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-opus-4-8".to_string(),
578            model: "claude-opus-4-8".to_string(),
579            display_name: "Claude Opus 4.8".to_string(),
580            description:
581                "Anthropic's most capable model for complex reasoning, long-horizon agentic coding, and high-autonomy work"
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 Opus 4.8 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-7".to_string(),
616            model: "claude-opus-4-7".to_string(),
617            display_name: "Claude Opus 4.7".to_string(),
618            description:
619                "Next-gen Anthropic flagship with adaptive thinking, optional task budgets, and configurable low-through-max effort"
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: "Default Opus 4.7 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-mythos-preview".to_string(),
654            model: "claude-mythos-preview".to_string(),
655            display_name: "Claude Mythos Preview".to_string(),
656            description:
657                "Invitation-only Anthropic preview with adaptive thinking and support for max effort"
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: false,
682            supported_in_api: true,
683            context_window: Some(1_000_000),
684        },
685        ModelPreset {
686            id: "claude-opus-4-6".to_string(),
687            model: "claude-opus-4-6".to_string(),
688            display_name: "Claude Opus 4.6".to_string(),
689            description:
690                "Previous Anthropic flagship now using adaptive thinking by default, with legacy manual-budget fallback"
691                    .to_string(),
692            provider: Provider::Anthropic,
693            default_reasoning_effort: ReasoningEffortLevel::High,
694            supported_reasoning_efforts: vec![
695                ReasoningEffortPreset {
696                    effort: ReasoningEffortLevel::Low,
697                    description: "Fast adaptive effort".to_string(),
698                },
699                ReasoningEffortPreset {
700                    effort: ReasoningEffortLevel::Medium,
701                    description: "Balanced adaptive effort".to_string(),
702                },
703                ReasoningEffortPreset {
704                    effort: ReasoningEffortLevel::High,
705                    description: "Default adaptive effort".to_string(),
706                },
707                ReasoningEffortPreset {
708                    effort: ReasoningEffortLevel::Max,
709                    description: "Maximum adaptive effort".to_string(),
710                },
711            ],
712            is_default: false,
713            upgrade: None,
714            show_in_picker: true,
715            supported_in_api: true,
716            context_window: Some(1_000_000),
717        },
718        ModelPreset {
719            id: "claude-sonnet-4-6".to_string(),
720            model: "claude-sonnet-4-6".to_string(),
721            display_name: "Claude Sonnet 4.6".to_string(),
722            description:
723                "The best combination of speed and intelligence. Supports extended thinking and adaptive thinking with 1M context."
724                    .to_string(),
725            provider: Provider::Anthropic,
726            default_reasoning_effort: ReasoningEffortLevel::High,
727            supported_reasoning_efforts: vec![
728                ReasoningEffortPreset {
729                    effort: ReasoningEffortLevel::Low,
730                    description: "Fast adaptive effort".to_string(),
731                },
732                ReasoningEffortPreset {
733                    effort: ReasoningEffortLevel::Medium,
734                    description: "Balanced adaptive effort".to_string(),
735                },
736                ReasoningEffortPreset {
737                    effort: ReasoningEffortLevel::High,
738                    description: "Default adaptive effort".to_string(),
739                },
740                ReasoningEffortPreset {
741                    effort: ReasoningEffortLevel::Max,
742                    description: "Maximum adaptive effort".to_string(),
743                },
744            ],
745            is_default: false,
746            upgrade: None,
747            show_in_picker: true,
748            supported_in_api: true,
749            context_window: Some(1_000_000),
750        },
751        ModelPreset {
752            id: "claude-haiku-4-5".to_string(),
753            model: "claude-haiku-4-5".to_string(),
754            display_name: "Claude Haiku 4.5".to_string(),
755            description: "The fastest model with near-frontier intelligence. Supports extended thinking with manual budget."
756                .to_string(),
757            provider: Provider::Anthropic,
758            default_reasoning_effort: ReasoningEffortLevel::Medium,
759            supported_reasoning_efforts: Vec::new(),
760            is_default: false,
761            upgrade: None,
762            show_in_picker: true,
763            supported_in_api: true,
764            context_window: Some(200_000),
765        },
766    ]
767}
768
769fn deepseek_presets() -> Vec<ModelPreset> {
770    vec![
771        ModelPreset {
772            id: "deepseek-v4-pro".to_string(),
773            model: "deepseek-v4-pro".to_string(),
774            display_name: "DeepSeek V4 Pro".to_string(),
775            description: "High-performance reasoning model with advanced thinking capabilities"
776                .to_string(),
777            provider: Provider::DeepSeek,
778            default_reasoning_effort: ReasoningEffortLevel::High,
779            supported_reasoning_efforts: vec![
780                ReasoningEffortPreset {
781                    effort: ReasoningEffortLevel::High,
782                    description: "Balanced".to_string(),
783                },
784                ReasoningEffortPreset {
785                    effort: ReasoningEffortLevel::Max,
786                    description: "Maximum thinking".to_string(),
787                },
788            ],
789            is_default: true,
790            upgrade: None,
791            show_in_picker: true,
792            supported_in_api: true,
793            context_window: Some(1_000_000),
794        },
795        ModelPreset {
796            id: "deepseek-v4-flash".to_string(),
797            model: "deepseek-v4-flash".to_string(),
798            display_name: "DeepSeek V4 Flash".to_string(),
799            description: "Fast inference model for cost-effective reasoning tasks".to_string(),
800            provider: Provider::DeepSeek,
801            default_reasoning_effort: ReasoningEffortLevel::High,
802            supported_reasoning_efforts: vec![
803                ReasoningEffortPreset {
804                    effort: ReasoningEffortLevel::High,
805                    description: "Balanced".to_string(),
806                },
807                ReasoningEffortPreset {
808                    effort: ReasoningEffortLevel::Max,
809                    description: "Maximum thinking".to_string(),
810                },
811            ],
812            is_default: false,
813            upgrade: None,
814            show_in_picker: true,
815            supported_in_api: true,
816            context_window: Some(1_000_000),
817        },
818    ]
819}
820
821fn zai_presets() -> Vec<ModelPreset> {
822    vec![
823        ModelPreset {
824            id: "glm-5".to_string(),
825            model: "glm-5".to_string(),
826            display_name: "GLM-5".to_string(),
827            description: "Z.ai's flagship open-source foundation model for complex systems"
828                .to_string(),
829            provider: Provider::ZAI,
830            default_reasoning_effort: ReasoningEffortLevel::Medium,
831            supported_reasoning_efforts: vec![
832                ReasoningEffortPreset {
833                    effort: ReasoningEffortLevel::Medium,
834                    description: "Balanced".to_string(),
835                },
836                ReasoningEffortPreset {
837                    effort: ReasoningEffortLevel::High,
838                    description: "Deep thinking".to_string(),
839                },
840            ],
841            is_default: false,
842            upgrade: None,
843            show_in_picker: true,
844            supported_in_api: true,
845            context_window: Some(200_000),
846        },
847        ModelPreset {
848            id: "glm-5.1".to_string(),
849            model: "glm-5.1".to_string(),
850            display_name: "GLM-5.1".to_string(),
851            description:
852                "Z.ai's next-gen foundation model with improved reasoning and agent capabilities"
853                    .to_string(),
854            provider: Provider::ZAI,
855            default_reasoning_effort: ReasoningEffortLevel::Medium,
856            supported_reasoning_efforts: vec![
857                ReasoningEffortPreset {
858                    effort: ReasoningEffortLevel::Medium,
859                    description: "Balanced".to_string(),
860                },
861                ReasoningEffortPreset {
862                    effort: ReasoningEffortLevel::High,
863                    description: "Deep thinking".to_string(),
864                },
865            ],
866            is_default: true,
867            upgrade: None,
868            show_in_picker: true,
869            supported_in_api: true,
870            context_window: Some(200_000),
871        },
872    ]
873}
874
875fn mistral_presets() -> Vec<ModelPreset> {
876    vec![
877        ModelPreset {
878            id: "mistral-large-2512".to_string(),
879            model: "mistral-large-2512".to_string(),
880            display_name: "Mistral Large 3".to_string(),
881            description:
882                "State-of-the-art open-weight general-purpose multimodal model (41B active, 675B total)".to_string(),
883            provider: Provider::Mistral,
884            default_reasoning_effort: ReasoningEffortLevel::Medium,
885            supported_reasoning_efforts: vec![
886                ReasoningEffortPreset {
887                    effort: ReasoningEffortLevel::Medium,
888                    description: "Balanced".to_string(),
889                },
890                ReasoningEffortPreset {
891                    effort: ReasoningEffortLevel::High,
892                    description: "Deep".to_string(),
893                },
894            ],
895            is_default: true,
896            upgrade: None,
897            show_in_picker: true,
898            supported_in_api: true,
899            context_window: Some(256_000),
900        },
901        ModelPreset {
902            id: "mistral-medium-3-5".to_string(),
903            model: "mistral-medium-3-5".to_string(),
904            display_name: "Mistral Medium 3.5".to_string(),
905            description:
906                "Frontier-class multimodal model optimized for agentic and coding use cases (256k context)"
907                    .to_string(),
908            provider: Provider::Mistral,
909            default_reasoning_effort: ReasoningEffortLevel::Medium,
910            supported_reasoning_efforts: vec![
911                ReasoningEffortPreset {
912                    effort: ReasoningEffortLevel::Medium,
913                    description: "Balanced".to_string(),
914                },
915                ReasoningEffortPreset {
916                    effort: ReasoningEffortLevel::High,
917                    description: "Deep".to_string(),
918                },
919            ],
920            is_default: false,
921            upgrade: None,
922            show_in_picker: true,
923            supported_in_api: true,
924            context_window: Some(256_000),
925        },
926        ModelPreset {
927            id: "mistral-small-2603".to_string(),
928            model: "mistral-small-2603".to_string(),
929            display_name: "Mistral Small 4".to_string(),
930            description:
931                "Hybrid model unifying instruct, reasoning, and coding (119B params, 6.5B active)"
932                    .to_string(),
933            provider: Provider::Mistral,
934            default_reasoning_effort: ReasoningEffortLevel::Medium,
935            supported_reasoning_efforts: vec![
936                ReasoningEffortPreset {
937                    effort: ReasoningEffortLevel::Medium,
938                    description: "Balanced".to_string(),
939                },
940                ReasoningEffortPreset {
941                    effort: ReasoningEffortLevel::High,
942                    description: "Deep".to_string(),
943                },
944            ],
945            is_default: false,
946            upgrade: None,
947            show_in_picker: true,
948            supported_in_api: true,
949            context_window: Some(256_000),
950        },
951        ModelPreset {
952            id: "mistral-medium-2508".to_string(),
953            model: "mistral-medium-2508".to_string(),
954            display_name: "Mistral Medium 3.1".to_string(),
955            description: "Frontier-class multimodal model with 256k context".to_string(),
956            provider: Provider::Mistral,
957            default_reasoning_effort: ReasoningEffortLevel::Medium,
958            supported_reasoning_efforts: vec![ReasoningEffortPreset {
959                effort: ReasoningEffortLevel::Medium,
960                description: "Balanced".to_string(),
961            }],
962            is_default: false,
963            upgrade: None,
964            show_in_picker: true,
965            supported_in_api: true,
966            context_window: Some(256_000),
967        },
968        ModelPreset {
969            id: "codestral-2508".to_string(),
970            model: "codestral-2508".to_string(),
971            display_name: "Codestral".to_string(),
972            description: "Cutting-edge language model for code completion".to_string(),
973            provider: Provider::Mistral,
974            default_reasoning_effort: ReasoningEffortLevel::Medium,
975            supported_reasoning_efforts: Vec::new(),
976            is_default: false,
977            upgrade: None,
978            show_in_picker: true,
979            supported_in_api: true,
980            context_window: Some(256_000),
981        },
982    ]
983}
984
985fn minimax_presets() -> Vec<ModelPreset> {
986    vec![
987        ModelPreset {
988            id: "minimax-m3".to_string(),
989            model: "MiniMax-M3".to_string(),
990            display_name: "MiniMax M3".to_string(),
991            description: "Frontier multimodal coding model with 1M context".to_string(),
992            provider: Provider::Minimax,
993            default_reasoning_effort: ReasoningEffortLevel::Medium,
994            supported_reasoning_efforts: vec![
995                ReasoningEffortPreset {
996                    effort: ReasoningEffortLevel::Medium,
997                    description: "Balanced".to_string(),
998                },
999                ReasoningEffortPreset {
1000                    effort: ReasoningEffortLevel::High,
1001                    description: "Deep".to_string(),
1002                },
1003            ],
1004            is_default: true,
1005            upgrade: None,
1006            show_in_picker: true,
1007            supported_in_api: true,
1008            context_window: Some(1_000_000),
1009        },
1010        ModelPreset {
1011            id: "minimax-m2.5".to_string(),
1012            model: "MiniMax-M2.5".to_string(),
1013            display_name: "MiniMax M2.5".to_string(),
1014            description: "Enhanced code understanding and reasoning".to_string(),
1015            provider: Provider::Minimax,
1016            default_reasoning_effort: ReasoningEffortLevel::Medium,
1017            supported_reasoning_efforts: vec![
1018                ReasoningEffortPreset {
1019                    effort: ReasoningEffortLevel::Medium,
1020                    description: "Balanced".to_string(),
1021                },
1022                ReasoningEffortPreset {
1023                    effort: ReasoningEffortLevel::High,
1024                    description: "Deep".to_string(),
1025                },
1026            ],
1027            is_default: false,
1028            upgrade: None,
1029            show_in_picker: true,
1030            supported_in_api: true,
1031            context_window: Some(128_000),
1032        },
1033    ]
1034}
1035
1036fn openrouter_presets() -> Vec<ModelPreset> {
1037    vec![
1038        ModelPreset {
1039            id: "openrouter/deepseek/deepseek-chat".to_string(),
1040            model: "deepseek/deepseek-chat".to_string(),
1041            display_name: "DeepSeek V3.2 (OpenRouter)".to_string(),
1042            description: "DeepSeek via OpenRouter".to_string(),
1043            provider: Provider::OpenRouter,
1044            default_reasoning_effort: ReasoningEffortLevel::Medium,
1045            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1046                effort: ReasoningEffortLevel::Medium,
1047                description: "Balanced".to_string(),
1048            }],
1049            is_default: false,
1050            upgrade: None,
1051            show_in_picker: true,
1052            supported_in_api: true,
1053            context_window: Some(128_000),
1054        },
1055        ModelPreset {
1056            id: "openrouter/moonshotai/kimi-k2.6".to_string(),
1057            model: "moonshotai/kimi-k2.6".to_string(),
1058            display_name: "Kimi K2.6 (OpenRouter)".to_string(),
1059            description: "Kimi K2.6 multimodal agentic model via OpenRouter".to_string(),
1060            provider: Provider::OpenRouter,
1061            default_reasoning_effort: ReasoningEffortLevel::Medium,
1062            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1063                effort: ReasoningEffortLevel::Medium,
1064                description: "Balanced".to_string(),
1065            }],
1066            is_default: false,
1067            upgrade: None,
1068            show_in_picker: true,
1069            supported_in_api: true,
1070            context_window: Some(262_144),
1071        },
1072        ModelPreset {
1073            id: "openrouter/qwen/qwen3.7-max".to_string(),
1074            model: "qwen/qwen3.7-max".to_string(),
1075            display_name: "Qwen3.7 Max (OpenRouter)".to_string(),
1076            description: "Qwen3.7 Max flagship model for coding and agentic workloads via OpenRouter".to_string(),
1077            provider: Provider::OpenRouter,
1078            default_reasoning_effort: ReasoningEffortLevel::Medium,
1079            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1080                effort: ReasoningEffortLevel::Medium,
1081                description: "Balanced".to_string(),
1082            }],
1083            is_default: false,
1084            upgrade: None,
1085            show_in_picker: true,
1086            supported_in_api: true,
1087            context_window: Some(1_000_000),
1088        },
1089        ModelPreset {
1090            id: "openrouter/tencent/hy3-preview".to_string(),
1091            model: "tencent/hy3-preview".to_string(),
1092            display_name: "Hy3 Preview (OpenRouter)".to_string(),
1093            description: "Tencent Hy3 high-efficiency MoE model with configurable reasoning via OpenRouter".to_string(),
1094            provider: Provider::OpenRouter,
1095            default_reasoning_effort: ReasoningEffortLevel::Medium,
1096            supported_reasoning_efforts: vec![
1097                ReasoningEffortPreset {
1098                    effort: ReasoningEffortLevel::Low,
1099                    description: "Fast".to_string(),
1100                },
1101                ReasoningEffortPreset {
1102                    effort: ReasoningEffortLevel::Medium,
1103                    description: "Balanced".to_string(),
1104                },
1105                ReasoningEffortPreset {
1106                    effort: ReasoningEffortLevel::High,
1107                    description: "Deep".to_string(),
1108                },
1109            ],
1110            is_default: false,
1111            upgrade: None,
1112            show_in_picker: true,
1113            supported_in_api: true,
1114            context_window: Some(262_144),
1115        },
1116        ModelPreset {
1117            id: "openrouter/x-ai/grok-build-0.1".to_string(),
1118            model: "x-ai/grok-build-0.1".to_string(),
1119            display_name: "Grok Build 0.1 (OpenRouter)".to_string(),
1120            description: "xAI Grok Build 0.1 coding model for agentic software engineering via OpenRouter".to_string(),
1121            provider: Provider::OpenRouter,
1122            default_reasoning_effort: ReasoningEffortLevel::Medium,
1123            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1124                effort: ReasoningEffortLevel::Medium,
1125                description: "Balanced".to_string(),
1126            }],
1127            is_default: false,
1128            upgrade: None,
1129            show_in_picker: true,
1130            supported_in_api: true,
1131            context_window: Some(256_000),
1132        },
1133        ModelPreset {
1134            id: "openrouter/xiaomi/mimo-v2.5".to_string(),
1135            model: "xiaomi/mimo-v2.5".to_string(),
1136            display_name: "MiMo-V2.5 (OpenRouter)".to_string(),
1137            description: "Xiaomi MiMo-V2.5 omnimodal agentic model for complex software engineering via OpenRouter".to_string(),
1138            provider: Provider::OpenRouter,
1139            default_reasoning_effort: ReasoningEffortLevel::Medium,
1140            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1141                effort: ReasoningEffortLevel::Medium,
1142                description: "Balanced".to_string(),
1143            }],
1144            is_default: false,
1145            upgrade: None,
1146            show_in_picker: true,
1147            supported_in_api: true,
1148            context_window: Some(1_000_000),
1149        },
1150        ModelPreset {
1151            id: "openrouter/xiaomi/mimo-v2.5-pro".to_string(),
1152            model: "xiaomi/mimo-v2.5-pro".to_string(),
1153            display_name: "MiMo-V2.5-Pro (OpenRouter)".to_string(),
1154            description: "Xiaomi MiMo-V2.5-Pro flagship agentic model for complex software engineering via OpenRouter".to_string(),
1155            provider: Provider::OpenRouter,
1156            default_reasoning_effort: ReasoningEffortLevel::Medium,
1157            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1158                effort: ReasoningEffortLevel::Medium,
1159                description: "Balanced".to_string(),
1160            }],
1161            is_default: true,
1162            upgrade: None,
1163            show_in_picker: true,
1164            supported_in_api: true,
1165            context_window: Some(1_000_000),
1166        },
1167        ModelPreset {
1168            id: "openrouter/poolside/laguna-m.1:free".to_string(),
1169            model: "poolside/laguna-m.1:free".to_string(),
1170            display_name: "Laguna M.1 free (OpenRouter)".to_string(),
1171            description: "Poolside Laguna M.1 flagship free coding agent model via OpenRouter".to_string(),
1172            provider: Provider::OpenRouter,
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(262_144),
1183        },
1184    ]
1185}
1186
1187fn ollama_presets() -> Vec<ModelPreset> {
1188    vec![
1189        ModelPreset {
1190            id: "ollama/gpt-oss:20b".to_string(),
1191            model: "gpt-oss:20b".to_string(),
1192            display_name: "GPT-OSS 20B (Ollama)".to_string(),
1193            description: "Open-weight GPT-OSS served locally".to_string(),
1194            provider: Provider::Ollama,
1195            default_reasoning_effort: ReasoningEffortLevel::Medium,
1196            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1197                effort: ReasoningEffortLevel::Medium,
1198                description: "Balanced".to_string(),
1199            }],
1200            is_default: true,
1201            upgrade: None,
1202            show_in_picker: true,
1203            supported_in_api: true,
1204            context_window: Some(96_000),
1205        },
1206        ModelPreset {
1207            id: "ollama/deepseek-v4-flash:cloud".to_string(),
1208            model: "deepseek-v4-flash:cloud".to_string(),
1209            display_name: "DeepSeek V4 Flash (Ollama)".to_string(),
1210            description: "Fast inference DeepSeek V4 Flash model via Ollama Cloud".to_string(),
1211            provider: Provider::Ollama,
1212            default_reasoning_effort: ReasoningEffortLevel::Medium,
1213            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1214                effort: ReasoningEffortLevel::Medium,
1215                description: "Balanced".to_string(),
1216            }],
1217            is_default: false,
1218            upgrade: None,
1219            show_in_picker: true,
1220            supported_in_api: true,
1221            context_window: Some(128_000),
1222        },
1223        ModelPreset {
1224            id: "ollama/deepseek-v4-pro:cloud".to_string(),
1225            model: "deepseek-v4-pro:cloud".to_string(),
1226            display_name: "DeepSeek V4 Pro (Ollama)".to_string(),
1227            description: "High-performance DeepSeek V4 Pro model via Ollama Cloud".to_string(),
1228            provider: Provider::Ollama,
1229            default_reasoning_effort: ReasoningEffortLevel::Medium,
1230            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1231                effort: ReasoningEffortLevel::Medium,
1232                description: "Balanced".to_string(),
1233            }],
1234            is_default: false,
1235            upgrade: None,
1236            show_in_picker: true,
1237            supported_in_api: true,
1238            context_window: Some(128_000),
1239        },
1240        ModelPreset {
1241            id: "ollama/nemotron-3-ultra:cloud".to_string(),
1242            model: "nemotron-3-ultra:cloud".to_string(),
1243            display_name: "Nemotron 3 Ultra (Ollama)".to_string(),
1244            description: "NVIDIA Nemotron 3 Ultra 550B for high-throughput reasoning and long-running agent workflows via Ollama Cloud".to_string(),
1245            provider: Provider::Ollama,
1246            default_reasoning_effort: ReasoningEffortLevel::Medium,
1247            supported_reasoning_efforts: vec![
1248                ReasoningEffortPreset {
1249                    effort: ReasoningEffortLevel::Medium,
1250                    description: "Balanced".to_string(),
1251                },
1252                ReasoningEffortPreset {
1253                    effort: ReasoningEffortLevel::High,
1254                    description: "Deep".to_string(),
1255                },
1256            ],
1257            is_default: false,
1258            upgrade: None,
1259            show_in_picker: true,
1260            supported_in_api: true,
1261            context_window: Some(256_000),
1262        },
1263        ModelPreset {
1264            id: "ollama/gemma4".to_string(),
1265            model: "gemma4".to_string(),
1266            display_name: "Gemma 4 (Ollama)".to_string(),
1267            description: "Google Gemma 4 for reasoning, agentic workflows, coding, and multimodal understanding".to_string(),
1268            provider: Provider::Ollama,
1269            default_reasoning_effort: ReasoningEffortLevel::Medium,
1270            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1271                effort: ReasoningEffortLevel::Medium,
1272                description: "Balanced".to_string(),
1273            }],
1274            is_default: false,
1275            upgrade: None,
1276            show_in_picker: true,
1277            supported_in_api: true,
1278            context_window: Some(128_000),
1279        },
1280        ModelPreset {
1281            id: "ollama/minimax-m3:cloud".to_string(),
1282            model: "minimax-m3:cloud".to_string(),
1283            display_name: "MiniMax-M3 (Ollama)".to_string(),
1284            description: "Cloud-hosted MiniMax-M3 model via Ollama Cloud".to_string(),
1285            provider: Provider::Ollama,
1286            default_reasoning_effort: ReasoningEffortLevel::Medium,
1287            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1288                effort: ReasoningEffortLevel::Medium,
1289                description: "Balanced".to_string(),
1290            }],
1291            is_default: false,
1292            upgrade: None,
1293            show_in_picker: true,
1294            supported_in_api: true,
1295            context_window: Some(131_072),
1296        },
1297    ]
1298}
1299
1300fn lmstudio_presets() -> Vec<ModelPreset> {
1301    use crate::config::constants::models::lmstudio as lmstudio_models;
1302    vec![
1303        ModelPreset {
1304            id: format!("lmstudio/{}", lmstudio_models::DEEPSEEK_R1_0528_QWEN3_8B),
1305            model: lmstudio_models::DEEPSEEK_R1_0528_QWEN3_8B.to_string(),
1306            display_name: "DeepSeek R1 0528 Qwen3 8B (LM Studio)".to_string(),
1307            description: "DeepSeek R1 distill on Qwen3 8B, reasoning-capable local model"
1308                .to_string(),
1309            provider: Provider::LmStudio,
1310            default_reasoning_effort: ReasoningEffortLevel::Medium,
1311            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1312                effort: ReasoningEffortLevel::Medium,
1313                description: "Balanced".to_string(),
1314            }],
1315            is_default: false,
1316            upgrade: None,
1317            show_in_picker: true,
1318            supported_in_api: true,
1319            context_window: Some(131_072),
1320        },
1321        ModelPreset {
1322            id: format!("lmstudio/{}", lmstudio_models::QWEN3_8B),
1323            model: lmstudio_models::QWEN3_8B.to_string(),
1324            display_name: "Qwen 3 8B (LM Studio)".to_string(),
1325            description: "Qwen 3 8B with thinking mode support for local inference".to_string(),
1326            provider: Provider::LmStudio,
1327            default_reasoning_effort: ReasoningEffortLevel::Medium,
1328            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1329                effort: ReasoningEffortLevel::Medium,
1330                description: "Balanced".to_string(),
1331            }],
1332            is_default: true,
1333            upgrade: None,
1334            show_in_picker: true,
1335            supported_in_api: true,
1336            context_window: Some(131_072),
1337        },
1338        ModelPreset {
1339            id: format!("lmstudio/{}", lmstudio_models::OPENAI_GPT_OSS_20B),
1340            model: lmstudio_models::OPENAI_GPT_OSS_20B.to_string(),
1341            display_name: "GPT-OSS 20B (LM Studio)".to_string(),
1342            description: "OpenAI's open-weight GPT-OSS 20B model served locally via LM Studio"
1343                .to_string(),
1344            provider: Provider::LmStudio,
1345            default_reasoning_effort: ReasoningEffortLevel::Medium,
1346            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1347                effort: ReasoningEffortLevel::Medium,
1348                description: "Balanced".to_string(),
1349            }],
1350            is_default: false,
1351            upgrade: None,
1352            show_in_picker: true,
1353            supported_in_api: true,
1354            context_window: Some(131_072),
1355        },
1356        ModelPreset {
1357            id: format!("lmstudio/{}", lmstudio_models::META_LLAMA_31_8B_INSTRUCT),
1358            model: lmstudio_models::META_LLAMA_31_8B_INSTRUCT.to_string(),
1359            display_name: "Llama 3.1 8B (LM Studio)".to_string(),
1360            description: "Meta Llama 3.1 8B Instruct for general-purpose local inference"
1361                .to_string(),
1362            provider: Provider::LmStudio,
1363            default_reasoning_effort: ReasoningEffortLevel::Medium,
1364            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1365                effort: ReasoningEffortLevel::Medium,
1366                description: "Balanced".to_string(),
1367            }],
1368            is_default: false,
1369            upgrade: None,
1370            show_in_picker: true,
1371            supported_in_api: true,
1372            context_window: Some(131_072),
1373        },
1374        ModelPreset {
1375            id: format!("lmstudio/{}", lmstudio_models::QWEN25_7B_INSTRUCT),
1376            model: lmstudio_models::QWEN25_7B_INSTRUCT.to_string(),
1377            display_name: "Qwen 2.5 7B (LM Studio)".to_string(),
1378            description: "Qwen 2.5 7B Instruct with tool calling support".to_string(),
1379            provider: Provider::LmStudio,
1380            default_reasoning_effort: ReasoningEffortLevel::Medium,
1381            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1382                effort: ReasoningEffortLevel::Medium,
1383                description: "Balanced".to_string(),
1384            }],
1385            is_default: false,
1386            upgrade: None,
1387            show_in_picker: true,
1388            supported_in_api: true,
1389            context_window: Some(32_768),
1390        },
1391        ModelPreset {
1392            id: format!("lmstudio/{}", lmstudio_models::GEMMA_3_12B_IT),
1393            model: lmstudio_models::GEMMA_3_12B_IT.to_string(),
1394            display_name: "Gemma 3 12B (LM Studio)".to_string(),
1395            description: "Google Gemma 3 12B IT for local inference".to_string(),
1396            provider: Provider::LmStudio,
1397            default_reasoning_effort: ReasoningEffortLevel::Medium,
1398            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1399                effort: ReasoningEffortLevel::Medium,
1400                description: "Balanced".to_string(),
1401            }],
1402            is_default: false,
1403            upgrade: None,
1404            show_in_picker: true,
1405            supported_in_api: true,
1406            context_window: Some(32_768),
1407        },
1408    ]
1409}
1410
1411fn llamacpp_presets() -> Vec<ModelPreset> {
1412    vec![
1413        ModelPreset {
1414            id: format!("llamacpp/{}", llamacpp_models::GPT_OSS_20B),
1415            model: llamacpp_models::GPT_OSS_20B.to_string(),
1416            display_name: "GPT-OSS 20B (llama.cpp)".to_string(),
1417            description: "OpenAI's open-weight GPT-OSS 20B model served locally through llama.cpp"
1418                .to_string(),
1419            provider: Provider::LlamaCpp,
1420            default_reasoning_effort: ReasoningEffortLevel::Medium,
1421            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1422                effort: ReasoningEffortLevel::Medium,
1423                description: "Balanced".to_string(),
1424            }],
1425            is_default: true,
1426            upgrade: None,
1427            show_in_picker: true,
1428            supported_in_api: true,
1429            context_window: Some(131_072),
1430        },
1431        ModelPreset {
1432            id: format!("llamacpp/{}", llamacpp_models::QWEN36_27B),
1433            model: llamacpp_models::QWEN36_27B.to_string(),
1434            display_name: "Qwen 3.6 27B (llama.cpp)".to_string(),
1435            description: "Dense Qwen 3.6 local model served through llama.cpp".to_string(),
1436            provider: Provider::LlamaCpp,
1437            default_reasoning_effort: ReasoningEffortLevel::Medium,
1438            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1439                effort: ReasoningEffortLevel::Medium,
1440                description: "Balanced".to_string(),
1441            }],
1442            is_default: false,
1443            upgrade: None,
1444            show_in_picker: true,
1445            supported_in_api: true,
1446            context_window: Some(262_144),
1447        },
1448        ModelPreset {
1449            id: format!("llamacpp/{}", llamacpp_models::QWEN36_35B_A3B),
1450            model: llamacpp_models::QWEN36_35B_A3B.to_string(),
1451            display_name: "Qwen 3.6 35B A3B (llama.cpp)".to_string(),
1452            description: "Qwen 3.6 MoE local model served through llama.cpp".to_string(),
1453            provider: Provider::LlamaCpp,
1454            default_reasoning_effort: ReasoningEffortLevel::Medium,
1455            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1456                effort: ReasoningEffortLevel::Medium,
1457                description: "Balanced".to_string(),
1458            }],
1459            is_default: false,
1460            upgrade: None,
1461            show_in_picker: true,
1462            supported_in_api: true,
1463            context_window: Some(262_144),
1464        },
1465        ModelPreset {
1466            id: format!("llamacpp/{}", llamacpp_models::GEMMA_4_26B_A4B),
1467            model: llamacpp_models::GEMMA_4_26B_A4B.to_string(),
1468            display_name: "Gemma 4 26B A4B (llama.cpp)".to_string(),
1469            description: "Gemma 4 desktop MoE model served through llama.cpp".to_string(),
1470            provider: Provider::LlamaCpp,
1471            default_reasoning_effort: ReasoningEffortLevel::Medium,
1472            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1473                effort: ReasoningEffortLevel::Medium,
1474                description: "Balanced".to_string(),
1475            }],
1476            is_default: false,
1477            upgrade: None,
1478            show_in_picker: true,
1479            supported_in_api: true,
1480            context_window: Some(262_144),
1481        },
1482        ModelPreset {
1483            id: format!("llamacpp/{}", llamacpp_models::GEMMA_4_E4B),
1484            model: llamacpp_models::GEMMA_4_E4B.to_string(),
1485            display_name: "Gemma 4 E4B (llama.cpp)".to_string(),
1486            description: "Tiny-footprint Gemma 4 model served through llama.cpp".to_string(),
1487            provider: Provider::LlamaCpp,
1488            default_reasoning_effort: ReasoningEffortLevel::Low,
1489            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1490                effort: ReasoningEffortLevel::Low,
1491                description: "Fast".to_string(),
1492            }],
1493            is_default: false,
1494            upgrade: None,
1495            show_in_picker: true,
1496            supported_in_api: true,
1497            context_window: Some(131_072),
1498        },
1499        ModelPreset {
1500            id: format!("llamacpp/{}", llamacpp_models::STEP_3_5_FLASH),
1501            model: llamacpp_models::STEP_3_5_FLASH.to_string(),
1502            display_name: "Step 3.5 Flash (llama.cpp)".to_string(),
1503            description: "StepFun's efficient reasoning model served through llama.cpp".to_string(),
1504            provider: Provider::LlamaCpp,
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(262_144),
1515        },
1516    ]
1517}
1518
1519fn opencode_zen_presets() -> Vec<ModelPreset> {
1520    vec![ModelPreset {
1521        id: "opencode/gpt-5.4".to_string(),
1522        model: "gpt-5.4".to_string(),
1523        display_name: "GPT-5.4 (OpenCode Zen)".to_string(),
1524        description: "OpenCode Zen gateway — curated, benchmarked models at cost".to_string(),
1525        provider: Provider::OpenCodeZen,
1526        default_reasoning_effort: ReasoningEffortLevel::Medium,
1527        supported_reasoning_efforts: vec![ReasoningEffortPreset {
1528            effort: ReasoningEffortLevel::Medium,
1529            description: "Balanced".to_string(),
1530        }],
1531        is_default: true,
1532        upgrade: None,
1533        show_in_picker: true,
1534        supported_in_api: true,
1535        context_window: Some(1_050_000),
1536    }]
1537}
1538
1539fn opencode_go_presets() -> Vec<ModelPreset> {
1540    vec![ModelPreset {
1541        id: "opencode-go/kimi-k2.5".to_string(),
1542        model: "kimi-k2.5".to_string(),
1543        display_name: "Kimi K2.5 (OpenCode Go)".to_string(),
1544        description: "OpenCode Go — affordable subscription for open coding models".to_string(),
1545        provider: Provider::OpenCodeGo,
1546        default_reasoning_effort: ReasoningEffortLevel::Medium,
1547        supported_reasoning_efforts: vec![ReasoningEffortPreset {
1548            effort: ReasoningEffortLevel::Medium,
1549            description: "Balanced".to_string(),
1550        }],
1551        is_default: true,
1552        upgrade: None,
1553        show_in_picker: true,
1554        supported_in_api: true,
1555        context_window: Some(256_000),
1556    }]
1557}
1558
1559fn poolside_presets() -> Vec<ModelPreset> {
1560    vec![
1561        ModelPreset {
1562            id: poolside_models::LAGUNA_M1.to_string(),
1563            model: poolside_models::LAGUNA_M1.to_string(),
1564            display_name: "Laguna M.1".to_string(),
1565            description:
1566                "Poolside's flagship MoE coding agent model optimized for multi-step agentic tasks, tool use, and validation (128K context)"
1567                    .to_string(),
1568            provider: Provider::Poolside,
1569            default_reasoning_effort: ReasoningEffortLevel::Medium,
1570            supported_reasoning_efforts: Vec::new(),
1571            is_default: true,
1572            upgrade: None,
1573            show_in_picker: true,
1574            supported_in_api: true,
1575            context_window: Some(131_072),
1576        },
1577        ModelPreset {
1578            id: poolside_models::LAGUNA_XS2.to_string(),
1579            model: poolside_models::LAGUNA_XS2.to_string(),
1580            display_name: "Laguna XS.2".to_string(),
1581            description:
1582                "Poolside's efficient MoE coding agent model optimized for fast agentic coding (128K context)"
1583                    .to_string(),
1584            provider: Provider::Poolside,
1585            default_reasoning_effort: ReasoningEffortLevel::Medium,
1586            supported_reasoning_efforts: Vec::new(),
1587            is_default: false,
1588            upgrade: None,
1589            show_in_picker: true,
1590            supported_in_api: true,
1591            context_window: Some(131_072),
1592        },
1593    ]
1594}
1595
1596fn mimo_presets() -> Vec<ModelPreset> {
1597    vec![
1598        ModelPreset {
1599            id: mimo_models::MIMO_V2_5_PRO.to_string(),
1600            model: mimo_models::MIMO_V2_5_PRO.to_string(),
1601            display_name: "MiMo V2.5 Pro".to_string(),
1602            description:
1603                "Xiaomi's flagship reasoning model with advanced capabilities (1M context)"
1604                    .to_string(),
1605            provider: Provider::MiMo,
1606            default_reasoning_effort: ReasoningEffortLevel::Medium,
1607            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1608                effort: ReasoningEffortLevel::Medium,
1609                description: "Balanced".to_string(),
1610            }],
1611            is_default: true,
1612            upgrade: None,
1613            show_in_picker: true,
1614            supported_in_api: true,
1615            context_window: Some(1_048_576),
1616        },
1617        ModelPreset {
1618            id: mimo_models::MIMO_V2_5.to_string(),
1619            model: mimo_models::MIMO_V2_5.to_string(),
1620            display_name: "MiMo V2.5".to_string(),
1621            description: "Xiaomi's general-purpose model with strong reasoning (1M context)"
1622                .to_string(),
1623            provider: Provider::MiMo,
1624            default_reasoning_effort: ReasoningEffortLevel::Medium,
1625            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1626                effort: ReasoningEffortLevel::Medium,
1627                description: "Balanced".to_string(),
1628            }],
1629            is_default: false,
1630            upgrade: None,
1631            show_in_picker: true,
1632            supported_in_api: true,
1633            context_window: Some(1_048_576),
1634        },
1635        ModelPreset {
1636            id: mimo_models::MIMO_V2_FLASH.to_string(),
1637            model: mimo_models::MIMO_V2_FLASH.to_string(),
1638            display_name: "MiMo V2 Flash".to_string(),
1639            description: "Xiaomi's lightweight fast model for high-throughput tasks (256K context)"
1640                .to_string(),
1641            provider: Provider::MiMo,
1642            default_reasoning_effort: ReasoningEffortLevel::Low,
1643            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1644                effort: ReasoningEffortLevel::Low,
1645                description: "Fast".to_string(),
1646            }],
1647            is_default: false,
1648            upgrade: None,
1649            show_in_picker: true,
1650            supported_in_api: true,
1651            context_window: Some(262_144),
1652        },
1653    ]
1654}
1655
1656fn qwen_presets() -> Vec<ModelPreset> {
1657    vec![
1658        ModelPreset {
1659            id: qwen_models::QWEN3_7_MAX.to_string(),
1660            model: qwen_models::QWEN3_7_MAX.to_string(),
1661            display_name: "Qwen 3.7 Max".to_string(),
1662            description:
1663                "Alibaba Cloud's flagship reasoning model with 131K context and advanced thinking"
1664                    .to_string(),
1665            provider: Provider::Qwen,
1666            default_reasoning_effort: ReasoningEffortLevel::Medium,
1667            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1668                effort: ReasoningEffortLevel::Medium,
1669                description: "Balanced".to_string(),
1670            }],
1671            is_default: true,
1672            upgrade: None,
1673            show_in_picker: true,
1674            supported_in_api: true,
1675            context_window: Some(131_072),
1676        },
1677        ModelPreset {
1678            id: qwen_models::QWEN3_6_FLASH.to_string(),
1679            model: qwen_models::QWEN3_6_FLASH.to_string(),
1680            display_name: "Qwen 3.6 Flash".to_string(),
1681            description:
1682                "Alibaba Cloud's fast inference model with 1M context, optimized for speed and cost-efficiency"
1683                    .to_string(),
1684            provider: Provider::Qwen,
1685            default_reasoning_effort: ReasoningEffortLevel::Low,
1686            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1687                effort: ReasoningEffortLevel::Low,
1688                description: "Fast".to_string(),
1689            }],
1690            is_default: false,
1691            upgrade: None,
1692            show_in_picker: true,
1693            supported_in_api: true,
1694            context_window: Some(1_048_576),
1695        },
1696        ModelPreset {
1697            id: qwen_models::QWEN3_6_PLUS.to_string(),
1698            model: qwen_models::QWEN3_6_PLUS.to_string(),
1699            display_name: "Qwen 3.6 Plus".to_string(),
1700            description:
1701                "Alibaba Cloud's balanced model with 131K context, strong reasoning and coding performance"
1702                    .to_string(),
1703            provider: Provider::Qwen,
1704            default_reasoning_effort: ReasoningEffortLevel::Medium,
1705            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1706                effort: ReasoningEffortLevel::Medium,
1707                description: "Balanced".to_string(),
1708            }],
1709            is_default: false,
1710            upgrade: None,
1711            show_in_picker: true,
1712            supported_in_api: true,
1713            context_window: Some(131_072),
1714        },
1715        ModelPreset {
1716            id: qwen_models::DEEPSEEK_V4_FLASH.to_string(),
1717            model: qwen_models::DEEPSEEK_V4_FLASH.to_string(),
1718            display_name: "DeepSeek V4 Flash (Qwen)".to_string(),
1719            description:
1720                "DeepSeek V4 Flash fast inference model served through Qwen Cloud API (1M context)"
1721                    .to_string(),
1722            provider: Provider::Qwen,
1723            default_reasoning_effort: ReasoningEffortLevel::Low,
1724            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1725                effort: ReasoningEffortLevel::Low,
1726                description: "Fast".to_string(),
1727            }],
1728            is_default: false,
1729            upgrade: None,
1730            show_in_picker: true,
1731            supported_in_api: true,
1732            context_window: Some(1_048_576),
1733        },
1734        ModelPreset {
1735            id: qwen_models::DEEPSEEK_V4_PRO.to_string(),
1736            model: qwen_models::DEEPSEEK_V4_PRO.to_string(),
1737            display_name: "DeepSeek V4 Pro (Qwen)".to_string(),
1738            description:
1739                "DeepSeek V4 Pro high-performance reasoning model served through Qwen Cloud API (1M context)"
1740                    .to_string(),
1741            provider: Provider::Qwen,
1742            default_reasoning_effort: ReasoningEffortLevel::Medium,
1743            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1744                effort: ReasoningEffortLevel::Medium,
1745                description: "Balanced".to_string(),
1746            }],
1747            is_default: false,
1748            upgrade: None,
1749            show_in_picker: true,
1750            supported_in_api: true,
1751            context_window: Some(1_048_576),
1752        },
1753        ModelPreset {
1754            id: qwen_models::GLM_5_1.to_string(),
1755            model: qwen_models::GLM_5_1.to_string(),
1756            display_name: "GLM-5.1 (Qwen)".to_string(),
1757            description:
1758                "Z.AI GLM-5.1 next-gen foundation model served through Qwen Cloud API"
1759                    .to_string(),
1760            provider: Provider::Qwen,
1761            default_reasoning_effort: ReasoningEffortLevel::Medium,
1762            supported_reasoning_efforts: vec![ReasoningEffortPreset {
1763                effort: ReasoningEffortLevel::Medium,
1764                description: "Balanced".to_string(),
1765            }],
1766            is_default: false,
1767            upgrade: None,
1768            show_in_picker: true,
1769            supported_in_api: true,
1770            context_window: Some(131_072),
1771        },
1772    ]
1773}
1774
1775fn stepfun_presets() -> Vec<ModelPreset> {
1776    vec![ModelPreset {
1777        id: stepfun_models::STEP_3_7_FLASH.to_string(),
1778        model: stepfun_models::STEP_3_7_FLASH.to_string(),
1779        display_name: "Step 3.7 Flash".to_string(),
1780        description:
1781            "StepFun's flagship multimodal reasoning model with 256K context and tool calling."
1782                .to_string(),
1783        provider: Provider::StepFun,
1784        default_reasoning_effort: ReasoningEffortLevel::Medium,
1785        supported_reasoning_efforts: vec![
1786            reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1787            reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1788            reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1789        ],
1790        is_default: true,
1791        upgrade: None,
1792        show_in_picker: true,
1793        supported_in_api: true,
1794        context_window: Some(262_144),
1795    }]
1796}
1797
1798fn evolink_presets() -> Vec<ModelPreset> {
1799    vec![
1800        ModelPreset {
1801            id: "evolink/gpt-5.2".to_string(),
1802            model: evolink_models::GPT_5_2.to_string(),
1803            display_name: "GPT-5.2 (Evolink)".to_string(),
1804            description: "GPT-5.2 served through the Evolink OpenAI-compatible gateway."
1805                .to_string(),
1806            provider: Provider::Evolink,
1807            default_reasoning_effort: ReasoningEffortLevel::Medium,
1808            supported_reasoning_efforts: vec![reasoning_preset(
1809                ReasoningEffortLevel::Medium,
1810                "Balanced",
1811            )],
1812            is_default: true,
1813            upgrade: None,
1814            show_in_picker: true,
1815            supported_in_api: true,
1816            context_window: Some(400_000),
1817        },
1818        ModelPreset {
1819            id: "evolink/gpt-5.5".to_string(),
1820            model: evolink_models::GPT_5_5.to_string(),
1821            display_name: "GPT-5.5 (Evolink)".to_string(),
1822            description: "GPT-5.5 flagship model served through the Evolink gateway.".to_string(),
1823            provider: Provider::Evolink,
1824            default_reasoning_effort: ReasoningEffortLevel::Medium,
1825            supported_reasoning_efforts: vec![reasoning_preset(
1826                ReasoningEffortLevel::Medium,
1827                "Balanced",
1828            )],
1829            is_default: false,
1830            upgrade: None,
1831            show_in_picker: true,
1832            supported_in_api: true,
1833            context_window: Some(400_000),
1834        },
1835        ModelPreset {
1836            id: "evolink/deepseek-v4-pro".to_string(),
1837            model: evolink_models::DEEPSEEK_V4_PRO.to_string(),
1838            display_name: "DeepSeek V4 Pro (Evolink)".to_string(),
1839            description: "DeepSeek V4 Pro reasoning model served through the Evolink gateway."
1840                .to_string(),
1841            provider: Provider::Evolink,
1842            default_reasoning_effort: ReasoningEffortLevel::Medium,
1843            supported_reasoning_efforts: vec![
1844                reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1845                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1846                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1847            ],
1848            is_default: false,
1849            upgrade: None,
1850            show_in_picker: true,
1851            supported_in_api: true,
1852            context_window: Some(163_840),
1853        },
1854        ModelPreset {
1855            id: "evolink/deepseek-v4-flash".to_string(),
1856            model: evolink_models::DEEPSEEK_V4_FLASH.to_string(),
1857            display_name: "DeepSeek V4 Flash (Evolink)".to_string(),
1858            description:
1859                "DeepSeek V4 Flash fast inference model served through the Evolink gateway."
1860                    .to_string(),
1861            provider: Provider::Evolink,
1862            default_reasoning_effort: ReasoningEffortLevel::Medium,
1863            supported_reasoning_efforts: vec![
1864                reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1865                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1866                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1867            ],
1868            is_default: false,
1869            upgrade: None,
1870            show_in_picker: true,
1871            supported_in_api: true,
1872            context_window: Some(1_000_000),
1873        },
1874        ModelPreset {
1875            id: "evolink/doubao-seed-2.0-pro".to_string(),
1876            model: evolink_models::DOUBAO_SEED_2_0_PRO.to_string(),
1877            display_name: "Doubao Seed 2.0 Pro (Evolink)".to_string(),
1878            description: "Doubao Seed 2.0 Pro served through the Evolink gateway.".to_string(),
1879            provider: Provider::Evolink,
1880            default_reasoning_effort: ReasoningEffortLevel::Medium,
1881            supported_reasoning_efforts: vec![
1882                reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1883                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1884                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1885            ],
1886            is_default: false,
1887            upgrade: None,
1888            show_in_picker: true,
1889            supported_in_api: true,
1890            context_window: Some(262_144),
1891        },
1892        ModelPreset {
1893            id: "evolink/gemini-3.1-pro-preview".to_string(),
1894            model: evolink_models::GEMINI_3_1_PRO.to_string(),
1895            display_name: "Gemini 3.1 Pro (Evolink)".to_string(),
1896            description: "Gemini 3.1 Pro served through the Evolink gateway via OpenAI SDK format."
1897                .to_string(),
1898            provider: Provider::Evolink,
1899            default_reasoning_effort: ReasoningEffortLevel::Medium,
1900            supported_reasoning_efforts: vec![reasoning_preset(
1901                ReasoningEffortLevel::Medium,
1902                "Balanced",
1903            )],
1904            is_default: false,
1905            upgrade: None,
1906            show_in_picker: true,
1907            supported_in_api: true,
1908            context_window: Some(1_000_000),
1909        },
1910        ModelPreset {
1911            id: "evolink/gemini-3.5-flash".to_string(),
1912            model: evolink_models::GEMINI_3_5_FLASH.to_string(),
1913            display_name: "Gemini 3.5 Flash (Evolink)".to_string(),
1914            description:
1915                "Gemini 3.5 Flash served through the Evolink gateway via OpenAI SDK format."
1916                    .to_string(),
1917            provider: Provider::Evolink,
1918            default_reasoning_effort: ReasoningEffortLevel::Medium,
1919            supported_reasoning_efforts: vec![reasoning_preset(
1920                ReasoningEffortLevel::Medium,
1921                "Balanced",
1922            )],
1923            is_default: false,
1924            upgrade: None,
1925            show_in_picker: true,
1926            supported_in_api: true,
1927            context_window: Some(1_000_000),
1928        },
1929        ModelPreset {
1930            id: "evolink/MiniMax-M3".to_string(),
1931            model: evolink_models::MINIMAX_M3.to_string(),
1932            display_name: "MiniMax-M3 (Evolink)".to_string(),
1933            description: "MiniMax-M3 frontier multimodal model served through the Evolink gateway."
1934                .to_string(),
1935            provider: Provider::Evolink,
1936            default_reasoning_effort: ReasoningEffortLevel::Medium,
1937            supported_reasoning_efforts: vec![reasoning_preset(
1938                ReasoningEffortLevel::Medium,
1939                "Balanced",
1940            )],
1941            is_default: false,
1942            upgrade: None,
1943            show_in_picker: true,
1944            supported_in_api: true,
1945            context_window: Some(1_000_000),
1946        },
1947        ModelPreset {
1948            id: "evolink/claude-sonnet-4-6".to_string(),
1949            model: evolink_models::CLAUDE_SONNET_4_6.to_string(),
1950            display_name: "Claude Sonnet 4.6 (Evolink)".to_string(),
1951            description: "Claude Sonnet 4.6 served through Evolink via Anthropic Messages API."
1952                .to_string(),
1953            provider: Provider::Evolink,
1954            default_reasoning_effort: ReasoningEffortLevel::Medium,
1955            supported_reasoning_efforts: vec![reasoning_preset(
1956                ReasoningEffortLevel::Medium,
1957                "Balanced",
1958            )],
1959            is_default: false,
1960            upgrade: None,
1961            show_in_picker: true,
1962            supported_in_api: true,
1963            context_window: Some(200_000),
1964        },
1965        ModelPreset {
1966            id: "evolink/claude-opus-4-8".to_string(),
1967            model: evolink_models::CLAUDE_OPUS_4_8.to_string(),
1968            display_name: "Claude Opus 4.8 (Evolink)".to_string(),
1969            description: "Claude Opus 4.8 served through Evolink via Anthropic Messages API."
1970                .to_string(),
1971            provider: Provider::Evolink,
1972            default_reasoning_effort: ReasoningEffortLevel::High,
1973            supported_reasoning_efforts: vec![
1974                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1975                reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1976            ],
1977            is_default: false,
1978            upgrade: None,
1979            show_in_picker: true,
1980            supported_in_api: true,
1981            context_window: Some(200_000),
1982        },
1983        ModelPreset {
1984            id: "evolink/claude-haiku-4-5-20251001".to_string(),
1985            model: evolink_models::CLAUDE_HAIKU_4_5.to_string(),
1986            display_name: "Claude Haiku 4.5 (Evolink)".to_string(),
1987            description:
1988                "Claude Haiku 4.5 fast model served through Evolink via Anthropic Messages API."
1989                    .to_string(),
1990            provider: Provider::Evolink,
1991            default_reasoning_effort: ReasoningEffortLevel::Low,
1992            supported_reasoning_efforts: vec![
1993                reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1994                reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1995            ],
1996            is_default: false,
1997            upgrade: None,
1998            show_in_picker: true,
1999            supported_in_api: true,
2000            context_window: Some(200_000),
2001        },
2002    ]
2003}
2004
2005fn moonshot_presets() -> Vec<ModelPreset> {
2006    vec![
2007        ModelPreset {
2008            id: "kimi-k2.6".to_string(),
2009            model: "kimi-k2.6".to_string(),
2010            display_name: "Kimi K2.6 (Moonshot)".to_string(),
2011            description: "Moonshot's latest flagship coding and agent model.".to_string(),
2012            provider: Provider::Moonshot,
2013            default_reasoning_effort: ReasoningEffortLevel::Medium,
2014            supported_reasoning_efforts: vec![reasoning_preset(
2015                ReasoningEffortLevel::Medium,
2016                "Balanced",
2017            )],
2018            is_default: true,
2019            upgrade: None,
2020            show_in_picker: true,
2021            supported_in_api: true,
2022            context_window: Some(256_000),
2023        },
2024        ModelPreset {
2025            id: "kimi-k2.5".to_string(),
2026            model: "kimi-k2.5".to_string(),
2027            display_name: "Kimi K2.5 (Moonshot)".to_string(),
2028            description: "Moonshot's previous flagship model for long-context coding.".to_string(),
2029            provider: Provider::Moonshot,
2030            default_reasoning_effort: ReasoningEffortLevel::Medium,
2031            supported_reasoning_efforts: vec![reasoning_preset(
2032                ReasoningEffortLevel::Medium,
2033                "Balanced",
2034            )],
2035            is_default: false,
2036            upgrade: None,
2037            show_in_picker: true,
2038            supported_in_api: true,
2039            context_window: Some(256_000),
2040        },
2041    ]
2042}
2043
2044fn huggingface_presets() -> Vec<ModelPreset> {
2045    vec![
2046        ModelPreset {
2047            id: "huggingface/deepseek-v4-flash".to_string(),
2048            model: "deepseek-ai/DeepSeek-V4-Flash:novita".to_string(),
2049            display_name: "DeepSeek V4 Flash (HF/Novita)".to_string(),
2050            description:
2051                "Fast inference model for cost-effective reasoning (1M context, 158B params)"
2052                    .to_string(),
2053            provider: Provider::HuggingFace,
2054            default_reasoning_effort: ReasoningEffortLevel::High,
2055            supported_reasoning_efforts: vec![
2056                ReasoningEffortPreset {
2057                    effort: ReasoningEffortLevel::High,
2058                    description: "Balanced".to_string(),
2059                },
2060                ReasoningEffortPreset {
2061                    effort: ReasoningEffortLevel::Max,
2062                    description: "Maximum thinking".to_string(),
2063                },
2064            ],
2065            is_default: false,
2066            upgrade: None,
2067            show_in_picker: true,
2068            supported_in_api: true,
2069            context_window: Some(1_000_000),
2070        },
2071        ModelPreset {
2072            id: "huggingface/deepseek-v4-pro".to_string(),
2073            model: "deepseek-ai/DeepSeek-V4-Pro:together".to_string(),
2074            display_name: "DeepSeek V4 Pro (HF/Together)".to_string(),
2075            description:
2076                "High-performance reasoning model with advanced thinking capabilities (1M context, 1.6T params)"
2077                    .to_string(),
2078            provider: Provider::HuggingFace,
2079            default_reasoning_effort: ReasoningEffortLevel::High,
2080            supported_reasoning_efforts: vec![
2081                ReasoningEffortPreset {
2082                    effort: ReasoningEffortLevel::High,
2083                    description: "Balanced".to_string(),
2084                },
2085                ReasoningEffortPreset {
2086                    effort: ReasoningEffortLevel::Max,
2087                    description: "Maximum thinking".to_string(),
2088                },
2089            ],
2090            is_default: false,
2091            upgrade: None,
2092            show_in_picker: true,
2093            supported_in_api: true,
2094            context_window: Some(1_000_000),
2095        },
2096        ModelPreset {
2097            id: "huggingface/nvidia-nemotron-3-ultra".to_string(),
2098            model: "nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4:together".to_string(),
2099            display_name: "NVIDIA-Nemotron-3-Ultra-550B (HF/Together)".to_string(),
2100            description:
2101                "NVIDIA Nemotron 3 Ultra 550B-A55B-NVFP4 via Together inference provider"
2102                    .to_string(),
2103            provider: Provider::HuggingFace,
2104            default_reasoning_effort: ReasoningEffortLevel::High,
2105            supported_reasoning_efforts: vec![
2106                ReasoningEffortPreset {
2107                    effort: ReasoningEffortLevel::High,
2108                    description: "Balanced".to_string(),
2109                },
2110                ReasoningEffortPreset {
2111                    effort: ReasoningEffortLevel::Max,
2112                    description: "Maximum thinking".to_string(),
2113                },
2114            ],
2115            is_default: false,
2116            upgrade: None,
2117            show_in_picker: true,
2118            supported_in_api: true,
2119            context_window: Some(128_000),
2120        },
2121    ]
2122}
2123
2124/// Get all model presets (for testing)
2125#[cfg(test)]
2126pub fn all_model_presets() -> Vec<ModelPreset> {
2127    builtin_model_presets()
2128}
2129
2130#[cfg(test)]
2131mod tests {
2132    use super::*;
2133
2134    #[test]
2135    fn only_one_default_per_provider() {
2136        let presets = builtin_model_presets();
2137        let providers: Vec<Provider> = Provider::all_providers();
2138
2139        for provider in providers {
2140            let default_count = presets
2141                .iter()
2142                .filter(|p| p.provider == provider && p.is_default)
2143                .count();
2144            assert!(
2145                default_count <= 1,
2146                "Provider {:?} has {} defaults, expected 0 or 1",
2147                provider,
2148                default_count
2149            );
2150        }
2151    }
2152
2153    #[test]
2154    fn gemini_presets_exist() {
2155        let presets = gemini_presets();
2156        assert!(!presets.is_empty());
2157        assert!(presets.iter().any(|p| p.id.contains("gemini")));
2158    }
2159
2160    #[test]
2161    fn model_info_converts_to_preset() {
2162        let info = ModelInfo {
2163            slug: "test-model".to_string(),
2164            display_name: "Test Model".to_string(),
2165            description: "A test model".to_string(),
2166            provider: Provider::Gemini,
2167            default_reasoning_level: ReasoningEffortLevel::Medium,
2168            supported_reasoning_levels: vec![],
2169            context_window: Some(128_000),
2170            supports_tool_use: true,
2171            supports_streaming: true,
2172            supports_reasoning: false,
2173            priority: 0,
2174            visibility: "list".to_string(),
2175            supported_in_api: true,
2176            upgrade: None,
2177        };
2178
2179        let preset: ModelPreset = info.into();
2180        assert_eq!(preset.id, "test-model");
2181        assert_eq!(preset.model, "test-model");
2182        assert!(preset.show_in_picker);
2183    }
2184
2185    #[test]
2186    fn anthropic_opus_47_defaults_to_xhigh_and_offers_max() {
2187        let opus = anthropic_presets()
2188            .into_iter()
2189            .find(|preset| preset.id == "claude-opus-4-7")
2190            .expect("claude-opus-4-7 preset");
2191
2192        assert_eq!(opus.default_reasoning_effort, ReasoningEffortLevel::XHigh);
2193        assert!(
2194            opus.supported_reasoning_efforts
2195                .iter()
2196                .any(|preset| preset.effort == ReasoningEffortLevel::Max)
2197        );
2198    }
2199
2200    #[test]
2201    fn openai_codex_presets_default_to_high_reasoning() {
2202        let codex = openai_presets()
2203            .into_iter()
2204            .find(|preset| preset.id == "gpt-5.3-codex")
2205            .expect("gpt-5.3-codex preset");
2206
2207        assert_eq!(codex.default_reasoning_effort, ReasoningEffortLevel::High);
2208    }
2209
2210    #[test]
2211    fn moonshot_presets_exist_and_default_to_kimi_k26() {
2212        let presets = moonshot_presets();
2213        assert_eq!(presets.len(), 2);
2214        assert!(presets.iter().any(|preset| preset.id == "kimi-k2.5"));
2215
2216        let default = presets
2217            .iter()
2218            .find(|preset| preset.is_default)
2219            .expect("moonshot default preset");
2220        assert_eq!(default.id, "kimi-k2.6");
2221        assert_eq!(default.provider, Provider::Moonshot);
2222    }
2223}