1use std::borrow::Cow;
5use std::sync::LazyLock;
6use crate::ReasoningEffort;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum AnthropicModel {
10 Claude35Haiku20241022,
11 Claude35Sonnet20240620,
12 Claude35Sonnet20241022,
13 Claude37Sonnet20250219,
14 Claude3Haiku20240307,
15 Claude3Opus20240229,
16 Claude3Sonnet20240229,
17 ClaudeHaiku45,
18 ClaudeHaiku4520251001,
19 ClaudeOpus40,
20 ClaudeOpus41,
21 ClaudeOpus4120250805,
22 ClaudeOpus420250514,
23 ClaudeOpus45,
24 ClaudeOpus4520251101,
25 ClaudeOpus46,
26 ClaudeOpus47,
27 ClaudeSonnet40,
28 ClaudeSonnet420250514,
29 ClaudeSonnet45,
30 ClaudeSonnet4520250929,
31 ClaudeSonnet46,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35pub enum CodexModel {
36 Gpt5,
37 Gpt5Codex,
38 Gpt51,
39 Gpt51Codex,
40 Gpt51CodexMax,
41 Gpt51CodexMini,
42 Gpt52,
43 Gpt52Codex,
44 Gpt52Pro,
45 Gpt53Codex,
46 Gpt53CodexSpark,
47 Gpt54,
48 Gpt54Mini,
49 Gpt54Nano,
50 Gpt54Pro,
51 Gpt55,
52 Gpt55Pro,
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
56pub enum DeepSeekModel {
57 DeepseekChat,
58 DeepseekReasoner,
59 DeepseekV4Flash,
60 DeepseekV4Pro,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
64pub enum GeminiModel {
65 Gemini15Flash,
66 Gemini15Flash8b,
67 Gemini15Pro,
68 Gemini20Flash,
69 Gemini20FlashLite,
70 Gemini25Flash,
71 Gemini25FlashLite,
72 Gemini25FlashLitePreview0617,
73 Gemini25FlashLitePreview092025,
74 Gemini25FlashPreview0417,
75 Gemini25FlashPreview0520,
76 Gemini25FlashPreview092025,
77 Gemini25Pro,
78 Gemini25ProPreview0506,
79 Gemini25ProPreview0605,
80 Gemini3FlashPreview,
81 Gemini3ProPreview,
82 Gemini31FlashLite,
83 Gemini31FlashLitePreview,
84 Gemini31ProPreview,
85 Gemini31ProPreviewCustomtools,
86 GeminiLive25Flash,
87 GeminiLive25FlashPreviewNativeAudio,
88 Gemma327bIt,
89 Gemma426bA4bIt,
90 Gemma431bIt,
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
94pub enum MoonshotModel {
95 KimiK20711Preview,
96 KimiK20905Preview,
97 KimiK2Thinking,
98 KimiK2ThinkingTurbo,
99 KimiK2TurboPreview,
100 KimiK25,
101 KimiK26,
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
105pub enum OpenaiModel {
106 Gpt4,
107 Gpt4Turbo,
108 Gpt41,
109 Gpt41Mini,
110 Gpt41Nano,
111 Gpt4o,
112 Gpt4o20240513,
113 Gpt4o20240806,
114 Gpt4o20241120,
115 Gpt4oMini,
116 Gpt5,
117 Gpt5Codex,
118 Gpt5Mini,
119 Gpt5Nano,
120 Gpt5Pro,
121 Gpt51,
122 Gpt51Codex,
123 Gpt51CodexMax,
124 Gpt51CodexMini,
125 Gpt52,
126 Gpt52Codex,
127 Gpt52Pro,
128 Gpt53Codex,
129 Gpt53CodexSpark,
130 Gpt54,
131 Gpt54Mini,
132 Gpt54Nano,
133 Gpt54Pro,
134 Gpt55,
135 Gpt55Pro,
136 O1,
137 O1Pro,
138 O3,
139 O3DeepResearch,
140 O3Mini,
141 O3Pro,
142 O4Mini,
143 O4MiniDeepResearch,
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
147pub enum OpenRouterModel {
148 AnthropicClaude35Haiku,
149 AnthropicClaude37Sonnet,
150 AnthropicClaudeHaiku45,
151 AnthropicClaudeOpus4,
152 AnthropicClaudeOpus41,
153 AnthropicClaudeOpus45,
154 AnthropicClaudeOpus46,
155 AnthropicClaudeOpus47,
156 AnthropicClaudeSonnet4,
157 AnthropicClaudeSonnet45,
158 AnthropicClaudeSonnet46,
159 ArceeAiTrinityLargePreviewFree,
160 ArceeAiTrinityLargeThinking,
161 DeepseekDeepseekChatV31,
162 DeepseekDeepseekR1,
163 DeepseekDeepseekV31Terminus,
164 DeepseekDeepseekV31TerminusExacto,
165 DeepseekDeepseekV32,
166 DeepseekDeepseekV32Speciale,
167 DeepseekDeepseekV4Flash,
168 DeepseekDeepseekV4Pro,
169 GoogleGemini20Flash001,
170 GoogleGemini25Flash,
171 GoogleGemini25FlashLite,
172 GoogleGemini25FlashLitePreview092025,
173 GoogleGemini25FlashPreview092025,
174 GoogleGemini25Pro,
175 GoogleGemini25ProPreview0506,
176 GoogleGemini25ProPreview0605,
177 GoogleGemini3FlashPreview,
178 GoogleGemini3ProPreview,
179 GoogleGemini31FlashLitePreview,
180 GoogleGemini31ProPreview,
181 GoogleGemini31ProPreviewCustomtools,
182 GoogleGemma327bIt,
183 GoogleGemma327bItFree,
184 GoogleGemma426bA4bIt,
185 GoogleGemma426bA4bItFree,
186 GoogleGemma431bIt,
187 GoogleGemma431bItFree,
188 InceptionMercury2,
189 MetaLlamaLlama3370bInstructFree,
190 MinimaxMinimax01,
191 MinimaxMinimaxM1,
192 MinimaxMinimaxM2,
193 MinimaxMinimaxM21,
194 MinimaxMinimaxM25,
195 MinimaxMinimaxM25Free,
196 MinimaxMinimaxM27,
197 MistralaiCodestral2508,
198 MistralaiDevstral2512,
199 MistralaiDevstralMedium2507,
200 MistralaiDevstralSmall2505,
201 MistralaiDevstralSmall2507,
202 MistralaiMistralMedium3,
203 MistralaiMistralMedium31,
204 MistralaiMistralSmall2603,
205 MistralaiMistralSmall3124bInstruct,
206 MistralaiMistralSmall3224bInstruct,
207 MoonshotaiKimiK2,
208 MoonshotaiKimiK20905,
209 MoonshotaiKimiK20905Exacto,
210 MoonshotaiKimiK2Thinking,
211 MoonshotaiKimiK25,
212 MoonshotaiKimiK26,
213 NousresearchHermes4405b,
214 NousresearchHermes470b,
215 NvidiaNemotron3Nano30bA3bFree,
216 NvidiaNemotron3NanoOmni30bA3bReasoningFree,
217 NvidiaNemotron3Super120bA12b,
218 NvidiaNemotron3Super120bA12bFree,
219 NvidiaNemotronNano12bV2VlFree,
220 NvidiaNemotronNano9bV2,
221 NvidiaNemotronNano9bV2Free,
222 OpenaiGpt41,
223 OpenaiGpt41Mini,
224 OpenaiGpt4oMini,
225 OpenaiGpt5,
226 OpenaiGpt5Codex,
227 OpenaiGpt5Image,
228 OpenaiGpt5Mini,
229 OpenaiGpt5Nano,
230 OpenaiGpt5Pro,
231 OpenaiGpt51,
232 OpenaiGpt51Chat,
233 OpenaiGpt51Codex,
234 OpenaiGpt51CodexMax,
235 OpenaiGpt51CodexMini,
236 OpenaiGpt52,
237 OpenaiGpt52Chat,
238 OpenaiGpt52Codex,
239 OpenaiGpt52Pro,
240 OpenaiGpt53Codex,
241 OpenaiGpt54,
242 OpenaiGpt54Mini,
243 OpenaiGpt54Nano,
244 OpenaiGpt54Pro,
245 OpenaiGpt55,
246 OpenaiGpt55Pro,
247 OpenaiGptOss120b,
248 OpenaiGptOss120bExacto,
249 OpenaiGptOss120bFree,
250 OpenaiGptOss20b,
251 OpenaiGptOss20bFree,
252 OpenaiGptOssSafeguard20b,
253 OpenaiO4Mini,
254 OpenrouterElephantAlpha,
255 OpenrouterFree,
256 OpenrouterOwlAlpha,
257 OpenrouterParetoCode,
258 PoolsideLagunaM1Free,
259 PoolsideLagunaXs2Free,
260 PrimeIntellectIntellect3,
261 QwenQwen3627b,
262 QwenQwenPlus,
263 QwenQwen3235bA22b0725,
264 QwenQwen3235bA22bThinking2507,
265 QwenQwen330bA3bInstruct2507,
266 QwenQwen330bA3bThinking2507,
267 QwenQwen3Coder,
268 QwenQwen3Coder30bA3bInstruct,
269 QwenQwen3CoderFlash,
270 QwenQwen3CoderPlus,
271 QwenQwen3CoderExacto,
272 QwenQwen3Max,
273 QwenQwen3Next80bA3bInstruct,
274 QwenQwen3Next80bA3bThinking,
275 QwenQwen35397bA17b,
276 QwenQwen35Flash0223,
277 QwenQwen35Plus0215,
278 QwenQwen36Plus,
279 StepfunStep35Flash,
280 TencentHy3Preview,
281 XAiGrok3,
282 XAiGrok3Beta,
283 XAiGrok3Mini,
284 XAiGrok3MiniBeta,
285 XAiGrok4,
286 XAiGrok4Fast,
287 XAiGrok41Fast,
288 XAiGrok420Beta,
289 XAiGrok43,
290 XAiGrokCodeFast1,
291 XiaomiMimoV2Flash,
292 XiaomiMimoV2Omni,
293 XiaomiMimoV2Pro,
294 XiaomiMimoV25,
295 XiaomiMimoV25Pro,
296 ZAiGlm45,
297 ZAiGlm45Air,
298 ZAiGlm45v,
299 ZAiGlm46,
300 ZAiGlm46Exacto,
301 ZAiGlm47,
302 ZAiGlm47Flash,
303 ZAiGlm5,
304 ZAiGlm5Turbo,
305 ZAiGlm51,
306}
307
308#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
309pub enum ZAiModel {
310 Glm45,
311 Glm45Air,
312 Glm45Flash,
313 Glm45v,
314 Glm46,
315 Glm46v,
316 Glm47,
317 Glm47Flash,
318 Glm47Flashx,
319 Glm5,
320 Glm5Turbo,
321 Glm51,
322 Glm5vTurbo,
323}
324
325#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
326pub enum BedrockModel {
327 AmazonNova2LiteV10,
328 AmazonNovaLiteV10,
329 AmazonNovaMicroV10,
330 AmazonNovaProV10,
331 AnthropicClaudeHaiku4520251001V10,
332 AnthropicClaudeOpus4120250805V10,
333 AnthropicClaudeOpus4520251101V10,
334 AnthropicClaudeOpus46V1,
335 AnthropicClaudeOpus47,
336 AnthropicClaudeSonnet4520250929V10,
337 AnthropicClaudeSonnet46,
338 AuAnthropicClaudeHaiku4520251001V10,
339 AuAnthropicClaudeOpus46V1,
340 AuAnthropicClaudeSonnet4520250929V10,
341 AuAnthropicClaudeSonnet46,
342 DeepseekR1V10,
343 DeepseekV3V10,
344 DeepseekV32,
345 EuAnthropicClaudeHaiku4520251001V10,
346 EuAnthropicClaudeOpus4520251101V10,
347 EuAnthropicClaudeOpus46V1,
348 EuAnthropicClaudeOpus47,
349 EuAnthropicClaudeSonnet4520250929V10,
350 EuAnthropicClaudeSonnet46,
351 GlobalAnthropicClaudeHaiku4520251001V10,
352 GlobalAnthropicClaudeOpus4520251101V10,
353 GlobalAnthropicClaudeOpus46V1,
354 GlobalAnthropicClaudeOpus47,
355 GlobalAnthropicClaudeSonnet4520250929V10,
356 GlobalAnthropicClaudeSonnet46,
357 GoogleGemma327bIt,
358 GoogleGemma34bIt,
359 JpAnthropicClaudeOpus47,
360 JpAnthropicClaudeSonnet4520250929V10,
361 JpAnthropicClaudeSonnet46,
362 MetaLlama3170bInstructV10,
363 MetaLlama318bInstructV10,
364 MetaLlama3370bInstructV10,
365 MetaLlama4Maverick17bInstructV10,
366 MetaLlama4Scout17bInstructV10,
367 MinimaxMinimaxM2,
368 MinimaxMinimaxM21,
369 MinimaxMinimaxM25,
370 MistralDevstral2123b,
371 MistralMagistralSmall2509,
372 MistralMinistral314bInstruct,
373 MistralMinistral33bInstruct,
374 MistralMinistral38bInstruct,
375 MistralMistralLarge3675bInstruct,
376 MistralPixtralLarge2502V10,
377 MistralVoxtralMini3b2507,
378 MistralVoxtralSmall24b2507,
379 MoonshotKimiK2Thinking,
380 MoonshotaiKimiK25,
381 NvidiaNemotronNano12bV2,
382 NvidiaNemotronNano330b,
383 NvidiaNemotronNano9bV2,
384 NvidiaNemotronSuper3120b,
385 OpenaiGptOss120b10,
386 OpenaiGptOss20b10,
387 OpenaiGptOssSafeguard120b,
388 OpenaiGptOssSafeguard20b,
389 QwenQwen3235bA22b2507V10,
390 QwenQwen332bV10,
391 QwenQwen3Coder30bA3bV10,
392 QwenQwen3Coder480bA35bV10,
393 QwenQwen3CoderNext,
394 QwenQwen3Next80bA3b,
395 QwenQwen3Vl235bA22b,
396 UsAnthropicClaudeHaiku4520251001V10,
397 UsAnthropicClaudeOpus4120250805V10,
398 UsAnthropicClaudeOpus4520251101V10,
399 UsAnthropicClaudeOpus46V1,
400 UsAnthropicClaudeOpus47,
401 UsAnthropicClaudeSonnet4520250929V10,
402 UsAnthropicClaudeSonnet46,
403 UsDeepseekR1V10,
404 UsMetaLlama4Maverick17bInstructV10,
405 UsMetaLlama4Scout17bInstructV10,
406 WriterPalmyraX4V10,
407 WriterPalmyraX5V10,
408 ZaiGlm47,
409 ZaiGlm47Flash,
410 ZaiGlm5,
411}
412
413impl AnthropicModel {
414 #[allow(clippy::too_many_lines)]
415 fn model_id(self) -> &'static str {
416 match self {
417 Self::Claude35Haiku20241022 => "claude-3-5-haiku-20241022",
418 Self::Claude35Sonnet20240620 => "claude-3-5-sonnet-20240620",
419 Self::Claude35Sonnet20241022 => "claude-3-5-sonnet-20241022",
420 Self::Claude37Sonnet20250219 => "claude-3-7-sonnet-20250219",
421 Self::Claude3Haiku20240307 => "claude-3-haiku-20240307",
422 Self::Claude3Opus20240229 => "claude-3-opus-20240229",
423 Self::Claude3Sonnet20240229 => "claude-3-sonnet-20240229",
424 Self::ClaudeHaiku45 => "claude-haiku-4-5",
425 Self::ClaudeHaiku4520251001 => "claude-haiku-4-5-20251001",
426 Self::ClaudeOpus40 => "claude-opus-4-0",
427 Self::ClaudeOpus41 => "claude-opus-4-1",
428 Self::ClaudeOpus4120250805 => "claude-opus-4-1-20250805",
429 Self::ClaudeOpus420250514 => "claude-opus-4-20250514",
430 Self::ClaudeOpus45 => "claude-opus-4-5",
431 Self::ClaudeOpus4520251101 => "claude-opus-4-5-20251101",
432 Self::ClaudeOpus46 => "claude-opus-4-6",
433 Self::ClaudeOpus47 => "claude-opus-4-7",
434 Self::ClaudeSonnet40 => "claude-sonnet-4-0",
435 Self::ClaudeSonnet420250514 => "claude-sonnet-4-20250514",
436 Self::ClaudeSonnet45 => "claude-sonnet-4-5",
437 Self::ClaudeSonnet4520250929 => "claude-sonnet-4-5-20250929",
438 Self::ClaudeSonnet46 => "claude-sonnet-4-6",
439 }
440 }
441
442 #[allow(clippy::too_many_lines)]
443 fn display_name(self) -> &'static str {
444 match self {
445 Self::Claude3Haiku20240307 => "Claude Haiku 3",
446 Self::Claude35Haiku20241022 => "Claude Haiku 3.5",
447 Self::ClaudeHaiku4520251001 => "Claude Haiku 4.5",
448 Self::ClaudeHaiku45 => "Claude Haiku 4.5 (latest)",
449 Self::Claude3Opus20240229 => "Claude Opus 3",
450 Self::ClaudeOpus420250514 => "Claude Opus 4",
451 Self::ClaudeOpus40 => "Claude Opus 4 (latest)",
452 Self::ClaudeOpus4120250805 => "Claude Opus 4.1",
453 Self::ClaudeOpus41 => "Claude Opus 4.1 (latest)",
454 Self::ClaudeOpus4520251101 => "Claude Opus 4.5",
455 Self::ClaudeOpus45 => "Claude Opus 4.5 (latest)",
456 Self::ClaudeOpus46 => "Claude Opus 4.6",
457 Self::ClaudeOpus47 => "Claude Opus 4.7",
458 Self::Claude3Sonnet20240229 => "Claude Sonnet 3",
459 Self::Claude35Sonnet20240620 => "Claude Sonnet 3.5",
460 Self::Claude35Sonnet20241022 => "Claude Sonnet 3.5 v2",
461 Self::Claude37Sonnet20250219 => "Claude Sonnet 3.7",
462 Self::ClaudeSonnet420250514 => "Claude Sonnet 4",
463 Self::ClaudeSonnet40 => "Claude Sonnet 4 (latest)",
464 Self::ClaudeSonnet4520250929 => "Claude Sonnet 4.5",
465 Self::ClaudeSonnet45 => "Claude Sonnet 4.5 (latest)",
466 Self::ClaudeSonnet46 => "Claude Sonnet 4.6",
467 }
468 }
469
470 fn context_window(self) -> u32 {
471 match self {
472 Self::ClaudeOpus46 | Self::ClaudeOpus47 | Self::ClaudeSonnet46 => 1_000_000,
473 Self::Claude35Haiku20241022 | Self::Claude35Sonnet20240620 | Self::Claude35Sonnet20241022 | Self::Claude37Sonnet20250219 | Self::Claude3Haiku20240307 | Self::Claude3Opus20240229 | Self::Claude3Sonnet20240229 | Self::ClaudeHaiku45 | Self::ClaudeHaiku4520251001 | Self::ClaudeOpus40 | Self::ClaudeOpus41 | Self::ClaudeOpus4120250805 | Self::ClaudeOpus420250514 | Self::ClaudeOpus45 | Self::ClaudeOpus4520251101 | Self::ClaudeSonnet40 | Self::ClaudeSonnet420250514 | Self::ClaudeSonnet45 | Self::ClaudeSonnet4520250929 => 200_000,
474 }
475 }
476
477 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
478 match self {
479 Self::Claude35Haiku20241022 | Self::Claude35Sonnet20240620 | Self::Claude35Sonnet20241022 | Self::Claude3Haiku20240307 | Self::Claude3Opus20240229 | Self::Claude3Sonnet20240229 => &[],
480 Self::Claude37Sonnet20250219 | Self::ClaudeHaiku45 | Self::ClaudeHaiku4520251001 | Self::ClaudeOpus40 | Self::ClaudeOpus41 | Self::ClaudeOpus4120250805 | Self::ClaudeOpus420250514 | Self::ClaudeOpus45 | Self::ClaudeOpus4520251101 | Self::ClaudeOpus46 | Self::ClaudeOpus47 | Self::ClaudeSonnet40 | Self::ClaudeSonnet420250514 | Self::ClaudeSonnet45 | Self::ClaudeSonnet4520250929 | Self::ClaudeSonnet46 => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High],
481 }
482 }
483
484 pub fn supports_reasoning(self) -> bool {
485 !self.reasoning_levels().is_empty()
486 }
487
488 pub fn supports_image(self) -> bool {
489 match self {
490 Self::Claude35Haiku20241022 | Self::Claude35Sonnet20240620 | Self::Claude35Sonnet20241022 | Self::Claude37Sonnet20250219 | Self::Claude3Haiku20240307 | Self::Claude3Opus20240229 | Self::Claude3Sonnet20240229 | Self::ClaudeHaiku45 | Self::ClaudeHaiku4520251001 | Self::ClaudeOpus40 | Self::ClaudeOpus41 | Self::ClaudeOpus4120250805 | Self::ClaudeOpus420250514 | Self::ClaudeOpus45 | Self::ClaudeOpus4520251101 | Self::ClaudeOpus46 | Self::ClaudeOpus47 | Self::ClaudeSonnet40 | Self::ClaudeSonnet420250514 | Self::ClaudeSonnet45 | Self::ClaudeSonnet4520250929 | Self::ClaudeSonnet46 => true,
491 }
492 }
493
494 pub fn supports_audio(self) -> bool {
495 match self {
496 Self::Claude35Haiku20241022 | Self::Claude35Sonnet20240620 | Self::Claude35Sonnet20241022 | Self::Claude37Sonnet20250219 | Self::Claude3Haiku20240307 | Self::Claude3Opus20240229 | Self::Claude3Sonnet20240229 | Self::ClaudeHaiku45 | Self::ClaudeHaiku4520251001 | Self::ClaudeOpus40 | Self::ClaudeOpus41 | Self::ClaudeOpus4120250805 | Self::ClaudeOpus420250514 | Self::ClaudeOpus45 | Self::ClaudeOpus4520251101 | Self::ClaudeOpus46 | Self::ClaudeOpus47 | Self::ClaudeSonnet40 | Self::ClaudeSonnet420250514 | Self::ClaudeSonnet45 | Self::ClaudeSonnet4520250929 | Self::ClaudeSonnet46 => false,
497 }
498 }
499
500 const ALL: &[AnthropicModel] = &[
501 Self::Claude35Haiku20241022,
502 Self::Claude35Sonnet20240620,
503 Self::Claude35Sonnet20241022,
504 Self::Claude37Sonnet20250219,
505 Self::Claude3Haiku20240307,
506 Self::Claude3Opus20240229,
507 Self::Claude3Sonnet20240229,
508 Self::ClaudeHaiku45,
509 Self::ClaudeHaiku4520251001,
510 Self::ClaudeOpus40,
511 Self::ClaudeOpus41,
512 Self::ClaudeOpus4120250805,
513 Self::ClaudeOpus420250514,
514 Self::ClaudeOpus45,
515 Self::ClaudeOpus4520251101,
516 Self::ClaudeOpus46,
517 Self::ClaudeOpus47,
518 Self::ClaudeSonnet40,
519 Self::ClaudeSonnet420250514,
520 Self::ClaudeSonnet45,
521 Self::ClaudeSonnet4520250929,
522 Self::ClaudeSonnet46,
523 ];
524}
525
526impl std::str::FromStr for AnthropicModel {
527 type Err = String;
528
529 #[allow(clippy::too_many_lines)]
530 fn from_str(s: &str) -> Result<Self, Self::Err> {
531 match s {
532 "claude-3-5-haiku-20241022" => Ok(Self::Claude35Haiku20241022),
533 "claude-3-5-sonnet-20240620" => Ok(Self::Claude35Sonnet20240620),
534 "claude-3-5-sonnet-20241022" => Ok(Self::Claude35Sonnet20241022),
535 "claude-3-7-sonnet-20250219" => Ok(Self::Claude37Sonnet20250219),
536 "claude-3-haiku-20240307" => Ok(Self::Claude3Haiku20240307),
537 "claude-3-opus-20240229" => Ok(Self::Claude3Opus20240229),
538 "claude-3-sonnet-20240229" => Ok(Self::Claude3Sonnet20240229),
539 "claude-haiku-4-5" => Ok(Self::ClaudeHaiku45),
540 "claude-haiku-4-5-20251001" => Ok(Self::ClaudeHaiku4520251001),
541 "claude-opus-4-0" => Ok(Self::ClaudeOpus40),
542 "claude-opus-4-1" => Ok(Self::ClaudeOpus41),
543 "claude-opus-4-1-20250805" => Ok(Self::ClaudeOpus4120250805),
544 "claude-opus-4-20250514" => Ok(Self::ClaudeOpus420250514),
545 "claude-opus-4-5" => Ok(Self::ClaudeOpus45),
546 "claude-opus-4-5-20251101" => Ok(Self::ClaudeOpus4520251101),
547 "claude-opus-4-6" => Ok(Self::ClaudeOpus46),
548 "claude-opus-4-7" => Ok(Self::ClaudeOpus47),
549 "claude-sonnet-4-0" => Ok(Self::ClaudeSonnet40),
550 "claude-sonnet-4-20250514" => Ok(Self::ClaudeSonnet420250514),
551 "claude-sonnet-4-5" => Ok(Self::ClaudeSonnet45),
552 "claude-sonnet-4-5-20250929" => Ok(Self::ClaudeSonnet4520250929),
553 "claude-sonnet-4-6" => Ok(Self::ClaudeSonnet46),
554 _ => Err(format!("Unknown anthropic model: '{s}'")),
555 }
556 }
557}
558
559impl CodexModel {
560 #[allow(clippy::too_many_lines)]
561 fn model_id(self) -> &'static str {
562 match self {
563 Self::Gpt5 => "gpt-5",
564 Self::Gpt5Codex => "gpt-5-codex",
565 Self::Gpt51 => "gpt-5.1",
566 Self::Gpt51Codex => "gpt-5.1-codex",
567 Self::Gpt51CodexMax => "gpt-5.1-codex-max",
568 Self::Gpt51CodexMini => "gpt-5.1-codex-mini",
569 Self::Gpt52 => "gpt-5.2",
570 Self::Gpt52Codex => "gpt-5.2-codex",
571 Self::Gpt52Pro => "gpt-5.2-pro",
572 Self::Gpt53Codex => "gpt-5.3-codex",
573 Self::Gpt53CodexSpark => "gpt-5.3-codex-spark",
574 Self::Gpt54 => "gpt-5.4",
575 Self::Gpt54Mini => "gpt-5.4-mini",
576 Self::Gpt54Nano => "gpt-5.4-nano",
577 Self::Gpt54Pro => "gpt-5.4-pro",
578 Self::Gpt55 => "gpt-5.5",
579 Self::Gpt55Pro => "gpt-5.5-pro",
580 }
581 }
582
583 #[allow(clippy::too_many_lines)]
584 fn display_name(self) -> &'static str {
585 match self {
586 Self::Gpt5 => "GPT-5",
587 Self::Gpt5Codex => "GPT-5-Codex",
588 Self::Gpt51 => "GPT-5.1",
589 Self::Gpt51Codex => "GPT-5.1 Codex",
590 Self::Gpt51CodexMax => "GPT-5.1 Codex Max",
591 Self::Gpt51CodexMini => "GPT-5.1 Codex mini",
592 Self::Gpt52 => "GPT-5.2",
593 Self::Gpt52Codex => "GPT-5.2 Codex",
594 Self::Gpt52Pro => "GPT-5.2 Pro",
595 Self::Gpt53Codex => "GPT-5.3 Codex",
596 Self::Gpt53CodexSpark => "GPT-5.3 Codex Spark",
597 Self::Gpt54 => "GPT-5.4",
598 Self::Gpt54Pro => "GPT-5.4 Pro",
599 Self::Gpt54Mini => "GPT-5.4 mini",
600 Self::Gpt54Nano => "GPT-5.4 nano",
601 Self::Gpt55 => "GPT-5.5",
602 Self::Gpt55Pro => "GPT-5.5 Pro",
603 }
604 }
605
606 fn context_window(self) -> u32 {
607 match self {
608 Self::Gpt54Pro | Self::Gpt55Pro => 1_050_000,
609 Self::Gpt53CodexSpark => 128_000,
610 Self::Gpt52 | Self::Gpt53Codex | Self::Gpt54 | Self::Gpt54Mini | Self::Gpt55 => 272_000,
611 Self::Gpt5 | Self::Gpt5Codex | Self::Gpt51 | Self::Gpt51Codex | Self::Gpt51CodexMax | Self::Gpt51CodexMini | Self::Gpt52Codex | Self::Gpt52Pro | Self::Gpt54Nano => 400_000,
612 }
613 }
614
615 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
616 match self {
617 Self::Gpt5 | Self::Gpt5Codex | Self::Gpt51 | Self::Gpt51Codex | Self::Gpt51CodexMax | Self::Gpt51CodexMini | Self::Gpt52 | Self::Gpt52Codex | Self::Gpt52Pro | Self::Gpt53Codex | Self::Gpt53CodexSpark | Self::Gpt54 | Self::Gpt54Mini | Self::Gpt54Nano | Self::Gpt54Pro | Self::Gpt55 | Self::Gpt55Pro => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High, ReasoningEffort::Xhigh],
618 }
619 }
620
621 pub fn supports_reasoning(self) -> bool {
622 !self.reasoning_levels().is_empty()
623 }
624
625 pub fn supports_image(self) -> bool {
626 match self {
627 Self::Gpt5 | Self::Gpt5Codex | Self::Gpt51 | Self::Gpt51Codex | Self::Gpt51CodexMax | Self::Gpt51CodexMini | Self::Gpt52 | Self::Gpt52Codex | Self::Gpt52Pro | Self::Gpt53Codex | Self::Gpt53CodexSpark | Self::Gpt54 | Self::Gpt54Mini | Self::Gpt54Nano | Self::Gpt54Pro | Self::Gpt55 | Self::Gpt55Pro => true,
628 }
629 }
630
631 pub fn supports_audio(self) -> bool {
632 match self {
633 Self::Gpt5 | Self::Gpt5Codex | Self::Gpt51 | Self::Gpt51Codex | Self::Gpt51CodexMax | Self::Gpt51CodexMini | Self::Gpt52 | Self::Gpt52Codex | Self::Gpt52Pro | Self::Gpt53Codex | Self::Gpt53CodexSpark | Self::Gpt54 | Self::Gpt54Mini | Self::Gpt54Nano | Self::Gpt54Pro | Self::Gpt55 | Self::Gpt55Pro => false,
634 }
635 }
636
637 const ALL: &[CodexModel] = &[
638 Self::Gpt5,
639 Self::Gpt5Codex,
640 Self::Gpt51,
641 Self::Gpt51Codex,
642 Self::Gpt51CodexMax,
643 Self::Gpt51CodexMini,
644 Self::Gpt52,
645 Self::Gpt52Codex,
646 Self::Gpt52Pro,
647 Self::Gpt53Codex,
648 Self::Gpt53CodexSpark,
649 Self::Gpt54,
650 Self::Gpt54Mini,
651 Self::Gpt54Nano,
652 Self::Gpt54Pro,
653 Self::Gpt55,
654 Self::Gpt55Pro,
655 ];
656}
657
658impl std::str::FromStr for CodexModel {
659 type Err = String;
660
661 #[allow(clippy::too_many_lines)]
662 fn from_str(s: &str) -> Result<Self, Self::Err> {
663 match s {
664 "gpt-5" => Ok(Self::Gpt5),
665 "gpt-5-codex" => Ok(Self::Gpt5Codex),
666 "gpt-5.1" => Ok(Self::Gpt51),
667 "gpt-5.1-codex" => Ok(Self::Gpt51Codex),
668 "gpt-5.1-codex-max" => Ok(Self::Gpt51CodexMax),
669 "gpt-5.1-codex-mini" => Ok(Self::Gpt51CodexMini),
670 "gpt-5.2" => Ok(Self::Gpt52),
671 "gpt-5.2-codex" => Ok(Self::Gpt52Codex),
672 "gpt-5.2-pro" => Ok(Self::Gpt52Pro),
673 "gpt-5.3-codex" => Ok(Self::Gpt53Codex),
674 "gpt-5.3-codex-spark" => Ok(Self::Gpt53CodexSpark),
675 "gpt-5.4" => Ok(Self::Gpt54),
676 "gpt-5.4-mini" => Ok(Self::Gpt54Mini),
677 "gpt-5.4-nano" => Ok(Self::Gpt54Nano),
678 "gpt-5.4-pro" => Ok(Self::Gpt54Pro),
679 "gpt-5.5" => Ok(Self::Gpt55),
680 "gpt-5.5-pro" => Ok(Self::Gpt55Pro),
681 _ => Err(format!("Unknown codex model: '{s}'")),
682 }
683 }
684}
685
686impl DeepSeekModel {
687 #[allow(clippy::too_many_lines)]
688 fn model_id(self) -> &'static str {
689 match self {
690 Self::DeepseekChat => "deepseek-chat",
691 Self::DeepseekReasoner => "deepseek-reasoner",
692 Self::DeepseekV4Flash => "deepseek-v4-flash",
693 Self::DeepseekV4Pro => "deepseek-v4-pro",
694 }
695 }
696
697 #[allow(clippy::too_many_lines)]
698 fn display_name(self) -> &'static str {
699 match self {
700 Self::DeepseekChat => "DeepSeek Chat",
701 Self::DeepseekReasoner => "DeepSeek Reasoner",
702 Self::DeepseekV4Flash => "DeepSeek V4 Flash",
703 Self::DeepseekV4Pro => "DeepSeek V4 Pro",
704 }
705 }
706
707 fn context_window(self) -> u32 {
708 match self {
709 Self::DeepseekChat | Self::DeepseekReasoner | Self::DeepseekV4Flash | Self::DeepseekV4Pro => 1_000_000,
710 }
711 }
712
713 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
714 match self {
715 Self::DeepseekChat => &[],
716 Self::DeepseekReasoner | Self::DeepseekV4Flash | Self::DeepseekV4Pro => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High],
717 }
718 }
719
720 pub fn supports_reasoning(self) -> bool {
721 !self.reasoning_levels().is_empty()
722 }
723
724 pub fn supports_image(self) -> bool {
725 match self {
726 Self::DeepseekChat | Self::DeepseekReasoner | Self::DeepseekV4Flash | Self::DeepseekV4Pro => false,
727 }
728 }
729
730 pub fn supports_audio(self) -> bool {
731 match self {
732 Self::DeepseekChat | Self::DeepseekReasoner | Self::DeepseekV4Flash | Self::DeepseekV4Pro => false,
733 }
734 }
735
736 const ALL: &[DeepSeekModel] = &[
737 Self::DeepseekChat,
738 Self::DeepseekReasoner,
739 Self::DeepseekV4Flash,
740 Self::DeepseekV4Pro,
741 ];
742}
743
744impl std::str::FromStr for DeepSeekModel {
745 type Err = String;
746
747 #[allow(clippy::too_many_lines)]
748 fn from_str(s: &str) -> Result<Self, Self::Err> {
749 match s {
750 "deepseek-chat" => Ok(Self::DeepseekChat),
751 "deepseek-reasoner" => Ok(Self::DeepseekReasoner),
752 "deepseek-v4-flash" => Ok(Self::DeepseekV4Flash),
753 "deepseek-v4-pro" => Ok(Self::DeepseekV4Pro),
754 _ => Err(format!("Unknown deepseek model: '{s}'")),
755 }
756 }
757}
758
759impl GeminiModel {
760 #[allow(clippy::too_many_lines)]
761 fn model_id(self) -> &'static str {
762 match self {
763 Self::Gemini15Flash => "gemini-1.5-flash",
764 Self::Gemini15Flash8b => "gemini-1.5-flash-8b",
765 Self::Gemini15Pro => "gemini-1.5-pro",
766 Self::Gemini20Flash => "gemini-2.0-flash",
767 Self::Gemini20FlashLite => "gemini-2.0-flash-lite",
768 Self::Gemini25Flash => "gemini-2.5-flash",
769 Self::Gemini25FlashLite => "gemini-2.5-flash-lite",
770 Self::Gemini25FlashLitePreview0617 => "gemini-2.5-flash-lite-preview-06-17",
771 Self::Gemini25FlashLitePreview092025 => "gemini-2.5-flash-lite-preview-09-2025",
772 Self::Gemini25FlashPreview0417 => "gemini-2.5-flash-preview-04-17",
773 Self::Gemini25FlashPreview0520 => "gemini-2.5-flash-preview-05-20",
774 Self::Gemini25FlashPreview092025 => "gemini-2.5-flash-preview-09-2025",
775 Self::Gemini25Pro => "gemini-2.5-pro",
776 Self::Gemini25ProPreview0506 => "gemini-2.5-pro-preview-05-06",
777 Self::Gemini25ProPreview0605 => "gemini-2.5-pro-preview-06-05",
778 Self::Gemini3FlashPreview => "gemini-3-flash-preview",
779 Self::Gemini3ProPreview => "gemini-3-pro-preview",
780 Self::Gemini31FlashLite => "gemini-3.1-flash-lite",
781 Self::Gemini31FlashLitePreview => "gemini-3.1-flash-lite-preview",
782 Self::Gemini31ProPreview => "gemini-3.1-pro-preview",
783 Self::Gemini31ProPreviewCustomtools => "gemini-3.1-pro-preview-customtools",
784 Self::GeminiLive25Flash => "gemini-live-2.5-flash",
785 Self::GeminiLive25FlashPreviewNativeAudio => "gemini-live-2.5-flash-preview-native-audio",
786 Self::Gemma327bIt => "gemma-3-27b-it",
787 Self::Gemma426bA4bIt => "gemma-4-26b-a4b-it",
788 Self::Gemma431bIt => "gemma-4-31b-it",
789 }
790 }
791
792 #[allow(clippy::too_many_lines)]
793 fn display_name(self) -> &'static str {
794 match self {
795 Self::Gemini15Flash => "Gemini 1.5 Flash",
796 Self::Gemini15Flash8b => "Gemini 1.5 Flash-8B",
797 Self::Gemini15Pro => "Gemini 1.5 Pro",
798 Self::Gemini20Flash => "Gemini 2.0 Flash",
799 Self::Gemini20FlashLite => "Gemini 2.0 Flash Lite",
800 Self::Gemini25Flash => "Gemini 2.5 Flash",
801 Self::Gemini25FlashLite => "Gemini 2.5 Flash Lite",
802 Self::Gemini25FlashLitePreview0617 => "Gemini 2.5 Flash Lite Preview 06-17",
803 Self::Gemini25FlashLitePreview092025 => "Gemini 2.5 Flash Lite Preview 09-25",
804 Self::Gemini25FlashPreview0417 => "Gemini 2.5 Flash Preview 04-17",
805 Self::Gemini25FlashPreview0520 => "Gemini 2.5 Flash Preview 05-20",
806 Self::Gemini25FlashPreview092025 => "Gemini 2.5 Flash Preview 09-25",
807 Self::Gemini25Pro => "Gemini 2.5 Pro",
808 Self::Gemini25ProPreview0506 => "Gemini 2.5 Pro Preview 05-06",
809 Self::Gemini25ProPreview0605 => "Gemini 2.5 Pro Preview 06-05",
810 Self::Gemini3FlashPreview => "Gemini 3 Flash Preview",
811 Self::Gemini3ProPreview => "Gemini 3 Pro Preview",
812 Self::Gemini31FlashLite => "Gemini 3.1 Flash Lite",
813 Self::Gemini31FlashLitePreview => "Gemini 3.1 Flash Lite Preview",
814 Self::Gemini31ProPreview => "Gemini 3.1 Pro Preview",
815 Self::Gemini31ProPreviewCustomtools => "Gemini 3.1 Pro Preview Custom Tools",
816 Self::GeminiLive25Flash => "Gemini Live 2.5 Flash",
817 Self::GeminiLive25FlashPreviewNativeAudio => "Gemini Live 2.5 Flash Preview Native Audio",
818 Self::Gemma327bIt => "Gemma 3 27B",
819 Self::Gemma426bA4bIt => "Gemma 4 26B",
820 Self::Gemma431bIt => "Gemma 4 31B",
821 }
822 }
823
824 fn context_window(self) -> u32 {
825 match self {
826 Self::Gemini15Flash | Self::Gemini15Flash8b | Self::Gemini15Pro | Self::Gemini3ProPreview => 1_000_000,
827 Self::Gemini20Flash | Self::Gemini20FlashLite | Self::Gemini25Flash | Self::Gemini25FlashLite | Self::Gemini25FlashLitePreview0617 | Self::Gemini25FlashLitePreview092025 | Self::Gemini25FlashPreview0417 | Self::Gemini25FlashPreview0520 | Self::Gemini25FlashPreview092025 | Self::Gemini25Pro | Self::Gemini25ProPreview0506 | Self::Gemini25ProPreview0605 | Self::Gemini3FlashPreview | Self::Gemini31FlashLite | Self::Gemini31FlashLitePreview | Self::Gemini31ProPreview | Self::Gemini31ProPreviewCustomtools => 1_048_576,
828 Self::GeminiLive25Flash => 128_000,
829 Self::GeminiLive25FlashPreviewNativeAudio | Self::Gemma327bIt => 131_072,
830 Self::Gemma426bA4bIt | Self::Gemma431bIt => 256_000,
831 }
832 }
833
834 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
835 match self {
836 Self::Gemini15Flash | Self::Gemini15Flash8b | Self::Gemini15Pro | Self::Gemini20Flash | Self::Gemini20FlashLite | Self::Gemma327bIt => &[],
837 Self::Gemini25Flash | Self::Gemini25FlashLite | Self::Gemini25FlashLitePreview0617 | Self::Gemini25FlashLitePreview092025 | Self::Gemini25FlashPreview0417 | Self::Gemini25FlashPreview0520 | Self::Gemini25FlashPreview092025 | Self::Gemini25Pro | Self::Gemini25ProPreview0506 | Self::Gemini25ProPreview0605 | Self::Gemini3FlashPreview | Self::Gemini3ProPreview | Self::Gemini31FlashLite | Self::Gemini31FlashLitePreview | Self::Gemini31ProPreview | Self::Gemini31ProPreviewCustomtools | Self::GeminiLive25Flash | Self::GeminiLive25FlashPreviewNativeAudio | Self::Gemma426bA4bIt | Self::Gemma431bIt => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High],
838 }
839 }
840
841 pub fn supports_reasoning(self) -> bool {
842 !self.reasoning_levels().is_empty()
843 }
844
845 pub fn supports_image(self) -> bool {
846 match self {
847 Self::GeminiLive25FlashPreviewNativeAudio => false,
848 Self::Gemini15Flash | Self::Gemini15Flash8b | Self::Gemini15Pro | Self::Gemini20Flash | Self::Gemini20FlashLite | Self::Gemini25Flash | Self::Gemini25FlashLite | Self::Gemini25FlashLitePreview0617 | Self::Gemini25FlashLitePreview092025 | Self::Gemini25FlashPreview0417 | Self::Gemini25FlashPreview0520 | Self::Gemini25FlashPreview092025 | Self::Gemini25Pro | Self::Gemini25ProPreview0506 | Self::Gemini25ProPreview0605 | Self::Gemini3FlashPreview | Self::Gemini3ProPreview | Self::Gemini31FlashLite | Self::Gemini31FlashLitePreview | Self::Gemini31ProPreview | Self::Gemini31ProPreviewCustomtools | Self::GeminiLive25Flash | Self::Gemma327bIt | Self::Gemma426bA4bIt | Self::Gemma431bIt => true,
849 }
850 }
851
852 pub fn supports_audio(self) -> bool {
853 match self {
854 Self::Gemma327bIt | Self::Gemma426bA4bIt | Self::Gemma431bIt => false,
855 Self::Gemini15Flash | Self::Gemini15Flash8b | Self::Gemini15Pro | Self::Gemini20Flash | Self::Gemini20FlashLite | Self::Gemini25Flash | Self::Gemini25FlashLite | Self::Gemini25FlashLitePreview0617 | Self::Gemini25FlashLitePreview092025 | Self::Gemini25FlashPreview0417 | Self::Gemini25FlashPreview0520 | Self::Gemini25FlashPreview092025 | Self::Gemini25Pro | Self::Gemini25ProPreview0506 | Self::Gemini25ProPreview0605 | Self::Gemini3FlashPreview | Self::Gemini3ProPreview | Self::Gemini31FlashLite | Self::Gemini31FlashLitePreview | Self::Gemini31ProPreview | Self::Gemini31ProPreviewCustomtools | Self::GeminiLive25Flash | Self::GeminiLive25FlashPreviewNativeAudio => true,
856 }
857 }
858
859 const ALL: &[GeminiModel] = &[
860 Self::Gemini15Flash,
861 Self::Gemini15Flash8b,
862 Self::Gemini15Pro,
863 Self::Gemini20Flash,
864 Self::Gemini20FlashLite,
865 Self::Gemini25Flash,
866 Self::Gemini25FlashLite,
867 Self::Gemini25FlashLitePreview0617,
868 Self::Gemini25FlashLitePreview092025,
869 Self::Gemini25FlashPreview0417,
870 Self::Gemini25FlashPreview0520,
871 Self::Gemini25FlashPreview092025,
872 Self::Gemini25Pro,
873 Self::Gemini25ProPreview0506,
874 Self::Gemini25ProPreview0605,
875 Self::Gemini3FlashPreview,
876 Self::Gemini3ProPreview,
877 Self::Gemini31FlashLite,
878 Self::Gemini31FlashLitePreview,
879 Self::Gemini31ProPreview,
880 Self::Gemini31ProPreviewCustomtools,
881 Self::GeminiLive25Flash,
882 Self::GeminiLive25FlashPreviewNativeAudio,
883 Self::Gemma327bIt,
884 Self::Gemma426bA4bIt,
885 Self::Gemma431bIt,
886 ];
887}
888
889impl std::str::FromStr for GeminiModel {
890 type Err = String;
891
892 #[allow(clippy::too_many_lines)]
893 fn from_str(s: &str) -> Result<Self, Self::Err> {
894 match s {
895 "gemini-1.5-flash" => Ok(Self::Gemini15Flash),
896 "gemini-1.5-flash-8b" => Ok(Self::Gemini15Flash8b),
897 "gemini-1.5-pro" => Ok(Self::Gemini15Pro),
898 "gemini-2.0-flash" => Ok(Self::Gemini20Flash),
899 "gemini-2.0-flash-lite" => Ok(Self::Gemini20FlashLite),
900 "gemini-2.5-flash" => Ok(Self::Gemini25Flash),
901 "gemini-2.5-flash-lite" => Ok(Self::Gemini25FlashLite),
902 "gemini-2.5-flash-lite-preview-06-17" => Ok(Self::Gemini25FlashLitePreview0617),
903 "gemini-2.5-flash-lite-preview-09-2025" => Ok(Self::Gemini25FlashLitePreview092025),
904 "gemini-2.5-flash-preview-04-17" => Ok(Self::Gemini25FlashPreview0417),
905 "gemini-2.5-flash-preview-05-20" => Ok(Self::Gemini25FlashPreview0520),
906 "gemini-2.5-flash-preview-09-2025" => Ok(Self::Gemini25FlashPreview092025),
907 "gemini-2.5-pro" => Ok(Self::Gemini25Pro),
908 "gemini-2.5-pro-preview-05-06" => Ok(Self::Gemini25ProPreview0506),
909 "gemini-2.5-pro-preview-06-05" => Ok(Self::Gemini25ProPreview0605),
910 "gemini-3-flash-preview" => Ok(Self::Gemini3FlashPreview),
911 "gemini-3-pro-preview" => Ok(Self::Gemini3ProPreview),
912 "gemini-3.1-flash-lite" => Ok(Self::Gemini31FlashLite),
913 "gemini-3.1-flash-lite-preview" => Ok(Self::Gemini31FlashLitePreview),
914 "gemini-3.1-pro-preview" => Ok(Self::Gemini31ProPreview),
915 "gemini-3.1-pro-preview-customtools" => Ok(Self::Gemini31ProPreviewCustomtools),
916 "gemini-live-2.5-flash" => Ok(Self::GeminiLive25Flash),
917 "gemini-live-2.5-flash-preview-native-audio" => Ok(Self::GeminiLive25FlashPreviewNativeAudio),
918 "gemma-3-27b-it" => Ok(Self::Gemma327bIt),
919 "gemma-4-26b-a4b-it" => Ok(Self::Gemma426bA4bIt),
920 "gemma-4-31b-it" => Ok(Self::Gemma431bIt),
921 _ => Err(format!("Unknown gemini model: '{s}'")),
922 }
923 }
924}
925
926impl MoonshotModel {
927 #[allow(clippy::too_many_lines)]
928 fn model_id(self) -> &'static str {
929 match self {
930 Self::KimiK20711Preview => "kimi-k2-0711-preview",
931 Self::KimiK20905Preview => "kimi-k2-0905-preview",
932 Self::KimiK2Thinking => "kimi-k2-thinking",
933 Self::KimiK2ThinkingTurbo => "kimi-k2-thinking-turbo",
934 Self::KimiK2TurboPreview => "kimi-k2-turbo-preview",
935 Self::KimiK25 => "kimi-k2.5",
936 Self::KimiK26 => "kimi-k2.6",
937 }
938 }
939
940 #[allow(clippy::too_many_lines)]
941 fn display_name(self) -> &'static str {
942 match self {
943 Self::KimiK20711Preview => "Kimi K2 0711",
944 Self::KimiK20905Preview => "Kimi K2 0905",
945 Self::KimiK2Thinking => "Kimi K2 Thinking",
946 Self::KimiK2ThinkingTurbo => "Kimi K2 Thinking Turbo",
947 Self::KimiK2TurboPreview => "Kimi K2 Turbo",
948 Self::KimiK25 => "Kimi K2.5",
949 Self::KimiK26 => "Kimi K2.6",
950 }
951 }
952
953 fn context_window(self) -> u32 {
954 match self {
955 Self::KimiK20711Preview => 131_072,
956 Self::KimiK20905Preview | Self::KimiK2Thinking | Self::KimiK2ThinkingTurbo | Self::KimiK2TurboPreview | Self::KimiK25 | Self::KimiK26 => 262_144,
957 }
958 }
959
960 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
961 match self {
962 Self::KimiK20711Preview | Self::KimiK20905Preview | Self::KimiK2TurboPreview => &[],
963 Self::KimiK2Thinking | Self::KimiK2ThinkingTurbo | Self::KimiK25 | Self::KimiK26 => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High],
964 }
965 }
966
967 pub fn supports_reasoning(self) -> bool {
968 !self.reasoning_levels().is_empty()
969 }
970
971 pub fn supports_image(self) -> bool {
972 match self {
973 Self::KimiK20711Preview | Self::KimiK20905Preview | Self::KimiK2Thinking | Self::KimiK2ThinkingTurbo | Self::KimiK2TurboPreview => false,
974 Self::KimiK25 | Self::KimiK26 => true,
975 }
976 }
977
978 pub fn supports_audio(self) -> bool {
979 match self {
980 Self::KimiK20711Preview | Self::KimiK20905Preview | Self::KimiK2Thinking | Self::KimiK2ThinkingTurbo | Self::KimiK2TurboPreview | Self::KimiK25 | Self::KimiK26 => false,
981 }
982 }
983
984 const ALL: &[MoonshotModel] = &[
985 Self::KimiK20711Preview,
986 Self::KimiK20905Preview,
987 Self::KimiK2Thinking,
988 Self::KimiK2ThinkingTurbo,
989 Self::KimiK2TurboPreview,
990 Self::KimiK25,
991 Self::KimiK26,
992 ];
993}
994
995impl std::str::FromStr for MoonshotModel {
996 type Err = String;
997
998 #[allow(clippy::too_many_lines)]
999 fn from_str(s: &str) -> Result<Self, Self::Err> {
1000 match s {
1001 "kimi-k2-0711-preview" => Ok(Self::KimiK20711Preview),
1002 "kimi-k2-0905-preview" => Ok(Self::KimiK20905Preview),
1003 "kimi-k2-thinking" => Ok(Self::KimiK2Thinking),
1004 "kimi-k2-thinking-turbo" => Ok(Self::KimiK2ThinkingTurbo),
1005 "kimi-k2-turbo-preview" => Ok(Self::KimiK2TurboPreview),
1006 "kimi-k2.5" => Ok(Self::KimiK25),
1007 "kimi-k2.6" => Ok(Self::KimiK26),
1008 _ => Err(format!("Unknown moonshot model: '{s}'")),
1009 }
1010 }
1011}
1012
1013impl OpenaiModel {
1014 #[allow(clippy::too_many_lines)]
1015 fn model_id(self) -> &'static str {
1016 match self {
1017 Self::Gpt4 => "gpt-4",
1018 Self::Gpt4Turbo => "gpt-4-turbo",
1019 Self::Gpt41 => "gpt-4.1",
1020 Self::Gpt41Mini => "gpt-4.1-mini",
1021 Self::Gpt41Nano => "gpt-4.1-nano",
1022 Self::Gpt4o => "gpt-4o",
1023 Self::Gpt4o20240513 => "gpt-4o-2024-05-13",
1024 Self::Gpt4o20240806 => "gpt-4o-2024-08-06",
1025 Self::Gpt4o20241120 => "gpt-4o-2024-11-20",
1026 Self::Gpt4oMini => "gpt-4o-mini",
1027 Self::Gpt5 => "gpt-5",
1028 Self::Gpt5Codex => "gpt-5-codex",
1029 Self::Gpt5Mini => "gpt-5-mini",
1030 Self::Gpt5Nano => "gpt-5-nano",
1031 Self::Gpt5Pro => "gpt-5-pro",
1032 Self::Gpt51 => "gpt-5.1",
1033 Self::Gpt51Codex => "gpt-5.1-codex",
1034 Self::Gpt51CodexMax => "gpt-5.1-codex-max",
1035 Self::Gpt51CodexMini => "gpt-5.1-codex-mini",
1036 Self::Gpt52 => "gpt-5.2",
1037 Self::Gpt52Codex => "gpt-5.2-codex",
1038 Self::Gpt52Pro => "gpt-5.2-pro",
1039 Self::Gpt53Codex => "gpt-5.3-codex",
1040 Self::Gpt53CodexSpark => "gpt-5.3-codex-spark",
1041 Self::Gpt54 => "gpt-5.4",
1042 Self::Gpt54Mini => "gpt-5.4-mini",
1043 Self::Gpt54Nano => "gpt-5.4-nano",
1044 Self::Gpt54Pro => "gpt-5.4-pro",
1045 Self::Gpt55 => "gpt-5.5",
1046 Self::Gpt55Pro => "gpt-5.5-pro",
1047 Self::O1 => "o1",
1048 Self::O1Pro => "o1-pro",
1049 Self::O3 => "o3",
1050 Self::O3DeepResearch => "o3-deep-research",
1051 Self::O3Mini => "o3-mini",
1052 Self::O3Pro => "o3-pro",
1053 Self::O4Mini => "o4-mini",
1054 Self::O4MiniDeepResearch => "o4-mini-deep-research",
1055 }
1056 }
1057
1058 #[allow(clippy::too_many_lines)]
1059 fn display_name(self) -> &'static str {
1060 match self {
1061 Self::Gpt4 => "GPT-4",
1062 Self::Gpt4Turbo => "GPT-4 Turbo",
1063 Self::Gpt41 => "GPT-4.1",
1064 Self::Gpt41Mini => "GPT-4.1 mini",
1065 Self::Gpt41Nano => "GPT-4.1 nano",
1066 Self::Gpt4o => "GPT-4o",
1067 Self::Gpt4o20240513 => "GPT-4o (2024-05-13)",
1068 Self::Gpt4o20240806 => "GPT-4o (2024-08-06)",
1069 Self::Gpt4o20241120 => "GPT-4o (2024-11-20)",
1070 Self::Gpt4oMini => "GPT-4o mini",
1071 Self::Gpt5 => "GPT-5",
1072 Self::Gpt5Mini => "GPT-5 Mini",
1073 Self::Gpt5Nano => "GPT-5 Nano",
1074 Self::Gpt5Pro => "GPT-5 Pro",
1075 Self::Gpt5Codex => "GPT-5-Codex",
1076 Self::Gpt51 => "GPT-5.1",
1077 Self::Gpt51Codex => "GPT-5.1 Codex",
1078 Self::Gpt51CodexMax => "GPT-5.1 Codex Max",
1079 Self::Gpt51CodexMini => "GPT-5.1 Codex mini",
1080 Self::Gpt52 => "GPT-5.2",
1081 Self::Gpt52Codex => "GPT-5.2 Codex",
1082 Self::Gpt52Pro => "GPT-5.2 Pro",
1083 Self::Gpt53Codex => "GPT-5.3 Codex",
1084 Self::Gpt53CodexSpark => "GPT-5.3 Codex Spark",
1085 Self::Gpt54 => "GPT-5.4",
1086 Self::Gpt54Pro => "GPT-5.4 Pro",
1087 Self::Gpt54Mini => "GPT-5.4 mini",
1088 Self::Gpt54Nano => "GPT-5.4 nano",
1089 Self::Gpt55 => "GPT-5.5",
1090 Self::Gpt55Pro => "GPT-5.5 Pro",
1091 Self::O1 => "o1",
1092 Self::O1Pro => "o1-pro",
1093 Self::O3 => "o3",
1094 Self::O3DeepResearch => "o3-deep-research",
1095 Self::O3Mini => "o3-mini",
1096 Self::O3Pro => "o3-pro",
1097 Self::O4Mini => "o4-mini",
1098 Self::O4MiniDeepResearch => "o4-mini-deep-research",
1099 }
1100 }
1101
1102 fn context_window(self) -> u32 {
1103 match self {
1104 Self::Gpt41 | Self::Gpt41Mini | Self::Gpt41Nano => 1_047_576,
1105 Self::Gpt54 | Self::Gpt54Pro | Self::Gpt55 | Self::Gpt55Pro => 1_050_000,
1106 Self::Gpt4Turbo | Self::Gpt4o | Self::Gpt4o20240513 | Self::Gpt4o20240806 | Self::Gpt4o20241120 | Self::Gpt4oMini | Self::Gpt53CodexSpark => 128_000,
1107 Self::O1 | Self::O1Pro | Self::O3 | Self::O3DeepResearch | Self::O3Mini | Self::O3Pro | Self::O4Mini | Self::O4MiniDeepResearch => 200_000,
1108 Self::Gpt5 | Self::Gpt5Codex | Self::Gpt5Mini | Self::Gpt5Nano | Self::Gpt5Pro | Self::Gpt51 | Self::Gpt51Codex | Self::Gpt51CodexMax | Self::Gpt51CodexMini | Self::Gpt52 | Self::Gpt52Codex | Self::Gpt52Pro | Self::Gpt53Codex | Self::Gpt54Mini | Self::Gpt54Nano => 400_000,
1109 Self::Gpt4 => 8192,
1110 }
1111 }
1112
1113 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
1114 match self {
1115 Self::Gpt4 | Self::Gpt4Turbo | Self::Gpt41 | Self::Gpt41Mini | Self::Gpt41Nano | Self::Gpt4o | Self::Gpt4o20240513 | Self::Gpt4o20240806 | Self::Gpt4o20241120 | Self::Gpt4oMini => &[],
1116 Self::Gpt5 | Self::Gpt5Codex | Self::Gpt5Mini | Self::Gpt5Nano | Self::Gpt5Pro | Self::Gpt51 | Self::Gpt51Codex | Self::Gpt51CodexMax | Self::Gpt51CodexMini | Self::Gpt52 | Self::Gpt52Codex | Self::Gpt52Pro | Self::Gpt53Codex | Self::Gpt53CodexSpark | Self::Gpt54 | Self::Gpt54Mini | Self::Gpt54Nano | Self::Gpt54Pro | Self::Gpt55 | Self::Gpt55Pro | Self::O1 | Self::O1Pro | Self::O3 | Self::O3DeepResearch | Self::O3Mini | Self::O3Pro | Self::O4Mini | Self::O4MiniDeepResearch => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High],
1117 }
1118 }
1119
1120 pub fn supports_reasoning(self) -> bool {
1121 !self.reasoning_levels().is_empty()
1122 }
1123
1124 pub fn supports_image(self) -> bool {
1125 match self {
1126 Self::Gpt4 | Self::O3Mini => false,
1127 Self::Gpt4Turbo | Self::Gpt41 | Self::Gpt41Mini | Self::Gpt41Nano | Self::Gpt4o | Self::Gpt4o20240513 | Self::Gpt4o20240806 | Self::Gpt4o20241120 | Self::Gpt4oMini | Self::Gpt5 | Self::Gpt5Codex | Self::Gpt5Mini | Self::Gpt5Nano | Self::Gpt5Pro | Self::Gpt51 | Self::Gpt51Codex | Self::Gpt51CodexMax | Self::Gpt51CodexMini | Self::Gpt52 | Self::Gpt52Codex | Self::Gpt52Pro | Self::Gpt53Codex | Self::Gpt53CodexSpark | Self::Gpt54 | Self::Gpt54Mini | Self::Gpt54Nano | Self::Gpt54Pro | Self::Gpt55 | Self::Gpt55Pro | Self::O1 | Self::O1Pro | Self::O3 | Self::O3DeepResearch | Self::O3Pro | Self::O4Mini | Self::O4MiniDeepResearch => true,
1128 }
1129 }
1130
1131 pub fn supports_audio(self) -> bool {
1132 match self {
1133 Self::Gpt4 | Self::Gpt4Turbo | Self::Gpt41 | Self::Gpt41Mini | Self::Gpt41Nano | Self::Gpt4o | Self::Gpt4o20240513 | Self::Gpt4o20240806 | Self::Gpt4o20241120 | Self::Gpt4oMini | Self::Gpt5 | Self::Gpt5Codex | Self::Gpt5Mini | Self::Gpt5Nano | Self::Gpt5Pro | Self::Gpt51 | Self::Gpt51Codex | Self::Gpt51CodexMax | Self::Gpt51CodexMini | Self::Gpt52 | Self::Gpt52Codex | Self::Gpt52Pro | Self::Gpt53Codex | Self::Gpt53CodexSpark | Self::Gpt54 | Self::Gpt54Mini | Self::Gpt54Nano | Self::Gpt54Pro | Self::Gpt55 | Self::Gpt55Pro | Self::O1 | Self::O1Pro | Self::O3 | Self::O3DeepResearch | Self::O3Mini | Self::O3Pro | Self::O4Mini | Self::O4MiniDeepResearch => false,
1134 }
1135 }
1136
1137 const ALL: &[OpenaiModel] = &[
1138 Self::Gpt4,
1139 Self::Gpt4Turbo,
1140 Self::Gpt41,
1141 Self::Gpt41Mini,
1142 Self::Gpt41Nano,
1143 Self::Gpt4o,
1144 Self::Gpt4o20240513,
1145 Self::Gpt4o20240806,
1146 Self::Gpt4o20241120,
1147 Self::Gpt4oMini,
1148 Self::Gpt5,
1149 Self::Gpt5Codex,
1150 Self::Gpt5Mini,
1151 Self::Gpt5Nano,
1152 Self::Gpt5Pro,
1153 Self::Gpt51,
1154 Self::Gpt51Codex,
1155 Self::Gpt51CodexMax,
1156 Self::Gpt51CodexMini,
1157 Self::Gpt52,
1158 Self::Gpt52Codex,
1159 Self::Gpt52Pro,
1160 Self::Gpt53Codex,
1161 Self::Gpt53CodexSpark,
1162 Self::Gpt54,
1163 Self::Gpt54Mini,
1164 Self::Gpt54Nano,
1165 Self::Gpt54Pro,
1166 Self::Gpt55,
1167 Self::Gpt55Pro,
1168 Self::O1,
1169 Self::O1Pro,
1170 Self::O3,
1171 Self::O3DeepResearch,
1172 Self::O3Mini,
1173 Self::O3Pro,
1174 Self::O4Mini,
1175 Self::O4MiniDeepResearch,
1176 ];
1177}
1178
1179impl std::str::FromStr for OpenaiModel {
1180 type Err = String;
1181
1182 #[allow(clippy::too_many_lines)]
1183 fn from_str(s: &str) -> Result<Self, Self::Err> {
1184 match s {
1185 "gpt-4" => Ok(Self::Gpt4),
1186 "gpt-4-turbo" => Ok(Self::Gpt4Turbo),
1187 "gpt-4.1" => Ok(Self::Gpt41),
1188 "gpt-4.1-mini" => Ok(Self::Gpt41Mini),
1189 "gpt-4.1-nano" => Ok(Self::Gpt41Nano),
1190 "gpt-4o" => Ok(Self::Gpt4o),
1191 "gpt-4o-2024-05-13" => Ok(Self::Gpt4o20240513),
1192 "gpt-4o-2024-08-06" => Ok(Self::Gpt4o20240806),
1193 "gpt-4o-2024-11-20" => Ok(Self::Gpt4o20241120),
1194 "gpt-4o-mini" => Ok(Self::Gpt4oMini),
1195 "gpt-5" => Ok(Self::Gpt5),
1196 "gpt-5-codex" => Ok(Self::Gpt5Codex),
1197 "gpt-5-mini" => Ok(Self::Gpt5Mini),
1198 "gpt-5-nano" => Ok(Self::Gpt5Nano),
1199 "gpt-5-pro" => Ok(Self::Gpt5Pro),
1200 "gpt-5.1" => Ok(Self::Gpt51),
1201 "gpt-5.1-codex" => Ok(Self::Gpt51Codex),
1202 "gpt-5.1-codex-max" => Ok(Self::Gpt51CodexMax),
1203 "gpt-5.1-codex-mini" => Ok(Self::Gpt51CodexMini),
1204 "gpt-5.2" => Ok(Self::Gpt52),
1205 "gpt-5.2-codex" => Ok(Self::Gpt52Codex),
1206 "gpt-5.2-pro" => Ok(Self::Gpt52Pro),
1207 "gpt-5.3-codex" => Ok(Self::Gpt53Codex),
1208 "gpt-5.3-codex-spark" => Ok(Self::Gpt53CodexSpark),
1209 "gpt-5.4" => Ok(Self::Gpt54),
1210 "gpt-5.4-mini" => Ok(Self::Gpt54Mini),
1211 "gpt-5.4-nano" => Ok(Self::Gpt54Nano),
1212 "gpt-5.4-pro" => Ok(Self::Gpt54Pro),
1213 "gpt-5.5" => Ok(Self::Gpt55),
1214 "gpt-5.5-pro" => Ok(Self::Gpt55Pro),
1215 "o1" => Ok(Self::O1),
1216 "o1-pro" => Ok(Self::O1Pro),
1217 "o3" => Ok(Self::O3),
1218 "o3-deep-research" => Ok(Self::O3DeepResearch),
1219 "o3-mini" => Ok(Self::O3Mini),
1220 "o3-pro" => Ok(Self::O3Pro),
1221 "o4-mini" => Ok(Self::O4Mini),
1222 "o4-mini-deep-research" => Ok(Self::O4MiniDeepResearch),
1223 _ => Err(format!("Unknown openai model: '{s}'")),
1224 }
1225 }
1226}
1227
1228impl OpenRouterModel {
1229 #[allow(clippy::too_many_lines)]
1230 fn model_id(self) -> &'static str {
1231 match self {
1232 Self::AnthropicClaude35Haiku => "anthropic/claude-3.5-haiku",
1233 Self::AnthropicClaude37Sonnet => "anthropic/claude-3.7-sonnet",
1234 Self::AnthropicClaudeHaiku45 => "anthropic/claude-haiku-4.5",
1235 Self::AnthropicClaudeOpus4 => "anthropic/claude-opus-4",
1236 Self::AnthropicClaudeOpus41 => "anthropic/claude-opus-4.1",
1237 Self::AnthropicClaudeOpus45 => "anthropic/claude-opus-4.5",
1238 Self::AnthropicClaudeOpus46 => "anthropic/claude-opus-4.6",
1239 Self::AnthropicClaudeOpus47 => "anthropic/claude-opus-4.7",
1240 Self::AnthropicClaudeSonnet4 => "anthropic/claude-sonnet-4",
1241 Self::AnthropicClaudeSonnet45 => "anthropic/claude-sonnet-4.5",
1242 Self::AnthropicClaudeSonnet46 => "anthropic/claude-sonnet-4.6",
1243 Self::ArceeAiTrinityLargePreviewFree => "arcee-ai/trinity-large-preview:free",
1244 Self::ArceeAiTrinityLargeThinking => "arcee-ai/trinity-large-thinking",
1245 Self::DeepseekDeepseekChatV31 => "deepseek/deepseek-chat-v3.1",
1246 Self::DeepseekDeepseekR1 => "deepseek/deepseek-r1",
1247 Self::DeepseekDeepseekV31Terminus => "deepseek/deepseek-v3.1-terminus",
1248 Self::DeepseekDeepseekV31TerminusExacto => "deepseek/deepseek-v3.1-terminus:exacto",
1249 Self::DeepseekDeepseekV32 => "deepseek/deepseek-v3.2",
1250 Self::DeepseekDeepseekV32Speciale => "deepseek/deepseek-v3.2-speciale",
1251 Self::DeepseekDeepseekV4Flash => "deepseek/deepseek-v4-flash",
1252 Self::DeepseekDeepseekV4Pro => "deepseek/deepseek-v4-pro",
1253 Self::GoogleGemini20Flash001 => "google/gemini-2.0-flash-001",
1254 Self::GoogleGemini25Flash => "google/gemini-2.5-flash",
1255 Self::GoogleGemini25FlashLite => "google/gemini-2.5-flash-lite",
1256 Self::GoogleGemini25FlashLitePreview092025 => "google/gemini-2.5-flash-lite-preview-09-2025",
1257 Self::GoogleGemini25FlashPreview092025 => "google/gemini-2.5-flash-preview-09-2025",
1258 Self::GoogleGemini25Pro => "google/gemini-2.5-pro",
1259 Self::GoogleGemini25ProPreview0506 => "google/gemini-2.5-pro-preview-05-06",
1260 Self::GoogleGemini25ProPreview0605 => "google/gemini-2.5-pro-preview-06-05",
1261 Self::GoogleGemini3FlashPreview => "google/gemini-3-flash-preview",
1262 Self::GoogleGemini3ProPreview => "google/gemini-3-pro-preview",
1263 Self::GoogleGemini31FlashLitePreview => "google/gemini-3.1-flash-lite-preview",
1264 Self::GoogleGemini31ProPreview => "google/gemini-3.1-pro-preview",
1265 Self::GoogleGemini31ProPreviewCustomtools => "google/gemini-3.1-pro-preview-customtools",
1266 Self::GoogleGemma327bIt => "google/gemma-3-27b-it",
1267 Self::GoogleGemma327bItFree => "google/gemma-3-27b-it:free",
1268 Self::GoogleGemma426bA4bIt => "google/gemma-4-26b-a4b-it",
1269 Self::GoogleGemma426bA4bItFree => "google/gemma-4-26b-a4b-it:free",
1270 Self::GoogleGemma431bIt => "google/gemma-4-31b-it",
1271 Self::GoogleGemma431bItFree => "google/gemma-4-31b-it:free",
1272 Self::InceptionMercury2 => "inception/mercury-2",
1273 Self::MetaLlamaLlama3370bInstructFree => "meta-llama/llama-3.3-70b-instruct:free",
1274 Self::MinimaxMinimax01 => "minimax/minimax-01",
1275 Self::MinimaxMinimaxM1 => "minimax/minimax-m1",
1276 Self::MinimaxMinimaxM2 => "minimax/minimax-m2",
1277 Self::MinimaxMinimaxM21 => "minimax/minimax-m2.1",
1278 Self::MinimaxMinimaxM25 => "minimax/minimax-m2.5",
1279 Self::MinimaxMinimaxM25Free => "minimax/minimax-m2.5:free",
1280 Self::MinimaxMinimaxM27 => "minimax/minimax-m2.7",
1281 Self::MistralaiCodestral2508 => "mistralai/codestral-2508",
1282 Self::MistralaiDevstral2512 => "mistralai/devstral-2512",
1283 Self::MistralaiDevstralMedium2507 => "mistralai/devstral-medium-2507",
1284 Self::MistralaiDevstralSmall2505 => "mistralai/devstral-small-2505",
1285 Self::MistralaiDevstralSmall2507 => "mistralai/devstral-small-2507",
1286 Self::MistralaiMistralMedium3 => "mistralai/mistral-medium-3",
1287 Self::MistralaiMistralMedium31 => "mistralai/mistral-medium-3.1",
1288 Self::MistralaiMistralSmall2603 => "mistralai/mistral-small-2603",
1289 Self::MistralaiMistralSmall3124bInstruct => "mistralai/mistral-small-3.1-24b-instruct",
1290 Self::MistralaiMistralSmall3224bInstruct => "mistralai/mistral-small-3.2-24b-instruct",
1291 Self::MoonshotaiKimiK2 => "moonshotai/kimi-k2",
1292 Self::MoonshotaiKimiK20905 => "moonshotai/kimi-k2-0905",
1293 Self::MoonshotaiKimiK20905Exacto => "moonshotai/kimi-k2-0905:exacto",
1294 Self::MoonshotaiKimiK2Thinking => "moonshotai/kimi-k2-thinking",
1295 Self::MoonshotaiKimiK25 => "moonshotai/kimi-k2.5",
1296 Self::MoonshotaiKimiK26 => "moonshotai/kimi-k2.6",
1297 Self::NousresearchHermes4405b => "nousresearch/hermes-4-405b",
1298 Self::NousresearchHermes470b => "nousresearch/hermes-4-70b",
1299 Self::NvidiaNemotron3Nano30bA3bFree => "nvidia/nemotron-3-nano-30b-a3b:free",
1300 Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree => "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free",
1301 Self::NvidiaNemotron3Super120bA12b => "nvidia/nemotron-3-super-120b-a12b",
1302 Self::NvidiaNemotron3Super120bA12bFree => "nvidia/nemotron-3-super-120b-a12b:free",
1303 Self::NvidiaNemotronNano12bV2VlFree => "nvidia/nemotron-nano-12b-v2-vl:free",
1304 Self::NvidiaNemotronNano9bV2 => "nvidia/nemotron-nano-9b-v2",
1305 Self::NvidiaNemotronNano9bV2Free => "nvidia/nemotron-nano-9b-v2:free",
1306 Self::OpenaiGpt41 => "openai/gpt-4.1",
1307 Self::OpenaiGpt41Mini => "openai/gpt-4.1-mini",
1308 Self::OpenaiGpt4oMini => "openai/gpt-4o-mini",
1309 Self::OpenaiGpt5 => "openai/gpt-5",
1310 Self::OpenaiGpt5Codex => "openai/gpt-5-codex",
1311 Self::OpenaiGpt5Image => "openai/gpt-5-image",
1312 Self::OpenaiGpt5Mini => "openai/gpt-5-mini",
1313 Self::OpenaiGpt5Nano => "openai/gpt-5-nano",
1314 Self::OpenaiGpt5Pro => "openai/gpt-5-pro",
1315 Self::OpenaiGpt51 => "openai/gpt-5.1",
1316 Self::OpenaiGpt51Chat => "openai/gpt-5.1-chat",
1317 Self::OpenaiGpt51Codex => "openai/gpt-5.1-codex",
1318 Self::OpenaiGpt51CodexMax => "openai/gpt-5.1-codex-max",
1319 Self::OpenaiGpt51CodexMini => "openai/gpt-5.1-codex-mini",
1320 Self::OpenaiGpt52 => "openai/gpt-5.2",
1321 Self::OpenaiGpt52Chat => "openai/gpt-5.2-chat",
1322 Self::OpenaiGpt52Codex => "openai/gpt-5.2-codex",
1323 Self::OpenaiGpt52Pro => "openai/gpt-5.2-pro",
1324 Self::OpenaiGpt53Codex => "openai/gpt-5.3-codex",
1325 Self::OpenaiGpt54 => "openai/gpt-5.4",
1326 Self::OpenaiGpt54Mini => "openai/gpt-5.4-mini",
1327 Self::OpenaiGpt54Nano => "openai/gpt-5.4-nano",
1328 Self::OpenaiGpt54Pro => "openai/gpt-5.4-pro",
1329 Self::OpenaiGpt55 => "openai/gpt-5.5",
1330 Self::OpenaiGpt55Pro => "openai/gpt-5.5-pro",
1331 Self::OpenaiGptOss120b => "openai/gpt-oss-120b",
1332 Self::OpenaiGptOss120bExacto => "openai/gpt-oss-120b:exacto",
1333 Self::OpenaiGptOss120bFree => "openai/gpt-oss-120b:free",
1334 Self::OpenaiGptOss20b => "openai/gpt-oss-20b",
1335 Self::OpenaiGptOss20bFree => "openai/gpt-oss-20b:free",
1336 Self::OpenaiGptOssSafeguard20b => "openai/gpt-oss-safeguard-20b",
1337 Self::OpenaiO4Mini => "openai/o4-mini",
1338 Self::OpenrouterElephantAlpha => "openrouter/elephant-alpha",
1339 Self::OpenrouterFree => "openrouter/free",
1340 Self::OpenrouterOwlAlpha => "openrouter/owl-alpha",
1341 Self::OpenrouterParetoCode => "openrouter/pareto-code",
1342 Self::PoolsideLagunaM1Free => "poolside/laguna-m.1:free",
1343 Self::PoolsideLagunaXs2Free => "poolside/laguna-xs.2:free",
1344 Self::PrimeIntellectIntellect3 => "prime-intellect/intellect-3",
1345 Self::QwenQwen3627b => "qwen/qwen-3.6-27b",
1346 Self::QwenQwenPlus => "qwen/qwen-plus",
1347 Self::QwenQwen3235bA22b0725 => "qwen/qwen3-235b-a22b-07-25",
1348 Self::QwenQwen3235bA22bThinking2507 => "qwen/qwen3-235b-a22b-thinking-2507",
1349 Self::QwenQwen330bA3bInstruct2507 => "qwen/qwen3-30b-a3b-instruct-2507",
1350 Self::QwenQwen330bA3bThinking2507 => "qwen/qwen3-30b-a3b-thinking-2507",
1351 Self::QwenQwen3Coder => "qwen/qwen3-coder",
1352 Self::QwenQwen3Coder30bA3bInstruct => "qwen/qwen3-coder-30b-a3b-instruct",
1353 Self::QwenQwen3CoderFlash => "qwen/qwen3-coder-flash",
1354 Self::QwenQwen3CoderPlus => "qwen/qwen3-coder-plus",
1355 Self::QwenQwen3CoderExacto => "qwen/qwen3-coder:exacto",
1356 Self::QwenQwen3Max => "qwen/qwen3-max",
1357 Self::QwenQwen3Next80bA3bInstruct => "qwen/qwen3-next-80b-a3b-instruct",
1358 Self::QwenQwen3Next80bA3bThinking => "qwen/qwen3-next-80b-a3b-thinking",
1359 Self::QwenQwen35397bA17b => "qwen/qwen3.5-397b-a17b",
1360 Self::QwenQwen35Flash0223 => "qwen/qwen3.5-flash-02-23",
1361 Self::QwenQwen35Plus0215 => "qwen/qwen3.5-plus-02-15",
1362 Self::QwenQwen36Plus => "qwen/qwen3.6-plus",
1363 Self::StepfunStep35Flash => "stepfun/step-3.5-flash",
1364 Self::TencentHy3Preview => "tencent/hy3-preview",
1365 Self::XAiGrok3 => "x-ai/grok-3",
1366 Self::XAiGrok3Beta => "x-ai/grok-3-beta",
1367 Self::XAiGrok3Mini => "x-ai/grok-3-mini",
1368 Self::XAiGrok3MiniBeta => "x-ai/grok-3-mini-beta",
1369 Self::XAiGrok4 => "x-ai/grok-4",
1370 Self::XAiGrok4Fast => "x-ai/grok-4-fast",
1371 Self::XAiGrok41Fast => "x-ai/grok-4.1-fast",
1372 Self::XAiGrok420Beta => "x-ai/grok-4.20-beta",
1373 Self::XAiGrok43 => "x-ai/grok-4.3",
1374 Self::XAiGrokCodeFast1 => "x-ai/grok-code-fast-1",
1375 Self::XiaomiMimoV2Flash => "xiaomi/mimo-v2-flash",
1376 Self::XiaomiMimoV2Omni => "xiaomi/mimo-v2-omni",
1377 Self::XiaomiMimoV2Pro => "xiaomi/mimo-v2-pro",
1378 Self::XiaomiMimoV25 => "xiaomi/mimo-v2.5",
1379 Self::XiaomiMimoV25Pro => "xiaomi/mimo-v2.5-pro",
1380 Self::ZAiGlm45 => "z-ai/glm-4.5",
1381 Self::ZAiGlm45Air => "z-ai/glm-4.5-air",
1382 Self::ZAiGlm45v => "z-ai/glm-4.5v",
1383 Self::ZAiGlm46 => "z-ai/glm-4.6",
1384 Self::ZAiGlm46Exacto => "z-ai/glm-4.6:exacto",
1385 Self::ZAiGlm47 => "z-ai/glm-4.7",
1386 Self::ZAiGlm47Flash => "z-ai/glm-4.7-flash",
1387 Self::ZAiGlm5 => "z-ai/glm-5",
1388 Self::ZAiGlm5Turbo => "z-ai/glm-5-turbo",
1389 Self::ZAiGlm51 => "z-ai/glm-5.1",
1390 }
1391 }
1392
1393 #[allow(clippy::too_many_lines)]
1394 fn display_name(self) -> &'static str {
1395 match self {
1396 Self::AnthropicClaude35Haiku => "Claude Haiku 3.5",
1397 Self::AnthropicClaudeHaiku45 => "Claude Haiku 4.5",
1398 Self::AnthropicClaudeOpus4 => "Claude Opus 4",
1399 Self::AnthropicClaudeOpus41 => "Claude Opus 4.1",
1400 Self::AnthropicClaudeOpus45 => "Claude Opus 4.5",
1401 Self::AnthropicClaudeOpus46 => "Claude Opus 4.6",
1402 Self::AnthropicClaudeOpus47 => "Claude Opus 4.7",
1403 Self::AnthropicClaude37Sonnet => "Claude Sonnet 3.7",
1404 Self::AnthropicClaudeSonnet4 => "Claude Sonnet 4",
1405 Self::AnthropicClaudeSonnet45 => "Claude Sonnet 4.5",
1406 Self::AnthropicClaudeSonnet46 => "Claude Sonnet 4.6",
1407 Self::MistralaiCodestral2508 => "Codestral 2508",
1408 Self::DeepseekDeepseekV31Terminus => "DeepSeek V3.1 Terminus",
1409 Self::DeepseekDeepseekV31TerminusExacto => "DeepSeek V3.1 Terminus (exacto)",
1410 Self::DeepseekDeepseekV32 => "DeepSeek V3.2",
1411 Self::DeepseekDeepseekV32Speciale => "DeepSeek V3.2 Speciale",
1412 Self::DeepseekDeepseekV4Flash => "DeepSeek V4 Flash",
1413 Self::DeepseekDeepseekV4Pro => "DeepSeek V4 Pro",
1414 Self::DeepseekDeepseekChatV31 => "DeepSeek-V3.1",
1415 Self::DeepseekDeepseekR1 => "DeepSeek: R1",
1416 Self::MistralaiDevstral2512 => "Devstral 2 2512",
1417 Self::MistralaiDevstralMedium2507 => "Devstral Medium",
1418 Self::MistralaiDevstralSmall2505 => "Devstral Small",
1419 Self::MistralaiDevstralSmall2507 => "Devstral Small 1.1",
1420 Self::OpenrouterElephantAlpha => "Elephant (free)",
1421 Self::OpenrouterFree => "Free Models Router",
1422 Self::ZAiGlm45 => "GLM 4.5",
1423 Self::ZAiGlm45Air => "GLM 4.5 Air",
1424 Self::ZAiGlm45v => "GLM 4.5V",
1425 Self::ZAiGlm46 => "GLM 4.6",
1426 Self::ZAiGlm46Exacto => "GLM 4.6 (exacto)",
1427 Self::ZAiGlm47 => "GLM-4.7",
1428 Self::ZAiGlm47Flash => "GLM-4.7-Flash",
1429 Self::ZAiGlm5 => "GLM-5",
1430 Self::ZAiGlm5Turbo => "GLM-5-Turbo",
1431 Self::ZAiGlm51 => "GLM-5.1",
1432 Self::OpenaiGptOss120b => "GPT OSS 120B",
1433 Self::OpenaiGptOss120bExacto => "GPT OSS 120B (exacto)",
1434 Self::OpenaiGptOss20b => "GPT OSS 20B",
1435 Self::OpenaiGptOssSafeguard20b => "GPT OSS Safeguard 20B",
1436 Self::OpenaiGpt41 => "GPT-4.1",
1437 Self::OpenaiGpt41Mini => "GPT-4.1 Mini",
1438 Self::OpenaiGpt4oMini => "GPT-4o-mini",
1439 Self::OpenaiGpt5 => "GPT-5",
1440 Self::OpenaiGpt5Codex => "GPT-5 Codex",
1441 Self::OpenaiGpt5Image => "GPT-5 Image",
1442 Self::OpenaiGpt5Mini => "GPT-5 Mini",
1443 Self::OpenaiGpt5Nano => "GPT-5 Nano",
1444 Self::OpenaiGpt5Pro => "GPT-5 Pro",
1445 Self::OpenaiGpt51 => "GPT-5.1",
1446 Self::OpenaiGpt51Chat => "GPT-5.1 Chat",
1447 Self::OpenaiGpt51Codex => "GPT-5.1-Codex",
1448 Self::OpenaiGpt51CodexMax => "GPT-5.1-Codex-Max",
1449 Self::OpenaiGpt51CodexMini => "GPT-5.1-Codex-Mini",
1450 Self::OpenaiGpt52 => "GPT-5.2",
1451 Self::OpenaiGpt52Chat => "GPT-5.2 Chat",
1452 Self::OpenaiGpt52Pro => "GPT-5.2 Pro",
1453 Self::OpenaiGpt52Codex => "GPT-5.2-Codex",
1454 Self::OpenaiGpt53Codex => "GPT-5.3-Codex",
1455 Self::OpenaiGpt54 => "GPT-5.4",
1456 Self::OpenaiGpt54Mini => "GPT-5.4 Mini",
1457 Self::OpenaiGpt54Nano => "GPT-5.4 Nano",
1458 Self::OpenaiGpt54Pro => "GPT-5.4 Pro",
1459 Self::OpenaiGpt55 => "GPT-5.5",
1460 Self::OpenaiGpt55Pro => "GPT-5.5 Pro",
1461 Self::GoogleGemini20Flash001 => "Gemini 2.0 Flash",
1462 Self::GoogleGemini25Flash => "Gemini 2.5 Flash",
1463 Self::GoogleGemini25FlashLite => "Gemini 2.5 Flash Lite",
1464 Self::GoogleGemini25FlashLitePreview092025 => "Gemini 2.5 Flash Lite Preview 09-25",
1465 Self::GoogleGemini25FlashPreview092025 => "Gemini 2.5 Flash Preview 09-25",
1466 Self::GoogleGemini25Pro => "Gemini 2.5 Pro",
1467 Self::GoogleGemini25ProPreview0506 => "Gemini 2.5 Pro Preview 05-06",
1468 Self::GoogleGemini25ProPreview0605 => "Gemini 2.5 Pro Preview 06-05",
1469 Self::GoogleGemini3FlashPreview => "Gemini 3 Flash Preview",
1470 Self::GoogleGemini3ProPreview => "Gemini 3 Pro Preview",
1471 Self::GoogleGemini31FlashLitePreview => "Gemini 3.1 Flash Lite Preview",
1472 Self::GoogleGemini31ProPreview => "Gemini 3.1 Pro Preview",
1473 Self::GoogleGemini31ProPreviewCustomtools => "Gemini 3.1 Pro Preview Custom Tools",
1474 Self::GoogleGemma327bIt => "Gemma 3 27B",
1475 Self::GoogleGemma327bItFree => "Gemma 3 27B (free)",
1476 Self::GoogleGemma426bA4bIt => "Gemma 4 26B A4B",
1477 Self::GoogleGemma426bA4bItFree => "Gemma 4 26B A4B (free)",
1478 Self::GoogleGemma431bIt => "Gemma 4 31B",
1479 Self::GoogleGemma431bItFree => "Gemma 4 31B (free)",
1480 Self::XAiGrok3 => "Grok 3",
1481 Self::XAiGrok3Beta => "Grok 3 Beta",
1482 Self::XAiGrok3Mini => "Grok 3 Mini",
1483 Self::XAiGrok3MiniBeta => "Grok 3 Mini Beta",
1484 Self::XAiGrok4 => "Grok 4",
1485 Self::XAiGrok4Fast => "Grok 4 Fast",
1486 Self::XAiGrok41Fast => "Grok 4.1 Fast",
1487 Self::XAiGrok420Beta => "Grok 4.20 Beta",
1488 Self::XAiGrok43 => "Grok 4.3",
1489 Self::XAiGrokCodeFast1 => "Grok Code Fast 1",
1490 Self::NousresearchHermes4405b => "Hermes 4 405B",
1491 Self::NousresearchHermes470b => "Hermes 4 70B",
1492 Self::TencentHy3Preview => "Hy3 preview",
1493 Self::PrimeIntellectIntellect3 => "Intellect 3",
1494 Self::MoonshotaiKimiK2 => "Kimi K2",
1495 Self::MoonshotaiKimiK20905 => "Kimi K2 Instruct 0905",
1496 Self::MoonshotaiKimiK20905Exacto => "Kimi K2 Instruct 0905 (exacto)",
1497 Self::MoonshotaiKimiK2Thinking => "Kimi K2 Thinking",
1498 Self::MoonshotaiKimiK25 => "Kimi K2.5",
1499 Self::MoonshotaiKimiK26 => "Kimi K2.6",
1500 Self::PoolsideLagunaM1Free => "Laguna M.1",
1501 Self::PoolsideLagunaXs2Free => "Laguna XS.2",
1502 Self::MetaLlamaLlama3370bInstructFree => "Llama 3.3 70B Instruct (free)",
1503 Self::InceptionMercury2 => "Mercury 2",
1504 Self::MinimaxMinimaxM1 => "MiniMax M1",
1505 Self::MinimaxMinimaxM2 => "MiniMax M2",
1506 Self::MinimaxMinimaxM21 => "MiniMax M2.1",
1507 Self::MinimaxMinimaxM25 => "MiniMax M2.5",
1508 Self::MinimaxMinimaxM25Free => "MiniMax M2.5 (free)",
1509 Self::MinimaxMinimaxM27 => "MiniMax M2.7",
1510 Self::MinimaxMinimax01 => "MiniMax-01",
1511 Self::MistralaiMistralMedium3 => "Mistral Medium 3",
1512 Self::MistralaiMistralMedium31 => "Mistral Medium 3.1",
1513 Self::MistralaiMistralSmall3124bInstruct => "Mistral Small 3.1 24B Instruct",
1514 Self::MistralaiMistralSmall3224bInstruct => "Mistral Small 3.2 24B Instruct",
1515 Self::MistralaiMistralSmall2603 => "Mistral Small 4",
1516 Self::NvidiaNemotron3Nano30bA3bFree => "Nemotron 3 Nano 30B A3B (free)",
1517 Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree => "Nemotron 3 Nano Omni (free)",
1518 Self::NvidiaNemotron3Super120bA12b => "Nemotron 3 Super",
1519 Self::NvidiaNemotron3Super120bA12bFree => "Nemotron 3 Super (free)",
1520 Self::NvidiaNemotronNano12bV2VlFree => "Nemotron Nano 12B 2 VL (free)",
1521 Self::NvidiaNemotronNano9bV2Free => "Nemotron Nano 9B V2 (free)",
1522 Self::OpenrouterOwlAlpha => "Owl Alpha",
1523 Self::OpenrouterParetoCode => "Pareto Code Router",
1524 Self::QwenQwen3235bA22b0725 => "Qwen3 235B A22B Instruct 2507",
1525 Self::QwenQwen3235bA22bThinking2507 => "Qwen3 235B A22B Thinking 2507",
1526 Self::QwenQwen330bA3bInstruct2507 => "Qwen3 30B A3B Instruct 2507",
1527 Self::QwenQwen330bA3bThinking2507 => "Qwen3 30B A3B Thinking 2507",
1528 Self::QwenQwen3Coder => "Qwen3 Coder",
1529 Self::QwenQwen3CoderExacto => "Qwen3 Coder (exacto)",
1530 Self::QwenQwen3Coder30bA3bInstruct => "Qwen3 Coder 30B A3B Instruct",
1531 Self::QwenQwen3CoderFlash => "Qwen3 Coder Flash",
1532 Self::QwenQwen3CoderPlus => "Qwen3 Coder Plus",
1533 Self::QwenQwen3Max => "Qwen3 Max",
1534 Self::QwenQwen3Next80bA3bInstruct => "Qwen3 Next 80B A3B Instruct",
1535 Self::QwenQwen3Next80bA3bThinking => "Qwen3 Next 80B A3B Thinking",
1536 Self::QwenQwen35397bA17b => "Qwen3.5 397B A17B",
1537 Self::QwenQwen35Plus0215 => "Qwen3.5 Plus 2026-02-15",
1538 Self::QwenQwen3627b => "Qwen3.6 27B",
1539 Self::QwenQwen36Plus => "Qwen3.6 Plus",
1540 Self::QwenQwenPlus => "Qwen: Qwen-Plus",
1541 Self::QwenQwen35Flash0223 => "Qwen: Qwen3.5-Flash",
1542 Self::StepfunStep35Flash => "Step 3.5 Flash",
1543 Self::ArceeAiTrinityLargePreviewFree => "Trinity Large Preview",
1544 Self::ArceeAiTrinityLargeThinking => "Trinity Large Thinking",
1545 Self::XiaomiMimoV2Flash => "Xiaomi: MiMo-V2-Flash",
1546 Self::XiaomiMimoV2Omni => "Xiaomi: MiMo-V2-Omni",
1547 Self::XiaomiMimoV2Pro => "Xiaomi: MiMo-V2-Pro",
1548 Self::XiaomiMimoV25 => "Xiaomi: MiMo-V2.5",
1549 Self::XiaomiMimoV25Pro => "Xiaomi: MiMo-V2.5-Pro",
1550 Self::OpenaiGptOss120bFree => "gpt-oss-120b (free)",
1551 Self::OpenaiGptOss20bFree => "gpt-oss-20b (free)",
1552 Self::NvidiaNemotronNano9bV2 => "nvidia-nemotron-nano-9b-v2",
1553 Self::OpenaiO4Mini => "o4 Mini",
1554 }
1555 }
1556
1557 fn context_window(self) -> u32 {
1558 match self {
1559 Self::AnthropicClaudeOpus46 | Self::AnthropicClaudeOpus47 | Self::AnthropicClaudeSonnet45 | Self::AnthropicClaudeSonnet46 | Self::MinimaxMinimax01 | Self::MinimaxMinimaxM1 | Self::QwenQwenPlus | Self::QwenQwen3CoderPlus | Self::QwenQwen35Flash0223 | Self::QwenQwen35Plus0215 | Self::QwenQwen36Plus | Self::XAiGrok43 => 1_000_000,
1560 Self::OpenaiGpt41 | Self::OpenaiGpt41Mini => 1_047_576,
1561 Self::DeepseekDeepseekV4Flash | Self::DeepseekDeepseekV4Pro | Self::GoogleGemini20Flash001 | Self::GoogleGemini25Flash | Self::GoogleGemini25FlashLite | Self::GoogleGemini25FlashLitePreview092025 | Self::GoogleGemini25FlashPreview092025 | Self::GoogleGemini25Pro | Self::GoogleGemini25ProPreview0506 | Self::GoogleGemini25ProPreview0605 | Self::GoogleGemini3FlashPreview | Self::GoogleGemini31FlashLitePreview | Self::GoogleGemini31ProPreview | Self::GoogleGemini31ProPreviewCustomtools | Self::XiaomiMimoV2Pro | Self::XiaomiMimoV25 | Self::XiaomiMimoV25Pro => 1_048_576,
1562 Self::OpenrouterOwlAlpha => 1_048_756,
1563 Self::GoogleGemini3ProPreview | Self::OpenaiGpt54 | Self::OpenaiGpt54Pro | Self::OpenaiGpt55 | Self::OpenaiGpt55Pro => 1_050_000,
1564 Self::InceptionMercury2 | Self::MistralaiDevstralSmall2505 | Self::MistralaiMistralSmall3124bInstruct | Self::NvidiaNemotronNano12bV2VlFree | Self::NvidiaNemotronNano9bV2Free | Self::OpenaiGpt4oMini | Self::OpenaiGpt51Chat | Self::OpenaiGpt52Chat | Self::QwenQwen3CoderFlash | Self::ZAiGlm45 | Self::ZAiGlm45Air => 128_000,
1565 Self::ArceeAiTrinityLargePreviewFree | Self::DeepseekDeepseekV31Terminus | Self::DeepseekDeepseekV31TerminusExacto | Self::GoogleGemma327bItFree | Self::MetaLlamaLlama3370bInstructFree | Self::MistralaiDevstralMedium2507 | Self::MistralaiDevstralSmall2507 | Self::MistralaiMistralMedium3 | Self::MoonshotaiKimiK2 | Self::NousresearchHermes4405b | Self::NousresearchHermes470b | Self::NvidiaNemotronNano9bV2 | Self::OpenaiGptOss120b | Self::OpenaiGptOss120bExacto | Self::OpenaiGptOss120bFree | Self::OpenaiGptOss20b | Self::OpenaiGptOss20bFree | Self::OpenaiGptOssSafeguard20b | Self::PoolsideLagunaM1Free | Self::PoolsideLagunaXs2Free | Self::PrimeIntellectIntellect3 | Self::QwenQwen3CoderExacto | Self::XAiGrok3 | Self::XAiGrok3Beta | Self::XAiGrok3Mini | Self::XAiGrok3MiniBeta => 131_072,
1566 Self::QwenQwen3Coder30bA3bInstruct => 160_000,
1567 Self::DeepseekDeepseekChatV31 | Self::DeepseekDeepseekV32 | Self::DeepseekDeepseekV32Speciale => 163_840,
1568 Self::MinimaxMinimaxM2 => 196_600,
1569 Self::AnthropicClaude35Haiku | Self::AnthropicClaude37Sonnet | Self::AnthropicClaudeHaiku45 | Self::AnthropicClaudeOpus4 | Self::AnthropicClaudeOpus41 | Self::AnthropicClaudeOpus45 | Self::AnthropicClaudeSonnet4 | Self::OpenaiO4Mini | Self::OpenrouterFree | Self::OpenrouterParetoCode | Self::ZAiGlm46 | Self::ZAiGlm46Exacto | Self::ZAiGlm47Flash => 200_000,
1570 Self::XAiGrok4Fast | Self::XAiGrok41Fast | Self::XAiGrok420Beta => 2_000_000,
1571 Self::ZAiGlm5 | Self::ZAiGlm5Turbo | Self::ZAiGlm51 => 202_752,
1572 Self::MinimaxMinimaxM21 | Self::MinimaxMinimaxM25 | Self::MinimaxMinimaxM25Free | Self::MinimaxMinimaxM27 | Self::ZAiGlm47 => 204_800,
1573 Self::MistralaiCodestral2508 | Self::NvidiaNemotron3Nano30bA3bFree | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree | Self::StepfunStep35Flash | Self::TencentHy3Preview | Self::XAiGrok4 | Self::XAiGrokCodeFast1 => 256_000,
1574 Self::QwenQwen330bA3bInstruct2507 | Self::QwenQwen330bA3bThinking2507 => 262_000,
1575 Self::ArceeAiTrinityLargeThinking | Self::GoogleGemma426bA4bIt | Self::GoogleGemma426bA4bItFree | Self::GoogleGemma431bIt | Self::GoogleGemma431bItFree | Self::MistralaiDevstral2512 | Self::MistralaiMistralMedium31 | Self::MistralaiMistralSmall2603 | Self::MoonshotaiKimiK20905 | Self::MoonshotaiKimiK20905Exacto | Self::MoonshotaiKimiK2Thinking | Self::MoonshotaiKimiK25 | Self::MoonshotaiKimiK26 | Self::NvidiaNemotron3Super120bA12b | Self::NvidiaNemotron3Super120bA12bFree | Self::OpenrouterElephantAlpha | Self::QwenQwen3627b | Self::QwenQwen3235bA22b0725 | Self::QwenQwen3235bA22bThinking2507 | Self::QwenQwen3Coder | Self::QwenQwen3Max | Self::QwenQwen3Next80bA3bInstruct | Self::QwenQwen3Next80bA3bThinking | Self::QwenQwen35397bA17b | Self::XiaomiMimoV2Flash | Self::XiaomiMimoV2Omni => 262_144,
1576 Self::OpenaiGpt5 | Self::OpenaiGpt5Codex | Self::OpenaiGpt5Image | Self::OpenaiGpt5Mini | Self::OpenaiGpt5Nano | Self::OpenaiGpt5Pro | Self::OpenaiGpt51 | Self::OpenaiGpt51Codex | Self::OpenaiGpt51CodexMax | Self::OpenaiGpt51CodexMini | Self::OpenaiGpt52 | Self::OpenaiGpt52Codex | Self::OpenaiGpt52Pro | Self::OpenaiGpt53Codex | Self::OpenaiGpt54Mini | Self::OpenaiGpt54Nano => 400_000,
1577 Self::DeepseekDeepseekR1 | Self::ZAiGlm45v => 64_000,
1578 Self::GoogleGemma327bIt | Self::MistralaiMistralSmall3224bInstruct => 96_000,
1579 }
1580 }
1581
1582 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
1583 match self {
1584 Self::AnthropicClaude35Haiku | Self::ArceeAiTrinityLargePreviewFree | Self::GoogleGemini20Flash001 | Self::GoogleGemma327bIt | Self::GoogleGemma327bItFree | Self::MetaLlamaLlama3370bInstructFree | Self::MistralaiCodestral2508 | Self::MistralaiDevstral2512 | Self::MistralaiDevstralMedium2507 | Self::MistralaiDevstralSmall2505 | Self::MistralaiDevstralSmall2507 | Self::MistralaiMistralMedium3 | Self::MistralaiMistralMedium31 | Self::MistralaiMistralSmall3124bInstruct | Self::MistralaiMistralSmall3224bInstruct | Self::MoonshotaiKimiK2 | Self::MoonshotaiKimiK20905 | Self::MoonshotaiKimiK20905Exacto | Self::OpenaiGpt41 | Self::OpenaiGpt41Mini | Self::OpenaiGpt4oMini | Self::OpenaiGpt54Nano | Self::QwenQwen3627b | Self::QwenQwenPlus | Self::QwenQwen3235bA22b0725 | Self::QwenQwen330bA3bInstruct2507 | Self::QwenQwen3Coder | Self::QwenQwen3Coder30bA3bInstruct | Self::QwenQwen3CoderFlash | Self::QwenQwen3CoderPlus | Self::QwenQwen3CoderExacto | Self::QwenQwen3Next80bA3bInstruct | Self::XAiGrok3 | Self::XAiGrok3Beta => &[],
1585 Self::AnthropicClaude37Sonnet | Self::AnthropicClaudeHaiku45 | Self::AnthropicClaudeOpus4 | Self::AnthropicClaudeOpus41 | Self::AnthropicClaudeOpus45 | Self::AnthropicClaudeOpus46 | Self::AnthropicClaudeOpus47 | Self::AnthropicClaudeSonnet4 | Self::AnthropicClaudeSonnet45 | Self::AnthropicClaudeSonnet46 | Self::ArceeAiTrinityLargeThinking | Self::DeepseekDeepseekChatV31 | Self::DeepseekDeepseekR1 | Self::DeepseekDeepseekV31Terminus | Self::DeepseekDeepseekV31TerminusExacto | Self::DeepseekDeepseekV32 | Self::DeepseekDeepseekV32Speciale | Self::DeepseekDeepseekV4Flash | Self::DeepseekDeepseekV4Pro | Self::GoogleGemini25Flash | Self::GoogleGemini25FlashLite | Self::GoogleGemini25FlashLitePreview092025 | Self::GoogleGemini25FlashPreview092025 | Self::GoogleGemini25Pro | Self::GoogleGemini25ProPreview0506 | Self::GoogleGemini25ProPreview0605 | Self::GoogleGemini3FlashPreview | Self::GoogleGemini3ProPreview | Self::GoogleGemini31FlashLitePreview | Self::GoogleGemini31ProPreview | Self::GoogleGemini31ProPreviewCustomtools | Self::GoogleGemma426bA4bIt | Self::GoogleGemma426bA4bItFree | Self::GoogleGemma431bIt | Self::GoogleGemma431bItFree | Self::InceptionMercury2 | Self::MinimaxMinimax01 | Self::MinimaxMinimaxM1 | Self::MinimaxMinimaxM2 | Self::MinimaxMinimaxM21 | Self::MinimaxMinimaxM25 | Self::MinimaxMinimaxM25Free | Self::MinimaxMinimaxM27 | Self::MistralaiMistralSmall2603 | Self::MoonshotaiKimiK2Thinking | Self::MoonshotaiKimiK25 | Self::MoonshotaiKimiK26 | Self::NousresearchHermes4405b | Self::NousresearchHermes470b | Self::NvidiaNemotron3Nano30bA3bFree | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree | Self::NvidiaNemotron3Super120bA12b | Self::NvidiaNemotron3Super120bA12bFree | Self::NvidiaNemotronNano12bV2VlFree | Self::NvidiaNemotronNano9bV2 | Self::NvidiaNemotronNano9bV2Free | Self::OpenaiGpt5 | Self::OpenaiGpt5Codex | Self::OpenaiGpt5Image | Self::OpenaiGpt5Mini | Self::OpenaiGpt5Nano | Self::OpenaiGpt5Pro | Self::OpenaiGpt51 | Self::OpenaiGpt51Chat | Self::OpenaiGpt51Codex | Self::OpenaiGpt51CodexMax | Self::OpenaiGpt51CodexMini | Self::OpenaiGpt52 | Self::OpenaiGpt52Chat | Self::OpenaiGpt52Codex | Self::OpenaiGpt52Pro | Self::OpenaiGpt53Codex | Self::OpenaiGpt54 | Self::OpenaiGpt54Mini | Self::OpenaiGpt54Pro | Self::OpenaiGpt55 | Self::OpenaiGpt55Pro | Self::OpenaiGptOss120b | Self::OpenaiGptOss120bExacto | Self::OpenaiGptOss120bFree | Self::OpenaiGptOss20b | Self::OpenaiGptOss20bFree | Self::OpenaiGptOssSafeguard20b | Self::OpenaiO4Mini | Self::OpenrouterElephantAlpha | Self::OpenrouterFree | Self::OpenrouterOwlAlpha | Self::OpenrouterParetoCode | Self::PoolsideLagunaM1Free | Self::PoolsideLagunaXs2Free | Self::PrimeIntellectIntellect3 | Self::QwenQwen3235bA22bThinking2507 | Self::QwenQwen330bA3bThinking2507 | Self::QwenQwen3Max | Self::QwenQwen3Next80bA3bThinking | Self::QwenQwen35397bA17b | Self::QwenQwen35Flash0223 | Self::QwenQwen35Plus0215 | Self::QwenQwen36Plus | Self::StepfunStep35Flash | Self::TencentHy3Preview | Self::XAiGrok3Mini | Self::XAiGrok3MiniBeta | Self::XAiGrok4 | Self::XAiGrok4Fast | Self::XAiGrok41Fast | Self::XAiGrok420Beta | Self::XAiGrok43 | Self::XAiGrokCodeFast1 | Self::XiaomiMimoV2Flash | Self::XiaomiMimoV2Omni | Self::XiaomiMimoV2Pro | Self::XiaomiMimoV25 | Self::XiaomiMimoV25Pro | Self::ZAiGlm45 | Self::ZAiGlm45Air | Self::ZAiGlm45v | Self::ZAiGlm46 | Self::ZAiGlm46Exacto | Self::ZAiGlm47 | Self::ZAiGlm47Flash | Self::ZAiGlm5 | Self::ZAiGlm5Turbo | Self::ZAiGlm51 => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High],
1586 }
1587 }
1588
1589 pub fn supports_reasoning(self) -> bool {
1590 !self.reasoning_levels().is_empty()
1591 }
1592
1593 pub fn supports_image(self) -> bool {
1594 match self {
1595 Self::ArceeAiTrinityLargePreviewFree | Self::ArceeAiTrinityLargeThinking | Self::DeepseekDeepseekChatV31 | Self::DeepseekDeepseekR1 | Self::DeepseekDeepseekV31Terminus | Self::DeepseekDeepseekV31TerminusExacto | Self::DeepseekDeepseekV32 | Self::DeepseekDeepseekV32Speciale | Self::DeepseekDeepseekV4Flash | Self::DeepseekDeepseekV4Pro | Self::InceptionMercury2 | Self::MetaLlamaLlama3370bInstructFree | Self::MinimaxMinimaxM1 | Self::MinimaxMinimaxM2 | Self::MinimaxMinimaxM21 | Self::MinimaxMinimaxM25 | Self::MinimaxMinimaxM25Free | Self::MinimaxMinimaxM27 | Self::MistralaiCodestral2508 | Self::MistralaiDevstral2512 | Self::MistralaiDevstralMedium2507 | Self::MistralaiDevstralSmall2505 | Self::MistralaiDevstralSmall2507 | Self::MoonshotaiKimiK2 | Self::MoonshotaiKimiK20905 | Self::MoonshotaiKimiK20905Exacto | Self::MoonshotaiKimiK2Thinking | Self::NousresearchHermes4405b | Self::NousresearchHermes470b | Self::NvidiaNemotron3Nano30bA3bFree | Self::NvidiaNemotron3Super120bA12b | Self::NvidiaNemotron3Super120bA12bFree | Self::NvidiaNemotronNano9bV2 | Self::NvidiaNemotronNano9bV2Free | Self::OpenaiGptOss120b | Self::OpenaiGptOss120bExacto | Self::OpenaiGptOss120bFree | Self::OpenaiGptOss20b | Self::OpenaiGptOss20bFree | Self::OpenaiGptOssSafeguard20b | Self::OpenrouterElephantAlpha | Self::OpenrouterOwlAlpha | Self::OpenrouterParetoCode | Self::PoolsideLagunaM1Free | Self::PoolsideLagunaXs2Free | Self::PrimeIntellectIntellect3 | Self::QwenQwenPlus | Self::QwenQwen3235bA22b0725 | Self::QwenQwen3235bA22bThinking2507 | Self::QwenQwen330bA3bInstruct2507 | Self::QwenQwen330bA3bThinking2507 | Self::QwenQwen3Coder | Self::QwenQwen3Coder30bA3bInstruct | Self::QwenQwen3CoderFlash | Self::QwenQwen3CoderPlus | Self::QwenQwen3CoderExacto | Self::QwenQwen3Max | Self::QwenQwen3Next80bA3bInstruct | Self::QwenQwen3Next80bA3bThinking | Self::StepfunStep35Flash | Self::TencentHy3Preview | Self::XAiGrok3 | Self::XAiGrok3Beta | Self::XAiGrok3Mini | Self::XAiGrok3MiniBeta | Self::XAiGrok4 | Self::XAiGrokCodeFast1 | Self::XiaomiMimoV2Flash | Self::XiaomiMimoV2Pro | Self::XiaomiMimoV25Pro | Self::ZAiGlm45 | Self::ZAiGlm45Air | Self::ZAiGlm46 | Self::ZAiGlm46Exacto | Self::ZAiGlm47 | Self::ZAiGlm47Flash | Self::ZAiGlm5 | Self::ZAiGlm5Turbo | Self::ZAiGlm51 => false,
1596 Self::AnthropicClaude35Haiku | Self::AnthropicClaude37Sonnet | Self::AnthropicClaudeHaiku45 | Self::AnthropicClaudeOpus4 | Self::AnthropicClaudeOpus41 | Self::AnthropicClaudeOpus45 | Self::AnthropicClaudeOpus46 | Self::AnthropicClaudeOpus47 | Self::AnthropicClaudeSonnet4 | Self::AnthropicClaudeSonnet45 | Self::AnthropicClaudeSonnet46 | Self::GoogleGemini20Flash001 | Self::GoogleGemini25Flash | Self::GoogleGemini25FlashLite | Self::GoogleGemini25FlashLitePreview092025 | Self::GoogleGemini25FlashPreview092025 | Self::GoogleGemini25Pro | Self::GoogleGemini25ProPreview0506 | Self::GoogleGemini25ProPreview0605 | Self::GoogleGemini3FlashPreview | Self::GoogleGemini3ProPreview | Self::GoogleGemini31FlashLitePreview | Self::GoogleGemini31ProPreview | Self::GoogleGemini31ProPreviewCustomtools | Self::GoogleGemma327bIt | Self::GoogleGemma327bItFree | Self::GoogleGemma426bA4bIt | Self::GoogleGemma426bA4bItFree | Self::GoogleGemma431bIt | Self::GoogleGemma431bItFree | Self::MinimaxMinimax01 | Self::MistralaiMistralMedium3 | Self::MistralaiMistralMedium31 | Self::MistralaiMistralSmall2603 | Self::MistralaiMistralSmall3124bInstruct | Self::MistralaiMistralSmall3224bInstruct | Self::MoonshotaiKimiK25 | Self::MoonshotaiKimiK26 | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree | Self::NvidiaNemotronNano12bV2VlFree | Self::OpenaiGpt41 | Self::OpenaiGpt41Mini | Self::OpenaiGpt4oMini | Self::OpenaiGpt5 | Self::OpenaiGpt5Codex | Self::OpenaiGpt5Image | Self::OpenaiGpt5Mini | Self::OpenaiGpt5Nano | Self::OpenaiGpt5Pro | Self::OpenaiGpt51 | Self::OpenaiGpt51Chat | Self::OpenaiGpt51Codex | Self::OpenaiGpt51CodexMax | Self::OpenaiGpt51CodexMini | Self::OpenaiGpt52 | Self::OpenaiGpt52Chat | Self::OpenaiGpt52Codex | Self::OpenaiGpt52Pro | Self::OpenaiGpt53Codex | Self::OpenaiGpt54 | Self::OpenaiGpt54Mini | Self::OpenaiGpt54Nano | Self::OpenaiGpt54Pro | Self::OpenaiGpt55 | Self::OpenaiGpt55Pro | Self::OpenaiO4Mini | Self::OpenrouterFree | Self::QwenQwen3627b | Self::QwenQwen35397bA17b | Self::QwenQwen35Flash0223 | Self::QwenQwen35Plus0215 | Self::QwenQwen36Plus | Self::XAiGrok4Fast | Self::XAiGrok41Fast | Self::XAiGrok420Beta | Self::XAiGrok43 | Self::XiaomiMimoV2Omni | Self::XiaomiMimoV25 | Self::ZAiGlm45v => true,
1597 }
1598 }
1599
1600 pub fn supports_audio(self) -> bool {
1601 match self {
1602 Self::AnthropicClaude35Haiku | Self::AnthropicClaude37Sonnet | Self::AnthropicClaudeHaiku45 | Self::AnthropicClaudeOpus4 | Self::AnthropicClaudeOpus41 | Self::AnthropicClaudeOpus45 | Self::AnthropicClaudeOpus46 | Self::AnthropicClaudeOpus47 | Self::AnthropicClaudeSonnet4 | Self::AnthropicClaudeSonnet45 | Self::AnthropicClaudeSonnet46 | Self::ArceeAiTrinityLargePreviewFree | Self::ArceeAiTrinityLargeThinking | Self::DeepseekDeepseekChatV31 | Self::DeepseekDeepseekR1 | Self::DeepseekDeepseekV31Terminus | Self::DeepseekDeepseekV31TerminusExacto | Self::DeepseekDeepseekV32 | Self::DeepseekDeepseekV32Speciale | Self::DeepseekDeepseekV4Flash | Self::DeepseekDeepseekV4Pro | Self::GoogleGemma327bIt | Self::GoogleGemma327bItFree | Self::GoogleGemma426bA4bIt | Self::GoogleGemma426bA4bItFree | Self::GoogleGemma431bIt | Self::GoogleGemma431bItFree | Self::InceptionMercury2 | Self::MetaLlamaLlama3370bInstructFree | Self::MinimaxMinimax01 | Self::MinimaxMinimaxM1 | Self::MinimaxMinimaxM2 | Self::MinimaxMinimaxM21 | Self::MinimaxMinimaxM25 | Self::MinimaxMinimaxM25Free | Self::MinimaxMinimaxM27 | Self::MistralaiCodestral2508 | Self::MistralaiDevstral2512 | Self::MistralaiDevstralMedium2507 | Self::MistralaiDevstralSmall2505 | Self::MistralaiDevstralSmall2507 | Self::MistralaiMistralMedium3 | Self::MistralaiMistralMedium31 | Self::MistralaiMistralSmall2603 | Self::MistralaiMistralSmall3124bInstruct | Self::MistralaiMistralSmall3224bInstruct | Self::MoonshotaiKimiK2 | Self::MoonshotaiKimiK20905 | Self::MoonshotaiKimiK20905Exacto | Self::MoonshotaiKimiK2Thinking | Self::MoonshotaiKimiK25 | Self::MoonshotaiKimiK26 | Self::NousresearchHermes4405b | Self::NousresearchHermes470b | Self::NvidiaNemotron3Nano30bA3bFree | Self::NvidiaNemotron3Super120bA12b | Self::NvidiaNemotron3Super120bA12bFree | Self::NvidiaNemotronNano12bV2VlFree | Self::NvidiaNemotronNano9bV2 | Self::NvidiaNemotronNano9bV2Free | Self::OpenaiGpt41 | Self::OpenaiGpt41Mini | Self::OpenaiGpt4oMini | Self::OpenaiGpt5 | Self::OpenaiGpt5Codex | Self::OpenaiGpt5Image | Self::OpenaiGpt5Mini | Self::OpenaiGpt5Nano | Self::OpenaiGpt5Pro | Self::OpenaiGpt51 | Self::OpenaiGpt51Chat | Self::OpenaiGpt51Codex | Self::OpenaiGpt51CodexMax | Self::OpenaiGpt51CodexMini | Self::OpenaiGpt52 | Self::OpenaiGpt52Chat | Self::OpenaiGpt52Codex | Self::OpenaiGpt52Pro | Self::OpenaiGpt53Codex | Self::OpenaiGpt54 | Self::OpenaiGpt54Mini | Self::OpenaiGpt54Nano | Self::OpenaiGpt54Pro | Self::OpenaiGpt55 | Self::OpenaiGpt55Pro | Self::OpenaiGptOss120b | Self::OpenaiGptOss120bExacto | Self::OpenaiGptOss120bFree | Self::OpenaiGptOss20b | Self::OpenaiGptOss20bFree | Self::OpenaiGptOssSafeguard20b | Self::OpenaiO4Mini | Self::OpenrouterElephantAlpha | Self::OpenrouterFree | Self::OpenrouterOwlAlpha | Self::OpenrouterParetoCode | Self::PoolsideLagunaM1Free | Self::PoolsideLagunaXs2Free | Self::PrimeIntellectIntellect3 | Self::QwenQwen3627b | Self::QwenQwenPlus | Self::QwenQwen3235bA22b0725 | Self::QwenQwen3235bA22bThinking2507 | Self::QwenQwen330bA3bInstruct2507 | Self::QwenQwen330bA3bThinking2507 | Self::QwenQwen3Coder | Self::QwenQwen3Coder30bA3bInstruct | Self::QwenQwen3CoderFlash | Self::QwenQwen3CoderPlus | Self::QwenQwen3CoderExacto | Self::QwenQwen3Max | Self::QwenQwen3Next80bA3bInstruct | Self::QwenQwen3Next80bA3bThinking | Self::QwenQwen35397bA17b | Self::QwenQwen35Flash0223 | Self::QwenQwen35Plus0215 | Self::QwenQwen36Plus | Self::StepfunStep35Flash | Self::TencentHy3Preview | Self::XAiGrok3 | Self::XAiGrok3Beta | Self::XAiGrok3Mini | Self::XAiGrok3MiniBeta | Self::XAiGrok4 | Self::XAiGrok4Fast | Self::XAiGrok41Fast | Self::XAiGrok420Beta | Self::XAiGrok43 | Self::XAiGrokCodeFast1 | Self::XiaomiMimoV2Flash | Self::XiaomiMimoV2Pro | Self::XiaomiMimoV25Pro | Self::ZAiGlm45 | Self::ZAiGlm45Air | Self::ZAiGlm45v | Self::ZAiGlm46 | Self::ZAiGlm46Exacto | Self::ZAiGlm47 | Self::ZAiGlm47Flash | Self::ZAiGlm5 | Self::ZAiGlm5Turbo | Self::ZAiGlm51 => false,
1603 Self::GoogleGemini20Flash001 | Self::GoogleGemini25Flash | Self::GoogleGemini25FlashLite | Self::GoogleGemini25FlashLitePreview092025 | Self::GoogleGemini25FlashPreview092025 | Self::GoogleGemini25Pro | Self::GoogleGemini25ProPreview0506 | Self::GoogleGemini25ProPreview0605 | Self::GoogleGemini3FlashPreview | Self::GoogleGemini3ProPreview | Self::GoogleGemini31FlashLitePreview | Self::GoogleGemini31ProPreview | Self::GoogleGemini31ProPreviewCustomtools | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree | Self::XiaomiMimoV2Omni | Self::XiaomiMimoV25 => true,
1604 }
1605 }
1606
1607 const ALL: &[OpenRouterModel] = &[
1608 Self::AnthropicClaude35Haiku,
1609 Self::AnthropicClaude37Sonnet,
1610 Self::AnthropicClaudeHaiku45,
1611 Self::AnthropicClaudeOpus4,
1612 Self::AnthropicClaudeOpus41,
1613 Self::AnthropicClaudeOpus45,
1614 Self::AnthropicClaudeOpus46,
1615 Self::AnthropicClaudeOpus47,
1616 Self::AnthropicClaudeSonnet4,
1617 Self::AnthropicClaudeSonnet45,
1618 Self::AnthropicClaudeSonnet46,
1619 Self::ArceeAiTrinityLargePreviewFree,
1620 Self::ArceeAiTrinityLargeThinking,
1621 Self::DeepseekDeepseekChatV31,
1622 Self::DeepseekDeepseekR1,
1623 Self::DeepseekDeepseekV31Terminus,
1624 Self::DeepseekDeepseekV31TerminusExacto,
1625 Self::DeepseekDeepseekV32,
1626 Self::DeepseekDeepseekV32Speciale,
1627 Self::DeepseekDeepseekV4Flash,
1628 Self::DeepseekDeepseekV4Pro,
1629 Self::GoogleGemini20Flash001,
1630 Self::GoogleGemini25Flash,
1631 Self::GoogleGemini25FlashLite,
1632 Self::GoogleGemini25FlashLitePreview092025,
1633 Self::GoogleGemini25FlashPreview092025,
1634 Self::GoogleGemini25Pro,
1635 Self::GoogleGemini25ProPreview0506,
1636 Self::GoogleGemini25ProPreview0605,
1637 Self::GoogleGemini3FlashPreview,
1638 Self::GoogleGemini3ProPreview,
1639 Self::GoogleGemini31FlashLitePreview,
1640 Self::GoogleGemini31ProPreview,
1641 Self::GoogleGemini31ProPreviewCustomtools,
1642 Self::GoogleGemma327bIt,
1643 Self::GoogleGemma327bItFree,
1644 Self::GoogleGemma426bA4bIt,
1645 Self::GoogleGemma426bA4bItFree,
1646 Self::GoogleGemma431bIt,
1647 Self::GoogleGemma431bItFree,
1648 Self::InceptionMercury2,
1649 Self::MetaLlamaLlama3370bInstructFree,
1650 Self::MinimaxMinimax01,
1651 Self::MinimaxMinimaxM1,
1652 Self::MinimaxMinimaxM2,
1653 Self::MinimaxMinimaxM21,
1654 Self::MinimaxMinimaxM25,
1655 Self::MinimaxMinimaxM25Free,
1656 Self::MinimaxMinimaxM27,
1657 Self::MistralaiCodestral2508,
1658 Self::MistralaiDevstral2512,
1659 Self::MistralaiDevstralMedium2507,
1660 Self::MistralaiDevstralSmall2505,
1661 Self::MistralaiDevstralSmall2507,
1662 Self::MistralaiMistralMedium3,
1663 Self::MistralaiMistralMedium31,
1664 Self::MistralaiMistralSmall2603,
1665 Self::MistralaiMistralSmall3124bInstruct,
1666 Self::MistralaiMistralSmall3224bInstruct,
1667 Self::MoonshotaiKimiK2,
1668 Self::MoonshotaiKimiK20905,
1669 Self::MoonshotaiKimiK20905Exacto,
1670 Self::MoonshotaiKimiK2Thinking,
1671 Self::MoonshotaiKimiK25,
1672 Self::MoonshotaiKimiK26,
1673 Self::NousresearchHermes4405b,
1674 Self::NousresearchHermes470b,
1675 Self::NvidiaNemotron3Nano30bA3bFree,
1676 Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree,
1677 Self::NvidiaNemotron3Super120bA12b,
1678 Self::NvidiaNemotron3Super120bA12bFree,
1679 Self::NvidiaNemotronNano12bV2VlFree,
1680 Self::NvidiaNemotronNano9bV2,
1681 Self::NvidiaNemotronNano9bV2Free,
1682 Self::OpenaiGpt41,
1683 Self::OpenaiGpt41Mini,
1684 Self::OpenaiGpt4oMini,
1685 Self::OpenaiGpt5,
1686 Self::OpenaiGpt5Codex,
1687 Self::OpenaiGpt5Image,
1688 Self::OpenaiGpt5Mini,
1689 Self::OpenaiGpt5Nano,
1690 Self::OpenaiGpt5Pro,
1691 Self::OpenaiGpt51,
1692 Self::OpenaiGpt51Chat,
1693 Self::OpenaiGpt51Codex,
1694 Self::OpenaiGpt51CodexMax,
1695 Self::OpenaiGpt51CodexMini,
1696 Self::OpenaiGpt52,
1697 Self::OpenaiGpt52Chat,
1698 Self::OpenaiGpt52Codex,
1699 Self::OpenaiGpt52Pro,
1700 Self::OpenaiGpt53Codex,
1701 Self::OpenaiGpt54,
1702 Self::OpenaiGpt54Mini,
1703 Self::OpenaiGpt54Nano,
1704 Self::OpenaiGpt54Pro,
1705 Self::OpenaiGpt55,
1706 Self::OpenaiGpt55Pro,
1707 Self::OpenaiGptOss120b,
1708 Self::OpenaiGptOss120bExacto,
1709 Self::OpenaiGptOss120bFree,
1710 Self::OpenaiGptOss20b,
1711 Self::OpenaiGptOss20bFree,
1712 Self::OpenaiGptOssSafeguard20b,
1713 Self::OpenaiO4Mini,
1714 Self::OpenrouterElephantAlpha,
1715 Self::OpenrouterFree,
1716 Self::OpenrouterOwlAlpha,
1717 Self::OpenrouterParetoCode,
1718 Self::PoolsideLagunaM1Free,
1719 Self::PoolsideLagunaXs2Free,
1720 Self::PrimeIntellectIntellect3,
1721 Self::QwenQwen3627b,
1722 Self::QwenQwenPlus,
1723 Self::QwenQwen3235bA22b0725,
1724 Self::QwenQwen3235bA22bThinking2507,
1725 Self::QwenQwen330bA3bInstruct2507,
1726 Self::QwenQwen330bA3bThinking2507,
1727 Self::QwenQwen3Coder,
1728 Self::QwenQwen3Coder30bA3bInstruct,
1729 Self::QwenQwen3CoderFlash,
1730 Self::QwenQwen3CoderPlus,
1731 Self::QwenQwen3CoderExacto,
1732 Self::QwenQwen3Max,
1733 Self::QwenQwen3Next80bA3bInstruct,
1734 Self::QwenQwen3Next80bA3bThinking,
1735 Self::QwenQwen35397bA17b,
1736 Self::QwenQwen35Flash0223,
1737 Self::QwenQwen35Plus0215,
1738 Self::QwenQwen36Plus,
1739 Self::StepfunStep35Flash,
1740 Self::TencentHy3Preview,
1741 Self::XAiGrok3,
1742 Self::XAiGrok3Beta,
1743 Self::XAiGrok3Mini,
1744 Self::XAiGrok3MiniBeta,
1745 Self::XAiGrok4,
1746 Self::XAiGrok4Fast,
1747 Self::XAiGrok41Fast,
1748 Self::XAiGrok420Beta,
1749 Self::XAiGrok43,
1750 Self::XAiGrokCodeFast1,
1751 Self::XiaomiMimoV2Flash,
1752 Self::XiaomiMimoV2Omni,
1753 Self::XiaomiMimoV2Pro,
1754 Self::XiaomiMimoV25,
1755 Self::XiaomiMimoV25Pro,
1756 Self::ZAiGlm45,
1757 Self::ZAiGlm45Air,
1758 Self::ZAiGlm45v,
1759 Self::ZAiGlm46,
1760 Self::ZAiGlm46Exacto,
1761 Self::ZAiGlm47,
1762 Self::ZAiGlm47Flash,
1763 Self::ZAiGlm5,
1764 Self::ZAiGlm5Turbo,
1765 Self::ZAiGlm51,
1766 ];
1767}
1768
1769impl std::str::FromStr for OpenRouterModel {
1770 type Err = String;
1771
1772 #[allow(clippy::too_many_lines)]
1773 fn from_str(s: &str) -> Result<Self, Self::Err> {
1774 match s {
1775 "anthropic/claude-3.5-haiku" => Ok(Self::AnthropicClaude35Haiku),
1776 "anthropic/claude-3.7-sonnet" => Ok(Self::AnthropicClaude37Sonnet),
1777 "anthropic/claude-haiku-4.5" => Ok(Self::AnthropicClaudeHaiku45),
1778 "anthropic/claude-opus-4" => Ok(Self::AnthropicClaudeOpus4),
1779 "anthropic/claude-opus-4.1" => Ok(Self::AnthropicClaudeOpus41),
1780 "anthropic/claude-opus-4.5" => Ok(Self::AnthropicClaudeOpus45),
1781 "anthropic/claude-opus-4.6" => Ok(Self::AnthropicClaudeOpus46),
1782 "anthropic/claude-opus-4.7" => Ok(Self::AnthropicClaudeOpus47),
1783 "anthropic/claude-sonnet-4" => Ok(Self::AnthropicClaudeSonnet4),
1784 "anthropic/claude-sonnet-4.5" => Ok(Self::AnthropicClaudeSonnet45),
1785 "anthropic/claude-sonnet-4.6" => Ok(Self::AnthropicClaudeSonnet46),
1786 "arcee-ai/trinity-large-preview:free" => Ok(Self::ArceeAiTrinityLargePreviewFree),
1787 "arcee-ai/trinity-large-thinking" => Ok(Self::ArceeAiTrinityLargeThinking),
1788 "deepseek/deepseek-chat-v3.1" => Ok(Self::DeepseekDeepseekChatV31),
1789 "deepseek/deepseek-r1" => Ok(Self::DeepseekDeepseekR1),
1790 "deepseek/deepseek-v3.1-terminus" => Ok(Self::DeepseekDeepseekV31Terminus),
1791 "deepseek/deepseek-v3.1-terminus:exacto" => Ok(Self::DeepseekDeepseekV31TerminusExacto),
1792 "deepseek/deepseek-v3.2" => Ok(Self::DeepseekDeepseekV32),
1793 "deepseek/deepseek-v3.2-speciale" => Ok(Self::DeepseekDeepseekV32Speciale),
1794 "deepseek/deepseek-v4-flash" => Ok(Self::DeepseekDeepseekV4Flash),
1795 "deepseek/deepseek-v4-pro" => Ok(Self::DeepseekDeepseekV4Pro),
1796 "google/gemini-2.0-flash-001" => Ok(Self::GoogleGemini20Flash001),
1797 "google/gemini-2.5-flash" => Ok(Self::GoogleGemini25Flash),
1798 "google/gemini-2.5-flash-lite" => Ok(Self::GoogleGemini25FlashLite),
1799 "google/gemini-2.5-flash-lite-preview-09-2025" => Ok(Self::GoogleGemini25FlashLitePreview092025),
1800 "google/gemini-2.5-flash-preview-09-2025" => Ok(Self::GoogleGemini25FlashPreview092025),
1801 "google/gemini-2.5-pro" => Ok(Self::GoogleGemini25Pro),
1802 "google/gemini-2.5-pro-preview-05-06" => Ok(Self::GoogleGemini25ProPreview0506),
1803 "google/gemini-2.5-pro-preview-06-05" => Ok(Self::GoogleGemini25ProPreview0605),
1804 "google/gemini-3-flash-preview" => Ok(Self::GoogleGemini3FlashPreview),
1805 "google/gemini-3-pro-preview" => Ok(Self::GoogleGemini3ProPreview),
1806 "google/gemini-3.1-flash-lite-preview" => Ok(Self::GoogleGemini31FlashLitePreview),
1807 "google/gemini-3.1-pro-preview" => Ok(Self::GoogleGemini31ProPreview),
1808 "google/gemini-3.1-pro-preview-customtools" => Ok(Self::GoogleGemini31ProPreviewCustomtools),
1809 "google/gemma-3-27b-it" => Ok(Self::GoogleGemma327bIt),
1810 "google/gemma-3-27b-it:free" => Ok(Self::GoogleGemma327bItFree),
1811 "google/gemma-4-26b-a4b-it" => Ok(Self::GoogleGemma426bA4bIt),
1812 "google/gemma-4-26b-a4b-it:free" => Ok(Self::GoogleGemma426bA4bItFree),
1813 "google/gemma-4-31b-it" => Ok(Self::GoogleGemma431bIt),
1814 "google/gemma-4-31b-it:free" => Ok(Self::GoogleGemma431bItFree),
1815 "inception/mercury-2" => Ok(Self::InceptionMercury2),
1816 "meta-llama/llama-3.3-70b-instruct:free" => Ok(Self::MetaLlamaLlama3370bInstructFree),
1817 "minimax/minimax-01" => Ok(Self::MinimaxMinimax01),
1818 "minimax/minimax-m1" => Ok(Self::MinimaxMinimaxM1),
1819 "minimax/minimax-m2" => Ok(Self::MinimaxMinimaxM2),
1820 "minimax/minimax-m2.1" => Ok(Self::MinimaxMinimaxM21),
1821 "minimax/minimax-m2.5" => Ok(Self::MinimaxMinimaxM25),
1822 "minimax/minimax-m2.5:free" => Ok(Self::MinimaxMinimaxM25Free),
1823 "minimax/minimax-m2.7" => Ok(Self::MinimaxMinimaxM27),
1824 "mistralai/codestral-2508" => Ok(Self::MistralaiCodestral2508),
1825 "mistralai/devstral-2512" => Ok(Self::MistralaiDevstral2512),
1826 "mistralai/devstral-medium-2507" => Ok(Self::MistralaiDevstralMedium2507),
1827 "mistralai/devstral-small-2505" => Ok(Self::MistralaiDevstralSmall2505),
1828 "mistralai/devstral-small-2507" => Ok(Self::MistralaiDevstralSmall2507),
1829 "mistralai/mistral-medium-3" => Ok(Self::MistralaiMistralMedium3),
1830 "mistralai/mistral-medium-3.1" => Ok(Self::MistralaiMistralMedium31),
1831 "mistralai/mistral-small-2603" => Ok(Self::MistralaiMistralSmall2603),
1832 "mistralai/mistral-small-3.1-24b-instruct" => Ok(Self::MistralaiMistralSmall3124bInstruct),
1833 "mistralai/mistral-small-3.2-24b-instruct" => Ok(Self::MistralaiMistralSmall3224bInstruct),
1834 "moonshotai/kimi-k2" => Ok(Self::MoonshotaiKimiK2),
1835 "moonshotai/kimi-k2-0905" => Ok(Self::MoonshotaiKimiK20905),
1836 "moonshotai/kimi-k2-0905:exacto" => Ok(Self::MoonshotaiKimiK20905Exacto),
1837 "moonshotai/kimi-k2-thinking" => Ok(Self::MoonshotaiKimiK2Thinking),
1838 "moonshotai/kimi-k2.5" => Ok(Self::MoonshotaiKimiK25),
1839 "moonshotai/kimi-k2.6" => Ok(Self::MoonshotaiKimiK26),
1840 "nousresearch/hermes-4-405b" => Ok(Self::NousresearchHermes4405b),
1841 "nousresearch/hermes-4-70b" => Ok(Self::NousresearchHermes470b),
1842 "nvidia/nemotron-3-nano-30b-a3b:free" => Ok(Self::NvidiaNemotron3Nano30bA3bFree),
1843 "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free" => Ok(Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree),
1844 "nvidia/nemotron-3-super-120b-a12b" => Ok(Self::NvidiaNemotron3Super120bA12b),
1845 "nvidia/nemotron-3-super-120b-a12b:free" => Ok(Self::NvidiaNemotron3Super120bA12bFree),
1846 "nvidia/nemotron-nano-12b-v2-vl:free" => Ok(Self::NvidiaNemotronNano12bV2VlFree),
1847 "nvidia/nemotron-nano-9b-v2" => Ok(Self::NvidiaNemotronNano9bV2),
1848 "nvidia/nemotron-nano-9b-v2:free" => Ok(Self::NvidiaNemotronNano9bV2Free),
1849 "openai/gpt-4.1" => Ok(Self::OpenaiGpt41),
1850 "openai/gpt-4.1-mini" => Ok(Self::OpenaiGpt41Mini),
1851 "openai/gpt-4o-mini" => Ok(Self::OpenaiGpt4oMini),
1852 "openai/gpt-5" => Ok(Self::OpenaiGpt5),
1853 "openai/gpt-5-codex" => Ok(Self::OpenaiGpt5Codex),
1854 "openai/gpt-5-image" => Ok(Self::OpenaiGpt5Image),
1855 "openai/gpt-5-mini" => Ok(Self::OpenaiGpt5Mini),
1856 "openai/gpt-5-nano" => Ok(Self::OpenaiGpt5Nano),
1857 "openai/gpt-5-pro" => Ok(Self::OpenaiGpt5Pro),
1858 "openai/gpt-5.1" => Ok(Self::OpenaiGpt51),
1859 "openai/gpt-5.1-chat" => Ok(Self::OpenaiGpt51Chat),
1860 "openai/gpt-5.1-codex" => Ok(Self::OpenaiGpt51Codex),
1861 "openai/gpt-5.1-codex-max" => Ok(Self::OpenaiGpt51CodexMax),
1862 "openai/gpt-5.1-codex-mini" => Ok(Self::OpenaiGpt51CodexMini),
1863 "openai/gpt-5.2" => Ok(Self::OpenaiGpt52),
1864 "openai/gpt-5.2-chat" => Ok(Self::OpenaiGpt52Chat),
1865 "openai/gpt-5.2-codex" => Ok(Self::OpenaiGpt52Codex),
1866 "openai/gpt-5.2-pro" => Ok(Self::OpenaiGpt52Pro),
1867 "openai/gpt-5.3-codex" => Ok(Self::OpenaiGpt53Codex),
1868 "openai/gpt-5.4" => Ok(Self::OpenaiGpt54),
1869 "openai/gpt-5.4-mini" => Ok(Self::OpenaiGpt54Mini),
1870 "openai/gpt-5.4-nano" => Ok(Self::OpenaiGpt54Nano),
1871 "openai/gpt-5.4-pro" => Ok(Self::OpenaiGpt54Pro),
1872 "openai/gpt-5.5" => Ok(Self::OpenaiGpt55),
1873 "openai/gpt-5.5-pro" => Ok(Self::OpenaiGpt55Pro),
1874 "openai/gpt-oss-120b" => Ok(Self::OpenaiGptOss120b),
1875 "openai/gpt-oss-120b:exacto" => Ok(Self::OpenaiGptOss120bExacto),
1876 "openai/gpt-oss-120b:free" => Ok(Self::OpenaiGptOss120bFree),
1877 "openai/gpt-oss-20b" => Ok(Self::OpenaiGptOss20b),
1878 "openai/gpt-oss-20b:free" => Ok(Self::OpenaiGptOss20bFree),
1879 "openai/gpt-oss-safeguard-20b" => Ok(Self::OpenaiGptOssSafeguard20b),
1880 "openai/o4-mini" => Ok(Self::OpenaiO4Mini),
1881 "openrouter/elephant-alpha" => Ok(Self::OpenrouterElephantAlpha),
1882 "openrouter/free" => Ok(Self::OpenrouterFree),
1883 "openrouter/owl-alpha" => Ok(Self::OpenrouterOwlAlpha),
1884 "openrouter/pareto-code" => Ok(Self::OpenrouterParetoCode),
1885 "poolside/laguna-m.1:free" => Ok(Self::PoolsideLagunaM1Free),
1886 "poolside/laguna-xs.2:free" => Ok(Self::PoolsideLagunaXs2Free),
1887 "prime-intellect/intellect-3" => Ok(Self::PrimeIntellectIntellect3),
1888 "qwen/qwen-3.6-27b" => Ok(Self::QwenQwen3627b),
1889 "qwen/qwen-plus" => Ok(Self::QwenQwenPlus),
1890 "qwen/qwen3-235b-a22b-07-25" => Ok(Self::QwenQwen3235bA22b0725),
1891 "qwen/qwen3-235b-a22b-thinking-2507" => Ok(Self::QwenQwen3235bA22bThinking2507),
1892 "qwen/qwen3-30b-a3b-instruct-2507" => Ok(Self::QwenQwen330bA3bInstruct2507),
1893 "qwen/qwen3-30b-a3b-thinking-2507" => Ok(Self::QwenQwen330bA3bThinking2507),
1894 "qwen/qwen3-coder" => Ok(Self::QwenQwen3Coder),
1895 "qwen/qwen3-coder-30b-a3b-instruct" => Ok(Self::QwenQwen3Coder30bA3bInstruct),
1896 "qwen/qwen3-coder-flash" => Ok(Self::QwenQwen3CoderFlash),
1897 "qwen/qwen3-coder-plus" => Ok(Self::QwenQwen3CoderPlus),
1898 "qwen/qwen3-coder:exacto" => Ok(Self::QwenQwen3CoderExacto),
1899 "qwen/qwen3-max" => Ok(Self::QwenQwen3Max),
1900 "qwen/qwen3-next-80b-a3b-instruct" => Ok(Self::QwenQwen3Next80bA3bInstruct),
1901 "qwen/qwen3-next-80b-a3b-thinking" => Ok(Self::QwenQwen3Next80bA3bThinking),
1902 "qwen/qwen3.5-397b-a17b" => Ok(Self::QwenQwen35397bA17b),
1903 "qwen/qwen3.5-flash-02-23" => Ok(Self::QwenQwen35Flash0223),
1904 "qwen/qwen3.5-plus-02-15" => Ok(Self::QwenQwen35Plus0215),
1905 "qwen/qwen3.6-plus" => Ok(Self::QwenQwen36Plus),
1906 "stepfun/step-3.5-flash" => Ok(Self::StepfunStep35Flash),
1907 "tencent/hy3-preview" => Ok(Self::TencentHy3Preview),
1908 "x-ai/grok-3" => Ok(Self::XAiGrok3),
1909 "x-ai/grok-3-beta" => Ok(Self::XAiGrok3Beta),
1910 "x-ai/grok-3-mini" => Ok(Self::XAiGrok3Mini),
1911 "x-ai/grok-3-mini-beta" => Ok(Self::XAiGrok3MiniBeta),
1912 "x-ai/grok-4" => Ok(Self::XAiGrok4),
1913 "x-ai/grok-4-fast" => Ok(Self::XAiGrok4Fast),
1914 "x-ai/grok-4.1-fast" => Ok(Self::XAiGrok41Fast),
1915 "x-ai/grok-4.20-beta" => Ok(Self::XAiGrok420Beta),
1916 "x-ai/grok-4.3" => Ok(Self::XAiGrok43),
1917 "x-ai/grok-code-fast-1" => Ok(Self::XAiGrokCodeFast1),
1918 "xiaomi/mimo-v2-flash" => Ok(Self::XiaomiMimoV2Flash),
1919 "xiaomi/mimo-v2-omni" => Ok(Self::XiaomiMimoV2Omni),
1920 "xiaomi/mimo-v2-pro" => Ok(Self::XiaomiMimoV2Pro),
1921 "xiaomi/mimo-v2.5" => Ok(Self::XiaomiMimoV25),
1922 "xiaomi/mimo-v2.5-pro" => Ok(Self::XiaomiMimoV25Pro),
1923 "z-ai/glm-4.5" => Ok(Self::ZAiGlm45),
1924 "z-ai/glm-4.5-air" => Ok(Self::ZAiGlm45Air),
1925 "z-ai/glm-4.5v" => Ok(Self::ZAiGlm45v),
1926 "z-ai/glm-4.6" => Ok(Self::ZAiGlm46),
1927 "z-ai/glm-4.6:exacto" => Ok(Self::ZAiGlm46Exacto),
1928 "z-ai/glm-4.7" => Ok(Self::ZAiGlm47),
1929 "z-ai/glm-4.7-flash" => Ok(Self::ZAiGlm47Flash),
1930 "z-ai/glm-5" => Ok(Self::ZAiGlm5),
1931 "z-ai/glm-5-turbo" => Ok(Self::ZAiGlm5Turbo),
1932 "z-ai/glm-5.1" => Ok(Self::ZAiGlm51),
1933 _ => Err(format!("Unknown openrouter model: '{s}'")),
1934 }
1935 }
1936}
1937
1938impl ZAiModel {
1939 #[allow(clippy::too_many_lines)]
1940 fn model_id(self) -> &'static str {
1941 match self {
1942 Self::Glm45 => "glm-4.5",
1943 Self::Glm45Air => "glm-4.5-air",
1944 Self::Glm45Flash => "glm-4.5-flash",
1945 Self::Glm45v => "glm-4.5v",
1946 Self::Glm46 => "glm-4.6",
1947 Self::Glm46v => "glm-4.6v",
1948 Self::Glm47 => "glm-4.7",
1949 Self::Glm47Flash => "glm-4.7-flash",
1950 Self::Glm47Flashx => "glm-4.7-flashx",
1951 Self::Glm5 => "glm-5",
1952 Self::Glm5Turbo => "glm-5-turbo",
1953 Self::Glm51 => "glm-5.1",
1954 Self::Glm5vTurbo => "glm-5v-turbo",
1955 }
1956 }
1957
1958 #[allow(clippy::too_many_lines)]
1959 fn display_name(self) -> &'static str {
1960 match self {
1961 Self::Glm45 => "GLM-4.5",
1962 Self::Glm45Air => "GLM-4.5-Air",
1963 Self::Glm45Flash => "GLM-4.5-Flash",
1964 Self::Glm45v => "GLM-4.5V",
1965 Self::Glm46 => "GLM-4.6",
1966 Self::Glm46v => "GLM-4.6V",
1967 Self::Glm47 => "GLM-4.7",
1968 Self::Glm47Flash => "GLM-4.7-Flash",
1969 Self::Glm47Flashx => "GLM-4.7-FlashX",
1970 Self::Glm5 => "GLM-5",
1971 Self::Glm5Turbo => "GLM-5-Turbo",
1972 Self::Glm51 => "GLM-5.1",
1973 Self::Glm5vTurbo => "GLM-5V-Turbo",
1974 }
1975 }
1976
1977 fn context_window(self) -> u32 {
1978 match self {
1979 Self::Glm46v => 128_000,
1980 Self::Glm45 | Self::Glm45Air | Self::Glm45Flash => 131_072,
1981 Self::Glm47Flash | Self::Glm47Flashx | Self::Glm5Turbo | Self::Glm51 | Self::Glm5vTurbo => 200_000,
1982 Self::Glm46 | Self::Glm47 | Self::Glm5 => 204_800,
1983 Self::Glm45v => 64_000,
1984 }
1985 }
1986
1987 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
1988 match self {
1989 Self::Glm45 | Self::Glm45Air | Self::Glm45Flash | Self::Glm45v | Self::Glm46 | Self::Glm46v | Self::Glm47 | Self::Glm47Flash | Self::Glm47Flashx | Self::Glm5 | Self::Glm5Turbo | Self::Glm51 | Self::Glm5vTurbo => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High],
1990 }
1991 }
1992
1993 pub fn supports_reasoning(self) -> bool {
1994 !self.reasoning_levels().is_empty()
1995 }
1996
1997 pub fn supports_image(self) -> bool {
1998 match self {
1999 Self::Glm45 | Self::Glm45Air | Self::Glm45Flash | Self::Glm46 | Self::Glm47 | Self::Glm47Flash | Self::Glm47Flashx | Self::Glm5 | Self::Glm5Turbo | Self::Glm51 => false,
2000 Self::Glm45v | Self::Glm46v | Self::Glm5vTurbo => true,
2001 }
2002 }
2003
2004 pub fn supports_audio(self) -> bool {
2005 match self {
2006 Self::Glm45 | Self::Glm45Air | Self::Glm45Flash | Self::Glm45v | Self::Glm46 | Self::Glm46v | Self::Glm47 | Self::Glm47Flash | Self::Glm47Flashx | Self::Glm5 | Self::Glm5Turbo | Self::Glm51 | Self::Glm5vTurbo => false,
2007 }
2008 }
2009
2010 const ALL: &[ZAiModel] = &[
2011 Self::Glm45,
2012 Self::Glm45Air,
2013 Self::Glm45Flash,
2014 Self::Glm45v,
2015 Self::Glm46,
2016 Self::Glm46v,
2017 Self::Glm47,
2018 Self::Glm47Flash,
2019 Self::Glm47Flashx,
2020 Self::Glm5,
2021 Self::Glm5Turbo,
2022 Self::Glm51,
2023 Self::Glm5vTurbo,
2024 ];
2025}
2026
2027impl std::str::FromStr for ZAiModel {
2028 type Err = String;
2029
2030 #[allow(clippy::too_many_lines)]
2031 fn from_str(s: &str) -> Result<Self, Self::Err> {
2032 match s {
2033 "glm-4.5" => Ok(Self::Glm45),
2034 "glm-4.5-air" => Ok(Self::Glm45Air),
2035 "glm-4.5-flash" => Ok(Self::Glm45Flash),
2036 "glm-4.5v" => Ok(Self::Glm45v),
2037 "glm-4.6" => Ok(Self::Glm46),
2038 "glm-4.6v" => Ok(Self::Glm46v),
2039 "glm-4.7" => Ok(Self::Glm47),
2040 "glm-4.7-flash" => Ok(Self::Glm47Flash),
2041 "glm-4.7-flashx" => Ok(Self::Glm47Flashx),
2042 "glm-5" => Ok(Self::Glm5),
2043 "glm-5-turbo" => Ok(Self::Glm5Turbo),
2044 "glm-5.1" => Ok(Self::Glm51),
2045 "glm-5v-turbo" => Ok(Self::Glm5vTurbo),
2046 _ => Err(format!("Unknown zai model: '{s}'")),
2047 }
2048 }
2049}
2050
2051impl BedrockModel {
2052 #[allow(clippy::too_many_lines)]
2053 fn model_id(self) -> &'static str {
2054 match self {
2055 Self::AmazonNova2LiteV10 => "amazon.nova-2-lite-v1:0",
2056 Self::AmazonNovaLiteV10 => "amazon.nova-lite-v1:0",
2057 Self::AmazonNovaMicroV10 => "amazon.nova-micro-v1:0",
2058 Self::AmazonNovaProV10 => "amazon.nova-pro-v1:0",
2059 Self::AnthropicClaudeHaiku4520251001V10 => "anthropic.claude-haiku-4-5-20251001-v1:0",
2060 Self::AnthropicClaudeOpus4120250805V10 => "anthropic.claude-opus-4-1-20250805-v1:0",
2061 Self::AnthropicClaudeOpus4520251101V10 => "anthropic.claude-opus-4-5-20251101-v1:0",
2062 Self::AnthropicClaudeOpus46V1 => "anthropic.claude-opus-4-6-v1",
2063 Self::AnthropicClaudeOpus47 => "anthropic.claude-opus-4-7",
2064 Self::AnthropicClaudeSonnet4520250929V10 => "anthropic.claude-sonnet-4-5-20250929-v1:0",
2065 Self::AnthropicClaudeSonnet46 => "anthropic.claude-sonnet-4-6",
2066 Self::AuAnthropicClaudeHaiku4520251001V10 => "au.anthropic.claude-haiku-4-5-20251001-v1:0",
2067 Self::AuAnthropicClaudeOpus46V1 => "au.anthropic.claude-opus-4-6-v1",
2068 Self::AuAnthropicClaudeSonnet4520250929V10 => "au.anthropic.claude-sonnet-4-5-20250929-v1:0",
2069 Self::AuAnthropicClaudeSonnet46 => "au.anthropic.claude-sonnet-4-6",
2070 Self::DeepseekR1V10 => "deepseek.r1-v1:0",
2071 Self::DeepseekV3V10 => "deepseek.v3-v1:0",
2072 Self::DeepseekV32 => "deepseek.v3.2",
2073 Self::EuAnthropicClaudeHaiku4520251001V10 => "eu.anthropic.claude-haiku-4-5-20251001-v1:0",
2074 Self::EuAnthropicClaudeOpus4520251101V10 => "eu.anthropic.claude-opus-4-5-20251101-v1:0",
2075 Self::EuAnthropicClaudeOpus46V1 => "eu.anthropic.claude-opus-4-6-v1",
2076 Self::EuAnthropicClaudeOpus47 => "eu.anthropic.claude-opus-4-7",
2077 Self::EuAnthropicClaudeSonnet4520250929V10 => "eu.anthropic.claude-sonnet-4-5-20250929-v1:0",
2078 Self::EuAnthropicClaudeSonnet46 => "eu.anthropic.claude-sonnet-4-6",
2079 Self::GlobalAnthropicClaudeHaiku4520251001V10 => "global.anthropic.claude-haiku-4-5-20251001-v1:0",
2080 Self::GlobalAnthropicClaudeOpus4520251101V10 => "global.anthropic.claude-opus-4-5-20251101-v1:0",
2081 Self::GlobalAnthropicClaudeOpus46V1 => "global.anthropic.claude-opus-4-6-v1",
2082 Self::GlobalAnthropicClaudeOpus47 => "global.anthropic.claude-opus-4-7",
2083 Self::GlobalAnthropicClaudeSonnet4520250929V10 => "global.anthropic.claude-sonnet-4-5-20250929-v1:0",
2084 Self::GlobalAnthropicClaudeSonnet46 => "global.anthropic.claude-sonnet-4-6",
2085 Self::GoogleGemma327bIt => "google.gemma-3-27b-it",
2086 Self::GoogleGemma34bIt => "google.gemma-3-4b-it",
2087 Self::JpAnthropicClaudeOpus47 => "jp.anthropic.claude-opus-4-7",
2088 Self::JpAnthropicClaudeSonnet4520250929V10 => "jp.anthropic.claude-sonnet-4-5-20250929-v1:0",
2089 Self::JpAnthropicClaudeSonnet46 => "jp.anthropic.claude-sonnet-4-6",
2090 Self::MetaLlama3170bInstructV10 => "meta.llama3-1-70b-instruct-v1:0",
2091 Self::MetaLlama318bInstructV10 => "meta.llama3-1-8b-instruct-v1:0",
2092 Self::MetaLlama3370bInstructV10 => "meta.llama3-3-70b-instruct-v1:0",
2093 Self::MetaLlama4Maverick17bInstructV10 => "meta.llama4-maverick-17b-instruct-v1:0",
2094 Self::MetaLlama4Scout17bInstructV10 => "meta.llama4-scout-17b-instruct-v1:0",
2095 Self::MinimaxMinimaxM2 => "minimax.minimax-m2",
2096 Self::MinimaxMinimaxM21 => "minimax.minimax-m2.1",
2097 Self::MinimaxMinimaxM25 => "minimax.minimax-m2.5",
2098 Self::MistralDevstral2123b => "mistral.devstral-2-123b",
2099 Self::MistralMagistralSmall2509 => "mistral.magistral-small-2509",
2100 Self::MistralMinistral314bInstruct => "mistral.ministral-3-14b-instruct",
2101 Self::MistralMinistral33bInstruct => "mistral.ministral-3-3b-instruct",
2102 Self::MistralMinistral38bInstruct => "mistral.ministral-3-8b-instruct",
2103 Self::MistralMistralLarge3675bInstruct => "mistral.mistral-large-3-675b-instruct",
2104 Self::MistralPixtralLarge2502V10 => "mistral.pixtral-large-2502-v1:0",
2105 Self::MistralVoxtralMini3b2507 => "mistral.voxtral-mini-3b-2507",
2106 Self::MistralVoxtralSmall24b2507 => "mistral.voxtral-small-24b-2507",
2107 Self::MoonshotKimiK2Thinking => "moonshot.kimi-k2-thinking",
2108 Self::MoonshotaiKimiK25 => "moonshotai.kimi-k2.5",
2109 Self::NvidiaNemotronNano12bV2 => "nvidia.nemotron-nano-12b-v2",
2110 Self::NvidiaNemotronNano330b => "nvidia.nemotron-nano-3-30b",
2111 Self::NvidiaNemotronNano9bV2 => "nvidia.nemotron-nano-9b-v2",
2112 Self::NvidiaNemotronSuper3120b => "nvidia.nemotron-super-3-120b",
2113 Self::OpenaiGptOss120b10 => "openai.gpt-oss-120b-1:0",
2114 Self::OpenaiGptOss20b10 => "openai.gpt-oss-20b-1:0",
2115 Self::OpenaiGptOssSafeguard120b => "openai.gpt-oss-safeguard-120b",
2116 Self::OpenaiGptOssSafeguard20b => "openai.gpt-oss-safeguard-20b",
2117 Self::QwenQwen3235bA22b2507V10 => "qwen.qwen3-235b-a22b-2507-v1:0",
2118 Self::QwenQwen332bV10 => "qwen.qwen3-32b-v1:0",
2119 Self::QwenQwen3Coder30bA3bV10 => "qwen.qwen3-coder-30b-a3b-v1:0",
2120 Self::QwenQwen3Coder480bA35bV10 => "qwen.qwen3-coder-480b-a35b-v1:0",
2121 Self::QwenQwen3CoderNext => "qwen.qwen3-coder-next",
2122 Self::QwenQwen3Next80bA3b => "qwen.qwen3-next-80b-a3b",
2123 Self::QwenQwen3Vl235bA22b => "qwen.qwen3-vl-235b-a22b",
2124 Self::UsAnthropicClaudeHaiku4520251001V10 => "us.anthropic.claude-haiku-4-5-20251001-v1:0",
2125 Self::UsAnthropicClaudeOpus4120250805V10 => "us.anthropic.claude-opus-4-1-20250805-v1:0",
2126 Self::UsAnthropicClaudeOpus4520251101V10 => "us.anthropic.claude-opus-4-5-20251101-v1:0",
2127 Self::UsAnthropicClaudeOpus46V1 => "us.anthropic.claude-opus-4-6-v1",
2128 Self::UsAnthropicClaudeOpus47 => "us.anthropic.claude-opus-4-7",
2129 Self::UsAnthropicClaudeSonnet4520250929V10 => "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
2130 Self::UsAnthropicClaudeSonnet46 => "us.anthropic.claude-sonnet-4-6",
2131 Self::UsDeepseekR1V10 => "us.deepseek.r1-v1:0",
2132 Self::UsMetaLlama4Maverick17bInstructV10 => "us.meta.llama4-maverick-17b-instruct-v1:0",
2133 Self::UsMetaLlama4Scout17bInstructV10 => "us.meta.llama4-scout-17b-instruct-v1:0",
2134 Self::WriterPalmyraX4V10 => "writer.palmyra-x4-v1:0",
2135 Self::WriterPalmyraX5V10 => "writer.palmyra-x5-v1:0",
2136 Self::ZaiGlm47 => "zai.glm-4.7",
2137 Self::ZaiGlm47Flash => "zai.glm-4.7-flash",
2138 Self::ZaiGlm5 => "zai.glm-5",
2139 }
2140 }
2141
2142 #[allow(clippy::too_many_lines)]
2143 fn display_name(self) -> &'static str {
2144 match self {
2145 Self::AuAnthropicClaudeOpus46V1 => "AU Anthropic Claude Opus 4.6",
2146 Self::AuAnthropicClaudeSonnet46 => "AU Anthropic Claude Sonnet 4.6",
2147 Self::AnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5",
2148 Self::AuAnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5 (AU)",
2149 Self::EuAnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5 (EU)",
2150 Self::GlobalAnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5 (Global)",
2151 Self::UsAnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5 (US)",
2152 Self::AnthropicClaudeOpus4120250805V10 => "Claude Opus 4.1",
2153 Self::UsAnthropicClaudeOpus4120250805V10 => "Claude Opus 4.1 (US)",
2154 Self::AnthropicClaudeOpus4520251101V10 => "Claude Opus 4.5",
2155 Self::EuAnthropicClaudeOpus4520251101V10 => "Claude Opus 4.5 (EU)",
2156 Self::GlobalAnthropicClaudeOpus4520251101V10 => "Claude Opus 4.5 (Global)",
2157 Self::UsAnthropicClaudeOpus4520251101V10 => "Claude Opus 4.5 (US)",
2158 Self::AnthropicClaudeOpus46V1 => "Claude Opus 4.6",
2159 Self::EuAnthropicClaudeOpus46V1 => "Claude Opus 4.6 (EU)",
2160 Self::GlobalAnthropicClaudeOpus46V1 => "Claude Opus 4.6 (Global)",
2161 Self::UsAnthropicClaudeOpus46V1 => "Claude Opus 4.6 (US)",
2162 Self::AnthropicClaudeOpus47 => "Claude Opus 4.7",
2163 Self::EuAnthropicClaudeOpus47 => "Claude Opus 4.7 (EU)",
2164 Self::GlobalAnthropicClaudeOpus47 => "Claude Opus 4.7 (Global)",
2165 Self::JpAnthropicClaudeOpus47 => "Claude Opus 4.7 (JP)",
2166 Self::UsAnthropicClaudeOpus47 => "Claude Opus 4.7 (US)",
2167 Self::AnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5",
2168 Self::AuAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (AU)",
2169 Self::EuAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (EU)",
2170 Self::GlobalAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (Global)",
2171 Self::JpAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (JP)",
2172 Self::UsAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (US)",
2173 Self::AnthropicClaudeSonnet46 => "Claude Sonnet 4.6",
2174 Self::EuAnthropicClaudeSonnet46 => "Claude Sonnet 4.6 (EU)",
2175 Self::GlobalAnthropicClaudeSonnet46 => "Claude Sonnet 4.6 (Global)",
2176 Self::JpAnthropicClaudeSonnet46 => "Claude Sonnet 4.6 (JP)",
2177 Self::UsAnthropicClaudeSonnet46 => "Claude Sonnet 4.6 (US)",
2178 Self::DeepseekR1V10 => "DeepSeek-R1",
2179 Self::UsDeepseekR1V10 => "DeepSeek-R1 (US)",
2180 Self::DeepseekV3V10 => "DeepSeek-V3.1",
2181 Self::DeepseekV32 => "DeepSeek-V3.2",
2182 Self::MistralDevstral2123b => "Devstral 2 123B",
2183 Self::ZaiGlm47 => "GLM-4.7",
2184 Self::ZaiGlm47Flash => "GLM-4.7-Flash",
2185 Self::ZaiGlm5 => "GLM-5",
2186 Self::OpenaiGptOssSafeguard120b => "GPT OSS Safeguard 120B",
2187 Self::OpenaiGptOssSafeguard20b => "GPT OSS Safeguard 20B",
2188 Self::GoogleGemma34bIt => "Gemma 3 4B IT",
2189 Self::GoogleGemma327bIt => "Google Gemma 3 27B Instruct",
2190 Self::MoonshotKimiK2Thinking => "Kimi K2 Thinking",
2191 Self::MoonshotaiKimiK25 => "Kimi K2.5",
2192 Self::MetaLlama3170bInstructV10 => "Llama 3.1 70B Instruct",
2193 Self::MetaLlama318bInstructV10 => "Llama 3.1 8B Instruct",
2194 Self::MetaLlama3370bInstructV10 => "Llama 3.3 70B Instruct",
2195 Self::MetaLlama4Maverick17bInstructV10 => "Llama 4 Maverick 17B Instruct",
2196 Self::UsMetaLlama4Maverick17bInstructV10 => "Llama 4 Maverick 17B Instruct (US)",
2197 Self::MetaLlama4Scout17bInstructV10 => "Llama 4 Scout 17B Instruct",
2198 Self::UsMetaLlama4Scout17bInstructV10 => "Llama 4 Scout 17B Instruct (US)",
2199 Self::MistralMagistralSmall2509 => "Magistral Small 1.2",
2200 Self::MinimaxMinimaxM2 => "MiniMax M2",
2201 Self::MinimaxMinimaxM21 => "MiniMax M2.1",
2202 Self::MinimaxMinimaxM25 => "MiniMax M2.5",
2203 Self::MistralMinistral314bInstruct => "Ministral 14B 3.0",
2204 Self::MistralMinistral33bInstruct => "Ministral 3 3B",
2205 Self::MistralMinistral38bInstruct => "Ministral 3 8B",
2206 Self::MistralMistralLarge3675bInstruct => "Mistral Large 3",
2207 Self::NvidiaNemotronSuper3120b => "NVIDIA Nemotron 3 Super 120B A12B",
2208 Self::NvidiaNemotronNano12bV2 => "NVIDIA Nemotron Nano 12B v2 VL BF16",
2209 Self::NvidiaNemotronNano330b => "NVIDIA Nemotron Nano 3 30B",
2210 Self::NvidiaNemotronNano9bV2 => "NVIDIA Nemotron Nano 9B v2",
2211 Self::AmazonNova2LiteV10 => "Nova 2 Lite",
2212 Self::AmazonNovaLiteV10 => "Nova Lite",
2213 Self::AmazonNovaMicroV10 => "Nova Micro",
2214 Self::AmazonNovaProV10 => "Nova Pro",
2215 Self::WriterPalmyraX4V10 => "Palmyra X4",
2216 Self::WriterPalmyraX5V10 => "Palmyra X5",
2217 Self::MistralPixtralLarge2502V10 => "Pixtral Large (25.02)",
2218 Self::QwenQwen3Next80bA3b => "Qwen/Qwen3-Next-80B-A3B-Instruct",
2219 Self::QwenQwen3Vl235bA22b => "Qwen/Qwen3-VL-235B-A22B-Instruct",
2220 Self::QwenQwen3235bA22b2507V10 => "Qwen3 235B A22B 2507",
2221 Self::QwenQwen332bV10 => "Qwen3 32B (dense)",
2222 Self::QwenQwen3Coder30bA3bV10 => "Qwen3 Coder 30B A3B Instruct",
2223 Self::QwenQwen3Coder480bA35bV10 => "Qwen3 Coder 480B A35B Instruct",
2224 Self::QwenQwen3CoderNext => "Qwen3 Coder Next",
2225 Self::MistralVoxtralMini3b2507 => "Voxtral Mini 3B 2507",
2226 Self::MistralVoxtralSmall24b2507 => "Voxtral Small 24B 2507",
2227 Self::OpenaiGptOss120b10 => "gpt-oss-120b",
2228 Self::OpenaiGptOss20b10 => "gpt-oss-20b",
2229 }
2230 }
2231
2232 fn context_window(self) -> u32 {
2233 match self {
2234 Self::AnthropicClaudeOpus46V1 | Self::AnthropicClaudeOpus47 | Self::AnthropicClaudeSonnet46 | Self::AuAnthropicClaudeOpus46V1 | Self::AuAnthropicClaudeSonnet46 | Self::EuAnthropicClaudeOpus46V1 | Self::EuAnthropicClaudeOpus47 | Self::EuAnthropicClaudeSonnet46 | Self::GlobalAnthropicClaudeOpus46V1 | Self::GlobalAnthropicClaudeOpus47 | Self::GlobalAnthropicClaudeSonnet46 | Self::JpAnthropicClaudeOpus47 | Self::JpAnthropicClaudeSonnet46 | Self::MetaLlama4Maverick17bInstructV10 | Self::UsAnthropicClaudeOpus46V1 | Self::UsAnthropicClaudeOpus47 | Self::UsAnthropicClaudeSonnet46 | Self::UsMetaLlama4Maverick17bInstructV10 => 1_000_000,
2235 Self::WriterPalmyraX5V10 => 1_040_000,
2236 Self::WriterPalmyraX4V10 => 122_880,
2237 Self::AmazonNova2LiteV10 | Self::AmazonNovaMicroV10 | Self::DeepseekR1V10 | Self::GoogleGemma34bIt | Self::MetaLlama3170bInstructV10 | Self::MetaLlama318bInstructV10 | Self::MetaLlama3370bInstructV10 | Self::MistralMagistralSmall2509 | Self::MistralMinistral314bInstruct | Self::MistralMinistral38bInstruct | Self::MistralPixtralLarge2502V10 | Self::MistralVoxtralMini3b2507 | Self::NvidiaNemotronNano12bV2 | Self::NvidiaNemotronNano330b | Self::NvidiaNemotronNano9bV2 | Self::OpenaiGptOss120b10 | Self::OpenaiGptOss20b10 | Self::OpenaiGptOssSafeguard120b | Self::OpenaiGptOssSafeguard20b | Self::UsDeepseekR1V10 => 128_000,
2238 Self::QwenQwen3Coder480bA35bV10 | Self::QwenQwen3CoderNext => 131_072,
2239 Self::QwenQwen332bV10 => 16_384,
2240 Self::DeepseekV3V10 | Self::DeepseekV32 => 163_840,
2241 Self::MinimaxMinimaxM25 => 196_608,
2242 Self::AnthropicClaudeHaiku4520251001V10 | Self::AnthropicClaudeOpus4120250805V10 | Self::AnthropicClaudeOpus4520251101V10 | Self::AnthropicClaudeSonnet4520250929V10 | Self::AuAnthropicClaudeHaiku4520251001V10 | Self::AuAnthropicClaudeSonnet4520250929V10 | Self::EuAnthropicClaudeHaiku4520251001V10 | Self::EuAnthropicClaudeOpus4520251101V10 | Self::EuAnthropicClaudeSonnet4520250929V10 | Self::GlobalAnthropicClaudeHaiku4520251001V10 | Self::GlobalAnthropicClaudeOpus4520251101V10 | Self::GlobalAnthropicClaudeSonnet4520250929V10 | Self::JpAnthropicClaudeSonnet4520250929V10 | Self::UsAnthropicClaudeHaiku4520251001V10 | Self::UsAnthropicClaudeOpus4120250805V10 | Self::UsAnthropicClaudeOpus4520251101V10 | Self::UsAnthropicClaudeSonnet4520250929V10 | Self::ZaiGlm47Flash => 200_000,
2243 Self::GoogleGemma327bIt | Self::ZaiGlm5 => 202_752,
2244 Self::MinimaxMinimaxM2 => 204_608,
2245 Self::MinimaxMinimaxM21 | Self::ZaiGlm47 => 204_800,
2246 Self::MistralDevstral2123b | Self::MistralMinistral33bInstruct | Self::MistralMistralLarge3675bInstruct | Self::MoonshotKimiK2Thinking | Self::MoonshotaiKimiK25 => 256_000,
2247 Self::QwenQwen3Next80bA3b | Self::QwenQwen3Vl235bA22b => 262_000,
2248 Self::NvidiaNemotronSuper3120b | Self::QwenQwen3235bA22b2507V10 | Self::QwenQwen3Coder30bA3bV10 => 262_144,
2249 Self::AmazonNovaLiteV10 | Self::AmazonNovaProV10 => 300_000,
2250 Self::MistralVoxtralSmall24b2507 => 32_000,
2251 Self::MetaLlama4Scout17bInstructV10 | Self::UsMetaLlama4Scout17bInstructV10 => 3_500_000,
2252 }
2253 }
2254
2255 pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
2256 match self {
2257 Self::AmazonNova2LiteV10 | Self::AmazonNovaLiteV10 | Self::AmazonNovaMicroV10 | Self::AmazonNovaProV10 | Self::GoogleGemma327bIt | Self::GoogleGemma34bIt | Self::MetaLlama3170bInstructV10 | Self::MetaLlama318bInstructV10 | Self::MetaLlama3370bInstructV10 | Self::MetaLlama4Maverick17bInstructV10 | Self::MetaLlama4Scout17bInstructV10 | Self::MistralDevstral2123b | Self::MistralMinistral314bInstruct | Self::MistralMinistral33bInstruct | Self::MistralMinistral38bInstruct | Self::MistralMistralLarge3675bInstruct | Self::MistralPixtralLarge2502V10 | Self::MistralVoxtralMini3b2507 | Self::MistralVoxtralSmall24b2507 | Self::NvidiaNemotronNano12bV2 | Self::NvidiaNemotronNano9bV2 | Self::OpenaiGptOss120b10 | Self::OpenaiGptOss20b10 | Self::OpenaiGptOssSafeguard120b | Self::OpenaiGptOssSafeguard20b | Self::QwenQwen3235bA22b2507V10 | Self::QwenQwen3Coder30bA3bV10 | Self::QwenQwen3Coder480bA35bV10 | Self::QwenQwen3Next80bA3b | Self::QwenQwen3Vl235bA22b | Self::UsMetaLlama4Maverick17bInstructV10 | Self::UsMetaLlama4Scout17bInstructV10 => &[],
2258 Self::AnthropicClaudeHaiku4520251001V10 | Self::AnthropicClaudeOpus4120250805V10 | Self::AnthropicClaudeOpus4520251101V10 | Self::AnthropicClaudeOpus46V1 | Self::AnthropicClaudeOpus47 | Self::AnthropicClaudeSonnet4520250929V10 | Self::AnthropicClaudeSonnet46 | Self::AuAnthropicClaudeHaiku4520251001V10 | Self::AuAnthropicClaudeOpus46V1 | Self::AuAnthropicClaudeSonnet4520250929V10 | Self::AuAnthropicClaudeSonnet46 | Self::DeepseekR1V10 | Self::DeepseekV3V10 | Self::DeepseekV32 | Self::EuAnthropicClaudeHaiku4520251001V10 | Self::EuAnthropicClaudeOpus4520251101V10 | Self::EuAnthropicClaudeOpus46V1 | Self::EuAnthropicClaudeOpus47 | Self::EuAnthropicClaudeSonnet4520250929V10 | Self::EuAnthropicClaudeSonnet46 | Self::GlobalAnthropicClaudeHaiku4520251001V10 | Self::GlobalAnthropicClaudeOpus4520251101V10 | Self::GlobalAnthropicClaudeOpus46V1 | Self::GlobalAnthropicClaudeOpus47 | Self::GlobalAnthropicClaudeSonnet4520250929V10 | Self::GlobalAnthropicClaudeSonnet46 | Self::JpAnthropicClaudeOpus47 | Self::JpAnthropicClaudeSonnet4520250929V10 | Self::JpAnthropicClaudeSonnet46 | Self::MinimaxMinimaxM2 | Self::MinimaxMinimaxM21 | Self::MinimaxMinimaxM25 | Self::MistralMagistralSmall2509 | Self::MoonshotKimiK2Thinking | Self::MoonshotaiKimiK25 | Self::NvidiaNemotronNano330b | Self::NvidiaNemotronSuper3120b | Self::QwenQwen332bV10 | Self::QwenQwen3CoderNext | Self::UsAnthropicClaudeHaiku4520251001V10 | Self::UsAnthropicClaudeOpus4120250805V10 | Self::UsAnthropicClaudeOpus4520251101V10 | Self::UsAnthropicClaudeOpus46V1 | Self::UsAnthropicClaudeOpus47 | Self::UsAnthropicClaudeSonnet4520250929V10 | Self::UsAnthropicClaudeSonnet46 | Self::UsDeepseekR1V10 | Self::WriterPalmyraX4V10 | Self::WriterPalmyraX5V10 | Self::ZaiGlm47 | Self::ZaiGlm47Flash | Self::ZaiGlm5 => &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High],
2259 }
2260 }
2261
2262 pub fn supports_reasoning(self) -> bool {
2263 !self.reasoning_levels().is_empty()
2264 }
2265
2266 pub fn supports_image(self) -> bool {
2267 match self {
2268 Self::AmazonNovaMicroV10 | Self::DeepseekR1V10 | Self::DeepseekV3V10 | Self::DeepseekV32 | Self::MetaLlama3170bInstructV10 | Self::MetaLlama318bInstructV10 | Self::MetaLlama3370bInstructV10 | Self::MinimaxMinimaxM2 | Self::MinimaxMinimaxM21 | Self::MinimaxMinimaxM25 | Self::MistralDevstral2123b | Self::MistralMinistral314bInstruct | Self::MistralMinistral38bInstruct | Self::MistralVoxtralMini3b2507 | Self::MistralVoxtralSmall24b2507 | Self::MoonshotKimiK2Thinking | Self::NvidiaNemotronNano330b | Self::NvidiaNemotronNano9bV2 | Self::NvidiaNemotronSuper3120b | Self::OpenaiGptOss120b10 | Self::OpenaiGptOss20b10 | Self::OpenaiGptOssSafeguard120b | Self::OpenaiGptOssSafeguard20b | Self::QwenQwen3235bA22b2507V10 | Self::QwenQwen332bV10 | Self::QwenQwen3Coder30bA3bV10 | Self::QwenQwen3Coder480bA35bV10 | Self::QwenQwen3CoderNext | Self::QwenQwen3Next80bA3b | Self::UsDeepseekR1V10 | Self::WriterPalmyraX4V10 | Self::WriterPalmyraX5V10 | Self::ZaiGlm47 | Self::ZaiGlm47Flash | Self::ZaiGlm5 => false,
2269 Self::AmazonNova2LiteV10 | Self::AmazonNovaLiteV10 | Self::AmazonNovaProV10 | Self::AnthropicClaudeHaiku4520251001V10 | Self::AnthropicClaudeOpus4120250805V10 | Self::AnthropicClaudeOpus4520251101V10 | Self::AnthropicClaudeOpus46V1 | Self::AnthropicClaudeOpus47 | Self::AnthropicClaudeSonnet4520250929V10 | Self::AnthropicClaudeSonnet46 | Self::AuAnthropicClaudeHaiku4520251001V10 | Self::AuAnthropicClaudeOpus46V1 | Self::AuAnthropicClaudeSonnet4520250929V10 | Self::AuAnthropicClaudeSonnet46 | Self::EuAnthropicClaudeHaiku4520251001V10 | Self::EuAnthropicClaudeOpus4520251101V10 | Self::EuAnthropicClaudeOpus46V1 | Self::EuAnthropicClaudeOpus47 | Self::EuAnthropicClaudeSonnet4520250929V10 | Self::EuAnthropicClaudeSonnet46 | Self::GlobalAnthropicClaudeHaiku4520251001V10 | Self::GlobalAnthropicClaudeOpus4520251101V10 | Self::GlobalAnthropicClaudeOpus46V1 | Self::GlobalAnthropicClaudeOpus47 | Self::GlobalAnthropicClaudeSonnet4520250929V10 | Self::GlobalAnthropicClaudeSonnet46 | Self::GoogleGemma327bIt | Self::GoogleGemma34bIt | Self::JpAnthropicClaudeOpus47 | Self::JpAnthropicClaudeSonnet4520250929V10 | Self::JpAnthropicClaudeSonnet46 | Self::MetaLlama4Maverick17bInstructV10 | Self::MetaLlama4Scout17bInstructV10 | Self::MistralMagistralSmall2509 | Self::MistralMinistral33bInstruct | Self::MistralMistralLarge3675bInstruct | Self::MistralPixtralLarge2502V10 | Self::MoonshotaiKimiK25 | Self::NvidiaNemotronNano12bV2 | Self::QwenQwen3Vl235bA22b | Self::UsAnthropicClaudeHaiku4520251001V10 | Self::UsAnthropicClaudeOpus4120250805V10 | Self::UsAnthropicClaudeOpus4520251101V10 | Self::UsAnthropicClaudeOpus46V1 | Self::UsAnthropicClaudeOpus47 | Self::UsAnthropicClaudeSonnet4520250929V10 | Self::UsAnthropicClaudeSonnet46 | Self::UsMetaLlama4Maverick17bInstructV10 | Self::UsMetaLlama4Scout17bInstructV10 => true,
2270 }
2271 }
2272
2273 pub fn supports_audio(self) -> bool {
2274 match self {
2275 Self::AmazonNova2LiteV10 | Self::AmazonNovaLiteV10 | Self::AmazonNovaMicroV10 | Self::AmazonNovaProV10 | Self::AnthropicClaudeHaiku4520251001V10 | Self::AnthropicClaudeOpus4120250805V10 | Self::AnthropicClaudeOpus4520251101V10 | Self::AnthropicClaudeOpus46V1 | Self::AnthropicClaudeOpus47 | Self::AnthropicClaudeSonnet4520250929V10 | Self::AnthropicClaudeSonnet46 | Self::AuAnthropicClaudeHaiku4520251001V10 | Self::AuAnthropicClaudeOpus46V1 | Self::AuAnthropicClaudeSonnet4520250929V10 | Self::AuAnthropicClaudeSonnet46 | Self::DeepseekR1V10 | Self::DeepseekV3V10 | Self::DeepseekV32 | Self::EuAnthropicClaudeHaiku4520251001V10 | Self::EuAnthropicClaudeOpus4520251101V10 | Self::EuAnthropicClaudeOpus46V1 | Self::EuAnthropicClaudeOpus47 | Self::EuAnthropicClaudeSonnet4520250929V10 | Self::EuAnthropicClaudeSonnet46 | Self::GlobalAnthropicClaudeHaiku4520251001V10 | Self::GlobalAnthropicClaudeOpus4520251101V10 | Self::GlobalAnthropicClaudeOpus46V1 | Self::GlobalAnthropicClaudeOpus47 | Self::GlobalAnthropicClaudeSonnet4520250929V10 | Self::GlobalAnthropicClaudeSonnet46 | Self::GoogleGemma327bIt | Self::GoogleGemma34bIt | Self::JpAnthropicClaudeOpus47 | Self::JpAnthropicClaudeSonnet4520250929V10 | Self::JpAnthropicClaudeSonnet46 | Self::MetaLlama3170bInstructV10 | Self::MetaLlama318bInstructV10 | Self::MetaLlama3370bInstructV10 | Self::MetaLlama4Maverick17bInstructV10 | Self::MetaLlama4Scout17bInstructV10 | Self::MinimaxMinimaxM2 | Self::MinimaxMinimaxM21 | Self::MinimaxMinimaxM25 | Self::MistralDevstral2123b | Self::MistralMagistralSmall2509 | Self::MistralMinistral314bInstruct | Self::MistralMinistral33bInstruct | Self::MistralMinistral38bInstruct | Self::MistralMistralLarge3675bInstruct | Self::MistralPixtralLarge2502V10 | Self::MoonshotKimiK2Thinking | Self::MoonshotaiKimiK25 | Self::NvidiaNemotronNano12bV2 | Self::NvidiaNemotronNano330b | Self::NvidiaNemotronNano9bV2 | Self::NvidiaNemotronSuper3120b | Self::OpenaiGptOss120b10 | Self::OpenaiGptOss20b10 | Self::OpenaiGptOssSafeguard120b | Self::OpenaiGptOssSafeguard20b | Self::QwenQwen3235bA22b2507V10 | Self::QwenQwen332bV10 | Self::QwenQwen3Coder30bA3bV10 | Self::QwenQwen3Coder480bA35bV10 | Self::QwenQwen3CoderNext | Self::QwenQwen3Next80bA3b | Self::QwenQwen3Vl235bA22b | Self::UsAnthropicClaudeHaiku4520251001V10 | Self::UsAnthropicClaudeOpus4120250805V10 | Self::UsAnthropicClaudeOpus4520251101V10 | Self::UsAnthropicClaudeOpus46V1 | Self::UsAnthropicClaudeOpus47 | Self::UsAnthropicClaudeSonnet4520250929V10 | Self::UsAnthropicClaudeSonnet46 | Self::UsDeepseekR1V10 | Self::UsMetaLlama4Maverick17bInstructV10 | Self::UsMetaLlama4Scout17bInstructV10 | Self::WriterPalmyraX4V10 | Self::WriterPalmyraX5V10 | Self::ZaiGlm47 | Self::ZaiGlm47Flash | Self::ZaiGlm5 => false,
2276 Self::MistralVoxtralMini3b2507 | Self::MistralVoxtralSmall24b2507 => true,
2277 }
2278 }
2279
2280 const ALL: &[BedrockModel] = &[
2281 Self::AmazonNova2LiteV10,
2282 Self::AmazonNovaLiteV10,
2283 Self::AmazonNovaMicroV10,
2284 Self::AmazonNovaProV10,
2285 Self::AnthropicClaudeHaiku4520251001V10,
2286 Self::AnthropicClaudeOpus4120250805V10,
2287 Self::AnthropicClaudeOpus4520251101V10,
2288 Self::AnthropicClaudeOpus46V1,
2289 Self::AnthropicClaudeOpus47,
2290 Self::AnthropicClaudeSonnet4520250929V10,
2291 Self::AnthropicClaudeSonnet46,
2292 Self::AuAnthropicClaudeHaiku4520251001V10,
2293 Self::AuAnthropicClaudeOpus46V1,
2294 Self::AuAnthropicClaudeSonnet4520250929V10,
2295 Self::AuAnthropicClaudeSonnet46,
2296 Self::DeepseekR1V10,
2297 Self::DeepseekV3V10,
2298 Self::DeepseekV32,
2299 Self::EuAnthropicClaudeHaiku4520251001V10,
2300 Self::EuAnthropicClaudeOpus4520251101V10,
2301 Self::EuAnthropicClaudeOpus46V1,
2302 Self::EuAnthropicClaudeOpus47,
2303 Self::EuAnthropicClaudeSonnet4520250929V10,
2304 Self::EuAnthropicClaudeSonnet46,
2305 Self::GlobalAnthropicClaudeHaiku4520251001V10,
2306 Self::GlobalAnthropicClaudeOpus4520251101V10,
2307 Self::GlobalAnthropicClaudeOpus46V1,
2308 Self::GlobalAnthropicClaudeOpus47,
2309 Self::GlobalAnthropicClaudeSonnet4520250929V10,
2310 Self::GlobalAnthropicClaudeSonnet46,
2311 Self::GoogleGemma327bIt,
2312 Self::GoogleGemma34bIt,
2313 Self::JpAnthropicClaudeOpus47,
2314 Self::JpAnthropicClaudeSonnet4520250929V10,
2315 Self::JpAnthropicClaudeSonnet46,
2316 Self::MetaLlama3170bInstructV10,
2317 Self::MetaLlama318bInstructV10,
2318 Self::MetaLlama3370bInstructV10,
2319 Self::MetaLlama4Maverick17bInstructV10,
2320 Self::MetaLlama4Scout17bInstructV10,
2321 Self::MinimaxMinimaxM2,
2322 Self::MinimaxMinimaxM21,
2323 Self::MinimaxMinimaxM25,
2324 Self::MistralDevstral2123b,
2325 Self::MistralMagistralSmall2509,
2326 Self::MistralMinistral314bInstruct,
2327 Self::MistralMinistral33bInstruct,
2328 Self::MistralMinistral38bInstruct,
2329 Self::MistralMistralLarge3675bInstruct,
2330 Self::MistralPixtralLarge2502V10,
2331 Self::MistralVoxtralMini3b2507,
2332 Self::MistralVoxtralSmall24b2507,
2333 Self::MoonshotKimiK2Thinking,
2334 Self::MoonshotaiKimiK25,
2335 Self::NvidiaNemotronNano12bV2,
2336 Self::NvidiaNemotronNano330b,
2337 Self::NvidiaNemotronNano9bV2,
2338 Self::NvidiaNemotronSuper3120b,
2339 Self::OpenaiGptOss120b10,
2340 Self::OpenaiGptOss20b10,
2341 Self::OpenaiGptOssSafeguard120b,
2342 Self::OpenaiGptOssSafeguard20b,
2343 Self::QwenQwen3235bA22b2507V10,
2344 Self::QwenQwen332bV10,
2345 Self::QwenQwen3Coder30bA3bV10,
2346 Self::QwenQwen3Coder480bA35bV10,
2347 Self::QwenQwen3CoderNext,
2348 Self::QwenQwen3Next80bA3b,
2349 Self::QwenQwen3Vl235bA22b,
2350 Self::UsAnthropicClaudeHaiku4520251001V10,
2351 Self::UsAnthropicClaudeOpus4120250805V10,
2352 Self::UsAnthropicClaudeOpus4520251101V10,
2353 Self::UsAnthropicClaudeOpus46V1,
2354 Self::UsAnthropicClaudeOpus47,
2355 Self::UsAnthropicClaudeSonnet4520250929V10,
2356 Self::UsAnthropicClaudeSonnet46,
2357 Self::UsDeepseekR1V10,
2358 Self::UsMetaLlama4Maverick17bInstructV10,
2359 Self::UsMetaLlama4Scout17bInstructV10,
2360 Self::WriterPalmyraX4V10,
2361 Self::WriterPalmyraX5V10,
2362 Self::ZaiGlm47,
2363 Self::ZaiGlm47Flash,
2364 Self::ZaiGlm5,
2365 ];
2366}
2367
2368impl std::str::FromStr for BedrockModel {
2369 type Err = String;
2370
2371 #[allow(clippy::too_many_lines)]
2372 fn from_str(s: &str) -> Result<Self, Self::Err> {
2373 match s {
2374 "amazon.nova-2-lite-v1:0" => Ok(Self::AmazonNova2LiteV10),
2375 "amazon.nova-lite-v1:0" => Ok(Self::AmazonNovaLiteV10),
2376 "amazon.nova-micro-v1:0" => Ok(Self::AmazonNovaMicroV10),
2377 "amazon.nova-pro-v1:0" => Ok(Self::AmazonNovaProV10),
2378 "anthropic.claude-haiku-4-5-20251001-v1:0" => Ok(Self::AnthropicClaudeHaiku4520251001V10),
2379 "anthropic.claude-opus-4-1-20250805-v1:0" => Ok(Self::AnthropicClaudeOpus4120250805V10),
2380 "anthropic.claude-opus-4-5-20251101-v1:0" => Ok(Self::AnthropicClaudeOpus4520251101V10),
2381 "anthropic.claude-opus-4-6-v1" => Ok(Self::AnthropicClaudeOpus46V1),
2382 "anthropic.claude-opus-4-7" => Ok(Self::AnthropicClaudeOpus47),
2383 "anthropic.claude-sonnet-4-5-20250929-v1:0" => Ok(Self::AnthropicClaudeSonnet4520250929V10),
2384 "anthropic.claude-sonnet-4-6" => Ok(Self::AnthropicClaudeSonnet46),
2385 "au.anthropic.claude-haiku-4-5-20251001-v1:0" => Ok(Self::AuAnthropicClaudeHaiku4520251001V10),
2386 "au.anthropic.claude-opus-4-6-v1" => Ok(Self::AuAnthropicClaudeOpus46V1),
2387 "au.anthropic.claude-sonnet-4-5-20250929-v1:0" => Ok(Self::AuAnthropicClaudeSonnet4520250929V10),
2388 "au.anthropic.claude-sonnet-4-6" => Ok(Self::AuAnthropicClaudeSonnet46),
2389 "deepseek.r1-v1:0" => Ok(Self::DeepseekR1V10),
2390 "deepseek.v3-v1:0" => Ok(Self::DeepseekV3V10),
2391 "deepseek.v3.2" => Ok(Self::DeepseekV32),
2392 "eu.anthropic.claude-haiku-4-5-20251001-v1:0" => Ok(Self::EuAnthropicClaudeHaiku4520251001V10),
2393 "eu.anthropic.claude-opus-4-5-20251101-v1:0" => Ok(Self::EuAnthropicClaudeOpus4520251101V10),
2394 "eu.anthropic.claude-opus-4-6-v1" => Ok(Self::EuAnthropicClaudeOpus46V1),
2395 "eu.anthropic.claude-opus-4-7" => Ok(Self::EuAnthropicClaudeOpus47),
2396 "eu.anthropic.claude-sonnet-4-5-20250929-v1:0" => Ok(Self::EuAnthropicClaudeSonnet4520250929V10),
2397 "eu.anthropic.claude-sonnet-4-6" => Ok(Self::EuAnthropicClaudeSonnet46),
2398 "global.anthropic.claude-haiku-4-5-20251001-v1:0" => Ok(Self::GlobalAnthropicClaudeHaiku4520251001V10),
2399 "global.anthropic.claude-opus-4-5-20251101-v1:0" => Ok(Self::GlobalAnthropicClaudeOpus4520251101V10),
2400 "global.anthropic.claude-opus-4-6-v1" => Ok(Self::GlobalAnthropicClaudeOpus46V1),
2401 "global.anthropic.claude-opus-4-7" => Ok(Self::GlobalAnthropicClaudeOpus47),
2402 "global.anthropic.claude-sonnet-4-5-20250929-v1:0" => Ok(Self::GlobalAnthropicClaudeSonnet4520250929V10),
2403 "global.anthropic.claude-sonnet-4-6" => Ok(Self::GlobalAnthropicClaudeSonnet46),
2404 "google.gemma-3-27b-it" => Ok(Self::GoogleGemma327bIt),
2405 "google.gemma-3-4b-it" => Ok(Self::GoogleGemma34bIt),
2406 "jp.anthropic.claude-opus-4-7" => Ok(Self::JpAnthropicClaudeOpus47),
2407 "jp.anthropic.claude-sonnet-4-5-20250929-v1:0" => Ok(Self::JpAnthropicClaudeSonnet4520250929V10),
2408 "jp.anthropic.claude-sonnet-4-6" => Ok(Self::JpAnthropicClaudeSonnet46),
2409 "meta.llama3-1-70b-instruct-v1:0" => Ok(Self::MetaLlama3170bInstructV10),
2410 "meta.llama3-1-8b-instruct-v1:0" => Ok(Self::MetaLlama318bInstructV10),
2411 "meta.llama3-3-70b-instruct-v1:0" => Ok(Self::MetaLlama3370bInstructV10),
2412 "meta.llama4-maverick-17b-instruct-v1:0" => Ok(Self::MetaLlama4Maverick17bInstructV10),
2413 "meta.llama4-scout-17b-instruct-v1:0" => Ok(Self::MetaLlama4Scout17bInstructV10),
2414 "minimax.minimax-m2" => Ok(Self::MinimaxMinimaxM2),
2415 "minimax.minimax-m2.1" => Ok(Self::MinimaxMinimaxM21),
2416 "minimax.minimax-m2.5" => Ok(Self::MinimaxMinimaxM25),
2417 "mistral.devstral-2-123b" => Ok(Self::MistralDevstral2123b),
2418 "mistral.magistral-small-2509" => Ok(Self::MistralMagistralSmall2509),
2419 "mistral.ministral-3-14b-instruct" => Ok(Self::MistralMinistral314bInstruct),
2420 "mistral.ministral-3-3b-instruct" => Ok(Self::MistralMinistral33bInstruct),
2421 "mistral.ministral-3-8b-instruct" => Ok(Self::MistralMinistral38bInstruct),
2422 "mistral.mistral-large-3-675b-instruct" => Ok(Self::MistralMistralLarge3675bInstruct),
2423 "mistral.pixtral-large-2502-v1:0" => Ok(Self::MistralPixtralLarge2502V10),
2424 "mistral.voxtral-mini-3b-2507" => Ok(Self::MistralVoxtralMini3b2507),
2425 "mistral.voxtral-small-24b-2507" => Ok(Self::MistralVoxtralSmall24b2507),
2426 "moonshot.kimi-k2-thinking" => Ok(Self::MoonshotKimiK2Thinking),
2427 "moonshotai.kimi-k2.5" => Ok(Self::MoonshotaiKimiK25),
2428 "nvidia.nemotron-nano-12b-v2" => Ok(Self::NvidiaNemotronNano12bV2),
2429 "nvidia.nemotron-nano-3-30b" => Ok(Self::NvidiaNemotronNano330b),
2430 "nvidia.nemotron-nano-9b-v2" => Ok(Self::NvidiaNemotronNano9bV2),
2431 "nvidia.nemotron-super-3-120b" => Ok(Self::NvidiaNemotronSuper3120b),
2432 "openai.gpt-oss-120b-1:0" => Ok(Self::OpenaiGptOss120b10),
2433 "openai.gpt-oss-20b-1:0" => Ok(Self::OpenaiGptOss20b10),
2434 "openai.gpt-oss-safeguard-120b" => Ok(Self::OpenaiGptOssSafeguard120b),
2435 "openai.gpt-oss-safeguard-20b" => Ok(Self::OpenaiGptOssSafeguard20b),
2436 "qwen.qwen3-235b-a22b-2507-v1:0" => Ok(Self::QwenQwen3235bA22b2507V10),
2437 "qwen.qwen3-32b-v1:0" => Ok(Self::QwenQwen332bV10),
2438 "qwen.qwen3-coder-30b-a3b-v1:0" => Ok(Self::QwenQwen3Coder30bA3bV10),
2439 "qwen.qwen3-coder-480b-a35b-v1:0" => Ok(Self::QwenQwen3Coder480bA35bV10),
2440 "qwen.qwen3-coder-next" => Ok(Self::QwenQwen3CoderNext),
2441 "qwen.qwen3-next-80b-a3b" => Ok(Self::QwenQwen3Next80bA3b),
2442 "qwen.qwen3-vl-235b-a22b" => Ok(Self::QwenQwen3Vl235bA22b),
2443 "us.anthropic.claude-haiku-4-5-20251001-v1:0" => Ok(Self::UsAnthropicClaudeHaiku4520251001V10),
2444 "us.anthropic.claude-opus-4-1-20250805-v1:0" => Ok(Self::UsAnthropicClaudeOpus4120250805V10),
2445 "us.anthropic.claude-opus-4-5-20251101-v1:0" => Ok(Self::UsAnthropicClaudeOpus4520251101V10),
2446 "us.anthropic.claude-opus-4-6-v1" => Ok(Self::UsAnthropicClaudeOpus46V1),
2447 "us.anthropic.claude-opus-4-7" => Ok(Self::UsAnthropicClaudeOpus47),
2448 "us.anthropic.claude-sonnet-4-5-20250929-v1:0" => Ok(Self::UsAnthropicClaudeSonnet4520250929V10),
2449 "us.anthropic.claude-sonnet-4-6" => Ok(Self::UsAnthropicClaudeSonnet46),
2450 "us.deepseek.r1-v1:0" => Ok(Self::UsDeepseekR1V10),
2451 "us.meta.llama4-maverick-17b-instruct-v1:0" => Ok(Self::UsMetaLlama4Maverick17bInstructV10),
2452 "us.meta.llama4-scout-17b-instruct-v1:0" => Ok(Self::UsMetaLlama4Scout17bInstructV10),
2453 "writer.palmyra-x4-v1:0" => Ok(Self::WriterPalmyraX4V10),
2454 "writer.palmyra-x5-v1:0" => Ok(Self::WriterPalmyraX5V10),
2455 "zai.glm-4.7" => Ok(Self::ZaiGlm47),
2456 "zai.glm-4.7-flash" => Ok(Self::ZaiGlm47Flash),
2457 "zai.glm-5" => Ok(Self::ZaiGlm5),
2458 _ => Err(format!("Unknown bedrock model: '{s}'")),
2459 }
2460 }
2461}
2462
2463#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2465pub enum LlmModel {
2466 Anthropic(AnthropicModel),
2467 Codex(CodexModel),
2468 DeepSeek(DeepSeekModel),
2469 Gemini(GeminiModel),
2470 Moonshot(MoonshotModel),
2471 Openai(OpenaiModel),
2472 OpenRouter(OpenRouterModel),
2473 ZAi(ZAiModel),
2474 Bedrock(BedrockModel),
2475 Ollama(String),
2476 LlamaCpp(String),
2477}
2478
2479impl From<AnthropicModel> for LlmModel {
2480 fn from(m: AnthropicModel) -> Self { LlmModel::Anthropic(m) }
2481}
2482
2483impl From<CodexModel> for LlmModel {
2484 fn from(m: CodexModel) -> Self { LlmModel::Codex(m) }
2485}
2486
2487impl From<DeepSeekModel> for LlmModel {
2488 fn from(m: DeepSeekModel) -> Self { LlmModel::DeepSeek(m) }
2489}
2490
2491impl From<GeminiModel> for LlmModel {
2492 fn from(m: GeminiModel) -> Self { LlmModel::Gemini(m) }
2493}
2494
2495impl From<MoonshotModel> for LlmModel {
2496 fn from(m: MoonshotModel) -> Self { LlmModel::Moonshot(m) }
2497}
2498
2499impl From<OpenaiModel> for LlmModel {
2500 fn from(m: OpenaiModel) -> Self { LlmModel::Openai(m) }
2501}
2502
2503impl From<OpenRouterModel> for LlmModel {
2504 fn from(m: OpenRouterModel) -> Self { LlmModel::OpenRouter(m) }
2505}
2506
2507impl From<ZAiModel> for LlmModel {
2508 fn from(m: ZAiModel) -> Self { LlmModel::ZAi(m) }
2509}
2510
2511impl From<BedrockModel> for LlmModel {
2512 fn from(m: BedrockModel) -> Self { LlmModel::Bedrock(m) }
2513}
2514
2515impl LlmModel {
2516 pub fn model_id(&self) -> Cow<'static, str> {
2518 match self {
2519 Self::Anthropic(m) => Cow::Borrowed(m.model_id()),
2520 Self::Codex(m) => Cow::Borrowed(m.model_id()),
2521 Self::DeepSeek(m) => Cow::Borrowed(m.model_id()),
2522 Self::Gemini(m) => Cow::Borrowed(m.model_id()),
2523 Self::Moonshot(m) => Cow::Borrowed(m.model_id()),
2524 Self::Openai(m) => Cow::Borrowed(m.model_id()),
2525 Self::OpenRouter(m) => Cow::Borrowed(m.model_id()),
2526 Self::ZAi(m) => Cow::Borrowed(m.model_id()),
2527 Self::Bedrock(m) => Cow::Borrowed(m.model_id()),
2528 Self::Ollama(s) | Self::LlamaCpp(s) => Cow::Owned(s.clone()),
2529 }
2530 }
2531
2532 pub fn display_name(&self) -> Cow<'static, str> {
2534 match self {
2535 Self::Anthropic(m) => Cow::Borrowed(m.display_name()),
2536 Self::Codex(m) => Cow::Borrowed(m.display_name()),
2537 Self::DeepSeek(m) => Cow::Borrowed(m.display_name()),
2538 Self::Gemini(m) => Cow::Borrowed(m.display_name()),
2539 Self::Moonshot(m) => Cow::Borrowed(m.display_name()),
2540 Self::Openai(m) => Cow::Borrowed(m.display_name()),
2541 Self::OpenRouter(m) => Cow::Borrowed(m.display_name()),
2542 Self::ZAi(m) => Cow::Borrowed(m.display_name()),
2543 Self::Bedrock(m) => Cow::Borrowed(m.display_name()),
2544 Self::Ollama(s) => Cow::Owned(format!("Ollama {s}")),
2545 Self::LlamaCpp(s) => Cow::Owned(format!("LlamaCpp {s}")),
2546 }
2547 }
2548
2549 pub fn provider(&self) -> &'static str {
2551 match self {
2552 Self::Anthropic(_) => "anthropic",
2553 Self::Codex(_) => "codex",
2554 Self::DeepSeek(_) => "deepseek",
2555 Self::Gemini(_) => "gemini",
2556 Self::Moonshot(_) => "moonshot",
2557 Self::Openai(_) => "openai",
2558 Self::OpenRouter(_) => "openrouter",
2559 Self::ZAi(_) => "zai",
2560 Self::Bedrock(_) => "bedrock",
2561 Self::Ollama(_) => "ollama",
2562 Self::LlamaCpp(_) => "llamacpp",
2563 }
2564 }
2565
2566 pub fn provider_display_name(&self) -> &'static str {
2568 match self {
2569 Self::Anthropic(_) => "Anthropic",
2570 Self::Codex(_) => "Codex",
2571 Self::DeepSeek(_) => "DeepSeek",
2572 Self::Gemini(_) => "Gemini",
2573 Self::Moonshot(_) => "Moonshot",
2574 Self::Openai(_) => "OpenAI",
2575 Self::OpenRouter(_) => "OpenRouter",
2576 Self::ZAi(_) => "ZAI",
2577 Self::Bedrock(_) => "AWS Bedrock",
2578 Self::Ollama(_) => "Ollama",
2579 Self::LlamaCpp(_) => "LlamaCpp",
2580 }
2581 }
2582
2583 pub fn context_window(&self) -> Option<u32> {
2585 match self {
2586 Self::Anthropic(m) => Some(m.context_window()),
2587 Self::Codex(m) => Some(m.context_window()),
2588 Self::DeepSeek(m) => Some(m.context_window()),
2589 Self::Gemini(m) => Some(m.context_window()),
2590 Self::Moonshot(m) => Some(m.context_window()),
2591 Self::Openai(m) => Some(m.context_window()),
2592 Self::OpenRouter(m) => Some(m.context_window()),
2593 Self::ZAi(m) => Some(m.context_window()),
2594 Self::Bedrock(m) => Some(m.context_window()),
2595 Self::Ollama(_) | Self::LlamaCpp(_) => None,
2596 }
2597 }
2598
2599 pub fn required_env_var(&self) -> Option<&'static str> {
2601 match self {
2602 Self::Anthropic(_) => Some("ANTHROPIC_API_KEY"),
2603 Self::DeepSeek(_) => Some("DEEPSEEK_API_KEY"),
2604 Self::Gemini(_) => Some("GEMINI_API_KEY"),
2605 Self::Moonshot(_) => Some("MOONSHOT_API_KEY"),
2606 Self::Openai(_) => Some("OPENAI_API_KEY"),
2607 Self::OpenRouter(_) => Some("OPENROUTER_API_KEY"),
2608 Self::ZAi(_) => Some("ZAI_API_KEY"),
2609 Self::Codex(_) | Self::Bedrock(_) | Self::Ollama(_) | Self::LlamaCpp(_) => None,
2610 }
2611 }
2612
2613 pub const ALL_REQUIRED_ENV_VARS: &[&str] = &["ANTHROPIC_API_KEY", "DEEPSEEK_API_KEY", "GEMINI_API_KEY", "MOONSHOT_API_KEY", "OPENAI_API_KEY", "OPENROUTER_API_KEY", "ZAI_API_KEY"];
2615
2616 pub fn oauth_provider_id(&self) -> Option<&'static str> {
2618 match self {
2619 Self::Codex(_) => Some("codex"),
2620 Self::Anthropic(_) | Self::DeepSeek(_) | Self::Gemini(_) | Self::Moonshot(_) | Self::Openai(_) | Self::OpenRouter(_) | Self::ZAi(_) | Self::Bedrock(_) | Self::Ollama(_) | Self::LlamaCpp(_) => None,
2621 }
2622 }
2623
2624 pub fn reasoning_levels(&self) -> &'static [ReasoningEffort] {
2626 match self {
2627 Self::Anthropic(m) => m.reasoning_levels(),
2628 Self::Codex(m) => m.reasoning_levels(),
2629 Self::DeepSeek(m) => m.reasoning_levels(),
2630 Self::Gemini(m) => m.reasoning_levels(),
2631 Self::Moonshot(m) => m.reasoning_levels(),
2632 Self::Openai(m) => m.reasoning_levels(),
2633 Self::OpenRouter(m) => m.reasoning_levels(),
2634 Self::ZAi(m) => m.reasoning_levels(),
2635 Self::Bedrock(m) => m.reasoning_levels(),
2636 Self::Ollama(_) | Self::LlamaCpp(_) => &[],
2637 }
2638 }
2639
2640 pub fn supports_reasoning(&self) -> bool {
2642 !self.reasoning_levels().is_empty()
2643 }
2644
2645 pub fn supports_image(&self) -> bool {
2647 match self {
2648 Self::Anthropic(m) => m.supports_image(),
2649 Self::Codex(m) => m.supports_image(),
2650 Self::DeepSeek(m) => m.supports_image(),
2651 Self::Gemini(m) => m.supports_image(),
2652 Self::Moonshot(m) => m.supports_image(),
2653 Self::Openai(m) => m.supports_image(),
2654 Self::OpenRouter(m) => m.supports_image(),
2655 Self::ZAi(m) => m.supports_image(),
2656 Self::Bedrock(m) => m.supports_image(),
2657 Self::Ollama(_) | Self::LlamaCpp(_) => false,
2658 }
2659 }
2660
2661 pub fn supports_audio(&self) -> bool {
2663 match self {
2664 Self::Anthropic(m) => m.supports_audio(),
2665 Self::Codex(m) => m.supports_audio(),
2666 Self::DeepSeek(m) => m.supports_audio(),
2667 Self::Gemini(m) => m.supports_audio(),
2668 Self::Moonshot(m) => m.supports_audio(),
2669 Self::Openai(m) => m.supports_audio(),
2670 Self::OpenRouter(m) => m.supports_audio(),
2671 Self::ZAi(m) => m.supports_audio(),
2672 Self::Bedrock(m) => m.supports_audio(),
2673 Self::Ollama(_) | Self::LlamaCpp(_) => false,
2674 }
2675 }
2676
2677 pub fn all() -> &'static [LlmModel] {
2679 static ALL: LazyLock<Vec<LlmModel>> = LazyLock::new(|| {
2680 let mut v = Vec::new();
2681 v.extend(AnthropicModel::ALL.iter().copied().map(LlmModel::Anthropic));
2682 v.extend(CodexModel::ALL.iter().copied().map(LlmModel::Codex));
2683 v.extend(DeepSeekModel::ALL.iter().copied().map(LlmModel::DeepSeek));
2684 v.extend(GeminiModel::ALL.iter().copied().map(LlmModel::Gemini));
2685 v.extend(MoonshotModel::ALL.iter().copied().map(LlmModel::Moonshot));
2686 v.extend(OpenaiModel::ALL.iter().copied().map(LlmModel::Openai));
2687 v.extend(OpenRouterModel::ALL.iter().copied().map(LlmModel::OpenRouter));
2688 v.extend(ZAiModel::ALL.iter().copied().map(LlmModel::ZAi));
2689 v.extend(BedrockModel::ALL.iter().copied().map(LlmModel::Bedrock));
2690 v
2691 });
2692 &ALL
2693 }
2694}
2695
2696impl std::fmt::Display for LlmModel {
2697 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2698 write!(f, "{}:{}", self.provider(), self.model_id())
2699 }
2700}
2701
2702impl std::str::FromStr for LlmModel {
2703 type Err = String;
2704
2705 fn from_str(s: &str) -> Result<Self, Self::Err> {
2707 let (provider_str, model_str) = s.split_once(':').unwrap_or((s, ""));
2708 match provider_str {
2709 "anthropic" => model_str.parse::<AnthropicModel>().map(Self::Anthropic),
2710 "codex" => model_str.parse::<CodexModel>().map(Self::Codex),
2711 "deepseek" => model_str.parse::<DeepSeekModel>().map(Self::DeepSeek),
2712 "gemini" => model_str.parse::<GeminiModel>().map(Self::Gemini),
2713 "moonshot" => model_str.parse::<MoonshotModel>().map(Self::Moonshot),
2714 "openai" => model_str.parse::<OpenaiModel>().map(Self::Openai),
2715 "openrouter" => model_str.parse::<OpenRouterModel>().map(Self::OpenRouter),
2716 "zai" => model_str.parse::<ZAiModel>().map(Self::ZAi),
2717 "bedrock" => model_str.parse::<BedrockModel>().map(Self::Bedrock),
2718 "ollama" => Ok(Self::Ollama(model_str.to_string())),
2719 "llamacpp" => Ok(Self::LlamaCpp(model_str.to_string())),
2720 _ => Err(format!("Unknown provider: '{provider_str}'")),
2721 }
2722 }
2723}