mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-30 05:02:58 +00:00
fix(codex): settle closed children independently of prior errors
Codex derives a close record's status from the child's previous state, so closing an errored child produces a failed record even after shutdown. Treat close as a terminal-preserving child event rather than a successful control-card status, retaining earlier completion when a close is stale.
This commit is contained in:
@@ -1864,7 +1864,7 @@ function readCodexSubAgentActivity(item: unknown): CodexSubAgentActivity | null
|
||||
interface CodexCollabAgentUpdate {
|
||||
threadId: string;
|
||||
status: ToolCallTimelineItem["status"];
|
||||
shutdown: boolean;
|
||||
preservesTerminal: boolean;
|
||||
reopen: boolean;
|
||||
}
|
||||
|
||||
@@ -1891,11 +1891,8 @@ function readCodexCollabAgentControl(item: unknown): CodexCollabAgentControl | n
|
||||
return [
|
||||
{
|
||||
threadId,
|
||||
status:
|
||||
record.tool === "closeAgent" && record.status === "completed" && status === "running"
|
||||
? "canceled"
|
||||
: status,
|
||||
shutdown: state.status === "shutdown",
|
||||
status: record.tool === "closeAgent" && status === "running" ? "canceled" : status,
|
||||
preservesTerminal: state.status === "shutdown" || record.tool === "closeAgent",
|
||||
reopen: record.tool === "sendInput" && record.status === "completed",
|
||||
},
|
||||
];
|
||||
@@ -1916,7 +1913,7 @@ function resolveCodexCollabAgentUpdate(
|
||||
): ToolCallTimelineItem["status"] {
|
||||
if (
|
||||
isTerminalSubAgentStatus(previous) &&
|
||||
(update.shutdown || (update.status === "running" && !update.reopen))
|
||||
(update.preservesTerminal || (update.status === "running" && !update.reopen))
|
||||
) {
|
||||
return previous;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,35 @@ describe("Codex collaboration history", () => {
|
||||
).toEqual([{ id: "first", status: "canceled" }]);
|
||||
});
|
||||
|
||||
test("stops counting an errored child whose close record reports failed", async () => {
|
||||
const history = await replay([
|
||||
collab("spawnAgent", { first: "pendingInit" }, "spawn-first"),
|
||||
{ ...collab("closeAgent", { first: "errored" }), status: "failed" },
|
||||
]);
|
||||
expect(
|
||||
history.flatMap((event) =>
|
||||
event.type === "provider_subagent" && event.event.type === "upsert"
|
||||
? [{ id: event.event.id, status: event.event.status }]
|
||||
: [],
|
||||
),
|
||||
).toEqual([{ id: "first", status: "canceled" }]);
|
||||
});
|
||||
|
||||
test("preserves completion when a close carries an older running snapshot", async () => {
|
||||
const history = await replay([
|
||||
collab("spawnAgent", { first: "pendingInit" }, "spawn-first"),
|
||||
collab("wait", { first: "completed" }),
|
||||
collab("closeAgent", { first: "running" }),
|
||||
]);
|
||||
expect(
|
||||
history.flatMap((event) =>
|
||||
event.type === "provider_subagent" && event.event.type === "upsert"
|
||||
? [{ id: event.event.id, status: event.event.status }]
|
||||
: [],
|
||||
),
|
||||
).toEqual([{ id: "first", status: "completed" }]);
|
||||
});
|
||||
|
||||
test.each([
|
||||
["shutdown", "canceled"],
|
||||
["notFound", "failed"],
|
||||
|
||||
Reference in New Issue
Block a user