"""Tests for /tools slash command handler in the interactive CLI.""" from unittest.mock import MagicMock, patch, call from cli import HermesCLI def _make_cli(enabled_toolsets=None): """Build a minimal HermesCLI stub without running __init__.""" cli_obj = HermesCLI.__new__(HermesCLI) cli_obj.enabled_toolsets = set(enabled_toolsets or ["web", "memory"]) cli_obj._command_running = False cli_obj.console = MagicMock() return cli_obj # ── /tools (no subcommand) ────────────────────────────────────────────────── class TestToolsSlashNoSubcommand: def test_bare_tools_shows_tool_list(self): cli_obj = _make_cli() with patch.object(cli_obj, "show_tools") as mock_show: cli_obj._handle_tools_command("/tools") mock_show.assert_called_once() def test_unknown_subcommand_falls_back_to_show_tools(self): cli_obj = _make_cli() with patch.object(cli_obj, "show_tools") as mock_show: cli_obj._handle_tools_command("/tools foobar") mock_show.assert_called_once() # ── /tools list ───────────────────────────────────────────────────────────── class TestToolsSlashList: def test_list_calls_backend(self, capsys): cli_obj = _make_cli() with patch("hermes_cli.tools_config.load_config", return_value={"platform_toolsets": {"cli": ["web"]}}), \ patch("hermes_cli.tools_config.save_config"): cli_obj._handle_tools_command("/tools list") out = capsys.readouterr().out assert "web" in out def test_list_does_not_modify_enabled_toolsets(self): """List is read-only — self.enabled_toolsets must not change.""" cli_obj = _make_cli(["web", "memory"]) with patch("hermes_cli.tools_config.load_config", return_value={"platform_toolsets": {"cli": ["web"]}}): cli_obj._handle_tools_command("/tools list") assert cli_obj.enabled_toolsets == {"web", "memory"} # ── /tools disable (session reset) ────────────────────────────────────────── class TestToolsSlashDisableWithReset: def test_disable_confirms_then_resets_session(self): cli_obj = _make_cli(["web", "memory"]) with patch("hermes_cli.tools_config.load_config", return_value={"platform_toolsets": {"cli": ["web", "memory"]}}), \ patch("hermes_cli.tools_config.save_config"), \ patch("hermes_cli.tools_config._get_platform_tools", return_value={"memory"}), \ patch("hermes_cli.config.load_config", return_value={}), \ patch.object(cli_obj, "new_session") as mock_reset, \ patch("builtins.input", return_value="y"): cli_obj._handle_tools_command("/tools disable web") mock_reset.assert_called_once() assert "web" not in cli_obj.enabled_toolsets def test_disable_cancelled_does_not_reset(self): cli_obj = _make_cli(["web", "memory"]) with patch.object(cli_obj, "new_session") as mock_reset, \ patch("builtins.input", return_value="n"): cli_obj._handle_tools_command("/tools disable web") mock_reset.assert_not_called() # Toolsets unchanged assert cli_obj.enabled_toolsets == {"web", "memory"} def test_disable_eof_cancels(self): cli_obj = _make_cli(["web", "memory"]) with patch.object(cli_obj, "new_session") as mock_reset, \ patch("builtins.input", side_effect=EOFError): cli_obj._handle_tools_command("/tools disable web") mock_reset.assert_not_called() def test_disable_missing_name_prints_usage(self, capsys): cli_obj = _make_cli() cli_obj._handle_tools_command("/tools disable") out = capsys.readouterr().out assert "Usage" in out # ── /tools enable (session reset) ─────────────────────────────────────────── class TestToolsSlashEnableWithReset: def test_enable_confirms_then_resets_session(self): cli_obj = _make_cli(["memory"]) with patch("hermes_cli.tools_config.load_config", return_value={"platform_toolsets": {"cli": ["memory"]}}), \ patch("hermes_cli.tools_config.save_config"), \ patch("hermes_cli.tools_config._get_platform_tools", return_value={"memory", "web"}), \ patch("hermes_cli.config.load_config", return_value={}), \ patch.object(cli_obj, "new_session") as mock_reset, \ patch("builtins.input", return_value="y"): cli_obj._handle_tools_command("/tools enable web") mock_reset.assert_called_once() assert "web" in cli_obj.enabled_toolsets def test_enable_missing_name_prints_usage(self, capsys): cli_obj = _make_cli() cli_obj._handle_tools_command("/tools enable") out = capsys.readouterr().out assert "Usage" in out