codex-multi-auth 2.2.0 → 2.2.2

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 (112) hide show
  1. package/.codex-plugin/plugin.json +9 -0
  2. package/README.md +4 -2
  3. package/dist/lib/auth/device-auth.d.ts.map +1 -1
  4. package/dist/lib/auth/device-auth.js +15 -0
  5. package/dist/lib/auth/device-auth.js.map +1 -1
  6. package/dist/lib/auth/server.d.ts.map +1 -1
  7. package/dist/lib/auth/server.js +12 -7
  8. package/dist/lib/auth/server.js.map +1 -1
  9. package/dist/lib/capability-policy.d.ts.map +1 -1
  10. package/dist/lib/capability-policy.js +5 -0
  11. package/dist/lib/capability-policy.js.map +1 -1
  12. package/dist/lib/codex-cli/state.d.ts.map +1 -1
  13. package/dist/lib/codex-cli/state.js +28 -7
  14. package/dist/lib/codex-cli/state.js.map +1 -1
  15. package/dist/lib/codex-manager/commands/best.d.ts.map +1 -1
  16. package/dist/lib/codex-manager/commands/best.js +2 -2
  17. package/dist/lib/codex-manager/commands/best.js.map +1 -1
  18. package/dist/lib/codex-manager/commands/budget.d.ts.map +1 -1
  19. package/dist/lib/codex-manager/commands/budget.js +6 -0
  20. package/dist/lib/codex-manager/commands/budget.js.map +1 -1
  21. package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -1
  22. package/dist/lib/codex-manager/commands/forecast.js +9 -7
  23. package/dist/lib/codex-manager/commands/forecast.js.map +1 -1
  24. package/dist/lib/codex-manager/commands/integrations.js +2 -2
  25. package/dist/lib/codex-manager/commands/integrations.js.map +1 -1
  26. package/dist/lib/codex-manager/commands/models.js +3 -3
  27. package/dist/lib/codex-manager/commands/models.js.map +1 -1
  28. package/dist/lib/codex-manager/commands/report.d.ts.map +1 -1
  29. package/dist/lib/codex-manager/commands/report.js +9 -7
  30. package/dist/lib/codex-manager/commands/report.js.map +1 -1
  31. package/dist/lib/codex-manager/commands/workspace.d.ts.map +1 -1
  32. package/dist/lib/codex-manager/commands/workspace.js +12 -1
  33. package/dist/lib/codex-manager/commands/workspace.js.map +1 -1
  34. package/dist/lib/codex-manager/forecast-report-commands.d.ts.map +1 -1
  35. package/dist/lib/codex-manager/forecast-report-commands.js +11 -10
  36. package/dist/lib/codex-manager/forecast-report-commands.js.map +1 -1
  37. package/dist/lib/codex-manager/help.d.ts.map +1 -1
  38. package/dist/lib/codex-manager/help.js +7 -5
  39. package/dist/lib/codex-manager/help.js.map +1 -1
  40. package/dist/lib/codex-manager/repair-commands.js +7 -7
  41. package/dist/lib/codex-manager/repair-commands.js.map +1 -1
  42. package/dist/lib/codex-manager.d.ts.map +1 -1
  43. package/dist/lib/codex-manager.js +72 -32
  44. package/dist/lib/codex-manager.js.map +1 -1
  45. package/dist/lib/config.d.ts.map +1 -1
  46. package/dist/lib/config.js +217 -13
  47. package/dist/lib/config.js.map +1 -1
  48. package/dist/lib/forecast.d.ts +1 -0
  49. package/dist/lib/forecast.d.ts.map +1 -1
  50. package/dist/lib/forecast.js +47 -3
  51. package/dist/lib/forecast.js.map +1 -1
  52. package/dist/lib/integration-generators.d.ts.map +1 -1
  53. package/dist/lib/integration-generators.js +1 -1
  54. package/dist/lib/integration-generators.js.map +1 -1
  55. package/dist/lib/local-client-tokens.d.ts.map +1 -1
  56. package/dist/lib/local-client-tokens.js +117 -64
  57. package/dist/lib/local-client-tokens.js.map +1 -1
  58. package/dist/lib/model-capability-matrix.d.ts.map +1 -1
  59. package/dist/lib/model-capability-matrix.js +13 -10
  60. package/dist/lib/model-capability-matrix.js.map +1 -1
  61. package/dist/lib/policy/runtime-policy.d.ts.map +1 -1
  62. package/dist/lib/policy/runtime-policy.js +8 -0
  63. package/dist/lib/policy/runtime-policy.js.map +1 -1
  64. package/dist/lib/prompts/codex.d.ts +1 -1
  65. package/dist/lib/prompts/codex.d.ts.map +1 -1
  66. package/dist/lib/prompts/codex.js +4 -4
  67. package/dist/lib/prompts/codex.js.map +1 -1
  68. package/dist/lib/quota-cache.d.ts.map +1 -1
  69. package/dist/lib/quota-cache.js +16 -1
  70. package/dist/lib/quota-cache.js.map +1 -1
  71. package/dist/lib/quota-probe.d.ts.map +1 -1
  72. package/dist/lib/quota-probe.js +2 -1
  73. package/dist/lib/quota-probe.js.map +1 -1
  74. package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
  75. package/dist/lib/request/fetch-helpers.js +3 -0
  76. package/dist/lib/request/fetch-helpers.js.map +1 -1
  77. package/dist/lib/request/helpers/model-map.d.ts +1 -0
  78. package/dist/lib/request/helpers/model-map.d.ts.map +1 -1
  79. package/dist/lib/request/helpers/model-map.js +10 -0
  80. package/dist/lib/request/helpers/model-map.js.map +1 -1
  81. package/dist/lib/routing-mutex.d.ts +12 -0
  82. package/dist/lib/routing-mutex.d.ts.map +1 -1
  83. package/dist/lib/routing-mutex.js +38 -1
  84. package/dist/lib/routing-mutex.js.map +1 -1
  85. package/dist/lib/runtime/quota-probe.d.ts.map +1 -1
  86. package/dist/lib/runtime/quota-probe.js +2 -5
  87. package/dist/lib/runtime/quota-probe.js.map +1 -1
  88. package/dist/lib/runtime/runtime-observability.d.ts +9 -0
  89. package/dist/lib/runtime/runtime-observability.d.ts.map +1 -1
  90. package/dist/lib/runtime/runtime-observability.js +28 -0
  91. package/dist/lib/runtime/runtime-observability.js.map +1 -1
  92. package/dist/lib/runtime-rotation-proxy.d.ts +23 -1
  93. package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
  94. package/dist/lib/runtime-rotation-proxy.js +135 -12
  95. package/dist/lib/runtime-rotation-proxy.js.map +1 -1
  96. package/dist/lib/storage/account-persistence.d.ts.map +1 -1
  97. package/dist/lib/storage/account-persistence.js +11 -1
  98. package/dist/lib/storage/account-persistence.js.map +1 -1
  99. package/dist/lib/storage/record-utils.d.ts.map +1 -1
  100. package/dist/lib/storage/record-utils.js +6 -1
  101. package/dist/lib/storage/record-utils.js.map +1 -1
  102. package/dist/lib/storage/transactions.d.ts +8 -0
  103. package/dist/lib/storage/transactions.d.ts.map +1 -1
  104. package/dist/lib/storage/transactions.js +14 -1
  105. package/dist/lib/storage/transactions.js.map +1 -1
  106. package/dist/lib/storage.d.ts.map +1 -1
  107. package/dist/lib/storage.js +46 -9
  108. package/dist/lib/storage.js.map +1 -1
  109. package/package.json +4 -3
  110. package/scripts/codex-bin-resolver.js +28 -1
  111. package/scripts/mcodex.js +367 -0
  112. package/scripts/mcodex +0 -117
@@ -46,7 +46,7 @@ import { DEFAULT_DASHBOARD_DISPLAY_SETTINGS, loadDashboardDisplaySettings, } fro
46
46
  import { evaluateForecastAccounts, recommendForecastAccount, summarizeForecast, } from "./forecast.js";
47
47
  import { createLogger } from "./logger.js";
48
48
  import { MODEL_FAMILIES } from "./prompts/codex.js";
49
- import { getModelCapabilities, getModelProfile, resolveNormalizedModel, } from "./request/helpers/model-map.js";
49
+ import { DEFAULT_MODEL, getModelCapabilities, getModelProfile, resolveNormalizedModel, } from "./request/helpers/model-map.js";
50
50
  import { formatRateLimitEntry as formatAccountRateLimitEntry, getRateLimitResetTimeForFamily, resolveActiveIndex, } from "./runtime/account-status.js";
51
51
  import { buildQuotaEmailFallbackState, hasSafeQuotaEmailFallback, hasUniqueQuotaAccountId, isQuotaCacheEntryExhausted, normalizeQuotaAccountId, normalizeQuotaEmail, quotaLeftPercentFromUsed, } from "./quota-readiness.js";
52
52
  import { loadQuotaCache, saveQuotaCache, } from "./quota-cache.js";
@@ -218,7 +218,7 @@ function styleQuotaSummary(summary) {
218
218
  return stylePromptText(segment, "muted");
219
219
  }
220
220
  const windowLabel = match[1] ?? "";
221
- const leftPercent = Number.parseInt(match[2] ?? "", 10);
221
+ const leftPercent = Math.max(0, Math.min(100, Number.parseInt(match[2] ?? "", 10)));
222
222
  if (!Number.isFinite(leftPercent)) {
223
223
  return stylePromptText(segment, "muted");
224
224
  }
@@ -239,9 +239,14 @@ export function styleAccountDetailText(detail, fallbackTone = "muted") {
239
239
  const prefix = (quotaMatch[1] ?? "").trim();
240
240
  const quota = (quotaMatch[2] ?? "").trim();
241
241
  const suffix = (quotaMatch[3] ?? "").trim();
242
- const prefixTone = /failed|error/i.test(prefix)
242
+ // danger wins across the WHOLE detail: a failure keyword anywhere — even
243
+ // trapped inside the (…%) quota segment, e.g.
244
+ // "signed in and working (live check failed: … 0%)" — must keep the prefix
245
+ // red, never let a "working"/"ok" prefix render green over a real failure.
246
+ const detailHasFailure = /failed|error|rate-limited/i.test(compact);
247
+ const prefixTone = detailHasFailure
243
248
  ? "danger"
244
- : /ok|working|succeeded|valid/i.test(prefix)
249
+ : /\b(ok|working|succeeded|valid)\b/i.test(prefix)
245
250
  ? "success"
246
251
  : fallbackTone;
247
252
  const suffixTone =
@@ -267,7 +272,7 @@ export function styleAccountDetailText(detail, fallbackTone = "muted") {
267
272
  return stylePromptText(compact, "danger");
268
273
  if (/re-login|stale|warning|fallback|unavailable|not available/i.test(compact))
269
274
  return stylePromptText(compact, "warning");
270
- if (/ok|working|succeeded|valid/i.test(compact))
275
+ if (/\b(ok|working|succeeded|valid)\b/i.test(compact))
271
276
  return stylePromptText(compact, "success");
272
277
  return stylePromptText(compact, fallbackTone);
273
278
  }
@@ -441,7 +446,7 @@ function getPersistedQuotaViewForAccount(cache, account, accounts, now, emailFal
441
446
  return {
442
447
  updatedAt: cachedEntry?.updatedAt ?? now,
443
448
  status: 429,
444
- model: cachedEntry?.model ?? "gpt-5.3-codex",
449
+ model: cachedEntry?.model ?? DEFAULT_MODEL,
445
450
  planType: cachedEntry?.planType,
446
451
  primary: {
447
452
  ...cachedEntry?.primary,
@@ -509,7 +514,8 @@ function pruneUnsafeQuotaEmailCacheEntry(cache, email, accounts, emailFallbackSt
509
514
  return true;
510
515
  }
511
516
  const DEFAULT_MENU_QUOTA_REFRESH_TTL_MS = 5 * 60_000;
512
- const MENU_QUOTA_REFRESH_MODEL = "gpt-5.3-codex";
517
+ const DEFAULT_LIVE_PROBE_MODEL = DEFAULT_MODEL;
518
+ const MENU_QUOTA_REFRESH_MODEL = DEFAULT_LIVE_PROBE_MODEL;
513
519
  function resolveMenuQuotaProbeInput(account, cache, maxAgeMs, now, accounts, emailFallbackState = buildQuotaEmailFallbackState(accounts)) {
514
520
  if (account.enabled === false)
515
521
  return null;
@@ -1581,7 +1587,7 @@ async function syncSelectionToCodex(tokens) {
1581
1587
  async function runHealthCheck(options = {}) {
1582
1588
  const forceRefresh = options.forceRefresh === true;
1583
1589
  const liveProbe = options.liveProbe === true;
1584
- const probeModel = options.model?.trim() || "gpt-5.3-codex";
1590
+ const probeModel = options.model?.trim() || DEFAULT_LIVE_PROBE_MODEL;
1585
1591
  const modelInspection = inspectRequestedModel(probeModel);
1586
1592
  const display = options.display ?? DEFAULT_DASHBOARD_DISPLAY_SETTINGS;
1587
1593
  const quotaCache = liveProbe ? await loadQuotaCache() : null;
@@ -1600,6 +1606,8 @@ async function runHealthCheck(options = {}) {
1600
1606
  let ok = 0;
1601
1607
  let failed = 0;
1602
1608
  let warnings = 0;
1609
+ let codexAvailable = 0;
1610
+ let signedInOnly = 0;
1603
1611
  const activeIndex = resolveActiveIndex(storage, "codex");
1604
1612
  let activeAccountRefreshed = false;
1605
1613
  const now = Date.now();
@@ -1625,6 +1633,7 @@ async function runHealthCheck(options = {}) {
1625
1633
  activeAccountRefreshed = true;
1626
1634
  }
1627
1635
  let healthDetail = "signed in and working";
1636
+ let healthTone = "success";
1628
1637
  if (liveProbe) {
1629
1638
  const currentAccessToken = account.accessToken;
1630
1639
  const probeAccountId = currentAccessToken
@@ -1632,8 +1641,10 @@ async function runHealthCheck(options = {}) {
1632
1641
  : undefined;
1633
1642
  if (!probeAccountId || !currentAccessToken) {
1634
1643
  warnings += 1;
1644
+ signedInOnly += 1;
1645
+ healthTone = "warning";
1635
1646
  healthDetail =
1636
- "signed in and working (live check skipped: missing account ID)";
1647
+ "signed in (live check skipped: missing account ID)";
1637
1648
  }
1638
1649
  else {
1639
1650
  try {
@@ -1647,16 +1658,19 @@ async function runHealthCheck(options = {}) {
1647
1658
  updateQuotaCacheForAccount(workingQuotaCache, account, snapshot, storage.accounts, quotaEmailFallbackState ?? undefined) || quotaCacheChanged;
1648
1659
  }
1649
1660
  healthDetail = formatQuotaSnapshotForDashboard(snapshot, display);
1661
+ codexAvailable += 1;
1650
1662
  }
1651
1663
  catch (error) {
1652
1664
  warnings += 1;
1665
+ signedInOnly += 1;
1666
+ healthTone = "warning";
1653
1667
  if (isCodexUnavailableError(error)) {
1654
1668
  healthDetail =
1655
- `signed in and working (${CODEX_UNAVAILABLE_PROBE_NOTE})`;
1669
+ `signed in; ${CODEX_UNAVAILABLE_PROBE_NOTE}`;
1656
1670
  }
1657
1671
  else {
1658
1672
  const message = normalizeFailureDetail(error instanceof Error ? error.message : String(error), undefined);
1659
- healthDetail = `signed in and working (live check failed: ${message})`;
1673
+ healthDetail = `signed in (live check failed: ${message})`;
1660
1674
  }
1661
1675
  }
1662
1676
  }
@@ -1666,7 +1680,8 @@ async function runHealthCheck(options = {}) {
1666
1680
  }
1667
1681
  ok += 1;
1668
1682
  if (display.showPerAccountRows) {
1669
- console.log(` ${stylePromptText("✓", "success")} ${labelText} ${stylePromptText("|", "muted")} ${styleAccountDetailText(healthDetail)}`);
1683
+ const healthMarker = healthTone === "success" ? "✓" : "!";
1684
+ console.log(` ${stylePromptText(healthMarker, healthTone)} ${labelText} ${stylePromptText("|", "muted")} ${styleAccountDetailText(healthDetail, healthTone)}`);
1670
1685
  }
1671
1686
  continue;
1672
1687
  }
@@ -1712,12 +1727,15 @@ async function runHealthCheck(options = {}) {
1712
1727
  }
1713
1728
  ok += 1;
1714
1729
  let healthyMessage = "working now";
1730
+ let healthyTone = "success";
1715
1731
  if (liveProbe) {
1716
1732
  const probeAccountId = account.accountId ?? tokenAccountId;
1717
1733
  if (!probeAccountId) {
1718
1734
  warnings += 1;
1735
+ signedInOnly += 1;
1736
+ healthyTone = "warning";
1719
1737
  healthyMessage =
1720
- "working now (live check skipped: missing account ID)";
1738
+ "signed in (live check skipped: missing account ID)";
1721
1739
  }
1722
1740
  else {
1723
1741
  try {
@@ -1731,28 +1749,35 @@ async function runHealthCheck(options = {}) {
1731
1749
  updateQuotaCacheForAccount(workingQuotaCache, account, snapshot, storage.accounts, quotaEmailFallbackState ?? undefined) || quotaCacheChanged;
1732
1750
  }
1733
1751
  healthyMessage = formatQuotaSnapshotForDashboard(snapshot, display);
1752
+ codexAvailable += 1;
1734
1753
  }
1735
1754
  catch (error) {
1736
1755
  warnings += 1;
1756
+ signedInOnly += 1;
1757
+ healthyTone = "warning";
1737
1758
  if (isCodexUnavailableError(error)) {
1738
1759
  healthyMessage =
1739
- `working now (${CODEX_UNAVAILABLE_PROBE_NOTE})`;
1760
+ `signed in; ${CODEX_UNAVAILABLE_PROBE_NOTE}`;
1740
1761
  }
1741
1762
  else {
1742
1763
  const message = normalizeFailureDetail(error instanceof Error ? error.message : String(error), undefined);
1743
- healthyMessage = `working now (live check failed: ${message})`;
1764
+ healthyMessage = `signed in (live check failed: ${message})`;
1744
1765
  }
1745
1766
  }
1746
1767
  }
1747
1768
  }
1748
1769
  if (display.showPerAccountRows) {
1749
- console.log(` ${stylePromptText("✓", "success")} ${labelText} ${stylePromptText("|", "muted")} ${styleAccountDetailText(healthyMessage)}`);
1770
+ const healthyMarker = healthyTone === "success" ? "✓" : "!";
1771
+ console.log(` ${stylePromptText(healthyMarker, healthyTone)} ${labelText} ${stylePromptText("|", "muted")} ${styleAccountDetailText(healthyMessage, healthyTone)}`);
1750
1772
  }
1751
1773
  }
1752
1774
  else {
1753
1775
  const detail = normalizeFailureDetail(result.message, result.reason);
1754
1776
  if (sessionLikelyValid) {
1755
1777
  warnings += 1;
1778
+ if (liveProbe) {
1779
+ signedInOnly += 1;
1780
+ }
1756
1781
  if (display.showPerAccountRows) {
1757
1782
  console.log(` ${stylePromptText("!", "warning")} ${labelText} ${stylePromptText("|", "muted")} ${stylePromptText(`refresh failed (${detail}) but this account still works right now`, "warning")}`);
1758
1783
  }
@@ -1796,17 +1821,32 @@ async function runHealthCheck(options = {}) {
1796
1821
  }
1797
1822
  }
1798
1823
  console.log("");
1799
- console.log(formatResultSummary([
1800
- { text: `${ok} working`, tone: "success" },
1801
- {
1802
- text: `${failed} need re-login`,
1803
- tone: failed > 0 ? "danger" : "muted",
1804
- },
1805
- {
1806
- text: `${warnings} warning${warnings === 1 ? "" : "s"}`,
1807
- tone: warnings > 0 ? "warning" : "muted",
1808
- },
1809
- ]));
1824
+ console.log(formatResultSummary(liveProbe
1825
+ ? [
1826
+ {
1827
+ text: `${codexAvailable} Codex available`,
1828
+ tone: codexAvailable > 0 ? "success" : "muted",
1829
+ },
1830
+ {
1831
+ text: `${signedInOnly} signed in only`,
1832
+ tone: signedInOnly > 0 ? "warning" : "muted",
1833
+ },
1834
+ {
1835
+ text: `${failed} need re-login`,
1836
+ tone: failed > 0 ? "danger" : "muted",
1837
+ },
1838
+ ]
1839
+ : [
1840
+ { text: `${ok} working`, tone: "success" },
1841
+ {
1842
+ text: `${failed} need re-login`,
1843
+ tone: failed > 0 ? "danger" : "muted",
1844
+ },
1845
+ {
1846
+ text: `${warnings} warning${warnings === 1 ? "" : "s"}`,
1847
+ tone: warnings > 0 ? "warning" : "muted",
1848
+ },
1849
+ ]));
1810
1850
  }
1811
1851
  function printBestUsage() {
1812
1852
  console.log([
@@ -1816,7 +1856,7 @@ function printBestUsage() {
1816
1856
  "Options:",
1817
1857
  " --live, -l Probe live quota headers via Codex backend before switching",
1818
1858
  " --json, -j Print machine-readable JSON output",
1819
- " --model, -m Probe model for live mode (default: gpt-5.3-codex)",
1859
+ ` --model, -m Probe model for live mode (default: ${DEFAULT_LIVE_PROBE_MODEL})`,
1820
1860
  "",
1821
1861
  "Behavior:",
1822
1862
  " - Chooses the healthiest account using forecast scoring",
@@ -1827,7 +1867,7 @@ function parseBestArgs(args) {
1827
1867
  const options = {
1828
1868
  live: false,
1829
1869
  json: false,
1830
- model: "gpt-5.3-codex",
1870
+ model: DEFAULT_LIVE_PROBE_MODEL,
1831
1871
  modelProvided: false,
1832
1872
  };
1833
1873
  for (let i = 0; i < args.length; i += 1) {
@@ -1843,8 +1883,8 @@ function parseBestArgs(args) {
1843
1883
  continue;
1844
1884
  }
1845
1885
  if (arg === "--model" || arg === "-m") {
1846
- const value = args[i + 1];
1847
- if (!value) {
1886
+ const value = args[i + 1]?.trim();
1887
+ if (!value || value.startsWith("-")) {
1848
1888
  return { ok: false, message: "Missing value for --model" };
1849
1889
  }
1850
1890
  options.model = value;
@@ -1854,7 +1894,7 @@ function parseBestArgs(args) {
1854
1894
  }
1855
1895
  if (arg.startsWith("--model=")) {
1856
1896
  const value = arg.slice("--model=".length).trim();
1857
- if (!value) {
1897
+ if (!value || value.startsWith("-")) {
1858
1898
  return { ok: false, message: "Missing value for --model" };
1859
1899
  }
1860
1900
  options.model = value;