microsoft / microsoft/vscode

Agents window: sign-in modal flashes on reload before the conditional-auth gate resolves

Open
#329,007 0 comments 0 reactions 1 assignee Claimed by @TylerLeonhardt View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

> [!NOTE]
> Follow-up to #328990, which is now **merged** (59bca39). Ready to pick up.

## The problem

With `chat.agentHost.allowSignedOutWhenUsable` enabled, signed out, and Claude resolving to native mode, **reloading the Agents window flashes the non-dismissible GitHub sign-in modal** before letting the user through.

This is the part that needs fixing. The user is never actually required to sign in — the modal appears and then dismisses itself — but flashing a non-dismissible auth wall at someone who is not being asked to authenticate reads as a failure.

There is a second, milder symptom from the same cause: the **"We've discovered your existing Claude configuration"** notification takes a beat to appear after reload. That one is acceptable as-is, and becomes less relevant once non-GitHub agents are allowed by default.

## Repro

1. Enable `chat.agentHost.allowSignedOutWhenUsable`
2. Launch the Agents window signed out (`launch.sh --agents -- --use-mock-keychain`) with a local Claude credential present, and no `claudeUseCopilotProxy` in `agent-host-config.json`
3. Reload the window (Cmd+R)

## Root cause

**The gate's inputs are asynchronous, and its initial value is "not usable."**

`observeUsableWithoutGitHub` derives from `getAllProviderSessionTypes()`. At window startup no agent-host session types have been advertised yet — the local agent host contributions register at `WorkbenchPhase.AfterRestored` — so the observable first reads `false`. `SessionsSetUpWidget` runs its startup check against that value, concludes sign-in is required, and shows the modal. Once the host advertises Claude, `onDidChangeSessionTypes` fires, the observable flips to `true`, and `_onUsableWithoutGitHubChanged` clears the dialog and lets the user in.

So the modal is *correctly* dismissed — it should never have been shown in the first place.

This is a known cost of the approach taken in #328990. The review there offered two options: react to the change, or *wait for the availability decision before showing the modal*. That PR took the first because it is the smaller change and fixes the correctness bug (previously the user was stuck behind the modal permanently). This issue is the second half.

## Suggested direction

The gate conflates **"resolved: nothing is usable"** with **"not resolved yet"**, and shows the modal for both. Making that distinction explicit is the fix:

- Give the gate an **unresolved** state and don't show the window-level modal while it holds — mirroring `ISessionType.authRequirement`, which already models a third state rather than an optional boolean for the same reason.
- Needs a **bounded wait**: if the agent host never reports (disabled, crashed, not installed), the gate must fall through to today's behaviour rather than hang. A settled/errored signal from the host is preferable to a timeout.
- Ordering alone is not enough — the host can advertise agents arbitrarily late, so pinning to a later lifecycle phase would just move the race.

## Environment

- Branch: `wip/discovered-config-onboarding` (#328990)
- macOS, Code OSS dev build

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.