languageModelToolsService.ts ×35

Frontier kind: Code frontier

unlabeled · c_acd66261cc25

630 tests · 10969 LOC · 75 files · introduces 0 tests · 658 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
37 ranges658 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1279 ranges10969 lines · 75 files · Browse complete extent
All tests (intent)
630 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.

2 files ranked by introduced lines: 658 introduced LOC across 37 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/tools/languageModelToolsService.ts 603 introduced LOC · 35 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- languageModelToolsService.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 { Separator } from '../../../../../base/common/actions.js';
7 > import { VSBuffer } from '../../../../../base/common/buffer.js';
8 > import { CancellationToken } from '../../../../../base/common/cancellation.js';
9 > import { Event } from '../../../../../base/common/event.js';
10 > import { IMarkdownString } from '../../../../../base/common/htmlContent.js';
11 > import { Iterable } from '../../../../../base/common/iterator.js';
12 > import { IJSONSchema } from '../../../../../base/common/jsonSchema.js';
13 > import { Disposable, IDisposable, toDisposable } from '../../../../../base/common/lifecycle.js';
14 > import { Schemas } from '../../../../../base/common/network.js';
15 > import { derived, IObservable, IReader, ITransaction, ObservableSet } from '../../../../../base/common/observable.js';
16 > import { ThemeIcon } from '../../../../../base/common/themables.js';
17 > import { URI } from '../../../../../base/common/uri.js';
18 > import { Location } from '../../../../../editor/common/languages.js';
19 > import { localize } from '../../../../../nls.js';
20 > import { ConfirmationOption } from '../../../../../platform/agentHost/common/state/protocol/state.js';
21 > import { ContextKeyExpression, IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js';
22 > import { ExtensionIdentifier } from '../../../../../platform/extensions/common/extensions.js';
23 > import { ByteSize } from '../../../../../platform/files/common/files.js';
24 > import { createDecorator } from '../../../../../platform/instantiation/common/instantiation.js';
25 > import { IProgress } from '../../../../../platform/progress/common/progress.js';
26 > import { ChatRequestToolReferenceEntry } from '../attachments/chatVariableEntries.js';
27 > import { IVariableReference } from '../chatModes.js';
28 > import { ConfirmedReason, IChatAgentFeedbackReviewConfirmationData, IChatAutomationConfigurationData, IChatAutomationConfiguredData, IChatExtensionsContent, IChatModifiedFilesConfirmationData, IChatSearchToolInvocationData, IChatSessionCreatedData, IChatSimpleToolInvocationData, IChatSubagentToolInvocationData, IChatTodoListContent, IChatToolInputInvocationData, IChatToolInvocation, type IChatTerminalToolInvocationData } from '../chatService/chatService.js';
29 > import { ILanguageModelChatMetadata, LanguageModelPartAudience } from '../languageModels.js';
30 > import { UserSelectedTools } from '../participants/chatAgents.js';
31 > import { PromptElementJSON, stringifyPromptElementJSON } from './promptTsxTypes.js';
32 >
33 > /**
34 > * Selector for matching language models by vendor, family, version, or id.
35 > * Used to filter tools to specific models or model families.
36 > */
37 > export interface ILanguageModelChatSelector {
38 > readonly vendor?: string;
39 > readonly family?: string;
40 > readonly version?: string;
41 > readonly id?: string;
42 > }
43 >
44 > export interface IToolData {
45 > readonly id: string;
46 > readonly source: ToolDataSource;
47 > readonly toolReferenceName?: string;
48 > readonly legacyToolReferenceFullNames?: readonly string[];
49 > readonly icon?: { dark: URI; light?: URI } | ThemeIcon;
50 > readonly when?: ContextKeyExpression;
51 > readonly tags?: readonly string[];
52 > readonly displayName: string;
53 > readonly userDescription?: string;
54 > readonly modelDescription: string;
55 > readonly inputSchema?: IJSONSchema;
56 > readonly canBeReferencedInPrompt?: boolean;
57 > /**
58 > * True if the tool runs in the (possibly remote) workspace, false if it runs
59 > * on the host, undefined if known.
60 > */
61 > readonly runsInWorkspace?: boolean;
62 > readonly alwaysDisplayInputOutput?: boolean;
63 > /** True if this tool might ask for pre-approval */
64 > readonly canRequestPreApproval?: boolean;
65 > /** True if this tool might ask for post-approval */
66 > readonly canRequestPostApproval?: boolean;
67 > /**
68 > * Model selectors that this tool is available for.
69 > * If defined, the tool is only available when the selected model matches one of the selectors.
70 > */
71 > readonly models?: readonly ILanguageModelChatSelector[];
72 > }
73 >
74 > /**
75 > * Check if a tool matches the given model metadata based on the tool's `models` selectors.
76 > * If the tool has no `models` defined, it matches all models.
77 > * If model is undefined, model-specific filtering is skipped (tool is included).
78 > */
79 > export function toolMatchesModel(toolData: IToolData, model: ILanguageModelChatMetadata | undefined): boolean {
80 // If no model selectors are defined, the tool is available for all models
81 if (!toolData.models || toolData.models.length === 0) {
94 );
95 }
97 > export interface IToolProgressStep {
98 > readonly message: string | IMarkdownString | undefined;
99 > /** 0-1 progress of the tool call */
100 > readonly progress?: number;
101 > }
102 >
103 > export type ToolProgress = IProgress<IToolProgressStep>;
104 >
105 > export type ToolDataSource =
106 > | {
107 > type: 'extension';
108 > label: string;
109 > extensionId: ExtensionIdentifier;
110 > }
111 > | {
112 > type: 'mcp';
113 > label: string;
114 > serverLabel: string | undefined;
115 > instructions: string | undefined;
116 > collectionId: string;
117 > definitionId: string;
118 > }
119 > | {
120 > type: 'user';
121 > label: string;
122 > file: URI;
123 > }
124 > | {
125 > type: 'internal';
126 > label: string;
127 > } | {
128 > type: 'external';
129 > label: string;
130 > };
131 >
132 > export namespace ToolDataSource {
133 >
134 > export const Internal: ToolDataSource = { type: 'internal', label: 'Built-In' };
135 >
136 > /** External tools may not be contributed or invoked, but may be invoked externally and described in an IChatToolInvocationSerialized */
137 > export const External: ToolDataSource = { type: 'external', label: 'External' };
138 >
139 > export function toKey(source: ToolDataSource): string {
140 switch (source.type) {
141 case 'extension': return `extension:${source.extensionId.value}`;
146 }
147 }
149 > export function equals(a: ToolDataSource, b: ToolDataSource): boolean {
150 return toKey(a) === toKey(b);
151 }
153 > export function classify(source: ToolDataSource): { readonly ordinal: number; readonly label: string } {
154 if (source.type === 'internal') {
155 return { ordinal: 1, label: localize('builtin', 'Built-In') };
162 }
163 }
165 >
166 > /**
167 > * Pre-tool-use hook result passed from the extension when the hook was executed externally.
168 > */
169 > export interface IExternalPreToolUseHookResult {
170 > permissionDecision?: 'allow' | 'deny' | 'ask';
171 > permissionDecisionReason?: string;
172 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
173 > updatedInput?: Record<string, any>;
174 > }
175 >
176 > export interface IToolInvocation {
177 > callId: string;
178 > toolId: string;
179 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
180 > parameters: Record<string, any>;
181 > tokenBudget?: number;
182 > context: IToolInvocationContext | undefined;
183 > chatRequestId?: string;
184 > chatInteractionId?: string;
185 > /**
186 > * Optional tool call ID from the chat stream, used to correlate with pending streaming tool calls.
187 > */
188 > chatStreamToolCallId?: string;
189 > /**
190 > * Lets us add some nicer UI to toolcalls that came from a sub-agent, but in the long run, this should probably just be rendered in a similar way to thinking text + tool call groups
191 > */
192 > subAgentInvocationId?: string;
193 > toolSpecificData?: IChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatTodoListContent | IChatSubagentToolInvocationData | IChatSimpleToolInvocationData | IChatSearchToolInvocationData | IChatModifiedFilesConfirmationData | IChatAgentFeedbackReviewConfirmationData | IChatSessionCreatedData | IChatAutomationConfigurationData | IChatAutomationConfiguredData;
194 > modelId?: string;
195 > userSelectedTools?: UserSelectedTools;
196 > /** The label of the custom button selected by the user during confirmation, if custom buttons were used. */
197 > selectedCustomButton?: string;
198 > /** Pre-tool-use hook result passed from the extension, if the hook was already executed externally. */
199 > preToolUseResult?: IExternalPreToolUseHookResult;
200 > /**
201 > * A confirmation reason resolved out-of-band by the caller (e.g. the agent
202 > * host, which decides auto-approval server-side). When set, the invocation
203 > * is treated as already auto-approved and transitions straight to executing
204 > * without ever entering the `WaitingForConfirmation` state. This avoids a
205 > * transient "needs input" flicker in surfaces (like the sessions list) that
206 > * observe pending confirmations, for tool calls that will be auto-approved
207 > * anyway.
208 > */
209 > preApproved?: ConfirmedReason;
210 > /**
211 > * Optional W3C trace context `traceparent` value identifying the parent distributed
212 > * tracing span for this tool invocation. Forwarded to MCP tool implementations as
213 > * `_meta.traceparent` (MCP SEP-414).
214 > */
215 > traceparent?: string;
216 > /** Optional W3C trace context `tracestate` value paired with {@link traceparent}. */
217 > tracestate?: string;
218 > }
219 >
220 > export interface IToolInvocationContext {
221 > readonly sessionResource: URI;
222 > /**
223 > * The working directory URI associated with this session.
224 > * Only set in the agents window context where each session can
225 > * have its own working directory that differs from the workspace folders.
226 > */
227 > readonly workingDirectory?: URI;
228 > }
229 >
230 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
231 > export function isToolInvocationContext(obj: any): obj is IToolInvocationContext {
232 return obj !== null && typeof obj === 'object' && URI.isUri(obj.sessionResource);
233 }
235 > export interface IToolInvocationPreparationContext {
236 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
237 > parameters: any;
238 > toolCallId: string;
239 > chatRequestId?: string;
240 > chatSessionResource: URI | undefined;
241 > chatInteractionId?: string;
242 > modelId?: string;
243 > /** If set, tells the tool that it should include confirmation messages. */
244 > forceConfirmationReason?: string;
245 > /**
246 > * The working directory URI for the session, if set.
247 > * Used by tools to resolve relative paths and check file access.
248 > */
249 > workingDirectory?: URI;
250 > }
251 >
252 > export type ToolInputOutputBase = {
253 > /** Mimetype of the value, optional */
254 > mimeType?: string;
255 > /** URI of the resource on the MCP server. */
256 > uri?: URI;
257 > /** If true, this part came in as a resource reference rather than direct data. */
258 > asResource?: boolean;
259 > /** Audience of the data part */
260 > audience?: LanguageModelPartAudience[];
261 > };
262 >
263 > export type ToolInputOutputEmbedded = ToolInputOutputBase & {
264 > type: 'embed';
265 > value: string;
266 > /** If true, value is text. If false or not given, value is base64 */
267 > isText?: boolean;
268 > };
269 >
270 > export type ToolInputOutputReference = ToolInputOutputBase & { type: 'ref'; uri: URI };
271 >
272 > export interface IToolResultInputOutputDetails {
273 > readonly input: string;
274 > /** Language identifier for syntax highlighting the input. Defaults to 'json'. */
275 > readonly inputLanguage?: string;
276 > readonly output: (ToolInputOutputEmbedded | ToolInputOutputReference)[];
277 > readonly isError?: boolean;
278 > /** Raw MCP tool result for MCP App UI rendering */
279 > readonly mcpOutput?: unknown;
280 > }
281 >
282 > export interface IToolResultOutputDetails {
283 > readonly output: { type: 'data'; mimeType: string; value: VSBuffer };
284 > }
285 >
286 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
287 > export function isToolResultInputOutputDetails(obj: any): obj is IToolResultInputOutputDetails {
288 return typeof obj === 'object' && typeof obj?.input === 'string' && (typeof obj?.output === 'string' || Array.isArray(obj?.output));
289 }
291 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
292 > export function isToolResultOutputDetails(obj: any): obj is IToolResultOutputDetails {
293 return typeof obj === 'object' && typeof obj?.output === 'object' && typeof obj?.output?.mimeType === 'string' && obj?.output?.type === 'data';
294 }
296 > export interface IToolResult {
297 > content: (IToolResultPromptTsxPart | IToolResultTextPart | IToolResultDataPart)[];
298 > toolSpecificData?: IChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatTodoListContent | IChatSubagentToolInvocationData | IChatSimpleToolInvocationData | IChatSearchToolInvocationData | IChatModifiedFilesConfirmationData | IChatAgentFeedbackReviewConfirmationData | IChatSessionCreatedData | IChatAutomationConfiguredData;
299 > toolResultMessage?: string | IMarkdownString;
300 > toolResultDetails?: Array<URI | Location> | IToolResultInputOutputDetails | IToolResultOutputDetails;
301 > toolResultError?: string | boolean;
302 > toolMetadata?: unknown;
303 > /** Whether to ask the user to confirm these tool results. Overrides {@link IToolConfirmationMessages.confirmResults}. */
304 > confirmResults?: boolean;
305 > }
306 >
307 > export function toolContentToA11yString(part: IToolResult['content']) {
308 return part.map(p => {
309 switch (p.kind) {
317 }).join(', ');
318 }
320 > export function toolResultHasBuffers(result: IToolResult): boolean {
321 return result.content.some(part => part.kind === 'data');
322 }
324 > export interface IToolResultPromptTsxPart {
325 > kind: 'promptTsx';
326 > value: unknown;
327 > }
328 >
329 > export function stringifyPromptTsxPart(part: IToolResultPromptTsxPart): string {
330 return stringifyPromptElementJSON(part.value as PromptElementJSON);
331 }
333 > export interface IToolResultTextPart {
334 > kind: 'text';
335 > value: string;
336 > audience?: LanguageModelPartAudience[];
337 > title?: string;
338 > }
339 >
340 > export interface IToolResultDataPart {
341 > kind: 'data';
342 > value: {
343 > mimeType: string;
344 > data: VSBuffer;
345 > };
346 > audience?: LanguageModelPartAudience[];
347 > title?: string;
348 > }
349 >
350 > export type IToolApprovalReason =
351 > | { readonly status: 'loading' }
352 > | {
353 > readonly status: 'complete';
354 > readonly explanation: string | IMarkdownString;
355 > readonly safety: number;
356 > };
357 >
358 > export interface IToolConfirmationMessages {
359 > /** Title for the confirmation. If set, the user will be asked to confirm execution of the tool */
360 > title?: string | IMarkdownString;
361 > /** MUST be set if `title` is also set */
362 > message?: string | IMarkdownString;
363 > disclaimer?: string | IMarkdownString;
364 > /** Model-provided assessment of whether automatic approval is safe. */
365 > approvalReason?: IToolApprovalReason;
366 > /** Whether this confirmation is eligible for automatic approval. */
367 > allowAutoConfirm?: boolean;
368 > terminalCustomActions?: ToolConfirmationAction[];
369 > /** If true, confirmation will be requested after the tool executes and before results are sent to the model */
370 > confirmResults?: boolean;
371 > /** If title is not set (no confirmation needed), this reason will be shown to explain why confirmation was not needed */
372 > confirmationNotNeededReason?: string | IMarkdownString;
373 > /** Custom options to display instead of the default Allow/Skip buttons. */
374 > customOptions?: ConfirmationOption[];
375 > /** When set, shows an additional approval option to approve this particular combination of tool and arguments */
376 > approveCombination?: {
377 > /** Human-readable label for the approval option */
378 > label: string | IMarkdownString;
379 > /** Precomputed SHA-256 key for the combination (set during tool preparation) */
380 > key: string;
381 > /** String representation of the arguments for this combination */
382 > arguments?: string;
383 > };
384 > }
385 >
386 > export interface IToolConfirmationAction {
387 > label: string;
388 > disabled?: boolean;
389 > tooltip?: string;
390 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
391 > data: any;
392 > }
393 >
394 > export type ToolConfirmationAction = IToolConfirmationAction | Separator;
395 >
396 > export enum ToolInvocationPresentation {
397 > Hidden = 'hidden',
398 > HiddenAfterComplete = 'hiddenAfterComplete'
399 > }
400 >
401 > export interface IToolInvocationStreamContext {
402 > toolCallId: string;
403 > rawInput: unknown;
404 > chatRequestId?: string;
405 > chatSessionResource?: URI;
406 > chatInteractionId?: string;
407 > }
408 >
409 > export interface IStreamedToolInvocation {
410 > invocationMessage?: string | IMarkdownString;
411 > }
412 >
413 > export interface IPreparedToolInvocation {
414 > invocationMessage?: string | IMarkdownString;
415 > pastTenseMessage?: string | IMarkdownString;
416 > originMessage?: string | IMarkdownString;
417 > confirmationMessages?: IToolConfirmationMessages;
418 > presentation?: ToolInvocationPresentation;
419 > icon?: ThemeIcon;
420 > toolSpecificData?: IChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatTodoListContent | IChatSubagentToolInvocationData | IChatSimpleToolInvocationData | IChatSearchToolInvocationData | IChatModifiedFilesConfirmationData | IChatAgentFeedbackReviewConfirmationData | IChatSessionCreatedData | IChatAutomationConfigurationData | IChatAutomationConfiguredData;
421 > }
422 >
423 > export interface IToolImpl {
424 > invoke(invocation: IToolInvocation, countTokens: CountTokensCallback, progress: ToolProgress, token: CancellationToken): Promise<IToolResult>;
425 > prepareToolInvocation?(context: IToolInvocationPreparationContext, token: CancellationToken): Promise<IPreparedToolInvocation | undefined>;
426 > handleToolStream?(context: IToolInvocationStreamContext, token: CancellationToken): Promise<IStreamedToolInvocation | undefined>;
427 > }
428 >
429 > export interface IToolSet {
430 > readonly id: string;
431 > readonly referenceName: string;
432 > readonly icon: ThemeIcon;
433 > readonly source: ToolDataSource;
434 > readonly description?: string;
435 > /** A longer, human-readable description of what the tool set is for, shown as a subtitle in the Chat Customizations "Tools" section. */
436 > readonly detail?: string;
437 > readonly legacyFullNames?: string[];
438 > /** When true, this tool set is deprecated: it is hidden from the Chat Customizations "Tools" section and these groupings will be removed when the Local harness is dropped. */
439 > readonly deprecated?: boolean;
440 > /** When true, this tool set is hidden from the chat tools picker (e.g. a customizations-only grouping). */
441 > readonly hiddenInToolsPicker?: boolean;
442 >
443 > getTools(r?: IReader): Iterable<IToolData>;
444 > }
445 >
446 >
447 >
448 > /**
449 > * Maps tools and tool sets to their enablement state. Use a class to control creation of the map and ensure
450 > * that it is not mutated after creation.
451 > */
452 > export class ToolAndToolSetEnablementMap implements Iterable<[IToolData | IToolSet, boolean]> {
453 >
454 > static fromEntries(entries: Iterable<[IToolData | IToolSet, boolean]>): ToolAndToolSetEnablementMap {
455 > return new ToolAndToolSetEnablementMap(new Map(entries));
456 > }
457 >
458 > static fromMap(map: Map<IToolData | IToolSet, boolean>): ToolAndToolSetEnablementMap {
459 return new ToolAndToolSetEnablementMap(new Map(map));
460 }
462 > private constructor(private readonly _map: Map<IToolData | IToolSet, boolean>) {
463 }
465 > [Symbol.iterator](): IterableIterator<[IToolData | IToolSet, boolean]> {
466 return this._map[Symbol.iterator]();
467 }
469 > public get(toolOrToolSet: IToolData | IToolSet): boolean | undefined {
470 return this._map.get(toolOrToolSet);
471 }
473 > public has(toolOrToolSet: IToolData | IToolSet): boolean {
474 return this._map.has(toolOrToolSet);
475 }
477 > public get size(): number {
478 return this._map.size;
479 }
481 > public entries(): IterableIterator<[IToolData | IToolSet, boolean]> {
482 return this._map.entries();
483 }
485 >
486 > export function isToolSet(obj: IToolData | IToolSet | undefined): obj is IToolSet {
487 return !!obj && (obj as IToolSet).getTools !== undefined;
488 }
490 > export class ToolSet implements IToolSet {
491 >
492 > protected readonly _tools = new ObservableSet<IToolData>();
493 >
494 > protected readonly _toolSets = new ObservableSet<IToolSet>();
495 >
496 > /**
497 > * A homogenous tool set only contains tools from the same source as the tool set itself
498 > */
499 > readonly isHomogenous: IObservable<boolean>;
500 >
501 > constructor(
502 readonly id: string,
503 readonly referenceName: string,
517 });
518 }
520 > addTool(data: IToolData, tx?: ITransaction): IDisposable {
521 this._tools.add(data, tx);
522 return toDisposable(() => {
524 });
525 }
527 > addToolSet(toolSet: IToolSet, tx?: ITransaction): IDisposable {
528 if (toolSet === this) {
529 return Disposable.None;
534 });
535 }
537 > getTools(r?: IReader): Iterable<IToolData> {
538 return Iterable.concat(
539 Iterable.filter(this._tools.observable.read(r), toolData => this._contextKeyService.contextMatchesRules(toolData.when)),
541 );
542 }
544 >
545 > export class ToolSetForModel {
546 > public get id() {
547 > return this._toolSet.id;
548 > }
549 >
550 > public get referenceName() {
551 return this._toolSet.referenceName;
552 }
554 > public get icon() {
555 return this._toolSet.icon;
556 }
558 > public get source() {
559 return this._toolSet.source;
560 }
562 > public get description() {
563 return this._toolSet.description;
564 }
566 > public get detail() {
567 return this._toolSet.detail;
568 }
570 > public get legacyFullNames() {
571 return this._toolSet.legacyFullNames;
572 }
574 > public get deprecated() {
575 return this._toolSet.deprecated;
576 }
578 > public get hiddenInToolsPicker() {
579 return this._toolSet.hiddenInToolsPicker;
580 }
582 > constructor(
583 private readonly _toolSet: IToolSet,
584 private readonly model: ILanguageModelChatMetadata | undefined,
585 private readonly toolFilter?: (toolData: IToolData) => boolean,
586 ) { }
588 > public getTools(r?: IReader): Iterable<IToolData> {
589 return Iterable.filter(this._toolSet.getTools(r), toolData => toolMatchesModel(toolData, this.model) && (!this.toolFilter || this.toolFilter(toolData)));
590 }
592 >
593 >
594 > export interface IBeginToolCallOptions {
595 > toolCallId: string;
596 > toolId: string;
597 > chatRequestId?: string;
598 > sessionResource?: URI;
599 > subagentInvocationId?: string;
600 > /**
601 > * Create the streaming invocation even when the tool does not
602 > * implement `handleToolStream`. Used by callers that need a
603 > * `ChatToolInvocation` handle to observe state transitions (e.g.
604 > * confirmation) before invoking the tool.
605 > */
606 > force?: boolean;
607 > }
608 >
609 > export interface IToolInvokedEvent {
610 > readonly toolId: string;
611 > readonly sessionResource: URI | undefined;
612 > readonly requestId: string | undefined;
613 > readonly subagentInvocationId: string | undefined;
614 > }
615 >
616 > export const ILanguageModelToolsService = createDecorator<ILanguageModelToolsService>('ILanguageModelToolsService');
617 >
618 > export type CountTokensCallback = (input: string, token: CancellationToken) => Promise<number>;
619 >
620 > export interface ILanguageModelToolsService {
621 > _serviceBrand: undefined;
622 > readonly vscodeToolSet: ToolSet;
623 > readonly executeToolSet: ToolSet;
624 > readonly readToolSet: ToolSet;
625 > readonly agentToolSet: ToolSet;
626 > readonly onDidChangeTools: Event<void>;
627 > readonly onDidPrepareToolCallBecomeUnresponsive: Event<{ readonly sessionResource: URI; readonly toolData: IToolData }>;
628 > readonly onDidInvokeTool: Event<IToolInvokedEvent>;
629 > registerToolData(toolData: IToolData): IDisposable;
630 > registerToolImplementation(id: string, tool: IToolImpl): IDisposable;
631 > registerTool(toolData: IToolData, tool: IToolImpl): IDisposable;
632 >
633 > /**
634 > * Get all tools currently enabled (matching `when` clauses and model).
635 > * @param model The language model metadata to filter tools by. If undefined, model-specific filtering is skipped.
636 > */
637 > getTools(model: ILanguageModelChatMetadata | undefined): Iterable<IToolData>;
638 >
639 > /**
640 > * Creats an observable of enabled tools in the context. Note the observable
641 > * should be created and reused, not created per reader, for example:
642 > *
643 > * ```
644 > * const toolsObs = toolsService.observeTools(model);
645 > * autorun(reader => {
646 > * const tools = toolsObs.read(reader);
647 > * ...
648 > * });
649 > * ```
650 > * @param model The language model metadata to filter tools by. If undefined, model-specific filtering is skipped.
651 > */
652 > observeTools(model: ILanguageModelChatMetadata | undefined): IObservable<readonly IToolData[]>;
653 >
654 > /**
655 > * Get all registered tools regardless of enablement state.
656 > * Use this for configuration UIs, completions, etc. where all tools should be visible.
657 > */
658 > getAllToolsIncludingDisabled(): Iterable<IToolData>;
659 >
660 > /**
661 > * Get a tool by its ID. Does not check when clauses.
662 > */
663 > getTool(id: string): IToolData | undefined;
664 >
665 > /**
666 > * Get a tool by its reference name. Does not check when clauses.
667 > */
668 > getToolByName(name: string): IToolData | undefined;
669 >
670 > /**
671 > * Begin a tool call in the streaming phase.
672 > * Creates a ChatToolInvocation in the Streaming state and appends it to the chat.
673 > * Returns the invocation so it can be looked up later when invokeTool is called.
674 > */
675 > beginToolCall(options: IBeginToolCallOptions): IChatToolInvocation | undefined;
676 >
677 > /**
678 > * Update the streaming state of a pending tool call.
679 > * Calls the tool's handleToolStream method to get a custom invocation message.
680 > */
681 > updateToolStream(toolCallId: string, partialInput: unknown, token: CancellationToken): Promise<void>;
682 >
683 > invokeTool(invocation: IToolInvocation, countTokens: CountTokensCallback, token: CancellationToken): Promise<IToolResult>;
684 > cancelToolCallsForRequest(requestId: string): void;
685 > /** Flush any pending tool updates to the extension hosts. */
686 > flushToolUpdates(): void;
687 >
688 > readonly toolSets: IObservable<Iterable<IToolSet>>;
689 > getToolSetsForModel(model: ILanguageModelChatMetadata | undefined, reader?: IReader): Iterable<IToolSet>;
690 > getToolSet(id: string): IToolSet | undefined;
691 > getToolSetByName(name: string): IToolSet | undefined;
692 > createToolSet(source: ToolDataSource, id: string, referenceName: string, options?: { icon?: ThemeIcon; description?: string; detail?: string; legacyFullNames?: string[]; deprecated?: boolean; hiddenInToolsPicker?: boolean }): ToolSet & IDisposable;
693 >
694 > // tool names in prompt and agent files ('full reference names')
695 > getFullReferenceNames(): Iterable<string>;
696 > getFullReferenceName(tool: IToolData | IToolSet, toolSet?: IToolSet): string;
697 > getFullReferenceNameMap(): Map<IToolData | IToolSet, string>;
698 > getToolByFullReferenceName(fullReferenceName: string): IToolData | IToolSet | undefined;
699 > getDeprecatedFullReferenceNames(): Map<string, Set<string>>;
700 >
701 > /**
702 > * Gets the enablement maps based on the given set of references.
703 > * @param fullReferenceNames The full reference names of the tools and tool sets to enable.
704 > * @param model Optional language model metadata to filter tools by.
705 > * If undefined is passed, all tools will be returned, even if normally disabled.
706 > */
707 > toToolAndToolSetEnablementMap(fullReferenceNames: readonly string[], model: ILanguageModelChatMetadata | undefined): ToolAndToolSetEnablementMap;
708 >
709 > toFullReferenceNames(map: ToolAndToolSetEnablementMap): string[];
710 > toToolReferences(variableReferences: readonly IVariableReference[]): ChatRequestToolReferenceEntry[];
711 > }
712 >
713 >
714 > export function createToolInputUri(toolCallId: string): URI {
715 return URI.from({ scheme: Schemas.inMemory, path: `/lm/tool/${toolCallId}/tool_input.json` });
716 }
718 > export function createToolSchemaUri(toolOrId: IToolData | string): URI {
719 if (typeof toolOrId !== 'string') {
720 toolOrId = toolOrId.id;
722 return URI.from({ scheme: Schemas.vscode, authority: 'schemas', path: `/lm/tool/${toolOrId}` });
723 }
725 > export namespace SpecedToolAliases {
726 > export const execute = 'execute';
727 > export const edit = 'edit';
728 > export const search = 'search';
729 > export const agent = 'agent';
730 > export const read = 'read';
731 > export const web = 'web';
732 > export const todo = 'todo';
733 > }
734 >
735 > export namespace VSCodeToolReference {
736 > export const runSubagent = 'runSubagent';
737 > export const vscode = 'vscode';
738 >
739 > }
src/vs/workbench/contrib/chat/common/tools/promptTsxTypes.ts 55 introduced LOC · 2 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- promptTsxTypes.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 > /**
7 > * This is a subset of the types export from jsonTypes.d.ts in @vscode/prompt-tsx.
8 > * It's just the types needed to stringify prompt-tsx tool results.
9 > * It should be kept in sync with the types in that file.
10 > *
11 > * Note: do NOT use `declare` with const enums, esbuild doesn't inline them.
12 > * See https://github.com/evanw/esbuild/issues/4394
13 > */
14 >
15 > export const enum PromptNodeType {
16 > Piece = 1,
17 > Text = 2
18 > }
19 > export interface TextJSON {
20 > type: PromptNodeType.Text;
21 > text: string;
22 > lineBreakBefore: boolean | undefined;
23 > }
24 > /**
25 > * Constructor kind of the node represented by {@link PieceJSON}. This is
26 > * less descriptive than the actual constructor, as we only care to preserve
27 > * the element data that the renderer cares about.
28 > */
29 > export const enum PieceCtorKind {
30 > BaseChatMessage = 1,
31 > Other = 2,
32 > ImageChatMessage = 3
33 > }
34 > export interface BasePieceJSON {
35 > type: PromptNodeType.Piece;
36 > ctor: PieceCtorKind.BaseChatMessage | PieceCtorKind.Other;
37 > children: PromptNodeJSON[];
38 > }
39 > export interface ImageChatMessagePieceJSON {
40 > type: PromptNodeType.Piece;
41 > ctor: PieceCtorKind.ImageChatMessage;
42 > children: PromptNodeJSON[];
43 > props: {
44 > src: string;
45 > detail?: 'low' | 'high';
46 > };
47 > }
48 > export type PieceJSON = BasePieceJSON | ImageChatMessagePieceJSON;
49 > export type PromptNodeJSON = PieceJSON | TextJSON;
50 > export interface PromptElementJSON {
51 > node: PieceJSON;
52 > }
53 >
54 > export function stringifyPromptElementJSON(element: PromptElementJSON): string {
55 const strs: string[] = [];
56 stringifyPromptNodeJSON(element.node, strs);
57 return strs.join('');
58 }
60 function stringifyPromptNodeJSON(node: PromptNodeJSON, strs: string[]): void {
61 if (node.type === PromptNodeType.Text) {