diff --git a/codex-rs/core/src/codex_delegate.rs b/codex-rs/core/src/codex_delegate.rs index 7733012007..969a6298ff 100644 --- a/codex-rs/core/src/codex_delegate.rs +++ b/codex-rs/core/src/codex_delegate.rs @@ -111,7 +111,7 @@ pub(crate) async fn run_codex_thread_interactive( } else { Arc::clone(&parent_session.services.extensions) }; - let (session, io) = Box::pin(Session::spawn(SessionSpawnArgs { + let (session, io) = Session::spawn(SessionSpawnArgs { config, allow_provider_model_fallback: false, user_instructions, @@ -158,7 +158,7 @@ pub(crate) async fn run_codex_thread_interactive( inherited_multi_agent_version: Some(MultiAgentVersion::Disabled), git_enrichment_policy, windows_sandbox_proxy_settings_mode, - })) + }) .or_cancel(&cancel_token) .await??; let thread_config = session.thread_config_snapshot().await; diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs index ea0651cc02..c99599b7d6 100644 --- a/codex-rs/core/src/session/mod.rs +++ b/codex-rs/core/src/session/mod.rs @@ -478,28 +478,34 @@ const CYBER_SAFETY_URL: &str = "https://developers.openai.com/codex/concepts/cyb impl Session { /// Spawn and initialize a new session. - pub(crate) async fn spawn(args: SessionSpawnArgs) -> CodexResult<(Arc, SessionIo)> { - let parent_trace = match args.parent_trace { - Some(trace) => { - if codex_otel::context_from_w3c_trace_context(&trace).is_some() { - Some(trace) - } else { - warn!("ignoring invalid thread spawn trace carrier"); - None + /// Hide the concrete startup future from callers while keeping initialization lazy. + #[inline(never)] + pub(crate) fn spawn( + args: SessionSpawnArgs, + ) -> BoxFuture<'static, CodexResult<(Arc, SessionIo)>> { + Box::pin(async move { + let parent_trace = match args.parent_trace { + Some(trace) => { + if codex_otel::context_from_w3c_trace_context(&trace).is_some() { + Some(trace) + } else { + warn!("ignoring invalid thread spawn trace carrier"); + None + } } + None => None, + }; + let thread_spawn_span = info_span!("thread_spawn", otel.name = "thread_spawn"); + if let Some(trace) = parent_trace.as_ref() { + let _ = set_parent_from_w3c_trace_context(&thread_spawn_span, trace); } - None => None, - }; - let thread_spawn_span = info_span!("thread_spawn", otel.name = "thread_spawn"); - if let Some(trace) = parent_trace.as_ref() { - let _ = set_parent_from_w3c_trace_context(&thread_spawn_span, trace); - } - Self::spawn_internal(SessionSpawnArgs { - parent_trace, - ..args + Self::spawn_internal(SessionSpawnArgs { + parent_trace, + ..args + }) + .instrument(thread_spawn_span) + .await }) - .instrument(thread_spawn_span) - .await } async fn spawn_internal(args: SessionSpawnArgs) -> CodexResult<(Arc, SessionIo)> { diff --git a/codex-rs/core/src/thread_manager.rs b/codex-rs/core/src/thread_manager.rs index 90fe9e06f7..7f6648bcb8 100644 --- a/codex-rs/core/src/thread_manager.rs +++ b/codex-rs/core/src/thread_manager.rs @@ -1987,7 +1987,7 @@ impl ThreadManagerState { } else { codex_sandboxing::WindowsSandboxProxySettingsMode::Reconcile }; - let (session, io) = Box::pin(Session::spawn(SessionSpawnArgs { + let (session, io) = Session::spawn(SessionSpawnArgs { config, allow_provider_model_fallback, user_instructions, @@ -2027,7 +2027,7 @@ impl ThreadManagerState { inherited_multi_agent_version: multi_agent_version, git_enrichment_policy: GitEnrichmentPolicy::Fresh, windows_sandbox_proxy_settings_mode, - })) + }) .await?; // Enable Full Access form input only after session startup so a required MCP server cannot // block startup while waiting for form input.