feat: add Claude 4.5 Sonnet model across all providers (#8368)

This commit is contained in:
Daniel 2025-09-29 13:04:40 -05:00 committed by GitHub
parent c943ba7875
commit 6a91385f05
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 98 additions and 5 deletions

View file

@ -6,6 +6,28 @@ export type AnthropicModelId = keyof typeof anthropicModels
export const anthropicDefaultModelId: AnthropicModelId = "claude-sonnet-4-20250514"
export const anthropicModels = {
"claude-4.5-sonnet": {
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'

View file

@ -13,6 +13,21 @@ export const bedrockDefaultPromptRouterModelId: BedrockModelId = "anthropic.clau
// of the default prompt routers AWS enabled for GA of the promot router
// feature.
export const bedrockModels = {
"anthropic.claude-4.5-sonnet-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"],
},
"amazon.nova-pro-v1:0": {
maxTokens: 5000,
contextWindow: 300_000,

View file

@ -40,6 +40,14 @@ export function getClaudeCodeModelId(baseModelId: ClaudeCodeModelId, useVertex =
}
export const claudeCodeModels = {
"claude-4.5-sonnet": {
...anthropicModels["claude-4.5-sonnet"],
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,

View file

@ -38,6 +38,7 @@ export const OPEN_ROUTER_PROMPT_CACHING_MODELS = new Set([
"anthropic/claude-3.7-sonnet:beta",
"anthropic/claude-3.7-sonnet:thinking",
"anthropic/claude-sonnet-4",
"anthropic/claude-4.5-sonnet",
"anthropic/claude-opus-4",
"anthropic/claude-opus-4.1",
"google/gemini-2.5-flash-preview",
@ -59,6 +60,7 @@ export const OPEN_ROUTER_COMPUTER_USE_MODELS = new Set([
"anthropic/claude-3.7-sonnet:beta",
"anthropic/claude-3.7-sonnet:thinking",
"anthropic/claude-sonnet-4",
"anthropic/claude-4.5-sonnet",
"anthropic/claude-opus-4",
"anthropic/claude-opus-4.1",
])
@ -81,6 +83,7 @@ export const OPEN_ROUTER_REASONING_BUDGET_MODELS = new Set([
"anthropic/claude-opus-4",
"anthropic/claude-opus-4.1",
"anthropic/claude-sonnet-4",
"anthropic/claude-4.5-sonnet",
"google/gemini-2.5-pro-preview",
"google/gemini-2.5-pro",
"google/gemini-2.5-flash-preview-05-20",

View file

@ -6,6 +6,18 @@ export type VertexModelId = keyof typeof vertexModels
export const vertexDefaultModelId: VertexModelId = "claude-sonnet-4@20250514"
export const vertexModels = {
"claude-4.5-sonnet": {
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,
},
"gemini-2.5-flash-preview-05-20:thinking": {
maxTokens: 65_535,
contextWindow: 1_048_576,

View file

@ -264,5 +264,29 @@ 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-4.5-sonnet",
})
const model = handler.getModel()
expect(model.id).toBe("claude-4.5-sonnet")
expect(model.info.maxTokens).toBe(64000)
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-4.5-sonnet",
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)
})
})
})

View file

@ -45,12 +45,16 @@ 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-4.5-sonnet") &&
this.options.anthropicBeta1MContext
) {
betas.push("context-1m-2025-08-07")
}
switch (modelId) {
case "claude-4.5-sonnet":
case "claude-sonnet-4-20250514":
case "claude-opus-4-1-20250805":
case "claude-opus-4-20250514":
@ -110,6 +114,7 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
// Then check for models that support prompt caching
switch (modelId) {
case "claude-4.5-sonnet":
case "claude-sonnet-4-20250514":
case "claude-opus-4-1-20250805":
case "claude-opus-4-20250514":
@ -243,8 +248,8 @@ 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-4.5-sonnet") && this.options.anthropicBeta1MContext) {
// Use the tier pricing for 1M context
const tier = info.tiers?.[0]
if (tier) {

View file

@ -34,6 +34,7 @@ describe("OpenRouter API", () => {
"google/gemini-2.5-flash", // OpenRouter doesn't report this as supporting prompt caching
"google/gemini-2.5-flash-lite-preview-06-17", // OpenRouter doesn't report this as supporting prompt caching
"anthropic/claude-opus-4.1", // Not yet available in OpenRouter API
"anthropic/claude-4.5-sonnet", // Not yet available in OpenRouter API
])
const ourCachingModels = Array.from(OPEN_ROUTER_PROMPT_CACHING_MODELS).filter(
@ -52,6 +53,7 @@ describe("OpenRouter API", () => {
const excludedComputerUseModels = new Set([
"anthropic/claude-opus-4.1", // Not yet available in OpenRouter API
"anthropic/claude-4.5-sonnet", // Not yet available in OpenRouter API
])
const expectedComputerUseModels = Array.from(OPEN_ROUTER_COMPUTER_USE_MODELS)
@ -134,6 +136,7 @@ describe("OpenRouter API", () => {
"google/gemini-2.5-flash-lite-preview-06-17",
"google/gemini-2.5-pro",
"anthropic/claude-opus-4.1", // Not yet available in OpenRouter API
"anthropic/claude-4.5-sonnet", // Not yet available in OpenRouter API
])
const expectedReasoningBudgetModels = Array.from(OPEN_ROUTER_REASONING_BUDGET_MODELS)

View file

@ -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-4.5-sonnet"
const handleInputChange = useCallback(
<K extends keyof ProviderSettings, E>(