Skip to content

fix(codex): 修复 reasoning 档位体系多处问题 - #9

Merged
BigStrongSun merged 2 commits into
BigStrongSun:bigstrongsun/fix-wizard-provider-subagent-uxfrom
zhushihao:fix/28-reasoning
Aug 15, 2026
Merged

fix(codex): 修复 reasoning 档位体系多处问题#9
BigStrongSun merged 2 commits into
BigStrongSun:bigstrongsun/fix-wizard-provider-subagent-uxfrom
zhushihao:fix/28-reasoning

Conversation

@zhushihao

Copy link
Copy Markdown
Contributor

问题

v3.19.1-28 的 Codex reasoning 档位体系存在多处问题,影响 DeepSeek/Kimi K3 档位显示、官方模型(luna/sol)子智能体档位配置、以及 schema1 旧配置迁移:

  1. Kimi K3/K3-256K 无推理档位:builtin 能力清单只认 deepseek,K3 能力解析为 Unknown,编辑器无法配档位
  2. 手动声明的档位被静默清空:后端 validate 失败时静默降级为 None,用户在 UI 手动声明的档位在保存后「消失」
  3. inspect 报 invalid_configuration:schema1 旧配置(legacy reasoningEffort 迁移为 Fixed)+ 能力 Unknown 时编译失败,错误码被兜底掩盖
  4. v28 死锁:未启用的可路由 profile 被误判为「不可路由」,启用开关与编辑按钮永久禁用
  5. 投影档位虚高:deepseek/k3 投影显示 6 档(含 medium/xhigh),但模型真实能力只有 3 档(low/high/max)
  6. 官方模型不继承官方档位:luna/sol 等官方模型的子智能体能力解析不含官方缓存来源,编辑器配不了档位
  7. schema1 legacy Fixed 档位被 3 档拒绝:xhigh/medium 等 legacy 档位在能力收窄后被编译拒绝

修复

  • codex_reasoning.rs:builtin 能力清单增加 Kimi K3/K3-256K(low/high/max,default high);reasoning 声明解析/校验失败改为打日志,不再静默清空;selectable 收窄为模型真实能力(窄显示)
  • codex.rs / transform_codex_chat.rs:effort_value_mode 保留完整 effort_map 映射,代理端先映射后校验(宽映射兜底,medium/xhigh 不报错)
  • codex_config.rs:子智能体能力解析新增官方缓存来源(cc_switch_owned 时读 backup),luna/sol 等官方模型继承官方档位;兼容字符串/对象数组两种 levels 格式
  • codex_subagent_profiles.rs:Unknown 能力 + Fixed 策略放行;Fixed 档位宽校验(effort_map 映射后合法则通过,保留显式档位由代理层运行时映射)
  • CodexSubagentProfileEditor.tsx:用 status.status 区分 Disabled/Unroutable,修复 v28 死锁
  • CodexFormFields.tsx / ProviderForm.tsx:取消勾选档位时清理 effortMap 孤儿映射;保存时校验映射 target 合法性(与后端 validate 对齐)

测试

  • 更新 5 处档位断言(6 档 → 3 档)
  • 新增 5 个测试:K3 builtin 能力、Unknown+Fixed 放行、effort_value_mode 宽映射、medium/xhigh 代理兜底、官方缓存能力(字符串/对象数组两种格式)
  • 全量 2995 passed(4 个 model_pricing 失败为既有环境问题:测试读取真实 LOCALAPPDATA 配置,与本次改动无关)

- builtin 能力清单增加 Kimi K3/K3-256K(low/high/max,default high)
- reasoning 声明解析/校验失败改为打日志,不再静默清空
- 前端取消勾选档位时清理 effortMap 孤儿映射;保存时校验映射 target 合法
- 子智能体 V2 编译:Unknown 能力 + Fixed 策略放行;Fixed 档位宽校验
  (effort_map 映射后合法则通过,保留显式档位由代理层运行时映射)
- 投影档位收窄为模型真实能力(deepseek/k3 变 3 档),effort_value_mode
  保留完整映射,代理端先映射后校验(窄显示 + 宽映射兜底)
- 子智能体能力解析新增官方缓存来源(cc_switch_owned 时读 backup),
  luna/sol 等官方模型继承官方档位
- 修复 v28 死锁:未启用 profile 用 status.status 区分 Disabled/Unroutable,
  开关与编辑按钮恢复可用
- 更新 5 处档位断言,新增 5 个测试;全量 2995 passed
providerWithFetchedModelCatalog rebuilds the provider model catalog from the stored catalog on every /models fetch, but the field spread list omitted `reasoning`. User-declared reasoning levels (K3, Qwen, etc.) were silently dropped on each refresh, so fixed reasoning levels disappeared after saving the MultiRouter or refreshing the catalog.

Carry `reasoning` forward from the existing provider model so manual declarations survive catalog refreshes. The rest of the sync chain (rebuildPlanModelCatalog -> buildSyncedRouteModels -> applyRouteCapabilities) already spreads the model object and preserves it.
@zhushihao

Copy link
Copy Markdown
Contributor Author

Bug 修复说明:providerWithFetchedModelCatalog 刷新模型目录时会静默清空手动声明的 reasoning 档位

现象
对第三方 provider(如自建 vLLM 的 qwen3.8)手动声明 reasoning 档位(例如 low/medium/xhigh)后,一旦触发"模型目录刷新",投影里该模型的档位就消失,必须重新声明。K3 不受影响,因为 Kimi 的 /models 拉取失败、不触发目录重建。

根因
src/components/codex/CodexRouterWorkspacePage.tsxproviderWithFetchedModelCatalog(约 688 行)在刷新时从现有 provider 目录重建每个模型行,spread 列表包含:
upstreamModel / displayName / contextWindow / inputModalities / textOnly / supportsImage / vision
唯独漏了 reasoning

该函数被刷新循环 refreshTask 调用(CodexRouterWorkspacePage.tsx:2572),随后 await providersApi.update(nextProvider, "codex")(2584 行)把重建后的目录写回 DB。由于重建时 reasoning 已被丢弃,写回后库里的 reasoning 真正丢失,MultiRouter plan 继承到空值 → 档位消失。

为什么是 bug(而非设计意图)

  1. 同一次重建里 vision / supportsImage / contextWindow 等能力字段都从现有模型保留,只有 reasoning 被漏掉——若设计为清空,不会只漏这一个字段。
  2. 项目设计笔记明确要求刷新函数对 reasoning 采用优先级「远端显式值 > 用户已有目录值 > 本地预设」,即用户已有目录值应优先保留;但实现时该字段根本没写进 spread,属实现遗漏。

Scope
只影响 reasoning 维护在 provider 存储目录中的模型(即上游不报 reasoning、需用户手动声明的第三方模型)。reasoning 来自 builtin 目录/投影逻辑的官方模型不在此路径,不显现。

修复
在 spread 中补回:

...(model.reasoning ? { reasoning: model.reasoning } : {}),

使 reasoning 与 vision / supportsImage 等一致地从现有模型继承。注意该路径下 fetched /models 响应并不携带 reasoning(代码只读取 contextWindow / inputModalities / supportsImage),故存储目录值本就是 reasoning 的唯一来源,保留它是正确且必要的。

验证
修复后 qwen3.8 档位在刷新与重启后均保留;全量 2995 测试不受影响。本 PR 仅含此修复的干净 commit,排查用的诊断日志已从源码撤除。

@BigStrongSun
BigStrongSun merged commit 7095f1a into BigStrongSun:bigstrongsun/fix-wizard-provider-subagent-ux Aug 15, 2026
1 check passed
BigStrongSun added a commit that referenced this pull request Aug 15, 2026
Resolve equivalent cherry-pick conflicts after PR #9 merged into the cloud development base. Preserve both v28 release evidence and v31 Qwen streaming root-cause records, and retain the rustfmt-normalized reasoning implementation. Validated focused capability-effort tests, rustfmt, diff checks, and strict UTF-8 without BOM. 本次提交由BigStrongsSun完成
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants