@@ -17,7 +17,7 @@ import { ITelemetryService } from '../../../platform/telemetry/common/telemetry'
1717import { IWorkspaceService } from '../../../platform/workspace/common/workspaceService' ;
1818import { disposableTimeout , raceCancellation } from '../../../util/vs/base/common/async' ;
1919import { isCancellationError } from '../../../util/vs/base/common/errors' ;
20- import { Emitter , Event } from '../../../util/vs/base/common/event' ;
20+ import { Emitter } from '../../../util/vs/base/common/event' ;
2121import { Disposable , DisposableStore , IDisposable , IReference , toDisposable } from '../../../util/vs/base/common/lifecycle' ;
2222import { autorun } from '../../../util/vs/base/common/observable' ;
2323import { isEqual } from '../../../util/vs/base/common/resources' ;
@@ -114,12 +114,8 @@ function escapeXml(text: string): string {
114114 . replace ( / ' / g, ''' ) ;
115115}
116116
117- export class CopilotCLIChatSessionItemProvider extends Disposable implements vscode . ChatSessionItemProvider {
118- private readonly _onDidChangeChatSessionItems = this . _register ( new Emitter < void > ( ) ) ;
119- public readonly onDidChangeChatSessionItems : Event < void > = this . _onDidChangeChatSessionItems . event ;
120-
121- private readonly _onDidCommitChatSessionItem = this . _register ( new Emitter < { original : vscode . ChatSessionItem ; modified : vscode . ChatSessionItem } > ( ) ) ;
122- public readonly onDidCommitChatSessionItem : Event < { original : vscode . ChatSessionItem ; modified : vscode . ChatSessionItem } > = this . _onDidCommitChatSessionItem . event ;
117+ export class CopilotCLIChatSessionItemProvider extends Disposable {
118+ private readonly controller : vscode . ChatSessionItemController ;
123119
124120 constructor (
125121 @ICopilotCLISessionService private readonly copilotcliSessionService : ICopilotCLISessionService ,
@@ -129,27 +125,45 @@ export class CopilotCLIChatSessionItemProvider extends Disposable implements vsc
129125 ) {
130126 super ( ) ;
131127 this . _register ( this . terminalIntegration ) ;
128+
129+ this . controller = this . _register ( vscode . chat . createChatSessionItemController (
130+ 'copilotcli' ,
131+ ( ) => this . refresh ( )
132+ ) ) ;
133+
132134 this . _register ( this . copilotcliSessionService . onDidChangeSessions ( ( ) => {
133135 this . notifySessionsChange ( ) ;
134136 } ) ) ;
135137 }
136138
137139 public notifySessionsChange ( ) : void {
138- this . _onDidChangeChatSessionItems . fire ( ) ;
140+ void this . controller . refreshHandler ( ) ;
139141 }
140142
141143 public swap ( original : vscode . ChatSessionItem , modified : vscode . ChatSessionItem ) : void {
142- this . _onDidCommitChatSessionItem . fire ( { original, modified } ) ;
144+ this . controller . items . delete ( original . resource ) ;
145+ this . controller . items . add ( modified ) ;
143146 }
144147
145- public async provideChatSessionItems ( token : vscode . CancellationToken ) : Promise < vscode . ChatSessionItem [ ] > {
146- const sessions = await this . copilotcliSessionService . getAllSessions ( token ) ;
147- const diskSessions = await Promise . all ( sessions . map ( async session => this . _toChatSessionItem ( session ) ) ) ;
148+ private async refresh ( ) : Promise < void > {
149+ const ctx = new vscode . CancellationTokenSource ( ) ;
150+ try {
151+ const sessions = await this . copilotcliSessionService . getAllSessions ( ctx . token ) ;
152+ const items : vscode . ChatSessionItem [ ] = [ ] ;
153+
154+ for ( const session of sessions ) {
155+ const item = await this . _toChatSessionItem ( session ) ;
156+ items . push ( item ) ;
157+ }
148158
149- const count = diskSessions . length ;
150- this . commandExecutionService . executeCommand ( 'setContext' , 'github.copilot.chat.cliSessionsEmpty' , count === 0 ) ;
159+ this . controller . items . replace ( items ) ;
151160
152- return diskSessions ;
161+ const count = items . length ;
162+ this . commandExecutionService . executeCommand ( 'setContext' , 'github.copilot.chat.cliSessionsEmpty' , count === 0 ) ;
163+ }
164+ finally {
165+ ctx . dispose ( ) ;
166+ }
153167 }
154168
155169 private async _toChatSessionItem ( session : ICopilotCLISessionItem ) : Promise < vscode . ChatSessionItem > {
@@ -158,27 +172,25 @@ export class CopilotCLIChatSessionItemProvider extends Disposable implements vsc
158172
159173 const label = session . label ;
160174
175+ const item = this . controller . createChatSessionItem ( resource , label ) ;
176+
161177 // Badge
162- let badge : vscode . MarkdownString | undefined ;
163178 if ( worktreeProperties ?. branchName ) {
164- badge = new vscode . MarkdownString ( `$(worktree) ${ worktreeProperties . branchName } ` ) ;
179+ const badge = new vscode . MarkdownString ( `$(worktree) ${ worktreeProperties . branchName } ` ) ;
165180 badge . supportThemeIcons = true ;
181+ item . badge = badge ;
166182 }
167183
168184 // Statistics
169- const changes = await this . worktreeManager . getWorktreeChanges ( session . id ) ;
185+ item . changes = await this . worktreeManager . getWorktreeChanges ( session . id ) ;
170186
171187 // Status
172- const status = session . status ?? vscode . ChatSessionStatus . Completed ;
188+ item . status = session . status ?? vscode . ChatSessionStatus . Completed ;
173189
174- return {
175- resource,
176- label,
177- badge,
178- timing : session . timing ,
179- changes,
180- status
181- } satisfies vscode . ChatSessionItem ;
190+ // Timing
191+ item . timing = session . timing ;
192+
193+ return item ;
182194 }
183195
184196 public async createCopilotCLITerminal ( ) : Promise < void > {
0 commit comments