Usage & cost stats: metering, pricing, and the stats drawer (0047) #122
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "glen/0047-usage-stats"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements docs/0047-usage-and-cost-stats.md (the approved spec, merged in #121): per-ticket usage/cost metering across a conversation group — Gloo costs exact from the public
/platform/v2/modelsprice table, tokens/steps/time for everything, and a stats drawer in the chat header.Capture
LanguageModelUsagesummed inturn.ts, oneusage_eventsrow per turn (u_<conv>_<skip>), written after the turn stream closes — never fails the turn, recorded even when a slice throws.finish-stepusage read through a newonUsagehook in the shared sink, checkpointed into theu_hc_<callId>row after EVERY advance step (idempotent upsert) so a cancelled call keeps its completed metering; settle makes the final pass. Pi is priced; claude/cursor record tokens with no dollars (plan badge).Pricing
lib/usage/pricing.ts: pure cost function (fresh×input + cached×cache_read + output×output per-1M, long-context tier selection, platform-fee multiplier, cent rounding, null = unmetered), Gloo payload parser (cache_write 5m/1h/default tiers, deprecated→replacement attribution),normalizeUsagefor both AI SDK usage shapes (verified against installed types).model_pricesrefreshed daily: Gloo public endpoint (no key) + OpenRouter pricing from the existing catalog payload. Manual rows survive refreshes. Cold-start closed:startChatTurnandstartHarnessCallfire-and-forgetensureModelPrices(the models API alone left a null-cost window on fresh deploys).model_prices.platform_feedefaults 1.0; calibrate once against Gloo Studio's Usage dashboard and set via a manual row.Read + UI
GET /api/x/stats/<id>rolls up the 0046 locked group (root+descendants): totals, wall/work/wait time, touches (real user messages only), median answer latency, byModel (labels from the catalogs), byChild (conversations + harness calls with links), cache hit rate.components/stats-drawer.tsx: overlay-aside off a header button — hand-rolled SVG donut (chart-1..5 tokens, no chart dependency), plan rows, stacked time strip, per-model bars, per-child links. Semantic tokens only, mono numerals. Empty-state friendly. QA'd visually on clickhouse + Cal themes with a seeded fixture (numbers hand-verified: $8.06 group, per-model split, 70% cache hit).Review — fresh-eyes
start_threadreview (review skill) before this PR; both should-fix findings addressed in the last commit (cancelled-call metering, price cold-start); its id-math, double-count, workflow-bundle-hygiene, and test-quality hunts all came back sound. Remaining known items (noted by the review, deliberately not here): drizzle snapshot drift from 0048–0053 hand-written migrations (pre-existing), and the Gloo fee calibration above.Tests: 33 new (pricing math, parser, store, turn capture via the scripted mock, harness settle + cancel-survival, API rollup, OpenRouter prices). Full gate green: typecheck, lint, 777 passing / 13 skipped (one pre-existing flaky x-chat test passes in isolation and passed the full run too). Migration 0054 verified applying on a fresh db.