fix(gateway): report bundled auto-loading plugins as enabled

Bundled backends/platforms/providers load without a plugins.enabled
entry ('must just work'), but plugins.manage reported them 'not
enabled' — clients rendered running plugins with an OFF switch.
Surface the truthful default; explicit disable still wins.
This commit is contained in:
Brooklyn Nicholson 2026-08-08 17:34:20 -05:00
parent c86da8397b
commit ed9eee5dc9
2 changed files with 39 additions and 1 deletions

View File

@ -1076,6 +1076,32 @@ def _is_portable_plugin_dir(dir_path) -> bool:
return False
# Manifest kinds that are active-by-default when bundled: backends auto-load,
# platforms register lazily but are available out of the box, model providers
# run through providers/ discovery (see PluginManager.discover_and_load).
_BUNDLED_DEFAULT_ON_KINDS = frozenset({"backend", "platform", "model-provider"})
def _bundled_default_on(dir_path) -> bool:
"""True when a bundled plugin at *dir_path* is active without an explicit
``plugins.enabled`` entry. Standalone/exclusive kinds stay opt-in, and
portable packages (``plugin.json``) have no kind at all."""
manifest_file = Path(dir_path) / "plugin.yaml"
if not manifest_file.exists():
manifest_file = Path(dir_path) / "plugin.yml"
if not manifest_file.exists():
return False
try:
import yaml
with open(manifest_file, encoding="utf-8") as f:
manifest = yaml.safe_load(f) or {}
kind = str(manifest.get("kind", "standalone")).strip().lower()
return kind in _BUNDLED_DEFAULT_ON_KINDS
except Exception:
return False
def _scan_level(
base: Path,
source: str,

View File

@ -1811,6 +1811,7 @@ def _(rid, params: dict) -> dict:
action = params.get("action", "list")
try:
from hermes_cli.plugins_cmd import (
_bundled_default_on,
_discover_all_plugins,
_get_disabled_set,
_get_enabled_set,
@ -1825,6 +1826,17 @@ def _(rid, params: dict) -> dict:
for name, version, desc, source, _dir, key in sorted(
_discover_all_plugins()
):
status = _plugin_status(name, enabled, disabled, key=key)
# Bundled backends/platforms/providers are active without an
# explicit enable (they "just work" — plugins.py). Reporting
# them "not enabled" reads as OFF in clients when they are in
# fact running; surface the truthful default instead.
if (
status == "not enabled"
and source == "bundled"
and _bundled_default_on(_dir)
):
status = "enabled"
out.append(
{
"name": name,
@ -1835,7 +1847,7 @@ def _(rid, params: dict) -> dict:
"version": str(version or ""),
"description": desc or "",
"source": source,
"status": _plugin_status(name, enabled, disabled, key=key),
"status": status,
# Agent Plugins v1 package (plugin.json — the portable
# skills/MCP format) vs a native Hermes plugin.
"portable": _is_portable_plugin_dir(_dir),