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-phone MCP 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.0
  • tools/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 事件源

  1. 编译安装 Android APK
  2. APK 的 AgentNotificationListenerService 实时收到通知后:
    • 方案 A:POST 到 EventServer localhost:8765(最简)
    • 方案 B:android_mcp.py 订阅 Unix Socket @agent_events,写入 SQLite
  3. 去掉 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