Bug Description
Bundled gateway platform plugins under plugins/platforms/<name>/ are discovered with keys like teams-platform instead of the path-derived key platforms/teams.
This is inconsistent with the plugin manager's key model for namespaced plugins (image_gen/openai, web/tavily, etc.) and breaks config/UI code that uses canonical plugin keys for plugins.enabled / plugins.disabled.
Root Cause
In PluginManager.discover_and_load(), bundled top-level plugins are scanned with platforms skipped, then platform plugins are scanned separately:
bundled = self._scan_directory(
repo_plugins,
source="bundled",
skip_names={"memory", "context_engine", "platforms", "model-providers"},
)
...
bundled_platforms = self._scan_directory(
repo_plugins / "platforms", source="bundled"
)
Because the second scan starts at plugins/platforms with an empty prefix, _parse_manifest() computes:
key = f"{prefix}/{plugin_dir.name}" if prefix else name
For platform manifests whose name is e.g. teams-platform, the key becomes teams-platform instead of platforms/teams.
Steps to Reproduce
Run plugin discovery from a clean HERMES_HOME on current HEAD:
HERMES_HOME=$(mktemp -d) python - <<'PY'
from hermes_cli.plugins import get_plugin_manager, discover_plugins
pm = get_plugin_manager()
discover_plugins(force=True)
for p in sorted(pm.list_plugins(), key=lambda x: x.get('key','')):
if p.get('kind') == 'platform':
print((p.get('key'), p.get('name'), p.get('enabled'), p.get('error')))
PY
Actual Behavior
('google_chat-platform', 'google_chat-platform', True, None)
('irc-platform', 'irc-platform', True, None)
('line-platform', 'line-platform', True, None)
('simplex-platform', 'simplex-platform', True, None)
('teams-platform', 'teams-platform', True, None)
Expected Behavior
Platform plugin keys should include the platforms/ namespace, while the display/manifest name can remain whatever the manifest declares:
('platforms/google_chat', 'google_chat-platform', True, None)
('platforms/irc', 'irc-platform', True, None)
('platforms/line', 'line-platform', True, None)
('platforms/simplex', 'simplex-platform', True, None)
('platforms/teams', 'teams-platform', True, None)
Impact
plugins.disabled / plugins.enabled entries using canonical keys like platforms/teams do not affect the discovered platform plugin if discovery reports teams-platform.
- Downstream tooling that displays plugin state by key can show platform plugins as neutral/not blocked even when config intended to disable them.
- The bug is specific to
plugins/platforms/* because other category plugins are scanned with a category prefix and already get keys like web/tavily or image_gen/openai.
Candidate Fix
Scan bundled platform plugins with _scan_directory_level() and prefix="platforms" instead of _scan_directory() from inside the platforms directory:
bundled_platforms = self._scan_directory_level(
repo_plugins / "platforms",
source="bundled",
skip_names=None,
prefix="platforms",
depth=0,
)
I verified this minimal local patch produces the expected platforms/* keys.
Verification Performed
- Reproduced on a clean detached worktree at HEAD: platform keys are
*-platform.
- Applied the minimal local patch above: platform keys become
platforms/*.
- Ran relevant plugin tests locally after the patch:
python -m pytest tests/hermes_cli/test_plugins.py tests/hermes_cli/test_plugins_cmd.py -q -o 'addopts='
137 passed in 6.39s
Environment
- Repo:
NousResearch/hermes-agent
- Component: plugin discovery / bundled gateway platform plugins
Bug Description
Bundled gateway platform plugins under
plugins/platforms/<name>/are discovered with keys liketeams-platforminstead of the path-derived keyplatforms/teams.This is inconsistent with the plugin manager's key model for namespaced plugins (
image_gen/openai,web/tavily, etc.) and breaks config/UI code that uses canonical plugin keys forplugins.enabled/plugins.disabled.Root Cause
In
PluginManager.discover_and_load(), bundled top-level plugins are scanned withplatformsskipped, then platform plugins are scanned separately:Because the second scan starts at
plugins/platformswith an empty prefix,_parse_manifest()computes:For platform manifests whose
nameis e.g.teams-platform, the key becomesteams-platforminstead ofplatforms/teams.Steps to Reproduce
Run plugin discovery from a clean
HERMES_HOMEon current HEAD:Actual Behavior
Expected Behavior
Platform plugin keys should include the
platforms/namespace, while the display/manifest name can remain whatever the manifest declares:Impact
plugins.disabled/plugins.enabledentries using canonical keys likeplatforms/teamsdo not affect the discovered platform plugin if discovery reportsteams-platform.plugins/platforms/*because other category plugins are scanned with a category prefix and already get keys likeweb/tavilyorimage_gen/openai.Candidate Fix
Scan bundled platform plugins with
_scan_directory_level()andprefix="platforms"instead of_scan_directory()from inside theplatformsdirectory:I verified this minimal local patch produces the expected
platforms/*keys.Verification Performed
*-platform.platforms/*.Environment
NousResearch/hermes-agent