fix(cats): resolve 'bound provider profile incompatible with client' error on client switch#375
Conversation
|
@claude review |
ZephaniaCN
left a comment
There was a problem hiding this comment.
Fix addresses stale effort values on provider switch. defaultEffortForProvider() + CLI reset logic looks correct. Test covers the cross-provider effort reset scenario. Note: no CI status checks visible — please confirm CI passed before merging.
edb5046 to
71b5a99
Compare
…itch - Add normalizeCliEffortForProvider to handle stale cross-provider effort values (e.g., OpenAI 'max' → 'xhigh', Anthropic 'xhigh' → 'max') - Rebase inherited seed binding when switching client families - Reset stale CLI config when switching client families Co-Authored-By: 宪宪/Opus-46🐾
…> runtime transform) - Remove normalizeCliEffortForProvider - data is now cleaned at write time - Extract resolveTargetAccountRef() and resolveNextCli() for better readability - Add defaultEffortForProvider() to reset effort on provider switch - Update tests to verify effort reset on provider switch - Add type UpdateCatRequestBody for better type safety Co-Authored-By: 宪宪/Opus-46🐾
71b5a99 to
11a821e
Compare
zts212653
left a comment
There was a problem hiding this comment.
Review — 布偶猫-Opus46 🐾
方向判定
Bug 是真实存在的:Anthropic → OpenAI 切换时 cli.effort: 'max' 残留导致 Codex CLI 崩溃。修复方向正确——写入时清理 > 运行时转换,从根本上消除 stale 数据。
架构上,resolveTargetAccountRef() 和 resolveNextCli() 的提取提升了 PATCH 路由的可读性和可维护性。getDefaultCliEffortForProvider() 替代 normalizeCliEffortForProvider() 语义更清晰。测试覆盖了两个核心场景(binding rebase + CLI reset)。
P1 — 编译错误:重复 const 声明(必须修)
packages/api/src/routes/cats.ts 约 L705-709,isBindingChange 和 isClientSwitch 各声明了两次:
const isBindingChange = targetAccountRef !== undefined && targetAccountRef !== currentEffectiveAccountRef;
const isClientSwitch = body.client !== undefined && body.client !== currentCat.provider;
// Compare against current binding — editor always sends accountRef even when unchanged.
const isBindingChange = targetAccountRef !== undefined && targetAccountRef !== currentEffectiveAccountRef; // ← 重复
const isClientSwitch = body.client !== undefined && body.client !== currentCat.provider; // ← 重复CI 已确认:TS2451: Cannot redeclare block-scoped variable 'isBindingChange'。Build / Lint / Test 全红。
修复:删除第二组声明(L708-709)和多余的注释(L707)。同时把下面 legacyCompat 里的 inline 表达式 !(body.client !== undefined && body.client !== currentCat.provider) 改回 !isClientSwitch。
P2 — Biome 格式问题
cat-config-loader.ts 新增的 JSDoc 注释缩进不对(* 前少了一个空格):
- * Note: Stale cross-provider effort values...
+ * Note: Stale cross-provider effort values...cats.ts import 排序:getDefaultCliEffortForProvider 应排在 getCliEffortOptionsForProvider 之后(字母序)。
Issue 标签
clowder-ai#373 目前没有 triaged 和 bug 标签。建议补上以满足 merge 前提。
P1 修完 + CI 全绿后,这个 PR 值得 merge 和 intake。
补充 Review — 布偶猫-Opus46 🐾(第二轮,经缅因猫-GPT5.4 独立交叉验证)P1 补充 — 删除 runtime normalize 对历史脏数据的风险PR 将 场景:用户升级到此版本前,
建议:保留 (此补充由缅因猫-GPT5.4 独立分析后发现,经布偶猫-Opus46 验证确认。) |
- Fix JSDoc comment format (Note: → @note) in cat-config-loader.ts - Fix ws type resolution in xiaoyi-ws.ts (use createRequire) - Add WsLike interface to xiaoyi-protocol.ts to avoid external ws type coupling - Remove duplicate variable declarations in cats.ts Co-Authored-By: 宪宪/Opus-4.5🐾
- getCatEffort(): validate persisted effort against provider before returning. Write-time cleanup prevents new stale values, but historical catalogs from before this fix may still carry cross-provider effort (e.g., openai + max). Defense-in-depth: isValidCliEffortForProvider gates the read path too. - cats.ts: remove duplicate comment, use !isClientSwitch instead of inline expr - test: add regression test for stale cross-provider effort in historical data [宪宪/Opus-46🐾] Co-Authored-By: 砚砚/GPT-5.4🐾
Adapt #375's resolveTargetAccountRef/resolveNextCli/resolveEffectiveAccountRefForUpdate to #340 naming (ClientId, body.clientId, currentCat.clientId). Add defense-in-depth effort validation in getCatEffort to reject stale cross-provider effort values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR Type
Related Issue
What
normalizeCliEffortForProvider- 彻底改为在数据写入时主动清理 stale 数据,而不是在 runtime 被动转换。resolveTargetAccountRef()和resolveNextCli()函数,显著提升了 account binding rebase 和 CLI config 重置逻辑的可读性与可维护性。defaultEffortForProvider(),在切换 provider(如anthropic切openai)时,能安全地重置effort为新 provider 的默认值。UpdateCatRequestBody类型。cats-routes-runtime-crud.test.js),确保在切换 client family 时,旧的 CLI 配置(包含 effort)被真实重置,而不仅仅是验证最终状态。Why
在前端修改猫猫的 client/model 组合时(如把默认的 Claude 切到 Codex),由于前端把旧的绑定配置传给后端,后端将其误判为非法而报错:
bound provider profile ... is incompatible with client ...。✅ 是的,现在写入阶段会重新计算 accountRebase 并移除非法的遗留信息,解决了该报错。
报错截图:

Tradeoff
Test Evidence
AC Checklist (Feature PRs only)