diff --git a/plugins/platforms/zulip/adapter.py b/plugins/platforms/zulip/adapter.py index 99918bd..3878a7d 100644 --- a/plugins/platforms/zulip/adapter.py +++ b/plugins/platforms/zulip/adapter.py @@ -853,12 +853,15 @@ class ZulipAdapter(BasePlatformAdapter): content: str, reply_to: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None, + **kwargs: Any, ) -> SendResult: """Send a message to a Zulip chat. For DMs, chat_id is the user_id. For streams, format is "stream_name:topic". Sends a placeholder first if this is the first message in a turn, then edits it on subsequent calls. + + Accepts **kwargs for Hermes Gateway compatibility. """ # Determine target type and IDs is_dm = not chat_id or ":" not in chat_id @@ -925,19 +928,42 @@ class ZulipAdapter(BasePlatformAdapter): message_id: str, content: str, metadata: Optional[Dict[str, Any]] = None, - ) -> bool: - """Edit a previously sent Zulip message (for placeholder replacement).""" + **kwargs: Any, + ) -> SendResult: + """Edit a previously sent Zulip message (for placeholder replacement). + + Returns SendResult for Hermes Gateway streaming interface compatibility. + Accepts **kwargs (e.g., finalize=True) — extra kwargs are silently ignored. + + Note: Zulip uses POST /api/v1/messages/{message_id} for editing. + """ truncated = _truncate(content) payload = { - "message_id": int(message_id), "content": truncated, } try: - resp, _ = await self._api_call("PATCH", "/api/v1/messages", data=payload) - return resp is not None + resp, status = await self._api_call( + "POST", f"/api/v1/messages/{int(message_id)}", + data=payload, + ) + if resp: + self._health_stats["send_count"] += 1 + return SendResult( + success=True, + message_id=str(resp.get("id", message_id)), + ) + self._health_stats["send_errors"] += 1 + return SendResult( + success=False, + error=f"Edit failed (status={status})", + ) except Exception as e: logger.warning("[%s] Edit message %s error: %s", self.name, message_id, e) - return False + self._health_stats["send_errors"] += 1 + return SendResult( + success=False, + error=str(e), + ) async def send_typing(self, chat_id: str, metadata: Optional[Dict] = None) -> None: """Send typing indicator to a Zulip chat.""" @@ -975,12 +1001,14 @@ class ZulipAdapter(BasePlatformAdapter): return {"name": chat_id, "type": "dm"} async def delete_message( - self, chat_id: str, message_id: str, metadata: Optional[Dict] = None - ) -> bool: + self, chat_id: str, message_id: str, + metadata: Optional[Dict] = None, + **kwargs: Any, + ) -> SendResult: """Delete a message via Zulip API.""" # Zulip doesn't support message deletion via API for bots # Send an empty edit instead - return await self.edit_message(chat_id, message_id, "*deleted*") + return await self.edit_message(chat_id, message_id, "*deleted*", **kwargs) # ------------------------------------------------------------------ # Gen 2: Self-test diagnostics