diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-17 23:55:08 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-17 23:59:56 +0300 |
| commit | e0758c32118f2aa006db3d8fa4b41833fe6e7ead (patch) | |
| tree | 2b29dd61ebf870db8d0ac95cc0b4515178c834c4 /src/app/actions.rs | |
| parent | 040956531f673c8fb7720037494ed4e61b123c6c (diff) | |
feat: harden named agent cli workflows
refs #1525
Diffstat (limited to 'src/app/actions.rs')
| -rw-r--r-- | src/app/actions.rs | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/src/app/actions.rs b/src/app/actions.rs index 3fedeeb3..b4f352b4 100644 --- a/src/app/actions.rs +++ b/src/app/actions.rs @@ -1,6 +1,8 @@ //! Pure state mutations on AppState. //! These don't need channels, async, or PTY runtime. +use std::time::Instant; + use tracing::{info, warn}; use crate::detect::{Agent, AgentState}; @@ -2583,7 +2585,7 @@ impl AppState { observed_at, } => self .update_terminal_state(pane_id, |terminal| { - Some(terminal.set_detected_state_with_screen_signals_at( + let mutation = terminal.set_detected_state_with_screen_signals_at( agent, state, visible_blocker, @@ -2591,7 +2593,11 @@ impl AppState { visible_working, process_exited, observed_at, - )) + ); + if process_exited { + terminal.reconcile_managed_agent_at(observed_at, true); + } + Some(mutation) }) .into_iter() .collect(), @@ -2753,11 +2759,13 @@ impl AppState { .attached_terminal_id .clone(); let previous_seen = self.workspaces[ws_idx].pane_state(pane_id)?.seen; - let mutation = { + let (mutation, managed_changed) = { let terminal = self.terminals.get_mut(&terminal_id)?; - update(terminal)? + let mutation = update(terminal)?; + let managed_changed = terminal.reconcile_managed_agent_at(Instant::now(), false); + (mutation, managed_changed) }; - if mutation.session_ref_changed { + if mutation.session_ref_changed || managed_changed { self.mark_session_dirty(); } let change = mutation.effective_state_change?; @@ -2785,6 +2793,40 @@ impl AppState { Some(update) } + pub(crate) fn next_managed_agent_deadline(&self) -> Option<Instant> { + self.terminals + .values() + .filter_map(crate::terminal::TerminalState::next_managed_agent_deadline) + .min() + } + + pub(crate) fn reconcile_managed_agents_at(&mut self, now: Instant) -> Vec<(usize, PaneId)> { + let mut changed_terminals = std::collections::HashSet::new(); + for (terminal_id, terminal) in &mut self.terminals { + if terminal.reconcile_managed_agent_at(now, false) { + changed_terminals.insert(terminal_id.clone()); + } + } + if changed_terminals.is_empty() { + return Vec::new(); + } + self.mark_session_dirty(); + self.workspaces + .iter() + .enumerate() + .flat_map(|(ws_idx, workspace)| { + let changed_terminals = &changed_terminals; + workspace.tabs.iter().flat_map(move |tab| { + tab.panes.iter().filter_map(move |(&pane_id, pane)| { + changed_terminals + .contains(&pane.attached_terminal_id) + .then_some((ws_idx, pane_id)) + }) + }) + }) + .collect() + } + pub(crate) fn publish_pane_process_exit_if_agent( &mut self, pane_id: PaneId, |
