From 49167ffe0539d22ffe1bdb15f14bb7e11c13dd4b Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Sat, 18 Jul 2026 15:16:18 -0700 Subject: [PATCH] fix(tools): apply missing-provider setup pass to per-platform configure flow too Sibling-site fix for the flaw addressed in the global 'Configure all platforms' flow: the per-platform checklist also returned to the menu without opening provider setup when a selected toolset was already enabled but lacked provider configuration. Adds a matching regression test. --- hermes_cli/tools_config.py | 34 ++++++++++++++++++-- tests/hermes_cli/test_tools_config.py | 46 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index a9612a2dbedb..54cce4aa4f38 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -4347,7 +4347,34 @@ def tools_command(args=None, first_install: bool = False, config: dict = None): force_fresh=True, ) - if new_enabled != current_enabled: + # Selected toolsets still missing provider/API-key setup must open + # configuration even when the checklist selection itself didn't + # change (e.g. Web Search already enabled but web.backend missing). + # Mirrors the "Configure all platforms (global)" flow above. + selected_to_configure = [ + ts_key for ts_key in sorted(new_enabled) + if (TOOL_CATEGORIES.get(ts_key) or TOOLSET_ENV_REQUIREMENTS.get(ts_key)) + and _toolset_needs_configuration_prompt( + ts_key, + config, + force_fresh=True, + ) + ] + + selected_to_configure_set = set(selected_to_configure) + + if selected_to_configure: + print() + print(color(f" Configuring {len(selected_to_configure)} selected tool(s):", Colors.YELLOW)) + for ts_key in selected_to_configure: + label = next((l for k, l, _ in _get_effective_configurable_toolsets() if k == ts_key), ts_key) + print(color(f" • {label}", Colors.DIM)) + print(color(" You can skip any tool you don't need right now.", Colors.DIM)) + print() + for ts_key in selected_to_configure: + _configure_toolset(ts_key, config) + + if new_enabled != current_enabled or selected_to_configure: # Scope the printed diff to the checklist's universe (see # _checklist_toolset_keys) so non-configurable toolsets like # ``kanban`` aren't reported as added/removed. @@ -4364,8 +4391,9 @@ def tools_command(args=None, first_install: bool = False, config: dict = None): label = next((l for k, l, _ in _get_effective_configurable_toolsets() if k == ts), ts) print(color(f" - {label}", Colors.RED)) - # Configure newly enabled toolsets that need API keys - for ts_key in sorted(added): + # Configure newly enabled toolsets that need API keys, skipping + # any already handled by the selected-tool pass above. + for ts_key in sorted(added - selected_to_configure_set): if (TOOL_CATEGORIES.get(ts_key) or TOOLSET_ENV_REQUIREMENTS.get(ts_key)): if _toolset_needs_configuration_prompt( ts_key, diff --git a/tests/hermes_cli/test_tools_config.py b/tests/hermes_cli/test_tools_config.py index 8074581cc537..09a501f33d30 100644 --- a/tests/hermes_cli/test_tools_config.py +++ b/tests/hermes_cli/test_tools_config.py @@ -939,6 +939,52 @@ def test_configure_all_platforms_configures_selected_tool_missing_provider(monke assert config["platform_toolsets"]["telegram"] == ["web"] +def test_configure_single_platform_configures_selected_tool_missing_provider(monkeypatch): + """Regression (per-platform sibling of the global flow): `hermes tools` → + Configure → Web Search must enter provider/API-key setup even + when Web was already enabled on that platform, so the checklist selection + itself has no diff. + """ + config = {"platform_toolsets": {"cli": ["web"]}} + configured = [] + + monkeypatch.setattr( + "hermes_cli.tools_config._get_enabled_platforms", + lambda: ["cli"], + ) + + menu_calls = 0 + + def choose_by_label(_question, choices, default=0): + nonlocal menu_calls + menu_calls += 1 + wanted = "CLI" if menu_calls == 1 else "Done" + for idx, choice in enumerate(choices): + if wanted in choice: + return idx + return default + + monkeypatch.setattr("hermes_cli.tools_config._prompt_choice", choose_by_label) + monkeypatch.setattr( + "hermes_cli.tools_config._prompt_toolset_checklist", + lambda *args, **kwargs: {"web"}, + ) + monkeypatch.setattr( + "hermes_cli.tools_config._toolset_needs_configuration_prompt", + lambda ts_key, config, **kwargs: ts_key == "web", + ) + monkeypatch.setattr( + "hermes_cli.tools_config._configure_toolset", + lambda ts_key, config, **kwargs: configured.append(ts_key), + ) + monkeypatch.setattr("hermes_cli.tools_config.save_config", lambda config: None) + + tools_command(first_install=False, config=config) + + assert configured == ["web"] + assert config["platform_toolsets"]["cli"] == ["web"] + + def test_first_install_nous_auto_configures_managed_defaults(monkeypatch): monkeypatch.setattr("hermes_cli.nous_subscription.managed_nous_tools_enabled", lambda: True) config = {