From a79b0ec46157efc91537e634a3dcc44a76f6dc7e Mon Sep 17 00:00:00 2001 From: Kathy Date: Sat, 18 Apr 2026 00:26:38 +0800 Subject: [PATCH] fix: keep Feishu topic replies from falling back to new threads (local patch) Co-Authored-By: Claude Opus 4.6 --- gateway/platforms/base.py | 23 ++++++++++++++++++++--- gateway/platforms/feishu.py | 13 ++++++++++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/gateway/platforms/base.py b/gateway/platforms/base.py index 78e0dd7e25..4d611fdaa5 100644 --- a/gateway/platforms/base.py +++ b/gateway/platforms/base.py @@ -2506,7 +2506,13 @@ class BasePlatformAdapter(ABC): _r = await self._send_with_retry( chat_id=event.source.chat_id, content=_text, - reply_to=event.message_id, + reply_to=( + event.reply_to_message_id + if event.source.platform == Platform.FEISHU + and event.source.thread_id + and event.reply_to_message_id + else event.message_id + ), metadata=thread_meta, ) if _eph_ttl > 0 and _r.success and _r.message_id: @@ -2606,7 +2612,13 @@ class BasePlatformAdapter(ABC): _r = await self._send_with_retry( chat_id=event.source.chat_id, content=_text, - reply_to=event.message_id, + reply_to=( + event.reply_to_message_id + if event.source.platform == Platform.FEISHU + and event.source.thread_id + and event.reply_to_message_id + else event.message_id + ), metadata=_thread_meta, ) if _eph_ttl > 0 and _r.success and _r.message_id: @@ -2810,10 +2822,15 @@ class BasePlatformAdapter(ABC): # Send the text portion if text_content: logger.info("[%s] Sending response (%d chars) to %s", self.name, len(text_content), event.source.chat_id) + _reply_anchor = ( + event.reply_to_message_id + if event.source.platform == Platform.FEISHU and event.source.thread_id and event.reply_to_message_id + else event.message_id + ) result = await self._send_with_retry( chat_id=event.source.chat_id, content=text_content, - reply_to=event.message_id, + reply_to=_reply_anchor, metadata=_thread_metadata, ) _record_delivery(result) diff --git a/gateway/platforms/feishu.py b/gateway/platforms/feishu.py index a6b522c4a2..ac920bab69 100644 --- a/gateway/platforms/feishu.py +++ b/gateway/platforms/feishu.py @@ -2757,9 +2757,11 @@ class FeishuAdapter(BasePlatformAdapter): if hint: text = f"{hint}\n\n{text}" if text else hint + thread_id = getattr(message, "thread_id", None) or getattr(message, "root_id", None) or None reply_to_message_id = ( getattr(message, "parent_id", None) or getattr(message, "upper_message_id", None) + or getattr(message, "root_id", None) or None ) reply_to_text = await self._fetch_message_text(reply_to_message_id) if reply_to_message_id else None @@ -2791,7 +2793,7 @@ class FeishuAdapter(BasePlatformAdapter): chat_type=self._resolve_source_chat_type(chat_info=chat_info, event_chat_type=chat_type), user_id=sender_profile["user_id"], user_name=sender_profile["user_name"], - thread_id=getattr(message, "thread_id", None) or None, + thread_id=thread_id, user_id_alt=sender_profile["user_id_alt"], is_bot=is_bot, ) @@ -4227,6 +4229,15 @@ class FeishuAdapter(BasePlatformAdapter): if active_reply_to and not self._response_succeeded(response): code = getattr(response, "code", None) if code in _FEISHU_REPLY_FALLBACK_CODES: + if (metadata or {}).get("thread_id"): + logger.warning( + "[Feishu] Reply to %s failed in thread %s (code %s — message withdrawn/missing); " + "skipping top-level fallback to avoid creating a new topic", + active_reply_to, + (metadata or {}).get("thread_id"), + code, + ) + return response logger.warning( "[Feishu] Reply to %s failed (code %s — message withdrawn/missing); " "falling back to new message in chat %s",