Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/test/simulation/panelCodeMapperSimulator.ts
13388 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
import type { ChatPromptReference, ChatResponseStream } from 'vscode';
6
import { isCodeBlockWithResource } from '../../src/extension/codeBlocks/node/codeBlockProcessor';
7
import { ITabsAndEditorsService } from '../../src/platform/tabs/common/tabsAndEditorsService';
8
import { TestingServiceCollection } from '../../src/platform/test/node/services';
9
import { isLocation } from '../../src/util/common/types';
10
import { URI } from '../../src/util/vs/base/common/uri';
11
import { ServicesAccessor } from '../../src/util/vs/platform/instantiation/common/instantiation';
12
import { ChatLocation, Location, Uri } from '../../src/vscodeTypes';
13
import { EditingSimulationHost, EditingSimulationHostResponseProcessor, simulateEditingScenario } from './inlineChatSimulator';
14
import { EditTestStrategy, IScenario, IScenarioQuery, OutcomeAnnotation } from './types';
15
16
export type EditTestStrategyPanel = EditTestStrategy.Agent | EditTestStrategy.Edits;
17
18
export async function simulatePanelCodeMapper(
19
testingServiceCollection: TestingServiceCollection,
20
scenario: IScenario,
21
strategy?: EditTestStrategyPanel,
22
spyOnStream?: (stream: ChatResponseStream) => ChatResponseStream
23
): Promise<void> {
24
const overrideCommand = strategy === undefined ? undefined :
25
strategy === EditTestStrategy.Edits ? '/edit' :
26
'/editAgent';
27
const ensureSlashEdit = (query: string) => {
28
if (!overrideCommand) {
29
return query;
30
}
31
32
return query.startsWith(overrideCommand) ? query : `${overrideCommand} ${query}`;
33
};
34
const prependEditToUserQueries = (queries: IScenarioQuery[]) => {
35
return queries.map(scenarioQuery => {
36
return {
37
...scenarioQuery,
38
query: ensureSlashEdit(scenarioQuery.query),
39
};
40
});
41
};
42
const massagedScenario = { ...scenario, queries: prependEditToUserQueries(scenario.queries) };
43
44
45
const host: EditingSimulationHost = {
46
prepareChatRequestLocation: (accessor: ServicesAccessor) => {
47
return {
48
location: ChatLocation.Panel,
49
location2: undefined,
50
};
51
},
52
53
contributeAdditionalReferences: (accessor: ServicesAccessor, existingReferences: readonly ChatPromptReference[]) => {
54
const tabsAndEditorsService = accessor.get(ITabsAndEditorsService);
55
const activeTextEditor = tabsAndEditorsService.activeTextEditor;
56
if (activeTextEditor) {
57
const existingReference = existingReferences.find(ref => _extractUri(ref.value)?.toString() === activeTextEditor.document.uri.toString());
58
if (!existingReference) {
59
const varWithArg = `file:${activeTextEditor.document.uri.path}`;
60
return [{
61
id: `copilot.file`,
62
name: varWithArg,
63
value: new Location(
64
activeTextEditor.document.uri,
65
activeTextEditor.selection,
66
)
67
}];
68
}
69
}
70
return [];
71
72
function _extractUri(something: Uri | Location | unknown | undefined): Uri | undefined {
73
if (isLocation(something)) {
74
return something.uri;
75
}
76
if (URI.isUri(something)) {
77
return something;
78
}
79
return undefined;
80
}
81
},
82
83
provideResponseProcessor: (_query: IScenarioQuery): EditingSimulationHostResponseProcessor => {
84
return {
85
spyOnStream: (stream: ChatResponseStream): ChatResponseStream => {
86
return spyOnStream ? spyOnStream(stream) : stream;
87
},
88
postProcess: async (accessor, workspace, stream, chatResult): Promise<OutcomeAnnotation[]> => {
89
const annotations: OutcomeAnnotation[] = [];
90
if (strategy === EditTestStrategy.Edits) {
91
if (chatResult?.errorDetails) {
92
annotations.push({
93
severity: 'error',
94
label: 'chat-error',
95
message: `Chat request failed: ${chatResult.errorDetails.message}`,
96
});
97
return annotations;
98
}
99
100
const codeBlocks = chatResult?.metadata?.codeBlocks;
101
if (!Array.isArray(codeBlocks)) {
102
throw new Error('No codeblocks in chat result metadata');
103
}
104
for (const codeBlock of codeBlocks) {
105
if (!isCodeBlockWithResource(codeBlock)) {
106
annotations.push({
107
severity: 'error',
108
label: 'missing-path-in-code-block',
109
message: 'Code block without a file path',
110
});
111
}
112
}
113
}
114
return annotations;
115
}
116
};
117
}
118
};
119
120
return simulateEditingScenario(
121
testingServiceCollection,
122
massagedScenario,
123
host
124
);
125
}
126
127