mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-17 20:52:15 +03:00
fix(providers): scope model target formats to providers (#10072)
Co-authored-by: xz-dev <xz-dev@users.noreply.github.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: adevwithpurpose <adevwithpurpose@users.noreply.github.com>
This commit is contained in:
@@ -173,14 +173,11 @@ export function getModelTargetFormat(aliasOrId: string, modelId: string): string
|
||||
// Accept either the public alias ("cmd") or the raw provider id ("command-code"),
|
||||
// mirroring getProviderModels (same pattern as #2798/#3870).
|
||||
const alias = PROVIDER_ID_TO_ALIAS[aliasOrId] || aliasOrId;
|
||||
const models = PROVIDER_MODELS[alias];
|
||||
// Strip provider prefix if present: "openai/gpt-5.6-luna" → "gpt-5.6-luna"
|
||||
const prefix = alias + "/";
|
||||
const bareModelId =
|
||||
typeof modelId === "string" && modelId.startsWith(prefix)
|
||||
? modelId.slice(prefix.length)
|
||||
: modelId;
|
||||
const found = models?.find((m) => m.id === bareModelId);
|
||||
const prefixes = [`${aliasOrId}/`, `${alias}/`];
|
||||
const prefix = prefixes.find((value) => modelId.startsWith(value));
|
||||
const bareModelId = prefix ? modelId.slice(prefix.length) : modelId;
|
||||
const found = PROVIDER_MODELS[alias]?.find((m) => m.id === bareModelId);
|
||||
if (found?.targetFormat) return found.targetFormat;
|
||||
// #5842: OpenAI "*-pro" reasoning models (o1-pro, gpt-5.x-pro) are only served by
|
||||
// the native /v1/responses endpoint — /v1/chat/completions 404s ("only supported
|
||||
@@ -188,16 +185,13 @@ export function getModelTargetFormat(aliasOrId: string, modelId: string): string
|
||||
// covers dynamically-synced ids that post-date the catalog (same spirit as the gh
|
||||
// executor's /codex/i routing, 9router#102). Scoped to the openai alias so other
|
||||
// providers shipping *-pro ids keep their own endpoint semantics.
|
||||
if (alias === "openai" && /-pro$/i.test(modelId)) return "openai-responses";
|
||||
if (alias === "openai" && /-pro$/i.test(bareModelId)) return "openai-responses";
|
||||
// Model-level targetFormat is provider-scoped: a catalog entry declares how THIS
|
||||
// provider's endpoint serves the model. When the provider has its own catalog but
|
||||
// the model is not in it, do NOT import the global entry's tag — it encodes the
|
||||
// DECLARING provider's endpoint semantics (e.g. ghe-copilot tags gpt-5.6-* as
|
||||
// openai-responses, which must not hijack command-code's chat-shaped
|
||||
// /alpha/generate → 502 "Invalid prompt: messages must not be empty"). Providers
|
||||
// with no catalog at all keep the global fallback as their only metadata source.
|
||||
if (models) return null;
|
||||
return getGlobalModel(bareModelId)?.targetFormat ?? null;
|
||||
// provider's endpoint serves the model — do NOT import another provider's tag.
|
||||
// #9994 scoped this for providers WITH a catalog; #10072 extends it to catalogless
|
||||
// providers (openai-compatible-chat-*), which previously inherited the declaring
|
||||
// provider's endpoint semantics via the global fallback.
|
||||
return null;
|
||||
}
|
||||
export function getModelStripTypes(aliasOrId: string, modelId: string): string[] {
|
||||
const models = PROVIDER_MODELS[aliasOrId];
|
||||
|
||||
@@ -58,6 +58,18 @@ test("delegates byte-identically for a normal model (no apiFormat / no custom ov
|
||||
assert.deepEqual(r, expected("openai", "gpt-4o", undefined, undefined, undefined));
|
||||
});
|
||||
|
||||
test("provider-local target format does not leak from another provider", () => {
|
||||
const r = resolveChatCoreTargetFormat({
|
||||
provider: "openai-compatible-chat-example",
|
||||
resolvedModel: "gpt-5.6-sol",
|
||||
apiFormat: undefined,
|
||||
sourceFormat: FORMATS.OPENAI_RESPONSES,
|
||||
customModelTargetFormat: undefined,
|
||||
providerSpecificData: undefined,
|
||||
});
|
||||
assert.equal(r.targetFormat, FORMATS.OPENAI);
|
||||
});
|
||||
|
||||
test("customModelTargetFormat is used when the model has no registry target format", () => {
|
||||
const customModel = "totally-unknown-custom-model-xyz";
|
||||
// precondition: the registry has no target format for this unknown model
|
||||
|
||||
Reference in New Issue
Block a user