From 4dc56fea517311949258dd9b0decbf73ee5ff2b2 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Fri, 23 Oct 2026 13:50:05 -0700 Subject: [PATCH] fix(plugins): an undeclared OS is not told to install the app A portable plugin with no app declaration for this OS maps to missing_app, so describe() told the user to install an app that cannot fix the OS restriction. It now says the app is not supported on this operating system. --- tests/hermes_cli/test_plugins_cmd.py | 14 ++++++++++++-- tools/mcp_liveness.py | 5 ++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/hermes_cli/test_plugins_cmd.py b/tests/hermes_cli/test_plugins_cmd.py index c619013747..5fc6c2d7d4 100644 --- a/tests/hermes_cli/test_plugins_cmd.py +++ b/tests/hermes_cli/test_plugins_cmd.py @@ -25,7 +25,7 @@ from hermes_cli.plugins_cmd import ( from hermes_cli.plugins_cmd_install import _refuse_unavailable_portable_plugin -def _write_portable_app_plugin(root: Path, app: Path) -> None: +def _write_portable_app_plugin(root: Path, app: Path, os_key: str | None = None) -> None: from hermes_cli.agent_plugins import MCP_SCHEMA_V1, PLUGIN_SCHEMA_V1 from hermes_platform.host.facts import os_family @@ -33,7 +33,7 @@ def _write_portable_app_plugin(root: Path, app: Path) -> None: "$schema": PLUGIN_SCHEMA_V1, "name": "example-plugin", "extensions": {"com.nousresearch.hermes": {"servers": {"worker": { - "app": {os_family(): {"presence": "executable", "location": str(app)}}, + "app": {os_key or os_family(): {"presence": "executable", "location": str(app)}}, "requires": {"app": True}, }}}}, }), encoding="utf-8") @@ -54,6 +54,16 @@ def test_portable_install_gate_accepts_present_app_and_refuses_missing(tmp_path: _refuse_unavailable_portable_plugin("example-plugin", tmp_path) +def test_portable_install_gate_on_undeclared_os_does_not_say_install(tmp_path: Path) -> None: + from hermes_platform.host.facts import os_family + + other = next(o for o in ("linux", "darwin", "win32") if o != os_family()) + _write_portable_app_plugin(tmp_path, tmp_path / "example-app", os_key=other) + with pytest.raises(PluginOperationError, match="Example App is not supported on this operating system") as exc: + _refuse_unavailable_portable_plugin("example-plugin", tmp_path, "Example App") + assert "Install" not in str(exc.value) + + # ── _sanitize_plugin_name ───────────────────────────────────────────────── diff --git a/tools/mcp_liveness.py b/tools/mcp_liveness.py index 5bd86f1175..562dccb5d3 100644 --- a/tools/mcp_liveness.py +++ b/tools/mcp_liveness.py @@ -180,7 +180,10 @@ def describe(decl: declaration.Declaration, available: Availability, liveness_st app_name = display_name or decl.name gpu = declaration.gpu_label(decl.required_gpu) action, _retry = _action(liveness_state, app_name, gpu) - if liveness_state == "missing_app": + if liveness_state == "missing_app" and available.state == "unsupported_os": + reason = f"{app_name} is not supported on this operating system." + action = "Use a supported operating system." + elif liveness_state == "missing_app": reason = f"{app_name} is not installed." if available.min_version: action = f"Install {app_name} {available.min_version} or newer, then try again."