[Bug] 用户配置未通过 schema 校验时被静默丢弃(零诊断):插件整体失效、开关弹回;GUI「更新」按钮会按陈旧记录降级重装
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
提交前确认 · Pre-submission checklist
- 我已搜索过现有 issue,确认这不是重复 / I searched existing issues and confirmed this isn't a duplicate.
- 我已阅读 CONTRIBUTING.md / I've read CONTRIBUTING.md.
问题类别 · Category
其他 / 不确定 · Other / Not sure(横跨配置校验 / 插件系统 / GUI,主报配置静默丢弃)
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
影响体验 · Major(插件系统整体不可用且无法自行排查,接近阻塞)
复现频率 · Reproducibility
必现 · Always(触发条件存在时 100% 复现)
问题描述 · Description
一次完整的插件系统故障排查中发现了 4 个相互关联的问题,其中问题 1 是根因,排查耗时远超预期,核心困难是全程零诊断输出:
问题 1(根因,严重):用户配置文件未通过 schema 校验时被整个静默丢弃,无任何诊断
~/.zcode/cli/config.json 的 provider 条目中存在 npm 字段(第三方管理工具写入),而捆绑 CLI(zcode.cjs 0.16.5)的 zod schema 定义为 npm: g.never()——该字段出现即导致整份配置 parse 失败,回退为空配置。实际后果:
- 所有 marketplace 来源插件(github、desktop-commander、superpowers、chrome-devtools-mcp、context7、serena)全部显示「未启用」,实际也未加载;
- 内置(bundled/seed)插件因走
officialPluginsEnabledByDefault默认启用管线而「看起来正常」,极具迷惑性; plugins list --verbose的 Diagnostics 区域完全不显示这次配置加载失败(该诊断未挂进 list 输出链);- 配置里其他段的失效也被连带掩盖(如 mcp.servers 自定义项)。
问题 2:GUI 启用开关「已启用」toast 后自动弹回,不提示任何失败原因
上述配置丢弃状态下,在插件管理页点击启用:弹出「已启用」提示,开关随即回到 OFF。真实原因(配置被丢弃导致启用状态无法生效)完全没有呈现给用户。
问题 3:「可更新」徽章不感知 GUI 之外的插件变更
手工将插件更新到与市场上游 pin 完全一致的版本(chrome-devtools-mcp 1.7.0 → 1.8.0,installed_plugins.json 的 version/sha 同步改写,cache 目录内容与市场 pin 逐字节一致),GUI 仍持续显示「可更新」。原因是 GUI 的安装记录(IndexedDB)仍记着装机时的 1.7.0,徽章基于 UI 侧记录而非实际安装文件计算。
问题 4:GUI「更新」按钮会按本地陈旧安装记录执行降级重装
针对问题 3 点击「更新」后,插件被从 1.8.0 降级重装回 1.7.0——更新流程读取的是客户端本地的陈旧安装记录/市场数据(快照文件 plugins/marketplaces/<id>/.claude-plugin/marketplace.json 我已手工更新到最新 pin,但更新流程没有使用它;该目录也不是 git 仓库、不会自动刷新)。也就是说:当本地市场数据陈旧时,「更新」按钮实际执行的是降级。
复现步骤 · Steps to reproduce
问题 1(其余问题均为其衍生或独立可复现):
- 在
~/.zcode/cli/config.json的任一provider条目中加入"npm": "some-package"(schema 中该键为g.never(),任何值都非法); - 运行
zcode plugins list(或打开桌面端插件管理页); - 观察到所有 marketplace 来源插件显示 disabled,且
--verbose下无任何 Diagnostics; - 删除该
npm字段后全部恢复。
问题 4:在插件 cache 目录手工将某插件更新到与市场上游一致的最新版本并同步 installed_plugins.json → GUI 显示「可更新」→ 点击「更新」→ 插件被重装回旧版本。
期望表现 · Expected behavior
- 配置文件校验失败时:在
plugins list(含--verbose)与桌面端显著位置呈现诊断(配置文件路径 + 失败原因 + 出错字段),严禁静默回退空配置;或至少降级为「忽略非法字段 + 警告」而非丢弃整份配置; - GUI 启用失败时 toast 展示失败原因(如「配置加载失败」),而非虚假的「已启用」后弹回;
- 「可更新」徽章基于实际安装文件(cache 内 plugin.json / installed_plugins.json)与市场上游比对计算,或提供「重新扫描已安装插件」入口;
- 「更新」流程使用最新市场数据并校验目标版本 ≥ 当前版本,避免降级重装;市场快照建议 git 化或提供自动刷新。
实际表现 · Actual behavior
见上。修复我本地问题的动作仅为:删除 provider 条目中的 npm 字段——其余所有字段(apiFormat/defaultKind/enabled/models/name/options/source)在 passthrough() 下均兼容。
ZCode 版本 · ZCode version
桌面版 3.11.2.6792(捆绑 CLI zcode 0.16.5,ZCODE_BUILD_COMMIT_ID 89817f5b)
设备 / 系统 / 浏览器 · Device / OS / Browser
Windows 11 Pro(10.0.26200)x64,桌面端 Electron
补充证据 · Evidence
- 定位方法:
USERPROFILE重定向 + junction 复用真实插件存储搭建沙盒,对 config.json 逐段/逐字段二分,最终锁定provider.*.npm; - schema 依据(zcode.cjs 0.16.5 反混淆):provider 条目 schema 为
{api?, id?, kind(必填), name?, npm: g.never().optional(), options?, headers?, models?}.passthrough(); plugins list --json对已装插件不返回updateStatus(GUI 的更新判定在另一条链路),排查期间 CLI 侧无法获得任何指向性线索。
如需完整的排查时间线或沙盒复现脚本,我可以补充。
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the invalid provider.npm case in ~/.zcode/cli/config.json and running zcode plugins list --verbose; trace how configuration diagnostics reach the CLI and desktop plugin manager. Then inspect installed_plugins.json and plugins/marketplaces//.claude-plugin/marketplace.json to compare update decisions. Done means configuration failures are visible, enablement reports errors, and updates cannot reinstall an older target version.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron
- Domain
- cli, desktop, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100