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-opus-4-8".to_string(),
578 model: "claude-opus-4-8".to_string(),
579 display_name: "Claude Opus 4.8".to_string(),
580 description:
581 "Anthropic's most capable model for complex reasoning, long-horizon agentic coding, and high-autonomy work"
582 .to_string(),
583 provider: Provider::Anthropic,
584 default_reasoning_effort: ReasoningEffortLevel::XHigh,
585 supported_reasoning_efforts: vec![
586 ReasoningEffortPreset {
587 effort: ReasoningEffortLevel::Low,
588 description: "Fast adaptive effort".to_string(),
589 },
590 ReasoningEffortPreset {
591 effort: ReasoningEffortLevel::Medium,
592 description: "Balanced adaptive effort".to_string(),
593 },
594 ReasoningEffortPreset {
595 effort: ReasoningEffortLevel::High,
596 description: "Deep adaptive effort".to_string(),
597 },
598 ReasoningEffortPreset {
599 effort: ReasoningEffortLevel::XHigh,
600 description: "Recommended Opus 4.8 effort for coding and agentic work".to_string(),
601 },
602 ReasoningEffortPreset {
603 effort: ReasoningEffortLevel::Max,
604 description: "Maximum adaptive effort for intelligence-demanding tasks"
605 .to_string(),
606 },
607 ],
608 is_default: false,
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-sonnet-4-6".to_string(),
616 model: "claude-sonnet-4-6".to_string(),
617 display_name: "Claude Sonnet 4.6".to_string(),
618 description:
619 "The best combination of speed and intelligence. Supports extended thinking and adaptive thinking with 1M context."
620 .to_string(),
621 provider: Provider::Anthropic,
622 default_reasoning_effort: ReasoningEffortLevel::High,
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: "Default adaptive effort".to_string(),
635 },
636 ReasoningEffortPreset {
637 effort: ReasoningEffortLevel::Max,
638 description: "Maximum adaptive effort".to_string(),
639 },
640 ],
641 is_default: false,
642 upgrade: None,
643 show_in_picker: true,
644 supported_in_api: true,
645 context_window: Some(1_000_000),
646 },
647 ModelPreset {
648 id: "claude-haiku-4-5".to_string(),
649 model: "claude-haiku-4-5".to_string(),
650 display_name: "Claude Haiku 4.5".to_string(),
651 description: "The fastest model with near-frontier intelligence. Supports extended thinking with manual budget."
652 .to_string(),
653 provider: Provider::Anthropic,
654 default_reasoning_effort: ReasoningEffortLevel::Medium,
655 supported_reasoning_efforts: Vec::new(),
656 is_default: false,
657 upgrade: None,
658 show_in_picker: true,
659 supported_in_api: true,
660 context_window: Some(200_000),
661 },
662 ]
663}
664
665fn deepseek_presets() -> Vec<ModelPreset> {
666 vec![
667 ModelPreset {
668 id: "deepseek-v4-pro".to_string(),
669 model: "deepseek-v4-pro".to_string(),
670 display_name: "DeepSeek V4 Pro".to_string(),
671 description: "High-performance reasoning model with advanced thinking capabilities"
672 .to_string(),
673 provider: Provider::DeepSeek,
674 default_reasoning_effort: ReasoningEffortLevel::High,
675 supported_reasoning_efforts: vec![
676 ReasoningEffortPreset {
677 effort: ReasoningEffortLevel::High,
678 description: "Balanced".to_string(),
679 },
680 ReasoningEffortPreset {
681 effort: ReasoningEffortLevel::Max,
682 description: "Maximum thinking".to_string(),
683 },
684 ],
685 is_default: true,
686 upgrade: None,
687 show_in_picker: true,
688 supported_in_api: true,
689 context_window: Some(1_000_000),
690 },
691 ModelPreset {
692 id: "deepseek-v4-flash".to_string(),
693 model: "deepseek-v4-flash".to_string(),
694 display_name: "DeepSeek V4 Flash".to_string(),
695 description: "Fast inference model for cost-effective reasoning tasks".to_string(),
696 provider: Provider::DeepSeek,
697 default_reasoning_effort: ReasoningEffortLevel::High,
698 supported_reasoning_efforts: vec![
699 ReasoningEffortPreset {
700 effort: ReasoningEffortLevel::High,
701 description: "Balanced".to_string(),
702 },
703 ReasoningEffortPreset {
704 effort: ReasoningEffortLevel::Max,
705 description: "Maximum thinking".to_string(),
706 },
707 ],
708 is_default: false,
709 upgrade: None,
710 show_in_picker: true,
711 supported_in_api: true,
712 context_window: Some(1_000_000),
713 },
714 ]
715}
716
717fn zai_presets() -> Vec<ModelPreset> {
718 vec![ModelPreset {
719 id: "glm-5.1".to_string(),
720 model: "glm-5.1".to_string(),
721 display_name: "GLM-5.1".to_string(),
722 description:
723 "Z.ai's next-gen foundation model with improved reasoning and agent capabilities"
724 .to_string(),
725 provider: Provider::ZAI,
726 default_reasoning_effort: ReasoningEffortLevel::Medium,
727 supported_reasoning_efforts: vec![
728 ReasoningEffortPreset {
729 effort: ReasoningEffortLevel::Medium,
730 description: "Balanced".to_string(),
731 },
732 ReasoningEffortPreset {
733 effort: ReasoningEffortLevel::High,
734 description: "Deep thinking".to_string(),
735 },
736 ],
737 is_default: true,
738 upgrade: None,
739 show_in_picker: true,
740 supported_in_api: true,
741 context_window: Some(200_000),
742 }]
743}
744
745fn mistral_presets() -> Vec<ModelPreset> {
746 vec![
747 ModelPreset {
748 id: "mistral-large-2512".to_string(),
749 model: "mistral-large-2512".to_string(),
750 display_name: "Mistral Large 3".to_string(),
751 description:
752 "State-of-the-art open-weight general-purpose multimodal model (41B active, 675B total)".to_string(),
753 provider: Provider::Mistral,
754 default_reasoning_effort: ReasoningEffortLevel::Medium,
755 supported_reasoning_efforts: vec![
756 ReasoningEffortPreset {
757 effort: ReasoningEffortLevel::Medium,
758 description: "Balanced".to_string(),
759 },
760 ReasoningEffortPreset {
761 effort: ReasoningEffortLevel::High,
762 description: "Deep".to_string(),
763 },
764 ],
765 is_default: true,
766 upgrade: None,
767 show_in_picker: true,
768 supported_in_api: true,
769 context_window: Some(256_000),
770 },
771 ModelPreset {
772 id: "mistral-medium-3-5".to_string(),
773 model: "mistral-medium-3-5".to_string(),
774 display_name: "Mistral Medium 3.5".to_string(),
775 description:
776 "Frontier-class multimodal model optimized for agentic and coding use cases (256k context)"
777 .to_string(),
778 provider: Provider::Mistral,
779 default_reasoning_effort: ReasoningEffortLevel::Medium,
780 supported_reasoning_efforts: vec![
781 ReasoningEffortPreset {
782 effort: ReasoningEffortLevel::Medium,
783 description: "Balanced".to_string(),
784 },
785 ReasoningEffortPreset {
786 effort: ReasoningEffortLevel::High,
787 description: "Deep".to_string(),
788 },
789 ],
790 is_default: false,
791 upgrade: None,
792 show_in_picker: true,
793 supported_in_api: true,
794 context_window: Some(256_000),
795 },
796 ModelPreset {
797 id: "mistral-small-2603".to_string(),
798 model: "mistral-small-2603".to_string(),
799 display_name: "Mistral Small 4".to_string(),
800 description:
801 "Hybrid model unifying instruct, reasoning, and coding (119B params, 6.5B active)"
802 .to_string(),
803 provider: Provider::Mistral,
804 default_reasoning_effort: ReasoningEffortLevel::Medium,
805 supported_reasoning_efforts: vec![
806 ReasoningEffortPreset {
807 effort: ReasoningEffortLevel::Medium,
808 description: "Balanced".to_string(),
809 },
810 ReasoningEffortPreset {
811 effort: ReasoningEffortLevel::High,
812 description: "Deep".to_string(),
813 },
814 ],
815 is_default: false,
816 upgrade: None,
817 show_in_picker: true,
818 supported_in_api: true,
819 context_window: Some(256_000),
820 },
821 ModelPreset {
822 id: "mistral-medium-2508".to_string(),
823 model: "mistral-medium-2508".to_string(),
824 display_name: "Mistral Medium 3.1".to_string(),
825 description: "Frontier-class multimodal model with 256k context".to_string(),
826 provider: Provider::Mistral,
827 default_reasoning_effort: ReasoningEffortLevel::Medium,
828 supported_reasoning_efforts: vec![ReasoningEffortPreset {
829 effort: ReasoningEffortLevel::Medium,
830 description: "Balanced".to_string(),
831 }],
832 is_default: false,
833 upgrade: None,
834 show_in_picker: true,
835 supported_in_api: true,
836 context_window: Some(256_000),
837 },
838 ModelPreset {
839 id: "codestral-2508".to_string(),
840 model: "codestral-2508".to_string(),
841 display_name: "Codestral".to_string(),
842 description: "Cutting-edge language model for code completion".to_string(),
843 provider: Provider::Mistral,
844 default_reasoning_effort: ReasoningEffortLevel::Medium,
845 supported_reasoning_efforts: Vec::new(),
846 is_default: false,
847 upgrade: None,
848 show_in_picker: true,
849 supported_in_api: true,
850 context_window: Some(256_000),
851 },
852 ]
853}
854
855fn minimax_presets() -> Vec<ModelPreset> {
856 vec![ModelPreset {
857 id: "minimax-m3".to_string(),
858 model: "MiniMax-M3".to_string(),
859 display_name: "MiniMax M3".to_string(),
860 description: "Frontier multimodal coding model with 1M context".to_string(),
861 provider: Provider::Minimax,
862 default_reasoning_effort: ReasoningEffortLevel::Medium,
863 supported_reasoning_efforts: vec![
864 ReasoningEffortPreset {
865 effort: ReasoningEffortLevel::Medium,
866 description: "Balanced".to_string(),
867 },
868 ReasoningEffortPreset {
869 effort: ReasoningEffortLevel::High,
870 description: "Deep".to_string(),
871 },
872 ],
873 is_default: true,
874 upgrade: None,
875 show_in_picker: true,
876 supported_in_api: true,
877 context_window: Some(1_000_000),
878 }]
879}
880
881fn openrouter_presets() -> Vec<ModelPreset> {
882 vec![
883 ModelPreset {
884 id: "openrouter/deepseek/deepseek-chat".to_string(),
885 model: "deepseek/deepseek-chat".to_string(),
886 display_name: "DeepSeek V3.2 (OpenRouter)".to_string(),
887 description: "DeepSeek via OpenRouter".to_string(),
888 provider: Provider::OpenRouter,
889 default_reasoning_effort: ReasoningEffortLevel::Medium,
890 supported_reasoning_efforts: vec![ReasoningEffortPreset {
891 effort: ReasoningEffortLevel::Medium,
892 description: "Balanced".to_string(),
893 }],
894 is_default: false,
895 upgrade: None,
896 show_in_picker: true,
897 supported_in_api: true,
898 context_window: Some(128_000),
899 },
900 ModelPreset {
901 id: "openrouter/moonshotai/kimi-k2.6".to_string(),
902 model: "moonshotai/kimi-k2.6".to_string(),
903 display_name: "Kimi K2.6 (OpenRouter)".to_string(),
904 description: "Kimi K2.6 multimodal agentic model via OpenRouter".to_string(),
905 provider: Provider::OpenRouter,
906 default_reasoning_effort: ReasoningEffortLevel::Medium,
907 supported_reasoning_efforts: vec![ReasoningEffortPreset {
908 effort: ReasoningEffortLevel::Medium,
909 description: "Balanced".to_string(),
910 }],
911 is_default: false,
912 upgrade: None,
913 show_in_picker: true,
914 supported_in_api: true,
915 context_window: Some(262_144),
916 },
917 ModelPreset {
918 id: "openrouter/moonshotai/kimi-k2.7-code".to_string(),
919 model: "moonshotai/kimi-k2.7-code".to_string(),
920 display_name: "Kimi K2.7 Code (OpenRouter)".to_string(),
921 description: "Kimi K2.7 Code most capable coding model with long-horizon coding breakthrough via OpenRouter".to_string(),
922 provider: Provider::OpenRouter,
923 default_reasoning_effort: ReasoningEffortLevel::Medium,
924 supported_reasoning_efforts: vec![ReasoningEffortPreset {
925 effort: ReasoningEffortLevel::Medium,
926 description: "Balanced".to_string(),
927 }],
928 is_default: false,
929 upgrade: None,
930 show_in_picker: true,
931 supported_in_api: true,
932 context_window: Some(262_144),
933 },
934 ModelPreset {
935 id: "openrouter/qwen/qwen3.7-max".to_string(),
936 model: "qwen/qwen3.7-max".to_string(),
937 display_name: "Qwen3.7 Max (OpenRouter)".to_string(),
938 description: "Qwen3.7 Max flagship model for coding and agentic workloads via OpenRouter".to_string(),
939 provider: Provider::OpenRouter,
940 default_reasoning_effort: ReasoningEffortLevel::Medium,
941 supported_reasoning_efforts: vec![ReasoningEffortPreset {
942 effort: ReasoningEffortLevel::Medium,
943 description: "Balanced".to_string(),
944 }],
945 is_default: false,
946 upgrade: None,
947 show_in_picker: true,
948 supported_in_api: true,
949 context_window: Some(1_000_000),
950 },
951 ModelPreset {
952 id: "openrouter/tencent/hy3-preview".to_string(),
953 model: "tencent/hy3-preview".to_string(),
954 display_name: "Hy3 Preview (OpenRouter)".to_string(),
955 description: "Tencent Hy3 high-efficiency MoE model with configurable reasoning via OpenRouter".to_string(),
956 provider: Provider::OpenRouter,
957 default_reasoning_effort: ReasoningEffortLevel::Medium,
958 supported_reasoning_efforts: vec![
959 ReasoningEffortPreset {
960 effort: ReasoningEffortLevel::Low,
961 description: "Fast".to_string(),
962 },
963 ReasoningEffortPreset {
964 effort: ReasoningEffortLevel::Medium,
965 description: "Balanced".to_string(),
966 },
967 ReasoningEffortPreset {
968 effort: ReasoningEffortLevel::High,
969 description: "Deep".to_string(),
970 },
971 ],
972 is_default: false,
973 upgrade: None,
974 show_in_picker: true,
975 supported_in_api: true,
976 context_window: Some(262_144),
977 },
978 ModelPreset {
979 id: "openrouter/x-ai/grok-build-0.1".to_string(),
980 model: "x-ai/grok-build-0.1".to_string(),
981 display_name: "Grok Build 0.1 (OpenRouter)".to_string(),
982 description: "xAI Grok Build 0.1 coding model for agentic software engineering via OpenRouter".to_string(),
983 provider: Provider::OpenRouter,
984 default_reasoning_effort: ReasoningEffortLevel::Medium,
985 supported_reasoning_efforts: vec![ReasoningEffortPreset {
986 effort: ReasoningEffortLevel::Medium,
987 description: "Balanced".to_string(),
988 }],
989 is_default: false,
990 upgrade: None,
991 show_in_picker: true,
992 supported_in_api: true,
993 context_window: Some(256_000),
994 },
995 ModelPreset {
996 id: "openrouter/xiaomi/mimo-v2.5".to_string(),
997 model: "xiaomi/mimo-v2.5".to_string(),
998 display_name: "MiMo-V2.5 (OpenRouter)".to_string(),
999 description: "Xiaomi MiMo-V2.5 omnimodal agentic model for complex software engineering via OpenRouter".to_string(),
1000 provider: Provider::OpenRouter,
1001 default_reasoning_effort: ReasoningEffortLevel::Medium,
1002 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1003 effort: ReasoningEffortLevel::Medium,
1004 description: "Balanced".to_string(),
1005 }],
1006 is_default: false,
1007 upgrade: None,
1008 show_in_picker: true,
1009 supported_in_api: true,
1010 context_window: Some(1_000_000),
1011 },
1012 ModelPreset {
1013 id: "openrouter/xiaomi/mimo-v2.5-pro".to_string(),
1014 model: "xiaomi/mimo-v2.5-pro".to_string(),
1015 display_name: "MiMo-V2.5-Pro (OpenRouter)".to_string(),
1016 description: "Xiaomi MiMo-V2.5-Pro flagship agentic model for complex software engineering via OpenRouter".to_string(),
1017 provider: Provider::OpenRouter,
1018 default_reasoning_effort: ReasoningEffortLevel::Medium,
1019 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1020 effort: ReasoningEffortLevel::Medium,
1021 description: "Balanced".to_string(),
1022 }],
1023 is_default: true,
1024 upgrade: None,
1025 show_in_picker: true,
1026 supported_in_api: true,
1027 context_window: Some(1_000_000),
1028 },
1029 ModelPreset {
1030 id: "openrouter/poolside/laguna-m.1:free".to_string(),
1031 model: "poolside/laguna-m.1:free".to_string(),
1032 display_name: "Laguna M.1 free (OpenRouter)".to_string(),
1033 description: "Poolside Laguna M.1 flagship free coding agent model via OpenRouter".to_string(),
1034 provider: Provider::OpenRouter,
1035 default_reasoning_effort: ReasoningEffortLevel::Medium,
1036 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1037 effort: ReasoningEffortLevel::Medium,
1038 description: "Balanced".to_string(),
1039 }],
1040 is_default: false,
1041 upgrade: None,
1042 show_in_picker: true,
1043 supported_in_api: true,
1044 context_window: Some(262_144),
1045 },
1046 ]
1047}
1048
1049fn ollama_presets() -> Vec<ModelPreset> {
1050 vec![
1051 ModelPreset {
1052 id: "ollama/gpt-oss:20b".to_string(),
1053 model: "gpt-oss:20b".to_string(),
1054 display_name: "GPT-OSS 20B (Ollama)".to_string(),
1055 description: "Open-weight GPT-OSS served locally".to_string(),
1056 provider: Provider::Ollama,
1057 default_reasoning_effort: ReasoningEffortLevel::Medium,
1058 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1059 effort: ReasoningEffortLevel::Medium,
1060 description: "Balanced".to_string(),
1061 }],
1062 is_default: true,
1063 upgrade: None,
1064 show_in_picker: true,
1065 supported_in_api: true,
1066 context_window: Some(96_000),
1067 },
1068 ModelPreset {
1069 id: "ollama/deepseek-v4-flash:cloud".to_string(),
1070 model: "deepseek-v4-flash:cloud".to_string(),
1071 display_name: "DeepSeek V4 Flash (Ollama)".to_string(),
1072 description: "Fast inference DeepSeek V4 Flash model via Ollama Cloud".to_string(),
1073 provider: Provider::Ollama,
1074 default_reasoning_effort: ReasoningEffortLevel::Medium,
1075 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1076 effort: ReasoningEffortLevel::Medium,
1077 description: "Balanced".to_string(),
1078 }],
1079 is_default: false,
1080 upgrade: None,
1081 show_in_picker: true,
1082 supported_in_api: true,
1083 context_window: Some(128_000),
1084 },
1085 ModelPreset {
1086 id: "ollama/deepseek-v4-pro:cloud".to_string(),
1087 model: "deepseek-v4-pro:cloud".to_string(),
1088 display_name: "DeepSeek V4 Pro (Ollama)".to_string(),
1089 description: "High-performance DeepSeek V4 Pro model via Ollama Cloud".to_string(),
1090 provider: Provider::Ollama,
1091 default_reasoning_effort: ReasoningEffortLevel::Medium,
1092 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1093 effort: ReasoningEffortLevel::Medium,
1094 description: "Balanced".to_string(),
1095 }],
1096 is_default: false,
1097 upgrade: None,
1098 show_in_picker: true,
1099 supported_in_api: true,
1100 context_window: Some(128_000),
1101 },
1102 ModelPreset {
1103 id: "ollama/nemotron-3-ultra:cloud".to_string(),
1104 model: "nemotron-3-ultra:cloud".to_string(),
1105 display_name: "Nemotron 3 Ultra (Ollama)".to_string(),
1106 description: "NVIDIA Nemotron 3 Ultra 550B for high-throughput reasoning and long-running agent workflows via Ollama Cloud".to_string(),
1107 provider: Provider::Ollama,
1108 default_reasoning_effort: ReasoningEffortLevel::Medium,
1109 supported_reasoning_efforts: vec![
1110 ReasoningEffortPreset {
1111 effort: ReasoningEffortLevel::Medium,
1112 description: "Balanced".to_string(),
1113 },
1114 ReasoningEffortPreset {
1115 effort: ReasoningEffortLevel::High,
1116 description: "Deep".to_string(),
1117 },
1118 ],
1119 is_default: false,
1120 upgrade: None,
1121 show_in_picker: true,
1122 supported_in_api: true,
1123 context_window: Some(256_000),
1124 },
1125 ModelPreset {
1126 id: "ollama/gemma4".to_string(),
1127 model: "gemma4".to_string(),
1128 display_name: "Gemma 4 (Ollama)".to_string(),
1129 description: "Google Gemma 4 for reasoning, agentic workflows, coding, and multimodal understanding".to_string(),
1130 provider: Provider::Ollama,
1131 default_reasoning_effort: ReasoningEffortLevel::Medium,
1132 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1133 effort: ReasoningEffortLevel::Medium,
1134 description: "Balanced".to_string(),
1135 }],
1136 is_default: false,
1137 upgrade: None,
1138 show_in_picker: true,
1139 supported_in_api: true,
1140 context_window: Some(128_000),
1141 },
1142 ModelPreset {
1143 id: "ollama/minimax-m3:cloud".to_string(),
1144 model: "minimax-m3:cloud".to_string(),
1145 display_name: "MiniMax-M3 (Ollama)".to_string(),
1146 description: "Cloud-hosted MiniMax-M3 model via Ollama Cloud".to_string(),
1147 provider: Provider::Ollama,
1148 default_reasoning_effort: ReasoningEffortLevel::Medium,
1149 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1150 effort: ReasoningEffortLevel::Medium,
1151 description: "Balanced".to_string(),
1152 }],
1153 is_default: false,
1154 upgrade: None,
1155 show_in_picker: true,
1156 supported_in_api: true,
1157 context_window: Some(131_072),
1158 },
1159 ]
1160}
1161
1162fn lmstudio_presets() -> Vec<ModelPreset> {
1163 use crate::config::constants::models::lmstudio as lmstudio_models;
1164 vec![
1165 ModelPreset {
1166 id: format!("lmstudio/{}", lmstudio_models::OPENAI_GPT_OSS_20B),
1167 model: lmstudio_models::OPENAI_GPT_OSS_20B.to_string(),
1168 display_name: "GPT-OSS 20B (LM Studio)".to_string(),
1169 description: "OpenAI's open-weight GPT-OSS 20B model served locally via LM Studio"
1170 .to_string(),
1171 provider: Provider::LmStudio,
1172 default_reasoning_effort: ReasoningEffortLevel::Medium,
1173 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1174 effort: ReasoningEffortLevel::Medium,
1175 description: "Balanced".to_string(),
1176 }],
1177 is_default: false,
1178 upgrade: None,
1179 show_in_picker: true,
1180 supported_in_api: true,
1181 context_window: Some(131_072),
1182 },
1183 ModelPreset {
1184 id: format!("lmstudio/{}", lmstudio_models::META_LLAMA_31_8B_INSTRUCT),
1185 model: lmstudio_models::META_LLAMA_31_8B_INSTRUCT.to_string(),
1186 display_name: "Llama 3.1 8B (LM Studio)".to_string(),
1187 description: "Meta Llama 3.1 8B Instruct for general-purpose local inference"
1188 .to_string(),
1189 provider: Provider::LmStudio,
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 ModelPreset {
1202 id: format!("lmstudio/{}", lmstudio_models::GEMMA_3_12B_IT),
1203 model: lmstudio_models::GEMMA_3_12B_IT.to_string(),
1204 display_name: "Gemma 3 12B (LM Studio)".to_string(),
1205 description: "Google Gemma 3 12B IT for local inference".to_string(),
1206 provider: Provider::LmStudio,
1207 default_reasoning_effort: ReasoningEffortLevel::Medium,
1208 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1209 effort: ReasoningEffortLevel::Medium,
1210 description: "Balanced".to_string(),
1211 }],
1212 is_default: false,
1213 upgrade: None,
1214 show_in_picker: true,
1215 supported_in_api: true,
1216 context_window: Some(32_768),
1217 },
1218 ]
1219}
1220
1221fn llamacpp_presets() -> Vec<ModelPreset> {
1222 vec![
1223 ModelPreset {
1224 id: format!("llamacpp/{}", llamacpp_models::GPT_OSS_20B),
1225 model: llamacpp_models::GPT_OSS_20B.to_string(),
1226 display_name: "GPT-OSS 20B (llama.cpp)".to_string(),
1227 description: "OpenAI's open-weight GPT-OSS 20B model served locally through llama.cpp"
1228 .to_string(),
1229 provider: Provider::LlamaCpp,
1230 default_reasoning_effort: ReasoningEffortLevel::Medium,
1231 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1232 effort: ReasoningEffortLevel::Medium,
1233 description: "Balanced".to_string(),
1234 }],
1235 is_default: true,
1236 upgrade: None,
1237 show_in_picker: true,
1238 supported_in_api: true,
1239 context_window: Some(131_072),
1240 },
1241 ModelPreset {
1242 id: format!("llamacpp/{}", llamacpp_models::GEMMA_4_26B_A4B),
1243 model: llamacpp_models::GEMMA_4_26B_A4B.to_string(),
1244 display_name: "Gemma 4 26B A4B (llama.cpp)".to_string(),
1245 description: "Gemma 4 desktop MoE model served through llama.cpp".to_string(),
1246 provider: Provider::LlamaCpp,
1247 default_reasoning_effort: ReasoningEffortLevel::Medium,
1248 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1249 effort: ReasoningEffortLevel::Medium,
1250 description: "Balanced".to_string(),
1251 }],
1252 is_default: false,
1253 upgrade: None,
1254 show_in_picker: true,
1255 supported_in_api: true,
1256 context_window: Some(262_144),
1257 },
1258 ModelPreset {
1259 id: format!("llamacpp/{}", llamacpp_models::GEMMA_4_E4B),
1260 model: llamacpp_models::GEMMA_4_E4B.to_string(),
1261 display_name: "Gemma 4 E4B (llama.cpp)".to_string(),
1262 description: "Tiny-footprint Gemma 4 model served through llama.cpp".to_string(),
1263 provider: Provider::LlamaCpp,
1264 default_reasoning_effort: ReasoningEffortLevel::Low,
1265 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1266 effort: ReasoningEffortLevel::Low,
1267 description: "Fast".to_string(),
1268 }],
1269 is_default: false,
1270 upgrade: None,
1271 show_in_picker: true,
1272 supported_in_api: true,
1273 context_window: Some(131_072),
1274 },
1275 ModelPreset {
1276 id: format!("llamacpp/{}", llamacpp_models::STEP_3_5_FLASH),
1277 model: llamacpp_models::STEP_3_5_FLASH.to_string(),
1278 display_name: "Step 3.5 Flash (llama.cpp)".to_string(),
1279 description: "StepFun's efficient reasoning model served through llama.cpp".to_string(),
1280 provider: Provider::LlamaCpp,
1281 default_reasoning_effort: ReasoningEffortLevel::Medium,
1282 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1283 effort: ReasoningEffortLevel::Medium,
1284 description: "Balanced".to_string(),
1285 }],
1286 is_default: false,
1287 upgrade: None,
1288 show_in_picker: true,
1289 supported_in_api: true,
1290 context_window: Some(262_144),
1291 },
1292 ]
1293}
1294
1295fn opencode_zen_presets() -> Vec<ModelPreset> {
1296 vec![ModelPreset {
1297 id: "opencode/gpt-5.4".to_string(),
1298 model: "gpt-5.4".to_string(),
1299 display_name: "GPT-5.4 (OpenCode Zen)".to_string(),
1300 description: "OpenCode Zen gateway — curated, benchmarked models at cost".to_string(),
1301 provider: Provider::OpenCodeZen,
1302 default_reasoning_effort: ReasoningEffortLevel::Medium,
1303 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1304 effort: ReasoningEffortLevel::Medium,
1305 description: "Balanced".to_string(),
1306 }],
1307 is_default: true,
1308 upgrade: None,
1309 show_in_picker: true,
1310 supported_in_api: true,
1311 context_window: Some(1_050_000),
1312 }]
1313}
1314
1315fn opencode_go_presets() -> Vec<ModelPreset> {
1316 vec![ModelPreset {
1317 id: "opencode-go/glm-5.1".to_string(),
1318 model: "glm-5.1".to_string(),
1319 display_name: "GLM-5.1 (OpenCode Go)".to_string(),
1320 description: "OpenCode Go — affordable subscription for open coding models".to_string(),
1321 provider: Provider::OpenCodeGo,
1322 default_reasoning_effort: ReasoningEffortLevel::Medium,
1323 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1324 effort: ReasoningEffortLevel::Medium,
1325 description: "Balanced".to_string(),
1326 }],
1327 is_default: true,
1328 upgrade: None,
1329 show_in_picker: true,
1330 supported_in_api: true,
1331 context_window: Some(256_000),
1332 }]
1333}
1334
1335fn poolside_presets() -> Vec<ModelPreset> {
1336 vec![
1337 ModelPreset {
1338 id: poolside_models::LAGUNA_M1.to_string(),
1339 model: poolside_models::LAGUNA_M1.to_string(),
1340 display_name: "Laguna M.1".to_string(),
1341 description:
1342 "Poolside's flagship MoE coding agent model optimized for multi-step agentic tasks, tool use, and validation (128K context)"
1343 .to_string(),
1344 provider: Provider::Poolside,
1345 default_reasoning_effort: ReasoningEffortLevel::Medium,
1346 supported_reasoning_efforts: Vec::new(),
1347 is_default: true,
1348 upgrade: None,
1349 show_in_picker: true,
1350 supported_in_api: true,
1351 context_window: Some(131_072),
1352 },
1353 ModelPreset {
1354 id: poolside_models::LAGUNA_XS2.to_string(),
1355 model: poolside_models::LAGUNA_XS2.to_string(),
1356 display_name: "Laguna XS.2".to_string(),
1357 description:
1358 "Poolside's efficient MoE coding agent model optimized for fast agentic coding (128K context)"
1359 .to_string(),
1360 provider: Provider::Poolside,
1361 default_reasoning_effort: ReasoningEffortLevel::Medium,
1362 supported_reasoning_efforts: Vec::new(),
1363 is_default: false,
1364 upgrade: None,
1365 show_in_picker: true,
1366 supported_in_api: true,
1367 context_window: Some(131_072),
1368 },
1369 ]
1370}
1371
1372fn mimo_presets() -> Vec<ModelPreset> {
1373 vec![
1374 ModelPreset {
1375 id: mimo_models::MIMO_V2_5_PRO.to_string(),
1376 model: mimo_models::MIMO_V2_5_PRO.to_string(),
1377 display_name: "MiMo V2.5 Pro".to_string(),
1378 description:
1379 "Xiaomi's flagship reasoning model with advanced capabilities (1M context)"
1380 .to_string(),
1381 provider: Provider::MiMo,
1382 default_reasoning_effort: ReasoningEffortLevel::Medium,
1383 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1384 effort: ReasoningEffortLevel::Medium,
1385 description: "Balanced".to_string(),
1386 }],
1387 is_default: true,
1388 upgrade: None,
1389 show_in_picker: true,
1390 supported_in_api: true,
1391 context_window: Some(1_048_576),
1392 },
1393 ModelPreset {
1394 id: mimo_models::MIMO_V2_5.to_string(),
1395 model: mimo_models::MIMO_V2_5.to_string(),
1396 display_name: "MiMo V2.5".to_string(),
1397 description: "Xiaomi's general-purpose model with strong reasoning (1M context)"
1398 .to_string(),
1399 provider: Provider::MiMo,
1400 default_reasoning_effort: ReasoningEffortLevel::Medium,
1401 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1402 effort: ReasoningEffortLevel::Medium,
1403 description: "Balanced".to_string(),
1404 }],
1405 is_default: false,
1406 upgrade: None,
1407 show_in_picker: true,
1408 supported_in_api: true,
1409 context_window: Some(1_048_576),
1410 },
1411 ]
1412}
1413
1414fn qwen_presets() -> Vec<ModelPreset> {
1415 vec![
1416 ModelPreset {
1417 id: qwen_models::DEEPSEEK_V4_FLASH.to_string(),
1418 model: qwen_models::DEEPSEEK_V4_FLASH.to_string(),
1419 display_name: "DeepSeek V4 Flash (Qwen)".to_string(),
1420 description:
1421 "DeepSeek V4 Flash fast inference model served through Qwen Cloud API (1M context)"
1422 .to_string(),
1423 provider: Provider::Qwen,
1424 default_reasoning_effort: ReasoningEffortLevel::Low,
1425 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1426 effort: ReasoningEffortLevel::Low,
1427 description: "Fast".to_string(),
1428 }],
1429 is_default: false,
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: qwen_models::DEEPSEEK_V4_PRO.to_string(),
1437 model: qwen_models::DEEPSEEK_V4_PRO.to_string(),
1438 display_name: "DeepSeek V4 Pro (Qwen)".to_string(),
1439 description:
1440 "DeepSeek V4 Pro high-performance reasoning model served through Qwen Cloud API (1M context)"
1441 .to_string(),
1442 provider: Provider::Qwen,
1443 default_reasoning_effort: ReasoningEffortLevel::Medium,
1444 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1445 effort: ReasoningEffortLevel::Medium,
1446 description: "Balanced".to_string(),
1447 }],
1448 is_default: false,
1449 upgrade: None,
1450 show_in_picker: true,
1451 supported_in_api: true,
1452 context_window: Some(1_048_576),
1453 },
1454 ModelPreset {
1455 id: qwen_models::GLM_5_1.to_string(),
1456 model: qwen_models::GLM_5_1.to_string(),
1457 display_name: "GLM-5.1 (Qwen)".to_string(),
1458 description:
1459 "Z.AI GLM-5.1 next-gen foundation model served through Qwen Cloud API"
1460 .to_string(),
1461 provider: Provider::Qwen,
1462 default_reasoning_effort: ReasoningEffortLevel::Medium,
1463 supported_reasoning_efforts: vec![ReasoningEffortPreset {
1464 effort: ReasoningEffortLevel::Medium,
1465 description: "Balanced".to_string(),
1466 }],
1467 is_default: false,
1468 upgrade: None,
1469 show_in_picker: true,
1470 supported_in_api: true,
1471 context_window: Some(131_072),
1472 },
1473 ]
1474}
1475
1476fn stepfun_presets() -> Vec<ModelPreset> {
1477 vec![ModelPreset {
1478 id: stepfun_models::STEP_3_7_FLASH.to_string(),
1479 model: stepfun_models::STEP_3_7_FLASH.to_string(),
1480 display_name: "Step 3.7 Flash".to_string(),
1481 description:
1482 "StepFun's flagship multimodal reasoning model with 256K context and tool calling."
1483 .to_string(),
1484 provider: Provider::StepFun,
1485 default_reasoning_effort: ReasoningEffortLevel::Medium,
1486 supported_reasoning_efforts: vec![
1487 reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1488 reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1489 reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1490 ],
1491 is_default: true,
1492 upgrade: None,
1493 show_in_picker: true,
1494 supported_in_api: true,
1495 context_window: Some(262_144),
1496 }]
1497}
1498
1499fn evolink_presets() -> Vec<ModelPreset> {
1500 vec![
1501 ModelPreset {
1502 id: "evolink/gpt-5.2".to_string(),
1503 model: evolink_models::GPT_5_2.to_string(),
1504 display_name: "GPT-5.2 (Evolink)".to_string(),
1505 description: "GPT-5.2 served through the Evolink OpenAI-compatible gateway."
1506 .to_string(),
1507 provider: Provider::Evolink,
1508 default_reasoning_effort: ReasoningEffortLevel::Medium,
1509 supported_reasoning_efforts: vec![reasoning_preset(
1510 ReasoningEffortLevel::Medium,
1511 "Balanced",
1512 )],
1513 is_default: true,
1514 upgrade: None,
1515 show_in_picker: true,
1516 supported_in_api: true,
1517 context_window: Some(400_000),
1518 },
1519 ModelPreset {
1520 id: "evolink/gpt-5.5".to_string(),
1521 model: evolink_models::GPT_5_5.to_string(),
1522 display_name: "GPT-5.5 (Evolink)".to_string(),
1523 description: "GPT-5.5 flagship model served through the Evolink gateway.".to_string(),
1524 provider: Provider::Evolink,
1525 default_reasoning_effort: ReasoningEffortLevel::Medium,
1526 supported_reasoning_efforts: vec![reasoning_preset(
1527 ReasoningEffortLevel::Medium,
1528 "Balanced",
1529 )],
1530 is_default: false,
1531 upgrade: None,
1532 show_in_picker: true,
1533 supported_in_api: true,
1534 context_window: Some(400_000),
1535 },
1536 ModelPreset {
1537 id: "evolink/deepseek-v4-pro".to_string(),
1538 model: evolink_models::DEEPSEEK_V4_PRO.to_string(),
1539 display_name: "DeepSeek V4 Pro (Evolink)".to_string(),
1540 description: "DeepSeek V4 Pro reasoning model served through the Evolink gateway."
1541 .to_string(),
1542 provider: Provider::Evolink,
1543 default_reasoning_effort: ReasoningEffortLevel::Medium,
1544 supported_reasoning_efforts: vec![
1545 reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1546 reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1547 reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1548 ],
1549 is_default: false,
1550 upgrade: None,
1551 show_in_picker: true,
1552 supported_in_api: true,
1553 context_window: Some(163_840),
1554 },
1555 ModelPreset {
1556 id: "evolink/deepseek-v4-flash".to_string(),
1557 model: evolink_models::DEEPSEEK_V4_FLASH.to_string(),
1558 display_name: "DeepSeek V4 Flash (Evolink)".to_string(),
1559 description:
1560 "DeepSeek V4 Flash fast inference model served through the Evolink gateway."
1561 .to_string(),
1562 provider: Provider::Evolink,
1563 default_reasoning_effort: ReasoningEffortLevel::Medium,
1564 supported_reasoning_efforts: vec![
1565 reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1566 reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1567 reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1568 ],
1569 is_default: false,
1570 upgrade: None,
1571 show_in_picker: true,
1572 supported_in_api: true,
1573 context_window: Some(1_000_000),
1574 },
1575 ModelPreset {
1576 id: "evolink/doubao-seed-2.0-pro".to_string(),
1577 model: evolink_models::DOUBAO_SEED_2_0_PRO.to_string(),
1578 display_name: "Doubao Seed 2.0 Pro (Evolink)".to_string(),
1579 description: "Doubao Seed 2.0 Pro served through the Evolink gateway.".to_string(),
1580 provider: Provider::Evolink,
1581 default_reasoning_effort: ReasoningEffortLevel::Medium,
1582 supported_reasoning_efforts: vec![
1583 reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1584 reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1585 reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1586 ],
1587 is_default: false,
1588 upgrade: None,
1589 show_in_picker: true,
1590 supported_in_api: true,
1591 context_window: Some(262_144),
1592 },
1593 ModelPreset {
1594 id: "evolink/gemini-3.1-pro-preview".to_string(),
1595 model: evolink_models::GEMINI_3_1_PRO.to_string(),
1596 display_name: "Gemini 3.1 Pro (Evolink)".to_string(),
1597 description: "Gemini 3.1 Pro served through the Evolink gateway via OpenAI SDK format."
1598 .to_string(),
1599 provider: Provider::Evolink,
1600 default_reasoning_effort: ReasoningEffortLevel::Medium,
1601 supported_reasoning_efforts: vec![reasoning_preset(
1602 ReasoningEffortLevel::Medium,
1603 "Balanced",
1604 )],
1605 is_default: false,
1606 upgrade: None,
1607 show_in_picker: true,
1608 supported_in_api: true,
1609 context_window: Some(1_000_000),
1610 },
1611 ModelPreset {
1612 id: "evolink/gemini-3.5-flash".to_string(),
1613 model: evolink_models::GEMINI_3_5_FLASH.to_string(),
1614 display_name: "Gemini 3.5 Flash (Evolink)".to_string(),
1615 description:
1616 "Gemini 3.5 Flash served through the Evolink gateway via OpenAI SDK format."
1617 .to_string(),
1618 provider: Provider::Evolink,
1619 default_reasoning_effort: ReasoningEffortLevel::Medium,
1620 supported_reasoning_efforts: vec![reasoning_preset(
1621 ReasoningEffortLevel::Medium,
1622 "Balanced",
1623 )],
1624 is_default: false,
1625 upgrade: None,
1626 show_in_picker: true,
1627 supported_in_api: true,
1628 context_window: Some(1_000_000),
1629 },
1630 ModelPreset {
1631 id: "evolink/MiniMax-M3".to_string(),
1632 model: evolink_models::MINIMAX_M3.to_string(),
1633 display_name: "MiniMax-M3 (Evolink)".to_string(),
1634 description: "MiniMax-M3 frontier multimodal model served through the Evolink gateway."
1635 .to_string(),
1636 provider: Provider::Evolink,
1637 default_reasoning_effort: ReasoningEffortLevel::Medium,
1638 supported_reasoning_efforts: vec![reasoning_preset(
1639 ReasoningEffortLevel::Medium,
1640 "Balanced",
1641 )],
1642 is_default: false,
1643 upgrade: None,
1644 show_in_picker: true,
1645 supported_in_api: true,
1646 context_window: Some(1_000_000),
1647 },
1648 ModelPreset {
1649 id: "evolink/claude-sonnet-4-6".to_string(),
1650 model: evolink_models::CLAUDE_SONNET_4_6.to_string(),
1651 display_name: "Claude Sonnet 4.6 (Evolink)".to_string(),
1652 description: "Claude Sonnet 4.6 served through Evolink via Anthropic Messages API."
1653 .to_string(),
1654 provider: Provider::Evolink,
1655 default_reasoning_effort: ReasoningEffortLevel::Medium,
1656 supported_reasoning_efforts: vec![reasoning_preset(
1657 ReasoningEffortLevel::Medium,
1658 "Balanced",
1659 )],
1660 is_default: false,
1661 upgrade: None,
1662 show_in_picker: true,
1663 supported_in_api: true,
1664 context_window: Some(200_000),
1665 },
1666 ModelPreset {
1667 id: "evolink/claude-opus-4-8".to_string(),
1668 model: evolink_models::CLAUDE_OPUS_4_8.to_string(),
1669 display_name: "Claude Opus 4.8 (Evolink)".to_string(),
1670 description: "Claude Opus 4.8 served through Evolink via Anthropic Messages API."
1671 .to_string(),
1672 provider: Provider::Evolink,
1673 default_reasoning_effort: ReasoningEffortLevel::High,
1674 supported_reasoning_efforts: vec![
1675 reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1676 reasoning_preset(ReasoningEffortLevel::High, "Deep"),
1677 ],
1678 is_default: false,
1679 upgrade: None,
1680 show_in_picker: true,
1681 supported_in_api: true,
1682 context_window: Some(200_000),
1683 },
1684 ModelPreset {
1685 id: "evolink/claude-haiku-4-5-20251001".to_string(),
1686 model: evolink_models::CLAUDE_HAIKU_4_5.to_string(),
1687 display_name: "Claude Haiku 4.5 (Evolink)".to_string(),
1688 description:
1689 "Claude Haiku 4.5 fast model served through Evolink via Anthropic Messages API."
1690 .to_string(),
1691 provider: Provider::Evolink,
1692 default_reasoning_effort: ReasoningEffortLevel::Low,
1693 supported_reasoning_efforts: vec![
1694 reasoning_preset(ReasoningEffortLevel::Low, "Fast"),
1695 reasoning_preset(ReasoningEffortLevel::Medium, "Balanced"),
1696 ],
1697 is_default: false,
1698 upgrade: None,
1699 show_in_picker: true,
1700 supported_in_api: true,
1701 context_window: Some(200_000),
1702 },
1703 ]
1704}
1705
1706fn moonshot_presets() -> Vec<ModelPreset> {
1707 vec![
1708 ModelPreset {
1709 id: "kimi-k2.7-code".to_string(),
1710 model: "kimi-k2.7-code".to_string(),
1711 display_name: "Kimi K2.7 Code (Moonshot)".to_string(),
1712 description:
1713 "Moonshot's most capable coding model with long-horizon coding breakthrough."
1714 .to_string(),
1715 provider: Provider::Moonshot,
1716 default_reasoning_effort: ReasoningEffortLevel::Medium,
1717 supported_reasoning_efforts: vec![reasoning_preset(
1718 ReasoningEffortLevel::Medium,
1719 "Balanced",
1720 )],
1721 is_default: true,
1722 upgrade: None,
1723 show_in_picker: true,
1724 supported_in_api: true,
1725 context_window: Some(256_000),
1726 },
1727 ModelPreset {
1728 id: "kimi-k2.6".to_string(),
1729 model: "kimi-k2.6".to_string(),
1730 display_name: "Kimi K2.6 (Moonshot)".to_string(),
1731 description: "Moonshot's previous flagship coding and agent model.".to_string(),
1732 provider: Provider::Moonshot,
1733 default_reasoning_effort: ReasoningEffortLevel::Medium,
1734 supported_reasoning_efforts: vec![reasoning_preset(
1735 ReasoningEffortLevel::Medium,
1736 "Balanced",
1737 )],
1738 is_default: false,
1739 upgrade: None,
1740 show_in_picker: true,
1741 supported_in_api: true,
1742 context_window: Some(256_000),
1743 },
1744 ]
1745}
1746
1747fn huggingface_presets() -> Vec<ModelPreset> {
1748 vec![
1749 ModelPreset {
1750 id: "huggingface/deepseek-v4-flash".to_string(),
1751 model: "deepseek-ai/DeepSeek-V4-Flash:novita".to_string(),
1752 display_name: "DeepSeek V4 Flash (HF/Novita)".to_string(),
1753 description:
1754 "Fast inference model for cost-effective reasoning (1M context, 158B params)"
1755 .to_string(),
1756 provider: Provider::HuggingFace,
1757 default_reasoning_effort: ReasoningEffortLevel::High,
1758 supported_reasoning_efforts: vec![
1759 ReasoningEffortPreset {
1760 effort: ReasoningEffortLevel::High,
1761 description: "Balanced".to_string(),
1762 },
1763 ReasoningEffortPreset {
1764 effort: ReasoningEffortLevel::Max,
1765 description: "Maximum thinking".to_string(),
1766 },
1767 ],
1768 is_default: false,
1769 upgrade: None,
1770 show_in_picker: true,
1771 supported_in_api: true,
1772 context_window: Some(1_000_000),
1773 },
1774 ModelPreset {
1775 id: "huggingface/deepseek-v4-pro".to_string(),
1776 model: "deepseek-ai/DeepSeek-V4-Pro:together".to_string(),
1777 display_name: "DeepSeek V4 Pro (HF/Together)".to_string(),
1778 description:
1779 "High-performance reasoning model with advanced thinking capabilities (1M context, 1.6T params)"
1780 .to_string(),
1781 provider: Provider::HuggingFace,
1782 default_reasoning_effort: ReasoningEffortLevel::High,
1783 supported_reasoning_efforts: vec![
1784 ReasoningEffortPreset {
1785 effort: ReasoningEffortLevel::High,
1786 description: "Balanced".to_string(),
1787 },
1788 ReasoningEffortPreset {
1789 effort: ReasoningEffortLevel::Max,
1790 description: "Maximum thinking".to_string(),
1791 },
1792 ],
1793 is_default: false,
1794 upgrade: None,
1795 show_in_picker: true,
1796 supported_in_api: true,
1797 context_window: Some(1_000_000),
1798 },
1799 ModelPreset {
1800 id: "huggingface/nvidia-nemotron-3-ultra".to_string(),
1801 model: "nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4:together".to_string(),
1802 display_name: "NVIDIA-Nemotron-3-Ultra-550B (HF/Together)".to_string(),
1803 description:
1804 "NVIDIA Nemotron 3 Ultra 550B-A55B-NVFP4 via Together inference provider"
1805 .to_string(),
1806 provider: Provider::HuggingFace,
1807 default_reasoning_effort: ReasoningEffortLevel::High,
1808 supported_reasoning_efforts: vec![
1809 ReasoningEffortPreset {
1810 effort: ReasoningEffortLevel::High,
1811 description: "Balanced".to_string(),
1812 },
1813 ReasoningEffortPreset {
1814 effort: ReasoningEffortLevel::Max,
1815 description: "Maximum thinking".to_string(),
1816 },
1817 ],
1818 is_default: false,
1819 upgrade: None,
1820 show_in_picker: true,
1821 supported_in_api: true,
1822 context_window: Some(128_000),
1823 },
1824 ModelPreset {
1825 id: "huggingface/minimax-m3".to_string(),
1826 model: "MiniMaxAI/MiniMax-M3:novita".to_string(),
1827 display_name: "MiniMax-M3 (HF/Novita)".to_string(),
1828 description:
1829 "Frontier multimodal coding model with 1M context window via Novita inference provider"
1830 .to_string(),
1831 provider: Provider::HuggingFace,
1832 default_reasoning_effort: ReasoningEffortLevel::High,
1833 supported_reasoning_efforts: vec![
1834 ReasoningEffortPreset {
1835 effort: ReasoningEffortLevel::High,
1836 description: "Balanced".to_string(),
1837 },
1838 ReasoningEffortPreset {
1839 effort: ReasoningEffortLevel::Max,
1840 description: "Maximum thinking".to_string(),
1841 },
1842 ],
1843 is_default: false,
1844 upgrade: None,
1845 show_in_picker: true,
1846 supported_in_api: true,
1847 context_window: Some(1_000_000),
1848 },
1849 ]
1850}
1851
1852#[cfg(test)]
1854pub fn all_model_presets() -> Vec<ModelPreset> {
1855 builtin_model_presets()
1856}
1857
1858#[cfg(test)]
1859mod tests {
1860 use super::*;
1861
1862 #[test]
1863 fn only_one_default_per_provider() {
1864 let presets = builtin_model_presets();
1865 let providers: Vec<Provider> = Provider::all_providers();
1866
1867 for provider in providers {
1868 let default_count = presets
1869 .iter()
1870 .filter(|p| p.provider == provider && p.is_default)
1871 .count();
1872 assert!(
1873 default_count <= 1,
1874 "Provider {:?} has {} defaults, expected 0 or 1",
1875 provider,
1876 default_count
1877 );
1878 }
1879 }
1880
1881 #[test]
1882 fn gemini_presets_exist() {
1883 let presets = gemini_presets();
1884 assert!(!presets.is_empty());
1885 assert!(presets.iter().any(|p| p.id.contains("gemini")));
1886 }
1887
1888 #[test]
1889 fn model_info_converts_to_preset() {
1890 let info = ModelInfo {
1891 slug: "test-model".to_string(),
1892 display_name: "Test Model".to_string(),
1893 description: "A test model".to_string(),
1894 provider: Provider::Gemini,
1895 default_reasoning_level: ReasoningEffortLevel::Medium,
1896 supported_reasoning_levels: vec![],
1897 context_window: Some(128_000),
1898 supports_tool_use: true,
1899 supports_streaming: true,
1900 supports_reasoning: false,
1901 priority: 0,
1902 visibility: "list".to_string(),
1903 supported_in_api: true,
1904 upgrade: None,
1905 };
1906
1907 let preset: ModelPreset = info.into();
1908 assert_eq!(preset.id, "test-model");
1909 assert_eq!(preset.model, "test-model");
1910 assert!(preset.show_in_picker);
1911 }
1912
1913 #[test]
1914 fn openai_codex_presets_default_to_high_reasoning() {
1915 let codex = openai_presets()
1916 .into_iter()
1917 .find(|preset| preset.id == "gpt-5.3-codex")
1918 .expect("gpt-5.3-codex preset");
1919
1920 assert_eq!(codex.default_reasoning_effort, ReasoningEffortLevel::High);
1921 }
1922
1923 #[test]
1924 fn moonshot_presets_exist_and_default_to_kimi_k26() {
1925 let presets = moonshot_presets();
1926 assert_eq!(presets.len(), 2);
1927
1928 let default = presets
1929 .iter()
1930 .find(|preset| preset.is_default)
1931 .expect("moonshot default preset");
1932 assert_eq!(default.id, "kimi-k2.6");
1933 assert_eq!(default.provider, Provider::Moonshot);
1934 }
1935}