import { AudioFrame } from "@livekit/rtc-node";
import { ReadableStream } from "node:stream/web";
import { describe, expect, it, vi } from "vitest";
import { initializeLogger } from "../log.js";
import { Agent } from "./agent.js";
import { AgentSession } from "./agent_session.js";
import { AgentSessionEventTypes } from "./events.js";
import { AudioOutput } from "./io.js";
import { FakeLLM } from "./testing/fake_llm.js";
function frame(durationMs = 20, sampleRate = 24e3) {
  const samples = Math.floor(sampleRate * durationMs / 1e3);
  return new AudioFrame(new Int16Array(samples), sampleRate, 1, samples);
}
class InterruptibleOutput extends AudioOutput {
  onFirstFrame;
  started = false;
  constructor() {
    super(24e3);
  }
  async captureFrame(f) {
    var _a;
    await super.captureFrame(f);
    if (!this.started) {
      this.started = true;
      this.onPlaybackStarted(Date.now());
      (_a = this.onFirstFrame) == null ? void 0 : _a.call(this);
    }
  }
  flush() {
    super.flush();
  }
  clearBuffer() {
    this.onPlaybackFinished({ playbackPosition: 0.02, interrupted: true });
  }
}
class FrameAgent extends Agent {
  constructor() {
    super({ instructions: "test" });
  }
  async ttsNode() {
    return new ReadableStream({
      start(controller) {
        for (let i = 0; i < 10; i++) controller.enqueue(frame());
        controller.close();
      }
    });
  }
}
describe("AgentActivity interrupted-speech commit", () => {
  initializeLogger({ pretty: false, level: "silent" });
  it("commits an interrupted reply to chat ctx when no synchronized transcript is available", async () => {
    const session = new AgentSession({
      llm: new FakeLLM([{ input: "hello", content: "A fairly long spoken reply." }])
    });
    const audioOut = new InterruptibleOutput();
    session.output.audio = audioOut;
    audioOut.onFirstFrame = () => session.interrupt({ force: true });
    const assistantMessages = [];
    session.on(AgentSessionEventTypes.ConversationItemAdded, (ev) => {
      if (ev.item.type === "message" && ev.item.role === "assistant") {
        assistantMessages.push({
          content: ev.item.textContent ?? "",
          interrupted: !!ev.item.interrupted
        });
      }
    });
    await session.start({ agent: new FrameAgent() });
    try {
      const handle = session.generateReply({ userInput: "hello" });
      await handle.waitForPlayout();
      await vi.waitFor(() => expect(assistantMessages.length).toBeGreaterThan(0));
      const msg = assistantMessages[0];
      expect(msg.interrupted).toBe(true);
      expect(msg.content.length).toBeGreaterThan(0);
      expect("A fairly long spoken reply.".startsWith(msg.content)).toBe(true);
    } finally {
      await session.close();
    }
  });
});
//# sourceMappingURL=agent_activity_interrupted_commit.test.js.map