Repository navigation
Open
Labels
bugSomething isn't workingSomething isn't workingkeep-open排除无反馈自动关闭,适用于已确认未修复或等待交付的问题排除无反馈自动关闭,适用于已确认未修复或等待交付的问题
Description
环境
- DSH Desktop 0.8.2(Windows 10 x64,官方安装包)
- 内置
dsh-desktop-market-installer(随 0.8.2) - profile:
web;迁移候选(来自 profiledependencies):@deepseek-ai/dsh-code-runtime、@deepseek-ai/dsh-tools、zod
症状
冷启动维护执行生成代迁移,对第一个候选(@deepseek-ai/ 前缀插件)install/promote 成功后立即失败,回滚并进入 6 小时 defer:
[desktop] migration: moving 3 plugin(s) to generations: @deepseek-ai/dsh-code-runtime, @deepseek-ai/dsh-tools, zod
[desktop] generation-install: installing 0.1.0-rc.8 into staging
[desktop] generation-install: installed in 1506ms
[desktop] generation-install: hoisted 1 host singletons: @deepseek-ai/dsh-code-runtime…
[desktop] generation-install: promoted to deepseek-ai+dsh-code-runtime+0.1.2-rc.1+0624d5844169
[desktop] migration failed, restoring the pre-upgrade profile: ENOENT: no such file or directory, open 'C:\Users\<user>\AppData\Roaming\dsh-desktop\harness\profiles\.generations\live\deepseek-ai+dsh-code-runtime+0.1.2-rc.1+0624d5844169\node_modules\@deepseek-ai\dsh-code-runtime\package.json'
[desktop] profile maintenance frozen: migration deferred (ENOENT: ...)
关键点:promoted to 已成功,随后却在新生成代里找不到插件自己的 package.json——错误路径就是 node_modules/@deepseek-ai/dsh-code-runtime/package.json。
根因(代码级)
packages/dsh-desktop-market-installer/generations/installer.mjs:
hoistHostSingletons(stagingDir)通过walkGenerationPackages遍历生成代内所有node_modules,isHostSingleton(name)命中(/^@deepseek-ai\//)的包一律删除。- 该清理没有排除『生成代的宿主插件自身』:当插件名本身以
@deepseek-ai/开头时(如@deepseek-ai/dsh-code-runtime、@deepseek-ai/dsh-tools,它们是常见的 profile 依赖),walk 会命中插件根并把插件自己删掉。 installGeneration对插件包的existsSync检查发生在 hoist 之前,所以 install 返回 ok;直到validateGeneration读<generation>/node_modules/<plugin.name>/package.json才爆 ENOENT → 迁移整体回滚 + defer。- 实测佐证:
hoisted 1 host singletons: @deepseek-ai/dsh-code-runtime…里被删的名字,正是随后 validate 找不到的那个;生成代目录下node_modules/@deepseek-ai/为空。
(hoist 删除嵌套的 @deepseek-ai/* 副本是预期行为;这里的问题是根插件也被一并删了。)
影响
- 只要迁移候选里有一个
@deepseek-ai/前缀插件,migrateProfileToGenerations每次都失败(retryAfter +6h 重试、再失败),生成代机制与依赖其完成的行为全部被冻结。 - 非
@deepseek-ai前缀的候选插件本身不受此条影响,但会被前面插件的失败连坐回滚。 - 疑似与 [Bug][Windows] Plugin migration freeze keeps profiles/web/node_modules junction on stale generation - sidebar 'Open with' silently loads unpatched client code #391 属同族(迁移失败被冻结)但触发点不同:本条是 staging/validate 阶段的确定性失败,与 peer 校验无关。
建议修复
在 hoist 时排除生成代自身的根插件:installGeneration 内本就有 pluginName,可传给 hoistHostSingletons 并在 walk 时跳过 join(generationDir, 'node_modules', pluginName);或改为只 hoist 嵌套副本、不触碰顶层插件根。修复后 @deepseek-ai/* 前缀插件即可正常迁移。
(现场已临时用 .generations-migrated 标记冻结迁移以规避,未在本机验证修复补丁。)
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingkeep-open排除无反馈自动关闭,适用于已确认未修复或等待交付的问题排除无反馈自动关闭,适用于已确认未修复或等待交付的问题
Activity
jiangxiao642-spec commentedon Sep 12, 2026
补充:hoist 之外还有一道生成代准入坎(收窄上文一处预期)
我们继续在本机追了整条迁移链,结论需要收窄上面「修复后
@deepseek-ai/*前缀插件即可正常迁移」的说法:修好hoistHostSingletons的自吃问题后,这三个候选依然不会被接受为生成代——它们过不了validateGeneration的补丁层校验(除非上游为这些包补上dsh.bundle声明,而它们本不是组合包,见下)。证据一:
validateGeneration对每个迁移候选硬性要求可读的 bundle 补丁(0.8.2 桌面主进程实测,原样摘录):即:候选包必须自带
dsh.bundle.patch指向可读文件,否则迁移在 validate 阶段以generation has no readable bundle patch抛错。证据二:三个候选都没有
dsh.bundle字段。 npm 全版本复核:@deepseek-ai/dsh-tools:已发布 21 个版本,全部无dsh.bundle.patch@deepseek-ai/dsh-code-runtime:已发布 20 个版本,全部无zod:通用库,无该字段(本机 4.6.2 亦无)对照组(真正的组合包):
@deepseek-ai/dsh-base:21 个版本全部带"dsh": {"bundle": {"patch": "./cordis.patch.yml"}}@deepseek-ai/dsh-web-app:同带证据三:同一「必须有补丁层」的假设贯穿启动与投影两侧。
dsh-app-boot解析dsh.profile.bundles每个条目时,无dsh.bundle会直接以declares no dsh.bundle失败(源码注释明言这是有意为之的 fail-loud);projection.mjs的declaresBundle()也只把带补丁的依赖算作组合层(组合进bundles的最小口径)。小结: 这三个候选不是「组合包(bundle)」,而是 profile 的普通依赖——生成代机制对它们本就不适用。
zod的情况见 #403,三者卡在同一处。看起来是两条口径的错位:迁移候选取「profile 的
dependencies与dsh.profile.bundles合并,再剔除保留集(dshmarket、dsh-base、dsh-web-app)之后剩下的全部名字」(本次的三个候选即由此而来);而生成代准入要求「必须声明dsh.bundle」。普通依赖天然不满足后者。建议一并考虑:dsh.bundle的包;普通依赖留在 pnpm 依赖集按常规方式升级,不参与生成代。dsh.bundle的包给出明确行为与提示(跳过/说明原因),避免用户走进必失败分支。以上均为桌面 0.8.2 / harness 0.1.2-rc.1 / Windows 10 的本地实证。现场我们保留着,需要脱敏日志或目录快照可以随时提供;后续版本修复后我们愿意帮验证。
suizhejiu commentedon Sep 13, 2026
另一台机器上复现了同一机制,补充佐证(插件为
@deepseek-ai/dsh-mcp-client@0.1.1-rc.1,profileweb,DSH Desktop 0.8.1 → 0.8.2 均存在):文件系统核实:
<DSH_HOME>\profiles\.generations\live\下 6 个 generation 的node_modules\@deepseek-ai\全部是空目录,插件自身的包目录确实不在生成代里;而预检又要求<gen>\node_modules\<pluginName>\package.json必须存在。时间线补充:09-12 03:02 与 11:08 两次自动重试都失败(网络正常,已 pin 镜像,生成代 install/promote 均成功),维护持续冻结,profile 的锁文件至今未被同步。该 profile 的三个官方插件全部是
@deepseek-ai/前缀,因此迁移永远不会成功。影响面提示:同一校验(
verifyGenerationPeers)也被市场安装路径调用(out/main/index.js中的调用点),因此从市场安装@deepseek-ai/前缀的插件可能同样直接报"包根缺失"。建议修复方向:清理宿主包时排除
generation.pluginName自身(或只清理嵌套node_modules),预检改为从共享树/安装闭包解析插件自身。同一台机器上这次排查的完整记录(含临时缓解与回滚步骤,已脱敏):https://gist.github.com/suizhejiu/b13d0287216d71831cc789e299572173
yaojin3616 commentedon Oct 28, 2026
v0.13.0 发布后状态复核:
复核发现该报告后续补充包含两层问题:host singleton hoist 对根包的处理,以及普通依赖没有 dsh.bundle.patch 时不应进入组合包迁移。后者仍由未合并 PR #812 跟踪,因此不能整体按 v0.13.0 已修复关闭。待包含该修复的版本发布后,应按普通依赖/组合包分别验证迁移、重启和加载结果。
版本入口:https://github.com/dataelement/dsh-desktop/releases/tag/v0.13.0
反馈请隐去 token、账号凭据、完整会话和其它敏感信息。