From 9eef0a24c92b5f7fc740b4a0261da243d090e074 Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Wed, 25 Feb 2026 22:34:25 -0800 Subject: [PATCH 1/6] Make reasoning summary config fallback to model default Keep config/session summary optional so missing values fall back to the model catalog default when building TurnContext, while TurnContext and request paths remain concrete. Also add protocol support for default_reasoning_summary with backward-compatible serde defaults. Co-authored-by: Codex --- codex-rs/core/src/codex.rs | 14 +++++++++----- codex-rs/core/src/config/mod.rs | 17 ++++++++--------- codex-rs/core/src/models_manager/model_info.rs | 2 ++ .../core/src/tools/handlers/multi_agents.rs | 6 +++--- codex-rs/protocol/src/openai_models.rs | 4 ++++ 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index b2145afaedd0..dadc7efaa908 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -754,7 +754,7 @@ pub(crate) struct SessionConfiguration { provider: ModelProviderInfo, collaboration_mode: CollaborationMode, - model_reasoning_summary: ReasoningSummaryConfig, + model_reasoning_summary: Option, /// Developer instructions that supplement the base instructions. developer_instructions: Option, @@ -824,7 +824,7 @@ impl SessionConfiguration { next_configuration.collaboration_mode = collaboration_mode; } if let Some(summary) = updates.reasoning_summary { - next_configuration.model_reasoning_summary = summary; + next_configuration.model_reasoning_summary = Some(summary); } if let Some(personality) = updates.personality { next_configuration.personality = Some(personality); @@ -985,7 +985,9 @@ impl Session { skills_outcome: Arc, ) -> TurnContext { let reasoning_effort = session_configuration.collaboration_mode.reasoning_effort(); - let reasoning_summary = session_configuration.model_reasoning_summary; + let reasoning_summary = session_configuration + .model_reasoning_summary + .unwrap_or(model_info.default_reasoning_summary); let otel_manager = otel_manager.clone().with_model( session_configuration.collaboration_mode.model(), model_info.slug.as_str(), @@ -1262,7 +1264,7 @@ impl Session { otel_manager.conversation_starts( config.model_provider.name.as_str(), session_configuration.collaboration_mode.reasoning_effort(), - config.model_reasoning_summary, + config.model_reasoning_summary.unwrap_or(ReasoningSummaryConfig::Auto), config.model_context_window, config.model_auto_compact_token_limit, config.permissions.approval_policy.value(), @@ -4615,7 +4617,9 @@ async fn spawn_review_thread( let provider_for_context = provider.clone(); let otel_manager_for_context = otel_manager.clone(); let reasoning_effort = per_turn_config.model_reasoning_effort; - let reasoning_summary = per_turn_config.model_reasoning_summary; + let reasoning_summary = per_turn_config + .model_reasoning_summary + .unwrap_or(model_info.default_reasoning_summary); let session_source = parent_turn_context.session_source.clone(); let per_turn_config = Arc::new(per_turn_config); diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index 306ba49c1006..994098544d7e 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -412,9 +412,9 @@ pub struct Config { /// global default"). pub plan_mode_reasoning_effort: Option, - /// If not "none", the value to use for `reasoning.summary` when making a - /// request using the Responses API. - pub model_reasoning_summary: ReasoningSummary, + /// Optional value to use for `reasoning.summary` when making a request + /// using the Responses API. When unset, the model catalog default is used. + pub model_reasoning_summary: Option, /// Optional override to force-enable reasoning summaries for the configured model. pub model_supports_reasoning_summaries: Option, @@ -2141,8 +2141,7 @@ impl Config { .or(cfg.plan_mode_reasoning_effort), model_reasoning_summary: config_profile .model_reasoning_summary - .or(cfg.model_reasoning_summary) - .unwrap_or_default(), + .or(cfg.model_reasoning_summary), model_supports_reasoning_summaries: cfg.model_supports_reasoning_summaries, model_catalog, model_verbosity: config_profile.model_verbosity.or(cfg.model_verbosity), @@ -4761,7 +4760,7 @@ model_verbosity = "high" show_raw_agent_reasoning: false, model_reasoning_effort: Some(ReasoningEffort::High), plan_mode_reasoning_effort: None, - model_reasoning_summary: ReasoningSummary::Detailed, + model_reasoning_summary: Some(ReasoningSummary::Detailed), model_supports_reasoning_summaries: None, model_catalog: None, model_verbosity: None, @@ -4887,7 +4886,7 @@ model_verbosity = "high" show_raw_agent_reasoning: false, model_reasoning_effort: None, plan_mode_reasoning_effort: None, - model_reasoning_summary: ReasoningSummary::default(), + model_reasoning_summary: None, model_supports_reasoning_summaries: None, model_catalog: None, model_verbosity: None, @@ -5011,7 +5010,7 @@ model_verbosity = "high" show_raw_agent_reasoning: false, model_reasoning_effort: None, plan_mode_reasoning_effort: None, - model_reasoning_summary: ReasoningSummary::default(), + model_reasoning_summary: None, model_supports_reasoning_summaries: None, model_catalog: None, model_verbosity: None, @@ -5121,7 +5120,7 @@ model_verbosity = "high" show_raw_agent_reasoning: false, model_reasoning_effort: Some(ReasoningEffort::High), plan_mode_reasoning_effort: None, - model_reasoning_summary: ReasoningSummary::Detailed, + model_reasoning_summary: Some(ReasoningSummary::Detailed), model_supports_reasoning_summaries: None, model_catalog: None, model_verbosity: Some(Verbosity::High), diff --git a/codex-rs/core/src/models_manager/model_info.rs b/codex-rs/core/src/models_manager/model_info.rs index 19a945f951f5..b63fdbad2795 100644 --- a/codex-rs/core/src/models_manager/model_info.rs +++ b/codex-rs/core/src/models_manager/model_info.rs @@ -3,6 +3,7 @@ use codex_protocol::openai_models::ModelInfo; use codex_protocol::openai_models::ModelInstructionsVariables; use codex_protocol::openai_models::ModelMessages; use codex_protocol::openai_models::ModelVisibility; +use codex_protocol::config_types::ReasoningSummary; use codex_protocol::openai_models::TruncationMode; use codex_protocol::openai_models::TruncationPolicyConfig; use codex_protocol::openai_models::default_input_modalities; @@ -72,6 +73,7 @@ pub(crate) fn model_info_from_slug(slug: &str) -> ModelInfo { base_instructions: BASE_INSTRUCTIONS.to_string(), model_messages: local_personality_messages_for_slug(slug), supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, diff --git a/codex-rs/core/src/tools/handlers/multi_agents.rs b/codex-rs/core/src/tools/handlers/multi_agents.rs index 6e62fd04fd1c..d8b83a866283 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents.rs @@ -914,7 +914,7 @@ fn build_agent_shared_config(turn: &TurnContext) -> Result, pub supports_reasoning_summaries: bool, + #[serde(default)] + pub default_reasoning_summary: ReasoningSummary, pub support_verbosity: bool, pub default_verbosity: Option, pub apply_patch_tool_type: Option, @@ -496,6 +499,7 @@ mod tests { base_instructions: "base".to_string(), model_messages: spec, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, From 5e1d8a0f62d787c5d7be4fa7bda61156beecb292 Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Wed, 25 Feb 2026 22:40:20 -0800 Subject: [PATCH 2/6] Fix suite tests for optional reasoning summary config Add a client integration test that verifies explicit model_reasoning_summary=none still omits reasoning.summary even when the model catalog default is detailed, and update suite tests for optional config summary + new model metadata field. Co-authored-by: Codex --- codex-rs/core/tests/suite/client.rs | 70 +++++++++++++++++-- .../tests/suite/collaboration_instructions.rs | 10 ++- codex-rs/core/tests/suite/model_switching.rs | 2 + codex-rs/core/tests/suite/models_cache_ttl.rs | 1 + codex-rs/core/tests/suite/personality.rs | 2 + codex-rs/core/tests/suite/prompt_caching.rs | 6 +- codex-rs/core/tests/suite/remote_models.rs | 7 +- codex-rs/core/tests/suite/resume_warning.rs | 3 +- codex-rs/core/tests/suite/rmcp_client.rs | 1 + codex-rs/core/tests/suite/view_image.rs | 1 + 10 files changed, 91 insertions(+), 12 deletions(-) diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index e040e61e77fa..039c75bb2d2a 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -32,6 +32,7 @@ use codex_protocol::models::ReasoningItemReasoningSummary; use codex_protocol::models::ResponseItem; use codex_protocol::models::WebSearchAction; use codex_protocol::openai_models::ReasoningEffort; +use codex_protocol::openai_models::ModelsResponse; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::SessionSource; @@ -992,7 +993,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re sandbox_policy: config.permissions.sandbox_policy.get().clone(), model: session_configured.model.clone(), effort: Some(ReasoningEffort::Low), - summary: config.model_reasoning_summary, + summary: config.model_reasoning_summary.unwrap_or(ReasoningSummary::Auto), collaboration_mode: Some(collaboration_mode), final_output_json_schema: None, personality: None, @@ -1026,7 +1027,7 @@ async fn configured_reasoning_summary_is_sent() -> anyhow::Result<()> { .await; let TestCodex { codex, .. } = test_codex() .with_config(|config| { - config.model_reasoning_summary = ReasoningSummary::Concise; + config.model_reasoning_summary = Some(ReasoningSummary::Concise); }) .build(&server) .await?; @@ -1070,7 +1071,7 @@ async fn reasoning_summary_is_omitted_when_disabled() -> anyhow::Result<()> { .await; let TestCodex { codex, .. } = test_codex() .with_config(|config| { - config.model_reasoning_summary = ReasoningSummary::None; + config.model_reasoning_summary = Some(ReasoningSummary::None); }) .build(&server) .await?; @@ -1101,6 +1102,60 @@ async fn reasoning_summary_is_omitted_when_disabled() -> anyhow::Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn reasoning_summary_none_overrides_model_catalog_default() -> anyhow::Result<()> { + skip_if_no_network!(Ok(())); + let server = MockServer::start().await; + + let resp_mock = mount_sse_once( + &server, + sse(vec![ev_response_created("resp1"), ev_completed("resp1")]), + ) + .await; + + let mut model_catalog: ModelsResponse = + serde_json::from_str(include_str!("../../models.json")).expect("valid models.json"); + let model = model_catalog + .models + .iter_mut() + .find(|model| model.slug == "gpt-5.1") + .expect("gpt-5.1 exists in bundled models.json"); + model.supports_reasoning_summaries = true; + model.default_reasoning_summary = ReasoningSummary::Detailed; + + let TestCodex { codex, .. } = test_codex() + .with_model("gpt-5.1") + .with_config(move |config| { + config.model_reasoning_summary = Some(ReasoningSummary::None); + config.model_catalog = Some(model_catalog.clone()); + }) + .build(&server) + .await?; + + codex + .submit(Op::UserInput { + items: vec![UserInput::Text { + text: "hello".into(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + }) + .await + .unwrap(); + + wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await; + + let request_body = resp_mock.single_request().body_json(); + pretty_assertions::assert_eq!( + request_body + .get("reasoning") + .and_then(|reasoning| reasoning.get("summary")), + None + ); + + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn includes_default_verbosity_in_request() -> anyhow::Result<()> { skip_if_no_network!(Ok(())); @@ -1430,7 +1485,14 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() { }); let mut stream = client_session - .stream(&prompt, &model_info, &otel_manager, effort, summary, None) + .stream( + &prompt, + &model_info, + &otel_manager, + effort, + summary.unwrap_or(ReasoningSummary::Auto), + None, + ) .await .expect("responses stream to start"); diff --git a/codex-rs/core/tests/suite/collaboration_instructions.rs b/codex-rs/core/tests/suite/collaboration_instructions.rs index 68d695325d3d..7f5732b3a3de 100644 --- a/codex-rs/core/tests/suite/collaboration_instructions.rs +++ b/codex-rs/core/tests/suite/collaboration_instructions.rs @@ -169,7 +169,10 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> { sandbox_policy: test.config.permissions.sandbox_policy.get().clone(), model: test.session_configured.model.clone(), effort: None, - summary: test.config.model_reasoning_summary, + summary: test + .config + .model_reasoning_summary + .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), collaboration_mode: Some(collaboration_mode), final_output_json_schema: None, personality: None, @@ -275,7 +278,10 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu sandbox_policy: test.config.permissions.sandbox_policy.get().clone(), model: test.session_configured.model.clone(), effort: None, - summary: test.config.model_reasoning_summary, + summary: test + .config + .model_reasoning_summary + .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), collaboration_mode: Some(turn_mode), final_output_json_schema: None, personality: None, diff --git a/codex-rs/core/tests/suite/model_switching.rs b/codex-rs/core/tests/suite/model_switching.rs index 6e06b0f22483..8bf189eb4265 100644 --- a/codex-rs/core/tests/suite/model_switching.rs +++ b/codex-rs/core/tests/suite/model_switching.rs @@ -234,6 +234,7 @@ async fn model_change_from_image_to_text_strips_prior_image_content() -> Result< base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, @@ -391,6 +392,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result< base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, diff --git a/codex-rs/core/tests/suite/models_cache_ttl.rs b/codex-rs/core/tests/suite/models_cache_ttl.rs index 3422e397b89c..1abe6e5dc4e2 100644 --- a/codex-rs/core/tests/suite/models_cache_ttl.rs +++ b/codex-rs/core/tests/suite/models_cache_ttl.rs @@ -336,6 +336,7 @@ fn test_remote_model(slug: &str, priority: i32) -> ModelInfo { base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, diff --git a/codex-rs/core/tests/suite/personality.rs b/codex-rs/core/tests/suite/personality.rs index 0b4d485cfb03..d2e7fadd4510 100644 --- a/codex-rs/core/tests/suite/personality.rs +++ b/codex-rs/core/tests/suite/personality.rs @@ -599,6 +599,7 @@ async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow }), }), supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, @@ -706,6 +707,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() - }), }), supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, diff --git a/codex-rs/core/tests/suite/prompt_caching.rs b/codex-rs/core/tests/suite/prompt_caching.rs index 38a8145d5066..744fd5ccf69a 100644 --- a/codex-rs/core/tests/suite/prompt_caching.rs +++ b/codex-rs/core/tests/suite/prompt_caching.rs @@ -746,7 +746,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a sandbox_policy: default_sandbox_policy.clone(), model: default_model.clone(), effort: default_effort, - summary: default_summary, + summary: default_summary.unwrap_or(ReasoningSummary::Auto), collaboration_mode: None, final_output_json_schema: None, personality: None, @@ -765,7 +765,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a sandbox_policy: default_sandbox_policy.clone(), model: default_model.clone(), effort: default_effort, - summary: default_summary, + summary: default_summary.unwrap_or(ReasoningSummary::Auto), collaboration_mode: None, final_output_json_schema: None, personality: None, @@ -854,7 +854,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu sandbox_policy: default_sandbox_policy.clone(), model: default_model, effort: default_effort, - summary: default_summary, + summary: default_summary.unwrap_or(ReasoningSummary::Auto), collaboration_mode: None, final_output_json_schema: None, personality: None, diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index 166f0ceac6c2..8cac97c314c0 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -175,7 +175,7 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<( sandbox_policy: config.permissions.sandbox_policy.get().clone(), model: requested_model.to_string(), effort: None, - summary: config.model_reasoning_summary, + summary: config.model_reasoning_summary.unwrap_or(ReasoningSummary::Auto), collaboration_mode: None, personality: None, }) @@ -227,7 +227,7 @@ async fn namespaced_model_slug_uses_catalog_metadata_without_fallback_warning() sandbox_policy: config.permissions.sandbox_policy.get().clone(), model: requested_model.to_string(), effort: None, - summary: config.model_reasoning_summary, + summary: config.model_reasoning_summary.unwrap_or(ReasoningSummary::Auto), collaboration_mode: None, personality: None, }) @@ -284,6 +284,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> { base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, @@ -520,6 +521,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> { base_instructions: remote_base.to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, @@ -980,6 +982,7 @@ fn test_remote_model_with_policy( base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, diff --git a/codex-rs/core/tests/suite/resume_warning.rs b/codex-rs/core/tests/suite/resume_warning.rs index b0503d5929c7..9ab9f191d11e 100644 --- a/codex-rs/core/tests/suite/resume_warning.rs +++ b/codex-rs/core/tests/suite/resume_warning.rs @@ -4,6 +4,7 @@ use codex_core::CodexAuth; use codex_core::NewThread; use codex_protocol::ThreadId; use codex_protocol::config_types::ModeKind; +use codex_protocol::config_types::ReasoningSummary; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::InitialHistory; use codex_protocol::protocol::ResumedHistory; @@ -34,7 +35,7 @@ fn resume_history( personality: None, collaboration_mode: None, effort: config.model_reasoning_effort, - summary: config.model_reasoning_summary, + summary: config.model_reasoning_summary.unwrap_or(ReasoningSummary::Auto), user_instructions: None, developer_instructions: None, final_output_json_schema: None, diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index df389c5ef74f..c1c71d3f7107 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -398,6 +398,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, diff --git a/codex-rs/core/tests/suite/view_image.rs b/codex-rs/core/tests/suite/view_image.rs index 36ccf1a25e6b..6cf9f54d4e4b 100644 --- a/codex-rs/core/tests/suite/view_image.rs +++ b/codex-rs/core/tests/suite/view_image.rs @@ -675,6 +675,7 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, From ab2620b4346378d2a41bcc7494b72006861aa88b Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Thu, 26 Feb 2026 08:31:35 -0800 Subject: [PATCH 3/6] tests: set default_reasoning_summary to Auto in models_client integration test --- codex-rs/codex-api/tests/models_integration.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codex-rs/codex-api/tests/models_integration.rs b/codex-rs/codex-api/tests/models_integration.rs index 9f7e38066501..08a086059466 100644 --- a/codex-rs/codex-api/tests/models_integration.rs +++ b/codex-rs/codex-api/tests/models_integration.rs @@ -3,6 +3,7 @@ use codex_api::ModelsClient; use codex_api::provider::Provider; use codex_api::provider::RetryConfig; use codex_client::ReqwestTransport; +use codex_protocol::config_types::ReasoningSummary; use codex_protocol::openai_models::ConfigShellToolType; use codex_protocol::openai_models::ModelInfo; use codex_protocol::openai_models::ModelVisibility; @@ -78,6 +79,7 @@ async fn models_client_hits_models_endpoint() { base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, From 226f984f9d202af99bdcc9c09113408e55ab09ae Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Thu, 26 Feb 2026 08:51:50 -0800 Subject: [PATCH 4/6] Fix clippy fallout for optional reasoning summary Update test fixtures and call sites for optional model reasoning summary and clean up a clippy redundant clone lint. Co-authored-by: Codex --- .../app-server/tests/common/models_cache.rs | 2 ++ codex-rs/core/tests/responses_headers.rs | 29 ++++++++++++++++--- codex-rs/core/tests/suite/client.rs | 8 +++-- codex-rs/exec/src/lib.rs | 3 +- codex-rs/tui/src/chatwidget.rs | 5 +++- codex-rs/tui/src/lib.rs | 4 ++- codex-rs/tui/src/status/card.rs | 5 +++- codex-rs/tui/src/status/tests.rs | 4 +-- .../sandbox-summary/src/config_summary.rs | 5 +++- 9 files changed, 51 insertions(+), 14 deletions(-) diff --git a/codex-rs/app-server/tests/common/models_cache.rs b/codex-rs/app-server/tests/common/models_cache.rs index 218a1d0e406d..a38da2e07fe9 100644 --- a/codex-rs/app-server/tests/common/models_cache.rs +++ b/codex-rs/app-server/tests/common/models_cache.rs @@ -1,6 +1,7 @@ use chrono::DateTime; use chrono::Utc; use codex_core::test_support::all_model_presets; +use codex_protocol::config_types::ReasoningSummary; use codex_protocol::openai_models::ConfigShellToolType; use codex_protocol::openai_models::ModelInfo; use codex_protocol::openai_models::ModelPreset; @@ -30,6 +31,7 @@ fn preset_to_info(preset: &ModelPreset, priority: i32) -> ModelInfo { base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, diff --git a/codex-rs/core/tests/responses_headers.rs b/codex-rs/core/tests/responses_headers.rs index 126dc2c288d4..f502ec08be9a 100644 --- a/codex-rs/core/tests/responses_headers.rs +++ b/codex-rs/core/tests/responses_headers.rs @@ -111,7 +111,14 @@ async fn responses_stream_includes_subagent_header_on_review() { }]; let mut stream = client_session - .stream(&prompt, &model_info, &otel_manager, effort, summary, None) + .stream( + &prompt, + &model_info, + &otel_manager, + effort, + summary.unwrap_or(model_info.default_reasoning_summary), + None, + ) .await .expect("stream failed"); while let Some(event) = stream.next().await { @@ -216,7 +223,14 @@ async fn responses_stream_includes_subagent_header_on_other() { }]; let mut stream = client_session - .stream(&prompt, &model_info, &otel_manager, effort, summary, None) + .stream( + &prompt, + &model_info, + &otel_manager, + effort, + summary.unwrap_or(model_info.default_reasoning_summary), + None, + ) .await .expect("stream failed"); while let Some(event) = stream.next().await { @@ -267,7 +281,7 @@ async fn responses_respects_model_info_overrides_from_config() { config.model_provider_id = provider.name.clone(); config.model_provider = provider.clone(); config.model_supports_reasoning_summaries = Some(true); - config.model_reasoning_summary = ReasoningSummary::Detailed; + config.model_reasoning_summary = Some(ReasoningSummary::Detailed); let effort = config.model_reasoning_effort; let summary = config.model_reasoning_summary; let model = config.model.clone().expect("model configured"); @@ -320,7 +334,14 @@ async fn responses_respects_model_info_overrides_from_config() { }]; let mut stream = client_session - .stream(&prompt, &model_info, &otel_manager, effort, summary, None) + .stream( + &prompt, + &model_info, + &otel_manager, + effort, + summary.unwrap_or(model_info.default_reasoning_summary), + None, + ) .await .expect("stream failed"); while let Some(event) = stream.next().await { diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 039c75bb2d2a..5670371c6c7f 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -31,8 +31,8 @@ use codex_protocol::models::ReasoningItemContent; use codex_protocol::models::ReasoningItemReasoningSummary; use codex_protocol::models::ResponseItem; use codex_protocol::models::WebSearchAction; -use codex_protocol::openai_models::ReasoningEffort; use codex_protocol::openai_models::ModelsResponse; +use codex_protocol::openai_models::ReasoningEffort; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::Op; use codex_protocol::protocol::SessionSource; @@ -993,7 +993,9 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re sandbox_policy: config.permissions.sandbox_policy.get().clone(), model: session_configured.model.clone(), effort: Some(ReasoningEffort::Low), - summary: config.model_reasoning_summary.unwrap_or(ReasoningSummary::Auto), + summary: config + .model_reasoning_summary + .unwrap_or(ReasoningSummary::Auto), collaboration_mode: Some(collaboration_mode), final_output_json_schema: None, personality: None, @@ -1127,7 +1129,7 @@ async fn reasoning_summary_none_overrides_model_catalog_default() -> anyhow::Res .with_model("gpt-5.1") .with_config(move |config| { config.model_reasoning_summary = Some(ReasoningSummary::None); - config.model_catalog = Some(model_catalog.clone()); + config.model_catalog = Some(model_catalog); }) .build(&server) .await?; diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index 1dca110aff65..9b3403f2e9ce 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -560,7 +560,8 @@ pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result sandbox_policy: default_sandbox_policy.clone(), model: default_model, effort: default_effort, - summary: default_summary, + summary: default_summary + .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), final_output_json_schema: output_schema, collaboration_mode: None, personality: None, diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index a4063ed3d6b5..5c6c51b7bce8 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -4139,7 +4139,10 @@ impl ChatWidget { sandbox_policy: self.config.permissions.sandbox_policy.get().clone(), model: effective_mode.model().to_string(), effort: effective_mode.reasoning_effort(), - summary: self.config.model_reasoning_summary, + summary: self + .config + .model_reasoning_summary + .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), final_output_json_schema: None, collaboration_mode, personality, diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index d51f42b2fffa..f5d0cab601d0 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -1159,7 +1159,9 @@ mod tests { personality: None, collaboration_mode: None, effort: config.model_reasoning_effort, - summary: config.model_reasoning_summary, + summary: config + .model_reasoning_summary + .unwrap_or(codex_protocol::config_types::ReasoningSummary::Auto), user_instructions: None, developer_instructions: None, final_output_json_schema: None, diff --git a/codex-rs/tui/src/status/card.rs b/codex-rs/tui/src/status/card.rs index acfa604e97c1..a87e76736fd9 100644 --- a/codex-rs/tui/src/status/card.rs +++ b/codex-rs/tui/src/status/card.rs @@ -185,7 +185,10 @@ impl StatusHistoryCell { config_entries.push(("reasoning effort", effort_value)); config_entries.push(( "reasoning summaries", - config.model_reasoning_summary.to_string(), + config + .model_reasoning_summary + .map(|summary| summary.to_string()) + .unwrap_or_else(|| "none".to_string()), )); } let (model_name, model_details) = compose_model_display(model_name, &config_entries); diff --git a/codex-rs/tui/src/status/tests.rs b/codex-rs/tui/src/status/tests.rs index fb1aad72753c..16ab60bd72ea 100644 --- a/codex-rs/tui/src/status/tests.rs +++ b/codex-rs/tui/src/status/tests.rs @@ -96,7 +96,7 @@ async fn status_snapshot_includes_reasoning_details() { let mut config = test_config(&temp_home).await; config.model = Some("gpt-5.1-codex-max".to_string()); config.model_provider_id = "openai".to_string(); - config.model_reasoning_summary = ReasoningSummary::Detailed; + config.model_reasoning_summary = Some(ReasoningSummary::Detailed); config .permissions .sandbox_policy @@ -596,7 +596,7 @@ async fn status_snapshot_truncates_in_narrow_terminal() { let mut config = test_config(&temp_home).await; config.model = Some("gpt-5.1-codex-max".to_string()); config.model_provider_id = "openai".to_string(); - config.model_reasoning_summary = ReasoningSummary::Detailed; + config.model_reasoning_summary = Some(ReasoningSummary::Detailed); config.cwd = PathBuf::from("/workspace/tests"); let auth_manager = test_auth_manager(&config); diff --git a/codex-rs/utils/sandbox-summary/src/config_summary.rs b/codex-rs/utils/sandbox-summary/src/config_summary.rs index a83a65723bda..0f6b1929790c 100644 --- a/codex-rs/utils/sandbox-summary/src/config_summary.rs +++ b/codex-rs/utils/sandbox-summary/src/config_summary.rs @@ -28,7 +28,10 @@ pub fn create_config_summary_entries(config: &Config, model: &str) -> Vec<(&'sta )); entries.push(( "reasoning summaries", - config.model_reasoning_summary.to_string(), + config + .model_reasoning_summary + .map(|summary| summary.to_string()) + .unwrap_or_else(|| "none".to_string()), )); } From 940d0a96aa806a2ed4e978a1b8bb458fe7b7d0c4 Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Thu, 26 Feb 2026 08:57:18 -0800 Subject: [PATCH 5/6] style: rustfmt fixes for reasoning summary config and imports --- codex-rs/core/src/codex.rs | 4 +++- codex-rs/core/src/models_manager/model_info.rs | 2 +- codex-rs/core/tests/suite/remote_models.rs | 8 ++++++-- codex-rs/core/tests/suite/resume_warning.rs | 4 +++- codex-rs/core/tests/suite/rmcp_client.rs | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index dadc7efaa908..10a1087481ab 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -1264,7 +1264,9 @@ impl Session { otel_manager.conversation_starts( config.model_provider.name.as_str(), session_configuration.collaboration_mode.reasoning_effort(), - config.model_reasoning_summary.unwrap_or(ReasoningSummaryConfig::Auto), + config + .model_reasoning_summary + .unwrap_or(ReasoningSummaryConfig::Auto), config.model_context_window, config.model_auto_compact_token_limit, config.permissions.approval_policy.value(), diff --git a/codex-rs/core/src/models_manager/model_info.rs b/codex-rs/core/src/models_manager/model_info.rs index b63fdbad2795..79b8520ecdbf 100644 --- a/codex-rs/core/src/models_manager/model_info.rs +++ b/codex-rs/core/src/models_manager/model_info.rs @@ -1,9 +1,9 @@ +use codex_protocol::config_types::ReasoningSummary; use codex_protocol::openai_models::ConfigShellToolType; use codex_protocol::openai_models::ModelInfo; use codex_protocol::openai_models::ModelInstructionsVariables; use codex_protocol::openai_models::ModelMessages; use codex_protocol::openai_models::ModelVisibility; -use codex_protocol::config_types::ReasoningSummary; use codex_protocol::openai_models::TruncationMode; use codex_protocol::openai_models::TruncationPolicyConfig; use codex_protocol::openai_models::default_input_modalities; diff --git a/codex-rs/core/tests/suite/remote_models.rs b/codex-rs/core/tests/suite/remote_models.rs index 8cac97c314c0..748c9146a048 100644 --- a/codex-rs/core/tests/suite/remote_models.rs +++ b/codex-rs/core/tests/suite/remote_models.rs @@ -175,7 +175,9 @@ async fn remote_models_long_model_slug_is_sent_with_high_reasoning() -> Result<( sandbox_policy: config.permissions.sandbox_policy.get().clone(), model: requested_model.to_string(), effort: None, - summary: config.model_reasoning_summary.unwrap_or(ReasoningSummary::Auto), + summary: config + .model_reasoning_summary + .unwrap_or(ReasoningSummary::Auto), collaboration_mode: None, personality: None, }) @@ -227,7 +229,9 @@ async fn namespaced_model_slug_uses_catalog_metadata_without_fallback_warning() sandbox_policy: config.permissions.sandbox_policy.get().clone(), model: requested_model.to_string(), effort: None, - summary: config.model_reasoning_summary.unwrap_or(ReasoningSummary::Auto), + summary: config + .model_reasoning_summary + .unwrap_or(ReasoningSummary::Auto), collaboration_mode: None, personality: None, }) diff --git a/codex-rs/core/tests/suite/resume_warning.rs b/codex-rs/core/tests/suite/resume_warning.rs index 9ab9f191d11e..a5f22e9f8dd9 100644 --- a/codex-rs/core/tests/suite/resume_warning.rs +++ b/codex-rs/core/tests/suite/resume_warning.rs @@ -35,7 +35,9 @@ fn resume_history( personality: None, collaboration_mode: None, effort: config.model_reasoning_effort, - summary: config.model_reasoning_summary.unwrap_or(ReasoningSummary::Auto), + summary: config + .model_reasoning_summary + .unwrap_or(ReasoningSummary::Auto), user_instructions: None, developer_instructions: None, final_output_json_schema: None, diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index c1c71d3f7107..fcb0d49a140b 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -398,7 +398,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re base_instructions: "base instructions".to_string(), model_messages: None, supports_reasoning_summaries: false, - default_reasoning_summary: ReasoningSummary::Auto, + default_reasoning_summary: ReasoningSummary::Auto, support_verbosity: false, default_verbosity: None, apply_patch_tool_type: None, From 3425fdbd7e8cd2f1c72f6c0a755131c1dd42cee4 Mon Sep 17 00:00:00 2001 From: pakrym-oai Date: Thu, 26 Feb 2026 09:13:30 -0800 Subject: [PATCH 6/6] tui: change default reasoning summary to auto --- codex-rs/tui/src/status/card.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codex-rs/tui/src/status/card.rs b/codex-rs/tui/src/status/card.rs index a87e76736fd9..a7546230bf58 100644 --- a/codex-rs/tui/src/status/card.rs +++ b/codex-rs/tui/src/status/card.rs @@ -188,7 +188,7 @@ impl StatusHistoryCell { config .model_reasoning_summary .map(|summary| summary.to_string()) - .unwrap_or_else(|| "none".to_string()), + .unwrap_or_else(|| "auto".to_string()), )); } let (model_name, model_details) = compose_model_display(model_name, &config_entries);