← Files Codex ReplayARCHIVED FILE

worker/src/codex-worker.mjs

27.1 KB · Oct 2, 2026 · 00:19 UTC

↓ Download file

import { createInterface } from "node:readline";
import { spawn, spawnSync } from "node:child_process";
import { accessSync, constants, readdirSync, statSync } from "node:fs";
import { homedir } from "node:os";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import { Codex } from "@openai/codex-sdk";

const PROTOCOL_VERSION = 1;
const MAX_PROMPT_CHARS = 2_000_000;
const MAX_SCHEMA_CHARS = 200_000;
const MAX_FINAL_RESPONSE_CHARS = 200_000;
const MAX_LIFECYCLE_EVENTS = 128;
const MAX_PROVIDER_ERROR_CHARS = 1_000;
const MAX_WORKER_DIAGNOSTIC_CHARS = 8_000;
const CLI_WRAPPER_MODE_ENV = "CODEX_REPLAY_CODEX_WRAPPER";
const CLI_WRAPPER_TARGET_ENV = "CODEX_REPLAY_CODEX_TARGET";
const CLI_WRAPPER_OWNER_ENV = "CODEX_REPLAY_CODEX_OWNER_PID";
const TREE_KILL_GRACE_MS = 2_000;
const CODEX_VERSION_PROBE_TIMEOUT_MS = 5_000;
const CODEX_VERSION_PROBE_MAX_BUFFER = 64 * 1024;
const SAFE_ID = /^[A-Za-z0-9._:-]{1,128}$/;
const SAFE_MODEL = /^[A-Za-z0-9._:-]{1,128}$/;
const SANDBOX_MODES = new Set(["read-only", "workspace-write"]);
const REASONING_EFFORTS = new Set([
  "minimal",
  "low",
  "medium",
  "high",
  "xhigh"
]);
const SAFE_ITEM_TYPES = new Set([
  "agent_message",
  "command_execution",
  "error",
  "file_change",
  "mcp_tool_call",
  "reasoning",
  "todo_list",
  "web_search"
]);

const SYSTEM_CODES = new Set([
  "ECONNRESET", "ECONNREFUSED", "ETIMEDOUT", "ENOTFOUND", "EAI_AGAIN",
  "ENOENT", "EACCES", "EPERM", "EPIPE"
]);
const PERMANENT_SYSTEM_CODES = new Set(["ENOENT", "EACCES", "EPERM"]);
const PERMANENT_STREAM_ERROR_KINDS = new Set([
  "invalid_request_error",
  "authentication_error",
  "permission_error",
  "not_found_error",
  "model_not_found",
  "insufficient_quota",
  "billing_error",
  "account_deactivated",
  "access_denied"
]);
const RETRYABLE_STREAM_ERROR_KINDS = new Set([
  "connection_error",
  "timeout_error",
  "transport_error",
  "rate_limit_error",
  "server_error",
  "service_unavailable_error",
  "internal_server_error",
  "overloaded_error"
]);

class SafeWorkerError extends Error {
  constructor(code, message, options = {}) {
    const { retryable = false, ...errorOptions } = options;
    super(message, errorOptions);
    this.name = "SafeWorkerError";
    this.code = code;
    this.retryable = retryable;
    this.systemCode = systemErrorCode(errorOptions.cause);
  }
}

function systemErrorCode(error) {
  for (let depth = 0; error instanceof Error && depth < 3; depth++, error = error.cause) {
    if (SYSTEM_CODES.has(error.code)) return error.code;
  }
  return "unknown";
}

export function normalizeRunRequest(input) {
  if (!isRecord(input) || input.type !== "run") {
    throw new SafeWorkerError("invalid_request", 'Expected a JSON object with type "run".');
  }

  const id = resolveAlias(input, "id", "requestId");
  if (typeof id !== "string" || !SAFE_ID.test(id)) {
    throw new SafeWorkerError(
      "invalid_request",
      "id or requestId must contain only letters, numbers, dot, underscore, colon, or dash."
    );
  }
  if (typeof input.model !== "string" || !SAFE_MODEL.test(input.model)) {
    throw new SafeWorkerError("invalid_request", "model must be a non-empty model identifier.");
  }
  if (
    typeof input.prompt !== "string" ||
    input.prompt.trim().length === 0 ||
    input.prompt.length > MAX_PROMPT_CHARS
  ) {
    throw new SafeWorkerError(
      "invalid_request",
      `prompt must contain between 1 and ${MAX_PROMPT_CHARS} characters.`
    );
  }
  if (
    typeof input.workingDirectory !== "string" ||
    input.workingDirectory.length === 0 ||
    input.workingDirectory.length > 4096 ||
    !path.isAbsolute(input.workingDirectory)
  ) {
    throw new SafeWorkerError("invalid_request", "workingDirectory must be an absolute path.");
  }
  if (!SANDBOX_MODES.has(input.sandboxMode)) {
    throw new SafeWorkerError(
      "invalid_request",
      'sandboxMode must be "read-only" or "workspace-write".'
    );
  }

  const networkAccessEnabled = resolveAlias(
    input,
    "networkAccessEnabled",
    "networkAccess"
  );
  if (typeof networkAccessEnabled !== "boolean") {
    throw new SafeWorkerError(
      "invalid_request",
      "networkAccessEnabled or networkAccess must be a boolean."
    );
  }

  if (
    input.reasoningEffort !== undefined &&
    !REASONING_EFFORTS.has(input.reasoningEffort)
  ) {
    throw new SafeWorkerError("invalid_request", "reasoningEffort is not supported.");
  }

  if (input.outputSchema !== undefined) {
    if (!isRecord(input.outputSchema)) {
      throw new SafeWorkerError("invalid_request", "outputSchema must be a JSON object.");
    }
    let serializedSchema;
    try {
      serializedSchema = JSON.stringify(input.outputSchema);
    } catch {
      throw new SafeWorkerError("invalid_request", "outputSchema must be JSON serializable.");
    }
    if (serializedSchema.length > MAX_SCHEMA_CHARS) {
      throw new SafeWorkerError(
        "invalid_request",
        `outputSchema must not exceed ${MAX_SCHEMA_CHARS} serialized characters.`
      );
    }
  }

  return {
    type: "run",
    id,
    model: input.model,
    prompt: input.prompt,
    workingDirectory: input.workingDirectory,
    sandboxMode: input.sandboxMode,
    networkAccessEnabled,
    ...(input.reasoningEffort === undefined
      ? {}
      : { reasoningEffort: input.reasoningEffort }),
    ...(input.outputSchema === undefined ? {} : { outputSchema: input.outputSchema })
  };
}

export async function executeRunRequest(
  request,
  {
    abortController = new AbortController(),
    codexFactory = defaultCodexFactory,
    emit = () => {},
    diagnostic = () => {}
  } = {}
) {
  const lifecycle = createLifecycleEmitter(request.id, emit);
  let threadId = null;
  let finalResponse = "";
  let finalResponseTruncated = false;
  let usage = null;
  let turnCompleted = false;
  let streamWarnings = 0;
  const itemCounts = {};
  const startedAt = performance.now();
  let stage = "launch";

  try {
    const codex = codexFactory();
    const thread = codex.startThread({
      model: request.model,
      sandboxMode: request.sandboxMode,
      approvalPolicy: "never",
      networkAccessEnabled: request.networkAccessEnabled,
      webSearchMode: "disabled",
      skipGitRepoCheck: true,
      workingDirectory: request.workingDirectory,
      ...(request.reasoningEffort === undefined
        ? {}
        : { modelReasoningEffort: request.reasoningEffort })
    });
    stage = "turn_start";
    const { events } = await thread.runStreamed(request.prompt, {
      signal: abortController.signal,
      ...(request.outputSchema === undefined
        ? {}
        : { outputSchema: request.outputSchema })
    });
    if (!events || typeof events[Symbol.asyncIterator] !== "function") {
      throw new SafeWorkerError(
        "invalid_sdk_response",
        "Codex SDK did not return an event stream."
      );
    }

    stage = "stream";
    for await (const event of events) {
      if (abortController.signal.aborted) {
        throw abortController.signal.reason;
      }
      if (!isRecord(event) || typeof event.type !== "string") continue;

      if (event.type === "thread.started") {
        threadId = safeThreadId(event.thread_id) ?? safeThreadId(thread.id);
        lifecycle({ phase: "thread_started", ...(threadId ? { threadId } : {}) });
      } else if (event.type === "turn.started") {
        lifecycle({ phase: "turn_started" });
      } else if (event.type === "item.completed" && isRecord(event.item)) {
        const itemType = safeItemType(event.item.type);
        itemCounts[itemType] = (itemCounts[itemType] ?? 0) + 1;
        if (
          event.item.type === "agent_message" &&
          typeof event.item.text === "string"
        ) {
          const truncated = truncate(event.item.text, MAX_FINAL_RESPONSE_CHARS);
          finalResponse = truncated.value;
          finalResponseTruncated = truncated.truncated;
        }
        lifecycle({
          phase: "item_completed",
          itemType,
          itemCount: itemCounts[itemType]
        });
      } else if (event.type === "turn.completed") {
        usage = normalizeUsage(event.usage);
        turnCompleted = true;
      } else if (event.type === "turn.failed") {
        const message = safeProviderErrorMessage(event.error?.message, "Codex turn failed.");
        diagnostic(`Codex turn failed: ${message}`);
        throw new SafeWorkerError("turn_failed", message);
      } else if (event.type === "error") {
        const message = safeProviderErrorMessage(
          event.message,
          "Codex reported an unrecoverable stream error."
        );
        diagnostic(`Codex stream error: ${message}`);
        throw new SafeWorkerError(
          "stream_error",
          message,
          { retryable: isRetryableStreamError(event) }
        );
      }
    }

    if (!turnCompleted) {
      throw new SafeWorkerError(
        "incomplete_stream",
        "Codex event stream ended before turn completion.",
        { retryable: true }
      );
    }

    return {
      threadId: threadId ?? safeThreadId(thread.id),
      finalResponse,
      finalResponseTruncated,
      usage,
      itemCounts,
      streamWarnings
    };
  } catch (error) {
    if (abortController.signal.aborted) {
      throw new SafeWorkerError("canceled", "Codex run was canceled.", { cause: error });
    }
    const message = error instanceof SafeWorkerError
      ? error.message
      : describeWorkerError(error, diagnostic);
    const failure = error instanceof SafeWorkerError ? error
      : looksLikeMissingCodex(error) ? new SafeWorkerError(
        "codex_unavailable",
        "The local Codex executable could not be started.",
        { cause: error }
      ) : new SafeWorkerError("worker_failed", message, {
        cause: error,
        retryable: stage === "stream" && isRetryableStreamFailure(error)
      });
    failure.stage = stage;
    failure.elapsedMs = performance.now() - startedAt;
    throw failure;
  }
}

export function startStdioWorker({
  input = process.stdin,
  output = process.stdout,
  errorOutput = process.stderr,
  setExitCode = (code) => {
    process.exitCode = code;
  },
  codexFactory = defaultCodexFactory
} = {}) {
  const readline = createInterface({ input, crlfDelay: Infinity });
  let active = null;
  let finished = false;
  let runStarted = false;

  const emit = (message) => {
    output.write(`${JSON.stringify(message)}\n`);
  };
  const finish = (exitCode) => {
    if (finished) return;
    finished = true;
    setExitCode(exitCode);
    readline.close();
    input.pause?.();
  };
  const failProtocol = (error, id = null) => {
    const safeError =
      error instanceof SafeWorkerError
        ? error
        : new SafeWorkerError("invalid_request", "Invalid worker request.");
    emit({
      type: "failed",
      id,
      code: safeError.code,
      message: safeError.message,
      retryable: safeError.retryable,
      systemCode: safeError.systemCode,
      stage: "validation"
    });
    finish(2);
  };

  const startRun = (inputRequest) => {
    let request;
    try {
      request = normalizeRunRequest(inputRequest);
    } catch (error) {
      failProtocol(error, safeRequestId(inputRequest));
      return;
    }
    runStarted = true;
    const abortController = new AbortController();
    active = { id: request.id, abortController };
    emit({ type: "accepted", id: request.id });

    void executeRunRequest(request, {
      abortController,
      codexFactory,
      emit,
      diagnostic: (message) => errorOutput.write(`[codex-worker] ${message}\n`)
    })
      .then((result) => {
        emit({
          type: "completed",
          id: request.id,
          threadId: result.threadId,
          finalResponse: result.finalResponse,
          finalResponseTruncated: result.finalResponseTruncated,
          usage: result.usage,
          itemCounts: result.itemCounts,
          streamWarnings: result.streamWarnings
        });
        finish(0);
      })
      .catch((error) => {
        const safeError =
          error instanceof SafeWorkerError
            ? error
            : new SafeWorkerError("worker_failed", "Codex worker failed.");
        if (safeError.code === "canceled") {
          const reason = active?.abortController.signal.reason;
          emit({
            type: "canceled",
            id: request.id,
            reason:
              isRecord(reason) && typeof reason.signal === "string"
                ? reason.signal
                : "requested"
          });
          finish(
            isRecord(reason) && reason.signal === "SIGTERM"
              ? 143
              : isRecord(reason) && reason.signal === "SIGINT"
                ? 130
                : 0
          );
          return;
        }
        emit({
          type: "failed",
          id: request.id,
          code: safeError.code,
          message: safeError.message,
          retryable: safeError.retryable,
          systemCode: safeError.systemCode,
          stage: safeError.stage ?? "validation",
          elapsedMs: safeError.elapsedMs ?? null
        });
        finish(1);
      });
  };

  readline.on("line", (line) => {
    if (finished || line.trim().length === 0) return;
    let message;
    try {
      message = JSON.parse(line);
    } catch {
      if (!runStarted) {
        failProtocol(new SafeWorkerError("invalid_json", "Input must be valid JSON."));
      } else {
        emit({
          type: "protocol_error",
          id: active?.id ?? null,
          code: "invalid_json",
          message: "Input must be valid JSON."
        });
      }
      return;
    }

    if (isRecord(message) && message.type === "cancel") {
      if (!active || message.id !== active.id) {
        emit({
          type: "protocol_error",
          id: safeRequestId(message),
          code: "unknown_run",
          message: "No matching run is active."
        });
        return;
      }
      active.abortController.abort({ kind: "cancel" });
      return;
    }

    if (runStarted) {
      emit({
        type: "protocol_error",
        id: safeRequestId(message),
        code: "run_already_started",
        message: "This worker accepts exactly one run request."
      });
      return;
    }
    startRun(message);
  });

  emit({ type: "ready", protocolVersion: PROTOCOL_VERSION });

  return {
    cancel(signal = "SIGTERM") {
      if (!active || active.abortController.signal.aborted) return false;
      active.abortController.abort({ kind: "signal", signal });
      return true;
    },
    close() {
      if (!finished) finish(0);
    }
  };
}

function defaultCodexFactory() {
  const target = resolveCodexTarget();
  const env = Object.fromEntries(
    Object.entries(process.env).filter((entry) => entry[1] !== undefined)
  );
  env[CLI_WRAPPER_MODE_ENV] = "1";
  env[CLI_WRAPPER_TARGET_ENV] = target;
  env[CLI_WRAPPER_OWNER_ENV] = String(process.pid);
  return new Codex({
    codexPathOverride: fileURLToPath(import.meta.url),
    env
  });
}

export function resolveCodexTarget({
  env = process.env,
  platform = process.platform,
  applicationRoots = defaultApplicationRoots(env, platform),
  probe = probeCodexCandidate
} = {}) {
  const candidates = [];
  const addCandidate = (candidate) => {
    if (candidate && !candidates.includes(candidate)) candidates.push(candidate);
  };
  const configured = env.CODEX_CLI_PATH?.trim();
  addCandidate(configured);

  const executableName = platform === "win32" ? "codex.exe" : "codex";
  for (const pathMatch of findExecutablesOnPath(executableName, env, platform)) {
    addCandidate(pathMatch);
  }

  if (platform === "darwin") {
    for (const applicationRoot of applicationRoots) {
      for (const applicationName of codexApplicationNames(applicationRoot)) {
        const candidate = path.join(
          applicationRoot,
          applicationName,
          "Contents",
          "Resources",
          "codex"
        );
        if (isExecutableFile(candidate)) addCandidate(candidate);
      }
    }
  }

  for (const candidate of candidates) {
    try {
      if (probe(candidate, env)) return candidate;
    } catch {
      // A failed probe only rejects this candidate.
    }
  }

  const checked = candidates.length > 0 ? ` Checked: ${candidates.join(", ")}.` : "";
  throw new SafeWorkerError(
    "codex_unavailable",
    `No working Codex executable was found.${checked}`
  );
}

function defaultApplicationRoots(env, platform) {
  if (platform !== "darwin") return [];
  const home = env.HOME?.trim() || homedir();
  return ["/Applications", path.join(home, "Applications")];
}

function findExecutablesOnPath(executableName, env, platform) {
  const pathValue =
    platform === "win32"
      ? Object.entries(env).find(([key]) => key.toLowerCase() === "path")?.[1]
      : env.PATH;
  if (!pathValue) return [];
  const matches = [];
  for (const directory of pathValue.split(path.delimiter)) {
    if (!directory) continue;
    const candidate = path.join(directory, executableName);
    if (isExecutableFile(candidate)) matches.push(candidate);
  }
  return matches;
}

function probeCodexCandidate(candidate, env) {
  const completed = spawnSync(candidate, ["--version"], {
    env,
    encoding: "utf8",
    stdio: ["ignore", "pipe", "pipe"],
    timeout: CODEX_VERSION_PROBE_TIMEOUT_MS,
    maxBuffer: CODEX_VERSION_PROBE_MAX_BUFFER,
    windowsHide: true
  });
  return completed.status === 0 && completed.error === undefined;
}

function codexApplicationNames(applicationRoot) {
  try {
    return readdirSync(applicationRoot, { withFileTypes: true })
      .filter(
        (entry) =>
          entry.isDirectory() && /^(?:Codex|ChatGPT).*\.app$/.test(entry.name)
      )
      .map((entry) => entry.name)
      .sort((left, right) => applicationPriority(left) - applicationPriority(right));
  } catch {
    return [];
  }
}

function applicationPriority(name) {
  if (name === "Codex.app") return 0;
  if (name === "ChatGPT.app") return 1;
  if (name.startsWith("Codex")) return 2;
  return 3;
}

function isExecutableFile(candidate) {
  try {
    if (!statSync(candidate).isFile()) return false;
    accessSync(candidate, constants.X_OK);
    return true;
  } catch {
    return false;
  }
}

function startCodexCliWrapper() {
  const target = process.env[CLI_WRAPPER_TARGET_ENV]?.trim();
  if (!target) {
    process.stderr.write("Missing isolated Codex CLI target.\n");
    process.exitCode = 127;
    return;
  }

  const originalArgs = process.argv.slice(2);
  if (originalArgs[0] !== "exec") {
    process.stderr.write("The isolated Codex wrapper only supports exec.\n");
    process.exitCode = 2;
    return;
  }
  const args = [
    "exec",
    "--ignore-rules",
    ...originalArgs.slice(1)
  ];
  const detached = process.platform !== "win32";
  const child = spawn(target, args, {
    detached,
    env: process.env,
    stdio: "inherit"
  });
  let killTimer = null;

  const killTree = (signal) => {
    if (child.exitCode !== null || child.signalCode !== null) return;
    try {
      if (detached && Number.isInteger(child.pid)) {
        process.kill(-child.pid, signal);
      } else {
        child.kill(signal);
      }
    } catch {
      // The process may have exited between the status check and signal delivery.
    }
  };
  const forwardSignal = (signal) => {
    killTree(signal);
    if (killTimer === null) {
      killTimer = setTimeout(() => killTree("SIGKILL"), TREE_KILL_GRACE_MS);
      killTimer.unref?.();
    }
  };
  const signalHandlers = new Map(
    ["SIGTERM", "SIGINT", "SIGHUP"].map((signal) => {
      const handler = () => forwardSignal(signal);
      process.on(signal, handler);
      return [signal, handler];
    })
  );
  const ownerPid = Number.parseInt(process.env[CLI_WRAPPER_OWNER_ENV] ?? "", 10);
  const ownerMonitor =
    Number.isInteger(ownerPid) && ownerPid > 1
      ? setInterval(() => {
          try {
            process.kill(ownerPid, 0);
          } catch {
            forwardSignal("SIGTERM");
          }
        }, 250)
      : null;
  ownerMonitor?.unref?.();

  const cleanup = () => {
    if (killTimer !== null) clearTimeout(killTimer);
    if (ownerMonitor !== null) clearInterval(ownerMonitor);
    for (const [signal, handler] of signalHandlers) {
      process.off(signal, handler);
    }
  };
  child.once("error", (error) => {
    cleanup();
    process.stderr.write(`${error.message}\n`);
    process.exitCode = 127;
  });
  child.once("exit", (code, signal) => {
    cleanup();
    process.exitCode = code ?? signalExitCode(signal);
  });
}

function signalExitCode(signal) {
  return {
    SIGHUP: 129,
    SIGINT: 130,
    SIGTERM: 143,
    SIGKILL: 137
  }[signal] ?? 1;
}

function createLifecycleEmitter(id, emit) {
  let emitted = 0;
  return (event) => {
    if (emitted >= MAX_LIFECYCLE_EVENTS) return;
    emitted += 1;
    emit({ type: "lifecycle", id, sequence: emitted, ...event });
  };
}

function normalizeUsage(value) {
  if (!isRecord(value)) return null;
  const usage = {};
  for (const key of [
    "input_tokens",
    "cached_input_tokens",
    "output_tokens",
    "reasoning_output_tokens"
  ]) {
    if (Number.isSafeInteger(value[key]) && value[key] >= 0) {
      usage[key] = value[key];
    }
  }
  return Object.keys(usage).length > 0 ? usage : null;
}

function resolveAlias(input, canonical, alias) {
  if (
    input[canonical] !== undefined &&
    input[alias] !== undefined &&
    input[canonical] !== input[alias]
  ) {
    throw new SafeWorkerError(
      "invalid_request",
      `${canonical} and ${alias} must match when both are provided.`
    );
  }
  return input[canonical] ?? input[alias];
}

function safeItemType(value) {
  return typeof value === "string" && SAFE_ITEM_TYPES.has(value) ? value : "other";
}

function safeThreadId(value) {
  return typeof value === "string" && /^[A-Za-z0-9_-]{1,256}$/.test(value)
    ? value
    : null;
}

function safeRequestId(value) {
  if (!isRecord(value)) return null;
  const id = value.id ?? value.requestId;
  return typeof id === "string" && SAFE_ID.test(id) ? id : null;
}

function describeWorkerError(error, diagnostic) {
  const messages = [];
  for (let depth = 0; error instanceof Error && depth < 3; depth++, error = error.cause) {
    if (error.message.trim()) messages.push(error.message.trim());
  }
  const fallback = "Codex worker failed.";
  if (messages.length === 0) return fallback;

  // SDK exceptions include CLI stderr. Keep bounded, redacted context locally,
  // but surface the final cause line rather than pages of startup warnings.
  diagnostic(`Codex worker exception: ${safeProviderErrorMessage(
    messages.join("\nCaused by: "), fallback, MAX_WORKER_DIAGNOSTIC_CHARS
  )}`);
  return safeProviderErrorMessage(messages.at(-1).split(/\r?\n/).at(-1), fallback);
}

function safeProviderErrorMessage(value, fallback, maxChars = MAX_PROVIDER_ERROR_CHARS) {
  if (typeof value !== "string" || !value.trim()) return fallback;

  let message = value;
  const parsed = parseProviderErrorPayload(value);
  if (isRecord(parsed?.error) && typeof parsed.error.message === "string") {
    message = parsed.error.message;
  } else if (isRecord(parsed) && typeof parsed.message === "string") {
    message = parsed.message;
  }

  return redactKnownCredentials(message)
    .replace(/[\u0000-\u001f\u007f]/g, " ")
    .trim()
    .slice(0, maxChars) || fallback;
}

function redactKnownCredentials(message) {
  return message
    .replace(/\bBearer\s+[A-Za-z0-9._~+/-]+=*/gi, "Bearer [REDACTED]")
    .replace(/\bsk-(?:proj-|svcacct-)?[A-Za-z0-9_-]{12,}/g, "[REDACTED]")
    .replace(/\b(api[_-]?key|access[_-]?token|password|secret)\s*[:=]\s*[^\s,;]+/gi, "$1=[REDACTED]");
}

function parseProviderErrorPayload(value) {
  if (typeof value !== "string" || !value.trim()) return null;
  try {
    const parsed = JSON.parse(value);
    return isRecord(parsed) ? parsed : null;
  } catch {
    return null;
  }
}

function providerErrorObjects(event) {
  if (!isRecord(event)) return [];
  const objects = [event];
  const parsed = parseProviderErrorPayload(event.message);
  if (parsed !== null) objects.push(parsed);
  for (const value of [...objects]) {
    if (isRecord(value.error)) objects.push(value.error);
  }
  return objects;
}

function providerErrorStatus(value) {
  const status = value.status ?? value.status_code ?? value.statusCode;
  if (Number.isInteger(status)) return status;
  if (typeof status === "string" && /^[0-9]{3}$/.test(status)) {
    return Number(status);
  }
  return null;
}

function providerErrorKinds(objects) {
  const kinds = [];
  for (const value of objects) {
    for (const field of ["type", "code", "error_code"]) {
      if (typeof value[field] === "string") kinds.push(value[field]);
    }
  }
  return kinds;
}

function isRetryableStreamError(event) {
  const objects = providerErrorObjects(event);
  const kinds = providerErrorKinds(objects).map((kind) => kind.toLowerCase());
  if (kinds.some((kind) => PERMANENT_STREAM_ERROR_KINDS.has(kind))) {
    return false;
  }
  if (kinds.some((kind) => RETRYABLE_STREAM_ERROR_KINDS.has(kind))) {
    return true;
  }

  for (const value of objects) {
    const status = providerErrorStatus(value);
    if (status === 408 || status === 429 || (status !== null && status >= 500)) {
      return true;
    }
    if (status !== null && status >= 400 && status < 500) {
      return false;
    }
  }

  const message = typeof event?.message === "string" ? event.message : "";
  if (
    /auth|unauthoriz|forbidden|api key|quota|billing|usage limit|model.*(?:access|not found)|invalid request/i.test(
      message
    )
  ) {
    return false;
  }

  // An SDK stream error without a known permanent cause is most likely a
  // transport interruption. Retrying in a fresh workspace is safer than
  // turning a wording change into a terminal Replay failure.
  return true;
}

function isRetryableStreamFailure(error) {
  const code = systemErrorCode(error);
  if (PERMANENT_SYSTEM_CODES.has(code)) return false;
  if (code !== "unknown") return true;
  if (looksLikePermanentLocalFailure(error)) return false;
  return isRetryableStreamError(error);
}

function looksLikePermanentLocalFailure(error) {
  const message = error instanceof Error ? error.message : String(error);
  return /(?:operation not permitted|permission denied|failed to initialize in-process app-server client)/i.test(
    message
  );
}

function truncate(value, maxChars) {
  if (value.length <= maxChars) return { value, truncated: false };
  return { value: value.slice(0, maxChars), truncated: true };
}

function looksLikeMissingCodex(error) {
  const message = error instanceof Error ? error.message : String(error);
  return /(?:ENOENT|Unable to locate Codex CLI binaries|spawn .* not found)/i.test(message);
}

function isRecord(value) {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function isMainModule() {
  const scriptPath = process.argv[1];
  return typeof scriptPath === "string" && pathToFileURL(path.resolve(scriptPath)).href === import.meta.url;
}

if (isMainModule()) {
  if (process.env[CLI_WRAPPER_MODE_ENV] === "1") {
    startCodexCliWrapper();
  } else {
    const worker = startStdioWorker();
    process.once("SIGTERM", () => {
      if (worker.cancel("SIGTERM")) {
        setTimeout(() => process.exit(143), 5_000).unref();
      } else {
        process.exitCode = 143;
        worker.close();
      }
    });
    process.once("SIGINT", () => {
      if (worker.cancel("SIGINT")) {
        setTimeout(() => process.exit(130), 5_000).unref();
      } else {
        process.exitCode = 130;
        worker.close();
      }
    });
  }
}

SHA-256: 36338d4f5a82f2d9805deb98b0ffecda511a2942c77cc3dd0517259c7527b312