fix(cost): fold delegated cost into by_day/by_model, price new Claude models, add cost-by-day table - #250
Open
mariadb-KyleHutchinson wants to merge 3 commits into
Conversation
…ice Claude 5 models Claude Code writes one JSONL line per content block of a single turn (thinking/text/tool_use), repeating the same message.usage on every line — summing without dedup on message.id inflated input/output/cache-creation tokens ~2-3x. Separately, cache-read tokens were tracked as a per-session high-water-mark instead of summed, undercounting any session with more than one cache-hitting turn (each turn bills its own cache reads under Anthropic's model). The two bugs partly canceled, masking a real cost undercount ($68.09 vs Anthropic's $110.49 on one sampled day). - Dedup token accumulation on message.id in the parent-session scan loop and the shared subagent/workflow transcript parser; switch cache-read tracking from max() to a cumulative sum used for both display and cost. - Fold delegated (Claude subagent/workflow) cost and tokens into by_day/by_agent/by_model/total in /analytics — verified zero message.id overlap between parent and subagent files across 180 real sessions, so this is additive, not a double count. Subagent spend is now attributed to its own model (can differ from the parent's) in by_model. - Add curated pricing for claude-sonnet-5 (introductory rate through 2026-08-31), claude-opus-5, claude-opus-4-8, claude-fable-5, verified against Anthropic's published rate card rather than the models.dev overlay. - Log a one-time warning when a model falls through to the generic _default rate, so the next new-model release degrades visibly instead of silently undercounting for weeks. - Bump the sidecar cache version (6->7) so previously-cached sessions reparse with the corrected numbers instead of serving stale ones forever. Independently re-verified the sampled day three ways (raw-jsonl recompute, the app's own scan, and the by_day fold-in logic) — all agree at $93.24, up from $68.09. Updated two delegation tests that had encoded the old high-water-mark behavior as expected, and added regression tests for the message.id dedup and the new pricing entries. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… no-op The previous commit folded Claude subagent/workflow (delegated) cost into by_agent/by_day/by_model/total in /analytics, but only for sessions coming from the LIVE scan. Any query for a day other than "today" is served entirely from history_store (SQLite) — and that store's schema never had a column for delegated_cost/delegated_input/output/cached, so the fold-in silently did nothing for every historical day. This is exactly what surfaced in the UI: 2026-08-06 kept showing $64.01 (session-only) instead of $93.24 even after restarting with the previous fix. Add delegated_* columns (schema v3), persist them in upsert_sessions(), and reconstruct them in _rehydrate() so a day served from the store folds delegated cost identically to a live-scanned day. Verified: after a fresh scan re-upserts history.db, querying 2026-08-06 through history_store.query() now returns $93.24, matching the live-scan figure exactly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mirrors the existing Agent breakdown table's style, sorted most-recent-first; reuses the by_day data the API already returns for the chart above it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mariadb-KyleHutchinson
force-pushed
the
fix/cost-undercount-subagents-and-pricing
branch
from
August 7, 2026 21:04
f2eddb1 to
23f80af
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This branch originally fixed a duplicate-JSONL-line/cache-read undercount in Claude session scanning. #248 landed an equivalent, independently-authored fix (
message.iddedup + cumulative cache-read billing via a dualcached/_cached_sumdesign) while this branch was in flight, so it's now rebased on top of that and only carries what #248 didn't already cover: delegated (subagent/workflow) cost was still missing fromby_day,by_model, and the/analyticsgrand total; four new Claude models had no pricing entry and silently fell back to the generic default rate; and historical (non-today)/analyticsqueries never persisted delegated cost at all. Also adds a cost-by-day breakdown table to the Analytics page.Fixes
by_day/by_model/total in/analytics(by_agentalready had this) — subagent spend is attributed to its own model, which can differ from the parent's (e.g. Explore on Haiku under an Opus session). Add curated pricing forclaude-sonnet-5(introductory rate through 2026-08-31),claude-opus-5,claude-opus-4-8,claude-fable-5, verified against Anthropic's published rate card rather than the models.dev overlay. Log a one-time warning when a model falls through to the generic_defaultrate, so the next new-model release degrades visibly instead of silently undercounting for weeks. Bumps the sidecar cache version (7→8) since the cached payload shape gained a newdelegated_by_modelfield.delegated_cost/delegated_input/output/cachedinhistory_store(schema v3) so historical (non-today)/analyticsdays fold in delegated cost the same way live-scanned days do — previously the schema had no column for it, so the fold-in silently no-op'd for every historical day.Features
🤖 Generated with Claude Code