diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 127960f073..e088f0073b 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -2707,14 +2707,15 @@ export class Cline { this.isAwaitingPlanResponse = false if (this.didRespondToPlanAskBySwitchingMode) { - // await this.say("user_feedback", text ?? "", images) pushToolResult( formatResponse.toolResult( `[The user has switched to ACT MODE, so you may now proceed with the task.]`, images, ), ) - } else { + } + + if (text) { await this.say("user_feedback", text ?? "", images) pushToolResult(formatResponse.toolResult(`\n${text}\n`, images)) } diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 397e11eb80..6fb3f415ab 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -618,7 +618,8 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.postMessageToWebview({ type: "invoke", invoke: "sendMessage", - text: "[Proceeding with the task...]", + text: message.chatContent?.message || "[Proceeding with the task...]", + images: message.chatContent?.images, }) } else { this.cancelTask() diff --git a/src/shared/ChatContent.ts b/src/shared/ChatContent.ts new file mode 100644 index 0000000000..fe209de363 --- /dev/null +++ b/src/shared/ChatContent.ts @@ -0,0 +1,4 @@ +export interface ChatContent { + message?: string + images?: string[] +} diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index a18a3c405a..447193dd18 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -2,6 +2,7 @@ import { ApiConfiguration } from "./api" import { AutoApprovalSettings } from "./AutoApprovalSettings" import { BrowserSettings } from "./BrowserSettings" import { ChatSettings } from "./ChatSettings" +import { ChatContent } from "./ChatContent" export interface WebviewMessage { type: @@ -53,6 +54,7 @@ export interface WebviewMessage { autoApprovalSettings?: AutoApprovalSettings browserSettings?: BrowserSettings chatSettings?: ChatSettings + chatContent?: ChatContent // For toggleToolAutoApprove serverName?: string diff --git a/src/test/webview/chat-native.test.ts b/src/test/webview/chat-native.test.ts index 775af4b7ae..d3fe630a94 100644 --- a/src/test/webview/chat-native.test.ts +++ b/src/test/webview/chat-native.test.ts @@ -28,7 +28,13 @@ describe("Chat Integration Tests", () => { vscode.postMessage({ type: 'newTask', text: message.text }); break; case 'toggleMode': - vscode.postMessage({ type: 'chatSettings', chatSettings: { mode: 'act' } }); + vscode.postMessage({ + type: 'chatSettings', + chatSettings: { mode: 'act' }, + chatContent: { + message: "message test", + } + }); break; case 'invoke': if (message.invoke === 'primaryButtonClick') { @@ -92,6 +98,25 @@ describe("Chat Integration Tests", () => { assert.equal(stateChange.chatSettings.mode, "act") }) + it("should toggle between plan and act modes with messages", async () => { + // Set up state change listener + const stateChangePromise = new Promise((resolve) => { + panel.webview.onDidReceiveMessage((message) => { + if (message.type === "chatSettings") { + resolve(message) + } + }) + }) + + // Trigger mode toggle + await panel.webview.postMessage({ type: "toggleMode" }) + + // Verify mode changed + const stateChange = await stateChangePromise + assert.equal(stateChange.chatSettings.mode, "act") + assert.equal(stateChange.chatContent.message, "message test") + }) + it("should handle tool approval flow", async () => { // Set up approval listener const approvalPromise = new Promise((resolve) => { diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index 0255ef0301..e86697405f 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -616,13 +616,17 @@ const ChatTextArea = forwardRef( chatSettings: { mode: newMode, }, + chatContent: { + message: inputValue.trim() ? inputValue : undefined, + images: selectedImages.length > 0 ? selectedImages : undefined, + }, }) // Focus the textarea after mode toggle with slight delay setTimeout(() => { textAreaRef.current?.focus() }, 100) }, changeModeDelay) - }, [chatSettings.mode, showModelSelector, submitApiConfig]) + }, [chatSettings.mode, showModelSelector, submitApiConfig, inputValue, selectedImages]) useShortcut("Meta+Shift+a", onModeToggle, { disableTextInputs: false }) // important that we don't disable the text input here