Skip to content

Add per-turn token usage tracking with cost analytics - #37

Merged
pufit merged 6 commits into
mainfrom
pufit/usage-tracking
Apr 7, 2026
Merged

Add per-turn token usage tracking with cost analytics#37
pufit merged 6 commits into
mainfrom
pufit/usage-tracking

Conversation

@pufit

@pufitpufit commented Apr 7, 2026

Copy link
Copy Markdown
Member

Summary

  • New migration v020: session_usage table stores per-turn token counts (input, output, cache creation, cache read, max context) — one row per agent turn, ~60 bytes each
  • total_cost_usd finally populated: The dead column from v003 now accumulates estimated cost per session using Opus 4 pricing ($15/M input, $75/M output, $1.50/M cache read, $18.75/M cache write)
  • Diagnostics endpoint: Returns 7-day usage summary, daily breakdown, per-source breakdown (web/cron/telegram), and cache hit rate
  • DiagnosticsPage UI: New "Usage & Cost" section with summary cards, CSS bar chart for daily usage, and source breakdown table
  • Session sidebar: Shows $X.XX cost under session title when cost > $0.005
  • Cascade delete: session_usage rows cleaned up when sessions are deleted

Purely additive — no existing behavior changes. One INSERT per agent turn (~1ms on SQLite).

Test plan

  • All 326 tests pass
  • Frontend builds clean (tsc + vite)
  • No secrets in diff (pre-commit scan)
  • Verify migration applies on fresh DB
  • Verify usage data appears in diagnostics after a few turns
  • Verify session cost shows in sidebar

Generated by Nerve

pufit added 6 commits April 6, 2026 21:42
- New migration v020: session_usage table storing per-turn token counts
- New UsageStore mixin with aggregate queries (by period, source, cache hit rate)
- engine.py: persist usage per turn + accumulate total_cost_usd on sessions
- Diagnostics endpoint: 7-day usage summary, daily chart data, source breakdown
- Frontend: Usage & Cost section in DiagnosticsPage with bar chart and source table
- Session sidebar: show estimated cost under session title when > $0.01
- Cascade delete session_usage rows when sessions are deleted
…on-cached
The SDK's input_tokens field only counts fresh (non-cached) input.
Total input = input_tokens + cache_read + cache_creation.
The old formula divided cache_read by just input_tokens (6), giving 7878900%.
- Fix context bar: total used now includes cached tokens (was under-counting)
- Add Cost section to hover: this turn's estimated cost, session total, cache hit rate
- Rename "Input tokens" to "Fresh input" for clarity
The SDK reports cumulative tokens across all API sub-calls in a turn
(each tool use triggers a new call). A turn with 3 tool calls shows
~2.4M cache_read even though each call only uses ~700K of the 1M window.
Estimate the number of sub-calls from total/max ratio and divide to
approximate single-call context occupancy. Shows ~N sub-calls in hover
when turn involved multiple API round-trips.
- Migration v021: add model, cost_usd, duration_ms, duration_api_ms,
num_turns, web_search/fetch columns to session_usage
- Capture ResultMessage fields (total_cost_usd, durations, num_turns)
and AssistantMessage.model in engine.py
- Use SDK-provided cost when available, fall back to model-specific
pricing (8 tiers matching Claude Code's modelCost.ts)
- Fix context bar: divide by num_turns (not broken ceil heuristic),
exclude output tokens from context window estimation
- Add per-model usage breakdown to diagnostics endpoint and UI
- Diagnostics uses SDK cost_usd directly instead of re-estimating
Sign up for freeto 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.

1 participant

@pufit