DeepSeek Harness Hub
← 返回列表

多工作区合并LoserForLoser/dsh-workspace-merge

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

一次调用同步修改多个项目根目录下的同一文件

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/11 · 已提供中文文档
综合分
29.4
GitHub 分
29.4
用户评分
★ Stars
0
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add LoserForLoser/dsh-workspace-merge
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-workspace-merge(工作区合并)

一个会话,同时改多个项目。

DSH 会话只锚定一个工作目录——它同时是沙箱边界、工作区键和所有相对路径的基准。
这个默认在绝大多数场景是对的,但有一种很常见的布局会很别扭:同一产品的 PC 端与
移动端、必须保持同步的 iOS 与 鸿蒙 App、公共库与它的调用方。它们是兄弟目录,于是
"同一个文件两边都改"退化成绝对路径 + 反复调用,两边悄悄漂移。

本插件引入 工作区组(workspace group):一组有序的本地项目根目录,外加八个
ws_ 工具——把"一个相对路径 × 组内所有根目录"当作一次操作,并逐根目录给出结果,
而不是一个含糊的失败。

一次调用: ws_edit src/components/AmountInput.vue
│
┌───────────────────────┼───────────────────────┐
▼                       ▼                       ▼
[pc]  ecam-ui           [mobile] ecam-mobile     [shared] lib-ui
changed · 1 处替换       changed · 1 处替换        not-found

安装

dsh plugin add dsh-workspace-merge

手工安装:把包装到 $DSH_HOME/profiles/web,并在 dsh.profile.bundles 里列出
dsh-workspace-merge。

配置

一个组 = 名称 + 根目录列表。id 是其它工具使用的短标签,path 可为绝对路径或
~ 开头。

// ws_group_set {group:"ecam", description:"PC + 移动端", roots:[
//   {id:"pc",     path:"~/Desktop/JLXY/ecam-ui"},
//   {id:"mobile", path:"~/Desktop/JLXY/ecam-mobile-ui"}
// ]}

写入 $DSH_HOME/workspace-groups.json,纯 JSON,也可手工编辑。

组的选择:调用可显式传 group;否则用"根目录包含当前会话目录"的组(嵌套根目录
取最长匹配);无匹配时,若只定义了一个组则直接用它,否则必须显式指定名称。

工具

| 工具 | 作用 |
| --- | --- |
| ws_groups | 列出所有组、根目录 id,以及当前会话命中的组。 |
| ws_group_set / ws_group_remove | 维护注册表(绝不触碰项目文件)。 |
| ws_ls | 在各根目录下列出同一个相对目录——一次定位所有项目里的同一组件。 |
| ws_read | 从每个根目录读取同一相对路径并全部返回。 |
| ws_diff | 逐行对比各副本(第一个根目录为基线),改之前先看清差异。 |
| ws_edit | 把同一个字面替换应用到每个根目录,逐根给出结果。 |
| ws_write | 把同一份完整内容写到每个根目录——新建公共文件,或把副本强制同步。 |

ws_edit 沿用内置 edit 的匹配规则:old_string 必须唯一出现,除非设置
replace_all。ws_edit / ws_write 支持 dry_run 预览和 roots:["pc"] 收窄范围。
逐根状态是显式的——changed / unchanged / not-found / ambiguous / missing /
invalid / denied,部分成功可见,绝不静默。

沙箱行为

每次写入都先解析会话的 sandboxPolicy,本插件不会放宽它:

danger-full-access —— 不受围栏,与其它工具一致。
* workspace-write —— 目标路径先做规范化(不存在的文件会挂到最近的已存在祖先下重新
锚定,因此符号链接父目录无法把写入偷渡出去),必须落在策略的可写根之内。
* read-only —— 全部写入被拒。

越界目标会以官方标记 [sandbox: file access denied under … mode] 加升级提示被拒,
可用 sandbox_permissions + justification 重试一次——与内置 write/edit 完全一致。
组注册表(ws_group_set / ws_group_remove)同样受策略约束:只读会话无法悄悄改配置。

说明与限制

* 组不是 monorepo:它只改变 ws_ 工具的指向,不改变会话工作目录,因此内置
read/edit/write/bash 仍只以会话根为基准。当"一次改动必须落到多个项目"时用它。
写入走 harness 的文件系统服务(ctx.fs):写入前先通过官方 fs/observed 事件登记
版本,使文件观察策略下发 replaceIfVersion 而不是以 FS_NOT_OBSERVED 拒绝,同时
允许其它插件通过 fs/write-intent 拦截。该服务未挂载时改用 node:fs,但策略判定
已在前——并且结果会明说(via: node:fs (fs service failed: …)),集成问题
不会静默。
* ws_ls 跳过 .git / node_modules,每根目录最多输出 200 条路径。
* ws_diff 每侧最多对齐 4000 行,更大文件退化为体量摘要。

测试

npm test

31 条断言,基于一次性 DSH home 与两个一次性根目录:注册、注册表增删、组选择、
读/对比/列目录、dry-run、逐根变更状态、路径越界拒绝、root id 校验,以及沙箱用例
(danger-full-access、workspace-write 拒绝、read-only 拒绝、注册表写入策略)。

测试桩复现了两条曾让本插件在真实启动中整行回滚的 cordis 规则,并在回归时立即失败:

* 未在 inject 中声明的服务不是可读属性——ctx.systemPrompt 会抛错(而非返回
undefined),并把整行连同其已注册的工具一起悄悄带走;可选服务必须用 ctx.get(name) 读;
* 提示词位次由中枢分配——getSectionOrder() 对未知位次名返回 undefined,而 order 非
有限数会抛错。本插件使用 TOOLS_SDK 位次并带数字兜底。

启动诊断

WSM_DEBUG=1 会把启动各阶段(模块求值 → apply → tools 服务就绪 → 注册结果)写入
stderr 与 /dsh-workspace-merge-debug.log。当 row 已在合成树里、但会话中
看不到工具时,用它定位。

许可证

MIT © 宋朝阳

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群