Fix message queue re-queue loop in Task.ask() (#7823)

This commit is contained in:
Daniel 2025-09-11 20:17:48 -05:00 committed by GitHub
parent 03709fd9a5
commit 08d7f80e22
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 58 additions and 3 deletions

View file

@ -845,9 +845,19 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
const message = this.messageQueueService.dequeueMessage()
if (message) {
setTimeout(async () => {
await this.submitUserMessage(message.text, message.images)
}, 0)
// Check if this is a tool approval ask that needs to be handled
if (
type === "tool" ||
type === "command" ||
type === "browser_action_launch" ||
type === "use_mcp_server"
) {
// For tool approvals, we need to approve first, then send the message if there's text/images
this.handleWebviewAskResponse("yesButtonClicked", message.text, message.images)
} else {
// For other ask types (like followup), fulfill the ask directly
this.setMessageResponse(message.text, message.images)
}
}
}
@ -2898,4 +2908,28 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
public get cwd() {
return this.workspacePath
}
/**
* Process any queued messages by dequeuing and submitting them.
* This ensures that queued user messages are sent when appropriate,
* preventing them from getting stuck in the queue.
*
* @param context - Context string for logging (e.g., the calling tool name)
*/
public processQueuedMessages(): void {
try {
if (!this.messageQueueService.isEmpty()) {
const queued = this.messageQueueService.dequeueMessage()
if (queued) {
setTimeout(() => {
this.submitUserMessage(queued.text, queued.images).catch((err) =>
console.error(`[Task] Failed to submit queued message:`, err),
)
}, 0)
}
}
} catch (e) {
console.error(`[Task] Queue processing error:`, e)
}
}
}

View file

@ -40,6 +40,7 @@ describe("applyDiffTool experiment routing", () => {
api: {
getModel: vi.fn().mockReturnValue({ id: "test-model" }),
},
processQueuedMessages: vi.fn(),
} as any
mockBlock = {

View file

@ -91,6 +91,7 @@ describe("multiApplyDiffTool", () => {
trackFileContext: vi.fn().mockResolvedValue(undefined),
},
didEditFile: false,
processQueuedMessages: vi.fn(),
} as any
mockAskApproval = vi.fn().mockResolvedValue(true)

View file

@ -207,6 +207,7 @@ export async function applyDiffToolLegacy(
if (!didApprove) {
await cline.diffViewProvider.revertChanges() // Cline likely handles closing the diff view
cline.processQueuedMessages()
return
}
@ -245,11 +246,15 @@ export async function applyDiffToolLegacy(
await cline.diffViewProvider.reset()
// Process any queued messages after file edit completes
cline.processQueuedMessages()
return
}
} catch (error) {
await handleError("applying diff", error)
await cline.diffViewProvider.reset()
cline.processQueuedMessages()
return
}
}

View file

@ -187,6 +187,9 @@ export async function insertContentTool(
pushToolResult(message)
await cline.diffViewProvider.reset()
// Process any queued messages after file edit completes
cline.processQueuedMessages()
} catch (error) {
handleError("insert content", error)
await cline.diffViewProvider.reset()

View file

@ -172,6 +172,7 @@ Original error: ${errorMessage}`
TelemetryService.instance.captureDiffApplicationError(cline.taskId, cline.consecutiveMistakeCount)
await cline.say("diff_error", `Failed to parse apply_diff XML: ${errorMessage}`)
pushToolResult(detailedError)
cline.processQueuedMessages()
return
}
} else if (legacyPath && typeof legacyDiffContent === "string") {
@ -195,6 +196,7 @@ Original error: ${errorMessage}`
"args (or legacy 'path' and 'diff' parameters)",
)
pushToolResult(errorMsg)
cline.processQueuedMessages()
return
}
@ -210,6 +212,7 @@ Original error: ${errorMessage}`
: "args (must contain at least one valid file element)",
),
)
cline.processQueuedMessages()
return
}
@ -675,10 +678,12 @@ ${errorDetails ? `\nTechnical details:\n${errorDetails}\n` : ""}
// Push the final result combining all operation results
pushToolResult(results.join("\n\n") + singleBlockNotice)
cline.processQueuedMessages()
return
} catch (error) {
await handleError("applying diff", error)
await cline.diffViewProvider.reset()
cline.processQueuedMessages()
return
}
}

View file

@ -263,6 +263,9 @@ export async function searchAndReplaceTool(
// Record successful tool usage and cleanup
cline.recordToolUsage("search_and_replace")
await cline.diffViewProvider.reset()
// Process any queued messages after file edit completes
cline.processQueuedMessages()
} catch (error) {
handleError("search and replace", error)
await cline.diffViewProvider.reset()

View file

@ -308,6 +308,9 @@ export async function writeToFileTool(
await cline.diffViewProvider.reset()
// Process any queued messages after file edit completes
cline.processQueuedMessages()
return
}
} catch (error) {