fix: keep compaction lifecycle runtime-only

This commit is contained in:
2026-09-16 04:19:02 +09:00
parent 4e7a314a00
commit 1d06d4b08a
10 changed files with 352 additions and 477 deletions
+6 -2
View File
@@ -75,6 +75,10 @@ export type CompactionLifecycle = { schema_version: number, compaction_id: strin
*/
started_at_ms: number, ended_at_ms?: number | null, summary?: string | null, error?: string | null, new_segment_id?: string | null, };
export type CompactionPhase = "preparing" | "summarizing" | "committing";
export type CompactionTrigger = "manual" | "pre_run" | "request_threshold";
export type UploadedFileAvailability = "available" | "unavailable" | "integrity_failed";
export type UploadedFileRef = { artifact_id: string, file_name: string, media_type: string, created_at_ms: number, availability: UploadedFileAvailability, byte_len: number, sha256: string, source_entry_id?: string | null, };
@@ -113,7 +117,7 @@ export type RewindSummary = { truncated_to_entries: number, discarded_entries: n
export type InFlightBlock = { "kind": "text", text: string, finished?: boolean, } | { "kind": "thinking", text: string, finished?: boolean, } | { "kind": "tool_call", id: string, name: string, args: string, state?: InFlightToolCallState, };
export type InFlightCompaction = { schema_version: number, compaction_id: string, revision: number, internal_worker: InternalWorkerRef | null, started_at_ms: number, };
export type InFlightCompaction = { phase: CompactionPhase, started_at_ms: number, trigger: CompactionTrigger, };
export type InFlightSnapshot = { blocks?: Array<InFlightBlock>, commands?: Array<CommandSnapshot>,
/**
@@ -318,4 +322,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": { session: SessionSnapshot, } } | { "event": "worker_state", "data": { snapshot: WorkerStateSnapshot, } } | { "event": "command_acknowledged", "data": { acknowledgement: WorkerCommandAcknowledgement, } } | { "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" };
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": "worker_state", "data": { snapshot: WorkerStateSnapshot, } } | { "event": "command_acknowledged", "data": { acknowledgement: WorkerCommandAcknowledgement, } } | { "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": "compaction_progress", "data": { compaction: InFlightCompaction | null, } } | { "event": "compact_start", "data": { lifecycle: CompactionLifecycle, } } | { "event": "compact_done", "data": { lifecycle: CompactionLifecycle, } } | { "event": "compact_failed", "data": { lifecycle: CompactionLifecycle, } } | { "event": "shutdown" };
@@ -1084,19 +1084,18 @@ Deno.test("snapshot restores running compaction without staged content", () => {
snapshot.data.in_flight = {
blocks: [],
compaction: {
schema_version: 3,
compaction_id: "compaction-snapshot",
revision: 1,
internal_worker: null,
phase: "summarizing",
started_at_ms: 1_000,
trigger: "manual",
},
};
const projection = projectConsole([{ eventId: "snapshot", event: snapshot }]);
assertEquals(projection.lines.length, 1);
assertEquals(projection.lines[0].id, "compaction-compaction-snapshot");
assertEquals(projection.lines[0].compaction?.state, "running");
assertEquals(projection.lines[0].id, "compaction-runtime");
assertEquals(projection.lines[0].streaming, true);
assertEquals(projection.lines[0].body, "compacting · summarizing");
assertEquals(projection.lines[0].body.includes("staged"), false);
});
@@ -720,16 +720,25 @@ function compactionActivity(
function applyInFlightCompaction(
projection: ConsoleProjection,
progress: InFlightCompaction,
progress: InFlightCompaction | null,
): ConsoleProjection {
return applyCompactionLifecycle(projection, {
...progress,
state: "running",
ended_at_ms: null,
summary: null,
error: null,
new_segment_id: null,
});
const id = "compaction-runtime";
const lines = projection.lines.filter((line) => line.id !== id);
if (!progress) return { ...projection, lines };
return {
...projection,
lines: [
...lines,
{
id,
kind: "status",
title: "Compaction",
body: `compacting · ${progress.phase.replaceAll("_", " ")}`,
source: "event",
streaming: true,
},
],
};
}
function applyCompactionLifecycle(
@@ -1110,6 +1119,8 @@ export function applyProtocolEvent(
// These are protocol/status/control events. TUI Console does not append
// them to the conversation surface; browser Console should not either.
break;
case "compaction_progress":
return applyInFlightCompaction(next, event.data.compaction ?? null);
case "compact_start":
case "compact_done":
case "compact_failed":