严重程度
普通 —— 但在繁忙的公共话题中会造成严重干扰:重复点击“重试”会导致该话题被大量重复的机器人帖子淹没,因此对成员而言,看起来像是机器人在“自行发帖/陷入循环”。
平台
- 服务器:Discourse 核心
main分支(2026.7.x 系列),在最新的origin/main(dbf5eedac40,2026-07-14)上复现。discourse-ai已集成在核心中。 - 客户端:在多种浏览器/设备上复现(桌面版 Chrome、Android Chrome、iOS Safari)—— 由于问题出在服务器端,客户端无关紧要。
描述
实际结果: 在公共话题中,点击 AI 机器人回复上的重试按钮,会向话题追加一个全新的机器人帖子。原始回复保持不变,因此每次重试都会增加一个新帖子。N 次重试 → N 个额外帖子。
预期结果: 重试应就地重新生成现有的机器人回复(替换其内容),就像在 AI 机器人的私信/直接消息对话中那样。不应创建新帖子。
复现步骤(基于全新的 Discourse)
- 启用 Discourse AI + AI 机器人;创建/启用一个 AI **代理(角色)并关联一个机器人用户,开启“允许话题提及”**功能以便其能在公共话题中回答(
allow_topic_mentions)。将你的用户组添加到代理的允许组以及ai_bot_allowed_groups中。 - 在一个公共话题中,在帖子中
@提及机器人以触发其回复。 - 在机器人的回复上,打开帖子管理/扳手菜单,点击重试(重新生成操作 →
POST /discourse-ai/ai-bot/post/:post_id/retry)。 - 观察: 会追加一个新的机器人回复,而不是重新生成现有的回复。重复点击重试 → 每次增加一个额外帖子。
- 作为对比,在与机器人的私信中执行相同操作:重试会正确地就地重新生成(无重复)。私信与公共话题之间的这种差异即为关键线索。
在公共话题中 100% 复现。
根本原因(代码指针,当前 origin/main)
BotController#retry_response(plugins/discourse-ai/app/controllers/discourse_ai/ai_bot/bot_controller.rb)将Jobs::CreateAiReply加入队列,并传入reply_post_id: post.id—— 即“重新生成此现有帖子”。Jobs::CreateAiReply将其加载为reply_post并传递给Playground#reply_to(..., existing_reply_post: reply_post)。- 在
Playground#reply_to(plugins/discourse-ai/lib/ai_bot/playground.rb)中:stream_reply = post.topic.private_message? if stream_reply.nil?→ 对于公共话题结果为false(约第 518 行)。existing_reply_post仅在if stream_reply分支内被使用(reply_post = existing_reply_post,约第 538 行)。- 非流式
else分支(约第 662 行)无条件执行PostCreator.create!(...),追加一个新帖子,且从未触及正在重试的帖子。
因此,对于任何非私信话题,retry_response 中“就地重新生成”的意图被静默丢弃,转而创建了重复帖子。(这种不对称性也意味着公共话题的机器人回复是非流式的,这是既有的行为;具体的 bug 在于重试路径上忽略了 existing_reply_post。)
建议的修复方案(仅方向)
无论是否流式,都应尊重 existing_reply_post —— 例如,在非流式分支中,如果存在 existing_reply_post,则对其进行 revise(修订)而不是调用 PostCreator.create!;或者将“复用现有帖子”的决策与 stream_reply 解耦。
安全模式
不适用 —— 服务器端插件行为,与主题/站点 JS 无关。