mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Clear live hook rows when turns finalize (#20674)
# Why When a user interrupts a turn while a hook is still running, the normal turn status is cleared but the separate live hook row can remain visible as `Running` because the TUI may never receive a matching `HookCompleted` event before cancellation. Once the turn itself is finalized, that turn-scoped live state should not remain on screen. # What - clear any still-live `active_hook_cell` during turn finalization - add a regression snapshot covering an interrupted turn with a visible `PreToolUse` hook row # Testing - `cargo test -p codex-tui interrupted_turn_clears_visible_running_hook` - attempted `cargo test -p codex-tui` (currently aborts on unrelated existing stack overflow in `app::tests::discard_side_thread_removes_agent_navigation_entry`)
This commit is contained in:
committed by
GitHub
Unverified
parent
443f6b831e
commit
d55479488e
@@ -2938,6 +2938,12 @@ impl ChatWidget {
|
||||
fn finalize_turn(&mut self) {
|
||||
// Ensure any spinner is replaced by a red ✗ and flushed into history.
|
||||
self.finalize_active_cell_as_failed();
|
||||
// Turn-scoped hook rows are transient live state; once the turn is over,
|
||||
// do not leave an orphaned running row behind if no matching completion
|
||||
// event arrived before cancellation.
|
||||
if self.active_hook_cell.take().is_some() {
|
||||
self.bump_active_cell_revision();
|
||||
}
|
||||
// Reset running state and clear streaming buffers.
|
||||
self.user_turn_pending_start = false;
|
||||
self.agent_turn_running = false;
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
---
|
||||
source: tui/src/chatwidget/tests/status_and_layout.rs
|
||||
expression: "format!(\"before interrupt:\\n{before_interrupt}after interrupt:\\n{}\",\nactive_hook_blob(&chat))"
|
||||
---
|
||||
before interrupt:
|
||||
• Running PreToolUse hook: checking command policy
|
||||
after interrupt:
|
||||
<empty>
|
||||
@@ -1331,6 +1331,32 @@ async fn status_line_branch_refreshes_after_interrupt() {
|
||||
assert!(chat.status_line_branch_pending);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn interrupted_turn_clears_visible_running_hook() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
|
||||
handle_hook_started(
|
||||
&mut chat,
|
||||
hook_started_run(
|
||||
"pre-tool-use:0:/tmp/hooks.json",
|
||||
codex_app_server_protocol::HookEventName::PreToolUse,
|
||||
Some("checking command policy"),
|
||||
),
|
||||
);
|
||||
reveal_running_hooks(&mut chat);
|
||||
let before_interrupt = active_hook_blob(&chat);
|
||||
|
||||
handle_turn_interrupted(&mut chat, "turn-1");
|
||||
|
||||
assert_chatwidget_snapshot!(
|
||||
"interrupted_turn_clears_visible_running_hook",
|
||||
format!(
|
||||
"before interrupt:\n{before_interrupt}after interrupt:\n{}",
|
||||
active_hook_blob(&chat)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn status_line_fast_mode_renders_on_and_off() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
|
||||
Reference in New Issue
Block a user