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