mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-27 11:22:03 +00:00
fix(cli): honor non-interactive context in prompt_yes_no
The dashboard/desktop spawn gateway actions with stdin=DEVNULL and
HERMES_NONINTERACTIVE=1 (hermes_cli/web_server.py), but prompt_yes_no
ignored that contract and called sys.exit(1) on the resulting EOFError.
On Windows, `gateway start` asks "Install it now so the gateway starts on
login? [Y/n]" when the scheduled task / startup entry is not yet
installed. Spawned from the desktop app there is no stdin to answer it, so
every desktop-triggered gateway restart aborted at that prompt and the
gateway never started ("Gateway service is not installed").
Fall back to the prompt's default when HERMES_NONINTERACTIVE is set, and
treat a bare EOFError as "accept default" rather than exiting. This lets
the Windows start path proceed unattended (Startup-folder fallback + direct
spawn) while interactive TTY usage is unchanged. Ctrl+C still exits.
This commit is contained in:
parent
8446c15706
commit
33926eb315
1 changed files with 35 additions and 2 deletions
|
|
@ -272,8 +272,35 @@ def prompt_choice(question: str, choices: list, default: int = 0, description: s
|
|||
sys.exit(1)
|
||||
|
||||
|
||||
def is_noninteractive() -> bool:
|
||||
"""True when no human is available to answer a prompt.
|
||||
|
||||
The dashboard/desktop spawn CLI actions with ``stdin=DEVNULL`` and
|
||||
``HERMES_NONINTERACTIVE=1`` (see ``hermes_cli/web_server.py``). In that
|
||||
context an ``input()`` raises ``EOFError`` immediately, so a prompt that
|
||||
aborts on EOF kills the spawned action — this is what made the desktop
|
||||
"restart gateway" fail when the Windows gateway service was not yet
|
||||
installed (the start path asks "Install it now?" with no one to answer).
|
||||
Honour the explicit env flag here so callers fall back to their default.
|
||||
"""
|
||||
return os.environ.get("HERMES_NONINTERACTIVE", "").strip().lower() in {
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
}
|
||||
|
||||
|
||||
def prompt_yes_no(question: str, default: bool = True) -> bool:
|
||||
"""Prompt for yes/no. Ctrl+C exits, empty input returns default."""
|
||||
"""Prompt for yes/no. Ctrl+C exits, empty input returns default.
|
||||
|
||||
Non-interactive callers (``HERMES_NONINTERACTIVE=1`` or a closed/redirected
|
||||
stdin) have no one to answer, so fall back to ``default`` instead of
|
||||
aborting the whole process.
|
||||
"""
|
||||
if is_noninteractive():
|
||||
return default
|
||||
|
||||
default_str = "Y/n" if default else "y/N"
|
||||
|
||||
while True:
|
||||
|
|
@ -283,9 +310,15 @@ def prompt_yes_no(question: str, default: bool = True) -> bool:
|
|||
.strip()
|
||||
.lower()
|
||||
)
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
sys.exit(1)
|
||||
except EOFError:
|
||||
# No stdin to read (closed/redirected, e.g. a spawned action with
|
||||
# stdin=DEVNULL). Accept the default rather than exit so the caller
|
||||
# can proceed unattended instead of failing the whole command.
|
||||
print()
|
||||
return default
|
||||
|
||||
if not value:
|
||||
return default
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue