Skip to content

fix(cli): invalidate per-instance config caches on global config update - #7180

Closed
markijbema wants to merge 1 commit into
mainfrom
mark/fix-stale-config-after-global-update-v2
Closed

fix(cli): invalidate per-instance config caches on global config update#7180
markijbema wants to merge 1 commit into
mainfrom
mark/fix-stale-config-after-global-update-v2

Conversation

@markijbema

Copy link
Copy Markdown
Contributor

Summary

  • Fixes stale per-instance config after Config.updateGlobal() — active instances now pick up global config changes (modes, providers, models, etc.) without requiring a server restart
  • Adds State.resetCaches() which clears all cache-only Instance.state entries across all instances without tearing down side-effectful resources

Problem

PR #7172 correctly removed Instance.disposeAll() from Config.updateGlobal() to stop it from destroying sessions, MCP connections, and in-flight operations on every config change. However, this left a gap: global.reset() only invalidates the process-wide global config lazy cache, not the per-instance Config.state (or downstream caches like Agent.state, Provider.state, etc.) that merge global config at initialization time.

This meant that after a global config change via the VS Code settings panel (e.g. changing default agent, provider, or model), the server's HTTP endpoints (/config, /app/agents, /app/providers) would continue returning stale cached data. The extension would re-fetch after the global.disposed SSE event, but get back the old values.

As noted by the review bot on #7172: comment

Fix

State.resetCaches() iterates all instance state maps and deletes entries that have no dispose callback. These are the 18 "pure cache" entries (Config, Agent, Provider, Tool, Skill, Command, Format, Plugin, etc.) that are safe to drop and will be re-computed on next access. The 9 entries with dispose callbacks (Prompt sessions, MCP connections, LSP clients, PTY processes, file watchers, etc.) are preserved.

The flow after the fix:

updateGlobal() writes config to disk
  → global.reset()           // clear global config lazy cache
  → State.resetCaches()      // clear all per-instance derived caches
  → emit "global.disposed"   // SSE to extension
  → extension re-fetches     // HTTP requests hit server
  → Config.state() re-inits  // fresh merge with updated global config
  → Agent.state() re-inits   // fresh agent list
  → UI updates correctly

Config.updateGlobal() was only resetting the global lazy cache but not
the per-instance State entries (Config.state, Agent.state, Provider.state,
etc.). This meant active instances served stale config data — e.g. after
changing default provider or model settings via the VS Code settings panel,
the server would continue returning the old values until restart.

Add State.resetCaches() which clears all cache-only State entries (those
without dispose callbacks) across all instances. This invalidates derived
state so it gets re-computed on next access, while preserving side-effectful
resources like MCP connections, sessions, and file watchers.
@markijbema markijbema closed this Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant