Roo-Code/src/core/prompts/system.ts
NaccOll d90bab71ff
feat: code indexing support multiple folder similar with task history (#6204)
* feat: Implement code indexing support multi-folder workspaces similar to task history

* fix: add missing mock for onDidChangeActiveTextEditor in tests
2025-08-04 19:39:37 -07:00

225 lines
6.3 KiB
TypeScript

import * as vscode from "vscode"
import * as os from "os"
import type { ModeConfig, PromptComponent, CustomModePrompts, TodoItem } from "@roo-code/types"
import type { SystemPromptSettings } from "./types"
import { Mode, modes, defaultModeSlug, getModeBySlug, getGroupName, getModeSelection } from "../../shared/modes"
import { DiffStrategy } from "../../shared/tools"
import { formatLanguage } from "../../shared/language"
import { isEmpty } from "../../utils/object"
import { McpHub } from "../../services/mcp/McpHub"
import { CodeIndexManager } from "../../services/code-index/manager"
import { PromptVariables, loadSystemPromptFile } from "./sections/custom-system-prompt"
import { getToolDescriptionsForMode } from "./tools"
import {
getRulesSection,
getSystemInfoSection,
getObjectiveSection,
getSharedToolUseSection,
getMcpServersSection,
getToolUseGuidelinesSection,
getCapabilitiesSection,
getModesSection,
addCustomInstructions,
markdownFormattingSection,
} from "./sections"
// Helper function to get prompt component, filtering out empty objects
export function getPromptComponent(
customModePrompts: CustomModePrompts | undefined,
mode: string,
): PromptComponent | undefined {
const component = customModePrompts?.[mode]
// Return undefined if component is empty
if (isEmpty(component)) {
return undefined
}
return component
}
async function generatePrompt(
context: vscode.ExtensionContext,
cwd: string,
supportsComputerUse: boolean,
mode: Mode,
mcpHub?: McpHub,
diffStrategy?: DiffStrategy,
browserViewportSize?: string,
promptComponent?: PromptComponent,
customModeConfigs?: ModeConfig[],
globalCustomInstructions?: string,
diffEnabled?: boolean,
experiments?: Record<string, boolean>,
enableMcpServerCreation?: boolean,
language?: string,
rooIgnoreInstructions?: string,
partialReadsEnabled?: boolean,
settings?: SystemPromptSettings,
todoList?: TodoItem[],
): Promise<string> {
if (!context) {
throw new Error("Extension context is required for generating system prompt")
}
// If diff is disabled, don't pass the diffStrategy
const effectiveDiffStrategy = diffEnabled ? diffStrategy : undefined
// Get the full mode config to ensure we have the role definition (used for groups, etc.)
const modeConfig = getModeBySlug(mode, customModeConfigs) || modes.find((m) => m.slug === mode) || modes[0]
const { roleDefinition, baseInstructions } = getModeSelection(mode, promptComponent, customModeConfigs)
// Check if MCP functionality should be included
const hasMcpGroup = modeConfig.groups.some((groupEntry) => getGroupName(groupEntry) === "mcp")
const hasMcpServers = mcpHub && mcpHub.getServers().length > 0
const shouldIncludeMcp = hasMcpGroup && hasMcpServers
const [modesSection, mcpServersSection] = await Promise.all([
getModesSection(context),
shouldIncludeMcp
? getMcpServersSection(mcpHub, effectiveDiffStrategy, enableMcpServerCreation)
: Promise.resolve(""),
])
const codeIndexManager = CodeIndexManager.getInstance(context, cwd)
const basePrompt = `${roleDefinition}
${markdownFormattingSection()}
${getSharedToolUseSection()}
${getToolDescriptionsForMode(
mode,
cwd,
supportsComputerUse,
codeIndexManager,
effectiveDiffStrategy,
browserViewportSize,
shouldIncludeMcp ? mcpHub : undefined,
customModeConfigs,
experiments,
partialReadsEnabled,
settings,
enableMcpServerCreation,
)}
${getToolUseGuidelinesSection(codeIndexManager)}
${mcpServersSection}
${getCapabilitiesSection(cwd, supportsComputerUse, shouldIncludeMcp ? mcpHub : undefined, effectiveDiffStrategy, codeIndexManager)}
${modesSection}
${getRulesSection(cwd, supportsComputerUse, effectiveDiffStrategy, codeIndexManager)}
${getSystemInfoSection(cwd)}
${getObjectiveSection(codeIndexManager, experiments)}
${await addCustomInstructions(baseInstructions, globalCustomInstructions || "", cwd, mode, {
language: language ?? formatLanguage(vscode.env.language),
rooIgnoreInstructions,
settings,
})}`
return basePrompt
}
export const SYSTEM_PROMPT = async (
context: vscode.ExtensionContext,
cwd: string,
supportsComputerUse: boolean,
mcpHub?: McpHub,
diffStrategy?: DiffStrategy,
browserViewportSize?: string,
mode: Mode = defaultModeSlug,
customModePrompts?: CustomModePrompts,
customModes?: ModeConfig[],
globalCustomInstructions?: string,
diffEnabled?: boolean,
experiments?: Record<string, boolean>,
enableMcpServerCreation?: boolean,
language?: string,
rooIgnoreInstructions?: string,
partialReadsEnabled?: boolean,
settings?: SystemPromptSettings,
todoList?: TodoItem[],
): Promise<string> => {
if (!context) {
throw new Error("Extension context is required for generating system prompt")
}
// Try to load custom system prompt from file
const variablesForPrompt: PromptVariables = {
workspace: cwd,
mode: mode,
language: language ?? formatLanguage(vscode.env.language),
shell: vscode.env.shell,
operatingSystem: os.type(),
}
const fileCustomSystemPrompt = await loadSystemPromptFile(cwd, mode, variablesForPrompt)
// Check if it's a custom mode
const promptComponent = getPromptComponent(customModePrompts, mode)
// Get full mode config from custom modes or fall back to built-in modes
const currentMode = getModeBySlug(mode, customModes) || modes.find((m) => m.slug === mode) || modes[0]
// If a file-based custom system prompt exists, use it
if (fileCustomSystemPrompt) {
const { roleDefinition, baseInstructions: baseInstructionsForFile } = getModeSelection(
mode,
promptComponent,
customModes,
)
const customInstructions = await addCustomInstructions(
baseInstructionsForFile,
globalCustomInstructions || "",
cwd,
mode,
{
language: language ?? formatLanguage(vscode.env.language),
rooIgnoreInstructions,
settings,
},
)
// For file-based prompts, don't include the tool sections
return `${roleDefinition}
${fileCustomSystemPrompt}
${customInstructions}`
}
// If diff is disabled, don't pass the diffStrategy
const effectiveDiffStrategy = diffEnabled ? diffStrategy : undefined
return generatePrompt(
context,
cwd,
supportsComputerUse,
currentMode.slug,
mcpHub,
effectiveDiffStrategy,
browserViewportSize,
promptComponent,
customModes,
globalCustomInstructions,
diffEnabled,
experiments,
enableMcpServerCreation,
language,
rooIgnoreInstructions,
partialReadsEnabled,
settings,
todoList,
)
}