codex-multi-auth 2.22.0 → 2.24.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 +9 -9
- package/LICENSE +21 -21
- package/README.md +159 -150
- 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 +1021 -1021
- package/config/codex-modern.json +347 -347
- package/config/minimal-codex.json +15 -15
- package/config/schema/config.schema.json +8 -0
- package/dist/index.js +33 -10
- package/dist/lib/account-policy.d.ts +2 -0
- package/dist/lib/account-policy.js +3 -1
- package/dist/lib/accounts/rate-limits.d.ts +6 -0
- package/dist/lib/accounts/rate-limits.js +14 -1
- package/dist/lib/accounts.d.ts +6 -1
- package/dist/lib/accounts.js +33 -8
- package/dist/lib/api-route-store.d.ts +1 -0
- package/dist/lib/api-route-store.js +2 -1
- package/dist/lib/auth/account-access.js +2 -1
- package/dist/lib/auth/auth.js +3 -2
- package/dist/lib/auth/device-auth.js +2 -1
- package/dist/lib/auth/http.d.ts +1 -0
- package/dist/lib/auth/http.js +1 -0
- package/dist/lib/auth/token-utils.d.ts +5 -0
- package/dist/lib/auth/token-utils.js +10 -0
- package/dist/lib/codex-manager/account-manager-commands.js +1 -0
- package/dist/lib/codex-manager/commands/account.js +15 -0
- package/dist/lib/codex-manager/commands/locale.d.ts +12 -0
- package/dist/lib/codex-manager/commands/locale.js +25 -0
- package/dist/lib/codex-manager/commands/resets.js +18 -5
- package/dist/lib/codex-manager/commands/status.d.ts +4 -0
- package/dist/lib/codex-manager/commands/status.js +476 -5
- package/dist/lib/codex-manager/commands/workspace.d.ts +4 -2
- package/dist/lib/codex-manager/commands/workspace.js +33 -2
- package/dist/lib/codex-manager/help.js +5 -3
- package/dist/lib/codex-manager.js +112 -30
- package/dist/lib/config.js +3 -0
- package/dist/lib/constants.d.ts +2 -0
- package/dist/lib/constants.js +2 -0
- package/dist/lib/context-budget-response.js +8 -8
- package/dist/lib/context-overflow.js +10 -10
- package/dist/lib/locale.d.ts +7 -0
- package/dist/lib/locale.js +35 -0
- package/dist/lib/oauth-success.html +125 -125
- package/dist/lib/policy/runtime-policy-cache.js +1 -1
- package/dist/lib/policy/runtime-policy.d.ts +1 -0
- package/dist/lib/policy/runtime-policy.js +4 -0
- package/dist/lib/preemptive-quota-scheduler.js +12 -3
- 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 +4 -0
- package/dist/lib/quota-probe.js +2 -1
- package/dist/lib/quota-readiness.d.ts +1 -1
- package/dist/lib/quota-readiness.js +9 -2
- package/dist/lib/request/proxy-fetch.d.ts +5 -0
- package/dist/lib/request/proxy-fetch.js +37 -0
- package/dist/lib/request/rate-limit-decision.js +1 -1
- package/dist/lib/request/url-rewriting.js +17 -0
- package/dist/lib/runtime/account-model-catalog.d.ts +2 -0
- package/dist/lib/runtime/account-model-catalog.js +7 -2
- package/dist/lib/runtime/account-reset-credits.d.ts +11 -2
- package/dist/lib/runtime/account-reset-credits.js +35 -12
- package/dist/lib/runtime/app-bind.d.ts +4 -1
- package/dist/lib/runtime/app-bind.js +63 -3
- package/dist/lib/runtime/automatic-account-checks.js +6 -5
- package/dist/lib/runtime/automatic-subscription-checks.js +4 -3
- package/dist/lib/runtime/model-discovery-status.js +2 -2
- package/dist/lib/runtime/reset-credit-routing.d.ts +11 -3
- package/dist/lib/runtime/reset-credit-routing.js +66 -21
- package/dist/lib/runtime/reset-credits.d.ts +31 -7
- package/dist/lib/runtime/reset-credits.js +135 -28
- package/dist/lib/runtime/responses-websocket.d.ts +30 -0
- package/dist/lib/runtime/responses-websocket.js +243 -29
- package/dist/lib/runtime/rotation-account-selection.d.ts +5 -4
- package/dist/lib/runtime/rotation-proxy-state.d.ts +3 -0
- package/dist/lib/runtime/rotation-server-types.d.ts +4 -1
- package/dist/lib/runtime/subscription-quota-order.d.ts +1 -0
- package/dist/lib/runtime/subscription-quota-order.js +7 -3
- package/dist/lib/runtime/workspace-model-scopes.d.ts +2 -0
- package/dist/lib/runtime/workspace-model-scopes.js +14 -4
- package/dist/lib/runtime-rotation-proxy.js +138 -38
- package/dist/lib/schemas.d.ts +5 -0
- package/dist/lib/schemas.js +1 -0
- package/dist/lib/storage/snapshot-merge.js +15 -4
- package/dist/lib/web-dashboard-html.d.ts +1 -0
- package/dist/lib/web-dashboard-html.js +66 -0
- package/dist/lib/web-dashboard.d.ts +36 -0
- package/dist/lib/web-dashboard.js +322 -0
- 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 +209 -207
- package/scripts/codex-app-launcher.js +653 -653
- package/scripts/codex-app-router.js +446 -402
- package/scripts/codex-bin-resolver.js +332 -332
- package/scripts/codex-multi-auth.js +65 -65
- package/scripts/codex-routing.js +63 -62
- package/scripts/codex.js +7143 -7006
- 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/skills/codex-auth-setup/SKILL.md +73 -73
- 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
|
@@ -7,7 +7,8 @@ export function printUsage() {
|
|
|
7
7
|
"Start here:",
|
|
8
8
|
" codex-multi-auth login [--device-auth|--manual|--no-browser] [--org <org_id>] [--preserve-selection] [--account <index|email|account_id>]",
|
|
9
9
|
" codex-multi-auth login --api (API credentials and visible models)",
|
|
10
|
-
" codex-multi-auth status [--json] (list is the same command)",
|
|
10
|
+
" codex-multi-auth status [--json|--details] (list is the same command)",
|
|
11
|
+
" codex-multi-auth web [--port 4317] [--no-open] (local real-time pool dashboard)",
|
|
11
12
|
" codex-multi-auth check [accounts|resets|capabilities] [--prime] (default: all checks)",
|
|
12
13
|
" codex-multi-auth limits --json [--refresh] (structured quota windows; refresh is age-gated)",
|
|
13
14
|
"",
|
|
@@ -16,10 +17,10 @@ export function printUsage() {
|
|
|
16
17
|
" codex-multi-auth switch <index> (pins the account for runtime routing)",
|
|
17
18
|
" codex-multi-auth resets list [--refresh] | redeem <account> | auto manual|last-resort",
|
|
18
19
|
" codex-multi-auth unpin (clears the manual pin set by switch)",
|
|
19
|
-
" codex-multi-auth workspace <account> [workspace] (list or
|
|
20
|
+
" codex-multi-auth workspace <account> [workspace] (list or select; add enable/disable to change availability)",
|
|
20
21
|
" codex-multi-auth best [--live] [--json] [--model <model>] (clears any manual pin set by switch)",
|
|
21
22
|
" codex-multi-auth forecast [--live] [--json] [--explain] [--model <model>] [--no-runtime-overlay]",
|
|
22
|
-
" codex-multi-auth account tag|untag|weight|priority|auto-prime|pause|unpause|drain|undrain|note|policy list ...",
|
|
23
|
+
" codex-multi-auth account tag|untag|weight|priority|auto-prime|emergency-only|pause|unpause|drain|undrain|note|policy list ...",
|
|
23
24
|
"",
|
|
24
25
|
"Repair:",
|
|
25
26
|
" codex-multi-auth uninstall [--dry-run] [--json] [--clear-accounts]",
|
|
@@ -41,6 +42,7 @@ export function printUsage() {
|
|
|
41
42
|
" codex-multi-auth rotation reset-rate-limits [--all | --account <idx>] [--dry-run] [--json]",
|
|
42
43
|
" codex-multi-auth why-selected [--now|-n | --last|-l] [--json]",
|
|
43
44
|
" codex-multi-auth history [list|show <id>] [--json] (all local sessions, ignores /resume provider filtering)",
|
|
45
|
+
" codex-multi-auth config locale [auto|en|zh] (language; auto follows the system locale)",
|
|
44
46
|
"",
|
|
45
47
|
"Advanced:",
|
|
46
48
|
" codex-multi-auth report [--live] [--json] [--explain] [--model <model>] [--max-accounts <n>] [--max-probes <n>] [--cached-only] [--out <path>]",
|
|
@@ -39,10 +39,13 @@ import { runInitConfigCommand } from "./codex-manager/commands/init-config.js";
|
|
|
39
39
|
import { runReportCommand } from "./codex-manager/commands/report.js";
|
|
40
40
|
import { runRotationCommand } from "./codex-manager/commands/rotation.js";
|
|
41
41
|
import { runFeaturesCommand, runStatusCommand, } from "./codex-manager/commands/status.js";
|
|
42
|
+
import { runWebCommand } from "./web-dashboard.js";
|
|
42
43
|
import { loadPersistedRuntimeObservabilitySnapshot } from "./runtime/runtime-observability.js";
|
|
43
44
|
import { runSwitchCommand } from "./codex-manager/commands/switch.js";
|
|
44
45
|
import { runHistoryCommand } from "./codex-manager/commands/history.js";
|
|
46
|
+
import { runLocaleCommand } from "./codex-manager/commands/locale.js";
|
|
45
47
|
import { runUnpinCommand } from "./codex-manager/commands/unpin.js";
|
|
48
|
+
import { resolveOutputLocale } from "./locale.js";
|
|
46
49
|
import { runWorkspaceCommand } from "./codex-manager/commands/workspace.js";
|
|
47
50
|
import { runUsageCommand } from "./codex-manager/commands/usage.js";
|
|
48
51
|
import { refreshQuotaCacheForMenu } from "./codex-manager/login-menu-data.js";
|
|
@@ -60,7 +63,7 @@ import { loadQuotaCache, saveQuotaCache } from "./quota-cache.js";
|
|
|
60
63
|
import { readAppRuntimeHelperAccountSignal } from "./runtime/runtime-current-account.js";
|
|
61
64
|
import { fetchCodexQuotaSnapshot, formatQuotaSnapshotLine, } from "./quota-probe.js";
|
|
62
65
|
import { queuedRefresh } from "./refresh-queue.js";
|
|
63
|
-
import { clearAccounts, inspectStorageHealth, getLastAccountsSaveTimestamp, getStoragePath, loadAccounts, loadFlaggedAccounts, saveAccounts, setStoragePath, } from "./storage.js";
|
|
66
|
+
import { clearAccounts, inspectStorageHealth, getLastAccountsSaveTimestamp, getStoragePath, loadAccounts, loadFlaggedAccounts, saveAccounts, setStoragePath, withAccountStorageTransaction, } from "./storage.js";
|
|
64
67
|
// Formatter implementations moved to lib/codex-manager/formatters/ (audit
|
|
65
68
|
// roadmap §4.1.1 phase 1). Re-exported here so existing consumers importing
|
|
66
69
|
// from lib/codex-manager.js keep working unchanged.
|
|
@@ -140,6 +143,7 @@ const IMPLEMENTED_FEATURES = [
|
|
|
140
143
|
{ id: 52, name: "Why-selected and monitor diagnostics" },
|
|
141
144
|
{ id: 53, name: "Config explain, init-config templates, and debug bundle" },
|
|
142
145
|
{ id: 54, name: "mcodex convenience launcher (monitor/tmux/forward)" },
|
|
146
|
+
{ id: 55, name: "Local real-time web pool dashboard" },
|
|
143
147
|
];
|
|
144
148
|
async function runForecast(args) {
|
|
145
149
|
return runForecastCommand(args, {
|
|
@@ -252,6 +256,18 @@ export function buildSelectAccountTraced() {
|
|
|
252
256
|
blockedReasonByAccount[index] = AUTH_INVALIDATION_MARKER;
|
|
253
257
|
}
|
|
254
258
|
}
|
|
259
|
+
// This offline diagnostic cannot establish ordinary-pool exhaustion or
|
|
260
|
+
// perform permitted reset recovery. Leave emergency capacity reserved;
|
|
261
|
+
// keep any more specific policy, authentication, or runtime exclusion.
|
|
262
|
+
for (const account of accountsWithMetrics) {
|
|
263
|
+
if (policy.emergencyAccountIndexes?.has(account.index) &&
|
|
264
|
+
account.isAvailable &&
|
|
265
|
+
!blockedAccountIndexes.has(account.index)) {
|
|
266
|
+
blockedAccountIndexes.add(account.index);
|
|
267
|
+
blockedReasonByAccount[account.index] =
|
|
268
|
+
"emergency-only: reserved until runtime confirms ordinary capacity and permitted resets are exhausted";
|
|
269
|
+
}
|
|
270
|
+
}
|
|
255
271
|
return selectHybridAccountTraced({
|
|
256
272
|
accounts: accountsWithMetrics,
|
|
257
273
|
healthTracker,
|
|
@@ -267,31 +283,50 @@ export function buildSelectAccountTraced() {
|
|
|
267
283
|
/**
|
|
268
284
|
* Shared handler for `list` and `status` (aliases of the same view).
|
|
269
285
|
*/
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
286
|
+
function buildStatusCommandDeps(rest, logInfo) {
|
|
287
|
+
return {
|
|
288
|
+
loadApiRoutes,
|
|
289
|
+
loadResetCreditState,
|
|
290
|
+
loadInferenceRequestTimes,
|
|
291
|
+
loadModelInventory,
|
|
292
|
+
setStoragePath,
|
|
293
|
+
getStoragePath,
|
|
294
|
+
loadAccounts,
|
|
295
|
+
inspectStorageHealth,
|
|
296
|
+
resolveActiveIndex,
|
|
297
|
+
formatRateLimitEntry,
|
|
298
|
+
loadRuntimeObservabilitySnapshot: loadPersistedRuntimeObservabilitySnapshot,
|
|
299
|
+
loadAppBindStatus: async () => getAppBindStatus()
|
|
300
|
+
.then((status) => status.router ? {
|
|
301
|
+
...status.router,
|
|
302
|
+
// Keep historical diagnostics, but never revive a crashed router's
|
|
303
|
+
// persisted "running" marker or its account-selection signal.
|
|
304
|
+
state: status.running ? status.router.state : "stopped",
|
|
305
|
+
nativeOpenai: status.running && status.state?.nativeOpenai === true,
|
|
306
|
+
} : null)
|
|
307
|
+
.catch(() => null),
|
|
308
|
+
loadAppHelperStatus: readAppRuntimeHelperAccountSignal,
|
|
309
|
+
loadQuotaCache,
|
|
310
|
+
json: rest.includes("--json") || rest.includes("-j"),
|
|
311
|
+
compact: !rest.includes("--details") && !rest.includes("--verbose") && !rest.includes("--json") && !rest.includes("-j"),
|
|
312
|
+
locale: resolveOutputLocale(loadPluginConfig().locale),
|
|
313
|
+
...(logInfo ? { logInfo } : {}),
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
const runListOrStatusCommand = (rest) => runStatusCommand(buildStatusCommandDeps(rest));
|
|
317
|
+
async function loadStatusJsonSnapshot() {
|
|
318
|
+
let serialized = "";
|
|
319
|
+
const exitCode = await runStatusCommand(buildStatusCommandDeps(["--json"], (message) => {
|
|
320
|
+
serialized = message;
|
|
321
|
+
}));
|
|
322
|
+
if (exitCode !== 0)
|
|
323
|
+
throw new Error("Unable to load status snapshot.");
|
|
324
|
+
const parsed = JSON.parse(serialized);
|
|
325
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
326
|
+
throw new Error("Status snapshot is not an object.");
|
|
327
|
+
}
|
|
328
|
+
return parsed;
|
|
329
|
+
}
|
|
295
330
|
/**
|
|
296
331
|
* Command registry for the `auth` dispatcher (audit roadmap §4.1.1 phase 2).
|
|
297
332
|
*
|
|
@@ -307,6 +342,10 @@ const CLI_COMMAND_HANDLERS = new Map([
|
|
|
307
342
|
["login", (rest) => runAuthLogin(rest, { runForecast, createRepairCommandDeps })],
|
|
308
343
|
["list", runListOrStatusCommand],
|
|
309
344
|
["status", runListOrStatusCommand],
|
|
345
|
+
["web", (rest) => runWebCommand(rest, {
|
|
346
|
+
getStatus: loadStatusJsonSnapshot,
|
|
347
|
+
locale: resolveOutputLocale(loadPluginConfig().locale),
|
|
348
|
+
})],
|
|
310
349
|
[
|
|
311
350
|
"limits",
|
|
312
351
|
(rest) => runLimitsCommand(rest, {
|
|
@@ -341,6 +380,7 @@ const CLI_COMMAND_HANDLERS = new Map([
|
|
|
341
380
|
setStoragePath,
|
|
342
381
|
loadAccounts,
|
|
343
382
|
saveAccounts,
|
|
383
|
+
withAccountStorageTransaction,
|
|
344
384
|
}),
|
|
345
385
|
],
|
|
346
386
|
["check", (rest) => runCheckCommand({
|
|
@@ -481,6 +521,12 @@ const CLI_COMMAND_HANDLERS = new Map([
|
|
|
481
521
|
if (subcommand === "template") {
|
|
482
522
|
return runInitConfigCommand(configArgs);
|
|
483
523
|
}
|
|
524
|
+
if (subcommand === "locale") {
|
|
525
|
+
return runLocaleCommand(configArgs, {
|
|
526
|
+
loadConfig: () => loadPluginConfig(),
|
|
527
|
+
saveConfig: savePluginConfig,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
484
530
|
console.error(`Unknown config command: ${subcommand ?? "(missing)"}`);
|
|
485
531
|
return 1;
|
|
486
532
|
},
|
|
@@ -506,6 +552,32 @@ const CLI_COMMAND_HANDLERS = new Map([
|
|
|
506
552
|
],
|
|
507
553
|
]);
|
|
508
554
|
export async function runCodexMultiAuthCli(rawArgs) {
|
|
555
|
+
const localeArgs = [...rawArgs];
|
|
556
|
+
const previousLocaleOverride = process.env.CODEX_MULTI_AUTH_LOCALE;
|
|
557
|
+
let localeOverrideChanged = false;
|
|
558
|
+
const restoreLocaleOverride = () => {
|
|
559
|
+
if (!localeOverrideChanged)
|
|
560
|
+
return;
|
|
561
|
+
if (previousLocaleOverride === undefined)
|
|
562
|
+
delete process.env.CODEX_MULTI_AUTH_LOCALE;
|
|
563
|
+
else
|
|
564
|
+
process.env.CODEX_MULTI_AUTH_LOCALE = previousLocaleOverride;
|
|
565
|
+
};
|
|
566
|
+
for (let i = 0; i < localeArgs.length; i += 1) {
|
|
567
|
+
const arg = localeArgs[i];
|
|
568
|
+
if (arg === "--locale" && localeArgs[i + 1]) {
|
|
569
|
+
process.env.CODEX_MULTI_AUTH_LOCALE = localeArgs[i + 1];
|
|
570
|
+
localeOverrideChanged = true;
|
|
571
|
+
localeArgs.splice(i, 2);
|
|
572
|
+
i -= 1;
|
|
573
|
+
}
|
|
574
|
+
else if (typeof arg === "string" && arg.startsWith("--locale=")) {
|
|
575
|
+
process.env.CODEX_MULTI_AUTH_LOCALE = arg.slice("--locale=".length);
|
|
576
|
+
localeOverrideChanged = true;
|
|
577
|
+
localeArgs.splice(i, 1);
|
|
578
|
+
i -= 1;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
509
581
|
// Lazy install setup (audit roadmap §4.5.4): app detection, Codex app bind,
|
|
510
582
|
// and launcher routing moved out of npm postinstall to the first CLI run.
|
|
511
583
|
// ensureFirstRunSetup never throws; the catch is belt-and-braces so no
|
|
@@ -515,31 +587,41 @@ export async function runCodexMultiAuthCli(rawArgs) {
|
|
|
515
587
|
}).catch(() => undefined);
|
|
516
588
|
const startupDisplaySettings = await loadDashboardDisplaySettings();
|
|
517
589
|
applyUiThemeFromDashboardSettings(startupDisplaySettings);
|
|
518
|
-
const args =
|
|
519
|
-
? ["auth", ...
|
|
520
|
-
: [...
|
|
590
|
+
const args = localeArgs[0] && localeArgs[0] !== "auth" && ACCOUNT_MANAGER_COMMANDS.has(localeArgs[0])
|
|
591
|
+
? ["auth", ...localeArgs]
|
|
592
|
+
: [...localeArgs];
|
|
521
593
|
if (args.length === 0) {
|
|
594
|
+
restoreLocaleOverride();
|
|
522
595
|
printUsage();
|
|
523
596
|
return 0;
|
|
524
597
|
}
|
|
525
598
|
if (args[0] === "--help" || args[0] === "-h") {
|
|
599
|
+
restoreLocaleOverride();
|
|
526
600
|
printUsage();
|
|
527
601
|
return 0;
|
|
528
602
|
}
|
|
529
603
|
const [root, sub, ...rest] = args;
|
|
530
604
|
if (root !== "auth") {
|
|
605
|
+
restoreLocaleOverride();
|
|
531
606
|
printUsage();
|
|
532
607
|
return 1;
|
|
533
608
|
}
|
|
534
609
|
const command = sub ?? "login";
|
|
535
610
|
if (command === "--help" || command === "-h") {
|
|
611
|
+
restoreLocaleOverride();
|
|
536
612
|
printUsage();
|
|
537
613
|
return 0;
|
|
538
614
|
}
|
|
539
615
|
const handler = CLI_COMMAND_HANDLERS.get(command);
|
|
540
616
|
if (handler) {
|
|
541
|
-
|
|
617
|
+
try {
|
|
618
|
+
return await handler(rest);
|
|
619
|
+
}
|
|
620
|
+
finally {
|
|
621
|
+
restoreLocaleOverride();
|
|
622
|
+
}
|
|
542
623
|
}
|
|
624
|
+
restoreLocaleOverride();
|
|
543
625
|
console.error(`Unknown command: ${command}`);
|
|
544
626
|
printUsage();
|
|
545
627
|
return 1;
|
package/dist/lib/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, promises as fs, readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { parseBooleanEnv } from "./env-parsing.js";
|
|
4
|
+
import { normalizeOutputLocaleSetting } from "./locale.js";
|
|
4
5
|
import { stripModelEffortSuffix } from "./constants.js";
|
|
5
6
|
import { withRetry, withRetrySync } from "./fs-retry.js";
|
|
6
7
|
import { logWarn } from "./logger.js";
|
|
@@ -113,6 +114,7 @@ function resolvePluginConfigPath() {
|
|
|
113
114
|
* CODEX_MODE is enabled by default for better Codex CLI parity
|
|
114
115
|
*/
|
|
115
116
|
export const DEFAULT_PLUGIN_CONFIG = {
|
|
117
|
+
locale: "auto",
|
|
116
118
|
codexMode: true,
|
|
117
119
|
codexRuntimeRotationProxy: true,
|
|
118
120
|
codexTuiV2: true,
|
|
@@ -1275,6 +1277,7 @@ function normalizeConfigExplainValue(value) {
|
|
|
1275
1277
|
return value;
|
|
1276
1278
|
}
|
|
1277
1279
|
const CONFIG_EXPLAIN_ENTRIES = [
|
|
1280
|
+
{ key: "locale", envNames: ["CODEX_MULTI_AUTH_LOCALE"], getValue: config => normalizeOutputLocaleSetting(process.env.CODEX_MULTI_AUTH_LOCALE?.trim() || config.locale || "auto") ?? "auto" },
|
|
1278
1281
|
{ key: "codexMode", envNames: ["CODEX_MODE"], getValue: getCodexMode },
|
|
1279
1282
|
{
|
|
1280
1283
|
key: "codexRuntimeRotationProxy",
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -116,3 +116,5 @@ export type WireReasoningEffort = Exclude<ModelReasoningEffort, "ultra">;
|
|
|
116
116
|
* untouched.
|
|
117
117
|
*/
|
|
118
118
|
export declare function stripModelEffortSuffix(modelId: string): string;
|
|
119
|
+
/** Maximum lifetime of a local quota rejection before upstream revalidation. */
|
|
120
|
+
export declare const RATE_LIMIT_CACHE_TTL_MS: number;
|
package/dist/lib/constants.js
CHANGED
|
@@ -136,3 +136,5 @@ export function stripModelEffortSuffix(modelId) {
|
|
|
136
136
|
return modelId;
|
|
137
137
|
return modelId.replace(EFFORT_SUFFIX_PATTERN, "");
|
|
138
138
|
}
|
|
139
|
+
/** Maximum lifetime of a local quota rejection before upstream revalidation. */
|
|
140
|
+
export const RATE_LIMIT_CACHE_TTL_MS = 60 * 60_000;
|
|
@@ -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.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type OutputLocale = "en" | "zh";
|
|
2
|
+
export type OutputLocaleSetting = OutputLocale | "auto";
|
|
3
|
+
/** Resolve an explicit locale, environment override, or system language. */
|
|
4
|
+
export declare function resolveOutputLocale(requested?: string | null, env?: NodeJS.ProcessEnv): OutputLocale;
|
|
5
|
+
export declare function normalizeOutputLocaleSetting(value: string): OutputLocaleSetting | null;
|
|
6
|
+
export declare function localized(locale: OutputLocale, en: string, zh: string): string;
|
|
7
|
+
export declare function localeName(locale: OutputLocale): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const SUPPORTED_LOCALES = new Set(["auto", "en", "zh"]);
|
|
2
|
+
/** Resolve an explicit locale, environment override, or system language. */
|
|
3
|
+
export function resolveOutputLocale(requested, env = process.env) {
|
|
4
|
+
const configured = requested?.trim().toLowerCase();
|
|
5
|
+
const value = (env.CODEX_MULTI_AUTH_LOCALE?.trim() || configured || "auto")
|
|
6
|
+
.trim()
|
|
7
|
+
.toLowerCase();
|
|
8
|
+
if (value === "en" || value.startsWith("en-"))
|
|
9
|
+
return "en";
|
|
10
|
+
if (value === "zh" || value.startsWith("zh-"))
|
|
11
|
+
return "zh";
|
|
12
|
+
if (value !== "" && value !== "auto" && SUPPORTED_LOCALES.has(value)) {
|
|
13
|
+
return value === "zh" ? "zh" : "en";
|
|
14
|
+
}
|
|
15
|
+
const system = [env.LC_ALL, env.LC_MESSAGES, env.LANG]
|
|
16
|
+
.find((candidate) => typeof candidate === "string" && candidate.trim())
|
|
17
|
+
?.toLowerCase() ?? "";
|
|
18
|
+
return system.startsWith("zh") ? "zh" : "en";
|
|
19
|
+
}
|
|
20
|
+
export function normalizeOutputLocaleSetting(value) {
|
|
21
|
+
const normalized = value.trim().toLowerCase();
|
|
22
|
+
if (normalized === "auto")
|
|
23
|
+
return "auto";
|
|
24
|
+
if (normalized === "en" || normalized.startsWith("en-"))
|
|
25
|
+
return "en";
|
|
26
|
+
if (normalized === "zh" || normalized.startsWith("zh-"))
|
|
27
|
+
return "zh";
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
export function localized(locale, en, zh) {
|
|
31
|
+
return locale === "zh" ? zh : en;
|
|
32
|
+
}
|
|
33
|
+
export function localeName(locale) {
|
|
34
|
+
return locale === "zh" ? "中文" : "English";
|
|
35
|
+
}
|
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
<title>Codex Sign-In Complete</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root {
|
|
9
|
-
color-scheme: dark;
|
|
10
|
-
--bg: #0b0b0b;
|
|
11
|
-
--panel: #111111;
|
|
12
|
-
--text: #f2f2f2;
|
|
13
|
-
--muted: #a3a3a3;
|
|
14
|
-
--line: #232323;
|
|
15
|
-
--ok: #7cf0a6;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
* {
|
|
19
|
-
box-sizing: border-box;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
body {
|
|
23
|
-
margin: 0;
|
|
24
|
-
min-height: 100vh;
|
|
25
|
-
display: grid;
|
|
26
|
-
place-items: center;
|
|
27
|
-
background: var(--bg);
|
|
28
|
-
color: var(--text);
|
|
29
|
-
font-family: "Geist Mono", "GeistMono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
30
|
-
padding: 24px;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
main {
|
|
34
|
-
width: min(520px, 100%);
|
|
35
|
-
background: var(--panel);
|
|
36
|
-
border: 1px solid var(--line);
|
|
37
|
-
border-radius: 12px;
|
|
38
|
-
padding: 20px;
|
|
39
|
-
display: grid;
|
|
40
|
-
gap: 14px;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
h1 {
|
|
44
|
-
margin: 0;
|
|
45
|
-
font-size: 20px;
|
|
46
|
-
font-weight: 600;
|
|
47
|
-
letter-spacing: -0.02em;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
p {
|
|
51
|
-
margin: 0;
|
|
52
|
-
color: var(--muted);
|
|
53
|
-
font-size: 14px;
|
|
54
|
-
line-height: 1.5;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.status {
|
|
58
|
-
display: inline-flex;
|
|
59
|
-
align-items: center;
|
|
60
|
-
gap: 8px;
|
|
61
|
-
color: var(--ok);
|
|
62
|
-
font-size: 13px;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.dot {
|
|
66
|
-
width: 8px;
|
|
67
|
-
height: 8px;
|
|
68
|
-
border-radius: 50%;
|
|
69
|
-
background: currentColor;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
dl {
|
|
73
|
-
margin: 0;
|
|
74
|
-
display: grid;
|
|
75
|
-
grid-template-columns: 120px 1fr;
|
|
76
|
-
gap: 8px 12px;
|
|
77
|
-
font-size: 13px;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
dt {
|
|
81
|
-
color: var(--muted);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
dd {
|
|
85
|
-
margin: 0;
|
|
86
|
-
color: var(--text);
|
|
87
|
-
word-break: break-word;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
code {
|
|
91
|
-
background: #171717;
|
|
92
|
-
border: 1px solid var(--line);
|
|
93
|
-
border-radius: 6px;
|
|
94
|
-
padding: 2px 6px;
|
|
95
|
-
font-family: inherit;
|
|
96
|
-
font-size: 12px;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
@media (max-width: 520px) {
|
|
100
|
-
dl {
|
|
101
|
-
grid-template-columns: 1fr;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
</style>
|
|
105
|
-
</head>
|
|
106
|
-
<body>
|
|
107
|
-
<main role="main" aria-label="OAuth callback received">
|
|
108
|
-
<h1>Sign-in complete</h1>
|
|
109
|
-
<p>Return to your terminal to finish Codex login.</p>
|
|
110
|
-
|
|
111
|
-
<div class="status" aria-live="polite">
|
|
112
|
-
<span class="dot" aria-hidden="true"></span>
|
|
113
|
-
Callback received
|
|
114
|
-
</div>
|
|
115
|
-
|
|
116
|
-
<dl>
|
|
117
|
-
<dt>Endpoint</dt>
|
|
118
|
-
<dd><code>localhost:1455</code></dd>
|
|
119
|
-
<dt>Flow</dt>
|
|
120
|
-
<dd>OAuth callback captured</dd>
|
|
121
|
-
<dt>Next</dt>
|
|
122
|
-
<dd>Close this tab and continue in terminal</dd>
|
|
123
|
-
</dl>
|
|
124
|
-
</main>
|
|
125
|
-
</body>
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Codex Sign-In Complete</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: dark;
|
|
10
|
+
--bg: #0b0b0b;
|
|
11
|
+
--panel: #111111;
|
|
12
|
+
--text: #f2f2f2;
|
|
13
|
+
--muted: #a3a3a3;
|
|
14
|
+
--line: #232323;
|
|
15
|
+
--ok: #7cf0a6;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
* {
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
body {
|
|
23
|
+
margin: 0;
|
|
24
|
+
min-height: 100vh;
|
|
25
|
+
display: grid;
|
|
26
|
+
place-items: center;
|
|
27
|
+
background: var(--bg);
|
|
28
|
+
color: var(--text);
|
|
29
|
+
font-family: "Geist Mono", "GeistMono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
30
|
+
padding: 24px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
main {
|
|
34
|
+
width: min(520px, 100%);
|
|
35
|
+
background: var(--panel);
|
|
36
|
+
border: 1px solid var(--line);
|
|
37
|
+
border-radius: 12px;
|
|
38
|
+
padding: 20px;
|
|
39
|
+
display: grid;
|
|
40
|
+
gap: 14px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
h1 {
|
|
44
|
+
margin: 0;
|
|
45
|
+
font-size: 20px;
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
letter-spacing: -0.02em;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
p {
|
|
51
|
+
margin: 0;
|
|
52
|
+
color: var(--muted);
|
|
53
|
+
font-size: 14px;
|
|
54
|
+
line-height: 1.5;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.status {
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: 8px;
|
|
61
|
+
color: var(--ok);
|
|
62
|
+
font-size: 13px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.dot {
|
|
66
|
+
width: 8px;
|
|
67
|
+
height: 8px;
|
|
68
|
+
border-radius: 50%;
|
|
69
|
+
background: currentColor;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
dl {
|
|
73
|
+
margin: 0;
|
|
74
|
+
display: grid;
|
|
75
|
+
grid-template-columns: 120px 1fr;
|
|
76
|
+
gap: 8px 12px;
|
|
77
|
+
font-size: 13px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
dt {
|
|
81
|
+
color: var(--muted);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
dd {
|
|
85
|
+
margin: 0;
|
|
86
|
+
color: var(--text);
|
|
87
|
+
word-break: break-word;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
code {
|
|
91
|
+
background: #171717;
|
|
92
|
+
border: 1px solid var(--line);
|
|
93
|
+
border-radius: 6px;
|
|
94
|
+
padding: 2px 6px;
|
|
95
|
+
font-family: inherit;
|
|
96
|
+
font-size: 12px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@media (max-width: 520px) {
|
|
100
|
+
dl {
|
|
101
|
+
grid-template-columns: 1fr;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
</style>
|
|
105
|
+
</head>
|
|
106
|
+
<body>
|
|
107
|
+
<main role="main" aria-label="OAuth callback received">
|
|
108
|
+
<h1>Sign-in complete</h1>
|
|
109
|
+
<p>Return to your terminal to finish Codex login.</p>
|
|
110
|
+
|
|
111
|
+
<div class="status" aria-live="polite">
|
|
112
|
+
<span class="dot" aria-hidden="true"></span>
|
|
113
|
+
Callback received
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<dl>
|
|
117
|
+
<dt>Endpoint</dt>
|
|
118
|
+
<dd><code>localhost:1455</code></dd>
|
|
119
|
+
<dt>Flow</dt>
|
|
120
|
+
<dd>OAuth callback captured</dd>
|
|
121
|
+
<dt>Next</dt>
|
|
122
|
+
<dd>Close this tab and continue in terminal</dd>
|
|
123
|
+
</dl>
|
|
124
|
+
</main>
|
|
125
|
+
</body>
|
|
126
126
|
</html>
|
|
@@ -168,7 +168,7 @@ export function loadAccountPolicyStoreCached() {
|
|
|
168
168
|
return loadStoreCached({
|
|
169
169
|
path: getAccountPolicyPath(),
|
|
170
170
|
cache: ACCOUNT_POLICY_CACHE,
|
|
171
|
-
load: loadAccountPolicyStore,
|
|
171
|
+
load: () => loadAccountPolicyStore({ strict: true }),
|
|
172
172
|
isEmptyStore: (store) => Object.keys(store.accounts).length === 0,
|
|
173
173
|
});
|
|
174
174
|
}
|