From e4b25622b5aad4974c88e06964810a74e50385b4 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:44:30 +0200 Subject: [PATCH 1/2] Agents - Changes view pickers should work with multiple chats in a session --- .../changes/browser/changesViewModel.ts | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/vs/sessions/contrib/changes/browser/changesViewModel.ts b/src/vs/sessions/contrib/changes/browser/changesViewModel.ts index d5d43af69822f..89d26ad7cb399 100644 --- a/src/vs/sessions/contrib/changes/browser/changesViewModel.ts +++ b/src/vs/sessions/contrib/changes/browser/changesViewModel.ts @@ -14,7 +14,7 @@ import { IStorageService, StorageScope, StorageTarget } from '../../../../platfo import { IAgentSessionsService } from '../../../../workbench/contrib/chat/browser/agentSessions/agentSessionsService.js'; import { IChatSessionFileChange, IChatSessionFileChange2 } from '../../../../workbench/contrib/chat/common/chatSessionsService.js'; import { GitDiffChange, IGitService } from '../../../../workbench/contrib/git/common/gitService.js'; -import { COPILOT_CLOUD_SESSION_TYPE } from '../../../services/sessions/common/session.js'; +import { COPILOT_CLOUD_SESSION_TYPE, IChat } from '../../../services/sessions/common/session.js'; import { ISessionsManagementService } from '../../../services/sessions/common/sessionsManagement.js'; import { IAgentFeedbackService } from '../../agentFeedback/browser/agentFeedbackService.js'; import { CodeReviewStateKind, getCodeReviewFilesFromSessionChanges, getCodeReviewVersion, ICodeReviewService, PRReviewStateKind } from '../../codeReview/browser/codeReviewService.js'; @@ -40,6 +40,25 @@ function toIChatSessionFileChange2(changes: GitDiffChange[], originalRef: string } satisfies IChatSessionFileChange2)); } +function sortChatByLastTurnEndDesc(chatA: IChat, chatB: IChat): number { + const chatALastTurnEnd = chatA.lastTurnEnd.get(); + const chatBLastTurnEnd = chatB.lastTurnEnd.get(); + + if (!chatALastTurnEnd && !chatBLastTurnEnd) { + return 0; + } + + if (!chatALastTurnEnd) { + return 1; + } + + if (!chatBLastTurnEnd) { + return -1; + } + + return chatBLastTurnEnd.getTime() - chatALastTurnEnd.getTime(); +} + export interface ActiveSessionState { readonly isolationMode: IsolationMode; readonly hasGitRepository: boolean; @@ -129,8 +148,21 @@ export class ChangesViewModel extends Disposable { // Active session last checkpoint ref this.activeSessionLastCheckpointRefObs = derived(reader => { - const metadata = this._activeSessionMetadataObs.read(reader); - return metadata?.lastCheckpointRef as string | undefined; + const activeSessionChats = this.sessionManagementService.activeSession.read(reader)?.chats.read(reader); + if (!activeSessionChats || activeSessionChats.length === 0) { + return undefined; + } + + // Session has only one chat + if (activeSessionChats.length === 1) { + const metadata = this._activeSessionMetadataObs.read(reader); + return metadata?.lastCheckpointRef as string | undefined; + } + + // Session has multiple chats - find the last chat that completed + const chatsSortedByLastTurnEnd = activeSessionChats.toSorted(sortChatByLastTurnEndDesc); + const model = this.agentSessionsService.getSession(chatsSortedByLastTurnEnd[0].resource); + return model?.metadata?.lastCheckpointRef as string | undefined; }); // Active session state @@ -429,7 +461,7 @@ export class ChangesViewModel extends Disposable { private async _getRepositoryChanges(repositoryPath: string, firstCheckpointRef: string, lastCheckpointRef: string): Promise { const repository = await this.gitService.openRepository(URI.file(repositoryPath)); - const changes = await repository?.diffBetweenWithStats(firstCheckpointRef, lastCheckpointRef) ?? []; + const changes = await repository?.diffBetweenWithStats2(`${firstCheckpointRef}..${lastCheckpointRef}`) ?? []; return toIChatSessionFileChange2(changes, firstCheckpointRef, lastCheckpointRef); } From 62f59b69d5112405f27a67d1783b7bf43094d87e Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:04:40 +0200 Subject: [PATCH 2/2] Pull request feedback --- .../changes/browser/changesViewModel.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/vs/sessions/contrib/changes/browser/changesViewModel.ts b/src/vs/sessions/contrib/changes/browser/changesViewModel.ts index 89d26ad7cb399..bed9a544d1a53 100644 --- a/src/vs/sessions/contrib/changes/browser/changesViewModel.ts +++ b/src/vs/sessions/contrib/changes/browser/changesViewModel.ts @@ -14,7 +14,7 @@ import { IStorageService, StorageScope, StorageTarget } from '../../../../platfo import { IAgentSessionsService } from '../../../../workbench/contrib/chat/browser/agentSessions/agentSessionsService.js'; import { IChatSessionFileChange, IChatSessionFileChange2 } from '../../../../workbench/contrib/chat/common/chatSessionsService.js'; import { GitDiffChange, IGitService } from '../../../../workbench/contrib/git/common/gitService.js'; -import { COPILOT_CLOUD_SESSION_TYPE, IChat } from '../../../services/sessions/common/session.js'; +import { COPILOT_CLOUD_SESSION_TYPE } from '../../../services/sessions/common/session.js'; import { ISessionsManagementService } from '../../../services/sessions/common/sessionsManagement.js'; import { IAgentFeedbackService } from '../../agentFeedback/browser/agentFeedbackService.js'; import { CodeReviewStateKind, getCodeReviewFilesFromSessionChanges, getCodeReviewVersion, ICodeReviewService, PRReviewStateKind } from '../../codeReview/browser/codeReviewService.js'; @@ -40,9 +40,9 @@ function toIChatSessionFileChange2(changes: GitDiffChange[], originalRef: string } satisfies IChatSessionFileChange2)); } -function sortChatByLastTurnEndDesc(chatA: IChat, chatB: IChat): number { - const chatALastTurnEnd = chatA.lastTurnEnd.get(); - const chatBLastTurnEnd = chatB.lastTurnEnd.get(); +function sortDateDesc(dateA: Date | undefined, dateB: Date | undefined): number { + const chatALastTurnEnd = dateA?.getTime(); + const chatBLastTurnEnd = dateB?.getTime(); if (!chatALastTurnEnd && !chatBLastTurnEnd) { return 0; @@ -56,7 +56,7 @@ function sortChatByLastTurnEndDesc(chatA: IChat, chatB: IChat): number { return -1; } - return chatBLastTurnEnd.getTime() - chatALastTurnEnd.getTime(); + return chatBLastTurnEnd - chatALastTurnEnd; } export interface ActiveSessionState { @@ -160,7 +160,13 @@ export class ChangesViewModel extends Disposable { } // Session has multiple chats - find the last chat that completed - const chatsSortedByLastTurnEnd = activeSessionChats.toSorted(sortChatByLastTurnEndDesc); + const chatsSortedByLastTurnEnd = activeSessionChats.toSorted((chatA, chatB) => { + const chatALastTurnEnd = chatA.lastTurnEnd.read(reader); + const chatBLastTurnEnd = chatB.lastTurnEnd.read(reader); + + return sortDateDesc(chatALastTurnEnd, chatBLastTurnEnd); + }); + const model = this.agentSessionsService.getSession(chatsSortedByLastTurnEnd[0].resource); return model?.metadata?.lastCheckpointRef as string | undefined; });