Skip to content

Commit

Permalink
add ExtensionContent#languageModelAccessInformation (#206420)
Browse files Browse the repository at this point in the history
* makes ExtHostAuth and ExtHostLM injectable
* (hack) makes silents auth requests for all extension upon LM registration

#206265
  • Loading branch information
jrieken authored Feb 28, 2024
1 parent 729612b commit 763df0e
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 45 deletions.
5 changes: 3 additions & 2 deletions src/vs/workbench/api/browser/mainThreadLanguageModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { coalesce } from 'vs/base/common/arrays';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, DisposableMap, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
Expand Down Expand Up @@ -36,7 +37,7 @@ export class MainThreadLanguageModels implements MainThreadLanguageModelsShape {
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostChatProvider);

this._proxy.$updateLanguageModels({ added: _chatProviderService.getLanguageModelIds() });
this._proxy.$updateLanguageModels({ added: coalesce(_chatProviderService.getLanguageModelIds().map(id => _chatProviderService.lookupLanguageModel(id))) });
this._store.add(_chatProviderService.onDidChangeLanguageModels(this._proxy.$updateLanguageModels, this._proxy));
}

Expand Down Expand Up @@ -91,7 +92,7 @@ export class MainThreadLanguageModels implements MainThreadLanguageModelsShape {

await Promise.race([
activate,
Event.toPromise(Event.filter(this._chatProviderService.onDidChangeLanguageModels, e => Boolean(e.added?.includes(providerId))))
Event.toPromise(Event.filter(this._chatProviderService.onDidChangeLanguageModels, e => Boolean(e.added?.some(value => value.identifier === providerId))))
]);

return this._chatProviderService.lookupLanguageModel(providerId);
Expand Down
18 changes: 10 additions & 8 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import { CandidatePortSource, ExtHostContext, ExtHostLogLevelServiceShape, MainC
import { ExtHostRelatedInformation } from 'vs/workbench/api/common/extHostAiRelatedInformation';
import { ExtHostApiCommands } from 'vs/workbench/api/common/extHostApiCommands';
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { ExtHostAuthentication } from 'vs/workbench/api/common/extHostAuthentication';
import { IExtHostAuthentication } from 'vs/workbench/api/common/extHostAuthentication';
import { ExtHostBulkEdits } from 'vs/workbench/api/common/extHostBulkEdits';
import { ExtHostChat } from 'vs/workbench/api/common/extHostChat';
import { ExtHostChatAgents2 } from 'vs/workbench/api/common/extHostChatAgents2';
import { ExtHostLanguageModels } from 'vs/workbench/api/common/extHostLanguageModels';
import { IExtHostLanguageModels } from 'vs/workbench/api/common/extHostLanguageModels';
import { ExtHostChatVariables } from 'vs/workbench/api/common/extHostChatVariables';
import { ExtHostClipboard } from 'vs/workbench/api/common/extHostClipboard';
import { ExtHostEditorInsets } from 'vs/workbench/api/common/extHostCodeInsets';
Expand Down Expand Up @@ -143,6 +143,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const extHostSecretState = accessor.get(IExtHostSecretState);
const extHostEditorTabs = accessor.get(IExtHostEditorTabs);
const extHostManagedSockets = accessor.get(IExtHostManagedSockets);
const extHostAuthentication = accessor.get(IExtHostAuthentication);
const extHostLanguageModels = accessor.get(IExtHostLanguageModels);

// register addressable instances
rpcProtocol.set(ExtHostContext.ExtHostFileSystemInfo, extHostFileSystemInfo);
Expand All @@ -157,6 +159,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
rpcProtocol.set(ExtHostContext.ExtHostTelemetry, extHostTelemetry);
rpcProtocol.set(ExtHostContext.ExtHostEditorTabs, extHostEditorTabs);
rpcProtocol.set(ExtHostContext.ExtHostManagedSockets, extHostManagedSockets);
rpcProtocol.set(ExtHostContext.ExtHostAuthentication, extHostAuthentication);
rpcProtocol.set(ExtHostContext.ExtHostChatProvider, extHostLanguageModels);

// automatically create and register addressable instances
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations));
Expand Down Expand Up @@ -196,7 +200,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHostLabelService, new ExtHostLabelService(rpcProtocol));
const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol));
const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol));
const extHostTimeline = rpcProtocol.set(ExtHostContext.ExtHostTimeline, new ExtHostTimeline(rpcProtocol, extHostCommands));
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol, initData.remote, extHostWorkspace, extHostLogService, extHostApiDeprecation));
const extHostWebviewPanels = rpcProtocol.set(ExtHostContext.ExtHostWebviewPanels, new ExtHostWebviewPanels(rpcProtocol, extHostWebviews, extHostWorkspace));
Expand All @@ -207,7 +210,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const extHostProfileContentHandlers = rpcProtocol.set(ExtHostContext.ExtHostProfileContentHandlers, new ExtHostProfileContentHandlers(rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostInteractive, new ExtHostInteractive(rpcProtocol, extHostNotebook, extHostDocumentsAndEditors, extHostCommands, extHostLogService));
const extHostInteractiveEditor = rpcProtocol.set(ExtHostContext.ExtHostInlineChat, new ExtHostInteractiveEditor(rpcProtocol, extHostCommands, extHostDocuments, extHostLogService));
const extHostChatProvider = rpcProtocol.set(ExtHostContext.ExtHostChatProvider, new ExtHostLanguageModels(rpcProtocol, extHostLogService, extHostAuthentication));
const extHostChatAgents2 = rpcProtocol.set(ExtHostContext.ExtHostChatAgents2, new ExtHostChatAgents2(rpcProtocol, extHostLogService, extHostCommands));
const extHostChatVariables = rpcProtocol.set(ExtHostContext.ExtHostChatVariables, new ExtHostChatVariables(rpcProtocol));
const extHostChat = rpcProtocol.set(ExtHostContext.ExtHostChat, new ExtHostChat(rpcProtocol));
Expand Down Expand Up @@ -1413,7 +1415,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const chat: typeof vscode.chat = {
registerChatResponseProvider(id: string, provider: vscode.ChatResponseProvider, metadata: vscode.ChatResponseProviderMetadata) {
checkProposedApiEnabled(extension, 'chatProvider');
return extHostChatProvider.registerLanguageModel(extension, id, provider, metadata);
return extHostLanguageModels.registerLanguageModel(extension, id, provider, metadata);
},
registerChatVariableResolver(name: string, description: string, resolver: vscode.ChatVariableResolver) {
checkProposedApiEnabled(extension, 'chatVariableResolver');
Expand All @@ -1433,15 +1435,15 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const lm: typeof vscode.lm = {
get languageModels() {
checkProposedApiEnabled(extension, 'languageModels');
return extHostChatProvider.getLanguageModelIds();
return extHostLanguageModels.getLanguageModelIds();
},
onDidChangeLanguageModels: (listener, thisArgs?, disposables?) => {
checkProposedApiEnabled(extension, 'languageModels');
return extHostChatProvider.onDidChangeProviders(listener, thisArgs, disposables);
return extHostLanguageModels.onDidChangeProviders(listener, thisArgs, disposables);
},
sendChatRequest(languageModel: string, messages: vscode.LanguageModelChatMessage[], options: vscode.LanguageModelChatRequestOptions, token: vscode.CancellationToken) {
checkProposedApiEnabled(extension, 'languageModels');
return extHostChatProvider.sendChatRequest(extension, languageModel, messages, options, token);
return extHostLanguageModels.sendChatRequest(extension, languageModel, messages, options, token);
}
};

Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/api/common/extHost.common.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ import { ILoggerService } from 'vs/platform/log/common/log';
import { ExtHostVariableResolverProviderService, IExtHostVariableResolverProvider } from 'vs/workbench/api/common/extHostVariableResolverService';
import { ExtHostLocalizationService, IExtHostLocalizationService } from 'vs/workbench/api/common/extHostLocalizationService';
import { ExtHostManagedSockets, IExtHostManagedSockets } from 'vs/workbench/api/common/extHostManagedSockets';
import { ExtHostAuthentication, IExtHostAuthentication } from 'vs/workbench/api/common/extHostAuthentication';
import { ExtHostLanguageModels, IExtHostLanguageModels } from 'vs/workbench/api/common/extHostLanguageModels';

registerSingleton(IExtHostLocalizationService, ExtHostLocalizationService, InstantiationType.Delayed);
registerSingleton(ILoggerService, ExtHostLoggerService, InstantiationType.Delayed);
registerSingleton(IExtHostApiDeprecationService, ExtHostApiDeprecationService, InstantiationType.Delayed);
registerSingleton(IExtHostCommands, ExtHostCommands, InstantiationType.Eager);
registerSingleton(IExtHostAuthentication, ExtHostAuthentication, InstantiationType.Eager);
registerSingleton(IExtHostLanguageModels, ExtHostLanguageModels, InstantiationType.Eager);
registerSingleton(IExtHostConfiguration, ExtHostConfiguration, InstantiationType.Eager);
registerSingleton(IExtHostConsumerFileSystem, ExtHostConsumerFileSystem, InstantiationType.Eager);
registerSingleton(IExtHostDebugService, WorkerExtHostDebugService, InstantiationType.Eager);
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ export interface MainThreadLanguageModelsShape extends IDisposable {
}

export interface ExtHostLanguageModelsShape {
$updateLanguageModels(data: { added?: string[]; removed?: string[] }): void;
$updateLanguageModels(data: { added?: ILanguageModelChatMetadata[]; removed?: string[] }): void;
$updateModelAccesslist(data: { from: ExtensionIdentifier; to: ExtensionIdentifier; enabled: boolean }[]): void;
$provideLanguageModelResponse(handle: number, requestId: number, from: ExtensionIdentifier, messages: IChatMessage[], options: { [name: string]: any }, token: CancellationToken): Promise<any>;
$handleResponseFragment(requestId: number, chunk: IChatResponseFragment): Promise<void>;
Expand Down
16 changes: 13 additions & 3 deletions src/vs/workbench/api/common/extHostAuthentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@

import type * as vscode from 'vscode';
import { Emitter, Event } from 'vs/base/common/event';
import { IMainContext, MainContext, MainThreadAuthenticationShape, ExtHostAuthenticationShape } from 'vs/workbench/api/common/extHost.protocol';
import { MainContext, MainThreadAuthenticationShape, ExtHostAuthenticationShape } from 'vs/workbench/api/common/extHost.protocol';
import { Disposable } from 'vs/workbench/api/common/extHostTypes';
import { IExtensionDescription, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { INTERNAL_AUTH_PROVIDER_PREFIX } from 'vs/workbench/services/authentication/common/authentication';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';

export interface IExtHostAuthentication extends ExtHostAuthentication { }
export const IExtHostAuthentication = createDecorator<IExtHostAuthentication>('IExtHostAuthentication');

interface ProviderWithMetadata {
label: string;
Expand All @@ -17,6 +22,9 @@ interface ProviderWithMetadata {
}

export class ExtHostAuthentication implements ExtHostAuthenticationShape {

declare _serviceBrand: undefined;

private _proxy: MainThreadAuthenticationShape;
private _authenticationProviders: Map<string, ProviderWithMetadata> = new Map<string, ProviderWithMetadata>();

Expand All @@ -26,8 +34,10 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape {
private _getSessionTaskSingler = new TaskSingler<vscode.AuthenticationSession | undefined>();
private _getSessionsTaskSingler = new TaskSingler<ReadonlyArray<vscode.AuthenticationSession>>();

constructor(mainContext: IMainContext) {
this._proxy = mainContext.getProxy(MainContext.MainThreadAuthentication);
constructor(
@IExtHostRpcService extHostRpc: IExtHostRpcService
) {
this._proxy = extHostRpc.getProxy(MainContext.MainThreadAuthentication);
}

async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions & ({ createIfNone: true } | { forceNewSession: true } | { forceNewSession: vscode.AuthenticationForceNewSessionOptions })): Promise<vscode.AuthenticationSession>;
Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/api/common/extHostExtensionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
import { IExtHostLanguageModels } from 'vs/workbench/api/common/extHostLanguageModels';
import { Emitter, Event } from 'vs/base/common/event';
import { IExtensionActivationHost, checkActivateWorkspaceContainsExtension } from 'vs/workbench/services/extensions/common/workspaceContains';
import { ExtHostSecretState, IExtHostSecretState } from 'vs/workbench/api/common/extHostSecretState';
Expand Down Expand Up @@ -136,6 +137,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
@IExtHostTerminalService extHostTerminalService: IExtHostTerminalService,
@IExtHostLocalizationService extHostLocalizationService: IExtHostLocalizationService,
@IExtHostManagedSockets private readonly _extHostManagedSockets: IExtHostManagedSockets,
@IExtHostLanguageModels private readonly _extHostLanguageModels: IExtHostLanguageModels,
) {
super();
this._hostUtils = hostUtils;
Expand Down Expand Up @@ -489,6 +491,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme

private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise<vscode.ExtensionContext> {

const lanuageModelAccessInformation = this._extHostLanguageModels.createLanguageModelAccessInformation(extensionDescription);
const globalState = new ExtensionGlobalMemento(extensionDescription, this._storage);
const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage);
const secrets = new ExtensionSecrets(extensionDescription, this._secretState);
Expand Down Expand Up @@ -517,6 +520,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
workspaceState,
secrets,
subscriptions: [],
get languageModelAccessInformation() { return lanuageModelAccessInformation; },
get extensionUri() { return extensionDescription.extensionLocation; },
get extensionPath() { return extensionDescription.extensionLocation.fsPath; },
asAbsolutePath(relativePath: string) { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
Expand Down
Loading

0 comments on commit 763df0e

Please sign in to comment.