Repository navigation
feat(app): copy the device code before opening the sign-in page - #59676
aryankeluskar wants to merge 3 commits into
Conversation
Device sign-ins such as GitHub Copilot's open a page that asks for the code without prefilling it. Copy the code to the clipboard first, so it can be pasted straight away; once the browser has focus the app can no longer write to the clipboard. Sign-ins whose URL already carries the code (`user_code`) leave the clipboard alone.
There was a problem hiding this comment.
Works as described. With the base controller, the new e2e case fails (Expected "8EA6-ACBA", Received ""), and with this change it passes. The other providers: cases and tsc --noEmit for packages/app pass. The regex matches the TUI's OAUTH_CODE and the Enter code: … text the Copilot, OpenAI and Console plugins produce, and the Console sign-in (whose URL carries user_code) is left alone.
The public API is unchanged.
One small fix is noted inline: new URL(url) can now throw before the browser opens.
|
|
||
| // Device pages such as GitHub's ask for a code the URL does not prefill (no `user_code`). Copy it | ||
| // before opening the browser: once the browser has focus, the app can no longer write to the clipboard. | ||
| const code = new URL(url).searchParams.has("user_code") |
There was a problem hiding this comment.
This now runs before any URL check and outside the .catch. With an empty or unparsable url (previously guarded by if (!url) return), new URL throws, open() rejects unhandled, and browserFailed is never set. Using URL.canParse(url) && new URL(url).searchParams.has("user_code"), like the web platform's openExternal does, or keeping the !url early return, avoids that.
Restore the early return for an empty sign-in URL and check URL.canParse before reading user_code, so open() no longer throws before the browser opens and still reports browserFailed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
The earlier point is addressed: the empty-URL guard is back, and URL.canParse keeps an invalid URL from throwing before the browser opens. I re-ran the device-code and Console sign-in e2e cases (both pass) and tsc --noEmit for packages/app (clean). The public API is unchanged. No new concerns.
Issue for this PR
None that I could find.
Type of change
What does this PR do?
Connecting GitHub Copilot in the app opens GitHub's device page. That page asks for the confirmation code but doesn't prefill it, so you had to switch back to the app and press the copy button next to the code. Now the app copies the code to the clipboard right before it opens the browser, and you can paste it straight away. ChatGPT's device sign-in gets the same behavior.
The change is in
open()inpackages/app/src/providers/connect/controller.ts, which runs for the automatic open and for the Open browser button. It finds the code in the attempt'sinstructions, such asEnter code: 8EA6-ACBA, with the same regex asOAUTH_CODEin the TUI'sdialog-integration.tsx. The copy has to come first because once the browser has focus, the web app can no longer write to the clipboard.If the URL already carries
user_code, as the OpenCode Console sign-in's URL does,open()leaves the clipboard alone. If the clipboard write fails,open()ignores the error and opens the browser anyway. The copy button still works.How did you verify your code works?
A new case in
packages/app/e2e/regression/settings.spec.ts, "providers: a device sign-in copies the code its page does not prefill", starts a Copilot sign-in, waits for the popup, and reads the clipboard. It fails without the change withExpected "8EA6-ACBA", Received "". To support it,onIntegrationOAuthin the e2e mock server can now returninstructions. The server used to hard-code them to"".All 13
providers:cases pass, and typecheck, oxlint, and prettier are clean:Visual
Screenshots / recordings
None. Nothing on screen changes, because the code is already on the clipboard when the browser opens.
Checklist