Commit c7f16ba1efd8dd488c70cb19a7ad95c107142cfc
1 parent
daa45829
docs(lifelog): 转向纯端上 App,废弃 lemonPCRM + 端上 CRM 补齐 TODO
- 主线改为 lifelog-recorder(纯端上 Personal CRM),lemonPCRM(server/frontend/packages) 标已废弃, 删掉 CLAUDE.md 里所有服务端章节(ACP/Master-Sub-Agent/GraphStore/server 微信链路) - 加「App 即 Personal CRM:与旧 lemonPCRM 能力对比」+ 6 项差距 + 「Transcript→内部 Person」方向 - HANDOFF §五:存储 TTL/设置页标✅;「回链 lemonPCRM」→「内部 Transcript→Person」; 新增「端上 CRM 补齐 TODO」P0–P3 清单 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Showing
2 changed files
with
78 additions
and
159 deletions
CLAUDE.md
| ... | ... | @@ -4,164 +4,35 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co |
| 4 | 4 | |
| 5 | 5 | ## 项目概述 |
| 6 | 6 | |
| 7 | -本仓库(`aipcrm/`)现在托管 **3 个互相关联但独立的子项目**: | |
| 7 | +本仓库(`aipcrm/`)的**主线 = `lifelog-recorder/`** —— Pixel 8 Pro 上一个**完全端上、零云端**的 Local-First 个人记忆 + 人脉管理(Personal CRM)原生应用:24/7 录音 + 本地中文 ASR + 声纹/人脸识别 + 端上 LLM 纪要/对话 + 以「人」为中心的联系人档案 + 全相册语义索引。所有能力跑在设备上,**不依赖任何 Mac/PC 服务**。 | |
| 8 | 8 | |
| 9 | 9 | | 子项目 | 路径 | 形态 | 状态 | |
| 10 | 10 | |---|---|---|---| |
| 11 | -| **lemonPCRM** | `server/` + `frontend/` + `packages/` | Node.js + Express 后端 + 静态前端 | 主线 | | |
| 12 | -| **wechat_plain** | `wechat_plain/` | Android Xposed/A11y 模块 + Pixel 部署脚本 | 主线 | | |
| 13 | -| **lifelog-recorder** | `lifelog-recorder/` | Pixel 原生 Android 应用(Kotlin + Compose) | v0.8 (2026-06) | | |
| 11 | +| **lifelog-recorder** | `lifelog-recorder/` | Pixel 原生 Android 应用(Kotlin + Compose) | **主线 v0.8** | | |
| 12 | +| **wechat_plain** | `wechat_plain/` | Pixel 上微信 bot 的 Xposed/A11y 模块(端上) | 辅助 | | |
| 13 | +| **lemonPCRM** | `server/` + `frontend/` + `packages/` | Node.js + Express 后端 + 静态前端 | **已废弃** | | |
| 14 | 14 | |
| 15 | -**lemonPCRM** — lemonAI 出品的 Local-First AI 个人人脉管理系统(Personal CRM)。以人为中心、以对话为链接,通过知识图谱管理微信、LinkedIn、X 等多平台社交关系,将每个联系人与其社媒动态、会议纪要、文件、照片全面关联。 | |
| 15 | +> [!IMPORTANT] 方向已转向纯端上 App | |
| 16 | +> 早期主线是 **lemonPCRM**(Mac 上 Node/Express + 知识图谱 + ACP 驱动 Claude CLI 的服务端 CRM)。 | |
| 17 | +> 现已**废弃**:其 Personal CRM 能力已在 `lifelog-recorder` 里**原生端上重实现**(联系人档案、人脸/声纹识别、 | |
| 18 | +> AI 印象、RAG 对话、照片语义检索),不再依赖 Mac。`server/` `frontend/` `packages/` 代码仅作历史留仓, | |
| 19 | +> **新功能不要往里加,也不要把 app 回链到它**。App 与旧 lemonPCRM 的能力对比 / 仍存差距见下文 | |
| 20 | +> §lifelog-recorder「App 即 Personal CRM:与旧 lemonPCRM 的能力对比」。 | |
| 16 | 21 | |
| 17 | -AI 对话与编排层基于 ACP 协议驱动本地 Claude CLI 进程,提供单 Agent 执行和 Master → Sub-Agent 多轮编排能力。Node.js + Express,无数据库依赖(使用 Node 22.5+ 内置 `node:sqlite`),数据完全本地化。 | |
| 22 | +### wechat_plain(端上微信 bot,辅助) | |
| 18 | 23 | |
| 19 | -**wechat_plain** — Pixel 上微信 bot 的 Xposed/A11y 落地(A11y UI 自动化是当前唯一能真把消息推进 message 表的发送链路;详见下文 §微信集成架构)。 | |
| 24 | +Pixel 上微信发送/跟踪的落地,纯设备内运行(不依赖 Mac): | |
| 20 | 25 | |
| 21 | -**lifelog-recorder** — Pixel 8 Pro 上的 24/7 录音 + 本地中文 ASR + 时间轴 lifelog 应用(2026-06 新增,详见下文 §lifelog-recorder)。 | |
| 22 | - | |
| 23 | -## 常用命令 | |
| 24 | - | |
| 25 | -```bash | |
| 26 | -npm run setup # 首次初始化:cp .env.example .env + pnpm install | |
| 27 | -npm start # 生产模式(node server/index.js) | |
| 28 | -npm run dev # 开发模式(node --watch server/index.js,热重载) | |
| 29 | -./dev.sh # 杀掉端口占用进程 + npm run dev(推荐开发用) | |
| 30 | -``` | |
| 31 | - | |
| 32 | -无测试框架,无 lint 脚本。使用 pnpm workspaces(`packageManager: pnpm@10.28.1`)。 | |
| 33 | - | |
| 34 | -## 架构 | |
| 35 | - | |
| 36 | -### 技术栈 | |
| 37 | -- **后端**:Node.js (≥18) + Express,pnpm workspace monorepo | |
| 38 | -- **数据库**:Node 22.5+ 内置 `node:sqlite`(`DatabaseSync`),位于 `server/db/lemon_crm.db` | |
| 39 | -- **AI**:Claude CLI(本地子进程,`--dangerously-skip-permissions` 自动批准) | |
| 40 | -- **文件解析**:mammoth(.docx)、pdf-parse(.pdf) | |
| 41 | - | |
| 42 | -### 目录速查 | |
| 43 | - | |
| 44 | -| 目录 | 说明 | | |
| 45 | -|------|------| | |
| 46 | -| `packages/acp-core/` | ACP 协议层:Protocol / Transport / Launcher 三层抽象 + ClaudeCliProtocol / AcpProtocol | | |
| 47 | -| `packages/agent-core/` | Agent 运行时(ESM):目录驱动的 Agent、AgentBus、AgentRegistry、AgentScaffold | | |
| 48 | -| `server/index.js` | Express 入口(路由 + 静态前端) | | |
| 49 | -| `server/src/core/` | 编排引擎:orchestrator、master-session、agent-manager、session-pool、stream-executor、prompt-builder、parser、runtime-resolver | | |
| 50 | -| `server/src/engine/` | 进程层:run-registry、command-queue、process-guard、idle-timer、failover-error | | |
| 51 | -| `server/src/tools/` | Master 工具:call-agent-tool、tool-registry、graph/(图谱 MCP 工具集) | | |
| 52 | -| `server/src/standalone-entry.js` | 编程 API:`runMasterSession` / `runOrchestration` / `runSingleAgent` | | |
| 53 | -| `server/routes/` | API 路由:master-chat、config、graph、wechat、import、analysis、photo | | |
| 54 | -| `server/services/` | conversation-logger、file-parser、memory-service、claude-chat-service、wechat/、linkedin/、meeting/、photo/、x/ | | |
| 55 | -| `server/db/GraphStore.js` | 本地知识图谱存储层(SQLite):Person / Organization / Project / Event / Asset 节点 + KNOWS / BELONGS_TO / PARTICIPATED 等边 | | |
| 56 | -| `frontend/` | 静态前端(单 HTML 文件,由 server/index.js 托管) | | |
| 57 | -| `server/config/backends.json` | ACP Launcher / Client 定义 | | |
| 58 | -| `server/config/agents.json` | 静态 Agent 注册表(可选,也可由 `system/agents/` 目录发现) | | |
| 59 | - | |
| 60 | -### API 路由 | |
| 61 | - | |
| 62 | -| 路径 | 说明 | | |
| 63 | -|------|------| | |
| 64 | -| `POST /api/master/chat` | Master Agent 多轮对话(SSE) | | |
| 65 | -| `POST /api/master/upload` | 文件上传注入对话 | | |
| 66 | -| `GET /api/master/sessions` | 列出活跃 session | | |
| 67 | -| `DELETE /api/master/sessions/:id` | 关闭 session | | |
| 68 | -| `GET/PUT /api/config/items/:key` | 读写配置文件 | | |
| 69 | -| `GET /api/health` | 健康检查 | | |
| 70 | -| `GET /api/graph/nodes` | 列出图谱节点(?type=Person&limit=100) | | |
| 71 | -| `GET /api/graph/nodes/:id` | 查询单个节点(含边) | | |
| 72 | -| `POST /api/graph/nodes` | 创建/更新节点 | | |
| 73 | -| `GET /api/graph/search?q=关键词` | 全文搜索 | | |
| 74 | -| `POST /api/graph/edges` | 创建关系边 | | |
| 75 | -| `GET /api/graph/path?from=id&to=id` | 查询关系路径 | | |
| 76 | -| `POST /api/wechat/import-contacts` | 导入微信联系人到图谱 | | |
| 77 | -| `POST /api/wechat/import-chat` | 导入微信聊天记录 | | |
| 78 | -| `GET /api/wechat/contacts?q=搜索` | 查询微信联系人 | | |
| 79 | -| `GET /api/wechat/sessions` | 最近会话列表 | | |
| 80 | -| `POST /api/import/...` | 多平台数据导入 | | |
| 81 | -| `POST /api/analysis/...` | 图谱分析(关系链路、聚类等) | | |
| 82 | -| `POST /api/photo/...` | 照片服务(人脸聚类、向量检索) | | |
| 83 | - | |
| 84 | -### 配置文件 | |
| 85 | - | |
| 86 | -| 文件 | 说明 | | |
| 87 | -|------|------| | |
| 88 | -| `.env` | PORT(默认 3010)、HOST、CORS_ORIGINS 等 | | |
| 89 | -| `server/config.js` | 端口、CORS、目录路径的运行时配置对象 | | |
| 90 | -| `server/config/backends.json` | ACP Launcher 定义(command、args、protocol) | | |
| 91 | -| `server/config/agents.json` | 静态 Agent 注册(可选) | | |
| 92 | - | |
| 93 | -## 关键架构模式 | |
| 94 | - | |
| 95 | -### ACP 协议四层结构 | |
| 96 | - | |
| 97 | -``` | |
| 98 | -Application (AgentManager) | |
| 99 | - ↓ | |
| 100 | -Protocol (ClaudeCliProtocol 直接 spawn / AcpProtocol JSON-RPC) | |
| 101 | - ↓ | |
| 102 | -Transport (ProcessTransport stdio / PipeTransport / WebSocketTransport) | |
| 103 | - ↓ | |
| 104 | -Launcher (ProcessLauncher spawn / NoneLauncher 无操作) | |
| 105 | -``` | |
| 106 | - | |
| 107 | -`runtime-resolver.js` 根据 `backends.json` + `agents.json` 配置自动推断使用哪一层。 | |
| 108 | - | |
| 109 | -**ClaudeCliProtocol 调用方式**: | |
| 110 | -- 生成命令:`claude --input-format stream-json --output-format stream-json --verbose --include-partial-messages --dangerously-skip-permissions` | |
| 111 | -- 输入格式:`{"type":"user","message":{"role":"user","content":[{"type":"text","text":"..."}]}}` | |
| 112 | -- 输出:NDJSON 事件流 | |
| 113 | -- 单进程跨多轮复用(session reuse) | |
| 114 | - | |
| 115 | -**Mock 模式**:设置 `LEMONBOSS_CLAUDE_MODE=mock` 可读取 fixture 文件而不启动真实进程,用于调试。 | |
| 116 | - | |
| 117 | -### Master → Sub-Agent 调度流程 | |
| 118 | - | |
| 119 | -1. 用户消息 → `MasterSession.handleMessage()` | |
| 120 | -2. `PromptBuilder` 组装系统提示(含工具描述 + 可用 Agent 列表) | |
| 121 | -3. Claude 响应中的工具调用用 `[TOOL_CALL: tool_name] {...json...} [/TOOL_CALL]` 格式标记 | |
| 122 | -4. `ToolRegistry.parseToolCalls()` 解析后交给 `AgentManager.callAgent()` | |
| 123 | -5. `SessionPool` 按 `agentName:client:deploy:workDir[:scope]` 为 key 复用已有 session | |
| 124 | -6. 工具结果注回对话,最多循环 10 轮(`SAFETY_MAX_LOOPS=15`) | |
| 125 | - | |
| 126 | -**Orchestrator** 额外提供格式自动修正(`MAX_REPAIRS=5`)与结果验证(`ResultTracker`)。 | |
| 127 | - | |
| 128 | -### Agent 发现与记忆 | |
| 129 | - | |
| 130 | -- Agent 优先从 `system/agents/` 目录发现(目录驱动),`agents.json` 作为静态补充 | |
| 131 | -- 每个 Agent 的记忆存储在其目录下的 `memory/` 子目录,纯文件系统 | |
| 132 | -- `AgentScaffold` 用于创建新 Agent 目录结构 | |
| 133 | - | |
| 134 | -### 知识图谱(GraphStore) | |
| 135 | - | |
| 136 | -`server/db/GraphStore.js` 使用 `node:sqlite`(Node 22.5+ `DatabaseSync`),无需额外依赖。 | |
| 137 | - | |
| 138 | -- **节点类型**:Person、Organization、Project、Event、Asset | |
| 139 | -- **边类型**:KNOWS、BELONGS_TO、PARTICIPATED、CONTAINS、MENTIONED_IN、ASSOCIATED | |
| 140 | -- **分析状态**:`analysis_status` 字段跟踪节点是否已被 AI 分析(none / pending / done) | |
| 141 | -- **Master 工具**:`server/src/tools/graph/` 提供 `create_person`、`get_person`、`link_persons`、`search_graph`、`get_relationship_path` 等工具供 AI 调用 | |
| 142 | - | |
| 143 | -### 微信集成架构 | |
| 144 | - | |
| 145 | -`server/services/wechat/` 提供从 Mac 和 Pixel 双端点与微信交互的能力: | |
| 146 | - | |
| 147 | -- **发送消息(实际工作链路)**:`am broadcast com.hermes.wechat.SEND_MSG` → **`HermesAccessibilityService`**(lsposed-wechat-sendmsg 模块内)→ 启动微信 LauncherUI → 点搜索按钮 → 搜索 `toUserDisplayName`(**必须传 nickname**,如"火星人")→ 点搜索结果 → 找 `bkk` 容器内的 EditText 输入文本 → 点 `bql` 发送按钮。纯 UI 自动化,绕开所有反射 / hook 失败。 | |
| 148 | -- **消息跟踪**:`android-wechat-tracker-sqlcipher.js` 直接轮询解密后的 `EnMicroMsg.db`(SQLCipher) | |
| 149 | -- **自动回复**:`auto-reply.js` 结合 tracker + broadcast,在 Pixel 上独立运行 | |
| 150 | -- **数据导入**:`wechat-importer.js` / `wechat-reader.js` 将联系人和聊天记录导入知识图谱 | |
| 151 | - | |
| 152 | -> [!WARNING] 关于其他两条已废弃的发送路径 | |
| 153 | -> - **LSPosed 反射 API**(`HermesWeChatModule.sendTextMessageDirect`):监听同一广播但走 `u01.r1.a → m1.a()`。`Send result: true` 是**误报**——`builder.a()` 后主线程异步提交触发 null 异常被 swallow,消息不进 `message` 表。 | |
| 154 | -> - **Frida daemon 队列**(`android-wechat-sender-frida.js` + `wechat_plain/scripts/frida-daemon/frida_daemon.js`):Frida 17 + 微信 8.0.72 注入大体积 bundle 触发反调试,微信进程崩溃,已废弃。 | |
| 155 | -> 这两条路径的命名让人误解;真正能把消息推进 message 表的只有 A11y service。 | |
| 26 | +- **发送消息(唯一可用链路)**:`am broadcast com.hermes.wechat.SEND_MSG` → **`HermesAccessibilityService`**(lsposed-wechat-sendmsg 模块内)→ 启动微信 LauncherUI → 点搜索按钮 → 搜索 nickname(如"火星人")→ 点结果 → `bkk` 容器内 EditText 输入文本 → 点 `bql` 发送按钮。纯 A11y UI 自动化,绕开所有反射 / hook 失败。 | |
| 27 | +- **已废弃的两条发送路径(命名误导,勿用)**:LSPosed 反射 API(`HermesWeChatModule.sendTextMessageDirect`,`Send result: true` 是误报,消息不进 `message` 表);Frida daemon(Frida 17 + 微信 8.0.72 注入大 bundle 触发反调试崩溃)。真正能推进 message 表的只有 A11y service。 | |
| 156 | 28 | |
| 157 | 29 | > [!IMPORTANT] A11y service 启用方式 |
| 158 | -> `enabled_accessibility_services` 系统设置易被关闭。检查与重新启用: | |
| 30 | +> `enabled_accessibility_services` 系统设置易被关掉,重启: | |
| 159 | 31 | > ```bash |
| 160 | -> adb shell "settings get secure enabled_accessibility_services" | |
| 161 | 32 | > adb shell "su -c 'settings put secure enabled_accessibility_services com.hermes.wechat.xposed/com.hermes.wechat.xposed.accessibility.HermesAccessibilityService; settings put secure accessibility_enabled 1'" |
| 162 | 33 | > ``` |
| 163 | 34 | |
| 164 | -详见 `server/services/wechat/README.md`。 | |
| 35 | +详见 `wechat_plain/` 内文档。 | |
| 165 | 36 | |
| 166 | 37 | ## lifelog-recorder(Pixel 8 Pro 24/7 录音 + 本地中文 ASR + 本地 LLM,v0.8) |
| 167 | 38 | |
| ... | ... | @@ -169,7 +40,7 @@ Launcher (ProcessLauncher spawn / NoneLauncher 无操作) |
| 169 | 40 | |
| 170 | 41 | ### 项目目标 |
| 171 | 42 | |
| 172 | -把 Pixel 8 Pro 当成**永远开机的麦克风**:7×24 后台录音 → VAD 切段 → 中文 ASR 转文字 → 入库 → 按时间轴显示和搜索 → LLM 总结成纪要。最终目的是把所有「我说过 / 别人对我说过」的内容沉淀成可搜索、可回放的个人记忆库,下接 lemonPCRM 的人脉图谱(某段语音 → 某联系人 → 某项目)。 | |
| 43 | +把 Pixel 8 Pro 当成**永远开机的麦克风**:7×24 后台录音 → VAD 切段 → 中文 ASR 转文字 → 入库 → 按时间轴显示和搜索 → LLM 总结成纪要。最终目的是把所有「我说过 / 别人对我说过」的内容沉淀成可搜索、可回放的个人记忆库,并在 **app 内自成端上 Personal CRM**(photolog):某段语音 → 声纹 → 联系人档案,照片 → 人脸 → 同一联系人。**整套 CRM 跑在设备上,已取代旧的 Mac 端 lemonPCRM**。 | |
| 173 | 44 | |
| 174 | 45 | 约束:**完全本地 / 零云端依赖 / 月成本 0 元 / 隐私走 0 网络**。 |
| 175 | 46 | |
| ... | ... | @@ -273,19 +144,43 @@ Foreground Service (foregroundServiceType=microphone, WAKE_LOCK partial) |
| 273 | 144 | |
| 274 | 145 | 剩余摘要: |
| 275 | 146 | - ⭐ **语义搜图落地**(v0.8 已接 `EmbedClient`,但需在 Pixel llama-swap 配 `embed` 模型才生效;中文 embedding GGUF) |
| 276 | -- ⭐ **回链 lemonPCRM**(Transcript / 照片 caption 实体 → GraphStore `MENTIONED_IN`,v2) | |
| 147 | +- ⭐ **内部 Transcript 实体 → Person 表**(端上 NER + 共现,取代旧「回链 lemonPCRM」;见下文 §下一步) | |
| 148 | +- ⭐ **微信抽取端上化**(消除 photolog 仅剩的 Mac 依赖;见下文差距分析 #6) | |
| 149 | + | |
| 150 | +### App 即 Personal CRM:与旧 lemonPCRM 的能力对比 | |
| 151 | + | |
| 152 | +App(photolog)已覆盖、并在「联系人」维度超过旧 lemonPCRM 的核心: | |
| 153 | + | |
| 154 | +| 能力 | 旧 lemonPCRM(Mac/server) | 现 app(端上) | | |
| 155 | +|---|---|---| | |
| 156 | +| 联系人实体 | `Person` 图节点 | `Person`(融合 **声纹/人脸/微信/手机** 四模态,更丰富) | | |
| 157 | +| 多源导入 | 微信 / LinkedIn / X / 会议 / 照片 | 微信 + 手机通讯录 + 手动 + **24/7 录音(独有)** | | |
| 158 | +| 每人聚合视图 | 社媒动态 / 纪要 / 文件 / 照片 | 聊天 / 朋友圈 / 照片 / **录音** / AI 印象 / 简历(`PersonProfileScreen` 四 tab) | | |
| 159 | +| AI | Master Agent over 图谱(工具编排) | RAG 对话 over 转写/纪要(`LifelogRetriever`)+ AI 印象 | | |
| 160 | +| 照片 | 人脸聚类 + CLIP 检索 | 人脸聚类 + 语义检索(端上 ML Kit + ArcFace + Qwen-VL + embed) | | |
| 161 | +| 部署 | Mac Node 服务(依赖 Claude CLI) | **纯端上**(更隐私 / 零成本 / 零网络) | | |
| 162 | + | |
| 163 | +**仍存差距**(旧 lemonPCRM 有、app 还没有): | |
| 164 | + | |
| 165 | +1. **人↔人关系图**:app 只有 *人↔模态*(声纹/人脸/微信/手机)链接,**没有 person↔person 边**(KNOWS / 同事 / 同项目)。app 现在是「带富资料的扁平联系人表」,不是知识图谱。 | |
| 166 | +2. **Organization / Project / Event 实体**:app 只有 `Person`/`Photo`/`Face`,没有组织/项目/事件节点。 | |
| 167 | +3. **关系分析**:旧有 关系路径(`path`) / 社群发现(`communities`) / 待跟进(`followups`);app 三者皆无。 | |
| 168 | +4. **AI agent / 工具编排**:app 是**纯 RAG 对话**,AI 不能对数据做动作(建人 / 连边);旧有 Master→Sub-Agent + 图谱工具(`create_person`/`link_persons` 等)。 | |
| 169 | +5. **Transcript 内容 → 实体**:app 只按**声纹**把录音连到 `Person`(谁说的),**没有从转写文本抽人名/项目**做关联(旧 lemonPCRM 的 `MENTIONED_IN`)——这正是下一步要补的。 | |
| 170 | +6. **微信抽取端上化**:微信联系人/头像/聊天/朋友圈仍由 **Mac 一次性抽取**(解密 `EnMicroMsg.db` + 抠头像)推到 `filesDir/wx_enroll/`,再由 `WeChatEnrollWorker` 端上入库。手机系统通讯录已完全端上;微信抽取是「纯 App」最后一块拼图。 | |
| 171 | + | |
| 172 | +### 下一步:Transcript 实体 → 内部 Person 表(取代旧「回链 lemonPCRM」) | |
| 277 | 173 | |
| 278 | -### 与 lemonPCRM 的关系 | |
| 174 | +**不再回链外部 server**,改在 **app 内部**打通:从 `Transcript.text` / `Summary` 抽实体(人名/项目/地点,端上 LLM 或规则 NER)→ 与本地 `Person` 表匹配 → 建一张「提及」关系(新表 `mentions(segmentId, personId, ...)` 或 Person↔Segment 边)。让 `PersonProfileScreen` 除了现有「TA 自己说的」(声纹匹配段)之外,还能显示「**TA 被哪些录音提到、说了什么**」。这直接补差距 #5;同段被同时提到的人 → 共现边,又为差距 #1(人↔人关系图)打基础。 | |
| 279 | 175 | |
| 280 | -目前**完全独立**——lifelog-recorder 的 Room DB 跟 lemonPCRM 的 GraphStore 没打通。未来计划:把 Transcript / Summary 表里的实体(人名 / 地名 / 项目)抽到 GraphStore 当 `MENTIONED_IN` 边,让你的「某次会议说了什么」可以从图谱里反查。这是 v2 范畴。 | |
| 176 | +> 上面 6 项差距的**可执行 TODO 清单(带优先级 P0–P3 + 做法)**见 `lifelog-recorder/HANDOFF.md` §「端上 CRM 补齐 — TODO」。路线:P0 #5 → P1 #1 → P2 #6。 | |
| 281 | 177 | |
| 282 | 178 | ## 注意事项 |
| 283 | 179 | |
| 284 | -- `server/src/standalone-entry.js` 的 `loadConfig()` 优先读 `backends.json` + `agents.json`,无需数据库。 | |
| 285 | -- `prompt-builder.js` 的 `getSystemStateXML()` 只返回时间戳(公司/OKR 层已移除)。 | |
| 286 | -- Agent 目录内放 `SKILL.md` 文件会绕过协议封装,直接作为系统提示使用。 | |
| 287 | -- `server/index.js` 包含控制字符净化中间件:Agent 通过 curl 发送的 JSON body 可能含原始换行符,若解析失败会自动清理 `\x00-\x1F` 控制字符后重试。 | |
| 180 | +- **构建**:`cd lifelog-recorder && JAVA_HOME=/opt/homebrew/opt/openjdk@17 ./gradlew :app:assembleDebug`,`adb install -r ...`。无测试框架。改 Room schema **必须写 Migration**(`AppDatabase` 已去 destructive 改 fail-loud;24/7 录音库静默清掉是大事故,见 memory `lifelog-room-migration-wipe.md`)。 | |
| 181 | +- **改完即真机验证**:app 是 24/7 录音的命脉,改 `RecorderService` / 管线后务必装机看 logcat(`reconcile →` / `pipeline running` / `BlockProcessor`)确认录音没断。 | |
| 182 | +- **`keys.properties` / `local.properties` gitignored**:讯飞凭证 + Hermes 端点 → `BuildConfig`;`sdk.dir` 换机要改。模板见 `keys.properties.example`。 | |
| 183 | +- **`server/` `frontend/` `packages/`(旧 lemonPCRM)已废弃**:不再维护、不要往里加功能、不要让 app 依赖它。 | |
| 288 | 184 | |
| 289 | -> [!WARNING] (Agentic Self-Correction Loop Prevention) | |
| 290 | -> **Master Agent 必读**:在 `Bash` tool 中使用含多重双引号的复杂命令(如 `curl -d '{"id":"lemonv"}'`)时,JSON 转义容易崩溃并陷入死循环。 | |
| 291 | -> **解决方案**:任何需要提交 JSON Payload 的操作,先写入 `/tmp/*.json` 文件,再通过 `curl -d @/tmp/payload.json` 发送。 | |
| 185 | +> [!NOTE] 旧 lemonPCRM 的服务端架构(ACP 四层 / Master→Sub-Agent / GraphStore / 微信 server 链路)已从本文件移除。 | |
| 186 | +> 如确需考古,查 git 历史里本文件的早期版本。 | ... | ... |
lifelog-recorder/HANDOFF.md
| ... | ... | @@ -254,11 +254,35 @@ Tier-0 PhotoFaceWorker (15min, battery-not-low) Tier-1 PhotoVlWorker (1 |
| 254 | 254 | |
| 255 | 255 | 剩下: |
| 256 | 256 | |
| 257 | -1. **存储 TTL**:删超过 N 天的 .opus,文字永留。Periodic WorkManager job。 | |
| 258 | -2. **设置页**:存储用量、模型切换、provider 切换、暂停时段配置(v1 定的 MVP 是「一键暂停就够」,但 v2 可能要细化)。 | |
| 257 | +1. ✅ **存储 TTL**(2026-06-08 完成):`StorageManager.prune` 按天目录删超期 .opus、文字永留;每天 periodic worker;设置页「存储」段(用量 + 保留时长 + 立即清理),默认永久保留。 | |
| 258 | +2. ✅ **设置页**(基本完成):`SettingsScreen` 已含 纪要模型后端 / 聚类·合并·最短识别阈值 / llama-swap 端点 / 分段间隔 / **定时不录(quiet hours)** / 存储用量+TTL / 电池豁免。 | |
| 259 | 259 | 3. ✅ **多 anchor 平均**(2026-06-07 完成,L2):重命名/合并某说话人时 `rebuildAnchor` 用该人名下全部段的均值重建 anchor,取代单段注册。 |
| 260 | -4. **回链 lemonPCRM**:Transcript 提到的人名 / 项目 → GraphStore `MENTIONED_IN` 边。 | |
| 260 | +4. **内部 Transcript 实体 → Person 表**(取代旧「回链 lemonPCRM」):在 **app 内部**从 `Transcript.text`/`Summary` 抽实体(人名/项目,端上 LLM 或规则 NER)→ 匹配本地 `Person` → 建「提及」关系(新表 `mentions(segmentId, personId)`),让人物档案显示「TA 被哪些录音提到」(现仅显示「TA 自己说的」=声纹段)。同段共现的人 → 人↔人边。**不再回链 Mac 端 lemonPCRM**(已废弃)。 | |
| 261 | 261 | 5. ✅ **hermes gateway 自启**(2026-06-04 完成):用 Magisk `service.d` 脚本开机拉起(Termux:Boot 未装,root 方案更稳),见下方「§ 自启(Magisk service.d)」。 |
| 262 | +6. **微信抽取端上化**:消除 photolog 仅剩的 Mac 依赖(微信联系人/头像/聊天/朋友圈现由 Mac 一次性抽取推到 `filesDir/wx_enroll/`)。 | |
| 263 | + | |
| 264 | +### 端上 CRM 补齐 — TODO(对齐并超越旧 lemonPCRM) | |
| 265 | + | |
| 266 | +> 旧 Mac 端 lemonPCRM 已废弃,能力在 app 内重建。下表是「app 当前缺、旧 lemonPCRM 有」的 6 项, | |
| 267 | +> 按优先级排(P0 先做)。能力对比详见 CLAUDE.md §「App 即 Personal CRM」。 | |
| 268 | + | |
| 269 | +- [ ] **P0 · #5 Transcript 内容 → Person「提及」关系**(最高价值,最贴 app 形态) | |
| 270 | + - 现状:录音只按**声纹**连到人(谁说的);不从转写文本抽人名/项目。 | |
| 271 | + - 做法:块处理后(或事后 worker)对 `Transcript.text` 抽实体(端上 LLM 4B 或规则/词典 NER)→ 匹配本地 `Person`(name/realName/nickname/alias,拼音兜底)→ 写新表 `mentions(segmentId, personId, name, confidence)`(Room 迁移 +1)。 | |
| 272 | + - 出口:`PersonProfileScreen` 加「被提到」tab(现只有「TA 自己说的」=声纹段)。 | |
| 273 | + - 依赖:端上 4B 已就绪(llama-swap 8080)。 | |
| 274 | +- [ ] **P1 · #1 人↔人关系(共现边)** | |
| 275 | + - 做法:基于 #5,同一会话/时间段被同时提到 + 同时在场(声纹)的人 → `relations(personA, personB, kind, weight)` 共现/认识边,weight 随共现次数累加。 | |
| 276 | + - 出口:人物档案「相关的人」;后续可做关系图可视化。 | |
| 277 | +- [ ] **P2 · #6 微信抽取端上化**(消除最后的 Mac 依赖,工程债) | |
| 278 | + - 现状:微信联系人/头像/聊天/朋友圈由 Mac 解密 `EnMicroMsg.db`(SQLCipher)+抠头像,推到 `filesDir/wx_enroll/`。 | |
| 279 | + - 做法:把解密+抽取搬到端上(root + SQLCipher key 端上取),`WeChatEnrollWorker` 直接读微信库;配方见 memory `wechat-android-decrypt.md` / `wechat-avatar-face-enrollment.md`。 | |
| 280 | +- [ ] **P3 · #2 Organization / Project / Event 实体**(产品决策:要不要从「联系人表」长成「图谱」) | |
| 281 | + - 新增节点类型 + 与 Person 的边(属于/参与);可由 #5 的实体抽取顺带产出(项目名/公司名/事件)。 | |
| 282 | +- [ ] **P3 · #3 关系分析**:关系路径(两人间最短链)/ 社群发现(聚类)/ 待跟进(followups:从录音承诺「下周给他发X」抽待办)。依赖 #1 的关系边。 | |
| 283 | +- [ ] **P3 · #4 AI 能对数据做动作(agent/工具编排)**:让对话 AI 不止 RAG 问答,还能调工具建人/连边/改资料(端上轻量 tool-calling,Hermes 或本地模型)。最大、最后做。 | |
| 284 | + | |
| 285 | +> 路线:**P0(#5) → P1(#1) → P2(#6)**,三步把「录音→人→关系」在端上闭环;P3 三项是「要不要把 app 升级成真·知识图谱 + AI agent」的产品选择,按需再开。 | |
| 262 | 286 | |
| 263 | 287 | ### hermes gateway 设置(v0.5 关键前置) |
| 264 | 288 | ... | ... |