mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-26 09:02:11 +03:00
* feat(alibaba): add free-tier routing with console quota and builtin allowlist Classify DashScope free vs paid models via console quota API, a hardcoded operator allowlist fallback, and per-connection drained tracking. Wire wildcard combo expansion, model refresh, combo exhaustion, and audit redaction for Alibaba console credentials. * fix(routing): reset forced connection pin and persist Alibaba free-tier drain Drop session affinity pins when a forced connection is excluded after 429, and record Alibaba free-tier exhaustion on upstream 403 so per-key drained lists stay accurate without blocking sibling keys. * fix(alibaba): prefer live quota sync over static free-tier allowlist Stop unioning the builtin text allowlist when a console quota snapshot exists, treat expired quotaValidityPeriod as not_capable, and add a dated JSON pack plus sync-alibaba-allowlist script for operator refresh without code edits. * docs(alibaba): document free-tier console path + allowlist env overrides Adds the 4 ALIBABA_FREE_TIER_*_FE_PATH / ALIBABA_FREE_TIER_ALLOWLIST_PATH env vars (referenced by alibabaFreeTierQuotaFetcher.ts and alibabaFreeTierAllowlist.ts) to .env.example and docs/reference/ENVIRONMENT.md so the env/docs contract check passes. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> * refactor(open-sse): split alibabaFreeTierQuotaFetcher.ts under file-size cap Extract pure parsing/classification/eligibility-filtering logic into alibabaFreeTierQuotaClassify.ts and shared types/primitives into alibabaFreeTierQuotaTypes.ts, leaving the HTTP/console-fetch flow in the original file. Public API is unchanged (re-exported), behavior is identical. Co-authored-by: AndrianBalanescu <AndrianBalanescu@users.noreply.github.com> * fix: resolve typecheck errors in alibaba-free-tier routing --------- Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: AndrianBalanescu <AndrianBalanescu@users.noreply.github.com> Co-authored-by: AndrianBalanescu <andrian@balanescu.dev>
59 lines
2.0 KiB
TypeScript
59 lines
2.0 KiB
TypeScript
/**
|
|
* @file alibabaFreeTierQuotaTypes.ts
|
|
* @description Shared types + small primitive helpers for the Alibaba free-tier quota
|
|
* fetcher/classifier split (extracted from alibabaFreeTierQuotaFetcher.ts to keep that
|
|
* file under the file-size cap; behavior is unchanged).
|
|
*/
|
|
|
|
export type AlibabaFreeTierQuotaEntry = {
|
|
model: string;
|
|
freeTierOnly: boolean;
|
|
quotaStatus: string;
|
|
quotaTotal?: number;
|
|
quotaInitTotal?: number;
|
|
quotaTotalPercentage?: number;
|
|
quotaValidityPeriod?: number;
|
|
};
|
|
|
|
export type AlibabaFreeTierQuotaClassification = {
|
|
capableModels: string[];
|
|
noFreeTierModels: string[];
|
|
drainedModels: string[];
|
|
entries: AlibabaFreeTierQuotaEntry[];
|
|
};
|
|
|
|
export type AlibabaFreeTierQuotaSnapshot = {
|
|
text: AlibabaFreeTierQuotaClassification;
|
|
vision: AlibabaFreeTierQuotaClassification;
|
|
multimodal: AlibabaFreeTierQuotaClassification;
|
|
audio: AlibabaFreeTierQuotaClassification;
|
|
entries: AlibabaFreeTierQuotaEntry[];
|
|
};
|
|
|
|
export function asRecord(value: unknown): Record<string, unknown> {
|
|
return value && typeof value === "object" && !Array.isArray(value)
|
|
? (value as Record<string, unknown>)
|
|
: {};
|
|
}
|
|
|
|
export function toTrimmedString(value: unknown): string | null {
|
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
}
|
|
|
|
export function normalizeModelIdList(raw: unknown): string[] {
|
|
if (!Array.isArray(raw)) return [];
|
|
return raw.filter((entry): entry is string => typeof entry === "string" && entry.length > 0);
|
|
}
|
|
|
|
export function getAlibabaFreeTierQuotaLastSyncAt(
|
|
providerSpecificData: Record<string, unknown> | null | undefined
|
|
): string | null {
|
|
return toTrimmedString(asRecord(providerSpecificData).alibabaFreeTierQuotaLastSyncAt);
|
|
}
|
|
|
|
/** True when the connection has a live console/API quota snapshot (not builtin fallback). */
|
|
export function isAlibabaLiveQuotaSyncAt(syncAt: string | null | undefined): boolean {
|
|
if (!syncAt || syncAt === "builtin-allowlist") return false;
|
|
return Number.isFinite(Date.parse(syncAt));
|
|
}
|