From fa08991e16967c2fb813517d97a0f9e9c66e2129 Mon Sep 17 00:00:00 2001 From: rabi Date: Fri, 30 Jan 2026 14:51:47 +0530 Subject: [PATCH] fix(canonical): handle gcp_vertex_ai model mapping correctly GCP Vertex AI hosts both Google and third-party models. - Handle Vertex AI @DATE suffix format (e.g., claude-opus-4-5@20251101) - Fix version normalization regex to handle @ separator Regression from e2a18c932 caused Claude models to not appear in Vertex AI model list during provider configuration. Signed-off-by: rabi --- .../canonical/data/canonical_models.json | 438 +++++++++++++++++- .../src/providers/canonical/name_builder.rs | 52 ++- 2 files changed, 474 insertions(+), 16 deletions(-) diff --git a/crates/goose/src/providers/canonical/data/canonical_models.json b/crates/goose/src/providers/canonical/data/canonical_models.json index f99c6a9b8aca..6a970a541c8d 100644 --- a/crates/goose/src/providers/canonical/data/canonical_models.json +++ b/crates/goose/src/providers/canonical/data/canonical_models.json @@ -654,6 +654,39 @@ "output": 64000 } }, + { + "id": "amazon-bedrock/anthropic.claude-opus-4.6-v1", + "name": "Claude Opus 4.6", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2025-05", + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "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-20250514-v1:0", "name": "Claude Sonnet 4", @@ -1010,14 +1043,47 @@ "cost": { "input": 5.0, "output": 25.0, - "cache_read": 1.5, - "cache_write": 18.75 + "cache_read": 0.5, + "cache_write": 6.25 }, "limit": { "context": 200000, "output": 64000 } }, + { + "id": "amazon-bedrock/eu.anthropic.claude-opus-4.6-v1", + "name": "Claude Opus 4.6 (EU)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2025-05", + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "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/eu.anthropic.claude-sonnet-4-20250514-v1:0", "name": "Claude Sonnet 4 (EU)", @@ -1150,6 +1216,39 @@ "output": 64000 } }, + { + "id": "amazon-bedrock/global.anthropic.claude-opus-4.6-v1", + "name": "Claude Opus 4.6 (Global)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2025-05", + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "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-20250514-v1:0", "name": "Claude Sonnet 4 (Global)", @@ -1238,8 +1337,8 @@ }, "open_weights": false, "cost": { - "input": 0.05, - "output": 0.1 + "input": 0.049999999999999996, + "output": 0.09999999999999999 }, "limit": { "context": 131072, @@ -2347,14 +2446,47 @@ "cost": { "input": 5.0, "output": 25.0, - "cache_read": 1.5, - "cache_write": 18.75 + "cache_read": 0.5, + "cache_write": 6.25 }, "limit": { "context": 200000, "output": 64000 } }, + { + "id": "amazon-bedrock/us.anthropic.claude-opus-4.6-v1", + "name": "Claude Opus 4.6 (US)", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2025-05", + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "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-20250514-v1:0", "name": "Claude Sonnet 4 (US)", @@ -2784,6 +2916,39 @@ "output": 64000 } }, + { + "id": "anthropic/claude-opus-4.6", + "name": "Claude Opus 4.6", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2025-05", + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "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": 200000, + "output": 128000 + } + }, { "id": "anthropic/claude-sonnet-4", "name": "Claude Sonnet 4", @@ -2982,6 +3147,39 @@ "output": 64000 } }, + { + "id": "azure/claude-opus-4.6", + "name": "Claude Opus 4.6", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2025-05", + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "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": 200000, + "output": 128000 + } + }, { "id": "azure/claude-sonnet-4.5", "name": "Claude Sonnet 4.5", @@ -4376,6 +4574,36 @@ "output": 262144 } }, + { + "id": "azure/kimi-k2.5", + "name": "Kimi K2.5", + "family": "kimi", + "attachment": false, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2025-01", + "release_date": "2026-02-06", + "last_updated": "2026-02-06", + "modalities": { + "input": [ + "text", + "image" + ], + "output": [ + "text" + ] + }, + "open_weights": true, + "cost": { + "input": 0.6, + "output": 3.0 + }, + "limit": { + "context": 262144, + "output": 262144 + } + }, { "id": "azure/llama-3.2-11b-vision-instruct", "name": "Llama-3.2-11B-Vision-Instruct", @@ -8767,6 +8995,38 @@ "output": 128000 } }, + { + "id": "openai/gpt-5.3-codex", + "name": "GPT-5.3 Codex", + "family": "gpt-codex", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": false, + "knowledge": "2025-08-31", + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "modalities": { + "input": [ + "text", + "image", + "pdf" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 1.75, + "output": 14.0, + "cache_read": 0.175 + }, + "limit": { + "context": 400000, + "output": 128000 + } + }, { "id": "openai/o1", "name": "o1", @@ -9165,7 +9425,7 @@ "family": "allenai", "attachment": false, "reasoning": true, - "tool_call": true, + "tool_call": false, "temperature": true, "knowledge": "2025-06", "release_date": "2026-01-09", @@ -9388,6 +9648,39 @@ "output": 32000 } }, + { + "id": "openrouter/anthropic/claude-opus-4.6", + "name": "Claude Opus 4.6", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2025-05-30", + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "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-sonnet-4", "name": "Claude Sonnet 4", @@ -9673,7 +9966,7 @@ "family": "mistral", "attachment": false, "reasoning": false, - "tool_call": true, + "tool_call": false, "temperature": true, "knowledge": "2025-06", "release_date": "2025-07-09", @@ -10831,7 +11124,7 @@ "family": "liquid", "attachment": false, "reasoning": false, - "tool_call": true, + "tool_call": false, "temperature": true, "knowledge": "2025-06", "release_date": "2026-01-20", @@ -10860,7 +11153,7 @@ "family": "liquid", "attachment": false, "reasoning": true, - "tool_call": true, + "tool_call": false, "temperature": true, "knowledge": "2025-06", "release_date": "2026-01-20", @@ -10889,7 +11182,7 @@ "family": "llama", "attachment": true, "reasoning": false, - "tool_call": true, + "tool_call": false, "temperature": true, "knowledge": "2024-08", "release_date": "2024-07-23", @@ -10948,7 +11241,7 @@ "family": "llama", "attachment": true, "reasoning": false, - "tool_call": true, + "tool_call": false, "temperature": true, "knowledge": "2023-12", "release_date": "2024-09-25", @@ -11770,7 +12063,7 @@ "family": "hermes", "attachment": false, "reasoning": true, - "tool_call": true, + "tool_call": false, "temperature": true, "knowledge": "2023-12", "release_date": "2024-08-16", @@ -12752,6 +13045,34 @@ "output": 100000 } }, + { + "id": "openrouter/openrouter/pony-alpha", + "name": "Pony Alpha", + "family": "pony", + "attachment": false, + "reasoning": true, + "tool_call": true, + "temperature": true, + "release_date": "2026-02-06", + "last_updated": "2026-02-06", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "open_weights": false, + "cost": { + "input": 0.0, + "output": 0.0 + }, + "limit": { + "context": 200000, + "output": 131000 + } + }, { "id": "openrouter/openrouter/sherlock-dash-alpha", "name": "Sherlock Dash Alpha", @@ -13782,7 +14103,7 @@ "family": "tngtech", "attachment": false, "reasoning": true, - "tool_call": false, + "tool_call": true, "temperature": true, "knowledge": "2025-07", "release_date": "2025-11-26", @@ -14054,6 +14375,36 @@ "output": 10000 } }, + { + "id": "openrouter/xiaomi/mimo-v2-flash", + "name": "MiMo-V2-Flash", + "family": "mimo", + "attachment": false, + "reasoning": true, + "tool_call": true, + "temperature": true, + "knowledge": "2024-12", + "release_date": "2025-12-14", + "last_updated": "2025-12-14", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "open_weights": true, + "cost": { + "input": 0.1, + "output": 0.3, + "cache_read": 0.01 + }, + "limit": { + "context": 262144, + "output": 65536 + } + }, { "id": "openrouter/z-ai/glm-4.5", "name": "GLM 4.5", @@ -14290,6 +14641,37 @@ "output": 65535 } }, + { + "id": "venice/claude-opus-4.6", + "name": "Claude Opus 4.6", + "family": "claude-opus", + "attachment": true, + "reasoning": true, + "tool_call": true, + "temperature": true, + "release_date": "2026-02-05", + "last_updated": "2026-02-05", + "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-45", "name": "Claude Opus 4.5", @@ -15072,6 +15454,34 @@ "output": 49500 } }, + { + "id": "venice/zai-org-glm-4.7-flash", + "name": "GLM 4.7 Flash", + "family": "glm-flash", + "attachment": false, + "reasoning": false, + "tool_call": true, + "temperature": true, + "release_date": "2026-01-29", + "last_updated": "2026-01-30", + "modalities": { + "input": [ + "text" + ], + "output": [ + "text" + ] + }, + "open_weights": true, + "cost": { + "input": 0.125, + "output": 0.5 + }, + "limit": { + "context": 128000, + "output": 32000 + } + }, { "id": "x-ai/grok-2", "name": "Grok 2 (1212)", diff --git a/crates/goose/src/providers/canonical/name_builder.rs b/crates/goose/src/providers/canonical/name_builder.rs index 93bc7668752d..afa7a5b2f899 100644 --- a/crates/goose/src/providers/canonical/name_builder.rs +++ b/crates/goose/src/providers/canonical/name_builder.rs @@ -2,12 +2,13 @@ use once_cell::sync::Lazy; use regex::Regex; // Patterns for normalizing version numbers and stripping suffixes -static NORMALIZE_VERSION_RE: Lazy = Lazy::new(|| Regex::new(r"-(\d)-(\d)(-|$)").unwrap()); +static NORMALIZE_VERSION_RE: Lazy = Lazy::new(|| Regex::new(r"-(\d)-(\d)(-|@|$)").unwrap()); static STRIP_PATTERNS: Lazy> = Lazy::new(|| { vec![ Regex::new(r"-latest$").unwrap(), Regex::new(r"-\d{8}$").unwrap(), + Regex::new(r"@\d{8}$").unwrap(), Regex::new(r"-\d{4}$").unwrap(), Regex::new(r"-\d{4}-\d{2}-\d{2}$").unwrap(), Regex::new(r"-bedrock$").unwrap(), @@ -57,8 +58,21 @@ pub fn map_to_canonical_model( ) -> Option { let registry_provider = map_provider_name(provider); + if provider == "gcp_vertex_ai" { + let normalized_model = strip_version_suffix(model); + if let Some(canonical) = registry.get(registry_provider, &normalized_model) { + return Some(canonical.id.clone()); + } + if let Some(canonical) = registry.get(registry_provider, model) { + return Some(canonical.id.clone()); + } + if model.starts_with("gemini-") { + return None; + } + } + // For normal providers (anthropic, openai, google, openrouter, etc.), just do direct lookup - if !is_meta_provider(provider) { + if !is_meta_provider(provider) && provider != "gcp_vertex_ai" { let normalized_model = strip_version_suffix(model); if let Some(canonical) = registry.get(registry_provider, &normalized_model) { return Some(canonical.id.clone()); @@ -474,5 +488,39 @@ mod tests { map_to_canonical_model("databricks", "x-ai-grok-3", r), Some("x-ai/grok-3".to_string()) ); + + // === GCP Vertex AI === + assert_eq!( + map_to_canonical_model("gcp_vertex_ai", "gemini-2.5-flash", r), + Some("google-vertex/gemini-2.5-flash".to_string()) + ); + assert_eq!( + map_to_canonical_model("gcp_vertex_ai", "gemini-2.5-pro", r), + Some("google-vertex/gemini-2.5-pro".to_string()) + ); + assert_eq!( + map_to_canonical_model("gcp_vertex_ai", "claude-3-5-sonnet", r), + Some("anthropic/claude-3.5-sonnet".to_string()) + ); + assert_eq!( + map_to_canonical_model("gcp_vertex_ai", "claude-sonnet-4@20250514", r), + Some("anthropic/claude-sonnet-4".to_string()) + ); + assert_eq!( + map_to_canonical_model("gcp_vertex_ai", "claude-3-5-haiku@20241022", r), + Some("anthropic/claude-3.5-haiku".to_string()) + ); + assert_eq!( + map_to_canonical_model("gcp_vertex_ai", "claude-sonnet-4-5@20250929", r), + Some("anthropic/claude-sonnet-4.5".to_string()) + ); + assert_eq!( + map_to_canonical_model("gcp_vertex_ai", "claude-opus-4-5@20251101", r), + Some("anthropic/claude-opus-4.5".to_string()) + ); + assert_eq!( + map_to_canonical_model("gcp_vertex_ai", "claude-haiku-4-5@20251001", r), + Some("anthropic/claude-haiku-4.5".to_string()) + ); } }