codex-multi-auth 2.22.0 → 2.23.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.
Files changed (43) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/README.md +4 -2
  3. package/config/schema/config.schema.json +8 -0
  4. package/dist/lib/api-route-store.d.ts +1 -0
  5. package/dist/lib/api-route-store.js +2 -1
  6. package/dist/lib/auth/account-access.js +2 -1
  7. package/dist/lib/auth/auth.js +3 -2
  8. package/dist/lib/auth/device-auth.js +2 -1
  9. package/dist/lib/auth/http.d.ts +1 -0
  10. package/dist/lib/auth/http.js +1 -0
  11. package/dist/lib/codex-manager/account-manager-commands.js +1 -0
  12. package/dist/lib/codex-manager/commands/locale.d.ts +12 -0
  13. package/dist/lib/codex-manager/commands/locale.js +25 -0
  14. package/dist/lib/codex-manager/commands/status.d.ts +4 -0
  15. package/dist/lib/codex-manager/commands/status.js +476 -5
  16. package/dist/lib/codex-manager/help.js +3 -1
  17. package/dist/lib/codex-manager.js +98 -29
  18. package/dist/lib/config.js +3 -0
  19. package/dist/lib/locale.d.ts +7 -0
  20. package/dist/lib/locale.js +35 -0
  21. package/dist/lib/quota-probe.js +2 -1
  22. package/dist/lib/request/proxy-fetch.d.ts +5 -0
  23. package/dist/lib/request/proxy-fetch.js +37 -0
  24. package/dist/lib/request/url-rewriting.js +17 -0
  25. package/dist/lib/runtime/account-model-catalog.d.ts +2 -0
  26. package/dist/lib/runtime/account-model-catalog.js +7 -2
  27. package/dist/lib/runtime/app-bind.d.ts +4 -1
  28. package/dist/lib/runtime/app-bind.js +63 -3
  29. package/dist/lib/runtime/responses-websocket.d.ts +30 -0
  30. package/dist/lib/runtime/responses-websocket.js +243 -29
  31. package/dist/lib/runtime/rotation-account-selection.d.ts +5 -4
  32. package/dist/lib/runtime/rotation-server-types.d.ts +4 -1
  33. package/dist/lib/runtime-rotation-proxy.js +30 -9
  34. package/dist/lib/schemas.d.ts +5 -0
  35. package/dist/lib/schemas.js +1 -0
  36. package/dist/lib/web-dashboard-html.d.ts +1 -0
  37. package/dist/lib/web-dashboard-html.js +66 -0
  38. package/dist/lib/web-dashboard.d.ts +36 -0
  39. package/dist/lib/web-dashboard.js +322 -0
  40. package/package.json +3 -1
  41. package/scripts/codex-app-router.js +45 -1
  42. package/scripts/codex-routing.js +1 -0
  43. package/scripts/codex.js +150 -13
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-multi-auth",
3
- "version": "2.22.0",
3
+ "version": "2.23.0",
4
4
  "description": "Install and operate codex-multi-auth for the official @openai/codex CLI with multi-account OAuth rotation, switching, health checks, and recovery tools.",
5
5
  "interface": {
6
6
  "composerIcon": "./assets/codex-multi-auth-icon.svg"
package/README.md CHANGED
@@ -28,7 +28,8 @@ Using OpenCode rather than the Codex CLI? The sibling project [`oc-codex-multi-a
28
28
 
29
29
  | Binary | Role |
30
30
  | --- | --- |
31
- | `codex-multi-auth` | The account manager. Runs all 31 management subcommands locally (`login`, `status`, `switch`, `forecast`, `rotation`, `fix`, ...). The `auth` prefix is optional: `codex-multi-auth login` ≡ `codex-multi-auth auth login`. |
31
+ | `codex-multi-auth` | The account manager. Runs all management subcommands locally (`login`, `status`, `web`, `switch`, `forecast`, `rotation`, `fix`, ...). The `auth` prefix is optional: `codex-multi-auth login` ≡ `codex-multi-auth auth login`. |
32
+ | `codex-ma` | Short alias for `codex-multi-auth`, including the local real-time web dashboard. |
32
33
  | `codex-multi-auth-codex` | Opt-in wrapper. Handles `auth ...` locally and forwards every other command to the official Codex CLI, enabling the rotation proxy for request-bearing commands. |
33
34
  | `mcodex` | Convenience launcher over the wrapper, with optional `--monitor` and `--tmux` modes. No account logic of its own. |
34
35
  | `codex-multi-auth-app-launcher` | User-level OS launcher routing helper (Windows shortcut, macOS wrapper app, Linux `.desktop`). |
@@ -52,6 +53,7 @@ codex-multi-auth login
52
53
 
53
54
  # 2. Repeat login to add more accounts, then inspect the pool
54
55
  codex-multi-auth status
56
+ codex-ma web --no-open
55
57
 
56
58
  # 3. Probe account health and preview which account would serve next
57
59
  codex-multi-auth check
@@ -139,7 +141,7 @@ Common symptoms — wrong active account, OAuth callback port `1455` already bou
139
141
 
140
142
  ## Release notes
141
143
 
142
- - Current stable: [v2.22.0](docs/releases/v2.22.0.md) — `npm i -g codex-multi-auth`
144
+ - Current stable: [v2.23.0](docs/releases/v2.23.0.md) — `npm i -g codex-multi-auth`
143
145
  - Earlier stable lines: [v2.6.0](docs/releases/v2.6.0.md), [v2.5.0](docs/releases/v2.5.0.md)
144
146
  - Full release archive: [docs/README.md#release-history](docs/README.md#release-history)
145
147
 
@@ -31,6 +31,14 @@
31
31
  "pluginConfig": {
32
32
  "type": "object",
33
33
  "properties": {
34
+ "locale": {
35
+ "type": "string",
36
+ "enum": [
37
+ "auto",
38
+ "en",
39
+ "zh"
40
+ ]
41
+ },
34
42
  "codexMode": {
35
43
  "type": "boolean"
36
44
  },
@@ -17,6 +17,7 @@ declare const routeSchema: z.ZodObject<{
17
17
  accessPrograms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
18
18
  modelAccessPrograms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>>;
19
19
  }, z.core.$strip>;
20
+ export declare const MAX_API_ROUTES = 100;
20
21
  export type ApiRouteCredential = z.infer<typeof routeSchema>;
21
22
  export declare function getApiRoutesPath(): string;
22
23
  export declare function loadApiRoutes(path?: string): Promise<ApiRouteCredential[]>;
@@ -41,9 +41,10 @@ const routeSchema = z.object({
41
41
  modelAccessPrograms: z.record(modelId, accessPrograms)
42
42
  .refine(value => Object.keys(value).length <= 1000).optional(),
43
43
  });
44
+ export const MAX_API_ROUTES = 100;
44
45
  const schema = z.object({
45
46
  version: z.literal(1),
46
- routes: z.array(routeSchema).max(100),
47
+ routes: z.array(routeSchema).max(MAX_API_ROUTES),
47
48
  });
48
49
  export function getApiRoutesPath() {
49
50
  return join(getCodexMultiAuthDir(), "api-routes.json");
@@ -1,5 +1,6 @@
1
1
  import { CODEX_BASE_URL } from "../constants.js";
2
2
  import { combineSignals } from "../utils.js";
3
+ import { fetchAuth } from "./http.js";
3
4
  const ACCOUNTS_CHECK_PATH = "/wham/accounts/check";
4
5
  const ACCOUNTS_CHECK_TIMEOUT_MS = 10_000;
5
6
  function readString(value) {
@@ -49,7 +50,7 @@ export async function fetchAuthorizedAccounts(accessToken, options = {}) {
49
50
  const token = readString(accessToken);
50
51
  if (!token)
51
52
  return null;
52
- const doFetch = options.fetch ?? globalThis.fetch;
53
+ const doFetch = options.fetch ?? fetchAuth;
53
54
  const timeout = AbortSignal.timeout(ACCOUNTS_CHECK_TIMEOUT_MS);
54
55
  // combineSignals wraps AbortSignal.any (available on every Node the
55
56
  // engines floor, `>=22.19`, permits) with null-tolerance; the native composite also detaches
@@ -2,6 +2,7 @@ import { randomBytes, webcrypto } from "node:crypto";
2
2
  import { logError } from "../logger.js";
3
3
  import { safeParseOAuthTokenResponse } from "../schemas.js";
4
4
  import { isAbortError } from "../utils.js";
5
+ import { fetchAuth } from "./http.js";
5
6
  // OAuth constants (from openai/codex)
6
7
  export const CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
7
8
  export const AUTHORIZE_URL = "https://auth.openai.com/oauth/authorize";
@@ -396,7 +397,7 @@ export function parseAuthorizationInput(input) {
396
397
  * @returns Token result
397
398
  */
398
399
  export async function exchangeAuthorizationCode(code, verifier, redirectUri = REDIRECT_URI) {
399
- const res = await fetch(TOKEN_URL, {
400
+ const res = await fetchAuth(TOKEN_URL, {
400
401
  method: "POST",
401
402
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
402
403
  body: new URLSearchParams({
@@ -468,7 +469,7 @@ export function decodeJWT(token) {
468
469
  }
469
470
  export async function refreshAccessToken(refreshToken, options = {}) {
470
471
  try {
471
- const response = await fetch(TOKEN_URL, {
472
+ const response = await fetchAuth(TOKEN_URL, {
472
473
  method: "POST",
473
474
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
474
475
  signal: options?.signal,
@@ -1,4 +1,5 @@
1
1
  import { CLIENT_ID, exchangeAuthorizationCode, sanitizeOAuthResponseBodyForLog, } from "./auth.js";
2
+ import { fetchAuth } from "./http.js";
2
3
  const DEVICE_AUTH_BASE_URL = "https://auth.openai.com";
3
4
  const DEVICE_AUTH_API_BASE_URL = `${DEVICE_AUTH_BASE_URL}/api/accounts`;
4
5
  export const DEVICE_AUTH_VERIFICATION_URL = `${DEVICE_AUTH_BASE_URL}/codex/device`;
@@ -14,7 +15,7 @@ const DEVICE_AUTH_TRANSIENT_PENDING_STATUSES = new Set([
14
15
  504,
15
16
  ]);
16
17
  function getFetch(options) {
17
- return options.fetchImpl ?? fetch;
18
+ return options.fetchImpl ?? fetchAuth;
18
19
  }
19
20
  function getNow(options) {
20
21
  return options.now ?? Date.now;
@@ -0,0 +1 @@
1
+ export { fetchWithProxy as fetchAuth } from "../request/proxy-fetch.js";
@@ -0,0 +1 @@
1
+ export { fetchWithProxy as fetchAuth } from "../request/proxy-fetch.js";
@@ -14,6 +14,7 @@ export const ACCOUNT_MANAGER_COMMANDS = new Set([
14
14
  "login",
15
15
  "list",
16
16
  "status",
17
+ "web",
17
18
  "limits",
18
19
  "switch",
19
20
  "unpin",
@@ -0,0 +1,12 @@
1
+ import { type OutputLocaleSetting } from "../../locale.js";
2
+ export interface LocaleCommandDeps {
3
+ loadConfig: () => {
4
+ locale?: OutputLocaleSetting;
5
+ };
6
+ saveConfig: (patch: {
7
+ locale: OutputLocaleSetting;
8
+ }) => Promise<void>;
9
+ logInfo?: (message: string) => void;
10
+ logError?: (message: string) => void;
11
+ }
12
+ export declare function runLocaleCommand(args: string[], deps: LocaleCommandDeps): Promise<number>;
@@ -0,0 +1,25 @@
1
+ import { localeName, normalizeOutputLocaleSetting, resolveOutputLocale, } from "../../locale.js";
2
+ export async function runLocaleCommand(args, deps) {
3
+ const logInfo = deps.logInfo ?? console.log;
4
+ const logError = deps.logError ?? console.error;
5
+ const requested = args[0]?.trim();
6
+ if (args.length > 1 || requested === "--help" || requested === "-h") {
7
+ logInfo("Usage: codex-multi-auth config locale [auto|en|zh]");
8
+ return requested === "--help" || requested === "-h" ? 0 : 1;
9
+ }
10
+ if (!requested) {
11
+ const configured = deps.loadConfig().locale ?? "auto";
12
+ const effective = resolveOutputLocale(configured);
13
+ logInfo(`Locale: ${configured} (effective: ${localeName(effective)})`);
14
+ return 0;
15
+ }
16
+ const locale = normalizeOutputLocaleSetting(requested);
17
+ if (!locale) {
18
+ logError(`Unsupported locale: ${requested}. Choose auto, en, or zh.`);
19
+ return 1;
20
+ }
21
+ await deps.saveConfig({ locale });
22
+ const effective = resolveOutputLocale(locale);
23
+ logInfo(`Locale saved: ${locale} (effective: ${localeName(effective)})`);
24
+ return 0;
25
+ }
@@ -7,6 +7,7 @@ import type { QuotaCacheData } from "../../quota-cache.js";
7
7
  import { type AppBindRouterStatus } from "../../runtime/app-bind.js";
8
8
  import { type RuntimeAccountSignal } from "../../runtime/runtime-current-account.js";
9
9
  import type { RuntimeObservabilitySnapshot } from "../../runtime/runtime-observability.js";
10
+ import { type OutputLocale } from "../../locale.js";
10
11
  import type { AccountStorageV3, StorageHealthSummary } from "../../storage.js";
11
12
  type LoadedStorage = AccountStorageV3 | null;
12
13
  export interface StatusCommandDeps {
@@ -31,6 +32,9 @@ export interface StatusCommandDeps {
31
32
  logInfo?: (message: string) => void;
32
33
  /** When true, emit a single machine-readable JSON object instead of text (cli-manager-03). */
33
34
  json?: boolean;
35
+ /** Compact human-facing summary. Undefined keeps the legacy detailed view for API callers. */
36
+ compact?: boolean;
37
+ locale?: OutputLocale;
34
38
  }
35
39
  export declare function runStatusCommand(deps: StatusCommandDeps): Promise<number>;
36
40
  export interface FeaturesCommandDeps {