| 1 | //! OpenCode Go's provider-owned transport roster. |
| 2 | //! |
| 3 | //! Reviewed against <https://opencode.ai/docs/go/#endpoints> on 2026-09-12. |
| 4 | //! Previously accepted Chat ids remain compatible absent explicit deprecation. |
| 5 | //! Membership proves a wire protocol, not live availability, limits or pricing. |
| 6 | |
| 7 | pub(crate) const MODEL_GROUPS: &[(&str, &[&str])] = &[ |
| 8 | ( |
| 9 | "chat", |
| 10 | &[ |
| 11 | crate::DEFAULT_OPENCODE_GO_MODEL, |
| 12 | crate::OPENCODE_GO_GROK_4_5_MODEL, |
| 13 | crate::OPENCODE_GO_GLM_5_2_MODEL, |
| 14 | crate::OPENCODE_GO_GLM_5_1_MODEL, |
| 15 | crate::OPENCODE_GO_KIMI_K3_MODEL, |
| 16 | crate::OPENCODE_GO_KIMI_K2_7_CODE_MODEL, |
| 17 | crate::OPENCODE_GO_KIMI_K2_6_MODEL, |
| 18 | crate::OPENCODE_GO_DEEPSEEK_V4_FLASH_MODEL, |
| 19 | crate::OPENCODE_GO_MIMO_V2_5_MODEL, |
| 20 | crate::OPENCODE_GO_MIMO_V2_5_PRO_MODEL, |
| 21 | "glm-5.3-flash", |
| 22 | "glm-5.3", |
| 23 | "longcat-2.0", |
| 24 | "deepseek-v4-flash-vision-exp", |
| 25 | "hy4-preview", |
| 26 | "hy3", |
| 27 | "omen-alpha", |
| 28 | "deepseek-v4.1-flash", |
| 29 | ], |
| 30 | ), |
| 31 | ( |
| 32 | "responses", |
| 33 | &[ |
| 34 | "grok-4.6", |
| 35 | "gpt-5.6-luna", |
| 36 | "muse-spark-1.3-contributor", |
| 37 | "muse-spark-1.2-contributor", |
| 38 | ], |
| 39 | ), |
| 40 | ( |
| 41 | "messages", |
| 42 | &[ |
| 43 | "minimax-m3", |
| 44 | "minimax-m2.7", |
| 45 | "minimax-m2.5", |
| 46 | "qwen3.8-max", |
| 47 | "qwen3.8-flash", |
| 48 | "qwen3.7-max", |
| 49 | "qwen3.7-plus", |
| 50 | "qwen3.6-plus", |
| 51 | ], |
| 52 | ), |
| 53 | ]; |
| 54 | |
| 55 | /// Every documented Go wire id, in stable picker order. |
| 56 | #[must_use] |
| 57 | pub fn opencode_go_models() -> Vec<&'static str> { |
| 58 | MODEL_GROUPS |
| 59 | .iter() |
| 60 | .flat_map(|(_, models)| models.iter().copied()) |
| 61 | .collect() |
| 62 | } |
| 63 | |
| 64 | /// Canonicalize only IDs whose Go protocol is known. Unknown models cannot |
| 65 | /// silently fall through to Chat, another provider, or the default model. |
| 66 | #[must_use] |
| 67 | pub fn opencode_go_model_id(model: &str) -> Option<&'static str> { |
| 68 | let normalized = model.trim().to_ascii_lowercase().replace(['_', ' '], "-"); |
| 69 | let normalized = normalized |
| 70 | .strip_prefix("opencode-go/") |
| 71 | .unwrap_or(&normalized); |
| 72 | let normalized = match normalized { |
| 73 | "grok-4-5" => "grok-4.5", |
| 74 | "glm-5-2" => "glm-5.2", |
| 75 | "glm-5-1" => "glm-5.1", |
| 76 | "kimi-k2-7-code" => "kimi-k2.7-code", |
| 77 | "kimi-k2-6" => "kimi-k2.6", |
| 78 | "deepseek-v4pro" => "deepseek-v4-pro", |
| 79 | "deepseek-v4flash" => "deepseek-v4-flash", |
| 80 | "mimo-v2-5" => "mimo-v2.5", |
| 81 | "mimo-v2-5-pro" => "mimo-v2.5-pro", |
| 82 | other => other, |
| 83 | }; |
| 84 | MODEL_GROUPS |
| 85 | .iter() |
| 86 | .flat_map(|(_, models)| models.iter().copied()) |
| 87 | .find(|candidate| *candidate == normalized) |
| 88 | } |
| 89 | |
| 90 | /// The documented endpoint for a Go model, independent of stale catalog metadata. |
| 91 | #[must_use] |
| 92 | pub fn opencode_go_endpoint_key(model: &str) -> Option<&'static str> { |
| 93 | let canonical = opencode_go_model_id(model)?; |
| 94 | MODEL_GROUPS |
| 95 | .iter() |
| 96 | .find_map(|(endpoint, models)| models.contains(&canonical).then_some(*endpoint)) |
| 97 | } |
| 98 |