fix: reconcile console history before grouping activity

This commit is contained in:
2026-09-30 14:16:58 +09:00
parent cbf1b83599
commit 8627d45085
6 changed files with 162 additions and 29 deletions
@@ -57,6 +57,20 @@ function historyEntry(index: number, role: "user" | "assistant") {
};
}
function historyTurnEntries(index: number) {
const tools = ["Bash", "Grep"].flatMap((name) => {
const callId = `${name}-${index}`;
return [{
kind: "tool_call", entry_id: `call-${callId}`, timestamp: index,
provenance: "model_output", call_id: callId, name, arguments: "{}",
}, {
kind: "tool_result", entry_id: `result-${callId}`, timestamp: index,
provenance: "tool_output", call_id: callId, summary: "done", content: "done", is_error: false,
}];
});
return [historyEntry(index, "user"), ...tools, historyEntry(index, "assistant")];
}
function historyPage(indices: number[], cursor: string | null) {
return {
availability: "page",
@@ -66,7 +80,7 @@ function historyPage(indices: number[], cursor: string | null) {
compact_ancestor_lineage_ids: [],
turns: indices.map((index) => ({
turn_id: `user-${index}`,
entries: [historyEntry(index, "user"), historyEntry(index, "assistant")],
entries: historyTurnEntries(index),
})),
next_cursor: cursor,
has_more: cursor !== null,
@@ -162,7 +176,7 @@ Deno.serve({ hostname: "127.0.0.1", port }, async (request) => {
) {
return json({
availability: "retained_snapshot",
identity: { session_id: "session-a", segment_id: "segment-a", entry_count: 12 },
identity: { session_id: "session-a", segment_id: "segment-a", entry_count: 36 },
snapshot: {
pending_submissions: {
revision: 0,
@@ -170,10 +184,7 @@ Deno.serve({ hostname: "127.0.0.1", port }, async (request) => {
head_id: null,
submissions: [],
},
entries: [7, 8, 9, 10, 11, 12].flatMap((index) => [
historyEntry(index, "user"),
historyEntry(index, "assistant"),
]),
entries: [7, 8, 9, 10, 11, 12].flatMap(historyTurnEntries),
},
});
}
@@ -103,6 +103,8 @@ async function checkConsoleHistory(viewportHeight: number): Promise<void> {
assertEquals(await historyRequestCount(baseUrl), 1);
assertEquals(await transcript.getByText(/^question (7|8|9|10|11|12)$/).count(), 6);
assertEquals(await navigation.getByRole("button", { name: /^Turn \d+: question (7|8|9|10|11|12)$/ }).count(), 6);
assertEquals(await transcript.getByText("searched 1 time・ran 1 command", { exact: true }).count(), 6,
"overlapping snapshot and history must render each tool activity once");
const turnList = navigation.locator(".turn-list");
const initialGeometry = await turnList.evaluate((element) => {
const boundary = element.querySelector(".history-boundary")!;
@@ -252,6 +254,14 @@ async function checkConsoleHistory(viewportHeight: number): Promise<void> {
return Math.abs((turn.top + turn.bottom) / 2 - (bar.top + bar.bottom) / 2);
});
assert(centering <= 1, `turn marker is not vertically centered (${centering}px)`);
assertEquals(await transcript.getByText("searched 1 time・ran 1 command", { exact: true }).count(), 12);
await page.getByRole("button", { name: "Normal", exact: true }).click();
const rowIds = await transcript.locator("[data-console-line-id]").evaluateAll((rows) =>
rows.map((row) => row.getAttribute("data-console-line-id")));
assertEquals(rowIds.length, 48);
assertEquals(new Set(rowIds).size, rowIds.length);
await page.getByRole("button", { name: "Overview", exact: true }).click();
assertEquals(await transcript.getByText("searched 1 time・ran 1 command", { exact: true }).count(), 12);
assertEquals(errors, []);
await context.close();
} finally {