fix(gateway): key the messaging fold on the profile name, not the home basename
_platform_payloads passed own_home.name — the directory basename, '.hermes' for the shipped default root or any custom HERMES_HOME name — into profile_platforms_from_multiplexer, whose fold only matches a profile NAME. Only secondaries under profiles/<name> have basename == profile id, so the default home's re-key came back empty and /api/messaging/platforms kept reading 'Restart needed' forever while the multiplexer served its flat-keyed adapters (#123088 follow-up; /api/status already passed 'default' explicitly). Resolve the name with profile_name_for_home, and add a regression test whose fixture home is literally named '.hermes'.
This commit is contained in:
@@ -22,8 +22,8 @@ from typing import Any, Optional
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from gateway.status import (
|
||||
multiplexer_liveness_for_profile, profile_platforms_from_multiplexer, resolve_gateway_liveness,
|
||||
retained_gateway_state)
|
||||
multiplexer_liveness_for_profile, profile_name_for_home, profile_platforms_from_multiplexer,
|
||||
resolve_gateway_liveness, retained_gateway_state)
|
||||
from hermes_cli._subprocess_compat import windows_hide_flags
|
||||
from hermes_cli.config import OPTIONAL_ENV_VARS, get_env_path
|
||||
from hermes_constants import get_process_hermes_home
|
||||
@@ -294,7 +294,7 @@ def _platform_payloads(scoped_dir: Optional[Path], entries) -> list[dict[str, An
|
||||
# profile's standalone days outranks nothing: only a record proving a live own gateway does —
|
||||
# the same rung order ``resolve_gateway_liveness`` uses (own runtime PID before the multiplexer),
|
||||
# so the two surfaces cannot disagree. Unscoped, the profile is the process's own home (a pooled
|
||||
# ``hermes --profile X serve``); the default home resolves to a name the multiplexer never serves.
|
||||
# ``hermes --profile X serve``).
|
||||
own_home = scoped_dir if scoped_dir is not None else get_process_hermes_home()
|
||||
if (
|
||||
runtime is None
|
||||
@@ -302,7 +302,16 @@ def _platform_payloads(scoped_dir: Optional[Path], entries) -> list[dict[str, An
|
||||
):
|
||||
served = multiplexer_liveness_for_profile(own_home)
|
||||
if served is not None:
|
||||
runtime = {**served[1], "platforms": profile_platforms_from_multiplexer(served[1], own_home.name)}
|
||||
# The fold keys on the profile NAME rung 4 just proved served; ``own_home.name`` is only
|
||||
# the directory basename (".hermes" or any custom HERMES_HOME name for the default root,
|
||||
# the profile id only for secondaries under profiles/<name>) — the default's flat keys
|
||||
# then never matched and the card read "Restart needed" forever (#123088).
|
||||
runtime = {
|
||||
**served[1],
|
||||
"platforms": profile_platforms_from_multiplexer(
|
||||
served[1], profile_name_for_home(own_home) or "default"
|
||||
),
|
||||
}
|
||||
return [_messaging_platform_payload(entry, env_on_disk, runtime, scoped=scoped_dir is not None, profile_home=scoped_dir)
|
||||
for entry in entries]
|
||||
|
||||
|
||||
@@ -89,6 +89,38 @@ def test_default_profile_keeps_its_flat_adapters_when_rekeyed(served_root):
|
||||
assert "telegram" not in plats # that entry belongs to alpha
|
||||
|
||||
|
||||
def test_messaging_card_for_the_default_home_rekeys_by_the_profile_not_the_dirname(tmp_path, monkeypatch):
|
||||
"""The multiplexer fold keys on the profile NAME; ``_platform_payloads`` used to pass
|
||||
``own_home.name`` — the directory basename, ``.hermes`` for the shipped default root or any
|
||||
custom ``HERMES_HOME`` name, equal to the profile id only for secondaries under
|
||||
``profiles/<name>``. On the default home the fold came back empty and the Channels card read
|
||||
"Restart needed" forever while the multiplexer served its flat-keyed adapters (#123088)."""
|
||||
import gateway.status as status
|
||||
from hermes_cli.web_routers import messaging
|
||||
root = tmp_path / ".hermes" # the shipped default root's literal name — never equal to "default"
|
||||
root.mkdir()
|
||||
(root / "config.yaml").write_text("gateway: {multiplex_profiles: true}\n", encoding="utf-8")
|
||||
record = {
|
||||
"pid": os.getpid(), "hermes_home": str(root), "gateway_state": "running",
|
||||
"served_profiles": ["default", "route-runner"],
|
||||
"platforms": {"telegram": {"state": "connected"}},
|
||||
}
|
||||
monkeypatch.setenv("HERMES_HOME", str(root))
|
||||
import hermes_constants
|
||||
monkeypatch.setattr(hermes_constants, "_default_hermes_root_memo", None)
|
||||
# A launch-service gateway's record fails the own-rung argv check (inline ``-c``), so the card
|
||||
# falls through to the multiplexer rung — mirrored here by an absent own record.
|
||||
monkeypatch.setattr(messaging, "read_runtime_status", lambda *a, **k: None)
|
||||
monkeypatch.setattr(messaging, "multiplexer_liveness_for_profile", lambda home: (os.getpid(), record))
|
||||
monkeypatch.setattr(status, "_read_process_cmdline", lambda pid: "hermes gateway run")
|
||||
monkeypatch.setattr(messaging, "_platform_enablement", lambda *a, **k: (True, True, None))
|
||||
entry = {"id": "telegram", "name": "Telegram", "description": "", "docs_url": "", "env_vars": [],
|
||||
"required_env": []}
|
||||
[payload] = messaging._platform_payloads(None, [entry]) # unscoped: the dashboard's own home
|
||||
assert payload["gateway_running"] is True
|
||||
assert payload["state"] == "connected", payload
|
||||
|
||||
|
||||
def test_messaging_card_for_a_served_profile_reads_connected_not_restart_needed(served_root, monkeypatch):
|
||||
from hermes_cli.web_routers import messaging
|
||||
monkeypatch.setattr(messaging, "_platform_enablement", lambda *a, **k: (True, True, None))
|
||||
|
||||
Reference in New Issue
Block a user