Skip to main content

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