diff --git a/bin/multiagent-safety.js b/bin/multiagent-safety.js index fc98160..a6e4b7b 100755 --- a/bin/multiagent-safety.js +++ b/bin/multiagent-safety.js @@ -1769,6 +1769,12 @@ function isInteractiveTerminal() { return Boolean(process.stdin.isTTY && process.stdout.isTTY); } +const stdinWaitArray = new Int32Array(new SharedArrayBuffer(4)); + +function sleepSyncMs(milliseconds) { + Atomics.wait(stdinWaitArray, 0, 0, milliseconds); +} + function readSingleLineFromStdin() { let input = ''; const buffer = Buffer.alloc(1); @@ -1777,11 +1783,19 @@ function readSingleLineFromStdin() { let bytesRead = 0; try { bytesRead = fs.readSync(process.stdin.fd, buffer, 0, 1); - } catch { + } catch (error) { + if (error && ['EAGAIN', 'EWOULDBLOCK', 'EINTR'].includes(error.code)) { + sleepSyncMs(15); + continue; + } return input; } if (bytesRead === 0) { + if (process.stdin.isTTY) { + sleepSyncMs(15); + continue; + } return input; } @@ -1921,9 +1935,8 @@ function maybeSelfUpdateBeforeStatus() { } const shouldUpdate = interactive - ? promptYesNo( + ? promptYesNoStrict( `Update now? (${NPM_BIN} i -g ${packageJson.name}@latest)`, - false, ) : autoApproval; diff --git a/test/install.test.js b/test/install.test.js index 018ccfa..d630a51 100644 --- a/test/install.test.js +++ b/test/install.test.js @@ -763,11 +763,11 @@ exit 1 assert.equal(fs.existsSync(markerPath), true, 'expected self-update command to run'); }); -test('self-update prompt defaults to no when approval is not preconfigured', () => { +test('self-update prompt requires explicit y/n when approval is not preconfigured', () => { const source = fs.readFileSync(cliPath, 'utf8'); assert.match( source, - /const shouldUpdate = interactive\s*\?\s*promptYesNo\(\s*`Update now\?\s*\(\$\{NPM_BIN\} i -g \$\{packageJson\.name\}@latest\)`\s*,\s*false,\s*\)\s*:\s*autoApproval;/s, + /const shouldUpdate = interactive\s*\?\s*promptYesNoStrict\(\s*`Update now\?\s*\(\$\{NPM_BIN\} i -g \$\{packageJson\.name\}@latest\)`\s*,?\s*\)\s*:\s*autoApproval;/s, ); });