DSH 插件 Runtime Hoisting 冲突
DeepSeek Harness 插件依赖冲突:Runtime Hoisting
- 作者
- DeepSeekAgent.io 编辑部
- 发布
- 更新
DeepSeek Harness 的插件可以扩展模型、工具与 Agent Preset,但插件目录一旦出现第二套 DSH Runtime,问题会从“依赖版本冲突”升级为“同一进程里存在两个框架实例”。社区案例显示,在 Desktop Profile 中安装 @deepseek-ai/dsh-subagent-codex 后,pnpm 的 hoisted 布局与自动 Peer 安装把约 48 个 @deepseek-ai 包一并放进 Profile。冷启动时,内置 Preset 与插件分别解析到不同 Runtime,Standard 和 Cordis Preset 随后无法挂载。
为什么热运行正常,重启后才坏
安装插件时,当前进程里的核心模块与 Preset 可能已经完成加载,模块缓存也已经建立。新增的 Profile 依赖暂时没有改变已经解析的引用,因此界面仍能继续使用。
下一次冷启动会重新走 Node 模块解析。应用内置 Runtime 与 Profile 下被提升的 Runtime 同时可见,不同入口根据自身路径加载不同副本。于是故障在重启后集中出现,旧 Session 和新 Session 都可能打不开。
这类“安装当下没事、重启全坏”的时间特征非常重要。它将排查范围从普通 Preset 配置缩小到启动时依赖解析、模块缓存与插件目录布局。
两套 Runtime 为什么不能和平共存
DSH 的 Scope、Context、注册表和若干身份判断依赖模块级状态。即使两个包的版本号一致,只要它们来自两个物理模块实例,JavaScript 对象身份和模块级单例就已经分裂。
社区案例出现了两类典型错误:
persona-prefix already registered:两个运行时分别参与注册,重复初始化同一个能力;tool-subagent的modelSelectionSettings缺少 scoped Preset Context:对象由 Runtime A 创建,却被 Runtime B 的 Context 规则读取。
这说明问题不只是 API 形状不兼容。复制一份相同版本也会破坏 Scope 身份。对框架插件而言,核心 Runtime 更适合作为 Host 提供的 Peer,而不是被插件安装器复制进插件目录。
如何确认是 Hoisting 冲突
推荐保留 Profile 后做只读检查:
- 记录故障发生前安装的插件和准确版本;
- 查看 Profile 的
node_modules/@deepseek-ai是否突然出现大量核心包; - 比较应用内置与 Profile 中
dsh-*包的实际路径和版本; - 从报错栈确认 Scope、Preset、Context 分别解析自哪一处;
- 用干净 Profile 复现一次冷启动,避免把 Session 数据问题混进来。
临时移走 Profile 中被提升的核心 Runtime 可能恢复启动,但下一次插件安装或更新还会把它们重新生成。因此这只能用于确认根因和恢复工作,不是稳定修复。
插件发布和安装器应怎样处理
插件包应把宿主 Runtime 声明为 Peer,并避免发布锁死整个 DSH 依赖图的产物。安装器还需要做到:
- 解析插件前识别会落地第二套核心 Runtime 的依赖计划;
- 禁止或隔离
@deepseek-ai/dsh-*核心包的自动提升; - 在 Profile 启动前验证所有插件最终引用同一 Host Runtime;
- 安装完成后执行一次全新进程的 Preset 冒烟测试;
- 失败时回滚插件依赖图,不留下可被下次启动读取的半成品。
对用户而言,插件管理器显示“安装成功”还不够。真正的验收条件是重启 Desktop 后 Standard、Cordis、旧 Session 与插件 Preset 都能正常挂载。
这篇文章与DSH 插件管理器:安装、更新与回滚互补。管理器教程讲操作流程,本篇解释为什么框架 Runtime 不应被当成普通插件依赖复制。
参考资料
常见问题
两份 Runtime 版本相同,也会冲突吗?
会。模块路径不同就会产生不同实例,模块级单例、Scope 身份和 Context 判断可能分裂。
删除整个 Profile 是唯一恢复办法吗?
不是。先备份并定位被提升的核心包,隔离冲突依赖即可验证根因;正式修复仍应调整安装计划或插件依赖声明。
为什么旧 Session 也打不开?
旧 Session 启动同样需要挂载 Preset 和 Context。共享启动链失败后,故障不会只影响新安装的插件。