Skip to main content

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