@@ -9,17 +9,17 @@ import vscode, { ChatPromptReference } from 'vscode';
99import { parseSessionLogs , parseToolCallDetails , StrReplaceEditorToolData } from '../../common/sessionParsing' ;
1010import { COPILOT_ACCOUNTS } from '../common/comment' ;
1111import { CopilotRemoteAgentConfig } from '../common/config' ;
12- import { COPILOT_LOGINS , COPILOT_SWE_AGENT , copilotEventToStatus , CopilotPRStatus , mostRecentCopilotEvent } from '../common/copilot' ;
12+ import { COPILOT_LOGINS , COPILOT_SWE_AGENT , CopilotPRStatus , mostRecentCopilotEvent } from '../common/copilot' ;
1313import { commands } from '../common/executeCommands' ;
1414import { Disposable } from '../common/lifecycle' ;
1515import Logger from '../common/logger' ;
1616import { GitHubRemote } from '../common/remote' ;
1717import { CODING_AGENT , CODING_AGENT_AUTO_COMMIT_AND_PUSH } from '../common/settingKeys' ;
1818import { ITelemetry } from '../common/telemetry' ;
1919import { toOpenPullRequestWebviewUri } from '../common/uri' ;
20- import { copilotEventToSessionStatus , copilotPRStatusToSessionStatus , IAPISessionLogs , ICopilotRemoteAgentCommandArgs , ICopilotRemoteAgentCommandResponse , OctokitCommon , RemoteAgentResult , RepoInfo } from './common' ;
21- import { ChatSessionFromSummarizedChat , ChatSessionWithPR , CopilotApi , getCopilotApi , RemoteAgentJobPayload , SessionInfo , SessionSetupStep } from './copilotApi' ;
22- import { CodingAgentPRAndStatus , CopilotPRWatcher , CopilotStateModel } from './copilotPrWatcher' ;
20+ import { copilotEventToSessionStatus , IAPISessionLogs , ICopilotRemoteAgentCommandArgs , ICopilotRemoteAgentCommandResponse , OctokitCommon , RemoteAgentResult , RepoInfo } from './common' ;
21+ import { ChatSessionFromSummarizedChat , ChatSessionWithPR , CopilotApi , getCopilotApi , RemoteAgentJobPayload , SessionInfo , SessionPullRequestInfo , SessionSetupStep } from './copilotApi' ;
22+ import { CopilotPRWatcher , CopilotStateModel } from './copilotPrWatcher' ;
2323import { ChatSessionContentBuilder } from './copilotRemoteAgent/chatSessionContentBuilder' ;
2424import { GitOperationsManager } from './copilotRemoteAgent/gitOperationsManager' ;
2525import { CredentialStore } from './credentials' ;
@@ -82,10 +82,7 @@ export class CopilotRemoteAgentManager extends Disposable {
8282 private readonly gitOperationsManager : GitOperationsManager ;
8383 private readonly ephemeralChatSessions : Map < string , ChatSessionFromSummarizedChat > = new Map ( ) ;
8484
85- private codingAgentPRsPromise : Promise < {
86- item : PullRequestModel ;
87- status : CopilotPRStatus ;
88- } [ ] > | undefined ;
85+ private codingAgentPRsPromise : Promise < ChatSessionWithPR [ ] > | undefined ;
8986
9087 constructor ( private credentialStore : CredentialStore , public repositoriesManager : RepositoriesManager , private telemetry : ITelemetry , private context : vscode . ExtensionContext ) {
9188 super ( ) ;
@@ -868,7 +865,7 @@ export class CopilotRemoteAgentManager extends Disposable {
868865 } ;
869866 }
870867
871- public async provideChatSessions ( token : vscode . CancellationToken ) : Promise < ChatSessionWithPR [ ] > {
868+ public async provideChatSessions ( token : vscode . CancellationToken ) : Promise < vscode . ChatSessionItem [ ] > {
872869 try {
873870 const capi = await this . copilotApi ;
874871 if ( ! capi ) {
@@ -882,54 +879,78 @@ export class CopilotRemoteAgentManager extends Disposable {
882879
883880 await this . waitRepoManagerInitialization ( ) ;
884881
885- let codingAgentPRs : CodingAgentPRAndStatus [ ] = [ ] ;
886- if ( this . _stateModel . isInitialized ) {
887- codingAgentPRs = this . _stateModel . all ;
888- Logger . debug ( `Fetched PRs from state model: ${ codingAgentPRs . length } ` , CopilotRemoteAgentManager . ID ) ;
889- } else {
890- this . codingAgentPRsPromise = this . codingAgentPRsPromise ?? new Promise < CodingAgentPRAndStatus [ ] > ( async ( resolve ) => {
891- try {
892- const sessions = await capi . getAllCodingAgentPRs ( this . repositoriesManager ) ;
893- const prAndStatus = await Promise . all ( sessions . map ( async pr => {
894- const timeline = await pr . getCopilotTimelineEvents ( pr ) ;
895- const status = copilotEventToStatus ( mostRecentCopilotEvent ( timeline ) ) ;
896- return { item : pr , status } ;
897- } ) ) ;
898-
899- resolve ( prAndStatus ) ;
900- } catch ( error ) {
901- Logger . error ( `Failed to fetch coding agent PRs: ${ error } ` , CopilotRemoteAgentManager . ID ) ;
902- resolve ( [ ] ) ;
882+ const currentRepositories = this . repositoriesManager . folderManagers . map ( folder => folder . gitHubRepositories ) . flat ( ) ;
883+
884+ this . codingAgentPRsPromise = this . codingAgentPRsPromise ?? new Promise < vscode . ChatSessionItem [ ] > ( async ( resolve ) => {
885+ const sessions = await capi . getAllSessions ( undefined ) ;
886+ const sessionMap = new Map < string , SessionInfo [ ] > ( ) ;
887+
888+ for ( const session of sessions ) {
889+ if ( ! session . resource_global_id ) {
890+ continue ;
903891 }
892+ const existing = sessionMap . get ( session . resource_global_id ) || [ ] ;
893+ existing . push ( session ) ;
894+ existing . sort ( ( a , b ) => new Date ( a . created_at ) . getTime ( ) - new Date ( b . created_at ) . getTime ( ) ) ;
895+ sessionMap . set ( session . resource_global_id , existing ) ;
896+ }
897+
898+ const groupedSessions = Array . from ( sessionMap . values ( ) ) . sort ( ( a , b ) => {
899+ const aFirstSession = a [ 0 ] ;
900+ const bFirstSession = b [ 0 ] ;
901+ return new Date ( aFirstSession . created_at ) . getTime ( ) - new Date ( bFirstSession . created_at ) . getTime ( ) ;
904902 } ) ;
905- codingAgentPRs = await this . codingAgentPRsPromise ;
906- Logger . debug ( `Fetched PRs from API: ${ codingAgentPRs . length } ` , CopilotRemoteAgentManager . ID ) ;
907- }
908- return await Promise . all ( codingAgentPRs . map ( async prAndStatus => {
909- const timestampNumber = new Date ( prAndStatus . item . createdAt ) . getTime ( ) ;
910- const status = copilotPRStatusToSessionStatus ( prAndStatus . status ) ;
911- const pullRequest = prAndStatus . item ;
912- const tooltip = await issueMarkdown ( pullRequest , this . context , this . repositoriesManager ) ;
913-
914- const uri = await toOpenPullRequestWebviewUri ( { owner : pullRequest . remote . owner , repo : pullRequest . remote . repositoryName , pullRequestNumber : pullRequest . number } ) ;
915- const description = new vscode . MarkdownString ( `[#${ pullRequest . number } ](${ uri . toString ( ) } )` ) ; // pullRequest.base.ref === defaultBranch ? `PR #${pullRequest.number}`: `PR #${pullRequest.number} → ${pullRequest.base.ref}`;
916- return {
917- id : `${ pullRequest . number } ` ,
918- label : pullRequest . title || `Session ${ pullRequest . number } ` ,
919- iconPath : this . getIconForSession ( status ) ,
920- pullRequest : pullRequest ,
921- description : description ,
922- tooltip,
923- status,
924- timing : {
925- startTime : timestampNumber
926- } ,
927- statistics : pullRequest . item . additions !== undefined && pullRequest . item . deletions !== undefined && ( pullRequest . item . additions > 0 || pullRequest . item . deletions > 0 ) ? {
928- insertions : pullRequest . item . additions ,
929- deletions : pullRequest . item . deletions
930- } : undefined
931- } ;
932- } ) ) ;
903+
904+ const filteredPRs = ( await Promise . all ( groupedSessions . map ( async sessions => {
905+ const initialSession = sessions [ 0 ] ;
906+
907+ const pullRequestInfo = await capi . getPullRequestFromSession ( initialSession . resource_global_id ) ;
908+ if ( ! pullRequestInfo ) {
909+ return ;
910+ }
911+
912+ return {
913+ id : initialSession . resource_global_id ,
914+ pullRequest : pullRequestInfo ,
915+ sessions
916+ } ;
917+ } ) ) ) . filter ( pr => {
918+ if ( ! pr ) {
919+ return false ;
920+ }
921+
922+ // Filter out PRs that are not in the current repositories
923+ const prRepo = currentRepositories . find ( repo =>
924+ repo . remote . owner === pr . pullRequest . headRepository . owner . login &&
925+ repo . remote . repositoryName === pr . pullRequest . headRepository . name
926+ ) ;
927+
928+ if ( ! prRepo ) {
929+ return false ;
930+ }
931+
932+ return true ;
933+ } ) . map ( ( pr : { id : string , pullRequest : SessionPullRequestInfo ; sessions : SessionInfo [ ] } ) => {
934+ const { id, pullRequest, sessions } = pr ;
935+ const latestSession = sessions [ sessions . length - 1 ] ;
936+ const status = latestSession . state === 'completed' ? vscode . ChatSessionStatus . Completed : ( latestSession . state === 'failed' ? vscode . ChatSessionStatus . Failed : vscode . ChatSessionStatus . InProgress ) ;
937+
938+ return {
939+ id : id ,
940+ label : pullRequest . title || `Session ${ pullRequest . number } ` ,
941+ status : status ,
942+ description : `${ pullRequest . headRepository . owner . login } /${ pullRequest . headRepository . name } #${ pullRequest . number } ` ,
943+ statistics : pullRequest . additions !== undefined && pullRequest . deletions !== undefined && ( pullRequest . additions > 0 || pullRequest . deletions > 0 ) ? {
944+ insertions : pullRequest . additions ,
945+ deletions : pullRequest . deletions
946+ } : undefined
947+ } ;
948+ } ) ;
949+
950+ resolve ( filteredPRs ) ;
951+ } ) ;
952+
953+ return this . codingAgentPRsPromise ;
933954 } catch ( error ) {
934955 Logger . error ( `Failed to provide coding agents information: ${ error } ` , CopilotRemoteAgentManager . ID ) ;
935956 } finally {
0 commit comments