0051 — Context-window meter per chat #131
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "glen/context-meter"
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/0051-context-meter.md (approved plan v1 in the ticket thread): ROADMAP item 7, the per-chat context-window meter — a percentage-first chip in the chat header ("oops, context is at 80% — wrap this up", per Chad).
What lands
0056_context_meter.sqladdslast_input_tokens/last_cached_tokens/last_output_tokens/last_reasoning_tokens(nullable) tousage_events;turn.tskeeps the turn's LAST slice's counts beside the summed usage andrecordUsageSteppersists them. The last slice's input re-sent the whole conversation, so lastInput+lastOutput is the conversation's size in tokens. Reasoning is NOT added on top (schema convention: it's a display-only slice of output).readContextUsage(SQLORDER BY ended_at DESC LIMIT 1, pre-0051 rows excluded outright);readConversationStatsgainscontext {usedTokens, windowTokens, pct}for THIS conversation (never the group), window resolved through the model catalogs. Null → hidden when unmetered or the model is unknown.components/context-meter.tsx: mono percent + thin fraction bar in the chat header, warning ≥85%, destructive ≥95%, exact numbers in the tooltip; refetches on turn settle with a delayed follow-up (the usage row lands after the stream finishes). The stats drawer gains a fuller readout section.Verification
npm run typecheck && npm run lint && npm run test— tsc clean, eslint at exactly the 2 pre-existing warnings, 774 passed / 13 skipped (11 new tests: store latest-row/pre-0051/harness exclusion, turn single- vs multi-slice last-slice pin via the steer mock, API present/absent/clamp-at-1/zero-token/unknown-model/tie-break).PRAGMA foreign_key_checkclean. The upgrade-path check caught a real bug pre-commit: the 0056 journal entry needswhen> 0055's future-dated timestamp (drizzle applies only entries newer than the last applied) — the first version silently skipped.117,600 / 128,000 tokens, post-fix 50% neutral chip; screenshots in the ticket thread.Fresh-eyes review (fix-first verdict, no blockers)
Both should-fixes taken:
finishfires beforerecordUsageStep); a one-shot 1.5s follow-up fetch after a turn ran closes it. (Lint then caught my ref-during-render — moved into an effect.)Nits taken: SQL pick with
isNotNull(dead tie-break code gone), pct comment matches reality, drawer copy says "that turn's model's window", plus 3 new guard tests (clamp/zero/latest-row-vs-newer-pre-0051). Nits declined: sharedformatTokenshelper (two components, different display intents — refactor when a third appears).Deliberately out of scope (0051 records the decisions): compaction/fresh-thread affordances (warn-only v1), backfill (forward-only per 0047), per-harness-call meters.
readConversationStats gains context {usedTokens, windowTokens, pct} from the conversation's own latest metered chat row (never the group's) against the catalog window. Null when unmetered/unknown.