fix(websearch): 面板「填 key + 同一次选它当主 provider」不再被自己的校验回滚
真机报障(2026-10-07 09:50):面板上给 zhipu 填了 API Key,保存却一直回 400 primary_not_configured;盘上配置文件 mtime 一动不动 —— 连刚填的 key 一起被回滚,界面表现为「怎么填都存不进去」。 根因(顺序错误):saveProvider 先 applySelectionPatch(内含「主 provider 必须 已配齐」的校验),后 UpsertProviderEntry。校验看的是**盘上的旧文件**,而这次 提交里的 key 还没落盘 ⇒ 校验判它没配齐,整笔拒绝。 修法:把校验从 applySelectionPatch 里摘出来,改名 mergeSelectionPatch(只合并 文件级字段 + 回报有没有给 primary),由 saveProvider 在 UpsertProviderEntry **之后**对最终文件校验,再写盘。判据本身一字未改 —— 「真的没配齐的主家照样拒」。 验证:cmd/cyrene 整包测试绿;新增回归 TestWebSearchSaveProviderAndPrimaryInOneSubmit (同一次提交填 key + 选主家 ⇒ 200 且盘上 key 与 primary 都在;反向:真没配齐仍 400 且文件字节不变);用 -overlay 把校验改回「拿旧文件校验」⇒ 该用例变红且报错文案 与主人看到的逐字相同。
This commit is contained in:
1 parent
ef8fc66e54
commit
aa0bf8b5a0
3 files changed
+73
-17
No files matched your search
@@ -79,11 +79,20 @@ func (e webSearchActionEnv) saveProvider(_ context.Context, req pluginmgr.Action
|
||||
return nil, err
|
||||
}
|
||||
entry.Provider = name
|
||||
next, err := e.applySelectionPatch(cur, values)
|
||||
next, setPrimary, err := e.mergeSelectionPatch(cur, values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := runtimeconfig.SaveWebSearch(e.path, runtimeconfig.UpsertProviderEntry(next, entry)); err != nil {
|
||||
final := runtimeconfig.UpsertProviderEntry(next, entry)
|
||||
// 🔴 校验必须在**并条之后**(顺序理由见 websearch_selection.go 的 mergeSelectionPatch):
|
||||
// 主 provider 配没配齐,取决于**这次刚落进文件的凭据** —— 拿旧文件校验会把
|
||||
// 「第一次填 key + 同一次提交里选它」整笔回滚,连 key 一起丢。
|
||||
if setPrimary {
|
||||
if err := e.checkPrimaryUsable(final, final.Provider); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := runtimeconfig.SaveWebSearch(e.path, final); err != nil {
|
||||
e.log.Error("web-search panel config write failed", "path", e.path, "provider", name, "error", err)
|
||||
return nil, pluginmgr.NewActionError(actionCodeConfigWriteFailed,
|
||||
"面板配置写不进去(磁盘或权限问题),本次改动**没有**生效", http.StatusInternalServerError, err)
|
||||
@@ -97,8 +106,8 @@ func (e webSearchActionEnv) saveProvider(_ context.Context, req pluginmgr.Action
|
||||
"enabled": entry.IsEnabled(),
|
||||
// 文件级选择的**落盘后**取值(没给 primary/fallback 时也如实回显当前值):
|
||||
// 面板按它回显「谁先用」,也让「这次保存有没有动到选择」有可机读的答案。
|
||||
"primary": strings.ToLower(strings.TrimSpace(next.Provider)),
|
||||
"fallback": selectionNames(next.Fallback),
|
||||
"primary": strings.ToLower(strings.TrimSpace(final.Provider)),
|
||||
"fallback": selectionNames(final.Fallback),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user