import assert from "node:assert/strict"; import test from "node:test"; import { Effect } from "effect"; import { codexBackend } from "./src/backends/codex.ts"; import type { ParentContext, SpawnTask } from "./src/domain.ts"; import { SubagentManager } from "./src/manager.ts"; import { createSubagentRuntime, runTool } from "./src/runtime.ts"; const parent: ParentContext = { parentCwd: process.cwd(), projectTrusted: false, }; function task(prompt: string): SpawnTask { return { prompt, title: "live Codex test", cwd: process.cwd(), parent, }; } function deadline(operation: Promise, timeoutMs: number) { let timer: ReturnType | undefined; const timeout = new Promise((_resolve, reject) => { timer = setTimeout( () => reject(new Error(`Live Codex test exceeded ${timeoutMs}ms`)), timeoutMs, ); }); return Promise.race([operation, timeout]).finally(() => { if (timer) clearTimeout(timer); }); } async function codexAvailable() { return Effect.runPromise(codexBackend.available); } test( "Codex backend completes a live manager run", { timeout: 75_000 }, async (t) => { if (!(await codexAvailable())) { t.skip("codex executable is unavailable"); return; } const runtime = createSubagentRuntime(); try { const manager = await runtime.runPromise(SubagentManager); const spawned = await runTool( runtime, manager.spawn("codex", task("Reply with exactly: hello codex")), ); await deadline(runTool(runtime, manager.waitFor([spawned.id])), 60_000); const done = manager.view.get(spawned.id); assert.equal(done?.status, "done"); assert.match(done?.finalText ?? "", /hello codex/i); assert.equal(done?.meta.backend, "codex"); assert.ok(done?.meta.nativeSessionId); assert.ok(done?.meta.sessionFilePath); } finally { await runtime.dispose(); } }, ); test( "Codex backend interrupt settles a live manager run", { timeout: 30_000 }, async (t) => { if (!(await codexAvailable())) { t.skip("codex executable is unavailable"); return; } const runtime = createSubagentRuntime(); try { const manager = await runtime.runPromise(SubagentManager); const spawned = await runTool( runtime, manager.spawn( "codex", task("Run `sleep 30`, then reply with the word finished."), ), ); await new Promise((resolve) => setTimeout(resolve, 250)); const result = await deadline( runTool(runtime, manager.cancel([spawned.id])), 10_000, ); assert.equal(result[0]?.cancelled, true); assert.equal(manager.view.get(spawned.id)?.status, "error"); assert.equal(manager.view.get(spawned.id)?.errorText, "Run was aborted"); } finally { await runtime.dispose(); } }, );