Skip to content

fix(app): 恢复 Pure API 旧线程时保留模型与推理档位 - #2742

Open
Yuimi-chaya wants to merge 6 commits into
BigPizzaV3:mainfrom
Yuimi-chaya:codex/preserve-thread-model-20261028
Open

Yuimi-chaya wants to merge 6 commits into
BigPizzaV3:mainfrom
Yuimi-chaya:codex/preserve-thread-model-20261028

Conversation

@Yuimi-chaya

@Yuimi-chaya Yuimi-chaya commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

问题

Pure API 恢复旧线程时,补入当前 modelProvider 会使原生跳过模型、推理档位和供应商的成组恢复。例如,线程保存的是 gpt-6.1-terra / xhigh,全局默认是 gpt-6.1-sol / medium,恢复后可能把后者写回线程。

只放行完全没有模型和供应商字段的请求仍不够:原生请求可能携带 model: null、空的可选配置,或者仅携带供应商字段。这些字段存在不代表用户明确选择了模型。另外,模型目录过滤会把宿主已有的默认模型描述符替换为当前目录的首选模型,并带入默认的 medium,也可能影响线程恢复时的选择。

修复

  • Pure API 本机恢复请求没有有效的显式模型时,先通过内部只读接口读取该线程保存的模型和推理档位,再携带当前供应商和保存设置恢复。覆盖只有线程 ID、空模型字段、仅供应商字段以及空可选配置;有效的显式模型、推理档位仍优先保留。
  • 模型和推理档位从同一 SQLite 行读取。数据库以只读方式打开,不读取聊天正文;元数据缺失、冲突、读取超时或等待期间设置发生变化时,停止本次恢复,避免静默采用全局默认。接口仅接受本机请求,不加入拓展路由白名单。
  • 保留外部供应商、远程主机和其他接入模式的既有边界。若线程已加载为旧供应商连接,明确提示重启,不自动卸载正在使用的会话;恢复后校验模型、供应商及指定的推理档位。
  • 模型目录继续补充、过滤可选项,但不接管宿主已有的 defaultModel、default_model 或线程模型;对仍匹配旧注入值的快照执行撤销。新增描述符保持 isDefault: false,后端供应商默认配置不删除。新建线程未显式指定模型时仍交由原生配置回退,旧线程则使用自己的保存设置。
  • 请求包装器版本提升至 31,同时覆盖实例、原型和主机信封入口。

此修复阻止后续恢复覆盖模型,不自动修复此前已经写入历史库的错误选择。

验证

  • 发布分支完整前端测试:1127 通过、0 失败、1 项既有跳过;TypeScript、两份注入产物组装检查通过。
  • Rust CDP 契约 170 项通过,包括有效 Pure API、本机目录下的默认模型归属测试。只读元数据 4 项、路由边界 1 项也已通过;这些 Rust 业务实现未在后续前端修正中改变。
  • 两项新增回归先在旧实现上失败:空模型字段绕过历史设置读取,以及目录替换宿主默认模型。修复后通过,包装器测试同时覆盖空字段、仅供应商字段和主机信封。
  • Windows 验收包的 Vite、Release 构建、一次隔离启动检查和 Setup 打包通过。验收包基于 main 2bf4dfdf;发布分支已更新至 main b70bcf26,原有 12 个变更文件与验收源码逐字节一致。
  • 插件市场独立测试夹具补齐恢复辅助函数的依赖,Rust 包装测试所调用的导航、UI、适配器三份 Node 脚本 32 项通过;模型与连接回归 57 项通过。该夹具调整不改变运行时源码或原有断言。

使用实际 codex-cli 0.165.0-alpha.1.2、独立 home/workspace 和合成旧线程完成 9 组原生复现及回归。保存设置为 Terra / xhigh / openai,全局默认为 Sol / medium / custom;上游仅连接本机模拟接口,不复制用户会话或凭据,不发送真实模型请求。

场景 原生结果
未修复的空模型 + 当前供应商基线 复现回落为 Sol / medium
修复后只有线程 ID,供应商同步关闭或开启 保留 Terra / xhigh,恢复为 custom,续发走当前供应商模拟地址
空模型、仅供应商、空配置三类恢复 保留 Terra / xhigh,续发走当前供应商模拟地址
原线程未指定推理档位 保留 Terra,档位沿用原生未指定时的默认语义
已加载当前供应商 恢复和续发保持保存设置及当前供应商
已加载旧供应商 明确拒绝并提示重启,不卸载会话

Windows 测试包已由用户在其一直使用的纯 API 接入环境中实测通过,反馈模型覆盖问题已解决。用户未单独报告“openai 历史线程 + 关闭供应商同步”这一特定组合;该组合的恢复、续发和供应商定向由上述原生隔离测试验证,不将模拟上游测试描述为真人供应商连通验收。

@BigPizzaV3

Copy link
Copy Markdown
Owner

感谢细致排查!有两点想先确认:

  1. thread/resume 的放行条件请收窄为「既无 model 也无 modelProvider/model_provider 字段」,显式带 model_provider: "openai" 的恢复仍需改写为当前供应商(这是之前的修复,显式 provider 本就会跳过原生成组恢复),并恢复对应测试;也请实测 Pure API、关闭供应商同步时恢复 openai 旧线程的情况。
  2. 删除默认模型替换会让 Pure API 过滤后的新线程默认用到供应商不提供的模型,请说明它和旧线程模型被覆盖之间的关系(最好两处分开验证),否则建议先只保留 resume 这部分。

另外请 rebase 到最新 main(cdp_bridge 测试已移到 tests/all/)。谢谢!

@Yuimi-chaya
Yuimi-chaya force-pushed the codex/preserve-thread-model-20261028 branch from 380176c to 170906f Compare October 29, 2026 09:45
@BigPizzaV3

Copy link
Copy Markdown
Owner

感谢按意见收窄并撤回默认模型的改动,测试也很完整!合入前还有一个顾虑:按你表格里的结果,只带线程 ID 的恢复会还原保存的 openai 供应商;而 Pure API 下后续的 turn/start 没带 provider 字段时也是原样放行,这样这个旧线程之后的消息可能发到 openai,而 Pure API 用户通常没有登录 ChatGPT。

建议的思路:Pure API 下遇到无字段的恢复,先读出线程保存的模型和推理档位,再带上当前供应商 + 这些设置一起恢复,这样既不被全局默认覆盖,也不会留在 openai。合入前也请补一下你提到的「Pure API + 关闭供应商同步 + openai 旧线程」客户端实测:能恢复、能继续发消息、请求确实走当前供应商。谢谢!

@Yuimi-chaya
Yuimi-chaya force-pushed the codex/preserve-thread-model-20261028 branch from 170906f to c526879 Compare October 29, 2026 14:19
@Yuimi-chaya Yuimi-chaya changed the title fix(app): 修复旧线程模型选择被覆盖的回归 fix(app): 恢复 Pure API 旧线程时保留模型与推理档位 Oct 29, 2026
@BigPizzaV3

Copy link
Copy Markdown
Owner

感谢按思路实现,恢复路径清楚!还有两点:

  1. patchModelDefaults 的默认模型替换又被删掉了,上一轮已约定先保留,请撤回这部分,或单独开 PR 验证新线程的情况;
  2. 读不到保存的设置时(model 为空的旧线程、多个库记录冲突、供应商刷新失败),现在会直接拒绝恢复,用户可能打不开旧线程。建议改为退回「当前供应商 + 不指定模型」并记录诊断,而不是报错。谢谢!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants