"use strict";
var import_rtc_node = require("@livekit/rtc-node");
var import_web = require("node:stream/web");
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_vad = require("../vad.cjs");
var import_audio_recognition = require("./audio_recognition.cjs");
const fastTurnDetector = {
  model: "test-turn-detector",
  provider: "test-provider",
  supportsLanguage: async () => true,
  unlikelyThreshold: async () => void 0,
  predictEndOfTurn: async () => 1
};
class SilentVADStream extends Object {
  updateInputStream() {
  }
  detachInputStream() {
  }
  close() {
  }
  [Symbol.asyncIterator]() {
    return this;
  }
  async next() {
    return { done: true, value: void 0 };
  }
}
class SilentVAD extends import_vad.VAD {
  label = "silent-vad";
  constructor() {
    super({ updateInterval: 1 });
  }
  stream() {
    return new SilentVADStream();
  }
}
function createHooks() {
  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)
  };
}
(0, import_vitest.describe)("AudioRecognition EOU scheduling with STT timestamps", () => {
  (0, import_log.initializeLogger)({ pretty: false, level: "silent" });
  (0, import_vitest.afterEach)(() => {
    import_vitest.vi.useRealTimers();
  });
  async function runTurn(opts) {
    import_vitest.vi.useFakeTimers();
    const hooks = createHooks();
    let sttController;
    const sttNode = async () => new import_web.ReadableStream({
      start(controller) {
        sttController = controller;
      }
    });
    const ar = new import_audio_recognition.AudioRecognition({
      recognitionHooks: hooks,
      stt: sttNode,
      vad: new SilentVAD(),
      turnDetector: fastTurnDetector,
      turnDetectionMode: "vad",
      minEndpointingDelay: 0,
      maxEndpointingDelay: 0,
      sttModel: "stt-model",
      sttProvider: "stt-provider",
      getLinkedParticipant: () => ({ sid: "p1", identity: "bob", kind: import_rtc_node.ParticipantKind.AGENT })
    });
    await ar.start({ inputStartedAt: Date.now() });
    await import_vitest.vi.advanceTimersByTimeAsync(0);
    sttController.enqueue({
      type: import_stt.SpeechEventType.FINAL_TRANSCRIPT,
      alternatives: [
        {
          language: "en",
          text: "okay",
          startTime: 0,
          endTime: opts.sttEndTimeInS,
          confidence: 0.9
        }
      ]
    });
    return { ar, hooks };
  }
  async function closeRecognition(ar) {
    import_vitest.vi.useRealTimers();
    await ar.close();
  }
  (0, import_vitest.it)("commits the user turn promptly when STT endTime maps to the past", async () => {
    const { ar, hooks } = await runTurn({ sttEndTimeInS: 0.5 });
    try {
      await import_vitest.vi.advanceTimersByTimeAsync(2e3);
      (0, import_vitest.expect)(hooks.onEndOfTurn).toHaveBeenCalledTimes(1);
    } finally {
      await closeRecognition(ar);
    }
  });
  (0, import_vitest.it)("does not stall the user turn commit when STT endTime maps to the future", async () => {
    const { ar, hooks } = await runTurn({ sttEndTimeInS: 120 });
    try {
      await import_vitest.vi.advanceTimersByTimeAsync(2e3);
      (0, import_vitest.expect)(hooks.onEndOfTurn).toHaveBeenCalledTimes(1);
    } finally {
      await closeRecognition(ar);
    }
  });
});
//# sourceMappingURL=audio_recognition_eou.test.cjs.map