VCPr0j3k7/dsh-skill-manager ↗★ 0

dsh-skill-manager

为 DeepSeek Harness 桌面版提供 skill 管理界面:列出宿主实际扫描的 skill 根目录、标注每个 skill 的来源与有效性、新建 skill、从文件夹导入、在系统文件管理器中打开目录。官方 Harness 会自动扫描并热加载 skill,但未提供这一层界面。 适合需要直观查看、新建、导入和管理DSH技能(skill)的用户。

패키지
dsh-skill-manager
호환성
미검증
버전
0.1.0
라이선스
MIT
최근 업데이트
2026. 9. 25.

같은 패키지 이름의 다른 저장소

설치

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:VCPr0j3k7/dsh-skill-manager

dsh-skill-manager

License: MIT Node.js

English | 简体中文

为 DeepSeek Harness (DSH) 桌面版提供 skill(技能)管理界面:列出宿主实际扫描的 skill 根目录、 标注每个 skill 的来源与有效性、新建 skill、从文件夹导入、在系统文件管理器中打开目录。

本插件以独立 bundle 形式装入 DSH profile,不接管官方 skill 的扫描与热加载。


目录

问题背景

官方桌面版已具备完整的 skill 能力,但没有任何可视化入口:

能力提供方是否随官方发行
扫描 skill 根、解析 frontmatter、热加载@deepseek-ai/dsh-skill-filesystem是
/ 唤起 skill@deepseek-ai/dsh-client-ui-skill是
列出扫描到的根、标记无效文件、新建与导入——否

因此当 frontmatter 写错、或 skill 没有被加载时,用户只能自己去翻目录与日志。

本插件补的就是这一层:它不参与加载,只在文件层面做增删查,并如实展示宿主扫描的根目录 与每个 skill 的来源。因此它与官方插件同时启用不会冲突 —— 一个负责装载,一个负责文件。

环境要求

项要求
Node.js^22.19.0 || >=24
DeepSeek Harness官方桌面版
依赖yaml(安装时自动装好)

安装

安装分两步:先装进 profile,再把包名登记进 bundle 层栈。

# 1. 进入桌面版的 profile 目录(Windows 默认:%USERPROFILE%\.dsh\profiles\desktop)
cd "/profiles/desktop"

# 2. 用官方桌面版随包的 pnpm 装进 profile
pnpm add "file:"
# 或者直接从 GitHub 装
pnpm add "github:VCPr0j3k7/dsh-skill-manager"

「随包的 pnpm」指 /resources/runtime/pnpm/bin/pnpm.cjs。若它不在 PATH 中, 用随包的 node 直接调用即可:

NODE="/resources/runtime/primary-runtime/dependencies/node/bin/node.exe"
PNPM="/resources/runtime/pnpm/bin/pnpm.cjs"

"$NODE" "$PNPM" add "file:"
"$NODE" "$PNPM" add "github:VCPr0j3k7/dsh-skill-manager"

必须登记 bundle 层栈

pnpm add 只会写入 dependencies。DSH 只装载 dsh.profile.bundles 中列出的 bundle, 因此必须手动把包名追加进 profile 的 package.json:

{
  "dsh": {
    "profile": {
      "bundles": [
        "@deepseek-ai/dsh-base",
        "@deepseek-ai/dsh-web-app",
        "dsh-skill-manager"        // ← 追加这一条
      ]
    }
  }
}

漏掉这一步的表现是:安装过程没有任何报错,依赖目录也在,但插件完全不加载 —— 界面上没有入口,日志里也没有记录。这是本项目最容易踩的一步。

dsh plugin --profile desktop add ... 会在 pnpm 结束后自动运行 reconcilePlugins(), 由它补上这一条。但官方桌面版通常不提供可直接调用的 dsh CLI, 走 pnpm add 的路径时就需要手动登记。

确认已登记:

cd "/profiles/desktop" && cat package.json

安装完成后需重启桌面版。宿主只在启动时装配插件树,运行中的实例不会热更新。

卸载

cd "/profiles/desktop"
"$NODE" "$PNPM" remove dsh-skill-manager

随后从 dsh.profile.bundles 中删除 "dsh-skill-manager" 一行。卸载后同样需要重启桌面版。

卸载不会删除任何 skill 文件:本插件只向 /skills 写入,从不清理该目录。

工作原理

插件由两个半边组成,各自独立运行:

半边运行位置形态
宿主半边DSH 宿主进程(Node.js)Cordis 插件,导出 name / inject / apply(ctx)
客户端半边桌面版窗口(浏览器)React 页面,经 window.__ModuleLoader__.load({ id, factory }) 装载

宿主半边在 ctx.webServer 上注册一条 kind: 'prefix' 路由 /dsh-skill-manager/api,前缀内部的路由派发由 host/router.mjs 完成。 这样做的好处是注册点只有一处,卸载时由框架统一清理,不会在 webServer 中留下半张路由表。

所有响应统一为 { ok: true, data } 或 { ok: false, error },业务失败也返回 HTTP 200 —— 状态码只用于表达「路由不存在」这类传输层事实。

客户端半边在首次请求时探测宿主基址。页面的来源可能是宿主自身的 HTTP 地址、 外壳的自定义 scheme(dsh-app://app/),也可能是不透明来源(location.origin === "null")。 因此它按顺序尝试相对路径与官方虚拟主机名 http://dsh.internal,并以 /info 返回的 data.plugin 是否等于本插件 id 作为判定依据 —— 仅凭 HTTP 200 不够,SPA 的兜底路由 会把未知路径也返回 200 + HTML。选定后缓存复用。

共享配置:本插件与同系列的其他插件共用 /dsh-extras.json, 通过 GET /config 读取、POST /config 深合并写回。本插件不定义自己的配置项, 但 GET /info 会带上其中的 appName 字段。

日志:宿主半边的日志写入 /plugin-data/logs/dsh-skill-manager.log, 同时在内存中保留最近 2000 行环形缓冲。

界面与操作

侧边栏的「Skill 管理」入口打开面板,包含四项操作:

操作行为
新建 Skill表单生成 /skills//SKILL.md。名称需符合 kebab-case,description 与正文必填;同名目录已存在时拒绝写入
从文件夹导入弹出系统目录选择器。若所选目录含 SKILL.md,整个目录按原目录名拷入用户 skill 根;否则把该目录下的平铺 .md 逐个拷入。目标已存在时跳过,不覆盖
打开 skill 目录在系统文件管理器中打开用户 skill 根;点击某条 skill 的「打开位置」则定位到该文件
重新装回内置 skill本插件中始终报告「不适用」,详见下文

面板同时展示:

  • 按 rank 分组的 skill 列表,每条显示名称、描述、何时使用、来源根、正文大小与正文预览;
  • 「随包内置」标记(依据记账文件判定,见下文);
  • 「被忽略的文件」列表,逐条给出 frontmatter 解析失败的原因;
  • 一张扫描根目录说明表(rank、路径、目录是否存在)。

关于「重新装回内置 skill」:本插件不适用

官方桌面版不随插件发行内置 skill:随包 skill 由运行时自行管理。因此宿主半边把 BUNDLED_DIR 固定为 null,POST /skills/restore-bundled 会明确返回:

官方桌面版不随插件发行内置 skill(随包 skill 由运行时自行管理),此项不适用

界面上的按钮保留,但点击后显示的就是上面这句话。列表中的「随包内置」一栏同样始终为空。

host/services/skills.mjs 中仍保留了一套完整的随包 skill 安装与记账实现 (installBundledSkills / restoreBundledSkills / bundledSkillNames, 记账文件为 /bundled-skills/.installed.json),但在本插件中 bundledDir 恒为 null,这些函数不会安装任何内容。

skill 的发现规则

官方按 rank 顺序扫描以下根目录,同名的 skill 以 rank 较小者为准。每个根只扫描一层, 不支持嵌套的 SKILL.md:

rank来源路径可写
100当前项目(.dsh)/.dsh/skills是
200当前项目(.agents)/.agents/skills是
400桌面版用户目录/skills是
500共享 agent 目录$DSH_AGENTS_HOME/skills(默认 ~/.agents/skills)是
600随包内置官方 bundledSkillDir,本插件不涉及否

「项目根」取最近的含 .git 的祖先目录(最多向上 24 层),没有则使用当前工作目录。

一个 skill 可以是:

  • 目录 bundle:/SKILL.md,可附带 references/、scripts/、assets/ 等资源;
  • 平铺文件:.md。

以 . 开头的条目会被跳过。SKILL.md 必须以 --- 包裹的 YAML frontmatter 开头:

字段必填说明
name是仅小写字母、数字与短横线(^[a-z0-9]+(?:-[a-z0-9]+)*$)
description是模型据此决定是否使用该 skill
whenToUse否何时使用
user-invocable否设为 false 时用户不可手动调用
disable-model-invocation否设为 true 时模型不可自动调用

布尔字段按严格布尔解析:接受 true / false,也接受 yes / no / on / off / 1 / 0 等字符串写法;其余值视为未设置(与官方一致)。

frontmatter 由 yaml 包解析,并且刻意使用运行时自带的那一份 —— 换用其他 YAML 库可能对边界写法给出不同结论,从而与宿主的判断不一致。

skill 是热生效的:新建或导入后无需重启宿主,官方 watcher 会在下一个模型步骤刷新目录。

宿主接口

所有接口挂在 /dsh-skill-manager/api 下。

插件自有路由

方法路径请求体返回
GET/skills/list——{ roots, skills, invalid, home, userRoot, bundledDir }
POST/skills/create{ input }{ path, name }
POST/skills/import{ sourceDir }{ imported, skipped, root }
POST/skills/restore-bundled——恒为「不适用」错误
POST/skills/open-dir{ target? }{ opened },缺省打开用户 skill 根

公共路由

以下路由由 host/router.mjs 统一提供(本插件的页面只用到其中的一部分):

方法路径说明
GET/info插件 id、宿主状态、运行时目录等;客户端以 data.plugin 判定基址是否可用
GET/config读取 /dsh-extras.json
POST/config深合并写回该文件
POST/open-external用系统默认程序打开 http/https 链接,其他协议一律拒绝
POST/pick-directory系统目录选择器;优先使用官方 ctx.directoryPicker,否则在 Windows 上用 PowerShell 兜底
GET/restart-pendingprofile 的关键文件是否比宿主就绪时刻更新
POST/restart-host恒定拒绝:插件无法重启承载自身的进程
GET/events事件增量拉取(?since=),客户端每 300ms 轮询一次

启用条件

  • 宿主半边:包名出现在 profile package.json 的 dsh.profile.bundles 数组中, 且 profile 已重新装载(重启桌面版)。没有环境变量开关。
  • 客户端半边:页面由官方桌面版外壳提供。基址探测成功后界面可用;探测失败时界面仍会渲染, 但所有数据请求都会失败并显示错误信息。

测试

npm test
# 等价于 node test/check.mjs

test/check.mjs 是纯 Node 自检(35 项),不依赖 DSH 运行时,也不需要把插件装进 profile。 它使用临时 DSH_HOME 与临时 APPDATA,不会读写用户的真实目录。覆盖范围:

  • package.json 清单契约:dsh.bundle.patch、dsh.client.platform、exports 与 files 所指向的文件真实存在;
  • 宿主半边可被 import,导出 name / inject / apply,apply(ctx) 不抛并注册前缀路由;
  • 路由对齐:从 client.js 中提取全部 request("METHOD", "PATH") 调用(当前 10 条), 逐条打到真实路由表上,确认没有一条落到 404;同时校验两侧的路由前缀一致;
  • host/config.mjs 的默认值包含 githubToken 等字段,且配置文件路径落在当前 DSH_HOME 之下。

路由对齐是本项目的核心契约:客户端半边是构建产物,一旦它调用的路由在宿主侧不存在, 表现只是界面上某个按钮静默失败(宿主回 404,页面只显示一句笼统的错误)。

端到端验证:装入并重启桌面版后,侧边栏应出现「Skill 管理」入口,面板能列出 /skills 下的 skill。

已知限制

  • 「重新装回内置 skill」不适用。 官方桌面版不随插件发行内置 skill,该操作恒定返回错误(详见上文)。
  • 宿主无法重启自身。 POST /restart-host 恒定拒绝;需要重启时请手动退出并重新打开桌面版。
  • 「打开 skill 目录」要求目录已存在。 若 /skills 尚不存在(例如全新安装且从未创建过 skill),该操作会报「路径不存在」。先用「新建 Skill」或「从文件夹导入」创建一次即可。
  • 只扫描一层。 与官方一致,根目录下的子目录不会被递归查找,嵌套的 SKILL.md 不会被发现。
  • 不接管加载与卸载。 扫描、解析、热加载均由官方 dsh-skill-filesystem 负责;本插件只做 文件层面的增删查。界面上「有效 / 被忽略」的判断是对同一套规则的重演,不是另一套判定。
  • 导入不覆盖同名文件。 目标已存在时跳过并在结果中列出;需要覆盖请先手动删除。
  • client.js 是构建产物。 它由构建脚本从桌面版前端源码切片生成,其中包含若干本页未使用的 组件(安装进度环、README 抽屉、重启提示条、若干图标等,来自同一套切片的其他面板)。 这些组件不参与本插件的渲染;直接手工修改会在下次构建时被覆盖。
  • 界面文案为中文。 当前版本未做多语言。

许可

MIT