computeAutomaticInstructions.ts ×20

Frontier kind: Code frontier

unlabeled · c_2165a6a18175

51 tests · 67825 LOC · 326 files · introduces 0 tests · 108 LOC · 4 files

Introduces — evidence that enters the hierarchy at this concept

Code
31 ranges108 lines · 4 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
6562 ranges67825 lines · 326 files · Browse complete extent
All tests (intent)
51 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

4 files ranked by introduced lines: 108 introduced LOC across 31 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/promptSyntax/computeAutomaticInstructions.ts 80 introduced LOC · 20 ranges

Open complete file

96
97 public async collect(variables: ChatRequestVariableSet, token: CancellationToken): Promise<void> {
99 > const startTime = performance.now();
100 > const instructionFiles = await this._promptsService.getInstructionFiles(token);
101 >
102 > this._logService.trace(`[InstructionsContextComputer] ${instructionFiles.length} instruction files available.`);
103 >
104 > const telemetryEvent: InstructionsCollectionEvent = newInstructionsCollectionEvent();
105 > const debugInfo: InstructionsCollectionDebugInfo = newInstructionsCollectionDebugInfo();
106 > const context = this._getContext(variables);
107 >
108 > // find instructions where the `applyTo` matches the attached context
109 > await this.addApplyingInstructions(instructionFiles, context, variables, telemetryEvent, debugInfo, token);
110 >
111 > // add all instructions referenced by all instruction files that are in the context
112 > await this._addReferencedInstructions(variables, telemetryEvent, debugInfo, token);
113 >
114 > // get copilot instructions
115 > await this._addAgentInstructions(variables, telemetryEvent, debugInfo, token);
116 >
117 > const customizationsIndexVariable = await this._getCustomizationsIndex(instructionFiles, variables, telemetryEvent, debugInfo, token);
118 > if (customizationsIndexVariable) {
119 variables.add(customizationsIndexVariable);
120 telemetryEvent.listedInstructionsCount++;
121 }
123 > debugInfo.durationInMillis = performance.now() - startTime;
124 > this.sendTelemetry(telemetryEvent);
125 > lastInstructionsCollectionResult = { telemetryEvent, debugInfo };
126 > }
127
128 private sendTelemetry(telemetryEvent: InstructionsCollectionEvent): void {
129 > // Emit telemetry computeAutomaticInstructions.ts
130 > telemetryEvent.totalInstructionsCount = telemetryEvent.agentInstructionsCount + telemetryEvent.referencedInstructionsCount + telemetryEvent.applyingInstructionsCount + telemetryEvent.listedInstructionsCount;
131 > this._telemetryService.publicLog2<InstructionsCollectionEvent, InstructionsCollectionClassification>('instructionsCollected', telemetryEvent);
132 > }
133
134 private async _logSkillLoadedTelemetry(skills: readonly IAgentSkill[]): Promise<void> {
239
240 private _getContext(attachedContext: ChatRequestVariableSet): { files: ResourceSet; instructions: ResourceSet } {
241 > const files = new ResourceSet(); computeAutomaticInstructions.ts
242 > const instructions = new ResourceSet();
243 > for (const variable of attachedContext.asArray()) {
244 if (isPromptFileVariableEntry(variable)) {
245 instructions.add(variable.value);
251 }
252 }
254 > return { files, instructions };
255 > }
256
257 private async _addAgentInstructions(variables: ChatRequestVariableSet, telemetryEvent: InstructionsCollectionEvent, debugInfo: InstructionsCollectionDebugInfo, token: CancellationToken): Promise<void> {
258 > const logger = { computeAutomaticInstructions.ts
259 > logInfo: (message: string) => this._logService.trace(`[InstructionsContextComputer] ${message}`)
260 > };
261 > const allCandidates = await this._promptsService.listAgentInstructions(token, logger);
262 >
263 > const entries: ChatRequestVariableSet = new ChatRequestVariableSet();
264 > const copilotEntries: ChatRequestVariableSet = new ChatRequestVariableSet();
265 >
266 > for (const { uri, type } of allCandidates) {
267 const varEntry = toPromptFileVariableEntry(uri, PromptFileVariableKind.Instruction, undefined, true);
268 entries.add(varEntry);
278 logger.logInfo(`Agent instruction file added: ${uri.toString()}`);
279 }
281 > // Process referenced instructions from copilot files (maintaining original behavior)
282 > if (copilotEntries.length > 0) {
283 await this._addReferencedInstructions(copilotEntries, telemetryEvent, debugInfo, token);
284 for (const entry of copilotEntries.asArray()) {
330
331 private _getTool(referenceName: string): { tool: IToolData; variable: string } | undefined {
332 > if (!this._enabledTools) { computeAutomaticInstructions.ts
333 return undefined;
334 }
335 const tool = this._languageModelToolsService.getToolByName(referenceName);
336 > if (tool && this._enabledTools[tool.id]) { computeAutomaticInstructions.ts
337 return { tool, variable: `#tool:${this._languageModelToolsService.getFullReferenceName(tool)}` };
338 }
339 return undefined;
341
342 private async _getCustomizationsIndex(instructionFiles: readonly IInstructionFile[], _existingVariables: ChatRequestVariableSet, telemetryEvent: InstructionsCollectionEvent, debugInfo: InstructionsCollectionDebugInfo, token: CancellationToken): Promise<IPromptTextVariableEntry | undefined> {
343 > const readTool = this._getTool('readFile'); computeAutomaticInstructions.ts
344 > const runInTerminalTool = this._getTool('runInTerminal');
345 > const fileReadTool = readTool ?? runInTerminalTool;
346 > const runSubagentTool = this._getTool(VSCodeToolReference.runSubagent);
347 > const skillTool = this._getTool('skill');
348 > const currentSessionType = this._currentSessionType;
349 >
350 > const remoteEnv = await this._remoteAgentService.getEnvironment();
351 > const remoteOS = remoteEnv?.os;
352 > const isRemote = this._remoteAgentService.getConnection() !== null;
353 > const filePath = (uri: URI) => getFilePath(uri, remoteOS, isRemote);
354 >
355 > const entries: string[] = [];
356 > if (fileReadTool) {
357
358 const searchNestedAgentMd = this._configurationService.getValue(PromptsConfig.USE_NESTED_AGENT_MD);
509 }
510 }
511 > if (runSubagentTool) { computeAutomaticInstructions.ts
512 const canUseAgent = (() => {
513 if (!this._enabledSubagents || this._enabledSubagents.includes('*')) {
567 collectToolReference(skillTool);
568 return toPromptTextVariableEntry(content, true, toolReferences);
570
571 private async _addReferencedInstructions(attachedContext: ChatRequestVariableSet, telemetryEvent: InstructionsCollectionEvent, debugInfo: InstructionsCollectionDebugInfo, token: CancellationToken): Promise<void> {
572 > const includeReferencedInstructions = this._configurationService.getValue(PromptsConfig.INCLUDE_REFERENCED_INSTRUCTIONS); computeAutomaticInstructions.ts
573 > if (!includeReferencedInstructions && this._modeKind !== ChatModeKind.Edit) {
574 this._logService.trace(`[InstructionsContextComputer] includeReferencedInstructions is disabled and agent kind is not Edit. No referenced instructions will be added.`);
575 return;
576 }
578 > const seen = new ResourceSet();
579 > const todo: URI[] = [];
580 > for (const variable of attachedContext.asArray()) {
581 if (isPromptFileVariableEntry(variable)) {
582 if (!seen.has(variable.value)) {
586 }
587 }
588 > let next = todo.pop(); computeAutomaticInstructions.ts
589 > while (next) {
590 const result = await this._parseInstructionsFile(next, token);
591 if (result && result.body) {
src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts 22 introduced LOC · 8 ranges

Open complete file

759
760 public async listAgentInstructions(token: CancellationToken, logger: Logger | undefined): Promise<IAgentInstructionFile[]> {
761 > const resolvedAgentFiles: IAgentInstructionFile[] = []; promptsServiceImpl.ts
762 > const promises: Promise<IAgentInstructionFile[]>[] = [];
763 >
764 > const includeParents = this.configurationService.getValue(PromptsConfig.USE_CUSTOMIZATIONS_IN_PARENT_REPOS) === true;
765 > const rootFolders = await this.fileLocator.getWorkspaceFolderRoots(includeParents, logger);
766 >
767 > const rootFiles: IWorkspaceInstructionFile[] = [];
768 > const useAgentMD = this.configurationService.getValue(PromptsConfig.USE_AGENT_MD);
769 > if (!useAgentMD) {
770 logger?.logInfo('Agent MD files are disabled via configuration.');
771 > } else { promptsServiceImpl.ts
772 rootFiles.push({ fileName: AGENT_MD_FILENAME, type: AgentInstructionFileType.agentsMd });
773 }
774 > const useClaudeMD = this.configurationService.getValue(PromptsConfig.USE_CLAUDE_MD); promptsServiceImpl.ts
775 > if (!useClaudeMD) {
776 logger?.logInfo('Claude MD files are disabled via configuration.');
777 > } else { promptsServiceImpl.ts
778 const claudeMdFile = { fileName: CLAUDE_MD_FILENAME, type: AgentInstructionFileType.claudeMd };
779 rootFiles.push(claudeMdFile); // CLAUDE.md in workspace root
783 promises.push(this.fileLocator.findFilesInRoots([await this.pathService.userHome()], CLAUDE_CONFIG_FOLDER, [claudeMdFile], token, resolvedAgentFiles)); // CLAUDE.md in in ~/.claude folder
784 }
785 > const useCopilotInstructionsFiles = this.configurationService.getValue(PromptsConfig.USE_COPILOT_INSTRUCTION_FILES); promptsServiceImpl.ts
786 > if (!useCopilotInstructionsFiles) {
787 logger?.logInfo('Copilot instructions files are disabled via configuration.');
788 > } else { promptsServiceImpl.ts
789 const copilotInstructionsFile = { fileName: COPILOT_CUSTOM_INSTRUCTIONS_FILENAME, type: AgentInstructionFileType.copilotInstructionsMd };
790 promises.push(this.fileLocator.findFilesInRoots(rootFolders, GITHUB_CONFIG_FOLDER, [copilotInstructionsFile], token, resolvedAgentFiles)); // copilot-instructions.md in .github folder under workspace root
791 promises.push(this.fileLocator.findFilesInRoots([await this.pathService.userHome()], COPILOT_CONFIG_FOLDER, [copilotInstructionsFile], token, resolvedAgentFiles)); // copilot-instructions.md in ~/.copilot folder
792 }
794 > promises.push(this.fileLocator.findFilesInRoots(rootFolders, undefined, rootFiles, token, resolvedAgentFiles));
795 >
796 > await Promise.all(promises);
797 > if (token.isCancellationRequested) {
798 return [];
799 }
821 }
822 return result.sort((a, b) => a.uri.toString().localeCompare(b.uri.toString()));
824
825 public getAgentFileURIFromModeFile(oldURI: URI): URI | undefined {
src/vs/workbench/contrib/chat/common/promptSyntax/utils/promptFilesLocator.ts 4 introduced LOC · 2 ranges

Open complete file

788
789 public async findFilesInRoots(roots: URI[], folder: string | undefined, paths: IWorkspaceInstructionFile[], token: CancellationToken, result: IAgentInstructionFile[] = []): Promise<IAgentInstructionFile[]> {
790 > const toResolve = roots.map(root => ({ resource: folder !== undefined ? joinPath(root, folder) : root })); promptFilesLocator.ts
791 > const resolvedRoots = await this.fileService.resolveAll(toResolve);
792 > if (token.isCancellationRequested) {
793 return result;
794 }
807 }
808 return result;
810
811 public getAgentFileURIFromModeFile(oldURI: URI): URI | undefined {
src/vs/workbench/contrib/chat/common/attachments/chatVariableEntries.ts 2 introduced LOC · 1 range

Open complete file

856
857 public get length(): number {
858 > return this._entries.length; chatVariableEntries.ts
859 > }
860 }