Skip to content

feat: 新增 Discord 渠道接入 - #82

Open
aurevian-biz wants to merge 15 commits into
OpenBMB:mainfrom
aurevian-biz:feat/discord-channel
Open

feat: 新增 Discord 渠道接入#82
aurevian-biz wants to merge 15 commits into
OpenBMB:mainfrom
aurevian-biz:feat/discord-channel

Conversation

@aurevian-biz

Copy link
Copy Markdown

Summary

数字员工现在可以接入 Discord 作为第 5 个消息渠道。在此之前接入渠道仅支持微信、企业微信、飞书、钉钉;本 PR 让用户能在控制台配置 Discord Bot Token,通过 Gateway 长连接接收消息、经 REST API 回复,复用现有渠道无关内核(入站 staging、出站 outbox、身份服务、凭证生命周期)。

实现方式

完全遵循既有渠道接入模式(以钉钉线程模式为模板),无内核结构性改动:

  • 适配器backend/app/channels/adapters/discord.py):normalize / send / start_ingress / stop_ingress 协议实现 + 每绑定一线程的 DiscordStreamManager(daemon 线程 + 独立 event loop + 5s reconcile),错误分类沿用 PermanentError / TransientError 分层
  • 入站持久化service_discord_inbox.py + discord_runtime.py):stage-before-ACK 模式,(binding_id, event_id) 幂等,绑定围栏校验(channel/active/revision/account-key),envelope 版本化 replay
  • 出站投递send() 经 Discord REST POST /channels/{id}/messages,长文本按 2000 字符分片,idempotency_key 稳定派生为 nonce(≤25 字符,分片间可复现)
  • 生命周期:凭证保存端点(Bot Token 校验经 GET /users/@me)、discord:bot:{len}:{id} 外部账号键、旧 bot 标识符不可变规则、_quiesce_binding_or_409 暂停/恢复衔接
  • 前端:渠道卡片 + DiscordSetup.tsx 配置界面(含 Message Content Intent 启用提示)

关键设计决策

决策 选择 理由
运行模式 线程模式(每绑定一线程 + 独立 loop) discord.py 2.x 无模块级 event loop 隐患,无需飞书式子进程隔离
会话建模 DM:dm:{author};群聊:session_id=channel_id, group_id=guild_id 贴合既有 conv_key = group_id or session_id 协议
出站目标 channel_id(Discord 无 context_token 体系) 回复/通知统一走 target.channel_id
幂等 outbox 状态机 + nonce 派生 分片重试可复现同一 nonce
Reaction 未实现(延后) 与 MVP 范围一致

验证

  • 后端:渠道核心 5 文件 140 passed + 其他渠道 3 文件 35 passed;ruff 全过;全库 1299 passed(11 个失败均为未触碰子系统,非回归)
  • 前端:vitest 13 文件 40 项全绿;npm run build(tsc + vite)通过
  • 线上实证:真实 Bot Token 配置后 connected=True,Discord 发消息 → AgentLoop 回复 delivered(含群聊与 DM 双场景);另附 3 轮真实 bug 修复(500 / 未接入 / 无回信)均由 Oracle 复核闭环

测试清单

  • test_channel_discord.py(487 行):normalize/send/validate/stage 幂等/fence/stream manager 生命周期/nonce 映射
  • test_discord_api.py:凭证端点(200/400/409/502/凭证不泄漏/不可变标识符)
  • test_channel_outbox.py:discord 投递 target 校验 + daemon→真实 adapter 集成 + 创建者告警跳过

风险与说明

  • 需要 Message Content Intent:未启用时群聊非 @bot 消息 content 为空,normalize 返回 None(UI 有启用提示)
  • 崩溃接管路径service_intake.py:794)在事件卡 processing 时重建的 target 不含 channel_id,discord 该窄窗口投递会失败——先于本 PR 已存在,未恶化,建议后续迭代补充
  • 本 PR 不含 Reaction 能力与真实网关集成测试(需真实 token)

Compound Engineering

@hm1229
hm1229 requested a review from fadeoreo August 9, 2026 07:05
@fadeoreo

Copy link
Copy Markdown
Collaborator

@aurevian-biz
你好,我注意到 PR #82 中的 commit 作者信息显示为 sunxu heli_9902@hotmail.com,这个邮箱是我的邮箱,但我并未授权在你的 Git 提交中使用它。
请不要使用他人的邮箱作为 Git author,并请尽快修改这些 commit 的 author 信息后强制更新 PR。建议使用你自己 GitHub 账号绑定的邮箱,或者使用 GitHub 提供的 noreply 邮箱。
修改后请确认 PR 中不再出现我的邮箱。谢谢。

@aurevian-biz

Copy link
Copy Markdown
Author

我没有主观故意性,应该是提交时没修改git的帐号,周四我会修改后再次提交。

@fadeoreo

Copy link
Copy Markdown
Collaborator

好的,十分感谢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants