test(server): exercise current daemon creation and permission contracts

The workspace resume regression shares this suite with creation checks that still waited for legacy status frames and permission listeners without an owned subscription. Verify the returned error snapshot and acquire event demand so the complete suite can validate workspace identity changes.

Co-authored-by: Darrell <DT@Terastar.biz>
This commit is contained in:
paseo-bot[bot]
2026-11-06 14:02:32 +00:00
co-authored by Darrell
parent d1450ad1b7
commit fa6850050b
@@ -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 });
}