diff --git a/src/vs/platform/agentHost/node/agentHostStateManager.ts b/src/vs/platform/agentHost/node/agentHostStateManager.ts index d5f643cde5ce1..d824f1fd3531e 100644 --- a/src/vs/platform/agentHost/node/agentHostStateManager.ts +++ b/src/vs/platform/agentHost/node/agentHostStateManager.ts @@ -306,12 +306,16 @@ export class AgentHostStateManager extends Disposable { const entry = this._sessionStates.get(session); return entry ? this._toSummary(session, entry) : undefined; }, - (session, changes) => this._onDidEmitNotification.fire({ - type: 'root/sessionSummaryChanged', - channel: ROOT_STATE_URI, - session, - changes, - }), + (session, changes) => { + if (this._publishedSessionSummaries.has(session)) { + this._onDidEmitNotification.fire({ + type: 'root/sessionSummaryChanged', + channel: ROOT_STATE_URI, + session, + changes, + }); + } + }, )); } private readonly _log = (msg: string) => this._logService.warn(`[AgentHostStateManager] ${msg}`); diff --git a/src/vs/platform/agentHost/test/node/agentHostStateManager.test.ts b/src/vs/platform/agentHost/test/node/agentHostStateManager.test.ts index 9e738679baae4..d4f14c3a7cd82 100644 --- a/src/vs/platform/agentHost/test/node/agentHostStateManager.test.ts +++ b/src/vs/platform/agentHost/test/node/agentHostStateManager.test.ts @@ -602,6 +602,37 @@ suite('AgentHostStateManager', () => { assert.strictEqual(notifications.length, 0, 'should not emit notification for restored sessions'); }); + test('restored unpublished sessions retain summary changes without notifying root clients', () => { + return runWithFakedTimers({ useFakeTimers: true }, async () => { + manager.restoreSession(makeSessionSummary(), []); + const notifications: INotification[] = []; + disposables.add(manager.onDidEmitNotification(notification => notifications.push(notification))); + + manager.dispatchServerAction(sessionUri, { type: ActionType.SessionTitleChanged, title: 'Hidden Title' }); + await new Promise(resolve => setTimeout(resolve, 150)); + const hiddenChanges = notifications.filter(notification => notification.type === NotificationType.SessionSummaryChanged); + const retainedTitle = manager.getSessionSummary(sessionUri)?.title; + + manager.setSessionSummaryPublished(sessionUri, true); + const added = notifications.find(notification => notification.type === NotificationType.SessionAdded); + manager.dispatchServerAction(sessionUri, { type: ActionType.SessionTitleChanged, title: 'Visible Title' }); + await new Promise(resolve => setTimeout(resolve, 150)); + const visibleChanges = notifications.filter(notification => notification.type === NotificationType.SessionSummaryChanged) as SessionSummaryChangedParams[]; + + assert.deepStrictEqual({ + hiddenChangeCount: hiddenChanges.length, + retainedTitle, + addedTitle: added?.type === NotificationType.SessionAdded ? added.summary.title : undefined, + visibleChanges: visibleChanges.map(change => change.changes.title), + }, { + hiddenChangeCount: 0, + retainedTitle: 'Hidden Title', + addedTitle: 'Hidden Title', + visibleChanges: ['Visible Title'], + }); + }); + }); + test('restoreSession emits sessionSummaryChanged clearing the adoptable marker for a previously surfaced session', () => { // A surfaced adoptable-legacy session is announced with the marker; adopting // it via restoreSession must notify clients the marker was cleared so they diff --git a/src/vs/sessions/contrib/providers/agentHost/AGENT_HOST_SESSIONS_PROVIDER.md b/src/vs/sessions/contrib/providers/agentHost/AGENT_HOST_SESSIONS_PROVIDER.md index fbb5f1b942f03..5d4d305e7699c 100644 --- a/src/vs/sessions/contrib/providers/agentHost/AGENT_HOST_SESSIONS_PROVIDER.md +++ b/src/vs/sessions/contrib/providers/agentHost/AGENT_HOST_SESSIONS_PROVIDER.md @@ -117,7 +117,7 @@ The **only** per-provider difference is the storage key: local uses the fixed `l ### External session visibility -Provider-native sessions discovered outside the Agent Host carry `_meta.external`. `chat.agentSessions.showExternal` controls whether the catalog publishes none, all, the last 24 hours, or the last 7 days (the default). Configuration changes publish or unpublish matching summaries immediately, including restored sessions, while retaining live Agent Host state so a later settings change can surface them again. The state manager distinguishes a summary retained as the diff baseline from one actually published through `root/sessionAdded`; restoring a filtered session records the former without implying the latter. +Provider-native sessions discovered outside the Agent Host carry `_meta.external`. `chat.agentSessions.showExternal` controls whether the catalog publishes none, all, the last 24 hours, or the last 7 days (the default). Configuration changes publish or unpublish matching summaries immediately, including restored sessions, while retaining live Agent Host state so a later settings change can surface them again. The state manager distinguishes a summary retained as the diff baseline from one actually published through `root/sessionAdded`; restoring a filtered session records the former without implying the latter, and hidden summary changes advance that baseline without emitting root notifications. Both the regular VS Code agent sessions list and the Agents Window Sessions list expose this setting as an `External` submenu directly below their provider filters. The checked option follows the effective configuration value, and selecting an option writes the user setting.