From 48c6d85c3cc5a57a729f14068e2346b17ed62088 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Sun, 7 Jun 2026 18:41:27 +0900 Subject: feat(chat): live turn metrics — telemetry reducer + rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consume wire/transport-contract 0.3.0 (step-complete event + timing fields on usage/tool-result/done). Pure core/telemetry module: foldMetricEvent (reducer) + derived selectors (stepTps, turnTps, etc). TelemetryState is pure data, no active-turn tracking — consumers pass turnId to selectors. ChatStore wires foldMetricEvent into handleDelta and exposes telemetry + currentTurnId. ChatView shows step-metrics footer (time/TPS/tokens) on assistant text bubbles and durationMs badge on tool cards. New TurnSummary component renders turn-level stats (wall-clock, tokens, steps, TPS) in a DaisyUI stats block. Extended live-probe to verify telemetry events against bin/up (pending backend restart). 336 tests, typecheck 0, biome clean, build ok. --- src/core/chunks/reducer.ts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core/chunks') diff --git a/src/core/chunks/reducer.ts b/src/core/chunks/reducer.ts index 1dcfa39..54b1922 100644 --- a/src/core/chunks/reducer.ts +++ b/src/core/chunks/reducer.ts @@ -148,6 +148,10 @@ export function foldEvent(state: TranscriptState, event: AgentEvent): Transcript case "usage": return { ...state, latestUsage: event.usage }; + case "step-complete": + // Timing metadata — no content chunk; handled by the telemetry reducer. + return state; + case "done": { const provisional = flushAccumulating(state.provisional, state.accumulating); return { -- cgit v1.2.3