fix(bridge): handle AskUserQuestion during continuation turns#275
Merged
Conversation
`handleContinuationTurn` renders the agent's response to an SDK-injected `<task-notification>` (background bash return etc.) as a fresh streaming card. Before this fix, if the agent invoked AskUserQuestion *inside* that continuation turn, the stream processor would set `state.pendingQuestion` but the loop body just kept updating the main card with the question text inline — no dedicated question card, no reply routing. The user's typed reply was treated as a fresh user turn that immediately blocked for 6 minutes on the still-hanging hook. Fix: reuse the standalone between-turn question pipeline from #274. When the continuation stream yields `waiting_for_input` + `pendingQuestion`: - update the main card with a "_Waiting for your answer to the question card below…_" hint (drops `pendingQuestion`, mirrors the pattern in runOneTurn) - call `handleBetweenTurnQuestion` to surface a dedicated v1 question card and register the toolUseId for reply interception in handleMessage - track surfaced toolUseIds in a per-stream Set so we don't re-send the card on every subsequent delta while the same question is still waiting Same `executor.resolveQuestion()` path unblocks the hook; the continuation stream then continues normally. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
SimonYeyi
pushed a commit
to SimonYeyi/metabot
that referenced
this pull request
May 26, 2026
…otics#275) `handleContinuationTurn` renders the agent's response to an SDK-injected `<task-notification>` (background bash return etc.) as a fresh streaming card. Before this fix, if the agent invoked AskUserQuestion *inside* that continuation turn, the stream processor would set `state.pendingQuestion` but the loop body just kept updating the main card with the question text inline — no dedicated question card, no reply routing. The user's typed reply was treated as a fresh user turn that immediately blocked for 6 minutes on the still-hanging hook. Fix: reuse the standalone between-turn question pipeline from xvirobotics#274. When the continuation stream yields `waiting_for_input` + `pendingQuestion`: - update the main card with a "_Waiting for your answer to the question card below…_" hint (drops `pendingQuestion`, mirrors the pattern in runOneTurn) - call `handleBetweenTurnQuestion` to surface a dedicated v1 question card and register the toolUseId for reply interception in handleMessage - track surfaced toolUseIds in a per-stream Set so we don't re-send the card on every subsequent delta while the same question is still waiting Same `executor.resolveQuestion()` path unblocks the hook; the continuation stream then continues normally. Co-authored-by: Flood Sung <floodsung@xvirobotics.ai> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
handleContinuationTurn— agent's response to an SDK-injected<task-notification>after a background task settles) didn't recognisestate.pendingQuestionfrom the stream processor. AskUserQuestion fired during a continuation turn rendered as inline text in the main card; the user's typed reply was treated as a fresh user turn that immediately blocked for 6 minutes on the still-hanging hook.handleMessage, route it viaexecutor.resolveQuestion()to unblock the hook so the continuation stream continues normally.What changed
src/bridge/message-bridge.ts— inside the stream loop inhandleContinuationTurn:state.status === 'waiting_for_input' && state.pendingQuestion:_Waiting for your answer to the question card below…_hint (dropspendingQuestion, same pattern asrunOneTurnat L1573-1586)handleBetweenTurnQuestion(chatId, { toolUseId, questions })— reuses the bookkeeping introduced in fix(bridge): surface between-turn AskUserQuestion as its own card #274 (pendingBetweenTurnQuestions), sohandleMessage's reply-interception path Just WorkstoolUseIds in a per-streamsurfacedQuestionIds: Set<string>so the card isn't re-sent on each subsequent delta while the same question is still waitingexecutor-removedcleanup (added in fix(bridge): surface between-turn AskUserQuestion as its own card #274) already handles the case where the executor is evicted while a continuation question is pending.Test plan
Automated:
npm run build— clean.npx vitest run— 298/298 pass.npm run lint— 0 errors (pre-existing warnings unrelated).Manual:
/resetshould mark the question card "canceled" and the continuation card "interrupted" (existing fix(bridge): surface between-turn AskUserQuestion as its own card #274 cleanup path).🤖 Generated with Claude Code