"use strict";
var import_rtc_node = require("@livekit/rtc-node");
var import_vitest = require("vitest");
var import_chat_context = require("../llm/chat_context.cjs");
var import_log = require("../log.cjs");
var import_stt = require("../stt/stt.cjs");
var import_audio_recognition = require("./audio_recognition.cjs");
function makeHooks() {
  return {
    onInterruption: import_vitest.vi.fn(),
    onStartOfSpeech: import_vitest.vi.fn(),
    onVADInferenceDone: import_vitest.vi.fn(),
    onEndOfSpeech: import_vitest.vi.fn(),
    onInterimTranscript: import_vitest.vi.fn(),
    onFinalTranscript: import_vitest.vi.fn(),
    onPreemptiveGeneration: import_vitest.vi.fn(),
    onAgentBackchannelOpportunity: import_vitest.vi.fn(),
    onUserTurnExceeded: import_vitest.vi.fn(),
    retrieveChatCtx: () => import_chat_context.ChatContext.empty(),
    onEndOfTurn: import_vitest.vi.fn(async () => true)
  };
}
function makeRecognition() {
  const opts = {
    recognitionHooks: makeHooks(),
    stt: void 0,
    vad: void 0,
    interruptionDetection: void 0,
    turnDetectionMode: "stt",
    minEndpointingDelay: 0,
    maxEndpointingDelay: 0,
    getLinkedParticipant: () => ({ sid: "p1", identity: "bob", kind: import_rtc_node.ParticipantKind.AGENT })
  };
  const recognition = new import_audio_recognition.AudioRecognition(opts);
  return { recognition, internals: recognition };
}
(0, import_vitest.describe)("AudioRecognition STT end-of-speech VAD reset", () => {
  (0, import_log.initializeLogger)({ pretty: false, level: "silent" });
  (0, import_vitest.it)("flushes the active VAD stream without restarting VAD", async () => {
    var _a;
    const { recognition, internals } = makeRecognition();
    internals.speaking = true;
    internals.vadSpeechStarted = true;
    internals.vad = {};
    const flush = import_vitest.vi.fn();
    const resettableStream = { flush };
    internals.vadStream = resettableStream;
    const resetVad = import_vitest.vi.spyOn(recognition, "resetVad").mockImplementation(() => {
    });
    try {
      await internals.onSTTEvent({ type: import_stt.SpeechEventType.END_OF_SPEECH });
      (0, import_vitest.expect)(flush).toHaveBeenCalledTimes(1);
      (0, import_vitest.expect)(resetVad).not.toHaveBeenCalled();
      (0, import_vitest.expect)(internals.vadStream).toBe(resettableStream);
    } finally {
      await ((_a = internals.bounceEOUTask) == null ? void 0 : _a.cancelAndWait().catch(() => {
      }));
    }
  });
  (0, import_vitest.it)("falls back to restarting VAD when there is no active stream", async () => {
    var _a;
    const { recognition, internals } = makeRecognition();
    internals.speaking = true;
    internals.vadSpeechStarted = true;
    internals.vad = {};
    internals.vadStream = void 0;
    const resetVad = import_vitest.vi.spyOn(recognition, "resetVad").mockImplementation(() => {
    });
    try {
      await internals.onSTTEvent({ type: import_stt.SpeechEventType.END_OF_SPEECH });
      (0, import_vitest.expect)(resetVad).toHaveBeenCalledTimes(1);
    } finally {
      await ((_a = internals.bounceEOUTask) == null ? void 0 : _a.cancelAndWait().catch(() => {
      }));
    }
  });
  (0, import_vitest.it)("preserves the VAD-owned lastSpeakingTime on STT end-of-speech", async () => {
    var _a;
    const { recognition, internals } = makeRecognition();
    internals.vad = {};
    const vadSpeakingTime = 12345;
    internals.lastSpeakingTime = vadSpeakingTime;
    import_vitest.vi.spyOn(recognition, "runEOUDetection").mockImplementation(() => {
    });
    try {
      await internals.onSTTEvent({ type: import_stt.SpeechEventType.END_OF_SPEECH });
      (0, import_vitest.expect)(internals.lastSpeakingTime).toBe(vadSpeakingTime);
    } finally {
      await ((_a = internals.bounceEOUTask) == null ? void 0 : _a.cancelAndWait().catch(() => {
      }));
    }
  });
  (0, import_vitest.it)("stamps lastSpeakingTime on STT end-of-speech when there is no VAD", async () => {
    var _a;
    const { recognition, internals } = makeRecognition();
    internals.vad = void 0;
    internals.lastSpeakingTime = void 0;
    import_vitest.vi.spyOn(recognition, "runEOUDetection").mockImplementation(() => {
    });
    try {
      await internals.onSTTEvent({ type: import_stt.SpeechEventType.END_OF_SPEECH });
      (0, import_vitest.expect)(internals.lastSpeakingTime).toBeTypeOf("number");
    } finally {
      await ((_a = internals.bounceEOUTask) == null ? void 0 : _a.cancelAndWait().catch(() => {
      }));
    }
  });
});
//# sourceMappingURL=audio_recognition_vad_reset.test.cjs.map