fix: stabilize token/cache accounting across providers and routed Roo metadata#11448
fix: stabilize token/cache accounting across providers and routed Roo metadata#11448hannesrudolph merged 4 commits intomainfrom
Conversation
Each provider now computes totalInputTokens/totalOutputTokens directly
in their usage chunks, since each provider knows its own protocol
semantics. Task.ts uses these provider-computed values instead of
re-deriving them through calculateApiCostAnthropic/calculateApiCostOpenAI
which made incorrect assumptions about whether inputTokens includes
cache tokens.
Root cause: For Bedrock, the AI SDK normalizes inputTokens to include
cache tokens (OpenAI convention), but getApiProtocol('bedrock') returned
'anthropic', causing calculateApiCostAnthropic() to add cache tokens
a second time — doubling the displayed input token count.
AI SDK v6 exposes cachedInputTokens at usage.cachedInputTokens (top-level) and usage.inputTokenDetails.cacheReadTokens (structured), not at the legacy usage.details.cachedInputTokens path. Similarly for reasoning tokens. Updates 18 providers with proper v6 fallback chains and adds 30 new tests covering the v6 cache and reasoning token extraction paths. Providers with providerMetadata (anthropic, bedrock, minimax) retain it as highest priority, with v6 paths as secondary fallbacks.
hannesrudolph
left a comment
There was a problem hiding this comment.
Architectural direction is sound. Moving total token computation to the provider boundary eliminates the protocol misclassification double-counting problem, and the AI SDK v6 field path normalization is thorough with good fallback chains.
P1 (1 issue): cacheWriteTokens appears in the cacheRead fallback chain in roo.ts. Looks like a copy-paste error that would misreport write tokens as reads.
P2 (3 issues): Mixed indentation in roo.spec.ts from incomplete restructuring. totalCost and telemetry cost can now be undefined where they previously had calculated fallbacks. Worth confirming this is intentional.
P3 (2 observations): Local types inside createMessage could be extracted to module scope. The expanded usage type signature is now duplicated across ~15 provider files and could benefit from a shared type.
Test coverage is solid (44/44 Roo suite, new v6 field path tests for Bedrock, Gemini, OpenAI Native, OpenAI).
Summary
usage.cachedInputTokens,inputTokenDetails,outputTokenDetails)What changed
Validation
Notes