Files
AgentsMeeting/gateway/docs/老莫消息路由设计.md
T
hmo 1b2b935832 Initial: multi-agent XMPP communication system with dashboard
- Platform-based architecture (Windows/Linux/Mac)
- Agent instance registry (agents.yaml)
- Management dashboard with cross-platform monitoring
- xmpp_bot with HTTP bridge + health endpoints
- wechat_agent with WeChat-Hermes bridging
- Platform services: ProcessGuardian, HealthProbe, APIRouter, ChannelBridge
- Deployment: systemd (Linux) + PowerShell (Windows)
- Monitoring: SSH+ejabberdctl for cross-platform presence
2026-06-12 21:51:36 +08:00

153 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 老莫微信消息 → 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()` 里加一段:
```python
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
```python
# 伪代码,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`
---
## 推荐方案
**方案 A**subprocess)最稳妥:
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 变化时能自动适配