fix(dashboard): drop systemd-only advice from the model-picker code-skew 503 (#97046)

Desktop-owned serve and macOS hosts have no hermes-dashboard unit, so the
restart hint now follows HERMES_SERVE_HEADLESS instead of hardcoding systemctl.
This commit is contained in:
xxxigm
2026-08-28 17:44:05 +07:00
committed by brooklyn!
parent 42c415820c
commit c99a3919a8
2 changed files with 46 additions and 13 deletions
+32 -13
View File
@@ -7416,17 +7416,18 @@ _AUX_TASK_SLOTS: Tuple[str, ...] = (
def _dashboard_code_skew_guard() -> Optional[str]:
"""Return a clear \"restart required\" message when the dashboard runs stale code.
"""Return a clear \"restart required\" message when this process runs stale code.
The dashboard is a long-lived process; its ``sys.modules`` is frozen at
boot. When ``hermes update`` (or a manual ``git pull``) replaces the
checkout underneath it, a first-time lazy import on a new code path can
resolve a freshly-pulled consumer module against a stale cached dependency
-> ImportError — e.g. ``/api/model/options`` 500 after the update added
``agent.model_metadata.is_grok_46_family`` while the running process kept
serving the pre-update module (#86207). Mirror the gateway's
``_model_switch_skew_guard``: refuse the risky call with an actionable
message instead of crashing with a cryptic import error.
The dashboard and Desktop-owned ``hermes serve`` are long-lived; their
``sys.modules`` is frozen at boot. When ``hermes update`` (or a manual
``git pull``) replaces the checkout underneath them, a first-time lazy
import on a new code path can resolve a freshly-pulled consumer module
against a stale cached dependency -> ImportError — e.g. ``/api/model/options``
500 after the update added ``agent.model_metadata.is_grok_46_family`` while
the running process kept serving the pre-update module (#86207). Mirror
the gateway's ``_model_switch_skew_guard``: refuse the risky call with an
actionable, deployment-aware message instead of crashing with a cryptic
import error (#97046).
Returns None when no drift is detectable (fresh process, or a non-git
install where the boot fingerprint could not be read — never a false
@@ -7439,10 +7440,28 @@ def _dashboard_code_skew_guard() -> Optional[str]:
return None
boot_rev, disk_rev = skew
return (
f"This dashboard is running code from {boot_rev} but the checkout on "
f"This process is running code from {boot_rev} but the checkout on "
f"disk is now {disk_rev}. The model picker would risk a stale-module "
f"crash — restart the dashboard to load the new code "
f"(systemctl --user restart hermes-dashboard, or hermes dashboard --port <port>)"
f"crash — {_dashboard_skew_restart_hint()}"
)
def _dashboard_skew_restart_hint() -> str:
"""Restart advice that matches how this process is actually owned.
The same FastAPI app backs the browser dashboard *and* Desktop-owned
``hermes serve --isolated`` (local or SSH). Hardcoding a systemd unit
misleads macOS/launchd hosts and Desktop SSH backends, which have no
``hermes-dashboard`` unit (#97046).
"""
if os.environ.get("HERMES_SERVE_HEADLESS") == "1":
return (
"restart the Desktop-owned backend to load the new code "
"(use Restart backend in Hermes Desktop, or quit and reopen the app)"
)
return (
"restart this Hermes process to load the new code "
"(hermes dashboard --port <port>, or the equivalent service restart for this install)"
)
+14
View File
@@ -81,12 +81,26 @@ class TestDashboardCodeSkewGuard:
def test_dashboard_guard_message_names_revs_and_restart(self, monkeypatch):
from hermes_cli import web_server
monkeypatch.delenv("HERMES_SERVE_HEADLESS", raising=False)
monkeypatch.setattr(code_skew, "detect_code_skew", lambda: ("abc1234567", "def4567890"))
msg = web_server._dashboard_code_skew_guard()
assert msg is not None
assert "abc1234567" in msg
assert "def4567890" in msg
assert "restart" in msg.lower()
# Browser-dashboard path: never hardcode a Linux-only unit (#97046).
assert "systemctl" not in msg
def test_serve_guard_message_points_at_desktop_backend(self, monkeypatch):
from hermes_cli import web_server
monkeypatch.setenv("HERMES_SERVE_HEADLESS", "1")
monkeypatch.setattr(code_skew, "detect_code_skew", lambda: ("abc1234567", "def4567890"))
msg = web_server._dashboard_code_skew_guard()
assert msg is not None
assert "Desktop-owned backend" in msg
assert "systemctl" not in msg
assert "hermes-dashboard" not in msg
class TestModelOptionsSkewGuard: