# 发布与分发 记录「怎么把这个插件发出去、怎么让别人装上、发新版要动哪些地方」。 信息来源分三类,**引用时请按来源定级**: - **DSH 源码**(本机解包的安装体)—— 硬事实,可复核。 - **社区目录自己的文档** —— 对方声明的规则,会变,链接随文给出。 - **本机实测** —— 标明命令与观测结果。 --- ## 1. DSH 产品本身没有「插件市场」 在安装体的全部 `@deepseek-ai/*` 包里搜 `marketplace`:**零命中**。名字最像的 `dsh-plugin-package-inventory-deepseek` 也不是市场,它的作用是把**已装载**的插件清单 上报给 DeepSeek LLM API(遥测/归因)。 客户端里与插件相关的界面只有两处:Web 侧边栏的 **Plugins** 页(管理本 profile 的 bundle、可按 spec 新增)与 Settings 里的只读清单。**没有可浏览、可提交的第三方目录。** 所以「上架」这件事在 DSH 侧不存在;分发靠的是 **npm / git / 路径 / tarball** 四种 spec (见第 4 节),「被发现」靠的是社区约定(第 2 节)。 --- ## 2. 社区生态的载体是 GitHub topic `dsh-plugin` 社区围绕一个 GitHub topic 建目录,各目录都按它做发现。查询入口: | 目录 | 说明 | |---|---| | [`vbarter/dsh-plugin-registry`](https://github.com/vbarter/dsh-plugin-registry) | 注册表,站点 ;`data/plugins.json` 为 schemaVersion 2 | | [`hikariming/dshfind`](https://github.com/hikariming/dshfind) | 「插件市场与最佳实践」 | | [`kejixiaoliang/awesome-dsh-plugins`](https://github.com/kejixiaoliang/awesome-dsh-plugins) | 分类精选目录 | | [`billLiao/awesome-dsh-plugin`](https://github.com/billLiao/awesome-dsh-plugin) | 定时同步的清单 | | [`fegnze/dsh-plugin-scout`](https://github.com/fegnze/dsh-plugin-scout) | 按 topic 发现 + 信任评分 | ### 注册表的收录契约(来自对方的 README 与 ) **自动发现**每 2 小时(cron `20 */2 * * *`)跑 `topic:dsh-plugin`,读每个仓库**根目录** `package.json`,要进「可安装」列表需同时满足: | 条件 | 本仓库 | |---|---| | 公开且可读(能取到仓库元数据与根 `package.json`) | ✅ | | 仓库声明 **`dsh-plugin`** topic | ✅ | | 根 `package.json` 的 `dsh.bundle.patch` 是**安全的相对路径**(不能绝对路径、不能用 `..` 逃出仓库根) | ✅ `./cordis.patch.yml` | | 未归档、非 Fork | ✅ | 缺 `dsh.bundle` 的仓库仍会出现在浏览页,只是不带安装命令(状态「缺少有效 dsh.bundle」)。 所有目录写入都走 PR(自动发现开 `discover/sync`,用户提交开 `submission/`), **维护者合并后站点数据才更新**——不是加完 topic 立刻可见。 **验证边界(对方明说)**:只核对公开元数据与 manifest 结构,**不运行插件代码、不验证 安装后行为、不持续盯权限变化**。目录里出现不等于安全背书。 --- ## 3. 发布 = 加 topic,然后等 1. 仓库 **About → ⚙ → Topics** 加上 `dsh-plugin`(必需)。本仓库另加了 `deepseek-harness`、`dsh`、`cordis-plugin`、`dsh-plugins`、`dsh-skill`、 `dsh-desktop`、`dsh-plugin-desktop`、`dsh-plugin-market` 以便多覆盖几个目录。 2. 等下一轮扫描(≤2 小时)开出发现 PR,维护者合并后出现在站点。 3. **(可选,曝光更好)** 走人工提交:打开 , 输入 `owner/repo` 做浏览器预检 → 提交会开预填的 GitHub Issue → Action 预检后 写 `data/plugins.json`(`source: "curated"`)或 `data/submissions.json`(待审)→ 开 PR。 > 自动发现进的是 `source: "discovered"`,人工提交进的是 `curated`。后者通常排序更靠前。 --- ## 4. 用户怎么装(`installBundle` 的四类 spec) `plugin_manager` 的 `installBundle` 接受: | spec 形式 | 说明 | |---|---| | 注册表包名 | 走 `pnpm view` 查注册表;默认 npmjs,回退 `https://registry.npmmirror.com/` | | **git 地址** | 支持 GitHub;安装前先 `git ls-remote` 探活(`githubConnectionTimeoutMs` 默认 5000 ms) | | 绝对路径 | 本地开发态;`pnpm` 生成 `link:` | | tarball | `npm pack` 的产物 | 命令行等价物(**会自动把 bundle 写进 `dsh.profile.bundles`**,不需要手工编辑): ```bash # 从 GitHub(当前可用,无需 npm 账号) dsh plugin --profile add github:yxdotnet/dsh-persona-driven # 从本地目录(开发态) dsh plugin --profile add <本仓库目录> # 发布到 npm 之后 dsh plugin --profile add @dsh-external/persona-driven ``` 也可在 Web 侧边栏 **Plugins** 页粘贴同一个 spec。 **本机实测(2026-10-17)**:`dsh plugin --profile pdmarket add github:yxdotnet/dsh-persona-driven` → pnpm 9.1 秒、exit 0、自动写入 `dsh.profile.bundles`;`--dump-config` 出现 `- id: persona-driven` 且零警告;headless 启动无插件报错;会话日志里技能确实进入 ``。 ### 版本兼容检查 安装前会校验 DSH peer 版本(本地路径读它自己的 `package.json`;注册表 spec 通过 `pnpm view` 解析所选版本声明的 peers)。不兼容会以 `incompatible-version` 拒绝, **在下载之前**中止。git / tarball spec 只能装完再判,失败会回滚 manifest 与 lockfile。 万一需要放行,用版本豁免(写在 profile 的 `compatibility.json`): ```bash dsh plugin --profile version-exemptions dsh plugin --profile allow-version <包@版本> --dsh-version <运行时> --accept-risk ``` 本包的声明是 `@deepseek-ai/dsh-llm|dsh-skill|dsh-tools: >=0.0.1-rc <2`、 `schemastery: ^3.18.0`,且全部标为 optional peer —— 当前运行时 `0.2.0-rc.2` / `~3.18.4` 均满足。 --- ## 5. 发新版的清单 版本号只有 `package.json` 一处是真相源(`lib/` 里没有硬编码版本)。要同步的地方: | 位置 | 说明 | |---|---| | `package.json` → `version` | 唯一真相源 | | `CHANGELOG.md` | 新增一节;文件头写了版本号约定(插件大版本对应技能版本) | | `docs/安装与验收.md` | 体检示例输出里有一行带版本号的「包」——改版本时一并更新(**不要在这里写死当前版本号,会漂移**) | | **文档里的断言总数** | README ×2、`docs/安装与验收.md`、`docs/架构与移植说明.md`、`docs/发布与分发.md` 五处写死了「N 条断言」——增删用例时必须一起改。**已经漂移过两次**(223→224、224→247),所以它是清单项,不是可选项 | | **打包面不得含 `.pyc`** | `package.json` 的 `files` 里有 `!skills/**/__pycache__` 与 `!skills/**/*.pyc`。npm 的 `files` 会**压过** `.gitignore`,靠 .gitignore 拦不住(踩过:104.7 KB 的字节码被打进包)。`tests/doctor.mjs` 已断言这两条声明存在 | | `skills/persona-driven/SKILL.md` → `metadata.version` | **技能自己的版本线**,与插件版本无关,只有技能内容变了才动 | | `skills/persona-driven/scripts/*` | 版本在 `SKILL.md` 里;脚本自身不含版本号 | 发版流程: ```bash cd <本仓库目录> # 1) 改版本号(package.json + CHANGELOG + docs 示例输出) # 2) 跑全量验证:247 条断言 + 安装自检 npm test # 3) 确认打包面:文件清单里没有多余文件(当前健康值:39 个文件、约 229 KB; # **必须不含 .pyc / __pycache__** —— npm 的 files 会压过 .gitignore,只靠 .gitignore 拦不住) npm pack --dry-run # 4) 提交并推 git add -A && git commit -F # 提交信息建议用文件传,避免引号/换行被 shell 拆开 git push origin main # 5) (可选)从 GitHub 装一次,验证发布物本身可安装 dsh plugin --profile <临时 profile> add github:yxdotnet/dsh-persona-driven # 6) (可选)打 tag git tag -a v1.6.x -m "..." && git push origin v1.6.x ``` **注意**:本地 `node_modules` 不能存在(DSH 的运行时解析器会把仓库根的 `node_modules/@deepseek-ai` 当成「本地候选包」,让已安装的插件与宿主加载两份 `dsh-llm`)。跑 `tests/plugin-wiring.mjs` 用 `PERSONA_DSH_NODE_MODULES=<一份 DSH 的 node_modules>`, 不要建软链。 --- ## 6. 还没做的两件事 1. **npm 发布**。需要 `npm login`,并确认 **`@dsh-external` 这个 npm scope 属于你**—— 不是的话 `npm publish` 会 403;改包名会连带改 `cordis.patch.yml` 的 `name`、 `lib/index.js` 的注册名与全部文档。当前 GitHub 通道已经可用,npm 只是额外的 版本固定与可发现性。 2. **人工提交到注册表**(`source: "curated"`),比只靠自动发现曝光更好。