Fix customization marketplace sign-in by pwang347 · Pull Request #341648 · microsoft/vscode · GitHub
Skip to content

Fix customization marketplace sign-in - #341648

Merged
Paul (pwang347) merged 3 commits into
mainfrom
fix/customizations-marketplace-sign-in
Oct 15, 2026
Merged

Paul (pwang347) merged 3 commits into
mainfrom
fix/customizations-marketplace-sign-in

Conversation

@pwang347

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

Copy link
Copy Markdown
Contributor

Summary

  • explicitly bind the current GitHub credential to the hidden customization policy session through the SDK's supported session.gitHubAuth.setCredentials API
  • pass the canonical configured GitHub host URL so GitHub Enterprise credentials and Copilot-user metadata use the correct authority
  • preserve signed-out behavior, report degraded account metadata, and clean up the partially created hidden session when credential binding fails
  • remove the superseded protected-resource fallback; no SDK/runtime change or runtimeOverride is used

The hidden session could report authenticated metadata while the SDK catalog auth manager still had no selected session credential. Catalog search therefore returned authentication-required / no-credential, and the recovery button appeared inert. Installing the session-owned credential after session creation selects it for SDK catalog operations.

Validation

  • npm run build-fast -- --client-only — passed
  • ./scripts/test.sh --run src/vs/platform/agentHost/test/node/copilotSessionLauncher.test.ts — passed (134 tests)
  • npm run typecheck-client — passed
  • npm run eslint -- src/vs/platform/agentHost/node/copilot/copilotAgent.ts src/vs/platform/agentHost/node/copilot/copilotSessionLauncher.ts src/vs/platform/agentHost/test/node/copilotSessionLauncher.test.ts — passed
  • git diff --check — passed
  • real Code OSS UI scenario on macOS arm64, Dev 1.143.0 — passed against /Users/paulwang/Desktop/shared/code/vscode-sdk-skill-install using the normal signed-in profile, checked-in SDK/runtime, no injected token, no synthetic response, and no runtime override. Searching figma returned six Skill · GitHub Feed results with no Sign In prompt.

How to Test

  1. Sign in to Copilot in Code OSS.
  2. Select the Copilot harness and open Agent Customizations.
  3. Open Browse and search for figma.
  4. Verify GitHub Feed skill results appear and no marketplace Sign In prompt is shown.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 14, 2026 22:54
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

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

Enterprise resource handling and fallback credential revocation on sign-out need correction.

2 open findings
What changed in this PR

Adds fallback Copilot authentication for customization marketplace recovery when the host advertises no protected resources.

Changes:

  • Selects an authentication resource for marketplace sign-in.
  • Adds regression coverage through the registered marketplace provider.
File Description
src/​vs/​workbench/​contrib/​chat/​test/​browser/​agentSessions/​agentHostChatContribution.test.ts Tests recovery with empty protected resources.
src/​vs/​workbench/​contrib/​chat/​browser/​agentSessions/​agentHost/​agentHostChatContribution.ts Adds fallback authentication resource selection.

🧠 Review effort: Balanced


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

@pwang347

Copy link
Copy Markdown
Contributor Author

Closing this draft after reproducing the exact workspace flow: the proposed protected-resource fallback does not fix the issue.

A direct SDK differential across @github/copilot-sdk 1.0.18-preview.4/runtime 1.0.94-4 through 1.0.22-preview.2/runtime 1.0.98-2 produced the same result under VS Code’s hidden policy-session options: session.gitHubAuth.getStatus reports authenticated=true, but bound catalog.search returns authentication-required/no-credential. Omitting enableManagedSettings/managedSettings changes the result away from authentication-required. This is therefore not a new SDK version regression; it is a latent incompatibility between the hidden managed-settings policy session and bound catalog credential lookup. If the flow worked previously, it was likely using a live materialized chat session instead of the hidden fallback session.

The exact UI click also starts GitHub Authentication’s device-code flow when no account exists, so the apparent no-op has a second UX issue: that pending sign-in is not surfaced clearly over the customization modal.

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

Copy link
Copy Markdown
Contributor Author

UI validation on macOS arm64 with Code OSS Dev 1.143.0: opened Agent Customizations for the Copilot harness in vscode-sdk-skill-install, searched for figma, and verified six Skill · GitHub Feed results with no Sign In prompt. This used the normal signed-in profile and checked-in SDK/runtime, with no injected token, synthetic response, or runtime override.

customizations-marketplace-sign-in-fix.mp4

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

Copy link
Copy Markdown
Contributor Author

Deep-review follow-up:

  • Found and fixed one real issue in 80f57586d1a: the credential payload used a bare authority (github.com) where the SDK requires a host URL. Search worked, but copilotUser re-resolution could fail and leave account metadata degraded. The code now shares the canonical full host URI with live-session credential updates.
  • Added provider-backed credential coverage, a non-default enterprise URL assertion, degraded-metadata logging coverage, and cleanup coverage where disconnect itself fails. The focused file now passes 134 tests, type-check, and ESLint.
  • The two existing inline findings targeted the removed protected-resource fallback. I replied with the replacement lifecycle and resolved both outdated threads.

@pwang347

Copy link
Copy Markdown
Contributor Author

@pwang347
Paul (pwang347) marked this pull request as ready for review October 15, 2026 06:24
@pwang347
Paul (pwang347) merged commit 53da99b into main Oct 15, 2026
55 of 56 checks passed
@pwang347
Paul (pwang347) deleted the fix/customizations-marketplace-sign-in branch October 15, 2026 06:33
@vs-code-engineering vs-code-engineering Bot added this to the 1.143.0 milestone Oct 15, 2026
Vritant Bhardwaj (vritant24) added a commit that referenced this pull request Oct 19, 2026
…ession

While a Copilot chat was open, the customization marketplace failed to load
installation receipts and the renderer logged, many times per second:

  Unable to load session-bound SDK installation receipts The SDK could not
  list installed MCP servers. (refused: policy-context-unavailable)

Root cause: CopilotCustomizationInstallations preferred the visible chat's SDK
session as `policySessionId` for list, recover, search, and install/uninstall
planning, and used the hidden policy session only when no chat was open. The
Copilot runtime admits installation and inventory requests only when the policy
session's GitHub credential is verified (a github.com login backed by a
resolved Copilot user record; see mcp_installation `authority()` ->
`installation_account_fingerprint()`). A credential supplied at createSession
(`gitHubToken`/`gitHubTokenProvider`) is never verified. Only
`session.rpc.gitHubAuth.setCredentials` verifies it. #341648 added that call to
the hidden policy session, but chat sessions get it only when the token changes
while they are live. Chats created after the last token change, and
provider-backed chats, were never verified, so every request bound to them was
refused.

Fix: always use the hidden, credential-verified policy session
(`getOrCreatePolicySessionId`) for catalog search, inventory, recovery, and
install/uninstall planning. None of these operations needs the chat's
identity:

- Installation receipts are scoped by the runtime's Copilot home plus the
  account and host fingerprints, not by session or working directory.
- The hidden session enables the same catalog-installation feature flags and
  managed settings as chat sessions.
- The client-level `installationConfirmationHandler` matches on the
  `policySessionId` that planned the operation. Plan and apply now always use
  the same hidden session, so confirmation matching is unchanged.
- Catalog cursors and selections stay keyed by `policySessionId`. They are now
  invalidated when the hidden session is replaced (auth change, client
  restart, idle disposal) rather than when switching between chats.
  Replacement goes through the existing re-search recovery path.

The visible-session getter and the no-factory path ("Start a Copilot agent
session before managing SDK installations." / `unavailable: session`) are
removed. The only production construction (CopilotAgent) always provides the
hidden-session factory, so that path was reachable only from tests. The factory
is now required. `releasePolicySession` behavior and the 10-minute idle
disposal are unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Vritant Bhardwaj (vritant24) added a commit that referenced this pull request Oct 19, 2026
…ession (#342613)

<!-- Thank you for submitting a Pull Request. Please:
* Read our Pull Request guidelines:

https://github.com/microsoft/vscode/wiki/How-to-Contribute#pull-requests
* Associate an issue with the Pull Request.
* Ensure that the code is up-to-date with the `main` branch.
* Include a description of the proposed changes and how to test them.
-->

## Problem

While a Copilot chat is open, the customization marketplace can't load
installation receipts. The renderer logs this many times per second:

```
[AgentHostCustomizationMarketplace] Unable to load session-bound SDK installation receipts The SDK could not list installed MCP servers. (refused: policy-context-unavailable)
```

## Root cause

`CopilotCustomizationInstallations` used the open chat's SDK session as
`policySessionId` for `list`, `recover`, `search`, and install/uninstall
planning. It used the hidden policy session only when no chat was open.

The Copilot runtime admits installation and inventory requests only when
the policy session's GitHub credential is **verified**: a github.com
login backed by a resolved Copilot user record (`mcp_installation`
`authority()` → `installation_account_fingerprint()`). A credential
passed at `createSession` (`gitHubToken` / `gitHubTokenProvider`) is
never verified. Only `session.rpc.gitHubAuth.setCredentials` verifies
it. A standalone SDK repro against runtimes 1.0.92-0 through 1.0.100-1
showed `refused: policy-context-unavailable` with the createSession
token, even after a chat turn, and `listed` right after `setCredentials`
on the same session.

#341648 added `setCredentials` to the hidden policy session. Chat
sessions get it only when the token changes while they're live. Chats
created after the last token change, and provider-backed chats, are
never verified.

## Fix

Search, inventory, recovery, and install/uninstall planning now always
use the hidden policy session (`getOrCreatePolicySessionId`). None of
these operations needs the chat's identity:

- **Receipts:** the runtime scopes them by Copilot home plus account and
host fingerprints, not by session or working directory, so results are
the same.
- **Feature flags and managed settings:** the hidden session has the
same catalog-installation feature flags and managed settings as chat
sessions.
- **Confirmation:** the client-level `installationConfirmationHandler`
matches on the `policySessionId` that planned the operation. Plan and
apply now always use the same hidden session, so matching is unchanged.
- **Cursors and selections:** they stay keyed by `policySessionId`.
They're now invalidated when the hidden session is replaced (auth
change, client restart, idle disposal) rather than when you switch
chats. The existing re-search recovery path handles that.

The visible-session getter and the no-factory path are removed. That
path produced "Start a Copilot agent session before managing SDK
installations." and `unavailable: session`. The only production caller
(`CopilotAgent`) always provides the hidden-session factory, so only
tests could reach it. The factory is now required.
`releasePolicySession` and the 10-minute idle disposal are unchanged.
`AI_CUSTOMIZATIONS.md` is updated.

## Tests

- `copilotCustomizationInstallations.test.ts`: tests that relied on a
fixed chat session ID now use a `TestPolicySessions` helper that records
created sessions. A new test checks that search, list, recover, and
prepare all bind to one hidden session.
- `copilotAgent.test.ts`: a new test opens a live chat and checks that
`listCustomizationInstallations` goes to the hidden session, which
received `setCredentials`, and not to the chat's session.

## Validation

- `npm run typecheck-client`: passed
- `npm run eslint -- <changed files>`: passed
- `./scripts/test.sh --run
src/vs/platform/agentHost/test/node/copilotCustomizationInstallations.test.ts
--run src/vs/platform/agentHost/test/node/copilotSessionLauncher.test.ts
--run src/vs/platform/agentHost/test/node/copilotAgent.test.ts`: 1012
passing, 1 pending, 1 failing. The failure is `isolates peer runtimes,
preserves local adoption identity and refuses revoked prepared work`,
which also fails on unmodified `main` (`e1a22a1ad40`).
Vritant Bhardwaj (vritant24) added a commit that referenced this pull request Oct 19, 2026
…ified policy session (#342629)

Cherry-pick of #342613 from `main`.

<!-- Thank you for submitting a Pull Request. Please:
* Read our Pull Request guidelines:

https://github.com/microsoft/vscode/wiki/How-to-Contribute#pull-requests
* Associate an issue with the Pull Request.
* Ensure that the code is up-to-date with the `main` branch.
* Include a description of the proposed changes and how to test them.
-->

## Problem

While a Copilot chat is open, the customization marketplace can't load
installation receipts. The renderer logs this many times per second:

```
[AgentHostCustomizationMarketplace] Unable to load session-bound SDK installation receipts The SDK could not list installed MCP servers. (refused: policy-context-unavailable)
```

## Root cause

`CopilotCustomizationInstallations` used the open chat's SDK session as
`policySessionId` for `list`, `recover`, `search`, and install/uninstall
planning. It used the hidden policy session only when no chat was open.

The Copilot runtime admits installation and inventory requests only when
the policy session's GitHub credential is **verified**: a github.com
login backed by a resolved Copilot user record (`mcp_installation`
`authority()` → `installation_account_fingerprint()`). A credential
passed at `createSession` (`gitHubToken` / `gitHubTokenProvider`) is
never verified. Only `session.rpc.gitHubAuth.setCredentials` verifies
it. A standalone SDK repro against runtimes 1.0.92-0 through 1.0.100-1
showed `refused: policy-context-unavailable` with the createSession
token, even after a chat turn, and `listed` right after `setCredentials`
on the same session.

#341648 added `setCredentials` to the hidden policy session. Chat
sessions get it only when the token changes while they're live. Chats
created after the last token change, and provider-backed chats, are
never verified.

## Fix

Search, inventory, recovery, and install/uninstall planning now always
use the hidden policy session (`getOrCreatePolicySessionId`). None of
these operations needs the chat's identity:

- **Receipts:** the runtime scopes them by Copilot home plus account and
host fingerprints, not by session or working directory, so results are
the same.
- **Feature flags and managed settings:** the hidden session has the
same catalog-installation feature flags and managed settings as chat
sessions.
- **Confirmation:** the client-level `installationConfirmationHandler`
matches on the `policySessionId` that planned the operation. Plan and
apply now always use the same hidden session, so matching is unchanged.
- **Cursors and selections:** they stay keyed by `policySessionId`.
They're now invalidated when the hidden session is replaced (auth
change, client restart, idle disposal) rather than when you switch
chats. The existing re-search recovery path handles that.

The visible-session getter and the no-factory path are removed. That
path produced "Start a Copilot agent session before managing SDK
installations." and `unavailable: session`. The only production caller
(`CopilotAgent`) always provides the hidden-session factory, so only
tests could reach it. The factory is now required.
`releasePolicySession` and the 10-minute idle disposal are unchanged.
`AI_CUSTOMIZATIONS.md` is updated.

## Tests

- `copilotCustomizationInstallations.test.ts`: tests that relied on a
fixed chat session ID now use a `TestPolicySessions` helper that records
created sessions. A new test checks that search, list, recover, and
prepare all bind to one hidden session.
- `copilotAgent.test.ts`: a new test opens a live chat and checks that
`listCustomizationInstallations` goes to the hidden session, which
received `setCredentials`, and not to the chat's session.

## Validation

- `npm run typecheck-client`: passed
- `npm run eslint -- <changed files>`: passed
- `./scripts/test.sh --run
src/vs/platform/agentHost/test/node/copilotCustomizationInstallations.test.ts
--run src/vs/platform/agentHost/test/node/copilotSessionLauncher.test.ts
--run src/vs/platform/agentHost/test/node/copilotAgent.test.ts`: 1012
passing, 1 pending, 1 failing. The failure is `isolates peer runtimes,
preserves local adoption identity and refuses revoked prepared work`,
which also fails on unmodified `main` (`e1a22a1ad40`).
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.

3 participants