Repository navigation
fix(parser): count Claude usage once per API response; price 1h cache writes - #43
Merged
Merged
Conversation
… writes Claude Code writes one API response as several transcript records (one per content block) that share message.id and each repeat the response's usage. ccx summed every record. Fable records repeat the final figure; Opus 5 records carry the figure as it stood when the block was cut, so the last record is the only honest one. Usage now lives on the last record of each response (Message.ResponseID) in the full parse, the quick parse and every sidechain file, and session totals are the sum of what the messages carry. Anthropic bills the 1h cache write at 2x input; ccx priced every write at the 5m rate. MessageUsage carries the 1h subset (usage.cache_creation.ephemeral_1h_input_tokens) and ModelPricing the 1h rate on every Claude tier, Sonnet 5 included; records without the split keep the cheaper reading. Backported from the agent-registry branch, where the rule was checked against a wire capture. On 17 real sessions (Opus 5, Opus 5.5, Fable 5, Fable 5.1, Opus 4.6, Haiku 4.5) the session-list cost now matches that branch's main-loop figure exactly; 0.17.0 was 2.2x high at the median (1.3x to 3.1x). Workflow-agent discovery and all-in totals stay on that branch. CacheFormatVersion 6 -> 10: 7-9 were stamped by unreleased development builds with other shapes, so their caches must never match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lroolle
force-pushed
the
fix/usage-once-per-response
branch
from
October 17, 2026 09:51
415e72e to
d303710
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
v0.17.0 overstates Claude Code cost. Claude Code writes one API response as several transcript records, one per content block. They share
message.id, and each repeats the response'susage; ccx summed every record. This backports the fix from the agent-registry branch (60278b9), where it was checked against a cctrace wire capture of 2,607 requests:Message.ResponseID) in the full parse, the quick parse, and sidechain files. Session totals are the sum after the collapse.usage.cache_creation.ephemeral_1h_input_tokens) are priced at 2x input instead of the 5-minute rate, on every Claude tier.CacheFormatVersiongoes 6 -> 10. Unreleased development builds stamped 7-9 with other shapes, so those caches must never match.Not included: workflow-agent discovery and all-in totals. They stay on the registry branch.
Evidence
17 real sessions (Opus 5, Opus 5.5, Fable 5, Fable 5.1, Opus 4.6, Haiku 4.5), each binary parsing with its own cache dir:
Not verified on real data: the Sonnet 5 1h rate (no Sonnet 5 sessions in the sample). It follows the same 2x-input rule as the other tiers.
Test plan
gofmt -l .empty,go vet ./...,go test -race ./...green locally🤖 Generated with Claude Code