前言¶
在 DeepSeek Harness(DSH)里,智能体通过 write 工具在工作区创建或更新文件。Windows 上 @deepseek-ai/dsh-fs-local 对新文件的发布路径会使用硬链接:把暂存目录里的临时文件硬链到目标路径,同时充当「不覆盖已存在文件」的守卫。若工作区落在 exFAT、FAT32(常见 U 盘、移动硬盘)或部分不支持硬链接的网络共享上,该 link 调用会被拒绝;Node 往往把错误报成 EISDIR,而不是更直观的 ENOTSUP/EPERM。结果是:新建文件每次都会失败,而更新已有文件仍走 rename/ReplaceFileW,看起来「能改不能建」,排查成本高。下面介绍社区插件 dsh-hardlink-publish-fallback 如何在不改默认行为的前提下,仅在识别到这类硬链接发布失败时做一次性兜底。
这是什么¶
dsh-hardlink-publish-fallback 由维护者 Mushroomcowisheggs 发布,仓库见 GitHub,目录页见 SkillHub。它以 DSH bundle 形式注入配置层(cordis.patch.yml),在 write 因「卷不支持硬链接发布」而失败时,在严格检测通过后改用卷已支持的 rename 路径完成新建(与更新文件时相同的路径),并记录与正常成功写入一致的 observation。未触发该失败签名的写入完全不受影响。
背景:失败长什么样¶
在不支持硬链接的卷上,典型错误类似:
cannot write "<workspace>\<file>": EISDIR: illegal operation on a directory,
link '<workspace>\.<file>.<pid>.<uuid>.tmpdir\<file>.tmp' -> '<workspace>\<file>'
调用方「仅在目标不存在时创建」的意图从未被满足,因此在该工作区上所有新建尝试都会永久失败。同一类卷通常也不支持符号链接;dsh-app-boot 的 healProfilesModuleFallback 会在组合时用符号链接把安装链到 profile,因此 DSH_HOME 不能放在无符号链接能力的文件系统上——本插件不解决 profile 无法启动的问题,只解决 write 新建文件的硬链接发布失败。
核心功能¶
插件行为可概括为四步(资料中的设计说明):
- 先让真实的
write原样执行。 - 仅当失败消息同时带有
.tmpdir暂存标记和link动词、且属于FS_IO_ERROR的硬链接发布特征时,再次确认目标仍不存在,然后用无「禁止替换」守卫的 intent-free 写入完成发布(rename 路径)。 - 写入成功后记录与正常
write相同的 observation。 - 兜底链路中任一步失败,则向调用方返回原始错误,不掩盖其它问题。
检测是严格的:无关的 EISDIR(例如目标是目录、路径组件错误)不会被拦截。默认行为不被修改——成功的写入不会进入兜底,也不会替换已有服务或覆盖已有配置行。
安装与启用¶
从 GitHub 安装时建议固定 tag 或 commit;不指定 ref 时,pnpm 会随默认分支当前指向变化,后续推送可能静默改变本机实际运行的代码:
dsh plugin --profile web add "github:Mushroomcowisheggs/dsh-hardlink-publish-fallback#v0.1.0"
# 更强:固定 40 位 commit
dsh plugin --profile web add "github:Mushroomcowisheggs/dsh-hardlink-publish-fallback#<40-char-sha>"
该包为纯 JavaScript,无 prepare/构建脚本,一般不需要在 profile 的 pnpm-workspace.yaml 里为 allowBuilds 单独授权(若未来版本增加构建步骤,则需按 DSH 文档处理 git 依赖构建)。
从本地目录或 tarball 安装时,路径务必用双引号包住(Windows 下未加引号时 \d、\t 等会被当作转义):
dsh plugin --profile web add "<path-to-checkout>"
pnpm pack
dsh plugin --profile web add "<path-to-checkout>\dsh-hardlink-publish-fallback-0.1.0.tgz"
dsh plugin add 会因包内声明的 dsh.bundle 自动把 bundle 追加到 profile 的 dsh.profile.bundles。
验证是否加载:
dsh --profile web --dump-config # 查找 "# == dsh-hardlink-publish-fallback"
典型用法与验证¶
在受影响的卷上打开工作区,让智能体创建一个新文件。未装插件时应出现上文 EISDIR/link 错误;安装并加载后,应像常一样报告 Created file。维护者在固定 exFAT 卷、从发布 tag 安装的场景下确认过:新建文件、在需先建目录的路径下新建、对同一文件连续第二次写入且无中间 read、以及无暂存残留;经本插件创建的文件 observation 与正常写入一致,后续行为与其它文件相同。
仓库内可用以下命令跑行为测试(无需真实 exFAT 卷):
npm test # 或: node test/plugin.test.mjs
适用场景与注意¶
适合谁: 在 exFAT/FAT32 或可移动介质、部分网络共享上跑 DSH,且主要痛点是 agent write 无法新建文件、但编辑已有文件正常时,可在对应 profile 安装本插件作为运行时 workaround。
范围与限制(以 README 为准):
- 只修复新建;更新与
edit本就不走硬链接路径,插件不拦截。 - 逻辑按失败签名识别,不限于 Windows;任何拒绝
link()且错误形态相同的 POSIX 文件系统也可能受益。 - 不能靠本插件在 Windows 盘符根目录直接新建文件:
writeFileAtomic在根上mkdir会EPERM,属于另一缺陷;请写到子目录。 - 不能替代上游修复
dsh-fs-local发布逻辑;详细分析见仓库内DEFECT-REPORT.md。 - 兜底前会再次检查目标不存在,与原始
writeText一样存在有限的 TOCTOU 窗口;仍保留「不静默覆盖竞态创建者」的语义。
安全与信任: 插件随当前 DSH 进程权限运行,会介入文件写入路径。安装前请阅读 源码与 MIT 许可证,自行评估是否纳入 profile。SkillHub 等为社区目录,与 DeepSeek / 幻方无官方从属关系;DSH 生态强调「一切皆插件」,选用第三方 bundle 需自行 pinning 与审计。
结尾¶
dsh-hardlink-publish-fallback 针对「不支持硬链接发布的新文件 write」做窄范围兜底:默认路径不变,仅在识别到硬链接失败且目标仍缺失时改用 rename 完成创建。若你的工作区常落在 exFAT 等卷上,可固定版本安装并在 --dump-config 中确认 bundle 已加载。更多信息见 SkillHub 目录页 与 GitHub 仓库。