fix(zulip): edit_message accepts **kwargs, returns SendResult; use POST for edits
CI / validate (pull_request) Failing after 2s
CI / validate (pull_request) Failing after 2s
The Gateway streaming interface calls edit_message() with finalize=True
and expects SendResult. Fixed:
1. Added **kwargs to edit_message() signature — silently ignores finalize
2. Changed return type from bool to SendResult for Gateway compatibility
3. Switched from PATCH to POST /api/v1/messages/{id} — Zulip docs use
POST for message editing (PATCH returns 405 Method Not Allowed)
4. Same fixes applied to delete_message() and send()
Discovered during Tanko Gen 4 testing.
This commit is contained in:
@@ -853,12 +853,15 @@ class ZulipAdapter(BasePlatformAdapter):
|
|||||||
content: str,
|
content: str,
|
||||||
reply_to: Optional[str] = None,
|
reply_to: Optional[str] = None,
|
||||||
metadata: Optional[Dict[str, Any]] = None,
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
|
**kwargs: Any,
|
||||||
) -> SendResult:
|
) -> SendResult:
|
||||||
"""Send a message to a Zulip chat.
|
"""Send a message to a Zulip chat.
|
||||||
|
|
||||||
For DMs, chat_id is the user_id. For streams, format is
|
For DMs, chat_id is the user_id. For streams, format is
|
||||||
"stream_name:topic". Sends a placeholder first if this is the
|
"stream_name:topic". Sends a placeholder first if this is the
|
||||||
first message in a turn, then edits it on subsequent calls.
|
first message in a turn, then edits it on subsequent calls.
|
||||||
|
|
||||||
|
Accepts **kwargs for Hermes Gateway compatibility.
|
||||||
"""
|
"""
|
||||||
# Determine target type and IDs
|
# Determine target type and IDs
|
||||||
is_dm = not chat_id or ":" not in chat_id
|
is_dm = not chat_id or ":" not in chat_id
|
||||||
@@ -925,19 +928,42 @@ class ZulipAdapter(BasePlatformAdapter):
|
|||||||
message_id: str,
|
message_id: str,
|
||||||
content: str,
|
content: str,
|
||||||
metadata: Optional[Dict[str, Any]] = None,
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
) -> bool:
|
**kwargs: Any,
|
||||||
"""Edit a previously sent Zulip message (for placeholder replacement)."""
|
) -> 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)
|
truncated = _truncate(content)
|
||||||
payload = {
|
payload = {
|
||||||
"message_id": int(message_id),
|
|
||||||
"content": truncated,
|
"content": truncated,
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
resp, _ = await self._api_call("PATCH", "/api/v1/messages", data=payload)
|
resp, status = await self._api_call(
|
||||||
return resp is not None
|
"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:
|
except Exception as e:
|
||||||
logger.warning("[%s] Edit message %s error: %s", self.name, message_id, 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:
|
async def send_typing(self, chat_id: str, metadata: Optional[Dict] = None) -> None:
|
||||||
"""Send typing indicator to a Zulip chat."""
|
"""Send typing indicator to a Zulip chat."""
|
||||||
@@ -975,12 +1001,14 @@ class ZulipAdapter(BasePlatformAdapter):
|
|||||||
return {"name": chat_id, "type": "dm"}
|
return {"name": chat_id, "type": "dm"}
|
||||||
|
|
||||||
async def delete_message(
|
async def delete_message(
|
||||||
self, chat_id: str, message_id: str, metadata: Optional[Dict] = None
|
self, chat_id: str, message_id: str,
|
||||||
) -> bool:
|
metadata: Optional[Dict] = None,
|
||||||
|
**kwargs: Any,
|
||||||
|
) -> SendResult:
|
||||||
"""Delete a message via Zulip API."""
|
"""Delete a message via Zulip API."""
|
||||||
# Zulip doesn't support message deletion via API for bots
|
# Zulip doesn't support message deletion via API for bots
|
||||||
# Send an empty edit instead
|
# 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
|
# Gen 2: Self-test diagnostics
|
||||||
|
|||||||
Reference in New Issue
Block a user