内网离线怎么更新 dsh plugin?DeepSeek Harness 插件离线包替换与 profile 校验
内网离线更新 dsh plugin,难点不在命令而在「包从哪来」和「装到哪去」:内网连不上公共 registry,所以要先把新版插件的 tgz 包在联网机器上准备好再搬进来,然后用 dsh plugin --profile <名字> add ./<包名>-<新版本>.tgz 把它覆盖进目标 profile;换完用 dsh plugin --profile <名字> list 与 dsh --profile <名字> --dump-config 两处校验,装坏了拿旧版 tgz 再 add 一次退回(来源)。
离线更新和在线更新差在哪:dsh plugin 一个取包、一个装包
在线更新是让 pnpm 去 registry 取新版;离线更新把「取包」这一步搬到有网的机器上单独完成,内网只做「装包」这一步——两者的落点完全相同,都是 $DSH_HOME/profiles/<名字> 这个目录(来源)。 所以整条链路只有两问:
- 包从哪来:联网机器打 tgz、私有源、或作者发布好的 tarball;
- 装到哪去:
dsh plugin --profile <名字> add <本地路径>,目录必须写准。
动手前先分清对象:本体的离线安装与插件的离线更新是两条不同的路。 前者见《内网、离线环境怎么装 dsh?》,本篇只讲已经装好的 DSH plugin 怎么换到新版。
离线拿到新版 dsh plugin 包的三种途径
内网拿不到公共 registry,新版插件包就必须先在联网环境准备好:作者或官方发布的 tgz、自己用 pnpm pack 打出的 tgz、私有 registry 里的包(来源)。 三条路各有适用场景:
-
直接搬作者发布的 tarball——最省事。
dsh plugin add的目标本来就允许写.tgz路径,作者打好的发布物搬进来即可,不用再自己构建。 -
在联网机器上自己打一份——源码就在你手上时用这条:
# 联网机器:进入插件源码目录后打包
pnpm pack
# → dsh-hello-plugin-0.2.0.tgz
注意打包顺序:pnpm pack 只把产物收进压缩包,prepare 这类构建脚本必须先在联网机器上跑完,否则搬进去的是一个缺产物的空壳。
- 走私有 registry——内网有 Verdaccio 之类的私有源时,把新版发布到内网源,内网端照常写包名安装,只是 registry 指向内网地址。这条路额外解决了依赖解析问题,见下一条提醒。
一个最容易踩的点:tgz 里只有插件本体。如果新版引入了原来没有的依赖,而 profile 里又没有这些依赖,pnpm 在安装时仍会去 registry 解析它们——完全断网时,要么把依赖一并带进来,要么用私有源兜住,否则命令会在解析阶段就失败。
把新包覆盖进正确的 profile:dsh plugin add 本地路径怎么写
覆盖升级就是对新版 tgz 再跑一次 add:dsh plugin --profile <名字> add ./<包名>-<新版本>.tgz,pnpm 会用新版本替换 package.json 里那条依赖与 node_modules 中的旧内容(来源)。 完整动作分四步:
- 先确认装到哪个 profile。
--profile必填且无短写,它决定改的是$DSH_HOME/profiles/<名字>这个目录:
ls "$DSH_HOME/profiles"
内网机器上常有多个 profile,装错目录等于白忙——多 profile 的隔离细节见《多个 profile 装同一个 dsh plugin》。
-
核对「是不是该升这一版」。在线环境里可以打开 DSH Plugin Hub 的设置 → 插件市场,在卡片上核对插件名、作者与最新版本号,再决定把哪一个 tgz 搬进内网。版本对不上时,先怀疑搬运环节拿错了包。
-
执行覆盖安装。
--profile之后的参数会整条转发给该 profile 目录里的 pnpm,所以本地 tarball 与本地目录两种写法都成立:
# 本地 tgz:离线更新最常用
dsh plugin --profile web add ./dsh-hello-plugin-0.2.0.tgz
# 本地目录:以 link 形式装入,改完即时生效,适合内网边改边测
dsh plugin --profile web add ./dsh-hello-plugin
- 留意
dsh.bundle的处理。新版包如果声明了dsh.bundle,dsh 会把它追加进 profile 的dsh.profile.bundles;包名已在清单里时不会重复追加,配置层保持唯一(来源)。
搬包到另一台机器时顺带看一眼依赖写法:用本地路径装过的插件,在 profile 的 package.json 里记的是 file: 形式的相对路径,换机器后这个相对路径也要成立,否则新版装不上。
换完怎么校验 dsh plugin 版本与生效,装坏了怎么退回
校验分三层:list 给出的版本号、profile package.json 里的依赖值、--dump-config 的组合树;退回则是对旧版 tgz 再 add 一次(来源)。 按顺序做四步:
- 看版本号是否真的换了:
dsh plugin --profile web list
这条命令的结果由 profile 目录里的 pnpm 给出,能看到包名与当前版本号。
- 看配置层是否还在:
dsh --profile web --dump-config | grep -n "# =="
插件生效时组合树里会有一层 # == <包名>,升级后这一层应当仍在(包名不变)。
-
看新能力是否出现:新版带来的工具或设置项,应该在工具列表、设置页里出现。这一条是「包换了但没生效」和「确实升级成功」的分界线。
-
装坏了就退回旧包,还是同一条命令,只把路径换成旧版 tgz:
dsh plugin --profile web add ./dsh-hello-plugin-0.1.0.tgz
退回前建议先整目录备份,万一新包把 package.json 改乱,能一把还原:
cp -r "$DSH_HOME/profiles/web" "$DSH_HOME/profiles/web.bak"
如果你遇到的不是「装错了包」而是「新版与当前 DSH 不兼容」,处理思路不同,见《DeepSeek Harness 更新后 DSH plugin 不兼容?》。
DSH plugin 离线更新的注意事项
一句话总结:离线更新搬的是「包」不是「注册表」,所以包要带全、目录要写准、版本要能退。 七条提醒:
- 先分本体与插件:本篇只管已装插件的离线升级,dsh 本体的离线安装见《内网、离线环境怎么装 dsh?》;
--profile必填且无短写:省略即非零退出;装之前先ls "$DSH_HOME/profiles"确认目标目录;- tgz 要打全:
pnpm pack只收产物,构建脚本必须在联网机器上先跑过,否则搬进来的是缺文件的包; - 依赖要有着落:本地 tgz 的传递依赖仍需可解析,完全断网时用私有源兜住,或把依赖一起带进来;
- 以版本号为准:升级后用
dsh plugin --profile <名字> list看版本,不要只凭命令是否成功退出下结论; - 升级前备份 profile:
cp -r "$DSH_HOME/profiles/<名字>" "$DSH_HOME/profiles/<名字>.bak",退回时整目录还原最稳; - 搬之前先核对:内网拿不准版本时,先在联网环境用 DSH Plugin Hub 核对插件与版本号,避免白搬一趟。
不想手工搬包的话,DSH Plugin Hub 的插件市场在有网环境里能直接点更新,卡片上的版本徽标与信任确认弹窗还会告诉你这次升级改了什么;只有真正断网的内网才需要走上面这条离线链路。

常见问题
内网离线更新 dsh plugin 换的是「包的来源」而不是安装方式:先在联网机器上把新版插件打成 tgz 或放进私有源,再把包搬进内网,执行 dsh plugin --profile <名字> add ./<包名>-<新版本>.tgz 覆盖安装。因为本地 tgz 不经过公共 registry,所以这条链路在断网环境同样成立,只要该包的依赖在 profile 里已经可解析。
dsh plugin 支持本地 tgz:add 之后的目标本来就允许写本地路径,完整命令是 dsh plugin --profile <名字> add ./hello-plugin-0.2.0.tgz,--profile 必填且决定改的是哪个 profile 目录。已经装过同名插件时,这条命令就是覆盖升级,pnpm 会用新版本替换依赖与 node_modules 里的旧内容。
确认 dsh plugin 离线升级是否成功要看三处:dsh plugin --profile <名字> list 输出的版本号是否为新版、profile 的 package.json 里依赖条目是否已更新、dsh --profile <名字> --dump-config 里那一层 # == <包名> 是否还在。三处一致才算升级到位,只看命令退出码不足以判断。
退回旧版 dsh plugin 就是把旧包再装一次:执行 dsh plugin --profile <名字> add ./<包名>-<旧版本>.tgz,pnpm 会用旧版本覆盖回去。更稳的做法是升级前先整目录备份 profile(cp -r "$DSH_HOME/profiles/<名字>" "$DSH_HOME/profiles/<名字>.bak"),退回时直接把备份目录换回来。
自己打的 dsh plugin tgz 只包含插件本体,传递依赖仍要由 pnpm 去解析——完全断网时就会在解析阶段失败。要么在内网搭一个私有源兜住这些依赖,要么把依赖一起打成包带进来;另一个常见原因是打包前没跑构建脚本,产物缺失会让安装后的加载阶段直接报错。
相关术语
- tarball(tgz)
- tarball 是 npm 生态里的包压缩格式,扩展名为 .tgz,内容为构建产物加 package.json。dsh plugin add 的目标可以是一个本地 tgz 路径,因此它天然适合把插件包搬进没有公共 registry 的内网环境。— dsh CLI README
- pnpm pack
- pnpm pack 是在包目录里生成 tgz 的命令,产出的压缩包与发布到 registry 的内容一致。它只打包产物,prepare 之类的构建步骤需要在打包前单独执行,否则包内会缺文件。— DeepSeek Harness 官方文档 - 打包与安装插件
- 覆盖安装(in-place upgrade)
- 覆盖安装指对已装过的同一个包再次执行 add,pnpm 会用新版本的依赖值替换 package.json 中原有的那一条,并更新 node_modules。离线更新插件走的就是这个动作,只是目标换成本地 tgz 路径。— dsh CLI README
- 私有 registry
- 私有 registry 是部署在内网、供受控环境使用的包源,形态类似 Verdaccio。把它配到 profile 的 npm 配置后,内网端可以照常写包名安装,pnpm 从内网源取包与依赖,不必访问公共 registry。— dsh CLI README
来源
- dsh CLI README· deepseek-ai
- DeepSeek Harness 官方文档 - 打包与安装插件· deepseek-harness