From 0fc3cbac5915b35b5731e4ab93949bec9e242022 Mon Sep 17 00:00:00 2001 From: nightq Date: Fri, 17 Apr 2026 00:25:51 +0800 Subject: [PATCH] fix: suppress stale "Still working..." heartbeats during gateway restart The gateway's long-running notification task was sending "Still working... messages even after a restart was requested, causing confusing UX where users received a restart warning followed by normal heartbeat messages. Added a check in _notify_long_running() to skip notifications when gateway is draining or restart has been requested. Fixes NousResearch/hermes-agent#10990 --- gateway/run_shutdown.py | 4 ++++ tests/gateway/test_busy_session_ack.py | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/gateway/run_shutdown.py b/gateway/run_shutdown.py index 78ed9bddd9..845ae0ce21 100644 --- a/gateway/run_shutdown.py +++ b/gateway/run_shutdown.py @@ -1077,6 +1077,10 @@ class GatewayShutdownMixin: """ if agent is None or (executor_task is not None and executor_task.done()): return False + # Drain/restart already told the chat the task will be interrupted; a "still working" + # heartbeat after that notice reads as a contradiction (#10990). + if getattr(self, "_draining", False) or getattr(self, "_restart_requested", False): + return False if session_key: _hb_state = self._peek_session_state(session_key) if (_hb_state.turn.agent if _hb_state else None) is not agent: diff --git a/tests/gateway/test_busy_session_ack.py b/tests/gateway/test_busy_session_ack.py index f28d847a9e..b4d01fb606 100644 --- a/tests/gateway/test_busy_session_ack.py +++ b/tests/gateway/test_busy_session_ack.py @@ -518,4 +518,17 @@ class TestLongRunningNotificationOwnership: "sess", original_agent, executor_task=None ) is False + @pytest.mark.parametrize("flag", ["_draining", "_restart_requested"]) + def test_notification_stops_once_shutdown_or_restart_begins(self, flag): + """After the restart/shutdown notice a heartbeat would contradict it (#10990).""" + from gateway.run import GatewayRunner + + runner = object.__new__(GatewayRunner) + runner._running_agents = {} + agent = MagicMock() + runner._running_agents["sess"] = agent + assert runner._should_emit_long_running_notification("sess", agent, executor_task=None) is True + setattr(runner, flag, True) + assert runner._should_emit_long_running_notification("sess", agent, executor_task=None) is False +