aboutsummaryrefslogtreecommitdiff
path: root/src/pane.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-24 02:49:33 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-24 02:50:58 +0300
commite608a75159fc5cca70485d83ffb8ee681c9da385 (patch)
tree5ffdec62d0bee9a798418d6414ecbddae7ff8ae5 /src/pane.rs
parent169a4fd90c20a00aec77d684ecec98b9f0f996cc (diff)
fix: make known-agent exit process-owned
refs #1792 refs #1648
Diffstat (limited to 'src/pane.rs')
-rw-r--r--src/pane.rs122
1 files changed, 81 insertions, 41 deletions
diff --git a/src/pane.rs b/src/pane.rs
index ee3aee12..ea6a13fd 100644
--- a/src/pane.rs
+++ b/src/pane.rs
@@ -290,6 +290,7 @@ fn foreground_member_cwd_different_from_shell(
enum ForegroundShellAgentAction {
ObserveProbe,
ReportProcessExit,
+ ReportReplacementProcess,
ClearAgent,
}
@@ -299,12 +300,20 @@ fn foreground_shell_agent_action(
foreground_is_pane_shell: bool,
process_exit_reported: bool,
) -> ForegroundShellAgentAction {
- if previous_agent.is_none() || new_agent.is_some() {
+ let Some(previous_agent) = previous_agent else {
return ForegroundShellAgentAction::ObserveProbe;
- }
-
+ };
if process_exit_reported {
- return ForegroundShellAgentAction::ClearAgent;
+ return if new_agent == Some(previous_agent) {
+ ForegroundShellAgentAction::ReportReplacementProcess
+ } else if new_agent.is_none() {
+ ForegroundShellAgentAction::ClearAgent
+ } else {
+ ForegroundShellAgentAction::ObserveProbe
+ };
+ }
+ if new_agent.is_some() {
+ return ForegroundShellAgentAction::ObserveProbe;
}
if foreground_is_pane_shell {
@@ -317,6 +326,38 @@ fn foreground_shell_agent_action(
ForegroundShellAgentAction::ObserveProbe
}
+fn apply_foreground_shell_agent_action(
+ agent_presence: &mut AgentDetectionPresence,
+ action: ForegroundShellAgentAction,
+ previous_agent: Option<Agent>,
+ new_agent: Option<Agent>,
+ pending_foreground_shell_clear: &mut bool,
+ foreground_shell_exit_reported: &mut bool,
+) -> bool {
+ match action {
+ ForegroundShellAgentAction::ReportReplacementProcess => {
+ *pending_foreground_shell_clear = false;
+ *foreground_shell_exit_reported = false;
+ agent_presence.observe_process_probe(previous_agent);
+ true
+ }
+ ForegroundShellAgentAction::ReportProcessExit => {
+ *pending_foreground_shell_clear = true;
+ false
+ }
+ ForegroundShellAgentAction::ClearAgent => {
+ *pending_foreground_shell_clear = false;
+ *foreground_shell_exit_reported = false;
+ agent_presence.clear_current_agent()
+ }
+ ForegroundShellAgentAction::ObserveProbe => {
+ *pending_foreground_shell_clear = false;
+ *foreground_shell_exit_reported = false;
+ agent_presence.observe_process_probe(new_agent)
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy)]
struct ProcessProbeInput {
current_agent: Option<Agent>,
@@ -680,27 +721,20 @@ fn spawn_basic_detection_task(
}
}
let previous_agent = agent_presence.current_agent();
- let changed = match foreground_shell_agent_action(
+ let foreground_action = foreground_shell_agent_action(
previous_agent,
new_agent,
foreground_is_pane_shell,
foreground_shell_exit_reported,
- ) {
- ForegroundShellAgentAction::ReportProcessExit => {
- pending_foreground_shell_clear = true;
- false
- }
- ForegroundShellAgentAction::ClearAgent => {
- pending_foreground_shell_clear = false;
- foreground_shell_exit_reported = false;
- agent_presence.clear_current_agent()
- }
- ForegroundShellAgentAction::ObserveProbe => {
- pending_foreground_shell_clear = false;
- foreground_shell_exit_reported = false;
- agent_presence.observe_process_probe(new_agent)
- }
- };
+ );
+ let changed = apply_foreground_shell_agent_action(
+ &mut agent_presence,
+ foreground_action,
+ previous_agent,
+ new_agent,
+ &mut pending_foreground_shell_clear,
+ &mut foreground_shell_exit_reported,
+ );
if new_agent.is_some() {
last_foreground_pgid = process_group_id.or(foreground_pgid);
acquisition_started_at = None;
@@ -715,7 +749,9 @@ fn spawn_basic_detection_task(
}
if changed {
agent = agent_presence.current_agent();
- agent_changed = previous_agent != agent;
+ agent_changed = previous_agent != agent
+ || foreground_action
+ == ForegroundShellAgentAction::ReportReplacementProcess;
if agent_changed {
pending_idle.clear();
last_screen_scan_detection_content_seq = None;
@@ -2105,27 +2141,20 @@ impl PaneRuntime {
}
let previous_agent = agent_presence.current_agent();
- let changed = match foreground_shell_agent_action(
+ let foreground_action = foreground_shell_agent_action(
previous_agent,
new_agent,
foreground_is_pane_shell,
foreground_shell_exit_reported,
- ) {
- ForegroundShellAgentAction::ReportProcessExit => {
- pending_foreground_shell_clear = true;
- false
- }
- ForegroundShellAgentAction::ClearAgent => {
- pending_foreground_shell_clear = false;
- foreground_shell_exit_reported = false;
- agent_presence.clear_current_agent()
- }
- ForegroundShellAgentAction::ObserveProbe => {
- pending_foreground_shell_clear = false;
- foreground_shell_exit_reported = false;
- agent_presence.observe_process_probe(new_agent)
- }
- };
+ );
+ let changed = apply_foreground_shell_agent_action(
+ &mut agent_presence,
+ foreground_action,
+ previous_agent,
+ new_agent,
+ &mut pending_foreground_shell_clear,
+ &mut foreground_shell_exit_reported,
+ );
if new_agent.is_some() {
last_foreground_pgid = process_group_id;
acquisition_started_at = None;
@@ -2142,7 +2171,10 @@ impl PaneRuntime {
}
if changed {
agent = agent_presence.current_agent();
- if agent != previous_agent {
+ if agent != previous_agent
+ || foreground_action
+ == ForegroundShellAgentAction::ReportReplacementProcess
+ {
pending_idle.clear();
last_screen_scan_detection_content_seq = None;
// A new foreground agent must not inherit OSC
@@ -3370,6 +3402,14 @@ mod tests {
}
#[test]
+ fn same_agent_after_reported_exit_is_a_replacement_process() {
+ assert_eq!(
+ foreground_shell_agent_action(Some(Agent::Pi), Some(Agent::Pi), false, true),
+ ForegroundShellAgentAction::ReportReplacementProcess
+ );
+ }
+
+ #[test]
fn unknown_non_shell_foreground_job_is_not_immediate_clear_signal() {
assert_eq!(
foreground_shell_agent_action(Some(Agent::Claude), None, false, false),
@@ -3388,7 +3428,7 @@ mod tests {
#[test]
fn foreground_agent_job_is_not_clear_signal() {
assert_eq!(
- foreground_shell_agent_action(Some(Agent::Claude), Some(Agent::OpenCode), true, false),
+ foreground_shell_agent_action(Some(Agent::Claude), Some(Agent::OpenCode), true, false,),
ForegroundShellAgentAction::ObserveProbe
);
}