Path: blob/main/extensions/copilot/src/extension/chatSessions/claude/common/toolPermissionHandlers/exitPlanModeHandler.ts
13406 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as l10n from '@vscode/l10n';6import { ILogService } from '../../../../../platform/log/common/logService';7import { CancellationToken } from '../../../../../util/vs/base/common/cancellation';8import { LanguageModelTextPart } from '../../../../../vscodeTypes';9import { ToolName } from '../../../../tools/common/toolNames';10import { IToolsService } from '../../../../tools/common/toolsService';11import { ClaudeToolPermissionContext, ClaudeToolPermissionResult, IClaudeToolPermissionHandler } from '../claudeToolPermission';12import { registerToolPermissionHandler } from '../claudeToolPermissionRegistry';13import { ClaudeToolNames, ExitPlanModeInput } from '../claudeTools';1415const ApproveButton = l10n.t('Approve');16const DenyButton = l10n.t('Deny');1718/**19* Handler for the ExitPlanMode tool.20* Shows a confirmation dialog with Claude's plan and Approve/Deny buttons.21*/22export class ExitPlanModeToolHandler implements IClaudeToolPermissionHandler<ClaudeToolNames.ExitPlanMode> {23public readonly toolNames = [ClaudeToolNames.ExitPlanMode] as const;2425constructor(26@IToolsService private readonly toolsService: IToolsService,27@ILogService private readonly logService: ILogService28) { }2930public async handle(31_toolName: ClaudeToolNames.ExitPlanMode,32input: ExitPlanModeInput,33{ toolInvocationToken }: ClaudeToolPermissionContext34): Promise<ClaudeToolPermissionResult> {35try {36const result = await this.toolsService.invokeTool(ToolName.CoreConfirmationToolWithOptions, {37input: {38title: l10n.t('Ready to code?'),39message: l10n.t("Here is Claude's plan:\n\n{0}", input.plan ?? ''),40// Use buttons instead of a simple confirmation because we do not want41// auto-approve options for this tool.42buttons: [ApproveButton, DenyButton]43},44toolInvocationToken45}, CancellationToken.None);4647const firstResultPart = result.content.at(0);48if (firstResultPart instanceof LanguageModelTextPart && firstResultPart.value === ApproveButton) {49return {50behavior: 'allow',51updatedInput: input52};53}54} catch (e) {55this.logService.warn(`[ExitPlanMode] Failed to invoke confirmation tool: ${e?.message ?? e}`);56return {57behavior: 'deny',58message: 'Failed to show plan confirmation'59};60}6162return {63behavior: 'deny',64message: 'The user declined the plan, maybe ask why?'65};66}67}6869// Self-register the handler70registerToolPermissionHandler(71[ClaudeToolNames.ExitPlanMode],72ExitPlanModeToolHandler73);747576