fix(agent_health): detect profile-scoped gateway.pid to fix false "Gateway not configured" - #2927
Conversation
_gateway_root_pid_path() unconditionally returned <hermes_root>/gateway.pid. Profile-scoped gateways (started with --profile <name> or via active_profile) write their runtime files under <hermes_root>/profiles/<name>/ instead of the root, so the root-level path never existed. build_agent_health_payload() therefore always received a non-existent pid_path, fell through to the stale root-level gateway_state.json, and returned alive=None. This caused the cron/scheduled-jobs page to display "Gateway not configured" even when a gateway was actively running. Fix: after failing to find a root-level gateway.pid, fall back to the active profile directory via get_active_hermes_home(). Root-level wins when it exists, so deployments that do write there are unaffected. Errors from profile lookup are swallowed and the root path is returned, preserving the previous safe default. Adds five focused unit tests covering the new fallback, the priority rule, and the error-handling path.
SummaryReading Code reference — production change is soundThe branch's root_pid = get_default_hermes_root() / _GATEWAY_PID_FILE
if root_pid.exists():
return root_pid
try:
from api.profiles import get_active_hermes_home
profile_pid = Path(get_active_hermes_home()) / _GATEWAY_PID_FILE
if profile_pid.exists():
return profile_pid
except Exception:
pass
return root_pidOrder-preserved (root wins when present, no regression for default-profile setups), failure caught, returns the root path when neither exists so downstream The CI failures are about test scaffolding, not the fixAll five tests fail with # tests/test_issue716_agent_heartbeat.py:89-93
monkeypatch.setitem(
sys.modules,
"hermes_constants",
types.SimpleNamespace(get_default_hermes_root=lambda: root_home),
)Switching the new Sibling cause — see #2935The handler at Even after this PR lands, that scenario will still show "Gateway not configured" because the gateway code isn't importable at all. A small companion change in VerificationAfter updating the test scaffolding, the existing |
a0ab168
…not available (CI fix)
…not available (CI fix)
Problem
When a Hermes gateway runs under a named profile — either via
gateway run --profile <name>or becauseactive_profileis set — it writes its runtime files under:_gateway_root_pid_path()inapi/agent_health.pyunconditionally returned<hermes_root>/gateway.pid(the root-level path), which is never created in profile-scoped deployments. As a result,build_agent_health_payload()always received a non-existentpid_path, fell through to reading the stale root-levelgateway_state.json(which retains the last recorded state, often"stopped"from a previous default-profile run), and returnedalive=None.The
/api/gateway/statusroute mapsalive=Nonetoconfigured=false, so the cron/scheduled-jobs page permanently displayed:…even when a profile-scoped gateway was actively running.
Root cause
The root-level
gateway.pidis only written when the gateway runs without a named profile. Profile-scoped gateways skip it.Fix
After failing to find a root-level
gateway.pid, fall back to the active profile's directory viaget_active_hermes_home():Errors from
get_active_hermes_home()are caught and silently ignored so the function retains its previous safe default.Tests
Five new unit tests in
tests/test_agent_health_pid_path_fallback.py:test_returns_root_pid_when_root_level_file_existstest_falls_back_to_profile_pid_when_root_absenttest_returns_root_path_when_neither_pid_existstest_returns_root_path_when_profile_lookup_raisesget_active_hermes_home()raises → root path returned silentlytest_root_takes_priority_over_profile_when_both_existAll 15 tests in
test_gateway_status_agent_health.pyandtest_agent_health_pid_path_fallback.pypass.