From 51fa2d51a25142eb0d06efcabefa8154ba12dbfd Mon Sep 17 00:00:00 2001 From: fangliquan Date: Thu, 17 Sep 2026 22:40:28 +0800 Subject: [PATCH] fix(feishu): retain attachments in text batches --- plugins/platforms/feishu/adapter.py | 3 ++ tests/gateway/test_feishu.py | 44 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/plugins/platforms/feishu/adapter.py b/plugins/platforms/feishu/adapter.py index 1b3cac63d0..aa6ec796de 100644 --- a/plugins/platforms/feishu/adapter.py +++ b/plugins/platforms/feishu/adapter.py @@ -2925,6 +2925,9 @@ class FeishuAdapter(BasePlatformAdapter): return existing.text = next_text + existing.media_urls.extend(event.media_urls) + existing.media_types.extend(event.media_types) + existing.media_text_inlined.extend(event.media_text_inlined) existing._last_chunk_len = chunk_len # type: ignore[attr-defined] existing.timestamp = event.timestamp if event.message_id: diff --git a/tests/gateway/test_feishu.py b/tests/gateway/test_feishu.py index 41e12052f4..494c43177c 100644 --- a/tests/gateway/test_feishu.py +++ b/tests/gateway/test_feishu.py @@ -1029,6 +1029,50 @@ class TestAdapterBehavior(unittest.TestCase): self.assertEqual(first.message_id, "om_2") self.assertEqual(first.source.message_id, first.message_id) + @patch.dict(os.environ, {}, clear=True) + def test_text_batch_preserves_later_message_attachments(self): + from gateway.config import PlatformConfig + from gateway.platforms.event import MessageEvent, MessageType + from gateway.session import SessionSource + from plugins.platforms.feishu.adapter import FeishuAdapter + + adapter = FeishuAdapter(PlatformConfig()) + adapter.handle_message = AsyncMock() + source = SessionSource( + platform=adapter.platform, + chat_id="oc_chat", + chat_name="Feishu DM", + chat_type="dm", + user_id="ou_user", + user_name="张三", + ) + + async def _run() -> None: + await adapter._enqueue_text_event( + MessageEvent(text="first", message_type=MessageType.TEXT, source=source) + ) + await adapter._enqueue_text_event( + MessageEvent( + text="second", + message_type=MessageType.TEXT, + source=source, + media_urls=["/cache/second.md"], + media_types=["text/markdown"], + media_text_inlined=[True], + ) + ) + await adapter._flush_text_batch_now(adapter._text_batch_key(source_event)) + + source_event = MessageEvent(text="", message_type=MessageType.TEXT, source=source) + asyncio.run(_run()) + + adapter.handle_message.assert_awaited_once() + event = adapter.handle_message.await_args.args[0] + self.assertEqual(event.text, "first\nsecond") + self.assertEqual(event.media_urls, ["/cache/second.md"]) + self.assertEqual(event.media_types, ["text/markdown"]) + self.assertEqual(event.media_text_inlined, [True]) + @patch.dict(os.environ, {}, clear=True) def test_media_batch_merges_rapid_photo_messages(self): from gateway.config import PlatformConfig