aboutsummaryrefslogtreecommitdiff
path: root/src/app/actions.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-26 17:10:28 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-26 17:10:28 +0300
commit3750e0bae21c54da3947d337584f180a21d0bc67 (patch)
tree4542d8af76b4fee0c428ca5e9378a06946ef62ca /src/app/actions.rs
parent1b980eaa9d4cbc050b6b81525e4b6b72ae853be5 (diff)
feat: add pane metadata reporting
refs #36
Diffstat (limited to 'src/app/actions.rs')
-rw-r--r--src/app/actions.rs125
1 files changed, 115 insertions, 10 deletions
diff --git a/src/app/actions.rs b/src/app/actions.rs
index da9e538a..ab2539bf 100644
--- a/src/app/actions.rs
+++ b/src/app/actions.rs
@@ -93,10 +93,11 @@ pub struct PaneStateUpdate {
pub previous_agent_label: Option<String>,
pub previous_known_agent: Option<Agent>,
pub previous_state: AgentState,
+ pub previous_presentation: crate::terminal::EffectivePresentation,
pub agent_label: Option<String>,
pub known_agent: Option<Agent>,
pub state: AgentState,
- pub custom_status: Option<String>,
+ pub presentation: crate::terminal::EffectivePresentation,
}
// ---------------------------------------------------------------------------
@@ -333,23 +334,37 @@ impl AppState {
let terminal = self.terminals.get(&pane.attached_terminal_id);
let pane_number = ws.public_pane_number(pane_id).unwrap_or(0);
let label = terminal
- .and_then(|terminal| terminal.manual_label.as_deref())
- .or_else(|| terminal.and_then(|terminal| terminal.agent_name.as_deref()))
- .or_else(|| terminal.and_then(|terminal| terminal.effective_agent_label()))
- .map(str::to_string)
+ .and_then(|terminal| terminal.effective_title())
+ .or_else(|| {
+ terminal
+ .and_then(|terminal| terminal.manual_label.as_deref().map(str::to_string))
+ })
+ .or_else(|| {
+ terminal.and_then(|terminal| terminal.agent_name.as_deref().map(str::to_string))
+ })
+ .or_else(|| {
+ terminal
+ .and_then(|terminal| terminal.effective_agent_label().map(str::to_string))
+ })
.or_else(|| {
launch_label(terminal.and_then(|terminal| terminal.launch_argv.as_ref()))
})
.unwrap_or_else(|| format!("pane {pane_number}"));
- let agent_label = terminal
- .and_then(|terminal| terminal.agent_name.as_deref())
- .or_else(|| terminal.and_then(|terminal| terminal.effective_agent_label()));
+ let display_agent = terminal.and_then(|terminal| terminal.effective_display_agent());
+ let agent_label = display_agent.as_deref().or_else(|| {
+ terminal
+ .and_then(|terminal| terminal.agent_name.as_deref())
+ .or_else(|| terminal.and_then(|terminal| terminal.effective_agent_label()))
+ });
let custom_status = terminal.and_then(|terminal| terminal.effective_custom_status());
let state = terminal
.map(|terminal| terminal.state)
.unwrap_or(AgentState::Unknown);
+ let status_label = terminal
+ .map(|terminal| terminal.effective_presentation().state_labels)
+ .and_then(|labels| labels.get(state_label_text(state, pane.seen)).cloned());
let status = custom_status
- .map(str::to_string)
+ .or(status_label)
.or_else(|| agent_label.map(|_| state_label_text(state, pane.seen).to_string()));
let meta = match (agent_label, status.as_deref()) {
(Some(agent_label), Some(status)) => format!("{agent_label} ยท {status}"),
@@ -656,6 +671,60 @@ fn activity_summary_for_panes<'a>(
// ---------------------------------------------------------------------------
impl AppState {
+ pub(crate) fn next_agent_metadata_expiry(&self) -> Option<std::time::Instant> {
+ self.terminals
+ .values()
+ .filter_map(|terminal| terminal.next_agent_metadata_expiry())
+ .min()
+ }
+
+ pub(crate) fn expire_agent_metadata_at(
+ &mut self,
+ scheduled_deadline: std::time::Instant,
+ now: std::time::Instant,
+ ) -> Vec<PaneStateUpdate> {
+ let pane_terminals: Vec<_> = self
+ .workspaces
+ .iter()
+ .enumerate()
+ .flat_map(|(ws_idx, ws)| {
+ ws.tabs.iter().flat_map(move |tab| {
+ tab.layout
+ .pane_ids()
+ .into_iter()
+ .filter_map(move |pane_id| {
+ ws.pane_state(pane_id)
+ .map(|pane| (ws_idx, pane_id, pane.attached_terminal_id.clone()))
+ })
+ })
+ })
+ .collect();
+ pane_terminals
+ .into_iter()
+ .filter_map(|(ws_idx, pane_id, terminal_id)| {
+ let mutation = self
+ .terminals
+ .get_mut(&terminal_id)?
+ .expire_agent_metadata_at(scheduled_deadline, now)?;
+ let change = mutation.effective_state_change?;
+ let update = PaneStateUpdate {
+ pane_id,
+ ws_idx,
+ previous_agent_label: change.previous_agent_label.clone(),
+ previous_known_agent: change.previous_known_agent,
+ previous_state: change.previous_state,
+ previous_presentation: change.previous_presentation.clone(),
+ agent_label: change.agent_label.clone(),
+ known_agent: change.known_agent,
+ state: change.state,
+ presentation: change.presentation.clone(),
+ };
+ self.apply_pane_state_change(ws_idx, pane_id, &change);
+ Some(update)
+ })
+ .collect()
+ }
+
pub(crate) fn pane_is_in_active_tab(&self, ws_idx: usize, pane_id: PaneId) -> bool {
let Some(active_ws_idx) = self.active else {
return false;
@@ -1844,6 +1913,41 @@ impl AppState {
})
.into_iter()
.collect(),
+ AppEvent::HookMetadataReported {
+ pane_id,
+ source,
+ agent_label,
+ applies_to_source,
+ title,
+ display_agent,
+ custom_status,
+ state_labels,
+ clear_title,
+ clear_display_agent,
+ clear_custom_status,
+ clear_state_labels,
+ seq,
+ ttl,
+ } => self
+ .update_terminal_state(pane_id, |terminal| {
+ terminal.set_agent_metadata(crate::terminal::AgentMetadataReport {
+ source,
+ agent_label,
+ applies_to_source,
+ title,
+ display_agent,
+ custom_status,
+ state_labels,
+ clear_title,
+ clear_display_agent,
+ clear_custom_status,
+ clear_state_labels,
+ ttl,
+ seq,
+ })
+ })
+ .into_iter()
+ .collect(),
AppEvent::HookAuthorityCleared {
pane_id,
source,
@@ -1904,10 +2008,11 @@ impl AppState {
previous_agent_label: change.previous_agent_label.clone(),
previous_known_agent: change.previous_known_agent,
previous_state: change.previous_state,
+ previous_presentation: change.previous_presentation.clone(),
agent_label: change.agent_label.clone(),
known_agent: change.known_agent,
state: change.state,
- custom_status: change.custom_status.clone(),
+ presentation: change.presentation.clone(),
};
self.apply_pane_state_change(ws_idx, pane_id, &change);
Some(update)