refactor(code-actions): implement parameter object pattern for prompt generation

- Extract prompt templates into constants
- Add createPrompt utility for template string handling
- Consolidate code action handling in ClineProvider
- Update tests to use new parameter object pattern
This commit is contained in:
sam hoang
2025-01-12 21:20:02 +07:00
parent 02a8eb96f1
commit 1b26f91ea7
4 changed files with 79 additions and 40 deletions

View File

@@ -6,7 +6,10 @@ describe('Code Action Prompts', () => {
describe('explainCodePrompt', () => { describe('explainCodePrompt', () => {
it('should format explain prompt correctly', () => { it('should format explain prompt correctly', () => {
const prompt = explainCodePrompt(testFilePath, testCode); const prompt = explainCodePrompt({
filePath: testFilePath,
selectedText: testCode
});
expect(prompt).toContain(`@/${testFilePath}`); expect(prompt).toContain(`@/${testFilePath}`);
expect(prompt).toContain(testCode); expect(prompt).toContain(testCode);
@@ -18,7 +21,10 @@ describe('Code Action Prompts', () => {
describe('fixCodePrompt', () => { describe('fixCodePrompt', () => {
it('should format fix prompt without diagnostics', () => { it('should format fix prompt without diagnostics', () => {
const prompt = fixCodePrompt(testFilePath, testCode); const prompt = fixCodePrompt({
filePath: testFilePath,
selectedText: testCode
});
expect(prompt).toContain(`@/${testFilePath}`); expect(prompt).toContain(`@/${testFilePath}`);
expect(prompt).toContain(testCode); expect(prompt).toContain(testCode);
@@ -39,7 +45,11 @@ describe('Code Action Prompts', () => {
} }
]; ];
const prompt = fixCodePrompt(testFilePath, testCode, diagnostics); const prompt = fixCodePrompt({
filePath: testFilePath,
selectedText: testCode,
diagnostics
});
expect(prompt).toContain('Current problems detected:'); expect(prompt).toContain('Current problems detected:');
expect(prompt).toContain('[eslint] Missing semicolon (semi)'); expect(prompt).toContain('[eslint] Missing semicolon (semi)');
@@ -50,7 +60,10 @@ describe('Code Action Prompts', () => {
describe('improveCodePrompt', () => { describe('improveCodePrompt', () => {
it('should format improve prompt correctly', () => { it('should format improve prompt correctly', () => {
const prompt = improveCodePrompt(testFilePath, testCode); const prompt = improveCodePrompt({
filePath: testFilePath,
selectedText: testCode
});
expect(prompt).toContain(`@/${testFilePath}`); expect(prompt).toContain(`@/${testFilePath}`);
expect(prompt).toContain(testCode); expect(prompt).toContain(testCode);

View File

@@ -1,8 +1,29 @@
export const explainCodePrompt = (filePath: string, selectedText: string) => ` type PromptParams = Record<string, string | any[]>;
Explain the following code from file path @/${filePath}:
const generateDiagnosticText = (diagnostics?: any[]) => {
if (!diagnostics?.length) return '';
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 => {
let result = template;
for (const [key, value] of Object.entries(params)) {
if (key === 'diagnostics') {
result = result.replaceAll('${diagnosticText}', generateDiagnosticText(value as any[]));
} else {
result = result.replaceAll(`\${${key}}`, value as string);
}
}
return result;
};
const EXPLAIN_TEMPLATE = `
Explain the following code from file path @/\${filePath}:
\`\`\` \`\`\`
${selectedText} \${selectedText}
\`\`\` \`\`\`
Please provide a clear and concise explanation of what this code does, including: Please provide a clear and concise explanation of what this code does, including:
@@ -11,18 +32,12 @@ 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
`; `;
export const fixCodePrompt = (filePath: string, selectedText: string, diagnostics?: any[]) => { const FIX_TEMPLATE = `
const diagnosticText = diagnostics && diagnostics.length > 0 Fix any issues in the following code from file path @/\${filePath}
? `\nCurrent problems detected: \${diagnosticText}
${diagnostics.map(d => `- [${d.source || 'Error'}] ${d.message}${d.code ? ` (${d.code})` : ''}`).join('\n')}`
: '';
return `
Fix any issues in the following code from file path @/${filePath}
${diagnosticText}
\`\`\` \`\`\`
${selectedText} \${selectedText}
\`\`\` \`\`\`
Please: Please:
@@ -31,13 +46,12 @@ Please:
3. Provide corrected code 3. Provide corrected code
4. Explain what was fixed and why 4. Explain what was fixed and why
`; `;
};
export const improveCodePrompt = (filePath: string, selectedText: string) => ` const IMPROVE_TEMPLATE = `
Improve the following code from file path @/${filePath}: Improve the following code from file path @/\${filePath}:
\`\`\` \`\`\`
${selectedText} \${selectedText}
\`\`\` \`\`\`
Please suggest improvements for: Please suggest improvements for:
@@ -47,4 +61,13 @@ Please suggest improvements for:
4. Error handling and edge cases 4. Error handling and edge cases
Provide the improved code along with explanations for each enhancement. Provide the improved code along with explanations for each enhancement.
`; `;
export const explainCodePrompt = (params: PromptParams) =>
createPrompt(EXPLAIN_TEMPLATE, params);
export const fixCodePrompt = (params: PromptParams) =>
createPrompt(FIX_TEMPLATE, params);
export const improveCodePrompt = (params: PromptParams) =>
createPrompt(IMPROVE_TEMPLATE, params);

View File

@@ -181,6 +181,20 @@ export class ClineProvider implements vscode.WebviewViewProvider {
return findLast(Array.from(this.activeInstances), (instance) => instance.view?.visible === true) return findLast(Array.from(this.activeInstances), (instance) => instance.view?.visible === true)
} }
public static async handleCodeAction(
promptGenerator: (params: Record<string, string | any[]>) => string,
params: Record<string, string | any[]>
): Promise<void> {
const visibleProvider = ClineProvider.getVisibleInstance()
if (!visibleProvider) {
return
}
const prompt = promptGenerator(params)
await visibleProvider.initClineWithTask(prompt)
}
resolveWebviewView( resolveWebviewView(
webviewView: vscode.WebviewView | vscode.WebviewPanel, webviewView: vscode.WebviewView | vscode.WebviewPanel,
//context: vscode.WebviewViewResolveContext<unknown>, used to recreate a deallocated webview, but we don't need this since we use retainContextWhenHidden //context: vscode.WebviewViewResolveContext<unknown>, used to recreate a deallocated webview, but we don't need this since we use retainContextWhenHidden

View File

@@ -174,34 +174,23 @@ export function activate(context: vscode.ExtensionContext) {
// Register code action commands // Register code action commands
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("roo-cline.explainCode", async (filePath: string, selectedText: string) => { vscode.commands.registerCommand("roo-cline.explainCode", async (filePath: string, selectedText: string) => {
const visibleProvider = ClineProvider.getVisibleInstance() await ClineProvider.handleCodeAction(explainCodePrompt, { filePath, selectedText })
if (!visibleProvider) {
return
}
const prompt = explainCodePrompt(filePath, selectedText)
await visibleProvider.initClineWithTask(prompt)
}) })
); );
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("roo-cline.fixCode", async (filePath: string, selectedText: string, diagnostics?: any[]) => { vscode.commands.registerCommand("roo-cline.fixCode", async (filePath: string, selectedText: string, diagnostics?: any[]) => {
const visibleProvider = ClineProvider.getVisibleInstance() await ClineProvider.handleCodeAction(fixCodePrompt, {
if (!visibleProvider) { filePath,
return selectedText,
} ...(diagnostics ? { diagnostics } : {})
const prompt = fixCodePrompt(filePath, selectedText, diagnostics) })
await visibleProvider.initClineWithTask(prompt)
}) })
); );
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("roo-cline.improveCode", async (filePath: string, selectedText: string) => { vscode.commands.registerCommand("roo-cline.improveCode", async (filePath: string, selectedText: string) => {
const visibleProvider = ClineProvider.getVisibleInstance() await ClineProvider.handleCodeAction(improveCodePrompt, { filePath, selectedText })
if (!visibleProvider) {
return
}
const prompt = improveCodePrompt(filePath, selectedText)
await visibleProvider.initClineWithTask(prompt)
}) })
); );