fix: Align token usage metrics for both Claude and Codex#1943
fix: Align token usage metrics for both Claude and Codex#1943juliusmarminge merged 2 commits intopingdotgg:mainfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
88a4d08 to
75b5cea
Compare
75b5cea to
e9cfd8e
Compare
ApprovabilityVerdict: Needs human review This PR changes runtime behavior for token usage metrics tracking, introducing clamping logic and modifying how accumulated tokens are calculated. An open review comment identifies a potential bug where removed type guards could allow NaN values to corrupt token tracking state. You can customize Macroscope's approvability policy. Learn more. |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dismissing prior approval to re-evaluate f0ad5d5
There was a problem hiding this comment.
🟢 Low
In maxClaudeContextWindowFromModelUsage, the new implementation removes defensive runtime type checks for value.contextWindow. If the SDK returns malformed data where contextWindow is undefined or NaN, the function returns NaN instead of undefined. This corrupts context.lastKnownContextWindow (line 1330) since NaN !== undefined passes, causing silent degradation of token usage tracking. Consider restoring the type and finiteness checks to ensure malformed values are treated as undefined.
🤖 Copy this AI Prompt to have your agent fix this:
In file apps/server/src/provider/Layers/ClaudeAdapter.ts around line 277:
In `maxClaudeContextWindowFromModelUsage`, the new implementation removes defensive runtime type checks for `value.contextWindow`. If the SDK returns malformed data where `contextWindow` is `undefined` or `NaN`, the function returns `NaN` instead of `undefined`. This corrupts `context.lastKnownContextWindow` (line 1330) since `NaN !== undefined` passes, causing silent degradation of token usage tracking. Consider restoring the type and finiteness checks to ensure malformed values are treated as undefined.
Evidence trail:
apps/server/src/provider/Layers/ClaudeAdapter.ts lines 277-290 (REVIEWED_COMMIT) - new implementation without defensive checks
git_diff MERGE_BASE..REVIEWED_COMMIT showing old code had: `typeof contextWindow !== "number" || !Number.isFinite(contextWindow) || contextWindow <= 0` checks that are now removed
apps/server/src/provider/Layers/ClaudeAdapter.ts lines 1328-1330 (REVIEWED_COMMIT) - shows `if (resultContextWindow !== undefined)` check that would pass NaN
apps/server/src/provider/Layers/ClaudeAdapter.ts line 1340, 1345, 2025, 2057 - shows lastKnownContextWindow is used in token tracking
JavaScript Math.max() behavior: Math.max(0, undefined) returns NaN
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f0ad5d5. Configure here.

What Changed
Aligned the Claude token usage normalization with the same shared semantics used by the Codex adapter.
Both adapters now expose the context window fields with the same meaning:
usedTokens - the current in-window token usage
totalProcessedTokens - the accumulated total processed across requests when it is larger than usedTokens
maxTokens - the reported model context window
On the Claude side, this change makes sure accumulated result totals are not surfaced as current context usage. Instead, the current usage is bounded to the reported context window and the larger accumulated total is preserved in totalProcessedTokens.
Why
The context window UI depends on consistent normalized token usage across providers.
Codex already separates current usage from accumulated processed totals. Claude could previously report accumulated totals as current usage, which made the shared context window UI inconsistent and misleading.
This change aligns the Claude adapter with Codex semantics so the same UI can be used for both providers.
This does not solve the remaining gaps around compaction details or compact_boundary behavior. That still needs follow-up investigation in a separate PR.
UI Changes
Checklist
Note
Fix token usage metrics to clamp
usedTokensto the Claude context windownormalizeClaudeTokenUsagein ClaudeAdapter.ts now clampsusedTokensto the model's context window, while preservingtotalProcessedTokenswhen it exceeds the clamped value.task_progresssnapshot, the final turn completion keepsusedTokensfrom the earlier observed value and only updatestotalProcessedTokensif the accumulated total is larger.maxClaudeContextWindowFromModelUsageis refactored to use typedModelUsagerecords from@anthropic-ai/claude-agent-sdk, removing redundant finite/positive guards.thread.token-usage.updatedevents will now reportusedTokenscapped atmaxTokens(context window) rather than raw totals that could exceed it.📊 Macroscope summarized f0ad5d5. 1 file reviewed, 1 issue evaluated, 0 issues filtered, 1 comment posted
🗂️ Filtered Issues
Note
Medium Risk
Changes how Claude token usage is normalized and emitted, which can affect context-window UI and any downstream logic relying on
thread.token-usage.updatedsemantics. Scoped to usage accounting/typing with added tests to reduce regression risk.Overview
Aligns Claude token-usage semantics with the shared provider contract.
normalizeClaudeTokenUsagenow treatsusage.total_tokensas an accumulated processed total, clampsusedTokensto the reported modelcontextWindow, and surfaces oversize totals viatotalProcessedTokens.On turn completion, Claude now preserves the last in-window snapshot (from
task_progress) as the currentusedTokenswhile still updatingtotalProcessedTokensfrom the final result totals when larger. Adds regression tests covering oversize clamping and ensuring accumulated totals remain correct after progress snapshots.Reviewed by Cursor Bugbot for commit f0ad5d5. Bugbot is set up for automated code reviews on this repo. Configure here.