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).
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