feat: OpenRouter quota tracking (key/credits + free-window counter) (#6842) (#7651)

Validated in merge-train --fast @ 4ed4498 (static gates + changed tests 29/29 + vitest green, 2m39s; full suite ran today on trains 1/2c)
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-07-18 03:11:01 -03:00
committed by GitHub
parent b28331307e
commit 9e084e18a7
15 changed files with 1341 additions and 9 deletions

View File

@@ -124,6 +124,7 @@ import {
import { registerBailianCodingPlanQuotaFetcher } from "@omniroute/open-sse/services/bailianQuotaFetcher.ts";
import { registerCrofUsageFetcher } from "@omniroute/open-sse/services/crofUsageFetcher.ts";
import { registerDeepseekQuotaFetcher } from "@omniroute/open-sse/services/deepseekQuotaFetcher.ts";
import { registerOpenrouterQuotaFetcher } from "@omniroute/open-sse/services/openrouterQuotaFetcher.ts";
import { registerOpencodeQuotaFetcher } from "@omniroute/open-sse/services/opencodeQuotaFetcher.ts";
import { registerGenericQuotaFetchers } from "@omniroute/open-sse/services/genericQuotaFetcher.ts";
import {
@@ -145,10 +146,10 @@ registerBailianCodingPlanQuotaFetcher();
// Surfaces usable_requests + credits in the monitor and only blocks (preflight
// opt-in) when the active bucket reaches zero.
registerCrofUsageFetcher();
// Register DeepSeek balance quota fetcher.
// Hooks into quotaPreflight + quotaMonitor so combos can switch accounts before balance is exhausted.
registerDeepseekQuotaFetcher();
registerOpenrouterQuotaFetcher();
// Register OpenCode quota fetcher (opencode-go / opencode / opencode-zen).
// Surfaces the $12/5h, $30/wk, $60/mo windows in the limits page and enables

View File

@@ -1483,8 +1483,7 @@ export async function getProviderCredentials(
{ fallbackStrategy?: string; stickyRoundRobinLimit?: number }
>;
const providerOverride = providerStrategyOverrides[resolvedId] || {};
const strategy =
providerOverride.fallbackStrategy || settings.fallbackStrategy || "fill-first";
const strategy = providerOverride.fallbackStrategy || settings.fallbackStrategy || "fill-first";
let connection;
const affinityConnection = await selectSessionAffinityConnection(
@@ -1834,8 +1833,10 @@ export async function getProviderCredentialsWithQuotaPreflight(
}
return defaultThresholdPercent;
};
// #6842: openrouter also needs requestedModel, for the :free-window check.
const modelAwarePreflight = provider === "codex" || provider === "openrouter";
const preflightCredentials =
requestedModel && provider === "codex" ? { ...credentials, requestedModel } : credentials;
requestedModel && modelAwarePreflight ? { ...credentials, requestedModel } : credentials;
const preflight = await preflightQuota(provider, connectionId, preflightCredentials, {
resolveMinRemainingPercent,
resolveWarnRemainingPercent: () => warnThresholdPercent,