From 78a8c559859d227d3fb791f91754e717a3b1c7a4 Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Fri, 19 Dec 2025 11:33:55 -0500 Subject: [PATCH 1/4] Claude 3.7 is out. we had some harcoded stuff --- crates/goose-cli/src/session/output.rs | 7 +- crates/goose/src/providers/anthropic.rs | 4 - .../src/providers/canonical/name_builder.rs | 56 ++------ .../goose/src/providers/formats/anthropic.rs | 59 ++------ .../goose/src/providers/formats/databricks.rs | 2 - .../src/providers/formats/gcpvertexai.rs | 127 ++++-------------- crates/goose/src/providers/openrouter.rs | 4 +- 7 files changed, 45 insertions(+), 214 deletions(-) diff --git a/crates/goose-cli/src/session/output.rs b/crates/goose-cli/src/session/output.rs index 04808ee345bf..39778c69a48f 100644 --- a/crates/goose-cli/src/session/output.rs +++ b/crates/goose-cli/src/session/output.rs @@ -809,10 +809,9 @@ fn normalize_model_name(model: &str) -> String { result = re_date.replace(&result, "").to_string(); } - // Convert version numbers like -3-7- to -3.7- (e.g., claude-3-7-sonnet -> claude-3.7-sonnet) - let re_version = Regex::new(r"-(\d+)-(\d+)-").unwrap(); - if re_version.is_match(&result) { - result = re_version.replace(&result, "-$1.$2-").to_string(); + let re_version_separator_pattern = Regex::new(r"-(\d+)-(\d+)-").unwrap(); + if re_version_separator_pattern.is_match(&result) { + result = re_version_separator_pattern.replace(&result, "-$1.$2-").to_string(); } result diff --git a/crates/goose/src/providers/anthropic.rs b/crates/goose/src/providers/anthropic.rs index cd5be5396c61..5f2976af4e05 100644 --- a/crates/goose/src/providers/anthropic.rs +++ b/crates/goose/src/providers/anthropic.rs @@ -37,10 +37,6 @@ const ANTHROPIC_KNOWN_MODELS: &[&str] = &[ "claude-sonnet-4-20250514", "claude-opus-4-0", "claude-opus-4-20250514", - // Legacy Claude 3.x models - "claude-3-7-sonnet-latest", - "claude-3-7-sonnet-20250219", - "claude-3-opus-latest", ]; const ANTHROPIC_DOC_URL: &str = "https://docs.anthropic.com/en/docs/about-claude/models"; diff --git a/crates/goose/src/providers/canonical/name_builder.rs b/crates/goose/src/providers/canonical/name_builder.rs index c82629ed56c4..6c278e70dae6 100644 --- a/crates/goose/src/providers/canonical/name_builder.rs +++ b/crates/goose/src/providers/canonical/name_builder.rs @@ -333,55 +333,17 @@ mod tests { Some("anthropic/claude-3.5-sonnet".to_string()) ); - // === Claude word-order swapping (3.x series) === - assert_eq!( - map_to_canonical_model("databricks", "claude-haiku-3-5", r), - Some("anthropic/claude-3.5-haiku".to_string()) - ); - assert_eq!( - map_to_canonical_model("databricks", "claude-sonnet-3-7", r), - Some("anthropic/claude-3.7-sonnet".to_string()) - ); - assert_eq!( - map_to_canonical_model("databricks", "ng-tools-claude-haiku-3-5", r), - Some("anthropic/claude-3.5-haiku".to_string()) - ); + // 3.x: {model}-{version} → {version}-{model} + assert_eq!(map_to_canonical_model("databricks", "claude-haiku-3-5", r), + Some("anthropic/claude-3.5-haiku".to_string())); - // === Claude word-order swapping (4.x series) === - assert_eq!( - map_to_canonical_model("databricks", "claude-4-opus", r), - Some("anthropic/claude-opus-4".to_string()) - ); - assert_eq!( - map_to_canonical_model("databricks", "claude-4-sonnet", r), - Some("anthropic/claude-sonnet-4".to_string()) - ); - assert_eq!( - map_to_canonical_model("databricks", "raml-claude-opus-4-5", r), - Some("anthropic/claude-opus-4.5".to_string()) - ); - assert_eq!( - map_to_canonical_model("databricks", "databricks-claude-sonnet-4-5", r), - Some("anthropic/claude-sonnet-4.5".to_string()) - ); + // 4.x: {version}-{model} → {model}-{version} + assert_eq!(map_to_canonical_model("databricks", "claude-4-sonnet", r), + Some("anthropic/claude-sonnet-4".to_string())); - // === Claude with custom prefixes === - assert_eq!( - map_to_canonical_model("databricks", "goose-claude-4-opus", r), - Some("anthropic/claude-opus-4".to_string()) - ); - assert_eq!( - map_to_canonical_model("databricks", "kgoose-claude-4-sonnet", r), - Some("anthropic/claude-sonnet-4".to_string()) - ); - assert_eq!( - map_to_canonical_model("databricks", "headless-goose-claude-4-sonnet", r), - Some("anthropic/claude-sonnet-4".to_string()) - ); - assert_eq!( - map_to_canonical_model("databricks", "kgoose-cashapp-claude-4-sonnet", r), - Some("anthropic/claude-sonnet-4".to_string()) - ); + // 4.x with minor version + prefix stripping + assert_eq!(map_to_canonical_model("databricks", "raml-claude-opus-4-5", r), + Some("anthropic/claude-opus-4.5".to_string())); // === Claude with platform suffixes === assert_eq!( diff --git a/crates/goose/src/providers/formats/anthropic.rs b/crates/goose/src/providers/formats/anthropic.rs index 3771b3adadca..9ade4ad24b70 100644 --- a/crates/goose/src/providers/formats/anthropic.rs +++ b/crates/goose/src/providers/formats/anthropic.rs @@ -394,9 +394,9 @@ pub fn create_request( return Err(anyhow!("No valid messages to send to Anthropic API")); } - // https://docs.anthropic.com/en/docs/about-claude/models/all-models#model-comparison-table - // Claude 3.7 supports max output tokens up to 8192 - let max_tokens = model_config.max_tokens.unwrap_or(8192); + // https://platform.claude.com/docs/en/about-claude/models/overview + // 64k output tokens works for most claude models: + let max_tokens = model_config.max_tokens.unwrap_or(64 * 1024); let mut payload = json!({ "model": model_config.model_name, "messages": anthropic_messages, @@ -421,18 +421,15 @@ pub fn create_request( // Add temperature if specified and not using extended thinking model if let Some(temp) = model_config.temperature { - // Claude 3.7 models with thinking enabled don't support temperature - if !model_config.model_name.starts_with("claude-3-7-sonnet-") { - payload - .as_object_mut() - .unwrap() - .insert("temperature".to_string(), json!(temp)); - } + payload + .as_object_mut() + .unwrap() + .insert("temperature".to_string(), json!(temp)); } // Add thinking parameters for claude-3-7-sonnet model let is_thinking_enabled = std::env::var("CLAUDE_THINKING_ENABLED").is_ok(); - if model_config.model_name.starts_with("claude-3-7-sonnet-") && is_thinking_enabled { + if is_thinking_enabled { // Minimum budget_tokens is 1024 let budget_tokens = std::env::var("CLAUDE_THINKING_BUDGET") .unwrap_or_else(|_| "16000".to_string()) @@ -452,7 +449,6 @@ pub fn create_request( }), ); } - Ok(payload) } @@ -931,45 +927,6 @@ mod tests { assert!(spec_array[0].get("cache_control").is_some()); } - #[test] - fn test_create_request_with_thinking() -> Result<()> { - let original_value = std::env::var("CLAUDE_THINKING_ENABLED").ok(); - std::env::set_var("CLAUDE_THINKING_ENABLED", "true"); - - let result = (|| { - let model_config = ModelConfig::new_or_fail("claude-3-7-sonnet-20250219"); - let system = "You are a helpful assistant."; - let messages = vec![Message::user().with_text("Hello")]; - let tools = vec![]; - - let payload = create_request(&model_config, system, &messages, &tools)?; - - // Verify basic structure - assert_eq!(payload["model"], "claude-3-7-sonnet-20250219"); - assert_eq!(payload["messages"][0]["role"], "user"); - assert_eq!(payload["messages"][0]["content"][0]["text"], "Hello"); - - // Verify thinking parameters - assert!(payload.get("thinking").is_some()); - assert_eq!(payload["thinking"]["type"], "enabled"); - assert!(payload["thinking"]["budget_tokens"].as_i64().unwrap() >= 1024); - - // Temperature should not be present for 3.7 models with thinking - assert!(payload.get("temperature").is_none()); - - Ok(()) - })(); - - // Restore the original env var state - match original_value { - Some(val) => std::env::set_var("CLAUDE_THINKING_ENABLED", val), - None => std::env::remove_var("CLAUDE_THINKING_ENABLED"), - } - - // Return the test result - result - } - #[test] fn test_cache_pricing_calculation() -> Result<()> { // Test realistic cache scenario: small fresh input, large cached content diff --git a/crates/goose/src/providers/formats/databricks.rs b/crates/goose/src/providers/formats/databricks.rs index 8265c5222d63..7c088c66bf74 100644 --- a/crates/goose/src/providers/formats/databricks.rs +++ b/crates/goose/src/providers/formats/databricks.rs @@ -572,7 +572,6 @@ pub fn create_request( .insert("tools".to_string(), json!(tools_spec)); } - // Add thinking parameters for Claude 3.7 Sonnet model when requested let is_thinking_enabled = std::env::var("CLAUDE_THINKING_ENABLED").is_ok(); if is_claude_sonnet && is_thinking_enabled { // Minimum budget_tokens is 1024 @@ -597,7 +596,6 @@ pub fn create_request( }), ); - // Temperature is fixed to 2 when using claude 3.7 thinking with Databricks payload .as_object_mut() .unwrap() diff --git a/crates/goose/src/providers/formats/gcpvertexai.rs b/crates/goose/src/providers/formats/gcpvertexai.rs index 8d60d6018593..b0076771bde3 100644 --- a/crates/goose/src/providers/formats/gcpvertexai.rs +++ b/crates/goose/src/providers/formats/gcpvertexai.rs @@ -58,83 +58,29 @@ pub enum ModelError { UnsupportedLocation(String), } -/// Represents available GCP Vertex AI models for goose. -/// -/// This enum encompasses different model families and their versions -/// that are supported in the GCP Vertex AI platform. #[derive(Debug, Clone, PartialEq, Eq)] pub enum GcpVertexAIModel { - /// Claude model family with specific versions - Claude(ClaudeVersion), - /// Gemini model family with specific versions - Gemini(GeminiVersion), + /// Claude model family + Claude(String), + /// Gemini model family + Gemini(String), /// MaaS (Model as a Service) models from Model Garden /// Contains (publisher, full_model_name) MaaS(String, String), } -/// Represents available versions of the Claude model for goose. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ClaudeVersion { - /// Claude 3.7 Sonnet - Sonnet37, - /// Claude Sonnet 4 - Sonnet4, - /// Claude Opus 4 - Opus4, - /// Generic Claude model for custom or new versions - Generic(String), -} - -/// Represents available versions of the Gemini model for goose. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum GeminiVersion { - /// Gemini 1.5 Pro version - Pro15, - /// Gemini 2.0 Flash version - Flash20, - /// Gemini 2.0 Pro Experimental version - Pro20Exp, - /// Gemini 2.5 Pro Experimental version - Pro25Exp, - /// Gemini 2.5 Flash Preview version - Flash25Preview, - /// Gemini 2.5 Pro Preview version - Pro25Preview, - /// Gemini 2.5 Flash version - Flash25, - /// Gemini 2.5 Pro version - Pro25, - /// Generic Gemini model for custom or new versions - Generic(String), -} impl fmt::Display for GcpVertexAIModel { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let model_id = match self { - Self::Claude(version) => match version { - ClaudeVersion::Sonnet37 => "claude-3-7-sonnet@20250219", - ClaudeVersion::Sonnet4 => "claude-sonnet-4@20250514", - ClaudeVersion::Opus4 => "claude-opus-4@20250514", - ClaudeVersion::Generic(name) => name, - }, - Self::Gemini(version) => match version { - GeminiVersion::Pro15 => "gemini-1.5-pro-002", - GeminiVersion::Flash20 => "gemini-2.0-flash-001", - GeminiVersion::Pro20Exp => "gemini-2.0-pro-exp-02-05", - GeminiVersion::Pro25Exp => "gemini-2.5-pro-exp-03-25", - GeminiVersion::Flash25Preview => "gemini-2.5-flash-preview-05-20", - GeminiVersion::Pro25Preview => "gemini-2.5-pro-preview-05-06", - GeminiVersion::Flash25 => "gemini-2.5-flash", - GeminiVersion::Pro25 => "gemini-2.5-pro", - GeminiVersion::Generic(name) => name, - }, - Self::MaaS(_, model_name) => model_name, - }; - write!(f, "{model_id}") + match self { + Self::Claude(model) => write!(f, "{model}"), + Self::Gemini(model) => write!(f, "{model}"), + Self::MaaS(_, model) => write!(f, "{model}"), + } } } + impl GcpVertexAIModel { /// Returns the default GCP location for the model. /// @@ -155,20 +101,9 @@ impl TryFrom<&str> for GcpVertexAIModel { type Error = ModelError; fn try_from(s: &str) -> Result { - // Known models match s { - "claude-3-7-sonnet@20250219" => Ok(Self::Claude(ClaudeVersion::Sonnet37)), - "claude-sonnet-4@20250514" => Ok(Self::Claude(ClaudeVersion::Sonnet4)), - "claude-opus-4@20250514" => Ok(Self::Claude(ClaudeVersion::Opus4)), - "gemini-1.5-pro-002" => Ok(Self::Gemini(GeminiVersion::Pro15)), - "gemini-2.0-flash-001" => Ok(Self::Gemini(GeminiVersion::Flash20)), - "gemini-2.0-pro-exp-02-05" => Ok(Self::Gemini(GeminiVersion::Pro20Exp)), - "gemini-2.5-pro-exp-03-25" => Ok(Self::Gemini(GeminiVersion::Pro25Exp)), - "gemini-2.5-flash-preview-05-20" => Ok(Self::Gemini(GeminiVersion::Flash25Preview)), - "gemini-2.5-pro-preview-05-06" => Ok(Self::Gemini(GeminiVersion::Pro25Preview)), - "gemini-2.5-flash" => Ok(Self::Gemini(GeminiVersion::Flash25)), - "gemini-2.5-pro" => Ok(Self::Gemini(GeminiVersion::Pro25)), - // MaaS models (Model as a Service from Model Garden) + _ if s.starts_with("claude-") => Ok(Self::Claude(s.to_string())), + _ if s.starts_with("gemini-") => Ok(Self::Gemini(s.to_string())), _ if s.ends_with("-maas") => { let publisher = s .split('-') @@ -177,13 +112,6 @@ impl TryFrom<&str> for GcpVertexAIModel { .to_string(); Ok(Self::MaaS(publisher, s.to_string())) } - // Generic models based on prefix matching - _ if s.starts_with("claude-") => { - Ok(Self::Claude(ClaudeVersion::Generic(s.to_string()))) - } - _ if s.starts_with("gemini-") => { - Ok(Self::Gemini(GeminiVersion::Generic(s.to_string()))) - } _ => Err(ModelError::UnsupportedModel(s.to_string())), } } @@ -429,41 +357,32 @@ mod tests { } #[test] - fn test_generic_model_parsing() -> Result<()> { - // Test generic Claude models + fn test_model_parsing() -> Result<()> { let claude_models = [ - "claude-3-8-apex@20250301", - "claude-new-version", + "claude-3-7-sonnet@20250219", + "claude-sonnet-4@20250514", "claude-experimental", ]; - for model_id in claude_models { let model = GcpVertexAIModel::try_from(model_id)?; - match model { - GcpVertexAIModel::Claude(ClaudeVersion::Generic(ref name)) => { - assert_eq!(name, model_id); - } - _ => panic!("Expected Claude generic model for {model_id}"), - } + assert!(matches!(model, GcpVertexAIModel::Claude(_))); assert_eq!(model.to_string(), model_id); assert_eq!(model.known_location(), GcpLocation::Ohio); } - // Test generic Gemini models - let gemini_models = ["gemini-3-pro", "gemini-2.0-flash", "gemini-experimental"]; - + let gemini_models = [ + "gemini-1.5-pro-002", + "gemini-2.0-flash-001", + "gemini-experimental", + ]; for model_id in gemini_models { let model = GcpVertexAIModel::try_from(model_id)?; - match model { - GcpVertexAIModel::Gemini(GeminiVersion::Generic(ref name)) => { - assert_eq!(name, model_id); - } - _ => panic!("Expected Gemini generic model for {model_id}"), - } + assert!(matches!(model, GcpVertexAIModel::Gemini(_))); assert_eq!(model.to_string(), model_id); assert_eq!(model.known_location(), GcpLocation::Iowa); } + assert!(GcpVertexAIModel::try_from("unsupported-model").is_err()); Ok(()) } } diff --git a/crates/goose/src/providers/openrouter.rs b/crates/goose/src/providers/openrouter.rs index 9869584d1bfb..04067b7f5514 100644 --- a/crates/goose/src/providers/openrouter.rs +++ b/crates/goose/src/providers/openrouter.rs @@ -17,16 +17,16 @@ use crate::providers::formats::openai::{create_request, get_usage, response_to_m use rmcp::model::Tool; pub const OPENROUTER_DEFAULT_MODEL: &str = "anthropic/claude-sonnet-4"; -pub const OPENROUTER_DEFAULT_FAST_MODEL: &str = "google/gemini-flash-2.5"; +pub const OPENROUTER_DEFAULT_FAST_MODEL: &str = "google/gemini-2.5-flash"; pub const OPENROUTER_MODEL_PREFIX_ANTHROPIC: &str = "anthropic"; // OpenRouter can run many models, we suggest the default pub const OPENROUTER_KNOWN_MODELS: &[&str] = &[ + "x-ai/grok-code-fast-1", "anthropic/claude-sonnet-4.5", "anthropic/claude-sonnet-4", "anthropic/claude-opus-4.1", "anthropic/claude-opus-4", - "anthropic/claude-3.7-sonnet", "google/gemini-2.5-pro", "google/gemini-2.5-flash", "deepseek/deepseek-r1-0528", From 474755baf83104b578c1a56b56529680dc1fbe78 Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Mon, 5 Jan 2026 10:30:20 -0500 Subject: [PATCH 2/4] Fix --- .../src/providers/formats/gcpvertexai.rs | 29 ------------------ crates/goose/src/providers/gcpvertexai.rs | 30 +++++++++---------- 2 files changed, 14 insertions(+), 45 deletions(-) diff --git a/crates/goose/src/providers/formats/gcpvertexai.rs b/crates/goose/src/providers/formats/gcpvertexai.rs index b0076771bde3..852b86e195e0 100644 --- a/crates/goose/src/providers/formats/gcpvertexai.rs +++ b/crates/goose/src/providers/formats/gcpvertexai.rs @@ -356,33 +356,4 @@ mod tests { Ok(()) } - #[test] - fn test_model_parsing() -> Result<()> { - let claude_models = [ - "claude-3-7-sonnet@20250219", - "claude-sonnet-4@20250514", - "claude-experimental", - ]; - for model_id in claude_models { - let model = GcpVertexAIModel::try_from(model_id)?; - assert!(matches!(model, GcpVertexAIModel::Claude(_))); - assert_eq!(model.to_string(), model_id); - assert_eq!(model.known_location(), GcpLocation::Ohio); - } - - let gemini_models = [ - "gemini-1.5-pro-002", - "gemini-2.0-flash-001", - "gemini-experimental", - ]; - for model_id in gemini_models { - let model = GcpVertexAIModel::try_from(model_id)?; - assert!(matches!(model, GcpVertexAIModel::Gemini(_))); - assert_eq!(model.to_string(), model_id); - assert_eq!(model.known_location(), GcpLocation::Iowa); - } - - assert!(GcpVertexAIModel::try_from("unsupported-model").is_err()); - Ok(()) - } } diff --git a/crates/goose/src/providers/gcpvertexai.rs b/crates/goose/src/providers/gcpvertexai.rs index bc441b08466d..f9ff84292880 100644 --- a/crates/goose/src/providers/gcpvertexai.rs +++ b/crates/goose/src/providers/gcpvertexai.rs @@ -14,8 +14,8 @@ use crate::providers::base::{ConfigKey, Provider, ProviderMetadata, ProviderUsag use crate::providers::errors::ProviderError; use crate::providers::formats::gcpvertexai::{ - create_request, get_usage, response_to_message, ClaudeVersion, GcpVertexAIModel, GeminiVersion, - ModelProvider, RequestContext, + create_request, get_usage, response_to_message, GcpVertexAIModel, ModelProvider, + RequestContext, }; use crate::providers::formats::gcpvertexai::GcpLocation::Iowa; @@ -440,17 +440,17 @@ impl Provider for GcpVertexAIProvider { Self: Sized, { let model_strings: Vec = vec![ - GcpVertexAIModel::Claude(ClaudeVersion::Sonnet37), - GcpVertexAIModel::Claude(ClaudeVersion::Sonnet4), - GcpVertexAIModel::Claude(ClaudeVersion::Opus4), - GcpVertexAIModel::Gemini(GeminiVersion::Pro15), - GcpVertexAIModel::Gemini(GeminiVersion::Flash20), - GcpVertexAIModel::Gemini(GeminiVersion::Pro20Exp), - GcpVertexAIModel::Gemini(GeminiVersion::Pro25Exp), - GcpVertexAIModel::Gemini(GeminiVersion::Flash25Preview), - GcpVertexAIModel::Gemini(GeminiVersion::Pro25Preview), - GcpVertexAIModel::Gemini(GeminiVersion::Flash25), - GcpVertexAIModel::Gemini(GeminiVersion::Pro25), + GcpVertexAIModel::Claude("claude-3-7-sonnet@20250219".to_string()), + GcpVertexAIModel::Claude("claude-sonnet-4@20250514".to_string()), + GcpVertexAIModel::Claude("claude-opus-4@20250514".to_string()), + GcpVertexAIModel::Gemini("gemini-1.5-pro-002".to_string()), + GcpVertexAIModel::Gemini("gemini-2.0-flash-001".to_string()), + GcpVertexAIModel::Gemini("gemini-2.0-pro-exp-02-05".to_string()), + GcpVertexAIModel::Gemini("gemini-2.5-pro-exp-03-25".to_string()), + GcpVertexAIModel::Gemini("gemini-2.5-flash-preview-05-20".to_string()), + GcpVertexAIModel::Gemini("gemini-2.5-pro-preview-05-06".to_string()), + GcpVertexAIModel::Gemini("gemini-2.5-flash".to_string()), + GcpVertexAIModel::Gemini("gemini-2.5-pro".to_string()), ] .iter() .map(|model| model.to_string()) @@ -462,9 +462,7 @@ impl Provider for GcpVertexAIProvider { "gcp_vertex_ai", "GCP Vertex AI", "Access variety of AI models such as Claude, Gemini through Vertex AI", - GcpVertexAIModel::Gemini(GeminiVersion::Flash25) - .to_string() - .as_str(), + "gemini-2.5-flash", known_models, GCP_VERTEX_AI_DOC_URL, vec![ From d505ad60fa172ff02bf0426fb6ff6df702c29c16 Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Mon, 5 Jan 2026 10:36:59 -0500 Subject: [PATCH 3/4] Cargo Fmt --- .../src/providers/canonical/name_builder.rs | 18 ++++++++++++------ .../goose/src/providers/formats/gcpvertexai.rs | 3 --- crates/goose/src/providers/gcpvertexai.rs | 3 +-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/crates/goose/src/providers/canonical/name_builder.rs b/crates/goose/src/providers/canonical/name_builder.rs index 6c278e70dae6..5765cfcbd82a 100644 --- a/crates/goose/src/providers/canonical/name_builder.rs +++ b/crates/goose/src/providers/canonical/name_builder.rs @@ -334,16 +334,22 @@ mod tests { ); // 3.x: {model}-{version} → {version}-{model} - assert_eq!(map_to_canonical_model("databricks", "claude-haiku-3-5", r), - Some("anthropic/claude-3.5-haiku".to_string())); + assert_eq!( + map_to_canonical_model("databricks", "claude-haiku-3-5", r), + Some("anthropic/claude-3.5-haiku".to_string()) + ); // 4.x: {version}-{model} → {model}-{version} - assert_eq!(map_to_canonical_model("databricks", "claude-4-sonnet", r), - Some("anthropic/claude-sonnet-4".to_string())); + assert_eq!( + map_to_canonical_model("databricks", "claude-4-sonnet", r), + Some("anthropic/claude-sonnet-4".to_string()) + ); // 4.x with minor version + prefix stripping - assert_eq!(map_to_canonical_model("databricks", "raml-claude-opus-4-5", r), - Some("anthropic/claude-opus-4.5".to_string())); + assert_eq!( + map_to_canonical_model("databricks", "raml-claude-opus-4-5", r), + Some("anthropic/claude-opus-4.5".to_string()) + ); // === Claude with platform suffixes === assert_eq!( diff --git a/crates/goose/src/providers/formats/gcpvertexai.rs b/crates/goose/src/providers/formats/gcpvertexai.rs index 852b86e195e0..8dfadbc4e05d 100644 --- a/crates/goose/src/providers/formats/gcpvertexai.rs +++ b/crates/goose/src/providers/formats/gcpvertexai.rs @@ -69,7 +69,6 @@ pub enum GcpVertexAIModel { MaaS(String, String), } - impl fmt::Display for GcpVertexAIModel { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -80,7 +79,6 @@ impl fmt::Display for GcpVertexAIModel { } } - impl GcpVertexAIModel { /// Returns the default GCP location for the model. /// @@ -355,5 +353,4 @@ mod tests { Ok(()) } - } diff --git a/crates/goose/src/providers/gcpvertexai.rs b/crates/goose/src/providers/gcpvertexai.rs index f9ff84292880..85cca278f624 100644 --- a/crates/goose/src/providers/gcpvertexai.rs +++ b/crates/goose/src/providers/gcpvertexai.rs @@ -14,8 +14,7 @@ use crate::providers::base::{ConfigKey, Provider, ProviderMetadata, ProviderUsag use crate::providers::errors::ProviderError; use crate::providers::formats::gcpvertexai::{ - create_request, get_usage, response_to_message, GcpVertexAIModel, ModelProvider, - RequestContext, + create_request, get_usage, response_to_message, GcpVertexAIModel, ModelProvider, RequestContext, }; use crate::providers::formats::gcpvertexai::GcpLocation::Iowa; From 88a71128657bd805a5bf9d624af832d55070e295 Mon Sep 17 00:00:00 2001 From: Douwe Osinga Date: Tue, 6 Jan 2026 14:10:14 -0500 Subject: [PATCH 4/4] 64K is 64000 according to Anthropic! --- crates/goose/src/providers/formats/anthropic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/goose/src/providers/formats/anthropic.rs b/crates/goose/src/providers/formats/anthropic.rs index 9ade4ad24b70..1f80545b25a5 100644 --- a/crates/goose/src/providers/formats/anthropic.rs +++ b/crates/goose/src/providers/formats/anthropic.rs @@ -396,7 +396,7 @@ pub fn create_request( // https://platform.claude.com/docs/en/about-claude/models/overview // 64k output tokens works for most claude models: - let max_tokens = model_config.max_tokens.unwrap_or(64 * 1024); + let max_tokens = model_config.max_tokens.unwrap_or(64000); let mut payload = json!({ "model": model_config.model_name, "messages": anthropic_messages,