Skip to content

fix(desktop): Antigravity Sign in opens the browser right away - #30126

Open
wenshen18643 wants to merge 1 commit into
pingdotgg:mainfrom
wenshen18643:fix/antigravity-open-sign-in-link
Open

wenshen18643 wants to merge 1 commit into
pingdotgg:mainfrom
wenshen18643:fix/antigravity-open-sign-in-link

Conversation

@wenshen18643

Copy link
Copy Markdown
Contributor

Problem

In the desktop app, pressing Sign in for Antigravity looks like it does nothing. The Google link does not exist yet: the Antigravity runtime creates it (OAuth state, PKCE, and a 127.0.0.1 redirect to its own listener), and on Windows the runtime takes about a minute to start (measured in #30079). When the link does arrive, the Account row shows an Open browser button, but only while Settings is open. Users who leave Settings during that minute, the natural reaction to "nothing happened", never see the link. The sign-in then expires after five minutes and the account stays signed out.

Reproduction: Windows 11, T3 Code desktop 0.1.6, Antigravity runtime 1.1.1. Press Sign in under Settings > Providers > Antigravity, then go back to a thread. No browser opens, and after five minutes the sign-in has expired. In my server trace: provider.auth.start at 17:06:11, the last Settings subscription closed at 17:06:46, the link was published at 17:07:22 with no subscriber, and the flow expired at 17:11:11.

Change

On desktop, Sign in now opens the browser immediately. The page there continues to Google as soon as the link exists.

  • Desktop main process (apps/desktop/src/app/PendingSignInPage.ts): starts a short-lived loopback listener on 127.0.0.1 with a random port and a 256-bit random path, and opens the browser to it with the existing ElectronShell.openExternal. It is modeled on the ChatGPT loopback helper (packages/shared/src/codexAuthCallback.ts).
    • While waiting, the page says "Starting sign-in" and refreshes every second.
    • Once settled with the link, it answers with a 303 to Google. Only https://accounts.google.com/o/oauth2/v2/auth is accepted, and the stored URL is the parsed href.
    • If sign-in ends without a link, the page says "Sign-in stopped".
    • Requests must be GET on the exact path with Host: 127.0.0.1:<port>, which rules out DNS rebinding. Responses are no-store, no-referrer, nosniff, with a strict CSP.
    • An unsettled page turns into "Sign-in stopped" after 5.5 minutes, for example if the renderer reloads. Every page closes a minute after it settles. At most four pages can be open, counting ones still opening.
  • IPC: openPendingSignIn() and settlePendingSignIn(id, url | null), with schema-validated payloads, on the main window's bridge.
  • Web:
    • watchProviderSignInLink watches providerAuthState through the app atom registry, so the subscription outlives the Settings view. It hands over the link for the flow this client started. It calls onEnd if that flow ends, disappears after being seen (for example on a server restart), or times out.
    • ProviderAuthenticationSection uses it only for Antigravity Google sign-in on desktop, not for API-key connections. If the page cannot open, or forwarding fails, the link opens directly when it arrives. Web clients keep Open browser, since a tab opened without a click would be blocked.
  • Docs: one sentence in docs/user/providers-antigravity.md.

Linux behaves the same in the desktop app, because Electron opens the default browser. A headless Linux server has no desktop app, so its web clients keep the button.

Related: #30079 fixes the misleading "has not reached Google" hint shown during the same startup wait. The two changes are independent.

Scope and approval

This changes desktop sign-in so the browser opens on the click instead of after a second click about a minute later. I'm submitting it as a focused fix because, today, a desktop Google sign-in only finishes if the user stays on Settings for a minute and then clicks again. Meanwhile the Account row already says "Finish signing in in your browser." while no browser is open. Nothing opens except the validated Google link the server already shows to the client that started sign-in. If you'd rather settle the behavior in an Ideas discussion first, I'm happy to move it there.

Verification

  • vp test run apps/desktop/src/app/PendingSignInPage.test.ts: 9/9 pass, over real loopback HTTP. They cover:

    • the waiting page with refresh
    • 404 for a wrong path or a rebound Host
    • the 303 to the exact link, including normalization of a trailing control character
    • refusal of non-Google, non-OAuth, plain-http or invalid links
    • the stopped page without refresh
    • expiry to stopped, then closed
    • the cap on concurrently opening pages
    • the listener closing when the browser can't be opened or the opener throws

    Stable over three runs.

  • vp test run apps/web/src/providerSignInLink.test.ts: 8/8 pass. They cover:

    • opening once for its own flow, or immediately if the link is already shown
    • ignoring other flows and older snapshots
    • onEnd when the flow is cancelled, vanishes after being seen, or times out, but not on an early stop
    • a throwing callback not escaping into the shared subscription
    • an idle-TTL-0 pushed atom, like providerAuthState, staying subscribed after the "Settings" mount is released and closing after the link opens. Without the watcher, that test fails because the stream closes on unmount.
  • vp test run apps/web/src/components/settings/ProviderSetupSection.browser.test.tsx: 6/6 pass. They check that, with a desktop bridge, Sign in opens the pending page and the watcher settles it with the link or null. Without a bridge, neither happens. A Gemini API key Connect opens no page. With the component change reverted, the desktop case fails.

  • Real Chromium (Playwright, with accounts.google.com mapped to NXDOMAIN so nothing reached Google): the page loaded as "Starting sign-in · T3 Code" and kept refreshing for 3 s. Within about 1 s of settling, the browser requested the exact Google link. A page settled with null showed "Sign-in stopped · T3 Code".

  • vp test run apps/desktop/src/ipc apps/desktop/src/app/DesktopApp.test.ts passes. tsc --noEmit for packages/contracts, apps/desktop and apps/web, plus vp lint and vp fmt --check on the changed files, are clean.

  • Not checked: I did not run the packaged or dev desktop app end to end, so the click-to-browser step through Electron's shell.openExternal is covered by the existing bridge, not by a recording. I have no macOS or Linux desktop to try.

Done with Claude Opus 5.5 in Claude Code.

🤖 Generated with Claude Code

Antigravity's runtime takes about a minute on Windows to produce its Google
link, and the Account row only offered an Open browser button while Settings
stayed open, so desktop sign-ins usually expired unseen. On desktop, Sign in
now opens a local loopback page immediately; it forwards to the validated
Google link when the runtime reports it, even if Settings was closed, or says
that sign-in stopped. Web clients keep the button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Nov 3, 2026
@macroscopeapp

macroscopeapp Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs Human Approval

Macroscope's review found this PR requires human approval — Desktop Antigravity sign-in now opens a browser immediately using a bounded local waiting page. Human review is required for this default interaction change and the new file-level diagnostic suppressions in PendingSignInPage.ts.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

Adds a loopback page for desktop Antigravity sign-in while the Google authorization link is pending. Connects the page to provider-flow link monitoring through the desktop bridge, and redirects to a validated Google OAuth URL when one arrives.

Changes: Antigravity sign-in handoff

Layer / File(s) Summary
Loopback page lifecycle
apps/desktop/src/app/PendingSignInPage.ts, apps/desktop/src/app/PendingSignInPage.test.ts
Adds a loopback server with waiting and stopped states, Google OAuth URL validation, expiry and cleanup, and a limit of four open pages. Tests cover redirects, rejected URLs, request validation, expiry, and browser-opening failures.
Desktop bridge and IPC
packages/contracts/src/ipc.ts, apps/desktop/src/ipc/channels.ts, apps/desktop/src/ipc/methods/providerAuth.ts, apps/desktop/src/ipc/DesktopIpcHandlers.ts, apps/desktop/src/preload.ts
Adds bridge methods and IPC channels to open a pending page and settle it with a nullable authorization URL.
Web sign-in link handoff
apps/web/src/providerSignInLink.ts, apps/web/src/providerSignInLink.test.ts, apps/web/src/components/settings/ProviderAuthenticationSection.tsx, apps/web/src/components/settings/ProviderSetupSection.browser.test.tsx, docs/user/providers-antigravity.md
Adds provider-flow link monitoring and connects eligible desktop Antigravity sign-ins to pending-page settlement. Tests cover watcher outcomes and desktop, non-desktop, and API-key paths. Updates setup instructions for desktop and web sign-in.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant ProviderAuthenticationSection
  participant desktopBridge
  participant PendingSignInPage
  participant ProviderAuthState
  participant Browser
  ProviderAuthenticationSection->>desktopBridge: openPendingSignIn()
  desktopBridge->>PendingSignInPage: Open page through IPC
  PendingSignInPage-->>desktopBridge: Return page ID
  desktopBridge-->>ProviderAuthenticationSection: Return page ID
  ProviderAuthenticationSection->>ProviderAuthState: Watch sign-in flow for authorization link
  ProviderAuthState-->>ProviderAuthenticationSection: Provide Google authorization URL
  ProviderAuthenticationSection->>desktopBridge: settlePendingSignIn(id, authorizationUrl)
  desktopBridge->>PendingSignInPage: Settle page
  Browser->>PendingSignInPage: GET loopback page
  PendingSignInPage-->>Browser: HTTP 303 to Google authorization URL
Loading

Possibly related issues

  • pingdotgg/t3code#9624 — Reports a desktop Antigravity browser handoff failure; this change adds the pending-page handoff and forwards the Google authorization URL.
  • pingdotgg/t3code#29379 — Reports delayed browser-link availability and a local-page handoff issue; this change opens the desktop page earlier and redirects it when the Google URL arrives.

Suggested labels: bugfix, size:L

Suggested reviewers: t3dotgg, juliusmarminge, macroscopeapp

Merge Risk: Minimal · up to 448ee

The sign-in handoff has no confirmed issue requiring a fix before merge.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly and concisely describes the primary change: desktop Antigravity sign-in opens the browser immediately.
Description check Passed The description includes all required sections. It clearly explains the problem, implementation, scope rationale, verification results, limitations, and agent details.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between cefb544 and 448ee89.

Files selected for processing: 12
  • apps/desktop/src/app/PendingSignInPage.test.ts
  • apps/desktop/src/app/PendingSignInPage.ts
  • apps/desktop/src/ipc/DesktopIpcHandlers.ts
  • apps/desktop/src/ipc/channels.ts
  • apps/desktop/src/ipc/methods/providerAuth.ts
  • apps/desktop/src/preload.ts
  • apps/web/src/components/settings/ProviderAuthenticationSection.tsx
  • apps/web/src/components/settings/ProviderSetupSection.browser.test.tsx
  • apps/web/src/providerSignInLink.test.ts
  • apps/web/src/providerSignInLink.ts
  • docs/user/providers-antigravity.md
  • packages/contracts/src/ipc.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

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

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants