From 636da4c932e1e0fe6e23cba5bb3030e341a76c21 Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Fri, 20 Mar 2026 12:24:27 +0800 Subject: [PATCH] refactor(auth): replace manual input handling with AsyncPrompt for callback URLs --- internal/auth/gemini/gemini_auth.go | 13 +------------ internal/misc/oauth.go | 17 +++++++++++++++++ sdk/auth/antigravity.go | 13 +------------ sdk/auth/claude.go | 13 +------------ sdk/auth/codex.go | 13 +------------ sdk/auth/iflow.go | 13 +------------ 6 files changed, 22 insertions(+), 60 deletions(-) diff --git a/internal/auth/gemini/gemini_auth.go b/internal/auth/gemini/gemini_auth.go index 0830e0a2..2995a1cb 100644 --- a/internal/auth/gemini/gemini_auth.go +++ b/internal/auth/gemini/gemini_auth.go @@ -329,18 +329,7 @@ waitForCallback: return nil, err default: } - inputCh := make(chan string, 1) - inputErrCh := make(chan error, 1) - go func() { - input, err := opts.Prompt("Paste the Gemini callback URL (or press Enter to keep waiting): ") - if err != nil { - inputErrCh <- err - return - } - inputCh <- input - }() - manualInputCh = inputCh - manualInputErrCh = inputErrCh + manualInputCh, manualInputErrCh = misc.AsyncPrompt(opts.Prompt, "Paste the Gemini callback URL (or press Enter to keep waiting): ") continue case input := <-manualInputCh: manualInputCh = nil diff --git a/internal/misc/oauth.go b/internal/misc/oauth.go index c14f39d2..88be2eef 100644 --- a/internal/misc/oauth.go +++ b/internal/misc/oauth.go @@ -30,6 +30,23 @@ type OAuthCallback struct { ErrorDescription string } +// AsyncPrompt runs a prompt function in a goroutine and returns channels for +// the result. The returned channels are buffered (size 1) so the goroutine can +// complete even if the caller abandons the channels. +func AsyncPrompt(promptFn func(string) (string, error), message string) (<-chan string, <-chan error) { + inputCh := make(chan string, 1) + errCh := make(chan error, 1) + go func() { + input, err := promptFn(message) + if err != nil { + errCh <- err + return + } + inputCh <- input + }() + return inputCh, errCh +} + // ParseOAuthCallback extracts OAuth parameters from a callback URL. // It returns nil when the input is empty. func ParseOAuthCallback(input string) (*OAuthCallback, error) { diff --git a/sdk/auth/antigravity.go b/sdk/auth/antigravity.go index 38617868..d52bf1d2 100644 --- a/sdk/auth/antigravity.go +++ b/sdk/auth/antigravity.go @@ -118,18 +118,7 @@ waitForCallback: break waitForCallback default: } - inputCh := make(chan string, 1) - inputErrCh := make(chan error, 1) - go func() { - input, errPrompt := opts.Prompt("Paste the antigravity callback URL (or press Enter to keep waiting): ") - if errPrompt != nil { - inputErrCh <- errPrompt - return - } - inputCh <- input - }() - manualInputCh = inputCh - manualInputErrCh = inputErrCh + manualInputCh, manualInputErrCh = misc.AsyncPrompt(opts.Prompt, "Paste the antigravity callback URL (or press Enter to keep waiting): ") continue case input := <-manualInputCh: manualInputCh = nil diff --git a/sdk/auth/claude.go b/sdk/auth/claude.go index 4e54a99f..d82a718b 100644 --- a/sdk/auth/claude.go +++ b/sdk/auth/claude.go @@ -152,18 +152,7 @@ waitForCallback: return nil, err default: } - inputCh := make(chan string, 1) - inputErrCh := make(chan error, 1) - go func() { - input, errPrompt := opts.Prompt("Paste the Claude callback URL (or press Enter to keep waiting): ") - if errPrompt != nil { - inputErrCh <- errPrompt - return - } - inputCh <- input - }() - manualInputCh = inputCh - manualInputErrCh = inputErrCh + manualInputCh, manualInputErrCh = misc.AsyncPrompt(opts.Prompt, "Paste the Claude callback URL (or press Enter to keep waiting): ") continue case input := <-manualInputCh: manualInputCh = nil diff --git a/sdk/auth/codex.go b/sdk/auth/codex.go index 7a6e0d38..269e3d8b 100644 --- a/sdk/auth/codex.go +++ b/sdk/auth/codex.go @@ -155,18 +155,7 @@ waitForCallback: return nil, err default: } - inputCh := make(chan string, 1) - inputErrCh := make(chan error, 1) - go func() { - input, errPrompt := opts.Prompt("Paste the Codex callback URL (or press Enter to keep waiting): ") - if errPrompt != nil { - inputErrCh <- errPrompt - return - } - inputCh <- input - }() - manualInputCh = inputCh - manualInputErrCh = inputErrCh + manualInputCh, manualInputErrCh = misc.AsyncPrompt(opts.Prompt, "Paste the Codex callback URL (or press Enter to keep waiting): ") continue case input := <-manualInputCh: manualInputCh = nil diff --git a/sdk/auth/iflow.go b/sdk/auth/iflow.go index 0e7b5ce8..584a3169 100644 --- a/sdk/auth/iflow.go +++ b/sdk/auth/iflow.go @@ -131,18 +131,7 @@ waitForCallback: return nil, fmt.Errorf("iflow auth: callback wait failed: %w", err) default: } - inputCh := make(chan string, 1) - inputErrCh := make(chan error, 1) - go func() { - input, errPrompt := opts.Prompt("Paste the iFlow callback URL (or press Enter to keep waiting): ") - if errPrompt != nil { - inputErrCh <- errPrompt - return - } - inputCh <- input - }() - manualInputCh = inputCh - manualInputErrCh = inputErrCh + manualInputCh, manualInputErrCh = misc.AsyncPrompt(opts.Prompt, "Paste the iFlow callback URL (or press Enter to keep waiting): ") continue case input := <-manualInputCh: manualInputCh = nil