web: show system items in worker console

This commit is contained in:
2026-08-05 03:36:50 +09:00
parent f98a123e40
commit 50726e4cf3
2 changed files with 66 additions and 4 deletions
@@ -718,7 +718,7 @@ Deno.test("projectConsole preserves in-progress assistant protocol stream", () =
);
});
Deno.test("projectConsole keeps protocol lifecycle events out of the console surface", () => {
Deno.test("projectConsole hides lifecycle events and renders system items", () => {
const projection = projectConsole([
{
eventId: "30",
@@ -743,12 +743,24 @@ Deno.test("projectConsole keeps protocol lifecycle events out of the console sur
eventId: "34",
event: {
event: "system_item",
data: { item: { kind: "note", content: "internal" } },
data: {
item: {
kind: "notification",
message: "Ticket queued",
body: "Reread Ticket 00001KZ6TSGG5 before acting.",
},
},
} satisfies Event,
},
]);
assertEquals(projection.lines, []);
assertEquals(projection.lines.length, 1);
assertEquals(projection.lines[0].kind, "system");
assertEquals(projection.lines[0].title, "System · notification");
assertEquals(
projection.lines[0].body,
"Reread Ticket 00001KZ6TSGG5 before acting.",
);
assertEquals(projection.status, "running");
});
@@ -859,6 +871,42 @@ Deno.test("projectConsole renders snapshot entries and in-flight output", () =>
);
});
Deno.test("projectConsole restores system items from snapshot entries", () => {
const projection = projectConsole([{
eventId: "system-snapshot",
event: {
event: "snapshot",
data: {
entries: [{
kind: "system_item",
ts: 1,
item: {
kind: "notification",
message: "Worker completed",
body: "Child Worker coder-1 completed.",
},
}],
greeting: {
worker_name: "Worker",
cwd: "/repo",
provider: "provider",
model: "model",
scope_summary: "bounded",
tools: [],
context_window: 100,
context_tokens: 20,
},
status: "idle",
},
} satisfies Event,
}]);
assertEquals(projection.lines.length, 1);
assertEquals(projection.lines[0].kind, "system");
assertEquals(projection.lines[0].title, "System · notification");
assertEquals(projection.lines[0].body, "Child Worker coder-1 completed.");
});
Deno.test("projectConsole reseeds visible rows from segment rotation", () => {
const projection = projectConsole([
{
@@ -208,7 +208,7 @@ export function applyProtocolEvent(
);
break;
case "system_item":
// System items are protocol/internal context, not console output.
next.lines.push(systemItemLine(envelope.eventId, event.data.item));
break;
case "text_delta":
appendStreaming(
@@ -397,6 +397,17 @@ function line(
};
}
function systemItemLine(eventId: string, item: unknown): ConsoleLine {
if (!isRecord(item)) {
return line(eventId, "system", "System item", jsonPreview(item));
}
const itemKind = stringField(item, "kind") ?? "item";
const title = `System · ${itemKind.replaceAll("_", " ")}`;
const body = stringField(item, "body") ?? stringField(item, "message") ??
stringField(item, "content") ?? jsonPreview(item);
return line(eventId, "system", title, body);
}
function upsertStatusLine(
projection: ConsoleProjection,
id: string,
@@ -1140,6 +1151,9 @@ function applyLogEntry(
),
);
break;
case "system_item":
projection.lines.push(systemItemLine(eventId, entry["item"]));
break;
case "assistant_item":
case "tool_result":
applyLoggedItem(projection, eventId, entry["item"]);