diff --git a/crates/anthropic/src/anthropic.rs b/crates/anthropic/src/anthropic.rs index db6f88d8b2ff5794ddbaaf8bf62c3b9dfababf7c..488802d7db3fe169708c33710f7e583c46d41ae9 100644 --- a/crates/anthropic/src/anthropic.rs +++ b/crates/anthropic/src/anthropic.rs @@ -70,6 +70,17 @@ pub enum Model { alias = "claude-opus-4-6-1m-context-thinking-latest" )] ClaudeOpus4_6, + #[serde( + rename = "claude-opus-4-7", + alias = "claude-opus-4-7-latest", + alias = "claude-opus-4-7-1m-context", + alias = "claude-opus-4-7-1m-context-latest", + alias = "claude-opus-4-7-thinking", + alias = "claude-opus-4-7-thinking-latest", + alias = "claude-opus-4-7-1m-context-thinking", + alias = "claude-opus-4-7-1m-context-thinking-latest" + )] + ClaudeOpus4_7, #[serde( rename = "claude-sonnet-4", alias = "claude-sonnet-4-latest", @@ -130,6 +141,10 @@ impl Model { } pub fn from_id(id: &str) -> Result { + if id.starts_with("claude-opus-4-7") { + return Ok(Self::ClaudeOpus4_7); + } + if id.starts_with("claude-opus-4-6") { return Ok(Self::ClaudeOpus4_6); } @@ -175,6 +190,7 @@ impl Model { Self::ClaudeOpus4_1 => "claude-opus-4-1-latest", Self::ClaudeOpus4_5 => "claude-opus-4-5-latest", Self::ClaudeOpus4_6 => "claude-opus-4-6-latest", + Self::ClaudeOpus4_7 => "claude-opus-4-7-latest", Self::ClaudeSonnet4 => "claude-sonnet-4-latest", Self::ClaudeSonnet4_5 => "claude-sonnet-4-5-latest", Self::ClaudeSonnet4_6 => "claude-sonnet-4-6-latest", @@ -191,6 +207,7 @@ impl Model { Self::ClaudeOpus4_1 => "claude-opus-4-1-20250805", Self::ClaudeOpus4_5 => "claude-opus-4-5-20251101", Self::ClaudeOpus4_6 => "claude-opus-4-6", + Self::ClaudeOpus4_7 => "claude-opus-4-7", Self::ClaudeSonnet4 => "claude-sonnet-4-20250514", Self::ClaudeSonnet4_5 => "claude-sonnet-4-5-20250929", Self::ClaudeSonnet4_6 => "claude-sonnet-4-6", @@ -206,6 +223,7 @@ impl Model { Self::ClaudeOpus4_1 => "Claude Opus 4.1", Self::ClaudeOpus4_5 => "Claude Opus 4.5", Self::ClaudeOpus4_6 => "Claude Opus 4.6", + Self::ClaudeOpus4_7 => "Claude Opus 4.7", Self::ClaudeSonnet4 => "Claude Sonnet 4", Self::ClaudeSonnet4_5 => "Claude Sonnet 4.5", Self::ClaudeSonnet4_6 => "Claude Sonnet 4.6", @@ -223,6 +241,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4 | Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4_6 @@ -248,7 +267,7 @@ impl Model { | Self::ClaudeSonnet4_5 | Self::ClaudeHaiku4_5 | Self::Claude3Haiku => 200_000, - Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6 => 1_000_000, + Self::ClaudeOpus4_6 | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 => 1_000_000, Self::Custom { max_tokens, .. } => *max_tokens, } } @@ -261,7 +280,7 @@ impl Model { | Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4_6 | Self::ClaudeHaiku4_5 => 64_000, - Self::ClaudeOpus4_6 => 128_000, + Self::ClaudeOpus4_6 | Self::ClaudeOpus4_7 => 128_000, Self::Claude3Haiku => 4_096, Self::Custom { max_output_tokens, .. @@ -275,6 +294,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4 | Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4_6 @@ -312,6 +332,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4 | Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4_6 @@ -320,10 +341,17 @@ impl Model { } } + pub fn supports_speed(&self) -> bool { + matches!(self, Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6) + } + pub fn supports_adaptive_thinking(&self) -> bool { match self { Self::Custom { mode, .. } => matches!(mode, AnthropicModelMode::AdaptiveThinking), - _ => matches!(self, Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6), + _ => matches!( + self, + Self::ClaudeOpus4_6 | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 + ), } } diff --git a/crates/bedrock/src/models.rs b/crates/bedrock/src/models.rs index 7c1e6e0e4e6ef873345c30c0af4c9e8842699c77..e26d98a3d716bf373e911af425c6bfa63c53a10d 100644 --- a/crates/bedrock/src/models.rs +++ b/crates/bedrock/src/models.rs @@ -84,6 +84,13 @@ pub enum Model { alias = "claude-opus-4-6-thinking-latest" )] ClaudeOpus4_6, + #[serde( + rename = "claude-opus-4-7", + alias = "claude-opus-4-7-latest", + alias = "claude-opus-4-7-thinking", + alias = "claude-opus-4-7-thinking-latest" + )] + ClaudeOpus4_7, #[serde( rename = "claude-sonnet-4-6", alias = "claude-sonnet-4-6-latest", @@ -203,7 +210,9 @@ impl Model { } pub fn from_id(id: &str) -> anyhow::Result { - if id.starts_with("claude-opus-4-6") { + if id.starts_with("claude-opus-4-7") { + Ok(Self::ClaudeOpus4_7) + } else if id.starts_with("claude-opus-4-6") { Ok(Self::ClaudeOpus4_6) } else if id.starts_with("claude-opus-4-5") { Ok(Self::ClaudeOpus4_5) @@ -230,6 +239,7 @@ impl Model { Self::ClaudeOpus4_1 => "claude-opus-4-1", Self::ClaudeOpus4_5 => "claude-opus-4-5", Self::ClaudeOpus4_6 => "claude-opus-4-6", + Self::ClaudeOpus4_7 => "claude-opus-4-7", Self::ClaudeSonnet4_6 => "claude-sonnet-4-6", Self::Llama4Scout17B => "llama-4-scout-17b", Self::Llama4Maverick17B => "llama-4-maverick-17b", @@ -279,6 +289,7 @@ impl Model { Self::ClaudeOpus4_1 => "anthropic.claude-opus-4-1-20250805-v1:0", Self::ClaudeOpus4_5 => "anthropic.claude-opus-4-5-20251101-v1:0", Self::ClaudeOpus4_6 => "anthropic.claude-opus-4-6-v1", + Self::ClaudeOpus4_7 => "anthropic.claude-opus-4-7-v1", Self::ClaudeSonnet4_6 => "anthropic.claude-sonnet-4-6", Self::Llama4Scout17B => "meta.llama4-scout-17b-instruct-v1:0", Self::Llama4Maverick17B => "meta.llama4-maverick-17b-instruct-v1:0", @@ -328,6 +339,7 @@ impl Model { Self::ClaudeOpus4_1 => "Claude Opus 4.1", Self::ClaudeOpus4_5 => "Claude Opus 4.5", Self::ClaudeOpus4_6 => "Claude Opus 4.6", + Self::ClaudeOpus4_7 => "Claude Opus 4.7", Self::ClaudeSonnet4_6 => "Claude Sonnet 4.6", Self::Llama4Scout17B => "Llama 4 Scout 17B", Self::Llama4Maverick17B => "Llama 4 Maverick 17B", @@ -383,6 +395,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 => 200_000, Self::Llama4Scout17B | Self::Llama4Maverick17B => 128_000, Self::Gemma3_4B | Self::Gemma3_12B | Self::Gemma3_27B => 128_000, @@ -416,7 +429,7 @@ impl Model { | Self::ClaudeOpus4_5 | Self::ClaudeSonnet4_6 => 64_000, Self::ClaudeOpus4_1 => 32_000, - Self::ClaudeOpus4_6 => 128_000, + Self::ClaudeOpus4_6 | Self::ClaudeOpus4_7 => 128_000, Self::Llama4Scout17B | Self::Llama4Maverick17B | Self::Gemma3_4B @@ -454,6 +467,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 => 1.0, Self::Custom { default_temperature, @@ -471,6 +485,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 => true, Self::NovaLite | Self::NovaPro | Self::NovaPremier | Self::Nova2Lite => true, Self::MistralLarge3 | Self::PixtralLarge | Self::MagistralSmall => true, @@ -501,6 +516,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 => true, Self::NovaLite | Self::NovaPro => true, Self::PixtralLarge => true, @@ -517,6 +533,7 @@ impl Model { | Self::ClaudeSonnet4_5 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 ) } @@ -529,6 +546,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 => true, Self::Custom { cache_configuration, @@ -545,6 +563,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 => Some(BedrockModelCacheConfiguration { max_cache_anchors: 4, min_total_token: 1024, @@ -570,12 +589,16 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 ) } pub fn supports_adaptive_thinking(&self) -> bool { - matches!(self, Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6) + matches!( + self, + Self::ClaudeOpus4_6 | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 + ) } pub fn thinking_mode(&self) -> BedrockModelMode { @@ -606,6 +629,7 @@ impl Model { | Self::ClaudeSonnet4_5 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 | Self::Nova2Lite ); @@ -665,6 +689,7 @@ impl Model { | Self::ClaudeSonnet4_5 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 | Self::Nova2Lite, "global", @@ -681,6 +706,7 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 | Self::Llama4Scout17B | Self::Llama4Maverick17B @@ -702,6 +728,7 @@ impl Model { | Self::ClaudeSonnet4 | Self::ClaudeSonnet4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6 | Self::NovaLite | Self::NovaPro @@ -714,6 +741,7 @@ impl Model { Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4_5 | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_7 | Self::ClaudeSonnet4_6, "au", ) => Ok(format!("{}.{}", region_group, model_id)), @@ -787,6 +815,10 @@ mod tests { Model::ClaudeOpus4_6.cross_region_inference_id("eu-west-1", false)?, "eu.anthropic.claude-opus-4-6-v1" ); + assert_eq!( + Model::ClaudeOpus4_7.cross_region_inference_id("eu-west-1", false)?, + "eu.anthropic.claude-opus-4-7-v1" + ); Ok(()) } @@ -817,6 +849,10 @@ mod tests { Model::ClaudeOpus4_6.cross_region_inference_id("ap-southeast-2", false)?, "au.anthropic.claude-opus-4-6-v1" ); + assert_eq!( + Model::ClaudeOpus4_7.cross_region_inference_id("ap-southeast-2", false)?, + "au.anthropic.claude-opus-4-7-v1" + ); Ok(()) } @@ -877,6 +913,10 @@ mod tests { Model::ClaudeOpus4_6.cross_region_inference_id("us-east-1", true)?, "global.anthropic.claude-opus-4-6-v1" ); + assert_eq!( + Model::ClaudeOpus4_7.cross_region_inference_id("us-east-1", true)?, + "global.anthropic.claude-opus-4-7-v1" + ); assert_eq!( Model::Nova2Lite.cross_region_inference_id("us-east-1", true)?, "global.amazon.nova-2-lite-v1:0" diff --git a/crates/language_models/src/provider/anthropic.rs b/crates/language_models/src/provider/anthropic.rs index 58de77d573293345ec2120695866c824f10c6108..3d2b763a6e4a97a3a819505a5d81a6e9330fbb9c 100644 --- a/crates/language_models/src/provider/anthropic.rs +++ b/crates/language_models/src/provider/anthropic.rs @@ -326,6 +326,10 @@ impl LanguageModel for AnthropicModel { self.model.supports_thinking() } + fn supports_fast_mode(&self) -> bool { + self.model.supports_speed() + } + fn supported_effort_levels(&self) -> Vec { if self.model.supports_adaptive_thinking() { vec![ @@ -431,13 +435,16 @@ impl LanguageModel for AnthropicModel { LanguageModelCompletionError, >, > { - let request = into_anthropic( + let mut request = into_anthropic( request, self.model.request_id().into(), self.model.default_temperature(), self.model.max_output_tokens(), self.model.mode(), ); + if !self.model.supports_speed() { + request.speed = None; + } let request = self.stream_completion(request, cx); let future = self.request_limiter.stream(async move { let response = request.await?; diff --git a/crates/language_models_cloud/src/language_models_cloud.rs b/crates/language_models_cloud/src/language_models_cloud.rs index 24c8ec87d5c672dbc18b20164f2fe28c9b46b2e1..95b94e146b374f8a5772239086616f3144efce03 100644 --- a/crates/language_models_cloud/src/language_models_cloud.rs +++ b/crates/language_models_cloud/src/language_models_cloud.rs @@ -496,6 +496,10 @@ impl LanguageModel for CloudLanguageModel &str { match self { + Self::ClaudeOpus4_7 => "claude-opus-4-7", Self::ClaudeOpus4_6 => "claude-opus-4-6", Self::ClaudeOpus4_5 => "claude-opus-4-5", Self::ClaudeOpus4_1 => "claude-opus-4-1", @@ -162,6 +165,7 @@ impl Model { pub fn display_name(&self) -> &str { match self { + Self::ClaudeOpus4_7 => "Claude Opus 4.7", Self::ClaudeOpus4_6 => "Claude Opus 4.6", Self::ClaudeOpus4_5 => "Claude Opus 4.5", Self::ClaudeOpus4_1 => "Claude Opus 4.1", @@ -209,7 +213,8 @@ impl Model { pub fn protocol(&self) -> ApiProtocol { match self { - Self::ClaudeOpus4_6 + Self::ClaudeOpus4_7 + | Self::ClaudeOpus4_6 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_1 | Self::ClaudeSonnet4_6 @@ -254,7 +259,7 @@ impl Model { pub fn max_token_count(&self) -> u64 { match self { // Anthropic models - Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6 => 1_000_000, + Self::ClaudeOpus4_7 | Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6 => 1_000_000, Self::ClaudeOpus4_5 | Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4 => 200_000, Self::ClaudeOpus4_1 => 200_000, Self::ClaudeHaiku4_5 => 200_000, @@ -292,7 +297,7 @@ impl Model { pub fn max_output_tokens(&self) -> Option { match self { // Anthropic models - Self::ClaudeOpus4_6 => Some(128_000), + Self::ClaudeOpus4_7 | Self::ClaudeOpus4_6 => Some(128_000), Self::ClaudeSonnet4_6 => Some(64_000), Self::ClaudeOpus4_5 | Self::ClaudeOpus4_1 @@ -342,7 +347,8 @@ impl Model { pub fn supports_images(&self) -> bool { match self { // Anthropic models support images - Self::ClaudeOpus4_6 + Self::ClaudeOpus4_7 + | Self::ClaudeOpus4_6 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_1 | Self::ClaudeSonnet4_6