{"version":3,"sources":["../../src/workflows/warm_transfer.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { SIPParticipantInfo } from '@livekit/protocol';\nimport { DisconnectReason, ParticipantKind, Room, RoomEvent } from '@livekit/rtc-node';\nimport { AccessToken, RoomServiceClient, SipClient } from 'livekit-server-sdk';\nimport { afterEach, describe, expect, it, vi } from 'vitest';\nimport * as job from '../job.js';\nimport type { JobContext } from '../job.js';\nimport { ChatContext, type FunctionTool } from '../llm/index.js';\nimport { log } from '../log.js';\nimport { AgentTask } from '../voice/agent.js';\nimport { AgentSession } from '../voice/agent_session.js';\nimport { BackgroundAudioPlayer } from '../voice/background_audio.js';\nimport { SpeechHandle } from '../voice/speech_handle.js';\nimport {\n  type WarmTransferResult,\n  createCallerHangupSpeech,\n  createWarmTransferSpeech,\n  createWarmTransferTask,\n  resolveHumanAgentRoomName,\n} from './warm_transfer.js';\n\nafterEach(() => {\n  vi.restoreAllMocks();\n  vi.unstubAllEnvs();\n});\n\nconst createFakeTask = () => {\n  let done = false;\n  const complete = vi.fn(() => {\n    done = true;\n  });\n  const setInputAudioEnabled = vi.fn();\n  const setOutputAudioEnabled = vi.fn();\n  const setOutputTranscriptionEnabled = vi.fn();\n  const task = {\n    get done() {\n      return done;\n    },\n    complete,\n    instructions: '',\n    stt: undefined,\n    vad: undefined,\n    llm: undefined,\n    tts: undefined,\n    toolCtx: { tools: [] },\n    chatCtx: ChatContext.empty(),\n    session: {\n      stt: undefined,\n      vad: undefined,\n      llm: undefined,\n      tts: undefined,\n      turnDetection: undefined,\n      input: {\n        audio: {},\n        audioEnabled: true,\n        setAudioEnabled: setInputAudioEnabled,\n      },\n      output: {\n        audio: {},\n        audioEnabled: true,\n        transcription: {},\n        transcriptionEnabled: true,\n        setAudioEnabled: setOutputAudioEnabled,\n        setTranscriptionEnabled: setOutputTranscriptionEnabled,\n      },\n    },\n  } as unknown as AgentTask<WarmTransferResult>;\n  const create = vi.spyOn(AgentTask, 'create').mockReturnValue(task);\n  return {\n    complete,\n    create,\n    setInputAudioEnabled,\n    setOutputAudioEnabled,\n    setOutputTranscriptionEnabled,\n  };\n};\n\nconst createCallerRoom = (): Room =>\n  ({\n    name: 'caller-room',\n    localParticipant: { identity: 'transfer-agent' },\n    remoteParticipants: new Map([\n      ['caller', { identity: 'caller', kind: ParticipantKind.STANDARD }],\n    ]),\n    on: vi.fn(),\n    off: vi.fn(),\n  }) as unknown as Room;\n\nconst mockDial = (sipParticipant: Promise<unknown> = Promise.resolve({})) => {\n  vi.stubEnv('LIVEKIT_API_KEY', 'api-key');\n  vi.stubEnv('LIVEKIT_API_SECRET', 'api-secret');\n  vi.spyOn(AccessToken.prototype, 'toJwt').mockResolvedValue('token');\n  const connect = vi.spyOn(Room.prototype, 'connect').mockImplementation(async function () {\n    Object.defineProperty(this, 'name', {\n      configurable: true,\n      value: 'caller-room-human-agent',\n    });\n    Object.defineProperty(this, 'isConnected', {\n      configurable: true,\n      get: () => true,\n    });\n  });\n  const disconnect = vi.spyOn(Room.prototype, 'disconnect').mockResolvedValue();\n  vi.spyOn(AgentSession.prototype, 'start').mockResolvedValue();\n  const close = vi.spyOn(AgentSession.prototype, 'close').mockResolvedValue();\n  const shutdown = vi.spyOn(AgentSession.prototype, 'shutdown').mockImplementation(() => {});\n  const createSipParticipant = vi\n    .spyOn(SipClient.prototype, 'createSipParticipant')\n    .mockReturnValue(sipParticipant as never);\n  vi.spyOn(BackgroundAudioPlayer.prototype, 'close').mockResolvedValue();\n  return { close, connect, createSipParticipant, disconnect, shutdown };\n};\n\nconst setupTransfer = (abortSignal: AbortSignal) => {\n  const callerRoom = createCallerRoom();\n  vi.spyOn(job, 'getJobContext').mockReturnValue({\n    room: callerRoom,\n    info: {\n      url: 'ws://localhost:7880',\n      apiKey: 'api-key',\n      apiSecret: 'api-secret',\n    },\n  } as JobContext);\n  const fakeTask = createFakeTask();\n  createWarmTransferTask({\n    abortSignal,\n    sipCallTo: '+15551234567',\n    sipTrunkId: 'ST_dummy',\n    holdAudio: null,\n  });\n  return { callerRoom, ...fakeTask };\n};\n\ndescribe('resolveHumanAgentRoomName', () => {\n  it('defaults to `<callerRoom>-human-agent` when no override is given', () => {\n    expect(resolveHumanAgentRoomName('call-123')).toBe('call-123-human-agent');\n  });\n\n  it('returns the override when provided', () => {\n    expect(resolveHumanAgentRoomName('call-123', 'consult-abc')).toBe('consult-abc');\n  });\n\n  it('rejects an override equal to the caller room name', () => {\n    expect(() => resolveHumanAgentRoomName('call-123', 'call-123')).toThrow(\n      /must differ from the caller room name/,\n    );\n  });\n});\n\ndescribe('createWarmTransferTask', () => {\n  it('rejects an empty roomName', () => {\n    expect(() =>\n      createWarmTransferTask({\n        sipCallTo: '+15551234567',\n        sipTrunkId: 'ST_dummy',\n        roomName: '',\n      }),\n    ).toThrow(/must not be empty/);\n  });\n\n  it('aborts before dialing when the signal is already aborted', async () => {\n    const controller = new AbortController();\n    const reason = new Error('application shutdown');\n    controller.abort(reason);\n    const { close, createSipParticipant, disconnect } = mockDial();\n    const { complete, create } = setupTransfer(controller.signal);\n\n    await create.mock.calls[0]![0].onEnter!({} as never);\n\n    expect(complete).toHaveBeenCalledWith(reason);\n    expect(createSipParticipant).not.toHaveBeenCalled();\n    expect(disconnect).not.toHaveBeenCalled();\n    expect(close).not.toHaveBeenCalled();\n  });\n\n  it('aborts a pending dial with the signal reason', async () => {\n    const controller = new AbortController();\n    const reason = new Error('application shutdown');\n    const dial = new Promise<never>(() => {});\n    const { close, createSipParticipant, disconnect, shutdown } = mockDial(dial);\n    const { complete, create } = setupTransfer(controller.signal);\n\n    const entering = create.mock.calls[0]![0].onEnter!({} as never);\n    await vi.waitFor(() => expect(createSipParticipant).toHaveBeenCalled());\n    controller.abort(reason);\n    await entering;\n\n    expect(complete).toHaveBeenCalledWith(reason);\n    expect(disconnect).toHaveBeenCalledOnce();\n    expect(shutdown).toHaveBeenCalledWith({ drain: false });\n    expect(close).not.toHaveBeenCalled();\n  });\n\n  it('does not block cancellation on transfer session teardown', async () => {\n    const controller = new AbortController();\n    const reason = new Error('application shutdown');\n    const dial = new Promise<never>(() => {});\n    const { close, createSipParticipant, disconnect, shutdown } = mockDial(dial);\n    close.mockReturnValue(new Promise<void>(() => {}));\n    const { complete, create } = setupTransfer(controller.signal);\n\n    const entering = create.mock.calls[0]![0].onEnter!({} as never);\n    await vi.waitFor(() => expect(createSipParticipant).toHaveBeenCalled());\n    controller.abort(reason);\n    await vi.waitFor(() => expect(complete).toHaveBeenCalledWith(reason));\n\n    const outcome = await Promise.race([\n      entering.then(() => 'completed' as const),\n      new Promise<'timed out'>((resolve) => {\n        setTimeout(() => resolve('timed out'), 100);\n      }),\n    ]);\n\n    expect(outcome).toBe('completed');\n    expect(shutdown).toHaveBeenCalledWith({ drain: false });\n    expect(close).not.toHaveBeenCalled();\n    expect(disconnect).toHaveBeenCalledOnce();\n    expect(shutdown.mock.invocationCallOrder[0]).toBeLessThan(\n      disconnect.mock.invocationCallOrder[0]!,\n    );\n  });\n\n  it('keeps caller I/O disabled until cancellation cleanup exits the task', async () => {\n    const controller = new AbortController();\n    const reason = new Error('application shutdown');\n    const dial = new Promise<never>(() => {});\n    let finishDisconnect!: () => void;\n    const disconnecting = new Promise<void>((resolve) => {\n      finishDisconnect = resolve;\n    });\n    const { createSipParticipant, disconnect } = mockDial(dial);\n    disconnect.mockReturnValue(disconnecting);\n    const {\n      complete,\n      create,\n      setInputAudioEnabled,\n      setOutputAudioEnabled,\n      setOutputTranscriptionEnabled,\n    } = setupTransfer(controller.signal);\n    const options = create.mock.calls[0]![0];\n\n    const entering = options.onEnter!({} as never);\n    await vi.waitFor(() => expect(createSipParticipant).toHaveBeenCalled());\n    controller.abort(reason);\n    await vi.waitFor(() => expect(complete).toHaveBeenCalledWith(reason));\n\n    const ioStateBeforeExit = [\n      setInputAudioEnabled.mock.lastCall?.[0],\n      setOutputAudioEnabled.mock.lastCall?.[0],\n      setOutputTranscriptionEnabled.mock.lastCall?.[0],\n    ];\n    finishDisconnect();\n    await entering;\n    await options.onExit!({} as never);\n\n    expect(ioStateBeforeExit).toEqual([false, false, false]);\n    expect(setInputAudioEnabled).toHaveBeenLastCalledWith(true);\n    expect(setOutputAudioEnabled).toHaveBeenLastCalledWith(true);\n    expect(setOutputTranscriptionEnabled).toHaveBeenLastCalledWith(true);\n  });\n\n  it('aborts an active consultation with the signal reason', async () => {\n    const controller = new AbortController();\n    const reason = new Error('consult deadline expired');\n    const { shutdown } = mockDial();\n    const { complete, create } = setupTransfer(controller.signal);\n\n    await create.mock.calls[0]![0].onEnter!({} as never);\n    controller.abort(reason);\n\n    expect(complete).toHaveBeenCalledWith(reason);\n    expect(shutdown).toHaveBeenCalledOnce();\n  });\n\n  it('removes the abort listener when the framework exits the task', async () => {\n    const controller = new AbortController();\n    const addEventListener = vi.spyOn(controller.signal, 'addEventListener');\n    const removeEventListener = vi.spyOn(controller.signal, 'removeEventListener');\n    mockDial();\n    const { create } = setupTransfer(controller.signal);\n\n    const options = create.mock.calls[0]![0];\n    await options.onEnter!({} as never);\n    const listener = addEventListener.mock.calls.find(([event]) => event === 'abort')?.[1];\n    expect(listener).toBeDefined();\n    expect(options.onExit).toBeDefined();\n    await options.onExit!({} as never);\n\n    expect(removeEventListener).toHaveBeenCalledWith('abort', listener);\n  });\n\n  it.each(['completes', 'fails', 'times out'] as const)(\n    'waits until caller-hangup notice playout %s before exiting and shutting down an answered agent',\n    async (outcome) => {\n      const controller = new AbortController();\n      const playoutTimeoutController = new AbortController();\n      const removalTimeoutController = new AbortController();\n      const timeout = vi\n        .spyOn(AbortSignal, 'timeout')\n        .mockReturnValueOnce(playoutTimeoutController.signal)\n        .mockReturnValueOnce(removalTimeoutController.signal);\n      let completePlayout!: () => void;\n      let failPlayout!: (error: Error) => void;\n      const playout = new Promise<void>((resolve, reject) => {\n        completePlayout = resolve;\n        failPlayout = reject;\n      });\n      const waitForPlayout = vi.fn().mockReturnValue(playout);\n      vi.spyOn(AgentSession.prototype, 'interrupt').mockReturnValue({} as never);\n      vi.spyOn(AgentSession.prototype, 'generateReply').mockReturnValue({\n        waitForPlayout,\n      } as never);\n      let finishRemoval!: () => void;\n      const removal = new Promise<void>((resolve) => {\n        finishRemoval = resolve;\n      });\n      const removeParticipant = vi\n        .spyOn(RoomServiceClient.prototype, 'removeParticipant')\n        .mockReturnValue(removal as never);\n      const { shutdown } = mockDial();\n      const { callerRoom, create } = setupTransfer(controller.signal);\n\n      const options = create.mock.calls[0]![0];\n      await options.onEnter!({} as never);\n      const onCallerLeft = vi\n        .mocked(callerRoom.on)\n        .mock.calls.find(([event]) => event === RoomEvent.ParticipantDisconnected)?.[1];\n      expect(onCallerLeft).toBeDefined();\n      (onCallerLeft as (participant: { identity: string; kind: ParticipantKind }) => void)({\n        identity: 'caller',\n        kind: ParticipantKind.STANDARD,\n      });\n\n      await vi.waitFor(() => expect(waitForPlayout).toHaveBeenCalledOnce());\n      expect(shutdown).not.toHaveBeenCalled();\n      let exitFinished = false;\n      const exiting = Promise.resolve(options.onExit!({} as never)).then(() => {\n        exitFinished = true;\n      });\n      await Promise.resolve();\n      expect(exitFinished).toBe(false);\n\n      if (outcome === 'completes') {\n        completePlayout();\n      } else if (outcome === 'fails') {\n        failPlayout(new Error('playout failed'));\n      } else {\n        expect(timeout).toHaveBeenCalledWith(30_000);\n        playoutTimeoutController.abort();\n      }\n\n      await vi.waitFor(\n        () =>\n          expect(removeParticipant).toHaveBeenCalledWith(\n            'caller-room-human-agent',\n            'human-agent-sip',\n          ),\n        { timeout: 200 },\n      );\n      expect(exitFinished).toBe(false);\n      expect(shutdown).not.toHaveBeenCalled();\n      finishRemoval();\n      await vi.waitFor(() => expect(shutdown).toHaveBeenCalledOnce());\n      await exiting;\n      expect(exitFinished).toBe(true);\n    },\n  );\n\n  it('stops waiting when removing the human agent after caller hangup times out', async () => {\n    const controller = new AbortController();\n    const playoutTimeoutController = new AbortController();\n    const removalTimeoutController = new AbortController();\n    const timeout = vi\n      .spyOn(AbortSignal, 'timeout')\n      .mockReturnValueOnce(playoutTimeoutController.signal)\n      .mockReturnValueOnce(removalTimeoutController.signal);\n    vi.spyOn(AgentSession.prototype, 'interrupt').mockReturnValue({} as never);\n    vi.spyOn(AgentSession.prototype, 'generateReply').mockReturnValue({\n      waitForPlayout: vi.fn().mockResolvedValue(undefined),\n    } as never);\n    const removeParticipant = vi\n      .spyOn(RoomServiceClient.prototype, 'removeParticipant')\n      .mockReturnValue(new Promise<never>(() => {}) as never);\n    const { shutdown } = mockDial();\n    const {\n      callerRoom,\n      create,\n      setInputAudioEnabled,\n      setOutputAudioEnabled,\n      setOutputTranscriptionEnabled,\n    } = setupTransfer(controller.signal);\n\n    const options = create.mock.calls[0]![0];\n    await options.onEnter!({} as never);\n    const onCallerLeft = vi\n      .mocked(callerRoom.on)\n      .mock.calls.find(([event]) => event === RoomEvent.ParticipantDisconnected)?.[1];\n    expect(onCallerLeft).toBeDefined();\n    (onCallerLeft as (participant: { identity: string; kind: ParticipantKind }) => void)({\n      identity: 'caller',\n      kind: ParticipantKind.STANDARD,\n    });\n\n    let exitFinished = false;\n    const exiting = Promise.resolve(options.onExit!({} as never)).then(() => {\n      exitFinished = true;\n    });\n    await vi.waitFor(() => expect(removeParticipant).toHaveBeenCalledOnce());\n    expect(timeout).toHaveBeenNthCalledWith(1, 30_000);\n    await vi.waitFor(() => expect(timeout).toHaveBeenNthCalledWith(2, 10_000), { timeout: 200 });\n    expect(exitFinished).toBe(false);\n    expect(shutdown).not.toHaveBeenCalled();\n\n    removalTimeoutController.abort();\n    await exiting;\n\n    expect(shutdown).toHaveBeenCalledOnce();\n    expect(setInputAudioEnabled).toHaveBeenLastCalledWith(true);\n    expect(setOutputAudioEnabled).toHaveBeenLastCalledWith(true);\n    expect(setOutputTranscriptionEnabled).toHaveBeenLastCalledWith(true);\n  });\n\n  it('lets a successful participant move win over an abort', async () => {\n    const controller = new AbortController();\n    mockDial();\n    let finishMove!: () => void;\n    const move = new Promise<void>((resolve) => {\n      finishMove = resolve;\n    });\n    const moveParticipant = vi\n      .spyOn(RoomServiceClient.prototype, 'moveParticipant')\n      .mockReturnValue(move as never);\n    const { complete, create } = setupTransfer(controller.signal);\n\n    const options = create.mock.calls[0]![0];\n    await options.onEnter!({} as never);\n    const connect = (options.tools as FunctionTool[]).find(\n      (entry) => entry.name === 'connect_to_caller',\n    )!;\n    const merging = connect.execute({}, {} as never);\n    await vi.waitFor(() => expect(moveParticipant).toHaveBeenCalled());\n\n    controller.abort(new Error('application shutdown'));\n    expect(complete).not.toHaveBeenCalled();\n    finishMove();\n    await merging;\n\n    expect(complete).toHaveBeenCalledWith({ humanAgentIdentity: 'human-agent-sip' });\n  });\n\n  it('uses the abort reason when the concurrent participant move fails', async () => {\n    const controller = new AbortController();\n    const reason = new Error('application shutdown');\n    mockDial();\n    let failMove!: (error: Error) => void;\n    const move = new Promise<void>((_resolve, reject) => {\n      failMove = reject;\n    });\n    const moveParticipant = vi\n      .spyOn(RoomServiceClient.prototype, 'moveParticipant')\n      .mockReturnValue(move as never);\n    const { complete, create } = setupTransfer(controller.signal);\n\n    const options = create.mock.calls[0]![0];\n    await options.onEnter!({} as never);\n    const connect = (options.tools as FunctionTool[]).find(\n      (entry) => entry.name === 'connect_to_caller',\n    )!;\n    const merging = connect.execute({}, {} as never);\n    await vi.waitFor(() => expect(moveParticipant).toHaveBeenCalled());\n\n    controller.abort(reason);\n    failMove(new Error('move failed'));\n    await merging;\n\n    expect(complete).toHaveBeenCalledWith(reason);\n  });\n\n  it('observes aborts after a participant move fails', async () => {\n    const controller = new AbortController();\n    const reason = new Error('application shutdown');\n    mockDial();\n    vi.spyOn(RoomServiceClient.prototype, 'moveParticipant').mockRejectedValue(\n      new Error('move failed'),\n    );\n    const { complete, create } = setupTransfer(controller.signal);\n\n    const options = create.mock.calls[0]![0];\n    await options.onEnter!({} as never);\n    const connect = (options.tools as FunctionTool[]).find(\n      (entry) => entry.name === 'connect_to_caller',\n    )!;\n\n    await expect(connect.execute({}, {} as never)).rejects.toThrow('move failed');\n    controller.abort(reason);\n\n    expect(complete).toHaveBeenCalledWith(reason);\n  });\n\n  it.each(['before', 'after'] as const)(\n    'observes human agent room closure %s a participant move failure',\n    async (timing) => {\n      const controller = new AbortController();\n      const warn = vi.spyOn(log(), 'warn').mockImplementation(() => undefined);\n      const { connect: connectRoom } = mockDial();\n      let failMove!: (error: Error) => void;\n      const move = new Promise<void>((_resolve, reject) => {\n        failMove = reject;\n      });\n      const moveParticipant = vi\n        .spyOn(RoomServiceClient.prototype, 'moveParticipant')\n        .mockReturnValue(move as never);\n      const { complete, create } = setupTransfer(controller.signal);\n\n      const options = create.mock.calls[0]![0];\n      await options.onEnter!({} as never);\n      const connect = (options.tools as FunctionTool[]).find(\n        (entry) => entry.name === 'connect_to_caller',\n      )!;\n      const humanAgentRoom = connectRoom.mock.instances[0]!;\n      const isConnected = vi.spyOn(humanAgentRoom, 'isConnected', 'get').mockReturnValue(true);\n\n      const merging = connect.execute({}, {} as never);\n      await vi.waitFor(() => expect(moveParticipant).toHaveBeenCalled());\n      if (timing === 'before') {\n        isConnected.mockReturnValue(false);\n        humanAgentRoom.emit(RoomEvent.Disconnected, DisconnectReason.CLIENT_INITIATED);\n      }\n\n      failMove(new Error('move failed'));\n      await expect(merging).rejects.toThrow('move failed');\n      if (timing === 'after') {\n        expect(complete).not.toHaveBeenCalled();\n        isConnected.mockReturnValue(false);\n        humanAgentRoom.emit(RoomEvent.Disconnected, DisconnectReason.CLIENT_INITIATED);\n      }\n\n      const expectedReason =\n        timing === 'before' ? DisconnectReason.UNKNOWN_REASON : DisconnectReason.CLIENT_INITIATED;\n      expect(warn).toHaveBeenCalledWith(\n        { reason: expectedReason },\n        'human agent room disconnected before transfer completed',\n      );\n      expect(complete).toHaveBeenCalledWith(\n        expect.objectContaining({\n          message: `Transfer failed: the human agent room disconnected before the transfer completed (reason: ${expectedReason}). The caller has not been connected to a human agent.`,\n        }),\n      );\n    },\n  );\n\n  it('starts greeting speech only after the outbound SIP call answers', async () => {\n    vi.stubEnv('LIVEKIT_API_KEY', 'api-key');\n    vi.stubEnv('LIVEKIT_API_SECRET', 'api-secret');\n    let resolveAnswer!: (participant: SIPParticipantInfo) => void;\n    const answer = new Promise<SIPParticipantInfo>((resolve) => {\n      resolveAnswer = resolve;\n    });\n    const createSipParticipant = vi\n      .spyOn(SipClient.prototype, 'createSipParticipant')\n      .mockReturnValue(answer);\n    vi.spyOn(AccessToken.prototype, 'toJwt').mockResolvedValue('token');\n    vi.spyOn(Room.prototype, 'connect').mockResolvedValue();\n    vi.spyOn(AgentSession.prototype, 'start').mockResolvedValue();\n\n    const greetingSpeech = vi.fn(() => completedSpeechHandle());\n    const callerRoom = {\n      name: 'caller-room',\n      localParticipant: { identity: 'transfer-agent' },\n      remoteParticipants: new Map([\n        ['caller', { identity: 'caller', kind: ParticipantKind.STANDARD }],\n      ]),\n      on: vi.fn(),\n      off: vi.fn(),\n    } as unknown as Room;\n    const callerSession = {\n      input: { audioEnabled: true, audio: null },\n      output: {\n        audioEnabled: true,\n        transcriptionEnabled: true,\n        audio: null,\n        transcription: null,\n      },\n      vad: undefined,\n      llm: undefined,\n      stt: undefined,\n      tts: undefined,\n      turnDetection: undefined,\n    } as unknown as AgentSession;\n    const task = createWarmTransferTask({\n      sipCallTo: '+15551234567',\n      sipTrunkId: 'ST_dummy',\n      holdAudio: null,\n      greetingSpeech,\n    });\n    task._agentActivity = { agentSession: callerSession } as never;\n    const jobContext = {\n      room: callerRoom,\n      info: { url: 'wss://example.livekit.cloud' },\n    } as JobContext;\n\n    const onEnter = job.runWithJobContextAsync(jobContext, () => task.onEnter());\n    await vi.waitFor(() => expect(createSipParticipant).toHaveBeenCalledOnce());\n\n    expect(greetingSpeech).not.toHaveBeenCalled();\n\n    resolveAnswer(new SIPParticipantInfo());\n    await onEnter;\n\n    expect(greetingSpeech).toHaveBeenCalledOnce();\n    expect(createSipParticipant).toHaveBeenCalledWith(\n      'ST_dummy',\n      '+15551234567',\n      'caller-room-human-agent',\n      expect.objectContaining({ waitUntilAnswered: true }),\n      undefined,\n    );\n  });\n});\n\nfunction completedSpeechHandle(): SpeechHandle {\n  const handle = SpeechHandle.create();\n  handle._markDone();\n  return handle;\n}\n\nfunction createSession() {\n  const sayHandle = completedSpeechHandle();\n  const generatedHandle = completedSpeechHandle();\n  const say = vi.fn(() => sayHandle);\n  const generateReply = vi.fn(() => generatedHandle);\n  const session = { say, generateReply } as unknown as AgentSession;\n\n  return { session, say, sayHandle, generateReply, generatedHandle };\n}\n\ndescribe('createWarmTransferSpeech', () => {\n  it('does nothing when no speech is configured', () => {\n    const { session, say, generateReply } = createSession();\n\n    expect(createWarmTransferSpeech(session, undefined)).toBeUndefined();\n    expect(say).not.toHaveBeenCalled();\n    expect(generateReply).not.toHaveBeenCalled();\n  });\n\n  it('speaks literal text with default say options', () => {\n    const { session, say, sayHandle, generateReply } = createSession();\n\n    expect(\n      createWarmTransferSpeech(session, 'Hello, I am calling about a customer transfer.'),\n    ).toBe(sayHandle);\n    expect(say).toHaveBeenCalledWith('Hello, I am calling about a customer transfer.', undefined);\n    expect(generateReply).not.toHaveBeenCalled();\n  });\n\n  it('uses a lazy factory to create any speech handle', () => {\n    const { session, say, generateReply } = createSession();\n    const customHandle = completedSpeechHandle();\n    const factory = vi.fn(() => customHandle);\n\n    expect(createWarmTransferSpeech(session, factory)).toBe(customHandle);\n    expect(factory).toHaveBeenCalledWith(session);\n    expect(say).not.toHaveBeenCalled();\n    expect(generateReply).not.toHaveBeenCalled();\n  });\n});\n\ndescribe('createCallerHangupSpeech', () => {\n  it('speaks literal text without generating a reply', () => {\n    const { session, say, sayHandle, generateReply } = createSession();\n\n    expect(\n      createCallerHangupSpeech(session, 'The caller disconnected. Hanging up now.', undefined),\n    ).toBe(sayHandle);\n    expect(say).toHaveBeenCalledWith('The caller disconnected. Hanging up now.', {\n      allowInterruptions: false,\n      addToChatCtx: false,\n    });\n    expect(generateReply).not.toHaveBeenCalled();\n  });\n\n  it('preserves the deprecated generated-reply path when no speech is configured', () => {\n    const { session, say, generateReply, generatedHandle } = createSession();\n\n    expect(\n      createCallerHangupSpeech(session, undefined, 'Generate a short caller hangup message.'),\n    ).toBe(generatedHandle);\n    expect(generateReply).toHaveBeenCalledWith({\n      instructions: 'Generate a short caller hangup message.',\n      allowInterruptions: false,\n      toolChoice: 'none',\n    });\n    expect(say).not.toHaveBeenCalled();\n  });\n});\n"],"mappings":"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","names":[]}