Skip to content

fix(install): require an interactive terminal for --station-deepseek (#7014) - #7018

Closed
yanyunl1991 wants to merge 5 commits into
mainfrom
fix/7014-station-deepseek-requires-tty
Closed

fix(install): require an interactive terminal for --station-deepseek (#7014)#7018
yanyunl1991 wants to merge 5 commits into
mainfrom
fix/7014-station-deepseek-requires-tty

Conversation

@yanyunl1991

@yanyunl1991 yanyunl1991 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

--station-deepseek selects the interactive DGX Station express prompt. On a host with no TTY, maybe_offer_express_install logs Skipping express prompt (no TTY) and continues — so the flag is silently ignored and a different configuration is installed, with no error.

This surfaces once #7008 stops notice acceptance from forcing non-interactive mode, which lets NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 … --station-deepseek reach the express step instead of aborting earlier. (Plain --station-deepseek with no TTY and no notice acceptance errors at the license prompt first; the silent-skip is the accept-notice + no-TTY corner.)

Fix

Add a TTY-availability check to validate_station_deepseek_override, so --station-deepseek fails fast at preflight (before Docker / build deps) with a clear, actionable message — mirroring the existing --non-interactive rejection. The check is last in the validator, so a genuine provider/model conflict is still reported first. A curl | bash pipe where /dev/tty is available (the normal interactive case) still proceeds.

[ERROR] --station-deepseek selects the DGX Station express prompt, which needs an interactive terminal. Re-run from a terminal (for a curl|bash pipe, /dev/tty must be available), or omit --station-deepseek and configure the install non-interactively.

Verification (DGX-Station-mocked aarch64)

Via validate_station_deepseek_override and full main:

  • No TTY (setsid, stdin /dev/null) + --station-deepseek → errors before any host mutation (was: silent skip, express ignored).
  • Precedence preserved: --non-interactive → its own error first; conflicting NEMOCLAW_VLLM_MODEL → model error first.
  • Real pty + --station-deepseek → validate passes (interactive express still works).

New test uses setsid for a deterministic no-TTY session; the existing --station-deepseek-with-TTY tests (run under a pty) still pass.

Stacking

Builds on #7010 (#7008 / #7009); this PR targets that branch and shows only its own diff. GitHub will retarget it to main once #7010 merges. It also adjusts the #7008 test to stop before validate (so it no longer needs a TTY to assert the arg-parse behavior).

Fixes #7014.

Signed-off-by: Yanyun Liao yanyunl@nvidia.com

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved installation validation for --station-deepseek when no interactive terminal is available.
    • Installations now fail with a clear error instead of silently skipping required interactive setup.
    • Validation occurs before any system changes are made.

…--station-deepseek (#7008, #7009)

#7008: NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=1 (and --yes-i-accept-third-party-software)
inferred non-interactive mode, which then made --station-deepseek reject its own
required interactive DGX Station express prompt, so the documented curl-pipe install
aborted immediately. The two signals are orthogonal -- one accepts a licence, the
other opts into an interactive express flow. Skip the inference when --station-deepseek
is set so the express prompt is reached; the inference is preserved for every other
install (its #4414/#2671 partial-install protection is unchanged).

#7009: the conflict error printed the same message regardless of what put the run in
non-interactive mode. main() exports NON_INTERACTIVE into NEMOCLAW_NON_INTERACTIVE, so
the origin cannot be recovered at error time -- record it during flag parsing and name
it in the message ("the --non-interactive flag" or "NEMOCLAW_NON_INTERACTIVE=1").

Verified on a DGX-Station-mocked aarch64 host: the reported command now proceeds past
the express preflight without inferring non-interactive; explicit --non-interactive and
NEMOCLAW_NON_INTERACTIVE=1 still conflict and now name their trigger; notice acceptance
without --station-deepseek still implies non-interactive.

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
shfmt (-i 2 -ci -bn) puts the binary operator at the start of the continuation
line. No behavior change.

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
- Drop the now-dead NON_INTERACTIVE_SOURCE assignment in the notice-acceptance
  block: with the #7008 guard it only runs for non-station installs, and its
  only reader (validate_station_deepseek_override) is station-only, so the value
  is never read.
- Append the "(triggered by: ...)" clause only when the origin is known, so
  direct callers that set NON_INTERACTIVE without going through flag parsing get
  a clean message instead of a guessed attribution.

No behavior change for real installs: in main(), NON_INTERACTIVE always has a
recorded source when it is set.

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
…7014)

--station-deepseek selects the interactive DGX Station express prompt. With no
TTY, maybe_offer_express_install logged "Skipping express prompt (no TTY)" and
continued, silently ignoring the flag and installing a different configuration.
This surfaces once #7008 stops notice acceptance from forcing non-interactive,
which lets accept-notice + --station-deepseek reach the express step.

Add a TTY-availability check to validate_station_deepseek_override so the flag
fails fast at preflight (before Docker / build deps) with a clear message,
mirroring the existing --non-interactive rejection. Checked last so a genuine
provider/model conflict is still reported first. A curl|bash pipe with /dev/tty
available (the normal interactive case) still proceeds.

Verified on a DGX-Station-mocked aarch64 host: no-TTY --station-deepseek now
errors before any host mutation; --non-interactive and conflicting-model errors
still take precedence; a real pty proceeds.

Stacked on #7010 (#7008/#7009), which this builds on.

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The installer now detects whether an interactive terminal is available for --station-deepseek and fails early when it is not. A regression test verifies the error and confirms no host mutations occur.

Changes

DGX Station DeepSeek terminal validation

Layer / File(s) Summary
Add terminal availability validation
scripts/install.sh
Adds TTY detection and rejects --station-deepseek when the interactive express prompt cannot access a terminal.
Validate no-TTY failure behavior
test/install-express-prompt.test.ts
Runs the installer without a controlling TTY, checks the terminal error, and verifies preflight causes no host mutations.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: area: install, platform: dgx-station

Suggested reviewers: ericksoa, sandl99

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly states the main change: requiring an interactive terminal for --station-deepseek.
Linked Issues check ✅ Passed The changes add a TTY preflight failure for --station-deepseek and test the no-TTY path, matching #7014.
Out of Scope Changes check ✅ Passed The only code and test changes directly support the TTY requirement, with no unrelated features added.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/7014-station-deepseek-requires-tty

Comment @coderabbitai help to get the list of available commands.

@github-code-quality

github-code-quality Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the main branch.

TypeScript / code-coverage/cli

The overall coverage in the fix/7014-station-dee... branch remains at 80%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main 41a5885 fix/7014-station-dee... 93de89d +/-
src/lib/onboard...box-prebuild.ts 88% 69% -19%
src/lib/domain/.../connect-env.ts 97% 89% -8%
src/lib/state/registry.ts 86% 83% -3%
src/lib/messagi...flow-planner.ts 93% 93% 0%
src/lib/actions...eway-restart.ts 90% 93% +3%
src/lib/onboard...u-patch-mode.ts 90% 93% +3%
src/lib/onboard...host-anchors.ts 90% 94% +4%
src/lib/credentials/store.ts 59% 64% +5%
src/lib/inferen...er-lifecycle.ts 65% 71% +6%
src/lib/core/pr...mpt-activity.ts 67% 92% +25%

Updated July 16, 2026 20:09 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / high confidence
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions
Status: No actionable findings remain in the canonical review ledger.

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings match; normalized E2E selections differ; severity counts match.

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: cloud-onboard

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

Base automatically changed from fix/7008-7009-station-deepseek-accept3p to main July 16, 2026 17:56
@apurvvkumaria apurvvkumaria added bug-fix PR fixes a bug or regression v0.0.85 labels Jul 16, 2026
@apurvvkumaria apurvvkumaria self-assigned this Jul 16, 2026
Signed-off-by: Carlos Villela <cvillela@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/install-express-prompt.test.ts (1)

408-447: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Clean up the temporary directory on test failure.

fs.rmSync runs only after all assertions succeed, so a failed assertion or spawnSync exception leaks the temporary directory. Move cleanup into a finally block or the test suite’s cleanup hook.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/install-express-prompt.test.ts` around lines 408 - 447, Update the
temporary-directory test around the spawnSync and assertions so cleanup always
runs, including assertion failures and spawnSync exceptions. Move fs.rmSync for
tmp into a finally block or the suite’s cleanup hook while preserving the
existing test behavior and assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/install-express-prompt.test.ts`:
- Around line 408-447: Update the temporary-directory test around the spawnSync
and assertions so cleanup always runs, including assertion failures and
spawnSync exceptions. Move fs.rmSync for tmp into a finally block or the suite’s
cleanup hook while preserving the existing test behavior and assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d8eea07e-aa9e-4030-bbe9-43a561d47eb8

📥 Commits

Reviewing files that changed from the base of the PR and between 41a5885 and 93de89d.

📒 Files selected for processing (2)
  • scripts/install.sh
  • test/install-express-prompt.test.ts

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Superseded by #7045, a clean current-main replacement that preserves Yanyun Liao's original authorship and DCO credit, retains the validated fail-fast fix, makes the no-TTY regression portable, and includes the required user-facing documentation. Closing this conflicted duplicate so review and CI continue on one compliant branch.

apurvvkumaria added a commit that referenced this pull request Jul 17, 2026
<!-- markdownlint-disable MD041 -->
## Summary
Require `--station-deepseek` to have a readable interactive terminal so
the installer fails before host mutation instead of silently selecting a
different configuration. This is a clean current-main replacement for
#7018 that preserves Yanyun Liao's original implementation and
contributor credit.

## Related Issue
Fixes #7014

## Changes
- Validate stdin or `/dev/tty` during the explicit Station DeepSeek
preflight, before Docker or build-dependency setup.
- Add a cross-platform no-controlling-terminal regression that proves
the flag fails without host mutation while normal PTY and conflict paths
remain covered.
- Document the terminal requirement, the `curl | bash` behavior, and the
equivalent headless managed-vLLM configuration in installer help,
quickstart, vLLM setup, and generated platform support.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [x] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Quality Gates
<!-- Check one tests line and one docs line. Check other lines when
applicable. Add every requested justification or approval reference. -->
- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: Independent maintainer
review found no security finding. The local terminal probe is
fail-closed, uses the existing installer TTY boundary, and the
regression proves failure occurs before Docker or build-dependency
mutation.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification
<!-- Check each applicable item only when supported by the requested
evidence. Run targeted tests once per relevant change set and rerun
after later edits or hook autofixes that can affect the tested behavior.
Do not rerun hook-covered checks. -->
- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — `npx vitest run --project
installer-integration test/install-express-prompt.test.ts` (26 passed, 1
skipped); installer help rendering and platform-doc sync also passed.
- [x] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — `npm run check:diff` passed against
current `origin/main`.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) — build
passed with 0 errors; Fern reported two pre-existing hidden/default
warnings.
- [x] 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)
— not applicable; no new page was added.

---
<!-- DCO sign-off is required in this PR description, and every commit
must appear as Verified in GitHub. Run: git config user.name && git
config user.email -->
Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Enforced that DGX Station `--station-deepseek` express install
requires an interactive terminal; it now fails fast with a clear error
when terminal access isn’t available.
* Installer behavior no longer proceeds when reading the interactive
prompt fails.

* **Documentation**
* Updated DGX Station setup guidance with terminal requirements,
download/model expectations, and clarified deferred express onboarding
status.
* Added/expanded headless and non-interactive installation examples
using environment variables.

* **Tests**
* Added coverage for terminal-required failure modes and prompt read
resiliency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Co-authored-by: Yanyun Liao <yanyunl@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DGX Station][Install] --station-deepseek silently skips express install when no TTY is available instead of erroring

3 participants