chatParserTypes.ts ×26

Frontier kind: Code frontier

unlabeled · c_3b8a2cc8c6ed

290 tests · 34578 LOC · 157 files · introduces 0 tests · 169 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
26 ranges169 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
3116 ranges34578 lines · 157 files · Browse complete extent
All tests (intent)
290 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.

1 file ranked by introduced lines: 169 introduced LOC across 26 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/requestParser/chatParserTypes.ts 169 introduced LOC · 26 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- chatParserTypes.ts
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 { revive } from '../../../../../base/common/marshalling.js';
7 > import { ThemeIcon } from '../../../../../base/common/themables.js';
8 > import { IOffsetRange, OffsetRange } from '../../../../../editor/common/core/ranges/offsetRange.js';
9 > import { IRange, Range } from '../../../../../editor/common/core/range.js';
10 > import { IChatAgentCommand, IChatAgentData, IChatAgentService, reviveSerializedAgent } from '../participants/chatAgents.js';
11 > import { IChatSlashData } from '../participants/chatSlashCommands.js';
12 > import { IChatRequestProblemsVariable, IChatRequestVariableValue } from '../attachments/chatVariables.js';
13 > import { ChatAgentLocation } from '../constants.js';
14 > import { IToolData } from '../tools/languageModelToolsService.js';
15 > import { IChatRequestToolEntry, IChatRequestToolSetEntry, IChatRequestVariableEntry, IDiagnosticVariableEntryFilterData } from '../attachments/chatVariableEntries.js';
16 > import { arrayEquals } from '../../../../../base/common/equals.js';
17 >
18 > // These are in a separate file to avoid circular dependencies with the dependencies of the parser
19 >
20 > export interface IParsedChatRequest {
21 > readonly parts: ReadonlyArray<IParsedChatRequestPart>;
22 > readonly text: string;
23 > }
24 >
25 > export namespace IParsedChatRequest {
26 > export function equals(a: IParsedChatRequest, b: IParsedChatRequest): boolean {
27 return a.text === b.text && arrayEquals(a.parts, b.parts, (p1, p2) =>
28 p1.kind === p2.kind &&
32 );
33 }
35 >
36 > export interface IParsedChatRequestPart {
37 > readonly kind: string; // for serialization
38 > readonly range: IOffsetRange;
39 > readonly editorRange: IRange;
40 > readonly text: string;
41 > /** How this part is represented in the prompt going to the agent */
42 > readonly promptText: string;
43 > }
44 >
45 > export function getPromptText(request: IParsedChatRequest): { message: string; diff: number } {
46 const message = request.parts.map(r => r.promptText).join('').trimStart();
47 const diff = request.text.length - message.length;
49 return { message, diff };
50 }
52 > export class ChatRequestTextPart implements IParsedChatRequestPart {
53 > static readonly Kind = 'text';
54 > readonly kind = ChatRequestTextPart.Kind;
55 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly text: string) { }
56 >
57 > get promptText(): string {
58 return this.text;
59 }
61 >
62 > // warning, these also show up in a regex in the parser
63 > export const chatVariableLeader = '#';
64 > export const chatAgentLeader = '@';
65 > export const chatSubcommandLeader = '/';
66 >
67 > /**
68 > * An invocation of a static variable that can be resolved by the variable service
69 > * @deprecated, but kept for backwards compatibility with old persisted chat requests
70 > */
71 > class ChatRequestVariablePart implements IParsedChatRequestPart {
72 > static readonly Kind = 'var';
73 > readonly kind = ChatRequestVariablePart.Kind;
74 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly variableName: string, readonly variableArg: string, readonly variableId: string) { }
75 >
76 > get text(): string {
77 const argPart = this.variableArg ? `:${this.variableArg}` : '';
78 return `${chatVariableLeader}${this.variableName}${argPart}`;
79 }
81 > get promptText(): string {
82 return this.text;
83 }
85 >
86 > /**
87 > * An invocation of a tool
88 > */
89 > export class ChatRequestToolPart implements IParsedChatRequestPart {
90 > static readonly Kind = 'tool';
91 > readonly kind = ChatRequestToolPart.Kind;
92 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly toolName: string, readonly toolId: string, readonly displayName?: string, readonly icon?: IToolData['icon']) { }
93 >
94 > get text(): string {
95 return `${chatVariableLeader}${this.toolName}`;
96 }
98 > get promptText(): string {
99 return this.text;
100 }
102 > toVariableEntry(): IChatRequestToolEntry {
103 return { kind: 'tool', id: this.toolId, name: this.toolName, range: this.range, value: undefined, icon: ThemeIcon.isThemeIcon(this.icon) ? this.icon : undefined, fullName: this.displayName };
104 }
106 >
107 > /**
108 > * An invocation of a tool
109 > */
110 > export class ChatRequestToolSetPart implements IParsedChatRequestPart {
111 > static readonly Kind = 'toolset';
112 > readonly kind = ChatRequestToolSetPart.Kind;
113 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly id: string, readonly name: string, readonly icon: ThemeIcon, readonly tools: IChatRequestToolEntry[]) { }
114 >
115 > get text(): string {
116 return `${chatVariableLeader}${this.name}`;
117 }
119 > get promptText(): string {
120 return this.text;
121 }
123 > toVariableEntry(): IChatRequestToolSetEntry {
124 return { kind: 'toolset', id: this.id, name: this.name, range: this.range, icon: this.icon, value: this.tools };
125 }
127 >
128 > /**
129 > * An invocation of an agent that can be resolved by the agent service
130 > */
131 > export class ChatRequestAgentPart implements IParsedChatRequestPart {
132 > static readonly Kind = 'agent';
133 > readonly kind = ChatRequestAgentPart.Kind;
134 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly agent: IChatAgentData) { }
135 >
136 > get text(): string {
137
138 return `${chatAgentLeader}${this.agent.name}`;
139 }
141 > get promptText(): string {
142 return '';
143 }
145 >
146 > /**
147 > * An invocation of an agent's subcommand
148 > */
149 > export class ChatRequestAgentSubcommandPart implements IParsedChatRequestPart {
150 > static readonly Kind = 'subcommand';
151 > readonly kind = ChatRequestAgentSubcommandPart.Kind;
152 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly command: IChatAgentCommand) { }
153 >
154 > get text(): string {
155 return `${chatSubcommandLeader}${this.command.name}`;
156 }
158 > get promptText(): string {
159 return '';
160 }
162 >
163 > /**
164 > * An invocation of a standalone slash command
165 > */
166 > export class ChatRequestSlashCommandPart implements IParsedChatRequestPart {
167 > static readonly Kind = 'slash';
168 > readonly kind = ChatRequestSlashCommandPart.Kind;
169 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly slashCommand: IChatSlashData) { }
170 >
171 > get text(): string {
172 return `${chatSubcommandLeader}${this.slashCommand.command}`;
173 }
175 > get promptText(): string {
176 return `${chatSubcommandLeader}${this.slashCommand.command}`;
177 }
179 >
180 > /**
181 > * An invocation of a standalone slash command
182 > */
183 > export class ChatRequestSlashPromptPart implements IParsedChatRequestPart {
184 > static readonly Kind = 'prompt';
185 > readonly kind = ChatRequestSlashPromptPart.Kind;
186 > readonly displayText?: string;
187 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly name: string, displayText?: string) {
188 // Only set the own property when provided so the canonical
189 // form (no `displayText` field) stays compatible with snapshots
193 }
194 }
196 > get text(): string {
197 return this.displayText ?? `${chatSubcommandLeader}${this.name}`;
198 }
200 > get promptText(): string {
201 return this.displayText ?? `${chatSubcommandLeader}${this.name}`;
202 }
204 >
205 > /**
206 > * An invocation of a dynamic reference like '#file:'
207 > */
208 > export class ChatRequestDynamicVariablePart implements IParsedChatRequestPart {
209 > static readonly Kind = 'dynamic';
210 > readonly kind = ChatRequestDynamicVariablePart.Kind;
211 > constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly text: string, readonly id: string, readonly modelDescription: string | undefined, readonly data: IChatRequestVariableValue, readonly fullName?: string, readonly icon?: ThemeIcon, readonly isFile?: boolean, readonly isDirectory?: boolean, readonly _meta?: Record<string, unknown>, readonly isAttachmentReference?: boolean) { }
212 >
213 > get referenceText(): string {
214 return this.text.replace(chatVariableLeader, '');
215 }
217 > get promptText(): string {
218 return this.text;
219 }
221 > toVariableEntry(): IChatRequestVariableEntry {
222 if (this.id === 'vscode.problems') {
223 return IDiagnosticVariableEntryFilterData.toEntry((this.data as IChatRequestProblemsVariable).filter);
226 return { kind: this.isDirectory ? 'directory' : this.isFile ? 'file' : 'generic', id: this.id, name: this.referenceText, range: this.range, value: this.data, fullName: this.fullName, icon: this.icon, _meta: this._meta };
227 }
229 >
230 > export function reviveParsedChatRequest(serialized: IParsedChatRequest): IParsedChatRequest {
231 return {
232 text: serialized.text,
313 };
314 }
316 > export function extractAgentAndCommand(parsed: IParsedChatRequest): { agentPart: ChatRequestAgentPart | undefined; commandPart: ChatRequestAgentSubcommandPart | undefined } {
317 const agentPart = parsed.parts.find((r): r is ChatRequestAgentPart => r instanceof ChatRequestAgentPart);
318 const commandPart = parsed.parts.find((r): r is ChatRequestAgentSubcommandPart => r instanceof ChatRequestAgentSubcommandPart);
319 return { agentPart, commandPart };
320 }
322 > export function formatChatQuestion(chatAgentService: IChatAgentService, location: ChatAgentLocation, prompt: string, participant: string | null = null, command: string | null = null): string | undefined {
323 let question = '';
324 if (participant && participant !== chatAgentService.getDefaultAgent(location)?.id) {