dsh-session-sync
DeepSeek Harness(DSH)会话跨设备同步插件
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 20, 2026
- Updated
- Aug 20, 2026
Introduction
dsh-session-sync
中文 | English
DeepSeek Harness(DSH)会话跨设备同步插件:把本机产生的每一个会话镜像到中心 PostgreSQL 数据库,并按照可配置的间隔把其他设备上的会话拉回本机。换一台 电脑也能继续看到、恢复之前的所有对话。
核心痛点:DSH 默认把会话存成
~/.dsh/sessions/...下的本地文件,换一台 电脑就"找不到"了。本插件在不动本地存储的前提下,加一层双向同步,让会话 跟着你走。
功能特性
- 双向同步:本机会话定时推送到中心数据库;远端会话定时拉回本机。
- 增量传输:只同步游标(seq)之后的新事件,不重复传输整段会话。
- 最后写入胜出(LWW):同一事件在多台设备同时修改时,以
updated_at较新者为准,不会静默丢失数据。 - 显式工作区绑定:远端工作区在本地必须手动绑定目录才会被拉取, 绝不把别人的路径自动绑到你机器上的任意目录。
- 崩溃安全:本地状态文件原子写入(写临时文件 → fsync → 改名);同步游标 只在事务提交后前进;进程中途被杀不会产生半成品数据。
- 完全惰性:
enabled: false时不连接数据库、不调度定时器、不订阅任何事件。
交付形态:常规 npm 包(不是动态插件)
本插件以常规 npm 包方式加载到 profile 的 cordis.yml(与
@deepseek-ai/dsh-session、@deepseek-ai/dsh-llm 等内置插件同级),不是
动态的 cordis_define / cordis_run 插件。
为什么:动态 Cordis 插件的 Host 沙盒只暴露 ctx、harness、console、
btoa/atob、TextEncoder/TextDecoder(已通过 Builtin.listBuiltins
验证)。它无法 import pg 驱动、无法读取 process.env、无法使用
node:fs —— 而这三者正是本插件的硬依赖(Postgres 连接、DSH_HOME 解析、
state.json 原子写入)。常规包插件拥有完整的 Node 能力,所以本插件必须
以此形态交付。
安装
1. 打包
# 在本仓库目录
pnpm install
pnpm pack # 生成 dsh-session-sync-0.1.0.tgz
2. 安装到 DSH profile
# 以 web profile 为例(其他 profile 同理)
cd ~/.dsh/profiles
pnpm add /path/to/dsh-session-sync-0.1.0.tgz # 装到 profiles/node_modules
3. 注册插件行
在 ~/.dsh/profiles/<profile>/cordis.patch.yml 中加入:
- insert:
- id: session-sync
name: 'dsh-session-sync'
config:
enabled: true
# Postgres 账号密码方式访问(独立字段,不用连接 URL)
pgHost: 'db.example.com'
pgPort: 5432
pgDatabase: 'dsh'
pgUser: 'dsh_app'
pgPassword: 's3cret'
pgSchema: 'public' # 数据库 schema(默认 public,可指定如 'dsh')
intervalMs: 30000 # 同步间隔,毫秒(默认 30000)
batchSize: 200 # 每批同步的事件数(默认 200)
syncScope: 'mine' # 'mine' = 只拉本设备;'all' = 拉取所有设备
重启 DSH 后生效。
enabled: false(默认值)时插件完全惰性:不连接数据库、不调度定时器、 不订阅事件。
配置项说明
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | false | 是否启用;false 时插件完全惰性 |
pgHost | string | 无 | Postgres 主机,启用时必填 |
pgPort | number | 5432 | Postgres 端口(范围 1–65535) |
pgDatabase | string | 无 | 数据库名,启用时必填 |
pgUser | string | 无 | 用户名,启用时必填 |
pgPassword | string | 无 | 密码,启用时必填 |
pgSchema | string | 'public' | 数据库 schema(必须是裸 SQL 标识符,如 public、dsh) |
intervalMs | number | 30000 | 同步周期(范围 1000–3600000) |
batchSize | number | 200 | 每批事件数(范围 1–2000) |
syncScope | 'mine' | 'all' | 'mine' | 'mine' 只同步本设备的工作区;'all' 拉取所有设备(计划 M2) |
deviceId | string | 自动生成 | 本机设备标识(UUIDv4),首次运行时写入 state.json |
工作方式
┌───────────────────────── 本地 DSH 进程 ─────────────────────────┐
│ │
│ 会话运行时 ─emit─> session/event ─listen─> 本地 JSONL.zstd │
│ │ │
│ └──listen──> SyncPlugin │
│ │ │
│ 定时器 (intervalMs) ◄─────── 本地同步状态文件 ────┘ │
│ │ │
│ ├── push: 本地未推送事件 ──> 中心 Postgres │
│ └── pull: 中心 Postgres 新事件 ──> 本地 JSONL │
└──────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────┐
│ PostgreSQL 数据库 │
│ - workspaces │
│ - session_headers │
│ - session_events │
└─────────────────────┘
同步流程(每个周期)
- push:扫描本机事件监听器记录的新事件,把 header 与新事件批量写入 Postgres(幂等,LWW 冲突处理),成功后推进本地游标。
- pull:读取云端 workspace 列表,只对本地已绑定的 workspace 拉取
新事件,追加到本地 JSONL(通过
sessionPersistence.append),成功后推进 游标。
工作区绑定(重要)
- 本地新工作区:首次出现在本机时自动注册为
bound。 - 远端工作区:在本机没有目录绑定时绝不会被拉取;它会出现在待绑定 列表里,等你手动指定本地目录后才开始同步。
- 绑定失效:本地绑定目录被删除后,工作区状态切换为
orphaned,提示你 重新绑定。 - 解绑:手动解绑后,本地映射保留并标记为
unbound(界面可显示"已解绑"), 重新绑定时复用同一个工作区 UUID。
同步预设(preset)
每个会话与其 agent 预设绑定。恢复会话时如果本地缺少该预设,DSH 会抛
UnknownPresetError 使恢复硬失败。因此:
- MVP:引用本地缺失预设的会话照常拉取(可只读查看),并记录 WARN 标注 "可读不可续"。
- M2(规划):预设定义随会话一起入云(
preset_definitions表),本地缺 预设时自动拉取并写回${DSH_HOME}/.agent-presets/<id>/,恢复不再失败。
客户端 UI(MVP 为占位)
./client 子路径导出(dsh-session-sync/client)是客户端插件。当前为 MVP
占位(no-op 桩),渲染辅助函数已就绪;真实的面板 Slot 注册需要在一个真实
运行的 DSH 会话中选定 Slot 键后完成(详见计划文档 Task 12)。
开发与测试
pnpm install
pnpm test # 全量测试(Postgres 集成测试需要 Docker)
提示:本机
~/.docker/config.json可能带有 Windows 风格的credsStore(会破坏 Linux 上的 testcontainers)。若遇到 Docker 报错, 可用干净的配置覆盖:DOCKER_CONFIG=/tmp/dsh-docker-config pnpm test
测试结构:
- 单元测试:状态文件、设置校验、事件监听器、渲染辅助。
- 集成测试:PostgresBackend、Push/Pull 引擎、工作区绑定状态机、 LWW 冲突(用 testcontainers 起真实 Postgres)。
- 端到端测试:设备 A 推送 → 设备 B 绑定 → 设备 B 拉取,验证完整闭环。
路线图
| 阶段 | 内容 |
|---|---|
| MVP(已完成) | PostgresBackend + 迁移 + Push/Pull 引擎 + 显式绑定 + 设置 + 状态文件;syncScope: 'mine' |
| M2 | syncScope: 'all' + 面板完整目录选择交互 + 状态恢复加固 + 预设同步 |
| M3 | testcontainers 集成套件全覆盖(引擎 + LWW + 绑定状态机) |
| M4 | 客户端同步状态条("Last sync: xxx") |
| 未来 | 服务端全文搜索,跨会话检索 |
相关文档
- 设计文档:
docs/superpowers/specs/2026-08-20-dsh-session-sync-design.md - 实施计划:
docs/superpowers/plans/2026-08-20-dsh-session-sync.md