"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var console_exports = {};
__export(console_exports, {
  runConsole: () => runConsole
});
module.exports = __toCommonJS(console_exports);
var import_protocol = require("@livekit/protocol");
var import_rtc_node = require("@livekit/rtc-node");
var import_node_url = require("node:url");
var import_generator = require("./generator.cjs");
var import_inference_runner = require("./inference_runner.cjs");
var import_inference_proc_executor = require("./ipc/inference_proc_executor.cjs");
var import_job = require("./job.cjs");
var import_log = require("./log.cjs");
var import_utils = require("./utils.cjs");
var import_console_io = require("./voice/console_io.cjs");
var import_remote_session = require("./voice/remote_session.cjs");
var import_worker = require("./worker.cjs");
const formatErrorMessage = (error) => error instanceof Error ? error.message : String(error);
class ConsoleInferenceExecutor {
  async doInference() {
    throw new Error("no inference runners registered; cannot run local inference");
  }
}
async function loadAgent(agentPath) {
  var _a;
  const module2 = await import((0, import_node_url.pathToFileURL)(agentPath).href);
  const agent = typeof module2.default === "function" || (0, import_generator.isAgent)(module2.default) ? module2.default : (_a = module2.default) == null ? void 0 : _a.default;
  if (agent === void 0 || !(0, import_generator.isAgent)(agent)) {
    throw new Error(`Unable to load agent: missing or invalid default export in ${agentPath}`);
  }
  return agent;
}
async function runConsole({
  agentPath,
  connectAddr,
  record
}) {
  const logger = (0, import_log.log)();
  const sep = connectAddr.lastIndexOf(":");
  if (sep <= 0 || sep === connectAddr.length - 1) {
    throw new Error(`invalid --connect-addr "${connectAddr}", expected host:port`);
  }
  const host = connectAddr.slice(0, sep);
  const portStr = connectAddr.slice(sep + 1);
  const port = Number(portStr);
  if (!/^\d+$/.test(portStr) || port < 1 || port > 65535) {
    throw new Error(`invalid port in --connect-addr "${connectAddr}", expected 1-65535`);
  }
  const agent = await loadAgent(agentPath);
  const prewarm = agent.prewarm ?? import_worker.defaultInitializeProcessFunc;
  const transport = new import_remote_session.TcpSessionTransport(host, port);
  const audioInput = new import_console_io.TcpAudioInput();
  const audioOutput = new import_console_io.TcpAudioOutput(transport);
  const consoleInst = import_console_io.AgentsConsole.getInstance();
  consoleInst.enabled = true;
  consoleInst.record = record;
  consoleInst.transport = transport;
  consoleInst.audioInput = audioInput;
  consoleInst.audioOutput = audioOutput;
  const proc = new import_job.JobProcess();
  await prewarm(proc);
  const info = {
    acceptArguments: { name: "", identity: "console", metadata: "" },
    job: new import_protocol.Job({
      id: (0, import_utils.shortuuid)("console-job-"),
      type: import_protocol.JobType.JT_ROOM,
      room: new import_protocol.Room({ name: "console-room" }),
      enableRecording: record
    }),
    url: "",
    token: "",
    workerId: "console",
    fakeJob: true
  };
  const room = new import_rtc_node.Room();
  const shutdown = new import_utils.Future();
  const onShutdown = () => {
    if (!shutdown.done) shutdown.resolve();
  };
  process.once("SIGINT", onShutdown);
  process.once("SIGTERM", onShutdown);
  logger.info({ host, port }, "starting console session");
  let inferenceProc;
  let ctx;
  try {
    let inferenceExecutor = new ConsoleInferenceExecutor();
    if (Object.keys(import_inference_runner.InferenceRunner.registeredRunners).length > 0) {
      inferenceProc = new import_inference_proc_executor.InferenceProcExecutor({
        runners: import_inference_runner.InferenceRunner.registeredRunners,
        // 5 minutes, matching python: loading model files into the child can
        // be slow on first run.
        initializeTimeout: 5 * 60 * 1e3,
        closeTimeout: 5e3,
        memoryWarnMB: 2e3,
        memoryLimitMB: 0,
        pingInterval: 5e3,
        pingTimeout: 6e4,
        highPingThreshold: 2500
      });
      try {
        await inferenceProc.start();
        await inferenceProc.initialize();
      } catch (error) {
        throw new Error(
          `the inference process failed to start (${formatErrorMessage(error)}); if your agent uses a plugin with local model files (e.g. the livekit turn detector), make sure they are downloaded: npx livekit-agents download-files`
        );
      }
      inferenceExecutor = inferenceProc;
    }
    const jobCtx = new import_job.JobContext(proc, info, room, () => {
    }, onShutdown, inferenceExecutor);
    ctx = jobCtx;
    await (0, import_job.runWithJobContextAsync)(jobCtx, async () => agent.entry(jobCtx));
    await shutdown.await;
  } finally {
    process.off("SIGINT", onShutdown);
    process.off("SIGTERM", onShutdown);
    const guarded = async (step, fn) => {
      try {
        await fn();
      } catch (error) {
        logger.error({ error }, `error in ${step}`);
      }
    };
    const session = ctx == null ? void 0 : ctx._primaryAgentSession;
    if (session) {
      await guarded("AgentSession.close", () => session.close());
    }
    const jobCtx = ctx;
    if (jobCtx) {
      await guarded("ctx._onSessionEnd", () => jobCtx._onSessionEnd());
    }
    await guarded("transport.close", () => transport.close());
    await guarded("room.disconnect", () => room.disconnect());
    if (jobCtx) {
      const results = await Promise.allSettled(jobCtx.shutdownCallbacks.map((cb) => cb()));
      for (const result of results) {
        if (result.status === "rejected") {
          logger.error({ error: result.reason }, "error while running shutdown callback");
        }
      }
    }
    const proc_ = inferenceProc;
    if (proc_) {
      await guarded("inference process close", () => proc_.close());
    }
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  runConsole
});
//# sourceMappingURL=console.cjs.map