fix(plugins): only register CLI commands for the active memory provider

discover_plugin_cli_commands() now reads memory.provider from config.yaml
and only loads CLI registration for the active provider. If no memory
provider is set, no plugin CLI commands appear in the CLI.

Only one memory provider can be active at a time — at most one set of
plugin CLI commands is registered. Users who haven't configured honcho
(or any memory provider) won't see 'hermes honcho' in their help output.

Adds test for inactive provider returning empty results.
This commit is contained in:
Teknium 2026-04-05 12:21:17 -07:00 committed by Teknium
parent b074b0b13a
commit 0f813c422c
2 changed files with 120 additions and 62 deletions

View file

@ -80,8 +80,8 @@ class TestGetPluginCliCommands:
class TestMemoryPluginCliDiscovery:
def test_discovers_plugin_with_register_cli(self, tmp_path, monkeypatch):
"""A memory plugin dir with cli.py containing register_cli is discovered."""
def test_discovers_active_plugin_with_register_cli(self, tmp_path, monkeypatch):
"""Only the active memory provider's CLI commands are discovered."""
plugin_dir = tmp_path / "testplugin"
plugin_dir.mkdir()
(plugin_dir / "__init__.py").write_text("pass\n")
@ -96,29 +96,58 @@ class TestMemoryPluginCliDiscovery:
"name: testplugin\ndescription: A test plugin\n"
)
# Patch _MEMORY_PLUGINS_DIR to our tmp dir
# Also create a second plugin that should NOT be discovered
other_dir = tmp_path / "otherplugin"
other_dir.mkdir()
(other_dir / "__init__.py").write_text("pass\n")
(other_dir / "cli.py").write_text(
"def register_cli(subparser):\n"
" subparser.add_argument('--other')\n"
)
import plugins.memory as pm
original_dir = pm._MEMORY_PLUGINS_DIR
# Clear any cached module to force reimport
mod_key = "plugins.memory.testplugin.cli"
sys.modules.pop(mod_key, None)
monkeypatch.setattr(pm, "_MEMORY_PLUGINS_DIR", tmp_path)
# Set testplugin as the active provider
monkeypatch.setattr(pm, "_get_active_memory_provider", lambda: "testplugin")
try:
cmds = pm.discover_plugin_cli_commands()
finally:
monkeypatch.setattr(pm, "_MEMORY_PLUGINS_DIR", original_dir)
sys.modules.pop(mod_key, None)
# Only testplugin should be discovered, not otherplugin
assert len(cmds) == 1
assert cmds[0]["name"] == "testplugin"
assert cmds[0]["help"] == "A test plugin"
assert callable(cmds[0]["setup_fn"])
assert cmds[0]["handler_fn"].__name__ == "testplugin_command"
def test_returns_nothing_when_no_active_provider(self, tmp_path, monkeypatch):
"""No commands when memory.provider is not set in config."""
plugin_dir = tmp_path / "testplugin"
plugin_dir.mkdir()
(plugin_dir / "__init__.py").write_text("pass\n")
(plugin_dir / "cli.py").write_text(
"def register_cli(subparser):\n pass\n"
)
import plugins.memory as pm
original_dir = pm._MEMORY_PLUGINS_DIR
monkeypatch.setattr(pm, "_MEMORY_PLUGINS_DIR", tmp_path)
monkeypatch.setattr(pm, "_get_active_memory_provider", lambda: None)
try:
cmds = pm.discover_plugin_cli_commands()
finally:
monkeypatch.setattr(pm, "_MEMORY_PLUGINS_DIR", original_dir)
assert len(cmds) == 0
def test_skips_plugin_without_register_cli(self, tmp_path, monkeypatch):
"""A memory plugin with cli.py but no register_cli is skipped."""
"""An active plugin with cli.py but no register_cli returns nothing."""
plugin_dir = tmp_path / "noplugin"
plugin_dir.mkdir()
(plugin_dir / "__init__.py").write_text("pass\n")
@ -127,6 +156,7 @@ class TestMemoryPluginCliDiscovery:
import plugins.memory as pm
original_dir = pm._MEMORY_PLUGINS_DIR
monkeypatch.setattr(pm, "_MEMORY_PLUGINS_DIR", tmp_path)
monkeypatch.setattr(pm, "_get_active_memory_provider", lambda: "noplugin")
try:
cmds = pm.discover_plugin_cli_commands()
finally:
@ -136,7 +166,7 @@ class TestMemoryPluginCliDiscovery:
assert len(cmds) == 0
def test_skips_plugin_without_cli_py(self, tmp_path, monkeypatch):
"""A memory plugin dir without cli.py is skipped."""
"""An active provider without cli.py returns nothing."""
plugin_dir = tmp_path / "nocli"
plugin_dir.mkdir()
(plugin_dir / "__init__.py").write_text("pass\n")
@ -144,6 +174,7 @@ class TestMemoryPluginCliDiscovery:
import plugins.memory as pm
original_dir = pm._MEMORY_PLUGINS_DIR
monkeypatch.setattr(pm, "_MEMORY_PLUGINS_DIR", tmp_path)
monkeypatch.setattr(pm, "_get_active_memory_provider", lambda: "nocli")
try:
cmds = pm.discover_plugin_cli_commands()
finally: