Skip to main content

vtcode_core/models_manager/
model_presets.rs

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