sessions: retain Changes details state per session (#330619)

* sessions: retain changes details state

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* sessions: rebuild stale changes tree

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Sandeep Somavarapu
2026-08-13 10:33:33 +00:00
committed by GitHub
co-authored by Copilot
parent 81d13c0686
commit 0a8daffbbb
6 changed files with 289 additions and 22 deletions
+3
View File
@@ -136,6 +136,9 @@ Then read the relevant spec for the area you are changing (see table below). If
- **`ChatSource` is fully discriminated**: Fork and side-chat sources both require explicit `kind` plus stable top-level `turnId`. Do not add no-kind compatibility helpers or route by structural property presence; switch directly on `source.kind`.
- **Sessions menu ids must live in the shared menu registry**: Do not declare sessions-owned `new MenuId(...)` constants ad hoc inside individual parts. Add them to `browser/menus.ts` under `Menus` with discoverable `SessionsEditor...` names so ownership and reuse stay obvious.
- **Events instead of observables**: Session state must flow through `IObservable`, not `Event`. Use `autorun`/`derived` for reactive UI, not `onDid*` event listeners.
- **Keep feature-specific ObjectTree restoration local**: data trees such as Explorer accept complete view state through `setInput`, but `ObjectTree.setChildren` does not. Do not widen the shared tree widget API for one Sessions consumer; apply saved collapse state to the replacement children, then restore focus, selection, and scroll from identities in the feature.
- **Bound retained Changes-details state like editor view state**: keep per-session details snapshots in a 100-entry LRU, move them on draft commit, and clear them only on definitive delete/discard events. Provider `removed` deltas are temporary eviction signals and must not discard durable UI state.
- **Do not persist a view snapshot through an independently registered shutdown listener**: service and view-container `onWillSaveState` listener order can save the service before the view captures its final state. Since the Changes tree is sampled only at lifecycle boundaries, persist synchronously when that sample updates the service, and likewise persist replacement/deletion mutations immediately.
- **Importing from providers**: Non-provider `contrib/*` code must never import from `contrib/providers/*`. Extract shared interfaces to `services/` or `common/`.
- **`IAgentSessionsService` in shared code**: `IAgentSessionsService` (`vs/workbench/contrib/chat/browser/agentSessions/agentSessionsService`) is a Copilot-provider internal and may be imported **only** by the Copilot chat sessions provider (`contrib/providers/copilotChatSessions/`). Shared sessions code (core/services/non-provider contribs, e.g. the sessions list or visible-sessions grid) must stay provider-agnostic and go through `ISession`/`ISessionsManagementService` — never reach into `model.observeSession(...)` etc. for lazy loading. This is enforced by an ESLint `no-restricted-imports` ban scoped to `src/vs/sessions/**` (Copilot provider exempted).
- **Missing entry point import**: New contribution files must be imported in the appropriate `sessions.*.main.ts` entry point to be loaded (for example `sessions.common.main.ts`, `sessions.desktop.main.ts`, `sessions.web.main.ts`, or `sessions.web.main.internal.ts`).