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