文档: 提交重整处方与在飞收尾
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
# DevFlow 集成三方 IM + 自定义 Web:AI Chat 远程接入规划
|
||||
|
||||
> 创建: 2026-10-04 | 状态: 📐 规划设计(待评审)
|
||||
> 上级索引: [../INDEX.md](../INDEX.md) | 姊妹篇: [F-260620-01-跨端AIChat-微信小程序](../已编号方案/F-260620-01-跨端AIChat-微信小程序-2026-06-20.md)
|
||||
|
||||
## 一、目标与范围
|
||||
|
||||
在**飞书、企业微信、钉钉**三个 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 引擎**:零改动
|
||||
Reference in New Issue
Block a user