-
send_voice_tts_via_hook 的最后一步从 send_voice_via_hook(SEND_VOICE_INTERNAL) 改为 send_voice_cgi_via_hook(SEND_VOICE_CGI)——让 Hermes 的 send_wechat_voice_tts MCP 工具(wechat-voice-sender skill 调的)走已验证的 uploadvoice cgi 全合成路: 音频上传+投递接收方+发送方本地已发送气泡。docstring 同步更新。 已 adb push 同步到设备 ~/.hermes/event_bus/(android_mcp.py + wechat_hook_send.py), 设备 wechat-image-sender skill 也更新为调 send_wechat_image MCP 工具(弃旧 ACTION_SEND UI 模拟)。设备文件权限修为 termux uid 可读(原 root:root 导致 MCP 子进程 import 失败)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
新 skill voice-synth-send:一段文本合成为语音,作为微信语音消息发给联系人。 全程在 Pixel Termux 内跑(Hermes 环境),无需 Mac、无需本地 TTS 模型。 - voice_synth.sh: text → edge-tts(默认,免费云) / 豆包 seed-audio(可选,需额度) → MP3 → ffmpeg 16k mono PCM → silk-wasm SILK V3 → stage 进微信数据目录 → SEND_VOICE_CGI。 引擎 edge|doubao;音色可选;豆包 key 走 DOUBAO_KEY 环境变量(不入库)。 - 澄清 edge-tts 是云 TTS(非本地模型,无需 key/GPU,联网即用);本机 Termux 已具备 python/edge-tts/node/silk-wasm/ffmpeg。 - SKILL.md: 用法/引擎对比/真机验证/坑(TMPDIR、SILK 权限、adb-su 无 DNS 是测试 artifact 非 skill bug)。 真机验证 2026-07-07:edge-tts(6.9s)+豆包 seed-audio(8.2s) 均发火星人成功,多分块上传 完整可播放,发送方本地已发送气泡。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
三种消息在使用层齐了(文字/图片/语音全走内部 API 全合成): - wechat_send.sh voice: 弃用旧 SEND_VOICE_INTERNAL(hot-swap 相关),改走 SEND_VOICE_CGI 全合成。SILK 须 WeChat 进程可读——动态取 WeChat uid(stat /data/user/0/com.tencent.mm), stage 进 /data/data/com.tencent.mm/files/ + chown + restorecon(/sdcard EACCES、 root cp 进沙盒需正确 owner+ctx)。 - wechat_hook_send.py: 新增 send_voice_cgi_via_hook(同上 staging + 广播 SEND_VOICE_CGI)。 - android_mcp.py: send_wechat_voice 改调 send_voice_cgi_via_hook,docstring 更新为全合成。 - skill_wechat_send/SKILL.md: 语音段改写为 SEND_VOICE_CGI 全合成用法。 真机验证:wechat_send.sh voice + MCP send_voice_cgi_via_hook 均 status=sent + hook svrMsgId>0(uploadvoice cgi 服务器接受)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
sendVoiceViaCgi 之前只上传+投递给接收方,发送方本地无记录。补上: - cgi 前把 SILK 写到 voice2/msg_<voiceId>.amr(进程内写,以 WeChat uid,避开 外部 root cp 被 SELinux categories 挡)供本地回放。 - w11.r0 Object 构造器插入 f9 语音气泡(voicemsg XML + voiceId 经 hookF9ImgPathInjector 注入)。 - convertTo hook 新增 sVoiceCgiInsert 标志:cgi 路已上传+投递,强制 status=4 (已发送),否则发送方气泡永远转圈「正在发送中」(hot-swap 路仍不强制,靠 H())。 真机 filehelper 对比验证:16:17(修复前)绿气泡转圈无时长 → 16:22(修复后)干净 「3" 语音条」已发送。接收方(火星人/Mac)收到能播 + 发送方本地正常显示 = 端到端 双向闭环。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
真机肉眼确认:SEND_VOICE_CGI 纯合成语音在 filehelper 渲染成绿色语音条(多条 2"/4"/6"/3" 全无红叹号=投递成功)。文档 §2 改写为全合成实现(分块 cv6 → modelbase.o 构造 → i.l()+pq5.g.l() 订阅派发),hot-swap 降级为旧路。TL;DR 新增 SEND_VOICE_CGI 行。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
修好派发:裸 z2.b(g) 不 wire 回调 → 场景永不完成、dv6 空。正确派发 = modelbase.i.l()(注册响应消费者 d + 返回 pq5.g deferred)+ pq5.g.l(timeoutMs) 终端订阅触发 cgi。加 sVoiceCgiKeepAlive 强引用防 deferred 弱持有的 i 被 GC。 真机 filehelper 验证(纯合成,无录音/无 hot-swap): RESP try=1 svrMsgId(11)=6727180359918674774 VOICECGI-RESULT errType=0 errCode=0 errMsg=null respClass=r45.dv6 = 服务器接受请求(errCode=0) + 分配 msgId(>0) = 投递成功。 诊断 hook hookVoiceCgiResult(modelbase.i onSceneEnd 按签名定位) 确认 errCode。 广播 SEND_VOICE_CGI --es to --es src_path <SILK> --ei duration。SILK 须 WeChat 进程可读(用其自身 voice2 文件或 chown 到 WeChat uid;/sdcard 会 EACCES)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
按捕获的 wire 协议实现全合成语音(无录音、无 hot-swap): - 读 SILK → 按 6000 字节分块 → 每块建 r45.cv6 请求 pb([0]self [1]talker [2]offset [3]len [4]"newSendVoice_"+voiceId [6]dur [7]cu5(SILK切片) [8]end [11]msgsource [12]=4)→ 经 modelbase.o 13参构造器(绕过 modelbase.l 字段名 base≠tinker 不匹配) → modelbase.i.p(o)(按签名定位) → scene modelbase.g(m1) → z2.b(scene) 入队(同文字发送)。 - 广播 SEND_VOICE_CGI --es to --es src_path <SILK> --ei duration。 真机 filehelper 测试:反射全部解析成功,scene=com.tencent.mm.modelbase.g, z2.b 提交 1 块无异常(silk=2593B dur=2000)。投递确认待(设备屏幕 doze + 需第二账号);已知待补:[15] long 字段省略、本地 f9 气泡未插、cgi 响应 getLong(11) 未校。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
真机 hook 追踪确认本机语音走 jg0.x.w 内联 cgi 分支(非 CDN 引擎 addSendTask, 那是 send_use_cdn_upload=1 的机器才走)。内联路可 z2.b 全合成,复用文字同队列。 新增追踪 hook: - hookCdnTrace: h2.d(addSendTask)/l1.keep_onUpload*/jg0.x.u — 证实 CDN 路本机不触发。 - hookVoiceCgiCapture: hook modelbase.l.a() 过滤 uploadvoice,按类型定位字段(base≠ tinker 名,NoSuchFieldError 教训),dump 请求 pb r45.cv6 全字段。 捕获的 wire 协议(cgi /cgi-bin/micromsg-bin/uploadvoice, cmdid 127, req cv6/resp dv6): [0]self [1]talker [2]netOffset [3]本块SILK长 [4]"newSendVoice_"+voiceId [6]时长ms [7]custom cu5(SILK字节) [8]endflag [11]msgsource [12]=4 [15]long 分块=6000字节/片,末块 end=1 响应 dv6.getLong(11)>0=服务器msgId=投递。 scene modelbase.g extends m1 → z2.b(scene) 同文字。modelbase.o 有公开构造器可绕 过 modelbase.l 字段名不匹配。 下一步: sendVoiceViaCgi 实现分块 cgi + z2.b 全合成。详见 memory + WECHAT_SEND_API。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
图片 CDN 上传打通后,把 MCP 发图工具从旧的 share-intent UI 模拟切到内部 API: - wechat_hook_send.py: 新增 send_image_via_hook(wxid, image_path) — 先 stage 到 /sdcard 保证 WeChat 进程可读,再广播 SEND_IMAGE_INTERNAL;hook 内部走 b80.u.oj(插库+建描述符) + v70.w.oj(提交 CDN 上传),接收方收全分辨率原图。 新增常量 SEND_IMAGE_ACTION。旧 send_image_via_intent 保留作参考/UI 兜底。 - android_mcp.py: send_wechat_image 工具改调 send_image_via_hook,更新 docstring (无 UI 模拟、无选联系人、无发错人风险;nickname 不解析,须传 wxid)。 真机验证(off-device 走 wechat_hook_send.send_image_via_hook 直调): status=sent + hook oj() DONE + CDN submit DONE items=1。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
图片 CDN 上传打通后,把发图能力接进使用层: - skill_wechat_send/SKILL.md: 图片段 🟢→✅,给出 SEND_IMAGE_INTERNAL 广播 + wechat_send.sh 封装用法,标注真机验证(filehelper + 火星人全图收到)。 - wechat_send.sh image: 弃用旧的 share intent + 手动选联系人(UI 模拟), 改走内部 API 广播 SEND_IMAGE_INTERNAL;先 stage 到 /sdcard 保证 WeChat 进程可读,再 fire-and-forget 到 <wxid>。真机验证 oj()+CDN submit 均 DONE。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
攻克图片发送最后一公里(LSPosed,微信 8.0.74,真机验证全分辨率送达): 根因: b80.u.oj(o70.k) 只做「插消息 f9 + 插 ImgInfo b0 + 建缩略图」并 返回 List<o70.l> CDN 上传描述符,自己不提交 CDN。旧代码拿到 res 就丢掉 list → 上传永不触发(缩略图渲染但全图转圈)。真实编排 pe5.f.a 才循环 list 逐图提交(b80.s 只是 prebuild service checkPreBuildImg,不含 oj)。 补上第二步(照搬 pe5.f.a): oj() 后对每个 o70.l: cdnSvc = n0.c(xs.d1.class) // v70.w MsgImgFeatureService g = new r70.g(l.e, compress, c01.z1.r()/*self wxid*/, talker, k70.i0{a=3}) cdnSvc.oj(g, l) // → 启动 CDN 上传协程 e80.c 真机: oj() DONE res=size=1 + CDN submit DONE items=1,无异常;filehelper 收到消息点开是全分辨率原图(有原图+保存按钮,不再转圈)。 坑: v70.w.oj 内部走 ViewModelProvider.get 须主线程调(广播 receiver 本就在 主线程);jadx 字段名末位字母=真实 dex 字段;XposedHelpers stub 无 getLongField 用原生反射。逆向靠拉 Tinker dex + jadx --single-class。 产物: WECHAT_SEND_API.md §3 完整两步实现 + API 表;backups 源码快照。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
-
逆向微信 8.0.74 内部发送 API(LSPosed,无 UI 模拟): - 文字(中英文): w11.r0(type=1) Object-ctor + z2.b NetSceneQueue,真机验证送达。 中文走 text_b64 base64 通道避免 shell 损坏 UTF-8。避开 dk5.s5.Ni(实为发名片)。 - 图片: hook 真实发送抓 o70.h/o70.k/o70.i 原样重放,攻克消息构建—— 能建 type=3 图片消息、缩略图渲染、进 pt0.e0 管线;全图 CDN 上传是最后一公里。 - 语音: jg0.x.w hot-swap(真机验证投递)。 - wxid 解析: EnMicroMsg.db SQLCipher 解密(key=MD5(imei+uin)[:7])查 rcontact。 - 坑: 真实代码在 Tinker 补丁 CL(hook 用 sTinkerCL);force-stop 不 flush 加密 WAL。 产物: WECHAT_SEND_API.md(完整逆向文档)+ skill_wechat_send/SKILL.md + backups/(WeChatHook.java 快照 + 构建/发送脚本)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> -
skills/wechat-voice-sender/SKILL.md: - when to use、核心工具调用示例、已知联系人 wxid 表 - 明确告知 Hermes:不要自己实现 edge-tts/silk-wasm,调工具即可 - 错误处理表、安全约束 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
- 去掉 send_voice_tts_via_hook 里多余的 staging 步骤: 生成 SILK 后直接把临时路径传给 send_voice_via_hook, 由它统一做 cp → wechat_cache + broadcast(避免 cp A→A 报错) - _tts_to_silk: ffmpeg/node 路径检测增加 Termux 全路径候选, root su shell 下 PATH 不含 Termux bin 时也能找到 验证:device 侧 Python 直调 send_voice_tts_via_hook → filehelper 5620ms 语音 OK Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
silk-wasm 搜索顺序调整为 Termux 全局路径优先, 与 node.js 在 Termux 下 NODE_PATH 行为一致。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
wechat_hook_send.py: - 新增 _tts_to_silk(): edge-tts → ffmpeg → silk-wasm 完整 TTS 管线 支持 on-device (Termux) 和 off-device (Mac adb push) 两种运行模式 - 新增 send_voice_tts_via_hook(): 文字 → 语音一步到位, 自动处理 TTS/SILK 编码+WeChat cache 暂存+broadcast 发送 android_mcp.py: - 新增 send_wechat_voice_tts MCP 工具(Hermes 直接传文字即可发语音) docstring 明确写明:不要自己实现 SILK,调这个工具就行 docs/wechat-voice-send-guide.md (新): - Hermes 调用说明:正确姿势 / 声音选项 / 依赖安装 / 常见错误 / 技术背景 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
**WeChatHook.java — 语音发送四个关键 fix**: - 跳过 H():DB INSERT 在 r0 构造器内已完成,H() 只触发 CDN 上传, 服务端拒绝后会删消息;skip H 彻底解决消息消失问题 - status=4 双写:ContentValues + f9.r1(4) 内存字段同时写, 防止 K(0) 回调再次 convertTo 时读到 status=1 覆盖回转圈 - sDatabaseF9 精准捕获:在 convertTo() hook 里捕获入库的 f9 对象 放入 r0.i,修复旧逻辑取第三个 f9(内容为空)导致点击崩溃 - K(0) 而非 I(0):onSceneEnd code=0 时调成功路径 K 而非失败路径 I, 修复红色感叹号问题 - fromusername 兜底:sMyWxid 为 null 时回退硬编码 wxid **tts_voice_send.sh(新)**: 一行命令 TTS 发语音:edge-tts → ffmpeg(16kHz PCM) → silk-wasm(SILK V3) → adb push → SEND_VOICE_INTERNAL **wechat_send.sh(新)**:统一 text / image / voice 三种发送模式的 CLI Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
Hermes 重编 APK 时连踩三坑导致平板登录失效: 1. 用 XposedBridgeApi.jar 而非 LSPosed legacy JAR 编译 → 所有 hook NoSuchMethodError 2. xposed_init 放在 APK 根目录而非 assets/ → daemon 验证失败每次重启自动删模块 DB 注册 3. 换了 keystore → INSTALL_FAILED_UPDATE_INCOMPATIBLE 修复:从 wechathook_v2_signed.apk(正确 legacy JAR 编译)提取 DEX 复用,重打包含正确 assets/xposed_init,debug.keystore 签名,fix_lspd_final.py 重建 DB 注册。 2026-07-04 重启后验证平板登录恢复正常,所有 tablet hook 日志无 NoSuchMethodError。 新增文件: - wechathook_v2_signed.apk: 黄金基准 APK(legacy JAR 编译,DEX 可复用) - do_not_break.md: 给 Hermes 的禁止事项清单 - hermes_task.md: 已在顶部加 DO NOT BREAK 警告 banner - analyze_wechathook.py: DEX 字节码分析工具(Tinker patch) - rebuild_wechathook.sh / update_wechathook_db.sh: Mac 侧重建脚本 - termux_build.sh: Hermes 的手机侧 build script(有编译 JAR bug,留作参考) - wechat_send_internal/: Hermes 对 WeChat 内部发送 API 的研究产出(进行中) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
目标设备:Pixel 10 Pro Fold / Android 16 / WeChat 8.0.74 - WeChatHook.java:双保险策略 1. hook bk.A()/bk.B() 返回 true(静态方法,AOT 不内联则有效) 2. hook Activity.onResume() 保底:框架跨 APK 调用无法被 WeChat AOT devirtualize,必然触发,直接强制平板按钮(LoginHistoryUI.N) VISIBLE - rebuild.sh / update_db.sh:一键编译部署脚本 - LESSONS.md:逆向过程、AOT devirtualize 坑、XposedHelpers.newInstance 子类类型陷阱等经验总结 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
Hook.java v3.1 (315 行): - body 捕获:okio.Buffer 读取 POST/PUT body(截断 2000 字符) - Proxy poller(后台线程,1s 轮询 /xhs_proxy/pending): executeOkHttp() 在 XHS 进程内用 OkHttpClient 执行代理请求, 自动经过 XHS 拦截器签名,结果 POST /xhs_proxy/result - 手写 JSON 解析器(无外部依赖) - 保留 /xhs_params 转发(每条 edith 请求实时上报) event_server.py(Hermes 编写): - proxy_requests 表(pending→ok/error 状态机) - POST /xhs_proxy — Hermes 下发代理请求 - GET /xhs_proxy/pending — Hook 轮询取下一个任务 - POST /xhs_proxy/result — Hook 上报执行结果 - GET /xhs_proxy/result/{id} — Hermes 轮询取结果 - DELETE /xhs_proxy/{id} — 清理完成的任务 架构:Hermes → event_server → Hook(XHS进程内OkHttp签名) → event_server → Hermes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> -
- STATUS.md: file index updated to v3 (DEX=6328B, HTTP forwarding), add ~/.hermes/event_bus/event_server.py to index - update_xhshook_db.sh: phase 3 — after checkpoint, verify scope table has row for current mid; auto-insert if missing (mid changes after every reinstall, missing scope → lspd skips injection silently) - .gitignore: ignore *.idsig (apksigner side-car, not useful in git) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
- event_server.py: POST /xhs_params receives forwarded XHS edith requests from xhshook v3 (Hook.java background thread), stores as type='xhs_request' in events DB; GET /xhs_params returns latest N captures for Hermes to query - Pushed to device ~/.hermes/event_bus/event_server.py - STATUS.md: reflect v3 state (mid=4, DEX=6328B, HTTP forwarding live), mark task C done, add Hermes startup instructions for event_server + xhs_params query Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
Hook.java v3:在现有 logcat 日志基础上,后台线程 POST 每条 edith.xiaohongshu.com 请求(method/url/全量 headers)到 Hermes event_server(127.0.0.1:8765/xhs_params)。 Hermes server 未运行时静默失败,logcat 捕获不受影响。 rebuild_xhshook.sh:d8 步骤改用 find 通配所有 .class 文件, 避免新增匿名类时漏掉(之前写死 Hook$1.class)。 update_xhshook_db.sh:两阶段更新策略 - Phase 1:Python in-place UPDATE + commit(不做 checkpoint, lspd 持有写锁时 checkpoint 会 OperationalError) - Phase 2:pull DB+WAL → Mac 本地 checkpoint → push 干净主文件 → 删设备端 WAL/SHM,确保重启后 DB 正确 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
- STATUS.md:更新至 2026-06-30 00:33 验证通过状态,新增捕获到的额外 签名 header(x-mini-sig/mua/s1/gid、x-legacy-sid、shield), 补充 curl HTTP 200 复现验证结果,记录 lspd crash 恢复流程 - update_xhshook_db.sh:改用 Termux Python 原地 UPDATE + wal_checkpoint 代替 cp/adb push(后者改变 inode,lspd FileObserver 监听旧 inode 不刷缓存) - STATUS.md "已知不行的路线" 新增 adb push DB 和手动重启 lspd 两条陷阱 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
修复 LSPosed(JingMatrix/Vector fork)在 Android 16 上 zygote64 崩溃问题, 并完成 xhshook Xposed 模块注入 XHS(com.xingin.xhs),实现 edith.xiaohongshu.com xy-common-params header 的实时拦截。 A16 崩溃根因:NDK 26 compile-time sizeof(JNINativeInterface) 不包含 Android 16 ART 新增的函数指针,memcpy 截断导致垃圾指针 → zygote 崩溃。 修复:从 env->functions->reserved0 读运行期实际大小,heap-alloc 后 memcpy。 其他修复: - service.sh 去掉 Android toybox 不支持的 --propagation slave flag - daemon 入口类名 org.lsposed.lspd.Main → org.matrix.vector.daemon.VectorDaemon xhshook 踩坑记录: - APK 必须含 assets/xposed_init(而非根目录),VectorConfigCache 只认这个路径 - adb install 必须加 --no-incremental,Incremental Install marker 破坏 ZipFile 解析 - Xposed API 类不能打进 module DEX,LSPosed 会检查 XposedBridge classloader 一致性 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
涵盖系统自动 OTA 升级静默清掉 Magisk root 的恢复流程、hermes gateway 才是真正监听消息平台的常驻进程(chat -q 测试不代表能收发消息)、 gateway stop 杀不干净手动 nohup 进程的坑、用 state.db 排查卡死 cron 任务的方法、tool_loop_guardrails.hard_stop_enabled 默认关闭导致无限 重试、以及 Kimi Coding Plan 模型标识符和 Thinking 模式的验证方法。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
Android 12+ 禁止从 BOOT_COMPLETED 直接启动 microphone 类型前台服务, 异常实际出现在 RecorderService.onCreate() 而非 BootReceiver(FGS 启动是 排队执行,BootReceiver 里的 try/catch 接不住)。原先没有捕获导致每次 重启手机后录音都无法自动恢复,必须手动开一次 App。 现在优雅捕获该异常,改为弹一条可划掉的"点击恢复录音"通知;同时给 onDestroy() 加了早退保护,避免提前 return 后摸到未初始化的 lateinit 字段导致连带崩溃。已用两轮真机重启验证。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
涵盖 macOS tar AppleDouble 文件污染、psutil Android sys.platform 不兼容、 jiter/maturin cargo 编译竞态与镜像缺口、ffmpeg libc++ 版本不一致、 以及 Kimi Coding Plan key 的非交互配置方法。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
Hermes Agent 手机端 ~/.hermes/ 的一次性设备备份,按用户要求原样提交, 含 configs/.env 真实凭证与 memory/memory_graph.db 真实微信消息原文/ 联系人数据。已知风险见 CLAUDE.md 对应记录。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
纯调研,未做任何实际操作(未关 SIP/未装解密工具),记录目录结构、 密文确认、key_info.db 误判等试错过程,供后续评估是否接入 Mac 端 微信聊天记录作为数据源时参考。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
用户从 Pixel 上的 ~/.hermes/ 拷了一份一次性备份到 Mac 核对内容,读完发现 几条对以后开发有用的事实,补进 CLAUDE.md: - phoneuse/android_mcp.py 的真实消费方是第三方框架 Hermes Agent (Nous Research,非本项目自研),驱动模型是 Kimi;memory_graph.db 确认 在线持续增长(1020 person/1255 message/518 vector,对比 TASKS.md 2026-06-16 审计时的 522/1205/510+)。 - Hermes 在 phoneuse 之外长出的 wechat-image-sender skill(2026-06-23 验证通过)已经解决了 wechat_send.py 没做的"发图片"能力(ACTION_SEND Intent + OCR 找联系人,1344x2992 屏幕坐标全程验证),该 skill 早期笔记 里提过想用 Frida bridge 但因为不在 Termux 里跑而放弃——正是这次新增 的 frida_inspect_tools.py 解决的链路,以后可以接上看看。 - wechat-group-digest 绑的两个 cron job 截至备份时都因 hermes-agent 自身的 `env_float` 缺失 bug 报错失败,不是 phoneuse 代码 问题,但别假设它们在正常工作。 - 备份的 manifest.json 声称有 5 个 skill,实际只备份了 3 个,不是完整镜像。 备份目录本身含真实 API key(.env)和真实微信消息/联系人原文 (memory_graph.db、persona.yaml),加进根 .gitignore 的 /hermes_backup_*/ 规则,确保不会被任何后续 git add -A 带进仓库。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
frida_call 此前完全不可达(TASKS.md S3-03):Mac 端没装 frida/frida-tools pip 包。新建 phoneuse/.venv,锁定 frida==17.9.10 + frida-tools==14.8.0 (与设备上跑的 frida-server 17.9.10 匹配,更新版本的 frida-tools 对 frida 有严格 range 依赖会直接报错),新增 start_frida_bridge.sh 一键 adb reverse + 起桥。 新增 frida_inspect_tools.py:inspect_foreground_intent(package) / dump_live_bitmaps(package, max_export) 两个通用 MCP 工具,分别用 Java.choose 枚举目标进程里存活的 Activity(按 hasWindowFocus 识别前台) 和 Bitmap(按 allocationByteCount 排序导出最大的 N 张为 base64 PNG)。 不需要逆向任何具体 App,跟 per-app hook(如微信 sendMessage,已被证实 重度混淆卡死过)明确区分开。 已知限制:frida_bridge.py 现有的进程名子串匹配按 frida 报告的人类可读 标签匹配,不是包名,微信类多进程 App 会匹配到无 UI 的子进程导致静默空 结果——两个新工具已对空结果加诊断提示,根因不在本次改动范围。真机端到 端验证因设备从 adb devices 掉线未完成,TASKS.md 按既有审计格式如实标 记为 [!] 阻塞,未来设备在线后用 Settings/Calculator 之类无隐私 App 补测。 CLAUDE.md 补上 phoneuse 子项目说明——2026-06-23 拍平合并进本仓库后一直 没同步进根文档。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
之前 mitm_proxy.py 一直是手动 nohup 起的,不在任何自启脚本里,进程被杀 或手机重启后需要手动重新启动。现跟 EventServer 一样接入 start_service/ stop_service 框架,用 pid 文件跟踪。 mitm_proxy 必须以 root 跑(~/.hermes/mitm_ca 历史上由 root 创建, 普通 Termux 用户没有写权限,新域名首次访问会因建证书失败退化成不拦截 的透传),stop_all.sh 原来的 stop_service 直接 kill 在非 root 进程上 会因 EPERM 失败,加了 as_root 参数走 su -c kill。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
全局 http_proxy 指向此代理后,Chrome 等遵守系统代理的 app 的 HTTPS 请求 全部失败,而不读系统代理的 Termux 工具表现正常。 - TLS 握手改用 asyncio 原生 loop.start_tls(),去掉手动 dup socket 同步 握手的旧实现:cert 生成 await 让出控制权时,asyncio 事件循环会把刚到的 ClientHello 字节读进自己的缓冲区,导致握手线程永远等不到数据。 - 证书生成加 _cert_lock,避免同一域名并发首次访问时生成的 cert/key 文件 互相踩踏导致 KEY_VALUES_MISMATCH,此后该域名永久失败。 已在设备上实测验证:单域名 + 5 并发首次访问全部通过。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
Android SDK platform-tools(adb/fastboot 等)放在仓库根目录, 供 lifelog-recorder/wechat_plain/phoneuse 等子项目共用。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
phoneuse 原是独立 git 仓库(origin: gitlab phoneuse.git),现移除其 内部 .git 元数据,把代码拍平为本仓库的普通文件纳入历史。phoneuse 自身 3 条 commit 历史仍完整保留在 gitlab 远端,未受影响。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
GoalScreen(新建): - 进行中 / 已完成分组;状态切换(✓完成 / 🔄重开);删除; - 新建对话框:目标内容 + 截止日期 + 关联人物下拉 - 删除目标自动解绑其下所有待跟进 PhotologScreen: - ContactsTab 加 showGoals 状态 + GoalScreen 导航 - ContactList 工具栏加「🎯 目标」入口按钮 FollowupsScreen 重写: - 每条待办显示「🎯 目标名」标签 - 点击弹出 GoalPickerDialog,可绑定/解绑目标 PhotologViewModel: - createGoal / updateGoalStatus / deleteGoal / linkFollowupToGoal ChatScreen: - 键盘 ImeAction.Send 支持 + 发送后自动收键盘 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
Room 校验时 Expected vs Found 两处不匹配: 1. status 列:migration SQL 写了 DEFAULT 'active',Room 期望 defaultValue=undefined (Entity 未用 @ColumnInfo(defaultValue=...),Room 不把 Kotlin 默认值当 SQL DEFAULT) 2. 多余 CREATE INDEX index_goals_status:@Entity 无 @Index,Room Expected indices=[] 修复:migration 去掉 DEFAULT 子句 + 去掉 CREATE INDEX 这两行。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-
P2 #6 Goal 实体(DB v23→v24): - goals 表:id/text/status/deadline/parentGoalId/personId/notes/createdAt/updatedAt - status: active/paused/done/cancelled - parentGoalId 支持树形分解(创业→融资→找VC→约张总) - GoalDao:insert/get/all/observeAll/observeByStatus/roots/children/updateStatus/updateNotes/delete P2 #7 Followup→Goal 挂载: - followups 表加 goalId 列 - FollowupDao 加 updateGoal / observeByGoal / all(一次性查,供 LLM 文本匹配) - FollowupRow 加 goalId 字段 P2 #8 AI Goal 工具(4 个): - create_goal:建目标,支持截止日期/父目标/关联人物 - get_goals:树形展示目标+子目标+已挂待跟进,支持状态过滤 - link_followup_to_goal:按 id 或关键词匹配,批量关联 followup→goal - update_goal_status:标完成/暂停/重启/放弃 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>