Skip to content

Commit a50d3d2

Browse files
authored
Forward chat summaries for cloud button v2 impl (#269583)
* merge * refactor and movie magic to hide fake progress chat req
1 parent 354d4bb commit a50d3d2

File tree

8 files changed

+107
-65
lines changed

8 files changed

+107
-65
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,11 @@ export class MainThreadChatAgents2 extends Disposable implements MainThreadChatA
170170
this._pendingProgress.set(request.requestId, progress);
171171
try {
172172
const chatSessionContext = this._chatService.getChatSessionFromInternalId(request.sessionId);
173-
return await this._proxy.$invokeAgent(handle, request, { history, chatSessionContext }, token) ?? {};
173+
return await this._proxy.$invokeAgent(handle, request, {
174+
history,
175+
chatSessionContext,
176+
chatSummary: request.chatSummary
177+
}, token) ?? {};
174178
} finally {
175179
this._pendingProgress.delete(request.requestId);
176180
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ export type IChatAgentHistoryEntryDto = {
13691369
};
13701370

13711371
export interface ExtHostChatAgentsShape2 {
1372-
$invokeAgent(handle: number, request: Dto<IChatAgentRequest>, context: { history: IChatAgentHistoryEntryDto[]; chatSessionContext?: { chatSessionType: string; chatSessionId: string; isUntitled: boolean } }, token: CancellationToken): Promise<IChatAgentResult | undefined>;
1372+
$invokeAgent(handle: number, request: Dto<IChatAgentRequest>, context: { history: IChatAgentHistoryEntryDto[]; chatSessionContext?: { chatSessionType: string; chatSessionId: string; isUntitled: boolean }; chatSummary?: { prompt?: string; history?: string } }, token: CancellationToken): Promise<IChatAgentResult | undefined>;
13731373
$provideFollowups(request: Dto<IChatAgentRequest>, handle: number, result: IChatAgentResult, context: { history: IChatAgentHistoryEntryDto[] }, token: CancellationToken): Promise<IChatFollowup[]>;
13741374
$acceptFeedback(handle: number, result: IChatAgentResult, voteAction: IChatVoteAction): void;
13751375
$acceptAction(handle: number, result: IChatAgentResult, action: IChatUserActionEvent): void;

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
541541
this._onDidChangeChatRequestTools.fire(request.extRequest);
542542
}
543543

544-
async $invokeAgent(handle: number, requestDto: Dto<IChatAgentRequest>, context: { history: IChatAgentHistoryEntryDto[]; chatSessionContext?: { chatSessionType: string; chatSessionId: string; isUntitled: boolean } }, token: CancellationToken): Promise<IChatAgentResult | undefined> {
544+
async $invokeAgent(handle: number, requestDto: Dto<IChatAgentRequest>, context: { history: IChatAgentHistoryEntryDto[]; chatSessionContext?: { chatSessionType: string; chatSessionId: string; isUntitled: boolean }; chatSummary?: { prompt?: string; history?: string } }, token: CancellationToken): Promise<IChatAgentResult | undefined> {
545545
const agent = this._agents.get(handle);
546546
if (!agent) {
547547
throw new Error(`[CHAT](${handle}) CANNOT invoke agent because the agent is not registered`);
@@ -588,7 +588,11 @@ export class ExtHostChatAgents2 extends Disposable implements ExtHostChatAgentsS
588588
};
589589
}
590590

591-
const chatContext: vscode.ChatContext = { history, chatSessionContext };
591+
const chatContext: vscode.ChatContext = {
592+
history,
593+
chatSessionContext,
594+
chatSummary: context.chatSummary
595+
};
592596
const task = agent.invoke(
593597
extRequest,
594598
chatContext,

src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts

Lines changed: 73 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { IQuickInputService } from '../../../../../platform/quickinput/common/qu
2626
import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';
2727
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
2828
import { IRemoteCodingAgent, IRemoteCodingAgentsService } from '../../../remoteCodingAgents/common/remoteCodingAgentsService.js';
29-
import { IChatAgentHistoryEntry, IChatAgentService } from '../../common/chatAgents.js';
29+
import { IChatAgent, IChatAgentHistoryEntry, IChatAgentService } from '../../common/chatAgents.js';
3030
import { ChatContextKeys, ChatContextKeyExprs } from '../../common/chatContextKeys.js';
3131
import { IChatModel, IChatRequestModel, toChatHistoryContent } from '../../common/chatModel.js';
3232
import { IChatMode, IChatModeService } from '../../common/chatModes.js';
@@ -648,14 +648,14 @@ export class CreateRemoteAgentJobAction extends Action2 {
648648
private async createWithChatSessions(
649649
chatSessionsService: IChatSessionsService,
650650
chatService: IChatService,
651-
chatAgentService: IChatAgentService,
652651
quickPickService: IQuickInputService,
653-
chatModel: IChatModel,
654-
requestParser: ChatRequestParser,
655652
sessionId: string,
656-
widget: IChatWidget,
657653
attachedContext: ChatRequestVariableSet,
658654
userPrompt: string,
655+
chatSummary?: {
656+
prompt?: string;
657+
history?: string;
658+
}
659659
) {
660660
const contributions = chatSessionsService.getAllChatSessionContributions();
661661
const agent = await this.pickCodingAgent(quickPickService, contributions);
@@ -664,9 +664,11 @@ export class CreateRemoteAgentJobAction extends Action2 {
664664
}
665665
// TODO(jospicer): The previous chat history doesn't get sent to chat participants!
666666
const { type } = agent;
667+
667668
await chatService.sendRequest(sessionId, userPrompt, {
668669
agentIdSilent: type,
669670
attachedContext: attachedContext.asArray(),
671+
chatSummary,
670672
});
671673
}
672674

@@ -797,22 +799,6 @@ export class CreateRemoteAgentJobAction extends Action2 {
797799
const instantiationService = accessor.get(IInstantiationService);
798800
const requestParser = instantiationService.createInstance(ChatRequestParser);
799801

800-
const isChatSessionsExperimentEnabled = configurationService.getValue<boolean>(ChatConfiguration.UseCloudButtonV2);
801-
if (isChatSessionsExperimentEnabled) {
802-
return await this.createWithChatSessions(
803-
chatSessionsService,
804-
chatService,
805-
chatAgentService,
806-
quickPickService,
807-
chatModel,
808-
requestParser,
809-
sessionId,
810-
widget,
811-
attachedContext,
812-
userPrompt
813-
);
814-
}
815-
816802
// Add the request to the model first
817803
const parsedRequest = requestParser.parseChatRequest(sessionId, userPrompt, ChatAgentLocation.Chat);
818804
const addedRequest = chatModel.addRequest(
@@ -836,23 +822,7 @@ export class CreateRemoteAgentJobAction extends Action2 {
836822
)
837823
});
838824

839-
const userPromptEntry: IChatAgentHistoryEntry = {
840-
request: {
841-
sessionId,
842-
requestId: generateUuid(),
843-
agentId: '',
844-
message: userPrompt,
845-
command: undefined,
846-
variables: { variables: attachedContext.asArray() },
847-
location: ChatAgentLocation.Chat,
848-
editedFileEvents: [],
849-
},
850-
response: [],
851-
result: {}
852-
};
853-
const historyEntries = [userPromptEntry];
854-
title = await chatAgentService.getChatTitle(defaultAgent.id, historyEntries, CancellationToken.None);
855-
summarizedUserPrompt = await chatAgentService.getChatSummary(defaultAgent.id, historyEntries, CancellationToken.None);
825+
({ title, summarizedUserPrompt } = await this.generateSummarizedUserPrompt(sessionId, userPrompt, attachedContext, title, chatAgentService, defaultAgent, summarizedUserPrompt));
856826
}
857827

858828
let summary: string = '';
@@ -870,34 +840,31 @@ export class CreateRemoteAgentJobAction extends Action2 {
870840
CreateRemoteAgentJobAction.markdownStringTrustedOptions
871841
)
872842
});
873-
const historyEntries: IChatAgentHistoryEntry[] = chatRequests
874-
.map(req => ({
875-
request: {
876-
sessionId,
877-
requestId: req.id,
878-
agentId: req.response?.agent?.id ?? '',
879-
message: req.message.text,
880-
command: req.response?.slashCommand?.name,
881-
variables: req.variableData,
882-
location: ChatAgentLocation.Chat,
883-
editedFileEvents: req.editedFileEvents,
884-
},
885-
response: toChatHistoryContent(req.response!.response.value),
886-
result: req.response?.result ?? {}
887-
}));
888-
889-
// TODO: Determine a cutoff point where we stop including earlier history
890-
// For example, if the user has already delegated to a coding agent once,
891-
// prefer the conversation afterwards.
892-
893-
title ??= await chatAgentService.getChatTitle(defaultAgent.id, historyEntries, CancellationToken.None);
894-
summary += await chatAgentService.getChatSummary(defaultAgent.id, historyEntries, CancellationToken.None);
843+
({ title, summary } = await this.generateSummarizedChatHistory(chatRequests, sessionId, title, chatAgentService, defaultAgent, summary));
895844
}
896845

897846
if (title) {
898847
summary += `\nTITLE: ${title}\n`;
899848
}
900849

850+
851+
const isChatSessionsExperimentEnabled = configurationService.getValue<boolean>(ChatConfiguration.UseCloudButtonV2);
852+
if (isChatSessionsExperimentEnabled) {
853+
await chatService.removeRequest(sessionId, addedRequest.id);
854+
return await this.createWithChatSessions(
855+
chatSessionsService,
856+
chatService,
857+
quickPickService,
858+
sessionId,
859+
attachedContext,
860+
userPrompt,
861+
{
862+
prompt: summarizedUserPrompt,
863+
history: summary,
864+
},
865+
);
866+
}
867+
901868
chatModel.acceptResponseProgress(addedRequest, {
902869
kind: 'progressMessage',
903870
content: new MarkdownString(
@@ -916,6 +883,52 @@ export class CreateRemoteAgentJobAction extends Action2 {
916883
remoteJobCreatingKey.set(false);
917884
}
918885
}
886+
887+
private async generateSummarizedChatHistory(chatRequests: IChatRequestModel[], sessionId: string, title: string | undefined, chatAgentService: IChatAgentService, defaultAgent: IChatAgent, summary: string) {
888+
const historyEntries: IChatAgentHistoryEntry[] = chatRequests
889+
.map(req => ({
890+
request: {
891+
sessionId: sessionId,
892+
requestId: req.id,
893+
agentId: req.response?.agent?.id ?? '',
894+
message: req.message.text,
895+
command: req.response?.slashCommand?.name,
896+
variables: req.variableData,
897+
location: ChatAgentLocation.Chat,
898+
editedFileEvents: req.editedFileEvents,
899+
},
900+
response: toChatHistoryContent(req.response!.response.value),
901+
result: req.response?.result ?? {}
902+
}));
903+
904+
// TODO: Determine a cutoff point where we stop including earlier history
905+
// For example, if the user has already delegated to a coding agent once,
906+
// prefer the conversation afterwards.
907+
title ??= await chatAgentService.getChatTitle(defaultAgent.id, historyEntries, CancellationToken.None);
908+
summary += await chatAgentService.getChatSummary(defaultAgent.id, historyEntries, CancellationToken.None);
909+
return { title, summary };
910+
}
911+
912+
private async generateSummarizedUserPrompt(sessionId: string, userPrompt: string, attachedContext: ChatRequestVariableSet, title: string | undefined, chatAgentService: IChatAgentService, defaultAgent: IChatAgent, summarizedUserPrompt: string | undefined) {
913+
const userPromptEntry: IChatAgentHistoryEntry = {
914+
request: {
915+
sessionId: sessionId,
916+
requestId: generateUuid(),
917+
agentId: '',
918+
message: userPrompt,
919+
command: undefined,
920+
variables: { variables: attachedContext.asArray() },
921+
location: ChatAgentLocation.Chat,
922+
editedFileEvents: [],
923+
},
924+
response: [],
925+
result: {}
926+
};
927+
const historyEntries = [userPromptEntry];
928+
title = await chatAgentService.getChatTitle(defaultAgent.id, historyEntries, CancellationToken.None);
929+
summarizedUserPrompt = await chatAgentService.getChatSummary(defaultAgent.id, historyEntries, CancellationToken.None);
930+
return { title, summarizedUserPrompt };
931+
}
919932
}
920933

921934
export class ChatSubmitWithCodebaseAction extends Action2 {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@ export interface IChatAgentRequest {
148148
userSelectedTools?: UserSelectedTools;
149149
modeInstructions?: IChatRequestModeInstructions;
150150
editedFileEvents?: IChatAgentEditedFileEvent[];
151+
152+
/**
153+
* Summary data for chat sessions context
154+
*/
155+
chatSummary?: {
156+
prompt?: string;
157+
history?: string;
158+
};
151159
}
152160

153161
export interface IChatQuestion {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,14 @@ export interface IChatSendRequestOptions {
682682
* The label of the confirmation action that was selected.
683683
*/
684684
confirmation?: string;
685+
686+
/**
687+
* Summary data for chat sessions context
688+
*/
689+
chatSummary?: {
690+
prompt?: string;
691+
history?: string;
692+
};
685693
}
686694

687695
export const IChatService = createDecorator<IChatService>('IChatService');

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,8 @@ export class ChatService extends Disposable implements IChatService {
822822
userSelectedModelId: options?.userSelectedModelId,
823823
userSelectedTools: options?.userSelectedTools?.get(),
824824
modeInstructions: options?.modeInfo?.modeInstructions,
825-
editedFileEvents: request.editedFileEvents
825+
editedFileEvents: request.editedFileEvents,
826+
chatSummary: options?.chatSummary
826827
} satisfies IChatAgentRequest;
827828
};
828829

src/vscode-dts/vscode.proposed.chatSessionsProvider.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ declare module 'vscode' {
194194

195195
export interface ChatContext {
196196
readonly chatSessionContext?: ChatSessionContext;
197+
readonly chatSummary?: {
198+
readonly prompt?: string;
199+
readonly history?: string;
200+
};
197201
}
198202

199203
export interface ChatSessionContext {

0 commit comments

Comments
 (0)