|
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information.
|
4 | 4 | *--------------------------------------------------------------------------------------------*/
|
5 | 5 |
|
6 |
| -import vscode, { ThemeIcon } from 'vscode'; |
| 6 | +import vscode from 'vscode'; |
7 | 7 | import { parseSessionLogs, parseToolCallDetails } from '../../common/sessionParsing';
|
8 | 8 | import { Repository } from '../api/api';
|
9 | 9 | import { COPILOT_LOGINS, copilotEventToStatus, CopilotPRStatus, mostRecentCopilotEvent } from '../common/copilot';
|
@@ -782,7 +782,7 @@ export class CopilotRemoteAgentManager extends Disposable {
|
782 | 782 | }
|
783 | 783 | return [];
|
784 | 784 | }
|
785 |
| - |
| 785 | + |
786 | 786 | private extractPromptFromEvent(event: TimelineEvent): string {
|
787 | 787 | let body = '';
|
788 | 788 | if (event.event === EventType.Commented) {
|
@@ -876,7 +876,7 @@ export class CopilotRemoteAgentManager extends Disposable {
|
876 | 876 | history.push(sessionRequest);
|
877 | 877 |
|
878 | 878 | // Create response turn
|
879 |
| - const responseHistory = await this.createResponseTurn(logs, session); |
| 879 | + const responseHistory = await this.createResponseTurn(pullRequest, logs, session); |
880 | 880 | if (responseHistory) {
|
881 | 881 | history.push(responseHistory);
|
882 | 882 | }
|
@@ -1019,9 +1019,9 @@ export class CopilotRemoteAgentManager extends Disposable {
|
1019 | 1019 | });
|
1020 | 1020 | }
|
1021 | 1021 |
|
1022 |
| - private async createResponseTurn(logs: string, session: SessionInfo): Promise<vscode.ChatResponseTurn2 | undefined> { |
| 1022 | + private async createResponseTurn(pullRequest: PullRequestModel, logs: string, session: SessionInfo): Promise<vscode.ChatResponseTurn2 | undefined> { |
1023 | 1023 | if (logs.trim().length > 0) {
|
1024 |
| - return await this.parseSessionLogsIntoResponseTurn(logs, session); |
| 1024 | + return await this.parseSessionLogsIntoResponseTurn(pullRequest, logs, session); |
1025 | 1025 | } else if (session.state === 'in_progress') {
|
1026 | 1026 | // For in-progress sessions without logs, create a placeholder response
|
1027 | 1027 | const placeholderParts = [new vscode.ChatResponseMarkdownPart('Session is initializing...')];
|
@@ -1135,7 +1135,12 @@ export class CopilotRemoteAgentManager extends Disposable {
|
1135 | 1135 | const pollingInterval = 3000; // 3 seconds
|
1136 | 1136 |
|
1137 | 1137 | return new Promise<void>((resolve, reject) => {
|
1138 |
| - const complete = () => { |
| 1138 | + const complete = async () => { |
| 1139 | + const multiDiffPart = await this.getFileChangesMultiDiffPart(pullRequest); |
| 1140 | + if (multiDiffPart) { |
| 1141 | + stream.push(multiDiffPart); |
| 1142 | + } |
| 1143 | + |
1139 | 1144 | stream.push(new vscode.ChatResponseCommandButtonPart({
|
1140 | 1145 | title: vscode.l10n.t('Open Changes'),
|
1141 | 1146 | command: 'pr.openChanges',
|
@@ -1218,6 +1223,37 @@ export class CopilotRemoteAgentManager extends Disposable {
|
1218 | 1223 | });
|
1219 | 1224 | }
|
1220 | 1225 |
|
| 1226 | + private async getFileChangesMultiDiffPart(pullRequest: PullRequestModel): Promise<vscode.ChatResponseMultiDiffPart | undefined> { |
| 1227 | + try { |
| 1228 | + const repoInfo = await this.repoInfo(); |
| 1229 | + if (!repoInfo) { |
| 1230 | + return undefined; |
| 1231 | + } |
| 1232 | + |
| 1233 | + const { fm: folderManager } = repoInfo; |
| 1234 | + const changeModels = await PullRequestModel.getChangeModels(folderManager, pullRequest); |
| 1235 | + |
| 1236 | + if (changeModels.length === 0) { |
| 1237 | + return undefined; |
| 1238 | + } |
| 1239 | + |
| 1240 | + const diffEntries: vscode.ChatResponseDiffEntry[] = []; |
| 1241 | + for (const changeModel of changeModels) { |
| 1242 | + diffEntries.push({ |
| 1243 | + originalUri: changeModel.parentFilePath, |
| 1244 | + modifiedUri: changeModel.filePath, |
| 1245 | + goToFileUri: changeModel.filePath |
| 1246 | + }); |
| 1247 | + } |
| 1248 | + |
| 1249 | + const title = `Changes in Pull Request #${pullRequest.number}`; |
| 1250 | + return new vscode.ChatResponseMultiDiffPart(diffEntries, title); |
| 1251 | + } catch (error) { |
| 1252 | + Logger.error(`Failed to get file changes multi diff part: ${error}`, CopilotRemoteAgentManager.ID); |
| 1253 | + return undefined; |
| 1254 | + } |
| 1255 | + } |
| 1256 | + |
1221 | 1257 | private findPullRequestById(id: number): PullRequestModel | undefined {
|
1222 | 1258 | for (const folderManager of this.repositoriesManager.folderManagers) {
|
1223 | 1259 | for (const githubRepo of folderManager.gitHubRepositories) {
|
@@ -1273,10 +1309,10 @@ export class CopilotRemoteAgentManager extends Disposable {
|
1273 | 1309 | return toolPart;
|
1274 | 1310 | }
|
1275 | 1311 |
|
1276 |
| - private async parseSessionLogsIntoResponseTurn(logs: string, _session: SessionInfo): Promise<vscode.ChatResponseTurn2 | undefined> { |
| 1312 | + private async parseSessionLogsIntoResponseTurn(pullRequest: PullRequestModel, logs: string, session: SessionInfo): Promise<vscode.ChatResponseTurn2 | undefined> { |
1277 | 1313 | try {
|
1278 | 1314 | const logChunks = parseSessionLogs(logs);
|
1279 |
| - const responseParts: Array<vscode.ChatResponseMarkdownPart | vscode.ChatToolInvocationPart> = []; |
| 1315 | + const responseParts: Array<vscode.ChatResponseMarkdownPart | vscode.ChatToolInvocationPart | vscode.ChatResponseMultiDiffPart> = []; |
1280 | 1316 | let currentResponseContent = '';
|
1281 | 1317 |
|
1282 | 1318 | for (const chunk of logChunks) {
|
@@ -1312,6 +1348,13 @@ export class CopilotRemoteAgentManager extends Disposable {
|
1312 | 1348 | responseParts.push(new vscode.ChatResponseMarkdownPart(currentResponseContent.trim()));
|
1313 | 1349 | }
|
1314 | 1350 |
|
| 1351 | + if (session.state === 'completed') { |
| 1352 | + const fileChangesPart = await this.getFileChangesMultiDiffPart(pullRequest); |
| 1353 | + if (fileChangesPart) { |
| 1354 | + responseParts.push(fileChangesPart); |
| 1355 | + } |
| 1356 | + } |
| 1357 | + |
1315 | 1358 | if (responseParts.length > 0) {
|
1316 | 1359 | const responseResult: vscode.ChatResult = {};
|
1317 | 1360 | return new vscode.ChatResponseTurn2(responseParts, responseResult, 'copilot-swe-agent');
|
@@ -1427,7 +1470,7 @@ export class CopilotRemoteAgentManager extends Disposable {
|
1427 | 1470 | const isDark = vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark ||
|
1428 | 1471 | vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.HighContrast;
|
1429 | 1472 | const themeKind = isDark ? 'dark' : 'light';
|
1430 |
| - |
| 1473 | + |
1431 | 1474 | switch (status) {
|
1432 | 1475 | case CopilotPRStatus.Completed:
|
1433 | 1476 | return DataUri.copilotSuccessAsImageDataURI(
|
|
0 commit comments