Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/prompts/node/agent/test/agentTasksInstructions.spec.tsx
13406 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 { BasePromptElementProps, PromptElement, UserMessage } from '@vscode/prompt-tsx';
7
import { expect, suite, test } from 'vitest';
8
import type * as vscode from 'vscode';
9
import { MockEndpoint } from '../../../../../platform/endpoint/test/node/mockEndpoint';
10
import { IIgnoreService, NullIgnoreService } from '../../../../../platform/ignore/common/ignoreService';
11
import { messageToMarkdown } from '../../../../../platform/log/common/messageStringify';
12
import { ITasksService } from '../../../../../platform/tasks/common/tasksService';
13
import { TestTasksService } from '../../../../../platform/tasks/common/testTasksService';
14
import { URI } from '../../../../../util/vs/base/common/uri';
15
import { SyncDescriptor } from '../../../../../util/vs/platform/instantiation/common/descriptors';
16
import { IInstantiationService } from '../../../../../util/vs/platform/instantiation/common/instantiation';
17
import { createExtensionUnitTestingServices } from '../../../../test/node/services';
18
import { ToolName } from '../../../../tools/common/toolNames';
19
import { renderPromptElement } from '../../base/promptRenderer';
20
import { AgentTasksInstructions } from '../agentPrompt';
21
22
interface TaskPromptProps extends BasePromptElementProps {
23
readonly availableTools: readonly vscode.LanguageModelToolInformation[];
24
}
25
26
class TaskPrompt extends PromptElement<TaskPromptProps> {
27
render() {
28
return (
29
<UserMessage>
30
<AgentTasksInstructions availableTools={this.props.availableTools} />
31
</UserMessage>
32
);
33
}
34
}
35
36
class StaticTasksService extends TestTasksService {
37
constructor(private readonly taskGroups: [URI, vscode.TaskDefinition[]][]) {
38
super();
39
}
40
41
override getTasks(...args: any[]): [] {
42
const workspaceFolder = args[0] as URI | undefined;
43
44
if (workspaceFolder) {
45
const tasksForFolder = this.taskGroups.find(([folder]) => folder.toString() === workspaceFolder.toString())?.[1] ?? [];
46
return tasksForFolder as unknown as [];
47
}
48
49
return this.taskGroups as unknown as [];
50
}
51
}
52
53
class TestIgnoreService extends NullIgnoreService {
54
constructor(private readonly ignoredResources: Set<string>) {
55
super();
56
}
57
58
override async isCopilotIgnored(file: URI): Promise<boolean> {
59
return this.ignoredResources.has(file.toString());
60
}
61
}
62
63
suite('AgentTasksInstructions', () => {
64
const workspaceFolder = URI.file('/workspace');
65
const tasksFile = URI.joinPath(workspaceFolder, '.vscode', 'tasks.json');
66
const taskDefinition: vscode.TaskDefinition = {
67
type: 'shell',
68
label: 'Build',
69
command: 'npm',
70
args: ['run', 'build']
71
};
72
73
const renderTaskPrompt = async (shouldIgnoreTasksFile: boolean) => {
74
const services = createExtensionUnitTestingServices();
75
services.define(ITasksService, new SyncDescriptor(StaticTasksService, [[[workspaceFolder, [taskDefinition]]]]));
76
services.define(IIgnoreService, new SyncDescriptor(TestIgnoreService, [new Set(shouldIgnoreTasksFile ? [tasksFile.toString()] : [])]));
77
const accessor = services.createTestingAccessor();
78
const instantiationService = accessor.get(IInstantiationService);
79
const endpoint = instantiationService.createInstance(MockEndpoint, undefined);
80
const taskTool: vscode.LanguageModelToolInformation = {
81
name: ToolName.CoreRunTask,
82
description: 'Run a workspace task',
83
source: undefined,
84
inputSchema: { type: 'object', properties: {} },
85
tags: []
86
};
87
88
const { messages } = await renderPromptElement(instantiationService, endpoint, TaskPrompt, {
89
priority: 1,
90
availableTools: [taskTool]
91
});
92
const output = messages.map(m => messageToMarkdown(m)).join('\n\n');
93
accessor.dispose();
94
return { messages, output };
95
};
96
97
test('renders task metadata when not ignored', async () => {
98
const { output } = await renderTaskPrompt(false);
99
expect(output).toContain('Build');
100
expect(output).toContain('"command": "npm"');
101
});
102
103
test('skips task metadata when tasks.json is ignored', async () => {
104
const { output } = await renderTaskPrompt(true);
105
expect(output).not.toContain('Build');
106
expect(output).not.toContain('"command": "npm"');
107
});
108
});
109
110