Forráskód Böngészése

Fix task resumption in the API module (#11369)

Chris Estreich 4 napja
szülő
commit
b02924530c
2 módosított fájl, 42 hozzáadás és 1 törlés
  1. 1 0
      src/extension/__tests__/api-send-message.spec.ts
  2. 41 1
      src/extension/api.ts

+ 1 - 0
src/extension/__tests__/api-send-message.spec.ts

@@ -28,6 +28,7 @@ describe("API - SendMessage Command", () => {
 			postMessageToWebview: mockPostMessageToWebview,
 			on: vi.fn(),
 			getCurrentTaskStack: vi.fn().mockReturnValue([]),
+			getCurrentTask: vi.fn().mockReturnValue(undefined),
 			viewLaunched: true,
 		} as unknown as ClineProvider
 

+ 41 - 1
src/extension/api.ts

@@ -4,6 +4,7 @@ import * as path from "path"
 import * as os from "os"
 
 import * as vscode from "vscode"
+import pWaitFor from "p-wait-for"
 
 import {
 	type RooCodeAPI,
@@ -208,9 +209,19 @@ export class API extends EventEmitter<RooCodeEvents> implements RooCodeAPI {
 	}
 
 	public async resumeTask(taskId: string): Promise<void> {
+		await vscode.commands.executeCommand(`${Package.name}.SidebarProvider.focus`)
+		await this.waitForWebviewLaunch(5_000)
+
 		const { historyItem } = await this.sidebarProvider.getTaskWithId(taskId)
 		await this.sidebarProvider.createTaskWithHistoryItem(historyItem)
-		await this.sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
+
+		if (this.sidebarProvider.viewLaunched) {
+			await this.sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
+		} else {
+			this.log(
+				`[API#resumeTask] webview not launched after resume for task ${taskId}; continuing in headless mode`,
+			)
+		}
 	}
 
 	public async isTaskInHistory(taskId: string): Promise<boolean> {
@@ -237,6 +248,21 @@ export class API extends EventEmitter<RooCodeEvents> implements RooCodeAPI {
 	}
 
 	public async sendMessage(text?: string, images?: string[]) {
+		const currentTask = this.sidebarProvider.getCurrentTask()
+
+		// In headless/sandbox flows the webview may not be launched, so routing
+		// through invoke=sendMessage drops the message. Deliver directly to the
+		// task ask-response channel instead.
+		if (!this.sidebarProvider.viewLaunched) {
+			if (!currentTask) {
+				this.log("[API#sendMessage] no current task in headless mode; message dropped")
+				return
+			}
+
+			await currentTask.submitUserMessage(text ?? "", images)
+			return
+		}
+
 		await this.sidebarProvider.postMessageToWebview({ type: "invoke", invoke: "sendMessage", text, images })
 	}
 
@@ -252,6 +278,20 @@ export class API extends EventEmitter<RooCodeEvents> implements RooCodeAPI {
 		return this.sidebarProvider.viewLaunched
 	}
 
+	private async waitForWebviewLaunch(timeoutMs: number): Promise<boolean> {
+		try {
+			await pWaitFor(() => this.sidebarProvider.viewLaunched, {
+				timeout: timeoutMs,
+				interval: 50,
+			})
+
+			return true
+		} catch {
+			this.log(`[API#waitForWebviewLaunch] webview did not launch within ${timeoutMs}ms`)
+			return false
+		}
+	}
+
 	private registerListeners(provider: ClineProvider) {
 		provider.on(RooCodeEventName.TaskCreated, (task) => {
 			// Task Lifecycle