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

View File

@@ -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(())
}

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")
);
}
}

View File

@@ -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![

View File

@@ -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.

View File

@@ -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.

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();