mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-26 17:38:36 +00:00
fix(dashboard): add lightweight /api/health liveness endpoint
/api/status is the only public liveness route, and its handler loads the gateway config, probes gateway health, and counts sessions before it can answer. That work is wrong for a readiness probe: a caller that only needs to know the process is up pays for a cold plugin import tree. Add /api/health, which returns process liveness, version, and the auth-gate shape and touches nothing else.
This commit is contained in:
parent
bb4765d21c
commit
ccab46ca43
4 changed files with 32 additions and 0 deletions
|
|
@ -31,6 +31,11 @@ the SPA should bootstrap it after login instead.
|
|||
from __future__ import annotations
|
||||
|
||||
PUBLIC_API_PATHS: frozenset[str] = frozenset({
|
||||
# Minimal process liveness probe for desktop/backend boot handshakes. It
|
||||
# intentionally avoids gateway config, platform discovery, MCP setup, and
|
||||
# host-local detail so readiness checks cannot spend their budget inside
|
||||
# cold plugin imports.
|
||||
"/api/health",
|
||||
# Liveness probe target. Returns version, gateway state, active
|
||||
# session count, and the dashboard auth-gate shape. No bodies, no
|
||||
# session content, no secrets. Documented as the portal's wildcard
|
||||
|
|
|
|||
|
|
@ -3036,6 +3036,16 @@ async def get_ssh_ownership(request: Request):
|
|||
return {"ok": True, "sshOwnerNonce": _SSH_OWNER_NONCE, "protocolVersion": 1}
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
async def get_health():
|
||||
"""Lightweight process liveness for desktop/backend readiness probes."""
|
||||
return {
|
||||
"ok": True,
|
||||
"version": __version__,
|
||||
"auth_required": bool(getattr(app.state, "auth_required", False)),
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/status")
|
||||
async def get_status(profile: Optional[str] = None):
|
||||
status_scope = None
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ def test_gated_status_is_public(gated_app):
|
|||
|
||||
|
||||
@pytest.mark.parametrize("path", [
|
||||
"/api/health",
|
||||
"/api/config/defaults",
|
||||
"/api/config/schema",
|
||||
"/api/model/info",
|
||||
|
|
|
|||
|
|
@ -67,6 +67,22 @@ def test_status_reports_auth_required_in_gated_mode(gated_client):
|
|||
assert body["auth_providers"] == ["stub"]
|
||||
|
||||
|
||||
def test_health_reports_liveness_without_loading_gateway_config(gated_client, monkeypatch):
|
||||
def _boom():
|
||||
raise AssertionError("health must not load gateway config")
|
||||
|
||||
monkeypatch.setattr("gateway.config.load_gateway_config", _boom)
|
||||
|
||||
r = gated_client.get("/api/health")
|
||||
assert r.status_code == 200
|
||||
body = r.json()
|
||||
assert body == {
|
||||
"ok": True,
|
||||
"version": web_server.__version__,
|
||||
"auth_required": True,
|
||||
}
|
||||
|
||||
|
||||
def test_status_reports_auth_disabled_in_loopback_mode(loopback_client):
|
||||
r = loopback_client.get("/api/status")
|
||||
assert r.status_code == 200
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue