Repository navigation
chat: preserve agent plugins across portable moves - #340900
Dmitriy Vasyura (dmitrivMS) wants to merge 2 commits into
Conversation
Store managed plugin locations relative to the current plugin home while retaining absolute URIs for older readers and external installations. Migrate legacy records with conditional-write metadata. Preserve enablement identities across relocated installs, shared manifests, workspaces, and profile switches. Cover relocation and nearby persistence regressions with focused tests. Fixes #340899 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
External updates and conflicts can leave manifests relocation-unsafe, while moved plugin updates can lose cross-profile enablement identity.
2 open findings
What changed in this PR
Preserves managed agent plugins and enablement state when portable installations move.
Changes:
- Persists relative plugin paths and stable enablement identities.
- Adds conflict-aware manifest migration.
- Expands relocation, profile, and cache regression coverage.
| File | Description |
|---|---|
agentPluginService.ts |
Defines the enablement service contract. |
agentPluginEnablement.ts |
Maintains stable enablement aliases across profile changes. |
fileBackedInstalledPluginsStore.ts |
Adds relocation-safe manifest persistence and migration. |
pluginMarketplaceService.ts |
Integrates enablement identity persistence. |
AGENTS_PLUGINS.md |
Documents the new storage format. |
agentPluginRepositoryService.test.ts |
Covers stale indexed repository paths. |
agentPluginEnablement.test.ts |
Covers profile-switch identity behavior. |
fileBackedInstalledPluginsStore.test.ts |
Covers relocation, migration, and conflicts. |
pluginMarketplaceService.test.ts |
Covers hydration after relocation. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Retry conflicted installed-plugin migrations from fresh file metadata at startup and after external edits, without repeatedly retrying ordinary write errors. Carry the durable enablement identity from the exact previous installation when plugin updates change its URI. Cover conflicting external installs, chained revision moves, and inactive profiles with regression tests. Refs #340899 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Follow-up fixes are pushed in 094102a and both selected review threads are resolved.
CI on the updated head is successful: https://github.com/microsoft/vscode/actions/runs/38126901809. Both previously failing checks (Compile & Hygiene and Linux / Electron-Smoke) passed. The original failures reported a killed ESLint process (exit 137, no preceding lint diagnostic) and a smoke-step timeout after 66 passing / 66 pending tests, not a reported plugin test failure. No workflow changes were needed. |

Fixes #340899.
Summary
pluginUrifor older readers and external installations.The manifest remains version 1 with optional
relativePathandenablementUrifields. The latter is a logical identity, not a filesystem location to access.Recovery limitation: an installation that has already moved with an absolute-only manifest may still need a one-time path repair or reinstallation. This change migrates identifiable current locations and makes subsequent moves safe; it does not guess a previous installation root.
Related regression coverage
Astra/max and Opus 5.5/max reviews were completed. Findings concerning path casing, disabled state, migration conflicts, and cross-profile identity preservation were addressed with regression tests.
Validation
Windows x64, Code OSS 1.142.0 Dev, updated to main at
eef761e9628.npm run compile- passed.npm run compile-client- final client compilation passed with 0 errors.git diff --checkandgit diff --cached --check- passed.Actual Code OSS
Five final runs of an ad-hoc local scenario, using isolated
VSCODE_PORTABLEdata and synthetic plugins: 22/22 steps passed.PORTABLE_PLUGIN_PHASEoriginalsecond-profilerelocatedrelocated-second-profiledeletedEach phase used this command with its corresponding environment value:
The temporary scenario is not part of this source change. Captioned recordings, screenshots, traces, and HTML reports were retained locally. These live runs used local fixture repositories and metadata, not remote/private repository authentication or model requests.
To verify manually, follow #340899, first opening the fixed build at the original location so existing absolute records migrate. Disable a plugin in each of two profiles, move the portable data, then verify plugin contributions and disabled state after restart and when switching profiles in the same window. Also verify that external local plugins still use their original external paths.