Skip to content

Commit 10546ae

Browse files
committed
feat: add beta support for Claude Sonnet 4 1M context window
- Default context window remains at 200K tokens - Added UI checkbox to enable 1M context via beta flag 'context-1m-2025-08-07' - Implemented tiered pricing structure that updates dynamically in model info - Added context window display to ModelInfoView - When beta is enabled: - Context window: 1,000,000 tokens - Input price: /MTok (vs standard /MTok) - Output price: 2.50/MTok (vs standard 5/MTok) - Added anthropicBeta1MContext field to provider settings - Updated AnthropicHandler to apply beta flag and adjust model info - Updated useSelectedModel hook to apply tier pricing in UI when beta is enabled
1 parent 44f4a49 commit 10546ae

File tree

6 files changed

+85
-6
lines changed

6 files changed

+85
-6
lines changed

packages/types/src/provider-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ const anthropicSchema = apiModelIdProviderModelSchema.extend({
9999
apiKey: z.string().optional(),
100100
anthropicBaseUrl: z.string().optional(),
101101
anthropicUseAuthToken: z.boolean().optional(),
102+
anthropicBeta1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window
102103
})
103104

104105
const claudeCodeSchema = apiModelIdProviderModelSchema.extend({

packages/types/src/providers/anthropic.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,25 @@ export const anthropicDefaultModelId: AnthropicModelId = "claude-sonnet-4-202505
88
export const anthropicModels = {
99
"claude-sonnet-4-20250514": {
1010
maxTokens: 64_000, // Overridden to 8k if `enableReasoningEffort` is false.
11-
contextWindow: 1_000_000,
11+
contextWindow: 200_000, // Default 200K, extendable to 1M with beta flag 'context-1m-2025-08-07'
1212
supportsImages: true,
1313
supportsComputerUse: true,
1414
supportsPromptCache: true,
15-
inputPrice: 3.0, // $3 per million input tokens
16-
outputPrice: 15.0, // $15 per million output tokens
15+
inputPrice: 3.0, // $3 per million input tokens (≤200K context)
16+
outputPrice: 15.0, // $15 per million output tokens (≤200K context)
1717
cacheWritesPrice: 3.75, // $3.75 per million tokens
1818
cacheReadsPrice: 0.3, // $0.30 per million tokens
1919
supportsReasoningBudget: true,
20+
// Tiered pricing for extended context (requires beta flag 'context-1m-2025-08-07')
21+
tiers: [
22+
{
23+
contextWindow: 1_000_000, // 1M tokens with beta flag
24+
inputPrice: 6.0, // $6 per million input tokens (>200K context)
25+
outputPrice: 22.5, // $22.50 per million output tokens (>200K context)
26+
cacheWritesPrice: 3.75, // Same cache pricing
27+
cacheReadsPrice: 0.3,
28+
},
29+
],
2030
},
2131
"claude-opus-4-1-20250805": {
2232
maxTokens: 8192,

src/api/providers/anthropic.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
4545
const cacheControl: CacheControlEphemeral = { type: "ephemeral" }
4646
let { id: modelId, betas = [], maxTokens, temperature, reasoning: thinking } = this.getModel()
4747

48+
// Add 1M context beta flag if enabled for Claude Sonnet 4
49+
if (modelId === "claude-sonnet-4-20250514" && this.options.anthropicBeta1MContext) {
50+
betas.push("context-1m-2025-08-07")
51+
}
52+
4853
switch (modelId) {
4954
case "claude-sonnet-4-20250514":
5055
case "claude-opus-4-1-20250805":
@@ -236,7 +241,21 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
236241
getModel() {
237242
const modelId = this.options.apiModelId
238243
let id = modelId && modelId in anthropicModels ? (modelId as AnthropicModelId) : anthropicDefaultModelId
239-
const info: ModelInfo = anthropicModels[id]
244+
let info: ModelInfo = anthropicModels[id]
245+
246+
// If 1M context beta is enabled for Claude Sonnet 4, update the model info
247+
if (id === "claude-sonnet-4-20250514" && this.options.anthropicBeta1MContext) {
248+
// Use the tier pricing for 1M context
249+
const tier = info.tiers?.[0]
250+
if (tier) {
251+
info = {
252+
...info,
253+
contextWindow: tier.contextWindow,
254+
inputPrice: tier.inputPrice,
255+
outputPrice: tier.outputPrice,
256+
}
257+
}
258+
}
240259

241260
const params = getModelParams({
242261
format: "anthropic",

webview-ui/src/components/settings/ModelInfoView.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ export const ModelInfoView = ({
4141
supportsLabel={t("settings:modelInfo.supportsPromptCache")}
4242
doesNotSupportLabel={t("settings:modelInfo.noPromptCache")}
4343
/>,
44+
typeof modelInfo?.contextWindow === "number" && modelInfo.contextWindow > 0 && (
45+
<>
46+
<span className="font-medium">Context Window:</span> {modelInfo.contextWindow?.toLocaleString()} tokens
47+
</>
48+
),
4449
typeof modelInfo?.maxTokens === "number" && modelInfo.maxTokens > 0 && (
4550
<>
4651
<span className="font-medium">{t("settings:modelInfo.maxOutput")}:</span>{" "}

webview-ui/src/components/settings/providers/Anthropic.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { ProviderSettings } from "@roo-code/types"
66

77
import { useAppTranslation } from "@src/i18n/TranslationContext"
88
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
9+
import { useSelectedModel } from "@src/components/ui/hooks/useSelectedModel"
910

1011
import { inputEventTransform, noTransform } from "../transforms"
1112

@@ -16,9 +17,13 @@ type AnthropicProps = {
1617

1718
export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: AnthropicProps) => {
1819
const { t } = useAppTranslation()
20+
const selectedModel = useSelectedModel(apiConfiguration)
1921

2022
const [anthropicBaseUrlSelected, setAnthropicBaseUrlSelected] = useState(!!apiConfiguration?.anthropicBaseUrl)
2123

24+
// Check if the current model supports 1M context beta
25+
const supports1MContextBeta = selectedModel?.id === "claude-sonnet-4-20250514"
26+
2227
const handleInputChange = useCallback(
2328
<K extends keyof ProviderSettings, E>(
2429
field: K,
@@ -79,6 +84,20 @@ export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: Anthro
7984
</>
8085
)}
8186
</div>
87+
{supports1MContextBeta && (
88+
<div>
89+
<Checkbox
90+
checked={apiConfiguration?.anthropicBeta1MContext ?? false}
91+
onChange={(checked: boolean) => {
92+
setApiConfigurationField("anthropicBeta1MContext", checked)
93+
}}>
94+
Enable 1M context window (Beta)
95+
</Checkbox>
96+
<div className="text-sm text-vscode-descriptionForeground mt-1 ml-6">
97+
Extends context window to 1 million tokens for Claude Sonnet 4
98+
</div>
99+
</div>
100+
)}
82101
</>
83102
)
84103
}

webview-ui/src/components/ui/hooks/useSelectedModel.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,33 @@ function getSelectedModel({
291291
default: {
292292
provider satisfies "anthropic" | "gemini-cli" | "human-relay" | "fake-ai"
293293
const id = apiConfiguration.apiModelId ?? anthropicDefaultModelId
294-
const info = anthropicModels[id as keyof typeof anthropicModels]
295-
return { id, info }
294+
const baseInfo = anthropicModels[id as keyof typeof anthropicModels]
295+
296+
// Apply 1M context beta tier pricing for Claude Sonnet 4
297+
if (
298+
provider === "anthropic" &&
299+
id === "claude-sonnet-4-20250514" &&
300+
apiConfiguration.anthropicBeta1MContext &&
301+
baseInfo
302+
) {
303+
// Type assertion since we know claude-sonnet-4-20250514 has tiers
304+
const modelWithTiers = baseInfo as typeof baseInfo & {
305+
tiers?: Array<{ contextWindow: number; inputPrice?: number; outputPrice?: number }>
306+
}
307+
const tier = modelWithTiers.tiers?.[0]
308+
if (tier) {
309+
// Create a new ModelInfo object with updated values
310+
const info: ModelInfo = {
311+
...baseInfo,
312+
contextWindow: tier.contextWindow,
313+
inputPrice: tier.inputPrice ?? baseInfo.inputPrice,
314+
outputPrice: tier.outputPrice ?? baseInfo.outputPrice,
315+
}
316+
return { id, info }
317+
}
318+
}
319+
320+
return { id, info: baseInfo }
296321
}
297322
}
298323
}

0 commit comments

Comments
 (0)