diff --git a/README.md b/README.md index 4c8e5d4..5c72535 100644 --- a/README.md +++ b/README.md @@ -25,16 +25,14 @@

- TraceMemo 主界面 + TraceMemo 日报

- TraceMemo 问问微信 + TraceMemo 自动化

-

- TraceMemo 退群监控 -

+ --- ## 🎨 社区日报模板 @@ -49,7 +47,7 @@ TraceMemo 日报除了内置版式,也支持从社区模板市场安装更多 在 TraceMemo 中打开: -**日报 → 今日日报 → 日报模板 → 模板市场** +**日报 → 社区模板市场** 即可查看、预览、安装和切换已发布的社区模板。 @@ -67,18 +65,21 @@ TraceMemo(迹忆)原名 **WechatExplorer** 是一款本地优先的微信数 ## 核心能力 -- 💬 **聊天档案与搜索**:浏览会话,按关键词或身份信息查找。 +- 💬 **聊天档案与搜索**:浏览会话,按关键词、备注、昵称或 wxid 查找消息。 - 🔍 **AI Search / 问问微信**:用自然语言找回模糊记忆,并查看来源。 -- 🧠 **本地知识库**:建立索引,提升跨会话查询稳定性。 -- 📊 **群聊日报**:生成今日、昨日或近 7 天的群聊总结。 -- 👀 **群成员变化监控**:记录指定群聊的退群动态。 -- 🔊 **文字转语音**:生成语音,试听后发送到选定会话。 -- 🤖 **Agent Hub**:在微信里调用本机 TraceMemo。 -- 🔌 **外部 Agent / Local HTTP API**:让外部 Agent 查询本机微信历史。 +- 🧠 **本地知识库**:在本机建立索引,让跨会话、跨时间的查询更稳定。 +- 🖼️ **图片文字索引**:在本机识别微信图片里的文字(截图、公告、报价图),识别结果可以在搜索和「问问微信」里被检索。识别全程不联网,原始图片不会因为本地识别而上传。 +- 📊 **群聊日报**:生成今日、昨日或近 7 天的群聊总结,可保存为 HTML 与 PNG。 +- 🗣️ **群发言统计**:统计群成员的发言量和沉默成员,看清一个群里谁在说、谁一直没说。 +- 👀 **退群监控**:用成员快照对比记录群成员退出事件,支持多群与事件历史。 +- ⚙️ **自动化**:把上面几步按规则串起来——定时生成并发送日报、成员退群时发送通知;能发到哪里取决于当前的发送能力。 +- 🔊 **文字转语音**:把文字生成语音,试听后发送到当前会话。 +- 🤖 **Agent Hub**:在微信里向本机 TraceMemo 提问。 +- 🔌 **外部 Agent / Local HTTP API**:让 Codex 等外部 Agent 查询本机微信历史。 ## 💻 平台支持 -TraceMemo 2.4.0 支持: +TraceMemo 2.5.0 支持: - **Windows x64** - **macOS Apple Silicon(M 系列 / arm64)** @@ -86,6 +87,12 @@ TraceMemo 2.4.0 支持: Windows 与 macOS 均支持微信本地数据库连接与数据库 Key 获取。 +### 关于“发送能力” + +浏览、搜索、日报生成、导出、知识库和图片文字索引都不需要额外的发送组件。只有**把内容真正发回微信**这一步——自动发送日报、退群通知、把语音发到会话——依赖本机发送能力: + +发送能力未就绪、未绑定或发送失败时,报告本身仍会正常生成并保存在本机,执行记录会显示为“已生成,但未发送”或“已生成,发送失败”,可以稍后重试。 + ## 项目缘起
@@ -138,11 +145,14 @@ TraceMemo 最早叫 **WechatExplorer**。 | 想做什么 | 使用入口 | | ---------------------------------- | ----------------------------- | | 找记得原文或关键词的消息 | 档案搜索 | -| 找记得大意、但不知道在哪聊过的内容 | AI Search / 问问微信 | +| 找记得大意、但不知道在哪聊过的内容 | 问问微信(AI Search) | +| 找到截图、公告图里写过的文字 | 问问微信 → 图片文字索引 | | 长期跨群查询历史 | 本地知识库 | -| 了解一个群今天或近 7 天聊了什么 | 群聊日报 | +| 了解一个群今天或近 7 天聊了什么 | 日报 | +| 看群里谁最活跃、谁一直没说话 | 档案 → 群聊 → 群发言统计 | | 持续关注群成员退出 | 退群监控 | -| 按计划生成并发送群聊日报 | 定时日报 | +| 按计划自动生成并发送群聊日报 | 自动化 | +| 成员退群时自动发一条通知 | 自动化 → 退群通知 | | 把文字生成微信语音 | 文字转语音 | | 在微信里向本机 TraceMemo 提问 | Agent Hub | | 让 Codex 等工具查询微信历史 | Reader Skill / Local HTTP API | @@ -159,9 +169,9 @@ TraceMemo 最早叫 **WechatExplorer**。 ## 文档 -- [用户指南](./docs/README.md#用户指南) +- [用户指南](./docs/README.md#档案与搜索) - [AI / Knowledge](./docs/README.md#ai-与知识库) -- [Monitor / Automation](./docs/README.md#日报与自动化) +- [日报与自动化](./docs/README.md#日报与自动化) - [Agent / API](./docs/README.md#agent--api) - [开发文档](./docs/development/overview.md) - [隐私与安全](./docs/user-guide/privacy.md) @@ -213,7 +223,7 @@ TraceMemo 在早期适配微信 4.x 时,曾参考 **[WeFlow](https://github.co 这个项目起初只是一个一时兴起的项目,所以它大概也不会有一份特别严肃的产品路线图。 -我可能会按照自己的兴趣继续折腾,也可能突然加入一些奇奇怪怪、但觉得有意思的功能—— 比如让AI给某个好友, 某个群发一个语音条(逗逗群友) 或者定时生成群聊日报并做成微信卡片。 +我可能会按照自己的兴趣继续折腾,也可能突然加入一些奇奇怪怪、但觉得有意思的功能 也因此,这个项目随时可能继续折腾,也可能因为其他事情暂时搁置。如果你有想要的功能,可以提Issue;如果觉得现有实现不符合你的需求,也欢迎直接 Fork 后自己改。 diff --git a/docs/README.md b/docs/README.md index 86d94f6..5493ace 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,29 +6,29 @@ - [第一次使用](./user-guide/getting-started.md):安装、连接微信并完成第一次搜索。 - [Intel Mac 获取微信密钥](./user-guide/intel-mac-key.md):按页面检查结果准备环境并获取密钥。 -- [聊天档案与搜索](./user-guide/chat-archive.md):浏览联系人和群聊,按关键词、备注、昵称、微信号或 wxid 查找消息;也包含档案中的文字转语音入口。 +- [聊天档案与搜索](./user-guide/chat-archive.md):浏览联系人和群聊,按关键词、备注、昵称、微信号或 wxid 查找消息;也包含档案中的文字转语音入口,以及群聊里的「群发言统计」。 ## AI 与知识库 - [AI Search / 问问微信](./user-guide/ai-search.md):用自然语言找回记得大意、但不知道在哪个会话里的内容,并查看 Evidence、Citation 和 Search Trace。 -- [本地知识库](./user-guide/knowledge.md):主动建立本地索引,提升跨会话、跨时间查询的稳定性。 +- [本地知识库](./user-guide/knowledge.md):主动建立本地索引,提升跨会话、跨时间查询的稳定性;也包括在本机识别图片文字、让截图和公告图变得可搜索的「图片文字索引」。 - [如何核对 AI 的回答来源](./concepts/answer-sources.md):从来源回到原始消息,检查上下文和覆盖范围。 - [从微信数据到回答、日报和导出](./concepts/how-it-works.md):了解哪些步骤在本机完成,哪些 AI 功能可能调用 Provider。 ## 日报与自动化 -- [群聊日报](./user-guide/report.md):手动生成今日、昨日或近 7 天的群聊报告,也可以创建定时日报。 -- 定时日报会依次生成报告、保存 Report History,再按当前微信发送能力尝试通知;发送失败时可复用已有 PNG 重试。 +- [群聊日报](./user-guide/report.md):手动生成今日、昨日或近 7 天的群聊报告,也可以在「自动化」里创建定时日报。 +- 「自动化」按三类规则执行:**@我生成日报**、**定时日报**、**退群通知**。定时日报会依次生成报告、保存 Report History,再按当前微信发送能力尝试通知;发送失败时可复用已有 PNG 重试。 - 自动发送和监控动作通过统一执行边界,并保留执行记录;简要说明见[产品工作方式](./concepts/how-it-works.md#动作执行与审计)。 -## Monitor +## 退群监控 -退群监控会比较当前成员与上一份有效快照,记录成员退出事件。它支持多群、Last Good Snapshot 和事件历史;监控关闭期间的变化不会在重新开启后补报。工作方式见[产品工作方式](./concepts/how-it-works.md#退群监控)。 +退群监控会比较当前成员与上一份有效快照,记录成员退出事件。它支持多群、Last Good Snapshot 和事件历史;监控关闭期间的变化不会在重新开启后补报。成员退出同时是「自动化 → 退群通知」的触发条件。工作方式见[产品工作方式](./concepts/how-it-works.md#退群监控)。 ## 语音能力 - [语音转文字](./user-guide/voice.md):在本机转写微信语音,结果可用于搜索、Knowledge 和导出。 -- [聊天档案与搜索](./user-guide/chat-archive.md#文字转语音):把文字生成微信语音,试听后发送到当前联系人或群聊。 +- [聊天档案与搜索](./user-guide/chat-archive.md#文字转语音):把文字生成微信语音,试听后发送到当前联系人或群聊;实际发送依赖本机发送能力。 ## Agent / API diff --git a/docs/agent/agent-hub.md b/docs/agent/agent-hub.md index 6db21ac..4f820e3 100644 --- a/docs/agent/agent-hub.md +++ b/docs/agent/agent-hub.md @@ -21,14 +21,15 @@ Agent Hub 是 TraceMemo 内置的微信机器人入口,也是应用一级导 - “帮我看看最近跟某人聊了些什么。” - “生成产品交流群今天的群聊总结图片。” -当前已实现的实时任务包括: +Hub 把入站文字分成两类处理。 -- 查看最近会话(数量限制为 1–20); -- 查询你和某位联系人的近期聊天; -- 用已配置的 AI 总结你和某位联系人近 7 天的聊天; -- 生成今天、昨天或近 7 天的群聊总结图片; -- 总结指定群成员在群里的近期发言; -- 对不需要读取聊天的普通文字请求返回简短 AI 回复。 +**确定性的快捷动作**(不经过模型,命中就执行): + +- 查看最近会话:数量限制为 1–20; +- 生成群聊总结图片:今天、昨天或近 7 天(需要同时提到“群”和“图片 / 长图 / 日报 / 报告”); +- 分析某个群成员的近期发言:可以指定“今天 / 昨天 / 最近 N 天”。 + +**其余问题**交给本机的 Query Agent:它和桌面端“问问微信”使用的是同一个实现,可以按需读取联系人、会话和时间范围来回答,必要时调用你在“设置 → AI 模型”里配置的 AI。例如“帮我看看最近跟某人聊了些什么”“上个月讨论过的项目地址在哪里”。 任务完成后,回复会发送回触发这次请求的微信用户。群聊总结会先发送进度提示,完成后发送图片。 @@ -56,12 +57,12 @@ Agent Hub 页面会记录系统、Agent Hub 和微信连接器日志。日志支 ## 安全与边界 -- Hub 使用本机通信,不把数据库直接暴露到公网; +- Hub 在主进程内运行,不开放本地监听端口;它不会把数据库暴露到公网; - 机器人账号和个人微信账号是不同的登录边界,请确认你连接的是正确账号; - 机器人回复会发送给当前发消息的人;开发者 API 另有受保护的测试发送入口,使用前必须确认接收者; -- Hub 生成群聊总结时仍可能调用你配置的 AI Provider; -- 当前实时自然语言入口主要处理文字消息。底层连接器可以接收图片、语音、文件和视频,但 Agent Hub 尚未为这些媒体提供同等的实时意图处理; -- 当前没有实现群发、广播、定时任务或通用自主操作微信; +- Hub 理解请求或生成总结时,会调用你在“设置 → AI 模型”配置的 Provider; +- 当前实时入口只处理文字消息。连接器会归一化收到的消息条目,但 Agent Hub 只把文本条目当作意图处理,尚未为图片、语音、文件和视频提供同等能力; +- 当前没有实现群发、广播、定时任务或通用自主操作微信(定时日报属于「自动化」,不是 Agent Hub); - 本页面的“Agent Hub 状态”可以通过 Local HTTP API 查询,但不要把它误认为外部 Agent 的实时消息订阅接口或 MCP Server。 ## 无法连接时 diff --git a/docs/agent/api-security.md b/docs/agent/api-security.md index df52bc2..d971777 100644 --- a/docs/agent/api-security.md +++ b/docs/agent/api-security.md @@ -4,9 +4,11 @@ TraceMemo 的本地 API 默认监听 `127.0.0.1:6131`。它面向同一台电脑上的 API Center、Reader Skill、CLI 和 Agent,不是公网网关,也不是带用户账户和细粒度权限 Scope 的服务。 +它同时包含**写入型**端点:生成报告并渲染 PNG(`/report`)、通过已连接机器人发送微信消息(`/agent/send`)、创建/修改/删除/启停定时日报任务并触发立即执行(`/scheduled-reports*`)。因此这个 Token 相当于本机敏感凭据,而不是一个只读查询键。 + ## Bearer Token -新 Agent 配置使用 `TRACEMEMO_API_TOKEN`。v2.2.0 仍兼容读取历史变量 `WECHATEXPLORER_API_TOKEN`,优先级为新变量高于旧变量。 +新 Agent 配置使用 `TRACEMEMO_API_TOKEN`。历史变量名 `WECHATEXPLORER_API_TOKEN` 仍被兼容读取,优先级为新变量高于旧变量;当前没有设定旧变量名的移除时间,新配置不要再使用它。 - `/api/v1/health` 是公开健康检查; - 其他所有端点都要求 `Authorization: Bearer `; @@ -14,7 +16,8 @@ TraceMemo 的本地 API 默认监听 `127.0.0.1:6131`。它面向同一台电脑 - Token 由 Electron `safeStorage` 加密保存在用户数据目录的 `local-api-token.bin`; - 文件权限设置为 `0600`; - 在“API Center”中可以显示、复制和重新生成; -- 重新生成后旧 Token 立即失效。 +- 重新生成后旧 Token 立即失效; +- 服务端只认这个 Token,**不接受用环境变量覆盖**——Agent 一侧的环境变量只是把 Token 交给 Agent 自己的方式,不是鉴权来源。 应用不会自动把 Token 写入 Codex、Claude Code、OpenClaw 或其他 Agent 配置。请把它放进 Agent 自己的本地 secret/environment,例如: diff --git a/docs/agent/api.md b/docs/agent/api.md index 7fb32d3..36424ef 100644 --- a/docs/agent/api.md +++ b/docs/agent/api.md @@ -24,31 +24,48 @@ curl -H "Authorization: Bearer $TRACEMEMO_API_TOKEN" \ 不要把 Token 放入 URL、Skill 文件、仓库或命令历史可被共享的脚本中。 -新配置必须优先使用 `TRACEMEMO_API_TOKEN`。已安装的旧 Reader Skill 可在 v2.2.0 兼容期内继续读取 `WECHATEXPLORER_API_TOKEN`;如果两个变量都存在,以新变量为准。 +新配置必须优先使用 `TRACEMEMO_API_TOKEN`。应用生成的安装指令仍会提示:尚未升级的旧配置可以继续读取 `WECHATEXPLORER_API_TOKEN`,但新配置必须使用新变量名;如果两个变量都存在,以新变量为准。当前没有设定旧变量名的移除时间。 + +Token 由应用生成并保存在本机,**不接受用环境变量覆盖**:Agent 侧的环境变量只是把 Token 传给 Agent 自己的方式,不是服务端的鉴权来源。 ## 端点 -| 方法 | 路径 | 作用 | 参数/请求体 | -| ---- | ---------------------------- | -------------------------------------- | --------------------------------------------------------------- | -| GET | `/api/v1/health` | 服务与数据库健康状态 | 无 | -| GET | `/api/v1/current_time` | 本机时间、时区和 Unix 时间戳 | 无 | -| GET | `/api/v1/contact` | 联系人和群聊列表 | `filter`、`type=user\|group` | -| GET | `/api/v1/chatroom` | 群聊列表 | `keyword` | -| GET | `/api/v1/recent_chat` | 最近会话 | `limit`,默认 50 | -| GET | `/api/v1/chatlog` | 指定会话的聊天记录 | 必填 `talker`;可选 `time` 或 `startTime`/`endTime` | -| GET | `/api/v1/media/{mediaId}` | 获取图片消息的二进制资源 | 原样使用 `/chatlog` 返回的 `media.url`,不要用消息 `id` 拼接 | -| GET | `/api/v1/group_snapshot` | 群成员快照 | 必填 `md5` | -| GET | `/api/v1/resolve` | 将昵称、wxid 或 md5 解析为会话 | 必填 `q` | -| POST | `/api/v1/report` | 将结构化日报渲染为 HTML 与 PNG | `GroupReportExportRequest` JSON | -| GET | `/api/v1/agent/status` | Agent Hub、连接器和数据库状态 | 无 | -| POST | `/api/v1/agent/group-report` | 读取群聊并生成总结图片 | `{ "group": "群名或标识", "range": "today\|yesterday\|7days" }` | -| POST | `/api/v1/agent/send` | 通过已连接机器人测试发送文字或本地图片 | `{ "to": "接收者", "text": "...", "media_url": "..." }` | +| 方法 | 路径 | 作用 | 参数/请求体 | +| ------ | --------------------------------------------------------------- | -------------------------------------- | --------------------------------------------------------------- | +| GET | `/api/v1/health` | 服务与数据库健康状态 | 无 | +| GET | `/api/v1/current_time` | 本机时间、时区和 Unix 时间戳 | 无 | +| GET | `/api/v1/contact` | 联系人和群聊列表 | `filter`、`type=user\|group` | +| GET | `/api/v1/chatroom` | 群聊列表 | `keyword` | +| GET | `/api/v1/recent_chat` | 最近会话 | `limit`,默认 50 | +| GET | `/api/v1/chatlog` | 指定会话的聊天记录 | 必填 `talker`;可选 `time` 或 `startTime`/`endTime` | +| GET | `/api/v1/media/{mediaId}` | 获取图片消息的二进制资源 | 原样使用 `/chatlog` 返回的 `media.url`,不要用消息 `id` 拼接 | +| GET | `/api/v1/group_snapshot` | 群成员快照 | 必填 `md5` | +| GET | `/api/v1/resolve` | 将昵称、wxid 或 md5 解析为会话 | 必填 `q` | +| POST | `/api/v1/report` | 将结构化日报渲染为 HTML 与 PNG | `GroupReportExportRequest` JSON | +| GET | `/api/v1/agent/status` | Agent Hub、连接器和数据库状态 | 无 | +| POST | `/api/v1/agent/group-report` | 读取群聊并生成总结图片 | `{ "group": "群名或标识", "range": "today\|yesterday\|7days" }` | +| POST | `/api/v1/agent/send` | 通过已连接机器人测试发送文字或本地图片 | `{ "to": "接收者", "text": "...", "media_url": "..." }` | +| GET | `/api/v1/wechat-personal/send-capability` | 个人微信发送能力状态 | 无 | +| GET | `/api/v1/scheduled-reports` | 定时日报任务列表 | 无 | +| POST | `/api/v1/scheduled-reports` | 创建定时日报任务 | `ScheduledReportApiCreateRequest` JSON | +| GET | `/api/v1/scheduled-reports/{id}` | 查询单个定时日报任务 | 无 | +| PATCH | `/api/v1/scheduled-reports/{id}` | 修改定时日报任务 | `ScheduledReportApiUpdateRequest` JSON | +| DELETE | `/api/v1/scheduled-reports/{id}` | 删除定时日报任务 | 无 | +| POST | `/api/v1/scheduled-reports/{id}/enable` | 启用定时日报任务 | 无 | +| POST | `/api/v1/scheduled-reports/{id}/disable` | 暂停定时日报任务 | 无 | +| POST | `/api/v1/scheduled-reports/{id}/run` | 立即执行一次并返回 execution | 无 | +| GET | `/api/v1/scheduled-reports/{id}/executions` | 查询某个任务的执行记录 | 无 | +| POST | `/api/v1/scheduled-reports/executions/{executionId}/retry-send` | 复用已有 PNG 重试发送 | 无 | + +`/api/v1/query/*` 是一组结构化的 Query 端点,见下方[LLM-friendly Query Tool API](#llm-friendly-query-tool-api)。 ### 这些端点与实时机器人有什么关系 - `/api/v1/agent/status` 只用于查询 Agent Hub、微信连接器和数据库状态; - `/api/v1/agent/group-report` 由外部 Agent 或脚本主动请求生成群聊总结图片; - `/api/v1/agent/send` 是受 Bearer Token 保护的开发者/测试发送入口,用于通过已经连接的机器人发送文字或本地图片;它不是任意群发能力,也不是实时消息订阅接口; +- `/api/v1/scheduled-reports*` 会**写入**应用状态:创建、修改、删除、启停定时日报任务,以及立刻执行一次。加上 `/report` 和 `/agent/send`,这个 API 并非只读接口——拿到 Token 就能改配置、生成报告并发送微信消息,请按本机敏感凭据对待; +- `POST /api/v1/scheduled-reports/{id}/run` 与定时触发共用同一条链路:读取群聊 → 生成报告 → 保存 Report History → 尝试发送; - 当前 API 没有对外暴露实时入站 webhook。微信消息由应用内部的 Agent Hub 和微信连接器接收、处理和回复。 ## 时间查询 @@ -83,10 +100,12 @@ curl -H "$AUTH" "$BASE/chatlog?talker=技术交流群&time=2026-08-07" ## 响应与错误 - `200`:请求成功; +- `201`:定时日报任务创建成功; - `401`:缺少、错误或已失效的 Bearer Token; - `400`:参数或 JSON 请求体无效; - `422`:媒体标识格式错误,或目标消息不是可读取的图片(`NOT_IMAGE`); - `403`:浏览器 Origin 不在允许的 loopback 列表; +- `409`:定时日报任务重复(`error === "duplicate"`,响应里会带回已存在的任务),或群聊名称匹配到多个目标(`ambiguous_contact`); - `404`:端点、会话或群聊不存在;媒体标识未登记、已过期、有歧义,或图片文件不存在(`NOT_FOUND`)。媒体请求遇到此状态时,先重新读取 `/chatlog` 并使用新的 `media.url`;若仍失败,再检查本地图片文件是否存在; - `503`:数据库或 Agent Hub 尚未就绪; - `500`:服务端处理或报告渲染失败。 @@ -154,12 +173,12 @@ curl -X POST -H "$AUTH" -H 'Content-Type: application/json' "$BASE/query/convers `query/messages`、`query/search`、`query/message-context` 和 `query/conversation-overview` 都接受一个可选的 `scope`,用来把检索限制在一个确定的语料边界内: -| scope | 含义 | -| ----- | ---- | -| `{"kind":"all"}` | 所有可读会话(默认;省略 `scope` 等价于此) | -| `{"kind":"groups"}` | 只搜群聊语料,**且包含群成员实际发送的消息**(不是群名称或群元数据) | -| `{"kind":"contact","conversationId":"…"}` | 只搜该一对一会话 | -| `{"kind":"current","conversationId":"…"}` | 只搜指定的那个会话(单聊或群聊) | +| scope | 含义 | +| ----------------------------------------- | -------------------------------------------------------------------- | +| `{"kind":"all"}` | 所有可读会话(默认;省略 `scope` 等价于此) | +| `{"kind":"groups"}` | 只搜群聊语料,**且包含群成员实际发送的消息**(不是群名称或群元数据) | +| `{"kind":"contact","conversationId":"…"}` | 只搜该一对一会话 | +| `{"kind":"current","conversationId":"…"}` | 只搜指定的那个会话(单聊或群聊) | `conversationId` 是会话标识,可用 `/api/v1/resolve` 或 `/api/v1/contact` 得到。`scope` 一旦给出就是**权威边界**:`target` 落在范围之外会被拒绝(`status: "invalid_tool_arguments"`、`constraint: "target_outside_scope"`),不会静默扩大范围;范围里包含多个会话时,`query/messages` 与 `query/conversation-overview` 必须显式指定 `target`(`constraint: "target_required_for_scope"`)。 @@ -186,11 +205,11 @@ curl -X POST -H "$AUTH" -H 'Content-Type: application/json' "$BASE/query/convers `query/search` 依赖本地索引,而本地索引是异步建立的派生数据,可能落后于聊天数据库。因此它的响应会显式给出覆盖口径: -| 字段 | 含义 | -| ---- | ---- | -| `indexLatestAt` | 索引目前覆盖到的源数据时间(epoch ms),`null` 表示无法判定 | -| `sourceLatestAt` | 聊天数据库里最新的活跃时间(epoch ms),`null` 表示无法判定 | -| `coverage.state` | `complete` 只在索引确实覆盖了所请求的时间范围时出现 | +| 字段 | 含义 | +| ------------------- | ------------------------------------------------------------------- | +| `indexLatestAt` | 索引目前覆盖到的源数据时间(epoch ms),`null` 表示无法判定 | +| `sourceLatestAt` | 聊天数据库里最新的活跃时间(epoch ms),`null` 表示无法判定 | +| `coverage.state` | `complete` 只在索引确实覆盖了所请求的时间范围时出现 | | `freshness.catchUp` | 本次为追赶索引做了什么:`none` / `reused` / `completed` / `pending` | 调用方**必须**把 `coverage` 当真:`coverage.state` 不是 `complete` 且 `evidence` 为空时,只能说明"这段范围暂时无法确认",**不能**下"没有找到"的结论。索引落后时服务端会自动请求一次追赶同步,但不会让请求无限等待;`freshness.catchUp` 为 `pending` 表示追赶仍在后台进行,稍后重试即可拿到更新的覆盖。 diff --git a/docs/agent/reader-skill.md b/docs/agent/reader-skill.md index 4ef66b3..45ec8a8 100644 --- a/docs/agent/reader-skill.md +++ b/docs/agent/reader-skill.md @@ -8,7 +8,7 @@ Reader Skill 是一份给 Agent 的操作说明。安装后,Codex、Claude Cod Reader Skill 只负责“外部 Agent 主动查询历史微信数据”。它不负责二维码登录、监听微信实时消息、接收机器人消息或管理 Agent Hub。想让机器人收到微信消息后处理并回复,请阅读[Agent Hub](./agent-hub.md)。 -正式 Reader Skill 名称和目录是 `tracememo-reader`,新安装使用 `TRACEMEMO_API_TOKEN`。已安装的旧 `wechatexplorer-reader` 可在 v2.2.0 兼容期内继续使用旧变量。 +正式 Reader Skill 名称和目录是 `tracememo-reader`,新安装使用 `TRACEMEMO_API_TOKEN`。已安装的旧 `wechatexplorer-reader` 仍可继续使用旧变量 `WECHATEXPLORER_API_TOKEN`(当前没有设定移除时间),但新安装请使用新名称与新变量名。 ## 推荐安装流程 @@ -53,8 +53,13 @@ Reader Skill 可以指导 Agent 使用: - 指定会话、日期或时间戳范围的聊天记录; - 群成员快照; - 结构化日报渲染和按群聊生成总结图片; +- 定时日报任务的查询、创建、修改、启停、删除、立即执行和执行记录;删除不可逆,Skill 要求先列出唯一任务并取得用户明确确认; +- 个人微信发送能力状态查询(`/wechat-personal/send-capability`); +- `query/*` 一组结构化 Query 端点:`messages`、`search`、`message-context`、`conversation-overview`; - Agent Hub 状态检查与已连接机器人发送测试。这里的发送接口是开发者/测试用途,不是实时机器人入口,也不会让 Reader Skill 自动监听微信消息。 +注意这个 API 不只是只读的:`/report`、`/agent/send` 和 `/scheduled-reports*` 会写入状态或真的发出微信消息。 + 端点、参数、错误码和鉴权细节以[Local HTTP API](./api.md)为准。Skill 文件保持短小,避免在多个文档中复制会变化的完整响应 schema。 ## 隐私边界 diff --git a/docs/concepts/how-it-works.md b/docs/concepts/how-it-works.md index a773dfd..2e746a7 100644 --- a/docs/concepts/how-it-works.md +++ b/docs/concepts/how-it-works.md @@ -4,39 +4,54 @@ ```mermaid flowchart LR - A[本机微信数据] --> B[读取与解析] - B --> C[聊天档案与普通搜索] - B --> D[本地知识索引] - D --> E[筛选相关消息] - E --> F[用户配置的 AI Provider] - F --> G[回答与可核对来源] - B --> H[聊天导出] - B --> I[整理日报输入] - I --> F - F --> J[本地保存 HTML 与 PNG] - B --> K[Local HTTP API] - K --> L[外部 Agent] - M[微信机器人消息] --> N[Agent Hub] - N --> B - N --> F - B --> O[Monitor / Snapshot] - O --> P[Proposed Action] - F --> P - P --> Q[Policy] - Q --> R[Action Gateway] - R --> S[Personal WeChat Send Capability] - S --> T[Action Audit / Logs] + WX["本机微信数据"] --> PARSE["读取与解析"] + + PARSE --> ARCHIVE["聊天档案与普通搜索"] + PARSE --> EXPORT["聊天导出"] + + PARSE --> IDX["本机索引"] + IDX --> TEXTIDX["聊天记录索引"] + IDX --> IMGIDX["图片文字索引(本机识别)"] + + TEXTIDX --> UNDERSTAND["Understand:AI Search / 问问微信"] + IMGIDX --> UNDERSTAND + UNDERSTAND --> PROVIDER["你配置的 AI Provider"] + PROVIDER --> ANSWER["回答与可核对来源"] + + PARSE --> REPORTINPUT["整理日报输入"] + REPORTINPUT --> PROVIDER + PROVIDER --> REPORTFILE["本机保存 HTML 与 PNG"] + + PARSE --> MONITOR["Monitor:退群监控 / 成员快照"] + MONITOR --> RULE["自动化规则"] + REPORTFILE --> RULE + RULE --> POLICY["Policy"] + POLICY --> GATEWAY["Action Gateway"] + GATEWAY --> CAP["本机发送能力"] + CAP --> AUDIT["执行记录与审计"] + + PARSE --> API["Local HTTP API"] + API --> EXTAGENT["外部 Agent / Reader Skill"] + BOT["微信机器人消息"] --> HUB["Agent Hub"] + HUB --> PARSE + HUB --> PROVIDER ``` -## Remember → Understand → Monitor → Act +## Remember → 图片文字 → Understand → Monitor → Act TraceMemo 的工作方式可以概括为: ```text -Remember → Understand → Monitor → Act +Remember → 图片文字 → Understand → Monitor → Act ``` -先读取和整理微信信息,再由 AI、Knowledge 或日报帮助理解;Monitor 负责发现成员变化,明确的业务动作再进入执行边界。回答和动作结果都应能回到来源或记录核对。 +- **Remember**:读取并解析本机微信数据,建立聊天档案、普通搜索和导出。 +- **图片文字**:在本机识别图片里的文字,把截图、公告、报价图也变成可检索的内容。这一步不联网。 +- **Understand**:Knowledge、AI Search / 问问微信、群聊日报。需要模型时,只把完成这次任务所需的受控上下文交给 Provider。 +- **Monitor**:用成员快照对比发现群成员变化,产出成员退出事件。 +- **Act**:自动化规则把前面的步骤串起来(定时日报、退群通知);动作经过统一执行边界,并留下执行记录。 + +回答和动作结果都应能回到来源或记录核对。 ## 退群监控 @@ -46,7 +61,9 @@ Remember → Understand → Monitor → Act Current Membership → Snapshot Diff → Member Event ``` -上一份有效快照(Last Good Snapshot)不会被不完整读取覆盖,因此重启后仍可继续监控通知。 +上一份有效快照(Last Good Snapshot)不会被不完整读取覆盖,因此重启后仍可继续监控通知。监控关闭期间发生的变化,不会在重新开启后补报。 + +成员退出事件同时是「自动化」里「退群通知」规则的触发条件。 ## 动作执行与审计 @@ -58,17 +75,20 @@ Feature → Policy → Gateway → Capability → Execution → Audit Policy blocked 表示策略不允许,Capability unavailable 表示当前发送能力不可用,Send failed 表示已经尝试但执行失败。Action Audit / Logs 会保留执行结果;定时日报即使发送失败,也会保留已生成的报告记录。 +这些动作统一由「自动化」管理,当前有三类规则:**@我生成日报**、**定时日报**、**退群通知**。发送目标支持当前群聊、文件传输助手、自己、指定好友,不是任意群发。 + ## 哪些步骤在本机 - 微信数据库读取与解析; - 聊天档案浏览和普通搜索; - Knowledge 索引与增量同步; +- 图片文字索引:识别图片中的文字完全在本机进行,原始图片不会因为本地识别而上传; - 离线语音转写; - 聊天导出文件、日报 HTML/PNG 和本地历史记录的保存。 ## 哪些步骤可能调用外部服务 -当你主动使用 AI Search、群聊日报或图片理解时,应用会把完成任务所需的受控问题和上下文发送给你配置的 Provider。它不会因为打开软件就自动上传完整数据库。 +当你主动使用 AI Search、群聊日报或图片理解时,应用会把完成任务所需的受控问题和上下文发送给你配置的 Provider。它不会因为打开软件就自动上传完整数据库,本机 OCR、离线语音转写和普通搜索也不会触发外发。 Agent Hub 收到微信机器人的文字后,也可能为了理解请求或生成总结调用已配置的 Provider。Reader Skill 调用的是本机 API;外部 Agent 是否把读取结果继续交给云端模型,取决于外部 Agent 自己的配置。 @@ -76,13 +96,15 @@ Agent Hub 收到微信机器人的文字后,也可能为了理解请求或生 ## 产品名词和用户任务的对应关系 -| 用户想做什么 | 产品中可能看到的名称 | -| ------------------------ | ---------------------------- | -| 让 AI 找相关聊天 | AI Search、Retrieval | -| 让答案能回到原消息 | Evidence、Citation | -| 查看 AI 查找过程 | Search Trace | -| 让跨会话查找更稳定 | Knowledge、FTS 索引 | -| 让外部 Agent 读取聊天 | Reader Skill、Local HTTP API | -| 让微信机器人调用本机能力 | Agent Hub | +| 用户想做什么 | 产品中可能看到的名称 | +| ------------------------------ | ---------------------------- | +| 让 AI 找相关聊天 | AI Search、Retrieval | +| 让答案能回到原消息 | Evidence、Citation | +| 查看 AI 查找过程 | Search Trace | +| 让跨会话查找更稳定 | Knowledge、FTS 索引 | +| 搜到截图、公告图里写过的文字 | 图片文字索引、本机 OCR | +| 让日报、退群通知按规则自动执行 | 自动化、Policy、执行记录 | +| 让外部 Agent 读取聊天 | Reader Skill、Local HTTP API | +| 让微信机器人调用本机能力 | Agent Hub | 先按任务使用,再在需要排查或开发集成时阅读术语。 diff --git a/docs/development/overview.md b/docs/development/overview.md index ef55df9..ad3ce5b 100644 --- a/docs/development/overview.md +++ b/docs/development/overview.md @@ -33,17 +33,24 @@ pnpm test:e2e:build ## 代码变更对应文档 -| 代码区域 | 需要同步检查的文档 | -| --------------------------------------------------------- | ------------------------------------------------------- | -| `src/shared/ai-search.ts`、AI Search pipeline | `user-guide/ai-search.md`、`concepts/answer-sources.md` | -| `src/shared/knowledge.ts`、`src/main/knowledge/` | `user-guide/knowledge.md`、`concepts/how-it-works.md` | -| `src/shared/voice-recognition.ts` | `user-guide/voice.md` | -| `src/shared/group-report.ts`、报告 UI | `user-guide/report.md`、API/Agent 文档 | -| `src/shared/export.ts`、导出服务/UI | `user-guide/export.md` | -| `src/main/services/recall-archive-service.ts` | `user-guide/privacy.md` | -| `src/shared/local-api-test.ts`、`src/main/http-server.ts` | `agent/api.md`、`api-security.md`、打包 Skill | -| Agent Hub service/UI | `agent/agent-hub.md`、`user-guide/privacy.md` | -| 设置导航、连接页面 | `user-guide/getting-started.md`、`docs/README.md` | +| 代码区域 | 需要同步检查的文档 | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | +| `src/shared/ai-search.ts`、AI Search pipeline | `user-guide/ai-search.md`、`concepts/answer-sources.md` | +| `src/shared/knowledge.ts`、`src/main/knowledge/` | `user-guide/knowledge.md`、`concepts/how-it-works.md` | +| `src/shared/voice-recognition.ts` | `user-guide/voice.md` | +| `src/shared/group-report.ts`、报告 UI | `user-guide/report.md`、API/Agent 文档 | +| `src/shared/export.ts`、导出服务/UI | `user-guide/export.md` | +| `src/main/services/system-ocr-service.ts`、`image-text-index-service.ts` | `user-guide/knowledge.md`、`concepts/how-it-works.md`、`user-guide/privacy.md` | +| `src/main/services/image-insight-service.ts`、AI Provider | `user-guide/report.md`、`user-guide/privacy.md` | +| `src/shared/automation.ts`、自动化服务与执行网关 | `user-guide/report.md`、`concepts/how-it-works.md`、`docs/README.md` | +| `src/shared/local-api-test.ts`、`src/main/http-server.ts` | `agent/api.md`、`api-security.md`、打包 Skill | +| Agent Hub service/UI | `agent/agent-hub.md`、`user-guide/privacy.md` | +| 设置导航、连接页面 | `user-guide/getting-started.md`、`docs/README.md` | + +两条容易被写错的边界: + +- **防撤回已下线**(`src/main/services/recall-archive-service.ts` 保留但不再启动):设置入口隐藏,`recallProtectionEnabled` 在所有读写路径上被强制收敛为 `false`。不要把它写回用户指南。 +- **图片文字索引(本机 OCR)与图片理解(需要 Provider)是两条不同的路径**:前者写入本地索引、能被搜索,且不联网;后者只在日报和设置里的模型检测中使用。改其中一条时不要把另一条的隐私口径带过去。 ## 文档检查 @@ -51,7 +58,10 @@ pnpm test:e2e:build ```bash git diff --check -rg -n "v2\.1\.7|TraceMemo|迹忆|mcpServers|无鉴权" README.md docs --glob '*.md' --glob '!development/overview.md' +# 过时版本号、旧品牌名、旧结构叙述、MCP 误解 +rg -n "v2\.1\.7|2\.4\.0|v2\.2\.0 兼容期|无鉴权|mcpServers" README.md docs --glob '*.md' --glob '!development/overview.md' +# 不存在的产品结构(定时日报已并入自动化) +rg -n "日报 → 定时日报|Monitor / Automation" README.md docs --glob '*.md' ``` -历史迁移说明可以出现旧版本号;正式使用指南不要把过时版本写成当前版本。负向澄清“6131 不是 MCP Server”可以保留,以防用户照抄错误配置。 +历史迁移说明可以出现旧版本号;正式使用指南不要把过时版本写成当前版本。负向澄清“6131 不是 MCP Server”可以保留,以防用户照抄错误配置。发版前额外确认 `README.md` 里的版本号与 `package.json` 的 `version` 一致。 diff --git a/docs/skill/tracememo-reader/SKILL.md b/docs/skill/tracememo-reader/SKILL.md index 0127e67..620dad7 100644 --- a/docs/skill/tracememo-reader/SKILL.md +++ b/docs/skill/tracememo-reader/SKILL.md @@ -1,6 +1,6 @@ --- name: tracememo-reader -description: 通过 TraceMemo 本地 HTTP API 按需读取用户有权访问的微信聊天数据和图片媒体。当用户要求查看微信消息、查找联系人或群聊、总结聊天、查看或理解图片、生成群聊总结时使用。此 Skill 由本机 TraceMemo 提供数据,不是 MCP Server。 +description: 通过 TraceMemo 本地 HTTP API 按需读取用户有权访问的微信聊天数据和图片媒体,并管理定时日报任务。当用户要求查看微信消息、查找联系人或群聊、总结聊天、查看或理解图片、生成群聊总结、查询或修改定时日报时使用。此 Skill 由本机 TraceMemo 提供数据,不是 MCP Server。 --- # TraceMemo Reader @@ -27,31 +27,39 @@ description: 通过 TraceMemo 本地 HTTP API 按需读取用户有权访问的 ## 端点速查 -| 方法 | 路径 | 用途 | -| ------ | ----------------------------------- | ------------------------------------------------- | -| GET | `/health` | 健康和数据库状态 | -| GET | `/current_time` | 本机时间与时区 | -| GET | `/contact` | 联系人/群聊列表;可传 `filter`、`type` | -| GET | `/chatroom` | 群聊列表;可传 `keyword` | -| GET | `/recent_chat` | 最近会话;可传 `limit` | -| GET | `/chatlog` | 会话消息;必填 `talker`,可传 `time` 或时间戳范围 | -| GET | `/media/{mediaId}` | 按消息返回的 `media.url` 获取图片二进制资源 | -| GET | `/group_snapshot` | 群成员快照;必填 `md5` | -| GET | `/resolve` | 昵称、wxid、md5 解析;必填 `q` | -| GET | `/wechat-personal/send-capability` | 个人微信图片发送能力状态 | -| GET | `/scheduled-reports` | 查询全部定时日报任务 | -| GET | `/scheduled-reports/:id` | 查询单个定时日报任务 | -| POST | `/scheduled-reports` | 创建定时日报任务 | -| PATCH | `/scheduled-reports/:id` | 修改定时日报任务 | -| DELETE | `/scheduled-reports/:id` | 删除定时日报任务(执行前必须获得用户确认) | -| POST | `/scheduled-reports/:id/enable` | 启用定时日报任务 | -| POST | `/scheduled-reports/:id/disable` | 暂停定时日报任务 | -| POST | `/scheduled-reports/:id/run` | 立即执行一次并返回 execution | -| GET | `/scheduled-reports/:id/executions` | 查询执行记录 | -| POST | `/report` | 将已有日报结构渲染为 HTML/PNG | -| GET | `/agent/status` | Agent Hub、连接器和数据库状态 | -| POST | `/agent/group-report` | 按群和 `today`/`yesterday`/`7days` 生成总结图片 | -| POST | `/agent/send` | 已连接机器人发送测试 | +| 方法 | 路径 | 用途 | +| ------ | ------------------------------------------------------- | ------------------------------------------------- | +| GET | `/health` | 健康和数据库状态 | +| GET | `/current_time` | 本机时间与时区 | +| GET | `/contact` | 联系人/群聊列表;可传 `filter`、`type` | +| GET | `/chatroom` | 群聊列表;可传 `keyword` | +| GET | `/recent_chat` | 最近会话;可传 `limit` | +| GET | `/chatlog` | 会话消息;必填 `talker`,可传 `time` 或时间戳范围 | +| GET | `/media/{mediaId}` | 按消息返回的 `media.url` 获取图片二进制资源 | +| GET | `/group_snapshot` | 群成员快照;必填 `md5` | +| GET | `/resolve` | 昵称、wxid、md5 解析;必填 `q` | +| POST | `/query/messages` | 按目标与时间范围取消息(结构化,不调用 AI) | +| POST | `/query/search` | 受限语义关键词检索(依赖本地索引,见 freshness) | +| POST | `/query/message-context` | 用 `messageRef` 取某条消息的前后文 | +| POST | `/query/conversation-overview` | 按会话与时间范围提取可总结的证据 | +| GET | `/query/capabilities` | Query 端点能力目录 | +| GET | `/wechat-personal/send-capability` | 个人微信发送能力状态(文字 / 图片 / 语音) | +| GET | `/scheduled-reports` | 查询全部定时日报任务 | +| GET | `/scheduled-reports/:id` | 查询单个定时日报任务 | +| POST | `/scheduled-reports` | 创建定时日报任务 | +| PATCH | `/scheduled-reports/:id` | 修改定时日报任务 | +| DELETE | `/scheduled-reports/:id` | 删除定时日报任务(执行前必须获得用户确认) | +| POST | `/scheduled-reports/:id/enable` | 启用定时日报任务 | +| POST | `/scheduled-reports/:id/disable` | 暂停定时日报任务 | +| POST | `/scheduled-reports/:id/run` | 立即执行一次并返回 execution | +| GET | `/scheduled-reports/:id/executions` | 查询执行记录 | +| POST | `/scheduled-reports/executions/:executionId/retry-send` | 复用已有 PNG 重试发送 | +| POST | `/report` | 将已有日报结构渲染为 HTML/PNG | +| GET | `/agent/status` | Agent Hub、连接器和数据库状态 | +| POST | `/agent/group-report` | 按群和 `today`/`yesterday`/`7days` 生成总结图片 | +| POST | `/agent/send` | 已连接机器人发送测试(文字或本地图片) | + +这个 API **不只是只读的**:`/report` 会渲染并写文件,`/agent/send` 会真的发出微信消息,`/scheduled-reports*` 会创建、修改、删除或立刻执行定时任务。这些调用都要先确认用户意图;`DELETE` 与 `/agent/send` 尤其需要用户明确确认。 ## 定时日报管理 @@ -78,7 +86,7 @@ description: 通过 TraceMemo 本地 HTTP API 按需读取用户有权访问的 } ``` -如果 API 返回 `409` 且 `error === "duplicate"`,告诉用户相同任务已经存在,不要再次创建。能力状态为 `unsupported`、`unconfigured`、`needs_binding`、`needs_verification` 或 `error` 时,直接说明需要先在 TraceMemo 设置中完成个人微信绑定和消息能力检测。 +如果 API 返回 `409` 且 `error === "duplicate"`,告诉用户相同任务已经存在,不要再次创建。能力状态不是 `ready` 时(`unsupported`、`unconfigured`、`needs_binding`、`initializing` 或 `error`),直接说明需要先在 TraceMemo 的“设置 → 发送能力”里完成个人微信绑定和能力检测,不要继续创建任务。 ### 查看、修改和执行 @@ -102,6 +110,20 @@ description: 通过 TraceMemo 本地 HTTP API 按需读取用户有权访问的 - 根据多条消息整理出的总结; - 没有来源支持的推断。 +## 结构化查询(query/\*) + +需要按目标 + 时间范围稳定取数时,优先使用 `query/*`,而不是自己拼 `chatlog`: + +- `query/messages`:按 `target`、`timeRange`、`direction`、`messageTypes` 取消息; +- `query/search`:受限语义关键词检索,依赖本地索引; +- `query/message-context`:用返回的 `messageRef` 取前后文; +- `query/conversation-overview`:按会话与时间范围提取可总结的证据。 + +两个要点: + +- `messageRef` 是服务端生成的不透明引用,**不要**自行构造 wxid、md5 或数据库路径; +- `query/search` 依赖异步建立的本地索引。`coverage.state` 不是 `complete` 且 `evidence` 为空时,只能说“这段范围暂时无法确认”,**不能**下“没有找到”的结论。 + ## 媒体消息 当 `/chatlog` 返回图片消息时: diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md index bda3736..bdc7a3b 100644 --- a/docs/user-guide/getting-started.md +++ b/docs/user-guide/getting-started.md @@ -33,7 +33,7 @@ Apple Silicon 和 Intel 均已适配微信 macOS `4.1.13` 系列。首次获取 - 上表中的版本是当前 TraceMemo 已适配或推荐使用的版本,并不代表只有这些版本可以运行。 - TraceMemo 必须取得当前微信账号对应的数据库密钥,才能读取聊天记录。 - 你需要有权访问要读取的微信账号和聊天数据。 -- 如果要使用 AI 问答、群聊日报或图片理解,还需要在应用中配置一个 AI 服务。 +- 如果要使用 AI 问答、群聊日报或图片理解,还需要在应用中配置一个 AI 服务。「图片文字索引」不在此列——它在本机识别图片里的文字,不需要配置 AI。 当前代码按微信 4.x 数据结构处理。不同微信客户端版本、系统权限和数据迁移状态可能影响自动连接;遇到问题时请查看[常见问题与排查](./troubleshooting.md)。 @@ -134,6 +134,7 @@ Apple Silicon 和 Intel 均已适配微信 macOS `4.1.13` 系列。首次获取 - [生成群聊日报或总结](./report.md) - [转写微信语音](./voice.md) - [导出聊天档案](./export.md) +- [让日报、退群通知按规则自动运行](../README.md#日报与自动化) - [在微信里向 TraceMemo 提问](../agent/agent-hub.md) - [让外部 Agent 查询微信历史](../agent/overview.md) @@ -159,14 +160,17 @@ Agent Hub 是普通用户可以直接使用的入口,不需要安装 Reader Sk ## 8. 需要配置 AI 吗? -不一定。浏览聊天、普通关键词搜索、建立本地知识库和导出不要求在线 AI 服务。 +不一定。浏览聊天、普通关键词搜索、建立本地知识库、图片文字识别、离线语音转写和导出都不要求在线 AI 服务。 使用“问问微信”、群聊日报或图片理解时,需要在“设置 → AI 模型”中添加并测试 AI 服务。你主动开始并确认远程 AI 功能后,完成任务所需的内容才可能发送给该服务;计费、留存和地区规则由对应服务商决定。 +这两种情况容易混淆:**本机识别图片里的文字**(图片文字索引)不联网、不需要 AI 服务;**让模型看图并回答**(图片理解)才需要配置 AI 服务。 + ## 9. 数据和隐私的最低须知 -- 微信数据库、聊天解析和本地索引默认留在本机。 +- 微信数据库、聊天解析、本地索引和图片文字识别默认留在本机。 - 离线语音转写使用本地模型;它与在线 AI 请求是两条不同的数据路径。 +- 图片文字索引只在本机识别,原始图片不会因为本地识别而上传;识别出的文字会进入本地索引,供搜索和“问问微信”使用。 - 你主动开始并确认 AI 问答或日报后,完成任务所需的受控上下文才可能发送给你选择的 AI 服务;打开应用不会自动上传全部聊天。 - 应用内 Local HTTP API 默认只监听 `127.0.0.1:6131`,受保护接口需要 Token。 diff --git a/docs/user-guide/knowledge.md b/docs/user-guide/knowledge.md index d77f8f3..05c4416 100644 --- a/docs/user-guide/knowledge.md +++ b/docs/user-guide/knowledge.md @@ -24,13 +24,13 @@ Knowledge 不会在第一次连接后自动悄悄建立。进入“问问微信 ### 状态怎么读 -| 状态 | 含义 | -| ---- | ---- | -| 可用 · 已追至最新 | 索引已覆盖到聊天记录的最新位置,可以直接用 | -| 可用 · 正在追新 | 索引可用,正在后台补充最近新增的消息 | -| 可用 · 正在补齐历史 | 索引可用,正在后台补齐较早的历史内容 | -| 可用 · 同步已取消 | 索引仍然可用;上一轮同步被取消,已建立的部分保留 | -| 可用 · 更新失败 | 索引仍然可用;上一轮同步出错,可以稍后重试 | +| 状态 | 含义 | +| ------------------- | ------------------------------------------------ | +| 可用 · 已追至最新 | 索引已覆盖到聊天记录的最新位置,可以直接用 | +| 可用 · 正在追新 | 索引可用,正在后台补充最近新增的消息 | +| 可用 · 正在补齐历史 | 索引可用,正在后台补齐较早的历史内容 | +| 可用 · 同步已取消 | 索引仍然可用;上一轮同步被取消,已建立的部分保留 | +| 可用 · 更新失败 | 索引仍然可用;上一轮同步出错,可以稍后重试 | 只有确实追平、且没有待补齐内容时才会出现“已追至最新”。索引不可查询时不会显示“可用”。 @@ -38,6 +38,21 @@ Knowledge 不会在第一次连接后自动悄悄建立。进入“问问微信 同步过程中可以点击 **取消同步**(点击后显示“正在取消…”)。取消只结束当前这一轮,不会删除已经建立的索引,也不会回滚已完成的部分;下次同步会从上次停下的位置继续,不需要从头重扫。中断过的索引仍然可以正常搜索。 +## 图片文字索引(另一份索引) + +本地索引其实有两份,彼此独立: + +- **聊天记录索引**(也就是上面说的 Knowledge):索引文字消息,用于跨会话、跨时间查找; +- **图片文字索引**:在本机识别微信图片里的文字(截图、公告、报价图等),把识别结果也变成可搜索的文字。 + +“独立”的意思是:聊天记录索引建好了,并不代表图片里的文字就搜得到。建立图片文字索引后,可以在“问问微信”里直接搜截图或公告图里写过的词。 + +图片文字索引只在本机识别,原始图片不会因为本地识别而上传。它**不等于“图片理解”**:识别文字不联网、不需要 AI 服务;而让模型看图并回答属于图片理解,需要配置 AI 服务,走的是另一条路径。 + +识别失败的图片可以单独重试,也有“只重建搜索索引、不重新识别图片”的修复入口——修索引不需要重跑几万张图。 + +两个索引都可以在“设置 → 本地索引”里集中查看状态、建立、同步和清理。 + ## 账号隔离 每个微信账号使用独立的本地索引。切换账号时,应用不会把一个账号的索引混入另一个账号的搜索结果。 @@ -58,4 +73,3 @@ Knowledge 不会在第一次连接后自动悄悄建立。进入“问问微信 ## 产品术语(可选) 源码和日志中可能出现 SQLite、FTS、Chunk、索引等词。它们描述的是本地存储和检索实现,不是你开始使用 TraceMemo 的前置知识。 - diff --git a/docs/user-guide/privacy.md b/docs/user-guide/privacy.md index f8cf4dc..78aaf88 100644 --- a/docs/user-guide/privacy.md +++ b/docs/user-guide/privacy.md @@ -9,6 +9,7 @@ TraceMemo 的核心路径是本地优先,但“本地优先”不等于所有 - 读取和解析微信数据库; - 聊天档案浏览和普通关键词搜索; - 本地 Knowledge 索引及其账号隔离; +- 图片文字索引:识别图片中的文字在本机完成,原始图片不会因为本地识别而上传; - 离线语音转写; - 导出文件生成和本地日报历史。 @@ -16,7 +17,7 @@ TraceMemo 的核心路径是本地优先,但“本地优先”不等于所有 ## 什么时候会请求外部服务 -当你主动使用 AI Search、群聊日报或图片理解,并配置了远程 Provider 时,完成任务所需的内容可能发送给该 Provider。当前设置页给出的边界是: +当你主动使用 AI Search、群聊日报或图片理解,并配置了远程 Provider 时,完成任务所需的内容可能发送给该 Provider。图片文字索引、离线语音转写、档案浏览和普通搜索不会触发这一步。当前设置页给出的边界是: - 当前用户问题; - 受控检索所需的有限上下文; @@ -28,7 +29,14 @@ Ollama 等本机 Provider 可以把模型请求留在本机,但本机服务的 ## 语音和媒体 -离线语音转写在本机进行。图片理解属于 AI 功能:只有你主动启用并使用相关报告/分析路径时,图片才可能按该 Provider 的请求规则被处理。无法读取的媒体不会被自动“猜出来”。 +离线语音转写在本机进行。 + +图片有两条完全不同的路径,不要混为一谈: + +- **图片文字索引**:在本机识别图片里的文字,产出的是本地索引数据;原始图片不会因为这一步被上传,也不需要配置 AI 服务。 +- **图片理解**:属于 AI 功能。只有你主动启用并使用相关报告/分析路径时,图片才可能按该 Provider 的请求规则被处理。 + +无法读取的媒体不会被自动“猜出来”。 ## Local HTTP API diff --git a/docs/user-guide/report.md b/docs/user-guide/report.md index 6f106e2..f901336 100644 --- a/docs/user-guide/report.md +++ b/docs/user-guide/report.md @@ -33,9 +33,11 @@ 生成成功后会保存本地 HTML 与 PNG,并出现在日报历史中。你可以复制图片、打开文件位置或重新生成。删除历史日报只删除本地生成的报告文件,不会影响微信聊天数据库。 -## 定时日报 +## 定时日报(在自动化里) -在“日报 → 定时日报”中可以创建每天运行的任务。选择群聊、执行时间、日报范围、消息类型和模板后,TraceMemo 会按计划执行: +定时日报现在是「自动化」里的一种规则,不再单独占一个页面:打开一级导航的「自动化」,新建或编辑一条「定时日报」规则,选择群聊、执行时间、日报范围、消息类型和发送目标。日报页顶部的指引条也会直接跳到自动化。 + +TraceMemo 会按计划执行: ```text 定时触发 → 读取群聊 → 生成报告 → 保存 Report History → 尝试发送 @@ -45,6 +47,8 @@ 执行记录支持查看已生成的日报。对“等待发送”或“发送失败”的记录,可以直接重试发送,重试会复用已经生成的 PNG,不会重新调用 AI 生成整份报告;完整执行状态和发送边界见[如何把聊天变成可用的信息](../concepts/how-it-works.md#动作执行与审计)。 +发送目标当前支持**当前群聊、文件传输助手、自己、指定好友**——还不是任意群发。 + ## 让报告更可靠 - 先选正确的群和时间范围; diff --git a/package.json b/package.json index 875629f..3c219a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tracememo", - "version": "2.4.0", + "version": "2.5.0", "packageManager": "pnpm@7.33.7", "description": "TraceMemo(迹忆)是一款本地优先、可追溯的 AI 微信知识与分析工作台。 原名 WechatExplorer,支持聊天记录搜索、知识库、微信群聊总结和 Agent 助手。", "keywords": [ diff --git a/public/自动化.png b/public/自动化.png new file mode 100644 index 0000000..35ca430 Binary files /dev/null and b/public/自动化.png differ diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 26946f8..af54c29 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -1951,7 +1951,6 @@ function App(): React.ReactElement { contentFilter={contentFilter} onContentFilterChange={setContentFilter} onRefresh={() => selectedContact && handleSelectContact(selectedContact, true)} - onRefreshData={loadContacts} onReloadAvatars={handleReloadCurrentAvatars} onLoadOlderMessages={handleLoadOlderMessages} onCreateGroupReport={handleOpenReportWorkspace} diff --git a/src/renderer/src/components/ChatWindow.tsx b/src/renderer/src/components/ChatWindow.tsx index caa6898..5ed1f9b 100644 --- a/src/renderer/src/components/ChatWindow.tsx +++ b/src/renderer/src/components/ChatWindow.tsx @@ -18,7 +18,6 @@ interface ChatWindowProps { contentFilter?: string onContentFilterChange?: (keyword: string) => void onRefresh?: () => void - onRefreshData?: () => void onReloadAvatars?: () => Promise onLoadOlderMessages?: () => Promise onCreateGroupReport?: () => void @@ -40,7 +39,6 @@ const ChatWindow: React.FC = ({ contentFilter, onContentFilterChange, onRefresh, - onRefreshData, onReloadAvatars, onLoadOlderMessages, onCreateGroupReport, @@ -182,7 +180,6 @@ const ChatWindow: React.FC = ({ isAiLoading={isAiLoading} onContentFilterChange={onContentFilterChange || (() => undefined)} onRefresh={onRefresh} - onRefreshData={onRefreshData} onTestSend={() => void handleOpenPersonalWechatSend()} onOpenAiSettings={onCreateGroupReport || (() => undefined)} onOpenLocalIndexSettings={onOpenLocalIndexSettings} diff --git a/src/renderer/src/components/chat/ChatHeader.tsx b/src/renderer/src/components/chat/ChatHeader.tsx index 2720f84..7a4bb7f 100644 --- a/src/renderer/src/components/chat/ChatHeader.tsx +++ b/src/renderer/src/components/chat/ChatHeader.tsx @@ -1,18 +1,8 @@ import React, { useState } from 'react' import { Contact } from '../../../../shared/types' -import { - Button, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, - IconButton, - Tooltip, - TooltipContent, - TooltipTrigger -} from '../ui' +import { Button, IconButton, Tooltip, TooltipContent, TooltipTrigger } from '../ui' import { ConversationContentSearch } from './ConversationContentSearch' -import { AiIcon, MoreIcon, RefreshIcon, SearchIcon, SendIcon } from './icons' +import { AiIcon, RefreshIcon, SearchIcon, SendIcon, StatsIcon } from './icons' import { supportsPersonalWechatSend } from '../../utils/runtime-environment' import { GroupMemberStatsDialog } from '../group-stats/GroupMemberStatsDialog' @@ -25,7 +15,6 @@ interface ChatHeaderProps { isAiLoading: boolean onContentFilterChange: (value: string) => void onRefresh?: () => void - onRefreshData?: () => void onTestSend: () => void onOpenAiSettings: () => void /** 跳到「设置 · 本地索引」(群统计发现索引没追平时用)。 */ @@ -41,7 +30,6 @@ export function ChatHeader({ isAiLoading, onContentFilterChange, onRefresh, - onRefreshData, onTestSend, onOpenAiSettings, onOpenLocalIndexSettings @@ -96,27 +84,20 @@ export function ChatHeader({ - - - - - - onRefreshData?.()}>刷新数据 - {/* 群发言统计只对群聊有意义;单聊没有「成员名单」这个概念。 */} - {isGroupChat ? ( - setStatsOpen(true)}>群发言统计 - ) : null} - - + {/* 群发言统计只对群聊有意义;单聊没有「成员名单」这个概念。 */} + {isGroupChat ? ( + + ) : null} {supportsPersonalWechatSend ? (