Skip to content

fix(plugins): discover nested category plugins in hermes plugins list#41081

Open
annguyenNous wants to merge 1 commit into
NousResearch:mainfrom
annguyenNous:fix/plugins-list-nested-categories
Open

fix(plugins): discover nested category plugins in hermes plugins list#41081
annguyenNous wants to merge 1 commit into
NousResearch:mainfrom
annguyenNous:fix/plugins-list-nested-categories

Conversation

@annguyenNous

Copy link
Copy Markdown
Contributor

Fixes #41066

Problem

hermes plugins list only iterates immediate subdirectories of ~/.hermes/plugins/ and the bundled plugins/ directory. Category-namespaced plugins (web/tavily, image_gen/openai, browser/browser_use, etc.) are invisible to the CLI listing, even though they load correctly at runtime via PluginManager._scan_directory_level().

This means 12+ bundled plugins and any user-installed category plugins never appear in hermes plugins list.

Root Cause

Two separate code paths implement plugin discovery:

Component Function Recurses into categories?
Runtime PluginManager._scan_directory_level() Yes (depth <= 2)
CLI list _discover_all_plugins() No (flat only)

Additionally, _plugin_status() only checks the manifest name against the enabled/disabled sets, but for category plugins the config key is path-derived (e.g. web/tinyfish) while the manifest name differs (e.g. web-tinyfish).

Fix

  1. Replace flat iterdir() in _discover_all_plugins() with a recursive _scan_level() helper that mirrors PluginManager._scan_directory_level() — recurse into directories without plugin.yaml up to 2 levels deep
  2. Add path-derived key to the entry tuple (6th element) for correct config lookup
  3. Update _plugin_status() to check both manifest name and path-derived key against enabled/disabled sets
  4. Update all callers: cmd_list (table/plain/JSON), _filter_plugin_entries, dashboard_remove_user_plugin, web server dashboard endpoint

Testing

  • All existing tests in test_plugins_cmd_list.py pass (updated for new 6-element tuple)
  • Flat plugins continue to work as before
  • Category plugins now correctly discovered and displayed

_discover_all_plugins() only iterated immediate subdirectories,
missing all category-namespaced plugins (web/tavily, image_gen/openai,
browser/browser_use, etc.).

Changes:
- Replace flat iterdir() with recursive _scan_level() matching
  PluginManager._scan_directory_level (depth <= 2)
- Add path-derived `key` to entry tuple for correct config lookup
- Update _plugin_status() to check both manifest name and key
- Update all callers (cmd_list, web_server, dashboard) for 6-tuple
- Update tests with new entry format

Fixes NousResearch#41066
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins comp/cli CLI entry point, hermes_cli/, setup wizard labels Jun 7, 2026
kshitijk4poor added a commit to kshitijk4poor/hermes-agent that referenced this pull request Jun 8, 2026
…ble/disable (NousResearch#41066)

Salvage consolidating three complementary community PRs into one coherent fix:

- NousResearch#41076 (islam666): made `hermes plugins list` discover nested category
  plugins (e.g. `observability/nemo_relay`, `image_gen/openai`).
- NousResearch#41613 (mnajafian-nv): the superset — nested discovery aligned with the
  runtime loader (reuses `PluginManager._scan_directory`/`_scan_entry_points`
  so list state can't drift from what actually loads), PLUS the enable/disable
  mutation side NousResearch#41076 left flat.
- NousResearch#41081 (annguyenNous): identified the `web_server.py` dashboard plugins-hub
  caller of `_discover_all_plugins()`, which must also be updated for the new
  tuple shape + key-aware status.

This combines the best of all three and fixes the mutation-side gap that made
nested bundled plugins untoggleable:

    $ hermes plugins enable nemo_relay
    Plugin 'nemo_relay' is not installed or bundled.   # exit 1 (before)

Now `enable`/`disable`/`toggle`, the `hermes plugins list` views, the dashboard
plugins-hub endpoint, and the dashboard enable/disable helpers all resolve a
bare manifest name OR a full path-derived key to the canonical key the loader
gates on, via a single `_resolve_plugin_reference()` normalization point, and
persist that key while clearing any stale legacy bare-name alias so the two
can't drift. `_plugin_status` is key+legacy-name aware.

`_discover_all_plugins` now returns 6-tuples
`(key, legacy_name, version, description, source, dir_path)`; ALL call sites
(`cmd_list` table/plain/JSON, `_filter_plugin_entries`, `cmd_toggle`,
`dashboard_remove_user_plugin`, and `web_server._merged_plugins_hub`) and the
`test_plugins_cmd_list.py` fixtures are updated to match. Updating the
`web_server.py` caller prevents a `ValueError: too many values to unpack` crash
in the dashboard plugins-hub endpoint.

Verified e2e on the real CLI + runtime loader (isolated HERMES_HOME):
`hermes plugins enable nemo_relay` writes `observability/nemo_relay` to
config.yaml and the loader then loads it (`enabled=True, error=None`); a stale
bare-name alias is cleared on disable (no contradictory state); the dashboard
`_merged_plugins_hub()` runs and lists nested plugins by canonical key.
Full `tests/hermes_cli/test_plugins_cmd*` + web_server plugin tests green.

Closes NousResearch#41066. Supersedes NousResearch#41076, NousResearch#41081, and NousResearch#41613.

Co-authored-by: islam666 <islam666@users.noreply.github.com>
Co-authored-by: mnajafian-nv <mnajafian@nvidia.com>
Co-authored-by: annguyenNous <annguyenNous@users.noreply.github.com>
Co-authored-by: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com>
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Heads-up: the nested category plugin work landed on main via #42076 (merge commit b99c6c4). Your catch here — that web_server._merged_plugins_hub() also iterates _discover_all_plugins() and needed updating for the new tuple shape — was real; that caller would have hit a ValueError on the dashboard plugins-hub endpoint otherwise, and the fix is included. Thanks for flagging it.

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 P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(plugins): hermes plugins list does not discover nested category plugins

3 participants