# 微信自动回复 · 需求文档 > 日期:2026-07-09 > 设备:Pixel(`59171FDCG0009N`),微信 8.0.74,LSPosed + Termux + Hermes Agent > 定位:Pixel 上的 Hermes Agent 自动处理"别人发给小火子的微信"——私聊 / 群里 @ / 群里引用——判断要不要回、怎么回、自动发还是人工审核。 --- ## 0. 目标 有人给小火子发微信(私聊、群 @我、群引用我)时,Hermes 能: 1. 接收到这条消息 2. 读取会话上下文 3. 基于上下文 + SOUL.md 生成回复 4. 判断"直接发"还是"进人工审核队列" 5. 发送回复(含微信原生引用气泡) 约束:尽量低电量 / 低资源;纯端上(Hermes 在设备 Termux 内跑,模型走 Kimi 或本地 llama-swap)。 --- ## 1. 设备现状(建这套的地基,2026-07 核对过) | 能力 | 现状 | 备注 | |---|---|---| | 微信 DB 解密读 | ✅ 可用 | 主账号目录 `ec4f423b316d41e9af5e8398155cf105`,**key `1986554`**(`MD5("1234567890ABCDEF"+uin257966415)[:7]`);参数 `cipher_compatibility=1`+`page_size=1024`。skill `~/.hermes/skills/wechat-db-decrypt/` 已就位 | | 发送文本 | ✅ 可用 | LSPosed 内部 API(`am broadcast com.hermes.wechat.SEND_MSG`);`WeChatHook.java` 已打通文本/语音/图片 | | 发送带原生引用气泡 | ❌ 未实现 | 见环节 5 | | 通知接收 | 待搭 | NotificationListenerService / dumpsys,见环节 1 | | lifelog 人物库 | 明文 SQLite | `com.lemon.lifelog/databases/lifelog.db`(4.8MB,`Person` 表),二期打通 | | SOUL.md | ✅ 存在 | `~/.hermes/SOUL.md`(Hermes 人格) | > ⚠️ 过时提醒:旧文档 `md/wechat-auto-reply-status.md`(2026-05-23)里的 key `e03ce81` / 目录 `653cdc…` 是**次账号**,已不是当前主账号;旧文档主推的 Frida daemon 发送已废弃(常驻注入微信触发反调试崩溃)。以本文件为准。 --- ## 2. 五环节需求 ### 环节 1 · 接收通知 —— ✅ **已实现并真机验证(2026-07-09)** 落地:`wechat_plain/scripts/auto-reply/wechat_reply_watcher.py`(设备 `~/.hermes/wechat_reply/`)。 - **触发**:纯 ctypes inotify 监听当前账号 DB 目录(SELinux 放行,零轮询);建 watch 失败自动退回 stat mtime 轮询。真机验证 `[inotify] +N` 事件驱动读取成立。 - **账号自适应**:运行时 `MD5("mm"+uin)` 定位当前登录账号(验证时账号已从 火星人 切到 小火子,daemon 自动跟上,无硬编码)。 - **增量+去重+基线**:持久化 `last_msgId`;只 `isSend=0 且 msgId>last`;首跑基线=当前最大 msgId,不重放历史。 - **分类**:private / group_at_me / group_quote_me / group_other;群消息剥 `wxid:\n` 前缀取 sender+body;自身 wxid/昵称从 userinfo 自动检测。 - **输出**:`incoming.jsonl` 事件队列(供环节 2-5 消费)。自检 `--selftest`、单读 `--once`、`--tail N`。 - **常驻自启(已接)**:`wechat_reply_daemon.sh` 监督器(root + Termux 环境、单实例锁、等微信登录、看门狗崩溃重启);`/data/adb/service.d/wechat-reply-watcher.sh` 开机拉起。真机验证:纯 root(boot 上下文) selftest 通过、单实例防重、杀 watcher 自动重启。已在设备常驻运行。 - 待接:env4 里过滤 gh_ 公众号与系统消息(撤回/拍一拍);daemon.log 无限增长需加轮转(ponytail:先不做,24/7 下每天几 MB)。 原始设计记录: ### (原)环节 1 · 接收通知 —— **事件驱动,非定时轮询** 根因:费电的不是 cron 循环,是"每次轮询都 su 拷 90MB 的 EnMicroMsg.db"。定 5s 紧循环拷 90MB → 电量扛不住。 - **主触发**:常驻 NotificationListenerService。系统主动 push,空闲近零成本;微信来消息才被唤醒 → 这时才读库。没消息 = 不动。 - **兜底**:Hermes cron 每几分钟扫一遍,捞免打扰 / 漏掉的消息。**不要跑紧循环。** - **读库**:优先只读 in-place 打开(immutable);锁住再拷。因为改成事件驱动,拷库只在真有消息时发生,频率极低,可接受。 - **消息源**:主账号 `ec4f…/EnMicroMsg.db` 的 `message` 表,`WHERE isSend=0 AND msgId>last_processed_id`。 - **分流(本环节难点)**: - 私聊:直接是一条 - 群 @我:群消息 content 前缀 `wxid:\n`,需匹配我的昵称判 @ - 群引用我:看 refermsg 是否指向我的 svrid ### 环节 2 · 读取上下文 - 从 `message` 表取该会话最近 N 条 + 发送者身份(`rcontact` 昵称/备注)。 - **二期加分**:回链 lifelog `Person` 库做人物增强("这个人是谁、跟小火子什么关系")。一期不做。 ### 环节 3 · 生成回复 - Hermes(Kimi / 本地 llama-swap):**上下文 + SOUL.md → 回复**。 - 建议一次结构化调用同时出 `{should_reply, confidence, draft, risk_flags}`,别拆两次。 - ⚠️ 若回复要以"小火子本人"口吻发出,SOUL.md 里可能需加一段"小火子语气"约定(否则像 agent 替他说话)。 ### 环节 4 · 自动 vs 审核 —— **白名单直发,其余进 viewer 待回复** - **白名单**(联系人 / 群 / 群里某发言人)+ 生成成功 → **直接发送**。 - **非白名单** → 写入 **Pixel 本地 wechat viewer 的"待回复列表"**,人工点击"发送"才真正发出。 - 落地新增:①「待回复队列」存储(sqlite/json);② wechat viewer 的"发送"按钮接到发送链路。 - 安全红线(贯穿):涉钱 / 承诺 / 约时间 / 低置信 → 即使白名单也建议进审核。 ### 环节 5 · 发送回复带引用(原生气泡) 需求 = 点原文→引用→发送后显示引用气泡。两条实现路: - **(a) A11y UI 自动化(一期推荐)**:长按目标气泡 → 点"引用" → 输入 → 发送。驱动微信自己 UI → **产出货真价实的原生引用气泡,零逆向**。代价:需微信前台、脚本略脆、比 API 慢。已有 A11y 发送服务底子。 - **(b) 内部 API 构造 refermsg(二期优化)**:微信引用 = type 49 appmsg + refermsg(type 57) 指向被引 svrid。一整块新逆向,量级同当初啃发图,重。留作提速。 --- ## 3. 贯穿层(不做会出事) - **防循环/去重**:只处理 `isSend=0`;持久化 per-talker `last_processed_msgId`;绝不回自己发的、绝不重放。 - **限流**:每人/每群回复冷却,防抖防刷屏。 - **安全红线**:陌生人 / 涉钱 / 承诺 / 约时间 → 永不自动发,硬编码兜底。 --- ## 4. 一期最小可跑(MVP) ``` 通知触发(NotificationListener) └→ 读库(主账号 ec4f/1986554, message 表, isSend=0 & msgId>last) └→ 分流(私聊/群@我/群引用我) + 取上下文(近 N 条 + rcontact 身份) └→ Hermes 生成(上下文 + SOUL.md → {should_reply,confidence,draft}) ├→ 白名单 → A11y 发送(纯文本+@;引用气泡) └→ 非白名单 → 写入 wechat viewer 待回复队列 → 人工点发送 ``` **二期**:lifelog `Person` 人物增强;内部 API refermsg 引用提速;cron 兜底调优。 --- ## 5. 待决策 / 待确认 - [ ] 白名单如何维护(配置文件 / viewer 里管理 / 从 lifelog 拉) - [ ] 待回复队列 + wechat viewer 的具体形态(现有 `wechat-web-viewer` skill 扩展?) - [ ] SOUL.md 是否加"小火子语气"段 - [ ] 群 @我 / 引用我的判定用昵称还是 wxid(昵称易误判,wxid 更准) - [ ] in-place 只读打开能否稳定绕过 WCDB 锁(否则回退拷库) - [ ] 环节 2 lifelog join key:`Person` 里存的微信标识字段(二期确认)