chatService.ts ×27

Frontier kind: Code frontier

unlabeled · c_2acd96b54aae

367 tests · 16558 LOC · 90 files · introduces 0 tests · 1847 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
27 ranges1847 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
2115 ranges16558 lines · 90 files · Browse complete extent
All tests (intent)
367 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: 1847 introduced LOC across 27 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/chatService/chatService.ts 1847 introduced LOC · 27 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- chatService.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 { IAction } from '../../../../../base/common/actions.js';
7 > import { DeferredPromise } from '../../../../../base/common/async.js';
8 > import { CancellationToken } from '../../../../../base/common/cancellation.js';
9 > import { IStringDictionary } from '../../../../../base/common/collections.js';
10 > import { Event } from '../../../../../base/common/event.js';
11 > import { IMarkdownString } from '../../../../../base/common/htmlContent.js';
12 > import { DisposableStore, IReference } from '../../../../../base/common/lifecycle.js';
13 > import { autorun, autorunSelfDisposable, IObservable, IReader } from '../../../../../base/common/observable.js';
14 > import { ThemeIcon } from '../../../../../base/common/themables.js';
15 > import { hasKey } from '../../../../../base/common/types.js';
16 > import { URI, UriComponents } from '../../../../../base/common/uri.js';
17 > import { IRange, Range } from '../../../../../editor/common/core/range.js';
18 > import { ISelection } from '../../../../../editor/common/core/selection.js';
19 > import { Command, Location, TextEdit } from '../../../../../editor/common/languages.js';
20 > import { FileType } from '../../../../../platform/files/common/files.js';
21 > import { createDecorator } from '../../../../../platform/instantiation/common/instantiation.js';
22 > import { IAutostartResult } from '../../../mcp/common/mcpTypes.js';
23 > import { ICellEditOperation } from '../../../notebook/common/notebookCommon.js';
24 > import { IWorkspaceSymbol } from '../../../search/common/search.js';
25 > import { IChatRequestVariableEntry } from '../attachments/chatVariableEntries.js';
26 > import { IChatRequestVariableValue } from '../attachments/chatVariables.js';
27 > import { ReadonlyChatSessionOptionsMap } from '../chatSessionsService.js';
28 > import { ChatAgentLocation, ChatModeKind } from '../constants.js';
29 > import { IChatEditingSession } from '../editing/chatEditingService.js';
30 > import { IChatModel, IChatRequestModeInfo, IChatRequestModel, IChatRequestVariableData, IChatResponseModel, IExportableChatData, ISerializableChatData } from '../model/chatModel.js';
31 > import type { IChatModelReferenceDebugSnapshot } from '../model/chatModelStore.js';
32 > import { IChatAgentCommand, IChatAgentData, IChatAgentResult, UserSelectedTools } from '../participants/chatAgents.js';
33 > import { HookTypeValue } from '../promptSyntax/hookTypes.js';
34 > import { IParsedChatRequest } from '../requestParser/chatParserTypes.js';
35 > import { IChatParserContext } from '../requestParser/chatRequestParser.js';
36 > import { IPreparedToolInvocation, IToolConfirmationMessages, IToolResult, IToolResultInputOutputDetails, ToolDataSource } from '../tools/languageModelToolsService.js';
37 > import { ConfirmationOptionKind, type McpOAuthClient } from '../../../../../platform/agentHost/common/state/protocol/state.js';
38 >
39 > export interface IChatRequest {
40 > message: string;
41 > variables: Record<string, IChatRequestVariableValue[]>;
42 > }
43 >
44 > export enum ChatErrorLevel {
45 > Info = 0,
46 > Warning = 1,
47 > Error = 2
48 > }
49 >
50 > export interface IChatResponseErrorDetailsConfirmationButton {
51 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
52 > data: any;
53 > label: string;
54 > isSecondary?: boolean;
55 > }
56 >
57 > export interface IChatResponseErrorDetails {
58 > message: string;
59 > responseIsIncomplete?: boolean;
60 > responseIsFiltered?: boolean;
61 > responseIsRedacted?: boolean;
62 > isQuotaExceeded?: boolean;
63 > isRateLimited?: boolean;
64 > /**
65 > * If true, the error is an expected operational condition (e.g. user-actionable
66 > * configuration, network connectivity, missing dependency) and should not be
67 > * logged as a `chatAgentError` telemetry event.
68 > */
69 > isExpectedError?: boolean;
70 > level?: ChatErrorLevel;
71 > confirmationButtons?: IChatResponseErrorDetailsConfirmationButton[];
72 > code?: string;
73 > }
74 >
75 > export interface IChatResponseProgressFileTreeData {
76 > label: string;
77 > uri: URI;
78 > type?: FileType;
79 > children?: IChatResponseProgressFileTreeData[];
80 > }
81 >
82 > export type IDocumentContext = {
83 > uri: URI;
84 > version: number;
85 > ranges: IRange[];
86 > };
87 >
88 > export function isIDocumentContext(obj: unknown): obj is IDocumentContext {
89 return (
90 !!obj &&
95 );
96 }
98 > export interface IChatUsedContext {
99 > documents: IDocumentContext[];
100 > kind: 'usedContext';
101 > }
102 >
103 > export function isIUsedContext(obj: unknown): obj is IChatUsedContext {
104 return (
105 !!obj &&
110 );
111 }
113 > export interface IChatContentVariableReference {
114 > variableName: string;
115 > value?: URI | Location;
116 > }
117 >
118 > export function isChatContentVariableReference(obj: unknown): obj is IChatContentVariableReference {
119 return !!obj &&
120 typeof obj === 'object' &&
121 typeof (obj as IChatContentVariableReference).variableName === 'string';
122 }
124 > export enum ChatResponseReferencePartStatusKind {
125 > Complete = 1,
126 > Partial = 2,
127 > Omitted = 3
128 > }
129 >
130 > export enum ChatResponseClearToPreviousToolInvocationReason {
131 > NoReason = 0,
132 > FilteredContentRetry = 1,
133 > CopyrightContentRetry = 2,
134 > }
135 >
136 > export interface IChatContentReference {
137 > reference: URI | Location | IChatContentVariableReference | string;
138 > iconPath?: ThemeIcon | { light: URI; dark?: URI };
139 > options?: {
140 > status?: { description: string; kind: ChatResponseReferencePartStatusKind };
141 > diffMeta?: { added: number; removed: number };
142 > originalUri?: URI;
143 > /** Overrides the reference URI when opening the modified side of a diff. */
144 > modifiedUri?: URI;
145 > isDeletion?: boolean;
146 > };
147 > kind: 'reference';
148 > }
149 >
150 > export interface IChatCodeCitation {
151 > value: URI;
152 > license: string;
153 > snippet: string;
154 > kind: 'codeCitation';
155 > }
156 >
157 > export interface IChatUsagePromptTokenDetail {
158 > category: string;
159 > label: string;
160 > percentageOfPrompt: number;
161 > }
162 >
163 > export interface IChatUsage {
164 > promptTokens: number;
165 > completionTokens: number;
166 > outputBuffer?: number;
167 > promptTokenDetails?: readonly IChatUsagePromptTokenDetail[];
168 > copilotCredits?: number;
169 > /**
170 > * The language-model ID that actually served the request. Set when a
171 > * meta-model (e.g. "auto") routes to a concrete model so consumers
172 > * can look up the real model's metadata (context window size, etc.).
173 > */
174 > actualModelId?: string;
175 > kind: 'usage';
176 > }
177 >
178 > /**
179 > * Formats a copilot credit value for display.
180 > */
181 > export function formatCopilotCredits(credits: number): string {
182 return parseFloat(credits.toFixed(1)).toString();
183 }
185 > export interface IChatContentInlineReference {
186 > resolveId?: string;
187 > inlineReference: URI | Location | IWorkspaceSymbol;
188 > name?: string;
189 > kind: 'inlineReference';
190 > }
191 >
192 > export interface IChatMarkdownContent {
193 > kind: 'markdownContent';
194 > content: IMarkdownString;
195 > inlineReferences?: Record<string, IChatContentInlineReference>;
196 > }
197 >
198 > export interface IChatTreeData {
199 > treeData: IChatResponseProgressFileTreeData;
200 > kind: 'treeData';
201 > }
202 > export interface IMultiDiffResource {
203 > originalUri?: URI;
204 > modifiedUri?: URI;
205 > goToFileUri?: URI;
206 > added?: number;
207 > removed?: number;
208 > }
209 >
210 > export interface IChatMultiDiffInnerData {
211 > title: string;
212 > resources: IMultiDiffResource[];
213 > }
214 >
215 > export interface IChatMultiDiffData {
216 > multiDiffData: IChatMultiDiffInnerData | IObservable<IChatMultiDiffInnerData>;
217 > kind: 'multiDiffData';
218 > collapsed?: boolean;
219 > readOnly?: boolean;
220 > toJSON(): IChatMultiDiffDataSerialized;
221 > }
222 >
223 > export interface IChatMultiDiffDataSerialized {
224 > multiDiffData: IChatMultiDiffInnerData;
225 > kind: 'multiDiffData';
226 > collapsed?: boolean;
227 > readOnly?: boolean;
228 > }
229 >
230 > export class ChatMultiDiffData implements IChatMultiDiffData {
231 > public readonly kind = 'multiDiffData';
232 > public readonly collapsed?: boolean | undefined;
233 > public readonly readOnly?: boolean | undefined;
234 > public readonly multiDiffData: IChatMultiDiffData['multiDiffData'];
235 >
236 > constructor(opts: {
237 multiDiffData: IChatMultiDiffInnerData | IObservable<IChatMultiDiffInnerData>;
238 collapsed?: boolean;
243 this.multiDiffData = opts.multiDiffData;
244 }
246 > toJSON(): IChatMultiDiffDataSerialized {
247 return {
248 kind: this.kind,
252 };
253 }
254 > } chatService.ts
255 >
256 > export interface IChatProgressMessage {
257 > content: IMarkdownString;
258 > kind: 'progressMessage';
259 > shimmer?: boolean;
260 > }
261 >
262 > export interface IChatSystemNotificationPart {
263 > content: IMarkdownString;
264 > kind: 'systemNotification';
265 > }
266 >
267 > export interface IChatTask extends IChatTaskDto {
268 > deferred: DeferredPromise<string | void>;
269 > progress: (IChatWarningMessage | IChatContentReference)[];
270 > readonly onDidAddProgress: Event<IChatWarningMessage | IChatContentReference>;
271 > add(progress: IChatWarningMessage | IChatContentReference): void;
272 >
273 > complete: (result: string | void) => void;
274 > task: () => Promise<string | void>;
275 > isSettled: () => boolean;
276 > toJSON(): IChatTaskSerialized;
277 > }
278 >
279 > export interface IChatUndoStop {
280 > kind: 'undoStop';
281 > id: string;
282 > }
283 >
284 > export interface IChatExternalEditsDto {
285 > kind: 'externalEdits';
286 > undoStopId: string;
287 > start: boolean; /** true=start, false=stop */
288 > resources: UriComponents[];
289 > /**
290 > * When present, these URIs are read instead of the `resources` URIs
291 > * (by-index) when capturing file snapshots. Used by the agent host
292 > * to provide before/after content from the remote filesystem
293 > * or from stored snapshots.
294 > */
295 > contentFor?: UriComponents[];
296 > }
297 >
298 > export interface IChatTaskDto {
299 > content: IMarkdownString;
300 > kind: 'progressTask';
301 > }
302 >
303 > export interface IChatTaskSerialized {
304 > content: IMarkdownString;
305 > progress: (IChatWarningMessage | IChatContentReference)[];
306 > kind: 'progressTaskSerialized';
307 > }
308 >
309 > export interface IChatTaskResult {
310 > content: IMarkdownString | void;
311 > kind: 'progressTaskResult';
312 > }
313 >
314 > export interface IChatWarningMessage {
315 > content: IMarkdownString;
316 > kind: 'warning';
317 > }
318 >
319 > export interface IChatInfoMessage {
320 > content: IMarkdownString;
321 > kind: 'info';
322 > }
323 >
324 > export interface IChatAgentVulnerabilityDetails {
325 > title: string;
326 > description: string;
327 > }
328 >
329 > export interface IChatResponseCodeblockUriPart {
330 > kind: 'codeblockUri';
331 > uri: URI;
332 > isEdit?: boolean;
333 > undoStopId?: string;
334 > subAgentInvocationId?: string;
335 > }
336 >
337 > export interface IChatAgentMarkdownContentWithVulnerability {
338 > content: IMarkdownString;
339 > vulnerabilities: IChatAgentVulnerabilityDetails[];
340 > kind: 'markdownVuln';
341 > }
342 >
343 > export interface IChatCommandButton {
344 > command: Command;
345 > kind: 'command';
346 > additionalCommands?: Command[]; // rendered as secondary buttons
347 > }
348 >
349 > export interface IChatMoveMessage {
350 > uri: URI;
351 > range: IRange;
352 > kind: 'move';
353 > }
354 >
355 > export interface IChatTextEdit {
356 > uri: URI;
357 > edits: TextEdit[];
358 > kind: 'textEdit';
359 > done?: boolean;
360 > isExternalEdit?: boolean;
361 > }
362 >
363 > export interface IChatClearToPreviousToolInvocation {
364 > kind: 'clearToPreviousToolInvocation';
365 > reason: ChatResponseClearToPreviousToolInvocationReason;
366 > }
367 >
368 > export interface IChatNotebookEdit {
369 > uri: URI;
370 > edits: ICellEditOperation[];
371 > kind: 'notebookEdit';
372 > done?: boolean;
373 > isExternalEdit?: boolean;
374 > }
375 >
376 > export interface IChatWorkspaceFileEdit {
377 > oldResource?: URI;
378 > newResource?: URI;
379 > }
380 >
381 > export interface IChatWorkspaceEdit {
382 > kind: 'workspaceEdit';
383 > edits: IChatWorkspaceFileEdit[];
384 > }
385 >
386 > /**
387 > * The kind of file operation an {@link IChatExternalEdit} represents.
388 > */
389 > export type ChatExternalEditKind = 'create' | 'delete' | 'rename' | 'edit';
390 >
391 > /**
392 > * A summary of a file edit that has been performed externally (i.e. by an
393 > * agent or tool outside of chat's own editing pipeline). Carries everything
394 > * needed to render a static "edit pill" without round-tripping through
395 > * {@link IChatEditingSession} for diff computation: the producer already
396 > * knows the URIs and diff stats up-front.
397 > */
398 > export interface IChatExternalEdit {
399 > kind: 'externalEdit';
400 > /** The resulting file URI (after-URI for create/edit/rename, before-URI for delete). */
401 > uri: URI;
402 > /** The kind of file operation. */
403 > editKind: ChatExternalEditKind;
404 > /** For renames, the file URI before the operation. */
405 > originalUri?: URI;
406 > /** URI from which the "before" content can be read (for diff viewing). Absent for creates. */
407 > beforeContentUri?: URI;
408 > /** URI from which the "after" content can be read (for diff viewing). Absent for deletes. */
409 > afterContentUri?: URI;
410 > /** Pre-computed diff display metadata. */
411 > diff?: { added: number; removed: number };
412 > /** Optional undo-stop id (typically the tool call id) for grouping. */
413 > undoStopId?: string;
414 > }
415 >
416 > export interface IChatConfirmation {
417 > title: string;
418 > message: string | IMarkdownString;
419 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
420 > data: any;
421 > buttons?: string[];
422 > isUsed?: boolean;
423 > kind: 'confirmation';
424 > }
425 >
426 > /**
427 > * Validation rules for a question in a question carousel.
428 > */
429 > export interface IChatQuestionValidation {
430 > minLength?: number;
431 > maxLength?: number;
432 > format?: 'email' | 'uri' | 'date' | 'date-time';
433 > minimum?: number;
434 > maximum?: number;
435 > isInteger?: boolean;
436 > }
437 >
438 > /**
439 > * Represents an individual question in a question carousel.
440 > */
441 > export interface IChatQuestion {
442 > id: string;
443 > type: 'text' | 'singleSelect' | 'multiSelect';
444 > title: string;
445 > message?: string | IMarkdownString;
446 > description?: string;
447 > options?: { id: string; label: string; value: string }[];
448 > defaultValue?: string | string[];
449 > allowFreeformInput?: boolean;
450 > required?: boolean;
451 > validation?: IChatQuestionValidation;
452 > detailedMessage?: string | IMarkdownString;
453 > }
454 >
455 > /** Answer shape for a single-select question. */
456 > export interface IChatSingleSelectAnswer {
457 > selectedValue?: string;
458 > freeformValue?: string;
459 > }
460 >
461 > /** Answer shape for a multi-select question. */
462 > export interface IChatMultiSelectAnswer {
463 > selectedValues: string[];
464 > freeformValue?: string;
465 > }
466 >
467 > /** Union of all possible answer values in a question carousel. */
468 > export type IChatQuestionAnswerValue = string | IChatSingleSelectAnswer | IChatMultiSelectAnswer;
469 >
470 > /** Record mapping question IDs to their typed answer values. */
471 > export type IChatQuestionAnswers = Record<string, IChatQuestionAnswerValue>;
472 >
473 > /**
474 > * A carousel for presenting multiple questions inline in the chat response.
475 > * Users can navigate between questions and submit their answers.
476 > */
477 > export interface IChatQuestionCarousel {
478 > questions: IChatQuestion[];
479 > allowSkip: boolean;
480 > /** Unique identifier for resolving the carousel answers back to the extension */
481 > resolveId?: string;
482 > /** Storage for collected answers when user submits */
483 > data?: IChatQuestionAnswers;
484 > /** Whether the carousel has been submitted/skipped */
485 > isUsed?: boolean;
486 > /** True when accepted/answered outside the carousel UI (e.g. via voice) without structured answers. */
487 > answeredExternally?: boolean;
488 > /** Top-level message shown above the questions (e.g. from MCP elicitation message) */
489 > message?: string | IMarkdownString;
490 > /** Source attribution (e.g. MCP server) */
491 > source?: ToolDataSource;
492 > /** Terminal ID when the carousel was triggered by a terminal needing input */
493 > terminalId?: string;
494 > kind: 'questionCarousel';
495 > }
496 >
497 > export const enum ElicitationState {
498 > Pending = 'pending',
499 > Accepted = 'accepted',
500 > Rejected = 'rejected',
501 > }
502 >
503 > export interface IChatElicitationRequest {
504 > kind: 'elicitation2'; // '2' because initially serialized data used the same kind
505 > title: string | IMarkdownString;
506 > message: string | IMarkdownString;
507 > acceptButtonLabel: string;
508 > rejectButtonLabel: string | undefined;
509 > subtitle?: string | IMarkdownString;
510 > source?: ToolDataSource;
511 > state: IObservable<ElicitationState>;
512 > acceptedResult?: Record<string, unknown>;
513 > moreActions?: IAction[];
514 > riskAssessment?: { toolId: string; parameters: unknown };
515 > accept(value: IAction | true): Promise<void>;
516 > reject?: () => Promise<void>;
517 > isHidden?: IObservable<boolean>;
518 > hide?(): void;
519 > toJSON(): IChatElicitationRequestSerialized;
520 > }
521 >
522 > export interface IChatElicitationRequestSerialized {
523 > kind: 'elicitationSerialized';
524 > title: string | IMarkdownString;
525 > message: string | IMarkdownString;
526 > subtitle: string | IMarkdownString | undefined;
527 > source: ToolDataSource | undefined;
528 > state: ElicitationState.Accepted | ElicitationState.Rejected;
529 > isHidden: boolean;
530 > acceptedResult?: Record<string, unknown>;
531 > }
532 >
533 > export interface IChatThinkingPart {
534 > kind: 'thinking';
535 > value?: string | string[];
536 > id?: string;
537 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
538 > metadata?: { readonly [key: string]: any };
539 > generatedTitle?: string;
540 > /** Elapsed reasoning time in milliseconds, persisted so the duration survives reload. */
541 > reasoningDurationMs?: number;
542 > }
543 >
544 > /**
545 > * A progress part representing an auto-mode model routing resolution.
546 > * Shown as a collapsible widget in the chat stream: collapsed displays
547 > * "Routed to <model>", expanded shows routing details and confidence.
548 > */
549 > export interface IChatAutoModeResolutionPart {
550 > kind: 'autoModeResolution';
551 > /** The model ID that was selected by the router */
552 > resolvedModel: string;
553 > /** The user-facing display name of the resolved model */
554 > resolvedModelName: string;
555 > /** The router's classification label */
556 > predictedLabel: 'needs_reasoning' | 'no_reasoning' | 'fallback';
557 > /** Confidence score (0-1) from the router */
558 > confidence: number;
559 > }
560 >
561 > /**
562 > * A progress part representing the execution result of a hook.
563 > * Aligned with the hook output JSON structure: { stopReason, systemMessage, hookSpecificOutput }.
564 > * If {@link stopReason} is set, the hook blocked/denied the operation.
565 > */
566 > export interface IChatHookPart {
567 > kind: 'hook';
568 > /** The type of hook that was executed */
569 > hookType: HookTypeValue;
570 > /** If set, the hook blocked processing. This message is shown to the user. */
571 > stopReason?: string;
572 > /** Warning/system message from the hook, shown to the user */
573 > systemMessage?: string;
574 > /** Display name of the tool that was affected by the hook */
575 > toolDisplayName?: string;
576 > metadata?: { readonly [key: string]: unknown };
577 > /** If set, this hook was executed within a subagent invocation and should be grouped with it. */
578 > subAgentInvocationId?: string;
579 > }
580 >
581 > export interface IChatTerminalToolInvocationData {
582 > kind: 'terminal';
583 > commandLine: {
584 > original: string;
585 > userEdited?: string;
586 > toolEdited?: string;
587 > // command to show in the chat UI (potentially different from what is actually run in the terminal)
588 > forDisplay?: string;
589 > // isSandboxWrapped boolean to run in the terminal (potentially different from original command)
590 > isSandboxWrapped?: boolean;
591 > };
592 > /**
593 > * LM-generated intention describing why the command is being run, shown
594 > * above the command in the terminal tool card. Set by the Agent Host; the
595 > * built-in terminal tool leaves this unset.
596 > */
597 > intention?: string;
598 > /** The working directory URI for the terminal */
599 > cwd?: UriComponents;
600 > /**
601 > * Pre-computed confirmation display data (localization must happen at source).
602 > * Contains the command line to show in confirmation (potentially without cd prefix)
603 > * and the formatted cwd label if a cd prefix was extracted.
604 > */
605 > confirmation?: {
606 > /** The command line to display in the confirmation editor */
607 > commandLine: string;
608 > /** The formatted cwd label to show in title (if cd was extracted) */
609 > cwdLabel?: string;
610 > /** The cd prefix to prepend back when user edits */
611 > cdPrefix?: string;
612 > };
613 > /**
614 > * Overrides to apply to the presentation of the tool call only, but not actually change the
615 > * command that gets run. For example, python -c "print('hello')" can be presented as just
616 > * the Python code with Python syntax highlighting.
617 > */
618 > presentationOverrides?: {
619 > /** The command line to display in the UI */
620 > commandLine: string;
621 > /** The language for syntax highlighting */
622 > language?: string;
623 > };
624 > /** Message for model recommending the use of an alternative tool */
625 > alternativeRecommendation?: string;
626 > language: string;
627 > terminalToolSessionId?: string;
628 > /** False for output-only data that must not create a workbench terminal instance. */
629 > isPty?: boolean;
630 > /** The predefined command ID that will be used for this terminal command */
631 > terminalCommandId?: string;
632 > /** Whether the terminal command was started as a background execution */
633 > isBackground?: boolean;
634 > /** Whether the command was explicitly approved to run outside the sandbox */
635 > requestUnsandboxedExecution?: boolean;
636 > /** The model-provided reason for requesting sandbox bypass */
637 > requestUnsandboxedExecutionReason?: string;
638 > /** Whether the terminal command was approved to run sandboxed with unrestricted network access */
639 > requestAllowNetwork?: boolean;
640 > /** The model-provided reason for requesting unrestricted network access within the sandbox */
641 > requestAllowNetworkReason?: string;
642 > /** Serialized URI for the command that was executed in the terminal */
643 > terminalCommandUri?: UriComponents;
644 > /** Serialized output of the executed command */
645 > terminalCommandOutput?: {
646 > text: string;
647 > truncated?: boolean;
648 > lineCount?: number;
649 > };
650 > /** Stored theme colors at execution time to style detached output */
651 > terminalTheme?: {
652 > background?: string;
653 > foreground?: string;
654 > };
655 > /** Stored command state to restore decorations after reload */
656 > terminalCommandState?: {
657 > exitCode?: number;
658 > timestamp?: number;
659 > duration?: number;
660 > };
661 > /** Whether the user chose to continue in background for this tool invocation */
662 > didContinueInBackground?: boolean;
663 > autoApproveInfo?: IMarkdownString;
664 > /** Names of missing sandbox dependencies that the user may choose to install */
665 > missingSandboxDependencies?: string[];
666 > /** Approved repair actions that may make an installed but unusable sandbox dependency work. */
667 > sandboxRemediations?: string[];
668 > /** User-visible reason a sandbox prerequisite cannot be repaired automatically. */
669 > sandboxPrerequisiteFailure?: string;
670 > }
671 >
672 > /**
673 > * @deprecated This is the old API shape, we should support this for a while before removing it so
674 > * we don't break existing chats
675 > */
676 > export interface ILegacyChatTerminalToolInvocationData {
677 > kind: 'terminal';
678 > command: string;
679 > language: string;
680 > }
681 >
682 > export function isLegacyChatTerminalToolInvocationData(data: unknown): data is ILegacyChatTerminalToolInvocationData {
683 return !!data && typeof data === 'object' && 'command' in data && 'language' in data;
684 }
686 > /**
687 > * Routing information for an MCP App's webview sub-RPCs. The kind
688 > * determines where `tools/call`, `resources/read`,
689 > * `sampling/createMessage`, etc. are sent:
690 > *
691 > * - `local`: resolves the MCP server via {@link IMcpService} from a
692 > * `serverDefinitionId` + `collectionId`. Used for locally-configured
693 > * MCP servers whose state lives in the workbench.
694 > * - `agentHost`: routes through {@link IAgentHostService.handleMcpRequest}
695 > * on an AHP `mcp://` side channel. Used for MCP servers owned by an
696 > * agent host (e.g. Copilot CLI).
697 > */
698 > export type ChatMcpAppData =
699 > | {
700 > kind: 'local';
701 > /** URI of the UI resource for rendering (e.g., "ui://weather-server/dashboard") */
702 > resourceUri: string;
703 > /** Reference to the server definition for reconnection */
704 > serverDefinitionId: string;
705 > /** Reference to the collection containing the server */
706 > collectionId: string;
707 > }
708 > | {
709 > kind: 'agentHost';
710 > /** URI of the UI resource for rendering (e.g., "ui://weather-server/dashboard") */
711 > resourceUri: string;
712 > /** AHP `mcp://` channel URI for the originating server. */
713 > channel: string;
714 > /**
715 > * Stable identifier for the originating server, used as the
716 > * additional key when computing the webview origin. Typically the
717 > * AHP customization id. For top-level (bare) MCP servers this id
718 > * is currently session-scoped, so see {@link ChatMcpAppModel} for
719 > * how it avoids growing persistent application storage on every
720 > * new session.
721 > */
722 > serverId: string;
723 > };
724 >
725 > export interface IChatToolInputInvocationData {
726 > kind: 'input';
727 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
728 > rawInput: any;
729 > /** Optional MCP App UI metadata for rendering during and after tool execution */
730 > mcpAppData?: ChatMcpAppData;
731 > }
732 >
733 > export const enum ToolConfirmKind {
734 > Denied,
735 > ConfirmationNotNeeded,
736 > Setting,
737 > LmServicePerTool,
738 > UserAction,
739 > Skipped
740 > }
741 >
742 > export type ConfirmedReason =
743 > | { type: ToolConfirmKind.Denied }
744 > | { type: ToolConfirmKind.ConfirmationNotNeeded; reason?: string | IMarkdownString }
745 > | { type: ToolConfirmKind.Setting; id: string }
746 > | { type: ToolConfirmKind.LmServicePerTool; scope: 'session' | 'workspace' | 'profile' }
747 > | { type: ToolConfirmKind.UserAction; selectedButton?: string; selectedButtonKind?: ConfirmationOptionKind }
748 > | { type: ToolConfirmKind.Skipped };
749 >
750 > /**
751 > * Active-only controls for a tool call executing on another connected client.
752 > */
753 > export interface IChatToolInvocationOtherClientData {
754 > readonly cancel: () => void;
755 > }
756 >
757 > export interface IChatToolInvocation {
758 > readonly presentation: IPreparedToolInvocation['presentation'];
759 > readonly toolSpecificData?: IChatTerminalToolInvocationData | ILegacyChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatPullRequestContent | IChatTodoListContent | IChatSubagentToolInvocationData | IChatSimpleToolInvocationData | IChatSearchToolInvocationData | IChatToolResourcesInvocationData | IChatModifiedFilesConfirmationData | IChatAgentFeedbackReviewConfirmationData | IChatSessionCreatedData | IChatAutomationConfigurationData | IChatAutomationConfiguredData;
760 > /** Active-only metadata that is omitted when the invocation is serialized. */
761 > readonly otherClientToolCall?: IChatToolInvocationOtherClientData;
762 > /**
763 > * Observable that tracks the `kind` of `toolSpecificData`. Used by the
764 > * tool invocation part to re-render when the kind changes (e.g. from
765 > * `'input'` to `'terminal'` when terminal content arrives).
766 > */
767 > readonly toolSpecificDataKind: IObservable<string | undefined>;
768 > readonly originMessage: string | IMarkdownString | undefined;
769 > readonly invocationMessage: string | IMarkdownString;
770 > readonly pastTenseMessage: string | IMarkdownString | undefined;
771 > readonly source: ToolDataSource;
772 > readonly toolId: string;
773 > readonly toolCallId: string;
774 > readonly subAgentInvocationId?: string;
775 > readonly icon?: ThemeIcon;
776 > readonly state: IObservable<IChatToolInvocation.State>;
777 > generatedTitle?: string;
778 > isAttachedToThinking: boolean;
779 >
780 > kind: 'toolInvocation';
781 >
782 > toJSON(): IChatToolInvocationSerialized;
783 > }
784 >
785 > export namespace IChatToolInvocation {
786 > export const enum StateKind {
787 > /** Tool call is streaming partial input from the LM */
788 > Streaming,
789 > WaitingForConfirmation,
790 > Executing,
791 > WaitingForPostApproval,
792 > Completed,
793 > Cancelled,
794 > WaitingForAuthentication,
795 > }
796 >
797 > interface IChatToolInvocationStateBase {
798 > type: StateKind;
799 > }
800 >
801 > export interface IChatToolInvocationStreamingState extends IChatToolInvocationStateBase {
802 > type: StateKind.Streaming;
803 > /** Observable partial input from the LM stream */
804 > readonly partialInput: IObservable<unknown>;
805 > /** Custom invocation message from handleToolStream */
806 > readonly streamingMessage: IObservable<string | IMarkdownString | undefined>;
807 > }
808 >
809 > /** Properties available after streaming is complete */
810 > interface IChatToolInvocationPostStreamState {
811 > readonly parameters: unknown;
812 > readonly confirmationMessages?: IToolConfirmationMessages;
813 > }
814 >
815 > interface IChatToolInvocationWaitingForConfirmationState extends IChatToolInvocationStateBase, IChatToolInvocationPostStreamState {
816 > type: StateKind.WaitingForConfirmation;
817 > confirm(reason: ConfirmedReason): void;
818 > }
819 >
820 > interface IChatToolInvocationPostConfirmState extends IChatToolInvocationPostStreamState {
821 > confirmed: ConfirmedReason;
822 > }
823 >
824 > interface IChatToolInvocationExecutingState extends IChatToolInvocationStateBase, IChatToolInvocationPostConfirmState {
825 > type: StateKind.Executing;
826 > progress: IObservable<{ message?: string | IMarkdownString; progress: number | undefined }>;
827 > }
828 >
829 > export interface IChatToolInvocationWaitingForAuthenticationState extends IChatToolInvocationStateBase, IChatToolInvocationPostConfirmState {
830 > type: StateKind.WaitingForAuthentication;
831 > readonly server: IChatMcpAuthenticationRequiredServer;
832 > cancel(): void;
833 > }
834 >
835 > interface IChatToolInvocationPostExecuteState extends IChatToolInvocationPostConfirmState {
836 > resultDetails: IToolResult['toolResultDetails'];
837 > }
838 >
839 > interface IChatToolWaitingForPostApprovalState extends IChatToolInvocationStateBase, IChatToolInvocationPostExecuteState {
840 > type: StateKind.WaitingForPostApproval;
841 > confirm(reason: ConfirmedReason): void;
842 > contentForModel: IToolResult['content'];
843 > }
844 >
845 > interface IChatToolInvocationCompleteState extends IChatToolInvocationStateBase, IChatToolInvocationPostExecuteState {
846 > type: StateKind.Completed;
847 > postConfirmed: ConfirmedReason | undefined;
848 > contentForModel: IToolResult['content'];
849 > }
850 >
851 > interface IChatToolInvocationCancelledState extends IChatToolInvocationStateBase, IChatToolInvocationPostStreamState {
852 > type: StateKind.Cancelled;
853 > reason: ToolConfirmKind.Denied | ToolConfirmKind.Skipped;
854 > /** Optional message explaining why the tool was cancelled (e.g., from hook denial) */
855 > reasonMessage?: string | IMarkdownString;
856 > }
857 >
858 > export type State =
859 > | IChatToolInvocationStreamingState
860 > | IChatToolInvocationWaitingForConfirmationState
861 > | IChatToolInvocationExecutingState
862 > | IChatToolInvocationWaitingForAuthenticationState
863 > | IChatToolWaitingForPostApprovalState
864 > | IChatToolInvocationCompleteState
865 > | IChatToolInvocationCancelledState;
866 >
867 > export function executionConfirmedOrDenied(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): ConfirmedReason | undefined {
868 if (invocation.kind === 'toolInvocationSerialized') {
869 if (invocation.isConfirmed === undefined || typeof invocation.isConfirmed === 'boolean') {
883 return state.confirmed;
884 }
886 > export function awaitConfirmation(invocation: IChatToolInvocation, token?: CancellationToken): Promise<ConfirmedReason> {
887 const reason = executionConfirmedOrDenied(invocation);
888 if (reason) {
909 });
910 }
912 > function postApprovalConfirmedOrDenied(invocation: IChatToolInvocation, reader?: IReader): ConfirmedReason | undefined {
913 const state = invocation.state.read(reader);
914 if (state.type === StateKind.Completed) {
921 return undefined;
922 }
924 > export function confirmWith(invocation: IChatToolInvocation | undefined, reason: ConfirmedReason) {
925 const state = invocation?.state.get();
926 if (state?.type === StateKind.WaitingForConfirmation || state?.type === StateKind.WaitingForPostApproval) {
930 return false;
931 }
933 > export function awaitPostConfirmation(invocation: IChatToolInvocation, token?: CancellationToken): Promise<ConfirmedReason> {
934 const reason = postApprovalConfirmedOrDenied(invocation);
935 if (reason) {
956 });
957 }
959 > export function resultDetails(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader) {
960 if (invocation.kind === 'toolInvocationSerialized') {
961 return invocation.resultDetails;
969 return undefined;
970 }
972 > export function isComplete(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): boolean {
973 if (invocation.kind === 'toolInvocationSerialized') {
974 return true; // always cancelled or complete
978 return state.type === StateKind.Completed || state.type === StateKind.Cancelled;
979 }
981 > export function isEffectivelyHidden(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): boolean {
982 if (invocation.presentation === 'hidden') {
983 return true;
988 return false;
989 }
991 > export function isStreaming(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): boolean {
992 if (invocation.kind === 'toolInvocationSerialized') {
993 return false;
997 return state.type === StateKind.Streaming;
998 }
1000 > /**
1001 > * Get parameters from invocation. Returns undefined during streaming state.
1002 > */
1003 > export function getParameters(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): unknown | undefined {
1004 if (invocation.kind === 'toolInvocationSerialized') {
1005 return undefined; // serialized invocations don't store parameters
1013 return state.parameters;
1014 }
1016 > /**
1017 > * Get confirmation messages from invocation. Returns undefined during streaming state.
1018 > */
1019 > export function getConfirmationMessages(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): IToolConfirmationMessages | undefined {
1020 if (invocation.kind === 'toolInvocationSerialized') {
1021 return undefined; // serialized invocations don't store confirmation messages
1029 return state.confirmationMessages;
1030 }
1031 > } chatService.ts
1032 >
1033 >
1034 > export interface IToolResultOutputDetailsSerialized {
1035 > output: {
1036 > type: 'data';
1037 > mimeType: string;
1038 > base64Data: string;
1039 > };
1040 > }
1041 >
1042 > /**
1043 > * This is a IChatToolInvocation that has been serialized, like after window reload, so it is no longer an active tool invocation.
1044 > */
1045 > export interface IChatToolInvocationSerialized {
1046 > presentation: IPreparedToolInvocation['presentation'];
1047 > toolSpecificData?: IChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatPullRequestContent | IChatTodoListContent | IChatSubagentToolInvocationData | IChatSimpleToolInvocationData | IChatSearchToolInvocationData | IChatToolResourcesInvocationData | IChatModifiedFilesConfirmationData | IChatAgentFeedbackReviewConfirmationData | IChatSessionCreatedData | IChatAutomationConfiguredData;
1048 > invocationMessage: string | IMarkdownString;
1049 > originMessage: string | IMarkdownString | undefined;
1050 > pastTenseMessage: string | IMarkdownString | undefined;
1051 > resultDetails?: Array<URI | Location> | IToolResultInputOutputDetails | IToolResultOutputDetailsSerialized;
1052 > /** boolean used by pre-1.104 versions */
1053 > isConfirmed: ConfirmedReason | boolean | undefined;
1054 > isComplete: boolean;
1055 > toolCallId: string;
1056 > toolId: string;
1057 > readonly icon?: undefined;
1058 > source: ToolDataSource | undefined; // undefined on pre-1.104 versions
1059 > readonly subAgentInvocationId?: string;
1060 > generatedTitle?: string;
1061 > isAttachedToThinking?: boolean;
1062 > kind: 'toolInvocationSerialized';
1063 > }
1064 >
1065 > export interface IChatExtensionsContent {
1066 > extensions: string[];
1067 > kind: 'extensions';
1068 > }
1069 >
1070 > export interface IChatPullRequestContent {
1071 > /**
1072 > * @deprecated use `command` instead
1073 > */
1074 > uri?: URI;
1075 > command: Command;
1076 > title: string;
1077 > description: string;
1078 > author: string;
1079 > linkTag: string;
1080 > kind: 'pullRequest';
1081 > }
1082 >
1083 > export interface IChatSubagentToolInvocationData {
1084 > kind: 'subagent';
1085 > isActive?: boolean;
1086 > description?: string;
1087 > agentName?: string;
1088 > prompt?: string;
1089 > result?: string;
1090 > modelName?: string;
1091 > credits?: number;
1092 > /** Millisecond timestamp when the subagent's first turn started. */
1093 > startedAt?: number;
1094 > /** Final elapsed duration in milliseconds. Set when the subagent stops. */
1095 > duration?: number;
1096 > /**
1097 > * Resource (URI string) of the subagent's own chat, when the subagent runs as
1098 > * a distinct chat (e.g. an agent host worker chat). Used to offer an "Open
1099 > * chat" link that reveals the subagent's read-only chat. Undefined when the
1100 > * subagent has no separately-openable chat. A string (not a `URI`) so it stays
1101 > * serializable across the extension host protocol.
1102 > */
1103 > chatResource?: string;
1104 > }
1105 >
1106 > /**
1107 > * Progress type for external tool invocation updates from extensions.
1108 > * When isComplete is false, creates or updates a tool invocation.
1109 > * When isComplete is true, completes an existing tool invocation.
1110 > */
1111 > export interface IChatExternalToolInvocationUpdate {
1112 > kind: 'externalToolInvocationUpdate';
1113 > toolCallId: string;
1114 > toolName: string;
1115 > isComplete: boolean;
1116 > errorMessage?: string;
1117 > invocationMessage?: string | IMarkdownString;
1118 > pastTenseMessage?: string | IMarkdownString;
1119 > toolSpecificData?: IChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatTodoListContent | IChatSubagentToolInvocationData | IChatModifiedFilesConfirmationData;
1120 > subagentInvocationId?: string;
1121 > resultDetails?: IToolResultInputOutputDetails;
1122 > }
1123 >
1124 > export interface IChatTodoListContent {
1125 > kind: 'todoList';
1126 > todoList: Array<{
1127 > id: string;
1128 > title: string;
1129 > status: 'not-started' | 'in-progress' | 'completed';
1130 > }>;
1131 > }
1132 >
1133 > export interface IChatSimpleToolInvocationData {
1134 > kind: 'simpleToolInvocation';
1135 > input: string;
1136 > output: string;
1137 > }
1138 >
1139 > export interface IChatSearchToolInvocationData {
1140 > readonly kind: 'search';
1141 > }
1142 >
1143 > export interface IChatToolResourcesInvocationData {
1144 > readonly kind: 'resources';
1145 > readonly values: Array<URI | Location>;
1146 > }
1147 >
1148 > /**
1149 > * Tool-specific data for a completed `create_session` / `create_chat`
1150 > * agent-host tool call. Carries a clickable link so the renderer can show a
1151 > * deterministic confirmation + "open" button instead of relying on the model
1152 > * to echo a markdown link.
1153 > */
1154 > export interface IChatSessionCreatedData {
1155 > readonly kind: 'sessionCreated';
1156 > /** The `agent-host-session://` link that opens the created/owning session. */
1157 > readonly openLink: string;
1158 > /** Label for the button (e.g. the session title / prompt). */
1159 > readonly label: string;
1160 > /** Whether this is a `create_chat` result (vs `create_session`); selects the pill icon. */
1161 > readonly isChat?: boolean;
1162 > }
1163 >
1164 > /**
1165 > * Tool-specific data for a completed automation create or update. The stable
1166 > * automation ID lets the renderer open the Automations editor at the affected
1167 > * entry without relying on model-authored prose.
1168 > */
1169 > export interface IChatAutomationConfiguredData {
1170 > readonly kind: 'automationConfigured';
1171 > readonly automationId: string;
1172 > readonly automationName: string;
1173 > readonly operation: 'created' | 'updated';
1174 > }
1175 >
1176 > /**
1177 > * Transient preparation data used to guard an automation update across the
1178 > * confirmation boundary. It is omitted from serialized chat invocations.
1179 > */
1180 > export interface IChatAutomationConfigurationData {
1181 > readonly kind: 'automationConfiguration';
1182 > readonly expectedAutomationId: string;
1183 > readonly expectedEditableState: string;
1184 > }
1185 >
1186 > export interface IChatModifiedFilesConfirmationData {
1187 > readonly kind: 'modifiedFilesConfirmation';
1188 > readonly options: readonly string[];
1189 > readonly modifiedFiles: readonly {
1190 > readonly uri: UriComponents;
1191 > /** The pending file operation represented by this entry. */
1192 > readonly editKind?: ChatExternalEditKind;
1193 > readonly originalUri?: UriComponents;
1194 > /**
1195 > * Optional URI to read the modified (after) content from for the diff
1196 > * view. When absent, {@link uri} is used as the modified side.
1197 > */
1198 > readonly modifiedContentUri?: UriComponents;
1199 > /**
1200 > * Optional URI to read the original (before) content from for the diff
1201 > * view. When absent, {@link originalUri} is used as the original side.
1202 > */
1203 > readonly originalContentUri?: UriComponents;
1204 > readonly insertions?: number;
1205 > readonly deletions?: number;
1206 > readonly title?: string;
1207 > readonly description?: string;
1208 > }[];
1209 > }
1210 >
1211 > /**
1212 > * Confirmation data for the agent host `viewUnreviewedComments` tool. The
1213 > * comments themselves are not carried here: the renderer fetches them (and
1214 > * performs reveal/delete/accept actions) through commands registered by the
1215 > * agent feedback feature, so this workbench/chat layer stays decoupled from the
1216 > * `vs/sessions` feedback model. The renderer resolves the owning session from
1217 > * its render context. Only the confirmation button labels are needed up front.
1218 > */
1219 > export interface IChatAgentFeedbackReviewConfirmationData {
1220 > readonly kind: 'agentFeedbackReviewConfirmation';
1221 > /** Confirmation button labels (first is the primary/approve action). */
1222 > readonly options: readonly string[];
1223 > }
1224 >
1225 > /**
1226 > * A single unreviewed comment shown in the {@link IChatAgentFeedbackReviewConfirmationData}
1227 > * confirmation. Produced by {@link AgentFeedbackReviewCommandId.GetComments}.
1228 > */
1229 > export interface IChatAgentFeedbackReviewComment {
1230 > readonly id: string;
1231 > /** Localized origin label, e.g. "PR Review" or "Agent Review"; absent for user-authored comments. */
1232 > readonly kindLabel?: string;
1233 > /** The comment body. */
1234 > readonly text: string;
1235 > /** The file the comment is anchored to. */
1236 > readonly fileUri: UriComponents;
1237 > }
1238 >
1239 > /**
1240 > * Command ids the agent feedback review confirmation renderer (workbench/chat)
1241 > * uses to fetch unreviewed comments and apply the user's selection. They are
1242 > * implemented by the agent feedback feature in `vs/sessions`, keeping the chat
1243 > * layer decoupled from the feedback model. Most take the owning session resource
1244 > * (`UriComponents`) as their first argument; {@link AgentFeedbackReviewCommandId.RevealAt}
1245 > * instead resolves the session from the file resource so a rendered tool call
1246 > * can link to a comment without knowing the session URI.
1247 > */
1248 > export const enum AgentFeedbackReviewCommandId {
1249 > /** `(sessionResource)` -> `IChatAgentFeedbackReviewComment[]` (the `created` reviewable comments). */
1250 > GetComments = '_agentFeedbackReview.getComments',
1251 > /** `(sessionResource, commentId)` -> opens the file and reveals the comment. */
1252 > Reveal = '_agentFeedbackReview.reveal',
1253 > /** `(resourceUri, range)` -> resolves the owning session and reveals the comment at that file range. */
1254 > RevealAt = '_agentFeedbackReview.revealAt',
1255 > /** `(sessionResource, commentId)` -> deletes the comment entirely. */
1256 > Delete = '_agentFeedbackReview.delete',
1257 > /** `(sessionResource, commentIds)` -> accepts (reveals) the given comments. */
1258 > Accept = '_agentFeedbackReview.accept',
1259 > }
1260 >
1261 > export interface IChatMcpServersStarting {
1262 > readonly kind: 'mcpServersStarting';
1263 > readonly state?: IObservable<IAutostartResult>; // not hydrated when serialized
1264 > didStartServerIds?: string[];
1265 > toJSON(): IChatMcpServersStartingSerialized;
1266 > }
1267 >
1268 > export interface IChatMcpServersStartingSerialized {
1269 > readonly kind: 'mcpServersStarting';
1270 > readonly state?: undefined;
1271 > didStartServerIds?: string[];
1272 > }
1273 >
1274 > export interface IChatMcpAuthenticationRequired {
1275 > readonly kind: 'mcpAuthenticationRequired';
1276 > readonly sessionResource: UriComponents;
1277 > readonly servers: IObservable<readonly IChatMcpAuthenticationRequiredServer[]>;
1278 > isUsed: boolean;
1279 > }
1280 >
1281 > export interface IChatMcpAuthenticationRequiredServer {
1282 > readonly id: string;
1283 > readonly name: string;
1284 > readonly resource: string;
1285 > readonly oauthClient?: McpOAuthClient;
1286 > readonly authorizationServers?: readonly string[];
1287 > readonly supportedScopes?: readonly string[];
1288 > readonly requiredScopes?: readonly string[];
1289 > readonly reason?: string;
1290 > }
1291 >
1292 > /**
1293 > * Surfaced by agent-host sessions when one or more MCP servers are still in the
1294 > * {@link McpServerStatus.Starting starting} state a noticeable time after a
1295 > * turn began without any content arriving from the host. The part lists the
1296 > * servers still starting and updates dynamically via {@link servers}: it hides
1297 > * itself (by emptying the observable) once every server has started, content
1298 > * starts being received, or the turn ends — whichever happens first.
1299 > *
1300 > * Unlike {@link IChatMcpServersStarting} (used by the in-process MCP autostart
1301 > * flow), this is a lightweight progress hint with no interactive affordance
1302 > * (there is no "Skip" button).
1303 > */
1304 > export interface IChatMcpServersStartingSlow {
1305 > readonly kind: 'mcpServersStartingSlow';
1306 > readonly sessionResource: UriComponents;
1307 > readonly servers: IObservable<readonly IChatMcpStartingServer[]>;
1308 > }
1309 >
1310 > export interface IChatMcpStartingServer {
1311 > readonly id: string;
1312 > readonly name: string;
1313 > }
1314 >
1315 > export interface IChatDisabledClaudeHooksPart {
1316 > readonly kind: 'disabledClaudeHooks';
1317 > }
1318 >
1319 > /** A single approval option shown in the plan review dropdown button. */
1320 > export interface IChatPlanApprovalAction {
1321 > /**
1322 > * Stable identifier for matching the chosen action programmatically.
1323 > * Unlike `label` this is not localized, so callers should compare
1324 > * against `IChatPlanReviewResult.actionId` rather than `action`.
1325 > * Optional for backwards-compatibility; omit for one-off actions
1326 > * where the localized label is the only intended identifier.
1327 > */
1328 > id?: string;
1329 > label: string;
1330 > description?: string;
1331 > default?: boolean;
1332 > /** When set to 'autopilot', a confirmation dialog is shown before proceeding. */
1333 > permissionLevel?: 'autopilot';
1334 > }
1335 >
1336 > /** The result of reviewing a plan. */
1337 > export interface IChatPlanReviewResult {
1338 > /** The chosen action's localized `label`. */
1339 > action?: string;
1340 > /** The chosen action's stable `id`, if it had one. Prefer this over
1341 > * `action` for programmatic comparisons. */
1342 > actionId?: string;
1343 > rejected: boolean;
1344 > /** Combined feedback string sent to the agent (overall comment + inline
1345 > * comments, joined and formatted as markdown). */
1346 > feedback?: string;
1347 > /** Display-only: the overall textarea comment, kept separate from
1348 > * `feedbackInlineMarkdown` so the chat transcript can render the two
1349 > * parts differently. Falls back to `feedback` when unset. */
1350 > feedbackOverall?: string;
1351 > /** Display-only: pre-formatted markdown listing the inline comments
1352 > * (heading + bullets). See `feedbackOverall`. */
1353 > feedbackInlineMarkdown?: string;
1354 > }
1355 >
1356 > /**
1357 > * A plan review widget. Presents a title, markdown plan content, an optional
1358 > * link to edit the backing plan file, a dropdown of approval actions, a reject
1359 > * button and an optional feedback textarea.
1360 > */
1361 > export interface IChatPlanReview {
1362 > kind: 'planReview';
1363 > /** Title to display in the widget header. */
1364 > title: string;
1365 > /** Markdown content rendered in the body (plan summary or contents). */
1366 > content: string;
1367 > /** Selectable approval actions. Displayed as a dropdown primary button. */
1368 > actions: IChatPlanApprovalAction[];
1369 > /** Whether to show the additional feedback textarea. */
1370 > canProvideFeedback: boolean;
1371 > /** Optional URI to the underlying plan file. An Edit button opens it. */
1372 > planUri?: UriComponents;
1373 > /** Unique identifier for resolving the review back to the extension. */
1374 > resolveId?: string;
1375 > /** Stored result once the user has responded. */
1376 > data?: IChatPlanReviewResult;
1377 > /** Whether the widget has been responded to. */
1378 > isUsed?: boolean;
1379 > /** Source attribution. */
1380 > source?: ToolDataSource;
1381 > }
1382 >
1383 > export class ChatMcpServersStarting implements IChatMcpServersStarting {
1384 > public readonly kind = 'mcpServersStarting';
1385 >
1386 > public didStartServerIds?: string[] = [];
1387 >
1388 > public get isEmpty() {
1389 > const s = this.state.get();
1390 > return !s.working && s.serversRequiringInteraction.length === 0;
1391 > }
1392 >
1393 > constructor(public readonly state: IObservable<IAutostartResult>) { }
1394 >
1395 > wait() {
1396 return new Promise<IAutostartResult>(resolve => {
1397 autorunSelfDisposable(reader => {
1404 });
1405 }
1407 > toJSON(): IChatMcpServersStartingSerialized {
1408 return { kind: 'mcpServersStarting', didStartServerIds: this.didStartServerIds };
1409 }
1410 > } chatService.ts
1411 >
1412 > export type IChatProgress =
1413 > | IChatMarkdownContent
1414 > | IChatAgentMarkdownContentWithVulnerability
1415 > | IChatUsage
1416 > | IChatTreeData
1417 > | IChatMultiDiffData
1418 > | IChatMultiDiffDataSerialized
1419 > | IChatUsedContext
1420 > | IChatContentReference
1421 > | IChatContentInlineReference
1422 > | IChatCodeCitation
1423 > | IChatProgressMessage
1424 > | IChatSystemNotificationPart
1425 > | IChatTask
1426 > | IChatTaskResult
1427 > | IChatCommandButton
1428 > | IChatWarningMessage
1429 > | IChatInfoMessage
1430 > | IChatTextEdit
1431 > | IChatNotebookEdit
1432 > | IChatWorkspaceEdit
1433 > | IChatExternalEdit
1434 > | IChatMoveMessage
1435 > | IChatResponseCodeblockUriPart
1436 > | IChatConfirmation
1437 > | IChatQuestionCarousel
1438 > | IChatPlanReview
1439 > | IChatClearToPreviousToolInvocation
1440 > | IChatToolInvocation
1441 > | IChatToolInvocationSerialized
1442 > | IChatExtensionsContent
1443 > | IChatPullRequestContent
1444 > | IChatUndoStop
1445 > | IChatThinkingPart
1446 > | IChatTaskSerialized
1447 > | IChatElicitationRequest
1448 > | IChatElicitationRequestSerialized
1449 > | IChatMcpServersStarting
1450 > | IChatMcpServersStartingSerialized
1451 > | IChatMcpAuthenticationRequired
1452 > | IChatMcpServersStartingSlow
1453 > | IChatHookPart
1454 > | IChatExternalToolInvocationUpdate
1455 > | IChatDisabledClaudeHooksPart
1456 > | IChatAutoModeResolutionPart;
1457 >
1458 > export interface IChatFollowup {
1459 > kind: 'reply';
1460 > message: string;
1461 > agentId: string;
1462 > subCommand?: string;
1463 > title?: string;
1464 > tooltip?: string;
1465 > }
1466 >
1467 > export function isChatFollowup(obj: unknown): obj is IChatFollowup {
1468 return (
1469 !!obj &&
1473 );
1474 }
1476 > export enum ChatAgentVoteDirection {
1477 > Down = 0,
1478 > Up = 1
1479 > }
1480 >
1481 > export interface IChatVoteAction {
1482 > kind: 'vote';
1483 > direction: ChatAgentVoteDirection;
1484 > }
1485 >
1486 > export enum ChatCopyKind {
1487 > // Keyboard shortcut or context menu
1488 > Action = 1,
1489 > Toolbar = 2
1490 > }
1491 >
1492 > export interface IChatCopyAction {
1493 > kind: 'copy';
1494 > codeBlockIndex: number;
1495 > copyKind: ChatCopyKind;
1496 > copiedCharacters: number;
1497 > totalCharacters: number;
1498 > copiedText: string;
1499 > totalLines: number;
1500 > copiedLines: number;
1501 > modelId: string;
1502 > languageId?: string;
1503 > }
1504 >
1505 > export interface IChatInsertAction {
1506 > kind: 'insert';
1507 > codeBlockIndex: number;
1508 > totalCharacters: number;
1509 > totalLines: number;
1510 > languageId?: string;
1511 > modelId: string;
1512 > newFile?: boolean;
1513 > }
1514 >
1515 > export interface IChatApplyAction {
1516 > kind: 'apply';
1517 > codeBlockIndex: number;
1518 > totalCharacters: number;
1519 > totalLines: number;
1520 > languageId?: string;
1521 > modelId: string;
1522 > newFile?: boolean;
1523 > codeMapper?: string;
1524 > editsProposed: boolean;
1525 > }
1526 >
1527 >
1528 > export interface IChatTerminalAction {
1529 > kind: 'runInTerminal';
1530 > codeBlockIndex: number;
1531 > languageId?: string;
1532 > }
1533 >
1534 > export interface IChatCommandAction {
1535 > kind: 'command';
1536 > commandButton: IChatCommandButton;
1537 > }
1538 >
1539 > export interface IChatFollowupAction {
1540 > kind: 'followUp';
1541 > followup: IChatFollowup;
1542 > }
1543 >
1544 > export interface IChatBugReportAction {
1545 > kind: 'bug';
1546 > }
1547 >
1548 > export interface IChatInlineChatCodeAction {
1549 > kind: 'inlineChat';
1550 > action: 'accepted' | 'discarded';
1551 > }
1552 >
1553 >
1554 > export interface IChatEditingSessionAction {
1555 > kind: 'chatEditingSessionAction';
1556 > uri: URI;
1557 > hasRemainingEdits: boolean;
1558 > outcome: 'accepted' | 'rejected' | 'userModified';
1559 > }
1560 >
1561 > export interface IChatEditingHunkAction {
1562 > kind: 'chatEditingHunkAction';
1563 > uri: URI;
1564 > lineCount: number;
1565 > linesAdded: number;
1566 > linesRemoved: number;
1567 > outcome: 'accepted' | 'rejected';
1568 > hasRemainingEdits: boolean;
1569 > modeId?: string;
1570 > modelId?: string;
1571 > languageId?: string;
1572 > }
1573 >
1574 > export type ChatUserAction = IChatVoteAction | IChatCopyAction | IChatInsertAction | IChatApplyAction | IChatTerminalAction | IChatCommandAction | IChatFollowupAction | IChatBugReportAction | IChatInlineChatCodeAction | IChatEditingSessionAction | IChatEditingHunkAction;
1575 >
1576 > export interface IChatUserActionEvent {
1577 > action: ChatUserAction;
1578 > agentId: string | undefined;
1579 > command: string | undefined;
1580 > sessionResource: URI;
1581 > requestId: string;
1582 > result: IChatAgentResult | undefined;
1583 > modelId?: string | undefined;
1584 > modeId?: string | undefined;
1585 > }
1586 >
1587 > export interface IChatDynamicRequest {
1588 > /**
1589 > * The message that will be displayed in the UI
1590 > */
1591 > message: string;
1592 >
1593 > /**
1594 > * Any extra metadata/context that will go to the provider.
1595 > */
1596 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
1597 > metadata?: any;
1598 > }
1599 >
1600 > export interface IChatCompleteResponse {
1601 > message: string | ReadonlyArray<IChatProgress>;
1602 > result?: IChatAgentResult;
1603 > followups?: IChatFollowup[];
1604 > }
1605 >
1606 > export interface IChatSessionStats {
1607 > readonly fileCount: number;
1608 > readonly added: number;
1609 > readonly removed: number;
1610 > }
1611 >
1612 > export type IChatSessionTiming = {
1613 > /**
1614 > * Timestamp when the session was created in milliseconds elapsed since January 1, 1970 00:00:00 UTC.
1615 > */
1616 > readonly created: number;
1617 >
1618 > /**
1619 > * Timestamp when the most recent request started in milliseconds elapsed since January 1, 1970 00:00:00 UTC.
1620 > *
1621 > * Should be undefined if no requests have been made yet.
1622 > */
1623 > readonly lastRequestStarted: number | undefined;
1624 >
1625 > /**
1626 > * Timestamp when the most recent request completed in milliseconds elapsed since January 1, 1970 00:00:00 UTC.
1627 > *
1628 > * Should be undefined if the most recent request is still in progress or if no requests have been made yet.
1629 > */
1630 > readonly lastRequestEnded: number | undefined;
1631 > };
1632 >
1633 > interface ILegacyChatSessionTiming {
1634 > readonly startTime: number;
1635 > readonly endTime?: number;
1636 > }
1637 >
1638 > export function convertLegacyChatSessionTiming(timing: IChatSessionTiming | ILegacyChatSessionTiming): IChatSessionTiming {
1639 if (hasKey(timing, { created: true })) {
1640 return timing;
1646 };
1647 }
1649 > export const enum ResponseModelState {
1650 > Pending,
1651 > Complete,
1652 > Cancelled,
1653 > Failed,
1654 > NeedsInput,
1655 > }
1656 >
1657 > export interface IChatDetail {
1658 > sessionResource: URI;
1659 > title: string;
1660 > lastMessageDate: number;
1661 > // Also support old timing format for backwards compatibility with persisted data
1662 > timing: IChatSessionTiming | ILegacyChatSessionTiming;
1663 > isActive: boolean;
1664 > stats?: IChatSessionStats;
1665 > lastResponseState: ResponseModelState;
1666 > /**
1667 > * The working directory URI associated with this session.
1668 > * Only populated in the sessions/agents window context.
1669 > */
1670 > workingDirectory?: URI;
1671 > }
1672 >
1673 > export interface IChatProviderInfo {
1674 > id: string;
1675 > }
1676 >
1677 > export interface IChatSendRequestResponseState {
1678 > responseCreatedPromise: Promise<IChatResponseModel>;
1679 > responseCompletePromise: Promise<void>;
1680 > }
1681 >
1682 > export interface IChatSendRequestData extends IChatSendRequestResponseState {
1683 > agent: IChatAgentData;
1684 > slashCommand?: IChatAgentCommand;
1685 > }
1686 >
1687 > /**
1688 > * Result of a sendRequest call - a discriminated union of possible outcomes.
1689 > */
1690 > export type ChatSendResult =
1691 > | ChatSendResultRejected
1692 > | ChatSendResultSent
1693 > | ChatSendResultQueued;
1694 >
1695 > export interface ChatSendResultRejected {
1696 > readonly kind: 'rejected';
1697 > readonly reason: string;
1698 > /** Set when the session was replaced before the request was rejected (e.g. untitled -> read-only contributed session). */
1699 > readonly newSessionResource?: URI;
1700 > }
1701 >
1702 > export interface ChatSendResultSent {
1703 > readonly kind: 'sent';
1704 > readonly data: IChatSendRequestData;
1705 > /** Set when the session was replaced by a new one (e.g. untitled -> real contributed session). */
1706 > readonly newSessionResource?: URI;
1707 > }
1708 >
1709 > export interface ChatSendResultQueued {
1710 > readonly kind: 'queued';
1711 > /**
1712 > * Promise that resolves when the queued message is actually processed.
1713 > * Will resolve to a 'sent' or 'rejected' result.
1714 > */
1715 > readonly deferred: Promise<ChatSendResult>;
1716 > }
1717 >
1718 > export namespace ChatSendResult {
1719 > export function isSent(result: ChatSendResult): result is ChatSendResultSent {
1720 return result.kind === 'sent';
1721 }
1723 > export function isRejected(result: ChatSendResult): result is ChatSendResultRejected {
1724 return result.kind === 'rejected';
1725 }
1727 > export function isQueued(result: ChatSendResult): result is ChatSendResultQueued {
1728 return result.kind === 'queued';
1729 }
1731 > /** Assertion function for tests - asserts that the result is a sent result */
1732 > export function assertSent(result: ChatSendResult): asserts result is ChatSendResultSent {
1733 if (result.kind !== 'sent') {
1734 throw new Error(`Expected ChatSendResult to be 'sent', but was '${result.kind}'`);
1735 }
1736 }
1737 > } chatService.ts
1738 >
1739 > export interface IChatEditorLocationData {
1740 > type: ChatAgentLocation.EditorInline;
1741 > id: string;
1742 > document: URI;
1743 > selection: ISelection;
1744 > wholeRange: IRange;
1745 > }
1746 >
1747 > export interface IChatNotebookLocationData {
1748 > type: ChatAgentLocation.Notebook;
1749 > sessionInputUri: URI;
1750 > }
1751 >
1752 > export interface IChatTerminalLocationData {
1753 > type: ChatAgentLocation.Terminal;
1754 > // TBD
1755 > }
1756 >
1757 > export type IChatLocationData = IChatEditorLocationData | IChatNotebookLocationData | IChatTerminalLocationData;
1758 >
1759 > /**
1760 > * The kind of queue request.
1761 > */
1762 > export const enum ChatRequestQueueKind {
1763 > /** Request is queued to be sent after current request completes */
1764 > Queued = 'queued',
1765 > /** Request is queued and signals the active request to yield */
1766 > Steering = 'steering'
1767 > }
1768 >
1769 > /**
1770 > * A queued or steering message that was authored outside of this client, e.g.
1771 > * by another window connected to the same server-managed session.
1772 > */
1773 > export interface IRemotePendingRequest {
1774 > /** Stable id of the message, as known by the server. */
1775 > readonly id: string;
1776 > readonly kind: ChatRequestQueueKind;
1777 > /** The raw message text. */
1778 > readonly message: string;
1779 > readonly variableData?: IChatRequestVariableData;
1780 > readonly timestamp?: number;
1781 > }
1782 >
1783 > export interface IChatSendRequestOptions {
1784 > modeInfo?: IChatRequestModeInfo;
1785 > userSelectedModelId?: string;
1786 > /**
1787 > * The configuration (e.g. context size, thinking effort) for the selected
1788 > * model as scoped to the requesting editor. When set, it takes precedence
1789 > * over the global per-model configuration so the value sent matches what the
1790 > * editor displays. See issue #320393.
1791 > */
1792 > userSelectedModelConfiguration?: IStringDictionary<unknown>;
1793 > userSelectedTools?: IObservable<UserSelectedTools>;
1794 > location?: ChatAgentLocation;
1795 > locationData?: IChatLocationData;
1796 > parserContext?: IChatParserContext;
1797 > attempt?: number;
1798 > noCommandDetection?: boolean;
1799 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
1800 > acceptedConfirmationData?: any[];
1801 > // eslint-disable-next-line @typescript-eslint/no-explicit-any
1802 > rejectedConfirmationData?: any[];
1803 > attachedContext?: IChatRequestVariableEntry[];
1804 > resolvedVariables?: IChatRequestVariableEntry[];
1805 > agentHostSessionConfig?: Record<string, unknown>;
1806 >
1807 > /** The target agent ID can be specified with this property instead of using @ in 'message' */
1808 > agentId?: string;
1809 > /** agentId, but will not add a @ name to the request */
1810 > agentIdSilent?: string;
1811 > slashCommand?: string;
1812 >
1813 > /**
1814 > * The label of the confirmation action that was selected.
1815 > */
1816 > confirmation?: string;
1817 >
1818 > /**
1819 > * When set, queues this message to be sent after the current request completes.
1820 > * If Steering, also sets yieldRequested on any active request to signal it should wrap up.
1821 > */
1822 > queue?: ChatRequestQueueKind;
1823 >
1824 > /**
1825 > * When true, the queued request will not be processed immediately even if no request is active.
1826 > * The request stays in the queue until `processPendingRequests` is called explicitly.
1827 > */
1828 > pauseQueue?: boolean;
1829 >
1830 > /**
1831 > * When true, the request is rendered as a compact tool-progress-style line
1832 > * instead of a full user message bubble. Used for system-initiated notifications
1833 > * such as terminal command completion.
1834 > */
1835 > isSystemInitiated?: boolean;
1836 >
1837 > /**
1838 > * Display label for system-initiated requests. When set, the request row renders
1839 > * this label as a compact progress-style message instead of the full request text.
1840 > */
1841 > systemInitiatedLabel?: string;
1842 >
1843 > /**
1844 > * Structured terminal execution ID for system-initiated terminal notifications.
1845 > * This avoids parsing IDs from request text when tools need to correlate
1846 > * terminal prompts with follow-up actions.
1847 > */
1848 > terminalExecutionId?: string;
1849 >
1850 > /**
1851 > * When set, the chat service will collect automatic instructions
1852 > * (for example `.instructions.md` files and skills) asynchronously after showing
1853 > * the request in the UI, rather than blocking the UI on collection.
1854 > */
1855 > instructionContext?: {
1856 > modeKind: ChatModeKind;
1857 > enabledTools?: UserSelectedTools;
1858 > enabledSubAgents?: readonly string[];
1859 > };
1860 > }
1861 >
1862 > export type IChatModelReference = IReference<IChatModel>;
1863 >
1864 > export const IChatService = createDecorator<IChatService>('IChatService');
1865 >
1866 > export interface IChatService {
1867 > _serviceBrand: undefined;
1868 > transferredSessionResource: URI | undefined;
1869 >
1870 > readonly onDidSubmitRequest: Event<{ readonly chatSessionResource: URI; readonly message?: IParsedChatRequest }>;
1871 >
1872 > readonly onDidCreateModel: Event<IChatModel>;
1873 >
1874 > /**
1875 > * An observable containing all live chat models.
1876 > */
1877 > readonly chatModels: IObservable<Iterable<IChatModel>>;
1878 >
1879 > readonly editingSessions: readonly IChatEditingSession[];
1880 >
1881 > isEnabled(location: ChatAgentLocation): boolean;
1882 >
1883 > hasSessions(): boolean;
1884 >
1885 > /**
1886 > * Starts a new chat session at the given location.
1887 > *
1888 > * @returns A reference to the session's model.
1889 > */
1890 > startNewLocalSession(location: ChatAgentLocation, options?: IChatSessionStartOptions): IChatModelReference;
1891 >
1892 > /**
1893 > * Get an active session without holding a reference to it.
1894 > *
1895 > * @returns The session's model, or undefined if no active session exists.
1896 > */
1897 > getSession(sessionResource: URI): IChatModel | undefined;
1898 >
1899 > /**
1900 > * Acquire a reference to an active session.
1901 > *
1902 > * @returns A reference to the session's model or undefined if there is no active session for the given resource.
1903 > */
1904 > acquireExistingSession(sessionResource: URI, debugOwner?: string): IChatModelReference | undefined;
1905 >
1906 > /**
1907 > * Tries to acquire an existing a chat session for the resource. If no session exists, tries to load one for the given
1908 > * session resource and location. This may load the session from an external provider.
1909 > *
1910 > * @returns A reference to the session's model, or undefined if the session could not be loaded
1911 > */
1912 > acquireOrLoadSession(sessionResource: URI, location: ChatAgentLocation, token: CancellationToken, debugOwner?: string): Promise<IChatModelReference | undefined>;
1913 >
1914 > /**
1915 > * Loads a session from exported chat data
1916 > */
1917 > loadSessionFromData(data: IExportableChatData | ISerializableChatData, debugOwner?: string): IChatModelReference;
1918 >
1919 > getChatModelReferenceDebugInfo(): IChatModelReferenceDebugSnapshot;
1920 >
1921 > /**
1922 > * Sends a chat request for the given session.
1923 > * @returns A result indicating whether the request was sent, queued, or rejected.
1924 > */
1925 > sendRequest(sessionResource: URI, message: string, options?: IChatSendRequestOptions): Promise<ChatSendResult>;
1926 >
1927 > getSessionTitle(sessionResource: URI): string | undefined;
1928 > setSessionTitle(sessionResource: URI, title: string): void;
1929 >
1930 > appendProgress(request: IChatRequestModel, progress: IChatProgress): void;
1931 > resendRequest(request: IChatRequestModel, options?: IChatSendRequestOptions): Promise<void>;
1932 > adoptRequest(sessionResource: URI, request: IChatRequestModel): Promise<void>;
1933 > removeRequest(sessionResource: URI, requestId: string): Promise<void>;
1934 > cancelCurrentRequestForSession(sessionResource: URI, source?: string): Promise<void>;
1935 > /**
1936 > * Migrates all in-flight and queued pending requests from one session to another.
1937 > * Cancels the in-flight request on the original session, removes queued requests,
1938 > * and re-sends them all on the target session preserving their original send options.
1939 > */
1940 > migrateRequests(originalResource: URI, targetResource: URI): void;
1941 > /**
1942 > * Sets yieldRequested on the active request for the given session.
1943 > */
1944 > setYieldRequested(sessionResource: URI): void;
1945 > /**
1946 > * Removes a pending request from the session's queue.
1947 > */
1948 > removePendingRequest(sessionResource: URI, requestId: string): void;
1949 > /**
1950 > * Sets the pending requests for a session, allowing for deletions/reordering.
1951 > * Adding new requests should go through sendRequest with the queue option.
1952 > */
1953 > setPendingRequests(sessionResource: URI, requests: readonly { requestId: string; kind: ChatRequestQueueKind }[]): void;
1954 > /**
1955 > * Atomically reconciles the pending queue with messages authored by another client.
1956 > * Preserves remote ids and existing matching requests, and no-ops when already equal.
1957 > */
1958 > syncPendingRequestsFromRemote(sessionResource: URI, requests: readonly IRemotePendingRequest[]): void;
1959 > /**
1960 > * Ensures pending requests for the session are processing. If restoring from
1961 > * storage or after an error, pending requests may be present without an
1962 > * active chat message 'loop' happening. THis triggers the loop to happen
1963 > * as needed. Idempotent, safe to call at any time.
1964 > */
1965 > processPendingRequests(sessionResource: URI): void;
1966 > /**
1967 > * Cancels the in-flight request and immediately sends a single pending
1968 > * (queued or steering) request. Local sessions move it to the front and
1969 > * dequeue it; server-managed (agent host) sessions re-send it as a normal
1970 > * turn, since the server does not drain its queue on cancellation.
1971 > */
1972 > sendPendingRequestImmediately(sessionResource: URI, requestId: string): Promise<void>;
1973 > addCompleteRequest(sessionResource: URI, message: IParsedChatRequest | string, variableData: IChatRequestVariableData | undefined, attempt: number | undefined, response: IChatCompleteResponse): void;
1974 > setChatSessionTitle(sessionResource: URI, title: string): void;
1975 > getLocalSessionHistory(): Promise<IChatDetail[]>;
1976 > clearAllHistoryEntries(): Promise<void>;
1977 > removeHistoryEntry(sessionResource: URI): Promise<void>;
1978 > getChatStorageFolder(): URI;
1979 > logChatIndex(): void;
1980 > getLiveSessionItems(): Promise<IChatDetail[]>;
1981 > getHistorySessionItems(): Promise<IChatDetail[]>;
1982 > getMetadataForSession(sessionResource: URI): Promise<IChatDetail | undefined>;
1983 >
1984 > readonly onDidPerformUserAction: Event<IChatUserActionEvent>;
1985 > notifyUserAction(event: IChatUserActionEvent): void;
1986 >
1987 > readonly onDidReceiveQuestionCarouselAnswer: Event<{ requestId: string; resolveId: string; answers: IChatQuestionAnswers | undefined }>;
1988 > notifyQuestionCarouselAnswer(requestId: string, resolveId: string, answers: IChatQuestionAnswers | undefined): void;
1989 >
1990 > readonly onDidDisposeSession: Event<{ readonly sessionResources: readonly URI[]; readonly reason: 'cleared' }>;
1991 >
1992 > transferChatSession(transferredSessionResource: URI, toWorkspace: URI): Promise<void>;
1993 >
1994 > activateDefaultAgent(location: ChatAgentLocation): Promise<void>;
1995 >
1996 > readonly requestInProgressObs: IObservable<boolean>;
1997 >
1998 > /**
1999 > * For tests only!
2000 > */
2001 > setSaveModelsEnabled(enabled: boolean): void;
2002 >
2003 > /**
2004 > * For tests only!
2005 > */
2006 > waitForModelDisposals(): Promise<void>;
2007 > }
2008 >
2009 > export interface IChatSessionContext {
2010 > readonly initialSessionOptions?: ReadonlyChatSessionOptionsMap;
2011 > }
2012 >
2013 > export const KEYWORD_ACTIVIATION_SETTING_ID = 'accessibility.voice.keywordActivation';
2014 >
2015 > export interface IChatSessionStartOptions {
2016 > canUseTools?: boolean;
2017 > disableBackgroundKeepAlive?: boolean;
2018 > debugOwner?: string;
2019 > }
2020 >
2021 > export const ChatStopCancellationNoopEventName = 'chat.stopCancellationNoop';
2022 >
2023 > export type ChatStopCancellationNoopEvent = {
2024 > source: string;
2025 > reason: 'noWidget' | 'noViewModel' | 'noPendingRequest' | 'requestAlreadyCanceled' | 'requestIdUnavailable';
2026 > requestInProgress: 'true' | 'false' | 'unknown';
2027 > pendingRequests: number;
2028 > sessionScheme?: string;
2029 > lastRequestId?: string;
2030 > chatSessionId?: string;
2031 > };
2032 >
2033 > export type ChatStopCancellationNoopClassification = {
2034 > source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The layer where stop cancellation no-op occurred.' };
2035 > reason: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The no-op reason when stop cancellation did not dispatch fully.' };
2036 > requestInProgress: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether request-in-progress was true, false, or unknown at no-op time.' };
2037 > pendingRequests: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The number of queued pending requests at no-op time when known.'; isMeasurement: true };
2038 > sessionScheme?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The URI scheme of the session resource (e.g. vscodeLocalChatSession vs remote).' };
2039 > lastRequestId?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the last request in the session, for correlating with tool invocations.' };
2040 > chatSessionId?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The chat session ID.' };
2041 > owner: 'roblourens';
2042 > comment: 'Tracks possible no-op stop cancellation paths.';
2043 > };
2044 >
2045 > export const ChatPendingRequestChangeEventName = 'chat.pendingRequestChange';
2046 >
2047 > export type ChatPendingRequestChangeEvent = {
2048 > action: 'add' | 'remove' | 'notCancelable';
2049 > source: string;
2050 > requestId?: string;
2051 > chatSessionId?: string;
2052 > };
2053 >
2054 > export type ChatPendingRequestChangeClassification = {
2055 > action: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether a pending request was added or removed.' };
2056 > source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The method that triggered the pending request change.' };
2057 > requestId?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The request ID associated with the pending request change.' };
2058 > chatSessionId?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The chat session ID.' };
2059 > owner: 'roblourens';
2060 > comment: 'Tracks pending request lifecycle changes in the chat service.';
2061 > };