chat: add "Don't show again" to Autopilot and Bypass Approvals warning dialogs (#311262)

* Add 'Don't show again' to autopilot/bypass approvals warning dialogs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add developer command to reset chat permission warning dialogs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Always show AutoApprove warning independently of Autopilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Extract permission storage keys to shared constants module

Move AUTOPILOT_DONT_SHOW_AGAIN_KEY and AUTO_APPROVE_DONT_SHOW_AGAIN_KEY
to chat/common/chatPermissionStorageKeys.ts so both chatDeveloperActions
and permissionPickerActionItem import from a lightweight shared module.
This avoids chatDeveloperActions pulling in heavy widget/UI dependencies
at startup via the permissionPickerActionItem import.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Ulugbek Abdullaev
2026-04-20 20:13:13 +05:00
committed by GitHub
parent 197f33eb36
commit 2212cb295d
3 changed files with 65 additions and 6 deletions

View File

@@ -17,6 +17,8 @@ import { ChatContextKeys } from '../../common/actions/chatContextKeys.js';
import { IChatService } from '../../common/chatService/chatService.js';
import { ILanguageModelsService } from '../../common/languageModels.js';
import { IChatWidgetService } from '../chat.js';
import { IStorageService, StorageScope } from '../../../../../platform/storage/common/storage.js';
import { AUTOPILOT_DONT_SHOW_AGAIN_KEY, AUTO_APPROVE_DONT_SHOW_AGAIN_KEY } from '../../common/chatPermissionStorageKeys.js';
function uriReplacer(_key: string, value: unknown): unknown {
if (URI.isUri(value)) {
@@ -37,6 +39,7 @@ export function registerChatDeveloperActions() {
registerAction2(InspectChatModelAction);
registerAction2(InspectChatModelReferencesAction);
registerAction2(ClearRecentlyUsedLanguageModelsAction);
registerAction2(ResetChatPermissionWarningDialogsAction);
}
function formatChatModelReferenceInspection(accessor: ServicesAccessor): string {
@@ -233,3 +236,23 @@ class ClearRecentlyUsedLanguageModelsAction extends Action2 {
accessor.get(ILanguageModelsService).clearRecentlyUsedList();
}
}
class ResetChatPermissionWarningDialogsAction extends Action2 {
static readonly ID = 'workbench.action.chat.resetPermissionWarningDialogs';
constructor() {
super({
id: ResetChatPermissionWarningDialogsAction.ID,
title: localize2('workbench.action.chat.resetPermissionWarningDialogs.label', "Reset Permission Warning Dialogs (Autopilot, Bypass Approvals)"),
category: Categories.Developer,
f1: true,
precondition: ChatContextKeys.enabled
});
}
override run(accessor: ServicesAccessor): void {
const storageService = accessor.get(IStorageService);
storageService.remove(AUTOPILOT_DONT_SHOW_AGAIN_KEY, StorageScope.PROFILE);
storageService.remove(AUTO_APPROVE_DONT_SHOW_AGAIN_KEY, StorageScope.PROFILE);
}
}

View File

@@ -24,17 +24,29 @@ import { MarkdownString } from '../../../../../../base/common/htmlContent.js';
import { ChatInputPickerActionViewItem, IChatInputPickerOptions } from './chatInputPickerActionItem.js';
import { IOpenerService } from '../../../../../../platform/opener/common/opener.js';
import { URI } from '../../../../../../base/common/uri.js';
import { IStorageService, StorageScope, StorageTarget } from '../../../../../../platform/storage/common/storage.js';
// Track whether warnings have been shown this VS Code session
const shownWarnings = new Set<ChatPermissionLevel>();
function hasShownElevatedWarning(level: ChatPermissionLevel): boolean {
import { AUTOPILOT_DONT_SHOW_AGAIN_KEY, AUTO_APPROVE_DONT_SHOW_AGAIN_KEY } from '../../../common/chatPermissionStorageKeys.js';
function dontShowAgainKey(level: ChatPermissionLevel): string | undefined {
if (level === ChatPermissionLevel.Autopilot) {
return AUTOPILOT_DONT_SHOW_AGAIN_KEY;
}
if (level === ChatPermissionLevel.AutoApprove) {
return AUTO_APPROVE_DONT_SHOW_AGAIN_KEY;
}
return undefined;
}
function hasShownElevatedWarning(level: ChatPermissionLevel, storageService: IStorageService): boolean {
if (shownWarnings.has(level)) {
return true;
}
// Autopilot is stricter than AutoApprove, so confirming Autopilot
// implies the user already accepted the AutoApprove risks.
if (level === ChatPermissionLevel.AutoApprove && shownWarnings.has(ChatPermissionLevel.Autopilot)) {
const key = dontShowAgainKey(level);
if (key && storageService.getBoolean(key, StorageScope.PROFILE, false)) {
return true;
}
return false;
@@ -57,6 +69,7 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
@IConfigurationService configurationService: IConfigurationService,
@IDialogService private readonly dialogService: IDialogService,
@IOpenerService openerService: IOpenerService,
@IStorageService storageService: IStorageService,
) {
const isAutoApprovePolicyRestricted = () => configurationService.inspect<boolean>(ChatConfiguration.GlobalAutoApprove).policyValue === false;
const isAutopilotEnabled = () => configurationService.getValue<boolean>(ChatConfiguration.AutopilotEnabled) !== false;
@@ -98,7 +111,7 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
: localize('permissions.autoApprove.description', "Auto-approve all tool calls and retry on errors"),
},
run: async () => {
if (!hasShownElevatedWarning(ChatPermissionLevel.AutoApprove)) {
if (!hasShownElevatedWarning(ChatPermissionLevel.AutoApprove, storageService)) {
const result = await this.dialogService.prompt({
type: Severity.Warning,
message: localize('permissions.autoApprove.warning.title', "Enable Bypass Approvals?"),
@@ -112,6 +125,10 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
run: () => false
},
],
checkbox: {
label: localize('permissions.warning.dontShowAgain', "Don't show again"),
checked: false,
},
custom: {
icon: Codicon.warning,
markdownDetails: [{
@@ -122,6 +139,9 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
if (result.result !== true) {
return;
}
if (result.checkboxChecked) {
storageService.store(AUTO_APPROVE_DONT_SHOW_AGAIN_KEY, true, StorageScope.PROFILE, StorageTarget.USER);
}
shownWarnings.add(ChatPermissionLevel.AutoApprove);
}
delegate.setPermissionLevel(ChatPermissionLevel.AutoApprove);
@@ -147,7 +167,7 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
: localize('permissions.autopilot.description', "Auto-approve all tool calls and continue until the task is done"),
},
run: async () => {
if (!hasShownElevatedWarning(ChatPermissionLevel.Autopilot)) {
if (!hasShownElevatedWarning(ChatPermissionLevel.Autopilot, storageService)) {
const result = await this.dialogService.prompt({
type: Severity.Warning,
message: localize('permissions.autopilot.warning.title', "Enable Autopilot?"),
@@ -161,6 +181,10 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
run: () => false
},
],
checkbox: {
label: localize('permissions.warning.dontShowAgain', "Don't show again"),
checked: false,
},
custom: {
icon: Codicon.rocket,
markdownDetails: [{
@@ -171,6 +195,9 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
if (result.result !== true) {
return;
}
if (result.checkboxChecked) {
storageService.store(AUTOPILOT_DONT_SHOW_AGAIN_KEY, true, StorageScope.PROFILE, StorageTarget.USER);
}
shownWarnings.add(ChatPermissionLevel.Autopilot);
}
delegate.setPermissionLevel(ChatPermissionLevel.Autopilot);

View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// Storage keys for persisting the user's choice to skip the warning dialog
// across sessions when "Don't show again" is checked.
export const AUTOPILOT_DONT_SHOW_AGAIN_KEY = 'chat.permissions.autopilot.dontShowWarningAgain';
export const AUTO_APPROVE_DONT_SHOW_AGAIN_KEY = 'chat.permissions.autoApprove.dontShowWarningAgain';