diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-26 17:10:28 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-26 17:10:28 +0300 |
| commit | 3750e0bae21c54da3947d337584f180a21d0bc67 (patch) | |
| tree | 4542d8af76b4fee0c428ca5e9378a06946ef62ca /src/server | |
| parent | 1b980eaa9d4cbc050b6b81525e4b6b72ae853be5 (diff) | |
feat: add pane metadata reporting
refs #36
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/headless.rs | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/server/headless.rs b/src/server/headless.rs index e65b741c..37c05bf0 100644 --- a/src/server/headless.rs +++ b/src/server/headless.rs @@ -2479,6 +2479,18 @@ impl HeadlessServer { self.app.save_session_now(); } + if let Some(deadline) = self + .app + .agent_metadata_deadline + .filter(|deadline| now >= *deadline) + { + for update in self.app.state.expire_agent_metadata_at(deadline, now) { + self.app.emit_pane_state_update(&update); + } + self.app.sync_agent_metadata_deadline(); + changed = true; + } + self.app.sync_headless_animation_timer(now); changed } @@ -3452,6 +3464,96 @@ next_tab = "" } #[test] + fn headless_scheduled_tasks_expire_agent_metadata() { + let mut server = test_headless_server(); + let workspace = crate::workspace::Workspace::test_new("metadata"); + let pane_id = workspace.tabs[0].root_pane; + server.app.state.workspaces = vec![workspace]; + server.app.state.ensure_test_terminals(); + + assert!( + server.handle_internal_event_with_forwarding(AppEvent::HookStateReported { + pane_id, + source: "herdr:pi".into(), + agent_label: "pi".into(), + state: crate::detect::AgentState::Working, + message: None, + custom_status: None, + seq: None, + session_ref: None, + }) + ); + assert!( + server.handle_internal_event_with_forwarding(AppEvent::HookMetadataReported { + pane_id, + source: "user:pi-display".into(), + agent_label: Some("pi".into()), + applies_to_source: Some("herdr:pi".into()), + title: None, + display_agent: None, + custom_status: Some("short lived".into()), + state_labels: HashMap::new(), + clear_title: false, + clear_display_agent: false, + clear_custom_status: false, + clear_state_labels: false, + seq: None, + ttl: Some(Duration::from_millis(1)), + }) + ); + + let deadline = server + .app + .agent_metadata_deadline + .expect("metadata deadline"); + let terminal_id = server.app.state.workspaces[0] + .pane_state(pane_id) + .expect("pane") + .attached_terminal_id + .clone(); + assert_eq!( + server + .app + .state + .terminals + .get(&terminal_id) + .expect("terminal") + .effective_custom_status() + .as_deref(), + Some("short lived") + ); + + assert!(server.handle_scheduled_tasks_headless(deadline + Duration::from_millis(1))); + + assert_eq!(server.app.agent_metadata_deadline, None); + assert_eq!( + server + .app + .state + .terminals + .get(&terminal_id) + .expect("terminal") + .effective_custom_status(), + None + ); + assert!(server + .app + .event_hub + .events_after(0) + .iter() + .any(|(_, event)| { + event.event == crate::api::schema::EventKind::PaneAgentStatusChanged + && matches!( + &event.data, + crate::api::schema::EventData::PaneAgentStatusChanged { + custom_status, + .. + } if custom_status.is_none() + ) + })); + } + + #[test] fn virtual_render_produces_nonempty_buffer() { let mut state = AppState::test_new(); let area = Rect::new(0, 0, 80, 24); |
