mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-05 06:42:12 +03:00
The Codex CLI WS->HTTP fallback rewrite (resolveResponsesApiModel) prefixes a bare model id with codex/ whenever codex/<id> resolves to codex. Codex accepts arbitrary model strings, so a combo name with no slash (e.g. n8n-text, paid-premium) was rewritten to codex/<combo> and sent to Codex instead of being resolved as a combo — regressing combos via /v1/responses in v3.8.9+. Skip the rewrite when the bare id is a combo (getComboByName). + unit test.
This commit is contained in:
committed by
GitHub
parent
b413774bdf
commit
cf7f684bd8
@@ -58,17 +58,31 @@ export async function resolveCodexWsModelInfo(
|
||||
*
|
||||
* @param requestedModel the model id from the Responses API request body
|
||||
* @param resolve a getModelInfo-style resolver
|
||||
* @param isCombo optional predicate — when the bare id is a combo name, skip the codex
|
||||
* rewrite so downstream combo routing resolves it (#3227/#3233).
|
||||
* @returns { model, changed } — model is the (possibly rewritten) id;
|
||||
* changed=true means a codex/ prefix was applied.
|
||||
*/
|
||||
export async function resolveResponsesApiModel(
|
||||
requestedModel: string,
|
||||
resolve: ModelResolver
|
||||
resolve: ModelResolver,
|
||||
isCombo?: (name: string) => Promise<boolean> | boolean
|
||||
): Promise<{ model: string; changed: boolean }> {
|
||||
if (!requestedModel || requestedModel.includes("/")) {
|
||||
return { model: requestedModel, changed: false };
|
||||
}
|
||||
|
||||
// #3227/#3233: a bare combo name (e.g. "n8n-text", "paid-premium") must NOT be
|
||||
// force-prefixed to codex/ — Codex accepts arbitrary model strings, so the rewrite
|
||||
// would shadow the combo and route to codex. Let downstream combo routing handle it.
|
||||
if (isCombo) {
|
||||
try {
|
||||
if (await isCombo(requestedModel)) return { model: requestedModel, changed: false };
|
||||
} catch {
|
||||
// combo lookup unavailable — fall through to normal codex-preference resolution
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const resolved = await resolveCodexWsModelInfo(requestedModel, resolve);
|
||||
if (resolved?.provider !== "codex") {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { handleChat } from "@/sse/handlers/chat";
|
||||
import { withEarlyStreamKeepalive } from "@omniroute/open-sse/utils/earlyStreamKeepalive";
|
||||
import { resolveResponsesApiModel } from "@/app/api/internal/codex-responses-ws/modelResolution";
|
||||
import { getModelInfo } from "@/sse/services/model";
|
||||
import { getComboByName } from "@/lib/db/combos";
|
||||
|
||||
// NOTE: We do NOT call initTranslators() here — the translator registry is
|
||||
// bootstrapped at module level inside open-sse/translator/index.ts when it
|
||||
@@ -37,7 +38,11 @@ async function withCodexPreferredModel(request: Request): Promise<Request> {
|
||||
if (!body || typeof body !== "object" || typeof body.model !== "string") {
|
||||
return request;
|
||||
}
|
||||
const { model, changed } = await resolveResponsesApiModel(body.model, getModelInfo);
|
||||
const { model, changed } = await resolveResponsesApiModel(
|
||||
body.model,
|
||||
getModelInfo,
|
||||
async (name) => !!(await getComboByName(name))
|
||||
);
|
||||
if (!changed) return request;
|
||||
|
||||
return new Request(request.url, {
|
||||
|
||||
Reference in New Issue
Block a user