Add support for Opus 4.5 (#43425)

Mikayla Maki and Richard Feldman created

Adds support for Opus 4.5
- [x] BYOK
- [x] Amazon Bedrock

Release Notes:

- Added support for Opus 4.5

Co-authored-by: Richard Feldman <oss@rtfeldman.com>

Change summary

crates/anthropic/src/anthropic.rs | 30 +++++++++++++++
crates/bedrock/src/models.rs      | 62 +++++++++++++++++++++++++++-----
2 files changed, 82 insertions(+), 10 deletions(-)

Detailed changes

crates/anthropic/src/anthropic.rs 🔗

@@ -67,6 +67,13 @@ pub enum Model {
         alias = "claude-opus-4-1-thinking-latest"
     )]
     ClaudeOpus4_1Thinking,
+    #[serde(rename = "claude-opus-4-5", alias = "claude-opus-4-5-latest")]
+    ClaudeOpus4_5,
+    #[serde(
+        rename = "claude-opus-4-5-thinking",
+        alias = "claude-opus-4-5-thinking-latest"
+    )]
+    ClaudeOpus4_5Thinking,
     #[serde(rename = "claude-sonnet-4", alias = "claude-sonnet-4-latest")]
     ClaudeSonnet4,
     #[serde(
@@ -131,6 +138,14 @@ impl Model {
     }
 
     pub fn from_id(id: &str) -> Result<Self> {
+        if id.starts_with("claude-opus-4-5-thinking") {
+            return Ok(Self::ClaudeOpus4_5Thinking);
+        }
+
+        if id.starts_with("claude-opus-4-5") {
+            return Ok(Self::ClaudeOpus4_5);
+        }
+
         if id.starts_with("claude-opus-4-1-thinking") {
             return Ok(Self::ClaudeOpus4_1Thinking);
         }
@@ -208,6 +223,8 @@ impl Model {
             Self::ClaudeOpus4_1 => "claude-opus-4-1-latest",
             Self::ClaudeOpus4Thinking => "claude-opus-4-thinking-latest",
             Self::ClaudeOpus4_1Thinking => "claude-opus-4-1-thinking-latest",
+            Self::ClaudeOpus4_5 => "claude-opus-4-5-latest",
+            Self::ClaudeOpus4_5Thinking => "claude-opus-4-5-thinking-latest",
             Self::ClaudeSonnet4 => "claude-sonnet-4-latest",
             Self::ClaudeSonnet4Thinking => "claude-sonnet-4-thinking-latest",
             Self::ClaudeSonnet4_5 => "claude-sonnet-4-5-latest",
@@ -230,6 +247,7 @@ impl Model {
         match self {
             Self::ClaudeOpus4 | Self::ClaudeOpus4Thinking => "claude-opus-4-20250514",
             Self::ClaudeOpus4_1 | Self::ClaudeOpus4_1Thinking => "claude-opus-4-1-20250805",
+            Self::ClaudeOpus4_5 | Self::ClaudeOpus4_5Thinking => "claude-opus-4-5-20251101",
             Self::ClaudeSonnet4 | Self::ClaudeSonnet4Thinking => "claude-sonnet-4-20250514",
             Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4_5Thinking => "claude-sonnet-4-5-20250929",
             Self::Claude3_5Sonnet => "claude-3-5-sonnet-latest",
@@ -249,6 +267,8 @@ impl Model {
             Self::ClaudeOpus4_1 => "Claude Opus 4.1",
             Self::ClaudeOpus4Thinking => "Claude Opus 4 Thinking",
             Self::ClaudeOpus4_1Thinking => "Claude Opus 4.1 Thinking",
+            Self::ClaudeOpus4_5 => "Claude Opus 4.5",
+            Self::ClaudeOpus4_5Thinking => "Claude Opus 4.5 Thinking",
             Self::ClaudeSonnet4 => "Claude Sonnet 4",
             Self::ClaudeSonnet4Thinking => "Claude Sonnet 4 Thinking",
             Self::ClaudeSonnet4_5 => "Claude Sonnet 4.5",
@@ -274,6 +294,8 @@ impl Model {
             | Self::ClaudeOpus4_1
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking
             | Self::ClaudeSonnet4
             | Self::ClaudeSonnet4Thinking
             | Self::ClaudeSonnet4_5
@@ -303,6 +325,8 @@ impl Model {
             | Self::ClaudeOpus4_1
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking
             | Self::ClaudeSonnet4
             | Self::ClaudeSonnet4Thinking
             | Self::ClaudeSonnet4_5
@@ -326,6 +350,8 @@ impl Model {
             | Self::ClaudeOpus4_1
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking
             | Self::ClaudeSonnet4
             | Self::ClaudeSonnet4Thinking
             | Self::ClaudeSonnet4_5
@@ -348,6 +374,8 @@ impl Model {
             | Self::ClaudeOpus4_1
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking
             | Self::ClaudeSonnet4
             | Self::ClaudeSonnet4Thinking
             | Self::ClaudeSonnet4_5
@@ -372,6 +400,7 @@ impl Model {
         match self {
             Self::ClaudeOpus4
             | Self::ClaudeOpus4_1
+            | Self::ClaudeOpus4_5
             | Self::ClaudeSonnet4
             | Self::ClaudeSonnet4_5
             | Self::Claude3_5Sonnet
@@ -383,6 +412,7 @@ impl Model {
             | Self::Claude3Haiku => AnthropicModelMode::Default,
             Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5Thinking
             | Self::ClaudeSonnet4Thinking
             | Self::ClaudeSonnet4_5Thinking
             | Self::ClaudeHaiku4_5Thinking

crates/bedrock/src/models.rs 🔗

@@ -51,6 +51,13 @@ pub enum Model {
         alias = "claude-opus-4-1-thinking-latest"
     )]
     ClaudeOpus4_1Thinking,
+    #[serde(rename = "claude-opus-4-5", alias = "claude-opus-4-5-latest")]
+    ClaudeOpus4_5,
+    #[serde(
+        rename = "claude-opus-4-5-thinking",
+        alias = "claude-opus-4-5-thinking-latest"
+    )]
+    ClaudeOpus4_5Thinking,
     #[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")]
@@ -141,7 +148,19 @@ impl Model {
     }
 
     pub fn from_id(id: &str) -> anyhow::Result<Self> {
-        if id.starts_with("claude-3-5-sonnet-v2") {
+        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)
+        } else if id.starts_with("claude-opus-4-1-thinking") {
+            Ok(Self::ClaudeOpus4_1Thinking)
+        } else if id.starts_with("claude-opus-4-1") {
+            Ok(Self::ClaudeOpus4_1)
+        } else if id.starts_with("claude-opus-4-thinking") {
+            Ok(Self::ClaudeOpus4Thinking)
+        } else if id.starts_with("claude-opus-4") {
+            Ok(Self::ClaudeOpus4)
+        } else if id.starts_with("claude-3-5-sonnet-v2") {
             Ok(Self::Claude3_5SonnetV2)
         } else if id.starts_with("claude-3-opus") {
             Ok(Self::Claude3Opus)
@@ -178,6 +197,8 @@ impl Model {
             Model::ClaudeOpus4_1 => "claude-opus-4-1",
             Model::ClaudeOpus4Thinking => "claude-opus-4-thinking",
             Model::ClaudeOpus4_1Thinking => "claude-opus-4-1-thinking",
+            Model::ClaudeOpus4_5 => "claude-opus-4-5",
+            Model::ClaudeOpus4_5Thinking => "claude-opus-4-5-thinking",
             Model::Claude3_5SonnetV2 => "claude-3-5-sonnet-v2",
             Model::Claude3_5Sonnet => "claude-3-5-sonnet",
             Model::Claude3Opus => "claude-3-opus",
@@ -245,6 +266,9 @@ impl Model {
             Model::ClaudeOpus4_1 | Model::ClaudeOpus4_1Thinking => {
                 "anthropic.claude-opus-4-1-20250805-v1:0"
             }
+            Model::ClaudeOpus4_5 | Model::ClaudeOpus4_5Thinking => {
+                "anthropic.claude-opus-4-5-20251101-v1:0"
+            }
             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",
@@ -309,6 +333,8 @@ impl Model {
             Self::ClaudeOpus4_1 => "Claude Opus 4.1",
             Self::ClaudeOpus4Thinking => "Claude Opus 4 Thinking",
             Self::ClaudeOpus4_1Thinking => "Claude Opus 4.1 Thinking",
+            Self::ClaudeOpus4_5 => "Claude Opus 4.5",
+            Self::ClaudeOpus4_5Thinking => "Claude Opus 4.5 Thinking",
             Self::Claude3_5SonnetV2 => "Claude 3.5 Sonnet v2",
             Self::Claude3_5Sonnet => "Claude 3.5 Sonnet",
             Self::Claude3Opus => "Claude 3 Opus",
@@ -379,7 +405,9 @@ impl Model {
             | Self::ClaudeSonnet4_5
             | Self::ClaudeSonnet4_5Thinking
             | Self::ClaudeOpus4Thinking
-            | Self::ClaudeOpus4_1Thinking => 200_000,
+            | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking => 200_000,
             Self::AmazonNovaPremier => 1_000_000,
             Self::PalmyraWriterX5 => 1_000_000,
             Self::PalmyraWriterX4 => 128_000,
@@ -393,7 +421,11 @@ impl Model {
             Self::Claude3Opus | Self::Claude3Sonnet | Self::Claude3_5Haiku => 4_096,
             Self::Claude3_7Sonnet | Self::Claude3_7SonnetThinking => 128_000,
             Self::ClaudeSonnet4 | Self::ClaudeSonnet4Thinking => 64_000,
-            Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4_5Thinking | Self::ClaudeHaiku4_5 => 64_000,
+            Self::ClaudeSonnet4_5
+            | Self::ClaudeSonnet4_5Thinking
+            | Self::ClaudeHaiku4_5
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking => 64_000,
             Self::ClaudeOpus4
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1
@@ -418,6 +450,8 @@ impl Model {
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1
             | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking
             | Self::ClaudeSonnet4
             | Self::ClaudeSonnet4Thinking
             | Self::ClaudeSonnet4_5
@@ -443,6 +477,8 @@ impl Model {
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1
             | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking
             | Self::ClaudeSonnet4
             | Self::ClaudeSonnet4Thinking
             | Self::ClaudeSonnet4_5
@@ -484,7 +520,9 @@ impl Model {
             | Self::ClaudeOpus4
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1
-            | Self::ClaudeOpus4_1Thinking => true,
+            | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking => true,
 
             // Custom models - check if they have cache configuration
             Self::Custom {
@@ -506,7 +544,9 @@ impl Model {
             | Self::ClaudeOpus4
             | Self::ClaudeOpus4Thinking
             | Self::ClaudeOpus4_1
-            | Self::ClaudeOpus4_1Thinking => Some(BedrockModelCacheConfiguration {
+            | Self::ClaudeOpus4_1Thinking
+            | Self::ClaudeOpus4_5
+            | Self::ClaudeOpus4_5Thinking => Some(BedrockModelCacheConfiguration {
                 max_cache_anchors: 4,
                 min_total_token: 1024,
             }),
@@ -535,11 +575,11 @@ impl Model {
                     budget_tokens: Some(4096),
                 }
             }
-            Model::ClaudeOpus4Thinking | Model::ClaudeOpus4_1Thinking => {
-                BedrockModelMode::Thinking {
-                    budget_tokens: Some(4096),
-                }
-            }
+            Model::ClaudeOpus4Thinking
+            | Model::ClaudeOpus4_1Thinking
+            | Model::ClaudeOpus4_5Thinking => BedrockModelMode::Thinking {
+                budget_tokens: Some(4096),
+            },
             _ => BedrockModelMode::Default,
         }
     }
@@ -593,6 +633,8 @@ impl Model {
                 | Model::ClaudeOpus4Thinking
                 | Model::ClaudeOpus4_1
                 | Model::ClaudeOpus4_1Thinking
+                | Model::ClaudeOpus4_5
+                | Model::ClaudeOpus4_5Thinking
                 | Model::Claude3Haiku
                 | Model::Claude3Opus
                 | Model::Claude3Sonnet