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

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