Skip to content

Commit a1f2ea3

Browse files
authored
Move from chat variable values array to a single value (#211897)
* Move from chat variable values array to a single value * Update
1 parent f8b1159 commit a1f2ea3

17 files changed

+57
-120
lines changed

src/vs/workbench/api/browser/mainThreadChatAgents2.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export class MainThreadChatAgents2 extends Disposable implements MainThreadChatA
212212
kind: CompletionItemKind.Text,
213213
detail: v.detail,
214214
documentation: v.documentation,
215-
command: { id: AddDynamicVariableAction.ID, title: '', arguments: [{ widget, range: rangeAfterInsert, variableData: revive(v.values), command: v.command } satisfies IAddDynamicVariableContext] }
215+
command: { id: AddDynamicVariableAction.ID, title: '', arguments: [{ widget, range: rangeAfterInsert, variableData: revive(v.value) as any, command: v.command } satisfies IAddDynamicVariableContext] }
216216
} satisfies CompletionItem;
217217
});
218218

src/vs/workbench/api/browser/mainThreadChatVariables.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ export class MainThreadChatVariables implements MainThreadChatVariablesShape {
3131
const registration = this._chatVariablesService.registerVariable(data, async (messageText, _arg, model, progress, token) => {
3232
const varRequestId = `${model.sessionId}-${handle}`;
3333
this._pendingProgress.set(varRequestId, progress);
34-
const result = revive<IChatRequestVariableValue[]>(await this._proxy.$resolveVariable(handle, varRequestId, messageText, token));
34+
const result = revive<IChatRequestVariableValue>(await this._proxy.$resolveVariable(handle, varRequestId, messageText, token));
3535

3636
this._pendingProgress.delete(varRequestId);
37-
return result;
37+
return result as any; // 'revive' type signature doesn't like this type for some reason
3838
});
3939
this._variables.set(handle, registration);
4040
}

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,7 @@ export interface MainThreadChatAgentsShape2 extends IDisposable {
12351235
export interface IChatAgentCompletionItem {
12361236
insertText?: string;
12371237
label: string | languages.CompletionItemLabel;
1238-
values: IChatRequestVariableValueDto[];
1238+
value: IChatRequestVariableValueDto;
12391239
detail?: string;
12401240
documentation?: string | IMarkdownString;
12411241
command?: ICommandDto;
@@ -1273,7 +1273,7 @@ export interface MainThreadChatVariablesShape extends IDisposable {
12731273
export type IChatRequestVariableValueDto = Dto<IChatRequestVariableValue>;
12741274

12751275
export interface ExtHostChatVariablesShape {
1276-
$resolveVariable(handle: number, requestId: string, messageText: string, token: CancellationToken): Promise<IChatRequestVariableValueDto[] | undefined>;
1276+
$resolveVariable(handle: number, requestId: string, messageText: string, token: CancellationToken): Promise<IChatRequestVariableValueDto | undefined>;
12771277
}
12781278

12791279
export interface MainThreadInlineChatShape extends IDisposable {

src/vs/workbench/api/common/extHostChatVariables.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class ExtHostChatVariables implements ExtHostChatVariablesShape {
2525
this._proxy = mainContext.getProxy(MainContext.MainThreadChatVariables);
2626
}
2727

28-
async $resolveVariable(handle: number, requestId: string, messageText: string, token: CancellationToken): Promise<IChatRequestVariableValue[] | undefined> {
28+
async $resolveVariable(handle: number, requestId: string, messageText: string, token: CancellationToken): Promise<IChatRequestVariableValue | undefined> {
2929
const item = this._resolver.get(handle);
3030
if (!item) {
3131
return undefined;
@@ -35,13 +35,15 @@ export class ExtHostChatVariables implements ExtHostChatVariablesShape {
3535
checkProposedApiEnabled(item.extension, 'chatParticipantAdditions');
3636
const stream = new ChatVariableResolverResponseStream(requestId, this._proxy);
3737
const value = await item.resolver.resolve2(item.data.name, { prompt: messageText }, stream.apiObject, token);
38-
if (value) {
39-
return value.map(typeConvert.ChatVariable.from);
38+
39+
// Temp, ignoring other returned values to convert the array into a single value
40+
if (value && value[0]) {
41+
return value[0].value;
4042
}
4143
} else {
4244
const value = await item.resolver.resolve(item.data.name, { prompt: messageText }, token);
43-
if (value) {
44-
return value.map(typeConvert.ChatVariable.from);
45+
if (value && value[0]) {
46+
return value[0].value;
4547
}
4648
}
4749
} catch (err) {

src/vs/workbench/api/common/extHostTypeConverters.ts

Lines changed: 3 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Mimes } from 'vs/base/common/mime';
1616
import { cloneAndChange } from 'vs/base/common/objects';
1717
import { IPrefixTreeNode, WellDefinedPrefixTree } from 'vs/base/common/prefixTree';
1818
import { basename } from 'vs/base/common/resources';
19+
import { ThemeIcon } from 'vs/base/common/themables';
1920
import { isDefined, isEmptyObject, isNumber, isString, isUndefinedOrNull } from 'vs/base/common/types';
2021
import { URI, UriComponents, isUriComponents } from 'vs/base/common/uri';
2122
import { IURITransformer } from 'vs/base/common/uriIpc';
@@ -40,7 +41,6 @@ import { IViewBadge } from 'vs/workbench/common/views';
4041
import { ChatAgentLocation, IChatAgentRequest, IChatAgentResult } from 'vs/workbench/contrib/chat/common/chatAgents';
4142
import { IChatRequestVariableEntry } from 'vs/workbench/contrib/chat/common/chatModel';
4243
import { IChatAgentDetection, IChatAgentMarkdownContentWithVulnerability, IChatCommandButton, IChatContentInlineReference, IChatContentReference, IChatFollowup, IChatMarkdownContent, IChatProgressMessage, IChatTextEdit, IChatTreeData, IChatUserActionEvent, IChatWarningMessage } from 'vs/workbench/contrib/chat/common/chatService';
43-
import { IChatRequestVariableValue } from 'vs/workbench/contrib/chat/common/chatVariables';
4444
import * as chatProvider from 'vs/workbench/contrib/chat/common/languageModels';
4545
import { DebugTreeItemCollapsibleState, IDebugVisualizationTreeItem } from 'vs/workbench/contrib/debug/common/debug';
4646
import { IInlineChatCommandFollowup, IInlineChatFollowup, IInlineChatReplyFollowup, InlineChatResponseFeedbackKind } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
@@ -54,7 +54,6 @@ import { ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/ed
5454
import { Dto } from 'vs/workbench/services/extensions/common/proxyIdentifier';
5555
import type * as vscode from 'vscode';
5656
import * as types from './extHostTypes';
57-
import { ThemeIcon } from 'vs/base/common/themables';
5857

5958
export namespace Command {
6059

@@ -2286,58 +2285,6 @@ export namespace LanguageModelMessage {
22862285
}
22872286
}
22882287

2289-
export namespace ChatVariable {
2290-
export function objectTo(variableObject: Record<string, IChatRequestVariableValue[]>): Record<string, vscode.ChatVariableValue[]> {
2291-
const result: Record<string, vscode.ChatVariableValue[]> = {};
2292-
for (const key of Object.keys(variableObject)) {
2293-
result[key] = variableObject[key].map(ChatVariable.to);
2294-
}
2295-
2296-
return result;
2297-
}
2298-
2299-
export function to(variable: IChatRequestVariableValue): vscode.ChatVariableValue {
2300-
return {
2301-
level: ChatVariableLevel.to(variable.level),
2302-
kind: variable.kind,
2303-
value: isUriComponents(variable.value) ? URI.revive(variable.value) : variable.value,
2304-
description: variable.description
2305-
};
2306-
}
2307-
2308-
export function from(variable: vscode.ChatVariableValue): IChatRequestVariableValue {
2309-
return {
2310-
level: ChatVariableLevel.from(variable.level),
2311-
kind: variable.kind,
2312-
value: variable.value,
2313-
description: variable.description
2314-
};
2315-
}
2316-
}
2317-
2318-
export namespace ChatVariableLevel {
2319-
2320-
2321-
export function to(level: 'short' | 'medium' | 'full'): vscode.ChatVariableLevel {
2322-
switch (level) {
2323-
case 'short': return types.ChatVariableLevel.Short;
2324-
case 'medium': return types.ChatVariableLevel.Medium;
2325-
case 'full':
2326-
default:
2327-
return types.ChatVariableLevel.Full;
2328-
}
2329-
}
2330-
export function from(level: vscode.ChatVariableLevel): 'short' | 'medium' | 'full' {
2331-
switch (level) {
2332-
case types.ChatVariableLevel.Short: return 'short';
2333-
case types.ChatVariableLevel.Medium: return 'medium';
2334-
case types.ChatVariableLevel.Full:
2335-
default:
2336-
return 'full';
2337-
}
2338-
}
2339-
}
2340-
23412288
export namespace InteractiveEditorResponseFeedbackKind {
23422289

23432290
export function to(kind: InlineChatResponseFeedbackKind): vscode.InteractiveEditorResponseFeedbackKind {
@@ -2628,7 +2575,7 @@ export namespace ChatLocation {
26282575

26292576
export namespace ChatAgentValueReference {
26302577
export function to(request: IChatRequestVariableEntry): vscode.ChatValueReference {
2631-
const value = request.values[0]?.value;
2578+
const value = request.value;
26322579
if (!value) {
26332580
throw new Error('Invalid value reference');
26342581
}
@@ -2645,7 +2592,7 @@ export namespace ChatAgentCompletionItem {
26452592
export function from(item: vscode.ChatCompletionItem, commandsConverter: CommandsConverter, disposables: DisposableStore): extHostProtocol.IChatAgentCompletionItem {
26462593
return {
26472594
label: item.label,
2648-
values: item.values.map(ChatVariable.from),
2595+
value: item.values[0].value,
26492596
insertText: item.insertText,
26502597
detail: item.detail,
26512598
documentation: item.documentation,

src/vs/workbench/contrib/chat/browser/chatMarkdownDecorationsRenderer.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ export class ChatMarkdownDecorationsRenderer {
4747

4848
result += `[${text}](${agentRefUrl}?${encodeURIComponent(part.agent.id)})`;
4949
} else {
50-
const uri = part instanceof ChatRequestDynamicVariablePart && part.data.map(d => d.value).find((d): d is URI => d instanceof URI)
51-
|| undefined;
50+
const uri = part instanceof ChatRequestDynamicVariablePart && part.data instanceof URI ?
51+
part.data :
52+
undefined;
5253
const title = uri ? encodeURIComponent(this.labelService.getUriLabel(uri, { relative: true })) :
5354
part instanceof ChatRequestAgentPart ? part.agent.id :
5455
'';

src/vs/workbench/contrib/chat/browser/chatVariables.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,20 @@ export class ChatVariablesService implements IChatVariablesService {
4747
}
4848
progress(item);
4949
};
50-
jobs.push(data.resolver(prompt.text, part.variableArg, model, variableProgressCallback, token).then(values => {
51-
resolvedVariables[i] = { name: part.variableName, range: part.range, values: values ?? [], references };
50+
jobs.push(data.resolver(prompt.text, part.variableArg, model, variableProgressCallback, token).then(value => {
51+
if (value) {
52+
resolvedVariables[i] = { name: part.variableName, range: part.range, value, references };
53+
}
5254
}).catch(onUnexpectedExternalError));
5355
}
5456
} else if (part instanceof ChatRequestDynamicVariablePart) {
55-
resolvedVariables[i] = { name: part.referenceText, range: part.range, values: part.data };
57+
resolvedVariables[i] = { name: part.referenceText, range: part.range, value: part.data };
5658
}
5759
});
5860

5961
await Promise.allSettled(jobs);
6062

61-
resolvedVariables = coalesce(resolvedVariables);
63+
resolvedVariables = coalesce<IChatRequestVariableEntry>(resolvedVariables);
6264

6365
// "reverse", high index first so that replacement is simple
6466
resolvedVariables.sort((a, b) => b.range!.start - a.range!.start);
@@ -68,13 +70,13 @@ export class ChatVariablesService implements IChatVariablesService {
6870
};
6971
}
7072

71-
async resolveVariable(variableName: string, promptText: string, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableValue[]> {
73+
async resolveVariable(variableName: string, promptText: string, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableValue | undefined> {
7274
const data = this._resolver.get(variableName.toLowerCase());
7375
if (!data) {
74-
return Promise.resolve([]);
76+
return undefined;
7577
}
7678

77-
return (await data.resolver(promptText, undefined, model, progress, token)) ?? [];
79+
return (await data.resolver(promptText, undefined, model, progress, token));
7880
}
7981

8082
hasVariable(name: string): boolean {

src/vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,11 @@ export class ChatDynamicVariableModel extends Disposable implements IChatWidgetC
106106
}
107107

108108
private getHoverForReference(ref: IDynamicVariable): string | IMarkdownString {
109-
const value = ref.data[0];
110-
if (URI.isUri(value.value)) {
111-
return new MarkdownString(this.labelService.getUriLabel(value.value, { relative: true }));
109+
const value = ref.data;
110+
if (URI.isUri(value)) {
111+
return new MarkdownString(this.labelService.getUriLabel(value, { relative: true }));
112112
} else {
113-
return value.value.toString();
113+
return (value as any).toString();
114114
}
115115
}
116116
}
@@ -209,7 +209,7 @@ export class SelectAndInsertFileAction extends Action2 {
209209

210210
context.widget.getContrib<ChatDynamicVariableModel>(ChatDynamicVariableModel.ID)?.addReference({
211211
range: { startLineNumber: range.startLineNumber, startColumn: range.startColumn, endLineNumber: range.endLineNumber, endColumn: range.startColumn + text.length },
212-
data: [{ level: 'full', value: resource }]
212+
data: resource
213213
});
214214
}
215215
}
@@ -218,7 +218,7 @@ registerAction2(SelectAndInsertFileAction);
218218
export interface IAddDynamicVariableContext {
219219
widget: IChatWidget;
220220
range: IRange;
221-
variableData: IChatRequestVariableValue[];
221+
variableData: IChatRequestVariableValue;
222222
command?: Command;
223223
}
224224

src/vs/workbench/contrib/chat/browser/contrib/chatHistoryVariables.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ChatHistoryVariables extends Disposable {
2626
return undefined;
2727
}
2828

29-
return [{ level: 'full', value: response.response.asString() }];
29+
return response.response.asString();
3030
}));
3131
}
3232
}

src/vs/workbench/contrib/chat/common/chatModel.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,10 @@ import { ChatRequestTextPart, IParsedChatRequest, getPromptText, reviveParsedCha
2323
import { IChatAgentMarkdownContentWithVulnerability, IChatCommandButton, IChatContentInlineReference, IChatContentReference, IChatFollowup, IChatMarkdownContent, IChatProgress, IChatProgressMessage, IChatResponseProgressFileTreeData, IChatTextEdit, IChatTreeData, IChatUsedContext, IChatWarningMessage, InteractiveSessionVoteDirection, isIUsedContext } from 'vs/workbench/contrib/chat/common/chatService';
2424
import { IChatRequestVariableValue } from 'vs/workbench/contrib/chat/common/chatVariables';
2525

26-
export interface IChatPromptVariableData {
27-
variables: { name: string; range: IOffsetRange; values: IChatRequestVariableValue[] }[];
28-
}
29-
3026
export interface IChatRequestVariableEntry {
3127
name: string;
3228
range?: IOffsetRange;
33-
values: IChatRequestVariableValue[];
29+
value: IChatRequestVariableValue;
3430
references?: IChatContentReference[];
3531
}
3632

src/vs/workbench/contrib/chat/common/chatParserTypes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export class ChatRequestSlashCommandPart implements IParsedChatRequestPart {
123123
export class ChatRequestDynamicVariablePart implements IParsedChatRequestPart {
124124
static readonly Kind = 'dynamic';
125125
readonly kind = ChatRequestDynamicVariablePart.Kind;
126-
constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly text: string, readonly data: IChatRequestVariableValue[]) { }
126+
constructor(readonly range: OffsetRange, readonly editorRange: IRange, readonly text: string, readonly data: IChatRequestVariableValue) { }
127127

128128
get referenceText(): string {
129129
return this.text.replace(chatVariableLeader, '');
@@ -183,7 +183,7 @@ export function reviveParsedChatRequest(serialized: IParsedChatRequest): IParsed
183183
new OffsetRange(part.range.start, part.range.endExclusive),
184184
part.editorRange,
185185
(part as ChatRequestDynamicVariablePart).text,
186-
revive((part as ChatRequestDynamicVariablePart).data)
186+
revive((part as ChatRequestDynamicVariablePart).data) as any
187187
);
188188
} else {
189189
throw new Error(`Unknown chat request part: ${part.kind}`);

src/vs/workbench/contrib/chat/common/chatServiceImpl.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { Action } from 'vs/base/common/actions';
7+
import { coalesce } from 'vs/base/common/arrays';
78
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
89
import { ErrorNoTelemetry } from 'vs/base/common/errors';
910
import { Emitter, Event } from 'vs/base/common/event';
@@ -544,8 +545,12 @@ export class ChatService extends Disposable implements IChatService {
544545
if (implicitVariablesEnabled) {
545546
const implicitVariables = agent.defaultImplicitVariables;
546547
if (implicitVariables) {
547-
const resolvedImplicitVariables = await Promise.all(implicitVariables.map(async v => ({ name: v, values: await this.chatVariablesService.resolveVariable(v, parsedRequest.text, model, progressCallback, token) } satisfies IChatRequestVariableEntry)));
548-
updatedVariableData.variables.push(...resolvedImplicitVariables);
548+
const resolvedImplicitVariables = await Promise.all(implicitVariables.map(async v => {
549+
const value = await this.chatVariablesService.resolveVariable(v, parsedRequest.text, model, progressCallback, token);
550+
return value ? { name: v, value } satisfies IChatRequestVariableEntry :
551+
undefined;
552+
}));
553+
updatedVariableData.variables.push(...coalesce(resolvedImplicitVariables));
549554
}
550555
}
551556

src/vs/workbench/contrib/chat/common/chatVariables.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
77
import { IDisposable } from 'vs/base/common/lifecycle';
88
import { URI } from 'vs/base/common/uri';
99
import { IRange } from 'vs/editor/common/core/range';
10+
import { Location } from 'vs/editor/common/languages';
1011
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
1112
import { IChatModel, IChatRequestVariableData } from 'vs/workbench/contrib/chat/common/chatModel';
1213
import { IParsedChatRequest } from 'vs/workbench/contrib/chat/common/chatParserTypes';
@@ -19,20 +20,14 @@ export interface IChatVariableData {
1920
canTakeArgument?: boolean;
2021
}
2122

22-
export interface IChatRequestVariableValue {
23-
level: 'short' | 'medium' | 'full';
24-
kind?: string;
25-
value: string | URI;
26-
description?: string;
27-
}
23+
export type IChatRequestVariableValue = string | URI | Location | unknown;
2824

2925
export type IChatVariableResolverProgress =
3026
| IChatContentReference
3127
| IChatProgressMessage;
3228

3329
export interface IChatVariableResolver {
34-
// TODO should we spec "zoom level"
35-
(messageText: string, arg: string | undefined, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableValue[] | undefined>;
30+
(messageText: string, arg: string | undefined, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableValue | undefined>;
3631
}
3732

3833
export const IChatVariablesService = createDecorator<IChatVariablesService>('IChatVariablesService');
@@ -49,10 +44,10 @@ export interface IChatVariablesService {
4944
* Resolves all variables that occur in `prompt`
5045
*/
5146
resolveVariables(prompt: IParsedChatRequest, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableData>;
52-
resolveVariable(variableName: string, promptText: string, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableValue[]>;
47+
resolveVariable(variableName: string, promptText: string, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableValue | undefined>;
5348
}
5449

5550
export interface IDynamicVariable {
5651
range: IRange;
57-
data: IChatRequestVariableValue[];
52+
data: IChatRequestVariableValue;
5853
}

src/vs/workbench/contrib/chat/test/browser/chatVariables.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ suite('ChatVariables', function () {
4141

4242
test('ChatVariables - resolveVariables', async function () {
4343

44-
const v1 = service.registerVariable({ name: 'foo', description: 'bar' }, async () => ([{ level: 'full', value: 'farboo' }]));
45-
const v2 = service.registerVariable({ name: 'far', description: 'boo' }, async () => ([{ level: 'full', value: 'farboo' }]));
44+
const v1 = service.registerVariable({ name: 'foo', description: 'bar' }, async () => 'farboo');
45+
const v2 = service.registerVariable({ name: 'far', description: 'boo' }, async () => 'farboo');
4646

4747
const parser = instantiationService.createInstance(ChatRequestParser);
4848

src/vs/workbench/contrib/chat/test/common/mockChatVariables.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class MockChatVariablesService implements IChatVariablesService {
3737
};
3838
}
3939

40-
resolveVariable(variableName: string, promptText: string, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableValue[]> {
40+
resolveVariable(variableName: string, promptText: string, model: IChatModel, progress: (part: IChatVariableResolverProgress) => void, token: CancellationToken): Promise<IChatRequestVariableValue> {
4141
throw new Error('Method not implemented.');
4242
}
4343
}

0 commit comments

Comments
 (0)