Skip to content

[Feature]: retain quota history and make reset windows a scheduling input (capacity estimation, reset ordering, automatic activation) #3376

Open

Description

@lidge-jun

Area

Authentication and account pool

What are you trying to accomplish?

Make quota windows a first-class scheduling input: activate them per account without manual work, order pool selection by when each account's window resets, and estimate how much capacity an account actually has from its observed history.

This consolidates three reports that describe one mechanism from three angles. Each is closed individually and absorbed here:

They share a single blocker: OpenCodex keeps only the newest quota snapshot per account, so nothing downstream can reason about windows over time.

What prevents this today?

Only the latest snapshot is retained. src/codex/quota.ts stores one quota snapshot per account and overwrites it on each observation. Without history, capacity estimation has no input, and reset-window ordering has nothing to sort by.

Pool strategies cannot express reset order. src/types/config.ts limits account-pool strategies to quota, round-robin, and fill-first. There is no way to prefer the account whose window resets soonest, or the one that just reset.

Window activation is manual. src/codex/warmup.ts is an invocation primitive with no reset-driven scheduling, so an account's window starts whenever a request happens to arrive rather than when the operator wants it to.

Note that the observation half now exists: the active account's observed subscription windows are surfaced at provider level (src/providers/muse-subscription-usage.ts, src/providers/registry.ts). The gap is that nothing durably retains or acts on that observation.

What should OpenCodex do?

  1. Retain a bounded history of quota observations per account rather than a single overwritten snapshot.
  2. Derive an effective-capacity estimate per account from that history, and surface it with an explicit confidence or sample count so an operator can tell a guess from a measurement.
  3. Add a reset-window-aware pool ordering strategy that prefers accounts by time-to-reset.
  4. Activate an account's quota window on a schedule tied to its reset, not to incidental traffic.

Example usage or interface

{
  "providers": {
    "codex": {
      "accountPool": {
        "strategy": "reset-window",     // prefer the account whose window resets soonest
        "quotaHistory": { "retain": 200 },
        "autoActivateWindows": true
      }
    }
  }
}
ocx quota history --account me@example.com
# window       observed   used    est. capacity   samples
# 5h           12:00-17:00  61%    ~2.1M tokens    18

Alternatives or workarounds

Operators currently watch the dashboard and rotate accounts by hand around reset times, which is exactly the manual loop these three issues each asked to remove.

Additional context

Absorbs #2344, #2874, #2969. Credit for the original analysis belongs to @Michael-Han0608, @wonny-log, and @terrytan95.

PR #2973 by @terrytan95 (auto-activate quota reset windows) is open and addresses item 4; it is not superseded by this issue.

Checks

  • I searched existing issues and documentation.
  • This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
  • I removed secrets and personal data.

Activity

  1. added
    enhancementNew feature or request
    account-poolOAuth, credentials, Codex pool, quota, failover, plans
    on Sep 3, 2026
  2. coderabbitai commented on Sep 3, 2026

    @coderabbitai
    Contributor
    ⚠️ Possible Duplicate Issue(s)

    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  3. added
    platformOS/service/tray/ACL (Windows-heavy, not Windows-only)
    on Sep 3, 2026
  4. lidge-jun commented on Sep 3, 2026

    @lidge-jun
    OwnerAuthor

    리뷰 · 우선순위 70 / 80

    이 이슈는 쿼터 창을 “지금 스냅샷 하나”가 아니라, 고르는 입력으로 쓰자는 요청입니다. 용량을 추정하고, 창이 언제 리셋되는지 보고 계정을 고르고, 리셋 시각에 창을 자동으로 켜려면, 과거 관측이 필요합니다. 지금 dev HEAD(664d80c76)의 src/codex/quota.ts는 계정마다 최신 스냅샷 하나를 디스크에 두고, 새 관측이 오면 덮어씁니다. 주간·월간·짧은 창·커스텀 창 필드는 있지만 시계열은 없습니다. 그래서 용량 추정(#2344)과 리셋 시각 정렬(#2874)과 자동 활성화(#2969)가 서로 다른 말처럼 보여도, 막힌 곳은 하나입니다. 과거가 없습니다.

    풀 전략도 아직 그 입력을 받을 자리가 없습니다. src/types/config.ts의 OcxAccountPoolRotationStrategy는 quota | round-robin | fill-first뿐입니다. 콤보 쪽 OcxComboStrategy에는 이미 reset-window가 있습니다(#3373이 GUI 선택기를 여는 바로 그 값). 계정 풀에는 같은 이름이 없습니다. src/codex/warmup.ts는 호출 프리미티브이지, 리셋 시각에 맞춰 창을 켜는 스케줄러가 아닙니다. 관측 반은 본문 말대로 제공자 수준에 있습니다(src/providers/muse-subscription-usage.ts 등). 없는 것은 그 관측을 쌓고, 풀 선택에 넣는 일입니다.

    흡수된 #2344, #2874, #2969는 닫혀 있습니다. 열린 PR #2973(feat(codex): auto-activate quota reset windows, @terrytan95)은 이 이슈가 “항목 4만 다룬다, 대체되지 않는다”고 적어 두었습니다. 자동 활성화만 먼저 넣으면 히스토리 없이 리셋 시각을 추측하게 되므로, #2973은 히스토리 저장이 생긴 뒤에 리베이스하는 편이 안전합니다. 이 이슈 자체는 types.ts/config.ts 분할에 치여 닫을 대상이 아닙니다. 다만 reset-window 전략을 설정에 넣는 패치는 src/types/config.ts를 만지므로, 분할 캠페인과 겹치면 그 PR은 닫고 다시 쓰는 쪽이 맞습니다.

    저장 상한(quotaHistory.retain: 200)은 필요합니다. 쿼터 스냅샷을 무한히 쌓으면 홈 디렉터리가 커집니다. CLI ocx quota history는 관측이 쌓인 다음에야 의미가 있습니다. 콤보의 reset-window와 계정 풀의 reset-window를 같은 이름으로 쓸지는 헷갈릴 수 있습니다. 콤보는 타깃 모델 사이, 풀은 계정 사이입니다. 이름이 같아도 객체가 다릅니다. 문서에 한 줄로 구분해 두는 편이 좋습니다.

    src/codex/quota.ts - 계정당 최신 스냅샷만 유지합니다. 히스토리가 없어 용량 추정·리셋 정렬의 입력이 없습니다.

    src/types/config.ts OcxAccountPoolRotationStrategy - quota / round-robin / fill-first만 있고 reset-window가 없습니다. 콤보 전략과 다릅니다.

    src/codex/warmup.ts - 리셋 시각 스케줄이 아니라 호출 프리미티브입니다.

    열린 PR #2973 - 자동 활성화만 다루며 이 이슈가 대체하지 않는다고 본문에 적혀 있습니다. 히스토리 저장보다 앞설 수 있습니다.

    메인테이너의 판단이 필요한 지점

    • 히스토리 저장을 먼저 넣고 #2973을 그 위에 올릴지, #2973을 독립으로 머지할지.
    • 계정 풀 전략 이름 reset-window를 콤보와 공유할지, 더 구체적인 이름을 쓸지.
    • retain 기본값과 디스크 위치(OPENCODEX_HOME 아래인지).

    너의 추천
    이 이슈를 열어 두고, 첫 작업은 계정당 쿼터 히스토리를 상한과 함께 저장하는 것입니다. 그 다음 풀 전략 reset-window와 자동 활성화를 얹으세요. #2973은 히스토리 커밋 위에 다시 맞추는 것을 권합니다. 흡수된 원본 이슈는 다시 열지 마세요.

    이 댓글은 grok-bot이 작성했습니다

  5. added
    priority: P3Low: new provider/client integration, large or experimental feature (>2000 LOC or >50 files), RFC/ro
    on Sep 24, 2026
  6. devin-ai-integration commented on Sep 24, 2026

    @devin-ai-integration
    Contributor

    Triage: priority: P3 — quota history and reset scheduling.

    Criteria (P3): Low: new provider/client integration, large or experimental feature (>2000 LOC or >50 files), RFC/roadmap, or long-stale branch.

    Matched pull requests:

  7. luvs01 commented on Sep 27, 2026

    @luvs01
    Collaborator

    Follow-up measurement for the automatic activation part of this issue, after #6056 was closed in favor of #6020 / #6062.

    On Windows, the running proxy reports OpenCodex 2.68.0. One configured, validated, unpaused Pro Lite pool account has weekly automatic activation enabled. Two direct, identity-checked WHAM reads showed:

    Observed (UTC) used_percent limit_window_seconds reset_after_seconds reset_at
    2026-09-27 12:49:29 0 604800 604800 1791118169
    2026-09-27 12:50:32 0 604800 604800 1791118232

    The reset moved by 63 seconds while the remaining duration stayed at the full seven days. This distinguishes an unanchored idle window from a started window whose small usage merely rounds to 0%. Other accounts in the same process have fixed reset timestamps and decreasing remaining durations.

    The idle account's persisted nextWeeklyResetAt is 1791018013000 (2026-10-03 09:00:13 UTC), still almost six days away. The retained-deadline implementation therefore addresses eventual activation, but does not start this already-opted-in idle weekly window now. This observation does not prove that the retained deadline will fail when it becomes due; it identifies the gap between scheduled activation and initial activation on enable/startup.

    For a narrow follow-up, an explicit per-account Start unused window now action with a small-request explanation would make this state actionable without reviving #6056's extra polling or account-wide retry fence. If initial activation is made automatic instead, it should require fresh same-credential moving-window evidence and replace the affected saved deadline only after verified completion, without delaying due work for other windows or repeating a request after an ambiguous result.

    No warmup, token refresh, reset-credit use, pin/priority change, or quota-counter edit was performed for this measurement. No account identifiers or credentials are included. Keeping this evidence in the existing tracking issue rather than opening a duplicate or reopening the superseded PR.

  8. lidge-jun commented on Sep 27, 2026

    @lidge-jun
    OwnerAuthor

    Release train 4 (account-pool lane) re-checked this against dev. Several parts already exist:

    • Bounded quota history (src/codex/quota-history.ts).
    • A capacity estimate that reports low confidence and its sample count (src/codex/quota-capacity.ts).
    • Codex reset-first ordering (src/codex/routing/selection.ts).
    • Opt-in scheduled activation (src/codex/quota-auto-refresh.ts).

    Keeping it open for the part @luvs01 measured on 2.68.0: an idle weekly window on an opted-in account stays unstarted until its later due time. Whether Anthropic has any reset ordering also still needs checking. This train does not change either.

  9. xmzzzw commented on Oct 15, 2026

    @xmzzzw

    Feature proposal: Adaptive Idle Quota Staggering & Realignment (extension to #3376)

    Area: Codex account pool / quota-window auto-activation

    I'd like to propose a pool-level, opt-in idle-mode coordinator on top of the existing quota history, reset-first routing, and per-account scheduled activation. The goal is not to raise upstream limits or force users to rotate accounts every five hours. It is to reduce simultaneous 5-hour quota exhaustion / waiting by keeping the actual refill/reset boundaries of eligible accounts reasonably spread out whenever the user is idle.

    Problem: static staggering breaks as soon as real work happens

    Suppose two Plus accounts have 5-hour windows and we initially aim for a 150-minute phase gap:

    • A starts at 00:00; next observed reset ~05:00.
    • B is scheduled to start at 02:30; next reset ~07:30.
    • But A is exhausted and real user traffic reaches B at 01:00. B's real window now anchors around 01:00 (assuming this provider/account uses first-use-anchored windows), with its next reset ~06:00.
    • B's 02:30 synthetic activation is now redundant; and the subsequent 05:00/06:00 resets are only 60 minutes apart.

    Simply repeating "A → B → A" every five hours does not solve this: normal traffic changes window anchors, so later rounds can converge again. Conversely, holding or redirecting real traffic merely to preserve staggered timing is unacceptable.

    Proposed behavior: two operating modes, one pool-level scheduler

    Active mode (real traffic always wins):

    • On observed real user/agent traffic, immediately suspend conflicting background activation jobs; never delay live requests for phase alignment.
    • Preserve existing pool selection, task/session affinity, priority, exhaustion failover, cooldown, re-authentication, and 5-hour/weekly enforcement.
    • Record authoritative per-account window/reset observations caused by normal use. Real use may change the planned phase; accept that and replan.
    • Only traffic visible to the proxy can be observed reliably; provide a manual pause for out-of-band usage.

    Idle mode (best-effort pre-activation and repair):

    • Enter after all proxied user tasks/requests have finished and a configurable quiet period has elapsed (e.g., 30 minutes).
    • Coordinate all opted-in automatic activations at the pool level; independent account refresh workers must not bypass the stagger policy and re-activate everything simultaneously at the next reset.
    • For healthy eligible accounts whose new 5-hour window is genuinely unstarted, schedule minimal, verifiable activation requests at staggered times. With N eligible homogeneous 5-hour accounts, 300/N minutes is a target phase spacing, not a mandatory per-account timer.
    • If real traffic changes an account's reset time, cancel stale synthetic jobs, calculate the actual gaps between eligible observed resets, and gradually realign by deferring a future idle-only activation, within a configurable deferral budget. Never modify an already-started window or assume its reset can be moved.
    • If a new real request arrives before a deferred warmup, the real request proceeds immediately and the plan is recomputed afterward. Missed jobs should be recomputed, not replayed blindly.
    • If delaying a warmup would meaningfully reduce useful capacity, exceed the deferral budget, or offer no clear improvement, skip the adjustment. This is best-effort optimization, not guaranteed synchronization.

    Example (two accounts)

    Time Event Expected scheduler decision
    00:00 A window starts A reset ~05:00
    01:00 A exhausted; actual work starts B early B reset ~06:00; cancel B's planned 02:30 warmup
    03:00 Real tasks finish Enter idle after quiet-period threshold
    05:00 A is eligible for a new window May activate A if still idle
    06:00 B becomes eligible for a new window Defer only B's background re-activation, e.g. toward 07:30 if allowed by policy/budget
    06:15 User sends work to B (if this occurs) Serve immediately; cancel B's pending warmup and replan

    This progressively restores the desired separation without making the user wait. The exact reset times must always be observed from the provider rather than inferred as fixed calendar cycles.

    Implementation constraints / safety

    1. One coordinator / one scheduling authority for opted-in background warmups. Reuse src/codex/quota-history.ts, src/codex/routing/selection.ts, src/codex/quota-auto-refresh.ts, and the existing activation primitive where appropriate; do not rebuild account routing.
    2. Explicitly distinguish UNSTARTED, ACTIVE, EXHAUSTED, ELIGIBLE_AFTER_RESET, and UNKNOWN for each short window. used_percent=0 alone does not prove an active/anchored window.
    3. Persist the scheduler's own monotonic/stable intended slot and activation generation. Do not derive an idle slot each time from a sliding reset_at ≈ now + 300min: see codex-lb #1976.
    4. Only healthy, authenticated, non-paused accounts with real 5-hour-window evidence enter the 5-hour cohort; exclude weekly-only/incompatible windows. Respect weekly exhaustion independently.
    5. Make activation idempotent per observed window generation, crash-safe, bounded in retries, and conservative on ambiguous success; verify any remote activation via reliable upstream quota signals, not merely HTTP 200.
    6. Keep all synthetic activity opt-in, off the request path, rate-limited, and subject to provider permissions/terms. Expose its quota/token cost and allow disabling or manual pause. No attempts to bypass upstream limits or anti-abuse controls.
    7. Show each account's observed reset, started/unstarted state, next planned idle warmup, phase-gap health, and reason for deferral/skip. Keep legacy automatic activation as the unchanged default.

    Suggested acceptance tests

    • Two/three untouched accounts start with evenly distributed planned slots; later cycles do not unintentionally collapse into same-time activations.
    • Real traffic activates B before its scheduled warmup; the warmup is cancelled and phase alignment is recomputed from B's actual reset.
    • Real traffic interrupts a deferred warmup; no user-visible delay or duplicate activation occurs.
    • A sliding, unanchored upstream reset_at does not indefinitely starve non-zero slots.
    • Mixed 5-hour/weekly-only accounts, weekly exhaustion, unknown metadata, 429/401, proxy restart/crash, and stale activation results behave safely.
    • Compare observed minutes when all eligible pool accounts are simultaneously unusable (and background cost) against current behavior; do not consider equal-looking planned timestamps alone a success.

    Prior work / rationale

    Would this be a reasonable opt-in pool-level activation policy under #3376, reusing the existing scheduler and routing components?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    account-poolOAuth, credentials, Codex pool, quota, failover, plansenhancementNew feature or requestplatformOS/service/tray/ACL (Windows-heavy, not Windows-only)priority: P3Low: new provider/client integration, large or experimental feature (>2000 LOC or >50 files), RFC/ro

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions