Skip to content

chat: preserve agent plugins across portable moves - #340900

Draft
Dmitriy Vasyura (dmitrivMS) wants to merge 2 commits into
mainfrom
agents/fix-agent-plugins-path-issue
Draft

Dmitriy Vasyura (dmitrivMS) wants to merge 2 commits into
mainfrom
agents/fix-agent-plugins-path-issue

Conversation

@dmitrivMS

Copy link
Copy Markdown
Collaborator

Fixes #340899.

Summary

  • Persist managed plugin paths relative to the current plugin home, retaining the absolute pluginUri for older readers and external installations.
  • Migrate existing records using the file service's conditional-write metadata, reloading instead of publishing a stale migration when a conflicting update is detected.
  • Retain a stable enablement identity when locations change, including legacy storage migration, other workspaces, multiple profiles sharing the manifest, and profile switches without reloading the window.
  • Add focused regression coverage and update the installed-storage documentation. Keep the existing upstream repository-cache validation rather than duplicate it.

The manifest remains version 1 with optional relativePath and enablementUri fields. 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

Earlier fixes Scenarios checked
#304977, #339655 File-backed plugin home, Windows path casing, old portable cache index, valid indexed paths, and sibling-prefix rejection
#317585, #314263, #333641 Marketplace/GitHub-source metadata, actual parsed skills, single-root plugin and recorded ref-directory hydration after restart
#324120 Local folder and file-URI installs, marketplace trust, and external locations remaining absolute
#338781 Missing targets excluded from discovery; explicit uninstall removes the exact durable URI and preserves other plugins in a shared repository

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.
  • The five focused suites below - 348 passing.
.\scripts\test.bat `
  --run src\vs\workbench\contrib\chat\test\common\plugins\fileBackedInstalledPluginsStore.test.ts `
  --run src\vs\workbench\contrib\chat\test\common\plugins\pluginMarketplaceService.test.ts `
  --run src\vs\workbench\contrib\chat\test\browser\plugins\agentPluginRepositoryService.test.ts `
  --run src\vs\workbench\contrib\chat\test\common\plugins\agentPluginEnablement.test.ts `
  --run src\vs\workbench\contrib\chat\test\browser\plugins\pluginInstallService.test.ts
  • Additional historical cleanup/discovery suites - 57 passing.
.\scripts\test.bat `
  --run src\vs\workbench\contrib\chat\test\browser\aiCustomization\customizationMarketplaceInstallService.test.ts `
  --run src\vs\workbench\contrib\chat\test\common\plugins\marketplaceAgentPluginDiscovery.test.ts
  • Targeted ESLint - all 8 changed TypeScript files passed.
npm run eslint -- `
  src\vs\workbench\contrib\chat\common\plugins\agentPluginEnablement.ts `
  src\vs\workbench\contrib\chat\common\plugins\agentPluginService.ts `
  src\vs\workbench\contrib\chat\common\plugins\fileBackedInstalledPluginsStore.ts `
  src\vs\workbench\contrib\chat\common\plugins\pluginMarketplaceService.ts `
  src\vs\workbench\contrib\chat\test\browser\plugins\agentPluginRepositoryService.test.ts `
  src\vs\workbench\contrib\chat\test\common\plugins\agentPluginEnablement.test.ts `
  src\vs\workbench\contrib\chat\test\common\plugins\fileBackedInstalledPluginsStore.test.ts `
  src\vs\workbench\contrib\chat\test\common\plugins\pluginMarketplaceService.test.ts
  • git diff --check and git diff --cached --check - passed.
  • Red/green checks: 10 relocation regressions failed before the original implementation; the two in-window profile-switch regressions failed before the final enablement correction and passed afterward.

Actual Code OSS

Five final runs of an ad-hoc local scenario, using isolated VSCODE_PORTABLE data and synthetic plugins: 22/22 steps passed.

PORTABLE_PLUGIN_PHASE Passed Coverage
original 6 Absolute-record migration, parsed skill, disable switch, local folder/file-URI installs, local marketplace trust
second-profile 4 Shared installations and an independently disabled second profile before relocation
relocated 4 Physical data-directory move, absent original path, metadata/skills, disabled state, and an in-window profile switch without renderer reload
relocated-second-profile 3 Fresh restart into the second profile after the shared manifest was rewritten
deleted 5 Missing-target restart, explicit stale-target uninstall, exact record removal, and disabled sibling/shared-repository preservation

Each phase used this command with its corresponding environment value:

$env:TEMP = Join-Path $PWD '.build\portable-plugin-harness-temp'
$env:TMP = $env:TEMP
$env:PORTABLE_PLUGIN_PHASE = '<phase from the table>'
node test\scenario\out\runScenario.js .build\portable-plugin-scenario.cjs --dev

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.

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>
Copilot AI balanced review requested due to automatic review settings October 11, 2026 08:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Comment thread src/vs/workbench/contrib/chat/common/plugins/fileBackedInstalledPluginsStore.ts Outdated
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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The migration, concurrency handling, identity preservation, and relevant edge cases are coherently implemented and covered by focused tests.

0 open findings

2 resolved since last review

🧠 Review effort: Balanced

@dmitrivMS

Copy link
Copy Markdown
Collaborator Author

Follow-up fixes are pushed in 094102a and both selected review threads are resolved.

  • Migration now also runs after external manifest edits and retries conditional-write conflicts using freshly read metadata.
  • Moving an installation to a new revision retains its stable enablement identity across inactive profiles and subsequent restarts.
  • Validation: 286 tests passed across the four affected plugin suites; client type checking, targeted ESLint, scoped hygiene, and whitespace checks passed.

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.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-plugins portable-mode VS Code portable mode issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent plugins disappear after moving a portable installation

2 participants