fix: clear stale internal worker in-flight state

This commit is contained in:
2026-08-20 06:18:21 +09:00
parent 80ffff642f
commit de72afd9a1
3 changed files with 72 additions and 14 deletions
@@ -1314,9 +1314,36 @@ Deno.test("parent snapshot authoritatively replaces Internal Worker projections"
kind: "sub_worker",
},
revision: 4,
entries: [],
entries: [{
kind: "assistant_item",
ts: 1,
item: {
kind: "tool_call",
call_id: "committed-call",
name: "Read",
arguments: JSON.stringify({ file_path: "/repo/a.md" }),
},
}, {
kind: "tool_result",
ts: 2,
item: {
kind: "tool_result",
call_id: "committed-call",
summary: "read file",
content: "content",
is_error: false,
},
}],
status: "idle",
in_flight: { blocks: [] },
in_flight: {
blocks: [{
kind: "tool_call",
id: "committed-call",
name: "Read",
args: JSON.stringify({ file_path: "/repo/a.md" }),
state: "done",
}],
},
internal_workers: [],
}];
const projector = createConsoleProjector();
@@ -1340,6 +1367,10 @@ Deno.test("parent snapshot authoritatively replaces Internal Worker projections"
assertEquals(projection.internalWorkers.map((worker) => worker.worker.session_id), [
"replacement",
]);
const childLines = projection.internalWorkers[0].console.lines;
assertEquals(childLines.length, 1);
assertEquals(new Set(childLines.map((line) => line.id)).size, 1);
assertEquals(childLines[0].kind, "tool");
});
Deno.test("snapshot restores TaskStore state from system history", () => {
@@ -224,6 +224,21 @@ function projectVisibleConsole(
};
}
function appendSnapshotInFlightLines(
projection: ConsoleProjection,
blocks: InFlightBlock[],
eventId: string,
cwd: string | null,
): void {
const lineIds = new Set(projection.lines.map((line) => line.id));
blocks.forEach((block, index) => {
const pending = inFlightLine(`${eventId}:${index}`, block, cwd);
if (lineIds.has(pending.id)) return;
projection.lines.push(pending);
lineIds.add(pending.id);
});
}
function projectInternalWorkerSnapshot(
snapshot: InternalWorkerSnapshot,
eventId: string,
@@ -235,15 +250,12 @@ function projectInternalWorkerSnapshot(
cwd,
);
console.status = snapshot.status;
for (const block of snapshot.in_flight?.blocks ?? []) {
console.lines.push(
inFlightLine(
`${eventId}:internal:${snapshot.worker.session_id}:in-flight`,
block,
cwd,
),
);
}
appendSnapshotInFlightLines(
console,
snapshot.in_flight?.blocks ?? [],
`${eventId}:internal:${snapshot.worker.session_id}:in-flight`,
cwd,
);
if (snapshot.error) {
console.lines.push({
id: `${eventId}:internal:${snapshot.worker.session_id}:error`,
@@ -385,9 +397,12 @@ export function applyProtocolEvent(
next.lines = snapshot.lines;
next.tasks = snapshot.tasks;
next.taskNextId = snapshot.taskNextId;
for (const block of event.data.in_flight?.blocks ?? []) {
next.lines.push(inFlightLine(envelope.eventId, block, next.cwd));
}
appendSnapshotInFlightLines(
next,
event.data.in_flight?.blocks ?? [],
`${envelope.eventId}:snapshot-in-flight`,
next.cwd,
);
next.internalWorkers = (event.data.internal_workers ?? []).map((worker) =>
projectInternalWorkerSnapshot(worker, envelope.eventId, next.cwd)
);