"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 end_call_exports = {};
__export(end_call_exports, {
  END_CALL_DESCRIPTION: () => END_CALL_DESCRIPTION,
  createEndCallTool: () => createEndCallTool
});
module.exports = __toCommonJS(end_call_exports);
var import_node_events = require("node:events");
var import_promises = require("node:timers/promises");
var import_job = require("../../job.cjs");
var import_llm = require("../../llm/index.cjs");
var import_log = require("../../log.cjs");
var import_events = require("../../voice/events.cjs");
const END_CALL_REPLY_TIMEOUT = 5e3;
function onceEvent(session, event, options) {
  return (0, import_node_events.once)(session, event, options).then(
    ([payload]) => payload,
    (err) => {
      var _a;
      if ((_a = options == null ? void 0 : options.signal) == null ? void 0 : _a.aborted) return void 0;
      throw err;
    }
  );
}
const END_CALL_DESCRIPTION = `
Ends the current call and disconnects immediately.

Call when:
- The user clearly indicates they are done (e.g., "that's all, bye").

Do not call when:
- The user asks to pause, hold, or transfer.
- Intent is unclear.

This is the final action the agent can take.
Once called, no further interaction is possible with the user.
Don't generate any other text or response when the tool is called.
`;
function createEndCallTool({
  extraDescription = "",
  deleteRoom = true,
  endInstructions = "say goodbye to the user",
  onToolCalled,
  onToolCompleted
} = {}) {
  const delayedSessionShutdown = async (session, signal) => {
    const speech = onceEvent(session, import_events.AgentSessionEventTypes.SpeechCreated, { signal }).then(
      (event) => event == null ? void 0 : event.speechHandle
    );
    const timeout = (0, import_promises.setTimeout)(END_CALL_REPLY_TIMEOUT, "timeout", { signal }).catch(
      () => void 0
    );
    const winner = await Promise.race([speech, timeout]);
    if (signal.aborted) return;
    if (winner === "timeout") {
      (0, import_log.log)().warn("tool reply timed out, shutting down session");
      session.shutdown();
    } else if (winner) {
      await winner.waitForPlayout();
      session.shutdown();
    }
  };
  return import_llm.Toolset.create({
    id: "end_call",
    tools: [
      (0, import_llm.tool)({
        name: "end_call",
        description: `${END_CALL_DESCRIPTION}
${extraDescription}`,
        execute: async (_args, { ctx, abortSignal }) => {
          (0, import_log.log)().debug("end_call tool called");
          const session = ctx.session;
          const llm = session.currentAgent.getActivityOrThrow().llm;
          const controller = new AbortController();
          const signal = abortSignal ? AbortSignal.any([abortSignal, controller.signal]) : controller.signal;
          void onceEvent(session, import_events.AgentSessionEventTypes.Close, { signal }).then((event) => {
            if (!event) return;
            controller.abort();
            const jobCtx = (0, import_job.getJobContext)(false);
            if (!jobCtx) return;
            if (deleteRoom) {
              jobCtx.addShutdownCallback(async () => {
                (0, import_log.log)().info("deleting the room because the user ended the call");
                await jobCtx.deleteRoom();
              });
            }
            jobCtx.shutdown(String(event.reason));
          }).catch((error) => (0, import_log.log)().error({ error }, "error during end call shutdown"));
          ctx.speechHandle.addDoneCallback(() => {
            if (!(llm instanceof import_llm.RealtimeModel) || !llm.capabilities.autoToolReplyGeneration) {
              session.shutdown();
              return;
            }
            void delayedSessionShutdown(session, signal).catch(
              (error) => (0, import_log.log)().error({ error }, "error during delayed session shutdown")
            );
          });
          if (onToolCalled) {
            await onToolCalled({ ctx, arguments: {} });
          }
          const completedEvent = {
            ctx,
            output: endInstructions === null ? void 0 : { type: "output", value: endInstructions }
          };
          if (onToolCompleted) {
            await onToolCompleted(completedEvent);
          }
          return endInstructions ?? void 0;
        }
      })
    ]
  });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  END_CALL_DESCRIPTION,
  createEndCallTool
});
//# sourceMappingURL=end_call.cjs.map