diff --git a/codex-rs/tui/src/app/agents_overview_grouping.rs b/codex-rs/tui/src/app/agents_overview_grouping.rs new file mode 100644 index 0000000000..aff9163ae7 --- /dev/null +++ b/codex-rs/tui/src/app/agents_overview_grouping.rs @@ -0,0 +1,39 @@ +//! Task grouping modes share model labels and group membership across rendering and navigation. + +use super::AgentsOverviewView; +use codex_app_server_protocol::Thread; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub(in super::super) enum AgentsOverviewGrouping { + #[default] + Project, + Status, + Model, +} + +pub(super) fn model_name(thread: &Thread) -> &str { + thread + .model + .as_deref() + .filter(|model| !model.is_empty()) + .unwrap_or("Unknown") +} + +impl AgentsOverviewView { + pub(super) fn same_group( + &self, + grouping: AgentsOverviewGrouping, + left: usize, + right: usize, + ) -> bool { + match grouping { + AgentsOverviewGrouping::Project => { + self.project_groups[left].key == self.project_groups[right].key + } + AgentsOverviewGrouping::Status => self.rows[left].group == self.rows[right].group, + AgentsOverviewGrouping::Model => { + model_name(&self.rows[left].thread) == model_name(&self.rows[right].thread) + } + } + } +} diff --git a/codex-rs/tui/src/app/agents_overview_input.rs b/codex-rs/tui/src/app/agents_overview_input.rs index d9d6edd9e4..680307c131 100644 --- a/codex-rs/tui/src/app/agents_overview_input.rs +++ b/codex-rs/tui/src/app/agents_overview_input.rs @@ -12,7 +12,7 @@ impl AgentsOverviewView { pub(super) fn handle_composer_key(&mut self, key: KeyEvent) { let mut state = self.state(); let offline = state.connection_notice.is_some(); - let status_grouping = state.status_grouping; + let grouping = state.grouping; if !offline && crate::key_hint::plain(KeyCode::Right).is_press(key) && state @@ -78,7 +78,7 @@ impl AgentsOverviewView { self.app_event_tx .send(AppEvent::DispatchAgentsOverviewTask { prompt, - cwd: (!status_grouping) + cwd: (grouping == AgentsOverviewGrouping::Project) .then(|| self.selected_row().map(|row| row.thread.cwd.clone())) .flatten(), }); diff --git a/codex-rs/tui/src/app/agents_overview_render.rs b/codex-rs/tui/src/app/agents_overview_render.rs index 82b51dc2c3..311783cb0f 100644 --- a/codex-rs/tui/src/app/agents_overview_render.rs +++ b/codex-rs/tui/src/app/agents_overview_render.rs @@ -95,7 +95,11 @@ impl AgentsOverviewView { add_hint( self.agents_keymap .primary_hint("toggle_grouping", &self.agents_keymap.toggle_grouping), - "group", + match self.state().grouping { + AgentsOverviewGrouping::Project => "group: project", + AgentsOverviewGrouping::Status => "group: status", + AgentsOverviewGrouping::Model => "group: model", + }, true, ); add_hint( diff --git a/codex-rs/tui/src/app/agents_overview_tests.rs b/codex-rs/tui/src/app/agents_overview_tests.rs index b4f2b59d48..7479011e46 100644 --- a/codex-rs/tui/src/app/agents_overview_tests.rs +++ b/codex-rs/tui/src/app/agents_overview_tests.rs @@ -1,3 +1,4 @@ +use super::super::agents_overview_view::AgentsOverviewGrouping; use super::*; #[tokio::test] @@ -1403,6 +1404,64 @@ async fn worktrees_overview_grouping_requires_feature() { } } +#[tokio::test] +async fn overview_model_grouping_shows_details_and_preserves_selection() { + let mut app = make_test_app().await; + let threads = [ + ("Older task", Some("model-a"), 1), + ("Other model", Some("model-b"), 2), + ("Recent task", Some("model-a"), 3), + ("Legacy task", None, 4), + ] + .into_iter() + .map(|(name, model, index)| { + let mut thread = overview_thread( + ThreadId::from_u128(index), + /*parent_thread_id*/ None, + name, + ThreadStatus::Idle, + ); + thread.model = model.map(str::to_string); + thread.updated_at = index as i64; + thread + }) + .collect(); + let selected = ThreadId::from_u128(/*value*/ 1); + let mut view = app.agents_overview_view(threads, Some(selected)); + view.handle_key_event(KeyCode::Esc.into()); + for _ in 0..2 { + view.handle_key_event(KeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL)); + } + assert_eq!( + app.agents_overview.view_state.lock().unwrap().grouping, + AgentsOverviewGrouping::Model + ); + assert_eq!( + view.rows[view.selected_index().unwrap()].thread_id, + selected + ); + // Within a model, newer tasks come first; navigation then crosses model groups. + for (key, expected) in [ + (KeyCode::Up, 3), + (KeyCode::Down, 1), + (KeyCode::Down, 2), + (KeyCode::Down, 4), + ] { + view.handle_key_event(key.into()); + assert_eq!( + view.rows[view.selected_index().unwrap()].thread_id, + ThreadId::from_u128(expected) + ); + } + app.chat_widget.show_bottom_pane_view(Box::new(view)); + insta::assert_snapshot!( + "agents_overview_model_grouping", + render_bottom_popup(&app.chat_widget, /*width*/ 100) + .replace(&test_path_display("/tmp/project"), "/tmp/project") + .replace("fwd del", "del") + ); +} + #[tokio::test] async fn shared_overview_shows_only_root_sessions() { assert_eq!( @@ -1466,12 +1525,21 @@ async fn shared_overview_shows_only_root_sessions() { Arc::clone(&app.agents_overview.view_state), ); let state = &app.agents_overview.view_state; - assert!(!state.lock().unwrap().status_grouping); + assert_eq!( + state.lock().unwrap().grouping, + AgentsOverviewGrouping::Project + ); action_view.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); action_view.handle_key_event(KeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL)); - assert!(state.lock().unwrap().status_grouping); + assert_eq!( + state.lock().unwrap().grouping, + AgentsOverviewGrouping::Status + ); app.agents_overview_view(Vec::new(), /*selected_thread_id*/ None); - assert!(state.lock().unwrap().status_grouping); + assert_eq!( + state.lock().unwrap().grouping, + AgentsOverviewGrouping::Status + ); assert!( action_view.handle_paste("Use \u{1b}[31mthe\u{1b}[0m current project\u{7}".to_string()) ); @@ -1483,6 +1551,23 @@ async fn shared_overview_shows_only_root_sessions() { )); action_view.handle_key_event(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)); action_view.handle_key_event(KeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL)); + assert_eq!( + state.lock().unwrap().grouping, + AgentsOverviewGrouping::Model + ); + assert!(action_view.handle_paste("Use the default project".to_string())); + action_view.handle_key_event(KeyCode::Enter.into()); + assert!(matches!( + event_rx.try_recv(), + Ok(AppEvent::DispatchAgentsOverviewTask { prompt, cwd: None }) + if prompt.text == "Use the default project" + )); + action_view.handle_key_event(KeyCode::Esc.into()); + action_view.handle_key_event(KeyEvent::new(KeyCode::Char('s'), KeyModifiers::CONTROL)); + assert_eq!( + state.lock().unwrap().grouping, + AgentsOverviewGrouping::Project + ); assert!(action_view.handle_paste("Fix the flaky tests after all retries complete".to_string())); let area = ratatui::layout::Rect::new( /*x*/ 0, /*y*/ 0, /*width*/ 40, /*height*/ 12, diff --git a/codex-rs/tui/src/app/agents_overview_threads.rs b/codex-rs/tui/src/app/agents_overview_threads.rs index ec2d31654f..78cf416443 100644 --- a/codex-rs/tui/src/app/agents_overview_threads.rs +++ b/codex-rs/tui/src/app/agents_overview_threads.rs @@ -86,6 +86,7 @@ impl App { ServerNotification::ThreadSettingsUpdated(settings) => { if let Some(thread) = thread { thread.cwd.clone_from(&settings.thread_settings.cwd); + thread.model = Some(settings.thread_settings.model.clone()); thread .model_provider .clone_from(&settings.thread_settings.model_provider); diff --git a/codex-rs/tui/src/app/agents_overview_view.rs b/codex-rs/tui/src/app/agents_overview_view.rs index 034bb41099..c4f3f64d1d 100644 --- a/codex-rs/tui/src/app/agents_overview_view.rs +++ b/codex-rs/tui/src/app/agents_overview_view.rs @@ -1,11 +1,16 @@ //! Dashboard for inspecting and managing the TUI's retained daemon tasks. //! The shared view state retains the new-task editor across metadata refreshes. +#[path = "agents_overview_grouping.rs"] +mod grouping; #[path = "agents_overview_input.rs"] mod input; #[path = "agents_overview_render.rs"] mod render; +pub(super) use grouping::AgentsOverviewGrouping; +use grouping::model_name; + use super::agents_overview::AGENTS_OVERVIEW_VIEW_ID; use super::agents_overview_details::AgentsOverviewDetails; use crate::app_event::AgentsOverviewAction; @@ -138,7 +143,7 @@ pub(super) struct AgentsOverviewViewState { pub(super) server_version_notice: Option, search: String, searching: bool, - pub(super) status_grouping: bool, + pub(super) grouping: AgentsOverviewGrouping, pub(super) renaming: bool, // The picker can finish this retained view when it selects the already active session. pub(super) completion: Option, @@ -281,13 +286,20 @@ impl AgentsOverviewView { (search.is_empty() || searchable.contains(&search)).then_some(index) }) .collect::>(); - if !state.status_grouping { - visible.sort_by_key(|index| { + match state.grouping { + AgentsOverviewGrouping::Project => visible.sort_by_key(|index| { ( &self.project_groups[*index].key, std::cmp::Reverse(self.rows[*index].thread.updated_at), ) - }); + }), + AgentsOverviewGrouping::Status => {} + AgentsOverviewGrouping::Model => visible.sort_by_key(|index| { + ( + model_name(&self.rows[*index].thread), + std::cmp::Reverse(self.rows[*index].thread.updated_at), + ) + }), } visible } @@ -367,11 +379,7 @@ impl AgentsOverviewView { fn render_rows(&self, area: Rect, buf: &mut Buffer) { let mut offset = 0; let mut previous_group_index: Option = None; - let project_grouping = !self - .state - .lock() - .unwrap_or_else(PoisonError::into_inner) - .status_grouping; + let grouping = self.state().grouping; let visible = self.visible_indices(); let mut first = visible .iter() @@ -381,13 +389,7 @@ impl AgentsOverviewView { while first > 0 { let previous_index = visible[first - 1]; let current_index = visible[first]; - let previous = &self.rows[previous_index]; - let current = &self.rows[current_index]; - let group_changed = if project_grouping { - self.project_groups[previous_index].key != self.project_groups[current_index].key - } else { - previous.group != current.group - }; + let group_changed = !self.same_group(grouping, previous_index, current_index); let added_height = 1 + 2 * u16::from(group_changed); if height + added_height > area.height { break; @@ -400,18 +402,15 @@ impl AgentsOverviewView { break; } let row = &self.rows[index]; - let group = if project_grouping { - self.project_groups[index].heading.display().to_string() - } else { - row.group.label().to_string() - }; - let group_changed = previous_group_index.is_none_or(|previous_index| { - if project_grouping { - self.project_groups[previous_index].key != self.project_groups[index].key - } else { - self.rows[previous_index].group != row.group + let group = match grouping { + AgentsOverviewGrouping::Project => { + self.project_groups[index].heading.display().to_string() } - }); + AgentsOverviewGrouping::Status => row.group.label().to_string(), + AgentsOverviewGrouping::Model => model_name(&row.thread).to_string(), + }; + let group_changed = previous_group_index + .is_none_or(|previous_index| !self.same_group(grouping, previous_index, index)); if group_changed { offset += u16::from(previous_group_index.is_some()); if offset >= area.height { @@ -421,13 +420,8 @@ impl AgentsOverviewView { .rows .iter() .enumerate() - .filter(|(candidate_index, candidate)| { - if project_grouping { - self.project_groups[*candidate_index].key - == self.project_groups[index].key - } else { - candidate.group == row.group - } + .filter(|(candidate_index, _)| { + self.same_group(grouping, *candidate_index, index) }) .count(); Line::from(vec![group.clone().bold(), format!(" {count}").dim()]) @@ -453,7 +447,7 @@ impl AgentsOverviewView { Span::styled(display_title(&row.thread), self.title_style(row.thread_id)), current.dim(), ]; - if project_grouping { + if grouping != AgentsOverviewGrouping::Status { spans.extend([" ".into(), status.dim()]); } Line::from(spans).render(Rect::new(area.x, area.y + offset, area.width, 1), buf); @@ -481,6 +475,10 @@ impl AgentsOverviewView { Line::default(), Line::from("Project".dim()), Line::from(row.thread.cwd.display().to_string()), + Line::from(vec![ + "Model: ".dim(), + model_name(&row.thread).to_string().into(), + ]), ]; if let Some(branch) = row .thread @@ -692,7 +690,11 @@ impl BottomPaneView for AgentsOverviewView { } if self.agents_keymap.toggle_grouping.is_pressed(key) { let mut state = self.state(); - state.status_grouping = !state.status_grouping; + state.grouping = match state.grouping { + AgentsOverviewGrouping::Project => AgentsOverviewGrouping::Status, + AgentsOverviewGrouping::Status => AgentsOverviewGrouping::Model, + AgentsOverviewGrouping::Model => AgentsOverviewGrouping::Project, + }; return; } if self.agents_keymap.new_task.is_pressed(key) { diff --git a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__actions__agents_custom_lifecycle_chords.snap b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__actions__agents_custom_lifecycle_chords.snap index 8e272d5b0b..b28a1047c9 100644 --- a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__actions__agents_custom_lifecycle_chords.snap +++ b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__actions__agents_custom_lifecycle_chords.snap @@ -1,6 +1,6 @@ --- source: tui/src/app/agents_overview_actions_tests.rs -expression: "render_bottom_popup(&app.chat_widget, 48)" +expression: "render_bottom_popup(&app.chat_widget,\n48).replace(&test_path_display(\"/tmp/project\"), \"/tmp/project\")" --- Agent command center 0 need input 0 working 1 ready @@ -17,12 +17,12 @@ expression: "render_bottom_popup(&app.chat_widget, 48)" - New task › Describe a new task ↑↓ navigate ctrl+o resume → open - ctrl+n new task ctrl+f search ctrl+s group - ctrl+r rename ctrl+x stop f5 f8 hide - f5 f6 archive f5 f7 delete esc back + ctrl+n new task ctrl+f search + ctrl+s group: project ctrl+r rename + ctrl+x stop f5 f8 hide f5 f6 archive + f5 f7 delete esc back diff --git a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown.snap b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown.snap index 8e74576624..f817fbe01a 100644 --- a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown.snap +++ b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown.snap @@ -22,6 +22,7 @@ expression: "cached.replace(&format!(\"{project} 1\"),\n&format!(\"/tmp/project " │ " " │ Project " " │ /tmp/project " +" │ Model: Unknown " " │ " " │ Prompt " " │ Review parser and token handling. " @@ -36,7 +37,6 @@ expression: "cached.replace(&format!(\"{project} 1\"),\n&format!(\"/tmp/project " │ " " │ " " │ " -" │ " " New task " " " "› Describe a new task " diff --git a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown_long_lines.snap b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown_long_lines.snap index fe24d76733..5cddd57bb2 100644 --- a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown_long_lines.snap +++ b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown_long_lines.snap @@ -12,11 +12,11 @@ expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{proj │ │ Last message │ let explanation = "A long code line - │ should wrap inside the task details - │ panel."; + │ … │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ long prompt long prompt long prompt diff --git a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown_table.snap b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown_table.snap index 4996dbacff..54f427419d 100644 --- a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown_table.snap +++ b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_markdown_table.snap @@ -12,11 +12,11 @@ expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{proj │ │ Last message │ Check Result - │ ━━━━━━━━ ━━━━━━━━ - │ Parser Fixed + │ … │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ long prompt long prompt long prompt diff --git a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_model_grouping.snap b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_model_grouping.snap new file mode 100644 index 0000000000..50d1d944fe --- /dev/null +++ b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__agents_overview_model_grouping.snap @@ -0,0 +1,28 @@ +--- +source: tui/src/app/agents_overview_tests.rs +expression: "render_bottom_popup(&app.chat_widget,\n100).replace(&test_path_display(\"/tmp/project\"),\n\"/tmp/project\").replace(\"fwd del\", \"del\")" +--- + Agent command center + 0 need input 0 working 4 ready + ──────────────────────────────────────────────────────────────────────────────────────────────── + Unknown 1 │ Task details + › ○ Legacy task Ready │ + │ Legacy task + model-a 2 │ ○ Ready + ○ Recent task Ready │ + ○ Older task Ready │ Project + │ /tmp/project + model-b 1 │ Model: Unknown + ○ Other model Ready │ + │ Prompt + │ Legacy task + │ + │ + │ + │ + New task + +› Describe a new task + + ↑↓ navigate ctrl+o resume → open ctrl+n new task ctrl+f search ctrl+s group: model ctrl+r rename + ctrl+x stop ctrl+w hide ctrl+e archive del delete esc back diff --git a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__overview_reopened_with_list_focus.snap b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__overview_reopened_with_list_focus.snap index ab2e1eae4b..79120030f5 100644 --- a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__overview_reopened_with_list_focus.snap +++ b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__overview_reopened_with_list_focus.snap @@ -1,6 +1,5 @@ --- source: tui/src/app/agents_overview_tests.rs -assertion_line: 314 expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{project} 2\"),\n&group).replace(&project, \"/tmp/project\").replace(\"fwd del\", \"del\")" --- Agent command center @@ -13,6 +12,7 @@ expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{proj │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ Second task @@ -20,10 +20,9 @@ expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{proj │ │ │ - │ New task › Unsent draft - ↑↓ navigate ctrl+o resume → open ctrl+n new task ctrl+f search ctrl+s group ctrl+r rename - ctrl+x stop ctrl+w hide ctrl+e archive del delete esc back + ↑↓ navigate ctrl+o resume → open ctrl+n new task ctrl+f search ctrl+s group: project + ctrl+r rename ctrl+x stop ctrl+w hide ctrl+e archive del delete esc back diff --git a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__overview_right_open_hint.snap b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__overview_right_open_hint.snap index 4ddb6123e8..85a456fe02 100644 --- a/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__overview_right_open_hint.snap +++ b/codex-rs/tui/src/app/snapshots/codex_tui__app__agents_overview__tests__overview_right_open_hint.snap @@ -2,4 +2,4 @@ source: tui/src/app/agents_overview_tests.rs expression: "rendered.lines().find(|line| line.contains(\"open\")).unwrap()" --- - ↑↓ navigate ctrl+o resume → open ctrl+n new task ctrl+f search ctrl+s group ctrl+r rename + ↑↓ navigate ctrl+o resume → open ctrl+n new task ctrl+f search ctrl+s group: project diff --git a/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_failed.snap b/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_failed.snap index 3c29537e8a..5b2bfd1d02 100644 --- a/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_failed.snap +++ b/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_failed.snap @@ -12,6 +12,7 @@ expression: "render_bottom_popup(&app.chat_widget, 100)" │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ Selected task @@ -20,7 +21,6 @@ expression: "render_bottom_popup(&app.chat_widget, 100)" │ │ │ - │ New task › Keep this task draft! diff --git a/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_reconnecting.snap b/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_reconnecting.snap index 73efe2e3c5..7ba8cdaf08 100644 --- a/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_reconnecting.snap +++ b/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_reconnecting.snap @@ -12,6 +12,7 @@ expression: "render_bottom_popup(&app.chat_widget, 100)" │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ Selected task @@ -20,7 +21,6 @@ expression: "render_bottom_popup(&app.chat_widget, 100)" │ │ │ - │ New task › Keep this task draft! diff --git a/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_vanished_rename.snap b/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_vanished_rename.snap index 112848c292..e7b1664d6a 100644 --- a/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_vanished_rename.snap +++ b/codex-rs/tui/src/app/tests/snapshots/codex_tui__app__tests__navigation_reconnect__daemon_command_center_vanished_rename.snap @@ -12,6 +12,7 @@ expression: "render_bottom_popup(&app.chat_widget, 100)" │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ New task @@ -20,7 +21,6 @@ expression: "render_bottom_popup(&app.chat_widget, 100)" │ │ │ - │ New task › Describe a new task diff --git a/codex-rs/tui/src/keymap_setup/actions.rs b/codex-rs/tui/src/keymap_setup/actions.rs index 761677d653..89181adf77 100644 --- a/codex-rs/tui/src/keymap_setup/actions.rs +++ b/codex-rs/tui/src/keymap_setup/actions.rs @@ -221,7 +221,7 @@ pub(super) const KEYMAP_ACTIONS: &[KeymapActionDescriptor] = &[ action("agents", "Agents", "archive", "Archive the selected task and its child agents."), action("agents", "Agents", "delete", "Permanently delete the selected task and its child agents."), action("agents", "Agents", "hide", "Hide the selected task until explicitly resumed."), - action("agents", "Agents", "toggle_grouping", "Group tasks by status or project."), + action("agents", "Agents", "toggle_grouping", "Cycle task grouping by project, status, or model."), action("approval", "Approval", "open_fullscreen", "Open approval details fullscreen."), action("approval", "Approval", "open_thread", "Open the approval source thread when available."), action("approval", "Approval", "approve", "Approve the primary option."), diff --git a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview.snap b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview.snap index 184ef30929..2ff62c6bd7 100644 --- a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview.snap +++ b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview.snap @@ -16,10 +16,10 @@ expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{proj │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ Build the dashboard - │ New task › First line diff --git a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_attention.snap b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_attention.snap index d5d44aa746..63b8f8a481 100644 --- a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_attention.snap +++ b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_attention.snap @@ -13,11 +13,11 @@ expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{proj │ Agent: Check dependencies │ Which dependency version should I use? │ Open task to review. - │ Waiting for approval. - │ Waiting for your response. + │ … │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ Repair authentication diff --git a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_empty_narrow.snap b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_empty_narrow.snap index b1aac35b4e..3d0ece6104 100644 --- a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_empty_narrow.snap +++ b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_empty_narrow.snap @@ -1,7 +1,6 @@ --- source: tui/src/app/agents_overview_tests.rs -assertion_line: 2041 -expression: "render_bottom_popup(&app.chat_widget, 48)" +expression: rendered --- Agent command center 0 need input 0 working 0 ready @@ -18,12 +17,12 @@ expression: "render_bottom_popup(&app.chat_widget, 48)" - New task › Describe a new task ↑↓ navigate ctrl+o resume → open - ctrl+n new task ctrl+f search ctrl+s group - ctrl+r rename ctrl+x stop ctrl+w hide - ctrl+e archive del delete esc back + ctrl+n new task ctrl+f search + ctrl+s group: project ctrl+r rename + ctrl+x stop ctrl+w hide ctrl+e archive + del delete esc back diff --git a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_last_message.snap b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_last_message.snap index 4efc045fb0..2484674f0f 100644 --- a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_last_message.snap +++ b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_last_message.snap @@ -12,11 +12,11 @@ expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{proj │ │ Last message │ Found the regression in the parser. - │ Found the regression in the parser. │ … │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ Investigate parser diff --git a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_live_activity.snap b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_live_activity.snap index 1266cc264f..eeee9fb409 100644 --- a/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_live_activity.snap +++ b/codex-rs/tui/src/snapshots/codex_tui__app__agents_overview__tests__agents_overview_live_activity.snap @@ -15,12 +15,12 @@ expression: "render_bottom_popup(&app.chat_widget,\n96).replace(&format!(\"{proj │ │ Project │ /tmp/project + │ Model: Unknown │ │ Prompt │ No prompt available. │ │ - │ New task › Keep this draft diff --git a/codex-rs/tui/src/snapshots/codex_tui__keymap_setup__tests__keymap_picker_agents_actions.snap b/codex-rs/tui/src/snapshots/codex_tui__keymap_setup__tests__keymap_picker_agents_actions.snap index 47a1d310cf..bb6866291e 100644 --- a/codex-rs/tui/src/snapshots/codex_tui__keymap_setup__tests__keymap_picker_agents_actions.snap +++ b/codex-rs/tui/src/snapshots/codex_tui__keymap_setup__tests__keymap_picker_agents_actions.snap @@ -1,6 +1,5 @@ --- source: tui/src/keymap_setup.rs -assertion_line: 1039 expression: agents --- Resume | ctrl-o | Agents resume Resume Open the session resume picker. ctrl-o Default @@ -11,4 +10,4 @@ Stop | ctrl-x | Agents stop Stop Stop the selected running task. ctrl-x Default Archive | ctrl-e | Agents archive Archive Archive the selected task and its child agents. ctrl-e Default Delete | delete | Agents delete Delete Permanently delete the selected task and its child agents. delete Default Hide | ctrl-w | Agents hide Hide Hide the selected task until explicitly resumed. ctrl-w Default -Toggle Grouping | ctrl-s | Agents toggle_grouping Toggle Grouping Group tasks by status or project. ctrl-s Default +Toggle Grouping | ctrl-s | Agents toggle_grouping Toggle Grouping Cycle task grouping by project, status, or model. ctrl-s Default