From 3d48862ec2ca4a27b23967d385afff409468a937 Mon Sep 17 00:00:00 2001 From: shijie-openai Date: Sun, 28 Jun 2026 09:06:47 -0700 Subject: [PATCH 1/3] Add first-class max reasoning effort --- codex-rs/core/tests/suite/remote_models.rs | 4 ++-- .../model-provider/src/amazon_bedrock/catalog.rs | 4 ++-- codex-rs/protocol/src/openai_models.rs | 16 ++++++++++++---- codex-rs/tui/src/chatwidget/model_popups.rs | 1 + .../tui/src/chatwidget/reasoning_shortcuts.rs | 2 +- ...__tests__model_reasoning_selection_popup.snap | 2 +- .../src/chatwidget/tests/popups_and_settings.rs | 4 ++-- 7 files changed, 21 insertions(+), 12 deletions(-) diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index 63d891bada8a..6ce0c42e449e 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -329,7 +329,7 @@ async fn remote_models_long_model_slug_is_sent_with_custom_reasoning() -> Result /*priority*/ 1_000, TruncationPolicyConfig::bytes(/*limit*/ 10_000), ); - let custom_reasoning_effort = ReasoningEffort::Custom("max".to_string()); + let custom_reasoning_effort = ReasoningEffort::Custom("future".to_string()); remote_model.default_reasoning_level = Some(custom_reasoning_effort.clone()); remote_model.supported_reasoning_levels = vec![ ReasoningEffortPreset { @@ -391,7 +391,7 @@ async fn remote_models_long_model_slug_is_sent_with_custom_reasoning() -> Result .and_then(|reasoning| reasoning.get("summary")) .and_then(|value| value.as_str()); assert_eq!(body["model"].as_str(), Some(requested_model)); - assert_eq!(reasoning_effort, Some("max")); + assert_eq!(reasoning_effort, Some("future")); assert_eq!(reasoning_summary, Some("detailed")); Ok(()) diff --git a/codex-rs/model-provider/src/amazon_bedrock/catalog.rs b/codex-rs/model-provider/src/amazon_bedrock/catalog.rs index 2294994ae69f..55e3fdd4d81c 100644 --- a/codex-rs/model-provider/src/amazon_bedrock/catalog.rs +++ b/codex-rs/model-provider/src/amazon_bedrock/catalog.rs @@ -70,7 +70,7 @@ fn gpt_5_6_bedrock_model(bedrock_slug: &str, display_name: &str, priority: i32) model .supported_reasoning_levels .push(ReasoningEffortPreset { - effort: ReasoningEffort::Custom("max".to_string()), + effort: ReasoningEffort::Max, description: "Maximum reasoning depth for the hardest problems".to_string(), }); model @@ -148,7 +148,7 @@ mod tests { expected .supported_reasoning_levels .push(ReasoningEffortPreset { - effort: ReasoningEffort::Custom("max".to_string()), + effort: ReasoningEffort::Max, description: "Maximum reasoning depth for the hardest problems".to_string(), }); diff --git a/codex-rs/protocol/src/openai_models.rs b/codex-rs/protocol/src/openai_models.rs index f697a8107f67..831c41dd2175 100644 --- a/codex-rs/protocol/src/openai_models.rs +++ b/codex-rs/protocol/src/openai_models.rs @@ -45,6 +45,7 @@ pub enum ReasoningEffort { Medium, High, XHigh, + Max, Ultra, /// A model-defined effort value that this client does not know yet. Custom(String), @@ -60,6 +61,7 @@ impl ReasoningEffort { Self::Medium => "medium", Self::High => "high", Self::XHigh => "xhigh", + Self::Max => "max", Self::Ultra => "ultra", Self::Custom(effort) => effort, } @@ -125,6 +127,7 @@ impl FromStr for ReasoningEffort { "medium" => Ok(Self::Medium), "high" => Ok(Self::High), "xhigh" => Ok(Self::XHigh), + "max" => Ok(Self::Max), "ultra" => Ok(Self::Ultra), "" => Err("reasoning_effort must not be empty".to_string()), effort => Ok(Self::Custom(effort.to_string())), @@ -700,30 +703,35 @@ mod tests { #[test] fn reasoning_effort_accepts_known_and_custom_values() { - let custom = ReasoningEffort::Custom("max".to_string()); - let deserialized = from_str::(r#""max""#) + let custom = ReasoningEffort::Custom("future".to_string()); + let deserialized = from_str::(r#""future""#) .expect("custom reasoning effort should deserialize"); let serialized = to_string(&custom).expect("custom reasoning effort should serialize"); + let serialized_max = to_string(&ReasoningEffort::Max).expect("Max should serialize"); let serialized_ultra = to_string(&ReasoningEffort::Ultra).expect("Ultra should serialize"); assert_eq!( ( "high".parse(), - "ultra".parse(), "max".parse(), + "ultra".parse(), + "future".parse(), deserialized, serialized, + serialized_max, serialized_ultra, custom.to_string(), ), ( Ok(ReasoningEffort::High), + Ok(ReasoningEffort::Max), Ok(ReasoningEffort::Ultra), Ok(custom.clone()), custom, + r#""future""#.to_string(), r#""max""#.to_string(), r#""ultra""#.to_string(), - "max".to_string(), + "future".to_string(), ) ); } diff --git a/codex-rs/tui/src/chatwidget/model_popups.rs b/codex-rs/tui/src/chatwidget/model_popups.rs index 3042ff6c7154..1194fc15c6ab 100644 --- a/codex-rs/tui/src/chatwidget/model_popups.rs +++ b/codex-rs/tui/src/chatwidget/model_popups.rs @@ -505,6 +505,7 @@ impl ChatWidget { ReasoningEffortConfig::Medium => "Medium".to_string(), ReasoningEffortConfig::High => "High".to_string(), ReasoningEffortConfig::XHigh => "Extra high".to_string(), + ReasoningEffortConfig::Max => "Max".to_string(), ReasoningEffortConfig::Ultra => "Ultra".to_string(), ReasoningEffortConfig::Custom(value) => value.clone(), } diff --git a/codex-rs/tui/src/chatwidget/reasoning_shortcuts.rs b/codex-rs/tui/src/chatwidget/reasoning_shortcuts.rs index 404bf870295e..0873bda6e003 100644 --- a/codex-rs/tui/src/chatwidget/reasoning_shortcuts.rs +++ b/codex-rs/tui/src/chatwidget/reasoning_shortcuts.rs @@ -225,7 +225,7 @@ mod tests { #[test] fn next_reasoning_effort_uses_advertised_order_for_custom_levels() { - let custom_effort = ReasoningEffortConfig::Custom("max".to_string()); + let custom_effort = ReasoningEffortConfig::Custom("future".to_string()); let choices = vec![ ReasoningEffortConfig::High, ReasoningEffortConfig::Low, diff --git a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__model_reasoning_selection_popup.snap b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__model_reasoning_selection_popup.snap index a436136570ee..60277720040d 100644 --- a/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__model_reasoning_selection_popup.snap +++ b/codex-rs/tui/src/chatwidget/snapshots/codex_tui__chatwidget__tests__model_reasoning_selection_popup.snap @@ -6,7 +6,7 @@ expression: popup 1. Low Fast responses with lighter reasoning 2. Medium (default) Balances speed and reasoning depth for everyday tasks - 3. max Maximum available reasoning + 3. Max Maximum available reasoning › 4. High (current) Greater reasoning depth for complex problems 5. Extra high Extra high reasoning depth for complex problems diff --git a/codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs b/codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs index 49b9ec7030ea..46af5f64f403 100644 --- a/codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs +++ b/codex-rs/tui/src/chatwidget/tests/popups_and_settings.rs @@ -3191,7 +3191,7 @@ async fn model_reasoning_selection_popup_snapshot() { preset.supported_reasoning_efforts.insert( 2, ReasoningEffortPreset { - effort: ReasoningEffortConfig::Custom("max".to_string()), + effort: ReasoningEffortConfig::Max, description: "Maximum available reasoning".to_string(), }, ); @@ -3204,7 +3204,7 @@ async fn model_reasoning_selection_popup_snapshot() { #[tokio::test] async fn model_reasoning_selection_popup_applies_custom_effort() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.4")).await; - let custom_effort = ReasoningEffortConfig::Custom("max".to_string()); + let custom_effort = ReasoningEffortConfig::Custom("future".to_string()); chat.set_reasoning_effort(Some(ReasoningEffortConfig::XHigh)); let mut preset = get_available_model(&chat, "gpt-5.4"); From 98cdcb84e50b6fab8357330bb6fa906027d62c6a Mon Sep 17 00:00:00 2001 From: shijie-openai Date: Sun, 28 Jun 2026 11:54:53 -0700 Subject: [PATCH 2/3] Test max reasoning effort request payload --- codex-rs/core/tests/suite/client.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index e109e51e6656..c87539f9406c 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -2171,7 +2171,7 @@ async fn skills_use_aliases_in_developer_message_under_budget_pressure() { } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn includes_configured_effort_in_request() -> anyhow::Result<()> { +async fn includes_configured_max_effort_in_request() -> anyhow::Result<()> { skip_if_no_network!(Ok(())); let server = MockServer::start().await; @@ -2183,7 +2183,7 @@ async fn includes_configured_effort_in_request() -> anyhow::Result<()> { let TestCodex { codex, .. } = test_codex() .with_model("gpt-5.4") .with_config(|config| { - config.model_reasoning_effort = Some(ReasoningEffort::Medium); + config.model_reasoning_effort = Some(ReasoningEffort::Max); }) .build(&server) .await?; @@ -2212,7 +2212,7 @@ async fn includes_configured_effort_in_request() -> anyhow::Result<()> { .get("reasoning") .and_then(|t| t.get("effort")) .and_then(|v| v.as_str()), - Some("medium") + Some("max") ); Ok(()) From 6a6da6f5fb59bfae7b7f740b776d1ef8a3c7902f Mon Sep 17 00:00:00 2001 From: shijie-openai Date: Sun, 28 Jun 2026 23:32:53 -0700 Subject: [PATCH 3/3] Use typed max effort for ultra requests --- codex-rs/core/src/client.rs | 2 +- codex-rs/core/src/client_tests.rs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs index ffa8ae8e20fa..48623a00e878 100644 --- a/codex-rs/core/src/client.rs +++ b/codex-rs/core/src/client.rs @@ -169,7 +169,7 @@ pub(crate) struct CompactConversationRequestSettings { fn reasoning_effort_for_request(effort: ReasoningEffortConfig) -> ReasoningEffortConfig { match effort { - ReasoningEffortConfig::Ultra => ReasoningEffortConfig::Custom("max".to_string()), + ReasoningEffortConfig::Ultra => ReasoningEffortConfig::Max, effort => effort, } } diff --git a/codex-rs/core/src/client_tests.rs b/codex-rs/core/src/client_tests.rs index dd2b1079f7b9..82c464625d5d 100644 --- a/codex-rs/core/src/client_tests.rs +++ b/codex-rs/core/src/client_tests.rs @@ -292,10 +292,7 @@ fn ultra_reasoning_uses_max_for_requests() { super::reasoning_effort_for_request(ReasoningEffort::Ultra), super::reasoning_effort_for_request(ReasoningEffort::High), ), - ( - ReasoningEffort::Custom("max".to_string()), - ReasoningEffort::High, - ) + (ReasoningEffort::Max, ReasoningEffort::High,) ); }