codex-multi-auth 0.1.5 → 0.1.8

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 (75) hide show
  1. package/LICENSE +21 -1
  2. package/README.md +19 -6
  3. package/assets/readme-hero.svg +31 -31
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/codex-cli/state.js +4 -4
  9. package/dist/lib/codex-cli/state.js.map +1 -1
  10. package/dist/lib/codex-cli/sync.d.ts +9 -16
  11. package/dist/lib/codex-cli/sync.d.ts.map +1 -1
  12. package/dist/lib/codex-cli/sync.js +51 -284
  13. package/dist/lib/codex-cli/sync.js.map +1 -1
  14. package/dist/lib/codex-cli/writer.d.ts.map +1 -1
  15. package/dist/lib/codex-cli/writer.js +62 -5
  16. package/dist/lib/codex-cli/writer.js.map +1 -1
  17. package/dist/lib/codex-manager/settings-hub.d.ts +44 -2
  18. package/dist/lib/codex-manager/settings-hub.d.ts.map +1 -1
  19. package/dist/lib/codex-manager/settings-hub.js +746 -117
  20. package/dist/lib/codex-manager/settings-hub.js.map +1 -1
  21. package/dist/lib/codex-manager.d.ts.map +1 -1
  22. package/dist/lib/codex-manager.js +3 -8
  23. package/dist/lib/codex-manager.js.map +1 -1
  24. package/dist/lib/context-overflow.js +10 -10
  25. package/dist/lib/named-backup-export.d.ts +69 -0
  26. package/dist/lib/named-backup-export.d.ts.map +1 -0
  27. package/dist/lib/named-backup-export.js +207 -0
  28. package/dist/lib/named-backup-export.js.map +1 -0
  29. package/dist/lib/oauth-success.html +66 -210
  30. package/dist/lib/oc-chatgpt-import-adapter.d.ts +64 -0
  31. package/dist/lib/oc-chatgpt-import-adapter.d.ts.map +1 -0
  32. package/dist/lib/oc-chatgpt-import-adapter.js +506 -0
  33. package/dist/lib/oc-chatgpt-import-adapter.js.map +1 -0
  34. package/dist/lib/oc-chatgpt-orchestrator.d.ts +80 -0
  35. package/dist/lib/oc-chatgpt-orchestrator.d.ts.map +1 -0
  36. package/dist/lib/oc-chatgpt-orchestrator.js +130 -0
  37. package/dist/lib/oc-chatgpt-orchestrator.js.map +1 -0
  38. package/dist/lib/oc-chatgpt-target-detection.d.ts +59 -0
  39. package/dist/lib/oc-chatgpt-target-detection.d.ts.map +1 -0
  40. package/dist/lib/oc-chatgpt-target-detection.js +327 -0
  41. package/dist/lib/oc-chatgpt-target-detection.js.map +1 -0
  42. package/dist/lib/prompts/codex.js +2 -2
  43. package/dist/lib/runtime-paths.d.ts.map +1 -1
  44. package/dist/lib/runtime-paths.js +44 -2
  45. package/dist/lib/runtime-paths.js.map +1 -1
  46. package/dist/lib/storage.d.ts +42 -3
  47. package/dist/lib/storage.d.ts.map +1 -1
  48. package/dist/lib/storage.js +634 -49
  49. package/dist/lib/storage.js.map +1 -1
  50. package/dist/lib/ui/auth-menu.d.ts.map +1 -1
  51. package/dist/lib/ui/auth-menu.js +13 -1
  52. package/dist/lib/ui/auth-menu.js.map +1 -1
  53. package/dist/lib/ui/copy.d.ts +15 -1
  54. package/dist/lib/ui/copy.d.ts.map +1 -1
  55. package/dist/lib/ui/copy.js +15 -1
  56. package/dist/lib/ui/copy.js.map +1 -1
  57. package/node_modules/@codex-ai/plugin/dist/index.d.ts +1 -1
  58. package/node_modules/@codex-ai/plugin/dist/tool.d.ts +41 -41
  59. package/node_modules/@codex-ai/plugin/dist/tool.js +28 -28
  60. package/package.json +132 -133
  61. package/scripts/bench-format/hashline-v2.mjs +642 -642
  62. package/scripts/bench-format/render.mjs +496 -496
  63. package/scripts/bench-format/stats.mjs +54 -54
  64. package/scripts/bench-format/tasks.mjs +151 -151
  65. package/scripts/benchmark-render-dashboard.mjs +49 -49
  66. package/scripts/codex-multi-auth.js +12 -0
  67. package/scripts/codex.js +315 -2
  68. package/scripts/install-codex-auth.js +9 -9
  69. package/scripts/test-all-models.sh +7 -7
  70. package/scripts/test-model-matrix.js +247 -148
  71. package/scripts/validate-model-map.sh +7 -7
  72. package/vendor/codex-ai-plugin/dist/index.d.ts +1 -1
  73. package/vendor/codex-ai-plugin/dist/tool.d.ts +41 -41
  74. package/vendor/codex-ai-plugin/dist/tool.js +28 -28
  75. package/vendor/codex-ai-sdk/dist/index.d.ts +3 -3
package/scripts/codex.js CHANGED
@@ -1,13 +1,26 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { spawn, spawnSync } from "node:child_process";
4
- import { existsSync } from "node:fs";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
5
  import { createRequire } from "node:module";
6
- import { dirname, join } from "node:path";
6
+ import { basename, delimiter, dirname, join, resolve as resolvePath } from "node:path";
7
7
  import process from "node:process";
8
8
  import { fileURLToPath } from "node:url";
9
9
  import { normalizeAuthAlias, shouldHandleMultiAuthAuth } from "./codex-routing.js";
10
10
 
11
+ function hydrateCliVersionEnv() {
12
+ try {
13
+ const require = createRequire(import.meta.url);
14
+ const pkg = require("../package.json");
15
+ const version = typeof pkg?.version === "string" ? pkg.version.trim() : "";
16
+ if (version.length > 0) {
17
+ process.env.CODEX_MULTI_AUTH_CLI_VERSION = version;
18
+ }
19
+ } catch {
20
+ // Best effort only.
21
+ }
22
+ }
23
+
11
24
  async function loadRunCodexMultiAuthCli() {
12
25
  try {
13
26
  const mod = await import("../dist/lib/codex-manager.js");
@@ -178,7 +191,307 @@ function normalizeExitCode(value) {
178
191
  return 1;
179
192
  }
180
193
 
194
+ const WINDOWS_SHIM_MARKER = "codex-multi-auth windows shim guardian v1";
195
+ const POWERSHELL_PROFILE_MARKER_START = "# >>> codex-multi-auth shell guard >>>";
196
+ const POWERSHELL_PROFILE_MARKER_END = "# <<< codex-multi-auth shell guard <<<";
197
+
198
+ function shouldInstallWindowsBatchShimGuard() {
199
+ if (process.platform !== "win32") return false;
200
+ const override = (process.env.CODEX_MULTI_AUTH_WINDOWS_BATCH_SHIM_GUARD ?? "1").trim();
201
+ return override !== "0";
202
+ }
203
+
204
+ function splitPathEntries(pathValue) {
205
+ if (typeof pathValue !== "string" || pathValue.trim().length === 0) {
206
+ return [];
207
+ }
208
+ return pathValue
209
+ .split(delimiter)
210
+ .map((entry) => entry.trim())
211
+ .filter((entry) => entry.length > 0);
212
+ }
213
+
214
+ function resolveWindowsShimDirectoryFromInvocation() {
215
+ const invokedScript = (process.argv[1] ?? "").trim();
216
+ if (invokedScript.length === 0) return null;
217
+ const resolvedScript = resolvePath(invokedScript);
218
+ const scriptDir = dirname(resolvedScript);
219
+ const packageRoot = dirname(scriptDir);
220
+ const nodeModulesDir = dirname(packageRoot);
221
+ if (basename(nodeModulesDir).toLowerCase() !== "node_modules") {
222
+ return null;
223
+ }
224
+ const shimDir = dirname(nodeModulesDir);
225
+ if (existsSync(join(shimDir, "codex-multi-auth.cmd"))) {
226
+ return shimDir;
227
+ }
228
+ return null;
229
+ }
230
+
231
+ function resolveWindowsShimDirectoryFromPath() {
232
+ const fromInvocation = resolveWindowsShimDirectoryFromInvocation();
233
+ if (fromInvocation) {
234
+ return fromInvocation;
235
+ }
236
+ const pathEntries = splitPathEntries(process.env.PATH ?? process.env.Path ?? "");
237
+ for (const entry of pathEntries) {
238
+ if (existsSync(join(entry, "codex-multi-auth.cmd"))) {
239
+ return entry;
240
+ }
241
+ }
242
+ return null;
243
+ }
244
+
245
+ function buildWindowsBatchShimContent() {
246
+ return [
247
+ "@ECHO off",
248
+ `:: ${WINDOWS_SHIM_MARKER}`,
249
+ "GOTO start",
250
+ ":find_dp0",
251
+ "SET dp0=%~dp0",
252
+ "EXIT /b",
253
+ ":start",
254
+ "SETLOCAL",
255
+ "CALL :find_dp0",
256
+ "",
257
+ 'IF EXIST "%dp0%\\node.exe" (',
258
+ ' SET "_prog=%dp0%\\node.exe"',
259
+ ") ELSE (",
260
+ ' SET "_prog=node"',
261
+ ' SET PATHEXT=%PATHEXT:;.JS;=%',
262
+ ")",
263
+ "",
264
+ 'endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\\node_modules\\codex-multi-auth\\scripts\\codex.js" %*',
265
+ ].join("\r\n");
266
+ }
267
+
268
+ function buildWindowsCmdShimContent() {
269
+ return [
270
+ "@ECHO off",
271
+ `:: ${WINDOWS_SHIM_MARKER}`,
272
+ "GOTO start",
273
+ ":find_dp0",
274
+ "SET dp0=%~dp0",
275
+ "EXIT /b",
276
+ ":start",
277
+ "SETLOCAL",
278
+ "CALL :find_dp0",
279
+ "",
280
+ 'IF EXIST "%dp0%\\node.exe" (',
281
+ ' SET "_prog=%dp0%\\node.exe"',
282
+ ") ELSE (",
283
+ ' SET "_prog=node"',
284
+ ' SET PATHEXT=%PATHEXT:;.JS;=%',
285
+ ")",
286
+ "",
287
+ 'endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\\node_modules\\codex-multi-auth\\scripts\\codex.js" %*',
288
+ ].join("\r\n");
289
+ }
290
+
291
+ function buildWindowsPowerShellShimContent() {
292
+ return [
293
+ `# ${WINDOWS_SHIM_MARKER}`,
294
+ "$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent",
295
+ "",
296
+ '$exe=""',
297
+ 'if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {',
298
+ ' $exe=".exe"',
299
+ "}",
300
+ "$ret=0",
301
+ 'if (Test-Path "$basedir/node$exe") {',
302
+ " if ($MyInvocation.ExpectingInput) {",
303
+ ' $input | & "$basedir/node$exe" "$basedir/node_modules/codex-multi-auth/scripts/codex.js" $args',
304
+ " } else {",
305
+ ' & "$basedir/node$exe" "$basedir/node_modules/codex-multi-auth/scripts/codex.js" $args',
306
+ " }",
307
+ " $ret=$LASTEXITCODE",
308
+ "} else {",
309
+ " if ($MyInvocation.ExpectingInput) {",
310
+ ' $input | & "node$exe" "$basedir/node_modules/codex-multi-auth/scripts/codex.js" $args',
311
+ " } else {",
312
+ ' & "node$exe" "$basedir/node_modules/codex-multi-auth/scripts/codex.js" $args',
313
+ " }",
314
+ " $ret=$LASTEXITCODE",
315
+ "}",
316
+ "if ($null -eq $ret) {",
317
+ " exit 0",
318
+ "}",
319
+ "exit $ret",
320
+ ].join("\r\n");
321
+ }
322
+
323
+ function ensureWindowsShellShim(filePath, desiredContent, options = {}) {
324
+ const {
325
+ overwriteCustomShim = false,
326
+ shimMarker = WINDOWS_SHIM_MARKER,
327
+ } = options;
328
+
329
+ let currentContent = "";
330
+ if (existsSync(filePath)) {
331
+ try {
332
+ currentContent = readFileSync(filePath, "utf8");
333
+ } catch {
334
+ return false;
335
+ }
336
+ if (currentContent === desiredContent || currentContent.includes(shimMarker)) {
337
+ if (currentContent !== desiredContent) {
338
+ try {
339
+ writeFileSync(filePath, desiredContent, { encoding: "utf8", mode: 0o755 });
340
+ return true;
341
+ } catch {
342
+ return false;
343
+ }
344
+ }
345
+ return false;
346
+ }
347
+ const looksLikeStockOpenAiShim =
348
+ currentContent.includes("node_modules\\@openai\\codex\\bin\\codex.js") ||
349
+ currentContent.includes("node_modules/@openai/codex/bin/codex.js");
350
+ if (looksLikeStockOpenAiShim) {
351
+ try {
352
+ writeFileSync(filePath, desiredContent, { encoding: "utf8", mode: 0o755 });
353
+ return true;
354
+ } catch {
355
+ return false;
356
+ }
357
+ }
358
+ if (!overwriteCustomShim) {
359
+ return false;
360
+ }
361
+ }
362
+
363
+ try {
364
+ writeFileSync(filePath, desiredContent, { encoding: "utf8", mode: 0o755 });
365
+ return true;
366
+ } catch {
367
+ return false;
368
+ }
369
+ }
370
+
371
+ function shouldInstallPowerShellProfileGuard() {
372
+ if (process.platform !== "win32") return false;
373
+ const override = (process.env.CODEX_MULTI_AUTH_PWSH_PROFILE_GUARD ?? "1").trim();
374
+ return override !== "0";
375
+ }
376
+
377
+ function resolveWindowsUserHomeDir() {
378
+ const userProfile = (process.env.USERPROFILE ?? "").trim();
379
+ if (userProfile.length > 0) return userProfile;
380
+ const homeDrive = (process.env.HOMEDRIVE ?? "").trim();
381
+ const homePath = (process.env.HOMEPATH ?? "").trim();
382
+ if (homeDrive.length > 0 && homePath.length > 0) {
383
+ return `${homeDrive}${homePath}`;
384
+ }
385
+ const home = (process.env.HOME ?? "").trim();
386
+ return home;
387
+ }
388
+
389
+ function buildPowerShellProfileGuardBlock(shimDirectory) {
390
+ const codexBatchPath = join(shimDirectory, "codex.bat").replace(/\\/g, "\\\\");
391
+ return [
392
+ POWERSHELL_PROFILE_MARKER_START,
393
+ `$CodexMultiAuthShim = "${codexBatchPath}"`,
394
+ "if (Test-Path $CodexMultiAuthShim) {",
395
+ " function global:codex {",
396
+ " & $CodexMultiAuthShim @args",
397
+ " }",
398
+ "}",
399
+ POWERSHELL_PROFILE_MARKER_END,
400
+ ].join("\r\n");
401
+ }
402
+
403
+ function upsertPowerShellProfileGuard(profilePath, guardBlock) {
404
+ let content = "";
405
+ if (existsSync(profilePath)) {
406
+ try {
407
+ content = readFileSync(profilePath, "utf8");
408
+ } catch {
409
+ return false;
410
+ }
411
+ }
412
+ const normalizedCurrentContent = content.replace(/\r?\n$/, "");
413
+
414
+ const startIndex = content.indexOf(POWERSHELL_PROFILE_MARKER_START);
415
+ const endIndex = content.indexOf(POWERSHELL_PROFILE_MARKER_END);
416
+ let nextContent;
417
+ if (startIndex >= 0 && endIndex >= startIndex) {
418
+ const endWithMarker = endIndex + POWERSHELL_PROFILE_MARKER_END.length;
419
+ const prefix = content.slice(0, startIndex).replace(/\s*$/, "");
420
+ const suffix = content.slice(endWithMarker).replace(/^\s*/, "");
421
+ nextContent = `${prefix}\r\n\r\n${guardBlock}\r\n\r\n${suffix}`.trimEnd();
422
+ } else if (normalizedCurrentContent.trim().length === 0) {
423
+ nextContent = guardBlock;
424
+ } else {
425
+ nextContent = `${normalizedCurrentContent.replace(/\s*$/, "")}\r\n\r\n${guardBlock}`;
426
+ }
427
+
428
+ if (nextContent === normalizedCurrentContent) {
429
+ return false;
430
+ }
431
+
432
+ try {
433
+ mkdirSync(dirname(profilePath), { recursive: true });
434
+ writeFileSync(profilePath, `${nextContent}\r\n`, { encoding: "utf8", mode: 0o644 });
435
+ return true;
436
+ } catch {
437
+ return false;
438
+ }
439
+ }
440
+
441
+ function ensurePowerShellProfileGuard(shimDirectory) {
442
+ if (!shouldInstallPowerShellProfileGuard()) return false;
443
+ const homeDir = resolveWindowsUserHomeDir();
444
+ if (!homeDir) return false;
445
+ const guardBlock = buildPowerShellProfileGuardBlock(shimDirectory);
446
+ const profilePaths = [
447
+ join(homeDir, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1"),
448
+ join(homeDir, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1"),
449
+ ];
450
+ let changed = false;
451
+ for (const profilePath of profilePaths) {
452
+ changed = upsertPowerShellProfileGuard(profilePath, guardBlock) || changed;
453
+ }
454
+ return changed;
455
+ }
456
+
457
+ function ensureWindowsShellShimGuards() {
458
+ if (!shouldInstallWindowsBatchShimGuard()) return;
459
+ const shimDirectory = resolveWindowsShimDirectoryFromPath();
460
+ if (!shimDirectory) return;
461
+
462
+ const codexMultiAuthShimPath = join(shimDirectory, "codex-multi-auth.cmd");
463
+ if (!existsSync(codexMultiAuthShimPath)) return;
464
+
465
+ const overwriteCustomShim =
466
+ (process.env.CODEX_MULTI_AUTH_OVERWRITE_CUSTOM_BATCH_SHIM ?? "0").trim() === "1";
467
+ const installedBatch = ensureWindowsShellShim(
468
+ join(shimDirectory, "codex.bat"),
469
+ buildWindowsBatchShimContent(),
470
+ { overwriteCustomShim },
471
+ );
472
+ const installedCmd = ensureWindowsShellShim(
473
+ join(shimDirectory, "codex.cmd"),
474
+ buildWindowsCmdShimContent(),
475
+ { overwriteCustomShim },
476
+ );
477
+ const installedPs1 = ensureWindowsShellShim(
478
+ join(shimDirectory, "codex.ps1"),
479
+ buildWindowsPowerShellShimContent(),
480
+ { overwriteCustomShim },
481
+ );
482
+ const installedAny = installedBatch || installedCmd || installedPs1;
483
+ const installedProfileGuard = ensurePowerShellProfileGuard(shimDirectory);
484
+ if (installedAny || installedProfileGuard) {
485
+ console.error(
486
+ "codex-multi-auth: installed Windows shell guards to keep multi-auth routing after codex npm updates.",
487
+ );
488
+ }
489
+ }
490
+
181
491
  async function main() {
492
+ hydrateCliVersionEnv();
493
+ ensureWindowsShellShimGuards();
494
+
182
495
  const rawArgs = process.argv.slice(2);
183
496
  const normalizedArgs = normalizeAuthAlias(rawArgs);
184
497
  const bypass = (process.env.CODEX_MULTI_AUTH_BYPASS ?? "").trim() === "1";
@@ -143,15 +143,15 @@ async function clearCache() {
143
143
  if (dryRun) {
144
144
  log(`[dry-run] Would remove ${cacheNodeModules}`);
145
145
  log(`[dry-run] Would remove ${cacheBunLock}`);
146
- } else {
147
- try {
148
- await withFileOperationRetry(() => rm(cacheNodeModules, { recursive: true, force: true }));
149
- await withFileOperationRetry(() => rm(cacheBunLock, { force: true }));
150
- } catch (error) {
151
- log(
152
- `Warning: Could not fully clear cache (${error instanceof Error ? error.message : String(error)}). You may need to restart Codex.`,
153
- );
154
- }
146
+ } else {
147
+ try {
148
+ await withFileOperationRetry(() => rm(cacheNodeModules, { recursive: true, force: true }));
149
+ await withFileOperationRetry(() => rm(cacheBunLock, { force: true }));
150
+ } catch (error) {
151
+ log(
152
+ `Warning: Could not fully clear cache (${error instanceof Error ? error.message : String(error)}). You may need to restart Codex.`,
153
+ );
154
+ }
155
155
  }
156
156
 
157
157
  await removePluginFromCachePackage();
@@ -1,7 +1,7 @@
1
- #!/bin/bash
2
-
3
- set -euo pipefail
4
-
5
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
- node "${SCRIPT_DIR}/test-model-matrix.js" "$@"
7
-
1
+ #!/bin/bash
2
+
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ node "${SCRIPT_DIR}/test-model-matrix.js" "$@"
7
+