Skip to main content

llm/opt/rustwide/target/x86_64-unknown-linux-gnu/debug/build/aether-llm-756840116a446bbc/out/
generated.rs

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