Chat participant API polishing (#212757)

API polishing
This commit is contained in:
Rob Lourens
2024-05-14 17:47:55 -07:00
committed by GitHub
parent 7415be2f47
commit 0d64170259
5 changed files with 152 additions and 64 deletions
@@ -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);
@@ -2351,10 +2351,13 @@ export namespace ChatResponseFilesPart {
export namespace ChatResponseAnchorPart {
export function from(part: vscode.ChatResponseAnchorPart): Dto<IChatContentInlineReference> {
// 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(<vscode.Location>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');
+3 -3
View File
@@ -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,
) { }
}
+119 -48
View File
@@ -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<ChatResponseMarkdownPart | ChatResponseFileTreePart | ChatResponseAnchorPart | ChatResponseCommandButtonPart>, 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<ChatRequestTurn | ChatResponseTurn>;
}
@@ -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<ChatResultFeedback>;
/**
* 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);
}
@@ -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<ChatResponseWarningPart | ChatResponseReferencePart>) => Thenable<string | void>): ChatResponseStream;
progress(value: string, task?: (progress: Progress<ChatResponseWarningPart | ChatResponseReferencePart>) => Thenable<string | void>): 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.
*/