Fix queued messages during /review (#9122)

Sending a message during /review interrupts the review, whereas during
normal operation, sending a message while the agent is running will
queue the message. This is unexpected behavior, and since /review
usually takes a while, it takes away a potentially useful operation.

Summary
- Treat review mode as an active task for message queuing so inputs
don’t inject into the running review turn.
- Prevents user submissions from rendering immediately in the transcript
while the review continues streaming.
- Keeps review UX consistent with normal “task running” behavior and
avoids accidental interrupt/replacement.

Notes
- This change only affects UI queuing logic; core review flow and task
lifecycle remain unchanged.
This commit is contained in:
charley-oai
2026-01-13 11:23:22 -08:00
committed by GitHub
parent 40e2405998
commit 57ba758df5
3 changed files with 64 additions and 4 deletions

View File

@@ -2077,7 +2077,7 @@ impl ChatWidget {
}
fn queue_user_message(&mut self, user_message: UserMessage) {
if self.bottom_pane.is_task_running() {
if self.bottom_pane.is_task_running() || self.is_review_mode {
self.queued_user_messages.push_back(user_message);
self.refresh_queued_user_messages();
} else {
@@ -2286,7 +2286,7 @@ impl ChatWidget {
}
}
EventMsg::EnteredReviewMode(review_request) => {
self.on_entered_review_mode(review_request)
self.on_entered_review_mode(review_request, from_replay)
}
EventMsg::ExitedReviewMode(review) => self.on_exited_review_mode(review),
EventMsg::ContextCompacted(_) => self.on_agent_message("Context compacted".to_owned()),
@@ -2300,11 +2300,15 @@ impl ChatWidget {
}
}
fn on_entered_review_mode(&mut self, review: ReviewRequest) {
fn on_entered_review_mode(&mut self, review: ReviewRequest, from_replay: bool) {
// Enter review mode and emit a concise banner
if self.pre_review_token_info.is_none() {
self.pre_review_token_info = Some(self.token_info.clone());
}
// Avoid toggling running state for replayed history events on resume.
if !from_replay && !self.bottom_pane.is_task_running() {
self.bottom_pane.set_task_running(true);
}
self.is_review_mode = true;
let hint = review
.user_facing_hint
@@ -3787,9 +3791,12 @@ impl ChatWidget {
self.bottom_pane.clear_esc_backtrack_hint();
}
/// Forward an `Op` directly to codex.
pub(crate) fn submit_op(&self, op: Op) {
pub(crate) fn submit_op(&mut self, op: Op) {
// Record outbound operation for session replay fidelity.
crate::session_log::log_outbound_op(&op);
if matches!(&op, Op::Review { .. }) && !self.bottom_pane.is_task_running() {
self.bottom_pane.set_task_running(true);
}
if let Err(e) = self.codex_op_tx.send(op) {
tracing::error!("failed to submit op: {e}");
}