Files

379 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MemRelay
MemRelay 是一个自托管的 AI 记忆、开发历史、密码库接入和文件仓储服务。它让 Codex、Cursor、Claude Code、VS Code 等客户端在不同设备、项目和聊天窗口之间恢复上下文,并在开发过程中持续写入规则、决定、经验、凭证和检查点。
外部 AI 整理和记忆 Git 都是独立的可选增强,默认关闭。两者都不配置时,MemRelay 不探测模型、不创建整理或 Git 任务、不初始化 `.git`,现有记忆、项目、搜索、密码库、文件、Web 和 MCP 能力保持正常可用。
MemRelay 面向个人和私有团队部署。Web、REST 与 Streamable HTTP MCP 共用同一套能力,配置一次后即可由 AI 客户端持续使用。
## 核心能力
- 全局规则与偏好,以及按项目组织的事实、决定、经验和开发检查点。
- 通过 Git remote、项目名称和多设备目录别名识别同一个项目。
- 秒级开发时间线,记录完成内容、原因、关键修改、验证、问题与解决方案和下一步。
- Basic Memory Markdown 正文、全文搜索和本地多语言语义搜索。
- 连接已有 Vaultwarden/Bitwarden,完整管理账号、密码、URI、Token、自定义字段和 TOTP。
- 带目录、说明、版本、标签、一次性上传、签名下载和 HTTP Range 的文件仓储。
- 项目文档 ZIP 直接下载到 `aidocs/`,避免 AI 逐条读取并重写而消耗 Token。
- 可取回、撤销的只读或读写 MCP Token,以及主流 AI 客户端配置生成。
- 中文默认、可切换英文的桌面 Web 界面。
## 系统架构
```mermaid
flowchart LR
AI["Codex / Cursor / Claude Code / VS Code"] -->|"Streamable HTTP MCP"| MCP["MemRelay MCP"]
WEB["Desktop Web"] -->|"REST / Session"| API["MemRelay API"]
MCP --> CORE["Project, Memory, Vault, File Services"]
API --> CORE
CORE --> CURATION["Optional Curation Worker"]
CURATION -.-> MODEL_API["OpenAI-compatible API"]
CURATION --> SOURCE["Memory, Files, Agent Sources, Read-only Git"]
CORE --> MEMORY_GIT["Optional Memory Git"]
MEMORY_GIT -.-> GIT_REMOTE["User-provided Git Remote"]
CORE --> DB[("SQLite metadata")]
CORE --> BM["Basic Memory"]
BM --> MD[("Markdown notes")]
BM --> MODEL["Local multilingual MiniLM"]
CORE --> BW["External Vaultwarden / Bitwarden"]
CORE --> FILES[("File repository")]
```
数据关系:
```mermaid
erDiagram
PROJECT ||--o{ PROJECT_ALIAS : identifies
PROJECT ||--o{ MEMORY_REFERENCE : owns
PROJECT ||--o{ FILE_RECORD : relates
MEMORY_REFERENCE }o--|| BASIC_MEMORY_NOTE : points_to
MCP_TOKEN }o--|| ADMINISTRATOR : managed_by
VAULT_CONNECTION ||--o{ CREDENTIAL_MAPPING : resolves
FILE_RECORD ||--o{ UPLOAD_TASK : receives
USAGE_PROFILE ||--o{ MEMORY_REFERENCE : scopes
PROJECT ||--o{ CURATED_DOCUMENT : organizes
CURATION_JOB ||--o{ CURATION_ATTEMPT : runs
GIT_CONNECTION ||--o{ MEMORY_REPOSITORY : manages
MEMORY_REPOSITORY ||--o{ GIT_SYNC_JOB : queues
```
一次完整 AI 会话:
```mermaid
sequenceDiagram
participant AI as AI Client
participant MCP as MemRelay MCP
participant MR as MemRelay Core
participant BM as Basic Memory
participant VW as Vaultwarden
participant FS as File Repository
AI->>MCP: capabilities_get
AI->>MCP: project_resolve_or_create(directory, git_remote, name)
AI->>MCP: context_get + checkpoint_get
MCP->>BM: Read global and project Markdown
BM-->>AI: Rules, facts, decisions, experience, progress
loop During development
AI->>MCP: memory_save
AI->>MCP: secret_search / secret_save
MCP->>VW: Read or update reusable credentials
AI->>MCP: file_upload_prepare / file tools
MCP->>FS: Store artifacts and metadata
end
AI->>MCP: checkpoint_save
MCP->>BM: Append structured development history
opt AI curation enabled
AI->>MCP: curation_source_submit
MCP->>MR: Queue bounded incremental curation
MR->>BM: Apply revisioned curated documents
end
opt Memory Git enabled
MR->>MR: Queue and commit the logical memory change
end
opt Local aidocs required
AI->>MCP: project_export_prepare
MCP-->>AI: Signed ZIP URL and extraction command
end
```
## 运行环境
- Windows:Docker Desktop 的 Linux 容器模式。
- Linux:Docker Engine 与 Docker Compose v2。
- 正式验证架构:`linux/amd64`、`linux/arm64`。
项目不绑定具体 CPU 型号、核心数、内存容量或 Linux 发行版。ARM64 验收在物理 Linux/Armbian 设备原生构建和运行。
## 快速部署
要求:Git、Docker、Docker Compose v2。
Linux:
```bash
git clone --recurse-submodules <repository-url> memrelay
cd memrelay
cp .env.example .env
docker compose up -d --build
```
Windows PowerShell:
```powershell
git clone --recurse-submodules <repository-url> memrelay
Set-Location memrelay
Copy-Item .env.example .env
docker compose up -d --build
```
默认地址:`http://localhost:8080`
新数据目录首次启动会自动创建管理员:
- 用户名:`admin`
- 初始密码:`242520`
已有实例不会被默认值覆盖。登录后可在“系统与备份”页面修改密码。
如果仓库已经克隆但缺少子模块:
```bash
git submodule update --init --recursive
```
## 配置
编辑 `.env`:
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `MEMRELAY_PORT` | `8080` | Web、REST 与 MCP 的宿主机端口 |
| `MEMRELAY_PUBLIC_URL` | `http://localhost:8080` | 浏览器、MCP 和签名下载使用的最终公开 URL |
| `MEMRELAY_DATA_PATH` | `./data` | 两个容器共享的持久化目录 |
| `MEMRELAY_INITIAL_ADMIN_USERNAME` | `admin` | 新实例初始管理员 |
| `MEMRELAY_INITIAL_ADMIN_PASSWORD` | `242520` | 新实例初始管理员密码 |
| `MEMRELAY_FILE_SCAN_INTERVAL_SECONDS` | `900` | 文件仓储扫描周期,`0` 关闭 |
| `MEMRELAY_VAULT_SYNC_INTERVAL_SECONDS` | `300` | 外部密码库同步周期,`0` 关闭 |
| `MEMRELAY_CONTEXT_MAX_CHARS` | `24000` | 上下文最大字符数 |
| `MEMRELAY_UPLOAD_MAX_BYTES` | `10737418240` | 单文件最大上传字节数 |
| `UID` / `GID` | `1000` | Linux 容器业务进程与数据目录属主 |
| `TZ` | `Asia/Shanghai` | 容器时区 |
| `MEMRELAY_BUILD_HTTP_PROXY` | 空 | 可选,仅用于镜像构建的 HTTP 代理 |
| `MEMRELAY_BUILD_HTTPS_PROXY` | 空 | 可选,仅用于镜像构建的 HTTPS 代理 |
| `MEMRELAY_BUILD_ALL_PROXY` | 空 | 可选,仅用于镜像构建的通用代理 |
| `MEMRELAY_BUILD_APT_MIRROR` | 空 | 可选 Debian 镜像主机,例如 `https://mirrors.aliyun.com` |
局域网可直接使用 HTTP。公网应由 Caddy、Nginx、OpenResty 或其他反向代理提供 HTTPS,并把 `MEMRELAY_PUBLIC_URL` 设置为最终 HTTPS 地址。
不要缓存 `/api/`、`/mcp`、登录、密码库、上传和签名下载响应。仅 `/assets/` 适合长期静态缓存。
1Panel OpenResty 可以使用仓库中的两份示例:
- `deploy/openresty/memrelay-cache.conf` 放入 OpenResty `http` 级配置目录,定义独立的 `memrelay_assets` 缓存区。
- `deploy/openresty/memrelay-assets.conf` 放入 MemRelay 站点的 `server` 配置或 `proxy/` 包含目录,只缓存带内容哈希的 `/assets/`。
示例中的上游为 `127.0.0.1:52001`,部署到其他端口或直接反代 MemRelay 时需要按实际地址调整。配置后先执行 `openresty -t`,成功后再热加载。首次请求应返回 `X-Cache: MISS`,后续请求返回 `X-Cache: HIT`;API 和 MCP 响应不得出现缓存命中。
## Web 使用
Web 页面包括:
- 仪表盘:项目、记忆、检查点、文件、Token、依赖状态、近 14 天新增记忆趋势、类型占比、项目排行和最近开发活动。
- 全局记忆:跨项目规则、偏好、事实和经验。
- 项目:搜索、编辑、停用、永久删除、项目记忆、开发时间线和文档下载。
- 搜索与编辑:全文、标题、混合和向量搜索,并显示所属项目。
- 项目开发时间线:按秒展示检查点,支持查看、创建、编辑和删除检查点。
- 密码库:连接、同步、列出、搜索、查看、新增、修改和删除登录条目。
- 文件仓储:目录与文件的上传、下载、移动、元数据和扫描。
- AI 整理:可选模型连接、任务、整理文档和调度;记忆空间与“全部记忆空间”Token 在 MCP Token 页面管理,未配置 AI 时保持中性关闭状态。
- 记忆版本:可选本地 Git 历史、远端同步、差异、恢复和受控仓库模式迁移;未配置时不创建 `.git`。
- MCP Token、客户端配置、Agent 提示词、运行设置和备份说明。
AI 整理会把连接超时、远端协议断开、代理断流、`408`、`429` 和 `5xx` 作为临时依赖故障处理:单次请求进行有限重试,仍不可用时任务进入 `waiting_dependency`,模型探测恢复后自动继续。长输出端点建议启用流式模式,以持续接收数据并降低反向代理空闲断开的概率;流式网络故障不会自动退回更容易被空闲超时中断的非流式请求,只有端点明确拒绝流式参数时才降级。执行输出每分钟记录长调用仍在处理的状态,完成后显示底层请求尝试次数和端到端总耗时。
Basic Memory 超时或暂时不可用只影响当前整理任务:任务按配置的有界指数退避重新排队,不会被永久标记失败,也不会把外部模型状态误判为不可用。整理 worker 会实时遵循启用状态和最大并发设置;降低并发或停用整理时,已有 worker 完成当前任务后平滑退出。服务停止会结束当前模型调用记录,服务重启会清理遗留调用并重新排队未完成任务。
已有记忆打开时 Markdown 默认进入预览,新建记忆默认进入编辑。新建记忆在正文为空时按类型提供编辑模板,支持规则、偏好、事实、决定、经验、检查点、需求文档和任务列表。项目开发时间线和导出的 `project_context.md` 均按最新在前排列,时间精确到秒。弹窗操作区固定,Markdown、预览、日志和列表在自己的区域滚动并按桌面浏览器高度自适应。
## MCP 接入
1. 在“MCP Token”页面创建读写 Token。
2. 在“客户端配置”选择 Codex、Cursor、Claude Code、VS Code 或通用客户端。
3. 使用生成的配置接入 `<MEMRELAY_PUBLIC_URL>/mcp`。
4. 在“提示词”页面复制当前语言的 Agent 工作流到项目或客户端规则文件。
支持 MCP Resource 的客户端在初始化后还应读取 `memrelay://guide` 和 `memrelay://capabilities`,以获得当前实例的可选能力状态;未配置 AI、Git 或密码库时继续使用基础记忆工作流,不需要额外配置。
`capabilities_get` 与 `memrelay://capabilities` 返回同一份实时能力清单,包含 Basic Memory/语义搜索、密码库、AI 整理和记忆 Git 的当前状态;`dashboard_get` 还返回与 Web 仪表盘一致的数据库、整理、记忆 Git 和依赖状态,客户端不需要猜测服务是否可用。
只读 Token 只能发现读取工具;读写 Token 可以使用全部项目、记忆、密码库、文件、系统和 Token 管理能力。创建 Token 时可选择具体记忆空间,或选择“全部记忆空间”;全部记忆空间 Token 自动包含之后新增的空间。撤销会让 Token 永久失效但保留记录,删除则永久移除 Token 记录。
### MCP 工具
| 分类 | 工具 |
| --- | --- |
| 能力 | `capabilities_get` |
| 项目 | `project_list`、`project_resolve`、`project_resolve_or_create`、`project_create`、`project_update`、`project_archive`、`project_delete`、`project_export_prepare` |
| 记忆 | `context_get`、`memory_list`、`memory_search`、`memory_get`、`memory_save`、`memory_mark_pending`、`memory_archive`、`memory_delete` |
| 检查点 | `checkpoint_get`、`checkpoint_save`、`checkpoint_delete` |
| 密码库 | `secret_capabilities`、`secret_sync`、`secret_list`、`secret_item_get`、`secret_search`、`secret_resolve`、`secret_get`、`secret_totp`、`secret_save`、`secret_delete` |
| 文件 | `file_list`、`file_search`、`file_get`、`file_directory_create`、`file_upload_prepare`、`file_upload_status`、`file_metadata_update`、`file_move`、`file_delete`、`file_scan` |
| AI 整理(可选) | `curation_run`、`curation_status`、`curation_history`、`curation_source_submit`、`curated_document_list/get/update/history/diff/revert`、`curation_cancel/retry`、`curation_settings_get/update`、`curation_schedule_list/save/delete/reset_defaults/preview`、`curation_model_connection_status/save/test`、`curation_model_list` |
| 记忆空间 | `usage_profile_list`、`usage_profile_save`、`usage_profile_token_bind`、`usage_profile_delete` |
| 记忆 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` |
| 系统 | `dashboard_get`、`system_settings_get`、`system_settings_update` |
| Token | `token_list`、`token_create`、`token_reveal`、`token_revoke`、`token_delete` |
MCP Resources:`memrelay://guide`、`memrelay://capabilities`、`memrelay://projects`。
`memory_search` 默认使用 `lifecycle=current`,同时返回稳定整理文档和尚未整理的新来源。结果中的 `result_kind` 和 `read_tool` 会明确指出应使用 `memory_get` 还是 `curated_document_get` 读取正文;只有追溯原始历史时才改用 `pending`、`covered`、`superseded`、`archived` 或 `all`。
失败的整理任务默认使用当前有效模型配置重试,也可以显式传入
`use_original_config=true`,复用任务保存的原模型配置 revision。整理文档支持任意两个
revision 的差异查询和以新 revision 方式回滚;调度规则可单独编辑,也可以恢复实例默认值。
## Agent 工作流
生成的提示词要求 AI 在每次新会话中:
1. 调用 `capabilities_get`。
2. 根据目录、Git remote 和名称解析项目,不存在时创建。
3. 修改代码前读取 `context_get` 和 `checkpoint_get`。
4. 过程中即时保存明确规则、偏好、事实、决定和经验。
5. 登录前先查密码库,唯一匹配直接复用;新凭证立即保存。
6. 通用文件、程序和构建产物使用文件仓储。
7. 每个有意义阶段和会话结束前保存结构化检查点。
8. 新窗口重复项目解析、上下文和检查点读取后继续工作。
启用 AI 整理后,Agent 通过 `curation_source_submit` 提交的来源在配置的新鲜度时间内优先使用;
来源过期、缺失或覆盖不足时,服务端才读取文件仓储,并在项目配置了源码 Git remote 时使用
只读 Git 工作区兜底。源码 Git 不会被整理器修改,记忆 Git 也与源码仓库相互独立。未启用 AI
或 Git 时不需要执行这些步骤,基础记忆工作流保持不变。
检查点正文应包含:
```markdown
## 完成内容
## 为什么这样做
## 关键修改
## 验证结果
## 遇到的问题与解决方案
## 下一步
## 给下个会话
```
会话结束前的最后一个检查点按交接标准书写:"下一步"和"给下个会话"要让零上下文的新会话直接接手,列出未完成线索、临时约定和需要避开的坑。
## 项目文档导出
Web 的“下载项目文档”或 MCP 的 `project_export_prepare` 会生成短期签名 ZIP,内容包括:
```text
aidocs/
project_context.md
manifest.json
curated/project/<type>.md
curated/global/<profile>/<type>.md
memories/<lifecycle>/<type>/*.md
global/sources/<lifecycle>/<type>/*.md
```
MCP 会同时返回 Windows PowerShell 和 POSIX Shell 命令。AI 应直接运行命令下载并解压到项目根目录,并确保 `.gitignore` 包含:
```gitignore
aidocs/
```
`aidocs/` 是本地上下文副本,正式写入仍通过 Web 或 MCP 完成。
## 外部密码库
MemRelay 不捆绑 Vaultwarden。请在“密码库”页面连接已有 Vaultwarden/Bitwarden:
- 注册邮箱 + 主密码。
- 个人 API 密钥 `client_id` / `client_secret` + 主密码。
- 私有网络可直接填写 HTTP 地址;公网建议填写由反向代理提供的 HTTPS 地址。
MemRelay 会持久化 Bitwarden CLI 加密状态,启动后自动登录、解锁并按周期同步。外部服务不可达时可读取最后一次成功同步的本地缓存。Web 和 MCP 均支持完整登录条目 CRUD 与 TOTP。
AI 获取的秘密值写入密码库;普通记忆只保存密码库条目名称与用途,后续客户端可直接定位和复用。
## 文件仓储
文件正文位于数据目录,SQLite 保存可重建目录元数据。目录是一等对象,Web 与 MCP 均可创建、浏览、移动和删除空目录。
- 上传:`file_upload_prepare` 返回一次性 HTTP PUT 地址,客户端直接传输字节。
- 下载:`file_get` 返回短期签名地址,支持 HTTP Range。
- 扫描:启动时、周期或手动扫描外部新增、修改和缺失文件。
- 覆盖和删除:由明确的 Web 或 MCP 操作触发。
## 数据目录
`MEMRELAY_DATA_PATH` 下保存:
- `memrelay/`:SQLite、部署主密钥、文件正文与 Bitwarden CLI 状态。
- `basic-memory/`:Markdown、索引数据库和本地语义模型缓存。
部署主密钥与 SQLite 必须一起备份,否则已加密的 MCP Token 和密码库连接配置无法恢复。
## 备份与恢复
备份脚本会短暂停止 Compose,归档整个数据目录并生成版本清单和 SHA-256:
```powershell
.\scripts\backup.ps1
```
```bash
sh scripts/backup.sh
```
恢复:
```powershell
.\scripts\restore.ps1 -Archive .\backups\memrelay-<timestamp>.tar.gz
```
```bash
sh scripts/restore.sh ./backups/memrelay-<timestamp>.tar.gz
```
恢复脚本会先校验同目录下的 `.sha256`,支持恢复到已有实例或全新数据目录,并使用 `docker compose up -d` 创建或重启服务。目标目录非空时必须显式使用 PowerShell 的 `-Force` 或 Shell 的 `--force`。
外部 Vaultwarden/Bitwarden 数据由密码库自身备份。
## 开发与测试
后端:
```bash
cd backend
uv sync --frozen
uv run ruff check .
uv run pytest
```
前端:
```bash
cd frontend
pnpm install --frozen-lockfile
pnpm test
pnpm lint
pnpm format
pnpm build
pnpm test:e2e
```
验收覆盖真实 Basic Memory、离线本地语义模型、Vaultwarden/Bitwarden CLI、20 路 Web/MCP 混合并发、一次性上传、Range 下载、项目导出、完整 MCP 工作流、停机备份与冷恢复、Windows Docker Desktop AMD64 和物理 Linux/Armbian ARM64。
## 许可证
MemRelay 使用 [GNU AGPL v3](LICENSE)(`AGPL-3.0-only`)。第三方组件和本地模型许可见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。