mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
Merge remote-tracking branch 'origin/tui-watchdog-timer-countdown' into repair/collab-stack-refresh-20260402
This commit is contained in:
@@ -13,6 +13,9 @@ pub(super) use crate::app_event_sender::AppEventSender;
|
||||
pub(super) use crate::bottom_pane::LocalImageAttachment;
|
||||
pub(super) use crate::bottom_pane::MentionBinding;
|
||||
pub(super) use crate::chatwidget::realtime::RealtimeConversationPhase;
|
||||
pub(super) use crate::history_cell::SubagentPanelAgent;
|
||||
pub(super) use crate::history_cell::SubagentPanelState;
|
||||
pub(super) use crate::history_cell::SubagentStatusCell;
|
||||
pub(super) use crate::history_cell::UserHistoryCell;
|
||||
pub(super) use crate::model_catalog::ModelCatalog;
|
||||
pub(super) use crate::test_backend::VT100Backend;
|
||||
@@ -203,6 +206,7 @@ pub(super) use std::collections::BTreeMap;
|
||||
pub(super) use std::collections::HashMap;
|
||||
pub(super) use std::collections::HashSet;
|
||||
pub(super) use std::path::PathBuf;
|
||||
pub(super) use std::sync::Mutex as StdMutex;
|
||||
pub(super) use tempfile::NamedTempFile;
|
||||
pub(super) use tempfile::tempdir;
|
||||
pub(super) use tokio::sync::mpsc::error::TryRecvError;
|
||||
|
||||
@@ -210,6 +210,7 @@ pub(super) async fn make_chatwidget_manual(
|
||||
pending_turn_copyable_output: None,
|
||||
running_commands: HashMap::new(),
|
||||
collab_agent_metadata: HashMap::new(),
|
||||
subagent_panel: None,
|
||||
pending_collab_spawn_requests: HashMap::new(),
|
||||
suppressed_exec_calls: HashSet::new(),
|
||||
skills_all: Vec::new(),
|
||||
@@ -286,9 +287,8 @@ pub(super) async fn make_chatwidget_manual(
|
||||
external_editor_state: ExternalEditorState::Closed,
|
||||
realtime_conversation: RealtimeConversationUiState::default(),
|
||||
last_rendered_user_message_event: None,
|
||||
last_non_retry_error: None,
|
||||
subagent_panel: None,
|
||||
last_replayed_agent_inbox_message: None,
|
||||
last_non_retry_error: None,
|
||||
};
|
||||
widget.set_model(&resolved_model);
|
||||
(widget, rx, op_rx)
|
||||
|
||||
@@ -111,6 +111,107 @@ async fn turn_started_uses_runtime_context_window_before_first_token_count() {
|
||||
"expected /status to avoid raw config context window, got: {context_line}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn subagent_panel_is_not_flushed_into_transcript_history() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ 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,
|
||||
watchdog_countdown_started_at: Some(Instant::now()),
|
||||
preview: "watchdog idle".to_string(),
|
||||
latest_update_at: Instant::now(),
|
||||
}],
|
||||
}));
|
||||
chat.on_subagent_panel_updated(Arc::new(SubagentStatusCell::new(
|
||||
Arc::clone(&state),
|
||||
/*animations_enabled*/ 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.subagent_panel
|
||||
.as_ref()
|
||||
.is_some_and(|panel| panel.matches_state(&state)),
|
||||
"subagent panel should stay mounted after other history cells are inserted"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn subagent_panel_mounts_while_placeholder_active_cell_exists_snapshot() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
chat.active_cell = Some(ChatWidget::placeholder_session_header_cell(
|
||||
chat.config_ref(),
|
||||
));
|
||||
chat.bottom_pane.set_composer_text(
|
||||
"show current subagent state".to_string(),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
);
|
||||
|
||||
let state = Arc::new(StdMutex::new(SubagentPanelState {
|
||||
started_at: Instant::now(),
|
||||
total_agents: 1,
|
||||
running_count: 0,
|
||||
running_agents: vec![SubagentPanelAgent {
|
||||
ordinal: 1,
|
||||
name: "watchdog-agent".to_string(),
|
||||
status: AgentStatus::PendingInit,
|
||||
is_watchdog: true,
|
||||
watchdog_countdown_started_at: Some(Instant::now()),
|
||||
preview: "watchdog idle".to_string(),
|
||||
latest_update_at: Instant::now(),
|
||||
}],
|
||||
}));
|
||||
chat.on_subagent_panel_updated(Arc::new(SubagentStatusCell::new(
|
||||
Arc::clone(&state),
|
||||
/*animations_enabled*/ false,
|
||||
)));
|
||||
|
||||
assert!(
|
||||
chat.active_cell
|
||||
.as_ref()
|
||||
.is_some_and(|cell| cell.as_any().is::<history_cell::SessionHeaderHistoryCell>()),
|
||||
"placeholder session header should remain the active cell"
|
||||
);
|
||||
assert!(
|
||||
chat.subagent_panel
|
||||
.as_ref()
|
||||
.is_some_and(|panel| panel.matches_state(&state)),
|
||||
"subagent panel should mount even when another active cell already exists"
|
||||
);
|
||||
|
||||
let width = 80;
|
||||
let height = chat.desired_height(width);
|
||||
let mut terminal =
|
||||
ratatui::Terminal::new(VT100Backend::new(width, height)).expect("create terminal");
|
||||
terminal.set_viewport_area(Rect::new(0, 0, width, height));
|
||||
terminal
|
||||
.draw(|f| chat.render(f.area(), f.buffer_mut()))
|
||||
.expect("render chat with placeholder header and subagent panel");
|
||||
|
||||
assert_chatwidget_snapshot!(
|
||||
"subagent_panel_mounts_while_placeholder_active_cell_exists",
|
||||
terminal.backend().vt100().screen().contents()
|
||||
);
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn helpers_are_available_and_do_not_panic() {
|
||||
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
||||
|
||||
Reference in New Issue
Block a user