fix(feishu): keep source.message_id in step with the batched event id
Text and media batching advance the coalesced MessageEvent.message_id to the newest message but left source.message_id at the first one, so after a batch the reply anchor and the event id disagreed. Advance both together at the two enqueue sites.
This commit is contained in:
@@ -2592,6 +2592,7 @@ class FeishuAdapter(BasePlatformAdapter):
|
||||
existing.timestamp = event.timestamp
|
||||
if event.message_id:
|
||||
existing.message_id = event.message_id
|
||||
existing.source.message_id = event.message_id
|
||||
self._schedule_media_batch_flush(key)
|
||||
|
||||
def _schedule_media_batch_flush(self, key: str) -> None:
|
||||
@@ -2850,6 +2851,7 @@ class FeishuAdapter(BasePlatformAdapter):
|
||||
existing.timestamp = event.timestamp
|
||||
if event.message_id:
|
||||
existing.message_id = event.message_id
|
||||
existing.source.message_id = event.message_id
|
||||
self._pending_text_batch_counts[key] = next_count
|
||||
self._schedule_text_batch_flush(key)
|
||||
|
||||
|
||||
@@ -971,14 +971,18 @@ class TestAdapterBehavior(unittest.TestCase):
|
||||
|
||||
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="张三",
|
||||
)
|
||||
|
||||
def _source(message_id: str) -> SessionSource:
|
||||
# Each inbound message carries its own source, pinned to that message's id.
|
||||
return SessionSource(
|
||||
platform=adapter.platform,
|
||||
chat_id="oc_chat",
|
||||
chat_name="Feishu DM",
|
||||
chat_type="dm",
|
||||
user_id="ou_user",
|
||||
user_name="张三",
|
||||
message_id=message_id,
|
||||
)
|
||||
|
||||
async def _sleep(_delay):
|
||||
return None
|
||||
@@ -986,13 +990,13 @@ class TestAdapterBehavior(unittest.TestCase):
|
||||
async def _run() -> None:
|
||||
with patch("plugins.platforms.feishu.adapter.asyncio.sleep", side_effect=_sleep):
|
||||
await adapter._dispatch_inbound_event(
|
||||
MessageEvent(text="A", message_type=MessageType.TEXT, source=source, message_id="om_1")
|
||||
MessageEvent(text="A", message_type=MessageType.TEXT, source=_source("om_1"), message_id="om_1")
|
||||
)
|
||||
await adapter._dispatch_inbound_event(
|
||||
MessageEvent(text="B", message_type=MessageType.TEXT, source=source, message_id="om_2")
|
||||
MessageEvent(text="B", message_type=MessageType.TEXT, source=_source("om_2"), message_id="om_2")
|
||||
)
|
||||
await adapter._dispatch_inbound_event(
|
||||
MessageEvent(text="C", message_type=MessageType.TEXT, source=source, message_id="om_3")
|
||||
MessageEvent(text="C", message_type=MessageType.TEXT, source=_source("om_3"), message_id="om_3")
|
||||
)
|
||||
pending = list(adapter._pending_text_batch_tasks.values())
|
||||
self.assertEqual(len(pending), 1)
|
||||
@@ -1005,6 +1009,10 @@ class TestAdapterBehavior(unittest.TestCase):
|
||||
second = adapter.handle_message.await_args_list[1].args[0]
|
||||
self.assertEqual(first.text, "A\nB")
|
||||
self.assertEqual(second.text, "C")
|
||||
# Coalescing advances the event id to the latest message; the reply anchor
|
||||
# (source.message_id) must move with it or replies/session tools disagree.
|
||||
self.assertEqual(first.message_id, "om_2")
|
||||
self.assertEqual(first.source.message_id, first.message_id)
|
||||
|
||||
@patch.dict(os.environ, {}, clear=True)
|
||||
def test_media_batch_merges_rapid_photo_messages(self):
|
||||
|
||||
Reference in New Issue
Block a user