diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-17 16:08:43 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-17 16:08:43 +0300 |
| commit | 54490254f70469cd154ee630bc4bec84da178f0c (patch) | |
| tree | 450bf0397398b28932f636d33e37f73c011dd19d /src/app/actions.rs | |
| parent | d998753efe506a04c80306795efc72bff60bb0ec (diff) | |
feat: sort agent panel by priority
refs #318
Diffstat (limited to 'src/app/actions.rs')
| -rw-r--r-- | src/app/actions.rs | 95 |
1 files changed, 67 insertions, 28 deletions
diff --git a/src/app/actions.rs b/src/app/actions.rs index 9df07af5..1e0f0f5e 100644 --- a/src/app/actions.rs +++ b/src/app/actions.rs @@ -951,12 +951,6 @@ impl AppState { let workspace_id = self.workspaces[idx].id.clone(); crate::logging::workspace_focused(&workspace_id); self.mark_session_dirty(); - if matches!( - self.agent_panel_scope, - crate::app::state::AgentPanelScope::CurrentWorkspace - ) { - self.agent_panel_scroll = 0; - } self.ensure_workspace_visible(idx); if let Some(ws) = self.workspaces.get_mut(idx) { let active_tab = ws.active_tab; @@ -994,14 +988,6 @@ impl AppState { crate::logging::workspace_focused(&workspace_id); } self.mark_session_dirty(); - if workspace_changed - && matches!( - self.agent_panel_scope, - crate::app::state::AgentPanelScope::CurrentWorkspace - ) - { - self.agent_panel_scroll = 0; - } self.ensure_workspace_visible(ws_idx); if let Some(ws) = self.workspaces.get_mut(ws_idx) { ws.switch_tab(tab_idx); @@ -2587,6 +2573,12 @@ impl AppState { self.mark_session_dirty(); } let change = mutation.effective_state_change?; + if change.previous_state != change.state { + self.next_agent_state_change_seq += 1; + if let Some(terminal) = self.terminals.get_mut(&terminal_id) { + terminal.last_agent_state_change_seq = Some(self.next_agent_state_change_seq); + } + } let seen = self.apply_pane_state_change(ws_idx, pane_id, &change)?; let update = PaneStateUpdate { pane_id, @@ -3542,6 +3534,16 @@ mod tests { } fn mark_agent(state: &mut AppState, ws_idx: usize, tab_idx: usize, pane_id: PaneId) { + set_agent_state(state, ws_idx, tab_idx, pane_id, AgentState::Idle); + } + + fn set_agent_state( + state: &mut AppState, + ws_idx: usize, + tab_idx: usize, + pane_id: PaneId, + agent_state: AgentState, + ) { state.ensure_test_terminals(); let terminal_id = state.workspaces[ws_idx].tabs[tab_idx] .panes @@ -3550,12 +3552,28 @@ mod tests { .attached_terminal_id .clone(); if let Some(terminal) = state.terminals.get_mut(&terminal_id) { - terminal.set_detected_state(Some(Agent::Pi), AgentState::Idle); + terminal.set_detected_state(Some(Agent::Pi), agent_state); } } + fn transition_agent_state(state: &mut AppState, pane_id: PaneId, agent_state: AgentState) { + state + .update_terminal_state(pane_id, |terminal| { + Some(terminal.set_detected_state_with_screen_signals_at( + Some(Agent::Pi), + agent_state, + matches!(agent_state, AgentState::Blocked), + false, + false, + false, + std::time::Instant::now(), + )) + }) + .expect("agent state transition should update pane state"); + } + #[test] - fn next_agent_cycles_agent_panel_entries_in_all_scope() { + fn next_agent_cycles_agent_panel_entries() { let mut first = Workspace::test_new("one"); let first_root = first.tabs[0].root_pane; let first_second = first.test_split(Direction::Horizontal); @@ -3569,7 +3587,6 @@ mod tests { state.active = Some(0); state.selected = 0; state.mode = Mode::Terminal; - state.agent_panel_scope = crate::app::state::AgentPanelScope::AllWorkspaces; mark_agent(&mut state, 0, 0, first_root); mark_agent(&mut state, 0, 0, first_second); mark_agent(&mut state, 1, 0, second_root); @@ -3602,7 +3619,6 @@ mod tests { state.active = Some(0); state.selected = 0; state.mode = Mode::Terminal; - state.agent_panel_scope = crate::app::state::AgentPanelScope::AllWorkspaces; mark_agent(&mut state, 0, 0, first_root); mark_agent(&mut state, 0, 0, first_second); mark_agent(&mut state, 1, 0, second_root); @@ -3618,7 +3634,6 @@ mod tests { fn focus_agent_entry_succeeds_for_already_focused_agent() { let mut state = app_with_workspaces(&["one"]); let root = state.workspaces[0].tabs[0].root_pane; - state.agent_panel_scope = crate::app::state::AgentPanelScope::AllWorkspaces; mark_agent(&mut state, 0, 0, root); assert!(state.focus_agent_entry(0)); @@ -3628,11 +3643,11 @@ mod tests { } #[test] - fn next_agent_cycles_only_current_scope_entries() { + fn next_agent_cycles_priority_sorted_agent_panel_entries() { let mut first = Workspace::test_new("one"); let first_root = first.tabs[0].root_pane; let first_second = first.test_split(Direction::Horizontal); - first.tabs[0].layout.focus_pane(first_second); + first.tabs[0].layout.focus_pane(first_root); let second = Workspace::test_new("two"); let second_root = second.tabs[0].root_pane; @@ -3642,15 +3657,40 @@ mod tests { state.active = Some(0); state.selected = 0; state.mode = Mode::Terminal; - state.agent_panel_scope = crate::app::state::AgentPanelScope::CurrentWorkspace; - mark_agent(&mut state, 0, 0, first_root); - mark_agent(&mut state, 0, 0, first_second); - mark_agent(&mut state, 1, 0, second_root); + state.agent_panel_sort = crate::app::state::AgentPanelSort::Priority; + set_agent_state(&mut state, 0, 0, first_root, AgentState::Idle); + set_agent_state(&mut state, 0, 0, first_second, AgentState::Working); + set_agent_state(&mut state, 1, 0, second_root, AgentState::Blocked); state.next_agent(); - assert_eq!(state.active, Some(0)); - assert_eq!(state.workspaces[0].focused_pane_id(), Some(first_root)); + assert_eq!(state.active, Some(1)); + assert_eq!(state.workspaces[1].focused_pane_id(), Some(second_root)); + state.assert_invariants_for_test(); + } + + #[test] + fn priority_sort_keeps_recently_changed_idle_agent_above_older_idle_agent() { + let mut workspace = Workspace::test_new("one"); + let first = workspace.tabs[0].root_pane; + let second = workspace.test_split(Direction::Horizontal); + workspace.tabs[0].layout.focus_pane(first); + + let mut state = AppState::test_new(); + state.workspaces = vec![workspace]; + state.ensure_test_terminals(); + state.active = Some(0); + state.selected = 0; + state.mode = Mode::Terminal; + state.agent_panel_sort = crate::app::state::AgentPanelSort::Priority; + + transition_agent_state(&mut state, first, AgentState::Idle); + transition_agent_state(&mut state, second, AgentState::Working); + assert_eq!(crate::ui::agent_panel_entries(&state)[0].pane_id, second); + + transition_agent_state(&mut state, second, AgentState::Idle); + + assert_eq!(crate::ui::agent_panel_entries(&state)[0].pane_id, second); state.assert_invariants_for_test(); } @@ -3668,7 +3708,6 @@ mod tests { state.active = Some(0); state.selected = 0; state.mode = Mode::Terminal; - state.agent_panel_scope = crate::app::state::AgentPanelScope::CurrentWorkspace; for tab_idx in 0..state.workspaces[0].tabs.len() { let pane_id = state.workspaces[0].tabs[tab_idx].root_pane; mark_agent(&mut state, 0, tab_idx, pane_id); |
