mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-19 05:32:19 +03:00
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)
50 lines
2.0 KiB
TypeScript
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",
|
|
},
|
|
};
|