DSH plugin 什么时候新增 workspace 包?DeepSeek Harness 新包目录、约束与验证
在 DeepSeek Harness 里新增 workspace 包,要回答三个问题:什么时候该新增、新包怎么写才算合规、写完后怎么验证。 官方提供了一份以 bash 与适配器包为模板验证过的逐文件清单(来源),本文把这份清单拆成可执行的步骤。
什么时候该新增 DSH plugin workspace 包
只有在仓库内需要复用或独立演进某项能力时才新增 workspace 包;通过 DSH Plugin Hub 安装的第三方 DSH plugin 不落 packages 目录。 判断标准有三条:
- 能力要被多个包复用 — 同一能力若只服务单个插件,先留在原包内,等出现第二个消费者再拆。预期:避免过早拆包。
- 能力要作为可替换能力独立演进 — 当 Service Definition、Service Provider、Consumer 三个角色需要分别替换时,把它们拆到不同包。预期:换 provider 不动 consumer,这正是 能力 Seams 的价值。
- 是外部第三方插件 — 从 DSH Plugin Hub 安装的第三方 DSH插件属于外部分发,不进入本仓库 packages 目录,也不受本文的 package.json 不变式约束。预期:清楚区分仓库内能力包与外部插件。
DSH plugin 新包的结构与硬性约束
目录与五个必备文件:@deepseek-ai/dsh-<name> 的固定位置
新包固定放在 packages/<group>/<pkg>/ 下,包名是 @deepseek-ai/dsh-<name>,最小形态包含五个位置(来源)。 目录长这样:
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
- 选分组 — 已有分组能匹配包角色时优先复用(
core、llm、shell、compaction、subagent、todo、session、client/host、util、test-support)。预期:允许新建分组,但分组只是纯容器,没有package.json与源文件。 - 写
tsconfig.json— 继承../../../tsconfig.base.json,rootDir为src,outDir为lib/types,references至少包含../../../vendor/cosmokit、../../../vendor/cordis;用Config时再加../../../vendor/schemastery,每个 dsh 依赖再加../../<group>/<dep>。预期:类型解析能找到全部依赖。 - 写
src/index.ts— 导出 service 或name/inject/apply/Config形态的插件。预期:包可被 Cordis 装载。 - 包内相对导入用显式
.ts后缀,例如export * from './types.ts'。预期:编译器在输出的 JS 中改写为.js,在声明文件中保留.ts,标准 NodeNext/Node16 消费方会解析到同目录的.d.ts。
package.json 不变式
package.json 的字段不是风格问题,而是由 pnpm run constraints 强制执行的硬性约束(来源)。 关键项如下:
| 字段 | 要求 |
|---|---|
private | true |
version | 与根 package.json 一致 |
type | module |
main / types | lib/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 与门禁认可的包专用运行时产物 |
- 发布
./invariant的包还要包含lib/invariant.js;运行时 export 指向输出树时还要包含lib/types/**/*.js。预期:发布物完整。 - 不要发布
src、声明映射、JS map 或陈旧的根声明文件。预期:包体积与曝光面最小。 - 带
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>" } |
- 普通包恰好属于一个 aggregate,绝不同时加进 Host 与 Client。预期:引用图不产生重复解析。
packages/client/*包改为 extendstsconfig.base.client.json,client 插件包还需在package.json声明dsh.client、导出./client、调用共享 tsdown preset。预期:client 侧构建走统一入口。- 以下内容由 glob 或包清单发现机制自动覆盖,无需手动编辑:根
package.jsonworkspaces、scripts/publint-all.ts、tsdown.config.ts、.oxlintrc.json、scripts/check-workspace-constraints.ts。预期:新增包被自动纳入检查。
一个仓库专属例外:api/remotes 因 Host 生成约定与 Client 消费约定之间存在顺序依赖而使用拆分,新增包不得仿照。
用角色名确定包拓扑与 ctx key
包拓扑与命名都要描述当前稳定职责,这决定了别人如何理解与替换你的能力(来源)。 两条规则:
- 可替换能力要拆包 — 不要在同一个包里同时放接口、实现与消费方;单一用途的插件保持一个包。预期:拓扑与第 1 节的判断标准一致。
- 名字对应当前职责 — 不要用首个实现、未来扩展或 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、扩展点与模型上下文契约(来源)。 顺序要求:
- 先写包特有内容 — 服务 API、配置、事件、扩展点与设计说明放前面。预期:消费者第一屏看到的就是接口。
- 按 kind 选 frontmatter — 组、参考、库或 bundle,四选一,每个 kind 恰好对应一个 README 模板。预期:文档结构与包在仓库中的位置一致。
- limitations 只记持久缺口 — 记录消费方可见的缺口与本包拥有的非显而易见维护者约束,日常清理事项留在源码 TODO。预期:文档不沦为 changelog。
- 补 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 与目录外路径会被拒绝。
验证命令
新包完成的判定标准是仓库级命令全部通过,而不是本地能跑(来源)。 按以下顺序执行:
- 注册并同步元信息 — 在仓库根运行
pnpm install注册 workspace,再运行pnpm run doc-sync同步文档。预期:workspace 与文档状态一致。 - 跑约束、类型与 lint — 依次运行
pnpm run constraints、pnpm run typecheck、pnpm run lint。预期:package.json 不变式、类型解析与代码规范全绿。 - 跑构建与卫生检查 — 运行
pnpm run build与pnpm run hygiene。预期:输出产物与仓库卫生检查通过。 - 可选校验展示元信息 — 若包提供展示元信息,运行
pnpm run verify-package-meta。预期:展示字段、资源 exports 与发布文件覆盖通过。
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 复用、或需要作为可替换能力独立演进时,才在 packages 下新增 workspace 包。第三方插件通过 DSH Plugin Hub 以外部形式安装,不进入本仓库的 packages 目录,也不受这里的 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 中且范围相同。
新包需要在 tsconfig.host.json 或 tsconfig.client.json 的 references 中加入自身路径,普通包恰好属于一个 aggregate,漏掉这一步项目引用与类型解析就找不到新包,typecheck 会失败。命名要描述当前稳定职责:接口包用能力名,实现包加机制 / 协议 / 环境 / 厂商限定词;engine、runtime、policy 等单一服务用单数 ctx key,registry 用复数。
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 新包写完要在仓库根依次运行 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
来源
- DeepSeek Harness 官方文档 - 实操手册:添加 workspace 包· deepseek-ai
- DeepSeek Harness 官方文档 - 架构与能力 Seams· deepseek-ai