DSH 能力中心(dsh-capability-pack)
把 DSH 的技能和 MCP 连接器从「启动即预载」改成「提问时检索、需要时加载」, 并给启动过程加一层防崩溃守卫。装完可以直接打包带走,在别的 DSH 上用同一条命令安装。
1. 它解决什么问题
| 现状 | 后果 | 本包的做法 |
|---|---|---|
技能目录只发现顶层 SKILL.md,市场里几千个技能要么全装、要么看不见 |
全装 → catalog 撑爆上下文;不装 → 明明有却用不上 | 索引全部技能(名字+描述),按任务检索,命中后才把那个目录装进顶层 |
dsh-mcp-client 在插件激活时连服务器并注册全部工具 |
一个 150 工具的服务器约 13 万 token,小窗口模型首轮就 400 | 改成 mcp 工具按需连接:不调用 = 0 进程、0 schema、0 token |
| 插件行解析不到包 / 语法错 / 重复 id | 启动报错甚至界面起不来 | doctor 静态体检 + 一键隔离;连续 2 次启动未完成自动落安全模式标记 |
| 功能重复:三套 Python MCP 原型 + 聚合器 | 改一处要改三处 | 合并成一个零依赖 servers/dsh-fs-mcp.mjs + 懒加载桥 |
实测数字(本机 2026-10-24)
- 索引:3439 个技能,已加载 50,可按需加载 3389;
- 工具 schema 常驻开销:2 个工具 / 1434 字符 / 约 600 tokens(合并前 8 个工具约 1600 tokens);
- 未调用任何连接器时,MCP 进程数 0;
- 索引构建 1.5 – 4 秒,之后界面读取为毫秒级(磁盘索引 + 内存缓存)。
2. 安装
从 GitHub 安装(推荐给别的机器)
git clone https://github.com/glentao-dev/dsh-capability-pack.git
cd dsh-capability-pack
node tools/install.mjs --profile desktop
安装脚本会:先导入本机 WorkBuddy 目录(有的话)→ 复制包体 → 登记
dsh.profile.bundles → 更新 pnpm-lock.yaml(DSH 只认 lockfile 里的模块映射,
漏了这步插件会被静默跳过)→ 重建索引 → 跑一次启动体检。装完重启 DSH。
从压缩包安装(另一台机器没有 git 时)
# 解压后进入 dsh-capability-pack/
node tools/install.mjs --profile desktop
--profile 省略时读环境变量 DSH_PROFILE,再退回 desktop。
脚本会:复制包到 <profile>/vendor/ 与 node_modules/ → 在 package.json 登记依赖与 dsh.profile.bundles → 追加一行 Loader 入口 → 重建索引 → 跑体检。幂等,重复执行安全。
装完重启 DSH。
通过 DSH 插件管理器(git 源)
plugin_manager action=install_bundle
target=github:glentao-dev/dsh-capability-pack
pnpm 支持 git spec,装完同样需要重启。npm 包发布后也可以直接用
dsh-capability-pack@<dsh 版本>。
从本工作区直接安装(开发时)
node dsh-capability-pack/tools/install.mjs --profile desktop
卸载
node tools/uninstall.mjs --profile desktop # 保留状态与已装载技能
node tools/uninstall.mjs --profile desktop --keep-state
3. 怎么用
3.1 模型侧:两个工具
capability action=search|load|unload|report|health
mcp action=list|tools|call
典型链路:
capability action=search query="pptx 生成"
→ - [skill] ppt-implement:智能 PPT 生成助手… → capability action=load name=ppt-implement
capability action=load name=ppt-implement
→ 已加载 …/skills/ppt-implement(返回 SKILL.md 开头 30 行)
skill name=ppt-implement # 用 DSH 原生 skill 工具真正读全文并执行
mcp action=list # 看有哪些连接器(不启动进程)
mcp action=tools server=fs # 首次调用才 spawn,列出工具名/必填参数
mcp action=call server=fs tool=fs_read arguments={"path":"README.md"}
设计原则:检索结果永远给出下一步动作,模型不需要猜。
3.2 界面侧:工作台(六页)
输入框上方出现「工作台 已加载/总数」按钮,点开是:
| 页 | 内容 | 数据来源 |
|---|---|---|
| 首页 | 「DSH,我帮你」+ 办公/开发/设计三档场景 + 8 张提示词卡片,点一下复制到剪贴板 | 内置文案 |
| 专家 | 从本机 WorkBuddy 导入的 448 位专家 / 15 个分类:分类卡片 + 筛选 + 搜索,点「召唤」复制该专家的开场提示词;下方同时列出 DSH 智能体预设 | /capability-pack/experts + index.json presets |
| 技能 | 搜索 + 列表;未加载点「加载」,本插件装的点「卸载」 | index.json skills |
| 连接器 | MCP 注册表,可「启用/停用」(停用会立刻回收进程) | index.json mcp |
| 定时 | 6 张定时任务模板,点一下复制「帮我创建定时任务…」指令 | 内置文案 + 模型 schedule_create |
| 资料 | 只读浏览工作区:目录树 + 文本预览(≤200KB) | /capability-pack/files、/file |
数据走 GET /capability-pack/index.json,动作走 POST /capability-pack/action。
整个面板包在 ErrorBoundary 里:即使渲染抛错也只会让按钮消失,不会白屏。
3.3 CLI
node tools/build-index.mjs [--workspace DIR] [--quiet] # 重建索引
node tools/doctor.mjs check [--profile p] [--json] [--fix] # 启动体检;--fix 隔离坏行
node tools/doctor.mjs safe-mode on|off|status # 安全模式
node tools/verify-live.mjs [--wait 60] # 重启后确认插件真的生效
node tools/import-workbuddy.mjs # 导入本机 WorkBuddy 的专家/技能目录
node tools/validate-tools.mjs # 工具 schema 预检(错一条插件就起不来)
node tools/audit-tools.mjs [--json] # 谁在占工具列表 / 哪些功能重叠
node tools/install.mjs / uninstall.mjs / pack.mjs
重启后先跑这一条,比翻日志快:
$ node tools/verify-live.mjs
[1] HTTP 路由 ok 路由可达(HTTP 200)
[2] 索引数据 ok 索引非空 · 技能 3439 · 已加载 50
[3] 启动守卫 ok 上次启动已标记为成功
[4] 安装登记 ok 依赖 / bundles / Loader 行 / node_modules 齐全
结论:能力中心已生效。
4. 启动防崩溃
三件事配合:
- doctor 静态体检:解析 profile 与 home 两层
cordis.patch.yml,对每个生效的插件行做 包解析 → 入口存在性 → ESM/CJS 语法检查(复制成.mjs再node --check,避免.js被当 CJS 误报), 并检查serverName重复。--fix把有问题的行追加disabled: true(带备份 + 隔离清单)。 - 安全模式:
doctor safe-mode on写~/.dsh/state/capability-pack/safe-mode.flag; Loader 行里disabled: !!js "process.env.DSH_SAFE_MODE === '1'"会整行跳过。bin/dsh-safe.cmd(或bin/dsh-safe.ps1)检测到标记就设DSH_SAFE_MODE=1再启动 —— 界面一定能起来。 - 崩溃计数:插件
apply时写boot.json(本次启动时间),30 秒后仍存活即写lastCleanAt。 下次若发现「上次启动没有正常结束」,crashCount++;连续 2 次就自动写安全模式标记。
本机第一次跑 doctor check 就抓到两行真实坏配置(dsh-vision-router、@michengai/dsh-agency-agents
在 profile 里没有安装),已隔离并记录到 ~/.dsh/state/capability-pack/quarantine.json。
4.5 数据从哪来:本机 WorkBuddy
能力中心的「专家」和一部分「技能」不是编的,是从本机已装的 WorkBuddy 目录里读出来的(全程离线):
| WorkBuddy 文件 | 内容 | 我们用在哪 |
|---|---|---|
~/.workbuddy/app/cache/experts/manifest.json |
448 位专家、15 个分类、职业/标签/开场提示词 | 工作台 → 专家页 |
~/.workbuddy/.skill-list-cache.json |
已装技能清单(名称/描述/SKILL.md 路径) | 工作台 → 技能页(带 WB 标记) |
~/.workbuddy/skills/**/SKILL.md |
技能正文 | capability action=load 复制进 DSH 技能根后即可被 skill 工具加载 |
node tools/import-workbuddy.mjs # 生成 data/workbuddy-catalog.json(约 290 KB)
node tools/build-index.mjs # 让技能索引包含 WB 技能
WorkBuddy 没装 / 没启动过时:脚本会输出「没读到专家清单」,其余功能照常。 专家头像在 WorkBuddy 里是远端资源,这里不热链,改用「首字母 + 分类色」的方块。
5. 目录结构
dsh-capability-pack/
├── index.js Host 插件:2 个工具 + 2 条路由 + 启动守卫
├── client.js Client 插件:工作台六页面板(原生 React,无外部依赖)
├── cordis.patch.yml bundle 的 Loader 行(带安全模式条件)
├── package.json dsh.bundle.patch + dsh.client 声明
├── lib/
│ ├── paths.mjs 全部路径常量(DSH_HOME / 技能根 / 状态目录)
│ ├── indexer.mjs 扫技能根、解析 frontmatter、去重、检索打分
│ ├── skills.mjs 装载/卸载技能(带 ledger,拒绝删别人的技能)
│ └── mcp.mjs 懒加载 MCP 桥:stdio(含 Content-Length 帧)+ Streamable HTTP
├── servers/
│ └── dsh-fs-mcp.mjs 零依赖 MCP 文件服务器(合并了原来的三套 Python 原型)
├── tools/
│ ├── build-index.mjs CLI 建索引
│ ├── doctor.mjs 启动体检 / 隔离 / 安全模式
│ ├── install.mjs 安装(幂等)
│ ├── uninstall.mjs 卸载
│ ├── verify-live.mjs 运行时自检(HTTP/索引/守卫/登记四层)
│ ├── import-workbuddy.mjs 导入本机 WorkBuddy 的 448 位专家 + 技能清单
│ ├── validate-tools.mjs 工具 schema 预检(additionalProperties 等硬规则)
│ ├── audit-tools.mjs 工具面审计:谁占了工具列表、哪些功能重叠
│ └── pack.mjs 打 zip(自带 ZIP 写入器,不依赖 7z/PowerShell)
├── data/mcp-servers.example.json
├── data/workbuddy-catalog.json WorkBuddy 专家/技能目录(import 生成)
├── docs/protocol-spec.md MCP 协议速查
├── docs/plugin-audit.md 工具面审计结论与整合建议(含可回滚命令)
├── bin/dsh-safe.cmd|ps1 安全模式启动器
├── locale/{zh,en}.json 插件标题/描述(插件管理器显示)
├── icon.svg
└── manifest.json 组件清单与安装效果说明
6. 数据文件(都在 ~/.dsh/state/capability-pack/)
| 文件 | 作用 |
|---|---|
index.json |
能力索引(技能/预设/连接器 + counts) |
index.tsv |
同一份数据的制表符版,方便 rg |
mcp-servers.json |
MCP 注册表(这是唯一需要手填的文件) |
installed.json |
本插件装载过的技能账本(卸载只认这个) |
boot.json |
启动守卫:尝试次数、连续未完成次数、最近正常时间 |
safe-mode.flag |
安全模式标记(存在即跳过本插件) |
quarantine.json |
doctor 隔离清单 |
7. 安全边界
- 只删自己装的:
unload只处理installed.json里登记、且路径仍在技能根之内的目录;用户自己的技能一律拒绝。 - MCP 服务器受根目录限制:
dsh-fs-mcp.mjs所有路径必须落在DSH_FS_MCP_ROOT内,越界直接报错(自检覆盖了这条)。 - 技能名净化:
safeSkillName去掉路径分隔符与..,不会写到技能根之外。 - 不改别人的配置:只追加自己的行;
--fix与安装都先写.bak-*备份。 - HTTP 路由只读+白名单动作:
install-skill/remove-skill/toggle-mcp/rebuild-index,无任意命令执行。
8. 已知限制
- 专家只做「召唤」(复制开场提示词),不做运行时人设注入:DSH 的“专家”等价物是智能体预设, 要真正换人设得在「设置 → 智能体预设」切换;把 WorkBuddy 的 448 个 agent 逐个改写成 DSH 预设不现实。
- 工具 schema 有硬规则:每个 object 必须显式
additionalProperties,否则整块插件激活失败 (实测踩过)。改完 schema 先跑node tools/validate-tools.mjs再重启。 - 界面渲染未在真实会话里验证:本包是在同一台机上用假 ctx 跑通 Host 全部动作、并把
/capability-pack/*路由处理跑通;Client 面板要重启 DSH 后由浏览器加载client.js才能看到。重启后若按钮不出现,先看~/.dsh/logs里capability-pack的 slot 注册告警。 - 索引构建 1.5–4 秒(3400+ 个
SKILL.md读 frontmatter)。放在启动后 3 秒后台执行,不阻塞启动;界面读的是磁盘索引,所以不受影响。 - MCP Streamable HTTP 只实现请求-响应,未处理服务器主动推送的 notification;stdio 是主路径。
- 未做增量索引:新增技能后要么等下次启动后台重建,要么点界面右上角刷新(
rebuild-index)或跑 CLI。 - DSH 只按
pnpm-lock.yaml建立模块映射:只写file:依赖而不更新 lockfile 的包会被静默跳过 (表现:patch 里能看到行,但模块从未被 import,日志无提示)。tools/install.mjs现在会自动跑一次pnpm install --prefer-offline --ignore-scripts补 lockfile;跑不了时会打印手动命令。tools/verify-live.mjs的[3] 插件加载痕迹就是用来抓这个坑的。 - 依赖登记用
file::安装会往 profilepackage.json写"dsh-capability-pack": "file:./vendor/dsh-capability-pack"。 正常情况这不会触发联网安装。若某台机器的 DSH 在启动时抱怨 profile 依赖不一致,把这一行删掉即可 ——node_modules/dsh-capability-pack与dsh.profile.bundles里的名字仍然能让插件加载。
9. 排错
# 界面/工具没出现
node tools/doctor.mjs check --profile desktop
tail -50 ~/.dsh/logs/*.log | grep capability-pack
# 启动异常 → 安全模式起来再说
node tools/doctor.mjs safe-mode on
bin\dsh-safe.cmd
# 索引不对
node tools/build-index.mjs --workspace "C:\Users\<你>\Documents\deepseek-harness\default-workspace"
# 界面报 HTTP 404(路由没挂上)
Get-Content "$env:USERPROFILE/.dsh/state/capability-pack/routes.json"
# {"registered":true,"reason":"ctx.inject"} ← 正常
# {"registered":false,"reason":"..."} ← 原因就写在 reason 里
# 连接器连不上
mcp action=list includeTools=true # 会尝试启动并回报工具数(0 = 起不来)
GitHub 上没有这个包的发布页;分发就是 node tools/pack.mjs 生成的 zip。
No comments yet. Be the first to write one.