Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/byok/vscode-node/byokContribution.ts
13399 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import { LanguageModelChatInformation, LanguageModelChatProvider, lm } from 'vscode';
6
import { IAuthenticationService } from '../../../platform/authentication/common/authentication';
7
import { ICAPIClientService } from '../../../platform/endpoint/common/capiClient';
8
import { IVSCodeExtensionContext } from '../../../platform/extContext/common/extensionContext';
9
import { ILogService } from '../../../platform/log/common/logService';
10
import { IFetcherService } from '../../../platform/networking/common/fetcherService';
11
import { Disposable, DisposableStore } from '../../../util/vs/base/common/lifecycle';
12
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
13
import { BYOKKnownModels, isBYOKEnabled } from '../../byok/common/byokProvider';
14
import { IExtensionContribution } from '../../common/contributions';
15
import { AnthropicLMProvider } from './anthropicProvider';
16
import { AzureBYOKModelProvider } from './azureProvider';
17
import { BYOKStorageService, IBYOKStorageService } from './byokStorageService';
18
import { CustomOAIBYOKModelProvider } from './customOAIProvider';
19
import { GeminiNativeBYOKLMProvider } from './geminiNativeProvider';
20
import { OllamaLMProvider } from './ollamaProvider';
21
import { OAIBYOKLMProvider } from './openAIProvider';
22
import { OpenRouterLMProvider } from './openRouterProvider';
23
import { XAIBYOKLMProvider } from './xAIProvider';
24
25
export class BYOKContrib extends Disposable implements IExtensionContribution {
26
public readonly id: string = 'byok-contribution';
27
private readonly _byokStorageService: IBYOKStorageService;
28
private readonly _providers: Map<string, LanguageModelChatProvider<LanguageModelChatInformation>> = new Map();
29
private readonly _byokRegistrations = this._register(new DisposableStore());
30
private _byokProvidersRegistered = false;
31
32
constructor(
33
@IFetcherService private readonly _fetcherService: IFetcherService,
34
@ILogService private readonly _logService: ILogService,
35
@ICAPIClientService private readonly _capiClientService: ICAPIClientService,
36
@IVSCodeExtensionContext extensionContext: IVSCodeExtensionContext,
37
@IAuthenticationService authService: IAuthenticationService,
38
@IInstantiationService private readonly _instantiationService: IInstantiationService,
39
) {
40
super();
41
this._byokStorageService = new BYOKStorageService(extensionContext);
42
this._authChange(authService, this._instantiationService);
43
44
this._register(authService.onDidAuthenticationChange(() => {
45
this._authChange(authService, this._instantiationService);
46
}));
47
}
48
49
private async _authChange(authService: IAuthenticationService, instantiationService: IInstantiationService) {
50
const byokEnabled = authService.copilotToken && isBYOKEnabled(authService.copilotToken, this._capiClientService);
51
52
if (!byokEnabled && this._byokProvidersRegistered) {
53
this._logService.info('BYOK: Disabling BYOK providers due to account change.');
54
this._byokRegistrations.clear();
55
this._providers.clear();
56
this._byokProvidersRegistered = false;
57
return;
58
}
59
60
if (byokEnabled && !this._byokProvidersRegistered) {
61
this._byokProvidersRegistered = true;
62
// Update known models list from CDN so all providers have the same list
63
const knownModels = await this.fetchKnownModelList(this._fetcherService);
64
if (this._store.isDisposed) {
65
return;
66
}
67
this._providers.set(OllamaLMProvider.providerName.toLowerCase(), instantiationService.createInstance(OllamaLMProvider, this._byokStorageService));
68
this._providers.set(AnthropicLMProvider.providerName.toLowerCase(), instantiationService.createInstance(AnthropicLMProvider, knownModels[AnthropicLMProvider.providerName], this._byokStorageService));
69
this._providers.set(GeminiNativeBYOKLMProvider.providerName.toLowerCase(), instantiationService.createInstance(GeminiNativeBYOKLMProvider, knownModels[GeminiNativeBYOKLMProvider.providerName], this._byokStorageService));
70
this._providers.set(XAIBYOKLMProvider.providerName.toLowerCase(), instantiationService.createInstance(XAIBYOKLMProvider, knownModels[XAIBYOKLMProvider.providerName], this._byokStorageService));
71
this._providers.set(OAIBYOKLMProvider.providerName.toLowerCase(), instantiationService.createInstance(OAIBYOKLMProvider, knownModels[OAIBYOKLMProvider.providerName], this._byokStorageService));
72
this._providers.set(OpenRouterLMProvider.providerName.toLowerCase(), instantiationService.createInstance(OpenRouterLMProvider, this._byokStorageService));
73
this._providers.set(AzureBYOKModelProvider.providerName.toLowerCase(), instantiationService.createInstance(AzureBYOKModelProvider, this._byokStorageService));
74
this._providers.set(CustomOAIBYOKModelProvider.providerName.toLowerCase(), instantiationService.createInstance(CustomOAIBYOKModelProvider, this._byokStorageService));
75
76
for (const [providerName, provider] of this._providers) {
77
this._byokRegistrations.add(lm.registerLanguageModelChatProvider(providerName, provider));
78
}
79
}
80
}
81
private async fetchKnownModelList(fetcherService: IFetcherService): Promise<Record<string, BYOKKnownModels>> {
82
const data = await (await fetcherService.fetch('https://main.vscode-cdn.net/extensions/copilotChat.json', { method: 'GET', callSite: 'byok-known-models' })).json();
83
// Use this for testing with changes from a local file. Don't check in
84
// const data = JSON.parse((await this._fileSystemService.readFile(URI.file('/Users/roblou/code/vscode-engineering/chat/copilotChat.json'))).toString());
85
let knownModels: Record<string, BYOKKnownModels>;
86
if (data.version !== 1) {
87
this._logService.warn('BYOK: Copilot Chat known models list is not in the expected format. Defaulting to empty list.');
88
knownModels = {};
89
} else {
90
knownModels = data.modelInfo;
91
}
92
this._logService.info('BYOK: Copilot Chat known models list fetched successfully.');
93
return knownModels;
94
}
95
}
96