chat: use SDK-owned customization installations by pwang347 · Pull Request #339896 · microsoft/vscode · GitHub
Skip to content

chat: use SDK-owned customization installations - #339896

Merged
Paul (pwang347) merged 37 commits into
mainfrom
copilot/sdk-owned-customization-installations
Oct 8, 2026
Merged

Paul (pwang347) merged 37 commits into
mainfrom
copilot/sdk-owned-customization-installations

Conversation

@pwang347

@pwang347 Paul (pwang347) commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Make the active customization harness's SDK/runtime inventory authoritative for marketplace installation state instead of persisting a second set of VS Code installation records.

  • adds harness seams for provider-owned catalog search, inventory, install, recovery, and uninstall operations
  • makes GitHub Feed discovery SDK-only and removes the platform REST/shared-process compatibility transport
  • exposes GitHub Feed only when the active harness supplies SDK search; Local retains Discover with MCP Gallery, configured Plugin marketplaces, and Connectors
  • mirrors GitHub App queryless Browse with the available subset of Azure, WorkIQ, and Security Best Practices from SDK-registered plugin marketplaces
  • keeps default MCP and Plugin registries available independently of the GitHub Feed setting
  • removes the unreachable Local GitHub Feed Skill, direct MCP, and direct plugin installers
  • uses bound Copilot SDK catalog search without requiring a visible or materialized chat session
  • creates one lazy hidden policy session with no tools, instructions, memory, session store, or enabled MCP servers
  • retains SDK candidate handles and pagination tokens inside Agent Host behind bounded, expiring workbench IDs
  • consumes the exact retained Skill/MCP candidate during installation, or recovers an invalidated one-use handle with the full discovery/trust contract only by matching the original card URL and visible metadata
  • routes Copilot SDK Skill and MCP operations through receipt-owned list/plan/confirm/apply/recover flows
  • supports SDK-owned input-free remote MCP installation and removal with native-host planning from SDK 1.0.18-preview.3 / runtime 1.0.94-3
  • routes Copilot SDK plugin install/uninstall through the provider that owns installedPlugins
  • validates marketplace trust, exact policy session, catalog version, and SDK confirmation review before applying an operation
  • removes legacy chat.customizations.marketplace.installationRecord.v1.* profile records eagerly
  • retains only bounded, in-memory associations for catalog presentation metadata
  • renders SDK-owned MCP receipts directly in MCP Servers when no local/runtime definition exists, without importing the SDK configuration into VS Code ownership
  • deduplicates receipt URNs and catalog card URLs through their exact canonical GitHub Registry identity, never display name
  • matches GitHub App icon behavior: a validated GitHub publisher gets its avatar; other entries use their customization kind icon
  • enriches SDK MCP rows without publishers from the GitHub MCP Registry owner-avatar snapshot used by GitHub App
  • restores trusted Registry owner avatars from canonical receipt resource identities when the transient card URL is unavailable
  • exposes the owning uninstall operation directly on installed Browse cards instead of a disabled Installed badge
  • keeps SDK plugin install/uninstall pending until authoritative plugin inventory publishes the mutation, preventing action flicker
  • surfaces SDK catalog authentication as an explicit Sign In source action, then retries the same query only after user activation
  • shares GitHub Feed recovery with the Connectors/default GitHub account and reuses that account's Connector-scoped session when authorized
  • coalesces default-account recovery into one GitHub App-style Sign In invitation; extra Connector consent starts only from explicit connection actions
  • never offers or requests elevated Connector permission during catalog browsing, including after HTTP 403
  • omits discovery-only Skills, unsupported direct plugins, policy-blocked entries, and unsupported MCP sources from Copilot SDK search while retaining native pagination for backfill
  • consumes SDK continuation pages internally when filtering removes every candidate, so workbench sources never receive an invalid empty page with a cursor
  • uses each URL-backed catalog card as presentation identity while retaining its opaque SDK selection separately, deduplicating repeated cards across SDK search pages
  • hides the legacy MCP and Plugin Available groups while Marketplace owns discovery

Design

The provider inventory is the only source of installation truth for provider-owned resources. Discover joins that inventory to catalog resources by exact catalog identity first, then by compatible URL/source identities that reject conflicting versions or revisions.

Catalog metadata is deliberately non-authoritative. It can enrich an SDK receipt row with an icon or description, but it cannot create an installed state. MCP Servers renders provider receipts directly only when no local or active-session server matches their exact target; the receipt remains the installation authority and its Uninstall action routes back to the provider. Discover joins the receipt's canonical Registry URN to the card's canonical Registry URL identity, with compatible versions, so installed and available representations collapse without fuzzy name matching.

The SDK exclusively owns Copilot GitHub Feed discovery and installation. Local never advertises that source. Queryless Browse mirrors GitHub App's bounded static featured-plugin list after one SDK marketplace-list policy check; typed Copilot searches use SDK catalog search. SDK unavailability returns an empty GitHub Feed instead of changing ownership to a VS Code REST fallback.

When no materialized Copilot chat exists, Agent Host creates a hidden policy session that is omitted from discovery, reused while current, and deleted on client restart, authentication change, or after ten minutes idle. SDK search projects only candidates the runtime marks installable and whose source VS Code can pass to the owning operation. Candidate handles and native pagination tokens never enter workbench state or telemetry. Harness or session changes invalidate marketplace continuations. Authentication or an earlier installation can also consume a one-use candidate handle; in that case Agent Host performs one fresh SDK search with the normal trust-snapshot contract and accepts only the original card URL with unchanged visible metadata.

Harnesses without an install provider can install only resources from existing owning services: configured Plugin marketplaces, MCP Gallery, and Connectors. Skill, direct MCP, direct plugin, and other SDK catalog installation kinds never fall back to a VS Code-owned installer.

Known limitations

  • VS Code supports only input-free remote MCP choices; GitHub App already presents a choice, value, and secret collection form for configured/package choices such as Azure AI Foundry
  • SDK catalog search requires a non-empty query, and current live Skill candidates are materialisation-unavailable; VS Code therefore shows installed/local Skills for an empty Skill filter and omits discovery-only catalog Skills

Tradeoffs

  • Local and SDK versions without catalog search no longer have GitHub Feed discovery; this removes duplicate requests, validation, planning, and installation ownership from VS Code
  • queryless Copilot Browse performs one SDK marketplace-list policy check for the three static editorial plugin picks
  • editorial plugins whose owning SDK marketplace is unavailable are omitted rather than shown with a broken install action
  • SDK selections are intentionally short-lived; after authentication invalidates a selection, VS Code performs one bounded search and requires the exact original card URL and unchanged visible metadata instead of accepting fuzzy identity
  • a receipt-only MCP row can show authoritative installation state, catalog presentation, details, and SDK uninstall, but it does not offer start/stop or enablement controls until the runtime publishes a matching server
  • the SDK does not carry arbitrary catalog icons, so a valid GitHub publisher uses github.com/<publisher>.png and all other entries use the type icon
  • Copilot SDK search omits non-installable candidates instead of matching GitHub App's current explanatory disabled rows
  • GitHub App's empty Skills page additionally shows curated featured bundles installed through its separate personal-skill bundle path; VS Code does not copy that non-SDK installer because it would recreate split installation ownership
  • a search may perform an additional SDK request when an entire native page is filtered; this preserves later actionable results without weakening marketplace pagination validation
  • GitHub App additionally searches its static MCP Registry snapshot, so it can show installable entries that SDK catalog search does not return; VS Code uses that snapshot only for icon enrichment and does not create a second discovery or installation authority
  • direct catalog plugins remain omitted from Copilot SDK search until exact-revision plugin installation exists
  • Connector, configured Plugin, and MCP Gallery lifecycle remain independently authoritative

Validation

  • npm run typecheck-client — passed
  • npm run define-class-fields-check — passed
  • npm run valid-layers-check — passed
  • changed-file ESLint — passed (23 files)
  • focused marketplace, MCP, provider, and management-widget suites — 356 passing
  • featured plugin browse, projection, installation, and telemetry suites — 92 passing
  • provider-owned featured plugin routing — passed in Chromium and WebKit
  • featured plugin inventory synchronization — passed in Electron, Chromium, and WebKit
  • no-flicker dev-build lifecycle scenario — 3/3 passing; observed Installing... → Uninstall with no intermediate Install
  • exact Copilot GitHub Feed figma search scenario — passed with an actionable Figma MCP Server result
  • explicit search sign-in recovery and unavailability errors — passed in Electron, Chromium, and WebKit
  • shared default-account invitation and separate Connector consent presentation — 187 affected tests passed; focused UI tests passed in Chromium and WebKit
  • connector browse/consent boundary — 158 affected tests passed; focused Chromium and WebKit tests passed
  • GitHub MCP Registry icon mapping — 219 unique trusted identities validated; Electron, Chromium, and WebKit tests passed
  • exact testing search UI scenario — Wopee, Argus Testing, and Playwright rendered curated owner avatars
  • exact azure search UI scenario — 8 results, including the SDK-backed Azure MCP Server, with no invalid-page warning
  • six-query GitHub App/VS Code parity audit (azure, testing, figma, skilldb, slack, and no-match) — shared SDK results matched on identity, description, icon, and enabled action state
  • broad mcp query regression — repeated SDK cards were reproduced, then removed by stable card presentation identity; 13 unique rows and no duplicate names after the fix
  • post-merge validation against @github/copilot-sdk@1.0.18-preview.3 / runtime 1.0.94-3 — 172 combined marketplace tests and 29 source-composition tests passed; the merged seven-query Dev scenario passed with per-marketplace sources and no duplicate SDK cards
  • focused SDK-owned installation suites — 18 passing, including expired-selection recovery, normalized MCP confirmation, tampered URL/header/tool rejection, receipt inventory, and Registry-authority uninstall
  • SkillDB differential native-host scenario — preview.9 reproduced planning-unavailable; preview.3 completed planning and displayed the exact endpoint/configuration review
  • SkillDB SDK-owned lifecycle scenario — 3/3 passing: discover → reviewed install → authoritative Uninstall → reviewed removal → Install
  • repeated Figma SDK-owned lifecycle scenario — three consecutive reviewed install/uninstall cycles passed; the regression loop reproduces the second-install trust-snapshot mismatch without the fix
  • SDK receipt presentation scenario — installed Figma and Anima receipts appear under User in MCP Servers with trusted Registry avatars, deduplicate against runtime/local servers, and expose provider-owned Uninstall
  • Figma Discover deduplication scenario — All Sources + figma renders one canonical Figma row with Uninstall, not separate installed and marketplace rows
  • live SDK Skill audit (release, review, design, test) — the backend returned Skill candidates, but every candidate was materialisation-unavailable; no broken Install actions were surfaced
  • strict Copilot Agent Host replay — 268 passing, 24 expected pending
  • npm run hygiene — passed
  • component fixtures — 6/6 rendered without errors; Local, MCP, and Plugin dark fixtures stable across three captures
  • Local dev-build source-ownership scenario — 4/4 passing:
    • Local source menu contains MCP Gallery, configured Plugin marketplaces, and Connectors, but no GitHub Feed
    • queryless Browse and typed search show no GitHub Feed provenance
    • legacy MCP and Plugin Available groups are hidden
  • Copilot dev-build source-ownership scenario — 3/3 passing:
    • Copilot source menu contains GitHub Feed plus existing registries
    • queryless Browse shows SDK-owned featured plugins plus existing registries
    • typed search returns an actionable SDK GitHub Feed result
  • GitHub App verified Skill lifecycle E2E — passed
  • GitHub App non-installable Skill explanation — passed

UI Validation

SDK inventory and frontend-to-backend session mapping

sdk-inventory-session-mapping.mp4

Bound SDK catalog search and GitHub App icon fallback

sdk-catalog-search.mp4

SDK search and planning request without a visible Copilot session

sdk-marketplace-without-visible-session.mp4

Audit Copilot search results for actionable installation state

annotated.mp4

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 5, 2026 20:09
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.

Copilot review overview

🟡 Changes recommended

Unresolved trust validation, session identity, and inventory ownership defects block reliable SDK-managed installation workflows.

Review effort: Balanced
Findings: 2 High severity · 4 Medium severity

Open (6)
What changed in this PR

Moves marketplace installation authority to the active harness’s SDK/runtime instead of separate persisted VS Code records.

Changes:

  • Adds provider-owned inventory, installation, recovery, and removal.
  • Introduces SDK review and confirmation flows for Skills and MCP servers.
  • Removes legacy records and retains in-memory catalog associations.
File Description
src/​vs/​workbench/​contrib/​chat/​test/​common/​plugins/​copilotCliAgentPluginDiscovery.test.ts Verifies SDK plugin provenance.
src/​vs/​workbench/​contrib/​chat/​test/​browser/​aiCustomization/​customizationMarketplaceInstallService.test.ts Tests provider inventory and associations.
src/​vs/​workbench/​contrib/​chat/​common/​plugins/​agentPluginServiceImpl.ts Preserves SDK installation identities.
src/​vs/​workbench/​contrib/​chat/​common/​plugins/​agentPluginService.ts Defines SDK plugin provenance types.
src/​vs/​workbench/​contrib/​chat/​common/​customizationMarketplaceInstallService.ts Adds installation-provider contracts.
src/​vs/​workbench/​contrib/​chat/​common/​customizationHarnessService.ts Exposes harness installation providers.
src/​vs/​workbench/​contrib/​chat/​browser/​aiCustomization/​pluginCustomizationMarketplaceProvider.ts Adds configured-plugin installation metadata.
src/​vs/​workbench/​contrib/​chat/​browser/​aiCustomization/​customizationMarketplaceSkillInstaller.ts Uses in-memory association types.
src/​vs/​workbench/​contrib/​chat/​browser/​aiCustomization/​customizationMarketplaceInstallService.ts Routes operations through providers.
src/​vs/​workbench/​contrib/​chat/​browser/​aiCustomization/​customizationMarketplaceInstallationRecordStore.ts Removes persisted record storage.
src/​vs/​workbench/​contrib/​chat/​browser/​aiCustomization/​customizationMarketplaceInstallationAssociation.ts Adds association cache and legacy cleanup.
src/​vs/​workbench/​contrib/​chat/​browser/​aiCustomization/​customizationMarketplace.contribution.ts Registers cleanup and updates help text.
src/​vs/​workbench/​contrib/​chat/​browser/​agentSessions/​agentHost/​agentHostCustomizationMarketplaceInstallProvider.ts Implements SDK-backed marketplace management.
src/​vs/​workbench/​contrib/​chat/​browser/​agentSessions/​agentHost/​agentHostChatContribution.ts Registers the Copilot installation provider.
src/​vs/​sessions/​AI_CUSTOMIZATIONS.md Documents provider-owned installation behavior.
src/​vs/​platform/​customizationMarketplace/​common/​customizationMarketplaceService.ts Extends configured-plugin descriptors.
src/​vs/​platform/​agentHost/​test/​node/​copilotCustomizationInstallations.test.ts Tests receipt inventory and confirmation.
src/​vs/​platform/​agentHost/​node/​copilot/​customizations/​copilotCustomizationInstallations.ts Implements SDK installation transactions.
src/​vs/​platform/​agentHost/​node/​copilot/​copilotFailureTelemetry.ts Adds plugin-install telemetry classification.
src/​vs/​platform/​agentHost/​node/​copilot/​copilotAgent.ts Connects installation operations to Copilot.
src/​vs/​platform/​agentHost/​node/​agentService.ts Delegates operations to providers.
src/​vs/​platform/​agentHost/​node/​agentHostManagementService.ts Exposes management operations.
src/​vs/​platform/​agentHost/​electron-browser/​localAgentHostService.ts Forwards local management calls.
src/​vs/​platform/​agentHost/​common/​agentService.ts Extends service contracts.
src/​vs/​platform/​agentHost/​common/​agent.ts Defines installation requests and reviews.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Paul (pwang347) and others added 3 commits October 5, 2026 16:40
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Screenshot Changes

Base: f6f19d60 Current: ee28294f

Changed (1)

chat/aiCustomizations/aiCustomizationManagementEditor/DiscoverInstallStates/Light
Before After
before after

Paul (pwang347) and others added 19 commits October 5, 2026 17:33
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep marketplace plugin mutations pending until authoritative SDK inventory observes the change, avoiding a transient available state between install and inventory publication.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Retry catalog search once after the standard Copilot authentication flow and surface persistent SDK unavailability as source errors instead of successful empty results.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Match GitHub App by surfacing authentication as a source recovery action and retrying only after explicit user activation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Pin GitHub Feed authentication recovery to the default account used by Connectors and reuse an authorized Connector-scoped session for that account when available.

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

@rickvela664-ops Rick (rickvela664-ops) left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • @ #Fixes #

Paul (pwang347) and others added 2 commits October 8, 2026 10:10
Consume Copilot SDK 1.0.18-preview.3 with native-host MCP planning. Authenticate before provider-catalog preparation, recover invalidated selections only by exact card URL and visible metadata, and validate the runtime's normalized remote configuration and Registry authority. This fixes SkillDB install and uninstall, whose confirmations were previously rejected for normalized HTTP transport, tools selection, and differing discovery versus Registry authorities.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the normal trust-snapshot catalog contract when recovering a consumed selection by exact URL. Without it, a second install received a candidate without trust metadata while the runtime confirmation contained the plan's trust snapshot, so the host correctly cancelled the mismatched review.

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

Copy link
Copy Markdown
Contributor Author

Follow-up repeated-action validation found and fixed one host-side bug in 69ab492695b: after the first install/uninstall consumed the original SDK selection, the exact-URL recovery search used a weaker contract without trust-snapshot. The second plan's confirmation included trust metadata while the recovered candidate did not, so the strict host validator cancelled the operation. Recovery now uses the normal discovery/trust contract. A deterministic Figma scenario reproduced the second-install failure before the fix and then passed three consecutive reviewed install/uninstall cycles after it. Focused suites pass 18/18, typecheck/lint/hygiene pass, and the final profile has no Figma receipt or configuration left behind.

Render provider-owned MCP receipts when no local or active-session definition matches, and route removal back through the owning provider. Restore trusted GitHub Registry avatars from canonical receipt identities so presentation survives restarts without creating VS Code installation records.

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

Copy link
Copy Markdown
Contributor Author

Follow-up fix 153c4fca1a0 addresses SDK-installed MCP servers missing from the MCP Servers list. The list previously used provider receipts only to annotate an existing VS Code/runtime row, but SDK-owned installs write the Copilot profile and can have no such row. MCP Servers now renders an authoritative receipt-only row under User, deduplicates it when a local/runtime twin appears, preserves trusted GitHub Registry avatars from the receipt's canonical resource identity, and routes Uninstall back through the provider. Receipt-only rows intentionally omit start/stop and enablement controls until the runtime publishes a matching server. Validation: 129 focused tests pass; a real Dev scenario confirms existing Figma and Anima receipts appear with icons and Figma exposes the SDK-owned Uninstall action.

Join trusted GitHub Registry receipt URNs to their exact card URL identities when versions are compatible. Prefer the later catalog representation over a previously observed receipt resource so Discover converges to one enriched installed row without display-name matching.

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

Copy link
Copy Markdown
Contributor Author

Discover deduplication follow-up 648efec229f: SDK receipts use canonical Registry URNs while fresh cards use canonical Registry URLs. The install-state join now normalizes both to the same trusted GitHub Registry identity, still requires compatible versions, and prefers the catalog representation for presentation. This removes the duplicate installed/marketplace Figma rows without fuzzy display-name matching. Validation: one Figma row with Uninstall in the exact All Sources search; 182 affected tests, typecheck, lint, and hygiene pass.

Preserve SDK-authoritative customization installation help while incorporating the modal-only Customizations editor and new Get started session behavior from main.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pwang347
Paul (pwang347) marked this pull request as ready for review October 8, 2026 20:27
@vs-code-engineering

Copy link
Copy Markdown
Contributor

📬 CODENOTIFY

The following users are being notified based on files changed in this PR:

Robo (@deepak1556)

Matched files:

  • src/vs/code/electron-utility/sharedProcess/sharedProcessMain.ts

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

@connor4312 Connor Peet (connor4312) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed security and correctness at 75be44b. No confirmed P1 issues found. Approving with one P2 finding: featured SDK plugin installations bypass the marketplace trust gate applied to configured plugins.

Written by Connor's agent running GPT-6.1 Sol

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P2] Apply marketplace trust validation to featured SDK plugins

A fresh profile can install a featured plugin from an untrusted marketplace through this branch without the source-trust/code-execution confirmation. Featured catalog entries are mapped to providerPlugin, but CustomizationMarketplaceInstallService.install only calls ensureMarketplaceTrusted for configuredPlugin; this branch then directly invokes SDK plugins.install. The SDK marketplace availability check does not establish user trust, and PluginMarketplaceService.isMarketplaceTrusted requires explicit trust (or the strict enterprise allowlist). Resolve the featured plugin's registered marketplace source and run the same trust/policy gate before installation. Cover an untrusted marketplace and a declined trust prompt so neither can reach SDK installation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in #340606. The follow-up resolves the SDK-featured plugin to its registered marketplace plugin, runs the existing trust/strict-policy gate before invoking SDK installation, and covers both approved and declined trust paths. #339896 merged while the stack was being prepared, so the follow-up targets main directly.

@pwang347
Paul (pwang347) enabled auto-merge (squash) October 8, 2026 23:19
@pwang347
Paul (pwang347) merged commit 3bcdc08 into main Oct 8, 2026
35 checks passed
@pwang347
Paul (pwang347) deleted the copilot/sdk-owned-customization-installations branch October 8, 2026 23:26
@vs-code-engineering vs-code-engineering Bot added this to the 1.142.0 milestone Oct 8, 2026
Vritant Bhardwaj (vritant24) added a commit that referenced this pull request Oct 19, 2026
…342471)

Follow-up to #339896.

## Problem

The workbench logged this, with no indication of why it failed:

```
[AgentHostCustomizationMarketplace] Unable to load session-bound SDK installation receipts The SDK could not list installed MCP servers.
```

The Copilot runtime's `mcp.installations.list` /
`skills.installations.list` reports refusals as `{ kind: 'outcome',
outcome: { kind: 'refused', reason: '<code>' } }` or `{ kind: 'outcome',
outcome: { kind: 'recovery-required' } }`, without a top-level
`message`. `resultError` only used `result.message ?? fallback`, so the
reason was always lost. Also, `list(session)` never called
`installations.recover`, so a `recovery-required` inventory could never
resolve on its own.

## Changes

In `copilotCustomizationInstallations.ts`:

- **Clearer errors:** `resultError` now adds the outcome kind and reason
after the existing message, using the localized pattern `"{0} ({1})"`.
Example: `The SDK could not list installed MCP servers. (refused:
lifecycle-unavailable)`. Reason codes are left as non-localized SDK
identifiers. Other callers (plan, prepare, uninstall) only reach
`resultError` when something has already failed, so the only change for
them is the added detail.
- **Recovery in `list(session)`:** if skills or MCP inventory returns
`recovery-required`, it calls `installations.recover` once for that kind
only and uses the recovered inventory. If recovery returns
`recovery-required` again, it throws `(recovery-required)` instead of
retrying, so it can't loop.

**For reviewers:** the private `listWithClient` used by the uninstall
flow still does not recover. That's deliberate, to keep this change
scoped to `list(session)`.

## Testing

`copilotCustomizationInstallations.test.ts` gets a new `inventory
failures` suite with three tests:
- A refused MCP list puts the reason in the error message.
- `recovery-required` calls recover once and returns the recovered
installations.
- A repeated `recovery-required` after recovery produces an error and no
second retry.

Commands run:
- `./scripts/test.sh --run
src/vs/platform/agentHost/test/node/copilotCustomizationInstallations.test.ts`:
passed (15 passing)
- `npm run eslint -- <changed files>`: passed
- `npm run typecheck-client`: passed
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.

5 participants