mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-12 22:08:04 -05:00
chat - towards experimental anonymous access (#265806)
This commit is contained in:
@@ -50,7 +50,8 @@
|
||||
"treeViewReveal",
|
||||
"tunnels",
|
||||
"workspaceTrust",
|
||||
"inlineCompletionsAdditions"
|
||||
"inlineCompletionsAdditions",
|
||||
"devDeviceId"
|
||||
],
|
||||
"private": true,
|
||||
"activationEvents": [],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.105.0",
|
||||
"distro": "34ee7cb7a51777c9233b9b97a87ed494d4bdeb0a",
|
||||
"distro": "1c56627fcbb7427c61b3debf10778ac069ba3027",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
||||
@@ -184,6 +184,9 @@ const _allApiProposals = {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.defaultChatParticipant.d.ts',
|
||||
version: 4
|
||||
},
|
||||
devDeviceId: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.devDeviceId.d.ts',
|
||||
},
|
||||
diffCommand: {
|
||||
proposal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.diffCommand.d.ts',
|
||||
},
|
||||
|
||||
@@ -384,6 +384,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
// namespace: env
|
||||
const env: typeof vscode.env = {
|
||||
get machineId() { return initData.telemetryInfo.machineId; },
|
||||
get devDeviceId() {
|
||||
checkProposedApiEnabled(extension, 'devDeviceId');
|
||||
return initData.telemetryInfo.devDeviceId;
|
||||
},
|
||||
get sessionId() { return initData.telemetryInfo.sessionId; },
|
||||
get language() { return initData.environment.appLanguage; },
|
||||
get appName() { return initData.environment.appName; },
|
||||
|
||||
@@ -660,7 +660,15 @@ configurationRegistry.registerConfiguration({
|
||||
type: 'boolean',
|
||||
description: nls.localize('chat.showAgentSessionsViewDescription', "Controls whether session descriptions are displayed on a second row in the Chat Sessions view."),
|
||||
default: true,
|
||||
}
|
||||
},
|
||||
'chat.allowAnonymousAccess': { // TODO@bpasero remove me eventually
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
tags: ['experimental'],
|
||||
experiment: {
|
||||
mode: 'auto'
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import './media/chatSetup.css';
|
||||
import { $ } from '../../../../base/browser/dom.js';
|
||||
import { IButton } from '../../../../base/browser/ui/button/button.js';
|
||||
import { Dialog, DialogContentsAlignment } from '../../../../base/browser/ui/dialog/dialog.js';
|
||||
@@ -52,7 +53,7 @@ import { AuthenticationSession, IAuthenticationService } from '../../../services
|
||||
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
|
||||
import { EnablementState, IWorkbenchExtensionEnablementService } from '../../../services/extensionManagement/common/extensionManagement.js';
|
||||
import { ExtensionUrlHandlerOverrideRegistry } from '../../../services/extensions/browser/extensionUrlHandler.js';
|
||||
import { nullExtensionDescription } from '../../../services/extensions/common/extensions.js';
|
||||
import { IExtensionService, nullExtensionDescription } from '../../../services/extensions/common/extensions.js';
|
||||
import { IHostService } from '../../../services/host/browser/host.js';
|
||||
import { IWorkbenchLayoutService, Parts } from '../../../services/layout/browser/layoutService.js';
|
||||
import { ILifecycleService } from '../../../services/lifecycle/common/lifecycle.js';
|
||||
@@ -73,7 +74,7 @@ import { ILanguageModelsService } from '../common/languageModels.js';
|
||||
import { CHAT_CATEGORY, CHAT_OPEN_ACTION_ID, CHAT_SETUP_ACTION_ID } from './actions/chatActions.js';
|
||||
import { ChatViewId, IChatWidgetService, showCopilotView } from './chat.js';
|
||||
import { CHAT_SIDEBAR_PANEL_ID } from './chatViewPane.js';
|
||||
import './media/chatSetup.css';
|
||||
import { IEnvironmentService } from '../../../../platform/environment/common/environment.js';
|
||||
import { chatViewsWelcomeRegistry } from './viewsWelcome/chatViewsWelcome.js';
|
||||
|
||||
const defaultChat = {
|
||||
@@ -439,7 +440,10 @@ class SetupAgent extends Disposable implements IChatAgentImplementation {
|
||||
|
||||
let result: IChatSetupResult | undefined = undefined;
|
||||
try {
|
||||
result = await ChatSetup.getInstance(this.instantiationService, this.context, this.controller).run({ disableChatViewReveal: true /* we are already in a chat context */ });
|
||||
result = await ChatSetup.getInstance(this.instantiationService, this.context, this.controller).run({
|
||||
disableChatViewReveal: true, // we are already in a chat context
|
||||
allowAnonymous: true, // in chat context we can allow anonymous usage (TODO@bpasero make this dependent on terms visibility)
|
||||
});
|
||||
} catch (error) {
|
||||
this.logService.error(`[chat setup] Error during setup: ${toErrorMessage(error)}`);
|
||||
} finally {
|
||||
@@ -649,7 +653,7 @@ class ChatSetup {
|
||||
this.skipDialogOnce = true;
|
||||
}
|
||||
|
||||
async run(options?: { disableChatViewReveal?: boolean; forceSignInDialog?: boolean; additionalScopes?: readonly string[] }): Promise<IChatSetupResult> {
|
||||
async run(options?: { disableChatViewReveal?: boolean; forceSignInDialog?: boolean; additionalScopes?: readonly string[]; allowAnonymous?: boolean }): Promise<IChatSetupResult> {
|
||||
if (this.pendingRun) {
|
||||
return this.pendingRun;
|
||||
}
|
||||
@@ -663,7 +667,7 @@ class ChatSetup {
|
||||
}
|
||||
}
|
||||
|
||||
private async doRun(options?: { disableChatViewReveal?: boolean; forceSignInDialog?: boolean; additionalScopes?: readonly string[] }): Promise<IChatSetupResult> {
|
||||
private async doRun(options?: { disableChatViewReveal?: boolean; forceSignInDialog?: boolean; additionalScopes?: readonly string[]; allowAnonymous?: boolean }): Promise<IChatSetupResult> {
|
||||
this.context.update({ later: false });
|
||||
|
||||
const dialogSkipped = this.skipDialogOnce;
|
||||
@@ -682,6 +686,8 @@ class ChatSetup {
|
||||
let setupStrategy: ChatSetupStrategy;
|
||||
if (!options?.forceSignInDialog && (dialogSkipped || isProUser(this.chatEntitlementService.entitlement) || this.chatEntitlementService.entitlement === ChatEntitlement.Free)) {
|
||||
setupStrategy = ChatSetupStrategy.DefaultSetup; // existing pro/free users setup without a dialog
|
||||
} else if (options?.allowAnonymous && this.chatEntitlementService.entitlement === ChatEntitlement.Anonymous) {
|
||||
setupStrategy = ChatSetupStrategy.DefaultSetup;
|
||||
} else {
|
||||
setupStrategy = await this.showDialog(options);
|
||||
}
|
||||
@@ -829,6 +835,8 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -1152,6 +1160,15 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr
|
||||
|
||||
private async checkExtensionInstallation(context: ChatEntitlementContext): Promise<void> {
|
||||
|
||||
// When developing extensions, await registration and then check
|
||||
if (this.environmentService.isExtensionDevelopment) {
|
||||
await this.extensionService.whenInstalledExtensionsRegistered();
|
||||
if (this.extensionService.extensions.find(ext => ExtensionIdentifier.equals(ext.identifier, defaultChat.chatExtensionId))) {
|
||||
context.update({ installed: true, disabled: false, untrusted: false });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Await extensions to be ready to be queried
|
||||
await this.extensionsWorkbenchService.queryLocal();
|
||||
|
||||
@@ -1461,9 +1478,10 @@ class ChatSetupController extends Disposable {
|
||||
let sessions = session ? [session] : undefined;
|
||||
try {
|
||||
if (
|
||||
entitlement !== ChatEntitlement.Free && // User is not signed up to Copilot Free
|
||||
!isProUser(entitlement) && // User is not signed up for a Copilot subscription
|
||||
entitlement !== ChatEntitlement.Unavailable // User is eligible for Copilot Free
|
||||
entitlement !== ChatEntitlement.Anonymous && // User is not eligible for anonymous access
|
||||
entitlement !== ChatEntitlement.Free && // User is not signed up to Copilot Free
|
||||
!isProUser(entitlement) && // User is not signed up for a Copilot subscription
|
||||
entitlement !== ChatEntitlement.Unavailable // User is eligible for Copilot Free
|
||||
) {
|
||||
if (!sessions) {
|
||||
try {
|
||||
|
||||
@@ -43,6 +43,7 @@ export namespace ChatEntitlementContextKeys {
|
||||
|
||||
export const Entitlement = {
|
||||
signedOut: new RawContextKey<boolean>('chatEntitlementSignedOut', false, true), // True when user is signed out.
|
||||
anonymous: new RawContextKey<boolean>('chatEntitlementAnonymous', false, true), // True when user is an anonymous user.
|
||||
canSignUp: new RawContextKey<boolean>('chatPlanCanSignUp', false, true), // True when user can sign up to be a chat free user.
|
||||
|
||||
planFree: new RawContextKey<boolean>('chatPlanFree', false, true), // True when user is a chat free user.
|
||||
@@ -63,24 +64,26 @@ export namespace ChatEntitlementContextKeys {
|
||||
export const IChatEntitlementService = createDecorator<IChatEntitlementService>('chatEntitlementService');
|
||||
|
||||
export enum ChatEntitlement {
|
||||
/* Signed out, anonymous */
|
||||
Anonymous = -1,
|
||||
/** Signed out */
|
||||
Unknown = 1,
|
||||
/** Signed in but not yet resolved */
|
||||
Unresolved,
|
||||
Unresolved = 2,
|
||||
/** Signed in and entitled to Free */
|
||||
Available,
|
||||
Available = 3,
|
||||
/** Signed in but not entitled to Free */
|
||||
Unavailable,
|
||||
Unavailable = 4,
|
||||
/** Signed-up to Free */
|
||||
Free,
|
||||
Free = 5,
|
||||
/** Signed-up to Pro */
|
||||
Pro,
|
||||
Pro = 6,
|
||||
/** Signed-up to Pro Plus */
|
||||
ProPlus,
|
||||
ProPlus = 7,
|
||||
/** Signed-up to Business */
|
||||
Business,
|
||||
Business = 8,
|
||||
/** Signed-up to Enterprise */
|
||||
Enterprise
|
||||
Enterprise = 9,
|
||||
}
|
||||
|
||||
export interface IChatSentiment {
|
||||
@@ -209,6 +212,7 @@ export class ChatEntitlementService extends Disposable implements IChatEntitleme
|
||||
ChatEntitlementContextKeys.Entitlement.planFree.key,
|
||||
ChatEntitlementContextKeys.Entitlement.canSignUp.key,
|
||||
ChatEntitlementContextKeys.Entitlement.signedOut.key,
|
||||
ChatEntitlementContextKeys.Entitlement.anonymous.key,
|
||||
ChatEntitlementContextKeys.Entitlement.organisations.key,
|
||||
ChatEntitlementContextKeys.Entitlement.internal.key,
|
||||
ChatEntitlementContextKeys.Entitlement.sku.key
|
||||
@@ -269,6 +273,8 @@ export class ChatEntitlementService extends Disposable implements IChatEntitleme
|
||||
return ChatEntitlement.Available;
|
||||
} else if (this.contextKeyService.getContextKeyValue<boolean>(ChatEntitlementContextKeys.Entitlement.signedOut.key) === true) {
|
||||
return ChatEntitlement.Unknown;
|
||||
} else if (this.contextKeyService.getContextKeyValue<boolean>(ChatEntitlementContextKeys.Entitlement.anonymous.key) === true) {
|
||||
return ChatEntitlement.Anonymous;
|
||||
}
|
||||
|
||||
return ChatEntitlement.Unresolved;
|
||||
@@ -1008,10 +1014,13 @@ type ChatEntitlementEvent = {
|
||||
export class ChatEntitlementContext extends Disposable {
|
||||
|
||||
private static readonly CHAT_ENTITLEMENT_CONTEXT_STORAGE_KEY = 'chat.setupContext';
|
||||
|
||||
private static readonly CHAT_DISABLED_CONFIGURATION_KEY = 'chat.disableAIFeatures';
|
||||
private static readonly CHAT_ALLOW_ANONYMOUS_CONFIGURATION_KEY = 'chat.allowAnonymousAccess';
|
||||
|
||||
private readonly canSignUpContextKey: IContextKey<boolean>;
|
||||
private readonly signedOutContextKey: IContextKey<boolean>;
|
||||
private readonly anonymousContextKey: IContextKey<boolean>;
|
||||
|
||||
private readonly freeContextKey: IContextKey<boolean>;
|
||||
private readonly proContextKey: IContextKey<boolean>;
|
||||
@@ -1049,6 +1058,8 @@ export class ChatEntitlementContext extends Disposable {
|
||||
|
||||
this.canSignUpContextKey = ChatEntitlementContextKeys.Entitlement.canSignUp.bindTo(contextKeyService);
|
||||
this.signedOutContextKey = ChatEntitlementContextKeys.Entitlement.signedOut.bindTo(contextKeyService);
|
||||
this.anonymousContextKey = ChatEntitlementContextKeys.Entitlement.anonymous.bindTo(contextKeyService);
|
||||
|
||||
this.freeContextKey = ChatEntitlementContextKeys.Entitlement.planFree.bindTo(contextKeyService);
|
||||
this.proContextKey = ChatEntitlementContextKeys.Entitlement.planPro.bindTo(contextKeyService);
|
||||
this.proPlusContextKey = ChatEntitlementContextKeys.Entitlement.planProPlus.bindTo(contextKeyService);
|
||||
@@ -1072,7 +1083,7 @@ export class ChatEntitlementContext extends Disposable {
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(ChatEntitlementContext.CHAT_DISABLED_CONFIGURATION_KEY)) {
|
||||
if (e.affectsConfiguration(ChatEntitlementContext.CHAT_DISABLED_CONFIGURATION_KEY) || e.affectsConfiguration(ChatEntitlementContext.CHAT_ALLOW_ANONYMOUS_CONFIGURATION_KEY)) {
|
||||
this.updateContext();
|
||||
}
|
||||
}));
|
||||
@@ -1080,8 +1091,19 @@ export class ChatEntitlementContext extends Disposable {
|
||||
|
||||
private withConfiguration(state: IChatEntitlementContextState): IChatEntitlementContextState {
|
||||
if (this.configurationService.getValue(ChatEntitlementContext.CHAT_DISABLED_CONFIGURATION_KEY) === true) {
|
||||
// Setting always wins: if AI is disabled, set `hidden: true`
|
||||
return { ...state, hidden: true };
|
||||
return {
|
||||
...state,
|
||||
hidden: true // Setting always wins: if AI is disabled, set `hidden: true`
|
||||
};
|
||||
}
|
||||
|
||||
if (this.configurationService.getValue(ChatEntitlementContext.CHAT_ALLOW_ANONYMOUS_CONFIGURATION_KEY) === true) {
|
||||
let entitlement = state.entitlement;
|
||||
if (entitlement === ChatEntitlement.Unknown /*&& !state.registered TODO@bpasero revisit */) {
|
||||
entitlement = ChatEntitlement.Anonymous; // enable `anonymous` based on exp config if entitlement is unknown and user never signed up
|
||||
}
|
||||
|
||||
return { ...state, entitlement };
|
||||
}
|
||||
|
||||
return state;
|
||||
@@ -1148,6 +1170,7 @@ export class ChatEntitlementContext extends Disposable {
|
||||
const state = this.withConfiguration(this._state);
|
||||
|
||||
this.signedOutContextKey.set(state.entitlement === ChatEntitlement.Unknown);
|
||||
this.anonymousContextKey.set(state.entitlement === ChatEntitlement.Anonymous);
|
||||
this.canSignUpContextKey.set(state.entitlement === ChatEntitlement.Available);
|
||||
|
||||
this.freeContextKey.set(state.entitlement === ChatEntitlement.Free);
|
||||
|
||||
15
src/vscode-dts/vscode.proposed.devDeviceId.d.ts
vendored
Normal file
15
src/vscode-dts/vscode.proposed.devDeviceId.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
export namespace env {
|
||||
|
||||
/**
|
||||
* An alternative unique identifier for the computer.
|
||||
*/
|
||||
export const devDeviceId: string;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user