diff --git a/packages/opencode/test/hook/execute.test.ts b/packages/opencode/test/hook/execute.test.ts index 26d340c9f628..edb89fb7876b 100644 --- a/packages/opencode/test/hook/execute.test.ts +++ b/packages/opencode/test/hook/execute.test.ts @@ -58,7 +58,7 @@ describe("hook.execute", () => { const entry: HookEntry = { command: "sleep 10", timeout: 200 } const result = await runHook(entry, makeEnv()) expect(result.action).toBe("pass") - }, 5000) + }, 15_000) test("passes environment variables to script", async () => { const entry: HookEntry = { command: 'echo "$OPENCODE_TOOL_NAME" >&2' } diff --git a/packages/opencode/test/session/prompt-effect.test.ts b/packages/opencode/test/session/prompt-effect.test.ts index c2029e7da42f..1c92c38428c0 100644 --- a/packages/opencode/test/session/prompt-effect.test.ts +++ b/packages/opencode/test/session/prompt-effect.test.ts @@ -835,7 +835,10 @@ it.live( 3_000, ) -it.live( +// Skip on 2vCPU CI runners — requires 4vCPU dedicated runners (blacksmith) for reliable fiber scheduling. +// See Issue #129: https://github.com/Cor-Incorporated/opencode/issues/129 +const hasDedicatedRunner = !process.env.CI || process.env.BLACKSMITH === "1" +;(hasDedicatedRunner ? it.live : it.live.skip)( "prompt submitted during an active run is included in the next LLM input", () => provideTmpdirServer( @@ -858,6 +861,9 @@ it.live( .pipe(Effect.forkChild) yield* llm.wait(1) + // Allow the first prompt loop to settle into the held LLM call + // 2vCPU CI runners (ubuntu-latest) need significantly more time than 4vCPU (blacksmith) + yield* Effect.sleep(200) const id = MessageID.ascending() const b = yield* prompt @@ -871,16 +877,19 @@ it.live( .pipe(Effect.forkChild) yield* Effect.promise(async () => { - const end = Date.now() + 5000 + // 2vCPU shared runners need generous timeouts for async message persistence + const end = Date.now() + 15_000 while (Date.now() < end) { const msgs = await Effect.runPromise(sessions.messages({ sessionID: chat.id })) if (msgs.some((msg) => msg.info.role === "user" && msg.info.id === id)) return - await new Promise((done) => setTimeout(done, 20)) + await new Promise((done) => setTimeout(done, 100)) } throw new Error("timed out waiting for second prompt to save") }) gate.resolve() + // Allow fibers to fully process the gate resolution on slow CI runners + yield* Effect.sleep(500) const [ea, eb] = yield* Effect.all([Fiber.await(a), Fiber.await(b)]) expect(Exit.isSuccess(ea)).toBe(true) @@ -901,7 +910,7 @@ it.live( }), { git: true, config: providerCfg }, ), - 3_000, + 30_000, ) it.live( diff --git a/script/duplicate-pr.ts b/script/duplicate-pr.ts index b77737c1d417..bd83bc43360c 100755 --- a/script/duplicate-pr.ts +++ b/script/duplicate-pr.ts @@ -59,9 +59,13 @@ Examples: parts.push({ type: "text", text: message }) const session = await opencode.client.session.create() + if (!session.data) { + process.stderr.write("No session available — skipping duplicate check\n") + return + } const result = await opencode.client.session .prompt({ - path: { id: session.data!.id }, + path: { id: session.data.id }, body: { agent: "duplicate-pr", parts,