mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-14 16:10:59 -07:00
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
131 lines
3.3 KiB
TypeScript
131 lines
3.3 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import {
|
|
BaseDeclarativeTool,
|
|
BaseToolInvocation,
|
|
type ToolResult,
|
|
Kind,
|
|
type ToolInfoConfirmationDetails,
|
|
ToolConfirmationOutcome,
|
|
} from './tools.js';
|
|
import type { MessageBus } from '../confirmation-bus/message-bus.js';
|
|
import type { Config } from '../config/config.js';
|
|
import { ENTER_PLAN_MODE_TOOL_NAME } from './tool-names.js';
|
|
import { ApprovalMode } from '../policy/types.js';
|
|
import { ENTER_PLAN_MODE_DEFINITION } from './definitions/coreTools.js';
|
|
import { resolveToolDeclaration } from './definitions/resolver.js';
|
|
|
|
export interface EnterPlanModeParams {
|
|
reason?: string;
|
|
}
|
|
|
|
export class EnterPlanModeTool extends BaseDeclarativeTool<
|
|
EnterPlanModeParams,
|
|
ToolResult
|
|
> {
|
|
constructor(
|
|
private config: Config,
|
|
messageBus: MessageBus,
|
|
) {
|
|
super(
|
|
ENTER_PLAN_MODE_TOOL_NAME,
|
|
'Enter Plan Mode',
|
|
ENTER_PLAN_MODE_DEFINITION.base.description!,
|
|
Kind.Plan,
|
|
ENTER_PLAN_MODE_DEFINITION.base.parametersJsonSchema,
|
|
messageBus,
|
|
);
|
|
}
|
|
|
|
protected createInvocation(
|
|
params: EnterPlanModeParams,
|
|
messageBus: MessageBus,
|
|
toolName: string,
|
|
toolDisplayName: string,
|
|
): EnterPlanModeInvocation {
|
|
return new EnterPlanModeInvocation(
|
|
params,
|
|
messageBus,
|
|
toolName,
|
|
toolDisplayName,
|
|
this.config,
|
|
);
|
|
}
|
|
|
|
override getSchema(modelId?: string) {
|
|
return resolveToolDeclaration(ENTER_PLAN_MODE_DEFINITION, modelId);
|
|
}
|
|
}
|
|
|
|
export class EnterPlanModeInvocation extends BaseToolInvocation<
|
|
EnterPlanModeParams,
|
|
ToolResult
|
|
> {
|
|
private confirmationOutcome: ToolConfirmationOutcome | null = null;
|
|
|
|
constructor(
|
|
params: EnterPlanModeParams,
|
|
messageBus: MessageBus,
|
|
toolName: string,
|
|
toolDisplayName: string,
|
|
private config: Config,
|
|
) {
|
|
super(params, messageBus, toolName, toolDisplayName);
|
|
}
|
|
|
|
getDescription(): string {
|
|
return this.params.reason || 'Initiating Plan Mode';
|
|
}
|
|
|
|
override async shouldConfirmExecute(
|
|
abortSignal: AbortSignal,
|
|
): Promise<ToolInfoConfirmationDetails | false> {
|
|
const decision = await this.getMessageBusDecision(abortSignal);
|
|
if (decision === 'ALLOW') {
|
|
return false;
|
|
}
|
|
|
|
if (decision === 'DENY') {
|
|
throw new Error(
|
|
`Tool execution for "${
|
|
this._toolDisplayName || this._toolName
|
|
}" denied by policy.`,
|
|
);
|
|
}
|
|
|
|
// ASK_USER
|
|
return {
|
|
type: 'info',
|
|
title: 'Enter Plan Mode',
|
|
prompt:
|
|
'This will restrict the agent to read-only tools to allow for safe planning.',
|
|
onConfirm: async (outcome: ToolConfirmationOutcome) => {
|
|
this.confirmationOutcome = outcome;
|
|
// Policy updates are now handled centrally by the scheduler
|
|
},
|
|
};
|
|
}
|
|
|
|
async execute(_signal: AbortSignal): Promise<ToolResult> {
|
|
if (this.confirmationOutcome === ToolConfirmationOutcome.Cancel) {
|
|
return {
|
|
llmContent: 'User cancelled entering Plan Mode.',
|
|
returnDisplay: 'Cancelled',
|
|
};
|
|
}
|
|
|
|
this.config.setApprovalMode(ApprovalMode.PLAN);
|
|
|
|
return {
|
|
llmContent: 'Switching to Plan mode.',
|
|
returnDisplay: this.params.reason
|
|
? `Switching to Plan mode: ${this.params.reason}`
|
|
: 'Switching to Plan mode',
|
|
};
|
|
}
|
|
}
|