diff --git a/packages/server/src/server/daemon-client.e2e.test.ts b/packages/server/src/server/daemon-client.e2e.test.ts index 701a7f6108..55aa4537c1 100644 --- a/packages/server/src/server/daemon-client.e2e.test.ts +++ b/packages/server/src/server/daemon-client.e2e.test.ts @@ -406,7 +406,7 @@ class RejectingMcpResumeClient implements AgentClient { } } -test("createAgent fails when the initial turn cannot start", async () => { +test("createAgent preserves the error snapshot when the initial turn cannot start", async () => { const testAgent = new StubAgentClient({ sessionId: "start-turn-failure-session", supportsStreaming: false, @@ -425,16 +425,18 @@ test("createAgent fails when the initial turn cannot start", async () => { await client.connect(); await client.fetchAgents({ subscribe: {} }); - await expect( - client.createAgent({ - provider: "codex", - cwd: tmpCwd(), - title: "Start failure agent", - modeId: "full-access", - model: "gpt-5.4-mini", - initialPrompt: "Run exactly: sleep 30", - }), - ).rejects.toThrow("Initial turn failed to start"); + const created = await client.createAgent({ + provider: "codex", + cwd: tmpCwd(), + title: "Start failure agent", + modeId: "full-access", + model: "gpt-5.4-mini", + initialPrompt: "Run exactly: sleep 30", + }); + expect(created.status).toBe("error"); + expect(created.lastError).toBe("Initial turn failed to start"); + const fetched = await client.fetchAgent({ agentId: created.id }); + expect(fetched?.agent.lastError).toBe("Initial turn failed to start"); } finally { await client.close(); await daemon.close(); @@ -1405,27 +1407,6 @@ test("creates agent and exercises lifecycle", async () => { }); const createRequestId = `create-${Date.now()}`; - const createdStatusPromise = waitForSignal(15000, (resolve) => { - const unsubscribe = ctx.client.on("status", (message) => { - if (message.type !== "status") { - return; - } - const payload = message.payload as { - status?: string; - agentId?: string; - requestId?: string; - }; - if (payload.status !== "agent_created") { - return; - } - if (payload.requestId !== createRequestId) { - return; - } - resolve(message); - }); - return unsubscribe; - }); - const agent = await ctx.client.createAgent({ ...getFullAccessConfig("codex"), cwd, @@ -1440,30 +1421,8 @@ test("creates agent and exercises lifecycle", async () => { const agentUpdate = await agentUpdatePromise; expect(agentUpdate.payload.agent.id).toBe(agent.id); - const createdStatus = await createdStatusPromise; - expect((createdStatus.payload as { agentId?: string }).agentId).toBe(agent.id); const failRequestId = `fail-${Date.now()}`; - const failedStatusPromise = waitForSignal(15000, (resolve) => { - const unsubscribe = ctx.client.on("status", (message) => { - if (message.type !== "status") { - return; - } - const payload = message.payload as { - status?: string; - requestId?: string; - }; - if (payload.status !== "agent_create_failed") { - return; - } - if (payload.requestId !== failRequestId) { - return; - } - resolve(message); - }); - return unsubscribe; - }); - await expect( ctx.client.createAgent({ ...getFullAccessConfig("codex"), @@ -1472,7 +1431,6 @@ test("creates agent and exercises lifecycle", async () => { requestId: failRequestId, }), ).rejects.toThrow("Working directory does not exist"); - await failedStatusPromise; let sawRefresh = false; const unsubscribe = ctx.client.subscribe((event) => { @@ -1651,6 +1609,11 @@ test("creates agent and exercises lifecycle", async () => { }, 300000); test("handles permission flow", async () => { + const permissionEvents = ctx.client.observeEvents([ + "agent_permission_request", + "agent_permission_resolved", + ]); + await permissionEvents.ready; const cwd = tmpCwd(); const filePath = path.join(cwd, "permission.txt"); @@ -1719,6 +1682,7 @@ test("handles permission flow", async () => { // Prevent unhandled rejections if the test fails before promises resolve. await permissionRequestPromise.catch(() => {}); await permissionResolvedPromise.catch(() => {}); + await permissionEvents.release(); await ctx.client.deleteAgent(agent.id); rmSync(cwd, { recursive: true, force: true }); }