DSH plugin 什么时候新增 workspace 包?DeepSeek Harness 新包目录、约束与验证

插件开发发布于 2026-10-02作者: DeepSeek Plugin 插件市场
DSH pluginDeepSeek Harnessworkspace 包插件开发包结构
在 DeepSeek Harness 里什么时候该新增 workspace 包、它和第三方 DSH plugin 有什么区别?本文按官方清单给出 @deepseek-ai/dsh-<name> 新包目录与五个必备文件、package.json 不变式、根配置注册、角色命名、README 契约与验证命令。

在 DeepSeek Harness 里新增 workspace 包,要回答三个问题:什么时候该新增、新包怎么写才算合规、写完后怎么验证。 官方提供了一份以 bash 与适配器包为模板验证过的逐文件清单(来源),本文把这份清单拆成可执行的步骤。

什么时候该新增 DSH plugin workspace 包

只有在仓库内需要复用或独立演进某项能力时才新增 workspace 包;通过 DSH Plugin Hub 安装的第三方 DSH plugin 不落 packages 目录。 判断标准有三条:

  1. 能力要被多个包复用 — 同一能力若只服务单个插件,先留在原包内,等出现第二个消费者再拆。预期:避免过早拆包。
  2. 能力要作为可替换能力独立演进 — 当 Service Definition、Service Provider、Consumer 三个角色需要分别替换时,把它们拆到不同包。预期:换 provider 不动 consumer,这正是 能力 Seams 的价值。
  3. 是外部第三方插件 — 从 DSH Plugin Hub 安装的第三方 DSH插件属于外部分发,不进入本仓库 packages 目录,也不受本文的 package.json 不变式约束。预期:清楚区分仓库内能力包与外部插件。

DSH plugin 新包的结构与硬性约束

目录与五个必备文件:@deepseek-ai/dsh-<name> 的固定位置

新包固定放在 packages/<group>/<pkg>/ 下,包名是 @deepseek-ai/dsh-<name>,最小形态包含五个位置(来源)。 目录长这样:

text
packages/<group>/<pkg>/
  package.json     # 复制 packages/core/tools 后调整 name/description/deps
  tsconfig.json    # extends ../../../tsconfig.base.json
  src/index.ts     # service 默认导出,或插件 (name/inject/apply/Config)
  locale/en.json   # 可选展示元信息 meta.title / meta.description
  locale/zh.json   # 同字段的翻译
  README.md        # 服务 API、事件、扩展点、设计说明与 Model Experience
  1. 选分组 — 已有分组能匹配包角色时优先复用(core、llm、shell、compaction、subagent、todo、session、client/host、util、test-support)。预期:允许新建分组,但分组只是纯容器,没有 package.json 与源文件。
  2. 写 tsconfig.json — 继承 ../../../tsconfig.base.json,rootDir 为 src,outDir 为 lib/types,references 至少包含 ../../../vendor/cosmokit、../../../vendor/cordis;用 Config 时再加 ../../../vendor/schemastery,每个 dsh 依赖再加 ../../<group>/<dep>。预期:类型解析能找到全部依赖。
  3. 写 src/index.ts — 导出 service 或 name/inject/apply/Config 形态的插件。预期:包可被 Cordis 装载。
  4. 包内相对导入用显式 .ts 后缀,例如 export * from './types.ts'。预期:编译器在输出的 JS 中改写为 .js,在声明文件中保留 .ts,标准 NodeNext/Node16 消费方会解析到同目录的 .d.ts。

package.json 不变式

package.json 的字段不是风格问题,而是由 pnpm run constraints 强制执行的硬性约束(来源)。 关键项如下:

字段要求
privatetrue
version与根 package.json 一致
typemodule
main / typeslib/index.js / lib/types/index.d.ts
exports["."]types 指向 ./lib/types/index.d.ts,default 指向 ./lib/index.js
@deepseek-ai/cordis同时出现在 peerDependencies 与 devDependencies,范围相同
其他 dsh 对等依赖每个都在 devDependencies 中镜像
@deepseek-ai/schemastery放在 dependencies(它是运行时校验器)
files精确包含 lib/index.js、lib/types/**/*.d.ts 与门禁认可的包专用运行时产物
  1. 发布 ./invariant 的包还要包含 lib/invariant.js;运行时 export 指向输出树时还要包含 lib/types/**/*.js。预期:发布物完整。
  2. 不要发布 src、声明映射、JS map 或陈旧的根声明文件。预期:包体积与曝光面最小。
  3. 带 bin 的 CLI 应用包在 files 中把 lib/bin.js 紧跟在 lib/index.js 之后。预期:命令入口被正确打包。

在根配置中注册新包

代码写完还不够,新包必须在根配置里登记,才能进入项目的引用图与检查范围(来源)。 需要动的位置只有两处:

文件变更
tsconfig.base.json已有分组无需编辑;新分组需要为 @deepseek-ai/dsh-* 通配符添加 ./packages/<group>/*/src 候选路径
tsconfig.host.json(Host 包)或 tsconfig.client.json(Client 包)在 references 中添加 { "path": "./packages/<group>/<pkg>" }
  1. 普通包恰好属于一个 aggregate,绝不同时加进 Host 与 Client。预期:引用图不产生重复解析。
  2. packages/client/* 包改为 extends tsconfig.base.client.json,client 插件包还需在 package.json 声明 dsh.client、导出 ./client、调用共享 tsdown preset。预期:client 侧构建走统一入口。
  3. 以下内容由 glob 或包清单发现机制自动覆盖,无需手动编辑:根 package.json workspaces、scripts/publint-all.ts、tsdown.config.ts、.oxlintrc.json、scripts/check-workspace-constraints.ts。预期:新增包被自动纳入检查。

一个仓库专属例外:api/remotes 因 Host 生成约定与 Client 消费约定之间存在顺序依赖而使用拆分,新增包不得仿照。

用角色名确定包拓扑与 ctx key

包拓扑与命名都要描述当前稳定职责,这决定了别人如何理解与替换你的能力(来源)。 两条规则:

  1. 可替换能力要拆包 — 不要在同一个包里同时放接口、实现与消费方;单一用途的插件保持一个包。预期:拓扑与第 1 节的判断标准一致。
  2. 名字对应当前职责 — 不要用首个实现、未来扩展或 Cordis 基类命名。接口包用能力名,实现包加机制 / 协议 / 环境 / 厂商限定词;只有同主机执行属于约定时才用 local。预期:bash-local、bash-sandbox、fs-local 这类名字自解释。

ctx key 的单复数也是约定:engine、runtime、policy、controller、resolver、store 或当前单一配置用单数;registry 或拥有多个具名成员的服务用复数。类的角色与 key 的单复数必须一致,并且不得让不兼容的 host 与 client 声明复用同一个 Cordis Context key——即使二者使用独立的运行时 context,TypeScript 声明合并仍会同时看到两种类型。

DSH plugin 新包的 README 契约与验证命令

README 与展示元信息

包的 README 不是可选项,它承载服务 API、扩展点与模型上下文契约(来源)。 顺序要求:

  1. 先写包特有内容 — 服务 API、配置、事件、扩展点与设计说明放前面。预期:消费者第一屏看到的就是接口。
  2. 按 kind 选 frontmatter — 组、参考、库或 bundle,四选一,每个 kind 恰好对应一个 README 模板。预期:文档结构与包在仓库中的位置一致。
  3. limitations 只记持久缺口 — 记录消费方可见的缺口与本包拥有的非显而易见维护者约束,日常清理事项留在源码 TODO。预期:文档不沦为 changelog。
  4. 补 Model Experience 与 Known Limitations and Deferred Work — 每个模型上下文条目用一个 H3,内含 What the model sees、Token effect、KV Cache effect 三个有序字段;没有上下文效果或仅有消费方拥有路径的包改用审计过的 None, as 或 Indirectly, through 语句,与模型无关的通用包可声明不适用。预期:验证器通过所需章节结构。

展示元信息是另一个可选层:在 locale/en.json 定义 meta.title 与 meta.description,把 ./package.json 与 ./locale/*.json 合进 exports,并把 locale/*.json 加入 files。回退链是「标题:locale meta.title → package.json.name → 完整 Cordis 插件名」「描述:locale meta.description → package.json.description → 不显示」。要在卡片、详情与组件行显示图标,在导出清单顶层设置 "icon": "./icon.svg" 并加入 files;图片必须自包含且不超过 256 KiB,支持 SVG、PNG、JPEG 与 WebP,绝对路径、URL 与目录外路径会被拒绝。

验证命令

新包完成的判定标准是仓库级命令全部通过,而不是本地能跑(来源)。 按以下顺序执行:

  1. 注册并同步元信息 — 在仓库根运行 pnpm install 注册 workspace,再运行 pnpm run doc-sync 同步文档。预期:workspace 与文档状态一致。
  2. 跑约束、类型与 lint — 依次运行 pnpm run constraints、pnpm run typecheck、pnpm run lint。预期:package.json 不变式、类型解析与代码规范全绿。
  3. 跑构建与卫生检查 — 运行 pnpm run build 与 pnpm run hygiene。预期:输出产物与仓库卫生检查通过。
  4. 可选校验展示元信息 — 若包提供展示元信息,运行 pnpm run verify-package-meta。预期:展示字段、资源 exports 与发布文件覆盖通过。
sh
pnpm install                    # 注册 workspace
pnpm run doc-sync
pnpm run constraints && pnpm run typecheck && pnpm run lint
pnpm run build && pnpm run hygiene
pnpm run verify-package-meta    # 仅当包提供展示元信息

写完自检三项:目录与五个文件是否齐全;package.json 不变式与根 tsconfig 注册是否都做完;README 的 Model Experience 与 limitations 章节是否补齐。想先理解底层框架,读 Cordis 三件套入门;已完成的插件可以放进 DSH Plugin Hub 供人检索。

常见问题

什么时候该新增 DSH plugin workspace 包?它和第三方插件有什么区别?

当一项能力需要在仓库内被多个 DSH plugin 复用、或需要作为可替换能力独立演进时,才在 packages 下新增 workspace 包。第三方插件通过 DSH Plugin Hub 以外部形式安装,不进入本仓库的 packages 目录,也不受这里的 package.json 不变式约束。

DSH plugin 新包应该放在仓库哪个目录,package.json 有哪些硬性约束?

DSH plugin 新包统一放在 packages/<group>/<pkg>/ 下,包名格式为 @deepseek-ai/dsh-<name>。package.json 由 pnpm run constraints 强制校验:private 为 true、version 与根 package.json 一致、type 为 module、main 指向 lib/index.js、types 指向 lib/types/index.d.ts,@deepseek-ai/cordis 同时出现在 peerDependencies 与 devDependencies 中且范围相同。

DSH plugin 新包为什么必须在根 tsconfig 里注册,目录名和 ctx key 怎么命名?

新包需要在 tsconfig.host.json 或 tsconfig.client.json 的 references 中加入自身路径,普通包恰好属于一个 aggregate,漏掉这一步项目引用与类型解析就找不到新包,typecheck 会失败。命名要描述当前稳定职责:接口包用能力名,实现包加机制 / 协议 / 环境 / 厂商限定词;engine、runtime、policy 等单一服务用单数 ctx key,registry 用复数。

DSH plugin 新包的 README 与展示元信息要写什么?

README 先写服务 API、事件、扩展点与设计说明,再按 kind 选 frontmatter,limitations 只记持久缺口,并补齐 Model Experience 的 What the model sees、Token effect、KV Cache effect 三个有序字段。展示元信息在 locale/en.json 定义 meta.title 与 meta.description,需要图标时在导出清单顶层设置 icon 并加入 files。

新增 DSH plugin 新包写完后,应该按什么顺序做仓库级验证?

DSH plugin 新包写完要在仓库根依次运行 pnpm install、pnpm run doc-sync、pnpm run constraints、pnpm run typecheck、pnpm run lint、pnpm run build 与 pnpm run hygiene。若包提供展示元信息,还要运行 pnpm run verify-package-meta 检查字段与发布文件覆盖。

相关术语

workspace 包
workspace 包是 DeepSeek Harness 仓库内以 @deepseek-ai/dsh-<name> 命名、位于 packages/<group>/<pkg> 下的一个独立单元,一个包可以同时承担 Service Definition、Service Provider 或 Consumer 角色。— https://deepseek-harness.github.io/deepseek-harness/reference/cookbook/adding-a-package
package.json 不变式
package.json 不变式是 DeepSeek Harness 对每个 workspace 包强制执行的清单约束,覆盖 private、version、type、main、types、exports 以及依赖出现位置,由 pnpm run constraints 统一检查。— https://deepseek-harness.github.io/deepseek-harness/reference/cookbook/adding-a-package
Service Definition
Service Definition 是能力 Seam 中声明接口的包,与实现它的 Service Provider、使用它的 Consumer 三者共同构成一个可替换能力;单独一个角色不构成 Seam。— https://deepseek-harness.github.io/deepseek-harness/reference/capability-seams
Model Experience
Model Experience 是包 README 中描述本包对模型上下文贡献的固定章节,每个条目用 What the model sees、Token effect、KV Cache effect 三个有序字段说明影响。— https://deepseek-harness.github.io/deepseek-harness/reference/cookbook/adding-a-package

来源