codex-multi-auth 0.1.7 → 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 (57) hide show
  1. package/LICENSE +21 -1
  2. package/README.md +13 -0
  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/sync.d.ts +9 -16
  9. package/dist/lib/codex-cli/sync.d.ts.map +1 -1
  10. package/dist/lib/codex-cli/sync.js +51 -284
  11. package/dist/lib/codex-cli/sync.js.map +1 -1
  12. package/dist/lib/codex-manager/settings-hub.d.ts +44 -2
  13. package/dist/lib/codex-manager/settings-hub.d.ts.map +1 -1
  14. package/dist/lib/codex-manager/settings-hub.js +746 -117
  15. package/dist/lib/codex-manager/settings-hub.js.map +1 -1
  16. package/dist/lib/codex-manager.d.ts.map +1 -1
  17. package/dist/lib/codex-manager.js +3 -8
  18. package/dist/lib/codex-manager.js.map +1 -1
  19. package/dist/lib/context-overflow.js +10 -10
  20. package/dist/lib/named-backup-export.d.ts +69 -0
  21. package/dist/lib/named-backup-export.d.ts.map +1 -0
  22. package/dist/lib/named-backup-export.js +207 -0
  23. package/dist/lib/named-backup-export.js.map +1 -0
  24. package/dist/lib/oc-chatgpt-import-adapter.d.ts +64 -0
  25. package/dist/lib/oc-chatgpt-import-adapter.d.ts.map +1 -0
  26. package/dist/lib/oc-chatgpt-import-adapter.js +506 -0
  27. package/dist/lib/oc-chatgpt-import-adapter.js.map +1 -0
  28. package/dist/lib/oc-chatgpt-orchestrator.d.ts +80 -0
  29. package/dist/lib/oc-chatgpt-orchestrator.d.ts.map +1 -0
  30. package/dist/lib/oc-chatgpt-orchestrator.js +130 -0
  31. package/dist/lib/oc-chatgpt-orchestrator.js.map +1 -0
  32. package/dist/lib/oc-chatgpt-target-detection.d.ts +59 -0
  33. package/dist/lib/oc-chatgpt-target-detection.d.ts.map +1 -0
  34. package/dist/lib/oc-chatgpt-target-detection.js +327 -0
  35. package/dist/lib/oc-chatgpt-target-detection.js.map +1 -0
  36. package/dist/lib/prompts/codex.js +2 -2
  37. package/dist/lib/runtime-paths.d.ts.map +1 -1
  38. package/dist/lib/runtime-paths.js +21 -1
  39. package/dist/lib/runtime-paths.js.map +1 -1
  40. package/dist/lib/storage.d.ts +42 -3
  41. package/dist/lib/storage.d.ts.map +1 -1
  42. package/dist/lib/storage.js +519 -51
  43. package/dist/lib/storage.js.map +1 -1
  44. package/dist/lib/ui/copy.d.ts +15 -1
  45. package/dist/lib/ui/copy.d.ts.map +1 -1
  46. package/dist/lib/ui/copy.js +15 -1
  47. package/dist/lib/ui/copy.js.map +1 -1
  48. package/package.json +132 -133
  49. package/scripts/bench-format/hashline-v2.mjs +642 -642
  50. package/scripts/bench-format/render.mjs +496 -496
  51. package/scripts/bench-format/stats.mjs +54 -54
  52. package/scripts/bench-format/tasks.mjs +151 -151
  53. package/scripts/benchmark-render-dashboard.mjs +49 -49
  54. package/scripts/install-codex-auth.js +9 -9
  55. package/scripts/test-all-models.sh +7 -7
  56. package/scripts/test-model-matrix.js +138 -46
  57. package/scripts/validate-model-map.sh +7 -7
@@ -1,13 +1,16 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { readFile, writeFile, rm, mkdir } from "node:fs/promises";
3
1
  import { spawnSync } from "node:child_process";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { dirname, join, resolve } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
5
  import process from "node:process";
6
+ import { fileURLToPath } from "node:url";
7
7
 
8
8
  const scriptDir = dirname(fileURLToPath(import.meta.url));
9
9
  const repoRoot = resolve(scriptDir, "..");
10
- const localConfigPaths = [join(repoRoot, ".codex.json"), join(repoRoot, "Codex.json")];
10
+ const localConfigPaths = [
11
+ join(repoRoot, ".codex.json"),
12
+ join(repoRoot, "Codex.json"),
13
+ ];
11
14
  const scenarioTemplates = {
12
15
  legacy: join(repoRoot, "config", "codex-legacy.json"),
13
16
  modern: join(repoRoot, "config", "codex-modern.json"),
@@ -15,6 +18,7 @@ const scenarioTemplates = {
15
18
 
16
19
  const pluginPackageName = "codex-multi-auth";
17
20
  const DEFAULT_MATRIX_TIMEOUT_MS = 120000;
21
+ const DEFAULT_SMOKE_MATRIX_TIMEOUT_MS = 15000;
18
22
 
19
23
  function resolveCmdScriptEntry(commandPath) {
20
24
  if (!/\.cmd$/i.test(commandPath)) {
@@ -153,14 +157,72 @@ export function __resetTrackedCodexPidsForTests() {
153
157
  spawnedCodexPids.clear();
154
158
  }
155
159
 
156
- export function resolveMatrixTimeoutMs() {
157
- const parsedTimeout = Number.parseInt(process.env.CODEX_MATRIX_TIMEOUT_MS ?? String(DEFAULT_MATRIX_TIMEOUT_MS), 10);
160
+ export function resolveMatrixTimeoutMs(smoke = false) {
161
+ const fallback = smoke
162
+ ? DEFAULT_SMOKE_MATRIX_TIMEOUT_MS
163
+ : DEFAULT_MATRIX_TIMEOUT_MS;
164
+ const parsedTimeout = Number.parseInt(
165
+ process.env.CODEX_MATRIX_TIMEOUT_MS ?? String(fallback),
166
+ 10,
167
+ );
158
168
  if (!Number.isFinite(parsedTimeout) || parsedTimeout <= 0) {
159
- return DEFAULT_MATRIX_TIMEOUT_MS;
169
+ return fallback;
160
170
  }
161
171
  return parsedTimeout;
162
172
  }
163
173
 
174
+ function hasCompletedSuccessfully(output, token) {
175
+ return (
176
+ output.includes(token) ||
177
+ output.includes('"type":"turn.completed"') ||
178
+ output.includes('"type":"response.completed"')
179
+ );
180
+ }
181
+
182
+ function getSmokeSkipReason(exitCode, output) {
183
+ if (exitCode === 124) {
184
+ return "timed-out";
185
+ }
186
+ if (/not supported when using codex with a chatgpt account/i.test(output)) {
187
+ return "unsupported-model";
188
+ }
189
+ if (
190
+ /unsupported value:\s*['"]xhigh['"]/i.test(output) ||
191
+ /unsupported_value/i.test(output)
192
+ ) {
193
+ return "unsupported-reasoning";
194
+ }
195
+ return null;
196
+ }
197
+
198
+ function finalizeModelCaseResult(caseInfo, exitCode, output, token, smoke) {
199
+ const hasToken = output.includes(token);
200
+ const completed = hasCompletedSuccessfully(output, token);
201
+ const ok = exitCode === 0 && completed;
202
+ const skipReason = !ok && smoke ? getSmokeSkipReason(exitCode, output) : null;
203
+
204
+ return {
205
+ ...caseInfo,
206
+ ok,
207
+ exitCode,
208
+ hasToken,
209
+ completed,
210
+ skipped: skipReason !== null,
211
+ skipReason,
212
+ output,
213
+ };
214
+ }
215
+
216
+ export function __finalizeModelCaseResultForTests(
217
+ caseInfo,
218
+ exitCode,
219
+ output,
220
+ token,
221
+ smoke = false,
222
+ ) {
223
+ return finalizeModelCaseResult(caseInfo, exitCode, output, token, smoke);
224
+ }
225
+
164
226
  function stopCodexServersInternal() {
165
227
  const tracked = [...spawnedCodexPids];
166
228
  spawnedCodexPids.clear();
@@ -267,7 +329,7 @@ export function __buildModelCaseArgsForTests(caseInfo, index) {
267
329
  function executeModelCase(caseInfo, index) {
268
330
  const { token, args } = buildModelCaseArgs(caseInfo, index);
269
331
 
270
- const timeoutMs = resolveMatrixTimeoutMs();
332
+ const timeoutMs = resolveMatrixTimeoutMs(caseInfo.smoke === true);
271
333
  const commandArgs = [...(CodexExecutable.prefixArgs ?? []), ...args];
272
334
  const finalized = spawnSync(CodexExecutable.command, commandArgs, {
273
335
  cwd: repoRoot,
@@ -285,27 +347,25 @@ function executeModelCase(caseInfo, index) {
285
347
  });
286
348
 
287
349
  if (finalized.error && finalized.error.code === "ETIMEDOUT") {
288
- return {
289
- ...caseInfo,
290
- ok: false,
291
- exitCode: 124,
292
- hasToken: false,
293
- output: `Timed out after ${timeoutMs}ms`,
294
- };
350
+ return finalizeModelCaseResult(
351
+ caseInfo,
352
+ 124,
353
+ `Timed out after ${timeoutMs}ms`,
354
+ token,
355
+ caseInfo.smoke === true,
356
+ );
295
357
  }
296
358
 
297
- const combinedOutput = `${finalized.stdout ?? ""}\n${finalized.stderr ?? ""}`.trim();
298
- const hasToken = combinedOutput.includes(token);
359
+ const combinedOutput =
360
+ `${finalized.stdout ?? ""}\n${finalized.stderr ?? ""}`.trim();
299
361
  const exitCode = finalized.status ?? 1;
300
- const ok = exitCode === 0 && hasToken;
301
-
302
- return {
303
- ...caseInfo,
304
- ok,
362
+ return finalizeModelCaseResult(
363
+ caseInfo,
305
364
  exitCode,
306
- hasToken,
307
- output: combinedOutput,
308
- };
365
+ combinedOutput,
366
+ token,
367
+ caseInfo.smoke === true,
368
+ );
309
369
  }
310
370
 
311
371
  async function readJson(pathValue) {
@@ -365,31 +425,43 @@ async function prepareScenarioConfig(templatePath, pluginRef) {
365
425
  async function runScenario(scenario, options) {
366
426
  const templatePath = scenarioTemplates[scenario];
367
427
  if (!templatePath || !existsSync(templatePath)) {
368
- throw new Error(`Template not found for scenario '${scenario}': ${templatePath}`);
428
+ throw new Error(
429
+ `Template not found for scenario '${scenario}': ${templatePath}`,
430
+ );
369
431
  }
370
432
 
371
433
  const config = await prepareScenarioConfig(templatePath, options.pluginRef);
372
434
  const models = config?.provider?.openai?.models;
373
435
  if (!models || typeof models !== "object") {
374
- throw new Error(`Scenario '${scenario}' has no provider.openai.models object`);
436
+ throw new Error(
437
+ `Scenario '${scenario}' has no provider.openai.models object`,
438
+ );
375
439
  }
376
440
 
377
- const cases = enumerateCases(models, options.smoke, options.maxCases);
441
+ const cases = enumerateCases(models, options.smoke, options.maxCases).map(
442
+ (caseInfo) => ({
443
+ ...caseInfo,
444
+ smoke: options.smoke,
445
+ }),
446
+ );
378
447
  console.log(`\n=== ${scenario.toUpperCase()} (${cases.length} cases) ===`);
379
448
 
380
449
  const results = [];
381
450
  for (let i = 0; i < cases.length; i += 1) {
382
451
  const caseInfo = cases[i];
383
- const result = executeModelCase(
384
- caseInfo,
385
- i + 1,
386
- );
452
+ const result = executeModelCase(caseInfo, i + 1);
387
453
  results.push(result);
388
454
  const variantLabel = result.variant ? ` [variant=${result.variant}]` : "";
389
455
  if (result.ok) {
390
456
  console.log(`PASS ${result.model}${variantLabel}`);
457
+ } else if (result.skipped) {
458
+ console.log(
459
+ `SKIP ${result.model}${variantLabel} (${result.skipReason})`,
460
+ );
391
461
  } else {
392
- console.log(`FAIL ${result.model}${variantLabel} (exit=${result.exitCode}, token=${result.hasToken})`);
462
+ console.log(
463
+ `FAIL ${result.model}${variantLabel} (exit=${result.exitCode}, token=${result.hasToken})`,
464
+ );
393
465
  const tail = result.output.split(/\r?\n/).slice(-12).join("\n");
394
466
  if (tail.trim().length > 0) {
395
467
  console.log(tail);
@@ -407,8 +479,9 @@ async function main() {
407
479
  return;
408
480
  }
409
481
 
410
- const scenarioValue = parseArgValue(args, "--scenario") ?? "all";
411
482
  const smoke = args.includes("--smoke");
483
+ const scenarioValue =
484
+ parseArgValue(args, "--scenario") ?? (smoke ? "modern" : "all");
412
485
  const pluginMode = parseArgValue(args, "--plugin") ?? "dist";
413
486
  const noRestore = args.includes("--no-restore");
414
487
  const maxCasesRaw = parseArgValue(args, "--max-cases");
@@ -419,13 +492,19 @@ async function main() {
419
492
  : undefined;
420
493
 
421
494
  if (!["all", "legacy", "modern"].includes(scenarioValue)) {
422
- throw new Error(`Invalid --scenario value '${scenarioValue}'. Use legacy, modern, or all.`);
495
+ throw new Error(
496
+ `Invalid --scenario value '${scenarioValue}'. Use legacy, modern, or all.`,
497
+ );
423
498
  }
424
499
  if (!["dist", "package"].includes(pluginMode)) {
425
- throw new Error(`Invalid --plugin value '${pluginMode}'. Use dist or package.`);
500
+ throw new Error(
501
+ `Invalid --plugin value '${pluginMode}'. Use dist or package.`,
502
+ );
426
503
  }
427
504
  if (Number.isNaN(maxCases) || maxCases < 0) {
428
- throw new Error(`Invalid --max-cases value '${maxCasesRaw}'. Use a non-negative integer.`);
505
+ throw new Error(
506
+ `Invalid --max-cases value '${maxCasesRaw}'. Use a non-negative integer.`,
507
+ );
429
508
  }
430
509
 
431
510
  const pluginRef = resolvePluginReference(pluginMode);
@@ -437,7 +516,9 @@ async function main() {
437
516
  console.log(`Scenarios: ${scenarios.join(", ")}`);
438
517
  console.log(`Mode: ${smoke ? "smoke" : "full"}`);
439
518
  console.log(`Plugin: ${pluginRef}`);
440
- console.log(`Codex command: ${CodexExecutable.displayCommand ?? CodexExecutable.command}`);
519
+ console.log(
520
+ `Codex command: ${CodexExecutable.displayCommand ?? CodexExecutable.command}`,
521
+ );
441
522
 
442
523
  const backups = await backupLocalConfigs();
443
524
  const allResults = [];
@@ -450,7 +531,9 @@ async function main() {
450
531
  maxCases,
451
532
  pluginRef,
452
533
  });
453
- allResults.push(...scenarioResults.map((item) => ({ ...item, scenario })));
534
+ allResults.push(
535
+ ...scenarioResults.map((item) => ({ ...item, scenario })),
536
+ );
454
537
  }
455
538
  } finally {
456
539
  if (!noRestore) {
@@ -458,11 +541,13 @@ async function main() {
458
541
  }
459
542
  }
460
543
 
461
- const failed = allResults.filter((result) => !result.ok);
462
- const passed = allResults.length - failed.length;
544
+ const passed = allResults.filter((result) => result.ok);
545
+ const skipped = allResults.filter((result) => result.skipped);
546
+ const failed = allResults.filter((result) => !result.ok && !result.skipped);
463
547
  console.log("\n=== SUMMARY ===");
464
548
  console.log(`Total: ${allResults.length}`);
465
- console.log(`Passed: ${passed}`);
549
+ console.log(`Passed: ${passed.length}`);
550
+ console.log(`Skipped: ${skipped.length}`);
466
551
  console.log(`Failed: ${failed.length}`);
467
552
 
468
553
  if (reportJsonPath) {
@@ -475,13 +560,18 @@ async function main() {
475
560
  CodexCommand: CodexExecutable.displayCommand ?? CodexExecutable.command,
476
561
  totals: {
477
562
  total: allResults.length,
478
- passed,
563
+ passed: passed.length,
564
+ skipped: skipped.length,
479
565
  failed: failed.length,
480
566
  },
481
567
  results: allResults,
482
568
  };
483
569
  await mkdir(dirname(reportJsonPath), { recursive: true });
484
- await writeFile(reportJsonPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
570
+ await writeFile(
571
+ reportJsonPath,
572
+ `${JSON.stringify(report, null, 2)}\n`,
573
+ "utf8",
574
+ );
485
575
  console.log(`Report written: ${reportJsonPath}`);
486
576
  }
487
577
 
@@ -492,6 +582,10 @@ async function main() {
492
582
  console.log(`- ${result.scenario}: ${result.model}${variantLabel}`);
493
583
  }
494
584
  process.exitCode = 1;
585
+ } else if (smoke && passed.length === 0) {
586
+ console.log(
587
+ "\nSmoke matrix was inconclusive: all cases were skipped for this current runtime/account capability set.",
588
+ );
495
589
  }
496
590
  }
497
591
 
@@ -507,5 +601,3 @@ if (isDirectRun) {
507
601
  process.exit(1);
508
602
  });
509
603
  }
510
-
511
-
@@ -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" --smoke "$@"
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" --smoke "$@"
7
+