Treated an explicit allowed=true and limit_reached=false verdict as authoritative when Codex rounds usage to 100 percent. AuthStorage now honors normalized non-exhausted statuses before numeric fallbacks, keeping a usable Team credential ahead of rejected siblings.
Fixes#7617
Codex reports one account-level limit flag alongside independent chat and Spark meters. Treating that flag, ranking windows, or persisted backoff as provider-wide made an exhausted meter block requests that still had headroom.
Scope exhaustion, ranking, and reactive backoff to the meter each request spends. Every selection path honors the request scope plus the legacy shared scope, including sibling availability, session pinning, and final OAuth resolution.
Reconciliation now evaluates and deletes each persisted meter block independently. The local and broker-backed stores support targeted deletion while the existing all-block deletion endpoint remains compatible.
Signed-off-by: Christian Stewart <christian@aperture.us>
- Ensure that canonical base URLs for openai-codex resolve to the correct `/backend-api` root path.
- Prevent invalid URL generation when a streaming path override is provided for the base URL.
- Added test coverage to verify that streaming paths are correctly stripped when fetching usage data.
Codex usage and reset-credit endpoints (`wham/usage`,
`wham/rate-limit-reset-credits`) live on the canonical ChatGPT origin
and authenticate with the OAuth bearer minted for that origin. They are
not part of the `/responses` API surface that streaming proxies
(Headroom, 9router, etc.) forward, so a `providers.openai-codex.baseUrl`
override pointed at such a proxy used to send wham/* requests at
`{proxy}/wham/usage` and 404 — surfacing as 'No usage data available'
in `/usage show`.
`normalizeCodexBaseUrl` now falls back to `CODEX_BASE_URL` whenever the
configured host is not `chatgpt.com` / `chat.openai.com`, so streaming
traffic keeps flowing through the proxy while usage requests go straight
to OpenAI. Canonical overrides without `/backend-api` are still upgraded
to include it, and empty/unparseable strings fall through to canonical
instead of being passed verbatim.
Fixes#3679
Address codex P2 review: when listCodexResetCredits succeeds but returns
an empty credits array (all expired/redeemed), the stale availableCount
from /wham/usage was preserved instead of being updated to the live value.
- Move availableCount sync outside the credits.length check into its own
if (list) block, so the count is always synced from the detail endpoint.
- Fix the test mock to route the rate-limit-reset-credits endpoint
separately (matching the pattern used by the credits-with-expiry test),
so the list endpoint returns a proper empty-credits response.
The /usage display (TUI, ACP text, and omp usage CLI) now shows when
banked Codex rate-limit resets expire, so users can plan when to redeem
them before the 30-day window lapses.
Changes:
- Added UsageResetCreditDetail interface (grantedAt, expiresAt, status)
and optional credits field to UsageResetCredits in packages/ai
- Updated both ArkType schema copies (usage.ts + wire-schemas.ts)
- The OpenAI Codex usage provider now calls listCodexResetCredits to
fetch individual credit details when availableCount > 0, filtering
out redeemed credits. Errors are logged and swallowed (graceful
degradation: count shows without expiry dates)
- TUI (command-controller.ts): shows per-credit expiry as relative time
+ absolute date under each account line
- ACP text (usage-report.ts): same per-credit expiry rendering
- CLI (usage-cli.ts): shows the soonest expiry date in the account header
- 2 new tests: credit detail fetching with expiry dates, and no extra
API call when availableCount is 0
- Added optional FetchImpl fields to compaction, proxy, AI, coding-agent, and mnemopi options.
- Threaded injected fetch implementations through OAuth, discovery, and search/LLM request flows.
- Removed exported hookFetch utility and its package entrypoint from utils.
- Replaced global-fetch test monkeypatching with per-test FetchImpl mocks across test suites.
- Added `omp auth-gateway serve/token/status` — a forward-proxy injecting broker credentials for OpenAI Chat, Anthropic Messages, and OpenAI Responses wire formats.
- Added `GET /v1/usage` to auth-broker and auth-gateway; usage cache switched to 5-min per-credential TTL with jitter and last-good fallback on failure.
- Added `AuthStorage.setConfigApiKey/removeConfigApiKey/clearConfigApiKeys` so `models.yml` `apiKey` beats OAuth tokens without overriding `--api-key`.
- Added `omp auth-broker migrate --from-local` for idempotent upload of local SQLite/env credentials to the broker.