Path: blob/main/src/vs/workbench/contrib/chat/common/chatService/chatService.ts
4780 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { IAction } from '../../../../../base/common/actions.js';6import { DeferredPromise } from '../../../../../base/common/async.js';7import { CancellationToken } from '../../../../../base/common/cancellation.js';8import { Event } from '../../../../../base/common/event.js';9import { IMarkdownString } from '../../../../../base/common/htmlContent.js';10import { DisposableStore, IReference } from '../../../../../base/common/lifecycle.js';11import { autorun, autorunSelfDisposable, IObservable, IReader } from '../../../../../base/common/observable.js';12import { ThemeIcon } from '../../../../../base/common/themables.js';13import { hasKey } from '../../../../../base/common/types.js';14import { URI, UriComponents } from '../../../../../base/common/uri.js';15import { IRange, Range } from '../../../../../editor/common/core/range.js';16import { ISelection } from '../../../../../editor/common/core/selection.js';17import { Command, Location, TextEdit } from '../../../../../editor/common/languages.js';18import { FileType } from '../../../../../platform/files/common/files.js';19import { createDecorator } from '../../../../../platform/instantiation/common/instantiation.js';20import { IAutostartResult } from '../../../mcp/common/mcpTypes.js';21import { ICellEditOperation } from '../../../notebook/common/notebookCommon.js';22import { IWorkspaceSymbol } from '../../../search/common/search.js';23import { IChatAgentCommand, IChatAgentData, IChatAgentResult, UserSelectedTools } from '../participants/chatAgents.js';24import { IChatEditingSession } from '../editing/chatEditingService.js';25import { IChatModel, IChatRequestModeInfo, IChatRequestModel, IChatRequestVariableData, IChatResponseModel, IExportableChatData, ISerializableChatData } from '../model/chatModel.js';26import { IParsedChatRequest } from '../requestParser/chatParserTypes.js';27import { IChatParserContext } from '../requestParser/chatRequestParser.js';28import { IChatRequestVariableEntry } from '../attachments/chatVariableEntries.js';29import { IChatRequestVariableValue } from '../attachments/chatVariables.js';30import { ChatAgentLocation } from '../constants.js';31import { IPreparedToolInvocation, IToolConfirmationMessages, IToolResult, IToolResultInputOutputDetails, ToolDataSource } from '../tools/languageModelToolsService.js';3233export interface IChatRequest {34message: string;35variables: Record<string, IChatRequestVariableValue[]>;36}3738export enum ChatErrorLevel {39Info = 0,40Warning = 1,41Error = 242}4344export interface IChatResponseErrorDetailsConfirmationButton {45// eslint-disable-next-line @typescript-eslint/no-explicit-any46data: any;47label: string;48isSecondary?: boolean;49}5051export interface IChatResponseErrorDetails {52message: string;53responseIsIncomplete?: boolean;54responseIsFiltered?: boolean;55responseIsRedacted?: boolean;56isQuotaExceeded?: boolean;57isRateLimited?: boolean;58level?: ChatErrorLevel;59confirmationButtons?: IChatResponseErrorDetailsConfirmationButton[];60code?: string;61}6263export interface IChatResponseProgressFileTreeData {64label: string;65uri: URI;66type?: FileType;67children?: IChatResponseProgressFileTreeData[];68}6970export type IDocumentContext = {71uri: URI;72version: number;73ranges: IRange[];74};7576export function isIDocumentContext(obj: unknown): obj is IDocumentContext {77return (78!!obj &&79typeof obj === 'object' &&80'uri' in obj && obj.uri instanceof URI &&81'version' in obj && typeof obj.version === 'number' &&82'ranges' in obj && Array.isArray(obj.ranges) && obj.ranges.every(Range.isIRange)83);84}8586export interface IChatUsedContext {87documents: IDocumentContext[];88kind: 'usedContext';89}9091export function isIUsedContext(obj: unknown): obj is IChatUsedContext {92return (93!!obj &&94typeof obj === 'object' &&95'documents' in obj &&96Array.isArray(obj.documents) &&97obj.documents.every(isIDocumentContext)98);99}100101export interface IChatContentVariableReference {102variableName: string;103value?: URI | Location;104}105106export function isChatContentVariableReference(obj: unknown): obj is IChatContentVariableReference {107return !!obj &&108typeof obj === 'object' &&109typeof (obj as IChatContentVariableReference).variableName === 'string';110}111112export enum ChatResponseReferencePartStatusKind {113Complete = 1,114Partial = 2,115Omitted = 3116}117118export enum ChatResponseClearToPreviousToolInvocationReason {119NoReason = 0,120FilteredContentRetry = 1,121CopyrightContentRetry = 2,122}123124export interface IChatContentReference {125reference: URI | Location | IChatContentVariableReference | string;126iconPath?: ThemeIcon | { light: URI; dark?: URI };127options?: {128status?: { description: string; kind: ChatResponseReferencePartStatusKind };129diffMeta?: { added: number; removed: number };130originalUri?: URI;131};132kind: 'reference';133}134135export interface IChatCodeCitation {136value: URI;137license: string;138snippet: string;139kind: 'codeCitation';140}141142export interface IChatContentInlineReference {143resolveId?: string;144inlineReference: URI | Location | IWorkspaceSymbol;145name?: string;146kind: 'inlineReference';147}148149export interface IChatMarkdownContent {150kind: 'markdownContent';151content: IMarkdownString;152inlineReferences?: Record<string, IChatContentInlineReference>;153fromSubagent?: boolean;154}155156export interface IChatTreeData {157treeData: IChatResponseProgressFileTreeData;158kind: 'treeData';159}160export interface IMultiDiffResource {161originalUri?: URI;162modifiedUri?: URI;163goToFileUri?: URI;164added?: number;165removed?: number;166}167168export interface IChatMultiDiffInnerData {169title: string;170resources: IMultiDiffResource[];171}172173export interface IChatMultiDiffData {174multiDiffData: IChatMultiDiffInnerData | IObservable<IChatMultiDiffInnerData>;175kind: 'multiDiffData';176collapsed?: boolean;177readOnly?: boolean;178}179180export interface IChatMultiDiffDataSerialized {181multiDiffData: IChatMultiDiffInnerData;182kind: 'multiDiffData';183collapsed?: boolean;184readOnly?: boolean;185}186187export class ChatMultiDiffData implements IChatMultiDiffData {188public readonly kind = 'multiDiffData';189public readonly collapsed?: boolean | undefined;190public readonly readOnly?: boolean | undefined;191public readonly multiDiffData: IChatMultiDiffData['multiDiffData'];192193constructor(opts: {194multiDiffData: IChatMultiDiffInnerData | IObservable<IChatMultiDiffInnerData>;195collapsed?: boolean;196readOnly?: boolean;197}) {198this.readOnly = opts.readOnly;199this.collapsed = opts.collapsed;200this.multiDiffData = opts.multiDiffData;201}202203toJSON(): IChatMultiDiffDataSerialized {204return {205kind: this.kind,206multiDiffData: hasKey(this.multiDiffData, { title: true }) ? this.multiDiffData : this.multiDiffData.get(),207collapsed: this.collapsed,208readOnly: this.readOnly,209};210}211}212213export interface IChatProgressMessage {214content: IMarkdownString;215kind: 'progressMessage';216}217218export interface IChatTask extends IChatTaskDto {219deferred: DeferredPromise<string | void>;220progress: (IChatWarningMessage | IChatContentReference)[];221readonly onDidAddProgress: Event<IChatWarningMessage | IChatContentReference>;222add(progress: IChatWarningMessage | IChatContentReference): void;223224complete: (result: string | void) => void;225task: () => Promise<string | void>;226isSettled: () => boolean;227}228229export interface IChatUndoStop {230kind: 'undoStop';231id: string;232}233234export interface IChatExternalEditsDto {235kind: 'externalEdits';236undoStopId: string;237start: boolean; /** true=start, false=stop */238resources: UriComponents[];239}240241export interface IChatTaskDto {242content: IMarkdownString;243kind: 'progressTask';244}245246export interface IChatTaskSerialized {247content: IMarkdownString;248progress: (IChatWarningMessage | IChatContentReference)[];249kind: 'progressTaskSerialized';250}251252export interface IChatTaskResult {253content: IMarkdownString | void;254kind: 'progressTaskResult';255}256257export interface IChatWarningMessage {258content: IMarkdownString;259kind: 'warning';260}261262export interface IChatAgentVulnerabilityDetails {263title: string;264description: string;265}266267export interface IChatResponseCodeblockUriPart {268kind: 'codeblockUri';269uri: URI;270isEdit?: boolean;271undoStopId?: string;272}273274export interface IChatAgentMarkdownContentWithVulnerability {275content: IMarkdownString;276vulnerabilities: IChatAgentVulnerabilityDetails[];277kind: 'markdownVuln';278}279280export interface IChatCommandButton {281command: Command;282kind: 'command';283}284285export interface IChatMoveMessage {286uri: URI;287range: IRange;288kind: 'move';289}290291export interface IChatTextEdit {292uri: URI;293edits: TextEdit[];294kind: 'textEdit';295done?: boolean;296isExternalEdit?: boolean;297}298299export interface IChatClearToPreviousToolInvocation {300kind: 'clearToPreviousToolInvocation';301reason: ChatResponseClearToPreviousToolInvocationReason;302}303304export interface IChatNotebookEdit {305uri: URI;306edits: ICellEditOperation[];307kind: 'notebookEdit';308done?: boolean;309isExternalEdit?: boolean;310}311312export interface IChatConfirmation {313title: string;314message: string | IMarkdownString;315// eslint-disable-next-line @typescript-eslint/no-explicit-any316data: any;317buttons?: string[];318isUsed?: boolean;319kind: 'confirmation';320}321322export const enum ElicitationState {323Pending = 'pending',324Accepted = 'accepted',325Rejected = 'rejected',326}327328export interface IChatElicitationRequest {329kind: 'elicitation2'; // '2' because initially serialized data used the same kind330title: string | IMarkdownString;331message: string | IMarkdownString;332acceptButtonLabel: string;333rejectButtonLabel: string | undefined;334subtitle?: string | IMarkdownString;335source?: ToolDataSource;336state: IObservable<ElicitationState>;337acceptedResult?: Record<string, unknown>;338moreActions?: IAction[];339accept(value: IAction | true): Promise<void>;340reject?: () => Promise<void>;341isHidden?: IObservable<boolean>;342hide?(): void;343}344345export interface IChatElicitationRequestSerialized {346kind: 'elicitationSerialized';347title: string | IMarkdownString;348message: string | IMarkdownString;349subtitle: string | IMarkdownString | undefined;350source: ToolDataSource | undefined;351state: ElicitationState.Accepted | ElicitationState.Rejected;352isHidden: boolean;353acceptedResult?: Record<string, unknown>;354}355356export interface IChatThinkingPart {357kind: 'thinking';358value?: string | string[];359id?: string;360// eslint-disable-next-line @typescript-eslint/no-explicit-any361metadata?: { readonly [key: string]: any };362generatedTitle?: string;363}364365export interface IChatTerminalToolInvocationData {366kind: 'terminal';367commandLine: {368original: string;369userEdited?: string;370toolEdited?: string;371};372/** Message for model recommending the use of an alternative tool */373alternativeRecommendation?: string;374language: string;375terminalToolSessionId?: string;376/** The predefined command ID that will be used for this terminal command */377terminalCommandId?: string;378/** Serialized URI for the command that was executed in the terminal */379terminalCommandUri?: UriComponents;380/** Serialized output of the executed command */381terminalCommandOutput?: {382text: string;383truncated?: boolean;384lineCount?: number;385};386/** Stored theme colors at execution time to style detached output */387terminalTheme?: {388background?: string;389foreground?: string;390};391/** Stored command state to restore decorations after reload */392terminalCommandState?: {393exitCode?: number;394timestamp?: number;395duration?: number;396};397autoApproveInfo?: IMarkdownString;398}399400/**401* @deprecated This is the old API shape, we should support this for a while before removing it so402* we don't break existing chats403*/404export interface ILegacyChatTerminalToolInvocationData {405kind: 'terminal';406command: string;407language: string;408}409410export function isLegacyChatTerminalToolInvocationData(data: unknown): data is ILegacyChatTerminalToolInvocationData {411return !!data && typeof data === 'object' && 'command' in data;412}413414export interface IChatToolInputInvocationData {415kind: 'input';416// eslint-disable-next-line @typescript-eslint/no-explicit-any417rawInput: any;418/** Optional MCP App UI metadata for rendering during and after tool execution */419mcpAppData?: {420/** URI of the UI resource for rendering (e.g., "ui://weather-server/dashboard") */421resourceUri: string;422/** Reference to the server definition for reconnection */423serverDefinitionId: string;424/** Reference to the collection containing the server */425collectionId: string;426};427}428429export const enum ToolConfirmKind {430Denied,431ConfirmationNotNeeded,432Setting,433LmServicePerTool,434UserAction,435Skipped436}437438export type ConfirmedReason =439| { type: ToolConfirmKind.Denied }440| { type: ToolConfirmKind.ConfirmationNotNeeded; reason?: string | IMarkdownString }441| { type: ToolConfirmKind.Setting; id: string }442| { type: ToolConfirmKind.LmServicePerTool; scope: 'session' | 'workspace' | 'profile' }443| { type: ToolConfirmKind.UserAction }444| { type: ToolConfirmKind.Skipped };445446export interface IChatToolInvocation {447readonly presentation: IPreparedToolInvocation['presentation'];448readonly toolSpecificData?: IChatTerminalToolInvocationData | ILegacyChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatPullRequestContent | IChatTodoListContent;449readonly confirmationMessages?: IToolConfirmationMessages;450readonly originMessage: string | IMarkdownString | undefined;451readonly invocationMessage: string | IMarkdownString;452readonly pastTenseMessage: string | IMarkdownString | undefined;453readonly source: ToolDataSource;454readonly toolId: string;455readonly toolCallId: string;456readonly parameters: unknown;457readonly fromSubAgent?: boolean;458readonly state: IObservable<IChatToolInvocation.State>;459generatedTitle?: string;460461kind: 'toolInvocation';462}463464export namespace IChatToolInvocation {465export const enum StateKind {466WaitingForConfirmation,467Executing,468WaitingForPostApproval,469Completed,470Cancelled,471}472473interface IChatToolInvocationStateBase {474type: StateKind;475}476477interface IChatToolInvocationWaitingForConfirmationState extends IChatToolInvocationStateBase {478type: StateKind.WaitingForConfirmation;479confirm(reason: ConfirmedReason): void;480}481482interface IChatToolInvocationPostConfirmState {483confirmed: ConfirmedReason;484}485486interface IChatToolInvocationExecutingState extends IChatToolInvocationStateBase, IChatToolInvocationPostConfirmState {487type: StateKind.Executing;488progress: IObservable<{ message?: string | IMarkdownString; progress: number | undefined }>;489}490491interface IChatToolInvocationPostExecuteState extends IChatToolInvocationPostConfirmState {492resultDetails: IToolResult['toolResultDetails'];493}494495interface IChatToolWaitingForPostApprovalState extends IChatToolInvocationStateBase, IChatToolInvocationPostExecuteState {496type: StateKind.WaitingForPostApproval;497confirm(reason: ConfirmedReason): void;498contentForModel: IToolResult['content'];499}500501interface IChatToolInvocationCompleteState extends IChatToolInvocationStateBase, IChatToolInvocationPostExecuteState {502type: StateKind.Completed;503postConfirmed: ConfirmedReason | undefined;504contentForModel: IToolResult['content'];505}506507interface IChatToolInvocationCancelledState extends IChatToolInvocationStateBase {508type: StateKind.Cancelled;509reason: ToolConfirmKind.Denied | ToolConfirmKind.Skipped;510}511512export type State =513| IChatToolInvocationWaitingForConfirmationState514| IChatToolInvocationExecutingState515| IChatToolWaitingForPostApprovalState516| IChatToolInvocationCompleteState517| IChatToolInvocationCancelledState;518519export function executionConfirmedOrDenied(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): ConfirmedReason | undefined {520if (invocation.kind === 'toolInvocationSerialized') {521if (invocation.isConfirmed === undefined || typeof invocation.isConfirmed === 'boolean') {522return { type: invocation.isConfirmed ? ToolConfirmKind.UserAction : ToolConfirmKind.Denied };523}524return invocation.isConfirmed;525}526527const state = invocation.state.read(reader);528if (state.type === StateKind.WaitingForConfirmation) {529return undefined; // don't know yet530}531if (state.type === StateKind.Cancelled) {532return { type: state.reason };533}534535return state.confirmed;536}537538export function awaitConfirmation(invocation: IChatToolInvocation, token?: CancellationToken): Promise<ConfirmedReason> {539const reason = executionConfirmedOrDenied(invocation);540if (reason) {541return Promise.resolve(reason);542}543544const store = new DisposableStore();545return new Promise<ConfirmedReason>(resolve => {546if (token) {547store.add(token.onCancellationRequested(() => {548resolve({ type: ToolConfirmKind.Denied });549}));550}551552store.add(autorun(reader => {553const reason = executionConfirmedOrDenied(invocation, reader);554if (reason) {555store.dispose();556resolve(reason);557}558}));559}).finally(() => {560store.dispose();561});562}563564function postApprovalConfirmedOrDenied(invocation: IChatToolInvocation, reader?: IReader): ConfirmedReason | undefined {565const state = invocation.state.read(reader);566if (state.type === StateKind.Completed) {567return state.postConfirmed || { type: ToolConfirmKind.ConfirmationNotNeeded };568}569if (state.type === StateKind.Cancelled) {570return { type: state.reason };571}572573return undefined;574}575576export function confirmWith(invocation: IChatToolInvocation | undefined, reason: ConfirmedReason) {577const state = invocation?.state.get();578if (state?.type === StateKind.WaitingForConfirmation || state?.type === StateKind.WaitingForPostApproval) {579state.confirm(reason);580return true;581}582return false;583}584585export function awaitPostConfirmation(invocation: IChatToolInvocation, token?: CancellationToken): Promise<ConfirmedReason> {586const reason = postApprovalConfirmedOrDenied(invocation);587if (reason) {588return Promise.resolve(reason);589}590591const store = new DisposableStore();592return new Promise<ConfirmedReason>(resolve => {593if (token) {594store.add(token.onCancellationRequested(() => {595resolve({ type: ToolConfirmKind.Denied });596}));597}598599store.add(autorun(reader => {600const reason = postApprovalConfirmedOrDenied(invocation, reader);601if (reason) {602store.dispose();603resolve(reason);604}605}));606}).finally(() => {607store.dispose();608});609}610611export function resultDetails(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader) {612if (invocation.kind === 'toolInvocationSerialized') {613return invocation.resultDetails;614}615616const state = invocation.state.read(reader);617if (state.type === StateKind.Completed || state.type === StateKind.WaitingForPostApproval) {618return state.resultDetails;619}620621return undefined;622}623624export function isComplete(invocation: IChatToolInvocation | IChatToolInvocationSerialized, reader?: IReader): boolean {625if (invocation.kind === 'toolInvocationSerialized') {626return true; // always cancelled or complete627}628629const state = invocation.state.read(reader);630return state.type === StateKind.Completed || state.type === StateKind.Cancelled;631}632}633634635export interface IToolResultOutputDetailsSerialized {636output: {637type: 'data';638mimeType: string;639base64Data: string;640};641}642643/**644* This is a IChatToolInvocation that has been serialized, like after window reload, so it is no longer an active tool invocation.645*/646export interface IChatToolInvocationSerialized {647presentation: IPreparedToolInvocation['presentation'];648toolSpecificData?: IChatTerminalToolInvocationData | IChatToolInputInvocationData | IChatExtensionsContent | IChatPullRequestContent | IChatTodoListContent;649invocationMessage: string | IMarkdownString;650originMessage: string | IMarkdownString | undefined;651pastTenseMessage: string | IMarkdownString | undefined;652resultDetails?: Array<URI | Location> | IToolResultInputOutputDetails | IToolResultOutputDetailsSerialized;653/** boolean used by pre-1.104 versions */654isConfirmed: ConfirmedReason | boolean | undefined;655isComplete: boolean;656toolCallId: string;657toolId: string;658source: ToolDataSource;659readonly fromSubAgent?: boolean;660generatedTitle?: string;661kind: 'toolInvocationSerialized';662}663664export interface IChatExtensionsContent {665extensions: string[];666kind: 'extensions';667}668669export interface IChatPullRequestContent {670uri: URI;671title: string;672description: string;673author: string;674linkTag: string;675kind: 'pullRequest';676}677678export interface IChatTodoListContent {679kind: 'todoList';680sessionId: string;681todoList: Array<{682id: string;683title: string;684description: string;685status: 'not-started' | 'in-progress' | 'completed';686}>;687}688689export interface IChatMcpServersStarting {690readonly kind: 'mcpServersStarting';691readonly state?: IObservable<IAutostartResult>; // not hydrated when serialized692didStartServerIds?: string[];693}694695export class ChatMcpServersStarting implements IChatMcpServersStarting {696public readonly kind = 'mcpServersStarting';697698public didStartServerIds?: string[] = [];699700public get isEmpty() {701const s = this.state.get();702return !s.working && s.serversRequiringInteraction.length === 0;703}704705constructor(public readonly state: IObservable<IAutostartResult>) { }706707wait() {708return new Promise<IAutostartResult>(resolve => {709autorunSelfDisposable(reader => {710const s = this.state.read(reader);711if (!s.working) {712reader.dispose();713resolve(s);714}715});716});717}718719toJSON(): IChatMcpServersStarting {720return { kind: 'mcpServersStarting', didStartServerIds: this.didStartServerIds };721}722}723724export interface IChatPrepareToolInvocationPart {725readonly kind: 'prepareToolInvocation';726readonly toolName: string;727}728729export type IChatProgress =730| IChatMarkdownContent731| IChatAgentMarkdownContentWithVulnerability732| IChatTreeData733| IChatMultiDiffData734| IChatUsedContext735| IChatContentReference736| IChatContentInlineReference737| IChatCodeCitation738| IChatProgressMessage739| IChatTask740| IChatTaskResult741| IChatCommandButton742| IChatWarningMessage743| IChatTextEdit744| IChatNotebookEdit745| IChatMoveMessage746| IChatResponseCodeblockUriPart747| IChatConfirmation748| IChatClearToPreviousToolInvocation749| IChatToolInvocation750| IChatToolInvocationSerialized751| IChatExtensionsContent752| IChatPullRequestContent753| IChatUndoStop754| IChatPrepareToolInvocationPart755| IChatThinkingPart756| IChatTaskSerialized757| IChatElicitationRequest758| IChatElicitationRequestSerialized759| IChatMcpServersStarting;760761export interface IChatFollowup {762kind: 'reply';763message: string;764agentId: string;765subCommand?: string;766title?: string;767tooltip?: string;768}769770export function isChatFollowup(obj: unknown): obj is IChatFollowup {771return (772!!obj &&773(obj as IChatFollowup).kind === 'reply' &&774typeof (obj as IChatFollowup).message === 'string' &&775typeof (obj as IChatFollowup).agentId === 'string'776);777}778779export enum ChatAgentVoteDirection {780Down = 0,781Up = 1782}783784export enum ChatAgentVoteDownReason {785IncorrectCode = 'incorrectCode',786DidNotFollowInstructions = 'didNotFollowInstructions',787IncompleteCode = 'incompleteCode',788MissingContext = 'missingContext',789PoorlyWrittenOrFormatted = 'poorlyWrittenOrFormatted',790RefusedAValidRequest = 'refusedAValidRequest',791OffensiveOrUnsafe = 'offensiveOrUnsafe',792Other = 'other',793WillReportIssue = 'willReportIssue'794}795796export interface IChatVoteAction {797kind: 'vote';798direction: ChatAgentVoteDirection;799reason: ChatAgentVoteDownReason | undefined;800}801802export enum ChatCopyKind {803// Keyboard shortcut or context menu804Action = 1,805Toolbar = 2806}807808export interface IChatCopyAction {809kind: 'copy';810codeBlockIndex: number;811copyKind: ChatCopyKind;812copiedCharacters: number;813totalCharacters: number;814copiedText: string;815totalLines: number;816copiedLines: number;817modelId: string;818languageId?: string;819}820821export interface IChatInsertAction {822kind: 'insert';823codeBlockIndex: number;824totalCharacters: number;825totalLines: number;826languageId?: string;827modelId: string;828newFile?: boolean;829}830831export interface IChatApplyAction {832kind: 'apply';833codeBlockIndex: number;834totalCharacters: number;835totalLines: number;836languageId?: string;837modelId: string;838newFile?: boolean;839codeMapper?: string;840editsProposed: boolean;841}842843844export interface IChatTerminalAction {845kind: 'runInTerminal';846codeBlockIndex: number;847languageId?: string;848}849850export interface IChatCommandAction {851kind: 'command';852commandButton: IChatCommandButton;853}854855export interface IChatFollowupAction {856kind: 'followUp';857followup: IChatFollowup;858}859860export interface IChatBugReportAction {861kind: 'bug';862}863864export interface IChatInlineChatCodeAction {865kind: 'inlineChat';866action: 'accepted' | 'discarded';867}868869870export interface IChatEditingSessionAction {871kind: 'chatEditingSessionAction';872uri: URI;873hasRemainingEdits: boolean;874outcome: 'accepted' | 'rejected' | 'userModified';875}876877export interface IChatEditingHunkAction {878kind: 'chatEditingHunkAction';879uri: URI;880lineCount: number;881linesAdded: number;882linesRemoved: number;883outcome: 'accepted' | 'rejected';884hasRemainingEdits: boolean;885modeId?: string;886modelId?: string;887languageId?: string;888}889890export type ChatUserAction = IChatVoteAction | IChatCopyAction | IChatInsertAction | IChatApplyAction | IChatTerminalAction | IChatCommandAction | IChatFollowupAction | IChatBugReportAction | IChatInlineChatCodeAction | IChatEditingSessionAction | IChatEditingHunkAction;891892export interface IChatUserActionEvent {893action: ChatUserAction;894agentId: string | undefined;895command: string | undefined;896sessionResource: URI;897requestId: string;898result: IChatAgentResult | undefined;899modelId?: string | undefined;900modeId?: string | undefined;901}902903export interface IChatDynamicRequest {904/**905* The message that will be displayed in the UI906*/907message: string;908909/**910* Any extra metadata/context that will go to the provider.911*/912// eslint-disable-next-line @typescript-eslint/no-explicit-any913metadata?: any;914}915916export interface IChatCompleteResponse {917message: string | ReadonlyArray<IChatProgress>;918result?: IChatAgentResult;919followups?: IChatFollowup[];920}921922export interface IChatSessionStats {923fileCount: number;924added: number;925removed: number;926}927928export interface IChatSessionTiming {929startTime: number;930endTime?: number;931}932933export const enum ResponseModelState {934Pending,935Complete,936Cancelled,937Failed,938NeedsInput,939}940941export interface IChatDetail {942sessionResource: URI;943title: string;944lastMessageDate: number;945timing: IChatSessionTiming;946isActive: boolean;947stats?: IChatSessionStats;948lastResponseState: ResponseModelState;949}950951export interface IChatProviderInfo {952id: string;953}954955export interface IChatSendRequestResponseState {956responseCreatedPromise: Promise<IChatResponseModel>;957responseCompletePromise: Promise<void>;958}959960export interface IChatSendRequestData extends IChatSendRequestResponseState {961agent: IChatAgentData;962slashCommand?: IChatAgentCommand;963}964965export interface IChatEditorLocationData {966type: ChatAgentLocation.EditorInline;967id: string;968document: URI;969selection: ISelection;970wholeRange: IRange;971}972973export interface IChatNotebookLocationData {974type: ChatAgentLocation.Notebook;975sessionInputUri: URI;976}977978export interface IChatTerminalLocationData {979type: ChatAgentLocation.Terminal;980// TBD981}982983export type IChatLocationData = IChatEditorLocationData | IChatNotebookLocationData | IChatTerminalLocationData;984985export interface IChatSendRequestOptions {986modeInfo?: IChatRequestModeInfo;987userSelectedModelId?: string;988userSelectedTools?: IObservable<UserSelectedTools>;989location?: ChatAgentLocation;990locationData?: IChatLocationData;991parserContext?: IChatParserContext;992attempt?: number;993noCommandDetection?: boolean;994// eslint-disable-next-line @typescript-eslint/no-explicit-any995acceptedConfirmationData?: any[];996// eslint-disable-next-line @typescript-eslint/no-explicit-any997rejectedConfirmationData?: any[];998attachedContext?: IChatRequestVariableEntry[];9991000/** The target agent ID can be specified with this property instead of using @ in 'message' */1001agentId?: string;1002/** agentId, but will not add a @ name to the request */1003agentIdSilent?: string;1004slashCommand?: string;10051006/**1007* The label of the confirmation action that was selected.1008*/1009confirmation?: string;10101011}10121013export type IChatModelReference = IReference<IChatModel>;10141015export const IChatService = createDecorator<IChatService>('IChatService');10161017export interface IChatService {1018_serviceBrand: undefined;1019transferredSessionResource: URI | undefined;10201021readonly onDidSubmitRequest: Event<{ readonly chatSessionResource: URI }>;10221023/**1024* An observable containing all live chat models.1025*/1026readonly chatModels: IObservable<Iterable<IChatModel>>;10271028isEnabled(location: ChatAgentLocation): boolean;1029hasSessions(): boolean;1030startSession(location: ChatAgentLocation, options?: IChatSessionStartOptions): IChatModelReference;10311032/**1033* Get an active session without holding a reference to it.1034*/1035getSession(sessionResource: URI): IChatModel | undefined;10361037/**1038* Acquire a reference to an active session.1039*/1040getActiveSessionReference(sessionResource: URI): IChatModelReference | undefined;10411042getOrRestoreSession(sessionResource: URI): Promise<IChatModelReference | undefined>;1043getSessionTitle(sessionResource: URI): string | undefined;1044loadSessionFromContent(data: IExportableChatData | ISerializableChatData | URI): IChatModelReference | undefined;1045loadSessionForResource(resource: URI, location: ChatAgentLocation, token: CancellationToken): Promise<IChatModelReference | undefined>;1046readonly editingSessions: IChatEditingSession[];1047getChatSessionFromInternalUri(sessionResource: URI): IChatSessionContext | undefined;10481049/**1050* Returns whether the request was accepted.`1051*/1052sendRequest(sessionResource: URI, message: string, options?: IChatSendRequestOptions): Promise<IChatSendRequestData | undefined>;10531054/**1055* Sets a custom title for a chat model.1056*/1057setTitle(sessionResource: URI, title: string): void;1058appendProgress(request: IChatRequestModel, progress: IChatProgress): void;1059resendRequest(request: IChatRequestModel, options?: IChatSendRequestOptions): Promise<void>;1060adoptRequest(sessionResource: URI, request: IChatRequestModel): Promise<void>;1061removeRequest(sessionResource: URI, requestId: string): Promise<void>;1062cancelCurrentRequestForSession(sessionResource: URI): void;1063addCompleteRequest(sessionResource: URI, message: IParsedChatRequest | string, variableData: IChatRequestVariableData | undefined, attempt: number | undefined, response: IChatCompleteResponse): void;1064setChatSessionTitle(sessionResource: URI, title: string): void;1065getLocalSessionHistory(): Promise<IChatDetail[]>;1066clearAllHistoryEntries(): Promise<void>;1067removeHistoryEntry(sessionResource: URI): Promise<void>;1068getChatStorageFolder(): URI;1069logChatIndex(): void;1070getLiveSessionItems(): Promise<IChatDetail[]>;1071getHistorySessionItems(): Promise<IChatDetail[]>;1072getMetadataForSession(sessionResource: URI): Promise<IChatDetail | undefined>;10731074readonly onDidPerformUserAction: Event<IChatUserActionEvent>;1075notifyUserAction(event: IChatUserActionEvent): void;1076readonly onDidDisposeSession: Event<{ readonly sessionResource: URI[]; readonly reason: 'cleared' }>;10771078transferChatSession(transferredSessionResource: URI, toWorkspace: URI): Promise<void>;10791080activateDefaultAgent(location: ChatAgentLocation): Promise<void>;10811082readonly edits2Enabled: boolean;10831084readonly requestInProgressObs: IObservable<boolean>;10851086/**1087* For tests only!1088*/1089setSaveModelsEnabled(enabled: boolean): void;10901091/**1092* For tests only!1093*/1094waitForModelDisposals(): Promise<void>;1095}10961097export interface IChatSessionContext {1098readonly chatSessionType: string;1099readonly chatSessionResource: URI;1100readonly isUntitled: boolean;1101}11021103export const KEYWORD_ACTIVIATION_SETTING_ID = 'accessibility.voice.keywordActivation';11041105export interface IChatSessionStartOptions {1106canUseTools?: boolean;1107disableBackgroundKeepAlive?: boolean;1108}110911101111