fix(prompts): dynamically list active tools in Plan Mode system prompt

- Updates `PromptProvider` to retrieve and alphabetically sort the active tools from `ToolRegistry` for the Plan Mode prompt list.
- Removes hardcoded descriptions for `write_file` and `replace` from `snippets.ts` and `snippets.legacy.ts` as they are now dynamically included.
- Modifies verbiage in Plan Mode instructions to reflect that tools may not be exclusively "read-only" when workspace policies apply overrides.
- Updates snapshot assertions and prompt test mocks to verify the correct dynamic and sorted injection of tool descriptions.
This commit is contained in:
Mahima Shanware
2026-02-24 00:07:42 +00:00
parent 3e5a250b6f
commit 2c7a62049e
5 changed files with 29 additions and 54 deletions

View File

@@ -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:
<tool>\`glob\`</tool>
<tool>\`grep_search\`</tool>
- \`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:
<tool>\`glob\`</tool>
<tool>\`grep_search\`</tool>
- \`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:
<tool>\`glob\`</tool>
<tool>\`grep_search\`</tool>
- \`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/\`

View File

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

View File

@@ -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) => ` <tool>\`${t}\`</tool>`)
.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) => ` <tool>\`${t.name}\` (${t.serverName})</tool>`)
.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 ` <tool>\`${t.name}\`${serverSuffix}</tool>`;
})
.join('\n');
}
let basePrompt: string;

View File

@@ -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}/\`

View File

@@ -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:
<available_tools>
${options.planModeToolsList}
<tool>${formatToolName(WRITE_FILE_TOOL_NAME)} - Save plans to the plans directory</tool>
<tool>${formatToolName(EDIT_TOOL_NAME)} - Update plans in the plans directory</tool>
</available_tools>
## Rules