codex: address PR review feedback (#18290)

This commit is contained in:
Eric Traut
2026-04-16 22:52:17 -07:00
parent bda2d87fc7
commit a4c8483955
4 changed files with 101 additions and 5 deletions
+12 -5
View File
@@ -1076,6 +1076,7 @@ pub(crate) struct ThreadInputState {
active_collaboration_mask: Option<CollaborationModeMask>,
task_running: bool,
agent_turn_running: bool,
pending_standalone_user_shell_command: bool,
standalone_user_shell_turn_id: Option<String>,
}
@@ -2376,8 +2377,9 @@ impl ChatWidget {
}
}
fn is_standalone_user_shell_turn_running(&self) -> bool {
self.standalone_user_shell_turn_id.is_some() && self.bottom_pane.is_task_running()
fn is_standalone_user_shell_turn_pending_or_running(&self) -> bool {
self.pending_standalone_user_shell_command
|| (self.standalone_user_shell_turn_id.is_some() && self.bottom_pane.is_task_running())
}
fn on_task_complete(&mut self, last_agent_message: Option<String>, from_replay: bool) {
@@ -3289,6 +3291,7 @@ impl ChatWidget {
active_collaboration_mask: self.active_collaboration_mask.clone(),
task_running: self.bottom_pane.is_task_running(),
agent_turn_running: self.agent_turn_running,
pending_standalone_user_shell_command: self.pending_standalone_user_shell_command,
standalone_user_shell_turn_id: self.standalone_user_shell_turn_id.clone(),
})
}
@@ -3299,7 +3302,8 @@ impl ChatWidget {
self.current_collaboration_mode = input_state.current_collaboration_mode;
self.active_collaboration_mask = input_state.active_collaboration_mask;
self.agent_turn_running = input_state.agent_turn_running;
self.pending_standalone_user_shell_command = false;
self.pending_standalone_user_shell_command =
input_state.pending_standalone_user_shell_command;
self.standalone_user_shell_turn_id = input_state.standalone_user_shell_turn_id;
self.update_collaboration_mode_indicator();
self.refresh_model_dependent_surfaces();
@@ -5173,7 +5177,7 @@ impl ChatWidget {
}
let should_submit_now = self.is_session_configured()
&& !self.is_plan_streaming_in_tui()
&& !self.is_standalone_user_shell_turn_running();
&& !self.is_standalone_user_shell_turn_pending_or_running();
if should_submit_now {
// Submitted is emitted when user submits.
// Reset any reasoning header only when we are actually submitting a turn.
@@ -5394,7 +5398,10 @@ impl ChatWidget {
}
fn queue_user_message(&mut self, user_message: UserMessage) {
if !self.is_session_configured() || self.bottom_pane.is_task_running() {
if !self.is_session_configured()
|| self.bottom_pane.is_task_running()
|| self.is_standalone_user_shell_turn_pending_or_running()
{
self.queued_user_messages.push_back(user_message);
self.refresh_pending_input_preview();
} else {
@@ -801,6 +801,7 @@ async fn restore_thread_input_state_syncs_sleep_inhibitor_state() {
active_collaboration_mask: chat.active_collaboration_mask.clone(),
task_running: true,
agent_turn_running: true,
pending_standalone_user_shell_command: false,
standalone_user_shell_turn_id: None,
}));
@@ -815,6 +816,27 @@ async fn restore_thread_input_state_syncs_sleep_inhibitor_state() {
assert!(!chat.bottom_pane.is_task_running());
}
#[tokio::test]
async fn restore_thread_input_state_preserves_pending_standalone_shell_command() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
chat.restore_thread_input_state(Some(ThreadInputState {
composer: None,
pending_steers: VecDeque::new(),
rejected_steers_queue: VecDeque::new(),
queued_user_messages: VecDeque::new(),
current_collaboration_mode: chat.current_collaboration_mode.clone(),
active_collaboration_mask: chat.active_collaboration_mask.clone(),
task_running: false,
agent_turn_running: false,
pending_standalone_user_shell_command: true,
standalone_user_shell_turn_id: None,
}));
assert!(chat.pending_standalone_user_shell_command);
assert!(chat.standalone_user_shell_turn_id.is_none());
}
#[tokio::test]
async fn alt_up_edits_most_recent_queued_message() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
@@ -1093,6 +1093,72 @@ async fn enter_during_standalone_user_shell_command_queues_follow_up() {
}
}
#[tokio::test]
async fn enter_before_standalone_user_shell_turn_started_queues_follow_up() {
let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
chat.thread_id = Some(ThreadId::new());
chat.bottom_pane
.set_composer_text("!sleep 10".to_string(), Vec::new(), Vec::new());
chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
match op_rx.try_recv() {
Ok(Op::RunUserShellCommand { command }) => assert_eq!(command, "sleep 10"),
other => panic!("expected RunUserShellCommand op, got {other:?}"),
}
chat.bottom_pane
.set_composer_text("hi".to_string(), Vec::new(), Vec::new());
chat.handle_key_event(KeyEvent::new(KeyCode::Enter, KeyModifiers::NONE));
assert_eq!(chat.queued_user_message_texts(), vec!["hi"]);
assert!(chat.pending_steers.is_empty());
assert_matches!(op_rx.try_recv(), Err(TryRecvError::Empty));
chat.handle_server_notification(
ServerNotification::TurnStarted(TurnStartedNotification {
thread_id: "thread-1".to_string(),
turn: AppServerTurn {
id: "shell-turn".to_string(),
items: Vec::new(),
status: AppServerTurnStatus::InProgress,
error: None,
started_at: Some(0),
completed_at: None,
duration_ms: None,
},
}),
/*replay_kind*/ None,
);
chat.handle_server_notification(
ServerNotification::TurnCompleted(TurnCompletedNotification {
thread_id: "thread-1".to_string(),
turn: AppServerTurn {
id: "shell-turn".to_string(),
items: Vec::new(),
status: AppServerTurnStatus::Completed,
error: None,
started_at: None,
completed_at: Some(0),
duration_ms: None,
},
}),
/*replay_kind*/ None,
);
match next_submit_op(&mut op_rx) {
Op::UserTurn { items, .. } => assert_eq!(
items,
vec![UserInput::Text {
text: "hi".to_string(),
text_elements: Vec::new(),
}]
),
other => panic!("expected queued follow-up submit, got {other:?}"),
}
}
#[tokio::test]
async fn disabled_slash_command_while_task_running_snapshot() {
// Build a chat widget and simulate an active task
@@ -365,6 +365,7 @@ async fn restore_thread_input_state_restores_pending_steers_without_downgrading_
active_collaboration_mask: chat.active_collaboration_mask.clone(),
task_running: false,
agent_turn_running: false,
pending_standalone_user_shell_command: false,
standalone_user_shell_turn_id: None,
}));