oc-codex-multi-auth 6.3.3 → 6.4.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 (64) hide show
  1. package/README.md +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +21 -6
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/accounts/rotation.d.ts +17 -0
  6. package/dist/lib/accounts/rotation.d.ts.map +1 -1
  7. package/dist/lib/accounts/rotation.js +51 -0
  8. package/dist/lib/accounts/rotation.js.map +1 -1
  9. package/dist/lib/accounts/stale-state.d.ts +139 -0
  10. package/dist/lib/accounts/stale-state.d.ts.map +1 -0
  11. package/dist/lib/accounts/stale-state.js +192 -0
  12. package/dist/lib/accounts/stale-state.js.map +1 -0
  13. package/dist/lib/accounts/warm-request.d.ts +41 -0
  14. package/dist/lib/accounts/warm-request.d.ts.map +1 -0
  15. package/dist/lib/accounts/warm-request.js +97 -0
  16. package/dist/lib/accounts/warm-request.js.map +1 -0
  17. package/dist/lib/accounts/warm.d.ts +71 -0
  18. package/dist/lib/accounts/warm.d.ts.map +1 -0
  19. package/dist/lib/accounts/warm.js +86 -0
  20. package/dist/lib/accounts/warm.js.map +1 -0
  21. package/dist/lib/accounts.d.ts +9 -0
  22. package/dist/lib/accounts.d.ts.map +1 -1
  23. package/dist/lib/accounts.js +19 -0
  24. package/dist/lib/accounts.js.map +1 -1
  25. package/dist/lib/auth/login-runner.d.ts.map +1 -1
  26. package/dist/lib/auth/login-runner.js +5 -1
  27. package/dist/lib/auth/login-runner.js.map +1 -1
  28. package/dist/lib/config.d.ts +17 -0
  29. package/dist/lib/config.d.ts.map +1 -1
  30. package/dist/lib/config.js +30 -0
  31. package/dist/lib/config.js.map +1 -1
  32. package/dist/lib/constants.d.ts +11 -0
  33. package/dist/lib/constants.d.ts.map +1 -1
  34. package/dist/lib/constants.js +11 -0
  35. package/dist/lib/constants.js.map +1 -1
  36. package/dist/lib/request/fetch-helpers.d.ts +11 -0
  37. package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
  38. package/dist/lib/request/fetch-helpers.js +25 -0
  39. package/dist/lib/request/fetch-helpers.js.map +1 -1
  40. package/dist/lib/schemas.d.ts +5 -0
  41. package/dist/lib/schemas.d.ts.map +1 -1
  42. package/dist/lib/schemas.js +1 -0
  43. package/dist/lib/schemas.js.map +1 -1
  44. package/dist/lib/storage/identity.d.ts +1 -0
  45. package/dist/lib/storage/identity.d.ts.map +1 -1
  46. package/dist/lib/storage/identity.js +45 -2
  47. package/dist/lib/storage/identity.js.map +1 -1
  48. package/dist/lib/tools/codex-doctor.d.ts.map +1 -1
  49. package/dist/lib/tools/codex-doctor.js +110 -2
  50. package/dist/lib/tools/codex-doctor.js.map +1 -1
  51. package/dist/lib/tools/codex-health.d.ts.map +1 -1
  52. package/dist/lib/tools/codex-health.js +21 -0
  53. package/dist/lib/tools/codex-health.js.map +1 -1
  54. package/dist/lib/tools/codex-help.d.ts.map +1 -1
  55. package/dist/lib/tools/codex-help.js +1 -0
  56. package/dist/lib/tools/codex-help.js.map +1 -1
  57. package/dist/lib/tools/codex-warm.d.ts +33 -0
  58. package/dist/lib/tools/codex-warm.d.ts.map +1 -0
  59. package/dist/lib/tools/codex-warm.js +113 -0
  60. package/dist/lib/tools/codex-warm.js.map +1 -0
  61. package/dist/lib/tools/index.d.ts.map +1 -1
  62. package/dist/lib/tools/index.js +2 -0
  63. package/dist/lib/tools/index.js.map +1 -1
  64. package/package.json +7 -4
package/README.md CHANGED
@@ -175,6 +175,7 @@ If browser launch is blocked, use the alternate login paths in [docs/getting-sta
175
175
  | --- | --- |
176
176
  | `codex-list` | Which accounts are saved and which one is active? |
177
177
  | `codex-switch` | How do I move to a different saved account? |
178
+ | `codex-warm` | How do I start every account's usage window now (stagger quota cooldowns)? |
178
179
  | `codex-status` | Which account, model family, and routing state are active? |
179
180
  | `codex-limits` | What quota or rate-limit state is visible now? |
180
181
  | `codex-dashboard` | Can I manage accounts from one interactive surface? |
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAwM/D;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAyqH/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAoB,CAAC;AAElD,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AA0M/D;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MA8rH/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAoB,CAAC;AAElD,eAAe,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ import { queuedRefresh } from "./lib/refresh-queue.js";
32
32
  import { openBrowserUrl } from "./lib/auth/browser.js";
33
33
  import { startLocalOAuthServer } from "./lib/auth/server.js";
34
34
  import { promptAddAnotherAccount, promptLoginMode } from "./lib/cli.js";
35
- import { getCodexMode, getRequestTransformMode, getFastSession, getFastSessionStrategy, getFastSessionMaxInputItems, getRetryProfile, getRetryBudgetOverrides, getRateLimitToastDebounceMs, getRetryAllAccountsMaxRetries, getRetryAllAccountsMaxWaitMs, getRetryAllAccountsRateLimited, getFallbackToGpt52OnUnsupportedGpt53, getUnsupportedCodexPolicy, getUnsupportedCodexFallbackChain, getTokenRefreshSkewMs, getSessionRecovery, getAutoResume, getAutoUpdate, getToastDurationMs, getPerProjectAccounts, getEmptyResponseMaxRetries, getEmptyResponseRetryDelayMs, getPidOffsetEnabled, getFetchTimeoutMs, getStreamStallTimeoutMs, getCodexTuiV2, getCodexTuiColorProfile, getCodexTuiGlyphMode, getBeginnerSafeMode, getCodexTuiMaskEmail, loadPluginConfig, } from "./lib/config.js";
35
+ import { getCodexMode, getRequestTransformMode, getFastSession, getFastSessionStrategy, getFastSessionMaxInputItems, getRetryProfile, getRetryBudgetOverrides, getRateLimitToastDebounceMs, getRetryAllAccountsMaxRetries, getRetryAllAccountsMaxWaitMs, getRetryAllAccountsRateLimited, getFallbackToGpt52OnUnsupportedGpt53, getUnsupportedCodexPolicy, getUnsupportedCodexFallbackChain, getTokenRefreshSkewMs, getSessionRecovery, getAutoResume, getAutoUpdate, getToastDurationMs, getPerProjectAccounts, getEmptyResponseMaxRetries, getEmptyResponseRetryDelayMs, getPidOffsetEnabled, getRotationStrategy, getFetchTimeoutMs, getStreamStallTimeoutMs, getCodexTuiV2, getCodexTuiColorProfile, getCodexTuiGlyphMode, getBeginnerSafeMode, getCodexTuiMaskEmail, loadPluginConfig, } from "./lib/config.js";
36
36
  import { AUTH_LABELS, CODEX_BASE_URL, DUMMY_API_KEY, LOG_STAGES, PLUGIN_NAME, PROVIDER_ID, ACCOUNT_LIMITS, } from "./lib/constants.js";
37
37
  import { initLogger, logRequest, logDebug, logInfo, logWarn, logError, setCorrelationId, clearCorrelationId, } from "./lib/logger.js";
38
38
  import { checkAndNotify } from "./lib/auto-update-checker.js";
@@ -41,7 +41,7 @@ import { AccountManager, extractAccountEmail, extractAccountId, formatAccountLab
41
41
  import { resolveDisplayEmail } from "./lib/account-display.js";
42
42
  import { CodexAuthError } from "./lib/errors.js";
43
43
  import { getStoragePath, loadAccounts, saveAccounts, withAccountStorageTransaction, clearAccounts, setStoragePath, loadFlaggedAccounts, saveFlaggedAccounts, withFlaggedAccountStorageTransaction, clearFlaggedAccounts, getWorkspaceIdentityKey, StorageError, formatStorageErrorHint, } from "./lib/storage.js";
44
- import { createCodexHeaders, extractRequestUrl, handleErrorResponse, handleSuccessResponse, isDeactivatedWorkspaceError, isInvalidatedAuthTokenError, getUnsupportedCodexModelInfo, resolveUnsupportedCodexFallbackModel, refreshAndUpdateToken, rewriteUrlForCodex, shouldRefreshToken, transformRequestForCodex, } from "./lib/request/fetch-helpers.js";
44
+ import { createCodexHeaders, extractRequestUrl, handleErrorResponse, handleSuccessResponse, isDeactivatedWorkspaceError, isInvalidatedAuthTokenError, createAbortError, getUnsupportedCodexModelInfo, resolveUnsupportedCodexFallbackModel, refreshAndUpdateToken, rewriteUrlForCodex, shouldRefreshToken, transformRequestForCodex, } from "./lib/request/fetch-helpers.js";
45
45
  import { createDeactivatedWorkspaceError, DEACTIVATED_WORKSPACE_ERROR_CODE, isDeactivatedWorkspaceErrorMessage, isInvalidatedAuthTokenMessage, } from "./lib/error-sentinels.js";
46
46
  import { applyFastSessionDefaults, upsertBackendModelIdentityMessage, } from "./lib/request/request-transformer.js";
47
47
  import { getRateLimitBackoff, RATE_LIMIT_SHORT_RETRY_THRESHOLD_MS, resetRateLimitBackoff, } from "./lib/request/rate-limit-backoff.js";
@@ -1127,6 +1127,7 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1127
1127
  const emptyResponseMaxRetries = getEmptyResponseMaxRetries(pluginConfig);
1128
1128
  const emptyResponseRetryDelayMs = getEmptyResponseRetryDelayMs(pluginConfig);
1129
1129
  const pidOffsetEnabled = getPidOffsetEnabled(pluginConfig);
1130
+ const rotationStrategy = getRotationStrategy(pluginConfig);
1130
1131
  const effectiveUserConfig = fastSessionEnabled
1131
1132
  ? applyFastSessionDefaults(userConfig)
1132
1133
  : userConfig;
@@ -1299,9 +1300,14 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1299
1300
  return false;
1300
1301
  };
1301
1302
  const abortSignal = requestInit?.signal ?? init?.signal ?? null;
1303
+ // Surface caller-cancellation during retry/backoff waits as a proper
1304
+ // AbortError (name set) carrying the caller abort reason, mirroring the
1305
+ // fetch path (Aborted by user) and lib/codex-usage.ts isAbortError. A bare
1306
+ // new Error("Aborted") was opaque and dropped abortSignal.reason (#176).
1307
+ const abortError = () => createAbortError(abortSignal);
1302
1308
  const sleep = (ms) => new Promise((resolve, reject) => {
1303
1309
  if (abortSignal?.aborted) {
1304
- reject(new Error("Aborted"));
1310
+ reject(abortError());
1305
1311
  return;
1306
1312
  }
1307
1313
  const timeout = setTimeout(() => {
@@ -1310,7 +1316,7 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1310
1316
  }, ms);
1311
1317
  const onAbort = () => {
1312
1318
  cleanup();
1313
- reject(new Error("Aborted"));
1319
+ reject(abortError());
1314
1320
  };
1315
1321
  const cleanup = () => {
1316
1322
  clearTimeout(timeout);
@@ -1323,7 +1329,7 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1323
1329
  const endTime = startTime + totalMs;
1324
1330
  while (Date.now() < endTime) {
1325
1331
  if (abortSignal?.aborted) {
1326
- throw new Error("Aborted");
1332
+ throw abortError();
1327
1333
  }
1328
1334
  const remaining = Math.max(0, endTime - Date.now());
1329
1335
  const waitLabel = formatWaitTime(remaining);
@@ -1364,7 +1370,7 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1364
1370
  fallbackTo,
1365
1371
  fallbackReason,
1366
1372
  };
1367
- const account = accountManager.getCurrentOrNextForFamilyHybrid(modelFamily, model, { pidOffsetEnabled });
1373
+ const account = accountManager.getAccountForStrategy(rotationStrategy, modelFamily, model, { pidOffsetEnabled });
1368
1374
  if (!account || attempted.has(account.index)) {
1369
1375
  break;
1370
1376
  }
@@ -1492,6 +1498,15 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1492
1498
  const tokenConsumed = accountManager.consumeToken(account, modelFamily, model);
1493
1499
  if (!tokenConsumed) {
1494
1500
  accountManager.recordRateLimit(account, modelFamily, model);
1501
+ // Mark a short, auto-expiring rate-limit window for this
1502
+ // (family, model) so the depleted account becomes ineligible in
1503
+ // `isRateLimitedForFamily`. Without this, drain-first `sticky`
1504
+ // (and the `hybrid` fast-path) re-select the SAME depleted account
1505
+ // on the next traversal iteration — `attempted` then trips the
1506
+ // guard and the loop 503s while other accounts still have quota.
1507
+ // The window also feeds `getMinWaitTimeForFamily`, so an all-
1508
+ // depleted pool waits for refill instead of failing fast.
1509
+ accountManager.markRateLimitedWithReason(account, ACCOUNT_LIMITS.LOCAL_TOKEN_DEPLETION_COOLDOWN_MS, modelFamily, "tokens", model);
1495
1510
  runtimeMetrics.accountRotations++;
1496
1511
  runtimeMetrics.lastError =
1497
1512
  `Local token bucket depleted for account ${account.index + 1} (${modelFamily}${model ? `:${model}` : ""})`;