import { ReadableStream } from "node:stream/web";
import { describe, expect, it, vi } from "vitest";
import { z } from "zod";
import { ChatContext, ChatMessage, tool } from "../llm/index.js";
import { initializeLogger } from "../log.js";
import { SynthesizeStream } from "../tts/index.js";
import { Task } from "../utils.js";
import { Agent, AgentTask, _setActivityTaskInfo } from "./agent.js";
import { AgentActivity, agentActivityStorage } from "./agent_activity.js";
import { defaultEndpointingOptions } from "./turn_config/endpointing.js";
import { defaultInterruptionOptions } from "./turn_config/interruption.js";
vi.mock("ofetch", () => ({ ofetch: vi.fn() }));
initializeLogger({ pretty: false, level: "error" });
async function collectReadableStream(stream) {
  const chunks = [];
  for await (const chunk of stream) {
    chunks.push(chunk);
  }
  return chunks;
}
describe("Agent", () => {
  it("should create agent with basic instructions", () => {
    const instructions = "You are a helpful assistant";
    const agent = new Agent({ instructions });
    expect(agent).toBeDefined();
    expect(agent.instructions).toBe(instructions);
  });
  it("should create agent with instructions and tools", () => {
    var _a, _b;
    const instructions = "You are a helpful assistant with tools";
    const mockTool1 = tool({
      name: "getTool1",
      description: "First test tool",
      parameters: z.object({}),
      execute: async () => "tool1 result"
    });
    const mockTool2 = tool({
      name: "getTool2",
      description: "Second test tool",
      parameters: z.object({
        input: z.string().describe("Input parameter")
      }),
      execute: async ({ input }) => `tool2: ${input}`
    });
    const agent = new Agent({
      instructions,
      tools: [mockTool1, mockTool2]
    });
    expect(agent).toBeDefined();
    expect(agent.instructions).toBe(instructions);
    const agentTools = agent.toolCtx.functionTools;
    expect(Object.keys(agentTools)).toHaveLength(2);
    expect(agentTools).toHaveProperty("getTool1");
    expect(agentTools).toHaveProperty("getTool2");
    expect((_a = agentTools.getTool1) == null ? void 0 : _a.description).toBe("First test tool");
    expect((_b = agentTools.getTool2) == null ? void 0 : _b.description).toBe("Second test tool");
  });
  it("toolCtx returns a defensive copy that exposes the same tools", () => {
    const instructions = "You are a helpful assistant";
    const mockTool = tool({
      name: "testTool",
      description: "Test tool",
      parameters: z.object({}),
      execute: async () => "result"
    });
    const agent = new Agent({ instructions, tools: [mockTool] });
    expect(agent.toolCtx).not.toBe(agent.toolCtx);
    expect(agent.toolCtx.getFunctionTool("testTool")).toBe(mockTool);
  });
  describe("create", () => {
    it("preserves constructor options and base Agent default id", () => {
      const mockTool = tool({
        name: "testTool",
        description: "Test tool",
        parameters: z.object({}),
        execute: async () => "result"
      });
      const agent = Agent.create({
        instructions: "factory instructions",
        tools: [mockTool]
      });
      expect(agent).toBeInstanceOf(Agent);
      expect(agent.instructions).toBe("factory instructions");
      expect(agent.id).toBe("default_agent");
      expect(agent.toolCtx.getFunctionTool("testTool")).toBe(mockTool);
    });
    it("passes AgentContext to lifecycle hooks", async () => {
      const calls = [];
      const chatCtx = ChatContext.empty();
      const newMessage = ChatMessage.create({ role: "user", content: ["hello"] });
      const agent = Agent.create({
        id: "factory_agent",
        instructions: "factory instructions",
        minConsecutiveSpeechDelay: 12,
        onEnter: (ctx) => {
          expect(ctx.agent).toBe(agent);
          expect(ctx.id).toBe(agent.id);
          expect(ctx.instructions).toBe(agent.instructions);
          expect(ctx.toolCtx.functionTools).toEqual(agent.toolCtx.functionTools);
          expect(ctx.chatCtx.items).toEqual(agent.chatCtx.items);
          expect(ctx.minConsecutiveSpeechDelay).toBe(agent.minConsecutiveSpeechDelay);
          calls.push("enter");
        },
        onExit: async (ctx) => {
          expect(ctx.agent).toBe(agent);
          calls.push("exit");
        },
        onUserTurnCompleted: (ctx, receivedChatCtx, receivedMessage) => {
          expect(ctx.agent).toBe(agent);
          expect(receivedChatCtx).toBe(chatCtx);
          expect(receivedMessage).toBe(newMessage);
          calls.push("turn");
        }
      });
      await agent.onEnter();
      await agent.onExit();
      await agent.onUserTurnCompleted(chatCtx, newMessage);
      expect(calls).toEqual(["enter", "exit", "turn"]);
    });
    it("adapts stream node hooks between ReadableStream and AsyncIterable", async () => {
      const audioFrame = "audio";
      const agent = Agent.create({
        instructions: "factory instructions",
        async sttNode(ctx, audio2) {
          async function* stream() {
            expect(ctx.agent).toBe(agent);
            const frames = [];
            for await (const frame of audio2) {
              frames.push(frame);
            }
            expect(frames).toEqual([audioFrame]);
            yield "transcript";
          }
          return stream();
        }
      });
      const audio = new ReadableStream({
        start(controller) {
          controller.enqueue(audioFrame);
          controller.close();
        }
      });
      const result = await agent.sttNode(audio, {});
      expect(result).not.toBeNull();
      await expect(collectReadableStream(result)).resolves.toEqual(["transcript"]);
    });
    it("supports async generator stream node hooks", async () => {
      const audioFrame = "audio";
      const outputFrame = "output-audio";
      const agent = Agent.create({
        instructions: "factory instructions",
        async *sttNode(ctx, audio2) {
          expect(ctx.agent).toBe(agent);
          const frames = [];
          for await (const frame of audio2) {
            frames.push(frame);
          }
          expect(frames).toEqual([audioFrame]);
          yield "transcript";
        },
        async *llmNode(ctx, chatCtx, toolCtx) {
          expect(ctx.agent).toBe(agent);
          expect(chatCtx).toBeInstanceOf(ChatContext);
          expect(toolCtx.equals(agent.toolCtx)).toBe(true);
          yield "llm-output";
        },
        async *ttsNode(ctx, text2) {
          expect(ctx.agent).toBe(agent);
          const chunks = [];
          for await (const chunk of text2) {
            chunks.push(chunk);
          }
          expect(chunks).toEqual(["hello"]);
          yield outputFrame;
        },
        async *realtimeAudioOutputNode(ctx, audio2) {
          expect(ctx.agent).toBe(agent);
          const frames = [];
          for await (const frame of audio2) {
            frames.push(frame);
          }
          expect(frames).toEqual([audioFrame]);
          yield outputFrame;
        }
      });
      const audio = new ReadableStream({
        start(controller) {
          controller.enqueue(audioFrame);
          controller.close();
        }
      });
      const text = new ReadableStream({
        start(controller) {
          controller.enqueue("hello");
          controller.close();
        }
      });
      const sttResult = await agent.sttNode(audio, {});
      const llmResult = await agent.llmNode(ChatContext.empty(), agent.toolCtx, {});
      const ttsResult = await agent.ttsNode(text, {});
      const realtimeResult = await agent.realtimeAudioOutputNode(
        new ReadableStream({
          start(controller) {
            controller.enqueue(audioFrame);
            controller.close();
          }
        }),
        {}
      );
      expect(sttResult).not.toBeNull();
      expect(llmResult).not.toBeNull();
      expect(ttsResult).not.toBeNull();
      expect(realtimeResult).not.toBeNull();
      await expect(collectReadableStream(sttResult)).resolves.toEqual(["transcript"]);
      await expect(collectReadableStream(llmResult)).resolves.toEqual(["llm-output"]);
      await expect(collectReadableStream(ttsResult)).resolves.toEqual([outputFrame]);
      await expect(collectReadableStream(realtimeResult)).resolves.toEqual([outputFrame]);
    });
    it("supports stream node hooks that return async iterables", async () => {
      function asyncIterableOf(...items) {
        return {
          async *[Symbol.asyncIterator]() {
            for (const item of items) {
              yield item;
            }
          }
        };
      }
      const audioFrame = "audio";
      const outputFrame = "output-audio";
      const agent = Agent.create({
        instructions: "factory instructions",
        sttNode(ctx) {
          expect(ctx.agent).toBe(agent);
          return asyncIterableOf("transcript");
        },
        llmNode(ctx) {
          expect(ctx.agent).toBe(agent);
          return asyncIterableOf("llm-output");
        },
        ttsNode(ctx) {
          expect(ctx.agent).toBe(agent);
          return asyncIterableOf(outputFrame);
        },
        realtimeAudioOutputNode(ctx) {
          expect(ctx.agent).toBe(agent);
          return asyncIterableOf(outputFrame);
        }
      });
      const sttResult = await agent.sttNode(
        new ReadableStream({
          start(controller) {
            controller.enqueue(audioFrame);
            controller.close();
          }
        }),
        {}
      );
      const llmResult = await agent.llmNode(ChatContext.empty(), agent.toolCtx, {});
      const ttsResult = await agent.ttsNode(
        new ReadableStream({
          start(controller) {
            controller.enqueue("hello");
            controller.close();
          }
        }),
        {}
      );
      const realtimeResult = await agent.realtimeAudioOutputNode(
        new ReadableStream({
          start(controller) {
            controller.enqueue(audioFrame);
            controller.close();
          }
        }),
        {}
      );
      expect(sttResult).not.toBeNull();
      expect(llmResult).not.toBeNull();
      expect(ttsResult).not.toBeNull();
      expect(realtimeResult).not.toBeNull();
      await expect(collectReadableStream(sttResult)).resolves.toEqual(["transcript"]);
      await expect(collectReadableStream(llmResult)).resolves.toEqual(["llm-output"]);
      await expect(collectReadableStream(ttsResult)).resolves.toEqual([outputFrame]);
      await expect(collectReadableStream(realtimeResult)).resolves.toEqual([outputFrame]);
    });
    it("falls back to existing defaults for missing hooks", async () => {
      const audioFrame = "audio";
      const audio = new ReadableStream({
        start(controller) {
          controller.enqueue(audioFrame);
          controller.close();
        }
      });
      const agent = Agent.create({ instructions: "factory instructions" });
      const result = await agent.realtimeAudioOutputNode(audio, {});
      expect(result).toBe(audio);
    });
  });
  describe("AsyncIterable pipeline node inputs", () => {
    it("accepts a plain AsyncIterable into Agent.create stream hooks without getReader crash", async () => {
      const outputFrame = "output-audio";
      const agent = Agent.create({
        instructions: "factory instructions",
        async *ttsNode(ctx, text) {
          expect(ctx.agent).toBe(agent);
          const chunks = [];
          for await (const chunk of text) {
            chunks.push(chunk);
          }
          expect(chunks).toEqual(["hello"]);
          yield outputFrame;
        }
      });
      async function* textInput() {
        yield "hello";
      }
      const result = await agent.ttsNode(textInput(), {});
      expect(result).not.toBeNull();
      await expect(collectReadableStream(result)).resolves.toEqual([outputFrame]);
    });
    it("forwards transformed output through an Agent.create transcriptionNode hook", async () => {
      const agent = Agent.create({
        instructions: "factory instructions",
        async *transcriptionNode(ctx, text) {
          expect(ctx.agent).toBe(agent);
          for await (const chunk of text) {
            yield `${chunk}!`;
          }
        }
      });
      async function* textInput() {
        yield "hello";
        yield "world";
      }
      const result = await agent.transcriptionNode(textInput(), {});
      expect(result).not.toBeNull();
      await expect(collectReadableStream(result)).resolves.toEqual(["hello!", "world!"]);
    });
    it("accepts a plain AsyncIterable into Agent.default.ttsNode", async () => {
      const frame = "frame";
      const agent = new Agent({ instructions: "default instructions" });
      let capturedInput;
      const ttsStream = {
        startTimeOffset: 0,
        updateInputStream(input) {
          capturedInput = input;
        },
        close() {
        },
        async *[Symbol.asyncIterator]() {
          yield { frame, timedTranscripts: [] };
          yield SynthesizeStream.END_OF_STREAM;
        }
      };
      agent._agentActivity = {
        tts: {
          capabilities: { streaming: true },
          stream: () => ttsStream,
          close: async () => {
          }
        },
        agentSession: { connOptions: { ttsConnOptions: {} } }
      };
      async function* textInput() {
        yield "hello";
      }
      const result = await Agent.default.ttsNode(agent, textInput(), {});
      expect(result).not.toBeNull();
      expect(capturedInput).toBeInstanceOf(ReadableStream);
      await expect(collectReadableStream(result)).resolves.toEqual([frame]);
    });
  });
  it("should require AgentTask to run inside task context", async () => {
    class TestTask extends AgentTask {
      constructor() {
        super({ instructions: "test task" });
      }
    }
    const task = new TestTask();
    await expect(task.run()).rejects.toThrow("must be executed inside a Task context");
  });
  it("should require AgentTask to run inside inline task context", async () => {
    class TestTask extends AgentTask {
      constructor() {
        super({ instructions: "test task" });
      }
    }
    const task = new TestTask();
    const wrapper = Task.from(async () => {
      return await task.run();
    });
    await expect(wrapper.result).rejects.toThrow(
      "should only be awaited inside function tools or the onEnter/onExit methods of an Agent"
    );
  });
  it("should allow AgentTask run from inline task context", async () => {
    class TestTask extends AgentTask {
      constructor() {
        super({ instructions: "test task" });
      }
    }
    const task = new TestTask();
    const oldAgent = new Agent({ instructions: "old agent" });
    const mockSession = {
      currentAgent: oldAgent,
      _globalRunState: void 0,
      _updateActivity: async (agent) => {
        if (agent === task) {
          task.complete("ok");
        }
      }
    };
    const mockActivity = {
      agent: oldAgent,
      agentSession: mockSession,
      _onEnterTask: void 0,
      llm: void 0,
      close: async () => {
      }
    };
    const wrapper = Task.from(async () => {
      const currentTask = Task.current();
      if (!currentTask) {
        throw new Error("expected task context");
      }
      _setActivityTaskInfo(currentTask, { inlineTask: true });
      return await agentActivityStorage.run(mockActivity, () => task.run());
    });
    await expect(wrapper.result).resolves.toBe("ok");
  });
  describe("AgentTask.create", () => {
    it("exposes complete on hook context", async () => {
      const task = AgentTask.create({
        instructions: "factory task",
        onEnter: (ctx) => {
          expect(ctx.agent).toBe(task);
          expect(ctx.id).toBe("default_agent");
          expect(ctx.instructions).toBe("factory task");
          ctx.complete("ok");
        }
      });
      const oldAgent = new Agent({ instructions: "old agent" });
      const mockSession = {
        currentAgent: oldAgent,
        _globalRunState: void 0,
        _updateActivity: async (agent) => {
          if (agent === task) {
            await agent.onEnter();
          }
        }
      };
      const mockActivity = {
        agent: oldAgent,
        agentSession: mockSession,
        _onEnterTask: void 0,
        llm: void 0,
        close: async () => {
        }
      };
      const wrapper = Task.from(async () => {
        const currentTask = Task.current();
        if (!currentTask) {
          throw new Error("expected task context");
        }
        _setActivityTaskInfo(currentTask, { inlineTask: true });
        return await agentActivityStorage.run(mockActivity, () => task.run());
      });
      await expect(wrapper.result).resolves.toBe("ok");
    });
    it("adapts stream node hooks between ReadableStream and AsyncIterable", async () => {
      const audioFrame = "audio";
      const task = AgentTask.create({
        instructions: "factory task",
        async sttNode(ctx, audio2) {
          async function* stream() {
            expect(ctx.agent).toBe(task);
            const frames = [];
            for await (const frame of audio2) {
              frames.push(frame);
            }
            expect(frames).toEqual([audioFrame]);
            yield "transcript";
          }
          return stream();
        }
      });
      const audio = new ReadableStream({
        start(controller) {
          controller.enqueue(audioFrame);
          controller.close();
        }
      });
      const result = await task.sttNode(audio, {});
      expect(result).not.toBeNull();
      await expect(collectReadableStream(result)).resolves.toEqual(["transcript"]);
    });
    it("falls back to existing defaults for missing hooks", async () => {
      const audioFrame = "audio";
      const audio = new ReadableStream({
        start(controller) {
          controller.enqueue(audioFrame);
          controller.close();
        }
      });
      const task = AgentTask.create({ instructions: "factory task" });
      const result = await task.realtimeAudioOutputNode(audio, {});
      expect(result).toBe(audio);
    });
  });
  it("should require AgentTask to run inside AgentActivity context", async () => {
    class TestTask extends AgentTask {
      constructor() {
        super({ instructions: "test task" });
      }
    }
    const task = new TestTask();
    const wrapper = Task.from(async () => {
      const currentTask = Task.current();
      if (!currentTask) {
        throw new Error("expected task context");
      }
      _setActivityTaskInfo(currentTask, { inlineTask: true });
      return await task.run();
    });
    await expect(wrapper.result).rejects.toThrow(
      "must be executed inside an AgentActivity context"
    );
  });
  it("should close old activity when current agent changes while AgentTask is pending", async () => {
    class TestTask extends AgentTask {
      constructor() {
        super({ instructions: "test task" });
      }
    }
    const task = new TestTask();
    const oldAgent = new Agent({ instructions: "old agent" });
    const switchedAgent = new Agent({ instructions: "switched agent" });
    const closeOldActivity = vi.fn(async () => {
    });
    const mockSession = {
      currentAgent: oldAgent,
      _globalRunState: void 0,
      _updateActivity: async (agent) => {
        if (agent === task) {
          mockSession.currentAgent = switchedAgent;
          task.complete("ok");
        }
      }
    };
    const mockActivity = {
      agent: oldAgent,
      agentSession: mockSession,
      _onEnterTask: void 0,
      llm: void 0,
      close: closeOldActivity
    };
    const wrapper = Task.from(async () => {
      const currentTask = Task.current();
      if (!currentTask) {
        throw new Error("expected task context");
      }
      _setActivityTaskInfo(currentTask, { inlineTask: true });
      return await agentActivityStorage.run(mockActivity, () => task.run());
    });
    await expect(wrapper.result).resolves.toBe("ok");
    expect(closeOldActivity).toHaveBeenCalledTimes(1);
  });
  describe("Agent constructor option migration", () => {
    it("should set allowInterruptions to false via deprecated constructor field", () => {
      var _a, _b;
      const agent = new Agent({ instructions: "test", allowInterruptions: false });
      expect((_b = (_a = agent.turnHandling) == null ? void 0 : _a.interruption) == null ? void 0 : _b.enabled).toBe(false);
    });
    it("should not set derived properties when no compatibility fields are provided", () => {
      const agent = new Agent({ instructions: "test" });
      expect(agent.turnHandling).toBeUndefined();
    });
    it("should expose minConsecutiveSpeechDelay", () => {
      const agent = new Agent({ instructions: "test", minConsecutiveSpeechDelay: 1.5 });
      expect(agent.minConsecutiveSpeechDelay).toBe(1.5);
    });
    it("should ignore deprecated constructor fields when turnHandling is provided", () => {
      var _a, _b, _c, _d, _e, _f, _g;
      const agent = new Agent({
        instructions: "test",
        turnHandling: {
          endpointing: { minDelay: 999 },
          interruption: {},
          preemptiveGeneration: {},
          turnDetection: "vad"
        },
        allowInterruptions: false
      });
      expect((_b = (_a = agent.turnHandling) == null ? void 0 : _a.endpointing) == null ? void 0 : _b.minDelay).toBe(999);
      expect((_d = (_c = agent.turnHandling) == null ? void 0 : _c.endpointing) == null ? void 0 : _d.maxDelay).toBeUndefined();
      expect((_f = (_e = agent.turnHandling) == null ? void 0 : _e.interruption) == null ? void 0 : _f.enabled).toBeUndefined();
      expect((_g = agent.turnHandling) == null ? void 0 : _g.turnDetection).toBe("vad");
    });
    it("should let turnHandling override deprecated constructor fields on conflicts", () => {
      var _a, _b, _c, _d, _e, _f, _g;
      const agent = new Agent({
        instructions: "test",
        turnHandling: {
          endpointing: { minDelay: 999, maxDelay: 4e3 },
          interruption: { enabled: true },
          preemptiveGeneration: {},
          turnDetection: "vad"
        },
        allowInterruptions: false,
        turnDetection: "stt"
      });
      expect((_b = (_a = agent.turnHandling) == null ? void 0 : _a.endpointing) == null ? void 0 : _b.minDelay).toBe(999);
      expect((_d = (_c = agent.turnHandling) == null ? void 0 : _c.endpointing) == null ? void 0 : _d.maxDelay).toBe(4e3);
      expect((_f = (_e = agent.turnHandling) == null ? void 0 : _e.interruption) == null ? void 0 : _f.enabled).toBe(true);
      expect((_g = agent.turnHandling) == null ? void 0 : _g.turnDetection).toBe("vad");
    });
    it("should set interruptionDetection from turnHandling.interruption.mode", () => {
      var _a, _b;
      const agent = new Agent({
        instructions: "test",
        turnHandling: {
          interruption: { mode: "adaptive" },
          endpointing: {},
          preemptiveGeneration: {},
          turnDetection: void 0
        }
      });
      expect((_b = (_a = agent.turnHandling) == null ? void 0 : _a.interruption) == null ? void 0 : _b.mode).toBe("adaptive");
    });
    it("should let AgentActivity prefer agent-level overrides over session defaults", () => {
      var _a, _b;
      const agent = new Agent({
        instructions: "test",
        turnHandling: {
          endpointing: { minDelay: 111, maxDelay: 222 },
          interruption: { enabled: false },
          preemptiveGeneration: {},
          turnDetection: "manual"
        }
      });
      const session = {
        options: {
          turnHandling: {
            endpointing: defaultEndpointingOptions,
            interruption: defaultInterruptionOptions
          }
        },
        turnDetection: "stt",
        useTtsAlignedTranscript: true,
        vad: void 0,
        stt: void 0,
        llm: void 0,
        tts: void 0,
        interruptionDetection: void 0
      };
      const activity = new AgentActivity(agent, session);
      expect(activity.allowInterruptions).toBe(false);
      expect(activity.turnDetection).toBe("manual");
      expect((_a = activity.turnHandling.endpointing) == null ? void 0 : _a.minDelay).toBe(111);
      expect((_b = activity.turnHandling.endpointing) == null ? void 0 : _b.maxDelay).toBe(222);
    });
    it("should disable adaptive interruption detection in default mode when prerequisites are missing", () => {
      const previousRemoteEotUrl = process.env.LIVEKIT_REMOTE_EOT_URL;
      process.env.LIVEKIT_REMOTE_EOT_URL = "http://localhost:9999";
      try {
        const agent = new Agent({ instructions: "test" });
        const session = {
          options: {
            turnHandling: {
              endpointing: defaultEndpointingOptions,
              interruption: defaultInterruptionOptions
            }
          },
          sessionOptions: {
            turnHandling: {
              endpointing: defaultEndpointingOptions,
              interruption: defaultInterruptionOptions
            }
          },
          turnDetection: "manual",
          useTtsAlignedTranscript: true,
          vad: {},
          stt: {
            capabilities: {
              alignedTranscript: true,
              streaming: true
            }
          },
          llm: void 0,
          tts: void 0,
          interruptionDetection: void 0
        };
        const activity = new AgentActivity(agent, session);
        expect(activity.interruptionDetector).toBeUndefined();
      } finally {
        if (previousRemoteEotUrl === void 0) {
          delete process.env.LIVEKIT_REMOTE_EOT_URL;
        } else {
          process.env.LIVEKIT_REMOTE_EOT_URL = previousRemoteEotUrl;
        }
      }
    });
    it("should warn when session explicitly requests adaptive detection even if agent overrides it", () => {
      const activity = Object.create(AgentActivity.prototype);
      activity.agent = {
        turnHandling: { interruption: { mode: "vad" } },
        turnDetection: void 0
      };
      activity.agentSession = {
        interruptionDetection: "adaptive",
        turnDetection: "manual"
      };
      activity.logger = { warn: vi.fn() };
      expect(activity.resolveInterruptionDetector()).toBeUndefined();
      expect(activity.logger.warn).toHaveBeenCalledWith(
        "interruptionDetection is provided, but it's not compatible with the current configuration and will be disabled"
      );
    });
    it("should disable adaptive interruption detection when interruptions are disabled", () => {
      const previousRemoteEotUrl = process.env.LIVEKIT_REMOTE_EOT_URL;
      process.env.LIVEKIT_REMOTE_EOT_URL = "http://localhost:9999";
      try {
        const activity = Object.create(AgentActivity.prototype);
        activity.agent = {
          turnHandling: {
            interruption: { enabled: false }
          },
          turnDetection: void 0,
          stt: void 0,
          vad: void 0,
          llm: void 0
        };
        activity.agentSession = {
          interruptionDetection: void 0,
          turnDetection: "stt",
          sessionOptions: {
            turnHandling: {
              interruption: defaultInterruptionOptions,
              endpointing: defaultEndpointingOptions
            }
          },
          stt: {
            capabilities: {
              alignedTranscript: true,
              streaming: true
            }
          },
          vad: {},
          llm: void 0
        };
        activity.logger = { warn: vi.fn() };
        expect(activity.resolveInterruptionDetector()).toBeUndefined();
        expect(activity.logger.warn).not.toHaveBeenCalled();
      } finally {
        if (previousRemoteEotUrl === void 0) {
          delete process.env.LIVEKIT_REMOTE_EOT_URL;
        } else {
          process.env.LIVEKIT_REMOTE_EOT_URL = previousRemoteEotUrl;
        }
      }
    });
  });
});
//# sourceMappingURL=agent.test.js.map