import type { CredentialRankingContext, CredentialRankingStrategy } from "../usage.js"; import type { RankingStrategyResolver } from "../usage/registry.js"; import type { CredentialBlocks } from "./blocks.js"; import type { KeyOverrides } from "./cascade.js"; import type { SessionAffinity } from "./affinity.js"; import type { CredentialPool } from "./pool.js"; import type { AuthCredentialStore } from "./store.js"; import type { CredentialRotation, InvalidateCredentialMatchingOptions, LimitsApi, MarkUsageLimitOptions, RotateCredentialOptions, UsageLimitMarkResult } from "./types.js"; import type { UsageService } from "./usage.js"; /** Routing scope and strategy for one failed credential. */ export type CredentialBlockRouting = { providerKey: string; strategy: CredentialRankingStrategy | undefined; rankingContext: CredentialRankingContext; blockScope: string | undefined; siblingBlockScopes: readonly string[]; }; /** Dependencies for rate-limit marking and credential rotation. */ export interface RateLimitsDeps { store: AuthCredentialStore; pool: CredentialPool; overrides: KeyOverrides; blocks: CredentialBlocks; affinity: SessionAffinity; usage: UsageService; strategies: RankingStrategyResolver; } /** Usage-limit marking, credential rotation after failures, and bearer-matched invalidation. */ export declare class RateLimits implements LimitsApi { #private; constructor(deps: RateLimitsDeps); /** * Marks the current session's credential as temporarily blocked due to usage limits. * Uses usage reports to determine accurate reset time when available. * Returns whether a sibling credential is available now; when none is, also * reports the earliest time a blocked sibling becomes available again so * callers can wait for the sibling instead of the provider's full window. */ markReached(provider: string, sessionId: string | undefined, options?: MarkUsageLimitOptions): Promise; invalidateMatching(provider: string, apiKey: string, options?: InvalidateCredentialMatchingOptions): Promise; /** * Rotate away from the credential that failed after a retryable auth error — * step (c) of the auth-retry policy. Prefer the failed stored row id supplied * in `options.credentialId`, then the failed bearer supplied in * `options.apiKey`, so overlapping requests cannot redirect rotation through * stale session stickiness. Fall back to the session-sticky credential only * when neither explicit target is available. For hard-auth errors, an explicit * target that no longer matches storage returns `false` without mutation. * Delayed usage-limit and account-policy errors may instead recover the durable * OAuth row from the bearer fingerprint recorded when the request resolved. * * - usage-limit / account-rate-limit error → {@link RateLimits.markReached} * (temporary block via its own backoff — default plus server usage-report * reset; sticky left intact so the next resolve re-ranks around the block). * - exact model-entitlement denial (Codex ChatGPT account or Cursor plan) → * temporarily block only that requested model, then rotate. * - other account-scoped policy denial → temporarily block that account * without marking its credential suspect, then rotate through siblings. * - otherwise (hard 401 / auth failure) → mark the credential suspect (or * reload when no broker hook is wired) and block it, then drop matching * sticky state. * * For usage-limit and account-policy failures with no free sibling, sleeps * until the earliest sibling unblocks when that is at most * {@link SIBLING_UNBLOCK_WAIT_MAX_MS} away, then reports `afterSiblingWait`. * Aborting `options.signal` during that wait rejects. */ rotate(provider: string, sessionId: string | undefined, options?: RotateCredentialOptions): Promise; }