aboutsummaryrefslogtreecommitdiff
path: root/crates/dinggerd/src/watcher.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/dinggerd/src/watcher.rs')
-rw-r--r--crates/dinggerd/src/watcher.rs21
1 files changed, 13 insertions, 8 deletions
diff --git a/crates/dinggerd/src/watcher.rs b/crates/dinggerd/src/watcher.rs
index 77b9259..aee8d5e 100644
--- a/crates/dinggerd/src/watcher.rs
+++ b/crates/dinggerd/src/watcher.rs
@@ -35,7 +35,7 @@ use std::collections::HashMap;
use detect_core::{detect_agent_with_osc, Agent, AgentState};
use tracing::{debug, info, warn};
-use crate::hooks;
+use crate::hooks::{self, Observation};
use crate::importance::Importance;
use crate::notify::{play_sound, send_notification, NotificationKind};
use crate::tmux;
@@ -376,7 +376,12 @@ impl Watcher {
// finished between two ticks is still a completion.
let mut alerts = Vec::new();
for observed in observations {
- let next = advance(track, observed, pane.attended, acked, now);
+ let mut next = advance(track, observed.state, pane.attended, acked, now);
+ // A cancelled run did not finish: idle, as if seen.
+ if observed.cancelled && next.state == AgentState::Idle {
+ next.seen = true;
+ next.held = false;
+ }
if next.state != track.state {
info!(
target = %pane.display_target,
@@ -386,7 +391,7 @@ impl Watcher {
);
// Notify on transitions observed by this process, not
// when resuming from options written before a restart.
- if !restored {
+ if !restored && !observed.cancelled {
alerts.extend(notification_kind_for_transition(track.state, next.state));
}
}
@@ -615,14 +620,14 @@ impl Watcher {
/// The pane's raw agent states this tick, in order, or `None` when the
/// screen is a viewer (transcript, picker) that says nothing about state.
-fn observe(pane: &tmux::Pane, listed: std::time::Instant) -> Option<Vec<AgentState>> {
+fn observe(pane: &tmux::Pane, listed: std::time::Instant) -> Option<Vec<Observation>> {
if pane.dead {
- return Some(vec![AgentState::Idle]);
+ return Some(vec![Observation::plain(AgentState::Idle)]);
}
let Some(agent) = pane.agent else {
// The agent is gone; its last hook report must not outlive it.
hooks::drop_reports(&pane.pane_id, listed);
- return Some(vec![AgentState::Unknown]);
+ return Some(vec![Observation::plain(AgentState::Unknown)]);
};
// Agent-reported state is authoritative; it survives restarts through
// the `@dingger_hook` option until the extension reports again.
@@ -630,7 +635,7 @@ fn observe(pane: &tmux::Pane, listed: std::time::Instant) -> Option<Vec<AgentSta
return Some(states);
}
if let Some(state) = parse_state(&pane.written_hook) {
- return Some(vec![state]);
+ return Some(vec![Observation::plain(state)]);
}
let screen = match tmux::capture_pane(&pane.pane_id) {
Ok(screen) => screen,
@@ -642,7 +647,7 @@ fn observe(pane: &tmux::Pane, listed: std::time::Instant) -> Option<Vec<AgentSta
// tmux pane_title carries the last OSC title the application set; tmux
// does not re-expose OSC progress sequences.
let detection = detect_agent_with_osc(Some(agent), &screen, &pane.pane_title, "");
- (!detection.skip_state_update).then(|| vec![detection.state])
+ (!detection.skip_state_update).then(|| vec![Observation::plain(detection.state)])
}
/// The host name tmux uses as a pane's default title.