vtcode_config/models/model_id/
parse.rs1use std::str::FromStr;
2
3use crate::models::ModelParseError;
4
5use super::ModelId;
6
7impl FromStr for ModelId {
8 type Err = ModelParseError;
9
10 fn from_str(s: &str) -> Result<Self, Self::Err> {
11 use crate::constants::models;
12 let trimmed = s.trim();
13
14 if trimmed == models::zai::GLM_5_3 {
15 return Ok(ModelId::ZaiGlm53);
16 }
17
18 if trimmed == models::GPT_5_CODEX {
19 return Ok(ModelId::GPT56Sol);
20 }
21
22 if trimmed == "gpt-5.4" {
23 return Ok(ModelId::GPT56Sol);
24 }
25
26 if let Some(opencode_model) = trimmed
27 .strip_prefix("opencode/")
28 .or_else(|| trimmed.strip_prefix("opencode-zen/"))
29 {
30 return match opencode_model {
31 "gpt-5.4" | "gpt-5.6-sol" => Ok(ModelId::GPT56Sol),
32 _ => Err(ModelParseError::InvalidModel(trimmed.to_string())),
33 };
34 }
35
36 if let Some(opencode_model) = trimmed.strip_prefix("opencode-go/") {
37 return match opencode_model {
38 m if m == models::opencode_go::GLM_5_3 => Ok(ModelId::OpenCodeGoGlm53),
39 m if m == models::opencode_go::GPT_5_6_LUNA => Ok(ModelId::OpenCodeGoGpt56Luna),
40 m if m == models::opencode_go::KIMI_K3 => Ok(ModelId::OpenCodeGoKimiK3),
41 m if m == models::opencode_go::MINIMAX_M3 => Ok(ModelId::OpenCodeGoMinimaxM3),
42 _ => Err(ModelParseError::InvalidModel(trimmed.to_string())),
43 };
44 }
45
46 if let Some(model) = Self::parse_openrouter_model(trimmed) {
47 return Ok(model);
48 }
49
50 if let Some(model) = Self::parse_table(trimmed) {
51 return Ok(model);
52 }
53
54 match trimmed {
55 "moonshotai/kimi-k3" => Ok(ModelId::OpenRouterMoonshotaiKimiK3),
57 _ => {
58 if let Some(model) = Self::parse_openrouter_model(s) {
59 Ok(model)
60 } else {
61 Err(ModelParseError::InvalidModel(s.to_string()))
62 }
63 }
64 }
65 }
66}