dsh-github-sync:把 DSH 会话同步到私有 GitHub 仓

前言

DSH 本地部署没有云端存储:会话落在本机 $DSH_HOME/sessions/ 下,换个电脑就接不上。把会话文件拷给同事,附件、工作区路径都不对,还得手动改格式。dsh-github-sync 解决的是这个问题:把 DSH 会话连同引用的附件推到你自己的私有 GitHub 仓库,另一台机器拉下来就能继续聊。它的前提是你有 GitHub 账号和一个私有仓库,它不提供服务器、不提供账号体系。

下面介绍这个插件的定位、安装方式和日常用法。

这是什么

一句话定位:一个 DSH 插件,把本地会话与(可选)工作区文件夹同步到私有 GitHub 仓库,用于跨设备接力。

  • 名称:dsh-github-sync,版本 0.5.1,MIT 协议
  • 分类:记忆
  • 目录页归属:lifeng4127;package.json 中作者字段写作 mount9527,repository 字段指向 mount9527/dsh-github-sync。两者指向同一包名与同一份 README,安装时以仓库搜索结果为准。
  • 同步是纯手动的:不点不动,没有后台定时任务

核心功能

能力 说明
上传会话 勾选本地会话推上去,连带它引用的图片等附件;一批文件合成一个原子提交
下载会话 从远端拉回,改写头帧里的 cwd 到本机工作区,并注册进项目列表,不用重启就能继续聊
上传文件夹 默认关闭,设置里开启后可推 <项目>/files/
下载文件 默认关闭,开启后写回工作区,同名冲突另存副本,路径做了防穿越
agent 工具 提供 3 个工具,通过自然语言触发,先预览清单再执行

几个值得留意的机制,来自 README 的「关键实现」一节:

  1. 会话在磁盘上就是一个文件 session.v4.jsonl.zstd,所以不需要任何服务端。
  2. 改写 cwd 时只重压第一帧,后面的帧字节原样保留,否则会破坏 append-only 字节链,前缀合并失效。
  3. 冲突判定只比对头帧之后的 body:一方是另一方的前缀则落后方补上,互不为前缀则分叉,远端另存 *.remote-fork-*。
  4. 前缀判定不下载远端文件,靠 manifest.json 里记录的 body 长度与哈希做本地切片比对(README 给的例子是一条 2MB 会话的预览从 134 秒降到 5 秒)。

仓库结构:

README.md                        自动生成的项目/会话索引(每次上传重写)
manifest.json                    权威索引:会话 id → 路径、原始 cwd、sha、附件列表
<项目>/sessions/<id>.jsonl.zstd  会话文件本体
<项目>/attachments/<sha>.<ext>   会话引用到的附件
<项目>/files/<相对路径>           文件夹上传的内容

manifest.json 里的原始 cwd 是跨机还原的关键:下载时它会被改写成目标机器的工作区路径。

安装与启用

从插件市场安装:在 DSH 的「插件」里搜索 dsh-github-sync,安装后启用即可。

从本地目录安装(开发或自用):打开 DSH →「插件」→ 添加插件 → 本地目录,选这个文件夹;或者由 agent 调用 plugin_manager install_bundle,target 填绝对路径;或者在 profile 的 package.json 里加 "dsh-github-sync": "link:<路径>",并把它加进 dsh.profile.bundles。

装完左侧边栏出现「GitHub 同步」图标,点开是面板。

大陆网络下如果 npm 官方源很慢,用镜像装,注意镜像同步有几分钟到几小时的延迟:

npm install dsh-github-sync --registry=https://registry.npmmirror.com

客户端改动按 F5 刷新页面即可生效;宿主代码改动需要重载插件(重启 DSH,或在插件管理器里关掉再启用)。插件没有原生模块,Windows 和 macOS 跑同一份代码。

典型用法

首次配置

  1. 建一个空的私有仓。GitHub 新建仓库,不要勾 README、不要勾 .gitignore,选 Private。README 强调空仓库很重要:首次提交若仓库已有文件会多一次合并。
  2. 建一个 fine-grained PAT。打开 https://github.com/settings/tokens?type=beta → Generate new token,Repository access 选 Only select repositories 并只勾这一个仓,Contents 给 Read and write(勾选后会自动带上 Metadata Read-only),其它权限全部 No access。令牌只显示一次。
  3. 面板里填。右上角 ⚙ → 仓库地址(owner/repo 或完整 URL 都行)+ 访问令牌 → 测试连接。成功显示 连接正常 · owner/repo;报「仓库是公开的」要去 Settings 改成 Private;401 多半是令牌没粘全,404 是仓库名错或令牌没授权到这个仓。

没连上仓库时,面板顶部会出引导条,点「开始配置」进三步向导,每步带官方页面链接。需要更细的图文步骤(截图位置、常见错误对照、令牌轮换)看仓库里的 TUTORIAL.md。

上传与下载

面板分两栏:左边远端仓库,右边本地会话。所有写操作都必须先预览,预览会逐个文件标注 upload / skip / blocked / copy 与原因,确认后才真正执行。被 blocked 远端更新 挡住的行,行尾直接有「先下载」按钮。

每条会话右侧有同步徽标,由本地 body 哈希与远端索引对比得出:

徽标 含义
已同步 两边内容一致
本地更新 本地多聊了几轮,可以推
远端更新 远端更新过,应先下载
未上传 还没传过
活跃 最近 5 分钟内还在写,推上去的是快照

也可以直接用自然语言,插件会调 github_sync_transfer:

"把这条会话推到 GitHub"
"远端都有哪些会话"
"从远端把某某会话拉到这个工作区"

前者先 phase=preview 出清单,确认后再 phase=execute 带同一个 token 执行。

传输过程中有文件级进度条(形如 12/30 · 上传文件 · f12.bin),点左边的 ▸ 能展开看过每个文件 等待 / 传输中 / 完成 / 已跳过。每个还没开始传的文件都有「跳过」按钮,跳过附件会自动从 manifest.json 里摘掉对应引用。取消在文件之间生效,ref 不更新,仓库里不会留下半个提交。传输状态存在宿主进程里,面板切走再回来会自动重新接上进度条,没确认的预览也会恢复。

删除与冲突

删除两边互不影响:本机行尾的 🗑 只删本机会话并回收不再被引用的本地附件;远端行尾的 🗑 只删仓库里的会话并回收远端附件。两边都要点两次确认(4 秒内有效)。

两端都动过同一条会话时,预览会标 blocked 并给出三个选择:「先下载」「用本地覆盖远端」「用远端覆盖本地」。选覆盖会直接执行并重新预览。

适用场景与注意

适合:两台及以上设备之间接力同一个任务,或把某台机器上的会话交给同事接着干;前提是 GitHub 可达、有私有仓库。不适合:想要自动云端备份、多端实时同步、或者会话需要跨组织权限管理的情况——它完全手动,且每台机器上传前先合并远端索引,所以不会互相覆盖记录,但也意味着它不做实时冲突自动合并。

几点必须留意:

  • 插件以当前 DSH 进程权限运行,能写 $DSH_HOME、能访问当前工作区、能访问 GitHub API。安装前应读一遍源码,确认许可证(MIT)与依赖符合你的要求。
  • 默认只写四个位置:$DSH_HOME/github-sync/、$DSH_HOME/sessions/、$DSH_HOME/attachments/v1/objects/、当前工作区(文件夹/文件同步默认关闭,未开启时相关接口直接返回 403)。
  • 只允许私有仓,公开仓直接拒绝;.env*、*.key、*.pem、id_rsa、.npmrc、.netrc 等密钥类文件二次确认也传不上。
  • token 只存在宿主进程的 $DSH_HOME/.credentials.yaml,面板不回显;README 声明插件不启动子进程、不执行外部命令、不访问 GitHub 以外的域名,这些不变量由 tools/audit-safety.mjs 静态检查,发布前必跑。
  • 仓库会变大且 GitHub 不会自动清理旧 blob。会话在仓库里是固定路径,历史版本只占空间不影响使用;要真回收需要 git clone --mirror 后用 git filter-repo 重写历史,或重建空仓。按 README 的建议,主要用途是接力的话,一个项目一个仓比混在一起好清理。
  • 附件按会话引用上传,未被引用的附件不会上传;单个附件超过 25MB 会跳过并在预览里告警。插件只处理 version: 4 的会话格式。

结尾

dsh-github-sync 的价值很明确:把 DSH 本地会话变成可以跨设备搬运的普通文件,靠一个私有仓库和一串 fine-grained token 完成接力,没有额外的服务端。功能不算多,但上传前先预览、文件级跳过、取消不影响 ref、token 只在宿主进程这几件事,说明作者对「手动操作可能出错」这件事考虑得比较细。如果你本来就用 GitHub 管理私有仓库、也接受手动同步的节奏,可以试试。

目录页:https://www.skillhub.cn/plugins/lifeng4127/dsh-github-sync
GitHub:https://github.com/lifeng4127/dsh-github-sync

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜