diff --git a/packages/core/src/core/__snapshots__/prompts.test.ts.snap b/packages/core/src/core/__snapshots__/prompts.test.ts.snap index 0028a052de..3ebee1c156 100644 --- a/packages/core/src/core/__snapshots__/prompts.test.ts.snap +++ b/packages/core/src/core/__snapshots__/prompts.test.ts.snap @@ -42,11 +42,9 @@ For example: You are operating in **Plan Mode** - a structured planning workflow for designing implementation strategies before execution. ## Available Tools -The following read-only tools are available in Plan Mode: +The following tools are available in Plan Mode: \`glob\` \`grep_search\` -- \`write_file\` - Save plans to the plans directory (see Plan Storage below) -- \`replace\` - Update plans in the plans directory ## Plan Storage - Save your plans as Markdown (.md) files ONLY within: \`/tmp/plans/\` @@ -174,11 +172,9 @@ For example: You are operating in **Plan Mode** - a structured planning workflow for designing implementation strategies before execution. ## Available Tools -The following read-only tools are available in Plan Mode: +The following tools are available in Plan Mode: \`glob\` \`grep_search\` -- \`write_file\` - Save plans to the plans directory (see Plan Storage below) -- \`replace\` - Update plans in the plans directory ## Plan Storage - Save your plans as Markdown (.md) files ONLY within: \`/tmp/plans/\` @@ -424,11 +420,9 @@ For example: You are operating in **Plan Mode** - a structured planning workflow for designing implementation strategies before execution. ## Available Tools -The following read-only tools are available in Plan Mode: +The following tools are available in Plan Mode: \`glob\` \`grep_search\` -- \`write_file\` - Save plans to the plans directory (see Plan Storage below) -- \`replace\` - Update plans in the plans directory ## Plan Storage - Save your plans as Markdown (.md) files ONLY within: \`/tmp/project-temp/plans/\` diff --git a/packages/core/src/core/prompts.test.ts b/packages/core/src/core/prompts.test.ts index 0cee2f8ae4..94354847a0 100644 --- a/packages/core/src/core/prompts.test.ts +++ b/packages/core/src/core/prompts.test.ts @@ -25,6 +25,7 @@ import { } from '../config/models.js'; import { ApprovalMode } from '../policy/types.js'; import { DiscoveredMCPTool } from '../tools/mcp-tool.js'; +import type { AnyDeclarativeTool } from '../tools/tool-registry.js'; import type { CallableTool } from '@google/genai'; import type { MessageBus } from '../confirmation-bus/message-bus.js'; @@ -85,6 +86,12 @@ describe('Core System Prompt (prompts.ts)', () => { getToolRegistry: vi.fn().mockReturnValue({ getAllToolNames: vi.fn().mockReturnValue(['grep_search', 'glob']), getAllTools: vi.fn().mockReturnValue([]), + getActiveTools: vi + .fn() + .mockReturnValue([ + { name: 'grep_search' } as unknown as AnyDeclarativeTool, + { name: 'glob' } as unknown as AnyDeclarativeTool, + ]), }), getEnableShellOutputEfficiency: vi.fn().mockReturnValue(true), storage: { @@ -452,24 +459,11 @@ describe('Core System Prompt (prompts.ts)', () => { true, // isReadOnly ); - const nonReadOnlyMcpTool = new DiscoveredMCPTool( - {} as CallableTool, - 'nonreadonly-server', - 'non_read_static_value', - 'A non-read-only tool', - {}, - {} as MessageBus, - false, - false, - ); + // Note: non-read-only MCP tools are implicitly filtered out by the logic + // because they are not potentially allowed in Plan Mode by default. - vi.mocked(mockConfig.getToolRegistry().getAllTools).mockReturnValue([ + vi.mocked(mockConfig.getToolRegistry().getActiveTools).mockReturnValue([ readOnlyMcpTool, - nonReadOnlyMcpTool, - ]); - vi.mocked(mockConfig.getToolRegistry().getAllToolNames).mockReturnValue([ - readOnlyMcpTool.name, - nonReadOnlyMcpTool.name, ]); const prompt = getCoreSystemPrompt(mockConfig); @@ -483,10 +477,10 @@ describe('Core System Prompt (prompts.ts)', () => { it('should only list available tools in PLAN mode', () => { vi.mocked(mockConfig.getApprovalMode).mockReturnValue(ApprovalMode.PLAN); // Only enable a subset of tools, including ask_user - vi.mocked(mockConfig.getToolRegistry().getAllToolNames).mockReturnValue([ - 'glob', - 'read_file', - 'ask_user', + vi.mocked(mockConfig.getToolRegistry().getActiveTools).mockReturnValue([ + { name: 'glob' } as unknown as AnyDeclarativeTool, + { name: 'read_file' } as unknown as AnyDeclarativeTool, + { name: 'ask_user' } as unknown as AnyDeclarativeTool, ]); const prompt = getCoreSystemPrompt(mockConfig); diff --git a/packages/core/src/prompts/promptProvider.ts b/packages/core/src/prompts/promptProvider.ts index 4f1a3afbff..0e2be603ee 100644 --- a/packages/core/src/prompts/promptProvider.ts +++ b/packages/core/src/prompts/promptProvider.ts @@ -22,7 +22,6 @@ import { import { CodebaseInvestigatorAgent } from '../agents/codebase-investigator.js'; import { isGitRepository } from '../utils/gitUtils.js'; import { - PLAN_MODE_TOOLS, WRITE_TODOS_TOOL_NAME, READ_FILE_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME, @@ -67,25 +66,17 @@ export class PromptProvider { const contextFilenames = getAllGeminiMdFilenames(); // --- Context Gathering --- - let planModeToolsList = PLAN_MODE_TOOLS.filter((t) => - enabledToolNames.has(t), - ) - .map((t) => ` \`${t}\``) - .join('\n'); - - // Add read-only MCP tools to the list + let planModeToolsList = ''; if (isPlanMode) { - const allTools = config.getToolRegistry().getAllTools(); - const readOnlyMcpTools = allTools.filter( - (t): t is DiscoveredMCPTool => - t instanceof DiscoveredMCPTool && !!t.isReadOnly, - ); - if (readOnlyMcpTools.length > 0) { - const mcpToolsList = readOnlyMcpTools - .map((t) => ` \`${t.name}\` (${t.serverName})`) - .join('\n'); - planModeToolsList += `\n${mcpToolsList}`; - } + const activeTools = config.getToolRegistry().getActiveTools(); + activeTools.sort((a, b) => a.name.localeCompare(b.name)); + planModeToolsList = activeTools + .map((t) => { + const serverSuffix = + t instanceof DiscoveredMCPTool ? ` (${t.serverName})` : ''; + return ` \`${t.name}\`${serverSuffix}`; + }) + .join('\n'); } let basePrompt: string; diff --git a/packages/core/src/prompts/snippets.legacy.ts b/packages/core/src/prompts/snippets.legacy.ts index 3671490089..33a4d6ddd2 100644 --- a/packages/core/src/prompts/snippets.legacy.ts +++ b/packages/core/src/prompts/snippets.legacy.ts @@ -398,10 +398,8 @@ export function renderPlanningWorkflow( You are operating in **Plan Mode** - a structured planning workflow for designing implementation strategies before execution. ## Available Tools -The following read-only tools are available in Plan Mode: +The following tools are available in Plan Mode: ${options.planModeToolsList} -- \`${WRITE_FILE_TOOL_NAME}\` - Save plans to the plans directory (see Plan Storage below) -- \`${EDIT_TOOL_NAME}\` - Update plans in the plans directory ## Plan Storage - Save your plans as Markdown (.md) files ONLY within: \`${options.plansDir}/\` diff --git a/packages/core/src/prompts/snippets.ts b/packages/core/src/prompts/snippets.ts index f7ea9b1eee..c6fbc2fb0a 100644 --- a/packages/core/src/prompts/snippets.ts +++ b/packages/core/src/prompts/snippets.ts @@ -452,11 +452,9 @@ export function renderPlanningWorkflow( You are operating in **Plan Mode**. Your goal is to produce a detailed implementation plan in \`${options.plansDir}/\` and get user approval before editing source code. ## Available Tools -The following read-only tools are available in Plan Mode: +The following tools are available in Plan Mode: ${options.planModeToolsList} - ${formatToolName(WRITE_FILE_TOOL_NAME)} - Save plans to the plans directory - ${formatToolName(EDIT_TOOL_NAME)} - Update plans in the plans directory ## Rules