From d1f7b65d60b602ae5576c46a8794bfb95c5fa340 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sat, 28 Feb 2026 07:30:18 +0000 Subject: [PATCH] feat: add overrideSystemPrompt option for custom modes When overrideSystemPrompt is true on a ModeConfig, the system prompt uses only the roleDefinition as its body, skipping all standard sections (CAPABILITIES, TOOL USE, MODES, SKILLS, RULES, SYSTEM INFO, OBJECTIVE, MARKDOWN RULES). Custom instructions from .roo/rules-* files and global settings are still appended. This gives power users full control over the system prompt for specialized workflows while maintaining backward compatibility -- the flag defaults to false/undefined so existing modes are unaffected. Closes #11793 --- packages/types/src/mode.ts | 1 + .../prompts/__tests__/system-prompt.spec.ts | 138 ++++++++++++++++++ src/core/prompts/system.ts | 17 +++ 3 files changed, 156 insertions(+) diff --git a/packages/types/src/mode.ts b/packages/types/src/mode.ts index f981ba7bf9a..5917b34ebd3 100644 --- a/packages/types/src/mode.ts +++ b/packages/types/src/mode.ts @@ -102,6 +102,7 @@ export const modeConfigSchema = z.object({ customInstructions: z.string().optional(), groups: groupEntryArraySchema, source: z.enum(["global", "project"]).optional(), + overrideSystemPrompt: z.boolean().optional(), }) export type ModeConfig = z.infer diff --git a/src/core/prompts/__tests__/system-prompt.spec.ts b/src/core/prompts/__tests__/system-prompt.spec.ts index f555daba060..ca5a749134b 100644 --- a/src/core/prompts/__tests__/system-prompt.spec.ts +++ b/src/core/prompts/__tests__/system-prompt.spec.ts @@ -575,6 +575,144 @@ describe("SYSTEM_PROMPT", () => { expect(prompt).toContain("OBJECTIVE") }) + describe("overrideSystemPrompt", () => { + it("should use only roleDefinition + custom instructions when overrideSystemPrompt is true", async () => { + const customModes: ModeConfig[] = [ + { + slug: "custom-override", + name: "Custom Override", + roleDefinition: "You are a fully custom assistant with complete override.", + customInstructions: "Follow these custom mode instructions.", + groups: ["read", "edit"], + overrideSystemPrompt: true, + }, + ] + + const prompt = await SYSTEM_PROMPT( + mockContext, + "/test/path", + false, + undefined, // mcpHub + undefined, // diffStrategy + "custom-override" as Mode, + undefined, // customModePrompts + customModes, + "Global instructions here", // globalCustomInstructions + experiments, + undefined, // language + undefined, // rooIgnoreInstructions + ) + + // Should contain the roleDefinition + expect(prompt).toContain("You are a fully custom assistant with complete override.") + + // Should NOT contain standard sections + expect(prompt).not.toContain("CAPABILITIES") + expect(prompt).not.toContain("TOOL USE") + expect(prompt).not.toContain("MODES") + expect(prompt).not.toContain("SYSTEM INFORMATION") + expect(prompt).not.toContain("OBJECTIVE") + expect(prompt).not.toContain("MARKDOWN RULES") + }) + + it("should still include custom instructions when overrideSystemPrompt is true", async () => { + const customModes: ModeConfig[] = [ + { + slug: "custom-override-instructions", + name: "Custom Override With Instructions", + roleDefinition: "You are a specialized assistant.", + customInstructions: "Mode-specific instructions here.", + groups: ["read"], + overrideSystemPrompt: true, + }, + ] + + const prompt = await SYSTEM_PROMPT( + mockContext, + "/test/path", + false, + undefined, // mcpHub + undefined, // diffStrategy + "custom-override-instructions" as Mode, + undefined, // customModePrompts + customModes, + "Global custom instructions.", // globalCustomInstructions + experiments, + undefined, // language + undefined, // rooIgnoreInstructions + ) + + // Should contain custom instructions section + expect(prompt).toContain("USER'S CUSTOM INSTRUCTIONS") + expect(prompt).toContain("Mode-specific instructions here.") + }) + + it("should behave normally when overrideSystemPrompt is false", async () => { + const customModes: ModeConfig[] = [ + { + slug: "custom-normal", + name: "Custom Normal", + roleDefinition: "You are a normal custom assistant.", + groups: ["read", "edit"], + overrideSystemPrompt: false, + }, + ] + + const prompt = await SYSTEM_PROMPT( + mockContext, + "/test/path", + false, + undefined, // mcpHub + undefined, // diffStrategy + "custom-normal" as Mode, + undefined, // customModePrompts + customModes, + undefined, // globalCustomInstructions + experiments, + undefined, // language + undefined, // rooIgnoreInstructions + ) + + // Should contain standard sections + expect(prompt).toContain("CAPABILITIES") + expect(prompt).toContain("TOOL USE") + expect(prompt).toContain("SYSTEM INFORMATION") + expect(prompt).toContain("OBJECTIVE") + }) + + it("should behave normally when overrideSystemPrompt is not set", async () => { + const customModes: ModeConfig[] = [ + { + slug: "custom-unset", + name: "Custom Unset", + roleDefinition: "You are a custom assistant without override flag.", + groups: ["read"], + }, + ] + + const prompt = await SYSTEM_PROMPT( + mockContext, + "/test/path", + false, + undefined, // mcpHub + undefined, // diffStrategy + "custom-unset" as Mode, + undefined, // customModePrompts + customModes, + undefined, // globalCustomInstructions + experiments, + undefined, // language + undefined, // rooIgnoreInstructions + ) + + // Should contain standard sections (default behavior) + expect(prompt).toContain("CAPABILITIES") + expect(prompt).toContain("TOOL USE") + expect(prompt).toContain("SYSTEM INFORMATION") + expect(prompt).toContain("OBJECTIVE") + }) + }) + afterAll(() => { vi.restoreAllMocks() }) diff --git a/src/core/prompts/system.ts b/src/core/prompts/system.ts index 0d6071644a9..85f189788d0 100644 --- a/src/core/prompts/system.ts +++ b/src/core/prompts/system.ts @@ -64,6 +64,23 @@ async function generatePrompt( const modeConfig = getModeBySlug(mode, customModeConfigs) || modes.find((m) => m.slug === mode) || modes[0] const { roleDefinition, baseInstructions } = getModeSelection(mode, promptComponent, customModeConfigs) + // When overrideSystemPrompt is true, use roleDefinition as the entire system prompt + // body, only appending custom instructions. All standard sections are skipped. + if (modeConfig.overrideSystemPrompt) { + const customInstructionsSection = await addCustomInstructions( + baseInstructions, + globalCustomInstructions || "", + cwd, + mode, + { + language: language ?? formatLanguage(vscode.env.language), + rooIgnoreInstructions, + settings, + }, + ) + return `${roleDefinition}${customInstructionsSection}` + } + // Check if MCP functionality should be included const hasMcpGroup = modeConfig.groups.some((groupEntry) => getGroupName(groupEntry) === "mcp") const hasMcpServers = mcpHub && mcpHub.getServers().length > 0