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