Skip to content

fix(plugins): enumerate entry-point plugins in CLI discovery - #54055

Closed
Bartok9 wants to merge 1 commit into
NousResearch:mainfrom
Bartok9:fix/plugins-cli-entrypoint-discovery
Closed

fix(plugins): enumerate entry-point plugins in CLI discovery#54055
Bartok9 wants to merge 1 commit into
NousResearch:mainfrom
Bartok9:fix/plugins-cli-entrypoint-discovery

Conversation

@Bartok9

@Bartok9 Bartok9 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Closes #53898.

Root Cause

Symptom — A pip-installed plugin (a package exposing a hermes_agent.plugins entry point) loads fine at gateway runtime, but hermes plugins list never shows it and hermes plugins enable <name> aborts with Plugin '<name>' is not installed or bundled. Because the CLI is what writes plugins.enabled in 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_load scans the hermes_agent.plugins entry-point group (step 4, via _scan_entry_points()), but the CLI's _discover_all_plugins() in hermes_cli/plugins_cmd.py only 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_keycmd_enable/cmd_disable/setup) inherited the blind spot.

Evidencehermes_cli/plugins_cmd.py::_discover_all_plugins (dir-only) vs hermes_cli/plugins.py::PluginManager._scan_entry_points (ENTRY_POINTS_GROUP = "hermes_agent.plugins"). New regression test test_entrypoint_plugin_discovered_via_metadata mocks importlib.metadata.entry_points() and asserts the plugin surfaces; it fails on current main (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 means list, enable, disable, and setup all see entry-point plugins without touching each command. Entry-point plugins surface with source="pip" and a None directory path (they have no plugin dir), as the issue suggested.

Scope / risk — Touches only _discover_all_plugins + one new helper in plugins_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.py138 passed
  • New file tests/hermes_cli/test_plugins_cmd_entrypoint_discovery.py (4 tests): discovery via the new helper, discovery end-to-end via mocked importlib.metadata, _resolve_plugin_key now resolves entry-point names (so enable works), and directory-wins-on-collision.

Real behavior proof

New tests on this branch (after fix):

tests/hermes_cli/test_plugins_cmd_entrypoint_discovery.py ....   [100%]
4 passed in 0.15s

The metadata-driven test on origin/main (source reverted, test kept):

E       AssertionError: assert 'my-pip-plugin' in {}
1 failed

@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have duplicate This issue or pull request already exists labels Jun 28, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #23814 — same fix (enumerate the hermes_agent.plugins entry-point group in the CLI's _discover_all_plugins() in hermes_cli/plugins_cmd.py), same file, same mechanism. #23814 is the earliest open canonical PR for this gap (fixes #23802); this PR closes #53898 which describes the identical CLI/runtime discovery divergence. Marking duplicate so a maintainer can pick one; cross-linking the shared issue thread.

@Bartok9

Bartok9 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

Acknowledged — #23814 is the earlier canonical PR for the same entry-point discovery fix. I'll defer to it. This PR was filed against #53898 (the CLI/runtime divergence); fine to close as duplicate once a maintainer confirms #23814 is the keeper.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
@Bartok9
Bartok9 force-pushed the fix/plugins-cli-entrypoint-discovery branch from 2ab80b5 to b881e27 Compare July 10, 2026 18:53
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for preserving regression coverage for the CLI/runtime plugin-discovery gap.

Automated hermes-sweeper review found this behavior is already implemented on current main:

  • hermes_cli/plugins_cmd.py:1037 adds pip entry-point plugins to _discover_all_plugins().
  • hermes_cli/plugins_cmd.py:1042 handles selectable, dict, and iterable importlib.metadata.entry_points() APIs for hermes_agent.plugins.
  • tests/hermes_cli/test_plugins_cmd_list.py:92 already covers metadata-driven entry-point discovery end-to-end.
  • This shipped in 94cdd56b8263b1f50b962907921ce970549555c7 (v2026.7.7).

The provided duplicate discussion is consistent with this being a now-redundant regression-test-only PR.

@teknium1 teknium1 closed this Jul 15, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins duplicate This issue or pull request already exists P3 Low — cosmetic, nice to have sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hermes plugins enable/list can't see pip-installed (entry-point) plugins, though the runtime loads them

4 participants