Skip to main content

vtcode_core/models_manager/
model_presets.rs

1//! Model presets and built-in model configurations.
2//!
3//! This module provides pre-configured model presets for all supported providers,
4//! following the pattern from OpenAI Codex's models_manager.
5
6use serde::{Deserialize, Serialize};
7
8use crate::config::constants::models::copilot as copilot_models;
9use crate::config::constants::models::evolink as evolink_models;
10use crate::config::constants::models::llamacpp as llamacpp_models;
11use crate::config::constants::models::mimo as mimo_models;
12use crate::config::constants::models::poolside as poolside_models;
13use crate::config::constants::models::qwen as qwen_models;
14use crate::config::constants::models::stepfun as stepfun_models;
15use crate::config::models::Provider;
16use crate::config::types::ReasoningEffortLevel;
17
18/// Reasoning effort preset with description
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20pub struct ReasoningEffortPreset {
21    /// The effort level
22    pub effort: ReasoningEffortLevel,
23    /// Human-readable description
24    pub description: String,
25}
26
27/// Model upgrade information
28#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
29pub struct ModelUpgrade {
30    /// Target model ID to upgrade to
31    pub id: String,
32    /// Optional reasoning effort mapping
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub reasoning_effort_mapping: Option<String>,
35    /// Configuration key for migration
36    pub migration_config_key: String,
37    /// Link to model documentation
38    #[serde(default, skip_serializing_if = "Option::is_none")]
39    pub model_link: Option<String>,
40    /// Upgrade notification copy
41    #[serde(default, skip_serializing_if = "Option::is_none")]
42    pub upgrade_copy: Option<String>,
43}
44
45/// Remote model information received from provider APIs
46#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
47pub struct ModelInfo {
48    /// Unique model identifier/slug
49    pub slug: String,
50    /// Display name for UI
51    pub display_name: String,
52    /// Model description
53    pub description: String,
54    /// Provider this model belongs to
55    pub provider: Provider,
56    /// Default reasoning level
57    #[serde(default)]
58    pub default_reasoning_level: ReasoningEffortLevel,
59    /// Supported reasoning levels
60    #[serde(default)]
61    pub supported_reasoning_levels: Vec<ReasoningEffortPreset>,
62    /// Context window size
63    #[serde(default)]
64    pub context_window: Option<i64>,
65    /// Whether this model supports tool use
66    #[serde(default = "default_true")]
67    pub supports_tool_use: bool,
68    /// Whether this model supports streaming
69    #[serde(default = "default_true")]
70    pub supports_streaming: bool,
71    /// Whether this model supports reasoning/thinking
72    #[serde(default)]
73    pub supports_reasoning: bool,
74    /// Priority for sorting (lower = higher priority)
75    #[serde(default)]
76    pub priority: i32,
77    /// Visibility in picker
78    #[serde(default = "default_visibility")]
79    pub visibility: String,
80    /// Whether supported in API mode
81    #[serde(default = "default_true")]
82    pub supported_in_api: bool,
83    /// Upgrade path if available
84    #[serde(default, skip_serializing_if = "Option::is_none")]
85    pub upgrade: Option<ModelUpgrade>,
86}
87
88fn default_true() -> bool {
89    true
90}
91
92fn default_visibility() -> String {
93    "list".to_string()
94}
95
96/// A preset configuration for a model shown in the picker
97#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
98pub struct ModelPreset {
99    /// Unique identifier for the preset
100    pub id: String,
101    /// Actual model slug to use in API calls
102    pub model: String,
103    /// Display name for UI
104    pub display_name: String,
105    /// Model description
106    pub description: String,
107    /// Provider
108    pub provider: Provider,
109    /// Default reasoning effort
110    pub default_reasoning_effort: ReasoningEffortLevel,
111    /// Supported reasoning efforts
112    pub supported_reasoning_efforts: Vec<ReasoningEffortPreset>,
113    /// Whether this is the default model
114    #[serde(default)]
115    pub is_default: bool,
116    /// Upgrade path
117    #[serde(default, skip_serializing_if = "Option::is_none")]
118    pub upgrade: Option<ModelUpgrade>,
119    /// Whether to show in picker
120    #[serde(default = "default_true")]
121    pub show_in_picker: bool,
122    /// Whether supported in API mode
123    #[serde(default = "default_true")]
124    pub supported_in_api: bool,
125    /// Context window size
126    #[serde(default)]
127    pub context_window: Option<i64>,
128}
129
130impl From<ModelInfo> for ModelPreset {
131    fn from(info: ModelInfo) -> Self {
132        Self {
133            id: info.slug.clone(),
134            model: info.slug,
135            display_name: info.display_name,
136            description: info.description,
137            provider: info.provider,
138            default_reasoning_effort: info.default_reasoning_level,
139            supported_reasoning_efforts: info.supported_reasoning_levels,
140            is_default: false,
141            upgrade: info.upgrade,
142            show_in_picker: info.visibility == "list",
143            supported_in_api: info.supported_in_api,
144            context_window: info.context_window,
145        }
146    }
147}
148
149/// Get built-in model presets for the given provider
150pub fn builtin_model_presets() -> Vec<ModelPreset> {
151    let mut presets = Vec::new();
152
153    // Gemini presets
154    presets.extend(gemini_presets());
155
156    // OpenAI presets
157    presets.extend(openai_presets());
158
159    // Anthropic presets
160    presets.extend(anthropic_presets());
161
162    // Copilot presets
163    presets.extend(copilot_presets());
164
165    // DeepSeek presets
166    presets.extend(deepseek_presets());
167
168    // Z.AI presets
169    presets.extend(zai_presets());
170
171    // LM Studio presets
172    presets.extend(lmstudio_presets());
173
174    // llama.cpp presets
175    presets.extend(llamacpp_presets());
176
177    // MiniMax presets
178    presets.extend(minimax_presets());
179
180    // OpenCode Zen presets
181    presets.extend(opencode_zen_presets());
182
183    // OpenCode Go presets
184    presets.extend(opencode_go_presets());
185
186    // Poolside presets
187    presets.extend(poolside_presets());
188
189    // StepFun presets
190    presets.extend(stepfun_presets());
191
192    // Evolink presets
193    presets.extend(evolink_presets());
194
195    presets
196}
197
198/// Get presets for a specific provider
199pub fn presets_for_provider(provider: Provider) -> Vec<ModelPreset> {
200    match provider {
201        Provider::Gemini => gemini_presets(),
202        Provider::OpenAI => openai_presets(),
203        Provider::Anthropic => anthropic_presets(),
204        Provider::Copilot => copilot_presets(),
205        Provider::DeepSeek => deepseek_presets(),
206        Provider::ZAI => zai_presets(),
207        Provider::Minimax => minimax_presets(),
208        Provider::OpenRouter => openrouter_presets(),
209        Provider::Ollama => ollama_presets(),
210        Provider::LmStudio => lmstudio_presets(),
211        Provider::LlamaCpp => llamacpp_presets(),
212        Provider::Moonshot => moonshot_presets(),
213        Provider::Mistral => mistral_presets(),
214        Provider::HuggingFace => huggingface_presets(),
215        Provider::OpenCodeZen => opencode_zen_presets(),
216        Provider::OpenCodeGo => opencode_go_presets(),
217        Provider::MiMo => mimo_presets(),
218        Provider::Qwen => qwen_presets(),
219        Provider::StepFun => stepfun_presets(),
220        Provider::Evolink => evolink_presets(),
221        Provider::Poolside => poolside_presets(),
222    }
223}
224
225fn copilot_presets() -> Vec<ModelPreset> {
226    vec![ModelPreset {
227        id: copilot_models::AUTO.to_string(),
228        model: copilot_models::AUTO.to_string(),
229        display_name: "GitHub Copilot Auto".to_string(),
230        description:
231            "Official GitHub Copilot preview provider via the Copilot CLI with automatic model selection."
232                .to_string(),
233        provider: Provider::Copilot,
234        default_reasoning_effort: ReasoningEffortLevel::Medium,
235        supported_reasoning_efforts: Vec::new(),
236        is_default: true,
237        upgrade: None,
238        show_in_picker: true,
239        supported_in_api: true,
240        context_window: Some(400_000),
241    }]
242}
243
244fn gemini_presets() -> Vec<ModelPreset> {
245    vec![ModelPreset {
246        id: "gemini-3-flash-preview".to_string(),
247        model: "gemini-3-flash-preview".to_string(),
248        display_name: "Gemini 3 Flash Preview".to_string(),
249        description: "Most intelligent model built for speed with superior search and grounding"
250            .to_string(),
251        provider: Provider::Gemini,
252        default_reasoning_effort: ReasoningEffortLevel::Medium,
253        supported_reasoning_efforts: vec![
254            ReasoningEffortPreset {
255                effort: ReasoningEffortLevel::Low,
256                description: "Fast responses".to_string(),
257            },
258            ReasoningEffortPreset {
259                effort: ReasoningEffortLevel::Medium,
260                description: "Balanced reasoning".to_string(),
261            },
262            ReasoningEffortPreset {
263                effort: ReasoningEffortLevel::High,
264                description: "Deep reasoning".to_string(),
265            },
266        ],
267        is_default: true,
268        upgrade: None,
269        show_in_picker: true,
270        supported_in_api: true,
271        context_window: Some(1_048_576),
272    }]
273}
274
275fn reasoning_preset(
276    effort: ReasoningEffortLevel,
277    description: &'static str,
278) -> ReasoningEffortPreset {
279    ReasoningEffortPreset {
280        effort,
281        description: description.to_string(),
282    }
283}
284
285fn openai_reasoning_efforts(include_none: bool, include_xhigh: bool) -> Vec<ReasoningEffortPreset> {
286    let mut efforts = Vec::new();
287    if include_none {
288        efforts.push(reasoning_preset(
289            ReasoningEffortLevel::None,
290            "Lowest latency",
291        ));
292    }
293    efforts.push(reasoning_preset(ReasoningEffortLevel::Low, "Fast"));
294    efforts.push(reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"));
295    efforts.push(reasoning_preset(ReasoningEffortLevel::High, "Deep"));
296    if include_xhigh {
297        efforts.push(reasoning_preset(
298            ReasoningEffortLevel::XHigh,
299            "Maximum reasoning",
300        ));
301    }
302    efforts
303}
304
305fn openai_presets() -> Vec<ModelPreset> {
306    vec![
307        ModelPreset {
308            id: "gpt-5.4".to_string(),
309            model: "gpt-5.4".to_string(),
310            display_name: "GPT-5.4".to_string(),
311            description: "Frontier model for complex professional work".to_string(),
312            provider: Provider::OpenAI,
313            default_reasoning_effort: ReasoningEffortLevel::None,
314            supported_reasoning_efforts: openai_reasoning_efforts(true, true),
315            is_default: true,
316            upgrade: None,
317            show_in_picker: true,
318            supported_in_api: true,
319            context_window: Some(1_050_000),
320        },
321        ModelPreset {
322            id: "gpt-5.4-pro".to_string(),
323            model: "gpt-5.4-pro".to_string(),
324            display_name: "GPT-5.4 Pro".to_string(),
325            description: "Higher-compute GPT-5.4 variant for tougher problems".to_string(),
326            provider: Provider::OpenAI,
327            default_reasoning_effort: ReasoningEffortLevel::Medium,
328            supported_reasoning_efforts: vec![
329                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
330                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
331                reasoning_preset(ReasoningEffortLevel::XHigh, "Maximum reasoning"),
332            ],
333            is_default: false,
334            upgrade: None,
335            show_in_picker: true,
336            supported_in_api: true,
337            context_window: Some(1_050_000),
338        },
339        ModelPreset {
340            id: "gpt-5.3-codex".to_string(),
341            model: "gpt-5.3-codex".to_string(),
342            display_name: "GPT-5.3 Codex".to_string(),
343            description: "GPT-5.3 variant optimized for agentic coding with xhigh reasoning"
344                .to_string(),
345            provider: Provider::OpenAI,
346            default_reasoning_effort: ReasoningEffortLevel::High,
347            supported_reasoning_efforts: openai_reasoning_efforts(true, true),
348            is_default: false,
349            upgrade: None,
350            show_in_picker: true,
351            supported_in_api: true,
352            context_window: Some(272_000),
353        },
354        ModelPreset {
355            id: "gpt-5.2-codex".to_string(),
356            model: "gpt-5.2-codex".to_string(),
357            display_name: "GPT-5.2 Codex".to_string(),
358            description: "GPT-5.2 variant optimized for agentic coding with xhigh reasoning"
359                .to_string(),
360            provider: Provider::OpenAI,
361            default_reasoning_effort: ReasoningEffortLevel::High,
362            supported_reasoning_efforts: openai_reasoning_efforts(true, true),
363            is_default: false,
364            upgrade: None,
365            show_in_picker: true,
366            supported_in_api: true,
367            context_window: Some(272_000),
368        },
369        ModelPreset {
370            id: "gpt-5.1-codex".to_string(),
371            model: "gpt-5.1-codex".to_string(),
372            display_name: "GPT-5.1 Codex".to_string(),
373            description: "GPT-5.1 variant optimized for agentic coding".to_string(),
374            provider: Provider::OpenAI,
375            default_reasoning_effort: ReasoningEffortLevel::High,
376            supported_reasoning_efforts: openai_reasoning_efforts(false, false),
377            is_default: false,
378            upgrade: None,
379            show_in_picker: true,
380            supported_in_api: true,
381            context_window: Some(272_000),
382        },
383        ModelPreset {
384            id: "gpt-5.1-codex-max".to_string(),
385            model: "gpt-5.1-codex-max".to_string(),
386            display_name: "GPT-5.1 Codex Max".to_string(),
387            description:
388                "Higher-compute GPT-5.1 Codex variant for longer-running engineering tasks"
389                    .to_string(),
390            provider: Provider::OpenAI,
391            default_reasoning_effort: ReasoningEffortLevel::High,
392            supported_reasoning_efforts: openai_reasoning_efforts(false, false),
393            is_default: false,
394            upgrade: None,
395            show_in_picker: true,
396            supported_in_api: true,
397            context_window: Some(272_000),
398        },
399        ModelPreset {
400            id: "gpt-5-codex".to_string(),
401            model: "gpt-5-codex".to_string(),
402            display_name: "GPT-5 Codex".to_string(),
403            description: "GPT-5 variant optimized for agentic coding".to_string(),
404            provider: Provider::OpenAI,
405            default_reasoning_effort: ReasoningEffortLevel::High,
406            supported_reasoning_efforts: openai_reasoning_efforts(false, false),
407            is_default: false,
408            upgrade: None,
409            show_in_picker: true,
410            supported_in_api: true,
411            context_window: Some(272_000),
412        },
413        ModelPreset {
414            id: "gpt-5.2".to_string(),
415            model: "gpt-5.2".to_string(),
416            display_name: "GPT-5.2".to_string(),
417            description: "Latest frontier model with improved reasoning and coding".to_string(),
418            provider: Provider::OpenAI,
419            default_reasoning_effort: ReasoningEffortLevel::None,
420            supported_reasoning_efforts: openai_reasoning_efforts(true, true),
421            is_default: false,
422            upgrade: None,
423            show_in_picker: true,
424            supported_in_api: true,
425            context_window: Some(272_000),
426        },
427        ModelPreset {
428            id: "gpt-5".to_string(),
429            model: "gpt-5".to_string(),
430            display_name: "GPT-5".to_string(),
431            description: "Latest most capable OpenAI model".to_string(),
432            provider: Provider::OpenAI,
433            default_reasoning_effort: ReasoningEffortLevel::Medium,
434            supported_reasoning_efforts: vec![
435                ReasoningEffortPreset {
436                    effort: ReasoningEffortLevel::Low,
437                    description: "Fast".to_string(),
438                },
439                ReasoningEffortPreset {
440                    effort: ReasoningEffortLevel::Medium,
441                    description: "Balanced".to_string(),
442                },
443                ReasoningEffortPreset {
444                    effort: ReasoningEffortLevel::High,
445                    description: "Deep".to_string(),
446                },
447            ],
448            is_default: false,
449            upgrade: None,
450            show_in_picker: true,
451            supported_in_api: true,
452            context_window: Some(200_000),
453        },
454        ModelPreset {
455            id: "gpt-5-mini".to_string(),
456            model: "gpt-5-mini".to_string(),
457            display_name: "GPT-5 Mini".to_string(),
458            description: "Efficient GPT-5 variant".to_string(),
459            provider: Provider::OpenAI,
460            default_reasoning_effort: ReasoningEffortLevel::Medium,
461            supported_reasoning_efforts: vec![ReasoningEffortPreset {
462                effort: ReasoningEffortLevel::Medium,
463                description: "Balanced".to_string(),
464            }],
465            is_default: false,
466            upgrade: None,
467            show_in_picker: true,
468            supported_in_api: true,
469            context_window: Some(128_000),
470        },
471        ModelPreset {
472            id: "gpt-5-nano".to_string(),
473            model: "gpt-5-nano".to_string(),
474            display_name: "GPT-5 Nano".to_string(),
475            description: "Most cost-effective GPT-5 variant for high-volume tasks".to_string(),
476            provider: Provider::OpenAI,
477            default_reasoning_effort: ReasoningEffortLevel::Medium,
478            supported_reasoning_efforts: vec![ReasoningEffortPreset {
479                effort: ReasoningEffortLevel::Medium,
480                description: "Balanced".to_string(),
481            }],
482            is_default: false,
483            upgrade: None,
484            show_in_picker: true,
485            supported_in_api: true,
486            context_window: Some(200_000),
487        },
488        ModelPreset {
489            id: "o3".to_string(),
490            model: "o3".to_string(),
491            display_name: "o3".to_string(),
492            description: "OpenAI reasoning model for harder multi-step work".to_string(),
493            provider: Provider::OpenAI,
494            default_reasoning_effort: ReasoningEffortLevel::Medium,
495            supported_reasoning_efforts: openai_reasoning_efforts(false, false),
496            is_default: false,
497            upgrade: None,
498            show_in_picker: true,
499            supported_in_api: true,
500            context_window: None,
501        },
502        ModelPreset {
503            id: "o4-mini".to_string(),
504            model: "o4-mini".to_string(),
505            display_name: "o4-mini".to_string(),
506            description: "Smaller OpenAI reasoning model with strong tool use".to_string(),
507            provider: Provider::OpenAI,
508            default_reasoning_effort: ReasoningEffortLevel::Medium,
509            supported_reasoning_efforts: openai_reasoning_efforts(false, false),
510            is_default: false,
511            upgrade: None,
512            show_in_picker: true,
513            supported_in_api: true,
514            context_window: None,
515        },
516        ModelPreset {
517            id: "gpt-oss-20b".to_string(),
518            model: "gpt-oss-20b".to_string(),
519            display_name: "GPT-OSS 20B".to_string(),
520            description: "OpenAI's open-source 20B parameter model".to_string(),
521            provider: Provider::OpenAI,
522            default_reasoning_effort: ReasoningEffortLevel::Medium,
523            supported_reasoning_efforts: vec![
524                ReasoningEffortPreset {
525                    effort: ReasoningEffortLevel::Low,
526                    description: "Fast".to_string(),
527                },
528                ReasoningEffortPreset {
529                    effort: ReasoningEffortLevel::Medium,
530                    description: "Balanced".to_string(),
531                },
532                ReasoningEffortPreset {
533                    effort: ReasoningEffortLevel::High,
534                    description: "Deep".to_string(),
535                },
536            ],
537            is_default: false,
538            upgrade: None,
539            show_in_picker: true,
540            supported_in_api: true,
541            context_window: Some(131_072),
542        },
543        ModelPreset {
544            id: "gpt-oss-120b".to_string(),
545            model: "gpt-oss-120b".to_string(),
546            display_name: "GPT-OSS 120B".to_string(),
547            description: "OpenAI's open-source 120B parameter model with advanced reasoning"
548                .to_string(),
549            provider: Provider::OpenAI,
550            default_reasoning_effort: ReasoningEffortLevel::Medium,
551            supported_reasoning_efforts: vec![
552                ReasoningEffortPreset {
553                    effort: ReasoningEffortLevel::Low,
554                    description: "Fast".to_string(),
555                },
556                ReasoningEffortPreset {
557                    effort: ReasoningEffortLevel::Medium,
558                    description: "Balanced".to_string(),
559                },
560                ReasoningEffortPreset {
561                    effort: ReasoningEffortLevel::High,
562                    description: "Deep".to_string(),
563                },
564            ],
565            is_default: false,
566            upgrade: None,
567            show_in_picker: true,
568            supported_in_api: true,
569            context_window: Some(131_072),
570        },
571    ]
572}
573
574fn anthropic_presets() -> Vec<ModelPreset> {
575    vec![
576        ModelPreset {
577            id: "claude-fable-5".to_string(),
578            model: "claude-fable-5".to_string(),
579            display_name: "Claude Fable 5".to_string(),
580            description:
581                "Anthropic's most capable widely released model with 1M context, 128k output, and always-on adaptive thinking"
582                    .to_string(),
583            provider: Provider::Anthropic,
584            default_reasoning_effort: ReasoningEffortLevel::XHigh,
585            supported_reasoning_efforts: vec![
586                ReasoningEffortPreset {
587                    effort: ReasoningEffortLevel::Low,
588                    description: "Fast adaptive effort".to_string(),
589                },
590                ReasoningEffortPreset {
591                    effort: ReasoningEffortLevel::Medium,
592                    description: "Balanced adaptive effort".to_string(),
593                },
594                ReasoningEffortPreset {
595                    effort: ReasoningEffortLevel::High,
596                    description: "Deep adaptive effort".to_string(),
597                },
598                ReasoningEffortPreset {
599                    effort: ReasoningEffortLevel::XHigh,
600                    description: "Recommended Fable 5 effort for coding and agentic work".to_string(),
601                },
602                ReasoningEffortPreset {
603                    effort: ReasoningEffortLevel::Max,
604                    description: "Maximum adaptive effort for intelligence-demanding tasks"
605                        .to_string(),
606                },
607            ],
608            is_default: true,
609            upgrade: None,
610            show_in_picker: true,
611            supported_in_api: true,
612            context_window: Some(1_000_000),
613        },
614        ModelPreset {
615            id: "claude-opus-4-8".to_string(),
616            model: "claude-opus-4-8".to_string(),
617            display_name: "Claude Opus 4.8".to_string(),
618            description:
619                "Anthropic's most capable model for complex reasoning, long-horizon agentic coding, and high-autonomy work"
620                    .to_string(),
621            provider: Provider::Anthropic,
622            default_reasoning_effort: ReasoningEffortLevel::XHigh,
623            supported_reasoning_efforts: vec![
624                ReasoningEffortPreset {
625                    effort: ReasoningEffortLevel::Low,
626                    description: "Fast adaptive effort".to_string(),
627                },
628                ReasoningEffortPreset {
629                    effort: ReasoningEffortLevel::Medium,
630                    description: "Balanced adaptive effort".to_string(),
631                },
632                ReasoningEffortPreset {
633                    effort: ReasoningEffortLevel::High,
634                    description: "Deep adaptive effort".to_string(),
635                },
636                ReasoningEffortPreset {
637                    effort: ReasoningEffortLevel::XHigh,
638                    description: "Recommended Opus 4.8 effort for coding and agentic work".to_string(),
639                },
640                ReasoningEffortPreset {
641                    effort: ReasoningEffortLevel::Max,
642                    description: "Maximum adaptive effort for intelligence-demanding tasks"
643                        .to_string(),
644                },
645            ],
646            is_default: false,
647            upgrade: None,
648            show_in_picker: true,
649            supported_in_api: true,
650            context_window: Some(1_000_000),
651        },
652        ModelPreset {
653            id: "claude-sonnet-4-6".to_string(),
654            model: "claude-sonnet-4-6".to_string(),
655            display_name: "Claude Sonnet 4.6".to_string(),
656            description:
657                "The best combination of speed and intelligence. Supports extended thinking and adaptive thinking with 1M context."
658                    .to_string(),
659            provider: Provider::Anthropic,
660            default_reasoning_effort: ReasoningEffortLevel::High,
661            supported_reasoning_efforts: vec![
662                ReasoningEffortPreset {
663                    effort: ReasoningEffortLevel::Low,
664                    description: "Fast adaptive effort".to_string(),
665                },
666                ReasoningEffortPreset {
667                    effort: ReasoningEffortLevel::Medium,
668                    description: "Balanced adaptive effort".to_string(),
669                },
670                ReasoningEffortPreset {
671                    effort: ReasoningEffortLevel::High,
672                    description: "Default adaptive effort".to_string(),
673                },
674                ReasoningEffortPreset {
675                    effort: ReasoningEffortLevel::Max,
676                    description: "Maximum adaptive effort".to_string(),
677                },
678            ],
679            is_default: false,
680            upgrade: None,
681            show_in_picker: true,
682            supported_in_api: true,
683            context_window: Some(1_000_000),
684        },
685        ModelPreset {
686            id: "claude-haiku-4-5".to_string(),
687            model: "claude-haiku-4-5".to_string(),
688            display_name: "Claude Haiku 4.5".to_string(),
689            description: "The fastest model with near-frontier intelligence. Supports extended thinking with manual budget."
690                .to_string(),
691            provider: Provider::Anthropic,
692            default_reasoning_effort: ReasoningEffortLevel::Medium,
693            supported_reasoning_efforts: Vec::new(),
694            is_default: false,
695            upgrade: None,
696            show_in_picker: true,
697            supported_in_api: true,
698            context_window: Some(200_000),
699        },
700    ]
701}
702
703fn deepseek_presets() -> Vec<ModelPreset> {
704    vec![
705        ModelPreset {
706            id: "deepseek-v4-pro".to_string(),
707            model: "deepseek-v4-pro".to_string(),
708            display_name: "DeepSeek V4 Pro".to_string(),
709            description: "High-performance reasoning model with advanced thinking capabilities"
710                .to_string(),
711            provider: Provider::DeepSeek,
712            default_reasoning_effort: ReasoningEffortLevel::High,
713            supported_reasoning_efforts: vec![
714                ReasoningEffortPreset {
715                    effort: ReasoningEffortLevel::High,
716                    description: "Balanced".to_string(),
717                },
718                ReasoningEffortPreset {
719                    effort: ReasoningEffortLevel::Max,
720                    description: "Maximum thinking".to_string(),
721                },
722            ],
723            is_default: true,
724            upgrade: None,
725            show_in_picker: true,
726            supported_in_api: true,
727            context_window: Some(1_000_000),
728        },
729        ModelPreset {
730            id: "deepseek-v4-flash".to_string(),
731            model: "deepseek-v4-flash".to_string(),
732            display_name: "DeepSeek V4 Flash".to_string(),
733            description: "Fast inference model for cost-effective reasoning tasks".to_string(),
734            provider: Provider::DeepSeek,
735            default_reasoning_effort: ReasoningEffortLevel::High,
736            supported_reasoning_efforts: vec![
737                ReasoningEffortPreset {
738                    effort: ReasoningEffortLevel::High,
739                    description: "Balanced".to_string(),
740                },
741                ReasoningEffortPreset {
742                    effort: ReasoningEffortLevel::Max,
743                    description: "Maximum thinking".to_string(),
744                },
745            ],
746            is_default: false,
747            upgrade: None,
748            show_in_picker: true,
749            supported_in_api: true,
750            context_window: Some(1_000_000),
751        },
752    ]
753}
754
755fn zai_presets() -> Vec<ModelPreset> {
756    vec![
757        ModelPreset {
758            id: "glm-5.1".to_string(),
759            model: "glm-5.1".to_string(),
760            display_name: "GLM-5.1".to_string(),
761            description:
762                "Z.ai's next-gen foundation model with improved reasoning and agent capabilities"
763                    .to_string(),
764            provider: Provider::ZAI,
765            default_reasoning_effort: ReasoningEffortLevel::Medium,
766            supported_reasoning_efforts: vec![
767                ReasoningEffortPreset {
768                    effort: ReasoningEffortLevel::Medium,
769                    description: "Balanced".to_string(),
770                },
771                ReasoningEffortPreset {
772                    effort: ReasoningEffortLevel::High,
773                    description: "Deep thinking".to_string(),
774                },
775            ],
776            is_default: true,
777            upgrade: None,
778            show_in_picker: true,
779            supported_in_api: true,
780            context_window: Some(200_000),
781        },
782    ]
783}
784
785fn mistral_presets() -> Vec<ModelPreset> {
786    vec![
787        ModelPreset {
788            id: "mistral-large-2512".to_string(),
789            model: "mistral-large-2512".to_string(),
790            display_name: "Mistral Large 3".to_string(),
791            description:
792                "State-of-the-art open-weight general-purpose multimodal model (41B active, 675B total)".to_string(),
793            provider: Provider::Mistral,
794            default_reasoning_effort: ReasoningEffortLevel::Medium,
795            supported_reasoning_efforts: vec![
796                ReasoningEffortPreset {
797                    effort: ReasoningEffortLevel::Medium,
798                    description: "Balanced".to_string(),
799                },
800                ReasoningEffortPreset {
801                    effort: ReasoningEffortLevel::High,
802                    description: "Deep".to_string(),
803                },
804            ],
805            is_default: true,
806            upgrade: None,
807            show_in_picker: true,
808            supported_in_api: true,
809            context_window: Some(256_000),
810        },
811        ModelPreset {
812            id: "mistral-medium-3-5".to_string(),
813            model: "mistral-medium-3-5".to_string(),
814            display_name: "Mistral Medium 3.5".to_string(),
815            description:
816                "Frontier-class multimodal model optimized for agentic and coding use cases (256k context)"
817                    .to_string(),
818            provider: Provider::Mistral,
819            default_reasoning_effort: ReasoningEffortLevel::Medium,
820            supported_reasoning_efforts: vec![
821                ReasoningEffortPreset {
822                    effort: ReasoningEffortLevel::Medium,
823                    description: "Balanced".to_string(),
824                },
825                ReasoningEffortPreset {
826                    effort: ReasoningEffortLevel::High,
827                    description: "Deep".to_string(),
828                },
829            ],
830            is_default: false,
831            upgrade: None,
832            show_in_picker: true,
833            supported_in_api: true,
834            context_window: Some(256_000),
835        },
836        ModelPreset {
837            id: "mistral-small-2603".to_string(),
838            model: "mistral-small-2603".to_string(),
839            display_name: "Mistral Small 4".to_string(),
840            description:
841                "Hybrid model unifying instruct, reasoning, and coding (119B params, 6.5B active)"
842                    .to_string(),
843            provider: Provider::Mistral,
844            default_reasoning_effort: ReasoningEffortLevel::Medium,
845            supported_reasoning_efforts: vec![
846                ReasoningEffortPreset {
847                    effort: ReasoningEffortLevel::Medium,
848                    description: "Balanced".to_string(),
849                },
850                ReasoningEffortPreset {
851                    effort: ReasoningEffortLevel::High,
852                    description: "Deep".to_string(),
853                },
854            ],
855            is_default: false,
856            upgrade: None,
857            show_in_picker: true,
858            supported_in_api: true,
859            context_window: Some(256_000),
860        },
861        ModelPreset {
862            id: "mistral-medium-2508".to_string(),
863            model: "mistral-medium-2508".to_string(),
864            display_name: "Mistral Medium 3.1".to_string(),
865            description: "Frontier-class multimodal model with 256k context".to_string(),
866            provider: Provider::Mistral,
867            default_reasoning_effort: ReasoningEffortLevel::Medium,
868            supported_reasoning_efforts: vec![ReasoningEffortPreset {
869                effort: ReasoningEffortLevel::Medium,
870                description: "Balanced".to_string(),
871            }],
872            is_default: false,
873            upgrade: None,
874            show_in_picker: true,
875            supported_in_api: true,
876            context_window: Some(256_000),
877        },
878        ModelPreset {
879            id: "codestral-2508".to_string(),
880            model: "codestral-2508".to_string(),
881            display_name: "Codestral".to_string(),
882            description: "Cutting-edge language model for code completion".to_string(),
883            provider: Provider::Mistral,
884            default_reasoning_effort: ReasoningEffortLevel::Medium,
885            supported_reasoning_efforts: Vec::new(),
886            is_default: false,
887            upgrade: None,
888            show_in_picker: true,
889            supported_in_api: true,
890            context_window: Some(256_000),
891        },
892    ]
893}
894
895fn minimax_presets() -> Vec<ModelPreset> {
896    vec![
897        ModelPreset {
898            id: "minimax-m3".to_string(),
899            model: "MiniMax-M3".to_string(),
900            display_name: "MiniMax M3".to_string(),
901            description: "Frontier multimodal coding model with 1M context".to_string(),
902            provider: Provider::Minimax,
903            default_reasoning_effort: ReasoningEffortLevel::Medium,
904            supported_reasoning_efforts: vec![
905                ReasoningEffortPreset {
906                    effort: ReasoningEffortLevel::Medium,
907                    description: "Balanced".to_string(),
908                },
909                ReasoningEffortPreset {
910                    effort: ReasoningEffortLevel::High,
911                    description: "Deep".to_string(),
912                },
913            ],
914            is_default: true,
915            upgrade: None,
916            show_in_picker: true,
917            supported_in_api: true,
918            context_window: Some(1_000_000),
919        },
920    ]
921}
922
923fn openrouter_presets() -> Vec<ModelPreset> {
924    vec![
925        ModelPreset {
926            id: "openrouter/deepseek/deepseek-chat".to_string(),
927            model: "deepseek/deepseek-chat".to_string(),
928            display_name: "DeepSeek V3.2 (OpenRouter)".to_string(),
929            description: "DeepSeek via OpenRouter".to_string(),
930            provider: Provider::OpenRouter,
931            default_reasoning_effort: ReasoningEffortLevel::Medium,
932            supported_reasoning_efforts: vec![ReasoningEffortPreset {
933                effort: ReasoningEffortLevel::Medium,
934                description: "Balanced".to_string(),
935            }],
936            is_default: false,
937            upgrade: None,
938            show_in_picker: true,
939            supported_in_api: true,
940            context_window: Some(128_000),
941        },
942        ModelPreset {
943            id: "openrouter/moonshotai/kimi-k2.6".to_string(),
944            model: "moonshotai/kimi-k2.6".to_string(),
945            display_name: "Kimi K2.6 (OpenRouter)".to_string(),
946            description: "Kimi K2.6 multimodal agentic model via OpenRouter".to_string(),
947            provider: Provider::OpenRouter,
948            default_reasoning_effort: ReasoningEffortLevel::Medium,
949            supported_reasoning_efforts: vec![ReasoningEffortPreset {
950                effort: ReasoningEffortLevel::Medium,
951                description: "Balanced".to_string(),
952            }],
953            is_default: false,
954            upgrade: None,
955            show_in_picker: true,
956            supported_in_api: true,
957            context_window: Some(262_144),
958        },
959        ModelPreset {
960            id: "openrouter/moonshotai/kimi-k2.7-code".to_string(),
961            model: "moonshotai/kimi-k2.7-code".to_string(),
962            display_name: "Kimi K2.7 Code (OpenRouter)".to_string(),
963            description: "Kimi K2.7 Code most capable coding model with long-horizon coding breakthrough via OpenRouter".to_string(),
964            provider: Provider::OpenRouter,
965            default_reasoning_effort: ReasoningEffortLevel::Medium,
966            supported_reasoning_efforts: vec![ReasoningEffortPreset {
967                effort: ReasoningEffortLevel::Medium,
968                description: "Balanced".to_string(),
969            }],
970            is_default: false,
971            upgrade: None,
972            show_in_picker: true,
973            supported_in_api: true,
974            context_window: Some(262_144),
975        },
976        ModelPreset {
977            id: "openrouter/qwen/qwen3.7-max".to_string(),
978            model: "qwen/qwen3.7-max".to_string(),
979            display_name: "Qwen3.7 Max (OpenRouter)".to_string(),
980            description: "Qwen3.7 Max flagship model for coding and agentic workloads via OpenRouter".to_string(),
981            provider: Provider::OpenRouter,
982            default_reasoning_effort: ReasoningEffortLevel::Medium,
983            supported_reasoning_efforts: vec![ReasoningEffortPreset {
984                effort: ReasoningEffortLevel::Medium,
985                description: "Balanced".to_string(),
986            }],
987            is_default: false,
988            upgrade: None,
989            show_in_picker: true,
990            supported_in_api: true,
991            context_window: Some(1_000_000),
992        },
993        ModelPreset {
994            id: "openrouter/tencent/hy3-preview".to_string(),
995            model: "tencent/hy3-preview".to_string(),
996            display_name: "Hy3 Preview (OpenRouter)".to_string(),
997            description: "Tencent Hy3 high-efficiency MoE model with configurable reasoning via OpenRouter".to_string(),
998            provider: Provider::OpenRouter,
999            default_reasoning_effort: ReasoningEffortLevel::Medium,
1000            supported_reasoning_efforts: vec![
1001                ReasoningEffortPreset {
1002                    effort: ReasoningEffortLevel::Low,
1003                    description: "Fast".to_string(),
1004                },
1005                ReasoningEffortPreset {
1006                    effort: ReasoningEffortLevel::Medium,
1007                    description: "Balanced".to_string(),
1008                },
1009                ReasoningEffortPreset {
1010                    effort: ReasoningEffortLevel::High,
1011                    description: "Deep".to_string(),
1012                },
1013            ],
1014            is_default: false,
1015            upgrade: None,
1016            show_in_picker: true,
1017            supported_in_api: true,
1018            context_window: Some(262_144),
1019        },
1020        ModelPreset {
1021            id: "openrouter/x-ai/grok-build-0.1".to_string(),
1022            model: "x-ai/grok-build-0.1".to_string(),
1023            display_name: "Grok Build 0.1 (OpenRouter)".to_string(),
1024            description: "xAI Grok Build 0.1 coding model for agentic software engineering via OpenRouter".to_string(),
1025            provider: Provider::OpenRouter,
1026            default_reasoning_effort: ReasoningEffortLevel::Medium,
1027            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1028                effort: ReasoningEffortLevel::Medium,
1029                description: "Balanced".to_string(),
1030            }],
1031            is_default: false,
1032            upgrade: None,
1033            show_in_picker: true,
1034            supported_in_api: true,
1035            context_window: Some(256_000),
1036        },
1037        ModelPreset {
1038            id: "openrouter/xiaomi/mimo-v2.5".to_string(),
1039            model: "xiaomi/mimo-v2.5".to_string(),
1040            display_name: "MiMo-V2.5 (OpenRouter)".to_string(),
1041            description: "Xiaomi MiMo-V2.5 omnimodal agentic model for complex software engineering via OpenRouter".to_string(),
1042            provider: Provider::OpenRouter,
1043            default_reasoning_effort: ReasoningEffortLevel::Medium,
1044            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1045                effort: ReasoningEffortLevel::Medium,
1046                description: "Balanced".to_string(),
1047            }],
1048            is_default: false,
1049            upgrade: None,
1050            show_in_picker: true,
1051            supported_in_api: true,
1052            context_window: Some(1_000_000),
1053        },
1054        ModelPreset {
1055            id: "openrouter/xiaomi/mimo-v2.5-pro".to_string(),
1056            model: "xiaomi/mimo-v2.5-pro".to_string(),
1057            display_name: "MiMo-V2.5-Pro (OpenRouter)".to_string(),
1058            description: "Xiaomi MiMo-V2.5-Pro flagship agentic model for complex software engineering via OpenRouter".to_string(),
1059            provider: Provider::OpenRouter,
1060            default_reasoning_effort: ReasoningEffortLevel::Medium,
1061            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1062                effort: ReasoningEffortLevel::Medium,
1063                description: "Balanced".to_string(),
1064            }],
1065            is_default: true,
1066            upgrade: None,
1067            show_in_picker: true,
1068            supported_in_api: true,
1069            context_window: Some(1_000_000),
1070        },
1071        ModelPreset {
1072            id: "openrouter/poolside/laguna-m.1:free".to_string(),
1073            model: "poolside/laguna-m.1:free".to_string(),
1074            display_name: "Laguna M.1 free (OpenRouter)".to_string(),
1075            description: "Poolside Laguna M.1 flagship free coding agent model via OpenRouter".to_string(),
1076            provider: Provider::OpenRouter,
1077            default_reasoning_effort: ReasoningEffortLevel::Medium,
1078            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1079                effort: ReasoningEffortLevel::Medium,
1080                description: "Balanced".to_string(),
1081            }],
1082            is_default: false,
1083            upgrade: None,
1084            show_in_picker: true,
1085            supported_in_api: true,
1086            context_window: Some(262_144),
1087        },
1088    ]
1089}
1090
1091fn ollama_presets() -> Vec<ModelPreset> {
1092    vec![
1093        ModelPreset {
1094            id: "ollama/gpt-oss:20b".to_string(),
1095            model: "gpt-oss:20b".to_string(),
1096            display_name: "GPT-OSS 20B (Ollama)".to_string(),
1097            description: "Open-weight GPT-OSS served locally".to_string(),
1098            provider: Provider::Ollama,
1099            default_reasoning_effort: ReasoningEffortLevel::Medium,
1100            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1101                effort: ReasoningEffortLevel::Medium,
1102                description: "Balanced".to_string(),
1103            }],
1104            is_default: true,
1105            upgrade: None,
1106            show_in_picker: true,
1107            supported_in_api: true,
1108            context_window: Some(96_000),
1109        },
1110        ModelPreset {
1111            id: "ollama/deepseek-v4-flash:cloud".to_string(),
1112            model: "deepseek-v4-flash:cloud".to_string(),
1113            display_name: "DeepSeek V4 Flash (Ollama)".to_string(),
1114            description: "Fast inference DeepSeek V4 Flash model via Ollama Cloud".to_string(),
1115            provider: Provider::Ollama,
1116            default_reasoning_effort: ReasoningEffortLevel::Medium,
1117            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1118                effort: ReasoningEffortLevel::Medium,
1119                description: "Balanced".to_string(),
1120            }],
1121            is_default: false,
1122            upgrade: None,
1123            show_in_picker: true,
1124            supported_in_api: true,
1125            context_window: Some(128_000),
1126        },
1127        ModelPreset {
1128            id: "ollama/deepseek-v4-pro:cloud".to_string(),
1129            model: "deepseek-v4-pro:cloud".to_string(),
1130            display_name: "DeepSeek V4 Pro (Ollama)".to_string(),
1131            description: "High-performance DeepSeek V4 Pro model via Ollama Cloud".to_string(),
1132            provider: Provider::Ollama,
1133            default_reasoning_effort: ReasoningEffortLevel::Medium,
1134            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1135                effort: ReasoningEffortLevel::Medium,
1136                description: "Balanced".to_string(),
1137            }],
1138            is_default: false,
1139            upgrade: None,
1140            show_in_picker: true,
1141            supported_in_api: true,
1142            context_window: Some(128_000),
1143        },
1144        ModelPreset {
1145            id: "ollama/nemotron-3-ultra:cloud".to_string(),
1146            model: "nemotron-3-ultra:cloud".to_string(),
1147            display_name: "Nemotron 3 Ultra (Ollama)".to_string(),
1148            description: "NVIDIA Nemotron 3 Ultra 550B for high-throughput reasoning and long-running agent workflows via Ollama Cloud".to_string(),
1149            provider: Provider::Ollama,
1150            default_reasoning_effort: ReasoningEffortLevel::Medium,
1151            supported_reasoning_efforts: vec![
1152                ReasoningEffortPreset {
1153                    effort: ReasoningEffortLevel::Medium,
1154                    description: "Balanced".to_string(),
1155                },
1156                ReasoningEffortPreset {
1157                    effort: ReasoningEffortLevel::High,
1158                    description: "Deep".to_string(),
1159                },
1160            ],
1161            is_default: false,
1162            upgrade: None,
1163            show_in_picker: true,
1164            supported_in_api: true,
1165            context_window: Some(256_000),
1166        },
1167        ModelPreset {
1168            id: "ollama/gemma4".to_string(),
1169            model: "gemma4".to_string(),
1170            display_name: "Gemma 4 (Ollama)".to_string(),
1171            description: "Google Gemma 4 for reasoning, agentic workflows, coding, and multimodal understanding".to_string(),
1172            provider: Provider::Ollama,
1173            default_reasoning_effort: ReasoningEffortLevel::Medium,
1174            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1175                effort: ReasoningEffortLevel::Medium,
1176                description: "Balanced".to_string(),
1177            }],
1178            is_default: false,
1179            upgrade: None,
1180            show_in_picker: true,
1181            supported_in_api: true,
1182            context_window: Some(128_000),
1183        },
1184        ModelPreset {
1185            id: "ollama/minimax-m3:cloud".to_string(),
1186            model: "minimax-m3:cloud".to_string(),
1187            display_name: "MiniMax-M3 (Ollama)".to_string(),
1188            description: "Cloud-hosted MiniMax-M3 model via Ollama Cloud".to_string(),
1189            provider: Provider::Ollama,
1190            default_reasoning_effort: ReasoningEffortLevel::Medium,
1191            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1192                effort: ReasoningEffortLevel::Medium,
1193                description: "Balanced".to_string(),
1194            }],
1195            is_default: false,
1196            upgrade: None,
1197            show_in_picker: true,
1198            supported_in_api: true,
1199            context_window: Some(131_072),
1200        },
1201    ]
1202}
1203
1204fn lmstudio_presets() -> Vec<ModelPreset> {
1205    use crate::config::constants::models::lmstudio as lmstudio_models;
1206    vec![
1207        ModelPreset {
1208            id: format!("lmstudio/{}", lmstudio_models::OPENAI_GPT_OSS_20B),
1209            model: lmstudio_models::OPENAI_GPT_OSS_20B.to_string(),
1210            display_name: "GPT-OSS 20B (LM Studio)".to_string(),
1211            description: "OpenAI's open-weight GPT-OSS 20B model served locally via LM Studio"
1212                .to_string(),
1213            provider: Provider::LmStudio,
1214            default_reasoning_effort: ReasoningEffortLevel::Medium,
1215            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1216                effort: ReasoningEffortLevel::Medium,
1217                description: "Balanced".to_string(),
1218            }],
1219            is_default: false,
1220            upgrade: None,
1221            show_in_picker: true,
1222            supported_in_api: true,
1223            context_window: Some(131_072),
1224        },
1225        ModelPreset {
1226            id: format!("lmstudio/{}", lmstudio_models::META_LLAMA_31_8B_INSTRUCT),
1227            model: lmstudio_models::META_LLAMA_31_8B_INSTRUCT.to_string(),
1228            display_name: "Llama 3.1 8B (LM Studio)".to_string(),
1229            description: "Meta Llama 3.1 8B Instruct for general-purpose local inference"
1230                .to_string(),
1231            provider: Provider::LmStudio,
1232            default_reasoning_effort: ReasoningEffortLevel::Medium,
1233            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1234                effort: ReasoningEffortLevel::Medium,
1235                description: "Balanced".to_string(),
1236            }],
1237            is_default: false,
1238            upgrade: None,
1239            show_in_picker: true,
1240            supported_in_api: true,
1241            context_window: Some(131_072),
1242        },
1243        ModelPreset {
1244            id: format!("lmstudio/{}", lmstudio_models::GEMMA_3_12B_IT),
1245            model: lmstudio_models::GEMMA_3_12B_IT.to_string(),
1246            display_name: "Gemma 3 12B (LM Studio)".to_string(),
1247            description: "Google Gemma 3 12B IT for local inference".to_string(),
1248            provider: Provider::LmStudio,
1249            default_reasoning_effort: ReasoningEffortLevel::Medium,
1250            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1251                effort: ReasoningEffortLevel::Medium,
1252                description: "Balanced".to_string(),
1253            }],
1254            is_default: false,
1255            upgrade: None,
1256            show_in_picker: true,
1257            supported_in_api: true,
1258            context_window: Some(32_768),
1259        },
1260    ]
1261}
1262
1263fn llamacpp_presets() -> Vec<ModelPreset> {
1264    vec![
1265        ModelPreset {
1266            id: format!("llamacpp/{}", llamacpp_models::GPT_OSS_20B),
1267            model: llamacpp_models::GPT_OSS_20B.to_string(),
1268            display_name: "GPT-OSS 20B (llama.cpp)".to_string(),
1269            description: "OpenAI's open-weight GPT-OSS 20B model served locally through llama.cpp"
1270                .to_string(),
1271            provider: Provider::LlamaCpp,
1272            default_reasoning_effort: ReasoningEffortLevel::Medium,
1273            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1274                effort: ReasoningEffortLevel::Medium,
1275                description: "Balanced".to_string(),
1276            }],
1277            is_default: true,
1278            upgrade: None,
1279            show_in_picker: true,
1280            supported_in_api: true,
1281            context_window: Some(131_072),
1282        },
1283        ModelPreset {
1284            id: format!("llamacpp/{}", llamacpp_models::GEMMA_4_26B_A4B),
1285            model: llamacpp_models::GEMMA_4_26B_A4B.to_string(),
1286            display_name: "Gemma 4 26B A4B (llama.cpp)".to_string(),
1287            description: "Gemma 4 desktop MoE model served through llama.cpp".to_string(),
1288            provider: Provider::LlamaCpp,
1289            default_reasoning_effort: ReasoningEffortLevel::Medium,
1290            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1291                effort: ReasoningEffortLevel::Medium,
1292                description: "Balanced".to_string(),
1293            }],
1294            is_default: false,
1295            upgrade: None,
1296            show_in_picker: true,
1297            supported_in_api: true,
1298            context_window: Some(262_144),
1299        },
1300        ModelPreset {
1301            id: format!("llamacpp/{}", llamacpp_models::GEMMA_4_E4B),
1302            model: llamacpp_models::GEMMA_4_E4B.to_string(),
1303            display_name: "Gemma 4 E4B (llama.cpp)".to_string(),
1304            description: "Tiny-footprint Gemma 4 model served through llama.cpp".to_string(),
1305            provider: Provider::LlamaCpp,
1306            default_reasoning_effort: ReasoningEffortLevel::Low,
1307            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1308                effort: ReasoningEffortLevel::Low,
1309                description: "Fast".to_string(),
1310            }],
1311            is_default: false,
1312            upgrade: None,
1313            show_in_picker: true,
1314            supported_in_api: true,
1315            context_window: Some(131_072),
1316        },
1317        ModelPreset {
1318            id: format!("llamacpp/{}", llamacpp_models::STEP_3_5_FLASH),
1319            model: llamacpp_models::STEP_3_5_FLASH.to_string(),
1320            display_name: "Step 3.5 Flash (llama.cpp)".to_string(),
1321            description: "StepFun's efficient reasoning model served through llama.cpp".to_string(),
1322            provider: Provider::LlamaCpp,
1323            default_reasoning_effort: ReasoningEffortLevel::Medium,
1324            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1325                effort: ReasoningEffortLevel::Medium,
1326                description: "Balanced".to_string(),
1327            }],
1328            is_default: false,
1329            upgrade: None,
1330            show_in_picker: true,
1331            supported_in_api: true,
1332            context_window: Some(262_144),
1333        },
1334    ]
1335}
1336
1337fn opencode_zen_presets() -> Vec<ModelPreset> {
1338    vec![ModelPreset {
1339        id: "opencode/gpt-5.4".to_string(),
1340        model: "gpt-5.4".to_string(),
1341        display_name: "GPT-5.4 (OpenCode Zen)".to_string(),
1342        description: "OpenCode Zen gateway — curated, benchmarked models at cost".to_string(),
1343        provider: Provider::OpenCodeZen,
1344        default_reasoning_effort: ReasoningEffortLevel::Medium,
1345        supported_reasoning_efforts: vec![ReasoningEffortPreset {
1346            effort: ReasoningEffortLevel::Medium,
1347            description: "Balanced".to_string(),
1348        }],
1349        is_default: true,
1350        upgrade: None,
1351        show_in_picker: true,
1352        supported_in_api: true,
1353        context_window: Some(1_050_000),
1354    }]
1355}
1356
1357fn opencode_go_presets() -> Vec<ModelPreset> {
1358    vec![ModelPreset {
1359        id: "opencode-go/glm-5.1".to_string(),
1360        model: "glm-5.1".to_string(),
1361        display_name: "GLM-5.1 (OpenCode Go)".to_string(),
1362        description: "OpenCode Go — affordable subscription for open coding models".to_string(),
1363        provider: Provider::OpenCodeGo,
1364        default_reasoning_effort: ReasoningEffortLevel::Medium,
1365        supported_reasoning_efforts: vec![ReasoningEffortPreset {
1366            effort: ReasoningEffortLevel::Medium,
1367            description: "Balanced".to_string(),
1368        }],
1369        is_default: true,
1370        upgrade: None,
1371        show_in_picker: true,
1372        supported_in_api: true,
1373        context_window: Some(256_000),
1374    }]
1375}
1376
1377fn poolside_presets() -> Vec<ModelPreset> {
1378    vec![
1379        ModelPreset {
1380            id: poolside_models::LAGUNA_M1.to_string(),
1381            model: poolside_models::LAGUNA_M1.to_string(),
1382            display_name: "Laguna M.1".to_string(),
1383            description:
1384                "Poolside's flagship MoE coding agent model optimized for multi-step agentic tasks, tool use, and validation (128K context)"
1385                    .to_string(),
1386            provider: Provider::Poolside,
1387            default_reasoning_effort: ReasoningEffortLevel::Medium,
1388            supported_reasoning_efforts: Vec::new(),
1389            is_default: true,
1390            upgrade: None,
1391            show_in_picker: true,
1392            supported_in_api: true,
1393            context_window: Some(131_072),
1394        },
1395        ModelPreset {
1396            id: poolside_models::LAGUNA_XS2.to_string(),
1397            model: poolside_models::LAGUNA_XS2.to_string(),
1398            display_name: "Laguna XS.2".to_string(),
1399            description:
1400                "Poolside's efficient MoE coding agent model optimized for fast agentic coding (128K context)"
1401                    .to_string(),
1402            provider: Provider::Poolside,
1403            default_reasoning_effort: ReasoningEffortLevel::Medium,
1404            supported_reasoning_efforts: Vec::new(),
1405            is_default: false,
1406            upgrade: None,
1407            show_in_picker: true,
1408            supported_in_api: true,
1409            context_window: Some(131_072),
1410        },
1411    ]
1412}
1413
1414fn mimo_presets() -> Vec<ModelPreset> {
1415    vec![
1416        ModelPreset {
1417            id: mimo_models::MIMO_V2_5_PRO.to_string(),
1418            model: mimo_models::MIMO_V2_5_PRO.to_string(),
1419            display_name: "MiMo V2.5 Pro".to_string(),
1420            description:
1421                "Xiaomi's flagship reasoning model with advanced capabilities (1M context)"
1422                    .to_string(),
1423            provider: Provider::MiMo,
1424            default_reasoning_effort: ReasoningEffortLevel::Medium,
1425            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1426                effort: ReasoningEffortLevel::Medium,
1427                description: "Balanced".to_string(),
1428            }],
1429            is_default: true,
1430            upgrade: None,
1431            show_in_picker: true,
1432            supported_in_api: true,
1433            context_window: Some(1_048_576),
1434        },
1435        ModelPreset {
1436            id: mimo_models::MIMO_V2_5.to_string(),
1437            model: mimo_models::MIMO_V2_5.to_string(),
1438            display_name: "MiMo V2.5".to_string(),
1439            description: "Xiaomi's general-purpose model with strong reasoning (1M context)"
1440                .to_string(),
1441            provider: Provider::MiMo,
1442            default_reasoning_effort: ReasoningEffortLevel::Medium,
1443            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1444                effort: ReasoningEffortLevel::Medium,
1445                description: "Balanced".to_string(),
1446            }],
1447            is_default: false,
1448            upgrade: None,
1449            show_in_picker: true,
1450            supported_in_api: true,
1451            context_window: Some(1_048_576),
1452        },
1453
1454    ]
1455}
1456
1457fn qwen_presets() -> Vec<ModelPreset> {
1458    vec![
1459        ModelPreset {
1460            id: qwen_models::DEEPSEEK_V4_FLASH.to_string(),
1461            model: qwen_models::DEEPSEEK_V4_FLASH.to_string(),
1462            display_name: "DeepSeek V4 Flash (Qwen)".to_string(),
1463            description:
1464                "DeepSeek V4 Flash fast inference model served through Qwen Cloud API (1M context)"
1465                    .to_string(),
1466            provider: Provider::Qwen,
1467            default_reasoning_effort: ReasoningEffortLevel::Low,
1468            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1469                effort: ReasoningEffortLevel::Low,
1470                description: "Fast".to_string(),
1471            }],
1472            is_default: false,
1473            upgrade: None,
1474            show_in_picker: true,
1475            supported_in_api: true,
1476            context_window: Some(1_048_576),
1477        },
1478        ModelPreset {
1479            id: qwen_models::DEEPSEEK_V4_PRO.to_string(),
1480            model: qwen_models::DEEPSEEK_V4_PRO.to_string(),
1481            display_name: "DeepSeek V4 Pro (Qwen)".to_string(),
1482            description:
1483                "DeepSeek V4 Pro high-performance reasoning model served through Qwen Cloud API (1M context)"
1484                    .to_string(),
1485            provider: Provider::Qwen,
1486            default_reasoning_effort: ReasoningEffortLevel::Medium,
1487            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1488                effort: ReasoningEffortLevel::Medium,
1489                description: "Balanced".to_string(),
1490            }],
1491            is_default: false,
1492            upgrade: None,
1493            show_in_picker: true,
1494            supported_in_api: true,
1495            context_window: Some(1_048_576),
1496        },
1497        ModelPreset {
1498            id: qwen_models::GLM_5_1.to_string(),
1499            model: qwen_models::GLM_5_1.to_string(),
1500            display_name: "GLM-5.1 (Qwen)".to_string(),
1501            description:
1502                "Z.AI GLM-5.1 next-gen foundation model served through Qwen Cloud API"
1503                    .to_string(),
1504            provider: Provider::Qwen,
1505            default_reasoning_effort: ReasoningEffortLevel::Medium,
1506            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1507                effort: ReasoningEffortLevel::Medium,
1508                description: "Balanced".to_string(),
1509            }],
1510            is_default: false,
1511            upgrade: None,
1512            show_in_picker: true,
1513            supported_in_api: true,
1514            context_window: Some(131_072),
1515        },
1516    ]
1517}
1518
1519fn stepfun_presets() -> Vec<ModelPreset> {
1520    vec![ModelPreset {
1521        id: stepfun_models::STEP_3_7_FLASH.to_string(),
1522        model: stepfun_models::STEP_3_7_FLASH.to_string(),
1523        display_name: "Step 3.7 Flash".to_string(),
1524        description:
1525            "StepFun's flagship multimodal reasoning model with 256K context and tool calling."
1526                .to_string(),
1527        provider: Provider::StepFun,
1528        default_reasoning_effort: ReasoningEffortLevel::Medium,
1529        supported_reasoning_efforts: vec![
1530            reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1531            reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1532            reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1533        ],
1534        is_default: true,
1535        upgrade: None,
1536        show_in_picker: true,
1537        supported_in_api: true,
1538        context_window: Some(262_144),
1539    }]
1540}
1541
1542fn evolink_presets() -> Vec<ModelPreset> {
1543    vec![
1544        ModelPreset {
1545            id: "evolink/gpt-5.2".to_string(),
1546            model: evolink_models::GPT_5_2.to_string(),
1547            display_name: "GPT-5.2 (Evolink)".to_string(),
1548            description: "GPT-5.2 served through the Evolink OpenAI-compatible gateway."
1549                .to_string(),
1550            provider: Provider::Evolink,
1551            default_reasoning_effort: ReasoningEffortLevel::Medium,
1552            supported_reasoning_efforts: vec![reasoning_preset(
1553                ReasoningEffortLevel::Medium,
1554                "Balanced",
1555            )],
1556            is_default: true,
1557            upgrade: None,
1558            show_in_picker: true,
1559            supported_in_api: true,
1560            context_window: Some(400_000),
1561        },
1562        ModelPreset {
1563            id: "evolink/gpt-5.5".to_string(),
1564            model: evolink_models::GPT_5_5.to_string(),
1565            display_name: "GPT-5.5 (Evolink)".to_string(),
1566            description: "GPT-5.5 flagship model served through the Evolink gateway.".to_string(),
1567            provider: Provider::Evolink,
1568            default_reasoning_effort: ReasoningEffortLevel::Medium,
1569            supported_reasoning_efforts: vec![reasoning_preset(
1570                ReasoningEffortLevel::Medium,
1571                "Balanced",
1572            )],
1573            is_default: false,
1574            upgrade: None,
1575            show_in_picker: true,
1576            supported_in_api: true,
1577            context_window: Some(400_000),
1578        },
1579        ModelPreset {
1580            id: "evolink/deepseek-v4-pro".to_string(),
1581            model: evolink_models::DEEPSEEK_V4_PRO.to_string(),
1582            display_name: "DeepSeek V4 Pro (Evolink)".to_string(),
1583            description: "DeepSeek V4 Pro reasoning model served through the Evolink gateway."
1584                .to_string(),
1585            provider: Provider::Evolink,
1586            default_reasoning_effort: ReasoningEffortLevel::Medium,
1587            supported_reasoning_efforts: vec![
1588                reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1589                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1590                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1591            ],
1592            is_default: false,
1593            upgrade: None,
1594            show_in_picker: true,
1595            supported_in_api: true,
1596            context_window: Some(163_840),
1597        },
1598        ModelPreset {
1599            id: "evolink/deepseek-v4-flash".to_string(),
1600            model: evolink_models::DEEPSEEK_V4_FLASH.to_string(),
1601            display_name: "DeepSeek V4 Flash (Evolink)".to_string(),
1602            description:
1603                "DeepSeek V4 Flash fast inference model served through the Evolink gateway."
1604                    .to_string(),
1605            provider: Provider::Evolink,
1606            default_reasoning_effort: ReasoningEffortLevel::Medium,
1607            supported_reasoning_efforts: vec![
1608                reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1609                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1610                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1611            ],
1612            is_default: false,
1613            upgrade: None,
1614            show_in_picker: true,
1615            supported_in_api: true,
1616            context_window: Some(1_000_000),
1617        },
1618        ModelPreset {
1619            id: "evolink/doubao-seed-2.0-pro".to_string(),
1620            model: evolink_models::DOUBAO_SEED_2_0_PRO.to_string(),
1621            display_name: "Doubao Seed 2.0 Pro (Evolink)".to_string(),
1622            description: "Doubao Seed 2.0 Pro served through the Evolink gateway.".to_string(),
1623            provider: Provider::Evolink,
1624            default_reasoning_effort: ReasoningEffortLevel::Medium,
1625            supported_reasoning_efforts: vec![
1626                reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1627                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1628                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1629            ],
1630            is_default: false,
1631            upgrade: None,
1632            show_in_picker: true,
1633            supported_in_api: true,
1634            context_window: Some(262_144),
1635        },
1636        ModelPreset {
1637            id: "evolink/gemini-3.1-pro-preview".to_string(),
1638            model: evolink_models::GEMINI_3_1_PRO.to_string(),
1639            display_name: "Gemini 3.1 Pro (Evolink)".to_string(),
1640            description: "Gemini 3.1 Pro served through the Evolink gateway via OpenAI SDK format."
1641                .to_string(),
1642            provider: Provider::Evolink,
1643            default_reasoning_effort: ReasoningEffortLevel::Medium,
1644            supported_reasoning_efforts: vec![reasoning_preset(
1645                ReasoningEffortLevel::Medium,
1646                "Balanced",
1647            )],
1648            is_default: false,
1649            upgrade: None,
1650            show_in_picker: true,
1651            supported_in_api: true,
1652            context_window: Some(1_000_000),
1653        },
1654        ModelPreset {
1655            id: "evolink/gemini-3.5-flash".to_string(),
1656            model: evolink_models::GEMINI_3_5_FLASH.to_string(),
1657            display_name: "Gemini 3.5 Flash (Evolink)".to_string(),
1658            description:
1659                "Gemini 3.5 Flash served through the Evolink gateway via OpenAI SDK format."
1660                    .to_string(),
1661            provider: Provider::Evolink,
1662            default_reasoning_effort: ReasoningEffortLevel::Medium,
1663            supported_reasoning_efforts: vec![reasoning_preset(
1664                ReasoningEffortLevel::Medium,
1665                "Balanced",
1666            )],
1667            is_default: false,
1668            upgrade: None,
1669            show_in_picker: true,
1670            supported_in_api: true,
1671            context_window: Some(1_000_000),
1672        },
1673        ModelPreset {
1674            id: "evolink/MiniMax-M3".to_string(),
1675            model: evolink_models::MINIMAX_M3.to_string(),
1676            display_name: "MiniMax-M3 (Evolink)".to_string(),
1677            description: "MiniMax-M3 frontier multimodal model served through the Evolink gateway."
1678                .to_string(),
1679            provider: Provider::Evolink,
1680            default_reasoning_effort: ReasoningEffortLevel::Medium,
1681            supported_reasoning_efforts: vec![reasoning_preset(
1682                ReasoningEffortLevel::Medium,
1683                "Balanced",
1684            )],
1685            is_default: false,
1686            upgrade: None,
1687            show_in_picker: true,
1688            supported_in_api: true,
1689            context_window: Some(1_000_000),
1690        },
1691        ModelPreset {
1692            id: "evolink/claude-sonnet-4-6".to_string(),
1693            model: evolink_models::CLAUDE_SONNET_4_6.to_string(),
1694            display_name: "Claude Sonnet 4.6 (Evolink)".to_string(),
1695            description: "Claude Sonnet 4.6 served through Evolink via Anthropic Messages API."
1696                .to_string(),
1697            provider: Provider::Evolink,
1698            default_reasoning_effort: ReasoningEffortLevel::Medium,
1699            supported_reasoning_efforts: vec![reasoning_preset(
1700                ReasoningEffortLevel::Medium,
1701                "Balanced",
1702            )],
1703            is_default: false,
1704            upgrade: None,
1705            show_in_picker: true,
1706            supported_in_api: true,
1707            context_window: Some(200_000),
1708        },
1709        ModelPreset {
1710            id: "evolink/claude-opus-4-8".to_string(),
1711            model: evolink_models::CLAUDE_OPUS_4_8.to_string(),
1712            display_name: "Claude Opus 4.8 (Evolink)".to_string(),
1713            description: "Claude Opus 4.8 served through Evolink via Anthropic Messages API."
1714                .to_string(),
1715            provider: Provider::Evolink,
1716            default_reasoning_effort: ReasoningEffortLevel::High,
1717            supported_reasoning_efforts: vec![
1718                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1719                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1720            ],
1721            is_default: false,
1722            upgrade: None,
1723            show_in_picker: true,
1724            supported_in_api: true,
1725            context_window: Some(200_000),
1726        },
1727        ModelPreset {
1728            id: "evolink/claude-haiku-4-5-20251001".to_string(),
1729            model: evolink_models::CLAUDE_HAIKU_4_5.to_string(),
1730            display_name: "Claude Haiku 4.5 (Evolink)".to_string(),
1731            description:
1732                "Claude Haiku 4.5 fast model served through Evolink via Anthropic Messages API."
1733                    .to_string(),
1734            provider: Provider::Evolink,
1735            default_reasoning_effort: ReasoningEffortLevel::Low,
1736            supported_reasoning_efforts: vec![
1737                reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1738                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1739            ],
1740            is_default: false,
1741            upgrade: None,
1742            show_in_picker: true,
1743            supported_in_api: true,
1744            context_window: Some(200_000),
1745        },
1746    ]
1747}
1748
1749fn moonshot_presets() -> Vec<ModelPreset> {
1750    vec![
1751        ModelPreset {
1752            id: "kimi-k2.7-code".to_string(),
1753            model: "kimi-k2.7-code".to_string(),
1754            display_name: "Kimi K2.7 Code (Moonshot)".to_string(),
1755            description:
1756                "Moonshot's most capable coding model with long-horizon coding breakthrough."
1757                    .to_string(),
1758            provider: Provider::Moonshot,
1759            default_reasoning_effort: ReasoningEffortLevel::Medium,
1760            supported_reasoning_efforts: vec![reasoning_preset(
1761                ReasoningEffortLevel::Medium,
1762                "Balanced",
1763            )],
1764            is_default: true,
1765            upgrade: None,
1766            show_in_picker: true,
1767            supported_in_api: true,
1768            context_window: Some(256_000),
1769        },
1770        ModelPreset {
1771            id: "kimi-k2.6".to_string(),
1772            model: "kimi-k2.6".to_string(),
1773            display_name: "Kimi K2.6 (Moonshot)".to_string(),
1774            description: "Moonshot's previous flagship coding and agent model.".to_string(),
1775            provider: Provider::Moonshot,
1776            default_reasoning_effort: ReasoningEffortLevel::Medium,
1777            supported_reasoning_efforts: vec![reasoning_preset(
1778                ReasoningEffortLevel::Medium,
1779                "Balanced",
1780            )],
1781            is_default: false,
1782            upgrade: None,
1783            show_in_picker: true,
1784            supported_in_api: true,
1785            context_window: Some(256_000),
1786        },
1787    ]
1788}
1789
1790fn huggingface_presets() -> Vec<ModelPreset> {
1791    vec![
1792        ModelPreset {
1793            id: "huggingface/deepseek-v4-flash".to_string(),
1794            model: "deepseek-ai/DeepSeek-V4-Flash:novita".to_string(),
1795            display_name: "DeepSeek V4 Flash (HF/Novita)".to_string(),
1796            description:
1797                "Fast inference model for cost-effective reasoning (1M context, 158B params)"
1798                    .to_string(),
1799            provider: Provider::HuggingFace,
1800            default_reasoning_effort: ReasoningEffortLevel::High,
1801            supported_reasoning_efforts: vec![
1802                ReasoningEffortPreset {
1803                    effort: ReasoningEffortLevel::High,
1804                    description: "Balanced".to_string(),
1805                },
1806                ReasoningEffortPreset {
1807                    effort: ReasoningEffortLevel::Max,
1808                    description: "Maximum thinking".to_string(),
1809                },
1810            ],
1811            is_default: false,
1812            upgrade: None,
1813            show_in_picker: true,
1814            supported_in_api: true,
1815            context_window: Some(1_000_000),
1816        },
1817        ModelPreset {
1818            id: "huggingface/deepseek-v4-pro".to_string(),
1819            model: "deepseek-ai/DeepSeek-V4-Pro:together".to_string(),
1820            display_name: "DeepSeek V4 Pro (HF/Together)".to_string(),
1821            description:
1822                "High-performance reasoning model with advanced thinking capabilities (1M context, 1.6T params)"
1823                    .to_string(),
1824            provider: Provider::HuggingFace,
1825            default_reasoning_effort: ReasoningEffortLevel::High,
1826            supported_reasoning_efforts: vec![
1827                ReasoningEffortPreset {
1828                    effort: ReasoningEffortLevel::High,
1829                    description: "Balanced".to_string(),
1830                },
1831                ReasoningEffortPreset {
1832                    effort: ReasoningEffortLevel::Max,
1833                    description: "Maximum thinking".to_string(),
1834                },
1835            ],
1836            is_default: false,
1837            upgrade: None,
1838            show_in_picker: true,
1839            supported_in_api: true,
1840            context_window: Some(1_000_000),
1841        },
1842        ModelPreset {
1843            id: "huggingface/nvidia-nemotron-3-ultra".to_string(),
1844            model: "nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4:together".to_string(),
1845            display_name: "NVIDIA-Nemotron-3-Ultra-550B (HF/Together)".to_string(),
1846            description:
1847                "NVIDIA Nemotron 3 Ultra 550B-A55B-NVFP4 via Together inference provider"
1848                    .to_string(),
1849            provider: Provider::HuggingFace,
1850            default_reasoning_effort: ReasoningEffortLevel::High,
1851            supported_reasoning_efforts: vec![
1852                ReasoningEffortPreset {
1853                    effort: ReasoningEffortLevel::High,
1854                    description: "Balanced".to_string(),
1855                },
1856                ReasoningEffortPreset {
1857                    effort: ReasoningEffortLevel::Max,
1858                    description: "Maximum thinking".to_string(),
1859                },
1860            ],
1861            is_default: false,
1862            upgrade: None,
1863            show_in_picker: true,
1864            supported_in_api: true,
1865            context_window: Some(128_000),
1866        },
1867        ModelPreset {
1868            id: "huggingface/minimax-m3".to_string(),
1869            model: "MiniMaxAI/MiniMax-M3:novita".to_string(),
1870            display_name: "MiniMax-M3 (HF/Novita)".to_string(),
1871            description:
1872                "Frontier multimodal coding model with 1M context window via Novita inference provider"
1873                    .to_string(),
1874            provider: Provider::HuggingFace,
1875            default_reasoning_effort: ReasoningEffortLevel::High,
1876            supported_reasoning_efforts: vec![
1877                ReasoningEffortPreset {
1878                    effort: ReasoningEffortLevel::High,
1879                    description: "Balanced".to_string(),
1880                },
1881                ReasoningEffortPreset {
1882                    effort: ReasoningEffortLevel::Max,
1883                    description: "Maximum thinking".to_string(),
1884                },
1885            ],
1886            is_default: false,
1887            upgrade: None,
1888            show_in_picker: true,
1889            supported_in_api: true,
1890            context_window: Some(1_000_000),
1891        },
1892    ]
1893}
1894
1895/// Get all model presets (for testing)
1896#[cfg(test)]
1897pub fn all_model_presets() -> Vec<ModelPreset> {
1898    builtin_model_presets()
1899}
1900
1901#[cfg(test)]
1902mod tests {
1903    use super::*;
1904
1905    #[test]
1906    fn only_one_default_per_provider() {
1907        let presets = builtin_model_presets();
1908        let providers: Vec<Provider> = Provider::all_providers();
1909
1910        for provider in providers {
1911            let default_count = presets
1912                .iter()
1913                .filter(|p| p.provider == provider && p.is_default)
1914                .count();
1915            assert!(
1916                default_count <= 1,
1917                "Provider {:?} has {} defaults, expected 0 or 1",
1918                provider,
1919                default_count
1920            );
1921        }
1922    }
1923
1924    #[test]
1925    fn gemini_presets_exist() {
1926        let presets = gemini_presets();
1927        assert!(!presets.is_empty());
1928        assert!(presets.iter().any(|p| p.id.contains("gemini")));
1929    }
1930
1931    #[test]
1932    fn model_info_converts_to_preset() {
1933        let info = ModelInfo {
1934            slug: "test-model".to_string(),
1935            display_name: "Test Model".to_string(),
1936            description: "A test model".to_string(),
1937            provider: Provider::Gemini,
1938            default_reasoning_level: ReasoningEffortLevel::Medium,
1939            supported_reasoning_levels: vec![],
1940            context_window: Some(128_000),
1941            supports_tool_use: true,
1942            supports_streaming: true,
1943            supports_reasoning: false,
1944            priority: 0,
1945            visibility: "list".to_string(),
1946            supported_in_api: true,
1947            upgrade: None,
1948        };
1949
1950        let preset: ModelPreset = info.into();
1951        assert_eq!(preset.id, "test-model");
1952        assert_eq!(preset.model, "test-model");
1953        assert!(preset.show_in_picker);
1954    }
1955
1956    #[test]
1957    fn openai_codex_presets_default_to_high_reasoning() {
1958        let codex = openai_presets()
1959            .into_iter()
1960            .find(|preset| preset.id == "gpt-5.3-codex")
1961            .expect("gpt-5.3-codex preset");
1962
1963        assert_eq!(codex.default_reasoning_effort, ReasoningEffortLevel::High);
1964    }
1965
1966    #[test]
1967    fn moonshot_presets_exist_and_default_to_kimi_k26() {
1968        let presets = moonshot_presets();
1969        assert_eq!(presets.len(), 2);
1970
1971        let default = presets
1972            .iter()
1973            .find(|preset| preset.is_default)
1974            .expect("moonshot default preset");
1975        assert_eq!(default.id, "kimi-k2.6");
1976        assert_eq!(default.provider, Provider::Moonshot);
1977    }
1978}