Replies: 3 comments
|
我也遇到了,有解决方案吗 |
|
你的诊断完全正确,而且「健康检查通过」这一点我可以给出字面证据。 已端到端验证的修复:
|
| 运行 | 启动时预设键 | roster 标记 | 会话创建 |
|---|---|---|---|
| 未挂插件 | text |
broken: null(报告为健康) |
失败:$.prefix missing required value |
| 挂上插件 | prefix |
broken: null |
成功 |
关于「没有任何校验」这一点,我可以补一条精确证据:compositionProblem()(packages/preset/agent-presets/src/discovery.ts:225)只做两件事 —— 用 entryListProblem() 检查行的形状,以及检查行里的包能不能解析;entryListProblem() 的注释明说它 "不解析插件名、也不套用 config"。所以你说的「健康检查通过」是字面意义上成立的:我实测该预设的 broken 字段就是 null,它确实被判为健康。
插件怎么修:启动时对每个 trust === 'user' 的预设根,扫描 agent.cordis.yml,把 persona 行 config 块里遗留的 text 键改名为 prefix。改写极其保守:除那一行外每一行、注释、空行必须逐字节相同,否则拒绝写入;会重新扫描自己的输出;流式写法只报告不猜测;shipped/configured 根一律不碰;原文件保留为 .dsh-preset-migrate.bak。
迁移在 apply() 内同步完成。loader 的兄弟 entry 是并发应用的 —— 我第一版是异步的,测试里就抓到了竞态:文件还没落盘,会话却已经开始挂载。同步执行消除了这个窗口。
边界:这是插件不是上游补丁。它没有让 discovery 去校验 config schema,所以未来别的字段改名仍会同样静默地坏掉 —— 那才是真正该修的地方。
Verified fix: dsh-plugin-preset-migrate
- npm: https://www.npmjs.com/package/dsh-plugin-preset-migrate
- Source / raw reproduction transcripts: https://github.com/Robin1987China/dsh-preset-guard (
docs/verification.md)
I reproduced it end to end against the real preset machinery: copied the shipped standard preset into a user preset, reverted only the persona row's prefix: >- back to text: >-, then created a session through the real sessionController.create({ agentPreset: 'broken-persona' }).
| Run | Preset key at boot | Roster marker | Session creation |
|---|---|---|---|
| Plugin absent | text |
broken: null (reported healthy) |
fails: $.prefix missing required value |
| Plugin mounted | prefix |
broken: null |
succeeds |
One precise addition to your "no preset validation runs" point: compositionProblem() (packages/preset/agent-presets/src/discovery.ts:225) does exactly two things — entryListProblem() for the row shape, and a package-resolvability check. entryListProblem()'s own comment says it "does not resolve plugin names or apply configs". So "healthy" is literally true: I measured the preset's broken field as null.
The plugin migrates the stored files at start, for trust === 'user' roots only, renaming the legacy key inside a persona row's config block. The rewrite is conservative: every other line, comment, and blank line must be byte-identical or it refuses to write; it re-scans its own output; flow-style configs are reported, never guessed at; the original is kept as .dsh-preset-migrate.bak.
It runs synchronously inside apply(). Sibling loader entries apply concurrently — my first, async version lost that race in the harness (the file was still text when the session began mounting), which is why the shipped version is synchronous.
Scope: a plugin, not an upstream patch. It does not teach discovery to validate config, so a preset broken by some other future rename still fails silently. That is the real fix.
|
更正:我上一条回复里推荐的 我把「过期默认 preset id」和「预设文件里的改名残留」这两个同源问题拆成了两个包,这是我判断失误 —— 装上要装两次、挂要挂两次。现在已收敛:
dsh plugin --profile <你的 profile> add dsh-preset-guard
# 或一次装齐:
dsh plugin --profile <你的 profile> add dsh-community-fixes前者需要再加一行 为一次反复的安装指引致歉 —— 那是我把每个 bug 都单独发包造成的碎片化。 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
English TL;DR
A breaking config-field rename in the official
@deepseek-ai/dsh-personaplugin (text→prefix, shipped in 0.1.5-rc.1) silently breaks every user custom agent preset that references persona. Because custom presets persist under~/.dsh/.agent-presets/and survive both DSH upgrades and reinstalls, a routine version bump bricks all "New Session" creation: the UI shows nothing, the only trace ispersona: invalid config: $.prefix missing required valuein the Host log. Client-sidestartSession()swallows the failure intoconsole.warn. No preset validation runs on upgrade, no migration of user preset files, no UI error surfaced.🐛 问题描述
0.1.5-rc.1 中官方插件
@deepseek-ai/dsh-persona将配置字段从text重命名为prefix(Configschema 从text: z.string().required()改为prefix: z.string().required()),但既没有版本迁移脚本,也没有在升级时校验用户自定义预设。用户存放在~/.dsh/.agent-presets/下的自定义预设(如dailyagent)中所有引用 persona 的配置条目全部失效。由于agent-presets默认值指向该自定义预设,所有新会话的 session resume 阶段挂载预设时失败,sessionController 服务不可用,「新会话」按钮点击无任何可见反应。复现步骤
@deepseek-ai/dsh-persona的自定义预设,配置形如:pnpm add -g @deepseek-ai/dsh@0.1.5-rc.1或 source build)。dsh web,打开任意已有会话,点击「新会话」(+)。期望行为
text→prefix),或在 UI 中明确提示"以下预设配置已过时,请手动更新";persona: $.prefix missing required value),并提供一键回退到内置默认预设的操作;实际行为
模型操作失败:gateway/internal: resume failed for session "…": RemoteError: agent-presets: preset "dailyagent" failed to mount: failed to apply loader entry persona (@deepseek-ai/dsh-persona): invalid config: - $.prefix missing required value (at prefix) (/Users/lion/.dsh/.agent-presets/dailyagent/agent.cordis.yml);代码定位
服务端(persona 配置 schema 破坏性变更)
packages/preset/persona/src/index.ts:无版本迁移逻辑、无 deprecation warning、无 fallback 到旧字段名。
客户端(静默失败)
packages/client/ui-workspace/src/client/navigation.ts:154-172,startSession():失败分支仅
console.warn,UI 无任何反馈。预设持久化(重装无法自救)
自定义 Agent 预设持久化在
~/.dsh/.agent-presets/(用户主目录),不在 npm 安装目录下。重装 DSH 后该文件原样保留;只要它仍是 In use 预设,重装完成后新会话依旧全部失败。附加问题:llm-pi-ai settings 校验级联故障
packages/llm/llm-pi-ai/src/index.ts:298-304,validate回调在registering = false后调用assertServiceable(value, current())(strict 模式),当用户settings.yaml中opencodeprovider 的 models 缺少api字段时抛出PiAiCatalogError,导致 llm-pi-ai 命名空间更新失败,可能级联导致 Host 服务初始化卡死。此问题在 npm 包 0.1.5-rc.1 中同样存在。与现有讨论的关系
影响
~/.dsh/.agent-presets/,重装 DSH 完全无法修复,用户最常见的自救手段在此失效,只会加深"DSH 本身坏了"的误解;assertServiceablestrict 模式校验会在 settings 变更时抛异常,导致 Host 初始化卡死(CPU 90%+ 持续 90 秒),加剧 sessionController 不可用;~/.dsh/.agent-presets/dailyagent/agent.cordis.yml把text改成prefix,或切换到内置默认预设,这远超普通用户的排查能力。改进建议
postinstall迁移脚本或在 Host 启动时自动修复用户预设文件中的旧字段名,至少输出明确的 deprecation warning;dsh升级后首次启动时做一次预设 mount 试探(dry-run),不可用则警告用户并阻止设为默认;resolveProfiles(value.providers, 'deferred');navigation.ts的startSession()失败分支应调用全局错误通知机制(toast/error banner),而非仅console.warn。All reactions