Fix turn-usage keying: idempotent per request turn id, not messageId

Live smoke exposed two bugs in the turn usage log:
- onFinish messages carry no ids (withMessageIds fills copies inside
  persistTurn), so fresh turns keyed messageId "" — provenance lost.
- The SDK coalesces continuation turns into ONE response message (a whole
  probe conversation lands in a single assistant message), so per-messageId
  idempotency swallowed every continuation turn's usage.

TurnUsage gains id: string (unique per request, the append idempotency
key); messageId stays as transcript provenance, taken from the id-filled
list. appendTurnUsage dedupes by id; continuation turns with the same
messageId each keep their usage.
This commit is contained in:
amosblomqvist
2026-09-11 04:16:05 +03:00
parent f4abad3f15
commit 741ff416d6
6 changed files with 38 additions and 21 deletions
+3 -2
View File
@@ -39,8 +39,9 @@ export interface ChatStore {
/** Persist the session plan tree (plan tools call this in execute). */
saveTree(id: string, tree: PlanTree): void;
/** Append one usage entry to the record's turn log (the money channel,
* 2026-09): idempotent per messageId — a turn persisted twice (abort
* replays, wake-turn retries) appends exactly once. */
* 2026-09): idempotent per turn id — each request carries its own, so
* a turn persisted twice appends once while continuation turns (which
* share a response message id) each keep their usage. */
appendTurnUsage(id: string, entry: TurnUsage): void;
/** Append one extraction-run usage entry — idempotent per startedAt. */
appendExtractionUsage(id: string, entry: ExtractionRunUsage): void;