diff --git a/packages/types/src/vscode.ts b/packages/types/src/vscode.ts index 00f6bbbcba9..cddac614306 100644 --- a/packages/types/src/vscode.ts +++ b/packages/types/src/vscode.ts @@ -53,6 +53,7 @@ export const commandIds = [ "focusInput", "acceptInput", "focusPanel", + "enhancePrompt", ] as const export type CommandId = (typeof commandIds)[number] diff --git a/src/activate/registerCommands.ts b/src/activate/registerCommands.ts index bd925b0e900..f4667df7117 100644 --- a/src/activate/registerCommands.ts +++ b/src/activate/registerCommands.ts @@ -218,6 +218,15 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt visibleProvider.postMessageToWebview({ type: "acceptInput" }) }, + enhancePrompt: () => { + const visibleProvider = getVisibleProviderOrLog(outputChannel) + + if (!visibleProvider) { + return + } + + visibleProvider.postMessageToWebview({ type: "triggerEnhancePrompt" }) + }, }) export const openClineInNewTab = async ({ context, outputChannel }: Omit) => { diff --git a/src/package.json b/src/package.json index 5e3cd3bc530..8abe7f243e7 100644 --- a/src/package.json +++ b/src/package.json @@ -174,6 +174,19 @@ "command": "roo-cline.acceptInput", "title": "%command.acceptInput.title%", "category": "%configuration.title%" + }, + { + "command": "roo-cline.enhancePrompt", + "title": "%command.enhancePrompt.title%", + "category": "%configuration.title%" + } + ], + "keybindings": [ + { + "command": "roo-cline.enhancePrompt", + "key": "ctrl+shift+e", + "mac": "cmd+shift+e", + "when": "view == roo-cline.SidebarProvider && focusedView == roo-cline.SidebarProvider || activeWebviewPanelId == roo-cline.TabPanelProvider" } ], "menus": { diff --git a/src/package.nls.json b/src/package.nls.json index 1eb294ca443..6a187e05874 100644 --- a/src/package.nls.json +++ b/src/package.nls.json @@ -25,6 +25,7 @@ "command.terminal.fixCommand.title": "Fix This Command", "command.terminal.explainCommand.title": "Explain This Command", "command.acceptInput.title": "Accept Input/Suggestion", + "command.enhancePrompt.title": "Enhance Prompt", "configuration.title": "Roo Code", "commands.allowedCommands.description": "Commands that can be auto-executed when 'Always approve execute operations' is enabled", "commands.deniedCommands.description": "Command prefixes that will be automatically denied without asking for approval. In case of conflicts with allowed commands, the longest prefix match takes precedence. Add * to deny all commands.", diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 4f2aa2da159..fcb90e99f6f 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -107,6 +107,7 @@ export interface ExtensionMessage { | "codeIndexSecretStatus" | "showDeleteMessageDialog" | "showEditMessageDialog" + | "triggerEnhancePrompt" text?: string payload?: any // Add a generic payload for now, can refine later action?: diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index 6c541353eb2..21351d0217f 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -115,56 +115,6 @@ const ChatTextArea = forwardRef( return () => document.removeEventListener("mousedown", handleClickOutside) }, [showDropdown]) - // Handle enhanced prompt response and search results. - useEffect(() => { - const messageHandler = (event: MessageEvent) => { - const message = event.data - - if (message.type === "enhancedPrompt") { - if (message.text && textAreaRef.current) { - try { - // Use execCommand to replace text while preserving undo history - if (document.execCommand) { - // Use native browser methods to preserve undo stack - const textarea = textAreaRef.current - - // Focus the textarea to ensure it's the active element - textarea.focus() - - // Select all text first - textarea.select() - document.execCommand("insertText", false, message.text) - } else { - setInputValue(message.text) - } - } catch { - setInputValue(message.text) - } - } - - setIsEnhancingPrompt(false) - } else if (message.type === "commitSearchResults") { - const commits = message.commits.map((commit: any) => ({ - type: ContextMenuOptionType.Git, - value: commit.hash, - label: commit.subject, - description: `${commit.shortHash} by ${commit.author} on ${commit.date}`, - icon: "$(git-commit)", - })) - - setGitCommits(commits) - } else if (message.type === "fileSearchResults") { - setSearchLoading(false) - if (message.requestId === searchRequestId) { - setFileSearchResults(message.results || []) - } - } - } - - window.addEventListener("message", messageHandler) - return () => window.removeEventListener("message", messageHandler) - }, [setInputValue, searchRequestId]) - const [isDraggingOver, setIsDraggingOver] = useState(false) const [textAreaBaseHeight, setTextAreaBaseHeight] = useState(undefined) const [showContextMenu, setShowContextMenu] = useState(false) @@ -218,6 +168,59 @@ const ChatTextArea = forwardRef( const allModes = useMemo(() => getAllModes(customModes), [customModes]) + // Handle enhanced prompt response and search results. + useEffect(() => { + const messageHandler = (event: MessageEvent) => { + const message = event.data + + if (message.type === "enhancedPrompt") { + if (message.text && textAreaRef.current) { + try { + // Use execCommand to replace text while preserving undo history + if (document.execCommand) { + // Use native browser methods to preserve undo stack + const textarea = textAreaRef.current + + // Focus the textarea to ensure it's the active element + textarea.focus() + + // Select all text first + textarea.select() + document.execCommand("insertText", false, message.text) + } else { + setInputValue(message.text) + } + } catch { + setInputValue(message.text) + } + } + + setIsEnhancingPrompt(false) + } else if (message.type === "triggerEnhancePrompt") { + // Handle the keyboard shortcut trigger + handleEnhancePrompt() + } else if (message.type === "commitSearchResults") { + const commits = message.commits.map((commit: any) => ({ + type: ContextMenuOptionType.Git, + value: commit.hash, + label: commit.subject, + description: `${commit.shortHash} by ${commit.author} on ${commit.date}`, + icon: "$(git-commit)", + })) + + setGitCommits(commits) + } else if (message.type === "fileSearchResults") { + setSearchLoading(false) + if (message.requestId === searchRequestId) { + setFileSearchResults(message.results || []) + } + } + } + + window.addEventListener("message", messageHandler) + return () => window.removeEventListener("message", messageHandler) + }, [setInputValue, searchRequestId, handleEnhancePrompt]) + const queryItems = useMemo(() => { return [ { type: ContextMenuOptionType.Problems, value: "problems" },