codex-multi-auth 2.12.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/README.md +10 -1
  3. package/dist/lib/accounts.d.ts +75 -0
  4. package/dist/lib/accounts.d.ts.map +1 -1
  5. package/dist/lib/accounts.js +213 -42
  6. package/dist/lib/codex-manager/account-manager-commands.d.ts.map +1 -1
  7. package/dist/lib/codex-manager/account-manager-commands.js +1 -0
  8. package/dist/lib/codex-manager/commands/limits.d.ts +21 -0
  9. package/dist/lib/codex-manager/commands/limits.d.ts.map +1 -0
  10. package/dist/lib/codex-manager/commands/limits.js +158 -0
  11. package/dist/lib/codex-manager/help.d.ts.map +1 -1
  12. package/dist/lib/codex-manager/help.js +1 -0
  13. package/dist/lib/codex-manager/persist-selected-account.d.ts.map +1 -1
  14. package/dist/lib/codex-manager/persist-selected-account.js +14 -0
  15. package/dist/lib/codex-manager.d.ts.map +1 -1
  16. package/dist/lib/codex-manager.js +12 -0
  17. package/dist/lib/forecast.d.ts.map +1 -1
  18. package/dist/lib/forecast.js +1 -14
  19. package/dist/lib/preemptive-quota-scheduler.d.ts +12 -0
  20. package/dist/lib/preemptive-quota-scheduler.d.ts.map +1 -1
  21. package/dist/lib/preemptive-quota-scheduler.js +21 -0
  22. package/dist/lib/redaction.d.ts +17 -0
  23. package/dist/lib/redaction.d.ts.map +1 -0
  24. package/dist/lib/redaction.js +28 -0
  25. package/dist/lib/request/error-classification.d.ts +13 -6
  26. package/dist/lib/request/error-classification.d.ts.map +1 -1
  27. package/dist/lib/request/error-classification.js +45 -0
  28. package/dist/lib/request/fetch-helpers.d.ts +1 -1
  29. package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
  30. package/dist/lib/request/fetch-helpers.js +1 -1
  31. package/dist/lib/runtime/rotation-proxy-state.d.ts +6 -0
  32. package/dist/lib/runtime/rotation-proxy-state.d.ts.map +1 -1
  33. package/dist/lib/runtime/rotation-server-types.d.ts +7 -0
  34. package/dist/lib/runtime/rotation-server-types.d.ts.map +1 -1
  35. package/dist/lib/runtime/rotation-storage-meta.d.ts.map +1 -1
  36. package/dist/lib/runtime/rotation-storage-meta.js +4 -1
  37. package/dist/lib/runtime-rotation-proxy.d.ts +23 -0
  38. package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
  39. package/dist/lib/runtime-rotation-proxy.js +237 -13
  40. package/dist/lib/storage.d.ts +20 -2
  41. package/dist/lib/storage.d.ts.map +1 -1
  42. package/dist/lib/storage.js +69 -25
  43. package/package.json +1 -1
  44. package/scripts/codex-routing.js +1 -0
  45. package/scripts/codex.js +157 -2
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-multi-auth",
3
- "version": "2.12.0",
3
+ "version": "2.14.0",
4
4
  "description": "Install and operate codex-multi-auth for the official @openai/codex CLI with multi-account OAuth rotation, switching, health checks, and recovery tools.",
5
5
  "interface": {
6
6
  "composerIcon": "./assets/codex-multi-auth-icon.svg"
package/README.md CHANGED
@@ -214,6 +214,7 @@ which would rebind the row to a different workspace.
214
214
  | Command | What it answers |
215
215
  | --- | --- |
216
216
  | `codex-multi-auth report --live --json` | How do I get the full machine-readable health report? |
217
+ | `codex-multi-auth limits --json [--refresh]` | How do I read account quota windows without parsing internal cache files or terminal text? |
217
218
  | `codex-multi-auth fix --live --model gpt-5.5` | How do I run live repair probes with a chosen model? |
218
219
  | `codex-multi-auth why-selected --json` | Which account does the selector pick now, and why? |
219
220
  | `codex-multi-auth usage --since 24h --by project` | What local usage has been recorded recently? |
@@ -296,6 +297,8 @@ Selected runtime/environment overrides:
296
297
  | `CODEX_MULTI_AUTH_FORCE_ACCOUNT=<index\|email\|id>` | Force one account for a single `codex-multi-auth-codex` run (ephemeral; requires rotation proxy) |
297
298
  | `CODEX_MULTI_AUTH_BYPASS=1` | Skip multi-auth intercept and forward straight to official Codex |
298
299
  | `CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0/1` | Opt out/in of live Responses proxy rotation for forwarded Codex CLI/app sessions |
300
+ | `CODEX_MULTI_AUTH_RUNTIME_PROXY_UPSTREAM_BASE_URL=http://127.0.0.1:<port>/<path>` | Route the runtime rotation proxy through an explicit loopback HTTP upstream; requires an explicit port and a numeric loopback host (`127.0.0.0/8` or `[::1]`), and rejects credentials, query strings, fragments, HTTPS, and every other host |
301
+ | `CODEX_MULTI_AUTH_MODEL_CAPACITY_RETRY_MS=<ms>` | Wall-clock ceiling on how long one request waits out a "selected model is at capacity" response before giving up (default 600000, max 3600000, `0` disables) |
299
302
  | `CODEX_MULTI_AUTH_APP_ROTATION_IDLE_MS=<ms>` | Override automatic Codex app helper idle shutdown |
300
303
  | `CODEX_MULTI_AUTH_APP_BIND_INSTALL=0/1` | Opt out/in of packaged Codex app bind self-heal on first CLI run or rotation enable |
301
304
  | `CODEX_MULTI_AUTH_APP_LAUNCHER_INSTALL=0/1` | Opt out/in of routing supported app shortcuts on first CLI run or rotation enable |
@@ -318,6 +321,12 @@ Responses background mode stays opt-in. Enable `backgroundResponses` in settings
318
321
 
319
322
  Runtime rotation is enabled by default for request-bearing wrapper-launched Codex sessions. Package install scripts stay side-effect-free: npm postinstall only prints a short notice (and stays silent in CI or non-interactive installs). The first CLI run after an install self-heals supported packaged Codex app binds and user-level launcher routing when possible (recorded once in a `first-run-setup.json` marker under the multi-auth runtime root), while `codex-multi-auth rotation enable` remains the explicit repair command. `codex-multi-auth rotation disable` turns the setting off and removes the persistent app bind. Set `CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0`, `CODEX_MULTI_AUTH_APP_BIND_INSTALL=0`, or `CODEX_MULTI_AUTH_APP_LAUNCHER_INSTALL=0` to opt out of the matching default behavior.
320
323
 
324
+ Advanced local proxy chains can set `CODEX_MULTI_AUTH_RUNTIME_PROXY_UPSTREAM_BASE_URL` for one wrapper process. The wrapper passes that URL to both the shadow-runtime and interactive-helper rotation paths and fails closed if the configured upstream is invalid or unavailable; it never falls back silently to the direct backend while an explicit upstream is required. Because the request that reaches the upstream carries the managed OAuth bearer token, the host must be a numeric loopback literal: a name such as `localhost` is rejected, since a hosts-file entry can point it at a routable address. "Fails closed" also covers the case where runtime rotation itself is off (`CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0`, `CODEX_MULTI_AUTH_BYPASS=1`, or the setting disabled): a request-bearing invocation exits non-zero rather than bypassing the configured upstream. Subcommands that make no backend requests still run normally.
325
+
326
+ When the backend answers that the selected model is at capacity, the runtime proxy waits and re-sends the request instead of burning the pool. Capacity is a property of the model, not of an account, so rotating spends the transient budget against accounts that all fail identically and the request ends as a 503 within seconds. The wait backs off (2s, 5s, 15s, 30s, then 60s), honors an upstream `retry-after` when one is sent, and stops at a wall-clock deadline set by `CODEX_MULTI_AUTH_MODEL_CAPACITY_RETRY_MS` (10 minutes by default, 1 hour maximum). Set that variable to `0` to restore the previous rotate-and-fail behavior. The responding account is left completely unpenalized: its pool token is refunded and it is never marked rate limited or cooled down, so selection runs normally on the next pass and may pick any healthy account. The wait is abandoned if the client disconnects, so no further upstream request is sent for a response nobody is reading. See [#689](https://github.com/ndycode/codex-multi-auth/issues/689).
327
+
328
+ Trust boundary: the loopback check bounds exposure to the local machine, and nothing more. It does not authenticate the process listening on that port, and plaintext HTTP is what a local inspection proxy needs, so any process that can bind the port you name receives the managed bearer token in cleartext. Set this variable only on a machine where you trust every local process that can bind a loopback port, and only for as long as you need the chain.
329
+
321
330
  Installed wrappers may perform a best-effort daily npm version check during normal forwarded Codex startup. When a newer package is detected, the wrapper only prints a manual notice on an interactive TTY or when `CODEX_MULTI_AUTH_DEBUG=1`: `npm install -g codex-multi-auth@latest`. It never runs npm install or update commands for you.
322
331
 
323
332
  ---
@@ -406,7 +415,7 @@ codex-multi-auth doctor --json
406
415
 
407
416
  ## Release Notes
408
417
 
409
- - Current stable: [docs/releases/v2.12.0.md](docs/releases/v2.12.0.md) — install via `npm i -g codex-multi-auth`
418
+ - Current stable: [docs/releases/v2.14.0.md](docs/releases/v2.14.0.md) — install via `npm i -g codex-multi-auth`
410
419
  - Previous stable: [docs/releases/v2.8.3.md](docs/releases/v2.8.3.md)
411
420
  - Previous stable: [docs/releases/v2.8.2.md](docs/releases/v2.8.2.md)
412
421
  - Previous stable: [docs/releases/v2.7.1.md](docs/releases/v2.7.1.md)
@@ -16,6 +16,26 @@ type AccountIdentityCandidate = Pick<ManagedAccount, "accountId" | "email" | "re
16
16
  export type { Workspace } from "./storage/public-types.js";
17
17
  /** Stable operator-facing marker for an explicitly invalidated OAuth token. */
18
18
  export declare const AUTH_INVALIDATION_MARKER = "token-invalid \u2014 re-login needed";
19
+ /**
20
+ * How long a 429 recorded while the selection metadata was unreadable stays
21
+ * eligible to be replayed over a `switch` that clears the account's markers.
22
+ *
23
+ * The window only has to cover the gap between the CLI's atomic storage write
24
+ * and this process observing it, which is a single filesystem read away and in
25
+ * practice sub-second. 30s is generous for a stalled Windows volume while still
26
+ * guaranteeing that a 429 from minutes or hours earlier can never be
27
+ * resurrected by a later, unrelated switch.
28
+ */
29
+ export declare const UNSEQUENCED_RATE_LIMIT_TTL_MS = 30000;
30
+ /**
31
+ * How many times a debounced save re-arms itself after a failure before giving
32
+ * up. A save can fail because the selection metadata was momentarily
33
+ * unreadable, and dropping it loses every rate-limit window, cooldown and
34
+ * rotated refresh token accumulated since the last successful save.
35
+ */
36
+ export declare const MAX_DEBOUNCED_SAVE_RETRIES = 5;
37
+ /** Ceiling for the debounced-save retry backoff. */
38
+ export declare const MAX_SAVE_RETRY_DELAY_MS = 8000;
19
39
  export interface ManagedAccount {
20
40
  index: number;
21
41
  recordId?: string;
@@ -50,6 +70,8 @@ export declare class AccountManager {
50
70
  private lastToastTime;
51
71
  private saveDebounceTimer;
52
72
  private pendingSave;
73
+ /** Consecutive debounced-save failures; reset by the next success. */
74
+ private saveRetryCount;
53
75
  private readonly storagePathState;
54
76
  /**
55
77
  * Manual pin set by the `switch` CLI command, hydrated from disk at
@@ -65,6 +87,7 @@ export declare class AccountManager {
65
87
  * as `pinnedAccountIndex`. See #474.
66
88
  */
67
89
  private affinityGeneration;
90
+ private readonly unsequencedRateLimits;
68
91
  /**
69
92
  * PR-N / R4: feature-flagged routing mutex mode.
70
93
  * Defaults to `"legacy"` to preserve pre-PR-N behaviour for one release
@@ -92,6 +115,21 @@ export declare class AccountManager {
92
115
  */
93
116
  getManagedAccountRuntimeSkipReason(account: ManagedAccount, family: ModelFamily, model?: string | null): string | null;
94
117
  static resetVolatileRuntimeState(): void;
118
+ /**
119
+ * Apply each explicit selection once without erasing a subsequent 429.
120
+ *
121
+ * A `switch` asks for a fresh upstream attempt, so the selected account's
122
+ * rate-limit markers are cleared. The only markers that survive that clear
123
+ * are ones recorded while the selection metadata was unreadable AND recent
124
+ * enough to have raced this switch (see UNSEQUENCED_RATE_LIMIT_TTL_MS); an
125
+ * older unsequenced entry provably predates the switch and is discarded.
126
+ *
127
+ * @param meta Latest successfully read selection generation and pin.
128
+ */
129
+ applyManualSelection(meta: {
130
+ pinnedAccountIndex?: number | null;
131
+ affinityGeneration: number;
132
+ }): void;
95
133
  /**
96
134
  * Wipe per-account transient state — active cooldowns and all rate-limit
97
135
  * reset windows — across every managed account, then schedule a debounced
@@ -213,6 +251,14 @@ export declare class AccountManager {
213
251
  setActiveIndexLocked(index: number): Promise<ManagedAccount | null>;
214
252
  markRateLimited(account: ManagedAccount, retryAfterMs: number, family: ModelFamily, model?: string | null): void;
215
253
  markRateLimitedWithReason(account: ManagedAccount, retryAfterMs: number, family: ModelFamily, reason: RateLimitReason, model?: string | null): void;
254
+ /**
255
+ * Storage file this manager owns, resolved through the path state captured
256
+ * at construction. Reading the ambient `getStoragePath()` instead would
257
+ * point a project-scoped pool at whichever storage file happens to be
258
+ * current on the calling async context. See `saveToDisk`, which wraps
259
+ * `runWithStoragePathState(this.storagePathState, ...)` for the same reason.
260
+ */
261
+ private resolveSelectionStoragePath;
216
262
  markAccountCoolingDown(account: ManagedAccount, cooldownMs: number, reason: CooldownReason): void;
217
263
  isAccountCoolingDown(account: ManagedAccount): boolean;
218
264
  clearAccountCooldown(account: ManagedAccount): void;
@@ -247,6 +293,29 @@ export declare class AccountManager {
247
293
  * never undoes a refresh we just performed.
248
294
  */
249
295
  private reconcileTokensFromDisk;
296
+ /**
297
+ * Re-read the on-disk selection and fold it into this manager's state.
298
+ *
299
+ * Race protection: a CLI `switch`/`unpin`/`best` may have written a NEW
300
+ * pin/gen between proxy startup (or the last save) and now. If we persisted
301
+ * our stale instance values, we'd silently clobber the CLI update on every
302
+ * routine save (rate-limit, cooldown, near-quota refund, etc.). See #474.
303
+ *
304
+ * This MUTATES `pinnedAccountIndex`, `affinityGeneration` and, when the
305
+ * generation advanced, the selected account's rate-limit markers, so it is a
306
+ * separate step from the pure `buildStorageSnapshot` serializer below rather
307
+ * than a hidden side effect of it. Callers must run it immediately before a
308
+ * snapshot they intend to persist. Applying it twice is a no-op.
309
+ *
310
+ * @throws when the metadata exists but cannot be observed (see
311
+ * `readPinAndGenFromDisk`), which is the one case where persisting would
312
+ * risk overwriting a newer pin.
313
+ */
314
+ private reconcileSelectionFromDisk;
315
+ /**
316
+ * Serialize the live pool. Pure: it reads no files and mutates no state.
317
+ * Persisting callers must call `reconcileSelectionFromDisk()` first.
318
+ */
250
319
  private buildStorageSnapshot;
251
320
  commitRefreshedAuth(source: Pick<ManagedAccount, "index" | "accountId" | "email" | "refreshToken">, auth: OAuthAuthDetails): Promise<ManagedAccount | null>;
252
321
  toAuthDetails(account: ManagedAccount): Auth;
@@ -263,6 +332,12 @@ export declare class AccountManager {
263
332
  setAccountEnabled(index: number, enabled: boolean): ManagedAccount | null;
264
333
  saveToDisk(): Promise<void>;
265
334
  saveToDiskDebounced(delayMs?: number): void;
335
+ /**
336
+ * Flush any debounced save. Never rejects: this runs on the proxy shutdown
337
+ * path (`RuntimeRotationProxy.close`), and a rejection there aborts the rest
338
+ * of the teardown. A failure is logged at error level instead, because the
339
+ * process is exiting and there is no later attempt to fall back to.
340
+ */
266
341
  flushPendingSave(): Promise<void>;
267
342
  private resetWorkspaces;
268
343
  getCurrentWorkspace(account: ManagedAccount): Workspace | null;
@@ -1 +1 @@
1
- {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../lib/accounts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../lib/accounts.ts"],"names":[],"mappings":"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"}
@@ -126,6 +126,26 @@ function isRetryableAuthPersistenceError(error) {
126
126
  }
127
127
  /** Stable operator-facing marker for an explicitly invalidated OAuth token. */
128
128
  export const AUTH_INVALIDATION_MARKER = "token-invalid — re-login needed";
129
+ /**
130
+ * How long a 429 recorded while the selection metadata was unreadable stays
131
+ * eligible to be replayed over a `switch` that clears the account's markers.
132
+ *
133
+ * The window only has to cover the gap between the CLI's atomic storage write
134
+ * and this process observing it, which is a single filesystem read away and in
135
+ * practice sub-second. 30s is generous for a stalled Windows volume while still
136
+ * guaranteeing that a 429 from minutes or hours earlier can never be
137
+ * resurrected by a later, unrelated switch.
138
+ */
139
+ export const UNSEQUENCED_RATE_LIMIT_TTL_MS = 30_000;
140
+ /**
141
+ * How many times a debounced save re-arms itself after a failure before giving
142
+ * up. A save can fail because the selection metadata was momentarily
143
+ * unreadable, and dropping it loses every rate-limit window, cooldown and
144
+ * rotated refresh token accumulated since the last successful save.
145
+ */
146
+ export const MAX_DEBOUNCED_SAVE_RETRIES = 5;
147
+ /** Ceiling for the debounced-save retry backoff. */
148
+ export const MAX_SAVE_RETRY_DELAY_MS = 8_000;
129
149
  export class AccountManager {
130
150
  accounts = [];
131
151
  cursorByFamily = initFamilyState(0);
@@ -134,6 +154,8 @@ export class AccountManager {
134
154
  lastToastTime = 0;
135
155
  saveDebounceTimer = null;
136
156
  pendingSave = null;
157
+ /** Consecutive debounced-save failures; reset by the next success. */
158
+ saveRetryCount = 0;
137
159
  storagePathState;
138
160
  /**
139
161
  * Manual pin set by the `switch` CLI command, hydrated from disk at
@@ -149,6 +171,17 @@ export class AccountManager {
149
171
  * as `pinnedAccountIndex`. See #474.
150
172
  */
151
173
  affinityGeneration;
174
+ // A 429 observed while the selection metadata was unreadable must survive
175
+ // the next reconciliation, because we cannot tell whether it landed before
176
+ // or after the `switch` that reconciliation is about to apply. Keep only
177
+ // those new markers, not the stale account map.
178
+ //
179
+ // `recordedAtMs` bounds that ambiguity. Only a 429 recorded within
180
+ // UNSEQUENCED_RATE_LIMIT_TTL_MS of the reconciliation could have raced the
181
+ // switch we are applying; an older entry provably predates it and must NOT
182
+ // be replayed, or an arbitrarily stale 429 would be resurrected by the very
183
+ // command meant to revalidate the account.
184
+ unsequencedRateLimits = new WeakMap();
152
185
  /**
153
186
  * PR-N / R4: feature-flagged routing mutex mode.
154
187
  * Defaults to `"legacy"` to preserve pre-PR-N behaviour for one release
@@ -248,7 +281,8 @@ export class AccountManager {
248
281
  this.affinityGeneration =
249
282
  typeof rawStoredGen === "number" &&
250
283
  Number.isFinite(rawStoredGen) &&
251
- Number.isInteger(rawStoredGen) &&
284
+ // See readAffinityGenerationFromDisk: an unsafe integer wedges the bump.
285
+ Number.isSafeInteger(rawStoredGen) &&
252
286
  rawStoredGen >= 0
253
287
  ? rawStoredGen
254
288
  : 0;
@@ -492,6 +526,38 @@ export class AccountManager {
492
526
  resetTrackers();
493
527
  resetAllCircuitBreakers();
494
528
  }
529
+ /**
530
+ * Apply each explicit selection once without erasing a subsequent 429.
531
+ *
532
+ * A `switch` asks for a fresh upstream attempt, so the selected account's
533
+ * rate-limit markers are cleared. The only markers that survive that clear
534
+ * are ones recorded while the selection metadata was unreadable AND recent
535
+ * enough to have raced this switch (see UNSEQUENCED_RATE_LIMIT_TTL_MS); an
536
+ * older unsequenced entry provably predates the switch and is discarded.
537
+ *
538
+ * @param meta Latest successfully read selection generation and pin.
539
+ */
540
+ applyManualSelection(meta) {
541
+ if (meta.affinityGeneration <= this.affinityGeneration)
542
+ return;
543
+ const index = meta.pinnedAccountIndex;
544
+ const account = typeof index === "number"
545
+ ? this.getAccountByIndex(index)
546
+ : null;
547
+ if (account) {
548
+ clearAllRateLimits(account);
549
+ const pending = this.unsequencedRateLimits.get(account);
550
+ const replayable = pending !== undefined &&
551
+ nowMs() - pending.recordedAtMs <= UNSEQUENCED_RATE_LIMIT_TTL_MS
552
+ ? pending
553
+ : undefined;
554
+ Object.assign(account.rateLimitResetTimes, replayable?.limits);
555
+ account.lastRateLimitReason = replayable?.reason;
556
+ this.unsequencedRateLimits.delete(account);
557
+ }
558
+ this.pinnedAccountIndex = account ? index ?? undefined : undefined;
559
+ this.affinityGeneration = meta.affinityGeneration;
560
+ }
495
561
  /**
496
562
  * Wipe per-account transient state — active cooldowns and all rate-limit
497
563
  * reset windows — across every managed account, then schedule a debounced
@@ -908,22 +974,74 @@ export class AccountManager {
908
974
  this.markRateLimitedWithReason(account, retryAfterMs, family, "unknown", model);
909
975
  }
910
976
  markRateLimitedWithReason(account, retryAfterMs, family, reason, model) {
977
+ let selectionReadable = false;
978
+ try {
979
+ // Deliberately a fresh strict read rather than the proxy's cached
980
+ // `readStorageMetaFromDisk`: that reader falls back to its last good
981
+ // snapshot on failure, so it cannot tell this call site the one thing
982
+ // it needs to know, namely whether the selection was observable at all.
983
+ const meta = readPinAndGenFromDisk(this.resolveSelectionStoragePath(), {
984
+ strict: true,
985
+ });
986
+ // Observe a switch BEFORE recording this response, not at the later
987
+ // debounced save where it would erase a genuine post-switch 429.
988
+ this.applyManualSelection(meta);
989
+ selectionReadable = true;
990
+ }
991
+ catch {
992
+ // Fail closed: retain this new limit if the selection cannot be read.
993
+ log.warn("Rate limit recorded while account selection metadata is unavailable");
994
+ }
911
995
  // Clamp to MAX_RATE_LIMIT_DELAY_MS so a bogus upstream retry-after value
912
996
  // cannot wedge this account unavailable for years (see stress audit H1).
913
997
  const retryMs = Math.min(Math.max(0, Math.floor(retryAfterMs)), MAX_RATE_LIMIT_DELAY_MS);
914
- const resetAt = nowMs() + retryMs;
998
+ const observedAtMs = nowMs();
999
+ const resetAt = observedAtMs + retryMs;
1000
+ // Only carry forward an unsequenced entry that is still replayable.
1001
+ // Merging an expired one would give it a fresh `recordedAtMs` below and
1002
+ // keep resurrecting it indefinitely.
1003
+ const pending = this.unsequencedRateLimits.get(account);
1004
+ const carried = pending !== undefined &&
1005
+ observedAtMs - pending.recordedAtMs <= UNSEQUENCED_RATE_LIMIT_TTL_MS
1006
+ ? pending
1007
+ : undefined;
1008
+ const newLimits = { ...carried?.limits };
915
1009
  const baseKey = getQuotaKey(family);
916
1010
  if (!model || reason === "quota" || reason === "unknown") {
917
1011
  const currentResetAt = account.rateLimitResetTimes[baseKey] ?? 0;
918
1012
  account.rateLimitResetTimes[baseKey] = Math.max(currentResetAt, resetAt);
1013
+ newLimits[baseKey] = Math.max(newLimits[baseKey] ?? 0, resetAt);
919
1014
  }
920
1015
  if (model &&
921
1016
  (reason === "tokens" || reason === "concurrent" || reason === "unknown")) {
922
1017
  const modelKey = getQuotaKey(family, model);
923
1018
  const currentResetAt = account.rateLimitResetTimes[modelKey] ?? 0;
924
1019
  account.rateLimitResetTimes[modelKey] = Math.max(currentResetAt, resetAt);
1020
+ newLimits[modelKey] = Math.max(newLimits[modelKey] ?? 0, resetAt);
925
1021
  }
926
1022
  account.lastRateLimitReason = reason;
1023
+ if (!selectionReadable) {
1024
+ this.unsequencedRateLimits.set(account, {
1025
+ limits: newLimits,
1026
+ reason,
1027
+ recordedAtMs: observedAtMs,
1028
+ });
1029
+ }
1030
+ else {
1031
+ // The selection was observable, so this 429 is unambiguously ordered
1032
+ // against the current generation and needs no replay backup.
1033
+ this.unsequencedRateLimits.delete(account);
1034
+ }
1035
+ }
1036
+ /**
1037
+ * Storage file this manager owns, resolved through the path state captured
1038
+ * at construction. Reading the ambient `getStoragePath()` instead would
1039
+ * point a project-scoped pool at whichever storage file happens to be
1040
+ * current on the calling async context. See `saveToDisk`, which wraps
1041
+ * `runWithStoragePathState(this.storagePathState, ...)` for the same reason.
1042
+ */
1043
+ resolveSelectionStoragePath() {
1044
+ return this.storagePathState.currentStoragePath ?? getStoragePath();
927
1045
  }
928
1046
  markAccountCoolingDown(account, cooldownMs, reason) {
929
1047
  const ms = Math.max(0, Math.floor(cooldownMs));
@@ -1076,6 +1194,54 @@ export class AccountManager {
1076
1194
  }
1077
1195
  return snapshot;
1078
1196
  }
1197
+ /**
1198
+ * Re-read the on-disk selection and fold it into this manager's state.
1199
+ *
1200
+ * Race protection: a CLI `switch`/`unpin`/`best` may have written a NEW
1201
+ * pin/gen between proxy startup (or the last save) and now. If we persisted
1202
+ * our stale instance values, we'd silently clobber the CLI update on every
1203
+ * routine save (rate-limit, cooldown, near-quota refund, etc.). See #474.
1204
+ *
1205
+ * This MUTATES `pinnedAccountIndex`, `affinityGeneration` and, when the
1206
+ * generation advanced, the selected account's rate-limit markers, so it is a
1207
+ * separate step from the pure `buildStorageSnapshot` serializer below rather
1208
+ * than a hidden side effect of it. Callers must run it immediately before a
1209
+ * snapshot they intend to persist. Applying it twice is a no-op.
1210
+ *
1211
+ * @throws when the metadata exists but cannot be observed (see
1212
+ * `readPinAndGenFromDisk`), which is the one case where persisting would
1213
+ * risk overwriting a newer pin.
1214
+ */
1215
+ reconcileSelectionFromDisk() {
1216
+ const onDisk = readPinAndGenFromDisk(this.resolveSelectionStoragePath(), {
1217
+ strict: true,
1218
+ });
1219
+ // A delayed save must not resurrect the markers the CLI just cleared.
1220
+ this.applyManualSelection(onDisk);
1221
+ let effectivePinnedAccountIndex = this.pinnedAccountIndex;
1222
+ let effectiveAffinityGeneration = this.affinityGeneration;
1223
+ if (onDisk.affinityGeneration > effectiveAffinityGeneration) {
1224
+ effectiveAffinityGeneration = onDisk.affinityGeneration;
1225
+ // The pin is part of the same atomic write the CLI performs when it
1226
+ // bumps the generation, so a strictly-greater on-disk gen is the
1227
+ // signal that the disk pin is the authoritative one.
1228
+ effectivePinnedAccountIndex = onDisk.pinnedAccountIndex;
1229
+ }
1230
+ // Validate the refreshed pin against the live account count.
1231
+ if (effectivePinnedAccountIndex !== undefined &&
1232
+ (effectivePinnedAccountIndex < 0 ||
1233
+ effectivePinnedAccountIndex >= this.accounts.length)) {
1234
+ effectivePinnedAccountIndex = undefined;
1235
+ }
1236
+ // Cache the refreshed values so subsequent saves start from the freshest
1237
+ // known state without re-reading every time.
1238
+ this.pinnedAccountIndex = effectivePinnedAccountIndex;
1239
+ this.affinityGeneration = effectiveAffinityGeneration;
1240
+ }
1241
+ /**
1242
+ * Serialize the live pool. Pure: it reads no files and mutates no state.
1243
+ * Persisting callers must call `reconcileSelectionFromDisk()` first.
1244
+ */
1079
1245
  buildStorageSnapshot() {
1080
1246
  const activeIndexByFamily = {};
1081
1247
  for (const family of MODEL_FAMILIES) {
@@ -1083,38 +1249,8 @@ export class AccountManager {
1083
1249
  activeIndexByFamily[family] = clampNonNegativeInt(raw, 0);
1084
1250
  }
1085
1251
  const activeIndex = clampNonNegativeInt(activeIndexByFamily.codex, 0);
1086
- // Race protection: a CLI `switch`/`unpin`/`best` may have written a NEW
1087
- // pin/gen between proxy startup (or the last save) and now. If we
1088
- // persisted our stale instance values, we'd silently clobber the CLI
1089
- // update on every routine save (rate-limit, cooldown, near-quota refund,
1090
- // etc.). Re-read just before snapshotting and prefer the fresher value.
1091
- // See #474.
1092
- let effectivePinnedAccountIndex = this.pinnedAccountIndex;
1093
- let effectiveAffinityGeneration = this.affinityGeneration;
1094
- try {
1095
- const onDisk = readPinAndGenFromDisk(getStoragePath());
1096
- if (onDisk.affinityGeneration > effectiveAffinityGeneration) {
1097
- effectiveAffinityGeneration = onDisk.affinityGeneration;
1098
- // The pin is part of the same atomic write the CLI performs when
1099
- // it bumps the generation, so a strictly-greater on-disk gen is
1100
- // the signal that the disk pin is the authoritative one.
1101
- effectivePinnedAccountIndex = onDisk.pinnedAccountIndex;
1102
- }
1103
- // Validate the refreshed pin against the live account count.
1104
- if (effectivePinnedAccountIndex !== undefined &&
1105
- (effectivePinnedAccountIndex < 0 ||
1106
- effectivePinnedAccountIndex >= this.accounts.length)) {
1107
- effectivePinnedAccountIndex = undefined;
1108
- }
1109
- // Cache the refreshed values so subsequent saves start from the
1110
- // freshest known state without re-reading every time.
1111
- this.pinnedAccountIndex = effectivePinnedAccountIndex;
1112
- this.affinityGeneration = effectiveAffinityGeneration;
1113
- }
1114
- catch {
1115
- // Disk read failures fall back to in-memory values; better than
1116
- // dropping the snapshot save entirely.
1117
- }
1252
+ const effectivePinnedAccountIndex = this.pinnedAccountIndex;
1253
+ const effectiveAffinityGeneration = this.affinityGeneration;
1118
1254
  const snapshot = {
1119
1255
  version: 3,
1120
1256
  accounts: this.accounts.map((account) => {
@@ -1164,7 +1300,11 @@ export class AccountManager {
1164
1300
  try {
1165
1301
  return await withAccountStorageTransaction(async (_current, persist) => {
1166
1302
  // Snapshot the live in-memory pool under the storage lock so refresh
1167
- // persistence merges against the latest account state.
1303
+ // persistence merges against the latest account state. Reconcile the
1304
+ // selection first for the same reason `saveToDisk` does: this write
1305
+ // carries `pinnedAccountIndex`/`affinityGeneration` too, so a stale
1306
+ // pair here would clobber a `switch` that landed since the last save.
1307
+ this.reconcileSelectionFromDisk();
1168
1308
  const nextStorage = structuredClone(this.buildStorageSnapshot());
1169
1309
  const storageIndex = findAccountIndexByIdentity(nextStorage.accounts, source, auth);
1170
1310
  if (storageIndex === undefined) {
@@ -1536,7 +1676,8 @@ export class AccountManager {
1536
1676
  await withAccountStorageTransaction(async (current, persist) => {
1537
1677
  // Reconcile against the disk state loaded under the storage lock so a
1538
1678
  // routine save does not clobber a token another process just rotated
1539
- // (stress audit H3).
1679
+ // (stress audit H3) or a pin the CLI just wrote (#474).
1680
+ this.reconcileSelectionFromDisk();
1540
1681
  await persist(this.reconcileTokensFromDisk(this.buildStorageSnapshot(), current));
1541
1682
  });
1542
1683
  });
@@ -1556,24 +1697,54 @@ export class AccountManager {
1556
1697
  this.pendingSave = null;
1557
1698
  });
1558
1699
  await this.pendingSave;
1700
+ this.saveRetryCount = 0;
1559
1701
  }
1560
1702
  catch (error) {
1561
1703
  log.warn("Debounced save failed", {
1562
1704
  error: error instanceof Error ? error.message : String(error),
1705
+ attempt: this.saveRetryCount + 1,
1563
1706
  });
1707
+ // The debounce timer has already fired and cleared itself, so
1708
+ // without re-arming this save is simply lost, and with it every
1709
+ // rate-limit window, cooldown and rotated refresh token recorded
1710
+ // since the last successful write. Saves fail for transient
1711
+ // reasons (a Windows AV scanner or indexer holding accounts.json,
1712
+ // a torn read of a concurrent atomic rename), so back off and try
1713
+ // again instead of dropping the state.
1714
+ if (this.saveRetryCount < MAX_DEBOUNCED_SAVE_RETRIES) {
1715
+ this.saveRetryCount += 1;
1716
+ this.saveToDiskDebounced(Math.min(delayMs * 2, MAX_SAVE_RETRY_DELAY_MS));
1717
+ }
1718
+ else {
1719
+ this.saveRetryCount = 0;
1720
+ log.error("Dropping account state save after repeated failures; runtime state since the last successful save is lost");
1721
+ }
1564
1722
  }
1565
1723
  };
1566
1724
  void doSave();
1567
1725
  }, delayMs);
1568
1726
  }
1727
+ /**
1728
+ * Flush any debounced save. Never rejects: this runs on the proxy shutdown
1729
+ * path (`RuntimeRotationProxy.close`), and a rejection there aborts the rest
1730
+ * of the teardown. A failure is logged at error level instead, because the
1731
+ * process is exiting and there is no later attempt to fall back to.
1732
+ */
1569
1733
  async flushPendingSave() {
1570
- if (this.saveDebounceTimer) {
1571
- clearTimeout(this.saveDebounceTimer);
1572
- this.saveDebounceTimer = null;
1573
- await this.saveToDisk();
1734
+ try {
1735
+ if (this.saveDebounceTimer) {
1736
+ clearTimeout(this.saveDebounceTimer);
1737
+ this.saveDebounceTimer = null;
1738
+ await this.saveToDisk();
1739
+ }
1740
+ if (this.pendingSave) {
1741
+ await this.pendingSave;
1742
+ }
1574
1743
  }
1575
- if (this.pendingSave) {
1576
- await this.pendingSave;
1744
+ catch (error) {
1745
+ log.error("Failed to flush pending account state save", {
1746
+ error: error instanceof Error ? error.message : String(error),
1747
+ });
1577
1748
  }
1578
1749
  }
1579
1750
  // Workspace management methods
@@ -1 +1 @@
1
- {"version":3,"file":"account-manager-commands.d.ts","sourceRoot":"","sources":["../../../lib/codex-manager/account-manager-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,aA8BnC,CAAC"}
1
+ {"version":3,"file":"account-manager-commands.d.ts","sourceRoot":"","sources":["../../../lib/codex-manager/account-manager-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,aA+BnC,CAAC"}
@@ -14,6 +14,7 @@ export const ACCOUNT_MANAGER_COMMANDS = new Set([
14
14
  "login",
15
15
  "list",
16
16
  "status",
17
+ "limits",
17
18
  "switch",
18
19
  "unpin",
19
20
  "workspace",
@@ -0,0 +1,21 @@
1
+ import { type ModelFamily } from "../../prompts/codex.js";
2
+ import type { QuotaCacheData } from "../../quota-cache.js";
3
+ import type { AccountStorageV3 } from "../../storage.js";
4
+ export interface LimitsCommandDeps {
5
+ setStoragePath: (path: string | null) => void;
6
+ loadAccounts: () => Promise<AccountStorageV3 | null>;
7
+ loadQuotaCache: () => Promise<QuotaCacheData>;
8
+ refreshQuotaCache: (storage: AccountStorageV3, cache: QuotaCacheData, maxAgeMs: number) => Promise<QuotaCacheData>;
9
+ resolveActiveIndex: (storage: AccountStorageV3, family?: ModelFamily) => number;
10
+ getNow?: () => number;
11
+ logInfo?: (message: string) => void;
12
+ logError?: (message: string) => void;
13
+ }
14
+ /**
15
+ * Emit configured accounts joined to safe cached quota records.
16
+ *
17
+ * Cached mode performs no provider requests. Refresh mode delegates to the
18
+ * existing sequential, age-gated refresh path before serializing the snapshot.
19
+ */
20
+ export declare function runLimitsCommand(args: string[], deps: LimitsCommandDeps): Promise<number>;
21
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../../../../lib/codex-manager/commands/limits.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAE5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAMzD,MAAM,WAAW,iBAAiB;IACjC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACrD,cAAc,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC9C,iBAAiB,EAAE,CAClB,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,KACZ,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,kBAAkB,EAAE,CACnB,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,WAAW,KAChB,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAsDD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE,iBAAiB,GACrB,OAAO,CAAC,MAAM,CAAC,CAoFjB"}