diff --git a/src/vs/workbench/api/common/extHostChatAgents2.ts b/src/vs/workbench/api/common/extHostChatAgents2.ts index 8e00dbbccd0..86518eac57a 100644 --- a/src/vs/workbench/api/common/extHostChatAgents2.ts +++ b/src/vs/workbench/api/common/extHostChatAgents2.ts @@ -22,7 +22,7 @@ import { CommandsConverter, ExtHostCommands } from 'vs/workbench/api/common/extH import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters'; import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; import { ChatAgentLocation, IChatAgentRequest, IChatAgentResult } from 'vs/workbench/contrib/chat/common/chatAgents'; -import { IChatContentReference, IChatFollowup, IChatUserActionEvent, ChatAgentVoteDirection } from 'vs/workbench/contrib/chat/common/chatService'; +import { IChatContentReference, IChatFollowup, IChatUserActionEvent, ChatAgentVoteDirection, IChatResponseErrorDetails } from 'vs/workbench/contrib/chat/common/chatService'; import { checkProposedApiEnabled, isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import { Dto } from 'vs/workbench/services/extensions/common/proxyIdentifier'; import type * as vscode from 'vscode'; @@ -318,7 +318,14 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS return { errorDetails: { message: msg }, timings: stream.timings }; } } - return { errorDetails: result?.errorDetails, timings: stream.timings, metadata: result?.metadata }; + let errorDetails: IChatResponseErrorDetails | undefined; + if (result?.errorDetails) { + errorDetails = { + ...result.errorDetails, + responseIsIncomplete: true + }; + } + return { errorDetails, timings: stream.timings, metadata: result?.metadata } satisfies IChatAgentResult; }), token); } catch (e) { this._logService.error(e, agent.extension); diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index e4031e0b167..dcfbaba32ef 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -2351,10 +2351,13 @@ export namespace ChatResponseFilesPart { export namespace ChatResponseAnchorPart { export function from(part: vscode.ChatResponseAnchorPart): Dto { + // Work around type-narrowing confusion between vscode.Uri and URI + const isUri = (thing: unknown): thing is vscode.Uri => URI.isUri(thing); + return { kind: 'inlineReference', name: part.title, - inlineReference: !URI.isUri(part.value) ? Location.from(part.value) : part.value + inlineReference: isUri(part.value) ? part.value : Location.from(part.value) }; } @@ -2566,7 +2569,7 @@ export namespace ChatLocation { } export namespace ChatAgentValueReference { - export function to(variable: IChatRequestVariableEntry): vscode.ChatValueReference { + export function to(variable: IChatRequestVariableEntry): vscode.ChatPromptReference { const value = variable.value; if (!value) { throw new Error('Invalid value reference'); diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index b69486af399..8ba1eae8425 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4361,9 +4361,9 @@ export class ChatResponseFileTreePart { } export class ChatResponseAnchorPart { - value: vscode.Uri | vscode.Location | vscode.SymbolInformation; + value: vscode.Uri | vscode.Location; title?: string; - constructor(value: vscode.Uri | vscode.Location | vscode.SymbolInformation, title?: string) { + constructor(value: vscode.Uri | vscode.Location, title?: string) { this.value = value; this.title = title; } @@ -4425,7 +4425,7 @@ export class ChatRequestTurn implements vscode.ChatRequestTurn { constructor( readonly prompt: string, readonly command: string | undefined, - readonly references: vscode.ChatValueReference[], + readonly references: vscode.ChatPromptReference[], readonly participant: string, ) { } } diff --git a/src/vscode-dts/vscode.proposed.chatParticipant.d.ts b/src/vscode-dts/vscode.proposed.chatParticipant.d.ts index 66e943c4330..9ace1a09551 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipant.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipant.d.ts @@ -32,9 +32,12 @@ declare module 'vscode' { /** * The references that were used in this message. */ - readonly references: ChatValueReference[]; + readonly references: ChatPromptReference[]; - private constructor(prompt: string, command: string | undefined, references: ChatValueReference[], participant: string); + /** + * @hidden + */ + private constructor(prompt: string, command: string | undefined, references: ChatPromptReference[], participant: string); } /** @@ -61,12 +64,18 @@ declare module 'vscode' { */ readonly command?: string; + /** + * @hidden + */ private constructor(response: ReadonlyArray, result: ChatResult, participant: string); } + /** + * Extra context passed to a participant. + */ export interface ChatContext { /** - * All of the chat messages so far in the current chat session. + * All of the chat messages so far in the current chat session. Currently, only chat messages for the current participant are included. */ readonly history: ReadonlyArray; } @@ -80,16 +89,6 @@ declare module 'vscode' { */ message: string; - /** - * If partial markdown content was sent over the {@link ChatRequestHandler handler}'s response stream before the response terminated, then this flag - * can be set to true and it will be rendered with incomplete markdown features patched up. - * - * For example, if the response terminated after sending part of a triple-backtick code block, then the editor will - * render it as a complete code block. - */ - // TODO@API: consider to have this always on, the presence of an error is a good indicator - responseIsIncomplete?: boolean; - /** * If set to true, the response will be partly blurred out. */ @@ -229,26 +228,19 @@ declare module 'vscode' { onDidReceiveFeedback: Event; /** - * Dispose this participant and free resources + * Dispose this participant and free resources. */ dispose(): void; } - export interface ChatValueReference { + export interface ChatPromptReference { /** - * A unique identifier for this reference. + * A unique identifier for this kind of reference. */ readonly id: string; /** - * The name of the reference. - * TODO@API should name be provided at all, or only ID? - */ - // TODO@API nuke it, add when needed - readonly name: string; - - /** - * The start and end index of the reference in the {@link ChatRequest.prompt prompt}. When undefined, the + * The start and end index of the reference in the {@link ChatRequest.prompt prompt}. When undefined, the reference was not part of the prompt text. * * *Note* that the indices take the leading `#`-character into account which means they can * used to modify the prompt as-is. @@ -282,18 +274,16 @@ declare module 'vscode' { */ readonly command: string | undefined; - /** * The list of references and their values that are referenced in the prompt. * - * *Note* that the prompt contains varibale references as authored and that it is up to the participant + * *Note* that the prompt contains references as authored and that it is up to the participant * to further modify the prompt, for instance by inlining reference values or creating links to * headings which contain the resolved values. References are sorted in reverse by their range * in the prompt. That means the last reference in the prompt is the first in this list. This simplifies * string-manipulation of the prompt. */ - // TODO@API: name ChatRequestReference, ChatPromptReference - readonly references: readonly ChatValueReference[]; + readonly references: readonly ChatPromptReference[]; } /** @@ -301,7 +291,6 @@ declare module 'vscode' { * which will be rendered in an appropriate way in the chat view. A participant can use the helper method for the type of content it wants to return, or it * can instantiate a {@link ChatResponsePart} and use the generic {@link ChatResponseStream.push} method to return it. */ - // TODO@API make them return void export interface ChatResponseStream { /** * Push a markdown part to this stream. Short-hand for @@ -309,48 +298,43 @@ declare module 'vscode' { * * @see {@link ChatResponseStream.push} * @param value A markdown string or a string that should be interpreted as markdown. The boolean form of {@link MarkdownString.isTrusted} is NOT supported. - * @returns This stream. */ - markdown(value: string | MarkdownString): ChatResponseStream; + markdown(value: string | MarkdownString): void; /** * Push an anchor part to this stream. Short-hand for * `push(new ChatResponseAnchorPart(value, title))`. * An anchor is an inline reference to some type of resource. * - * @param value A uri or location - * @param title An optional title that is rendered with value - * @returns This stream. + * @param value A uri, location, or symbol information. + * @param title An optional title that is rendered with value. */ - anchor(value: Uri | Location, title?: string): ChatResponseStream; + anchor(value: Uri | Location, title?: string): void; /** * Push a command button part to this stream. Short-hand for * `push(new ChatResponseCommandButtonPart(value, title))`. * * @param command A Command that will be executed when the button is clicked. - * @returns This stream. */ - button(command: Command): ChatResponseStream; + button(command: Command): void; /** * Push a filetree part to this stream. Short-hand for * `push(new ChatResponseFileTreePart(value))`. * * @param value File tree data. - * @param baseUri The base uri to which this file tree is relative to. - * @returns This stream. + * @param baseUri The base uri to which this file tree is relative. */ - filetree(value: ChatResponseFileTree[], baseUri: Uri): ChatResponseStream; + filetree(value: ChatResponseFileTree[], baseUri: Uri): void; /** * Push a progress part to this stream. Short-hand for * `push(new ChatResponseProgressPart(value))`. * * @param value A progress message - * @returns This stream. */ - progress(value: string): ChatResponseStream; + progress(value: string): void; /** * Push a reference to this stream. Short-hand for @@ -360,57 +344,144 @@ declare module 'vscode' { * * @param value A uri or location * @param iconPath Icon for the reference shown in UI - * @returns This stream. */ - reference(value: Uri | Location, iconPath?: Uri | ThemeIcon | { light: Uri; dark: Uri }): ChatResponseStream; + reference(value: Uri | Location, iconPath?: Uri | ThemeIcon | { light: Uri; dark: Uri }): void; /** * Pushes a part to this stream. * * @param part A response part, rendered or metadata */ - push(part: ChatResponsePart): ChatResponseStream; + push(part: ChatResponsePart): void; } + /** + * Represents a part of a chat response that is formatted as Markdown. + */ export class ChatResponseMarkdownPart { + /** + * A markdown string or a string that should be interpreted as markdown. + */ value: MarkdownString; /** - * @param value Note: The boolean form of {@link MarkdownString.isTrusted} is NOT supported. + * Create a new ChatResponseMarkdownPart. + * + * @param value A markdown string or a string that should be interpreted as markdown. The boolean form of {@link MarkdownString.isTrusted} is NOT supported. */ constructor(value: string | MarkdownString); } + /** + * Represents a file tree structure in a chat response. + */ export interface ChatResponseFileTree { + /** + * The name of the file or directory. + */ name: string; + + /** + * An array of child file trees, if the current file tree is a directory. + */ children?: ChatResponseFileTree[]; } + /** + * Represents a part of a chat response that is a file tree. + */ export class ChatResponseFileTreePart { + /** + * File tree data. + */ value: ChatResponseFileTree[]; + + /** + * The base uri to which this file tree is relative + */ baseUri: Uri; + + /** + * Create a new ChatResponseFileTreePart. + * @param value File tree data. + * @param baseUri The base uri to which this file tree is relative. + */ constructor(value: ChatResponseFileTree[], baseUri: Uri); } + /** + * Represents a part of a chat response that is an anchor, that is rendered as a link to a target. + */ export class ChatResponseAnchorPart { - value: Uri | Location | SymbolInformation; + /** + * The target of this anchor. + */ + value: Uri | Location; + + /** + * An optional title that is rendered with value. + */ title?: string; - constructor(value: Uri | Location | SymbolInformation, title?: string); + + /** + * Create a new ChatResponseAnchorPart. + * @param value A uri or location. + * @param title An optional title that is rendered with value. + */ + constructor(value: Uri | Location, title?: string); } + /** + * Represents a part of a chat response that is a progress message. + */ export class ChatResponseProgressPart { + /** + * The progress message + */ value: string; + + /** + * Create a new ChatResponseProgressPart. + * @param value A progress message + */ constructor(value: string); } + /** + * Represents a part of a chat response that is a reference, rendered separately from the content. + */ export class ChatResponseReferencePart { + /** + * The reference target. + */ value: Uri | Location; + + /** + * The icon for the reference. + */ iconPath?: Uri | ThemeIcon | { light: Uri; dark: Uri }; + + /** + * Create a new ChatResponseReferencePart. + * @param value A uri or location + * @param iconPath Icon for the reference shown in UI + */ constructor(value: Uri | Location, iconPath?: Uri | ThemeIcon | { light: Uri; dark: Uri }); } + /** + * Represents a part of a chat response that is a button that executes a command. + */ export class ChatResponseCommandButtonPart { + /** + * The command that will be executed when the button is clicked. + */ value: Command; + + /** + * Create a new ChatResponseCommandButtonPart. + * @param value A Command that will be executed when the button is clicked. + */ constructor(value: Command); } diff --git a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts index c34b97baace..13d98419f84 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts @@ -132,12 +132,12 @@ declare module 'vscode' { * @param task If provided, a task to run while the progress is displayed. When the Thenable resolves, the progress will be marked complete in the UI, and the progress message will be updated to the resolved string if one is specified. * @returns This stream. */ - progress(value: string, task?: (progress: Progress) => Thenable): ChatResponseStream; + progress(value: string, task?: (progress: Progress) => Thenable): void; - textEdit(target: Uri, edits: TextEdit | TextEdit[]): ChatResponseStream; - markdownWithVulnerabilities(value: string | MarkdownString, vulnerabilities: ChatVulnerability[]): ChatResponseStream; - detectedParticipant(participant: string, command?: ChatCommand): ChatResponseStream; - push(part: ChatResponsePart | ChatResponseTextEditPart | ChatResponseDetectedParticipantPart | ChatResponseWarningPart | ChatResponseProgressPart2): ChatResponseStream; + textEdit(target: Uri, edits: TextEdit | TextEdit[]): void; + markdownWithVulnerabilities(value: string | MarkdownString, vulnerabilities: ChatVulnerability[]): void; + detectedParticipant(participant: string, command?: ChatCommand): void; + push(part: ChatResponsePart | ChatResponseTextEditPart | ChatResponseDetectedParticipantPart | ChatResponseWarningPart | ChatResponseProgressPart2): void; /** * Show an inline message in the chat view asking the user to confirm an action. @@ -149,7 +149,7 @@ declare module 'vscode' { * TODO@API should this be MarkdownString? * TODO@API should actually be a more generic function that takes an array of buttons */ - confirmation(title: string, message: string, data: any): ChatResponseStream; + confirmation(title: string, message: string, data: any): void; /** * Push a warning to this stream. Short-hand for @@ -158,11 +158,11 @@ declare module 'vscode' { * @param message A warning message * @returns This stream. */ - warning(message: string | MarkdownString): ChatResponseStream; + warning(message: string | MarkdownString): void; - reference(value: Uri | Location | { variableName: string; value?: Uri | Location }, iconPath?: Uri | ThemeIcon | { light: Uri; dark: Uri }): ChatResponseStream; + reference(value: Uri | Location | { variableName: string; value?: Uri | Location }, iconPath?: Uri | ThemeIcon | { light: Uri; dark: Uri }): void; - push(part: ExtendedChatResponsePart): ChatResponseStream; + push(part: ExtendedChatResponsePart): void; } /** @@ -300,6 +300,13 @@ declare module 'vscode' { readonly action: ChatCopyAction | ChatInsertAction | ChatTerminalAction | ChatCommandAction | ChatFollowupAction | ChatBugReportAction | ChatEditorAction; } + export interface ChatPromptReference { + /** + * TODO Needed for now to drive the variableName-type reference, but probably both of these should go away in the future. + */ + readonly name: string; + } + /** * The detail level of this chat variable value. */