mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 14:10:37 -07:00
fix(plan): exclude EnterPlanMode tool from YOLO mode (#19570)
This commit is contained in:
@@ -69,6 +69,7 @@ You can enter Plan Mode in three ways:
|
||||
2. **Command:** Type `/plan` in the input box.
|
||||
3. **Natural Language:** Ask the agent to "start a plan for...". The agent will
|
||||
then call the [`enter_plan_mode`] tool to switch modes.
|
||||
- **Note:** This tool is not available when the CLI is in YOLO mode.
|
||||
|
||||
### The Planning Workflow
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ by the agent when you ask it to "start a plan" using natural language. In this
|
||||
mode, the agent is restricted to read-only tools to allow for safe exploration
|
||||
and planning.
|
||||
|
||||
> **Note:** This tool is not available when the CLI is in YOLO mode.
|
||||
|
||||
- **Tool name:** `enter_plan_mode`
|
||||
- **Display name:** Enter Plan Mode
|
||||
- **File:** `enter-plan-mode.ts`
|
||||
|
||||
@@ -1392,7 +1392,22 @@ describe('setApprovalMode with folder trust', () => {
|
||||
expect(updateSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not update system instruction when switching between non-Plan modes', () => {
|
||||
it('should update system instruction when entering YOLO mode', () => {
|
||||
const config = new Config(baseParams);
|
||||
vi.spyOn(config, 'isTrustedFolder').mockReturnValue(true);
|
||||
vi.spyOn(config, 'getToolRegistry').mockReturnValue({
|
||||
getTool: vi.fn().mockReturnValue(undefined),
|
||||
unregisterTool: vi.fn(),
|
||||
registerTool: vi.fn(),
|
||||
} as Partial<ToolRegistry> as ToolRegistry);
|
||||
const updateSpy = vi.spyOn(config, 'updateSystemInstructionIfInitialized');
|
||||
|
||||
config.setApprovalMode(ApprovalMode.YOLO);
|
||||
|
||||
expect(updateSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not update system instruction when switching between non-Plan/non-YOLO modes', () => {
|
||||
const config = new Config(baseParams);
|
||||
vi.spyOn(config, 'isTrustedFolder').mockReturnValue(true);
|
||||
const updateSpy = vi.spyOn(config, 'updateSystemInstructionIfInitialized');
|
||||
@@ -2649,6 +2664,27 @@ describe('syncPlanModeTools', () => {
|
||||
expect(registeredTool).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should NOT register EnterPlanModeTool when in YOLO mode, even if plan is enabled', async () => {
|
||||
const config = new Config({
|
||||
...baseParams,
|
||||
approvalMode: ApprovalMode.YOLO,
|
||||
plan: true,
|
||||
});
|
||||
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());
|
||||
|
||||
@@ -1793,7 +1793,11 @@ export class Config {
|
||||
const isPlanModeTransition =
|
||||
currentMode !== mode &&
|
||||
(currentMode === ApprovalMode.PLAN || mode === ApprovalMode.PLAN);
|
||||
if (isPlanModeTransition) {
|
||||
const isYoloModeTransition =
|
||||
currentMode !== mode &&
|
||||
(currentMode === ApprovalMode.YOLO || mode === ApprovalMode.YOLO);
|
||||
|
||||
if (isPlanModeTransition || isYoloModeTransition) {
|
||||
this.syncPlanModeTools();
|
||||
this.updateSystemInstructionIfInitialized();
|
||||
}
|
||||
@@ -1803,8 +1807,13 @@ export class Config {
|
||||
* Synchronizes enter/exit plan mode tools based on current mode.
|
||||
*/
|
||||
syncPlanModeTools(): void {
|
||||
const isPlanMode = this.getApprovalMode() === ApprovalMode.PLAN;
|
||||
const registry = this.getToolRegistry();
|
||||
if (!registry) {
|
||||
return;
|
||||
}
|
||||
const approvalMode = this.getApprovalMode();
|
||||
const isPlanMode = approvalMode === ApprovalMode.PLAN;
|
||||
const isYoloMode = approvalMode === ApprovalMode.YOLO;
|
||||
|
||||
if (isPlanMode) {
|
||||
if (registry.getTool(ENTER_PLAN_MODE_TOOL_NAME)) {
|
||||
@@ -1817,7 +1826,7 @@ export class Config {
|
||||
if (registry.getTool(EXIT_PLAN_MODE_TOOL_NAME)) {
|
||||
registry.unregisterTool(EXIT_PLAN_MODE_TOOL_NAME);
|
||||
}
|
||||
if (this.planEnabled) {
|
||||
if (this.planEnabled && !isYoloMode) {
|
||||
if (!registry.getTool(ENTER_PLAN_MODE_TOOL_NAME)) {
|
||||
registry.registerTool(new EnterPlanModeTool(this, this.messageBus));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user