fix(autoCombo): exclude paid models from fusion candidate pools when hidePaidModels=true (#6328) (#6550)

fix(autoCombo): exclude paid-tier auto/* ids from the catalog when hidePaidModels=true (#6328). Integrated into release/v3.8.47. (thanks @chirag127)
This commit is contained in:
Chirag Singhal
2026-07-08 04:49:43 +05:30
committed by GitHub
parent d180ac1244
commit fc8459faa3
3 changed files with 66 additions and 0 deletions

View File

@@ -88,6 +88,28 @@ export function isRecognizedBuiltinAuto(modelStr: string, suffix: string): boole
);
}
/**
* #6328 (follow-up to #6495 / #6512): recognize built-in `auto/*` ids whose
* intent is paid-tier only, so callers can REMOVE — not just hide — them from
* advertised catalogs when the operator opts into `hidePaidModels`.
*
* Two shapes qualify as paid-tier:
* - flat variants prefixed `auto/pro-*` (e.g. `auto/pro-coding`)
* - suffix variants with the `:pro` tier (e.g. `auto/coding:pro`)
*
* Non-`pro` `auto/*` ids (auto/coding, auto/best-*, auto/coding:free, …) keep
* their advertised status; the candidate-pool filter in `virtualFactory` (#6512)
* already excludes paid backends from them at request time. `auto/<family>` ids
* are unaffected — the family is a backend selector, not a tier.
*/
export function isPaidTierAutoId(autoId: string): boolean {
if (typeof autoId !== "string" || !autoId.startsWith("auto/")) return false;
const suffix = autoId.slice("auto/".length);
if (suffix.startsWith("pro-")) return true;
const parsed = parseAutoSuffix(suffix);
return parsed.valid && parsed.tier === "pro";
}
export async function createBuiltinAutoCombo(modelStr: string, suffix: string) {
const { createVirtualAutoCombo } = await import("./virtualFactory.ts");

View File

@@ -26,6 +26,7 @@ import {
AUTO_SUFFIX_VARIANTS,
AUTO_FAMILY_IDS,
createBuiltinAutoCombo,
isPaidTierAutoId,
} from "@omniroute/open-sse/services/autoCombo/builtinCatalog";
import { getAllSyncedAvailableModels, type SyncedAvailableModel } from "@/lib/db/models";
import { getModelCatalogCacheVersion } from "@/lib/db/readCache";
@@ -649,6 +650,11 @@ async function buildUnifiedModelsResponseCore(
...AUTO_FAMILY_IDS,
]) {
if (blockedProviders.has("auto") || listedIds.has(autoId)) continue; // #5192
// #6328 (follow-up to #6495 / #6512): REMOVE — not just hide — paid-tier
// auto/* ids (auto/pro-* + auto/*:pro) from the advertised catalog when the
// operator opts into hidePaidModels. The candidate-pool filter in
// virtualFactory (#6512) still gates request-time routing for the rest.
if (hidePaid && isPaidTierAutoId(autoId)) continue;
listedIds.add(autoId);
const baseAutoEntry = {
id: autoId,

View File

@@ -0,0 +1,38 @@
/**
* #6328 (follow-up to #6495 / #6512) — regression guard for
* `isPaidTierAutoId`, which lets `/v1/models` REMOVE (not just hide) paid-tier
* `auto/*` ids when the operator opts into `hidePaidModels`.
*/
import { test } from "vitest";
import assert from "node:assert/strict";
import { isPaidTierAutoId } from "../../../open-sse/services/autoCombo/builtinCatalog.ts";
test("flat auto/pro-* variants are paid-tier", () => {
assert.equal(isPaidTierAutoId("auto/pro-coding"), true);
assert.equal(isPaidTierAutoId("auto/pro-reasoning"), true);
assert.equal(isPaidTierAutoId("auto/pro-fast"), true);
});
test("suffix auto/<category>:pro variants are paid-tier", () => {
assert.equal(isPaidTierAutoId("auto/coding:pro"), true);
assert.equal(isPaidTierAutoId("auto/reasoning:pro"), true);
});
test("non-pro auto/* ids are NOT paid-tier (kept in advertised catalog)", () => {
assert.equal(isPaidTierAutoId("auto/coding"), false);
assert.equal(isPaidTierAutoId("auto/coding:free"), false);
assert.equal(isPaidTierAutoId("auto/coding:fast"), false);
assert.equal(isPaidTierAutoId("auto/best-coding"), false);
assert.equal(isPaidTierAutoId("auto/best-free"), false);
assert.equal(isPaidTierAutoId("auto/vision"), false);
});
test("non-auto ids and malformed input return false (guard)", () => {
assert.equal(isPaidTierAutoId("openai/gpt-4o"), false);
assert.equal(isPaidTierAutoId(""), false);
assert.equal(isPaidTierAutoId("auto/"), false);
// Argument is typed `string` at the call sites, but the guard tolerates junk.
assert.equal(isPaidTierAutoId(undefined as unknown as string), false);
assert.equal(isPaidTierAutoId(null as unknown as string), false);
});