From a130aa81657d637ac3ef19c49255a859eee79964 Mon Sep 17 00:00:00 2001 From: teknium1 Date: Sun, 8 Mar 2026 21:59:39 -0700 Subject: [PATCH] fix: first-time setup skips API key prompts + install.sh sudo on WSL Two issues fixed: 1. (Critical) hermes setup tools / hermes tools: On first-time setup, the tool checklist showed all tools as pre-selected (from the default hermes-cli toolset), but after confirming the selection, NO API key prompts appeared. This is because the code only prompted for 'newly added' tools (added = new_enabled - current_enabled), but since all tools were already in the default set, 'added' was always empty. Fix: Detect first-time configuration (no platform_toolsets entry in config) and check ALL enabled tools for missing API keys, not just newly added ones. Returning users still only get prompted for newly added tools (preserving skip behavior). 2. install.sh: When run via curl|bash on WSL2/Ubuntu, ripgrep and ffmpeg install was silently skipped with a confusing 'Non-interactive mode' message. The script already uses /dev/tty for the setup wizard, but the system package section didn't. Fix: Try reading from /dev/tty when available (same pattern as the build-tools section and setup wizard). Only truly skip when no terminal is available at all (Docker build, CI). --- hermes_cli/tools_config.py | 33 ++++++++++++++++++++++++++------- scripts/install.sh | 18 ++++++++++++++++-- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index 7fe88691..7f168042 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -882,7 +882,10 @@ def tools_command(args=None): # Show checklist new_enabled = _prompt_toolset_checklist(pinfo["label"], current_enabled) - if new_enabled != current_enabled: + # Detect first-time configuration (no saved toolsets for this platform yet) + is_first_config = pkey not in config.get("platform_toolsets", {}) + + if new_enabled != current_enabled or is_first_config: added = new_enabled - current_enabled removed = current_enabled - new_enabled @@ -895,12 +898,28 @@ def tools_command(args=None): label = next((l for k, l, _ in CONFIGURABLE_TOOLSETS if k == ts), ts) print(color(f" - {label}", Colors.RED)) - # Configure newly enabled toolsets that need API keys - if added: - for ts_key in sorted(added): - if TOOL_CATEGORIES.get(ts_key) or TOOLSET_ENV_REQUIREMENTS.get(ts_key): - if not _toolset_has_keys(ts_key): - _configure_toolset(ts_key, config) + # Determine which tools need API key configuration. + # On first-time setup, check ALL enabled tools (the defaults + # include everything, so "added" would be empty and no API key + # prompts would ever appear). For returning users, only + # prompt for newly added tools. + tools_to_configure = new_enabled if is_first_config else added + + unconfigured = [ + ts_key for ts_key in sorted(tools_to_configure) + if (TOOL_CATEGORIES.get(ts_key) or TOOLSET_ENV_REQUIREMENTS.get(ts_key)) + and not _toolset_has_keys(ts_key) + ] + + if unconfigured: + print() + print(color(f" {len(unconfigured)} tool(s) need API keys to be configured:", Colors.YELLOW)) + for ts_key in unconfigured: + label = next((l for k, l, _ in CONFIGURABLE_TOOLSETS if k == ts_key), ts_key) + print(color(f" • {label}", Colors.DIM)) + print() + for ts_key in unconfigured: + _configure_toolset(ts_key, config) _save_platform_tools(config, pkey, new_enabled) save_config(config) diff --git a/scripts/install.sh b/scripts/install.sh index b4a9716b..7b87237b 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -492,9 +492,23 @@ install_system_packages() { return 0 fi fi + elif [ -e /dev/tty ]; then + # Non-interactive (e.g. curl | bash) but a terminal is available. + # Read the prompt from /dev/tty (same approach the setup wizard uses). + echo "" + log_info "Installing ${description} requires sudo." + read -p "Install? [Y/n] " -n 1 -r < /dev/tty + echo + if [[ $REPLY =~ ^[Yy]$ ]] || [[ -z $REPLY ]]; then + if sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a $install_cmd < /dev/tty; then + [ "$need_ripgrep" = true ] && HAS_RIPGREP=true && log_success "ripgrep installed" + [ "$need_ffmpeg" = true ] && HAS_FFMPEG=true && log_success "ffmpeg installed" + return 0 + fi + fi else - log_warn "Non-interactive mode: cannot prompt for sudo password" - log_info "Install missing packages manually: sudo $install_cmd" + log_warn "Non-interactive mode and no terminal available — cannot install system packages" + log_info "Install manually after setup completes: sudo $install_cmd" fi fi fi