Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/api/common/extHostLanguageModels.ts
3296 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
6
import type * as vscode from 'vscode';
7
import { AsyncIterableObject, AsyncIterableSource, RunOnceScheduler } from '../../../base/common/async.js';
8
import { VSBuffer } from '../../../base/common/buffer.js';
9
import { CancellationToken } from '../../../base/common/cancellation.js';
10
import { SerializedError, transformErrorForSerialization, transformErrorFromSerialization } from '../../../base/common/errors.js';
11
import { Emitter, Event } from '../../../base/common/event.js';
12
import { Iterable } from '../../../base/common/iterator.js';
13
import { IDisposable, toDisposable } from '../../../base/common/lifecycle.js';
14
import { URI, UriComponents } from '../../../base/common/uri.js';
15
import { localize } from '../../../nls.js';
16
import { ExtensionIdentifier, ExtensionIdentifierMap, ExtensionIdentifierSet, IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
17
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
18
import { ILogService } from '../../../platform/log/common/log.js';
19
import { Progress } from '../../../platform/progress/common/progress.js';
20
import { IChatMessage, IChatResponsePart, ILanguageModelChatMetadata, ILanguageModelChatMetadataAndIdentifier } from '../../contrib/chat/common/languageModels.js';
21
import { DEFAULT_MODEL_PICKER_CATEGORY } from '../../contrib/chat/common/modelPicker/modelPickerWidget.js';
22
import { INTERNAL_AUTH_PROVIDER_PREFIX } from '../../services/authentication/common/authentication.js';
23
import { checkProposedApiEnabled, isProposedApiEnabled } from '../../services/extensions/common/extensions.js';
24
import { SerializableObjectWithBuffers } from '../../services/extensions/common/proxyIdentifier.js';
25
import { ExtHostLanguageModelsShape, MainContext, MainThreadLanguageModelsShape } from './extHost.protocol.js';
26
import { IExtHostAuthentication } from './extHostAuthentication.js';
27
import { IExtHostRpcService } from './extHostRpcService.js';
28
import * as typeConvert from './extHostTypeConverters.js';
29
import * as extHostTypes from './extHostTypes.js';
30
31
export interface IExtHostLanguageModels extends ExtHostLanguageModels { }
32
33
export const IExtHostLanguageModels = createDecorator<IExtHostLanguageModels>('IExtHostLanguageModels');
34
35
type LanguageModelProviderData = {
36
readonly extension: IExtensionDescription;
37
readonly provider: vscode.LanguageModelChatProvider;
38
};
39
40
type LMResponsePart = vscode.LanguageModelTextPart | vscode.LanguageModelToolCallPart | vscode.LanguageModelDataPart | vscode.LanguageModelThinkingPart;
41
42
43
class LanguageModelResponse {
44
45
readonly apiObject: vscode.LanguageModelChatResponse;
46
47
private readonly _defaultStream = new AsyncIterableSource<LMResponsePart>();
48
private _isDone: boolean = false;
49
50
constructor() {
51
52
const that = this;
53
this.apiObject = {
54
// result: promise,
55
get stream() {
56
return that._defaultStream.asyncIterable;
57
},
58
get text() {
59
return AsyncIterableObject.map(that._defaultStream.asyncIterable, part => {
60
if (part instanceof extHostTypes.LanguageModelTextPart) {
61
return part.value;
62
} else {
63
return undefined;
64
}
65
}).coalesce();
66
},
67
};
68
}
69
70
handleResponsePart(parts: IChatResponsePart | IChatResponsePart[]): void {
71
if (this._isDone) {
72
return;
73
}
74
75
const lmResponseParts: LMResponsePart[] = [];
76
77
for (const part of Iterable.wrap(parts)) {
78
79
let out: LMResponsePart;
80
if (part.type === 'text') {
81
out = new extHostTypes.LanguageModelTextPart(part.value, part.audience);
82
} else if (part.type === 'thinking') {
83
out = new extHostTypes.LanguageModelThinkingPart(part.value, part.id, part.metadata);
84
85
} else if (part.type === 'data') {
86
out = new extHostTypes.LanguageModelDataPart(part.data.buffer, part.mimeType, part.audience);
87
} else {
88
out = new extHostTypes.LanguageModelToolCallPart(part.toolCallId, part.name, part.parameters);
89
}
90
lmResponseParts.push(out);
91
}
92
93
this._defaultStream.emitMany(lmResponseParts);
94
}
95
96
reject(err: Error): void {
97
this._isDone = true;
98
this._defaultStream.reject(err);
99
}
100
101
resolve(): void {
102
this._isDone = true;
103
this._defaultStream.resolve();
104
}
105
}
106
107
export class ExtHostLanguageModels implements ExtHostLanguageModelsShape {
108
109
declare _serviceBrand: undefined;
110
111
private static _idPool = 1;
112
113
private readonly _proxy: MainThreadLanguageModelsShape;
114
private readonly _onDidChangeModelAccess = new Emitter<{ from: ExtensionIdentifier; to: ExtensionIdentifier }>();
115
private readonly _onDidChangeProviders = new Emitter<void>();
116
readonly onDidChangeProviders = this._onDidChangeProviders.event;
117
118
private readonly _languageModelProviders = new Map<string, LanguageModelProviderData>();
119
// TODO @lramos15 - Remove the need for both info and metadata as it's a lot of redundancy. Should just need one
120
private readonly _localModels = new Map<string, { metadata: ILanguageModelChatMetadata; info: vscode.LanguageModelChatInformation }>();
121
private readonly _modelAccessList = new ExtensionIdentifierMap<ExtensionIdentifierSet>();
122
private readonly _pendingRequest = new Map<number, { languageModelId: string; res: LanguageModelResponse }>();
123
private readonly _ignoredFileProviders = new Map<number, vscode.LanguageModelIgnoredFileProvider>();
124
125
constructor(
126
@IExtHostRpcService extHostRpc: IExtHostRpcService,
127
@ILogService private readonly _logService: ILogService,
128
@IExtHostAuthentication private readonly _extHostAuthentication: IExtHostAuthentication,
129
) {
130
this._proxy = extHostRpc.getProxy(MainContext.MainThreadLanguageModels);
131
}
132
133
dispose(): void {
134
this._onDidChangeModelAccess.dispose();
135
this._onDidChangeProviders.dispose();
136
}
137
138
registerLanguageModelChatProvider(extension: IExtensionDescription, vendor: string, provider: vscode.LanguageModelChatProvider): IDisposable {
139
140
this._languageModelProviders.set(vendor, { extension: extension, provider });
141
this._proxy.$registerLanguageModelProvider(vendor);
142
143
let providerChangeEventDisposable: IDisposable | undefined;
144
if (provider.onDidChangeLanguageModelChatInformation) {
145
providerChangeEventDisposable = provider.onDidChangeLanguageModelChatInformation(() => {
146
this._proxy.$onLMProviderChange(vendor);
147
});
148
}
149
150
return toDisposable(() => {
151
this._languageModelProviders.delete(vendor);
152
this._clearModelCache(vendor);
153
providerChangeEventDisposable?.dispose();
154
this._proxy.$unregisterProvider(vendor);
155
});
156
}
157
158
// Helper function to clear the local cache for a specific vendor. There's no lookup, so this involves iterating over all models.
159
private _clearModelCache(vendor: string): void {
160
this._localModels.forEach((value, key) => {
161
if (value.metadata.vendor === vendor) {
162
this._localModels.delete(key);
163
}
164
});
165
}
166
167
async $provideLanguageModelChatInfo(vendor: string, options: { silent: boolean }, token: CancellationToken): Promise<ILanguageModelChatMetadataAndIdentifier[]> {
168
const data = this._languageModelProviders.get(vendor);
169
if (!data) {
170
return [];
171
}
172
this._clearModelCache(vendor);
173
// TODO @lramos15 - Remove this old prepare method support in debt week
174
const modelInformation: vscode.LanguageModelChatInformation[] = (data.provider.provideLanguageModelChatInformation ? await data.provider.provideLanguageModelChatInformation(options, token) : await (data.provider as any).prepareLanguageModelChatInformation(options, token)) ?? [];
175
const modelMetadataAndIdentifier: ILanguageModelChatMetadataAndIdentifier[] = modelInformation.map(m => {
176
let auth;
177
if (m.requiresAuthorization && isProposedApiEnabled(data.extension, 'chatProvider')) {
178
auth = {
179
providerLabel: data.extension.displayName || data.extension.name,
180
accountLabel: typeof m.requiresAuthorization === 'object' ? m.requiresAuthorization.label : undefined
181
};
182
}
183
return {
184
metadata: {
185
extension: data.extension.identifier,
186
id: m.id,
187
vendor,
188
name: m.name ?? '',
189
family: m.family ?? '',
190
detail: m.detail,
191
tooltip: m.tooltip,
192
version: m.version,
193
maxInputTokens: m.maxInputTokens,
194
maxOutputTokens: m.maxOutputTokens,
195
auth,
196
isDefault: m.isDefault,
197
isUserSelectable: m.isUserSelectable,
198
statusIcon: m.statusIcon,
199
modelPickerCategory: m.category ?? DEFAULT_MODEL_PICKER_CATEGORY,
200
capabilities: m.capabilities ? {
201
vision: m.capabilities.imageInput,
202
toolCalling: !!m.capabilities.toolCalling,
203
agentMode: !!m.capabilities.toolCalling
204
} : undefined,
205
},
206
identifier: `${vendor}/${m.id}`,
207
};
208
});
209
210
for (let i = 0; i < modelMetadataAndIdentifier.length; i++) {
211
212
this._localModels.set(modelMetadataAndIdentifier[i].identifier, {
213
metadata: modelMetadataAndIdentifier[i].metadata,
214
info: modelInformation[i]
215
});
216
}
217
218
return modelMetadataAndIdentifier;
219
}
220
221
async $startChatRequest(modelId: string, requestId: number, from: ExtensionIdentifier, messages: SerializableObjectWithBuffers<IChatMessage[]>, options: vscode.LanguageModelChatRequestOptions, token: CancellationToken): Promise<void> {
222
const knownModel = this._localModels.get(modelId);
223
if (!knownModel) {
224
throw new Error('Model not found');
225
}
226
227
const data = this._languageModelProviders.get(knownModel.metadata.vendor);
228
if (!data) {
229
throw new Error(`Language model provider for '${knownModel.metadata.id}' not found.`);
230
}
231
232
const queue: IChatResponsePart[] = [];
233
const sendNow = () => {
234
if (queue.length > 0) {
235
this._proxy.$reportResponsePart(requestId, new SerializableObjectWithBuffers(queue));
236
queue.length = 0;
237
}
238
};
239
const queueScheduler = new RunOnceScheduler(sendNow, 30);
240
const sendSoon = (part: IChatResponsePart) => {
241
const newLen = queue.push(part);
242
// flush/send if things pile up more than expected
243
if (newLen > 30) {
244
sendNow();
245
queueScheduler.cancel();
246
} else {
247
queueScheduler.schedule();
248
}
249
};
250
251
const progress = new Progress<vscode.LanguageModelTextPart | vscode.LanguageModelToolCallPart | vscode.LanguageModelDataPart | vscode.LanguageModelThinkingPart>(async fragment => {
252
if (token.isCancellationRequested) {
253
this._logService.warn(`[CHAT](${data.extension.identifier.value}) CANNOT send progress because the REQUEST IS CANCELLED`);
254
return;
255
}
256
257
let part: IChatResponsePart | undefined;
258
if (fragment instanceof extHostTypes.LanguageModelToolCallPart) {
259
part = { type: 'tool_use', name: fragment.name, parameters: fragment.input, toolCallId: fragment.callId };
260
} else if (fragment instanceof extHostTypes.LanguageModelTextPart) {
261
part = { type: 'text', value: fragment.value, audience: fragment.audience };
262
} else if (fragment instanceof extHostTypes.LanguageModelDataPart) {
263
part = { type: 'data', mimeType: fragment.mimeType, data: VSBuffer.wrap(fragment.data), audience: fragment.audience };
264
} else if (fragment instanceof extHostTypes.LanguageModelThinkingPart) {
265
part = { type: 'thinking', value: fragment.value, id: fragment.id, metadata: fragment.metadata };
266
}
267
268
if (!part) {
269
this._logService.warn(`[CHAT](${data.extension.identifier.value}) UNKNOWN part ${JSON.stringify(fragment)}`);
270
return;
271
}
272
273
sendSoon(part);
274
});
275
276
let value: unknown;
277
278
try {
279
value = data.provider.provideLanguageModelChatResponse(
280
knownModel.info,
281
messages.value.map(typeConvert.LanguageModelChatMessage2.to),
282
{ ...options, modelOptions: options.modelOptions ?? {}, requestInitiator: ExtensionIdentifier.toKey(from), toolMode: options.toolMode ?? extHostTypes.LanguageModelChatToolMode.Auto },
283
progress,
284
token
285
);
286
287
} catch (err) {
288
// synchronously failed
289
throw err;
290
}
291
292
Promise.resolve(value).then(() => {
293
sendNow();
294
this._proxy.$reportResponseDone(requestId, undefined);
295
}, err => {
296
sendNow();
297
this._proxy.$reportResponseDone(requestId, transformErrorForSerialization(err));
298
});
299
}
300
301
//#region --- token counting
302
303
$provideTokenLength(modelId: string, value: string, token: CancellationToken): Promise<number> {
304
const knownModel = this._localModels.get(modelId);
305
if (!knownModel) {
306
return Promise.resolve(0);
307
}
308
const data = this._languageModelProviders.get(knownModel.metadata.vendor);
309
if (!data) {
310
return Promise.resolve(0);
311
}
312
return Promise.resolve(data.provider.provideTokenCount(knownModel.info, value, token));
313
}
314
315
316
//#region --- making request
317
318
async getDefaultLanguageModel(extension: IExtensionDescription, forceResolveModels?: boolean): Promise<vscode.LanguageModelChat | undefined> {
319
let defaultModelId: string | undefined;
320
321
if (forceResolveModels) {
322
await this.selectLanguageModels(extension, {});
323
}
324
325
for (const [modelIdentifier, modelData] of this._localModels) {
326
if (modelData.metadata.isDefault) {
327
defaultModelId = modelIdentifier;
328
break;
329
}
330
}
331
if (!defaultModelId) {
332
// Maybe the default wasn't cached so we will try again with resolving the models too
333
return this.getDefaultLanguageModel(extension, true);
334
}
335
return this.getLanguageModelByIdentifier(extension, defaultModelId);
336
}
337
338
async getLanguageModelByIdentifier(extension: IExtensionDescription, modelId: string): Promise<vscode.LanguageModelChat | undefined> {
339
340
const model = this._localModels.get(modelId);
341
if (!model) {
342
// model gone? is this an error on us?
343
return;
344
}
345
346
// make sure auth information is correct
347
if (this._isUsingAuth(extension.identifier, model.metadata)) {
348
await this._fakeAuthPopulate(model.metadata);
349
}
350
351
let apiObject: vscode.LanguageModelChat | undefined;
352
if (!apiObject) {
353
const that = this;
354
apiObject = {
355
id: model.info.id,
356
vendor: model.metadata.vendor,
357
family: model.info.family,
358
version: model.info.version,
359
name: model.info.name,
360
capabilities: {
361
supportsImageToText: model.metadata.capabilities?.vision ?? false,
362
supportsToolCalling: !!model.metadata.capabilities?.toolCalling,
363
},
364
maxInputTokens: model.metadata.maxInputTokens,
365
countTokens(text, token) {
366
if (!that._localModels.has(modelId)) {
367
throw extHostTypes.LanguageModelError.NotFound(modelId);
368
}
369
return that._computeTokenLength(modelId, text, token ?? CancellationToken.None);
370
},
371
sendRequest(messages, options, token) {
372
if (!that._localModels.has(modelId)) {
373
throw extHostTypes.LanguageModelError.NotFound(modelId);
374
}
375
return that._sendChatRequest(extension, modelId, messages, options ?? {}, token ?? CancellationToken.None);
376
}
377
};
378
379
Object.freeze(apiObject);
380
}
381
382
return apiObject;
383
}
384
385
async selectLanguageModels(extension: IExtensionDescription, selector: vscode.LanguageModelChatSelector) {
386
387
// this triggers extension activation
388
const models = await this._proxy.$selectChatModels({ ...selector, extension: extension.identifier });
389
390
const result: vscode.LanguageModelChat[] = [];
391
392
const modelPromises = models.map(identifier => this.getLanguageModelByIdentifier(extension, identifier));
393
const modelResults = await Promise.all(modelPromises);
394
for (const model of modelResults) {
395
if (model) {
396
result.push(model);
397
}
398
}
399
400
return result;
401
}
402
403
private async _sendChatRequest(extension: IExtensionDescription, languageModelId: string, messages: vscode.LanguageModelChatMessage2[], options: vscode.LanguageModelChatRequestOptions, token: CancellationToken) {
404
405
const internalMessages: IChatMessage[] = this._convertMessages(extension, messages);
406
407
const from = extension.identifier;
408
const metadata = this._localModels.get(languageModelId)?.metadata;
409
410
if (!metadata || !this._localModels.has(languageModelId)) {
411
throw extHostTypes.LanguageModelError.NotFound(`Language model '${languageModelId}' is unknown.`);
412
}
413
414
if (this._isUsingAuth(from, metadata)) {
415
const success = await this._getAuthAccess(extension, { identifier: metadata.extension, displayName: metadata.auth.providerLabel }, options.justification, false);
416
417
if (!success || !this._modelAccessList.get(from)?.has(metadata.extension)) {
418
throw extHostTypes.LanguageModelError.NoPermissions(`Language model '${languageModelId}' cannot be used by '${from.value}'.`);
419
}
420
}
421
422
const requestId = (Math.random() * 1e6) | 0;
423
const res = new LanguageModelResponse();
424
this._pendingRequest.set(requestId, { languageModelId, res });
425
426
try {
427
await this._proxy.$tryStartChatRequest(from, languageModelId, requestId, new SerializableObjectWithBuffers(internalMessages), options, token);
428
429
} catch (error) {
430
// error'ing here means that the request could NOT be started/made, e.g. wrong model, no access, etc, but
431
// later the response can fail as well. Those failures are communicated via the stream-object
432
this._pendingRequest.delete(requestId);
433
throw extHostTypes.LanguageModelError.tryDeserialize(error) ?? error;
434
}
435
436
return res.apiObject;
437
}
438
439
private _convertMessages(extension: IExtensionDescription, messages: vscode.LanguageModelChatMessage2[]) {
440
const internalMessages: IChatMessage[] = [];
441
for (const message of messages) {
442
if (message.role as number === extHostTypes.LanguageModelChatMessageRole.System) {
443
checkProposedApiEnabled(extension, 'languageModelSystem');
444
}
445
internalMessages.push(typeConvert.LanguageModelChatMessage2.from(message));
446
}
447
return internalMessages;
448
}
449
450
async $acceptResponsePart(requestId: number, chunk: SerializableObjectWithBuffers<IChatResponsePart | IChatResponsePart[]>): Promise<void> {
451
const data = this._pendingRequest.get(requestId);
452
if (data) {
453
data.res.handleResponsePart(chunk.value);
454
}
455
}
456
457
async $acceptResponseDone(requestId: number, error: SerializedError | undefined): Promise<void> {
458
const data = this._pendingRequest.get(requestId);
459
if (!data) {
460
return;
461
}
462
this._pendingRequest.delete(requestId);
463
if (error) {
464
// we error the stream because that's the only way to signal
465
// that the request has failed
466
data.res.reject(extHostTypes.LanguageModelError.tryDeserialize(error) ?? transformErrorFromSerialization(error));
467
} else {
468
data.res.resolve();
469
}
470
}
471
472
// BIG HACK: Using AuthenticationProviders to check access to Language Models
473
private async _getAuthAccess(from: IExtensionDescription, to: { identifier: ExtensionIdentifier; displayName: string }, justification: string | undefined, silent: boolean | undefined): Promise<boolean> {
474
// This needs to be done in both MainThread & ExtHost ChatProvider
475
const providerId = INTERNAL_AUTH_PROVIDER_PREFIX + to.identifier.value;
476
const session = await this._extHostAuthentication.getSession(from, providerId, [], { silent: true });
477
478
if (session) {
479
this.$updateModelAccesslist([{ from: from.identifier, to: to.identifier, enabled: true }]);
480
return true;
481
}
482
483
if (silent) {
484
return false;
485
}
486
487
try {
488
const detail = justification
489
? localize('chatAccessWithJustification', "Justification: {1}", to.displayName, justification)
490
: undefined;
491
await this._extHostAuthentication.getSession(from, providerId, [], { forceNewSession: { detail } });
492
this.$updateModelAccesslist([{ from: from.identifier, to: to.identifier, enabled: true }]);
493
return true;
494
495
} catch (err) {
496
// ignore
497
return false;
498
}
499
}
500
501
private _isUsingAuth(from: ExtensionIdentifier, toMetadata: ILanguageModelChatMetadata): toMetadata is ILanguageModelChatMetadata & { auth: NonNullable<ILanguageModelChatMetadata['auth']> } {
502
// If the 'to' extension uses an auth check
503
return !!toMetadata.auth
504
// And we're asking from a different extension
505
&& !ExtensionIdentifier.equals(toMetadata.extension, from);
506
}
507
508
private async _fakeAuthPopulate(metadata: ILanguageModelChatMetadata): Promise<void> {
509
510
if (!metadata.auth) {
511
return;
512
}
513
514
for (const from of this._languageAccessInformationExtensions) {
515
try {
516
await this._getAuthAccess(from, { identifier: metadata.extension, displayName: '' }, undefined, true);
517
} catch (err) {
518
this._logService.error('Fake Auth request failed');
519
this._logService.error(err);
520
}
521
}
522
}
523
524
private async _computeTokenLength(modelId: string, value: string | vscode.LanguageModelChatMessage2, token: vscode.CancellationToken): Promise<number> {
525
526
const data = this._localModels.get(modelId);
527
if (!data) {
528
throw extHostTypes.LanguageModelError.NotFound(`Language model '${modelId}' is unknown.`);
529
}
530
return this._languageModelProviders.get(data.metadata.vendor)?.provider.provideTokenCount(data.info, value, token) ?? 0;
531
// return this._proxy.$countTokens(languageModelId, (typeof value === 'string' ? value : typeConvert.LanguageModelChatMessage2.from(value)), token);
532
}
533
534
$updateModelAccesslist(data: { from: ExtensionIdentifier; to: ExtensionIdentifier; enabled: boolean }[]): void {
535
const updated = new Array<{ from: ExtensionIdentifier; to: ExtensionIdentifier }>();
536
for (const { from, to, enabled } of data) {
537
const set = this._modelAccessList.get(from) ?? new ExtensionIdentifierSet();
538
const oldValue = set.has(to);
539
if (oldValue !== enabled) {
540
if (enabled) {
541
set.add(to);
542
} else {
543
set.delete(to);
544
}
545
this._modelAccessList.set(from, set);
546
const newItem = { from, to };
547
updated.push(newItem);
548
this._onDidChangeModelAccess.fire(newItem);
549
}
550
}
551
}
552
553
private readonly _languageAccessInformationExtensions = new Set<Readonly<IExtensionDescription>>();
554
555
createLanguageModelAccessInformation(from: Readonly<IExtensionDescription>): vscode.LanguageModelAccessInformation {
556
557
this._languageAccessInformationExtensions.add(from);
558
559
// const that = this;
560
const _onDidChangeAccess = Event.signal(Event.filter(this._onDidChangeModelAccess.event, e => ExtensionIdentifier.equals(e.from, from.identifier)));
561
const _onDidAddRemove = Event.signal(this._onDidChangeProviders.event);
562
563
return {
564
get onDidChange() {
565
return Event.any(_onDidChangeAccess, _onDidAddRemove);
566
},
567
canSendRequest(chat: vscode.LanguageModelChat): boolean | undefined {
568
return true;
569
// TODO @lramos15 - Fix
570
571
// let metadata: ILanguageModelChatMetadata | undefined;
572
573
// out: for (const [_, value] of that._allLanguageModelData) {
574
// for (const candidate of value.apiObjects.values()) {
575
// if (candidate === chat) {
576
// metadata = value.metadata;
577
// break out;
578
// }
579
// }
580
// }
581
// if (!metadata) {
582
// return undefined;
583
// }
584
// if (!that._isUsingAuth(from.identifier, metadata)) {
585
// return true;
586
// }
587
588
// const list = that._modelAccessList.get(from.identifier);
589
// if (!list) {
590
// return undefined;
591
// }
592
// return list.has(metadata.extension);
593
}
594
};
595
}
596
597
fileIsIgnored(extension: IExtensionDescription, uri: vscode.Uri, token: vscode.CancellationToken = CancellationToken.None): Promise<boolean> {
598
checkProposedApiEnabled(extension, 'chatParticipantAdditions');
599
600
return this._proxy.$fileIsIgnored(uri, token);
601
}
602
603
async $isFileIgnored(handle: number, uri: UriComponents, token: CancellationToken): Promise<boolean> {
604
const provider = this._ignoredFileProviders.get(handle);
605
if (!provider) {
606
throw new Error('Unknown LanguageModelIgnoredFileProvider');
607
}
608
609
return (await provider.provideFileIgnored(URI.revive(uri), token)) ?? false;
610
}
611
612
registerIgnoredFileProvider(extension: IExtensionDescription, provider: vscode.LanguageModelIgnoredFileProvider): vscode.Disposable {
613
checkProposedApiEnabled(extension, 'chatParticipantPrivate');
614
615
const handle = ExtHostLanguageModels._idPool++;
616
this._proxy.$registerFileIgnoreProvider(handle);
617
this._ignoredFileProviders.set(handle, provider);
618
return toDisposable(() => {
619
this._proxy.$unregisterFileIgnoreProvider(handle);
620
this._ignoredFileProviders.delete(handle);
621
});
622
}
623
}
624
625