mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-12 22:14:22 +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:
1 parent
cfe604a97c
commit
0557f93f2f
1 file changed
+21
@@ -347,6 +347,21 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise<Accou
|
|||||||
|
|
||||||
const startTime = Date.now();
|
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) => {
|
authProcess.stdout?.on('data', async (data: Buffer) => {
|
||||||
await handleStdout(data.toString(), state, options, authProcess, log);
|
await handleStdout(data.toString(), state, options, authProcess, log);
|
||||||
});
|
});
|
||||||
@@ -393,6 +408,8 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise<Accou
|
|||||||
// Timeout handling
|
// Timeout handling
|
||||||
const timeoutMs = headless ? 300000 : 120000;
|
const timeoutMs = headless ? 300000 : 120000;
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
|
// H7: Clear stdin keepalive interval
|
||||||
|
if (stdinKeepalive) clearInterval(stdinKeepalive);
|
||||||
// H5: Remove signal handlers before killing process
|
// H5: Remove signal handlers before killing process
|
||||||
process.removeListener('SIGINT', cleanup);
|
process.removeListener('SIGINT', cleanup);
|
||||||
process.removeListener('SIGTERM', cleanup);
|
process.removeListener('SIGTERM', cleanup);
|
||||||
@@ -409,6 +426,8 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise<Accou
|
|||||||
|
|
||||||
authProcess.on('exit', async (code) => {
|
authProcess.on('exit', async (code) => {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
|
// H7: Clear stdin keepalive interval
|
||||||
|
if (stdinKeepalive) clearInterval(stdinKeepalive);
|
||||||
// H5: Remove signal handlers to prevent memory leaks
|
// H5: Remove signal handlers to prevent memory leaks
|
||||||
process.removeListener('SIGINT', cleanup);
|
process.removeListener('SIGINT', cleanup);
|
||||||
process.removeListener('SIGTERM', cleanup);
|
process.removeListener('SIGTERM', cleanup);
|
||||||
@@ -462,6 +481,8 @@ export function executeOAuthProcess(options: OAuthProcessOptions): Promise<Accou
|
|||||||
|
|
||||||
authProcess.on('error', (error) => {
|
authProcess.on('error', (error) => {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
|
// H7: Clear stdin keepalive interval
|
||||||
|
if (stdinKeepalive) clearInterval(stdinKeepalive);
|
||||||
// H5: Remove signal handlers to prevent memory leaks
|
// H5: Remove signal handlers to prevent memory leaks
|
||||||
process.removeListener('SIGINT', cleanup);
|
process.removeListener('SIGINT', cleanup);
|
||||||
process.removeListener('SIGTERM', cleanup);
|
process.removeListener('SIGTERM', cleanup);
|
||||||
|
|||||||
Reference in new issue
Block a user