fix(plugins): enumerate entry-point plugins in CLI discovery - #54055
fix(plugins): enumerate entry-point plugins in CLI discovery#54055Bartok9 wants to merge 1 commit into
Conversation
Duplicate of #23814 — same fix (enumerate the |
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved
Fixes CLI discovery of pip-installed entry-point plugins. The runtime PluginManager scans the hermes_agent.plugins entry-point group, but the CLI's _discover_all_plugins previously only walked directories. This caused hermes plugins list/enable to report pip-installed plugins as "not installed or bundled". The new _scan_entry_point_plugins() helper mirrors the runtime discovery path. Directory plugins take precedence on key collision, matching the loader's ordering. Comprehensive tests cover discovery, resolution, metadata extraction, and collision handling.
Reviewed by Hermes Agent
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: LGTM
Enumerates pip-installed plugins in CLI discovery via the hermes_agent.plugins entry-point group. Previously the CLI only scanned directories, so pip-installed plugins loaded at runtime but were invisible to hermes plugins list/enable.
Changes
hermes_cli/plugins_cmd.py: New_scan_entry_point_plugins()function + integration in_discover_all_plugins()tests/hermes_cli/test_plugins_cmd_entrypoint_discovery.py: 4 tests covering discovery, resolution, metadata, and collision precedence
Looks Good
- Directory plugins take precedence on key collision (mirrors loader ordering)
- Handles all importlib.metadata API variants (3.9+ dict, 3.12+ select, fallback)
- Best-effort with graceful failure (empty list on any exception)
- Tests cover end-to-end through importlib.metadata, not just the helper
(Note: prior COMMENT review from tonydwb exists; this is a new review.)
Reviewed by Hermes Agent
Regression for NousResearch#53898: hermes plugins list must include hermes_agent.plugins entry points, not only directory plugins.
2ab80b5 to
b881e27
Compare
|
Thanks for preserving regression coverage for the CLI/runtime plugin-discovery gap. Automated hermes-sweeper review found this behavior is already implemented on current
The provided duplicate discussion is consistent with this being a now-redundant regression-test-only PR. |
Closes #53898.
Root Cause
Symptom — A pip-installed plugin (a package exposing a
hermes_agent.pluginsentry point) loads fine at gateway runtime, buthermes plugins listnever shows it andhermes plugins enable <name>aborts withPlugin '<name>' is not installed or bundled.Because the CLI is what writesplugins.enabledin config.yaml — and refuses for plugins it can't see — the documented pip-install path can only be enabled by hand-editing~/.hermes/config.yaml.Root cause — The runtime
PluginManager.discover_and_loadscans thehermes_agent.pluginsentry-point group (step 4, via_scan_entry_points()), but the CLI's_discover_all_plugins()inhermes_cli/plugins_cmd.pyonly walked directories (get_bundled_plugins_dir()+~/.hermes/plugins/). It never enumerated entry points, so the CLI's view of installed plugins drifted from the loader's. Every CLI surface built on_discover_all_plugins(cmd_list, and_resolve_plugin_key→cmd_enable/cmd_disable/setup) inherited the blind spot.Evidence —
hermes_cli/plugins_cmd.py::_discover_all_plugins(dir-only) vshermes_cli/plugins.py::PluginManager._scan_entry_points(ENTRY_POINTS_GROUP = "hermes_agent.plugins"). New regression testtest_entrypoint_plugin_discovered_via_metadatamocksimportlib.metadata.entry_points()and asserts the plugin surfaces; it fails on currentmain(assert 'my-pip-plugin' in {}) and passes with the fix.Fix + why this level — Add
_scan_entry_point_plugins()to the CLI (mirroring the loader's_scan_entry_points, including the 3.12+.select()/ dict / iterable shapes) and have_discover_all_plugins()fold those entries in AFTER the directory scan, with directory plugins winning on key collision — matching the loader's user/bundled-over-entrypoint precedence. Fixing the single shared discovery function meanslist,enable,disable, andsetupall see entry-point plugins without touching each command. Entry-point plugins surface withsource="pip"and aNonedirectory path (they have no plugin dir), as the issue suggested.Scope / risk — Touches only
_discover_all_plugins+ one new helper inplugins_cmd.py. The entry-point scan is best-effort (any exception → empty list), so a broken/odd environment degrades to today's directory-only behavior rather than crashing the CLI. Directory plugins are unaffected (collision test proves they keep precedence).Verification
python -m pytest tests/hermes_cli/test_plugins_cmd.py tests/hermes_cli/test_plugins_cmd_category_discovery.py tests/hermes_cli/test_plugins_cmd_list.py tests/hermes_cli/test_plugins_cmd_enable_disable_nested.py tests/hermes_cli/test_plugins_cmd_entrypoint_discovery.py— 138 passedtests/hermes_cli/test_plugins_cmd_entrypoint_discovery.py(4 tests): discovery via the new helper, discovery end-to-end via mockedimportlib.metadata,_resolve_plugin_keynow resolves entry-point names (soenableworks), and directory-wins-on-collision.Real behavior proof
New tests on this branch (after fix):
The metadata-driven test on
origin/main(source reverted, test kept):