Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions packages/types/src/providers/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
15 changes: 15 additions & 0 deletions packages/types/src/providers/bedrock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 8 additions & 0 deletions packages/types/src/providers/claude-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions packages/types/src/providers/openrouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
])
Expand All @@ -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",
Expand Down
12 changes: 12 additions & 0 deletions packages/types/src/providers/vertex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
24 changes: 24 additions & 0 deletions src/api/providers/__tests__/anthropic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Strengthen the 1M-context assertions to validate cache pricing overrides as well. Since getModel() applies the first tier (contextWindow, inputPrice, outputPrice, cacheWritesPrice, cacheReadsPrice), consider also asserting cacheWritesPrice and cacheReadsPrice after enabling anthropicBeta1MContext to catch regressions in tier merging.

expect(model.info.contextWindow).toBe(1000000)
expect(model.info.inputPrice).toBe(6.0)
expect(model.info.outputPrice).toBe(22.5)
})
})
})
13 changes: 9 additions & 4 deletions src/api/providers/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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":
Expand Down Expand Up @@ -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":
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions src/api/providers/fetchers/__tests__/openrouter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
Expand Down
Loading