Skip to content

Commit 994e2a2

Browse files
committed
fix: prevent enhance prompt from overwriting both edit and new message boxes
- Add context parameter to enhance prompt messages to distinguish between main and edit mode - Update ChatTextArea to only respond to enhance prompt messages matching its context - Add comprehensive test coverage for context-specific behavior Fixes #8553
1 parent 5a3f911 commit 994e2a2

File tree

3 files changed

+129
-25
lines changed

3 files changed

+129
-25
lines changed

src/core/webview/webviewMessageHandler.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,7 +1694,12 @@ export const webviewMessageHandler = async (
16941694
if (result.success && result.enhancedText) {
16951695
// Capture telemetry for prompt enhancement
16961696
MessageEnhancer.captureTelemetry(currentCline?.taskId, includeTaskHistoryInEnhance)
1697-
await provider.postMessageToWebview({ type: "enhancedPrompt", text: result.enhancedText })
1697+
// Include the context from the original request in the response
1698+
await provider.postMessageToWebview({
1699+
type: "enhancedPrompt",
1700+
text: result.enhancedText,
1701+
context: message.context,
1702+
})
16981703
} else {
16991704
throw new Error(result.error || "Unknown error")
17001705
}
@@ -1704,7 +1709,11 @@ export const webviewMessageHandler = async (
17041709
)
17051710

17061711
vscode.window.showErrorMessage(t("common:errors.enhance_prompt"))
1707-
await provider.postMessageToWebview({ type: "enhancedPrompt" })
1712+
// Include context even in error response
1713+
await provider.postMessageToWebview({
1714+
type: "enhancedPrompt",
1715+
context: message.context,
1716+
})
17081717
}
17091718
}
17101719
break

webview-ui/src/components/chat/ChatTextArea.tsx

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -124,28 +124,33 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
124124
const message = event.data
125125

126126
if (message.type === "enhancedPrompt") {
127-
if (message.text && textAreaRef.current) {
128-
try {
129-
// Use execCommand to replace text while preserving undo history
130-
if (document.execCommand) {
131-
// Use native browser methods to preserve undo stack
132-
const textarea = textAreaRef.current
133-
134-
// Focus the textarea to ensure it's the active element
135-
textarea.focus()
136-
137-
// Select all text first
138-
textarea.select()
139-
document.execCommand("insertText", false, message.text)
140-
} else {
127+
// Only handle the enhanced prompt if it's for this specific textarea instance
128+
// Edit mode textareas have context "edit", main textarea has context "main"
129+
const expectedContext = isEditMode ? "edit" : "main"
130+
if (message.context === expectedContext) {
131+
if (message.text && textAreaRef.current) {
132+
try {
133+
// Use execCommand to replace text while preserving undo history
134+
if (document.execCommand) {
135+
// Use native browser methods to preserve undo stack
136+
const textarea = textAreaRef.current
137+
138+
// Focus the textarea to ensure it's the active element
139+
textarea.focus()
140+
141+
// Select all text first
142+
textarea.select()
143+
document.execCommand("insertText", false, message.text)
144+
} else {
145+
setInputValue(message.text)
146+
}
147+
} catch {
141148
setInputValue(message.text)
142149
}
143-
} catch {
144-
setInputValue(message.text)
145150
}
146-
}
147151

148-
setIsEnhancingPrompt(false)
152+
setIsEnhancingPrompt(false)
153+
}
149154
} else if (message.type === "insertTextIntoTextarea") {
150155
if (message.text && textAreaRef.current) {
151156
// Insert the command text at the current cursor position
@@ -196,7 +201,7 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
196201

197202
window.addEventListener("message", messageHandler)
198203
return () => window.removeEventListener("message", messageHandler)
199-
}, [setInputValue, searchRequestId, inputValue])
204+
}, [setInputValue, searchRequestId, inputValue, isEditMode])
200205

201206
const [isDraggingOver, setIsDraggingOver] = useState(false)
202207
const [textAreaBaseHeight, setTextAreaBaseHeight] = useState<number | undefined>(undefined)
@@ -239,11 +244,13 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
239244

240245
if (trimmedInput) {
241246
setIsEnhancingPrompt(true)
242-
vscode.postMessage({ type: "enhancePrompt" as const, text: trimmedInput })
247+
// Include context to identify which textarea is requesting enhancement
248+
const context = isEditMode ? "edit" : "main"
249+
vscode.postMessage({ type: "enhancePrompt" as const, text: trimmedInput, context })
243250
} else {
244251
setInputValue(t("chat:enhancePromptDescription"))
245252
}
246-
}, [inputValue, setInputValue, t])
253+
}, [inputValue, setInputValue, t, isEditMode])
247254

248255
const allModes = useMemo(() => getAllModes(customModes), [customModes])
249256

webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ describe("ChatTextArea", () => {
112112
expect(mockPostMessage).toHaveBeenCalledWith({
113113
type: "enhancePrompt",
114114
text: "Test prompt",
115+
context: "main",
115116
})
116117
})
117118

@@ -183,7 +184,7 @@ describe("ChatTextArea", () => {
183184
})
184185

185186
describe("enhanced prompt response", () => {
186-
it("should update input value using native browser methods when receiving enhanced prompt", () => {
187+
it("should update input value using native browser methods when receiving enhanced prompt with matching context", () => {
187188
const setInputValue = vi.fn()
188189

189190
// Mock document.execCommand
@@ -205,12 +206,13 @@ describe("ChatTextArea", () => {
205206
textarea.select = mockSelect
206207
textarea.focus = mockFocus
207208

208-
// Simulate receiving enhanced prompt message
209+
// Simulate receiving enhanced prompt message with matching context
209210
window.dispatchEvent(
210211
new MessageEvent("message", {
211212
data: {
212213
type: "enhancedPrompt",
213214
text: "Enhanced test prompt",
215+
context: "main",
214216
},
215217
}),
216218
)
@@ -221,6 +223,90 @@ describe("ChatTextArea", () => {
221223
expect(mockExecCommand).toHaveBeenCalledWith("insertText", false, "Enhanced test prompt")
222224
})
223225

226+
it("should ignore enhanced prompt with non-matching context", () => {
227+
const setInputValue = vi.fn()
228+
229+
// Mock document.execCommand
230+
const mockExecCommand = vi.fn().mockReturnValue(true)
231+
Object.defineProperty(document, "execCommand", {
232+
value: mockExecCommand,
233+
writable: true,
234+
})
235+
236+
const { container } = render(
237+
<ChatTextArea {...defaultProps} setInputValue={setInputValue} inputValue="Original prompt" />,
238+
)
239+
240+
const textarea = container.querySelector("textarea")!
241+
242+
// Mock textarea methods
243+
const mockSelect = vi.fn()
244+
const mockFocus = vi.fn()
245+
textarea.select = mockSelect
246+
textarea.focus = mockFocus
247+
248+
// Simulate receiving enhanced prompt message with non-matching context (edit instead of main)
249+
window.dispatchEvent(
250+
new MessageEvent("message", {
251+
data: {
252+
type: "enhancedPrompt",
253+
text: "Enhanced test prompt",
254+
context: "edit",
255+
},
256+
}),
257+
)
258+
259+
// Verify native browser methods were NOT called
260+
expect(mockFocus).not.toHaveBeenCalled()
261+
expect(mockSelect).not.toHaveBeenCalled()
262+
expect(mockExecCommand).not.toHaveBeenCalled()
263+
expect(setInputValue).not.toHaveBeenCalled()
264+
})
265+
266+
it("should handle enhanced prompt for edit mode", () => {
267+
const setInputValue = vi.fn()
268+
269+
// Mock document.execCommand
270+
const mockExecCommand = vi.fn().mockReturnValue(true)
271+
Object.defineProperty(document, "execCommand", {
272+
value: mockExecCommand,
273+
writable: true,
274+
})
275+
276+
const { container } = render(
277+
<ChatTextArea
278+
{...defaultProps}
279+
setInputValue={setInputValue}
280+
inputValue="Original prompt"
281+
isEditMode={true}
282+
/>,
283+
)
284+
285+
const textarea = container.querySelector("textarea")!
286+
287+
// Mock textarea methods
288+
const mockSelect = vi.fn()
289+
const mockFocus = vi.fn()
290+
textarea.select = mockSelect
291+
textarea.focus = mockFocus
292+
293+
// Simulate receiving enhanced prompt message with edit context
294+
window.dispatchEvent(
295+
new MessageEvent("message", {
296+
data: {
297+
type: "enhancedPrompt",
298+
text: "Enhanced test prompt",
299+
context: "edit",
300+
},
301+
}),
302+
)
303+
304+
// Verify native browser methods were called for edit mode
305+
expect(mockFocus).toHaveBeenCalled()
306+
expect(mockSelect).toHaveBeenCalled()
307+
expect(mockExecCommand).toHaveBeenCalledWith("insertText", false, "Enhanced test prompt")
308+
})
309+
224310
it("should fallback to setInputValue when execCommand is not available", () => {
225311
const setInputValue = vi.fn()
226312

@@ -238,6 +324,7 @@ describe("ChatTextArea", () => {
238324
data: {
239325
type: "enhancedPrompt",
240326
text: "Enhanced test prompt",
327+
context: "main",
241328
},
242329
}),
243330
)
@@ -258,6 +345,7 @@ describe("ChatTextArea", () => {
258345
data: {
259346
type: "enhancedPrompt",
260347
text: "Enhanced test prompt",
348+
context: "main",
261349
},
262350
}),
263351
)

0 commit comments

Comments
 (0)