Browse Source

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
sam hoang 1 year ago
parent
commit
22907a0578

+ 0 - 76
src/core/prompts/__tests__/code-actions.test.ts

@@ -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');
-        });
-    });
-});

+ 0 - 87
src/core/prompts/code-actions.ts

@@ -1,87 +0,0 @@
-type PromptParams = Record<string, string | any[]>;
-
-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
-}

+ 56 - 29
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<string, string | any[]>
+		params: Record<string, string | any[]>,
 	): Promise<void> {
-		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
+							}
+
+							const existingPrompts = ((await this.getGlobalState("customPrompts")) || {}) as Record<
+								string,
+								any
+							>
 
-						await this.updateGlobalState("customPrompts", updatedPrompts)
+							const updatedPrompts = {
+								...existingPrompts,
+							}
 
-						// Get current state and explicitly include customPrompts
-						const currentState = await this.getState()
+							updatedPrompts[message.text] = undefined
 
-						const stateWithPrompts = {
-							...currentState,
-							customPrompts: updatedPrompts,
+							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) {

+ 34 - 36
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
-				});
-
-				const params = {
-					filePath,
-					selectedText,
-					...(diagnostics ? { diagnostics } : {}),
-					...(userInput ? { userInput } : {})
-				};
-
-				await ClineProvider.handleCodeAction(promptType, params);
-			})
-		);
-	};
+			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 } : {}),
+					}
+
+					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)
 }

+ 2 - 1
src/shared/WebviewMessage.ts

@@ -68,7 +68,8 @@ export interface WebviewMessage {
 		| "requestVsCodeLmModels"
 		| "mode"
 		| "updatePrompt"
-		| "updateEnhancedPrompt"
+		| "updateSupportPrompt"
+		| "resetSupportPrompt"
 		| "getSystemPrompt"
 		| "systemPrompt"
 		| "enhancementApiConfigId"

+ 138 - 0
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")
+		})
+	})
+})

+ 10 - 27
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<string>()
@@ -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<string, any> | undefined): string => {
-		return customPrompts?.enhance ?? enhance.prompt
-	},
-} as const
-
 // Create the mode-specific default prompts
 export const defaultPrompts: Readonly<CustomPrompts> = Object.freeze(
 	Object.fromEntries(modes.map((mode) => [mode.slug, { roleDefinition: mode.roleDefinition }])),

+ 118 - 0
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<string, any> | undefined): string => {
+		return customPrompts?.enhance ?? enhance.prompt
+	},
+} as const
+
+// Code action prompts
+type PromptParams = Record<string, string | any[]>
+
+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<string, any> | undefined, type: CodeActionType): string => {
+		return customPrompts?.[type] ?? defaultTemplates[type]
+	},
+	create: (type: CodeActionType, params: PromptParams, customPrompts?: Record<string, any>): 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<CodeActionType, string> = {
+	FIX: "Fix Issues",
+	EXPLAIN: "Explain Code",
+	IMPROVE: "Improve Code",
+} as const

+ 111 - 14
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<CodeActionType>("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) => {
 						<VSCodeTextArea
 							value={(() => {
 								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) => {
 						<VSCodeTextArea
 							value={(() => {
 								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) => {
 					</VSCodeButton>
 				</div>
 
+				<div style={{ marginBottom: "20px" }}>
+					<div style={{ fontWeight: "bold", marginBottom: "12px" }}>Code Action Prompts</div>
+					<div
+						style={{
+							display: "flex",
+							gap: "16px",
+							alignItems: "center",
+							marginBottom: "12px",
+							overflowX: "auto",
+							flexWrap: "nowrap",
+							paddingBottom: "4px",
+							paddingRight: "20px",
+						}}>
+						{Object.keys(codeActionPrompt.default).map((type) => (
+							<button
+								key={type}
+								data-testid={`${type}-tab`}
+								data-active={activeCodeActionTab === type ? "true" : "false"}
+								onClick={() => setActiveCodeActionTab(type as CodeActionType)}
+								style={{
+									padding: "4px 8px",
+									border: "none",
+									background:
+										activeCodeActionTab === type ? "var(--vscode-button-background)" : "none",
+									color:
+										activeCodeActionTab === type
+											? "var(--vscode-button-foreground)"
+											: "var(--vscode-foreground)",
+									cursor: "pointer",
+									opacity: activeCodeActionTab === type ? 1 : 0.8,
+									borderRadius: "3px",
+									fontWeight: "bold",
+								}}>
+								{codeActionLabels[type as CodeActionType]}
+							</button>
+						))}
+					</div>
+
+					{/* Show active tab content */}
+					<div key={activeCodeActionTab}>
+						<div
+							style={{
+								display: "flex",
+								justifyContent: "space-between",
+								alignItems: "center",
+								marginBottom: "4px",
+							}}>
+							<div style={{ fontWeight: "bold" }}>{activeCodeActionTab} Prompt</div>
+							<VSCodeButton
+								appearance="icon"
+								onClick={() => handleCodeActionReset(activeCodeActionTab)}
+								title={`Reset ${activeCodeActionTab} prompt to default`}>
+								<span className="codicon codicon-discard"></span>
+							</VSCodeButton>
+						</div>
+						<VSCodeTextArea
+							value={getCodeActionPromptValue(activeCodeActionTab)}
+							onChange={(e) => {
+								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%" }}
+						/>
+					</div>
+				</div>
+
 				<h3 style={{ color: "var(--vscode-foreground)", margin: "40px 0 20px 0" }}>Prompt Enhancement</h3>
 
 				<div