diff --git a/packages/server/src/server/agent/providers/codex-app-server-agent.test.ts b/packages/server/src/server/agent/providers/codex-app-server-agent.test.ts index c8269722a7..912f197013 100644 --- a/packages/server/src/server/agent/providers/codex-app-server-agent.test.ts +++ b/packages/server/src/server/agent/providers/codex-app-server-agent.test.ts @@ -7073,3 +7073,74 @@ describe("Codex denied plan approvals", () => { }); }); }); + +test.each([ + { statuses: ["completed"], expected: ["completed"] }, + { statuses: ["completed", "inProgress"], expected: ["completed", "running"] }, + { statuses: ["inProgress", "completed"], expected: ["running", "completed"] }, +])( + "restores each native child status without settling a running sibling: $statuses", + async ({ statuses, expected }) => { + const ids = statuses.map((_, i) => `child-${i}`); + const app = createFakeCodexAppServer({ + "thread/read": (params) => { + const id = (params as { threadId: string }).threadId; + if (id !== "parent") + return { thread: { turns: [{ status: statuses[ids.indexOf(id)], items: [] }] } }; + return { + thread: { + turns: [ + { + status: "completed", + items: [ + { + type: "collabAgentToolCall", + id: "shared-spawn", + tool: "spawnAgent", + status: "completed", + receiverThreadIds: ids, + agentsStates: Object.fromEntries( + ids.map((childId) => [childId, { status: "running" }]), + ), + }, + ], + }, + ], + }, + }; + }, + }); + const session = new CodexAppServerAgentSession( + { provider: "codex", cwd: process.cwd(), modeId: "full-access" }, + { sessionId: "parent" }, + createTestLogger(), + async () => app.child, + {}, + false, + false, + false, + undefined, + "history", + ); + try { + await session.connect(); + const statusesById = new Map(); + let parentStatus: string | undefined; + for await (const event of session.streamHistory()) { + if ( + event.type === "timeline" && + event.item.type === "tool_call" && + event.item.callId === "shared-spawn" + ) + parentStatus = event.item.status; + if (event.type === "provider_subagent" && event.event.type === "upsert") + statusesById.set(event.event.id, event.event.status); + } + expect(ids.map((id) => statusesById.get(id))).toEqual(expected); + expect(parentStatus).toBe(expected.includes("running") ? "running" : "completed"); + } finally { + await session.close(); + } + app.assertNoErrors(); + }, +);