fix(hermes): add StreamHandler, finally/loop.close, event logging per Abiba review
CI / validate (pull_request) Failing after 2s

This commit is contained in:
kagentz-bot
2026-06-20 13:15:48 -04:00
parent 941b69e782
commit 141814a12a
@@ -4,12 +4,23 @@
import asyncio import asyncio
import logging import logging
import sys
import time import time
import re import re
import threading import threading
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
logger = logging.getLogger(__name__) 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: class ZulipAdapter:
"""Zulip adapter for Hermes agents. Connects to Zulip, listens for """Zulip adapter for Hermes agents. Connects to Zulip, listens for
@@ -112,10 +123,11 @@ class ZulipAdapter:
} }
def _event_loop(self) -> None: 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() loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop) asyncio.set_event_loop(loop)
"""Background thread to listen for Zulip events."""
try: try:
self._client.call_on_each_message( self._client.call_on_each_message(
lambda event: self._process_event(event), lambda event: self._process_event(event),
@@ -123,10 +135,14 @@ class ZulipAdapter:
except Exception as e: except Exception as e:
logger.error(f"Event loop crashed: {e}") logger.error(f"Event loop crashed: {e}")
self.connected = False self.connected = False
finally:
loop.close()
logger.info("Event loop closed.")
def _process_event(self, event: Dict[str, Any]) -> None: def _process_event(self, event: Dict[str, Any]) -> None:
"""Bridge the synchronous event to the async on_event handler.""" """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: try:
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
if loop.is_running(): if loop.is_running():
@@ -134,4 +150,4 @@ class ZulipAdapter:
else: else:
asyncio.run(self.on_event(event)) asyncio.run(self.on_event(event))
except Exception as e: except Exception as e:
logger.error(f"Error processing event: {e}") logger.error(f"Error processing event: {e}")