dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
按工作区门控插件:把选定插件的工具 schema 与系统提示词段,从不需要它们的目录的模型上下文中摘掉。
简体中文 | English
插件照常加载,但按工作区把它不该占的提示词前缀摘掉——工具 schema 与提示词段都不再进模型上下文。
一个 DeepSeek Harness(dsh)插件。
它让"要不要让模型看见某个插件"从全局下沉到工作区:插件依然全部加载、功能随时可用, 但在你指定的目录下,它的工具 JSON schema 和系统提示词段不再出现在每一次请求里。 省下的是每轮请求的输入 token,而不是插件的加载开销。
DSH 自带的插件管理只有 全局 开关:一个插件要么对所有工作区都开,要么都关。
但插件对 prompt 的成本是每轮都付的——只要它启用了,它的工具 JSON schema 和 系统提示词段就会出现在每一次请求里,哪怕这次对话完全用不到它。
典型场景:
本插件把"要不要让模型看见"从全局下沉到工作区,不动全局开关、不重启、不重载插件。
| 做 | 不做 |
|---|---|
| 按目录(含子目录继承)决定哪些工具/段不进 prompt | ❌ 不安装/卸载/升级插件 |
| 组级开关 + 展开到单个工具名/段名 | ❌ 不改变插件的全局启用状态 |
| 按来源分档:第三方 / 自定义 / 官方 / 官方可选包 | ❌ 不能把全局已停用的插件"变出来"(只减不加) |
| 自动归属推断 + 静态扫包 + 手工归属 | ❌ 不回溯已开会话(前缀已经发出去了) |
| fail-open:任何异常都当作"没配置" | ❌ 不碰 sandbox / approval 策略 |
D:\Projects 配一次,
D:\Projects\api 就继承)。ctx.tools.restrict(),它只能移除,不会新增能力。availability 判断"随 dsh 安装"还是"用户自装",
第三方档默认展开,官方档默认收起。workspace_gate 工具支持 status / list / set。--dsw-alias-* 主题 token。lib/policy.mjs,24 条单测,不启动 DSH 也能跑。插件管理页会多出一个 「按工作区」 页签:
插件照常加载;勾掉的插件,它的工具与提示词段不再进入这个目录的请求。
存储: ~/.dsh/data/workspace-gate.json [重新扫描]
工作区 (default-workspace) (my-project ●) (+ 添加目录)
C:\work\my-project · 跟随全局 · 已关 1 组 · 共 9 组
插件组 [筛选…]
› 第三方 2 ≈ 2.7k
[网] web-search-free [9 工具][1 段] ≈2.7k › ●
› 自定义分组 1
› 官方 7 ≈ 17.8k
› 官方可选包 1
› 未归属 27
› 展开后可以只勾单个工具/段,右侧下拉可以改它的归属;本插件是标准 DSH bundle(package.json 里声明 dsh.bundle.patch)。
三种装法,推荐顺序从上往下;装好后都会在插件管理页出现「工作区插件门控」这一行。
已发布到 npm:
dsh-workspace-gate@0.1.1。 能访问 npm 的机器可以直接dsh plugin --profile <your-profile> add dsh-workspace-gate@0.1.1,不必走 GitHub。
版本要求:
engines.dsh = ^0.2.1-rc.2。比这更老的 DSH 会被插件管理器直接拒绝安装, 而不是装上以后在运行期报错。
新开一个会话,把这句话发给助手:
帮我安装这个 DSH 插件:
github:M1r0er/dsh-workspace-gate
助手会调用 plugin_manager 完成「pnpm 安装 → 选中 bundle → 激活」整条链路,最后告诉你
application: applied。然后刷新页面即可。
plugin_manager 工具。DSH 默认只在 Creator 模式下启用它,
其它预设默认关闭;如果助手说没有这个工具,切到 Creator 再试,或改用方式 2。github:M1r0er/dsh-workspace-gate
(也可以填你本地 clone 的绝对路径);dsh-workspace-gate 即装好,刷新页面;# A. 用 dsh CLI(profile 不是 Desktop 时)
dsh plugin --profile <your-profile> add github:M1r0er/dsh-workspace-gate
# B. 直接进 profile 目录用 pnpm
cd ~/.dsh/profiles/<your-profile>
pnpm add github:M1r0er/dsh-workspace-gate
# C. 本地目录(开发/调试)
git clone https://github.com/M1r0er/dsh-workspace-gate.git
pnpm add link:<克隆下来的绝对路径>
# D. 从 npm(0.1.1 起可用)
dsh plugin --profile <your-profile> add dsh-workspace-gate@0.1.1
--profile <name>决定改哪个 profile 目录:--profile web改的是~/.dsh/profiles/web, 而桌面版 GUI 跑的是desktopprofile —— 装进web,桌面窗口里看不到,两个 profile 的 依赖和dsh.profile.bundles互相独立。要装进桌面版,请用它自己的插件页 (npm 版 CLI 会拒绝管理desktop)。
⚠️ pnpm 只装依赖,不会把包写进
dsh.profile.bundles。 少这一步插件不会加载。装完必须再做一件事:
- 打开 Web 插件页,把
dsh-workspace-gate这个 bundle 打开;或- 手工在
~/.dsh/profiles/<profile>/package.json的dsh.profile.bundles数组末尾加"dsh-workspace-gate"。然后重启 DSH(没有 HMR 时)才会加载。
装好后:关掉插件管理页里「工作区插件门控」这一行 = 门控整体不生效,行为回到未安装状态(fail-open)。
| 现象 | 原因 / 处理 |
|---|---|
| 装完插件页没有这一行 | bundle 没被选中:按方式 3 的提示把它加进 dsh.profile.bundles |
返回 already-installed | 同 spec 已装过;先在插件页 Remove 再装 |
| 桌面版提示 CLI 不接管 | Desktop profile 由 Electron 托管,npm CLI 会拒绝管理它;请用 Web 插件页 |
| 安装卡在 build scripts | pnpm 11 默认拦截安装脚本;在弹窗里批准后重试 |
| 想在插件市场里搜到 | 仓库已打 dsh-plugin topic,但要在市场出现还需被 awesome-dsh-plugin 索引收录(提交 PR) |
插件管理 → 「按工作区」→ 选目录 → 关掉不需要的组 → 保存。对新会话生效。
workspace_gate(action:"status") # 最近哪些会话命中了哪个目录、摘掉了什么
workspace_gate(action:"list") # 可门控的插件 → 工具名/段名
workspace_gate(action:"set", dir:"D:\\Projects\\api",
hide:["plugin:r18-novel"]) # 需要显式给 dir
workspace_gate(action:"set", dir:"D:\\Projects",
show:["tool:read"]) # 从隐藏清单移除
这个工具没有用
deferLoading:实测打开后子会话里它直接不可见,模型想调也调不到。
两种写法等价(dir 必须是绝对路径,子目录会继承):
plugin:<分组 id>tool:<工具名> / section:<段名>DSH 运行时不记录某个工具是哪个插件注册的(tools.register() 只按名字存),
所以"按插件勾选"只能推断。本插件按强度依次尝试:
| 顺序 | 手段 | 说明 | 可靠度 |
|---|---|---|---|
| 1 | 段名命名空间 | r18-novel:protocol → r18-novel,与插件 id/包名归一后比较 | 高(约定) |
| 2 | 工具名前缀 | 工具名 token 与插件 id 或包名 token 的前导全等匹配 | 中高 |
| 3 | 静态扫包 | 读包入口(第三方递归扫 .js)里的 name: 'x' 定义位,与未归属工具名求交,只在唯一命中时采纳 | 较高 |
| 4 | 手工归属 | 界面里自己指定,赢过以上全部 | 最高 |
静态扫包解决的是这类情况:dsh-free-search 的 profile 行 id 是 web-search-free,
而它注册的 platform_search / video_search / weather 等名字里根本不含包名——
只靠前缀只能认出 1/9,扫包之后 9 个全部归位。
硬边界:官方内置包在 app.asar 里,磁盘上没有目录,扫不到;运行时动态注册的工具
(没有对应文件插件)也没有包可扫。这些会留在「未归属」,用手工归属分类即可。
<profile>/data/workspace-gate.json(本机示例:~/.dsh/data/workspace-gate.json)
{
"version": 1,
"overrides": {
"d:/projects/api": ["plugin:r18-novel", "tool:free_search_news"]
},
"assignments": {
"tool:read": "文件工具"
}
}
overrides:按工作区的隐藏清单,键是归一化目录(小写 + /),子目录继承最近祖先;assignments:全局的手工归属,赢过自动推断,只改分组、不影响"要不要隐藏";三条硬理由:
disabled 是每个 profile 一份,不是每个工作区一份;
两个工作区想一开一关只能来回改文件。本机 DSH 0.2.0-rc.2 / desktop profile:
| 事实 | 数值 |
|---|---|
全局可见工具(tools.schemas(undefined)) | 19 |
| 4 个 preset 作用域并集 | 53 |
| 某个具体会话可见工具 | 52–59 |
| 提示词段(按 preset 并集取) | 20 |
| 插件行总数 | 204 |
两个踩出来的坑:
agentPresets.acquireScope(id) 取并集。systemPrompt.assemble() 是 async,不 await 只拿到一个空对象。验证记录(对某个目录隐藏 tool:read 与 section:free-search:engines 后新开子会话):
bound = { cwd: "D:\\DSH Workspace", key: "d:/dsh workspace",
deny: ["weather"], sections: ["free-search:engines"], skipped: [] }
weather in agentTools : no
free-search:engines in agentSections : no
skipped: [] 说明两个名字都被接受——包括 preset 作用域里的工具,即 restrict 对
"继承面"(全局 + 祖先层)有效,不必是全局注册。
npm run check # node --check 三个入口
npm test # 24 条单测(纯逻辑,不需要 DSH)
index.js Host 半:绑定 agent、workspace_gate 工具、HTTP 路由
client.js Client 半:插件页「按工作区」页签
lib/policy.mjs 纯逻辑:目录匹配、归属推断、spec 展开、存储规整
tests/policy.test.mjs 上面那层的单测
cordis.patch.yml 组合包的行声明
locale/{zh,en}.json 插件管理页标题与描述
icon.svg 图标
Host 与 Client 之间的通道是本插件自注册的 HTTP 路由
(/workspace-gate/state|apply|assign|refresh):第三方插件的 Host 服务无法凭空长出
一个 remote namespace,而 webServer.register() 是宿主公开的接缝。
app.asar 内与动态注册的工具无法自动归属,需手工分类。restrict 只作用于继承面:极少见的、在该 agent 自己层注册的工具会落进 skipped。MIT © 2026 M1r0er
本仓库打了 dsh-plugin topic,便于在 DSH 插件索引/市场里被检索到。