codex-multi-auth 1.3.1 → 1.3.2

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
@@ -333,9 +333,9 @@ codex auth doctor --json
333
333
 
334
334
  ## Release Notes
335
335
 
336
- - Current stable: [docs/releases/v1.3.1.md](docs/releases/v1.3.1.md)
337
- - Previous stable: [docs/releases/v1.2.6.md](docs/releases/v1.2.6.md)
338
- - Earlier stable: [docs/releases/v1.2.5.md](docs/releases/v1.2.5.md)
336
+ - Current stable: [docs/releases/v1.3.2.md](docs/releases/v1.3.2.md)
337
+ - Previous stable: [docs/releases/v1.3.1.md](docs/releases/v1.3.1.md)
338
+ - Earlier stable: [docs/releases/v1.3.0.md](docs/releases/v1.3.0.md)
339
339
  - Full release archive: [docs/README.md#release-history](docs/README.md#release-history)
340
340
  - Archived prerelease: [docs/releases/v0.1.0-beta.0.md](docs/releases/v0.1.0-beta.0.md)
341
341
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-multi-auth",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
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",
package/scripts/codex.js CHANGED
@@ -232,10 +232,10 @@ function resolveUnsupportedModelRetryTarget(
232
232
  return undefined;
233
233
  }
234
234
 
235
- function replaceRequestedModel(args, nextModel) {
236
- if (!nextModel) {
237
- return [...args];
238
- }
235
+ function replaceRequestedModel(args, nextModel) {
236
+ if (!nextModel) {
237
+ return [...args];
238
+ }
239
239
 
240
240
  const nextArgs = [...args];
241
241
  for (let i = 0; i < nextArgs.length; i += 1) {
@@ -250,56 +250,88 @@ function replaceRequestedModel(args, nextModel) {
250
250
  }
251
251
  }
252
252
 
253
- return nextArgs;
254
- }
255
-
256
- function forwardToRealCodexOnce(codexBin, args, env = process.env, cleanup) {
257
- return new Promise((resolve) => {
258
- let settled = false;
259
- let stdout = "";
260
- let stderr = "";
261
- const finalize = (exitCode) => {
262
- if (settled) {
263
- return;
264
- }
253
+ return nextArgs;
254
+ }
255
+
256
+ function shouldCaptureForwardedCodexOutput(env = process.env) {
257
+ const override = (env.CODEX_MULTI_AUTH_CAPTURE_FORWARD_OUTPUT ?? "").trim();
258
+ if (override === "1") {
259
+ return true;
260
+ }
261
+ if (override === "0") {
262
+ return false;
263
+ }
264
+ // Windows child processes can report undefined isTTY; treat that as non-TTY so retry capture remains available.
265
+ return process.stdout.isTTY !== true || process.stderr.isTTY !== true;
266
+ }
267
+
268
+ function forwardToRealCodexOnce(
269
+ codexBin,
270
+ args,
271
+ env = process.env,
272
+ cleanup,
273
+ options = {},
274
+ ) {
275
+ return new Promise((resolve) => {
276
+ let settled = false;
277
+ let stdout = "";
278
+ let stderr = "";
279
+ const captureOutput = options.captureOutput === true;
280
+ const finalize = (exitCode) => {
281
+ if (settled) {
282
+ return;
283
+ }
265
284
  settled = true;
266
285
  try {
267
286
  cleanup?.();
268
287
  } catch {
269
288
  // Best-effort cleanup only.
270
- }
271
- resolve({
272
- exitCode,
273
- output: `${stdout}\n${stderr}`.trim(),
274
- });
275
- };
276
-
277
- const command = codexBin.launchWithNode ? process.execPath : codexBin.path;
278
- const commandArgs = codexBin.launchWithNode ? [codexBin.path, ...args] : args;
279
- const child = spawn(command, commandArgs, {
280
- stdio: ["inherit", "pipe", "pipe"],
281
- env,
282
- });
283
-
284
- child.stdout?.on("data", (chunk) => {
285
- const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
286
- stdout += text;
287
- process.stdout.write(chunk);
288
- });
289
- child.stderr?.on("data", (chunk) => {
290
- const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
291
- stderr += text;
292
- process.stderr.write(chunk);
293
- });
294
-
295
- child.once("error", (error) => {
296
- const message = `Failed to launch real Codex CLI: ${String(error)}`;
297
- stderr += `${stderr ? "\n" : ""}${message}`;
298
- console.error(message);
299
- finalize(1);
300
- });
301
-
302
- child.once("close", (code, signal) => {
289
+ }
290
+ resolve({
291
+ exitCode,
292
+ // No-capture output stays empty by design so retry parsing cannot
293
+ // reintroduce pipes that break terminal passthrough.
294
+ output: `${stdout}\n${stderr}`.trim(),
295
+ });
296
+ };
297
+
298
+ const command = codexBin.launchWithNode ? process.execPath : codexBin.path;
299
+ const commandArgs = codexBin.launchWithNode ? [codexBin.path, ...args] : args;
300
+ let child;
301
+ const failLaunch = (error) => {
302
+ const message = `Failed to launch real Codex CLI: ${String(error)}`;
303
+ stderr += `${stderr ? "\n" : ""}${message}`;
304
+ console.error(message);
305
+ finalize(1);
306
+ };
307
+ try {
308
+ child = spawn(command, commandArgs, {
309
+ stdio: captureOutput ? ["inherit", "pipe", "pipe"] : "inherit",
310
+ env,
311
+ });
312
+ } catch (error) {
313
+ failLaunch(error);
314
+ return;
315
+ }
316
+
317
+ if (captureOutput) {
318
+ child.stdout?.on("data", (chunk) => {
319
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
320
+ stdout += text;
321
+ process.stdout.write(chunk);
322
+ });
323
+ child.stderr?.on("data", (chunk) => {
324
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
325
+ stderr += text;
326
+ process.stderr.write(chunk);
327
+ });
328
+ }
329
+
330
+ child.once("error", (error) => {
331
+ failLaunch(error);
332
+ });
333
+
334
+ child.once("close", (code, signal) => {
303
335
  if (signal) {
304
336
  const signalNumber = signal === "SIGINT" ? 130 : 1;
305
337
  finalize(signalNumber);
@@ -328,12 +360,15 @@ async function forwardToRealCodex(codexBin, rawArgs, baseEnv = process.env) {
328
360
  compatibilityRequestedModel,
329
361
  baseEnv,
330
362
  );
331
- const result = await forwardToRealCodexOnce(
332
- codexBin,
333
- compatibility.args,
334
- compatibility.env,
335
- compatibility.cleanup,
336
- );
363
+ const result = await forwardToRealCodexOnce(
364
+ codexBin,
365
+ compatibility.args,
366
+ compatibility.env,
367
+ compatibility.cleanup,
368
+ {
369
+ captureOutput: shouldCaptureForwardedCodexOutput(compatibility.env),
370
+ },
371
+ );
337
372
  lastExitCode = result.exitCode;
338
373
  if (result.exitCode === 0) {
339
374
  return result.exitCode;