Skip to content

Add per-completion observability records and cache-aware cost accounting (#458) - #464

Open
wschenk wants to merge 1 commit into
mainfrom
feat/observability-completion-records
Open

Add per-completion observability records and cache-aware cost accounting (#458)#464
wschenk wants to merge 1 commit into
mainfrom
feat/observability-completion-records

Conversation

@wschenk

@wschenk wschenk commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Closes #458 (step 1–2 of epic #457). Design: reports/2026-09-02-observability-and-cheapest-model-mvp.md.

What

  • packages/core/src/observability/: CompletionRecord, CompletionSink, JsonlCompletionSink (<project>/.umwelten/completions/YYYY-MM-DD.jsonl), MemoryCompletionSink, NullCompletionSink. UMWELTEN_TRACE=0 disables; UMWELTEN_COMPLETIONS_DIR overrides; new BaseModelRunner({ sink }) overrides in-process.
  • BaseModelRunner emits one record per call from makeResult (all four ops), the aborted-stream path, and error paths.
  • TokenUsage/CostBreakdown gain cacheRead/cacheWrite/reasoning; normalizeTokenUsage maps AI SDK v5/v7, OpenAI and raw Anthropic shapes; calculateCost is cache-aware with input-rate fallback; OpenRouter reads input_cache_read/_write pricing.
  • Interaction.messageUsage + writeSessionTranscript(..., usageFor) persist Claude-shaped usage on assistant entries; sessions show renders cache rows when reads or writes exist.
  • ResponseMetadata.cost is now optional (already undefined at runtime for free models; all callers guarded it).

Verification

  • Targeted core suites: 75 passed. Full pnpm test:run: 3074 passed; only agent-runner-tools.test.ts fails (git signing key in sandbox temp repo — pre-existing, unrelated).
  • pnpm typecheck clean; eslint 0 errors on touched files.
  • End-to-end via MockLanguageModelV3 through the real generateText path: JSONL record has tokens.cacheRead: 800, cost.total = 0.00159 (200×$3 + 800×$0.30 + 50×$15 per M), and sessions show --session-dir prints Cache reads 800 from the written transcript.
  • Not run: live provider call (no API keys in sandbox).

…ing (#458)

- New packages/core/src/observability: CompletionRecord, CompletionSink,
  JsonlCompletionSink (<project>/.umwelten/completions/YYYY-MM-DD.jsonl),
  MemoryCompletionSink, NullCompletionSink; UMWELTEN_TRACE=0 disables,
  UMWELTEN_COMPLETIONS_DIR overrides the directory.
- BaseModelRunner emits one record per generate/stream call from makeResult
  (completed), the aborted-stream path, and error paths; ModelRunnerConfig.sink
  overrides the process default.
- TokenUsage/CostBreakdown gain cacheRead/cacheWrite/reasoning fields;
  normalizeTokenUsage maps AI SDK v5/v7, OpenAI and raw Anthropic shapes;
  calculateCost prices cache tokens at their own rate; OpenRouter pricing
  reads input_cache_read/input_cache_write.
- Interaction.messageUsage tags each assistant message; transcript-write
  persists Claude-shaped `usage` on assistant entries so `sessions show`
  reports cache reads for native umwelten transcripts.
- ResponseMetadata.cost is now optional (free models / no usage).
- Design report: reports/2026-09-02-observability-and-cheapest-model-mvp.md

Amp-Thread-ID: https://ampcode.com/threads/T-01a063b8-8fec-76fd-8d2a-6a5afd6fc60f
Co-authored-by: Will Schenk <wschenk@thefocus.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Observability step 1–2: CompletionRecord JSONL sink and cache-aware usage/pricing

2 participants