fix(tui): keep subagent panel out of transcript history

This commit is contained in:
Friel
2026-03-28 18:24:50 -07:00
parent 4ef8493fd2
commit 0af3f1f66e
2 changed files with 48 additions and 0 deletions
+8
View File
@@ -5495,6 +5495,14 @@ impl ChatWidget {
fn flush_active_cell(&mut self) {
if let Some(active) = self.active_cell.take() {
// Subagent status is a transient panel, not transcript history. If we
// flush it into history every time another cell is inserted, the
// transcript gets spammed with repeated identical "Subagents ..." blocks.
// Keep the panel mounted so later transcript cells do not make it disappear.
if active.as_any().is::<SubagentStatusCell>() {
self.active_cell = Some(active);
return;
}
self.needs_final_message_separator = true;
self.app_event_tx.send(AppEvent::InsertHistoryCell(active));
}
+40
View File
@@ -14,6 +14,9 @@ use crate::bottom_pane::FeedbackAudience;
use crate::bottom_pane::LocalImageAttachment;
use crate::bottom_pane::MentionBinding;
use crate::chatwidget::realtime::RealtimeConversationPhase;
use crate::history_cell::SubagentPanelAgent;
use crate::history_cell::SubagentPanelState;
use crate::history_cell::SubagentStatusCell;
use crate::history_cell::UserHistoryCell;
use crate::model_catalog::ModelCatalog;
use crate::test_backend::VT100Backend;
@@ -197,6 +200,7 @@ use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::Mutex as StdMutex;
use tempfile::NamedTempFile;
use tempfile::tempdir;
use tokio::sync::mpsc::error::TryRecvError;
@@ -2431,6 +2435,42 @@ fn status_line_text(chat: &ChatWidget) -> Option<String> {
chat.status_line_text()
}
async fn subagent_panel_is_not_flushed_into_transcript_history() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await;
let state = Arc::new(StdMutex::new(SubagentPanelState {
started_at: Instant::now(),
total_agents: 1,
running_count: 0,
running_agents: vec![SubagentPanelAgent {
ordinal: 1,
name: "user-request-derisk-implement".to_string(),
status: AgentStatus::PendingInit,
is_watchdog: true,
preview: "watchdog idle".to_string(),
latest_update_at: Instant::now(),
}],
}));
chat.on_subagent_panel_updated(Arc::new(SubagentStatusCell::new(state, true)));
chat.add_to_history(history_cell::new_error_event("follow-up cell".to_string()));
let inserted = drain_insert_history(&mut rx);
assert_eq!(
inserted.len(),
1,
"subagent panel should remain transient and not be inserted into transcript history"
);
let rendered = lines_to_single_string(&inserted[0]);
assert!(rendered.contains("follow-up cell"));
assert!(!rendered.contains("Subagents"));
assert!(
chat.active_cell
.as_ref()
.is_some_and(|cell| cell.as_any().is::<SubagentStatusCell>()),
"subagent panel should stay mounted after other history cells are inserted"
);
}
fn make_token_info(total_tokens: i64, context_window: i64) -> TokenUsageInfo {
fn usage(total_tokens: i64) -> TokenUsage {
TokenUsage {