Allow to hide Copilot via user setting and policy (fix #249615) (#261798)

This commit is contained in:
Benjamin Pasero
2025-08-15 16:36:46 +02:00
committed by GitHub
parent afb9516426
commit e2423d6644
9 changed files with 79 additions and 26 deletions
+8 -1
View File
@@ -23,8 +23,15 @@ set VSCODE_DEV=1
set ELECTRON_ENABLE_LOGGING=1
set ELECTRON_ENABLE_STACK_DUMPING=1
set DISABLE_TEST_EXTENSION="--disable-extension=vscode.vscode-api-tests"
for %%A in (%*) do (
if "%%~A"=="--extensionTestsPath" (
set DISABLE_TEST_EXTENSION=""
)
)
:: Launch Code
%CODE% --inspect=5874 out\cli.js %~dp0.. %*
%CODE% --inspect=5874 out\cli.js %~dp0.. %DISABLE_TEST_EXTENSION% %*
goto end
:builtin
+7 -1
View File
@@ -29,12 +29,18 @@ function code() {
return
fi
# Disable test extension
DISABLE_TEST_EXTENSION="--disable-extension=vscode.vscode-api-tests"
if [[ "$@" == *"--extensionTestsPath"* ]]; then
DISABLE_TEST_EXTENSION=""
fi
ELECTRON_RUN_AS_NODE=1 \
NODE_ENV=development \
VSCODE_DEV=1 \
ELECTRON_ENABLE_LOGGING=1 \
ELECTRON_ENABLE_STACK_DUMPING=1 \
"$CODE" --inspect=5874 "$ROOT/out/cli.js" . "$@"
"$CODE" --inspect=5874 "$ROOT/out/cli.js" . $DISABLE_TEST_EXTENSION "$@"
}
code "$@"
-1
View File
@@ -31,7 +31,6 @@ for %%A in (%*) do (
)
:: Launch Code
%CODE% . %DISABLE_TEST_EXTENSION% %*
goto end
@@ -480,9 +480,8 @@ export class Menubar extends Disposable {
}
private shouldDrawMenu(menuId: string): boolean {
// We need to draw an empty menu to override the electron default
if (!isMacintosh && !this.showNativeMenu) {
return false;
return false; // We need to draw an empty menu to override the electron default
}
switch (menuId) {
@@ -551,7 +551,19 @@ configurationRegistry.registerConfiguration({
default: false,
description: nls.localize('chat.agent.showThinking', "Controls whether to show the thinking process of the model in chat responses."),
tags: ['experimental'],
}
},
'chat.hideAIFeatures': {
type: 'boolean',
description: nls.localize('chat.hideAIFeatures', "Hide and disables the getting started UI elements for setting up AI features and Chat. This setting has no effect when Copilot extensions are installed."),
default: false,
scope: ConfigurationScope.APPLICATION,
policy: {
name: 'ChatHideAIFeatures',
minimumVersion: '1.104',
},
tags: ['experimental']
},
}
});
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
@@ -728,7 +728,7 @@ export class ViewPreviousEditsAction extends EditingSessionAction {
tooltip: ViewPreviousEditsAction.Label,
f1: true,
icon: Codicon.diffMultiple,
precondition: hasUndecidedChatEditingResourceContextKey.negate(),
precondition: ContextKeyExpr.and(ChatContextKeys.enabled, hasUndecidedChatEditingResourceContextKey.negate()),
menu: [
{
id: MenuId.ChatEditingWidgetToolbar,
@@ -872,9 +872,12 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr
}
private registerActions(context: ChatEntitlementContext, requests: ChatEntitlementRequests, controller: Lazy<ChatSetupController>): void {
const chatSetupTriggerContext = ContextKeyExpr.or(
ChatContextKeys.Setup.installed.negate(),
ChatContextKeys.Entitlement.canSignUp
const chatSetupTriggerContext = ContextKeyExpr.and(
ContextKeyExpr.not('config.chat.hideAIFeatures'),
ContextKeyExpr.or(
ChatContextKeys.Setup.installed.negate(),
ChatContextKeys.Entitlement.canSignUp
)
);
const CHAT_SETUP_ACTION_LABEL = localize2('triggerChatSetup', "Use AI Features with Copilot for free...");
@@ -934,6 +934,7 @@ export interface IChatEntitlementContextState extends IChatSentiment {
export class ChatEntitlementContext extends Disposable {
private static readonly CHAT_ENTITLEMENT_CONTEXT_STORAGE_KEY = 'chat.setupContext';
private static readonly CHAT_HIDDEN_CONFIGURATION_KEY = 'chat.hideAIFeatures';
private readonly canSignUpContextKey: IContextKey<boolean>;
private readonly signedOutContextKey: IContextKey<boolean>;
@@ -954,7 +955,7 @@ export class ChatEntitlementContext extends Disposable {
private _state: IChatEntitlementContextState;
private suspendedState: IChatEntitlementContextState | undefined = undefined;
get state(): IChatEntitlementContextState { return this.suspendedState ?? this._state; }
get state(): IChatEntitlementContextState { return this.withConfiguration(this.suspendedState ?? this._state); }
private readonly _onDidChange = this._register(new Emitter<void>());
readonly onDidChange = this._onDidChange.event;
@@ -967,6 +968,7 @@ export class ChatEntitlementContext extends Disposable {
@IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService,
@ILogService private readonly logService: ILogService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super();
@@ -988,6 +990,27 @@ export class ChatEntitlementContext extends Disposable {
this.checkExtensionInstallation();
this.updateContextSync();
this.registerListeners();
}
private registerListeners(): void {
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(ChatEntitlementContext.CHAT_HIDDEN_CONFIGURATION_KEY)) {
this.updateContext();
}
}));
}
private withConfiguration(state: IChatEntitlementContextState): IChatEntitlementContextState {
if (
state.installed ||
this.configurationService.getValue(ChatEntitlementContext.CHAT_HIDDEN_CONFIGURATION_KEY) !== true
) {
return state; // only applicable until extension is installed or when disabled via setting
}
return { ...state, hidden: true };
}
private async checkExtensionInstallation(): Promise<void> {
@@ -1074,21 +1097,23 @@ export class ChatEntitlementContext extends Disposable {
}
private updateContextSync(): void {
this.logService.trace(`[chat entitlement context] updateContext(): ${JSON.stringify(this._state)}`);
const state = this.withConfiguration(this._state);
this.signedOutContextKey.set(this._state.entitlement === ChatEntitlement.Unknown);
this.canSignUpContextKey.set(this._state.entitlement === ChatEntitlement.Available);
this.freeContextKey.set(this._state.entitlement === ChatEntitlement.Free);
this.proContextKey.set(this._state.entitlement === ChatEntitlement.Pro);
this.proPlusContextKey.set(this._state.entitlement === ChatEntitlement.ProPlus);
this.businessContextKey.set(this._state.entitlement === ChatEntitlement.Business);
this.enterpriseContextKey.set(this._state.entitlement === ChatEntitlement.Enterprise);
this.isInternalContextKey.set(this._state.isInternal);
this.hiddenContext.set(!!this._state.hidden);
this.laterContext.set(!!this._state.later);
this.installedContext.set(!!this._state.installed);
this.disabledContext.set(!!this._state.disabled);
this.untrustedContext.set(!!this._state.untrusted);
this.logService.trace(`[chat entitlement context] updateContext(): ${JSON.stringify(state)}`);
this.signedOutContextKey.set(state.entitlement === ChatEntitlement.Unknown);
this.canSignUpContextKey.set(state.entitlement === ChatEntitlement.Available);
this.freeContextKey.set(state.entitlement === ChatEntitlement.Free);
this.proContextKey.set(state.entitlement === ChatEntitlement.Pro);
this.proPlusContextKey.set(state.entitlement === ChatEntitlement.ProPlus);
this.businessContextKey.set(state.entitlement === ChatEntitlement.Business);
this.enterpriseContextKey.set(state.entitlement === ChatEntitlement.Enterprise);
this.isInternalContextKey.set(state.isInternal);
this.hiddenContext.set(!!state.hidden);
this.laterContext.set(!!state.later);
this.installedContext.set(!!state.installed);
this.disabledContext.set(!!state.disabled);
this.untrustedContext.set(!!state.untrusted);
this._onDidChange.fire();
}
@@ -24,6 +24,8 @@ import { IChatWidgetService, showChatView } from '../../../chat/browser/chat.js'
import { IViewsService } from '../../../../services/views/common/viewsService.js';
import { TerminalContextMenuGroup } from '../../../terminal/browser/terminalMenus.js';
import { TerminalContextKeys } from '../../../terminal/common/terminalContextKey.js';
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
import { ChatContextKeys } from '../../../chat/common/chatContextKeys.js';
// #region Workbench contributions
@@ -100,7 +102,7 @@ registerWorkbenchContribution2(ChatAgentToolsContribution.ID, ChatAgentToolsCont
registerActiveInstanceAction({
id: TerminalChatAgentToolsCommandId.ChatAddTerminalSelection,
title: localize('addTerminalSelection', 'Add Terminal Selection to Chat'),
precondition: sharedWhenClause.terminalAvailable,
precondition: ContextKeyExpr.and(ChatContextKeys.enabled, sharedWhenClause.terminalAvailable),
menu: [
{
id: MenuId.TerminalInstanceContext,