346 lines
25 KiB
Markdown
346 lines
25 KiB
Markdown
# 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 引擎**:零改动
|
||
|
||
## 附录A、PostgreSQL 多租户 × DevFlow 结合分析(§十 S3 展开论证)
|
||
|
||
### A.1 概念:多租户三模式
|
||
|
||
| 模式 | 结构 | 优点 | 缺点 | 适合 |
|
||
|---|---|---|---|---|
|
||
| **行级隔离** | 同库同表,每行 `tenant_id` 列,查询强制 WHERE | 成本最低、迁移跑一份、跨租户统计易 | 隔离最弱(漏写 WHERE 即泄漏)、noisy neighbor | 租户多单租户数据小,SaaS 主流 |
|
||
| **独立 Schema** | 一实例每租户一 schema | 隔离较强,按 schema 备份 | 租户多时爆炸;DDL 迁移跑 N 遍 | 租户几百内 |
|
||
| **独立 Database** | 每租户一库 | 最强隔离 | 资源贵、连接池复杂、跨租户查询难 | 租户少而大、合规严 |
|
||
|
||
行级隔离通常配合 **PG RLS(Row Level Security)**:租户过滤下沉数据库层——session 设 `SET app.tenant_id`,策略自动过滤,应用层漏写 WHERE 也不泄漏。这是 PG 多租户的核心王牌。
|
||
|
||
### A.2 激活时机
|
||
|
||
DevFlow 当前是本地优先单机应用(SQLite/单用户/零运维),「租户」不存在。多租户仅在 **S3 AI 引擎上云**时被激活:SQLite 单写者模型扛不住云端多用户并发写,且「本地优先」范式失效——隔离必须显式设计。**多租户是需求,PostgreSQL 是载体**(PG 因并发写 + RLS + 生态成为默认答案)。
|
||
|
||
### A.3 租户模型与选型
|
||
|
||
- 租户模型:`tenant`=团队(付费主体),`user`=成员;现有全部表(projects/tasks/ideas/workflows/ai_messages/knowledge/audit…)挂 `tenant_id`
|
||
- 选型:**行级隔离 + RLS**(非 schema/database 隔离)。决定性理由是迁移演进节奏:V1-V16+ 已 20+ 表且快速迭代,per-tenant schema 下每次迁移要循环跑 N 遍并处理失败重试,直接拖死迭代速度;行级隔离迁移只跑一份
|
||
|
||
### A.4 落点三抓手
|
||
|
||
1. **df-storage trait 层**(对齐 F-07 下沉思路):存储访问收敛 Repository trait,多租户化 = trait 实现层注入租户上下文(依赖 PG session 变量),上层 commands 无感——现有分层红利
|
||
2. **迁移体系**:SQLite 手写迁移换 sqlx/refinery 版本化迁移,一套脚本跑一份
|
||
3. **RLS 策略**:每表 `USING (tenant_id = current_setting('app.tenant_id')::uuid)`,连接池(pgbouncer)按事务设租户变量
|
||
|
||
### A.5 配套改造清单(多租户 ≠ 换数据库驱动)
|
||
|
||
缓存键带租户(防 Redis 串数据)/ 对象存储按租户前缀隔离 / 日志审计按租户切分 / 备份恢复按租户粒度。**全链路改造**——这正是 §十 把 PG 多租户列入「显式不做」的原因:现在做 = 为不存在的需求付全链路成本。
|
||
|
||
### A.6 与本期规划的交集
|
||
|
||
唯一交集 = P0 已预留的会话映射表 `owner_user_id` 列(S2 时是「用户归属」,S3 升级语义为「租户内用户」),成本≈0。时序红线重申:S2 各人数据仍在各自桌面端 SQLite,云端只有路由表,**不需要 PG**;S3 才引入 PG+RLS,与引擎多租户化统一做。
|
||
|
||
## 附录B、引入云端后的多人架构模式(C4 视图)
|
||
|
||
> 按 C4 模型整理:C1 上下文(现状基线 → S2 多人 → S3 引擎上云)+ C2 容器(网关内部)+ 部署视图 + 数据归属演进表。
|
||
> 贯穿不变量:**TunnelCommand/TunnelEvent 是网关↔执行端唯一契约**,执行端可从「桌面端 df-tunnel」无缝换成「云端 df-agent」,网关与 IM 端零改动。
|
||
|
||
### B.1 C1 上下文 —— 现状基线(S0:单机 + 小程序遥控)
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph local["💻 用户本地(数据主权 100% 在个人)"]
|
||
desktop["DevFlow 桌面端 (Tauri v2)<br/>AI Chat 引擎(Agentic Loop+审批) · SQLite · df-tunnel(Agent)"]
|
||
end
|
||
subgraph cloud["☁️ 云端 u-relay.1216.top(nginx TLS 终止)"]
|
||
relay["u-relay :9180<br/>channel_id 配对 · payload 透传零业务耦合"]
|
||
end
|
||
mini["📱 df-miniapp 微信小程序<br/>(Commander)"]
|
||
mini <-->|"WSS"| relay
|
||
relay <-.->|"WS Agent 出站穿NAT<br/>单 channel 配对"| desktop
|
||
```
|
||
|
||
### B.2 C1 上下文 —— S2 团队多人(云端路由化,数据仍归各人)
|
||
|
||
本期 IM 网关落地后的直接形态:**云端只有「路由与审计」,业务数据仍在各桌面端**。
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph users["👥 多人入口"]
|
||
direction LR
|
||
im["飞书 / 钉钉 / 企微<br/>企业机器人"]
|
||
web["Web Chat<br/>浏览器/手机"]
|
||
mini["df-miniapp<br/>微信小程序"]
|
||
end
|
||
|
||
subgraph cloud["☁️ 云端(nginx TLS 终止)"]
|
||
direction TB
|
||
gw["df-im-gateway :9190<br/>平台适配器 · 会话映射 · 白名单<br/>节流聚合 · 审批分级 · 审计"]
|
||
relay["u-relay :9180<br/>多 channel 配对转发"]
|
||
gw <-->|"WS Commander(多channel)<br/>TunnelCommand / TunnelEvent"| relay
|
||
end
|
||
|
||
subgraph deskA["用户A 本地"]
|
||
dA["DevFlow 桌面端<br/>AI引擎 + SQLite(A) · df-tunnel"]
|
||
end
|
||
subgraph deskB["用户B 本地"]
|
||
dB["DevFlow 桌面端<br/>AI引擎 + SQLite(B) · df-tunnel"]
|
||
end
|
||
|
||
im --> gw
|
||
web <-->|"HTTP/WS"| gw
|
||
mini <-->|"WSS Commander"| relay
|
||
relay <-.->|"WS Agent · chan-userA"| dA
|
||
relay <-.->|"WS Agent · chan-userB"| dB
|
||
```
|
||
|
||
**路由链路**:IM 消息 → 网关查映射表 `chat_id → (owner_user_id, channel_id, conv_id)` → 发 `TunnelCommand::Send` 到对应 channel → 该用户桌面端执行。**用户隔离靠 channel 隔离**(一人一 channel,per-channel token 为 u-relay 演进观察项)。
|
||
|
||
### B.3 C2 容器 —— df-im-gateway 内部(适配器 trait 分层,S4 扩展点)
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph adapters["平台适配器层(各平台差异收敛于此)"]
|
||
feishu["feishu_adapter<br/>长连接+卡片流式"]
|
||
dingtalk["dingtalk_adapter<br/>Stream Mode"]
|
||
wecom["wecom_adapter<br/>回调验签+AES"]
|
||
webui["web_adapter<br/>WS 直连+静态页"]
|
||
end
|
||
subgraph core["核心(平台无关,S4 加端零改动)"]
|
||
unify["统一模型<br/>InboundEvent / OutboundAction"]
|
||
sess["会话映射表 (SQLite)<br/>chat_id | conv_id | owner_user_id | platform | channel_id"]
|
||
throttle["节流聚合器<br/>TextDelta 时间窗"]
|
||
acl["白名单 + 审批分级"]
|
||
audit["审计日志<br/>IM消息 ↔ TunnelCommand"]
|
||
unify --> sess
|
||
sess --> throttle
|
||
acl --> sess
|
||
sess --> audit
|
||
end
|
||
relay["u-relay WS Commander"]
|
||
feishu --> unify
|
||
dingtalk --> unify
|
||
wecom --> unify
|
||
webui <--> unify
|
||
core <-->|"TunnelCommand / TunnelEvent"| relay
|
||
```
|
||
|
||
### B.4 C1 上下文 —— S3 引擎上云(云端多人完整形态,PG 多租户)
|
||
|
||
执行端从「各人桌面端」切换为「云端 df-agent 服务」,**同一协议**,网关/IM 端零改动;桌面端退化为瘦客户端/管理台,本地优先形态仍可用(不废弃)。
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph users["👥 多人入口"]
|
||
direction LR
|
||
im["飞书/钉钉/企微"]
|
||
web["Web Chat"]
|
||
end
|
||
subgraph cloud["☁️ 云端"]
|
||
direction TB
|
||
gw["df-im-gateway<br/>(零改动)"]
|
||
relay["u-relay<br/>(零改动)"]
|
||
agent["df-agent 云端执行服务<br/>AI 引擎(Agentic Loop) · 工具沙箱<br/>多会话/多租户调度"]
|
||
gw <--> relay
|
||
relay <-.->|"同协议<br/>TunnelCommand / TunnelEvent"| agent
|
||
end
|
||
subgraph data["数据层(附录A 落点)"]
|
||
pg[("PostgreSQL<br/>行级 tenant_id + RLS<br/>projects/tasks/messages/audit")]
|
||
redis[("Redis<br/>租户前缀缓存键")]
|
||
oss[("对象存储<br/>租户前缀隔离")]
|
||
end
|
||
thin["💻 桌面端=瘦客户端/管理台<br/>本地 SQLite 留个人配置"]
|
||
im --> gw
|
||
web <--> gw
|
||
agent --> pg
|
||
agent --> redis
|
||
agent --> oss
|
||
thin <-.-> relay
|
||
```
|
||
|
||
### B.5 部署视图(S2 落地形态,单机双服务 + nginx)
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph inet["互联网"]
|
||
u["用户 IM / 浏览器 / 小程序"]
|
||
end
|
||
subgraph server["云端主机(u-relay 同机,复用 nginx+systemd 模式)"]
|
||
nginx["nginx :443 TLS 终止<br/>/ws/* → 9180<br/>/im/* /chat/* → 9190"]
|
||
ur["u-relay :9180<br/>systemd · musl 单二进制 ~3.6MB"]
|
||
gig["df-im-gateway :9190<br/>systemd · musl 单二进制<br/>静态 Web Chat 页托管"]
|
||
nginx --> ur
|
||
nginx --> gig
|
||
end
|
||
subgraph homes["各用户本地"]
|
||
dt["DevFlow 桌面端<br/>出站 WSS → /ws/agent"]
|
||
end
|
||
u -->|"wss://u-relay.1216.top"| nginx
|
||
dt <-.->|"出站穿NAT"| nginx
|
||
```
|
||
|
||
### B.6 数据归属与信任边界演进表
|
||
|
||
| 维度 | S0 现状 | S2 团队多人 | S3 引擎上云 |
|
||
|---|---|---|---|
|
||
| 身份/会话映射 | 桌面端 Settings | **网关 SQLite**(owner/channel 列已预留) | 网关 → 并入 PG |
|
||
| 项目/任务/工作流 | 桌面端 SQLite | **各桌面端 SQLite**(主权在个人) | PG(tenant_id+RLS) |
|
||
| AI 消息/溯源 | 桌面端 ai_messages | 各桌面端 | PG |
|
||
| IM↔指令审计 | — | 网关审计日志 | PG(租户维度) |
|
||
| 信任边界 | 个人设备 | 云端只见「指令与脱敏结果」 | 云端见全部业务数据(需租户隔离+合规) |
|
||
| 桌面端角色 | 全栈主体 | 执行主体 | 瘦客户端/管理台(可选保留本地优先) |
|
||
|
||
### B.7 演进的三条设计不变量
|
||
|
||
1. **协议不变性**:网关↔执行端唯一契约是 TunnelCommand/TunnelEvent(df-tunnel crate 类型),S3 换执行端零成本——这是全方案最重要的远期红利
|
||
2. **u-relay 纯转发零耦合**不破例:业务逻辑只进 df-im-gateway / df-agent,中继永远轻
|
||
3. **数据主权渐进上移**:S0/S2 数据在个人(本地优先不被废弃),S3 才集中上云并配套 RLS 隔离——每一步都由真实需求触发,不过度设计
|