@codingame/monaco-vscode-extensions-service-override
Version:
VSCode public API plugged on the monaco editor - extensions service-override
209 lines (206 loc) • 10.4 kB
JavaScript
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js';
import { DeferredPromise, AsyncIterableSource } from 'vscode/vscode/vs/base/common/async';
import { transformErrorFromSerialization, transformErrorForSerialization } from 'vscode/vscode/vs/base/common/errors';
import { Emitter } from 'vscode/vscode/vs/base/common/event';
import { DisposableStore, DisposableMap, Disposable, toDisposable } from 'vscode/vscode/vs/base/common/lifecycle';
import { localize } from 'vscode/vscode/vs/nls';
import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service';
import { ExtHostContext, MainContext } from 'vscode/vscode/vs/workbench/api/common/extHost.protocol';
import { ILanguageModelStatsService } from 'vscode/vscode/vs/workbench/contrib/chat/common/languageModelStats.service';
import { ILanguageModelsService } from 'vscode/vscode/vs/workbench/contrib/chat/common/languageModels.service';
import { IAuthenticationAccessService } from 'vscode/vscode/vs/workbench/services/authentication/browser/authenticationAccessService.service';
import { INTERNAL_AUTH_PROVIDER_PREFIX } from 'vscode/vscode/vs/workbench/services/authentication/common/authentication';
import { IAuthenticationService } from 'vscode/vscode/vs/workbench/services/authentication/common/authentication.service';
import { extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js';
import { IExtensionService } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions.service';
let MainThreadLanguageModels = class MainThreadLanguageModels {
constructor(extHostContext, _chatProviderService, _languageModelStatsService, _logService, _authenticationService, _authenticationAccessService, _extensionService) {
this._chatProviderService = _chatProviderService;
this._languageModelStatsService = _languageModelStatsService;
this._logService = _logService;
this._authenticationService = _authenticationService;
this._authenticationAccessService = _authenticationAccessService;
this._extensionService = _extensionService;
this._store = ( (new DisposableStore()));
this._providerRegistrations = ( (new DisposableMap()));
this._pendingProgress = ( (new Map()));
this._proxy = ( (extHostContext.getProxy(ExtHostContext.ExtHostChatProvider)));
this._proxy.$acceptChatModelMetadata({ added: ( (_chatProviderService.getLanguageModelIds().map(
id => ({ identifier: id, metadata: _chatProviderService.lookupLanguageModel(id) })
))) });
this._store.add(_chatProviderService.onDidChangeLanguageModels(this._proxy.$acceptChatModelMetadata, this._proxy));
}
dispose() {
this._providerRegistrations.dispose();
this._store.dispose();
}
$registerLanguageModelProvider(handle, identifier, metadata) {
const dipsosables = ( (new DisposableStore()));
dipsosables.add(this._chatProviderService.registerLanguageModelChat(identifier, {
metadata,
sendChatRequest: async (messages, from, options, token) => {
const requestId = (Math.random() * 1e6) | 0;
const defer = ( (new DeferredPromise()));
const stream = ( (new AsyncIterableSource()));
try {
this._pendingProgress.set(requestId, { defer, stream });
await this._proxy.$startChatRequest(handle, requestId, from, messages, options, token);
}
catch (err) {
this._pendingProgress.delete(requestId);
throw err;
}
return {
result: defer.p,
stream: stream.asyncIterable
};
},
provideTokenCount: (str, token) => {
return this._proxy.$provideTokenLength(handle, str, token);
},
}));
if (metadata.auth) {
dipsosables.add(this._registerAuthenticationProvider(metadata.extension, metadata.auth));
}
this._providerRegistrations.set(handle, dipsosables);
}
async $reportResponsePart(requestId, chunk) {
const data = this._pendingProgress.get(requestId);
this._logService.trace('[LM] report response PART', Boolean(data), requestId, chunk);
if (data) {
data.stream.emitOne(chunk);
}
}
async $reportResponseDone(requestId, err) {
const data = this._pendingProgress.get(requestId);
this._logService.trace('[LM] report response DONE', Boolean(data), requestId, err);
if (data) {
this._pendingProgress.delete(requestId);
if (err) {
const error = transformErrorFromSerialization(err);
data.stream.reject(error);
data.defer.error(error);
}
else {
data.stream.resolve();
data.defer.complete(undefined);
}
}
}
$unregisterProvider(handle) {
this._providerRegistrations.deleteAndDispose(handle);
}
$selectChatModels(selector) {
return this._chatProviderService.selectLanguageModels(selector);
}
$whenLanguageModelChatRequestMade(identifier, extensionId, participant, tokenCount) {
this._languageModelStatsService.update(identifier, extensionId, participant, tokenCount);
}
async $tryStartChatRequest(extension, providerId, requestId, messages, options, token) {
this._logService.trace('[CHAT] request STARTED', extension.value, requestId);
const response = await this._chatProviderService.sendChatRequest(providerId, extension, messages, options, token);
const streaming = (async () => {
try {
for await (const part of response.stream) {
this._logService.trace('[CHAT] request PART', extension.value, requestId, part);
await this._proxy.$acceptResponsePart(requestId, part);
}
this._logService.trace('[CHAT] request DONE', extension.value, requestId);
}
catch (err) {
this._logService.error('[CHAT] extension request ERRORED in STREAM', err, extension.value, requestId);
this._proxy.$acceptResponseDone(requestId, transformErrorForSerialization(err));
}
})();
Promise.allSettled([response.result, streaming]).then(() => {
this._logService.debug('[CHAT] extension request DONE', extension.value, requestId);
this._proxy.$acceptResponseDone(requestId, undefined);
}, err => {
this._logService.error('[CHAT] extension request ERRORED', err, extension.value, requestId);
this._proxy.$acceptResponseDone(requestId, transformErrorForSerialization(err));
});
}
$countTokens(provider, value, token) {
return this._chatProviderService.computeTokenLength(provider, value, token);
}
_registerAuthenticationProvider(extension, auth) {
const authProviderId = INTERNAL_AUTH_PROVIDER_PREFIX + extension.value;
if (this._authenticationService.getProviderIds().includes(authProviderId)) {
return Disposable.None;
}
const accountLabel = auth.accountLabel ?? ( localize(4828, 'Language Models'));
const disposables = ( (new DisposableStore()));
this._authenticationService.registerAuthenticationProvider(authProviderId, ( (new LanguageModelAccessAuthProvider(authProviderId, auth.providerLabel, accountLabel))));
disposables.add(toDisposable(() => {
this._authenticationService.unregisterAuthenticationProvider(authProviderId);
}));
disposables.add(this._authenticationAccessService.onDidChangeExtensionSessionAccess(async (e) => {
const allowedExtensions = this._authenticationAccessService.readAllowedExtensions(authProviderId, accountLabel);
const accessList = [];
for (const allowedExtension of allowedExtensions) {
const from = await this._extensionService.getExtension(allowedExtension.id);
if (from) {
accessList.push({
from: from.identifier,
to: extension,
enabled: allowedExtension.allowed ?? true
});
}
}
this._proxy.$updateModelAccesslist(accessList);
}));
return disposables;
}
};
MainThreadLanguageModels = __decorate([
extHostNamedCustomer(MainContext.MainThreadLanguageModels),
( (__param(1, ILanguageModelsService))),
( (__param(2, ILanguageModelStatsService))),
( (__param(3, ILogService))),
( (__param(4, IAuthenticationService))),
( (__param(5, IAuthenticationAccessService))),
( (__param(6, IExtensionService)))
], MainThreadLanguageModels);
class LanguageModelAccessAuthProvider {
constructor(id, label, _accountLabel) {
this.id = id;
this.label = label;
this._accountLabel = _accountLabel;
this.supportsMultipleAccounts = false;
this._onDidChangeSessions = ( (new Emitter()));
this.onDidChangeSessions = this._onDidChangeSessions.event;
}
async getSessions(scopes) {
if (scopes === undefined && !this._session) {
return [];
}
if (this._session) {
return [this._session];
}
return [await this.createSession(scopes || [])];
}
async createSession(scopes) {
this._session = this._createFakeSession(scopes);
this._onDidChangeSessions.fire({ added: [this._session], changed: [], removed: [] });
return this._session;
}
removeSession(sessionId) {
if (this._session) {
this._onDidChangeSessions.fire({ added: [], changed: [], removed: [this._session] });
this._session = undefined;
}
return Promise.resolve();
}
_createFakeSession(scopes) {
return {
id: 'fake-session',
account: {
id: this.id,
label: this._accountLabel,
},
accessToken: 'fake-access-token',
scopes,
};
}
}
export { MainThreadLanguageModels };