ARCHITECTURE.md
8.3 KB
Agent Phone Runtime — Architecture
当前状态 (2026-06-11)
项目有两个并行实现,需要合并:
实现 A:Python/Termux 栈(已跑通)
假设:Hermes 运行在 Pixel 的 Termux 里,一切本地化,不依赖 Mac。
Android System
↓ root su + dumpsys notification (2s 轮询)
notification_monitor.py (root Python daemon)
↓ HTTP POST localhost:8765
event_server.py (FastAPI + SQLite queue, Termux)
↑ MCP stdio
android_mcp.py (FastMCP server)
↑ MCP protocol
Hermes Agent (Termux)
文件位置(设备)
~/.hermes/event_bus/
├── event_server.py # FastAPI HTTP 事件队列,127.0.0.1:8765
├── notification_monitor.py # root 进程,轮询 dumpsys,POST 通知
├── android_mcp.py # FastMCP stdio server (Hermes 调用)
├── start_all.sh # 一键启动(需 Termux 终端里运行)
├── stop_all.sh # 一键停止
└── events.db # SQLite 事件持久化
EventServer API(127.0.0.1:8765)
| 端点 | 用途 |
|---|---|
POST /events |
Android 推送单条事件 |
POST /events/batch |
批量推送 |
GET /events?since_id=X |
MCP 增量拉取 |
GET /events/latest?limit=N |
最近 N 条 |
GET /stats |
队列统计 |
GET /health |
健康检查 |
MCP 工具(android_mcp.py)
| 工具 | 功能 |
|---|---|
get_events(since_id, limit, type_filter, app_filter) |
增量拉取事件 |
get_latest(limit, type_filter, app_filter) |
最近 N 条事件 |
get_stats() |
队列统计 |
list_event_apps() |
哪些 App 有活动 |
query_wechat(sql, key?, db_path?) |
root + sqlcipher 查微信 DB |
已验证
- ✅ EventServer 接收 → SQLite 持久化
- ✅ notification_monitor 捕获真实系统通知
- ✅ MCP JSON-RPC stdio 协议完整通讯
- ✅ Hermes config 已注册
android-phoneMCP server - ✅
since_id增量轮询、类型过滤 - ✅ WeChat sqlcipher 工具框架
已知限制
- notification_monitor 用
dumpsys轮询(2s 延迟,不是实时推送) - 没有 AccessibilityService(无 UI Tree 事件)
- notification_monitor 需要 root 才能跑 dumpsys
start_all.sh必须从 Termux 终端 app 里运行(不能通过adb run-as)
实现 B:Kotlin Android APK(架构完整,大部分为 stub)
假设:Hermes 运行在 Mac 或单独机器,通过 gRPC/MCP HTTP 连接 Android。
Hermes Agent (外部)
↓ gRPC :50051 (未接 codegen) / MCP HTTP :8080
AndroidRuntimeServer.kt (gRPC service)
↓ EventBus (SharedFlow)
AgentNotificationListenerService.kt ← 实时通知(无需 root)
AgentAccessibilityService.kt ← UI Tree 事件
↓ Unix Domain Socket @agent_events (NDJSON)
EventStreamServer.kt
模块结构
android/
├── core/ # 统一实体模型 (Person/Conversation/Message/Event/Task/Document)
├── event-bus/ # EventBus (SharedFlow) + Unix Socket (NDJSON, @agent_events)
├── app/ # AccessibilityService + NotificationListenerService + BootReceiver
├── mcp-server/ # gRPC server + MCP HTTP/SSE server (port 8080) + ActionDispatcher
├── memory-graph/ # Room DB schema + GraphSchema 验证 (stub)
├── data-extraction/# SQLite/MMKV/Realm/LevelDB 提取器 (stub)
└── frida-bridge/ # Frida REST API 客户端 (OkHttp)
实现状态
| 模块 | 状态 |
|---|---|
| AgentNotificationListenerService | ✅ 完整实现 |
| AgentAccessibilityService | ✅ 完整实现 |
| EventBus + Unix Socket | ✅ 完整实现 |
| MCP HTTP/SSE server (port 8080) | ✅ 完整实现 |
| gRPC server | ⚠️ 接口定义完整,未接 protoc codegen |
| ActionDispatcher / QueryDispatcher | ⚠️ 路由逻辑完整,handler 为 stub |
| Memory Graph | ⚠️ Schema 设计完整,MemoryGraph.kt 为空 stub |
| Data Extraction (SQLite/MMKV/etc) | ⚠️ 类结构完整,实际读取为 stub |
| Frida Bridge | ✅ HTTP client 完整,JS scripts 框架完整 |
注意:TASKS.md 所有任务标记为 [x],但实际代码中大量为 stub,不代表功能可用。
MCP HTTP/SSE 协议(port 8080)
GET /sse— Server-Sent Events 流POST /messages— JSON-RPC 2.0tools/list,tools/call,initialize
gRPC 协议(port 50051)
service AndroidRuntime {
rpc Execute(ActionRequest) returns (ActionResponse);
rpc Query(QueryRequest) returns (QueryResponse);
rpc Subscribe(SubscribeRequest) returns (stream Event);
}
架构差异
| 维度 | 实现 A (Python/Termux) | 实现 B (Kotlin APK) |
|---|---|---|
| Hermes 位置 | Android 本机 Termux | 外部机器 |
| 事件采集 | dumpsys 轮询 (root, 2s) | NotificationListenerService (实时) |
| Accessibility | ❌ | ✅ |
| MCP 传输 | stdio (FastMCP) | HTTP/SSE :8080 |
| 持久化 | SQLite event queue | SharedFlow (内存) + Room |
| 可用状态 | ✅ 端到端跑通 | ⚠️ 未编译部署 |
| WeChat DB | ✅ sqlcipher 工具可用 | ⚠️ stub |
| Frida | ❌ | ✅ HTTP client 框架 |
合并方案
目标:保留两边的优势,以"Hermes 在 Termux 本机"为基础架构。
阶段 1(当前可做):打通 APK 事件源
- 编译安装 Android APK
- APK 的
AgentNotificationListenerService实时收到通知后:- 方案 A:POST 到 EventServer
localhost:8765(最简) - 方案 B:android_mcp.py 订阅 Unix Socket
@agent_events,写入 SQLite
- 方案 A:POST 到 EventServer
- 去掉
notification_monitor.py(dumpsys 轮询),替换为 APK 实时推送
阶段 2:接入 AccessibilityService
APK 的 AgentAccessibilityService 捕获 UI Tree 事件,同样推送到 EventServer。
在 MCP 增加 get_ui_state(package?) 工具。
阶段 3:接入 Frida
APK 的 FridaBridge.kt 已实现 frida-server REST client。
在 android_mcp.py 增加 frida_call(package, script) 工具,内部调用 FridaBridge HTTP API。
阶段 4:gRPC(可选)
如果后续需要 Hermes 从 Mac 控制 Android,再接 gRPC protoc codegen。 当前 Hermes 在 Termux 本机,stdio MCP 足够,gRPC 优先级低。
启动指南
前置条件
- Pixel 8 Pro,Root(Magisk)
- Termux 已安装,Hermes 已安装(
~/.hermes/hermes-agent/) - 已在 Termux 给予 Root 权限
启动服务(在 Termux 终端里运行)
bash ~/.hermes/event_bus/start_all.sh
输出:
[+] EventServer started (pid XXXX) on http://127.0.0.1:8765
[+] NotificationMonitor started as root (pid XXXX)
停止服务
bash ~/.hermes/event_bus/stop_all.sh
Hermes MCP 配置(已写入 ~/.hermes/config.yaml)
mcp_servers:
android-phone:
command: /data/data/com.termux/files/home/.hermes/hermes-agent/venv/bin/python
args:
- /data/data/com.termux/files/home/.hermes/event_bus/android_mcp.py
env:
EVENT_BUS_DB: /data/data/com.termux/files/home/.hermes/event_bus/events.db
timeout: 30
connect_timeout: 10
Hermes 里使用
在 Hermes 对话中直接问:
- "手机上最近有什么通知?"
- "查一下微信最近 20 条消息"
- "现在哪个 App 在前台?"
WeChat SQLCipher
Key 存放:~/.hermes/event_bus/wechat_key(默认 e03ce81)
DB 路径:/data/data/com.tencent.mm/MicroMsg/<hash>/EnMicroMsg.db(root 读取)
详细实现参考:/Users/yibo/Documents/aipcrm/server/services/wechat/
文件清单
Mac 端(开发)
/Users/yibo/Documents/lemonAI/phoneuse/
├── ARCHITECTURE.md # 本文档
├── phoneuse.md # 项目 Vision & Milestone 原始文档
├── TASKS.md # 任务追踪(另一进程生成)
├── android/ # Kotlin Android APK 项目
├── event_server.py # EventServer 源码
├── notification_monitor.py # Notification monitor 源码
├── android_mcp.py # MCP server 源码
├── start_all.sh # 启动脚本
├── stop_all.sh # 停止脚本
└── test_mcp_rpc.py # MCP 协议测试脚本
设备端(Pixel 8 Pro)
~/.hermes/event_bus/ # 所有运行时文件
~/.hermes/config.yaml # 含 mcp_servers.android-phone 配置
~/.hermes/logs/ # event_server.log, notification_monitor.log