Skip to content

feat(ai-anthropic, ai-bedrock, ai-claude-code)!: report the total input in promptTokens - #1677

Merged
AlemTuzlak merged 2 commits into
mainfrom
feat/total-prompt-tokens
Oct 9, 2026
Merged

AlemTuzlak merged 2 commits into
mainfrom
feat/total-prompt-tokens

Conversation

@AlemTuzlak

@AlemTuzlak AlemTuzlak commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

usage.promptTokens now counts the whole input on Anthropic, Bedrock Converse, and Claude Code: uncached tokens, plus cache reads, plus cache writes. Before, these three adapters counted only the uncached tokens, while every other adapter counted the total. totalTokens follows the new value. The cache split stays in promptTokensDetails.

This PR is split out of #1555.

🎯 Changes

  • ai-anthropic (src/usage.ts), ai-bedrock (src/converse/usage.ts), and ai-claude-code (src/stream/translate.ts) add cachedTokens and cacheWriteTokens into promptTokens.
  • On Bedrock, totalTokens is never less than the sum of the parts.
  • Main's Anthropic message_start fallback (start) now also covers the cache counts.
  • Not in this PR: cacheWrite1hTokens. It ships later with the model catalog.
  • Docs:
    • New ## Token usage section in chat/stream-events.md, with an upgrade note.
    • The Bedrock usage paragraph is fixed. Before, it told readers to add the cache counts.
    • One line each in the Anthropic and Claude Code pages.
  • Changeset: minor for the three packages, with a Breaking note.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with pnpm run test:pr, or these tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.
  • Docs: I updated docs/ for this change, or this change is not user-facing.
  • Changeset: I added a changeset (pnpm changeset), or this PR does not change a published package.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Testing

Commands run

  • vitest run: ai-anthropic 194 tests, ai-bedrock 120 tests, ai-claude-code 71 tests. All pass.
  • test:types and test:oxlint for the three packages: both pass.
  • pnpm test:docs: no broken links.
  • Not run locally: pnpm test:pr and the E2E suite. CI runs them.

Manual test

  1. Run pnpm --dir packages/ai-anthropic exec vitest run tests/usage-extraction.test.ts.
  2. Check that a response with input_tokens: 100, cache_read_input_tokens: 25, and cache_creation_input_tokens: 50 reports promptTokens: 175.
  3. Do the same for packages/ai-bedrock (the usage tests) and packages/ai-claude-code (the translate tests).

How this PR makes testing easy

  • Unit tests for each adapter pin the new numbers, including a null cache write.
  • E2E: anthropic-structured-usage.spec.ts changes from 125 to 5885, and bedrock-converse-cache.spec.ts changes from 3 to 8412. The aimock responses in global-setup.ts hard-code the cache counts (5760 and 8409), so the new values come from this change only.

Risk / rollback

Breaking for one pattern. Code that adds cachedTokens (or cacheWriteTokens) to promptTokens to get the total now counts the cache two times. Fix: use promptTokens as the total. Cost dashboards built on the old number show a larger input count after the upgrade. To undo, revert this PR.

Public API change

Before (Anthropic with a cache hit)

// usage: { promptTokens: 100, completionTokens: 50, totalTokens: 150,
//          promptTokensDetails: { cachedTokens: 25, cacheWriteTokens: 50 } }
const input = usage.promptTokens + (usage.promptTokensDetails?.cachedTokens ?? 0) + (usage.promptTokensDetails?.cacheWriteTokens ?? 0)

After

// usage: { promptTokens: 175, completionTokens: 50, totalTokens: 225,
//          promptTokensDetails: { cachedTokens: 25, cacheWriteTokens: 50 } }
const input = usage.promptTokens

Summary by CodeRabbit

  • Bug Fixes

    • Token usage totals for Anthropic, Bedrock, and Claude Code now include cached input tokens in promptTokens and totalTokens, providing a more complete view of usage.
  • Documentation

    • Clarified how cached and cache-write token counts are reported and how to calculate uncached input tokens. Updated guidance warns against adding cached counts to promptTokens, which would double-count them.

…t in promptTokens

promptTokens is now uncached + cache read + cache write on the Anthropic, Bedrock Converse, and Claude Code adapters. totalTokens follows. The cache parts stay in promptTokensDetails.
@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: TanStack/ai/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 54f4e0aa-1fa1-41cc-9786-733862979457

📥 Commits

Reviewing files that changed from the base of the PR and between a674520 and d8aa49e.


📒 Files selected for processing (15)
  • .changeset/total-prompt-tokens.md
  • docs/adapters/anthropic.md
  • docs/adapters/bedrock.md
  • docs/adapters/claude-code.md
  • docs/chat/stream-events.md
  • docs/config.json
  • packages/ai-anthropic/src/usage.ts
  • packages/ai-anthropic/tests/usage-extraction.test.ts
  • packages/ai-bedrock/src/converse/usage.ts
  • packages/ai-bedrock/tests/converse/adapter.test.ts
  • packages/ai-bedrock/tests/converse/stream-processor.test.ts
  • packages/ai-claude-code/src/stream/translate.ts
  • packages/ai-claude-code/tests/translate.test.ts
  • testing/e2e/tests/anthropic-structured-usage.spec.ts
  • testing/e2e/tests/bedrock-converse-cache.spec.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.



📝 Walkthrough

Walkthrough

The Anthropic, Bedrock, and Claude Code adapters now include cache-read and cache-write tokens in promptTokens and totalTokens. Tests, adapter documentation, and stream-event documentation reflect the updated token counts.

Changes

Cached Prompt Usage

Layer / File(s) Summary
Anthropic usage mapping
packages/ai-anthropic/src/usage.ts, packages/ai-anthropic/tests/usage-extraction.test.ts, testing/e2e/tests/anthropic-structured-usage.spec.ts
Anthropic prompt totals now include uncached input, cache-read tokens, and cache-write tokens. Tests update expected totals and cover missing cache-write counts and streaming usage cases.
Bedrock Converse usage mapping
packages/ai-bedrock/src/converse/usage.ts, packages/ai-bedrock/tests/converse/*, testing/e2e/tests/bedrock-converse-cache.spec.ts
Bedrock prompt totals now include cache-read and cache-write tokens. totalTokens uses the greater of the provider total and the computed prompt-plus-completion total. Tests cover both paths.
Claude Code usage mapping
packages/ai-claude-code/src/stream/translate.ts, packages/ai-claude-code/tests/translate.test.ts
Claude Code prompt and total counts now include cache-read and cache-write tokens. Tests cover usage with and without input_tokens.
Usage documentation and release notes
.changeset/total-prompt-tokens.md, docs/adapters/anthropic.md, docs/adapters/bedrock.md, docs/adapters/claude-code.md, docs/chat/stream-events.md, docs/config.json
Documentation describes full-input prompt counts, cache-token details, and how to calculate uncached tokens. The changeset declares minor releases for the three adapters, and documentation dates are updated.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Suggested reviewers: devholic, tombeckenham


Merge Risk: ⚪ Minimal · up to d8aa4

The adapters and documentation consistently describe full-input prompt tokens. No identified issue prevents merging after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 9 files. (6 skipped: 6… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check Passed The title clearly and concisely describes the primary change: reporting total input tokens in promptTokens for the three named adapters.
Description check Passed The description follows the required template, explains the implementation and breaking impact, documents testing, and includes the changeset and documentation updates. It clearly states that pnpm tes…
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.

Full details: Docstring Coverage

Explanation

Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 9 files. (6 skipped: 6 unsupported.)



  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR


  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@nx-cloud

nx-cloud Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit d8aa49e

Command Status Duration Result
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 3s View ↗

☁️ Nx Cloud last updated this comment at 2026-10-09 09:36:25 UTC

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Coverage

✅ Coverage held across 4 compared package(s).

Each package is measured twice in this job — on this PR and on its merge-base with main — and compared. A metric fails only when it is at or above 60% on the merge-base and under 60% on this PR. Other drops are listed but do not fail. Packages your PR doesn't affect are not measured and not listed.

package statements branches functions lines
ai-anthropic 88.01% (+0.02) 80.78% (+0.15) 86.74% (0.00) 88.34% (+0.02) ok
ai-bedrock 86.05% (+0.04) 77.73% (+0.39) 86.40% (0.00) 86.86% (+0.05) ok
ai-claude-code 88.31% (0.00) 76.00% (+0.44) 86.20% (0.00) 89.89% (0.00) ok
ai-code-mode-snippets 87.13% (0.00) 75.67% (0.00) 91.11% (0.00) 88.39% (0.00) ok

@pkg-pr-new

pkg-pr-new Bot commented Oct 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

npm i https://pkg.pr.new/@tanstack/ai@1677

@tanstack/ai-acp

npm i https://pkg.pr.new/@tanstack/ai-acp@1677

@tanstack/ai-angular

npm i https://pkg.pr.new/@tanstack/ai-angular@1677

@tanstack/ai-anthropic

npm i https://pkg.pr.new/@tanstack/ai-anthropic@1677

@tanstack/ai-bedrock

npm i https://pkg.pr.new/@tanstack/ai-bedrock@1677

@tanstack/ai-byteplus

npm i https://pkg.pr.new/@tanstack/ai-byteplus@1677

@tanstack/ai-claude-code

npm i https://pkg.pr.new/@tanstack/ai-claude-code@1677

@tanstack/ai-client

npm i https://pkg.pr.new/@tanstack/ai-client@1677

@tanstack/ai-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-cloudflare@1677

@tanstack/ai-code-mode

npm i https://pkg.pr.new/@tanstack/ai-code-mode@1677

@tanstack/ai-code-mode-snippets

npm i https://pkg.pr.new/@tanstack/ai-code-mode-snippets@1677

@tanstack/ai-codex

npm i https://pkg.pr.new/@tanstack/ai-codex@1677

@tanstack/ai-cohere

npm i https://pkg.pr.new/@tanstack/ai-cohere@1677

@tanstack/ai-compaction

npm i https://pkg.pr.new/@tanstack/ai-compaction@1677

@tanstack/ai-devtools-core

npm i https://pkg.pr.new/@tanstack/ai-devtools-core@1677

@tanstack/ai-durable-stream

npm i https://pkg.pr.new/@tanstack/ai-durable-stream@1677

@tanstack/ai-elevenlabs

npm i https://pkg.pr.new/@tanstack/ai-elevenlabs@1677

@tanstack/ai-event-client

npm i https://pkg.pr.new/@tanstack/ai-event-client@1677

@tanstack/ai-fal

npm i https://pkg.pr.new/@tanstack/ai-fal@1677

@tanstack/ai-gemini

npm i https://pkg.pr.new/@tanstack/ai-gemini@1677

@tanstack/ai-grok

npm i https://pkg.pr.new/@tanstack/ai-grok@1677

@tanstack/ai-grok-build

npm i https://pkg.pr.new/@tanstack/ai-grok-build@1677

@tanstack/ai-groq

npm i https://pkg.pr.new/@tanstack/ai-groq@1677

@tanstack/ai-isolate-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-isolate-cloudflare@1677

@tanstack/ai-isolate-daytona

npm i https://pkg.pr.new/@tanstack/ai-isolate-daytona@1677

@tanstack/ai-isolate-e2b

npm i https://pkg.pr.new/@tanstack/ai-isolate-e2b@1677

@tanstack/ai-isolate-node

npm i https://pkg.pr.new/@tanstack/ai-isolate-node@1677

@tanstack/ai-isolate-quickjs

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs@1677

@tanstack/ai-isolate-quickjs-bun

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs-bun@1677

@tanstack/ai-llmgateway

npm i https://pkg.pr.new/@tanstack/ai-llmgateway@1677

@tanstack/ai-lovable

npm i https://pkg.pr.new/@tanstack/ai-lovable@1677

@tanstack/ai-mcp

npm i https://pkg.pr.new/@tanstack/ai-mcp@1677

@tanstack/ai-memory

npm i https://pkg.pr.new/@tanstack/ai-memory@1677

@tanstack/ai-mistral

npm i https://pkg.pr.new/@tanstack/ai-mistral@1677

@tanstack/ai-octane

npm i https://pkg.pr.new/@tanstack/ai-octane@1677

@tanstack/ai-ollama

npm i https://pkg.pr.new/@tanstack/ai-ollama@1677

@tanstack/ai-ollaya

npm i https://pkg.pr.new/@tanstack/ai-ollaya@1677

@tanstack/ai-openai

npm i https://pkg.pr.new/@tanstack/ai-openai@1677

@tanstack/ai-opencode

npm i https://pkg.pr.new/@tanstack/ai-opencode@1677

@tanstack/ai-openrouter

npm i https://pkg.pr.new/@tanstack/ai-openrouter@1677

@tanstack/ai-perplexity

npm i https://pkg.pr.new/@tanstack/ai-perplexity@1677

@tanstack/ai-persistence

npm i https://pkg.pr.new/@tanstack/ai-persistence@1677

@tanstack/ai-preact

npm i https://pkg.pr.new/@tanstack/ai-preact@1677

@tanstack/ai-react

npm i https://pkg.pr.new/@tanstack/ai-react@1677

@tanstack/ai-react-ui

npm i https://pkg.pr.new/@tanstack/ai-react-ui@1677

@tanstack/ai-reactor

npm i https://pkg.pr.new/@tanstack/ai-reactor@1677

@tanstack/ai-remix

npm i https://pkg.pr.new/@tanstack/ai-remix@1677

@tanstack/ai-sandbox

npm i https://pkg.pr.new/@tanstack/ai-sandbox@1677

@tanstack/ai-sandbox-blaxel

npm i https://pkg.pr.new/@tanstack/ai-sandbox-blaxel@1677

@tanstack/ai-sandbox-boxd

npm i https://pkg.pr.new/@tanstack/ai-sandbox-boxd@1677

@tanstack/ai-sandbox-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-sandbox-cloudflare@1677

@tanstack/ai-sandbox-daytona

npm i https://pkg.pr.new/@tanstack/ai-sandbox-daytona@1677

@tanstack/ai-sandbox-docker

npm i https://pkg.pr.new/@tanstack/ai-sandbox-docker@1677

@tanstack/ai-sandbox-e2b

npm i https://pkg.pr.new/@tanstack/ai-sandbox-e2b@1677

@tanstack/ai-sandbox-local-process

npm i https://pkg.pr.new/@tanstack/ai-sandbox-local-process@1677

@tanstack/ai-sandbox-railway

npm i https://pkg.pr.new/@tanstack/ai-sandbox-railway@1677

@tanstack/ai-sandbox-sprites

npm i https://pkg.pr.new/@tanstack/ai-sandbox-sprites@1677

@tanstack/ai-sandbox-upstash-box

npm i https://pkg.pr.new/@tanstack/ai-sandbox-upstash-box@1677

@tanstack/ai-sandbox-vercel

npm i https://pkg.pr.new/@tanstack/ai-sandbox-vercel@1677

@tanstack/ai-skills

npm i https://pkg.pr.new/@tanstack/ai-skills@1677

@tanstack/ai-solid

npm i https://pkg.pr.new/@tanstack/ai-solid@1677

@tanstack/ai-solid-ui

npm i https://pkg.pr.new/@tanstack/ai-solid-ui@1677

@tanstack/ai-svelte

npm i https://pkg.pr.new/@tanstack/ai-svelte@1677

@tanstack/ai-typesafe

npm i https://pkg.pr.new/@tanstack/ai-typesafe@1677

@tanstack/ai-utils

npm i https://pkg.pr.new/@tanstack/ai-utils@1677

@tanstack/ai-vercel-gateway

npm i https://pkg.pr.new/@tanstack/ai-vercel-gateway@1677

@tanstack/ai-vertex

npm i https://pkg.pr.new/@tanstack/ai-vertex@1677

@tanstack/ai-vue

npm i https://pkg.pr.new/@tanstack/ai-vue@1677

@tanstack/ai-vue-ui

npm i https://pkg.pr.new/@tanstack/ai-vue-ui@1677

@tanstack/ai-worldlabs

npm i https://pkg.pr.new/@tanstack/ai-worldlabs@1677

@tanstack/openai-base

npm i https://pkg.pr.new/@tanstack/openai-base@1677

@tanstack/preact-ai-devtools

npm i https://pkg.pr.new/@tanstack/preact-ai-devtools@1677

@tanstack/react-ai-devtools

npm i https://pkg.pr.new/@tanstack/react-ai-devtools@1677

@tanstack/solid-ai-devtools

npm i https://pkg.pr.new/@tanstack/solid-ai-devtools@1677

@tanstack/svelte-ai-devtools

npm i https://pkg.pr.new/@tanstack/svelte-ai-devtools@1677

commit: d8aa49e

@AlemTuzlak
AlemTuzlak merged commit f562eac into main Oct 9, 2026
15 checks passed
@AlemTuzlak
AlemTuzlak deleted the feat/total-prompt-tokens branch October 9, 2026 09:43
@github-actions github-actions Bot mentioned this pull request Oct 9, 2026
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