Skip to content

Commit 16ce893

Browse files
authored
Provide more context when 'Delegating to coding agent' (microsoft#264788)
* Cloud Button Improvements - Show/attach file context when passed to coding agent - Attach the verbatim chat history in the summary * tidy
1 parent 66aa080 commit 16ce893

1 file changed

Lines changed: 62 additions & 7 deletions

File tree

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

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import { CancellationToken } from '../../../../../base/common/cancellation.js';
77
import { Codicon } from '../../../../../base/common/codicons.js';
88
import { MarkdownString } from '../../../../../base/common/htmlContent.js';
99
import { KeyCode, KeyMod } from '../../../../../base/common/keyCodes.js';
10-
import { basename } from '../../../../../base/common/resources.js';
10+
import { basename, relativePath } from '../../../../../base/common/resources.js';
1111
import { ThemeIcon } from '../../../../../base/common/themables.js';
1212
import { assertType } from '../../../../../base/common/types.js';
13+
import { URI } from '../../../../../base/common/uri.js';
1314
import { ServicesAccessor } from '../../../../../editor/browser/editorExtensions.js';
1415
import { EditorContextKeys } from '../../../../../editor/common/editorContextKeys.js';
1516
import { localize, localize2 } from '../../../../../nls.js';
@@ -22,6 +23,7 @@ import { IInstantiationService } from '../../../../../platform/instantiation/com
2223
import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';
2324
import { IQuickInputService } from '../../../../../platform/quickinput/common/quickInput.js';
2425
import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';
26+
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
2527
import { IEditorService } from '../../../../services/editor/common/editorService.js';
2628
import { IRemoteCodingAgent, IRemoteCodingAgentsService } from '../../../remoteCodingAgents/common/remoteCodingAgentsService.js';
2729
import { IChatAgentHistoryEntry, IChatAgentService } from '../../common/chatAgents.js';
@@ -33,6 +35,7 @@ import { ChatRequestParser } from '../../common/chatRequestParser.js';
3335
import { IChatPullRequestContent, IChatService } from '../../common/chatService.js';
3436
import { IChatSessionsExtensionPoint, IChatSessionsService } from '../../common/chatSessionsService.js';
3537
import { ChatSessionUri } from '../../common/chatUri.js';
38+
import { ChatRequestVariableSet, isChatRequestFileEntry } from '../../common/chatVariableEntries.js';
3639
import { ChatAgentLocation, ChatConfiguration, ChatModeKind, } from '../../common/constants.js';
3740
import { ILanguageModelChatMetadata } from '../../common/languageModels.js';
3841
import { ILanguageModelToolsService } from '../../common/languageModelToolsService.js';
@@ -662,6 +665,47 @@ export class CreateRemoteAgentJobAction extends Action2 {
662665
}
663666
}
664667

668+
/**
669+
* Converts full URIs from the user's systems into workspace-relative paths for coding agent.
670+
*/
671+
private extractRelativeFromAttachedContext(attachedContext: ChatRequestVariableSet, workspaceContextService: IWorkspaceContextService): string[] {
672+
const workspaceFolder = workspaceContextService.getWorkspace().folders[0];
673+
if (!workspaceFolder) {
674+
return [];
675+
}
676+
const relativePaths: string[] = [];
677+
for (const contextEntry of attachedContext.asArray()) {
678+
if (isChatRequestFileEntry(contextEntry)) { // TODO: Extend for more variable types as needed
679+
if (!(contextEntry.value instanceof URI)) {
680+
continue;
681+
}
682+
const fileUri = contextEntry.value;
683+
const relativePathResult = relativePath(workspaceFolder.uri, fileUri);
684+
if (relativePathResult) {
685+
relativePaths.push(relativePathResult);
686+
}
687+
}
688+
}
689+
return relativePaths;
690+
}
691+
692+
private extractChatTurns(historyEntries: IChatAgentHistoryEntry[]): string {
693+
let result = '\n';
694+
for (const entry of historyEntries) {
695+
if (entry.request.message) {
696+
result += `User: ${entry.request.message}\n`;
697+
}
698+
if (entry.response) {
699+
for (const content of entry.response) {
700+
if (content.kind === 'markdownContent') {
701+
result += `AI: ${content.content.value}\n`;
702+
}
703+
}
704+
}
705+
}
706+
return `${result}\n`;
707+
}
708+
665709
async run(accessor: ServicesAccessor, ...args: any[]) {
666710
const contextKeyService = accessor.get(IContextKeyService);
667711
const remoteJobCreatingKey = ChatContextKeys.remoteJobCreating.bindTo(contextKeyService);
@@ -702,26 +746,31 @@ export class CreateRemoteAgentJobAction extends Action2 {
702746
userPrompt = 'implement this.';
703747
}
704748

749+
const attachedContext = widget.input.getAttachedAndImplicitContext(session);
705750
widget.input.acceptInput(true);
706751

707752
const defaultAgent = chatAgentService.getDefaultAgent(ChatAgentLocation.Panel);
708-
709-
// Parse the request text to create a structured request
710753
const instantiationService = accessor.get(IInstantiationService);
711754
const requestParser = instantiationService.createInstance(ChatRequestParser);
712755
const parsedRequest = requestParser.parseChatRequest(session, userPrompt, ChatAgentLocation.Panel);
713756

757+
714758
// Add the request to the model first
715759
const addedRequest = chatModel.addRequest(
716760
parsedRequest,
717-
{ variables: [] },
761+
{ variables: attachedContext.asArray() },
718762
0,
719763
undefined,
720764
defaultAgent,
721765
);
722766

723-
let summary: string | undefined;
724-
if (defaultAgent && chatRequests.length > 0) {
767+
let summary: string = '';
768+
const relativeAttachedContext = this.extractRelativeFromAttachedContext(attachedContext, accessor.get(IWorkspaceContextService));
769+
if (relativeAttachedContext.length) {
770+
summary += `\n\n${localize('attachedFiles', "The user has attached the following files from their workspace:")}\n${relativeAttachedContext.map(file => `- ${file}`).join('\n')}\n\n`;
771+
}
772+
773+
if (defaultAgent && chatRequests.length > 1) {
725774
chatModel.acceptResponseProgress(addedRequest, {
726775
kind: 'progressMessage',
727776
content: new MarkdownString(
@@ -745,7 +794,13 @@ export class CreateRemoteAgentJobAction extends Action2 {
745794
result: req.response?.result ?? {}
746795
}));
747796

748-
summary = await chatAgentService.getChatSummary(defaultAgent.id, historyEntries, CancellationToken.None);
797+
// TODO: Determine a cutoff point where we stop including earlier history
798+
// For example, if the user has already delegated to a coding agent once,
799+
// prefer the conversation afterwards.
800+
801+
summary += 'The following is a snapshot of a chat conversation between a user and an AI coding assistant. Prioritize later messages in the conversation.';
802+
summary += this.extractChatTurns(historyEntries);
803+
summary += await chatAgentService.getChatSummary(defaultAgent.id, historyEntries, CancellationToken.None);
749804
}
750805

751806
chatModel.acceptResponseProgress(addedRequest, {

0 commit comments

Comments
 (0)