mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-14 23:21:19 +00:00
feat: add systemPrompt property to ModeConfig for custom system prompt override
This commit is contained in:
parent
8ef61bd32b
commit
d4914ef91b
3 changed files with 197 additions and 0 deletions
|
|
@ -70,6 +70,12 @@ export const modeConfigSchema = z.object({
|
|||
customInstructions: z.string().optional(),
|
||||
groups: groupEntryArraySchema,
|
||||
source: z.enum(["global", "project"]).optional(),
|
||||
/**
|
||||
* When provided, replaces the middle sections of the generated system prompt
|
||||
* (CAPABILITIES, TOOL USE, OBJECTIVE, etc.) with this custom content.
|
||||
* The final prompt will be: roleDefinition + systemPrompt + customInstructions
|
||||
*/
|
||||
systemPrompt: z.string().optional(),
|
||||
})
|
||||
|
||||
export type ModeConfig = z.infer<typeof modeConfigSchema>
|
||||
|
|
|
|||
|
|
@ -626,6 +626,169 @@ describe("SYSTEM_PROMPT", () => {
|
|||
expect(prompt).toContain("OBJECTIVE")
|
||||
})
|
||||
|
||||
describe("systemPrompt override", () => {
|
||||
it("should use systemPrompt from mode config when provided", async () => {
|
||||
const customSystemPrompt = "This is a custom system prompt that replaces the default sections."
|
||||
|
||||
const customModes: ModeConfig[] = [
|
||||
{
|
||||
slug: "minimal-mode",
|
||||
name: "Minimal Mode",
|
||||
roleDefinition: "You are a minimal assistant.",
|
||||
customInstructions: "Be concise.",
|
||||
groups: ["mcp"] as const,
|
||||
systemPrompt: customSystemPrompt,
|
||||
},
|
||||
]
|
||||
|
||||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
false,
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
"minimal-mode", // mode
|
||||
undefined, // customModePrompts
|
||||
customModes, // customModes
|
||||
"Global instructions", // globalCustomInstructions
|
||||
experiments, // experiments
|
||||
undefined, // language
|
||||
undefined, // rooIgnoreInstructions
|
||||
undefined, // settings
|
||||
)
|
||||
|
||||
// Should contain the custom systemPrompt
|
||||
expect(prompt).toContain(customSystemPrompt)
|
||||
|
||||
// Should contain role definition at the top
|
||||
expect(prompt).toContain("You are a minimal assistant.")
|
||||
expect(prompt.indexOf("You are a minimal assistant.")).toBeLessThan(prompt.indexOf(customSystemPrompt))
|
||||
|
||||
// Should NOT contain the default sections (TOOL USE, CAPABILITIES, OBJECTIVE, etc.)
|
||||
expect(prompt).not.toContain("TOOL USE")
|
||||
expect(prompt).not.toContain("CAPABILITIES")
|
||||
expect(prompt).not.toContain("OBJECTIVE")
|
||||
expect(prompt).not.toContain("MARKDOWN RULES")
|
||||
})
|
||||
|
||||
it("should include customInstructions when using systemPrompt override", async () => {
|
||||
const customSystemPrompt = "Custom system prompt content."
|
||||
const modeCustomInstructions = "Be concise."
|
||||
|
||||
const customModes: ModeConfig[] = [
|
||||
{
|
||||
slug: "minimal-mode",
|
||||
name: "Minimal Mode",
|
||||
roleDefinition: "You are a minimal assistant.",
|
||||
customInstructions: modeCustomInstructions,
|
||||
groups: ["mcp"] as const,
|
||||
systemPrompt: customSystemPrompt,
|
||||
},
|
||||
]
|
||||
|
||||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
false,
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
"minimal-mode", // mode
|
||||
undefined, // customModePrompts
|
||||
customModes, // customModes
|
||||
"Global instructions", // globalCustomInstructions
|
||||
experiments, // experiments
|
||||
undefined, // language
|
||||
undefined, // rooIgnoreInstructions
|
||||
undefined, // settings
|
||||
)
|
||||
|
||||
// Should contain the customInstructions
|
||||
expect(prompt).toContain(modeCustomInstructions)
|
||||
|
||||
// Custom instructions should come after the systemPrompt
|
||||
expect(prompt.indexOf(customSystemPrompt)).toBeLessThan(prompt.indexOf(modeCustomInstructions))
|
||||
})
|
||||
|
||||
it("should use default sections when systemPrompt is not provided", async () => {
|
||||
const customModes: ModeConfig[] = [
|
||||
{
|
||||
slug: "regular-mode",
|
||||
name: "Regular Mode",
|
||||
roleDefinition: "You are a regular assistant.",
|
||||
customInstructions: "Follow all guidelines.",
|
||||
groups: ["read"] as const,
|
||||
// No systemPrompt provided
|
||||
},
|
||||
]
|
||||
|
||||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
false,
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
"regular-mode", // mode
|
||||
undefined, // customModePrompts
|
||||
customModes, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
experiments, // experiments
|
||||
undefined, // language
|
||||
undefined, // rooIgnoreInstructions
|
||||
undefined, // settings
|
||||
)
|
||||
|
||||
// Should contain the default sections
|
||||
expect(prompt).toContain("TOOL USE")
|
||||
expect(prompt).toContain("CAPABILITIES")
|
||||
expect(prompt).toContain("OBJECTIVE")
|
||||
})
|
||||
|
||||
it("should prioritize file-based system prompt over config systemPrompt", async () => {
|
||||
// Mock fs to return a file-based system prompt
|
||||
const fsMock = vi.mocked(await import("fs/promises"))
|
||||
fsMock.readFile.mockResolvedValueOnce("File-based system prompt content.")
|
||||
|
||||
const customSystemPrompt = "Config-based system prompt content."
|
||||
|
||||
const customModes: ModeConfig[] = [
|
||||
{
|
||||
slug: "priority-mode",
|
||||
name: "Priority Mode",
|
||||
roleDefinition: "You are a priority assistant.",
|
||||
customInstructions: "Test instructions.",
|
||||
groups: ["read"] as const,
|
||||
systemPrompt: customSystemPrompt,
|
||||
},
|
||||
]
|
||||
|
||||
const prompt = await SYSTEM_PROMPT(
|
||||
mockContext,
|
||||
"/test/path",
|
||||
false,
|
||||
undefined, // mcpHub
|
||||
undefined, // diffStrategy
|
||||
undefined, // browserViewportSize
|
||||
"priority-mode", // mode
|
||||
undefined, // customModePrompts
|
||||
customModes, // customModes
|
||||
undefined, // globalCustomInstructions
|
||||
experiments, // experiments
|
||||
undefined, // language
|
||||
undefined, // rooIgnoreInstructions
|
||||
undefined, // settings
|
||||
)
|
||||
|
||||
// Should contain the file-based system prompt
|
||||
expect(prompt).toContain("File-based system prompt content.")
|
||||
|
||||
// Should NOT contain the config-based systemPrompt
|
||||
expect(prompt).not.toContain(customSystemPrompt)
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -177,6 +177,34 @@ export const SYSTEM_PROMPT = async (
|
|||
|
||||
${fileCustomSystemPrompt}
|
||||
|
||||
${customInstructions}`
|
||||
}
|
||||
|
||||
// If the mode config has a systemPrompt defined, use it as custom middle content
|
||||
if (currentMode.systemPrompt) {
|
||||
const { roleDefinition, baseInstructions: baseInstructionsForConfig } = getModeSelection(
|
||||
mode,
|
||||
promptComponent,
|
||||
customModes,
|
||||
)
|
||||
|
||||
const customInstructions = await addCustomInstructions(
|
||||
baseInstructionsForConfig,
|
||||
globalCustomInstructions || "",
|
||||
cwd,
|
||||
mode,
|
||||
{
|
||||
language: language ?? formatLanguage(vscode.env.language),
|
||||
rooIgnoreInstructions,
|
||||
settings,
|
||||
},
|
||||
)
|
||||
|
||||
// For config-based systemPrompt, use the simplified structure
|
||||
return `${roleDefinition}
|
||||
|
||||
${currentMode.systemPrompt}
|
||||
|
||||
${customInstructions}`
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue