From 051b72c3701c9d8fefac7b7a965b6ae7eff2672c Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Wed, 8 Jul 2026 18:19:52 -0700 Subject: [PATCH] core: move reasoning effort to step context --- codex-rs/core/src/compact.rs | 9 ++++-- codex-rs/core/src/compact_remote_request.rs | 2 +- codex-rs/core/src/compact_remote_v2.rs | 5 +-- .../core/src/compact_remote_v2_attempt.rs | 2 +- codex-rs/core/src/guardian/review.rs | 3 +- codex-rs/core/src/guardian/review_session.rs | 2 +- codex-rs/core/src/mcp_tool_call.rs | 7 +++-- codex-rs/core/src/mcp_tool_call_tests.rs | 22 +++++++++---- codex-rs/core/src/session/mod.rs | 2 ++ codex-rs/core/src/session/review.rs | 2 -- .../session/rollout_reconstruction_tests.rs | 16 +++++----- codex-rs/core/src/session/step_context.rs | 20 ++++++++++++ codex-rs/core/src/session/tests.rs | 10 +++--- codex-rs/core/src/session/turn.rs | 17 +++++----- codex-rs/core/src/session/turn_context.rs | 31 +++++++++---------- codex-rs/core/src/session_startup_prewarm.rs | 2 +- .../src/tools/handlers/multi_agents_common.rs | 3 +- .../src/tools/handlers/multi_agents_tests.rs | 4 +-- codex-rs/core/src/tools/spec_plan_tests.rs | 1 + 19 files changed, 97 insertions(+), 63 deletions(-) diff --git a/codex-rs/core/src/compact.rs b/codex-rs/core/src/compact.rs index d2a9fd5222..e335792ac3 100644 --- a/codex-rs/core/src/compact.rs +++ b/codex-rs/core/src/compact.rs @@ -15,6 +15,7 @@ use crate::responses_metadata::CompactionTurnMetadata; #[cfg(test)] use crate::session::PreviousTurnSettings; use crate::session::session::Session; +use crate::session::step_context::StepContext; use crate::session::turn::get_last_assistant_message_from_turn; use crate::session::turn_context::TurnContext; use crate::util::backoff; @@ -238,6 +239,7 @@ async fn run_compact_task_inner_impl( let max_retries = turn_context.provider.info().stream_max_retries(); let mut retries = 0; let mut client_session = sess.services.model_client.new_session(); + let step_context = sess.capture_step_context(Arc::clone(&turn_context)).await; // Reuse one client session so turn-scoped state (sticky routing, websocket incremental // request tracking) // survives retries within this compact turn. @@ -261,7 +263,7 @@ async fn run_compact_task_inner_impl( }; let attempt_result = drain_to_completed( &sess, - turn_context.as_ref(), + step_context.as_ref(), &mut client_session, &responses_metadata, &prompt, @@ -660,17 +662,18 @@ fn build_compacted_history_with_limit( async fn drain_to_completed( sess: &Session, - turn_context: &TurnContext, + step_context: &StepContext, client_session: &mut ModelClientSession, responses_metadata: &CodexResponsesMetadata, prompt: &Prompt, ) -> CodexResult<()> { + let turn_context = step_context.turn.as_ref(); let mut stream = client_session .stream( prompt, &turn_context.model_info, &turn_context.session_telemetry, - turn_context.reasoning_effort.clone(), + step_context.reasoning_effort.clone(), turn_context.reasoning_summary, turn_context.config.service_tier.clone(), responses_metadata, diff --git a/codex-rs/core/src/compact_remote_request.rs b/codex-rs/core/src/compact_remote_request.rs index bbf2f04446..1ab9213f00 100644 --- a/codex-rs/core/src/compact_remote_request.rs +++ b/codex-rs/core/src/compact_remote_request.rs @@ -87,7 +87,7 @@ pub(super) async fn run_remote_compact_attempt( &turn_context.model_info, turn_state, CompactConversationRequestSettings { - effort: turn_context.reasoning_effort.clone(), + effort: step_context.reasoning_effort.clone(), summary: turn_context.reasoning_summary, service_tier: if sess.services.auth_manager.auth_mode() == Some(AuthMode::ApiKey) { None diff --git a/codex-rs/core/src/compact_remote_v2.rs b/codex-rs/core/src/compact_remote_v2.rs index 1571602cc1..d3ffdcbd65 100644 --- a/codex-rs/core/src/compact_remote_v2.rs +++ b/codex-rs/core/src/compact_remote_v2.rs @@ -329,11 +329,12 @@ struct RemoteCompactionV2Output { async fn run_remote_compaction_request_v2( sess: &Session, - turn_context: &TurnContext, + step_context: &StepContext, client_session: &mut ModelClientSession, prompt: &Prompt, responses_metadata: &CodexResponsesMetadata, ) -> CodexResult { + let turn_context = step_context.turn.as_ref(); let max_retries = turn_context .provider .info() @@ -346,7 +347,7 @@ async fn run_remote_compaction_request_v2( prompt, &turn_context.model_info, &turn_context.session_telemetry, - turn_context.reasoning_effort.clone(), + step_context.reasoning_effort.clone(), turn_context.reasoning_summary, turn_context.config.service_tier.clone(), responses_metadata, diff --git a/codex-rs/core/src/compact_remote_v2_attempt.rs b/codex-rs/core/src/compact_remote_v2_attempt.rs index a145d00ae6..e21889c189 100644 --- a/codex-rs/core/src/compact_remote_v2_attempt.rs +++ b/codex-rs/core/src/compact_remote_v2_attempt.rs @@ -101,7 +101,7 @@ pub(super) async fn run_remote_compact_v2_attempt( }; let compaction_output_result = run_remote_compaction_request_v2( sess, - turn_context.as_ref(), + step_context.as_ref(), client_session, &prompt, &responses_metadata, diff --git a/codex-rs/core/src/guardian/review.rs b/codex-rs/core/src/guardian/review.rs index 4756cc1fc4..2e93194fde 100644 --- a/codex-rs/core/src/guardian/review.rs +++ b/codex-rs/core/src/guardian/review.rs @@ -722,7 +722,8 @@ pub(super) async fn guardian_review_session_config( .supported_reasoning_levels .iter() .any(|preset| preset.effort == codex_protocol::openai_models::ReasoningEffort::Low), - turn.reasoning_effort + turn.config + .model_reasoning_effort .clone() .or_else(|| turn.model_info.default_reasoning_level.clone()), ); diff --git a/codex-rs/core/src/guardian/review_session.rs b/codex-rs/core/src/guardian/review_session.rs index 05ef58b4dd..4662990c5b 100644 --- a/codex-rs/core/src/guardian/review_session.rs +++ b/codex-rs/core/src/guardian/review_session.rs @@ -1204,7 +1204,7 @@ mod tests { async fn test_review_params() -> GuardianReviewSessionParams { let (session, turn) = crate::session::tests::make_session_and_context().await; let model = turn.model_info.slug.clone(); - let reasoning_effort = turn.reasoning_effort.clone(); + let reasoning_effort = turn.config.model_reasoning_effort.clone(); let reasoning_summary = turn.reasoning_summary; let personality = turn.personality; #[allow(deprecated)] diff --git a/codex-rs/core/src/mcp_tool_call.rs b/codex-rs/core/src/mcp_tool_call.rs index 63d21504b9..1926a1b896 100644 --- a/codex-rs/core/src/mcp_tool_call.rs +++ b/codex-rs/core/src/mcp_tool_call.rs @@ -395,7 +395,7 @@ async fn handle_approved_mcp_tool_call( let result = async { let rewritten_arguments = rewrite?; let request_meta = - build_mcp_tool_call_request_meta(turn_context, &server, call_id, metadata); + build_mcp_tool_call_request_meta(step_context, &server, call_id, metadata); execute_mcp_tool_call( sess, step_context, @@ -1081,18 +1081,19 @@ async fn custom_mcp_tool_approval_mode( } fn build_mcp_tool_call_request_meta( - turn_context: &TurnContext, + step_context: &StepContext, server: &str, call_id: &str, metadata: Option<&McpToolApprovalMetadata>, ) -> Option { + let turn_context = step_context.turn.as_ref(); let mut request_meta = serde_json::Map::new(); if let Some(turn_metadata) = turn_context .turn_metadata_state .current_meta_value_for_mcp_request(McpTurnMetadataContext { model: turn_context.model_info.slug.as_str(), - reasoning_effort: turn_context.effective_reasoning_effort(), + reasoning_effort: step_context.effective_reasoning_effort(), }) { request_meta.insert( diff --git a/codex-rs/core/src/mcp_tool_call_tests.rs b/codex-rs/core/src/mcp_tool_call_tests.rs index 277caa482d..eb820a0307 100644 --- a/codex-rs/core/src/mcp_tool_call_tests.rs +++ b/codex-rs/core/src/mcp_tool_call_tests.rs @@ -1092,13 +1092,15 @@ fn truncate_mcp_tool_result_for_event_bounds_large_error() { #[tokio::test] async fn mcp_tool_call_request_meta_includes_turn_metadata_for_custom_server() { let (_, turn_context) = make_session_and_context().await; + let turn_context = Arc::new(turn_context); + let step_context = StepContext::for_test(Arc::clone(&turn_context)); let expected_turn_metadata = turn_context .turn_metadata_state .current_meta_value_for_mcp_request(mcp_turn_metadata_context(&turn_context)) .expect("turn metadata"); let meta = build_mcp_tool_call_request_meta( - &turn_context, + &step_context, "custom_server", "call-custom", /*metadata*/ None, @@ -1118,7 +1120,7 @@ async fn mcp_tool_call_request_meta_includes_turn_metadata_for_custom_server() { turn_metadata .get("reasoning_effort") .and_then(serde_json::Value::as_str), - turn_context + step_context .effective_reasoning_effort() .map(|effort| effort.to_string()) .as_deref() @@ -1135,12 +1137,14 @@ async fn mcp_tool_call_request_meta_includes_turn_metadata_for_custom_server() { #[tokio::test] async fn mcp_tool_call_request_meta_includes_turn_started_at_unix_ms() { let (_, turn_context) = make_session_and_context().await; + let turn_context = Arc::new(turn_context); + let step_context = StepContext::for_test(Arc::clone(&turn_context)); turn_context .turn_metadata_state .set_turn_started_at_unix_ms(/*turn_started_at_unix_ms*/ 1_700_000_000_123); let meta = build_mcp_tool_call_request_meta( - &turn_context, + &step_context, "custom_server", "call-custom", /*metadata*/ None, @@ -1196,6 +1200,8 @@ async fn mcp_sandbox_cwd_is_none_for_unselected_server_environment() -> anyhow:: #[tokio::test] async fn plugin_mcp_tool_call_request_meta_includes_plugin_id() { let (_, turn_context) = make_session_and_context().await; + let turn_context = Arc::new(turn_context); + let step_context = StepContext::for_test(Arc::clone(&turn_context)); let expected_turn_metadata = turn_context .turn_metadata_state .current_meta_value_for_mcp_request(mcp_turn_metadata_context(&turn_context)) @@ -1208,7 +1214,7 @@ async fn plugin_mcp_tool_call_request_meta_includes_plugin_id() { metadata.plugin_id = Some("sample@test".to_string()); assert_eq!( - build_mcp_tool_call_request_meta(&turn_context, "sample", "call-plugin", Some(&metadata),), + build_mcp_tool_call_request_meta(&step_context, "sample", "call-plugin", Some(&metadata),), Some(serde_json::json!({ crate::X_CODEX_TURN_METADATA_HEADER: expected_turn_metadata, MCP_TOOL_PLUGIN_ID_META_KEY: "sample@test", @@ -1315,6 +1321,8 @@ async fn mcp_tool_call_item_includes_app_identity() { #[tokio::test] async fn codex_apps_tool_call_request_meta_includes_turn_metadata_and_codex_apps_meta() { let (_, turn_context) = make_session_and_context().await; + let turn_context = Arc::new(turn_context); + let step_context = StepContext::for_test(Arc::clone(&turn_context)); let expected_turn_metadata = turn_context .turn_metadata_state .current_meta_value_for_mcp_request(mcp_turn_metadata_context(&turn_context)) @@ -1346,7 +1354,7 @@ async fn codex_apps_tool_call_request_meta_includes_turn_metadata_and_codex_apps assert_eq!( build_mcp_tool_call_request_meta( - &turn_context, + &step_context, CODEX_APPS_MCP_SERVER_NAME, "call_abc123xyz789", Some(&metadata), @@ -1366,6 +1374,8 @@ async fn codex_apps_tool_call_request_meta_includes_turn_metadata_and_codex_apps #[tokio::test] async fn codex_apps_tool_call_request_meta_includes_call_id_without_existing_codex_apps_meta() { let (_, turn_context) = make_session_and_context().await; + let turn_context = Arc::new(turn_context); + let step_context = StepContext::for_test(Arc::clone(&turn_context)); let expected_turn_metadata = turn_context .turn_metadata_state .current_meta_value_for_mcp_request(mcp_turn_metadata_context(&turn_context)) @@ -1373,7 +1383,7 @@ async fn codex_apps_tool_call_request_meta_includes_call_id_without_existing_cod assert_eq!( build_mcp_tool_call_request_meta( - &turn_context, + &step_context, CODEX_APPS_MCP_SERVER_NAME, "call_abc123xyz789", /*metadata*/ None, diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs index 1efdc44189..e0eb2ec756 100644 --- a/codex-rs/core/src/session/mod.rs +++ b/codex-rs/core/src/session/mod.rs @@ -2894,8 +2894,10 @@ impl Session { &selected_capability_roots, ) .await; + let reasoning_effort = turn_context.config.model_reasoning_effort.clone(); Arc::new(StepContext::new( turn_context, + reasoning_effort, environments, selected_capability_roots, mcp, diff --git a/codex-rs/core/src/session/review.rs b/codex-rs/core/src/session/review.rs index 33de46ede0..55aaccba64 100644 --- a/codex-rs/core/src/session/review.rs +++ b/codex-rs/core/src/session/review.rs @@ -70,7 +70,6 @@ pub(super) async fn spawn_review_thread( let auth_manager_for_context = auth_manager.clone(); let provider_for_context = provider.clone(); let session_telemetry_for_context = session_telemetry.clone(); - let reasoning_effort = per_turn_config.model_reasoning_effort.clone(); let reasoning_summary = per_turn_config .model_reasoning_summary .unwrap_or(model_info.default_reasoning_summary); @@ -114,7 +113,6 @@ pub(super) async fn spawn_review_thread( model_info: model_info.clone(), session_telemetry: session_telemetry_for_context, provider: provider_for_context, - reasoning_effort, reasoning_summary, session_source, parent_thread_id: parent_turn_context.parent_thread_id, diff --git a/codex-rs/core/src/session/rollout_reconstruction_tests.rs b/codex-rs/core/src/session/rollout_reconstruction_tests.rs index a7d2a7efc1..b72d19b679 100644 --- a/codex-rs/core/src/session/rollout_reconstruction_tests.rs +++ b/codex-rs/core/src/session/rollout_reconstruction_tests.rs @@ -183,7 +183,7 @@ async fn record_initial_history_resumed_bare_turn_context_does_not_hydrate_previ multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let rollout_items = vec![RolloutItem::TurnContext(previous_context_item)]; @@ -229,7 +229,7 @@ async fn record_initial_history_resumed_hydrates_previous_turn_settings_from_lif multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let turn_id = previous_context_item @@ -1263,7 +1263,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let previous_turn_id = previous_context_item @@ -1349,7 +1349,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, })) .expect("serialize expected reference context item") @@ -1380,7 +1380,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let previous_turn_id = previous_context_item @@ -1506,7 +1506,7 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, }; @@ -1627,7 +1627,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let previous_turn_id = previous_context_item @@ -1794,7 +1794,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let previous_turn_id = previous_context_item diff --git a/codex-rs/core/src/session/step_context.rs b/codex-rs/core/src/session/step_context.rs index 1d7316d914..14caa2ea43 100644 --- a/codex-rs/core/src/session/step_context.rs +++ b/codex-rs/core/src/session/step_context.rs @@ -6,12 +6,14 @@ use crate::session::McpRuntimeSnapshot; use crate::session::turn_context::TurnContext; use codex_exec_server::ResolvedSelectedCapabilityRoot; use codex_mcp::ToolInfo; +use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig; use tokio::sync::OnceCell; /// Request-scoped state that may change between model sampling requests. #[derive(Debug)] pub(crate) struct StepContext { pub(crate) turn: Arc, + pub(crate) reasoning_effort: Option, pub(crate) environments: TurnEnvironmentSnapshot, /// Capability roots bound to ready environments in this exact step. pub(crate) selected_capability_roots: Vec, @@ -26,6 +28,7 @@ pub(crate) struct StepContext { impl StepContext { pub(crate) fn new( turn: Arc, + reasoning_effort: Option, environments: TurnEnvironmentSnapshot, selected_capability_roots: Vec, mcp: Arc, @@ -33,6 +36,7 @@ impl StepContext { ) -> Self { Self { turn, + reasoning_effort, environments, selected_capability_roots, mcp, @@ -46,4 +50,20 @@ impl StepContext { .get_or_init(|| self.mcp.manager().list_all_tools()) .await } + + pub(crate) fn effective_reasoning_effort(&self) -> Option { + if self.turn.model_info.supports_reasoning_summaries { + self.reasoning_effort + .clone() + .or_else(|| self.turn.model_info.default_reasoning_level.clone()) + } else { + None + } + } + + pub(crate) fn effective_reasoning_effort_for_tracing(&self) -> String { + self.effective_reasoning_effort() + .map(|effort| effort.to_string()) + .unwrap_or_else(|| "default".to_string()) + } } diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 7274d583e8..2495ccdb1b 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -196,6 +196,7 @@ impl StepContext { let environments = turn.environments.clone(); Arc::new(Self::new( Arc::clone(&turn), + turn.config.model_reasoning_effort.clone(), environments, Vec::new(), crate::session::McpRuntimeSnapshot::new_uninitialized_for_test(&turn.config), @@ -3093,7 +3094,7 @@ async fn record_initial_history_forked_hydrates_previous_turn_settings() { multi_agent_version: None, multi_agent_mode: None, realtime_active: Some(turn_context.realtime_active), - effort: turn_context.reasoning_effort.clone(), + effort: turn_context.config.model_reasoning_effort.clone(), summary: codex_protocol::config_types::ReasoningSummary::Auto, }; let turn_id = previous_context_item @@ -3969,7 +3970,8 @@ async fn includes_timed_out_message() { #[tokio::test] async fn turn_context_with_model_updates_model_fields() { let (session, mut turn_context) = make_session_and_context().await; - turn_context.reasoning_effort = Some(ReasoningEffortConfig::Minimal); + Arc::make_mut(&mut turn_context.config).model_reasoning_effort = + Some(ReasoningEffortConfig::Minimal); let updated = turn_context .with_model("gpt-5.4".to_string(), &session.services.models_manager) .await; @@ -3985,10 +3987,6 @@ async fn turn_context_with_model_updates_model_fields() { assert_eq!(updated.config.model.as_deref(), Some("gpt-5.4")); assert_eq!(updated.collaboration_mode.model(), "gpt-5.4"); assert_eq!(updated.model_info, expected_model_info); - assert_eq!( - updated.reasoning_effort, - Some(ReasoningEffortConfig::Medium) - ); assert_eq!( updated.collaboration_mode.reasoning_effort(), Some(ReasoningEffortConfig::Medium) diff --git a/codex-rs/core/src/session/turn.rs b/codex-rs/core/src/session/turn.rs index 41098b2c1e..f2f0174d86 100644 --- a/codex-rs/core/src/session/turn.rs +++ b/codex-rs/core/src/session/turn.rs @@ -777,7 +777,7 @@ async fn track_turn_resolved_config_analytics( permission_profile: turn_context.permission_profile(), #[allow(deprecated)] permission_profile_cwd: turn_context.cwd.to_path_buf(), - reasoning_effort: turn_context.reasoning_effort.clone(), + reasoning_effort: turn_context.config.model_reasoning_effort.clone(), reasoning_summary: Some(turn_context.reasoning_summary), service_tier: turn_context .config @@ -1157,7 +1157,7 @@ async fn run_sampling_request( let err = match try_run_sampling_request( tool_runtime.clone(), Arc::clone(&sess), - Arc::clone(&turn_context), + Arc::clone(&step_context), Arc::clone(&turn_store), client_session, responses_metadata, @@ -1920,14 +1920,14 @@ async fn drain_in_flight( #[instrument(level = "trace", skip_all, fields( - turn_id = %turn_context.sub_id, - model = %turn_context.model_info.slug + turn_id = %step_context.turn.sub_id, + model = %step_context.turn.model_info.slug ) )] async fn try_run_sampling_request( tool_runtime: ToolCallRuntime, sess: Arc, - turn_context: Arc, + step_context: Arc, turn_store: Arc, client_session: &mut ModelClientSession, responses_metadata: &CodexResponsesMetadata, @@ -1935,11 +1935,12 @@ async fn try_run_sampling_request( prompt: &Prompt, cancellation_token: CancellationToken, ) -> CodexResult { + let turn_context = &step_context.turn; feedback_tags!( model = turn_context.model_info.slug.clone(), approval_policy = turn_context.approval_policy.value(), sandbox_policy = &turn_context.sandbox_policy(), - effort = turn_context.reasoning_effort, + effort = step_context.reasoning_effort, auth_mode = sess.services.auth_manager.auth_mode(), features = sess.features.enabled_features(), ); @@ -1959,7 +1960,7 @@ async fn try_run_sampling_request( prompt, &turn_context.model_info, &turn_context.session_telemetry, - turn_context.reasoning_effort.clone(), + step_context.reasoning_effort.clone(), turn_context.reasoning_summary, turn_context.config.service_tier.clone(), responses_metadata, @@ -1979,7 +1980,7 @@ async fn try_run_sampling_request( )> = None; let mut should_emit_turn_diff = false; let mut should_emit_token_count = false; - let reasoning_effort = turn_context.effective_reasoning_effort_for_tracing(); + let reasoning_effort = step_context.effective_reasoning_effort_for_tracing(); let plan_mode = turn_context.collaboration_mode.mode == ModeKind::Plan; let mut assistant_message_stream_parsers = AssistantMessageStreamParsers::new(plan_mode); let mut plan_mode_state = plan_mode.then(|| PlanModeStreamState::new(&turn_context.sub_id)); diff --git a/codex-rs/core/src/session/turn_context.rs b/codex-rs/core/src/session/turn_context.rs index b9bf42073b..a90c3b4534 100644 --- a/codex-rs/core/src/session/turn_context.rs +++ b/codex-rs/core/src/session/turn_context.rs @@ -108,7 +108,6 @@ pub struct TurnContext { pub(crate) model_info: ModelInfo, pub(crate) session_telemetry: SessionTelemetry, pub(crate) provider: SharedModelProvider, - pub(crate) reasoning_effort: Option, pub(crate) reasoning_summary: ReasoningSummaryConfig, pub(crate) session_source: SessionSource, pub(crate) parent_thread_id: Option, @@ -171,7 +170,8 @@ impl TurnContext { pub(crate) fn effective_reasoning_effort(&self) -> Option { if self.model_info.supports_reasoning_summaries { - self.reasoning_effort + self.config + .model_reasoning_effort .clone() .or_else(|| self.model_info.default_reasoning_level.clone()) } else { @@ -220,22 +220,22 @@ impl TurnContext { .iter() .map(|preset| preset.effort.clone()) .collect::>(); - let reasoning_effort = if let Some(current_reasoning_effort) = self.reasoning_effort.clone() - { - if supported_reasoning_levels.contains(¤t_reasoning_effort) { - Some(current_reasoning_effort) + let reasoning_effort = + if let Some(current_reasoning_effort) = self.config.model_reasoning_effort.clone() { + if supported_reasoning_levels.contains(¤t_reasoning_effort) { + Some(current_reasoning_effort) + } else { + supported_reasoning_levels + .get(supported_reasoning_levels.len().saturating_sub(1) / 2) + .cloned() + .or_else(|| model_info.default_reasoning_level.clone()) + } } else { supported_reasoning_levels .get(supported_reasoning_levels.len().saturating_sub(1) / 2) .cloned() .or_else(|| model_info.default_reasoning_level.clone()) - } - } else { - supported_reasoning_levels - .get(supported_reasoning_levels.len().saturating_sub(1) / 2) - .cloned() - .or_else(|| model_info.default_reasoning_level.clone()) - }; + }; config.model_reasoning_effort = reasoning_effort.clone(); let collaboration_mode = self.collaboration_mode.with_updates( @@ -259,7 +259,6 @@ impl TurnContext { .clone() .with_model(model.as_str(), model_info.slug.as_str()), provider: self.provider.clone(), - reasoning_effort, reasoning_summary: self.reasoning_summary, session_source: self.session_source.clone(), parent_thread_id: self.parent_thread_id, @@ -372,7 +371,7 @@ impl TurnContext { multi_agent_version: Some(self.multi_agent_version), multi_agent_mode: super::multi_agents::effective_multi_agent_mode(self), realtime_active: Some(self.realtime_active), - effort: self.reasoning_effort.clone(), + effort: self.config.model_reasoning_effort.clone(), summary: ReasoningSummaryConfig::Auto, } } @@ -485,7 +484,6 @@ impl Session { sub_id: String, skills_snapshot: HostSkillsSnapshot, ) -> TurnContext { - let reasoning_effort = session_configuration.collaboration_mode.reasoning_effort(); let reasoning_summary = session_configuration .model_reasoning_summary .unwrap_or(model_info.default_reasoning_summary); @@ -537,7 +535,6 @@ impl Session { model_info, session_telemetry: session_telemetry_for_context, provider: provider_for_context, - reasoning_effort, reasoning_summary, session_source, parent_thread_id: session_configuration.parent_thread_id, diff --git a/codex-rs/core/src/session_startup_prewarm.rs b/codex-rs/core/src/session_startup_prewarm.rs index a5a4c5e437..5c69a0e600 100644 --- a/codex-rs/core/src/session_startup_prewarm.rs +++ b/codex-rs/core/src/session_startup_prewarm.rs @@ -310,7 +310,7 @@ async fn schedule_startup_prewarm_inner( &startup_prompt, &startup_turn_context.model_info, &startup_turn_context.session_telemetry, - startup_turn_context.reasoning_effort.clone(), + step_context.reasoning_effort.clone(), startup_turn_context.reasoning_summary, startup_turn_context.config.service_tier.clone(), &responses_metadata, diff --git a/codex-rs/core/src/tools/handlers/multi_agents_common.rs b/codex-rs/core/src/tools/handlers/multi_agents_common.rs index 287e4b30d5..792cfd4090 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_common.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_common.rs @@ -180,7 +180,8 @@ fn build_agent_shared_config(turn: &TurnContext) -> Result