fix(feishu): 修复飞书话题群中AI回复不跟帖的问题及open/proactive模式@mention检查 - #31384
fix(feishu): 修复飞书话题群中AI回复不跟帖的问题及open/proactive模式@mention检查#31384yuanchenglu wants to merge 1 commit into
Conversation
## 问题背景
在飞书话题群中,用户在一个已有话题里发送消息后,Hermes Agent 在处理过程中会
发送多条回复消息(如状态更新、中间进度等)。但之前的表现是:只有最终结果能
正确跟随在原话题下方,过程中的中间回复会变成与原话题平级的新话题(新帖子),
导致话题群中出现大量零散的小话题,用户体验极差。
## 根因分析
### 问题1:_prepare_reply_context 中 reply_to 为空
当用户在话题群中发送一条消息,该消息带有 thread_id(标识它属于某个话题),但
飞书 API 返回的消息结构中不一定包含 parent_id、upper_message_id 或 root_id。
原来的代码:
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_message_id 为 None。Gateway 在发送回复时,
如果 reply_to 为空,飞书 API 会将其当做新话题创建,而不是跟帖回复。这就是
为什么中间回复会变成独立小话题的原因。
### 问题2:_check_group_policy 中 open/proactive 模式仍需 @mention
在 _check_group_policy 方法中,原来直接检查 require_mention 标志:
if require_mention and not self._mentions_self(message):
return "group_policy_rejected"
但在 open/proactive 政策下,管理员意图是所有来自白名单用户的消息都应该被处理,
不需要 @mention。原逻辑没有考虑群策略的覆盖。
## 修复方案
### 修复1:_prepare_reply_context(~2980行)
当消息有 thread_id 但缺少 parent_id/upper_message_id/root_id 时,
使用消息自身的 message_id 作为 reply_to_message_id:
thread_id = getattr(message, "thread_id", None) or getattr(message, "root_id", None) or None
parent_id = getattr(message, "parent_id", None)
upper_message_id = getattr(message, "upper_message_id", None)
root_id = getattr(message, "root_id", None)
# 在话题群中,如果消息有 thread_id 但没有 parent/upper/root,
# 用消息自身 message_id 作为 reply_to,确保回复归属原话题
if thread_id and not parent_id and not upper_message_id and not root_id:
reply_to_message_id = message_id
else:
reply_to_message_id = parent_id or upper_message_id or root_id or None
这样 fallback 到 message_id 后,飞书 API 知道该回复属于原话题线程。
### 修复2:_check_group_policy(~3979行)
新增 _get_effective_policy() 方法获取群聊的有效政策,然后在 @mention 检查前
先判断政策类型:
# Open/proactive 模式:跳过 @mention 检查
if not require_mention or self._get_effective_policy(chat_id) in ("open", "proactive"):
return None
if not self._mentions_self(message):
return "group_policy_rejected"
### 新增方法:_get_effective_policy()
def _get_effective_policy(self, chat_id: str) -> str:
"""获取群聊的有效政策。"""
rule = self._group_rules.get(chat_id) if chat_id else None
if rule:
return rule.policy
return self._default_group_policy or self._group_policy
该方法返回指定 chat 的有效政策字符串,优先使用群级别规则,其次为默认政策。
## 修改范围
仅修改 gateway/platforms/feishu.py,+21 / -7 行,无其他文件变动。
## 验证
- 在飞书话题群中发送消息测试:所有 AI 回复(包括中间状态消息)均正确跟帖在
原话题下方,不再产生独立小话题
- open/proactive 政策群聊中:白名单用户无需 @mention 即可触发 AI 响应
|
Related prior work on Feishu topic thread replies: #11433 (thread_id as reply target when reply_to empty), #16018 (superseded by #18121), #18121 (comprehensive topic thread fix, closed), #23729/#24290 (keep group replies in group chats). The |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for identifying two concrete Feishu workflows.
Problems
- The
openpolicy bypass atgateway/platforms/feishu.py:3979changes an intentional contract: current docs require an @mention in every group-policy mode (website/docs/user-guide/messaging/feishu.md:238), whilerequire_mention: falseis the supported opt-out (:240). Current coverage deliberately asserts this foropen(tests/gateway/test_feishu.py:920). - The topic-routing portion is already covered on current main:
gateway/run.py:17921-17931carries the triggering message id through all metadata-only Feishu paths, andplugins/platforms/feishu/adapter.py:4609-4634routes replies or thread-targeted creates inside the topic.tests/gateway/test_run_progress_topics.py:451-491covers progress routing.
Suggested changes
- Re-scope any remaining report to the current plugin adapter and use the existing per-group
require_mention: falsesetting instead of coupling mention behavior toopen.
Automated hermes-sweeper review.
| return "group_policy_rejected" | ||
| if require_mention and not self._mentions_self(message): | ||
| # Open/proactive mode: accept all messages from allowed users without @mention | ||
| if not require_mention or self._get_effective_policy(chat_id) in ("open", "proactive"): |
There was a problem hiding this comment.
open is intentionally independent of mention gating: current docs require a mention in all group-policy modes (website/docs/user-guide/messaging/feishu.md:238), and current tests enforce that for open (tests/gateway/test_feishu.py:920). Use the existing global/per-chat require_mention: false override instead; current coverage is at tests/gateway/test_feishu_bot_admission.py:463-479.
|
@teknium1 Thanks for the thorough review — appreciate the detailed analysis on both points. Topic routing (change 1): Understood that how the triggering message_id is now carried through Feishu metadata-only paths on main (run.py:17921-17931), and the plugin adapter routes thread replies (adapter.py:4609-4634). Withdrawing this change as it is already covered. Open/proactive @mention bypass (change 2): You are correct — coupling mention behavior to the policy mode is the wrong approach. The existing per-group Since both changes in this PR are either already addressed on main or follow an incorrect approach, I will close this PR. Thanks again for the clear guidance. |
问题背景
在飞书话题群中,用户在一个已有话题里发送消息后,Hermes Agent 在处理过程中会发送多条回复消息(如状态更新、中间进度等)。但之前只有最终结果能正确跟随在原话题下方,过程中的中间回复会变成与原话题平级的新话题(新帖子),导致话题群中出现大量零散的小话题,用户体验极差。
根因分析
问题1:
_prepare_reply_context中 reply_to 为空当用户在话题群中发送一条消息,该消息带有
thread_id(标识它属于某个话题),但飞书 API 返回的消息结构中不一定包含parent_id、upper_message_id或root_id。原来的代码:当这三个字段都为空时,
reply_to_message_id为None。Gateway 在发送回复时,如果 reply_to 为空,飞书 API 会将其当做新话题创建,而不是跟帖回复。问题2:
_check_group_policy中 open/proactive 模式仍需 @mention在
_check_group_policy方法中,原来直接检查require_mention标志:但在 open/proactive 政策下,管理员意图是所有来自白名单用户的消息都应该被处理,不需要 @mention。原逻辑没有考虑群策略的覆盖。
修复方案
修复1:
_prepare_reply_context(~2980行)当消息有
thread_id但缺少parent_id/upper_message_id/root_id时,使用消息自身的message_id作为reply_to_message_id:这样 fallback 到
message_id后,飞书 API 知道该回复属于原话题线程。修复2:
_check_group_policy(~3979行)+ 新增_get_effective_policy()新增
_get_effective_policy()方法获取群聊的有效政策,然后在 @mention 检查前先判断政策类型:Open/proactive 政策下跳过 @mention 检查:
修改范围
仅修改
gateway/platforms/feishu.py,+21 / -7 行,无其他文件变动。验证