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
13 if s == models::zai::GLM_5 || s == models::zai::GLM_5_LEGACY {
15 return Ok(ModelId::ZaiGlm5);
16 }
17
18 if let Some(model) = Self::parse_openrouter_model(s) {
19 return Ok(model);
20 }
21
22 match s {
23 s if s == models::GEMINI_3_1_PRO_PREVIEW => Ok(ModelId::Gemini31ProPreview),
25 s if s == models::GEMINI_3_1_PRO_PREVIEW_CUSTOMTOOLS => {
26 Ok(ModelId::Gemini31ProPreviewCustomTools)
27 }
28 s if s == models::GEMINI_3_PRO_PREVIEW => Ok(ModelId::Gemini3ProPreview),
29 s if s == models::GEMINI_3_FLASH_PREVIEW => Ok(ModelId::Gemini3FlashPreview),
30 s if s == models::GPT_5 => Ok(ModelId::GPT5),
32 s if s == models::openai::GPT_5_2 => Ok(ModelId::GPT52),
33 s if s == models::openai::GPT_5_2_ALIAS => Ok(ModelId::GPT52),
34 s if s == models::openai::GPT_5_2_CODEX => Ok(ModelId::GPT52Codex),
35 s if s == models::GPT_5_CODEX => Ok(ModelId::GPT5Codex),
36 s if s == models::GPT_5_MINI => Ok(ModelId::GPT5Mini),
37 s if s == models::GPT_5_NANO => Ok(ModelId::GPT5Nano),
38 s if s == models::openai::GPT_5_1 => Ok(ModelId::GPT51),
39 s if s == models::openai::GPT_5_1_CODEX => Ok(ModelId::GPT51Codex),
40 s if s == models::openai::GPT_5_1_CODEX_MAX => Ok(ModelId::GPT51CodexMax),
41 s if s == models::openai::GPT_5_1_MINI => Ok(ModelId::GPT51Mini),
42 s if s == models::CODEX_MINI_LATEST => Ok(ModelId::CodexMiniLatest),
43 s if s == models::openai::GPT_OSS_20B => Ok(ModelId::OpenAIGptOss20b),
44 s if s == models::openai::GPT_OSS_120B => Ok(ModelId::OpenAIGptOss120b),
45 s if s == models::CLAUDE_OPUS_4_6 => Ok(ModelId::ClaudeOpus46),
47 s if s == models::CLAUDE_SONNET_4_6 => Ok(ModelId::ClaudeSonnet46),
48 s if s == models::CLAUDE_OPUS_4_1_20250805 => Ok(ModelId::ClaudeOpus41),
49 s if s == models::CLAUDE_OPUS_4_1 => Ok(ModelId::ClaudeOpus41),
50 s if s == models::CLAUDE_OPUS_4_5_20251101 => Ok(ModelId::ClaudeOpus45),
51 s if s == models::CLAUDE_OPUS_4_5 => Ok(ModelId::ClaudeOpus45),
52 s if s == models::CLAUDE_SONNET_4_5 => Ok(ModelId::ClaudeSonnet45),
53 s if s == models::CLAUDE_HAIKU_4_5 => Ok(ModelId::ClaudeHaiku45),
54 s if s == models::CLAUDE_SONNET_4_5_20250929 => Ok(ModelId::ClaudeSonnet45),
55 s if s == models::CLAUDE_SONNET_4_20250514 => Ok(ModelId::ClaudeSonnet4),
56 s if s == models::CLAUDE_SONNET_4_0 => Ok(ModelId::ClaudeSonnet4),
57 s if s == models::CLAUDE_OPUS_4_20250514 => Ok(ModelId::ClaudeOpus4),
58 s if s == models::CLAUDE_OPUS_4_0 => Ok(ModelId::ClaudeOpus4),
59 s if s == models::CLAUDE_3_7_SONNET_20250219 => Ok(ModelId::ClaudeSonnet37),
60 s if s == models::CLAUDE_3_7_SONNET_LATEST => Ok(ModelId::ClaudeSonnet37),
61 s if s == models::CLAUDE_3_5_HAIKU_20241022 => Ok(ModelId::ClaudeHaiku35),
62 s if s == models::CLAUDE_3_5_HAIKU_LATEST => Ok(ModelId::ClaudeHaiku35),
63 s if s == models::DEEPSEEK_CHAT => Ok(ModelId::DeepSeekChat),
65 s if s == models::DEEPSEEK_REASONER => Ok(ModelId::DeepSeekReasoner),
66 s if s == models::xai::GROK_4 => Ok(ModelId::XaiGrok4),
68 s if s == models::xai::GROK_4_MINI => Ok(ModelId::XaiGrok4Mini),
69 s if s == models::xai::GROK_4_CODE => Ok(ModelId::XaiGrok4Code),
70 s if s == models::xai::GROK_4_CODE_LATEST => Ok(ModelId::XaiGrok4CodeLatest),
71 s if s == models::xai::GROK_4_VISION => Ok(ModelId::XaiGrok4Vision),
72 s if s == models::zai::GLM_5 || s == models::zai::GLM_5_LEGACY => {
74 Ok(ModelId::ZaiGlm5)
75 }
76 s if s == models::moonshot::MINIMAX_M2_5 => Ok(ModelId::MoonshotMinimaxM25),
78 s if s == models::moonshot::QWEN3_CODER_NEXT => Ok(ModelId::MoonshotQwen3CoderNext),
79 s if s == models::ollama::GPT_OSS_20B => Ok(ModelId::OllamaGptOss20b),
80 s if s == models::ollama::GPT_OSS_20B_CLOUD => Ok(ModelId::OllamaGptOss20bCloud),
81 s if s == models::ollama::GPT_OSS_120B_CLOUD => Ok(ModelId::OllamaGptOss120bCloud),
82 s if s == models::ollama::QWEN3_1_7B => Ok(ModelId::OllamaQwen317b),
83 s if s == models::ollama::DEEPSEEK_V32_CLOUD => Ok(ModelId::OllamaDeepseekV32Cloud),
84 s if s == models::ollama::QWEN3_NEXT_80B_CLOUD => Ok(ModelId::OllamaQwen3Next80bCloud),
85 s if s == models::ollama::MISTRAL_LARGE_3_675B_CLOUD => {
86 Ok(ModelId::OllamaMistralLarge3675bCloud)
87 }
88 s if s == models::ollama::QWEN3_CODER_480B_CLOUD => {
89 Ok(ModelId::OllamaQwen3Coder480bCloud)
90 }
91 s if s == models::ollama::GLM_5_CLOUD => Ok(ModelId::OllamaGlm5Cloud),
92 s if s == models::ollama::GEMINI_3_PRO_PREVIEW_LATEST_CLOUD => {
93 Ok(ModelId::OllamaGemini3ProPreviewLatestCloud)
94 }
95 s if s == models::ollama::GEMINI_3_FLASH_PREVIEW_CLOUD => {
96 Ok(ModelId::OllamaGemini3FlashPreviewCloud)
97 }
98 s if s == models::ollama::MINIMAX_M2_CLOUD => Ok(ModelId::OllamaMinimaxM2Cloud),
99 s if s == models::ollama::MINIMAX_M25_CLOUD => Ok(ModelId::OllamaMinimaxM25Cloud),
100 s if s == models::ollama::DEVSTRAL_2_123B_CLOUD => {
101 Ok(ModelId::OllamaDevstral2123bCloud)
102 }
103 s if s == models::ollama::NEMOTRON_3_NANO_30B_CLOUD => {
104 Ok(ModelId::OllamaNemotron3Nano30bCloud)
105 }
106 s if s == models::lmstudio::META_LLAMA_3_8B_INSTRUCT => {
107 Ok(ModelId::LmStudioMetaLlama38BInstruct)
108 }
109 s if s == models::lmstudio::META_LLAMA_31_8B_INSTRUCT => {
110 Ok(ModelId::LmStudioMetaLlama318BInstruct)
111 }
112 s if s == models::lmstudio::QWEN25_7B_INSTRUCT => Ok(ModelId::LmStudioQwen257BInstruct),
113 s if s == models::lmstudio::GEMMA_2_2B_IT => Ok(ModelId::LmStudioGemma22BIt),
114 s if s == models::lmstudio::GEMMA_2_9B_IT => Ok(ModelId::LmStudioGemma29BIt),
115 s if s == models::lmstudio::PHI_31_MINI_4K_INSTRUCT => {
116 Ok(ModelId::LmStudioPhi31Mini4kInstruct)
117 }
118 s if s == models::minimax::MINIMAX_M2_5 => Ok(ModelId::MinimaxM25),
119 s if s == models::minimax::MINIMAX_M2 => Ok(ModelId::MinimaxM2),
120 s if s == models::huggingface::DEEPSEEK_V32 => Ok(ModelId::HuggingFaceDeepseekV32),
122 s if s == models::huggingface::OPENAI_GPT_OSS_20B => {
123 Ok(ModelId::HuggingFaceOpenAIGptOss20b)
124 }
125 s if s == models::huggingface::OPENAI_GPT_OSS_120B => {
126 Ok(ModelId::HuggingFaceOpenAIGptOss120b)
127 }
128 s if s == models::huggingface::MINIMAX_M2_5_NOVITA => {
129 Ok(ModelId::HuggingFaceMinimaxM25Novita)
130 }
131 s if s == models::huggingface::DEEPSEEK_V32_NOVITA => {
132 Ok(ModelId::HuggingFaceDeepseekV32Novita)
133 }
134 s if s == models::huggingface::XIAOMI_MIMO_V2_FLASH_NOVITA => {
135 Ok(ModelId::HuggingFaceXiaomiMimoV2FlashNovita)
136 }
137 s if s == models::huggingface::ZAI_GLM_5_NOVITA => Ok(ModelId::HuggingFaceGlm5Novita),
138 s if s == models::huggingface::QWEN3_CODER_NEXT_NOVITA => {
139 Ok(ModelId::HuggingFaceQwen3CoderNextNovita)
140 }
141 "minimax/minimax-m2.5" => Ok(ModelId::OpenRouterMinimaxM25),
142 "qwen/qwen3-coder-next" => Ok(ModelId::OpenRouterQwen3CoderNext),
143 _ => {
144 if let Some(model) = Self::parse_openrouter_model(s) {
145 Ok(model)
146 } else {
147 Err(ModelParseError::InvalidModel(s.to_string()))
148 }
149 }
150 }
151 }
152}