@theia/ai-copilot 1.71.0-next.8 → 1.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/copilot-auth-dialog-messages.d.ts +19 -0
- package/lib/browser/copilot-auth-dialog-messages.d.ts.map +1 -0
- package/lib/browser/copilot-auth-dialog-messages.js +36 -0
- package/lib/browser/copilot-auth-dialog-messages.js.map +1 -0
- package/lib/browser/copilot-auth-dialog.d.ts +2 -0
- package/lib/browser/copilot-auth-dialog.d.ts.map +1 -1
- package/lib/browser/copilot-auth-dialog.js +7 -3
- package/lib/browser/copilot-auth-dialog.js.map +1 -1
- package/lib/browser/copilot-frontend-module.d.ts.map +1 -1
- package/lib/browser/copilot-frontend-module.js +6 -3
- package/lib/browser/copilot-frontend-module.js.map +1 -1
- package/lib/browser/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/common/copilot-language-models-manager.d.ts +0 -1
- package/lib/common/copilot-language-models-manager.d.ts.map +1 -1
- package/lib/common/copilot-language-models-manager.js +1 -2
- package/lib/common/copilot-language-models-manager.js.map +1 -1
- package/lib/common/copilot-oauth-config.d.ts +33 -0
- package/lib/common/copilot-oauth-config.d.ts.map +1 -0
- package/lib/common/copilot-oauth-config.js +29 -0
- package/lib/common/copilot-oauth-config.js.map +1 -0
- package/lib/common/index.d.ts +1 -0
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +1 -0
- package/lib/common/index.js.map +1 -1
- package/lib/node/copilot-auth-service-impl.d.ts +2 -0
- package/lib/node/copilot-auth-service-impl.d.ts.map +1 -1
- package/lib/node/copilot-auth-service-impl.js +15 -14
- package/lib/node/copilot-auth-service-impl.js.map +1 -1
- package/lib/node/copilot-auth-service-impl.spec.js +46 -0
- package/lib/node/copilot-auth-service-impl.spec.js.map +1 -1
- package/lib/node/copilot-backend-module.d.ts.map +1 -1
- package/lib/node/copilot-backend-module.js +2 -0
- package/lib/node/copilot-backend-module.js.map +1 -1
- package/lib/node/copilot-language-model.d.ts +3 -3
- package/lib/node/copilot-language-model.d.ts.map +1 -1
- package/lib/node/copilot-language-model.js +14 -20
- package/lib/node/copilot-language-model.js.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.d.ts +3 -2
- package/lib/node/copilot-language-models-manager-impl.d.ts.map +1 -1
- package/lib/node/copilot-language-models-manager-impl.js +7 -6
- package/lib/node/copilot-language-models-manager-impl.js.map +1 -1
- package/package.json +7 -7
- package/src/browser/copilot-auth-dialog-messages.ts +55 -0
- package/src/browser/copilot-auth-dialog.tsx +6 -5
- package/src/browser/copilot-frontend-module.ts +7 -4
- package/src/browser/index.ts +1 -0
- package/src/common/copilot-language-models-manager.ts +0 -1
- package/src/common/copilot-oauth-config.ts +55 -0
- package/src/common/index.ts +1 -0
- package/src/node/copilot-auth-service-impl.spec.ts +59 -0
- package/src/node/copilot-auth-service-impl.ts +15 -15
- package/src/node/copilot-backend-module.ts +2 -0
- package/src/node/copilot-language-model.ts +14 -29
- package/src/node/copilot-language-models-manager-impl.ts +8 -7
|
@@ -18,6 +18,7 @@ import { expect } from 'chai';
|
|
|
18
18
|
import * as sinon from 'sinon';
|
|
19
19
|
import { Container } from '@theia/core/shared/inversify';
|
|
20
20
|
import { KeyStoreService } from '@theia/core/lib/common/key-store';
|
|
21
|
+
import { CopilotOAuthConfig, DEFAULT_COPILOT_OAUTH_CONFIG } from '../common/copilot-oauth-config';
|
|
21
22
|
import { CopilotAuthServiceImpl } from './copilot-auth-service-impl';
|
|
22
23
|
|
|
23
24
|
describe('CopilotAuthServiceImpl', () => {
|
|
@@ -40,6 +41,7 @@ describe('CopilotAuthServiceImpl', () => {
|
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
container.bind(KeyStoreService).toConstantValue(keyStoreService);
|
|
44
|
+
container.bind(CopilotOAuthConfig).toConstantValue(DEFAULT_COPILOT_OAUTH_CONFIG);
|
|
43
45
|
container.bind(CopilotAuthServiceImpl).toSelf().inSingletonScope();
|
|
44
46
|
|
|
45
47
|
authService = container.get(CopilotAuthServiceImpl);
|
|
@@ -183,3 +185,60 @@ describe('CopilotAuthServiceImpl', () => {
|
|
|
183
185
|
});
|
|
184
186
|
});
|
|
185
187
|
});
|
|
188
|
+
|
|
189
|
+
describe('CopilotAuthServiceImpl with custom CopilotOAuthConfig', () => {
|
|
190
|
+
|
|
191
|
+
const customConfig: CopilotOAuthConfig = {
|
|
192
|
+
clientId: 'CustomClientId',
|
|
193
|
+
userAgent: 'MyApp/1.0.0',
|
|
194
|
+
keystoreService: 'myapp-copilot',
|
|
195
|
+
keystoreAccount: 'myapp-github'
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
let authService: CopilotAuthServiceImpl;
|
|
199
|
+
let getPasswordStub: sinon.SinonStub;
|
|
200
|
+
let deletePasswordStub: sinon.SinonStub;
|
|
201
|
+
|
|
202
|
+
beforeEach(() => {
|
|
203
|
+
const container = new Container();
|
|
204
|
+
|
|
205
|
+
getPasswordStub = sinon.stub().resolves(undefined);
|
|
206
|
+
deletePasswordStub = sinon.stub().resolves(true);
|
|
207
|
+
const keyStoreService: KeyStoreService = {
|
|
208
|
+
setPassword: sinon.stub().resolves() as KeyStoreService['setPassword'],
|
|
209
|
+
getPassword: getPasswordStub as KeyStoreService['getPassword'],
|
|
210
|
+
deletePassword: deletePasswordStub as KeyStoreService['deletePassword'],
|
|
211
|
+
findPassword: sinon.stub().resolves(undefined) as KeyStoreService['findPassword'],
|
|
212
|
+
findCredentials: sinon.stub().resolves([]) as KeyStoreService['findCredentials'],
|
|
213
|
+
keys: sinon.stub().resolves([]) as KeyStoreService['keys']
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
container.bind(KeyStoreService).toConstantValue(keyStoreService);
|
|
217
|
+
container.bind(CopilotOAuthConfig).toConstantValue(customConfig);
|
|
218
|
+
container.bind(CopilotAuthServiceImpl).toSelf().inSingletonScope();
|
|
219
|
+
|
|
220
|
+
authService = container.get(CopilotAuthServiceImpl);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
afterEach(() => {
|
|
224
|
+
sinon.restore();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should read credentials from the custom keystore service and account', async () => {
|
|
228
|
+
getPasswordStub.resolves(JSON.stringify({
|
|
229
|
+
accessToken: 'gho_custom_token',
|
|
230
|
+
accountLabel: 'customuser'
|
|
231
|
+
}));
|
|
232
|
+
|
|
233
|
+
const token = await authService.getAccessToken();
|
|
234
|
+
|
|
235
|
+
expect(token).to.equal('gho_custom_token');
|
|
236
|
+
expect(getPasswordStub.calledOnceWith(customConfig.keystoreService, customConfig.keystoreAccount)).to.be.true;
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('should delete credentials from the custom keystore service and account on sign out', async () => {
|
|
240
|
+
await authService.signOut();
|
|
241
|
+
|
|
242
|
+
expect(deletePasswordStub.calledOnceWith(customConfig.keystoreService, customConfig.keystoreAccount)).to.be.true;
|
|
243
|
+
});
|
|
244
|
+
});
|
|
@@ -23,13 +23,10 @@ import {
|
|
|
23
23
|
CopilotAuthState,
|
|
24
24
|
DeviceCodeResponse
|
|
25
25
|
} from '../common/copilot-auth-service';
|
|
26
|
-
import {
|
|
26
|
+
import { CopilotOAuthConfig } from '../common/copilot-oauth-config';
|
|
27
27
|
|
|
28
|
-
const COPILOT_CLIENT_ID = 'Ov23liS2vINy9VOAweyv'; // 'Theia Copilot OAuth Access' Client ID
|
|
29
28
|
const COPILOT_SCOPE = 'read:user';
|
|
30
29
|
const COPILOT_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';
|
|
31
|
-
const KEYSTORE_SERVICE = 'theia-copilot-auth';
|
|
32
|
-
const KEYSTORE_ACCOUNT = 'github-copilot';
|
|
33
30
|
|
|
34
31
|
/**
|
|
35
32
|
* Maximum number of polling attempts for token retrieval.
|
|
@@ -53,6 +50,9 @@ export class CopilotAuthServiceImpl implements CopilotAuthService {
|
|
|
53
50
|
@inject(KeyStoreService)
|
|
54
51
|
protected readonly keyStoreService: KeyStoreService;
|
|
55
52
|
|
|
53
|
+
@inject(CopilotOAuthConfig)
|
|
54
|
+
protected readonly oauthConfig: CopilotOAuthConfig;
|
|
55
|
+
|
|
56
56
|
protected client: CopilotAuthServiceClient | undefined;
|
|
57
57
|
protected cachedState: CopilotAuthState | undefined;
|
|
58
58
|
|
|
@@ -87,10 +87,10 @@ export class CopilotAuthServiceImpl implements CopilotAuthService {
|
|
|
87
87
|
headers: {
|
|
88
88
|
'Accept': 'application/json',
|
|
89
89
|
'Content-Type': 'application/json',
|
|
90
|
-
'User-Agent':
|
|
90
|
+
'User-Agent': this.oauthConfig.userAgent
|
|
91
91
|
},
|
|
92
92
|
body: JSON.stringify({
|
|
93
|
-
client_id:
|
|
93
|
+
client_id: this.oauthConfig.clientId,
|
|
94
94
|
scope: COPILOT_SCOPE
|
|
95
95
|
})
|
|
96
96
|
});
|
|
@@ -117,10 +117,10 @@ export class CopilotAuthServiceImpl implements CopilotAuthService {
|
|
|
117
117
|
headers: {
|
|
118
118
|
'Accept': 'application/json',
|
|
119
119
|
'Content-Type': 'application/json',
|
|
120
|
-
'User-Agent':
|
|
120
|
+
'User-Agent': this.oauthConfig.userAgent
|
|
121
121
|
},
|
|
122
122
|
body: JSON.stringify({
|
|
123
|
-
client_id:
|
|
123
|
+
client_id: this.oauthConfig.clientId,
|
|
124
124
|
device_code: deviceCode,
|
|
125
125
|
grant_type: COPILOT_GRANT_TYPE
|
|
126
126
|
})
|
|
@@ -149,8 +149,8 @@ export class CopilotAuthServiceImpl implements CopilotAuthService {
|
|
|
149
149
|
};
|
|
150
150
|
|
|
151
151
|
await this.keyStoreService.setPassword(
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
this.oauthConfig.keystoreService,
|
|
153
|
+
this.oauthConfig.keystoreAccount,
|
|
154
154
|
JSON.stringify(credentials)
|
|
155
155
|
);
|
|
156
156
|
|
|
@@ -199,7 +199,7 @@ export class CopilotAuthServiceImpl implements CopilotAuthService {
|
|
|
199
199
|
const response = await fetch(`${apiBaseUrl}/user`, {
|
|
200
200
|
headers: {
|
|
201
201
|
'Authorization': `Bearer ${accessToken}`,
|
|
202
|
-
'User-Agent':
|
|
202
|
+
'User-Agent': this.oauthConfig.userAgent,
|
|
203
203
|
'Accept': 'application/vnd.github.v3+json'
|
|
204
204
|
}
|
|
205
205
|
});
|
|
@@ -220,13 +220,13 @@ export class CopilotAuthServiceImpl implements CopilotAuthService {
|
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
try {
|
|
223
|
-
const stored = await this.keyStoreService.getPassword(
|
|
223
|
+
const stored = await this.keyStoreService.getPassword(this.oauthConfig.keystoreService, this.oauthConfig.keystoreAccount);
|
|
224
224
|
if (stored) {
|
|
225
225
|
const credentials: StoredCredentials = JSON.parse(stored);
|
|
226
226
|
// Tokens from the current OAuth App start with 'gho_'; other prefixes (e.g. 'ghu_') indicate a token from the previous GitHub App (Iv-prefixed client ID).
|
|
227
227
|
if (!credentials.accessToken.startsWith('gho_')) {
|
|
228
228
|
console.info('Copilot: clearing outdated GitHub App token. Please sign in again.');
|
|
229
|
-
await this.keyStoreService.deletePassword(
|
|
229
|
+
await this.keyStoreService.deletePassword(this.oauthConfig.keystoreService, this.oauthConfig.keystoreAccount);
|
|
230
230
|
this.cachedState = { isAuthenticated: false, migrationRequired: true };
|
|
231
231
|
return this.cachedState;
|
|
232
232
|
}
|
|
@@ -247,7 +247,7 @@ export class CopilotAuthServiceImpl implements CopilotAuthService {
|
|
|
247
247
|
|
|
248
248
|
async getAccessToken(): Promise<string | undefined> {
|
|
249
249
|
try {
|
|
250
|
-
const stored = await this.keyStoreService.getPassword(
|
|
250
|
+
const stored = await this.keyStoreService.getPassword(this.oauthConfig.keystoreService, this.oauthConfig.keystoreAccount);
|
|
251
251
|
if (stored) {
|
|
252
252
|
const credentials: StoredCredentials = JSON.parse(stored);
|
|
253
253
|
return credentials.accessToken;
|
|
@@ -260,7 +260,7 @@ export class CopilotAuthServiceImpl implements CopilotAuthService {
|
|
|
260
260
|
|
|
261
261
|
async signOut(): Promise<void> {
|
|
262
262
|
try {
|
|
263
|
-
await this.keyStoreService.deletePassword(
|
|
263
|
+
await this.keyStoreService.deletePassword(this.oauthConfig.keystoreService, this.oauthConfig.keystoreAccount);
|
|
264
264
|
} catch (error) {
|
|
265
265
|
console.warn('Failed to delete Copilot credentials:', error);
|
|
266
266
|
}
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
COPILOT_AUTH_SERVICE_PATH,
|
|
25
25
|
CopilotAuthServiceClient
|
|
26
26
|
} from '../common';
|
|
27
|
+
import { CopilotOAuthConfig, DEFAULT_COPILOT_OAUTH_CONFIG } from '../common/copilot-oauth-config';
|
|
27
28
|
import { CopilotLanguageModelsManagerImpl } from './copilot-language-models-manager-impl';
|
|
28
29
|
import { CopilotAuthServiceImpl } from './copilot-auth-service-impl';
|
|
29
30
|
|
|
@@ -54,5 +55,6 @@ const copilotConnectionModule = ConnectionContainerModule.create(({ bind }) => {
|
|
|
54
55
|
});
|
|
55
56
|
|
|
56
57
|
export default new ContainerModule(bind => {
|
|
58
|
+
bind(CopilotOAuthConfig).toConstantValue(DEFAULT_COPILOT_OAUTH_CONFIG);
|
|
57
59
|
bind(ConnectionContainerModule).toConstantValue(copilotConnectionModule);
|
|
58
60
|
});
|
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
LanguageModelResponse,
|
|
24
24
|
LanguageModelStatus,
|
|
25
25
|
LanguageModelTextResponse,
|
|
26
|
-
TokenUsageService,
|
|
27
26
|
UserRequest
|
|
28
27
|
} from '@theia/ai-core';
|
|
29
28
|
import { CancellationToken } from '@theia/core';
|
|
@@ -31,7 +30,7 @@ import OpenAI from 'openai';
|
|
|
31
30
|
import { RunnableToolFunctionWithoutParse } from 'openai/lib/RunnableFunction';
|
|
32
31
|
import { ChatCompletionMessageParam } from 'openai/resources';
|
|
33
32
|
import { StreamingAsyncIterator } from '@theia/ai-openai/lib/node/openai-streaming-iterator';
|
|
34
|
-
import { COPILOT_PROVIDER_ID,
|
|
33
|
+
import { COPILOT_PROVIDER_ID, getCopilotApiBaseUrl } from '../common';
|
|
35
34
|
import type { RunnerOptions } from 'openai/lib/AbstractChatCompletionRunner';
|
|
36
35
|
import type { ChatCompletionStream } from 'openai/lib/ChatCompletionStream';
|
|
37
36
|
|
|
@@ -54,7 +53,7 @@ export class CopilotLanguageModel implements LanguageModel {
|
|
|
54
53
|
public maxRetries: number,
|
|
55
54
|
protected readonly accessTokenProvider: () => Promise<string | undefined>,
|
|
56
55
|
protected readonly enterpriseUrlProvider: () => string | undefined,
|
|
57
|
-
protected readonly
|
|
56
|
+
protected readonly userAgentProvider: () => string,
|
|
58
57
|
) { }
|
|
59
58
|
|
|
60
59
|
protected getSettings(request: LanguageModelRequest): Record<string, unknown> {
|
|
@@ -107,7 +106,7 @@ export class CopilotLanguageModel implements LanguageModel {
|
|
|
107
106
|
}
|
|
108
107
|
|
|
109
108
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
|
-
return { stream: new StreamingAsyncIterator(runner as any,
|
|
109
|
+
return { stream: new StreamingAsyncIterator(runner as any, cancellationToken) };
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
protected async handleNonStreamingRequest(openai: OpenAI, request: UserRequest): Promise<LanguageModelTextResponse> {
|
|
@@ -120,19 +119,12 @@ export class CopilotLanguageModel implements LanguageModel {
|
|
|
120
119
|
|
|
121
120
|
const message = response.choices[0].message;
|
|
122
121
|
|
|
123
|
-
if (this.tokenUsageService && response.usage) {
|
|
124
|
-
await this.tokenUsageService.recordTokenUsage(
|
|
125
|
-
this.id,
|
|
126
|
-
{
|
|
127
|
-
inputTokens: response.usage.prompt_tokens,
|
|
128
|
-
outputTokens: response.usage.completion_tokens,
|
|
129
|
-
requestId: request.requestId
|
|
130
|
-
}
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
122
|
return {
|
|
135
|
-
text: message.content ?? ''
|
|
123
|
+
text: message.content ?? '',
|
|
124
|
+
usage: response.usage ? {
|
|
125
|
+
input_tokens: response.usage.prompt_tokens,
|
|
126
|
+
output_tokens: response.usage.completion_tokens,
|
|
127
|
+
} : undefined
|
|
136
128
|
};
|
|
137
129
|
}
|
|
138
130
|
|
|
@@ -150,20 +142,13 @@ export class CopilotLanguageModel implements LanguageModel {
|
|
|
150
142
|
console.error('Error in Copilot chat completion:', JSON.stringify(message));
|
|
151
143
|
}
|
|
152
144
|
|
|
153
|
-
if (this.tokenUsageService && result.usage) {
|
|
154
|
-
await this.tokenUsageService.recordTokenUsage(
|
|
155
|
-
this.id,
|
|
156
|
-
{
|
|
157
|
-
inputTokens: result.usage.prompt_tokens,
|
|
158
|
-
outputTokens: result.usage.completion_tokens,
|
|
159
|
-
requestId: request.requestId
|
|
160
|
-
}
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
145
|
return {
|
|
165
146
|
content: message.content ?? '',
|
|
166
|
-
parsed: message.parsed
|
|
147
|
+
parsed: message.parsed,
|
|
148
|
+
usage: result.usage ? {
|
|
149
|
+
input_tokens: result.usage.prompt_tokens,
|
|
150
|
+
output_tokens: result.usage.completion_tokens,
|
|
151
|
+
} : undefined
|
|
167
152
|
};
|
|
168
153
|
}
|
|
169
154
|
|
|
@@ -191,7 +176,7 @@ export class CopilotLanguageModel implements LanguageModel {
|
|
|
191
176
|
apiKey: accessToken,
|
|
192
177
|
baseURL,
|
|
193
178
|
defaultHeaders: {
|
|
194
|
-
'User-Agent':
|
|
179
|
+
'User-Agent': this.userAgentProvider(),
|
|
195
180
|
'Openai-Intent': 'conversation-edits',
|
|
196
181
|
'X-Initiator': 'user'
|
|
197
182
|
}
|
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import { LanguageModelRegistry, LanguageModelStatus
|
|
17
|
+
import { LanguageModelRegistry, LanguageModelStatus } from '@theia/ai-core';
|
|
18
18
|
import { Disposable, DisposableCollection } from '@theia/core';
|
|
19
19
|
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
20
|
-
import { CopilotLanguageModelsManager, CopilotModelDescription, COPILOT_PROVIDER_ID,
|
|
20
|
+
import { CopilotLanguageModelsManager, CopilotModelDescription, COPILOT_PROVIDER_ID, getCopilotApiBaseUrl } from '../common';
|
|
21
|
+
import { CopilotOAuthConfig } from '../common/copilot-oauth-config';
|
|
21
22
|
import { CopilotLanguageModel } from './copilot-language-model';
|
|
22
23
|
import { CopilotAuthServiceImpl } from './copilot-auth-service-impl';
|
|
23
24
|
|
|
@@ -31,12 +32,12 @@ export class CopilotLanguageModelsManagerImpl implements CopilotLanguageModelsMa
|
|
|
31
32
|
@inject(LanguageModelRegistry)
|
|
32
33
|
protected readonly languageModelRegistry: LanguageModelRegistry;
|
|
33
34
|
|
|
34
|
-
@inject(TokenUsageService)
|
|
35
|
-
protected readonly tokenUsageService: TokenUsageService;
|
|
36
|
-
|
|
37
35
|
@inject(CopilotAuthServiceImpl)
|
|
38
36
|
protected readonly authService: CopilotAuthServiceImpl;
|
|
39
37
|
|
|
38
|
+
@inject(CopilotOAuthConfig)
|
|
39
|
+
protected readonly oauthConfig: CopilotOAuthConfig;
|
|
40
|
+
|
|
40
41
|
protected enterpriseUrl: string | undefined;
|
|
41
42
|
protected readonly toDispose = new DisposableCollection();
|
|
42
43
|
|
|
@@ -92,7 +93,7 @@ export class CopilotLanguageModelsManagerImpl implements CopilotLanguageModelsMa
|
|
|
92
93
|
modelDescription.maxRetries,
|
|
93
94
|
() => this.authService.getAccessToken(),
|
|
94
95
|
() => this.enterpriseUrl,
|
|
95
|
-
this.
|
|
96
|
+
() => this.oauthConfig.userAgent
|
|
96
97
|
)
|
|
97
98
|
]);
|
|
98
99
|
}
|
|
@@ -128,7 +129,7 @@ export class CopilotLanguageModelsManagerImpl implements CopilotLanguageModelsMa
|
|
|
128
129
|
const response = await fetch(`${baseURL}/models`, {
|
|
129
130
|
headers: {
|
|
130
131
|
'Authorization': `Bearer ${accessToken}`,
|
|
131
|
-
'User-Agent':
|
|
132
|
+
'User-Agent': this.oauthConfig.userAgent,
|
|
132
133
|
'Accept': 'application/json'
|
|
133
134
|
}
|
|
134
135
|
});
|