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
This commit is contained in:
sam hoang
2025-01-23 00:31:43 +07:00
parent 7845791720
commit 22907a0578
9 changed files with 467 additions and 268 deletions

View File

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

View File

@@ -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")
})
})
})

View File

@@ -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 }])),

View File

@@ -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