Compact successful command activity in the TUI (#38921)

## What changed

- Group consecutive successful agent and unified-exec startup commands into a compact `Ran N commands` entry while preserving their full transcript.
- Flush command groups at interaction boundaries, after failures, and after 32 completed commands. Keep manual shell commands and failed or declined commands visible.
- Apply the same grouping rules when replaying thread history without duplicating command starts or disturbing unrelated active commands.

## Testing

- Add TUI coverage for live and replayed grouping, transcript preservation, failures, overlapping commands, group limits, and interaction boundaries.

GitOrigin-RevId: d6602a20201644012fcff3d6cecf4690024383a9
This commit is contained in:
Eric Traut authored and copyberry committed 2026-08-17 00:32:09 +00:00
1 parent 935b1c4e3d
commit 1f41cc5d92
18 files changed
+696 -76

No files matched your search

+24
View File
@@ -1207,6 +1207,9 @@ impl ChatWidget {
pub(crate) fn pre_draw_tick(&mut self) {
self.update_due_hook_visibility();
self.schedule_hook_timer_if_needed();
if self.bottom_pane.has_active_view() {
self.flush_completed_command_activity();
}
self.bottom_pane.pre_draw_tick();
if let Some(pet) = self.ambient_pet.as_ref() {
pet.schedule_next_frame();
@@ -1233,6 +1236,18 @@ impl ChatWidget {
}
}
fn flush_completed_command_activity(&mut self) {
if self
.transcript
.active_cell
.as_ref()
.and_then(|cell| cell.as_any().downcast_ref::<ExecCell>())
.is_some_and(|cell| !cell.is_active())
{
self.flush_active_cell();
}
}
pub(crate) fn add_to_history(&mut self, cell: impl HistoryCell + 'static) {
self.add_boxed_history(Box::new(cell));
}
@@ -1262,6 +1277,15 @@ impl ChatWidget {
self.flush_active_cell();
}
self.transcript.needs_final_message_separator = true;
} else if !keep_placeholder_header_active
&& self
.transcript
.active_cell
.as_ref()
.is_some_and(|active_cell| active_cell.as_any().is::<ExecCell>())
&& !cell.transcript_lines(history_width).is_empty()
{
self.flush_completed_command_activity();
}
self.app_event_tx.send(AppEvent::InsertHistoryCell(cell));
}