Skip to content

Commit 08d7f80

Browse files
authored
Fix message queue re-queue loop in Task.ask() (#7823)
1 parent 03709fd commit 08d7f80

File tree

8 files changed

+58
-3
lines changed

8 files changed

+58
-3
lines changed

src/core/task/Task.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -845,9 +845,19 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
845845
const message = this.messageQueueService.dequeueMessage()
846846

847847
if (message) {
848-
setTimeout(async () => {
849-
await this.submitUserMessage(message.text, message.images)
850-
}, 0)
848+
// Check if this is a tool approval ask that needs to be handled
849+
if (
850+
type === "tool" ||
851+
type === "command" ||
852+
type === "browser_action_launch" ||
853+
type === "use_mcp_server"
854+
) {
855+
// For tool approvals, we need to approve first, then send the message if there's text/images
856+
this.handleWebviewAskResponse("yesButtonClicked", message.text, message.images)
857+
} else {
858+
// For other ask types (like followup), fulfill the ask directly
859+
this.setMessageResponse(message.text, message.images)
860+
}
851861
}
852862
}
853863

@@ -2898,4 +2908,28 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
28982908
public get cwd() {
28992909
return this.workspacePath
29002910
}
2911+
2912+
/**
2913+
* Process any queued messages by dequeuing and submitting them.
2914+
* This ensures that queued user messages are sent when appropriate,
2915+
* preventing them from getting stuck in the queue.
2916+
*
2917+
* @param context - Context string for logging (e.g., the calling tool name)
2918+
*/
2919+
public processQueuedMessages(): void {
2920+
try {
2921+
if (!this.messageQueueService.isEmpty()) {
2922+
const queued = this.messageQueueService.dequeueMessage()
2923+
if (queued) {
2924+
setTimeout(() => {
2925+
this.submitUserMessage(queued.text, queued.images).catch((err) =>
2926+
console.error(`[Task] Failed to submit queued message:`, err),
2927+
)
2928+
}, 0)
2929+
}
2930+
}
2931+
} catch (e) {
2932+
console.error(`[Task] Queue processing error:`, e)
2933+
}
2934+
}
29012935
}

src/core/tools/__tests__/applyDiffTool.experiment.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ describe("applyDiffTool experiment routing", () => {
4040
api: {
4141
getModel: vi.fn().mockReturnValue({ id: "test-model" }),
4242
},
43+
processQueuedMessages: vi.fn(),
4344
} as any
4445

4546
mockBlock = {

src/core/tools/__tests__/multiApplyDiffTool.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ describe("multiApplyDiffTool", () => {
9191
trackFileContext: vi.fn().mockResolvedValue(undefined),
9292
},
9393
didEditFile: false,
94+
processQueuedMessages: vi.fn(),
9495
} as any
9596

9697
mockAskApproval = vi.fn().mockResolvedValue(true)

src/core/tools/applyDiffTool.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ export async function applyDiffToolLegacy(
207207

208208
if (!didApprove) {
209209
await cline.diffViewProvider.revertChanges() // Cline likely handles closing the diff view
210+
cline.processQueuedMessages()
210211
return
211212
}
212213

@@ -245,11 +246,15 @@ export async function applyDiffToolLegacy(
245246

246247
await cline.diffViewProvider.reset()
247248

249+
// Process any queued messages after file edit completes
250+
cline.processQueuedMessages()
251+
248252
return
249253
}
250254
} catch (error) {
251255
await handleError("applying diff", error)
252256
await cline.diffViewProvider.reset()
257+
cline.processQueuedMessages()
253258
return
254259
}
255260
}

src/core/tools/insertContentTool.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ export async function insertContentTool(
187187
pushToolResult(message)
188188

189189
await cline.diffViewProvider.reset()
190+
191+
// Process any queued messages after file edit completes
192+
cline.processQueuedMessages()
190193
} catch (error) {
191194
handleError("insert content", error)
192195
await cline.diffViewProvider.reset()

src/core/tools/multiApplyDiffTool.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ Original error: ${errorMessage}`
172172
TelemetryService.instance.captureDiffApplicationError(cline.taskId, cline.consecutiveMistakeCount)
173173
await cline.say("diff_error", `Failed to parse apply_diff XML: ${errorMessage}`)
174174
pushToolResult(detailedError)
175+
cline.processQueuedMessages()
175176
return
176177
}
177178
} else if (legacyPath && typeof legacyDiffContent === "string") {
@@ -195,6 +196,7 @@ Original error: ${errorMessage}`
195196
"args (or legacy 'path' and 'diff' parameters)",
196197
)
197198
pushToolResult(errorMsg)
199+
cline.processQueuedMessages()
198200
return
199201
}
200202

@@ -210,6 +212,7 @@ Original error: ${errorMessage}`
210212
: "args (must contain at least one valid file element)",
211213
),
212214
)
215+
cline.processQueuedMessages()
213216
return
214217
}
215218

@@ -675,10 +678,12 @@ ${errorDetails ? `\nTechnical details:\n${errorDetails}\n` : ""}
675678

676679
// Push the final result combining all operation results
677680
pushToolResult(results.join("\n\n") + singleBlockNotice)
681+
cline.processQueuedMessages()
678682
return
679683
} catch (error) {
680684
await handleError("applying diff", error)
681685
await cline.diffViewProvider.reset()
686+
cline.processQueuedMessages()
682687
return
683688
}
684689
}

src/core/tools/searchAndReplaceTool.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ export async function searchAndReplaceTool(
263263
// Record successful tool usage and cleanup
264264
cline.recordToolUsage("search_and_replace")
265265
await cline.diffViewProvider.reset()
266+
267+
// Process any queued messages after file edit completes
268+
cline.processQueuedMessages()
266269
} catch (error) {
267270
handleError("search and replace", error)
268271
await cline.diffViewProvider.reset()

src/core/tools/writeToFileTool.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,9 @@ export async function writeToFileTool(
308308

309309
await cline.diffViewProvider.reset()
310310

311+
// Process any queued messages after file edit completes
312+
cline.processQueuedMessages()
313+
311314
return
312315
}
313316
} catch (error) {

0 commit comments

Comments
 (0)