Files
wechat-hermes-gateway/docs/老莫消息路由设计.md

4.9 KiB
Raw Permalink Blame History

老莫微信消息 → serve session 路由设计方案

2026-05-20 目标:老莫给机器人号发微信,小小莫也能看到,不依赖莫荷转述


现状

你微信 → wxhelper TCP (:19099) → wechat_agent.py
                                          ↓
                                  Hermes API (:8642)
                                          ↓
                                    莫荷回复你

莫荷独占所有微信消息。小小莫只能被动等她转述。


目标

你微信 → wxhelper TCP → wechat_agent.py ─┬→ Hermes API → 莫荷 (不变)
                                          └→ opencode serve (:4096) → 小小莫看到

新增一条岔路:老莫的消息同时写入 serve session,小小莫可主动查看。


方案对比

方案 Asubprocess 调用 opencode run --attach --message

做法wechat_agent.py 的 process_msg() 里加一段:

def fork_to_session(fu, ct):
    """将消息写入 opencode serve session (非阻塞)"""
    if fu != "wxid_c0a6izmwd78y22":
        return  # 只转发老莫
    try:
        import subprocess
        subprocess.run(
            ["opencode", "run", "--attach", "http://localhost:4096",
             "--password", "hermes123",
             "--session", SESSION_ID,
             "--message", f"[老莫] {ct}"],
            capture_output=True, timeout=10,
            env={**os.environ, "PYTHONHOME": ""}
        )
    except Exception as e:
        log(f"FORK ERR (non-fatal): {e}")
方面 评估
复杂度 低,~10 行代码
对现有链路影响 ,fork 是独立线程,失败不影响 Hermes
session ID 稳定性 ⚠️ serve 重启后 ses_xxx 会变 → 需想办法拿到当前 ID
性能开销 subprocess 每次约 1-2 秒,但独立线程不阻塞主流程
serve 密码硬编码 ⚠️ 已经在代码库(hermes123),无新增风险
可靠性 subprocess 可能因 PATH/PYTHONHOME 问题失败

方案 B:直接 HTTP POST 调用 serve API

做法:抓包分析 opencode run --attach 的 HTTP 协议,直接用 urllib.request POST

# 伪代码,serve API 协议未知,需逆向
urllib.request.urlopen("http://localhost:4096/api/session/inject", 
    data=json.dumps({"session": SID, "message": "[老莫] xxx"}))
方面 评估
复杂度 未知,需逆向 serve API
性能 纯 HTTP,无 subprocess 开销
稳定性 ⚠️ 非官方 API,版本更新可能不兼容

方案 C:写 inbox 文件 + 小小莫轮询

做法wechat_agent 写文件,小小莫定期读取

方面 评估
复杂度 最低
即时性 需要轮询,无法实时

关键风险

1. session ID 稳定性(最核心)

opencode run --attach 需要 session ID。每次 serve 重启后,当前 TUI session 的 ID 可能变化:

  • 如果 serve 重启 → 老 session 消失 → 新 session 新 ID → 需要更新 wechat_agent 里的配置
  • 解决思路:用 session 名称而不是 ID,或每次启动时自动获取

2. 不对莫荷通信造成任何影响

铁律fork 到 session 的代码必须:

  • 在独立线程中运行
  • 捕获所有异常
  • 设置超时(≤10 秒)
  • 永远不阻塞 call_hermes()send_wx()

3. 循环消息风暴

如果我不小心回了一条 [老莫] 到 sessionwechat_agent 不能把它再 fork 一次。

  • 现有的 is_self 检查已经过滤自己发送的消息
  • 但如果 serve session 的消息被 serve 再推给 wechat_agent... 需要确认不会发生

4. opencode CLI 在 wechat_agent 环境中是否可用

wechat_agent 以 $env:PYTHONHOME='' 启动,opencode.cmd 可能也依赖 Python。

  • 需测试:从 Python subprocess 能否直接调用 opencode run --attach --message

推荐方案

方案 Asubprocess)最稳妥:

  1. 对现有链路零影响
  2. 改动最小
  3. 可以逐步优化(先 subprocess,后改 HTTP API

待确认事项

  1. serve session ID 如何维护?

    • 能否用固定名称?还是每次启动获取?
    • 如果 serve 重启导致 ID 变了,wechat_agent 如何感知?
  2. opencode run --attach --message 是否支持在 Python subprocess 中调用?

    • 需要验证 CLI 安装路径和调用方式
  3. 是否需要前缀路由?

    • 是全部消息都 fork
    • 还是只有特定前缀(如 [小小莫] 开头的消息)才 fork

验证清单

实现后验证:

  • 老莫发微信 → 莫荷正常回复(链路不变)
  • 老莫发微信 → serve session 能看到消息(新增)
  • opencode run --attach 超时/失败 → 莫荷通信不受影响
  • 老莫连续发多条 → 都能看到
  • wechat_agent 重启后依然工作
  • serve 重启后 session ID 变化时能自动适配