This commit is contained in:
Ahmed Ibrahim
2025-11-18 14:34:14 -08:00
parent 1fafbb0fb8
commit 0afeea3b5e
6 changed files with 120 additions and 19 deletions
@@ -45,6 +45,29 @@ async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
} = to_response::<ModelListResponse>(response)?;
let expected_models = vec![
Model {
id: "codex-auto".to_string(),
model: "codex-auto".to_string(),
display_name: "codex-auto".to_string(),
description: "Automatically chooses the best Codex model configuration for your task."
.to_string(),
supported_reasoning_efforts: vec![
ReasoningEffortOption {
reasoning_effort: ReasoningEffort::Low,
description: "Works faster".to_string(),
},
ReasoningEffortOption {
reasoning_effort: ReasoningEffort::Medium,
description: "Balances speed with intelligence".to_string(),
},
ReasoningEffortOption {
reasoning_effort: ReasoningEffort::High,
description: "Works longer for harder tasks".to_string(),
},
],
default_reasoning_effort: ReasoningEffort::Medium,
is_default: true,
},
Model {
id: "gpt-5.1-codex".to_string(),
model: "gpt-5.1-codex".to_string(),
@@ -66,7 +89,7 @@ async fn list_models_returns_all_models_with_large_limit() -> Result<()> {
},
],
default_reasoning_effort: ReasoningEffort::Medium,
is_default: true,
is_default: false,
},
Model {
id: "gpt-5.1-codex-mini".to_string(),
@@ -147,7 +170,7 @@ async fn list_models_pagination_works() -> Result<()> {
} = to_response::<ModelListResponse>(first_response)?;
assert_eq!(first_items.len(), 1);
assert_eq!(first_items[0].id, "gpt-5.1-codex");
assert_eq!(first_items[0].id, "codex-auto");
let next_cursor = first_cursor.ok_or_else(|| anyhow!("cursor for second page"))?;
let second_request = mcp
@@ -169,7 +192,7 @@ async fn list_models_pagination_works() -> Result<()> {
} = to_response::<ModelListResponse>(second_response)?;
assert_eq!(second_items.len(), 1);
assert_eq!(second_items[0].id, "gpt-5.1-codex-mini");
assert_eq!(second_items[0].id, "gpt-5.1-codex");
let third_cursor = second_cursor.ok_or_else(|| anyhow!("cursor for third page"))?;
let third_request = mcp
@@ -191,8 +214,30 @@ async fn list_models_pagination_works() -> Result<()> {
} = to_response::<ModelListResponse>(third_response)?;
assert_eq!(third_items.len(), 1);
assert_eq!(third_items[0].id, "gpt-5.1");
assert!(third_cursor.is_none());
assert_eq!(third_items[0].id, "gpt-5.1-codex-mini");
let fourth_cursor = third_cursor.ok_or_else(|| anyhow!("cursor for fourth page"))?;
let fourth_request = mcp
.send_list_models_request(ModelListParams {
limit: Some(1),
cursor: Some(fourth_cursor.clone()),
})
.await?;
let fourth_response: JSONRPCResponse = timeout(
DEFAULT_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(fourth_request)),
)
.await??;
let ModelListResponse {
data: fourth_items,
next_cursor: fourth_cursor,
} = to_response::<ModelListResponse>(fourth_response)?;
assert_eq!(fourth_items.len(), 1);
assert_eq!(fourth_items[0].id, "gpt-5.1");
assert!(fourth_cursor.is_none());
Ok(())
}
+33 -2
View File
@@ -245,11 +245,15 @@ static PRESETS: Lazy<Vec<ModelPreset>> = Lazy::new(|| {
]
});
pub fn builtin_model_presets(_auth_mode: Option<AuthMode>) -> Vec<ModelPreset> {
// leave auth mode for later use
pub fn builtin_model_presets(auth_mode: Option<AuthMode>) -> Vec<ModelPreset> {
PRESETS
.iter()
.filter(|preset| preset.upgrade.is_none())
.filter(|preset| match auth_mode {
// `codex-auto` is only available when using ChatGPT-style auth.
Some(AuthMode::ApiKey) => preset.id != "codex-auto",
_ => true,
})
.cloned()
.collect()
}
@@ -276,4 +280,31 @@ mod tests {
let default_models = PRESETS.iter().filter(|preset| preset.is_default).count();
assert!(default_models == 1);
}
#[test]
fn codex_auto_is_included_for_non_api_auth() {
let presets_no_auth = builtin_model_presets(None);
assert!(
presets_no_auth
.iter()
.any(|preset| preset.id == "codex-auto")
);
let presets_chatgpt = builtin_model_presets(Some(AuthMode::ChatGPT));
assert!(
presets_chatgpt
.iter()
.any(|preset| preset.id == "codex-auto")
);
}
#[test]
fn codex_auto_is_excluded_for_api_key_auth() {
let presets_api_key = builtin_model_presets(Some(AuthMode::ApiKey));
assert!(
!presets_api_key
.iter()
.any(|preset| preset.id == "codex-auto")
);
}
}
@@ -194,6 +194,18 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> {
"view_image",
],
),
(
"codex-auto",
vec![
"shell",
"list_mcp_resources",
"list_mcp_resource_templates",
"read_mcp_resource",
"update_plan",
"apply_patch",
"view_image",
],
),
(
"gpt-5.1-codex",
vec![
@@ -4,9 +4,9 @@ expression: popup
---
Select Reasoning Level for gpt-5.1-codex
1. Low Fastest responses with limited reasoning
2. Medium (default) Dynamically adjusts reasoning based on the task
› 3. High (current) Maximizes reasoning depth for complex or ambiguous
1. low Fastest responses with limited reasoning
2. medium (default) Dynamically adjusts reasoning based on the task
› 3. high (current) Maximizes reasoning depth for complex or ambiguous
problems
⚠ High reasoning effort can quickly consume Plus plan
rate limits.
@@ -1,15 +1,13 @@
---
source: tui/src/chatwidget/tests.rs
assertion_line: 1440
expression: popup
---
Select Model
Quickly pick Codex Auto or open the legacy list for more options.
Select Model and Effort
Access legacy models by running codex -m <model_name> or in your config.toml
› 1. Fast Works faster
2. Balanced (default) Balances speed with intelligence
3. Thorough Works longer for harder tasks
4. All models Choose and configure what model and reasoning level
to use
› 1. gpt-5.1-codex Optimized for codex.
2. gpt-5.1-codex-mini Optimized for codex. Cheaper, faster, but less
capable.
3. gpt-5.1 Broad world knowledge with strong general reasoning.
Press enter to apply selection, or esc to dismiss.
Press enter to select reasoning effort, or esc to dismiss.
+15
View File
@@ -1440,6 +1440,21 @@ fn model_selection_popup_snapshot() {
assert_snapshot!("model_selection_popup", popup);
}
#[test]
fn model_selection_popup_chatgpt_auth_snapshot() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual();
chat.auth_manager =
AuthManager::from_auth_for_testing(CodexAuth::create_dummy_chatgpt_auth_for_testing());
chat.config.model = "gpt-5.1-codex".to_string();
chat.open_model_popup();
let popup = render_bottom_popup(&chat, 80);
insta::with_settings!({ snapshot_suffix => "chatgpt_auth" }, {
assert_snapshot!("model_selection_popup", popup);
});
}
#[test]
fn featured_model_popup_hides_default_label_when_option_is_current() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual();