Files
weixin_ClawBot_Bridge/docs/04-bridge-design.md
T

7.6 KiB
Raw Blame History

04 — Bridge(转接器)架构设计指南

目标读者:要把微信 ClawBot 接到自己已有 AI 项目的开发者。 本文档不绑定具体语言,给出模块划分、状态模型、对接模式和可靠性设计。

1. Bridge 的职责边界

Bridge 是一个薄适配层,职责只有:

iLink 长轮询 ──▶ 消息规范化 ──▶ 调用你的 AI 后端 ──▶ 回复格式化 ──▶ sendmessage

Bridge 不负责:

  • 对话历史/记忆管理(那是 AI 后端的事,除非后端无状态)
  • 业务逻辑、工具调用编排
  • 用户体系、计费

保持薄的好处:协议变了只改 Bridge;AI 后端可以独立演进、独立测试。

2. 推荐模块划分

bridge/
├── ilink/
│   ├── client.*        # HTTP 封装:请求头、鉴权、X-WECHAT-UIN、超时
│   ├── auth.*          # 扫码登录流程(get_bot_qrcode / get_qrcode_status)
│   ├── poller.*        # 长轮询主循环、游标管理、退避重试
│   ├── sender.*        # sendmessage / sendtyping / 分片发送
│   └── media.*         # getuploadurl、CDN 上传下载、AES-128-ECB
├── store/
│   ├── account.*       # bot_token / ilink_bot_id / baseurl 持久化
│   ├── cursor.*        # get_updates_buf 持久化(每次更新立即落盘)
│   └── context.*       # peer_id → context_token 映射持久化
├── normalize.*         # WeixinMessage → 内部统一消息模型
├── backend.*           # 你的 AI 项目的调用封装(HTTP / SDK / 进程)
└── main.*              # 装配 + 启动 + 优雅退出

参考:官方包 @tencent-weixin/openclaw-weixin 的目录结构(auth/ api/ cdn/ messaging/ monitor/ config/ storage/)几乎就是这个划分;Java SDK 的门面模式(OpenClawWeixinSdk 统一封装 QrLoginFlowService / WeixinApiClient / WeixinLongPollMonitor / MediaUploadService)也值得对照。

3. 必须持久化的三类状态

状态 内容 更新时机 丢失后果
账号凭据 bot_token、ilink_bot_id、ilink_user_id、baseurl 扫码成功时 需重新扫码
同步游标 get_updates_buf 每次 getupdates 响应后立即 重复收到历史消息
上下文令牌 peer_id → context_token 每条入站消息 无法回复/主动消息送达不到

实现建议:

  • 单机用 JSON 文件或 SQLite 就够(官方包就是文件存储,Java SDK 用 FileAccountStore / FileContextTokenStore / FileSyncCursorStore)
  • 游标落盘要同步写(或至少 flush),崩溃丢游标 = 重启后消息轰炸
  • 文件加个简易锁,防止多开实例写坏状态

4. 与 AI 后端的对接模式

按你的 AI 项目形态选一种:

模式 A:HTTP API 后端(最常见)

poller.onMessage(msg):
    reply = http_post("http://127.0.0.1:8000/chat", {
        "session_id": msg.peer_id,        # 用微信用户 ID 当会话 ID
        "text": msg.text,
        "attachments": msg.media_paths
    })
    sender.send_text(msg.peer_id, reply.text, msg.context_token)
  • 会话 ID 直接映射微信 from_user_id,天然一对一私聊
  • 后端无状态的话,Bridge 也不存历史;有状态则后端自己管

模式 B:本地 SDK / 库调用

Bridge 与 AI 项目同进程(或同语言直接 import),把消息对象传给 Agent 函数,拿回字符串。参考 cc-weixin 把 Claude Agent SDK 的 query() 包一层。

模式 C:异步任务队列

AI 处理慢(深度研究、图像生成)时:

1. 收到消息 → 立即回复「收到,处理中」(可选:sendtyping)
2. 任务入队,worker 处理
3. 完成后用保存的最新 context_token 主动 sendmessage

⚠️ 注意 24h 窗口限制(见 06 文档):任务完成后主动推送必须在窗口内才送得到。慢任务一定要设计超时兜底文案。

模式 D:多通道网关(进阶)

如果以后还要接 Telegram/飞书/钉钉,把「规范化消息模型 + 统一网关」抽出来,iLink 只是其中一个 adapter。直接参考 OpenAkita 的架构:Adapter → UnifiedMessage → Gateway → Agent,发送路径反向。第一版不用做,但内部消息模型(见 03 文档第 7 节)建议一开始就用。

5. 可靠性设计

5.1 长轮询主循环

伪代码:

loop:
    try:
        resp = getupdates(cursor, timeout=server_timeout + 10s)
        if resp.ret == 0:
            if resp.get_updates_buf: cursor.save(resp.get_updates_buf)
            for msg in resp.msgs: dispatch(msg)
            backoff.reset()
        elif resp.errcode == -14:
            pause_account(1h); notify("需重新扫码")
        else:
            backoff.retry()     # 2s 快速重试,连续 3 次后 30s
    except HttpTimeout:
        continue                # 长轮询正常超时
    except NetworkError:
        backoff.retry()

5.2 消息去重

三层兜底:

  1. 游标正确持久化(治本)
  2. 应用层按消息 ID 去重(client_id / 服务端消息 ID,存最近 N 条的 set)
  3. 发送侧带唯一 client_id(防自己重发)

5.3 回复超时

  • AI 后端设硬超时(如 60s),超时回「处理超时,请重试」
  • 有资料称 24h 窗口外消息送达不到——对「用户发问 → bot 回复」场景这不是问题(立即回复),只影响主动推送

5.4 优雅退出

  • 捕获 SIGTERM/SIGINT:停 poller → 等正在处理的消息发完 → flush 状态 → 退出
  • 不要在 dispatch 中途杀进程,游标已推进但回复没发 = 用户消息被吞

5.5 可观测性

  • 结构化日志:收消息(peer、类型、长度)、发消息、游标推进、错误码、退避事件
  • 关键指标:轮询错误率、-14 出现次数、AI 后端耗时分布
  • token、context_token 不要打进日志(打 hash 前缀即可)

6. 安全注意

  • bot_token 等于这个微信 bot 的全部权限:不入 git、不进日志、文件权限 600
  • 谁扫码谁就是这个 bot 的「主人」,但任何拿到 token 的人都能收发消息——服务器上注意文件权限
  • 入站消息内容视为不可信输入:如果 AI 后端有工具调用能力(执行命令、读写文件),提示词注入风险要自己评估
  • 建议加白名单:只响应指定 from_user_id(比如就你自己),防止别人给 bot 发消息白嫖你的模型 API 额度

7. 容量与限制设计

  • 微信侧不支持 Markdown:发送前转纯文本
  • 长回复分片:按段落或固定字数(如 1500 字)切多条,注意保持顺序
  • 媒体大小:入站大图/大文件设上限,超限回复提示而不是硬下载
  • AI 后端并发:一个微信号只有一个 bot,但用户可能连发多条——dispatch 建议串行 per-peer(或按 peer 加锁),避免回复乱序

8. 测试策略

  • 协议层:把 iLink client 抽象成接口,测试时用 mock server 回放抓包 JSON
  • 规范化层:构造各类 WeixinMessage JSON(文本/图片/语音/图文混排/多 item)做单元测试
  • 端到端:真机扫码,用另一个微信号发消息验证
  • 回归重点:游标持久化(重启不重复收)、context_token 传递、-14 恢复流程

参考资料