Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/test/intent/intentTest.ts
13389 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 assert from 'assert';
7
import * as fs from 'fs';
8
import path from 'path';
9
import type { ChatParticipantDetectionResult, ChatParticipantMetadata } from 'vscode';
10
import '../../src/extension/intents/node/allIntents';
11
import { IIntentService } from '../../src/extension/intents/node/intentService';
12
import { ChatVariablesCollection } from '../../src/extension/prompt/common/chatVariablesCollection';
13
import { IntentDetector } from '../../src/extension/prompt/node/intentDetector';
14
import { createTelemetryWithId } from '../../src/extension/prompt/node/telemetry';
15
import { editingSessionAgentEditorName, editsAgentName } from '../../src/platform/chat/common/chatAgents';
16
import { ChatLocation } from '../../src/platform/chat/common/commonTypes';
17
import { ITabsAndEditorsService } from '../../src/platform/tabs/common/tabsAndEditorsService';
18
import { TestingServiceCollection } from '../../src/platform/test/node/services';
19
import { TestingTabsAndEditorsService } from '../../src/platform/test/node/simulationWorkspaceServices';
20
import { CancellationToken } from '../../src/util/vs/base/common/cancellation';
21
import { IInstantiationService } from '../../src/util/vs/platform/instantiation/common/instantiation';
22
import { stest } from '../base/stest';
23
24
export interface IIntentScenario {
25
name: string;
26
location: ChatLocation;
27
query: string;
28
expectedIntent: string | string[];
29
}
30
31
export function generateIntentTest(scenario: IIntentScenario) {
32
stest({ description: scenario.name }, async (testingServiceCollection) => {
33
await executeIntentTest(testingServiceCollection, scenario);
34
});
35
}
36
37
export async function executeIntentTest(testingServiceCollection: TestingServiceCollection, scenario: IIntentScenario) {
38
testingServiceCollection.define(ITabsAndEditorsService, new TestingTabsAndEditorsService({
39
getActiveTextEditor: () => undefined,
40
getVisibleTextEditors: () => [],
41
getActiveNotebookEditor: () => undefined
42
}));
43
const accessor = testingServiceCollection.createTestingAccessor();
44
const intentService = accessor.get(IIntentService);
45
const instaService = accessor.get(IInstantiationService);
46
const intentDetector = instaService.createInstance(IntentDetector);
47
const query = scenario.query;
48
const builtinIntents = readBuiltinIntents(scenario.location);
49
const detectedIntent = await intentDetector.detectIntent(scenario.location, undefined, query, CancellationToken.None, createTelemetryWithId(), new ChatVariablesCollection([]), builtinIntents);
50
const intent = detectedIntent ?? intentService.unknownIntent;
51
52
const expectedIntents = Array.isArray(scenario.expectedIntent) ? scenario.expectedIntent : [scenario.expectedIntent];
53
assert.ok(intent && expectedIntents.includes('participant' in intent ? detectedParticipantToIntentId(intent) : intent.id), `Expected intent [${expectedIntents.join(',')}] but got ${'participant' in intent ? intent.participant : intent.id}`);
54
}
55
56
function detectedParticipantToIntentId(detected: ChatParticipantDetectionResult) {
57
switch (detected.participant) {
58
case 'github.copilot.default':
59
return 'unknown';
60
case `github.copilot.${editingSessionAgentEditorName}`:
61
if (detected.command) {
62
return detected.command;
63
}
64
return 'unknown';
65
case 'github.copilot.terminalPanel':
66
return 'terminalExplain';
67
case `github.copilot.${editsAgentName}`:
68
switch (detected.command) {
69
case 'new':
70
return 'new';
71
case 'newNotebook':
72
return 'newNotebook';
73
case 'tests':
74
return 'tests';
75
case 'setupTests':
76
return 'setupTests';
77
default:
78
return 'workspace';
79
}
80
case 'github.copilot.vscode':
81
return 'vscode';
82
case 'github.copilot-dynamic.platform':
83
return 'github.copilot-dynamic.platform';
84
}
85
throw new Error(`Unknown participant ${detected.participant} with command ${detected.command}`);
86
}
87
88
export function readBuiltinIntents(location: ChatLocation) {
89
const packageJson = JSON.parse(fs.readFileSync(path.resolve(path.join(__dirname, '..', 'package.json'))).toString(), undefined);
90
const participantMetadata: ChatParticipantMetadata[] = [];
91
for (const participant of packageJson['contributes']['chatParticipants']) {
92
const locationName = location === ChatLocation.Panel ? 'panel' : location === ChatLocation.Editor ? 'editor' : undefined;
93
if (!locationName || !participant.locations || !participant.locations.includes(locationName)) {
94
continue;
95
}
96
if (participant.disambiguation?.length) {
97
participantMetadata.push({
98
participant: participant.id, disambiguation: participant.disambiguation
99
});
100
}
101
if (participant.commands) {
102
for (const command of participant.commands) {
103
if (command.disambiguation?.length) {
104
participantMetadata.push({
105
participant: participant.id, command: command.name, disambiguation: command.disambiguation
106
});
107
}
108
}
109
}
110
}
111
return participantMetadata;
112
}
113
114