codex-multi-auth 2.0.1 → 2.1.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 (143) hide show
  1. package/README.md +22 -8
  2. package/config/README.md +4 -4
  3. package/config/codex-legacy.json +571 -571
  4. package/config/codex-modern.json +258 -258
  5. package/config/minimal-codex.json +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +91 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/account-policy.d.ts +22 -0
  10. package/dist/lib/account-policy.d.ts.map +1 -0
  11. package/dist/lib/account-policy.js +159 -0
  12. package/dist/lib/account-policy.js.map +1 -0
  13. package/dist/lib/accounts.d.ts.map +1 -1
  14. package/dist/lib/accounts.js +2 -1
  15. package/dist/lib/accounts.js.map +1 -1
  16. package/dist/lib/auth/device-auth.d.ts +46 -0
  17. package/dist/lib/auth/device-auth.d.ts.map +1 -0
  18. package/dist/lib/auth/device-auth.js +325 -0
  19. package/dist/lib/auth/device-auth.js.map +1 -0
  20. package/dist/lib/auth/index.d.ts +2 -0
  21. package/dist/lib/auth/index.d.ts.map +1 -1
  22. package/dist/lib/auth/index.js +1 -0
  23. package/dist/lib/auth/index.js.map +1 -1
  24. package/dist/lib/budget-guard.d.ts +39 -0
  25. package/dist/lib/budget-guard.d.ts.map +1 -0
  26. package/dist/lib/budget-guard.js +201 -0
  27. package/dist/lib/budget-guard.js.map +1 -0
  28. package/dist/lib/codex-manager/commands/account.d.ts +13 -0
  29. package/dist/lib/codex-manager/commands/account.d.ts.map +1 -0
  30. package/dist/lib/codex-manager/commands/account.js +156 -0
  31. package/dist/lib/codex-manager/commands/account.js.map +1 -0
  32. package/dist/lib/codex-manager/commands/bridge.d.ts +6 -0
  33. package/dist/lib/codex-manager/commands/bridge.d.ts.map +1 -0
  34. package/dist/lib/codex-manager/commands/bridge.js +100 -0
  35. package/dist/lib/codex-manager/commands/bridge.js.map +1 -0
  36. package/dist/lib/codex-manager/commands/budget.d.ts +12 -0
  37. package/dist/lib/codex-manager/commands/budget.d.ts.map +1 -0
  38. package/dist/lib/codex-manager/commands/budget.js +123 -0
  39. package/dist/lib/codex-manager/commands/budget.js.map +1 -0
  40. package/dist/lib/codex-manager/commands/integrations.d.ts +6 -0
  41. package/dist/lib/codex-manager/commands/integrations.d.ts.map +1 -0
  42. package/dist/lib/codex-manager/commands/integrations.js +78 -0
  43. package/dist/lib/codex-manager/commands/integrations.js.map +1 -0
  44. package/dist/lib/codex-manager/commands/models.d.ts +14 -0
  45. package/dist/lib/codex-manager/commands/models.d.ts.map +1 -0
  46. package/dist/lib/codex-manager/commands/models.js +74 -0
  47. package/dist/lib/codex-manager/commands/models.js.map +1 -0
  48. package/dist/lib/codex-manager/commands/monitor.d.ts +22 -0
  49. package/dist/lib/codex-manager/commands/monitor.d.ts.map +1 -0
  50. package/dist/lib/codex-manager/commands/monitor.js +94 -0
  51. package/dist/lib/codex-manager/commands/monitor.js.map +1 -0
  52. package/dist/lib/codex-manager/commands/rotation.d.ts +1 -0
  53. package/dist/lib/codex-manager/commands/rotation.d.ts.map +1 -1
  54. package/dist/lib/codex-manager/commands/rotation.js +293 -10
  55. package/dist/lib/codex-manager/commands/rotation.js.map +1 -1
  56. package/dist/lib/codex-manager/commands/usage.d.ts +13 -0
  57. package/dist/lib/codex-manager/commands/usage.d.ts.map +1 -0
  58. package/dist/lib/codex-manager/commands/usage.js +347 -0
  59. package/dist/lib/codex-manager/commands/usage.js.map +1 -0
  60. package/dist/lib/codex-manager/help.d.ts +1 -0
  61. package/dist/lib/codex-manager/help.d.ts.map +1 -1
  62. package/dist/lib/codex-manager/help.js +26 -1
  63. package/dist/lib/codex-manager/help.js.map +1 -1
  64. package/dist/lib/codex-manager.d.ts.map +1 -1
  65. package/dist/lib/codex-manager.js +64 -7
  66. package/dist/lib/codex-manager.js.map +1 -1
  67. package/dist/lib/config.d.ts.map +1 -1
  68. package/dist/lib/config.js +2 -22
  69. package/dist/lib/config.js.map +1 -1
  70. package/dist/lib/constants.d.ts +1 -0
  71. package/dist/lib/constants.d.ts.map +1 -1
  72. package/dist/lib/constants.js +1 -0
  73. package/dist/lib/constants.js.map +1 -1
  74. package/dist/lib/env-parsing.d.ts +21 -0
  75. package/dist/lib/env-parsing.d.ts.map +1 -0
  76. package/dist/lib/env-parsing.js +34 -0
  77. package/dist/lib/env-parsing.js.map +1 -0
  78. package/dist/lib/index.d.ts +9 -0
  79. package/dist/lib/index.d.ts.map +1 -1
  80. package/dist/lib/index.js +9 -0
  81. package/dist/lib/index.js.map +1 -1
  82. package/dist/lib/integration-generators.d.ts +14 -0
  83. package/dist/lib/integration-generators.d.ts.map +1 -0
  84. package/dist/lib/integration-generators.js +93 -0
  85. package/dist/lib/integration-generators.js.map +1 -0
  86. package/dist/lib/local-bridge.d.ts +17 -0
  87. package/dist/lib/local-bridge.d.ts.map +1 -0
  88. package/dist/lib/local-bridge.js +249 -0
  89. package/dist/lib/local-bridge.js.map +1 -0
  90. package/dist/lib/local-client-tokens.d.ts +37 -0
  91. package/dist/lib/local-client-tokens.d.ts.map +1 -0
  92. package/dist/lib/local-client-tokens.js +200 -0
  93. package/dist/lib/local-client-tokens.js.map +1 -0
  94. package/dist/lib/model-capability-matrix.d.ts +38 -0
  95. package/dist/lib/model-capability-matrix.d.ts.map +1 -0
  96. package/dist/lib/model-capability-matrix.js +89 -0
  97. package/dist/lib/model-capability-matrix.js.map +1 -0
  98. package/dist/lib/policy/runtime-policy.d.ts +59 -0
  99. package/dist/lib/policy/runtime-policy.d.ts.map +1 -0
  100. package/dist/lib/policy/runtime-policy.js +156 -0
  101. package/dist/lib/policy/runtime-policy.js.map +1 -0
  102. package/dist/lib/proactive-refresh.js +4 -4
  103. package/dist/lib/proactive-refresh.js.map +1 -1
  104. package/dist/lib/refresh-lease.d.ts.map +1 -1
  105. package/dist/lib/refresh-lease.js +1 -10
  106. package/dist/lib/refresh-lease.js.map +1 -1
  107. package/dist/lib/routing-profiles.d.ts +36 -0
  108. package/dist/lib/routing-profiles.d.ts.map +1 -0
  109. package/dist/lib/routing-profiles.js +203 -0
  110. package/dist/lib/routing-profiles.js.map +1 -0
  111. package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
  112. package/dist/lib/runtime-rotation-proxy.js +96 -6
  113. package/dist/lib/runtime-rotation-proxy.js.map +1 -1
  114. package/dist/lib/schemas.d.ts +3 -0
  115. package/dist/lib/schemas.d.ts.map +1 -1
  116. package/dist/lib/schemas.js +1 -0
  117. package/dist/lib/schemas.js.map +1 -1
  118. package/dist/lib/usage/index.d.ts +5 -0
  119. package/dist/lib/usage/index.d.ts.map +1 -0
  120. package/dist/lib/usage/index.js +5 -0
  121. package/dist/lib/usage/index.js.map +1 -0
  122. package/dist/lib/usage/ledger.d.ts +12 -0
  123. package/dist/lib/usage/ledger.d.ts.map +1 -0
  124. package/dist/lib/usage/ledger.js +493 -0
  125. package/dist/lib/usage/ledger.js.map +1 -0
  126. package/dist/lib/usage/pricing.d.ts +11 -0
  127. package/dist/lib/usage/pricing.d.ts.map +1 -0
  128. package/dist/lib/usage/pricing.js +67 -0
  129. package/dist/lib/usage/pricing.js.map +1 -0
  130. package/dist/lib/usage/redaction.d.ts +10 -0
  131. package/dist/lib/usage/redaction.d.ts.map +1 -0
  132. package/dist/lib/usage/redaction.js +129 -0
  133. package/dist/lib/usage/redaction.js.map +1 -0
  134. package/dist/lib/usage/types.d.ts +89 -0
  135. package/dist/lib/usage/types.d.ts.map +1 -0
  136. package/dist/lib/usage/types.js +2 -0
  137. package/dist/lib/usage/types.js.map +1 -0
  138. package/package.json +1 -1
  139. package/scripts/bench-format/codex-host.mjs +142 -142
  140. package/scripts/bench-format/models.mjs +23 -23
  141. package/scripts/benchmark-edit-formats.mjs +9 -9
  142. package/scripts/codex-app-router.js +121 -121
  143. package/scripts/codex.js +165 -165
package/dist/index.js CHANGED
@@ -37,6 +37,7 @@ import { EntitlementCache, resolveEntitlementAccountKey, } from "./lib/entitleme
37
37
  import { LiveAccountSync } from "./lib/live-account-sync.js";
38
38
  import { clearCorrelationId, initLogger, logDebug, logError, logInfo, logRequest, logWarn, setCorrelationId, } from "./lib/logger.js";
39
39
  import { PreemptiveQuotaScheduler, readQuotaSchedulerSnapshot, } from "./lib/preemptive-quota-scheduler.js";
40
+ import { createRuntimeUsageRecorder, evaluateRuntimePolicy, loadRuntimePolicyState, } from "./lib/policy/runtime-policy.js";
40
41
  import { getModelFamily, MODEL_FAMILIES, prewarmCodexInstructions, } from "./lib/prompts/codex.js";
41
42
  import { prewarmHostCodexPrompt } from "./lib/prompts/host-codex-prompt.js";
42
43
  import { fetchCodexQuotaSnapshot, formatQuotaSnapshotLine, } from "./lib/quota-probe.js";
@@ -543,6 +544,8 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
543
544
  * @returns Response from Codex API
544
545
  */
545
546
  async fetch(input, init) {
547
+ let usageRecorder = null;
548
+ let usageCompletion = null;
546
549
  try {
547
550
  if (cachedAccountManager &&
548
551
  cachedAccountManager !== accountManager) {
@@ -608,6 +611,59 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
608
611
  const requestTraceId = requestCorrelationId;
609
612
  runtimeMetrics.lastRequestAt = Date.now();
610
613
  syncRuntimeObservability(requestTraceId);
614
+ let runtimePolicyDecision = null;
615
+ try {
616
+ const runtimePolicyState = await loadRuntimePolicyState();
617
+ runtimePolicyDecision = await evaluateRuntimePolicy({
618
+ state: runtimePolicyState,
619
+ accounts: accountManager.getAccountsSnapshot(),
620
+ model: model ?? null,
621
+ capabilityPolicy: capabilityPolicyStore,
622
+ });
623
+ }
624
+ catch (policyError) {
625
+ logWarn("Runtime policy evaluation failed open.", {
626
+ error: policyError instanceof Error
627
+ ? policyError.message
628
+ : String(policyError),
629
+ });
630
+ }
631
+ usageRecorder = createRuntimeUsageRecorder({
632
+ source: "plugin-host",
633
+ operation: "responses",
634
+ model: model ?? null,
635
+ projectKey: runtimePolicyDecision?.projectKey ?? null,
636
+ requestId: requestTraceId,
637
+ startedAt: Date.now(),
638
+ });
639
+ usageCompletion = {
640
+ outcome: "failure",
641
+ statusCode: null,
642
+ errorCode: "plugin_host_request_failed",
643
+ };
644
+ if (runtimePolicyDecision && !runtimePolicyDecision.allowed) {
645
+ runtimeMetrics.failedRequests += 1;
646
+ runtimeMetrics.lastError = "Runtime policy blocked request";
647
+ syncRuntimeObservability(requestTraceId);
648
+ usageCompletion = {
649
+ outcome: "blocked",
650
+ statusCode: runtimePolicyDecision.statusCode,
651
+ errorCode: runtimePolicyDecision.errorCode,
652
+ };
653
+ return new Response(JSON.stringify({
654
+ error: {
655
+ message: "Runtime policy blocked this local request.",
656
+ code: runtimePolicyDecision.errorCode ??
657
+ "policy_blocked",
658
+ reasons: runtimePolicyDecision.reasons,
659
+ },
660
+ }), {
661
+ status: runtimePolicyDecision.statusCode,
662
+ headers: {
663
+ "content-type": "application/json; charset=utf-8",
664
+ },
665
+ });
666
+ }
611
667
  const abortSignal = requestInit?.signal ?? init?.signal ?? null;
612
668
  const sleep = createAbortableSleep(abortSignal);
613
669
  const poolCooldownRemainingMs = getPoolExhaustionCooldownRemaining();
@@ -616,6 +672,11 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
616
672
  runtimeMetrics.poolExhaustionFastFails += 1;
617
673
  runtimeMetrics.lastError = "Pool exhaustion cooldown active";
618
674
  syncRuntimeObservability(requestTraceId);
675
+ usageCompletion = {
676
+ outcome: "failure",
677
+ statusCode: 429,
678
+ errorCode: "pool_exhaustion_cooldown",
679
+ };
619
680
  return new Response(JSON.stringify({
620
681
  error: {
621
682
  message: `The account pool is cooling down after recent rate-limit exhaustion. Try again in ${formatWaitTime(poolCooldownRemainingMs)} or inspect \`codex auth status\`.`,
@@ -633,6 +694,11 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
633
694
  runtimeMetrics.serverBurstFastFails += 1;
634
695
  runtimeMetrics.lastError = "Server burst cooldown active";
635
696
  syncRuntimeObservability(requestTraceId);
697
+ usageCompletion = {
698
+ outcome: "failure",
699
+ statusCode: 503,
700
+ errorCode: "server_burst_cooldown",
701
+ };
636
702
  return new Response(JSON.stringify({
637
703
  error: {
638
704
  message: `Multiple accounts recently failed with upstream server errors. Try again in ${formatWaitTime(serverBurstCooldownRemainingMs)} or inspect \`codex auth report --json\`.`,
@@ -713,12 +779,20 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
713
779
  capabilityBoostByAccount[candidate.index] =
714
780
  capabilityPolicyStore.getBoost(accountKey, model ?? modelFamily);
715
781
  }
782
+ for (const [rawIndex, boost] of Object.entries(runtimePolicyDecision?.scoreBoostByAccount ?? {})) {
783
+ const index = Number(rawIndex);
784
+ if (!Number.isInteger(index))
785
+ continue;
786
+ capabilityBoostByAccount[index] =
787
+ (capabilityBoostByAccount[index] ?? 0) + boost;
788
+ }
716
789
  accountAttemptLoop: while (attempted.size < Math.max(1, accountCount)) {
717
790
  let account = null;
718
791
  if (!usedPreferredSessionAccount &&
719
792
  typeof preferredSessionAccountIndex === "number") {
720
793
  usedPreferredSessionAccount = true;
721
- if (accountManager.isAccountAvailableForFamily(preferredSessionAccountIndex, modelFamily, model)) {
794
+ if (accountManager.isAccountAvailableForFamily(preferredSessionAccountIndex, modelFamily, model) &&
795
+ !runtimePolicyDecision?.blockedAccountIndexes.has(preferredSessionAccountIndex)) {
722
796
  account = accountManager.getAccountByIndex(preferredSessionAccountIndex);
723
797
  if (account) {
724
798
  account.lastUsed = Date.now();
@@ -739,6 +813,9 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
739
813
  break;
740
814
  }
741
815
  attempted.add(account.index);
816
+ if (runtimePolicyDecision?.blockedAccountIndexes.has(account.index)) {
817
+ continue;
818
+ }
742
819
  // Log account selection for debugging rotation
743
820
  logDebug(`Using account ${account.index + 1}/${accountCount}: ${account.email ?? "unknown"} for ${modelFamily}`);
744
821
  let accountAuth = accountManager.toAuthDetails(account);
@@ -1587,6 +1664,16 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1587
1664
  }
1588
1665
  runtimeMetrics.successfulRequests++;
1589
1666
  runtimeMetrics.lastError = null;
1667
+ usageCompletion = {
1668
+ outcome: "success",
1669
+ statusCode: successResponse.status,
1670
+ errorCode: null,
1671
+ account: {
1672
+ index: successAccountForResponse.index,
1673
+ accountId: successAccountForResponse.accountId ?? null,
1674
+ email: successAccountForResponse.email ?? null,
1675
+ },
1676
+ };
1590
1677
  if (lastCodexCliActiveSyncIndex !==
1591
1678
  successAccountForResponse.index) {
1592
1679
  void accountManager.syncCodexCliActiveSelectionForIndex(successAccountForResponse.index);
@@ -1657,6 +1744,9 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
1657
1744
  }
1658
1745
  }
1659
1746
  finally {
1747
+ if (usageRecorder && usageCompletion) {
1748
+ await usageRecorder.record(usageCompletion);
1749
+ }
1660
1750
  syncRuntimeObservability(null);
1661
1751
  clearCorrelationId();
1662
1752
  }