Skip to content

feat: expose cached token count in usage statistics#636

Open
JulioVianaDev wants to merge 1 commit into
TanStack:mainfrom
JulioVianaDev:feat/expose-cached-tokens-in-usage
Open

feat: expose cached token count in usage statistics#636
JulioVianaDev wants to merge 1 commit into
TanStack:mainfrom
JulioVianaDev:feat/expose-cached-tokens-in-usage

Conversation

@JulioVianaDev
Copy link
Copy Markdown

@JulioVianaDev JulioVianaDev commented May 25, 2026

Provider adapters now forward cached/prompt-cache token counts into the unified cachedTokens field on RunFinishedEvent.usage, UsageInfo, and FinishInfo. This lets consumers calculate accurate costs by distinguishing cached vs uncached input tokens.

Provider mapping:

  • OpenAI Chat Completions: prompt_tokens_details.cached_tokens
  • OpenAI Responses API: input_tokens_details.cached_tokens
  • Anthropic: cache_read_input_tokens
  • Gemini: usageMetadata.cachedContentTokenCount
  • OpenRouter: promptTokensDetails.cachedTokens
  • Groq/Grok: inherited from openai-base
  • Ollama: no caching support (field omitted)

The field is optional — only present when the provider returns a non-null value, so existing consumers are unaffected.

Usage

const middleware: ChatMiddleware = {
  onFinish: (ctx, info) => {
    if (info.usage) {
      const { promptTokens, completionTokens, cachedTokens = 0 } = info.usage;
      const uncachedInput = promptTokens - cachedTokens;
      console.log(`Cached: ${cachedTokens}, Uncached: ${uncachedInput}`);
    }
  },
};


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **New Features**
* Added cached token usage tracking across multiple AI provider integrations including OpenAI, Anthropic, Gemini, and OpenRouter. The platform now surfaces cached prompt token counts in usage metrics and completion events, enabling users to better track and analyze costs associated with prompt caching features for improved budget visibility and reporting.

<!-- review_stack_entry_start -->

[![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/TanStack/ai/pull/636?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Provider adapters now forward cached/prompt-cache token counts into
the unified `cachedTokens` field on `RunFinishedEvent.usage`,
`UsageInfo`, and `FinishInfo`. This lets consumers calculate accurate
costs by distinguishing cached vs uncached input tokens.

Provider mapping:
- OpenAI Chat Completions: `prompt_tokens_details.cached_tokens`
- OpenAI Responses API: `input_tokens_details.cached_tokens`
- Anthropic: `cache_read_input_tokens`
- Gemini: `usageMetadata.cachedContentTokenCount`
- OpenRouter: `promptTokensDetails.cachedTokens`
- Groq/Grok: inherited from openai-base
- Ollama: no caching support (field omitted)

The field is optional — only present when the provider returns a
non-null value, so existing consumers are unaffected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d6b8bb3b-b4ac-4895-8fb2-3bfd66fa886d

📥 Commits

Reviewing files that changed from the base of the PR and between 3796438 and 9480b51.

📒 Files selected for processing (7)
  • packages/typescript/ai-anthropic/src/adapters/text.ts
  • packages/typescript/ai-gemini/src/adapters/text.ts
  • packages/typescript/ai-openrouter/src/adapters/text.ts
  • packages/typescript/ai/src/activities/chat/middleware/types.ts
  • packages/typescript/ai/src/types.ts
  • packages/typescript/openai-base/src/adapters/chat-completions-text.ts
  • packages/typescript/openai-base/src/adapters/responses-text.ts

📝 Walkthrough

Walkthrough

This PR adds support for forwarding cached token counts from AI provider APIs through RUN_FINISHED event usage objects. Core type definitions are extended with an optional cachedTokens field, and all provider adapters now conditionally emit this field when providers report cached token consumption.

Changes

Cached Token Support

Layer / File(s) Summary
Core usage type contracts
packages/typescript/ai/src/types.ts, packages/typescript/ai/src/activities/chat/middleware/types.ts
RunFinishedEvent, TextCompletionChunk, and SummarizationResult usage objects gain optional cachedTokens?: number field. Middleware types UsageInfo and FinishInfo are updated to expose cached token counts.
Provider adapters — cached token forwarding
packages/typescript/ai-anthropic/src/adapters/text.ts, packages/typescript/ai-gemini/src/adapters/text.ts, packages/typescript/ai-openrouter/src/adapters/text.ts, packages/typescript/openai-base/src/adapters/chat-completions-text.ts, packages/typescript/openai-base/src/adapters/responses-text.ts
Anthropic reads cache_read_input_tokens, Gemini reads cachedContentTokenCount, OpenRouter reads promptTokensDetails.cachedTokens, and OpenAI adapters read prompt_tokens_details.cached_tokens or input_tokens_details.cached_tokens, then conditionally include cachedTokens in terminal RUN_FINISHED usage objects.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Cached tokens flow from API to event,
Each provider's gift now clearly sent,
Core types and adapters aligned as one,
Token counts from cache—no code undone!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: exposing cached token counts in usage statistics across provider adapters.
Description check ✅ Passed The description provides comprehensive details about the changes, provider mappings, and usage examples, but the PR description template's checklist items are not filled out.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: lockfile failed supply-chain policy check. Run pnpm install locally to update the lockfile.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tombeckenham tombeckenham self-requested a review May 26, 2026 04:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant