diff options
Diffstat (limited to 'src/core/telemetry/reducer.ts')
| -rw-r--r-- | src/core/telemetry/reducer.ts | 122 |
1 files changed, 0 insertions, 122 deletions
diff --git a/src/core/telemetry/reducer.ts b/src/core/telemetry/reducer.ts deleted file mode 100644 index 4083231..0000000 --- a/src/core/telemetry/reducer.ts +++ /dev/null @@ -1,122 +0,0 @@ -import type { AgentEvent, StepId, Usage } from "@dispatch/wire"; -import type { StepMetrics, TelemetryState, TurnMetrics } from "./types"; - -/** The initial empty telemetry state. */ -export function initialState(): TelemetryState { - return { turns: new Map() }; -} - -function mergeStep(existing: StepMetrics, patch: StepMetrics): StepMetrics { - const merged: StepMetrics = { ...existing }; - if (patch.ttftMs !== undefined) (merged as { ttftMs?: number }).ttftMs = patch.ttftMs; - if (patch.decodeMs !== undefined) (merged as { decodeMs?: number }).decodeMs = patch.decodeMs; - if (patch.genTotalMs !== undefined) - (merged as { genTotalMs?: number }).genTotalMs = patch.genTotalMs; - if (patch.usage !== undefined) { - (merged as { usage?: Usage }).usage = { ...existing.usage, ...patch.usage }; - } - if (patch.toolDurationMs !== undefined) { - (merged as { toolDurationMs?: number }).toolDurationMs = - (existing.toolDurationMs ?? 0) + patch.toolDurationMs; - } - return merged; -} - -function upsertStep( - steps: readonly StepMetrics[], - stepId: StepId, - patch: StepMetrics, -): readonly StepMetrics[] { - const idx = steps.findIndex((s) => s.stepId === stepId); - if (idx === -1) { - return [...steps, patch]; - } - return [...steps.slice(0, idx), mergeStep(steps[idx]!, patch), ...steps.slice(idx + 1)]; -} - -function setTurn( - turns: ReadonlyMap<string, TurnMetrics>, - turnId: string, - turn: TurnMetrics, -): ReadonlyMap<string, TurnMetrics> { - const next = new Map(turns); - next.set(turnId, turn); - return next; -} - -/** - * Fold one live AgentEvent into the telemetry state. - * - * - `turn-start` records the active turnId. - * - `step-complete` creates/updates the step's timing metrics. - * - `usage` merges token counts into the step (joined by `stepId`). - * - `tool-result` accumulates `durationMs` into the step. - * - `done` records turn-level wall-clock + token totals. - * - All other event types are no-ops (content events belong to the transcript). - * - * Pure: input → output, no DOM, no side effects. - */ -export function foldMetricEvent(state: TelemetryState, event: AgentEvent): TelemetryState { - switch (event.type) { - case "turn-start": { - return { - ...state, - turns: setTurn(state.turns, event.turnId, { steps: [] }), - }; - } - - case "step-complete": { - const turnId = event.turnId; - const existing = state.turns.get(turnId); - const patch: StepMetrics = { stepId: event.stepId }; - if (event.ttftMs !== undefined) (patch as { ttftMs?: number }).ttftMs = event.ttftMs; - if (event.decodeMs !== undefined) (patch as { decodeMs?: number }).decodeMs = event.decodeMs; - if (event.genTotalMs !== undefined) - (patch as { genTotalMs?: number }).genTotalMs = event.genTotalMs; - const steps = - existing !== undefined ? upsertStep(existing.steps, event.stepId, patch) : [patch]; - return { - ...state, - turns: setTurn(state.turns, turnId, { ...existing, steps } as TurnMetrics), - }; - } - - case "usage": { - if (event.stepId === undefined) return state; - const turnId = event.turnId; - const existing = state.turns.get(turnId); - const patch: StepMetrics = { stepId: event.stepId, usage: event.usage }; - const steps = - existing !== undefined ? upsertStep(existing.steps, event.stepId, patch) : [patch]; - return { - ...state, - turns: setTurn(state.turns, turnId, { ...existing, steps } as TurnMetrics), - }; - } - - case "tool-result": { - if (event.durationMs === undefined) return state; - const turnId = event.turnId; - const existing = state.turns.get(turnId); - if (existing === undefined) return state; - const patch: StepMetrics = { stepId: event.stepId, toolDurationMs: event.durationMs }; - const steps = upsertStep(existing.steps, event.stepId, patch); - return { ...state, turns: setTurn(state.turns, turnId, { ...existing, steps }) }; - } - - case "done": { - const turnId = event.turnId; - const existing = state.turns.get(turnId); - const updated: TurnMetrics = { - ...(existing ?? { steps: [] }), - }; - if (event.durationMs !== undefined) - (updated as { wallMs?: number }).wallMs = event.durationMs; - if (event.usage !== undefined) (updated as { doneUsage?: Usage }).doneUsage = event.usage; - return { ...state, turns: setTurn(state.turns, turnId, updated) }; - } - - default: - return state; - } -} |
