codex-multi-auth 2.1.13-beta.2 → 2.2.1
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 -0
- package/README.md +5 -4
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +30 -1
- package/dist/lib/accounts.js.map +1 -1
- package/dist/lib/auth/device-auth.d.ts.map +1 -1
- package/dist/lib/auth/device-auth.js +15 -0
- package/dist/lib/auth/device-auth.js.map +1 -1
- package/dist/lib/auth/org-override.d.ts +19 -0
- package/dist/lib/auth/org-override.d.ts.map +1 -0
- package/dist/lib/auth/org-override.js +23 -0
- package/dist/lib/auth/org-override.js.map +1 -0
- package/dist/lib/auth/server.d.ts.map +1 -1
- package/dist/lib/auth/server.js +12 -7
- package/dist/lib/auth/server.js.map +1 -1
- package/dist/lib/capability-policy.d.ts.map +1 -1
- package/dist/lib/capability-policy.js +5 -0
- package/dist/lib/capability-policy.js.map +1 -1
- package/dist/lib/circuit-breaker.d.ts +6 -0
- package/dist/lib/circuit-breaker.d.ts.map +1 -1
- package/dist/lib/circuit-breaker.js +8 -0
- package/dist/lib/circuit-breaker.js.map +1 -1
- package/dist/lib/codex-cli/state.d.ts.map +1 -1
- package/dist/lib/codex-cli/state.js +28 -7
- package/dist/lib/codex-cli/state.js.map +1 -1
- package/dist/lib/codex-manager/account-manager-commands.d.ts +14 -0
- package/dist/lib/codex-manager/account-manager-commands.d.ts.map +1 -0
- package/dist/lib/codex-manager/account-manager-commands.js +43 -0
- package/dist/lib/codex-manager/account-manager-commands.js.map +1 -0
- package/dist/lib/codex-manager/commands/best.d.ts +1 -1
- package/dist/lib/codex-manager/commands/best.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/best.js +4 -3
- package/dist/lib/codex-manager/commands/best.js.map +1 -1
- package/dist/lib/codex-manager/commands/budget.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/budget.js +6 -0
- package/dist/lib/codex-manager/commands/budget.js.map +1 -1
- package/dist/lib/codex-manager/commands/debug-bundle.d.ts +16 -0
- package/dist/lib/codex-manager/commands/debug-bundle.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/debug-bundle.js +80 -5
- package/dist/lib/codex-manager/commands/debug-bundle.js.map +1 -1
- 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 +11 -8
- package/dist/lib/codex-manager/commands/forecast.js.map +1 -1
- package/dist/lib/codex-manager/commands/integrations.js +2 -2
- package/dist/lib/codex-manager/commands/integrations.js.map +1 -1
- package/dist/lib/codex-manager/commands/models.js +3 -3
- package/dist/lib/codex-manager/commands/models.js.map +1 -1
- package/dist/lib/codex-manager/commands/report.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/report.js +11 -9
- package/dist/lib/codex-manager/commands/report.js.map +1 -1
- package/dist/lib/codex-manager/commands/status.d.ts +2 -0
- package/dist/lib/codex-manager/commands/status.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/status.js +84 -25
- package/dist/lib/codex-manager/commands/status.js.map +1 -1
- package/dist/lib/codex-manager/commands/switch.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/switch.js +7 -0
- package/dist/lib/codex-manager/commands/switch.js.map +1 -1
- package/dist/lib/codex-manager/commands/workspace.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/workspace.js +12 -1
- package/dist/lib/codex-manager/commands/workspace.js.map +1 -1
- package/dist/lib/codex-manager/experimental-settings-prompt.d.ts.map +1 -1
- package/dist/lib/codex-manager/experimental-settings-prompt.js +13 -3
- package/dist/lib/codex-manager/experimental-settings-prompt.js.map +1 -1
- package/dist/lib/codex-manager/forecast-report-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/forecast-report-commands.js +14 -13
- package/dist/lib/codex-manager/forecast-report-commands.js.map +1 -1
- package/dist/lib/codex-manager/help.d.ts.map +1 -1
- package/dist/lib/codex-manager/help.js +7 -5
- package/dist/lib/codex-manager/help.js.map +1 -1
- package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/repair-commands.js +18 -8
- package/dist/lib/codex-manager/repair-commands.js.map +1 -1
- package/dist/lib/codex-manager/settings-hub/experimental.d.ts.map +1 -1
- package/dist/lib/codex-manager/settings-hub/experimental.js +8 -0
- package/dist/lib/codex-manager/settings-hub/experimental.js.map +1 -1
- package/dist/lib/codex-manager.d.ts +3 -0
- package/dist/lib/codex-manager.d.ts.map +1 -1
- package/dist/lib/codex-manager.js +121 -93
- package/dist/lib/codex-manager.js.map +1 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +327 -18
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/context-overflow.d.ts +7 -2
- package/dist/lib/context-overflow.d.ts.map +1 -1
- package/dist/lib/context-overflow.js +55 -37
- package/dist/lib/context-overflow.js.map +1 -1
- package/dist/lib/errors.d.ts +16 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +23 -0
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/forecast.d.ts +1 -0
- package/dist/lib/forecast.d.ts.map +1 -1
- package/dist/lib/forecast.js +25 -2
- package/dist/lib/forecast.js.map +1 -1
- package/dist/lib/integration-generators.d.ts.map +1 -1
- package/dist/lib/integration-generators.js +1 -1
- package/dist/lib/integration-generators.js.map +1 -1
- package/dist/lib/local-bridge.d.ts +8 -0
- package/dist/lib/local-bridge.d.ts.map +1 -1
- package/dist/lib/local-bridge.js +81 -7
- package/dist/lib/local-bridge.js.map +1 -1
- package/dist/lib/local-client-tokens.d.ts.map +1 -1
- package/dist/lib/local-client-tokens.js +117 -64
- package/dist/lib/local-client-tokens.js.map +1 -1
- package/dist/lib/logger.d.ts +9 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +104 -19
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/model-capability-matrix.d.ts.map +1 -1
- package/dist/lib/model-capability-matrix.js +13 -10
- package/dist/lib/model-capability-matrix.js.map +1 -1
- package/dist/lib/oc-chatgpt-orchestrator.d.ts +7 -1
- package/dist/lib/oc-chatgpt-orchestrator.d.ts.map +1 -1
- package/dist/lib/oc-chatgpt-orchestrator.js +68 -9
- package/dist/lib/oc-chatgpt-orchestrator.js.map +1 -1
- package/dist/lib/policy/runtime-policy.d.ts.map +1 -1
- package/dist/lib/policy/runtime-policy.js +23 -1
- package/dist/lib/policy/runtime-policy.js.map +1 -1
- package/dist/lib/prompts/codex.d.ts +1 -1
- package/dist/lib/prompts/codex.d.ts.map +1 -1
- package/dist/lib/prompts/codex.js +128 -33
- package/dist/lib/prompts/codex.js.map +1 -1
- package/dist/lib/prompts/fetch-utils.d.ts +72 -0
- package/dist/lib/prompts/fetch-utils.d.ts.map +1 -0
- package/dist/lib/prompts/fetch-utils.js +165 -0
- package/dist/lib/prompts/fetch-utils.js.map +1 -0
- package/dist/lib/prompts/host-codex-prompt.d.ts.map +1 -1
- package/dist/lib/prompts/host-codex-prompt.js +24 -10
- package/dist/lib/prompts/host-codex-prompt.js.map +1 -1
- package/dist/lib/quota-cache.d.ts.map +1 -1
- package/dist/lib/quota-cache.js +26 -2
- package/dist/lib/quota-cache.js.map +1 -1
- package/dist/lib/quota-probe.d.ts +21 -0
- package/dist/lib/quota-probe.d.ts.map +1 -1
- package/dist/lib/quota-probe.js +41 -1
- package/dist/lib/quota-probe.js.map +1 -1
- package/dist/lib/quota-readiness.d.ts +3 -1
- package/dist/lib/quota-readiness.d.ts.map +1 -1
- package/dist/lib/quota-readiness.js +16 -3
- package/dist/lib/quota-readiness.js.map +1 -1
- package/dist/lib/recovery/storage.d.ts +7 -0
- package/dist/lib/recovery/storage.d.ts.map +1 -1
- package/dist/lib/recovery/storage.js +178 -10
- package/dist/lib/recovery/storage.js.map +1 -1
- package/dist/lib/refresh-lease.d.ts +1 -1
- package/dist/lib/refresh-lease.d.ts.map +1 -1
- package/dist/lib/refresh-lease.js +25 -3
- package/dist/lib/refresh-lease.js.map +1 -1
- package/dist/lib/refresh-queue.d.ts.map +1 -1
- package/dist/lib/refresh-queue.js +31 -17
- package/dist/lib/refresh-queue.js.map +1 -1
- package/dist/lib/request/fetch-helpers.d.ts +0 -5
- package/dist/lib/request/fetch-helpers.d.ts.map +1 -1
- package/dist/lib/request/fetch-helpers.js +39 -7
- package/dist/lib/request/fetch-helpers.js.map +1 -1
- package/dist/lib/request/helpers/model-map.d.ts +1 -0
- package/dist/lib/request/helpers/model-map.d.ts.map +1 -1
- package/dist/lib/request/helpers/model-map.js +10 -0
- package/dist/lib/request/helpers/model-map.js.map +1 -1
- package/dist/lib/rotation.d.ts +12 -0
- package/dist/lib/rotation.d.ts.map +1 -1
- package/dist/lib/rotation.js +36 -0
- package/dist/lib/rotation.js.map +1 -1
- package/dist/lib/routing-mutex.d.ts +12 -0
- package/dist/lib/routing-mutex.d.ts.map +1 -1
- package/dist/lib/routing-mutex.js +38 -1
- package/dist/lib/routing-mutex.js.map +1 -1
- package/dist/lib/runtime/account-check-types.d.ts +1 -0
- package/dist/lib/runtime/account-check-types.d.ts.map +1 -1
- package/dist/lib/runtime/account-check-types.js +1 -0
- package/dist/lib/runtime/account-check-types.js.map +1 -1
- package/dist/lib/runtime/account-check.d.ts.map +1 -1
- package/dist/lib/runtime/account-check.js +15 -4
- package/dist/lib/runtime/account-check.js.map +1 -1
- package/dist/lib/runtime/quota-probe.d.ts.map +1 -1
- package/dist/lib/runtime/quota-probe.js +2 -5
- package/dist/lib/runtime/quota-probe.js.map +1 -1
- package/dist/lib/runtime/runtime-observability.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-observability.js +24 -2
- package/dist/lib/runtime/runtime-observability.js.map +1 -1
- package/dist/lib/runtime-rotation-proxy.d.ts +24 -1
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +289 -26
- package/dist/lib/runtime-rotation-proxy.js.map +1 -1
- package/dist/lib/storage/account-clear.d.ts.map +1 -1
- package/dist/lib/storage/account-clear.js +4 -2
- package/dist/lib/storage/account-clear.js.map +1 -1
- package/dist/lib/storage/account-persistence.d.ts.map +1 -1
- package/dist/lib/storage/account-persistence.js +11 -1
- package/dist/lib/storage/account-persistence.js.map +1 -1
- package/dist/lib/storage/flagged-storage-io.d.ts.map +1 -1
- package/dist/lib/storage/flagged-storage-io.js +4 -1
- package/dist/lib/storage/flagged-storage-io.js.map +1 -1
- package/dist/lib/storage/import-export.d.ts.map +1 -1
- package/dist/lib/storage/import-export.js +29 -9
- package/dist/lib/storage/import-export.js.map +1 -1
- package/dist/lib/storage/paths.d.ts.map +1 -1
- package/dist/lib/storage/paths.js +93 -0
- package/dist/lib/storage/paths.js.map +1 -1
- package/dist/lib/storage/record-utils.d.ts.map +1 -1
- package/dist/lib/storage/record-utils.js +6 -1
- package/dist/lib/storage/record-utils.js.map +1 -1
- package/dist/lib/storage/storage-parser.d.ts.map +1 -1
- package/dist/lib/storage/storage-parser.js +7 -1
- package/dist/lib/storage/storage-parser.js.map +1 -1
- package/dist/lib/storage/transactions.d.ts +8 -0
- package/dist/lib/storage/transactions.d.ts.map +1 -1
- package/dist/lib/storage/transactions.js +14 -1
- package/dist/lib/storage/transactions.js.map +1 -1
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +59 -18
- package/dist/lib/storage.js.map +1 -1
- package/dist/lib/table-formatter.d.ts.map +1 -1
- package/dist/lib/table-formatter.js +20 -2
- package/dist/lib/table-formatter.js.map +1 -1
- package/dist/lib/types.d.ts +7 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.js +8 -2
- package/dist/lib/ui/auth-menu.js.map +1 -1
- package/dist/lib/ui/display-width.d.ts +27 -0
- package/dist/lib/ui/display-width.d.ts.map +1 -0
- package/dist/lib/ui/display-width.js +194 -0
- package/dist/lib/ui/display-width.js.map +1 -0
- package/dist/lib/ui/select.d.ts +23 -0
- package/dist/lib/ui/select.d.ts.map +1 -1
- package/dist/lib/ui/select.js +64 -16
- package/dist/lib/ui/select.js.map +1 -1
- package/dist/lib/ui/theme.d.ts +13 -0
- package/dist/lib/ui/theme.d.ts.map +1 -1
- package/dist/lib/ui/theme.js +34 -1
- package/dist/lib/ui/theme.js.map +1 -1
- package/node_modules/@codex-ai/sdk/dist/index.d.ts +4 -0
- package/node_modules/@codex-ai/sdk/dist/index.js +2 -0
- package/node_modules/@codex-ai/sdk/package.json +8 -0
- package/package.json +10 -6
- package/scripts/codex-bin-resolver.js +28 -1
- package/scripts/codex-routing.js +3 -0
- package/scripts/codex.js +508 -1
- package/scripts/mcodex.js +367 -0
|
@@ -3,6 +3,7 @@ import { createInterface } from "node:readline/promises";
|
|
|
3
3
|
import { extractAccountEmail, extractAccountId, formatAccountLabel, formatWaitTime, getAccountIdCandidates, resolveRequestAccountId, sanitizeEmail, selectBestAccountCandidate, shouldUpdateAccountIdFromToken, } from "./accounts.js";
|
|
4
4
|
import { createAuthorizationFlow, exchangeAuthorizationCode, parseAuthorizationInput, redactOAuthUrlForLog, REDIRECT_URI, } from "./auth/auth.js";
|
|
5
5
|
import { runDeviceAuthFlow } from "./auth/device-auth.js";
|
|
6
|
+
import { resolveOrgOverride } from "./auth/org-override.js";
|
|
6
7
|
import { copyTextToClipboard, isBrowserLaunchSuppressed, openBrowserUrl, } from "./auth/browser.js";
|
|
7
8
|
import { startLocalOAuthServer } from "./auth/server.js";
|
|
8
9
|
import { promptAddAnotherAccount, promptLoginMode, } from "./cli.js";
|
|
@@ -10,6 +11,7 @@ import { loadCodexCliState } from "./codex-cli/state.js";
|
|
|
10
11
|
import { setCodexCliActiveSelection } from "./codex-cli/writer.js";
|
|
11
12
|
import { runBestCommand, } from "./codex-manager/commands/best.js";
|
|
12
13
|
import { runAccountCommand } from "./codex-manager/commands/account.js";
|
|
14
|
+
import { ACCOUNT_MANAGER_COMMANDS } from "./codex-manager/account-manager-commands.js";
|
|
13
15
|
import { runBudgetCommand } from "./codex-manager/commands/budget.js";
|
|
14
16
|
import { runBridgeCommand } from "./codex-manager/commands/bridge.js";
|
|
15
17
|
import { runCheckCommand } from "./codex-manager/commands/check.js";
|
|
@@ -44,12 +46,13 @@ import { DEFAULT_DASHBOARD_DISPLAY_SETTINGS, loadDashboardDisplaySettings, } fro
|
|
|
44
46
|
import { evaluateForecastAccounts, recommendForecastAccount, summarizeForecast, } from "./forecast.js";
|
|
45
47
|
import { createLogger } from "./logger.js";
|
|
46
48
|
import { MODEL_FAMILIES } from "./prompts/codex.js";
|
|
47
|
-
import { getModelCapabilities, getModelProfile, resolveNormalizedModel, } from "./request/helpers/model-map.js";
|
|
49
|
+
import { DEFAULT_MODEL, getModelCapabilities, getModelProfile, resolveNormalizedModel, } from "./request/helpers/model-map.js";
|
|
48
50
|
import { formatRateLimitEntry as formatAccountRateLimitEntry, getRateLimitResetTimeForFamily, resolveActiveIndex, } from "./runtime/account-status.js";
|
|
49
51
|
import { buildQuotaEmailFallbackState, hasSafeQuotaEmailFallback, hasUniqueQuotaAccountId, isQuotaCacheEntryExhausted, normalizeQuotaAccountId, normalizeQuotaEmail, quotaLeftPercentFromUsed, } from "./quota-readiness.js";
|
|
50
52
|
import { loadQuotaCache, saveQuotaCache, } from "./quota-cache.js";
|
|
51
53
|
import { isDisplayCurrentAccount, readAppRuntimeHelperAccountSignal, resolveAccountCurrentMarkers, resolveRuntimeCurrentAccount, } from "./runtime/runtime-current-account.js";
|
|
52
|
-
import { fetchCodexQuotaSnapshot, formatQuotaSnapshotLine, } from "./quota-probe.js";
|
|
54
|
+
import { fetchCodexQuotaSnapshot, formatQuotaSnapshotLine, CODEX_UNAVAILABLE_PROBE_NOTE, } from "./quota-probe.js";
|
|
55
|
+
import { isCodexUnavailableError } from "./errors.js";
|
|
53
56
|
import { queuedRefresh } from "./refresh-queue.js";
|
|
54
57
|
import { clearAccounts, findMatchingAccountIndex, formatStorageErrorHint, inspectStorageHealth, getLastAccountsSaveTimestamp, getNamedBackups, getStoragePath, loadAccounts, loadFlaggedAccounts, readAffinityGenerationFromDisk, restoreAccountsFromBackup, StorageError, saveAccounts, setStoragePath, withAccountStorageTransaction, } from "./storage.js";
|
|
55
58
|
import { ANSI } from "./ui/ansi.js";
|
|
@@ -59,36 +62,6 @@ import { paintUiText, quotaToneFromLeftPercent } from "./ui/format.js";
|
|
|
59
62
|
import { getUiRuntimeOptions } from "./ui/runtime.js";
|
|
60
63
|
import { select } from "./ui/select.js";
|
|
61
64
|
const log = createLogger("codex-manager");
|
|
62
|
-
const ACCOUNT_MANAGER_COMMANDS = new Set([
|
|
63
|
-
"login",
|
|
64
|
-
"list",
|
|
65
|
-
"status",
|
|
66
|
-
"switch",
|
|
67
|
-
"unpin",
|
|
68
|
-
"workspace",
|
|
69
|
-
"best",
|
|
70
|
-
"check",
|
|
71
|
-
"features",
|
|
72
|
-
"usage",
|
|
73
|
-
"verify-flagged",
|
|
74
|
-
"verify",
|
|
75
|
-
"forecast",
|
|
76
|
-
"report",
|
|
77
|
-
"fix",
|
|
78
|
-
"doctor",
|
|
79
|
-
"uninstall",
|
|
80
|
-
"account",
|
|
81
|
-
"budget",
|
|
82
|
-
"bridge",
|
|
83
|
-
"integrations",
|
|
84
|
-
"models",
|
|
85
|
-
"monitor",
|
|
86
|
-
"rotation",
|
|
87
|
-
"why-selected",
|
|
88
|
-
"config",
|
|
89
|
-
"init-config",
|
|
90
|
-
"debug",
|
|
91
|
-
]);
|
|
92
65
|
function stylePromptText(text, tone) {
|
|
93
66
|
if (!output.isTTY)
|
|
94
67
|
return text;
|
|
@@ -245,7 +218,7 @@ function styleQuotaSummary(summary) {
|
|
|
245
218
|
return stylePromptText(segment, "muted");
|
|
246
219
|
}
|
|
247
220
|
const windowLabel = match[1] ?? "";
|
|
248
|
-
const leftPercent = Number.parseInt(match[2] ?? "", 10);
|
|
221
|
+
const leftPercent = Math.max(0, Math.min(100, Number.parseInt(match[2] ?? "", 10)));
|
|
249
222
|
if (!Number.isFinite(leftPercent)) {
|
|
250
223
|
return stylePromptText(segment, "muted");
|
|
251
224
|
}
|
|
@@ -254,7 +227,10 @@ function styleQuotaSummary(summary) {
|
|
|
254
227
|
});
|
|
255
228
|
return joinStyledSegments(rendered);
|
|
256
229
|
}
|
|
257
|
-
|
|
230
|
+
// Exported for unit tests: tone precedence (danger before warning) is
|
|
231
|
+
// security/UX-relevant — a failure whose text contains "unavailable" must
|
|
232
|
+
// render red, not be downgraded to yellow. See test/codex-manager-detail-tone.test.ts.
|
|
233
|
+
export function styleAccountDetailText(detail, fallbackTone = "muted") {
|
|
258
234
|
const compact = collapseWhitespace(detail);
|
|
259
235
|
if (!compact)
|
|
260
236
|
return stylePromptText("", fallbackTone);
|
|
@@ -263,15 +239,24 @@ function styleAccountDetailText(detail, fallbackTone = "muted") {
|
|
|
263
239
|
const prefix = (quotaMatch[1] ?? "").trim();
|
|
264
240
|
const quota = (quotaMatch[2] ?? "").trim();
|
|
265
241
|
const suffix = (quotaMatch[3] ?? "").trim();
|
|
266
|
-
|
|
242
|
+
// danger wins across the WHOLE detail: a failure keyword anywhere — even
|
|
243
|
+
// trapped inside the (…%) quota segment, e.g.
|
|
244
|
+
// "signed in and working (live check failed: … 0%)" — must keep the prefix
|
|
245
|
+
// red, never let a "working"/"ok" prefix render green over a real failure.
|
|
246
|
+
const detailHasFailure = /failed|error|rate-limited/i.test(compact);
|
|
247
|
+
const prefixTone = detailHasFailure
|
|
267
248
|
? "danger"
|
|
268
|
-
:
|
|
249
|
+
: /\b(ok|working|succeeded|valid)\b/i.test(prefix)
|
|
269
250
|
? "success"
|
|
270
251
|
: fallbackTone;
|
|
271
|
-
const suffixTone =
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
252
|
+
const suffixTone =
|
|
253
|
+
// danger wins first: a real failure whose text happens to contain
|
|
254
|
+
// "unavailable"/"not available" (e.g. a 5xx "service not available")
|
|
255
|
+
// must render red, not be downgraded to a yellow warning.
|
|
256
|
+
/failed|error/i.test(suffix)
|
|
257
|
+
? "danger"
|
|
258
|
+
: /re-login|stale|warning|retry|fallback|unavailable|not available/i.test(suffix)
|
|
259
|
+
? "warning"
|
|
275
260
|
: "muted";
|
|
276
261
|
const chunks = [];
|
|
277
262
|
if (prefix)
|
|
@@ -283,11 +268,11 @@ function styleAccountDetailText(detail, fallbackTone = "muted") {
|
|
|
283
268
|
}
|
|
284
269
|
if (/rate-limited/i.test(compact))
|
|
285
270
|
return stylePromptText(compact, "danger");
|
|
286
|
-
if (/re-login|stale|warning|fallback/i.test(compact))
|
|
287
|
-
return stylePromptText(compact, "warning");
|
|
288
271
|
if (/failed|error/i.test(compact))
|
|
289
272
|
return stylePromptText(compact, "danger");
|
|
290
|
-
if (/
|
|
273
|
+
if (/re-login|stale|warning|fallback|unavailable|not available/i.test(compact))
|
|
274
|
+
return stylePromptText(compact, "warning");
|
|
275
|
+
if (/\b(ok|working|succeeded|valid)\b/i.test(compact))
|
|
291
276
|
return stylePromptText(compact, "success");
|
|
292
277
|
return stylePromptText(compact, fallbackTone);
|
|
293
278
|
}
|
|
@@ -461,7 +446,7 @@ function getPersistedQuotaViewForAccount(cache, account, accounts, now, emailFal
|
|
|
461
446
|
return {
|
|
462
447
|
updatedAt: cachedEntry?.updatedAt ?? now,
|
|
463
448
|
status: 429,
|
|
464
|
-
model: cachedEntry?.model ??
|
|
449
|
+
model: cachedEntry?.model ?? DEFAULT_MODEL,
|
|
465
450
|
planType: cachedEntry?.planType,
|
|
466
451
|
primary: {
|
|
467
452
|
...cachedEntry?.primary,
|
|
@@ -529,7 +514,8 @@ function pruneUnsafeQuotaEmailCacheEntry(cache, email, accounts, emailFallbackSt
|
|
|
529
514
|
return true;
|
|
530
515
|
}
|
|
531
516
|
const DEFAULT_MENU_QUOTA_REFRESH_TTL_MS = 5 * 60_000;
|
|
532
|
-
const
|
|
517
|
+
const DEFAULT_LIVE_PROBE_MODEL = DEFAULT_MODEL;
|
|
518
|
+
const MENU_QUOTA_REFRESH_MODEL = DEFAULT_LIVE_PROBE_MODEL;
|
|
533
519
|
function resolveMenuQuotaProbeInput(account, cache, maxAgeMs, now, accounts, emailFallbackState = buildQuotaEmailFallbackState(accounts)) {
|
|
534
520
|
if (account.enabled === false)
|
|
535
521
|
return null;
|
|
@@ -860,8 +846,17 @@ async function syncCodexCliActiveSelectionIfDrifted(storage) {
|
|
|
860
846
|
return false;
|
|
861
847
|
}
|
|
862
848
|
}
|
|
863
|
-
|
|
864
|
-
|
|
849
|
+
/**
|
|
850
|
+
* Resolve the account-id selection for freshly-minted tokens.
|
|
851
|
+
*
|
|
852
|
+
* The org-override precedence (explicit `login --org` wins over the ambient
|
|
853
|
+
* CODEX_AUTH_ACCOUNT_ID env, for this call only) lives in the internal
|
|
854
|
+
* lib/auth/org-override.ts module so it can be unit-tested without exporting this
|
|
855
|
+
* CLI-internal function. Threading the org as a parameter avoids mutating
|
|
856
|
+
* process.env for the duration of a login, which raced on concurrent re-entry.
|
|
857
|
+
*/
|
|
858
|
+
function resolveAccountSelection(tokens, orgOverride) {
|
|
859
|
+
const override = resolveOrgOverride(orgOverride);
|
|
865
860
|
if (override) {
|
|
866
861
|
return {
|
|
867
862
|
...tokens,
|
|
@@ -1592,7 +1587,7 @@ async function syncSelectionToCodex(tokens) {
|
|
|
1592
1587
|
async function runHealthCheck(options = {}) {
|
|
1593
1588
|
const forceRefresh = options.forceRefresh === true;
|
|
1594
1589
|
const liveProbe = options.liveProbe === true;
|
|
1595
|
-
const probeModel = options.model?.trim() ||
|
|
1590
|
+
const probeModel = options.model?.trim() || DEFAULT_LIVE_PROBE_MODEL;
|
|
1596
1591
|
const modelInspection = inspectRequestedModel(probeModel);
|
|
1597
1592
|
const display = options.display ?? DEFAULT_DASHBOARD_DISPLAY_SETTINGS;
|
|
1598
1593
|
const quotaCache = liveProbe ? await loadQuotaCache() : null;
|
|
@@ -1611,6 +1606,8 @@ async function runHealthCheck(options = {}) {
|
|
|
1611
1606
|
let ok = 0;
|
|
1612
1607
|
let failed = 0;
|
|
1613
1608
|
let warnings = 0;
|
|
1609
|
+
let codexAvailable = 0;
|
|
1610
|
+
let signedInOnly = 0;
|
|
1614
1611
|
const activeIndex = resolveActiveIndex(storage, "codex");
|
|
1615
1612
|
let activeAccountRefreshed = false;
|
|
1616
1613
|
const now = Date.now();
|
|
@@ -1636,6 +1633,7 @@ async function runHealthCheck(options = {}) {
|
|
|
1636
1633
|
activeAccountRefreshed = true;
|
|
1637
1634
|
}
|
|
1638
1635
|
let healthDetail = "signed in and working";
|
|
1636
|
+
let healthTone = "success";
|
|
1639
1637
|
if (liveProbe) {
|
|
1640
1638
|
const currentAccessToken = account.accessToken;
|
|
1641
1639
|
const probeAccountId = currentAccessToken
|
|
@@ -1643,8 +1641,10 @@ async function runHealthCheck(options = {}) {
|
|
|
1643
1641
|
: undefined;
|
|
1644
1642
|
if (!probeAccountId || !currentAccessToken) {
|
|
1645
1643
|
warnings += 1;
|
|
1644
|
+
signedInOnly += 1;
|
|
1645
|
+
healthTone = "warning";
|
|
1646
1646
|
healthDetail =
|
|
1647
|
-
"signed in
|
|
1647
|
+
"signed in (live check skipped: missing account ID)";
|
|
1648
1648
|
}
|
|
1649
1649
|
else {
|
|
1650
1650
|
try {
|
|
@@ -1658,11 +1658,20 @@ async function runHealthCheck(options = {}) {
|
|
|
1658
1658
|
updateQuotaCacheForAccount(workingQuotaCache, account, snapshot, storage.accounts, quotaEmailFallbackState ?? undefined) || quotaCacheChanged;
|
|
1659
1659
|
}
|
|
1660
1660
|
healthDetail = formatQuotaSnapshotForDashboard(snapshot, display);
|
|
1661
|
+
codexAvailable += 1;
|
|
1661
1662
|
}
|
|
1662
1663
|
catch (error) {
|
|
1663
|
-
const message = normalizeFailureDetail(error instanceof Error ? error.message : String(error), undefined);
|
|
1664
1664
|
warnings += 1;
|
|
1665
|
-
|
|
1665
|
+
signedInOnly += 1;
|
|
1666
|
+
healthTone = "warning";
|
|
1667
|
+
if (isCodexUnavailableError(error)) {
|
|
1668
|
+
healthDetail =
|
|
1669
|
+
`signed in; ${CODEX_UNAVAILABLE_PROBE_NOTE}`;
|
|
1670
|
+
}
|
|
1671
|
+
else {
|
|
1672
|
+
const message = normalizeFailureDetail(error instanceof Error ? error.message : String(error), undefined);
|
|
1673
|
+
healthDetail = `signed in (live check failed: ${message})`;
|
|
1674
|
+
}
|
|
1666
1675
|
}
|
|
1667
1676
|
}
|
|
1668
1677
|
}
|
|
@@ -1671,7 +1680,8 @@ async function runHealthCheck(options = {}) {
|
|
|
1671
1680
|
}
|
|
1672
1681
|
ok += 1;
|
|
1673
1682
|
if (display.showPerAccountRows) {
|
|
1674
|
-
|
|
1683
|
+
const healthMarker = healthTone === "success" ? "✓" : "!";
|
|
1684
|
+
console.log(` ${stylePromptText(healthMarker, healthTone)} ${labelText} ${stylePromptText("|", "muted")} ${styleAccountDetailText(healthDetail, healthTone)}`);
|
|
1675
1685
|
}
|
|
1676
1686
|
continue;
|
|
1677
1687
|
}
|
|
@@ -1717,12 +1727,15 @@ async function runHealthCheck(options = {}) {
|
|
|
1717
1727
|
}
|
|
1718
1728
|
ok += 1;
|
|
1719
1729
|
let healthyMessage = "working now";
|
|
1730
|
+
let healthyTone = "success";
|
|
1720
1731
|
if (liveProbe) {
|
|
1721
1732
|
const probeAccountId = account.accountId ?? tokenAccountId;
|
|
1722
1733
|
if (!probeAccountId) {
|
|
1723
1734
|
warnings += 1;
|
|
1735
|
+
signedInOnly += 1;
|
|
1736
|
+
healthyTone = "warning";
|
|
1724
1737
|
healthyMessage =
|
|
1725
|
-
"
|
|
1738
|
+
"signed in (live check skipped: missing account ID)";
|
|
1726
1739
|
}
|
|
1727
1740
|
else {
|
|
1728
1741
|
try {
|
|
@@ -1736,22 +1749,35 @@ async function runHealthCheck(options = {}) {
|
|
|
1736
1749
|
updateQuotaCacheForAccount(workingQuotaCache, account, snapshot, storage.accounts, quotaEmailFallbackState ?? undefined) || quotaCacheChanged;
|
|
1737
1750
|
}
|
|
1738
1751
|
healthyMessage = formatQuotaSnapshotForDashboard(snapshot, display);
|
|
1752
|
+
codexAvailable += 1;
|
|
1739
1753
|
}
|
|
1740
1754
|
catch (error) {
|
|
1741
|
-
const message = normalizeFailureDetail(error instanceof Error ? error.message : String(error), undefined);
|
|
1742
1755
|
warnings += 1;
|
|
1743
|
-
|
|
1756
|
+
signedInOnly += 1;
|
|
1757
|
+
healthyTone = "warning";
|
|
1758
|
+
if (isCodexUnavailableError(error)) {
|
|
1759
|
+
healthyMessage =
|
|
1760
|
+
`signed in; ${CODEX_UNAVAILABLE_PROBE_NOTE}`;
|
|
1761
|
+
}
|
|
1762
|
+
else {
|
|
1763
|
+
const message = normalizeFailureDetail(error instanceof Error ? error.message : String(error), undefined);
|
|
1764
|
+
healthyMessage = `signed in (live check failed: ${message})`;
|
|
1765
|
+
}
|
|
1744
1766
|
}
|
|
1745
1767
|
}
|
|
1746
1768
|
}
|
|
1747
1769
|
if (display.showPerAccountRows) {
|
|
1748
|
-
|
|
1770
|
+
const healthyMarker = healthyTone === "success" ? "✓" : "!";
|
|
1771
|
+
console.log(` ${stylePromptText(healthyMarker, healthyTone)} ${labelText} ${stylePromptText("|", "muted")} ${styleAccountDetailText(healthyMessage, healthyTone)}`);
|
|
1749
1772
|
}
|
|
1750
1773
|
}
|
|
1751
1774
|
else {
|
|
1752
1775
|
const detail = normalizeFailureDetail(result.message, result.reason);
|
|
1753
1776
|
if (sessionLikelyValid) {
|
|
1754
1777
|
warnings += 1;
|
|
1778
|
+
if (liveProbe) {
|
|
1779
|
+
signedInOnly += 1;
|
|
1780
|
+
}
|
|
1755
1781
|
if (display.showPerAccountRows) {
|
|
1756
1782
|
console.log(` ${stylePromptText("!", "warning")} ${labelText} ${stylePromptText("|", "muted")} ${stylePromptText(`refresh failed (${detail}) but this account still works right now`, "warning")}`);
|
|
1757
1783
|
}
|
|
@@ -1795,17 +1821,32 @@ async function runHealthCheck(options = {}) {
|
|
|
1795
1821
|
}
|
|
1796
1822
|
}
|
|
1797
1823
|
console.log("");
|
|
1798
|
-
console.log(formatResultSummary(
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1824
|
+
console.log(formatResultSummary(liveProbe
|
|
1825
|
+
? [
|
|
1826
|
+
{
|
|
1827
|
+
text: `${codexAvailable} Codex available`,
|
|
1828
|
+
tone: codexAvailable > 0 ? "success" : "muted",
|
|
1829
|
+
},
|
|
1830
|
+
{
|
|
1831
|
+
text: `${signedInOnly} signed in only`,
|
|
1832
|
+
tone: signedInOnly > 0 ? "warning" : "muted",
|
|
1833
|
+
},
|
|
1834
|
+
{
|
|
1835
|
+
text: `${failed} need re-login`,
|
|
1836
|
+
tone: failed > 0 ? "danger" : "muted",
|
|
1837
|
+
},
|
|
1838
|
+
]
|
|
1839
|
+
: [
|
|
1840
|
+
{ text: `${ok} working`, tone: "success" },
|
|
1841
|
+
{
|
|
1842
|
+
text: `${failed} need re-login`,
|
|
1843
|
+
tone: failed > 0 ? "danger" : "muted",
|
|
1844
|
+
},
|
|
1845
|
+
{
|
|
1846
|
+
text: `${warnings} warning${warnings === 1 ? "" : "s"}`,
|
|
1847
|
+
tone: warnings > 0 ? "warning" : "muted",
|
|
1848
|
+
},
|
|
1849
|
+
]));
|
|
1809
1850
|
}
|
|
1810
1851
|
function printBestUsage() {
|
|
1811
1852
|
console.log([
|
|
@@ -1815,7 +1856,7 @@ function printBestUsage() {
|
|
|
1815
1856
|
"Options:",
|
|
1816
1857
|
" --live, -l Probe live quota headers via Codex backend before switching",
|
|
1817
1858
|
" --json, -j Print machine-readable JSON output",
|
|
1818
|
-
|
|
1859
|
+
` --model, -m Probe model for live mode (default: ${DEFAULT_LIVE_PROBE_MODEL})`,
|
|
1819
1860
|
"",
|
|
1820
1861
|
"Behavior:",
|
|
1821
1862
|
" - Chooses the healthiest account using forecast scoring",
|
|
@@ -1826,7 +1867,7 @@ function parseBestArgs(args) {
|
|
|
1826
1867
|
const options = {
|
|
1827
1868
|
live: false,
|
|
1828
1869
|
json: false,
|
|
1829
|
-
model:
|
|
1870
|
+
model: DEFAULT_LIVE_PROBE_MODEL,
|
|
1830
1871
|
modelProvided: false,
|
|
1831
1872
|
};
|
|
1832
1873
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -1842,8 +1883,8 @@ function parseBestArgs(args) {
|
|
|
1842
1883
|
continue;
|
|
1843
1884
|
}
|
|
1844
1885
|
if (arg === "--model" || arg === "-m") {
|
|
1845
|
-
const value = args[i + 1];
|
|
1846
|
-
if (!value) {
|
|
1886
|
+
const value = args[i + 1]?.trim();
|
|
1887
|
+
if (!value || value.startsWith("-")) {
|
|
1847
1888
|
return { ok: false, message: "Missing value for --model" };
|
|
1848
1889
|
}
|
|
1849
1890
|
options.model = value;
|
|
@@ -1853,7 +1894,7 @@ function parseBestArgs(args) {
|
|
|
1853
1894
|
}
|
|
1854
1895
|
if (arg.startsWith("--model=")) {
|
|
1855
1896
|
const value = arg.slice("--model=".length).trim();
|
|
1856
|
-
if (!value) {
|
|
1897
|
+
if (!value || value.startsWith("-")) {
|
|
1857
1898
|
return { ok: false, message: "Missing value for --model" };
|
|
1858
1899
|
}
|
|
1859
1900
|
options.model = value;
|
|
@@ -2074,27 +2115,13 @@ async function runAuthLogin(args) {
|
|
|
2074
2115
|
const loginOptions = parsedArgs.options;
|
|
2075
2116
|
// `--org <id>` binds this login to a specific workspace/org so the same
|
|
2076
2117
|
// email's personal vs business/team workspace can be registered on demand
|
|
2077
|
-
// (issue #491).
|
|
2078
|
-
//
|
|
2079
|
-
//
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
return runAuthLoginFlow(loginOptions);
|
|
2083
|
-
}
|
|
2084
|
-
const previousAccountIdOverride = process.env.CODEX_AUTH_ACCOUNT_ID;
|
|
2085
|
-
process.env.CODEX_AUTH_ACCOUNT_ID = loginOptions.org;
|
|
2086
|
-
console.log(`Binding this login to workspace org id: ${loginOptions.org}`);
|
|
2087
|
-
try {
|
|
2088
|
-
return await runAuthLoginFlow(loginOptions);
|
|
2089
|
-
}
|
|
2090
|
-
finally {
|
|
2091
|
-
if (previousAccountIdOverride === undefined) {
|
|
2092
|
-
delete process.env.CODEX_AUTH_ACCOUNT_ID;
|
|
2093
|
-
}
|
|
2094
|
-
else {
|
|
2095
|
-
process.env.CODEX_AUTH_ACCOUNT_ID = previousAccountIdOverride;
|
|
2096
|
-
}
|
|
2118
|
+
// (issue #491). The org is threaded explicitly into resolveAccountSelection
|
|
2119
|
+
// (no process.env mutation), so concurrent re-entry (menu re-entry, a reused
|
|
2120
|
+
// test worker) can never bind a login to a stale org via a shared global.
|
|
2121
|
+
if (loginOptions.org) {
|
|
2122
|
+
console.log(`Binding this login to workspace org id: ${loginOptions.org}`);
|
|
2097
2123
|
}
|
|
2124
|
+
return runAuthLoginFlow(loginOptions);
|
|
2098
2125
|
}
|
|
2099
2126
|
async function runAuthLoginFlow(loginOptions) {
|
|
2100
2127
|
setStoragePath(null);
|
|
@@ -2368,7 +2395,7 @@ async function runAuthLoginFlow(loginOptions) {
|
|
|
2368
2395
|
console.error(`Login failed: ${tokenResult.message ?? tokenResult.reason ?? "unknown error"}`);
|
|
2369
2396
|
return 1;
|
|
2370
2397
|
}
|
|
2371
|
-
const resolved = resolveAccountSelection(tokenResult);
|
|
2398
|
+
const resolved = resolveAccountSelection(tokenResult, loginOptions.org);
|
|
2372
2399
|
await persistAccountPool([resolved], false);
|
|
2373
2400
|
await syncSelectionToCodex(resolved);
|
|
2374
2401
|
const latestStorage = await loadAccounts();
|
|
@@ -2688,6 +2715,7 @@ export async function runCodexMultiAuthCli(rawArgs) {
|
|
|
2688
2715
|
.catch(() => null),
|
|
2689
2716
|
loadAppHelperStatus: readAppRuntimeHelperAccountSignal,
|
|
2690
2717
|
loadQuotaCache,
|
|
2718
|
+
json: rest.includes("--json") || rest.includes("-j"),
|
|
2691
2719
|
});
|
|
2692
2720
|
}
|
|
2693
2721
|
if (command === "switch") {
|