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:
+32
-13
@@ -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)"
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user