codex-multi-auth 0.1.4 → 0.1.7
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/LICENSE +1 -1
- package/README.md +3 -3
- package/assets/readme-hero.svg +31 -31
- package/dist/lib/codex-cli/state.js +4 -4
- package/dist/lib/codex-cli/state.js.map +1 -1
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +62 -5
- package/dist/lib/codex-cli/writer.js.map +1 -1
- package/dist/lib/context-overflow.js +10 -10
- package/dist/lib/oauth-success.html +66 -210
- package/dist/lib/prompts/codex.js +2 -2
- package/dist/lib/runtime-paths.d.ts.map +1 -1
- package/dist/lib/runtime-paths.js +23 -1
- package/dist/lib/runtime-paths.js.map +1 -1
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +119 -2
- package/dist/lib/storage.js.map +1 -1
- package/dist/lib/ui/auth-menu.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.js +13 -1
- package/dist/lib/ui/auth-menu.js.map +1 -1
- package/package.json +1 -1
- package/scripts/bench-format/hashline-v2.mjs +642 -642
- package/scripts/bench-format/render.mjs +496 -496
- package/scripts/bench-format/stats.mjs +54 -54
- package/scripts/bench-format/tasks.mjs +151 -151
- package/scripts/benchmark-render-dashboard.mjs +49 -49
- package/scripts/codex-multi-auth.js +13 -1
- package/scripts/codex.js +345 -28
- package/scripts/install-codex-auth.js +9 -9
- package/scripts/test-all-models.sh +7 -7
- package/scripts/test-model-matrix.js +59 -24
- package/scripts/validate-model-map.sh +7 -7
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,39 +191,343 @@ function normalizeExitCode(value) {
|
|
|
178
191
|
return 1;
|
|
179
192
|
}
|
|
180
193
|
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
const
|
|
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
|
+
}
|
|
184
362
|
|
|
185
|
-
if (!bypass && shouldHandleMultiAuthAuth(normalizedArgs)) {
|
|
186
363
|
try {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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;
|
|
190
410
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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) {
|
|
194
485
|
console.error(
|
|
195
|
-
|
|
486
|
+
"codex-multi-auth: installed Windows shell guards to keep multi-auth routing after codex npm updates.",
|
|
196
487
|
);
|
|
197
|
-
process.exit(1);
|
|
198
488
|
}
|
|
199
489
|
}
|
|
200
490
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
)
|
|
210
|
-
|
|
491
|
+
async function main() {
|
|
492
|
+
hydrateCliVersionEnv();
|
|
493
|
+
ensureWindowsShellShimGuards();
|
|
494
|
+
|
|
495
|
+
const rawArgs = process.argv.slice(2);
|
|
496
|
+
const normalizedArgs = normalizeAuthAlias(rawArgs);
|
|
497
|
+
const bypass = (process.env.CODEX_MULTI_AUTH_BYPASS ?? "").trim() === "1";
|
|
498
|
+
|
|
499
|
+
if (!bypass && shouldHandleMultiAuthAuth(normalizedArgs)) {
|
|
500
|
+
try {
|
|
501
|
+
const runCodexMultiAuthCli = await loadRunCodexMultiAuthCli();
|
|
502
|
+
if (!runCodexMultiAuthCli) {
|
|
503
|
+
return 1;
|
|
504
|
+
}
|
|
505
|
+
const exitCode = await runCodexMultiAuthCli(normalizedArgs);
|
|
506
|
+
return normalizeExitCode(exitCode);
|
|
507
|
+
} catch (error) {
|
|
508
|
+
console.error(
|
|
509
|
+
`codex-multi-auth runner failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
510
|
+
);
|
|
511
|
+
return 1;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const realCodexBin = resolveRealCodexBin();
|
|
516
|
+
if (!realCodexBin) {
|
|
517
|
+
console.error(
|
|
518
|
+
[
|
|
519
|
+
"Could not locate the official Codex CLI binary (@openai/codex).",
|
|
520
|
+
"Install it globally: npm install -g @openai/codex",
|
|
521
|
+
"Or set CODEX_MULTI_AUTH_REAL_CODEX_BIN to a full bin/codex.js path.",
|
|
522
|
+
].join("\n"),
|
|
523
|
+
);
|
|
524
|
+
return 1;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
await autoSyncManagerActiveSelectionIfEnabled();
|
|
528
|
+
const forwardArgs = buildForwardArgs(rawArgs);
|
|
529
|
+
return forwardToRealCodex(realCodexBin, forwardArgs);
|
|
211
530
|
}
|
|
212
531
|
|
|
213
|
-
await
|
|
214
|
-
|
|
215
|
-
const forwardExitCode = await forwardToRealCodex(realCodexBin, forwardArgs);
|
|
216
|
-
process.exit(forwardExitCode);
|
|
532
|
+
const exitCode = await main();
|
|
533
|
+
process.exitCode = normalizeExitCode(exitCode);
|
|
@@ -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
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { readFile, writeFile, rm, mkdir } from "node:fs/promises";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
4
|
import { dirname, join, resolve } from "node:path";
|
|
@@ -13,16 +13,45 @@ const scenarioTemplates = {
|
|
|
13
13
|
modern: join(repoRoot, "config", "codex-modern.json"),
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const defaultPromptPrefix = "Reply exactly:";
|
|
17
|
-
const modelProviderId = "openai";
|
|
18
16
|
const pluginPackageName = "codex-multi-auth";
|
|
19
17
|
const DEFAULT_MATRIX_TIMEOUT_MS = 120000;
|
|
20
18
|
|
|
19
|
+
function resolveCmdScriptEntry(commandPath) {
|
|
20
|
+
if (!/\.cmd$/i.test(commandPath)) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const raw = readFileSync(commandPath, "utf8");
|
|
25
|
+
const match = raw.match(/"%dp0%\\([^"\r\n]+\.js)"/i);
|
|
26
|
+
if (!match || typeof match[1] !== "string") {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const relScriptPath = match[1].replace(/[\\/]+/g, "/");
|
|
30
|
+
const scriptPath = resolve(dirname(commandPath), relScriptPath);
|
|
31
|
+
return existsSync(scriptPath) ? scriptPath : null;
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildExecutable(command) {
|
|
38
|
+
const scriptEntry = resolveCmdScriptEntry(command);
|
|
39
|
+
if (scriptEntry) {
|
|
40
|
+
return {
|
|
41
|
+
command: process.execPath,
|
|
42
|
+
shell: false,
|
|
43
|
+
prefixArgs: [scriptEntry],
|
|
44
|
+
displayCommand: command,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return { command, shell: /\.cmd$/i.test(command) };
|
|
48
|
+
}
|
|
49
|
+
|
|
21
50
|
export function resolveCodexExecutable() {
|
|
22
51
|
const envOverride = process.env.CODEX_BIN;
|
|
23
52
|
if (envOverride && envOverride.trim().length > 0) {
|
|
24
53
|
const command = envOverride.trim();
|
|
25
|
-
return
|
|
54
|
+
return buildExecutable(command);
|
|
26
55
|
}
|
|
27
56
|
|
|
28
57
|
if (process.platform !== "win32") {
|
|
@@ -53,12 +82,12 @@ export function resolveCodexExecutable() {
|
|
|
53
82
|
/npm\\Codex\.cmd$/i.test(candidate),
|
|
54
83
|
);
|
|
55
84
|
if (exactCmd) {
|
|
56
|
-
return
|
|
85
|
+
return buildExecutable(exactCmd);
|
|
57
86
|
}
|
|
58
87
|
|
|
59
88
|
const anyCmd = candidates.find((candidate) => /\.cmd$/i.test(candidate));
|
|
60
89
|
if (anyCmd) {
|
|
61
|
-
return
|
|
90
|
+
return buildExecutable(anyCmd);
|
|
62
91
|
}
|
|
63
92
|
|
|
64
93
|
return { command: candidates[0], shell: false };
|
|
@@ -101,6 +130,9 @@ function toFileUri(pathValue) {
|
|
|
101
130
|
return `file:///${normalized}`;
|
|
102
131
|
}
|
|
103
132
|
|
|
133
|
+
let stopCodexServersQueue = Promise.resolve();
|
|
134
|
+
const spawnedCodexPids = new Set();
|
|
135
|
+
|
|
104
136
|
function runQuiet(command, commandArgs) {
|
|
105
137
|
try {
|
|
106
138
|
spawnSync(command, commandArgs, {
|
|
@@ -112,9 +144,6 @@ function runQuiet(command, commandArgs) {
|
|
|
112
144
|
}
|
|
113
145
|
}
|
|
114
146
|
|
|
115
|
-
let stopCodexServersQueue = Promise.resolve();
|
|
116
|
-
const spawnedCodexPids = new Set();
|
|
117
|
-
|
|
118
147
|
export function registerSpawnedCodex(pid) {
|
|
119
148
|
if (!Number.isInteger(pid) || pid <= 0) return;
|
|
120
149
|
spawnedCodexPids.add(pid);
|
|
@@ -215,23 +244,32 @@ function enumerateCases(models, smoke, maxCases) {
|
|
|
215
244
|
return selected;
|
|
216
245
|
}
|
|
217
246
|
|
|
218
|
-
function
|
|
247
|
+
function buildModelCaseArgs(caseInfo, index) {
|
|
219
248
|
const token = `MODEL_MATRIX_OK_${index}`;
|
|
220
|
-
const message = `${defaultPromptPrefix} ${token}`;
|
|
221
249
|
const args = [
|
|
222
|
-
"
|
|
223
|
-
|
|
250
|
+
"exec",
|
|
251
|
+
token,
|
|
224
252
|
"--model",
|
|
225
|
-
|
|
226
|
-
"--
|
|
227
|
-
|
|
253
|
+
caseInfo.model,
|
|
254
|
+
"--json",
|
|
255
|
+
"--skip-git-repo-check",
|
|
228
256
|
];
|
|
229
257
|
if (caseInfo.variant) {
|
|
230
|
-
args.push("
|
|
258
|
+
args.push("-c", `model_reasoning_effort="${caseInfo.variant}"`);
|
|
231
259
|
}
|
|
260
|
+
return { token, args };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function __buildModelCaseArgsForTests(caseInfo, index) {
|
|
264
|
+
return buildModelCaseArgs(caseInfo, index);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function executeModelCase(caseInfo, index) {
|
|
268
|
+
const { token, args } = buildModelCaseArgs(caseInfo, index);
|
|
232
269
|
|
|
233
270
|
const timeoutMs = resolveMatrixTimeoutMs();
|
|
234
|
-
const
|
|
271
|
+
const commandArgs = [...(CodexExecutable.prefixArgs ?? []), ...args];
|
|
272
|
+
const finalized = spawnSync(CodexExecutable.command, commandArgs, {
|
|
235
273
|
cwd: repoRoot,
|
|
236
274
|
encoding: "utf8",
|
|
237
275
|
windowsHide: true,
|
|
@@ -258,9 +296,8 @@ function executeModelCase(caseInfo, index, port) {
|
|
|
258
296
|
|
|
259
297
|
const combinedOutput = `${finalized.stdout ?? ""}\n${finalized.stderr ?? ""}`.trim();
|
|
260
298
|
const hasToken = combinedOutput.includes(token);
|
|
261
|
-
const hasFatalError = /ProviderModelNotFoundError|Model not found/i.test(combinedOutput);
|
|
262
299
|
const exitCode = finalized.status ?? 1;
|
|
263
|
-
const ok = exitCode === 0 && hasToken
|
|
300
|
+
const ok = exitCode === 0 && hasToken;
|
|
264
301
|
|
|
265
302
|
return {
|
|
266
303
|
...caseInfo,
|
|
@@ -346,7 +383,6 @@ async function runScenario(scenario, options) {
|
|
|
346
383
|
const result = executeModelCase(
|
|
347
384
|
caseInfo,
|
|
348
385
|
i + 1,
|
|
349
|
-
options.portStart + i,
|
|
350
386
|
);
|
|
351
387
|
results.push(result);
|
|
352
388
|
const variantLabel = result.variant ? ` [variant=${result.variant}]` : "";
|
|
@@ -401,7 +437,7 @@ async function main() {
|
|
|
401
437
|
console.log(`Scenarios: ${scenarios.join(", ")}`);
|
|
402
438
|
console.log(`Mode: ${smoke ? "smoke" : "full"}`);
|
|
403
439
|
console.log(`Plugin: ${pluginRef}`);
|
|
404
|
-
console.log(`Codex command: ${CodexExecutable.command}`);
|
|
440
|
+
console.log(`Codex command: ${CodexExecutable.displayCommand ?? CodexExecutable.command}`);
|
|
405
441
|
|
|
406
442
|
const backups = await backupLocalConfigs();
|
|
407
443
|
const allResults = [];
|
|
@@ -413,7 +449,6 @@ async function main() {
|
|
|
413
449
|
smoke,
|
|
414
450
|
maxCases,
|
|
415
451
|
pluginRef,
|
|
416
|
-
portStart: 47000 + i * 500,
|
|
417
452
|
});
|
|
418
453
|
allResults.push(...scenarioResults.map((item) => ({ ...item, scenario })));
|
|
419
454
|
}
|
|
@@ -437,7 +472,7 @@ async function main() {
|
|
|
437
472
|
scenarios,
|
|
438
473
|
mode: smoke ? "smoke" : "full",
|
|
439
474
|
plugin: pluginRef,
|
|
440
|
-
CodexCommand: CodexExecutable.command,
|
|
475
|
+
CodexCommand: CodexExecutable.displayCommand ?? CodexExecutable.command,
|
|
441
476
|
totals: {
|
|
442
477
|
total: allResults.length,
|
|
443
478
|
passed,
|
|
@@ -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
|
+
|