diff --git a/codex-rs/app-server/tests/suite/v2/turn_start.rs b/codex-rs/app-server/tests/suite/v2/turn_start.rs index 7c409855d4..8cd139c2de 100644 --- a/codex-rs/app-server/tests/suite/v2/turn_start.rs +++ b/codex-rs/app-server/tests/suite/v2/turn_start.rs @@ -2024,11 +2024,11 @@ async fn turn_start_model_surface_gates_multi_environment_process_tools() -> Res assert!(body_contains(multi_request, "")); assert!(body_contains( multi_request, - r#""# + r#""# )); assert!(body_contains( multi_request, - r#""# + r#""# )); assert!(body_contains(multi_request, "environment_id")); diff --git a/codex-rs/core/src/context/environment_context.rs b/codex-rs/core/src/context/environment_context.rs index e5d45425a3..3ff1992f4b 100644 --- a/codex-rs/core/src/context/environment_context.rs +++ b/codex-rs/core/src/context/environment_context.rs @@ -21,7 +21,7 @@ pub(crate) struct EnvironmentContext { pub(crate) struct EnvironmentContextEnvironment { pub(crate) id: String, pub(crate) cwd: PathBuf, - pub(crate) primary: bool, + pub(crate) default: bool, } impl EnvironmentContextEnvironment { @@ -34,7 +34,7 @@ impl EnvironmentContextEnvironment { .map(|(index, environment)| Self { id: environment.environment_id.clone(), cwd: environment.cwd.to_path_buf(), - primary: index == 0, + default: index == 0, }) .collect() } @@ -48,7 +48,7 @@ impl EnvironmentContextEnvironment { .map(|(index, environment)| Self { id: environment.environment_id.clone(), cwd: environment.cwd.to_path_buf(), - primary: index == 0, + default: index == 0, }) .collect() } @@ -146,10 +146,17 @@ impl EnvironmentContext { } pub(crate) fn from_turn_context(turn_context: &TurnContext, shell: &Shell) -> Self { + let environments = + EnvironmentContextEnvironment::from_turn_environments(&turn_context.environments); + let environments = if environments.len() > 1 { + environments + } else { + Vec::new() + }; Self::new( Some(turn_context.cwd.to_path_buf()), shell.name().to_string(), - EnvironmentContextEnvironment::from_turn_environments(&turn_context.environments), + environments, turn_context.current_date.clone(), turn_context.timezone.clone(), Self::network_from_turn_context(turn_context), @@ -239,8 +246,8 @@ impl ContextualUserFragment for EnvironmentContext { lines.push(" ".to_string()); for environment in &self.environments { lines.push(format!( - " ", - environment.id, environment.primary + " ", + environment.id, environment.default )); lines.push(format!( " {}", diff --git a/codex-rs/core/src/context/environment_context_tests.rs b/codex-rs/core/src/context/environment_context_tests.rs index 2913fb2ecf..6e98ecc4d9 100644 --- a/codex-rs/core/src/context/environment_context_tests.rs +++ b/codex-rs/core/src/context/environment_context_tests.rs @@ -210,22 +210,22 @@ fn serialize_environment_context_with_multiple_selected_environments() { EnvironmentContextEnvironment { id: "local".to_string(), cwd: test_path_buf("/primary"), - primary: true, + default: true, }, EnvironmentContextEnvironment { id: "remote".to_string(), cwd: test_path_buf("/remote/repo"), - primary: false, + default: false, }, ]; let expected = format!( r#" - + {} - + {} diff --git a/codex-rs/core/src/environment_selection.rs b/codex-rs/core/src/environment_selection.rs index 06f2dcba01..606556bdea 100644 --- a/codex-rs/core/src/environment_selection.rs +++ b/codex-rs/core/src/environment_selection.rs @@ -174,4 +174,15 @@ mod tests { "local" ); } + + #[tokio::test] + async fn resolved_environment_selections_use_fallback_without_selections() { + let cwd = AbsolutePathBuf::current_dir().expect("cwd"); + let manager = EnvironmentManager::default_for_tests(); + + let resolved = + resolve_environment_selections(&manager, &[]).expect("empty selections are valid"); + + assert_eq!(resolved.primary_cwd_or_fallback(&cwd), cwd); + } } diff --git a/codex-rs/core/src/session/turn_context.rs b/codex-rs/core/src/session/turn_context.rs index cc74b9f56b..cb7c1f877c 100644 --- a/codex-rs/core/src/session/turn_context.rs +++ b/codex-rs/core/src/session/turn_context.rs @@ -105,10 +105,6 @@ impl TurnContext { self.permission_profile.network_sandbox_policy() } - pub(crate) fn primary_environment(&self) -> Option<&TurnEnvironment> { - self.environments.first() - } - pub(crate) fn sandbox_policy(&self) -> SandboxPolicy { let file_system_sandbox_policy = self.file_system_sandbox_policy(); let network_sandbox_policy = self.network_sandbox_policy(); diff --git a/codex-rs/core/src/tools/handlers/mod.rs b/codex-rs/core/src/tools/handlers/mod.rs index 4afd48f78a..6890b1a526 100644 --- a/codex-rs/core/src/tools/handlers/mod.rs +++ b/codex-rs/core/src/tools/handlers/mod.rs @@ -109,11 +109,10 @@ pub(crate) fn resolve_process_tool_environment( ) -> Result, FunctionCallError> { if environment_id.is_none() && !turn.has_multiple_selected_environments() { return Ok(turn - .environment - .as_ref() + .primary_environment() .map(|environment| ProcessToolEnvironment { - environment: Arc::clone(environment), - cwd: turn.cwd.clone(), + environment: Arc::clone(&environment.environment), + cwd: environment.cwd.clone(), })); } 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 8ea9bfc913..4947281141 100644 --- a/codex-rs/core/src/unified_exec/process_manager_tests.rs +++ b/codex-rs/core/src/unified_exec/process_manager_tests.rs @@ -176,7 +176,12 @@ async fn failed_initial_end_for_unstored_process_uses_fallback_output() { yield_time_ms: 1000, max_output_tokens: None, workdir: None, - environment: turn.environment.as_ref().expect("turn environment").clone(), + environment: Arc::clone( + &turn + .primary_environment() + .expect("turn environment") + .environment, + ), network: None, tty: true, sandbox_permissions: crate::sandboxing::SandboxPermissions::UseDefault, diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 0947f4fba7..4f5624859d 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -44,6 +44,7 @@ use codex_protocol::protocol::McpToolCallBeginEvent; use codex_protocol::protocol::Op; use codex_protocol::user_input::UserInput; use codex_utils_cargo_bin::cargo_bin; +use core_test_support::PathBufExt; use core_test_support::assert_regex_match; use core_test_support::remote_env_env_var; use core_test_support::responses;