codex-multi-auth 2.19.0 → 2.20.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 (107) hide show
  1. package/.codex-plugin/plugin.json +9 -9
  2. package/LICENSE +21 -21
  3. package/README.md +149 -148
  4. package/assets/codex-multi-auth-icon.svg +39 -39
  5. package/assets/readme-hero.svg +31 -31
  6. package/config/README.md +31 -31
  7. package/config/codex-legacy.json +1021 -1021
  8. package/config/codex-modern.json +347 -347
  9. package/config/minimal-codex.json +15 -15
  10. package/dist/index.js +1 -1
  11. package/dist/lib/accounts/rate-limits.js +5 -0
  12. package/dist/lib/accounts.js +5 -4
  13. package/dist/lib/auth/account-access.js +2 -2
  14. package/dist/lib/codex-cli/version.d.ts +22 -0
  15. package/dist/lib/codex-cli/version.js +78 -0
  16. package/dist/lib/codex-manager/commands/limits.d.ts +2 -0
  17. package/dist/lib/codex-manager/commands/limits.js +31 -0
  18. package/dist/lib/codex-manager/commands/status.js +1 -1
  19. package/dist/lib/codex-manager/dashboard-settings-data.js +2 -0
  20. package/dist/lib/codex-manager/formatters/subscription-status.d.ts +2 -2
  21. package/dist/lib/codex-manager/formatters/text-style.js +4 -1
  22. package/dist/lib/codex-manager/settings-hub/dashboard.d.ts +1 -1
  23. package/dist/lib/codex-manager/settings-hub/dashboard.js +4 -0
  24. package/dist/lib/codex-manager/settings-panels.d.ts +1 -0
  25. package/dist/lib/codex-manager/settings-panels.js +1 -0
  26. package/dist/lib/codex-manager/theme-settings-panel.d.ts +2 -1
  27. package/dist/lib/codex-manager/theme-settings-panel.js +39 -0
  28. package/dist/lib/codex-manager.js +2 -0
  29. package/dist/lib/constants.d.ts +2 -0
  30. package/dist/lib/constants.js +2 -0
  31. package/dist/lib/context-budget/model-context-windows.d.ts +1 -1
  32. package/dist/lib/context-budget/model-context-windows.js +4 -0
  33. package/dist/lib/context-budget-response.js +8 -8
  34. package/dist/lib/context-overflow.js +10 -10
  35. package/dist/lib/dashboard-settings.d.ts +2 -0
  36. package/dist/lib/dashboard-settings.js +18 -0
  37. package/dist/lib/luna-reserve.d.ts +26 -0
  38. package/dist/lib/luna-reserve.js +68 -0
  39. package/dist/lib/model-route-policy.d.ts +5 -5
  40. package/dist/lib/oauth-success.html +125 -125
  41. package/dist/lib/policy/runtime-policy.js +14 -0
  42. package/dist/lib/prompts/codex-host-bridge.js +138 -138
  43. package/dist/lib/prompts/codex.js +79 -79
  44. package/dist/lib/quota-readiness.d.ts +2 -2
  45. package/dist/lib/request/helpers/model-map.d.ts +1 -1
  46. package/dist/lib/request/helpers/model-map.js +12 -0
  47. package/dist/lib/request/response-outcome.d.ts +1 -1
  48. package/dist/lib/request/response-outcome.js +4 -1
  49. package/dist/lib/request/url-rewriting.js +3 -1
  50. package/dist/lib/runtime/account-model-catalog.d.ts +5 -5
  51. package/dist/lib/runtime/account-reset-credits.d.ts +2 -2
  52. package/dist/lib/runtime/account-status.js +2 -1
  53. package/dist/lib/runtime/luna-reserve-usage.d.ts +9 -0
  54. package/dist/lib/runtime/luna-reserve-usage.js +68 -0
  55. package/dist/lib/runtime/model-discovery-status.d.ts +11 -7
  56. package/dist/lib/runtime/model-discovery-status.js +13 -5
  57. package/dist/lib/runtime/reset-credit-routing.js +4 -1
  58. package/dist/lib/runtime/reset-credits.d.ts +7 -7
  59. package/dist/lib/runtime/resume-picker.js +1 -1
  60. package/dist/lib/runtime/rotation-server-types.d.ts +2 -0
  61. package/dist/lib/runtime/runtime-observability.d.ts +2 -0
  62. package/dist/lib/runtime/runtime-observability.js +1 -0
  63. package/dist/lib/runtime/workspace-model-scopes.d.ts +3 -3
  64. package/dist/lib/runtime-rotation-proxy.js +200 -32
  65. package/dist/lib/schemas.d.ts +65 -65
  66. package/dist/lib/ui/index.d.ts +1 -1
  67. package/dist/lib/ui/index.js +1 -1
  68. package/dist/lib/ui/runtime.d.ts +3 -1
  69. package/dist/lib/ui/runtime.js +11 -1
  70. package/dist/lib/ui/theme.d.ts +20 -1
  71. package/dist/lib/ui/theme.js +154 -30
  72. package/dist/lib/ui/ui-copy.d.ts +3 -2
  73. package/dist/lib/ui/ui-copy.js +3 -2
  74. package/dist/lib/usage/pricing.d.ts +1 -1
  75. package/dist/lib/usage/pricing.js +4 -0
  76. package/dist/lib/usage/usage-extraction.d.ts +2 -0
  77. package/dist/lib/usage/usage-extraction.js +25 -1
  78. package/dist/lib/utils.d.ts +1 -1
  79. package/dist/lib/utils.js +1 -1
  80. package/node_modules/@codex-ai/plugin/dist/index.d.ts +2 -2
  81. package/node_modules/@codex-ai/plugin/dist/index.js +2 -2
  82. package/node_modules/@codex-ai/plugin/dist/tool.d.ts +42 -42
  83. package/node_modules/@codex-ai/plugin/dist/tool.js +29 -29
  84. package/node_modules/@codex-ai/plugin/package.json +9 -9
  85. package/node_modules/@codex-ai/sdk/dist/index.d.ts +4 -4
  86. package/node_modules/@codex-ai/sdk/dist/index.js +2 -2
  87. package/node_modules/@codex-ai/sdk/package.json +8 -8
  88. package/package.json +207 -206
  89. package/scripts/codex-app-launcher.js +653 -653
  90. package/scripts/codex-app-router.js +374 -373
  91. package/scripts/codex-bin-resolver.js +332 -332
  92. package/scripts/codex-multi-auth.js +65 -65
  93. package/scripts/codex-routing.js +62 -62
  94. package/scripts/codex.js +7006 -7005
  95. package/scripts/install-codex-auth-utils.js +213 -213
  96. package/scripts/mcodex.js +367 -367
  97. package/scripts/postinstall.js +114 -114
  98. package/scripts/preuninstall.js +265 -265
  99. package/skills/codex-auth-setup/SKILL.md +73 -73
  100. package/vendor/codex-ai-plugin/dist/index.d.ts +2 -2
  101. package/vendor/codex-ai-plugin/dist/index.js +2 -2
  102. package/vendor/codex-ai-plugin/dist/tool.d.ts +42 -42
  103. package/vendor/codex-ai-plugin/dist/tool.js +29 -29
  104. package/vendor/codex-ai-plugin/package.json +9 -9
  105. package/vendor/codex-ai-sdk/dist/index.d.ts +4 -4
  106. package/vendor/codex-ai-sdk/dist/index.js +2 -2
  107. package/vendor/codex-ai-sdk/package.json +8 -8
@@ -19,6 +19,7 @@ export const DEFAULT_DASHBOARD_DISPLAY_SETTINGS = {
19
19
  menuSortQuickSwitchVisibleRow: true,
20
20
  uiThemePreset: "green",
21
21
  uiAccentColor: "green",
22
+ uiColorMode: "auto",
22
23
  menuShowStatusBadge: true,
23
24
  menuShowCurrentBadge: true,
24
25
  menuShowLastUsed: true,
@@ -102,6 +103,22 @@ function normalizeAccentColor(value) {
102
103
  return "green";
103
104
  }
104
105
  }
106
+ /**
107
+ * Normalize an input value into a dashboard terminal-background mode.
108
+ *
109
+ * @param value - Input value to coerce into a color mode
110
+ * @returns `'dark'` or `'light'` if `value` matches one of those strings; otherwise `'auto'` (terminal detection)
111
+ */
112
+ function normalizeColorMode(value) {
113
+ switch (value) {
114
+ case "dark":
115
+ return "dark";
116
+ case "light":
117
+ return "light";
118
+ default:
119
+ return "auto";
120
+ }
121
+ }
105
122
  /**
106
123
  * Validate a dashboard layout mode, allowing only "expanded-rows".
107
124
  *
@@ -249,6 +266,7 @@ export function normalizeDashboardDisplaySettings(value) {
249
266
  menuSortQuickSwitchVisibleRow: normalizeBoolean(value.menuSortQuickSwitchVisibleRow, DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuSortQuickSwitchVisibleRow ?? true),
250
267
  uiThemePreset: normalizeThemePreset(value.uiThemePreset),
251
268
  uiAccentColor: normalizeAccentColor(value.uiAccentColor),
269
+ uiColorMode: normalizeColorMode(value.uiColorMode),
252
270
  menuShowStatusBadge: normalizeBoolean(value.menuShowStatusBadge, DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuShowStatusBadge ?? true),
253
271
  menuShowCurrentBadge: normalizeBoolean(value.menuShowCurrentBadge, DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuShowCurrentBadge ?? true),
254
272
  menuShowLastUsed: normalizeBoolean(value.menuShowLastUsed, DEFAULT_DASHBOARD_DISPLAY_SETTINGS.menuShowLastUsed ?? true),
@@ -0,0 +1,26 @@
1
+ import { LUNA_RESERVE_MODEL } from "./constants.js";
2
+ export interface LunaReserveWindow {
3
+ usedPercent: number | null;
4
+ remainingPercent: number | null;
5
+ windowMinutes: number | null;
6
+ resetAtMs: number | null;
7
+ }
8
+ export interface LunaReserveSnapshot {
9
+ observedAt: number;
10
+ offered: boolean;
11
+ available: boolean | null;
12
+ limitId: string | null;
13
+ limitName: typeof LUNA_RESERVE_MODEL | null;
14
+ normalModelSlug: string | null;
15
+ primary: LunaReserveWindow | null;
16
+ secondary: LunaReserveWindow | null;
17
+ }
18
+ /**
19
+ * Parse the official Codex app-server `account/rateLimits/read` response for
20
+ * the separately metered Luna Reserve bucket.
21
+ *
22
+ * Absence is intentionally represented as `offered:false`, never as 0% left:
23
+ * the backend may omit Reserve when an account is not currently eligible or
24
+ * when the experiment is not active for that account.
25
+ */
26
+ export declare function parseLunaReserveRateLimits(value: unknown, observedAt?: number): LunaReserveSnapshot;
@@ -0,0 +1,68 @@
1
+ import { LUNA_RESERVE_MODEL } from "./constants.js";
2
+ import { isRecord } from "./utils.js";
3
+ /** Return a finite numeric value or null for malformed backend data. */
4
+ function finiteNumber(value) {
5
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
6
+ }
7
+ /** Normalize backend percentages into the inclusive 0-100 range. */
8
+ function clampPercent(value) {
9
+ const number = finiteNumber(value);
10
+ return number === null ? null : Math.max(0, Math.min(100, number));
11
+ }
12
+ /** Parse one Reserve usage window without inventing missing values. */
13
+ function parseWindow(value) {
14
+ if (!isRecord(value))
15
+ return null;
16
+ const usedPercent = clampPercent(value.usedPercent);
17
+ const duration = finiteNumber(value.windowDurationMins);
18
+ const resetSeconds = finiteNumber(value.resetsAt);
19
+ return {
20
+ usedPercent,
21
+ remainingPercent: usedPercent === null ? null : Math.max(0, 100 - usedPercent),
22
+ windowMinutes: duration === null || duration < 0 ? null : duration,
23
+ resetAtMs: resetSeconds === null || resetSeconds <= 0 ? null : resetSeconds * 1000,
24
+ };
25
+ }
26
+ /**
27
+ * Parse the official Codex app-server `account/rateLimits/read` response for
28
+ * the separately metered Luna Reserve bucket.
29
+ *
30
+ * Absence is intentionally represented as `offered:false`, never as 0% left:
31
+ * the backend may omit Reserve when an account is not currently eligible or
32
+ * when the experiment is not active for that account.
33
+ */
34
+ export function parseLunaReserveRateLimits(value, observedAt = Date.now()) {
35
+ const absent = {
36
+ observedAt,
37
+ offered: false,
38
+ available: null,
39
+ limitId: null,
40
+ limitName: null,
41
+ normalModelSlug: null,
42
+ primary: null,
43
+ secondary: null,
44
+ };
45
+ if (!isRecord(value) || !isRecord(value.rateLimitsByLimitId))
46
+ return absent;
47
+ for (const [limitId, candidate] of Object.entries(value.rateLimitsByLimitId)) {
48
+ if (!isRecord(candidate) || candidate.limitName !== LUNA_RESERVE_MODEL)
49
+ continue;
50
+ const primary = parseWindow(candidate.primary);
51
+ const secondary = parseWindow(candidate.secondary);
52
+ const knownWindows = [primary, secondary].filter((window) => window !== null && window.usedPercent !== null);
53
+ const exhausted = knownWindows.some((window) => (window.usedPercent ?? 0) >= 100);
54
+ return {
55
+ observedAt,
56
+ offered: true,
57
+ available: knownWindows.length === 0 ? null : !exhausted,
58
+ limitId: limitId || (typeof candidate.limitId === "string" ? candidate.limitId : null),
59
+ limitName: LUNA_RESERVE_MODEL,
60
+ normalModelSlug: typeof candidate.normalModelSlug === "string" && candidate.normalModelSlug.trim()
61
+ ? candidate.normalModelSlug.trim()
62
+ : null,
63
+ primary,
64
+ secondary,
65
+ };
66
+ }
67
+ return absent;
68
+ }
@@ -37,15 +37,15 @@ export declare function resolveModelRoute(model: string, catalogs: RouteCatalog[
37
37
  export declare function buildVisibleModelUnion(catalogs: RouteCatalog[]): RouteModel[];
38
38
  /** Whitelist capability metadata; never persist model instructions or arbitrary fields. */
39
39
  export declare function modelEntitlements(model: RouteModel): {
40
+ model: string;
41
+ checkedAt?: number | undefined;
42
+ probes?: {
43
+ [k: string]: "downgraded" | "unsupported" | "unverified" | "verified";
44
+ } | undefined;
40
45
  serviceTiers: {
41
46
  id: string;
42
47
  name: string;
43
48
  }[];
44
49
  reasoningLevels: string[];
45
50
  accessPrograms: string[];
46
- probes?: {
47
- [k: string]: "unsupported" | "verified" | "unverified" | "downgraded";
48
- } | undefined;
49
- checkedAt?: number | undefined;
50
- model: string;
51
51
  };
@@ -1,126 +1,126 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>Codex Sign-In Complete</title>
7
- <style>
8
- :root {
9
- color-scheme: dark;
10
- --bg: #0b0b0b;
11
- --panel: #111111;
12
- --text: #f2f2f2;
13
- --muted: #a3a3a3;
14
- --line: #232323;
15
- --ok: #7cf0a6;
16
- }
17
-
18
- * {
19
- box-sizing: border-box;
20
- }
21
-
22
- body {
23
- margin: 0;
24
- min-height: 100vh;
25
- display: grid;
26
- place-items: center;
27
- background: var(--bg);
28
- color: var(--text);
29
- font-family: "Geist Mono", "GeistMono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
30
- padding: 24px;
31
- }
32
-
33
- main {
34
- width: min(520px, 100%);
35
- background: var(--panel);
36
- border: 1px solid var(--line);
37
- border-radius: 12px;
38
- padding: 20px;
39
- display: grid;
40
- gap: 14px;
41
- }
42
-
43
- h1 {
44
- margin: 0;
45
- font-size: 20px;
46
- font-weight: 600;
47
- letter-spacing: -0.02em;
48
- }
49
-
50
- p {
51
- margin: 0;
52
- color: var(--muted);
53
- font-size: 14px;
54
- line-height: 1.5;
55
- }
56
-
57
- .status {
58
- display: inline-flex;
59
- align-items: center;
60
- gap: 8px;
61
- color: var(--ok);
62
- font-size: 13px;
63
- }
64
-
65
- .dot {
66
- width: 8px;
67
- height: 8px;
68
- border-radius: 50%;
69
- background: currentColor;
70
- }
71
-
72
- dl {
73
- margin: 0;
74
- display: grid;
75
- grid-template-columns: 120px 1fr;
76
- gap: 8px 12px;
77
- font-size: 13px;
78
- }
79
-
80
- dt {
81
- color: var(--muted);
82
- }
83
-
84
- dd {
85
- margin: 0;
86
- color: var(--text);
87
- word-break: break-word;
88
- }
89
-
90
- code {
91
- background: #171717;
92
- border: 1px solid var(--line);
93
- border-radius: 6px;
94
- padding: 2px 6px;
95
- font-family: inherit;
96
- font-size: 12px;
97
- }
98
-
99
- @media (max-width: 520px) {
100
- dl {
101
- grid-template-columns: 1fr;
102
- }
103
- }
104
- </style>
105
- </head>
106
- <body>
107
- <main role="main" aria-label="OAuth callback received">
108
- <h1>Sign-in complete</h1>
109
- <p>Return to your terminal to finish Codex login.</p>
110
-
111
- <div class="status" aria-live="polite">
112
- <span class="dot" aria-hidden="true"></span>
113
- Callback received
114
- </div>
115
-
116
- <dl>
117
- <dt>Endpoint</dt>
118
- <dd><code>localhost:1455</code></dd>
119
- <dt>Flow</dt>
120
- <dd>OAuth callback captured</dd>
121
- <dt>Next</dt>
122
- <dd>Close this tab and continue in terminal</dd>
123
- </dl>
124
- </main>
125
- </body>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Codex Sign-In Complete</title>
7
+ <style>
8
+ :root {
9
+ color-scheme: dark;
10
+ --bg: #0b0b0b;
11
+ --panel: #111111;
12
+ --text: #f2f2f2;
13
+ --muted: #a3a3a3;
14
+ --line: #232323;
15
+ --ok: #7cf0a6;
16
+ }
17
+
18
+ * {
19
+ box-sizing: border-box;
20
+ }
21
+
22
+ body {
23
+ margin: 0;
24
+ min-height: 100vh;
25
+ display: grid;
26
+ place-items: center;
27
+ background: var(--bg);
28
+ color: var(--text);
29
+ font-family: "Geist Mono", "GeistMono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
30
+ padding: 24px;
31
+ }
32
+
33
+ main {
34
+ width: min(520px, 100%);
35
+ background: var(--panel);
36
+ border: 1px solid var(--line);
37
+ border-radius: 12px;
38
+ padding: 20px;
39
+ display: grid;
40
+ gap: 14px;
41
+ }
42
+
43
+ h1 {
44
+ margin: 0;
45
+ font-size: 20px;
46
+ font-weight: 600;
47
+ letter-spacing: -0.02em;
48
+ }
49
+
50
+ p {
51
+ margin: 0;
52
+ color: var(--muted);
53
+ font-size: 14px;
54
+ line-height: 1.5;
55
+ }
56
+
57
+ .status {
58
+ display: inline-flex;
59
+ align-items: center;
60
+ gap: 8px;
61
+ color: var(--ok);
62
+ font-size: 13px;
63
+ }
64
+
65
+ .dot {
66
+ width: 8px;
67
+ height: 8px;
68
+ border-radius: 50%;
69
+ background: currentColor;
70
+ }
71
+
72
+ dl {
73
+ margin: 0;
74
+ display: grid;
75
+ grid-template-columns: 120px 1fr;
76
+ gap: 8px 12px;
77
+ font-size: 13px;
78
+ }
79
+
80
+ dt {
81
+ color: var(--muted);
82
+ }
83
+
84
+ dd {
85
+ margin: 0;
86
+ color: var(--text);
87
+ word-break: break-word;
88
+ }
89
+
90
+ code {
91
+ background: #171717;
92
+ border: 1px solid var(--line);
93
+ border-radius: 6px;
94
+ padding: 2px 6px;
95
+ font-family: inherit;
96
+ font-size: 12px;
97
+ }
98
+
99
+ @media (max-width: 520px) {
100
+ dl {
101
+ grid-template-columns: 1fr;
102
+ }
103
+ }
104
+ </style>
105
+ </head>
106
+ <body>
107
+ <main role="main" aria-label="OAuth callback received">
108
+ <h1>Sign-in complete</h1>
109
+ <p>Return to your terminal to finish Codex login.</p>
110
+
111
+ <div class="status" aria-live="polite">
112
+ <span class="dot" aria-hidden="true"></span>
113
+ Callback received
114
+ </div>
115
+
116
+ <dl>
117
+ <dt>Endpoint</dt>
118
+ <dd><code>localhost:1455</code></dd>
119
+ <dt>Flow</dt>
120
+ <dd>OAuth callback captured</dd>
121
+ <dt>Next</dt>
122
+ <dd>Close this tab and continue in terminal</dd>
123
+ </dl>
124
+ </main>
125
+ </body>
126
126
  </html>
@@ -1,3 +1,4 @@
1
+ import { logDebug } from "../logger.js";
1
2
  import { resolveEntitlementAccountKey } from "../entitlement-cache.js";
2
3
  import { getAccountPolicyKey, } from "../account-policy.js";
3
4
  import { evaluateBudgetGuard, getBudgetWindowStart, normalizeBudgetKey, } from "../budget-guard.js";
@@ -198,6 +199,19 @@ export function createRuntimeUsageRecorder(input) {
198
199
  if (recorded)
199
200
  return;
200
201
  recorded = true;
202
+ if (input.operation === "responses" && recordInput.outcome === "success" && ![
203
+ recordInput.inputTokens,
204
+ recordInput.outputTokens,
205
+ recordInput.cachedInputTokens,
206
+ recordInput.reasoningTokens,
207
+ recordInput.totalTokens,
208
+ ].some(count => typeof count === "number" && count > 0)) {
209
+ // Keep diagnostics free of account identities, credentials and body data.
210
+ logDebug("Successful Responses request has zero or missing token usage", {
211
+ source: input.source,
212
+ operation: input.operation,
213
+ });
214
+ }
201
215
  const account = recordInput.account;
202
216
  const row = {
203
217
  source: input.source,