fix: prevent interrupt mode from replaying previous assistant reply#50147
fix: prevent interrupt mode from replaying previous assistant reply#50147nano-jason wants to merge 1 commit into
Conversation
When messages.queue.mode is 'interrupt', aborting an active run causes the previous turn's assistant reply to be re-sent to the user. Root cause: buildEmbeddedRunPayloads falls back to extractAssistantText(lastAssistant) when assistantTexts is empty. After an abort, assistantTexts is empty but lastAssistant still references the previous turn's message from session history. Fix: 1. Guard lastAssistant fallback: pass undefined when aborted and no new assistant text was generated (run.ts) 2. Skip blockReplyPipeline flush and payload delivery entirely when the run was aborted (agent-runner.ts) Fixes openclaw#50145
Greptile SummaryThis PR fixes a bug in interrupt queue mode ( The fix applies two complementary guards:
Notably, The only side effect worth noting is that Confidence Score: 5/5
Last reviewed commit: "fix: prevent interru..." |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a1f0cdba66
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (wasAborted) { | ||
| return finalizeWithFollowup(undefined, queueKey, runFollowupTurn); |
There was a problem hiding this comment.
Don't drop timeout payloads on aborted runs
This early return regresses the timeout path. In src/agents/pi-embedded-runner/run/attempt.ts:2231-2238, a timeout sets aborted = true, and src/agents/pi-embedded-runner/run.ts:1624-1649 deliberately synthesizes a user-facing timeout error payload when no reply was generated. Because this branch exits before payload delivery, any auto-reply turn that hits timeoutMs now becomes a silent/no-reply turn again instead of surfacing the timeout notice.
Useful? React with 👍 / 👎.
| if (wasAborted) { | ||
| return finalizeWithFollowup(undefined, queueKey, runFollowupTurn); |
There was a problem hiding this comment.
Keep post-compaction bookkeeping when aborting a turn
Returning here skips the autoCompactionCount handling later in this function. src/auto-reply/reply/agent-runner-execution.ts:475-483 still records completed compactions even if the run is later aborted, so an interrupt that lands after compaction will now bypass both incrementRunCompactionCount() and the readPostCompactionContext() injection at src/auto-reply/reply/agent-runner.ts:679-707. The next queued turn can therefore resume from a compacted session without the AGENTS refresh/startup reminder that normally protects post-compaction correctness.
Useful? React with 👍 / 👎.
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: yes. Source inspection on current main shows interrupt mode aborts active work, an aborted empty attempt can retain an older Real behavior proof Next step before merge Security Review findings
Review detailsBest possible solution: Keep the narrow stale Do we have a high-confidence way to reproduce the issue? Yes. Source inspection on current main shows interrupt mode aborts active work, an aborted empty attempt can retain an older Is this the best way to solve the issue? No. The Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 6a589017cab2. |
|
This pull request has been automatically marked as stale due to inactivity. |
|
Closing due to inactivity. |
Fixes #50145
Problem
When
messages.queue.modeis set to"interrupt", incoming messages that abort an active run cause the previous turn's assistant reply to be re-sent to the user before the new (correct) reply is delivered.Root Cause
buildEmbeddedRunPayloadsfalls back toextractAssistantText(lastAssistant)whenassistantTextsis empty. After an abort,assistantTextsis empty (model never generated new text), butlastAssistantstill references the previous turn's message frommessagesSnapshot(full session history). This stale text gets packaged as the current run's output and delivered to the user.Fix
Two changes (defense in depth):
1. Guard
lastAssistantfallback (run.ts)When the run was aborted and produced no new assistant text, pass
undefinedinstead of the stalelastAssistant:2. Early exit for aborted runs (
agent-runner.ts)blockReplyPipeline.flush()when aborted (buffer may contain stale content)wasAbortedis trueTesting
messages.queue.mode: "interrupt"