-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
copilotProviders.ts
103 lines (87 loc) · 4.77 KB
/
copilotProviders.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import * as util from '../common';
import { ChatContextResult, GetIncludesResult } from './client';
import { getActiveClient } from './extension';
export interface CopilotTrait {
name: string;
value: string;
includeInPrompt?: boolean;
promptTextOverride?: string;
}
export interface CopilotApi {
registerRelatedFilesProvider(
providerId: { extensionId: string; languageId: string },
callback: (
uri: vscode.Uri,
context: { flags: Record<string, unknown> },
cancellationToken: vscode.CancellationToken
) => Promise<{ entries: vscode.Uri[]; traits?: CopilotTrait[] }>
): Disposable;
}
export async function registerRelatedFilesProvider(): Promise<void> {
const api = await getCopilotApi();
if (util.extensionContext && api) {
try {
for (const languageId of ['c', 'cpp', 'cuda-cpp']) {
api.registerRelatedFilesProvider(
{ extensionId: util.extensionContext.extension.id, languageId },
async (_uri: vscode.Uri, context: { flags: Record<string, unknown> }, token: vscode.CancellationToken) => {
const getIncludesHandler = async () => (await getIncludesWithCancellation(1, token))?.includedFiles.map(file => vscode.Uri.file(file)) ?? [];
const getTraitsHandler = async () => {
const chatContext: ChatContextResult | undefined = await (getActiveClient().getChatContext(token) ?? undefined);
if (!chatContext) {
return undefined;
}
let traits: CopilotTrait[] = [
{ name: "language", value: chatContext.language, includeInPrompt: true, promptTextOverride: `The language is ${chatContext.language}.` },
{ name: "compiler", value: chatContext.compiler, includeInPrompt: true, promptTextOverride: `This project compiles using ${chatContext.compiler}.` },
{ name: "standardVersion", value: chatContext.standardVersion, includeInPrompt: true, promptTextOverride: `This project uses the ${chatContext.standardVersion} language standard.` },
{ name: "targetPlatform", value: chatContext.targetPlatform, includeInPrompt: true, promptTextOverride: `This build targets ${chatContext.targetPlatform}.` },
{ name: "targetArchitecture", value: chatContext.targetArchitecture, includeInPrompt: true, promptTextOverride: `This build targets ${chatContext.targetArchitecture}.` }
];
const excludeTraits = context.flags.copilotcppExcludeTraits as string[] ?? [];
traits = traits.filter(trait => !excludeTraits.includes(trait.name));
return traits.length > 0 ? traits : undefined;
};
// Call both handlers in parallel
const traitsPromise = ((context.flags.copilotcppTraits as boolean) ?? false) ? getTraitsHandler() : Promise.resolve(undefined);
const includesPromise = getIncludesHandler();
return { entries: await includesPromise, traits: await traitsPromise };
}
);
}
} catch {
console.log("Failed to register Copilot related files provider.");
}
}
}
async function getIncludesWithCancellation(maxDepth: number, token: vscode.CancellationToken): Promise<GetIncludesResult> {
const activeClient = getActiveClient();
const includes = await activeClient.getIncludes(maxDepth, token);
const wksFolder = activeClient.RootUri?.toString();
if (!wksFolder) {
return includes;
}
includes.includedFiles = includes.includedFiles.filter(header => vscode.Uri.file(header).toString().startsWith(wksFolder));
return includes;
}
export async function getCopilotApi(): Promise<CopilotApi | undefined> {
const copilotExtension = vscode.extensions.getExtension<CopilotApi>('github.copilot');
if (!copilotExtension) {
return undefined;
}
if (!copilotExtension.isActive) {
try {
return await copilotExtension.activate();
} catch {
return undefined;
}
} else {
return copilotExtension.exports;
}
}