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
This commit is contained in:
sam hoang
2025-01-13 02:48:52 +07:00
parent 1b26f91ea7
commit 7845791720
4 changed files with 81 additions and 30 deletions

View File

@@ -1,7 +1,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as path from 'path'; import * as path from 'path';
const ACTION_NAMES = { export const ACTION_NAMES = {
EXPLAIN: 'Roo Cline: Explain Code', EXPLAIN: 'Roo Cline: Explain Code',
FIX: 'Roo Cline: Fix Code', FIX: 'Roo Cline: Fix Code',
IMPROVE: 'Roo Cline: Improve Code' IMPROVE: 'Roo Cline: Improve Code'

View File

@@ -7,7 +7,7 @@ const generateDiagnosticText = (diagnostics?: any[]) => {
).join('\n')}`; ).join('\n')}`;
}; };
const createPrompt = (template: string, params: PromptParams): string => { export const createPrompt = (template: string, params: PromptParams): string => {
let result = template; let result = template;
for (const [key, value] of Object.entries(params)) { for (const [key, value] of Object.entries(params)) {
if (key === 'diagnostics') { if (key === 'diagnostics') {
@@ -16,11 +16,16 @@ const createPrompt = (template: string, params: PromptParams): string => {
result = result.replaceAll(`\${${key}}`, value as string); result = result.replaceAll(`\${${key}}`, value as string);
} }
} }
// Replace any remaining user_input placeholders with empty string
result = result.replaceAll('${userInput}', '');
return result; return result;
}; };
const EXPLAIN_TEMPLATE = ` export const EXPLAIN_TEMPLATE = `
Explain the following code from file path @/\${filePath}: Explain the following code from file path @/\${filePath}:
\${userInput}
\`\`\` \`\`\`
\${selectedText} \${selectedText}
@@ -32,9 +37,10 @@ Please provide a clear and concise explanation of what this code does, including
3. Important patterns or techniques used 3. Important patterns or techniques used
`; `;
const FIX_TEMPLATE = ` export const FIX_TEMPLATE = `
Fix any issues in the following code from file path @/\${filePath} Fix any issues in the following code from file path @/\${filePath}
\${diagnosticText} \${diagnosticText}
\${userInput}
\`\`\` \`\`\`
\${selectedText} \${selectedText}
@@ -47,8 +53,9 @@ Please:
4. Explain what was fixed and why 4. Explain what was fixed and why
`; `;
const IMPROVE_TEMPLATE = ` export const IMPROVE_TEMPLATE = `
Improve the following code from file path @/\${filePath}: Improve the following code from file path @/\${filePath}:
\${userInput}
\`\`\` \`\`\`
\${selectedText} \${selectedText}
@@ -71,3 +78,10 @@ export const fixCodePrompt = (params: PromptParams) =>
export const improveCodePrompt = (params: PromptParams) => export const improveCodePrompt = (params: PromptParams) =>
createPrompt(IMPROVE_TEMPLATE, params); createPrompt(IMPROVE_TEMPLATE, params);
// Get template based on prompt type
export const defaultTemplates = {
'EXPLAIN': EXPLAIN_TEMPLATE,
'FIX': FIX_TEMPLATE,
'IMPROVE': IMPROVE_TEMPLATE
}

View File

@@ -40,6 +40,12 @@ import { enhancePrompt } from "../../utils/enhance-prompt"
import { getCommitInfo, searchCommits, getWorkingState } from "../../utils/git" import { getCommitInfo, searchCommits, getWorkingState } from "../../utils/git"
import { ConfigManager } from "../config/ConfigManager" import { ConfigManager } from "../config/ConfigManager"
import { CustomModesManager } from "../config/CustomModesManager" 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 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( public static async handleCodeAction(
promptGenerator: (params: Record<string, string | any[]>) => string, promptType: keyof typeof ACTION_NAMES,
params: Record<string, string | any[]> params: Record<string, string | any[]>
): Promise<void> { ): Promise<void> {
const visibleProvider = ClineProvider.getVisibleInstance() const visibleProvider = ClineProvider.getVisibleInstance()
@@ -190,8 +196,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
return 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) await visibleProvider.initClineWithTask(prompt)
} }

View File

@@ -5,7 +5,7 @@ import * as vscode from "vscode"
import { ClineProvider } from "./core/webview/ClineProvider" import { ClineProvider } from "./core/webview/ClineProvider"
import { createClineAPI } from "./exports" import { createClineAPI } from "./exports"
import "./utils/path" // necessary to have access to String.prototype.toPosix 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 { explainCodePrompt, fixCodePrompt, improveCodePrompt } from "./core/prompts/code-actions"
import { DIFF_VIEW_URI_SCHEME } from "./integrations/editor/DiffViewProvider" import { DIFF_VIEW_URI_SCHEME } from "./integrations/editor/DiffViewProvider"
@@ -171,27 +171,56 @@ export function activate(context: vscode.ExtensionContext) {
) )
); );
// Register code action commands // Helper function to handle code actions
context.subscriptions.push( const registerCodeAction = (
vscode.commands.registerCommand("roo-cline.explainCode", async (filePath: string, selectedText: string) => { context: vscode.ExtensionContext,
await ClineProvider.handleCodeAction(explainCodePrompt, { filePath, selectedText }) 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( const params = {
vscode.commands.registerCommand("roo-cline.fixCode", async (filePath: string, selectedText: string, diagnostics?: any[]) => { filePath,
await ClineProvider.handleCodeAction(fixCodePrompt, { selectedText,
filePath, ...(diagnostics ? { diagnostics } : {}),
selectedText, ...(userInput ? { userInput } : {})
...(diagnostics ? { diagnostics } : {}) };
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( registerCodeAction(
vscode.commands.registerCommand("roo-cline.improveCode", async (filePath: string, selectedText: string) => { context,
await ClineProvider.handleCodeAction(improveCodePrompt, { filePath, selectedText }) "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) return createClineAPI(outputChannel, sidebarProvider)