import type { ProviderUsageLimitsUpdate, ServerProviderUsageLimits, ServerProviderUsageWindow, } from "@t3tools/contracts"; const WINDOW_KIND_ORDER: Record = { session: 0, weekly: 1, monthly: 2, other: 3, }; export function clampPercent(value: number): number { return Number.isFinite(value) ? Math.max(0, Math.min(100, value)) : 0; } function sortWindows( windows: Iterable, ): ReadonlyArray { return [...windows].toSorted( (left, right) => WINDOW_KIND_ORDER[left.kind] - WINDOW_KIND_ORDER[right.kind] || left.id.localeCompare(right.id), ); } export function makeUsageLimits(input: { readonly checkedAt: string; readonly windows: Iterable; }): ServerProviderUsageLimits { return { checkedAt: input.checkedAt, windows: sortWindows(input.windows) }; } export function makeUnavailableUsageLimits(input: { readonly checkedAt: string; readonly reason: "unsupported" | "probeFailed"; readonly message?: string; }): ServerProviderUsageLimits { return { checkedAt: input.checkedAt, windows: [], unavailable: { reason: input.reason, ...(input.message ? { message: input.message } : {}), }, }; } /** * Fold a sparse runtime update into the limits a provider currently * publishes. Windows upsert by `id`; a window the update omits keeps its * previous values, and a window that arrives without `resetsAt` or * `windowDurationMins` keeps whatever the last probe resolved for it. An * update with no windows leaves `previous` untouched. * * An `unsupported` snapshot stays unsupported: an account that cannot have * subscription windows will not start reporting them mid-turn. */ export function applyUsageLimitsUpdate(input: { readonly previous: ServerProviderUsageLimits | undefined; readonly update: ProviderUsageLimitsUpdate; readonly checkedAt: string; }): ServerProviderUsageLimits | undefined { const { previous, update } = input; if (update.windows.length === 0 || previous?.unavailable?.reason === "unsupported") { return previous; } const merged = new Map(previous?.windows.map((window) => [window.id, window] as const)); // Codex sends this notification beside every token-usage tick, almost // always with unchanged numbers. Decide "nothing changed" per window on // the way through so the no-op case never allocates a new snapshot. let changed = false; for (const window of update.windows) { const existing = merged.get(window.id); const next: ServerProviderUsageWindow = { ...window, usedPercent: clampPercent(window.usedPercent), ...(window.resetsAt === undefined && existing?.resetsAt !== undefined ? { resetsAt: existing.resetsAt } : {}), ...(window.windowDurationMins === undefined && existing?.windowDurationMins !== undefined ? { windowDurationMins: existing.windowDurationMins } : {}), }; if (existing === undefined || !usageWindowEquals(existing, next)) { merged.set(window.id, next); changed = true; } } if (!changed && previous !== undefined && previous.unavailable === undefined) { return previous; } return { ...makeUsageLimits({ checkedAt: input.checkedAt, windows: merged.values() }), ...(previous?.resetCredits !== undefined ? { resetCredits: previous.resetCredits } : {}), }; } function usageWindowEquals(a: ServerProviderUsageWindow, b: ServerProviderUsageWindow): boolean { return ( a.id === b.id && a.kind === b.kind && a.label === b.label && a.usedPercent === b.usedPercent && a.resetsAt === b.resetsAt && a.windowDurationMins === b.windowDurationMins ); } /** * Choose what to publish after a status probe finishes. A probe that failed * this time must not wipe bars a previous probe or a turn already * established, so the last good snapshot stays; `unsupported` is * authoritative and replaces them. * * A successful probe replaces the published windows outright, including any * runtime update that landed while it was running. That is a deliberate * trade-off: the Codex and Claude reads take a few seconds at most, the * probe is the fresher full read in every case except that window, and the * per-window epoch bookkeeping needed to reconcile the two was more code * than the sub-second regression it prevented. The next runtime event * corrects it. */ export function resolveUsageLimitsAfterProbe(input: { readonly published: ServerProviderUsageLimits | undefined; readonly probed: ServerProviderUsageLimits | undefined; }): ServerProviderUsageLimits | undefined { const { published, probed } = input; if (probed?.unavailable?.reason === "probeFailed" && published && !published.unavailable) { return published; } return probed; }