Files
OmniRoute/src/shared/constants/quotaAutoPing.ts
Diego Rodrigues de Sa e Souza ad7692b3d3 feat(quota): opt-in auto-ping to keep Codex quota windows warm (#6977) (#6995)
Codex's rolling "session" quota window only starts counting down once a
request lands inside it, so an idle connection's window keeps sliding
forward and the first real request after a long idle period pays for the
whole warm-up latency. This adds a strictly opt-in, per-connection
scheduler (default OFF) that watches an enabled connection's reported
resetAt and, once it slides forward, fires one tiny non-billed-model
request through the real Codex executor to keep the window warm.

- New in-process scheduler (src/lib/services/quotaAutoPing.ts), fully
  dependency-injected (settings, DB, credential refresh, usage fetch,
  executor, circuit breaker) and clock-injectable for deterministic tests.
  Reimplemented in TS from the shipped 9router
  src/shared/services/quotaAutoPing.js (Codex half only).
- Migration 123: last_ping_at / last_pinged_reset_key on
  provider_connections, so the scheduler never re-pings the same reset
  window twice.
- Settings: codexAutoPing.connections map, default {} (nobody opted in),
  validated by the shared Zod schema.
- Respects the existing resilience layers: skips a connection whose
  provider circuit breaker is open or whose rateLimitedUntil cooldown is
  active, and applies its own 15-minute failure cooldown after a failed
  ping.
- UI: new per-connection toggle (Settings -> AI -> Codex Quota Auto-Ping)
  with an explicit "consumes real quota" tooltip, wired to the settings
  PATCH route; i18n keys added to all 43 locales (EN authored, others
  filled from the EN fallback pending real translation).
- 15 new deterministic unit tests covering enable/disable, first-reset
  observation (cache-only, no ping), reset-slide ping, stable-reset
  no-op, min-ping-interval, same-resetKey dedupe, session/weekly quota
  exhaustion, non-OAuth skip, circuit-breaker-open skip, cooldown skip,
  failure-cooldown skip, failed-ping bookkeeping, the real executor call
  shape, and credential-refresh failure handling.

Antigravity's 2-bucket auto-ping is out of scope for this PR (no upstream
reference exists for its reset shape) and is tracked as a follow-up.

Ref #6977 (backend + settings + minimal UI toggle; Antigravity follow-up
tracked separately — not closing the issue from this PR)
2026-07-17 10:54:56 -03:00

50 lines
2.0 KiB
TypeScript

/**
* quotaAutoPing.ts — config for the opt-in Codex quota auto-ping (#6977).
*
* Phase 1 (this file): Codex only — resetAt is inferred by watching the
* "session" window slide forward (Codex has no explicit reset event; an
* inactive window quietly rolls to a fresh one on the next usage read).
* Antigravity (2 buckets, no upstream reference) is a follow-up — see the
* PR body for #6977.
*/
export const QUOTA_AUTOPING_TICK_INTERVAL_MS = 60_000;
// How long a connection must stay quiet after a failed ping before we retry it.
export const QUOTA_AUTOPING_FAILURE_COOLDOWN_MS = 15 * 60 * 1000;
// Once a resetAt is observed and cached, skip re-fetching usage until we're
// within this window of it (Codex resetAt slides constantly while idle, so we
// still poll every tick, but this bounds how eagerly we ping right after a slide).
export const QUOTA_AUTOPING_REFRESH_AHEAD_MS = 5 * 60 * 1000;
export type QuotaAutoPingProviderConfig = {
settingsKey: string;
quotaKey: string;
/** Codex has no fixed reset schedule — ping whenever resetAt slides forward. */
pingWhenResetAtSlides: true;
/** Minimum forward drift (ms) before a slide counts as "the window rolled". */
resetAtDriftMs: number;
/** Never re-ping the same connection more often than this, even across resets. */
minPingIntervalMs: number;
/** Skip the ping when a non-session quota (e.g. weekly) is already exhausted. */
skipWhenBlockingQuotaExhausted: true;
pingModel: string;
pingText: string;
pingInstructions: string;
pingReasoningEffort: string;
};
export const QUOTA_AUTOPING_PROVIDERS: Record<"codex", QuotaAutoPingProviderConfig> = {
codex: {
settingsKey: "codexAutoPing",
quotaKey: "session",
pingWhenResetAtSlides: true,
resetAtDriftMs: 30_000,
minPingIntervalMs: 10 * 60 * 1000,
skipWhenBlockingQuotaExhausted: true,
pingModel: "gpt-5.1-codex-mini",
pingText: "hi",
pingInstructions: "Reply with OK.",
pingReasoningEffort: "none",
},
};