From 141814a12a4863df01120d1ceec93b9a26b364d7 Mon Sep 17 00:00:00 2001 From: kagentz-bot Date: Sat, 20 Jun 2026 13:15:48 -0400 Subject: [PATCH] fix(hermes): add StreamHandler, finally/loop.close, event logging per Abiba review --- .../src/hermes_zulip/adapter.py | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/hermes-zulip-plugin/src/hermes_zulip/adapter.py b/hermes-zulip-plugin/src/hermes_zulip/adapter.py index f478150..904e26d 100644 --- a/hermes-zulip-plugin/src/hermes_zulip/adapter.py +++ b/hermes-zulip-plugin/src/hermes_zulip/adapter.py @@ -4,12 +4,23 @@ import asyncio import logging +import sys import time import re import threading from typing import Any, Dict, Optional logger = logging.getLogger(__name__) +# Ensure logger output reaches journald (systemd captures stderr) +if not logger.handlers: + _handler = logging.StreamHandler(sys.stderr) + _handler.setLevel(logging.INFO) + _handler.setFormatter(logging.Formatter( + '%(asctime)s [%(levelname)s] %(name)s: %(message)s', + datefmt='%Y-%m-%d %H:%M:%S' + )) + logger.addHandler(_handler) + logger.setLevel(logging.INFO) class ZulipAdapter: """Zulip adapter for Hermes agents. Connects to Zulip, listens for @@ -112,10 +123,11 @@ class ZulipAdapter: } def _event_loop(self) -> None: - # Create an event loop for this background thread (Python 3.13+) + """Background thread to listen for Zulip events. + Creates a dedicated asyncio event loop for this thead (Python 3.13+). + """ loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - """Background thread to listen for Zulip events.""" try: self._client.call_on_each_message( lambda event: self._process_event(event), @@ -123,10 +135,14 @@ class ZulipAdapter: except Exception as e: logger.error(f"Event loop crashed: {e}") self.connected = False + finally: + loop.close() + logger.info("Event loop closed.") def _process_event(self, event: Dict[str, Any]) -> None: """Bridge the synchronous event to the async on_event handler.""" - import asyncio + event_type = str(event.get("type", "unknown")) + logger.info(f"[ZULIP_EVENT] Processing: {event_type}") try: loop = asyncio.get_event_loop() if loop.is_running(): @@ -134,4 +150,4 @@ class ZulipAdapter: else: asyncio.run(self.on_event(event)) except Exception as e: - logger.error(f"Error processing event: {e}") + logger.error(f"Error processing event: {e}") \ No newline at end of file