From efa952531ba99cd4e1c6eb80e755ade60d04560a Mon Sep 17 00:00:00 2001 From: Robert DaSilva Date: Sat, 23 May 2026 15:18:57 -0400 Subject: [PATCH] fix: ignore Telegram start pings --- gateway/run.py | 11 +++++++ hermes_cli/commands.py | 2 ++ tests/gateway/test_gateway_command_help.py | 10 ++++++ tests/gateway/test_session_race_guard.py | 36 ++++++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/gateway/run.py b/gateway/run.py index fed1d6abe90..4cefe4303bb 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -7025,6 +7025,13 @@ class GatewayRunner: if _denied is not None: return _denied + # Telegram sends /start for bot launches/deep-links. Treat it as a + # platform ping, not a user command: no help dump, no agent + # interrupt, no queued text. + if _cmd_def_inner and _cmd_def_inner.name == "start": + logger.info("Ignoring /start platform ping for active session %s", _quick_key) + return "" + if _cmd_def_inner and _cmd_def_inner.name == "restart": return await self._handle_restart_command(event) @@ -7458,6 +7465,10 @@ class GatewayRunner: if canonical == "help": return await self._handle_help_command(event) + if canonical == "start": + logger.info("Ignoring /start platform ping for session %s", _quick_key) + return "" + if canonical == "commands": return await self._handle_commands_command(event) diff --git a/hermes_cli/commands.py b/hermes_cli/commands.py index f589248621c..47cc1733967 100644 --- a/hermes_cli/commands.py +++ b/hermes_cli/commands.py @@ -63,6 +63,8 @@ class CommandDef: COMMAND_REGISTRY: list[CommandDef] = [ # Session + CommandDef("start", "Acknowledge platform start pings without a reply", "Session", + gateway_only=True), CommandDef("new", "Start a new session (fresh session ID + history)", "Session", aliases=("reset",), args_hint="[name]"), CommandDef("topic", "Enable or inspect Telegram DM topic sessions", "Session", diff --git a/tests/gateway/test_gateway_command_help.py b/tests/gateway/test_gateway_command_help.py index 61d5d73de0d..d1dfb71d94d 100644 --- a/tests/gateway/test_gateway_command_help.py +++ b/tests/gateway/test_gateway_command_help.py @@ -26,6 +26,16 @@ def _make_runner(): return object.__new__(GatewayRunner) +def test_start_is_known_gateway_command(): + """Telegram sends /start automatically; gateway should intercept it as a no-op.""" + from hermes_cli.commands import GATEWAY_KNOWN_COMMANDS, resolve_command + + cmd = resolve_command("start") + assert "start" in GATEWAY_KNOWN_COMMANDS + assert cmd is not None + assert cmd.name == "start" + + @pytest.mark.asyncio async def test_help_sanitizes_slash_command_mentions_for_telegram(monkeypatch): """Telegram help output must not expose invalid uppercase/hyphenated slashes.""" diff --git a/tests/gateway/test_session_race_guard.py b/tests/gateway/test_session_race_guard.py index 152a1704766..80ec02c22f0 100644 --- a/tests/gateway/test_session_race_guard.py +++ b/tests/gateway/test_session_race_guard.py @@ -330,6 +330,42 @@ async def test_command_messages_do_not_leave_sentinel(): ) +@pytest.mark.asyncio +async def test_start_command_is_noop_and_does_not_show_help(): + """Telegram /start is a platform ping; it must not dump /help output.""" + runner = _make_runner() + event = _make_event(text="/start") + session_key = build_session_key(event.source) + + runner._handle_help_command = AsyncMock(return_value="Help text") + + result = await runner._handle_message(event) + + assert result == "" + runner._handle_help_command.assert_not_awaited() + assert session_key not in runner._running_agents + + +@pytest.mark.asyncio +async def test_start_command_is_noop_during_active_session(): + """A mid-run /start must not interrupt the active agent or show commands.""" + runner = _make_runner() + event = _make_event(text="/start") + session_key = build_session_key(event.source) + + fake_agent = MagicMock() + fake_agent.get_activity_summary.return_value = {"seconds_since_activity": 0} + runner._running_agents[session_key] = fake_agent + runner._handle_help_command = AsyncMock(return_value="Help text") + + result = await runner._handle_message(event) + + assert result == "" + runner._handle_help_command.assert_not_awaited() + fake_agent.interrupt.assert_not_called() + assert session_key not in runner.adapters[Platform.TELEGRAM]._pending_messages + + @pytest.mark.asyncio @pytest.mark.parametrize( ("command_text", "handler_attr", "handler_result"),