# Phase 4: 多平台接入 — 开发报告 > **报告日期**:2026-05-23 > **分支**:`dev` > **阶段**:Phase 4 — 多平台接入 > **总计修改文件数**:18 个 (新增 15 个, 修改 3 个) > **总代码行数**:1852 行 (Go) + 配置文件 > **编译状态**:platform-bridge ✅ / ai-core ⚠️ 网络不可用 (预存在问题) --- ## 一、背景 Phase 3 完成了插件与工具系统。Phase 4 的目标是建立统一的多平台消息接入层,让昔涟能够通过 QQ、Telegram、Webhook 等多种渠道与用户交互。 ### 核心目标 | 任务 | 说明 | |------|------| | 统一消息模型 | 所有平台消息转换为统一的 UnifiedMessage/UnifiedResponse | | 身份映射 | 平台用户 UID → Cyrene 用户的身份映射与权限管理 | | QQ OBv11 适配器 | 反向 WebSocket 连接,QQ 机器人协议适配 | | Telegram 适配器 | Bot API Webhook 模式,消息收发 + 输入状态 | | 通用 Webhook | 标准 HTTP POST 接收任意平台消息 | | 权限检查器 | admin/full/basic/restricted 四级权限,工具/设备白名单 | | WeChat/Feishu/Discord 桩 | 预留接口,待后续接入外部 SDK | --- ## 二、架构概览 ``` ┌──────────────────────────────────────────────────────┐ │ Platform Bridge (port 8095) │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ QQ OBv11 │ │ Telegram │ │ Webhook │ ... 6 适配器│ │ │ (WS 8096)│ │ (Bot API)│ │ (通用) │ │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ ┌────▼──────────────▼──────────────▼────┐ │ │ │ Platform Router │ │ │ │ ┌────────────┐ ┌─────────────────┐ │ │ │ │ │ Identity │ │ Permission │ │ │ │ │ │ Mapper │ │ Checker │ │ │ │ │ └────────────┘ └────────┬────────┘ │ │ │ └───────────────────────────┴────────────┘ │ │ │ │ │ forwardToAICore() │ │ │ │ │ ┌───────▼────────┐ │ │ │ AI-Core │ │ │ │ (port 8081) │ │ │ └────────────────┘ │ └──────────────────────────────────────────────────────┘ ``` ## 消息流程 ``` 外部平台消息 → Adapter.ToUnified() → 统一消息 → IdentityMapper.Resolve() → Permission Check → forwardToAICore() → 统一响应 → Adapter.FromUnified() → 平台消息发送 ``` --- ## 三、文件清单 ### 3.1 核心类型 (internal/bridge/) | 文件 | 行数 | 说明 | |------|------|------| | `unified.go` | 76 | UnifiedMessage, UnifiedResponse, ResponseMessage, PlatformCapabilities, PlatformMessage, Attachment, PlatformHints | | `adapter.go` | 24 | PlatformAdapter 接口 (PlatformName, ToUnified, FromUnified, Capabilities, Connect, Disconnect, IsConnected, HealthCheck) + MessageHandler 类型 | | `mapper.go` | 73 | IdentityMapper — platform:platformUID → CyreneUser 映射注册/查询/列表 | | `router.go` | 168 | PlatformRouter — 适配器注册、消息路由、通道上下文管理、响应发送 | ### 3.2 权限系统 (internal/permissions/) | 文件 | 行数 | 说明 | |------|------|------| | `permissions.go` | 115 | PlatformIdentity 结构体 + Checker 权限检查器 (四级权限: admin/full/basic/restricted)、工具白名单、IoT 设备白名单 | ### 3.3 平台适配器 (internal/adapter/) | 文件 | 行数 | 说明 | |------|------|------| | `qq/protocol.go` | 75 | OBv11 协议类型 (OBv11Message, OBv11Sender, OBv11SendMsg 等) | | `qq/adapter.go` | 394 | QQ 适配器 — 反向 WebSocket 服务器, ToUnified/FromUnified, SendMessage, ReadMessages 事件循环, markdown→QQ 格式转换 | | `telegram/adapter.go` | 251 | Telegram 适配器 — Bot API Webhook, ToUnified 支持结构化/map 两种输入, SendMessage, SendChatAction (typing 指示器) | | `webhook/adapter.go` | 121 | 通用 Webhook 适配器 — WebhookPayload/WebhookResponse 标准格式 | | `wechat/stub.go` | 50 | 微信桩 (待 WeChatFerry / 企业微信 SDK) | | `feishu/stub.go` | 50 | 飞书桩 (待 Lark Go SDK) | | `discord/stub.go` | 50 | Discord 桩 (待 discordgo) | ### 3.4 REST API (internal/handler/) | 文件 | 行数 | 说明 | |------|------|------| | `bridge_handler.go` | 149 | 路由注册, /health, /api/v1/platforms, /api/v1/identities, /api/v1/webhook/telegram, /api/v1/webhook/{platform} | ### 3.5 配置与入口 | 文件 | 行数 | 说明 | |------|------|------| | `config/config.go` | 52 | 环境变量加载 (PORT, AI_CORE_URL, QQ_BOT_PORT, TELEGRAM_BOT_TOKEN, TELEGRAM_WEBHOOK_URL) | | `cmd/main.go` | 204 | 服务入口 — 创建 mapper/checker/router, 注册 6 个适配器, 设置消息处理器, QQ 消息读取循环, 身份种子数据 | ### 3.6 DevTools 集成 (修改) | 文件 | 变更 | 说明 | |------|------|------| | `devtools/src/config.js` | +33 行 | 添加 plugin-manager 和 platform-bridge 服务配置 | | `devtools/src/process-manager.js` | +2/-2 | 添加新服务到启动顺序和 DB 检查列表 | | `backend/go.work` | +1 | 添加 platform-bridge 模块 | --- ## 四、关键设计决策 ### 4.1 导入循环解决 原始设计中 `adapter` 包定义了 `PlatformAdapter` 接口,`bridge` 包的 `router.go` 引用它,但 `adapter` 实现文件又引用 `bridge` 的类型。产生了循环依赖: ``` adapter ↔ bridge (import cycle) ``` **解决方案**:将 `PlatformAdapter` 接口和 `MessageHandler` 类型从 `internal/adapter/` 移到 `internal/bridge/adapter.go`,与它们引用的类型 (`UnifiedMessage`, `UnifiedResponse`) 放在同一包中。 同理,`permissions ↔ bridge` 循环通过将 `PlatformIdentity` 从 `bridge/mapper.go` 移到 `permissions/permissions.go` 解决。 ### 4.2 QQ 适配器的反向 WebSocket QQ 使用 OneBot v11 协议,采用反向 WebSocket 模式: - **平台桥接启动 WebSocket 服务器** (端口 8096) - **QQ 机器人框架主动连接到此端口** - 消息通过 WebSocket 双向传递 ```go // Connect 非阻塞:在 goroutine 中启动 HTTP Server mux.HandleFunc("/ws/qq", func(w, r) { upgrade(w, r) }) go srv.ListenAndServe() ``` ### 4.3 Telegram Webhook 模式 Telegram 适配器使用 Bot API webhook: - **启动时**调用 `setWebhook` 注册回调 URL - **运行时**被动接收 Telegram 服务器推送的 Update - **ToUnified** 同时支持结构化 `*TelegramUpdate` 和原始 `map[string]interface{}`,避免 HTTP handler 与适配器类型耦合 ### 4.4 桩适配器策略 WeChat、Feishu、Discord 目前为桩实现。它们实现了完整的 `PlatformAdapter` 接口但返回错误信息,提示需要哪个 SDK。这样做的好处: - 路由注册和平台列表正常工作 - 当获取到对应的 SDK 和凭据后,只需替换桩实现即可 - Auth 系统可通过 API 查看所有平台状态 ### 4.5 权限模型 ``` admin → 所有权限 (聊天/IoT操控/查询/记忆管理/系统管理/全部工具/全部设备) full → 聊天 + IoT操控 + IoT查询 + 记忆访问 basic → 聊天 + IoT查询 restricted → 仅聊天 ``` 权限检查器支持细粒度的工具白名单和设备白名单,admin 自动拥有所有权限。 --- ## 五、API 端点 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/health` | 健康检查,返回平台列表 | | GET | `/api/v1/platforms` | 列出所有平台及其能力 | | GET | `/api/v1/platforms/{name}` | 单个平台详情 | | GET | `/api/v1/identities` | 列出所有身份映射 | | POST | `/api/v1/webhook/telegram` | 接收 Telegram Bot API Update | | POST | `/api/v1/webhook/{platform}` | 接收通用 Webhook 消息 | --- ## 六、环境变量 | 变量 | 默认值 | 说明 | |------|--------|------| | `PORT` | 8095 | 桥接服务 HTTP 端口 | | `AI_CORE_URL` | http://localhost:8081 | AI-Core 地址 | | `QQ_BOT_PORT` | 8096 | QQ OBv11 WebSocket 监听端口 | | `TELEGRAM_BOT_TOKEN` | (空) | Telegram Bot API Token | | `TELEGRAM_WEBHOOK_URL` | (空) | Telegram Webhook 回调 URL | | `QQ_ADMIN_UID` | (空) | QQ 管理员 UID (种子身份) | | `TELEGRAM_ADMIN_UID` | (空) | Telegram 管理员 UID (种子身份) | --- ## 七、已知限制 1. **WeChat/Feishu/Discord 为桩** — 需要对应的 SDK 和凭据后才能启用 2. **QQ 适配器未实现心跳** — OBv11 协议中 bot 需要定期发送心跳包维持连接 3. **Telegram 未处理 callback_query** — 目前仅处理 message 类型的 Update 4. **平台桥接与 Gateway 之间无内部认证** — `forwardToAICore` 直接调用 AI-Core,绕过 Gateway。后续若需要 Gateway 统一管理会话,应通过 Gateway 的 HTTP API 而非 WebSocket --- ## 八、验证指南 ```bash # 1. 编译 platform-bridge cd backend/platform-bridge GOWORK=off go build ./cmd/main.go # 2. 启动服务 ./main # 3. 健康检查 curl http://localhost:8095/health # 4. 查看注册的平台 curl http://localhost:8095/api/v1/platforms # 5. 测试通用 Webhook curl -X POST http://localhost:8095/api/v1/webhook/webhook \ -H "Content-Type: application/json" \ -d '{"user_id":"test_user","user_name":"测试用户","content":"你好昔涟","channel_id":"test_channel"}' # 6. 查看身份映射 curl http://localhost:8095/api/v1/identities ```