From 375c104b325a64b76f0ba7650c65a429cad47496 Mon Sep 17 00:00:00 2001 From: Jerop Kipruto Date: Sun, 8 Feb 2026 20:57:01 -0500 Subject: [PATCH] fix(core): ensure `enter_plan_mode` tool registration respects `experimental.plan` (#18587) --- packages/core/src/config/config.test.ts | 24 +++++++++++++++++++++++- packages/core/src/config/config.ts | 10 ++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index 312c1b5b0a..d2c460d240 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -2333,10 +2333,11 @@ describe('syncPlanModeTools', () => { expect(registeredTool).toBeInstanceOf(ExitPlanModeTool); }); - it('should register EnterPlanModeTool and unregister ExitPlanModeTool when NOT in PLAN mode', async () => { + it('should register EnterPlanModeTool and unregister ExitPlanModeTool when NOT in PLAN mode and experimental.plan is enabled', async () => { const config = new Config({ ...baseParams, approvalMode: ApprovalMode.DEFAULT, + plan: true, }); const registry = new ToolRegistry(config, config.getMessageBus()); vi.spyOn(config, 'getToolRegistry').mockReturnValue(registry); @@ -2360,6 +2361,27 @@ describe('syncPlanModeTools', () => { expect(registeredTool).toBeInstanceOf(EnterPlanModeTool); }); + it('should NOT register EnterPlanModeTool when experimental.plan is disabled', async () => { + const config = new Config({ + ...baseParams, + approvalMode: ApprovalMode.DEFAULT, + plan: false, + }); + const registry = new ToolRegistry(config, config.getMessageBus()); + vi.spyOn(config, 'getToolRegistry').mockReturnValue(registry); + + const registerSpy = vi.spyOn(registry, 'registerTool'); + vi.spyOn(registry, 'getTool').mockReturnValue(undefined); + + config.syncPlanModeTools(); + + const { EnterPlanModeTool } = await import('../tools/enter-plan-mode.js'); + const registeredTool = registerSpy.mock.calls.find( + (call) => call[0] instanceof EnterPlanModeTool, + ); + expect(registeredTool).toBeUndefined(); + }); + it('should call geminiClient.setTools if initialized', async () => { const config = new Config(baseParams); const registry = new ToolRegistry(config, config.getMessageBus()); diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 4df65f51a2..92e20f9163 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -1540,8 +1540,14 @@ export class Config { if (registry.getTool(EXIT_PLAN_MODE_TOOL_NAME)) { registry.unregisterTool(EXIT_PLAN_MODE_TOOL_NAME); } - if (!registry.getTool(ENTER_PLAN_MODE_TOOL_NAME)) { - registry.registerTool(new EnterPlanModeTool(this, this.messageBus)); + if (this.planEnabled) { + if (!registry.getTool(ENTER_PLAN_MODE_TOOL_NAME)) { + registry.registerTool(new EnterPlanModeTool(this, this.messageBus)); + } + } else { + if (registry.getTool(ENTER_PLAN_MODE_TOOL_NAME)) { + registry.unregisterTool(ENTER_PLAN_MODE_TOOL_NAME); + } } }