Skip to main content

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