DSH 插件发布全链路:npm 打包、bundle 与 profile 机制、商店元信息、用户安装一条龙

发布时间:2026/10/29 2:05:16
DSH 插件发布全链路:npm 打包、bundle 与 profile 机制、商店元信息、用户安装一条龙

CFzjy

AI Engineer


▍深耕领域AI Agent 架构设计Harness 插件开发Context Engineering多智能体协同 & RAG
▍技术底座PythonTypeScript·Cordis 插件MCP & Skills·FastAPIDocker
▍工程能力专注 Agent 运行时与 Harness 插件开发、长上下文与流式交互优化、LLM 全链路工程化落地

「 让 AI 交互更智能,让技术落地更高效 」|欢迎技术探讨 / 项目合作,关注解锁大模型与智能交互的无限可能!

DSH 插件发布全链路:npm 打包、bundle 与 profile 机制、商店元信息、用户安装一条龙

📚《DeepSeek Harness 插件架构》连载专栏 · 第 13 篇

前面十二篇把 DSH 插件从原理写到实战、从官方解剖写到迁移。这一篇解决最后一公里:你写好的插件,怎么变成别人一行命令就能装上的成品?很多插件死在"本地能跑、一发布就坏"——不是代码不行,是打包、元信息、分发方式没对齐。DSH 的发布有一套清晰的契约:先分清"组合包(bundle)"和"profile"两个概念,再搞定 npm 打包不变式,然后补商店元信息,最后验证用户安装。这一篇把整条链路串起来。

痛点一:插件本地跑得好,npm publish 一装就坏。因为files白名单漏了产物,线上包缺文件。

痛点二:分不清 bundle 和 profile。把两者混为一谈,结果装不进、启不来。

痛点三:插件在商店里丑得没眼看。没有 locale 标题、没有 icon、没有实机截图,商店卡片一片空白。

痛点四:从 GitHub 直装总失败。不知道 git 安装拉的是源码不是产物,需要prepare脚本和allowBuilds授权。

网上讲 DSH 的教程大多停在"写个插件",本篇把"发布"讲透。读完你会拿到:bundle/profile 的概念区分、package.json 的发布级不变式、三种分发方式的取舍表、商店元信息的完整清单、以及一张发布避坑速查表。想追完结篇(下一篇:插件化是 Agent 应用层的未来吗),可以先关注我的 CSDN 主页。

文章目录

    • DSH 插件发布全链路:npm 打包、bundle 与 profile 机制、商店元信息、用户安装一条龙
      • 一、发布全链路概览:两个概念,两种 manifest
      • 二、npm 打包:package.json 的不变式
      • 三、三种分发方式:npm / tarball / git 的取舍
      • 四、商店元信息:locale、icon、screenshots 与市场
      • 五、用户安装验证 + 发布避坑速查表
      • 结语

一、发布全链路概览:两个概念,两种 manifest

DSH 的安装机制建立在两个概念之上,二者都由package.json描述,但回答的问题不同(官方原话):

概念manifest 键回答的问题谁写、谁用
组合包(bundle)dsh.bundle“这个包贡献什么?”你编写、你分发
profiledsh.profile“这套配置由哪些组合包按什么顺序组成?”用户用dsh --profile启动

组合包是附带一个配置层的 npm 包——它的dsh.bundle.patch指向一个 patch 文件,声明"我往插件树里插/覆盖哪些行"。profile是$DSH_HOME/profiles/<name>下的目录,用dsh.profile.bundles列表声明"我按什么顺序组合哪些 bundle"。官方强调了一句容易踩的边界:“没有东西同时是两者”——组合包是你发的东西,profile 是用户启的东西。

源码
src/index.ts

构建
lib/index.js

npm 打包
files 白名单

三种分发

用户 dsh plugin add

写入 profile.bundles

--dump-config 验证

二、npm 打包:package.json 的不变式

第 07 篇你搭过骨架,这里给"发布级"的硬约束——官方通过 CI(pnpm run constraints)强制执行这些不变式,新包不满足就过不了门禁:

字段硬约束不满足的后果
privatetrue(monorepo 内)意外发版
version与根 package.json 一致版本漂移
type/main/typesmodule/lib/index.js/lib/types/index.d.tsimport/export 报错
peer 依赖@deepseek-ai/cordis同时进 peerDependencies + devDependencies(同范围)类型检查/测试孤岛
@deepseek-ai/schemastery放dependencies(运行时校验器)运行时缺依赖
files精确列出lib/index.js、lib/types/**/*.d.ts等线上包缺文件

其中files是最高的坑,官方特别强调:“不要发布 src、声明映射、JS map 或陈旧的根声明文件”。它的逻辑是只发产物不发源码——TypeScript 源码留在仓库,消费者只拿编译好的lib/。发布前用pnpm pack --dry-run核对打包清单,能提前发现漏了cordis.patch.yml或screenshots.json这类线上坏包。

三、三种分发方式:npm / tarball / git 的取舍

官方给了三种交付方式,各有适用场景,也各有坑:

方式命令优点代价
npm 发布dsh plugin add your-package预构建、零授权、体验最好要发版到 registry
tarballdsh plugin add ./your-package-0.1.0.tgz离线交付、不需 registry要自己pnpm pack
git 直装dsh plugin add github:you/pkg不用发 registry拉的是源码,需要构建授权

git 直装是坑最多的一种,官方专门提醒:git 安装拉取的是源码,不是构建产物——没有任何环节运行你的build脚本,TypeScript 包到手时没有lib/输出,加载就失败。解法两边各做一件事:作者提供自包含的prepare脚本(pnpm 在 git 安装后运行它),从源码构建出发布入口;用户为构建授权——pnpm ≥10 在显式允许前拒绝运行 git 依赖的prepare脚本,所以第一次add会失败,dsh会提示把确切的包键写进 profile 的pnpm-workspace.yaml:

allowBuilds:dsh-hello-plugin:true

官方给了一句分量很重的话:这项授权意味着"允许该包的代码在安装时于你的机器上执行,且不在 agent 运行的任何沙箱之内"——所以只对源码可信的包授权,并锁定 commit(github:you/pkg#<sha>),让后续推送无法悄悄改变实际运行的内容。如果不想让用户做授权,就改用前两种(npm / tarball),它们都是预构建产物、零构建权限。

四、商店元信息:locale、icon、screenshots 与市场

插件进了商店长什么样,取决于三样元信息——这是"能被搜到、点进、装走"的关键:

元信息位置作用
locale 标题/描述locale/en.json+locale/zh.json商店卡片的名称和简介(中英双语)
iconpackage.json"icon": "./icon.svg"商店卡片图标
screenshotsscreenshots.json+assets/*.png实机运行截图(严禁伪造)

locale 的字段很简洁:

{"meta":{"title":"Workspace Tools","description":"Tools for your workspace."}}

官方给了一条回退链值得记:标题回退顺序是locale meta.title→package.json.name→ 完整 Cordis 插件名;描述是meta.description→package.json.description→ 不显示。所以即使你不写 locale,插件也不会在商店"消失",只是显示技术名。但想要商店卡片专业,就得补双语 locale + icon(SVG/PNG/JPEG/WebP,≤256 KiB,自包含)+ 实机截图。第 07 篇提过screenshots.json必须是合法字符串数组、图片在仓库里真实存在——商店 CI 会校验,伪造截图过不了。

五、用户安装验证 + 发布避坑速查表

用户侧一行命令安装,dsh会转发给 pnpm 并维护 profile 的 bundle 列表:

dsh plugin--profiledemoadd./hello-plugin# 首次会初始化 profile(@deepseek-ai/dsh-base 作为第一个 bundle)# 因为包声明了 dsh.bundle,会被追加进 dsh.profile.bundles

装完先别急着启动,用--dump-config验证你的层真的被应用了(第 05/09 篇的验层法):

dsh--profiledemo --dump-config# 输出里应出现 "# == dsh-hello-plugin" 这一层dsh--profiledemo

生效配置按四层层序组合(第 05 篇):profile 的 bundles 列表 → profile 自己的 patch → home 级$DSH_HOME/cordis.patch.yml→ 每个--patchoverlay,后层按行胜出,且整行替换不深度合并。

序号遇到的报错或现象背后的真正原因一句话解决办法
1npm 装完插件不生效包没声明 dsh.bundle.patchpackage.json 加 dsh 键
2线上包行为与本地不一致files 白名单漏了 patch 或 assets发布前 pnpm pack --dry-run 核对
3git 直装 TS 包加载失败拉的是源码,无 lib/ 产物作者加 prepare 脚本,用户配 allowBuilds
4git 安装被 pnpm 拒绝pnpm≥10 默认拒绝运行 prepareprofile 的 pnpm-workspace.yaml 加 allowBuilds
5商店卡片显示技术名没写 locale 元信息locale/en.json + zh.json 补 meta.title
6商店 CI 校验 screenshots 失败不是合法字符串数组或图片缺失格式 [“./assets/screenshot-1.png”] 且文件真实存在
7装了但 --dump-config 看不到层层序或整行替换语义没吃透回到第 05 篇核对四层层序与覆盖语义

这张表的心法回到本篇主题:发布不是"npm publish 一下"就完,而是把 bundle 概念、打包不变式、分发方式、商店元信息、安装验证五件事全部对齐。任何一环漏了,都会在"别人装你的插件"那一刻爆雷,而不是在你本地跑的时候爆雷。

结语

这一篇把 DSH 插件发布串成了完整链路:两个概念(bundle 贡献什么 vs profile 由什么组成)、打包不变式(package.json 的 files/peer/exports 硬约束)、三种分发(npm 预构建 / tarball 离线 / git 直装需授权)、商店元信息(locale + icon + screenshots)、用户安装验证(dsh plugin add + --dump-config)。核心一句话:发布质量 = 对齐契约,而不是代码能跑——你的插件在别人机器上装不装得上,取决于你有没有把每一层的契约做对。

知识要点文字回顾:① bundle(贡献什么) vs profile(由什么组成) 是两个概念,没有东西同时是两者;② package.json 不变式:files 只发 lib 不发 src、cordis 同时进 peer+dev、schemastery 进 dependencies;③ 三种分发:npm 预构建零授权、tarball 离线、git 直装需 prepare+allowBuilds;④ 商店元信息 = locale(meta.title/description) + icon + screenshots.json;⑤ 安装后用 --dump-config 验证层被应用。

完结篇预告:《插件化是 Agent 应用层的未来吗?DeepSeek Harness 架构趋势前瞻》——回到本系列开头的判断,做一个收束和展望,关注 CSDN 主页 不错过更新。

你发布过 DSH 插件(或 npm 包)吗?卡在 files 白名单、git 授权还是商店元信息?评论区聊聊,我挨个回。本文事实基于 DeepSeek Harness 官方文档(打包与安装插件、添加 workspace 包手册,2026-10 版本),API 迭代快,有出入评论区提醒我。

参考资料(正文数据来源):DeepSeek Harness 官方文档《打包与安装插件》《实操手册:添加 workspace 包》《插件配置》。