// Force strict mode and setup for ESM
"use strict";
import {
  CHANNEL_DAEMON_WORKER_SENTINEL,
  CHANNEL_WEBHOOK_TASK_IPC_TIMEOUT_MS,
  CHANNEL_WORKER_HEARTBEAT_INTERVAL_MS,
  ChannelWebhookEnqueueError,
  MAX_CHANNEL_STARTUP_FAILURES,
  MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH,
  MAX_CHANNEL_STARTUP_FAILURE_CODE_LENGTH,
  MAX_CHANNEL_STARTUP_FAILURE_MESSAGE_LENGTH,
  QWEN_DAEMON_TOKEN_ENV,
  QWEN_DAEMON_URL_ENV,
  QWEN_DAEMON_WORKSPACE_ENV,
  QWEN_SERVER_TOKEN_ENV,
  createChannelWebhookTaskMessage,
  createWorkerDiagnosticRedactor,
  isChannelStartupReportMessage,
  isChannelStartupReportType,
  isChannelWebhookEnqueueErrorCode,
  isChannelWebhookTaskResultMessage,
  normalizeWorkerDiagnostic,
  sanitizeWorkerDiagnostic
} from "./chunk-KSZKSE23.js";
import {
  channelSelectionNames
} from "./chunk-TJTKSVIV.js";
import {
  CHANNEL_WORKER_KILL_GRACE_MS,
  CHANNEL_WORKER_STARTUP_TIMEOUT_MS,
  CHANNEL_WORKER_STOP_GRACE_MS
} from "./chunk-5HBA2Z7V.js";
import {
  sanitizeLogText
} from "./chunk-ZQIYGQCG.js";
import {
  init_esbuild_shims
} from "./chunk-5O2XNYP6.js";
import {
  __name
} from "./chunk-J2S4EL5Y.js";

// packages/cli/src/serve/channel-worker-supervisor.ts
init_esbuild_shims();
import { fork } from "node:child_process";
import { randomUUID } from "node:crypto";
var DEFAULT_CHANNEL_WORKER_HEARTBEAT_TIMEOUT_MS = 45e3;
var MAX_WORKER_LOG_LINE_LENGTH = 4096;
var MAX_WORKER_LOG_BUFFER_LENGTH = 64 * 1024;
var MAX_WORKER_LOG_DISCARDED_REMAINDER_LENGTH = MAX_WORKER_LOG_BUFFER_LENGTH;
var ChannelWorkerStopError = class extends Error {
  static {
    __name(this, "ChannelWorkerStopError");
  }
  constructor(message = "Channel worker did not exit after SIGKILL.") {
    super(message);
    this.name = "ChannelWorkerStopError";
  }
};
var ChannelWorkerStartupError = class extends Error {
  static {
    __name(this, "ChannelWorkerStartupError");
  }
  startupFailures;
  startupFailuresTruncated;
  constructor(message, details) {
    super(message);
    this.name = "ChannelWorkerStartupError";
    this.startupFailures = details.startupFailures.map((failure) => ({
      ...failure,
      workspaceCwd: details.workspaceCwd
    }));
    this.startupFailuresTruncated = details.startupFailuresTruncated === true;
  }
};
var DEFAULT_RESTART_POLICY = {
  maxRestarts: 3,
  windowMs: 5 * 6e4,
  delaysMs: [1e3, 5e3, 15e3]
};
function selectionChannelArgs(selection) {
  return channelSelectionNames(selection).flatMap((name) => [
    "--channel",
    name
  ]);
}
__name(selectionChannelArgs, "selectionChannelArgs");
function defaultSpawnWorker(execPath, argv, options) {
  const child = fork(argv[0], argv.slice(1), {
    execPath,
    cwd: options.cwd,
    env: options.env,
    stdio: options.stdio
  });
  return child;
}
__name(defaultSpawnWorker, "defaultSpawnWorker");
function isReadyMessage(message) {
  return typeof message === "object" && message !== null && message.type === "ready";
}
__name(isReadyMessage, "isReadyMessage");
function isHeartbeatMessage(message) {
  return typeof message === "object" && message !== null && message.type === "heartbeat";
}
__name(isHeartbeatMessage, "isHeartbeatMessage");
function requestedChannelNames(selection) {
  return selection.mode === "names" ? [...selection.names] : void 0;
}
__name(requestedChannelNames, "requestedChannelNames");
function workerLogRedactionOptions(daemonToken, workerEnv) {
  return {
    ...daemonToken ? { daemonToken } : {},
    workerEnv
  };
}
__name(workerLogRedactionOptions, "workerLogRedactionOptions");
function sanitizeWorkerError(error, redaction) {
  return redaction ? sanitizeWorkerDiagnostic(error, 512, redaction) : sanitizeLogText(normalizeWorkerDiagnostic(error), 512);
}
__name(sanitizeWorkerError, "sanitizeWorkerError");
function notifyExit(onExit, snapshot) {
  try {
    onExit?.(snapshot);
  } catch {
  }
}
__name(notifyExit, "notifyExit");
function notifyReady(onReady, snapshot) {
  try {
    onReady?.(snapshot);
  } catch {
  }
}
__name(notifyReady, "notifyReady");
function notifyLog(onLog, entry) {
  try {
    onLog?.(entry);
  } catch {
  }
}
__name(notifyLog, "notifyLog");
function waitForExit(child, timeoutMs) {
  return new Promise((resolve) => {
    let settled = false;
    const onExit = /* @__PURE__ */ __name(() => done(true), "onExit");
    const done = /* @__PURE__ */ __name((exited) => {
      if (settled) return;
      settled = true;
      clearTimeout(timer);
      child.removeListener("exit", onExit);
      resolve(exited);
    }, "done");
    const timer = setTimeout(() => done(false), timeoutMs);
    timer.unref();
    child.once("exit", onExit);
  });
}
__name(waitForExit, "waitForExit");
function hasObservedExit(snapshot) {
  return snapshot.exitCode !== void 0 || snapshot.signal !== void 0;
}
__name(hasObservedExit, "hasObservedExit");
function createWorkerEnv(opts) {
  const env = { ...opts.baseEnv ?? process.env };
  env["QWEN_CODE_NO_RELAUNCH"] = "true";
  env[CHANNEL_DAEMON_WORKER_SENTINEL] = randomUUID();
  env[QWEN_DAEMON_URL_ENV] = opts.daemonUrl;
  env[QWEN_DAEMON_WORKSPACE_ENV] = opts.workspace;
  delete env[QWEN_SERVER_TOKEN_ENV];
  delete env[QWEN_DAEMON_TOKEN_ENV];
  if (opts.daemonToken) {
    env[QWEN_DAEMON_TOKEN_ENV] = opts.daemonToken;
  }
  return env;
}
__name(createWorkerEnv, "createWorkerEnv");
function attachWorkerLogStream(stream, streamName, opts) {
  if (!stream) return () => {
  };
  let buffer = "";
  let discardingOversizedLineRemainder = false;
  let discardedOversizedLineRemainderLength = 0;
  const redactWorkerLogLineForStream = createWorkerDiagnosticRedactor({
    ...opts.daemonToken ? { daemonToken: opts.daemonToken } : {},
    workerEnv: opts.workerEnv
  });
  const flushLine = /* @__PURE__ */ __name((line) => {
    const displayLine = line.replace(/\t/gu, " ");
    const redacted = redactWorkerLogLineForStream(
      normalizeWorkerDiagnostic(displayLine)
    );
    notifyLog(opts.onLog, {
      stream: streamName,
      line: sanitizeLogText(redacted, MAX_WORKER_LOG_LINE_LENGTH)
    });
  }, "flushLine");
  const flushPartial = /* @__PURE__ */ __name(() => {
    if (buffer.length === 0) return;
    flushLine(buffer);
    buffer = "";
  }, "flushPartial");
  const flushOversizedBuffer = /* @__PURE__ */ __name(() => {
    if (buffer.length <= MAX_WORKER_LOG_BUFFER_LENGTH) return;
    flushLine(buffer);
    buffer = "";
    discardingOversizedLineRemainder = true;
    discardedOversizedLineRemainderLength = 0;
  }, "flushOversizedBuffer");
  stream.on("data", (chunk) => {
    buffer += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
    for (; ; ) {
      const newlineIndex = buffer.search(/\r?\n/);
      if (newlineIndex < 0) break;
      const line = buffer.slice(0, newlineIndex);
      const newlineLength = buffer[newlineIndex] === "\r" && buffer[newlineIndex + 1] === "\n" ? 2 : 1;
      buffer = buffer.slice(newlineIndex + newlineLength);
      if (!discardingOversizedLineRemainder) {
        flushLine(line);
      }
      discardingOversizedLineRemainder = false;
      discardedOversizedLineRemainderLength = 0;
    }
    if (discardingOversizedLineRemainder) {
      discardedOversizedLineRemainderLength += buffer.length;
      buffer = "";
      if (discardedOversizedLineRemainderLength >= MAX_WORKER_LOG_DISCARDED_REMAINDER_LENGTH) {
        discardingOversizedLineRemainder = false;
        discardedOversizedLineRemainderLength = 0;
      }
      return;
    }
    flushOversizedBuffer();
  });
  stream.on("end", flushPartial);
  stream.on("close", flushPartial);
  stream.on("error", () => {
    flushPartial();
  });
  return flushPartial;
}
__name(attachWorkerLogStream, "attachWorkerLogStream");
function createChannelWorkerSupervisor(opts) {
  const spawnWorker = opts.spawnWorker ?? defaultSpawnWorker;
  const restartPolicy = opts.restartPolicy ?? DEFAULT_RESTART_POLICY;
  if (restartPolicy.delaysMs.length === 0) {
    throw new Error("restartPolicy.delaysMs must be non-empty.");
  }
  const heartbeatTimeoutMs = opts.heartbeatTimeoutMs ?? DEFAULT_CHANNEL_WORKER_HEARTBEAT_TIMEOUT_MS;
  if (heartbeatTimeoutMs > 0 && heartbeatTimeoutMs <= CHANNEL_WORKER_HEARTBEAT_INTERVAL_MS) {
    throw new Error(
      `heartbeatTimeoutMs (${heartbeatTimeoutMs}) must exceed the worker heartbeat interval (${CHANNEL_WORKER_HEARTBEAT_INTERVAL_MS}ms) or be 0 to disable.`
    );
  }
  let child;
  let snapshot = {
    enabled: true,
    state: "disabled",
    channels: channelSelectionNames(opts.selection),
    restartCount: 0
  };
  let stopping = false;
  let restartTimer;
  let staleHeartbeatTimer;
  let restartAttemptTimes = [];
  const pendingWebhookTasks = /* @__PURE__ */ new Map();
  let restarting;
  let disposed = false;
  const snapshotCopy = /* @__PURE__ */ __name(() => ({
    ...snapshot,
    channels: [...snapshot.channels],
    ...snapshot.requestedChannels ? { requestedChannels: [...snapshot.requestedChannels] } : {},
    ...snapshot.startupFailures ? {
      startupFailures: snapshot.startupFailures.map((failure) => ({
        ...failure
      }))
    } : {}
  }), "snapshotCopy");
  const clearRestartTimer = /* @__PURE__ */ __name(() => {
    if (restartTimer) {
      clearTimeout(restartTimer);
      restartTimer = void 0;
    }
    if (snapshot.nextRestartAt) {
      const next = { ...snapshot };
      delete next.nextRestartAt;
      snapshot = next;
    }
  }, "clearRestartTimer");
  const clearStaleHeartbeatTimer = /* @__PURE__ */ __name(() => {
    if (!staleHeartbeatTimer) return;
    clearTimeout(staleHeartbeatTimer);
    staleHeartbeatTimer = void 0;
  }, "clearStaleHeartbeatTimer");
  const rejectPendingWebhookTasks = /* @__PURE__ */ __name((code, message) => {
    for (const pending of pendingWebhookTasks.values()) {
      clearTimeout(pending.timer);
      pending.reject(new ChannelWebhookEnqueueError(code, message));
    }
    pendingWebhookTasks.clear();
  }, "rejectPendingWebhookTasks");
  const rejectPendingWebhookTask = /* @__PURE__ */ __name((id, err) => {
    const pending = pendingWebhookTasks.get(id);
    if (!pending) return;
    pendingWebhookTasks.delete(id);
    clearTimeout(pending.timer);
    pending.reject(err);
  }, "rejectPendingWebhookTask");
  const settleWebhookTask = /* @__PURE__ */ __name((message) => {
    if (!isChannelWebhookTaskResultMessage(message)) return false;
    const pending = pendingWebhookTasks.get(message.id);
    if (!pending) return true;
    if (message.ok) {
      pendingWebhookTasks.delete(message.id);
      clearTimeout(pending.timer);
      pending.resolve({ accepted: true });
    } else {
      const code = isChannelWebhookEnqueueErrorCode(message.code) ? message.code : "channel_webhook_enqueue_failed";
      rejectPendingWebhookTask(
        message.id,
        new ChannelWebhookEnqueueError(
          code,
          message.error || "Channel webhook task failed."
        )
      );
    }
    return true;
  }, "settleWebhookTask");
  const pruneRestartAttempts = /* @__PURE__ */ __name((nowMs) => {
    restartAttemptTimes = restartAttemptTimes.filter(
      (attemptMs) => nowMs - attemptMs < restartPolicy.windowMs
    );
  }, "pruneRestartAttempts");
  const canScheduleRestart = /* @__PURE__ */ __name((nowMs) => {
    pruneRestartAttempts(nowMs);
    return restartAttemptTimes.length < restartPolicy.maxRestarts;
  }, "canScheduleRestart");
  const nextRestartDelayMs = /* @__PURE__ */ __name(() => {
    const index = Math.min(
      restartAttemptTimes.length,
      restartPolicy.delaysMs.length - 1
    );
    return restartPolicy.delaysMs[index] ?? 0;
  }, "nextRestartDelayMs");
  const setExited = /* @__PURE__ */ __name((state, code, signal, error) => {
    const next = {
      ...snapshot,
      state,
      exitCode: code,
      signal,
      lastExitAt: (/* @__PURE__ */ new Date()).toISOString()
    };
    if (error) {
      next.error = error;
    } else {
      delete next.error;
    }
    snapshot = {
      ...next
    };
  }, "setExited");
  const scheduleRestart = /* @__PURE__ */ __name(() => {
    if (stopping) return false;
    const nowMs = Date.now();
    if (!canScheduleRestart(nowMs)) {
      const lastError = snapshot.error;
      snapshot = {
        ...snapshot,
        state: "failed",
        error: lastError ? `Channel worker restart budget exhausted. Last error: ${lastError}` : "Channel worker restart budget exhausted.",
        nextRestartAt: void 0
      };
      return false;
    }
    clearRestartTimer();
    const delayMs = nextRestartDelayMs();
    const nextRestartAt = new Date(nowMs + delayMs).toISOString();
    snapshot = {
      ...snapshot,
      nextRestartAt
    };
    restartTimer = setTimeout(() => {
      restartTimer = void 0;
      void launch("restart").catch((err) => {
        handleRestartFailure(err instanceof Error ? err.message : String(err));
      });
    }, delayMs);
    restartTimer.unref();
    return true;
  }, "scheduleRestart");
  const handleRestartFailure = /* @__PURE__ */ __name((error, redaction) => {
    snapshot = {
      ...snapshot,
      state: "failed",
      error: sanitizeWorkerError(error, redaction)
    };
    scheduleRestart();
    notifyExit(opts.onExit, snapshotCopy());
  }, "handleRestartFailure");
  const armStaleHeartbeatTimer = /* @__PURE__ */ __name((startedChild) => {
    clearStaleHeartbeatTimer();
    if (heartbeatTimeoutMs <= 0) return;
    staleHeartbeatTimer = setTimeout(() => {
      if (child !== startedChild || stopping) return;
      snapshot = {
        ...snapshot,
        error: "Channel worker heartbeat timed out.",
        staleHeartbeatAt: (/* @__PURE__ */ new Date()).toISOString()
      };
      startedChild.kill("SIGKILL");
    }, heartbeatTimeoutMs);
    staleHeartbeatTimer.unref();
  }, "armStaleHeartbeatTimer");
  const launch = /* @__PURE__ */ __name(async (kind) => {
    clearStaleHeartbeatTimer();
    const argv = [
      opts.cliEntryPath,
      "channel",
      "daemon-worker",
      ...selectionChannelArgs(opts.selection)
    ];
    const env = createWorkerEnv({
      daemonUrl: opts.daemonUrl,
      workspace: opts.workspace,
      ...opts.daemonToken ? { daemonToken: opts.daemonToken } : {},
      ...opts.workerBaseEnv ? { baseEnv: opts.workerBaseEnv } : {}
    });
    const redaction = workerLogRedactionOptions(opts.daemonToken, env);
    const requestedChannels = requestedChannelNames(opts.selection);
    const startedAt = (/* @__PURE__ */ new Date()).toISOString();
    snapshot = {
      enabled: true,
      state: "starting",
      channels: channelSelectionNames(opts.selection),
      ...requestedChannels ? { requestedChannels } : {},
      startedAt,
      restartCount: snapshot.restartCount ?? 0,
      ...snapshot.lastExitAt ? { lastExitAt: snapshot.lastExitAt } : {},
      ...snapshot.lastHeartbeatAt ? { lastHeartbeatAt: snapshot.lastHeartbeatAt } : {},
      ...snapshot.staleHeartbeatAt ? { staleHeartbeatAt: snapshot.staleHeartbeatAt } : {}
    };
    if (kind === "restart") {
      const nowMs = Date.now();
      restartAttemptTimes.push(nowMs);
      snapshot = {
        ...snapshot,
        restartCount: (snapshot.restartCount ?? 0) + 1,
        lastRestartAt: new Date(nowMs).toISOString(),
        nextRestartAt: void 0
      };
    }
    let startedChild;
    try {
      startedChild = spawnWorker(process.execPath, argv, {
        cwd: opts.workspace,
        env,
        stdio: ["ignore", "pipe", "pipe", "ipc"]
      });
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err);
      const error = sanitizeWorkerError(message, redaction);
      if (kind === "initial") {
        snapshot = {
          ...snapshot,
          state: "failed",
          error
        };
        throw new Error(error);
      }
      handleRestartFailure(message, redaction);
      return;
    }
    child = startedChild;
    attachWorkerLogStream(startedChild.stdout, "stdout", {
      ...redaction,
      onLog: opts.onLog
    });
    attachWorkerLogStream(startedChild.stderr, "stderr", {
      ...redaction,
      onLog: opts.onLog
    });
    if (startedChild.pid !== void 0) {
      snapshot = { ...snapshot, pid: startedChild.pid };
    }
    await new Promise((resolve, reject) => {
      let settled = false;
      let ready = false;
      let exitObserved = false;
      let terminatingBeforeReady = false;
      let startupTimer;
      const cleanupStartupTimer = /* @__PURE__ */ __name(() => {
        if (!startupTimer) return;
        clearTimeout(startupTimer);
        startupTimer = void 0;
      }, "cleanupStartupTimer");
      const cleanupLaunch = /* @__PURE__ */ __name(() => {
        cleanupStartupTimer();
        startedChild.removeListener("message", handleMessage);
        clearStaleHeartbeatTimer();
      }, "cleanupLaunch");
      const terminateBeforeReady = /* @__PURE__ */ __name(() => {
        cleanupLaunch();
        if (terminatingBeforeReady) return;
        terminatingBeforeReady = true;
        const exited = waitForExit(startedChild, CHANNEL_WORKER_KILL_GRACE_MS);
        startedChild.kill("SIGTERM");
        void exited.then(async (didExit) => {
          if (!didExit && child === startedChild && !exitObserved) {
            const killed = waitForExit(
              startedChild,
              CHANNEL_WORKER_KILL_GRACE_MS
            );
            startedChild.kill("SIGKILL");
            if (!await killed && child === startedChild && !exitObserved) {
              stopping = true;
              notifyLog(opts.onLog, {
                stream: "stderr",
                line: "Channel worker did not exit after SIGKILL; automatic restart is disabled."
              });
              snapshot = {
                ...snapshot,
                state: "failed",
                error: snapshot.error ?? "Channel worker did not exit after SIGKILL."
              };
              notifyExit(opts.onExit, snapshotCopy());
            }
          }
        });
      }, "terminateBeforeReady");
      const failBeforeReady = /* @__PURE__ */ __name((err) => {
        if (settled) return;
        settled = true;
        cleanupStartupTimer();
        if (kind === "initial") {
          reject(err);
        } else {
          resolve();
        }
      }, "failBeforeReady");
      const startupError = /* @__PURE__ */ __name((message) => {
        const failures = snapshot.startupFailures;
        return failures && failures.length > 0 ? new ChannelWorkerStartupError(message, {
          workspaceCwd: opts.workspace,
          startupFailures: failures,
          ...snapshot.startupFailuresTruncated ? { startupFailuresTruncated: true } : {}
        }) : new Error(message);
      }, "startupError");
      const failStartupProtocol = /* @__PURE__ */ __name((detail) => {
        if (settled || ready || child !== startedChild) return;
        const error = sanitizeWorkerError(
          `Channel worker startup IPC protocol error: ${detail}`,
          redaction
        );
        snapshot = { ...snapshot, state: "failed", error };
        failBeforeReady(startupError(error));
        terminateBeforeReady();
      }, "failStartupProtocol");
      const acknowledgeStartupReport = /* @__PURE__ */ __name(() => {
        const send = startedChild.send;
        if (!send) {
          failStartupProtocol("acknowledgement is unavailable.");
          return;
        }
        try {
          send.call(
            startedChild,
            { type: "channel_startup_report_ack" },
            (err) => {
              if (err) {
                failStartupProtocol("acknowledgement failed.");
              }
            }
          );
        } catch {
          failStartupProtocol("acknowledgement failed.");
        }
      }, "acknowledgeStartupReport");
      const handleStartupReport = /* @__PURE__ */ __name((message) => {
        if (!isChannelStartupReportMessage(message)) {
          failStartupProtocol("invalid startup report.");
          return;
        }
        if (message.type === "channel_startup_failures_truncated") {
          if (snapshot.startupFailuresTruncated || snapshot.startupFailures?.length !== MAX_CHANNEL_STARTUP_FAILURES) {
            failStartupProtocol("invalid truncation marker.");
            return;
          }
          snapshot = { ...snapshot, startupFailuresTruncated: true };
          acknowledgeStartupReport();
          return;
        }
        if (snapshot.startupFailuresTruncated || (snapshot.startupFailures?.length ?? 0) >= MAX_CHANNEL_STARTUP_FAILURES) {
          failStartupProtocol("too many startup failures.");
          return;
        }
        const safeChannel = sanitizeWorkerDiagnostic(
          message.failure.channel,
          MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH,
          redaction
        ) || "<unnamed>";
        const safeMessage = sanitizeWorkerDiagnostic(
          message.failure.message,
          MAX_CHANNEL_STARTUP_FAILURE_MESSAGE_LENGTH,
          redaction
        ) || "Channel connection failed.";
        const safeCode = message.failure.code ? sanitizeWorkerDiagnostic(
          message.failure.code,
          MAX_CHANNEL_STARTUP_FAILURE_CODE_LENGTH,
          redaction
        ) : void 0;
        const failure = {
          channel: safeChannel,
          phase: "connect",
          ...safeCode ? { code: safeCode } : {},
          message: safeMessage
        };
        snapshot = {
          ...snapshot,
          startupFailures: [...snapshot.startupFailures ?? [], failure]
        };
        acknowledgeStartupReport();
      }, "handleStartupReport");
      const completeReady = /* @__PURE__ */ __name((message) => {
        if (settled || child !== startedChild) return;
        settled = true;
        ready = true;
        cleanupStartupTimer();
        const next = {
          ...snapshot,
          state: "running",
          pid: message.pid ?? startedChild.pid,
          channels: message.channels && message.channels.length > 0 ? [...message.channels] : [...snapshot.channels]
        };
        delete next.error;
        delete next.lastHeartbeatAt;
        delete next.nextRestartAt;
        delete next.staleHeartbeatAt;
        if (message.requestedChannels?.length) {
          next.requestedChannels = [...message.requestedChannels];
        }
        snapshot = next;
        armStaleHeartbeatTimer(startedChild);
        notifyReady(opts.onReady, snapshotCopy());
        resolve();
      }, "completeReady");
      const handleHeartbeat = /* @__PURE__ */ __name((message) => {
        if (!ready || child !== startedChild) return;
        const currentPid = snapshot.pid ?? startedChild.pid;
        if (message.pid !== void 0 && currentPid !== void 0) {
          if (message.pid !== currentPid) return;
        }
        snapshot = {
          ...snapshot,
          lastHeartbeatAt: (/* @__PURE__ */ new Date()).toISOString()
        };
        armStaleHeartbeatTimer(startedChild);
      }, "handleHeartbeat");
      function handleMessage(message) {
        if (child !== startedChild) return;
        if (settleWebhookTask(message)) {
          return;
        }
        if (!ready && isChannelStartupReportType(message)) {
          handleStartupReport(message);
        } else if (!ready && isReadyMessage(message)) {
          completeReady(message);
        } else if (isHeartbeatMessage(message)) {
          handleHeartbeat(message);
        }
      }
      __name(handleMessage, "handleMessage");
      function settleExit(code, signal) {
        if (child !== startedChild) return;
        exitObserved = true;
        cleanupLaunch();
        const state = ready ? "exited" : "failed";
        const message = `Channel worker exited before ready (code=${code ?? "null"}, signal=${signal ?? "null"}).`;
        setExited(
          state,
          code,
          signal,
          snapshot.error ?? (ready ? void 0 : sanitizeWorkerError(message, redaction))
        );
        rejectPendingWebhookTasks(
          "channel_worker_unavailable",
          "Channel worker exited."
        );
        child = void 0;
        if ((ready || kind === "restart") && !stopping) {
          scheduleRestart();
          notifyExit(opts.onExit, snapshotCopy());
        }
        if (!settled) {
          failBeforeReady(startupError(snapshot.error ?? message));
        }
      }
      __name(settleExit, "settleExit");
      function settleError(err) {
        if (child !== startedChild || exitObserved) return;
        if (settled && ready) {
          snapshot = {
            ...snapshot,
            error: sanitizeWorkerError(err.message, redaction)
          };
          startedChild.kill("SIGTERM");
          return;
        }
        snapshot = {
          ...snapshot,
          state: "failed",
          error: sanitizeWorkerError(err.message, redaction)
        };
        terminateBeforeReady();
        if (!settled) {
          failBeforeReady(
            startupError(snapshot.error ?? "Channel worker failed to start.")
          );
        }
      }
      __name(settleError, "settleError");
      startupTimer = setTimeout(() => {
        const timeoutMs = opts.startupTimeoutMs ?? CHANNEL_WORKER_STARTUP_TIMEOUT_MS;
        const error = `Channel worker did not become ready within ${timeoutMs}ms.`;
        snapshot = {
          ...snapshot,
          state: "failed",
          error: sanitizeWorkerError(error, redaction)
        };
        failBeforeReady(startupError(error));
        if (child === startedChild) {
          terminateBeforeReady();
        }
      }, opts.startupTimeoutMs ?? CHANNEL_WORKER_STARTUP_TIMEOUT_MS);
      startupTimer.unref();
      startedChild.on("message", handleMessage);
      startedChild.once("exit", settleExit);
      startedChild.once("error", settleError);
    });
  }, "launch");
  const supervisor = {
    async start() {
      if (disposed) return;
      if (child) {
        if (stopping) {
          throw new ChannelWorkerStopError(
            "Channel worker stop is not yet confirmed."
          );
        }
        return;
      }
      stopping = false;
      clearRestartTimer();
      restartAttemptTimes = [];
      await launch("initial");
    },
    async stop() {
      clearRestartTimer();
      clearStaleHeartbeatTimer();
      rejectPendingWebhookTasks(
        "channel_worker_unavailable",
        "Channel worker stopped."
      );
      if (!child || snapshot.state === "exited" || snapshot.state === "failed" && hasObservedExit(snapshot) || snapshot.state === "stopped") {
        child = void 0;
        snapshot = { ...snapshot, state: "stopped" };
        return;
      }
      const stoppingChild = child;
      const exited = waitForExit(stoppingChild, CHANNEL_WORKER_STOP_GRACE_MS);
      stopping = true;
      stoppingChild.kill("SIGTERM");
      if (!await exited && child === stoppingChild) {
        const killed = waitForExit(stoppingChild, CHANNEL_WORKER_KILL_GRACE_MS);
        stoppingChild.kill("SIGKILL");
        if (!await killed) {
          snapshot = {
            ...snapshot,
            state: "failed",
            error: "Channel worker did not exit after SIGKILL."
          };
          throw new ChannelWorkerStopError();
        }
      }
      child = void 0;
      stopping = false;
      snapshot = { ...snapshot, state: "stopped" };
    },
    async restart() {
      if (disposed) return snapshotCopy();
      restarting ??= (async () => {
        try {
          await supervisor.stop();
          await supervisor.start();
          return snapshotCopy();
        } finally {
          restarting = void 0;
        }
      })();
      return restarting;
    },
    killAllSync() {
      disposed = true;
      rejectPendingWebhookTasks(
        "channel_worker_unavailable",
        "Channel worker stopped."
      );
      if (!child || snapshot.state === "exited" || snapshot.state === "failed" && hasObservedExit(snapshot) || snapshot.state === "stopped") {
        clearRestartTimer();
        clearStaleHeartbeatTimer();
        return;
      }
      const preserveFailure = snapshot.state === "failed" && !hasObservedExit(snapshot);
      clearRestartTimer();
      clearStaleHeartbeatTimer();
      stopping = true;
      child.kill("SIGKILL");
      child = void 0;
      if (!preserveFailure) {
        snapshot = {
          ...snapshot,
          state: "stopped",
          signal: "SIGKILL"
        };
      }
    },
    snapshot() {
      return snapshotCopy();
    },
    async enqueueWebhookTask(task) {
      const startedChild = child;
      if (!startedChild || snapshot.state !== "running") {
        throw new ChannelWebhookEnqueueError(
          "channel_worker_unavailable",
          "Channel worker is not running."
        );
      }
      const send = startedChild.send;
      if (!send) {
        throw new ChannelWebhookEnqueueError(
          "channel_worker_unavailable",
          "Channel worker IPC send failed."
        );
      }
      const message = createChannelWebhookTaskMessage(task);
      return await new Promise((resolve, reject) => {
        const timer = setTimeout(() => {
          pendingWebhookTasks.delete(message.id);
          reject(
            new ChannelWebhookEnqueueError(
              "channel_webhook_enqueue_timeout",
              "Channel webhook task IPC timed out."
            )
          );
        }, CHANNEL_WEBHOOK_TASK_IPC_TIMEOUT_MS);
        timer.unref();
        pendingWebhookTasks.set(message.id, { resolve, reject, timer });
        try {
          send.call(startedChild, message, (err) => {
            if (err) {
              rejectPendingWebhookTask(
                message.id,
                new ChannelWebhookEnqueueError(
                  "channel_worker_unavailable",
                  `Channel worker IPC send failed: ${err.message}`
                )
              );
            }
          });
        } catch (err) {
          rejectPendingWebhookTask(
            message.id,
            new ChannelWebhookEnqueueError(
              "channel_worker_unavailable",
              `Channel worker IPC send failed: ${err instanceof Error ? err.message : String(err)}`
            )
          );
        }
      });
    }
  };
  return supervisor;
}
__name(createChannelWorkerSupervisor, "createChannelWorkerSupervisor");

export {
  ChannelWorkerStopError,
  ChannelWorkerStartupError,
  createChannelWorkerSupervisor
};
