From 22907a05787b089e83b48c27a2ac987b4e82ea88 Mon Sep 17 00:00:00 2001 From: sam hoang Date: Thu, 23 Jan 2025 00:31:43 +0700 Subject: [PATCH] refactor: consolidate prompt functionality into support-prompt module - Move code action prompts from core/prompts to shared/support-prompt - Migrate enhance prompt functionality from modes to support-prompt - Add UI for managing code action prompts in PromptsView - Update types and interfaces for better prompt management --- .../prompts/__tests__/code-actions.test.ts | 76 ---------- src/core/prompts/code-actions.ts | 87 ----------- src/core/webview/ClineProvider.ts | 85 +++++++---- src/extension.ts | 66 ++++----- src/shared/WebviewMessage.ts | 3 +- src/shared/__tests__/support-prompts.test.ts | 138 ++++++++++++++++++ src/shared/modes.ts | 37 ++--- src/shared/support-prompt.ts | 118 +++++++++++++++ .../src/components/prompts/PromptsView.tsx | 125 ++++++++++++++-- 9 files changed, 467 insertions(+), 268 deletions(-) delete mode 100644 src/core/prompts/__tests__/code-actions.test.ts delete mode 100644 src/core/prompts/code-actions.ts create mode 100644 src/shared/__tests__/support-prompts.test.ts create mode 100644 src/shared/support-prompt.ts diff --git a/src/core/prompts/__tests__/code-actions.test.ts b/src/core/prompts/__tests__/code-actions.test.ts deleted file mode 100644 index 0ddb6bd..0000000 --- a/src/core/prompts/__tests__/code-actions.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { explainCodePrompt, fixCodePrompt, improveCodePrompt } from '../code-actions'; - -describe('Code Action Prompts', () => { - const testFilePath = 'test/file.ts'; - const testCode = 'function test() { return true; }'; - - describe('explainCodePrompt', () => { - it('should format explain prompt correctly', () => { - const prompt = explainCodePrompt({ - filePath: testFilePath, - selectedText: testCode - }); - - expect(prompt).toContain(`@/${testFilePath}`); - expect(prompt).toContain(testCode); - expect(prompt).toContain('purpose and functionality'); - expect(prompt).toContain('Key components'); - expect(prompt).toContain('Important patterns'); - }); - }); - - describe('fixCodePrompt', () => { - it('should format fix prompt without diagnostics', () => { - const prompt = fixCodePrompt({ - filePath: testFilePath, - selectedText: testCode - }); - - expect(prompt).toContain(`@/${testFilePath}`); - expect(prompt).toContain(testCode); - expect(prompt).toContain('Address all detected problems'); - expect(prompt).not.toContain('Current problems detected'); - }); - - it('should format fix prompt with diagnostics', () => { - const diagnostics = [ - { - source: 'eslint', - message: 'Missing semicolon', - code: 'semi' - }, - { - message: 'Unused variable', - severity: 1 - } - ]; - - const prompt = fixCodePrompt({ - filePath: testFilePath, - selectedText: testCode, - diagnostics - }); - - expect(prompt).toContain('Current problems detected:'); - expect(prompt).toContain('[eslint] Missing semicolon (semi)'); - expect(prompt).toContain('[Error] Unused variable'); - expect(prompt).toContain(testCode); - }); - }); - - describe('improveCodePrompt', () => { - it('should format improve prompt correctly', () => { - const prompt = improveCodePrompt({ - filePath: testFilePath, - selectedText: testCode - }); - - expect(prompt).toContain(`@/${testFilePath}`); - expect(prompt).toContain(testCode); - expect(prompt).toContain('Code readability'); - expect(prompt).toContain('Performance optimization'); - expect(prompt).toContain('Best practices'); - expect(prompt).toContain('Error handling'); - }); - }); -}); \ No newline at end of file diff --git a/src/core/prompts/code-actions.ts b/src/core/prompts/code-actions.ts deleted file mode 100644 index 0811c48..0000000 --- a/src/core/prompts/code-actions.ts +++ /dev/null @@ -1,87 +0,0 @@ -type PromptParams = Record; - -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')}`; -}; - -export 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); - } - } - - // Replace any remaining user_input placeholders with empty string - result = result.replaceAll('${userInput}', ''); - - return result; -}; - -export const EXPLAIN_TEMPLATE = ` -Explain the following code from file path @/\${filePath}: -\${userInput} - -\`\`\` -\${selectedText} -\`\`\` - -Please provide a clear and concise explanation of what this code does, including: -1. The purpose and functionality -2. Key components and their interactions -3. Important patterns or techniques used -`; - -export const FIX_TEMPLATE = ` -Fix any issues in the following code from file path @/\${filePath} -\${diagnosticText} -\${userInput} - -\`\`\` -\${selectedText} -\`\`\` - -Please: -1. Address all detected problems listed above (if any) -2. Identify any other potential bugs or issues -3. Provide corrected code -4. Explain what was fixed and why -`; - -export const IMPROVE_TEMPLATE = ` -Improve the following code from file path @/\${filePath}: -\${userInput} - -\`\`\` -\${selectedText} -\`\`\` - -Please suggest improvements for: -1. Code readability and maintainability -2. Performance optimization -3. Best practices and patterns -4. Error handling and edge cases - -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); - -// 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 d897838..f919df6 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1,4 +1,5 @@ import { Anthropic } from "@anthropic-ai/sdk" +import delay from "delay" import axios from "axios" import fs from "fs/promises" import os from "os" @@ -23,7 +24,6 @@ import { modes, CustomPrompts, PromptComponent, - enhance, ModeConfig, defaultModeSlug, getModeBySlug, @@ -40,10 +40,7 @@ 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 { enhance, codeActionPrompt } from "../../shared/support-prompt" import { ACTION_NAMES } from "../CodeActionProvider" @@ -189,17 +186,27 @@ export class ClineProvider implements vscode.WebviewViewProvider { public static async handleCodeAction( promptType: keyof typeof ACTION_NAMES, - params: Record + params: Record, ): Promise { - const visibleProvider = ClineProvider.getVisibleInstance() + let visibleProvider = ClineProvider.getVisibleInstance() + + // If no visible provider, try to show the sidebar view + if (!visibleProvider) { + await vscode.commands.executeCommand("roo-cline.SidebarProvider.focus") + // Wait briefly for the view to become visible + await delay(100) + visibleProvider = ClineProvider.getVisibleInstance() + } + + // If still no visible provider, return if (!visibleProvider) { return } - const { utilPrompt } = await visibleProvider.getState() + const { customPrompts } = await visibleProvider.getState() + + const prompt = codeActionPrompt.create(promptType, params, customPrompts) - const template = utilPrompt?.[promptType] ?? defaultTemplates[promptType] - const prompt = createPrompt(template, params) await visibleProvider.initClineWithTask(prompt) } @@ -297,7 +304,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { experimentalDiffStrategy, } = await this.getState() - const modePrompt = customPrompts?.[mode] + const modePrompt = customPrompts?.[mode] as PromptComponent const effectiveInstructions = [globalInstructions, modePrompt?.customInstructions].filter(Boolean).join("\n\n") this.cline = new Cline( @@ -325,7 +332,7 @@ export class ClineProvider implements vscode.WebviewViewProvider { experimentalDiffStrategy, } = await this.getState() - const modePrompt = customPrompts?.[mode] + const modePrompt = customPrompts?.[mode] as PromptComponent const effectiveInstructions = [globalInstructions, modePrompt?.customInstructions].filter(Boolean).join("\n\n") this.cline = new Cline( @@ -804,29 +811,49 @@ export class ClineProvider implements vscode.WebviewViewProvider { await this.postStateToWebview() break - case "updateEnhancedPrompt": - const existingPrompts = (await this.getGlobalState("customPrompts")) || {} + case "updateSupportPrompt": + try { + if (Object.keys(message?.values ?? {}).length === 0) { + return + } - const updatedPrompts = { - ...existingPrompts, - enhance: message.text, + const existingPrompts = (await this.getGlobalState("customPrompts")) || {} + + const updatedPrompts = { + ...existingPrompts, + ...message.values, + } + + await this.updateGlobalState("customPrompts", updatedPrompts) + await this.postStateToWebview() + } catch (error) { + console.error("Error update support prompt:", error) + vscode.window.showErrorMessage("Failed to update support prompt") } + break + case "resetSupportPrompt": + try { + if (!message?.text) { + return + } - await this.updateGlobalState("customPrompts", updatedPrompts) + const existingPrompts = ((await this.getGlobalState("customPrompts")) || {}) as Record< + string, + any + > - // Get current state and explicitly include customPrompts - const currentState = await this.getState() + const updatedPrompts = { + ...existingPrompts, + } - const stateWithPrompts = { - ...currentState, - customPrompts: updatedPrompts, + updatedPrompts[message.text] = undefined + + await this.updateGlobalState("customPrompts", updatedPrompts) + await this.postStateToWebview() + } catch (error) { + console.error("Error reset support prompt:", error) + vscode.window.showErrorMessage("Failed to reset support prompt") } - - // Post state with prompts - this.view?.webview.postMessage({ - type: "state", - state: stateWithPrompts, - }) break case "updatePrompt": if (message.promptMode && message.customPrompt !== undefined) { diff --git a/src/extension.ts b/src/extension.ts index cf910fc..db011e0 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -6,7 +6,6 @@ import { ClineProvider } from "./core/webview/ClineProvider" import { createClineAPI } from "./exports" import "./utils/path" // necessary to have access to String.prototype.toPosix 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" /* @@ -162,14 +161,10 @@ export function activate(context: vscode.ExtensionContext) { // Register code actions provider context.subscriptions.push( - vscode.languages.registerCodeActionsProvider( - { pattern: "**/*" }, - new CodeActionProvider(), - { - providedCodeActionKinds: CodeActionProvider.providedCodeActionKinds - } - ) - ); + vscode.languages.registerCodeActionsProvider({ pattern: "**/*" }, new CodeActionProvider(), { + providedCodeActionKinds: CodeActionProvider.providedCodeActionKinds, + }), + ) // Helper function to handle code actions const registerCodeAction = ( @@ -177,51 +172,54 @@ export function activate(context: vscode.ExtensionContext) { command: string, promptType: keyof typeof ACTION_NAMES, inputPrompt: string, - inputPlaceholder: 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 - }); + vscode.commands.registerCommand( + command, + async (filePath: string, selectedText: string, diagnostics?: any[]) => { + const userInput = await vscode.window.showInputBox({ + prompt: inputPrompt, + placeHolder: inputPlaceholder, + }) - const params = { - filePath, - selectedText, - ...(diagnostics ? { diagnostics } : {}), - ...(userInput ? { userInput } : {}) - }; + const params = { + filePath, + selectedText, + ...(diagnostics ? { diagnostics } : {}), + ...(userInput ? { userInput } : {}), + } - await ClineProvider.handleCodeAction(promptType, params); - }) - ); - }; + await ClineProvider.handleCodeAction(promptType, params) + }, + ), + ) + } // Register code action commands registerCodeAction( context, "roo-cline.explainCode", - 'EXPLAIN', + "EXPLAIN", "Any specific questions about this code?", - "E.g. How does the error handling work?" - ); + "E.g. How does the error handling work?", + ) registerCodeAction( context, "roo-cline.fixCode", - 'FIX', + "FIX", "Any specific concerns about fixing this code?", - "E.g. Maintain backward compatibility" - ); + "E.g. Maintain backward compatibility", + ) registerCodeAction( context, "roo-cline.improveCode", - 'IMPROVE', + "IMPROVE", "Any specific aspects you want to improve?", - "E.g. Focus on performance optimization" - ); + "E.g. Focus on performance optimization", + ) return createClineAPI(outputChannel, sidebarProvider) } diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index b63b898..e2830bf 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -68,7 +68,8 @@ export interface WebviewMessage { | "requestVsCodeLmModels" | "mode" | "updatePrompt" - | "updateEnhancedPrompt" + | "updateSupportPrompt" + | "resetSupportPrompt" | "getSystemPrompt" | "systemPrompt" | "enhancementApiConfigId" diff --git a/src/shared/__tests__/support-prompts.test.ts b/src/shared/__tests__/support-prompts.test.ts new file mode 100644 index 0000000..92d2342 --- /dev/null +++ b/src/shared/__tests__/support-prompts.test.ts @@ -0,0 +1,138 @@ +import { codeActionPrompt, type CodeActionType } from "../support-prompt" + +describe("Code Action Prompts", () => { + const testFilePath = "test/file.ts" + const testCode = "function test() { return true; }" + + describe("EXPLAIN action", () => { + it("should format explain prompt correctly", () => { + const prompt = codeActionPrompt.create("EXPLAIN", { + filePath: testFilePath, + selectedText: testCode, + }) + + expect(prompt).toContain(`@/${testFilePath}`) + expect(prompt).toContain(testCode) + expect(prompt).toContain("purpose and functionality") + expect(prompt).toContain("Key components") + expect(prompt).toContain("Important patterns") + }) + }) + + describe("FIX action", () => { + it("should format fix prompt without diagnostics", () => { + const prompt = codeActionPrompt.create("FIX", { + filePath: testFilePath, + selectedText: testCode, + }) + + expect(prompt).toContain(`@/${testFilePath}`) + expect(prompt).toContain(testCode) + expect(prompt).toContain("Address all detected problems") + expect(prompt).not.toContain("Current problems detected") + }) + + it("should format fix prompt with diagnostics", () => { + const diagnostics = [ + { + source: "eslint", + message: "Missing semicolon", + code: "semi", + }, + { + message: "Unused variable", + severity: 1, + }, + ] + + const prompt = codeActionPrompt.create("FIX", { + filePath: testFilePath, + selectedText: testCode, + diagnostics, + }) + + expect(prompt).toContain("Current problems detected:") + expect(prompt).toContain("[eslint] Missing semicolon (semi)") + expect(prompt).toContain("[Error] Unused variable") + expect(prompt).toContain(testCode) + }) + }) + + describe("IMPROVE action", () => { + it("should format improve prompt correctly", () => { + const prompt = codeActionPrompt.create("IMPROVE", { + filePath: testFilePath, + selectedText: testCode, + }) + + expect(prompt).toContain(`@/${testFilePath}`) + expect(prompt).toContain(testCode) + expect(prompt).toContain("Code readability") + expect(prompt).toContain("Performance optimization") + expect(prompt).toContain("Best practices") + expect(prompt).toContain("Error handling") + }) + }) + + describe("get template", () => { + it("should return default template when no custom prompts provided", () => { + const template = codeActionPrompt.get(undefined, "EXPLAIN") + expect(template).toBe(codeActionPrompt.default.EXPLAIN) + }) + + it("should return custom template when provided", () => { + const customTemplate = "Custom template for explaining code" + const customPrompts = { + EXPLAIN: customTemplate, + } + const template = codeActionPrompt.get(customPrompts, "EXPLAIN") + expect(template).toBe(customTemplate) + }) + + it("should return default template when custom prompts does not include type", () => { + const customPrompts = { + SOMETHING_ELSE: "Other template", + } + const template = codeActionPrompt.get(customPrompts, "EXPLAIN") + expect(template).toBe(codeActionPrompt.default.EXPLAIN) + }) + }) + + describe("create with custom prompts", () => { + it("should use custom template when provided", () => { + const customTemplate = "Custom template for ${filePath}" + const customPrompts = { + EXPLAIN: customTemplate, + } + + const prompt = codeActionPrompt.create( + "EXPLAIN", + { + filePath: testFilePath, + selectedText: testCode, + }, + customPrompts, + ) + + expect(prompt).toContain(`Custom template for ${testFilePath}`) + expect(prompt).not.toContain("purpose and functionality") + }) + + it("should use default template when custom prompts does not include type", () => { + const customPrompts = { + EXPLAIN: "Other template", + } + + const prompt = codeActionPrompt.create( + "EXPLAIN", + { + filePath: testFilePath, + selectedText: testCode, + }, + customPrompts, + ) + + expect(prompt).toContain("Other template") + }) + }) +}) diff --git a/src/shared/modes.ts b/src/shared/modes.ts index c6ea89a..451e661 100644 --- a/src/shared/modes.ts +++ b/src/shared/modes.ts @@ -12,6 +12,16 @@ export type ModeConfig = { groups: readonly ToolGroup[] // Now uses groups instead of tools array } +// Mode-specific prompts only +export type PromptComponent = { + roleDefinition?: string + customInstructions?: string +} + +export type CustomPrompts = { + [key: string]: PromptComponent | undefined | string +} + // Helper to get all tools for a mode export function getToolsForMode(groups: readonly ToolGroup[]): string[] { const tools = new Set() @@ -130,33 +140,6 @@ export function isToolAllowedForMode( return mode.groups.some((group) => TOOL_GROUPS[group].includes(tool as string)) } -export type PromptComponent = { - roleDefinition?: string - customInstructions?: string -} - -// Mode-specific prompts only -export type CustomPrompts = { - [key: string]: PromptComponent | undefined -} - -// Separate enhance prompt type and definition -export type EnhanceConfig = { - prompt: string -} - -export const enhance: EnhanceConfig = { - prompt: "Generate an enhanced version of this prompt (reply with only the enhanced prompt - no conversation, explanations, lead-in, bullet points, placeholders, or surrounding quotes):", -} as const - -// Completely separate enhance prompt handling -export const enhancePrompt = { - default: enhance.prompt, - get: (customPrompts: Record | undefined): string => { - return customPrompts?.enhance ?? enhance.prompt - }, -} as const - // Create the mode-specific default prompts export const defaultPrompts: Readonly = Object.freeze( Object.fromEntries(modes.map((mode) => [mode.slug, { roleDefinition: mode.roleDefinition }])), diff --git a/src/shared/support-prompt.ts b/src/shared/support-prompt.ts new file mode 100644 index 0000000..4ce9f93 --- /dev/null +++ b/src/shared/support-prompt.ts @@ -0,0 +1,118 @@ +// Separate enhance prompt type and definition +export type EnhanceConfig = { + prompt: string +} + +export const enhance: EnhanceConfig = { + prompt: "Generate an enhanced version of this prompt (reply with only the enhanced prompt - no conversation, explanations, lead-in, bullet points, placeholders, or surrounding quotes):", +} as const + +// Completely separate enhance prompt handling +export const enhancePrompt = { + default: enhance.prompt, + get: (customPrompts: Record | undefined): string => { + return customPrompts?.enhance ?? enhance.prompt + }, +} as const + +// Code action prompts +type PromptParams = Record + +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")}` +} + +export 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) + } + } + + // Replace any remaining user_input placeholders with empty string + result = result.replaceAll("${userInput}", "") + + return result +} + +const EXPLAIN_TEMPLATE = ` +Explain the following code from file path @/\${filePath}: +\${userInput} + +\`\`\` +\${selectedText} +\`\`\` + +Please provide a clear and concise explanation of what this code does, including: +1. The purpose and functionality +2. Key components and their interactions +3. Important patterns or techniques used +` + +const FIX_TEMPLATE = ` +Fix any issues in the following code from file path @/\${filePath} +\${diagnosticText} +\${userInput} + +\`\`\` +\${selectedText} +\`\`\` + +Please: +1. Address all detected problems listed above (if any) +2. Identify any other potential bugs or issues +3. Provide corrected code +4. Explain what was fixed and why +` + +const IMPROVE_TEMPLATE = ` +Improve the following code from file path @/\${filePath}: +\${userInput} + +\`\`\` +\${selectedText} +\`\`\` + +Please suggest improvements for: +1. Code readability and maintainability +2. Performance optimization +3. Best practices and patterns +4. Error handling and edge cases + +Provide the improved code along with explanations for each enhancement. +` + +// Get template based on prompt type +const defaultTemplates = { + EXPLAIN: EXPLAIN_TEMPLATE, + FIX: FIX_TEMPLATE, + IMPROVE: IMPROVE_TEMPLATE, +} as const + +type CodeActionType = keyof typeof defaultTemplates + +export const codeActionPrompt = { + default: defaultTemplates, + get: (customPrompts: Record | undefined, type: CodeActionType): string => { + return customPrompts?.[type] ?? defaultTemplates[type] + }, + create: (type: CodeActionType, params: PromptParams, customPrompts?: Record): string => { + const template = codeActionPrompt.get(customPrompts, type) + return createPrompt(template, params) + }, +} as const + +export type { CodeActionType } + +// User-friendly labels for code action types +export const codeActionLabels: Record = { + FIX: "Fix Issues", + EXPLAIN: "Explain Code", + IMPROVE: "Improve Code", +} as const diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx index ebd4d0f..a767fd4 100644 --- a/webview-ui/src/components/prompts/PromptsView.tsx +++ b/webview-ui/src/components/prompts/PromptsView.tsx @@ -8,14 +8,14 @@ import { VSCodeCheckbox, } from "@vscode/webview-ui-toolkit/react" import { useExtensionState } from "../../context/ExtensionStateContext" +import { Mode, PromptComponent, getRoleDefinition, getAllModes, ModeConfig } from "../../../../src/shared/modes" import { - Mode, - PromptComponent, - getRoleDefinition, - getAllModes, - ModeConfig, enhancePrompt, -} from "../../../../src/shared/modes" + codeActionPrompt, + CodeActionType, + codeActionLabels, +} from "../../../../src/shared/support-prompt" + import { TOOL_GROUPS, GROUP_DISPLAY_NAMES, ToolGroup } from "../../../../src/shared/tool-groups" import { vscode } from "../../utils/vscode" @@ -50,11 +50,12 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { const [selectedPromptTitle, setSelectedPromptTitle] = useState("") const [isToolsEditMode, setIsToolsEditMode] = useState(false) const [isCreateModeDialogOpen, setIsCreateModeDialogOpen] = useState(false) + const [activeCodeActionTab, setActiveCodeActionTab] = useState("FIX") // Direct update functions const updateAgentPrompt = useCallback( (mode: Mode, promptData: PromptComponent) => { - const existingPrompt = customPrompts?.[mode] + const existingPrompt = customPrompts?.[mode] as PromptComponent const updatedPrompt = { ...existingPrompt, ...promptData } // Only include properties that differ from defaults @@ -256,8 +257,19 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { const updateEnhancePrompt = (value: string | undefined) => { vscode.postMessage({ - type: "updateEnhancedPrompt", - text: value, + type: "updateSupportPrompt", + values: { + enhance: value, + }, + }) + } + + const updateCodeActionPrompt = (type: CodeActionType, value: string | undefined) => { + vscode.postMessage({ + type: "updateSupportPrompt", + values: { + [type]: value, + }, }) } @@ -271,7 +283,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { const handleAgentReset = (modeSlug: string) => { // Only reset role definition for built-in modes - const existingPrompt = customPrompts?.[modeSlug] + const existingPrompt = customPrompts?.[modeSlug] as PromptComponent updateAgentPrompt(modeSlug, { ...existingPrompt, roleDefinition: undefined, @@ -279,13 +291,27 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { } const handleEnhanceReset = () => { - updateEnhancePrompt(undefined) + vscode.postMessage({ + type: "resetSupportPrompt", + text: "enhance", + }) + } + + const handleCodeActionReset = (type: CodeActionType) => { + vscode.postMessage({ + type: "resetSupportPrompt", + text: type, + }) } const getEnhancePromptValue = (): string => { return enhancePrompt.get(customPrompts) } + const getCodeActionPromptValue = (type: CodeActionType): string => { + return codeActionPrompt.get(customPrompts, type) + } + const handleTestEnhancement = () => { if (!testPrompt.trim()) return @@ -563,7 +589,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { { const customMode = findModeBySlug(mode, customModes) - const prompt = customPrompts?.[mode] + const prompt = customPrompts?.[mode] as PromptComponent return customMode?.roleDefinition ?? prompt?.roleDefinition ?? getRoleDefinition(mode) })()} onChange={(e) => { @@ -680,7 +706,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { { const customMode = findModeBySlug(mode, customModes) - const prompt = customPrompts?.[mode] + const prompt = customPrompts?.[mode] as PromptComponent return customMode?.customInstructions ?? prompt?.customInstructions ?? "" })()} onChange={(e) => { @@ -696,7 +722,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { }) } else { // For built-in modes, update the prompts - const existingPrompt = customPrompts?.[mode] + const existingPrompt = customPrompts?.[mode] as PromptComponent updateAgentPrompt(mode, { ...existingPrompt, customInstructions: value.trim() || undefined, @@ -759,6 +785,77 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { +
+
Code Action Prompts
+
+ {Object.keys(codeActionPrompt.default).map((type) => ( + + ))} +
+ + {/* Show active tab content */} +
+
+
{activeCodeActionTab} Prompt
+ handleCodeActionReset(activeCodeActionTab)} + title={`Reset ${activeCodeActionTab} prompt to default`}> + + +
+ { + const value = + (e as CustomEvent)?.detail?.target?.value || + ((e as any).target as HTMLTextAreaElement).value + const trimmedValue = value.trim() + updateCodeActionPrompt(activeCodeActionTab, trimmedValue || undefined) + }} + rows={4} + resize="vertical" + style={{ width: "100%" }} + /> +
+
+

Prompt Enhancement