# Hermes WeChat 本地闭环架构方案 > 版本: 3.0 (Node.js Plugin + SQLCipher + Frida) > 日期: 2026-05-23 > 目标设备: Pixel 10 Fold (Android) > 运行环境: Termux + Ubuntu proot-distro > 微信版本: 8.0.72 --- ## 1. 目标 在 Pixel 手机本地实现微信全自动闭环: ``` 收到消息 → 读取内容 → HTTP 调用 hermes-agent → 生成回复 → 发送回复 ``` **不依赖 Mac 远程 adb**,所有组件运行在 Android 本地。 **核心设计原则**: - **auto-reply.js** (Node.js plugin) 是常驻后台进程,负责消息检测、AI 调用、回复发送 - **hermes-agent** (lemonPCRM wrapper) 是独立的 OpenAI-compatible AI 服务,负责 LLM 推理 - 两者通过 HTTP API (`POST /v1/chat/completions`) 通信 - **SQLCipher DB 轮询** 替代 LSPosed 日志 tail,更稳定可靠 - **`am broadcast` → HermesAccessibilityService UI 自动化** 是当前唯一稳定可用的发送方式(Frida 注入 / LSPosed 反射 NetSceneSendMsg 都在 WeChat 8.0.72 上失败) --- ## 2. 架构总览 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ Pixel 手机本地运行环境 │ │ │ │ ┌───────────────────────────────────────────────────────────────────────┐ │ │ │ Ubuntu proot-distro 容器 │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ │ │ hermes-agent (:8642) │ │ │ │ │ │ ┌──────────────┐ ┌──────────┐ ┌──────────────────────────┐ │ │ │ │ │ │ │ Node.js │ │ OpenAI │ │ Claude CLI / Agents │ │ │ │ │ │ │ │ Express │ │ compat │ │ (wrapped via lemonPCRM) │ │ │ │ │ │ │ └──────────────┘ └──────────┘ └──────────────────────────┘ │ │ │ │ │ │ ↑ │ │ │ │ │ │ │ POST /v1/chat/completions │ │ │ │ │ │ │ {model, messages, stream} │ │ │ │ │ └─────────┼────────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ ┌─────────┴─────────────────────────────────────────────────────────┐ │ │ │ │ │ auto-reply.js (Node.js) │ │ │ │ │ │ ┌──────────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ │ │ │ │ SQLCipher │→ │ 新消息 │→ │ HTTP │→ │ am broadcast │ │ │ │ │ │ │ │ DB 轮询 │ │ 检测 │ │ hermes- │ │ SEND_MSG │ │ │ │ │ │ │ │ │ │ │ │ agent │ │ │ │ │ │ │ │ │ └──────────────┘ └──────────┘ └──────────┘ └──────────────┘ │ │ │ │ │ │ ↑ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌──────────────┐ ┌──────────────┴───────┐ │ │ │ │ │ │ │ sqlcipher │ │ HermesA11yService │ │ │ │ │ │ │ │ 直接查询 │ │ (lsposed-wechat- │ │ │ │ │ │ │ │ │ │ sendmsg 模块进程) │ │ │ │ │ │ │ │ │ │ UI 自动化点击微信 │ │ │ │ │ │ │ └──────────────┘ └──────────────────────┘ │ │ │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ ↑ │ │ │ │ │ │ │ │ │ ┌──────────────┐ ┌──────────┴──┐│ │ │ │ EnMicroMsg.db│ │ com.tencent ││ │ │ │ (SQLCipher) │ │ .mm 主进程 ││ │ │ └──────────────┘ └─────────────┘│ │ └───────────────────────────────────────────────────────────────────────────┘ │ │ ↑ │ │ │ │ ▼ │ │ ┌───────────────────────────────────────────────────────────────────────┐ │ │ │ Termux 环境 (与 proot 共享 home) │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ │ │ 通知监听线程(息屏兜底) │ │ │ │ │ │ termux-notification-list 每 3 秒轮询 │ │ │ │ │ │ 发现微信通知 → 点亮屏幕 → 解锁 → 启动微信 → tracker 恢复工作 │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ │ │ Termux:Boot 开机自启 │ │ │ │ │ │ ~/.termux/boot/start-hermes.sh │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ │ │ HermesWeChatSendMsg APK (含 A11y service) │ │ │ │ │ │ /data/app/com.hermes.wechat.xposed-*/base.apk │ │ │ │ │ │ 必须在 设置 → 辅助功能 中启用 HermesAccessibilityService │ │ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ └───────────────────────────────────────────────────────────────────────┘ │ │ ↑ │ │ │ │ ▼ │ │ ┌───────────────────────────────────────────────────────────────────────┐ │ │ │ Android 系统层 │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ 微信 APK │ │ SQLCipher DB │ │ 通知栏 │ │ │ │ │ │ (已 root) │ │ EnMicroMsg │ │ (微信通知) │ │ │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ └───────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────────┘ ``` --- ## 3. 数据流详解 ### 3.1 完整消息处理流程 ``` 1. 息屏状态:通知监听线程发现微信通知 │ ▼ 2. 点亮屏幕 → 解除锁屏 → 启动微信到前台(约 3-5 秒) │ ▼ 3. auto-reply.js 的 SQLCipher tracker 轮询 EnMicroMsg.db │ ▼ 4. 查询 message 表:SELECT ... WHERE msgId > last_msg_id AND isSend = 0 │ ▼ 5. 提取消息内容(单聊 / 群聊@ / 群聊引用) │ ▼ 6. 构造 OpenAI messages 数组,HTTP POST 到 hermes-agent /v1/chat/completions │ { │ "model": "hermes-agent", │ "messages": [{"role": "system", ...}, {"role": "user", ...}], │ "stream": false │ } │ ▼ 7. hermes-agent (lemonPCRM) 调用 Claude CLI 处理消息,返回 JSON │ {"choices": [{"message": {"content": "回复内容"}}]} │ ▼ 8. auto-reply.js 提取 content 作为回复文本 │ ▼ 9. 写入 /data/data/com.termux/files/home/hermes-wechat/.frida_queue/queue.jsonl │ ▼ 10. Frida Daemon(注入微信进程)读取队列,调用微信内部 API 发送消息 ``` ### 3.2 Session 管理 每个微信联系人 (`talker`) 对应一个独立的 hermes-agent session: | talker | sessionId(X-Hermes-Session-Id) | 作用 | |--------|--------------------------------|------| | `filehelper` | `wx-filehelper` | 文件传输助手 | | `wxid_abc123` | `wx-wxid_abc123` | 个人联系人 | | `123456789@chatroom` | `wx-123456789@chatroom` | 群聊 | **好处**: - hermes-agent 自动维护每个对话的上下文记忆 - 不同联系人的对话互不干扰 --- ## 4. 消息监听双通道 ### 4.1 通道 A: SQLCipher DB 轮询(主推) **原理**: sqlcipher CLI 直接查询微信加密 DB 的 message 表,检测 msgId 变化。 **流程**: ```js // AndroidWechatTrackerSQLCipher await tracker.init(); // SELECT MAX(msgId) 初始化 lastMsgId tracker.startPolling(3000); // 每 3 秒轮询 // 每次轮询执行: SELECT msgId, type, isSend, talker, content, createTime FROM message WHERE msgId > ${lastMsgId} AND isSend = 0 AND type IN (1, 10002) ORDER BY msgId ASC ``` **关键参数**: | 参数 | 值 | 说明 | |------|-----|------| | SQLCipher key | `e03ce81` | 7 字符字符串密码 | | cipher_compatibility | `1` | WCDB 兼容模式 | | cipher_page_size | `1024` | 页大小 | | 轮询间隔 | `3000ms` | 可配置 | | 查询条件 | `isSend = 0` | 只查收到的消息 | | 消息类型 | `type IN (1, 10002)` | 文本消息 + 撤回通知 | **优势**: - 不依赖 LSPosed hook(WeChat 8.0.72 上 Xposed 不稳定) - 数据完整(含群聊名称、发送者等) - 不需要复制 WAL 文件 ### 4.2 通道 B: 通知监听(息屏兜底) **原理**: 通过 Termux:API 的 `termux-notification-list` 读取系统通知栏,发现微信通知后执行屏幕唤醒流程。 **唤醒流程**: ``` 检测到微信通知 │ ▼ 屏幕关闭? → input keyevent 224 (KEYCODE_WAKEUP) │ ▼ 锁屏状态? → wm dismiss-keyguard (无密码设备) │ ▼ 微信不在前台? → am start -n com.tencent.mm/.ui.LauncherUI │ ▼ 轮询确认 screen on + unlocked + WeChat foreground(最多 20 秒) │ ▼ tracker 恢复 DB 轮询,捕获新消息 ``` **权限要求**: 1. 安装 Termux:API 应用 2. 设置 → 应用 → Termux:API → 通知访问权限 → 允许 3. 关闭 Termux 和 Termux:API 的电池优化 ### 4.3 双通道协同 ``` 正常状态: SQLCipher tracker 每 3 秒轮询 DB 息屏后微信被冻结: 微信消息到来 → 系统通知栏产生通知 │ ▼ termux-notification-list 在 3 秒内发现 │ ▼ 执行 wakeWechat() 唤醒流程(约 3-5 秒) │ ▼ 微信前台运行 → SQLCipher tracker 恢复轮询 │ ▼ 获取完整消息内容 → HTTP POST hermes-agent → 发送回复 ``` --- ## 5. Hermes-Agent HTTP API 调用 ### 5.1 API 端点 | 端点 | 方法 | 说明 | |------|------|------| | `POST /v1/chat/completions` | HTTP | OpenAI-compatible,发送消息,返回 JSON | | `GET /api/health` | HTTP | 健康检查 | ### 5.2 请求格式 ```json POST /v1/chat/completions Content-Type: application/json X-Hermes-Session-Id: wx-filehelper { "model": "hermes-agent", "messages": [ {"role": "system", "content": "你是 lemonAI 助手..."}, {"role": "user", "content": "收到微信私聊消息(来自 filehelper):你好\n请给出自然、简短、得体的中文回复。只输出回复内容,不要加任何解释。"} ], "stream": false } ``` ### 5.3 响应格式 ```json { "choices": [ { "message": { "role": "assistant", "content": "你好!很高兴收到你的消息。" } } ] } ``` auto-reply.js 提取 `choices[0].message.content` 作为最终回复。 --- ## 6. 消息发送 ### 6.1 发送机制(Frida Daemon — 主推) Frida Daemon 注入微信主进程,通过 Java.perform 调用微信内部 API: ``` auto-reply.js │ ├── 写入队列文件 /data/data/com.termux/files/home/hermes-wechat/.frida_queue/queue.jsonl │ {"talker": "filehelper", "content": "回复内容", "id": "msg_xxx"} │ ▼ Frida Daemon(注入微信进程) │ ├── 读取 queue.jsonl │ ▼ Java.perform → 调用微信内部发送 API │ ▼ 微信服务器 ``` **前置条件**: 1. frida-server 运行中 2. frida_daemon.js 已注入微信进程 ### 6.2 发送机制(LSPosed Broadcast — 备用) 当 Frida Daemon 不可用时,回退到 am broadcast: ```bash /system/bin/am broadcast \ -a com.hermes.wechat.SEND_MSG \ --es toUser "filehelper" \ --es content "回复内容" ``` ### 6.3 发送限制 | 限制 | 说明 | |------|------| | 仅文本消息 | 当前只支持文本 | | Frida 依赖 | 需要 frida-server + 注入的 daemon | | 微信主进程 | 发送必须在微信主进程存活时 | --- ## 7. 开机自启(Termux:Boot) ### 7.1 启动脚本 文件: `~/.termux/boot/start-hermes.sh` ```bash #!/bin/bash # 启动 frida-server if [ -f "/data/data/com.termux/files/home/hermes-wechat/bin/frida-server" ]; then su -c "/data/data/com.termux/files/home/hermes-wechat/bin/frida-server &" fi # 启动微信(如果未运行) if ! su -c "pgrep -x com.tencent.mm" > /dev/null 2>&1; then su -c "am start -n com.tencent.mm/.ui.LauncherUI" sleep 5 fi # 启动 hermes-agent (lemonPCRM) — 在 proot 内 export PATH=/data/data/com.termux/files/usr/bin:$PATH proot-distro login --shared-home ubuntu --user ubuntu -- bash -c \ "cd /data/data/com.termux/files/home/hermes-wechat && . .env && node server/index.js &" sleep 5 # 启动 auto-reply plugin proot-distro login --shared-home ubuntu --user ubuntu -- bash -c \ "cd /data/data/com.termux/files/home/hermes-wechat/server/services/wechat && MY_WXID=xxx MY_NICKNAME=xxx node auto-reply.js &" # 发送启动通知 termux-notification \ --title "Hermes WeChat" \ --content "自动回复已启动" \ --priority low ``` ### 7.2 安装步骤 ```bash mkdir -p ~/.termux/boot cp setup_termux_boot.sh ~/.termux/boot/start-hermes.sh chmod +x ~/.termux/boot/start-hermes.sh ``` --- ## 8. 目录结构 ``` ~/hermes-wechat/server/services/wechat/ # 主 plugin ├── auto-reply.js # 主入口 ├── android-wechat-tracker-sqlcipher.js # **主推** 消息跟踪 ├── android-wechat-sender-frida.js # **主推** 消息发送 ├── android-wechat-tracker.js # 备用消息跟踪 ├── android-wechat-sender.js # 备用消息发送 ├── index.js # 统一入口 └── README.md # plugin 文档 ~/local-testkit/ # 备用 daemon / 工具 ├── hermes_wechat_daemon.py # 备用 Python 守护进程 ├── config.json # 运行时配置 ├── keepalive.sh # 保活脚本 ├── test_env.py # 环境预检 ├── test_send_msg.py # 发送消息测试 ├── run_all_tests.sh # 一键测试 └── docs/ ├── README.md # 使用文档 ├── HERMES_WECHAT_ARCHITECTURE.md # 本方案文档 ├── REVERSE_ENGINEERING_LOG.md ├── NOTIFICATION_STRATEGY.md └── plan.md /sdcard/hermes/ # 运行时数据 ├── dbs/ # DB 副本(备用方案用) ├── wechat_msgs.jsonl # 消息日志(备用方案用) └── auto-reply.log # auto-reply plugin 日志 ``` --- ## 9. 配置说明 ### auto-reply.js 环境变量 | 变量 | 默认值 | 说明 | |------|--------|------| | `MY_WXID` | — | 你的微信 wxid(必填) | | `MY_NICKNAME` | — | 你的微信昵称(必填,用于判断群聊@) | | `HERMES_HOST` | `127.0.0.1` | hermes-agent API 地址 | | `HERMES_PORT` | `8642` | hermes-agent API 端口 | | `NOTIFICATION_ENABLED` | `true` | 是否启用通知监听兜底 | ### config.json(Python daemon 备用) ```json { "db_src_path": "", "db_copy_dir": "/sdcard/hermes/dbs", "sqlcipher_key": "e03ce81", "cipher_compatibility": 1, "cipher_page_size": 1024, "poll_interval_sec": 10, "max_msgs_per_poll": 50, "hermes": { "api_url": "http://localhost:3010/api/master/chat", "timeout_sec": 120 }, "auto_reply": { "enabled": false, "contacts": ["filehelper"], "exclude_types": [10000], "cooldown_sec": 5 }, "send": { "method": "am_broadcast", "broadcast_action": "com.hermes.wechat.SEND_MSG", "am_path": "/system/bin/am" }, "logging": { "level": "INFO", "file": "/sdcard/hermes/daemon.log" } } ``` **注意**:主流程(auto-reply.js)不读取 config.json,所有配置通过环境变量传入。 --- ## 10. 部署步骤 ### Step 1: 环境准备 ```bash # Pixel Termux 中 pkg update pkg install python sqlcipher termux-api # 安装 Termux:Boot 和 Termux:API 应用(F-Droid 或 GitHub) # 关闭电池优化(Termux / Termux:API / 微信) ``` ### Step 2: 部署 hermes-agent (lemonPCRM) ```bash # 在 proot Ubuntu 中 cd ~/hermes-wechat npm install # 配置 .env 中的 Claude API key npm start # 或 npm run dev(热重载) ``` 确认 hermes-agent 监听 `127.0.0.1:8642`: ```bash curl http://127.0.0.1:8642/v1/chat/completions \ -X POST -H "Content-Type: application/json" \ -d '{"model":"hermes-agent","messages":[{"role":"user","content":"hi"}]}' ``` ### Step 3: 部署 Frida Daemon ```bash # 1. 确保 frida-server 运行 su -c "/data/data/com.termux/files/home/hermes-wechat/bin/frida-server &" # 2. 注入 daemon 到微信进程(从 Mac 或手机端) frida -U -n com.tencent.mm -l frida_daemon.js ``` ### Step 4: 部署 auto-reply plugin ```bash cd ~/hermes-wechat/server/services/wechat export MY_WXID=wxid_xxxxxx export MY_NICKNAME=你的昵称 export HERMES_HOST=127.0.0.1 export HERMES_PORT=8642 nohup node auto-reply.js > auto-reply.log 2>&1 & ``` ### Step 5: 启动保活脚本 ```bash cd ~/local-testkit chmod +x keepalive.sh nohup ./keepalive.sh > keepalive.log 2>&1 & ``` ### Step 6: 设置开机自启 ```bash cp setup_termux_boot.sh ~/.termux/boot/start-hermes.sh chmod +x ~/.termux/boot/start-hermes.sh ``` --- ## 11. 故障排查 ### Q: DB 轮询报错 "database is locked" **A**: 微信正在写入 DB 时 sqlcipher 尝试打开。tracker 已对此静默处理,会在下次轮询重试。如频繁出现,可增大轮询间隔。 ### Q: sqlcipher 解密失败 **A**: 1. 确认 key 正确:`e03ce81` 2. 确认 cipher_compatibility=1 和 cipher_page_size=1024 3. 直接测试:`sqlcipher /path/to/EnMicroMsg.db "PRAGMA key='e03ce81'; PRAGMA cipher_compatibility=1; SELECT COUNT(*) FROM message;"` ### Q: hermes-agent API 调用超时 **A**: 1. 确认 hermes-agent 已启动:`curl http://127.0.0.1:8642/api/health` 2. 检查 hermes-agent 日志是否有 Claude CLI 调用错误 3. 增加 `HERMES_TIMEOUT`(Claude 推理可能需要 30-60 秒) ### Q: Frida 发送失败 **A**: 1. 确认 frida-server 运行中:`ps aux | grep frida-server` 2. 确认 frida_daemon.js 已注入微信进程 3. 检查队列文件权限:`ls -la /data/data/com.termux/files/home/hermes-wechat/.frida_queue/queue.jsonl` 4. 备用方案:回退到 `sendTextMessageBroadcast()` ### Q: 息屏后完全失效 **A**: 1. 确认电池优化已关闭(Termux / Termux:API / 微信) 2. 检查 `keepalive.sh` 是否运行 3. 检查通知权限:Termux:API 是否有通知访问权限 4. 检查日志:`tail -f auto-reply.log` 看是否有 `[NOTIF]` 或 `[WAKE]` 日志 ### Q: termux-notification-list 返回空 **A**: 1. 确认 Termux:API 应用已安装 2. 确认已授予通知访问权限 3. 发送一条测试消息,等待通知出现 --- ## 12. 版本演进 | 版本 | 日期 | 主要变更 | |------|------|---------| | 1.0 | 2026-05-20 | 初始方案:Mac adb + Python daemon | | 2.0 | 2026-05-22 | Pixel 本地方案:LSPosed 日志 tail + am broadcast + SSE API | | **3.0** | **2026-05-23** | **SQLCipher DB 轮询 + Frida 发送 + OpenAI-compatible API** | --- ## 13. 安全与风险提示 1. **微信封号风险**: 自动化操作存在被检测风险,建议使用测试小号 2. **Root 权限**: 需要 Magisk root 3. **Frida 注入**: 需要 frida-server 常驻运行 4. **API Key**: Claude API key 仅在 hermes-agent 中配置,plugin 不持有 --- ## 14. 扩展方向 - [ ] 支持群聊 @识别和回复 - [ ] 支持图片/语音消息处理 - [ ] 本地 LLM 部署(减少 API 延迟) - [ ] Web UI 管理界面 - [ ] 多账号支持