feat: add Opus [1M] model with correct 1M context window reporting#649
feat: add Opus [1M] model with correct 1M context window reporting#649bbesner wants to merge 1 commit intositeboon:mainfrom
Conversation
Closes siteboon#579 Adds `opus[1m]` to the Claude model picker and fixes context window reporting so 1M-context models display the correct token budget. Changes: - Add opus[1m] option to CLAUDE_MODELS.OPTIONS in modelConstants.js - Read contextWindow from SDK result's modelUsage data instead of hardcoding 160K — the SDK already reports the correct value - Pass selectedModel to extractTokenBudget for fallback detection - Thread selectedModel through ChatInterface → ChatComposer → ChatInputControls so the pie chart shows 1M before first response - Prevent HTTP token-usage fetch from overwriting the correct WebSocket-provided context window (race condition where HTTP returns 200K default after WebSocket already set 1M) The context window fix required four layers: 1. Model list entry (trivial) 2. Server-side: read contextWindow from SDK modelUsage 3. Frontend: model-aware fallback in TokenUsagePie 4. Frontend: prevent HTTP/WebSocket state race on token budget Tested with Claude Code CLI 2.1.92 + SDK 0.2.104.
📝 WalkthroughWalkthroughThis pull request adds support for Claude Opus with 1M token context window in the model picker UI, improves server-side token budget calculation to leverage selected model information, and enhances client-side token usage fetching with cancellation tracking and state preservation. Changes
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/components/chat/view/subcomponents/ChatInputControls.tsx (1)
83-83: Consider centralizing context-window fallback inference.Line 83 duplicates model-suffix fallback logic that now also exists server-side. A shared helper/constants path would reduce frontend/backend drift.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/chat/view/subcomponents/ChatInputControls.tsx` at line 83, The TokenUsagePie invocation is duplicating the context-window fallback logic (ternary using selectedModel.includes('1m')); extract that inference into a shared helper or constant (e.g., getDefaultContextWindow or DEFAULT_CONTEXT_WINDOW) used by both frontend and backend and replace the inline fallback in TokenUsagePie props (where tokenBudget?.total || (selectedModel && selectedModel.includes('1m') ? 1000000 : 200000)) with a call to the shared helper or the shared constant so both sides use the same source of truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@server/claude-sdk.js`:
- Around line 305-307: The override for CONTEXT_WINDOW currently uses
parseInt(process.env.CONTEXT_WINDOW) || 0 which accepts negative or non-integer
values; update the logic that sets contextWindow so it parses the env var,
verifies it's a finite positive integer (>0) (e.g., use Number.isInteger(parsed)
&& parsed > 0) and only applies it when valid, otherwise fall back to 0 or the
existing model-derived value; modify the code where contextWindow is assigned
(the parseInt(...) usage and the subsequent if (!contextWindow) check) to
perform this validation and fall back safely.
In `@src/components/chat/hooks/useChatSessionState.ts`:
- Around line 565-567: The code is clearing an existing valid WebSocket-provided
token budget on transient fetch failures by calling setTokenBudget(null) in the
fetch error path; update the error/else path inside useChatSessionState so it
does not overwrite a current tokenBudget on transient failures—either remove the
setTokenBudget(null) call or guard it so you only clear tokenBudget when you
have a definitive “no budget” response (e.g., only setTokenBudget(null) when the
fetch returned a confirmed null budget), and leave tokenBudget untouched when
the fetch failed or was cancelled (check cancelled and the fetched value
variable before calling setTokenBudget).
---
Nitpick comments:
In `@src/components/chat/view/subcomponents/ChatInputControls.tsx`:
- Line 83: The TokenUsagePie invocation is duplicating the context-window
fallback logic (ternary using selectedModel.includes('1m')); extract that
inference into a shared helper or constant (e.g., getDefaultContextWindow or
DEFAULT_CONTEXT_WINDOW) used by both frontend and backend and replace the inline
fallback in TokenUsagePie props (where tokenBudget?.total || (selectedModel &&
selectedModel.includes('1m') ? 1000000 : 200000)) with a call to the shared
helper or the shared constant so both sides use the same source of truth.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: fa4587b2-427e-4ef4-a765-a6f3330dc513
📒 Files selected for processing (6)
server/claude-sdk.jsshared/modelConstants.jssrc/components/chat/hooks/useChatSessionState.tssrc/components/chat/view/ChatInterface.tsxsrc/components/chat/view/subcomponents/ChatComposer.tsxsrc/components/chat/view/subcomponents/ChatInputControls.tsx
| // Determine context window: env override > model usage data > selected model > default | ||
| let contextWindow = parseInt(process.env.CONTEXT_WINDOW) || 0; | ||
| if (!contextWindow) { |
There was a problem hiding this comment.
Validate CONTEXT_WINDOW as a positive integer before applying override.
At Line 306, parseInt(process.env.CONTEXT_WINDOW) || 0 treats negative values as valid and can emit an invalid budget total.
Suggested fix
- let contextWindow = parseInt(process.env.CONTEXT_WINDOW) || 0;
+ const envContextWindow = Number.parseInt(process.env.CONTEXT_WINDOW ?? '', 10);
+ let contextWindow = Number.isFinite(envContextWindow) && envContextWindow > 0 ? envContextWindow : 0;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Determine context window: env override > model usage data > selected model > default | |
| let contextWindow = parseInt(process.env.CONTEXT_WINDOW) || 0; | |
| if (!contextWindow) { | |
| // Determine context window: env override > model usage data > selected model > default | |
| const envContextWindow = Number.parseInt(process.env.CONTEXT_WINDOW ?? '', 10); | |
| let contextWindow = Number.isFinite(envContextWindow) && envContextWindow > 0 ? envContextWindow : 0; | |
| if (!contextWindow) { |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@server/claude-sdk.js` around lines 305 - 307, The override for CONTEXT_WINDOW
currently uses parseInt(process.env.CONTEXT_WINDOW) || 0 which accepts negative
or non-integer values; update the logic that sets contextWindow so it parses the
env var, verifies it's a finite positive integer (>0) (e.g., use
Number.isInteger(parsed) && parsed > 0) and only applies it when valid,
otherwise fall back to 0 or the existing model-derived value; modify the code
where contextWindow is assigned (the parseInt(...) usage and the subsequent if
(!contextWindow) check) to perform this validation and fall back safely.
| } else if (!cancelled) { | ||
| setTokenBudget(null); | ||
| } |
There was a problem hiding this comment.
Avoid clearing existing token budget on transient fetch failures.
At Line 565-Line 567, setting tokenBudget to null can erase a valid WebSocket-provided budget and cause UI regression.
Suggested fix
- } else if (!cancelled) {
- setTokenBudget(null);
- }
+ } else if (!cancelled) {
+ // Preserve existing budget (especially realtime WS updates) on HTTP fetch failures.
+ setTokenBudget((prev: Record<string, unknown> | null) => prev);
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } else if (!cancelled) { | |
| setTokenBudget(null); | |
| } | |
| } else if (!cancelled) { | |
| // Preserve existing budget (especially realtime WS updates) on HTTP fetch failures. | |
| setTokenBudget((prev: Record<string, unknown> | null) => prev); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/chat/hooks/useChatSessionState.ts` around lines 565 - 567, The
code is clearing an existing valid WebSocket-provided token budget on transient
fetch failures by calling setTokenBudget(null) in the fetch error path; update
the error/else path inside useChatSessionState so it does not overwrite a
current tokenBudget on transient failures—either remove the setTokenBudget(null)
call or guard it so you only clear tokenBudget when you have a definitive “no
budget” response (e.g., only setTokenBudget(null) when the fetch returned a
confirmed null budget), and leave tokenBudget untouched when the fetch failed or
was cancelled (check cancelled and the fetched value variable before calling
setTokenBudget).
|
@bbesner thank you for your effort in this PR. I've added the new models in the context and soon the context window reporting will also be revamped so I'll close this PR for now. |
Summary
Closes #579
Adds
opus[1m]to the Claude model picker and fixes context window reporting so 1M-context models display the correct token budget instead of showing 160K/200K.Problem
When using Opus with 1M context (
claude-opus-4-6[1m]), the token usage pie chart incorrectly showed 160K or 200K as the total context window, making it appear 100% full even with plenty of room remaining.Root Cause
The fix required addressing four layers:
opus[1m]was missing fromCLAUDE_MODELS.OPTIONSextractTokenBudget()hardcoded160000instead of readingcontextWindowfrom the SDK'smodelUsageresult (which already reports1000000for 1M models)TokenUsagePieused160000as fallback before the first server response. Now checks the selected model name for1msuffixtotal: 1000000, the HTTPtoken-usageendpoint re-fires and overwrites it with200000. Fixed by preventing HTTP from overwriting a higher WebSocket valueChanges
shared/modelConstants.js— Addopus[1m]optionserver/claude-sdk.js— ReadcontextWindowfrom SDK result'smodelUsagedata; passselectedModelfor fallback detectionsrc/.../ChatInputControls.tsx— AcceptselectedModelprop, use model-aware context window fallbacksrc/.../ChatComposer.tsx— ThreadselectedModelpropsrc/.../ChatInterface.tsx— PassclaudeModelto composersrc/.../useChatSessionState.ts— Prevent HTTP token-usage fetch from overwriting WebSocket valueTesting
Tested with Claude Code CLI 2.1.92 +
@anthropic-ai/claude-agent-sdk0.2.104.opus[1m]→ pie shows 1,000,000 immediately ✓sonnet→ pie correctly shows 200,000 ✓sonnet[1m]→ pie correctly shows 1,000,000 ✓Note
The SDK (0.2.104) already reports
contextWindow: 1000000in themodelUsageresult for 1M models. This PR makes CloudCLI read that value instead of ignoring it. Users on older SDK versions may need to upgrade for the server-side detection to work; the frontend fallback handles the case where the SDK doesn't reportcontextWindow.Summary by CodeRabbit
New Features
Improvements