From b8292ab7f2e9f64142e1713e8c8fcc836d30daad Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 1 May 2024 16:14:54 +0000 Subject: [PATCH] Replace ChatResolvedVariable with ChatValueReference (#211665) * Replace ChatResolvedVariable with ChatValueReference Participant API #199908 * Fix integration test * any -> unknown --- .../src/singlefolder-tests/chat.test.ts | 2 +- .../api/common/extHostChatAgents2.ts | 2 +- .../api/common/extHostTypeConverters.ts | 15 ++++-- src/vs/workbench/api/common/extHostTypes.ts | 2 +- .../vscode.proposed.chatParticipant.d.ts | 54 ++++--------------- ...ode.proposed.chatParticipantAdditions.d.ts | 24 +++++++++ 6 files changed, 48 insertions(+), 51 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts index 8fd84382944..19de2b62057 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts @@ -81,7 +81,7 @@ suite('chat', () => { commands.executeCommand('workbench.action.chat.open', { query: '@participant hi #myVar' }); const request = await deferred.p; assert.strictEqual(request.prompt, 'hi #myVar'); - assert.strictEqual(request.variables[0].values[0].value, 'myValue'); + assert.strictEqual(request.variables[0].value, 'myValue'); }); test('result metadata is returned to the followup provider', async () => { diff --git a/src/vs/workbench/api/common/extHostChatAgents2.ts b/src/vs/workbench/api/common/extHostChatAgents2.ts index b53f624362e..82a25240fe4 100644 --- a/src/vs/workbench/api/common/extHostChatAgents2.ts +++ b/src/vs/workbench/api/common/extHostChatAgents2.ts @@ -294,7 +294,7 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS { ...ehResult, metadata: undefined }; // REQUEST turn - res.push(new extHostTypes.ChatRequestTurn(h.request.message, h.request.command, h.request.variables.variables.map(typeConvert.ChatAgentResolvedVariable.to), h.request.agentId)); + res.push(new extHostTypes.ChatRequestTurn(h.request.message, h.request.command, h.request.variables.variables.map(typeConvert.ChatAgentValueReference.to), h.request.agentId)); // RESPONSE turn const parts = coalesce(h.response.map(r => typeConvert.ChatResponsePart.toContent(r, this.commands.converter))); diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 057f30aaf17..bb32ca47812 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -2595,7 +2595,7 @@ export namespace ChatAgentRequest { command: request.command, attempt: request.attempt ?? 0, enableCommandDetection: request.enableCommandDetection ?? true, - variables: request.variables.variables.map(ChatAgentResolvedVariable.to), + variables: request.variables.variables.map(ChatAgentValueReference.to), location: ChatLocation.to(request.location), }; } @@ -2612,12 +2612,17 @@ export namespace ChatLocation { } } -export namespace ChatAgentResolvedVariable { - export function to(request: IChatRequestVariableEntry): vscode.ChatResolvedVariable { +export namespace ChatAgentValueReference { + export function to(request: IChatRequestVariableEntry): vscode.ChatValueReference { + const value = request.values[0]?.value; + if (!value) { + throw new Error('Invalid value reference'); + } + return { name: request.name, - range: request.range && [request.range.start, request.range.endExclusive], - values: request.values.map(ChatVariable.to) + range: (request.range && [request.range.start, request.range.endExclusive])!, // TODO + value: isUriComponents(value) ? URI.revive(value) : value, }; } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 551e1289cc9..362ae439933 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4391,7 +4391,7 @@ export class ChatRequestTurn implements vscode.ChatRequestTurn { constructor( readonly prompt: string, readonly command: string | undefined, - readonly variables: vscode.ChatResolvedVariable[], + readonly variables: vscode.ChatValueReference[], readonly participant: string, ) { } } diff --git a/src/vscode-dts/vscode.proposed.chatParticipant.d.ts b/src/vscode-dts/vscode.proposed.chatParticipant.d.ts index d22f0b8e58b..be004ff4a91 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipant.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipant.d.ts @@ -30,12 +30,12 @@ declare module 'vscode' { readonly command?: string; /** - * The variables that were referenced in this message. - * TODO@API ensure that this will be compatible with future changes to chat variables. + * The variables that were used in this message. + * TODO@API rename to `references`? */ - readonly variables: ChatResolvedVariable[]; + readonly variables: ChatValueReference[]; - private constructor(prompt: string, command: string | undefined, variables: ChatResolvedVariable[], participant: string); + private constructor(prompt: string, command: string | undefined, variables: ChatValueReference[], participant: string); } /** @@ -234,15 +234,10 @@ declare module 'vscode' { dispose(): void; } - /** - * A resolved variable value is a name-value pair as well as the range in the prompt where a variable was used. - */ - export interface ChatResolvedVariable { + export interface ChatValueReference { /** - * The name of the variable. - * - * *Note* that the name doesn't include the leading `#`-character, - * e.g `selection` for `#selection`. + * The name of the reference. + * TODO@API How to handle name conflicts? Need id vs name? */ readonly name: string; @@ -252,13 +247,12 @@ declare module 'vscode' { * *Note* that the indices take the leading `#`-character into account which means they can * used to modify the prompt as-is. */ - readonly range?: [start: number, end: number]; + readonly range: [start: number, end: number]; - // TODO@API decouple of resolve API, use `value: string | Uri | (maybe) unknown?` /** - * The values of the variable. Can be an empty array if the variable doesn't currently have a value. + * The value of this reference. The `string | Uri | Location` types are used today, but this could expand in the future. */ - readonly values: ChatVariableValue[]; + readonly value: string | Uri | Location | unknown; } export interface ChatRequest { @@ -287,7 +281,7 @@ declare module 'vscode' { * in the prompt. That means the last variable in the prompt is the first in this list. This simplifies * string-manipulation of the prompt. */ - readonly variables: readonly ChatResolvedVariable[]; + readonly variables: readonly ChatValueReference[]; } /** @@ -424,30 +418,4 @@ declare module 'vscode' { */ export function createChatParticipant(id: string, handler: ChatRequestHandler): ChatParticipant; } - - /** - * The detail level of this chat variable value. - */ - export enum ChatVariableLevel { - Short = 1, - Medium = 2, - Full = 3 - } - - export interface ChatVariableValue { - /** - * The detail level of this chat variable value. If possible, variable resolvers should try to offer shorter values that will consume fewer tokens in an LLM prompt. - */ - level: ChatVariableLevel; - - /** - * The variable's value, which can be included in an LLM prompt as-is, or the chat participant may decide to read the value and do something else with it. - */ - value: string | Uri; - - /** - * A description of this value, which could be provided to the LLM as a hint. - */ - description?: string; - } } diff --git a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts index 875b53f51e2..a827edc123d 100644 --- a/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts @@ -209,7 +209,31 @@ declare module 'vscode' { readonly action: ChatCopyAction | ChatInsertAction | ChatTerminalAction | ChatCommandAction | ChatFollowupAction | ChatBugReportAction | ChatEditorAction; } + /** + * The detail level of this chat variable value. + */ + export enum ChatVariableLevel { + Short = 1, + Medium = 2, + Full = 3 + } + export interface ChatVariableValue { + /** + * The detail level of this chat variable value. If possible, variable resolvers should try to offer shorter values that will consume fewer tokens in an LLM prompt. + */ + level: ChatVariableLevel; + + /** + * The variable's value, which can be included in an LLM prompt as-is, or the chat participant may decide to read the value and do something else with it. + */ + value: string | Uri; + + /** + * A description of this value, which could be provided to the LLM as a hint. + */ + description?: string; + /** * An optional type tag for extensions to communicate the kind of the variable. An extension might use it to interpret the shape of `value`. */