← Back to PRs

#7758: fix: prevent opts closure reuse across messages in shared followup queue

by Alexwang-sol open 2026-02-03 05:34 View on GitHub →
stale
When multiple messages from the same session enter a shared followup queue, the queue runner (created by createFollowupRunner) captured opts in a closure. This caused all messages in that queue to reuse the first message's opts, leading to incorrect deliver callbacks being invoked. This fix stores opts directly in the FollowupRun object, ensuring each queued message carries its own reply options. The followup runner now prefers queued.opts over closure-captured opts, maintaining backwards compatibility while fixing the closure reuse issue. Changes: - Add opts field to FollowupRun type (queue/types.ts) - Pass opts when creating followupRun (get-reply-run.ts) - Use queued.opts ?? opts in followup runner (followup-runner.ts) Co-Authored-By: Claude Sonnet 4.5 Related Issues: - #4424 <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR fixes a subtle followup-queue bug where `createFollowupRunner` captured `opts` in a closure, causing multiple queued messages in a shared followup queue to reuse the first message’s callbacks (e.g., delivering replies via the wrong `onBlockReply`). It does this by adding an `opts` field to `FollowupRun`, populating it when enqueuing, and preferring `queued.opts ?? opts` when dispatching followup payloads. The change fits cleanly into the existing queue architecture: `get-reply-run.ts` constructs the `FollowupRun` object, `queue/types.ts` defines the queued payload shape, and `followup-runner.ts` is the executor that now picks per-message delivery options. <h3>Confidence Score: 4/5</h3> - This PR is likely safe to merge, with one remaining closure-capture inconsistency around typing heartbeat behavior. - The change is small and targeted (adds `FollowupRun.opts` and uses it for delivery), but `typingSignals` is still initialized from closure-captured `opts?.isHeartbeat`, which can reintroduce per-message behavior drift in shared queues. - src/auto-reply/reply/followup-runner.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs