fix(sse): canonicalize alias provider ids before quota fetcher lookup (#10877)

This commit is contained in:
Markus Hartung
2026-08-20 20:41:59 -03:00
parent bc9090ba65
commit b668d91364
4 changed files with 78 additions and 2 deletions

View File

@@ -0,0 +1 @@
- **fix(sse):** `getResetAwareProvider()` and the auto-combo quota lookup in `combo.ts` now canonicalize the provider id via `resolveProviderId()` before calling `getQuotaFetcher()`, so a fetcher registered under a provider's canonical id (e.g. `ollama-cloud`, `codex`) is found for combo targets stored under an alias spelling (e.g. `ollamacloud`, `cx`) instead of silently degrading reset-aware/reset-window/auto quota-aware routing to plain priority ordering (#10877)

View File

@@ -64,6 +64,7 @@ import { getHiddenModelsByProvider } from "@/models";
import { resolveModelLockoutSettings } from "../../src/lib/resilience/modelLockoutSettings";
import { fetchCodexQuota } from "./codexQuotaFetcher.ts";
import { evaluateQuotaCutoff, getQuotaFetcher, type QuotaInfo } from "./quotaPreflight.ts";
import { resolveProviderId } from "../../src/shared/constants/providers.ts";
import * as semaphore from "./rateLimitSemaphore.ts";
import { getCircuitBreaker } from "../../src/shared/utils/circuitBreaker";
import { parseModel } from "./model.ts";
@@ -491,7 +492,10 @@ export async function buildAutoCandidates(
let quotaRemaining = 100;
let quotaCutoffBlocked = false;
let quotaCutoffReason: string | undefined;
const fetcher = getQuotaFetcher(provider);
// #10877: `provider` here may be a legacy/user-facing alias spelling
// (target.provider/parseModel output); canonicalize before the fetcher
// registry lookup so aliased combo members still hit quota-aware scoring.
const fetcher = getQuotaFetcher(resolveProviderId(provider));
const connection = target.connectionId ? connectionById.get(target.connectionId) : undefined;
const authType = typeof connection?.authType === "string" ? connection.authType : null;
const sessionAvailability =

View File

@@ -14,6 +14,7 @@ import { isRecord } from "./comboData.ts";
import type { SlaRoutingPolicy } from "../autoCombo/routerStrategy.ts";
import { RESET_WINDOW_NAMES } from "./types.ts";
import type { ResolvedComboTarget } from "./types.ts";
import { resolveProviderId } from "../../../src/shared/constants/providers.ts";
const RESET_AWARE_SESSION_WINDOW_MS = 5 * 60 * 60 * 1000;
const RESET_AWARE_WEEKLY_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
@@ -138,7 +139,11 @@ export function resolveSlaRoutingPolicy(
export function getResetAwareProvider(target: ResolvedComboTarget): string | null {
const provider = (target.providerId || target.provider || "").toLowerCase();
return provider || null;
// #10877: combo targets can carry a legacy/user-facing alias spelling
// (e.g. "ollamacloud", "cx") while quota fetchers register under the
// canonical provider id (e.g. "ollama-cloud", "codex"). Canonicalize here
// so getQuotaFetcher() lookups downstream (quotaStrategies.ts) find them.
return provider ? resolveProviderId(provider) : null;
}
function normalizeResetAt(value: unknown): string | null {

View File

@@ -0,0 +1,66 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { getResetAwareProvider } from "../../open-sse/services/combo/quotaScoring.ts";
import { registerQuotaFetcher, getQuotaFetcher } from "../../open-sse/services/quotaPreflight.ts";
import { resolveProviderId } from "../../src/shared/constants/providers.ts";
import type { ResolvedComboTarget } from "../../open-sse/services/combo/types.ts";
function buildTarget(provider: string): ResolvedComboTarget {
return {
kind: "model",
stepId: "s1",
executionKey: "e1",
modelStr: `${provider}/some-model`,
provider,
providerId: provider,
connectionId: "conn-1",
weight: 1,
label: null,
} as ResolvedComboTarget;
}
test("#10877: getResetAwareProvider() canonicalizes an alias-spelled provider so the fetcher registered under the canonical id is found", () => {
registerQuotaFetcher("ollama-cloud", async () => ({ ok: true }) as never);
const target = buildTarget("ollamacloud");
const lookedUpProvider = getResetAwareProvider(target);
assert.equal(
lookedUpProvider,
resolveProviderId("ollamacloud"),
"getResetAwareProvider() should return the canonical provider id, not the raw alias"
);
const fetcher = getQuotaFetcher(lookedUpProvider!);
assert.notEqual(
fetcher,
undefined,
"a fetcher registered under the canonical provider id must be found for an alias-spelled combo target"
);
});
test("#10877: getResetAwareProvider() is a no-op (same cache key) for already-canonical provider ids", () => {
registerQuotaFetcher("codex", async () => ({ ok: true }) as never);
const target = buildTarget("codex");
const lookedUpProvider = getResetAwareProvider(target);
assert.equal(lookedUpProvider, "codex");
assert.notEqual(getQuotaFetcher(lookedUpProvider!), undefined);
});
test("#10877: getResetAwareProvider() returns null when neither providerId nor provider is set", () => {
const target = {
kind: "model",
stepId: "s1",
executionKey: "e1",
modelStr: "unknown/model",
provider: "",
providerId: "",
connectionId: "conn-1",
weight: 1,
label: null,
} as ResolvedComboTarget;
assert.equal(getResetAwareProvider(target), null);
});