From 7d6bc575af30491eed13bfdde08a3ca2b31e7acf Mon Sep 17 00:00:00 2001 From: jif-oai Date: Sat, 13 Dec 2025 12:42:45 +0100 Subject: [PATCH] feat: close unified_exec at end of turn --- codex-rs/core/src/tasks/mod.rs | 18 ++++++++++++++++-- .../core/src/unified_exec/session_manager.rs | 5 +++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/src/tasks/mod.rs b/codex-rs/core/src/tasks/mod.rs index fa5433ef5e..9a6ddebb38 100644 --- a/codex-rs/core/src/tasks/mod.rs +++ b/codex-rs/core/src/tasks/mod.rs @@ -159,6 +159,7 @@ impl Session { for task in self.take_all_running_tasks().await { self.handle_task_abort(task, reason.clone()).await; } + self.close_unified_exec_sessions().await; } pub async fn on_task_finished( @@ -167,12 +168,18 @@ impl Session { last_agent_message: Option, ) { let mut active = self.active_turn.lock().await; - if let Some(at) = active.as_mut() + let should_close_sessions = if let Some(at) = active.as_mut() && at.remove_task(&turn_context.sub_id) { *active = None; - } + true + } else { + false + }; drop(active); + if should_close_sessions { + self.close_unified_exec_sessions().await; + } let event = EventMsg::TaskComplete(TaskCompleteEvent { last_agent_message }); self.send_event(turn_context.as_ref(), event).await; } @@ -196,6 +203,13 @@ impl Session { } } + async fn close_unified_exec_sessions(&self) { + self.services + .unified_exec_manager + .close_open_sessions() + .await; + } + async fn handle_task_abort(self: &Arc, task: RunningTask, reason: TurnAbortReason) { let sub_id = task.turn_context.sub_id.clone(); if task.cancellation_token.is_cancelled() { diff --git a/codex-rs/core/src/unified_exec/session_manager.rs b/codex-rs/core/src/unified_exec/session_manager.rs index 4b24c574ac..1ba793cfe2 100644 --- a/codex-rs/core/src/unified_exec/session_manager.rs +++ b/codex-rs/core/src/unified_exec/session_manager.rs @@ -643,6 +643,11 @@ impl UnifiedExecSessionManager { entry.session.terminate(); } } + + pub(crate) async fn close_open_sessions(&self) { + // Terminating sessions ensures the exit watcher emits ExecCommandEnd events. + self.terminate_all_sessions().await; + } } enum SessionStatus {