diff --git a/codex-rs/core/src/unified_exec/mod.rs b/codex-rs/core/src/unified_exec/mod.rs index 65b18b064..c14d063e9 100644 --- a/codex-rs/core/src/unified_exec/mod.rs +++ b/codex-rs/core/src/unified_exec/mod.rs @@ -62,6 +62,7 @@ pub(crate) use process::SpawnLifecycleHandle; pub(crate) use process::UnifiedExecProcess; pub(crate) const MIN_YIELD_TIME_MS: u64 = 250; +pub(crate) const WINDOWS_INITIAL_EXEC_YIELD_TIME_FLOOR_MS: u64 = 2_000; // Minimum yield time for an empty `write_stdin`. pub(crate) const MIN_EMPTY_YIELD_TIME_MS: u64 = 5_000; pub(crate) const MAX_YIELD_TIME_MS: u64 = 30_000; @@ -165,6 +166,11 @@ struct ProcessEntry { } pub(crate) fn clamp_yield_time(yield_time_ms: u64) -> u64 { + let yield_time_ms = if cfg!(windows) { + yield_time_ms.max(WINDOWS_INITIAL_EXEC_YIELD_TIME_FLOOR_MS) + } else { + yield_time_ms + }; yield_time_ms.clamp(MIN_YIELD_TIME_MS, MAX_YIELD_TIME_MS) } diff --git a/codex-rs/core/src/unified_exec/process_manager_tests.rs b/codex-rs/core/src/unified_exec/process_manager_tests.rs index d9b3a771b..a84f6345e 100644 --- a/codex-rs/core/src/unified_exec/process_manager_tests.rs +++ b/codex-rs/core/src/unified_exec/process_manager_tests.rs @@ -1,4 +1,5 @@ use super::*; +use crate::unified_exec::clamp_yield_time; use pretty_assertions::assert_eq; use tokio::time::Duration; use tokio::time::Instant; @@ -131,6 +132,32 @@ fn exec_server_process_id_matches_unified_exec_process_id() { assert_eq!(exec_server_process_id(/*process_id*/ 4321), "4321"); } +#[cfg(windows)] +#[test] +fn initial_exec_yield_time_uses_windows_floor() { + let above_max_yield_time_ms = crate::unified_exec::MAX_YIELD_TIME_MS + 1; + + assert_eq!( + clamp_yield_time(/*yield_time_ms*/ 1_000), + crate::unified_exec::WINDOWS_INITIAL_EXEC_YIELD_TIME_FLOOR_MS + ); + assert_eq!(clamp_yield_time(/*yield_time_ms*/ 10_000), 10_000); + assert_eq!( + clamp_yield_time(/*yield_time_ms*/ above_max_yield_time_ms), + crate::unified_exec::MAX_YIELD_TIME_MS + ); +} + +#[cfg(not(windows))] +#[test] +fn initial_exec_yield_time_has_no_platform_floor() { + assert_eq!(clamp_yield_time(/*yield_time_ms*/ 1_000), 1_000); + assert_eq!( + clamp_yield_time(/*yield_time_ms*/ 1), + crate::unified_exec::MIN_YIELD_TIME_MS + ); +} + #[tokio::test] async fn network_denial_fallback_message_names_sandbox_network_proxy() { let message = network_denial_message_for_session(/*session*/ None, /*deferred*/ None).await;