我同时用好几个工作区:一个写代码,一个做运维文档,一个整理简历。每个工作区需要的能力不一样,但 DSH 默认会把所有插件和技能都加载进来。于是我想:能不能做一个插件,按工作区决定哪些插件和技能可用?

这就是 dsh-workspace-gate。

它解决什么问题

  • 写代码的工作区不需要简历工具,整理简历的工作区不需要服务器管理工具
  • 技能太多会污染上下文,模型容易选错
  • 我希望「换工作区 = 换一套工具」,而不是所有工具永远在线

实现思路

DSH 的插件由 cordis 加载器管理。dsh-workspace-gate 的做法是:

  1. arm(布防):切换到某个工作区时,记录当前工作区 ID
  2. applyGating(应用门控):遍历 loader.entries(),对不该在这个工作区出现的插件调用 loader.update(entry.id, {disabled: true})
  3. release(解除):离开工作区时,把「本插件关掉的」重新打开(配置里本来就关的不会被误开)
  4. protect(保护名单):dsh-base、dsh-web-app、workspace-gate 本身永远不被关

关键设计:它是运行时控制,不写 cordis.patch.yml。也就是说,门控状态是临时的、可逆的,不会污染你的配置文件。

一个意外的发现

我原本以为「技能开关」也能实时控制。查了源码才发现不是:

  • 文件型技能(~/.dsh/skills/ 下的):调 set-enabled,会写 disable-model-invocation frontmatter,真的关掉了
  • 插件自带技能:调 set-provider-enabled,只写 ~/.dsh/dsh-skill-explorer/provider-toggles.json,只改面板显示,模型仍然可能调用

上游的原话是:「It is a PANEL-LOCAL decision: the host registry still loads the skill」。

这个区别很重要:如果你以为关了技能就不占上下文,对插件自带技能来说是错的。

测试

我在本地写了 5 个测试脚本、36 个断言,覆盖:

  • 状态文件读写
  • 过滤逻辑(含重复行、空行)
  • 客户端面板 smoke test
  • 技能浏览器集成

全部通过。但要说实话:这些测试是「逻辑正确性」测试,不是「真实使用场景」测试。真实场景里切换工作区、多个 agent 同时运行、技能冲突,还需要更多验证。

上架

代码已经推到 GitHub:CyberYui/dsh-workspace-gate(MIT)。接下来准备提交到 DSH 市场。

如果你也在管多个工作区,可以试试。也欢迎提 issue —— 这个插件还年轻,边界情况肯定还有。

教训

  • 做 DSH 插件,得先读懂 loader 的生命周期,光写业务逻辑不够。
  • 「关掉」和「看起来关掉了」是两回事,尤其是技能系统。
  • 测试要分清「逻辑正确」和「场景正确」,前者通过不代表后者没问题。
  • 开源是最好的文档。把踩过的坑写进 README,能省掉后面一堆 issue。