codex-multi-auth 2.16.0 → 2.17.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.
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +22 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/lib/account-policy.d.ts +4 -0
- package/dist/lib/account-policy.d.ts.map +1 -1
- package/dist/lib/account-policy.js +8 -0
- package/dist/lib/accounts/rate-limits.d.ts.map +1 -1
- package/dist/lib/accounts/rate-limits.js +2 -0
- package/dist/lib/accounts.d.ts +21 -3
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +229 -17
- package/dist/lib/api-route-store.d.ts +24 -0
- package/dist/lib/api-route-store.d.ts.map +1 -0
- package/dist/lib/api-route-store.js +145 -0
- package/dist/lib/auth/account-access.d.ts +115 -0
- package/dist/lib/auth/account-access.d.ts.map +1 -0
- package/dist/lib/auth/account-access.js +214 -0
- package/dist/lib/auth/token-utils.d.ts +54 -1
- package/dist/lib/auth/token-utils.d.ts.map +1 -1
- package/dist/lib/auth/token-utils.js +92 -7
- package/dist/lib/cli.d.ts +1 -1
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +4 -0
- package/dist/lib/codex-cli/state.d.ts +7 -0
- package/dist/lib/codex-cli/state.d.ts.map +1 -1
- package/dist/lib/codex-cli/state.js +18 -0
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +60 -8
- package/dist/lib/codex-manager/account-manager-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/account-manager-commands.js +1 -0
- package/dist/lib/codex-manager/account-pool-write.d.ts +3 -1
- package/dist/lib/codex-manager/account-pool-write.d.ts.map +1 -1
- package/dist/lib/codex-manager/account-pool-write.js +4 -0
- package/dist/lib/codex-manager/api-login-menu.d.ts +14 -0
- package/dist/lib/codex-manager/api-login-menu.d.ts.map +1 -0
- package/dist/lib/codex-manager/api-login-menu.js +224 -0
- package/dist/lib/codex-manager/commands/account.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/account.js +27 -0
- package/dist/lib/codex-manager/commands/best.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/best.js +6 -2
- package/dist/lib/codex-manager/commands/check.d.ts +7 -1
- package/dist/lib/codex-manager/commands/check.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/check.js +24 -3
- package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/forecast.js +5 -1
- package/dist/lib/codex-manager/commands/report.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/report.js +5 -1
- package/dist/lib/codex-manager/commands/resets.d.ts +2 -0
- package/dist/lib/codex-manager/commands/resets.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/resets.js +67 -0
- package/dist/lib/codex-manager/commands/rotation.d.ts +2 -2
- package/dist/lib/codex-manager/commands/rotation.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/rotation.js +63 -12
- package/dist/lib/codex-manager/commands/status.d.ts +12 -1
- package/dist/lib/codex-manager/commands/status.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/status.js +166 -22
- package/dist/lib/codex-manager/commands/uninstall.js +1 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts.map +1 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.js +3 -2
- package/dist/lib/codex-manager/health-check.d.ts +3 -0
- package/dist/lib/codex-manager/health-check.d.ts.map +1 -1
- package/dist/lib/codex-manager/health-check.js +56 -6
- package/dist/lib/codex-manager/help.d.ts.map +1 -1
- package/dist/lib/codex-manager/help.js +4 -2
- package/dist/lib/codex-manager/login-flow.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-flow.js +69 -7
- package/dist/lib/codex-manager/login-menu-data.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-menu-data.js +14 -5
- package/dist/lib/codex-manager/login-oauth.d.ts +3 -0
- package/dist/lib/codex-manager/login-oauth.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-oauth.js +6 -1
- package/dist/lib/codex-manager/login-workspace-choice.d.ts +11 -0
- package/dist/lib/codex-manager/login-workspace-choice.d.ts.map +1 -0
- package/dist/lib/codex-manager/login-workspace-choice.js +37 -0
- package/dist/lib/codex-manager/persist-selected-account.d.ts.map +1 -1
- package/dist/lib/codex-manager/persist-selected-account.js +2 -1
- package/dist/lib/codex-manager/repair-commands.d.ts +13 -0
- package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/repair-commands.js +143 -8
- package/dist/lib/codex-manager.d.ts.map +1 -1
- package/dist/lib/codex-manager.js +25 -6
- package/dist/lib/concurrency.d.ts +3 -0
- package/dist/lib/concurrency.d.ts.map +1 -0
- package/dist/lib/concurrency.js +31 -0
- package/dist/lib/model-route-policy.d.ts +52 -0
- package/dist/lib/model-route-policy.d.ts.map +1 -0
- package/dist/lib/model-route-policy.js +159 -0
- package/dist/lib/policy/runtime-policy.d.ts +1 -0
- package/dist/lib/policy/runtime-policy.d.ts.map +1 -1
- package/dist/lib/policy/runtime-policy.js +3 -0
- package/dist/lib/preemptive-quota-scheduler.d.ts +2 -0
- package/dist/lib/preemptive-quota-scheduler.d.ts.map +1 -1
- package/dist/lib/preemptive-quota-scheduler.js +4 -0
- package/dist/lib/quota-probe.d.ts +5 -0
- package/dist/lib/quota-probe.d.ts.map +1 -1
- package/dist/lib/quota-probe.js +26 -2
- package/dist/lib/request/client-cancellation.d.ts +5 -0
- package/dist/lib/request/client-cancellation.d.ts.map +1 -0
- package/dist/lib/request/client-cancellation.js +7 -0
- package/dist/lib/request/response-outcome.d.ts +25 -0
- package/dist/lib/request/response-outcome.d.ts.map +1 -0
- package/dist/lib/request/response-outcome.js +49 -0
- package/dist/lib/request/stream-failover-runtime.d.ts +2 -1
- package/dist/lib/request/stream-failover-runtime.d.ts.map +1 -1
- package/dist/lib/request/stream-failover-runtime.js +29 -10
- package/dist/lib/runtime/account-check.d.ts.map +1 -1
- package/dist/lib/runtime/account-check.js +2 -8
- package/dist/lib/runtime/account-model-catalog.d.ts +64 -0
- package/dist/lib/runtime/account-model-catalog.d.ts.map +1 -0
- package/dist/lib/runtime/account-model-catalog.js +154 -0
- package/dist/lib/runtime/account-pool.d.ts +3 -1
- package/dist/lib/runtime/account-pool.d.ts.map +1 -1
- package/dist/lib/runtime/account-pool.js +4 -0
- package/dist/lib/runtime/account-reset-credits.d.ts +42 -0
- package/dist/lib/runtime/account-reset-credits.d.ts.map +1 -0
- package/dist/lib/runtime/account-reset-credits.js +82 -0
- package/dist/lib/runtime/api-model-capabilities.d.ts +30 -0
- package/dist/lib/runtime/api-model-capabilities.d.ts.map +1 -0
- package/dist/lib/runtime/api-model-capabilities.js +434 -0
- package/dist/lib/runtime/api-model-runtime.d.ts +42 -0
- package/dist/lib/runtime/api-model-runtime.d.ts.map +1 -0
- package/dist/lib/runtime/api-model-runtime.js +358 -0
- package/dist/lib/runtime/app-bind.d.ts +19 -1
- package/dist/lib/runtime/app-bind.d.ts.map +1 -1
- package/dist/lib/runtime/app-bind.js +79 -9
- package/dist/lib/runtime/automatic-account-checks.d.ts +31 -0
- package/dist/lib/runtime/automatic-account-checks.d.ts.map +1 -0
- package/dist/lib/runtime/automatic-account-checks.js +113 -0
- package/dist/lib/runtime/automatic-subscription-checks.d.ts +7 -0
- package/dist/lib/runtime/automatic-subscription-checks.d.ts.map +1 -0
- package/dist/lib/runtime/automatic-subscription-checks.js +57 -0
- package/dist/lib/runtime/catalog-capabilities.d.ts +8 -0
- package/dist/lib/runtime/catalog-capabilities.d.ts.map +1 -0
- package/dist/lib/runtime/catalog-capabilities.js +61 -0
- package/dist/lib/runtime/inference-activity.d.ts +15 -0
- package/dist/lib/runtime/inference-activity.d.ts.map +1 -0
- package/dist/lib/runtime/inference-activity.js +95 -0
- package/dist/lib/runtime/model-discovery-status.d.ts +100 -0
- package/dist/lib/runtime/model-discovery-status.d.ts.map +1 -0
- package/dist/lib/runtime/model-discovery-status.js +387 -0
- package/dist/lib/runtime/native-account-storage.d.ts +11 -0
- package/dist/lib/runtime/native-account-storage.d.ts.map +1 -0
- package/dist/lib/runtime/native-account-storage.js +50 -0
- package/dist/lib/runtime/native-account-sync.d.ts +19 -0
- package/dist/lib/runtime/native-account-sync.d.ts.map +1 -0
- package/dist/lib/runtime/native-account-sync.js +62 -0
- package/dist/lib/runtime/native-binding-lock.d.ts +3 -0
- package/dist/lib/runtime/native-binding-lock.d.ts.map +1 -0
- package/dist/lib/runtime/native-binding-lock.js +5 -0
- package/dist/lib/runtime/native-client-auth.d.ts +3 -0
- package/dist/lib/runtime/native-client-auth.d.ts.map +1 -0
- package/dist/lib/runtime/native-client-auth.js +42 -0
- package/dist/lib/runtime/native-provider-config.d.ts +4 -0
- package/dist/lib/runtime/native-provider-config.d.ts.map +1 -0
- package/dist/lib/runtime/native-provider-config.js +52 -0
- package/dist/lib/runtime/native-rate-limits.d.ts +18 -0
- package/dist/lib/runtime/native-rate-limits.d.ts.map +1 -0
- package/dist/lib/runtime/native-rate-limits.js +135 -0
- package/dist/lib/runtime/reset-credit-routing.d.ts +41 -0
- package/dist/lib/runtime/reset-credit-routing.d.ts.map +1 -0
- package/dist/lib/runtime/reset-credit-routing.js +66 -0
- package/dist/lib/runtime/reset-credits.d.ts +101 -0
- package/dist/lib/runtime/reset-credits.d.ts.map +1 -0
- package/dist/lib/runtime/reset-credits.js +162 -0
- package/dist/lib/runtime/response-output-history.d.ts +17 -0
- package/dist/lib/runtime/response-output-history.d.ts.map +1 -0
- package/dist/lib/runtime/response-output-history.js +85 -0
- package/dist/lib/runtime/responses-websocket.d.ts +31 -0
- package/dist/lib/runtime/responses-websocket.d.ts.map +1 -0
- package/dist/lib/runtime/responses-websocket.js +636 -0
- package/dist/lib/runtime/resume-picker.d.ts +41 -0
- package/dist/lib/runtime/resume-picker.d.ts.map +1 -0
- package/dist/lib/runtime/resume-picker.js +169 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts +6 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-account-selection.js +63 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts +33 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-server-types.d.ts +18 -0
- package/dist/lib/runtime/rotation-server-types.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-capability-failures.d.ts +14 -0
- package/dist/lib/runtime/runtime-capability-failures.d.ts.map +1 -0
- package/dist/lib/runtime/runtime-capability-failures.js +76 -0
- package/dist/lib/runtime/runtime-observability.d.ts +7 -0
- package/dist/lib/runtime/runtime-observability.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-observability.js +42 -2
- package/dist/lib/runtime/subscription-first-use.d.ts +10 -0
- package/dist/lib/runtime/subscription-first-use.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-first-use.js +64 -0
- package/dist/lib/runtime/subscription-quota-event.d.ts +6 -0
- package/dist/lib/runtime/subscription-quota-event.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-quota-event.js +31 -0
- package/dist/lib/runtime/subscription-quota-order.d.ts +17 -0
- package/dist/lib/runtime/subscription-quota-order.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-quota-order.js +31 -0
- package/dist/lib/runtime/workspace-model-scopes.d.ts +15 -0
- package/dist/lib/runtime/workspace-model-scopes.d.ts.map +1 -0
- package/dist/lib/runtime/workspace-model-scopes.js +34 -0
- package/dist/lib/runtime-constants.d.ts +3 -0
- package/dist/lib/runtime-constants.d.ts.map +1 -1
- package/dist/lib/runtime-constants.js +5 -0
- package/dist/lib/runtime-paths.d.ts.map +1 -1
- package/dist/lib/runtime-paths.js +4 -1
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +852 -42
- package/dist/lib/schemas.d.ts +20 -0
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +3 -0
- package/dist/lib/storage/credential-sidecars.d.ts +13 -0
- package/dist/lib/storage/credential-sidecars.d.ts.map +1 -0
- package/dist/lib/storage/credential-sidecars.js +52 -0
- package/dist/lib/storage/file-lock.d.ts +9 -0
- package/dist/lib/storage/file-lock.d.ts.map +1 -0
- package/dist/lib/storage/file-lock.js +186 -0
- package/dist/lib/storage/flagged-storage.d.ts.map +1 -1
- package/dist/lib/storage/flagged-storage.js +12 -0
- package/dist/lib/storage/path-state.d.ts +2 -0
- package/dist/lib/storage/path-state.d.ts.map +1 -1
- package/dist/lib/storage/path-state.js +9 -0
- package/dist/lib/storage/paths.js +4 -4
- package/dist/lib/storage/pending-auth.d.ts +17 -0
- package/dist/lib/storage/pending-auth.d.ts.map +1 -0
- package/dist/lib/storage/pending-auth.js +153 -0
- package/dist/lib/storage/public-types.d.ts +13 -0
- package/dist/lib/storage/public-types.d.ts.map +1 -1
- package/dist/lib/storage/snapshot-merge.d.ts +16 -0
- package/dist/lib/storage/snapshot-merge.d.ts.map +1 -0
- package/dist/lib/storage/snapshot-merge.js +206 -0
- package/dist/lib/storage/transactions.d.ts.map +1 -1
- package/dist/lib/storage/transactions.js +5 -4
- package/dist/lib/storage.d.ts +6 -0
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +77 -7
- package/dist/lib/ui/auth-menu-builder.d.ts +2 -0
- package/dist/lib/ui/auth-menu-builder.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu-builder.js +1 -0
- package/dist/lib/ui/auth-menu.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.js +1 -0
- package/dist/lib/ui/check-progress.d.ts +8 -0
- package/dist/lib/ui/check-progress.d.ts.map +1 -0
- package/dist/lib/ui/check-progress.js +30 -0
- package/dist/lib/ui/format.d.ts +3 -1
- package/dist/lib/ui/format.d.ts.map +1 -1
- package/dist/lib/ui/format.js +8 -0
- package/dist/lib/ui/ui-copy.d.ts +2 -2
- package/dist/lib/ui/ui-copy.js +2 -2
- package/dist/lib/usage/pricing.js +2 -2
- package/dist/lib/usage/usage-extraction.d.ts +3 -1
- package/dist/lib/usage/usage-extraction.d.ts.map +1 -1
- package/dist/lib/usage/usage-extraction.js +46 -9
- package/package.json +7 -4
- package/scripts/codex-app-router.js +7 -0
- package/scripts/codex-bin-resolver.js +40 -8
- package/scripts/codex-routing.js +1 -0
- package/scripts/codex.js +100 -22
package/dist/lib/ui/ui-copy.js
CHANGED
|
@@ -144,8 +144,8 @@ export const UI_COPY = {
|
|
|
144
144
|
fallback: {
|
|
145
145
|
addAnotherTip: "Tip: Use private mode or sign out before adding another account.",
|
|
146
146
|
addAnotherQuestion: (count) => `Add another account? (${count} added) (y/n): `,
|
|
147
|
-
selectModePrompt: "(a) add, (c) check, (b) best, fi(x), (s) settings, (d) deep, (g) problem, (f) fresh, (q) back [a/c/b/x/s/d/g/f/q]: ",
|
|
148
|
-
invalidModePrompt: "Use one of: a, c, b, x, s, d, g, f, q.",
|
|
147
|
+
selectModePrompt: "(api) API models, (a) add, (c) check, (b) best, fi(x), (s) settings, (d) deep, (g) problem, (f) fresh, (q) back [api/a/c/b/x/s/d/g/f/q]: ",
|
|
148
|
+
invalidModePrompt: "Use one of: api, a, c, b, x, s, d, g, f, q.",
|
|
149
149
|
},
|
|
150
150
|
};
|
|
151
151
|
/**
|
|
@@ -159,7 +159,7 @@ function normalizeModelName(model) {
|
|
|
159
159
|
return trimmed && trimmed.length > 0 ? trimmed : null;
|
|
160
160
|
}
|
|
161
161
|
export function getUsageModelPricing(model) {
|
|
162
|
-
const normalized = normalizeModelName(model);
|
|
162
|
+
const normalized = normalizeModelName(model?.replace(/^(api|zdr)\//, ""));
|
|
163
163
|
if (!normalized) {
|
|
164
164
|
return null;
|
|
165
165
|
}
|
|
@@ -177,7 +177,7 @@ export function getUsageModelPricing(model) {
|
|
|
177
177
|
// `gpt-5.6-sol` request; pricing it at the retired model's old rate would
|
|
178
178
|
// under-count a `maxCostUsd` budget. Rows already on disk are unaffected:
|
|
179
179
|
// the ledger stores `costUsd` when a row is written and never re-prices it.
|
|
180
|
-
const effective = Object.hasOwn(RETIRED_MODEL_REPLACEMENTS, normalized)
|
|
180
|
+
const effective = !/^(api|zdr)\//.test(model ?? "") && Object.hasOwn(RETIRED_MODEL_REPLACEMENTS, normalized)
|
|
181
181
|
? RETIRED_MODEL_REPLACEMENTS[normalized]
|
|
182
182
|
: normalized;
|
|
183
183
|
if (!effective || !Object.hasOwn(MODEL_PRICING, effective)) {
|
|
@@ -30,7 +30,7 @@ export interface UsageStreamScanner {
|
|
|
30
30
|
/**
|
|
31
31
|
* Observe a forwarded response body and recover its token counts.
|
|
32
32
|
*
|
|
33
|
-
* SSE bodies are scanned
|
|
33
|
+
* SSE bodies are scanned frame by frame so only the current bounded event is
|
|
34
34
|
* retained; a full response can be gigabytes of deltas and must never be
|
|
35
35
|
* buffered. Non-SSE JSON bodies have no incremental structure to exploit, so
|
|
36
36
|
* they are accumulated up to `MAX_BUFFERED_BYTES` and parsed at the end —
|
|
@@ -39,5 +39,7 @@ export interface UsageStreamScanner {
|
|
|
39
39
|
*/
|
|
40
40
|
export declare function createUsageStreamScanner(options: {
|
|
41
41
|
contentType?: string | null;
|
|
42
|
+
/** Observe parsed upstream events without reparsing the stream. */
|
|
43
|
+
onEvent?: (event: unknown) => void;
|
|
42
44
|
}): UsageStreamScanner;
|
|
43
45
|
//# sourceMappingURL=usage-extraction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage-extraction.d.ts","sourceRoot":"","sources":["../../../lib/usage/usage-extraction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA+BrE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,OAAO,GACZ,gBAAgB,GAAG,IAAI,CA+BzB;AAoCD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAa/E;AAED,MAAM,WAAW,kBAAkB;IAClC,8CAA8C;IAC9C,IAAI,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAClC,2EAA2E;IAC3E,MAAM,EAAE,MAAM,gBAAgB,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IACjD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"usage-extraction.d.ts","sourceRoot":"","sources":["../../../lib/usage/usage-extraction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA+BrE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,OAAO,GACZ,gBAAgB,GAAG,IAAI,CA+BzB;AAoCD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAa/E;AAED,MAAM,WAAW,kBAAkB;IAClC,8CAA8C;IAC9C,IAAI,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAClC,2EAA2E;IAC3E,MAAM,EAAE,MAAM,gBAAgB,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IACjD,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mEAAmE;IACnE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACnC,GAAG,kBAAkB,CAmGrB"}
|
|
@@ -124,7 +124,7 @@ export function extractResponsesUsage(payload) {
|
|
|
124
124
|
/**
|
|
125
125
|
* Observe a forwarded response body and recover its token counts.
|
|
126
126
|
*
|
|
127
|
-
* SSE bodies are scanned
|
|
127
|
+
* SSE bodies are scanned frame by frame so only the current bounded event is
|
|
128
128
|
* retained; a full response can be gigabytes of deltas and must never be
|
|
129
129
|
* buffered. Non-SSE JSON bodies have no incremental structure to exploit, so
|
|
130
130
|
* they are accumulated up to `MAX_BUFFERED_BYTES` and parsed at the end —
|
|
@@ -138,11 +138,20 @@ export function createUsageStreamScanner(options) {
|
|
|
138
138
|
let bufferedBytes = 0;
|
|
139
139
|
let overflowed = false;
|
|
140
140
|
let latest = null;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
let eventData = [];
|
|
142
|
+
let eventSize = 0;
|
|
143
|
+
let droppingEvent = false;
|
|
144
|
+
let droppingLine = false;
|
|
145
|
+
const consumeEvent = () => {
|
|
146
|
+
if (droppingEvent) {
|
|
147
|
+
droppingEvent = false;
|
|
148
|
+
eventData = [];
|
|
149
|
+
eventSize = 0;
|
|
144
150
|
return;
|
|
145
|
-
|
|
151
|
+
}
|
|
152
|
+
const payload = eventData.join("\n");
|
|
153
|
+
eventData = [];
|
|
154
|
+
eventSize = 0;
|
|
146
155
|
if (payload.length === 0 || payload === "[DONE]")
|
|
147
156
|
return;
|
|
148
157
|
let parsed;
|
|
@@ -152,6 +161,7 @@ export function createUsageStreamScanner(options) {
|
|
|
152
161
|
catch {
|
|
153
162
|
return;
|
|
154
163
|
}
|
|
164
|
+
options.onEvent?.(parsed);
|
|
155
165
|
// Prefer terminal events, which carry the authoritative totals, but fall
|
|
156
166
|
// back to any event that reports usage so a stream that ends on a
|
|
157
167
|
// non-standard terminal type still records something.
|
|
@@ -162,6 +172,24 @@ export function createUsageStreamScanner(options) {
|
|
|
162
172
|
latest = counts;
|
|
163
173
|
}
|
|
164
174
|
};
|
|
175
|
+
const consumeLine = (raw) => {
|
|
176
|
+
const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
|
|
177
|
+
if (line.length === 0) {
|
|
178
|
+
consumeEvent();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (droppingEvent || !line.startsWith("data:"))
|
|
182
|
+
return;
|
|
183
|
+
const value = line.slice(5).replace(/^ /, "");
|
|
184
|
+
eventSize += value.length + 1;
|
|
185
|
+
if (eventSize > MAX_BUFFERED_BYTES) {
|
|
186
|
+
droppingEvent = true;
|
|
187
|
+
eventData = [];
|
|
188
|
+
eventSize = 0;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
eventData.push(value);
|
|
192
|
+
};
|
|
165
193
|
return {
|
|
166
194
|
push: (chunk) => {
|
|
167
195
|
try {
|
|
@@ -178,14 +206,20 @@ export function createUsageStreamScanner(options) {
|
|
|
178
206
|
}
|
|
179
207
|
let newlineAt = pending.indexOf("\n");
|
|
180
208
|
while (newlineAt !== -1) {
|
|
181
|
-
|
|
209
|
+
if (droppingLine)
|
|
210
|
+
droppingLine = false;
|
|
211
|
+
else
|
|
212
|
+
consumeLine(pending.slice(0, newlineAt));
|
|
182
213
|
pending = pending.slice(newlineAt + 1);
|
|
183
214
|
newlineAt = pending.indexOf("\n");
|
|
184
215
|
}
|
|
185
216
|
// A single unterminated line this long is not SSE any more; stop
|
|
186
217
|
// retaining it rather than growing the buffer for the whole body.
|
|
187
|
-
if (pending.length > MAX_BUFFERED_BYTES) {
|
|
188
|
-
|
|
218
|
+
if (pending.length > MAX_BUFFERED_BYTES || droppingLine) {
|
|
219
|
+
droppingEvent = true;
|
|
220
|
+
droppingLine = true;
|
|
221
|
+
eventData = [];
|
|
222
|
+
eventSize = 0;
|
|
189
223
|
pending = "";
|
|
190
224
|
}
|
|
191
225
|
}
|
|
@@ -202,13 +236,16 @@ export function createUsageStreamScanner(options) {
|
|
|
202
236
|
if (pending.length > 0)
|
|
203
237
|
consumeLine(pending);
|
|
204
238
|
pending = "";
|
|
239
|
+
consumeEvent();
|
|
205
240
|
return latest;
|
|
206
241
|
}
|
|
207
242
|
if (pending.trim().length === 0)
|
|
208
243
|
return latest;
|
|
209
244
|
const parsed = JSON.parse(pending);
|
|
210
245
|
pending = "";
|
|
211
|
-
|
|
246
|
+
options.onEvent?.(parsed);
|
|
247
|
+
latest = extractResponsesUsage(parsed) ?? latest;
|
|
248
|
+
return latest;
|
|
212
249
|
}
|
|
213
250
|
catch {
|
|
214
251
|
return latest;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-multi-auth",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.17.0",
|
|
4
4
|
"description": "Codex CLI multi-account OAuth manager with account switching, health checks, runtime rotation, diagnostics, and recovery tools for @openai/codex",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -157,6 +157,7 @@
|
|
|
157
157
|
},
|
|
158
158
|
"devDependencies": {
|
|
159
159
|
"@types/node": "^20.19.42",
|
|
160
|
+
"@types/ws": "8.18.1",
|
|
160
161
|
"@typescript-eslint/eslint-plugin": "^8.56.0",
|
|
161
162
|
"@typescript-eslint/parser": "^8.56.0",
|
|
162
163
|
"@vitest/coverage-v8": "^4.1.8",
|
|
@@ -174,12 +175,13 @@
|
|
|
174
175
|
"dependencies": {
|
|
175
176
|
"@codex-ai/plugin": "file:vendor/codex-ai-plugin",
|
|
176
177
|
"@codex-ai/sdk": "file:vendor/codex-ai-sdk",
|
|
177
|
-
"hono": "4.
|
|
178
|
+
"hono": "4.13.9",
|
|
178
179
|
"undici": "6.28.0",
|
|
180
|
+
"ws": "8.21.3",
|
|
179
181
|
"zod": "4.4.3"
|
|
180
182
|
},
|
|
181
183
|
"overrides": {
|
|
182
|
-
"hono": "4.
|
|
184
|
+
"hono": "4.13.9",
|
|
183
185
|
"flatted": "3.4.2",
|
|
184
186
|
"minimatch": "10.2.4",
|
|
185
187
|
"picomatch": "4.0.4",
|
|
@@ -192,6 +194,7 @@
|
|
|
192
194
|
"minimatch": "9.0.9"
|
|
193
195
|
},
|
|
194
196
|
"brace-expansion": "5.0.9",
|
|
195
|
-
"postcss": "8.5.25"
|
|
197
|
+
"postcss": "8.5.25",
|
|
198
|
+
"nanoid": "3.3.18"
|
|
196
199
|
}
|
|
197
200
|
}
|
|
@@ -177,11 +177,16 @@ function createStatusPayload({
|
|
|
177
177
|
baseUrl: proxyServer?.baseUrl ?? stateRecord?.baseUrl ?? null,
|
|
178
178
|
totalRequests: proxyStatus.totalRequests ?? 0,
|
|
179
179
|
upstreamRequests: proxyStatus.upstreamRequests ?? 0,
|
|
180
|
+
websocketConnections: proxyStatus.websocketConnections ?? 0,
|
|
181
|
+
websocketUpstreamRequests: proxyStatus.websocketUpstreamRequests ?? 0,
|
|
182
|
+
streamQuotaUpdates: proxyStatus.streamQuotaUpdates ?? 0,
|
|
183
|
+
lastStreamQuotaUpdateAt: proxyStatus.lastStreamQuotaUpdateAt ?? null,
|
|
180
184
|
retries: proxyStatus.retries ?? 0,
|
|
181
185
|
rotations: proxyStatus.rotations ?? 0,
|
|
182
186
|
lastAccountIndex,
|
|
183
187
|
lastAccountLabel,
|
|
184
188
|
lastAccountId: proxyStatus.lastAccountId ?? null,
|
|
189
|
+
lastRequestedWorkspaceId: proxyStatus.lastRequestedWorkspaceId ?? null,
|
|
185
190
|
lastAccountUpdatedAt: proxyStatus.lastAccountUpdatedAt ?? null,
|
|
186
191
|
lastError: error ? (error instanceof Error ? error.message : String(error)) : proxyStatus.lastError ?? null,
|
|
187
192
|
};
|
|
@@ -323,6 +328,8 @@ async function main() {
|
|
|
323
328
|
try {
|
|
324
329
|
const proxyModule = await import("../dist/lib/runtime-rotation-proxy.js");
|
|
325
330
|
proxyServer = await proxyModule.startRuntimeRotationProxy({
|
|
331
|
+
nativeOpenai: stateRecord?.nativeOpenai === true,
|
|
332
|
+
catalogAccount: stateRecord?.catalogAccount,
|
|
326
333
|
host,
|
|
327
334
|
port,
|
|
328
335
|
clientApiKey,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { existsSync, realpathSync } from "node:fs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
-
import { basename,
|
|
4
|
+
import { basename, dirname, extname, isAbsolute, join, posix, relative, win32 } from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
|
|
@@ -55,6 +55,29 @@ function defaultResolvePackageBin(moduleUrl) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// spawn() without a shell cannot run these on Windows: `.cmd`/`.bat` are
|
|
59
|
+
// EINVAL, `.ps1` is not an executable image, and an extensionless file
|
|
60
|
+
// (npm's `#!/bin/sh` shim) is ENOENT even when it is a real PE image. Going through cmd.exe instead would put every
|
|
61
|
+
// forwarded argument through cmd's quoting rules.
|
|
62
|
+
export function isWindowsShimPath(candidatePath) {
|
|
63
|
+
const extension = win32.extname(candidatePath).toLowerCase();
|
|
64
|
+
return extension === "" || extension === ".cmd" || extension === ".bat" || extension === ".ps1";
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// npm's Windows shims sit in the prefix dir and run
|
|
68
|
+
// `<prefix>\node_modules\@openai\codex\bin\codex.js`.
|
|
69
|
+
export function resolveWindowsShimPackageEntry(shimPath, existsSyncImpl = existsSync) {
|
|
70
|
+
const entry = win32.join(
|
|
71
|
+
win32.dirname(shimPath),
|
|
72
|
+
"node_modules",
|
|
73
|
+
"@openai",
|
|
74
|
+
"codex",
|
|
75
|
+
"bin",
|
|
76
|
+
"codex.js",
|
|
77
|
+
);
|
|
78
|
+
return existsSyncImpl(entry) ? entry : null;
|
|
79
|
+
}
|
|
80
|
+
|
|
58
81
|
function resolveWindowsCmdPath(env) {
|
|
59
82
|
const comSpec = (env.ComSpec ?? env.COMSPEC ?? "").trim();
|
|
60
83
|
if (comSpec.length > 0) return comSpec;
|
|
@@ -67,12 +90,12 @@ function resolveWindowsCmdPath(env) {
|
|
|
67
90
|
return "cmd.exe";
|
|
68
91
|
}
|
|
69
92
|
|
|
70
|
-
export function splitPathEntries(pathValue) {
|
|
93
|
+
export function splitPathEntries(pathValue, platform = process.platform) {
|
|
71
94
|
if (typeof pathValue !== "string" || pathValue.trim().length === 0) {
|
|
72
95
|
return [];
|
|
73
96
|
}
|
|
74
97
|
return pathValue
|
|
75
|
-
.split(
|
|
98
|
+
.split(platform === "win32" ? ";" : ":")
|
|
76
99
|
.map((entry) => entry.trim())
|
|
77
100
|
.filter((entry) => entry.length > 0);
|
|
78
101
|
}
|
|
@@ -85,7 +108,12 @@ function resolveCandidateExecutableNames(platform) {
|
|
|
85
108
|
if (platform !== "win32") {
|
|
86
109
|
return [resolvePathExecutableName(platform)];
|
|
87
110
|
}
|
|
88
|
-
|
|
111
|
+
// npm on Windows puts `codex.cmd` plus an extensionless `#!/bin/sh` shim in
|
|
112
|
+
// the prefix dir and the package under `<prefix>\node_modules`. Neither shim
|
|
113
|
+
// can be spawned without a shell (`.cmd` is EINVAL, the sh script ENOENT),
|
|
114
|
+
// so launch the package entry the shims point at before falling back to an
|
|
115
|
+
// extensionless `codex`.
|
|
116
|
+
return ["codex.exe", win32.join("node_modules", "@openai", "codex", "bin", "codex.js"), "codex"];
|
|
89
117
|
}
|
|
90
118
|
|
|
91
119
|
function resolveCodexExecutableFromPath(
|
|
@@ -97,7 +125,7 @@ function resolveCodexExecutableFromPath(
|
|
|
97
125
|
) {
|
|
98
126
|
for (const entry of pathEntries) {
|
|
99
127
|
for (const executableName of resolveCandidateExecutableNames(platform)) {
|
|
100
|
-
const candidate = join(entry, executableName);
|
|
128
|
+
const candidate = (platform === "win32" ? win32 : posix).join(entry, executableName);
|
|
101
129
|
if (!existsSyncImpl(candidate)) {
|
|
102
130
|
continue;
|
|
103
131
|
}
|
|
@@ -134,7 +162,7 @@ function resolveCodexExecutableFromSystemPath(
|
|
|
134
162
|
selfScriptPath,
|
|
135
163
|
realpathSyncImpl,
|
|
136
164
|
) {
|
|
137
|
-
const pathEntries = splitPathEntries(env.PATH ?? env.Path ?? "");
|
|
165
|
+
const pathEntries = splitPathEntries(env.PATH ?? env.Path ?? "", platform);
|
|
138
166
|
const fromEnvPath = resolveCodexExecutableFromPath(
|
|
139
167
|
pathEntries,
|
|
140
168
|
platform,
|
|
@@ -207,8 +235,12 @@ export function resolveRealCodexBin(options = {}) {
|
|
|
207
235
|
|
|
208
236
|
const override = (env.CODEX_MULTI_AUTH_REAL_CODEX_BIN ?? "").trim();
|
|
209
237
|
if (override.length > 0) {
|
|
210
|
-
if (existsSyncImpl(override)) return
|
|
211
|
-
|
|
238
|
+
if (!existsSyncImpl(override)) return null;
|
|
239
|
+
if (platform === "win32" && isWindowsShimPath(override)) {
|
|
240
|
+
const entry = resolveWindowsShimPackageEntry(override, existsSyncImpl);
|
|
241
|
+
return entry ? createResolvedCodexBin(entry) : null;
|
|
242
|
+
}
|
|
243
|
+
return createResolvedCodexBin(override);
|
|
212
244
|
}
|
|
213
245
|
|
|
214
246
|
const resolved = resolvePackageBin(moduleUrl);
|
package/scripts/codex-routing.js
CHANGED
package/scripts/codex.js
CHANGED
|
@@ -26,7 +26,9 @@ import process from "node:process";
|
|
|
26
26
|
import { StringDecoder } from "node:string_decoder";
|
|
27
27
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
28
28
|
import {
|
|
29
|
+
isWindowsShimPath,
|
|
29
30
|
resolveRealCodexBin as resolveRealCodexBinFromEnvironment,
|
|
31
|
+
resolveWindowsShimPackageEntry,
|
|
30
32
|
splitPathEntries,
|
|
31
33
|
} from "./codex-bin-resolver.js";
|
|
32
34
|
import { normalizeAuthAlias, shouldHandleMultiAuthAuth } from "./codex-routing.js";
|
|
@@ -1350,6 +1352,17 @@ function resolveRealCodexBin() {
|
|
|
1350
1352
|
);
|
|
1351
1353
|
return null;
|
|
1352
1354
|
}
|
|
1355
|
+
if (
|
|
1356
|
+
process.platform === "win32" &&
|
|
1357
|
+
isWindowsShimPath(override) &&
|
|
1358
|
+
!resolveWindowsShimPackageEntry(override)
|
|
1359
|
+
) {
|
|
1360
|
+
console.error(
|
|
1361
|
+
`CODEX_MULTI_AUTH_REAL_CODEX_BIN points at a script shim that cannot be launched directly on Windows: ${override}\n` +
|
|
1362
|
+
"Point it at codex.exe or @openai/codex/bin/codex.js instead.",
|
|
1363
|
+
);
|
|
1364
|
+
return null;
|
|
1365
|
+
}
|
|
1353
1366
|
return resolveRealCodexBinFromEnvironment({
|
|
1354
1367
|
moduleUrl: import.meta.url,
|
|
1355
1368
|
env: process.env,
|
|
@@ -3599,7 +3612,16 @@ function parseRuntimeRotationProxyEnv(value) {
|
|
|
3599
3612
|
return undefined;
|
|
3600
3613
|
}
|
|
3601
3614
|
|
|
3615
|
+
function hasNativeAppBinding(env = process.env) {
|
|
3616
|
+
try {
|
|
3617
|
+
const config = readFileSync(join(resolveCodexHomeDir(env), "config.toml"), "utf8");
|
|
3618
|
+
return config.includes("# codex-multi-auth native provider begin") &&
|
|
3619
|
+
extractConfigAssignmentValue(config, "model_provider") === "openai";
|
|
3620
|
+
} catch { return false; }
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3602
3623
|
async function isRuntimeRotationProxyEnabled(rawArgs, baseEnv = process.env) {
|
|
3624
|
+
if (hasNativeAppBinding(baseEnv)) return false;
|
|
3603
3625
|
if ((baseEnv.CODEX_MULTI_AUTH_BYPASS ?? "").trim() === "1") {
|
|
3604
3626
|
return false;
|
|
3605
3627
|
}
|
|
@@ -4021,29 +4043,20 @@ function installRuntimeRotationAppServerCliShim(forwardedEnv, configArgs = []) {
|
|
|
4021
4043
|
// Best-effort stale shim cleanup only; the copy below will report a
|
|
4022
4044
|
// persistent failure without leaving a partially-created helper.
|
|
4023
4045
|
}
|
|
4024
|
-
if (
|
|
4025
|
-
|
|
4026
|
-
(process.env.CODEX_MULTI_AUTH_TEST_FORCE_APP_SERVER_SHIM_COPY ?? "") === "1"
|
|
4027
|
-
) {
|
|
4028
|
-
// A Windows hard link to the running node.exe remains locked by the
|
|
4029
|
-
// helper process itself, which prevents the shim directory from being
|
|
4030
|
-
// removed during graceful helper shutdown. Use an independent image so
|
|
4031
|
-
// the helper can clean up its app-server shim before exiting.
|
|
4046
|
+
if (process.platform === "win32") {
|
|
4047
|
+
// A running hard-linked node.exe prevents helper cleanup on Windows.
|
|
4032
4048
|
withSynchronousFileOperationRetry(() => {
|
|
4033
4049
|
maybeThrowSimulatedAppServerShimFileError("copy");
|
|
4034
4050
|
copyFileSync(process.execPath, executablePath);
|
|
4035
4051
|
});
|
|
4036
4052
|
} else {
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
}
|
|
4045
|
-
}
|
|
4046
|
-
if (process.platform !== "win32") {
|
|
4053
|
+
// Relocating Node breaks installations with executable-relative shared
|
|
4054
|
+
// libraries (including Homebrew). Invoke the original image in place.
|
|
4055
|
+
const quotedNode = "'" + process.execPath.replace(/'/g, "'\\''") + "'";
|
|
4056
|
+
withSynchronousFileOperationRetry(() => {
|
|
4057
|
+
maybeThrowSimulatedAppServerShimFileError("copy");
|
|
4058
|
+
writeFileSync(executablePath, `#!/bin/sh\nexec ${quotedNode} "$@"\n`, { mode: 0o755 });
|
|
4059
|
+
});
|
|
4047
4060
|
chmodSync(executablePath, 0o755);
|
|
4048
4061
|
}
|
|
4049
4062
|
writeFileSync(
|
|
@@ -5964,8 +5977,13 @@ function createCompatibilityCodexHome(
|
|
|
5964
5977
|
};
|
|
5965
5978
|
}
|
|
5966
5979
|
|
|
5967
|
-
function buildForwardArgs(rawArgs) {
|
|
5968
|
-
|
|
5980
|
+
function buildForwardArgs(rawArgs, { preserveNativeSettings = false } = {}) {
|
|
5981
|
+
// Native app binding keeps the caller's model and reasoning settings verbatim;
|
|
5982
|
+
// it still needs the file auth store, because the router authenticates the
|
|
5983
|
+
// desktop token it reads from auth.json.
|
|
5984
|
+
const { args: compatibilityArgs, requestedModel } = preserveNativeSettings
|
|
5985
|
+
? { args: [...rawArgs], requestedModel: extractRequestedModel(rawArgs) }
|
|
5986
|
+
: rewriteReasoningConfigArgs(rawArgs);
|
|
5969
5987
|
const forceFileAuthStore = (process.env.CODEX_MULTI_AUTH_FORCE_FILE_AUTH_STORE ?? "1").trim() !== "0";
|
|
5970
5988
|
if (!forceFileAuthStore) {
|
|
5971
5989
|
return { args: compatibilityArgs, requestedModel };
|
|
@@ -6473,6 +6491,33 @@ function ensureWindowsShellShimGuards() {
|
|
|
6473
6491
|
}
|
|
6474
6492
|
}
|
|
6475
6493
|
|
|
6494
|
+
export function getResumePickerRequest(args, cwd = process.cwd()) {
|
|
6495
|
+
const baseCwd = cwd;
|
|
6496
|
+
const command = findForwardedCommand(args);
|
|
6497
|
+
if (command?.command !== "resume" || findForwardedSubcommand(args, command.index)) return null;
|
|
6498
|
+
const configArgs = [];
|
|
6499
|
+
let showAll = false;
|
|
6500
|
+
let includeNonInteractive = false;
|
|
6501
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
6502
|
+
const arg = args[i];
|
|
6503
|
+
if (arg === "--") break;
|
|
6504
|
+
if (consumesNextArg(arg) && args[i + 1] === undefined) return null;
|
|
6505
|
+
if (["--last", "--help", "-h", "--remote"].includes(arg) || arg.startsWith("--remote=")) return null;
|
|
6506
|
+
if (arg === "--all") showAll = true;
|
|
6507
|
+
if (arg === "--include-non-interactive") includeNonInteractive = true;
|
|
6508
|
+
if (arg === "-C" || arg === "--cd") cwd = resolvePath(baseCwd, args[i + 1]);
|
|
6509
|
+
else if (arg.startsWith("--cd=")) cwd = resolvePath(baseCwd, arg.slice(5));
|
|
6510
|
+
else if (arg.startsWith("-C") && arg.length > 2) cwd = resolvePath(baseCwd, arg.slice(2));
|
|
6511
|
+
if (["-c", "--config", "-p", "--profile", "--enable", "--disable"].includes(arg)) {
|
|
6512
|
+
configArgs.push(arg, args[i + 1]);
|
|
6513
|
+
} else if (/^--(config|profile|enable|disable)=/.test(arg) || /^-[cp].+/.test(arg)) {
|
|
6514
|
+
configArgs.push(arg);
|
|
6515
|
+
}
|
|
6516
|
+
i = skipOptionValueSpan(args, i);
|
|
6517
|
+
}
|
|
6518
|
+
return { commandIndex: command.index, cwd, configArgs, showAll, includeNonInteractive };
|
|
6519
|
+
}
|
|
6520
|
+
|
|
6476
6521
|
async function main() {
|
|
6477
6522
|
hydrateCliVersionEnv();
|
|
6478
6523
|
|
|
@@ -6513,7 +6558,9 @@ async function main() {
|
|
|
6513
6558
|
[
|
|
6514
6559
|
"Could not locate the official Codex CLI.",
|
|
6515
6560
|
"Install it with npm, Homebrew, or an official native release so `codex` is on PATH.",
|
|
6516
|
-
|
|
6561
|
+
process.platform === "win32"
|
|
6562
|
+
? "Or set CODEX_MULTI_AUTH_REAL_CODEX_BIN to the full path of codex.exe or @openai/codex/bin/codex.js."
|
|
6563
|
+
: "Or set CODEX_MULTI_AUTH_REAL_CODEX_BIN to the full path of either codex or @openai/codex/bin/codex.js.",
|
|
6517
6564
|
].join("\n"),
|
|
6518
6565
|
);
|
|
6519
6566
|
return 1;
|
|
@@ -6522,12 +6569,42 @@ async function main() {
|
|
|
6522
6569
|
// Resolve `--account` / CODEX_MULTI_AUTH_FORCE_ACCOUNT before forwarding: strip
|
|
6523
6570
|
// the launcher-only flag from the Codex args and publish the resolved pin, or
|
|
6524
6571
|
// fail hard so a forced account can never silently fall back to another one.
|
|
6572
|
+
if (hasNativeAppBinding(process.env)) {
|
|
6573
|
+
const forced = resolveForcedAccountSelector(rawArgs, process.env);
|
|
6574
|
+
if (forced.error || forced.selector !== null) {
|
|
6575
|
+
console.error(forced.error ?? "Native app binding uses the persistent inference selection. Use codex-multi-auth switch instead of --account.");
|
|
6576
|
+
return 1;
|
|
6577
|
+
}
|
|
6578
|
+
delete process.env.CODEX_MULTI_AUTH_FORCE_ACCOUNT_INDEX;
|
|
6579
|
+
// Best effort: a locked or read-only config.toml (Windows EPERM/EBUSY)
|
|
6580
|
+
// must not block the launch; the per-invocation override below still applies.
|
|
6581
|
+
await ensurePersistedCodexFileAuthStore();
|
|
6582
|
+
const { args: nativeArgs } = buildForwardArgs(forced.strippedArgs, { preserveNativeSettings: true });
|
|
6583
|
+
const result = await forwardToRealCodexOnce(realCodexBin, nativeArgs, process.env);
|
|
6584
|
+
return result.exitCode;
|
|
6585
|
+
}
|
|
6525
6586
|
const forcedAccount = await applyForcedAccountSelection(rawArgs, process.env);
|
|
6526
6587
|
if (forcedAccount.error) {
|
|
6527
6588
|
console.error(forcedAccount.error);
|
|
6528
6589
|
return 1;
|
|
6529
6590
|
}
|
|
6530
|
-
const forwardArgs = forcedAccount.forwardArgs;
|
|
6591
|
+
const forwardArgs = [...forcedAccount.forwardArgs];
|
|
6592
|
+
|
|
6593
|
+
|
|
6594
|
+
if (process.stdin.isTTY && process.stdout.isTTY && !bypass) {
|
|
6595
|
+
const pickerRequest = getResumePickerRequest(forwardArgs);
|
|
6596
|
+
if (pickerRequest && await isRuntimeRotationProxyEnabled(forwardArgs)) {
|
|
6597
|
+
try {
|
|
6598
|
+
const { pickResumeThread } = await import("../dist/lib/runtime/resume-picker.js");
|
|
6599
|
+
const id = await pickResumeThread({ ...pickerRequest, codexBin: realCodexBin });
|
|
6600
|
+
if (!id) return 0;
|
|
6601
|
+
forwardArgs.splice(pickerRequest.commandIndex + 1, 0, id);
|
|
6602
|
+
} catch (error) {
|
|
6603
|
+
// Discovery is optional: fall back to native `codex resume` with the original args.
|
|
6604
|
+
console.error(`Could not list saved Codex sessions: ${error instanceof Error ? error.message : String(error)}`);
|
|
6605
|
+
}
|
|
6606
|
+
}
|
|
6607
|
+
}
|
|
6531
6608
|
|
|
6532
6609
|
await ensurePersistedCodexFileAuthStore();
|
|
6533
6610
|
await autoSyncManagerActiveSelectionIfEnabled();
|
|
@@ -6546,6 +6623,7 @@ async function main() {
|
|
|
6546
6623
|
// lib/request/helpers/model-map.ts (see test/codex-model-resolution.test.ts,
|
|
6547
6624
|
// which asserts wrapper<->lib parity).
|
|
6548
6625
|
export {
|
|
6626
|
+
isRuntimeRotationProxyEnabled,
|
|
6549
6627
|
normalizeRequestedModel,
|
|
6550
6628
|
coerceReasoningEffortForModel,
|
|
6551
6629
|
resolveModelFamilyForStatus,
|