返回目录
其他 待识别

dsh-plugin-skill-picker

jerry-l3/dsh-plugin-skill-picker

DeepSeek Harness 编辑器插件:在「+」按钮右侧新增 Skill 选择按钮,为下一条消息选择 Skill(不选/单选/多选),并支持把本地 md/txt 文件注册为仅当前会话可用的临时 Skill

Stars
0
Forks
0
Issues
0
更新
4 天前

PROJECT TOPICS

项目标签

PROJECT README

README

DSH Skill Picker Plugin

DeepSeek Harness(DSH) Web 客户端新增的「Skill 选择按钮」:在输入框「+」按钮右侧,让用户为下一条消息选择要调用的 Skill(不选 / 单选 / 多选),并支持把一个本地 .md / .txt 文件临时注册成本会话可用的 Skill。

  • 目标仓库:deepseek-ai/deepseek-harness(DSH 是 DeepSeek 官方项目,本仓库只承载这个插件作为补丁提交
  • 插件包名:@deepseek-ai/dsh-client-ui-skill-picker

仓库结构

dsh/
  packages/client/ui-skill-picker/          ← 新增插件包(node 半边 + 浏览器半边 + Remote)
  .agents/notes/implemented/feature/         ← 本功能的 Agent Note(中英)
dsh-patch/after/                            ← 需要在 DSH 中修改的 8 个文件(改后内容)
dsh-patch/CHANGES.patch                     ← 上述文件的统一 diff(生成后写入)
MANIFEST.sha256                             ← 所有文件的校验清单

dsh-patch/after/ 里的文件是改后全文,对应的仓库相对路径就是它在 after/ 下的路径。 应用方式:把 after/ 下的文件覆盖到你的 DSH 检出对应路径;或直接应用 CHANGES.patch


它做了什么

需求 实现
「+」右侧新增按钮 注册一个 conversation.input.left list cell —— 该 slot 本来就渲染在「+」紧右侧,因此没有改动 ui-conversation 一行代码
折叠栏(展开/关闭/点外/Esc) 面板锚定在 composer 卡片上沿(与 / 菜单、popupSelect 同一套 bottom: calc(100% + 4px) 规则),外卖点击落在卡片内则不关闭
列表 + 搜索 数据来自现有 skills/list Remote(按会话 single-flight 缓存),搜索按名称/描述做有序子序列匹配
0/1/多选 状态是 selected: string[],点整行切换
chips 已选项显示为 chips,可单独移除、可一键清空
按钮高亮 + 数量 data-active 属性选择器 + 数量角标
添加本地 Skill 文件 折叠栏底部入口 → 解析 front matter → 经本包自有 Remote 注册为该会话作用域的运行时 Skill 并自动选中
临时 Skill 仅本会话、发送后取消选中但保留在列表 注册落在 Agent scope layer;发送成功后清空选择,行仍留在列表
请求携带已选 Skill 选择被写成正文里的 /name 手势(dsh-tool-skillagent/pre-step 已解析并注入正文),不新增第二条注入通道

为什么用 /name 手势而不是新增字段

Host 的 dsh-tool-skillagent/pre-step 会扫描已认领用户消息里所有 /<name> token,逐个解析并把 renderSkillContent 结果作为 instructions 注入。这条既有边界天然满足:多个 Skill 随一条消息发出、disable-model-invocation Skill 可达、"只影响下一条"(发送即清空草稿)。所以本插件只做 UI + 把选择变成手势。


安装到 DSH

前置:DSH 源码检出、Node ^22.19 || >=24、pnpm。

# 1. 复制插件包
cp -r dsh/packages/client/ui-skill-picker  <DSH>/packages/client/ui-skill-picker
cp -r dsh/.agents/notes/implemented/feature/2026-09-19-composer-skill-picker*.md \
      <DSH>/.agents/notes/implemented/feature/

# 2. 应用对既有文件的修改(8 个文件)
cd <DSH> && git apply /path/to/CHANGES.patch

# 3. 安装依赖(新增了 zod 与两个 peer,必须装)
pnpm install

# 4. 构建 + 启动
pnpm run build:lib     # host + client 两个构建面(生成 typert 产物)
pnpm run build:web     # 刷新前端 dist
pnpm run start:desktop

开发期热更:pnpm run dev:web 配合 pnpm dsh web

8 个需要修改的文件及其原因

文件 改了什么 / 为什么
packages/api/remotes/src/client/index.ts 把本包的 Remote contribution 加进 Client 装配列表(仓库里所有 namespace 的统一挂载点)
packages/api/remotes/package.json 声明对 @deepseek-ai/dsh-client-ui-skill-picker 的依赖
packages/bundle/web-app/cordis.patch.yml 新增 ui-skill-picker 浏览器插件行
packages/bundle/web-app/package.json 声明该 bundle 对插件包的依赖(verify-cordis-config 要求)
scripts/package-dependency-policy.ts PEER_REQUIRED_HOST_EXPORTS 增加 dsh-scope: createScopedsh-skill: isSkillName仓库规定此类新增须人工评审,PR 里需单列标题
scripts/verify-package-readme-model-experience.ts README 门禁的 allowlist 增加本包(kind: indirect
tsconfig.base.json 手写路径别名(包名与目录名不同,生成器不覆盖)
tsconfig.client.json Client 聚合 references 增加本包

已知限制

  • 发送成功即清空草稿,因此"发送失败后手势丢失"由 chips 旁的「重新附加」按钮处理;发送失败时选择本身会保留。
  • 临时 Skill 需要活跃 Agent:冷会话会被拒绝,而不是把注册放宽到全局层。
  • 临时 Skill 不落盘,随进程结束消失;永久安装仍是 skill 文件系统的职责。
  • 文本即载荷:手工键入的 /name 与选择器选中的在协议上不可区分。

已修复的一个真实 bug(编码)

最初的实现用 file.text() 读取本地文件,一律按 UTF-8 解码。中文 Windows 编辑器默认写 GBK,于是 GBK 字节被解成 U+FFFD 替换字符并被当成 Skill 正文注册(表现为乱码)。

现在 src/client/domain.tsdecodeSkillText严格 UTF-8 解码器做判别器,失败则回退 GB18030,并剥离 BOM;tests/browser-plugin.client.spec.ts 里有对应的回归用例(UTF-8 不被改动 / 真实 GBK 字节正确解出中文 / 带 BOM 仍能解析 front matter)。


验证状态

结果
tsc -b 两个 face 通过
tsdown host / client 两面 通过,产出 typert.host.js / typert.remote-client.js / client.js
真实浏览器(Edge + Playwright) 按钮存在、折叠栏可展开、搜索框与底部入口就位、列表渲染真实 Skill、Console 零报错
纯函数与编码回归用例 通过(16 个用例中 11 个)
插件注册类用例 未通过 —— 原因见下

未通过项说明(仓库既有缺陷,非本插件引入)

sections/scripts/test-invariants.ts(Vitest 全局 setup)在 fiber.ctx.fiber.state 处抛 TypeError: Cannot read properties of undefined (reading 'PENDING'),使任何在 spec 中直接调用 ctx.plugin() 的用例失败。

对照证据:未修改的 packages/client/ui-plan/tests/browser-plugin.client.spec.ts 报完全相同的错误(4 个用例挂 2 个)。因此插件注册类用例的失败属于该全局 setup 与 ctx.plugin() 的兼容问题。


License

与 DSH 上游一致(MIT)。本仓库内容为对 deepseek-ai/deepseek-harness 的补丁贡献。

CLASSIFICATION EVIDENCE

分类依据

项目类型待识别
功能分类其他
规则置信度

系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。