feat(model): add gpt-5-codex-mini presets

This commit is contained in:
James Peter
2025-11-08 07:57:41 +10:00
parent 23b6a52a41
commit febfa7e6a1
3 changed files with 102 additions and 15 deletions
+43 -2
View File
@@ -38,6 +38,20 @@ const PRESETS: &[ModelPreset] = &[
model: "gpt-5-codex",
effort: Some(ReasoningEffort::High),
},
ModelPreset {
id: "gpt-5-codex-mini",
label: "gpt-5-codex-mini",
description: "Optimized for codex. Cheaper, faster, and less capable.",
model: "gpt-5-codex-mini",
effort: Some(ReasoningEffort::Medium),
},
ModelPreset {
id: "gpt-5-codex-mini-high",
label: "gpt-5-codex-mini high",
description: "Maximizes reasoning depth for complex or ambiguous problems",
model: "gpt-5-codex-mini",
effort: Some(ReasoningEffort::High),
},
ModelPreset {
id: "gpt-5-minimal",
label: "gpt-5 minimal",
@@ -68,6 +82,33 @@ const PRESETS: &[ModelPreset] = &[
},
];
pub fn builtin_model_presets(_auth_mode: Option<AuthMode>) -> Vec<ModelPreset> {
PRESETS.to_vec()
pub fn builtin_model_presets(auth_mode: Option<AuthMode>) -> Vec<ModelPreset> {
let allow_codex_mini = matches!(auth_mode, Some(AuthMode::ChatGPT));
PRESETS
.iter()
.filter(|preset| {
allow_codex_mini || preset.model != "gpt-5-codex-mini"
})
.copied()
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chatgpt_accounts_include_codex_mini() {
let presets = builtin_model_presets(Some(AuthMode::ChatGPT));
assert!(presets.iter().filter(|preset| preset.model == "gpt-5-codex-mini").count() == 2);
}
#[test]
fn api_key_accounts_exclude_codex_mini() {
let presets = builtin_model_presets(Some(AuthMode::ApiKey));
assert!(!presets.iter().any(|preset| preset.model == "gpt-5-codex-mini"));
let presets = builtin_model_presets(None);
assert!(!presets.iter().any(|preset| preset.model == "gpt-5-codex-mini"));
}
}
@@ -169,10 +169,12 @@ impl ModelSelectionView {
if is_new_model {
if previous_model.is_some() {
// Spacer plus header when switching between model groups.
lines = lines.saturating_add(2);
} else {
// Only the header for the first model group; initial spacer already counted.
// Spacer between model groups.
lines = lines.saturating_add(1);
}
// Header when entering a new model group.
lines = lines.saturating_add(1);
if Self::model_description(preset.model).is_some() {
lines = lines.saturating_add(1);
}
previous_model = Some(preset.model);
@@ -218,10 +220,24 @@ impl ModelSelectionView {
fn model_rank(model: &str) -> u8 {
if model.eq_ignore_ascii_case("gpt-5-codex") {
0
} else if model.eq_ignore_ascii_case("gpt-5") {
} else if model.eq_ignore_ascii_case("gpt-5-codex-mini") {
1
} else {
} else if model.eq_ignore_ascii_case("gpt-5") {
2
} else {
3
}
}
fn model_description(model: &str) -> Option<&'static str> {
if model.eq_ignore_ascii_case("gpt-5-codex") {
Some("Optimized for coding.")
} else if model.eq_ignore_ascii_case("gpt-5-codex-mini") {
Some("Optimized for coding. Cheaper, faster, but less capable.")
} else if model.eq_ignore_ascii_case("gpt-5") {
Some("Broad world knowledge with strong general reasoning.")
} else {
None
}
}
@@ -350,6 +366,12 @@ impl ModelSelectionView {
.fg(crate::colors::text_bright())
.add_modifier(Modifier::BOLD),
)]));
if let Some(desc) = Self::model_description(&preset.model) {
lines.push(Line::from(vec![Span::styled(
desc,
Style::default().fg(crate::colors::text_dim()),
)]));
}
previous_model = Some(preset.model);
}
+31 -7
View File
@@ -5515,16 +5515,33 @@ impl ChatWidget<'_> {
/// Format model name with proper capitalization (e.g., "gpt-4" -> "GPT-4")
fn format_model_name(&self, model_name: &str) -> String {
fn format_segment(segment: &str) -> String {
if segment.eq_ignore_ascii_case("codex") {
return "Codex".to_string();
}
let mut chars = segment.chars();
match chars.next() {
Some(first) if first.is_ascii_alphabetic() => {
let mut formatted = String::new();
formatted.push(first.to_ascii_uppercase());
formatted.push_str(chars.as_str());
formatted
}
Some(first) => {
let mut formatted = String::new();
formatted.push(first);
formatted.push_str(chars.as_str());
formatted
}
None => String::new(),
}
}
if let Some(rest) = model_name.strip_prefix("gpt-") {
let formatted_rest = rest
.split('-')
.map(|segment| {
if segment.eq_ignore_ascii_case("codex") {
"Codex".to_string()
} else {
segment.to_string()
}
})
.map(format_segment)
.collect::<Vec<_>>()
.join("-");
format!("GPT-{}", formatted_rest)
@@ -23661,6 +23678,13 @@ mod tests {
TaskCompleteEvent,
};
use code_core::protocol::AgentInfo as CoreAgentInfo;
#[test]
fn format_model_name_capitalizes_codex_mini() {
let mut harness = ChatWidgetHarness::new();
let formatted = harness.chat().format_model_name("gpt-5-codex-mini");
assert_eq!(formatted, "GPT-5-Codex-Mini");
}
use ratatui::backend::TestBackend;
use ratatui::text::Line;
use ratatui::Terminal;