From 9291a123fb96ca7d11eae27bcdecec06dcbe0d14 Mon Sep 17 00:00:00 2001 From: Channing Conger Date: Tue, 28 Jul 2026 05:13:06 +0000 Subject: [PATCH] Honor disabled code mode fallback without a process host (#35721) ## Why When the code mode host feature was disabled, thread startup always selected the in-process provider, even when `disable_in_process_fallback` was set. ## What changed - Select a disabled provider when both the process host and in-process fallback are disabled. - Return a clear tool error instead of running code mode in process for that configuration. ## Testing Added an integration test covering code mode with the process host feature and in-process fallback both disabled. GitOrigin-RevId: 3ed80afc23e0a5518c0133fe337a37b1fa545ead --- codex-rs/core/src/thread_manager.rs | 18 ++++++++++++++++ codex-rs/core/tests/suite/code_mode.rs | 29 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/codex-rs/core/src/thread_manager.rs b/codex-rs/core/src/thread_manager.rs index 5c718cede6..8514f47b11 100644 --- a/codex-rs/core/src/thread_manager.rs +++ b/codex-rs/core/src/thread_manager.rs @@ -24,7 +24,9 @@ use codex_agent_graph_store::LocalAgentGraphStore; use codex_analytics::AnalyticsEventsClient; use codex_app_server_protocol::ThreadHistoryBuilder; use codex_app_server_protocol::TurnStatus; +use codex_code_mode::CodeModeSessionDelegate; use codex_code_mode::CodeModeSessionProvider; +use codex_code_mode::CodeModeSessionProviderFuture; use codex_code_mode::InProcessCodeModeSessionProvider; use codex_code_mode::ProcessOwnedCodeModeSessionProvider; use codex_core_plugins::PluginsManager; @@ -95,6 +97,20 @@ use tracing::instrument; use tracing::warn; const THREAD_CREATED_CHANNEL_CAPACITY: usize = 1024; + +struct DisabledCodeModeSessionProvider; + +impl CodeModeSessionProvider for DisabledCodeModeSessionProvider { + fn create_session<'a>( + &'a self, + _delegate: Arc, + ) -> CodeModeSessionProviderFuture<'a> { + Box::pin(async { + Err("code-mode host is disabled and in-process fallback is disabled".to_string()) + }) + } +} + /// Test-only override for enabling thread-manager behaviors used by integration /// tests. /// @@ -382,6 +398,8 @@ impl ThreadManager { } else { Arc::new(provider) } + } else if config.code_mode.disable_in_process_fallback { + Arc::new(DisabledCodeModeSessionProvider) } else { Arc::new(InProcessCodeModeSessionProvider) }; diff --git a/codex-rs/core/tests/suite/code_mode.rs b/codex-rs/core/tests/suite/code_mode.rs index 1003534324..2a9bf2b486 100644 --- a/codex-rs/core/tests/suite/code_mode.rs +++ b/codex-rs/core/tests/suite/code_mode.rs @@ -285,6 +285,35 @@ async fn missing_process_host_fails_when_in_process_fallback_is_disabled() -> Re Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn disabled_process_host_fails_when_in_process_fallback_is_disabled() -> Result<()> { + skip_if_no_network!(Ok(())); + + let server = responses::start_mock_server().await; + let builder = test_codex() + .with_model("test-gpt-5.1-codex") + .with_config(|config| { + config + .features + .enable(Feature::CodeMode) + .expect("code mode should be enabled"); + config + .features + .disable(Feature::CodeModeHost) + .expect("code-mode host should be disabled"); + config.code_mode.disable_in_process_fallback = true; + }); + let (_test, follow_up_mock) = + run_code_mode_turn_with_builder(&server, "Run code mode", "text('unreachable')", builder) + .await?; + + let (output, _) = + custom_tool_output_body_and_success(&follow_up_mock.single_request(), "call-1"); + assert!(output.contains("code-mode host is disabled and in-process fallback is disabled")); + + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn missing_process_host_error_is_bounded_when_in_process_fallback_is_disabled() -> Result<()> {