2
2
* Copyright (c) Microsoft Corporation. All Rights Reserved.
3
3
* See 'LICENSE' in the project root for license information.
4
4
* ------------------------------------------------------------------------------------------ */
5
- import { ContextResolver , ResolveRequest , SupportedContextItem } from '@github/copilot-language-server' ;
5
+ import { ContextResolver , ResolveRequest , SupportedContextItem , type ContextProvider } from '@github/copilot-language-server' ;
6
6
import { randomUUID } from 'crypto' ;
7
7
import * as vscode from 'vscode' ;
8
8
import { DocumentSelector } from 'vscode-languageserver-protocol' ;
@@ -11,7 +11,7 @@ import { getOutputChannelLogger, Logger } from '../logger';
11
11
import * as telemetry from '../telemetry' ;
12
12
import { CopilotCompletionContextResult } from './client' ;
13
13
import { CopilotCompletionContextTelemetry } from './copilotCompletionContextTelemetry' ;
14
- import { getCopilotApi } from './copilotProviders' ;
14
+ import { getCopilotChatApi , getCopilotClientApi , type CopilotContextProviderAPI } from './copilotProviders' ;
15
15
import { clients } from './extension' ;
16
16
import { CppSettings } from './settings' ;
17
17
@@ -83,7 +83,7 @@ export class CopilotCompletionContextProvider implements ContextResolver<Support
83
83
private static readonly defaultMaxSnippetLength = 3 * 1024 ;
84
84
private static readonly defaultDoAggregateSnippets = true ;
85
85
private completionContextCancellation = new vscode . CancellationTokenSource ( ) ;
86
- private contextProviderDisposable : vscode . Disposable | undefined ;
86
+ private contextProviderDisposables : vscode . Disposable [ ] | undefined ;
87
87
static readonly CppContextProviderEnabledFeatures = 'enabledFeatures' ;
88
88
static readonly CppContextProviderTimeBudgetMs = 'timeBudgetMs' ;
89
89
static readonly CppContextProviderMaxSnippetCount = 'maxSnippetCount' ;
@@ -312,7 +312,12 @@ export class CopilotCompletionContextProvider implements ContextResolver<Support
312
312
313
313
public dispose ( ) : void {
314
314
this . completionContextCancellation . cancel ( ) ;
315
- this . contextProviderDisposable ?. dispose ( ) ;
315
+ if ( this . contextProviderDisposables ) {
316
+ for ( const disposable of this . contextProviderDisposables ) {
317
+ disposable . dispose ( ) ;
318
+ }
319
+ this . contextProviderDisposables = undefined ;
320
+ }
316
321
}
317
322
318
323
public removeFile ( fileUri : string ) : void {
@@ -444,18 +449,32 @@ ${copilotCompletionContext?.areSnippetsMissing ? "(missing code snippets)" : ""}
444
449
const properties : Record < string , string > = { } ;
445
450
const registerCopilotContextProvider = 'registerCopilotContextProvider' ;
446
451
try {
447
- const copilotApi = await getCopilotApi ( ) ;
448
- if ( ! copilotApi ) { throw new CopilotContextProviderException ( "getCopilotApi() returned null, Copilot is missing or inactive." ) ; }
449
- const hasGetContextProviderAPI = "getContextProviderAPI" in copilotApi ;
450
- if ( ! hasGetContextProviderAPI ) { throw new CopilotContextProviderException ( "getContextProviderAPI() is not available." ) ; }
451
- const contextAPI = await copilotApi . getContextProviderAPI ( "v1" ) ;
452
- if ( ! contextAPI ) { throw new CopilotContextProviderException ( "getContextProviderAPI(v1) returned null." ) ; }
453
- this . contextProviderDisposable = contextAPI . registerContextProvider ( {
452
+ const copilotApi = await getCopilotClientApi ( ) ;
453
+ const copilotChatApi = await getCopilotChatApi ( ) ;
454
+ if ( ! copilotApi && ! copilotChatApi ) { throw new CopilotContextProviderException ( "getCopilotApi() returned null, Copilot is missing or inactive." ) ; }
455
+ const contextProvider = {
454
456
id : CopilotCompletionContextProvider . providerId ,
455
457
selector : CopilotCompletionContextProvider . defaultCppDocumentSelector ,
456
458
resolver : this
457
- } ) ;
458
- properties [ "cppCodeSnippetsProviderRegistered" ] = "true" ;
459
+ } ;
460
+ type InstallSummary = { hasGetContextProviderAPI : boolean ; hasAPI : boolean } ;
461
+ const installSummary : { client ?: InstallSummary ; chat ?: InstallSummary } = { } ;
462
+ if ( copilotApi ) {
463
+ installSummary . client = await this . installContextProvider ( copilotApi , contextProvider ) ;
464
+ }
465
+ if ( copilotChatApi ) {
466
+ installSummary . chat = await this . installContextProvider ( copilotChatApi , contextProvider ) ;
467
+ }
468
+ if ( installSummary . client ?. hasAPI || installSummary . chat ?. hasAPI ) {
469
+ properties [ "cppCodeSnippetsProviderRegistered" ] = "true" ;
470
+ } else {
471
+ if ( installSummary . client ?. hasGetContextProviderAPI === false &&
472
+ installSummary . chat ?. hasGetContextProviderAPI === false ) {
473
+ throw new CopilotContextProviderException ( "getContextProviderAPI() is not available." ) ;
474
+ } else {
475
+ throw new CopilotContextProviderException ( "getContextProviderAPI(v1) returned null." ) ;
476
+ }
477
+ }
459
478
} catch ( e ) {
460
479
console . debug ( "Failed to register the Copilot Context Provider." ) ;
461
480
properties [ "error" ] = "Failed to register the Copilot Context Provider" ;
@@ -466,4 +485,18 @@ ${copilotCompletionContext?.areSnippetsMissing ? "(missing code snippets)" : ""}
466
485
telemetry . logCopilotEvent ( registerCopilotContextProvider , { ...properties } ) ;
467
486
}
468
487
}
488
+
489
+ private async installContextProvider ( copilotAPI : CopilotContextProviderAPI , contextProvider : ContextProvider < SupportedContextItem > ) : Promise < { hasGetContextProviderAPI : boolean ; hasAPI : boolean } > {
490
+ const hasGetContextProviderAPI = typeof copilotAPI . getContextProviderAPI === 'function' ;
491
+ if ( hasGetContextProviderAPI ) {
492
+ const contextAPI = await copilotAPI . getContextProviderAPI ( "v1" ) ;
493
+ if ( contextAPI ) {
494
+ this . contextProviderDisposables = this . contextProviderDisposables ?? [ ] ;
495
+ this . contextProviderDisposables . push ( contextAPI . registerContextProvider ( contextProvider ) ) ;
496
+ }
497
+ return { hasGetContextProviderAPI, hasAPI : contextAPI !== undefined } ;
498
+ } else {
499
+ return { hasGetContextProviderAPI : false , hasAPI : false } ;
500
+ }
501
+ }
469
502
}
0 commit comments