Commit 771edeb
authored
fix(onboard): release stdin event-loop ref so the wizard exits after its final prompt (#2665)
## Summary
`nemoclaw onboard` on Linux interactive TTY hangs after the post-onboard
summary box — the wizard finishes, prints the dashboard URL, and then
sits there with no shell prompt until the user reaches for Ctrl+C. The
cause is `readline.createInterface({ input: process.stdin })` resuming
stdin internally and leaving the underlying TTY handle ref'd to the
event loop after `rl.close()`; once the wizard's last prompt resolves
Node has no other refs but still cannot exit. CI and other non-TTY
callers did not hit this because the previous cleanup pause+unref'd
stdin only when `!process.stdin.isTTY`.
This switches the shared `prompt()` cleanup to always pause+unref and
adds a matching `process.stdin.ref()` at every prompt entry — the
readline branch, the secret branch, `promptSecret()` itself, and the
four raw-mode TUI selectors in `onboard.ts` — so a sticky `unref()` from
a prior prompt cannot strand a follow-up read on a detached handle. The
same TTY-guarded cleanup pattern in `policies.ts` and the missing
pause/unref in `sandbox-config.ts:confirmYesNo` are aligned to the same
shape.
## Related Issues
Fixes #2518
## Changes
- `src/lib/credentials.ts`: drop the `if (!process.stdin.isTTY)` guard
from `prompt()` cleanup so pause+unref runs on every code path; hoist
`process.stdin.ref()` above the secret-vs-readline branch so both paths
re-attach stdin before the next read; make `promptSecret()`
self-contained — ref() at the top of the body and pause+unref in its own
cleanup so a direct caller (or two sequential direct calls) is safe
regardless of prior stdin state.
- `src/lib/onboard.ts`: add `process.stdin.ref()` before the
`setRawMode(true) + resume()` block in the messaging-channels selector
and in the three identical arrow-key picker patterns (sandbox-prompt,
model-prompt, policy-preset-prompt) so a sticky unref() from earlier
`prompt()` cleanup does not leave the raw-mode read attached to a
detached handle; add `unref()` to each cleanup so wizards that end on a
TUI selector also exit naturally.
- `src/lib/policies.ts`: drop the `if (!process.stdin.isTTY)` guards in
both preset-selection callbacks (lines 446 and 770) and add ref() at the
top of each prompt block.
- `src/lib/sandbox-config.ts`: add the matching ref() + pause/unref pair
to `confirmYesNo()`, which previously only ran `rl.close()` and would
have leaked the same stdin ref had it ever been the wizard's last
prompt.
- `test/credentials.test.ts`: source-text assertions for the new
contract — TTY guard is gone from `prompt()` cleanup, ref() precedes the
silent/secret branch in `prompt()`, `promptSecret()` is self-contained,
and the secret-path cleanup pauses+unrefs.
- `test/policies.test.ts`: source-text assertions for the same contract
on the two preset-selection prompts — TTY guard removed and a ref()
precedes each `createInterface`.
- `test/onboard.test.ts`: source-text assertion that all four raw-mode
TUI sites (one `input.ref()` alias + three `process.stdin.ref()` calls)
ref before `setRawMode(true)` and unref after `setRawMode(false)`, so
any one of them stays safe to be the wizard's last prompt.
## Type of Change
- [x] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)
## Verification
- [x] `npx prek run --all-files` passes
- [x] `npm test` passes
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [ ] Docs updated for user-facing behavior changes
- [ ] `make docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)
## AI Disclosure
- [x] AI-assisted — tool: Claude Code, Codex
---
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved reliability of sequential interactive prompts (credentials,
onboarding, policies, and configuration flows) so prompts no longer hang
and the process exits cleanly after the final prompt.
* **Tests**
* Added and extended tests to validate interactive prompt lifecycle and
ensure multiple sequential prompts complete without leaving lingering
handles or blocking subsequent prompts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>1 parent ea7fbba commit 771edeb
7 files changed
Lines changed: 231 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
390 | 390 | | |
391 | 391 | | |
392 | 392 | | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
393 | 400 | | |
394 | 401 | | |
395 | 402 | | |
| |||
399 | 406 | | |
400 | 407 | | |
401 | 408 | | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
402 | 412 | | |
403 | 413 | | |
404 | 414 | | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
405 | 418 | | |
406 | 419 | | |
407 | 420 | | |
| |||
480 | 493 | | |
481 | 494 | | |
482 | 495 | | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
483 | 504 | | |
484 | 505 | | |
485 | 506 | | |
| |||
499 | 520 | | |
500 | 521 | | |
501 | 522 | | |
502 | | - | |
503 | | - | |
504 | | - | |
505 | | - | |
506 | | - | |
507 | | - | |
508 | | - | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
509 | 532 | | |
510 | 533 | | |
511 | 534 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5316 | 5316 | | |
5317 | 5317 | | |
5318 | 5318 | | |
| 5319 | + | |
| 5320 | + | |
| 5321 | + | |
| 5322 | + | |
| 5323 | + | |
| 5324 | + | |
| 5325 | + | |
| 5326 | + | |
5319 | 5327 | | |
5320 | 5328 | | |
5321 | 5329 | | |
| |||
5353 | 5361 | | |
5354 | 5362 | | |
5355 | 5363 | | |
| 5364 | + | |
| 5365 | + | |
| 5366 | + | |
| 5367 | + | |
| 5368 | + | |
| 5369 | + | |
5356 | 5370 | | |
5357 | 5371 | | |
5358 | 5372 | | |
| |||
5766 | 5780 | | |
5767 | 5781 | | |
5768 | 5782 | | |
| 5783 | + | |
| 5784 | + | |
| 5785 | + | |
| 5786 | + | |
5769 | 5787 | | |
5770 | 5788 | | |
5771 | 5789 | | |
| |||
5774 | 5792 | | |
5775 | 5793 | | |
5776 | 5794 | | |
| 5795 | + | |
| 5796 | + | |
| 5797 | + | |
5777 | 5798 | | |
5778 | 5799 | | |
5779 | 5800 | | |
| |||
5950 | 5971 | | |
5951 | 5972 | | |
5952 | 5973 | | |
| 5974 | + | |
| 5975 | + | |
| 5976 | + | |
| 5977 | + | |
5953 | 5978 | | |
5954 | 5979 | | |
5955 | 5980 | | |
| |||
5958 | 5983 | | |
5959 | 5984 | | |
5960 | 5985 | | |
| 5986 | + | |
| 5987 | + | |
| 5988 | + | |
5961 | 5989 | | |
5962 | 5990 | | |
5963 | 5991 | | |
| |||
6093 | 6121 | | |
6094 | 6122 | | |
6095 | 6123 | | |
| 6124 | + | |
| 6125 | + | |
| 6126 | + | |
| 6127 | + | |
6096 | 6128 | | |
6097 | 6129 | | |
6098 | 6130 | | |
| |||
6101 | 6133 | | |
6102 | 6134 | | |
6103 | 6135 | | |
| 6136 | + | |
| 6137 | + | |
| 6138 | + | |
6104 | 6139 | | |
6105 | 6140 | | |
6106 | 6141 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
440 | 440 | | |
441 | 441 | | |
442 | 442 | | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
443 | 446 | | |
444 | 447 | | |
445 | 448 | | |
446 | | - | |
447 | | - | |
448 | | - | |
449 | | - | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
450 | 453 | | |
451 | 454 | | |
452 | 455 | | |
| |||
764 | 767 | | |
765 | 768 | | |
766 | 769 | | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
767 | 773 | | |
768 | 774 | | |
769 | 775 | | |
770 | | - | |
771 | | - | |
772 | | - | |
773 | | - | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
774 | 780 | | |
775 | 781 | | |
776 | 782 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
752 | 752 | | |
753 | 753 | | |
754 | 754 | | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
755 | 758 | | |
756 | 759 | | |
757 | 760 | | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
758 | 765 | | |
759 | 766 | | |
760 | 767 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
504 | 504 | | |
505 | 505 | | |
506 | 506 | | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
507 | 582 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2648 | 2648 | | |
2649 | 2649 | | |
2650 | 2650 | | |
| 2651 | + | |
| 2652 | + | |
| 2653 | + | |
| 2654 | + | |
| 2655 | + | |
| 2656 | + | |
| 2657 | + | |
| 2658 | + | |
| 2659 | + | |
| 2660 | + | |
| 2661 | + | |
| 2662 | + | |
| 2663 | + | |
| 2664 | + | |
| 2665 | + | |
| 2666 | + | |
| 2667 | + | |
| 2668 | + | |
| 2669 | + | |
| 2670 | + | |
| 2671 | + | |
| 2672 | + | |
| 2673 | + | |
| 2674 | + | |
| 2675 | + | |
| 2676 | + | |
| 2677 | + | |
| 2678 | + | |
| 2679 | + | |
| 2680 | + | |
| 2681 | + | |
| 2682 | + | |
| 2683 | + | |
| 2684 | + | |
| 2685 | + | |
| 2686 | + | |
| 2687 | + | |
| 2688 | + | |
2651 | 2689 | | |
2652 | 2690 | | |
2653 | 2691 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1498 | 1498 | | |
1499 | 1499 | | |
1500 | 1500 | | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
| 1509 | + | |
| 1510 | + | |
| 1511 | + | |
| 1512 | + | |
| 1513 | + | |
| 1514 | + | |
| 1515 | + | |
| 1516 | + | |
| 1517 | + | |
| 1518 | + | |
| 1519 | + | |
| 1520 | + | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
1501 | 1533 | | |
0 commit comments