fix: render compaction on worker status
This commit is contained in:
+10
-18
@@ -279,6 +279,7 @@ pub struct App {
|
|||||||
run_error_messages: Vec<String>,
|
run_error_messages: Vec<String>,
|
||||||
/// Current compaction identity/revision used to fence snapshot/live updates.
|
/// Current compaction identity/revision used to fence snapshot/live updates.
|
||||||
active_compaction: Option<(String, u64)>,
|
active_compaction: Option<(String, u64)>,
|
||||||
|
compaction_progress: Option<protocol::InFlightCompaction>,
|
||||||
/// Presentation-only Internal Worker projections keyed by session identity.
|
/// Presentation-only Internal Worker projections keyed by session identity.
|
||||||
/// They are rendered in separate selectable views and never mixed into `blocks`.
|
/// They are rendered in separate selectable views and never mixed into `blocks`.
|
||||||
pub internal_workers: Vec<InternalWorkerView>,
|
pub internal_workers: Vec<InternalWorkerView>,
|
||||||
@@ -367,6 +368,7 @@ impl App {
|
|||||||
shutdown_confirm: None,
|
shutdown_confirm: None,
|
||||||
blocks: Vec::new(),
|
blocks: Vec::new(),
|
||||||
active_compaction: None,
|
active_compaction: None,
|
||||||
|
compaction_progress: None,
|
||||||
run_error_messages: Vec::new(),
|
run_error_messages: Vec::new(),
|
||||||
internal_workers: Vec::new(),
|
internal_workers: Vec::new(),
|
||||||
selected_internal_worker_session_id: None,
|
selected_internal_worker_session_id: None,
|
||||||
@@ -1401,17 +1403,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::CompactionProgress { compaction } => {
|
Event::CompactionProgress { compaction } => {
|
||||||
if compaction.is_some() {
|
self.compaction_progress = compaction;
|
||||||
if self.last_streaming_compact_mut().is_none() {
|
|
||||||
self.blocks.push(Block::Compact(CompactEvent::Streaming {
|
|
||||||
started_at: Instant::now(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
} else if let Some(Block::Compact(CompactEvent::Streaming { .. })) =
|
|
||||||
self.blocks.last()
|
|
||||||
{
|
|
||||||
self.blocks.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Event::CompactStart { lifecycle } => {
|
Event::CompactStart { lifecycle } => {
|
||||||
let should_apply = match &self.active_compaction {
|
let should_apply = match &self.active_compaction {
|
||||||
@@ -1702,11 +1694,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.active_compaction = None;
|
self.active_compaction = None;
|
||||||
if compaction.is_some() && self.last_streaming_compact_mut().is_none() {
|
self.compaction_progress = compaction;
|
||||||
self.blocks.push(Block::Compact(CompactEvent::Streaming {
|
|
||||||
started_at: Instant::now(),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_assistant_text(&mut self, text: &str) {
|
fn append_assistant_text(&mut self, text: &str) {
|
||||||
@@ -4322,11 +4310,15 @@ mod completion_flow_tests {
|
|||||||
}),
|
}),
|
||||||
..InFlightSnapshot::default()
|
..InFlightSnapshot::default()
|
||||||
});
|
});
|
||||||
assert_eq!(compact_block_count(&app), 1);
|
assert_eq!(compact_block_count(&app), 0);
|
||||||
|
assert_eq!(
|
||||||
|
app.compaction_progress.as_ref().map(|item| item.phase),
|
||||||
|
Some(protocol::CompactionPhase::Summarizing)
|
||||||
|
);
|
||||||
|
|
||||||
app.handle_worker_event(Event::CompactionProgress { compaction: None });
|
app.handle_worker_event(Event::CompactionProgress { compaction: None });
|
||||||
|
|
||||||
assert_eq!(compact_block_count(&app), 0);
|
assert!(app.compaction_progress.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -7,9 +7,11 @@
|
|||||||
requests: number;
|
requests: number;
|
||||||
uploadTokens: number;
|
uploadTokens: number;
|
||||||
outputTokens: number;
|
outputTokens: number;
|
||||||
|
compaction?: { phase: string } | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
let { startedAtMs, requests, uploadTokens, outputTokens }: Props = $props();
|
let { startedAtMs, requests, uploadTokens, outputTokens, compaction = null }: Props =
|
||||||
|
$props();
|
||||||
let nowMs = $state(Date.now());
|
let nowMs = $state(Date.now());
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@@ -27,6 +29,10 @@
|
|||||||
|
|
||||||
<div class="worker-run-status" role="status" aria-live="off">
|
<div class="worker-run-status" role="status" aria-live="off">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
|
{#if compaction}
|
||||||
|
<span>Compacting · {compaction.phase}</span>
|
||||||
|
<span aria-hidden="true">|</span>
|
||||||
|
{/if}
|
||||||
<span>{elapsed}</span>
|
<span>{elapsed}</span>
|
||||||
<span aria-hidden="true">・</span>
|
<span aria-hidden="true">・</span>
|
||||||
<span>{requests} {requestLabel}</span>
|
<span>{requests} {requestLabel}</span>
|
||||||
|
|||||||
@@ -1092,11 +1092,9 @@ Deno.test("snapshot restores running compaction without staged content", () => {
|
|||||||
|
|
||||||
const projection = projectConsole([{ eventId: "snapshot", event: snapshot }]);
|
const projection = projectConsole([{ eventId: "snapshot", event: snapshot }]);
|
||||||
|
|
||||||
assertEquals(projection.lines.length, 1);
|
assertEquals(projection.lines.length, 0);
|
||||||
assertEquals(projection.lines[0].id, "compaction-runtime");
|
assertEquals(projection.compaction?.phase, "summarizing");
|
||||||
assertEquals(projection.lines[0].streaming, true);
|
assertEquals(projection.compaction?.trigger, "manual");
|
||||||
assertEquals(projection.lines[0].body, "compacting · summarizing");
|
|
||||||
assertEquals(projection.lines[0].body.includes("staged"), false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Deno.test("compaction service activity stays nested in one lifecycle item", () => {
|
Deno.test("compaction service activity stays nested in one lifecycle item", () => {
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ export type ConsoleProjection = {
|
|||||||
taskNextId: number;
|
taskNextId: number;
|
||||||
status: string | null;
|
status: string | null;
|
||||||
workerState: WorkerStateSnapshot | null;
|
workerState: WorkerStateSnapshot | null;
|
||||||
|
compaction: InFlightCompaction | null;
|
||||||
usage: string | null;
|
usage: string | null;
|
||||||
runActivity: RunActivityStats;
|
runActivity: RunActivityStats;
|
||||||
cwd: string | null;
|
cwd: string | null;
|
||||||
@@ -246,6 +247,7 @@ export function emptyConsoleProjection(): ConsoleProjection {
|
|||||||
taskNextId: 1,
|
taskNextId: 1,
|
||||||
status: null,
|
status: null,
|
||||||
workerState: null,
|
workerState: null,
|
||||||
|
compaction: null,
|
||||||
usage: null,
|
usage: null,
|
||||||
runActivity: emptyRunActivityStats(),
|
runActivity: emptyRunActivityStats(),
|
||||||
cwd: null,
|
cwd: null,
|
||||||
@@ -722,23 +724,7 @@ function applyInFlightCompaction(
|
|||||||
projection: ConsoleProjection,
|
projection: ConsoleProjection,
|
||||||
progress: InFlightCompaction | null,
|
progress: InFlightCompaction | null,
|
||||||
): ConsoleProjection {
|
): ConsoleProjection {
|
||||||
const id = "compaction-runtime";
|
return { ...projection, compaction: progress };
|
||||||
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(
|
function applyCompactionLifecycle(
|
||||||
@@ -863,6 +849,7 @@ export function applyProtocolEvent(
|
|||||||
taskNextId: projection.taskNextId,
|
taskNextId: projection.taskNextId,
|
||||||
status: projection.status,
|
status: projection.status,
|
||||||
workerState: projection.workerState,
|
workerState: projection.workerState,
|
||||||
|
compaction: projection.compaction,
|
||||||
usage: projection.usage,
|
usage: projection.usage,
|
||||||
runActivity: applyRunActivityEvent(
|
runActivity: applyRunActivityEvent(
|
||||||
projection.runActivity,
|
projection.runActivity,
|
||||||
@@ -1003,6 +990,7 @@ export function applyProtocolEvent(
|
|||||||
event.data.in_flight.compaction,
|
event.data.in_flight.compaction,
|
||||||
);
|
);
|
||||||
next.lines = withCompaction.lines;
|
next.lines = withCompaction.lines;
|
||||||
|
next.compaction = withCompaction.compaction;
|
||||||
}
|
}
|
||||||
for (const line of next.lines) {
|
for (const line of next.lines) {
|
||||||
const compaction = line.compaction;
|
const compaction = line.compaction;
|
||||||
@@ -2013,6 +2001,7 @@ function snapshotProjectionFromSession(
|
|||||||
taskNextId: 1,
|
taskNextId: 1,
|
||||||
status: null,
|
status: null,
|
||||||
workerState: null,
|
workerState: null,
|
||||||
|
compaction: null,
|
||||||
usage: null,
|
usage: null,
|
||||||
runActivity: emptyRunActivityStats(),
|
runActivity: emptyRunActivityStats(),
|
||||||
cwd,
|
cwd,
|
||||||
|
|||||||
@@ -1907,6 +1907,7 @@
|
|||||||
requests={consoleProjection.runActivity.requests}
|
requests={consoleProjection.runActivity.requests}
|
||||||
uploadTokens={consoleProjection.runActivity.uploadTokens}
|
uploadTokens={consoleProjection.runActivity.uploadTokens}
|
||||||
outputTokens={consoleProjection.runActivity.outputTokens}
|
outputTokens={consoleProjection.runActivity.outputTokens}
|
||||||
|
compaction={consoleProjection.compaction}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user