mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-09 04:40:45 +08:00
Scheduled outbound only sent text via pollOutboundQueue; collect deliverable attachments from the turn, encode them in source JSON, and send via sendReplyWithAttachments. Co-authored-by: Cursor <cursoragent@cursor.com>
116 lines
4.6 KiB
Python
116 lines
4.6 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
from runtime.scheduler.channel_delivery import deliver_scheduled_reply
|
|
from runtime.scheduler.whatsapp_mentions import encode_whatsapp_outbound_source
|
|
from svc.persistence.sqlite_store import SqliteStore
|
|
|
|
|
|
class WhatsappAttachmentDeliveryTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self._tmp = tempfile.TemporaryDirectory(ignore_cleanup_errors=True)
|
|
self.db = Path(self._tmp.name) / "wa_attach.sqlite"
|
|
self.store = SqliteStore(str(self.db))
|
|
tenant = self.store.create_tenant("Team")
|
|
self.tenant_id = str(tenant["id"])
|
|
sess = self.store.create_session("WA scheduled")
|
|
self.session_id = str(sess.id)
|
|
|
|
def tearDown(self) -> None:
|
|
self._tmp.cleanup()
|
|
|
|
def test_encode_whatsapp_outbound_source_with_attachments(self) -> None:
|
|
atts = [{"name": "report.xlsx", "mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "data_base64": "abc"}]
|
|
raw = encode_whatsapp_outbound_source(
|
|
mention_jids=["111@lid"],
|
|
attachments=atts,
|
|
media_path="/tmp/report.xlsx",
|
|
)
|
|
data = json.loads(raw)
|
|
self.assertEqual(data.get("mention_jids"), ["111@lid"])
|
|
self.assertEqual(data.get("attachments"), atts)
|
|
self.assertEqual(data.get("media_path"), "/tmp/report.xlsx")
|
|
|
|
def test_list_pending_whatsapp_outbound_includes_attachments_from_source(self) -> None:
|
|
source = encode_whatsapp_outbound_source(
|
|
attachments=[{"name": "a.txt", "data_base64": "dGVzdA=="}],
|
|
media_path="D:/tmp/a.txt",
|
|
)
|
|
self.store.enqueue_channel_outbound_message(
|
|
channel="whatsapp",
|
|
chat_id="120363012345678@g.us",
|
|
text="file attached",
|
|
tenant_id=self.tenant_id,
|
|
account_id="wa-default",
|
|
source=source,
|
|
)
|
|
items = self.store.list_pending_channel_outbound_messages(channel="whatsapp", account_id="wa-default", limit=5)
|
|
self.assertEqual(len(items), 1)
|
|
self.assertEqual(len(items[0].get("attachments") or []), 1)
|
|
self.assertEqual(items[0].get("media_path"), "D:/tmp/a.txt")
|
|
|
|
def test_deliver_scheduled_reply_encodes_tool_attachments_for_turn(self) -> None:
|
|
turn_uuid = "turn-wa-attach-1"
|
|
self.store.add_message(
|
|
session_id=self.session_id,
|
|
role="tool",
|
|
content='{"ok": true}',
|
|
turn_uuid=turn_uuid,
|
|
event_type="tool_result",
|
|
attachments=json.dumps(
|
|
[
|
|
{
|
|
"type": "binary_ref",
|
|
"attachment_id": "att-1",
|
|
"name": "daily.xlsx",
|
|
"mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
"deliverable": True,
|
|
}
|
|
],
|
|
ensure_ascii=False,
|
|
),
|
|
)
|
|
delivery = {
|
|
"whatsapp": {
|
|
"enabled": True,
|
|
"target_type": "group",
|
|
"chat_id": "120363012345678@g.us",
|
|
"account_id": "wa-default",
|
|
},
|
|
"weixin": {"enabled": False},
|
|
}
|
|
with mock.patch(
|
|
"runtime.scheduler.channel_delivery._prepare_channel_outbound_attachments",
|
|
return_value=(
|
|
[{"name": "daily.xlsx", "mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "data_base64": "ZGF0YQ=="}],
|
|
"",
|
|
),
|
|
):
|
|
result = deliver_scheduled_reply(
|
|
self.store,
|
|
tenant_id=self.tenant_id,
|
|
reply_text="今日报表已生成",
|
|
delivery_json=json.dumps(delivery, ensure_ascii=False),
|
|
session_id=self.session_id,
|
|
turn_uuid=turn_uuid,
|
|
)
|
|
self.assertTrue(result.get("ok"), result)
|
|
pending = self.store.list_pending_channel_outbound_messages(
|
|
channel="whatsapp",
|
|
account_id="wa-default",
|
|
limit=5,
|
|
)
|
|
self.assertEqual(len(pending), 1)
|
|
source = json.loads(str(pending[0].get("source") or "{}"))
|
|
self.assertEqual(len(source.get("attachments") or []), 1)
|
|
self.assertEqual(source["attachments"][0].get("name"), "daily.xlsx")
|
|
self.assertEqual((result.get("channels") or {}).get("whatsapp", {}).get("attachments"), 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|