主人报障:「为什么中文搜索接口……下拉菜单里全给的英文名?你甚至不愿意带个括号 把中文名写上去」。根因不是漏写文案,而是整条链路没有「显示名」的位置:字段 声明只有 optionsFrom,候选动作回的就是 KnownNames() 的纯 id 数组。 - 后端:候选改为对象数组 {value,label};label 表与接入位表同源(键用 NameSearXNG 等常量),未知 id 原样回。value 逐字等于 KnownNames()。 - 前端:下拉/多选「显示 label、写 value」;表格单元格按 value→label 索引显示, 查不到回落显示原值。多选从裸输入框改成「候选开关 + 落盘值输入框」。 解码器本就兼容裸字符串/{value,label}/{id} 三形状 ⇒ 其他插件零影响。 中文名逐字:SearXNG 本地兜底(searxng)/ 智谱 BigModel(zhipu)/ 阿里云 IQS 信息查询(aliyun_iqs)/ 博查 Bocha(bocha)/ 火山引擎·豆包搜索(volcengine)/ 百度千帆 AI 搜索(baidu_qianfan)。 验收(主会话复跑 + 亲自变异):go build ./... + vet 绿;search 包测试绿; tsc --noEmit 0 错;新渲染测试 26 checks + 既有 plugin panel 55 / data 90 / schema values 40 / channel config 70 全绿。我用 sed 把 values.ts 的 option.value 全换成 option.label ⇒ 渲染测试红(「点选把候选项的 id 追加到 降级链末尾」got="bocha, 智谱 BigModel(zhipu)")—— 这正是会把配置文件写坏的 错法;还原后 md5 一致且绿。 ⚠️ 契约面变更(我在 Docs/api-client.md 登记):plugin.providers 候选响应形状 字符串数组 → 对象数组;label 仅供显示、value 才是落盘值。 ⚠️ 已知边界:viewer 角色看不到 form 区块 ⇒ 表格对 viewer 仍显示裸 id(未做)。 ⚠️ 真机浏览器点击未跑(项目无 jsdom)⇒ 建议刷新管理页点一次确认观感。
- 保存被包成事务:快照 → 落盘 → 按新配置重建工具 → 原子替换注册表条目(registry.ReplaceTool 窄方法,保留运行期 Policy);下一轮即生效,不要求重启 - 若新配置会让后端下次起不来(主家未配齐 fail-fast)⇒ 文件按字节回滚 + 409 config_unstartable - 声明面补 primary + fallback[](可配可生效);否决「另开 form」方案(会破坏既有 reauth 回填) - 主 provider 解析口径核查结论:没被 PLG-4 改坏(顺手修了一处日志缺陷) - 4 个变异自检(丢 Policy/不换条目/回滚 no-op/忽略 fallback)
- 新增 $DATA_DIR/config/plugins/web-search.json(0600 + temp+rename,文件名 = 插件 id) - 组合根改「先读可变源、缺失回落 .env 播种」;**不新增任何 env 键**(.env 已冻结) - 多实例:每家 provider 独立 key/baseURL/启用态 + 「测试连通」探针 - 用 PLG-1 的声明库给出该面板的 adminPanels 声明;动作名交给 PLG-2 的通用动作端点分发 (本片自己不开路由) ⚠️ 本片自认越界:改了 cmd/cyrene/wire_web_search_test.go(既有测试,为适配 DataDir); 另有 design/28 的相关注册留给主会话。