Limit chat history to messages with the current participant (#209898)

* Limit chat history to messages with the current participant

* Fix build error

* Fix build for real
This commit is contained in:
Rob Lourens 2024-04-09 12:56:52 -03:00 committed by GitHub
parent 923c0a87ca
commit eb736c18c2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 40 additions and 12 deletions

View file

@ -75,6 +75,12 @@
"description": "Hello"
}
]
},
{
"id": "api-test.participant2",
"name": "participant2",
"description": "test",
"commands": [ ]
}
],
"configuration": {

View file

@ -6,7 +6,7 @@
import * as assert from 'assert';
import 'mocha';
import { ChatContext, ChatRequest, ChatResult, ChatVariableLevel, Disposable, Event, EventEmitter, chat, commands } from 'vscode';
import { DeferredPromise, assertNoRpc, closeAllEditors, disposeAll } from '../utils';
import { DeferredPromise, asPromise, assertNoRpc, closeAllEditors, disposeAll } from '../utils';
suite('chat', () => {
@ -28,11 +28,12 @@ suite('chat', () => {
return deferred;
}
function setupParticipant(): Event<{ request: ChatRequest; context: ChatContext }> {
function setupParticipant(second?: boolean): Event<{ request: ChatRequest; context: ChatContext }> {
const emitter = new EventEmitter<{ request: ChatRequest; context: ChatContext }>();
disposables.push(emitter);
const participant = chat.createChatParticipant('api-test.participant', (request, context, _progress, _token) => {
const id = second ? 'api-test.participant2' : 'api-test.participant';
const participant = chat.createChatParticipant(id, (request, context, _progress, _token) => {
emitter.fire({ request, context });
});
participant.isDefault = true;
@ -101,4 +102,25 @@ suite('chat', () => {
const result = await deferred.p;
assert.deepStrictEqual(result.metadata, { key: 'value' });
});
test('isolated participant history', async () => {
const onRequest = setupParticipant();
const onRequest2 = setupParticipant(true);
commands.executeCommand('workbench.action.chat.open', { query: '@participant hi' });
await asPromise(onRequest);
// Request is still being handled at this point, wait for it to end
setTimeout(() => {
commands.executeCommand('workbench.action.chat.open', { query: '@participant2 hi' });
}, 0);
const request2 = await asPromise(onRequest2);
assert.strictEqual(request2.context.history.length, 0);
setTimeout(() => {
commands.executeCommand('workbench.action.chat.open', { query: '@participant2 hi' });
}, 0);
const request3 = await asPromise(onRequest2);
assert.strictEqual(request3.context.history.length, 2); // request + response = 2
});
});

View file

@ -894,13 +894,19 @@ export class ChatWelcomeMessageModel implements IChatWelcomeMessageModel {
}
}
export function getHistoryEntriesFromModel(model: IChatModel): IChatAgentHistoryEntry[] {
export function getHistoryEntriesFromModel(model: IChatModel, forAgentId: string | undefined): IChatAgentHistoryEntry[] {
const history: IChatAgentHistoryEntry[] = [];
for (const request of model.getRequests()) {
if (!request.response) {
continue;
}
if (forAgentId && forAgentId !== request.response.agent?.id) {
// An agent only gets to see requests that were sent to this agent.
// The default agent (the undefined case) gets to see all of them.
continue;
}
const promptTextResult = getPromptText(request.message);
const historyRequest: IChatAgentRequest = {
sessionId: model.sessionId,

View file

@ -331,12 +331,6 @@ export class ChatService extends Disposable implements IChatService {
return model;
}
// TODO, when default agent shows up?
// private reinitializeModel(model: ChatModel): void {
// this.trace('reinitializeModel', `Start reinit`);
// this.initializeSession(model, CancellationToken.None);
// }
private async initializeSession(model: ChatModel, token: CancellationToken): Promise<void> {
try {
this.trace('initializeSession', `Initialize session ${model.sessionId}`);
@ -521,7 +515,7 @@ export class ChatService extends Disposable implements IChatService {
if (agentPart || (defaultAgent && !commandPart)) {
const agent = (agentPart?.agent ?? defaultAgent)!;
await this.extensionService.activateByEvent(`onChatParticipant:${agent.id}`);
const history = getHistoryEntriesFromModel(model);
const history = getHistoryEntriesFromModel(model, agentPart?.agent.id);
const initVariableData: IChatRequestVariableData = { variables: [] };
request = model.addRequest(parsedRequest, initVariableData, attempt, agent, agentSlashCommandPart?.command);

View file

@ -301,7 +301,7 @@ export class TerminalChatController extends Disposable implements ITerminalContr
location: ChatAgentLocation.Terminal
};
try {
const task = this._chatAgentService.invokeAgent(this._terminalAgentId!, requestProps, progressCallback, getHistoryEntriesFromModel(model), cancellationToken);
const task = this._chatAgentService.invokeAgent(this._terminalAgentId!, requestProps, progressCallback, getHistoryEntriesFromModel(model, this._terminalAgentId!), cancellationToken);
this._chatWidget?.value.inlineChatWidget.updateChatMessage(undefined);
this._chatWidget?.value.inlineChatWidget.updateFollowUps(undefined);
this._chatWidget?.value.inlineChatWidget.updateProgress(true);