/** * Plan limits for client-side pacing (same account limits the dashboard shows). */ import { OPENFERENCE_ORIGIN, OPENFERENCE_USER_AGENT } from "./constants.ts"; export interface AccountLimits { maxRpm: number; } const DEFAULT_MAX_RPM = 60; /** * Fetch effective plan RPM via GET /api/user/me (authMiddleware accepts OAuth JWTs). */ export async function fetchAccountLimits( accessToken: string, fetchImpl: typeof fetch = fetch, signal?: AbortSignal, ): Promise { const res = await fetchImpl(`${OPENFERENCE_ORIGIN}/api/user/me`, { headers: { Authorization: `Bearer ${accessToken}`, "User-Agent": OPENFERENCE_USER_AGENT, }, signal, }); if (!res.ok) { throw new Error(`GET /api/user/me -> HTTP ${res.status}`); } const json = (await res.json()) as { limits?: { maxRpm?: number }; plan?: { maxRpm?: number }; }; const maxRpm = Number(json.limits?.maxRpm ?? json.plan?.maxRpm ?? DEFAULT_MAX_RPM); return { maxRpm: Number.isFinite(maxRpm) && maxRpm > 0 ? maxRpm : DEFAULT_MAX_RPM, }; } /** Minimum spacing between request starts for a given RPM (ms). */ export function minIntervalMsForRpm(maxRpm: number): number { const rpm = Math.max(1, maxRpm); return Math.ceil(60_000 / rpm); }