mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-04 06:12:10 +03:00
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:
@@ -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");
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
38
tests/unit/autoCombo/paid-tier-auto-id-6328.test.ts
Normal file
38
tests/unit/autoCombo/paid-tier-auto-id-6328.test.ts
Normal 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);
|
||||
});
|
||||
Reference in New Issue
Block a user