dsh-workspace-relink:给搬过家的 DSH 工作区指条新路

前言

DSH(DeepSeek Harness)里一个工作区(workspace)是注册表里的一条记录,指向一个目录;一条会话归属哪个工作区,看的是会话不可变头部里记录的 cwd 规范形式。目录一旦移动,两边同时失效:工作区报 missing-dir,它列出的会话解析不到工作目录,工具调用全部失败。

而头部是只追加存储,没有现成的搬迁接口。的意思是:要让旧路径的「拼写」重新能解析到新位置,同时把工作区记录搬到新的规范路径上——也就是建立一个目录路由(Windows 上是 directory junction)。这是路由问题,不是改历史的问题。

下面介绍的 blankwy/dsh-workspace-relink 就是做这件事的客户端插件:搬目录,不重写任何会话历史。

这是什么

dsh-workspace-relink 由 blankwy 维护,分类为客户端,仓库当前星标为 0,许可证 MIT。它解决的问题是:项目目录挪走后,让旧工作区和旧会话继续可用,而不是让整段会话历史作废。

插件自己不搬文件、不删文件。你把文件移到新位置,它在旧位置建一个 junction,把工作区记录指向新路径,然后按注册表自带的 attach/detach 校验逐个移交会话归属,最后注销旧登记。

核心功能

路由式迁移,而不是改历史。迁移结果示意:

D:\A\B\C  ──►  moved by you to  ──►  D:\E\F\A\B\C
    │                                     │
    └── becomes a junction ───────────────┘
        (workspace record now lives here)

处理流程分三步:

  1. 你自己移动文件,插件不参与搬运。
  2. 在插件页面(Plugins → 工作区路由迁徙)用 修改位置 输入新路径,预览计划 会先检查新目录是否存在、旧路径是否空闲,并列出将要做的动作,写盘之前把阻塞项和警告说清楚。
  3. 点击 执行迁徙:在旧路径建 junction,在新规范路径创建或复用工作区,逐个会话走注册表的 attach/detach 校验转移归属,旧登记清空后再注销。

同一个页面还支持:把单条会话移到另一个工作区;查看本插件创建的路由及其目标存活状态;对记录在案的路由执行移除。

插件另有智能体工具,在 agentTools 未设为 false 时对模型可见,每个工具返回一行人类可读摘要加完整 JSON:

工具 用途
workspace_relink_status 列出工作区、路径、状态、会话数与已记录路由;includeSessions: true 时返回各会话的 id、标题、记录的 cwd、cwdState 与 live 标记
workspace_relink_plan 对单工作区改址做干跑
workspace_relink_apply 执行(需要 confirmed: true)
workspace_relink_move_session 把单条会话移入另一个工作区
workspace_relink_route_remove 移除一条已记录路由

安装与启用

README 与仓库内文档都没有给出安装命令,这里不拼接 dsh plugin add github:owner/repo。插件在目录页 skillhub.cn 有条目,可从目录页确认当前提供的安装或接入方式后再使用;仓库地址见文末。

已知环境要求:DSH >= 0.2.0,Node >= 20;在 Windows 上创建 junction 不需要管理员权限(fs.symlink(..., 'junction'))。web 端页面通过 dsh bundle 机制接入,配置见包内 cordis.patch.yml。

配置项只有两个:

键 默认值 含义
agentTools true 是否向模型暴露上表的工具;页面始终可用
allowSessionRoutes true 移动一条目录已不存在的会话时,是否允许创建路由

启用后从 Plugins → 工作区路由迁徙 打开页面。

典型用法

先移动目录(示例,Windows):

move D:\A\B\C D:\E\F\A\B\C

然后在页面上执行:

  1. 找到报 missing-dir 的工作区,点击 修改位置。
  2. 填入 D:\E\F\A\B\C,或按 浏览… 选择。
  3. 点 预览计划,确认没有阻塞项。
  4. 点 执行迁徙。

结束后旧路径 D:\A\B\C 是一个指向新目录的 junction,工作区记录位于新路径,历史会话原样保留、继续可用。

想跑插件自带的自测,在仓库根目录执行:

node scripts/selftest.mjs

自测针对一个模拟注册表运行,复现 DSH 的成员归属规则(realpath(header.cwd) 相等,加上缺 cwd 的通配情形),覆盖破坏态、plan、apply、路由复用、拒绝场景、残留目录搬移、单会话收养与路由移除;除临时目录外不写任何内容。

适用场景与注意

适合这类情况:目录已经挪走(或打算挪),但工作区里的会话历史不想丢、不想重开新会话。

使用前需要知道的限制:

  1. 新旧目录必须在同一台机器上可达,junction 是本地文件系统对象。
  2. 旧目录若没删干净(比如做了复制而不是移动),计划会被阻塞,直到你允许插件把它重命名为 <name>.moved-<timestamp>;插件不删除任何内容。
  3. 只有本插件记录的路由能被移除,且路径当前仍是 junction 时才允许;经该路由解析工作目录的会话会回到「目录缺失」的状态。
  4. 若某条会话记录的目录是另一个现存目录,插件拒绝把它改派到不匹配的工作区(DSH 自身也会拒绝),而不是静默 detach。
  5. 日志里没有 cwd 的会话会被标记为不可迁移,不会被猜测处理。

另外两点:插件以当前 DSH 进程的权限运行,安装前应检查源码与许可证;它只负责路由和归属转移,不改写会话历史。

路由记录写在 <DSH_HOME>/workspace-relink/routes.json(绝对路径、类型、id、时间戳)。它只是文件系统的索引,不是权威来源:手工建立的符号链接不会被碰,记录中链接已失效的路由只是如实汇报。

结尾

迁移工作区的关键是给旧路径留一条能解析的路由,而不是改写历史。blankwy/dsh-workspace-relink 把这两件事拆开处理得比较干净,功能边界和失败模式在 README 里也写清楚了。

  • 目录页:https://www.skillhub.cn/plugins/blankwy/dsh-workspace-relink
  • GitHub:https://github.com/blankwy/dsh-workspace-relink
羽毛球分组比赛记分
小程序二维码

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

小夜