OMP Codex 搜索后端的选择逻辑

makoMakoGo 于 2026-05-06 发布

1. 先说结论

关于 omp search --provider codex,先把两层选择拆开看:

  1. 顶层 search provider 选择

    • 这一层决定走 exacodexbraveperplexity 还是别的 provider
    • providers.webSearch: exa 只影响这里
  2. codex provider 内部 backend 选择

    • 这一层决定 codex 下面到底走:
      • 官方 openai-codex OAuth / ChatGPT 登录 builtin search
      • 还是 models.yml 里声明的自定义 Responses-compatible backend

一句话概括:


2. 顶层 search provider 选择和 Codex 内部 backend 选择不是一回事

2.1 顶层 provider 选择

文件:

这里负责:

所以:

2.2 Codex provider 内部 backend 选择

文件:

这里负责:

当前 patch 的真实顺序是:

async function resolveCodexBackend(): Promise<CodexBackend | null> {
	const byok = await loadBYOKConfig();
	if (byok) return { type: "byok", ...byok };

	const oauth = await findCodexAuth();
	if (oauth) return { type: "oauth", ...oauth };

	return null;
}

也就是:


3. Codex 搜索是怎么匹配自定义 provider 的

这里不能只理解成“models.yml 里 provider 写了 api: openai-responses 就一定会被选中”。

真实逻辑分三步。

3.1 先确定“请求目标模型”

Codex search 会先取:

  1. PI_CODEX_WEB_SEARCH_MODEL
  2. 如果没有,再取 ~/.omp/agent/config.yml -> modelRoles.default

也就是说,Codex search 并不是盲扫 models.yml 里的所有自定义 provider,而是先有一个“当前想要的目标模型”。

3.2 只看 Responses 类型 provider

当前代码里,只有这些 api 会进入 BYOK 候选集合:

const RESPONSES_APIS = new Set(["openai-responses", "openai-codex-responses"]);

所以:

3.3 候选集合里再做精确匹配

真正的选择逻辑不是模糊匹配,而是精确匹配:

  1. 如果请求模型里带 provider 前缀,providerName 必须完全一致
  2. models[].id 也必须和请求 modelId 完全一致
  3. 同时还要有可用的 baseUrlapiKey

关键逻辑可以概括成:

requestedModel = PI_CODEX_WEB_SEARCH_MODEL ?? config.modelRoles.default

for each provider in models.yml:
  if provider.api not in [openai-responses, openai-codex-responses]: skip
  if requestedModel.provider exists and requestedModel.provider !== providerName: skip
  if requestedModel.modelId not in provider.models[].id: skip
  if no baseUrl or no apiKey: skip
  return this provider as BYOK backend

fallback to openai-codex OAuth

所以结论是:


当前配置:

把它代入匹配逻辑后,当前请求模型会被解析成:

而自定义 provider 实际是:

所以有两层都对不上:

  1. provider 名不匹配

    • openai-codex != codex-proxy
    • openai-codex != codex-gateway
  2. model id 也不匹配

    • gpt-5.4:high != gpt-5.4(high)

结果就是:

所以这里的关键不是“responses 类型失效了”,而是:


5. 实测结果

5.1 当前配置下,显式 --provider codex 会落到官方 OAuth 路径

当前 config.yml

modelRoles:
  default: openai-codex/gpt-5.4:high

实测命令:

omp search --provider codex --compact "what is ai infra"

结果:

Error: Codex API error (400): {"detail":"The 'gpt-5-codex-mini' model is not supported when using Codex with a ChatGPT account."}

这个结果说明:

5.2 强制指定自定义目标模型后,同一个 --provider codex 会走 BYOK

实测命令:

PI_CODEX_WEB_SEARCH_MODEL='codex-proxy/gpt-5.4(xhigh)' omp search --provider codex --compact "what is ai infra"

结果正常返回:

这说明:


6. 关于 search --provider codex 的准确理解

可以把它理解成:

所以当前语义最准确的表述是:

  1. 显式 --provider codex
  2. 先尝试匹配 models.yml 里的 Responses-compatible 自定义 backend
  3. 如果当前请求模型和自定义 provider / model id 对不上
  4. 再 fallback 到官方 openai-codex OAuth builtin search

在当前这份配置下,这个结果就等价于:

但这是因为:

而不是因为:


7. 最后压缩成一句话

当前 OMP 的 Codex 搜索逻辑可以概括成: