Files
MemRelay/docs/implementation-plan.md
T

58 KiB
Raw Blame History

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 等缺少上游依赖的架构开发替代实现。