From c811fdfc7914cc3bde3811ea04281055ebb3e273 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Wed, 24 Dec 2025 03:52:27 -0500 Subject: [PATCH] fix(qwen): inherit stdin for Device Code flows to enable interactive prompts Device Code flows (Qwen, GHCP) may require interactive terminal input before generating the device code. For example, Qwen prompts for email. Previously, all auth processes used piped stdin which blocked user input. Now Device Code flows use 'inherit' for stdin, allowing users to respond to prompts directly in the terminal. Authorization Code flows (Gemini, Codex) still use piped stdin for programmatic project selection. Closes #188 --- src/cliproxy/auth/oauth-process.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cliproxy/auth/oauth-process.ts b/src/cliproxy/auth/oauth-process.ts index 51848279..60396c07 100644 --- a/src/cliproxy/auth/oauth-process.ts +++ b/src/cliproxy/auth/oauth-process.ts @@ -112,8 +112,8 @@ async function handleStdout( log(`Parsed ${state.parsedProjects.length} projects`); } - // Handle project selection prompt - if (!state.projectPromptHandled && isProjectSelectionPrompt(output)) { + // Handle project selection prompt (Authorization Code flows only - Device Code has no stdin pipe) + if (!isDeviceCodeFlow && !state.projectPromptHandled && isProjectSelectionPrompt(output)) { state.projectPromptHandled = true; await handleProjectSelection(output, state, options, authProcess, log); } @@ -258,8 +258,13 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise((resolve) => { + // Device Code flows (Qwen, GHCP) may need interactive stdin for email/prompts + // Authorization Code flows need piped stdin for project selection + const isDeviceCodeFlow = callbackPort === null; + const stdinMode = isDeviceCodeFlow ? 'inherit' : 'pipe'; + const authProcess = spawn(binaryPath, args, { - stdio: ['pipe', 'pipe', 'pipe'], + stdio: [stdinMode, 'pipe', 'pipe'], env: { ...process.env, CLI_PROXY_AUTH_DIR: tokenDir }, }); @@ -291,7 +296,6 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise { if (isDeviceCodeFlow) { // Device Code Flow: show polling message