From 85c7e87fc7bbbd2b646da3398b402c42c88454cb Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 25 Sep 2026 11:04:04 -0500 Subject: [PATCH] fix(gateway): recognize Atomic desktop-gateway.py in gateway detection Atomic Hermes' bundled desktop runner (desktop-gateway.py) shares HERMES_HOME with the CLI but was not recognized by the gateway command-line matcher, so `gateway run --replace` skipped the terminate-and-scoped-lock-handoff path and collided with the desktop runner's still-held scoped locks (e.g. the Discord bot-token lock), leaving Discord responses down until the desktop gateway was killed by hand. Recognize desktop-gateway.py as a gateway entrypoint in _gateway_command_subcommand, covering both live process detection and the PID-record metadata fallback. Co-authored-by: namhyuk kim --- gateway/status.py | 6 ++++++ .../gateway/test_gateway_command_line_matcher.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/gateway/status.py b/gateway/status.py index 9a1a3bce2b..9120495780 100644 --- a/gateway/status.py +++ b/gateway/status.py @@ -552,6 +552,12 @@ def _gateway_command_subcommand(command: str | None) -> str | None: # Gateway-dedicated entrypoints carry no subcommand to inspect. if any(t == "gateway/run.py" or t.endswith("/gateway/run.py") for t in tokens): return "run" + # Atomic Hermes' bundled desktop runner shares HERMES_HOME with the CLI; without this, + # `gateway run --replace` does not recognise it as a running gateway, skips the + # terminate-and-scoped-lock-handoff path, and collides with its still-held scoped locks + # (e.g. the Discord bot-token lock). See #22418. + if any(b == "desktop-gateway.py" for b in basenames): + return "run" if any(b in ("hermes-gateway", "hermes-gateway.exe") for b in basenames): return "run" joined = " ".join(tokens) diff --git a/tests/gateway/test_gateway_command_line_matcher.py b/tests/gateway/test_gateway_command_line_matcher.py index 88867a58a5..ddcae282a5 100644 --- a/tests/gateway/test_gateway_command_line_matcher.py +++ b/tests/gateway/test_gateway_command_line_matcher.py @@ -58,3 +58,18 @@ def test_accepts_real_gateway_run(cmd): assert matches(cmd) is True +# Atomic Hermes' bundled desktop runner (regression for #22418): it shares +# HERMES_HOME with the CLI and must be recognised as a gateway so +# ``gateway run --replace`` enters the replace/lock-handoff path instead of +# colliding with the desktop runner's still-held scoped locks. +ATOMIC_DESKTOP = ( + "/Applications/Atomic Hermes.app/Contents/Resources/python-server/python " + "/Applications/Atomic Hermes.app/Contents/Resources/python-server/desktop-gateway.py" +) + + +def test_accepts_atomic_desktop_gateway(): + assert matches(ATOMIC_DESKTOP) is True + assert matches_runtime(ATOMIC_DESKTOP) is True + +