云同步后端设计说明(Cloud Sync Backend Design)
August 14, 2026 · View on GitHub
配套
memory-system技能的可选插件:把 L1/L3 记忆文件从"本地 + 手动 Git 同步"升级为"插件驱动的自动云同步"。 状态:设计草案(Design Draft) · 作者:yunyu422 · English summary
背景与目标(Background & Goals)
当前技能的三层记忆中,L3 学习画像(PREFERENCES.md)和 L1 用户档案(USER.md)位于 ${DSH_HOME}/memory/。references/learned-preferences.md 已给出"手动接入 Git 私有仓库或云盘"的等效方案,但它有三个不足:
- 手动:需要用户自己
git init、commit、push,Agent 无法参与; - 无加密:明文同步到云端有隐私风险;
- 无冲突策略:多台机器同时改同一个画像文件时行为未定义。
本设计定义一个 DSH 插件(@dsh-contrib/memory-sync),在 Host 平面提供同步服务,在 Agent 平面提供模型面工具,把"同步"变成 Agent 日常工作流的一部分:
- 会话开始时自动拉取远端更新(
agent/pre-step钩子); - 任务收尾例程写入记忆后自动推送(技能指令调用模型面工具);
- 可选定时推送(
dsh-schedule的every机制); - 可选端到端加密(AES-256-GCM,密钥走
ctx.credentials,云端只见密文); - 定义明确冲突策略(默认 Last-Write-Wins,画像文件用追加合并)。
架构总览(Architecture)
遵循 DSH 的 双平面规则(与 subagents 注册表 / 后端的关系同构):
┌────────────────────────── Host 平面(进程级,一次)──────────────────────────┐
│ │
│ dsh-memory-sync (插件) │
│ ├─ ctx.memorySync 服务(同步引擎:状态机 / 冲突合并 / 加密 / 后端路由) │
│ ├─ 后端适配器注册表(git | webdav | s3 | http —— 可插拔,类似 LLM 适配器) │
│ └─ 消费:ctx.credentials(密钥引用)、ctx.sessions(持久化屏障)、 │
│ ctx.schedule(可选定时)、ctx.fs(本地文件) │
└──────────────────────────────────────────────────────────────────────────────┘
│ 注册工具(agent 平面)
▼
┌────────────────────────── Agent 平面(每会话)───────────────────────────────┐
│ memory_sync_status / memory_sync_pull / memory_sync_push / │
│ memory_sync_configure(模型面工具,经 cordis:group + isolate realm 注册) │
│ 技能 SKILL.md 的任务收尾例程调用 memory_sync_push │
└──────────────────────────────────────────────────────────────────────────────┘
为什么这样分:网络 I/O、密钥解析、状态持久化必须留在 Host(一个实例服务所有会话);工具只把"模型意图"翻译成对 ctx.memorySync 的调用。与 subagents 相同——注册表在 Host,preset 只贡献工具行。
数据模型(Data Model)
同步单元
| 单元 | 路径 | 同步策略 |
|---|---|---|
| L1 用户档案 | ${DSH_HOME}/memory/USER.md | 整文件 Last-Write-Wins |
| L3 学习画像 | ${DSH_HOME}/memory/PREFERENCES.md | 追加合并(append-merge,见冲突策略) |
| 项目记忆(可选) | <projectRoot>/.memory/MEMORY.md | 整文件 LWW,按项目 key 隔离 |
版本元数据
每个同步单元附带:
interface MemoryFileMeta {
path: string // 相对同步根的规范路径
version: string // 内容 SHA-256(16 进制)
updatedAt: string // RFC 3339 UTC 最后写入
source: string // 产生该版本的机器标识(hostname 或配置 id)
encrypted: boolean // 是否端到端加密
}
云端仓库(任选后端)存 { meta, blob },blob 为明文或密文。
后端适配器(Backends)
引擎对后端只依赖一个最小接口,新增后端只需实现它(对齐 LlmAdapter 模式):
interface SyncBackend {
id: string
// 拉取远端全部记忆单元(返回 meta 列表 + 按需 blob)
list(): Promise<MemoryFileMeta[]>
get(meta: MemoryFileMeta): Promise<{ blob: Uint8Array }>
put(meta: MemoryFileMeta, blob: Uint8Array): Promise<void>
// 可选:服务端条件写,避免竞态(后端不支持则降级为客户端合并)
compareAndSwap?(meta: MemoryFileMeta, expected: string): Promise<boolean>
}
首期后端(M1)——Git:在 ${DSH_HOME}/memory/ 内 git init + remote add,每次同步 = add → commit → push/pull。复用用户已配好的 SSH 通道(含 ssh.github.com:443 绕行场景),零新增依赖,最适合先跑通闭环。
M2 —— WebDAV / S3:无 Git 依赖的通用存储(坚果云/OneDrive WebDAV、MinIO、R2)。密钥(密码/access key)经 ctx.credentials 引用,cordis.yml 只写 secretRef: MEMORY_SYNC_WEBDAV_PASSWORD 这类引用,绝不写值(对齐 credentials 包"配置携带引用,不携带密钥"教义)。
M3 —— HTTP 服务端(团队画像):可选的自托管服务,支持多用户/多空间,用于团队共享项目约定(类似 WorkBuddy 云端画像的协作形态)。属于远期,设计里只留接口位。
冲突策略(Conflict Resolution)
- Last-Write-Wins(默认):比较
updatedAt(UTC,机器时钟漂移容忍 ±5 分钟,超出则回退到内容 hash 比较),新者胜。适用于 L1/L2 整文件单元。 - 追加合并(L3 画像专用):
PREFERENCES.md是 append-only 风格,冲突时两端各自的新增条目都保留,按日期字段重排序,重复条目(同日期同文本)去重。引擎返回合并后的文件并在当轮工具结果里告知"已合并 N 条来自另一台机器的偏好"。 - 自动冲突无法解决时:引擎不丢数据——把对方版本存为
<name>.conflict-<source>.md旁路文件,并在工具结果中提示模型向用户询问。
加密(Encryption)
- 可选端到端加密:AES-256-GCM,随机 96-bit IV 前置在密文 blob。
- 密钥来源:
ctx.credentials.resolve('MEMORY_SYNC_PASSPHRASE')——由用户在设置界面或环境变量配置,模型和工具永远拿不到明文密钥(credentials 包保证describe不含值)。 - 加密开关记录在
meta.encrypted;同一仓库混用明文/密文单元是允许的(L3 建议加密,L1 可选)。
安全边界(Security Boundary)
- 同步范围白名单:仅同步
memory/下的记忆文件,绝不触碰~/.dsh/.credentials.yaml、settings.yaml等配置。 - 大小上限:单个记忆文件超过阈值(默认 256 KB)拒绝 push,提示先裁剪(与技能既有的裁剪规则配合)。
- 速率限制:每次会话 pull/push 各 ≤ N 次,防止循环触发(
agent/pre-step只在会话第一次请求前拉取一次)。 - 模型面工具是"薄客户端":工具只触发操作、返回状态摘要;网络与密钥处理全在 Host 引擎,模型无法借工具外带密钥。
触发机制(Triggers)
| 时机 | 机制 | 动作 |
|---|---|---|
| 会话开始(每会话一次) | agent/pre-step 监听器(prepend 注册,参考 dsh-plan-mode 的追加模式) | 拉取远端更新并合入本地记忆文件 |
| 任务收尾例程 | 技能 SKILL.md 指令 → 调用 memory_sync_push | 推送本次写入的记忆单元 |
| 可选定时 | dsh-schedule 的 every_seconds(≥300s) | 兜底推送,防止模型忘记调用 |
| 手动 | 用户说"同步记忆" / /memory-system sync | 立即 pull+push |
注意对齐 plan-mode 的实现教训:
agent/pre-step的追加必须在 downstream 接受该步骤之后进行;追加失败不能阻塞轮次。
与现有技能的关系(Relationship to the Skill)
- 技能继续负责"何时写"(会话例程、写层触发规则、隐私红线不变);
- 插件只负责"同步到哪"(后端、加密、冲突);
- 升级
references/learned-preferences.md的"可选云同步"一节:从"手动 git 命令"改为"推荐安装memory-sync插件,体验自动同步"; - 插件可选:不安装时,技能行为与现在完全一致(向后兼容)。
仓库与包结构(Proposed Package Layout)
dsh-memory-sync/ # 独立仓库(与 memory-system 技能仓库分离,便于独立发布)
├── package.json # name: @dsh-contrib/memory-sync
├── src/
│ ├── index.ts # Host 插件入口:注册 ctx.memorySync 服务
│ ├── engine.ts # 状态机 / 冲突合并 / 加密
│ ├── backends/
│ │ ├── git.ts # M1
│ │ ├── webdav.ts # M2
│ │ └── http.ts # M3(预留)
│ └── tools.ts # 模型面工具定义(memory_sync_*)
├── agent.cordis.yml # Agent 平面组合片段(工具行,供 preset 引用)
└── README.md
实施里程碑(Milestones)
| 里程碑 | 内容 | 验收 |
|---|---|---|
| M1 | Git 后端 + 会话开始拉取 + 收尾推送 + LWW 冲突策略 | 两台机器同步 L1/L3,无数据丢失 |
| M2 | WebDAV/S3 后端 + AES-256-GCM 加密 + 追加合并策略 | 加密推送后云端无法明文读取 |
| M3 | HTTP 服务端 + 多用户空间 + 团队约定共享 | 两人共享项目 MEMORY.md 约定 |
开放问题(Open Questions)
- 多用户共享时,L3 画像属于个人还是按空间隔离?(倾向:个人画像按用户隔离,只有项目级 MEMORY.md 共享)
- 加密密钥丢失的恢复路径?(倾向:提供
memory_sync_export_clear导出未加密副本,提示用户自行保管) - 是否需要观察者模式(监听本地文件变化自动同步)而非仅靠触发点?(M2 之后评估,避免与
fs/observed机制耦合过深)
English Summary
This design defines an optional DSH plugin (@dsh-contrib/memory-sync) that upgrades the memory-system skill's L1/L3 files from manual Git syncing to automatic, encrypted, conflict-aware cloud sync:
- Host plane: a
ctx.memorySyncservice (engine + pluggable backends: Git → WebDAV/S3 → HTTP) consumingctx.credentialsfor secrets,ctx.sessionsfor durability barriers, and optionallyctx.schedule. - Agent plane: thin model-facing tools (
memory_sync_status/pull/push/configure) registered per-session, invoked by the skill's task-end routine. - Triggers: pull once at session start via a prepended
agent/pre-steplistener; push at task end; optional scheduled fallback. - Conflicts: Last-Write-Wins for whole files; append-merge for the L3 preferences file; sidecar files instead of data loss when unresolvable.
- Security: optional AES-256-GCM end-to-end encryption with keys resolved through
ctx.credentials(never visible to the model); whitelisted sync scope; size/rate limits. - Compat: the plugin is optional; without it the skill behaves exactly as today.
Milestones: M1 Git backend → M2 WebDAV/S3 + encryption + merge → M3 self-hosted HTTP server for team-shared project conventions.
设计文档 · memory-system · 与 DeepSeek 官方无关