DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

wedfrgt /

wedfrgt/dsh-workspace-sync

Verified

This plugin has no description yet.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@23f2b0a5

dsh-workspace-sync

Share DSH sessions between machines (Windows ⇄ macOS) through a private git repository. A conversation started on one machine shows up on the other, grouped under the same workspace, and can be continued there — while the repository itself never contains a machine-specific path.

  • Sessions are the only thing that syncs. The repository holds session logs plus three metadata files (manifest.json, workspaces.json, devices/); a test asserts nothing else can appear in it.
  • Identity is explicit: a session's header carries dsh-workspace-sync://<workspaceId>, and each machine keeps its own workspaceId → local path mapping. When an incoming workspace has no counterpart here, the plugin asks (pick a local directory, place it in a default workspace, or ignore it) instead of writing to your disk on its own.
  • Adoption rewrites only the first frame's cwd (byte-surgical); the rest of the log is copied byte-identically.
  • Deletion propagation is bounded twice over: it needs the committed state to be fully adopted locally, and a session this machine did not create is never deleted by it.
  • Configured in a runtime-live settings page (native DSH UI components); the /wssync status|pull|push|map commands do the same from the terminal.

跨设备共享 DSH 会话(Windows ⇄ macOS)。一台机器上的对话,在另一台上能看到、归到同一个工作区分组、并且能接着聊——同时同步仓库里不出现任何机器相关的路径。

内核经过实测验证:git 传输、append-only 三方合并、keep-both 冲突保留、绝不 force-push、确认门、错误文本脱敏。


它解决什么

问题 这一版的做法
仓库里带着 D:/code/Article、/Users/x/… 这类机器路径 仓库里的会话 header 写成可移植标记 dsh-workspace-sync://<workspaceId>;真实路径只留在各机本地的映射表里
对端拉过来的会话在本机"看得到但不在工作区分组里" 采纳时只做帧级手术把 header 的 cwd 换成本机路径(只重压第一帧,正文逐字节不动),再挂进本机工作区
每台机器的路径不同,不知道怎么对应 自动映射:本机已有映射 → 对端路径在本机真实存在 → 根重映射 → 按名字在本机找到同名目录。都对不上时停下来问你:指定一个本机目录、放到默认工作区(~/.dsh/workspaces/<名字>),或者忽略这个工作区
一台机器删会话会把另一台的一起删掉 删除传播要求提交态已全部并入本机(水位 == HEAD),且本机自有会话绝不被对端删除
配置是一行 21 键的 YAML 图形设置页,同步方式/时间/工作区映射改完立即生效

安装

dsh plugin --profile desktop add link:/path/to/dsh-workspace-sync

仓库里声明了 dsh.bundle(cordis.patch.yml),所以 dsh plugin add 会自己把插件行挂进 profile,不必手写 patch;从市场安装时还会直接用预构建的 tgz,不需要构建授权。

想手写或覆写那一行时(id 覆写会替换整行,所以要的键都要写全):

- id: workspace-sync
  name: dsh-workspace-sync
  config:
    remote: git@github.com:you/your-sessions.git
    branch: main
    authMode: ssh
    syncMode: manual

认证三种模式

authMode 做法 适用
ssh(默认) 沿用本机既有的 git/ssh 配置(密钥、~/.ssh/config、代理隧道) 已经配好 SSH 的机器
token 从 DSH 凭据库取令牌,经 GIT_ASKPASS 喂给 git。配置里只存引用名;令牌不进 YAML、不进 remote URL、不进 argv、也不进磁盘上的脚本(只经子进程环境传递) 想省事的新机器(尤其 Windows)
system 完全交给系统 git 的凭据助手,插件不碰凭据 环境已经配好

token 模式先存令牌:

# 值存在 ~/.dsh/.credentials.yaml(0600),配置里只引用它的名字
# 名称与 config.tokenRef 一致,默认 DSH_GIT_TOKEN

命令与工具

/wssync status   镜像状态、工作区落位、领先/落后(只读)
/wssync map      列出工作区映射与待确认项
/wssync pull     拉取对端会话、合并、落到本机工作区
/wssync push     镜像本机会话、提交、推送(绝不强推)

模型侧工具同名:wssync_status / wssync_map / wssync_pull / wssync_push。


设置页

Settings → 工作区同步(运行期即时生效):

  • 同步方式:仅手动 / 启动时拉取 / 每轮结束推送 / 定时拉取(间隔可调)
  • 仓库:远端、分支、认证方式、凭据引用名
  • 状态:本机 head、远端 head、领先/落后、是否已全部采纳、上次拉/推时间、问题
  • 工作区映射表:共享名、本机路径、来源、会话数、对端路径;可移除映射
  • 待确认:给每个共享工作区选定本机目录(可点候选,也可手填)

本机路径(会话库 / 同步工作树 / 默认工作区)可直接编辑——它们决定仓库位置,属于需要 重启的改动,请在 profile patch 里设置。


语义细节(值得知道的)

  • 删除会传播,但要求"提交态已全部并入本机"。水位对不上时镜像只补不删—— 这条闸门挡掉的是最坏的一种失败:迁移完(或刚克隆完)本机库是空的,第一次镜像就 把仓库里的会话全删掉。
  • 本机自有的会话绝不被对端的缺失删除(在 manifest 里出现过的才算"曾同步过")。
  • 真分歧两边都保留:本机版本留在原路径,对端版本写成 <文件名>.remote-fork-<14位时间戳>-<短设备id>,永不自动清理(有专门的测试钉住 这条不变量:就算你后来把那个会话删了,fork 文件仍然留着)。
  • 纯追加不算冲突:本机字节是提交态前缀时直接采纳对端,不会制造假冲突。
  • flock 租约与迁移暂存文件(session.lock / session.migration.*.tmp)不参与同步 ——它们是运行时状态,同步它们只会把某台机器的瞬时状态变成另一侧的噪音。

测试

系统里没有 node,用 Electron 的 node:

ELECTRON_RUN_AS_NODE=1 "/Applications/DSH Desktop.app/Contents/MacOS/DSH Desktop" \
  --test --test-timeout=90000 test/*.test.mjs

323 个测试,其中十四组跑真实数据 / 完整插件入口 / 真实设置页 / 真实 git 冲突 / 并发推送 / 真实数据端到端彩排 / 真实 git 安全边界 / 无 node_modules 加载:

  • realdata.test.mjs —— 用本机会话库里的每个真实会话验证"只改第一帧、其余逐字节不变";
  • hostkey.test.mjs —— 用真实会话库核对 projectKey / encodeSegment 的复刻与宿主一致;
  • e2e-sync.test.mjs —— 两台设备经真 bare 远端跑通推/拉/落位/本地化/续写/删除传播;
  • migrate.test.mjs —— 迁移的计划/执行/对账,以及迁移后的仓库能被引擎原地接上且第一次 push 不会删掉迁移来的会话;
  • plugin-wiring.test.mjs / two-device-wiring.test.mjs —— 在保真宿主仿真里真的执行 apply():两台机器各自装配插件、经真 bare 远端互通,并用一个照宿主真实约束实现的 workspace 注册表校验挂载(本地化写错了它会拒绝挂载);
  • auto-modes.test.mjs —— 真的分发 turn/end / 配置重载事件,断言自动同步确实发生;
  • settings-page.test.mjs —— 用一个小型 React 渲染器渲染真实客户端 bundle,点按钮, 把产生的 RPC 喂给宿主真实的处理器,断言仓库/映射真的变了;
  • cross-platform.test.mjs —— Windows ⇄ macOS 双向同步:Windows 端用一份会翻译盘符的 探针,路径逻辑全跑真实的 D:\... 字符串(文件 I/O 重定向到沙箱)。验的是:双向同步、 cwd 按机器本地化、同一工作区在两台机器上共享同一个身份 id、每台机器每个会话只有一份 日志、采纳后能挂进工作区、仓库里不含任何机器路径;
  • tools-contract.test.mjs —— 工具描述与真实 ctx.tools 的契约(5 项):形状静态锁 (input.schema、execute()、必填的 output、对象级 required 必须是数组),以及把 四个描述注册到真实 tools 服务上必须全部被接受。这一组是为一次真实事故写的:工具描述 缺 output 会让 register 抛错,而 apply() 抛出会让 cordis 回滚整个插件—— 连设置页的 RPC 路由一起消失,前端只看到 HTTP 405;
  • rungit.test.mjs —— git runner 与 ctx.subprocess 的对接(9 项):文本走 readFrom、 二进制走 snapshot()、二进制用独立的大上限、截断响亮报错、超时真的终止进程、 外部中止转成可读错误、可执行文件解析失败抛错、认证环境每次现取。这一组是用真实宿主 服务的语义写的(收集模式没有 handle.stdout、readFrom 只给 utf8),此前那三个 装配测试的替身在这三处撒谎,正好掩盖了"二进制读取被截断"的真 bug;
  • packaging.test.mjs —— 打包与依赖解析:每个外部 import 都已声明、声明的都真被用、 files 覆盖运行时全部路径、客户端 bundle 的 exports 形状与 dsh.client.platform; 以及动态证明——把插件拷到不含 node_modules 的目录、用模拟宿主 profile 解析器的 loader hook 加载,全部模块仍然成功(所以 link 安装不需要 pnpm install);
  • git-safety.test.mjs —— 安全边界:动词白名单(15 个,含"就是这 15 个"的闸门)、 强推的各种写法被拒、commit --amend 被拒;以及事实层面的证明——一次真实的非快进推送 被拒后远端引用一动不动,调和重推后远端历史只前进、两条历史都在;
  • realdata-migration.test.mjs —— 用本机真实存在的旧仓库跑完整流程(数量按实际存在的算, 仓库被清空时该测试自动跳过):拷贝 → 迁移 → 推到 bare 远端 → 一台空会话库的机器全部拉取(每个都用保真注册表校验 cwd 真能挂进工作区) → 正文逐字节一致 → 再推一次不删任何东西。真实数据里带着合成 fixture 没有的东西:v3 与 v4 并存的会话、子会话、Windows 盘符路径、遗留的 fork 文件;
  • push-retry.test.mjs —— 并发推送:push 被拒后自动调和并重推(这条分支在其余所有 测试里都不会走到,因为首次推送总是成功);同一会话两侧都改过时对端版本留成 fork 文件; 反复交替推拉多轮后会话集合收敛、一条不丢;
  • merge.test.mjs / merge-git.test.mjs —— 冲突解决的语义与真实 git 冲突: 双边追加留 fork、对端删除+本机改过保留本机(上游 abort 缺陷的回归锁)、本机删除+ 对端改过采纳对端,并断言每次之后工作树干净、没有留下进行中的合并。

许可

Apache-2.0。传输与合并内核继承自上游 dsh-session-sync(作者 PerryLink)及其 fork dsh-session-share;本仓库的数据模型(可移植工作区标识)、配置面与设置页是重写的部分。 保留这段署名是许可证(以及诚实)的要求,删掉它会让本仓库变成一份没有出处的衍生作品。

—/ 5

No ratings yet

Verified DSH bundle

Commit 23f2b0a540e4

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout