mirror of
https://github.com/Microsoft/vscode
synced 2024-10-04 02:14:06 +00:00
Get rid of history2, variables2 (#205124)
* Get rid of history2 * Remove prompt2 and variables2 * Clean up variables2/prompt2 * Fix tests * Fix ranges * Fix test
This commit is contained in:
parent
da8f671716
commit
c2316194e2
|
@ -64,8 +64,8 @@ suite('chat', () => {
|
||||||
const deferred = getDeferredForRequest();
|
const deferred = getDeferredForRequest();
|
||||||
interactive.sendInteractiveRequestToProvider('provider', { message: '@agent hi #myVar' });
|
interactive.sendInteractiveRequestToProvider('provider', { message: '@agent hi #myVar' });
|
||||||
const request = await deferred.p;
|
const request = await deferred.p;
|
||||||
assert.strictEqual(request.prompt, 'hi [#myVar](values:myVar)');
|
assert.strictEqual(request.prompt, 'hi #myVar');
|
||||||
assert.strictEqual(request.variables['myVar'][0].value, 'myValue');
|
assert.strictEqual(request.variables[0].values[0].value, 'myValue');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('result metadata is returned to the followup provider', async () => {
|
test('result metadata is returned to the followup provider', async () => {
|
||||||
|
|
|
@ -200,7 +200,7 @@ export class ExtHostChatAgents2 implements ExtHostChatAgentsShape2 {
|
||||||
const convertedHistory = await this.prepareHistoryTurns(request, context);
|
const convertedHistory = await this.prepareHistoryTurns(request, context);
|
||||||
const task = agent.invoke(
|
const task = agent.invoke(
|
||||||
typeConvert.ChatAgentRequest.to(request),
|
typeConvert.ChatAgentRequest.to(request),
|
||||||
{ history: convertedHistory, history2: convertedHistory },
|
{ history: convertedHistory },
|
||||||
stream.apiObject,
|
stream.apiObject,
|
||||||
token
|
token
|
||||||
);
|
);
|
||||||
|
@ -239,7 +239,7 @@ export class ExtHostChatAgents2 implements ExtHostChatAgentsShape2 {
|
||||||
{ ...ehResult, metadata: undefined };
|
{ ...ehResult, metadata: undefined };
|
||||||
|
|
||||||
// REQUEST turn
|
// REQUEST turn
|
||||||
res.push(new extHostTypes.ChatAgentRequestTurn(h.request.message, h.request.command, h.request.variables2.variables.map(typeConvert.ChatAgentResolvedVariable.to), { extensionId: '', agentId: h.request.agentId }));
|
res.push(new extHostTypes.ChatAgentRequestTurn(h.request.message, h.request.command, h.request.variables.variables.map(typeConvert.ChatAgentResolvedVariable.to), { extensionId: '', agentId: h.request.agentId }));
|
||||||
|
|
||||||
// RESPONSE turn
|
// RESPONSE turn
|
||||||
const parts = coalesce(h.response.map(r => typeConvert.ChatResponsePart.from(r, this.commands.converter)));
|
const parts = coalesce(h.response.map(r => typeConvert.ChatResponsePart.from(r, this.commands.converter)));
|
||||||
|
|
|
@ -2631,11 +2631,8 @@ export namespace ChatAgentRequest {
|
||||||
export function to(request: IChatAgentRequest): vscode.ChatAgentRequest {
|
export function to(request: IChatAgentRequest): vscode.ChatAgentRequest {
|
||||||
return {
|
return {
|
||||||
prompt: request.message,
|
prompt: request.message,
|
||||||
prompt2: request.variables2.message,
|
|
||||||
variables: ChatVariable.objectTo(request.variables),
|
|
||||||
command: request.command,
|
command: request.command,
|
||||||
agentId: request.agentId,
|
variables: request.variables.variables.map(ChatAgentResolvedVariable.to)
|
||||||
variables2: request.variables2.variables.map(ChatAgentResolvedVariable.to)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { coalesce } from 'vs/base/common/arrays';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { onUnexpectedExternalError } from 'vs/base/common/errors';
|
import { onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||||
import { Iterable } from 'vs/base/common/iterator';
|
import { Iterable } from 'vs/base/common/iterator';
|
||||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { IOffsetRange } from 'vs/editor/common/core/offsetRange';
|
||||||
import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
|
import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
|
||||||
import { ChatDynamicVariableModel } from 'vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables';
|
import { ChatDynamicVariableModel } from 'vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables';
|
||||||
import { IChatModel, IChatRequestVariableData } from 'vs/workbench/contrib/chat/common/chatModel';
|
import { IChatModel, IChatRequestVariableData } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||||
|
@ -29,51 +31,37 @@ export class ChatVariablesService implements IChatVariablesService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async resolveVariables(prompt: IParsedChatRequest, model: IChatModel, token: CancellationToken): Promise<IChatRequestVariableData> {
|
async resolveVariables(prompt: IParsedChatRequest, model: IChatModel, token: CancellationToken): Promise<IChatRequestVariableData> {
|
||||||
const resolvedVariables: Record<string, IChatRequestVariableValue[]> = {};
|
let resolvedVariables: { name: string; range: IOffsetRange; values: IChatRequestVariableValue[] }[] = [];
|
||||||
const jobs: Promise<any>[] = [];
|
const jobs: Promise<any>[] = [];
|
||||||
|
|
||||||
const parsedPrompt: string[] = [];
|
|
||||||
prompt.parts
|
prompt.parts
|
||||||
.forEach((part, i) => {
|
.forEach((part, i) => {
|
||||||
if (part instanceof ChatRequestVariablePart) {
|
if (part instanceof ChatRequestVariablePart) {
|
||||||
const data = this._resolver.get(part.variableName.toLowerCase());
|
const data = this._resolver.get(part.variableName.toLowerCase());
|
||||||
if (data) {
|
if (data) {
|
||||||
jobs.push(data.resolver(prompt.text, part.variableArg, model, token).then(value => {
|
jobs.push(data.resolver(prompt.text, part.variableArg, model, token).then(values => {
|
||||||
if (value) {
|
if (values?.length) {
|
||||||
resolvedVariables[part.variableName] = value;
|
resolvedVariables[i] = { name: part.variableName, range: part.range, values };
|
||||||
parsedPrompt[i] = `[${part.text}](values:${part.variableName})`;
|
|
||||||
} else {
|
|
||||||
parsedPrompt[i] = part.promptText;
|
|
||||||
}
|
}
|
||||||
}).catch(onUnexpectedExternalError));
|
}).catch(onUnexpectedExternalError));
|
||||||
}
|
}
|
||||||
} else if (part instanceof ChatRequestDynamicVariablePart) {
|
} else if (part instanceof ChatRequestDynamicVariablePart) {
|
||||||
const referenceName = this.getUniqueReferenceName(part.referenceText, resolvedVariables);
|
resolvedVariables[i] = { name: part.referenceText, range: part.range, values: part.data };
|
||||||
resolvedVariables[referenceName] = part.data;
|
|
||||||
const safeText = part.text.replace(/[\[\]]/g, '_');
|
|
||||||
const safeTarget = referenceName.replace(/[\(\)]/g, '_');
|
|
||||||
parsedPrompt[i] = `[${safeText}](values:${safeTarget})`;
|
|
||||||
} else {
|
|
||||||
parsedPrompt[i] = part.promptText;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.allSettled(jobs);
|
await Promise.allSettled(jobs);
|
||||||
|
|
||||||
|
resolvedVariables = coalesce(resolvedVariables);
|
||||||
|
|
||||||
|
// "reverse", high index first so that replacement is simple
|
||||||
|
resolvedVariables.sort((a, b) => b.range.start - a.range.start);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
variables: resolvedVariables,
|
variables: resolvedVariables,
|
||||||
message: parsedPrompt.join('').trim()
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private getUniqueReferenceName(name: string, vars: Record<string, any>): string {
|
|
||||||
let i = 1;
|
|
||||||
while (vars[name]) {
|
|
||||||
name = `${name}_${i++}`;
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
hasVariable(name: string): boolean {
|
hasVariable(name: string): boolean {
|
||||||
return this._resolver.has(name.toLowerCase());
|
return this._resolver.has(name.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,8 @@ import { URI } from 'vs/base/common/uri';
|
||||||
import { ProviderResult } from 'vs/editor/common/languages';
|
import { ProviderResult } from 'vs/editor/common/languages';
|
||||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IChatProgressResponseContent, IChatRequestVariableData2 } from 'vs/workbench/contrib/chat/common/chatModel';
|
import { IChatProgressResponseContent, IChatRequestVariableData } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||||
import { IChatFollowup, IChatProgress, IChatResponseErrorDetails } from 'vs/workbench/contrib/chat/common/chatService';
|
import { IChatFollowup, IChatProgress, IChatResponseErrorDetails } from 'vs/workbench/contrib/chat/common/chatService';
|
||||||
import { IChatRequestVariableValue } from 'vs/workbench/contrib/chat/common/chatVariables';
|
|
||||||
|
|
||||||
//#region agent service, commands etc
|
//#region agent service, commands etc
|
||||||
|
|
||||||
|
@ -89,8 +88,7 @@ export interface IChatAgentRequest {
|
||||||
agentId: string;
|
agentId: string;
|
||||||
command?: string;
|
command?: string;
|
||||||
message: string;
|
message: string;
|
||||||
variables: Record<string, IChatRequestVariableValue[]>;
|
variables: IChatRequestVariableData;
|
||||||
variables2: IChatRequestVariableData2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IChatAgentResult {
|
export interface IChatAgentResult {
|
||||||
|
|
|
@ -20,16 +20,6 @@ import { IChat, IChatAgentMarkdownContentWithVulnerability, IChatCommandButton,
|
||||||
import { IChatRequestVariableValue } from 'vs/workbench/contrib/chat/common/chatVariables';
|
import { IChatRequestVariableValue } from 'vs/workbench/contrib/chat/common/chatVariables';
|
||||||
|
|
||||||
export interface IChatRequestVariableData {
|
export interface IChatRequestVariableData {
|
||||||
/**
|
|
||||||
* The user's message with variable references for extension API.
|
|
||||||
*/
|
|
||||||
message: string;
|
|
||||||
|
|
||||||
variables: Record<string, IChatRequestVariableValue[]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IChatRequestVariableData2 {
|
|
||||||
message: string;
|
|
||||||
variables: { name: string; range: IOffsetRange; values: IChatRequestVariableValue[] }[];
|
variables: { name: string; range: IOffsetRange; values: IChatRequestVariableValue[] }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,8 +564,10 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||||
? this.getParsedRequestFromString(raw.message)
|
? this.getParsedRequestFromString(raw.message)
|
||||||
: reviveParsedChatRequest(raw.message);
|
: reviveParsedChatRequest(raw.message);
|
||||||
|
|
||||||
// Only old messages don't have variableData
|
// Old messages don't have variableData, or have it in the wrong (non-array) shape
|
||||||
const variableData: IChatRequestVariableData = raw.variableData ?? { message: parsedRequest.text, variables: {} };
|
const variableData: IChatRequestVariableData = raw.variableData && Array.isArray(raw.variableData.variables)
|
||||||
|
? raw.variableData :
|
||||||
|
{ variables: [] };
|
||||||
const request = new ChatRequestModel(this, parsedRequest, variableData);
|
const request = new ChatRequestModel(this, parsedRequest, variableData);
|
||||||
if (raw.response || raw.result || (raw as any).responseErrorDetails) {
|
if (raw.response || raw.result || (raw as any).responseErrorDetails) {
|
||||||
const agent = (raw.agent && 'metadata' in raw.agent) ? // Check for the new format, ignore entries in the old format
|
const agent = (raw.agent && 'metadata' in raw.agent) ? // Check for the new format, ignore entries in the old format
|
||||||
|
|
|
@ -26,8 +26,11 @@ export interface IParsedChatRequestPart {
|
||||||
readonly promptText: string;
|
readonly promptText: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPromptText(request: ReadonlyArray<IParsedChatRequestPart>): string {
|
export function getPromptText(request: IParsedChatRequest): { message: string; diff: number } {
|
||||||
return request.map(r => r.promptText).join('');
|
const message = request.parts.map(r => r.promptText).join('').trimStart();
|
||||||
|
const diff = request.text.length - message.length;
|
||||||
|
|
||||||
|
return { message, diff };
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChatRequestTextPart implements IParsedChatRequestPart {
|
export class ChatRequestTextPart implements IParsedChatRequestPart {
|
||||||
|
|
|
@ -22,8 +22,8 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||||
import { IChatAgentHistoryEntry, IChatAgentRequest, IChatAgentResult, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents';
|
import { IChatAgentHistoryEntry, IChatAgentRequest, IChatAgentResult, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents';
|
||||||
import { CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
import { CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||||
import { ChatModel, ChatModelInitState, ChatRequestModel, ChatWelcomeMessageModel, IChatModel, IChatRequestVariableData, IChatRequestVariableData2, ISerializableChatData, ISerializableChatsData } from 'vs/workbench/contrib/chat/common/chatModel';
|
import { ChatModel, ChatModelInitState, ChatRequestModel, ChatWelcomeMessageModel, IChatModel, IChatRequestVariableData, ISerializableChatData, ISerializableChatsData } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||||
import { ChatRequestAgentPart, ChatRequestAgentSubcommandPart, ChatRequestDynamicVariablePart, ChatRequestSlashCommandPart, ChatRequestVariablePart, IParsedChatRequest, getPromptText } from 'vs/workbench/contrib/chat/common/chatParserTypes';
|
import { ChatRequestAgentPart, ChatRequestAgentSubcommandPart, ChatRequestSlashCommandPart, IParsedChatRequest, getPromptText } from 'vs/workbench/contrib/chat/common/chatParserTypes';
|
||||||
import { ChatMessageRole, IChatMessage } from 'vs/workbench/contrib/chat/common/chatProvider';
|
import { ChatMessageRole, IChatMessage } from 'vs/workbench/contrib/chat/common/chatProvider';
|
||||||
import { ChatRequestParser } from 'vs/workbench/contrib/chat/common/chatRequestParser';
|
import { ChatRequestParser } from 'vs/workbench/contrib/chat/common/chatRequestParser';
|
||||||
import { ChatAgentCopyKind, IChat, IChatCompleteResponse, IChatDetail, IChatDynamicRequest, IChatFollowup, IChatProgress, IChatProvider, IChatProviderInfo, IChatSendRequestData, IChatService, IChatTransferredSessionData, IChatUserActionEvent, InteractiveSessionVoteDirection } from 'vs/workbench/contrib/chat/common/chatService';
|
import { ChatAgentCopyKind, IChat, IChatCompleteResponse, IChatDetail, IChatDynamicRequest, IChatFollowup, IChatProgress, IChatProvider, IChatProviderInfo, IChatSendRequestData, IChatService, IChatTransferredSessionData, IChatUserActionEvent, InteractiveSessionVoteDirection } from 'vs/workbench/contrib/chat/common/chatService';
|
||||||
|
@ -537,38 +537,38 @@ export class ChatService extends Disposable implements IChatService {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const promptTextResult = getPromptText(request.message);
|
||||||
const historyRequest: IChatAgentRequest = {
|
const historyRequest: IChatAgentRequest = {
|
||||||
sessionId,
|
sessionId,
|
||||||
requestId: request.id,
|
requestId: request.id,
|
||||||
agentId: request.response.agent?.id ?? '',
|
agentId: request.response.agent?.id ?? '',
|
||||||
message: request.variableData.message,
|
message: promptTextResult.message,
|
||||||
variables: request.variableData.variables,
|
|
||||||
command: request.response.slashCommand?.name,
|
command: request.response.slashCommand?.name,
|
||||||
variables2: asVariablesData2(request.message, request.variableData)
|
variables: updateRanges(request.variableData, promptTextResult.diff) // TODO bit of a hack
|
||||||
};
|
};
|
||||||
history.push({ request: historyRequest, response: request.response.response.value, result: request.response.result ?? {} });
|
history.push({ request: historyRequest, response: request.response.response.value, result: request.response.result ?? {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
const initVariableData: IChatRequestVariableData = { message: getPromptText(parsedRequest.parts), variables: {} };
|
const initVariableData: IChatRequestVariableData = { variables: [] };
|
||||||
request = model.addRequest(parsedRequest, initVariableData, agent, agentSlashCommandPart?.command);
|
request = model.addRequest(parsedRequest, initVariableData, agent, agentSlashCommandPart?.command);
|
||||||
const variableData = await this.chatVariablesService.resolveVariables(parsedRequest, model, token);
|
const variableData = await this.chatVariablesService.resolveVariables(parsedRequest, model, token);
|
||||||
request.variableData = variableData;
|
request.variableData = variableData;
|
||||||
|
|
||||||
|
const promptTextResult = getPromptText(request.message);
|
||||||
const requestProps: IChatAgentRequest = {
|
const requestProps: IChatAgentRequest = {
|
||||||
sessionId,
|
sessionId,
|
||||||
requestId: request.id,
|
requestId: request.id,
|
||||||
agentId: agent.id,
|
agentId: agent.id,
|
||||||
message: variableData.message,
|
message: promptTextResult.message,
|
||||||
variables: variableData.variables,
|
|
||||||
command: agentSlashCommandPart?.command.name,
|
command: agentSlashCommandPart?.command.name,
|
||||||
variables2: asVariablesData2(parsedRequest, variableData)
|
variables: updateRanges(variableData, promptTextResult.diff) // TODO bit of a hack
|
||||||
};
|
};
|
||||||
|
|
||||||
const agentResult = await this.chatAgentService.invokeAgent(agent.id, requestProps, progressCallback, history, token);
|
const agentResult = await this.chatAgentService.invokeAgent(agent.id, requestProps, progressCallback, history, token);
|
||||||
rawResult = agentResult;
|
rawResult = agentResult;
|
||||||
agentOrCommandFollowups = this.chatAgentService.getFollowups(agent.id, requestProps, agentResult, followupsCancelToken);
|
agentOrCommandFollowups = this.chatAgentService.getFollowups(agent.id, requestProps, agentResult, followupsCancelToken);
|
||||||
} else if (commandPart && this.chatSlashCommandService.hasCommand(commandPart.slashCommand.command)) {
|
} else if (commandPart && this.chatSlashCommandService.hasCommand(commandPart.slashCommand.command)) {
|
||||||
request = model.addRequest(parsedRequest, { message: parsedRequest.text, variables: {} });
|
request = model.addRequest(parsedRequest, { variables: [] });
|
||||||
// contributed slash commands
|
// contributed slash commands
|
||||||
// TODO: spell this out in the UI
|
// TODO: spell this out in the UI
|
||||||
const history: IChatMessage[] = [];
|
const history: IChatMessage[] = [];
|
||||||
|
@ -670,7 +670,7 @@ export class ChatService extends Disposable implements IChatService {
|
||||||
const parsedRequest = typeof message === 'string' ?
|
const parsedRequest = typeof message === 'string' ?
|
||||||
this.instantiationService.createInstance(ChatRequestParser).parseChatRequest(sessionId, message) :
|
this.instantiationService.createInstance(ChatRequestParser).parseChatRequest(sessionId, message) :
|
||||||
message;
|
message;
|
||||||
const request = model.addRequest(parsedRequest, variableData || { message: parsedRequest.text, variables: {} });
|
const request = model.addRequest(parsedRequest, variableData || { variables: [] });
|
||||||
if (typeof response.message === 'string') {
|
if (typeof response.message === 'string') {
|
||||||
model.acceptResponseProgress(request, { content: response.message, kind: 'content' });
|
model.acceptResponseProgress(request, { content: response.message, kind: 'content' });
|
||||||
} else {
|
} else {
|
||||||
|
@ -765,25 +765,14 @@ export class ChatService extends Disposable implements IChatService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function asVariablesData2(parsedRequest: IParsedChatRequest, variableData: IChatRequestVariableData): IChatRequestVariableData2 {
|
function updateRanges(variableData: IChatRequestVariableData, diff: number): IChatRequestVariableData {
|
||||||
|
return {
|
||||||
const res: IChatRequestVariableData2 = {
|
variables: variableData.variables.map(v => ({
|
||||||
message: getPromptText(parsedRequest.parts),
|
...v,
|
||||||
variables: []
|
range: {
|
||||||
|
start: v.range.start - diff,
|
||||||
|
endExclusive: v.range.endExclusive - diff
|
||||||
|
}
|
||||||
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const part of parsedRequest.parts) {
|
|
||||||
if (part instanceof ChatRequestVariablePart) {
|
|
||||||
const values = variableData.variables[part.variableName];
|
|
||||||
res.variables.push({ name: part.variableName, range: part.range, values });
|
|
||||||
} else if (part instanceof ChatRequestDynamicVariablePart) {
|
|
||||||
// Need variable without `#`
|
|
||||||
res.variables.push({ name: part.referenceText, range: part.range, values: part.data });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "reverse", high index first so that replacement is simple
|
|
||||||
res.variables.sort((a, b) => b.range.start - a.range.start);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,48 +41,44 @@ suite('ChatVariables', function () {
|
||||||
const parser = instantiationService.createInstance(ChatRequestParser);
|
const parser = instantiationService.createInstance(ChatRequestParser);
|
||||||
|
|
||||||
const resolveVariables = async (text: string) => {
|
const resolveVariables = async (text: string) => {
|
||||||
const result = await parser.parseChatRequest('1', text);
|
const result = parser.parseChatRequest('1', text);
|
||||||
return await service.resolveVariables(result, null!, CancellationToken.None);
|
return await service.resolveVariables(result, null!, CancellationToken.None);
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
const data = await resolveVariables('Hello #foo and#far');
|
const data = await resolveVariables('Hello #foo and#far');
|
||||||
assert.strictEqual(Object.keys(data.variables).length, 1);
|
assert.strictEqual(data.variables.length, 1);
|
||||||
assert.deepEqual(Object.keys(data.variables).sort(), ['foo']);
|
assert.deepEqual(data.variables.map(v => v.name), ['foo']);
|
||||||
assert.strictEqual(data.message, 'Hello [#foo](values:foo) and#far');
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const data = await resolveVariables('#foo Hello');
|
const data = await resolveVariables('#foo Hello');
|
||||||
assert.strictEqual(Object.keys(data.variables).length, 1);
|
assert.strictEqual(data.variables.length, 1);
|
||||||
assert.deepEqual(Object.keys(data.variables).sort(), ['foo']);
|
assert.deepEqual(data.variables.map(v => v.name), ['foo']);
|
||||||
assert.strictEqual(data.message, '[#foo](values:foo) Hello');
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const data = await resolveVariables('Hello #foo');
|
const data = await resolveVariables('Hello #foo');
|
||||||
assert.strictEqual(Object.keys(data.variables).length, 1);
|
assert.strictEqual(data.variables.length, 1);
|
||||||
assert.deepEqual(Object.keys(data.variables).sort(), ['foo']);
|
assert.deepEqual(data.variables.map(v => v.name), ['foo']);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const data = await resolveVariables('Hello #foo?');
|
const data = await resolveVariables('Hello #foo?');
|
||||||
assert.strictEqual(Object.keys(data.variables).length, 1);
|
assert.strictEqual(data.variables.length, 1);
|
||||||
assert.deepEqual(Object.keys(data.variables).sort(), ['foo']);
|
assert.deepEqual(data.variables.map(v => v.name), ['foo']);
|
||||||
assert.strictEqual(data.message, 'Hello [#foo](values:foo)?');
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const data = await resolveVariables('Hello #foo and#far #foo');
|
const data = await resolveVariables('Hello #foo and#far #foo');
|
||||||
assert.strictEqual(Object.keys(data.variables).length, 1);
|
assert.strictEqual(data.variables.length, 2);
|
||||||
assert.deepEqual(Object.keys(data.variables).sort(), ['foo']);
|
assert.deepEqual(data.variables.map(v => v.name), ['foo', 'foo']);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const data = await resolveVariables('Hello #foo and #far #foo');
|
const data = await resolveVariables('Hello #foo and #far #foo');
|
||||||
assert.strictEqual(Object.keys(data.variables).length, 2);
|
assert.strictEqual(data.variables.length, 3);
|
||||||
assert.deepEqual(Object.keys(data.variables).sort(), ['far', 'foo']);
|
assert.deepEqual(data.variables.map(v => v.name), ['foo', 'far', 'foo']);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const data = await resolveVariables('Hello #foo and #far #foo #unknown');
|
const data = await resolveVariables('Hello #foo and #far #foo #unknown');
|
||||||
assert.strictEqual(Object.keys(data.variables).length, 2);
|
assert.strictEqual(data.variables.length, 3);
|
||||||
assert.deepEqual(Object.keys(data.variables).sort(), ['far', 'foo']);
|
assert.deepEqual(data.variables.map(v => v.name), ['foo', 'far', 'foo']);
|
||||||
assert.strictEqual(data.message, 'Hello [#foo](values:foo) and [#far](values:far) [#foo](values:foo) #unknown');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v1.dispose();
|
v1.dispose();
|
||||||
|
|
|
@ -42,10 +42,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
variableData: {
|
variableData: { variables: [ ] },
|
||||||
message: "@ChatProviderWithUsedContext test request",
|
|
||||||
variables: { }
|
|
||||||
},
|
|
||||||
response: [ ],
|
response: [ ],
|
||||||
result: { metadata: { metadataKey: "value" } },
|
result: { metadata: { metadataKey: "value" } },
|
||||||
followups: undefined,
|
followups: undefined,
|
||||||
|
|
|
@ -42,10 +42,7 @@
|
||||||
],
|
],
|
||||||
text: "@ChatProviderWithUsedContext test request"
|
text: "@ChatProviderWithUsedContext test request"
|
||||||
},
|
},
|
||||||
variableData: {
|
variableData: { variables: [ ] },
|
||||||
message: "@ChatProviderWithUsedContext test request",
|
|
||||||
variables: { }
|
|
||||||
},
|
|
||||||
response: [ ],
|
response: [ ],
|
||||||
result: { metadata: { metadataKey: "value" } },
|
result: { metadata: { metadataKey: "value" } },
|
||||||
followups: undefined,
|
followups: undefined,
|
||||||
|
|
|
@ -111,7 +111,7 @@ suite('ChatModel', () => {
|
||||||
model.startInitialize();
|
model.startInitialize();
|
||||||
model.initialize({} as any, undefined);
|
model.initialize({} as any, undefined);
|
||||||
const text = 'hello';
|
const text = 'hello';
|
||||||
model.addRequest({ text, parts: [new ChatRequestTextPart(new OffsetRange(0, text.length), new Range(1, text.length, 1, text.length), text)] }, { message: text, variables: {} });
|
model.addRequest({ text, parts: [new ChatRequestTextPart(new OffsetRange(0, text.length), new Range(1, text.length, 1, text.length), text)] }, { variables: [] });
|
||||||
const requests = model.getRequests();
|
const requests = model.getRequests();
|
||||||
assert.strictEqual(requests.length, 1);
|
assert.strictEqual(requests.length, 1);
|
||||||
|
|
||||||
|
|
|
@ -131,11 +131,11 @@ suite('Chat', () => {
|
||||||
|
|
||||||
const session1 = testDisposables.add(testService.startSession('provider1', CancellationToken.None));
|
const session1 = testDisposables.add(testService.startSession('provider1', CancellationToken.None));
|
||||||
await session1.waitForInitialization();
|
await session1.waitForInitialization();
|
||||||
session1.addRequest({ parts: [], text: 'request 1' }, { message: 'request 1', variables: {} });
|
session1.addRequest({ parts: [], text: 'request 1' }, { variables: [] });
|
||||||
|
|
||||||
const session2 = testDisposables.add(testService.startSession('provider2', CancellationToken.None));
|
const session2 = testDisposables.add(testService.startSession('provider2', CancellationToken.None));
|
||||||
await session2.waitForInitialization();
|
await session2.waitForInitialization();
|
||||||
session2.addRequest({ parts: [], text: 'request 2' }, { message: 'request 2', variables: {} });
|
session2.addRequest({ parts: [], text: 'request 2' }, { variables: [] });
|
||||||
|
|
||||||
storageService.flush();
|
storageService.flush();
|
||||||
const testService2 = testDisposables.add(instantiationService.createInstance(ChatService));
|
const testService2 = testDisposables.add(instantiationService.createInstance(ChatService));
|
||||||
|
|
|
@ -29,8 +29,7 @@ export class MockChatVariablesService implements IChatVariablesService {
|
||||||
|
|
||||||
async resolveVariables(prompt: IParsedChatRequest, model: IChatModel, token: CancellationToken): Promise<IChatRequestVariableData> {
|
async resolveVariables(prompt: IParsedChatRequest, model: IChatModel, token: CancellationToken): Promise<IChatRequestVariableData> {
|
||||||
return {
|
return {
|
||||||
message: prompt.text,
|
variables: []
|
||||||
variables: {}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
src/vscode-dts/vscode.proposed.chatAgents2.d.ts
vendored
31
src/vscode-dts/vscode.proposed.chatAgents2.d.ts
vendored
|
@ -31,7 +31,7 @@ declare module 'vscode' {
|
||||||
/**
|
/**
|
||||||
* The prompt as entered by the user.
|
* The prompt as entered by the user.
|
||||||
*
|
*
|
||||||
* Information about variables used in this request are is stored in {@link ChatAgentRequest.variables2}.
|
* Information about variables used in this request are is stored in {@link ChatAgentRequest.variables}.
|
||||||
*
|
*
|
||||||
* *Note* that the {@link ChatAgent2.name name} of the agent and the {@link ChatAgentCommand.name command}
|
* *Note* that the {@link ChatAgent2.name name} of the agent and the {@link ChatAgentCommand.name command}
|
||||||
* are not part of the prompt.
|
* are not part of the prompt.
|
||||||
|
@ -88,11 +88,6 @@ declare module 'vscode' {
|
||||||
* All of the chat messages so far in the current chat session.
|
* All of the chat messages so far in the current chat session.
|
||||||
*/
|
*/
|
||||||
readonly history: ReadonlyArray<ChatAgentRequestTurn | ChatAgentResponseTurn>;
|
readonly history: ReadonlyArray<ChatAgentRequestTurn | ChatAgentResponseTurn>;
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated, use histroy
|
|
||||||
*/
|
|
||||||
readonly history2: ReadonlyArray<ChatAgentRequestTurn | ChatAgentResponseTurn>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -325,41 +320,25 @@ declare module 'vscode' {
|
||||||
|
|
||||||
export interface ChatAgentRequest {
|
export interface ChatAgentRequest {
|
||||||
|
|
||||||
/**
|
|
||||||
* The prompt entered by the user. The {@link ChatAgent2.name name} of the agent or the {@link ChatAgentCommand.name command}
|
|
||||||
* are not part of the prompt.
|
|
||||||
*
|
|
||||||
* @see {@link ChatAgentRequest.command}
|
|
||||||
*/
|
|
||||||
prompt: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prompt as entered by the user.
|
* The prompt as entered by the user.
|
||||||
*
|
*
|
||||||
* Information about variables used in this request are is stored in {@link ChatAgentRequest.variables2}.
|
* Information about variables used in this request are is stored in {@link ChatAgentRequest.variables}.
|
||||||
*
|
*
|
||||||
* *Note* that the {@link ChatAgent2.name name} of the agent and the {@link ChatAgentCommand.name command}
|
* *Note* that the {@link ChatAgent2.name name} of the agent and the {@link ChatAgentCommand.name command}
|
||||||
* are not part of the prompt.
|
* are not part of the prompt.
|
||||||
*/
|
*/
|
||||||
prompt2: string;
|
prompt: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The ID of the chat agent to which this request was directed.
|
|
||||||
*/
|
|
||||||
agentId: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the {@link ChatAgentCommand command} that was selected for this request.
|
* The name of the {@link ChatAgentCommand command} that was selected for this request.
|
||||||
*/
|
*/
|
||||||
command?: string;
|
command?: string;
|
||||||
|
|
||||||
/** @deprecated */
|
|
||||||
variables: Record<string, ChatVariableValue[]>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* The list of variables that are referenced in the prompt.
|
||||||
*/
|
*/
|
||||||
variables2: ChatAgentResolvedVariable[];
|
variables: ChatAgentResolvedVariable[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChatAgentResponseStream {
|
export interface ChatAgentResponseStream {
|
||||||
|
|
Loading…
Reference in a new issue