diff options
| author | Adam Malczewski <[email protected]> | 2026-06-10 08:29:59 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-10 08:29:59 +0900 |
| commit | 6db12ff70acb3333d05a5020ab66da4172a5225a (patch) | |
| tree | de5cc6314a3a6dd966d7c4fdb9b20adb04ae8307 /packages/transport-contract/src | |
| parent | 4248cd1d546a4c1fb4e68940c11b5e309c2c2736 (diff) | |
| download | dispatch-6db12ff70acb3333d05a5020ab66da4172a5225a.tar.gz dispatch-6db12ff70acb3333d05a5020ab66da4172a5225a.zip | |
feat(metrics): durable per-turn/step token+timing metrics (observability spans + persisted replay)
Two-part token-data improvement:
#2 Observability spans (kernel run-turn): turn & step span-close now stamp
ALL four Usage fields — added usage.cacheReadTokens/cacheWriteTokens (were
silently dropped) and normalized usage_* -> usage.* to match the
provider.request span (consistent D9 GROUP BY). No contract change.
#3 Persisted replay metrics (conversation-store + read endpoint): new
StepMetrics/TurnMetrics wire types; conversation-store persists per-turn
metrics in a separate key space (appendMetrics/loadMetrics, turn-append
order); session-orchestrator accumulates per-step+turn metrics from the
event stream (pure metrics.ts) and persists after seal; transport-http
serves GET /conversations/:id/metrics -> ConversationMetricsResponse.
Contracts: @dispatch/wire + @dispatch/transport-contract bumped 0.3.0->0.4.0
(additive). GLOSSARY: turn metrics / step metrics.
typecheck EXIT 0, biome clean, 546 vitest + 89 bun = 635 tests.
Diffstat (limited to 'packages/transport-contract/src')
| -rw-r--r-- | packages/transport-contract/src/index.ts | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/packages/transport-contract/src/index.ts b/packages/transport-contract/src/index.ts index cdddad6..bc01ca6 100644 --- a/packages/transport-contract/src/index.ts +++ b/packages/transport-contract/src/index.ts @@ -20,9 +20,9 @@ */ import type { SurfaceClientMessage, SurfaceServerMessage } from "@dispatch/ui-contract"; -import type { AgentEvent, StoredChunk } from "@dispatch/wire"; +import type { AgentEvent, StoredChunk, TurnMetrics } from "@dispatch/wire"; -export type { AgentEvent, StoredChunk } from "@dispatch/wire"; +export type { AgentEvent, StepMetrics, StoredChunk, TurnMetrics } from "@dispatch/wire"; /** * Request body for `POST /chat` (sent as JSON). @@ -92,6 +92,25 @@ export interface ConversationHistoryResponse { readonly latestSeq: number; } +/** + * Response body for `GET /conversations/:id/metrics` — the persisted per-turn + * (and per-step) token + timing metrics for a conversation, for a client + * reopening a past conversation to render historical usage/latency. + * + * This is a SEPARATE axis from the two other read concerns and is deliberately + * its own endpoint: the live `usage`/`step-complete`/`done` events are transient + * (not persisted), and `ConversationHistoryResponse` carries seq-cursor chunk + * CONTENT. Metrics are keyed per TURN (not per chunk) and so are not seq-filtered + * — hence a sibling route rather than a field on the history response. + * + * `turns` is every SEALED turn's `TurnMetrics` in turn order. A turn appears only + * after its metrics were persisted (post-seal); an in-flight or unsealed turn is + * absent until then. + */ +export interface ConversationMetricsResponse { + readonly turns: readonly TurnMetrics[]; +} + // ─── WebSocket chat ops ─────────────────────────────────────────────────────── // The persistent WS connection multiplexes chat ops (below) with surface ops // (`@dispatch/ui-contract`). The unified unions at the bottom compose both. Chat |
