{"version":3,"sources":["../src/lib/useMicrophoneStream.ts","../src/lib/useMicrophone.ts","../src/lib/convertFrequencyScale.ts","../src/lib/generateEmptyFft.ts","../src/lib/useSoundPlayer.ts","../src/utils/loadAudioWorklet.ts","../src/lib/useVoiceClient.ts","../src/lib/VoiceProvider.tsx","../src/lib/noop.ts","../src/lib/useCallDuration.ts","../src/lib/useMessages.ts","../src/utils/index.ts","../src/lib/useToolStatus.ts","../src/lib/errors.ts","../src/lib/messages.ts","../src/lib/audio-message.ts","../src/models/audio.ts","../src/models/llm.ts","../src/models/messages.ts","../src/models/ttsService.ts"],"sourcesContent":["// cspell:ignore dataavailable\nimport { checkForAudioTracks } from 'hume';\nimport { useCallback, useRef, useState } from 'react';\n\ntype PermissionStatus = 'prompt' | 'granted' | 'denied';\n\nconst getAudioStream = async (\n  audioConstraints: MediaTrackConstraints,\n): Promise<MediaStream> => {\n  return navigator.mediaDevices.getUserMedia({\n    audio: {\n      ...audioConstraints,\n      echoCancellation: audioConstraints.echoCancellation ?? true,\n      noiseSuppression: audioConstraints.noiseSuppression ?? true,\n      autoGainControl: audioConstraints.autoGainControl ?? true,\n      deviceId: audioConstraints.deviceId,\n    },\n    video: false,\n  });\n};\n\nexport const useMicrophoneStream = () => {\n  const [permission, setPermission] = useState<PermissionStatus>('prompt');\n  const currentStream = useRef<MediaStream | null>(null);\n\n  const getStream = useCallback(\n    async (audioConstraints: MediaTrackConstraints) => {\n      let stream: MediaStream | null = null;\n\n      try {\n        stream = await getAudioStream(audioConstraints);\n      } catch (e) {\n        if (\n          e instanceof DOMException &&\n          'name' in e &&\n          e.name === 'NotAllowedError'\n        ) {\n          setPermission('denied');\n        }\n        throw e;\n      }\n\n      setPermission('granted');\n\n      checkForAudioTracks(stream);\n\n      currentStream.current = stream;\n\n      return stream;\n    },\n    [],\n  );\n\n  const stopStream = useCallback(() => {\n    if (currentStream.current) {\n      currentStream.current.getTracks().forEach((track) => track.stop());\n      currentStream.current = null;\n    }\n  }, []);\n\n  return {\n    getStream,\n    stopStream,\n    permission,\n  };\n};\n","// cspell:ignore dataavailable\nimport type { MimeType } from 'hume';\nimport { getBrowserSupportedMimeType } from 'hume';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { convertLinearFrequenciesToBark } from './convertFrequencyScale';\nimport { generateEmptyFft } from './generateEmptyFft';\nimport type { MicErrorReason } from './VoiceProvider';\n\nexport type MicrophoneProps = {\n  onAudioCaptured: (b: ArrayBuffer) => void;\n  onStartRecording?: () => void;\n  onStopRecording?: () => void;\n  onError: (message: string, reason: MicErrorReason) => void;\n};\n\nexport const useMicrophone = (props: MicrophoneProps) => {\n  const { onAudioCaptured, onError } = props;\n  const [isMuted, setIsMuted] = useState(false);\n  const isMutedRef = useRef(isMuted);\n  const currentStream = useRef<MediaStream | null>(null);\n\n  const [fft, setFft] = useState<number[]>(generateEmptyFft());\n  const currentAnalyzer = useRef<AnalyserNode | null>(null);\n  const fftAnimationId = useRef<number | null>(null);\n  const analyzerSource = useRef<MediaStreamAudioSourceNode | null>(null);\n\n  const mimeTypeRef = useRef<MimeType | null>(null);\n\n  const audioContext = useRef<AudioContext | null>(null);\n\n  const recorder = useRef<MediaRecorder | null>(null);\n\n  const sendAudio = useRef(onAudioCaptured);\n  sendAudio.current = onAudioCaptured;\n\n  const dataHandler = useCallback((event: BlobEvent) => {\n    const blob = event.data;\n\n    blob\n      .arrayBuffer()\n      .then((buffer) => {\n        if (buffer.byteLength > 0) {\n          sendAudio.current?.(buffer);\n        }\n      })\n      .catch((err) => {\n        console.log(err);\n      });\n  }, []);\n\n  const startFftAnalyzer = useCallback((stream: MediaStream) => {\n    if (!audioContext.current) {\n      return;\n    }\n\n    const source = audioContext.current.createMediaStreamSource(stream);\n    analyzerSource.current = source;\n    currentAnalyzer.current = audioContext.current.createAnalyser();\n    currentAnalyzer.current.fftSize = 2048;\n    const bufferLength = currentAnalyzer.current.frequencyBinCount;\n    const dataArray = new Uint8Array(bufferLength);\n    source.connect(currentAnalyzer.current);\n    const draw = () => {\n      if (!currentAnalyzer.current || !audioContext.current) {\n        return;\n      }\n\n      currentAnalyzer.current.getByteFrequencyData(dataArray);\n\n      const sampleRate = audioContext.current.sampleRate;\n\n      const barkFrequencies = convertLinearFrequenciesToBark(\n        dataArray,\n        sampleRate,\n      );\n\n      setFft(barkFrequencies);\n      fftAnimationId.current = requestAnimationFrame(draw);\n    };\n    draw();\n  }, []);\n\n  const start = useCallback(\n    (stream: MediaStream) => {\n      if (!stream) {\n        throw new Error('No stream connected');\n      }\n\n      if (fftAnimationId.current) {\n        cancelAnimationFrame(fftAnimationId.current);\n      }\n\n      currentStream.current = stream;\n\n      const context = new AudioContext();\n      audioContext.current = context;\n\n      try {\n        startFftAnalyzer(stream);\n      } catch (e: unknown) {\n        const message = e instanceof Error ? e.message : 'Unknown error';\n        console.error(`Failed to start mic analyzer: ${message}`);\n      }\n      const mimeType = mimeTypeRef.current;\n      if (!mimeType) {\n        throw new Error('No MimeType specified');\n      }\n\n      recorder.current = new MediaRecorder(stream, {\n        mimeType,\n      });\n      recorder.current.addEventListener('dataavailable', dataHandler);\n      recorder.current.start(100);\n    },\n    [dataHandler, startFftAnalyzer],\n  );\n\n  const stop = useCallback(async () => {\n    if (analyzerSource.current) {\n      analyzerSource.current.disconnect();\n      analyzerSource.current = null;\n    }\n\n    if (currentAnalyzer.current) {\n      if (fftAnimationId.current) {\n        cancelAnimationFrame(fftAnimationId.current);\n      }\n      fftAnimationId.current = null;\n      currentAnalyzer.current = null;\n    }\n\n    if (audioContext.current) {\n      await audioContext.current\n        .close()\n        .then(() => {\n          audioContext.current = null;\n        })\n        .catch(() => {\n          // .close() rejects if the audio context is already closed.\n          // Therefore, we just need to catch the error, but we don't need to\n          // do anything with it.\n          return null;\n        });\n    }\n\n    recorder.current?.stop();\n    recorder.current?.removeEventListener('dataavailable', dataHandler);\n    recorder.current = null;\n    currentStream.current?.getTracks().forEach((track) => track.stop());\n\n    setIsMuted(false);\n  }, [dataHandler]);\n\n  const stopMicWithRetries = async (maxAttempts = 3, delayMs = 500) => {\n    for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n      try {\n        await stop();\n        return;\n      } catch (e) {\n        if (attempt < maxAttempts) {\n          await new Promise((res) => setTimeout(res, delayMs));\n        } else {\n          const message = e instanceof Error ? e.message : 'Unknown error';\n          onError?.(\n            `Failed to stop mic after ${maxAttempts} attempts: ${message}`,\n            'mic_closure_failure',\n          );\n        }\n      }\n    }\n  };\n\n  const mute = useCallback(() => {\n    if (currentAnalyzer.current) {\n      setFft(generateEmptyFft());\n    }\n\n    currentStream.current?.getTracks().forEach((track) => {\n      track.enabled = false;\n    });\n\n    isMutedRef.current = true;\n    setIsMuted(true);\n  }, []);\n\n  const unmute = useCallback(() => {\n    currentStream.current?.getTracks().forEach((track) => {\n      track.enabled = true;\n    });\n\n    isMutedRef.current = false;\n    setIsMuted(false);\n  }, [currentStream]);\n\n  useEffect(() => {\n    return () => {\n      try {\n        recorder.current?.stop();\n        recorder.current?.removeEventListener('dataavailable', dataHandler);\n\n        if (currentAnalyzer.current) {\n          analyzerSource.current?.disconnect();\n          if (fftAnimationId.current) {\n            cancelAnimationFrame(fftAnimationId.current);\n          }\n          fftAnimationId.current = null;\n          currentAnalyzer.current = null;\n        }\n\n        currentStream.current?.getTracks().forEach((track) => track.stop());\n        currentStream.current = null;\n      } catch (e) {\n        console.log(e);\n        void true;\n      }\n    };\n  }, [dataHandler, currentStream]);\n\n  useEffect(() => {\n    const mimeTypeResult = getBrowserSupportedMimeType();\n    if (mimeTypeResult.success) {\n      mimeTypeRef.current = mimeTypeResult.mimeType;\n    } else {\n      onError(mimeTypeResult.error.message, 'mime_types_not_supported');\n    }\n  }, [onError]);\n\n  return {\n    start,\n    stop: stopMicWithRetries,\n    mute,\n    unmute,\n    isMuted,\n    fft,\n  };\n};\n","// This function converts linear-scaled frequency decibels from an AnalyserNode's frequncy data to Bark scale [https://en.wikipedia.org/wiki/Bark_scale]\n// This implementation uses a simple approach of mapping indices in the linear-scaled array to the closest\n// Bark scale center frequency and is not intended to be an accurate representation, but rather \"close-enough\" for visualization purposes\nconst barkCenterFrequencies = [\n  50, 150, 250, 350, 450, 570, 700, 840, 1000, 1170, 1370, 1600, 1850, 2150,\n  2500, 2900, 3400, 4000, 4800, 5800, 7000, 8500, 10500, 13500,\n]; // Center frequency value in Hz\n\n// Min/max values from https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteFrequencyData\nconst minValue = 0;\nconst maxValue = 255;\n\nexport function convertLinearFrequenciesToBark(\n  linearData: Uint8Array,\n  sampleRate: number,\n): number[] {\n  const maxFrequency = sampleRate / 2;\n  const frequencyResolution = maxFrequency / linearData.length;\n\n  const barkFrequencies = barkCenterFrequencies.map((barkFreq) => {\n    const linearDataIndex = Math.round(barkFreq / frequencyResolution);\n    if (linearDataIndex >= 0 && linearDataIndex < linearData.length) {\n      return (\n        (((linearData[linearDataIndex] ?? 0) - minValue) /\n          (maxValue - minValue)) *\n        2\n      );\n    } else {\n      return 0;\n    }\n  });\n\n  return barkFrequencies;\n}\n","export function generateEmptyFft(): number[] {\n  return Array.from({ length: 24 }).map(() => 0);\n}\n","import { convertBase64ToBlob } from 'hume';\nimport { useCallback, useRef, useState } from 'react';\nimport z from 'zod';\n\nimport { convertLinearFrequenciesToBark } from './convertFrequencyScale';\nimport { generateEmptyFft } from './generateEmptyFft';\nimport type { AudioPlayerErrorReason } from './VoiceProvider';\nimport type { AudioOutputMessage } from '../models/messages';\nimport { loadAudioWorklet } from '../utils/loadAudioWorklet';\n\nexport const useSoundPlayer = (props: {\n  enableAudioWorklet: boolean;\n  onError: (message: string, reason: AudioPlayerErrorReason) => void;\n  onPlayAudio: (id: string) => void;\n  onStopAudio: (id: string) => void;\n}) => {\n  const [isPlaying, setIsPlaying] = useState(false);\n  const [isAudioMuted, setIsAudioMuted] = useState(false);\n  const [volume, setVolumeState] = useState<number>(1.0);\n  const [fft, setFft] = useState<number[]>(generateEmptyFft());\n\n  const audioContext = useRef<AudioContext | null>(null);\n  const analyserNode = useRef<AnalyserNode | null>(null);\n  const gainNode = useRef<GainNode | null>(null);\n  const workletNode = useRef<AudioWorkletNode | null>(null);\n  const isInitialized = useRef(false);\n\n  const isProcessing = useRef(false);\n  const frequencyDataIntervalId = useRef<number | null>(null);\n\n  const onPlayAudio = useRef<typeof props.onPlayAudio>(props.onPlayAudio);\n  onPlayAudio.current = props.onPlayAudio;\n\n  const onStopAudio = useRef<typeof props.onStopAudio>(props.onStopAudio);\n  onStopAudio.current = props.onStopAudio;\n\n  const onError = useRef<typeof props.onError>(props.onError);\n  onError.current = props.onError;\n\n  const isWorkletActive = useRef(false);\n\n  // chunkBufferQueues and lastQueuedChunk are used to make sure that\n  // we don't play chunks out of order. chunkBufferQueues is NOT the\n  // audio playback queue.\n  const chunkBufferQueues = useRef<\n    Record<string, Array<AudioBuffer | undefined>>\n  >({});\n  const lastQueuedChunk = useRef<{ id: string; index: number } | null>(null);\n\n  /**\n   * Only for non-AudioWorklet mode.\n   * In non-AudioWorklet mode, audio clips are managed and played sequentially.\n   * When the current audio clip finishes, the next clip in the queue is played automatically.\n   * In AudioWorklet mode, audio processing and playback are handled by the worklet itself.\n   * In non-AudioWorklet, we must track the currently playing audio buffer\n   * in order to stop it when a new clip is added or when playback is manually stopped by the user.\n   */\n  const clipQueue = useRef<\n    Array<{\n      id: string;\n      buffer: AudioBuffer;\n      index: number;\n    }>\n  >([]);\n  const [queueLength, setQueueLength] = useState(0);\n  const currentlyPlayingAudioBuffer = useRef<AudioBufferSourceNode | null>(\n    null,\n  );\n\n  /**\n   * Only for non-AudioWorklet mode.\n   * This function is called when the current audio clip ends.\n   * It will play the next clip in the queue if there is one.\n   */\n  const playNextClip = useCallback(() => {\n    if (clipQueue.current.length === 0 || isProcessing.current) {\n      setQueueLength(0);\n      return;\n    }\n\n    if (analyserNode.current === null || audioContext.current === null) {\n      onError.current(\n        'Audio player is not initialized',\n        'audio_player_initialization_failure',\n      );\n      return;\n    }\n\n    const nextClip = clipQueue.current.shift();\n    setQueueLength(clipQueue.current.length);\n\n    if (!nextClip) return;\n\n    isProcessing.current = true;\n    setIsPlaying(true);\n\n    const bufferSource = audioContext.current.createBufferSource();\n\n    bufferSource.buffer = nextClip.buffer;\n\n    bufferSource.connect(analyserNode.current);\n\n    currentlyPlayingAudioBuffer.current = bufferSource;\n\n    const updateFrequencyData = () => {\n      try {\n        const bufferSampleRate = bufferSource.buffer?.sampleRate;\n\n        if (!analyserNode.current || typeof bufferSampleRate === 'undefined')\n          return;\n\n        const dataArray = new Uint8Array(\n          analyserNode.current.frequencyBinCount,\n        ); // frequencyBinCount is 1/2 of fftSize\n        analyserNode.current.getByteFrequencyData(dataArray); // Using getByteFrequencyData for performance\n\n        const barkFrequencies = convertLinearFrequenciesToBark(\n          dataArray,\n          bufferSampleRate,\n        );\n        setFft(() => barkFrequencies);\n      } catch (e) {\n        setFft(generateEmptyFft());\n      }\n    };\n\n    frequencyDataIntervalId.current = window.setInterval(\n      updateFrequencyData,\n      5,\n    );\n\n    bufferSource.start(0);\n    if (nextClip.index === 0) {\n      onPlayAudio.current(nextClip.id);\n    }\n\n    bufferSource.onended = () => {\n      if (frequencyDataIntervalId.current) {\n        clearInterval(frequencyDataIntervalId.current);\n        frequencyDataIntervalId.current = null;\n      }\n      setFft(generateEmptyFft());\n      bufferSource.disconnect();\n      isProcessing.current = false;\n      setIsPlaying(false);\n      onStopAudio.current(nextClip.id);\n      currentlyPlayingAudioBuffer.current = null;\n      playNextClip();\n    };\n  }, []);\n\n  const initPlayer = useCallback(\n    async (speakerDeviceId?: string) => {\n      isWorkletActive.current = true;\n\n      try {\n        const initAudioContext = new AudioContext();\n        audioContext.current = initAudioContext;\n\n        // Set the speaker device if specified and supported\n        if (speakerDeviceId && 'setSinkId' in initAudioContext) {\n          try {\n            // TypeScript doesn't recognize setSinkId on AudioContext yet, so we need to cast\n            await (\n              initAudioContext as AudioContext & {\n                setSinkId: (deviceId: string) => Promise<void>;\n              }\n            ).setSinkId(speakerDeviceId);\n          } catch (e) {\n            onError.current(\n              `Failed to set speaker device: ${e instanceof Error ? e.message : 'Unknown error'}`,\n              'audio_player_initialization_failure',\n            );\n            // Continue initialization even if setSinkId fails\n          }\n        }\n\n        // Use AnalyserNode to get fft frequency data for visualizations\n        const analyser = initAudioContext.createAnalyser();\n        // Use GainNode to adjust volume\n        const gain = initAudioContext.createGain();\n\n        analyser.fftSize = 2048; // Must be a power of 2\n        analyser.connect(gain);\n        gain.connect(initAudioContext.destination);\n\n        analyserNode.current = analyser;\n        gainNode.current = gain;\n\n        if (props.enableAudioWorklet) {\n          const isWorkletLoaded = await loadAudioWorklet(initAudioContext);\n          if (!isWorkletLoaded) {\n            onError.current(\n              'Failed to load audio worklet',\n              'audio_worklet_load_failure',\n            );\n            return;\n          }\n\n          const worklet = new AudioWorkletNode(\n            initAudioContext,\n            'audio-processor',\n          );\n          worklet.connect(analyser);\n          workletNode.current = worklet;\n\n          worklet.port.onmessage = (e: MessageEvent) => {\n            const playingEvent = z\n              .object({\n                type: z.literal('start_clip'),\n                id: z.string(),\n                index: z.number(),\n              })\n              .safeParse(e.data);\n\n            if (playingEvent.success) {\n              if (playingEvent.data.index === 0) {\n                onPlayAudio.current(playingEvent.data.id);\n              }\n              setIsPlaying(true);\n            }\n\n            const endedEvent = z\n              .object({ type: z.literal('ended') })\n              .safeParse(e.data);\n            if (endedEvent.success) {\n              setIsPlaying(false);\n              onStopAudio.current('stream');\n            }\n\n            const queueLengthEvent = z\n              .object({ type: z.literal('queueLength'), length: z.number() })\n              .safeParse(e.data);\n            if (queueLengthEvent.success) {\n              if (queueLengthEvent.data.length === 0) {\n                setIsPlaying(false);\n              }\n              setQueueLength(queueLengthEvent.data.length);\n            }\n\n            const closedEvent = z\n              .object({ type: z.literal('worklet_closed') })\n              .safeParse(e.data);\n            if (closedEvent.success) {\n              isWorkletActive.current = false;\n            }\n          };\n\n          frequencyDataIntervalId.current = window.setInterval(() => {\n            const dataArray = new Uint8Array(analyser.frequencyBinCount);\n            analyser.getByteFrequencyData(dataArray);\n\n            const barkFrequencies = convertLinearFrequenciesToBark(\n              dataArray,\n              initAudioContext.sampleRate,\n            );\n            setFft(() => barkFrequencies);\n          }, 5);\n          isInitialized.current = true;\n        } else {\n          isInitialized.current = true;\n        }\n      } catch (e) {\n        onError.current(\n          'Failed to initialize audio player',\n          'audio_player_initialization_failure',\n        );\n      }\n    },\n    [props.enableAudioWorklet],\n  );\n\n  const convertToAudioBuffer = useCallback(\n    async (message: AudioOutputMessage) => {\n      if (!isInitialized.current || !audioContext.current) {\n        onError.current(\n          'Audio player has not been initialized',\n          'audio_player_not_initialized',\n        );\n        return;\n      }\n      const blob = convertBase64ToBlob(message.data);\n      const arrayBuffer = await blob.arrayBuffer();\n      const audioBuffer =\n        await audioContext.current.decodeAudioData(arrayBuffer);\n      return audioBuffer;\n    },\n    [],\n  );\n\n  const getNextAudioBuffers = useCallback(\n    (message: AudioOutputMessage, audioBuffer: AudioBuffer) => {\n      //1. Add the current buffer to the queue\n      if (!chunkBufferQueues.current[message.id]) {\n        chunkBufferQueues.current[message.id] = [];\n      }\n      const queueForCurrMessage = chunkBufferQueues.current[message.id] || [];\n      queueForCurrMessage[message.index] = audioBuffer;\n\n      // 2. Now collect buffers that are ready to be played\n      const lastId = lastQueuedChunk.current?.id;\n      const buffers: Array<{ id: string; index: number; buffer: AudioBuffer }> =\n        [];\n\n      // If the current message ID is different from the last one that was added\n      // to the queue, that means that we're playing a new message now, so the first chunk\n      // we play needs to be at index 0.\n      if (message.id !== lastId) {\n        if (queueForCurrMessage[0]) {\n          lastQueuedChunk.current = { id: message.id, index: 0 };\n          buffers.push({\n            id: message.id,\n            index: 0,\n            buffer: queueForCurrMessage[0],\n          });\n          // Every time we add a buffer to the buffers array, we set the current index to undefined.\n          // This is so that we don't try to add the same buffer to the buffers array again the next\n          // time we call this function.\n          queueForCurrMessage[0] = undefined;\n        } else {\n          // If the current index is not 0, that means the chunks came out of order,\n          // so we return an empty array instead of returning anything to be added to the queue.\n          return [];\n        }\n      }\n\n      // Drain the queue - basically if any chunks were received out of order previously,\n      // and they're now ready to be played because the earlier chunks\n      // have been received, we can add them to the buffers array.\n      let nextIdx = (lastQueuedChunk.current?.index || 0) + 1;\n      let nextBuf = queueForCurrMessage[nextIdx];\n      while (nextBuf) {\n        buffers.push({ index: nextIdx, buffer: nextBuf, id: message.id });\n        // As above re: setting queueForCurrMessage[nextIdx] to undefined\n        queueForCurrMessage[nextIdx] = undefined;\n        lastQueuedChunk.current = { id: message.id, index: nextIdx };\n        nextIdx += 1;\n        nextBuf = queueForCurrMessage[nextIdx];\n      }\n\n      return buffers;\n    },\n    [],\n  );\n\n  const addToQueue = useCallback(\n    async (message: AudioOutputMessage) => {\n      if (!isInitialized.current || !audioContext.current) {\n        onError.current(\n          'Audio player has not been initialized',\n          'audio_player_not_initialized',\n        );\n        return;\n      }\n\n      const audioBuffer = await convertToAudioBuffer(message);\n      if (!audioBuffer) {\n        onError.current(\n          'Failed to convert data to audio buffer',\n          'malformed_audio',\n        );\n        return;\n      }\n\n      // Because converting the data to an audi obuffer is async, chunks that are\n      // only a few ms apart can end up converting out of order. So we need this\n      // getNextAudioBuffers function to make sure that we're playing the chunks\n      // in the correct order.\n      const playableBuffers = getNextAudioBuffers(message, audioBuffer);\n      if (playableBuffers.length === 0) {\n        return;\n      }\n\n      try {\n        // Loop through the buffers and add them to the playback queue one at a time\n        for (const nextAudioBufferToPlay of playableBuffers) {\n          if (props.enableAudioWorklet) {\n            // AudioWorklet mode\n            const pcmData = nextAudioBufferToPlay.buffer.getChannelData(0);\n            workletNode.current?.port.postMessage({\n              type: 'audio',\n              data: pcmData,\n              id: nextAudioBufferToPlay.id,\n              index: nextAudioBufferToPlay.index,\n            });\n          } else if (!props.enableAudioWorklet) {\n            // Non-AudioWorklet mode\n            clipQueue.current.push({\n              id: nextAudioBufferToPlay.id,\n              buffer: nextAudioBufferToPlay.buffer,\n              index: nextAudioBufferToPlay.index,\n            });\n            setQueueLength(clipQueue.current.length);\n            // playNextClip will iterate the clipQueue upon finishing\n            // the playback of the current audio clip,\n            // so we can just call playNextClip here if it's the only one in the queue\n            if (clipQueue.current.length === 1) {\n              playNextClip();\n            }\n          }\n        }\n      } catch (e) {\n        const eMessage = e instanceof Error ? e.message : 'Unknown error';\n        onError.current(\n          `Failed to add clip to queue: ${eMessage}`,\n          'malformed_audio',\n        );\n      }\n    },\n    [\n      convertToAudioBuffer,\n      getNextAudioBuffers,\n      playNextClip,\n      props.enableAudioWorklet,\n    ],\n  );\n\n  const stopAll = useCallback(async () => {\n    isInitialized.current = false;\n    isProcessing.current = false;\n    setIsPlaying(false);\n    setIsAudioMuted(false);\n    setVolumeState(1.0);\n    setFft(generateEmptyFft());\n\n    chunkBufferQueues.current = {};\n    lastQueuedChunk.current = null;\n\n    if (frequencyDataIntervalId.current) {\n      window.clearInterval(frequencyDataIntervalId.current);\n    }\n\n    if (props.enableAudioWorklet) {\n      // AudioWorklet mode\n      workletNode.current?.port.postMessage({ type: 'fadeAndClear' });\n      workletNode.current?.port.postMessage({ type: 'end' });\n\n      // We use this loop to make sure the worklet has been closed before we consider\n      // the player to be successfully stopped. The audio worklet asynchronously emits\n      // the 'worklet_closed' message in order to confirm that it has been closed successfully.\n      // If you close the worklet before the fade-out, the user may hear a small audio\n      // artifact when the call ends.\n      // (Reference the `_fadeOutDurationMs` constant in `audio-worklet.js`\n      // to see how long it takes for the worklet to close - the current default is 300ms.)\n      let closed = 0;\n      while (closed < 5) {\n        if (isWorkletActive.current === false) {\n          break;\n        }\n        closed += 1;\n        await new Promise((resolve) => setTimeout(resolve, 100));\n      }\n      // In the unlikely event that the worklet is still active after 500ms,\n      // something went wrong in the worklet code, and the worklet failed to close.\n      // So we should reset isWorkletActive to false anyway.\n      isWorkletActive.current = false;\n\n      if (workletNode.current) {\n        workletNode.current.port.close();\n        workletNode.current.disconnect();\n        workletNode.current = null;\n      }\n    } else if (!props.enableAudioWorklet) {\n      // Non-AudioWorklet mode\n      if (currentlyPlayingAudioBuffer.current) {\n        currentlyPlayingAudioBuffer.current.disconnect();\n        currentlyPlayingAudioBuffer.current = null;\n      }\n\n      clipQueue.current = [];\n      setQueueLength(0);\n    }\n\n    if (analyserNode.current) {\n      analyserNode.current.disconnect();\n      analyserNode.current = null;\n    }\n\n    if (audioContext.current) {\n      await audioContext.current\n        .close()\n        .then(() => {\n          audioContext.current = null;\n        })\n        .catch(() => {\n          // .close() rejects if the audio context is already closed.\n          // Therefore, we just need to catch the error, but we don't need to\n          // do anything with it.\n          return null;\n        });\n    }\n  }, [props.enableAudioWorklet]);\n\n  const stopAllWithRetries = async (maxAttempts = 3, delayMs = 500) => {\n    for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n      try {\n        await stopAll();\n        return;\n      } catch (e) {\n        if (attempt < maxAttempts) {\n          await new Promise((res) => setTimeout(res, delayMs));\n        } else {\n          const message = e instanceof Error ? e.message : 'Unknown error';\n          onError.current?.(\n            `Failed to stop audio player after ${maxAttempts} attempts: ${message}`,\n            'audio_player_closure_failure',\n          );\n        }\n      }\n    }\n  };\n\n  const clearQueue = useCallback(() => {\n    if (props.enableAudioWorklet) {\n      // AudioWorklet mode\n      workletNode.current?.port.postMessage({\n        type: 'fadeAndClear',\n      });\n    } else if (!props.enableAudioWorklet) {\n      // Non-AudioWorklet mode\n      if (currentlyPlayingAudioBuffer.current) {\n        currentlyPlayingAudioBuffer.current.stop();\n        currentlyPlayingAudioBuffer.current = null;\n      }\n      clipQueue.current = [];\n      setQueueLength(0);\n    }\n\n    isProcessing.current = false;\n    setIsPlaying(false);\n    setFft(generateEmptyFft());\n  }, [props.enableAudioWorklet]);\n\n  const setVolume = useCallback(\n    (newLevel: number) => {\n      const clampedLevel = Math.max(0, Math.min(newLevel, 1.0));\n      setVolumeState(clampedLevel);\n      if (gainNode.current && audioContext.current && !isAudioMuted) {\n        gainNode.current.gain.setValueAtTime(\n          clampedLevel,\n          audioContext.current.currentTime,\n        );\n      }\n    },\n    [isAudioMuted],\n  );\n\n  const muteAudio = useCallback(() => {\n    if (gainNode.current && audioContext.current) {\n      gainNode.current.gain.setValueAtTime(0, audioContext.current.currentTime);\n      setIsAudioMuted(true);\n    }\n  }, []);\n\n  const unmuteAudio = useCallback(() => {\n    if (gainNode.current && audioContext.current) {\n      gainNode.current.gain.setValueAtTime(\n        volume,\n        audioContext.current.currentTime,\n      );\n      setIsAudioMuted(false);\n    }\n  }, [volume]);\n\n  return {\n    addToQueue,\n    fft,\n    initPlayer,\n    isPlaying,\n    isAudioMuted,\n    muteAudio,\n    unmuteAudio,\n    stopAll: stopAllWithRetries,\n    clearQueue,\n    volume,\n    setVolume,\n    queueLength,\n  };\n};\n","export const loadAudioWorklet = async (\n  ctx: AudioContext,\n  attemptNumber = 1,\n): Promise<boolean> => {\n  return ctx.audioWorklet\n    .addModule(\n      `https://storage.googleapis.com/evi-react-sdk-assets/audio-worklet-20250702.js`,\n    )\n    .then(() => {\n      return true;\n    })\n    .catch(() => {\n      if (attemptNumber >= 10) {\n        return false;\n      }\n      return loadAudioWorklet(ctx, attemptNumber + 1);\n    });\n};\n","import { Hume, HumeClient } from 'hume';\nimport { useCallback, useRef, useState } from 'react';\nimport { type Simplify } from 'type-fest';\n\nimport { type AuthStrategy } from './auth';\nimport type {\n  AudioOutputMessage,\n  JSONMessage,\n  ToolCall,\n} from '../models/messages';\n\nconst isNever = (_n: never) => {\n  return;\n};\n\nexport type SocketConfig = {\n  auth: AuthStrategy;\n  hostname?: string;\n} & Hume.empathicVoice.chat.Chat.ConnectArgs;\n\nexport enum VoiceReadyState {\n  IDLE = 'idle',\n  CONNECTING = 'connecting',\n  OPEN = 'open',\n  CLOSED = 'closed',\n}\ntype SessionSettingsOnConnect = Omit<\n  Hume.empathicVoice.SessionSettings,\n  'builtinTools' | 'tools' | 'metadata' | 'type'\n>;\n/**\n * Extracts session settings that can be sent as query params when the websocket connects.\n * Matches ConnectSessionSettings in the TypeScript SDK (systemPrompt, voiceId, context, etc. are supported).\n *\n * `tools`, `builtinTools`, and `metadata` are not yet supported in the connect query string.\n */\nconst getSessionSettingsOnConnect = (\n  sessionSettings?: Hume.empathicVoice.SessionSettings,\n): SessionSettingsOnConnect | undefined => {\n  if (!sessionSettings) {\n    return undefined;\n  }\n\n  const { builtinTools, tools, metadata, type, ...onConnect } = sessionSettings;\n  return onConnect;\n};\n\nexport type ToolCallHandler = (\n  // message will always be a tool call message where toolType === 'function'\n  message: Simplify<\n    ToolCall & {\n      // caveat: this doesn't actually do what it appears to, since ToolType is\n      // exported as both an interface and a value, this ends up being a constant\n      // that doesn't share an type identity with the actual ToolType enum\n      toolType: typeof Hume.empathicVoice.ToolType.Function;\n    }\n  >,\n  send: {\n    success: (content: unknown) => Hume.empathicVoice.ToolResponseMessage;\n    error: (e: {\n      error: string;\n      code: string;\n      level: string;\n      content: string;\n    }) => Hume.empathicVoice.ToolErrorMessage;\n  },\n) => Promise<\n  Hume.empathicVoice.ToolResponseMessage | Hume.empathicVoice.ToolErrorMessage\n>;\n\nexport const useVoiceClient = (props: {\n  onAudioMessage?: (message: AudioOutputMessage) => void;\n  onMessage?: (message: JSONMessage) => void;\n  onSessionSettings?: (\n    sessionSettings: Hume.empathicVoice.SessionSettings,\n  ) => void;\n  onToolCall?: ToolCallHandler;\n  onToolCallError?: (message: string, error?: Error) => void;\n  onClientError?: (message: string, error?: Error) => void;\n  onOpen?: () => void;\n  onClose?: Hume.empathicVoice.chat.ChatSocket.EventHandlers['close'];\n}) => {\n  const connectAbortController = useRef<AbortController | null>(null);\n\n  const client = useRef<Hume.empathicVoice.chat.ChatSocket | null>(null);\n\n  const [readyState, setReadyState] = useState<VoiceReadyState>(\n    VoiceReadyState.IDLE,\n  );\n\n  // this pattern might look hacky but it allows us to use the latest props\n  // in callbacks set up inside useEffect without re-rendering the useEffect\n  const onAudioMessage = useRef<typeof props.onAudioMessage>(\n    props.onAudioMessage,\n  );\n  onAudioMessage.current = props.onAudioMessage;\n\n  const onMessage = useRef<typeof props.onMessage>(props.onMessage);\n  onMessage.current = props.onMessage;\n\n  const onSessionSettings = useRef<typeof props.onSessionSettings>(\n    props.onSessionSettings,\n  );\n  onSessionSettings.current = props.onSessionSettings;\n\n  const onToolCall = useRef<typeof props.onToolCall>(props.onToolCall);\n  onToolCall.current = props.onToolCall;\n\n  const onClientError = useRef<typeof props.onClientError>(props.onClientError);\n  onClientError.current = props.onClientError;\n\n  const onToolCallError = useRef<typeof props.onToolCallError>(\n    props.onToolCallError,\n  );\n  onToolCallError.current = props.onToolCallError;\n\n  const onOpen = useRef<typeof props.onOpen>(props.onOpen);\n  onOpen.current = props.onOpen;\n\n  const onClose = useRef<typeof props.onClose>(props.onClose);\n  onClose.current = props.onClose;\n\n  const connect = useCallback(\n    (\n      config: SocketConfig,\n      sessionSettings?: Hume.empathicVoice.SessionSettings,\n    ) => {\n      // Abort previous attempt if any\n      connectAbortController.current?.abort();\n\n      const controller = new AbortController();\n      const signal = controller.signal;\n      connectAbortController.current = controller;\n\n      const connectSettings = getSessionSettingsOnConnect(sessionSettings);\n\n      return new Promise<VoiceReadyState>((resolve, reject) => {\n        if (signal.aborted) {\n          reject(new Error('Connection attempt has already been aborted'));\n        }\n\n        const hostname = config.hostname || 'api.hume.ai';\n\n        const hume = new HumeClient(\n          config.auth.type === 'apiKey'\n            ? {\n                apiKey: config.auth.value,\n                environment: hostname,\n              }\n            : {\n                accessToken: config.auth.value,\n                environment: hostname,\n              },\n        );\n\n        const socket = hume.empathicVoice.chat.connect({\n          ...config,\n          reconnectAttempts: 0,\n          ...(connectSettings && { sessionSettings: connectSettings }),\n        });\n\n        client.current = socket;\n\n        const abortHandler = () => {\n          socket.close();\n          reject(new Error('Connection attempt has been aborted'));\n        };\n\n        signal.addEventListener('abort', abortHandler);\n\n        socket.on('message', (message) => {\n          if (signal.aborted) {\n            return;\n          }\n\n          if (message.type === 'audio_output') {\n            const messageWithReceivedAt = {\n              ...message,\n              receivedAt: new Date(),\n            };\n            onAudioMessage.current?.(messageWithReceivedAt);\n            return;\n          }\n\n          if (message.type === 'chat_metadata') {\n            onOpen.current?.();\n            setReadyState(VoiceReadyState.OPEN);\n            signal.removeEventListener('abort', abortHandler);\n            resolve(VoiceReadyState.OPEN);\n          }\n\n          if (\n            message.type === 'assistant_message' ||\n            message.type === 'user_message' ||\n            message.type === 'user_interruption' ||\n            message.type === 'error' ||\n            message.type === 'tool_response' ||\n            message.type === 'tool_error' ||\n            message.type === 'chat_metadata' ||\n            message.type === 'assistant_end' ||\n            message.type === 'assistant_prosody'\n          ) {\n            const messageWithReceivedAt = {\n              ...message,\n              receivedAt: new Date(),\n            };\n            onMessage.current?.(messageWithReceivedAt);\n            return;\n          }\n\n          if (message.type === 'tool_call') {\n            const messageWithReceivedAt = {\n              ...message,\n              receivedAt: new Date(),\n            };\n            onMessage.current?.(messageWithReceivedAt);\n\n            // only pass tool call messages for user defined tools\n            if (message.toolType === Hume.empathicVoice.ToolType.Function) {\n              void onToolCall\n                .current?.(\n                  {\n                    ...messageWithReceivedAt,\n                    // we have to do this because even though we are using the correct\n                    // enum on line 30 for the type definition\n                    // fern exports an interface and a value using the same `ToolType`\n                    // identifier so the type comparisons will always fail\n                    toolType: 'function',\n                  },\n                  {\n                    success: (content: unknown) => ({\n                      type: 'tool_response',\n                      toolCallId: messageWithReceivedAt.toolCallId,\n                      content: JSON.stringify(content),\n                    }),\n                    error: ({\n                      error,\n                      code,\n                      level,\n                      content,\n                    }: {\n                      error: string;\n                      code: string;\n                      level: string;\n                      content: string;\n                    }) => ({\n                      type: 'tool_error',\n                      toolCallId: messageWithReceivedAt.toolCallId,\n                      error,\n                      code,\n                      level: level !== null ? 'warn' : undefined, // level can only be warn\n                      content,\n                    }),\n                  },\n                )\n                .then((response) => {\n                  // if valid send it to the socket\n                  // otherwise, report error\n                  if (response.type === 'tool_response') {\n                    socket.sendToolResponseMessage(response);\n                  } else if (response.type === 'tool_error') {\n                    socket.sendToolErrorMessage(response);\n                  } else {\n                    onToolCallError.current?.(\n                      'Invalid response from tool call',\n                    );\n                  }\n                });\n            }\n            return;\n          }\n          if (message.type === 'session_settings') {\n            onSessionSettings.current?.(message);\n            return;\n          }\n\n          // asserts that all message types are handled\n          isNever(message);\n          return;\n        });\n\n        socket.on('close', (event) => {\n          signal.removeEventListener('abort', abortHandler);\n          onClose.current?.(event);\n          setReadyState(VoiceReadyState.CLOSED);\n        });\n\n        socket.on('error', (e) => {\n          signal.removeEventListener('abort', abortHandler);\n          const message = e instanceof Error ? e.message : 'Unknown error';\n          onClientError.current?.(message, e instanceof Error ? e : undefined);\n          reject(e);\n        });\n\n        setReadyState(VoiceReadyState.CONNECTING);\n      });\n    },\n    [],\n  );\n\n  const disconnect = useCallback(() => {\n    connectAbortController.current?.abort();\n    connectAbortController.current = null;\n    setReadyState(VoiceReadyState.IDLE);\n    client.current?.close();\n  }, []);\n\n  const sendSessionSettings = useCallback(\n    (sessionSettings: Hume.empathicVoice.SessionSettings) => {\n      if (readyState !== VoiceReadyState.OPEN) {\n        return;\n      }\n      client.current?.sendSessionSettings(sessionSettings);\n      onSessionSettings.current?.(sessionSettings);\n    },\n    [readyState],\n  );\n\n  const sendAudio = useCallback(\n    (arrayBuffer: ArrayBufferLike) => {\n      if (readyState !== VoiceReadyState.OPEN) {\n        return;\n      }\n      client.current?.socket?.send(arrayBuffer);\n    },\n    [readyState],\n  );\n\n  const sendUserInput = useCallback(\n    (text: string) => {\n      if (readyState !== VoiceReadyState.OPEN) {\n        return;\n      }\n      client.current?.sendUserInput(text);\n    },\n    [readyState],\n  );\n\n  const sendAssistantInput = useCallback(\n    (text: string) => {\n      if (readyState !== VoiceReadyState.OPEN) {\n        return;\n      }\n      client.current?.sendAssistantInput({\n        text,\n      });\n    },\n    [readyState],\n  );\n\n  const sendToolMessage = useCallback(\n    (\n      // type definitions for toolMessage come from the Hume SDK because messages that are sent from the client\n      // to the backend do not have the extended `receivedAt` field\n      toolMessage:\n        | Hume.empathicVoice.ToolResponseMessage\n        | Hume.empathicVoice.ToolErrorMessage,\n    ) => {\n      if (readyState !== VoiceReadyState.OPEN) {\n        return;\n      }\n      if (toolMessage.type === 'tool_error') {\n        client.current?.sendToolErrorMessage(toolMessage);\n      } else {\n        client.current?.sendToolResponseMessage(toolMessage);\n      }\n    },\n    [readyState],\n  );\n\n  const sendPauseAssistantMessage = useCallback(() => {\n    if (readyState !== VoiceReadyState.OPEN) {\n      return;\n    }\n    client.current?.pauseAssistant({});\n  }, [readyState]);\n  const sendResumeAssistantMessage = useCallback(() => {\n    if (readyState !== VoiceReadyState.OPEN) {\n      return;\n    }\n    client.current?.resumeAssistant({});\n  }, [readyState]);\n\n  return {\n    readyState,\n    sendSessionSettings,\n    sendAudio,\n    connect,\n    disconnect,\n    sendUserInput,\n    sendAssistantInput,\n    sendToolMessage,\n    sendPauseAssistantMessage,\n    sendResumeAssistantMessage,\n  };\n};\n","import { type Hume } from 'hume';\nimport React, {\n  createContext,\n  FC,\n  PropsWithChildren,\n  useCallback,\n  useContext,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\n\nimport { ConnectionMessage } from './connection-message';\nimport { noop } from './noop';\nimport { useCallDuration } from './useCallDuration';\nimport { useMessages } from './useMessages';\nimport { useMicrophone } from './useMicrophone';\nimport { useMicrophoneStream } from './useMicrophoneStream';\nimport { useSoundPlayer } from './useSoundPlayer';\nimport { useToolStatus } from './useToolStatus';\nimport {\n  ToolCallHandler,\n  useVoiceClient,\n  VoiceReadyState,\n} from './useVoiceClient';\nimport { ConnectOptions } from '../models/connect-options';\nimport {\n  AssistantProsodyMessage,\n  AssistantTranscriptMessage,\n  AudioOutputMessage,\n  ChatMetadataMessage,\n  JSONMessage,\n  UserInterruptionMessage,\n  UserTranscriptMessage,\n} from '../models/messages';\n\nexport type SocketErrorReason =\n  | 'socket_connection_failure'\n  | 'failed_to_send_audio'\n  | 'failed_to_send_message'\n  | 'received_assistant_error_message'\n  | 'received_tool_call_error';\n\nexport type AudioPlayerErrorReason =\n  | 'audio_player_initialization_failure'\n  | 'audio_worklet_load_failure'\n  | 'audio_player_not_initialized'\n  | 'malformed_audio'\n  | 'audio_player_closure_failure';\n\nexport type MicErrorReason =\n  | 'mic_permission_denied'\n  | 'mic_initialization_failure'\n  | 'mic_closure_failure'\n  | 'mime_types_not_supported';\n\ntype VoiceError =\n  | {\n      type: 'socket_error';\n      reason: SocketErrorReason;\n      message: string;\n      error?: Error;\n    }\n  | {\n      type: 'audio_error';\n      reason: AudioPlayerErrorReason;\n      message: string;\n      error?: Error;\n    }\n  | {\n      type: 'mic_error';\n      reason: MicErrorReason;\n      message: string;\n      error?: Error;\n    };\n\ntype VoiceStatus =\n  | {\n      value: 'disconnected' | 'connecting' | 'connected';\n      reason?: never;\n    }\n  | {\n      value: 'error';\n      reason: string;\n    };\n\ntype ResourceStatus =\n  | 'connecting'\n  | 'connected'\n  | 'disconnecting'\n  | 'disconnected';\n\nexport type VoiceContextType = {\n  connect: (options: ConnectOptions) => Promise<void>;\n  disconnect: () => Promise<void>;\n  fft: number[];\n  isMuted: boolean;\n  isAudioMuted: boolean;\n  isPlaying: boolean;\n  messages: (JSONMessage | ConnectionMessage)[];\n  lastVoiceMessage: AssistantTranscriptMessage | null;\n  lastUserMessage: UserTranscriptMessage | null;\n  lastAssistantProsodyMessage: AssistantProsodyMessage | null;\n  clearMessages: () => void;\n  mute: () => void;\n  unmute: () => void;\n  muteAudio: () => void;\n  unmuteAudio: () => void;\n  readyState: VoiceReadyState;\n  sendUserInput: (text: string) => void;\n  sendAssistantInput: (text: string) => void;\n  sendSessionSettings: Hume.empathicVoice.chat.ChatSocket['sendSessionSettings'];\n  sendToolMessage: (\n    type:\n      | Hume.empathicVoice.ToolResponseMessage\n      | Hume.empathicVoice.ToolErrorMessage,\n  ) => void;\n  pauseAssistant: () => void;\n  resumeAssistant: () => void;\n  status: VoiceStatus;\n  micFft: number[];\n  error: VoiceError | null;\n  isAudioError: boolean;\n  isError: boolean;\n  isMicrophoneError: boolean;\n  isSocketError: boolean;\n  callDurationTimestamp: string | null;\n  toolStatusStore: ReturnType<typeof useToolStatus>['store'];\n  chatMetadata: ChatMetadataMessage | null;\n  playerQueueLength: number;\n  isPaused: boolean;\n  volume: number;\n  setVolume: (level: number) => void;\n};\n\nconst VoiceContext = createContext<VoiceContextType | null>(null);\n\nexport type VoiceProviderProps = PropsWithChildren<{\n  onMessage?: (message: JSONMessage) => void;\n  onError?: (err: VoiceError) => void;\n  onOpen?: () => void;\n  onClose?: Hume.empathicVoice.chat.ChatSocket.EventHandlers['close'];\n  onToolCall?: ToolCallHandler;\n  onAudioReceived?: (audioOutputMessage: AudioOutputMessage) => void;\n  onAudioStart?: (clipId: string) => void;\n  onAudioEnd?: (clipId: string) => void;\n  onInterruption?: (\n    message: UserTranscriptMessage | UserInterruptionMessage,\n  ) => void;\n  /**\n   * @default true\n   * @description Clear messages when the voice is disconnected.\n   */\n  clearMessagesOnDisconnect?: boolean;\n  /**\n   * @default 100\n   * @description The maximum number of messages to keep in memory.\n   */\n  messageHistoryLimit?: number;\n  enableAudioWorklet?: boolean;\n}>;\n\nexport const useVoice = () => {\n  const ctx = useContext(VoiceContext);\n  if (!ctx) {\n    throw new Error('useVoice must be used within an VoiceProvider');\n  }\n  return ctx;\n};\n\nexport const VoiceProvider: FC<VoiceProviderProps> = ({\n  children,\n  clearMessagesOnDisconnect = true,\n  messageHistoryLimit = 100,\n  enableAudioWorklet = true,\n  ...props\n}) => {\n  const {\n    timestamp: callDurationTimestamp,\n    start: startTimer,\n    stop: stopTimer,\n  } = useCallDuration();\n\n  const [status, setStatus] = useState<VoiceStatus>({\n    value: 'disconnected',\n  });\n  const isConnectingRef = useRef(false);\n\n  // stores information about whether certain resources are being disconnected\n  const resourceStatusRef = useRef<{\n    mic: ResourceStatus;\n    audioPlayer: ResourceStatus;\n    socket: ResourceStatus;\n  }>({\n    mic: 'disconnected',\n    audioPlayer: 'disconnected',\n    socket: 'disconnected',\n  });\n\n  const [isPaused, setIsPaused] = useState(false);\n\n  // error handling\n  const [error, setError] = useState<VoiceError | null>(null);\n  const isError = error !== null;\n  const isMicrophoneError = error?.type === 'mic_error';\n  const isSocketError = error?.type === 'socket_error';\n  const isAudioError = error?.type === 'audio_error';\n\n  const onError = useRef(props.onError ?? noop);\n  onError.current = props.onError ?? noop;\n\n  const onClose = useRef(props.onClose ?? noop);\n  onClose.current = props.onClose ?? noop;\n\n  const onMessage = useRef(props.onMessage ?? noop);\n  onMessage.current = props.onMessage ?? noop;\n\n  const onAudioReceived = useRef(props.onAudioReceived ?? noop);\n  onAudioReceived.current = props.onAudioReceived ?? noop;\n\n  const onAudioStart = useRef(props.onAudioStart ?? noop);\n  onAudioStart.current = props.onAudioStart ?? noop;\n\n  const onAudioEnd = useRef(props.onAudioEnd ?? noop);\n  onAudioEnd.current = props.onAudioEnd ?? noop;\n\n  const onInterruption = useRef(props.onInterruption ?? noop);\n  onInterruption.current = props.onInterruption ?? noop;\n\n  const toolStatus = useToolStatus();\n\n  const messageStore = useMessages({\n    sendMessageToParent: onMessage.current,\n    messageHistoryLimit,\n  });\n\n  const checkIsDisconnected = useCallback(() => {\n    return (\n      resourceStatusRef.current.mic === 'disconnected' ||\n      resourceStatusRef.current.audioPlayer === 'disconnected' ||\n      resourceStatusRef.current.socket === 'disconnected'\n    );\n  }, []);\n\n  const checkIsDisconnecting = useCallback(() => {\n    return (\n      resourceStatusRef.current.mic === 'disconnecting' ||\n      resourceStatusRef.current.audioPlayer === 'disconnecting' ||\n      resourceStatusRef.current.socket === 'disconnecting'\n    );\n  }, []);\n\n  const updateError = useCallback((err: VoiceError | null) => {\n    setError(err);\n    if (err !== null) {\n      onError.current?.(err);\n    }\n  }, []);\n\n  const onClientError: NonNullable<\n    Parameters<typeof useVoiceClient>[0]['onClientError']\n  > = useCallback(\n    (msg, err) => {\n      stopTimer();\n      const message = `A websocket connection could not be established. Error message: ${msg ?? 'unknown'}`;\n      updateError({\n        type: 'socket_error',\n        reason: 'socket_connection_failure',\n        message,\n        error: err,\n      });\n    },\n    [stopTimer, updateError],\n  );\n\n  const config = props;\n\n  const micStopFnRef = useRef<null | (() => Promise<void>)>(null);\n\n  const player = useSoundPlayer({\n    enableAudioWorklet,\n    onError: (message, reason) => {\n      if (checkIsDisconnecting() || checkIsDisconnected()) {\n        return;\n      }\n      updateError({ type: 'audio_error', reason, message });\n    },\n    onPlayAudio: (id: string) => {\n      messageStore.onPlayAudio(id);\n      onAudioStart.current(id);\n    },\n    onStopAudio: (id: string) => {\n      onAudioEnd.current(id);\n    },\n  });\n\n  const { getStream, stopStream } = useMicrophoneStream();\n\n  const client = useVoiceClient({\n    onAudioMessage: (message: AudioOutputMessage) => {\n      if (checkIsDisconnecting() || checkIsDisconnected()) {\n        // disconnection in progress, and resources are being cleaned up.\n        // ignore the message\n        return;\n      }\n      void player.addToQueue(message);\n      onAudioReceived.current(message);\n    },\n    onMessage: useCallback(\n      (message: JSONMessage) => {\n        if (checkIsDisconnecting() || checkIsDisconnected()) {\n          // disconnection in progress, and resources are being cleaned up.\n          // ignore the message\n          return;\n        }\n\n        // store message\n        messageStore.onMessage(message);\n\n        if (\n          message.type === 'user_interruption' ||\n          message.type === 'user_message'\n        ) {\n          if (player.isPlaying) {\n            onInterruption.current(message);\n          }\n          player.clearQueue();\n        }\n\n        if (\n          message.type === 'tool_call' ||\n          message.type === 'tool_response' ||\n          message.type === 'tool_error'\n        ) {\n          toolStatus.addToStore(message);\n        }\n\n        if (message.type === 'error') {\n          const error: VoiceError = {\n            type: 'socket_error',\n            reason: 'received_assistant_error_message',\n            message: message.message,\n          };\n          onError.current?.(error);\n        }\n      },\n      [\n        checkIsDisconnected,\n        checkIsDisconnecting,\n        messageStore,\n        player,\n        toolStatus,\n      ],\n    ),\n    onSessionSettings: useCallback(\n      (sessionSettings: Hume.empathicVoice.SessionSettings) => {\n        if (checkIsDisconnecting() || checkIsDisconnected()) {\n          // disconnection in progress, and resources are being cleaned up.\n          // ignore the message\n          return;\n        }\n        messageStore.createSessionSettingsMessage(sessionSettings);\n      },\n      [checkIsDisconnected, checkIsDisconnecting, messageStore],\n    ),\n    onClientError,\n    onToolCallError: useCallback(\n      (message: string, err?: Error) => {\n        const error: VoiceError = {\n          type: 'socket_error',\n          reason: 'received_tool_call_error',\n          message,\n          error: err,\n        };\n        updateError(error);\n      },\n      [updateError],\n    ),\n    onOpen: useCallback(() => {\n      startTimer();\n      messageStore.createConnectMessage();\n      props.onOpen?.();\n    }, [messageStore, props, startTimer]),\n    onClose: useCallback<\n      NonNullable<Hume.empathicVoice.chat.ChatSocket.EventHandlers['close']>\n    >(\n      (event) => {\n        // onClose handler needs to handle resource cleanup in the event that the\n        // websocket connection is closed by the server and not the user/client\n        stopTimer();\n        isConnectingRef.current = false;\n        resourceStatusRef.current.socket = 'disconnected';\n\n        messageStore.createDisconnectMessage(event);\n        if (clearMessagesOnDisconnect) {\n          messageStore.clearMessages();\n        }\n        toolStatus.clearStore();\n        setIsPaused(false);\n\n        const resourceShutdownFns = [];\n        if (resourceStatusRef.current.audioPlayer === 'connected') {\n          resourceShutdownFns.push(player.stopAll());\n        }\n        if (resourceStatusRef.current.mic === 'connected') {\n          resourceShutdownFns.push(micStopFnRef.current?.());\n        }\n\n        if (resourceShutdownFns.length > 0) {\n          void Promise.all(resourceShutdownFns).then(() => {\n            resourceStatusRef.current.audioPlayer = 'disconnected';\n            resourceStatusRef.current.mic = 'disconnected';\n            // if audio player and mic were connected at the time the socket\n            // shut down, we can assume that the connection was closed by\n            // the server, and not the user. Therefore, set the status\n            // to 'disconnected'\n            setStatus({ value: 'disconnected' });\n            onClose.current?.(event);\n          });\n        } else {\n          // if audio player and mic were not connected at the time the socket,\n          // no need to setStatus because the user initiated the disconnect.\n          onClose.current?.(event);\n        }\n      },\n      [clearMessagesOnDisconnect, messageStore, player, stopTimer, toolStatus],\n    ),\n    onToolCall: props.onToolCall,\n  });\n\n  const {\n    sendAudio: clientSendAudio,\n    sendUserInput: clientSendUserInput,\n    sendAssistantInput: clientSendAssistantInput,\n    sendSessionSettings: clientSendSessionSettings,\n    sendToolMessage: clientSendToolMessage,\n    sendPauseAssistantMessage,\n    sendResumeAssistantMessage,\n  } = client;\n\n  const mic = useMicrophone({\n    onAudioCaptured: useCallback(\n      (arrayBuffer) => {\n        if (\n          resourceStatusRef.current.socket === 'disconnecting' ||\n          resourceStatusRef.current.socket === 'disconnected'\n        ) {\n          // if socket is being disconnected, don't try to send audio\n          return;\n        }\n        try {\n          clientSendAudio(arrayBuffer);\n        } catch (e) {\n          const message = e instanceof Error ? e.message : 'Unknown error';\n          updateError({\n            type: 'socket_error',\n            reason: 'failed_to_send_audio',\n            message,\n          });\n        }\n      },\n      [clientSendAudio, updateError],\n    ),\n    onError: useCallback(\n      (message, reason) => {\n        updateError({ type: 'mic_error', reason, message });\n      },\n      [updateError],\n    ),\n  });\n\n  useEffect(() => {\n    micStopFnRef.current = mic.stop;\n  }, [mic]);\n\n  const { clearQueue } = player;\n\n  const pauseAssistant = useCallback(() => {\n    try {\n      sendPauseAssistantMessage();\n      setIsPaused(true);\n    } catch (e) {\n      const message = e instanceof Error ? e.message : 'Unknown error';\n      updateError({\n        type: 'socket_error',\n        reason: 'failed_to_send_message',\n        message,\n      });\n    }\n    clearQueue();\n  }, [sendPauseAssistantMessage, clearQueue, updateError]);\n\n  const resumeAssistant = useCallback(() => {\n    try {\n      sendResumeAssistantMessage();\n      setIsPaused(false);\n    } catch (e) {\n      const message = e instanceof Error ? e.message : 'Unknown error';\n      updateError({\n        type: 'socket_error',\n        reason: 'failed_to_send_message',\n        message,\n      });\n    }\n  }, [sendResumeAssistantMessage, updateError]);\n\n  const checkShouldContinueConnecting = useCallback(() => {\n    // This check exists because if the user disconnects while the\n    // connection is in progress, we need to stop the connection\n    // attempt and prevent audio resources from being initialized.\n    return isConnectingRef.current !== false;\n  }, []);\n\n  const connect = useCallback(\n    async (options: ConnectOptions) => {\n      const {\n        audioConstraints = {},\n        sessionSettings,\n        devices,\n        ...socketConfig\n      } = options;\n      if (isConnectingRef.current || status.value === 'connected') {\n        console.warn(\n          'Already connected or connecting to a chat. Ignoring duplicate connection attempt.',\n        );\n        return;\n      }\n\n      updateError(null);\n      setStatus({ value: 'connecting' });\n      resourceStatusRef.current.socket = 'connecting';\n      resourceStatusRef.current.audioPlayer = 'connecting';\n      resourceStatusRef.current.mic = 'connecting';\n      isConnectingRef.current = true;\n\n      // Microphone permissions check - happens first\n      let stream: MediaStream | null = null;\n\n      const micConstraints: MediaTrackConstraints = {\n        ...audioConstraints,\n        deviceId: devices?.microphoneDeviceId,\n      };\n\n      try {\n        stream = await getStream(micConstraints);\n      } catch (e) {\n        const isPermissionDeniedError =\n          e instanceof DOMException && e.name === 'NotAllowedError';\n        const error: VoiceError = {\n          type: 'mic_error',\n          reason: isPermissionDeniedError\n            ? 'mic_permission_denied'\n            : 'mic_initialization_failure',\n          message:\n            e instanceof Error\n              ? e.message\n              : 'The microphone could not be initialized.',\n        };\n        updateError(error);\n        return;\n      }\n\n      // Audio Player - must initialize before connecting to the socket\n      // because it needs to exist by the time the socket is ready to send audio data\n      if (!checkShouldContinueConnecting()) {\n        console.warn('Connection attempt was canceled. Stopping connection.');\n        return;\n      }\n      try {\n        await player.initPlayer(devices?.speakerDeviceId);\n      } catch (e) {\n        resourceStatusRef.current.audioPlayer = 'disconnected';\n        updateError({\n          type: 'audio_error',\n          reason: 'audio_player_initialization_failure',\n          message:\n            e instanceof Error\n              ? e.message\n              : 'We could not connect to the audio player. Please try again.',\n        });\n        return;\n      }\n      resourceStatusRef.current.audioPlayer = 'connected';\n\n      // WEBSOCKET - needs to be connected before the microphone is initialized\n      // because a connection needs to be established before the microphone can start sending\n      // the audio stream\n      if (!checkShouldContinueConnecting()) {\n        console.warn('Connection attempt was canceled. Stopping connection.');\n        return;\n      }\n      try {\n        await client.connect(\n          {\n            ...socketConfig,\n            verboseTranscription: socketConfig.verboseTranscription ?? true,\n          },\n          sessionSettings,\n        );\n      } catch (e) {\n        // catching the thrown error here so we can return early from the connect function.\n        // Any errors themselves are handled in the `onClientError` callback on the client,\n        // except for the AbortController case, which we don't need to call onClientError for\n        // because cancellations are intentional, and not network errors.\n        return;\n      }\n      // we can set resourceStatusRef.current.socket here because `client.connect` resolves\n      // at the same time as when the onOpen callback is called\n      resourceStatusRef.current.socket = 'connected';\n\n      // MICROPHONE - initialized last\n      if (!checkShouldContinueConnecting()) {\n        console.warn('Connection attempt was canceled. Stopping connection.');\n        return;\n      }\n      try {\n        mic.start(stream);\n      } catch (e) {\n        resourceStatusRef.current.mic = 'disconnected';\n        updateError({\n          type: 'mic_error',\n          reason: 'mic_initialization_failure',\n          message:\n            e instanceof Error\n              ? e.message\n              : 'We could not connect to the microphone. Please try again.',\n        });\n        return;\n      }\n      resourceStatusRef.current.mic = 'connected';\n\n      // Everything is now initialized (socket, audio player, microphone),\n      // so set the global connected status\n      setStatus({ value: 'connected' });\n      isConnectingRef.current = false;\n    },\n    [\n      checkShouldContinueConnecting,\n      client,\n      getStream,\n      mic,\n      player,\n      status.value,\n      updateError,\n    ],\n  );\n\n  // `disconnectAndCleanUpResources`: Internal function that is called to actually disconnect\n  // from the socket, audio player, and microphone.\n  const disconnectAndCleanUpResources = useCallback(async () => {\n    resourceStatusRef.current.socket = 'disconnecting';\n    resourceStatusRef.current.audioPlayer = 'disconnecting';\n    resourceStatusRef.current.mic = 'disconnecting';\n\n    // set isConnectingRef to false in order to cancel any in-progress\n    // connection attempts\n    isConnectingRef.current = false;\n\n    stopTimer();\n\n    // MICROPHONE - shut this down before shutting down the websocket.\n    // Call stopStream separately because the user could stop the\n    // the connection before the microphone is initialized\n    stopStream();\n    await mic.stop();\n    resourceStatusRef.current.mic = 'disconnected';\n\n    // WEBSOCKET - shut this down before shutting down the audio player\n    if (client.readyState !== VoiceReadyState.CLOSED) {\n      // socket is open, so close it. resourceStatusRef will be set to 'disconnected'\n      // in the onClose callback of the websocket client.\n      client.disconnect();\n    } else {\n      // socket is already closed, so ensure that the socket status is appropriately set\n      resourceStatusRef.current.socket = 'disconnected';\n    }\n    // resourceStatusRef.current.socket is not set to 'disconnected' here,\n    // but rather in the onClose callback of the client. This is because\n    // onClose signals that the socket is actually disconnected.\n\n    // AUDIO PLAYER\n    await player.stopAll();\n    resourceStatusRef.current.audioPlayer = 'disconnected';\n\n    // Clean up other state variables that are synchronous\n    if (clearMessagesOnDisconnect) {\n      messageStore.clearMessages();\n    }\n    toolStatus.clearStore();\n    setIsPaused(false);\n  }, [\n    stopTimer,\n    stopStream,\n    mic,\n    client,\n    player,\n    clearMessagesOnDisconnect,\n    toolStatus,\n    messageStore,\n  ]);\n\n  // `disconnect` is the function that the end user calls to disconnect a call\n  const disconnect = useCallback(\n    async (disconnectOnError?: boolean) => {\n      await disconnectAndCleanUpResources();\n\n      if (status.value !== 'error' && !disconnectOnError) {\n        // if status was 'error', keep the error status so we can show the error message to the end user.\n        // otherwise, set status to 'disconnected'\n        setStatus({ value: 'disconnected' });\n      }\n    },\n    [disconnectAndCleanUpResources, status.value],\n  );\n\n  useEffect(() => {\n    if (error !== null && status.value !== 'error') {\n      // If the status is ever set to `error`, disconnect the call\n      // and clean up resources.\n      setStatus({ value: 'error', reason: error.message });\n      void disconnectAndCleanUpResources();\n    }\n  }, [status.value, disconnect, disconnectAndCleanUpResources, error]);\n\n  useEffect(() => {\n    // disconnect from socket when the voice provider component unmounts\n    return () => {\n      void disconnectAndCleanUpResources().then(() => {\n        setStatus({ value: 'disconnected' });\n        isConnectingRef.current = false;\n        resourceStatusRef.current = {\n          mic: 'disconnected',\n          audioPlayer: 'disconnected',\n          socket: 'disconnected',\n        };\n      });\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n\n  const sendUserInput = useCallback(\n    (text: string) => {\n      if (resourceStatusRef.current.socket !== 'connected') {\n        console.warn('Socket is not connected. Cannot send user input.');\n        return;\n      }\n      try {\n        clientSendUserInput(text);\n      } catch (e) {\n        const message = e instanceof Error ? e.message : 'Unknown error';\n        updateError({\n          type: 'socket_error',\n          reason: 'failed_to_send_message',\n          message,\n        });\n      }\n    },\n    [clientSendUserInput, updateError],\n  );\n\n  const sendAssistantInput = useCallback(\n    (text: string) => {\n      if (resourceStatusRef.current.socket !== 'connected') {\n        console.warn('Socket is not connected. Cannot send assistant input.');\n        return;\n      }\n      try {\n        clientSendAssistantInput(text);\n      } catch (e) {\n        const message = e instanceof Error ? e.message : 'Unknown error';\n        updateError({\n          type: 'socket_error',\n          reason: 'failed_to_send_message',\n          message,\n        });\n      }\n    },\n    [clientSendAssistantInput, updateError],\n  );\n\n  const sendSessionSettings = useCallback(\n    (sessionSettings: Hume.empathicVoice.SessionSettings) => {\n      if (resourceStatusRef.current.socket !== 'connected') {\n        console.warn('Socket is not connected. Cannot send session settings.');\n        return;\n      }\n      try {\n        clientSendSessionSettings(sessionSettings);\n      } catch (e) {\n        const message = e instanceof Error ? e.message : 'Unknown error';\n        updateError({\n          type: 'socket_error',\n          reason: 'failed_to_send_message',\n          message,\n        });\n      }\n    },\n    [clientSendSessionSettings, updateError],\n  );\n\n  const sendToolMessage = useCallback(\n    (\n      message:\n        | Hume.empathicVoice.ToolResponseMessage\n        | Hume.empathicVoice.ToolErrorMessage,\n    ) => {\n      if (resourceStatusRef.current.socket !== 'connected') {\n        console.warn('Socket is not connected. Cannot send tool message.');\n        return;\n      }\n      try {\n        clientSendToolMessage(message);\n      } catch (e) {\n        const message = e instanceof Error ? e.message : 'Unknown error';\n        updateError({\n          type: 'socket_error',\n          reason: 'failed_to_send_message',\n          message,\n        });\n      }\n    },\n    [clientSendToolMessage, updateError],\n  );\n\n  const ctx = useMemo(\n    () =>\n      ({\n        connect,\n        disconnect,\n        fft: player.fft,\n        micFft: mic.fft,\n        isMuted: mic.isMuted,\n        isAudioMuted: player.isAudioMuted,\n        isPlaying: player.isPlaying,\n        messages: messageStore.messages,\n        lastVoiceMessage: messageStore.lastVoiceMessage,\n        lastUserMessage: messageStore.lastUserMessage,\n        lastAssistantProsodyMessage: messageStore.lastAssistantProsodyMessage,\n        clearMessages: messageStore.clearMessages,\n        mute: mic.mute,\n        muteAudio: player.muteAudio,\n        readyState: client.readyState,\n        sendUserInput,\n        sendAssistantInput,\n        sendSessionSettings,\n        pauseAssistant,\n        resumeAssistant,\n        sendToolMessage,\n        status,\n        unmute: mic.unmute,\n        unmuteAudio: player.unmuteAudio,\n        error,\n        isAudioError,\n        isError,\n        isMicrophoneError,\n        isSocketError,\n        callDurationTimestamp,\n        toolStatusStore: toolStatus.store,\n        chatMetadata: messageStore.chatMetadata,\n        playerQueueLength: player.queueLength,\n        isPaused,\n        volume: player.volume,\n        setVolume: player.setVolume,\n      }) satisfies VoiceContextType,\n    [\n      connect,\n      disconnect,\n      player.fft,\n      player.isAudioMuted,\n      player.isPlaying,\n      player.muteAudio,\n      player.unmuteAudio,\n      player.queueLength,\n      player.volume,\n      player.setVolume,\n      mic.fft,\n      mic.isMuted,\n      mic.mute,\n      mic.unmute,\n      messageStore.messages,\n      messageStore.lastVoiceMessage,\n      messageStore.lastUserMessage,\n      messageStore.lastAssistantProsodyMessage,\n      messageStore.clearMessages,\n      messageStore.chatMetadata,\n      client.readyState,\n      sendUserInput,\n      sendAssistantInput,\n      sendSessionSettings,\n      pauseAssistant,\n      resumeAssistant,\n      sendToolMessage,\n      status,\n      error,\n      isAudioError,\n      isError,\n      isMicrophoneError,\n      isSocketError,\n      callDurationTimestamp,\n      toolStatus.store,\n      isPaused,\n    ],\n  );\n\n  return <VoiceContext.Provider value={ctx}>{children}</VoiceContext.Provider>;\n};\n","export const noop = () => {};\n","import { intervalToDuration } from 'date-fns';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nexport const useCallDuration = () => {\n  const interval = useRef<number | null>(null);\n  const startTime = useRef<number | null>(null);\n\n  const [timestamp, setTimestamp] = useState<string | null>(null);\n\n  const start = useCallback(() => {\n    startTime.current = Date.now();\n\n    setTimestamp('00:00:00');\n\n    interval.current = window.setInterval(() => {\n      if (startTime.current) {\n        const duration = intervalToDuration({\n          start: startTime.current,\n          end: Date.now(),\n        });\n\n        const hours = (duration.hours ?? 0).toString().padStart(2, '0');\n        const minutes = (duration.minutes ?? 0).toString().padStart(2, '0');\n        const seconds = (duration.seconds ?? 0).toString().padStart(2, '0');\n\n        setTimestamp(`${hours}:${minutes}:${seconds}`);\n      }\n    }, 500);\n  }, []);\n\n  const stop = useCallback(() => {\n    if (interval.current) {\n      window.clearInterval(interval.current);\n      interval.current = null;\n    }\n  }, []);\n\n  const reset = useCallback(() => {\n    setTimestamp(null);\n  }, []);\n\n  useEffect(() => {\n    // clean up on unmount\n    return () => {\n      if (interval.current) {\n        window.clearInterval(interval.current);\n        interval.current = null;\n      }\n    };\n  }, []);\n\n  return { timestamp, start, stop, reset };\n};\n","import type { Hume } from 'hume';\nimport { useCallback, useState } from 'react';\n\nimport type { CloseEvent, ConnectionMessage } from './connection-message';\nimport type {\n  AssistantProsodyMessage,\n  AssistantTranscriptMessage,\n  ChatMetadataMessage,\n  JSONMessage,\n  UserTranscriptMessage,\n} from '../models/messages';\nimport { keepLastN } from '../utils';\n\nexport const useMessages = ({\n  sendMessageToParent,\n  messageHistoryLimit,\n}: {\n  sendMessageToParent?: (message: JSONMessage) => void;\n  messageHistoryLimit: number;\n}) => {\n  const [voiceMessageMap, setVoiceMessageMap] = useState<\n    Record<string, AssistantTranscriptMessage>\n  >({});\n\n  const [messages, setMessages] = useState<\n    Array<JSONMessage | ConnectionMessage>\n  >([]);\n\n  const [lastVoiceMessage, setLastVoiceMessage] =\n    useState<AssistantTranscriptMessage | null>(null);\n  const [lastUserMessage, setLastUserMessage] =\n    useState<UserTranscriptMessage | null>(null);\n  const [lastAssistantProsodyMessage, setLastAssistantProsodyMessage] =\n    useState<AssistantProsodyMessage | null>(null);\n\n  const [chatMetadata, setChatMetadata] = useState<ChatMetadataMessage | null>(\n    null,\n  );\n\n  const createConnectMessage = useCallback(() => {\n    setChatMetadata(null);\n    setMessages((prev) =>\n      prev.concat([\n        {\n          type: 'socket_connected',\n          receivedAt: new Date(),\n        },\n      ]),\n    );\n  }, []);\n\n  const createSessionSettingsMessage = useCallback(\n    (sessionSettings: Hume.empathicVoice.SessionSettings) => {\n      setMessages((prev) =>\n        prev.concat([\n          {\n            type: 'session_settings',\n            sessionSettings,\n            receivedAt: new Date(),\n          },\n        ]),\n      );\n    },\n    [],\n  );\n\n  const createDisconnectMessage = useCallback((event: CloseEvent) => {\n    setMessages((prev) =>\n      prev.concat([\n        {\n          type: 'socket_disconnected',\n          code: event.code,\n          reason: event.reason,\n          receivedAt: new Date(),\n        },\n      ]),\n    );\n  }, []);\n\n  const findMostRecentUserMessage = useCallback(\n    (allMessages: typeof messages) => {\n      let mostRecentUserMessage: UserTranscriptMessage | undefined;\n      let mostRecentUserMessageIndex: number | undefined;\n      for (let i = allMessages.length - 1; i >= 0; i--) {\n        const m = allMessages[i];\n        if (m && m.type === 'user_message') {\n          mostRecentUserMessage = m;\n          mostRecentUserMessageIndex = i;\n          break;\n        }\n      }\n      return { mostRecentUserMessage, mostRecentUserMessageIndex };\n    },\n    [],\n  );\n\n  const updateMessagesArray = useCallback(\n    (messageToAdd: JSONMessage) => {\n      setMessages((prev) => {\n        // If there is an interim user message, move it to the end of the array and insert the current\n        // message into the penultimate position.\n        // Otherwise, add the message to the end of the array.\n        const { mostRecentUserMessage, mostRecentUserMessageIndex } =\n          findMostRecentUserMessage(prev);\n\n        if (mostRecentUserMessage?.interim === true) {\n          // Move interim user messages to the end of the array\n          const nextMessages = prev.filter((m, idx) => {\n            if (idx === mostRecentUserMessageIndex) {\n              return false;\n            }\n            return true;\n          });\n          return keepLastN(\n            messageHistoryLimit,\n            nextMessages.concat([messageToAdd, mostRecentUserMessage]),\n          );\n        }\n        return keepLastN(messageHistoryLimit, prev.concat([messageToAdd]));\n      });\n    },\n    [findMostRecentUserMessage, messageHistoryLimit],\n  );\n\n  const onMessage = useCallback(\n    (message: JSONMessage) => {\n      /* \n      1. message comes in from the backend\n        - if the message IS NOT AssistantTranscriptMessage, store in `messages` immediately  \n        - if the message is an AssistantTranscriptMessage, stored in `voiceMessageMap`\n      2. audio clip plays\n        - find the AssistantTranscriptMessage with a matching ID, and store it in `messages`\n        - remove the AssistantTranscriptMessage from `voiceMessageMap`\n    */\n      switch (message.type) {\n        case 'assistant_message':\n          // for assistant messages, `sendMessageToParent` is called in `onPlayAudio`\n          // in order to line up the transcript event with the correct audio clip\n          setVoiceMessageMap((prev) => ({\n            ...prev,\n            [`${message.id}`]: message,\n          }));\n          break;\n        case 'user_message':\n          // Replace interim user message with current message\n          // If there are no interim user messages, add the current message to the end of the messages array\n          sendMessageToParent?.(message);\n\n          if (message.interim === false) {\n            setLastUserMessage(message);\n          }\n\n          setMessages((prev) => {\n            if (prev.length === 0) {\n              return keepLastN(messageHistoryLimit, [message]);\n            }\n            const { mostRecentUserMessage, mostRecentUserMessageIndex } =\n              findMostRecentUserMessage(prev);\n            if (mostRecentUserMessage?.interim === true) {\n              const nextMessages = prev.filter((m, idx) => {\n                if (idx === mostRecentUserMessageIndex) {\n                  return false;\n                }\n                return true;\n              });\n              return keepLastN(\n                messageHistoryLimit,\n                nextMessages.concat([message]),\n              );\n            }\n            return keepLastN(messageHistoryLimit, prev.concat([message]));\n          });\n\n          break;\n        case 'user_interruption':\n        case 'error':\n        case 'tool_call':\n        case 'tool_response':\n        case 'tool_error':\n        case 'assistant_end':\n          sendMessageToParent?.(message);\n          updateMessagesArray(message);\n          break;\n        case 'assistant_prosody':\n          setLastAssistantProsodyMessage(message);\n          sendMessageToParent?.(message);\n          updateMessagesArray(message);\n\n          break;\n        case 'chat_metadata':\n          sendMessageToParent?.(message);\n          updateMessagesArray(message);\n          setChatMetadata(message);\n          break;\n        default:\n          break;\n      }\n    },\n    [\n      findMostRecentUserMessage,\n      messageHistoryLimit,\n      sendMessageToParent,\n      updateMessagesArray,\n    ],\n  );\n\n  const onPlayAudio = useCallback(\n    (id: string) => {\n      const matchingTranscript = voiceMessageMap[id];\n      if (matchingTranscript) {\n        sendMessageToParent?.(matchingTranscript);\n        setLastVoiceMessage(matchingTranscript);\n        updateMessagesArray(matchingTranscript);\n\n        // remove the message from the map to ensure we don't\n        // accidentally push it to the messages array more than once\n        setVoiceMessageMap((prev) => {\n          const newMap = { ...prev };\n          delete newMap[id];\n          return newMap;\n        });\n      }\n    },\n    [voiceMessageMap, sendMessageToParent, updateMessagesArray],\n  );\n\n  const clearMessages = useCallback(() => {\n    setMessages([]);\n    setLastVoiceMessage(null);\n    setLastUserMessage(null);\n    setLastAssistantProsodyMessage(null);\n    setVoiceMessageMap({});\n    setChatMetadata(null);\n  }, []);\n\n  return {\n    createConnectMessage,\n    createDisconnectMessage,\n    createSessionSettingsMessage,\n    onMessage,\n    onPlayAudio,\n    clearMessages,\n    messages,\n    lastVoiceMessage,\n    lastUserMessage,\n    lastAssistantProsodyMessage,\n    chatMetadata,\n  };\n};\n","export const keepLastN = <T>(n: number, arr: T[]): T[] => {\n  if (arr.length <= n) {\n    return arr;\n  }\n  return arr.slice(arr.length - n);\n};\n","import { useCallback, useState } from 'react';\n\nimport type { ToolCall, ToolError, ToolResponse } from '../models/messages';\n\nexport const useToolStatus = () => {\n  const [store, setStore] = useState<\n    Record<\n      string,\n      {\n        call?: ToolCall;\n        resolved?: ToolResponse | ToolError;\n      }\n    >\n  >({});\n\n  const addToStore = useCallback(\n    (message: ToolCall | ToolResponse | ToolError) => {\n      setStore((prev) => {\n        const entry = {\n          ...prev[message.toolCallId],\n        };\n\n        if (message.type === 'tool_call') {\n          entry.call = message;\n        }\n\n        if (message.type === 'tool_response' || message.type === 'tool_error') {\n          entry.resolved = message;\n        }\n\n        return {\n          ...prev,\n          [message.toolCallId]: entry,\n        };\n      });\n    },\n    [],\n  );\n\n  const clearStore = useCallback(() => {\n    setStore({});\n  }, []);\n\n  return {\n    store,\n    addToStore,\n    clearStore,\n  };\n};\n","export class SocketUnknownMessageError extends Error {\n  constructor(message?: string) {\n    super(`Unknown message type.${message ? ' ' + message : ''}`);\n    this.name = 'SocketUnknownMessageError';\n  }\n}\n\n/**\n * @name isSocketUnknownMessageError\n * @description\n * Check if an error is a SocketUnknownMessageError.\n * @param err - The error to check.\n * @returns\n * `true` if the error is a SocketUnknownMessageError.\n * @example\n * ```ts\n * if (isSocketUnknownMessageError(err)) {\n * console.error('Unknown message type');\n * }\n * ```\n */\nexport const isSocketUnknownMessageError = (\n  err: unknown,\n): err is SocketUnknownMessageError => {\n  return err instanceof SocketUnknownMessageError;\n};\n\nexport class SocketFailedToParseMessageError extends Error {\n  constructor(message?: string) {\n    super(\n      `Failed to parse message from socket.${message ? ' ' + message : ''}`,\n    );\n    this.name = 'SocketFailedToParseMessageError';\n  }\n}\n\n/**\n * @name isSocketFailedToParseMessageError\n * @description\n * Check if an error is a SocketFailedToParseMessageError.\n * @param err - The error to check.\n * @returns\n * `true` if the error is a SocketFailedToParseMessageError.\n * @example\n * ```ts\n * if (isSocketFailedToParseMessageError(err)) {\n * console.error('Failed to parse message from socket');\n * }\n * ```\n */\nexport const isSocketFailedToParseMessageError = (\n  err: unknown,\n): err is SocketFailedToParseMessageError => {\n  return err instanceof SocketFailedToParseMessageError;\n};\n","import { type Hume } from 'hume';\nimport * as HumeSerialization from 'hume/serialization';\n\nimport { type AudioMessage, parseAudioMessage } from './audio-message';\nimport {\n  SocketFailedToParseMessageError,\n  SocketUnknownMessageError,\n} from './errors';\n\n/**\n * @name parseMessageData\n * @description\n * Parse the data of a message from the socket.\n * @param data - The data to parse.\n * @returns\n * The parsed message data.\n * @example\n * ```ts\n * const message = await parseMessageData(data);\n * ```\n */\nexport const parseMessageData = async (\n  data: unknown,\n): Promise<\n  | {\n      success: true;\n      message: Hume.empathicVoice.SubscribeEvent | AudioMessage;\n    }\n  | {\n      success: false;\n      error: Error;\n    }\n> => {\n  if (data instanceof Blob) {\n    const message = await parseAudioMessage(data);\n\n    if (message) {\n      return {\n        success: true,\n        message,\n      };\n    } else {\n      return {\n        success: false,\n        error: new SocketFailedToParseMessageError(\n          `Received blob was unable to be converted to ArrayBuffer.`,\n        ),\n      };\n    }\n  }\n\n  if (typeof data !== 'string') {\n    return {\n      success: false,\n      error: new SocketFailedToParseMessageError(\n        `Expected a string but received ${typeof data}.`,\n      ),\n    };\n  }\n\n  const parseResponse =\n    HumeSerialization.empathicVoice.SubscribeEvent.parse(data);\n\n  if (!parseResponse.ok) {\n    return {\n      success: false,\n      error: new SocketUnknownMessageError(\n        `Received JSON was not a known message type.`,\n      ),\n    };\n  }\n\n  return {\n    success: true,\n    message: parseResponse.value,\n  };\n};\n\n/**\n * @name parseMessageType\n * @description\n * Parse the type of a message from the socket.\n * @param event - The event to parse.\n * @returns\n * The parsed message type.\n * @example\n * ```ts\n * const message = await parseMessageType(event);\n * ```\n */\nexport const parseMessageType = async (\n  event: MessageEvent,\n): Promise<\n  | {\n      success: true;\n      message: Hume.empathicVoice.SubscribeEvent | AudioMessage;\n    }\n  | {\n      success: false;\n      error: Error;\n    }\n> => {\n  const data: unknown = event.data;\n  return parseMessageData(data);\n};\n","import z from 'zod';\n\nexport const AudioMessageSchema = z\n  .object({\n    type: z.literal('audio'),\n    data: z.instanceof(ArrayBuffer),\n  })\n  .transform((obj) => {\n    return Object.assign(obj, {\n      receivedAt: new Date(),\n    });\n  });\n\nexport type AudioMessage = z.infer<typeof AudioMessageSchema>;\n\nexport const parseAudioMessage = async (\n  blob: Blob,\n): Promise<AudioMessage | null> => {\n  return blob\n    .arrayBuffer()\n    .then((buffer) => {\n      return {\n        type: 'audio' as const,\n        data: buffer,\n        receivedAt: new Date(),\n      };\n    })\n    .catch(() => {\n      return null;\n    });\n};\n","export enum Channels {\n  /** Mono */\n  MONO = 1,\n  /** Stereo */\n  STEREO = 2,\n}\n\nexport enum AudioEncoding {\n  /** 16-bit signed little-endian (PCM) */\n  LINEAR16 = 'linear16',\n  /** Ogg Opus */\n  OPUS = 'opus',\n}\n","export enum LanguageModelOption {\n  CLAUDE_3_OPUS = 'CLAUDE_3_OPUS',\n  CLAUDE_3_SONNET = 'CLAUDE_3_SONNET',\n  CLAUDE_3_HAIKU = 'CLAUDE_3_HAIKU',\n  CLAUDE_21 = 'CLAUDE_21',\n  CLAUDE_INSTANT_12 = 'CLAUDE_INSTANT_12',\n  GPT_4_TURBO_PREVIEW = 'GPT_4_TURBO_PREVIEW',\n  GPT_35_TURBO_0125 = 'GPT_35_TURBO_0125',\n  GPT_35_TURBO = 'GPT_35_TURBO',\n  FIREWORKS_MIXTRAL_8X7B = 'FIREWORKS_MIXTRAL_8X7B',\n}\n","import { type Hume } from 'hume';\nimport z from 'zod';\n\ntype AssistantEnd = Hume.empathicVoice.AssistantEnd;\ntype AssistantMessage = Hume.empathicVoice.AssistantMessage;\ntype AssistantProsody = Hume.empathicVoice.AssistantProsody;\ntype AudioInput = Hume.empathicVoice.AudioInput;\ntype AudioOutput = Hume.empathicVoice.AudioOutput;\ntype ChatMetadata = Hume.empathicVoice.ChatMetadata;\ntype JsonMessage = Hume.empathicVoice.JsonMessage;\ntype ToolCallMessage = Hume.empathicVoice.ToolCallMessage;\ntype ToolErrorMessage = Hume.empathicVoice.ToolErrorMessage;\ntype ToolResponseMessage = Hume.empathicVoice.ToolResponseMessage;\ntype UserInterruption = Hume.empathicVoice.UserInterruption;\ntype UserMessage = Hume.empathicVoice.UserMessage;\ntype WebSocketError = Hume.empathicVoice.WebSocketError;\n\ntype WithReceivedAt<T> = T & { receivedAt: Date };\n\nexport type AssistantEndMessage = WithReceivedAt<AssistantEnd>;\nexport type AssistantTranscriptMessage = WithReceivedAt<AssistantMessage>;\nexport type AssistantProsodyMessage = WithReceivedAt<AssistantProsody>;\nexport type AudioMessage = WithReceivedAt<AudioInput>;\nexport type AudioOutputMessage = WithReceivedAt<AudioOutput>;\nexport type ChatMetadataMessage = WithReceivedAt<ChatMetadata>;\nexport type JSONErrorMessage = WithReceivedAt<WebSocketError>;\nexport type JSONMessage = WithReceivedAt<JsonMessage>;\nexport type ToolCall = WithReceivedAt<ToolCallMessage>;\nexport type ToolError = WithReceivedAt<ToolErrorMessage>;\nexport type ToolResponse = WithReceivedAt<ToolResponseMessage>;\nexport type UserInterruptionMessage = WithReceivedAt<UserInterruption>;\nexport type UserTranscriptMessage = WithReceivedAt<UserMessage>;\n\nexport const TimeSliceSchema = z.object({\n  begin: z.number(),\n  end: z.number(),\n});\n\nexport type TimeSlice = z.infer<typeof TimeSliceSchema>;\n","export enum TTSService {\n  /** Hume's Text-To-Speech */\n  DEFAULT = 'hume_ai',\n  /** ElevenLab's Text-To-Speech */\n  ELEVEN_LABS = 'eleven_labs',\n  /** Play HT's Text-To-Speech */\n  PLAY_HT = 'play_ht',\n}\n"],"mappings":"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","names":["useCallback","useRef","useState","useState","useRef","useCallback","useCallback","useRef","useState","useState","useRef","useCallback","useCallback","useRef","useState","VoiceReadyState","useCallback","useEffect","useRef","useState","useCallback","useEffect","useRef","useState","useCallback","useState","useState","useCallback","useCallback","useState","useState","useRef","useCallback","error","useEffect","message","z","Channels","AudioEncoding","LanguageModelOption","z","TTSService"]}