From 305849b71709b95b86ed9f11bd3bc939899c0aab Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Mon, 27 Jul 2026 10:37:18 +1000 Subject: [PATCH] chore: opus5 support (including adaptive thinking) (#10686) Co-authored-by: Michael Neale <14976+michaelneale@users.noreply.github.com> --- crates/goose-provider-types/src/canonical.rs | 10 + .../src/canonical/data/canonical_models.json | 659 ++++++++++++++++++ .../src/formats/anthropic.rs | 22 + crates/goose-providers/src/anthropic.rs | 1 + .../goose/src/bin/build_canonical_models.rs | 1 + 5 files changed, 693 insertions(+) diff --git a/crates/goose-provider-types/src/canonical.rs b/crates/goose-provider-types/src/canonical.rs index cb92b606c..5ac718dae 100644 --- a/crates/goose-provider-types/src/canonical.rs +++ b/crates/goose-provider-types/src/canonical.rs @@ -115,4 +115,14 @@ mod tests { assert!(canonical.cost.input.is_some()); assert!(canonical.cost.output.is_some()); } + + #[test] + fn anthropic_opus_5_resolves() { + let canonical = maybe_get_canonical_model("anthropic", "claude-opus-5") + .expect("claude-opus-5 should resolve"); + assert_eq!(canonical.limit.context, 1_000_000); + assert_eq!(canonical.limit.output, Some(128_000)); + assert!(canonical.cost.input.is_some()); + assert!(canonical.cost.output.is_some()); + } } diff --git a/crates/goose-provider-types/src/canonical/data/canonical_models.json b/crates/goose-provider-types/src/canonical/data/canonical_models.json index 988015b11..7f5e02742 100644 --- a/crates/goose-provider-types/src/canonical/data/canonical_models.json +++ b/crates/goose-provider-types/src/canonical/data/canonical_models.json @@ -14161,6 +14161,39 @@ "output": 128000 } }, + { + "id": "amazon-bedrock/anthropic.claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "amazon-bedrock/anthropic.claude-sonnet-4.5-20250929-v1:0", "name": "Claude Sonnet 4.5", @@ -14359,6 +14392,39 @@ "output": 128000 } }, + { + "id": "amazon-bedrock/au.anthropic.claude-opus-5", + "name": "Claude Opus 5 (AU)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "amazon-bedrock/au.anthropic.claude-sonnet-4.5-20250929-v1:0", "name": "Claude Sonnet 4.5 (AU)", @@ -14743,6 +14809,39 @@ "output": 128000 } }, + { + "id": "amazon-bedrock/eu.anthropic.claude-opus-5", + "name": "Claude Opus 5 (EU)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.5, + "output": 27.5, + "cache_read": 0.55, + "cache_write": 6.875 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "amazon-bedrock/eu.anthropic.claude-sonnet-4.5-20250929-v1:0", "name": "Claude Sonnet 4.5 (EU)", @@ -15040,6 +15139,39 @@ "output": 128000 } }, + { + "id": "amazon-bedrock/global.anthropic.claude-opus-5", + "name": "Claude Opus 5 (Global)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "amazon-bedrock/global.anthropic.claude-sonnet-4.5-20250929-v1:0", "name": "Claude Sonnet 4.5 (Global)", @@ -15327,6 +15459,39 @@ "output": 128000 } }, + { + "id": "amazon-bedrock/jp.anthropic.claude-opus-5", + "name": "Claude Opus 5 (JP)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "amazon-bedrock/jp.anthropic.claude-sonnet-4.5-20250929-v1:0", "name": "Claude Sonnet 4.5 (JP)", @@ -16848,6 +17013,39 @@ "output": 128000 } }, + { + "id": "amazon-bedrock/us.anthropic.claude-opus-5", + "name": "Claude Opus 5 (US)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "amazon-bedrock/us.anthropic.claude-sonnet-4.5-20250929-v1:0", "name": "Claude Sonnet 4.5 (US)", @@ -17724,6 +17922,40 @@ "output": 128000 } }, + { + "id": "anthropic/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "thinking_mode": "adaptive", + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "anthropic/claude-sonnet-4.5", "name": "Claude Sonnet 4.5 (latest)", @@ -19433,6 +19665,39 @@ "output": 128000 } }, + { + "id": "azure-cognitive-services/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "azure-cognitive-services/claude-sonnet-4.5", "name": "Claude Sonnet 4.5", @@ -22330,6 +22595,39 @@ "output": 128000 } }, + { + "id": "azure/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "azure/claude-sonnet-4.5", "name": "Claude Sonnet 4.5", @@ -44959,6 +45257,39 @@ "output": 64000 } }, + { + "id": "github-copilot/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 64000 + } + }, { "id": "github-copilot/claude-sonnet-4", "name": "Claude Sonnet 4 (latest)", @@ -48613,6 +48944,39 @@ "output": 128000 } }, + { + "id": "google-vertex-anthropic/claude-opus-5@default", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "google-vertex-anthropic/claude-sonnet-4", "name": "Claude Sonnet 4", @@ -49009,6 +49373,39 @@ "output": 128000 } }, + { + "id": "google-vertex/claude-opus-5@default", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "google-vertex/claude-sonnet-4", "name": "Claude Sonnet 4", @@ -69652,6 +70049,39 @@ "output": 128000 } }, + { + "id": "llmgateway/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "llmgateway/claude-sonnet-4.5", "name": "Claude Sonnet 4.5 (latest)", @@ -110215,6 +110645,39 @@ "output": 128000 } }, + { + "id": "opencode/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "opencode/claude-sonnet-4", "name": "Claude Sonnet 4", @@ -113201,6 +113664,72 @@ "output": 128000 } }, + { + "id": "openrouter/anthropic/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, + { + "id": "openrouter/anthropic/claude-opus-5-fast", + "name": "Claude Opus 5 (Fast)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 10.0, + "output": 50.0, + "cache_read": 1.0, + "cache_write": 12.5 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "openrouter/anthropic/claude-sonnet-4", "name": "Claude Sonnet 4", @@ -146916,6 +147445,70 @@ "output": 128000 } }, + { + "id": "venice/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-23", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 6.0, + "output": 30.0, + "cache_read": 0.6, + "cache_write": 7.5 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, + { + "id": "venice/claude-opus-5-fast", + "name": "Claude Opus 5 Fast", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2026-05", + "release_date": "2026-07-23", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 12.0, + "output": 60.0, + "cache_read": 1.2, + "cache_write": 15.0 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "venice/claude-sonnet-4.5", "name": "Claude Sonnet 4.5", @@ -150800,6 +151393,72 @@ "output": 128000 } }, + { + "id": "vercel/anthropic/claude-opus-5", + "name": "Claude Opus 5", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 5.0, + "output": 25.0, + "cache_read": 0.5, + "cache_write": 6.25 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, + { + "id": "vercel/anthropic/claude-opus-5-fast", + "name": "Claude Opus 5 (Fast)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2026-05", + "release_date": "2026-07-24", + "last_updated": "2026-07-24", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 10.0, + "output": 50.0, + "cache_read": 1.0, + "cache_write": 12.5 + }, + "limit": { + "context": 1000000, + "output": 128000 + } + }, { "id": "vercel/anthropic/claude-sonnet-4", "name": "Claude Sonnet 4", diff --git a/crates/goose-provider-types/src/formats/anthropic.rs b/crates/goose-provider-types/src/formats/anthropic.rs index 5ceb5fe57..d40ccdac0 100644 --- a/crates/goose-provider-types/src/formats/anthropic.rs +++ b/crates/goose-provider-types/src/formats/anthropic.rs @@ -1388,6 +1388,28 @@ mod tests { Ok(()) } + #[test] + fn test_create_request_adaptive_thinking_for_opus_5() -> Result<()> { + // Claude 5 models reject the legacy thinking.type=enabled shape and + // require thinking.type=adaptive + output_config.effort. + let _guard = env_lock::lock_env([("GOOSE_THINKING_EFFORT", None::<&str>)]); + + let mut params = std::collections::HashMap::new(); + params.insert("thinking_effort".to_string(), json!("high")); + + let mut config = cfg("claude-opus-5"); + config.max_tokens = Some(4096); + config.request_params = Some(params); + let messages = vec![Message::user().with_text("Hello")]; + let payload = create_request_with_default_options(&config, "system", &messages, &[])?; + + assert_eq!(payload["thinking"]["type"], "adaptive"); + assert_eq!(payload["output_config"]["effort"], "high"); + assert!(payload["thinking"].get("budget_tokens").is_none()); + + Ok(()) + } + #[test] fn test_create_request_enabled_thinking_with_budget() -> Result<()> { let _guard = env_lock::lock_env([ diff --git a/crates/goose-providers/src/anthropic.rs b/crates/goose-providers/src/anthropic.rs index 04a520616..5c8b0e50b 100644 --- a/crates/goose-providers/src/anthropic.rs +++ b/crates/goose-providers/src/anthropic.rs @@ -28,6 +28,7 @@ use rmcp::model::Tool; pub const ANTHROPIC_DEFAULT_MODEL: &str = "claude-sonnet-4-5"; pub const ANTHROPIC_DEFAULT_FAST_MODEL: &str = "claude-haiku-4-5"; const ANTHROPIC_KNOWN_MODELS: &[&str] = &[ + "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", // Claude 4.6 models diff --git a/crates/goose/src/bin/build_canonical_models.rs b/crates/goose/src/bin/build_canonical_models.rs index a14034c7b..4419c4b09 100644 --- a/crates/goose/src/bin/build_canonical_models.rs +++ b/crates/goose/src/bin/build_canonical_models.rs @@ -357,6 +357,7 @@ fn get_thinking_mode(canonical_id: &str, value: &Value) -> Option fn inferred_thinking_mode(canonical_id: &str) -> Option { match canonical_id { "anthropic/claude-fable-5" => Some(ThinkingMode::AlwaysOnAdaptive), + "anthropic/claude-opus-5" => Some(ThinkingMode::Adaptive), "anthropic/claude-opus-4.6" => Some(ThinkingMode::Adaptive), "anthropic/claude-opus-4.7" => Some(ThinkingMode::Adaptive), "anthropic/claude-opus-4.8" => Some(ThinkingMode::Adaptive),