diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index 5edb227d95..b3df18d932 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -1822,7 +1822,7 @@ def _reconfigure_tool(config: dict): cat = TOOL_CATEGORIES.get(ts_key) reqs = TOOLSET_ENV_REQUIREMENTS.get(ts_key) if cat or reqs: - if _toolset_has_keys(ts_key, config): + if _toolset_has_keys(ts_key, config) or _toolset_enabled_for_reconfigure(ts_key, config): configurable.append((ts_key, ts_label)) if not configurable: @@ -1848,6 +1848,28 @@ def _reconfigure_tool(config: dict): save_config(config) +def _toolset_enabled_for_reconfigure(ts_key: str, config: dict) -> bool: + """Return True if a configurable toolset is enabled anywhere. + + Reconfigure must include enabled-but-unconfigured categories so users can + finish provider/API-key setup without disabling and re-enabling the toolset. + """ + for platform in PLATFORMS: + if not _toolset_allowed_for_platform(ts_key, platform): + continue + try: + enabled = _get_platform_tools( + config, + platform, + include_default_mcp_servers=False, + ) + except Exception: + continue + if ts_key in enabled: + return True + return False + + def _configure_tool_category_for_reconfig(ts_key: str, cat: dict, config: dict): """Reconfigure a tool category - provider selection + API key update.""" icon = cat.get("icon", "") diff --git a/tests/hermes_cli/test_tools_config.py b/tests/hermes_cli/test_tools_config.py index d5b8aec3b7..abe211f4fb 100644 --- a/tests/hermes_cli/test_tools_config.py +++ b/tests/hermes_cli/test_tools_config.py @@ -8,6 +8,7 @@ from hermes_cli.tools_config import ( _configure_provider, _get_platform_tools, _platform_toolset_summary, + _reconfigure_tool, _save_platform_tools, _toolset_has_keys, CONFIGURABLE_TOOLSETS, @@ -468,6 +469,33 @@ def test_local_browser_provider_is_saved_explicitly(monkeypatch): assert config["browser"]["cloud_provider"] == "local" +def test_reconfigure_lists_enabled_web_without_existing_provider_config(monkeypatch): + config = {"platform_toolsets": {"cli": ["web"]}} + seen = {} + configured = [] + + monkeypatch.setattr( + "hermes_cli.tools_config._toolset_has_keys", + lambda ts_key, config=None: False, + ) + + def fake_prompt_choice(question, choices, default=0): + seen["choices"] = choices + return 0 + + monkeypatch.setattr("hermes_cli.tools_config._prompt_choice", fake_prompt_choice) + monkeypatch.setattr( + "hermes_cli.tools_config._configure_tool_category_for_reconfig", + lambda ts_key, cat, config: configured.append(ts_key), + ) + monkeypatch.setattr("hermes_cli.tools_config.save_config", lambda config: None) + + _reconfigure_tool(config) + + assert any("Web Search" in choice for choice in seen["choices"]) + assert configured == ["web"] + + def test_first_install_nous_auto_configures_managed_defaults(monkeypatch): monkeypatch.setattr("hermes_cli.tools_config.managed_nous_tools_enabled", lambda: True) monkeypatch.setattr("hermes_cli.nous_subscription.managed_nous_tools_enabled", lambda: True)