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