You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Cache-read tokens are priced at the full input rate — overstates cost ~10x on the cached path #268
// Cache reads bill at the input rate here (we already fold cache_read/creation
// into `input` in user-ai.ts), which slightly over-estimates cached calls
"Slightly" is doing a lot of work. Anthropic bills cache reads at ~10% of the input rate and cache writes at 1.25×. Folding both into input at the full $3/M is a 10× overcharge on the read path.
Live 30d ledger, chat kind: input=4,796,074, of which cache_read=993,574. Those tokens are charged ~$2.98 and really cost ~$0.30 — about $2.68 overstated on one kind alone, ~7% of the reported total. The ratio gets worse as prompt caching does its job, so the error grows precisely as the platform gets more efficient.
Fix
Stop folding cache_read_input_tokens / cache_creation_input_tokens into input in user-ai.ts — carry them as their own fields.
Add cacheReadPerM / cacheWritePerM to the PRICES table (Anthropic: 0.1× and 1.25× of input).
Price the three components separately.
Storage: ai_usage has input_tokens/output_tokens only. Add nullable cache_read_tokens/cache_write_tokens columns in a migration; existing rows stay NULL and keep their historical (over-stated) cost rather than being retro-corrected.
Acceptance
Cache reads priced at the cache rate, not the input rate; unit test with a known Anthropic usage block.
Historical rows unchanged — no retroactive rewrite of a ledger.
Usage page can show the cached share, since it is now the interesting number (it is the saving).
Note the sign: this makes reported cost go down. It does not offset #267, which makes it go up by more.
Already fixed — I filed this off a stale comment. Closing.
Cache tokens are priced correctly today:
migrations/0074_ai_usage_cache_tokens.sql adds cache_read_tokens / cache_write_tokens, nullable so pre-migration rows read as unknown rather than asserting "no cache activity".
user-ai.ts:195 keeps cache_read_input_tokens / cache_creation_input_tokensseparate instead of summing them into input.
ai-pricing.ts has CACHE_READ_MULTIPLIER (0.1x) and CACHE_WRITE_MULTIPLIER (1.25x) applied against the model's input rate.
What misled me: the comment at the top of PRICES still said "we already fold cache_read/creation into input in user-ai.ts, which slightly over-estimates cached calls" — describing the pre-fix behaviour, ten lines above the constants that disprove it. Fixed in this session so the next reader isn't caught the same way.
One real residual, not worth its own issue: rows written before 0074 were priced with the old fold and remain overstated. They cannot be corrected — the split was never recorded, which is exactly why 0074 chose NULL over a 0 backfill. So historical totals skew high; current ones don't.
Activity
serge-ivo commentedon Aug 6, 2026
Already fixed — I filed this off a stale comment. Closing.
Cache tokens are priced correctly today:
migrations/0074_ai_usage_cache_tokens.sqladdscache_read_tokens/cache_write_tokens, nullable so pre-migration rows read as unknown rather than asserting "no cache activity".user-ai.ts:195keepscache_read_input_tokens/cache_creation_input_tokensseparate instead of summing them intoinput.ai-pricing.tshasCACHE_READ_MULTIPLIER(0.1x) andCACHE_WRITE_MULTIPLIER(1.25x) applied against the model's input rate.What misled me: the comment at the top of
PRICESstill said "we already fold cache_read/creation intoinputin user-ai.ts, which slightly over-estimates cached calls" — describing the pre-fix behaviour, ten lines above the constants that disprove it. Fixed in this session so the next reader isn't caught the same way.One real residual, not worth its own issue: rows written before 0074 were priced with the old fold and remain overstated. They cannot be corrected — the split was never recorded, which is exactly why 0074 chose NULL over a 0 backfill. So historical totals skew high; current ones don't.
feat(console): disclose what the usage estimate leaves out (#270)
docs(pricing): the comment outlived the fix it described