From 78457917207a90616a6f24b9eb4fbbe1dbe104a4 Mon Sep 17 00:00:00 2001 From: sam hoang Date: Mon, 13 Jan 2025 02:48:52 +0700 Subject: [PATCH] feat(code-actions): add user input and customizable templates Add ability to provide custom input when using code actions Make code action templates customizable and resettable Refactor code action handling for better maintainability Add state management for utility prompts --- src/core/CodeActionProvider.ts | 2 +- src/core/prompts/code-actions.ts | 32 ++++++++++----- src/core/webview/ClineProvider.ts | 12 +++++- src/extension.ts | 65 ++++++++++++++++++++++--------- 4 files changed, 81 insertions(+), 30 deletions(-) diff --git a/src/core/CodeActionProvider.ts b/src/core/CodeActionProvider.ts index 11bafdb..cac2bdc 100644 --- a/src/core/CodeActionProvider.ts +++ b/src/core/CodeActionProvider.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; -const ACTION_NAMES = { +export const ACTION_NAMES = { EXPLAIN: 'Roo Cline: Explain Code', FIX: 'Roo Cline: Fix Code', IMPROVE: 'Roo Cline: Improve Code' diff --git a/src/core/prompts/code-actions.ts b/src/core/prompts/code-actions.ts index 2b9445d..0811c48 100644 --- a/src/core/prompts/code-actions.ts +++ b/src/core/prompts/code-actions.ts @@ -2,12 +2,12 @@ type PromptParams = Record; const generateDiagnosticText = (diagnostics?: any[]) => { if (!diagnostics?.length) return ''; - return `\nCurrent problems detected:\n${diagnostics.map(d => + return `\nCurrent problems detected:\n${diagnostics.map(d => `- [${d.source || 'Error'}] ${d.message}${d.code ? ` (${d.code})` : ''}` ).join('\n')}`; }; -const createPrompt = (template: string, params: PromptParams): string => { +export const createPrompt = (template: string, params: PromptParams): string => { let result = template; for (const [key, value] of Object.entries(params)) { if (key === 'diagnostics') { @@ -16,11 +16,16 @@ const createPrompt = (template: string, params: PromptParams): string => { result = result.replaceAll(`\${${key}}`, value as string); } } + + // Replace any remaining user_input placeholders with empty string + result = result.replaceAll('${userInput}', ''); + return result; }; -const EXPLAIN_TEMPLATE = ` +export const EXPLAIN_TEMPLATE = ` Explain the following code from file path @/\${filePath}: +\${userInput} \`\`\` \${selectedText} @@ -32,9 +37,10 @@ Please provide a clear and concise explanation of what this code does, including 3. Important patterns or techniques used `; -const FIX_TEMPLATE = ` +export const FIX_TEMPLATE = ` Fix any issues in the following code from file path @/\${filePath} \${diagnosticText} +\${userInput} \`\`\` \${selectedText} @@ -47,8 +53,9 @@ Please: 4. Explain what was fixed and why `; -const IMPROVE_TEMPLATE = ` +export const IMPROVE_TEMPLATE = ` Improve the following code from file path @/\${filePath}: +\${userInput} \`\`\` \${selectedText} @@ -63,11 +70,18 @@ Please suggest improvements for: Provide the improved code along with explanations for each enhancement. `; -export const explainCodePrompt = (params: PromptParams) => +export const explainCodePrompt = (params: PromptParams) => createPrompt(EXPLAIN_TEMPLATE, params); -export const fixCodePrompt = (params: PromptParams) => +export const fixCodePrompt = (params: PromptParams) => createPrompt(FIX_TEMPLATE, params); -export const improveCodePrompt = (params: PromptParams) => - createPrompt(IMPROVE_TEMPLATE, params); \ No newline at end of file +export const improveCodePrompt = (params: PromptParams) => + createPrompt(IMPROVE_TEMPLATE, params); + +// Get template based on prompt type +export const defaultTemplates = { + 'EXPLAIN': EXPLAIN_TEMPLATE, + 'FIX': FIX_TEMPLATE, + 'IMPROVE': IMPROVE_TEMPLATE +} \ No newline at end of file diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 17289f5..d897838 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -40,6 +40,12 @@ import { enhancePrompt } from "../../utils/enhance-prompt" import { getCommitInfo, searchCommits, getWorkingState } from "../../utils/git" import { ConfigManager } from "../config/ConfigManager" import { CustomModesManager } from "../config/CustomModesManager" +import { + defaultTemplates, + createPrompt +} from "../prompts/code-actions" + +import { ACTION_NAMES } from "../CodeActionProvider" /* https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts @@ -182,7 +188,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { } public static async handleCodeAction( - promptGenerator: (params: Record) => string, + promptType: keyof typeof ACTION_NAMES, params: Record ): Promise { const visibleProvider = ClineProvider.getVisibleInstance() @@ -190,8 +196,10 @@ export class ClineProvider implements vscode.WebviewViewProvider { return } - const prompt = promptGenerator(params) + const { utilPrompt } = await visibleProvider.getState() + const template = utilPrompt?.[promptType] ?? defaultTemplates[promptType] + const prompt = createPrompt(template, params) await visibleProvider.initClineWithTask(prompt) } diff --git a/src/extension.ts b/src/extension.ts index 6c8c9e7..cf910fc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -5,7 +5,7 @@ import * as vscode from "vscode" import { ClineProvider } from "./core/webview/ClineProvider" import { createClineAPI } from "./exports" import "./utils/path" // necessary to have access to String.prototype.toPosix -import { CodeActionProvider } from "./core/CodeActionProvider" +import { ACTION_NAMES, CodeActionProvider } from "./core/CodeActionProvider" import { explainCodePrompt, fixCodePrompt, improveCodePrompt } from "./core/prompts/code-actions" import { DIFF_VIEW_URI_SCHEME } from "./integrations/editor/DiffViewProvider" @@ -171,27 +171,56 @@ export function activate(context: vscode.ExtensionContext) { ) ); - // Register code action commands - context.subscriptions.push( - vscode.commands.registerCommand("roo-cline.explainCode", async (filePath: string, selectedText: string) => { - await ClineProvider.handleCodeAction(explainCodePrompt, { filePath, selectedText }) - }) - ); + // Helper function to handle code actions + const registerCodeAction = ( + context: vscode.ExtensionContext, + command: string, + promptType: keyof typeof ACTION_NAMES, + inputPrompt: string, + inputPlaceholder: string + ) => { + context.subscriptions.push( + vscode.commands.registerCommand(command, async (filePath: string, selectedText: string, diagnostics?: any[]) => { + const userInput = await vscode.window.showInputBox({ + prompt: inputPrompt, + placeHolder: inputPlaceholder + }); - context.subscriptions.push( - vscode.commands.registerCommand("roo-cline.fixCode", async (filePath: string, selectedText: string, diagnostics?: any[]) => { - await ClineProvider.handleCodeAction(fixCodePrompt, { - filePath, - selectedText, - ...(diagnostics ? { diagnostics } : {}) + const params = { + filePath, + selectedText, + ...(diagnostics ? { diagnostics } : {}), + ...(userInput ? { userInput } : {}) + }; + + await ClineProvider.handleCodeAction(promptType, params); }) - }) + ); + }; + + // Register code action commands + registerCodeAction( + context, + "roo-cline.explainCode", + 'EXPLAIN', + "Any specific questions about this code?", + "E.g. How does the error handling work?" ); - context.subscriptions.push( - vscode.commands.registerCommand("roo-cline.improveCode", async (filePath: string, selectedText: string) => { - await ClineProvider.handleCodeAction(improveCodePrompt, { filePath, selectedText }) - }) + registerCodeAction( + context, + "roo-cline.fixCode", + 'FIX', + "Any specific concerns about fixing this code?", + "E.g. Maintain backward compatibility" + ); + + registerCodeAction( + context, + "roo-cline.improveCode", + 'IMPROVE', + "Any specific aspects you want to improve?", + "E.g. Focus on performance optimization" ); return createClineAPI(outputChannel, sidebarProvider)