fix(pricing): stop double-counting cached tokens; default cache prices to input rate #6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "trevin/fix/cache-cost-double-counting"
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?
Summary
prompt_tokensalready includescached_tokens(a subset), so the extractors now subtract cached from prompt soinputholds only fresh billable tokens. Anthropic's counts are independent/additive (no subset), so no subtraction there.completion_tokens_details.reasoning_tokensis a subset of output, NOT cache-creation input. It was wrongly mapped intocache_write(latent output-side double count for reasoning models). Now ignored.cache_read_per_million/cache_write_per_millionchanged from0.0toNone;Noneresolves toinput_per_millionat billing time. Unconfigured cache tokens are never silently free. Explicit0.0still honored as "free cache".prompt_total_tokenscolumn: nullable, migration-safe. Records total prompt for display parity with the OpenCode dashboard's Input column;input_tokens(fresh) shown as secondary._convert_usage+ streamingfinalize()emitprompt_tokens = input + cache_read + cache_write(total) so the OpenAI extractor reads the correct total from translated bodies.Root cause
OpenAI's
usage.prompt_tokensis the total prompt tokens (fresh + cached). AOR stored it verbatim intoTokenCounts.inputand billed it at the full input rate, then also billedcached_tokensat the cache-read rate. Every cached token was overcharged byinput_per_million. The fix is in the extract layer (per-adapter subset semantics), keepingcompute_cost_cma dumb sum.Testing
uv run ruff check .— passuv run ruff format --check .— passuv run pytest -q— 291 passedNew tests in
test_pricing.py:test_cache_no_double_count_fixed_formula— known-input regression proving cached billed once at cache-read ratetest_cache_double_count_bug_would_overcharge— documents the pre-fix bugtest_cache_default_none_never_silently_free— cache prices default to input ratetest_translated_anthropic_cost_matches_native— invariant consistency across adapterstest_extract_usage_openai_reasoning_tokens_not_cache_write— reasoning no longer hijacked into cache_write