fix: add first_install flag to tools setup for reliable API key prompting
On fresh installs, the multi-level curses menu flow (platform menu → checklist → loop back → Done) was unreliable — users could end up skipping API key configuration entirely. Now the setup wizard passes first_install=True to tools_command(), which: - Skips the platform selection menu entirely - Goes straight to the tool checklist - Prompts for API keys on ALL selected tools that need them - Linear flow, no loop — impossible to accidentally skip Returning users (hermes tools / hermes setup tools) get the existing platform menu loop as before.
This commit is contained in:
parent
3045e29232
commit
167eb824cb
2 changed files with 71 additions and 38 deletions
|
|
@ -1660,14 +1660,18 @@ def setup_gateway(config: dict):
|
||||||
# Section 5: Tool Configuration (delegates to unified tools_config.py)
|
# Section 5: Tool Configuration (delegates to unified tools_config.py)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
def setup_tools(config: dict):
|
def setup_tools(config: dict, first_install: bool = False):
|
||||||
"""Configure tools — delegates to the unified tools_command() in tools_config.py.
|
"""Configure tools — delegates to the unified tools_command() in tools_config.py.
|
||||||
|
|
||||||
Both `hermes setup tools` and `hermes tools` use the same flow:
|
Both `hermes setup tools` and `hermes tools` use the same flow:
|
||||||
platform selection → toolset toggles → provider/API key configuration.
|
platform selection → toolset toggles → provider/API key configuration.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
first_install: When True, uses the simplified first-install flow
|
||||||
|
(no platform menu, prompts for all unconfigured API keys).
|
||||||
"""
|
"""
|
||||||
from hermes_cli.tools_config import tools_command
|
from hermes_cli.tools_config import tools_command
|
||||||
tools_command()
|
tools_command(first_install=first_install)
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
@ -1820,7 +1824,7 @@ def run_setup_wizard(args):
|
||||||
setup_gateway(config)
|
setup_gateway(config)
|
||||||
|
|
||||||
# Section 5: Tools
|
# Section 5: Tools
|
||||||
setup_tools(config)
|
setup_tools(config, first_install=not is_existing)
|
||||||
|
|
||||||
# Save and show summary
|
# Save and show summary
|
||||||
save_config(config)
|
save_config(config)
|
||||||
|
|
|
||||||
|
|
@ -840,8 +840,14 @@ def _reconfigure_simple_requirements(ts_key: str):
|
||||||
|
|
||||||
# ─── Main Entry Point ─────────────────────────────────────────────────────────
|
# ─── Main Entry Point ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def tools_command(args=None):
|
def tools_command(args=None, first_install: bool = False):
|
||||||
"""Entry point for `hermes tools` and `hermes setup tools`."""
|
"""Entry point for `hermes tools` and `hermes setup tools`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
first_install: When True (set by the setup wizard on fresh installs),
|
||||||
|
skip the platform menu, go straight to the CLI checklist, and
|
||||||
|
prompt for API keys on all enabled tools that need them.
|
||||||
|
"""
|
||||||
config = load_config()
|
config = load_config()
|
||||||
enabled_platforms = _get_enabled_platforms()
|
enabled_platforms = _get_enabled_platforms()
|
||||||
|
|
||||||
|
|
@ -851,6 +857,55 @@ def tools_command(args=None):
|
||||||
print(color(" Tools that need API keys will be configured when enabled.", Colors.DIM))
|
print(color(" Tools that need API keys will be configured when enabled.", Colors.DIM))
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
# ── First-time install: linear flow, no platform menu ──
|
||||||
|
if first_install:
|
||||||
|
for pkey in enabled_platforms:
|
||||||
|
pinfo = PLATFORMS[pkey]
|
||||||
|
current_enabled = _get_platform_tools(config, pkey)
|
||||||
|
|
||||||
|
# Uncheck toolsets that should be off by default
|
||||||
|
checklist_preselected = current_enabled - _DEFAULT_OFF_TOOLSETS
|
||||||
|
|
||||||
|
# Show checklist
|
||||||
|
new_enabled = _prompt_toolset_checklist(pinfo["label"], checklist_preselected)
|
||||||
|
|
||||||
|
added = new_enabled - current_enabled
|
||||||
|
removed = current_enabled - new_enabled
|
||||||
|
if added:
|
||||||
|
for ts in sorted(added):
|
||||||
|
label = next((l for k, l, _ in CONFIGURABLE_TOOLSETS if k == ts), ts)
|
||||||
|
print(color(f" + {label}", Colors.GREEN))
|
||||||
|
if removed:
|
||||||
|
for ts in sorted(removed):
|
||||||
|
label = next((l for k, l, _ in CONFIGURABLE_TOOLSETS if k == ts), ts)
|
||||||
|
print(color(f" - {label}", Colors.RED))
|
||||||
|
|
||||||
|
# Prompt for API keys on ALL selected tools that need them
|
||||||
|
unconfigured = [
|
||||||
|
ts_key for ts_key in sorted(new_enabled)
|
||||||
|
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(color(" Press Enter to skip any key you don't have yet.", Colors.DIM))
|
||||||
|
print()
|
||||||
|
for ts_key in unconfigured:
|
||||||
|
_configure_toolset(ts_key, config)
|
||||||
|
|
||||||
|
_save_platform_tools(config, pkey, new_enabled)
|
||||||
|
save_config(config)
|
||||||
|
print(color(f" ✓ Saved {pinfo['label']} tool configuration", Colors.GREEN))
|
||||||
|
print()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
# ── Returning user: platform menu loop ──
|
||||||
# Build platform choices
|
# Build platform choices
|
||||||
platform_choices = []
|
platform_choices = []
|
||||||
platform_keys = []
|
platform_keys = []
|
||||||
|
|
@ -884,19 +939,10 @@ def tools_command(args=None):
|
||||||
# Get current enabled toolsets for this platform
|
# Get current enabled toolsets for this platform
|
||||||
current_enabled = _get_platform_tools(config, pkey)
|
current_enabled = _get_platform_tools(config, pkey)
|
||||||
|
|
||||||
# Detect first-time configuration (no saved toolsets for this platform yet)
|
|
||||||
is_first_config = pkey not in config.get("platform_toolsets", {})
|
|
||||||
|
|
||||||
# For first-time users, uncheck toolsets that should be off by default
|
|
||||||
# (MoA, Home Assistant, RL Training) so they aren't enabled blindly.
|
|
||||||
checklist_preselected = current_enabled
|
|
||||||
if is_first_config:
|
|
||||||
checklist_preselected = current_enabled - _DEFAULT_OFF_TOOLSETS
|
|
||||||
|
|
||||||
# Show checklist
|
# Show checklist
|
||||||
new_enabled = _prompt_toolset_checklist(pinfo["label"], checklist_preselected)
|
new_enabled = _prompt_toolset_checklist(pinfo["label"], current_enabled)
|
||||||
|
|
||||||
if new_enabled != current_enabled or is_first_config:
|
if new_enabled != current_enabled:
|
||||||
added = new_enabled - current_enabled
|
added = new_enabled - current_enabled
|
||||||
removed = current_enabled - new_enabled
|
removed = current_enabled - new_enabled
|
||||||
|
|
||||||
|
|
@ -909,28 +955,11 @@ def tools_command(args=None):
|
||||||
label = next((l for k, l, _ in CONFIGURABLE_TOOLSETS if k == ts), ts)
|
label = next((l for k, l, _ in CONFIGURABLE_TOOLSETS if k == ts), ts)
|
||||||
print(color(f" - {label}", Colors.RED))
|
print(color(f" - {label}", Colors.RED))
|
||||||
|
|
||||||
# Determine which tools need API key configuration.
|
# Configure newly enabled toolsets that need API keys
|
||||||
# On first-time setup, check ALL enabled tools (the defaults
|
for ts_key in sorted(added):
|
||||||
# include everything, so "added" would be empty and no API key
|
if (TOOL_CATEGORIES.get(ts_key) or TOOLSET_ENV_REQUIREMENTS.get(ts_key)):
|
||||||
# prompts would ever appear). For returning users, only
|
if not _toolset_has_keys(ts_key):
|
||||||
# prompt for newly added tools.
|
_configure_toolset(ts_key, config)
|
||||||
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_platform_tools(config, pkey, new_enabled)
|
||||||
save_config(config)
|
save_config(config)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue