Merge feat/graph-rendering: wave 4 — extraction usage capture (live + persisted), true abort

# Conflicts:
#	src/server/observability.ts
This commit is contained in:
amosblomqvist
2026-09-11 03:28:23 +03:00
10 changed files with 335 additions and 32 deletions
+36
View File
@@ -9,6 +9,7 @@
import type { UIMessage } from "ai";
import type { Phase3 } from "../phases.ts";
import type { PlanNodeStatus, PlanTree } from "./plan.ts";
import type { EmissionStats } from "./graph.ts";
// ─── Chat records (the session store's on-disk format) ───────────────────────
@@ -32,6 +33,41 @@ export interface ChatRecord {
* each entry onto its message; aggregates are folds over this log
* (core/prices.ts). */
turns?: TurnUsage[];
/** Append-only background-extraction usage log (2026-09 observability):
* one entry per finished pipeline run on THIS chat — extraction is real
* spend too. Same parallel-log discipline as `turns` (nothing rides
* inside messages). Keyed by startedAt; idempotent appends. */
extractions?: ExtractionRunUsage[];
}
// ─── Background-extraction usage (the money channel, extraction side) ────────
/** One pipeline stage's model usage — the stage's model + every step it
* billed (CallUsage per agent step). Steps, not a sum: cost and context
* folds happen at read time (core/prices.ts). */
export interface ExtractionStageUsage {
/** The OpenRouter model id that ran this stage. */
model: string;
steps: CallUsage[];
}
/** One finished (or failed mid-flight) extraction run's usage record.
* Appended to the chat's `extractions` log when the run ends — success or
* failure, because money was spent either way; `stats` is present only
* when the merger actually ran. */
export interface ExtractionRunUsage {
/** The run's registry startedAt (ms) — the idempotency key. */
startedAt: number;
at: string;
durationMs: number;
/** What the run merged into the graph; absent when it failed first. */
stats?: EmissionStats;
/** Model usage per stage, in pipeline order (merger is deterministic —
* no model call, no entry). */
stages: {
extractor: ExtractionStageUsage;
auditor: ExtractionStageUsage;
};
}
// ─── Usage accounting (the money channel) ─────────────────────────────────────
+11
View File
@@ -22,6 +22,17 @@
* strength — strength is derived at read time from topology. */
export type EdgeType = "follows" | "supports";
/** What one extraction run merged into the graph ledgers — the merger's
* output, also persisted in extraction-run usage records (contracts/chat). */
export interface EmissionStats {
/** New graph nodes appended. */
nodes: number;
/** New edge assertions appended. */
edges: number;
/** Ledger events rebuilt (quiz outcomes + observations). */
events: number;
}
/** One provenance point — message-granular (DECIDED 2026-09-02): nodes and
* edges record every (chat, message) where they came up, deep-linkable to
* the exact transcript point. */