DeepSeek Harness 插件

wyzh0117/dsh-skill-select

Star 数 ★ 3 分类 技能包 收录于 2026-08-22

侧边栏技能选择器:列出已安装技能并标注 Global 与所属 repo,支持本会话勾选与常驻默认启动、可选 Guard、Codex/Grok/Hermes 用户技能,以及 /skill 注入。

安装

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:wyzh0117/dsh-skill-select

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

dsh-SkillSelect

English · 中文

DSH Web 插件:在官方右侧栏页签中勾选已安装的 skill,并注入当前会话。

功能

  • 列出全部已配置 skill。标注 Global,能推断时显示所属 repo。
  • Skills:本会话勾选。单项写入 /skill-name;整 repo 勾满写入 /repo,发送时展开。页签隐藏后重新打开会清空本会话勾选。
  • Auto-start:常驻默认启动名单,每个会话首条消息注入一次。勾选方式与 Skills 相同。
  • 排序:Repo(默认)/ Name / Most used / Source。Repo 与 Source 按组折叠。
  • Guard(默认关):打开后,模型经 skill 工具调用不在「默认启动 ∪ 本会话勾选」内的技能会被拒绝。手动 /skill 不受限。
  • 有 frontmatter description 则直接用;否则生成一句英文简介并缓存。不改任何 skill 文件。
  • 同时列出 Codex / Grok / Hermes 用户技能(跳过内置)。重名分列。勾选写入 /name@agent,由插件注入对应来源的 SKILL.md。不注册进模型的 available_skills。
  • Update:对 git 仓库执行 git pull,对技能目录内来源标记重拉;根级标记与无来源为 skipped。变更摘要显示在面板内。

安装

仅 web profile。

dsh plugin --profile web add "github:wyzh0117/dsh-skill-select#main"

# 本地开发请用 link:,改代码重启即生效
# dsh plugin --profile web add "link:/path/to/skill-select"

重启 dsh web,然后硬刷新浏览器(Cmd/Ctrl+Shift+R)。

DSH 版本兼容

插件版本 支持的 DSH 说明
0.2.0(当前) ^0.2.0-rc.2 注册进官方右侧栏(见下)。
0.1.1 ^0.1.0-rc.6 || ^0.1.5-rc.1 0.1.x 两条线的最后一版;在 0.2.x 上会被下面的 peer 门禁静默跳过。
0.1.0 ^0.1.0-rc.6 在 0.1.5+ 上不可用,见下。

dsh 0.2.0-rc.2 起有硬兼容门禁:dsh-app-boot 读取 package.json peerDependencies 里名字为 @deepseek-ai/dsh 或以 @deepseek-ai/dsh- 开头的 条目,逐条执行 semver.satisfies(runtimeVersion, range, { includePrerelease: true }), 任一不满足就整棵 bundle 跳过——模块根本不会被 import,插件行直接显示禁用, 且没有任何报错。插件在升级 DSH 后静默消失时,第一步就对照 dsh --version 检查这些 peer 范围。 dsh.plugin.json 的 engines.dsh 在 rc.2 不参与判定 (仅当元数据保留)。确需强行加载时的逃生门:dsh plugin allow-version, 写入 <profile>/compatibility.json。

rc.2 还把「读会话」拆成了冷、活两条路。 ctx.sessions 现在只是一个装着 活会话的内存 store:sessions.get(id) 只对本进程激活过的会话作答。你只是在 网页端打开过的会话是冷会话,所以旧的单路径代码会对屏幕上明明存在的每个会话 报 session "…" not found(404)。openSkillView() 两条路都覆盖:活会话直接 当 scope,注册表由 ctx.agentPresets.serviceFor(agent, "skills") 取;冷会话用 ctx.sessionQuery.observeSession(id, { projectionMode }) 读 header.cwd 与 projections.values.agentPreset,再向 ctx.agentPresets.acquireScope(preset) 要一个常驻 scope——因为给一个从未 进入本进程的会话列技能同样需要一个 scope。每个句柄都在 finally 里释放 (Symbol.dispose / Symbol.asyncDispose),scope 不还会把 preset 注册表钉在 内存里。SESSION_QUERY_SESSION_NOT_FOUND 映射 404,其余查询错误映射 500; 没有 sessionQuery 的宿主退回 sessions.get()。要记住的症状:接口 200 但 skills: [],而同一个会话里模型明显能用上技能,就是冷路径没拿到 scope——通常因为 profile 里某条 @deepseek-ai/dsh-* 被版本门禁跳过,而 acquireScope 会牵动 shell / sandbox / tool 整条依赖链,那条链一断它就抛错。

DSH 0.1.5 改了 client 模块表:@deepseek-ai/dsh-client-runtime 不再是种子包, require("@deepseek-ai/dsh-client-runtime") 会抛 missed the module table, 页面报 Failed to load plugins(宿主本身能起来)。0.1.1 改用 ctx.sessions.scope(sessionId),并在 dsh.plugin.json / peerDependencies 里声明支持 0.1.5。client 代码只能 require() 平台种子包——侧栏图标因此 必须是内联 SVG 组件。

升级 DSH 后必做:dsh 只升了 CLI,profile 里已安装的插件仍停在旧 API, 需要重新解析一次:

dsh plugin --profile web update     # 重新解析 github:/registry 安装的插件
# link:/ 本地目录是就地使用,重启 dsh web 即可

再在本仓库跑 npm test:tests/dsh-compat.test.js 会在 DSH 删掉某个 named export、砍掉某个 client 种子包、或某个 @deepseek-ai/dsh-* peer 范围不再覆盖 本机运行时版本时直接失败,不必等宿主/页面炸掉才发现。

侧栏

插件以两阶段注册接入 dsh 官方右侧栏(dsh ≥ 0.2),两阶段都必须正确:

  1. 页面类型 —— ctx.sidebarRightTabs.register({ id: "dsh-skill-select", kind: "skill-select", priority: "extension", title: () => "Skills", guide: [{ id: "dsh-skill-select", order: 70, /* … */ icon: SkillIcon }] })。 kind 是 ctx.sidebarRight.openTab(kind) 用的判别式;guide 条目决定 右侧栏 guide 页上是否出现 Skills 入口。guide[].id 必填——两个都省略 id 的 guide 条目会抛 "duplicate guide entry id"。
  2. keyed 插槽 —— 主体用 ctx.slots.register({ name: "sidebar.right.pane.tab", key: "dsh-skill-select", inject: () => ({ rootCtx: ctx }) }, SkillSelectTab), 胶囊标题用 sidebar.right.pane.tab.title。插槽 key 必须等于阶段一的 id(不是 kind);给 keyed 插槽挂 list 形的 {id, order} 属于注册失败。 两处注册都包在 ctx.effect(...) 里,并经 ctx.slots.inject(slotName, cb) 兜住加载顺序。

打开右侧栏,在 guide 页点 Skills。ctx.sidebarRight.openTab("skill-select") 总会展开侧栏,且画面内没有 Session 时抛错。页签主体拿到 sessionId 与 useTabInfo(),按 tab.visible 门控技能拉取,并在隐藏→重新显示时重置本会话 勾选。

不依赖第三方侧边栏,也没有自绘回退 UI:官方侧栏不在,就没有页签。

开发

node --test
node --check lib/index.js && node --check lib/client.js

设计文档:docs/design.md。

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →

社区评论

评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。