Files
OmniRoute/open-sse/services/autoCombo/candidateOverrides.ts
Adrian A. Firmansyah a20771d6ac fix(auto): pool accounts by provider model (#7928)
* fix(auto): pool accounts by provider model

* test(auto): update provider-family-combos to the #7928 Cartesian pool shape

Since #7928 the auto-combo candidate pool is a connections × models Cartesian
product, so createBuiltinAutoCombo("auto/<family>") now surfaces each backend's
full family line-up rather than exactly one default model per connection. The
#6453 invariant is unchanged and still asserted — which providers span the
family and that unrelated providers (the connected openai/gpt-4o-mini, the
connected glm on auto/zai) are excluded — but the two exact-count assertions are
relaxed to the provider SET and the detectModelFamily() family check, matching
the pattern the sibling auto/minimax case already uses.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Your Name <you@example.com>
Co-authored-by: adrianaryaputra <adrian.arya@gmail.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
2026-07-21 12:17:18 -03:00

46 lines
1.7 KiB
TypeScript

/**
* #7819 (Level 2) — per-API-key candidate exclusions for `auto/*` channels.
*
* Pure, dependency-light filter kept separate from `virtualFactory.ts` so it
* is unit-testable in isolation, mirroring `paidModelFilter.ts` in this same
* directory (`filterPaidOnlyCandidates`). Fail-open by design: an empty
* exclusion set is the identity function (near-zero overhead on the
* unconfigured hot path), and any caller-side lookup failure should pass the
* candidate pool through unfiltered rather than break routing.
*/
interface OverridableCandidate {
connectionId: string | null;
allowedConnectionIds?: string[];
}
/**
* Return the candidate pool with excluded connection IDs removed. Returns
* the SAME array reference (identity) when there is nothing to filter, so
* callers can cheaply detect "unchanged" the same way
* `filterPaidOnlyCandidates` does.
*/
export function filterExcludedCandidates<T extends OverridableCandidate>(
pool: T[],
excludedConnectionIds: Set<string>
): T[] {
if (!excludedConnectionIds || excludedConnectionIds.size === 0) return pool;
return pool.flatMap((candidate) => {
if (Array.isArray(candidate.allowedConnectionIds)) {
const allowedConnectionIds = candidate.allowedConnectionIds.filter(
(connectionId) => !excludedConnectionIds.has(connectionId)
);
if (allowedConnectionIds.length === 0) return [];
if (allowedConnectionIds.length === candidate.allowedConnectionIds.length) {
return [candidate];
}
return [{ ...candidate, allowedConnectionIds }];
}
return candidate.connectionId && excludedConnectionIds.has(candidate.connectionId)
? []
: [candidate];
});
}