mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-02 08:15:56 +01:00
bypass approvals and toolbar in cli (#300228)
* bypass approvals and toolbar in cli * new picker in new chat state for sessions
This commit is contained in:
201
src/vs/sessions/contrib/chat/browser/newChatPermissionPicker.ts
Normal file
201
src/vs/sessions/contrib/chat/browser/newChatPermissionPicker.ts
Normal file
@@ -0,0 +1,201 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as dom from '../../../../base/browser/dom.js';
|
||||
import { Codicon } from '../../../../base/common/codicons.js';
|
||||
import { Emitter, Event } from '../../../../base/common/event.js';
|
||||
import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
import { IActionWidgetService } from '../../../../platform/actionWidget/browser/actionWidget.js';
|
||||
import { ActionListItemKind, IActionListDelegate, IActionListItem } from '../../../../platform/actionWidget/browser/actionList.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js';
|
||||
import { renderIcon } from '../../../../base/browser/ui/iconLabel/iconLabels.js';
|
||||
import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||
import { ChatConfiguration, ChatPermissionLevel } from '../../../../workbench/contrib/chat/common/constants.js';
|
||||
import Severity from '../../../../base/common/severity.js';
|
||||
import { MarkdownString } from '../../../../base/common/htmlContent.js';
|
||||
|
||||
// Track whether warnings have been shown this VS Code session
|
||||
const shownWarnings = new Set<ChatPermissionLevel>();
|
||||
|
||||
interface IPermissionItem {
|
||||
readonly level: ChatPermissionLevel;
|
||||
readonly label: string;
|
||||
readonly icon: ThemeIcon;
|
||||
readonly checked: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A permission picker for the new-session welcome view.
|
||||
* Shows Default Approvals and Bypass Approvals options (no Autopilot for CLI sessions).
|
||||
*/
|
||||
export class NewChatPermissionPicker extends Disposable {
|
||||
|
||||
private readonly _onDidChangeLevel = this._register(new Emitter<ChatPermissionLevel>());
|
||||
readonly onDidChangeLevel: Event<ChatPermissionLevel> = this._onDidChangeLevel.event;
|
||||
|
||||
private _currentLevel: ChatPermissionLevel = ChatPermissionLevel.Default;
|
||||
private _triggerElement: HTMLElement | undefined;
|
||||
private _container: HTMLElement | undefined;
|
||||
private readonly _renderDisposables = this._register(new DisposableStore());
|
||||
|
||||
get permissionLevel(): ChatPermissionLevel {
|
||||
return this._currentLevel;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@IActionWidgetService private readonly actionWidgetService: IActionWidgetService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
render(container: HTMLElement): HTMLElement {
|
||||
this._renderDisposables.clear();
|
||||
|
||||
const slot = dom.append(container, dom.$('.sessions-chat-picker-slot'));
|
||||
this._container = slot;
|
||||
this._renderDisposables.add({ dispose: () => slot.remove() });
|
||||
|
||||
const trigger = dom.append(slot, dom.$('a.action-label'));
|
||||
trigger.tabIndex = 0;
|
||||
trigger.role = 'button';
|
||||
this._triggerElement = trigger;
|
||||
|
||||
this._updateTriggerLabel(trigger);
|
||||
|
||||
this._renderDisposables.add(dom.addDisposableListener(trigger, dom.EventType.CLICK, (e) => {
|
||||
dom.EventHelper.stop(e, true);
|
||||
this.showPicker();
|
||||
}));
|
||||
|
||||
this._renderDisposables.add(dom.addDisposableListener(trigger, dom.EventType.KEY_DOWN, (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
dom.EventHelper.stop(e, true);
|
||||
this.showPicker();
|
||||
}
|
||||
}));
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
setVisible(visible: boolean): void {
|
||||
if (this._container) {
|
||||
this._container.style.display = visible ? '' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
showPicker(): void {
|
||||
if (!this._triggerElement || this.actionWidgetService.isVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
const policyRestricted = this.configurationService.inspect<boolean>(ChatConfiguration.GlobalAutoApprove).policyValue === false;
|
||||
|
||||
const items: IActionListItem<IPermissionItem>[] = [
|
||||
{
|
||||
kind: ActionListItemKind.Action,
|
||||
group: { kind: ActionListItemKind.Header, title: '', icon: Codicon.shield },
|
||||
item: {
|
||||
level: ChatPermissionLevel.Default,
|
||||
label: localize('permissions.default', "Default Approvals"),
|
||||
icon: Codicon.shield,
|
||||
checked: this._currentLevel === ChatPermissionLevel.Default,
|
||||
},
|
||||
label: localize('permissions.default', "Default Approvals"),
|
||||
description: localize('permissions.default.subtext', "Copilot uses your configured settings"),
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
kind: ActionListItemKind.Action,
|
||||
group: { kind: ActionListItemKind.Header, title: '', icon: Codicon.warning },
|
||||
item: {
|
||||
level: ChatPermissionLevel.AutoApprove,
|
||||
label: localize('permissions.autoApprove', "Bypass Approvals"),
|
||||
icon: Codicon.warning,
|
||||
checked: this._currentLevel === ChatPermissionLevel.AutoApprove,
|
||||
},
|
||||
label: localize('permissions.autoApprove', "Bypass Approvals"),
|
||||
description: localize('permissions.autoApprove.subtext', "All tool calls are auto-approved"),
|
||||
disabled: policyRestricted,
|
||||
},
|
||||
];
|
||||
|
||||
const triggerElement = this._triggerElement;
|
||||
const delegate: IActionListDelegate<IPermissionItem> = {
|
||||
onSelect: async (item) => {
|
||||
this.actionWidgetService.hide();
|
||||
await this._selectLevel(item.level);
|
||||
},
|
||||
onHide: () => { triggerElement.focus(); },
|
||||
};
|
||||
|
||||
this.actionWidgetService.show<IPermissionItem>(
|
||||
'permissionPicker',
|
||||
false,
|
||||
items,
|
||||
delegate,
|
||||
this._triggerElement,
|
||||
undefined,
|
||||
[],
|
||||
{
|
||||
getAriaLabel: (item) => item.label ?? '',
|
||||
getWidgetAriaLabel: () => localize('permissionPicker.ariaLabel', "Permission Picker"),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private async _selectLevel(level: ChatPermissionLevel): Promise<void> {
|
||||
if (level === ChatPermissionLevel.AutoApprove && !shownWarnings.has(ChatPermissionLevel.AutoApprove)) {
|
||||
const result = await this.dialogService.prompt({
|
||||
type: Severity.Warning,
|
||||
message: localize('permissions.autoApprove.warning.title', "Enable Bypass Approvals?"),
|
||||
buttons: [
|
||||
{
|
||||
label: localize('permissions.autoApprove.warning.confirm', "Enable"),
|
||||
run: () => true
|
||||
},
|
||||
{
|
||||
label: localize('permissions.autoApprove.warning.cancel', "Cancel"),
|
||||
run: () => false
|
||||
},
|
||||
],
|
||||
custom: {
|
||||
icon: Codicon.warning,
|
||||
markdownDetails: [{
|
||||
markdown: new MarkdownString(localize('permissions.autoApprove.warning.detail', "Bypass Approvals will auto-approve all tool calls without asking for confirmation. This includes file edits, terminal commands, and external tool calls.")),
|
||||
}],
|
||||
},
|
||||
});
|
||||
if (result.result !== true) {
|
||||
return;
|
||||
}
|
||||
shownWarnings.add(ChatPermissionLevel.AutoApprove);
|
||||
}
|
||||
|
||||
this._currentLevel = level;
|
||||
this._updateTriggerLabel(this._triggerElement);
|
||||
this._onDidChangeLevel.fire(level);
|
||||
}
|
||||
|
||||
private _updateTriggerLabel(trigger: HTMLElement | undefined): void {
|
||||
if (!trigger) {
|
||||
return;
|
||||
}
|
||||
|
||||
dom.clearNode(trigger);
|
||||
const icon = this._currentLevel === ChatPermissionLevel.AutoApprove ? Codicon.warning : Codicon.shield;
|
||||
const label = this._currentLevel === ChatPermissionLevel.AutoApprove
|
||||
? localize('permissions.autoApprove.label', "Bypass Approvals")
|
||||
: localize('permissions.default.label', "Default Approvals");
|
||||
|
||||
dom.append(trigger, renderIcon(icon));
|
||||
const labelSpan = dom.append(trigger, dom.$('span.sessions-chat-dropdown-label'));
|
||||
labelSpan.textContent = label;
|
||||
dom.append(trigger, renderIcon(Codicon.chevronDown));
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,7 @@ import { IChatRequestVariableEntry } from '../../../../workbench/contrib/chat/co
|
||||
import { ChatAgentLocation, ChatModeKind } from '../../../../workbench/contrib/chat/common/constants.js';
|
||||
import { ChatHistoryNavigator } from '../../../../workbench/contrib/chat/common/widget/chatWidgetHistoryService.js';
|
||||
import { IHistoryNavigationWidget } from '../../../../base/browser/history.js';
|
||||
import { NewChatPermissionPicker } from './newChatPermissionPicker.js';
|
||||
import { registerAndCreateHistoryNavigationContext, IHistoryNavigationContext } from '../../../../platform/history/browser/contextScopedHistoryWidget.js';
|
||||
|
||||
const STORAGE_KEY_DRAFT_STATE = 'sessions.draftState';
|
||||
@@ -147,6 +148,7 @@ class NewChatWidget extends Disposable implements IHistoryNavigationWidget {
|
||||
private _inputSlot: HTMLElement | undefined;
|
||||
private readonly _folderPicker: FolderPicker;
|
||||
private _folderPickerContainer: HTMLElement | undefined;
|
||||
private readonly _permissionPicker: NewChatPermissionPicker;
|
||||
private readonly _repoPicker: RepoPicker;
|
||||
private _repoPickerContainer: HTMLElement | undefined;
|
||||
private readonly _cloudModelPicker: CloudModelPicker;
|
||||
@@ -194,6 +196,7 @@ class NewChatWidget extends Disposable implements IHistoryNavigationWidget {
|
||||
this._history = this._register(this.instantiationService.createInstance(ChatHistoryNavigator, ChatAgentLocation.Chat));
|
||||
this._contextAttachments = this._register(this.instantiationService.createInstance(NewChatContextAttachments));
|
||||
this._folderPicker = this._register(this.instantiationService.createInstance(FolderPicker));
|
||||
this._permissionPicker = this._register(this.instantiationService.createInstance(NewChatPermissionPicker));
|
||||
this._repoPicker = this._register(this.instantiationService.createInstance(RepoPicker));
|
||||
this._cloudModelPicker = this._register(this.instantiationService.createInstance(CloudModelPicker));
|
||||
this._targetPicker = this._register(new SessionTargetPicker(options.allowedTargets, this._resolveDefaultTarget(options)));
|
||||
@@ -207,6 +210,7 @@ class NewChatWidget extends Disposable implements IHistoryNavigationWidget {
|
||||
this._createNewSession();
|
||||
const isLocal = target === AgentSessionProviders.Background;
|
||||
this._isolationModePicker.setVisible(isLocal);
|
||||
this._permissionPicker.setVisible(isLocal);
|
||||
this._branchPicker.setVisible(isLocal);
|
||||
this._syncIndicator.setVisible(isLocal);
|
||||
this._updateDraftState();
|
||||
@@ -305,6 +309,7 @@ class NewChatWidget extends Disposable implements IHistoryNavigationWidget {
|
||||
const isolationContainer = dom.append(welcomeElement, dom.$('.chat-full-welcome-local-mode'));
|
||||
this._isolationModePicker.render(isolationContainer);
|
||||
dom.append(isolationContainer, dom.$('.sessions-chat-local-mode-spacer'));
|
||||
this._permissionPicker.render(isolationContainer);
|
||||
const branchContainer = dom.append(isolationContainer, dom.$('.sessions-chat-local-mode-right'));
|
||||
this._branchPicker.render(branchContainer);
|
||||
this._syncIndicator.render(branchContainer);
|
||||
@@ -313,6 +318,7 @@ class NewChatWidget extends Disposable implements IHistoryNavigationWidget {
|
||||
const isLocal = this._targetPicker.selectedTarget === AgentSessionProviders.Background;
|
||||
const isWorktree = this._isolationModePicker.isolationMode === 'worktree';
|
||||
this._isolationModePicker.setVisible(isLocal);
|
||||
this._permissionPicker.setVisible(isLocal);
|
||||
this._branchPicker.setVisible(isLocal && isWorktree);
|
||||
this._syncIndicator.setVisible(isLocal && isWorktree);
|
||||
|
||||
@@ -1021,7 +1027,10 @@ class NewChatWidget extends Disposable implements IHistoryNavigationWidget {
|
||||
try {
|
||||
await this.sessionsManagementService.sendRequestForNewSession(
|
||||
session.resource,
|
||||
options?.openNewAfterSend ? { openNewSessionView: true } : undefined
|
||||
{
|
||||
...options?.openNewAfterSend ? { openNewSessionView: true } : {},
|
||||
permissionLevel: this._permissionPicker.permissionLevel,
|
||||
}
|
||||
);
|
||||
this._newSessionListener.clear();
|
||||
this._contextAttachments.clear();
|
||||
|
||||
@@ -16,7 +16,7 @@ import { ISessionOpenOptions, openSession as openSessionDefault } from '../../..
|
||||
import { ChatViewPaneTarget, IChatWidgetService } from '../../../../workbench/contrib/chat/browser/chat.js';
|
||||
import { IChatSessionProviderOptionItem, IChatSessionsService } from '../../../../workbench/contrib/chat/common/chatSessionsService.js';
|
||||
import { IChatService, IChatSendRequestOptions } from '../../../../workbench/contrib/chat/common/chatService/chatService.js';
|
||||
import { ChatAgentLocation, ChatModeKind } from '../../../../workbench/contrib/chat/common/constants.js';
|
||||
import { ChatAgentLocation, ChatModeKind, ChatPermissionLevel } from '../../../../workbench/contrib/chat/common/constants.js';
|
||||
import { IAgentSession, isAgentSession } from '../../../../workbench/contrib/chat/browser/agentSessions/agentSessionsModel.js';
|
||||
import { IAgentSessionsService } from '../../../../workbench/contrib/chat/browser/agentSessions/agentSessionsService.js';
|
||||
import { ICommandService } from '../../../../platform/commands/common/commands.js';
|
||||
@@ -92,7 +92,7 @@ export interface ISessionsManagementService {
|
||||
* When `openNewSessionView` is true, opens a new session view after sending
|
||||
* instead of navigating to the newly created session.
|
||||
*/
|
||||
sendRequestForNewSession(sessionResource: URI, options?: { openNewSessionView?: boolean }): Promise<void>;
|
||||
sendRequestForNewSession(sessionResource: URI, options?: { openNewSessionView?: boolean; permissionLevel?: ChatPermissionLevel }): Promise<void>;
|
||||
|
||||
/**
|
||||
* Commit files in a worktree and refresh the agent sessions model
|
||||
@@ -306,7 +306,7 @@ export class SessionsManagementService extends Disposable implements ISessionsMa
|
||||
this.logService.info(`[ActiveSessionService] Active session changed (new): ${sessionResource.toString()}, repository: ${repository?.toString() ?? 'none'}`);
|
||||
}
|
||||
|
||||
async sendRequestForNewSession(sessionResource: URI, options?: { openNewSessionView?: boolean }): Promise<void> {
|
||||
async sendRequestForNewSession(sessionResource: URI, options?: { openNewSessionView?: boolean; permissionLevel?: ChatPermissionLevel }): Promise<void> {
|
||||
const session = this._newSession.value;
|
||||
if (!session) {
|
||||
this.logService.error(`[SessionsManagementService] No new session found for resource: ${sessionResource.toString()}`);
|
||||
@@ -334,6 +334,7 @@ export class SessionsManagementService extends Disposable implements ISessionsMa
|
||||
modeInstructions: undefined,
|
||||
modeId: 'agent',
|
||||
applyCodeBlockSuggestionId: undefined,
|
||||
permissionLevel: options?.permissionLevel ?? ChatPermissionLevel.Default,
|
||||
},
|
||||
agentIdSilent: contribution?.type,
|
||||
attachedContext: session.attachedContext,
|
||||
@@ -353,6 +354,13 @@ export class SessionsManagementService extends Disposable implements ISessionsMa
|
||||
this.openNewSessionView();
|
||||
}
|
||||
|
||||
// Sync the permission level from the welcome picker to the ChatWidget's input part
|
||||
const permissionLevel = sendOptions.modeInfo?.permissionLevel;
|
||||
if (permissionLevel) {
|
||||
const chatWidget = this.chatWidgetService.getWidgetBySessionResource(session.resource);
|
||||
chatWidget?.input.setPermissionLevel(permissionLevel);
|
||||
}
|
||||
|
||||
// 2. Apply selected model and options to the session
|
||||
const modelRef = this.chatService.acquireExistingSession(session.resource);
|
||||
if (modelRef) {
|
||||
|
||||
@@ -475,8 +475,10 @@ export class OpenPermissionPickerAction extends Action2 {
|
||||
ChatContextKeys.location.isEqualTo(ChatAgentLocation.Chat),
|
||||
ChatContextKeys.chatModeKind.notEqualsTo(ChatModeKind.Ask),
|
||||
ChatContextKeys.inQuickChat.negate(),
|
||||
ChatContextKeys.lockedToCodingAgent.negate(),
|
||||
IsSessionsWindowContext.negate(),
|
||||
ContextKeyExpr.or(
|
||||
ChatContextKeys.lockedToCodingAgent.negate(),
|
||||
ChatContextKeys.lockedCodingAgentId.isEqualTo(AgentSessionProviders.Background),
|
||||
),
|
||||
)
|
||||
}
|
||||
});
|
||||
@@ -599,17 +601,6 @@ export class OpenDelegationPickerAction extends Action2 {
|
||||
f1: false,
|
||||
precondition: ContextKeyExpr.and(ChatContextKeys.enabled, ChatContextKeys.chatSessionIsEmpty.negate(), ChatContextKeys.currentlyEditingInput.negate(), ChatContextKeys.currentlyEditing.negate()),
|
||||
menu: [
|
||||
{
|
||||
id: MenuId.ChatInput,
|
||||
order: 0.5,
|
||||
when: ContextKeyExpr.and(
|
||||
ChatContextKeys.enabled,
|
||||
ChatContextKeys.location.isEqualTo(ChatAgentLocation.Chat),
|
||||
ChatContextKeys.inQuickChat.negate(),
|
||||
ChatContextKeys.chatSessionIsEmpty.negate(),
|
||||
IsSessionsWindowContext),
|
||||
group: 'navigation',
|
||||
},
|
||||
{
|
||||
id: MenuId.ChatInputSecondary,
|
||||
order: 0.5,
|
||||
@@ -617,8 +608,8 @@ export class OpenDelegationPickerAction extends Action2 {
|
||||
ChatContextKeys.enabled,
|
||||
ChatContextKeys.location.isEqualTo(ChatAgentLocation.Chat),
|
||||
ChatContextKeys.inQuickChat.negate(),
|
||||
ChatContextKeys.chatSessionIsEmpty.negate(),
|
||||
IsSessionsWindowContext.negate()),
|
||||
ChatContextKeys.chatSessionIsEmpty.negate()
|
||||
),
|
||||
group: 'navigation',
|
||||
},
|
||||
]
|
||||
|
||||
@@ -286,6 +286,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
displayName: string;
|
||||
};
|
||||
private readonly _lockedToCodingAgentContextKey: IContextKey<boolean>;
|
||||
private readonly _lockedCodingAgentIdContextKey: IContextKey<string>;
|
||||
private readonly _agentSupportsAttachmentsContextKey: IContextKey<boolean>;
|
||||
private readonly _sessionIsEmptyContextKey: IContextKey<boolean>;
|
||||
private readonly _hasPendingRequestsContextKey: IContextKey<boolean>;
|
||||
@@ -400,6 +401,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
super();
|
||||
|
||||
this._lockedToCodingAgentContextKey = ChatContextKeys.lockedToCodingAgent.bindTo(this.contextKeyService);
|
||||
this._lockedCodingAgentIdContextKey = ChatContextKeys.lockedCodingAgentId.bindTo(this.contextKeyService);
|
||||
this._agentSupportsAttachmentsContextKey = ChatContextKeys.agentSupportsAttachments.bindTo(this.contextKeyService);
|
||||
this._sessionIsEmptyContextKey = ChatContextKeys.chatSessionIsEmpty.bindTo(this.contextKeyService);
|
||||
this._hasPendingRequestsContextKey = ChatContextKeys.hasPendingRequests.bindTo(this.contextKeyService);
|
||||
@@ -2095,6 +2097,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
displayName
|
||||
};
|
||||
this._lockedToCodingAgentContextKey.set(true);
|
||||
this._lockedCodingAgentIdContextKey.set(agentId);
|
||||
this.renderWelcomeViewContentIfNeeded();
|
||||
// Update capabilities for the locked agent
|
||||
const agent = this.chatAgentService.getAgent(agentId);
|
||||
@@ -2109,6 +2112,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
// Clear all state related to locking
|
||||
this._lockedAgent = undefined;
|
||||
this._lockedToCodingAgentContextKey.set(false);
|
||||
this._lockedCodingAgentIdContextKey.set('');
|
||||
this._updateAgentCapabilitiesContextKeys(undefined);
|
||||
|
||||
// Explicitly update the DOM to reflect unlocked state
|
||||
|
||||
@@ -2026,7 +2026,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
this.attachedContextContainer = elements.attachedContextContainer;
|
||||
const toolbarsContainer = elements.inputToolbars;
|
||||
this.secondaryToolbarContainer = elements.secondaryToolbar;
|
||||
if (this.options.isSessionsWindow || this.options.renderStyle === 'compact') {
|
||||
if (this.options.renderStyle === 'compact') {
|
||||
this.secondaryToolbarContainer.style.display = 'none';
|
||||
}
|
||||
this.chatEditingSessionWidgetContainer = elements.chatEditingSessionWidgetContainer;
|
||||
|
||||
@@ -57,6 +57,7 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
|
||||
) {
|
||||
const isAutoApprovePolicyRestricted = () => configurationService.inspect<boolean>(ChatConfiguration.GlobalAutoApprove).policyValue === false;
|
||||
const isAutopilotEnabled = () => configurationService.getValue<boolean>(ChatConfiguration.AutopilotEnabled) !== false;
|
||||
const isBackgroundProvider = contextKeyService.getContextKeyValue<string>('lockedCodingAgentId') === 'copilotcli';
|
||||
const actionProvider: IActionWidgetDropdownActionProvider = {
|
||||
getActions: () => {
|
||||
const currentLevel = delegate.currentPermissionLevel.get();
|
||||
@@ -130,7 +131,7 @@ export class PermissionPickerActionItem extends ChatInputPickerActionViewItem {
|
||||
},
|
||||
} satisfies IActionWidgetDropdownAction,
|
||||
];
|
||||
if (isAutopilotEnabled()) {
|
||||
if (isAutopilotEnabled() && !isBackgroundProvider) {
|
||||
actions.push({
|
||||
...action,
|
||||
id: 'chat.permissions.autopilot',
|
||||
|
||||
@@ -58,6 +58,7 @@ export namespace ChatContextKeys {
|
||||
* True when the chat widget is locked to the coding agent session.
|
||||
*/
|
||||
export const lockedToCodingAgent = new RawContextKey<boolean>('lockedToCodingAgent', false, { type: 'boolean', description: localize('lockedToCodingAgent', "True when the chat widget is locked to the coding agent session.") });
|
||||
export const lockedCodingAgentId = new RawContextKey<string>('lockedCodingAgentId', '', { type: 'string', description: localize('lockedCodingAgentId', "The agent ID when the chat widget is locked to a coding agent session.") });
|
||||
/**
|
||||
* True when the chat session has a customAgentTarget defined in its contribution,
|
||||
* which means the mode picker should be shown with filtered custom agents.
|
||||
|
||||
Reference in New Issue
Block a user