mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 10:16:49 +00:00
fix(oauth): add stdin keepalive to prevent blocking on manual URL prompt
CLIProxyAPIPlus has a 15-second timer that prompts for manual URL paste. If user completes browser auth after this timer fires but before the non-blocking check, the prompt blocks forever on stdin since CCS pipes stdin but doesn't write to it. Workaround: Send newline every 16s for authorization code flows to skip the manual prompt and continue polling for callback.
This commit is contained in:
@@ -347,6 +347,21 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise<Accou
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
// H7: Stdin keepalive for Authorization Code flows
|
||||
// CLIProxyAPIPlus has a 15-second timer that prompts for manual URL paste.
|
||||
// If the user completes browser auth after this timer fires but before the
|
||||
// non-blocking check, the prompt blocks forever on stdin.
|
||||
// Workaround: Send newline every 16s to skip the manual prompt and continue polling.
|
||||
let stdinKeepalive: ReturnType<typeof setInterval> | null = null;
|
||||
if (!isDeviceCodeFlow && stdinMode === 'pipe') {
|
||||
stdinKeepalive = setInterval(() => {
|
||||
if (authProcess.stdin && !authProcess.stdin.destroyed) {
|
||||
authProcess.stdin.write('\n');
|
||||
log('Sent stdin keepalive (skip manual URL prompt)');
|
||||
}
|
||||
}, 16000);
|
||||
}
|
||||
|
||||
authProcess.stdout?.on('data', async (data: Buffer) => {
|
||||
await handleStdout(data.toString(), state, options, authProcess, log);
|
||||
});
|
||||
@@ -393,6 +408,8 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise<Accou
|
||||
// Timeout handling
|
||||
const timeoutMs = headless ? 300000 : 120000;
|
||||
const timeout = setTimeout(() => {
|
||||
// H7: Clear stdin keepalive interval
|
||||
if (stdinKeepalive) clearInterval(stdinKeepalive);
|
||||
// H5: Remove signal handlers before killing process
|
||||
process.removeListener('SIGINT', cleanup);
|
||||
process.removeListener('SIGTERM', cleanup);
|
||||
@@ -409,6 +426,8 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise<Accou
|
||||
|
||||
authProcess.on('exit', async (code) => {
|
||||
clearTimeout(timeout);
|
||||
// H7: Clear stdin keepalive interval
|
||||
if (stdinKeepalive) clearInterval(stdinKeepalive);
|
||||
// H5: Remove signal handlers to prevent memory leaks
|
||||
process.removeListener('SIGINT', cleanup);
|
||||
process.removeListener('SIGTERM', cleanup);
|
||||
@@ -462,6 +481,8 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise<Accou
|
||||
|
||||
authProcess.on('error', (error) => {
|
||||
clearTimeout(timeout);
|
||||
// H7: Clear stdin keepalive interval
|
||||
if (stdinKeepalive) clearInterval(stdinKeepalive);
|
||||
// H5: Remove signal handlers to prevent memory leaks
|
||||
process.removeListener('SIGINT', cleanup);
|
||||
process.removeListener('SIGTERM', cleanup);
|
||||
|
||||
Reference in New Issue
Block a user