feat(session): expose canonical public snapshots

This commit is contained in:
2026-08-30 00:41:51 +09:00
parent 40ac83e632
commit 88be87e03e
26 changed files with 1512 additions and 413 deletions
+27 -3
View File
@@ -73,11 +73,35 @@ export type InFlightBlock = { "kind": "text", text: string, finished?: boolean,
export type InFlightSnapshot = { blocks?: Array<InFlightBlock>, commands?: Array<CommandSnapshot>, };
export type SessionEntryProvenance = "human_input" | "worker_input" | "flow_instruction" | "backend_instruction" | "model_output" | "tool_output" | "derived_summary" | "legacy_unknown";
export type SessionMessageRole = "user" | "assistant";
export type SessionContentPart = { "kind": "text", text: string, } | { "kind": "refusal", refusal: string, };
export type SessionToolAttachment = { media_type: string,
/**
* Base64-encoded durable attachment body. Public snapshots preserve the
* committed multimodal value instead of replacing it with placeholder text.
*/
data_base64: string, };
export type SessionSnapshotEntryData = { "kind": "user_input", segments: Array<Segment>, } | { "kind": "message", role: SessionMessageRole, content: Array<SessionContentPart>, } | { "kind": "tool_call", call_id: string, name: string, arguments: string, } | { "kind": "tool_result", call_id: string, summary: string, content?: string | null, is_error: boolean, attachments?: Array<SessionToolAttachment>, } | { "kind": "system_item", item_kind: string, content: string, data?: unknown, } | { "kind": "run_error", message: string, };
export type SessionSnapshotEntry = {
/**
* Stable identity from durable history metadata, or a deterministic
* identity derived from the legacy segment and log position.
*/
entry_id: string, provenance: SessionEntryProvenance, derived_from?: Array<string>, } & ({ "kind": "user_input", segments: Array<Segment>, } | { "kind": "message", role: SessionMessageRole, content: Array<SessionContentPart>, } | { "kind": "tool_call", call_id: string, name: string, arguments: string, } | { "kind": "tool_result", call_id: string, summary: string, content?: string | null, is_error: boolean, attachments?: Array<SessionToolAttachment>, } | { "kind": "system_item", item_kind: string, content: string, data?: unknown, } | { "kind": "run_error", message: string, });
export type SessionSnapshot = { entries: Array<SessionSnapshotEntry>, };
export type InternalWorkerKind = "sub_worker" | { "service": { kind: string, } };
export type InternalWorkerRef = { session_id: string, name: string, parent_session_id?: string | null, kind: InternalWorkerKind, };
export type InternalWorkerSnapshot = { worker: InternalWorkerRef, revision: number, entries: Array<unknown>, status: WorkerStatus, error?: string | null, in_flight?: InFlightSnapshot, internal_workers?: Array<InternalWorkerSnapshot>, };
export type InternalWorkerSnapshot = { worker: InternalWorkerRef, revision: number, session: SessionSnapshot, status: WorkerStatus, error?: string | null, in_flight?: InFlightSnapshot, internal_workers?: Array<InternalWorkerSnapshot>, };
export type Greeting = { worker_name: string, cwd: string, provider: string, model: string, scope_summary: string, tools: Array<string>,
/**
@@ -193,7 +217,7 @@ summary: string,
* Full tool output. Absent when the tool chose to return
* summary-only, or when the result was pruned.
*/
output?: string | null, disposition?: ToolResultDisposition | null, is_error: boolean, } } | { "event": "usage", "data": { input_tokens: number | null, output_tokens: number | null, cache_read_input_tokens?: number | null, } } | { "event": "run_end", "data": { result: RunResult, } } | { "event": "error", "data": { code: ErrorCode, message: string, } } | { "event": "snapshot", "data": { entries: Array<unknown>, greeting: Greeting, status: WorkerStatus,
output?: string | null, disposition?: ToolResultDisposition | null, is_error: boolean, } } | { "event": "usage", "data": { input_tokens: number | null, output_tokens: number | null, cache_read_input_tokens?: number | null, } } | { "event": "run_end", "data": { result: RunResult, } } | { "event": "error", "data": { code: ErrorCode, message: string, } } | { "event": "snapshot", "data": { session: SessionSnapshot, greeting: Greeting, status: WorkerStatus,
/**
* Unfinished model output that has already streamed in the current
* run but is not yet represented by committed snapshot entries.
@@ -203,4 +227,4 @@ in_flight?: InFlightSnapshot,
* Parent-owned Internal Worker sessions visible to this client.
* Service-private Internal Workers are deliberately excluded.
*/
internal_workers?: Array<InternalWorkerSnapshot>, } } | { "event": "internal_worker", "data": { worker: InternalWorkerRef, revision: number, event: Event, } } | { "event": "internal_worker_removed", "data": { worker: InternalWorkerRef, revision: number, } } | { "event": "segment_rotated", "data": { entry: unknown, } } | { "event": "status", "data": { status: WorkerStatus, } } | { "event": "command", "data": { event: CommandEvent, } } | { "event": "completions", "data": { kind: CompletionKind, entries: Array<CompletionEntry>, } } | { "event": "rewind_targets", "data": { head_entries: number, targets: Array<RewindTarget>, } } | { "event": "rewind_applied", "data": { entries: Array<unknown>, input: Array<Segment>, summary: RewindSummary, } } | { "event": "workers_listed", "data": { workers: unknown, } } | { "event": "worker_restored", "data": { result: unknown, } } | { "event": "peer_registered", "data": { result: unknown, } } | { "event": "alert", "data": Alert } | { "event": "memory_worker", "data": MemoryWorkerEvent } | { "event": "compact_start", "data": { lifecycle: CompactionLifecycle, } } | { "event": "compact_done", "data": { lifecycle: CompactionLifecycle, } } | { "event": "compact_failed", "data": { lifecycle: CompactionLifecycle, } } | { "event": "shutdown" };
internal_workers?: Array<InternalWorkerSnapshot>, } } | { "event": "internal_worker", "data": { worker: InternalWorkerRef, revision: number, event: Event, } } | { "event": "internal_worker_removed", "data": { worker: InternalWorkerRef, revision: number, } } | { "event": "segment_rotated", "data": { session: SessionSnapshot, } } | { "event": "status", "data": { status: WorkerStatus, } } | { "event": "command", "data": { event: CommandEvent, } } | { "event": "completions", "data": { kind: CompletionKind, entries: Array<CompletionEntry>, } } | { "event": "rewind_targets", "data": { head_entries: number, targets: Array<RewindTarget>, } } | { "event": "rewind_applied", "data": { session: SessionSnapshot, input: Array<Segment>, summary: RewindSummary, } } | { "event": "workers_listed", "data": { workers: unknown, } } | { "event": "worker_restored", "data": { result: unknown, } } | { "event": "peer_registered", "data": { result: unknown, } } | { "event": "alert", "data": Alert } | { "event": "memory_worker", "data": MemoryWorkerEvent } | { "event": "compact_start", "data": { lifecycle: CompactionLifecycle, } } | { "event": "compact_done", "data": { lifecycle: CompactionLifecycle, } } | { "event": "compact_failed", "data": { lifecycle: CompactionLifecycle, } } | { "event": "shutdown" };
@@ -43,11 +43,84 @@ function consoleLine(id: string, kind: ConsoleLine["kind"]): ConsoleLine {
};
}
function canonicalSession(logEntries: unknown[]): Event extends {
event: "snapshot";
data: infer D;
} ? D extends { session: infer S } ? S : never : never {
const entries: Record<string, unknown>[] = [];
let sequence = 0;
const itemEntry = (item: Record<string, unknown>) => {
const kind = item["kind"];
if (kind === "reasoning" || item["role"] === "system") return;
entries.push({
entry_id: `legacy-test-${sequence++}`,
provenance: "legacy_unknown",
...item,
});
};
for (const raw of logEntries) {
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
const entry = raw as Record<string, unknown>;
switch (entry["kind"]) {
case "segment_start":
case "annotated_segment_start":
entries.length = 0;
for (const history of Array.isArray(entry["history"]) ? entry["history"] : []) {
const value = history as Record<string, unknown>;
itemEntry((value["item"] as Record<string, unknown> | undefined) ?? value);
}
break;
case "user_input":
case "annotated_user_input":
entries.push({
entry_id: `legacy-test-${sequence++}`,
provenance: "legacy_unknown",
kind: "user_input",
segments: entry["segments"] ?? [],
});
break;
case "assistant_item":
case "tool_result":
case "annotated_assistant_item":
case "annotated_tool_result": {
const annotated = entry["entry"] as Record<string, unknown> | undefined;
itemEntry((annotated?.["item"] as Record<string, unknown> | undefined) ??
(entry["item"] as Record<string, unknown>));
break;
}
case "system_item":
case "annotated_system_item": {
const annotated = entry["entry"] as Record<string, unknown> | undefined;
const item = (annotated?.["item"] as Record<string, unknown> | undefined) ??
(entry["item"] as Record<string, unknown>);
entries.push({
entry_id: `legacy-test-${sequence++}`,
provenance: "legacy_unknown",
kind: "system_item",
item_kind: item?.["kind"] ?? "system_item",
content: item?.["body"] ?? item?.["message"] ?? "",
data: item,
});
break;
}
case "run_errored":
entries.push({
entry_id: `legacy-test-${sequence++}`,
provenance: "legacy_unknown",
kind: "run_error",
message: entry["message"] ?? "Worker run failed.",
});
break;
}
}
return { entries } as never;
}
function snapshotEvent(cwd: string, entries: unknown[] = []): Event {
return {
event: "snapshot",
data: {
entries,
session: canonicalSession(entries),
greeting: {
worker_name: "Worker",
cwd,
@@ -138,7 +211,7 @@ Deno.test("segment rotation retains a live error beside the real SegmentStart hi
event: {
event: "segment_rotated",
data: {
entry: {
session: canonicalSession([{
kind: "segment_start",
ts: 5,
session_id: "session-1",
@@ -149,7 +222,7 @@ Deno.test("segment rotation retains a live error beside the real SegmentStart hi
role: "user",
content: [{ kind: "text", text: "retained conversation" }],
}],
},
}]),
},
} satisfies Event,
},
@@ -852,7 +925,7 @@ Deno.test("compaction service activity stays nested in one lifecycle item", () =
);
});
Deno.test("snapshot normalizes orphaned running compaction to interrupted", () => {
Deno.test("snapshot excludes storage-only compaction extension records", () => {
const projection = projectConsole([{
eventId: "snapshot",
observedAtMs: 9_000,
@@ -876,10 +949,7 @@ Deno.test("snapshot normalizes orphaned running compaction to interrupted", () =
}]),
}]);
assertEquals(projection.lines.length, 1);
assertEquals(projection.lines[0].compaction?.state, "interrupted");
assertEquals(projection.lines[0].compaction?.endedAtMs, 9_000);
assertEquals(projection.lines[0].streaming, false);
assertEquals(projection.lines.length, 0);
});
Deno.test("createConsoleProjector ignores stale compaction revisions", () => {
@@ -1238,7 +1308,7 @@ Deno.test("projectConsole renders snapshot entries and in-flight output", () =>
event: {
event: "snapshot",
data: {
entries: [
session: canonicalSession([
{
kind: "segment_start",
ts: 1,
@@ -1300,7 +1370,7 @@ Deno.test("projectConsole renders snapshot entries and in-flight output", () =>
message: "Compacting…",
},
},
],
]),
greeting: {
worker_name: "Worker",
cwd: "/repo",
@@ -1332,7 +1402,6 @@ Deno.test("projectConsole renders snapshot entries and in-flight output", () =>
"user:new user:false",
"assistant:assistant reply:false",
"tool:Read(1 file)\n /tmp/a.md:false",
"status:Compacting…:true",
"in_flight:partial:true",
],
);
@@ -1344,7 +1413,7 @@ Deno.test("projectConsole restores system items from snapshot entries", () => {
event: {
event: "snapshot",
data: {
entries: [{
session: canonicalSession([{
kind: "system_item",
ts: 1,
item: {
@@ -1352,7 +1421,7 @@ Deno.test("projectConsole restores system items from snapshot entries", () => {
message: "Worker completed",
body: "Child Worker coder-1 completed.",
},
}],
}]),
greeting: {
worker_name: "Worker",
cwd: "/repo",
@@ -1388,7 +1457,7 @@ Deno.test("projectConsole reseeds visible rows from segment rotation", () => {
event: {
event: "segment_rotated",
data: {
entry: {
session: canonicalSession([{
kind: "segment_start",
ts: 10,
session_id: "00000000-0000-0000-0000-000000000001",
@@ -1401,7 +1470,7 @@ Deno.test("projectConsole reseeds visible rows from segment rotation", () => {
content: [{ kind: "text", text: "after rotation seed" }],
},
],
},
}]),
},
} satisfies Event,
},
@@ -1773,7 +1842,7 @@ Deno.test("parent snapshot authoritatively replaces Internal Worker projections"
kind: "sub_worker",
},
revision: 4,
entries: [{
session: canonicalSession([{
kind: "assistant_item",
ts: 1,
item: {
@@ -1792,7 +1861,7 @@ Deno.test("parent snapshot authoritatively replaces Internal Worker projections"
content: "content",
is_error: false,
},
}],
}]),
status: "idle",
in_flight: {
blocks: [{
@@ -1934,18 +2003,20 @@ Deno.test("snapshot restores TaskStore state from system history", () => {
`[Session TaskStore snapshot]\n\n\`\`\`json\n{\n "tasks": [{"taskid": 3, "status": "pending", "subject": "Restored", "description": "From compaction"}]\n}\n\`\`\``;
const event = snapshotEvent("/repo");
if (event.event !== "snapshot") throw new Error("snapshot fixture expected");
event.data.entries = [{
kind: "segment_start",
ts: 1,
session_id: "00000000-0000-0000-0000-000000000001",
system_prompt: null,
config: {},
history: [{
kind: "message",
role: "system",
content: [{ kind: "text", text: taskSnapshot }],
event.data.session = {
entries: [{
entry_id: "task-reminder-1",
provenance: "backend_instruction",
kind: "system_item",
item_kind: "task_reminder",
content: taskSnapshot,
data: {
kind: "task_reminder",
body: taskSnapshot,
source: "automatic",
},
}],
}];
};
const projection = projectConsole([{ eventId: "task-snapshot", event }]);
assertEquals(projection.tasks, [{
@@ -650,9 +650,9 @@ function projectInternalWorkerSnapshot(
eventId: string,
cwd: string | null,
): InternalWorkerProjection {
const console = snapshotProjectionFromEntries(
const console = snapshotProjectionFromSession(
`${eventId}:internal:${snapshot.worker.session_id}:snapshot`,
snapshot.entries,
snapshot.session,
cwd,
);
console.status = snapshot.status;
@@ -905,9 +905,9 @@ export function applyProtocolEvent(
case "snapshot": {
next.status = event.data.status;
next.cwd = event.data.greeting.cwd;
const snapshot = snapshotProjectionFromEntries(
const snapshot = snapshotProjectionFromSession(
envelope.eventId,
event.data.entries,
event.data.session,
next.cwd,
);
next.lines = snapshot.lines;
@@ -1008,9 +1008,9 @@ export function applyProtocolEvent(
break;
case "segment_rotated": {
const retainedErrors = next.lines.filter((line) => line.kind === "error");
const segment = snapshotProjectionFromEntries(
const segment = snapshotProjectionFromSession(
envelope.eventId,
[event.data.entry],
event.data.session,
next.cwd,
);
next.lines = [...segment.lines, ...retainedErrors];
@@ -1925,9 +1925,9 @@ function applyTaskSystemItem(
if (typeof body === "string") applyTaskSnapshot(projection, body);
}
function snapshotProjectionFromEntries(
function snapshotProjectionFromSession(
eventId: string,
entries: unknown[],
snapshot: unknown,
cwd: string | null,
): ConsoleProjection {
const projection: ConsoleProjection = {
@@ -1942,58 +1942,74 @@ function snapshotProjectionFromEntries(
internalWorkers: [],
removedInternalWorkers: {},
};
const entries = isRecord(snapshot) ? arrayField(snapshot, "entries") : [];
entries.forEach((entry, index) =>
applyLogEntry(projection, `${eventId}-snapshot-${index}`, entry)
applySessionEntry(projection, `${eventId}-snapshot-${index}`, entry)
);
return projection;
}
function applyLogEntry(
function applySessionEntry(
projection: ConsoleProjection,
eventId: string,
entry: unknown,
fallbackEventId: string,
value: unknown,
): void {
if (!isRecord(entry)) return;
switch (stringField(entry, "kind")) {
case "segment_start":
arrayField(entry, "history").forEach((item, index) =>
applyLoggedItem(projection, `${eventId}-history-${index}`, item)
);
break;
if (!isRecord(value)) return;
const eventId = stringField(value, "entry_id") ?? fallbackEventId;
switch (stringField(value, "kind")) {
case "user_input":
projection.lines.push(
line(
eventId,
"user",
"User",
segmentsToText(arrayField(entry, "segments") as Segment[]),
segmentsToText(arrayField(value, "segments") as Segment[]),
),
);
break;
case "system_item":
projection.lines.push(systemItemLine(eventId, entry["item"]));
applyTaskSystemItem(projection, entry["item"]);
case "message":
applyLoggedItem(projection, eventId, {
kind: "message",
role: value["role"],
content: value["content"],
});
break;
case "tool_call":
applyLoggedItem(projection, eventId, {
kind: "tool_call",
call_id: value["call_id"],
name: value["name"],
arguments: value["arguments"],
});
break;
case "assistant_item":
case "tool_result":
applyLoggedItem(projection, eventId, entry["item"]);
applyLoggedItem(projection, eventId, {
kind: "tool_result",
call_id: value["call_id"],
summary: value["summary"],
content: value["content"],
is_error: value["is_error"],
});
break;
case "run_errored":
case "system_item": {
const item = value["data"];
projection.lines.push(systemItemLine(eventId, item ?? value));
applyTaskSystemItem(projection, item);
break;
}
case "run_error":
projection.lines.push(
line(
eventId,
"error",
"Run error",
stringField(entry, "message") ?? "Worker run failed.",
stringField(value, "message") ?? "Worker run failed.",
undefined,
false,
true,
),
);
break;
case "extension":
applyExtensionEntry(projection, eventId, entry);
break;
default:
break;
}