From 1137b3c0f7d6b462b695273a65679a4dec82e418 Mon Sep 17 00:00:00 2001 From: Shardul Vaidya <31039336+5herlocked@users.noreply.github.com> Date: Mon, 9 Feb 2026 04:19:51 -0500 Subject: [PATCH] bedrock: Add Claude Opus 4.6 (#48525) Release Notes: - Added Claude Opus 4.6 and 4.6 Thinking with Cross region inference for US, EU, and Global endpoints. --------- Co-authored-by: Ona --- crates/bedrock/src/bedrock.rs | 49 ++++++++----- crates/bedrock/src/models.rs | 70 +++++++++++++++++-- crates/language_models/Cargo.toml | 2 +- .../language_models/src/provider/bedrock.rs | 19 +++-- crates/zed/Cargo.toml | 2 +- 5 files changed, 116 insertions(+), 26 deletions(-) diff --git a/crates/bedrock/src/bedrock.rs b/crates/bedrock/src/bedrock.rs index 744dde38076a5a12c9bc957a75e2435b1b753d96..2ca39326d30f88f59922aeeb34bca40d3ea79f46 100644 --- a/crates/bedrock/src/bedrock.rs +++ b/crates/bedrock/src/bedrock.rs @@ -39,21 +39,33 @@ pub async fn stream_completion( .model_id(request.model.clone()) .set_messages(request.messages.into()); - if let Some(Thinking::Enabled { - budget_tokens: Some(budget_tokens), - }) = request.thinking - { - let thinking_config = HashMap::from([ - ("type".to_string(), Document::String("enabled".to_string())), - ( - "budget_tokens".to_string(), - Document::Number(AwsNumber::PosInt(budget_tokens)), - ), - ]); - response = response.additional_model_request_fields(Document::Object(HashMap::from([( - "thinking".to_string(), - Document::from(thinking_config), - )]))); + match request.thinking { + Some(Thinking::Enabled { + budget_tokens: Some(budget_tokens), + }) => { + let thinking_config = HashMap::from([ + ("type".to_string(), Document::String("enabled".to_string())), + ( + "budget_tokens".to_string(), + Document::Number(AwsNumber::PosInt(budget_tokens)), + ), + ]); + response = + response.additional_model_request_fields(Document::Object(HashMap::from([( + "thinking".to_string(), + Document::from(thinking_config), + )]))); + } + Some(Thinking::Adaptive { effort: _ }) => { + let thinking_config = + HashMap::from([("type".to_string(), Document::String("adaptive".to_string()))]); + response = + response.additional_model_request_fields(Document::Object(HashMap::from([( + "thinking".to_string(), + Document::from(thinking_config), + )]))); + } + _ => {} } if request.tools.as_ref().is_some_and(|t| !t.tools.is_empty()) { @@ -145,7 +157,12 @@ pub fn value_to_aws_document(value: &Value) -> Document { #[derive(Debug, Serialize, Deserialize)] pub enum Thinking { - Enabled { budget_tokens: Option }, + Enabled { + budget_tokens: Option, + }, + Adaptive { + effort: BedrockAdaptiveThinkingEffort, + }, } #[derive(Debug)] diff --git a/crates/bedrock/src/models.rs b/crates/bedrock/src/models.rs index 51e1b29f9ad3cf953605c5c59090785f3ab45eac..bd3c1e7337743a334312ba0c5cd314a1f7410583 100644 --- a/crates/bedrock/src/models.rs +++ b/crates/bedrock/src/models.rs @@ -1,6 +1,27 @@ use serde::{Deserialize, Serialize}; use strum::EnumIter; +#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq)] +pub enum BedrockAdaptiveThinkingEffort { + Low, + Medium, + #[default] + High, + Max, +} + +impl BedrockAdaptiveThinkingEffort { + pub fn as_str(&self) -> &'static str { + match self { + Self::Low => "low", + Self::Medium => "medium", + Self::High => "high", + Self::Max => "max", + } + } +} + #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)] pub enum BedrockModelMode { @@ -9,6 +30,9 @@ pub enum BedrockModelMode { Thinking { budget_tokens: Option, }, + AdaptiveThinking { + effort: BedrockAdaptiveThinkingEffort, + }, } #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] @@ -58,6 +82,13 @@ pub enum Model { alias = "claude-opus-4-5-thinking-latest" )] ClaudeOpus4_5Thinking, + #[serde(rename = "claude-opus-4-6", alias = "claude-opus-4-6-latest")] + ClaudeOpus4_6, + #[serde( + rename = "claude-opus-4-6-thinking", + alias = "claude-opus-4-6-thinking-latest" + )] + ClaudeOpus4_6Thinking, #[serde(rename = "claude-3-5-sonnet-v2", alias = "claude-3-5-sonnet-latest")] Claude3_5SonnetV2, #[serde(rename = "claude-3-7-sonnet", alias = "claude-3-7-sonnet-latest")] @@ -148,7 +179,11 @@ impl Model { } pub fn from_id(id: &str) -> anyhow::Result { - if id.starts_with("claude-opus-4-5-thinking") { + if id.starts_with("claude-opus-4-6-thinking") { + Ok(Self::ClaudeOpus4_6Thinking) + } else if id.starts_with("claude-opus-4-6") { + Ok(Self::ClaudeOpus4_6) + } else if id.starts_with("claude-opus-4-5-thinking") { Ok(Self::ClaudeOpus4_5Thinking) } else if id.starts_with("claude-opus-4-5") { Ok(Self::ClaudeOpus4_5) @@ -199,6 +234,8 @@ impl Model { Model::ClaudeOpus4_1Thinking => "claude-opus-4-1-thinking", Model::ClaudeOpus4_5 => "claude-opus-4-5", Model::ClaudeOpus4_5Thinking => "claude-opus-4-5-thinking", + Model::ClaudeOpus4_6 => "claude-opus-4-6", + Model::ClaudeOpus4_6Thinking => "claude-opus-4-6-thinking", Model::Claude3_5SonnetV2 => "claude-3-5-sonnet-v2", Model::Claude3_5Sonnet => "claude-3-5-sonnet", Model::Claude3Opus => "claude-3-opus", @@ -269,6 +306,7 @@ impl Model { Model::ClaudeOpus4_5 | Model::ClaudeOpus4_5Thinking => { "anthropic.claude-opus-4-5-20251101-v1:0" } + Model::ClaudeOpus4_6 | Model::ClaudeOpus4_6Thinking => "anthropic.claude-opus-4-6-v1", Model::Claude3_5SonnetV2 => "anthropic.claude-3-5-sonnet-20241022-v2:0", Model::Claude3_5Sonnet => "anthropic.claude-3-5-sonnet-20240620-v1:0", Model::Claude3Opus => "anthropic.claude-3-opus-20240229-v1:0", @@ -335,6 +373,8 @@ impl Model { Self::ClaudeOpus4_1Thinking => "Claude Opus 4.1 Thinking", Self::ClaudeOpus4_5 => "Claude Opus 4.5", Self::ClaudeOpus4_5Thinking => "Claude Opus 4.5 Thinking", + Self::ClaudeOpus4_6 => "Claude Opus 4.6", + Self::ClaudeOpus4_6Thinking => "Claude Opus 4.6 Thinking", Self::Claude3_5SonnetV2 => "Claude 3.5 Sonnet v2", Self::Claude3_5Sonnet => "Claude 3.5 Sonnet", Self::Claude3Opus => "Claude 3 Opus", @@ -407,7 +447,9 @@ impl Model { | Self::ClaudeOpus4Thinking | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking => 200_000, + | Self::ClaudeOpus4_5Thinking + | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_6Thinking => 200_000, Self::AmazonNovaPremier => 1_000_000, Self::PalmyraWriterX5 => 1_000_000, Self::PalmyraWriterX4 => 128_000, @@ -426,6 +468,7 @@ impl Model { | Self::ClaudeHaiku4_5 | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_5Thinking => 64_000, + Self::ClaudeOpus4_6 | Self::ClaudeOpus4_6Thinking => 128_000, Self::ClaudeOpus4 | Self::ClaudeOpus4Thinking | Self::ClaudeOpus4_1 @@ -452,6 +495,8 @@ impl Model { | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_5Thinking + | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_6Thinking | Self::ClaudeSonnet4 | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 @@ -479,6 +524,8 @@ impl Model { | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 | Self::ClaudeOpus4_5Thinking + | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_6Thinking | Self::ClaudeSonnet4 | Self::ClaudeSonnet4Thinking | Self::ClaudeSonnet4_5 @@ -522,7 +569,9 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking => true, + | Self::ClaudeOpus4_5Thinking + | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_6Thinking => true, // Custom models - check if they have cache configuration Self::Custom { @@ -546,7 +595,9 @@ impl Model { | Self::ClaudeOpus4_1 | Self::ClaudeOpus4_1Thinking | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_5Thinking => Some(BedrockModelCacheConfiguration { + | Self::ClaudeOpus4_5Thinking + | Self::ClaudeOpus4_6 + | Self::ClaudeOpus4_6Thinking => Some(BedrockModelCacheConfiguration { max_cache_anchors: 4, min_total_token: 1024, }), @@ -580,6 +631,9 @@ impl Model { | Model::ClaudeOpus4_5Thinking => BedrockModelMode::Thinking { budget_tokens: Some(4096), }, + Model::ClaudeOpus4_6Thinking => BedrockModelMode::AdaptiveThinking { + effort: BedrockAdaptiveThinkingEffort::default(), + }, _ => BedrockModelMode::Default, } } @@ -597,6 +651,8 @@ impl Model { self, Model::ClaudeOpus4_5 | Model::ClaudeOpus4_5Thinking + | Model::ClaudeOpus4_6 + | Model::ClaudeOpus4_6Thinking | Model::ClaudeHaiku4_5 | Model::ClaudeSonnet4 | Model::ClaudeSonnet4Thinking @@ -637,6 +693,8 @@ impl Model { ( Model::ClaudeOpus4_5 | Model::ClaudeOpus4_5Thinking + | Model::ClaudeOpus4_6 + | Model::ClaudeOpus4_6Thinking | Model::ClaudeHaiku4_5 | Model::ClaudeSonnet4 | Model::ClaudeSonnet4Thinking @@ -694,6 +752,8 @@ impl Model { | Model::ClaudeOpus4_1Thinking | Model::ClaudeOpus4_5 | Model::ClaudeOpus4_5Thinking + | Model::ClaudeOpus4_6 + | Model::ClaudeOpus4_6Thinking | Model::Claude3Haiku | Model::Claude3Opus | Model::Claude3Sonnet @@ -728,6 +788,8 @@ impl Model { | Model::ClaudeSonnet4 | Model::ClaudeSonnet4_5 | Model::ClaudeSonnet4_5Thinking + | Model::ClaudeOpus4_6 + | Model::ClaudeOpus4_6Thinking | Model::Claude3Haiku | Model::Claude3Sonnet | Model::MetaLlama321BInstructV1 diff --git a/crates/language_models/Cargo.toml b/crates/language_models/Cargo.toml index ae944f29eb7ab78bec2c3d0575bc641b308e63db..751a568da0b8739c1b83d2afb7c24b7b38ea5773 100644 --- a/crates/language_models/Cargo.toml +++ b/crates/language_models/Cargo.toml @@ -18,7 +18,7 @@ anyhow.workspace = true aws-config = { workspace = true, features = ["behavior-version-latest"] } aws-credential-types = { workspace = true, features = ["hardcoded-credentials"] } aws_http_client.workspace = true -bedrock.workspace = true +bedrock = { workspace = true, features = ["schemars"] } chrono.workspace = true client.workspace = true cloud_api_types.workspace = true diff --git a/crates/language_models/src/provider/bedrock.rs b/crates/language_models/src/provider/bedrock.rs index 98b276bb49b76aa78c7cbd0a21966a5845044209..b10c2789c86024b5eab3d4238754f4e755fe42b0 100644 --- a/crates/language_models/src/provider/bedrock.rs +++ b/crates/language_models/src/provider/bedrock.rs @@ -146,6 +146,9 @@ pub enum ModelMode { /// The maximum number of tokens to use for reasoning. Must be lower than the model's `max_output_tokens`. budget_tokens: Option, }, + AdaptiveThinking { + effort: bedrock::BedrockAdaptiveThinkingEffort, + }, } impl From for BedrockModelMode { @@ -153,6 +156,7 @@ impl From for BedrockModelMode { match value { ModelMode::Default => BedrockModelMode::Default, ModelMode::Thinking { budget_tokens } => BedrockModelMode::Thinking { budget_tokens }, + ModelMode::AdaptiveThinking { effort } => BedrockModelMode::AdaptiveThinking { effort }, } } } @@ -162,6 +166,7 @@ impl From for ModelMode { match value { BedrockModelMode::Default => ModelMode::Default, BedrockModelMode::Thinking { budget_tokens } => ModelMode::Thinking { budget_tokens }, + BedrockModelMode::AdaptiveThinking { effort } => ModelMode::AdaptiveThinking { effort }, } } } @@ -932,10 +937,16 @@ pub fn into_bedrock( max_tokens: max_output_tokens, system: Some(system_message), tools: Some(tool_config), - thinking: if request.thinking_allowed - && let BedrockModelMode::Thinking { budget_tokens } = mode - { - Some(bedrock::Thinking::Enabled { budget_tokens }) + thinking: if request.thinking_allowed { + match mode { + BedrockModelMode::Thinking { budget_tokens } => { + Some(bedrock::Thinking::Enabled { budget_tokens }) + } + BedrockModelMode::AdaptiveThinking { effort } => { + Some(bedrock::Thinking::Adaptive { effort }) + } + BedrockModelMode::Default => None, + } } else { None }, diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 066f52ab6220280d657f7264e21f8d1f4869134f..c4d1beecb2232756be95e451c8ca52db6b09817d 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -261,7 +261,7 @@ agent_ui_v2 = { workspace = true, features = ["test-support"] } search = { workspace = true, features = ["test-support"] } repl = { workspace = true, features = ["test-support"] } -[package.metadata.bundle-dev] +[package.metadata.bundle] icon = ["resources/app-icon-dev@2x.png", "resources/app-icon-dev.png"] identifier = "dev.zed.Zed-Dev" name = "Zed Dev"