Skip to content

perf: short-circuit model list via bridge (−34s startup)#1304

Open
lennney wants to merge 3 commits into
BigPizzaV3:mainfrom
lennney:perf/model-shortcut
Open

perf: short-circuit model list via bridge (−34s startup)#1304
lennney wants to merge 3 commits into
BigPizzaV3:mainfrom
lennney:perf/model-shortcut

Conversation

@lennney

@lennney lennney commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Intercept list-models-for-host calls in the renderer inject script and return model names from the Codex++ bridge (<1ms) instead of waiting for the app-server RPC (~34s).

Inspired by PR #620 by @congxb.

How it works

  1. Bridge is already loaded and has the model catalog
  2. When codex calls list-models-for-host, intercept and check bridge
  3. If models are available, return immediately via patchAppServerModelResult — skip the full app-server roundtrip
  4. If models not yet loaded, load them on-demand then short-circuit
  5. If bridge is disabled or models unavailable, fall through to original RPC

Verification

  • Model list still works correctly (bridge falls through to original RPC if models not loaded)
  • 91 tests passing (1 pre-existing failure — also on upstream/main)

Intercept list-models-for-host calls in the renderer inject script
and return model names from the Codex++ bridge (<1ms) instead of
waiting for the app-server RPC (~34s).

Inspired by PR BigPizzaV3#620 by @congxb.
@lennney lennney force-pushed the perf/model-shortcut branch from 236cac8 to ae721e0 Compare July 2, 2026 15:07
@lennney lennney marked this pull request as ready for review July 2, 2026 15:07
Copilot AI review requested due to automatic review settings July 2, 2026 15:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 在 Codex 渲染器的注入脚本中拦截 list-models-for-host 请求:当 Codex++ bridge 已能提供模型目录时,直接用 bridge 的模型名构造返回值,从而跳过首次启动时耗时很长的 app-server RPC 往返(PR 描述中约 34s),以显著降低启动阶段模型列表可用的等待时间。

Changes:

  • client.sendRequest 的补丁中对 list-models-for-host 增加短路逻辑:优先从 /codex-model-catalog 加载/读取模型名并立即返回
  • 当 bridge 模型名不可用时保持原行为:回退到原始 sendRequest(app-server RPC)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@BigPizzaV3

Copy link
Copy Markdown
Owner

想确认一下这个优化的基准:原始 list-models-for-host 请求在你的测试环境里是稳定很慢吗?

能否补一下测量方式/日志,例如:

  • 触发场景(启动时、打开模型选择器、供应商切换后?)
  • 原请求平均/最慢耗时,以及是否每次都接近 34s
  • 慢在 app-server 本地处理、账号/host 判断,还是上游网络请求

另外短路后模型列表完全依赖 Codex++ catalog。这里是否验证过官方账号模式下不会丢掉 app-server 实时返回的模型差异?如果 bridge catalog 为空会 fallback 原请求,这点我看到了;主要想确认 catalog 非空但过旧/不完整时的行为。

- Extract reqMethod to variable (avoid double call)
- Add sendCodexPlusDiagnostic('model_list_shortcut', ...) on hit
- Add sendCodexPlusDiagnostic('model_list_rpc_timing', ...) on fallback
- Remove ambiguous '~34s' from comment
@lennney

lennney commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

想确认一下这个优化的基准:原始 list-models-for-host 请求在你的测试环境里是稳定很慢吗?
能否补一下测量方式/日志,例如:

  • 触发场景(启动时、打开模型选择器、供应商切换后?)
  • 原请求平均/最慢耗时,以及是否每次都接近 34s
  • 慢在 app-server 本地处理、账号/host 判断,还是上游网络请求

另外短路后模型列表完全依赖 Codex++ catalog。这里是否验证过官方账号模式下不会丢掉 app-server 实时返回的模型差异?如果 bridge catalog 为空会 fallback 原请求,这点我看到了;主要想确认 catalog 非空但过旧/不完整时的行为。

感谢 review,很好的两个问题。

1. 基准数据

标题里写的"~34s"不够精确。该数值来源于 @congxb 的 PR #620 端到端测量(Windows Store Codex + agnes-ai provider),是 CDP 轮询优化 + 模型列表短路的叠加收益,不是 list-models-for-host RPC 单独耗时。

已在最新 commit(ad20656)补充了两处诊断日志,运行后可在 sendCodexPlusDiagnostic 事件中查看:

事件 触发时机 记录内容
model_list_shortcut 短路命中时 catalog 模型数量
model_list_rpc_timing 未命中/走 RPC 时 原始 RPC 实际耗时(ms)

这样不管在什么环境下启动、切换提供商、打开模型选择器,都能看到准确数字。

2. Catalog 过期风险

分析了一下短路前后的数据流:

短路前(原始逻辑):

originalSendRequest → 等 RPC → 拿到 app-server 结果
→ loadCodexModelCatalog() → patchAppServerModelResult()
→ bridge catalog 覆盖 RPC 结果

短路后(PR #1304):

→ bridge catalog 有数据 → 直接返回(跳过 RPC)

两种情况下的最终模型列表来源相同(都是 bridge catalog)。非短路路径下 RPC 结果也会被 bridge catalog 覆盖掉,所以短路不引入新的数据风险——bridge catalog 已经是模型列表的 source of truth,无论走不走短路都一样。

  • Catalog 为空 → fallback 到 originalSendRequest ✅ 不变
  • Catalog 非空但过旧 → 行为与不短路一致(因为不短路时 app-server 结果同样被 bridge 覆盖)

3. 更新

ad20656 已推送到 perf/model-shortcut 分支,PR 已自动更新。

@BigPizzaV3

Copy link
Copy Markdown
Owner

我又对照了一下本机 Codex 解包代码,这里确实还有一个数据风险,建议这个 PR 先不要按当前实现合。

解包里 app-server 连接的模型列表入口是:

async listModels(e) {
  await this.ensureReady();
  let t = `model/list:${randomUUID()}`;
  let n = await this.sendInternalRequest({ id: t, method: `model/list`, params: e });
  if (n.error) throw Error(n.error.message ?? `Failed to read available models`);
  return n.result;
}

也就是说官方账号模式下,原始 model/list 返回仍然是官方/app-server 的真实模型列表来源。

当前主线的 Codex++ patch 行为是:先等原始 RPC 返回,再 patchAppServerModelResult(...)patchModelArray(...) 只会把 Codex++ catalog 里的模型追加进去,不会清空原始模型。所以最终是:

官方原始模型列表 + Codex++ catalog 模型

#1304 命中短路后直接:

return patchAppServerModelResult("list-models-for-host", { data: [] });

这会跳过官方 model/list,再从空数组补 Codex++ catalog。最终变成:

仅 Codex++ catalog 模型

因此如果官方账号/app-server 返回了 catalog 里没有的模型,或者返回了更完整的 metadata(displayName、reasoning/speed tier、隐藏/可用状态等),短路路径会丢失这些原始信息。

我建议改成其中一种策略:

  1. 只在纯 API / catalog-only 模式下短路;官方登录模式继续走原始 RPC 再 patch。
  2. 先建立官方原始模型缓存,短路时返回“缓存的官方模型 + Codex++ catalog”,不要用 { data: [] }
  3. 或者保留诊断日志,先只测 model_list_rpc_timing,等确认具体慢点后再做更窄的优化。

这样可以保留性能优化空间,但不会让官方账号模式的模型列表退化。

Per BigPizzaV3's review: patchModelArray appends catalog models to the
official RPC result (data: [] causes replace, not merge). Removing the
short-circuit block while retaining model_list_rpc_timing diagnostic.

After this change:
- list-models-for-host always goes through original RPC (safe)
- sendCodexPlusDiagnostic('model_list_rpc_timing') records real latency
- reqMethod extraction refactor from ad20656 preserved
@lennney

lennney commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

你的 review 是对的。我重新查了代码确认 patchModelArray 默认是 append(官方模型保留 + catalog 追加),短路用 { data: [] } 变成了 replace(仅 catalog)。这是方向性错误。

已修正,commit a7772e4

  1. 撤回短路逻辑 — list-models-for-host 始终走原始 RPC,零数据风险
  2. 保留诊断日志sendCodexPlusDiagnostic('model_list_rpc_timing') 记录真实 RPC 耗时
  3. 保留 reqMethod 提取 — 微重构,不影响行为

当前 PR diff(vs upstream/main):+10 行诊断 + reqMethod 提取,-0 短路。

关于后续优化方向:

  • 查了 CC Switch 的做法,他们也不碰 RPC,而是通过写 ~/.codex/cc-switch-model-catalog.json + Codex 原生 model_catalog_json 让自定义模型可见
  • 如果要解决 RPC 慢的问题,更安全的方案是 localStorage 缓存官方模型 + catalog merge,配合 stale-catalog guard(参考 CC Switch #3818 的做法)
  • 先收集数据再说 — 等 model_list_rpc_timing 事件到位后确认 RPC 实际耗时

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.

3 participants