mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-17 09:41:58 +00:00
Detect containerized dashboard update management
This commit is contained in:
parent
0b6b29a30c
commit
b1d6a57883
4 changed files with 48 additions and 26 deletions
|
|
@ -1224,15 +1224,24 @@ def _default_hermes_root_is_opt_data() -> bool:
|
|||
return root == _HOSTED_MANAGED_FILES_ROOT
|
||||
|
||||
|
||||
def _dashboard_hosted_agent_mode() -> bool:
|
||||
"""Return true for the hosted/container dashboard layout.
|
||||
def _dashboard_local_update_managed_externally() -> bool:
|
||||
"""Return true when the dashboard should not offer ``hermes update``.
|
||||
|
||||
Hosted agent dashboards run with the Hermes root at ``/opt/data``. This is
|
||||
the same signal the Files page uses to lock browsing to the managed data
|
||||
directory, and it keeps local remote-auth dashboards from being mistaken for
|
||||
hosted service instances.
|
||||
Hosted agent dashboards run with the Hermes root at ``/opt/data``. Generic
|
||||
containerized dashboards may not use that exact root, but their lifecycle is
|
||||
still owned by the outer launcher/image, not by an in-browser local update
|
||||
action. Keep this dashboard capability separate from install-method
|
||||
detection: manual git/pip installs inside containers can still behave like
|
||||
their actual install method in the CLI.
|
||||
"""
|
||||
return _default_hermes_root_is_opt_data()
|
||||
if _default_hermes_root_is_opt_data():
|
||||
return True
|
||||
try:
|
||||
from hermes_constants import is_container
|
||||
|
||||
return is_container()
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _managed_files_policy(request: Request, *, create_root: bool = True) -> ManagedFilesPolicy:
|
||||
|
|
@ -1665,7 +1674,7 @@ async def get_status():
|
|||
"release_date": __release_date__,
|
||||
"config_version": current_ver,
|
||||
"latest_config_version": latest_ver,
|
||||
"can_update_hermes": not _dashboard_hosted_agent_mode(),
|
||||
"can_update_hermes": not _dashboard_local_update_managed_externally(),
|
||||
"gateway_running": gateway_running,
|
||||
"gateway_state": gateway_state,
|
||||
"gateway_platforms": gateway_platforms,
|
||||
|
|
@ -2177,19 +2186,20 @@ async def restart_gateway():
|
|||
@app.post("/api/hermes/update")
|
||||
async def update_hermes():
|
||||
"""Kick off ``hermes update`` in the background."""
|
||||
if _dashboard_hosted_agent_mode():
|
||||
if _dashboard_local_update_managed_externally():
|
||||
message = (
|
||||
"Hermes updates are managed by the hosted agent service for this "
|
||||
"dashboard. The built-in local updater is disabled here."
|
||||
"Hermes updates are managed outside this dashboard for hosted or "
|
||||
"containerized environments. The built-in local updater is "
|
||||
"disabled here."
|
||||
)
|
||||
_record_completed_action("hermes-update", message, exit_code=1)
|
||||
return {
|
||||
"ok": False,
|
||||
"pid": None,
|
||||
"name": "hermes-update",
|
||||
"error": "hosted_update_managed",
|
||||
"error": "dashboard_update_managed_externally",
|
||||
"message": message,
|
||||
"update_command": "managed by hosted agent service",
|
||||
"update_command": "managed outside dashboard",
|
||||
}
|
||||
|
||||
install_method = detect_install_method(PROJECT_ROOT)
|
||||
|
|
@ -2291,15 +2301,18 @@ async def check_hermes_update(force: bool = False):
|
|||
desktop's remote update overlay renders this as "what's
|
||||
changed". Additive: existing consumers ignore it.
|
||||
"""
|
||||
if _dashboard_hosted_agent_mode():
|
||||
if _dashboard_local_update_managed_externally():
|
||||
return {
|
||||
"install_method": "hosted",
|
||||
"install_method": "managed-runtime",
|
||||
"current_version": __version__,
|
||||
"behind": None,
|
||||
"update_available": False,
|
||||
"can_apply": False,
|
||||
"update_command": "managed by hosted agent service",
|
||||
"message": "Hermes updates are managed by the hosted agent service.",
|
||||
"update_command": "managed outside dashboard",
|
||||
"message": (
|
||||
"Hermes updates are managed outside this dashboard for hosted "
|
||||
"or containerized environments."
|
||||
),
|
||||
}
|
||||
|
||||
install_method = detect_install_method(PROJECT_ROOT)
|
||||
|
|
|
|||
|
|
@ -775,7 +775,7 @@ class TestUpdateCheckEndpoint:
|
|||
def test_hosted_dashboard_is_not_applyable(self, monkeypatch):
|
||||
import hermes_cli.web_server as ws
|
||||
|
||||
monkeypatch.setattr(ws, "_dashboard_hosted_agent_mode", lambda: True)
|
||||
monkeypatch.setattr(ws, "_dashboard_local_update_managed_externally", lambda: True)
|
||||
monkeypatch.setattr(
|
||||
ws,
|
||||
"detect_install_method",
|
||||
|
|
@ -785,11 +785,11 @@ class TestUpdateCheckEndpoint:
|
|||
)
|
||||
|
||||
body = self.client.get("/api/hermes/update/check").json()
|
||||
assert body["install_method"] == "hosted"
|
||||
assert body["install_method"] == "managed-runtime"
|
||||
assert body["can_apply"] is False
|
||||
assert body["update_available"] is False
|
||||
assert body["behind"] is None
|
||||
assert "hosted agent service" in body["message"]
|
||||
assert "managed outside this dashboard" in body["message"]
|
||||
|
||||
def test_check_failure_is_soft(self, monkeypatch):
|
||||
import hermes_cli.web_server as ws
|
||||
|
|
|
|||
|
|
@ -250,12 +250,21 @@ class TestWebServerEndpoints:
|
|||
def test_get_status_hides_update_capability_in_hosted_mode(self, monkeypatch):
|
||||
import hermes_cli.web_server as web_server
|
||||
|
||||
monkeypatch.setattr(web_server, "_dashboard_hosted_agent_mode", lambda: True)
|
||||
monkeypatch.setattr(web_server, "_dashboard_local_update_managed_externally", lambda: True)
|
||||
|
||||
resp = self.client.get("/api/status")
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["can_update_hermes"] is False
|
||||
|
||||
def test_dashboard_update_capability_detects_generic_container(self, monkeypatch):
|
||||
import hermes_constants
|
||||
import hermes_cli.web_server as web_server
|
||||
|
||||
monkeypatch.setattr(web_server, "_default_hermes_root_is_opt_data", lambda: False)
|
||||
monkeypatch.setattr(hermes_constants, "is_container", lambda: True)
|
||||
|
||||
assert web_server._dashboard_local_update_managed_externally() is True
|
||||
|
||||
# ── GET /api/media (remote image display) ───────────────────────────
|
||||
|
||||
def test_get_media_serves_image_in_root(self):
|
||||
|
|
@ -938,7 +947,7 @@ class TestWebServerEndpoints:
|
|||
detected = True
|
||||
raise AssertionError("hosted update guard should not detect install method")
|
||||
|
||||
monkeypatch.setattr(web_server, "_dashboard_hosted_agent_mode", lambda: True)
|
||||
monkeypatch.setattr(web_server, "_dashboard_local_update_managed_externally", lambda: True)
|
||||
monkeypatch.setattr(web_server, "detect_install_method", fail_detect)
|
||||
monkeypatch.setattr(web_server, "_spawn_hermes_action", fail_spawn)
|
||||
web_server._ACTION_PROCS.pop("hermes-update", None)
|
||||
|
|
@ -951,8 +960,8 @@ class TestWebServerEndpoints:
|
|||
assert data["ok"] is False
|
||||
assert data["name"] == "hermes-update"
|
||||
assert data["pid"] is None
|
||||
assert data["error"] == "hosted_update_managed"
|
||||
assert "hosted agent service" in data["message"]
|
||||
assert data["error"] == "dashboard_update_managed_externally"
|
||||
assert "managed outside this dashboard" in data["message"]
|
||||
assert spawned is False
|
||||
assert detected is False
|
||||
|
||||
|
|
@ -962,7 +971,7 @@ class TestWebServerEndpoints:
|
|||
assert status_data["running"] is False
|
||||
assert status_data["exit_code"] == 1
|
||||
assert status_data["pid"] is None
|
||||
assert any("hosted agent service" in line for line in status_data["lines"])
|
||||
assert any("managed outside this dashboard" in line for line in status_data["lines"])
|
||||
|
||||
def test_update_hermes_spawns_on_non_docker_install(self, monkeypatch):
|
||||
import hermes_cli.web_server as web_server
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ export default function SystemPage() {
|
|||
setUpdateConfirmOpen(false);
|
||||
if (status?.can_update_hermes === false) {
|
||||
showToast(
|
||||
"Hermes updates are managed by the hosted agent service.",
|
||||
"Hermes updates are managed outside this dashboard.",
|
||||
"success",
|
||||
);
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue