diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 587b04df5a6..5084a0ffd16 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1857,6 +1857,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I ChatResponseExtensionsPart: extHostTypes.ChatResponseExtensionsPart, ChatResponsePullRequestPart: extHostTypes.ChatResponsePullRequestPart, ChatPrepareToolInvocationPart: extHostTypes.ChatPrepareToolInvocationPart, + ChatResponseMultiDiffPart: extHostTypes.ChatResponseMultiDiffPart, ChatResponseReferencePartStatusKind: extHostTypes.ChatResponseReferencePartStatusKind, ChatRequestTurn: extHostTypes.ChatRequestTurn, ChatRequestTurn2: extHostTypes.ChatRequestTurn, diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 8056f1ffaf1..1564dcd29f6 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -41,7 +41,7 @@ import { IViewBadge } from '../../common/views.js'; import { IChatAgentRequest, IChatAgentResult } from '../../contrib/chat/common/chatAgents.js'; import { IChatRequestDraft } from '../../contrib/chat/common/chatEditingService.js'; import { IChatRequestVariableEntry, isImageVariableEntry } from '../../contrib/chat/common/chatVariableEntries.js'; -import { IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatMoveMessage, IChatPrepareToolInvocationPart, IChatProgressMessage, IChatPullRequestContent, IChatResponseCodeblockUriPart, IChatTaskDto, IChatTaskResult, IChatTextEdit, IChatTreeData, IChatUserActionEvent, IChatWarningMessage } from '../../contrib/chat/common/chatService.js'; +import { IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatMoveMessage, IChatMultiDiffData, IChatPrepareToolInvocationPart, IChatProgressMessage, IChatPullRequestContent, IChatResponseCodeblockUriPart, IChatTaskDto, IChatTaskResult, IChatTextEdit, IChatTreeData, IChatUserActionEvent, IChatWarningMessage } from '../../contrib/chat/common/chatService.js'; import { IToolResult, IToolResultInputOutputDetails, IToolResultOutputDetails, ToolDataSource } from '../../contrib/chat/common/languageModelToolsService.js'; import * as chatProvider from '../../contrib/chat/common/languageModels.js'; import { IChatMessageDataPart, IChatResponseDataPart, IChatResponsePromptTsxPart, IChatResponseTextPart } from '../../contrib/chat/common/languageModels.js'; @@ -2633,6 +2633,30 @@ export namespace ChatResponseFilesPart { } } +export namespace ChatResponseMultiDiffPart { + export function from(part: vscode.ChatResponseMultiDiffPart): IChatMultiDiffData { + return { + kind: 'multiDiffData', + multiDiffData: { + title: part.title, + resources: part.value.map(entry => ({ + originalUri: entry.originalUri, + modifiedUri: entry.modifiedUri, + goToFileUri: entry.goToFileUri + })) + } + }; + } + export function to(part: Dto): vscode.ChatResponseMultiDiffPart { + const resources = part.multiDiffData.resources.map(resource => ({ + originalUri: resource.originalUri ? URI.revive(resource.originalUri) : undefined, + modifiedUri: resource.modifiedUri ? URI.revive(resource.modifiedUri) : undefined, + goToFileUri: resource.goToFileUri ? URI.revive(resource.goToFileUri) : undefined + })); + return new types.ChatResponseMultiDiffPart(resources, part.multiDiffData.title); + } +} + export namespace ChatResponseAnchorPart { export function from(part: vscode.ChatResponseAnchorPart): Dto { // Work around type-narrowing confusion between vscode.Uri and URI @@ -2977,6 +3001,8 @@ export namespace ChatResponsePart { return ChatResponseProgressPart.from(part); } else if (part instanceof types.ChatResponseFileTreePart) { return ChatResponseFilesPart.from(part); + } else if (part instanceof types.ChatResponseMultiDiffPart) { + return ChatResponseMultiDiffPart.from(part); } else if (part instanceof types.ChatResponseCommandButtonPart) { return ChatResponseCommandButtonPart.from(part, commandsConverter, commandDisposables); } else if (part instanceof types.ChatResponseTextEditPart) { diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index f6a3d064b4a..95796cea8e0 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4609,6 +4609,15 @@ export class ChatResponseFileTreePart { } } +export class ChatResponseMultiDiffPart { + value: vscode.ChatResponseDiffEntry[]; + title: string; + constructor(value: vscode.ChatResponseDiffEntry[], title: string) { + this.value = value; + this.title = title; + } +} + export class ChatResponseAnchorPart implements vscode.ChatResponseAnchorPart { value: vscode.Uri | vscode.Location; title?: string; diff --git a/src/vs/workbench/contrib/chat/browser/chatContentParts/chatMultiDiffContentPart.ts b/src/vs/workbench/contrib/chat/browser/chatContentParts/chatMultiDiffContentPart.ts new file mode 100644 index 00000000000..9f3d8364924 --- /dev/null +++ b/src/vs/workbench/contrib/chat/browser/chatContentParts/chatMultiDiffContentPart.ts @@ -0,0 +1,243 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as dom from '../../../../../base/browser/dom.js'; +import { ButtonWithIcon } from '../../../../../base/browser/ui/button/button.js'; +import { Disposable, DisposableStore, IDisposable, toDisposable } from '../../../../../base/common/lifecycle.js'; +import { URI } from '../../../../../base/common/uri.js'; +import { localize } from '../../../../../nls.js'; +import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; +import { IChatContentPart } from './chatContentParts.js'; +import { IChatMultiDiffData } from '../../common/chatService.js'; +import { ChatTreeItem } from '../chat.js'; +import { IResourceLabel, ResourceLabels } from '../../../../browser/labels.js'; +import { WorkbenchList } from '../../../../../platform/list/browser/listService.js'; +import { IListRenderer, IListVirtualDelegate } from '../../../../../base/browser/ui/list/list.js'; +import { FileKind } from '../../../../../platform/files/common/files.js'; +import { createFileIconThemableTreeContainerScope } from '../../../files/browser/views/explorerView.js'; +import { IThemeService } from '../../../../../platform/theme/common/themeService.js'; +import { IEditSessionEntryDiff } from '../../common/chatEditingService.js'; +import { IEditorService } from '../../../../services/editor/common/editorService.js'; +import { IEditorGroupsService } from '../../../../services/editor/common/editorGroupsService.js'; +import { MultiDiffEditorInput } from '../../../multiDiffEditor/browser/multiDiffEditorInput.js'; +import { MultiDiffEditorItem } from '../../../multiDiffEditor/browser/multiDiffSourceResolverService.js'; +import { Codicon } from '../../../../../base/common/codicons.js'; +import { ThemeIcon } from '../../../../../base/common/themables.js'; +import { IChatRendererContent } from '../../common/chatViewModel.js'; +import { Emitter, Event } from '../../../../../base/common/event.js'; + +const $ = dom.$; + +interface IChatMultiDiffItem { + uri: URI; + diff?: IEditSessionEntryDiff; +} + +const ELEMENT_HEIGHT = 22; +const MAX_ITEMS_SHOWN = 6; + +export class ChatMultiDiffContentPart extends Disposable implements IChatContentPart { + public readonly domNode: HTMLElement; + + + private readonly _onDidChangeHeight = this._register(new Emitter()); + public readonly onDidChangeHeight = this._onDidChangeHeight.event; + + private list!: WorkbenchList; + private isCollapsed: boolean = true; + + constructor( + private readonly content: IChatMultiDiffData, + element: ChatTreeItem, + @IInstantiationService private readonly instantiationService: IInstantiationService, + @IEditorService private readonly editorService: IEditorService, + @IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService, + @IThemeService private readonly themeService: IThemeService + ) { + super(); + + const headerDomNode = $('.checkpoint-file-changes-summary-header'); + this.domNode = $('.checkpoint-file-changes-summary', undefined, headerDomNode); + this.domNode.tabIndex = 0; + + this._register(this.renderHeader(headerDomNode)); + this._register(this.renderFilesList(this.domNode)); + } + + private renderHeader(container: HTMLElement): IDisposable { + const fileCount = this.content.multiDiffData.resources.length; + + const viewListButtonContainer = container.appendChild($('.chat-file-changes-label')); + const viewListButton = new ButtonWithIcon(viewListButtonContainer, {}); + viewListButton.label = fileCount === 1 + ? localize('chatMultiDiff.oneFile', 'Changed 1 file') + : localize('chatMultiDiff.manyFiles', 'Changed {0} files', fileCount); + + const setExpansionState = () => { + viewListButton.icon = this.isCollapsed ? Codicon.chevronRight : Codicon.chevronDown; + this.domNode.classList.toggle('chat-file-changes-collapsed', this.isCollapsed); + this._onDidChangeHeight.fire(); + }; + setExpansionState(); + + const disposables = new DisposableStore(); + disposables.add(viewListButton); + disposables.add(viewListButton.onDidClick(() => { + this.isCollapsed = !this.isCollapsed; + setExpansionState(); + })); + disposables.add(this.renderViewAllFileChangesButton(viewListButton.element)); + return toDisposable(() => disposables.dispose()); + } + + private renderViewAllFileChangesButton(container: HTMLElement): IDisposable { + const button = container.appendChild($('.chat-view-changes-icon')); + button.classList.add(...ThemeIcon.asClassNameArray(Codicon.diffMultiple)); + + return dom.addDisposableListener(button, 'click', (e) => { + const source = URI.parse(`multi-diff-editor:${new Date().getMilliseconds().toString() + Math.random().toString()}`); + const input = this.instantiationService.createInstance( + MultiDiffEditorInput, + source, + this.content.multiDiffData.title || 'Multi-Diff', + this.content.multiDiffData.resources.map(resource => new MultiDiffEditorItem( + resource.originalUri, + resource.modifiedUri, + resource.goToFileUri + )), + false + ); + this.editorGroupsService.activeGroup.openEditor(input); + dom.EventHelper.stop(e, true); + }); + } + + private renderFilesList(container: HTMLElement): IDisposable { + const store = new DisposableStore(); + + const listContainer = container.appendChild($('.chat-summary-list')); + store.add(createFileIconThemableTreeContainerScope(listContainer, this.themeService)); + const resourceLabels = store.add(this.instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: Event.None })); + + this.list = store.add(this.instantiationService.createInstance( + WorkbenchList, + 'ChatMultiDiffList', + listContainer, + new ChatMultiDiffListDelegate(), + [this.instantiationService.createInstance(ChatMultiDiffListRenderer, resourceLabels)], + { + identityProvider: { + getId: (element: IChatMultiDiffItem) => element.uri.toString() + }, + setRowLineHeight: true, + horizontalScrolling: false, + supportDynamicHeights: false, + mouseSupport: true, + accessibilityProvider: { + getAriaLabel: (element: IChatMultiDiffItem) => element.uri.path, + getWidgetAriaLabel: () => localize('chatMultiDiffList', "File Changes") + } + } + )); + + const items: IChatMultiDiffItem[] = []; + for (const resource of this.content.multiDiffData.resources) { + const uri = resource.modifiedUri || resource.originalUri || resource.goToFileUri; + if (!uri) { + continue; + } + + const item: IChatMultiDiffItem = { uri }; + + if (resource.originalUri && resource.modifiedUri) { + item.diff = { + originalURI: resource.originalUri, + modifiedURI: resource.modifiedUri, + quitEarly: false, + identical: false, + added: 0, + removed: 0 + }; + } + + items.push(item); + } + + this.list.splice(0, this.list.length, items); + + const height = Math.min(items.length, MAX_ITEMS_SHOWN) * ELEMENT_HEIGHT; + this.list.layout(height); + listContainer.style.height = `${height}px`; + + store.add(this.list.onDidOpen((e) => { + if (!e.element) { + return; + } + + if (e.element.diff) { + this.editorService.openEditor({ + original: { resource: e.element.diff.originalURI }, + modified: { resource: e.element.diff.modifiedURI }, + options: { preserveFocus: true } + }); + } else { + this.editorService.openEditor({ + resource: e.element.uri, + options: { preserveFocus: true } + }); + } + })); + + return store; + } + + hasSameContent(other: IChatRendererContent): boolean { + return other.kind === 'multiDiffData' && + (other as any).multiDiffData?.resources?.length === this.content.multiDiffData.resources.length; + } + + addDisposable(disposable: IDisposable): void { + this._register(disposable); + } +} + +class ChatMultiDiffListDelegate implements IListVirtualDelegate { + getHeight(): number { + return 22; + } + + getTemplateId(): string { + return 'chatMultiDiffItem'; + } +} + +interface IChatMultiDiffItemTemplate extends IDisposable { + readonly label: IResourceLabel; +} + +class ChatMultiDiffListRenderer implements IListRenderer { + static readonly TEMPLATE_ID = 'chatMultiDiffItem'; + static readonly CHANGES_SUMMARY_CLASS_NAME = 'insertions-and-deletions'; + + readonly templateId: string = ChatMultiDiffListRenderer.TEMPLATE_ID; + + constructor(private labels: ResourceLabels) { } + + renderTemplate(container: HTMLElement): IChatMultiDiffItemTemplate { + const label = this.labels.create(container, { supportHighlights: true, supportIcons: true }); + return { label, dispose: () => label.dispose() }; + } + + renderElement(element: IChatMultiDiffItem, _index: number, templateData: IChatMultiDiffItemTemplate): void { + templateData.label.setFile(element.uri, { + fileKind: FileKind.FILE, + title: element.uri.path + }); + } + + disposeTemplate(templateData: IChatMultiDiffItemTemplate): void { + templateData.dispose(); + } +} diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index cba516ad573..e8eed964cd6 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -49,7 +49,7 @@ import { IChatAgentMetadata } from '../common/chatAgents.js'; import { ChatContextKeys } from '../common/chatContextKeys.js'; import { IChatTextEditGroup } from '../common/chatModel.js'; import { chatSubcommandLeader } from '../common/chatParserTypes.js'; -import { ChatAgentVoteDirection, ChatAgentVoteDownReason, ChatErrorLevel, IChatChangesSummary, IChatConfirmation, IChatContentReference, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatPullRequestContent, IChatTask, IChatTaskSerialized, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop } from '../common/chatService.js'; +import { ChatAgentVoteDirection, ChatAgentVoteDownReason, ChatErrorLevel, IChatChangesSummary, IChatConfirmation, IChatContentReference, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatMarkdownContent, IChatPullRequestContent, IChatMultiDiffData, IChatTask, IChatTaskSerialized, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop } from '../common/chatService.js'; import { IChatChangesSummaryPart, IChatCodeCitations, IChatErrorDetailsPart, IChatReferences, IChatRendererContent, IChatRequestViewModel, IChatResponseViewModel, IChatViewModel, IChatWorkingProgress, isRequestVM, isResponseVM } from '../common/chatViewModel.js'; import { getNWords } from '../common/chatWordCounter.js'; import { CodeBlockModelCollection } from '../common/codeBlockModelCollection.js'; @@ -72,6 +72,7 @@ import { ChatCollapsibleListContentPart, ChatUsedReferencesListContentPart, Coll import { ChatTaskContentPart } from './chatContentParts/chatTaskContentPart.js'; import { ChatTextEditContentPart, DiffEditorPool } from './chatContentParts/chatTextEditContentPart.js'; import { ChatTreeContentPart, TreePool } from './chatContentParts/chatTreeContentPart.js'; +import { ChatMultiDiffContentPart } from './chatContentParts/chatMultiDiffContentPart.js'; import { ChatErrorContentPart } from './chatContentParts/chatErrorContentPart.js'; import { ChatToolInvocationPart } from './chatContentParts/toolInvocationParts/chatToolInvocationPart.js'; import { ChatMarkdownDecorationsRenderer } from './chatMarkdownDecorationsRenderer.js'; @@ -1104,6 +1105,8 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer { + this.updateItemHeight(templateData); + })); + return multiDiffPart; + } + private renderContentReferencesListData(references: IChatReferences, labelOverride: string | undefined, context: IChatContentPartRenderContext, templateData: IChatListItemTemplate): ChatCollapsibleListContentPart { const referencesPart = this.instantiationService.createInstance(ChatUsedReferencesListContentPart, references.references, labelOverride, context, this._contentReferencesListPool, { expandedWhenEmptyResponse: checkModeOption(this.delegate.currentChatMode(), this.rendererOptions.referencesExpandedWhenEmptyResponse) }); referencesPart.addDisposable(referencesPart.onDidChangeHeight(() => { diff --git a/src/vs/workbench/contrib/chat/common/chatModel.ts b/src/vs/workbench/contrib/chat/common/chatModel.ts index dc9ee6f9269..f17335b9bd6 100644 --- a/src/vs/workbench/contrib/chat/common/chatModel.ts +++ b/src/vs/workbench/contrib/chat/common/chatModel.ts @@ -26,7 +26,7 @@ import { CellUri, ICellEditOperation } from '../../notebook/common/notebookCommo import { IChatAgentCommand, IChatAgentData, IChatAgentResult, IChatAgentService, reviveSerializedAgent } from './chatAgents.js'; import { IChatEditingService, IChatEditingSession } from './chatEditingService.js'; import { ChatRequestTextPart, IParsedChatRequest, reviveParsedChatRequest } from './chatParserTypes.js'; -import { ChatAgentVoteDirection, ChatAgentVoteDownReason, IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatEditingSessionAction, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatLocationData, IChatMarkdownContent, IChatNotebookEdit, IChatPrepareToolInvocationPart, IChatProgress, IChatProgressMessage, IChatPullRequestContent, IChatResponseCodeblockUriPart, IChatResponseProgressFileTreeData, IChatTask, IChatTaskSerialized, IChatTextEdit, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop, IChatUsedContext, IChatWarningMessage, isIUsedContext } from './chatService.js'; +import { ChatAgentVoteDirection, ChatAgentVoteDownReason, IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatEditingSessionAction, IChatElicitationRequest, IChatExtensionsContent, IChatFollowup, IChatLocationData, IChatMarkdownContent, IChatMultiDiffData, IChatNotebookEdit, IChatPrepareToolInvocationPart, IChatProgress, IChatProgressMessage, IChatPullRequestContent, IChatResponseCodeblockUriPart, IChatResponseProgressFileTreeData, IChatTask, IChatTaskSerialized, IChatTextEdit, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop, IChatUsedContext, IChatWarningMessage, isIUsedContext } from './chatService.js'; import { IChatRequestVariableEntry } from './chatVariableEntries.js'; import { ChatAgentLocation, ChatModeKind } from './constants.js'; @@ -107,6 +107,7 @@ export type IChatProgressHistoryResponseContent = | IChatAgentMarkdownContentWithVulnerability | IChatResponseCodeblockUriPart | IChatTreeData + | IChatMultiDiffData | IChatContentInlineReference | IChatProgressMessage | IChatCommandButton @@ -359,6 +360,7 @@ class AbstractResponse implements IResponse { case 'undoStop': case 'prepareToolInvocation': case 'elicitation': + case 'multiDiffData': // Ignore continue; case 'inlineReference': diff --git a/src/vs/workbench/contrib/chat/common/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService.ts index ba5896b98fd..8ea24fb92dc 100644 --- a/src/vs/workbench/contrib/chat/common/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService.ts @@ -140,6 +140,17 @@ export interface IChatTreeData { treeData: IChatResponseProgressFileTreeData; kind: 'treeData'; } +export interface IChatMultiDiffData { + multiDiffData: { + title: string; + resources: Array<{ + originalUri?: URI; + modifiedUri?: URI; + goToFileUri?: URI; + }>; + }; + kind: 'multiDiffData'; +} export interface IChatProgressMessage { content: IMarkdownString; @@ -344,6 +355,7 @@ export type IChatProgress = | IChatMarkdownContent | IChatAgentMarkdownContentWithVulnerability | IChatTreeData + | IChatMultiDiffData | IChatUsedContext | IChatContentReference | IChatContentInlineReference diff --git a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts index fc616ac275c..7e2136b72e9 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts @@ -107,7 +107,49 @@ declare module 'vscode' { constructor(toolName: string, toolCallId: string, isError?: boolean); } - export type ExtendedChatResponsePart = ChatResponsePart | ChatResponseTextEditPart | ChatResponseNotebookEditPart | ChatResponseConfirmationPart | ChatResponseCodeCitationPart | ChatResponseReferencePart2 | ChatResponseMovePart | ChatResponseExtensionsPart | ChatResponsePullRequestPart | ChatPrepareToolInvocationPart | ChatToolInvocationPart; + /** + * Represents a single file diff entry in a multi diff view. + */ + export interface ChatResponseDiffEntry { + /** + * The original file URI (undefined for new files). + */ + originalUri?: Uri; + + /** + * The modified file URI (undefined for deleted files). + */ + modifiedUri?: Uri; + + /** + * Optional URI to navigate to when clicking on the file. + */ + goToFileUri?: Uri; + } + + /** + * Represents a part of a chat response that shows multiple file diffs. + */ + export class ChatResponseMultiDiffPart { + /** + * Array of file diff entries to display. + */ + value: ChatResponseDiffEntry[]; + + /** + * The title for the multi diff editor. + */ + title: string; + + /** + * Create a new ChatResponseMultiDiffPart. + * @param value Array of file diff entries. + * @param title The title for the multi diff editor. + */ + constructor(value: ChatResponseDiffEntry[], title: string); + } + + export type ExtendedChatResponsePart = ChatResponsePart | ChatResponseTextEditPart | ChatResponseNotebookEditPart | ChatResponseConfirmationPart | ChatResponseCodeCitationPart | ChatResponseReferencePart2 | ChatResponseMovePart | ChatResponseExtensionsPart | ChatResponsePullRequestPart | ChatPrepareToolInvocationPart | ChatToolInvocationPart | ChatResponseMultiDiffPart; export class ChatResponseWarningPart { value: MarkdownString; constructor(value: string | MarkdownString);