diff --git a/codex-rs/core/src/codex_delegate.rs b/codex-rs/core/src/codex_delegate.rs index 5a01384bf..493771e28 100644 --- a/codex-rs/core/src/codex_delegate.rs +++ b/codex-rs/core/src/codex_delegate.rs @@ -530,7 +530,10 @@ async fn handle_patch_approval( let guardian_decision = if routes_approval_to_guardian(parent_ctx) { let files = changes .keys() - .map(|path| parent_ctx.cwd.join(path)) + .map(|path| { + #[allow(deprecated)] + parent_ctx.cwd.join(path) + }) .collect::>(); let review_cancel = cancel_token.child_token(); let patch = changes @@ -566,6 +569,7 @@ async fn handle_patch_approval( new_guardian_review_id(), GuardianApprovalRequest::ApplyPatch { id: approval_id.clone(), + #[allow(deprecated)] cwd: parent_ctx.cwd.clone(), files, patch, @@ -739,7 +743,10 @@ async fn handle_request_permissions( reason: event.reason, permissions: event.permissions, }; - let cwd = event.cwd.unwrap_or_else(|| parent_ctx.cwd.clone()); + let cwd = event.cwd.unwrap_or_else(|| { + #[allow(deprecated)] + parent_ctx.cwd.clone() + }); let response_fut = parent_session.request_permissions_for_cwd( parent_ctx, call_id.clone(), diff --git a/codex-rs/core/src/codex_delegate_tests.rs b/codex-rs/core/src/codex_delegate_tests.rs index ecd392e3e..66cde8d1e 100644 --- a/codex-rs/core/src/codex_delegate_tests.rs +++ b/codex-rs/core/src/codex_delegate_tests.rs @@ -207,6 +207,7 @@ async fn handle_request_permissions_uses_tool_call_id_for_round_trip() { scope: PermissionGrantScope::Turn, strict_auto_review: false, }; + #[allow(deprecated)] let delegated_cwd = parent_ctx.cwd.join("delegated-cwd"); let cancel_token = CancellationToken::new(); let request_call_id = call_id.clone(); diff --git a/codex-rs/core/src/context_manager/updates.rs b/codex-rs/core/src/context_manager/updates.rs index 0cdbc0b01..d7302bbbf 100644 --- a/codex-rs/core/src/context_manager/updates.rs +++ b/codex-rs/core/src/context_manager/updates.rs @@ -61,6 +61,7 @@ fn build_permissions_update_item( next.approval_policy.value(), next.config.approvals_reviewer, exec_policy, + #[allow(deprecated)] &next.cwd, next.features.enabled(Feature::ExecPermissionApprovals), next.features.enabled(Feature::RequestPermissionsTool), diff --git a/codex-rs/core/src/guardian/review_session.rs b/codex-rs/core/src/guardian/review_session.rs index a419d7cbf..d3fae0f2e 100644 --- a/codex-rs/core/src/guardian/review_session.rs +++ b/codex-rs/core/src/guardian/review_session.rs @@ -708,6 +708,7 @@ async fn run_review_on_session( Box::pin(review_session.codex.submit(Op::UserTurn { environments: None, items: prompt_items.items, + #[allow(deprecated)] cwd: params.parent_turn.cwd.to_path_buf(), approval_policy: AskForApproval::Never, approvals_reviewer: None, @@ -1086,6 +1087,7 @@ mod tests { let reasoning_effort = turn.reasoning_effort; let reasoning_summary = turn.reasoning_summary; let personality = turn.personality; + #[allow(deprecated)] let cwd = turn.cwd.clone(); let spawn_config = build_guardian_review_session_config( turn.config.as_ref(), diff --git a/codex-rs/core/src/hook_runtime.rs b/codex-rs/core/src/hook_runtime.rs index 3d72e4a7c..78fc24833 100644 --- a/codex-rs/core/src/hook_runtime.rs +++ b/codex-rs/core/src/hook_runtime.rs @@ -116,6 +116,7 @@ pub(crate) async fn run_pending_session_start_hooks( let request = codex_hooks::SessionStartRequest { session_id: sess.session_id().into(), + #[allow(deprecated)] cwd: turn_context.cwd.clone(), transcript_path: sess.hook_transcript_path().await, model: turn_context.model_info.slug.clone(), @@ -150,6 +151,7 @@ pub(crate) async fn run_pre_tool_use_hooks( let request = PreToolUseRequest { session_id: sess.session_id().into(), turn_id: turn_context.sub_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.clone(), transcript_path: sess.hook_transcript_path().await, model: turn_context.model_info.slug.clone(), @@ -209,6 +211,7 @@ pub(crate) async fn run_permission_request_hooks( let request = PermissionRequestRequest { session_id: sess.session_id().into(), turn_id: turn_context.sub_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), transcript_path: sess.hook_transcript_path().await, model: turn_context.model_info.slug.clone(), @@ -249,6 +252,7 @@ pub(crate) async fn run_post_tool_use_hooks( let request = PostToolUseRequest { session_id: sess.session_id().into(), turn_id: turn_context.sub_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.clone(), transcript_path: sess.hook_transcript_path().await, model: turn_context.model_info.slug.clone(), @@ -276,6 +280,7 @@ pub(crate) async fn run_pre_compact_hooks( let request = codex_hooks::PreCompactRequest { session_id: sess.session_id().into(), turn_id: turn_context.sub_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.clone(), transcript_path: sess.hook_transcript_path().await, model: turn_context.model_info.slug.clone(), @@ -313,6 +318,7 @@ pub(crate) async fn run_post_compact_hooks( let request = codex_hooks::PostCompactRequest { session_id: sess.session_id().into(), turn_id: turn_context.sub_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.clone(), transcript_path: sess.hook_transcript_path().await, model: turn_context.model_info.slug.clone(), @@ -338,6 +344,7 @@ pub(crate) async fn run_user_prompt_submit_hooks( let request = UserPromptSubmitRequest { session_id: sess.session_id().into(), turn_id: turn_context.sub_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.clone(), transcript_path: sess.hook_transcript_path().await, model: turn_context.model_info.slug.clone(), diff --git a/codex-rs/core/src/mcp_openai_file.rs b/codex-rs/core/src/mcp_openai_file.rs index 0e0d4a600..ae44515c6 100644 --- a/codex-rs/core/src/mcp_openai_file.rs +++ b/codex-rs/core/src/mcp_openai_file.rs @@ -102,6 +102,7 @@ async fn build_uploaded_local_argument_value( index: Option, file_path: &str, ) -> Result { + #[allow(deprecated)] let resolved_path = turn_context.resolve_path(Some(file_path.to_string())); let Some(auth) = auth else { return Err( @@ -216,7 +217,10 @@ mod tests { tokio::fs::write(&local_path, b"hello") .await .expect("write local file"); - turn_context.cwd = AbsolutePathBuf::try_from(dir.path()).expect("absolute path"); + #[allow(deprecated)] + { + turn_context.cwd = AbsolutePathBuf::try_from(dir.path()).expect("absolute path"); + } let mut config = (*turn_context.config).clone(); config.chatgpt_base_url = format!("{}/backend-api", server.uri()); @@ -297,7 +301,10 @@ mod tests { tokio::fs::write(&local_path, b"hello") .await .expect("write local file"); - turn_context.cwd = AbsolutePathBuf::try_from(dir.path()).expect("absolute path"); + #[allow(deprecated)] + { + turn_context.cwd = AbsolutePathBuf::try_from(dir.path()).expect("absolute path"); + } let mut config = (*turn_context.config).clone(); config.chatgpt_base_url = format!("{}/backend-api", server.uri()); @@ -411,7 +418,10 @@ mod tests { tokio::fs::write(dir.path().join("two.csv"), b"two") .await .expect("write second local file"); - turn_context.cwd = AbsolutePathBuf::try_from(dir.path()).expect("absolute path"); + #[allow(deprecated)] + { + turn_context.cwd = AbsolutePathBuf::try_from(dir.path()).expect("absolute path"); + } let mut config = (*turn_context.config).clone(); config.chatgpt_base_url = format!("{}/backend-api", server.uri()); diff --git a/codex-rs/core/src/mcp_tool_call.rs b/codex-rs/core/src/mcp_tool_call.rs index 8855aae62..d1faa421d 100644 --- a/codex-rs/core/src/mcp_tool_call.rs +++ b/codex-rs/core/src/mcp_tool_call.rs @@ -732,6 +732,7 @@ async fn augment_mcp_tool_request_meta_with_sandbox_state( permission_profile: Some(turn_context.permission_profile()), sandbox_policy: turn_context.sandbox_policy(), codex_linux_sandbox_exe: turn_context.codex_linux_sandbox_exe.clone(), + #[allow(deprecated)] sandbox_cwd: turn_context.cwd.to_path_buf(), use_legacy_landlock: turn_context.features.use_legacy_landlock(), })?; diff --git a/codex-rs/core/src/mcp_tool_call_tests.rs b/codex-rs/core/src/mcp_tool_call_tests.rs index 65f897728..8b4f1ba22 100644 --- a/codex-rs/core/src/mcp_tool_call_tests.rs +++ b/codex-rs/core/src/mcp_tool_call_tests.rs @@ -1221,7 +1221,10 @@ async fn install_host_owned_codex_apps_manager(session: &Session, turn_context: turn_context.sub_id.clone(), session.get_tx_event(), turn_context.permission_profile(), - codex_mcp::McpRuntimeEnvironment::new(environment, turn_context.cwd.to_path_buf()), + codex_mcp::McpRuntimeEnvironment::new(environment, { + #[allow(deprecated)] + turn_context.cwd.to_path_buf() + }), turn_context.config.codex_home.to_path_buf(), codex_mcp::codex_apps_tools_cache_key(auth.as_ref()), /*host_owned_codex_apps_enabled*/ true, @@ -2230,7 +2233,10 @@ async fn maybe_persist_mcp_tool_approval_writes_project_config_for_project_serve .build() .await .expect("load project config"); - turn_context.cwd = config.cwd.clone(); + #[allow(deprecated)] + { + turn_context.cwd = config.cwd.clone(); + } turn_context.config = Arc::new(config); let key = McpToolApprovalKey { server: "docs".to_string(), @@ -2431,12 +2437,14 @@ async fn permission_request_hook_allows_mcp_tool_call() { .lines() .map(|line| serde_json::from_str::(line).expect("parse hook input")) .collect::>(); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); assert_eq!( inputs, vec![serde_json::json!({ "session_id": session.session_id(), "turn_id": "turn_id", - "cwd": turn_context.cwd, + "cwd": turn_cwd, "transcript_path": null, "model": turn_context.model_info.slug, "permission_mode": "default", @@ -2491,12 +2499,14 @@ async fn permission_request_hook_uses_hook_tool_name_without_metadata() { .lines() .map(|line| serde_json::from_str::(line).expect("parse hook input")) .collect::>(); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); assert_eq!( inputs, vec![serde_json::json!({ "session_id": session.session_id(), "turn_id": "turn_id", - "cwd": turn_context.cwd, + "cwd": turn_cwd, "transcript_path": null, "model": turn_context.model_info.slug, "permission_mode": "default", diff --git a/codex-rs/core/src/memory_usage.rs b/codex-rs/core/src/memory_usage.rs index bd856d5e6..b5bc6eef5 100644 --- a/codex-rs/core/src/memory_usage.rs +++ b/codex-rs/core/src/memory_usage.rs @@ -44,10 +44,9 @@ fn shell_command_for_invocation(invocation: &ToolInvocation) -> Option<(Vec Option<(Vec serde_json::from_str::(arguments) .ok() @@ -71,10 +69,9 @@ fn shell_command_for_invocation(invocation: &ToolInvocation) -> Option<(Vec None, } diff --git a/codex-rs/core/src/session/handlers.rs b/codex-rs/core/src/session/handlers.rs index ab40cb8ee..5cb37f982 100644 --- a/codex-rs/core/src/session/handlers.rs +++ b/codex-rs/core/src/session/handlers.rs @@ -699,6 +699,7 @@ pub async fn review( .await; sess.refresh_mcp_servers_if_requested(&turn_context, Some(sess.mcp_elicitation_reviewer())) .await; + #[allow(deprecated)] match resolve_review_request(review_request, &turn_context.cwd) { Ok(resolved) => { spawn_review_thread( diff --git a/codex-rs/core/src/session/mcp.rs b/codex-rs/core/src/session/mcp.rs index d32ecf2b1..fcaaa17c5 100644 --- a/codex-rs/core/src/session/mcp.rs +++ b/codex-rs/core/src/session/mcp.rs @@ -296,6 +296,7 @@ impl Session { .environment_manager .default_environment() .unwrap_or_else(|| self.services.environment_manager.local_environment()), + #[allow(deprecated)] turn_context.cwd.to_path_buf(), ), }; diff --git a/codex-rs/core/src/session/mod.rs b/codex-rs/core/src/session/mod.rs index 3ef946681..fd3f31771 100644 --- a/codex-rs/core/src/session/mod.rs +++ b/codex-rs/core/src/session/mod.rs @@ -2051,6 +2051,7 @@ impl Session { turn_context, call_id, args, + #[allow(deprecated)] turn_context.cwd.clone(), cancellation_token, ) @@ -2630,6 +2631,7 @@ impl Session { turn_context.approval_policy.value(), turn_context.config.approvals_reviewer, self.services.exec_policy.current().as_ref(), + #[allow(deprecated)] &turn_context.cwd, turn_context .features @@ -2763,6 +2765,7 @@ impl Session { contextual_user_sections.push( UserInstructions { text: user_instructions.to_string(), + #[allow(deprecated)] directory: turn_context.cwd.to_string_lossy().into_owned(), } .render(), diff --git a/codex-rs/core/src/session/review.rs b/codex-rs/core/src/session/review.rs index 083aac8c0..e84465508 100644 --- a/codex-rs/core/src/session/review.rs +++ b/codex-rs/core/src/session/review.rs @@ -107,6 +107,7 @@ pub(super) async fn spawn_review_thread( sess.thread_id().to_string(), parent_turn_context.thread_source, review_turn_id.clone(), + #[allow(deprecated)] parent_turn_context.cwd.clone(), &parent_turn_context.permission_profile, parent_turn_context.windows_sandbox_level, @@ -143,6 +144,7 @@ pub(super) async fn spawn_review_thread( network: parent_turn_context.network.clone(), windows_sandbox_level: parent_turn_context.windows_sandbox_level, shell_environment_policy: parent_turn_context.shell_environment_policy.clone(), + #[allow(deprecated)] cwd: parent_turn_context.cwd.clone(), final_output_json_schema: None, codex_self_exe: parent_turn_context.codex_self_exe.clone(), diff --git a/codex-rs/core/src/session/rollout_reconstruction_tests.rs b/codex-rs/core/src/session/rollout_reconstruction_tests.rs index 5cfcc3805..143b23d3a 100644 --- a/codex-rs/core/src/session/rollout_reconstruction_tests.rs +++ b/codex-rs/core/src/session/rollout_reconstruction_tests.rs @@ -60,6 +60,7 @@ async fn record_initial_history_resumed_bare_turn_context_does_not_hydrate_previ let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), @@ -101,6 +102,7 @@ async fn record_initial_history_resumed_hydrates_previous_turn_settings_from_lif let mut previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), @@ -911,6 +913,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), @@ -989,6 +992,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis serde_json::to_value(Some(TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), @@ -1020,6 +1024,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), @@ -1135,6 +1140,7 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo let current_context_item = TurnContextItem { turn_id: Some(current_turn_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), @@ -1249,6 +1255,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), @@ -1401,6 +1408,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 9ef67bcb8..577b2fa5e 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -2216,6 +2216,7 @@ async fn record_initial_history_forked_hydrates_previous_turn_settings() { let previous_context_item = TurnContextItem { turn_id: Some(turn_context.sub_id.clone()), trace_id: turn_context.trace_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.to_path_buf(), current_date: turn_context.current_date.clone(), timezone: turn_context.timezone.clone(), @@ -3769,6 +3770,7 @@ async fn session_configuration_apply_preserves_absolute_cwd_write_root_on_cwd_up #[tokio::test] async fn session_update_settings_does_not_rewrite_sticky_environment_cwds() { let (session, turn_context) = make_session_and_context().await; + #[allow(deprecated)] let updated_cwd = turn_context.cwd.join("project"); std::fs::create_dir_all(updated_cwd.as_path()).expect("create project dir"); @@ -3788,8 +3790,12 @@ async fn session_update_settings_does_not_rewrite_sticky_environment_cwds() { let next_turn = session.new_default_turn().await; assert_eq!(session_cwd, updated_cwd); - assert_eq!(config.cwd, turn_context.cwd); - assert_eq!(next_turn.cwd, updated_cwd); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); + #[allow(deprecated)] + let next_turn_cwd = next_turn.cwd.clone(); + assert_eq!(config.cwd, turn_cwd); + assert_eq!(next_turn_cwd, updated_cwd); assert_eq!(next_turn.config.cwd, updated_cwd); } @@ -3873,7 +3879,9 @@ async fn absolute_cwd_update_with_turn_environment_is_allowed() { .await .expect("absolute cwd with explicit environments should succeed"); - assert_eq!(turn_context.cwd, absolute_cwd); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); + assert_eq!(turn_cwd, absolute_cwd); assert_eq!(turn_context.config.cwd, absolute_cwd); assert_eq!(turn_context.environments.turn_environments.len(), 1); } @@ -4674,7 +4682,9 @@ async fn request_permissions_emits_event_when_granular_policy_allows_requests() panic!("expected request_permissions event"); }; assert_eq!(request.call_id, call_id); - assert_eq!(request.cwd, Some(turn_context.cwd.clone())); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); + assert_eq!(request.cwd, Some(turn_cwd)); session .notify_request_permissions_response(&request.call_id, expected_response.clone()) @@ -5103,7 +5113,9 @@ async fn turn_environments_set_primary_environment() { &turn_environments.turn_environments[0].environment )); assert!(!turn_context.environments.turn_environments.is_empty()); - assert_eq!(turn_context.cwd.as_path(), selected_cwd.as_path()); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); + assert_eq!(turn_cwd.as_path(), selected_cwd.as_path()); assert_eq!(turn_context.config.cwd.as_path(), selected_cwd.as_path()); } @@ -5134,7 +5146,9 @@ async fn default_turn_overlays_session_cwd_onto_stored_thread_environments() { &turn_environment.environment, &turn_environments.turn_environments[0].environment )); - assert_eq!(turn_context.cwd, session_cwd); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); + assert_eq!(turn_cwd, session_cwd); assert_eq!(turn_context.config.cwd, session_cwd); } @@ -5152,7 +5166,9 @@ async fn default_turn_honors_empty_stored_thread_environments() { assert!(turn_context.environments.primary().is_none()); assert!(turn_context.environments.turn_environments.is_empty()); - assert_eq!(turn_context.cwd, session_cwd); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); + assert_eq!(turn_cwd, session_cwd); assert_eq!(turn_context.config.cwd, session_cwd); assert_eq!(turn_context.environments.turn_environments.len(), 0); } @@ -5161,6 +5177,7 @@ async fn default_turn_honors_empty_stored_thread_environments() { async fn primary_environment_uses_first_turn_environment() { let (_session, mut turn_context) = make_session_and_context().await; let first_environment = turn_context.environments.turn_environments[0].clone(); + #[allow(deprecated)] let second_cwd = turn_context.cwd.join("second"); turn_context .environments @@ -5214,7 +5231,9 @@ async fn empty_turn_environments_clear_primary_environment() { assert!(turn_context.environments.primary().is_none()); assert!(turn_context.environments.turn_environments.is_empty()); - assert_eq!(turn_context.cwd, session.get_config().await.cwd); + #[allow(deprecated)] + let turn_cwd = turn_context.cwd.clone(); + assert_eq!(turn_cwd, session.get_config().await.cwd); assert_eq!(turn_context.config.cwd, session.get_config().await.cwd); } @@ -7033,13 +7052,16 @@ async fn build_initial_context_restates_realtime_start_when_reference_context_is } fn file_system_policy_with_unreadable_glob(turn_context: &TurnContext) -> FileSystemSandboxPolicy { + #[allow(deprecated)] let mut policy = FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd( &turn_context.sandbox_policy(), &turn_context.cwd, ); + #[allow(deprecated)] + let cwd_display = turn_context.cwd.as_path().display().to_string(); policy.entries.push(FileSystemSandboxEntry { path: FileSystemPath::GlobPattern { - pattern: format!("{}/**/*.env", turn_context.cwd.as_path().display()), + pattern: format!("{cwd_display}/**/*.env"), }, access: FileSystemAccessMode::None, }); @@ -9381,6 +9403,8 @@ async fn rejects_escalated_permissions_when_policy_not_on_request() { let call_id = "test-call".to_string(); let handler = ShellCommandHandler::from(ShellCommandBackendConfig::Classic); + #[allow(deprecated)] + let workdir = Some(turn_context.cwd.to_string_lossy().to_string()); let resp = handler .handle(ToolInvocation { session: Arc::clone(&session), @@ -9393,7 +9417,7 @@ async fn rejects_escalated_permissions_when_policy_not_on_request() { payload: ToolPayload::Function { arguments: serde_json::json!({ "command": command_script, - "workdir": Some(turn_context.cwd.to_string_lossy().to_string()), + "workdir": workdir, "timeout_ms": timeout_ms, "sandbox_permissions": sandbox_permissions, "justification": Some("test"), @@ -9433,6 +9457,7 @@ async fn rejects_escalated_permissions_when_policy_not_on_request() { approval_policy: turn_context.approval_policy.value(), permission_profile: turn_context.permission_profile(), file_system_sandbox_policy: &file_system_sandbox_policy, + #[allow(deprecated)] sandbox_cwd: turn_context.cwd.as_path(), sandbox_permissions: SandboxPermissions::UseDefault, prefix_rule: None, diff --git a/codex-rs/core/src/session/tests/guardian_tests.rs b/codex-rs/core/src/session/tests/guardian_tests.rs index ffb0d94d8..718b9bf05 100644 --- a/codex-rs/core/src/session/tests/guardian_tests.rs +++ b/codex-rs/core/src/session/tests/guardian_tests.rs @@ -291,6 +291,8 @@ async fn guardian_allows_shell_command_additional_permissions_requests_past_poli let handler = crate::tools::handlers::ShellCommandHandler::from( codex_tools::ShellCommandBackendConfig::Classic, ); + #[allow(deprecated)] + let workdir = Some(turn_context.cwd.to_string_lossy().to_string()); let resp = handler .handle(ToolInvocation { session: Arc::clone(&session), @@ -304,7 +306,7 @@ async fn guardian_allows_shell_command_additional_permissions_requests_past_poli arguments: serde_json::json!({ "command": "echo hi", "login": false, - "workdir": Some(turn_context.cwd.to_string_lossy().to_string()), + "workdir": workdir, "timeout_ms": expiration_ms, "sandbox_permissions": SandboxPermissions::WithAdditionalPermissions, "additional_permissions": PermissionProfile { @@ -392,6 +394,8 @@ async fn strict_auto_review_turn_grant_forces_guardian_for_shell_command_policy_ let handler = crate::tools::handlers::ShellCommandHandler::from( codex_tools::ShellCommandBackendConfig::Classic, ); + #[allow(deprecated)] + let workdir = Some(turn_context.cwd.to_string_lossy().to_string()); let resp = handler .handle(ToolInvocation { session: Arc::clone(&session), @@ -405,7 +409,7 @@ async fn strict_auto_review_turn_grant_forces_guardian_for_shell_command_policy_ arguments: serde_json::json!({ "command": "echo hi", "login": false, - "workdir": Some(turn_context.cwd.to_string_lossy().to_string()), + "workdir": workdir, "timeout_ms": 1_000_u64, }) .to_string(), @@ -558,6 +562,8 @@ async fn shell_command_allows_sticky_turn_permissions_without_inline_request_per let handler = crate::tools::handlers::ShellCommandHandler::from( codex_tools::ShellCommandBackendConfig::Classic, ); + #[allow(deprecated)] + let workdir = Some(turn_context.cwd.to_string_lossy().to_string()); let resp = handler .handle(ToolInvocation { session: Arc::clone(&session), @@ -572,7 +578,7 @@ async fn shell_command_allows_sticky_turn_permissions_without_inline_request_per "command": "echo hi", "login": false, "timeout_ms": 1_000_u64, - "workdir": Some(turn_context.cwd.to_string_lossy().to_string()), + "workdir": workdir, }) .to_string(), }, diff --git a/codex-rs/core/src/session/turn.rs b/codex-rs/core/src/session/turn.rs index 2dd84213e..d910e03b2 100644 --- a/codex-rs/core/src/session/turn.rs +++ b/codex-rs/core/src/session/turn.rs @@ -366,6 +366,7 @@ pub(crate) async fn run_turn( let mut stop_hook_active = false; // Although from the perspective of codex.rs, TurnDiffTracker has the lifecycle of a Task which contains // many turns, from the perspective of the user, it is a single turn. + #[allow(deprecated)] let display_root = get_git_repo_root(turn_context.cwd.as_path()) .unwrap_or_else(|| turn_context.cwd.clone().into_path_buf()); let turn_diff_tracker = Arc::new(tokio::sync::Mutex::new(TurnDiffTracker::with_display_root( @@ -524,6 +525,7 @@ pub(crate) async fn run_turn( let stop_request = codex_hooks::StopRequest { session_id: sess.session_id().into(), turn_id: turn_context.sub_id.clone(), + #[allow(deprecated)] cwd: turn_context.cwd.clone(), transcript_path: sess.hook_transcript_path().await, model: turn_context.model_info.slug.clone(), @@ -573,6 +575,7 @@ pub(crate) async fn run_turn( .hooks() .dispatch(HookPayload { session_id: sess.session_id().into(), + #[allow(deprecated)] cwd: turn_context.cwd.clone(), client: turn_context.app_server_client_name.clone(), triggered_at: chrono::Utc::now(), @@ -697,6 +700,7 @@ async fn track_turn_resolved_config_analytics( model: turn_context.model_info.slug.clone(), model_provider: turn_context.config.model_provider_id.clone(), permission_profile: turn_context.permission_profile(), + #[allow(deprecated)] permission_profile_cwd: turn_context.cwd.to_path_buf(), reasoning_effort: turn_context.reasoning_effort, reasoning_summary: Some(turn_context.reasoning_summary), @@ -993,6 +997,7 @@ pub(crate) fn build_prompt( } #[allow(clippy::too_many_arguments)] +#[allow(deprecated)] #[instrument(level = "trace", skip_all, fields( diff --git a/codex-rs/core/src/session/turn_context.rs b/codex-rs/core/src/session/turn_context.rs index 7b22ddcc3..8caec7aae 100644 --- a/codex-rs/core/src/session/turn_context.rs +++ b/codex-rs/core/src/session/turn_context.rs @@ -69,6 +69,7 @@ pub struct TurnContext { /// The session's absolute working directory. All relative paths provided /// by the model as well as sandbox policies are resolved against this path /// instead of `std::env::current_dir()`. + #[deprecated(note = "use the selected turn environment cwd instead")] pub(crate) cwd: AbsolutePathBuf, pub(crate) current_date: Option, pub(crate) timezone: Option, @@ -118,6 +119,7 @@ impl TurnContext { &self.permission_profile, &file_system_sandbox_policy, network_sandbox_policy, + #[allow(deprecated)] &self.cwd, ) } @@ -253,6 +255,7 @@ impl TurnContext { session_source: self.session_source.clone(), thread_source: self.thread_source, environments: self.environments.clone(), + #[allow(deprecated)] cwd: self.cwd.clone(), current_date: self.current_date.clone(), timezone: self.timezone.clone(), @@ -288,7 +291,9 @@ impl TurnContext { } } + #[deprecated(note = "resolve paths from the selected turn environment cwd instead")] pub(crate) fn resolve_path(&self, path: Option) -> AbsolutePathBuf { + #[allow(deprecated)] path.as_ref() .map_or_else(|| self.cwd.clone(), |path| self.cwd.join(path)) } @@ -314,6 +319,7 @@ impl TurnContext { ); FileSystemSandboxContext { permissions, + #[allow(deprecated)] cwd: Some(self.cwd.clone()), windows_sandbox_level: self.windows_sandbox_level, windows_sandbox_private_desktop: self @@ -332,6 +338,7 @@ impl TurnContext { let legacy_file_system_sandbox_policy = FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd( &self.sandbox_policy(), + #[allow(deprecated)] &self.cwd, ); let file_system_sandbox_policy = self.file_system_sandbox_policy(); @@ -349,6 +356,7 @@ impl TurnContext { TurnContextItem { turn_id: Some(self.sub_id.clone()), trace_id: self.trace_id.clone(), + #[allow(deprecated)] cwd: self.cwd.to_path_buf(), current_date: self.current_date.clone(), timezone: self.timezone.clone(), @@ -566,6 +574,7 @@ impl Session { session_source, thread_source: session_configuration.thread_source, environments, + #[allow(deprecated)] cwd, current_date: Some(current_date), timezone: Some(timezone), diff --git a/codex-rs/core/src/tasks/user_shell.rs b/codex-rs/core/src/tasks/user_shell.rs index 683856b90..23f3882ed 100644 --- a/codex-rs/core/src/tasks/user_shell.rs +++ b/codex-rs/core/src/tasks/user_shell.rs @@ -148,6 +148,7 @@ pub(crate) async fn execute_user_shell_command( let exec_command = maybe_wrap_shell_lc_with_snapshot( &display_command, session_shell.as_ref(), + #[allow(deprecated)] &turn_context.cwd, &turn_context.shell_environment_policy.r#set, &exec_env_map, @@ -155,6 +156,7 @@ pub(crate) async fn execute_user_shell_command( let call_id = Uuid::new_v4().to_string(); let raw_command = command; + #[allow(deprecated)] let cwd = turn_context.cwd.clone(); let parsed_cmd = parse_command(&display_command); diff --git a/codex-rs/core/src/tools/handlers/agent_jobs/spawn_agents_on_csv.rs b/codex-rs/core/src/tools/handlers/agent_jobs/spawn_agents_on_csv.rs index 6dd7ea2b3..e1a37be6b 100644 --- a/codex-rs/core/src/tools/handlers/agent_jobs/spawn_agents_on_csv.rs +++ b/codex-rs/core/src/tools/handlers/agent_jobs/spawn_agents_on_csv.rs @@ -68,6 +68,7 @@ pub async fn handle( } let db = required_state_db(&session)?; + #[allow(deprecated)] let input_path = turn.resolve_path(Some(args.csv_path)); let input_path_display = input_path.display().to_string(); let csv_content = tokio::fs::read_to_string(&input_path) @@ -141,7 +142,10 @@ pub async fn handle( let job_id = Uuid::new_v4().to_string(); let output_csv_path = args.output_csv_path.map_or_else( || default_output_csv_path(&input_path, job_id.as_str()), - |path| turn.resolve_path(Some(path)), + |path| { + #[allow(deprecated)] + turn.resolve_path(Some(path)) + }, ); let job_suffix = &job_id[..8]; let job_name = format!("agent-job-{job_suffix}"); 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 cc4e9ebfc..216a420e3 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_common.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_common.rs @@ -268,7 +268,9 @@ pub(crate) fn apply_spawn_agent_runtime_overrides( })?; config.permissions.shell_environment_policy = turn.shell_environment_policy.clone(); config.codex_linux_sandbox_exe = turn.codex_linux_sandbox_exe.clone(); - config.cwd = turn.cwd.clone(); + #[allow(deprecated)] + let turn_cwd = turn.cwd.clone(); + config.cwd = turn_cwd; config .permissions .set_permission_profile(turn.permission_profile()) diff --git a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs index f051fb0f7..1a5856173 100644 --- a/codex-rs/core/src/tools/handlers/multi_agents_tests.rs +++ b/codex-rs/core/src/tools/handlers/multi_agents_tests.rs @@ -2088,6 +2088,7 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() { let manager = thread_manager(); session.services.agent_control = manager.agent_control(); let expected_sandbox = turn.config.legacy_sandbox_policy(); + #[allow(deprecated)] let mut expected_file_system_sandbox_policy = FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&expected_sandbox, &turn.cwd); expected_file_system_sandbox_policy @@ -3767,15 +3768,20 @@ async fn build_agent_spawn_config_uses_turn_context_values() { ..ShellEnvironmentPolicy::default() }; let temp_dir = tempfile::tempdir().expect("temp dir"); - turn.cwd = temp_dir.abs(); + #[allow(deprecated)] + { + turn.cwd = temp_dir.abs(); + } turn.codex_linux_sandbox_exe = Some(PathBuf::from("/bin/echo")); + #[allow(deprecated)] + let turn_cwd = turn.cwd.clone(); let sandbox_policy = pick_allowed_sandbox_policy( &turn.config.permissions.permission_profile, turn.config.legacy_sandbox_policy(), - turn.cwd.as_path(), + turn_cwd.as_path(), ); let file_system_sandbox_policy = - FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&sandbox_policy, &turn.cwd); + FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&sandbox_policy, &turn_cwd); let network_sandbox_policy = NetworkSandboxPolicy::from(&sandbox_policy); let permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement( SandboxEnforcement::from_legacy_sandbox_policy(&sandbox_policy), @@ -3798,7 +3804,10 @@ async fn build_agent_spawn_config_uses_turn_context_values() { expected.compact_prompt = turn.compact_prompt.clone(); expected.permissions.shell_environment_policy = turn.shell_environment_policy.clone(); expected.codex_linux_sandbox_exe = turn.codex_linux_sandbox_exe.clone(); - expected.cwd = turn.cwd.clone(); + #[allow(deprecated)] + { + expected.cwd = turn.cwd.clone(); + } expected .permissions .approval_policy @@ -3849,7 +3858,10 @@ async fn build_agent_resume_config_clears_base_instructions() { expected.compact_prompt = turn.compact_prompt.clone(); expected.permissions.shell_environment_policy = turn.shell_environment_policy.clone(); expected.codex_linux_sandbox_exe = turn.codex_linux_sandbox_exe.clone(); - expected.cwd = turn.cwd.clone(); + #[allow(deprecated)] + { + expected.cwd = turn.cwd.clone(); + } expected .permissions .approval_policy diff --git a/codex-rs/core/src/tools/handlers/request_permissions.rs b/codex-rs/core/src/tools/handlers/request_permissions.rs index 243ed52d1..5d49ad861 100644 --- a/codex-rs/core/src/tools/handlers/request_permissions.rs +++ b/codex-rs/core/src/tools/handlers/request_permissions.rs @@ -47,6 +47,7 @@ impl ToolExecutor for RequestPermissionsHandler { } }; + #[allow(deprecated)] let mut args: RequestPermissionsArgs = parse_arguments_with_base_path(&arguments, &turn.cwd)?; args.permissions = normalize_additional_permissions(args.permissions.into()) diff --git a/codex-rs/core/src/tools/handlers/shell.rs b/codex-rs/core/src/tools/handlers/shell.rs index e6ce6908f..84f400854 100644 --- a/codex-rs/core/src/tools/handlers/shell.rs +++ b/codex-rs/core/src/tools/handlers/shell.rs @@ -92,6 +92,7 @@ async fn run_exec_like(args: RunExecLikeArgs) -> Result Result for ShellCommandHandler { ))); }; + #[allow(deprecated)] let cwd = resolve_workdir_base_path(&arguments, &turn.cwd)?; let params: ShellCommandToolCallParams = parse_arguments_with_base_path(&arguments, &cwd)?; + #[allow(deprecated)] let workdir = turn.resolve_path(params.workdir.clone()); maybe_emit_implicit_skill_invocation( session.as_ref(), diff --git a/codex-rs/core/src/tools/handlers/shell_tests.rs b/codex-rs/core/src/tools/handlers/shell_tests.rs index 9db561d57..660bac678 100644 --- a/codex-rs/core/src/tools/handlers/shell_tests.rs +++ b/codex-rs/core/src/tools/handlers/shell_tests.rs @@ -88,6 +88,7 @@ async fn shell_command_handler_to_exec_params_uses_session_shell_and_turn_contex let expected_command = session .user_shell() .derive_exec_args(&command, /*use_login_shell*/ true); + #[allow(deprecated)] let expected_cwd = turn_context.resolve_path(workdir.clone()); let expected_env = create_env( &turn_context.shell_environment_policy, diff --git a/codex-rs/core/src/tools/handlers/view_image.rs b/codex-rs/core/src/tools/handlers/view_image.rs index 3efbedc0e..bb74adb86 100644 --- a/codex-rs/core/src/tools/handlers/view_image.rs +++ b/codex-rs/core/src/tools/handlers/view_image.rs @@ -282,7 +282,10 @@ mod tests { let (session, mut turn) = make_session_and_context().await; let image_dir = tempfile::tempdir().expect("create image temp dir"); let image_cwd = image_dir.abs(); - turn.cwd = image_cwd.clone(); + #[allow(deprecated)] + { + turn.cwd = image_cwd.clone(); + } turn.environments .turn_environments .first_mut() diff --git a/codex-rs/core/src/tools/network_approval.rs b/codex-rs/core/src/tools/network_approval.rs index 14af2c9c5..39441d96f 100644 --- a/codex-rs/core/src/tools/network_approval.rs +++ b/codex-rs/core/src/tools/network_approval.rs @@ -525,6 +525,7 @@ impl NetworkApprovalService { guardian_approval_id, /*approval_id*/ None, prompt_command, + #[allow(deprecated)] turn_context.cwd.clone(), Some(prompt_reason), Some(network_approval_context.clone()), diff --git a/codex-rs/core/src/tools/orchestrator.rs b/codex-rs/core/src/tools/orchestrator.rs index 648d3f79e..deb9ae596 100644 --- a/codex-rs/core/src/tools/orchestrator.rs +++ b/codex-rs/core/src/tools/orchestrator.rs @@ -234,6 +234,7 @@ impl ToolOrchestrator { // Platform-specific flag gating is handled by SandboxManager::select_initial. let use_legacy_landlock = turn_ctx.features.use_legacy_landlock(); + #[allow(deprecated)] let sandbox_cwd = tool.sandbox_cwd(req).unwrap_or(&turn_ctx.cwd); let initial_attempt = SandboxAttempt { sandbox: initial_sandbox, diff --git a/codex-rs/core/src/tools/registry.rs b/codex-rs/core/src/tools/registry.rs index 85c346f48..6486e7db7 100644 --- a/codex-rs/core/src/tools/registry.rs +++ b/codex-rs/core/src/tools/registry.rs @@ -409,6 +409,7 @@ impl ToolRegistry { "sandbox_policy", permission_profile_policy_tag( &invocation.turn.permission_profile, + #[allow(deprecated)] invocation.turn.cwd.as_path(), ), ), diff --git a/codex-rs/core/src/unified_exec/mod_tests.rs b/codex-rs/core/src/unified_exec/mod_tests.rs index f8a1480af..6926f9cbf 100644 --- a/codex-rs/core/src/unified_exec/mod_tests.rs +++ b/codex-rs/core/src/unified_exec/mod_tests.rs @@ -83,6 +83,7 @@ async fn exec_command_with_tty( ) -> Result { let manager = &session.services.unified_exec_manager; let process_id = manager.allocate_process_id().await; + #[allow(deprecated)] let cwd = workdir .as_ref() .map_or_else(|| turn.cwd.clone(), |workdir| turn.cwd.join(workdir)); @@ -501,10 +502,12 @@ async fn reusing_completed_process_returns_unknown_process() -> anyhow::Result<( #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn completed_pipe_commands_preserve_exit_code() -> anyhow::Result<()> { let (_, turn) = make_session_and_context().await; + #[allow(deprecated)] + let cwd = turn.cwd.clone(); let request = test_exec_request( &turn, vec!["bash".to_string(), "-lc".to_string(), "exit 17".to_string()], - turn.cwd.clone(), + cwd, shell_env(), ); @@ -598,10 +601,12 @@ async fn remote_exec_server_rejects_inherited_fd_launches() -> anyhow::Result<() turn.environments.turn_environments[0].environment = Arc::new(remote_test_env.environment().clone()); + #[allow(deprecated)] + let cwd = turn.cwd.clone(); let request = test_exec_request( &turn, vec!["bash".to_string(), "-lc".to_string(), "echo ok".to_string()], - turn.cwd.clone(), + cwd, shell_env(), ); 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 5ef599403..87d9553dd 100644 --- a/codex-rs/core/src/unified_exec/process_manager_tests.rs +++ b/codex-rs/core/src/unified_exec/process_manager_tests.rs @@ -175,7 +175,9 @@ async fn failed_initial_end_for_unstored_process_uses_fallback_output() { process_id: 123, yield_time_ms: 1000, max_output_tokens: None, + #[allow(deprecated)] cwd: turn.cwd.clone(), + #[allow(deprecated)] sandbox_cwd: turn.cwd.clone(), environment: turn .environments @@ -200,6 +202,7 @@ async fn failed_initial_end_for_unstored_process_uses_fallback_output() { /*process_started_alive*/ false, &context, &request, + #[allow(deprecated)] turn.cwd.clone(), transcript, "PRE_DENIAL_MARKER".to_string(),