wechat-auto-reply-requirements.md 8.21 KB

微信自动回复 · 需求文档

日期: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 · 读取上下文 —— ✅ 不写模块,走 skill 配方(2026-07-09)

结论:Hermes 是有 shell+SQL 的 agent,已有 wechat-db-decrypt skill,环节2 无需新代码。

  • 给 skill 补了「读会话上下文」一节(~/.hermes/skills/wechat-db-decrypt/SKILL.md,仓库留档 wechat_plain/scripts/auto-reply/skill/):一次拷库查齐 ①发送者身份 rcontact(显示名优先级 conRemark>nickname>alias)②最近 N 条 message 历史(剥群 wxid: 前缀、type→占位符、只喂文本)③引用 refermsg 解析 + 群名;末尾给出喂 env3 的上下文骨架。
  • 真机验证配方查询产出干净上下文(身份+时间正序历史)。
  • 架构澄清:环节 3(生成)= Hermes 这个 LLM 本身;环节 4(策略)= 它的推理;只有环节 4/5 的「审核队列 + viewer 接发送」还需写代码。
  • 二期加分:回链 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 里存的微信标识字段(二期确认)