agentHost: observe capabilities lazily in session adapters - #330853
Merged
Sandeep Somavarapu (sandy081) merged 1 commit intoAug 17, 2026
Merged
agentHost: observe capabilities lazily in session adapters#330853Sandeep Somavarapu (sandy081) merged 1 commit into
Sandeep Somavarapu (sandy081) merged 1 commit into
Conversation
Every cached AgentHostSessionAdapter eagerly subscribed to the shared agent-capabilities observable, so a window restoring hundreds of sessions installed hundreds of observers and tripped the listener leak detector. Most of those observers had nothing to do: the autorun only re-applies a chat catalog, and an adapter that never received one has no catalog to reconcile. Install the observer on the first applyChatCatalog call instead, so only adapters with catalog state to reapply subscribe. Late-hydrating capabilities still re-expand a collapsed peer catalog. Found while self-hosting Insiders. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Alexandru Dima (alexdima)
requested review from
Sandeep Somavarapu (sandy081)
and
a balanced review from Copilot
August 14, 2026 13:13
Contributor
There was a problem hiding this comment.
Pull request overview
Lazily observes Agent Host capabilities only when a session adapter has a chat catalog requiring reconciliation, preventing unnecessary observers.
Changes:
- Moves capability observation from construction to first catalog application.
- Adds regression coverage for lazy observation and late hydration.
- Documents the updated architecture.
Show a summary per file
| File | Description |
|---|---|
baseAgentHostSessionsProvider.ts |
Lazily installs the capability observer. |
localAgentHostSessionsProvider.test.ts |
Tests observer counts and catalog hydration. |
AGENT_HOST_SESSIONS_PROVIDER.md |
Documents lazy capability observation. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 3/3 changed files
- Comments generated: 0
- Review effort level: Balanced
Sandeep Somavarapu (sandy081)
approved these changes
Aug 17, 2026
Sandeep Somavarapu (sandy081)
deleted the
alexd/agent-host-lazy-capability-observer
branch
August 17, 2026 10:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I generated this by scanning my logs, pls take if it's good/useful
🤖
Found while self-hosting Insiders: scanning my recent session logs for errors and leaked-disposable warnings surfaced a listener leak originating in the Agent Host sessions provider.
The symptom
~/Library/Application Support/Code - Insiders/logs/*/window1/renderer.log:The minified frames deobfuscate to
BaseAgentHostSessionsProvider._refreshSessions→createAdapter→new AgentHostSessionAdapter→ anautorunadding an observer to a shared observable.Root cause
AgentHostSessionAdapter's constructor registered anautorunthat readsthis.capabilities, which is derived from the provider-wideagentCapabilitiesobservable. Every adapter therefore attached an observer to that one shared observable at construction time._refreshSessionsbuilds an adapter for every session the host lists, so a window restoring a large session list installed one observer per session and crossed the leak-detector threshold.The subscription was also mostly pointless. That autorun exists only to re-apply a chat catalog when capabilities hydrate late (the race #323625 addressed, where a multi-chat
SessionStateis processed before root state advertisessupportsMultipleChats). Its body no-ops unless_lastCatalogStateis set — and_lastCatalogStateis only ever assigned byapplyChatCatalog. Adapters that never received a catalog (the overwhelming majority in a large list) held a live observer that could never do work.The fix
Install the capabilities observer on the first
applyChatCatalogcall rather than in the constructor, held in aMutableDisposable. Adapters with catalog state to reconcile subscribe; adapters without one cost nothing.This is a natural follow-on to #328031, which collapsed N root-state event listeners into one shared lookup. This removes the remaining N per-adapter observers on that shared lookup.
Behavior preserved
Late-hydrating capabilities still re-expand a collapsed peer catalog. The existing test
a peer catalog collapsed while capabilities were absent re-expands when they hydratecovers exactly that path and passes unchanged — the observer is installed byapplyChatCatalog, which necessarily runs before any catalog needs reapplying.Validation
session adapters observe capabilities only after receiving a chat catalogbuilds 200 adapters and asserts 0 capability observers before any catalog, exactly 1 after, and correct peer-chat expansion on late hydration.npm run typecheck-clientandnpm run valid-layers-checkpass. (typecheck-clientreports two pre-existingassignmentService.tserrors that also reproduce on a pristinemain— unrelated to this change.)Review note
Sandeep Somavarapu (@sandy081) flagging you since you authored
applyChatCatalog,_lastCatalogState, and the "Make ISession.capabilities observable so late-hydrating capabilities reconcile" change that introduced this autorun. The one assumption worth your eyes: that an adapter which never receives a chat catalog genuinely has nothing to reconcile when capabilities hydrate late. Everything else here is listener bookkeeping.