codex-multi-auth 1.2.5 → 1.2.6

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/README.md CHANGED
@@ -19,7 +19,7 @@ Codex CLI-first multi-account OAuth manager for the official `@openai/codex` CLI
19
19
  - Interactive dashboard for account actions and settings
20
20
  - Experimental settings tab for staged sync, backup, and refresh-guard controls
21
21
  - Forecast, report, fix, and doctor commands for operational safety
22
- - Runtime request budget, cooldown, and traffic observability in `codex auth status` / `codex auth report`
22
+ - Runtime counters, budget/cooldown state, and multi-auth probe visibility in `codex auth status` / `codex auth report`
23
23
  - Flagged account verification and restore flow
24
24
  - Session affinity and live account sync controls
25
25
  - Proactive refresh and preemptive quota deferral controls
@@ -321,9 +321,10 @@ codex auth doctor --json
321
321
 
322
322
  ## Release Notes
323
323
 
324
- - Current stable: [docs/releases/v1.2.4.md](docs/releases/v1.2.4.md)
325
- - Previous stable: [docs/releases/v1.2.2.md](docs/releases/v1.2.2.md)
326
- - Earlier stable: [docs/releases/v1.2.1.md](docs/releases/v1.2.1.md)
324
+ - Current stable: [docs/releases/v1.2.6.md](docs/releases/v1.2.6.md)
325
+ - Recent patch release: [docs/releases/v1.2.5.md](docs/releases/v1.2.5.md)
326
+ - Previous stable: [docs/releases/v1.2.2.md](docs/releases/v1.2.2.md)
327
+ - Earlier stable: [docs/releases/v1.2.1.md](docs/releases/v1.2.1.md)
327
328
  - Archived prerelease: [docs/releases/v0.1.0-beta.0.md](docs/releases/v0.1.0-beta.0.md)
328
329
 
329
330
  ## License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-multi-auth",
3
- "version": "1.2.5",
3
+ "version": "1.2.6",
4
4
  "description": "Multi-account OAuth manager and codex auth wrapper for the official @openai/codex CLI, with switching, health checks, and recovery tools",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  // @ts-check
4
4
 
package/scripts/codex.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  import { spawn } from "node:child_process";
4
4
  import {
@@ -653,18 +653,201 @@ function rewriteConfigTomlReasoningEffort(rawConfig, requestedModel) {
653
653
  return ensureTrailingNewline(nextLines.join(lineEnding));
654
654
  }
655
655
 
656
- function resolveOriginalMultiAuthDir(env) {
657
- const explicit = (env.CODEX_MULTI_AUTH_DIR ?? "").trim();
658
- if (explicit.length > 0) {
659
- return explicit;
660
- }
661
- return undefined;
662
- }
663
-
664
- function createCompatibilityCodexHome(
665
- processedArgs,
666
- requestedModel,
667
- baseEnv = process.env,
656
+ function resolveOriginalMultiAuthDir(env) {
657
+ const explicit = (env.CODEX_MULTI_AUTH_DIR ?? "").trim();
658
+ if (explicit.length > 0) {
659
+ return explicit;
660
+ }
661
+ return undefined;
662
+ }
663
+
664
+ async function loadRuntimeObservabilityModule() {
665
+ try {
666
+ const mod = await import("../dist/lib/runtime/runtime-observability.js");
667
+ if (
668
+ typeof mod.loadPersistedRuntimeObservabilitySnapshot !== "function" ||
669
+ typeof mod.mutateRuntimeObservabilitySnapshot !== "function"
670
+ ) {
671
+ return null;
672
+ }
673
+ return mod;
674
+ } catch (error) {
675
+ if (
676
+ error &&
677
+ typeof error === "object" &&
678
+ "code" in error &&
679
+ error.code === "ERR_MODULE_NOT_FOUND"
680
+ ) {
681
+ return null;
682
+ }
683
+ throw error;
684
+ }
685
+ }
686
+
687
+ function isPureHelpOrVersionArgs(rawArgs) {
688
+ if (!Array.isArray(rawArgs) || rawArgs.length === 0) {
689
+ return false;
690
+ }
691
+ return rawArgs.every((arg) =>
692
+ typeof arg === "string" && ["--help", "-h", "--version", "-V"].includes(arg),
693
+ );
694
+ }
695
+
696
+ function consumesNextArg(arg) {
697
+ return new Set([
698
+ "-c",
699
+ "--config",
700
+ "--enable",
701
+ "--disable",
702
+ "--remote",
703
+ "--remote-auth-token-env",
704
+ "-i",
705
+ "--image",
706
+ "-m",
707
+ "--model",
708
+ "--local-provider",
709
+ "-p",
710
+ "--profile",
711
+ "-s",
712
+ "--sandbox",
713
+ "-a",
714
+ "--ask-for-approval",
715
+ "-C",
716
+ "--cd",
717
+ "--add-dir",
718
+ "--output-schema",
719
+ "--color",
720
+ "-o",
721
+ "--output-last-message",
722
+ ]).has(arg);
723
+ }
724
+
725
+ function shouldTrackForwardedRuntimeObservability(rawArgs) {
726
+ if (!Array.isArray(rawArgs) || rawArgs.length === 0) {
727
+ return true;
728
+ }
729
+ if (isPureHelpOrVersionArgs(rawArgs)) {
730
+ return false;
731
+ }
732
+
733
+ const requestCommands = new Set(["exec", "review", "resume", "fork"]);
734
+ const nonRequestCommands = new Set([
735
+ "help",
736
+ "completion",
737
+ "login",
738
+ "logout",
739
+ "mcp",
740
+ "mcp-server",
741
+ "app-server",
742
+ "sandbox",
743
+ "debug",
744
+ "apply",
745
+ "cloud",
746
+ "features",
747
+ "auth",
748
+ ]);
749
+
750
+ for (let i = 0; i < rawArgs.length; i += 1) {
751
+ const arg = rawArgs[i];
752
+ if (typeof arg !== "string" || arg.length === 0) continue;
753
+ if (arg === "--") {
754
+ return i + 1 < rawArgs.length;
755
+ }
756
+ if (arg.startsWith("--config=")) {
757
+ continue;
758
+ }
759
+ if (arg.startsWith("--") || (arg.startsWith("-") && arg !== "-")) {
760
+ if (consumesNextArg(arg)) {
761
+ i += 1;
762
+ }
763
+ continue;
764
+ }
765
+ if (requestCommands.has(arg)) {
766
+ return true;
767
+ }
768
+ if (nonRequestCommands.has(arg)) {
769
+ return false;
770
+ }
771
+ return true;
772
+ }
773
+
774
+ return true;
775
+ }
776
+
777
+ function createRuntimeSnapshotChangeToken(snapshot) {
778
+ return JSON.stringify({
779
+ updatedAt: snapshot?.updatedAt ?? null,
780
+ responsesRequests: snapshot?.responsesRequests ?? null,
781
+ authRefreshRequests: snapshot?.authRefreshRequests ?? null,
782
+ diagnosticProbeRequests: snapshot?.diagnosticProbeRequests ?? null,
783
+ totalRequests: snapshot?.runtimeMetrics?.totalRequests ?? null,
784
+ successfulRequests: snapshot?.runtimeMetrics?.successfulRequests ?? null,
785
+ failedRequests: snapshot?.runtimeMetrics?.failedRequests ?? null,
786
+ lastRequestAt: snapshot?.runtimeMetrics?.lastRequestAt ?? null,
787
+ });
788
+ }
789
+
790
+ async function loadRuntimeSnapshotWithRetry(runtimeObservabilityModule) {
791
+ let snapshot = null;
792
+ for (let attempt = 0; attempt < 5; attempt += 1) {
793
+ snapshot =
794
+ (await runtimeObservabilityModule.loadPersistedRuntimeObservabilitySnapshot()) ??
795
+ null;
796
+ if (snapshot) {
797
+ return snapshot;
798
+ }
799
+ if (attempt < 4) {
800
+ await new Promise((resolve) => setTimeout(resolve, 20));
801
+ }
802
+ }
803
+ return snapshot;
804
+ }
805
+
806
+ async function withForwardedRuntimeObservability(rawArgs, runForwardedCommand) {
807
+ if (!shouldTrackForwardedRuntimeObservability(rawArgs)) {
808
+ return runForwardedCommand();
809
+ }
810
+
811
+ const runtimeObservabilityModule = await loadRuntimeObservabilityModule();
812
+ if (!runtimeObservabilityModule) {
813
+ return runForwardedCommand();
814
+ }
815
+
816
+ const beforeSnapshot = await loadRuntimeSnapshotWithRetry(runtimeObservabilityModule);
817
+ const beforeToken = createRuntimeSnapshotChangeToken(beforeSnapshot);
818
+ const startedAt = Date.now();
819
+ const exitCode = await runForwardedCommand();
820
+ const afterSnapshot = await loadRuntimeSnapshotWithRetry(runtimeObservabilityModule);
821
+ const afterToken = createRuntimeSnapshotChangeToken(afterSnapshot);
822
+ if (afterToken !== beforeToken) {
823
+ return exitCode;
824
+ }
825
+
826
+ runtimeObservabilityModule.mutateRuntimeObservabilitySnapshot((snapshot) => {
827
+ snapshot.currentRequestId = null;
828
+ snapshot.responsesRequests += 1;
829
+ snapshot.runtimeMetrics.totalRequests += 1;
830
+ snapshot.runtimeMetrics.responsesRequests += 1;
831
+ snapshot.runtimeMetrics.cumulativeLatencyMs += Math.max(0, Date.now() - startedAt);
832
+ snapshot.runtimeMetrics.lastRequestAt = Date.now();
833
+ if (!snapshot.runtimeMetrics.startedAt) {
834
+ snapshot.runtimeMetrics.startedAt = startedAt;
835
+ }
836
+ if (exitCode === 0) {
837
+ snapshot.runtimeMetrics.successfulRequests += 1;
838
+ snapshot.runtimeMetrics.lastError = null;
839
+ } else {
840
+ snapshot.runtimeMetrics.failedRequests += 1;
841
+ snapshot.runtimeMetrics.lastError = `forwarded-codex-exit:${exitCode}`;
842
+ }
843
+ });
844
+ return exitCode;
845
+ }
846
+
847
+ function createCompatibilityCodexHome(
848
+ processedArgs,
849
+ requestedModel,
850
+ baseEnv = process.env,
668
851
  ) {
669
852
  if (!requestedModel) {
670
853
  return { args: processedArgs, env: baseEnv, cleanup: undefined };
@@ -1149,13 +1332,15 @@ async function main() {
1149
1332
  forwardArgs,
1150
1333
  requestedModel,
1151
1334
  );
1152
- return forwardToRealCodex(
1153
- realCodexBin,
1154
- compatibility.args,
1155
- compatibility.env,
1156
- compatibility.cleanup,
1157
- );
1158
- }
1335
+ return withForwardedRuntimeObservability(rawArgs, () =>
1336
+ forwardToRealCodex(
1337
+ realCodexBin,
1338
+ compatibility.args,
1339
+ compatibility.env,
1340
+ compatibility.cleanup,
1341
+ ),
1342
+ );
1343
+ }
1159
1344
 
1160
1345
  const exitCode = await main();
1161
1346
  process.exitCode = normalizeExitCode(exitCode);