From 28360107c1bfab57fb0de99d74bfa48e74423ca8 Mon Sep 17 00:00:00 2001 From: Can Celik Date: Mon, 21 Sep 2026 20:47:14 +0300 Subject: fix: distinguish agent completion from startup and session changes (#4457) refs #3338 refs #3990 refs #3916 --- src/terminal/state.rs | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'src/terminal') diff --git a/src/terminal/state.rs b/src/terminal/state.rs index c084b034..119916c8 100644 --- a/src/terminal/state.rs +++ b/src/terminal/state.rs @@ -142,6 +142,7 @@ pub struct TerminalState { metadata_token_sequence_sources: std::collections::HashSet, pub state: AgentState, pub last_agent_state_change_seq: Option, + pub last_agent_completion_seq: Option, pub revision: u64, pub launch_argv: Option>, pub respawn_shell_on_exit: bool, @@ -178,6 +179,7 @@ impl TerminalState { metadata_token_sequence_sources: std::collections::HashSet::new(), state: AgentState::Unknown, last_agent_state_change_seq: None, + last_agent_completion_seq: None, revision: 0, launch_argv: None, respawn_shell_on_exit: false, @@ -584,14 +586,18 @@ impl TerminalState { if agent.is_none() && self.recent_agent_process_exit.is_some() { self.clear_agent_name(); } + let effective_state_change = self.recompute_effective_state( + previous_agent_label, + previous_known_agent, + previous_state, + previous_presentation, + now, + ); + if fallback_state == AgentState::Working && self.state == AgentState::Working { + self.agent_process_acquisition_pending = false; + } TerminalStateMutation { - effective_state_change: self.recompute_effective_state( - previous_agent_label, - previous_known_agent, - previous_state, - previous_presentation, - now, - ), + effective_state_change, session_ref_changed: previous_session != self.current_session_identity_for_persistence(), agent_released, @@ -742,14 +748,18 @@ impl TerminalState { session_ref, }); let current_session = self.current_session_identity_for_persistence(); + let effective_state_change = self.recompute_effective_state( + previous_agent_label, + previous_known_agent, + previous_state, + previous_presentation, + now, + ); + if state == AgentState::Working && self.state == AgentState::Working { + self.agent_process_acquisition_pending = false; + } Some(TerminalStateMutation { - effective_state_change: self.recompute_effective_state( - previous_agent_label, - previous_known_agent, - previous_state, - previous_presentation, - now, - ), + effective_state_change, session_ref_changed: previous_session != current_session, agent_released: false, }) @@ -1615,6 +1625,10 @@ impl TerminalState { } self.persisted_agent_session = Some(persisted_session); let current_session = self.current_session_identity_for_persistence(); + if previous_session.is_some() && previous_session != current_session { + // Rebinding can expose a cached Working screen; only a fresh report ends acquisition. + self.agent_process_acquisition_pending = true; + } Some(TerminalStateMutation { effective_state_change: self.recompute_effective_state( previous_agent_label, @@ -1925,6 +1939,7 @@ impl TerminalState { timeout: Duration, ) { self.set_agent_name(name); + self.agent_process_acquisition_pending = true; self.agent_name_owner = Some(AgentNameOwner { agent_label: crate::detect::agent_label(kind).to_string(), session_ref: None, @@ -2092,6 +2107,7 @@ impl TerminalState { self.stale_full_lifecycle_hook_sessions.clear(); self.state = AgentState::Unknown; self.last_agent_state_change_seq = None; + self.last_agent_completion_seq = None; self.launch_argv = None; self.respawn_shell_on_exit = false; self.recent_agent_process_exit = None; -- cgit v1.2.3