Skip to main content

llm/opt/rustwide/target/x86_64-unknown-linux-gnu/debug/build/aether-llm-641682209560f1e7/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#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum AnthropicModel {
9    Claude35Haiku20241022,
10    Claude35Sonnet20240620,
11    Claude35Sonnet20241022,
12    Claude37Sonnet20250219,
13    Claude3Haiku20240307,
14    Claude3Opus20240229,
15    Claude3Sonnet20240229,
16    ClaudeHaiku45,
17    ClaudeHaiku4520251001,
18    ClaudeOpus40,
19    ClaudeOpus41,
20    ClaudeOpus4120250805,
21    ClaudeOpus420250514,
22    ClaudeOpus45,
23    ClaudeOpus4520251101,
24    ClaudeOpus46,
25    ClaudeOpus47,
26    ClaudeSonnet40,
27    ClaudeSonnet420250514,
28    ClaudeSonnet45,
29    ClaudeSonnet4520250929,
30    ClaudeSonnet46,
31}
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum CodexModel {
34    Gpt5,
35    Gpt5Codex,
36    Gpt51,
37    Gpt51Codex,
38    Gpt51CodexMax,
39    Gpt51CodexMini,
40    Gpt52,
41    Gpt52Codex,
42    Gpt52Pro,
43    Gpt53Codex,
44    Gpt53CodexSpark,
45    Gpt54,
46    Gpt54Mini,
47    Gpt54Nano,
48    Gpt54Pro,
49    Gpt55,
50    Gpt55Pro,
51}
52#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
53pub enum DeepSeekModel {
54    DeepseekChat,
55    DeepseekReasoner,
56    DeepseekV4Flash,
57    DeepseekV4Pro,
58}
59#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
60pub enum GeminiModel {
61    Gemini15Flash,
62    Gemini15Flash8b,
63    Gemini15Pro,
64    Gemini20Flash,
65    Gemini20FlashLite,
66    Gemini25Flash,
67    Gemini25FlashLite,
68    Gemini25FlashLitePreview0617,
69    Gemini25FlashLitePreview092025,
70    Gemini25FlashPreview0417,
71    Gemini25FlashPreview0520,
72    Gemini25FlashPreview092025,
73    Gemini25Pro,
74    Gemini25ProPreview0506,
75    Gemini25ProPreview0605,
76    Gemini3FlashPreview,
77    Gemini3ProPreview,
78    Gemini31FlashLite,
79    Gemini31FlashLitePreview,
80    Gemini31ProPreview,
81    Gemini31ProPreviewCustomtools,
82    GeminiLive25Flash,
83    GeminiLive25FlashPreviewNativeAudio,
84    Gemma327bIt,
85    Gemma426bA4bIt,
86    Gemma431bIt,
87}
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
89pub enum MoonshotModel {
90    KimiK20711Preview,
91    KimiK20905Preview,
92    KimiK2Thinking,
93    KimiK2ThinkingTurbo,
94    KimiK2TurboPreview,
95    KimiK25,
96    KimiK26,
97}
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
99pub enum OpenaiModel {
100    Gpt4,
101    Gpt4Turbo,
102    Gpt41,
103    Gpt41Mini,
104    Gpt41Nano,
105    Gpt4o,
106    Gpt4o20240513,
107    Gpt4o20240806,
108    Gpt4o20241120,
109    Gpt4oMini,
110    Gpt5,
111    Gpt5Codex,
112    Gpt5Mini,
113    Gpt5Nano,
114    Gpt5Pro,
115    Gpt51,
116    Gpt51Codex,
117    Gpt51CodexMax,
118    Gpt51CodexMini,
119    Gpt52,
120    Gpt52Codex,
121    Gpt52Pro,
122    Gpt53Codex,
123    Gpt53CodexSpark,
124    Gpt54,
125    Gpt54Mini,
126    Gpt54Nano,
127    Gpt54Pro,
128    Gpt55,
129    Gpt55Pro,
130    O1,
131    O1Pro,
132    O3,
133    O3DeepResearch,
134    O3Mini,
135    O3Pro,
136    O4Mini,
137    O4MiniDeepResearch,
138}
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
140pub enum OpenRouterModel {
141    AnthropicClaude35Haiku,
142    AnthropicClaude37Sonnet,
143    AnthropicClaudeHaiku45,
144    AnthropicClaudeOpus4,
145    AnthropicClaudeOpus41,
146    AnthropicClaudeOpus45,
147    AnthropicClaudeOpus46,
148    AnthropicClaudeOpus47,
149    AnthropicClaudeSonnet4,
150    AnthropicClaudeSonnet45,
151    AnthropicClaudeSonnet46,
152    ArceeAiTrinityLargePreviewFree,
153    ArceeAiTrinityLargeThinking,
154    DeepseekDeepseekChatV31,
155    DeepseekDeepseekR1,
156    DeepseekDeepseekV31Terminus,
157    DeepseekDeepseekV31TerminusExacto,
158    DeepseekDeepseekV32,
159    DeepseekDeepseekV32Speciale,
160    DeepseekDeepseekV4Flash,
161    DeepseekDeepseekV4Pro,
162    GoogleGemini20Flash001,
163    GoogleGemini25Flash,
164    GoogleGemini25FlashLite,
165    GoogleGemini25FlashLitePreview092025,
166    GoogleGemini25FlashPreview092025,
167    GoogleGemini25Pro,
168    GoogleGemini25ProPreview0506,
169    GoogleGemini25ProPreview0605,
170    GoogleGemini3FlashPreview,
171    GoogleGemini3ProPreview,
172    GoogleGemini31FlashLitePreview,
173    GoogleGemini31ProPreview,
174    GoogleGemini31ProPreviewCustomtools,
175    GoogleGemma327bIt,
176    GoogleGemma327bItFree,
177    GoogleGemma426bA4bIt,
178    GoogleGemma426bA4bItFree,
179    GoogleGemma431bIt,
180    GoogleGemma431bItFree,
181    InceptionMercury2,
182    MetaLlamaLlama3370bInstructFree,
183    MinimaxMinimax01,
184    MinimaxMinimaxM1,
185    MinimaxMinimaxM2,
186    MinimaxMinimaxM21,
187    MinimaxMinimaxM25,
188    MinimaxMinimaxM25Free,
189    MinimaxMinimaxM27,
190    MistralaiCodestral2508,
191    MistralaiDevstral2512,
192    MistralaiDevstralMedium2507,
193    MistralaiDevstralSmall2505,
194    MistralaiDevstralSmall2507,
195    MistralaiMistralMedium3,
196    MistralaiMistralMedium31,
197    MistralaiMistralSmall2603,
198    MistralaiMistralSmall3124bInstruct,
199    MistralaiMistralSmall3224bInstruct,
200    MoonshotaiKimiK2,
201    MoonshotaiKimiK20905,
202    MoonshotaiKimiK20905Exacto,
203    MoonshotaiKimiK2Thinking,
204    MoonshotaiKimiK25,
205    MoonshotaiKimiK26,
206    NousresearchHermes4405b,
207    NousresearchHermes470b,
208    NvidiaNemotron3Nano30bA3bFree,
209    NvidiaNemotron3NanoOmni30bA3bReasoningFree,
210    NvidiaNemotron3Super120bA12b,
211    NvidiaNemotron3Super120bA12bFree,
212    NvidiaNemotronNano12bV2VlFree,
213    NvidiaNemotronNano9bV2,
214    NvidiaNemotronNano9bV2Free,
215    OpenaiGpt41,
216    OpenaiGpt41Mini,
217    OpenaiGpt4oMini,
218    OpenaiGpt5,
219    OpenaiGpt5Codex,
220    OpenaiGpt5Image,
221    OpenaiGpt5Mini,
222    OpenaiGpt5Nano,
223    OpenaiGpt5Pro,
224    OpenaiGpt51,
225    OpenaiGpt51Chat,
226    OpenaiGpt51Codex,
227    OpenaiGpt51CodexMax,
228    OpenaiGpt51CodexMini,
229    OpenaiGpt52,
230    OpenaiGpt52Chat,
231    OpenaiGpt52Codex,
232    OpenaiGpt52Pro,
233    OpenaiGpt53Codex,
234    OpenaiGpt54,
235    OpenaiGpt54Mini,
236    OpenaiGpt54Nano,
237    OpenaiGpt54Pro,
238    OpenaiGpt55,
239    OpenaiGpt55Pro,
240    OpenaiGptOss120b,
241    OpenaiGptOss120bExacto,
242    OpenaiGptOss120bFree,
243    OpenaiGptOss20b,
244    OpenaiGptOss20bFree,
245    OpenaiGptOssSafeguard20b,
246    OpenaiO4Mini,
247    OpenrouterElephantAlpha,
248    OpenrouterFree,
249    OpenrouterOwlAlpha,
250    OpenrouterParetoCode,
251    PoolsideLagunaM1Free,
252    PoolsideLagunaXs2Free,
253    PrimeIntellectIntellect3,
254    QwenQwen3627b,
255    QwenQwenPlus,
256    QwenQwen3235bA22b0725,
257    QwenQwen3235bA22bThinking2507,
258    QwenQwen330bA3bInstruct2507,
259    QwenQwen330bA3bThinking2507,
260    QwenQwen3Coder,
261    QwenQwen3Coder30bA3bInstruct,
262    QwenQwen3CoderFlash,
263    QwenQwen3CoderPlus,
264    QwenQwen3CoderExacto,
265    QwenQwen3Max,
266    QwenQwen3Next80bA3bInstruct,
267    QwenQwen3Next80bA3bThinking,
268    QwenQwen35397bA17b,
269    QwenQwen35Flash0223,
270    QwenQwen35Plus0215,
271    QwenQwen36Plus,
272    StepfunStep35Flash,
273    TencentHy3Preview,
274    XAiGrok3,
275    XAiGrok3Beta,
276    XAiGrok3Mini,
277    XAiGrok3MiniBeta,
278    XAiGrok4,
279    XAiGrok4Fast,
280    XAiGrok41Fast,
281    XAiGrok420Beta,
282    XAiGrok43,
283    XAiGrokCodeFast1,
284    XiaomiMimoV2Flash,
285    XiaomiMimoV2Omni,
286    XiaomiMimoV2Pro,
287    XiaomiMimoV25,
288    XiaomiMimoV25Pro,
289    ZAiGlm45,
290    ZAiGlm45Air,
291    ZAiGlm45v,
292    ZAiGlm46,
293    ZAiGlm46Exacto,
294    ZAiGlm47,
295    ZAiGlm47Flash,
296    ZAiGlm5,
297    ZAiGlm5Turbo,
298    ZAiGlm51,
299}
300#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
301pub enum ZAiModel {
302    Glm45,
303    Glm45Air,
304    Glm45Flash,
305    Glm45v,
306    Glm46,
307    Glm46v,
308    Glm47,
309    Glm47Flash,
310    Glm47Flashx,
311    Glm5,
312    Glm5Turbo,
313    Glm51,
314    Glm5vTurbo,
315}
316#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
317pub enum BedrockFoundationModel {
318    AmazonNova2LiteV10,
319    AmazonNovaLiteV10,
320    AmazonNovaMicroV10,
321    AmazonNovaProV10,
322    AnthropicClaudeHaiku4520251001V10,
323    AnthropicClaudeOpus4120250805V10,
324    AnthropicClaudeOpus4520251101V10,
325    AnthropicClaudeOpus46V1,
326    AnthropicClaudeOpus47,
327    AnthropicClaudeSonnet4520250929V10,
328    AnthropicClaudeSonnet46,
329    AuAnthropicClaudeHaiku4520251001V10,
330    AuAnthropicClaudeOpus46V1,
331    AuAnthropicClaudeSonnet4520250929V10,
332    AuAnthropicClaudeSonnet46,
333    DeepseekR1V10,
334    DeepseekV3V10,
335    DeepseekV32,
336    EuAnthropicClaudeHaiku4520251001V10,
337    EuAnthropicClaudeOpus4520251101V10,
338    EuAnthropicClaudeOpus46V1,
339    EuAnthropicClaudeOpus47,
340    EuAnthropicClaudeSonnet4520250929V10,
341    EuAnthropicClaudeSonnet46,
342    GlobalAnthropicClaudeHaiku4520251001V10,
343    GlobalAnthropicClaudeOpus4520251101V10,
344    GlobalAnthropicClaudeOpus46V1,
345    GlobalAnthropicClaudeOpus47,
346    GlobalAnthropicClaudeSonnet4520250929V10,
347    GlobalAnthropicClaudeSonnet46,
348    GoogleGemma327bIt,
349    GoogleGemma34bIt,
350    JpAnthropicClaudeOpus47,
351    JpAnthropicClaudeSonnet4520250929V10,
352    JpAnthropicClaudeSonnet46,
353    MetaLlama3170bInstructV10,
354    MetaLlama318bInstructV10,
355    MetaLlama3370bInstructV10,
356    MetaLlama4Maverick17bInstructV10,
357    MetaLlama4Scout17bInstructV10,
358    MinimaxMinimaxM2,
359    MinimaxMinimaxM21,
360    MinimaxMinimaxM25,
361    MistralDevstral2123b,
362    MistralMagistralSmall2509,
363    MistralMinistral314bInstruct,
364    MistralMinistral33bInstruct,
365    MistralMinistral38bInstruct,
366    MistralMistralLarge3675bInstruct,
367    MistralPixtralLarge2502V10,
368    MistralVoxtralMini3b2507,
369    MistralVoxtralSmall24b2507,
370    MoonshotKimiK2Thinking,
371    MoonshotaiKimiK25,
372    NvidiaNemotronNano12bV2,
373    NvidiaNemotronNano330b,
374    NvidiaNemotronNano9bV2,
375    NvidiaNemotronSuper3120b,
376    OpenaiGptOss120b10,
377    OpenaiGptOss20b10,
378    OpenaiGptOssSafeguard120b,
379    OpenaiGptOssSafeguard20b,
380    QwenQwen3235bA22b2507V10,
381    QwenQwen332bV10,
382    QwenQwen3Coder30bA3bV10,
383    QwenQwen3Coder480bA35bV10,
384    QwenQwen3CoderNext,
385    QwenQwen3Next80bA3b,
386    QwenQwen3Vl235bA22b,
387    UsAnthropicClaudeHaiku4520251001V10,
388    UsAnthropicClaudeOpus4120250805V10,
389    UsAnthropicClaudeOpus4520251101V10,
390    UsAnthropicClaudeOpus46V1,
391    UsAnthropicClaudeOpus47,
392    UsAnthropicClaudeSonnet4520250929V10,
393    UsAnthropicClaudeSonnet46,
394    UsDeepseekR1V10,
395    UsMetaLlama4Maverick17bInstructV10,
396    UsMetaLlama4Scout17bInstructV10,
397    WriterPalmyraX4V10,
398    WriterPalmyraX5V10,
399    ZaiGlm47,
400    ZaiGlm47Flash,
401    ZaiGlm5,
402}
403impl AnthropicModel {
404    #[allow(clippy::too_many_lines)]
405    fn model_id(self) -> &'static str {
406        match self {
407            Self::Claude35Haiku20241022 => "claude-3-5-haiku-20241022",
408            Self::Claude35Sonnet20240620 => "claude-3-5-sonnet-20240620",
409            Self::Claude35Sonnet20241022 => "claude-3-5-sonnet-20241022",
410            Self::Claude37Sonnet20250219 => "claude-3-7-sonnet-20250219",
411            Self::Claude3Haiku20240307 => "claude-3-haiku-20240307",
412            Self::Claude3Opus20240229 => "claude-3-opus-20240229",
413            Self::Claude3Sonnet20240229 => "claude-3-sonnet-20240229",
414            Self::ClaudeHaiku45 => "claude-haiku-4-5",
415            Self::ClaudeHaiku4520251001 => "claude-haiku-4-5-20251001",
416            Self::ClaudeOpus40 => "claude-opus-4-0",
417            Self::ClaudeOpus41 => "claude-opus-4-1",
418            Self::ClaudeOpus4120250805 => "claude-opus-4-1-20250805",
419            Self::ClaudeOpus420250514 => "claude-opus-4-20250514",
420            Self::ClaudeOpus45 => "claude-opus-4-5",
421            Self::ClaudeOpus4520251101 => "claude-opus-4-5-20251101",
422            Self::ClaudeOpus46 => "claude-opus-4-6",
423            Self::ClaudeOpus47 => "claude-opus-4-7",
424            Self::ClaudeSonnet40 => "claude-sonnet-4-0",
425            Self::ClaudeSonnet420250514 => "claude-sonnet-4-20250514",
426            Self::ClaudeSonnet45 => "claude-sonnet-4-5",
427            Self::ClaudeSonnet4520250929 => "claude-sonnet-4-5-20250929",
428            Self::ClaudeSonnet46 => "claude-sonnet-4-6",
429        }
430    }
431    #[allow(clippy::too_many_lines)]
432    fn display_name(self) -> &'static str {
433        match self {
434            Self::Claude3Haiku20240307 => "Claude Haiku 3",
435            Self::Claude35Haiku20241022 => "Claude Haiku 3.5",
436            Self::ClaudeHaiku4520251001 => "Claude Haiku 4.5",
437            Self::ClaudeHaiku45 => "Claude Haiku 4.5 (latest)",
438            Self::Claude3Opus20240229 => "Claude Opus 3",
439            Self::ClaudeOpus420250514 => "Claude Opus 4",
440            Self::ClaudeOpus40 => "Claude Opus 4 (latest)",
441            Self::ClaudeOpus4120250805 => "Claude Opus 4.1",
442            Self::ClaudeOpus41 => "Claude Opus 4.1 (latest)",
443            Self::ClaudeOpus4520251101 => "Claude Opus 4.5",
444            Self::ClaudeOpus45 => "Claude Opus 4.5 (latest)",
445            Self::ClaudeOpus46 => "Claude Opus 4.6",
446            Self::ClaudeOpus47 => "Claude Opus 4.7",
447            Self::Claude3Sonnet20240229 => "Claude Sonnet 3",
448            Self::Claude35Sonnet20240620 => "Claude Sonnet 3.5",
449            Self::Claude35Sonnet20241022 => "Claude Sonnet 3.5 v2",
450            Self::Claude37Sonnet20250219 => "Claude Sonnet 3.7",
451            Self::ClaudeSonnet420250514 => "Claude Sonnet 4",
452            Self::ClaudeSonnet40 => "Claude Sonnet 4 (latest)",
453            Self::ClaudeSonnet4520250929 => "Claude Sonnet 4.5",
454            Self::ClaudeSonnet45 => "Claude Sonnet 4.5 (latest)",
455            Self::ClaudeSonnet46 => "Claude Sonnet 4.6",
456        }
457    }
458    #[allow(clippy::too_many_lines)]
459    fn context_window(self) -> u32 {
460        match self {
461            Self::Claude35Haiku20241022
462            | Self::Claude35Sonnet20240620
463            | Self::Claude35Sonnet20241022
464            | Self::Claude37Sonnet20250219
465            | Self::Claude3Haiku20240307
466            | Self::Claude3Opus20240229
467            | Self::Claude3Sonnet20240229
468            | Self::ClaudeHaiku45
469            | Self::ClaudeHaiku4520251001
470            | Self::ClaudeOpus40
471            | Self::ClaudeOpus41
472            | Self::ClaudeOpus4120250805
473            | Self::ClaudeOpus420250514
474            | Self::ClaudeOpus45
475            | Self::ClaudeOpus4520251101
476            | Self::ClaudeSonnet40
477            | Self::ClaudeSonnet420250514
478            | Self::ClaudeSonnet45
479            | Self::ClaudeSonnet4520250929 => 200_000,
480            Self::ClaudeOpus46 | Self::ClaudeOpus47 | Self::ClaudeSonnet46 => 1_000_000,
481        }
482    }
483    #[allow(clippy::too_many_lines)]
484    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
485        match self {
486            Self::Claude35Haiku20241022
487            | Self::Claude35Sonnet20240620
488            | Self::Claude35Sonnet20241022
489            | Self::Claude3Haiku20240307
490            | Self::Claude3Opus20240229
491            | Self::Claude3Sonnet20240229 => &[],
492            Self::Claude37Sonnet20250219
493            | Self::ClaudeHaiku45
494            | Self::ClaudeHaiku4520251001
495            | Self::ClaudeOpus40
496            | Self::ClaudeOpus41
497            | Self::ClaudeOpus4120250805
498            | Self::ClaudeOpus420250514
499            | Self::ClaudeOpus45
500            | Self::ClaudeOpus4520251101
501            | Self::ClaudeOpus46
502            | Self::ClaudeOpus47
503            | Self::ClaudeSonnet40
504            | Self::ClaudeSonnet420250514
505            | Self::ClaudeSonnet45
506            | Self::ClaudeSonnet4520250929
507            | Self::ClaudeSonnet46 => {
508                &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High]
509            }
510        }
511    }
512    pub fn supports_reasoning(self) -> bool {
513        !self.reasoning_levels().is_empty()
514    }
515    #[allow(clippy::too_many_lines)]
516    pub fn supports_prompt_caching(self) -> bool {
517        match self {
518            Self::Claude35Haiku20241022
519            | Self::Claude35Sonnet20240620
520            | Self::Claude35Sonnet20241022
521            | Self::Claude37Sonnet20250219
522            | Self::Claude3Haiku20240307
523            | Self::Claude3Opus20240229
524            | Self::Claude3Sonnet20240229
525            | Self::ClaudeHaiku45
526            | Self::ClaudeHaiku4520251001
527            | Self::ClaudeOpus40
528            | Self::ClaudeOpus41
529            | Self::ClaudeOpus4120250805
530            | Self::ClaudeOpus420250514
531            | Self::ClaudeOpus45
532            | Self::ClaudeOpus4520251101
533            | Self::ClaudeOpus46
534            | Self::ClaudeOpus47
535            | Self::ClaudeSonnet40
536            | Self::ClaudeSonnet420250514
537            | Self::ClaudeSonnet45
538            | Self::ClaudeSonnet4520250929
539            | Self::ClaudeSonnet46 => true,
540        }
541    }
542    #[allow(clippy::too_many_lines)]
543    pub fn supports_image(self) -> bool {
544        match self {
545            Self::Claude35Haiku20241022
546            | Self::Claude35Sonnet20240620
547            | Self::Claude35Sonnet20241022
548            | Self::Claude37Sonnet20250219
549            | Self::Claude3Haiku20240307
550            | Self::Claude3Opus20240229
551            | Self::Claude3Sonnet20240229
552            | Self::ClaudeHaiku45
553            | Self::ClaudeHaiku4520251001
554            | Self::ClaudeOpus40
555            | Self::ClaudeOpus41
556            | Self::ClaudeOpus4120250805
557            | Self::ClaudeOpus420250514
558            | Self::ClaudeOpus45
559            | Self::ClaudeOpus4520251101
560            | Self::ClaudeOpus46
561            | Self::ClaudeOpus47
562            | Self::ClaudeSonnet40
563            | Self::ClaudeSonnet420250514
564            | Self::ClaudeSonnet45
565            | Self::ClaudeSonnet4520250929
566            | Self::ClaudeSonnet46 => true,
567        }
568    }
569    #[allow(clippy::too_many_lines)]
570    pub fn supports_audio(self) -> bool {
571        match self {
572            Self::Claude35Haiku20241022
573            | Self::Claude35Sonnet20240620
574            | Self::Claude35Sonnet20241022
575            | Self::Claude37Sonnet20250219
576            | Self::Claude3Haiku20240307
577            | Self::Claude3Opus20240229
578            | Self::Claude3Sonnet20240229
579            | Self::ClaudeHaiku45
580            | Self::ClaudeHaiku4520251001
581            | Self::ClaudeOpus40
582            | Self::ClaudeOpus41
583            | Self::ClaudeOpus4120250805
584            | Self::ClaudeOpus420250514
585            | Self::ClaudeOpus45
586            | Self::ClaudeOpus4520251101
587            | Self::ClaudeOpus46
588            | Self::ClaudeOpus47
589            | Self::ClaudeSonnet40
590            | Self::ClaudeSonnet420250514
591            | Self::ClaudeSonnet45
592            | Self::ClaudeSonnet4520250929
593            | Self::ClaudeSonnet46 => false,
594        }
595    }
596    const ALL: &[AnthropicModel] = &[
597        Self::Claude35Haiku20241022,
598        Self::Claude35Sonnet20240620,
599        Self::Claude35Sonnet20241022,
600        Self::Claude37Sonnet20250219,
601        Self::Claude3Haiku20240307,
602        Self::Claude3Opus20240229,
603        Self::Claude3Sonnet20240229,
604        Self::ClaudeHaiku45,
605        Self::ClaudeHaiku4520251001,
606        Self::ClaudeOpus40,
607        Self::ClaudeOpus41,
608        Self::ClaudeOpus4120250805,
609        Self::ClaudeOpus420250514,
610        Self::ClaudeOpus45,
611        Self::ClaudeOpus4520251101,
612        Self::ClaudeOpus46,
613        Self::ClaudeOpus47,
614        Self::ClaudeSonnet40,
615        Self::ClaudeSonnet420250514,
616        Self::ClaudeSonnet45,
617        Self::ClaudeSonnet4520250929,
618        Self::ClaudeSonnet46,
619    ];
620}
621impl std::str::FromStr for AnthropicModel {
622    type Err = String;
623    #[allow(clippy::too_many_lines)]
624    fn from_str(s: &str) -> Result<Self, Self::Err> {
625        match s {
626            "claude-3-5-haiku-20241022" => Ok(Self::Claude35Haiku20241022),
627            "claude-3-5-sonnet-20240620" => Ok(Self::Claude35Sonnet20240620),
628            "claude-3-5-sonnet-20241022" => Ok(Self::Claude35Sonnet20241022),
629            "claude-3-7-sonnet-20250219" => Ok(Self::Claude37Sonnet20250219),
630            "claude-3-haiku-20240307" => Ok(Self::Claude3Haiku20240307),
631            "claude-3-opus-20240229" => Ok(Self::Claude3Opus20240229),
632            "claude-3-sonnet-20240229" => Ok(Self::Claude3Sonnet20240229),
633            "claude-haiku-4-5" => Ok(Self::ClaudeHaiku45),
634            "claude-haiku-4-5-20251001" => Ok(Self::ClaudeHaiku4520251001),
635            "claude-opus-4-0" => Ok(Self::ClaudeOpus40),
636            "claude-opus-4-1" => Ok(Self::ClaudeOpus41),
637            "claude-opus-4-1-20250805" => Ok(Self::ClaudeOpus4120250805),
638            "claude-opus-4-20250514" => Ok(Self::ClaudeOpus420250514),
639            "claude-opus-4-5" => Ok(Self::ClaudeOpus45),
640            "claude-opus-4-5-20251101" => Ok(Self::ClaudeOpus4520251101),
641            "claude-opus-4-6" => Ok(Self::ClaudeOpus46),
642            "claude-opus-4-7" => Ok(Self::ClaudeOpus47),
643            "claude-sonnet-4-0" => Ok(Self::ClaudeSonnet40),
644            "claude-sonnet-4-20250514" => Ok(Self::ClaudeSonnet420250514),
645            "claude-sonnet-4-5" => Ok(Self::ClaudeSonnet45),
646            "claude-sonnet-4-5-20250929" => Ok(Self::ClaudeSonnet4520250929),
647            "claude-sonnet-4-6" => Ok(Self::ClaudeSonnet46),
648            _ => Err(format!("Unknown anthropic model: '{s}'")),
649        }
650    }
651}
652impl CodexModel {
653    #[allow(clippy::too_many_lines)]
654    fn model_id(self) -> &'static str {
655        match self {
656            Self::Gpt5 => "gpt-5",
657            Self::Gpt5Codex => "gpt-5-codex",
658            Self::Gpt51 => "gpt-5.1",
659            Self::Gpt51Codex => "gpt-5.1-codex",
660            Self::Gpt51CodexMax => "gpt-5.1-codex-max",
661            Self::Gpt51CodexMini => "gpt-5.1-codex-mini",
662            Self::Gpt52 => "gpt-5.2",
663            Self::Gpt52Codex => "gpt-5.2-codex",
664            Self::Gpt52Pro => "gpt-5.2-pro",
665            Self::Gpt53Codex => "gpt-5.3-codex",
666            Self::Gpt53CodexSpark => "gpt-5.3-codex-spark",
667            Self::Gpt54 => "gpt-5.4",
668            Self::Gpt54Mini => "gpt-5.4-mini",
669            Self::Gpt54Nano => "gpt-5.4-nano",
670            Self::Gpt54Pro => "gpt-5.4-pro",
671            Self::Gpt55 => "gpt-5.5",
672            Self::Gpt55Pro => "gpt-5.5-pro",
673        }
674    }
675    #[allow(clippy::too_many_lines)]
676    fn display_name(self) -> &'static str {
677        match self {
678            Self::Gpt5 => "GPT-5",
679            Self::Gpt5Codex => "GPT-5-Codex",
680            Self::Gpt51 => "GPT-5.1",
681            Self::Gpt51Codex => "GPT-5.1 Codex",
682            Self::Gpt51CodexMax => "GPT-5.1 Codex Max",
683            Self::Gpt51CodexMini => "GPT-5.1 Codex mini",
684            Self::Gpt52 => "GPT-5.2",
685            Self::Gpt52Codex => "GPT-5.2 Codex",
686            Self::Gpt52Pro => "GPT-5.2 Pro",
687            Self::Gpt53Codex => "GPT-5.3 Codex",
688            Self::Gpt53CodexSpark => "GPT-5.3 Codex Spark",
689            Self::Gpt54 => "GPT-5.4",
690            Self::Gpt54Pro => "GPT-5.4 Pro",
691            Self::Gpt54Mini => "GPT-5.4 mini",
692            Self::Gpt54Nano => "GPT-5.4 nano",
693            Self::Gpt55 => "GPT-5.5",
694            Self::Gpt55Pro => "GPT-5.5 Pro",
695        }
696    }
697    #[allow(clippy::too_many_lines)]
698    fn context_window(self) -> u32 {
699        match self {
700            Self::Gpt53CodexSpark => 128_000,
701            Self::Gpt52
702            | Self::Gpt53Codex
703            | Self::Gpt54
704            | Self::Gpt54Mini
705            | Self::Gpt55 => 272_000,
706            Self::Gpt5
707            | Self::Gpt5Codex
708            | Self::Gpt51
709            | Self::Gpt51Codex
710            | Self::Gpt51CodexMax
711            | Self::Gpt51CodexMini
712            | Self::Gpt52Codex
713            | Self::Gpt52Pro
714            | Self::Gpt54Nano => 400_000,
715            Self::Gpt54Pro | Self::Gpt55Pro => 1_050_000,
716        }
717    }
718    #[allow(clippy::too_many_lines)]
719    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
720        match self {
721            Self::Gpt5
722            | Self::Gpt5Codex
723            | Self::Gpt51
724            | Self::Gpt51Codex
725            | Self::Gpt51CodexMax
726            | Self::Gpt51CodexMini
727            | Self::Gpt52
728            | Self::Gpt52Codex
729            | Self::Gpt52Pro
730            | Self::Gpt53Codex
731            | Self::Gpt53CodexSpark
732            | Self::Gpt54
733            | Self::Gpt54Mini
734            | Self::Gpt54Nano
735            | Self::Gpt54Pro
736            | Self::Gpt55
737            | Self::Gpt55Pro => {
738                &[
739                    ReasoningEffort::Low,
740                    ReasoningEffort::Medium,
741                    ReasoningEffort::High,
742                    ReasoningEffort::Xhigh,
743                ]
744            }
745        }
746    }
747    pub fn supports_reasoning(self) -> bool {
748        !self.reasoning_levels().is_empty()
749    }
750    #[allow(clippy::too_many_lines)]
751    pub fn supports_prompt_caching(self) -> bool {
752        match self {
753            Self::Gpt52Pro | Self::Gpt54Pro | Self::Gpt55Pro => false,
754            Self::Gpt5
755            | Self::Gpt5Codex
756            | Self::Gpt51
757            | Self::Gpt51Codex
758            | Self::Gpt51CodexMax
759            | Self::Gpt51CodexMini
760            | Self::Gpt52
761            | Self::Gpt52Codex
762            | Self::Gpt53Codex
763            | Self::Gpt53CodexSpark
764            | Self::Gpt54
765            | Self::Gpt54Mini
766            | Self::Gpt54Nano
767            | Self::Gpt55 => true,
768        }
769    }
770    #[allow(clippy::too_many_lines)]
771    pub fn supports_image(self) -> bool {
772        match self {
773            Self::Gpt5
774            | Self::Gpt5Codex
775            | Self::Gpt51
776            | Self::Gpt51Codex
777            | Self::Gpt51CodexMax
778            | Self::Gpt51CodexMini
779            | Self::Gpt52
780            | Self::Gpt52Codex
781            | Self::Gpt52Pro
782            | Self::Gpt53Codex
783            | Self::Gpt53CodexSpark
784            | Self::Gpt54
785            | Self::Gpt54Mini
786            | Self::Gpt54Nano
787            | Self::Gpt54Pro
788            | Self::Gpt55
789            | Self::Gpt55Pro => true,
790        }
791    }
792    #[allow(clippy::too_many_lines)]
793    pub fn supports_audio(self) -> bool {
794        match self {
795            Self::Gpt5
796            | Self::Gpt5Codex
797            | Self::Gpt51
798            | Self::Gpt51Codex
799            | Self::Gpt51CodexMax
800            | Self::Gpt51CodexMini
801            | Self::Gpt52
802            | Self::Gpt52Codex
803            | Self::Gpt52Pro
804            | Self::Gpt53Codex
805            | Self::Gpt53CodexSpark
806            | Self::Gpt54
807            | Self::Gpt54Mini
808            | Self::Gpt54Nano
809            | Self::Gpt54Pro
810            | Self::Gpt55
811            | Self::Gpt55Pro => false,
812        }
813    }
814    const ALL: &[CodexModel] = &[
815        Self::Gpt5,
816        Self::Gpt5Codex,
817        Self::Gpt51,
818        Self::Gpt51Codex,
819        Self::Gpt51CodexMax,
820        Self::Gpt51CodexMini,
821        Self::Gpt52,
822        Self::Gpt52Codex,
823        Self::Gpt52Pro,
824        Self::Gpt53Codex,
825        Self::Gpt53CodexSpark,
826        Self::Gpt54,
827        Self::Gpt54Mini,
828        Self::Gpt54Nano,
829        Self::Gpt54Pro,
830        Self::Gpt55,
831        Self::Gpt55Pro,
832    ];
833}
834impl std::str::FromStr for CodexModel {
835    type Err = String;
836    #[allow(clippy::too_many_lines)]
837    fn from_str(s: &str) -> Result<Self, Self::Err> {
838        match s {
839            "gpt-5" => Ok(Self::Gpt5),
840            "gpt-5-codex" => Ok(Self::Gpt5Codex),
841            "gpt-5.1" => Ok(Self::Gpt51),
842            "gpt-5.1-codex" => Ok(Self::Gpt51Codex),
843            "gpt-5.1-codex-max" => Ok(Self::Gpt51CodexMax),
844            "gpt-5.1-codex-mini" => Ok(Self::Gpt51CodexMini),
845            "gpt-5.2" => Ok(Self::Gpt52),
846            "gpt-5.2-codex" => Ok(Self::Gpt52Codex),
847            "gpt-5.2-pro" => Ok(Self::Gpt52Pro),
848            "gpt-5.3-codex" => Ok(Self::Gpt53Codex),
849            "gpt-5.3-codex-spark" => Ok(Self::Gpt53CodexSpark),
850            "gpt-5.4" => Ok(Self::Gpt54),
851            "gpt-5.4-mini" => Ok(Self::Gpt54Mini),
852            "gpt-5.4-nano" => Ok(Self::Gpt54Nano),
853            "gpt-5.4-pro" => Ok(Self::Gpt54Pro),
854            "gpt-5.5" => Ok(Self::Gpt55),
855            "gpt-5.5-pro" => Ok(Self::Gpt55Pro),
856            _ => Err(format!("Unknown codex model: '{s}'")),
857        }
858    }
859}
860impl DeepSeekModel {
861    #[allow(clippy::too_many_lines)]
862    fn model_id(self) -> &'static str {
863        match self {
864            Self::DeepseekChat => "deepseek-chat",
865            Self::DeepseekReasoner => "deepseek-reasoner",
866            Self::DeepseekV4Flash => "deepseek-v4-flash",
867            Self::DeepseekV4Pro => "deepseek-v4-pro",
868        }
869    }
870    #[allow(clippy::too_many_lines)]
871    fn display_name(self) -> &'static str {
872        match self {
873            Self::DeepseekChat => "DeepSeek Chat",
874            Self::DeepseekReasoner => "DeepSeek Reasoner",
875            Self::DeepseekV4Flash => "DeepSeek V4 Flash",
876            Self::DeepseekV4Pro => "DeepSeek V4 Pro",
877        }
878    }
879    #[allow(clippy::too_many_lines)]
880    fn context_window(self) -> u32 {
881        match self {
882            Self::DeepseekChat
883            | Self::DeepseekReasoner
884            | Self::DeepseekV4Flash
885            | Self::DeepseekV4Pro => 1_000_000,
886        }
887    }
888    #[allow(clippy::too_many_lines)]
889    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
890        match self {
891            Self::DeepseekChat => &[],
892            Self::DeepseekReasoner | Self::DeepseekV4Flash | Self::DeepseekV4Pro => {
893                &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High]
894            }
895        }
896    }
897    pub fn supports_reasoning(self) -> bool {
898        !self.reasoning_levels().is_empty()
899    }
900    #[allow(clippy::too_many_lines)]
901    pub fn supports_prompt_caching(self) -> bool {
902        match self {
903            Self::DeepseekChat
904            | Self::DeepseekReasoner
905            | Self::DeepseekV4Flash
906            | Self::DeepseekV4Pro => true,
907        }
908    }
909    #[allow(clippy::too_many_lines)]
910    pub fn supports_image(self) -> bool {
911        match self {
912            Self::DeepseekChat
913            | Self::DeepseekReasoner
914            | Self::DeepseekV4Flash
915            | Self::DeepseekV4Pro => false,
916        }
917    }
918    #[allow(clippy::too_many_lines)]
919    pub fn supports_audio(self) -> bool {
920        match self {
921            Self::DeepseekChat
922            | Self::DeepseekReasoner
923            | Self::DeepseekV4Flash
924            | Self::DeepseekV4Pro => false,
925        }
926    }
927    const ALL: &[DeepSeekModel] = &[
928        Self::DeepseekChat,
929        Self::DeepseekReasoner,
930        Self::DeepseekV4Flash,
931        Self::DeepseekV4Pro,
932    ];
933}
934impl std::str::FromStr for DeepSeekModel {
935    type Err = String;
936    #[allow(clippy::too_many_lines)]
937    fn from_str(s: &str) -> Result<Self, Self::Err> {
938        match s {
939            "deepseek-chat" => Ok(Self::DeepseekChat),
940            "deepseek-reasoner" => Ok(Self::DeepseekReasoner),
941            "deepseek-v4-flash" => Ok(Self::DeepseekV4Flash),
942            "deepseek-v4-pro" => Ok(Self::DeepseekV4Pro),
943            _ => Err(format!("Unknown deepseek model: '{s}'")),
944        }
945    }
946}
947impl GeminiModel {
948    #[allow(clippy::too_many_lines)]
949    fn model_id(self) -> &'static str {
950        match self {
951            Self::Gemini15Flash => "gemini-1.5-flash",
952            Self::Gemini15Flash8b => "gemini-1.5-flash-8b",
953            Self::Gemini15Pro => "gemini-1.5-pro",
954            Self::Gemini20Flash => "gemini-2.0-flash",
955            Self::Gemini20FlashLite => "gemini-2.0-flash-lite",
956            Self::Gemini25Flash => "gemini-2.5-flash",
957            Self::Gemini25FlashLite => "gemini-2.5-flash-lite",
958            Self::Gemini25FlashLitePreview0617 => "gemini-2.5-flash-lite-preview-06-17",
959            Self::Gemini25FlashLitePreview092025 => {
960                "gemini-2.5-flash-lite-preview-09-2025"
961            }
962            Self::Gemini25FlashPreview0417 => "gemini-2.5-flash-preview-04-17",
963            Self::Gemini25FlashPreview0520 => "gemini-2.5-flash-preview-05-20",
964            Self::Gemini25FlashPreview092025 => "gemini-2.5-flash-preview-09-2025",
965            Self::Gemini25Pro => "gemini-2.5-pro",
966            Self::Gemini25ProPreview0506 => "gemini-2.5-pro-preview-05-06",
967            Self::Gemini25ProPreview0605 => "gemini-2.5-pro-preview-06-05",
968            Self::Gemini3FlashPreview => "gemini-3-flash-preview",
969            Self::Gemini3ProPreview => "gemini-3-pro-preview",
970            Self::Gemini31FlashLite => "gemini-3.1-flash-lite",
971            Self::Gemini31FlashLitePreview => "gemini-3.1-flash-lite-preview",
972            Self::Gemini31ProPreview => "gemini-3.1-pro-preview",
973            Self::Gemini31ProPreviewCustomtools => "gemini-3.1-pro-preview-customtools",
974            Self::GeminiLive25Flash => "gemini-live-2.5-flash",
975            Self::GeminiLive25FlashPreviewNativeAudio => {
976                "gemini-live-2.5-flash-preview-native-audio"
977            }
978            Self::Gemma327bIt => "gemma-3-27b-it",
979            Self::Gemma426bA4bIt => "gemma-4-26b-a4b-it",
980            Self::Gemma431bIt => "gemma-4-31b-it",
981        }
982    }
983    #[allow(clippy::too_many_lines)]
984    fn display_name(self) -> &'static str {
985        match self {
986            Self::Gemini15Flash => "Gemini 1.5 Flash",
987            Self::Gemini15Flash8b => "Gemini 1.5 Flash-8B",
988            Self::Gemini15Pro => "Gemini 1.5 Pro",
989            Self::Gemini20Flash => "Gemini 2.0 Flash",
990            Self::Gemini20FlashLite => "Gemini 2.0 Flash Lite",
991            Self::Gemini25Flash => "Gemini 2.5 Flash",
992            Self::Gemini25FlashLite => "Gemini 2.5 Flash Lite",
993            Self::Gemini25FlashLitePreview0617 => "Gemini 2.5 Flash Lite Preview 06-17",
994            Self::Gemini25FlashLitePreview092025 => "Gemini 2.5 Flash Lite Preview 09-25",
995            Self::Gemini25FlashPreview0417 => "Gemini 2.5 Flash Preview 04-17",
996            Self::Gemini25FlashPreview0520 => "Gemini 2.5 Flash Preview 05-20",
997            Self::Gemini25FlashPreview092025 => "Gemini 2.5 Flash Preview 09-25",
998            Self::Gemini25Pro => "Gemini 2.5 Pro",
999            Self::Gemini25ProPreview0506 => "Gemini 2.5 Pro Preview 05-06",
1000            Self::Gemini25ProPreview0605 => "Gemini 2.5 Pro Preview 06-05",
1001            Self::Gemini3FlashPreview => "Gemini 3 Flash Preview",
1002            Self::Gemini3ProPreview => "Gemini 3 Pro Preview",
1003            Self::Gemini31FlashLite => "Gemini 3.1 Flash Lite",
1004            Self::Gemini31FlashLitePreview => "Gemini 3.1 Flash Lite Preview",
1005            Self::Gemini31ProPreview => "Gemini 3.1 Pro Preview",
1006            Self::Gemini31ProPreviewCustomtools => "Gemini 3.1 Pro Preview Custom Tools",
1007            Self::GeminiLive25Flash => "Gemini Live 2.5 Flash",
1008            Self::GeminiLive25FlashPreviewNativeAudio => {
1009                "Gemini Live 2.5 Flash Preview Native Audio"
1010            }
1011            Self::Gemma327bIt => "Gemma 3 27B",
1012            Self::Gemma426bA4bIt => "Gemma 4 26B",
1013            Self::Gemma431bIt => "Gemma 4 31B",
1014        }
1015    }
1016    #[allow(clippy::too_many_lines)]
1017    fn context_window(self) -> u32 {
1018        match self {
1019            Self::GeminiLive25Flash => 128_000,
1020            Self::GeminiLive25FlashPreviewNativeAudio | Self::Gemma327bIt => 131_072,
1021            Self::Gemma426bA4bIt | Self::Gemma431bIt => 256_000,
1022            Self::Gemini15Flash
1023            | Self::Gemini15Flash8b
1024            | Self::Gemini15Pro
1025            | Self::Gemini3ProPreview => 1_000_000,
1026            Self::Gemini20Flash
1027            | Self::Gemini20FlashLite
1028            | Self::Gemini25Flash
1029            | Self::Gemini25FlashLite
1030            | Self::Gemini25FlashLitePreview0617
1031            | Self::Gemini25FlashLitePreview092025
1032            | Self::Gemini25FlashPreview0417
1033            | Self::Gemini25FlashPreview0520
1034            | Self::Gemini25FlashPreview092025
1035            | Self::Gemini25Pro
1036            | Self::Gemini25ProPreview0506
1037            | Self::Gemini25ProPreview0605
1038            | Self::Gemini3FlashPreview
1039            | Self::Gemini31FlashLite
1040            | Self::Gemini31FlashLitePreview
1041            | Self::Gemini31ProPreview
1042            | Self::Gemini31ProPreviewCustomtools => 1_048_576,
1043        }
1044    }
1045    #[allow(clippy::too_many_lines)]
1046    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
1047        match self {
1048            Self::Gemini15Flash
1049            | Self::Gemini15Flash8b
1050            | Self::Gemini15Pro
1051            | Self::Gemini20Flash
1052            | Self::Gemini20FlashLite
1053            | Self::Gemma327bIt => &[],
1054            Self::Gemini25Flash
1055            | Self::Gemini25FlashLite
1056            | Self::Gemini25FlashLitePreview0617
1057            | Self::Gemini25FlashLitePreview092025
1058            | Self::Gemini25FlashPreview0417
1059            | Self::Gemini25FlashPreview0520
1060            | Self::Gemini25FlashPreview092025
1061            | Self::Gemini25Pro
1062            | Self::Gemini25ProPreview0506
1063            | Self::Gemini25ProPreview0605
1064            | Self::Gemini3FlashPreview
1065            | Self::Gemini3ProPreview
1066            | Self::Gemini31FlashLite
1067            | Self::Gemini31FlashLitePreview
1068            | Self::Gemini31ProPreview
1069            | Self::Gemini31ProPreviewCustomtools
1070            | Self::GeminiLive25Flash
1071            | Self::GeminiLive25FlashPreviewNativeAudio
1072            | Self::Gemma426bA4bIt
1073            | Self::Gemma431bIt => {
1074                &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High]
1075            }
1076        }
1077    }
1078    pub fn supports_reasoning(self) -> bool {
1079        !self.reasoning_levels().is_empty()
1080    }
1081    #[allow(clippy::too_many_lines)]
1082    pub fn supports_prompt_caching(self) -> bool {
1083        match self {
1084            Self::Gemini20FlashLite
1085            | Self::GeminiLive25Flash
1086            | Self::GeminiLive25FlashPreviewNativeAudio
1087            | Self::Gemma327bIt
1088            | Self::Gemma426bA4bIt
1089            | Self::Gemma431bIt => false,
1090            Self::Gemini15Flash
1091            | Self::Gemini15Flash8b
1092            | Self::Gemini15Pro
1093            | Self::Gemini20Flash
1094            | Self::Gemini25Flash
1095            | Self::Gemini25FlashLite
1096            | Self::Gemini25FlashLitePreview0617
1097            | Self::Gemini25FlashLitePreview092025
1098            | Self::Gemini25FlashPreview0417
1099            | Self::Gemini25FlashPreview0520
1100            | Self::Gemini25FlashPreview092025
1101            | Self::Gemini25Pro
1102            | Self::Gemini25ProPreview0506
1103            | Self::Gemini25ProPreview0605
1104            | Self::Gemini3FlashPreview
1105            | Self::Gemini3ProPreview
1106            | Self::Gemini31FlashLite
1107            | Self::Gemini31FlashLitePreview
1108            | Self::Gemini31ProPreview
1109            | Self::Gemini31ProPreviewCustomtools => true,
1110        }
1111    }
1112    #[allow(clippy::too_many_lines)]
1113    pub fn supports_image(self) -> bool {
1114        match self {
1115            Self::GeminiLive25FlashPreviewNativeAudio => false,
1116            Self::Gemini15Flash
1117            | Self::Gemini15Flash8b
1118            | Self::Gemini15Pro
1119            | Self::Gemini20Flash
1120            | Self::Gemini20FlashLite
1121            | Self::Gemini25Flash
1122            | Self::Gemini25FlashLite
1123            | Self::Gemini25FlashLitePreview0617
1124            | Self::Gemini25FlashLitePreview092025
1125            | Self::Gemini25FlashPreview0417
1126            | Self::Gemini25FlashPreview0520
1127            | Self::Gemini25FlashPreview092025
1128            | Self::Gemini25Pro
1129            | Self::Gemini25ProPreview0506
1130            | Self::Gemini25ProPreview0605
1131            | Self::Gemini3FlashPreview
1132            | Self::Gemini3ProPreview
1133            | Self::Gemini31FlashLite
1134            | Self::Gemini31FlashLitePreview
1135            | Self::Gemini31ProPreview
1136            | Self::Gemini31ProPreviewCustomtools
1137            | Self::GeminiLive25Flash
1138            | Self::Gemma327bIt
1139            | Self::Gemma426bA4bIt
1140            | Self::Gemma431bIt => true,
1141        }
1142    }
1143    #[allow(clippy::too_many_lines)]
1144    pub fn supports_audio(self) -> bool {
1145        match self {
1146            Self::Gemma327bIt | Self::Gemma426bA4bIt | Self::Gemma431bIt => false,
1147            Self::Gemini15Flash
1148            | Self::Gemini15Flash8b
1149            | Self::Gemini15Pro
1150            | Self::Gemini20Flash
1151            | Self::Gemini20FlashLite
1152            | Self::Gemini25Flash
1153            | Self::Gemini25FlashLite
1154            | Self::Gemini25FlashLitePreview0617
1155            | Self::Gemini25FlashLitePreview092025
1156            | Self::Gemini25FlashPreview0417
1157            | Self::Gemini25FlashPreview0520
1158            | Self::Gemini25FlashPreview092025
1159            | Self::Gemini25Pro
1160            | Self::Gemini25ProPreview0506
1161            | Self::Gemini25ProPreview0605
1162            | Self::Gemini3FlashPreview
1163            | Self::Gemini3ProPreview
1164            | Self::Gemini31FlashLite
1165            | Self::Gemini31FlashLitePreview
1166            | Self::Gemini31ProPreview
1167            | Self::Gemini31ProPreviewCustomtools
1168            | Self::GeminiLive25Flash
1169            | Self::GeminiLive25FlashPreviewNativeAudio => true,
1170        }
1171    }
1172    const ALL: &[GeminiModel] = &[
1173        Self::Gemini15Flash,
1174        Self::Gemini15Flash8b,
1175        Self::Gemini15Pro,
1176        Self::Gemini20Flash,
1177        Self::Gemini20FlashLite,
1178        Self::Gemini25Flash,
1179        Self::Gemini25FlashLite,
1180        Self::Gemini25FlashLitePreview0617,
1181        Self::Gemini25FlashLitePreview092025,
1182        Self::Gemini25FlashPreview0417,
1183        Self::Gemini25FlashPreview0520,
1184        Self::Gemini25FlashPreview092025,
1185        Self::Gemini25Pro,
1186        Self::Gemini25ProPreview0506,
1187        Self::Gemini25ProPreview0605,
1188        Self::Gemini3FlashPreview,
1189        Self::Gemini3ProPreview,
1190        Self::Gemini31FlashLite,
1191        Self::Gemini31FlashLitePreview,
1192        Self::Gemini31ProPreview,
1193        Self::Gemini31ProPreviewCustomtools,
1194        Self::GeminiLive25Flash,
1195        Self::GeminiLive25FlashPreviewNativeAudio,
1196        Self::Gemma327bIt,
1197        Self::Gemma426bA4bIt,
1198        Self::Gemma431bIt,
1199    ];
1200}
1201impl std::str::FromStr for GeminiModel {
1202    type Err = String;
1203    #[allow(clippy::too_many_lines)]
1204    fn from_str(s: &str) -> Result<Self, Self::Err> {
1205        match s {
1206            "gemini-1.5-flash" => Ok(Self::Gemini15Flash),
1207            "gemini-1.5-flash-8b" => Ok(Self::Gemini15Flash8b),
1208            "gemini-1.5-pro" => Ok(Self::Gemini15Pro),
1209            "gemini-2.0-flash" => Ok(Self::Gemini20Flash),
1210            "gemini-2.0-flash-lite" => Ok(Self::Gemini20FlashLite),
1211            "gemini-2.5-flash" => Ok(Self::Gemini25Flash),
1212            "gemini-2.5-flash-lite" => Ok(Self::Gemini25FlashLite),
1213            "gemini-2.5-flash-lite-preview-06-17" => {
1214                Ok(Self::Gemini25FlashLitePreview0617)
1215            }
1216            "gemini-2.5-flash-lite-preview-09-2025" => {
1217                Ok(Self::Gemini25FlashLitePreview092025)
1218            }
1219            "gemini-2.5-flash-preview-04-17" => Ok(Self::Gemini25FlashPreview0417),
1220            "gemini-2.5-flash-preview-05-20" => Ok(Self::Gemini25FlashPreview0520),
1221            "gemini-2.5-flash-preview-09-2025" => Ok(Self::Gemini25FlashPreview092025),
1222            "gemini-2.5-pro" => Ok(Self::Gemini25Pro),
1223            "gemini-2.5-pro-preview-05-06" => Ok(Self::Gemini25ProPreview0506),
1224            "gemini-2.5-pro-preview-06-05" => Ok(Self::Gemini25ProPreview0605),
1225            "gemini-3-flash-preview" => Ok(Self::Gemini3FlashPreview),
1226            "gemini-3-pro-preview" => Ok(Self::Gemini3ProPreview),
1227            "gemini-3.1-flash-lite" => Ok(Self::Gemini31FlashLite),
1228            "gemini-3.1-flash-lite-preview" => Ok(Self::Gemini31FlashLitePreview),
1229            "gemini-3.1-pro-preview" => Ok(Self::Gemini31ProPreview),
1230            "gemini-3.1-pro-preview-customtools" => {
1231                Ok(Self::Gemini31ProPreviewCustomtools)
1232            }
1233            "gemini-live-2.5-flash" => Ok(Self::GeminiLive25Flash),
1234            "gemini-live-2.5-flash-preview-native-audio" => {
1235                Ok(Self::GeminiLive25FlashPreviewNativeAudio)
1236            }
1237            "gemma-3-27b-it" => Ok(Self::Gemma327bIt),
1238            "gemma-4-26b-a4b-it" => Ok(Self::Gemma426bA4bIt),
1239            "gemma-4-31b-it" => Ok(Self::Gemma431bIt),
1240            _ => Err(format!("Unknown gemini model: '{s}'")),
1241        }
1242    }
1243}
1244impl MoonshotModel {
1245    #[allow(clippy::too_many_lines)]
1246    fn model_id(self) -> &'static str {
1247        match self {
1248            Self::KimiK20711Preview => "kimi-k2-0711-preview",
1249            Self::KimiK20905Preview => "kimi-k2-0905-preview",
1250            Self::KimiK2Thinking => "kimi-k2-thinking",
1251            Self::KimiK2ThinkingTurbo => "kimi-k2-thinking-turbo",
1252            Self::KimiK2TurboPreview => "kimi-k2-turbo-preview",
1253            Self::KimiK25 => "kimi-k2.5",
1254            Self::KimiK26 => "kimi-k2.6",
1255        }
1256    }
1257    #[allow(clippy::too_many_lines)]
1258    fn display_name(self) -> &'static str {
1259        match self {
1260            Self::KimiK20711Preview => "Kimi K2 0711",
1261            Self::KimiK20905Preview => "Kimi K2 0905",
1262            Self::KimiK2Thinking => "Kimi K2 Thinking",
1263            Self::KimiK2ThinkingTurbo => "Kimi K2 Thinking Turbo",
1264            Self::KimiK2TurboPreview => "Kimi K2 Turbo",
1265            Self::KimiK25 => "Kimi K2.5",
1266            Self::KimiK26 => "Kimi K2.6",
1267        }
1268    }
1269    #[allow(clippy::too_many_lines)]
1270    fn context_window(self) -> u32 {
1271        match self {
1272            Self::KimiK20711Preview => 131_072,
1273            Self::KimiK20905Preview
1274            | Self::KimiK2Thinking
1275            | Self::KimiK2ThinkingTurbo
1276            | Self::KimiK2TurboPreview
1277            | Self::KimiK25
1278            | Self::KimiK26 => 262_144,
1279        }
1280    }
1281    #[allow(clippy::too_many_lines)]
1282    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
1283        match self {
1284            Self::KimiK20711Preview
1285            | Self::KimiK20905Preview
1286            | Self::KimiK2TurboPreview => &[],
1287            Self::KimiK2Thinking
1288            | Self::KimiK2ThinkingTurbo
1289            | Self::KimiK25
1290            | Self::KimiK26 => {
1291                &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High]
1292            }
1293        }
1294    }
1295    pub fn supports_reasoning(self) -> bool {
1296        !self.reasoning_levels().is_empty()
1297    }
1298    #[allow(clippy::too_many_lines)]
1299    pub fn supports_prompt_caching(self) -> bool {
1300        match self {
1301            Self::KimiK20711Preview
1302            | Self::KimiK20905Preview
1303            | Self::KimiK2Thinking
1304            | Self::KimiK2ThinkingTurbo
1305            | Self::KimiK2TurboPreview
1306            | Self::KimiK25
1307            | Self::KimiK26 => true,
1308        }
1309    }
1310    #[allow(clippy::too_many_lines)]
1311    pub fn supports_image(self) -> bool {
1312        match self {
1313            Self::KimiK20711Preview
1314            | Self::KimiK20905Preview
1315            | Self::KimiK2Thinking
1316            | Self::KimiK2ThinkingTurbo
1317            | Self::KimiK2TurboPreview => false,
1318            Self::KimiK25 | Self::KimiK26 => true,
1319        }
1320    }
1321    #[allow(clippy::too_many_lines)]
1322    pub fn supports_audio(self) -> bool {
1323        match self {
1324            Self::KimiK20711Preview
1325            | Self::KimiK20905Preview
1326            | Self::KimiK2Thinking
1327            | Self::KimiK2ThinkingTurbo
1328            | Self::KimiK2TurboPreview
1329            | Self::KimiK25
1330            | Self::KimiK26 => false,
1331        }
1332    }
1333    const ALL: &[MoonshotModel] = &[
1334        Self::KimiK20711Preview,
1335        Self::KimiK20905Preview,
1336        Self::KimiK2Thinking,
1337        Self::KimiK2ThinkingTurbo,
1338        Self::KimiK2TurboPreview,
1339        Self::KimiK25,
1340        Self::KimiK26,
1341    ];
1342}
1343impl std::str::FromStr for MoonshotModel {
1344    type Err = String;
1345    #[allow(clippy::too_many_lines)]
1346    fn from_str(s: &str) -> Result<Self, Self::Err> {
1347        match s {
1348            "kimi-k2-0711-preview" => Ok(Self::KimiK20711Preview),
1349            "kimi-k2-0905-preview" => Ok(Self::KimiK20905Preview),
1350            "kimi-k2-thinking" => Ok(Self::KimiK2Thinking),
1351            "kimi-k2-thinking-turbo" => Ok(Self::KimiK2ThinkingTurbo),
1352            "kimi-k2-turbo-preview" => Ok(Self::KimiK2TurboPreview),
1353            "kimi-k2.5" => Ok(Self::KimiK25),
1354            "kimi-k2.6" => Ok(Self::KimiK26),
1355            _ => Err(format!("Unknown moonshot model: '{s}'")),
1356        }
1357    }
1358}
1359impl OpenaiModel {
1360    #[allow(clippy::too_many_lines)]
1361    fn model_id(self) -> &'static str {
1362        match self {
1363            Self::Gpt4 => "gpt-4",
1364            Self::Gpt4Turbo => "gpt-4-turbo",
1365            Self::Gpt41 => "gpt-4.1",
1366            Self::Gpt41Mini => "gpt-4.1-mini",
1367            Self::Gpt41Nano => "gpt-4.1-nano",
1368            Self::Gpt4o => "gpt-4o",
1369            Self::Gpt4o20240513 => "gpt-4o-2024-05-13",
1370            Self::Gpt4o20240806 => "gpt-4o-2024-08-06",
1371            Self::Gpt4o20241120 => "gpt-4o-2024-11-20",
1372            Self::Gpt4oMini => "gpt-4o-mini",
1373            Self::Gpt5 => "gpt-5",
1374            Self::Gpt5Codex => "gpt-5-codex",
1375            Self::Gpt5Mini => "gpt-5-mini",
1376            Self::Gpt5Nano => "gpt-5-nano",
1377            Self::Gpt5Pro => "gpt-5-pro",
1378            Self::Gpt51 => "gpt-5.1",
1379            Self::Gpt51Codex => "gpt-5.1-codex",
1380            Self::Gpt51CodexMax => "gpt-5.1-codex-max",
1381            Self::Gpt51CodexMini => "gpt-5.1-codex-mini",
1382            Self::Gpt52 => "gpt-5.2",
1383            Self::Gpt52Codex => "gpt-5.2-codex",
1384            Self::Gpt52Pro => "gpt-5.2-pro",
1385            Self::Gpt53Codex => "gpt-5.3-codex",
1386            Self::Gpt53CodexSpark => "gpt-5.3-codex-spark",
1387            Self::Gpt54 => "gpt-5.4",
1388            Self::Gpt54Mini => "gpt-5.4-mini",
1389            Self::Gpt54Nano => "gpt-5.4-nano",
1390            Self::Gpt54Pro => "gpt-5.4-pro",
1391            Self::Gpt55 => "gpt-5.5",
1392            Self::Gpt55Pro => "gpt-5.5-pro",
1393            Self::O1 => "o1",
1394            Self::O1Pro => "o1-pro",
1395            Self::O3 => "o3",
1396            Self::O3DeepResearch => "o3-deep-research",
1397            Self::O3Mini => "o3-mini",
1398            Self::O3Pro => "o3-pro",
1399            Self::O4Mini => "o4-mini",
1400            Self::O4MiniDeepResearch => "o4-mini-deep-research",
1401        }
1402    }
1403    #[allow(clippy::too_many_lines)]
1404    fn display_name(self) -> &'static str {
1405        match self {
1406            Self::Gpt4 => "GPT-4",
1407            Self::Gpt4Turbo => "GPT-4 Turbo",
1408            Self::Gpt41 => "GPT-4.1",
1409            Self::Gpt41Mini => "GPT-4.1 mini",
1410            Self::Gpt41Nano => "GPT-4.1 nano",
1411            Self::Gpt4o => "GPT-4o",
1412            Self::Gpt4o20240513 => "GPT-4o (2024-05-13)",
1413            Self::Gpt4o20240806 => "GPT-4o (2024-08-06)",
1414            Self::Gpt4o20241120 => "GPT-4o (2024-11-20)",
1415            Self::Gpt4oMini => "GPT-4o mini",
1416            Self::Gpt5 => "GPT-5",
1417            Self::Gpt5Mini => "GPT-5 Mini",
1418            Self::Gpt5Nano => "GPT-5 Nano",
1419            Self::Gpt5Pro => "GPT-5 Pro",
1420            Self::Gpt5Codex => "GPT-5-Codex",
1421            Self::Gpt51 => "GPT-5.1",
1422            Self::Gpt51Codex => "GPT-5.1 Codex",
1423            Self::Gpt51CodexMax => "GPT-5.1 Codex Max",
1424            Self::Gpt51CodexMini => "GPT-5.1 Codex mini",
1425            Self::Gpt52 => "GPT-5.2",
1426            Self::Gpt52Codex => "GPT-5.2 Codex",
1427            Self::Gpt52Pro => "GPT-5.2 Pro",
1428            Self::Gpt53Codex => "GPT-5.3 Codex",
1429            Self::Gpt53CodexSpark => "GPT-5.3 Codex Spark",
1430            Self::Gpt54 => "GPT-5.4",
1431            Self::Gpt54Pro => "GPT-5.4 Pro",
1432            Self::Gpt54Mini => "GPT-5.4 mini",
1433            Self::Gpt54Nano => "GPT-5.4 nano",
1434            Self::Gpt55 => "GPT-5.5",
1435            Self::Gpt55Pro => "GPT-5.5 Pro",
1436            Self::O1 => "o1",
1437            Self::O1Pro => "o1-pro",
1438            Self::O3 => "o3",
1439            Self::O3DeepResearch => "o3-deep-research",
1440            Self::O3Mini => "o3-mini",
1441            Self::O3Pro => "o3-pro",
1442            Self::O4Mini => "o4-mini",
1443            Self::O4MiniDeepResearch => "o4-mini-deep-research",
1444        }
1445    }
1446    #[allow(clippy::too_many_lines)]
1447    fn context_window(self) -> u32 {
1448        match self {
1449            Self::Gpt4 => 8192,
1450            Self::Gpt4Turbo
1451            | Self::Gpt4o
1452            | Self::Gpt4o20240513
1453            | Self::Gpt4o20240806
1454            | Self::Gpt4o20241120
1455            | Self::Gpt4oMini
1456            | Self::Gpt53CodexSpark => 128_000,
1457            Self::O1
1458            | Self::O1Pro
1459            | Self::O3
1460            | Self::O3DeepResearch
1461            | Self::O3Mini
1462            | Self::O3Pro
1463            | Self::O4Mini
1464            | Self::O4MiniDeepResearch => 200_000,
1465            Self::Gpt5
1466            | Self::Gpt5Codex
1467            | Self::Gpt5Mini
1468            | Self::Gpt5Nano
1469            | Self::Gpt5Pro
1470            | Self::Gpt51
1471            | Self::Gpt51Codex
1472            | Self::Gpt51CodexMax
1473            | Self::Gpt51CodexMini
1474            | Self::Gpt52
1475            | Self::Gpt52Codex
1476            | Self::Gpt52Pro
1477            | Self::Gpt53Codex
1478            | Self::Gpt54Mini
1479            | Self::Gpt54Nano => 400_000,
1480            Self::Gpt41 | Self::Gpt41Mini | Self::Gpt41Nano => 1_047_576,
1481            Self::Gpt54 | Self::Gpt54Pro | Self::Gpt55 | Self::Gpt55Pro => 1_050_000,
1482        }
1483    }
1484    #[allow(clippy::too_many_lines)]
1485    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
1486        match self {
1487            Self::Gpt4
1488            | Self::Gpt4Turbo
1489            | Self::Gpt41
1490            | Self::Gpt41Mini
1491            | Self::Gpt41Nano
1492            | Self::Gpt4o
1493            | Self::Gpt4o20240513
1494            | Self::Gpt4o20240806
1495            | Self::Gpt4o20241120
1496            | Self::Gpt4oMini => &[],
1497            Self::Gpt5
1498            | Self::Gpt5Codex
1499            | Self::Gpt5Mini
1500            | Self::Gpt5Nano
1501            | Self::Gpt5Pro
1502            | Self::Gpt51
1503            | Self::Gpt51Codex
1504            | Self::Gpt51CodexMax
1505            | Self::Gpt51CodexMini
1506            | Self::Gpt52
1507            | Self::Gpt52Codex
1508            | Self::Gpt52Pro
1509            | Self::Gpt53Codex
1510            | Self::Gpt53CodexSpark
1511            | Self::Gpt54
1512            | Self::Gpt54Mini
1513            | Self::Gpt54Nano
1514            | Self::Gpt54Pro
1515            | Self::Gpt55
1516            | Self::Gpt55Pro
1517            | Self::O1
1518            | Self::O1Pro
1519            | Self::O3
1520            | Self::O3DeepResearch
1521            | Self::O3Mini
1522            | Self::O3Pro
1523            | Self::O4Mini
1524            | Self::O4MiniDeepResearch => {
1525                &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High]
1526            }
1527        }
1528    }
1529    pub fn supports_reasoning(self) -> bool {
1530        !self.reasoning_levels().is_empty()
1531    }
1532    #[allow(clippy::too_many_lines)]
1533    pub fn supports_prompt_caching(self) -> bool {
1534        match self {
1535            Self::Gpt4
1536            | Self::Gpt4Turbo
1537            | Self::Gpt4o20240513
1538            | Self::Gpt5Pro
1539            | Self::Gpt52Pro
1540            | Self::Gpt54Pro
1541            | Self::Gpt55Pro
1542            | Self::O1Pro
1543            | Self::O3Pro => false,
1544            Self::Gpt41
1545            | Self::Gpt41Mini
1546            | Self::Gpt41Nano
1547            | Self::Gpt4o
1548            | Self::Gpt4o20240806
1549            | Self::Gpt4o20241120
1550            | Self::Gpt4oMini
1551            | Self::Gpt5
1552            | Self::Gpt5Codex
1553            | Self::Gpt5Mini
1554            | Self::Gpt5Nano
1555            | Self::Gpt51
1556            | Self::Gpt51Codex
1557            | Self::Gpt51CodexMax
1558            | Self::Gpt51CodexMini
1559            | Self::Gpt52
1560            | Self::Gpt52Codex
1561            | Self::Gpt53Codex
1562            | Self::Gpt53CodexSpark
1563            | Self::Gpt54
1564            | Self::Gpt54Mini
1565            | Self::Gpt54Nano
1566            | Self::Gpt55
1567            | Self::O1
1568            | Self::O3
1569            | Self::O3DeepResearch
1570            | Self::O3Mini
1571            | Self::O4Mini
1572            | Self::O4MiniDeepResearch => true,
1573        }
1574    }
1575    #[allow(clippy::too_many_lines)]
1576    pub fn supports_image(self) -> bool {
1577        match self {
1578            Self::Gpt4 | Self::O3Mini => false,
1579            Self::Gpt4Turbo
1580            | Self::Gpt41
1581            | Self::Gpt41Mini
1582            | Self::Gpt41Nano
1583            | Self::Gpt4o
1584            | Self::Gpt4o20240513
1585            | Self::Gpt4o20240806
1586            | Self::Gpt4o20241120
1587            | Self::Gpt4oMini
1588            | Self::Gpt5
1589            | Self::Gpt5Codex
1590            | Self::Gpt5Mini
1591            | Self::Gpt5Nano
1592            | Self::Gpt5Pro
1593            | Self::Gpt51
1594            | Self::Gpt51Codex
1595            | Self::Gpt51CodexMax
1596            | Self::Gpt51CodexMini
1597            | Self::Gpt52
1598            | Self::Gpt52Codex
1599            | Self::Gpt52Pro
1600            | Self::Gpt53Codex
1601            | Self::Gpt53CodexSpark
1602            | Self::Gpt54
1603            | Self::Gpt54Mini
1604            | Self::Gpt54Nano
1605            | Self::Gpt54Pro
1606            | Self::Gpt55
1607            | Self::Gpt55Pro
1608            | Self::O1
1609            | Self::O1Pro
1610            | Self::O3
1611            | Self::O3DeepResearch
1612            | Self::O3Pro
1613            | Self::O4Mini
1614            | Self::O4MiniDeepResearch => true,
1615        }
1616    }
1617    #[allow(clippy::too_many_lines)]
1618    pub fn supports_audio(self) -> bool {
1619        match self {
1620            Self::Gpt4
1621            | Self::Gpt4Turbo
1622            | Self::Gpt41
1623            | Self::Gpt41Mini
1624            | Self::Gpt41Nano
1625            | Self::Gpt4o
1626            | Self::Gpt4o20240513
1627            | Self::Gpt4o20240806
1628            | Self::Gpt4o20241120
1629            | Self::Gpt4oMini
1630            | Self::Gpt5
1631            | Self::Gpt5Codex
1632            | Self::Gpt5Mini
1633            | Self::Gpt5Nano
1634            | Self::Gpt5Pro
1635            | Self::Gpt51
1636            | Self::Gpt51Codex
1637            | Self::Gpt51CodexMax
1638            | Self::Gpt51CodexMini
1639            | Self::Gpt52
1640            | Self::Gpt52Codex
1641            | Self::Gpt52Pro
1642            | Self::Gpt53Codex
1643            | Self::Gpt53CodexSpark
1644            | Self::Gpt54
1645            | Self::Gpt54Mini
1646            | Self::Gpt54Nano
1647            | Self::Gpt54Pro
1648            | Self::Gpt55
1649            | Self::Gpt55Pro
1650            | Self::O1
1651            | Self::O1Pro
1652            | Self::O3
1653            | Self::O3DeepResearch
1654            | Self::O3Mini
1655            | Self::O3Pro
1656            | Self::O4Mini
1657            | Self::O4MiniDeepResearch => false,
1658        }
1659    }
1660    const ALL: &[OpenaiModel] = &[
1661        Self::Gpt4,
1662        Self::Gpt4Turbo,
1663        Self::Gpt41,
1664        Self::Gpt41Mini,
1665        Self::Gpt41Nano,
1666        Self::Gpt4o,
1667        Self::Gpt4o20240513,
1668        Self::Gpt4o20240806,
1669        Self::Gpt4o20241120,
1670        Self::Gpt4oMini,
1671        Self::Gpt5,
1672        Self::Gpt5Codex,
1673        Self::Gpt5Mini,
1674        Self::Gpt5Nano,
1675        Self::Gpt5Pro,
1676        Self::Gpt51,
1677        Self::Gpt51Codex,
1678        Self::Gpt51CodexMax,
1679        Self::Gpt51CodexMini,
1680        Self::Gpt52,
1681        Self::Gpt52Codex,
1682        Self::Gpt52Pro,
1683        Self::Gpt53Codex,
1684        Self::Gpt53CodexSpark,
1685        Self::Gpt54,
1686        Self::Gpt54Mini,
1687        Self::Gpt54Nano,
1688        Self::Gpt54Pro,
1689        Self::Gpt55,
1690        Self::Gpt55Pro,
1691        Self::O1,
1692        Self::O1Pro,
1693        Self::O3,
1694        Self::O3DeepResearch,
1695        Self::O3Mini,
1696        Self::O3Pro,
1697        Self::O4Mini,
1698        Self::O4MiniDeepResearch,
1699    ];
1700}
1701impl std::str::FromStr for OpenaiModel {
1702    type Err = String;
1703    #[allow(clippy::too_many_lines)]
1704    fn from_str(s: &str) -> Result<Self, Self::Err> {
1705        match s {
1706            "gpt-4" => Ok(Self::Gpt4),
1707            "gpt-4-turbo" => Ok(Self::Gpt4Turbo),
1708            "gpt-4.1" => Ok(Self::Gpt41),
1709            "gpt-4.1-mini" => Ok(Self::Gpt41Mini),
1710            "gpt-4.1-nano" => Ok(Self::Gpt41Nano),
1711            "gpt-4o" => Ok(Self::Gpt4o),
1712            "gpt-4o-2024-05-13" => Ok(Self::Gpt4o20240513),
1713            "gpt-4o-2024-08-06" => Ok(Self::Gpt4o20240806),
1714            "gpt-4o-2024-11-20" => Ok(Self::Gpt4o20241120),
1715            "gpt-4o-mini" => Ok(Self::Gpt4oMini),
1716            "gpt-5" => Ok(Self::Gpt5),
1717            "gpt-5-codex" => Ok(Self::Gpt5Codex),
1718            "gpt-5-mini" => Ok(Self::Gpt5Mini),
1719            "gpt-5-nano" => Ok(Self::Gpt5Nano),
1720            "gpt-5-pro" => Ok(Self::Gpt5Pro),
1721            "gpt-5.1" => Ok(Self::Gpt51),
1722            "gpt-5.1-codex" => Ok(Self::Gpt51Codex),
1723            "gpt-5.1-codex-max" => Ok(Self::Gpt51CodexMax),
1724            "gpt-5.1-codex-mini" => Ok(Self::Gpt51CodexMini),
1725            "gpt-5.2" => Ok(Self::Gpt52),
1726            "gpt-5.2-codex" => Ok(Self::Gpt52Codex),
1727            "gpt-5.2-pro" => Ok(Self::Gpt52Pro),
1728            "gpt-5.3-codex" => Ok(Self::Gpt53Codex),
1729            "gpt-5.3-codex-spark" => Ok(Self::Gpt53CodexSpark),
1730            "gpt-5.4" => Ok(Self::Gpt54),
1731            "gpt-5.4-mini" => Ok(Self::Gpt54Mini),
1732            "gpt-5.4-nano" => Ok(Self::Gpt54Nano),
1733            "gpt-5.4-pro" => Ok(Self::Gpt54Pro),
1734            "gpt-5.5" => Ok(Self::Gpt55),
1735            "gpt-5.5-pro" => Ok(Self::Gpt55Pro),
1736            "o1" => Ok(Self::O1),
1737            "o1-pro" => Ok(Self::O1Pro),
1738            "o3" => Ok(Self::O3),
1739            "o3-deep-research" => Ok(Self::O3DeepResearch),
1740            "o3-mini" => Ok(Self::O3Mini),
1741            "o3-pro" => Ok(Self::O3Pro),
1742            "o4-mini" => Ok(Self::O4Mini),
1743            "o4-mini-deep-research" => Ok(Self::O4MiniDeepResearch),
1744            _ => Err(format!("Unknown openai model: '{s}'")),
1745        }
1746    }
1747}
1748impl OpenRouterModel {
1749    #[allow(clippy::too_many_lines)]
1750    fn model_id(self) -> &'static str {
1751        match self {
1752            Self::AnthropicClaude35Haiku => "anthropic/claude-3.5-haiku",
1753            Self::AnthropicClaude37Sonnet => "anthropic/claude-3.7-sonnet",
1754            Self::AnthropicClaudeHaiku45 => "anthropic/claude-haiku-4.5",
1755            Self::AnthropicClaudeOpus4 => "anthropic/claude-opus-4",
1756            Self::AnthropicClaudeOpus41 => "anthropic/claude-opus-4.1",
1757            Self::AnthropicClaudeOpus45 => "anthropic/claude-opus-4.5",
1758            Self::AnthropicClaudeOpus46 => "anthropic/claude-opus-4.6",
1759            Self::AnthropicClaudeOpus47 => "anthropic/claude-opus-4.7",
1760            Self::AnthropicClaudeSonnet4 => "anthropic/claude-sonnet-4",
1761            Self::AnthropicClaudeSonnet45 => "anthropic/claude-sonnet-4.5",
1762            Self::AnthropicClaudeSonnet46 => "anthropic/claude-sonnet-4.6",
1763            Self::ArceeAiTrinityLargePreviewFree => "arcee-ai/trinity-large-preview:free",
1764            Self::ArceeAiTrinityLargeThinking => "arcee-ai/trinity-large-thinking",
1765            Self::DeepseekDeepseekChatV31 => "deepseek/deepseek-chat-v3.1",
1766            Self::DeepseekDeepseekR1 => "deepseek/deepseek-r1",
1767            Self::DeepseekDeepseekV31Terminus => "deepseek/deepseek-v3.1-terminus",
1768            Self::DeepseekDeepseekV31TerminusExacto => {
1769                "deepseek/deepseek-v3.1-terminus:exacto"
1770            }
1771            Self::DeepseekDeepseekV32 => "deepseek/deepseek-v3.2",
1772            Self::DeepseekDeepseekV32Speciale => "deepseek/deepseek-v3.2-speciale",
1773            Self::DeepseekDeepseekV4Flash => "deepseek/deepseek-v4-flash",
1774            Self::DeepseekDeepseekV4Pro => "deepseek/deepseek-v4-pro",
1775            Self::GoogleGemini20Flash001 => "google/gemini-2.0-flash-001",
1776            Self::GoogleGemini25Flash => "google/gemini-2.5-flash",
1777            Self::GoogleGemini25FlashLite => "google/gemini-2.5-flash-lite",
1778            Self::GoogleGemini25FlashLitePreview092025 => {
1779                "google/gemini-2.5-flash-lite-preview-09-2025"
1780            }
1781            Self::GoogleGemini25FlashPreview092025 => {
1782                "google/gemini-2.5-flash-preview-09-2025"
1783            }
1784            Self::GoogleGemini25Pro => "google/gemini-2.5-pro",
1785            Self::GoogleGemini25ProPreview0506 => "google/gemini-2.5-pro-preview-05-06",
1786            Self::GoogleGemini25ProPreview0605 => "google/gemini-2.5-pro-preview-06-05",
1787            Self::GoogleGemini3FlashPreview => "google/gemini-3-flash-preview",
1788            Self::GoogleGemini3ProPreview => "google/gemini-3-pro-preview",
1789            Self::GoogleGemini31FlashLitePreview => {
1790                "google/gemini-3.1-flash-lite-preview"
1791            }
1792            Self::GoogleGemini31ProPreview => "google/gemini-3.1-pro-preview",
1793            Self::GoogleGemini31ProPreviewCustomtools => {
1794                "google/gemini-3.1-pro-preview-customtools"
1795            }
1796            Self::GoogleGemma327bIt => "google/gemma-3-27b-it",
1797            Self::GoogleGemma327bItFree => "google/gemma-3-27b-it:free",
1798            Self::GoogleGemma426bA4bIt => "google/gemma-4-26b-a4b-it",
1799            Self::GoogleGemma426bA4bItFree => "google/gemma-4-26b-a4b-it:free",
1800            Self::GoogleGemma431bIt => "google/gemma-4-31b-it",
1801            Self::GoogleGemma431bItFree => "google/gemma-4-31b-it:free",
1802            Self::InceptionMercury2 => "inception/mercury-2",
1803            Self::MetaLlamaLlama3370bInstructFree => {
1804                "meta-llama/llama-3.3-70b-instruct:free"
1805            }
1806            Self::MinimaxMinimax01 => "minimax/minimax-01",
1807            Self::MinimaxMinimaxM1 => "minimax/minimax-m1",
1808            Self::MinimaxMinimaxM2 => "minimax/minimax-m2",
1809            Self::MinimaxMinimaxM21 => "minimax/minimax-m2.1",
1810            Self::MinimaxMinimaxM25 => "minimax/minimax-m2.5",
1811            Self::MinimaxMinimaxM25Free => "minimax/minimax-m2.5:free",
1812            Self::MinimaxMinimaxM27 => "minimax/minimax-m2.7",
1813            Self::MistralaiCodestral2508 => "mistralai/codestral-2508",
1814            Self::MistralaiDevstral2512 => "mistralai/devstral-2512",
1815            Self::MistralaiDevstralMedium2507 => "mistralai/devstral-medium-2507",
1816            Self::MistralaiDevstralSmall2505 => "mistralai/devstral-small-2505",
1817            Self::MistralaiDevstralSmall2507 => "mistralai/devstral-small-2507",
1818            Self::MistralaiMistralMedium3 => "mistralai/mistral-medium-3",
1819            Self::MistralaiMistralMedium31 => "mistralai/mistral-medium-3.1",
1820            Self::MistralaiMistralSmall2603 => "mistralai/mistral-small-2603",
1821            Self::MistralaiMistralSmall3124bInstruct => {
1822                "mistralai/mistral-small-3.1-24b-instruct"
1823            }
1824            Self::MistralaiMistralSmall3224bInstruct => {
1825                "mistralai/mistral-small-3.2-24b-instruct"
1826            }
1827            Self::MoonshotaiKimiK2 => "moonshotai/kimi-k2",
1828            Self::MoonshotaiKimiK20905 => "moonshotai/kimi-k2-0905",
1829            Self::MoonshotaiKimiK20905Exacto => "moonshotai/kimi-k2-0905:exacto",
1830            Self::MoonshotaiKimiK2Thinking => "moonshotai/kimi-k2-thinking",
1831            Self::MoonshotaiKimiK25 => "moonshotai/kimi-k2.5",
1832            Self::MoonshotaiKimiK26 => "moonshotai/kimi-k2.6",
1833            Self::NousresearchHermes4405b => "nousresearch/hermes-4-405b",
1834            Self::NousresearchHermes470b => "nousresearch/hermes-4-70b",
1835            Self::NvidiaNemotron3Nano30bA3bFree => "nvidia/nemotron-3-nano-30b-a3b:free",
1836            Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree => {
1837                "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free"
1838            }
1839            Self::NvidiaNemotron3Super120bA12b => "nvidia/nemotron-3-super-120b-a12b",
1840            Self::NvidiaNemotron3Super120bA12bFree => {
1841                "nvidia/nemotron-3-super-120b-a12b:free"
1842            }
1843            Self::NvidiaNemotronNano12bV2VlFree => "nvidia/nemotron-nano-12b-v2-vl:free",
1844            Self::NvidiaNemotronNano9bV2 => "nvidia/nemotron-nano-9b-v2",
1845            Self::NvidiaNemotronNano9bV2Free => "nvidia/nemotron-nano-9b-v2:free",
1846            Self::OpenaiGpt41 => "openai/gpt-4.1",
1847            Self::OpenaiGpt41Mini => "openai/gpt-4.1-mini",
1848            Self::OpenaiGpt4oMini => "openai/gpt-4o-mini",
1849            Self::OpenaiGpt5 => "openai/gpt-5",
1850            Self::OpenaiGpt5Codex => "openai/gpt-5-codex",
1851            Self::OpenaiGpt5Image => "openai/gpt-5-image",
1852            Self::OpenaiGpt5Mini => "openai/gpt-5-mini",
1853            Self::OpenaiGpt5Nano => "openai/gpt-5-nano",
1854            Self::OpenaiGpt5Pro => "openai/gpt-5-pro",
1855            Self::OpenaiGpt51 => "openai/gpt-5.1",
1856            Self::OpenaiGpt51Chat => "openai/gpt-5.1-chat",
1857            Self::OpenaiGpt51Codex => "openai/gpt-5.1-codex",
1858            Self::OpenaiGpt51CodexMax => "openai/gpt-5.1-codex-max",
1859            Self::OpenaiGpt51CodexMini => "openai/gpt-5.1-codex-mini",
1860            Self::OpenaiGpt52 => "openai/gpt-5.2",
1861            Self::OpenaiGpt52Chat => "openai/gpt-5.2-chat",
1862            Self::OpenaiGpt52Codex => "openai/gpt-5.2-codex",
1863            Self::OpenaiGpt52Pro => "openai/gpt-5.2-pro",
1864            Self::OpenaiGpt53Codex => "openai/gpt-5.3-codex",
1865            Self::OpenaiGpt54 => "openai/gpt-5.4",
1866            Self::OpenaiGpt54Mini => "openai/gpt-5.4-mini",
1867            Self::OpenaiGpt54Nano => "openai/gpt-5.4-nano",
1868            Self::OpenaiGpt54Pro => "openai/gpt-5.4-pro",
1869            Self::OpenaiGpt55 => "openai/gpt-5.5",
1870            Self::OpenaiGpt55Pro => "openai/gpt-5.5-pro",
1871            Self::OpenaiGptOss120b => "openai/gpt-oss-120b",
1872            Self::OpenaiGptOss120bExacto => "openai/gpt-oss-120b:exacto",
1873            Self::OpenaiGptOss120bFree => "openai/gpt-oss-120b:free",
1874            Self::OpenaiGptOss20b => "openai/gpt-oss-20b",
1875            Self::OpenaiGptOss20bFree => "openai/gpt-oss-20b:free",
1876            Self::OpenaiGptOssSafeguard20b => "openai/gpt-oss-safeguard-20b",
1877            Self::OpenaiO4Mini => "openai/o4-mini",
1878            Self::OpenrouterElephantAlpha => "openrouter/elephant-alpha",
1879            Self::OpenrouterFree => "openrouter/free",
1880            Self::OpenrouterOwlAlpha => "openrouter/owl-alpha",
1881            Self::OpenrouterParetoCode => "openrouter/pareto-code",
1882            Self::PoolsideLagunaM1Free => "poolside/laguna-m.1:free",
1883            Self::PoolsideLagunaXs2Free => "poolside/laguna-xs.2:free",
1884            Self::PrimeIntellectIntellect3 => "prime-intellect/intellect-3",
1885            Self::QwenQwen3627b => "qwen/qwen-3.6-27b",
1886            Self::QwenQwenPlus => "qwen/qwen-plus",
1887            Self::QwenQwen3235bA22b0725 => "qwen/qwen3-235b-a22b-07-25",
1888            Self::QwenQwen3235bA22bThinking2507 => "qwen/qwen3-235b-a22b-thinking-2507",
1889            Self::QwenQwen330bA3bInstruct2507 => "qwen/qwen3-30b-a3b-instruct-2507",
1890            Self::QwenQwen330bA3bThinking2507 => "qwen/qwen3-30b-a3b-thinking-2507",
1891            Self::QwenQwen3Coder => "qwen/qwen3-coder",
1892            Self::QwenQwen3Coder30bA3bInstruct => "qwen/qwen3-coder-30b-a3b-instruct",
1893            Self::QwenQwen3CoderFlash => "qwen/qwen3-coder-flash",
1894            Self::QwenQwen3CoderPlus => "qwen/qwen3-coder-plus",
1895            Self::QwenQwen3CoderExacto => "qwen/qwen3-coder:exacto",
1896            Self::QwenQwen3Max => "qwen/qwen3-max",
1897            Self::QwenQwen3Next80bA3bInstruct => "qwen/qwen3-next-80b-a3b-instruct",
1898            Self::QwenQwen3Next80bA3bThinking => "qwen/qwen3-next-80b-a3b-thinking",
1899            Self::QwenQwen35397bA17b => "qwen/qwen3.5-397b-a17b",
1900            Self::QwenQwen35Flash0223 => "qwen/qwen3.5-flash-02-23",
1901            Self::QwenQwen35Plus0215 => "qwen/qwen3.5-plus-02-15",
1902            Self::QwenQwen36Plus => "qwen/qwen3.6-plus",
1903            Self::StepfunStep35Flash => "stepfun/step-3.5-flash",
1904            Self::TencentHy3Preview => "tencent/hy3-preview",
1905            Self::XAiGrok3 => "x-ai/grok-3",
1906            Self::XAiGrok3Beta => "x-ai/grok-3-beta",
1907            Self::XAiGrok3Mini => "x-ai/grok-3-mini",
1908            Self::XAiGrok3MiniBeta => "x-ai/grok-3-mini-beta",
1909            Self::XAiGrok4 => "x-ai/grok-4",
1910            Self::XAiGrok4Fast => "x-ai/grok-4-fast",
1911            Self::XAiGrok41Fast => "x-ai/grok-4.1-fast",
1912            Self::XAiGrok420Beta => "x-ai/grok-4.20-beta",
1913            Self::XAiGrok43 => "x-ai/grok-4.3",
1914            Self::XAiGrokCodeFast1 => "x-ai/grok-code-fast-1",
1915            Self::XiaomiMimoV2Flash => "xiaomi/mimo-v2-flash",
1916            Self::XiaomiMimoV2Omni => "xiaomi/mimo-v2-omni",
1917            Self::XiaomiMimoV2Pro => "xiaomi/mimo-v2-pro",
1918            Self::XiaomiMimoV25 => "xiaomi/mimo-v2.5",
1919            Self::XiaomiMimoV25Pro => "xiaomi/mimo-v2.5-pro",
1920            Self::ZAiGlm45 => "z-ai/glm-4.5",
1921            Self::ZAiGlm45Air => "z-ai/glm-4.5-air",
1922            Self::ZAiGlm45v => "z-ai/glm-4.5v",
1923            Self::ZAiGlm46 => "z-ai/glm-4.6",
1924            Self::ZAiGlm46Exacto => "z-ai/glm-4.6:exacto",
1925            Self::ZAiGlm47 => "z-ai/glm-4.7",
1926            Self::ZAiGlm47Flash => "z-ai/glm-4.7-flash",
1927            Self::ZAiGlm5 => "z-ai/glm-5",
1928            Self::ZAiGlm5Turbo => "z-ai/glm-5-turbo",
1929            Self::ZAiGlm51 => "z-ai/glm-5.1",
1930        }
1931    }
1932    #[allow(clippy::too_many_lines)]
1933    fn display_name(self) -> &'static str {
1934        match self {
1935            Self::AnthropicClaude35Haiku => "Claude Haiku 3.5",
1936            Self::AnthropicClaudeHaiku45 => "Claude Haiku 4.5",
1937            Self::AnthropicClaudeOpus4 => "Claude Opus 4",
1938            Self::AnthropicClaudeOpus41 => "Claude Opus 4.1",
1939            Self::AnthropicClaudeOpus45 => "Claude Opus 4.5",
1940            Self::AnthropicClaudeOpus46 => "Claude Opus 4.6",
1941            Self::AnthropicClaudeOpus47 => "Claude Opus 4.7",
1942            Self::AnthropicClaude37Sonnet => "Claude Sonnet 3.7",
1943            Self::AnthropicClaudeSonnet4 => "Claude Sonnet 4",
1944            Self::AnthropicClaudeSonnet45 => "Claude Sonnet 4.5",
1945            Self::AnthropicClaudeSonnet46 => "Claude Sonnet 4.6",
1946            Self::MistralaiCodestral2508 => "Codestral 2508",
1947            Self::DeepseekDeepseekV31Terminus => "DeepSeek V3.1 Terminus",
1948            Self::DeepseekDeepseekV31TerminusExacto => "DeepSeek V3.1 Terminus (exacto)",
1949            Self::DeepseekDeepseekV32 => "DeepSeek V3.2",
1950            Self::DeepseekDeepseekV32Speciale => "DeepSeek V3.2 Speciale",
1951            Self::DeepseekDeepseekV4Flash => "DeepSeek V4 Flash",
1952            Self::DeepseekDeepseekV4Pro => "DeepSeek V4 Pro",
1953            Self::DeepseekDeepseekChatV31 => "DeepSeek-V3.1",
1954            Self::DeepseekDeepseekR1 => "DeepSeek: R1",
1955            Self::MistralaiDevstral2512 => "Devstral 2 2512",
1956            Self::MistralaiDevstralMedium2507 => "Devstral Medium",
1957            Self::MistralaiDevstralSmall2505 => "Devstral Small",
1958            Self::MistralaiDevstralSmall2507 => "Devstral Small 1.1",
1959            Self::OpenrouterElephantAlpha => "Elephant (free)",
1960            Self::OpenrouterFree => "Free Models Router",
1961            Self::ZAiGlm45 => "GLM 4.5",
1962            Self::ZAiGlm45Air => "GLM 4.5 Air",
1963            Self::ZAiGlm45v => "GLM 4.5V",
1964            Self::ZAiGlm46 => "GLM 4.6",
1965            Self::ZAiGlm46Exacto => "GLM 4.6 (exacto)",
1966            Self::ZAiGlm47 => "GLM-4.7",
1967            Self::ZAiGlm47Flash => "GLM-4.7-Flash",
1968            Self::ZAiGlm5 => "GLM-5",
1969            Self::ZAiGlm5Turbo => "GLM-5-Turbo",
1970            Self::ZAiGlm51 => "GLM-5.1",
1971            Self::OpenaiGptOss120b => "GPT OSS 120B",
1972            Self::OpenaiGptOss120bExacto => "GPT OSS 120B (exacto)",
1973            Self::OpenaiGptOss20b => "GPT OSS 20B",
1974            Self::OpenaiGptOssSafeguard20b => "GPT OSS Safeguard 20B",
1975            Self::OpenaiGpt41 => "GPT-4.1",
1976            Self::OpenaiGpt41Mini => "GPT-4.1 Mini",
1977            Self::OpenaiGpt4oMini => "GPT-4o-mini",
1978            Self::OpenaiGpt5 => "GPT-5",
1979            Self::OpenaiGpt5Codex => "GPT-5 Codex",
1980            Self::OpenaiGpt5Image => "GPT-5 Image",
1981            Self::OpenaiGpt5Mini => "GPT-5 Mini",
1982            Self::OpenaiGpt5Nano => "GPT-5 Nano",
1983            Self::OpenaiGpt5Pro => "GPT-5 Pro",
1984            Self::OpenaiGpt51 => "GPT-5.1",
1985            Self::OpenaiGpt51Chat => "GPT-5.1 Chat",
1986            Self::OpenaiGpt51Codex => "GPT-5.1-Codex",
1987            Self::OpenaiGpt51CodexMax => "GPT-5.1-Codex-Max",
1988            Self::OpenaiGpt51CodexMini => "GPT-5.1-Codex-Mini",
1989            Self::OpenaiGpt52 => "GPT-5.2",
1990            Self::OpenaiGpt52Chat => "GPT-5.2 Chat",
1991            Self::OpenaiGpt52Pro => "GPT-5.2 Pro",
1992            Self::OpenaiGpt52Codex => "GPT-5.2-Codex",
1993            Self::OpenaiGpt53Codex => "GPT-5.3-Codex",
1994            Self::OpenaiGpt54 => "GPT-5.4",
1995            Self::OpenaiGpt54Mini => "GPT-5.4 Mini",
1996            Self::OpenaiGpt54Nano => "GPT-5.4 Nano",
1997            Self::OpenaiGpt54Pro => "GPT-5.4 Pro",
1998            Self::OpenaiGpt55 => "GPT-5.5",
1999            Self::OpenaiGpt55Pro => "GPT-5.5 Pro",
2000            Self::GoogleGemini20Flash001 => "Gemini 2.0 Flash",
2001            Self::GoogleGemini25Flash => "Gemini 2.5 Flash",
2002            Self::GoogleGemini25FlashLite => "Gemini 2.5 Flash Lite",
2003            Self::GoogleGemini25FlashLitePreview092025 => {
2004                "Gemini 2.5 Flash Lite Preview 09-25"
2005            }
2006            Self::GoogleGemini25FlashPreview092025 => "Gemini 2.5 Flash Preview 09-25",
2007            Self::GoogleGemini25Pro => "Gemini 2.5 Pro",
2008            Self::GoogleGemini25ProPreview0506 => "Gemini 2.5 Pro Preview 05-06",
2009            Self::GoogleGemini25ProPreview0605 => "Gemini 2.5 Pro Preview 06-05",
2010            Self::GoogleGemini3FlashPreview => "Gemini 3 Flash Preview",
2011            Self::GoogleGemini3ProPreview => "Gemini 3 Pro Preview",
2012            Self::GoogleGemini31FlashLitePreview => "Gemini 3.1 Flash Lite Preview",
2013            Self::GoogleGemini31ProPreview => "Gemini 3.1 Pro Preview",
2014            Self::GoogleGemini31ProPreviewCustomtools => {
2015                "Gemini 3.1 Pro Preview Custom Tools"
2016            }
2017            Self::GoogleGemma327bIt => "Gemma 3 27B",
2018            Self::GoogleGemma327bItFree => "Gemma 3 27B (free)",
2019            Self::GoogleGemma426bA4bIt => "Gemma 4 26B A4B",
2020            Self::GoogleGemma426bA4bItFree => "Gemma 4 26B A4B (free)",
2021            Self::GoogleGemma431bIt => "Gemma 4 31B",
2022            Self::GoogleGemma431bItFree => "Gemma 4 31B (free)",
2023            Self::XAiGrok3 => "Grok 3",
2024            Self::XAiGrok3Beta => "Grok 3 Beta",
2025            Self::XAiGrok3Mini => "Grok 3 Mini",
2026            Self::XAiGrok3MiniBeta => "Grok 3 Mini Beta",
2027            Self::XAiGrok4 => "Grok 4",
2028            Self::XAiGrok4Fast => "Grok 4 Fast",
2029            Self::XAiGrok41Fast => "Grok 4.1 Fast",
2030            Self::XAiGrok420Beta => "Grok 4.20 Beta",
2031            Self::XAiGrok43 => "Grok 4.3",
2032            Self::XAiGrokCodeFast1 => "Grok Code Fast 1",
2033            Self::NousresearchHermes4405b => "Hermes 4 405B",
2034            Self::NousresearchHermes470b => "Hermes 4 70B",
2035            Self::TencentHy3Preview => "Hy3 preview",
2036            Self::PrimeIntellectIntellect3 => "Intellect 3",
2037            Self::MoonshotaiKimiK2 => "Kimi K2",
2038            Self::MoonshotaiKimiK20905 => "Kimi K2 Instruct 0905",
2039            Self::MoonshotaiKimiK20905Exacto => "Kimi K2 Instruct 0905 (exacto)",
2040            Self::MoonshotaiKimiK2Thinking => "Kimi K2 Thinking",
2041            Self::MoonshotaiKimiK25 => "Kimi K2.5",
2042            Self::MoonshotaiKimiK26 => "Kimi K2.6",
2043            Self::PoolsideLagunaM1Free => "Laguna M.1",
2044            Self::PoolsideLagunaXs2Free => "Laguna XS.2",
2045            Self::MetaLlamaLlama3370bInstructFree => "Llama 3.3 70B Instruct (free)",
2046            Self::InceptionMercury2 => "Mercury 2",
2047            Self::MinimaxMinimaxM1 => "MiniMax M1",
2048            Self::MinimaxMinimaxM2 => "MiniMax M2",
2049            Self::MinimaxMinimaxM21 => "MiniMax M2.1",
2050            Self::MinimaxMinimaxM25 => "MiniMax M2.5",
2051            Self::MinimaxMinimaxM25Free => "MiniMax M2.5 (free)",
2052            Self::MinimaxMinimaxM27 => "MiniMax M2.7",
2053            Self::MinimaxMinimax01 => "MiniMax-01",
2054            Self::MistralaiMistralMedium3 => "Mistral Medium 3",
2055            Self::MistralaiMistralMedium31 => "Mistral Medium 3.1",
2056            Self::MistralaiMistralSmall3124bInstruct => "Mistral Small 3.1 24B Instruct",
2057            Self::MistralaiMistralSmall3224bInstruct => "Mistral Small 3.2 24B Instruct",
2058            Self::MistralaiMistralSmall2603 => "Mistral Small 4",
2059            Self::NvidiaNemotron3Nano30bA3bFree => "Nemotron 3 Nano 30B A3B (free)",
2060            Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree => {
2061                "Nemotron 3 Nano Omni (free)"
2062            }
2063            Self::NvidiaNemotron3Super120bA12b => "Nemotron 3 Super",
2064            Self::NvidiaNemotron3Super120bA12bFree => "Nemotron 3 Super (free)",
2065            Self::NvidiaNemotronNano12bV2VlFree => "Nemotron Nano 12B 2 VL (free)",
2066            Self::NvidiaNemotronNano9bV2Free => "Nemotron Nano 9B V2 (free)",
2067            Self::OpenrouterOwlAlpha => "Owl Alpha",
2068            Self::OpenrouterParetoCode => "Pareto Code Router",
2069            Self::QwenQwen3235bA22b0725 => "Qwen3 235B A22B Instruct 2507",
2070            Self::QwenQwen3235bA22bThinking2507 => "Qwen3 235B A22B Thinking 2507",
2071            Self::QwenQwen330bA3bInstruct2507 => "Qwen3 30B A3B Instruct 2507",
2072            Self::QwenQwen330bA3bThinking2507 => "Qwen3 30B A3B Thinking 2507",
2073            Self::QwenQwen3Coder => "Qwen3 Coder",
2074            Self::QwenQwen3CoderExacto => "Qwen3 Coder (exacto)",
2075            Self::QwenQwen3Coder30bA3bInstruct => "Qwen3 Coder 30B A3B Instruct",
2076            Self::QwenQwen3CoderFlash => "Qwen3 Coder Flash",
2077            Self::QwenQwen3CoderPlus => "Qwen3 Coder Plus",
2078            Self::QwenQwen3Max => "Qwen3 Max",
2079            Self::QwenQwen3Next80bA3bInstruct => "Qwen3 Next 80B A3B Instruct",
2080            Self::QwenQwen3Next80bA3bThinking => "Qwen3 Next 80B A3B Thinking",
2081            Self::QwenQwen35397bA17b => "Qwen3.5 397B A17B",
2082            Self::QwenQwen35Plus0215 => "Qwen3.5 Plus 2026-02-15",
2083            Self::QwenQwen3627b => "Qwen3.6 27B",
2084            Self::QwenQwen36Plus => "Qwen3.6 Plus",
2085            Self::QwenQwenPlus => "Qwen: Qwen-Plus",
2086            Self::QwenQwen35Flash0223 => "Qwen: Qwen3.5-Flash",
2087            Self::StepfunStep35Flash => "Step 3.5 Flash",
2088            Self::ArceeAiTrinityLargePreviewFree => "Trinity Large Preview",
2089            Self::ArceeAiTrinityLargeThinking => "Trinity Large Thinking",
2090            Self::XiaomiMimoV2Flash => "Xiaomi: MiMo-V2-Flash",
2091            Self::XiaomiMimoV2Omni => "Xiaomi: MiMo-V2-Omni",
2092            Self::XiaomiMimoV2Pro => "Xiaomi: MiMo-V2-Pro",
2093            Self::XiaomiMimoV25 => "Xiaomi: MiMo-V2.5",
2094            Self::XiaomiMimoV25Pro => "Xiaomi: MiMo-V2.5-Pro",
2095            Self::OpenaiGptOss120bFree => "gpt-oss-120b (free)",
2096            Self::OpenaiGptOss20bFree => "gpt-oss-20b (free)",
2097            Self::NvidiaNemotronNano9bV2 => "nvidia-nemotron-nano-9b-v2",
2098            Self::OpenaiO4Mini => "o4 Mini",
2099        }
2100    }
2101    #[allow(clippy::too_many_lines)]
2102    fn context_window(self) -> u32 {
2103        match self {
2104            Self::DeepseekDeepseekR1 | Self::ZAiGlm45v => 64_000,
2105            Self::GoogleGemma327bIt | Self::MistralaiMistralSmall3224bInstruct => 96_000,
2106            Self::InceptionMercury2
2107            | Self::MistralaiDevstralSmall2505
2108            | Self::MistralaiMistralSmall3124bInstruct
2109            | Self::NvidiaNemotronNano12bV2VlFree
2110            | Self::NvidiaNemotronNano9bV2Free
2111            | Self::OpenaiGpt4oMini
2112            | Self::OpenaiGpt51Chat
2113            | Self::OpenaiGpt52Chat
2114            | Self::QwenQwen3CoderFlash
2115            | Self::ZAiGlm45
2116            | Self::ZAiGlm45Air => 128_000,
2117            Self::ArceeAiTrinityLargePreviewFree
2118            | Self::DeepseekDeepseekV31Terminus
2119            | Self::DeepseekDeepseekV31TerminusExacto
2120            | Self::GoogleGemma327bItFree
2121            | Self::MetaLlamaLlama3370bInstructFree
2122            | Self::MistralaiDevstralMedium2507
2123            | Self::MistralaiDevstralSmall2507
2124            | Self::MistralaiMistralMedium3
2125            | Self::MoonshotaiKimiK2
2126            | Self::NousresearchHermes4405b
2127            | Self::NousresearchHermes470b
2128            | Self::NvidiaNemotronNano9bV2
2129            | Self::OpenaiGptOss120b
2130            | Self::OpenaiGptOss120bExacto
2131            | Self::OpenaiGptOss120bFree
2132            | Self::OpenaiGptOss20b
2133            | Self::OpenaiGptOss20bFree
2134            | Self::OpenaiGptOssSafeguard20b
2135            | Self::PoolsideLagunaM1Free
2136            | Self::PoolsideLagunaXs2Free
2137            | Self::PrimeIntellectIntellect3
2138            | Self::QwenQwen3CoderExacto
2139            | Self::XAiGrok3
2140            | Self::XAiGrok3Beta
2141            | Self::XAiGrok3Mini
2142            | Self::XAiGrok3MiniBeta => 131_072,
2143            Self::QwenQwen3Coder30bA3bInstruct => 160_000,
2144            Self::DeepseekDeepseekChatV31
2145            | Self::DeepseekDeepseekV32
2146            | Self::DeepseekDeepseekV32Speciale => 163_840,
2147            Self::MinimaxMinimaxM2 => 196_600,
2148            Self::AnthropicClaude35Haiku
2149            | Self::AnthropicClaude37Sonnet
2150            | Self::AnthropicClaudeHaiku45
2151            | Self::AnthropicClaudeOpus4
2152            | Self::AnthropicClaudeOpus41
2153            | Self::AnthropicClaudeOpus45
2154            | Self::AnthropicClaudeSonnet4
2155            | Self::OpenaiO4Mini
2156            | Self::OpenrouterFree
2157            | Self::OpenrouterParetoCode
2158            | Self::ZAiGlm46
2159            | Self::ZAiGlm46Exacto
2160            | Self::ZAiGlm47Flash => 200_000,
2161            Self::ZAiGlm5 | Self::ZAiGlm5Turbo | Self::ZAiGlm51 => 202_752,
2162            Self::MinimaxMinimaxM21
2163            | Self::MinimaxMinimaxM25
2164            | Self::MinimaxMinimaxM25Free
2165            | Self::MinimaxMinimaxM27
2166            | Self::ZAiGlm47 => 204_800,
2167            Self::MistralaiCodestral2508
2168            | Self::NvidiaNemotron3Nano30bA3bFree
2169            | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree
2170            | Self::StepfunStep35Flash
2171            | Self::TencentHy3Preview
2172            | Self::XAiGrok4
2173            | Self::XAiGrokCodeFast1 => 256_000,
2174            Self::QwenQwen330bA3bInstruct2507 | Self::QwenQwen330bA3bThinking2507 => {
2175                262_000
2176            }
2177            Self::ArceeAiTrinityLargeThinking
2178            | Self::GoogleGemma426bA4bIt
2179            | Self::GoogleGemma426bA4bItFree
2180            | Self::GoogleGemma431bIt
2181            | Self::GoogleGemma431bItFree
2182            | Self::MistralaiDevstral2512
2183            | Self::MistralaiMistralMedium31
2184            | Self::MistralaiMistralSmall2603
2185            | Self::MoonshotaiKimiK20905
2186            | Self::MoonshotaiKimiK20905Exacto
2187            | Self::MoonshotaiKimiK2Thinking
2188            | Self::MoonshotaiKimiK25
2189            | Self::MoonshotaiKimiK26
2190            | Self::NvidiaNemotron3Super120bA12b
2191            | Self::NvidiaNemotron3Super120bA12bFree
2192            | Self::OpenrouterElephantAlpha
2193            | Self::QwenQwen3627b
2194            | Self::QwenQwen3235bA22b0725
2195            | Self::QwenQwen3235bA22bThinking2507
2196            | Self::QwenQwen3Coder
2197            | Self::QwenQwen3Max
2198            | Self::QwenQwen3Next80bA3bInstruct
2199            | Self::QwenQwen3Next80bA3bThinking
2200            | Self::QwenQwen35397bA17b
2201            | Self::XiaomiMimoV2Flash
2202            | Self::XiaomiMimoV2Omni => 262_144,
2203            Self::OpenaiGpt5
2204            | Self::OpenaiGpt5Codex
2205            | Self::OpenaiGpt5Image
2206            | Self::OpenaiGpt5Mini
2207            | Self::OpenaiGpt5Nano
2208            | Self::OpenaiGpt5Pro
2209            | Self::OpenaiGpt51
2210            | Self::OpenaiGpt51Codex
2211            | Self::OpenaiGpt51CodexMax
2212            | Self::OpenaiGpt51CodexMini
2213            | Self::OpenaiGpt52
2214            | Self::OpenaiGpt52Codex
2215            | Self::OpenaiGpt52Pro
2216            | Self::OpenaiGpt53Codex
2217            | Self::OpenaiGpt54Mini
2218            | Self::OpenaiGpt54Nano => 400_000,
2219            Self::AnthropicClaudeOpus46
2220            | Self::AnthropicClaudeOpus47
2221            | Self::AnthropicClaudeSonnet45
2222            | Self::AnthropicClaudeSonnet46
2223            | Self::MinimaxMinimax01
2224            | Self::MinimaxMinimaxM1
2225            | Self::QwenQwenPlus
2226            | Self::QwenQwen3CoderPlus
2227            | Self::QwenQwen35Flash0223
2228            | Self::QwenQwen35Plus0215
2229            | Self::QwenQwen36Plus
2230            | Self::XAiGrok43 => 1_000_000,
2231            Self::OpenaiGpt41 | Self::OpenaiGpt41Mini => 1_047_576,
2232            Self::DeepseekDeepseekV4Flash
2233            | Self::DeepseekDeepseekV4Pro
2234            | Self::GoogleGemini20Flash001
2235            | Self::GoogleGemini25Flash
2236            | Self::GoogleGemini25FlashLite
2237            | Self::GoogleGemini25FlashLitePreview092025
2238            | Self::GoogleGemini25FlashPreview092025
2239            | Self::GoogleGemini25Pro
2240            | Self::GoogleGemini25ProPreview0506
2241            | Self::GoogleGemini25ProPreview0605
2242            | Self::GoogleGemini3FlashPreview
2243            | Self::GoogleGemini31FlashLitePreview
2244            | Self::GoogleGemini31ProPreview
2245            | Self::GoogleGemini31ProPreviewCustomtools
2246            | Self::XiaomiMimoV2Pro
2247            | Self::XiaomiMimoV25
2248            | Self::XiaomiMimoV25Pro => 1_048_576,
2249            Self::OpenrouterOwlAlpha => 1_048_756,
2250            Self::GoogleGemini3ProPreview
2251            | Self::OpenaiGpt54
2252            | Self::OpenaiGpt54Pro
2253            | Self::OpenaiGpt55
2254            | Self::OpenaiGpt55Pro => 1_050_000,
2255            Self::XAiGrok4Fast | Self::XAiGrok41Fast | Self::XAiGrok420Beta => 2_000_000,
2256        }
2257    }
2258    #[allow(clippy::too_many_lines)]
2259    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
2260        match self {
2261            Self::AnthropicClaude35Haiku
2262            | Self::ArceeAiTrinityLargePreviewFree
2263            | Self::GoogleGemini20Flash001
2264            | Self::GoogleGemma327bIt
2265            | Self::GoogleGemma327bItFree
2266            | Self::MetaLlamaLlama3370bInstructFree
2267            | Self::MistralaiCodestral2508
2268            | Self::MistralaiDevstral2512
2269            | Self::MistralaiDevstralMedium2507
2270            | Self::MistralaiDevstralSmall2505
2271            | Self::MistralaiDevstralSmall2507
2272            | Self::MistralaiMistralMedium3
2273            | Self::MistralaiMistralMedium31
2274            | Self::MistralaiMistralSmall3124bInstruct
2275            | Self::MistralaiMistralSmall3224bInstruct
2276            | Self::MoonshotaiKimiK2
2277            | Self::MoonshotaiKimiK20905
2278            | Self::MoonshotaiKimiK20905Exacto
2279            | Self::OpenaiGpt41
2280            | Self::OpenaiGpt41Mini
2281            | Self::OpenaiGpt4oMini
2282            | Self::OpenaiGpt54Nano
2283            | Self::QwenQwen3627b
2284            | Self::QwenQwenPlus
2285            | Self::QwenQwen3235bA22b0725
2286            | Self::QwenQwen330bA3bInstruct2507
2287            | Self::QwenQwen3Coder
2288            | Self::QwenQwen3Coder30bA3bInstruct
2289            | Self::QwenQwen3CoderFlash
2290            | Self::QwenQwen3CoderPlus
2291            | Self::QwenQwen3CoderExacto
2292            | Self::QwenQwen3Next80bA3bInstruct
2293            | Self::XAiGrok3
2294            | Self::XAiGrok3Beta => &[],
2295            Self::AnthropicClaude37Sonnet
2296            | Self::AnthropicClaudeHaiku45
2297            | Self::AnthropicClaudeOpus4
2298            | Self::AnthropicClaudeOpus41
2299            | Self::AnthropicClaudeOpus45
2300            | Self::AnthropicClaudeOpus46
2301            | Self::AnthropicClaudeOpus47
2302            | Self::AnthropicClaudeSonnet4
2303            | Self::AnthropicClaudeSonnet45
2304            | Self::AnthropicClaudeSonnet46
2305            | Self::ArceeAiTrinityLargeThinking
2306            | Self::DeepseekDeepseekChatV31
2307            | Self::DeepseekDeepseekR1
2308            | Self::DeepseekDeepseekV31Terminus
2309            | Self::DeepseekDeepseekV31TerminusExacto
2310            | Self::DeepseekDeepseekV32
2311            | Self::DeepseekDeepseekV32Speciale
2312            | Self::DeepseekDeepseekV4Flash
2313            | Self::DeepseekDeepseekV4Pro
2314            | Self::GoogleGemini25Flash
2315            | Self::GoogleGemini25FlashLite
2316            | Self::GoogleGemini25FlashLitePreview092025
2317            | Self::GoogleGemini25FlashPreview092025
2318            | Self::GoogleGemini25Pro
2319            | Self::GoogleGemini25ProPreview0506
2320            | Self::GoogleGemini25ProPreview0605
2321            | Self::GoogleGemini3FlashPreview
2322            | Self::GoogleGemini3ProPreview
2323            | Self::GoogleGemini31FlashLitePreview
2324            | Self::GoogleGemini31ProPreview
2325            | Self::GoogleGemini31ProPreviewCustomtools
2326            | Self::GoogleGemma426bA4bIt
2327            | Self::GoogleGemma426bA4bItFree
2328            | Self::GoogleGemma431bIt
2329            | Self::GoogleGemma431bItFree
2330            | Self::InceptionMercury2
2331            | Self::MinimaxMinimax01
2332            | Self::MinimaxMinimaxM1
2333            | Self::MinimaxMinimaxM2
2334            | Self::MinimaxMinimaxM21
2335            | Self::MinimaxMinimaxM25
2336            | Self::MinimaxMinimaxM25Free
2337            | Self::MinimaxMinimaxM27
2338            | Self::MistralaiMistralSmall2603
2339            | Self::MoonshotaiKimiK2Thinking
2340            | Self::MoonshotaiKimiK25
2341            | Self::MoonshotaiKimiK26
2342            | Self::NousresearchHermes4405b
2343            | Self::NousresearchHermes470b
2344            | Self::NvidiaNemotron3Nano30bA3bFree
2345            | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree
2346            | Self::NvidiaNemotron3Super120bA12b
2347            | Self::NvidiaNemotron3Super120bA12bFree
2348            | Self::NvidiaNemotronNano12bV2VlFree
2349            | Self::NvidiaNemotronNano9bV2
2350            | Self::NvidiaNemotronNano9bV2Free
2351            | Self::OpenaiGpt5
2352            | Self::OpenaiGpt5Codex
2353            | Self::OpenaiGpt5Image
2354            | Self::OpenaiGpt5Mini
2355            | Self::OpenaiGpt5Nano
2356            | Self::OpenaiGpt5Pro
2357            | Self::OpenaiGpt51
2358            | Self::OpenaiGpt51Chat
2359            | Self::OpenaiGpt51Codex
2360            | Self::OpenaiGpt51CodexMax
2361            | Self::OpenaiGpt51CodexMini
2362            | Self::OpenaiGpt52
2363            | Self::OpenaiGpt52Chat
2364            | Self::OpenaiGpt52Codex
2365            | Self::OpenaiGpt52Pro
2366            | Self::OpenaiGpt53Codex
2367            | Self::OpenaiGpt54
2368            | Self::OpenaiGpt54Mini
2369            | Self::OpenaiGpt54Pro
2370            | Self::OpenaiGpt55
2371            | Self::OpenaiGpt55Pro
2372            | Self::OpenaiGptOss120b
2373            | Self::OpenaiGptOss120bExacto
2374            | Self::OpenaiGptOss120bFree
2375            | Self::OpenaiGptOss20b
2376            | Self::OpenaiGptOss20bFree
2377            | Self::OpenaiGptOssSafeguard20b
2378            | Self::OpenaiO4Mini
2379            | Self::OpenrouterElephantAlpha
2380            | Self::OpenrouterFree
2381            | Self::OpenrouterOwlAlpha
2382            | Self::OpenrouterParetoCode
2383            | Self::PoolsideLagunaM1Free
2384            | Self::PoolsideLagunaXs2Free
2385            | Self::PrimeIntellectIntellect3
2386            | Self::QwenQwen3235bA22bThinking2507
2387            | Self::QwenQwen330bA3bThinking2507
2388            | Self::QwenQwen3Max
2389            | Self::QwenQwen3Next80bA3bThinking
2390            | Self::QwenQwen35397bA17b
2391            | Self::QwenQwen35Flash0223
2392            | Self::QwenQwen35Plus0215
2393            | Self::QwenQwen36Plus
2394            | Self::StepfunStep35Flash
2395            | Self::TencentHy3Preview
2396            | Self::XAiGrok3Mini
2397            | Self::XAiGrok3MiniBeta
2398            | Self::XAiGrok4
2399            | Self::XAiGrok4Fast
2400            | Self::XAiGrok41Fast
2401            | Self::XAiGrok420Beta
2402            | Self::XAiGrok43
2403            | Self::XAiGrokCodeFast1
2404            | Self::XiaomiMimoV2Flash
2405            | Self::XiaomiMimoV2Omni
2406            | Self::XiaomiMimoV2Pro
2407            | Self::XiaomiMimoV25
2408            | Self::XiaomiMimoV25Pro
2409            | Self::ZAiGlm45
2410            | Self::ZAiGlm45Air
2411            | Self::ZAiGlm45v
2412            | Self::ZAiGlm46
2413            | Self::ZAiGlm46Exacto
2414            | Self::ZAiGlm47
2415            | Self::ZAiGlm47Flash
2416            | Self::ZAiGlm5
2417            | Self::ZAiGlm5Turbo
2418            | Self::ZAiGlm51 => {
2419                &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High]
2420            }
2421        }
2422    }
2423    pub fn supports_reasoning(self) -> bool {
2424        !self.reasoning_levels().is_empty()
2425    }
2426    #[allow(clippy::too_many_lines)]
2427    pub fn supports_prompt_caching(self) -> bool {
2428        match self {
2429            Self::ArceeAiTrinityLargePreviewFree
2430            | Self::ArceeAiTrinityLargeThinking
2431            | Self::DeepseekDeepseekChatV31
2432            | Self::DeepseekDeepseekR1
2433            | Self::DeepseekDeepseekV31Terminus
2434            | Self::DeepseekDeepseekV31TerminusExacto
2435            | Self::DeepseekDeepseekV32
2436            | Self::DeepseekDeepseekV32Speciale
2437            | Self::GoogleGemini3ProPreview
2438            | Self::GoogleGemini31ProPreview
2439            | Self::GoogleGemini31ProPreviewCustomtools
2440            | Self::GoogleGemma327bIt
2441            | Self::GoogleGemma327bItFree
2442            | Self::GoogleGemma426bA4bIt
2443            | Self::GoogleGemma426bA4bItFree
2444            | Self::GoogleGemma431bIt
2445            | Self::GoogleGemma431bItFree
2446            | Self::MetaLlamaLlama3370bInstructFree
2447            | Self::MinimaxMinimax01
2448            | Self::MinimaxMinimaxM1
2449            | Self::MinimaxMinimaxM21
2450            | Self::MinimaxMinimaxM25Free
2451            | Self::MistralaiCodestral2508
2452            | Self::MistralaiDevstral2512
2453            | Self::MistralaiDevstralMedium2507
2454            | Self::MistralaiDevstralSmall2505
2455            | Self::MistralaiDevstralSmall2507
2456            | Self::MistralaiMistralMedium3
2457            | Self::MistralaiMistralMedium31
2458            | Self::MistralaiMistralSmall2603
2459            | Self::MistralaiMistralSmall3124bInstruct
2460            | Self::MistralaiMistralSmall3224bInstruct
2461            | Self::MoonshotaiKimiK2
2462            | Self::MoonshotaiKimiK20905
2463            | Self::MoonshotaiKimiK20905Exacto
2464            | Self::NousresearchHermes4405b
2465            | Self::NousresearchHermes470b
2466            | Self::NvidiaNemotron3Nano30bA3bFree
2467            | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree
2468            | Self::NvidiaNemotron3Super120bA12b
2469            | Self::NvidiaNemotron3Super120bA12bFree
2470            | Self::NvidiaNemotronNano12bV2VlFree
2471            | Self::NvidiaNemotronNano9bV2
2472            | Self::NvidiaNemotronNano9bV2Free
2473            | Self::OpenaiGpt5
2474            | Self::OpenaiGpt5Mini
2475            | Self::OpenaiGpt5Nano
2476            | Self::OpenaiGpt5Pro
2477            | Self::OpenaiGpt52Pro
2478            | Self::OpenaiGpt55Pro
2479            | Self::OpenaiGptOss120b
2480            | Self::OpenaiGptOss120bExacto
2481            | Self::OpenaiGptOss120bFree
2482            | Self::OpenaiGptOss20b
2483            | Self::OpenaiGptOss20bFree
2484            | Self::OpenaiGptOssSafeguard20b
2485            | Self::OpenrouterElephantAlpha
2486            | Self::OpenrouterFree
2487            | Self::OpenrouterOwlAlpha
2488            | Self::OpenrouterParetoCode
2489            | Self::PrimeIntellectIntellect3
2490            | Self::QwenQwen3627b
2491            | Self::QwenQwen3235bA22b0725
2492            | Self::QwenQwen3235bA22bThinking2507
2493            | Self::QwenQwen330bA3bInstruct2507
2494            | Self::QwenQwen330bA3bThinking2507
2495            | Self::QwenQwen3Coder
2496            | Self::QwenQwen3Coder30bA3bInstruct
2497            | Self::QwenQwen3CoderExacto
2498            | Self::QwenQwen3Next80bA3bInstruct
2499            | Self::QwenQwen3Next80bA3bThinking
2500            | Self::QwenQwen35397bA17b
2501            | Self::QwenQwen35Flash0223
2502            | Self::QwenQwen35Plus0215
2503            | Self::ZAiGlm45
2504            | Self::ZAiGlm45Air
2505            | Self::ZAiGlm45v
2506            | Self::ZAiGlm47Flash => false,
2507            Self::AnthropicClaude35Haiku
2508            | Self::AnthropicClaude37Sonnet
2509            | Self::AnthropicClaudeHaiku45
2510            | Self::AnthropicClaudeOpus4
2511            | Self::AnthropicClaudeOpus41
2512            | Self::AnthropicClaudeOpus45
2513            | Self::AnthropicClaudeOpus46
2514            | Self::AnthropicClaudeOpus47
2515            | Self::AnthropicClaudeSonnet4
2516            | Self::AnthropicClaudeSonnet45
2517            | Self::AnthropicClaudeSonnet46
2518            | Self::DeepseekDeepseekV4Flash
2519            | Self::DeepseekDeepseekV4Pro
2520            | Self::GoogleGemini20Flash001
2521            | Self::GoogleGemini25Flash
2522            | Self::GoogleGemini25FlashLite
2523            | Self::GoogleGemini25FlashLitePreview092025
2524            | Self::GoogleGemini25FlashPreview092025
2525            | Self::GoogleGemini25Pro
2526            | Self::GoogleGemini25ProPreview0506
2527            | Self::GoogleGemini25ProPreview0605
2528            | Self::GoogleGemini3FlashPreview
2529            | Self::GoogleGemini31FlashLitePreview
2530            | Self::InceptionMercury2
2531            | Self::MinimaxMinimaxM2
2532            | Self::MinimaxMinimaxM25
2533            | Self::MinimaxMinimaxM27
2534            | Self::MoonshotaiKimiK2Thinking
2535            | Self::MoonshotaiKimiK25
2536            | Self::MoonshotaiKimiK26
2537            | Self::OpenaiGpt41
2538            | Self::OpenaiGpt41Mini
2539            | Self::OpenaiGpt4oMini
2540            | Self::OpenaiGpt5Codex
2541            | Self::OpenaiGpt5Image
2542            | Self::OpenaiGpt51
2543            | Self::OpenaiGpt51Chat
2544            | Self::OpenaiGpt51Codex
2545            | Self::OpenaiGpt51CodexMax
2546            | Self::OpenaiGpt51CodexMini
2547            | Self::OpenaiGpt52
2548            | Self::OpenaiGpt52Chat
2549            | Self::OpenaiGpt52Codex
2550            | Self::OpenaiGpt53Codex
2551            | Self::OpenaiGpt54
2552            | Self::OpenaiGpt54Mini
2553            | Self::OpenaiGpt54Nano
2554            | Self::OpenaiGpt54Pro
2555            | Self::OpenaiGpt55
2556            | Self::OpenaiO4Mini
2557            | Self::PoolsideLagunaM1Free
2558            | Self::PoolsideLagunaXs2Free
2559            | Self::QwenQwenPlus
2560            | Self::QwenQwen3CoderFlash
2561            | Self::QwenQwen3CoderPlus
2562            | Self::QwenQwen3Max
2563            | Self::QwenQwen36Plus
2564            | Self::StepfunStep35Flash
2565            | Self::TencentHy3Preview
2566            | Self::XAiGrok3
2567            | Self::XAiGrok3Beta
2568            | Self::XAiGrok3Mini
2569            | Self::XAiGrok3MiniBeta
2570            | Self::XAiGrok4
2571            | Self::XAiGrok4Fast
2572            | Self::XAiGrok41Fast
2573            | Self::XAiGrok420Beta
2574            | Self::XAiGrok43
2575            | Self::XAiGrokCodeFast1
2576            | Self::XiaomiMimoV2Flash
2577            | Self::XiaomiMimoV2Omni
2578            | Self::XiaomiMimoV2Pro
2579            | Self::XiaomiMimoV25
2580            | Self::XiaomiMimoV25Pro
2581            | Self::ZAiGlm46
2582            | Self::ZAiGlm46Exacto
2583            | Self::ZAiGlm47
2584            | Self::ZAiGlm5
2585            | Self::ZAiGlm5Turbo
2586            | Self::ZAiGlm51 => true,
2587        }
2588    }
2589    #[allow(clippy::too_many_lines)]
2590    pub fn supports_image(self) -> bool {
2591        match self {
2592            Self::ArceeAiTrinityLargePreviewFree
2593            | Self::ArceeAiTrinityLargeThinking
2594            | Self::DeepseekDeepseekChatV31
2595            | Self::DeepseekDeepseekR1
2596            | Self::DeepseekDeepseekV31Terminus
2597            | Self::DeepseekDeepseekV31TerminusExacto
2598            | Self::DeepseekDeepseekV32
2599            | Self::DeepseekDeepseekV32Speciale
2600            | Self::DeepseekDeepseekV4Flash
2601            | Self::DeepseekDeepseekV4Pro
2602            | Self::InceptionMercury2
2603            | Self::MetaLlamaLlama3370bInstructFree
2604            | Self::MinimaxMinimaxM1
2605            | Self::MinimaxMinimaxM2
2606            | Self::MinimaxMinimaxM21
2607            | Self::MinimaxMinimaxM25
2608            | Self::MinimaxMinimaxM25Free
2609            | Self::MinimaxMinimaxM27
2610            | Self::MistralaiCodestral2508
2611            | Self::MistralaiDevstral2512
2612            | Self::MistralaiDevstralMedium2507
2613            | Self::MistralaiDevstralSmall2505
2614            | Self::MistralaiDevstralSmall2507
2615            | Self::MoonshotaiKimiK2
2616            | Self::MoonshotaiKimiK20905
2617            | Self::MoonshotaiKimiK20905Exacto
2618            | Self::MoonshotaiKimiK2Thinking
2619            | Self::NousresearchHermes4405b
2620            | Self::NousresearchHermes470b
2621            | Self::NvidiaNemotron3Nano30bA3bFree
2622            | Self::NvidiaNemotron3Super120bA12b
2623            | Self::NvidiaNemotron3Super120bA12bFree
2624            | Self::NvidiaNemotronNano9bV2
2625            | Self::NvidiaNemotronNano9bV2Free
2626            | Self::OpenaiGptOss120b
2627            | Self::OpenaiGptOss120bExacto
2628            | Self::OpenaiGptOss120bFree
2629            | Self::OpenaiGptOss20b
2630            | Self::OpenaiGptOss20bFree
2631            | Self::OpenaiGptOssSafeguard20b
2632            | Self::OpenrouterElephantAlpha
2633            | Self::OpenrouterOwlAlpha
2634            | Self::OpenrouterParetoCode
2635            | Self::PoolsideLagunaM1Free
2636            | Self::PoolsideLagunaXs2Free
2637            | Self::PrimeIntellectIntellect3
2638            | Self::QwenQwenPlus
2639            | Self::QwenQwen3235bA22b0725
2640            | Self::QwenQwen3235bA22bThinking2507
2641            | Self::QwenQwen330bA3bInstruct2507
2642            | Self::QwenQwen330bA3bThinking2507
2643            | Self::QwenQwen3Coder
2644            | Self::QwenQwen3Coder30bA3bInstruct
2645            | Self::QwenQwen3CoderFlash
2646            | Self::QwenQwen3CoderPlus
2647            | Self::QwenQwen3CoderExacto
2648            | Self::QwenQwen3Max
2649            | Self::QwenQwen3Next80bA3bInstruct
2650            | Self::QwenQwen3Next80bA3bThinking
2651            | Self::StepfunStep35Flash
2652            | Self::TencentHy3Preview
2653            | Self::XAiGrok3
2654            | Self::XAiGrok3Beta
2655            | Self::XAiGrok3Mini
2656            | Self::XAiGrok3MiniBeta
2657            | Self::XAiGrok4
2658            | Self::XAiGrokCodeFast1
2659            | Self::XiaomiMimoV2Flash
2660            | Self::XiaomiMimoV2Pro
2661            | Self::XiaomiMimoV25Pro
2662            | Self::ZAiGlm45
2663            | Self::ZAiGlm45Air
2664            | Self::ZAiGlm46
2665            | Self::ZAiGlm46Exacto
2666            | Self::ZAiGlm47
2667            | Self::ZAiGlm47Flash
2668            | Self::ZAiGlm5
2669            | Self::ZAiGlm5Turbo
2670            | Self::ZAiGlm51 => false,
2671            Self::AnthropicClaude35Haiku
2672            | Self::AnthropicClaude37Sonnet
2673            | Self::AnthropicClaudeHaiku45
2674            | Self::AnthropicClaudeOpus4
2675            | Self::AnthropicClaudeOpus41
2676            | Self::AnthropicClaudeOpus45
2677            | Self::AnthropicClaudeOpus46
2678            | Self::AnthropicClaudeOpus47
2679            | Self::AnthropicClaudeSonnet4
2680            | Self::AnthropicClaudeSonnet45
2681            | Self::AnthropicClaudeSonnet46
2682            | Self::GoogleGemini20Flash001
2683            | Self::GoogleGemini25Flash
2684            | Self::GoogleGemini25FlashLite
2685            | Self::GoogleGemini25FlashLitePreview092025
2686            | Self::GoogleGemini25FlashPreview092025
2687            | Self::GoogleGemini25Pro
2688            | Self::GoogleGemini25ProPreview0506
2689            | Self::GoogleGemini25ProPreview0605
2690            | Self::GoogleGemini3FlashPreview
2691            | Self::GoogleGemini3ProPreview
2692            | Self::GoogleGemini31FlashLitePreview
2693            | Self::GoogleGemini31ProPreview
2694            | Self::GoogleGemini31ProPreviewCustomtools
2695            | Self::GoogleGemma327bIt
2696            | Self::GoogleGemma327bItFree
2697            | Self::GoogleGemma426bA4bIt
2698            | Self::GoogleGemma426bA4bItFree
2699            | Self::GoogleGemma431bIt
2700            | Self::GoogleGemma431bItFree
2701            | Self::MinimaxMinimax01
2702            | Self::MistralaiMistralMedium3
2703            | Self::MistralaiMistralMedium31
2704            | Self::MistralaiMistralSmall2603
2705            | Self::MistralaiMistralSmall3124bInstruct
2706            | Self::MistralaiMistralSmall3224bInstruct
2707            | Self::MoonshotaiKimiK25
2708            | Self::MoonshotaiKimiK26
2709            | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree
2710            | Self::NvidiaNemotronNano12bV2VlFree
2711            | Self::OpenaiGpt41
2712            | Self::OpenaiGpt41Mini
2713            | Self::OpenaiGpt4oMini
2714            | Self::OpenaiGpt5
2715            | Self::OpenaiGpt5Codex
2716            | Self::OpenaiGpt5Image
2717            | Self::OpenaiGpt5Mini
2718            | Self::OpenaiGpt5Nano
2719            | Self::OpenaiGpt5Pro
2720            | Self::OpenaiGpt51
2721            | Self::OpenaiGpt51Chat
2722            | Self::OpenaiGpt51Codex
2723            | Self::OpenaiGpt51CodexMax
2724            | Self::OpenaiGpt51CodexMini
2725            | Self::OpenaiGpt52
2726            | Self::OpenaiGpt52Chat
2727            | Self::OpenaiGpt52Codex
2728            | Self::OpenaiGpt52Pro
2729            | Self::OpenaiGpt53Codex
2730            | Self::OpenaiGpt54
2731            | Self::OpenaiGpt54Mini
2732            | Self::OpenaiGpt54Nano
2733            | Self::OpenaiGpt54Pro
2734            | Self::OpenaiGpt55
2735            | Self::OpenaiGpt55Pro
2736            | Self::OpenaiO4Mini
2737            | Self::OpenrouterFree
2738            | Self::QwenQwen3627b
2739            | Self::QwenQwen35397bA17b
2740            | Self::QwenQwen35Flash0223
2741            | Self::QwenQwen35Plus0215
2742            | Self::QwenQwen36Plus
2743            | Self::XAiGrok4Fast
2744            | Self::XAiGrok41Fast
2745            | Self::XAiGrok420Beta
2746            | Self::XAiGrok43
2747            | Self::XiaomiMimoV2Omni
2748            | Self::XiaomiMimoV25
2749            | Self::ZAiGlm45v => true,
2750        }
2751    }
2752    #[allow(clippy::too_many_lines)]
2753    pub fn supports_audio(self) -> bool {
2754        match self {
2755            Self::AnthropicClaude35Haiku
2756            | Self::AnthropicClaude37Sonnet
2757            | Self::AnthropicClaudeHaiku45
2758            | Self::AnthropicClaudeOpus4
2759            | Self::AnthropicClaudeOpus41
2760            | Self::AnthropicClaudeOpus45
2761            | Self::AnthropicClaudeOpus46
2762            | Self::AnthropicClaudeOpus47
2763            | Self::AnthropicClaudeSonnet4
2764            | Self::AnthropicClaudeSonnet45
2765            | Self::AnthropicClaudeSonnet46
2766            | Self::ArceeAiTrinityLargePreviewFree
2767            | Self::ArceeAiTrinityLargeThinking
2768            | Self::DeepseekDeepseekChatV31
2769            | Self::DeepseekDeepseekR1
2770            | Self::DeepseekDeepseekV31Terminus
2771            | Self::DeepseekDeepseekV31TerminusExacto
2772            | Self::DeepseekDeepseekV32
2773            | Self::DeepseekDeepseekV32Speciale
2774            | Self::DeepseekDeepseekV4Flash
2775            | Self::DeepseekDeepseekV4Pro
2776            | Self::GoogleGemma327bIt
2777            | Self::GoogleGemma327bItFree
2778            | Self::GoogleGemma426bA4bIt
2779            | Self::GoogleGemma426bA4bItFree
2780            | Self::GoogleGemma431bIt
2781            | Self::GoogleGemma431bItFree
2782            | Self::InceptionMercury2
2783            | Self::MetaLlamaLlama3370bInstructFree
2784            | Self::MinimaxMinimax01
2785            | Self::MinimaxMinimaxM1
2786            | Self::MinimaxMinimaxM2
2787            | Self::MinimaxMinimaxM21
2788            | Self::MinimaxMinimaxM25
2789            | Self::MinimaxMinimaxM25Free
2790            | Self::MinimaxMinimaxM27
2791            | Self::MistralaiCodestral2508
2792            | Self::MistralaiDevstral2512
2793            | Self::MistralaiDevstralMedium2507
2794            | Self::MistralaiDevstralSmall2505
2795            | Self::MistralaiDevstralSmall2507
2796            | Self::MistralaiMistralMedium3
2797            | Self::MistralaiMistralMedium31
2798            | Self::MistralaiMistralSmall2603
2799            | Self::MistralaiMistralSmall3124bInstruct
2800            | Self::MistralaiMistralSmall3224bInstruct
2801            | Self::MoonshotaiKimiK2
2802            | Self::MoonshotaiKimiK20905
2803            | Self::MoonshotaiKimiK20905Exacto
2804            | Self::MoonshotaiKimiK2Thinking
2805            | Self::MoonshotaiKimiK25
2806            | Self::MoonshotaiKimiK26
2807            | Self::NousresearchHermes4405b
2808            | Self::NousresearchHermes470b
2809            | Self::NvidiaNemotron3Nano30bA3bFree
2810            | Self::NvidiaNemotron3Super120bA12b
2811            | Self::NvidiaNemotron3Super120bA12bFree
2812            | Self::NvidiaNemotronNano12bV2VlFree
2813            | Self::NvidiaNemotronNano9bV2
2814            | Self::NvidiaNemotronNano9bV2Free
2815            | Self::OpenaiGpt41
2816            | Self::OpenaiGpt41Mini
2817            | Self::OpenaiGpt4oMini
2818            | Self::OpenaiGpt5
2819            | Self::OpenaiGpt5Codex
2820            | Self::OpenaiGpt5Image
2821            | Self::OpenaiGpt5Mini
2822            | Self::OpenaiGpt5Nano
2823            | Self::OpenaiGpt5Pro
2824            | Self::OpenaiGpt51
2825            | Self::OpenaiGpt51Chat
2826            | Self::OpenaiGpt51Codex
2827            | Self::OpenaiGpt51CodexMax
2828            | Self::OpenaiGpt51CodexMini
2829            | Self::OpenaiGpt52
2830            | Self::OpenaiGpt52Chat
2831            | Self::OpenaiGpt52Codex
2832            | Self::OpenaiGpt52Pro
2833            | Self::OpenaiGpt53Codex
2834            | Self::OpenaiGpt54
2835            | Self::OpenaiGpt54Mini
2836            | Self::OpenaiGpt54Nano
2837            | Self::OpenaiGpt54Pro
2838            | Self::OpenaiGpt55
2839            | Self::OpenaiGpt55Pro
2840            | Self::OpenaiGptOss120b
2841            | Self::OpenaiGptOss120bExacto
2842            | Self::OpenaiGptOss120bFree
2843            | Self::OpenaiGptOss20b
2844            | Self::OpenaiGptOss20bFree
2845            | Self::OpenaiGptOssSafeguard20b
2846            | Self::OpenaiO4Mini
2847            | Self::OpenrouterElephantAlpha
2848            | Self::OpenrouterFree
2849            | Self::OpenrouterOwlAlpha
2850            | Self::OpenrouterParetoCode
2851            | Self::PoolsideLagunaM1Free
2852            | Self::PoolsideLagunaXs2Free
2853            | Self::PrimeIntellectIntellect3
2854            | Self::QwenQwen3627b
2855            | Self::QwenQwenPlus
2856            | Self::QwenQwen3235bA22b0725
2857            | Self::QwenQwen3235bA22bThinking2507
2858            | Self::QwenQwen330bA3bInstruct2507
2859            | Self::QwenQwen330bA3bThinking2507
2860            | Self::QwenQwen3Coder
2861            | Self::QwenQwen3Coder30bA3bInstruct
2862            | Self::QwenQwen3CoderFlash
2863            | Self::QwenQwen3CoderPlus
2864            | Self::QwenQwen3CoderExacto
2865            | Self::QwenQwen3Max
2866            | Self::QwenQwen3Next80bA3bInstruct
2867            | Self::QwenQwen3Next80bA3bThinking
2868            | Self::QwenQwen35397bA17b
2869            | Self::QwenQwen35Flash0223
2870            | Self::QwenQwen35Plus0215
2871            | Self::QwenQwen36Plus
2872            | Self::StepfunStep35Flash
2873            | Self::TencentHy3Preview
2874            | Self::XAiGrok3
2875            | Self::XAiGrok3Beta
2876            | Self::XAiGrok3Mini
2877            | Self::XAiGrok3MiniBeta
2878            | Self::XAiGrok4
2879            | Self::XAiGrok4Fast
2880            | Self::XAiGrok41Fast
2881            | Self::XAiGrok420Beta
2882            | Self::XAiGrok43
2883            | Self::XAiGrokCodeFast1
2884            | Self::XiaomiMimoV2Flash
2885            | Self::XiaomiMimoV2Pro
2886            | Self::XiaomiMimoV25Pro
2887            | Self::ZAiGlm45
2888            | Self::ZAiGlm45Air
2889            | Self::ZAiGlm45v
2890            | Self::ZAiGlm46
2891            | Self::ZAiGlm46Exacto
2892            | Self::ZAiGlm47
2893            | Self::ZAiGlm47Flash
2894            | Self::ZAiGlm5
2895            | Self::ZAiGlm5Turbo
2896            | Self::ZAiGlm51 => false,
2897            Self::GoogleGemini20Flash001
2898            | Self::GoogleGemini25Flash
2899            | Self::GoogleGemini25FlashLite
2900            | Self::GoogleGemini25FlashLitePreview092025
2901            | Self::GoogleGemini25FlashPreview092025
2902            | Self::GoogleGemini25Pro
2903            | Self::GoogleGemini25ProPreview0506
2904            | Self::GoogleGemini25ProPreview0605
2905            | Self::GoogleGemini3FlashPreview
2906            | Self::GoogleGemini3ProPreview
2907            | Self::GoogleGemini31FlashLitePreview
2908            | Self::GoogleGemini31ProPreview
2909            | Self::GoogleGemini31ProPreviewCustomtools
2910            | Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree
2911            | Self::XiaomiMimoV2Omni
2912            | Self::XiaomiMimoV25 => true,
2913        }
2914    }
2915    const ALL: &[OpenRouterModel] = &[
2916        Self::AnthropicClaude35Haiku,
2917        Self::AnthropicClaude37Sonnet,
2918        Self::AnthropicClaudeHaiku45,
2919        Self::AnthropicClaudeOpus4,
2920        Self::AnthropicClaudeOpus41,
2921        Self::AnthropicClaudeOpus45,
2922        Self::AnthropicClaudeOpus46,
2923        Self::AnthropicClaudeOpus47,
2924        Self::AnthropicClaudeSonnet4,
2925        Self::AnthropicClaudeSonnet45,
2926        Self::AnthropicClaudeSonnet46,
2927        Self::ArceeAiTrinityLargePreviewFree,
2928        Self::ArceeAiTrinityLargeThinking,
2929        Self::DeepseekDeepseekChatV31,
2930        Self::DeepseekDeepseekR1,
2931        Self::DeepseekDeepseekV31Terminus,
2932        Self::DeepseekDeepseekV31TerminusExacto,
2933        Self::DeepseekDeepseekV32,
2934        Self::DeepseekDeepseekV32Speciale,
2935        Self::DeepseekDeepseekV4Flash,
2936        Self::DeepseekDeepseekV4Pro,
2937        Self::GoogleGemini20Flash001,
2938        Self::GoogleGemini25Flash,
2939        Self::GoogleGemini25FlashLite,
2940        Self::GoogleGemini25FlashLitePreview092025,
2941        Self::GoogleGemini25FlashPreview092025,
2942        Self::GoogleGemini25Pro,
2943        Self::GoogleGemini25ProPreview0506,
2944        Self::GoogleGemini25ProPreview0605,
2945        Self::GoogleGemini3FlashPreview,
2946        Self::GoogleGemini3ProPreview,
2947        Self::GoogleGemini31FlashLitePreview,
2948        Self::GoogleGemini31ProPreview,
2949        Self::GoogleGemini31ProPreviewCustomtools,
2950        Self::GoogleGemma327bIt,
2951        Self::GoogleGemma327bItFree,
2952        Self::GoogleGemma426bA4bIt,
2953        Self::GoogleGemma426bA4bItFree,
2954        Self::GoogleGemma431bIt,
2955        Self::GoogleGemma431bItFree,
2956        Self::InceptionMercury2,
2957        Self::MetaLlamaLlama3370bInstructFree,
2958        Self::MinimaxMinimax01,
2959        Self::MinimaxMinimaxM1,
2960        Self::MinimaxMinimaxM2,
2961        Self::MinimaxMinimaxM21,
2962        Self::MinimaxMinimaxM25,
2963        Self::MinimaxMinimaxM25Free,
2964        Self::MinimaxMinimaxM27,
2965        Self::MistralaiCodestral2508,
2966        Self::MistralaiDevstral2512,
2967        Self::MistralaiDevstralMedium2507,
2968        Self::MistralaiDevstralSmall2505,
2969        Self::MistralaiDevstralSmall2507,
2970        Self::MistralaiMistralMedium3,
2971        Self::MistralaiMistralMedium31,
2972        Self::MistralaiMistralSmall2603,
2973        Self::MistralaiMistralSmall3124bInstruct,
2974        Self::MistralaiMistralSmall3224bInstruct,
2975        Self::MoonshotaiKimiK2,
2976        Self::MoonshotaiKimiK20905,
2977        Self::MoonshotaiKimiK20905Exacto,
2978        Self::MoonshotaiKimiK2Thinking,
2979        Self::MoonshotaiKimiK25,
2980        Self::MoonshotaiKimiK26,
2981        Self::NousresearchHermes4405b,
2982        Self::NousresearchHermes470b,
2983        Self::NvidiaNemotron3Nano30bA3bFree,
2984        Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree,
2985        Self::NvidiaNemotron3Super120bA12b,
2986        Self::NvidiaNemotron3Super120bA12bFree,
2987        Self::NvidiaNemotronNano12bV2VlFree,
2988        Self::NvidiaNemotronNano9bV2,
2989        Self::NvidiaNemotronNano9bV2Free,
2990        Self::OpenaiGpt41,
2991        Self::OpenaiGpt41Mini,
2992        Self::OpenaiGpt4oMini,
2993        Self::OpenaiGpt5,
2994        Self::OpenaiGpt5Codex,
2995        Self::OpenaiGpt5Image,
2996        Self::OpenaiGpt5Mini,
2997        Self::OpenaiGpt5Nano,
2998        Self::OpenaiGpt5Pro,
2999        Self::OpenaiGpt51,
3000        Self::OpenaiGpt51Chat,
3001        Self::OpenaiGpt51Codex,
3002        Self::OpenaiGpt51CodexMax,
3003        Self::OpenaiGpt51CodexMini,
3004        Self::OpenaiGpt52,
3005        Self::OpenaiGpt52Chat,
3006        Self::OpenaiGpt52Codex,
3007        Self::OpenaiGpt52Pro,
3008        Self::OpenaiGpt53Codex,
3009        Self::OpenaiGpt54,
3010        Self::OpenaiGpt54Mini,
3011        Self::OpenaiGpt54Nano,
3012        Self::OpenaiGpt54Pro,
3013        Self::OpenaiGpt55,
3014        Self::OpenaiGpt55Pro,
3015        Self::OpenaiGptOss120b,
3016        Self::OpenaiGptOss120bExacto,
3017        Self::OpenaiGptOss120bFree,
3018        Self::OpenaiGptOss20b,
3019        Self::OpenaiGptOss20bFree,
3020        Self::OpenaiGptOssSafeguard20b,
3021        Self::OpenaiO4Mini,
3022        Self::OpenrouterElephantAlpha,
3023        Self::OpenrouterFree,
3024        Self::OpenrouterOwlAlpha,
3025        Self::OpenrouterParetoCode,
3026        Self::PoolsideLagunaM1Free,
3027        Self::PoolsideLagunaXs2Free,
3028        Self::PrimeIntellectIntellect3,
3029        Self::QwenQwen3627b,
3030        Self::QwenQwenPlus,
3031        Self::QwenQwen3235bA22b0725,
3032        Self::QwenQwen3235bA22bThinking2507,
3033        Self::QwenQwen330bA3bInstruct2507,
3034        Self::QwenQwen330bA3bThinking2507,
3035        Self::QwenQwen3Coder,
3036        Self::QwenQwen3Coder30bA3bInstruct,
3037        Self::QwenQwen3CoderFlash,
3038        Self::QwenQwen3CoderPlus,
3039        Self::QwenQwen3CoderExacto,
3040        Self::QwenQwen3Max,
3041        Self::QwenQwen3Next80bA3bInstruct,
3042        Self::QwenQwen3Next80bA3bThinking,
3043        Self::QwenQwen35397bA17b,
3044        Self::QwenQwen35Flash0223,
3045        Self::QwenQwen35Plus0215,
3046        Self::QwenQwen36Plus,
3047        Self::StepfunStep35Flash,
3048        Self::TencentHy3Preview,
3049        Self::XAiGrok3,
3050        Self::XAiGrok3Beta,
3051        Self::XAiGrok3Mini,
3052        Self::XAiGrok3MiniBeta,
3053        Self::XAiGrok4,
3054        Self::XAiGrok4Fast,
3055        Self::XAiGrok41Fast,
3056        Self::XAiGrok420Beta,
3057        Self::XAiGrok43,
3058        Self::XAiGrokCodeFast1,
3059        Self::XiaomiMimoV2Flash,
3060        Self::XiaomiMimoV2Omni,
3061        Self::XiaomiMimoV2Pro,
3062        Self::XiaomiMimoV25,
3063        Self::XiaomiMimoV25Pro,
3064        Self::ZAiGlm45,
3065        Self::ZAiGlm45Air,
3066        Self::ZAiGlm45v,
3067        Self::ZAiGlm46,
3068        Self::ZAiGlm46Exacto,
3069        Self::ZAiGlm47,
3070        Self::ZAiGlm47Flash,
3071        Self::ZAiGlm5,
3072        Self::ZAiGlm5Turbo,
3073        Self::ZAiGlm51,
3074    ];
3075}
3076impl std::str::FromStr for OpenRouterModel {
3077    type Err = String;
3078    #[allow(clippy::too_many_lines)]
3079    fn from_str(s: &str) -> Result<Self, Self::Err> {
3080        match s {
3081            "anthropic/claude-3.5-haiku" => Ok(Self::AnthropicClaude35Haiku),
3082            "anthropic/claude-3.7-sonnet" => Ok(Self::AnthropicClaude37Sonnet),
3083            "anthropic/claude-haiku-4.5" => Ok(Self::AnthropicClaudeHaiku45),
3084            "anthropic/claude-opus-4" => Ok(Self::AnthropicClaudeOpus4),
3085            "anthropic/claude-opus-4.1" => Ok(Self::AnthropicClaudeOpus41),
3086            "anthropic/claude-opus-4.5" => Ok(Self::AnthropicClaudeOpus45),
3087            "anthropic/claude-opus-4.6" => Ok(Self::AnthropicClaudeOpus46),
3088            "anthropic/claude-opus-4.7" => Ok(Self::AnthropicClaudeOpus47),
3089            "anthropic/claude-sonnet-4" => Ok(Self::AnthropicClaudeSonnet4),
3090            "anthropic/claude-sonnet-4.5" => Ok(Self::AnthropicClaudeSonnet45),
3091            "anthropic/claude-sonnet-4.6" => Ok(Self::AnthropicClaudeSonnet46),
3092            "arcee-ai/trinity-large-preview:free" => {
3093                Ok(Self::ArceeAiTrinityLargePreviewFree)
3094            }
3095            "arcee-ai/trinity-large-thinking" => Ok(Self::ArceeAiTrinityLargeThinking),
3096            "deepseek/deepseek-chat-v3.1" => Ok(Self::DeepseekDeepseekChatV31),
3097            "deepseek/deepseek-r1" => Ok(Self::DeepseekDeepseekR1),
3098            "deepseek/deepseek-v3.1-terminus" => Ok(Self::DeepseekDeepseekV31Terminus),
3099            "deepseek/deepseek-v3.1-terminus:exacto" => {
3100                Ok(Self::DeepseekDeepseekV31TerminusExacto)
3101            }
3102            "deepseek/deepseek-v3.2" => Ok(Self::DeepseekDeepseekV32),
3103            "deepseek/deepseek-v3.2-speciale" => Ok(Self::DeepseekDeepseekV32Speciale),
3104            "deepseek/deepseek-v4-flash" => Ok(Self::DeepseekDeepseekV4Flash),
3105            "deepseek/deepseek-v4-pro" => Ok(Self::DeepseekDeepseekV4Pro),
3106            "google/gemini-2.0-flash-001" => Ok(Self::GoogleGemini20Flash001),
3107            "google/gemini-2.5-flash" => Ok(Self::GoogleGemini25Flash),
3108            "google/gemini-2.5-flash-lite" => Ok(Self::GoogleGemini25FlashLite),
3109            "google/gemini-2.5-flash-lite-preview-09-2025" => {
3110                Ok(Self::GoogleGemini25FlashLitePreview092025)
3111            }
3112            "google/gemini-2.5-flash-preview-09-2025" => {
3113                Ok(Self::GoogleGemini25FlashPreview092025)
3114            }
3115            "google/gemini-2.5-pro" => Ok(Self::GoogleGemini25Pro),
3116            "google/gemini-2.5-pro-preview-05-06" => {
3117                Ok(Self::GoogleGemini25ProPreview0506)
3118            }
3119            "google/gemini-2.5-pro-preview-06-05" => {
3120                Ok(Self::GoogleGemini25ProPreview0605)
3121            }
3122            "google/gemini-3-flash-preview" => Ok(Self::GoogleGemini3FlashPreview),
3123            "google/gemini-3-pro-preview" => Ok(Self::GoogleGemini3ProPreview),
3124            "google/gemini-3.1-flash-lite-preview" => {
3125                Ok(Self::GoogleGemini31FlashLitePreview)
3126            }
3127            "google/gemini-3.1-pro-preview" => Ok(Self::GoogleGemini31ProPreview),
3128            "google/gemini-3.1-pro-preview-customtools" => {
3129                Ok(Self::GoogleGemini31ProPreviewCustomtools)
3130            }
3131            "google/gemma-3-27b-it" => Ok(Self::GoogleGemma327bIt),
3132            "google/gemma-3-27b-it:free" => Ok(Self::GoogleGemma327bItFree),
3133            "google/gemma-4-26b-a4b-it" => Ok(Self::GoogleGemma426bA4bIt),
3134            "google/gemma-4-26b-a4b-it:free" => Ok(Self::GoogleGemma426bA4bItFree),
3135            "google/gemma-4-31b-it" => Ok(Self::GoogleGemma431bIt),
3136            "google/gemma-4-31b-it:free" => Ok(Self::GoogleGemma431bItFree),
3137            "inception/mercury-2" => Ok(Self::InceptionMercury2),
3138            "meta-llama/llama-3.3-70b-instruct:free" => {
3139                Ok(Self::MetaLlamaLlama3370bInstructFree)
3140            }
3141            "minimax/minimax-01" => Ok(Self::MinimaxMinimax01),
3142            "minimax/minimax-m1" => Ok(Self::MinimaxMinimaxM1),
3143            "minimax/minimax-m2" => Ok(Self::MinimaxMinimaxM2),
3144            "minimax/minimax-m2.1" => Ok(Self::MinimaxMinimaxM21),
3145            "minimax/minimax-m2.5" => Ok(Self::MinimaxMinimaxM25),
3146            "minimax/minimax-m2.5:free" => Ok(Self::MinimaxMinimaxM25Free),
3147            "minimax/minimax-m2.7" => Ok(Self::MinimaxMinimaxM27),
3148            "mistralai/codestral-2508" => Ok(Self::MistralaiCodestral2508),
3149            "mistralai/devstral-2512" => Ok(Self::MistralaiDevstral2512),
3150            "mistralai/devstral-medium-2507" => Ok(Self::MistralaiDevstralMedium2507),
3151            "mistralai/devstral-small-2505" => Ok(Self::MistralaiDevstralSmall2505),
3152            "mistralai/devstral-small-2507" => Ok(Self::MistralaiDevstralSmall2507),
3153            "mistralai/mistral-medium-3" => Ok(Self::MistralaiMistralMedium3),
3154            "mistralai/mistral-medium-3.1" => Ok(Self::MistralaiMistralMedium31),
3155            "mistralai/mistral-small-2603" => Ok(Self::MistralaiMistralSmall2603),
3156            "mistralai/mistral-small-3.1-24b-instruct" => {
3157                Ok(Self::MistralaiMistralSmall3124bInstruct)
3158            }
3159            "mistralai/mistral-small-3.2-24b-instruct" => {
3160                Ok(Self::MistralaiMistralSmall3224bInstruct)
3161            }
3162            "moonshotai/kimi-k2" => Ok(Self::MoonshotaiKimiK2),
3163            "moonshotai/kimi-k2-0905" => Ok(Self::MoonshotaiKimiK20905),
3164            "moonshotai/kimi-k2-0905:exacto" => Ok(Self::MoonshotaiKimiK20905Exacto),
3165            "moonshotai/kimi-k2-thinking" => Ok(Self::MoonshotaiKimiK2Thinking),
3166            "moonshotai/kimi-k2.5" => Ok(Self::MoonshotaiKimiK25),
3167            "moonshotai/kimi-k2.6" => Ok(Self::MoonshotaiKimiK26),
3168            "nousresearch/hermes-4-405b" => Ok(Self::NousresearchHermes4405b),
3169            "nousresearch/hermes-4-70b" => Ok(Self::NousresearchHermes470b),
3170            "nvidia/nemotron-3-nano-30b-a3b:free" => {
3171                Ok(Self::NvidiaNemotron3Nano30bA3bFree)
3172            }
3173            "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free" => {
3174                Ok(Self::NvidiaNemotron3NanoOmni30bA3bReasoningFree)
3175            }
3176            "nvidia/nemotron-3-super-120b-a12b" => Ok(Self::NvidiaNemotron3Super120bA12b),
3177            "nvidia/nemotron-3-super-120b-a12b:free" => {
3178                Ok(Self::NvidiaNemotron3Super120bA12bFree)
3179            }
3180            "nvidia/nemotron-nano-12b-v2-vl:free" => {
3181                Ok(Self::NvidiaNemotronNano12bV2VlFree)
3182            }
3183            "nvidia/nemotron-nano-9b-v2" => Ok(Self::NvidiaNemotronNano9bV2),
3184            "nvidia/nemotron-nano-9b-v2:free" => Ok(Self::NvidiaNemotronNano9bV2Free),
3185            "openai/gpt-4.1" => Ok(Self::OpenaiGpt41),
3186            "openai/gpt-4.1-mini" => Ok(Self::OpenaiGpt41Mini),
3187            "openai/gpt-4o-mini" => Ok(Self::OpenaiGpt4oMini),
3188            "openai/gpt-5" => Ok(Self::OpenaiGpt5),
3189            "openai/gpt-5-codex" => Ok(Self::OpenaiGpt5Codex),
3190            "openai/gpt-5-image" => Ok(Self::OpenaiGpt5Image),
3191            "openai/gpt-5-mini" => Ok(Self::OpenaiGpt5Mini),
3192            "openai/gpt-5-nano" => Ok(Self::OpenaiGpt5Nano),
3193            "openai/gpt-5-pro" => Ok(Self::OpenaiGpt5Pro),
3194            "openai/gpt-5.1" => Ok(Self::OpenaiGpt51),
3195            "openai/gpt-5.1-chat" => Ok(Self::OpenaiGpt51Chat),
3196            "openai/gpt-5.1-codex" => Ok(Self::OpenaiGpt51Codex),
3197            "openai/gpt-5.1-codex-max" => Ok(Self::OpenaiGpt51CodexMax),
3198            "openai/gpt-5.1-codex-mini" => Ok(Self::OpenaiGpt51CodexMini),
3199            "openai/gpt-5.2" => Ok(Self::OpenaiGpt52),
3200            "openai/gpt-5.2-chat" => Ok(Self::OpenaiGpt52Chat),
3201            "openai/gpt-5.2-codex" => Ok(Self::OpenaiGpt52Codex),
3202            "openai/gpt-5.2-pro" => Ok(Self::OpenaiGpt52Pro),
3203            "openai/gpt-5.3-codex" => Ok(Self::OpenaiGpt53Codex),
3204            "openai/gpt-5.4" => Ok(Self::OpenaiGpt54),
3205            "openai/gpt-5.4-mini" => Ok(Self::OpenaiGpt54Mini),
3206            "openai/gpt-5.4-nano" => Ok(Self::OpenaiGpt54Nano),
3207            "openai/gpt-5.4-pro" => Ok(Self::OpenaiGpt54Pro),
3208            "openai/gpt-5.5" => Ok(Self::OpenaiGpt55),
3209            "openai/gpt-5.5-pro" => Ok(Self::OpenaiGpt55Pro),
3210            "openai/gpt-oss-120b" => Ok(Self::OpenaiGptOss120b),
3211            "openai/gpt-oss-120b:exacto" => Ok(Self::OpenaiGptOss120bExacto),
3212            "openai/gpt-oss-120b:free" => Ok(Self::OpenaiGptOss120bFree),
3213            "openai/gpt-oss-20b" => Ok(Self::OpenaiGptOss20b),
3214            "openai/gpt-oss-20b:free" => Ok(Self::OpenaiGptOss20bFree),
3215            "openai/gpt-oss-safeguard-20b" => Ok(Self::OpenaiGptOssSafeguard20b),
3216            "openai/o4-mini" => Ok(Self::OpenaiO4Mini),
3217            "openrouter/elephant-alpha" => Ok(Self::OpenrouterElephantAlpha),
3218            "openrouter/free" => Ok(Self::OpenrouterFree),
3219            "openrouter/owl-alpha" => Ok(Self::OpenrouterOwlAlpha),
3220            "openrouter/pareto-code" => Ok(Self::OpenrouterParetoCode),
3221            "poolside/laguna-m.1:free" => Ok(Self::PoolsideLagunaM1Free),
3222            "poolside/laguna-xs.2:free" => Ok(Self::PoolsideLagunaXs2Free),
3223            "prime-intellect/intellect-3" => Ok(Self::PrimeIntellectIntellect3),
3224            "qwen/qwen-3.6-27b" => Ok(Self::QwenQwen3627b),
3225            "qwen/qwen-plus" => Ok(Self::QwenQwenPlus),
3226            "qwen/qwen3-235b-a22b-07-25" => Ok(Self::QwenQwen3235bA22b0725),
3227            "qwen/qwen3-235b-a22b-thinking-2507" => {
3228                Ok(Self::QwenQwen3235bA22bThinking2507)
3229            }
3230            "qwen/qwen3-30b-a3b-instruct-2507" => Ok(Self::QwenQwen330bA3bInstruct2507),
3231            "qwen/qwen3-30b-a3b-thinking-2507" => Ok(Self::QwenQwen330bA3bThinking2507),
3232            "qwen/qwen3-coder" => Ok(Self::QwenQwen3Coder),
3233            "qwen/qwen3-coder-30b-a3b-instruct" => Ok(Self::QwenQwen3Coder30bA3bInstruct),
3234            "qwen/qwen3-coder-flash" => Ok(Self::QwenQwen3CoderFlash),
3235            "qwen/qwen3-coder-plus" => Ok(Self::QwenQwen3CoderPlus),
3236            "qwen/qwen3-coder:exacto" => Ok(Self::QwenQwen3CoderExacto),
3237            "qwen/qwen3-max" => Ok(Self::QwenQwen3Max),
3238            "qwen/qwen3-next-80b-a3b-instruct" => Ok(Self::QwenQwen3Next80bA3bInstruct),
3239            "qwen/qwen3-next-80b-a3b-thinking" => Ok(Self::QwenQwen3Next80bA3bThinking),
3240            "qwen/qwen3.5-397b-a17b" => Ok(Self::QwenQwen35397bA17b),
3241            "qwen/qwen3.5-flash-02-23" => Ok(Self::QwenQwen35Flash0223),
3242            "qwen/qwen3.5-plus-02-15" => Ok(Self::QwenQwen35Plus0215),
3243            "qwen/qwen3.6-plus" => Ok(Self::QwenQwen36Plus),
3244            "stepfun/step-3.5-flash" => Ok(Self::StepfunStep35Flash),
3245            "tencent/hy3-preview" => Ok(Self::TencentHy3Preview),
3246            "x-ai/grok-3" => Ok(Self::XAiGrok3),
3247            "x-ai/grok-3-beta" => Ok(Self::XAiGrok3Beta),
3248            "x-ai/grok-3-mini" => Ok(Self::XAiGrok3Mini),
3249            "x-ai/grok-3-mini-beta" => Ok(Self::XAiGrok3MiniBeta),
3250            "x-ai/grok-4" => Ok(Self::XAiGrok4),
3251            "x-ai/grok-4-fast" => Ok(Self::XAiGrok4Fast),
3252            "x-ai/grok-4.1-fast" => Ok(Self::XAiGrok41Fast),
3253            "x-ai/grok-4.20-beta" => Ok(Self::XAiGrok420Beta),
3254            "x-ai/grok-4.3" => Ok(Self::XAiGrok43),
3255            "x-ai/grok-code-fast-1" => Ok(Self::XAiGrokCodeFast1),
3256            "xiaomi/mimo-v2-flash" => Ok(Self::XiaomiMimoV2Flash),
3257            "xiaomi/mimo-v2-omni" => Ok(Self::XiaomiMimoV2Omni),
3258            "xiaomi/mimo-v2-pro" => Ok(Self::XiaomiMimoV2Pro),
3259            "xiaomi/mimo-v2.5" => Ok(Self::XiaomiMimoV25),
3260            "xiaomi/mimo-v2.5-pro" => Ok(Self::XiaomiMimoV25Pro),
3261            "z-ai/glm-4.5" => Ok(Self::ZAiGlm45),
3262            "z-ai/glm-4.5-air" => Ok(Self::ZAiGlm45Air),
3263            "z-ai/glm-4.5v" => Ok(Self::ZAiGlm45v),
3264            "z-ai/glm-4.6" => Ok(Self::ZAiGlm46),
3265            "z-ai/glm-4.6:exacto" => Ok(Self::ZAiGlm46Exacto),
3266            "z-ai/glm-4.7" => Ok(Self::ZAiGlm47),
3267            "z-ai/glm-4.7-flash" => Ok(Self::ZAiGlm47Flash),
3268            "z-ai/glm-5" => Ok(Self::ZAiGlm5),
3269            "z-ai/glm-5-turbo" => Ok(Self::ZAiGlm5Turbo),
3270            "z-ai/glm-5.1" => Ok(Self::ZAiGlm51),
3271            _ => Err(format!("Unknown openrouter model: '{s}'")),
3272        }
3273    }
3274}
3275impl ZAiModel {
3276    #[allow(clippy::too_many_lines)]
3277    fn model_id(self) -> &'static str {
3278        match self {
3279            Self::Glm45 => "glm-4.5",
3280            Self::Glm45Air => "glm-4.5-air",
3281            Self::Glm45Flash => "glm-4.5-flash",
3282            Self::Glm45v => "glm-4.5v",
3283            Self::Glm46 => "glm-4.6",
3284            Self::Glm46v => "glm-4.6v",
3285            Self::Glm47 => "glm-4.7",
3286            Self::Glm47Flash => "glm-4.7-flash",
3287            Self::Glm47Flashx => "glm-4.7-flashx",
3288            Self::Glm5 => "glm-5",
3289            Self::Glm5Turbo => "glm-5-turbo",
3290            Self::Glm51 => "glm-5.1",
3291            Self::Glm5vTurbo => "glm-5v-turbo",
3292        }
3293    }
3294    #[allow(clippy::too_many_lines)]
3295    fn display_name(self) -> &'static str {
3296        match self {
3297            Self::Glm45 => "GLM-4.5",
3298            Self::Glm45Air => "GLM-4.5-Air",
3299            Self::Glm45Flash => "GLM-4.5-Flash",
3300            Self::Glm45v => "GLM-4.5V",
3301            Self::Glm46 => "GLM-4.6",
3302            Self::Glm46v => "GLM-4.6V",
3303            Self::Glm47 => "GLM-4.7",
3304            Self::Glm47Flash => "GLM-4.7-Flash",
3305            Self::Glm47Flashx => "GLM-4.7-FlashX",
3306            Self::Glm5 => "GLM-5",
3307            Self::Glm5Turbo => "GLM-5-Turbo",
3308            Self::Glm51 => "GLM-5.1",
3309            Self::Glm5vTurbo => "GLM-5V-Turbo",
3310        }
3311    }
3312    #[allow(clippy::too_many_lines)]
3313    fn context_window(self) -> u32 {
3314        match self {
3315            Self::Glm45v => 64_000,
3316            Self::Glm46v => 128_000,
3317            Self::Glm45 | Self::Glm45Air | Self::Glm45Flash => 131_072,
3318            Self::Glm47Flash
3319            | Self::Glm47Flashx
3320            | Self::Glm5Turbo
3321            | Self::Glm51
3322            | Self::Glm5vTurbo => 200_000,
3323            Self::Glm46 | Self::Glm47 | Self::Glm5 => 204_800,
3324        }
3325    }
3326    #[allow(clippy::too_many_lines)]
3327    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
3328        match self {
3329            Self::Glm45
3330            | Self::Glm45Air
3331            | Self::Glm45Flash
3332            | Self::Glm45v
3333            | Self::Glm46
3334            | Self::Glm46v
3335            | Self::Glm47
3336            | Self::Glm47Flash
3337            | Self::Glm47Flashx
3338            | Self::Glm5
3339            | Self::Glm5Turbo
3340            | Self::Glm51
3341            | Self::Glm5vTurbo => {
3342                &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High]
3343            }
3344        }
3345    }
3346    pub fn supports_reasoning(self) -> bool {
3347        !self.reasoning_levels().is_empty()
3348    }
3349    #[allow(clippy::too_many_lines)]
3350    pub fn supports_prompt_caching(self) -> bool {
3351        match self {
3352            Self::Glm45v | Self::Glm46v => false,
3353            Self::Glm45
3354            | Self::Glm45Air
3355            | Self::Glm45Flash
3356            | Self::Glm46
3357            | Self::Glm47
3358            | Self::Glm47Flash
3359            | Self::Glm47Flashx
3360            | Self::Glm5
3361            | Self::Glm5Turbo
3362            | Self::Glm51
3363            | Self::Glm5vTurbo => true,
3364        }
3365    }
3366    #[allow(clippy::too_many_lines)]
3367    pub fn supports_image(self) -> bool {
3368        match self {
3369            Self::Glm45
3370            | Self::Glm45Air
3371            | Self::Glm45Flash
3372            | Self::Glm46
3373            | Self::Glm47
3374            | Self::Glm47Flash
3375            | Self::Glm47Flashx
3376            | Self::Glm5
3377            | Self::Glm5Turbo
3378            | Self::Glm51 => false,
3379            Self::Glm45v | Self::Glm46v | Self::Glm5vTurbo => true,
3380        }
3381    }
3382    #[allow(clippy::too_many_lines)]
3383    pub fn supports_audio(self) -> bool {
3384        match self {
3385            Self::Glm45
3386            | Self::Glm45Air
3387            | Self::Glm45Flash
3388            | Self::Glm45v
3389            | Self::Glm46
3390            | Self::Glm46v
3391            | Self::Glm47
3392            | Self::Glm47Flash
3393            | Self::Glm47Flashx
3394            | Self::Glm5
3395            | Self::Glm5Turbo
3396            | Self::Glm51
3397            | Self::Glm5vTurbo => false,
3398        }
3399    }
3400    const ALL: &[ZAiModel] = &[
3401        Self::Glm45,
3402        Self::Glm45Air,
3403        Self::Glm45Flash,
3404        Self::Glm45v,
3405        Self::Glm46,
3406        Self::Glm46v,
3407        Self::Glm47,
3408        Self::Glm47Flash,
3409        Self::Glm47Flashx,
3410        Self::Glm5,
3411        Self::Glm5Turbo,
3412        Self::Glm51,
3413        Self::Glm5vTurbo,
3414    ];
3415}
3416impl std::str::FromStr for ZAiModel {
3417    type Err = String;
3418    #[allow(clippy::too_many_lines)]
3419    fn from_str(s: &str) -> Result<Self, Self::Err> {
3420        match s {
3421            "glm-4.5" => Ok(Self::Glm45),
3422            "glm-4.5-air" => Ok(Self::Glm45Air),
3423            "glm-4.5-flash" => Ok(Self::Glm45Flash),
3424            "glm-4.5v" => Ok(Self::Glm45v),
3425            "glm-4.6" => Ok(Self::Glm46),
3426            "glm-4.6v" => Ok(Self::Glm46v),
3427            "glm-4.7" => Ok(Self::Glm47),
3428            "glm-4.7-flash" => Ok(Self::Glm47Flash),
3429            "glm-4.7-flashx" => Ok(Self::Glm47Flashx),
3430            "glm-5" => Ok(Self::Glm5),
3431            "glm-5-turbo" => Ok(Self::Glm5Turbo),
3432            "glm-5.1" => Ok(Self::Glm51),
3433            "glm-5v-turbo" => Ok(Self::Glm5vTurbo),
3434            _ => Err(format!("Unknown zai model: '{s}'")),
3435        }
3436    }
3437}
3438impl BedrockFoundationModel {
3439    #[allow(clippy::too_many_lines)]
3440    fn model_id(self) -> &'static str {
3441        match self {
3442            Self::AmazonNova2LiteV10 => "amazon.nova-2-lite-v1:0",
3443            Self::AmazonNovaLiteV10 => "amazon.nova-lite-v1:0",
3444            Self::AmazonNovaMicroV10 => "amazon.nova-micro-v1:0",
3445            Self::AmazonNovaProV10 => "amazon.nova-pro-v1:0",
3446            Self::AnthropicClaudeHaiku4520251001V10 => {
3447                "anthropic.claude-haiku-4-5-20251001-v1:0"
3448            }
3449            Self::AnthropicClaudeOpus4120250805V10 => {
3450                "anthropic.claude-opus-4-1-20250805-v1:0"
3451            }
3452            Self::AnthropicClaudeOpus4520251101V10 => {
3453                "anthropic.claude-opus-4-5-20251101-v1:0"
3454            }
3455            Self::AnthropicClaudeOpus46V1 => "anthropic.claude-opus-4-6-v1",
3456            Self::AnthropicClaudeOpus47 => "anthropic.claude-opus-4-7",
3457            Self::AnthropicClaudeSonnet4520250929V10 => {
3458                "anthropic.claude-sonnet-4-5-20250929-v1:0"
3459            }
3460            Self::AnthropicClaudeSonnet46 => "anthropic.claude-sonnet-4-6",
3461            Self::AuAnthropicClaudeHaiku4520251001V10 => {
3462                "au.anthropic.claude-haiku-4-5-20251001-v1:0"
3463            }
3464            Self::AuAnthropicClaudeOpus46V1 => "au.anthropic.claude-opus-4-6-v1",
3465            Self::AuAnthropicClaudeSonnet4520250929V10 => {
3466                "au.anthropic.claude-sonnet-4-5-20250929-v1:0"
3467            }
3468            Self::AuAnthropicClaudeSonnet46 => "au.anthropic.claude-sonnet-4-6",
3469            Self::DeepseekR1V10 => "deepseek.r1-v1:0",
3470            Self::DeepseekV3V10 => "deepseek.v3-v1:0",
3471            Self::DeepseekV32 => "deepseek.v3.2",
3472            Self::EuAnthropicClaudeHaiku4520251001V10 => {
3473                "eu.anthropic.claude-haiku-4-5-20251001-v1:0"
3474            }
3475            Self::EuAnthropicClaudeOpus4520251101V10 => {
3476                "eu.anthropic.claude-opus-4-5-20251101-v1:0"
3477            }
3478            Self::EuAnthropicClaudeOpus46V1 => "eu.anthropic.claude-opus-4-6-v1",
3479            Self::EuAnthropicClaudeOpus47 => "eu.anthropic.claude-opus-4-7",
3480            Self::EuAnthropicClaudeSonnet4520250929V10 => {
3481                "eu.anthropic.claude-sonnet-4-5-20250929-v1:0"
3482            }
3483            Self::EuAnthropicClaudeSonnet46 => "eu.anthropic.claude-sonnet-4-6",
3484            Self::GlobalAnthropicClaudeHaiku4520251001V10 => {
3485                "global.anthropic.claude-haiku-4-5-20251001-v1:0"
3486            }
3487            Self::GlobalAnthropicClaudeOpus4520251101V10 => {
3488                "global.anthropic.claude-opus-4-5-20251101-v1:0"
3489            }
3490            Self::GlobalAnthropicClaudeOpus46V1 => "global.anthropic.claude-opus-4-6-v1",
3491            Self::GlobalAnthropicClaudeOpus47 => "global.anthropic.claude-opus-4-7",
3492            Self::GlobalAnthropicClaudeSonnet4520250929V10 => {
3493                "global.anthropic.claude-sonnet-4-5-20250929-v1:0"
3494            }
3495            Self::GlobalAnthropicClaudeSonnet46 => "global.anthropic.claude-sonnet-4-6",
3496            Self::GoogleGemma327bIt => "google.gemma-3-27b-it",
3497            Self::GoogleGemma34bIt => "google.gemma-3-4b-it",
3498            Self::JpAnthropicClaudeOpus47 => "jp.anthropic.claude-opus-4-7",
3499            Self::JpAnthropicClaudeSonnet4520250929V10 => {
3500                "jp.anthropic.claude-sonnet-4-5-20250929-v1:0"
3501            }
3502            Self::JpAnthropicClaudeSonnet46 => "jp.anthropic.claude-sonnet-4-6",
3503            Self::MetaLlama3170bInstructV10 => "meta.llama3-1-70b-instruct-v1:0",
3504            Self::MetaLlama318bInstructV10 => "meta.llama3-1-8b-instruct-v1:0",
3505            Self::MetaLlama3370bInstructV10 => "meta.llama3-3-70b-instruct-v1:0",
3506            Self::MetaLlama4Maverick17bInstructV10 => {
3507                "meta.llama4-maverick-17b-instruct-v1:0"
3508            }
3509            Self::MetaLlama4Scout17bInstructV10 => "meta.llama4-scout-17b-instruct-v1:0",
3510            Self::MinimaxMinimaxM2 => "minimax.minimax-m2",
3511            Self::MinimaxMinimaxM21 => "minimax.minimax-m2.1",
3512            Self::MinimaxMinimaxM25 => "minimax.minimax-m2.5",
3513            Self::MistralDevstral2123b => "mistral.devstral-2-123b",
3514            Self::MistralMagistralSmall2509 => "mistral.magistral-small-2509",
3515            Self::MistralMinistral314bInstruct => "mistral.ministral-3-14b-instruct",
3516            Self::MistralMinistral33bInstruct => "mistral.ministral-3-3b-instruct",
3517            Self::MistralMinistral38bInstruct => "mistral.ministral-3-8b-instruct",
3518            Self::MistralMistralLarge3675bInstruct => {
3519                "mistral.mistral-large-3-675b-instruct"
3520            }
3521            Self::MistralPixtralLarge2502V10 => "mistral.pixtral-large-2502-v1:0",
3522            Self::MistralVoxtralMini3b2507 => "mistral.voxtral-mini-3b-2507",
3523            Self::MistralVoxtralSmall24b2507 => "mistral.voxtral-small-24b-2507",
3524            Self::MoonshotKimiK2Thinking => "moonshot.kimi-k2-thinking",
3525            Self::MoonshotaiKimiK25 => "moonshotai.kimi-k2.5",
3526            Self::NvidiaNemotronNano12bV2 => "nvidia.nemotron-nano-12b-v2",
3527            Self::NvidiaNemotronNano330b => "nvidia.nemotron-nano-3-30b",
3528            Self::NvidiaNemotronNano9bV2 => "nvidia.nemotron-nano-9b-v2",
3529            Self::NvidiaNemotronSuper3120b => "nvidia.nemotron-super-3-120b",
3530            Self::OpenaiGptOss120b10 => "openai.gpt-oss-120b-1:0",
3531            Self::OpenaiGptOss20b10 => "openai.gpt-oss-20b-1:0",
3532            Self::OpenaiGptOssSafeguard120b => "openai.gpt-oss-safeguard-120b",
3533            Self::OpenaiGptOssSafeguard20b => "openai.gpt-oss-safeguard-20b",
3534            Self::QwenQwen3235bA22b2507V10 => "qwen.qwen3-235b-a22b-2507-v1:0",
3535            Self::QwenQwen332bV10 => "qwen.qwen3-32b-v1:0",
3536            Self::QwenQwen3Coder30bA3bV10 => "qwen.qwen3-coder-30b-a3b-v1:0",
3537            Self::QwenQwen3Coder480bA35bV10 => "qwen.qwen3-coder-480b-a35b-v1:0",
3538            Self::QwenQwen3CoderNext => "qwen.qwen3-coder-next",
3539            Self::QwenQwen3Next80bA3b => "qwen.qwen3-next-80b-a3b",
3540            Self::QwenQwen3Vl235bA22b => "qwen.qwen3-vl-235b-a22b",
3541            Self::UsAnthropicClaudeHaiku4520251001V10 => {
3542                "us.anthropic.claude-haiku-4-5-20251001-v1:0"
3543            }
3544            Self::UsAnthropicClaudeOpus4120250805V10 => {
3545                "us.anthropic.claude-opus-4-1-20250805-v1:0"
3546            }
3547            Self::UsAnthropicClaudeOpus4520251101V10 => {
3548                "us.anthropic.claude-opus-4-5-20251101-v1:0"
3549            }
3550            Self::UsAnthropicClaudeOpus46V1 => "us.anthropic.claude-opus-4-6-v1",
3551            Self::UsAnthropicClaudeOpus47 => "us.anthropic.claude-opus-4-7",
3552            Self::UsAnthropicClaudeSonnet4520250929V10 => {
3553                "us.anthropic.claude-sonnet-4-5-20250929-v1:0"
3554            }
3555            Self::UsAnthropicClaudeSonnet46 => "us.anthropic.claude-sonnet-4-6",
3556            Self::UsDeepseekR1V10 => "us.deepseek.r1-v1:0",
3557            Self::UsMetaLlama4Maverick17bInstructV10 => {
3558                "us.meta.llama4-maverick-17b-instruct-v1:0"
3559            }
3560            Self::UsMetaLlama4Scout17bInstructV10 => {
3561                "us.meta.llama4-scout-17b-instruct-v1:0"
3562            }
3563            Self::WriterPalmyraX4V10 => "writer.palmyra-x4-v1:0",
3564            Self::WriterPalmyraX5V10 => "writer.palmyra-x5-v1:0",
3565            Self::ZaiGlm47 => "zai.glm-4.7",
3566            Self::ZaiGlm47Flash => "zai.glm-4.7-flash",
3567            Self::ZaiGlm5 => "zai.glm-5",
3568        }
3569    }
3570    #[allow(clippy::too_many_lines)]
3571    fn display_name(self) -> &'static str {
3572        match self {
3573            Self::AuAnthropicClaudeOpus46V1 => "AU Anthropic Claude Opus 4.6",
3574            Self::AuAnthropicClaudeSonnet46 => "AU Anthropic Claude Sonnet 4.6",
3575            Self::AnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5",
3576            Self::AuAnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5 (AU)",
3577            Self::EuAnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5 (EU)",
3578            Self::GlobalAnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5 (Global)",
3579            Self::UsAnthropicClaudeHaiku4520251001V10 => "Claude Haiku 4.5 (US)",
3580            Self::AnthropicClaudeOpus4120250805V10 => "Claude Opus 4.1",
3581            Self::UsAnthropicClaudeOpus4120250805V10 => "Claude Opus 4.1 (US)",
3582            Self::AnthropicClaudeOpus4520251101V10 => "Claude Opus 4.5",
3583            Self::EuAnthropicClaudeOpus4520251101V10 => "Claude Opus 4.5 (EU)",
3584            Self::GlobalAnthropicClaudeOpus4520251101V10 => "Claude Opus 4.5 (Global)",
3585            Self::UsAnthropicClaudeOpus4520251101V10 => "Claude Opus 4.5 (US)",
3586            Self::AnthropicClaudeOpus46V1 => "Claude Opus 4.6",
3587            Self::EuAnthropicClaudeOpus46V1 => "Claude Opus 4.6 (EU)",
3588            Self::GlobalAnthropicClaudeOpus46V1 => "Claude Opus 4.6 (Global)",
3589            Self::UsAnthropicClaudeOpus46V1 => "Claude Opus 4.6 (US)",
3590            Self::AnthropicClaudeOpus47 => "Claude Opus 4.7",
3591            Self::EuAnthropicClaudeOpus47 => "Claude Opus 4.7 (EU)",
3592            Self::GlobalAnthropicClaudeOpus47 => "Claude Opus 4.7 (Global)",
3593            Self::JpAnthropicClaudeOpus47 => "Claude Opus 4.7 (JP)",
3594            Self::UsAnthropicClaudeOpus47 => "Claude Opus 4.7 (US)",
3595            Self::AnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5",
3596            Self::AuAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (AU)",
3597            Self::EuAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (EU)",
3598            Self::GlobalAnthropicClaudeSonnet4520250929V10 => {
3599                "Claude Sonnet 4.5 (Global)"
3600            }
3601            Self::JpAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (JP)",
3602            Self::UsAnthropicClaudeSonnet4520250929V10 => "Claude Sonnet 4.5 (US)",
3603            Self::AnthropicClaudeSonnet46 => "Claude Sonnet 4.6",
3604            Self::EuAnthropicClaudeSonnet46 => "Claude Sonnet 4.6 (EU)",
3605            Self::GlobalAnthropicClaudeSonnet46 => "Claude Sonnet 4.6 (Global)",
3606            Self::JpAnthropicClaudeSonnet46 => "Claude Sonnet 4.6 (JP)",
3607            Self::UsAnthropicClaudeSonnet46 => "Claude Sonnet 4.6 (US)",
3608            Self::DeepseekR1V10 => "DeepSeek-R1",
3609            Self::UsDeepseekR1V10 => "DeepSeek-R1 (US)",
3610            Self::DeepseekV3V10 => "DeepSeek-V3.1",
3611            Self::DeepseekV32 => "DeepSeek-V3.2",
3612            Self::MistralDevstral2123b => "Devstral 2 123B",
3613            Self::ZaiGlm47 => "GLM-4.7",
3614            Self::ZaiGlm47Flash => "GLM-4.7-Flash",
3615            Self::ZaiGlm5 => "GLM-5",
3616            Self::OpenaiGptOssSafeguard120b => "GPT OSS Safeguard 120B",
3617            Self::OpenaiGptOssSafeguard20b => "GPT OSS Safeguard 20B",
3618            Self::GoogleGemma34bIt => "Gemma 3 4B IT",
3619            Self::GoogleGemma327bIt => "Google Gemma 3 27B Instruct",
3620            Self::MoonshotKimiK2Thinking => "Kimi K2 Thinking",
3621            Self::MoonshotaiKimiK25 => "Kimi K2.5",
3622            Self::MetaLlama3170bInstructV10 => "Llama 3.1 70B Instruct",
3623            Self::MetaLlama318bInstructV10 => "Llama 3.1 8B Instruct",
3624            Self::MetaLlama3370bInstructV10 => "Llama 3.3 70B Instruct",
3625            Self::MetaLlama4Maverick17bInstructV10 => "Llama 4 Maverick 17B Instruct",
3626            Self::UsMetaLlama4Maverick17bInstructV10 => {
3627                "Llama 4 Maverick 17B Instruct (US)"
3628            }
3629            Self::MetaLlama4Scout17bInstructV10 => "Llama 4 Scout 17B Instruct",
3630            Self::UsMetaLlama4Scout17bInstructV10 => "Llama 4 Scout 17B Instruct (US)",
3631            Self::MistralMagistralSmall2509 => "Magistral Small 1.2",
3632            Self::MinimaxMinimaxM2 => "MiniMax M2",
3633            Self::MinimaxMinimaxM21 => "MiniMax M2.1",
3634            Self::MinimaxMinimaxM25 => "MiniMax M2.5",
3635            Self::MistralMinistral314bInstruct => "Ministral 14B 3.0",
3636            Self::MistralMinistral33bInstruct => "Ministral 3 3B",
3637            Self::MistralMinistral38bInstruct => "Ministral 3 8B",
3638            Self::MistralMistralLarge3675bInstruct => "Mistral Large 3",
3639            Self::NvidiaNemotronSuper3120b => "NVIDIA Nemotron 3 Super 120B A12B",
3640            Self::NvidiaNemotronNano12bV2 => "NVIDIA Nemotron Nano 12B v2 VL BF16",
3641            Self::NvidiaNemotronNano330b => "NVIDIA Nemotron Nano 3 30B",
3642            Self::NvidiaNemotronNano9bV2 => "NVIDIA Nemotron Nano 9B v2",
3643            Self::AmazonNova2LiteV10 => "Nova 2 Lite",
3644            Self::AmazonNovaLiteV10 => "Nova Lite",
3645            Self::AmazonNovaMicroV10 => "Nova Micro",
3646            Self::AmazonNovaProV10 => "Nova Pro",
3647            Self::WriterPalmyraX4V10 => "Palmyra X4",
3648            Self::WriterPalmyraX5V10 => "Palmyra X5",
3649            Self::MistralPixtralLarge2502V10 => "Pixtral Large (25.02)",
3650            Self::QwenQwen3Next80bA3b => "Qwen/Qwen3-Next-80B-A3B-Instruct",
3651            Self::QwenQwen3Vl235bA22b => "Qwen/Qwen3-VL-235B-A22B-Instruct",
3652            Self::QwenQwen3235bA22b2507V10 => "Qwen3 235B A22B 2507",
3653            Self::QwenQwen332bV10 => "Qwen3 32B (dense)",
3654            Self::QwenQwen3Coder30bA3bV10 => "Qwen3 Coder 30B A3B Instruct",
3655            Self::QwenQwen3Coder480bA35bV10 => "Qwen3 Coder 480B A35B Instruct",
3656            Self::QwenQwen3CoderNext => "Qwen3 Coder Next",
3657            Self::MistralVoxtralMini3b2507 => "Voxtral Mini 3B 2507",
3658            Self::MistralVoxtralSmall24b2507 => "Voxtral Small 24B 2507",
3659            Self::OpenaiGptOss120b10 => "gpt-oss-120b",
3660            Self::OpenaiGptOss20b10 => "gpt-oss-20b",
3661        }
3662    }
3663    #[allow(clippy::too_many_lines)]
3664    fn context_window(self) -> u32 {
3665        match self {
3666            Self::QwenQwen332bV10 => 16_384,
3667            Self::MistralVoxtralSmall24b2507 => 32_000,
3668            Self::WriterPalmyraX4V10 => 122_880,
3669            Self::AmazonNova2LiteV10
3670            | Self::AmazonNovaMicroV10
3671            | Self::DeepseekR1V10
3672            | Self::GoogleGemma34bIt
3673            | Self::MetaLlama3170bInstructV10
3674            | Self::MetaLlama318bInstructV10
3675            | Self::MetaLlama3370bInstructV10
3676            | Self::MistralMagistralSmall2509
3677            | Self::MistralMinistral314bInstruct
3678            | Self::MistralMinistral38bInstruct
3679            | Self::MistralPixtralLarge2502V10
3680            | Self::MistralVoxtralMini3b2507
3681            | Self::NvidiaNemotronNano12bV2
3682            | Self::NvidiaNemotronNano330b
3683            | Self::NvidiaNemotronNano9bV2
3684            | Self::OpenaiGptOss120b10
3685            | Self::OpenaiGptOss20b10
3686            | Self::OpenaiGptOssSafeguard120b
3687            | Self::OpenaiGptOssSafeguard20b
3688            | Self::UsDeepseekR1V10 => 128_000,
3689            Self::QwenQwen3Coder480bA35bV10 | Self::QwenQwen3CoderNext => 131_072,
3690            Self::DeepseekV3V10 | Self::DeepseekV32 => 163_840,
3691            Self::MinimaxMinimaxM25 => 196_608,
3692            Self::AnthropicClaudeHaiku4520251001V10
3693            | Self::AnthropicClaudeOpus4120250805V10
3694            | Self::AnthropicClaudeOpus4520251101V10
3695            | Self::AnthropicClaudeSonnet4520250929V10
3696            | Self::AuAnthropicClaudeHaiku4520251001V10
3697            | Self::AuAnthropicClaudeSonnet4520250929V10
3698            | Self::EuAnthropicClaudeHaiku4520251001V10
3699            | Self::EuAnthropicClaudeOpus4520251101V10
3700            | Self::EuAnthropicClaudeSonnet4520250929V10
3701            | Self::GlobalAnthropicClaudeHaiku4520251001V10
3702            | Self::GlobalAnthropicClaudeOpus4520251101V10
3703            | Self::GlobalAnthropicClaudeSonnet4520250929V10
3704            | Self::JpAnthropicClaudeSonnet4520250929V10
3705            | Self::UsAnthropicClaudeHaiku4520251001V10
3706            | Self::UsAnthropicClaudeOpus4120250805V10
3707            | Self::UsAnthropicClaudeOpus4520251101V10
3708            | Self::UsAnthropicClaudeSonnet4520250929V10
3709            | Self::ZaiGlm47Flash => 200_000,
3710            Self::GoogleGemma327bIt | Self::ZaiGlm5 => 202_752,
3711            Self::MinimaxMinimaxM2 => 204_608,
3712            Self::MinimaxMinimaxM21 | Self::ZaiGlm47 => 204_800,
3713            Self::MistralDevstral2123b
3714            | Self::MistralMinistral33bInstruct
3715            | Self::MistralMistralLarge3675bInstruct
3716            | Self::MoonshotKimiK2Thinking
3717            | Self::MoonshotaiKimiK25 => 256_000,
3718            Self::QwenQwen3Next80bA3b | Self::QwenQwen3Vl235bA22b => 262_000,
3719            Self::NvidiaNemotronSuper3120b
3720            | Self::QwenQwen3235bA22b2507V10
3721            | Self::QwenQwen3Coder30bA3bV10 => 262_144,
3722            Self::AmazonNovaLiteV10 | Self::AmazonNovaProV10 => 300_000,
3723            Self::AnthropicClaudeOpus46V1
3724            | Self::AnthropicClaudeOpus47
3725            | Self::AnthropicClaudeSonnet46
3726            | Self::AuAnthropicClaudeOpus46V1
3727            | Self::AuAnthropicClaudeSonnet46
3728            | Self::EuAnthropicClaudeOpus46V1
3729            | Self::EuAnthropicClaudeOpus47
3730            | Self::EuAnthropicClaudeSonnet46
3731            | Self::GlobalAnthropicClaudeOpus46V1
3732            | Self::GlobalAnthropicClaudeOpus47
3733            | Self::GlobalAnthropicClaudeSonnet46
3734            | Self::JpAnthropicClaudeOpus47
3735            | Self::JpAnthropicClaudeSonnet46
3736            | Self::MetaLlama4Maverick17bInstructV10
3737            | Self::UsAnthropicClaudeOpus46V1
3738            | Self::UsAnthropicClaudeOpus47
3739            | Self::UsAnthropicClaudeSonnet46
3740            | Self::UsMetaLlama4Maverick17bInstructV10 => 1_000_000,
3741            Self::WriterPalmyraX5V10 => 1_040_000,
3742            Self::MetaLlama4Scout17bInstructV10
3743            | Self::UsMetaLlama4Scout17bInstructV10 => 3_500_000,
3744        }
3745    }
3746    #[allow(clippy::too_many_lines)]
3747    pub fn reasoning_levels(self) -> &'static [ReasoningEffort] {
3748        match self {
3749            Self::AmazonNova2LiteV10
3750            | Self::AmazonNovaLiteV10
3751            | Self::AmazonNovaMicroV10
3752            | Self::AmazonNovaProV10
3753            | Self::GoogleGemma327bIt
3754            | Self::GoogleGemma34bIt
3755            | Self::MetaLlama3170bInstructV10
3756            | Self::MetaLlama318bInstructV10
3757            | Self::MetaLlama3370bInstructV10
3758            | Self::MetaLlama4Maverick17bInstructV10
3759            | Self::MetaLlama4Scout17bInstructV10
3760            | Self::MistralDevstral2123b
3761            | Self::MistralMinistral314bInstruct
3762            | Self::MistralMinistral33bInstruct
3763            | Self::MistralMinistral38bInstruct
3764            | Self::MistralMistralLarge3675bInstruct
3765            | Self::MistralPixtralLarge2502V10
3766            | Self::MistralVoxtralMini3b2507
3767            | Self::MistralVoxtralSmall24b2507
3768            | Self::NvidiaNemotronNano12bV2
3769            | Self::NvidiaNemotronNano9bV2
3770            | Self::OpenaiGptOss120b10
3771            | Self::OpenaiGptOss20b10
3772            | Self::OpenaiGptOssSafeguard120b
3773            | Self::OpenaiGptOssSafeguard20b
3774            | Self::QwenQwen3235bA22b2507V10
3775            | Self::QwenQwen3Coder30bA3bV10
3776            | Self::QwenQwen3Coder480bA35bV10
3777            | Self::QwenQwen3Next80bA3b
3778            | Self::QwenQwen3Vl235bA22b
3779            | Self::UsMetaLlama4Maverick17bInstructV10
3780            | Self::UsMetaLlama4Scout17bInstructV10 => &[],
3781            Self::AnthropicClaudeHaiku4520251001V10
3782            | Self::AnthropicClaudeOpus4120250805V10
3783            | Self::AnthropicClaudeOpus4520251101V10
3784            | Self::AnthropicClaudeOpus46V1
3785            | Self::AnthropicClaudeOpus47
3786            | Self::AnthropicClaudeSonnet4520250929V10
3787            | Self::AnthropicClaudeSonnet46
3788            | Self::AuAnthropicClaudeHaiku4520251001V10
3789            | Self::AuAnthropicClaudeOpus46V1
3790            | Self::AuAnthropicClaudeSonnet4520250929V10
3791            | Self::AuAnthropicClaudeSonnet46
3792            | Self::DeepseekR1V10
3793            | Self::DeepseekV3V10
3794            | Self::DeepseekV32
3795            | Self::EuAnthropicClaudeHaiku4520251001V10
3796            | Self::EuAnthropicClaudeOpus4520251101V10
3797            | Self::EuAnthropicClaudeOpus46V1
3798            | Self::EuAnthropicClaudeOpus47
3799            | Self::EuAnthropicClaudeSonnet4520250929V10
3800            | Self::EuAnthropicClaudeSonnet46
3801            | Self::GlobalAnthropicClaudeHaiku4520251001V10
3802            | Self::GlobalAnthropicClaudeOpus4520251101V10
3803            | Self::GlobalAnthropicClaudeOpus46V1
3804            | Self::GlobalAnthropicClaudeOpus47
3805            | Self::GlobalAnthropicClaudeSonnet4520250929V10
3806            | Self::GlobalAnthropicClaudeSonnet46
3807            | Self::JpAnthropicClaudeOpus47
3808            | Self::JpAnthropicClaudeSonnet4520250929V10
3809            | Self::JpAnthropicClaudeSonnet46
3810            | Self::MinimaxMinimaxM2
3811            | Self::MinimaxMinimaxM21
3812            | Self::MinimaxMinimaxM25
3813            | Self::MistralMagistralSmall2509
3814            | Self::MoonshotKimiK2Thinking
3815            | Self::MoonshotaiKimiK25
3816            | Self::NvidiaNemotronNano330b
3817            | Self::NvidiaNemotronSuper3120b
3818            | Self::QwenQwen332bV10
3819            | Self::QwenQwen3CoderNext
3820            | Self::UsAnthropicClaudeHaiku4520251001V10
3821            | Self::UsAnthropicClaudeOpus4120250805V10
3822            | Self::UsAnthropicClaudeOpus4520251101V10
3823            | Self::UsAnthropicClaudeOpus46V1
3824            | Self::UsAnthropicClaudeOpus47
3825            | Self::UsAnthropicClaudeSonnet4520250929V10
3826            | Self::UsAnthropicClaudeSonnet46
3827            | Self::UsDeepseekR1V10
3828            | Self::WriterPalmyraX4V10
3829            | Self::WriterPalmyraX5V10
3830            | Self::ZaiGlm47
3831            | Self::ZaiGlm47Flash
3832            | Self::ZaiGlm5 => {
3833                &[ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High]
3834            }
3835        }
3836    }
3837    pub fn supports_reasoning(self) -> bool {
3838        !self.reasoning_levels().is_empty()
3839    }
3840    #[allow(clippy::too_many_lines)]
3841    pub fn supports_prompt_caching(self) -> bool {
3842        match self {
3843            Self::AmazonNova2LiteV10
3844            | Self::DeepseekR1V10
3845            | Self::DeepseekV3V10
3846            | Self::DeepseekV32
3847            | Self::GoogleGemma327bIt
3848            | Self::GoogleGemma34bIt
3849            | Self::MetaLlama3170bInstructV10
3850            | Self::MetaLlama318bInstructV10
3851            | Self::MetaLlama3370bInstructV10
3852            | Self::MetaLlama4Maverick17bInstructV10
3853            | Self::MetaLlama4Scout17bInstructV10
3854            | Self::MinimaxMinimaxM2
3855            | Self::MinimaxMinimaxM21
3856            | Self::MinimaxMinimaxM25
3857            | Self::MistralDevstral2123b
3858            | Self::MistralMagistralSmall2509
3859            | Self::MistralMinistral314bInstruct
3860            | Self::MistralMinistral33bInstruct
3861            | Self::MistralMinistral38bInstruct
3862            | Self::MistralMistralLarge3675bInstruct
3863            | Self::MistralPixtralLarge2502V10
3864            | Self::MistralVoxtralMini3b2507
3865            | Self::MistralVoxtralSmall24b2507
3866            | Self::MoonshotKimiK2Thinking
3867            | Self::MoonshotaiKimiK25
3868            | Self::NvidiaNemotronNano12bV2
3869            | Self::NvidiaNemotronNano330b
3870            | Self::NvidiaNemotronNano9bV2
3871            | Self::NvidiaNemotronSuper3120b
3872            | Self::OpenaiGptOss120b10
3873            | Self::OpenaiGptOss20b10
3874            | Self::OpenaiGptOssSafeguard120b
3875            | Self::OpenaiGptOssSafeguard20b
3876            | Self::QwenQwen3235bA22b2507V10
3877            | Self::QwenQwen332bV10
3878            | Self::QwenQwen3Coder30bA3bV10
3879            | Self::QwenQwen3Coder480bA35bV10
3880            | Self::QwenQwen3CoderNext
3881            | Self::QwenQwen3Next80bA3b
3882            | Self::QwenQwen3Vl235bA22b
3883            | Self::UsDeepseekR1V10
3884            | Self::UsMetaLlama4Maverick17bInstructV10
3885            | Self::UsMetaLlama4Scout17bInstructV10
3886            | Self::WriterPalmyraX4V10
3887            | Self::WriterPalmyraX5V10
3888            | Self::ZaiGlm47
3889            | Self::ZaiGlm47Flash
3890            | Self::ZaiGlm5 => false,
3891            Self::AmazonNovaLiteV10
3892            | Self::AmazonNovaMicroV10
3893            | Self::AmazonNovaProV10
3894            | Self::AnthropicClaudeHaiku4520251001V10
3895            | Self::AnthropicClaudeOpus4120250805V10
3896            | Self::AnthropicClaudeOpus4520251101V10
3897            | Self::AnthropicClaudeOpus46V1
3898            | Self::AnthropicClaudeOpus47
3899            | Self::AnthropicClaudeSonnet4520250929V10
3900            | Self::AnthropicClaudeSonnet46
3901            | Self::AuAnthropicClaudeHaiku4520251001V10
3902            | Self::AuAnthropicClaudeOpus46V1
3903            | Self::AuAnthropicClaudeSonnet4520250929V10
3904            | Self::AuAnthropicClaudeSonnet46
3905            | Self::EuAnthropicClaudeHaiku4520251001V10
3906            | Self::EuAnthropicClaudeOpus4520251101V10
3907            | Self::EuAnthropicClaudeOpus46V1
3908            | Self::EuAnthropicClaudeOpus47
3909            | Self::EuAnthropicClaudeSonnet4520250929V10
3910            | Self::EuAnthropicClaudeSonnet46
3911            | Self::GlobalAnthropicClaudeHaiku4520251001V10
3912            | Self::GlobalAnthropicClaudeOpus4520251101V10
3913            | Self::GlobalAnthropicClaudeOpus46V1
3914            | Self::GlobalAnthropicClaudeOpus47
3915            | Self::GlobalAnthropicClaudeSonnet4520250929V10
3916            | Self::GlobalAnthropicClaudeSonnet46
3917            | Self::JpAnthropicClaudeOpus47
3918            | Self::JpAnthropicClaudeSonnet4520250929V10
3919            | Self::JpAnthropicClaudeSonnet46
3920            | Self::UsAnthropicClaudeHaiku4520251001V10
3921            | Self::UsAnthropicClaudeOpus4120250805V10
3922            | Self::UsAnthropicClaudeOpus4520251101V10
3923            | Self::UsAnthropicClaudeOpus46V1
3924            | Self::UsAnthropicClaudeOpus47
3925            | Self::UsAnthropicClaudeSonnet4520250929V10
3926            | Self::UsAnthropicClaudeSonnet46 => true,
3927        }
3928    }
3929    #[allow(clippy::too_many_lines)]
3930    pub fn supports_image(self) -> bool {
3931        match self {
3932            Self::AmazonNovaMicroV10
3933            | Self::DeepseekR1V10
3934            | Self::DeepseekV3V10
3935            | Self::DeepseekV32
3936            | Self::MetaLlama3170bInstructV10
3937            | Self::MetaLlama318bInstructV10
3938            | Self::MetaLlama3370bInstructV10
3939            | Self::MinimaxMinimaxM2
3940            | Self::MinimaxMinimaxM21
3941            | Self::MinimaxMinimaxM25
3942            | Self::MistralDevstral2123b
3943            | Self::MistralMinistral314bInstruct
3944            | Self::MistralMinistral38bInstruct
3945            | Self::MistralVoxtralMini3b2507
3946            | Self::MistralVoxtralSmall24b2507
3947            | Self::MoonshotKimiK2Thinking
3948            | Self::NvidiaNemotronNano330b
3949            | Self::NvidiaNemotronNano9bV2
3950            | Self::NvidiaNemotronSuper3120b
3951            | Self::OpenaiGptOss120b10
3952            | Self::OpenaiGptOss20b10
3953            | Self::OpenaiGptOssSafeguard120b
3954            | Self::OpenaiGptOssSafeguard20b
3955            | Self::QwenQwen3235bA22b2507V10
3956            | Self::QwenQwen332bV10
3957            | Self::QwenQwen3Coder30bA3bV10
3958            | Self::QwenQwen3Coder480bA35bV10
3959            | Self::QwenQwen3CoderNext
3960            | Self::QwenQwen3Next80bA3b
3961            | Self::UsDeepseekR1V10
3962            | Self::WriterPalmyraX4V10
3963            | Self::WriterPalmyraX5V10
3964            | Self::ZaiGlm47
3965            | Self::ZaiGlm47Flash
3966            | Self::ZaiGlm5 => false,
3967            Self::AmazonNova2LiteV10
3968            | Self::AmazonNovaLiteV10
3969            | Self::AmazonNovaProV10
3970            | Self::AnthropicClaudeHaiku4520251001V10
3971            | Self::AnthropicClaudeOpus4120250805V10
3972            | Self::AnthropicClaudeOpus4520251101V10
3973            | Self::AnthropicClaudeOpus46V1
3974            | Self::AnthropicClaudeOpus47
3975            | Self::AnthropicClaudeSonnet4520250929V10
3976            | Self::AnthropicClaudeSonnet46
3977            | Self::AuAnthropicClaudeHaiku4520251001V10
3978            | Self::AuAnthropicClaudeOpus46V1
3979            | Self::AuAnthropicClaudeSonnet4520250929V10
3980            | Self::AuAnthropicClaudeSonnet46
3981            | Self::EuAnthropicClaudeHaiku4520251001V10
3982            | Self::EuAnthropicClaudeOpus4520251101V10
3983            | Self::EuAnthropicClaudeOpus46V1
3984            | Self::EuAnthropicClaudeOpus47
3985            | Self::EuAnthropicClaudeSonnet4520250929V10
3986            | Self::EuAnthropicClaudeSonnet46
3987            | Self::GlobalAnthropicClaudeHaiku4520251001V10
3988            | Self::GlobalAnthropicClaudeOpus4520251101V10
3989            | Self::GlobalAnthropicClaudeOpus46V1
3990            | Self::GlobalAnthropicClaudeOpus47
3991            | Self::GlobalAnthropicClaudeSonnet4520250929V10
3992            | Self::GlobalAnthropicClaudeSonnet46
3993            | Self::GoogleGemma327bIt
3994            | Self::GoogleGemma34bIt
3995            | Self::JpAnthropicClaudeOpus47
3996            | Self::JpAnthropicClaudeSonnet4520250929V10
3997            | Self::JpAnthropicClaudeSonnet46
3998            | Self::MetaLlama4Maverick17bInstructV10
3999            | Self::MetaLlama4Scout17bInstructV10
4000            | Self::MistralMagistralSmall2509
4001            | Self::MistralMinistral33bInstruct
4002            | Self::MistralMistralLarge3675bInstruct
4003            | Self::MistralPixtralLarge2502V10
4004            | Self::MoonshotaiKimiK25
4005            | Self::NvidiaNemotronNano12bV2
4006            | Self::QwenQwen3Vl235bA22b
4007            | Self::UsAnthropicClaudeHaiku4520251001V10
4008            | Self::UsAnthropicClaudeOpus4120250805V10
4009            | Self::UsAnthropicClaudeOpus4520251101V10
4010            | Self::UsAnthropicClaudeOpus46V1
4011            | Self::UsAnthropicClaudeOpus47
4012            | Self::UsAnthropicClaudeSonnet4520250929V10
4013            | Self::UsAnthropicClaudeSonnet46
4014            | Self::UsMetaLlama4Maverick17bInstructV10
4015            | Self::UsMetaLlama4Scout17bInstructV10 => true,
4016        }
4017    }
4018    #[allow(clippy::too_many_lines)]
4019    pub fn supports_audio(self) -> bool {
4020        match self {
4021            Self::AmazonNova2LiteV10
4022            | Self::AmazonNovaLiteV10
4023            | Self::AmazonNovaMicroV10
4024            | Self::AmazonNovaProV10
4025            | Self::AnthropicClaudeHaiku4520251001V10
4026            | Self::AnthropicClaudeOpus4120250805V10
4027            | Self::AnthropicClaudeOpus4520251101V10
4028            | Self::AnthropicClaudeOpus46V1
4029            | Self::AnthropicClaudeOpus47
4030            | Self::AnthropicClaudeSonnet4520250929V10
4031            | Self::AnthropicClaudeSonnet46
4032            | Self::AuAnthropicClaudeHaiku4520251001V10
4033            | Self::AuAnthropicClaudeOpus46V1
4034            | Self::AuAnthropicClaudeSonnet4520250929V10
4035            | Self::AuAnthropicClaudeSonnet46
4036            | Self::DeepseekR1V10
4037            | Self::DeepseekV3V10
4038            | Self::DeepseekV32
4039            | Self::EuAnthropicClaudeHaiku4520251001V10
4040            | Self::EuAnthropicClaudeOpus4520251101V10
4041            | Self::EuAnthropicClaudeOpus46V1
4042            | Self::EuAnthropicClaudeOpus47
4043            | Self::EuAnthropicClaudeSonnet4520250929V10
4044            | Self::EuAnthropicClaudeSonnet46
4045            | Self::GlobalAnthropicClaudeHaiku4520251001V10
4046            | Self::GlobalAnthropicClaudeOpus4520251101V10
4047            | Self::GlobalAnthropicClaudeOpus46V1
4048            | Self::GlobalAnthropicClaudeOpus47
4049            | Self::GlobalAnthropicClaudeSonnet4520250929V10
4050            | Self::GlobalAnthropicClaudeSonnet46
4051            | Self::GoogleGemma327bIt
4052            | Self::GoogleGemma34bIt
4053            | Self::JpAnthropicClaudeOpus47
4054            | Self::JpAnthropicClaudeSonnet4520250929V10
4055            | Self::JpAnthropicClaudeSonnet46
4056            | Self::MetaLlama3170bInstructV10
4057            | Self::MetaLlama318bInstructV10
4058            | Self::MetaLlama3370bInstructV10
4059            | Self::MetaLlama4Maverick17bInstructV10
4060            | Self::MetaLlama4Scout17bInstructV10
4061            | Self::MinimaxMinimaxM2
4062            | Self::MinimaxMinimaxM21
4063            | Self::MinimaxMinimaxM25
4064            | Self::MistralDevstral2123b
4065            | Self::MistralMagistralSmall2509
4066            | Self::MistralMinistral314bInstruct
4067            | Self::MistralMinistral33bInstruct
4068            | Self::MistralMinistral38bInstruct
4069            | Self::MistralMistralLarge3675bInstruct
4070            | Self::MistralPixtralLarge2502V10
4071            | Self::MoonshotKimiK2Thinking
4072            | Self::MoonshotaiKimiK25
4073            | Self::NvidiaNemotronNano12bV2
4074            | Self::NvidiaNemotronNano330b
4075            | Self::NvidiaNemotronNano9bV2
4076            | Self::NvidiaNemotronSuper3120b
4077            | Self::OpenaiGptOss120b10
4078            | Self::OpenaiGptOss20b10
4079            | Self::OpenaiGptOssSafeguard120b
4080            | Self::OpenaiGptOssSafeguard20b
4081            | Self::QwenQwen3235bA22b2507V10
4082            | Self::QwenQwen332bV10
4083            | Self::QwenQwen3Coder30bA3bV10
4084            | Self::QwenQwen3Coder480bA35bV10
4085            | Self::QwenQwen3CoderNext
4086            | Self::QwenQwen3Next80bA3b
4087            | Self::QwenQwen3Vl235bA22b
4088            | Self::UsAnthropicClaudeHaiku4520251001V10
4089            | Self::UsAnthropicClaudeOpus4120250805V10
4090            | Self::UsAnthropicClaudeOpus4520251101V10
4091            | Self::UsAnthropicClaudeOpus46V1
4092            | Self::UsAnthropicClaudeOpus47
4093            | Self::UsAnthropicClaudeSonnet4520250929V10
4094            | Self::UsAnthropicClaudeSonnet46
4095            | Self::UsDeepseekR1V10
4096            | Self::UsMetaLlama4Maverick17bInstructV10
4097            | Self::UsMetaLlama4Scout17bInstructV10
4098            | Self::WriterPalmyraX4V10
4099            | Self::WriterPalmyraX5V10
4100            | Self::ZaiGlm47
4101            | Self::ZaiGlm47Flash
4102            | Self::ZaiGlm5 => false,
4103            Self::MistralVoxtralMini3b2507 | Self::MistralVoxtralSmall24b2507 => true,
4104        }
4105    }
4106    const ALL: &[BedrockFoundationModel] = &[
4107        Self::AmazonNova2LiteV10,
4108        Self::AmazonNovaLiteV10,
4109        Self::AmazonNovaMicroV10,
4110        Self::AmazonNovaProV10,
4111        Self::AnthropicClaudeHaiku4520251001V10,
4112        Self::AnthropicClaudeOpus4120250805V10,
4113        Self::AnthropicClaudeOpus4520251101V10,
4114        Self::AnthropicClaudeOpus46V1,
4115        Self::AnthropicClaudeOpus47,
4116        Self::AnthropicClaudeSonnet4520250929V10,
4117        Self::AnthropicClaudeSonnet46,
4118        Self::AuAnthropicClaudeHaiku4520251001V10,
4119        Self::AuAnthropicClaudeOpus46V1,
4120        Self::AuAnthropicClaudeSonnet4520250929V10,
4121        Self::AuAnthropicClaudeSonnet46,
4122        Self::DeepseekR1V10,
4123        Self::DeepseekV3V10,
4124        Self::DeepseekV32,
4125        Self::EuAnthropicClaudeHaiku4520251001V10,
4126        Self::EuAnthropicClaudeOpus4520251101V10,
4127        Self::EuAnthropicClaudeOpus46V1,
4128        Self::EuAnthropicClaudeOpus47,
4129        Self::EuAnthropicClaudeSonnet4520250929V10,
4130        Self::EuAnthropicClaudeSonnet46,
4131        Self::GlobalAnthropicClaudeHaiku4520251001V10,
4132        Self::GlobalAnthropicClaudeOpus4520251101V10,
4133        Self::GlobalAnthropicClaudeOpus46V1,
4134        Self::GlobalAnthropicClaudeOpus47,
4135        Self::GlobalAnthropicClaudeSonnet4520250929V10,
4136        Self::GlobalAnthropicClaudeSonnet46,
4137        Self::GoogleGemma327bIt,
4138        Self::GoogleGemma34bIt,
4139        Self::JpAnthropicClaudeOpus47,
4140        Self::JpAnthropicClaudeSonnet4520250929V10,
4141        Self::JpAnthropicClaudeSonnet46,
4142        Self::MetaLlama3170bInstructV10,
4143        Self::MetaLlama318bInstructV10,
4144        Self::MetaLlama3370bInstructV10,
4145        Self::MetaLlama4Maverick17bInstructV10,
4146        Self::MetaLlama4Scout17bInstructV10,
4147        Self::MinimaxMinimaxM2,
4148        Self::MinimaxMinimaxM21,
4149        Self::MinimaxMinimaxM25,
4150        Self::MistralDevstral2123b,
4151        Self::MistralMagistralSmall2509,
4152        Self::MistralMinistral314bInstruct,
4153        Self::MistralMinistral33bInstruct,
4154        Self::MistralMinistral38bInstruct,
4155        Self::MistralMistralLarge3675bInstruct,
4156        Self::MistralPixtralLarge2502V10,
4157        Self::MistralVoxtralMini3b2507,
4158        Self::MistralVoxtralSmall24b2507,
4159        Self::MoonshotKimiK2Thinking,
4160        Self::MoonshotaiKimiK25,
4161        Self::NvidiaNemotronNano12bV2,
4162        Self::NvidiaNemotronNano330b,
4163        Self::NvidiaNemotronNano9bV2,
4164        Self::NvidiaNemotronSuper3120b,
4165        Self::OpenaiGptOss120b10,
4166        Self::OpenaiGptOss20b10,
4167        Self::OpenaiGptOssSafeguard120b,
4168        Self::OpenaiGptOssSafeguard20b,
4169        Self::QwenQwen3235bA22b2507V10,
4170        Self::QwenQwen332bV10,
4171        Self::QwenQwen3Coder30bA3bV10,
4172        Self::QwenQwen3Coder480bA35bV10,
4173        Self::QwenQwen3CoderNext,
4174        Self::QwenQwen3Next80bA3b,
4175        Self::QwenQwen3Vl235bA22b,
4176        Self::UsAnthropicClaudeHaiku4520251001V10,
4177        Self::UsAnthropicClaudeOpus4120250805V10,
4178        Self::UsAnthropicClaudeOpus4520251101V10,
4179        Self::UsAnthropicClaudeOpus46V1,
4180        Self::UsAnthropicClaudeOpus47,
4181        Self::UsAnthropicClaudeSonnet4520250929V10,
4182        Self::UsAnthropicClaudeSonnet46,
4183        Self::UsDeepseekR1V10,
4184        Self::UsMetaLlama4Maverick17bInstructV10,
4185        Self::UsMetaLlama4Scout17bInstructV10,
4186        Self::WriterPalmyraX4V10,
4187        Self::WriterPalmyraX5V10,
4188        Self::ZaiGlm47,
4189        Self::ZaiGlm47Flash,
4190        Self::ZaiGlm5,
4191    ];
4192}
4193impl std::str::FromStr for BedrockFoundationModel {
4194    type Err = String;
4195    #[allow(clippy::too_many_lines)]
4196    fn from_str(s: &str) -> Result<Self, Self::Err> {
4197        match s {
4198            "amazon.nova-2-lite-v1:0" => Ok(Self::AmazonNova2LiteV10),
4199            "amazon.nova-lite-v1:0" => Ok(Self::AmazonNovaLiteV10),
4200            "amazon.nova-micro-v1:0" => Ok(Self::AmazonNovaMicroV10),
4201            "amazon.nova-pro-v1:0" => Ok(Self::AmazonNovaProV10),
4202            "anthropic.claude-haiku-4-5-20251001-v1:0" => {
4203                Ok(Self::AnthropicClaudeHaiku4520251001V10)
4204            }
4205            "anthropic.claude-opus-4-1-20250805-v1:0" => {
4206                Ok(Self::AnthropicClaudeOpus4120250805V10)
4207            }
4208            "anthropic.claude-opus-4-5-20251101-v1:0" => {
4209                Ok(Self::AnthropicClaudeOpus4520251101V10)
4210            }
4211            "anthropic.claude-opus-4-6-v1" => Ok(Self::AnthropicClaudeOpus46V1),
4212            "anthropic.claude-opus-4-7" => Ok(Self::AnthropicClaudeOpus47),
4213            "anthropic.claude-sonnet-4-5-20250929-v1:0" => {
4214                Ok(Self::AnthropicClaudeSonnet4520250929V10)
4215            }
4216            "anthropic.claude-sonnet-4-6" => Ok(Self::AnthropicClaudeSonnet46),
4217            "au.anthropic.claude-haiku-4-5-20251001-v1:0" => {
4218                Ok(Self::AuAnthropicClaudeHaiku4520251001V10)
4219            }
4220            "au.anthropic.claude-opus-4-6-v1" => Ok(Self::AuAnthropicClaudeOpus46V1),
4221            "au.anthropic.claude-sonnet-4-5-20250929-v1:0" => {
4222                Ok(Self::AuAnthropicClaudeSonnet4520250929V10)
4223            }
4224            "au.anthropic.claude-sonnet-4-6" => Ok(Self::AuAnthropicClaudeSonnet46),
4225            "deepseek.r1-v1:0" => Ok(Self::DeepseekR1V10),
4226            "deepseek.v3-v1:0" => Ok(Self::DeepseekV3V10),
4227            "deepseek.v3.2" => Ok(Self::DeepseekV32),
4228            "eu.anthropic.claude-haiku-4-5-20251001-v1:0" => {
4229                Ok(Self::EuAnthropicClaudeHaiku4520251001V10)
4230            }
4231            "eu.anthropic.claude-opus-4-5-20251101-v1:0" => {
4232                Ok(Self::EuAnthropicClaudeOpus4520251101V10)
4233            }
4234            "eu.anthropic.claude-opus-4-6-v1" => Ok(Self::EuAnthropicClaudeOpus46V1),
4235            "eu.anthropic.claude-opus-4-7" => Ok(Self::EuAnthropicClaudeOpus47),
4236            "eu.anthropic.claude-sonnet-4-5-20250929-v1:0" => {
4237                Ok(Self::EuAnthropicClaudeSonnet4520250929V10)
4238            }
4239            "eu.anthropic.claude-sonnet-4-6" => Ok(Self::EuAnthropicClaudeSonnet46),
4240            "global.anthropic.claude-haiku-4-5-20251001-v1:0" => {
4241                Ok(Self::GlobalAnthropicClaudeHaiku4520251001V10)
4242            }
4243            "global.anthropic.claude-opus-4-5-20251101-v1:0" => {
4244                Ok(Self::GlobalAnthropicClaudeOpus4520251101V10)
4245            }
4246            "global.anthropic.claude-opus-4-6-v1" => {
4247                Ok(Self::GlobalAnthropicClaudeOpus46V1)
4248            }
4249            "global.anthropic.claude-opus-4-7" => Ok(Self::GlobalAnthropicClaudeOpus47),
4250            "global.anthropic.claude-sonnet-4-5-20250929-v1:0" => {
4251                Ok(Self::GlobalAnthropicClaudeSonnet4520250929V10)
4252            }
4253            "global.anthropic.claude-sonnet-4-6" => {
4254                Ok(Self::GlobalAnthropicClaudeSonnet46)
4255            }
4256            "google.gemma-3-27b-it" => Ok(Self::GoogleGemma327bIt),
4257            "google.gemma-3-4b-it" => Ok(Self::GoogleGemma34bIt),
4258            "jp.anthropic.claude-opus-4-7" => Ok(Self::JpAnthropicClaudeOpus47),
4259            "jp.anthropic.claude-sonnet-4-5-20250929-v1:0" => {
4260                Ok(Self::JpAnthropicClaudeSonnet4520250929V10)
4261            }
4262            "jp.anthropic.claude-sonnet-4-6" => Ok(Self::JpAnthropicClaudeSonnet46),
4263            "meta.llama3-1-70b-instruct-v1:0" => Ok(Self::MetaLlama3170bInstructV10),
4264            "meta.llama3-1-8b-instruct-v1:0" => Ok(Self::MetaLlama318bInstructV10),
4265            "meta.llama3-3-70b-instruct-v1:0" => Ok(Self::MetaLlama3370bInstructV10),
4266            "meta.llama4-maverick-17b-instruct-v1:0" => {
4267                Ok(Self::MetaLlama4Maverick17bInstructV10)
4268            }
4269            "meta.llama4-scout-17b-instruct-v1:0" => {
4270                Ok(Self::MetaLlama4Scout17bInstructV10)
4271            }
4272            "minimax.minimax-m2" => Ok(Self::MinimaxMinimaxM2),
4273            "minimax.minimax-m2.1" => Ok(Self::MinimaxMinimaxM21),
4274            "minimax.minimax-m2.5" => Ok(Self::MinimaxMinimaxM25),
4275            "mistral.devstral-2-123b" => Ok(Self::MistralDevstral2123b),
4276            "mistral.magistral-small-2509" => Ok(Self::MistralMagistralSmall2509),
4277            "mistral.ministral-3-14b-instruct" => Ok(Self::MistralMinistral314bInstruct),
4278            "mistral.ministral-3-3b-instruct" => Ok(Self::MistralMinistral33bInstruct),
4279            "mistral.ministral-3-8b-instruct" => Ok(Self::MistralMinistral38bInstruct),
4280            "mistral.mistral-large-3-675b-instruct" => {
4281                Ok(Self::MistralMistralLarge3675bInstruct)
4282            }
4283            "mistral.pixtral-large-2502-v1:0" => Ok(Self::MistralPixtralLarge2502V10),
4284            "mistral.voxtral-mini-3b-2507" => Ok(Self::MistralVoxtralMini3b2507),
4285            "mistral.voxtral-small-24b-2507" => Ok(Self::MistralVoxtralSmall24b2507),
4286            "moonshot.kimi-k2-thinking" => Ok(Self::MoonshotKimiK2Thinking),
4287            "moonshotai.kimi-k2.5" => Ok(Self::MoonshotaiKimiK25),
4288            "nvidia.nemotron-nano-12b-v2" => Ok(Self::NvidiaNemotronNano12bV2),
4289            "nvidia.nemotron-nano-3-30b" => Ok(Self::NvidiaNemotronNano330b),
4290            "nvidia.nemotron-nano-9b-v2" => Ok(Self::NvidiaNemotronNano9bV2),
4291            "nvidia.nemotron-super-3-120b" => Ok(Self::NvidiaNemotronSuper3120b),
4292            "openai.gpt-oss-120b-1:0" => Ok(Self::OpenaiGptOss120b10),
4293            "openai.gpt-oss-20b-1:0" => Ok(Self::OpenaiGptOss20b10),
4294            "openai.gpt-oss-safeguard-120b" => Ok(Self::OpenaiGptOssSafeguard120b),
4295            "openai.gpt-oss-safeguard-20b" => Ok(Self::OpenaiGptOssSafeguard20b),
4296            "qwen.qwen3-235b-a22b-2507-v1:0" => Ok(Self::QwenQwen3235bA22b2507V10),
4297            "qwen.qwen3-32b-v1:0" => Ok(Self::QwenQwen332bV10),
4298            "qwen.qwen3-coder-30b-a3b-v1:0" => Ok(Self::QwenQwen3Coder30bA3bV10),
4299            "qwen.qwen3-coder-480b-a35b-v1:0" => Ok(Self::QwenQwen3Coder480bA35bV10),
4300            "qwen.qwen3-coder-next" => Ok(Self::QwenQwen3CoderNext),
4301            "qwen.qwen3-next-80b-a3b" => Ok(Self::QwenQwen3Next80bA3b),
4302            "qwen.qwen3-vl-235b-a22b" => Ok(Self::QwenQwen3Vl235bA22b),
4303            "us.anthropic.claude-haiku-4-5-20251001-v1:0" => {
4304                Ok(Self::UsAnthropicClaudeHaiku4520251001V10)
4305            }
4306            "us.anthropic.claude-opus-4-1-20250805-v1:0" => {
4307                Ok(Self::UsAnthropicClaudeOpus4120250805V10)
4308            }
4309            "us.anthropic.claude-opus-4-5-20251101-v1:0" => {
4310                Ok(Self::UsAnthropicClaudeOpus4520251101V10)
4311            }
4312            "us.anthropic.claude-opus-4-6-v1" => Ok(Self::UsAnthropicClaudeOpus46V1),
4313            "us.anthropic.claude-opus-4-7" => Ok(Self::UsAnthropicClaudeOpus47),
4314            "us.anthropic.claude-sonnet-4-5-20250929-v1:0" => {
4315                Ok(Self::UsAnthropicClaudeSonnet4520250929V10)
4316            }
4317            "us.anthropic.claude-sonnet-4-6" => Ok(Self::UsAnthropicClaudeSonnet46),
4318            "us.deepseek.r1-v1:0" => Ok(Self::UsDeepseekR1V10),
4319            "us.meta.llama4-maverick-17b-instruct-v1:0" => {
4320                Ok(Self::UsMetaLlama4Maverick17bInstructV10)
4321            }
4322            "us.meta.llama4-scout-17b-instruct-v1:0" => {
4323                Ok(Self::UsMetaLlama4Scout17bInstructV10)
4324            }
4325            "writer.palmyra-x4-v1:0" => Ok(Self::WriterPalmyraX4V10),
4326            "writer.palmyra-x5-v1:0" => Ok(Self::WriterPalmyraX5V10),
4327            "zai.glm-4.7" => Ok(Self::ZaiGlm47),
4328            "zai.glm-4.7-flash" => Ok(Self::ZaiGlm47Flash),
4329            "zai.glm-5" => Ok(Self::ZaiGlm5),
4330            _ => Err(format!("Unknown bedrock model: '{s}'")),
4331        }
4332    }
4333}
4334/// A model from a specific provider
4335#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4336pub enum LlmModel {
4337    Anthropic(AnthropicModel),
4338    Codex(CodexModel),
4339    DeepSeek(DeepSeekModel),
4340    Gemini(GeminiModel),
4341    Moonshot(MoonshotModel),
4342    Openai(OpenaiModel),
4343    OpenRouter(OpenRouterModel),
4344    ZAi(ZAiModel),
4345    Bedrock(BedrockModel),
4346    Ollama(String),
4347    LlamaCpp(String),
4348}
4349impl From<AnthropicModel> for LlmModel {
4350    fn from(m: AnthropicModel) -> Self {
4351        LlmModel::Anthropic(m)
4352    }
4353}
4354impl From<CodexModel> for LlmModel {
4355    fn from(m: CodexModel) -> Self {
4356        LlmModel::Codex(m)
4357    }
4358}
4359impl From<DeepSeekModel> for LlmModel {
4360    fn from(m: DeepSeekModel) -> Self {
4361        LlmModel::DeepSeek(m)
4362    }
4363}
4364impl From<GeminiModel> for LlmModel {
4365    fn from(m: GeminiModel) -> Self {
4366        LlmModel::Gemini(m)
4367    }
4368}
4369impl From<MoonshotModel> for LlmModel {
4370    fn from(m: MoonshotModel) -> Self {
4371        LlmModel::Moonshot(m)
4372    }
4373}
4374impl From<OpenaiModel> for LlmModel {
4375    fn from(m: OpenaiModel) -> Self {
4376        LlmModel::Openai(m)
4377    }
4378}
4379impl From<OpenRouterModel> for LlmModel {
4380    fn from(m: OpenRouterModel) -> Self {
4381        LlmModel::OpenRouter(m)
4382    }
4383}
4384impl From<ZAiModel> for LlmModel {
4385    fn from(m: ZAiModel) -> Self {
4386        LlmModel::ZAi(m)
4387    }
4388}
4389impl From<BedrockModel> for LlmModel {
4390    fn from(m: BedrockModel) -> Self {
4391        LlmModel::Bedrock(m)
4392    }
4393}
4394impl LlmModel {
4395    /// Raw model ID (e.g. `claude-opus-4-6`, `llama3.2`)
4396    pub fn model_id(&self) -> Cow<'static, str> {
4397        match self {
4398            Self::Anthropic(m) => Cow::Borrowed(m.model_id()),
4399            Self::Codex(m) => Cow::Borrowed(m.model_id()),
4400            Self::DeepSeek(m) => Cow::Borrowed(m.model_id()),
4401            Self::Gemini(m) => Cow::Borrowed(m.model_id()),
4402            Self::Moonshot(m) => Cow::Borrowed(m.model_id()),
4403            Self::Openai(m) => Cow::Borrowed(m.model_id()),
4404            Self::OpenRouter(m) => Cow::Borrowed(m.model_id()),
4405            Self::ZAi(m) => Cow::Borrowed(m.model_id()),
4406            Self::Bedrock(m) => m.model_id(),
4407            Self::Ollama(s) | Self::LlamaCpp(s) => Cow::Owned(s.clone()),
4408        }
4409    }
4410    /// Human-readable display name (e.g. `Claude Opus 4.6`)
4411    pub fn display_name(&self) -> Cow<'static, str> {
4412        match self {
4413            Self::Anthropic(m) => Cow::Borrowed(m.display_name()),
4414            Self::Codex(m) => Cow::Borrowed(m.display_name()),
4415            Self::DeepSeek(m) => Cow::Borrowed(m.display_name()),
4416            Self::Gemini(m) => Cow::Borrowed(m.display_name()),
4417            Self::Moonshot(m) => Cow::Borrowed(m.display_name()),
4418            Self::Openai(m) => Cow::Borrowed(m.display_name()),
4419            Self::OpenRouter(m) => Cow::Borrowed(m.display_name()),
4420            Self::ZAi(m) => Cow::Borrowed(m.display_name()),
4421            Self::Bedrock(m) => m.display_name(),
4422            Self::Ollama(s) => Cow::Owned(format!("Ollama {s}")),
4423            Self::LlamaCpp(s) => Cow::Owned(format!("LlamaCpp {s}")),
4424        }
4425    }
4426    /// Provider identifier (e.g. `anthropic`)
4427    pub fn provider(&self) -> &'static str {
4428        match self {
4429            Self::Anthropic(_) => "anthropic",
4430            Self::Codex(_) => "codex",
4431            Self::DeepSeek(_) => "deepseek",
4432            Self::Gemini(_) => "gemini",
4433            Self::Moonshot(_) => "moonshot",
4434            Self::Openai(_) => "openai",
4435            Self::OpenRouter(_) => "openrouter",
4436            Self::ZAi(_) => "zai",
4437            Self::Bedrock(_) => "bedrock",
4438            Self::Ollama(_) => "ollama",
4439            Self::LlamaCpp(_) => "llamacpp",
4440        }
4441    }
4442    /// Human-readable provider name (e.g. `AWS Bedrock`)
4443    pub fn provider_display_name(&self) -> &'static str {
4444        match self {
4445            Self::Anthropic(_) => "Anthropic",
4446            Self::Codex(_) => "Codex",
4447            Self::DeepSeek(_) => "DeepSeek",
4448            Self::Gemini(_) => "Gemini",
4449            Self::Moonshot(_) => "Moonshot",
4450            Self::Openai(_) => "OpenAI",
4451            Self::OpenRouter(_) => "OpenRouter",
4452            Self::ZAi(_) => "ZAI",
4453            Self::Bedrock(_) => "AWS Bedrock",
4454            Self::Ollama(_) => "Ollama",
4455            Self::LlamaCpp(_) => "LlamaCpp",
4456        }
4457    }
4458    /// Context window size in tokens (None for dynamic providers)
4459    pub fn context_window(&self) -> Option<u32> {
4460        match self {
4461            Self::Anthropic(m) => Some(m.context_window()),
4462            Self::Codex(m) => Some(m.context_window()),
4463            Self::DeepSeek(m) => Some(m.context_window()),
4464            Self::Gemini(m) => Some(m.context_window()),
4465            Self::Moonshot(m) => Some(m.context_window()),
4466            Self::Openai(m) => Some(m.context_window()),
4467            Self::OpenRouter(m) => Some(m.context_window()),
4468            Self::ZAi(m) => Some(m.context_window()),
4469            Self::Bedrock(m) => m.context_window(),
4470            Self::Ollama(_) | Self::LlamaCpp(_) => None,
4471        }
4472    }
4473    /// Required env var for this model's provider (None for local providers)
4474    pub fn required_env_var(&self) -> Option<&'static str> {
4475        match self {
4476            Self::Anthropic(_) => Some("ANTHROPIC_API_KEY"),
4477            Self::DeepSeek(_) => Some("DEEPSEEK_API_KEY"),
4478            Self::Gemini(_) => Some("GEMINI_API_KEY"),
4479            Self::Moonshot(_) => Some("MOONSHOT_API_KEY"),
4480            Self::Openai(_) => Some("OPENAI_API_KEY"),
4481            Self::OpenRouter(_) => Some("OPENROUTER_API_KEY"),
4482            Self::ZAi(_) => Some("ZAI_API_KEY"),
4483            Self::Codex(_) | Self::Bedrock(_) | Self::Ollama(_) | Self::LlamaCpp(_) => {
4484                None
4485            }
4486        }
4487    }
4488    /// All provider API key env var names (deduplicated, static)
4489    pub const ALL_REQUIRED_ENV_VARS: &[&str] = &[
4490        "ANTHROPIC_API_KEY",
4491        "DEEPSEEK_API_KEY",
4492        "GEMINI_API_KEY",
4493        "MOONSHOT_API_KEY",
4494        "OPENAI_API_KEY",
4495        "OPENROUTER_API_KEY",
4496        "ZAI_API_KEY",
4497    ];
4498    /// OAuth provider ID if this model requires OAuth login (e.g. `"codex"`)
4499    pub fn oauth_provider_id(&self) -> Option<&'static str> {
4500        match self {
4501            Self::Codex(_) => Some("codex"),
4502            Self::Anthropic(_)
4503            | Self::DeepSeek(_)
4504            | Self::Gemini(_)
4505            | Self::Moonshot(_)
4506            | Self::Openai(_)
4507            | Self::OpenRouter(_)
4508            | Self::ZAi(_)
4509            | Self::Bedrock(_)
4510            | Self::Ollama(_)
4511            | Self::LlamaCpp(_) => None,
4512        }
4513    }
4514    /// Reasoning levels supported by this model (empty if not a reasoning model)
4515    pub fn reasoning_levels(&self) -> &'static [ReasoningEffort] {
4516        match self {
4517            Self::Anthropic(m) => m.reasoning_levels(),
4518            Self::Codex(m) => m.reasoning_levels(),
4519            Self::DeepSeek(m) => m.reasoning_levels(),
4520            Self::Gemini(m) => m.reasoning_levels(),
4521            Self::Moonshot(m) => m.reasoning_levels(),
4522            Self::Openai(m) => m.reasoning_levels(),
4523            Self::OpenRouter(m) => m.reasoning_levels(),
4524            Self::ZAi(m) => m.reasoning_levels(),
4525            Self::Bedrock(m) => m.reasoning_levels(),
4526            Self::Ollama(_) | Self::LlamaCpp(_) => &[],
4527        }
4528    }
4529    /// Whether this model supports reasoning/extended thinking
4530    pub fn supports_reasoning(&self) -> bool {
4531        !self.reasoning_levels().is_empty()
4532    }
4533    /// Whether this model supports provider-side prompt caching
4534    pub fn supports_prompt_caching(&self) -> bool {
4535        match self {
4536            Self::Anthropic(m) => m.supports_prompt_caching(),
4537            Self::Codex(m) => m.supports_prompt_caching(),
4538            Self::DeepSeek(m) => m.supports_prompt_caching(),
4539            Self::Gemini(m) => m.supports_prompt_caching(),
4540            Self::Moonshot(m) => m.supports_prompt_caching(),
4541            Self::Openai(m) => m.supports_prompt_caching(),
4542            Self::OpenRouter(m) => m.supports_prompt_caching(),
4543            Self::ZAi(m) => m.supports_prompt_caching(),
4544            Self::Bedrock(m) => m.supports_prompt_caching(),
4545            Self::Ollama(_) | Self::LlamaCpp(_) => false,
4546        }
4547    }
4548    /// Whether this model supports image input
4549    pub fn supports_image(&self) -> bool {
4550        match self {
4551            Self::Anthropic(m) => m.supports_image(),
4552            Self::Codex(m) => m.supports_image(),
4553            Self::DeepSeek(m) => m.supports_image(),
4554            Self::Gemini(m) => m.supports_image(),
4555            Self::Moonshot(m) => m.supports_image(),
4556            Self::Openai(m) => m.supports_image(),
4557            Self::OpenRouter(m) => m.supports_image(),
4558            Self::ZAi(m) => m.supports_image(),
4559            Self::Bedrock(m) => m.supports_image(),
4560            Self::Ollama(_) | Self::LlamaCpp(_) => false,
4561        }
4562    }
4563    /// Whether this model supports audio input
4564    pub fn supports_audio(&self) -> bool {
4565        match self {
4566            Self::Anthropic(m) => m.supports_audio(),
4567            Self::Codex(m) => m.supports_audio(),
4568            Self::DeepSeek(m) => m.supports_audio(),
4569            Self::Gemini(m) => m.supports_audio(),
4570            Self::Moonshot(m) => m.supports_audio(),
4571            Self::Openai(m) => m.supports_audio(),
4572            Self::OpenRouter(m) => m.supports_audio(),
4573            Self::ZAi(m) => m.supports_audio(),
4574            Self::Bedrock(m) => m.supports_audio(),
4575            Self::Ollama(_) | Self::LlamaCpp(_) => false,
4576        }
4577    }
4578    /// All catalog models (excludes dynamic providers)
4579    pub fn all() -> &'static [LlmModel] {
4580        static ALL: LazyLock<Vec<LlmModel>> = LazyLock::new(|| {
4581            let mut v = Vec::new();
4582            v.extend(AnthropicModel::ALL.iter().copied().map(LlmModel::Anthropic));
4583            v.extend(CodexModel::ALL.iter().copied().map(LlmModel::Codex));
4584            v.extend(DeepSeekModel::ALL.iter().copied().map(LlmModel::DeepSeek));
4585            v.extend(GeminiModel::ALL.iter().copied().map(LlmModel::Gemini));
4586            v.extend(MoonshotModel::ALL.iter().copied().map(LlmModel::Moonshot));
4587            v.extend(OpenaiModel::ALL.iter().copied().map(LlmModel::Openai));
4588            v.extend(OpenRouterModel::ALL.iter().copied().map(LlmModel::OpenRouter));
4589            v.extend(ZAiModel::ALL.iter().copied().map(LlmModel::ZAi));
4590            v.extend(
4591                BedrockFoundationModel::ALL
4592                    .iter()
4593                    .copied()
4594                    .map(BedrockModel::Foundation)
4595                    .map(LlmModel::Bedrock),
4596            );
4597            v
4598        });
4599        &ALL
4600    }
4601}
4602impl std::fmt::Display for LlmModel {
4603    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4604        write!(f, "{}:{}", self.provider(), self.model_id())
4605    }
4606}
4607impl std::str::FromStr for LlmModel {
4608    type Err = String;
4609    /// Parse a `provider:model` string into an `LlmModel`
4610    fn from_str(s: &str) -> Result<Self, Self::Err> {
4611        let (provider_str, model_str) = s.split_once(':').unwrap_or((s, ""));
4612        match provider_str {
4613            "anthropic" => model_str.parse::<AnthropicModel>().map(Self::Anthropic),
4614            "codex" => model_str.parse::<CodexModel>().map(Self::Codex),
4615            "deepseek" => model_str.parse::<DeepSeekModel>().map(Self::DeepSeek),
4616            "gemini" => model_str.parse::<GeminiModel>().map(Self::Gemini),
4617            "moonshot" => model_str.parse::<MoonshotModel>().map(Self::Moonshot),
4618            "openai" => model_str.parse::<OpenaiModel>().map(Self::Openai),
4619            "openrouter" => model_str.parse::<OpenRouterModel>().map(Self::OpenRouter),
4620            "zai" => model_str.parse::<ZAiModel>().map(Self::ZAi),
4621            "bedrock" => model_str.parse::<BedrockModel>().map(Self::Bedrock),
4622            "ollama" => Ok(Self::Ollama(model_str.to_string())),
4623            "llamacpp" => Ok(Self::LlamaCpp(model_str.to_string())),
4624            _ => Err(format!("Unknown provider: '{provider_str}'")),
4625        }
4626    }
4627}