Repository navigation
chat: use SDK-owned customization installations - #339896
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
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
Open (6)
Enforce marketplace trust and policy checks for SDK installs · New Resolve backend session identity before Skill/MCP operations · New Validate requested Skill version against the discovered plan · New Preserve SDK plugin inventory when receipt listing fails · New Make SDK provider inventory authoritative over local associations · New Use registered SDK marketplace identity instead of display labels · New
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.
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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>
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>
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>
|
Follow-up repeated-action validation found and fixed one host-side bug in |
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>
|
Follow-up fix |
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>
|
Discover deduplication follow-up |
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>
📬 CODENOTIFYThe following users are being notified based on files changed in this PR: Robo (@deepak1556)Matched files:
|
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Connor Peet (connor4312)
left a comment
There was a problem hiding this comment.
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
There was a problem hiding this comment.
[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.
There was a problem hiding this comment.
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.
…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



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.
1.0.18-preview.3/ runtime1.0.94-3installedPluginschat.customizations.marketplace.installationRecord.v1.*profile records eagerlyDesign
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
materialisation-unavailable; VS Code therefore shows installed/local Skills for an empty Skill filter and omits discovery-only catalog SkillsTradeoffs
github.com/<publisher>.pngand all other entries use the type iconValidation
npm run typecheck-client— passednpm run define-class-fields-check— passednpm run valid-layers-check— passedInstalling...→Uninstallwith no intermediateInstallfigmasearch scenario — passed with an actionable Figma MCP Server resulttestingsearch UI scenario — Wopee, Argus Testing, and Playwright rendered curated owner avatarsazuresearch UI scenario — 8 results, including the SDK-backed Azure MCP Server, with no invalid-page warningazure,testing,figma,skilldb,slack, and no-match) — shared SDK results matched on identity, description, icon, and enabled action statemcpquery regression — repeated SDK cards were reproduced, then removed by stable card presentation identity; 13 unique rows and no duplicate names after the fix@github/copilot-sdk@1.0.18-preview.3/ runtime1.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 cardsplanning-unavailable; preview.3 completed planning and displayed the exact endpoint/configuration reviewUninstall→ reviewed removal →Installfigmarenders one canonical Figma row withUninstall, not separate installed and marketplace rowsrelease,review,design,test) — the backend returned Skill candidates, but every candidate wasmaterialisation-unavailable; no broken Install actions were surfacednpm run hygiene— passedUI 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