diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index 45255e670e96..a9612a2dbedb 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -4266,7 +4266,30 @@ def tools_command(args=None, first_install: bool = False, config: dict = None): all_current, force_fresh=True, ) - if new_enabled != all_current: + 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 != all_current or selected_to_configure: for pk in platform_keys: prev = _get_platform_tools(config, pk, include_default_mcp_servers=False) # Scope the printed diff to the checklist's universe (see @@ -4284,8 +4307,13 @@ def tools_command(args=None, first_install: bool = False, config: dict = None): for ts in sorted(removed): label = next((l for k, l, _ in _get_effective_configurable_toolsets() if k == ts), ts) print(color(f" - {label}", Colors.RED)) - # Configure API keys for newly enabled tools - for ts_key in sorted(added): + # Configure API keys for newly enabled tools not already + # handled by the global selected-tool pass above. This + # preserves the old per-platform enable flow but avoids + # dropping users back to the main menu when a selected tool + # was already enabled globally and only lacked provider + # configuration. + 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 d640061335fa..8074581cc537 100644 --- a/tests/hermes_cli/test_tools_config.py +++ b/tests/hermes_cli/test_tools_config.py @@ -893,6 +893,52 @@ def test_reconfigure_lists_enabled_web_without_existing_provider_config(monkeypa assert configured == ["web"] +def test_configure_all_platforms_configures_selected_tool_missing_provider(monkeypatch): + """Regression: `hermes tools` → Configure all platforms → Web Search + must enter provider/API-key setup even when Web was already enabled on all + configured platforms, so the checklist selection itself has no diff. + """ + config = {"platform_toolsets": {"cli": ["web"], "telegram": ["web"]}} + configured = [] + + monkeypatch.setattr( + "hermes_cli.tools_config._get_enabled_platforms", + lambda: ["cli", "telegram"], + ) + + menu_calls = 0 + + def choose_by_label(_question, choices, default=0): + nonlocal menu_calls + menu_calls += 1 + wanted = "Configure all platforms" 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"] + assert config["platform_toolsets"]["telegram"] == ["web"] + + def test_first_install_nous_auto_configures_managed_defaults(monkeypatch): monkeypatch.setattr("hermes_cli.nous_subscription.managed_nous_tools_enabled", lambda: True) config = {