diff --git a/packages/types/src/providers/anthropic.ts b/packages/types/src/providers/anthropic.ts index 2cb38537a4..f6057fbcca 100644 --- a/packages/types/src/providers/anthropic.ts +++ b/packages/types/src/providers/anthropic.ts @@ -6,6 +6,28 @@ export type AnthropicModelId = keyof typeof anthropicModels export const anthropicDefaultModelId: AnthropicModelId = "claude-sonnet-4-20250514" export const anthropicModels = { + "claude-sonnet-4-5-20250514": { + maxTokens: 64_000, // Overridden to 8k if `enableReasoningEffort` is false. + contextWindow: 200_000, // Default 200K, extendable to 1M with beta flag 'context-1m-2025-08-07' + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 3.0, // $3 per million input tokens (≤200K context) + outputPrice: 15.0, // $15 per million output tokens (≤200K context) + cacheWritesPrice: 3.75, // $3.75 per million tokens + cacheReadsPrice: 0.3, // $0.30 per million tokens + supportsReasoningBudget: true, + // Tiered pricing for extended context (requires beta flag 'context-1m-2025-08-07') + tiers: [ + { + contextWindow: 1_000_000, // 1M tokens with beta flag + inputPrice: 6.0, // $6 per million input tokens (>200K context) + outputPrice: 22.5, // $22.50 per million output tokens (>200K context) + cacheWritesPrice: 7.5, // $7.50 per million tokens (>200K context) + cacheReadsPrice: 0.6, // $0.60 per million tokens (>200K context) + }, + ], + }, "claude-sonnet-4-20250514": { maxTokens: 64_000, // Overridden to 8k if `enableReasoningEffort` is false. contextWindow: 200_000, // Default 200K, extendable to 1M with beta flag 'context-1m-2025-08-07' @@ -28,6 +50,18 @@ export const anthropicModels = { }, ], }, + "claude-opus-4-5-20250514": { + maxTokens: 32_000, // Overridden to 8k if `enableReasoningEffort` is false. + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 15.0, // $15 per million input tokens + outputPrice: 75.0, // $75 per million output tokens + cacheWritesPrice: 18.75, // $18.75 per million tokens + cacheReadsPrice: 1.5, // $1.50 per million tokens + supportsReasoningBudget: true, + }, "claude-opus-4-1-20250805": { maxTokens: 8192, contextWindow: 200_000, diff --git a/packages/types/src/providers/bedrock.ts b/packages/types/src/providers/bedrock.ts index 67215e7796..a6fff55a7a 100644 --- a/packages/types/src/providers/bedrock.ts +++ b/packages/types/src/providers/bedrock.ts @@ -67,6 +67,21 @@ export const bedrockModels = { maxCachePoints: 1, cachableFields: ["system"], }, + "anthropic.claude-sonnet-4-5-20250514-v1:0": { + maxTokens: 8192, + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + supportsReasoningBudget: true, + inputPrice: 3.0, + outputPrice: 15.0, + cacheWritesPrice: 3.75, + cacheReadsPrice: 0.3, + minTokensPerCachePoint: 1024, + maxCachePoints: 4, + cachableFields: ["system", "messages", "tools"], + }, "anthropic.claude-sonnet-4-20250514-v1:0": { maxTokens: 8192, contextWindow: 200_000, @@ -82,6 +97,21 @@ export const bedrockModels = { maxCachePoints: 4, cachableFields: ["system", "messages", "tools"], }, + "anthropic.claude-opus-4-5-20250514-v1:0": { + maxTokens: 8192, + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + supportsReasoningBudget: true, + inputPrice: 15.0, + outputPrice: 75.0, + cacheWritesPrice: 18.75, + cacheReadsPrice: 1.5, + minTokensPerCachePoint: 1024, + maxCachePoints: 4, + cachableFields: ["system", "messages", "tools"], + }, "anthropic.claude-opus-4-1-20250805-v1:0": { maxTokens: 8192, contextWindow: 200_000, diff --git a/packages/types/src/providers/claude-code.ts b/packages/types/src/providers/claude-code.ts index d9b658319a..a99f89335c 100644 --- a/packages/types/src/providers/claude-code.ts +++ b/packages/types/src/providers/claude-code.ts @@ -40,6 +40,14 @@ export function getClaudeCodeModelId(baseModelId: ClaudeCodeModelId, useVertex = } export const claudeCodeModels = { + "claude-sonnet-4-5-20250514": { + ...anthropicModels["claude-sonnet-4-5-20250514"], + supportsImages: false, + supportsPromptCache: true, // Claude Code does report cache tokens + supportsReasoningEffort: false, + supportsReasoningBudget: false, + requiredReasoningBudget: false, + }, "claude-sonnet-4-20250514": { ...anthropicModels["claude-sonnet-4-20250514"], supportsImages: false, @@ -48,6 +56,14 @@ export const claudeCodeModels = { supportsReasoningBudget: false, requiredReasoningBudget: false, }, + "claude-opus-4-5-20250514": { + ...anthropicModels["claude-opus-4-5-20250514"], + supportsImages: false, + supportsPromptCache: true, // Claude Code does report cache tokens + supportsReasoningEffort: false, + supportsReasoningBudget: false, + requiredReasoningBudget: false, + }, "claude-opus-4-1-20250805": { ...anthropicModels["claude-opus-4-1-20250805"], supportsImages: false, diff --git a/packages/types/src/providers/vertex.ts b/packages/types/src/providers/vertex.ts index 8010fccf8e..d1a1e0b12c 100644 --- a/packages/types/src/providers/vertex.ts +++ b/packages/types/src/providers/vertex.ts @@ -163,6 +163,18 @@ export const vertexModels = { inputPrice: 1.25, outputPrice: 5, }, + "claude-sonnet-4-5@20250514": { + maxTokens: 8192, + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 3.0, + outputPrice: 15.0, + cacheWritesPrice: 3.75, + cacheReadsPrice: 0.3, + supportsReasoningBudget: true, + }, "claude-sonnet-4@20250514": { maxTokens: 8192, contextWindow: 200_000, @@ -175,6 +187,18 @@ export const vertexModels = { cacheReadsPrice: 0.3, supportsReasoningBudget: true, }, + "claude-opus-4-5@20250514": { + maxTokens: 8192, + contextWindow: 200_000, + supportsImages: true, + supportsComputerUse: true, + supportsPromptCache: true, + inputPrice: 15.0, + outputPrice: 75.0, + cacheWritesPrice: 18.75, + cacheReadsPrice: 1.5, + supportsReasoningBudget: true, + }, "claude-opus-4-1@20250805": { maxTokens: 8192, contextWindow: 200_000, diff --git a/src/api/providers/__tests__/anthropic.spec.ts b/src/api/providers/__tests__/anthropic.spec.ts index b1d0a2f6b3..a71ddd55f4 100644 --- a/src/api/providers/__tests__/anthropic.spec.ts +++ b/src/api/providers/__tests__/anthropic.spec.ts @@ -264,5 +264,41 @@ describe("AnthropicHandler", () => { expect(result.reasoningBudget).toBeUndefined() expect(result.temperature).toBe(0) }) + + it("should handle Claude 4.5 Sonnet model correctly", () => { + const handler = new AnthropicHandler({ + apiKey: "test-api-key", + apiModelId: "claude-sonnet-4-5-20250514", + }) + const model = handler.getModel() + expect(model.id).toBe("claude-sonnet-4-5-20250514") + expect(model.info.maxTokens).toBe(64000) + expect(model.info.contextWindow).toBe(200000) + expect(model.info.supportsReasoningBudget).toBe(true) + }) + + it("should handle Claude 4.5 Opus model correctly", () => { + const handler = new AnthropicHandler({ + apiKey: "test-api-key", + apiModelId: "claude-opus-4-5-20250514", + }) + const model = handler.getModel() + expect(model.id).toBe("claude-opus-4-5-20250514") + expect(model.info.maxTokens).toBe(32000) + expect(model.info.contextWindow).toBe(200000) + expect(model.info.supportsReasoningBudget).toBe(true) + }) + + it("should enable 1M context for Claude 4.5 Sonnet when beta flag is set", () => { + const handler = new AnthropicHandler({ + apiKey: "test-api-key", + apiModelId: "claude-sonnet-4-5-20250514", + anthropicBeta1MContext: true, + }) + const model = handler.getModel() + expect(model.info.contextWindow).toBe(1000000) + expect(model.info.inputPrice).toBe(6.0) + expect(model.info.outputPrice).toBe(22.5) + }) }) }) diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index cb48492b60..9f328be904 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -45,13 +45,18 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa const cacheControl: CacheControlEphemeral = { type: "ephemeral" } let { id: modelId, betas = [], maxTokens, temperature, reasoning: thinking } = this.getModel() - // Add 1M context beta flag if enabled for Claude Sonnet 4 - if (modelId === "claude-sonnet-4-20250514" && this.options.anthropicBeta1MContext) { + // Add 1M context beta flag if enabled for Claude Sonnet 4 and 4.5 + if ( + (modelId === "claude-sonnet-4-20250514" || modelId === "claude-sonnet-4-5-20250514") && + this.options.anthropicBeta1MContext + ) { betas.push("context-1m-2025-08-07") } switch (modelId) { + case "claude-sonnet-4-5-20250514": case "claude-sonnet-4-20250514": + case "claude-opus-4-5-20250514": case "claude-opus-4-1-20250805": case "claude-opus-4-20250514": case "claude-3-7-sonnet-20250219": @@ -110,7 +115,9 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa // Then check for models that support prompt caching switch (modelId) { + case "claude-sonnet-4-5-20250514": case "claude-sonnet-4-20250514": + case "claude-opus-4-5-20250514": case "claude-opus-4-1-20250805": case "claude-opus-4-20250514": case "claude-3-7-sonnet-20250219": @@ -243,8 +250,11 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa let id = modelId && modelId in anthropicModels ? (modelId as AnthropicModelId) : anthropicDefaultModelId let info: ModelInfo = anthropicModels[id] - // If 1M context beta is enabled for Claude Sonnet 4, update the model info - if (id === "claude-sonnet-4-20250514" && this.options.anthropicBeta1MContext) { + // If 1M context beta is enabled for Claude Sonnet 4 or 4.5, update the model info + if ( + (id === "claude-sonnet-4-20250514" || id === "claude-sonnet-4-5-20250514") && + this.options.anthropicBeta1MContext + ) { // Use the tier pricing for 1M context const tier = info.tiers?.[0] if (tier) { diff --git a/webview-ui/src/components/settings/providers/Anthropic.tsx b/webview-ui/src/components/settings/providers/Anthropic.tsx index ede2b90208..3aeed2b479 100644 --- a/webview-ui/src/components/settings/providers/Anthropic.tsx +++ b/webview-ui/src/components/settings/providers/Anthropic.tsx @@ -22,7 +22,8 @@ export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: Anthro const [anthropicBaseUrlSelected, setAnthropicBaseUrlSelected] = useState(!!apiConfiguration?.anthropicBaseUrl) // Check if the current model supports 1M context beta - const supports1MContextBeta = selectedModel?.id === "claude-sonnet-4-20250514" + const supports1MContextBeta = + selectedModel?.id === "claude-sonnet-4-20250514" || selectedModel?.id === "claude-sonnet-4-5-20250514" const handleInputChange = useCallback( (