codex-multi-auth 1.2.7 → 1.3.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 (115) hide show
  1. package/README.md +5 -3
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +41 -21
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/accounts.d.ts +47 -0
  6. package/dist/lib/accounts.d.ts.map +1 -1
  7. package/dist/lib/accounts.js +219 -33
  8. package/dist/lib/accounts.js.map +1 -1
  9. package/dist/lib/auth/auth.d.ts +16 -0
  10. package/dist/lib/auth/auth.d.ts.map +1 -1
  11. package/dist/lib/auth/auth.js +52 -6
  12. package/dist/lib/auth/auth.js.map +1 -1
  13. package/dist/lib/auth/server.d.ts +1 -1
  14. package/dist/lib/auth/server.d.ts.map +1 -1
  15. package/dist/lib/auth/server.js +10 -8
  16. package/dist/lib/auth/server.js.map +1 -1
  17. package/dist/lib/codex-manager/commands/status.d.ts.map +1 -1
  18. package/dist/lib/codex-manager/commands/status.js +13 -5
  19. package/dist/lib/codex-manager/commands/status.js.map +1 -1
  20. package/dist/lib/codex-manager/commands/verify.d.ts +59 -0
  21. package/dist/lib/codex-manager/commands/verify.d.ts.map +1 -0
  22. package/dist/lib/codex-manager/commands/verify.js +332 -0
  23. package/dist/lib/codex-manager/commands/verify.js.map +1 -0
  24. package/dist/lib/codex-manager/commands/why-selected.d.ts +57 -0
  25. package/dist/lib/codex-manager/commands/why-selected.d.ts.map +1 -0
  26. package/dist/lib/codex-manager/commands/why-selected.js +198 -0
  27. package/dist/lib/codex-manager/commands/why-selected.js.map +1 -0
  28. package/dist/lib/codex-manager/help.d.ts.map +1 -1
  29. package/dist/lib/codex-manager/help.js +4 -0
  30. package/dist/lib/codex-manager/help.js.map +1 -1
  31. package/dist/lib/codex-manager/settings-hub/backend.d.ts +9 -0
  32. package/dist/lib/codex-manager/settings-hub/backend.d.ts.map +1 -0
  33. package/dist/lib/codex-manager/settings-hub/backend.js +79 -0
  34. package/dist/lib/codex-manager/settings-hub/backend.js.map +1 -0
  35. package/dist/lib/codex-manager/settings-hub/dashboard.d.ts +24 -0
  36. package/dist/lib/codex-manager/settings-hub/dashboard.d.ts.map +1 -0
  37. package/dist/lib/codex-manager/settings-hub/dashboard.js +223 -0
  38. package/dist/lib/codex-manager/settings-hub/dashboard.js.map +1 -0
  39. package/dist/lib/codex-manager/settings-hub/experimental.d.ts +18 -0
  40. package/dist/lib/codex-manager/settings-hub/experimental.d.ts.map +1 -0
  41. package/dist/lib/codex-manager/settings-hub/experimental.js +78 -0
  42. package/dist/lib/codex-manager/settings-hub/experimental.js.map +1 -0
  43. package/dist/lib/codex-manager/settings-hub/index.d.ts +34 -0
  44. package/dist/lib/codex-manager/settings-hub/index.d.ts.map +1 -0
  45. package/dist/lib/codex-manager/settings-hub/index.js +81 -0
  46. package/dist/lib/codex-manager/settings-hub/index.js.map +1 -0
  47. package/dist/lib/codex-manager/settings-hub/shared.d.ts +40 -0
  48. package/dist/lib/codex-manager/settings-hub/shared.d.ts.map +1 -0
  49. package/dist/lib/codex-manager/settings-hub/shared.js +103 -0
  50. package/dist/lib/codex-manager/settings-hub/shared.js.map +1 -0
  51. package/dist/lib/codex-manager/settings-hub.d.ts +1 -64
  52. package/dist/lib/codex-manager/settings-hub.d.ts.map +1 -1
  53. package/dist/lib/codex-manager/settings-hub.js +4 -515
  54. package/dist/lib/codex-manager/settings-hub.js.map +1 -1
  55. package/dist/lib/codex-manager.d.ts.map +1 -1
  56. package/dist/lib/codex-manager.js +95 -13
  57. package/dist/lib/codex-manager.js.map +1 -1
  58. package/dist/lib/config.d.ts +14 -0
  59. package/dist/lib/config.d.ts.map +1 -1
  60. package/dist/lib/config.js +21 -9
  61. package/dist/lib/config.js.map +1 -1
  62. package/dist/lib/health.d.ts.map +1 -1
  63. package/dist/lib/health.js.map +1 -1
  64. package/dist/lib/recovery/storage.d.ts.map +1 -1
  65. package/dist/lib/recovery/storage.js +112 -8
  66. package/dist/lib/recovery/storage.js.map +1 -1
  67. package/dist/lib/request/response-handler.d.ts.map +1 -1
  68. package/dist/lib/request/response-handler.js +67 -23
  69. package/dist/lib/request/response-handler.js.map +1 -1
  70. package/dist/lib/rotation.d.ts +53 -1
  71. package/dist/lib/rotation.d.ts.map +1 -1
  72. package/dist/lib/rotation.js +135 -23
  73. package/dist/lib/rotation.js.map +1 -1
  74. package/dist/lib/routing-mutex.d.ts +107 -0
  75. package/dist/lib/routing-mutex.d.ts.map +1 -0
  76. package/dist/lib/routing-mutex.js +104 -0
  77. package/dist/lib/routing-mutex.js.map +1 -0
  78. package/dist/lib/runtime/storage-scope.d.ts.map +1 -1
  79. package/dist/lib/runtime/storage-scope.js +17 -1
  80. package/dist/lib/runtime/storage-scope.js.map +1 -1
  81. package/dist/lib/schemas.d.ts +125 -0
  82. package/dist/lib/schemas.d.ts.map +1 -1
  83. package/dist/lib/schemas.js +139 -5
  84. package/dist/lib/schemas.js.map +1 -1
  85. package/dist/lib/storage/account-clear.d.ts.map +1 -1
  86. package/dist/lib/storage/account-clear.js +7 -1
  87. package/dist/lib/storage/account-clear.js.map +1 -1
  88. package/dist/lib/storage/flagged-storage-file.d.ts.map +1 -1
  89. package/dist/lib/storage/flagged-storage-file.js +17 -1
  90. package/dist/lib/storage/flagged-storage-file.js.map +1 -1
  91. package/dist/lib/storage/flagged-storage-io.d.ts.map +1 -1
  92. package/dist/lib/storage/flagged-storage-io.js +24 -10
  93. package/dist/lib/storage/flagged-storage-io.js.map +1 -1
  94. package/dist/lib/storage/import-export.d.ts.map +1 -1
  95. package/dist/lib/storage/import-export.js +16 -4
  96. package/dist/lib/storage/import-export.js.map +1 -1
  97. package/dist/lib/storage/paths.d.ts.map +1 -1
  98. package/dist/lib/storage/paths.js +62 -7
  99. package/dist/lib/storage/paths.js.map +1 -1
  100. package/dist/lib/storage/snapshot-inspectors.d.ts.map +1 -1
  101. package/dist/lib/storage/snapshot-inspectors.js +23 -16
  102. package/dist/lib/storage/snapshot-inspectors.js.map +1 -1
  103. package/dist/lib/storage/storage-parser.d.ts +17 -0
  104. package/dist/lib/storage/storage-parser.d.ts.map +1 -1
  105. package/dist/lib/storage/storage-parser.js +30 -1
  106. package/dist/lib/storage/storage-parser.js.map +1 -1
  107. package/dist/lib/storage.d.ts +1 -1
  108. package/dist/lib/storage.d.ts.map +1 -1
  109. package/dist/lib/storage.js +45 -26
  110. package/dist/lib/storage.js.map +1 -1
  111. package/dist/lib/ui/copy.d.ts +1 -1
  112. package/dist/lib/ui/copy.d.ts.map +1 -1
  113. package/dist/lib/ui/copy.js +2 -1
  114. package/dist/lib/ui/copy.js.map +1 -1
  115. package/package.json +5 -5
package/README.md CHANGED
@@ -157,6 +157,7 @@ If browser launch is blocked, use the alternate login paths in [docs/getting-sta
157
157
  | Command | What it answers |
158
158
  | --- | --- |
159
159
  | `codex auth verify-flagged` | Can any previously flagged account be restored? |
160
+ | `codex auth verify --paths` | Do my storage path chain and sandbox probes still pass self-test? |
160
161
  | `codex auth fix --dry-run` | What safe storage or account repairs are available? |
161
162
  | `codex auth doctor --fix` | Can the CLI diagnose and apply the safest fixes now? |
162
163
 
@@ -166,6 +167,7 @@ If browser launch is blocked, use the alternate login paths in [docs/getting-sta
166
167
  | --- | --- |
167
168
  | `codex auth report --live --json` | How do I get the full machine-readable health report? |
168
169
  | `codex auth fix --live --model gpt-5-codex` | How do I run live repair probes with a chosen model? |
170
+ | `codex auth why-selected --json` | Which account does the selector pick now, and why? |
169
171
 
170
172
  ### Reliability behavior
171
173
 
@@ -331,9 +333,9 @@ codex auth doctor --json
331
333
 
332
334
  ## Release Notes
333
335
 
334
- - Current stable: [docs/releases/v1.2.7.md](docs/releases/v1.2.7.md)
335
- - Previous stable: [docs/releases/v1.2.6.md](docs/releases/v1.2.6.md)
336
- - Earlier stable: [docs/releases/v1.2.5.md](docs/releases/v1.2.5.md)
336
+ - Current stable: [docs/releases/v1.3.0.md](docs/releases/v1.3.0.md)
337
+ - Previous stable: [docs/releases/v1.2.6.md](docs/releases/v1.2.6.md)
338
+ - Earlier stable: [docs/releases/v1.2.5.md](docs/releases/v1.2.5.md)
337
339
  - Full release archive: [docs/README.md#release-history](docs/README.md#release-history)
338
340
  - Archived prerelease: [docs/releases/v0.1.0-beta.0.md](docs/releases/v0.1.0-beta.0.md)
339
341
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,kBAAkB,CAAC;AAyR5D;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MA2/H/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,KAAoB,CAAC;AAElD,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,kBAAkB,CAAC;AAwR5D;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MA+hI/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,KAAoB,CAAC;AAElD,eAAe,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@
25
25
  import { tool } from "@codex-ai/plugin/tool";
26
26
  import { AccountManager, extractAccountEmail, extractAccountId, formatAccountLabel, formatCooldown, formatWaitTime, getAccountIdCandidates, isCodexCliSyncEnabled, lookupCodexCliTokensByEmail, parseRateLimitReason, resolveRequestAccountId, resolveRuntimeRequestIdentity, sanitizeEmail, selectBestAccountCandidate, shouldUpdateAccountIdFromToken, } from "./lib/accounts.js";
27
27
  import { createAuthorizationFlow, exchangeAuthorizationCode, parseAuthorizationInput, redactOAuthUrlForLog, REDIRECT_URI, } from "./lib/auth/auth.js";
28
- import { isBrowserLaunchSuppressed, openBrowserUrl } from "./lib/auth/browser.js";
28
+ import { isBrowserLaunchSuppressed, openBrowserUrl, } from "./lib/auth/browser.js";
29
29
  import { startLocalOAuthServer } from "./lib/auth/server.js";
30
30
  import { checkAndNotify } from "./lib/auto-update-checker.js";
31
31
  import { CapabilityPolicyStore } from "./lib/capability-policy.js";
@@ -74,7 +74,7 @@ import { buildLoginMenuAccounts } from "./lib/runtime/login-menu-accounts.js";
74
74
  import { ensureLiveAccountSyncEntry } from "./lib/runtime/live-sync-entry.js";
75
75
  import { applyLoaderRuntimeSetup } from "./lib/runtime/loader-setup.js";
76
76
  import { buildManualOAuthFlow } from "./lib/runtime/manual-oauth-flow.js";
77
- import { applyPreemptiveQuotaSettingsFromConfig, } from "./lib/runtime/quota-settings.js";
77
+ import { applyPreemptiveQuotaSettingsFromConfig } from "./lib/runtime/quota-settings.js";
78
78
  import { ensureLiveAccountSyncState, ensureRefreshGuardianState, ensureSessionAffinityState, } from "./lib/runtime/runtime-services.js";
79
79
  import { mutateRuntimeObservabilitySnapshot } from "./lib/runtime/runtime-observability.js";
80
80
  import { applyAccountStorageScopeFromConfig } from "./lib/runtime/storage-scope.js";
@@ -88,7 +88,7 @@ import { clearAccounts, clearFlaggedAccounts, exportAccounts, findMatchingAccoun
88
88
  import { buildTableHeader, buildTableRow, } from "./lib/table-formatter.js";
89
89
  import { createHashlineEditTool, createHashlineReadTool, } from "./lib/tools/hashline-tools.js";
90
90
  import { formatUiBadge, formatUiHeader, formatUiItem, formatUiKeyValue, formatUiSection, paintUiText, } from "./lib/ui/format.js";
91
- import { setUiRuntimeOptions, } from "./lib/ui/runtime.js";
91
+ import { setUiRuntimeOptions } from "./lib/ui/runtime.js";
92
92
  /**
93
93
  * OpenAI Codex OAuth authentication plugin for Codex CLI host runtime
94
94
  *
@@ -191,13 +191,9 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
191
191
  const burstRemaining = getServerBurstCooldownRemaining(now);
192
192
  snapshot.currentRequestId = requestId;
193
193
  snapshot.poolExhaustionCooldownUntil =
194
- poolRemaining > 0
195
- ? now + poolRemaining
196
- : null;
194
+ poolRemaining > 0 ? now + poolRemaining : null;
197
195
  snapshot.serverBurstCooldownUntil =
198
- burstRemaining > 0
199
- ? now + burstRemaining
200
- : null;
196
+ burstRemaining > 0 ? now + burstRemaining : null;
201
197
  snapshot.responsesRequests = runtimeMetrics.responsesRequests;
202
198
  snapshot.authRefreshRequests = runtimeMetrics.authRefreshRequests;
203
199
  snapshot.diagnosticProbeRequests = runtimeMetrics.diagnosticProbeRequests;
@@ -300,8 +296,7 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
300
296
  });
301
297
  refreshGuardian = next.refreshGuardian;
302
298
  refreshGuardianConfigKey = next.refreshGuardianConfigKey;
303
- refreshGuardianCleanupRegistered =
304
- next.refreshGuardianCleanupRegistered;
299
+ refreshGuardianCleanupRegistered = next.refreshGuardianCleanupRegistered;
305
300
  };
306
301
  const ensureSessionAffinity = (pluginConfig) => {
307
302
  const next = ensureSessionAffinityState({
@@ -593,7 +588,12 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
593
588
  error: {
594
589
  message: `The account pool is cooling down after recent rate-limit exhaustion. Try again in ${formatWaitTime(poolCooldownRemainingMs)} or inspect \`codex auth status\`.`,
595
590
  },
596
- }), { status: 429, headers: { "content-type": "application/json; charset=utf-8" } });
591
+ }), {
592
+ status: 429,
593
+ headers: {
594
+ "content-type": "application/json; charset=utf-8",
595
+ },
596
+ });
597
597
  }
598
598
  const serverBurstCooldownRemainingMs = getServerBurstCooldownRemaining();
599
599
  if (serverBurstCooldownRemainingMs > 0) {
@@ -605,7 +605,12 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
605
605
  error: {
606
606
  message: `Multiple accounts recently failed with upstream server errors. Try again in ${formatWaitTime(serverBurstCooldownRemainingMs)} or inspect \`codex auth report --json\`.`,
607
607
  },
608
- }), { status: 503, headers: { "content-type": "application/json; charset=utf-8" } });
608
+ }), {
609
+ status: 503,
610
+ headers: {
611
+ "content-type": "application/json; charset=utf-8",
612
+ },
613
+ });
609
614
  }
610
615
  const maxOutboundRequestAttempts = computeOutboundRequestAttemptBudget({
611
616
  accountCount: accountManager.getAccountCount(),
@@ -628,8 +633,7 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
628
633
  const tryConsumeOutboundRequestAttempt = (reason, accountIndex) => {
629
634
  if (outboundRequestAttemptsRemaining <= 0) {
630
635
  runtimeMetrics.requestAttemptBudgetExhaustions += 1;
631
- runtimeMetrics.lastError =
632
- `Request attempt budget exhausted after ${maxOutboundRequestAttempts} outbound request(s)`;
636
+ runtimeMetrics.lastError = `Request attempt budget exhausted after ${maxOutboundRequestAttempts} outbound request(s)`;
633
637
  logWarn("Request attempt budget exhausted.", {
634
638
  requestTraceId,
635
639
  reason,
@@ -730,7 +734,8 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
730
734
  if (retryableRefreshPolicy.recordFailure) {
731
735
  accountManager.recordFailure(account, modelFamily, model);
732
736
  }
733
- if (typeof retryableRefreshPolicy.cooldownMs === "number" &&
737
+ if (typeof retryableRefreshPolicy.cooldownMs ===
738
+ "number" &&
734
739
  retryableRefreshPolicy.cooldownReason) {
735
740
  accountManager.markAccountCoolingDown(account, retryableRefreshPolicy.cooldownMs, retryableRefreshPolicy.cooldownReason);
736
741
  accountManager.saveToDiskDebounced();
@@ -1224,10 +1229,18 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1224
1229
  preemptiveQuotaScheduler.markRateLimited(quotaScheduleKey, cooldownMs);
1225
1230
  const waitLabel = formatWaitTime(cooldownMs);
1226
1231
  const shortRetryThresholdMs = getConfiguredRateLimitShortRetryThresholdMs();
1227
- if (cooldownMs <=
1228
- shortRetryThresholdMs &&
1232
+ if (cooldownMs <= shortRetryThresholdMs &&
1229
1233
  shortRateLimitRetryCount < MAX_SHORT_RETRY_ATTEMPTS) {
1230
1234
  shortRateLimitRetryCount += 1;
1235
+ // Mark the account unavailable BEFORE we sleep so
1236
+ // concurrent in-flight requests do not select the
1237
+ // same freshly rate-limited account during the retry
1238
+ // window. Without this, the fetch loop amplifies the
1239
+ // throttling pressure instead of spreading load.
1240
+ // The current request will continue after the sleep
1241
+ // regardless of the cooldown mark (AUDIT-H3 / D-07).
1242
+ accountManager.markRateLimitedWithReason(account, cooldownMs, modelFamily, parseRateLimitReason(rateLimit?.code), model);
1243
+ accountManager.recordRateLimit(account, modelFamily, model);
1231
1244
  if (accountManager.shouldShowAccountToast(account.index, rateLimitToastDebounceMs)) {
1232
1245
  await showRuntimeToast(client, `Rate limited. Retrying in ${waitLabel} (attempt ${shortRateLimitRetryCount})...`, "warning", { duration: toastDurationMs });
1233
1246
  accountManager.markToastShown(account.index);
@@ -1382,7 +1395,7 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1382
1395
  preemptiveQuotaScheduler.update(`${fallbackEntitlementAccountKey}:${model ?? modelFamily}`, fallbackSnapshot);
1383
1396
  }
1384
1397
  if (!fallbackResponse.ok) {
1385
- const { response: handledFallbackResponse, rateLimit: fallbackRateLimit } = await handleErrorResponse(fallbackResponse);
1398
+ const { response: handledFallbackResponse, rateLimit: fallbackRateLimit, } = await handleErrorResponse(fallbackResponse);
1386
1399
  try {
1387
1400
  await fallbackResponse.body?.cancel();
1388
1401
  }
@@ -1391,7 +1404,9 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1391
1404
  }
1392
1405
  if (handledFallbackResponse.status === 429) {
1393
1406
  const retryAfterMs = fallbackRateLimit?.retryAfterMs ?? 60_000;
1394
- const fallbackQuotaKey = model ? `${modelFamily}:${model}` : modelFamily;
1407
+ const fallbackQuotaKey = model
1408
+ ? `${modelFamily}:${model}`
1409
+ : modelFamily;
1395
1410
  const { delayMs } = getRateLimitBackoff(fallbackAccount.index, fallbackQuotaKey, retryAfterMs);
1396
1411
  const cooldownMs = Math.max(delayMs, retryAfterMs);
1397
1412
  preemptiveQuotaScheduler.markRateLimited(`${fallbackEntitlementAccountKey}:${model ?? modelFamily}`, cooldownMs);
@@ -1502,7 +1517,12 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1502
1517
  error: {
1503
1518
  message: `Upstream server failures were observed across multiple accounts. Pausing retries for ${formatWaitTime(serverBurstCooldownUntil - Date.now())}. Check \`codex auth report --json\` for runtime metrics.`,
1504
1519
  },
1505
- }), { status: 503, headers: { "content-type": "application/json; charset=utf-8" } });
1520
+ }), {
1521
+ status: 503,
1522
+ headers: {
1523
+ "content-type": "application/json; charset=utf-8",
1524
+ },
1525
+ });
1506
1526
  }
1507
1527
  }
1508
1528
  logWarn(`Empty response after ${emptyResponseMaxRetries} retries. Returning as-is.`);