diff --git a/src/vs/sessions/SESSIONS_LIST.md b/src/vs/sessions/SESSIONS_LIST.md index 9f9f54485345c..c830170a0ebe7 100644 --- a/src/vs/sessions/SESSIONS_LIST.md +++ b/src/vs/sessions/SESSIONS_LIST.md @@ -90,6 +90,7 @@ Pinned sessions appear in a dedicated "Pinned" section at the top. Pin state is - Sessions start as **unread** - A session becomes **read** when the user opens it or explicitly marks it - A session becomes **unread** when it completes in the background (transitions from InProgress to a terminal status while not active) +- Pin and read state are cleaned up when a provider reports a real session removal; remote agent host disconnects hide cached sessions without reporting them as removed ### Navigation diff --git a/src/vs/sessions/contrib/providers/agentHost/browser/baseAgentHostSessionsProvider.ts b/src/vs/sessions/contrib/providers/agentHost/browser/baseAgentHostSessionsProvider.ts index 18f2c211a85cf..8e2320b65bf1d 100644 --- a/src/vs/sessions/contrib/providers/agentHost/browser/baseAgentHostSessionsProvider.ts +++ b/src/vs/sessions/contrib/providers/agentHost/browser/baseAgentHostSessionsProvider.ts @@ -2040,7 +2040,7 @@ export abstract class BaseAgentHostSessionsProvider extends Disposable implement this._refreshSessions(); } - protected async _refreshSessions(): Promise { + protected async _refreshSessions(announceExistingAsAdded = false): Promise { const connection = this.connection; if (!connection) { return; @@ -2057,6 +2057,9 @@ export abstract class BaseAgentHostSessionsProvider extends Disposable implement const existing = this._sessionCache.get(rawId); if (existing) { + if (announceExistingAsAdded) { + added.push(existing); + } if (existing.update(meta)) { changed.push(existing); } diff --git a/src/vs/sessions/contrib/providers/remoteAgentHost/browser/remoteAgentHostSessionsProvider.ts b/src/vs/sessions/contrib/providers/remoteAgentHost/browser/remoteAgentHostSessionsProvider.ts index 510af4f81dee0..fcb481b46b6b0 100644 --- a/src/vs/sessions/contrib/providers/remoteAgentHost/browser/remoteAgentHostSessionsProvider.ts +++ b/src/vs/sessions/contrib/providers/remoteAgentHost/browser/remoteAgentHostSessionsProvider.ts @@ -375,6 +375,7 @@ export class RemoteAgentHostSessionsProvider extends BaseAgentHostSessionsProvid return; } + const wasUnpublished = this._unpublished; this._connectionListeners.clear(); this._sessionStateSubscriptions.clearAndDisposeAll(); this._connection = connection; @@ -396,7 +397,7 @@ export class RemoteAgentHostSessionsProvider extends BaseAgentHostSessionsProvid // Always refresh sessions when a connection is (re)established this._cacheInitialized = true; - this._refreshSessions(); + this._refreshSessions(wasUnpublished); } /** @@ -450,9 +451,8 @@ export class RemoteAgentHostSessionsProvider extends BaseAgentHostSessionsProvid return; } this._unpublished = true; - const removed: ISession[] = Array.from(this._sessionCache.values()); - if (removed.length > 0) { - this._onDidChangeSessions.fire({ added: [], removed, changed: [] }); + if (this._sessionCache.size > 0) { + this._onDidChangeSessions.fire({ added: [], removed: [], changed: [] }); } } diff --git a/src/vs/sessions/contrib/providers/remoteAgentHost/test/browser/remoteAgentHostSessionsProvider.test.ts b/src/vs/sessions/contrib/providers/remoteAgentHost/test/browser/remoteAgentHostSessionsProvider.test.ts index 6547363e08d03..c63a268b00beb 100644 --- a/src/vs/sessions/contrib/providers/remoteAgentHost/test/browser/remoteAgentHostSessionsProvider.test.ts +++ b/src/vs/sessions/contrib/providers/remoteAgentHost/test/browser/remoteAgentHostSessionsProvider.test.ts @@ -838,9 +838,10 @@ suite('RemoteAgentHostSessionsProvider', () => { assert.deepStrictEqual( { sessionCount: provider.getSessions().length, + eventCount: events.length, eventRemovedTitles: events.flatMap(e => e.removed.map(s => s.title.get())), }, - { sessionCount: 0, eventRemovedTitles: ['Keep Me'] }, + { sessionCount: 0, eventCount: 1, eventRemovedTitles: [] }, ); // Flush triggers onWillSaveState; the metadata must survive so the @@ -862,18 +863,30 @@ suite('RemoteAgentHostSessionsProvider', () => { provider.unpublishCachedSessions(); assert.strictEqual(provider.getSessions().length, 0); + const events: ISessionChangeEvent[] = []; + disposables.add(provider.onDidChangeSessions(e => events.push(e))); // Simulate the host coming back online with a fresh connection that - // still reports the same session. + // still reports the same session with updated metadata. const reconnected = new MockAgentConnection(); disposables.add(toDisposable(() => reconnected.dispose())); - reconnected.addSession(createSession('restore-me', { summary: 'Restore Me' })); + reconnected.addSession(createSession('restore-me', { summary: 'Restored' })); provider.setConnection(reconnected); await timeout(0); assert.deepStrictEqual( - provider.getSessions().map(s => s.title.get()), - ['Restore Me'], + { + sessions: provider.getSessions().map(s => s.title.get()), + added: events.flatMap(e => e.added.map(s => s.title.get())), + changed: events.flatMap(e => e.changed.map(s => s.title.get())), + removed: events.flatMap(e => e.removed.map(s => s.title.get())), + }, + { + sessions: ['Restored'], + added: ['Restored'], + changed: ['Restored'], + removed: [], + }, ); }));