aboutsummaryrefslogtreecommitdiff
path: root/src/pane.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-03 04:38:46 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-03 04:38:46 +0300
commit58af4902fc51b6be8fec99a3cec576c98e0c6075 (patch)
tree8dbb2501a61904b4c90d368150b5370b5f9e90e6 /src/pane.rs
parent816cb88cd9df3cba305a50842ebf78db19279dd5 (diff)
fix: preserve status in transcript viewers
Diffstat (limited to 'src/pane.rs')
-rw-r--r--src/pane.rs70
1 files changed, 60 insertions, 10 deletions
diff --git a/src/pane.rs b/src/pane.rs
index 4611b315..55b08f60 100644
--- a/src/pane.rs
+++ b/src/pane.rs
@@ -323,6 +323,29 @@ fn stable_visible_signal_refresh_due(
})
}
+fn detection_update_for_publish(
+ agent: Option<Agent>,
+ content: &str,
+ process_exited: bool,
+) -> Option<crate::detect::AgentDetection> {
+ if crate::detect::should_skip_state_update(agent, content) {
+ return None;
+ }
+
+ if process_exited {
+ return Some(crate::detect::AgentDetection {
+ state: AgentState::Idle,
+ skip_state_update: false,
+ visible_blocker: false,
+ visible_idle: false,
+ visible_working: false,
+ });
+ }
+
+ let detection = crate::detect::detect_agent(agent, content);
+ (!detection.skip_state_update).then_some(detection)
+}
+
fn spawn_basic_detection_task(
pane_id: PaneId,
child_pid: Arc<AtomicU32>,
@@ -380,6 +403,9 @@ fn spawn_basic_detection_task(
let mut agent_changed = false;
let mut agent = agent_presence.current_agent();
let content = terminal.detection_text();
+ if crate::detect::should_skip_state_update(agent, &content) {
+ continue;
+ }
let foreground_pgid = (pid > 0)
.then(|| crate::detect::foreground_process_group_id(pid))
@@ -429,7 +455,9 @@ fn spawn_basic_detection_task(
}
}
- let detection = crate::detect::detect_agent(agent, &content);
+ let Some(detection) = detection_update_for_publish(agent, &content, false) else {
+ continue;
+ };
let new_state = detection.state;
let visible_blocker = detection.visible_blocker && new_state == AgentState::Blocked;
let visible_idle = detection.visible_idle && new_state == AgentState::Idle;
@@ -1467,6 +1495,9 @@ impl PaneRuntime {
release_was_active = suppressed_agent.is_some();
let pid = child_pid.load(Ordering::Acquire);
let content = terminal.detection_text();
+ if detect::should_skip_state_update(agent_presence.current_agent(), &content) {
+ continue;
+ }
let foreground_pgid = (pid > 0)
.then(|| detect::foreground_process_group_id(pid))
.flatten();
@@ -1581,15 +1612,10 @@ impl PaneRuntime {
let process_exited = pending_foreground_shell_clear
&& agent.is_some()
&& !foreground_shell_exit_reported;
- let detection = if process_exited {
- detect::AgentDetection {
- state: AgentState::Idle,
- visible_blocker: false,
- visible_idle: false,
- visible_working: false,
- }
- } else {
- detect::detect_agent(agent, &content)
+ let Some(detection) =
+ detection_update_for_publish(agent, &content, process_exited)
+ else {
+ continue;
};
let raw_state = detection.state;
let new_state = crate::terminal::state::stabilize_agent_detection(
@@ -2425,6 +2451,30 @@ mod tests {
}
#[test]
+ fn codex_transcript_viewer_suppresses_prompt_idle_publish() {
+ let content = "/ T R A N S C R I P T /\n\n› yeah go ahead\n────────────────────────────────────────────────────────────────────────────────── 100% ─\n ↑/↓ to scroll pgup/pgdn to page home/end to jump\n q to quit esc to edit prev";
+
+ assert!(detection_update_for_publish(Some(Agent::Codex), content, false).is_none());
+ }
+
+ #[test]
+ fn codex_transcript_viewer_suppresses_process_exit_idle_publish() {
+ let content = "/ T R A N S C R I P T /\n\n› yeah go ahead\n────────────────────────────────────────────────────────────────────────────────── 100% ─\n ↑/↓ to scroll pgup/pgdn to page home/end to jump\n q to quit esc to edit prev";
+
+ assert!(detection_update_for_publish(Some(Agent::Codex), content, true).is_none());
+ }
+
+ #[test]
+ fn process_exit_without_transcript_still_reports_idle() {
+ let detection =
+ detection_update_for_publish(Some(Agent::Codex), "Codex finished\n› ", true)
+ .expect("process exit should publish idle outside transcript viewer");
+
+ assert_eq!(detection.state, AgentState::Idle);
+ assert!(!detection.skip_state_update);
+ }
+
+ #[test]
fn stable_visible_idle_republishes_for_stale_hook_deadline() {
let now = std::time::Instant::now();
let previous = DetectionPublishState {