Files
DevFlow/docs/02-架构设计/专项设计/devflow集成三方IM-飞书企微钉钉Web-规划设计-2026-10-04.md
T

16 KiB
Raw Blame History

DevFlow 集成三方 IM + 自定义 Web:AI Chat 远程接入规划

创建: 2026-10-04 | 状态: 📐 规划设计(待评审) 上级索引: ../INDEX.md | 姊妹篇: F-260620-01-跨端AIChat-微信小程序

一、目标与范围

在飞书、企业微信、钉钉三个 IM 内以及自定义 Web 页面中远程使用 DevFlow AI Chat:发消息、停止、重新生成、审批工具调用、切换会话——体验对齐桌面端。

范围外(本期不做):IM 内直接查看项目/任务列表等富 UI(依赖对话即入口,由 AI 工具调用返回文本结果);多人协作/团队版。

二、现状盘点(可复用的基础设施)

组件 现状 复用方式
u-relay(E:/wk-lab/u-relay) 生产运行(u-relay.1216.top:9180,nginx+systemd),channel_id 配对点对点转发,payload 透传零业务耦合,25 项测试 直接复用,IM 网关作为新 Commander 接入
df-tunnel(devflow crate) 桌面端出站 WS 隧道(Agent 角色),已实现 TunnelCommand 五指令路由(Send/Stop/Approve/Regenerate/Switch)+ TunnelEvent 四事件透传(TextDelta/ToolCall/Approval/Completed)+ 指数退避重连 零改动,桌面端不感知控制端是小程序还是 IM 机器人
df-miniapp(小程序端) F-260620-01 方案先行(Commander 模式先例) 自定义 Web 端直接套用该模式
AI Chat 引擎 Agentic Loop + 工具审批,多会话 conv_id 路由(F-09) 不动,仅靠隧道透传

核心洞察:三方 IM 机器人 + 自定义 Web = 新增的 Commander 端。桌面端(Agent)与 AI 引擎完全无感,全部新增工作收敛在「网关层」。

三、总体架构:IM 网关(df-im-gateway)

飞书 ─┐                                                        ┌─ DevFlow 桌面端 (Agent)
企微 ─┼─► df-im-gateway ──WS Commander──► u-relay ──WS Agent ──┤   df-tunnel + AI Chat 引擎
钉钉 ─┤   (新增,Rust 独立服务)            (生产已有,零改动)      │   (零改动)
Web ──┘  协议转换: IM API/回调 ↔ TunnelCommand/TunnelEvent      └─ 多桌面端=多 channel_id

df-im-gateway 职责(唯一新增组件):

  1. 以 WS Commander 身份连 u-relay(每条 channel 绑一个 DevFlow 桌面端)
  2. 接收 IM 平台事件(回调 Webhook 或长连接推送),转 TunnelCommand::Send/Stop/Approve
  3. 接收 TunnelEvent,聚合节流后调各 IM 平台消息 API 回复(流式 → 卡片刷新或一次性回复)
  4. Approval 事件 → 发交互卡片(同意/拒绝按钮)→ 点击回填 TunnelCommand::Approve
  5. IM 用户白名单 + channel_id 路由管理

为什么独立服务而不并入 u-relay:u-relay 的设计原则是「纯转发、零业务耦合、无外部依赖」。IM 对接需要凭证管理、回调验签、卡片模板、节流聚合等大量业务逻辑,塞进去会让中继失控。独立部署同机即可。

语言选型 Rust:直接 path 引用 df-tunnel 的 TunnelCommand/TunnelEvent 类型(同 workspace 或 git 依赖),编译时保证协议类型一致——这正是 F-260620-01 已论证的 Rust 中继优势。三方 IM SDK 均为 HTTP API,reqwest 直调即可,无 SDK 依赖硬伤。

三A、新组件必要性分析(df-im-gateway 为什么必须存在)

新增组件的正当性须逐一排除所有替代方案,全部不成立才立得住:

替代方案 排除理由
并入 u-relay ① u-relay 设计原则是「纯转发、payload 透传、零业务耦合、无外部依赖」,IM 对接需引入各平台 HTTP 客户端/AES 加解密/卡片模板/SQLite/节流器,塞入即毁掉其小审计面与高可用定位;② 故障域耦合:u-relay 是全局单点(小程序+IM+未来端全挂它),IM 平台 API 迭代快(钉钉卡片版本频繁),会让生产中继被迫高频重启;③ 二进制膨胀:3.6MB musl 单二进制的部署优势丧失
做进桌面端(df-tunnel/src-tauri) ① NAT 硬伤:企微回调必须公网 URL+可信 IP/域名,桌面端在内网/笔记本无法满足;飞书/钉钉长连接虽是出站,但桌面端休眠/离线时连「桌面端离线」提示都发不出(只有云端网关能兜底回复);② 桌面端会变成三套 IM 协议怪兽,Tauri 依赖拖重;③ 桌面端 IP 不固定、生命周期随人,不适合承载对外服务
Go/Node 跨语言独立服务 违背 F-260620-01 已论证的选型结论:TunnelCommand/TunnelEvent 跨语言镜像必然漂移,运行时消息丢失;Rust git 依赖 df-tunnel 类型 = 编译期协议一致 + 复用 publish-df-relay 同款 musl→scp→systemd 发布流水线。诚实 trade-off:飞书/钉钉官方 SDK 无 Rust 版需自写 HTTP 客户端,但均为标准 REST+签名协议,工作量可控
现成开源桥接器(onebot/matrix bridge 等) ① 三家 IM 官方机器人协议均非 onebot 标准,桥接器面向「自建聊天服务」场景,与「驱动本机 AI 引擎+工具审批」语义不匹配;② 审批按钮/卡片流式深度交互现成方案覆盖不了;③ 徒增第三方供应链风险
不做(维持现状) 需求价值真实:手机端随时驱动工作机 AI、审批卡片当场点掉无需回工位——是「桌面 AI 使用场景从工位扩展到任何地方」的产品能力增量,非技术炫技

结论:df-im-gateway 是「协议转换 + 凭证管理 + 公网可达性」三个约束的唯一交汇落点,必要性成立。

三B、破坏性分析(对既有系统的侵入面)

零改动承诺(桌面端/u-relay/AI 引擎)逐项压力测试,暴露真实破坏点:

受影响面 破坏性 等级 缓解/收敛策略
u-relay 双 Commander 并存语义 网关与 df-miniapp 同 channel 时:TunnelEvent 广播给两个 Commander → 双端重复回复用户;审批卡片双消费(小程序已点同意,IM 端卡片仍挂起可再点 → 重复 Approve) 🔴 唯一高危点 P0 实测 u-relay 多 Commander 投递行为;桌面端 Approve 处理按 approval_id 状态机幂等(pending→approved,二次点击无效——待 P0 验证,若无则补);过渡期运营约定同 channel 单活跃控制端;长期可演进「每端独立 channel + 桌面端多连接」(代价是破坏桌面端零改动,仅双端并存真实痛点出现时再议)
df-tunnel 协议扩展压力 IM 场景或需新指令/事件变体(如列会话、选择会话),触发桌面端升级 🟡 低 「新增变体只加不减」契约已内建向后兼容(serde #[serde(other)] 兜底);u-relay payload 透传对新变体天然无感;版本错配窗口仅存在于桌面端未升级期间
桌面端资源与连接 无新增常驻负担(仍是一条出站 WS,连接数不变) 🟢 无 —
公网暴露面 攻击面从「u-relay 一个 WS 服务」扩大到「+网关 HTTP/WS(企微回调、Web Chat 端点)」 🟡 中 网关自身不执行任何命令/写盘(纯转发,真正工具执行仍在桌面端审批门禁之后);IM 用户白名单默认拒绝;审批分级(IM 端仅低风险工具)
密钥面 三家 IM app_secret 新增落地,泄漏面 +1 🟡 中 网关 env/600 权限配置文件,不进 git;泄漏即换 secret 的应急预案
运维面 同机新增 systemd 服务(Rust 常驻 ~10-30MB)+ nginx +1 路由 🟢 低 发布节奏与 u-relay 解耦,互不牵连
数据一致性 chat_id↔conv_id 映射漂移(桌面端删会话后悬空);IM 卡片状态与桌面端真实状态漂移(审批后卡片未刷新) 🟡 低 映射悬空时网关回复「会话不存在」并自动清理重映射;卡片带状态版本号 + 过期失效文案

总结论:破坏性集中收敛于「双 Commander 并存」单点(🔴→🟡 可收敛),其余均为低危可控。零改动承诺成立——不需要为接入 IM 而改动任何现有生产组件;仅当未来「多控制端并存成常态」时才需重审 channel 架构。

四、四端集成模式对比

维度 飞书 企微 钉钉 自定义 Web
应用形态 企业自建应用 企业自建应用 企业内部应用 + 机器人 网关托管静态页或桌面端内嵌页
事件接收 长连接模式(官方 WS 推送,免公网回调)✅ HTTP 回调(GET 验签 + POST AES 加密解密,需公网 URL) Stream Mode(官方 WS 推送,免公网回调)✅ 用户浏览器直连网关 HTTP/WS
主动回复 im/v1/messages(卡片消息) 应用消息 send(Markdown 卡片) 机器人发送 + 卡片 Stream 更新 WS 推流(复用 df-miniapp 模式)
流式体验 卡片流式更新(官方支持) 消息可编辑(弱流式,节流刷新) 卡片 AI 流式更新(官方支持) 原生流式,体验最佳
审批按钮 交互卡片(最完善) 按钮交互卡片(支持但样式受限) 卡片回调按钮(支持) 页面按钮(自由发挥)
接入复杂度 中(长连接最省事) 高(回调验签/AES/IP 白名单/可信域名) 中 低(无三方审核)
前置条件 管理员后台建应用+开权限 管理员后台建应用+配置可信 IP 开放平台建应用+Stream 开关 无

接入顺序建议:Web(0 审核成本,先打通网关全链路)→ 飞书(长连接,免公网回调)→ 钉钉(Stream,同免公网)→ 企微(回调配置最繁琐,放最后)。

五、消息协议映射

IM 用户 @机器人 "把登录任务推进到 in_review"
  → 网关识别平台+用户+群聊 chat_id → 映射 conv_id(chat_id ↔ conv_id 持久化映射表)
  → TunnelCommand::Send { conv_id, content }
  → [桌面端 AI 引擎执行,ToolCall 需审批时回 TunnelEvent::Approval]
  → 网关发交互卡片 "[审批] advance_task(id=xxx, in_review)  [同意] [拒绝]"
  → 用户点同意 → TunnelCommand::Approve { conv_id, approval_id, accepted: true }
  → TunnelEvent::TextDelta(节流聚合) / Completed
  → 网关更新卡片 / 发最终回复 + 来源标注("由 DevFlow AI 生成")

关键设计点:

  1. 流式节流:IM 平台消息 API 有频控(飞书 50 QPS/应用级、企微 200 次/分钟级),TextDelta 需聚合(如 800ms 窗口批量刷卡片);P1 可先非流式(进行中卡片 → Completed 后一次性回复)
  2. 会话映射:IM chat_id(单聊/群聊)↔ conv_id 一对一映射存网关侧 SQLite;群聊内仅 @机器人 时响应
  3. 多桌面端路由:网关支持配多 channel_id(如 chan-work→工作机、chan-home→家用机),IM 指令默认路由或按前缀路由(/dev2 任务描述)
  4. 离线兜底:Agent 不在线时网关直接回「桌面端未连接」(u-relay 有 PresenceState 可查询)+ 可选指令缓存重发
  5. 消息长度:IM 单条上限(飞书卡片较大、企微 Markdown 4096 字节),超长回复分段或转摘要+附件

六、安全设计

  1. 双因子:u-relay 侧 channel_id + token 配对(已有,常量时间比较);IM 侧回调验签(飞书 encrypt key/verification token、企微 AES+签名、钉钉 Stream 免验签)
  2. 用户白名单:企业成员 user_id 白名单表(默认拒绝所有),防止应用可见范围内任何人都能驱动桌面端 AI(高危:AI 可执行命令/改数据)
  3. 审批降权:IM 端默认只允许 Approve 低风险审批(只读工具);高风险(run_command/生产写入)强制回桌面端确认——网关侧按工具风险等级过滤
  4. 凭证管理:各平台 app_id/secret 存网关本地 env/配置文件(600 权限),不进 git;token 自动续期(企微 access_token 2h 缓存)
  5. 审计:网关侧记录 IM 消息 ↔ TunnelCommand 全量日志(谁在何时通过哪个平台驱动了什么指令)

七、实施分阶段

Phase 内容 产出 预估工作量 依赖
P0 网关骨架 df-im-gateway Rust 项目:WS Commander 连 u-relay(复用 df-tunnel 类型)、会话映射表、节流聚合器、配置管理、白名单框架 可连通桌面端收发消息的骨架 + 单测 2-3 天 u-relay 生产实例(已有)
P1 Web 端 自定义 Web Chat 页(复用 df-miniapp 交互模式:流式渲染/审批按钮/会话切换)+ 网关托管 浏览器/手机浏览器可用完整 AI Chat 2-3 天 P0
P2 飞书 长连接事件订阅 + 消息卡片(流式更新)+ 交互卡片审批 + 群聊 @识别 飞书内完整可用 3-4 天 P0;管理员开应用权限
P3 钉钉 Stream Mode + 卡片流式 + 按钮回调 钉钉内完整可用 3-4 天 P0;开放平台建应用
P4 企微 回调 URL 验签 + AES 解密 + IP 白名单 + Markdown 卡片(节流伪流式)+ 按钮审批 企微内完整可用 3-4 天 P0;管理员后台配置
P5 收尾 审批分级(IM 低风险白名单)、全平台 E2E 联调、运维脚本(复用 publish-df-relay 模式发布网关)、文档 生产上线 2 天 P1-P4

总计约 15-20 人天。里程碑切法:P0+P1 完成即有「自定义 Web 远程 AI Chat」可日常自用(最快见效);P2/P3 并行推进;P4 视需求紧迫度排后。

八、风险与对策

风险 影响 对策
IM 平台 API 频控/卡片更新限制 流式体验降级 节流聚合 + 降级为「进行中→完成」两段式
企微回调配置(可信域名/IP 白名单/AES) 接入周期拉长 放 P4;提前准备备案域名与出口固定 IP
IM 端误触高危操作(命令执行/生产写入) 安全事故 审批分级:IM 端仅放行低风险工具,高危强制桌面端确认
桌面端离线/休眠 IM 无响应 离线提示 + PresenceState 感知 + 桌面端防休眠提醒
u-relay 单 token 全局配对粒度粗 多渠道管理乱 网关侧单连接多路复用(channel 维度由网关统一持有);若需多 token 再扩 u-relay
三平台 API 版本迭代(钉钉旧版机器人已停更) 维护成本 统一走各家「新版卡片 + Stream/长连接」官方推荐路径,不碰 legacy

九、待决策项

# 决策点 选项 建议
D1 网关部署位置 a) 与 u-relay 同机部署 b) 独立小鸡 a(省成本,nginx 加路由即可)
D2 df-im-gateway 与 df-tunnel 类型复用方式 a) git 依赖 df-tunnel crate b) 复制镜像类型 a(编译期类型一致,协议演进单点维护)
D3 Web 端形态 a) 独立静态页托管在网关 b) 复用 df-miniapp 代码库分支 a(小程序与 Web 场景差异渐大)
D4 IM 审批放权策略 a) 全审批 IM 可批 b) 低风险白名单 b(安全优先)
D5 飞书/钉钉/企微三个应用是否现在就申请 a) 立即申请配权限 b) 到对应 Phase 再申请 b 中的 a:飞书立即申请(管理员审批周期不可控,先启动)

十、与现有架构关系

  • F-260620-01 跨端 AI Chat:本规划是其横向扩展(Commander 端从「微信小程序」扩展到「IM 机器人 + Web」),协议与中继完全复用
  • df-mcp:对外 stdio 暴露数据层(本地进程级);本规划是远程人类入口(IM 级),互补不重叠
  • u-relay:零改动(除非 D5 触发多 token 需求)
  • df-tunnel / AI 引擎:零改动