feat: 导入 MemRelay 初始源码
This commit is contained in:
@@ -0,0 +1,903 @@
|
||||
# MemRelay 无人值守整理与记忆版本管理计划
|
||||
|
||||
> 状态:已完成。本文档是功能、接口、可靠性和验收标准的权威说明;计划内能力已通过 Windows AMD64、真实 Responses、真实 Git、备份恢复和物理 Armbian ARM64 验收,并已部署正式实例。AI 整理与记忆 Git 仍是默认关闭、彼此独立的可选增强。
|
||||
|
||||
> 2026-08-07 复审:MCP 能力资源与 `capabilities_get` 已统一为实时能力清单,语义搜索会反映 Basic Memory 健康状态;当前隔离实例发现 95 个工具和 3 个资源,MCP 仪表盘与 Web 仪表盘状态字段保持一致。
|
||||
|
||||
## 1. 目标
|
||||
|
||||
- 为 MemRelay 增加生成式 AI 整理能力,自动整理开发项目、办公资料、学习课程、研究资料、个人笔记和通用工作区,以及全局个人习惯和跨工作区经验。
|
||||
- 最终运行方式为无人值守:无需依赖用户打开 Web,也不要求每次由用户手动触发。
|
||||
- 优先使用正在操作本地资料的 Codex、Cursor、Claude Code 和其他 MCP 客户端对源码、文档、笔记、课程或办公文件的理解,通过 MCP 将结论、进度、文档和进度快照同步到 MemRelay。
|
||||
- 当没有 Agent 同步、同步内容不足或超过配置的新鲜度阈值时,服务器自动读取文件仓储;配置了 Git remote 的工作区再使用受管理的 Git 工作区读取源码和版本化文档。
|
||||
- 整理结果可被 Web、MCP、Basic Memory、工作区文档导出和 Obsidian 兼容读取共同使用。
|
||||
- 使用本地 Git 为全部 Markdown 记忆、检查点和整理文档保留真实内容历史,并可选择同步到用户自行注册的专用 Git 账号,实现跨设备备份、差异审计和受控恢复。
|
||||
|
||||
## 2. 核心原则
|
||||
|
||||
### 2.1 原始记录和整理文档双层并存
|
||||
|
||||
- 原始记忆、进度快照、时间线和来源文档继续保留,作为完整事实来源。
|
||||
- AI 生成独立的“整理文档”,不通过覆盖或删除原始记录来实现整理。
|
||||
- 整理文档使用稳定 ID 和 revision,每次更新保留来源、模型、提示词版本、时间和变更摘要。
|
||||
- 冲突内容标记为冲突、过期或已被替代,不自动抹除历史。
|
||||
- `context_get` 优先返回整理后的当前信息,同时补入该整理文档成功游标之后尚未整理的相关原始变化和最新检查点,并标明整理状态/滞后范围;模型长期不可用时不能只返回陈旧整理文档。其余原始记忆按需要补充,减少上下文长度和重复内容。
|
||||
|
||||
### 2.2 MCP 优先,Git 工作区兜底
|
||||
|
||||
来源优先级固定为:
|
||||
|
||||
1. 本机 Agent 直接读取当前工作区的源码、配置、文档、笔记、课程、办公文件和本地变更。
|
||||
2. Agent 通过现有 MCP 工具写入规则、事实、决定、经验和进度快照,文档或附件通过文件仓储上传。
|
||||
3. 整理任务优先消费这些由 Agent 提炼过的内容,避免服务器重复读取全部原始资料。
|
||||
4. Agent 来源不足时读取 MemRelay 文件仓储;工作区配置了 Git remote 时,再创建或更新受管理的源码工作区作为补充来源。
|
||||
5. 没有 Git 的办公、学习、个人笔记和通用工作区仍可依靠记忆、进度快照和文件仓储完成全部整理能力,并在任务结果中标记来源覆盖范围。
|
||||
|
||||
### 2.3 模型不直接修改任意文件
|
||||
|
||||
- 模型读取经过 MemRelay 选择、分段和标注的文本,不获得任意服务器文件路径或 Shell。
|
||||
- 模型返回结构化整理结果,包括目标文档、Markdown 正文、来源 ID、冲突、替代关系和标签。
|
||||
- MemRelay 校验任务状态、工作区范围、revision 和输出格式后,通过现有记忆服务写入 Markdown 并触发 Basic Memory 索引。
|
||||
- 源码 Git 工作区明确作为服务器端整理器的只读来源,不由整理器修改源码、创建提交或推送分支。整理正文统一写入 MemRelay,启用记忆 Git 时再进入独立版本历史;项目仓库中的正式文件仍由有本地源码上下文的 Agent 修改并通过正常 Git 工作流提交。这个职责边界是最终架构,不保留服务器端源码 Git 写回实现。
|
||||
|
||||
### 2.4 通用工作区与场景隔离
|
||||
|
||||
- 数据层继续保留现有 `Project`/`project_id` 兼容接口,产品语义扩展为“工作区”,避免破坏现有 MCP 客户端和数据。
|
||||
- 每个工作区增加 `workspace_type`:`development`、`office`、`study`、`research`、`personal`、`general`,并允许自定义整理模板。
|
||||
- 有 Git remote 的现有项目迁移为 `development`,没有 Git remote 的现有项目迁移为 `general`;管理员可在 Web/MCP 中修改类型。
|
||||
- 现有项目创建、更新、列表和解析 REST/MCP 接口增加 `workspace_type` 与可空自定义模板字段;旧客户端不传时按 remote 和默认规则自动选择,不破坏兼容性。
|
||||
- 工作区类型只决定默认文档模板、来源优先级和提示词,不限制用户混合使用文件、笔记、记忆、Git 或进度快照。
|
||||
- 个人习惯分为全局、场景和工作区三级。开发编码习惯不会自动污染办公或学习场景,只有用户明确声明为全局或跨场景重复成立的偏好才提升到全局。
|
||||
- 增加轻量 `usage_profile` 做习惯归属和来源标记,不把它扩展成多租户权限系统。实例默认只有 `shared` 团队档案,也可为不同成员建立档案。
|
||||
- MCP Token 可绑定一个记忆空间;Web 会话可选择当前空间。未指定时使用 `shared`,团队规则继续共享,个人习惯只在对应空间内提升和整理。
|
||||
- `context_get` 根据当前工作区类型组合对应场景偏好、工作区整理文档、原始记忆和最新进度快照。
|
||||
|
||||
### 2.5 记忆 Git 与源码 Git 分离
|
||||
|
||||
- Basic Memory Markdown 继续是记忆正文唯一权威来源;启用 Git 后,它只作为版本历史和远程镜像层,不建立第二套记忆写入接口。
|
||||
- AI 整理启用且工作区配置源码 remote 时,只读源码 Git 工作区位于 `/data/memrelay/workspaces/`;记忆 Git 启用时,仓库位于 `/data/basic-memory/memories/` 对应范围内,由 MemRelay 写入和提交。
|
||||
- 记忆写入、归档、删除、整理和恢复都先经过 MemRelay 的 revision、引用和索引逻辑,再生成 Git 提交;Agent、Web 用户和远程平台不能绕过 MemRelay 直接改变当前记忆状态。
|
||||
- 远程仓库默认是 MemRelay 单向推送的镜像。外部提交不会自动 pull 或 merge 到在线记忆;需要使用受控导入/恢复流程,避免 Markdown、SQLite 引用和 Basic Memory 索引分裂。
|
||||
- Git 只跟踪 Markdown 和必要的非秘密清单,不跟踪 SQLite、索引、模型缓存、文件仓储正文、密码、Token、TOTP、私钥或临时文件。
|
||||
|
||||
### 2.6 来源可信边界与秘密过滤
|
||||
|
||||
- 来自源码、文档、网页、压缩包、OCR、记忆和 Agent 来源包的正文一律作为不可信数据处理,其中出现的“忽略规则”“执行命令”“读取凭证”等内容不能改变系统提示词、工具权限或整理策略。
|
||||
- MemRelay 使用结构化边界向模型传递来源,系统指令与来源正文分离;模型不获得 Shell、文件系统、密码库或任意 MCP 工具调用能力,模型输出也继续按不可信数据校验。
|
||||
- Vaultwarden/Bitwarden 中的密码、Token、TOTP、私钥和隐藏字段绝不进入整理模型请求。来源收集前执行秘密候选检测与脱敏,整理结果写入 Markdown 前再次扫描;命中已知秘密或高置信凭证模式时阻止应用,低置信候选脱敏并给出警告,均返回可定位但不回显秘密值的结果。
|
||||
- 允许整理文档保存密码库条目名称、用途和非秘密映射,但不得保存其秘密字段。日志、任务错误、模型调用摘要、Git 提交和未覆盖来源报告遵循相同边界。
|
||||
|
||||
### 2.7 AI 与 Git 均为可选增强
|
||||
|
||||
- AI 整理和 Git 版本管理彼此独立且都不是 MemRelay 基础能力的前置条件。用户可以两者都不配置、只启用其中一个或同时启用。
|
||||
- 默认安装采用“AI 关闭 + Git 关闭”的零配置基础模式。初始化向导、项目创建/编辑、客户端配置和日常使用不得把模型连接、源码 Git remote 或记忆 Git remote 设为必填项;没有 Git 的工作区同样可以完整使用记忆、检查点、搜索、密码库、文件仓储和 MCP。
|
||||
- 未配置或未启用 AI 时,不执行模型探测、不创建自动整理任务,也不因缺少模型显示系统故障;记忆、项目、检查点、全文/语义搜索、文件仓储、密码库、Web 和现有 MCP 工具保持当前行为,`context_get` 直接组合原始记忆与检查点。
|
||||
- 首次启用 AI 时从现有记忆、检查点和文件建立基线并执行一次可观察的初始整理;停用后不再创建任务,重新启用时根据最后成功游标和当前 revision 补齐变化。
|
||||
- 未配置或未启用 Git 版本管理时,不创建 `.git`、提交任务或远程同步状态,记忆仍按当前 Basic Memory + SQLite 流程读写。启用 Git 后才初始化本地历史,remote 继续可选;停用 Git 不删除已有本地仓库和历史。
|
||||
- Web 初始化、健康检查、部署和验收必须覆盖“AI 关闭 + Git 关闭”的基础模式,不能用红色错误或阻塞提示迫使用户配置任一增强能力。
|
||||
- Web 对未配置的 AI/Git 使用中性的“未启用”状态,不计入系统故障、依赖异常或待处理告警;REST/MCP 能力发现返回对应开关状态,并指导客户端继续使用基础工作流,不能要求用户先配置增强能力。
|
||||
|
||||
## 3. 内容载体与存放位置
|
||||
|
||||
| 内容 | 权威载体 | 存放位置 |
|
||||
| --- | --- | --- |
|
||||
| 原始全局/工作区记忆 | Basic Memory Markdown | `/data/basic-memory/memories/` |
|
||||
| AI 整理文档 | Basic Memory Markdown | `global/curated/`、`projects/<id>/curated/` 逻辑目录 |
|
||||
| 进度历史 | 进度快照 Markdown | 现有检查点和时间线 |
|
||||
| 可选记忆本地版本历史 | Git | 启用后位于 Markdown 范围目录内的 `.git/`,由仓库策略决定 |
|
||||
| 记忆远程镜像 | 标准 Git remote | 用户自行提供的准确 URL 或带 `{repo}` 占位符的 URL 模板 |
|
||||
| 本机 Agent 上下文副本 | Markdown ZIP | 项目 `aidocs/`,继续加入 `.gitignore` |
|
||||
| 版本化资料兜底副本 | Git 工作区 | `/data/memrelay/workspaces/<project-id>/` |
|
||||
| 通用文件、PDF、图片和附件 | MemRelay 文件仓储 | `/data/memrelay/files/` |
|
||||
| 整理任务、revision、来源关系和模型调用摘要 | SQLite | `/data/memrelay/db/memrelay.sqlite3` |
|
||||
| 外部模型服务访问 Token | MemRelay 加密设置 | 使用现有部署主密钥加密,不写入 Markdown 或日志 |
|
||||
| 源码和记忆 Git 凭证 | Vaultwarden/Bitwarden 或 MemRelay 本地加密设置 | 优先保存密码库条目引用;未配置密码库时使用部署主密钥加密,不写入 Markdown 或 Git 配置 |
|
||||
| 临时分段和模型中间结果 | 临时目录 | `/data/memrelay/tmp/curation/<job-id>/`,任务结束后清理 |
|
||||
|
||||
完整整理文档类型按工作区模板组合:
|
||||
|
||||
```text
|
||||
global/curated/profile.md
|
||||
global/curated/preferences.md
|
||||
global/curated/workflows.md
|
||||
global/curated/cross-workspace-experience.md
|
||||
global/curated/contexts/development.md
|
||||
global/curated/contexts/office.md
|
||||
global/curated/contexts/study.md
|
||||
global/curated/contexts/research.md
|
||||
global/curated/contexts/personal.md
|
||||
global/curated/contexts/general.md
|
||||
|
||||
projects/<project-id>/curated/overview.md
|
||||
projects/<project-id>/curated/current-state.md
|
||||
projects/<project-id>/curated/decisions.md
|
||||
projects/<project-id>/curated/timeline.md
|
||||
projects/<project-id>/curated/tasks.md
|
||||
projects/<project-id>/curated/glossary.md
|
||||
|
||||
projects/<project-id>/curated/development/architecture.md
|
||||
projects/<project-id>/curated/development/troubleshooting.md
|
||||
projects/<project-id>/curated/development/deployment.md
|
||||
projects/<project-id>/curated/development/maintenance.md
|
||||
|
||||
projects/<project-id>/curated/office/meetings.md
|
||||
projects/<project-id>/curated/office/action-items.md
|
||||
projects/<project-id>/curated/office/procedures.md
|
||||
projects/<project-id>/curated/office/reports.md
|
||||
|
||||
projects/<project-id>/curated/study/course-outline.md
|
||||
projects/<project-id>/curated/study/knowledge-map.md
|
||||
projects/<project-id>/curated/study/concepts.md
|
||||
projects/<project-id>/curated/study/exercises-and-mistakes.md
|
||||
projects/<project-id>/curated/study/review-plan.md
|
||||
projects/<project-id>/curated/study/references.md
|
||||
|
||||
projects/<project-id>/curated/research/literature.md
|
||||
projects/<project-id>/curated/research/evidence.md
|
||||
projects/<project-id>/curated/research/hypotheses.md
|
||||
projects/<project-id>/curated/research/experiments.md
|
||||
projects/<project-id>/curated/research/citations.md
|
||||
|
||||
projects/<project-id>/curated/personal/topics.md
|
||||
projects/<project-id>/curated/personal/insights.md
|
||||
projects/<project-id>/curated/personal/goals.md
|
||||
projects/<project-id>/curated/personal/habits.md
|
||||
```
|
||||
|
||||
整理文档 frontmatter 至少记录:
|
||||
|
||||
- `stable_id`
|
||||
- `scope`
|
||||
- `project_id`
|
||||
- `workspace_type`
|
||||
- `usage_profile_id`
|
||||
- `preference_context`
|
||||
- `document_type`
|
||||
- `revision`
|
||||
- `source_memory_ids`
|
||||
- `source_checkpoint_ids`
|
||||
- `source_file_ids`
|
||||
- `source_git_commit`
|
||||
- `model_connection`
|
||||
- `model_name`
|
||||
- `prompt_version`
|
||||
- `curation_job_id`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
## 4. 模型接入
|
||||
|
||||
### 4.1 通用外部模型服务
|
||||
|
||||
- MemRelay 不内置 CLIProxyAPI、Sub2API 或任何模型服务,也不限定服务商。用户自行填写一个 OpenAI-compatible Base URL、可空 Bearer Token、文本模型名称、可空视觉模型名称和协议模式。
|
||||
- Base URL 可以指向 OpenAI-compatible 官方平台、CLIProxyAPI、Sub2API、团队网关或其他兼容服务;MemRelay 不要求用户声明平台类型,也不编写平台专用分支。
|
||||
- 模型服务不加入 MemRelay 核心 Compose,由用户自行部署、购买、升级和备份。部署文档只提供通用字段说明和若干可选连接示例,不把任何示例设为必需组件。
|
||||
- 连接成功后,MemRelay 尝试从规范化 Base URL 的 `/models` 接口发现模型,供 Web/MCP 刷新、搜索、选择和测试;接口不存在或未列出目标模型时仍允许手工填写模型名称。
|
||||
- 实例保存一个当前启用的模型连接,包括连接名称、Base URL、加密 Token、文本/视觉模型名称、协议模式、探测出的有效协议、请求超时、探测间隔和可空外部管理页面地址。
|
||||
- Token 由 Web 直接填写并使用现有部署主密钥加密;读取配置时不返回明文,也不写入 Markdown、任务正文或日志。
|
||||
- 当前 MiniLM/FastEmbed 继续负责本地语义召回,不经过外部生成模型服务,不占用生成模型额度,也不承担归纳和文档生成。
|
||||
|
||||
### 4.2 调用与职责边界
|
||||
|
||||
- MemRelay 同时实现 OpenAI-compatible Responses API `/responses` 和 Chat Completions API `/chat/completions`,统一转换为内部生成请求和结果,不要求端点同时支持两种协议。
|
||||
- 协议模式支持 `auto`、`responses` 和 `chat_completions`。显式“连接测试”分别使用最小请求探测 Responses 和 Chat Completions,不能仅依赖 `404/405` 判断协议,因为部分兼容端点会对不支持的协议返回通用 `400`。探测过程逐项记录请求是否真正到达、响应格式和稳定错误,不把普通业务参数错误直接判定为协议不支持。
|
||||
- `auto` 根据已完成的能力探测优先选择 Responses,Responses 未通过而 Chat Completions 通过时选择后者;探测成功后保存 `effective_protocol`。正式整理任务只调用已确定的协议,不在生成失败后跨协议重放,避免重复生成和计费。手动模式只测试和调用指定协议;管理员可以重新探测或切换,不需要修改 Base URL 和 Token。
|
||||
- Responses 和 Chat Completions 都支持非流式响应与 SSE 流式响应;端点只支持其中一种传输方式时保存有效模式,后台整理器统一组装完整结果后再校验。
|
||||
- 两种协议都必须能产生可通过固定 Pydantic schema 校验的 JSON 结果。优先使用端点支持的原生 JSON Schema/structured output;不支持时使用严格 JSON 提示词并执行相同校验和一次结构化修复。
|
||||
- MemRelay 只记录连接名称、请求模型、响应模型、服务请求 ID、标准响应中可用的输入/输出 Token、耗时和结果,不建立本地月度额度、费用估算或服务端账号用量账本。
|
||||
- 账号轮询、模型映射、优先级、权重、配额冷却和上游故障切换只在外部服务本身提供时生效;MemRelay 把连接视为一个端点,不假设或管理其内部路由。
|
||||
- 网关层对同一次外部生成请求最多执行 3 次有界重试,覆盖全部 HTTP 传输层异常(包括远端协议断开、代理断流、连接错误和超时)、408、429、5xx 和流式中断,并遵循 `Retry-After` 或指数退避;流式失败时可降级为非流式,结构化参数不兼容时可移除 schema 重试。整理任务级重试、依赖等待和队列合并仍由上层单独控制,不能形成无界重复调用。
|
||||
- 模型返回格式无效时,MemRelay 可以基于原响应发起一次明确的结构化修复请求;这属于整理业务校验,不属于上游故障切换。
|
||||
- 每次调用执行可配置的输入、输出和总上下文预算,每个任务另有最大模型调用轮数和总 Token 预算。来源超出单次预算时先按文档/代码符号等自然边界分批生成带来源引用的中间结果,再在独立预算内分层合并;任务在同一持久化记录内继续分批,全部应处理来源得到明确处置前不能标记成功或推进成功游标。达到任务总预算时以稳定错误进入 `failed` 并保留原游标,调整预算后可显式重试,不能静默截断。
|
||||
- 外部服务的账号、真实模型映射、路由、额度和详细统计继续在对应服务中维护;MemRelay Web 不复制这些功能,也不调用非标准管理 API。
|
||||
|
||||
### 4.3 依赖健康、暂停与自动恢复
|
||||
|
||||
- 模型连接状态为 `unconfigured`、`checking`、`available`、`waiting_dependency`、`configuration_error`。
|
||||
- `unconfigured` 是正常的中性状态:不启动探测、调度或整理 worker,不创建 `waiting_dependency` 任务,也不影响任何非 AI 接口。只有保存并启用完整连接后才进入检查流程。
|
||||
- 保存配置时立即测试 Base URL、认证、可空 `/models`、Responses、Chat Completions、非流式/流式传输、文本模型最小结构化生成和可空视觉模型;逐项记录 `unknown`、`supported`、`unsupported` 或 `error`。文本生成、选定协议和结构化结果等必需能力失败时标红;未配置视觉模型、不提供 `/models`、标准用量字段缺失等可选能力使用中性或警告状态,不把连接整体误报为故障。
|
||||
- `/models`、视觉或标准用量字段不受支持时不阻断已通过的文本整理能力;文本生成或结构化结果不可用时连接不能进入 `available`。
|
||||
- 网络、TLS、远端协议断开、代理断流、超时、`429` 和服务最终返回的 `5xx` 表示模型连接暂不可用。当前执行尝试和模型调用记录必须结束并保存稳定错误码,任务释放运行租约后进入 `waiting_dependency`,自动整理工作进程停止领取新任务;后续自动变化继续合并到各范围唯一的等待任务,不逐条追加队列。记忆、搜索、密码库、文件仓储和 Agent 来源同步继续工作。
|
||||
- 优先遵循 `Retry-After`;没有时从 5 分钟开始指数退避,最长 1 小时。每次到期先执行最小端到端生成探测,成功后按合并键恢复等待任务,不要求用户手动重试。
|
||||
- `401/403`、Base URL 无效、文本模型不存在或响应协议不兼容标记为 `configuration_error`。任务继续保留,修正配置并通过测试后自动恢复,不进行高频无效探测。
|
||||
- 服务重启后从 SQLite 恢复模型连接等待状态和所有等待任务;上个进程遗留的 `running` 模型调用统一结束为 `MODEL_CALL_INTERRUPTED`,未完成整理任务重新排队。依赖故障不会把整理任务标记为永久失败,也不会修改最后成功的整理文档。
|
||||
|
||||
### 4.4 当前项目开发测试连接
|
||||
|
||||
- Base URL:`https://cc2.cx/v1`
|
||||
- 文本模型:`gpt-5.6`
|
||||
- 协议:`responses`
|
||||
- API Key 由用户在当前执行环境中提供,只通过临时环境变量和 MemRelay 加密运行时配置使用,不写入计划、源码、测试快照、错误响应或部署示例。
|
||||
- 使用 `POST /responses` 和最小输入完成真实生成验收,再验证结构化输出、流式响应、错误映射、暂停/恢复和任务整理;模型发现接口即使不可用也不阻断手工模型名。
|
||||
- 开发测试凭证只允许运行时注入或写入隔离的加密测试数据库;生产配置不得包含或复用任何开发测试连接和凭证,凭证到期/撤销由提供方管理。
|
||||
|
||||
## 5. 整理任务模型
|
||||
|
||||
SQLite 增加以下可迁移、可恢复的数据:
|
||||
|
||||
### 5.1 `curation_jobs`
|
||||
|
||||
- 任务 ID、范围、项目 ID、触发方式、整理模式、来源策略和目标文档。
|
||||
- 状态:`queued`、`collecting`、`running`、`waiting_dependency`、`applying`、`completed`、`failed`、`cancelled`。
|
||||
- 保存稳定的 `coalesce_key`、上次成功整理游标、最新观察游标、有限的目标文档提示、触发次数和聚合摘要。自动任务按“范围或工作区 + 整理模式”生成 `coalesce_key`,同一键最多存在一个等待任务;任务行不累加每次变化的来源 ID 或完整触发正文。
|
||||
- 来源游标、开始/结束时间、重试次数、下次重试时间、错误码和可读错误;整理起点始终是上次成功游标,终点持续更新为最新观察游标,不能因覆盖等待任务而跳过中间变化。
|
||||
- 输入来源数量、生成文档数量、跳过数量、模型用量、耗时、覆盖范围和未覆盖来源摘要。每个来源最终处置为 `processed`、`unchanged` 或带稳定原因的 `unsupported/skipped`;没有处置的来源仍属于待处理范围。
|
||||
- 每次执行尝试领取时快照非秘密的模型连接 revision、有效协议、模型名、提示词版本、结构化 schema 版本和整理预算;Token 仍从加密连接配置按 revision 解析,不复制到任务。运行中的一次尝试固定使用该快照;进入 `waiting_dependency` 后原尝试已经结束,恢复时建立新尝试并使用当前已验证配置。
|
||||
|
||||
### 5.2 `curation_attempts`
|
||||
|
||||
- 每次实际执行保存任务 ID、尝试序号、模型配置 revision、有效协议、模型、提示词/schema 版本、预算、状态和错误。
|
||||
- `curation_retry` 默认使用当前已验证配置;只有原配置仍存在且凭证可用时,管理员才可明确选择原配置。历史任务展示实际使用的快照,避免配置变化后无法复盘。
|
||||
|
||||
### 5.3 `curated_documents`
|
||||
|
||||
- 稳定文档 ID、范围、项目、文档类型、Markdown 路径和当前 revision。
|
||||
- 最新任务 ID、来源摘要哈希、模型和提示词版本、更新时间。
|
||||
- SQLite 只保存可重建引用,正文仍由 Basic Memory Markdown 保存。
|
||||
|
||||
### 5.4 `curation_sources`
|
||||
|
||||
- 任务与记忆、检查点、文件、Git commit 的来源关系。
|
||||
- 保存来源 ID、来源 revision、内容哈希、`origin`、是否实际送入模型及最终处置。处置为 `processed`、`unchanged`、`unsupported` 或 `skipped`,后两者必须保存稳定原因;`origin` 至少区分 `user`、`agent`、`external`、`curation`、`index`、`git` 和 `system`。
|
||||
- 用于增量整理、追溯来源、跳过未变化内容和判断是否需要重新整理。
|
||||
|
||||
### 5.5 `curation_change_log`
|
||||
|
||||
- 每个用户、Agent 和外部来源变化分配单调递增序号,保存范围、来源引用、变更类型、revision/内容哈希、目标提示、`origin` 和时间;删除使用 tombstone,确保游标范围查询不会漏掉已删除来源。
|
||||
- 等待任务只保存起止序号,执行时查询 `(last_success_cursor, latest_observed_cursor]` 的变化并解析当前来源内容,不把事件清单复制进任务行。
|
||||
- 所有受影响合并键的成功游标越过某段变化且任务历史不再需要逐事件追溯后,才按保留策略压缩旧变更日志;任务实际使用的来源关系继续保存在 `curation_sources`。
|
||||
|
||||
### 5.6 `curation_settings`
|
||||
|
||||
- 实例只有一份当前启用的外部模型连接;Base URL、加密 Token、文本/视觉模型名称、配置协议、有效协议、流式模式、请求超时、探测间隔和可空管理页面地址按 revision 保存。被任务尝试引用的历史 revision 和提示词/schema 版本按历史保留策略保存,未被引用的旧配置可清理。
|
||||
- 实例时区只保留一份全局配置;新鲜度阈值、重试策略、场景模板、最大并发、单次输入/输出 Token 预算、每任务最大调用轮数/总 Token 预算、分批大小和合并层级可按全局、场景类型和工作区配置,工作区未覆盖时依次继承场景和全局值。
|
||||
|
||||
### 5.7 `curation_model_calls`
|
||||
|
||||
- 任务 ID、用途、连接名称、有效协议、流式模式、请求模型、响应模型、服务请求 ID、提示词版本、开始/结束时间和结果。
|
||||
- 输入/输出 Token、延迟和稳定错误码;只用于任务追踪,不维护上游账号额度或费用账本。
|
||||
|
||||
### 5.8 `curation_dependency_state`
|
||||
|
||||
- 外部模型连接当前状态、能力矩阵、最后检查/成功/失败时间、HTTP 状态、稳定错误码、可读原因和下次探测时间。
|
||||
- 状态在服务重启后恢复;不保存外部服务内部的账号、上游 Token、真实额度、路由或凭证冷却明细。
|
||||
|
||||
### 5.9 `curation_schedules`
|
||||
|
||||
- 规则 ID、名称、触发类型、作用范围、可空工作区 ID、启用状态、继承方式、时区模式、IANA 时区和 recurrence 配置。
|
||||
- 触发类型为 `workspace_quiet`、`workspace_fallback` 或 `global_curation`。前两类支持实例默认和工作区覆盖;全局整理只使用实例级规则。
|
||||
- `workspace_quiet` 保存静默时长和可空最大延迟;其余规则支持 `interval`、`daily`、`weekly` 和 `cron`。
|
||||
- `interval` 保存正整数、`minutes/hours/days` 单位和锚点;`daily` 保存本地时间;`weekly` 保存一个或多个星期和本地时间;`cron` 保存标准五段表达式。
|
||||
- 保存上次计划时间、上次实际触发时间、下次触发时间、错过执行策略、最近状态和可读错误。默认错过策略为恢复后合并执行一次,不回放每个错过周期。
|
||||
|
||||
### 5.10 `usage_profiles`
|
||||
|
||||
- 档案 ID、名称、说明、启用状态和时间;默认创建不可删除的 `shared` 团队档案。
|
||||
- MCP Token 和来源包可关联档案,记忆与整理文档 frontmatter 保存档案引用。
|
||||
- 档案只用于习惯归属、上下文选择和来源追溯,不改变现有单管理员、共享工作区和 Token 权限模型。
|
||||
|
||||
### 5.11 `git_connections`
|
||||
|
||||
- 连接名称、准确 remote URL 或带 `{repo}` 占位符的 URL 模板、用户名、传输方式、凭证存储方式及引用、默认分支、本地提交身份、允许写入测试、允许 push-to-create 和启用状态。
|
||||
- 用户自行选择任意 Git 服务、注册专用于 MemRelay 的账号,并在 MemRelay 的 Git 连接页面填写 URL、用户名以及 Token、账号密码或 SSH 私钥;MemRelay 不识别或绑定具体平台,也不注册平台账号。
|
||||
- Web 接收凭证明文但不回显;凭证存储支持外部 Vaultwarden/Bitwarden 条目或使用部署主密钥进行本地 AES-GCM 加密。已连接密码库时默认保存到密码库,否则允许使用本地加密存储,Git remote 不因密码库未配置而失效。
|
||||
- 能力探测只使用标准 Git CLI,分别记录 URL 解析、`ls-remote`、clone/fetch、push、删除临时探测 ref 和服务端 push-to-create 的 `unknown/supported/unsupported/error` 状态。
|
||||
- 标准 Git 协议没有远程仓库列表、创建、改名、归档和删除接口;只有服务端支持 push-to-create 时才能通过首次 push 创建仓库,其余能力明确标红且不伪装可用。
|
||||
|
||||
### 5.12 `memory_repositories`
|
||||
|
||||
- 仓库 ID、模式、范围、工作区 ID、本地根目录、解析后的远程 URL、默认分支和状态。
|
||||
- 保存当前本地 commit、最后成功 push、远程可达性、落后提交数、工作树状态和可空归档时间。
|
||||
- 全局仓库和工作区仓库使用稳定 ID 绑定;工作区改名不改变本地目录和远程仓库标识,避免 URL 漂移。
|
||||
|
||||
### 5.13 `git_sync_jobs`
|
||||
|
||||
- 操作 ID、仓库 ID、记忆/检查点/整理任务引用、动作、目标 commit、状态、尝试次数、下次重试和错误。
|
||||
- 状态为 `pending`、`committing`、`pushing`、`completed`、`waiting_remote`、`failed`、`cancelled`。
|
||||
- 同一逻辑写入只生成一个本地提交;服务重启、网络中断和重复事件通过操作 ID 幂等恢复。
|
||||
|
||||
## 6. 无人值守工作流
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Trigger["定时 / 进度快照 / 记忆或文件变化 / 手动触发"] --> Merge["按范围与模式合并自动变化"]
|
||||
Merge --> Queue["持久化整理任务"]
|
||||
Queue --> Fresh{"MCP 来源是否足够且新鲜"}
|
||||
Fresh -->|是| McpSource["读取 Agent 已同步的记忆、进度和文档"]
|
||||
Fresh -->|否| Repository["读取文件仓储与原始笔记"]
|
||||
Repository --> HasGit{"工作区是否配置 Git"}
|
||||
HasGit -->|是| GitSource["更新受管理的 Git 工作区"]
|
||||
HasGit -->|否| Collect["合并记忆、进度、文档和文件来源"]
|
||||
GitSource --> Collect
|
||||
McpSource --> Collect
|
||||
Collect --> Retrieve["语义召回、去重、分段和来源标注"]
|
||||
Retrieve --> Gateway{"外部模型连接是否可用"}
|
||||
Gateway -->|否| Wait["任务等待依赖并暂停自动领取"]
|
||||
Wait --> Probe["按 Retry-After / 退避执行端到端探测"]
|
||||
Probe -->|恢复| Gateway
|
||||
Gateway -->|是| Model["调用已配置文本模型生成结构化结果"]
|
||||
Model --> Validate["校验 schema、范围、来源和 revision"]
|
||||
Validate --> Write["写入整理 Markdown 新 revision"]
|
||||
Write --> Index["Basic Memory 重新索引"]
|
||||
Index --> GitEnabled{"记忆 Git 是否启用"}
|
||||
GitEnabled -->|否| Finish["记录历史、调用摘要和下次增量游标"]
|
||||
GitEnabled -->|是| GitCommit["生成记忆 Git 提交"]
|
||||
GitCommit --> Finish
|
||||
GitCommit -.异步.-> GitPush["推送远程记忆仓库"]
|
||||
```
|
||||
|
||||
执行步骤:
|
||||
|
||||
1. 触发器先把真实来源变化写入带单调序号的变更日志,再按范围和整理模式查找可合并任务。自动触发存在等待任务时只推进其最新游标并合并有限目标提示与触发摘要;不存在时才创建持久化任务。手动强制任务遵循调用方明确选择的拒绝或替换策略,不被静默合并。
|
||||
2. 工作进程领取任务并记录租约,服务重启后可恢复未完成任务。
|
||||
3. 根据最后 Agent 同步时间、来源数量、文件变化和目标文档判断来源覆盖是否完整。
|
||||
4. 先读取记忆、进度快照和文件仓储;配置 Git remote 的工作区再使用目标分支和所选凭证存储中的 Git 凭证执行 clone/fetch/checkout。
|
||||
5. 根据工作区类型读取源码、项目文档、办公资料、课程、笔记、研究材料和版本历史;二进制附件通过文件提取适配器处理。
|
||||
6. 使用 MiniLM 和元数据分层检索与目标文档相关的来源,增量任务覆盖上次成功游标到最新观察游标之间的全部变化。超过配置的输入预算时在同一任务内按来源边界分批整理,再执行有预算上限的层级合并;每个来源记录明确处置,任务结果列出不支持或跳过的来源,不能静默截断。
|
||||
7. 领取任务时固定本次尝试使用的模型连接 revision、有效协议、模型、提示词/schema 版本和输入/输出预算,再调用配置的文本模型;账号轮询、配额冷却和故障切换仅在所连接服务自身支持时由其完成。
|
||||
8. 生成模型返回固定 JSON schema,MemRelay 按工作区模板渲染为 Markdown。
|
||||
9. 写入前检查整理文档 revision;冲突时重新读取最新版本后执行一次受控重整,不直接覆盖。
|
||||
10. 写入成功后更新 Basic Memory 索引;记忆 Git 已启用时再为本次逻辑变更生成一个本地提交,配置 remote 时异步 push。Git 未启用或 remote 未配置都不阻塞整理结果使用。
|
||||
11. 更新上下文优先级、任务历史、模型调用摘要和成功来源游标;Git 提交记录任务 ID、来源范围、操作者和变更摘要。只有完整应用成功,且游标范围内每个变化都已有 `processed/unchanged/unsupported/skipped` 明确处置后才推进成功游标;未处置来源使任务保持未完成。
|
||||
12. 任务临时文件清理;外部模型连接不可用时保留每个合并键唯一的等待任务并暂停自动整理,后续变化继续合并。端到端探测恢复后,每个合并键只执行一次即可覆盖故障期间全部变化。
|
||||
|
||||
## 7. 自动触发
|
||||
|
||||
- 自动触发器只有在 AI 整理已配置并启用时才创建或合并任务;未配置 AI 时不排队。AI 从关闭切换为启用时先比较现有 revision 与最后成功游标,没有基线则创建一个初始全量任务,已有基线则把停用期间变化合并为一个增量任务。
|
||||
- AI 整理启用后,用户、Agent 或外部来源产生的 `memory_save`、`checkpoint_save`、`curation_source_submit`、文件上传和文件元数据变化只记录“需要整理”,不为每次写入立即调用模型。AI 整理写回、Basic Memory 索引、Git 提交/推送、扫描缓存和其他内部事件标记对应 `origin`,不得再次设置“需要整理”,避免形成递归整理循环。
|
||||
- 工作区静默增量整理具有独立开关。启用后在最后一次变化达到配置的静默时长时合并变化并运行一次增量整理;静默时长可自定义,可空最大延迟用于避免持续变化导致任务永远不触发。
|
||||
- 保存重要进度快照后按工作区模板优先刷新当前状态、决定、任务,以及开发故障、办公行动项、学习知识点等场景文档。
|
||||
- 工作区兜底整理和全局习惯/跨工作区经验整理分别具有独立开关和 recurrence 规则,可选择每隔若干分钟、小时或天,每日指定时间,每周选择一个或多个星期并指定时间,或使用高级五段 Cron。
|
||||
- 每条规则的时区默认继承实例时区,也可单独选择 IANA 时区;实例时区本身可在 Web/MCP 中修改。所有状态、预览和任务历史同时显示时区与带偏移的实际时间。
|
||||
- 实例规则可作为工作区默认值;工作区可以选择继承、完全覆盖或关闭自己的静默增量和兜底整理,不影响其他工作区。
|
||||
- 保存规则前校验时区、间隔、星期、时间和 Cron,并返回未来至少 5 次执行时间预览;配置生效后原子重算 `next_run_at`,无需重启服务。
|
||||
- 服务重启或停机错过周期时默认只合并补跑一次,不为每个错过时间创建任务;管理员也可选择跳过错过执行。夏令时不存在的本地时间顺延到下一个有效时刻,重复的本地时间只触发一次。
|
||||
- 同一工作区的静默和周期触发按来源游标合并;模型长期不可用时,每个“范围或工作区 + 整理模式”最多保留一个等待的自动任务,新变化只更新该任务的最新游标、有限目标文档提示、计数和聚合摘要,不复制来源正文或逐事件 ID。若任务正在运行,最多保留一个合并后的自动后继任务。
|
||||
- 手动非强制触发可复用相同范围的等待任务并返回其任务 ID;手动强制任务不被静默丢弃或合并。同一范围已有待执行的强制任务时默认返回冲突,调用方只有显式指定替换后才取消旧任务并创建新任务,防止手动操作绕过队列上限。
|
||||
- 全量整理只在首次启用、模型/提示词重大升级、索引重建或用户明确触发时运行。
|
||||
- 同一工作区默认只允许一个整理任务运行;不同工作区可按配置并发。
|
||||
- 关闭任一自动规则只停止对应触发器;关闭全部调度时仍保留手动 Web、REST 和 MCP 触发能力。
|
||||
|
||||
## 8. MCP 工具
|
||||
|
||||
- 现有 `capabilities_get` 同步返回工作区类型、记忆空间、整理文档类型、来源适配器、外部模型连接健康和全部整理工具能力;不返回 Token。
|
||||
- `capabilities_get` 分别返回 `curation_enabled` 和 `memory_git_enabled`。能力关闭时工具仍可被客户端发现,但运行类工具返回稳定的 `FEATURE_DISABLED` 和配置入口信息,不创建后台任务;读取既有整理文档或既有 Git 历史的工具在数据存在时仍可用。
|
||||
|
||||
### 8.1 `curation_run`
|
||||
|
||||
创建整理任务并立即返回,不等待模型执行完成。
|
||||
|
||||
建议参数:
|
||||
|
||||
- `scope`: `global` 或 `project`
|
||||
- `project_id`: 工作区范围必填,沿用兼容字段名
|
||||
- `mode`: `incremental` 或 `full`
|
||||
- `source_strategy`: `auto`、`mcp`、`repository`、`git` 或 `all`
|
||||
- `document_types`: 可空,空值表示按范围使用默认文档集合
|
||||
- `reason`: 可空,记录本次触发原因
|
||||
- `force`: 是否忽略未变化判断
|
||||
- `pending_policy`: 手动任务遇到同范围待执行任务时使用 `reuse`、`reject` 或 `replace`;非强制默认 `reuse`,强制默认 `reject`,`replace` 必须由调用方明确指定
|
||||
|
||||
`replace` 只替换待执行任务身份和调用参数,新任务必须继承旧任务尚未成功覆盖的最早游标并合并当前最新游标,不能因替换而丢失已积累变化。
|
||||
|
||||
返回任务 ID、初始状态、来源策略和预计目标文档,不返回整理正文。
|
||||
|
||||
### 8.2 `curation_status`
|
||||
|
||||
查询整理服务和任务状态。
|
||||
|
||||
- 传入 `job_id` 时返回单个任务的阶段、进度、来源统计、重试、错误和时间。
|
||||
- 不传 `job_id` 时返回工作进程状态、队列长度、当前任务、模型可用性,以及各启用规则的时区和下一次计划执行时间。
|
||||
- 队列统计同时返回实际等待任务数、被合并的触发次数、各合并任务覆盖的起止游标和运行任务的后继任务状态,不能把触发计数误报为队列长度。
|
||||
- 状态查询不泄露模型凭证或 Git 凭证。
|
||||
|
||||
### 8.3 `curation_history`
|
||||
|
||||
分页查询整理历史。
|
||||
|
||||
建议筛选:
|
||||
|
||||
- `scope`
|
||||
- `project_id`
|
||||
- `status`
|
||||
- `trigger`
|
||||
- `started_after`
|
||||
- `limit`
|
||||
- `cursor`
|
||||
|
||||
每条历史返回任务、来源范围、生成/更新文档、实际使用的模型配置/提示词/schema revision、合并触发摘要、覆盖与未覆盖来源、用量、耗时、错误和变更摘要。
|
||||
|
||||
### 8.4 `curated_document_get`
|
||||
|
||||
读取当前整理文档或指定历史 revision。
|
||||
|
||||
支持两种定位方式:
|
||||
|
||||
- `document_id`
|
||||
- `scope + project_id + document_type`
|
||||
|
||||
建议参数:
|
||||
|
||||
- `revision`: 可空,默认返回最新版本
|
||||
- `include_sources`: 是否返回来源引用,默认只返回正文和核心元数据
|
||||
|
||||
返回 Markdown 正文、revision、更新时间、来源摘要、模型和最新任务 ID。
|
||||
|
||||
### 8.5 `curation_source_submit`
|
||||
|
||||
让具有本地工作区上下文的 Agent 一次提交完整来源包,减少多次 MCP 往返并为无人值守整理提供明确来源边界。
|
||||
|
||||
参数包括:
|
||||
|
||||
- `request_id`:整个来源包的幂等键。
|
||||
- `project_id`:目标工作区,沿用兼容字段名。
|
||||
- `usage_profile_id`:可空;默认从调用该工具的 MCP Token 获取,未绑定时使用 `shared`。
|
||||
- `workspace_type`:开发、办公、学习、研究、个人或通用场景。
|
||||
- `git_remote`、`branch`、`commit`、`dirty`:可空,仅在 Agent 实际读取 Git 工作区时提交。
|
||||
- `changed_resources`:文件 ID 或路径、变更类型、内容哈希、资源类型和可空摘要。
|
||||
- `memories`:规则、事实、决定和经验数组,每项包含标题、正文和标签。
|
||||
- `documents`:已通过文件仓储上传的文件 ID、工作区相对路径、用途和摘要。
|
||||
- `checkpoint`:可空的进度快照,包含完成内容、原因、关键变化、验证/证据、问题、解决方案和下一步;字段适用于开发、办公、学习和个人任务。
|
||||
- `observed_at`:Agent 完成本次观察的时间。
|
||||
|
||||
服务端先校验整个来源包,再为各项派生稳定请求 ID,复用现有记忆、检查点和文件服务写入。中途失败时任务保持可恢复状态,重试从未完成项继续且不重复已成功项;只有全部写入完成后才返回来源包成功状态。
|
||||
|
||||
返回来源包 ID、各类写入结果、可空来源 commit、完成状态和是否触发增量整理。
|
||||
|
||||
### 8.6 配套工具
|
||||
|
||||
同时提供完成工作流必需的工具:
|
||||
|
||||
- `curated_document_list`:列出全局或工作区整理文档及更新时间。
|
||||
- `curation_cancel`:取消仍在排队或尚未写入的任务。
|
||||
- `curation_retry`:使用原任务来源和目标重新执行失败或已取消任务并建立新的尝试记录;默认使用当前已验证模型配置,可在原配置仍可用时明确选择原配置。
|
||||
- `curation_settings_get`:读取模型、调度、来源、场景和工作区覆盖配置。
|
||||
- `curation_settings_update`:更新实例时区、无人值守来源、场景和并发配置。
|
||||
- `curation_schedule_list`:按触发类型和工作区列出规则、继承关系、最终时区、上次/下次执行时间和状态。
|
||||
- `curation_schedule_save`:创建或更新静默、间隔、每日、每周或 Cron 规则,立即重算下一次执行时间。
|
||||
- `curation_schedule_delete`:删除自定义规则或工作区覆盖并恢复继承;内置默认规则只允许关闭或修改,不物理删除。
|
||||
- `curation_schedule_preview`:不保存配置,校验候选规则并返回指定时区下未来至少 5 次执行时间。
|
||||
- `curation_model_connection_status`:返回外部模型连接配置状态、Responses/Chat Completions 和流式能力矩阵、配置/有效协议、当前可用性、文本/视觉模型、最后成功/失败、等待任务数和下次探测时间,不返回 Token。
|
||||
- `curation_model_list`:通过规范化 Base URL 的可空 `/models` 刷新并返回模型名称、显示名称和服务提供的能力元数据;接口不可用时返回 `unsupported` 并继续允许手工模型名。
|
||||
- `curation_model_connection_test`:立即执行连接、认证、模型发现、Responses、Chat Completions、流式/非流式、最小结构化文本生成和可空视觉测试;成功时保存有效协议并恢复等待队列,失败时返回逐项状态、稳定错误码和可读原因。
|
||||
- `usage_profile_list`:列出记忆空间及关联 Token、记忆和整理状态。
|
||||
- `usage_profile_save`:创建或更新档案,并可把 MCP Token 绑定到该档案。
|
||||
- `usage_profile_token_bind`:把一个或多个已有 MCP Token 重新绑定到指定档案,可选择替换该档案的现有绑定。
|
||||
- `usage_profile_delete`:删除没有正式来源引用的非 `shared` 档案,或把来源迁移到指定档案后删除。
|
||||
- `curated_document_revert`:把指定历史 revision 作为新的最新 revision 写回,保留完整回滚记录并重新索引。
|
||||
|
||||
### 8.7 记忆 Git 工具
|
||||
|
||||
- `memory_repository_status` 在功能从未启用时返回中性 `disabled`;创建、同步和恢复类工具要求管理员先明确启用记忆 Git,不因缺少 remote 或凭证自动启用。
|
||||
- `git_connection_get/save/test/delete`:配置准确 remote URL 或 URL 模板及用户自行准备的凭证,使用 Git CLI 测试读写能力;秘密值优先写入 Vaultwarden,未配置密码库时由部署主密钥本地加密,读取时不返回明文。
|
||||
- `memory_repository_list/status/create/sync`:列出本地记忆仓库、查看本地/远程状态、按 URL 模板初始化映射并立即提交或推送待同步内容;远程不存在且不支持 push-to-create 时返回明确待处理状态。
|
||||
- `memory_repository_history`:按全局/工作区、时间、操作者、操作类型和记忆 ID 查询提交历史。
|
||||
- `memory_repository_diff`:查看两个 commit 或指定 commit 与当前版本之间的 Markdown 差异。
|
||||
- `memory_version_get`:读取某条记忆、检查点或整理文档在指定 commit 的内容和元数据。
|
||||
- `memory_version_restore`:通过正常记忆服务恢复单个文档历史版本,增加 revision、重新索引并生成新的恢复提交,不重写既有 Git 历史。
|
||||
- `memory_snapshot_restore`:在正确范围的写锁下恢复一个记忆仓库的历史快照;`single` 仓库使用全局记忆写锁,`per_workspace` 使用目标范围写锁。校验 Markdown 后重建 SQLite 可重建引用和 Basic Memory 索引,再生成新的恢复提交。
|
||||
- `memory_remote_inspect`:clone/fetch 到隔离暂存区,只读检查远程分支、commit、Markdown 树、稳定 ID、模式兼容性和与本地历史的关系,不改变在线记忆。
|
||||
- `memory_remote_import`:从已检查的远程 commit 选择单文档、工作区或仓库范围,通过正常记忆服务导入为新的 revision 和本地提交;用于处理 `remote_diverged`,不执行自动 pull/merge 或历史重写。
|
||||
- `memory_remote_bootstrap`:在空实例或明确的恢复模式中从 remote 建立本地记忆仓库,校验全部 Markdown,重建 SQLite 可重建引用和 Basic Memory 索引,再绑定远程状态。该工具不恢复部署主密钥、会话、Token、文件正文或密码库数据。
|
||||
- `memory_repository_archive_purge`:永久清除已删除工作区对应的独立本地 Git 历史;必须与普通项目删除分离并由管理员明确执行。
|
||||
- `memory_repository_unbind`:解除 remote 绑定但保留本地仓库和历史;标准 Git CLI 不提供远程仓库归档或删除能力。
|
||||
|
||||
Agent 同步本地资料和结论继续复用现有工具:
|
||||
|
||||
- `project_resolve_or_create`
|
||||
- `context_get`
|
||||
- `memory_save`
|
||||
- `checkpoint_save`
|
||||
- `file_upload_prepare`
|
||||
- `file_metadata_update`
|
||||
- `curation_source_submit`
|
||||
|
||||
`curation_source_submit` 是对一次工作区上下文同步的编排入口,不替代单条 `memory_save`、`checkpoint_save` 和文件上传;Agent 可按任务规模选择批量同步或单项写入。
|
||||
|
||||
## 9. REST 接口
|
||||
|
||||
REST 统一放在 `/api/v1/curation`:
|
||||
|
||||
- `POST /jobs`
|
||||
- `POST /sources`
|
||||
- `GET /status`
|
||||
- `GET /jobs/{job_id}`
|
||||
- `POST /jobs/{job_id}/cancel`
|
||||
- `POST /jobs/{job_id}/retry`
|
||||
- `GET /history`
|
||||
- `GET /documents`
|
||||
- `GET /documents/{document_id}`
|
||||
- `PATCH /documents/{document_id}`
|
||||
- `GET /documents/{document_id}/history`
|
||||
- `GET /documents/{document_id}/diff`
|
||||
- `POST /documents/{document_id}/revert`
|
||||
- `GET /settings`
|
||||
- `PATCH /settings`
|
||||
- `GET /schedules`
|
||||
- `POST /schedules`
|
||||
- `PATCH /schedules/{schedule_id}`
|
||||
- `DELETE /schedules/{schedule_id}`
|
||||
- `POST /schedules/reset-defaults`
|
||||
- `POST /schedules/preview`
|
||||
- `GET /model-connection/status`
|
||||
- `GET /model-connection/models`
|
||||
- `POST /model-connection/test`
|
||||
- `GET /profiles`
|
||||
- `POST /profiles`
|
||||
- `PATCH /profiles/{profile_id}`
|
||||
- `PUT /profiles/{profile_id}/tokens`
|
||||
- `DELETE /profiles/{profile_id}`
|
||||
|
||||
MCP 与 Web 复用同一服务层,不建立并行整理逻辑。
|
||||
|
||||
记忆 Git REST 接口统一放在 `/api/v1/git`:
|
||||
|
||||
- `GET/POST/PATCH/DELETE /connections`
|
||||
- `POST /connections/test`
|
||||
- `GET /mode-migration`
|
||||
- `POST /mode-migration`
|
||||
- `GET /repositories`
|
||||
- `POST /repositories`
|
||||
- `GET /repositories/{repository_id}/status`
|
||||
- `POST /repositories/{repository_id}/sync`
|
||||
- `POST /repositories/{repository_id}/remote/inspect`
|
||||
- `POST /repositories/{repository_id}/remote/import`
|
||||
- `POST /repositories/bootstrap`
|
||||
- `GET /repositories/{repository_id}/history`,支持时间、提交者、操作类型、工作区和资源 ID 筛选
|
||||
- `GET /repositories/{repository_id}/diff`
|
||||
- `POST /repositories/{repository_id}/restore`
|
||||
- `DELETE /repositories/{repository_id}/archive`
|
||||
- `DELETE /repositories/{repository_id}/remote`
|
||||
- `GET /versions/{resource_id}`
|
||||
- `POST /versions/{resource_id}/restore`
|
||||
|
||||
## 10. Web 页面
|
||||
|
||||
### 10.1 AI 整理总览
|
||||
|
||||
- 外部模型连接状态、能力矩阵、队列长度、等待依赖任务、运行中任务、最近成功/失败和下一次计划运行。
|
||||
- 未配置 AI 时显示中性的“未启用”空状态和配置入口,不显示等待依赖、失败告警或待处理任务;其他页面和导航保持可用。
|
||||
- 支持编辑连接名称、Base URL、可空 Token、协议模式、请求超时、探测间隔、输入/输出 Token 预算、分批/合并预算和可空管理界面地址;自动刷新可搜索模型列表并选择文本/视觉模型,也可手工输入,然后分别执行真实能力测试。
|
||||
- 协议使用 `auto/responses/chat_completions` 分段选择;能力矩阵分别显示 Responses、Chat Completions、流式、非流式、结构化输出、视觉和用量字段,`auto` 旁显示当前探测出的有效协议。必需能力失败标红,暂时不可用显示警告,可选能力未配置或不支持使用中性状态。
|
||||
- 页面不出现平台类型选择,也不内置 CLIProxyAPI、Sub2API 或官方平台配置;只按 OpenAI-compatible 接口探测 Base URL 和实际能力。
|
||||
- 页面显示最近模型调用摘要和可空外部管理页面链接;外部服务内部的账号、上游 Token、路由、额度和详细用量仍由该服务维护。
|
||||
- 全局立即整理、全量整理和暂停/恢复自动整理。
|
||||
- 队列区域按合并键显示上次成功游标、最新观察游标、合并触发次数和后继任务;模型不可用期间队列数量保持有界,同时可观察积累的变化范围。
|
||||
|
||||
### 10.2 工作区整理
|
||||
|
||||
- 工作区类型、整理模板、启用状态、来源策略、Agent 最后同步时间和来源覆盖情况。
|
||||
- 整理文档列表、最后更新时间、revision、来源数量和立即整理按钮。
|
||||
- 文件仓储来源、新鲜度阈值和场景偏好配置;配置 Git remote 时再显示分支、凭证条目和最后抓取 commit。
|
||||
|
||||
### 10.3 记忆空间
|
||||
|
||||
- 管理 `shared` 团队档案和可选成员档案,显示各档案的场景偏好、来源数量和最后活动时间。
|
||||
- MCP Token 可绑定档案;Web 会话可切换当前档案。档案切换只影响习惯归属和上下文,不改变工作区访问权限。
|
||||
|
||||
### 10.4 整理历史
|
||||
|
||||
- 按工作区、范围、状态和时间筛选。
|
||||
- 查看任务阶段、来源、模型用量、错误、生成文档和前后 revision 差异。
|
||||
- 对失败任务重新运行,对排队任务取消。
|
||||
|
||||
### 10.5 整理文档
|
||||
|
||||
- 使用现有 Markdown 编辑/预览组件。
|
||||
- 查看当前正文、历史 revision、来源引用、变更摘要和相关原始记忆。
|
||||
- 人工编辑仍通过现有 revision 冲突检查,后续 AI 整理以最新人工版本为基线。
|
||||
|
||||
### 10.6 记忆版本管理
|
||||
|
||||
- 页面首先提供独立的记忆 Git 启用开关。关闭且从未启用时显示中性的功能说明和启用操作,不初始化仓库、不要求凭证或 remote;关闭已有配置时明确说明历史会保留但停止产生新提交。
|
||||
- 不区分 Gitea、GitHub、GitLab、Gitee 或其他服务,也不内置 Git 平台;用户填写准确 remote URL 或带 `{repo}` 的 URL 模板、用户名、Token/密码或 SSH 私钥、默认分支、本地提交身份和仓库策略。凭证可选择外部密码库或 MemRelay 本地加密存储。
|
||||
- 提供“允许写入测试”和“允许自动创建远程仓库”开关。保存后立即使用 Git CLI 测试;新建工作区时自动初始化本地仓库、生成初始提交,并在允许时通过首次 push 尝试由服务端创建远程仓库。
|
||||
- 使用 Git CLI 展示 URL、读取、写入、临时 ref 清理和 push-to-create 能力矩阵;`unsupported` 或 `error` 项标红并显示原始 Git 错误的可读摘要。
|
||||
- 显示本地仓库列表、当前 commit、远程同步状态、待推送数量、最后成功时间和可读错误。
|
||||
- 支持初始化/绑定本地仓库、立即同步、查看提交历史和 Markdown 差异、恢复单个文档或整个仓库快照、检查/导入远程历史、从远程冷启动重建,以及解除 remote 绑定。
|
||||
- 仓库策略切换先执行只读预检并展示迁移计划;确认后在全局写锁下完成,失败则保持原策略。禁止在已有仓库内部生成嵌套 `.git`,完整 URL 不能选择多仓库模式,URL 模板不能选择单仓库模式。
|
||||
- 工作区创建后按策略解析目标 URL 并尝试首次 push;服务端不支持 push-to-create 时标记 `remote_repository_missing`,展示应由用户自行创建的完整仓库 URL,创建后可一键重试。
|
||||
- remote 不可达不影响本地 Git 提交;页面持续显示 `waiting_remote`,网络或服务恢复后自动补推。
|
||||
|
||||
### 10.7 自动整理调度
|
||||
|
||||
- 顶部提供可搜索的 IANA 实例时区选择器,默认使用部署实例时区;每条规则可以继承实例时区或单独覆盖,并显示当前 UTC 偏移。
|
||||
- 静默增量、工作区兜底和全局整理分开显示,每项都有启用开关。工作区页面可选择继承实例默认、覆盖配置或对当前工作区关闭。
|
||||
- 静默规则使用时长输入并支持可空最大延迟;周期规则使用模式选择器切换“每隔一段时间”“每日”“每周”和“高级 Cron”。
|
||||
- 间隔模式可选分钟、小时或天并填写正整数和锚点;每周模式允许多选星期;Cron 提供五段输入、格式校验和字段说明。
|
||||
- 编辑过程中实时显示未来至少 5 次执行时间、最终时区和带偏移时间;保存后显示上次计划、上次实际运行、下一次运行、错过执行策略和最近错误。
|
||||
- 默认调度可一键恢复,但恢复前显示将被改动的三类规则;关闭自动调度不隐藏或禁用“立即整理”。
|
||||
|
||||
## 11. Agent 提示词更新
|
||||
|
||||
生成的中英文 Agent 提示词增加以下工作流:
|
||||
|
||||
- 会话开始先解析工作区并读取 `workspace_type`,按开发、办公、学习、研究、个人或通用场景使用对应的记忆和整理策略。
|
||||
- 会话同时读取 MCP Token 绑定的 `usage_profile`;个人偏好写入该档案,团队约定明确写入 `shared`。
|
||||
- Agent 有本地资料访问能力时,优先由 Agent 理解源码、文档、笔记、课程和办公文件,不要求服务端重复下载。
|
||||
- 工作过程中持续通过 `memory_save` 保存规则、事实、决定和经验,通过 `checkpoint_save` 保存结构化进度快照。
|
||||
- 需要保留完整文档或附件时使用文件仓储,不把大文件正文塞进普通记忆。
|
||||
- 会话结束前确保当前进度、关键原因、验证或证据、未解决问题和下一步已经同步;没有 Git 的场景不得省略同步。
|
||||
- Agent 不需要等待整理任务;无人值守整理器会在静默期或计划时间自动消费已同步内容。
|
||||
- 需要立即得到整理结果时调用 `curation_run`,随后使用 `curation_status` 查询,完成后通过 `curated_document_get` 读取。
|
||||
- 新会话首先读取场景匹配的整理文档、当前上下文和最新进度快照,再按需要读取原始记忆,降低 Token 消耗。
|
||||
- Agent 只能通过 MemRelay MCP 查询差异和执行受控恢复,不直接操作服务端记忆仓库或向其 remote 推送。
|
||||
|
||||
## 12. Git 兜底工作区
|
||||
|
||||
- 工作区以项目 ID 隔离,路径固定为 `/data/memrelay/workspaces/<project-id>/`。
|
||||
- 使用项目 Git remote 和 Vaultwarden 中映射的 Git 凭证,无需再次询问账号密码。
|
||||
- 分支优先使用项目配置,其次读取远端默认分支,最后依次尝试 `main` 和 `master`;每次任务记录 remote、分支和实际 commit。
|
||||
- HTTPS 和 SSH remote 均可读取;凭证按规范化主机、仓库 URI 和项目映射从 Vaultwarden 唯一解析。
|
||||
- fetch 失败时保留上次成功工作区并标记为缓存来源;网络恢复后自动刷新。
|
||||
- 读取 `.gitignore`、源码、Markdown、配置、提交历史和工作区状态;跳过 `.git` 对象、依赖目录、构建输出和二进制构建产物。
|
||||
- 工作区只作为整理来源,不执行依赖安装、构建脚本、项目代码或任意项目 Shell,也不创建提交或推送远端。
|
||||
- 工作区不放入 MemRelay 文件仓储,也不混入项目文档导出。
|
||||
|
||||
## 13. 记忆 Git 版本管理
|
||||
|
||||
### 13.1 本地仓库布局
|
||||
|
||||
- 记忆 Git 版本管理默认关闭。管理员明确启用后才初始化本地仓库和提交队列;启用后即使没有配置 remote 也持续提交,保证误修改、归档和删除可以回看与恢复。
|
||||
- 首次启用时先在记忆写锁下为当前 Markdown 建立基线提交,不追溯伪造启用前的逐次历史。关闭后停止创建新提交和同步任务,但保留已有 `.git`、映射和可查询历史;重新启用时把关闭期间的当前差异生成一个恢复提交。
|
||||
- 仓库策略支持 `single` 和 `per_workspace`。`single` 以 `/data/basic-memory/memories/` 为仓库根目录;`per_workspace` 分别以 `global/` 和 `projects/<id>/` 为仓库根目录。
|
||||
- 使用完整 remote URL 时只允许 `single`;使用且必须包含 `{repo}` 占位符的 URL 模板时只允许 `per_workspace`。保存时拒绝不匹配的组合,避免多个工作区意外推入同一仓库或模板无法展开。
|
||||
- 仓库策略切换属于受控迁移:先检查现有 `.git`、目标目录、remote 和未提交状态,生成可预览计划;确认后获取全局记忆写锁,提交当前状态、迁移历史并重建映射。任何目标路径已位于其他 Git 工作树内时拒绝执行,禁止嵌套仓库。
|
||||
- 多仓库模式中全局仓库名默认为 `memrelay-global`,工作区仓库名默认为 `memrelay-<slug>-<short-id>`;稳定 ID 防止同名冲突,工作区改名不自动改变既有 remote URL。
|
||||
- 归档 Markdown 保持在原范围仓库内,例如 `global/archive/` 和 `projects/<id>/archive/`,避免归档操作跨 Git 仓库丢失历史。
|
||||
- Basic Memory 扫描和索引必须排除所有 `.git/` 内容;Git `.gitignore` 排除索引、缓存、SQLite、锁、临时文件和秘密值。
|
||||
- 初始化仓库时生成 `.gitattributes`,至少固定 `*.md text eol=lf`,并统一清单类文本的行尾,避免 Windows/Linux 间产生无意义差异。
|
||||
|
||||
### 13.2 通用 remote 与能力探测
|
||||
|
||||
- MemRelay 只调用系统 Git CLI,不使用 Gitea、GitHub、GitLab、Gitee 或其他平台专用 API,也不随 Compose 内置任何 Git 服务。
|
||||
- HTTPS 支持用户名加 Token/密码,SSH 支持私钥和可空口令;秘密值从 Vaultwarden 或 MemRelay 本地加密设置临时注入 `GIT_ASKPASS` 或 SSH 命令环境,不嵌入 remote URL、`.git/config`、进程参数和日志。
|
||||
- 保存连接时先规范化 URL 并执行无副作用的 `git ls-remote` 与 fetch 测试;对已存在且用户允许写测试的 remote,推送唯一临时 ref 后立即删除,以判断 push 和 ref 删除能力。
|
||||
- push-to-create 不能在不产生远程仓库的前提下通用探测,因此初始状态为 `unknown`;首次向真实目标仓库 push 后更新为 `supported` 或 `unsupported`,不创建额外测试仓库。
|
||||
- URL 模板只替换 `{repo}`,不拼接平台特有 API 路径。远程仓库不存在且 push-to-create 不可用时,返回 `remote_repository_missing` 并显示完整目标 URL,等待用户自行创建后重试。
|
||||
- 能力矩阵逐项显示 `unknown`、`supported`、`unsupported` 或 `error`;不支持项标红,但不会阻断本地 Git 历史、记忆读取和其他可用能力。
|
||||
|
||||
### 13.3 新工作区自动建仓
|
||||
|
||||
- 配置 per-workspace URL 模板后,新建工作区自动计算稳定仓库名和完整 remote URL,初始化本地仓库,并把初始 Markdown 与非秘密清单生成第一个提交。
|
||||
- “允许自动创建远程仓库”默认启用。MemRelay 在目标 remote 不存在时执行首次 push;服务端支持 push-to-create 且当前凭证具有权限时,该 push 同时完成远程建仓和初始同步。
|
||||
- 首次 push 成功后记录 `push_to_create=supported`、远程默认分支和最后同步 commit,后续使用普通 push。
|
||||
- 首次 push 失败时不撤销本地仓库和提交:确认远程不存在且不支持 push-to-create 时进入 `remote_repository_missing`;URL 或凭证错误时进入 `configuration_error`;网络或远端暂时不可用时进入 `waiting_remote`。对应能力标红并展示可读原因和完整目标 URL。
|
||||
- 用户在任意 Git 服务上自行创建空仓库或修正权限后,可以执行重新测试/立即同步;MemRelay 不要求更换平台,也不调用平台 API。
|
||||
|
||||
### 13.4 提交与远程同步
|
||||
|
||||
- 每个成功的单条记忆/检查点写入生成一个逻辑提交;`curation_source_submit`、批量导入和一次 AI 整理中的多文档变更各自合并成一个提交,不按文件制造碎片提交。
|
||||
- 提交作者使用配置的 MemRelay Git 身份,提交信息保存操作类型和可读摘要,并使用 trailers 记录操作 ID、工作区 ID、记忆 ID、整理任务 ID 和调用方类型,不记录秘密值。
|
||||
- SQLite 在保存记忆引用时同步写入 `git_sync_jobs`;提交工作进程按仓库加锁并立即尝试提交,失败后通过脏工作树扫描和操作 ID 幂等补交,服务重启不会丢失版本事件。
|
||||
- 本地提交完成后异步 push;remote 不可达、认证失败或网络中断进入 `waiting_remote`,不回滚已生效记忆,恢复后按提交顺序自动补推。
|
||||
- 禁止自动 force push。远程分支出现非 MemRelay 提交或历史分叉时状态变为 `remote_diverged`,停止自动 push 并要求管理员选择重新绑定空仓库、受控导入远程版本或继续使用本地历史。
|
||||
- 远程仓库仅作镜像和恢复来源,不自动 pull/merge 到在线 Markdown。解绑 remote 不删除本地仓库,也不尝试删除服务器上的仓库。
|
||||
|
||||
### 13.5 历史与恢复
|
||||
|
||||
- Web、REST 和 MCP 可以按时间、操作者、操作类型、工作区和资源 ID 查询提交,并查看 Markdown 级差异。
|
||||
- 单文档恢复从指定 commit 读取正文和 frontmatter,通过正常记忆服务写成新 revision,重新索引并生成新的恢复提交;不执行 `git reset` 或重写历史。
|
||||
- 仓库快照恢复先获取与仓库范围匹配的写锁:`single` 模式获取全局记忆写锁,`per_workspace` 获取目标工作区或全局范围写锁。恢复期间暂停对应范围的 Basic Memory 写入和索引,校验目标树中所有 Markdown 和稳定 ID,再恢复文件、重建 SQLite 可重建引用、重建 Basic Memory 索引并生成新提交。
|
||||
- 删除项目之前先通过正常记忆服务删除其 Markdown 并生成 Git 删除提交。`per_workspace` 仓库随后移入 `/data/memrelay/git-archive/<repository-id>/` 保留独立历史;`single` 仓库继续由删除提交保留历史。普通项目删除不物理清除 Git 历史,永久清除归档仓库必须使用单独的管理员操作。
|
||||
- remote 冷启动或灾难恢复先 clone 到隔离暂存区,校验仓库模式、路径、Markdown frontmatter、稳定 ID 和重复项,再在恢复锁下导入,重建 SQLite 可重建引用和 Basic Memory 索引。远程镜像不能恢复未纳入 Git 的数据,完成后仍需显示缺失范围。
|
||||
- `remote_diverged` 的“受控导入”使用同一暂存和校验流程,把选定远程版本通过正常记忆服务写为新的 revision 和提交;不得把远程分支直接覆盖在线工作树。
|
||||
- 永久删除产生 Git 删除提交;只要本地仓库或 remote 历史存在,就可通过受控恢复重新建立引用和索引。
|
||||
- Git 历史不能替代完整 `/data` 备份:它不包含 MemRelay 会话、Token、凭证映射、文件仓储正文、Basic Memory 索引或部署主密钥。
|
||||
|
||||
## 14. 文件内容提取与分段
|
||||
|
||||
- 源码和文本不依赖固定扩展名列表,结合 MIME、内容探测、编码识别和二进制检测读取;保留文件路径、语言、行号范围和 Git commit 来源。
|
||||
- 原生支持 Markdown、纯文本、常见编程语言、JSON、YAML、TOML、XML、HTML、INI、Properties、CSV 和日志。
|
||||
- PDF 先提取文本层,扫描版页面自动进入 OCR;结果保留页码。
|
||||
- DOCX 提取标题、段落、列表和表格;XLSX/XLS/ODS 提取工作表、单元格区域和公式显示值;PPTX/ODP 提取页面标题、正文、备注和表格。
|
||||
- PNG、JPEG、WebP、TIFF 等图片执行 OCR;配置了视觉模型时可同时生成图片内容说明,并保留原文件引用。
|
||||
- ZIP、TAR 和常见压缩包按安全路径和展开上限读取目录及其中受支持文件,不执行归档内程序。
|
||||
- 提取器采用统一接口并缓存结果,缓存键由文件 SHA-256、提取器版本和配置组成;文件未变化时不重复提取。
|
||||
- 长文档按标题、段落、代码符号、页码、工作表或幻灯片边界分段,不在固定字符位置粗暴截断。
|
||||
- 单个文本/源码文件默认直接读取上限为 2 MiB,Office/PDF/图片默认原文件上限为 50 MiB,每个任务默认最多处理 1,000 个文件和 2,000 万提取字符;超过范围时按工作区核心文档、最近变更、入口文件、语义相关度排序,并在结果中报告未覆盖部分。所有上限可配置。
|
||||
- OCR、Office、PDF 和压缩包依赖同时进入 AMD64/ARM64 镜像、许可清单、健康检查和验收,不允许只在开发机存在。
|
||||
|
||||
## 15. 个人习惯与场景记忆整理规则
|
||||
|
||||
- 用户明确表达为“任何场景都适用”的长期规则和偏好进入当前记忆空间的全局整理文档;明确属于团队的规则进入 `shared`。
|
||||
- 用户在某一场景表达的习惯先进入 `development`、`office`、`study`、`research`、`personal` 或 `general` 场景偏好,不默认提升为全局。
|
||||
- 从行为归纳的偏好记录来源工作区、场景、出现次数、最近时间、反例和置信度;默认至少在 3 次独立任务中重复才形成场景偏好。
|
||||
- 场景偏好只有在同一记忆空间的至少 2 种场景中重复成立且没有反例时才自动提升为该空间的全局偏好,不要求逐条确认。
|
||||
- 工作区专用做法保留在工作区范围,办公格式、学习复习方式、编码规范和个人笔记习惯互不污染。
|
||||
- 不同记忆空间的个人习惯不互相提升;团队共享规则和跨成员协作约定单独整理到 `shared`。
|
||||
- 新的明确规则与旧规则冲突时,在相同范围内以最新明确表达为当前结论,旧内容标记为已被替代并保留来源;不同场景的差异可以同时有效。
|
||||
- 办公场景重点整理会议、行动项、流程、报告和沟通偏好;学习场景重点整理课程结构、知识点、错题、复习计划和引用;个人笔记重点整理主题、洞见、目标和习惯;开发场景保留架构、决定、故障、部署和维护。
|
||||
- 密码、Token、TOTP 和私钥不进入整理正文;整理文档只保留 Vaultwarden 条目名称和用途。
|
||||
|
||||
## 16. 数据库容量与并发决策
|
||||
|
||||
- MemRelay 继续使用 SQLite,不切换 MySQL,也不同时维护 PostgreSQL 适配;这是本次完整交付的确定架构。
|
||||
- 记忆正文由 Basic Memory Markdown 保存,文件正文位于文件仓储,源码 Git 内容位于只读工作区,记忆 Git 历史位于 Markdown 仓库,提取缓存位于独立目录;SQLite 只保存用户会话、项目/工作区、引用、任务、来源、Git 连接/仓库/同步任务、外部模型连接状态、模型调用摘要和设置,数据量与写入频率可控。
|
||||
- Basic Memory 仍有自己的本地数据库和索引边界,只把 MemRelay 元数据切换到 MySQL/PostgreSQL 并不能消除整个系统中的本地数据库,因此不为形式上的“生产数据库”增加额外服务。
|
||||
- SQLite 启用 WAL、foreign keys、合理的 `busy_timeout` 和自动 checkpoint;所有 Web/MCP 写事务保持短小。
|
||||
- 模型请求、外部模型连接探测、OCR、文件提取、Git 操作和 Basic Memory 网络调用期间不得持有 SQLite 事务;任务先提交状态,再执行外部操作,完成后用短事务写入结果。
|
||||
- 整理任务通过原子领取、租约和幂等键串行化同一工作区写入;模型调用摘要按请求追加,不为模型流式输出逐 Token 写数据库。
|
||||
- 调度器使用 SQLite 租约选出唯一活动调度者,并对“规则 ID + 计划时间”建立唯一触发键;即使运行多个 Uvicorn worker 或服务重启,同一计划时间也只能创建或合并一次任务。
|
||||
- 读取接口继续允许并发,写入遇到短暂锁竞争执行有上限的 SQLite busy retry;写操作本身不做不受控业务重试。
|
||||
- 定期清理过期会话、依赖探测明细、临时任务和可重建缓存;任务历史、文档 revision 和模型调用摘要按管理员配置保留或归档。
|
||||
- 仪表盘和健康接口暴露数据库大小、WAL 大小、checkpoint 时间、锁等待/重试次数、事务延迟和完整性检查结果,便于在真实使用中直接判断容量与并发是否健康。
|
||||
- 备份前执行 WAL checkpoint,并把 SQLite 主文件、WAL/SHM、部署主密钥和 Markdown/文件数据作为一致性整体处理。
|
||||
- MySQL 不提供该场景需要的额外价值;PostgreSQL 适用于多应用节点、高持续写 QPS 和数据库级多租户隔离,而当前单实例、共享团队和低频整理任务不具备这些必要条件。
|
||||
- 验收必须覆盖 20 个并发 Web/MCP 客户端、记忆/文件/进度写入与后台整理混合运行,连续任务期间不得出现未处理的 `database is locked`、重复领取、丢任务或损坏;同时验证异常退出、WAL 恢复和完整备份恢复。
|
||||
|
||||
## 17. 可靠性与恢复
|
||||
|
||||
- 整理任务写入 SQLite 后才进入队列,服务重启不会丢失任务。
|
||||
- 工作进程使用任务租约和心跳;超时任务可重新领取。单实例服务启动时会立即将上次进程中断的 `collecting`、`running` 或 `applying` 任务重新排队,不等待旧租约自然过期;来源游标、合并键和历史尝试记录保持不变。
|
||||
- worker 池必须动态遵循整理开关和实例最大并发。并发降低或停用整理时,不取消正在安全执行的任务,超出目标的 worker 在当前任务结束后退休;再次启用或提高并发时按槽位补充 worker,不能长期残留旧并发规模。
|
||||
- 一个整理任务需要生成多个稳定文档时,最终文档生成按每批最多 4 个目标拆分;每批模型输出上限按目标数收紧到 4,096 至 8,192 Token,避免单个超大结构化请求长期占用 worker 或反复触发上游超时,来源、revision 和应用顺序保持不变。
|
||||
- 同一个变化游标范围、目标文档、模型配置 revision 和提示词/schema 版本计算尝试幂等键,避免重复执行和重复 revision;等待任务推进最新游标后生成新的尝试键。
|
||||
- 自动任务使用稳定 `coalesce_key` 做有界背压:每个范围和整理模式最多一个等待任务;新变化只推进最新观察游标并合并有限目标提示、计数和摘要,起点保持上次成功游标。运行中任务最多拥有一个合并后继,模型恢复后一次执行即可覆盖故障期间全部变化。
|
||||
- 手动强制任务不静默丢弃;同范围已有待执行强制任务时默认拒绝,只有调用方明确选择替换才取消旧任务。已完成、失败和取消历史不参与合并并按保留策略归档。
|
||||
- 写回使用现有 optimistic revision;冲突不静默覆盖。
|
||||
- 模型输出必须通过 Pydantic schema 校验,格式错误可在同一任务中进行一次修复请求。
|
||||
- 整理结果验证通过后自动应用,不设置依赖人工批准的阻塞流程;Web 和 MCP 提供差异查看与 `curated_document_revert` 完整回滚。
|
||||
- 外部模型服务最终返回暂时不可用错误时,任务进入 `waiting_dependency`,自动整理停止领取新任务;连接恢复后按合并键继续,不丢失来源、游标或目标文档,也不按故障期间每次触发回放任务洪峰。
|
||||
- Basic Memory 超时或暂时不可用时,只把当前任务按策略中的初始/最大重试间隔做有界指数退避并重新排队;不永久失败任务,不暂停全部模型队列,也不修改外部模型依赖状态。
|
||||
- 流式请求的网络类临时故障继续使用流式重试,只有端点明确拒绝流式参数或协议时才降级为非流式;配置超时直接作为单次流式读取超时。每个模型调用每 60 秒产生一次受控等待事件,完成后保存底层请求尝试次数和端到端总耗时,服务取消时立即收尾调用记录。
|
||||
- 任务失败不影响原始记忆和当前整理文档,Web/MCP 明确显示最后成功时间和失败原因。
|
||||
- 所有变化事件携带 `origin`;只有用户、Agent 和外部来源可触发自动整理。整理写回、索引、Git 同步和扫描缓存等内部事件不得再次触发,防止无人值守递归循环。
|
||||
- Basic Memory 只挂载其所需的 `/data/basic-memory` 子目录且服务端口不直接暴露给非 MemRelay 客户端。普通写入由 MemRelay 获取范围写租约后调用 Basic Memory;Basic Memory 确认 Markdown 写入完成后,Git worker 才获取仓库锁提交。恢复和仓库策略迁移期间暂停对应范围的 Basic Memory 写入与索引,完成引用/索引重建后再解除。
|
||||
- 范围写租约和仓库锁不能持有 SQLite 事务;租约状态先短事务落库,再执行 Basic Memory 或 Git 操作。租约超时可恢复,但操作 ID 和 revision 校验必须阻止重复写入。
|
||||
- 来源正文始终视为不可信数据,不能覆盖系统指令或获得工具权限;模型请求前和 Markdown 应用前都执行秘密检测。疑似密码、Token、TOTP 或私钥时阻止写入,且错误与日志不得回显秘密值。
|
||||
- 记忆 Git 提交和 push 任务持久化后再执行;服务重启时扫描未完成任务和脏工作树,按操作 ID 补交或补推,不能重复生成逻辑提交。
|
||||
- remote 断网、认证失败或服务不可用不阻塞记忆写入;本地历史保持可用,恢复后按提交顺序补推。远程分叉不自动 force push、pull 或 merge。
|
||||
- 备份脚本继续备份整个 `/data`,必须包含记忆 Markdown、已存在的本地记忆 Git `.git/` 历史、任务、连接元数据、凭证引用和来源引用;仅 `/data/memrelay/workspaces/` 下可重新 fetch 的只读源码工作区允许从备份排除。
|
||||
- 恢复后校验 SQLite、Markdown、本地 Git 对象和索引的一致性;remote 未配置或暂时不可达时仍能完成本地恢复,联网后再补推。
|
||||
|
||||
## 18. 实施阶段
|
||||
|
||||
以下阶段只表示依赖顺序,不表示分版本交付。所有阶段、工具、文件提取器、Web 页面、调度和验收全部完成后,AI 整理功能才可标记为完成并部署正式实例。
|
||||
|
||||
### 阶段一:契约和数据
|
||||
|
||||
- 锁定通用工作区类型、场景模板、整理文档、frontmatter、结构化模型输出和 MCP/REST schema。
|
||||
- 增加 `workspace_type` 兼容迁移、整理数据表、单调变化日志/tombstone、任务状态机、成功/观察游标和分层配置模型。
|
||||
- 增加通用外部模型连接的加密配置、能力矩阵、依赖状态、模型调用摘要、配置 revision/尝试快照、上下文预算和 `waiting_dependency` 任务状态。
|
||||
- 增加 `curation_schedules`、实例/规则时区、工作区继承覆盖、recurrence 联合类型、错过执行策略和 `next_run_at` 迁移。
|
||||
- 增加 `git_connections`、`memory_repositories`、`git_sync_jobs` 迁移、状态机、幂等键及 Git 凭证的 Vaultwarden 引用/本地加密存储。
|
||||
|
||||
### 阶段二:整理引擎
|
||||
|
||||
- 实现任务领取、合并背压、运行中单一后继、恢复、重试、取消、状态和历史。
|
||||
- 实现记忆、进度快照、文件仓储、Git 和语义检索来源收集。
|
||||
- 实现 OpenAI-compatible 模型发现、手工模型名、Responses/Chat Completions 独立能力探测与适配器、SSE/非流式解析、有效协议缓存、结构化输出回退、依赖暂停/恢复、配置快照、分层预算整理、场景模板渲染、自动应用、revision 回滚和重新索引。
|
||||
- 实现带唯一调度租约的可热更新调度器、静默防抖、间隔/每日/每周/Cron 计算、IANA 时区、工作区继承、停机补跑、触发合并、内部事件过滤和服务重启恢复。
|
||||
- 落实 SQLite WAL、短事务、任务租约、busy retry、用量批量更新和异常恢复约束。
|
||||
- 把记忆、检查点、归档、删除、整理和恢复统一接入本地 Git 提交队列,保证一个逻辑操作对应一个可追溯提交。
|
||||
|
||||
### 阶段三:MCP 优先工作流
|
||||
|
||||
- 完成四个核心整理 MCP 工具、`curation_source_submit`、文档列表/回滚、任务取消/重试、记忆 Git 连接/仓库/历史/差异/恢复和配置工具。
|
||||
- 更新通用 Agent 提示词,让本机 Agent 按工作区类型持续同步本地资料、结论、进度和文档。
|
||||
- 验证开发、办公、学习、研究、个人笔记和通用工作区的新建、持续工作、新会话恢复和无人值守增量整理。
|
||||
|
||||
### 阶段四:Git、记忆版本与文件来源
|
||||
|
||||
- 实现只读源码工作区管理、凭证解析、clone/fetch、分支/commit 记录和缓存读取。
|
||||
- 实现通用 Git CLI 连接、完整 URL/URL 模板严格模式、双凭证存储、凭证临时注入、能力探测、本地记忆仓库、新工作区首次提交、push-to-create、异步 push、断网补推、分叉停止、删除归档、远程检查/导入/冷启动和受控恢复。
|
||||
- 实现文本/源码、PDF、Office、图片 OCR、压缩包提取、智能分段、缓存、限制和来源哈希。
|
||||
- 验证没有 Agent、没有 Git 以及同时具有文件仓储和 Git 的不同来源组合都能完成整理。
|
||||
|
||||
### 阶段五:Web 和调度
|
||||
|
||||
- 完成整理总览、工作区类型/模板、历史、文档、通用外部模型连接设置/健康、记忆版本管理和调度设置页面。
|
||||
- 调度页面完整支持实例时区、规则时区覆盖、三类独立开关、静默时长、可空最大延迟、分钟/小时/天间隔、每日、每周多选、五段 Cron、错过执行策略和未来执行预览。
|
||||
- 模型能力矩阵必须分别显示 Responses、Chat Completions、SSE/非流式和结构化输出;必需能力的 `unsupported/error` 标红,暂时错误显示警告,可选能力缺失显示中性状态,并提供可读原因。`/models` 不可用时允许手工输入模型,不把未选择协议或可选视觉能力缺失误判为文本整理整体故障。
|
||||
- Git 能力矩阵必须把 `unsupported` 和 `error` 标红,并显示受影响能力、可读原因、目标 URL 和重试操作;未配置 remote 时明确显示“仅本地版本历史”,不显示为故障。
|
||||
- 接入静默期、进度快照、每日工作区和每周全局触发。
|
||||
- 加入仪表盘任务状态和依赖健康。
|
||||
- 验证 AI/Git 未配置时使用中性状态,基础页面、MCP 和健康检查不降级;增强能力只有在用户明确启用后才出现相应任务和状态。
|
||||
|
||||
### 阶段六:验收与部署
|
||||
|
||||
- 完成单元、集成、MCP、Web、通用 OpenAI-compatible 连接与不可用恢复、调度/时区/停机恢复、非 Git 场景、SQLite 并发、Git CLI 能力探测、断网/分叉、服务重启和备份恢复测试。
|
||||
- 在 Windows Docker Desktop AMD64 和现有 Armbian ARM64 实机验证。
|
||||
- 更新 README、Mermaid、Agent 提示词、MCP 工具表、部署变量和第三方许可。
|
||||
- 清理临时任务与测试数据,更新项目记忆,提交独立中文 Git commit 后部署正式实例。
|
||||
|
||||
## 19. 验收标准
|
||||
|
||||
- 全新实例不配置 AI 且不启用 Git 时,不执行模型探测、不创建整理/Git 任务和 `.git` 目录;现有记忆、项目、检查点、搜索、文件仓储、密码库、Web、MCP、导出和备份行为保持可用,健康状态为正常而非降级。
|
||||
- 分别验证“仅 AI”“仅本地 Git”“Git + remote”“AI + Git”和“两者关闭”五种组合,任一未启用增强能力都不能阻塞另一能力或基础服务。
|
||||
- 有本机 Agent 时,整理任务优先使用 MCP 已同步内容,不重复扫描 Git。
|
||||
- 没有 Agent 时先使用记忆和文件仓储;配置 Git 的工作区可自动补充 Git 来源,没有 Git 的办公、学习和个人工作区仍能完整整理。
|
||||
- `curation_source_submit` 能一次同步可空 Git 状态、变更资源、结构化记忆、文档引用和进度快照,部分失败后可幂等续传且不会产生重复记录。
|
||||
- 服务重启后排队和运行中的任务可恢复,不丢失来源游标。
|
||||
- 模拟模型长期不可用并连续产生至少 10,000 次自动变化后,每个“范围或工作区 + 整理模式”仍最多只有一个等待任务,任务行大小不随事件正文线性增长;任务的起点保持上次成功游标、终点等于最新观察游标,通过变更日志查询覆盖中间全部创建、更新和删除事件。模型恢复后只运行一次且结果覆盖完整范围。
|
||||
- 变更日志只有在所有受影响成功游标越过后才允许压缩;压缩前后的增量结果一致,删除 tombstone 不会因来源正文已不存在而漏掉整理更新。
|
||||
- 任务运行期间继续产生变化时最多创建一个合并后继;前一任务成功后,后继从新的成功游标处理剩余变化,不重复或漏掉边界事件。
|
||||
- 手动强制任务遇到同范围待执行强制任务时默认返回冲突;明确 `replace` 后旧任务变为已取消且保留历史,新任务完整继承要求的来源范围。手动重复操作不能让队列无界增长。
|
||||
- 整理写回、Basic Memory 索引、Git 提交/推送和缓存扫描不会再次创建整理任务;用户、Agent 和外部来源的真实后续变化仍能正常触发。
|
||||
- 实例时区默认取部署时区,可通过 Web/MCP 改为任意受支持的 IANA 时区;规则继承和单独覆盖后的下一次执行时间、UTC 偏移与实际触发一致。
|
||||
- 静默增量可以独立启用/关闭并修改时长;启用最大延迟时持续写入最终会触发一次合并任务,关闭后变化只记录待整理状态而不自动创建增量任务。
|
||||
- 工作区兜底和全局整理分别验证每 N 分钟/小时/天、每日指定时间、每周多选星期和五段 Cron;无效数字、时间、时区和 Cron 必须拒绝保存并返回字段级错误。
|
||||
- `curation_schedule_preview`、Web 预览和调度器对未来至少 5 次执行时间的计算一致;修改规则后无需重启即可使用新的 `next_run_at`。
|
||||
- 工作区继承、覆盖和关闭只影响目标工作区;删除覆盖后恢复实例默认,不改变其他工作区或全局整理规则。
|
||||
- 服务停机跨过多个周期后,`run_once` 只合并补跑一次,`skip` 不补跑;两种策略都不回放任务洪峰。夏令时跳时和重复时刻按计划规则各验证一次。
|
||||
- 静默、周期和手动触发同时命中同一来源范围时只执行一次有效整理;无来源变化时不调用模型、不创建空 revision。
|
||||
- 增量整理只处理变化内容;无变化时不调用生成模型、不创建空 revision。
|
||||
- 来源超过单次模型上下文时能在同一任务中按配置预算分批和层级合并;任务历史准确记录每个来源处置、输入/输出用量和实际预算。未处置来源时成功游标不推进;达到任务总预算时返回稳定错误并可在调整预算后续跑,任何超限内容都不得被静默截断。
|
||||
- 模型配置在任务排队期间发生变化时,尚未领取任务使用新配置;运行中的尝试保持领取时快照。暂时故障使当前尝试结束并进入等待,恢复后的新尝试使用当前已验证配置。显式重试默认使用当前配置,明确选择仍存在的原配置时才复用原 revision,任务历史可完整复盘。
|
||||
- 整理文档正文为标准 Markdown,可通过 Web、MCP、Basic Memory 和工作区 ZIP 读取。
|
||||
- `curation_run`、`curation_status`、`curation_history`、`curated_document_get` 及全部配套工具完成真实 Streamable HTTP MCP 验收。
|
||||
- 文本/源码、PDF、扫描 PDF、DOCX、表格、PPTX、图片 OCR 和压缩包来源在 AMD64/ARM64 都能提取、分段、追溯和缓存。
|
||||
- 整理结果自动应用,历史 revision、差异和回滚完整可用。
|
||||
- 明确启用记忆 Git 但不配置 remote 时,本地历史仍能提交、查询、查看差异,并通过 MemRelay 恢复单文档和仓库快照;未启用 Git 时不产生这些操作且基础记忆行为不受影响。
|
||||
- 使用任意标准 Git remote URL 和用户输入的 HTTPS Token/账号密码或 SSH 私钥后,`git ls-remote`、fetch、临时 ref push/delete 分别给出真实能力状态;不可用项在 Web 标红,其他能力继续工作。
|
||||
- 开启写入测试时,临时 ref 使用唯一名称并在成功与失败路径尽力清理,不污染默认分支和正式历史。
|
||||
- 新建工作区在本地自动建仓并生成初始提交;测试服务支持 push-to-create 且凭证有权限时,自动完成远程建仓和首次 push;不支持时准确返回 `remote_repository_missing` 并可在用户手工建仓后重试成功。
|
||||
- remote 断网或不可达时,多次记忆变更继续形成有序本地提交并进入 `waiting_remote`;网络恢复和服务重启后自动补推且不重复、不丢提交。
|
||||
- 人为制造 remote 分叉后必须进入 `remote_diverged` 并停止自动 push,不得 force push、静默 pull 或覆盖任一侧历史。
|
||||
- 单文档恢复会生成新 revision、新索引和新 Git 提交;仓库快照恢复会校验 Markdown、重建可重建引用与索引并生成新提交,两者都不重写既有历史。
|
||||
- 完整 remote URL 只能保存为 `single`,包含 `{repo}` 的模板只能保存为 `per_workspace`;两种模式的受控迁移不会生成嵌套仓库,失败时原仓库、映射和在线记忆保持可用。
|
||||
- 未连接 Vaultwarden/Bitwarden 时,HTTPS 和 SSH Git 凭证可通过部署主密钥本地加密后完成 `ls-remote`、fetch 和 push;连接密码库后可切换为密码库条目且日志、进程参数和 Git 配置均不泄露秘密。
|
||||
- 删除 `per_workspace` 项目会先生成删除提交并把仓库移入独立归档区,普通项目删除后历史仍可查看和恢复;只有单独的管理员永久清除操作才删除归档 Git 历史。
|
||||
- 在空的恢复实例中可从 remote 冷启动,校验 Markdown 后重建 SQLite 可重建引用和 Basic Memory 索引;结果明确报告 Git 无法恢复的部署主密钥、Token、文件正文和其他范围。
|
||||
- `memory_remote_inspect/import` 能处理 `remote_diverged`:远程内容先在隔离暂存区检查,再作为新 revision 导入并形成新提交,不直接覆盖工作树或改写本地/远程历史。
|
||||
- Windows 与 Linux 对同一 Markdown 仓库往返同步时,`.gitattributes` 保持 LF 且不产生仅行尾变化的提交。
|
||||
- 相同的 Base URL、Token、模型和协议字段可以连接 OpenAI-compatible 官方平台、CLIProxyAPI、Sub2API 或其他兼容服务,服务端代码不根据平台名称分支;至少使用不同类别的真实端点或协议测试替身完成契约验收。
|
||||
- Responses-only、Chat-Completions-only 和两者都支持的端点分别通过真实调用或协议测试替身验收;三种协议模式都必须选择正确端点且生成相同内部结构化结果。
|
||||
- 显式连接测试能分别探测 Responses 与 Chat Completions,包括把通用 `400 Invalid request` 与协议不支持、业务参数错误区分记录;`auto` 从已通过的能力中优先选择 Responses。保存后的正式任务只使用 `effective_protocol`,超时、`429`、`5xx` 和连接中断不得触发跨协议重复生成。
|
||||
- Responses 和 Chat Completions 的流式 SSE、非流式响应、服务请求 ID、响应模型、Token 用量和错误映射分别验证;流中断不得应用半截文档。
|
||||
- 原生 JSON Schema 可用时优先使用;不支持时通过严格 JSON 提示词仍能得到同一 Pydantic schema,格式错误只允许一次明确修复请求。
|
||||
- `/models` 自动发现、模型搜索/选择、手工模型名和文本/视觉能力测试在 Web、REST 与 MCP 中结果一致;模型列表仅用于发现,真实可用性以端到端结构化生成测试为准。
|
||||
- 不提供 `/models` 但支持有效文本生成的端点可通过手工模型名进入 `available`;模型发现显示 `unsupported`,不得阻断整理任务。
|
||||
- 外部服务停止、网络中断、上游额度耗尽或最终返回 `429/5xx` 时,任务进入 `waiting_dependency`,新自动变化继续合并到有界等待任务;连接恢复后无需人工操作即可完成故障期间全部变化。
|
||||
- Base URL、Token 或文本模型名错误时 Web/MCP 明确显示 `configuration_error`;修正并测试成功后自动恢复等待任务,且错误页面不泄露 Token。
|
||||
- 使用具备内部多账号、模型路由和故障切换能力的外部服务时,MemRelay 能透明使用最终结果但不依赖这些扩展;直连不具备路由能力的官方端点时,基础整理、暂停和恢复仍完整可用。
|
||||
- 开发、办公、学习、研究、个人和通用工作区分别生成匹配场景的完整整理文档,不要求具备 Git 或开发术语。
|
||||
- 全局习惯能够从明确规则和跨场景重复行为中自动整理;场景和工作区习惯互不污染,并保留来源和替代关系。
|
||||
- `shared` 与成员记忆空间能通过 Web/MCP Token 正确归属来源;个人习惯不跨空间污染,团队规则仍可共享。
|
||||
- 20 个并发 Web/MCP 客户端与后台整理混合运行时 SQLite 不得出现未处理锁错误、重复任务、丢失写入或损坏,异常退出和备份恢复必须通过。
|
||||
- 使用至少两个 Uvicorn worker 同时运行调度器时,同一规则和计划时间只创建或合并一次任务;租约持有者异常退出后其他 worker 能接管且不重复触发。
|
||||
- Basic Memory 写入完成后才允许对应 Git 提交;恢复期间对相同范围的写入会等待或返回稳定忙碌错误,不会与索引重建交叉。Compose 中 Basic Memory 仅能访问自己的数据子目录,不能读写 MemRelay 数据库、文件仓储或部署主密钥。
|
||||
- 在来源文件中放入提示注入文本、测试密码、Token、TOTP 和私钥后,模型不能获得额外工具或改变系统规则,秘密值不会出现在模型请求、Markdown、Git、日志和任务错误中;被拦截内容有不含秘密值的可定位报告。
|
||||
- 模型、Git 或网络故障不会破坏现有记忆和最后成功的整理文档。
|
||||
- 正式部署可连续无人值守运行,Web 能看到最后成功、当前任务、失败原因和下一次计划时间。
|
||||
- 不发布缺少任一计划能力的中间整理版本;全部验收通过后统一交付。
|
||||
|
||||
## 20. 已锁定默认值
|
||||
|
||||
- 本计划中的全部能力属于同一次完整交付,实施阶段不是产品版本拆分。
|
||||
- AI 整理默认未配置且不启用;MemRelay 不内置或限定模型服务。用户明确配置后,实例保存一个当前启用的 OpenAI-compatible 连接,由用户自行填写 Base URL、可空加密 Token、文本模型名、可空视觉模型名和协议模式。
|
||||
- CLIProxyAPI、Sub2API、官方平台和其他兼容服务地位相同;MemRelay 不调用平台专用管理 API,也不管理端点内部的账号、优先级、权重、额度或路由。
|
||||
- Responses API 和 Chat Completions API 同时实现;协议默认 `auto` 并优先探测 Responses,也可手动固定。模型列表自动发现是可选能力,允许手工填写未公开的模型名;文本结构化生成是整理功能进入 `available` 的必要能力,视觉模型保持可选。
|
||||
- 已启用的外部模型连接默认每 5 分钟探测;未配置或关闭时不探测。暂时不可用时任务进入 `waiting_dependency` 并暂停自动领取,遵循 `Retry-After` 或 5 分钟至 1 小时退避,端到端探测成功后自动继续。
|
||||
- 实例时区默认继承部署时区并可修改;每条调度规则可继承实例时区或选择独立 IANA 时区。
|
||||
- AI 整理启用后,静默增量规则默认启用并设为 15 分钟;工作区可继承、覆盖或关闭。最大延迟默认为空,由管理员按持续写入场景配置。
|
||||
- AI 整理启用后,工作区兜底规则默认启用并设为实例时区每日 `02:30`;全局习惯和跨工作区经验整理规则默认启用并设为实例时区每周日 `03:30`。
|
||||
- 周期规则同时支持每 N 分钟/小时/天、每日、每周多选和高级五段 Cron;错过执行默认合并补跑一次,可改为跳过。
|
||||
- Agent 来源默认新鲜度为 24 小时;来源不完整、超过 24 小时或用户强制全量时读取文件仓储,配置 Git 的工作区同时启用 Git 兜底。
|
||||
- 工作区类型固定支持 `development`、`office`、`study`、`research`、`personal`、`general` 和自定义模板;现有有 Git 项目迁移为开发类型,其余迁移为通用类型。
|
||||
- 默认创建 `shared` 记忆空间;未绑定 MCP Token 和未选择空间的 Web 会话都归属 `shared`,成员空间不改变现有权限模型。
|
||||
- 源码 Git 分支按项目配置、远端默认分支、`main`、`master` 的顺序解析;`/data/memrelay/workspaces/` 下的源码工作区永久保持来源只读,不创建提交或推送。
|
||||
- 记忆 Git 默认关闭;用户明确启用后建立本地历史,remote 仍可选并按用户提供的完整 URL 或 `{repo}` 模板连接,不内置 Git 服务、不限定平台、不调用平台专用 API。
|
||||
- 记忆 Git 和 remote 都已启用时,默认允许新工作区通过首次 push 尝试 push-to-create;成功时自动完成远程建仓与同步,不支持时标红并等待用户自行创建空仓库。
|
||||
- HTTPS Token/账号密码和 SSH 私钥都从 Git 设置页面接收;已连接 Vaultwarden/Bitwarden 时默认保存为密码库条目,否则使用部署主密钥本地加密。Git CLI 运行时临时注入,配置和日志只保留非秘密引用。
|
||||
- 记忆 remote 只接受 MemRelay 单向普通 push,禁止自动 force push 和自动 pull/merge;断网时保留本地提交并自动补推。
|
||||
- `curation_source_submit` 与四个核心整理工具及全部配套工具同时交付。
|
||||
- 文本、源码、PDF、扫描件、DOCX、电子表格、PPTX、图片 OCR 和压缩包提取全部纳入交付及双架构验收。
|
||||
- 整理结果验证后自动应用;所有修改都生成 revision,并支持 Web/MCP 差异查看和回滚。
|
||||
- MemRelay 只记录任务级连接名称、请求/响应模型、服务请求 ID、标准响应提供的 Token 用量、耗时和结果;额度、费用、账号健康及详细用量由外部模型服务负责。
|
||||
- MemRelay 数据库继续使用 SQLite WAL,不引入 MySQL/PostgreSQL;所有外部 AI、Git、OCR、文件和 Basic Memory 操作不得占用数据库事务。
|
||||
- 同一工作区最大整理并发默认为 1,全局任务最大并发默认为 1,失败默认重试 3 次并指数退避;均可配置。
|
||||
- AI 整理启用后,自动队列默认使用按范围和模式合并的有界背压,运行中任务最多一个自动后继;手动强制任务默认拒绝同范围重复排队,只有显式替换才能取代旧任务。
|
||||
- 模型输入/输出预算、每任务最大调用轮数/总 Token 预算、分批大小和合并层级可配置;默认值由所选模型配置提供的上下文能力与 MemRelay 保守上限共同决定,未知上下文能力时使用保守上限。预算耗尽不推进成功游标,调整后可继续同一来源范围。
|
||||
|
||||
## 21. 实施与验收结果
|
||||
|
||||
- 完成工作区类型、来源策略、MCP 优先/Git 兜底、来源墓碑、稳定 `source_key`、结构化输出 schema v2、冲突/替代关系、场景偏好和 revision 元数据。
|
||||
- 完成 Responses 与 Chat Completions、流式/非流式、原生 JSON Schema、能力探测、错误分类、依赖等待、自动恢复、有界合并队列、并发租约、调度继承和可配置来源限制。
|
||||
- 完成默认关闭的记忆 Git、本地历史、可选 remote、模式迁移、断网补推、分叉检测、push-to-create、历史/差异/恢复、远程导入与冷启动。
|
||||
- 完成 REST、95 个 MCP 工具、3 个 MCP Resources、中文/英文桌面 Web、动态 Agent 提示词、备份恢复和部署文档。
|
||||
- 真实 Responses 已覆盖非流式、SSE、JSON Schema、全局整理、项目连续增量、历史、差异、回滚和暂时断网恢复;永久模型输出错误进入 `failed`,只有可恢复依赖错误进入 `waiting_dependency`。
|
||||
- 生产长任务已覆盖流式远端断线后的请求内恢复和 Basic Memory 并发超时;正式全局与两个项目范围的最新重试均完成。自动测试覆盖动态并发缩减、任务级本地依赖退避、长调用进度、端到端耗时、请求尝试次数和取消收尾;ARM64 正式发布后运行时 worker 为 `1 / 1`,队列和运行中调用为 0。受控停止 Basic Memory 后,重试任务按预期以本地依赖错误重新排队且不改变模型依赖状态,取消测试任务并恢复依赖后 LAN/公网服务均正常。
|
||||
- Windows Docker Desktop AMD64、物理 Armbian ARM64、Alembic `0001 -> 0009`、SQLite 并发、正式数据迁移、公网 HTTPS/MCP 和重启自动恢复全部通过。
|
||||
- 零配置基础模式已在正式实例验证:AI/Git 均未配置时不探测、不排队、不 Clone、不创建 `.git`,原有记忆、项目、搜索、密码库、文件、Web、REST 和 MCP 保持完整可用。
|
||||
@@ -0,0 +1,40 @@
|
||||
# MemRelay 对话交接入口
|
||||
|
||||
> 定位:跨聊天窗口、跨 AI 客户端的**稳定入口文档**,只记录很少变化的事实、路径与硬约束。
|
||||
>
|
||||
> 维护规则:仅当部署拓扑、安全边界或上下文获取路径变化时更新本文。功能迭代、模型选型、任务状态、近期讨论等易变信息一律不写在这里——它们的正确归宿见"上下文获取路径"。
|
||||
|
||||
## 项目定位
|
||||
|
||||
MemRelay 是自托管的 AI 记忆、开发历史、密码库接入和文件仓储服务:让 Codex、Cursor、Claude Code 等客户端跨设备、跨项目、跨窗口恢复上下文,持续沉淀规则、偏好、事实、决定、经验、凭证与秒级检查点。AI 整理与记忆 Git 为可选增强、默认关闭;零配置基础模式是正式支持的完整运行方式。
|
||||
|
||||
## 部署拓扑(稳定事实)
|
||||
|
||||
- 正式实例:`https://mr.asio.asia`;ARM 板 `192.168.32.100`(Armbian,SSH root),Compose 位于 `/opt/1panel/docker/compose/memrelay`,数据 `/data/memrelay-stack`,宿主端口 `3003`。
|
||||
- Sub2API 模型网关:同一块板,宿主端口 `3004`(板内/内网直连 `http://192.168.32.100:3004/v1`),公网 `https://sub2.asio.asia`。同板服务间调用走内网地址,不绕公网。
|
||||
- 本机 Windows 不再部署 Docker 实例;开发目录 `E:\NIXProject\MemRelay`。
|
||||
- 技术栈:后端 Python 3.12 + FastAPI + FastMCP + SQLAlchemy/SQLite + uv;前端 Vue 3 + Vite + Element Plus + pnpm;记忆引擎 Basic Memory v0.22.1(`third_party/` 子模块,独立容器经 MCP HTTP 调用)。
|
||||
- OpenResty 只缓存带哈希的 `/assets/`;API、MCP、认证、签名地址不进代理缓存。
|
||||
|
||||
## 上下文获取路径(新窗口按序执行)
|
||||
|
||||
1. 读本文。
|
||||
2. 读 `aidocs/project_context.md`——本机项目记忆时间线,最新条目在最上,是最完整的演进记录(gitignore,本机专属)。
|
||||
3. 读 `docs/implementation-plan.md` 顶部数节——最近迭代的契约、诊断与验收结果。
|
||||
4. 需要正式记忆、检查点、密码库或文件时,走 MemRelay 本体:Web `https://mr.asio.asia` 或 Streamable HTTP MCP(Token 在 Web「MCP Token」页创建,用完可撤销)。模型选型、生产经验等长期结论保存在 MemRelay 全局记忆中,以那里为准。
|
||||
5. 不假设本地 git 与生产一致:核对 `git log` 与生产容器状态后再动手。
|
||||
|
||||
## 安全与工程边界(硬约束)
|
||||
|
||||
- 秘密值不进仓库、记忆正文、日志或交接文档;聊天中出现过的测试密钥用后立即撤销轮换。
|
||||
- 发布纪律:完整门禁(后端 Ruff + pytest、前端 Vitest/ESLint/Prettier/构建)→ 停机备份(`MEMRELAY_DATA_PATH=/data/memrelay-stack sh scripts/backup.sh`)→ 只重建 `memrelay` 服务 → 保留回滚镜像标签 → 验证内外网 readiness。
|
||||
- 含中文的文件禁止用 PowerShell `Get-Content`/`Set-Content` 修改——ANSI 误读会把 UTF-8 写成"合法编码的乱码",常规校验发现不了;只用编辑工具或显式 UTF-8 编解码的 Python 脚本,改完做关键中文串的内容断言。
|
||||
- 长 SSH 组合命令拆分执行;生产只读诊断用脚本管道 `docker exec -i memrelay-memrelay-1 python -`(脚本含中文时先 scp 再远端重定向,避免 PowerShell 管道污染)。
|
||||
- Web、REST、MCP 共用服务层,改一处三端生效;提交信息格式 `<type>: <中文描述>`。
|
||||
- 模型只通过"提案 + 服务端校验"影响记忆,永远不给模型直接增删改查记忆文件的能力。
|
||||
|
||||
## 常用验证(稳定)
|
||||
|
||||
- 就绪:`curl http://192.168.32.100:3003/api/v1/health/ready`、`curl https://mr.asio.asia/api/v1/health/ready`
|
||||
- 容器:`docker ps --format '{{.Names}} {{.Status}}' | grep mem`(应两个 healthy)
|
||||
- 数据库:容器内 `PRAGMA quick_check` 应为 ok;迁移版本查 `alembic_version` 表
|
||||
@@ -0,0 +1,434 @@
|
||||
# MemRelay 完整实施计划
|
||||
|
||||
## 2026-08-19 Git 来源增量收集与无变化任务短路(已实施)
|
||||
|
||||
背景:`_collect_git` 每次对仓库 HEAD 全量 `ls-tree` 提取全部文件,与游标增量(memory/file)不对称;Git-only 项目(无 agent 活动,`auto` 策略每次兜底收集 git)即使一个字未改,每次任务也全仓重提取、重压缩、重写全部文档(实测 274 文件 → 40 次调用、约 115 万 Token)。定时任务每日空转消耗。
|
||||
|
||||
契约:
|
||||
|
||||
1. `_collect_git` 接受 `base_commit`(上次成功整理写入 CurationSource 的 git 来源 revision):与当前 HEAD 相同 → 零收集(`git_coverage.mode=unchanged`);不同 → `git diff --name-status` 只提取变更文件并为删除文件生成 SOURCE_REMOVED 声明(`mode=diff`);基线不可用(首次、浅克隆丢失)→ 回退全量(`mode=full`)。full 模式任务不传基线,始终全量。
|
||||
2. 任务级短路:可用来源只剩 `curated_baseline`/全局指导(无任何主来源)且现有文档的 prompt_version 均为当前版本时,任务记录 `no_primary_changes` 事件并零调用完成(stats 带 `skip_reason`);提示词版本升级时放行重建。
|
||||
3. 未变文件的信息由 curated_baseline 文档承载,与既有"基线 + 新证据重写"语义一致;diff 空集不再误标 GIT_SOURCE_EMPTY。
|
||||
4. 验收:`_collect_git` 全量/unchanged/diff(含删除声明)/无效基线回退四态回归;端到端"第二次无变化任务零调用短路"回归;完整后端套件 + 前端门禁通过后发布 ARM,生产实测同一项目从"40 次调用/115 万 Token"降为"零调用完成"。
|
||||
|
||||
## 2026-08-19 调用预算自适应工作量(已实施)
|
||||
|
||||
背景:BDYG18Pro 积压 293 个来源产生 27 个证据批次,任务约需 43 次模型调用,配置上限 `task_max_calls=30` 使每天 18:30 定时任务连续 7 天在第 31 次调用(合并 4/7)处失败,每次白烧 31 次调用;失败导致增量游标不推进、积压继续膨胀,形成每日必败循环。
|
||||
|
||||
契约:
|
||||
|
||||
1. 批次准备完成后按工作量估算所需调用上界:证据每批 1 次(单批不计)+ 合并树每层 ceil(n/4) 收敛至单份 + 文档每 4 份 1 批 × 2(含 repair 预留)。
|
||||
2. 估算超过配置上限时,本任务内自动放宽调用上限至估算值,并记录 `budget_calls_auto_raised` 事件(configured/required)供审计;Token 预算保持硬顶不放宽,真实成本仍受控。
|
||||
3. `CURATION_BUDGET_EXCEEDED` 错误信息附带用量与上限明细(调用 X/Y,Token A/B)。
|
||||
4. 验收:估算函数数学回归(27 批 10 文档=43)、调用上限 1 + 五文档两批的端到端放宽回归(事件唯一、任务完成)、Token 硬顶既有回归不变;完整后端套件 + 前端门禁通过后发布 ARM,生产实测放宽事件触发且任务越过 30 次调用关口。
|
||||
|
||||
## 2026-08-13 时间字段统一 UTC-aware 序列化(已实施)
|
||||
|
||||
背景:SQLite 存储 datetime 丢弃时区,ORM 读回 naive UTC,isoformat 序列化不带偏移,Web 前端与 MCP 客户端把它误当本地时间,全站时间显示偏差 8 小时;散落各服务的 `_ensure_utc` 补丁未覆盖序列化路径。该偏差还让静默期去抖中的整理任务(next_retry_at 为未来时刻)看起来像"卡死数小时不执行"。
|
||||
|
||||
契约:
|
||||
|
||||
1. `models.UTCDateTime`(TypeDecorator)在读取时为 naive 值补回 UTC tzinfo;全部模型时间列使用该类型,存储格式不变、无需迁移。
|
||||
2. REST(FastAPI)输出 `+00:00` 偏移、MCP(pydantic)输出 `Z` 后缀;前端 `new Date().toLocaleString()` 自动转本地时区,前端零改动。
|
||||
3. 任务调度语义不变:source_change 任务的 `next_retry_at` 仍是静默期去抖到期时刻,"计划执行"列语义正确。
|
||||
4. 验收:REST 往返断言时间带 UTC 偏移;修正依赖"读回 naive"旧行为的存量断言;完整后端套件通过后发布 ARM,容器内 ORM 读回 aware、公网 MCP 时间带 `Z` 实测确认。
|
||||
|
||||
## 2026-08-13 MCP GET /mcp 返回 405 兼容新版客户端(已实施)
|
||||
|
||||
背景:无状态 Streamable HTTP 下 fastmcp 只注册 POST/DELETE,GET /mcp 落入 SPA 兜底返回 404;新版 Cursor 在 initialize 后主动 GET 打开服务端通知 SSE 流,把 404 视为会话失效,连续重试后墓碑化整个连接导致 MCP 不可用。
|
||||
|
||||
契约:
|
||||
|
||||
1. `/mcp` 显式注册 GET(含自动 HEAD)返回 405 + `Allow: POST, DELETE`,符合 MCP Streamable HTTP 规范"不支持服务端主动 SSE 流必须回 405";客户端(官方 TS SDK 及 Cursor)对 405 静默容忍。
|
||||
2. 该处理不做鉴权(405 优先于 401,无信息泄露);POST/DELETE 行为不变。
|
||||
3. 验收:回归覆盖 GET /mcp 为 405 且带 Allow 头;完整后端套件通过后发布 ARM,内外网实测 405/200。
|
||||
|
||||
## 2026-08-12 操作列收纳与生命周期筛选默认全部(已实施)
|
||||
|
||||
背景:全局记忆操作列在 132px 内排 3 个图标按钮导致换行错乱;用户希望各生命周期筛选组默认即显示"全部"。
|
||||
|
||||
契约:
|
||||
|
||||
1. 全局记忆操作列改为"编辑直达 + 更多下拉":标记待整理/移入回收站/永久删除收入 `el-dropdown`,永久删除以危险色标识(下拉挂载于 body,样式入全局 styles.css),列宽收窄为 104px 单行。新增 `common.moreActions` 文案。
|
||||
2. 生命周期筛选默认值统一为 `all`:全局记忆、项目记忆(原 `pending`)、搜索页(原 `current`);项目记忆"全部"视图混入检查点与回收站记录,与手动选择"全部"语义一致。历史契约中"默认显示待整理内容"自本节起由本契约取代。
|
||||
3. 验收:Vitest 覆盖搜索默认 `lifecycle=all` 请求;ESLint、Prettier、vue-tsc 构建通过;发布 ARM 后确认站点提供新构建资源。
|
||||
|
||||
## 2026-08-12 整理输出语言设置(已实施)
|
||||
|
||||
背景:文档生成提示词未指定输出语言,整理文档语言隐式跟随来源主导语言,混合语言来源下可能漂移甚至 revision 间不一致;英文习惯的使用者需要确定性保证。
|
||||
|
||||
契约:
|
||||
|
||||
1. `CurationSettings` 新增实例级 `output_language`:`auto`(默认,跟随来源主导语言且单份文档内保持一致)、`zh-CN`、`en-US`;迁移 `20260812_0015` 为存量行回填 `auto`。不做工作区级覆盖(auto 已天然按项目来源自适应)。
|
||||
2. 文档生成提示词按设置注入确定性语言指令;显式语言时无论来源语言一律按目标语言书写标题与正文。`PROMPT_VERSION` 升级触发下轮全量重生成。
|
||||
3. REST/MCP 设置读写自动携带该字段;Web 整理设置页新增下拉(自动/中文/English)。
|
||||
4. 验收:提示词三种模式的指令注入回归、设置读写回归;完整门禁后发布 ARM。
|
||||
|
||||
## 2026-08-12 提示词页多场景形态(已实施)
|
||||
|
||||
背景:提示词页目前只展示一段通用工作流,用户需要自行摸索"规则文件放哪、如何让 AI 遵守、已有项目如何迁移到 MemRelay 记忆"。
|
||||
|
||||
契约:
|
||||
|
||||
1. 提示词页改为三个场景:`通用工作流`(现状保留)、`新项目接入`、`已有项目迁移`;语言切换对全部场景生效。
|
||||
2. 新项目接入:提供各客户端规则文件位置表(Cursor:项目根 `AGENTS.md` 或 `.cursor/rules/*.mdc`;Codex CLI:项目根 `AGENTS.md`,全局 `~/.codex/AGENTS.md`;Claude Code:项目根 `CLAUDE.md`,全局 `~/.claude/CLAUDE.md`;VS Code Copilot:`.github/copilot-instructions.md`;其他客户端:项目根 `AGENTS.md` 事实标准),每行附路径复制按钮;三步流程文案——创建规则文件并粘贴工作流提示词(复制按钮)、说明客户端会自动注入每次会话、新会话验证 AI 已解析 MemRelay 项目。
|
||||
3. 已有项目迁移:后端新增 `build_migration_prompt`(中英文,随密码库/AI 整理启用状态裁剪),指导 AI 完成——解析或创建项目 → 通读 README/docs/脚本/既有 AI 规则文件 → 按 rule/fact/decision/experience 分类精炼写入(凭证只入密码库、记忆只存条目名)→ 建立迁移基线检查点 → 搜索与上下文抽查校验 → 转入标准工作流;明确只迁移确定的长期知识、原文档保留。`/api/v1/system/prompt` 增加 `variant` 参数(workflow/migration)。
|
||||
4. 验收:后端覆盖 variant 参数与迁移提示词中英文关键内容、功能开关裁剪;前端覆盖场景切换、位置表渲染与迁移变体请求;完整门禁后发布 ARM。
|
||||
|
||||
## 2026-08-12 模型分配的双模式交互重做(已实施)
|
||||
|
||||
背景:模型页的"候选模型链"编辑器(自由列表 + 任务类别多选 + 顺序语义)对人不直观;用户期望配置完连接后,模型选择支持两种心智模型:全部任务统一使用一个模型(区分文本与视觉),或按任务类型分别指定。
|
||||
|
||||
契约:
|
||||
|
||||
1. 连接表单保留"文本模型 + 视觉模型"两个字段不变;其下新增"模型分配"分段开关:`统一模型` 与 `按任务分配`。
|
||||
2. 统一模型:不显示任何链配置,保存时提交空候选链(后端链自动回落文本模型);提示文案说明所有任务用文本模型、涉图内容用视觉模型。
|
||||
3. 按任务分配:三个带标签的单选下拉——全局整理、开发项目、高频增量,均可留空表示"跟随文本模型";一个"通用兜底"有序多选(任一模型失败冷却后按顺序尝试);一个冷却秒数输入。视觉模型保持连接级单字段,不按任务拆分。
|
||||
4. 保存映射:任务专属模型各生成一条对应类别候选,文本模型生成一条通配候选,兜底列表按顺序生成通配候选;该结构与既有后端候选链语义完全兼容,无后端改动。加载时按同样结构反解;无法精确表示的历史高级链(同类别多候选、default 标签等)折叠为"任务槽 + 兜底",提示文案说明保存将按简化结构重写。
|
||||
5. 候选健康(冷却中标签、最近错误)继续展示在对应的任务槽上。
|
||||
6. 验收:Vitest 覆盖两种模式的保存载荷映射与历史链反解;ESLint、Prettier、TypeScript/Vite 构建通过;发布 ARM 后浏览器确认两种模式交互与现有生产配置的正确回显。
|
||||
|
||||
## 2026-08-09 模型连接测试的可见性与抗中断改造(已实施)
|
||||
|
||||
背景:保存/测试模型连接会同步执行完整能力探测(模型列表、双协议文本生成、结构化输出、流式、视觉),受超时与重试影响可达数分钟。现状按钮无加载状态、过程无反馈、结果仅一次性 toast,用户离开页面即错过结果;HTTP 请求被反向代理超时或客户端断开时探测协程可能被取消,依赖状态停留在 `checking`(生产已出现,靠探测循环 5 分钟后自愈)。
|
||||
|
||||
契约:
|
||||
|
||||
1. 探测单飞与抗中断:`CurationManager` 持有单个探测任务,保存/测试/自动探测统一入口;测试与自动探测复用运行中的任务,保存新配置则取消旧任务后重启。请求侧以 `asyncio.shield` 等待,客户端断开或代理超时不再取消探测,依赖状态必定被写入终态。
|
||||
2. 启动自愈:服务启动时若依赖状态遗留 `checking`,将 `next_probe_at` 置为当前时间,由探测循环在 30 秒内重新探测,不再依赖旧的探测计划时间。
|
||||
3. `model_status` 增加 `probe` 字段(running、started_at、trigger),Web 轮询可见探测进行中状态。
|
||||
4. Web 模型页:保存与测试按钮增加加载状态;探测进行中显示驻留面板——本次将依次验证的项目清单(模型列表、Responses/Chat Completions 文本生成、结构化输出、流式输出、视觉模型)、已耗时秒数、"可离开页面,结果会保留"提示,期间每 2 秒轮询模型状态;完成后面板转为驻留的结果横幅(成功/失败 + 错误码文案 + 检查时间),不再依赖一次性 toast。测试按钮旁增加帮助图标说明测试内容。
|
||||
5. 探测语义不变:仍使用连接配置的协议、流式与超时设置端到端验证;不改动模型网关。
|
||||
6. 验收:后端覆盖探测单飞复用、保存替换旧探测、请求取消后状态仍到终态、启动 `checking` 自愈;前端覆盖加载状态、探测面板轮询与结果驻留;完整门禁后发布 ARM。
|
||||
|
||||
## 2026-08-08 输出截断显式检测与预算默认值提升(已实施)
|
||||
|
||||
背景:生产首个全局 full 整理失败于 `MODEL_OUTPUT_INVALID`。三批文档(4+4+2)的最后一批被旧公式 `max(4096, 2048*n)` 压到 4096 输出上限,推理模型的思考 Token 计入输出导致 JSON 截断,repair 调用同上限再次截断后任务失败;实例配置的 80000 输出上限对小批次不生效,属代码缺陷。已先行以 `62fa810` 将下限提高到 `max(8192, 4096*n)` 并发布。标准 OpenAI 兼容协议无法可靠读取模型最大输出值(`/v1/models` 不含该字段),因此不做"自动读取模型上限",改用协议内的确定性截断信号。
|
||||
|
||||
契约:
|
||||
|
||||
1. 网关显式检测输出截断:Chat Completions `finish_reason=length`,或 Responses `status=incomplete` 且 `incomplete_details.reason=max_output_tokens`,抛出确定性 `MODEL_OUTPUT_TRUNCATED`(非 transient),不再把截断文本交给 JSON 解析产生误导性的 `MODEL_OUTPUT_INVALID`;配置候选链时按既有语义顺延下一候选。
|
||||
2. Responses 流式 `response.incomplete` 是正常终止事件:计入流完成标记并作为终态响应参与截断判定,不再被误判为 `MODEL_STREAM_INCOMPLETE` 而按临时故障重试;Chat 流式装配保留 `finish_reason`。
|
||||
3. 能力探测使用 16/32 Token 微预算,推理模型可能带 length 标记仍返回可用文本;全部探测调用豁免截断检测(`fail_on_truncation=False`),不因该标记把依赖判成配置错误。
|
||||
4. 文档生成输出预算下限提升为 `max(32768, 4096*文档数)`;实例默认 `context_output_tokens` 从 8000 提升为 32000(SQLAlchemy 客户端默认,仅影响新实例,存量配置值不变)。
|
||||
5. 暂不实施、观察真实运行后再定:截断后自动折半文档批次重试;对"max_tokens 过大"的 400 自适应钳制并按模型记忆实际上限(可存 `curation_model_candidate_states`);机会式读取 `/models` 非标上限字段。
|
||||
6. 验收:网关回归覆盖非流式/流式截断、探测豁免与 `finish_reason` 装配;预算与批次断言更新;完整后端门禁通过后发布 ARM。
|
||||
|
||||
## 2026-08-08 整理覆盖状态与统计修复(已实施)
|
||||
|
||||
生产诊断(192.168.32.100 实例,2026-08-08):26 条活动记忆中 22 条待整理(含 7 条检查点),30 份活动整理文档存在且内容正常。确认以下原因,前两条为实现缺陷:
|
||||
|
||||
1. `_apply_documents` 写新 revision 时,文档元数据的 `cited_source_ids` 与 `source_revisions` 只包含本次运行的引用与来源;随后 `rebuild_memory_curation_states` 按“当前活动文档元数据”全量重建生命周期,上一轮已覆盖但本轮未再次引用的记忆整体翻回待整理。生产证据:任务 `ed8aa16d`(18:42)将约 10 条记忆置为已整理,任务 `ce73902c`(23:50)写入 revision 6(每份文档仅引用 1 条新来源)后这些记忆全部回到待整理。
|
||||
2. 增量任务只收集变化来源,`source_revisions` 缺少未变化旧来源的 key;即使模型再次引用旧来源,revision 匹配也会失败。
|
||||
3. 检查点计入待整理统计,但整理文档几乎不会逐条引用检查点,统计长期虚高。
|
||||
4. 附带缺陷:`rebuild_memory_curation_states` 赋回原 `updated_at` 时值未变化、不进入 UPDATE 集合,`onupdate=utcnow` 仍触发,生命周期翻转会污染记忆的 `updated_at`。
|
||||
|
||||
修复契约(已按以下最终形态实现):
|
||||
|
||||
1. 覆盖元数据跨 revision 累计:`_apply_documents` 写新 revision 时继承活动文档现有 `cited_source_ids`、`source_revisions` 与 `supersedes` 并与本次合并(`_merge_document_coverage`);已删除记忆对应的历史引用在合并时剔除。本次重新引用的来源把 `source_revisions` 更新到新 revision;未再次引用的旧来源保留原 revision,因此被引用记忆再次编辑(revision 变化)仍自动回到待整理,现有 revision 匹配逻辑不变。元数据新增 `job_cited_source_ids` 记录本次任务实际引用,便于追溯;累计规模受范围内记忆数量约束,不会无界增长。
|
||||
2. 模型对本批次每个来源声明处置:`cited`、`redundant`、`no_action`(文档生成调用的 JSON Schema 新增顶层 `source_dispositions`,Prompt/修复 Prompt 同步说明;PROMPT_VERSION=2026-08-08.1、SCHEMA_VERSION=3)。处置为宽松解析:未知来源 ID 或非法值直接忽略,模型输出缺少该字段时保持现状语义,不阻断任务。实现偏差(等价且更可靠):`redundant`/`no_action` 不写入文档元数据,而是作为持久审阅标记落在 `MemoryReference.reviewed_revision`/`reviewed_job_id` 列——审阅可能不伴随任何文档变化,文档元数据无法承载;重建时 `reviewed_revision == revision` 且未被引用/替代的记忆计为已整理,`covered_reason` 区分 `cited` 与 `reviewed`。来源在收集后被再次编辑(revision 不匹配)时跳过标记,保持待整理。
|
||||
3. 检查点与“待整理”统计分离:仪表盘 `memory_lifecycle`、AI 整理状态与 rebuild 统计不再把 `checkpoint` 计入 pending/covered/superseded,检查点单独计数(rebuild 返回 `checkpoints`);记忆生命周期筛选新增 `checkpoint` 值,Web 记忆页与项目页提供该筛选;`memory_search` 的 `current` 语义保留检查点可搜索。检查点作为整理来源的行为不变。
|
||||
4. 修复 rebuild 的 `updated_at` 保留:`_preserve_updated_at` 用 `flag_modified` 强制把原值纳入 UPDATE 集合,杜绝 `onupdate` 覆盖(与 Core update 等价、改动更小)。`reset_memory_curation` 同步修复并清除审阅标记。
|
||||
5. 迁移 `20260808_0014`:`memory_references` 新增可空 `covered_reason`、`reviewed_revision`、`reviewed_job_id` 列,存量 `covered` 记忆回填 `covered_reason='cited'`。历史活动文档元数据为旧格式,已丢失的跨轮覆盖关系无法凭空恢复;发布后由用户手动触发整理,以新累计语义重建覆盖。
|
||||
6. 验收:回归覆盖“第二轮重写不翻回已覆盖来源 + 处置声明落库 + revision 变化后审阅失效”(`test_document_rewrite_keeps_previous_citations_and_review_marks_cover_sources`)、“检查点统计分离与筛选”(`test_checkpoints_have_their_own_lifecycle_bucket`)、“updated_at 保留”(同前者断言);生产发布后由用户手动执行整理复测收敛。
|
||||
|
||||
## 2026-08-08 AI 整理模型退避链与场景路由(已实施)
|
||||
|
||||
背景:当前 `CurationModelConfig` 为单连接单文本模型,模型不可用时任务进入 `waiting_dependency` 等待探测恢复。外部网关(如 Sub2API)能在同一模型的多个账号之间切换,但不做跨模型降级;跨模型退避由 MemRelay 自身实现。
|
||||
|
||||
契约(已按以下最终形态实现):
|
||||
|
||||
1. 保持单连接(一个 Base URL、Token、协议),`CurationModelConfig` 新增 `candidates_json`(有序候选:模型名、任务类别、启用开关)与 `candidate_cooldown_seconds`(默认 600 秒)。不引入多连接或多 Base URL;候选链为空时回落 `text_model` 单模型链,向后兼容。视觉模型维持单独字段不变。
|
||||
2. 任务类别与链(实现为集合匹配,与优先级方案等价且更简单):每个任务派生类别集合 `_job_task_classes`——恒含 `default`,`scope=global` 加 `global`,`trigger=source_change` 加 `incremental`,项目 `workspace_type=development` 加 `development`。候选按声明顺序参与匹配:类别为空的候选匹配全部任务,否则要求与任务类别集合有交集;因任务恒含 `default`,标记 `default` 的候选天然充当所有链的兜底。任务内选择粘性:候选一旦成功即服务同一任务后续全部调用,保证证据/合并/文档批次的一致性。
|
||||
3. 退避语义:单次请求保持现有最多 3 次有界重试(`OpenAICompatibleClient` 不变);候选调用抛出任何 `ModelGatewayError` 时把该候选置入共享冷却(`CurationModelCandidateState.cooling_until`),同一任务内顺延到链上下一候选并记录切换事件;`MODEL_AUTH_FAILED` 属连接级错误,不触发切换。整链耗尽或全部冷却时抛出 `MODEL_CANDIDATES_EXHAUSTED`(transient,`retry_after` 取最近冷却剩余时间),任务进入 `waiting_dependency`。
|
||||
4. 候选健康是运行时状态,存储于独立表 `curation_model_candidate_states`(按模型名主键),不进配置 revision 快照、不被配置保存重置;配置 revision 快照包含完整候选链,失败任务重试按现有语义使用当前配置,或 `use_original_config` 复用原链。
|
||||
5. 探测按需进行:不做全候选周期轮询;连接保存时仍只端到端验证 `text_model`。候选可用性由真实任务调用驱动(成功清除冷却、失败进入冷却),冷却到期后自动重新参与选择。
|
||||
6. 可观测性:`ModelCall.requested_model` 记录每次实际请求的候选模型(每个候选尝试一条记录);执行输出新增 `model_candidate_switched` 事件(原候选、错误码、新候选),不含 Prompt 与秘密值;任务 usage 记录 `model_used`,文档元数据与来源指纹使用实际产出模型。
|
||||
7. REST/MCP:`ModelConnectionSaveRequest` 新增 `candidates`(模型名去重校验)与 `candidate_cooldown_seconds`;`model_status` 的 connection 返回候选链及每候选健康(冷却状态、最近错误、最近成功/失败时间);MCP `curation_model_connection_save` 同步扩展参数。Web 模型页提供链编辑(增删、类别多选、启用开关)与健康标签展示。
|
||||
8. 验收:单元覆盖类别路由(`test_job_task_classes_follow_scope_trigger_and_workspace`)、冷却/跨任务共享/整链耗尽(`test_candidate_chain_routes_falls_back_and_cools_failed_models`)、任务内退避与调用记录/切换事件(`test_call_model_switches_candidates_and_records_each_attempt`);真实网关跨模型退避留待生产观察(用户手动触发整理验收)。未配置 AI 的零配置模式行为不变。
|
||||
|
||||
交付顺序:先交付“整理覆盖状态与统计修复”(生产可见的正确性问题),再交付“模型退避链与场景路由”。两份方案已在同一提交中实现并通过完整前后端门禁;发布到 ARM 生产实例后不自动触发整理任务,由用户手动执行一次整理观察新逻辑(冗余文档处置、未整理残留收敛)作为最终验收。
|
||||
|
||||
## 2026-08-07 AI 整理长请求断线修复
|
||||
|
||||
- 生产任务在来源收集和批次准备完成后,长时间非流式 Responses 请求间歇出现 `Server disconnected without sending a response.`;短模型探测仍可成功,因此该问题属于长请求传输稳定性,而不是 SQLite、Basic Memory 或文档写回故障。
|
||||
- `httpx.RemoteProtocolError` 属于 `TransportError` 而不是 `NetworkError`。模型网关必须统一捕获全部 `httpx.TransportError`,映射为可恢复的 `MODEL_UNAVAILABLE`,让任务进入 `waiting_dependency`、按有界退避等待探测恢复,而不是被最外层误标记为永久 `CURATION_FAILED`。
|
||||
- 模型调用记录必须在所有异常路径结束;已知模型异常保存稳定错误码,未知异常保存 `MODEL_CALL_FAILED` 后继续向上抛出。服务启动时将上个进程遗留的 `running` 模型调用标记为 `MODEL_CALL_INTERRUPTED`,避免 Web/MCP 长期显示不存在的运行中调用。
|
||||
- 回归测试覆盖模型列表与生成请求的远端协议断线、请求内重试、整理任务进入依赖等待、未知调用异常收尾和启动清理遗留调用。完整后端门禁通过后才允许发布。
|
||||
- 正式实例发布前创建一致性备份,只原生重建 ARM64 `memrelay` 服务;模型连接启用已验证可用的流式 Responses,使用当前活动模型配置重试每个范围最新的一条传输失败任务,不批量重放已经被后续成功任务覆盖的旧失败记录。
|
||||
- 生产重试进一步发现实例并发值为 3 时,多个任务会同时读取本地 Basic Memory 并触发 `BASIC_MEMORY_TIMEOUT`。并发降低或停用整理时现有 worker 必须在当前任务结束后自动退休,不能只增不减;Basic Memory 的超时和暂时不可用必须按任务级有界退避重新排队,不得永久失败,也不得错误污染模型依赖状态。
|
||||
- 流式模型请求发生网络、协议断线或服务端临时故障时,只重试当前流式模式;只有服务明确拒绝流式参数或协议时才允许退回非流式,避免一次逻辑调用被放大为多轮长超时。配置的模型超时必须直接作为每次流式读取超时,不能隐式翻倍。
|
||||
- 长模型调用每 60 秒写入一次不含 Prompt 或响应正文的安全进度事件;成功事件显示底层请求尝试次数和端到端总耗时。服务停止或 worker 取消时立即结束模型调用记录,避免依赖启动清理才能修正状态。
|
||||
- 修复以提交 `c3304bf` 发布到正式 ARM64 实例。发布前一致性备份为 `memrelay-20260807T140405Z.tar.gz`,新镜像摘要为 `sha256:050b38618ae05c9ae8161b79252bd27e45cd983785d8e02a868d0970f609994a`,旧镜像保留为 `memrelay:pre-curation-recovery-20260807`。发布后两个容器健康,LAN/公网 readiness 均为 200,运行时 worker 为 `1 / 1`,队列、活动任务和运行中模型调用均为 0。
|
||||
- 正式实例通过受控故障实验验证本地依赖恢复:停止 Basic Memory 后重试旧超时任务,新任务以 `BASIC_MEMORY_UNAVAILABLE`、`retries=1` 和未来 `next_retry_at` 回到 `queued`,尝试状态为 `waiting_dependency`,执行输出为 `local_dependency_waiting`;测试任务随后取消,Basic Memory 恢复健康,模型依赖未被污染。
|
||||
|
||||
## 2026-08-07 全链路复审结果
|
||||
|
||||
- 对照设计初衷重新核验记忆/项目上下文、检查点与时间线、外部密码库 CRUD/TOTP、目录化文件仓储、签名上传下载、MCP、动态提示词、可选 AI 整理和可选记忆 Git;Web、REST 与 MCP 仍共用同一服务层,AI/Git 未配置时基础模式可以独立运行。
|
||||
- 修正能力发现的一致性:语义搜索状态根据 Basic Memory 实际健康状态返回,不再固定宣称已启用;`memrelay://capabilities` 与 `capabilities_get` 复用同一完整能力清单;MCP `dashboard_get` 补齐数据库、整理、记忆 Git 和 Basic Memory 运行状态。
|
||||
- ARM64 线上验收发现 AI 整理状态包含时间字段时 `memrelay://capabilities` 无法直接 JSON 序列化;资源输出统一经过 FastAPI `jsonable_encoder`,并增加带真实 `datetime` 状态的 Streamable HTTP MCP 回归测试。
|
||||
- 修正桌面文件仓储目录按钮的可访问名称,并让 Playwright 只定位本次创建的目录,避免多设备/历史目录存在时出现歧义。
|
||||
- 本轮门禁:后端 `153 passed, 18 skipped`、Ruff 通过;前端 `34 passed`、ESLint、Prettier、TypeScript/Vite 构建通过;真实桌面 Playwright `1 passed`;隔离 Docker 实例的 Streamable HTTP MCP 实测 `95` 个工具、`3` 个资源。
|
||||
- 本地审计数据、测试 Token、测试文件和临时容器只存在于隔离目录,正式数据不在本轮本地测试中修改;线上发布必须在提交后重新备份并只重建 `memrelay` 服务。
|
||||
- ARM64 发布后公网 HTTPS、REST 登录、95 个 MCP 工具、3 个 MCP Resources、外部 Vaultwarden 解锁、Basic Memory 语义搜索、SQLite WAL 和记忆 Git 均通过真实验证;OpenResty 只缓存带哈希的 `/assets/`,API 与 MCP 不进入代理缓存。AI 上游短暂 503 时任务保持有限合并队列,探测恢复后会自动重新排队并继续执行。
|
||||
|
||||
## 持续交付审计修正
|
||||
|
||||
- 密码库连接兼容私有网络和反向代理环境中的 HTTP/HTTPS Vaultwarden/Bitwarden 地址,不把是否启用 TLS 作为功能前置条件。
|
||||
- AI 自动保存凭证时,只在名称相同且请求中提供的用户名、URI 等身份字段与已有条目吻合时自动更新;多个候选必须返回歧义,不能因“同名或任一 URI 相同”误覆盖其他账号。
|
||||
- 文件元数据更新采用真正的局部更新语义,未提交字段保持原值;MCP 同时提供明确清空可空字段和解除项目关联的能力。
|
||||
- 文件说明、版本、用途、标签或项目归属变化必须生成新的整理活动版本,不能因为文件正文校验值未变化而被静默去重。
|
||||
- 一次性上传任务必须持久保存发起来源和记忆档案;上传完成、元数据更新、移动与删除由 Web 或 MCP 发起时,都必须以正确的 `origin` 和 `usage_profile_id` 进入同一整理事件流。
|
||||
- 整理来源达到文件数量或字符预算时,未入选但仍存在的文件只能标记为未覆盖,不能生成删除墓碑;仅 MCP 来源策略不得把活动仓储文件误判为已删除。
|
||||
- 文件扫描与密码库同步周期在运行中启用、停用或修改后必须生效,不要求重启服务,也不得在周期设为 `0` 时形成高频空转。
|
||||
- 启动、周期、Web 和 MCP 文件扫描发现的外部新增、修改、恢复或丢失文件必须生成准确的整理活动;目录变化只维护目录表,不作为正文来源。
|
||||
- 未显式指定 `scope` 但指定 `project_id` 的 `memory_search` 必须同时搜索该项目和当前记忆空间可见的全局记忆/整理文档,与 `context_get` 的全局规则继承语义保持一致;显式 `scope=project` 或 `scope=global` 时仍严格限定范围。
|
||||
- MCP 必须提供写权限保护的 `project_resolve_or_create`:优先按 Git remote、设备目录和项目名称解析,找不到时仅用已提供的标识创建项目,并返回项目与 `created` 标记;动态提示词和能力清单必须引用真实存在的工具,避免新项目首个会话依赖两次非原子调用。
|
||||
- 上述行为必须同时由 REST 与 MCP 回归测试覆盖,并继续保持 Web、REST、MCP 共用同一服务层。
|
||||
|
||||
## 原始记忆生命周期与稳定整理文档优化
|
||||
|
||||
> 执行状态:已完成。原始 Markdown 和完整来源追溯保持不变,默认浏览、搜索和上下文只关注尚未整理或重新发生变化的内容;数据库层保证同一范围、记忆空间、项目和文档类型只有一个活动整理文档。
|
||||
|
||||
1. 为原始记忆增加可重建的整理状态:`pending`、`covered`、`superseded`。记录被哪些活动整理文档覆盖、覆盖时的原始记忆 revision、整理任务和整理时间;原始 Markdown 仍是正文来源,整理状态属于可由活动整理文档元数据和变化游标重建的 SQLite 派生索引。
|
||||
2. 新建或编辑原始记忆时自动回到 `pending`,清除旧覆盖关系;成功整理后,仅把被模型明确引用的记忆标记为 `covered`,把 `supersedes` 明确指出的旧记忆标记为 `superseded`,未被引用的来源继续保持 `pending`,避免静默隐藏未处理内容。
|
||||
3. 全局和项目整理文档继续按稳定文档更新 revision,不为同类型内容反复创建文件。增加基于 `scope + COALESCE(project_id) + COALESCE(usage_profile_id) + document_type` 的活动文档唯一索引;迁移时保留最新活动文档并把历史重复项标记为已替代,不删除历史 revision。
|
||||
4. `context_get` 优先读取稳定整理文档,并补充所有类型的 `pending` 原始记忆、整理游标之后发生变化的内容和最近检查点;为待整理来源和最新进度保留独立上下文预算,避免超长整理文档独占返回内容。`memory_search` 默认使用 `current`,同时搜索活动整理文档和待整理来源,排除 `covered`、`superseded` 与回收站内容;Web/MCP 可以显式检索这些历史来源。
|
||||
5. 全局记忆页和项目记忆页提供“待整理、已整理、已替代、回收站、全部”筛选和状态数量,默认显示待整理内容;AI 未启用时所有现有活动记忆保持 `pending`,页面和基础记忆工作流不受影响。
|
||||
6. REST 与 MCP 返回整理状态、覆盖文档、覆盖 revision 和整理时间;`memory_list`、`memory_search` 支持生命周期筛选,并提供把已整理或已替代记忆重新放回待整理队列的能力。重新整理只更新派生状态并记录新的变化事件,不复制正文。
|
||||
7. 仪表盘和 AI 整理状态增加待整理、已整理、已替代和活动整理文档统计;整理任务详情记录本次覆盖、替代和仍待整理的记忆数量。
|
||||
8. 启动时检查并修复缺失或过期的派生状态;迁移、备份恢复和旧实例升级后无需手工整理数据库。覆盖状态重建不得调用外部 AI,也不得修改原始 Markdown。
|
||||
9. 验收覆盖:同类型整理多次只增加 revision、不增加活动文件;被引用记忆退出默认列表和搜索;编辑后重新变为待整理;未引用来源不被隐藏;已替代来源可追溯;AI/Git 均未配置时基础模式保持原行为;Windows AMD64 与 ARM64 正式实例迁移、备份和公网 Web/MCP 均正常。
|
||||
|
||||
> 生命周期优化验收:后端 Ruff 与全量 pytest 通过,结果为 `141 passed, 18 skipped`;前端 33 项 Vitest、ESLint、Prettier、TypeScript/Vite 构建和桌面浏览器布局通过。Windows Docker Desktop AMD64 和物理 Armbian ARM64 均完成原生镜像构建;正式实例迁移到 `20260806_0012`,启动重建得到 19 条待整理、4 条已整理、1 条已替代和 13 份活动整理文档,LAN readiness、公网 HTTPS 页面和生命周期筛选均正常。
|
||||
|
||||
> 执行状态:已完成。AI 整理与记忆 Git 保持默认关闭、彼此独立且完全可选;两者均未配置时不探测、不排队、不初始化仓库,基础 Web、REST、MCP、记忆、项目、搜索、密码库和文件仓储完整可用。Responses 非流式、SSE、原生 JSON Schema、真实整理、历史/差异/回滚、Windows AMD64、Armbian ARM64、备份恢复、正式迁移、公网 HTTPS/MCP 和重启恢复均已通过验收。
|
||||
|
||||
> 零配置基础模式是正式支持的完整运行方式,不是降级或试用模式。初始化、创建项目、使用 Web/MCP、健康检查和部署均不得要求填写模型或 Git 配置;AI 整理与记忆 Git 只能由用户分别显式启用,未启用时不产生后台探测、队列、工作区 clone、`.git` 目录、错误告警或额外外部请求。
|
||||
|
||||
## 最终验收结果
|
||||
|
||||
- 后端完整环境回归、Ruff、真实 Responses、真实 Git、并发、备份冷恢复和迁移链均通过;当前无外部凭证回归为 `145 passed, 18 skipped`,跳过项已在带真实依赖的独立验收中覆盖。
|
||||
- 前端 `27 passed`,ESLint、Prettier、TypeScript、Vite 和桌面浏览器验收全部通过。
|
||||
- Windows Docker Desktop 在所有可选构建加速参数为空时成功构建 `linux/amd64` 镜像;物理 Armbian 原生构建并运行 `linux/arm64` 镜像。
|
||||
- 正式实例部署于 `192.168.32.100:/opt/1panel/docker/compose/memrelay`,数据位于 `/data/memrelay-stack`,数据库迁移至 `20260806_0013`;容器重启后项目、记忆、密码库、MCP 以及中断的 AI 整理任务自动恢复。
|
||||
- `https://mr.asio.asia` 的登录、REST、Streamable HTTP MCP 均通过;上一轮线上验收发现 93 个工具和 3 个资源,本轮源码与隔离实例已核对为 95 个工具和 3 个资源。OpenResty 只缓存 `/assets/`,动态 API/MCP 不缓存。
|
||||
- 正式实例在 AI/Git 都未配置时模型配置、整理队列、Git 连接和记忆仓库均为空,现有 2 个项目、23 条记忆引用、文件与已连接密码库保持可用。
|
||||
|
||||
## 完整交付审计与真实模型验收
|
||||
|
||||
1. 保留已通过的可选模式、SQLite WAL、多 worker、备份恢复、Windows AMD64 和 Armbian ARM64 能力,并对照两个正式计划逐项重新取证,不能用单元测试数量替代功能验收。
|
||||
2. 修正项目源码 Git 地址的“身份规范化值”和“真实 clone URL”混用问题;补齐工作区来源策略、分支、密码库凭证引用、整理开关、Agent 最近同步和来源覆盖状态的 REST/MCP/Web 管理。
|
||||
3. 修正项目归档与永久删除顺序:普通归档不得移动仍在使用的仓库;永久删除必须先删除 Markdown、生成本地 Git 删除提交,再归档 `per_workspace` 历史并保留可恢复的远程同步任务。
|
||||
4. 补齐整理文档 revision 差异、调度默认恢复、间隔锚点、记忆空间统计与已有 MCP Token 重新绑定能力,并保持 Web、REST 与 MCP 同一服务层。
|
||||
5. 扩展来源秘密过滤和提示注入验收,覆盖常见密码、Bearer/API Token、TOTP 种子、私钥、连接 URI 和常见平台 Token;测试凭证不得进入 Markdown、Git、日志、错误或临时产物。
|
||||
6. 增加真实 Git 断网补推、服务重启、远程分叉、项目删除历史、Agent 优先/源码 Git 兜底、所有工作区模板、调度继承/恢复和真实 Streamable HTTP MCP 测试。
|
||||
7. 使用运行时注入的新网关和 `gpt-5.6-sol` 完成 Responses 非流式、SSE、JSON Schema、模型探测、真实全局/项目整理、历史、差异、回滚及故障恢复;密钥只存在于进程环境或加密测试数据库。
|
||||
8. 重新执行完整 pytest、Ruff、Vitest、ESLint、Prettier、TypeScript、Vite、Playwright、Windows Docker、备份冷恢复、ARM64 原生构建、正式数据迁移和公网 HTTPS/MCP 验收,最后清理测试环境并覆盖部署。
|
||||
|
||||
审计修正已经锁定以下契约:项目级关闭或归档会使其待处理整理任务停止;全局首次启用 AI 只为项目级启用的工作区建立基线;增量整理把已删除的记忆和文件作为来源墓碑处理;`auto` 来源策略在 Agent 数据新鲜且完整时不拉取源码 Git,过期或不足时才使用 Git 兜底;静默调度的 `inherit`、`override`、`disabled` 与周期调度保持一致;失败任务默认使用当前模型配置重试,也可显式复用任务原配置 revision。
|
||||
|
||||
## 无人值守 AI 整理与可选 Git 版本管理完整交付
|
||||
|
||||
本轮以 `docs/ai-curation-plan.md` 为详细功能、公共接口、可靠性和验收标准的权威文档,所有能力一次完整实现,不发布缺少计划能力的中间版本。
|
||||
|
||||
执行顺序:
|
||||
|
||||
1. 增加整理任务、尝试、来源、变化日志、文档、模型连接、依赖状态、调度、记忆空间及 Git 连接/仓库/同步任务的 Alembic 迁移和服务层。
|
||||
2. 实现有界任务合并、运行中单一后继、调度租约、来源游标、内部事件过滤、模型配置快照、预算分批和异常恢复。
|
||||
3. 实现 OpenAI-compatible Responses 与 Chat Completions、SSE/非流式、结构化输出、能力探测、退避暂停和自动恢复;真实 Responses 验收使用运行时注入的测试凭证,不把密钥写入 Git、日志或快照。
|
||||
4. 实现 MCP/文件/Git 来源收集、文本/PDF/Office/图片 OCR/压缩包提取、可信边界、秘密过滤和整理 Markdown 自动应用。
|
||||
5. 实现默认关闭的记忆 Git、本地历史、可选 remote、双凭证存储、push-to-create、离线补推、分叉处理、删除归档、历史/差异/恢复及远程检查/导入/冷启动。
|
||||
6. 完成 REST、MCP、中文/英文桌面 Web、动态 Agent 提示词、状态诊断和 README/许可文档;AI 与 Git 未配置时必须保持当前基础服务行为。
|
||||
7. 完成后端单元/集成、真实 Responses、调度与并发、MCP、前端 Vitest/TypeScript/ESLint/构建、Playwright、Windows Docker Desktop AMD64 和 Armbian ARM64 验收。
|
||||
8. 通过全部验收后备份并部署到 `192.168.32.100:/opt/1panel/docker/compose/memrelay`,沿用 `/data/memrelay-stack`、端口 `3003` 和 `mr.asio.asia`,验证 LAN、公网 HTTPS、MCP、数据迁移、重启恢复与资源状态。
|
||||
|
||||
交付门槛:
|
||||
|
||||
- 模型长期不可用并积累大量变化时队列有界且不漏事件;恢复后自动补齐。
|
||||
- AI 和 Git 可分别关闭,两者都未配置时不探测、不排队、不初始化仓库,也不影响现有功能。
|
||||
- 所有模型、Git、Basic Memory 和文件外部 I/O 均不占用 SQLite 长事务;多 worker 不重复调度或领取。
|
||||
- 测试密钥只通过进程环境或隔离的加密测试数据库使用;正式部署不包含测试连接、密钥或模型任务。
|
||||
- Windows AMD64 与真实 Armbian ARM64 上全部测试和端到端工作流通过后才允许部署完成。
|
||||
|
||||
## 完整 AI 开发记忆工作流与正式部署
|
||||
|
||||
### 目标
|
||||
|
||||
- 让 Codex、Cursor、Claude Code 等客户端在新项目、新设备和新会话中,仅配置 MCP 与生成的 Agent 提示词即可识别项目、恢复上下文、持续记录开发历史、复用凭证和管理文件。
|
||||
- Web、REST 与 MCP 共用同一套项目、记忆、检查点、密码库、文件仓储和系统能力,避免只在页面或单一客户端中可用的功能。
|
||||
- 开发历史使用检查点统一记录,每条包含完成内容、原因、关键修改、验证结果、问题与解决方案及下一步,时间精确到秒并按最新在前展示。
|
||||
- 对 MemRelay、Basic Memory、本地语义模型、Vaultwarden 连接、文件仓储、Web、REST、MCP、Docker 与反向代理进行完整能力和诊断审计,确认不存在静默降级、接口缺口或阻断主要工作流的问题。
|
||||
|
||||
### 后端与数据
|
||||
|
||||
- 新实例首次启动自动创建管理员 `admin`,初始密码为 `242520`;已有实例管理员不受影响,初始化接口继续作为显式关闭自动初始化时的兼容入口。
|
||||
- 增加记忆和检查点永久删除能力,同时删除 Basic Memory Markdown 与 SQLite 可重建引用;归档和永久删除保持为不同操作。
|
||||
- 记忆 frontmatter 明确保存 `created_at` 与 `updated_at`,更新时保留创建时间;检查点默认生成秒级标题和结构化正文。
|
||||
- 记忆搜索结果返回范围、项目 ID 和项目名称,全局记忆明确标记为全局。
|
||||
- 增加项目文档 ZIP 导出,直接生成 `aidocs/project_context.md`、项目记忆、全局记忆与清单;不让 AI 逐条读取后重写。导出使用短期签名下载地址,Web 和 MCP 均可准备下载。
|
||||
- 仪表盘接口提供记忆类型分布、近 14 天新增记忆趋势、项目记忆排行、最近检查点、检查点数量、文件容量、有效 Token 与密码库状态。
|
||||
|
||||
### MCP 与 Agent 提示词
|
||||
|
||||
- 补齐项目创建、更新、归档、删除和文档导出;记忆列表、永久删除;检查点删除;密码库同步;仪表盘与系统设置查询/更新等 MCP 工具。
|
||||
- 能力资源和 `capabilities_get` 返回实际可用工具、权限及推荐工作流;破坏性操作保留明确标记,但不人为削减读写 Token 的管理能力。
|
||||
- 动态提示词提供中英文版本并锁定工作流:会话开始发现能力和解析项目,支持 Resource 的客户端继续读取 `memrelay://guide` 与 `memrelay://capabilities` 获取当前能力状态;工作前读取上下文与最新检查点,过程中保存规则、偏好、事实、决定和经验,获得凭证后立即写入密码库,重要节点和结束前保存结构化检查点。
|
||||
- 提示词要求登录或连接前先查密码库,唯一匹配直接复用;通用文件进入仓储;需要本地项目文档时直接下载并解压 ZIP 到 `aidocs/`,同时确保 `.gitignore` 包含 `aidocs/`。
|
||||
|
||||
### Web
|
||||
|
||||
- 已有记忆的 Markdown 编辑器每次打开默认预览,新建记忆默认编辑。
|
||||
- 项目列表增加搜索,项目名和 Git remote 分行显示;项目详情提供“项目记忆”和“开发时间线”标签及项目文档下载。
|
||||
- 不设置独立进度页面;项目开发时间线显示秒级检查点并支持创建、编辑和删除;搜索与编辑页面显示每条结果所属项目或全局范围。
|
||||
- 弹窗头部和底部操作区固定,正文按内容在内部滚动;Markdown、预览、日志和列表使用独立滚动区域并按桌面浏览器高度自适应。普通表单标签在左、控件在右,大型多行编辑器标签在上;提示文案使用标题旁帮助图标并在悬停时显示。
|
||||
- MCP Token 页面同时管理记忆空间;默认提供共享/全部空间范围,全部记忆空间 Token 自动覆盖后续新增空间,具体空间 Token 仍可限制写入范围。
|
||||
- 仪表盘使用原生 CSS、SVG 折线图和环形占比图展示聚合统计、趋势、依赖状态与最近活动,不新增重量级图表依赖;最近开发活动固定在依赖状态之后。
|
||||
- 全局 AI 整理调度不显示或提交项目字段,项目调度才允许选择具体项目。
|
||||
|
||||
### 正式数据、文档与部署
|
||||
|
||||
- 更新 MemRelay 正式全局记忆、BDYG18Pro 项目记忆及最新开发检查点,清理无效测试数据。
|
||||
- 将当前仍有效且可明确定位的基础设施账号、密码、Token 和服务登录信息精确匹配写入已连接 Vaultwarden,避免重复;普通记忆仅保存条目名称和用途。
|
||||
- README 补充部署、使用、MCP 工具、Agent 提示词、备份恢复、项目导出,以及 AI、MCP、MemRelay、Basic Memory、Vaultwarden 和文件仓储的 Mermaid 架构图、关系图与时序图。
|
||||
- 在 Windows Docker Desktop 完成 AMD64 回归后,构建并部署到 `192.168.32.100` 的 `/opt/1panel/docker/compose/memrelay`,数据保存在 `/data/memrelay-stack`,主机端口使用 `3003`。
|
||||
- 备份 OpenWrt FRPC 配置后新增 `mr.asio.asia` 到 `192.168.32.100:3003` 的 HTTP 映射,验证公网 HTTPS、MCP Streamable HTTP、登录 Cookie 和转发头;API、MCP、认证及签名下载禁用代理缓存,仅静态资源允许长期缓存。
|
||||
- 正式服务、数据和公网访问验收通过后关闭本机 MemRelay Compose,保留源码与构建缓存。
|
||||
|
||||
### 验收顺序
|
||||
|
||||
1. 后端迁移、单元测试、真实 Basic Memory、语义模型与 Vaultwarden 集成测试,并检查依赖健康、索引状态、降级状态和诊断信息。
|
||||
2. MCP 工具发现、权限、完整新项目/新会话工作流与项目 ZIP 导出测试。
|
||||
3. 前端 Vitest、TypeScript、ESLint、Prettier、Vite 构建和桌面 Playwright 验收。
|
||||
4. Windows AMD64 镜像验收、Armbian ARM64 原生构建部署、FRP 与公网 HTTPS 验收。
|
||||
5. 清理临时内容,更新时间线记忆、README 与第三方说明,检查 `.gitignore` 和全部工作树改动后提交独立中文 Commit。
|
||||
|
||||
## 总体方案
|
||||
|
||||
- MemRelay 是单管理员、单共享工作区的自托管 AI 记忆、密码库接入和文件仓储服务。
|
||||
- 后端:Python 3.12、FastAPI、FastMCP、Pydantic、SQLAlchemy 2、Alembic、SQLite,使用 `uv` 管理依赖。
|
||||
- 前端:Vue 3、TypeScript、Vite、Pinia、Vue Router、Element Plus、Vue I18n,使用 `pnpm`。
|
||||
- 记忆引擎:Basic Memory `v0.22.1`,通过 Git 子模块固定源码并构建定制镜像。
|
||||
- 密码库:只连接用户已有的外部 Vaultwarden/Bitwarden,不部署密码库服务。
|
||||
- 许可证:AGPL-3.0-only;同步提供第三方依赖和本地语义模型许可清单。
|
||||
- 支持 Windows Docker Desktop 的 Linux 容器模式,以及 Linux 原生 Docker/Compose 部署;不支持 Windows 容器模式。
|
||||
- 发布固定版本的 `linux/amd64`、`linux/arm64` Docker 镜像,不绑定特定 CPU 型号、核心数、内存容量或 Linux 发行版。
|
||||
- 其他架构不作为正式发布和测试目标;不为缺少上游依赖的架构维护专用实现。
|
||||
|
||||
## 执行顺序
|
||||
|
||||
### 1. 同步计划与源码
|
||||
|
||||
- 任何代码实施前,先将本 Codex 计划完整同步到 `docs/implementation-plan.md`。
|
||||
- 更新 `aidocs/project_context.md`,检查 `.gitignore`,提交 `docs: 同步完整实施计划`。
|
||||
- 将 Basic Memory 添加为 `third_party/basic-memory` Git 子模块,固定到 `v0.22.1`,禁止跟随浮动分支。
|
||||
- 提交 `.gitmodules` 和子模块引用,提交 `chore: 引入Basic Memory源码`。
|
||||
- 后续所有实现必须同时遵循 Codex 计划和正式计划文档;决策变化时先同步两处。
|
||||
|
||||
### 2. 阶段零验证
|
||||
|
||||
- 从本地 Basic Memory 子模块审查 MCP 工具、Markdown 格式、自定义元信息、项目、归档、索引和错误模型。
|
||||
- 验证 Streamable HTTP MCP 的写入、读取、搜索、移动、归档、索引重建和并发行为。
|
||||
- 构建定制 Basic Memory 镜像,预置 `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2`。
|
||||
- FastEmbed 完全在本地运行,不配置 OpenAI/LiteLLM,不消耗外部 AI Token 或产生 API 费用。
|
||||
- ONNX/FastEmbed 线程数根据容器可用 CPU 自动选择并允许环境变量覆盖,模型缓存持久化到 `/data/basic-memory/cache`。
|
||||
- 在 Windows Docker Desktop 的 Linux 容器环境验证 `linux/amd64`,在真实 ARM64 Linux 设备验证 `linux/arm64`;两种镜像均须能够启动并提供完整能力。记录模型加载、首次索引、增量写入、查询延迟和内存占用,用于发布说明和后续优化,不设置特定硬件性能门槛,也不使用 QEMU 模拟替代正式 ARM64 验收。
|
||||
- 模型故障时保留全文、标签、元数据和关系搜索,Web 显示语义搜索降级状态。
|
||||
- 验证 Bitwarden CLI `2026.7.0` 在 AMD64/ARM64 下连接外部 Vaultwarden/Bitwarden、注册邮箱加主密码登录、个人 API 密钥登录、同步、TOTP、自动解锁、离线缓存和并发读取。
|
||||
- 验证不通过时停止后续开发,先修正兼容版本或接口契约,不由实现者临时替换架构。
|
||||
|
||||
### 3. 基础框架与数据
|
||||
|
||||
- 建立 `backend/`、`frontend/`、`deploy/`、`scripts/`、`third_party/` 目录。
|
||||
- Web 使用 HttpOnly 服务端会话;管理员密码使用 Argon2id;MCP 使用 Bearer Token。
|
||||
- 部署主密钥首次启动自动生成到持久化目录;可取回 Token 和密码库登录凭据使用 AES-GCM 加密。
|
||||
- SQLite 保存管理员、会话、Token、项目、项目别名、记忆引用、幂等请求、密码库连接、凭证映射、文件目录、上传任务和系统设置。
|
||||
- Alembic 管理迁移;迁移前备份数据库,失败时停止启动并保留旧数据。
|
||||
- 后端统一错误码、超时、取消、健康检查和结构化日志;日志不保存密码、Token、TOTP 或文件上传地址。
|
||||
|
||||
### 4. 记忆与项目
|
||||
|
||||
- Basic Memory Markdown 是记忆正文唯一来源,按 `global/`、`projects/<id>/`、`archive/` 组织。
|
||||
- frontmatter 保存稳定 ID、范围、类型、项目、状态、revision、标签和时间;MemRelay SQLite 只保存可重建引用。
|
||||
- 统一 SSH/HTTPS Git remote,结合目录、仓库名、人工别名和设备路径识别项目;歧义选择一次后保存映射。
|
||||
- 明确规则、偏好、稳定事实、已确定决定和有效进度由读写 MCP 客户端自动保存。
|
||||
- 推测、临时信息、冲突内容、普通闲聊及秘密值不自动保存;任务无实质变化时不生成空检查点。
|
||||
- 记忆更新携带 revision;冲突返回最新内容;检查点只追加;创建使用请求 ID 保证幂等。
|
||||
- Obsidian 可以直接读取 Markdown;第一版不保证外部编辑后的同步,所有正式写入统一通过 Web/MCP。
|
||||
- 上下文依次组装全局规则、项目规则、偏好、事实、决定、最新检查点和相关经验,并限制返回长度。
|
||||
|
||||
### 5. 外部密码库
|
||||
|
||||
- 一个 MemRelay 实例维护一个外部 Vaultwarden/Bitwarden 连接。
|
||||
- Web 支持两种登录方式:注册邮箱加主密码,或个人 API 密钥的 `client_id`、`client_secret` 加主密码;账号密码方式必须填写 Vaultwarden/Bitwarden 的注册邮箱,不能使用显示名称。
|
||||
- API 密钥只负责 CLI 身份认证,主密码仍用于解锁密码库;账号、主密码、`client_id` 和 `client_secret` 均使用 AES-GCM 加密保存且不进入日志。
|
||||
- 第一版不支持密码库账号二步验证;启用二步验证的账号使用个人 API 密钥方式连接。
|
||||
- Bitwarden CLI 配置和加密缓存持久化,服务启动后自动登录和解锁。
|
||||
- 默认每 5 分钟同步并支持 Web 手动同步。
|
||||
- 外部服务不可达时允许读取最后一次成功同步的加密缓存,结果标明缓存状态和最后同步时间;恢复联网后自动刷新。
|
||||
- 唯一凭证自动解析;多个候选选择一次并保存非秘密映射;未找到时才创建或询问用户。
|
||||
- Web 和 MCP 支持登录条目的完整列表、详情、新建、修改和删除,字段覆盖账号、密码、多个 URI、备注、TOTP 和自定义字段。
|
||||
- MCP 在 AI 获得、生成或修改可复用凭证后自动保存;没有条目 ID 时先按名称匹配,并使用请求中实际提供的用户名和 URI 继续收窄,唯一匹配才更新,没有匹配则创建,多个匹配返回稳定歧义错误。
|
||||
- 秘密结果不进入普通日志、记忆或文件目录表。
|
||||
|
||||
### 6. 文件仓储
|
||||
|
||||
- 文件正文保存在配置目录;SQLite 文件目录表保存路径、名称、可空说明、可空版本、用途、标签、项目、MIME、大小、校验值、状态和时间。
|
||||
- 启动时扫描,默认每 15 分钟周期扫描,Web/MCP 支持手动扫描;管理员可以调整或关闭周期扫描。
|
||||
- Web/MCP 操作后立即更新目录表;外部新增、修改和丢失文件由扫描补齐。
|
||||
- 文件版本只是可搜索字段,不保存历史版本。
|
||||
- 只读 Token 可以搜索、列出和下载;读写 Token 可以更新说明、移动、重命名、删除及准备上传。
|
||||
- 覆盖和删除只在用户明确要求时执行。
|
||||
- MCP 不传输文件正文;`file_upload_prepare` 创建上传任务并返回一次性短期 HTTP PUT 地址。
|
||||
- PUT 流写入临时文件,校验大小和可选哈希后原子移动,随后自动写入目录表;失败临时文件定期清理。
|
||||
- 下载使用短期签名 GET 地址,支持 HTTP Range;上传和下载地址默认 10 分钟有效。
|
||||
|
||||
### 7. Web、部署与恢复
|
||||
|
||||
- 页面包括初始化、仪表盘、全局记忆、项目、搜索编辑、外部密码库、文件仓储、MCP Token、客户端配置、提示词、系统与备份;检查点统一在项目开发时间线中管理。
|
||||
- 中文为默认语言,可切换英文;只适配桌面浏览器。
|
||||
- 为 Codex、Cursor、Claude Code、VS Code 和通用 Streamable HTTP MCP 客户端生成配置和动态提示词。
|
||||
- Compose 只包含 `memrelay` 和定制 `basic-memory`,统一挂载 `/data`。
|
||||
- 同一套 Compose 配置用于 Windows Docker Desktop 和 Linux Docker;宿主机差异只通过环境变量、卷路径和部署脚本处理。
|
||||
- 支持 UID/GID、时区、公共 URL、扫描周期、文件容量、上传限制和外部密码库配置。
|
||||
- HTTP 不附加加密;HTTPS 由反向代理提供 TLS;生成地址沿用公共 URL 协议。
|
||||
- 提供 Linux Shell 和 Windows PowerShell 手动备份脚本:停止 Compose、归档 `/data`、生成版本清单与校验值、恢复服务。
|
||||
- 不实现定时备份和 Web 备份调度;外部 Vaultwarden/Bitwarden 数据由其自身备份。
|
||||
|
||||
## 公共接口
|
||||
|
||||
- REST 统一使用 `/api/v1`,覆盖认证、状态、项目、记忆、检查点、密码库、文件、上传任务、Token、客户端配置和系统设置。
|
||||
- MCP 项目与记忆工具:`capabilities_get`、`project_create/update/archive/delete/resolve/resolve_or_create/list/export_prepare`、`context_get`、`memory_list/search/get/save/mark_pending/archive/delete`、`checkpoint_get/save/delete`。
|
||||
- MCP 密码库工具:`secret_capabilities`、`secret_list`、`secret_item_get`、`secret_search`、`secret_resolve`、`secret_get`、`secret_totp`、`secret_save`、`secret_delete`。
|
||||
- MCP 文件工具:`file_search/list/get`、`file_directory_create`、`file_upload_prepare/status`、`file_metadata_update`、`file_move`、`file_delete`、`file_scan`。
|
||||
- MCP 整理工具:`curation_run/status/history/source_submit/cancel/retry`、`curated_document_list/get/update/history/diff/revert`、`curation_settings_get/update`、`curation_schedule_list/save/delete/reset_defaults/preview`、`curation_model_connection_status/save/test`、`curation_model_list`、`usage_profile_list/save/token_bind/delete`。
|
||||
- MCP 记忆 Git 工具:`git_connection_get/save/test/delete`、`git_mode_migration_preview/execute`、`memory_repository_list/create/status/sync/history/diff`、`memory_version_get/restore`、`memory_snapshot_restore`、`memory_repository_remote_inspect`、`memory_remote_import/bootstrap`、`memory_repository_unbind/archive_purge`。历史查询支持时间、提交者、操作类型、工作区和资源 ID 筛选。
|
||||
- MCP 系统工具:`dashboard_get`、`system_settings_get/update`、`token_list/create/reveal/revoke/delete`。
|
||||
- MCP Resources:`memrelay://guide`、`memrelay://capabilities`、`memrelay://projects`。
|
||||
- 读取和状态查询允许一次受控重试;写入不自动重试;超时、取消、冲突、候选歧义和依赖不可用返回稳定错误码。
|
||||
|
||||
## 测试与验收
|
||||
|
||||
- pytest 覆盖权限、加密、项目归一、revision、幂等、自动记忆、密码库映射与条目 CRUD、签名 URL、扫描和错误映射。
|
||||
- 使用真实 Basic Memory 和测试 Vaultwarden 进行集成测试,覆盖在线、断网、重启、离线缓存与索引重建。
|
||||
- 使用固定中英文检索样本验证多语言语义搜索,并断言运行期间没有外部嵌入 API 请求。
|
||||
- Vitest 覆盖状态、表单、国际化和组件;Playwright 覆盖桌面端完整工作流。
|
||||
- 验证 MCP 完整文件管理、一次性 PUT、Range 下载、15 分钟扫描、目录表实时更新和说明/版本搜索。
|
||||
- 验证 HTTP、反向代理 HTTPS、Windows Docker Desktop、Linux Docker、`linux/amd64`、`linux/arm64`、目录权限、迁移失败和完整备份恢复。
|
||||
- 每个阶段完成后清理临时内容、更新 `aidocs/project_context.md`、检查 `.gitignore` 并提交独立中文 Git commit。
|
||||
|
||||
## 已锁定默认值
|
||||
|
||||
- 单实例、单管理员、单共享工作区、单外部密码库连接。
|
||||
- Element Plus、Vue I18n、AGPL-3.0-only。
|
||||
- Basic Memory 以 Git 子模块固定在 `third_party/basic-memory`。
|
||||
- Obsidian 只读兼容,不承诺外部 Markdown 编辑同步。
|
||||
- 本地多语言 MiniLM 默认启用并预置镜像,不使用付费嵌入服务。
|
||||
- 明确记忆自动保存;已有唯一凭证无感使用。
|
||||
- 新获得或生成的可复用凭证由读写 MCP 客户端自动保存到外部密码库;唯一匹配条目直接更新,避免重复创建。
|
||||
- 文件扫描默认 15 分钟;文件版本仅为元数据。
|
||||
- MCP 完整管理文件,但上传只生成 HTTP PUT 地址。
|
||||
- 密码库离线时允许使用最后同步缓存。
|
||||
- 完整备份由手动短暂停机脚本触发。
|
||||
- Windows 通过 Docker Desktop Linux 容器部署;Linux 通过原生 Docker/Compose 部署。
|
||||
- 正式构建和测试 `linux/amd64`、`linux/arm64` 镜像,不针对 ARMv7 等缺少上游依赖的架构开发替代实现。
|
||||
@@ -0,0 +1,36 @@
|
||||
# 阶段零验证报告
|
||||
|
||||
验证日期:2026-08-02
|
||||
|
||||
## Basic Memory
|
||||
|
||||
- 固定源码:`v0.22.1`,提交 `232f4690656d7c93f39fc0cb13b0826243f2e0da`。
|
||||
- 固定 FastMCP:`3.3.1`;Streamable HTTP 路径为 `/mcp`。
|
||||
- 实际枚举 23 个 MCP 工具;MemRelay 所需的写入、读取、全文搜索、移动、删除和目录读取工具均存在。
|
||||
- 自定义 frontmatter 可以保存稳定 ID、范围、revision、状态和标签;中文 Markdown 往返无损。
|
||||
- AMD64 与真实 ARM64 均通过写入、读取、全文搜索、5 路并发写入、移动归档和归档后读取。
|
||||
- 本地模型 `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` 输出 384 维向量,中英文凭证查询可以将中文目标记忆排在第一位。
|
||||
- AMD64 与真实 ARM64 均在断网容器中通过语义检索,证明运行期不依赖外部嵌入 API。
|
||||
- 定制镜像使用 Python 3.12 和 Streamable HTTP,构建时预载模型;全新 `/data` 卷首次启动会生成约 241 MB 的持久模型缓存。
|
||||
|
||||
## Bitwarden CLI
|
||||
|
||||
- 固定 CLI:`@bitwarden/cli@2026.7.0`,运行时为 Node.js 22。
|
||||
- AMD64 与真实 ARM64 均通过版本加载。
|
||||
- 使用隔离的临时 Vaultwarden `1.37.1` 和一次性测试账号完成真实协议验证。
|
||||
- AMD64 与真实 ARM64 均通过账号密码登录、同步、创建 TOTP 项、5 路并发读取、锁定后重新解锁和再次同步。
|
||||
- 停止临时 TLS 入口后,AMD64 与真实 ARM64 均可使用持久化的加密 CLI 状态离线解锁并读取最后同步缓存。
|
||||
- 测试使用 Caddy 内部测试证书并只在测试 CLI 中关闭证书校验;正式实现不得关闭 TLS 证书验证。
|
||||
|
||||
## 代表性结果
|
||||
|
||||
- Docker Desktop AMD64:Basic Memory 完整 MCP 回归约 5 秒。
|
||||
- 真实 ARM64 设备:非语义 MCP 回归约 55 秒,语义 MCP 回归约 75 秒。
|
||||
- 上述时间只用于后续优化和发布说明,不是通用硬件门槛。
|
||||
|
||||
## 实现约束
|
||||
|
||||
- 正式构建和测试目标为 `linux/amd64`、`linux/arm64`。
|
||||
- Basic Memory 的 OpenAI/LiteLLM 包是上游强依赖,但 MemRelay 固定 `fastembed` 本地提供者,不配置外部嵌入服务。
|
||||
- Docker 主机级代理可能自动注入容器并污染内部服务通信;Compose 必须为内部通信清空代理变量或配置完整 `NO_PROXY`。
|
||||
- Bitwarden CLI 登录要求 HTTPS;局域网 HTTP 只适用于 MemRelay 自身,不代表外部密码库连接可以绕过 CLI 的 HTTPS 要求。
|
||||
Reference in New Issue
Block a user