codex-multi-auth 2.16.0 → 2.17.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.
- package/.codex-plugin/plugin.json +9 -9
- package/LICENSE +21 -21
- package/README.md +487 -463
- package/assets/codex-multi-auth-icon.svg +39 -39
- package/assets/readme-hero.svg +31 -31
- package/config/README.md +31 -31
- package/config/codex-legacy.json +1221 -1221
- package/config/codex-modern.json +423 -423
- package/config/minimal-codex.json +15 -15
- 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 +15 -3
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +231 -30
- 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 +1 -1
- package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/forecast.js +7 -3
- 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 +57 -7
- 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 +21 -8
- 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/quota-cache-helpers.d.ts +7 -1
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts.map +1 -1
- package/dist/lib/codex-manager/quota-cache-helpers.js +34 -19
- 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 +144 -9
- 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/context-budget-response.js +8 -8
- package/dist/lib/context-overflow.js +10 -10
- 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/oauth-success.html +125 -125
- 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/prompts/codex-host-bridge.js +138 -138
- package/dist/lib/prompts/codex.js +79 -79
- package/dist/lib/quota-cache.d.ts +7 -3
- package/dist/lib/quota-cache.d.ts.map +1 -1
- package/dist/lib/quota-cache.js +91 -59
- 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/quota-readiness.d.ts +7 -2
- package/dist/lib/quota-readiness.d.ts.map +1 -1
- package/dist/lib/quota-readiness.js +25 -4
- 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 +89 -11
- package/dist/lib/runtime/automatic-account-checks.d.ts +35 -0
- package/dist/lib/runtime/automatic-account-checks.d.ts.map +1 -0
- package/dist/lib/runtime/automatic-account-checks.js +140 -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 +54 -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 +18 -0
- package/dist/lib/storage/pending-auth.d.ts.map +1 -0
- package/dist/lib/storage/pending-auth.js +155 -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/record-identity.d.ts +16 -0
- package/dist/lib/storage/record-identity.d.ts.map +1 -0
- package/dist/lib/storage/record-identity.js +16 -0
- 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/node_modules/@codex-ai/plugin/dist/index.d.ts +2 -2
- package/node_modules/@codex-ai/plugin/dist/index.js +2 -2
- package/node_modules/@codex-ai/plugin/dist/tool.d.ts +42 -42
- package/node_modules/@codex-ai/plugin/dist/tool.js +29 -29
- package/node_modules/@codex-ai/plugin/package.json +9 -9
- package/node_modules/@codex-ai/sdk/dist/index.d.ts +4 -4
- package/node_modules/@codex-ai/sdk/dist/index.js +2 -2
- package/node_modules/@codex-ai/sdk/package.json +8 -8
- package/package.json +200 -197
- package/scripts/codex-app-launcher.js +653 -653
- package/scripts/codex-app-router.js +373 -366
- package/scripts/codex-bin-resolver.js +313 -281
- package/scripts/codex-multi-auth.js +59 -59
- package/scripts/codex-routing.js +62 -61
- package/scripts/codex.js +6642 -6564
- package/scripts/install-codex-auth-utils.js +213 -213
- package/scripts/mcodex.js +367 -367
- package/scripts/postinstall.js +114 -114
- package/scripts/preuninstall.js +265 -265
- package/vendor/codex-ai-plugin/dist/index.d.ts +2 -2
- package/vendor/codex-ai-plugin/dist/index.js +2 -2
- package/vendor/codex-ai-plugin/dist/tool.d.ts +42 -42
- package/vendor/codex-ai-plugin/dist/tool.js +29 -29
- package/vendor/codex-ai-plugin/package.json +9 -9
- package/vendor/codex-ai-sdk/dist/index.d.ts +4 -4
- package/vendor/codex-ai-sdk/dist/index.js +2 -2
- package/vendor/codex-ai-sdk/package.json +8 -8
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildQuotaEmailFallbackState, hasSafeQuotaEmailFallback, hasUniqueQuotaAccountId, normalizeQuotaAccountId, normalizeQuotaEmail, } from "../quota-readiness.js";
|
|
1
|
+
import { buildQuotaEmailFallbackState, findQuotaCacheEntryForAccount, quotaWorkspaceKey, hasSafeQuotaEmailFallback, hasUniqueQuotaAccountId, normalizeQuotaAccountId, normalizeQuotaEmail, } from "../quota-readiness.js";
|
|
2
2
|
import { DEFAULT_MODEL, DEFAULT_PROBE_MODEL, } from "../request/helpers/model-map.js";
|
|
3
3
|
import { getRateLimitResetTimeForFamily } from "../runtime/account-status.js";
|
|
4
4
|
/**
|
|
@@ -11,24 +11,10 @@ import { getRateLimitResetTimeForFamily } from "../runtime/account-status.js";
|
|
|
11
11
|
*/
|
|
12
12
|
/** Default model used for live quota probes across manager commands. */
|
|
13
13
|
export const DEFAULT_LIVE_PROBE_MODEL = DEFAULT_PROBE_MODEL;
|
|
14
|
-
|
|
15
|
-
const accountId = normalizeQuotaAccountId(account.accountId);
|
|
16
|
-
if (accountId &&
|
|
17
|
-
hasUniqueQuotaAccountId(accounts, account) &&
|
|
18
|
-
cache.byAccountId[accountId]) {
|
|
19
|
-
return cache.byAccountId[accountId] ?? null;
|
|
20
|
-
}
|
|
21
|
-
const email = normalizeQuotaEmail(account.email);
|
|
22
|
-
if (email &&
|
|
23
|
-
hasSafeQuotaEmailFallback(emailFallbackState, account) &&
|
|
24
|
-
cache.byEmail[email]) {
|
|
25
|
-
return cache.byEmail[email] ?? null;
|
|
26
|
-
}
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
14
|
+
/** Combine selected-workspace observations with persisted account-level rate-limit blockers. */
|
|
29
15
|
export function getPersistedQuotaViewForAccount(cache, account, accounts, now, emailFallbackState = buildQuotaEmailFallbackState(accounts)) {
|
|
30
16
|
const cachedEntry = cache
|
|
31
|
-
?
|
|
17
|
+
? findQuotaCacheEntryForAccount(cache, account, accounts, emailFallbackState)
|
|
32
18
|
: null;
|
|
33
19
|
const persistedResetAt = getRateLimitResetTimeForFamily(account, now, "codex");
|
|
34
20
|
if (typeof persistedResetAt !== "number") {
|
|
@@ -52,8 +38,9 @@ export function getPersistedQuotaViewForAccount(cache, account, accounts, now, e
|
|
|
52
38
|
secondary: cachedEntry?.secondary ?? {},
|
|
53
39
|
};
|
|
54
40
|
}
|
|
55
|
-
|
|
56
|
-
|
|
41
|
+
/** Retain only quota fields from a probe, never its credentials or response body. */
|
|
42
|
+
function quotaEntryFromSnapshot(snapshot) {
|
|
43
|
+
return {
|
|
57
44
|
updatedAt: Date.now(),
|
|
58
45
|
status: snapshot.status,
|
|
59
46
|
model: snapshot.model,
|
|
@@ -69,6 +56,10 @@ export function updateQuotaCacheForAccount(cache, account, snapshot, accounts, e
|
|
|
69
56
|
resetAtMs: snapshot.secondary.resetAtMs,
|
|
70
57
|
},
|
|
71
58
|
};
|
|
59
|
+
}
|
|
60
|
+
/** Update legacy stored-binding quota with a unique ID or safe email fallback. */
|
|
61
|
+
export function updateQuotaCacheForAccount(cache, account, snapshot, accounts, emailFallbackState = buildQuotaEmailFallbackState(accounts)) {
|
|
62
|
+
const nextEntry = quotaEntryFromSnapshot(snapshot);
|
|
72
63
|
let changed = false;
|
|
73
64
|
const accountId = normalizeQuotaAccountId(account.accountId);
|
|
74
65
|
const hasUniqueAccountId = accountId !== null && hasUniqueQuotaAccountId(accounts, account);
|
|
@@ -89,12 +80,36 @@ export function updateQuotaCacheForAccount(cache, account, snapshot, accounts, e
|
|
|
89
80
|
}
|
|
90
81
|
return changed;
|
|
91
82
|
}
|
|
83
|
+
/** Persist the observed workspace without attributing sibling quota to a stored binding. */
|
|
84
|
+
export function updateQuotaCacheForWorkspace(cache, account, workspaceId, snapshot, accounts) {
|
|
85
|
+
const key = quotaWorkspaceKey(account, workspaceId);
|
|
86
|
+
if (!key)
|
|
87
|
+
return;
|
|
88
|
+
cache.byWorkspace ??= {};
|
|
89
|
+
cache.byWorkspace[key] = quotaEntryFromSnapshot(snapshot);
|
|
90
|
+
if (workspaceId === normalizeQuotaAccountId(account.accountId)) {
|
|
91
|
+
updateQuotaCacheForAccount(cache, account, snapshot, accounts);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Retire the ambiguous fallback only after retaining its binding observation.
|
|
95
|
+
const boundId = normalizeQuotaAccountId(account.accountId);
|
|
96
|
+
const binding = boundId ? findQuotaCacheEntryForAccount(cache, account, accounts, undefined, boundId) : null;
|
|
97
|
+
const boundKey = boundId && quotaWorkspaceKey(account, boundId);
|
|
98
|
+
if (binding && boundKey)
|
|
99
|
+
cache.byWorkspace[boundKey] = binding;
|
|
100
|
+
const email = normalizeQuotaEmail(account.email);
|
|
101
|
+
if (email)
|
|
102
|
+
delete cache.byEmail[email];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Clone every cache namespace; immutable entries may safely remain shared. */
|
|
92
106
|
export function cloneQuotaCacheData(cache) {
|
|
93
107
|
// Shallow spreading is safe because quota cache entries are always replaced,
|
|
94
108
|
// never mutated in-place.
|
|
95
109
|
return {
|
|
96
110
|
byAccountId: { ...cache.byAccountId },
|
|
97
111
|
byEmail: { ...cache.byEmail },
|
|
112
|
+
...(cache.byWorkspace ? { byWorkspace: { ...cache.byWorkspace } } : {}),
|
|
98
113
|
};
|
|
99
114
|
}
|
|
100
115
|
export function pruneUnsafeQuotaEmailCacheEntry(cache, email, accounts, emailFallbackState = buildQuotaEmailFallbackState(accounts)) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type QuotaCacheData } from "../quota-cache.js";
|
|
2
2
|
import { fetchCodexQuotaSnapshot } from "../quota-probe.js";
|
|
3
|
+
import type { CodexCliMirrorUpdate, ConstrainedSelection } from "../auth/account-access.js";
|
|
3
4
|
import { type AccountMetadataV3, type AccountStorageV3 } from "../storage.js";
|
|
4
5
|
import { type ModelFamily } from "../prompts/codex.js";
|
|
5
6
|
import type { AccountIdSource } from "../types.js";
|
|
@@ -46,6 +47,18 @@ export interface RepairCommandDeps {
|
|
|
46
47
|
formatCompactQuotaSnapshot: (snapshot: Awaited<ReturnType<typeof fetchCodexQuotaSnapshot>>) => string;
|
|
47
48
|
resolveStoredAccountIdentity: (storedAccountId: string | undefined, storedAccountIdSource: AccountIdSource | undefined, refreshedAccountId: string | undefined) => AccountIdentityResolution;
|
|
48
49
|
applyTokenAccountIdentity: (account: AccountMetadataV3, refreshedAccountId: string | undefined) => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Migrates an org-sourced account id the backend no longer authorizes
|
|
52
|
+
* (Codex CLI >= 0.156.0's `wham/accounts/check`); see
|
|
53
|
+
* lib/auth/account-access.ts for the full contract. Live-only: called from
|
|
54
|
+
* `fix --live`, where a network round trip already happens per account.
|
|
55
|
+
*/
|
|
56
|
+
reboundUnauthorizedAccountIdentity: (account: AccountMetadataV3, accessToken: string) => Promise<ConstrainedSelection | null>;
|
|
57
|
+
/**
|
|
58
|
+
* Keeps an explicit (`manual`) account's CodexCliMirror in step with the
|
|
59
|
+
* backend's authorization; see lib/auth/account-access.ts. Live-only.
|
|
60
|
+
*/
|
|
61
|
+
refreshCodexCliMirror: (account: AccountMetadataV3, accessToken: string) => Promise<CodexCliMirrorUpdate | null>;
|
|
49
62
|
}
|
|
50
63
|
export declare function parseFixArgs(args: string[]): ParsedArgsResult<FixCliOptions>;
|
|
51
64
|
export declare function runVerifyFlagged(args: string[], deps: RepairCommandDeps): Promise<number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repair-commands.d.ts","sourceRoot":"","sources":["../../../lib/codex-manager/repair-commands.ts"],"names":[],"mappings":"AAcA,OAAO,EAAkC,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EACN,uBAAuB,EAEvB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"repair-commands.d.ts","sourceRoot":"","sources":["../../../lib/codex-manager/repair-commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ import { extractAccountEmail, extractAccountId, formatAccountLabel, sanitizeEmai
|
|
|
6
6
|
import { loadQuotaCache, saveQuotaCache } from "../quota-cache.js";
|
|
7
7
|
import { fetchCodexQuotaSnapshot, CODEX_UNAVAILABLE_PROBE_NOTE, } from "../quota-probe.js";
|
|
8
8
|
import { isCodexUnavailableError } from "../errors.js";
|
|
9
|
+
import { codexAuthAccountIdsMatch, codexCliAccountIdFor, codexCliActiveIdentity, isOpenAiOrgId, } from "../auth/token-utils.js";
|
|
9
10
|
import { queuedRefresh } from "../refresh-queue.js";
|
|
10
11
|
import { findMatchingAccountIndex, getStoragePath, loadAccounts, loadFlaggedAccounts, setStoragePath, withAccountStorageTransaction, withAccountAndFlaggedStorageTransaction, withFlaggedStorageTransaction, } from "../storage.js";
|
|
11
12
|
import { getCodexCliAuthPath, getCodexCliConfigPath, loadCodexCliState, } from "../codex-cli/state.js";
|
|
@@ -28,6 +29,7 @@ function printFixUsage() {
|
|
|
28
29
|
" - Refreshes tokens for enabled accounts",
|
|
29
30
|
" - Disables hard-failed accounts (never deletes)",
|
|
30
31
|
" - Recommends a better current account when needed",
|
|
32
|
+
" - With --live, rebinds an org workspace id the backend no longer authorizes",
|
|
31
33
|
].join("\n"));
|
|
32
34
|
}
|
|
33
35
|
function printVerifyFlaggedUsage() {
|
|
@@ -160,7 +162,8 @@ function summarizeFixReports(reports) {
|
|
|
160
162
|
healthy += 1;
|
|
161
163
|
else if (report.outcome === "disabled-hard-failure")
|
|
162
164
|
disabled += 1;
|
|
163
|
-
else if (report.outcome === "warning-soft-failure"
|
|
165
|
+
else if (report.outcome === "warning-soft-failure" ||
|
|
166
|
+
report.outcome === "rebound-unauthorized-workspace")
|
|
164
167
|
warnings += 1;
|
|
165
168
|
else
|
|
166
169
|
skipped += 1;
|
|
@@ -186,7 +189,11 @@ function hasAccountStorageMutation(before, after) {
|
|
|
186
189
|
|| before.email !== after.email
|
|
187
190
|
|| before.accountId !== after.accountId
|
|
188
191
|
|| before.accountIdSource !== after.accountIdSource
|
|
189
|
-
|| before.enabled !== after.enabled
|
|
192
|
+
|| before.enabled !== after.enabled
|
|
193
|
+
|| before.accountLabel !== after.accountLabel
|
|
194
|
+
|| before.currentWorkspaceIndex !== after.currentWorkspaceIndex
|
|
195
|
+
|| JSON.stringify(before.workspaces) !== JSON.stringify(after.workspaces)
|
|
196
|
+
|| JSON.stringify(before.codexCliMirror) !== JSON.stringify(after.codexCliMirror));
|
|
190
197
|
}
|
|
191
198
|
function collectAccountStorageMutations(beforeAccounts, afterAccounts) {
|
|
192
199
|
const mutations = [];
|
|
@@ -224,6 +231,33 @@ function applyAccountStorageMutations(storage, mutations) {
|
|
|
224
231
|
target.accountId = mutation.after.accountId;
|
|
225
232
|
target.accountIdSource = mutation.after.accountIdSource;
|
|
226
233
|
target.enabled = mutation.after.enabled;
|
|
234
|
+
// Only the workspace rebind in `fix --live` moves these; copying them
|
|
235
|
+
// unconditionally would clobber a label/workspace change made on disk
|
|
236
|
+
// since this run loaded storage.
|
|
237
|
+
if (mutation.before.accountLabel !== mutation.after.accountLabel) {
|
|
238
|
+
target.accountLabel = mutation.after.accountLabel;
|
|
239
|
+
}
|
|
240
|
+
if (JSON.stringify(mutation.before.codexCliMirror) !==
|
|
241
|
+
JSON.stringify(mutation.after.codexCliMirror)) {
|
|
242
|
+
target.codexCliMirror = mutation.after.codexCliMirror;
|
|
243
|
+
if (!target.codexCliMirror)
|
|
244
|
+
delete target.codexCliMirror;
|
|
245
|
+
}
|
|
246
|
+
// The pointer indexes the list, so the two move together: copying only
|
|
247
|
+
// the list would keep a pointer moved on disk meanwhile, possibly out
|
|
248
|
+
// of range of the new list.
|
|
249
|
+
if (mutation.before.currentWorkspaceIndex !== mutation.after.currentWorkspaceIndex ||
|
|
250
|
+
JSON.stringify(mutation.before.workspaces) !==
|
|
251
|
+
JSON.stringify(mutation.after.workspaces)) {
|
|
252
|
+
const workspaces = mutation.after.workspaces;
|
|
253
|
+
const pointer = mutation.after.currentWorkspaceIndex;
|
|
254
|
+
target.workspaces = workspaces;
|
|
255
|
+
target.currentWorkspaceIndex =
|
|
256
|
+
!workspaces ||
|
|
257
|
+
(typeof pointer === "number" && pointer >= 0 && pointer < workspaces.length)
|
|
258
|
+
? pointer
|
|
259
|
+
: Math.max(0, workspaces.findIndex((workspace) => workspace.id === mutation.after.accountId));
|
|
260
|
+
}
|
|
227
261
|
}
|
|
228
262
|
}
|
|
229
263
|
function findExistingAccountIndexForFlagged(storage, flagged, nextRefreshToken, nextAccountId, nextEmail) {
|
|
@@ -866,6 +900,29 @@ export async function runFix(args, deps) {
|
|
|
866
900
|
const reports = [];
|
|
867
901
|
const refreshFailures = new Map();
|
|
868
902
|
const hardDisabledIndexes = [];
|
|
903
|
+
// A rebind mutates the account before its live probe, so a later rebind
|
|
904
|
+
// attempt on the refresh path sees a `token` source and reports nothing.
|
|
905
|
+
// Tracking it per index keeps the note on whichever report ends up final.
|
|
906
|
+
const reboundIndexes = new Set();
|
|
907
|
+
// Explicit accounts whose CodexCliMirror this run set or cleared. Checked
|
|
908
|
+
// once per account even when the refresh path runs after a failed probe.
|
|
909
|
+
const mirrorUpdates = new Map();
|
|
910
|
+
const checkMirror = async (index, accessToken) => {
|
|
911
|
+
const account = storage.accounts[index];
|
|
912
|
+
if (!account || mirrorUpdates.has(index))
|
|
913
|
+
return;
|
|
914
|
+
const update = await deps.refreshCodexCliMirror(account, accessToken);
|
|
915
|
+
mirrorUpdates.set(index, update);
|
|
916
|
+
if (update)
|
|
917
|
+
accountStorageChanged = true;
|
|
918
|
+
};
|
|
919
|
+
const noteRebound = (index) => {
|
|
920
|
+
reboundIndexes.add(index);
|
|
921
|
+
accountStorageChanged = true;
|
|
922
|
+
if (workingQuotaCache) {
|
|
923
|
+
quotaEmailFallbackState = deps.buildQuotaEmailFallbackState(storage.accounts);
|
|
924
|
+
}
|
|
925
|
+
};
|
|
869
926
|
for (let i = 0; i < storage.accounts.length; i += 1) {
|
|
870
927
|
const account = storage.accounts[i];
|
|
871
928
|
if (!account)
|
|
@@ -884,6 +941,12 @@ export async function runFix(args, deps) {
|
|
|
884
941
|
let refreshAfterLiveProbeFailure = false;
|
|
885
942
|
if (options.live) {
|
|
886
943
|
const currentAccessToken = account.accessToken;
|
|
944
|
+
if (currentAccessToken &&
|
|
945
|
+
(await deps.reboundUnauthorizedAccountIdentity(account, currentAccessToken))) {
|
|
946
|
+
noteRebound(i);
|
|
947
|
+
}
|
|
948
|
+
if (currentAccessToken)
|
|
949
|
+
await checkMirror(i, currentAccessToken);
|
|
887
950
|
const probeAccountId = currentAccessToken
|
|
888
951
|
? account.accountId ?? extractAccountId(currentAccessToken)
|
|
889
952
|
: undefined;
|
|
@@ -962,6 +1025,10 @@ export async function runFix(args, deps) {
|
|
|
962
1025
|
deps.pruneUnsafeQuotaEmailCacheEntry(workingQuotaCache, previousEmail, storage.accounts, quotaEmailFallbackState) || quotaCacheChanged;
|
|
963
1026
|
}
|
|
964
1027
|
if (options.live) {
|
|
1028
|
+
if (await deps.reboundUnauthorizedAccountIdentity(account, refreshResult.access)) {
|
|
1029
|
+
noteRebound(i);
|
|
1030
|
+
}
|
|
1031
|
+
await checkMirror(i, refreshResult.access);
|
|
965
1032
|
const probeAccountId = account.accountId ?? nextAccountId;
|
|
966
1033
|
if (probeAccountId) {
|
|
967
1034
|
try {
|
|
@@ -1068,8 +1135,32 @@ export async function runFix(args, deps) {
|
|
|
1068
1135
|
refreshFailure: refreshFailures.get(index),
|
|
1069
1136
|
})));
|
|
1070
1137
|
const recommendation = recommendForecastAccount(forecastResults);
|
|
1138
|
+
for (const report of reports) {
|
|
1139
|
+
const mirrorUpdate = mirrorUpdates.get(report.index);
|
|
1140
|
+
if (mirrorUpdate === "set") {
|
|
1141
|
+
report.message = `explicit workspace is not authorized for these credentials; Codex CLI auth uses the backend default. ${report.message}`;
|
|
1142
|
+
}
|
|
1143
|
+
else if (mirrorUpdate === "cleared") {
|
|
1144
|
+
report.message = `explicit workspace is authorized again; Codex CLI auth uses it. ${report.message}`;
|
|
1145
|
+
}
|
|
1146
|
+
if (!reboundIndexes.has(report.index))
|
|
1147
|
+
continue;
|
|
1148
|
+
report.label = formatAccountLabel(storage.accounts[report.index], report.index);
|
|
1149
|
+
report.message = `workspace was not authorized for these credentials; rebound to the account's default identity. ${report.message}`;
|
|
1150
|
+
if (report.outcome === "healthy") {
|
|
1151
|
+
report.outcome = "rebound-unauthorized-workspace";
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1071
1154
|
const reportSummary = summarizeFixReports(reports);
|
|
1072
1155
|
const accountMutations = collectAccountStorageMutations(originalAccounts, storage.accounts);
|
|
1156
|
+
// ~/.codex/auth.json still carries the rejected id for the active account,
|
|
1157
|
+
// and Codex CLI keeps refusing it until something rewrites that file. The
|
|
1158
|
+
// mirror is taken from the committed snapshot, not this run's in-memory
|
|
1159
|
+
// view, and written while the storage lock is still held: another process
|
|
1160
|
+
// may switch the active account around this run, and a sync outside the
|
|
1161
|
+
// lock could put the old selection back into auth.json.
|
|
1162
|
+
let codexActiveSynced = null;
|
|
1163
|
+
let committedActiveIndex = activeIndex;
|
|
1073
1164
|
if (accountStorageChanged && !options.dryRun) {
|
|
1074
1165
|
await withAccountStorageTransaction(async (loadedStorage, persist) => {
|
|
1075
1166
|
const nextStorage = loadedStorage
|
|
@@ -1077,12 +1168,34 @@ export async function runFix(args, deps) {
|
|
|
1077
1168
|
: createEmptyAccountStorage();
|
|
1078
1169
|
applyAccountStorageMutations(nextStorage, accountMutations);
|
|
1079
1170
|
await persist(nextStorage);
|
|
1171
|
+
committedActiveIndex = deps.resolveActiveIndex(nextStorage, "codex");
|
|
1172
|
+
const committedActive = nextStorage.accounts[committedActiveIndex];
|
|
1173
|
+
const syncIndexes = [
|
|
1174
|
+
...reboundIndexes,
|
|
1175
|
+
...[...mirrorUpdates].filter(([, update]) => update).map(([index]) => index),
|
|
1176
|
+
];
|
|
1177
|
+
const isRebound = committedActive !== undefined &&
|
|
1178
|
+
syncIndexes.some((index) => {
|
|
1179
|
+
const rebound = storage.accounts[index];
|
|
1180
|
+
return (rebound !== undefined &&
|
|
1181
|
+
rebound.accountId === committedActive.accountId &&
|
|
1182
|
+
rebound.refreshToken === committedActive.refreshToken);
|
|
1183
|
+
});
|
|
1184
|
+
if (isRebound && committedActive.enabled !== false) {
|
|
1185
|
+
codexActiveSynced = await setCodexCliActiveSelection({
|
|
1186
|
+
accountId: codexCliAccountIdFor(committedActive, committedActive.accessToken),
|
|
1187
|
+
email: committedActive.email,
|
|
1188
|
+
accessToken: committedActive.accessToken,
|
|
1189
|
+
refreshToken: committedActive.refreshToken,
|
|
1190
|
+
expiresAt: committedActive.expiresAt,
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1080
1193
|
});
|
|
1081
1194
|
}
|
|
1082
1195
|
let quotaCacheSaveError = null;
|
|
1083
1196
|
if (!options.dryRun && workingQuotaCache && quotaCacheChanged) {
|
|
1084
1197
|
try {
|
|
1085
|
-
await saveQuotaCache(workingQuotaCache);
|
|
1198
|
+
await saveQuotaCache(workingQuotaCache, quotaCache ?? undefined);
|
|
1086
1199
|
}
|
|
1087
1200
|
catch (error) {
|
|
1088
1201
|
// Account storage was already persisted above. Surface the quota-cache
|
|
@@ -1103,6 +1216,7 @@ export async function runFix(args, deps) {
|
|
|
1103
1216
|
changed,
|
|
1104
1217
|
quotaCacheChanged,
|
|
1105
1218
|
quotaCacheSaveError,
|
|
1219
|
+
codexActiveSynced,
|
|
1106
1220
|
summary: reportSummary,
|
|
1107
1221
|
recommendation,
|
|
1108
1222
|
recommendedSwitchCommand: recommendation.recommendedIndex !== null
|
|
@@ -1129,6 +1243,9 @@ export async function runFix(args, deps) {
|
|
|
1129
1243
|
if (quotaCacheSaveError) {
|
|
1130
1244
|
console.log(deps.stylePromptText(`Warning: quota cache save failed (${quotaCacheSaveError}); account fixes were saved.`, "warning"));
|
|
1131
1245
|
}
|
|
1246
|
+
if (codexActiveSynced === false) {
|
|
1247
|
+
console.log(deps.stylePromptText(`Warning: the rebound active account could not be synced into Codex auth state; run \`codex-multi-auth switch ${committedActiveIndex + 1}\` to retry.`, "warning"));
|
|
1248
|
+
}
|
|
1132
1249
|
if (display.showPerAccountRows) {
|
|
1133
1250
|
console.log("");
|
|
1134
1251
|
for (const report of reports) {
|
|
@@ -1136,14 +1253,16 @@ export async function runFix(args, deps) {
|
|
|
1136
1253
|
? "✓"
|
|
1137
1254
|
: report.outcome === "disabled-hard-failure"
|
|
1138
1255
|
? "✗"
|
|
1139
|
-
: report.outcome === "warning-soft-failure"
|
|
1256
|
+
: report.outcome === "warning-soft-failure" ||
|
|
1257
|
+
report.outcome === "rebound-unauthorized-workspace"
|
|
1140
1258
|
? "!"
|
|
1141
1259
|
: "-";
|
|
1142
1260
|
const tone = report.outcome === "healthy"
|
|
1143
1261
|
? "success"
|
|
1144
1262
|
: report.outcome === "disabled-hard-failure"
|
|
1145
1263
|
? "danger"
|
|
1146
|
-
: report.outcome === "warning-soft-failure"
|
|
1264
|
+
: report.outcome === "warning-soft-failure" ||
|
|
1265
|
+
report.outcome === "rebound-unauthorized-workspace"
|
|
1147
1266
|
? "warning"
|
|
1148
1267
|
: "muted";
|
|
1149
1268
|
console.log(`${deps.stylePromptText(prefix, tone)} ${deps.stylePromptText(`${report.index + 1}. ${report.label}`, "accent")} ${deps.stylePromptText("|", "muted")} ${deps.styleAccountDetailText(report.message, tone === "success" ? "muted" : tone)}`);
|
|
@@ -1233,6 +1352,7 @@ export async function runDoctor(args, deps) {
|
|
|
1233
1352
|
const codexConfigFileExists = existsSync(codexConfigPath);
|
|
1234
1353
|
let codexAuthEmail;
|
|
1235
1354
|
let codexAuthAccountId;
|
|
1355
|
+
let codexAuthFileAccountId;
|
|
1236
1356
|
addCheck({
|
|
1237
1357
|
key: "codex-auth-file",
|
|
1238
1358
|
severity: codexAuthFileExists ? "ok" : "warn",
|
|
@@ -1269,6 +1389,7 @@ export async function runDoctor(args, deps) {
|
|
|
1269
1389
|
: undefined;
|
|
1270
1390
|
const emailFromFile = typeof payload.email === "string" ? payload.email : undefined;
|
|
1271
1391
|
codexAuthEmail = sanitizeEmail(emailFromFile ?? extractAccountEmail(accessToken, idToken));
|
|
1392
|
+
codexAuthFileAccountId = accountIdFromFile;
|
|
1272
1393
|
codexAuthAccountId = accountIdFromFile ?? extractAccountId(accessToken);
|
|
1273
1394
|
addCheck({
|
|
1274
1395
|
key: "codex-auth-readable",
|
|
@@ -1553,9 +1674,23 @@ export async function runDoctor(args, deps) {
|
|
|
1553
1674
|
const isEmailMismatch = !!managerActiveEmail
|
|
1554
1675
|
&& !!codexActiveEmail
|
|
1555
1676
|
&& managerActiveEmail !== codexActiveEmail;
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1677
|
+
// A stored "org-..." id is written to auth.json as the token's
|
|
1678
|
+
// workspace id, while the legacy accounts.json keeps the raw id (#700).
|
|
1679
|
+
const codexActiveIdentity = codexCliState?.activeAccountId
|
|
1680
|
+
? codexCliActiveIdentity(codexCliState)
|
|
1681
|
+
: { accountId: codexActiveAccountId };
|
|
1682
|
+
// An org account_id in auth.json itself (written before #700) is
|
|
1683
|
+
// rejected by Codex CLI 0.156+, so it is never aligned.
|
|
1684
|
+
const isAccountIdMismatch = isOpenAiOrgId(codexAuthFileAccountId)
|
|
1685
|
+
|| (!!managerActiveAccountId
|
|
1686
|
+
&& !!codexActiveAccountId
|
|
1687
|
+
&& !codexAuthAccountIdsMatch({
|
|
1688
|
+
// As the writer would write it (CodexCliMirror applied).
|
|
1689
|
+
accountId: activeAccount
|
|
1690
|
+
? codexCliAccountIdFor(activeAccount, activeAccount.accessToken)
|
|
1691
|
+
: managerActiveAccountId,
|
|
1692
|
+
accessToken: activeAccount?.accessToken,
|
|
1693
|
+
}, codexActiveIdentity));
|
|
1559
1694
|
addCheck({
|
|
1560
1695
|
key: "active-selection-sync",
|
|
1561
1696
|
severity: isEmailMismatch || isAccountIdMismatch ? "warn" : "ok",
|
|
@@ -1627,7 +1762,7 @@ export async function runDoctor(args, deps) {
|
|
|
1627
1762
|
}
|
|
1628
1763
|
if (!options.dryRun && canSyncActiveAccount) {
|
|
1629
1764
|
pendingCodexActiveSync = {
|
|
1630
|
-
accountId: activeAccount
|
|
1765
|
+
accountId: codexCliAccountIdFor(activeAccount, syncAccessToken, syncIdToken),
|
|
1631
1766
|
email: activeAccount.email,
|
|
1632
1767
|
accessToken: syncAccessToken,
|
|
1633
1768
|
refreshToken: syncRefreshToken,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-manager.d.ts","sourceRoot":"","sources":["../../lib/codex-manager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codex-manager.d.ts","sourceRoot":"","sources":["../../lib/codex-manager.ts"],"names":[],"mappings":"AAsEA,OAAO,EAIN,yBAAyB,EACzB,MAAM,eAAe,CAAC;AA8BvB,OAAO,EAEN,mBAAmB,EAMnB,sBAAsB,EAGtB,MAAM,qCAAqC,CAAC;AA+B7C,OAAO,EAEN,KAAK,gBAAgB,EAWrB,MAAM,cAAc,CAAC;AAKtB,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,CAAC;AA8IvD,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,OAAO,CAAC,CAyGrE;AACD,mFAAmF;AACnF,wBAAgB,wBAAwB,IAAI,CAC3C,OAAO,EAAE,gBAAgB,KACrB,OAAO,CAAC,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAwEzD;AAyQD,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4C7E"}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
+
import { runResetsCommand } from "./codex-manager/commands/resets.js";
|
|
2
|
+
import { loadResetCreditState } from "./runtime/account-reset-credits.js";
|
|
3
|
+
import { loadApiRoutes } from "./api-route-store.js";
|
|
4
|
+
import { loadInferenceRequestTimes } from "./runtime/inference-activity.js";
|
|
5
|
+
import { loadModelInventory, refreshAndPrintModelInventory } from "./runtime/model-discovery-status.js";
|
|
1
6
|
import { AUTH_INVALIDATION_MARKER, AccountManager, extractAccountEmail, extractAccountId, formatAccountLabel, formatWaitTime, sanitizeEmail, } from "./accounts.js";
|
|
7
|
+
import { reboundUnauthorizedAccountIdentity, refreshCodexCliMirror, } from "./auth/account-access.js";
|
|
8
|
+
import { codexCliAccountIdFor } from "./auth/token-utils.js";
|
|
2
9
|
import { loadCodexCliState } from "./codex-cli/state.js";
|
|
3
10
|
import { setCodexCliActiveSelection } from "./codex-cli/writer.js";
|
|
4
11
|
import { parseBestArgs, printBestUsage, runBestCommand, } from "./codex-manager/commands/best.js";
|
|
@@ -27,6 +34,7 @@ import { evaluateRuntimePolicy, loadRuntimePolicyState, } from "./policy/runtime
|
|
|
27
34
|
import { CURRENT_CODEX_MODEL } from "./request/helpers/model-map.js";
|
|
28
35
|
import { runDoctor as runRepairDoctor, runFix as runRepairFix, runVerifyFlagged as runRepairVerifyFlagged, } from "./codex-manager/repair-commands.js";
|
|
29
36
|
import { runUninstallCommand } from "./codex-manager/commands/uninstall.js";
|
|
37
|
+
import { clearAccountsAndCredentialSidecars } from "./storage/credential-sidecars.js";
|
|
30
38
|
import { runForecastCommand } from "./codex-manager/commands/forecast.js";
|
|
31
39
|
import { runInitConfigCommand } from "./codex-manager/commands/init-config.js";
|
|
32
40
|
import { runReportCommand } from "./codex-manager/commands/report.js";
|
|
@@ -73,6 +81,8 @@ function createRepairCommandDeps() {
|
|
|
73
81
|
formatCompactQuotaSnapshot,
|
|
74
82
|
resolveStoredAccountIdentity,
|
|
75
83
|
applyTokenAccountIdentity,
|
|
84
|
+
reboundUnauthorizedAccountIdentity,
|
|
85
|
+
refreshCodexCliMirror,
|
|
76
86
|
};
|
|
77
87
|
}
|
|
78
88
|
const IMPLEMENTED_FEATURES = [
|
|
@@ -210,7 +220,6 @@ export async function autoSyncActiveAccountToCodex() {
|
|
|
210
220
|
let syncRefreshToken = account.refreshToken;
|
|
211
221
|
let syncExpiresAt = account.expiresAt;
|
|
212
222
|
let syncIdToken;
|
|
213
|
-
let syncAccountId = account.accountId;
|
|
214
223
|
let syncEmail = account.email;
|
|
215
224
|
let changed = false;
|
|
216
225
|
let nextStoredAccount = null;
|
|
@@ -245,7 +254,6 @@ export async function autoSyncActiveAccountToCodex() {
|
|
|
245
254
|
syncRefreshToken = refreshResult.refresh;
|
|
246
255
|
syncExpiresAt = refreshResult.expires;
|
|
247
256
|
syncIdToken = refreshResult.idToken;
|
|
248
|
-
syncAccountId = nextStoredAccount.accountId;
|
|
249
257
|
syncEmail = nextStoredAccount.email;
|
|
250
258
|
}
|
|
251
259
|
if (changed && nextStoredAccount) {
|
|
@@ -273,7 +281,7 @@ export async function autoSyncActiveAccountToCodex() {
|
|
|
273
281
|
}
|
|
274
282
|
}
|
|
275
283
|
return setCodexCliActiveSelection({
|
|
276
|
-
accountId:
|
|
284
|
+
accountId: codexCliAccountIdFor(nextStoredAccount ?? account, syncAccessToken, syncIdToken),
|
|
277
285
|
email: syncEmail,
|
|
278
286
|
accessToken: syncAccessToken,
|
|
279
287
|
refreshToken: syncRefreshToken,
|
|
@@ -349,6 +357,10 @@ export function buildSelectAccountTraced() {
|
|
|
349
357
|
* Shared handler for `list` and `status` (aliases of the same view).
|
|
350
358
|
*/
|
|
351
359
|
const runListOrStatusCommand = (rest) => runStatusCommand({
|
|
360
|
+
loadApiRoutes,
|
|
361
|
+
loadResetCreditState,
|
|
362
|
+
loadInferenceRequestTimes,
|
|
363
|
+
loadModelInventory,
|
|
352
364
|
setStoragePath,
|
|
353
365
|
getStoragePath,
|
|
354
366
|
loadAccounts,
|
|
@@ -357,7 +369,7 @@ const runListOrStatusCommand = (rest) => runStatusCommand({
|
|
|
357
369
|
formatRateLimitEntry,
|
|
358
370
|
loadRuntimeObservabilitySnapshot: loadPersistedRuntimeObservabilitySnapshot,
|
|
359
371
|
loadAppBindStatus: async () => getAppBindStatus()
|
|
360
|
-
.then((status) => (status.running ? status.router : null))
|
|
372
|
+
.then((status) => (status.running && status.router ? { ...status.router, nativeOpenai: status.state?.nativeOpenai === true } : null))
|
|
361
373
|
.catch(() => null),
|
|
362
374
|
loadAppHelperStatus: readAppRuntimeHelperAccountSignal,
|
|
363
375
|
loadQuotaCache,
|
|
@@ -413,7 +425,11 @@ const CLI_COMMAND_HANDLERS = new Map([
|
|
|
413
425
|
saveAccounts,
|
|
414
426
|
}),
|
|
415
427
|
],
|
|
416
|
-
["check", () => runCheckCommand({
|
|
428
|
+
["check", (rest) => runCheckCommand({
|
|
429
|
+
runHealthCheck,
|
|
430
|
+
runResetCheck: () => runResetsCommand(["list", "--refresh"]),
|
|
431
|
+
runCapabilityCheck: () => refreshAndPrintModelInventory(console.log, { forceProbes: true }),
|
|
432
|
+
}, rest)],
|
|
417
433
|
[
|
|
418
434
|
"features",
|
|
419
435
|
() => runFeaturesCommand({ implementedFeatures: IMPLEMENTED_FEATURES }),
|
|
@@ -468,6 +484,7 @@ const CLI_COMMAND_HANDLERS = new Map([
|
|
|
468
484
|
}),
|
|
469
485
|
],
|
|
470
486
|
["usage", (rest) => runUsageCommand(rest)],
|
|
487
|
+
["resets", (rest) => runResetsCommand(rest)],
|
|
471
488
|
[
|
|
472
489
|
"rotation",
|
|
473
490
|
(rest) => runRotationCommand(rest, {
|
|
@@ -531,7 +548,9 @@ const CLI_COMMAND_HANDLERS = new Map([
|
|
|
531
548
|
],
|
|
532
549
|
["fix", (rest) => runRepairFix(rest, createRepairCommandDeps())],
|
|
533
550
|
["doctor", (rest) => runRepairDoctor(rest, createRepairCommandDeps())],
|
|
534
|
-
["uninstall", (rest) => runUninstallCommand(rest, {
|
|
551
|
+
["uninstall", (rest) => runUninstallCommand(rest, {
|
|
552
|
+
clearAccounts: () => clearAccountsAndCredentialSidecars(clearAccounts),
|
|
553
|
+
})],
|
|
535
554
|
[
|
|
536
555
|
"config",
|
|
537
556
|
(rest) => {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Bounded independent work, refilling free slots immediately and preserving result order. */
|
|
2
|
+
export declare function mapWithConcurrency<T, R>(items: readonly T[], limit: number, worker: (item: T, index: number) => Promise<R>): Promise<R[]>;
|
|
3
|
+
//# sourceMappingURL=concurrency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../lib/concurrency.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CA6B/I"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Bounded independent work, refilling free slots immediately and preserving result order. */
|
|
2
|
+
export async function mapWithConcurrency(items, limit, worker) {
|
|
3
|
+
if (!Number.isInteger(limit) || limit < 1)
|
|
4
|
+
throw new RangeError("Concurrency must be a positive integer");
|
|
5
|
+
const results = new Array(items.length);
|
|
6
|
+
let next = 0;
|
|
7
|
+
let failed = false;
|
|
8
|
+
let failure;
|
|
9
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, async () => {
|
|
10
|
+
while (!failed) {
|
|
11
|
+
const index = next++;
|
|
12
|
+
if (index >= items.length)
|
|
13
|
+
return;
|
|
14
|
+
const item = items[index];
|
|
15
|
+
if (item === undefined)
|
|
16
|
+
continue;
|
|
17
|
+
try {
|
|
18
|
+
results[index] = await worker(item, index);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (!failed)
|
|
22
|
+
failure = error;
|
|
23
|
+
failed = true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}));
|
|
27
|
+
// Drain active work before returning an error, so no detached writes survive the caller.
|
|
28
|
+
if (failed)
|
|
29
|
+
throw failure;
|
|
30
|
+
return results;
|
|
31
|
+
}
|
|
@@ -17,14 +17,14 @@ function buildPauseMessage(advisory) {
|
|
|
17
17
|
const windowNote = advisory.windowSource === "override"
|
|
18
18
|
? "your configured window size"
|
|
19
19
|
: "an estimated window size (unverified — set `contextBudgetGuardModelWindowOverrides` if you know the real limit)";
|
|
20
|
-
return `[Plugin Notice] Context budget guard paused this session at ${formatPercent(advisory.percent)}% of ${windowNote} for \`${advisory.model}\`, before hitting the model's actual limit.
|
|
21
|
-
|
|
22
|
-
Please use one of these commands to reduce context size:
|
|
23
|
-
|
|
24
|
-
• **/compact** - Compress conversation history (recommended)
|
|
25
|
-
• **/clear** - Start fresh with empty context
|
|
26
|
-
• **/undo** - Remove recent messages
|
|
27
|
-
|
|
20
|
+
return `[Plugin Notice] Context budget guard paused this session at ${formatPercent(advisory.percent)}% of ${windowNote} for \`${advisory.model}\`, before hitting the model's actual limit.
|
|
21
|
+
|
|
22
|
+
Please use one of these commands to reduce context size:
|
|
23
|
+
|
|
24
|
+
• **/compact** - Compress conversation history (recommended)
|
|
25
|
+
• **/clear** - Start fresh with empty context
|
|
26
|
+
• **/undo** - Remove recent messages
|
|
27
|
+
|
|
28
28
|
Then retry your request. This pause clears itself automatically once your context usage drops back below the threshold.`;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
@@ -33,16 +33,16 @@ export function isContextOverflowError(status, bodyText) {
|
|
|
33
33
|
/**
|
|
34
34
|
* The message shown to users when context overflow occurs
|
|
35
35
|
*/
|
|
36
|
-
const CONTEXT_OVERFLOW_MESSAGE = `[Plugin Notice] Context is too long for this model.
|
|
37
|
-
|
|
38
|
-
Please use one of these commands to reduce context size:
|
|
39
|
-
|
|
40
|
-
• **/compact** - Compress conversation history (recommended)
|
|
41
|
-
• **/clear** - Start fresh with empty context
|
|
42
|
-
• **/undo** - Remove recent messages
|
|
43
|
-
|
|
44
|
-
Then retry your request.
|
|
45
|
-
|
|
36
|
+
const CONTEXT_OVERFLOW_MESSAGE = `[Plugin Notice] Context is too long for this model.
|
|
37
|
+
|
|
38
|
+
Please use one of these commands to reduce context size:
|
|
39
|
+
|
|
40
|
+
• **/compact** - Compress conversation history (recommended)
|
|
41
|
+
• **/clear** - Start fresh with empty context
|
|
42
|
+
• **/undo** - Remove recent messages
|
|
43
|
+
|
|
44
|
+
Then retry your request.
|
|
45
|
+
|
|
46
46
|
Alternatively, you can switch to a model with a larger context window.`;
|
|
47
47
|
/**
|
|
48
48
|
* Creates a synthetic SSE response for context overflow errors.
|