From 934d44732c8803c13de3fcf8f7ee19bd3f2dedd2 Mon Sep 17 00:00:00 2001 From: can1357 Date: Mon, 8 Jun 2026 14:47:28 +0200 Subject: [PATCH] fix(coding-agent/tools): serialized ask tool batch execution to prevent selector clobbering - Set AskTool concurrency to exclusive so the tool runner executes ask calls serially. - Updated the changelog to document the hanging ask failure when multiple asks were triggered concurrently in one batch. --- packages/coding-agent/CHANGELOG.md | 1 + packages/coding-agent/src/tools/ask.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 3411f6528..58880e0e3 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -28,6 +28,7 @@ - Fixed clipboard-pasted images being rejected when steering or following up during compaction. Instead of bailing with "Retry after it completes to send images", the message and its images are now queued via `queueCompactionMessage` and forwarded to the session (steer/follow-up/prompt) when the compaction queue flushes. - Fixed edit tool result previews to show only current-file lines and collapse long inserted blocks instead of echoing removed content. - Fixed `generateDiffString` to omit the mid-skip `...` placeholder between two nearby edits, conveying the elided gap via the jump in line numbers instead (consistent with how leading/trailing context skips already render). The placeholder row was indistinguishable from a genuine `...` context line and wasted a row in compact previews. +- Fixed the `ask` tool hanging when the model emitted two `ask` calls in one tool batch. The interactive selector is a single shared UI surface (`ExtensionUiController.showHookSelector` has no queue and overwrites `ctx.hookSelector` on each call), so concurrent asks clobbered each other: the second stole focus and orphaned the first, whose select promise hung until the user aborted the whole turn (surfacing a stray `Ask input was cancelled`). `ask` now declares `concurrency: "exclusive"`, so the agent loop serializes the batch and each question's selector runs to completion. ## [15.10.4] - 2026-06-08 diff --git a/packages/coding-agent/src/tools/ask.ts b/packages/coding-agent/src/tools/ask.ts index 5ff09d52d..33f16cd00 100644 --- a/packages/coding-agent/src/tools/ask.ts +++ b/packages/coding-agent/src/tools/ask.ts @@ -407,6 +407,12 @@ export class AskTool implements AgentTool { readonly description: string; readonly parameters = askSchema; readonly strict = true; + // Run alone in its tool batch. The interactive selector/editor is a single + // shared UI surface (`ExtensionUiController.showHookSelector` has no queue and + // overwrites `ctx.hookSelector` on each call), so two concurrent `ask` calls + // would clobber each other: the second steals focus and orphans the first, + // whose promise then hangs until the user aborts the whole turn. + readonly concurrency = "exclusive"; readonly loadMode = "discoverable"; constructor(private readonly session: ToolSession) {