From 9b8a06d0e6286ea14e65e8f47f38f6fd52171347 Mon Sep 17 00:00:00 2001 From: Juraj Bednar Date: Thu, 16 Jul 2026 22:20:22 -0400 Subject: [PATCH] fix(hermes/marmot): accept is_reconnect kwarg in connect() The hermes-agent gateway connects adapters via connect(is_reconnect=...) on cold boot and reconnect alike, so the override must accept the keyword-only argument even though wn-agent owns reconnect/resync and the flag is intentionally unused. Includes a regression test pinning the gateway calling convention against both the adapter and the base-class test stub. Closes #836 Co-authored-by: Javier G. Montoya S --- integrations/hermes/marmot/adapter.py | 2 +- .../hermes/marmot/tests/test_adapter.py | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/integrations/hermes/marmot/adapter.py b/integrations/hermes/marmot/adapter.py index fb64c15a..281596bf 100644 --- a/integrations/hermes/marmot/adapter.py +++ b/integrations/hermes/marmot/adapter.py @@ -1297,7 +1297,7 @@ async def get_chat_info(self, chat_id: str) -> Dict[str, Any]: "id": chat_id, } - async def connect(self) -> bool: + async def connect(self, *, is_reconnect: bool = False) -> bool: try: await self._ensure_account_id() await self._sync_welcomer_allowlist() diff --git a/integrations/hermes/marmot/tests/test_adapter.py b/integrations/hermes/marmot/tests/test_adapter.py index d5e9abb8..cea1b0bd 100644 --- a/integrations/hermes/marmot/tests/test_adapter.py +++ b/integrations/hermes/marmot/tests/test_adapter.py @@ -88,6 +88,12 @@ def _mark_connected(self): def _mark_disconnected(self): self._running = False + async def connect(self, *, is_reconnect: bool = False) -> bool: + # Mirrors hermes-agent's keyword-only base signature; the gateway + # always calls connect(is_reconnect=...), so overrides must accept + # the keyword even when they ignore it (#836). + raise NotImplementedError + def build_source(self, **kwargs): return SessionSource(platform=self.platform, **kwargs) @@ -812,6 +818,30 @@ async def test_disconnect_clears_tool_progress_dedupe_cache(self): self.assertEqual(adapter._tool_progress_events, {}) self.assertEqual(adapter._tool_progress_replies, {}) + async def test_connect_accepts_gateway_is_reconnect_keyword(self): + # hermes-agent's gateway connects adapters via connect(is_reconnect=...) + # on cold boot and reconnect alike, so a signature without the + # keyword-only argument raises TypeError before the platform ever + # comes up (#836). + class FakeClient: + async def inbound_events(self, account_id_hex=None, group_id_hex=None): + await asyncio.Event().wait() + yield {} # unreachable: marks this as an async generator + + for is_reconnect in (False, True): + with self.subTest(is_reconnect=is_reconnect): + adapter = self.adapter_module.MarmotPlatformAdapter( + self.config_cls(extra={"account_id_hex": "11" * 32}), + client=FakeClient(), + ) + try: + self.assertTrue(await adapter.connect(is_reconnect=is_reconnect)) + self.assertTrue(adapter._running) + self.assertIsNotNone(adapter._listener_task) + finally: + await adapter.disconnect() + self.assertIsNone(adapter._listener_task) + async def test_inbound_event_is_forwarded_to_hermes_message_event(self): events = [ {