{"version":3,"sources":["../src/useChatData.ts","../src/state.ts","../src/utils/group.ts","../src/wavtools/analysis/constants.js","../src/wavtools/analysis/audio_analysis.js","../src/wavtools/wav_packer.js","../src/wavtools/worklets/audio_processor.js","../src/wavtools/wav_recorder.js","../src/wavtools/worklets/stream_processor.js","../src/wavtools/wav_stream_player.js","../src/useChatInteract.ts","../src/utils/message.ts","../src/context.ts","../src/api/hooks/auth/config.ts","../src/api/hooks/api.ts","../src/api/hooks/auth/state.ts","../src/api/hooks/auth/sessionManagement.ts","../src/api/hooks/auth/userManagement.ts","../src/api/hooks/auth/index.ts","../src/api/index.tsx","../src/useChatMessages.ts","../src/useChatSession.ts","../src/useAudio.ts","../src/useConfig.ts","../src/index.ts","../src/wavtools/wav_renderer.ts"],"names":["useRecoilValue","isEqual","DefaultValue","atom","selector","uuidv4","groupByDate","data","groupedData","today","a","b","item","threadDate","daysDiff","locale","category","octave8Frequencies","octave8FrequencyLabels","noteFrequencies","noteFrequencyLabels","i","f","freq","voiceFrequencyRange","voiceFrequencies","_","voiceFrequencyLabels","AudioAnalysis","_AudioAnalysis","analyser","sampleRate","fftResult","analysisType","minDecibels","maxDecibels","nyquistFrequency","frequencyStep","outputValues","frequencies","labels","useFrequencies","aggregateOutput","frequency","amplitude","n","normalizedOutput","v","audioElement","audioBuffer","length","offlineAudioContext","source","renderQuantumInSeconds","durationInSeconds","analyze","index","suspendTime","audioContext","track","pct","WavPacker","float32Array","buffer","view","offset","s","leftBuffer","rightBuffer","tmpArray","size","arg","audio","bitsPerSample","channels","output","blob","url","AudioProcessorWorklet","script","src","AudioProcessorSrc","WavRecorder","outputToSpeakers","debug","audioData","fromSampleRate","context","arrayBuffer","values","name","_processor","message","t0","res","payload","callback","lastId","lastDevices","serializeDevices","devices","d","cb","id","permissionStatus","audioDevices","device","defaultDeviceIndex","deviceList","defaultDevice","existingIndex","deviceId","config","err","e","processor","event","node","chunkProcessor","chunkSize","force","exportData","StreamProcessorWorklet","StreamProcessorSrc","WavStreamPlayer","onStop","streamNode","requestId","trackId","currentTime","interrupt","trackSampleOffset","r","threadIdToResumeState","resumeThreadErrorState","chatProfileState","sessionIdAtom","sessionIdState","get","set","newValue","sessionState","actionState","messagesState","commandsState","modesState","tokenCountState","loadingState","askUserState","wavRecorderState","wavStreamPlayerState","audioConnectionState","isAiSpeakingState","callFnState","chatSettingsInputsState","chatSettingsDefaultValueSelector","chatSettings","collectInitialValues","inputs","acc","input","chatSettingsValueState","elementState","tasklistState","firstUserInteraction","userState","configState","authState","threadHistoryState","setSelf","onSet","oldValue","timeGroupedThreads","sideViewState","currentThreadIdState","localStorageEffect","key","savedValue","error","isReset","mcpState","favoriteMessagesState","useChatData","loading","elements","tasklists","actions","session","askUser","callFn","chatSettingsInputs","chatSettingsValue","chatSettingsDefaultValue","connected","disabled","useCallback","useContext","useResetRecoilState","useSetRecoilState","nestMessages","messages","nestedMessages","addMessage","isLastMessage","hasMessageById","updateMessageById","addMessageToParent","addIndentMessage","indent","newMessage","currentIndentation","msg","msgSteps","updatedMsg","nextMessages","updatedSteps","parentId","hasChanges","findMessageById","messageId","foundMessage","updatedMessage","deleteMessageById","updateMessageContentById","updatedContent","isSequence","isInput","newMsg","createContext","useEffect","useMemo","useSWR","SWRConfig","useRecoilState","useAuthState","authConfig","setAuthConfig","user","setUser","setThreadHistory","fetcher","client","endpoint","cloneClient","newClient","ChainlitAPI","useApi","path","swrConfig","ChainlitContext","memoizedFetcher","args","useApiClient","swrKey","useAuthConfig","authConfigData","isLoading","useSessionManagement","apiClient","reload","useUserManagement","userData","setUserFromAPI","useAuth","logout","isReady","ClientError","status","detail","APIBase","httpEndpoint","type","additionalQueryParams","on401","onError","fullUrl","params","separator","method","signal","headers","body","token","sessionId","feedback","feedbackId","pagination","filter","threadId","file","onProgress","xhr","promise","resolve","reject","formData","ask_parent_id","percentage","response","contentType","action","element","fullCommand","queryParams","theme","configuredLogoUrl","provider","isShared","defaultChainlitContext","useChatInteract","resetChatSettings","resetSessionId","resetChatSettingsValue","setFirstUserInteraction","setLoading","setMessages","setElements","setTasklists","setActions","setTokenCount","setIdToResume","setSideView","setCurrentThreadId","setFavoriteMessages","clear","sendMessage","fileReferences","oldMessages","editMessage","toggleMessageFavorite","favorite","updatedMetadata","nextMessage","oldFavorites","filtered","step","windowMessage","startAudioStream","sendAudioChunk","isStart","mimeType","elapsedTime","endAudioStream","replyMessage","updateChatSettings","editChatSettings","stopTask","m","useChatMessages","firstInteraction","debounce","io","toast","useChatSession","setSession","setIsAiSpeaking","setAudioConnection","setChatSettingsValue","setMcps","wavStreamPlayer","wavRecorder","setAskUser","setCallFn","setCommands","setModes","setChatSettingsInputs","chatProfile","setChatProfile","idToResume","setThreadResumeError","currentThreadId","_connect","transports","userEnv","protocol","host","pathname","uri","socket","old","prev","mcp","success","existingMcp","state","isFirstChunk","startTime","chunk","thread","isReadOnlyView","spec","commands","modes","steps","title","remove","count","connect","disconnect","useAudio","audioConnection","isAiSpeaking","startConversation","endConversation","useRef","useConfig","setConfig","isAuthenticated","language","prevChatProfileRef","apiUrl","shouldFetch","Socket","dataMap","normalizeArray","downsamplePeaks","memoize","cache","mKey","dKey","result","low","high","t","WavRenderer","ctx","cssWidth","cssHeight","color","pointCount","barWidth","barSpacing","center","points","height","x","y","radius"],"mappings":"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","sourcesContent":["import { useRecoilValue } from 'recoil';\n\nimport {\n  actionState,\n  askUserState,\n  callFnState,\n  chatSettingsDefaultValueSelector,\n  chatSettingsInputsState,\n  chatSettingsValueState,\n  elementState,\n  loadingState,\n  sessionState,\n  tasklistState\n} from './state';\n\nexport interface IToken {\n  id: number | string;\n  token: string;\n  isSequence: boolean;\n  isInput: boolean;\n}\n\nconst useChatData = () => {\n  const loading = useRecoilValue(loadingState);\n  const elements = useRecoilValue(elementState);\n  const tasklists = useRecoilValue(tasklistState);\n  const actions = useRecoilValue(actionState);\n  const session = useRecoilValue(sessionState);\n  const askUser = useRecoilValue(askUserState);\n  const callFn = useRecoilValue(callFnState);\n  const chatSettingsInputs = useRecoilValue(chatSettingsInputsState);\n  const chatSettingsValue = useRecoilValue(chatSettingsValueState);\n  const chatSettingsDefaultValue = useRecoilValue(\n    chatSettingsDefaultValueSelector\n  );\n\n  const connected = session?.socket.connected && !session?.error;\n  const disabled =\n    !connected ||\n    loading ||\n    askUser?.spec.type === 'file' ||\n    askUser?.spec.type === 'action' ||\n    askUser?.spec.type === 'element';\n\n  return {\n    actions,\n    askUser,\n    callFn,\n    chatSettingsDefaultValue,\n    chatSettingsInputs,\n    chatSettingsValue,\n    connected,\n    disabled,\n    elements,\n    error: session?.error,\n    loading,\n    tasklists\n  };\n};\n\nexport { useChatData };\n","import { isEqual } from 'lodash';\nimport { AtomEffect, DefaultValue, atom, selector } from 'recoil';\nimport { Socket } from 'socket.io-client';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { ICommand } from './types/command';\nimport { IMode } from './types/mode';\n\nimport {\n  IAction,\n  IAsk,\n  IAuthConfig,\n  ICallFn,\n  IChainlitConfig,\n  IMcp,\n  IMessageElement,\n  IStep,\n  ITasklistElement,\n  IUser,\n  ThreadHistory\n} from './types';\nimport { groupByDate } from './utils/group';\nimport { WavRecorder, WavStreamPlayer } from './wavtools';\n\nexport interface ISession {\n  socket: Socket;\n  error?: boolean;\n}\n\nexport const threadIdToResumeState = atom<string | undefined>({\n  key: 'ThreadIdToResume',\n  default: undefined\n});\n\nexport const resumeThreadErrorState = atom<string | undefined>({\n  key: 'ResumeThreadErrorState',\n  default: undefined\n});\n\nexport const chatProfileState = atom<string | undefined>({\n  key: 'ChatProfile',\n  default: undefined\n});\n\nconst sessionIdAtom = atom<string>({\n  key: 'SessionId',\n  default: uuidv4()\n});\n\nexport const sessionIdState = selector({\n  key: 'SessionIdSelector',\n  get: ({ get }) => get(sessionIdAtom),\n  set: ({ set }, newValue) =>\n    set(sessionIdAtom, newValue instanceof DefaultValue ? uuidv4() : newValue)\n});\n\nexport const sessionState = atom<ISession | undefined>({\n  key: 'Session',\n  dangerouslyAllowMutability: true,\n  default: undefined\n});\n\nexport const actionState = atom<IAction[]>({\n  key: 'Actions',\n  default: []\n});\n\nexport const messagesState = atom<IStep[]>({\n  key: 'Messages',\n  dangerouslyAllowMutability: true,\n  default: []\n});\n\nexport const commandsState = atom<ICommand[]>({\n  key: 'Commands',\n  default: []\n});\n\nexport const modesState = atom<IMode[]>({\n  key: 'Modes',\n  default: []\n});\n\nexport const tokenCountState = atom<number>({\n  key: 'TokenCount',\n  default: 0\n});\n\nexport const loadingState = atom<boolean>({\n  key: 'Loading',\n  default: false\n});\n\nexport const askUserState = atom<IAsk | undefined>({\n  key: 'AskUser',\n  default: undefined\n});\n\nexport const wavRecorderState = atom({\n  key: 'WavRecorder',\n  dangerouslyAllowMutability: true,\n  default: new WavRecorder()\n});\n\nexport const wavStreamPlayerState = atom({\n  key: 'WavStreamPlayer',\n  dangerouslyAllowMutability: true,\n  default: new WavStreamPlayer()\n});\n\nexport const audioConnectionState = atom<'connecting' | 'on' | 'off'>({\n  key: 'AudioConnection',\n  default: 'off'\n});\n\nexport const isAiSpeakingState = atom({\n  key: 'isAiSpeaking',\n  default: false\n});\n\nexport const callFnState = atom<ICallFn | undefined>({\n  key: 'CallFn',\n  default: undefined\n});\n\nexport const chatSettingsInputsState = atom<any>({\n  key: 'ChatSettings',\n  default: []\n});\n\nexport const chatSettingsDefaultValueSelector = selector({\n  key: 'ChatSettingsValue/Default',\n  get: ({ get }) => {\n    const chatSettings = get(chatSettingsInputsState);\n\n    const collectInitialValues = (\n      inputs: any[],\n      acc: Record<string, any>\n    ): Record<string, any> => {\n      if (!Array.isArray(inputs)) {\n        return acc;\n      }\n\n      inputs.forEach((input) => {\n        if (!input) {\n          return;\n        }\n        if (Array.isArray(input?.inputs) && input.inputs.length > 0) {\n          // Handle tabs\n          collectInitialValues(input.inputs, acc);\n        } else if (input?.id !== undefined) {\n          acc[input.id] = input.initial;\n        }\n      });\n\n      return acc;\n    };\n\n    return collectInitialValues(chatSettings, {});\n  }\n});\n\nexport const chatSettingsValueState = atom<Record<string, any>>({\n  key: 'ChatSettingsValue',\n  default: chatSettingsDefaultValueSelector\n});\n\nexport const elementState = atom<IMessageElement[]>({\n  key: 'DisplayElements',\n  default: []\n});\n\nexport const tasklistState = atom<ITasklistElement[]>({\n  key: 'TasklistElements',\n  default: []\n});\n\nexport const firstUserInteraction = atom<string | undefined>({\n  key: 'FirstUserInteraction',\n  default: undefined\n});\n\nexport const userState = atom<IUser | undefined | null>({\n  key: 'User',\n  default: undefined\n});\n\nexport const configState = atom<IChainlitConfig | undefined>({\n  key: 'ChainlitConfig',\n  default: undefined\n});\n\nexport const authState = atom<IAuthConfig | undefined>({\n  key: 'AuthConfig',\n  default: undefined\n});\n\nexport const threadHistoryState = atom<ThreadHistory | undefined>({\n  key: 'ThreadHistory',\n  default: {\n    threads: undefined,\n    currentThreadId: undefined,\n    timeGroupedThreads: undefined,\n    pageInfo: undefined\n  },\n  effects: [\n    ({ setSelf, onSet }: { setSelf: any; onSet: any }) => {\n      onSet(\n        (\n          newValue: ThreadHistory | undefined,\n          oldValue: ThreadHistory | undefined\n        ) => {\n          let timeGroupedThreads = newValue?.timeGroupedThreads;\n          if (\n            newValue?.threads &&\n            !isEqual(newValue.threads, oldValue?.timeGroupedThreads)\n          ) {\n            timeGroupedThreads = groupByDate(newValue.threads);\n          }\n\n          setSelf({\n            ...newValue,\n            timeGroupedThreads\n          });\n        }\n      );\n    }\n  ]\n});\n\nexport const sideViewState = atom<\n  { title: string; elements: IMessageElement[]; key?: string } | undefined\n>({\n  key: 'SideView',\n  default: undefined\n});\n\nexport const currentThreadIdState = atom<string | undefined>({\n  key: 'CurrentThreadId',\n  default: undefined\n});\n\nconst localStorageEffect =\n  <T>(key: string): AtomEffect<T> =>\n  ({ setSelf, onSet }) => {\n    // When the atom is first initialized, try to get its value from localStorage\n    const savedValue = localStorage.getItem(key);\n    if (savedValue != null) {\n      try {\n        setSelf(JSON.parse(savedValue));\n      } catch (error) {\n        console.error(\n          `Error parsing localStorage value for key \"${key}\":`,\n          error\n        );\n      }\n    }\n\n    // Subscribe to state changes and update localStorage\n    onSet((newValue, _, isReset) => {\n      if (isReset) {\n        localStorage.removeItem(key);\n      } else {\n        localStorage.setItem(key, JSON.stringify(newValue));\n      }\n    });\n  };\n\nexport const mcpState = atom<IMcp[]>({\n  key: 'Mcp',\n  default: [],\n  effects: [localStorageEffect<IMcp[]>('mcp_storage_key')]\n});\n\nexport const favoriteMessagesState = atom<IStep[]>({\n  key: 'favoriteMessagesState',\n  default: []\n});\n","import { IThread } from 'src/types';\n\nexport const groupByDate = (data: IThread[]) => {\n  const groupedData: { [key: string]: IThread[] } = {};\n\n  const today = new Date();\n  today.setHours(0, 0, 0, 0);\n\n  [...data]\n    .sort(\n      (a, b) =>\n        new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n    )\n    .forEach((item) => {\n      const threadDate = new Date(item.createdAt);\n      threadDate.setHours(0, 0, 0, 0);\n\n      const daysDiff = Math.floor(\n        (today.getTime() - threadDate.getTime()) / 86400000\n      );\n      const locale = navigator.language;\n\n      let category: string;\n      if (daysDiff === 0) {\n        category = 'Today';\n      } else if (daysDiff === 1) {\n        category = 'Yesterday';\n      } else if (daysDiff <= 7) {\n        category = 'Previous 7 days';\n      } else if (daysDiff <= 30) {\n        category = 'Previous 30 days';\n      } else {\n        category = threadDate.toLocaleString(locale, {\n          month: 'long',\n          year: 'numeric'\n        });\n      }\n\n      groupedData[category] ??= [];\n      groupedData[category].push(item);\n    });\n\n  return groupedData;\n};\n","/**\n * Constants for help with visualization\n * Helps map frequency ranges from Fast Fourier Transform\n * to human-interpretable ranges, notably music ranges and\n * human vocal ranges.\n */\n\n// Eighth octave frequencies\nconst octave8Frequencies = [\n  4186.01, 4434.92, 4698.63, 4978.03, 5274.04, 5587.65, 5919.91, 6271.93,\n  6644.88, 7040.0, 7458.62, 7902.13\n];\n\n// Labels for each of the above frequencies\nconst octave8FrequencyLabels = [\n  'C',\n  'C#',\n  'D',\n  'D#',\n  'E',\n  'F',\n  'F#',\n  'G',\n  'G#',\n  'A',\n  'A#',\n  'B'\n];\n\n/**\n * All note frequencies from 1st to 8th octave\n * in format \"A#8\" (A#, 8th octave)\n */\nexport const noteFrequencies = [];\nexport const noteFrequencyLabels = [];\nfor (let i = 1; i <= 8; i++) {\n  for (let f = 0; f < octave8Frequencies.length; f++) {\n    const freq = octave8Frequencies[f];\n    noteFrequencies.push(freq / Math.pow(2, 8 - i));\n    noteFrequencyLabels.push(octave8FrequencyLabels[f] + i);\n  }\n}\n\n/**\n * Subset of the note frequencies between 32 and 2000 Hz\n * 6 octave range: C1 to B6\n */\nconst voiceFrequencyRange = [32.0, 2000.0];\nexport const voiceFrequencies = noteFrequencies.filter((_, i) => {\n  return (\n    noteFrequencies[i] > voiceFrequencyRange[0] &&\n    noteFrequencies[i] < voiceFrequencyRange[1]\n  );\n});\nexport const voiceFrequencyLabels = noteFrequencyLabels.filter((_, i) => {\n  return (\n    noteFrequencies[i] > voiceFrequencyRange[0] &&\n    noteFrequencies[i] < voiceFrequencyRange[1]\n  );\n});\n","import {\n  noteFrequencies,\n  noteFrequencyLabels,\n  voiceFrequencies,\n  voiceFrequencyLabels\n} from './constants.js';\n\n/**\n * Output of AudioAnalysis for the frequency domain of the audio\n * @typedef {Object} AudioAnalysisOutputType\n * @property {Float32Array} values Amplitude of this frequency between {0, 1} inclusive\n * @property {number[]} frequencies Raw frequency bucket values\n * @property {string[]} labels Labels for the frequency bucket values\n */\n\n/**\n * Analyzes audio for visual output\n * @class\n */\nexport class AudioAnalysis {\n  /**\n   * Retrieves frequency domain data from an AnalyserNode adjusted to a decibel range\n   * returns human-readable formatting and labels\n   * @param {AnalyserNode} analyser\n   * @param {number} sampleRate\n   * @param {Float32Array} [fftResult]\n   * @param {\"frequency\"|\"music\"|\"voice\"} [analysisType]\n   * @param {number} [minDecibels] default -100\n   * @param {number} [maxDecibels] default -30\n   * @returns {AudioAnalysisOutputType}\n   */\n  static getFrequencies(\n    analyser,\n    sampleRate,\n    fftResult,\n    analysisType = 'frequency',\n    minDecibels = -100,\n    maxDecibels = -30\n  ) {\n    if (!fftResult) {\n      fftResult = new Float32Array(analyser.frequencyBinCount);\n      analyser.getFloatFrequencyData(fftResult);\n    }\n    const nyquistFrequency = sampleRate / 2;\n    const frequencyStep = (1 / fftResult.length) * nyquistFrequency;\n    let outputValues;\n    let frequencies;\n    let labels;\n    if (analysisType === 'music' || analysisType === 'voice') {\n      const useFrequencies =\n        analysisType === 'voice' ? voiceFrequencies : noteFrequencies;\n      const aggregateOutput = Array(useFrequencies.length).fill(minDecibels);\n      for (let i = 0; i < fftResult.length; i++) {\n        const frequency = i * frequencyStep;\n        const amplitude = fftResult[i];\n        for (let n = useFrequencies.length - 1; n >= 0; n--) {\n          if (frequency > useFrequencies[n]) {\n            aggregateOutput[n] = Math.max(aggregateOutput[n], amplitude);\n            break;\n          }\n        }\n      }\n      outputValues = aggregateOutput;\n      frequencies =\n        analysisType === 'voice' ? voiceFrequencies : noteFrequencies;\n      labels =\n        analysisType === 'voice' ? voiceFrequencyLabels : noteFrequencyLabels;\n    } else {\n      outputValues = Array.from(fftResult);\n      frequencies = outputValues.map((_, i) => frequencyStep * i);\n      labels = frequencies.map((f) => `${f.toFixed(2)} Hz`);\n    }\n    // We normalize to {0, 1}\n    const normalizedOutput = outputValues.map((v) => {\n      return Math.max(\n        0,\n        Math.min((v - minDecibels) / (maxDecibels - minDecibels), 1)\n      );\n    });\n    const values = new Float32Array(normalizedOutput);\n    return {\n      values,\n      frequencies,\n      labels\n    };\n  }\n\n  /**\n   * Creates a new AudioAnalysis instance for an HTMLAudioElement\n   * @param {HTMLAudioElement} audioElement\n   * @param {AudioBuffer|null} [audioBuffer] If provided, will cache all frequency domain data from the buffer\n   * @returns {AudioAnalysis}\n   */\n  constructor(audioElement, audioBuffer = null) {\n    this.fftResults = [];\n    if (audioBuffer) {\n      /**\n       * Modified from\n       * https://stackoverflow.com/questions/75063715/using-the-web-audio-api-to-analyze-a-song-without-playing\n       *\n       * We do this to populate FFT values for the audio if provided an `audioBuffer`\n       * The reason to do this is that Safari fails when using `createMediaElementSource`\n       * This has a non-zero RAM cost so we only opt-in to run it on Safari, Chrome is better\n       */\n      const { length, sampleRate } = audioBuffer;\n      const offlineAudioContext = new OfflineAudioContext({\n        length,\n        sampleRate\n      });\n      const source = offlineAudioContext.createBufferSource();\n      source.buffer = audioBuffer;\n      const analyser = offlineAudioContext.createAnalyser();\n      analyser.fftSize = 8192;\n      analyser.smoothingTimeConstant = 0.1;\n      source.connect(analyser);\n      // limit is :: 128 / sampleRate;\n      // but we just want 60fps - cuts ~1s from 6MB to 1MB of RAM\n      const renderQuantumInSeconds = 1 / 60;\n      const durationInSeconds = length / sampleRate;\n      const analyze = (index) => {\n        const suspendTime = renderQuantumInSeconds * index;\n        if (suspendTime < durationInSeconds) {\n          offlineAudioContext.suspend(suspendTime).then(() => {\n            const fftResult = new Float32Array(analyser.frequencyBinCount);\n            analyser.getFloatFrequencyData(fftResult);\n            this.fftResults.push(fftResult);\n            analyze(index + 1);\n          });\n        }\n        if (index === 1) {\n          offlineAudioContext.startRendering();\n        } else {\n          offlineAudioContext.resume();\n        }\n      };\n      source.start(0);\n      analyze(1);\n      this.audio = audioElement;\n      this.context = offlineAudioContext;\n      this.analyser = analyser;\n      this.sampleRate = sampleRate;\n      this.audioBuffer = audioBuffer;\n    } else {\n      const audioContext = new AudioContext();\n      const track = audioContext.createMediaElementSource(audioElement);\n      const analyser = audioContext.createAnalyser();\n      analyser.fftSize = 8192;\n      analyser.smoothingTimeConstant = 0.1;\n      track.connect(analyser);\n      analyser.connect(audioContext.destination);\n      this.audio = audioElement;\n      this.context = audioContext;\n      this.analyser = analyser;\n      this.sampleRate = this.context.sampleRate;\n      this.audioBuffer = null;\n    }\n  }\n\n  /**\n   * Gets the current frequency domain data from the playing audio track\n   * @param {\"frequency\"|\"music\"|\"voice\"} [analysisType]\n   * @param {number} [minDecibels] default -100\n   * @param {number} [maxDecibels] default -30\n   * @returns {AudioAnalysisOutputType}\n   */\n  getFrequencies(\n    analysisType = 'frequency',\n    minDecibels = -100,\n    maxDecibels = -30\n  ) {\n    let fftResult = null;\n    if (this.audioBuffer && this.fftResults.length) {\n      const pct = this.audio.currentTime / this.audio.duration;\n      const index = Math.min(\n        (pct * this.fftResults.length) | 0,\n        this.fftResults.length - 1\n      );\n      fftResult = this.fftResults[index];\n    }\n    return AudioAnalysis.getFrequencies(\n      this.analyser,\n      this.sampleRate,\n      fftResult,\n      analysisType,\n      minDecibels,\n      maxDecibels\n    );\n  }\n\n  /**\n   * Resume the internal AudioContext if it was suspended due to the lack of\n   * user interaction when the AudioAnalysis was instantiated.\n   * @returns {Promise<true>}\n   */\n  async resumeIfSuspended() {\n    if (this.context.state === 'suspended') {\n      await this.context.resume();\n    }\n    return true;\n  }\n}\n\nglobalThis.AudioAnalysis = AudioAnalysis;\n","/**\n * Raw wav audio file contents\n * @typedef {Object} WavPackerAudioType\n * @property {Blob} blob\n * @property {string} url\n * @property {number} channelCount\n * @property {number} sampleRate\n * @property {number} duration\n */\n\n/**\n * Utility class for assembling PCM16 \"audio/wav\" data\n * @class\n */\nexport class WavPacker {\n  /**\n   * Converts Float32Array of amplitude data to ArrayBuffer in Int16Array format\n   * @param {Float32Array} float32Array\n   * @returns {ArrayBuffer}\n   */\n  static floatTo16BitPCM(float32Array) {\n    const buffer = new ArrayBuffer(float32Array.length * 2);\n    const view = new DataView(buffer);\n    let offset = 0;\n    for (let i = 0; i < float32Array.length; i++, offset += 2) {\n      let s = Math.max(-1, Math.min(1, float32Array[i]));\n      view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n    }\n    return buffer;\n  }\n\n  /**\n   * Concatenates two ArrayBuffers\n   * @param {ArrayBuffer} leftBuffer\n   * @param {ArrayBuffer} rightBuffer\n   * @returns {ArrayBuffer}\n   */\n  static mergeBuffers(leftBuffer, rightBuffer) {\n    const tmpArray = new Uint8Array(\n      leftBuffer.byteLength + rightBuffer.byteLength\n    );\n    tmpArray.set(new Uint8Array(leftBuffer), 0);\n    tmpArray.set(new Uint8Array(rightBuffer), leftBuffer.byteLength);\n    return tmpArray.buffer;\n  }\n\n  /**\n   * Packs data into an Int16 format\n   * @private\n   * @param {number} size 0 = 1x Int16, 1 = 2x Int16\n   * @param {number} arg value to pack\n   * @returns\n   */\n  _packData(size, arg) {\n    return [\n      new Uint8Array([arg, arg >> 8]),\n      new Uint8Array([arg, arg >> 8, arg >> 16, arg >> 24])\n    ][size];\n  }\n\n  /**\n   * Packs audio into \"audio/wav\" Blob\n   * @param {number} sampleRate\n   * @param {{bitsPerSample: number, channels: Array<Float32Array>, data: Int16Array}} audio\n   * @returns {WavPackerAudioType}\n   */\n  pack(sampleRate, audio) {\n    if (!audio?.bitsPerSample) {\n      throw new Error(`Missing \"bitsPerSample\"`);\n    } else if (!audio?.channels) {\n      throw new Error(`Missing \"channels\"`);\n    } else if (!audio?.data) {\n      throw new Error(`Missing \"data\"`);\n    }\n    const { bitsPerSample, channels, data } = audio;\n    const output = [\n      // Header\n      'RIFF',\n      this._packData(\n        1,\n        4 + (8 + 24) /* chunk 1 length */ + (8 + 8) /* chunk 2 length */\n      ), // Length\n      'WAVE',\n      // chunk 1\n      'fmt ', // Sub-chunk identifier\n      this._packData(1, 16), // Chunk length\n      this._packData(0, 1), // Audio format (1 is linear quantization)\n      this._packData(0, channels.length),\n      this._packData(1, sampleRate),\n      this._packData(1, (sampleRate * channels.length * bitsPerSample) / 8), // Byte rate\n      this._packData(0, (channels.length * bitsPerSample) / 8),\n      this._packData(0, bitsPerSample),\n      // chunk 2\n      'data', // Sub-chunk identifier\n      this._packData(\n        1,\n        (channels[0].length * channels.length * bitsPerSample) / 8\n      ), // Chunk length\n      data\n    ];\n    const blob = new Blob(output, { type: 'audio/mpeg' });\n    const url = URL.createObjectURL(blob);\n    return {\n      blob,\n      url,\n      channelCount: channels.length,\n      sampleRate,\n      duration: data.byteLength / (channels.length * sampleRate * 2)\n    };\n  }\n}\n\nglobalThis.WavPacker = WavPacker;\n","const AudioProcessorWorklet = `\nclass AudioProcessor extends AudioWorkletProcessor {\n\n  constructor() {\n    super();\n    this.port.onmessage = this.receive.bind(this);\n    this.initialize();\n  }\n\n  initialize() {\n    this.foundAudio = false;\n    this.recording = false;\n    this.chunks = [];\n  }\n\n  /**\n   * Concatenates sampled chunks into channels\n   * Format is chunk[Left[], Right[]]\n   */\n  readChannelData(chunks, channel = -1, maxChannels = 9) {\n    let channelLimit;\n    if (channel !== -1) {\n      if (chunks[0] && chunks[0].length - 1 < channel) {\n        throw new Error(\n          \\`Channel \\${channel} out of range: max \\${chunks[0].length}\\`\n        );\n      }\n      channelLimit = channel + 1;\n    } else {\n      channel = 0;\n      channelLimit = Math.min(chunks[0] ? chunks[0].length : 1, maxChannels);\n    }\n    const channels = [];\n    for (let n = channel; n < channelLimit; n++) {\n      const length = chunks.reduce((sum, chunk) => {\n        return sum + chunk[n].length;\n      }, 0);\n      const buffers = chunks.map((chunk) => chunk[n]);\n      const result = new Float32Array(length);\n      let offset = 0;\n      for (let i = 0; i < buffers.length; i++) {\n        result.set(buffers[i], offset);\n        offset += buffers[i].length;\n      }\n      channels[n] = result;\n    }\n    return channels;\n  }\n\n  /**\n   * Combines parallel audio data into correct format,\n   * channels[Left[], Right[]] to float32Array[LRLRLRLR...]\n   */\n  formatAudioData(channels) {\n    if (channels.length === 1) {\n      // Simple case is only one channel\n      const float32Array = channels[0].slice();\n      const meanValues = channels[0].slice();\n      return { float32Array, meanValues };\n    } else {\n      const float32Array = new Float32Array(\n        channels[0].length * channels.length\n      );\n      const meanValues = new Float32Array(channels[0].length);\n      for (let i = 0; i < channels[0].length; i++) {\n        const offset = i * channels.length;\n        let meanValue = 0;\n        for (let n = 0; n < channels.length; n++) {\n          float32Array[offset + n] = channels[n][i];\n          meanValue += channels[n][i];\n        }\n        meanValues[i] = meanValue / channels.length;\n      }\n      return { float32Array, meanValues };\n    }\n  }\n\n  /**\n   * Converts 32-bit float data to 16-bit integers\n   */\n  floatTo16BitPCM(float32Array) {\n    const buffer = new ArrayBuffer(float32Array.length * 2);\n    const view = new DataView(buffer);\n    let offset = 0;\n    for (let i = 0; i < float32Array.length; i++, offset += 2) {\n      let s = Math.max(-1, Math.min(1, float32Array[i]));\n      view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n    }\n    return buffer;\n  }\n\n  /**\n   * Retrieves the most recent amplitude values from the audio stream\n   * @param {number} channel\n   */\n  getValues(channel = -1) {\n    const channels = this.readChannelData(this.chunks, channel);\n    const { meanValues } = this.formatAudioData(channels);\n    return { meanValues, channels };\n  }\n\n  /**\n   * Exports chunks as an audio/wav file\n   */\n  export() {\n    const channels = this.readChannelData(this.chunks);\n    const { float32Array, meanValues } = this.formatAudioData(channels);\n    const audioData = this.floatTo16BitPCM(float32Array);\n    return {\n      meanValues: meanValues,\n      audio: {\n        bitsPerSample: 16,\n        channels: channels,\n        data: audioData,\n      },\n    };\n  }\n\n  receive(e) {\n    const { event, id } = e.data;\n    let receiptData = {};\n    switch (event) {\n      case 'start':\n        this.recording = true;\n        break;\n      case 'stop':\n        this.recording = false;\n        break;\n      case 'clear':\n        this.initialize();\n        break;\n      case 'export':\n        receiptData = this.export();\n        break;\n      case 'read':\n        receiptData = this.getValues();\n        break;\n      default:\n        break;\n    }\n    // Always send back receipt\n    this.port.postMessage({ event: 'receipt', id, data: receiptData });\n  }\n\n  sendChunk(chunk) {\n    const channels = this.readChannelData([chunk]);\n    const { float32Array, meanValues } = this.formatAudioData(channels);\n    const rawAudioData = this.floatTo16BitPCM(float32Array);\n    const monoAudioData = this.floatTo16BitPCM(meanValues);\n    this.port.postMessage({\n      event: 'chunk',\n      data: {\n        mono: monoAudioData,\n        raw: rawAudioData,\n      },\n    });\n  }\n\n  process(inputList, outputList, parameters) {\n    // Copy input to output (e.g. speakers)\n    // Note that this creates choppy sounds with Mac products\n    const sourceLimit = Math.min(inputList.length, outputList.length);\n    for (let inputNum = 0; inputNum < sourceLimit; inputNum++) {\n      const input = inputList[inputNum];\n      const output = outputList[inputNum];\n      const channelCount = Math.min(input.length, output.length);\n      for (let channelNum = 0; channelNum < channelCount; channelNum++) {\n        input[channelNum].forEach((sample, i) => {\n          output[channelNum][i] = sample;\n        });\n      }\n    }\n    const inputs = inputList[0];\n    // There's latency at the beginning of a stream before recording starts\n    // Make sure we actually receive audio data before we start storing chunks\n    let sliceIndex = 0;\n    if (!this.foundAudio) {\n      for (const channel of inputs) {\n        sliceIndex = 0; // reset for each channel\n        if (this.foundAudio) {\n          break;\n        }\n        if (channel) {\n          for (const value of channel) {\n            if (value !== 0) {\n              // find only one non-zero entry in any channel\n              this.foundAudio = true;\n              break;\n            } else {\n              sliceIndex++;\n            }\n          }\n        }\n      }\n    }\n    if (inputs && inputs[0] && this.foundAudio && this.recording) {\n      // We need to copy the TypedArray, because the \\`process\\`\n      // internals will reuse the same buffer to hold each input\n      const chunk = inputs.map((input) => input.slice(sliceIndex));\n      this.chunks.push(chunk);\n      this.sendChunk(chunk);\n    }\n    return true;\n  }\n}\n\nregisterProcessor('audio_processor', AudioProcessor);\n`;\n\nconst script = new Blob([AudioProcessorWorklet], {\n  type: 'application/javascript'\n});\nconst src = URL.createObjectURL(script);\nexport const AudioProcessorSrc = src;\n","import { AudioAnalysis } from './analysis/audio_analysis.js';\nimport { WavPacker } from './wav_packer.js';\nimport { AudioProcessorSrc } from './worklets/audio_processor.js';\n\n/**\n * Decodes audio into a wav file\n * @typedef {Object} DecodedAudioType\n * @property {Blob} blob\n * @property {string} url\n * @property {Float32Array} values\n * @property {AudioBuffer} audioBuffer\n */\n\n/**\n * Records live stream of user audio as PCM16 \"audio/wav\" data\n * @class\n */\nexport class WavRecorder {\n  /**\n   * Create a new WavRecorder instance\n   * @param {{sampleRate?: number, outputToSpeakers?: boolean, debug?: boolean}} [options]\n   * @returns {WavRecorder}\n   */\n  constructor({\n    sampleRate = 24000,\n    outputToSpeakers = false,\n    debug = false\n  } = {}) {\n    // Script source\n    this.scriptSrc = AudioProcessorSrc;\n    // Config\n    this.sampleRate = sampleRate;\n    this.outputToSpeakers = outputToSpeakers;\n    this.debug = !!debug;\n    this._deviceChangeCallback = null;\n    this._devices = [];\n    // State variables\n    this.stream = null;\n    this.processor = null;\n    this.source = null;\n    this.node = null;\n    this.recording = false;\n    // Event handling with AudioWorklet\n    this._lastEventId = 0;\n    this.eventReceipts = {};\n    this.eventTimeout = 5000;\n    // Process chunks of audio\n    this._chunkProcessor = () => {};\n    this._chunkProcessorSize = void 0;\n    this._chunkProcessorBuffer = {\n      raw: new ArrayBuffer(0),\n      mono: new ArrayBuffer(0)\n    };\n  }\n\n  /**\n   * Decodes audio data from multiple formats to a Blob, url, Float32Array and AudioBuffer\n   * @param {Blob|Float32Array|Int16Array|ArrayBuffer|number[]} audioData\n   * @param {number} sampleRate\n   * @param {number} fromSampleRate\n   * @returns {Promise<DecodedAudioType>}\n   */\n  static async decode(audioData, sampleRate = 24000, fromSampleRate = -1) {\n    const context = new AudioContext({ sampleRate });\n    let arrayBuffer;\n    let blob;\n    if (audioData instanceof Blob) {\n      if (fromSampleRate !== -1) {\n        throw new Error(\n          `Can not specify \"fromSampleRate\" when reading from Blob`\n        );\n      }\n      blob = audioData;\n      arrayBuffer = await blob.arrayBuffer();\n    } else if (audioData instanceof ArrayBuffer) {\n      if (fromSampleRate !== -1) {\n        throw new Error(\n          `Can not specify \"fromSampleRate\" when reading from ArrayBuffer`\n        );\n      }\n      arrayBuffer = audioData;\n      blob = new Blob([arrayBuffer], { type: 'audio/wav' });\n    } else {\n      let float32Array;\n      let data;\n      if (audioData instanceof Int16Array) {\n        data = audioData;\n        float32Array = new Float32Array(audioData.length);\n        for (let i = 0; i < audioData.length; i++) {\n          float32Array[i] = audioData[i] / 0x8000;\n        }\n      } else if (audioData instanceof Float32Array) {\n        float32Array = audioData;\n      } else if (audioData instanceof Array) {\n        float32Array = new Float32Array(audioData);\n      } else {\n        throw new Error(\n          `\"audioData\" must be one of: Blob, Float32Arrray, Int16Array, ArrayBuffer, Array<number>`\n        );\n      }\n      if (fromSampleRate === -1) {\n        throw new Error(\n          `Must specify \"fromSampleRate\" when reading from Float32Array, In16Array or Array`\n        );\n      } else if (fromSampleRate < 3000) {\n        throw new Error(`Minimum \"fromSampleRate\" is 3000 (3kHz)`);\n      }\n      if (!data) {\n        data = WavPacker.floatTo16BitPCM(float32Array);\n      }\n      const audio = {\n        bitsPerSample: 16,\n        channels: [float32Array],\n        data\n      };\n      const packer = new WavPacker();\n      const result = packer.pack(fromSampleRate, audio);\n      blob = result.blob;\n      arrayBuffer = await blob.arrayBuffer();\n    }\n    const audioBuffer = await context.decodeAudioData(arrayBuffer);\n    const values = audioBuffer.getChannelData(0);\n    const url = URL.createObjectURL(blob);\n    return {\n      blob,\n      url,\n      values,\n      audioBuffer\n    };\n  }\n\n  /**\n   * Logs data in debug mode\n   * @param {...any} arguments\n   * @returns {true}\n   */\n  log() {\n    if (this.debug) {\n      this.log(...arguments);\n    }\n    return true;\n  }\n\n  /**\n   * Retrieves the current sampleRate for the recorder\n   * @returns {number}\n   */\n  getSampleRate() {\n    return this.sampleRate;\n  }\n\n  /**\n   * Retrieves the current status of the recording\n   * @returns {\"ended\"|\"paused\"|\"recording\"}\n   */\n  getStatus() {\n    if (!this.processor) {\n      return 'ended';\n    } else if (!this.recording) {\n      return 'paused';\n    } else {\n      return 'recording';\n    }\n  }\n\n  /**\n   * Sends an event to the AudioWorklet\n   * @private\n   * @param {string} name\n   * @param {{[key: string]: any}} data\n   * @param {AudioWorkletNode} [_processor]\n   * @returns {Promise<{[key: string]: any}>}\n   */\n  async _event(name, data = {}, _processor = null) {\n    _processor = _processor || this.processor;\n    if (!_processor) {\n      throw new Error('Can not send events without recording first');\n    }\n    const message = {\n      event: name,\n      id: this._lastEventId++,\n      data\n    };\n    _processor.port.postMessage(message);\n    const t0 = new Date().valueOf();\n    while (!this.eventReceipts[message.id]) {\n      if (new Date().valueOf() - t0 > this.eventTimeout) {\n        throw new Error(`Timeout waiting for \"${name}\" event`);\n      }\n      await new Promise((res) => setTimeout(() => res(true), 1));\n    }\n    const payload = this.eventReceipts[message.id];\n    delete this.eventReceipts[message.id];\n    return payload;\n  }\n\n  /**\n   * Sets device change callback, remove if callback provided is `null`\n   * @param {(Array<MediaDeviceInfo & {default: boolean}>): void|null} callback\n   * @returns {true}\n   */\n  listenForDeviceChange(callback) {\n    if (callback === null && this._deviceChangeCallback) {\n      navigator.mediaDevices.removeEventListener(\n        'devicechange',\n        this._deviceChangeCallback\n      );\n      this._deviceChangeCallback = null;\n    } else if (callback !== null) {\n      // Basically a debounce; we only want this called once when devices change\n      // And we only want the most recent callback() to be executed\n      // if a few are operating at the same time\n      let lastId = 0;\n      let lastDevices = [];\n      const serializeDevices = (devices) =>\n        devices\n          .map((d) => d.deviceId)\n          .sort()\n          .join(',');\n      const cb = async () => {\n        let id = ++lastId;\n        const devices = await this.listDevices();\n        if (id === lastId) {\n          if (serializeDevices(lastDevices) !== serializeDevices(devices)) {\n            lastDevices = devices;\n            callback(devices.slice());\n          }\n        }\n      };\n      navigator.mediaDevices.addEventListener('devicechange', cb);\n      cb();\n      this._deviceChangeCallback = cb;\n    }\n    return true;\n  }\n\n  /**\n   * Manually request permission to use the microphone\n   * @returns {Promise<true>}\n   */\n  async requestPermission() {\n    const permissionStatus = await navigator.permissions.query({\n      name: 'microphone'\n    });\n    if (permissionStatus.state === 'denied') {\n      window.alert('You must grant microphone access to use this feature.');\n    } else if (permissionStatus.state === 'prompt') {\n      try {\n        const stream = await navigator.mediaDevices.getUserMedia({\n          audio: true\n        });\n        const tracks = stream.getTracks();\n        tracks.forEach((track) => track.stop());\n      } catch (_e) {\n        window.alert('You must grant microphone access to use this feature.');\n      }\n    }\n    return true;\n  }\n\n  /**\n   * List all eligible devices for recording, will request permission to use microphone\n   * @returns {Promise<Array<MediaDeviceInfo & {default: boolean}>>}\n   */\n  async listDevices() {\n    if (\n      !navigator.mediaDevices ||\n      !('enumerateDevices' in navigator.mediaDevices)\n    ) {\n      throw new Error('Could not request user devices');\n    }\n    await this.requestPermission();\n    const devices = await navigator.mediaDevices.enumerateDevices();\n    const audioDevices = devices.filter(\n      (device) => device.kind === 'audioinput'\n    );\n    const defaultDeviceIndex = audioDevices.findIndex(\n      (device) => device.deviceId === 'default'\n    );\n    const deviceList = [];\n    if (defaultDeviceIndex !== -1) {\n      let defaultDevice = audioDevices.splice(defaultDeviceIndex, 1)[0];\n      let existingIndex = audioDevices.findIndex(\n        (device) => device.groupId === defaultDevice.groupId\n      );\n      if (existingIndex !== -1) {\n        defaultDevice = audioDevices.splice(existingIndex, 1)[0];\n      }\n      defaultDevice.default = true;\n      deviceList.push(defaultDevice);\n    }\n    return deviceList.concat(audioDevices);\n  }\n\n  /**\n   * Begins a recording session and requests microphone permissions if not already granted\n   * Microphone recording indicator will appear on browser tab but status will be \"paused\"\n   * @param {string} [deviceId] if no device provided, default device will be used\n   * @returns {Promise<true>}\n   */\n  async begin(deviceId) {\n    if (this.processor) {\n      throw new Error(\n        `Already connected: please call .end() to start a new session`\n      );\n    }\n\n    if (\n      !navigator.mediaDevices ||\n      !('getUserMedia' in navigator.mediaDevices)\n    ) {\n      throw new Error('Could not request user media');\n    }\n    try {\n      const config = { audio: true };\n      if (deviceId) {\n        config.audio = { deviceId: { exact: deviceId } };\n      }\n      this.stream = await navigator.mediaDevices.getUserMedia(config);\n    } catch (err) {\n      throw new Error('Could not start media stream', { cause: err });\n    }\n\n    const context = new AudioContext({ sampleRate: this.sampleRate });\n    const source = context.createMediaStreamSource(this.stream);\n    // Load and execute the module script.\n    try {\n      await context.audioWorklet.addModule(this.scriptSrc);\n    } catch (e) {\n      console.error(e);\n      throw new Error(`Could not add audioWorklet module: ${this.scriptSrc}`, {\n        cause: e\n      });\n    }\n    const processor = new AudioWorkletNode(context, 'audio_processor');\n    processor.port.onmessage = (e) => {\n      const { event, id, data } = e.data;\n      if (event === 'receipt') {\n        this.eventReceipts[id] = data;\n      } else if (event === 'chunk') {\n        if (this._chunkProcessorSize) {\n          const buffer = this._chunkProcessorBuffer;\n          this._chunkProcessorBuffer = {\n            raw: WavPacker.mergeBuffers(buffer.raw, data.raw),\n            mono: WavPacker.mergeBuffers(buffer.mono, data.mono)\n          };\n          if (\n            this._chunkProcessorBuffer.mono.byteLength >=\n            this._chunkProcessorSize\n          ) {\n            this._chunkProcessor(this._chunkProcessorBuffer);\n            this._chunkProcessorBuffer = {\n              raw: new ArrayBuffer(0),\n              mono: new ArrayBuffer(0)\n            };\n          }\n        } else {\n          this._chunkProcessor(data);\n        }\n      }\n    };\n\n    const node = source.connect(processor);\n    const analyser = context.createAnalyser();\n    analyser.fftSize = 8192;\n    analyser.smoothingTimeConstant = 0.1;\n    node.connect(analyser);\n    if (this.outputToSpeakers) {\n      console.warn(\n        'Warning: Output to speakers may affect sound quality,\\n' +\n          'especially due to system audio feedback preventative measures.\\n' +\n          'use only for debugging'\n      );\n      analyser.connect(context.destination);\n    }\n\n    this.source = source;\n    this.node = node;\n    this.analyser = analyser;\n    this.processor = processor;\n    return true;\n  }\n\n  /**\n   * Gets the current frequency domain data from the recording track\n   * @param {\"frequency\"|\"music\"|\"voice\"} [analysisType]\n   * @param {number} [minDecibels] default -100\n   * @param {number} [maxDecibels] default -30\n   * @returns {import('./analysis/audio_analysis.js').AudioAnalysisOutputType}\n   */\n  getFrequencies(\n    analysisType = 'frequency',\n    minDecibels = -100,\n    maxDecibels = -30\n  ) {\n    if (!this.processor) {\n      throw new Error('Session ended: please call .begin() first');\n    }\n    return AudioAnalysis.getFrequencies(\n      this.analyser,\n      this.sampleRate,\n      null,\n      analysisType,\n      minDecibels,\n      maxDecibels\n    );\n  }\n\n  /**\n   * Pauses the recording\n   * Keeps microphone stream open but halts storage of audio\n   * @returns {Promise<true>}\n   */\n  async pause() {\n    if (!this.processor) {\n      throw new Error('Session ended: please call .begin() first');\n    } else if (!this.recording) {\n      throw new Error('Already paused: please call .record() first');\n    }\n    if (this._chunkProcessorBuffer.raw.byteLength) {\n      this._chunkProcessor(this._chunkProcessorBuffer);\n    }\n    this.log('Pausing ...');\n    await this._event('stop');\n    this.recording = false;\n    return true;\n  }\n\n  /**\n   * Start recording stream and storing to memory from the connected audio source\n   * @param {(data: { mono: Int16Array; raw: Int16Array }) => any} [chunkProcessor]\n   * @param {number} [chunkSize] chunkProcessor will not be triggered until this size threshold met in mono audio\n   * @returns {Promise<true>}\n   */\n  async record(chunkProcessor = () => {}, chunkSize = 8192) {\n    if (!this.processor) {\n      throw new Error('Session ended: please call .begin() first');\n    } else if (this.recording) {\n      throw new Error('Already recording: please call .pause() first');\n    } else if (typeof chunkProcessor !== 'function') {\n      throw new Error(`chunkProcessor must be a function`);\n    }\n    this._chunkProcessor = chunkProcessor;\n    this._chunkProcessorSize = chunkSize;\n    this._chunkProcessorBuffer = {\n      raw: new ArrayBuffer(0),\n      mono: new ArrayBuffer(0)\n    };\n    this.log('Recording ...');\n    await this._event('start');\n    this.recording = true;\n    return true;\n  }\n\n  /**\n   * Clears the audio buffer, empties stored recording\n   * @returns {Promise<true>}\n   */\n  async clear() {\n    if (!this.processor) {\n      throw new Error('Session ended: please call .begin() first');\n    }\n    await this._event('clear');\n    return true;\n  }\n\n  /**\n   * Reads the current audio stream data\n   * @returns {Promise<{meanValues: Float32Array, channels: Array<Float32Array>}>}\n   */\n  async read() {\n    if (!this.processor) {\n      throw new Error('Session ended: please call .begin() first');\n    }\n    this.log('Reading ...');\n    const result = await this._event('read');\n    return result;\n  }\n\n  /**\n   * Saves the current audio stream to a file\n   * @param {boolean} [force] Force saving while still recording\n   * @returns {Promise<import('./wav_packer.js').WavPackerAudioType>}\n   */\n  async save(force = false) {\n    if (!this.processor) {\n      throw new Error('Session ended: please call .begin() first');\n    }\n    if (!force && this.recording) {\n      throw new Error(\n        'Currently recording: please call .pause() first, or call .save(true) to force'\n      );\n    }\n    this.log('Exporting ...');\n    const exportData = await this._event('export');\n    const packer = new WavPacker();\n    const result = packer.pack(this.sampleRate, exportData.audio);\n    return result;\n  }\n\n  /**\n   * Ends the current recording session and saves the result\n   * @returns {Promise<import('./wav_packer.js').WavPackerAudioType>}\n   */\n  async end() {\n    if (!this.processor) {\n      throw new Error('Session ended: please call .begin() first');\n    }\n\n    const _processor = this.processor;\n\n    this.log('Stopping ...');\n    await this._event('stop');\n    this.recording = false;\n    const tracks = this.stream.getTracks();\n    tracks.forEach((track) => track.stop());\n\n    this.log('Exporting ...');\n    const exportData = await this._event('export', {}, _processor);\n\n    this.processor.disconnect();\n    this.source.disconnect();\n    this.node.disconnect();\n    this.analyser.disconnect();\n    this.stream = null;\n    this.processor = null;\n    this.source = null;\n    this.node = null;\n\n    const packer = new WavPacker();\n    const result = packer.pack(this.sampleRate, exportData.audio);\n    return result;\n  }\n\n  /**\n   * Performs a full cleanup of WavRecorder instance\n   * Stops actively listening via microphone and removes existing listeners\n   * @returns {Promise<true>}\n   */\n  async quit() {\n    this.listenForDeviceChange(null);\n    if (this.processor) {\n      await this.end();\n    }\n    return true;\n  }\n}\n\nglobalThis.WavRecorder = WavRecorder;\n","export const StreamProcessorWorklet = `\nclass StreamProcessor extends AudioWorkletProcessor {\n  constructor() {\n    super();\n    this.hasStarted = false;\n    this.hasInterrupted = false;\n    this.outputBuffers = [];\n    this.bufferLength = 128;\n    this.write = { buffer: new Float32Array(this.bufferLength), trackId: null };\n    this.writeOffset = 0;\n    this.trackSampleOffsets = {};\n    this.port.onmessage = (event) => {\n      if (event.data) {\n        const payload = event.data;\n        if (payload.event === 'write') {\n          const int16Array = payload.buffer;\n          const float32Array = new Float32Array(int16Array.length);\n          for (let i = 0; i < int16Array.length; i++) {\n            float32Array[i] = int16Array[i] / 0x8000; // Convert Int16 to Float32\n          }\n          this.writeData(float32Array, payload.trackId);\n        } else if (\n          payload.event === 'offset' ||\n          payload.event === 'interrupt'\n        ) {\n          const requestId = payload.requestId;\n          const trackId = this.write.trackId;\n          const offset = this.trackSampleOffsets[trackId] || 0;\n          this.port.postMessage({\n            event: 'offset',\n            requestId,\n            trackId,\n            offset,\n          });\n          if (payload.event === 'interrupt') {\n            this.hasInterrupted = true;\n          }\n        } else {\n          throw new Error(\\`Unhandled event \"\\${payload.event}\"\\`);\n        }\n      }\n    };\n  }\n\n  writeData(float32Array, trackId = null) {\n    let { buffer } = this.write;\n    let offset = this.writeOffset;\n    for (let i = 0; i < float32Array.length; i++) {\n      buffer[offset++] = float32Array[i];\n      if (offset >= buffer.length) {\n        this.outputBuffers.push(this.write);\n        this.write = { buffer: new Float32Array(this.bufferLength), trackId };\n        buffer = this.write.buffer;\n        offset = 0;\n      }\n    }\n    this.writeOffset = offset;\n    return true;\n  }\n\n  process(inputs, outputs, parameters) {\n    const output = outputs[0];\n    const outputChannelData = output[0];\n    const outputBuffers = this.outputBuffers;\n    if (this.hasInterrupted) {\n      this.port.postMessage({ event: 'stop' });\n      return false;\n    } else if (outputBuffers.length) {\n      this.hasStarted = true;\n      const { buffer, trackId } = outputBuffers.shift();\n      for (let i = 0; i < outputChannelData.length; i++) {\n        outputChannelData[i] = buffer[i] || 0;\n      }\n      if (trackId) {\n        this.trackSampleOffsets[trackId] =\n          this.trackSampleOffsets[trackId] || 0;\n        this.trackSampleOffsets[trackId] += buffer.length;\n      }\n      return true;\n    } else if (this.hasStarted) {\n      this.port.postMessage({ event: 'stop' });\n      return false;\n    } else {\n      return true;\n    }\n  }\n}\n\nregisterProcessor('stream_processor', StreamProcessor);\n`;\n\nconst script = new Blob([StreamProcessorWorklet], {\n  type: 'application/javascript'\n});\nconst src = URL.createObjectURL(script);\nexport const StreamProcessorSrc = src;\n","import { AudioAnalysis } from './analysis/audio_analysis.js';\nimport { StreamProcessorSrc } from './worklets/stream_processor.js';\n\n/**\n * Plays audio streams received in raw PCM16 chunks from the browser\n * @class\n */\nexport class WavStreamPlayer {\n  /**\n   * Creates a new WavStreamPlayer instance\n   * @param {{sampleRate?: number}} options\n   * @returns {WavStreamPlayer}\n   */\n  constructor({ sampleRate = 24000, onStop } = {}) {\n    this.scriptSrc = StreamProcessorSrc;\n    this.onStop = onStop;\n    this.sampleRate = sampleRate;\n    this.context = null;\n    this.stream = null;\n    this.analyser = null;\n    this.trackSampleOffsets = {};\n    this.interruptedTrackIds = {};\n  }\n\n  /**\n   * Connects the audio context and enables output to speakers\n   * @returns {Promise<true>}\n   */\n  async connect() {\n    this.context = new AudioContext({ sampleRate: this.sampleRate });\n    if (this.context.state === 'suspended') {\n      await this.context.resume();\n    }\n    try {\n      await this.context.audioWorklet.addModule(this.scriptSrc);\n    } catch (e) {\n      console.error(e);\n      throw new Error(`Could not add audioWorklet module: ${this.scriptSrc}`, {\n        cause: e\n      });\n    }\n    const analyser = this.context.createAnalyser();\n    analyser.fftSize = 8192;\n    analyser.smoothingTimeConstant = 0.1;\n    this.analyser = analyser;\n    return true;\n  }\n\n  /**\n   * Gets the current frequency domain data from the playing track\n   * @param {\"frequency\"|\"music\"|\"voice\"} [analysisType]\n   * @param {number} [minDecibels] default -100\n   * @param {number} [maxDecibels] default -30\n   * @returns {import('./analysis/audio_analysis.js').AudioAnalysisOutputType}\n   */\n  getFrequencies(\n    analysisType = 'frequency',\n    minDecibels = -100,\n    maxDecibels = -30\n  ) {\n    if (!this.analyser) {\n      throw new Error('Not connected, please call .connect() first');\n    }\n    return AudioAnalysis.getFrequencies(\n      this.analyser,\n      this.sampleRate,\n      null,\n      analysisType,\n      minDecibels,\n      maxDecibels\n    );\n  }\n\n  /**\n   * Starts audio streaming\n   * @private\n   * @returns {Promise<true>}\n   */\n  _start() {\n    const streamNode = new AudioWorkletNode(this.context, 'stream_processor');\n    streamNode.connect(this.context.destination);\n    streamNode.port.onmessage = (e) => {\n      const { event } = e.data;\n      if (event === 'stop') {\n        this.onStop?.();\n        streamNode.disconnect();\n        this.stream = null;\n      } else if (event === 'offset') {\n        const { requestId, trackId, offset } = e.data;\n        const currentTime = offset / this.sampleRate;\n        this.trackSampleOffsets[requestId] = { trackId, offset, currentTime };\n      }\n    };\n    this.analyser.disconnect();\n    streamNode.connect(this.analyser);\n    this.stream = streamNode;\n    return true;\n  }\n\n  /**\n   * Adds 16BitPCM data to the currently playing audio stream\n   * You can add chunks beyond the current play point and they will be queued for play\n   * @param {ArrayBuffer|Int16Array} arrayBuffer\n   * @param {string} [trackId]\n   * @returns {Int16Array}\n   */\n  add16BitPCM(arrayBuffer, trackId = 'default') {\n    if (typeof trackId !== 'string') {\n      throw new Error(`trackId must be a string`);\n    } else if (this.interruptedTrackIds[trackId]) {\n      return;\n    }\n    if (!this.stream) {\n      this._start();\n    }\n    let buffer;\n    if (arrayBuffer instanceof Int16Array) {\n      buffer = arrayBuffer;\n    } else if (arrayBuffer instanceof ArrayBuffer) {\n      buffer = new Int16Array(arrayBuffer);\n    } else {\n      throw new Error(`argument must be Int16Array or ArrayBuffer`);\n    }\n    this.stream.port.postMessage({ event: 'write', buffer, trackId });\n    return buffer;\n  }\n\n  /**\n   * Gets the offset (sample count) of the currently playing stream\n   * @param {boolean} [interrupt]\n   * @returns {{trackId: string|null, offset: number, currentTime: number}}\n   */\n  async getTrackSampleOffset(interrupt = false) {\n    if (!this.stream) {\n      return null;\n    }\n    const requestId = crypto.randomUUID();\n    this.stream.port.postMessage({\n      event: interrupt ? 'interrupt' : 'offset',\n      requestId\n    });\n    let trackSampleOffset;\n    while (!trackSampleOffset) {\n      trackSampleOffset = this.trackSampleOffsets[requestId];\n      await new Promise((r) => setTimeout(() => r(), 1));\n    }\n    const { trackId } = trackSampleOffset;\n    if (interrupt && trackId) {\n      this.interruptedTrackIds[trackId] = true;\n    }\n    return trackSampleOffset;\n  }\n\n  /**\n   * Strips the current stream and returns the sample offset of the audio\n   * @param {boolean} [interrupt]\n   * @returns {{trackId: string|null, offset: number, currentTime: number}}\n   */\n  async interrupt() {\n    return this.getTrackSampleOffset(true);\n  }\n}\n\nglobalThis.WavStreamPlayer = WavStreamPlayer;\n","import { useCallback, useContext } from 'react';\nimport { useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil';\nimport {\n  actionState,\n  askUserState,\n  chatSettingsInputsState,\n  chatSettingsValueState,\n  currentThreadIdState,\n  elementState,\n  favoriteMessagesState,\n  firstUserInteraction,\n  loadingState,\n  messagesState,\n  sessionIdState,\n  sessionState,\n  sideViewState,\n  tasklistState,\n  threadIdToResumeState,\n  tokenCountState\n} from 'src/state';\nimport { IFileRef, IStep } from 'src/types';\nimport { addMessage } from 'src/utils/message';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { ChainlitContext } from './context';\n\ntype PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;\n\nconst useChatInteract = () => {\n  const client = useContext(ChainlitContext);\n  const session = useRecoilValue(sessionState);\n  const askUser = useRecoilValue(askUserState);\n  const sessionId = useRecoilValue(sessionIdState);\n\n  const resetChatSettings = useResetRecoilState(chatSettingsInputsState);\n  const resetSessionId = useResetRecoilState(sessionIdState);\n  const resetChatSettingsValue = useResetRecoilState(chatSettingsValueState);\n\n  const setFirstUserInteraction = useSetRecoilState(firstUserInteraction);\n  const setLoading = useSetRecoilState(loadingState);\n  const setMessages = useSetRecoilState(messagesState);\n  const setElements = useSetRecoilState(elementState);\n  const setTasklists = useSetRecoilState(tasklistState);\n  const setActions = useSetRecoilState(actionState);\n  const setTokenCount = useSetRecoilState(tokenCountState);\n  const setIdToResume = useSetRecoilState(threadIdToResumeState);\n  const setSideView = useSetRecoilState(sideViewState);\n  const setCurrentThreadId = useSetRecoilState(currentThreadIdState);\n  const setFavoriteMessages = useSetRecoilState(favoriteMessagesState);\n\n  const clear = useCallback(() => {\n    session?.socket.emit('clear_session');\n    session?.socket.disconnect();\n    setIdToResume(undefined);\n    resetSessionId();\n    setFirstUserInteraction(undefined);\n    setMessages([]);\n    setElements([]);\n    setTasklists([]);\n    setActions([]);\n    setTokenCount(0);\n    resetChatSettings();\n    resetChatSettingsValue();\n    setSideView(undefined);\n    setCurrentThreadId(undefined);\n  }, [session]);\n\n  const sendMessage = useCallback(\n    (\n      message: PartialBy<IStep, 'createdAt' | 'id'>,\n      fileReferences: IFileRef[] = []\n    ) => {\n      if (!message.id) {\n        message.id = uuidv4();\n      }\n      if (!message.createdAt) {\n        message.createdAt = new Date().toISOString();\n      }\n      setMessages((oldMessages) => addMessage(oldMessages, message as IStep));\n\n      session?.socket.emit('client_message', { message, fileReferences });\n    },\n    [session?.socket]\n  );\n\n  const editMessage = useCallback(\n    (message: IStep) => {\n      session?.socket.emit('edit_message', { message });\n    },\n    [session?.socket]\n  );\n\n  const toggleMessageFavorite = useCallback(\n    (message: IStep) => {\n      const favorite = !(message.metadata?.favorite ?? false);\n      const updatedMetadata = {\n        ...(message.metadata || {}),\n        favorite\n      };\n\n      setMessages((oldMessages) =>\n        oldMessages.map((item) =>\n          item.id === message.id\n            ? { ...item, metadata: { ...(item.metadata || {}), favorite } }\n            : item\n        )\n      );\n\n      const nextMessage: IStep = {\n        ...message,\n        metadata: updatedMetadata\n      };\n\n      setFavoriteMessages((oldFavorites) => {\n        if (favorite) {\n          const filtered = oldFavorites.filter(\n            (step) => step.id !== message.id\n          );\n          return [nextMessage, ...filtered];\n        }\n        return oldFavorites.filter((step) => step.id !== message.id);\n      });\n\n      session?.socket.emit('message_favorite', { message: nextMessage });\n    },\n    [session?.socket, setFavoriteMessages, setMessages]\n  );\n\n  const windowMessage = useCallback(\n    (data: any) => {\n      session?.socket.emit('window_message', data);\n    },\n    [session?.socket]\n  );\n\n  const startAudioStream = useCallback(() => {\n    session?.socket.emit('audio_start');\n  }, [session?.socket]);\n\n  const sendAudioChunk = useCallback(\n    (\n      isStart: boolean,\n      mimeType: string,\n      elapsedTime: number,\n      data: Int16Array\n    ) => {\n      session?.socket.emit('audio_chunk', {\n        isStart,\n        mimeType,\n        elapsedTime,\n        data\n      });\n    },\n    [session?.socket]\n  );\n\n  const endAudioStream = useCallback(() => {\n    session?.socket.emit('audio_end');\n  }, [session?.socket]);\n\n  const replyMessage = useCallback(\n    (message: IStep) => {\n      if (askUser) {\n        if (askUser.parentId) message.parentId = askUser.parentId;\n        setMessages((oldMessages) => addMessage(oldMessages, message));\n        askUser.callback(message);\n      }\n    },\n    [askUser]\n  );\n\n  const updateChatSettings = useCallback(\n    (values: object) => {\n      session?.socket.emit('chat_settings_change', values);\n    },\n    [session?.socket]\n  );\n\n  const editChatSettings = useCallback(\n    (values: object) => {\n      session?.socket.emit('chat_settings_edit', values);\n    },\n    [session?.socket]\n  );\n\n  const stopTask = useCallback(() => {\n    setMessages((oldMessages) =>\n      oldMessages.map((m) => {\n        m.streaming = false;\n        return m;\n      })\n    );\n\n    setLoading(false);\n\n    session?.socket.emit('stop');\n  }, [session?.socket]);\n\n  const uploadFile = useCallback(\n    (file: File, onProgress: (progress: number) => void, parentId?: string) => {\n      return client.uploadFile(file, onProgress, sessionId, parentId);\n    },\n    [sessionId]\n  );\n\n  return {\n    uploadFile,\n    clear,\n    replyMessage,\n    sendMessage,\n    editMessage,\n    windowMessage,\n    startAudioStream,\n    sendAudioChunk,\n    endAudioStream,\n    stopTask,\n    setIdToResume,\n    updateChatSettings,\n    editChatSettings,\n    toggleMessageFavorite\n  };\n};\n\nexport { useChatInteract };\n","import { isEqual } from 'lodash';\n\nimport { IStep } from '..';\n\nconst nestMessages = (messages: IStep[]): IStep[] => {\n  let nestedMessages: IStep[] = [];\n\n  for (const message of messages) {\n    nestedMessages = addMessage(nestedMessages, message);\n  }\n\n  return nestedMessages;\n};\n\nconst isLastMessage = (messages: IStep[], index: number) => {\n  if (messages.length - 1 === index) {\n    return true;\n  }\n\n  for (let i = index + 1; i < messages.length; i++) {\n    if (messages[i].streaming) {\n      continue;\n    } else {\n      return false;\n    }\n  }\n\n  return true;\n};\n\n// Nested messages utils\n\nconst addMessage = (messages: IStep[], message: IStep): IStep[] => {\n  if (hasMessageById(messages, message.id)) {\n    return updateMessageById(messages, message.id, message);\n  } else if ('parentId' in message && message.parentId) {\n    return addMessageToParent(messages, message.parentId, message);\n  } else if ('indent' in message && message.indent && message.indent > 0) {\n    return addIndentMessage(messages, message.indent, message);\n  } else {\n    return [...messages, message];\n  }\n};\n\nconst addIndentMessage = (\n  messages: IStep[],\n  indent: number,\n  newMessage: IStep,\n  currentIndentation: number = 0\n): IStep[] => {\n  if (messages.length === 0) {\n    return [newMessage];\n  }\n\n  const index = messages.length - 1;\n  const msg = messages[index];\n  const msgSteps = msg.steps || [];\n\n  if (currentIndentation + 1 === indent) {\n    const updatedMsg = {\n      ...msg,\n      steps: [...msgSteps, newMessage]\n    };\n    const nextMessages = [...messages];\n    nextMessages[index] = updatedMsg;\n    return nextMessages;\n  } else {\n    const updatedSteps = addIndentMessage(\n      msgSteps,\n      indent,\n      newMessage,\n      currentIndentation + 1\n    );\n\n    if (updatedSteps === msgSteps) {\n      return messages;\n    }\n\n    const nextMessages = [...messages];\n    nextMessages[index] = { ...msg, steps: updatedSteps };\n    return nextMessages;\n  }\n};\n\nconst addMessageToParent = (\n  messages: IStep[],\n  parentId: string,\n  newMessage: IStep\n): IStep[] => {\n  let hasChanges = false;\n\n  const nextMessages = messages.map((msg) => {\n    if (isEqual(msg.id, parentId)) {\n      hasChanges = true;\n      return {\n        ...msg,\n        steps: msg.steps ? [...msg.steps, newMessage] : [newMessage]\n      };\n    } else if (hasMessageById(messages, parentId) && msg.steps) {\n      const updatedSteps = addMessageToParent(msg.steps, parentId, newMessage);\n      if (updatedSteps !== msg.steps) {\n        hasChanges = true;\n        return { ...msg, steps: updatedSteps };\n      }\n    }\n    return msg;\n  });\n\n  return hasChanges ? nextMessages : messages;\n};\n\nconst findMessageById = (\n  messages: IStep[],\n  messageId: string\n): IStep | undefined => {\n  for (const message of messages) {\n    if (isEqual(message.id, messageId)) {\n      return message;\n    } else if (message.steps && message.steps.length > 0) {\n      const foundMessage = findMessageById(message.steps, messageId);\n      if (foundMessage) {\n        return foundMessage;\n      }\n    }\n  }\n  return undefined;\n};\n\nconst hasMessageById = (messages: IStep[], messageId: string): boolean => {\n  return findMessageById(messages, messageId) !== undefined;\n};\n\nconst updateMessageById = (\n  messages: IStep[],\n  messageId: string,\n  updatedMessage: IStep\n): IStep[] => {\n  let hasChanges = false;\n  const nextMessages = messages.map((msg) => {\n    if (isEqual(msg.id, messageId)) {\n      hasChanges = true;\n      return { ...msg, ...updatedMessage };\n    } else if (msg.steps) {\n      const updatedSteps = updateMessageById(\n        msg.steps,\n        messageId,\n        updatedMessage\n      );\n      if (updatedSteps !== msg.steps) {\n        hasChanges = true;\n        return { ...msg, steps: updatedSteps };\n      }\n    }\n    return msg;\n  });\n\n  return hasChanges ? nextMessages : messages;\n};\n\nconst deleteMessageById = (messages: IStep[], messageId: string): IStep[] => {\n  let hasChanges = false;\n  const nextMessages = messages.reduce((acc, msg) => {\n    if (msg.id === messageId) {\n      hasChanges = true;\n      return acc;\n    } else if (msg.steps) {\n      const updatedSteps = deleteMessageById(msg.steps, messageId);\n      if (updatedSteps !== msg.steps) {\n        hasChanges = true;\n        acc.push({ ...msg, steps: updatedSteps });\n        return acc;\n      }\n    }\n    acc.push(msg);\n    return acc;\n  }, [] as IStep[]);\n\n  return hasChanges ? nextMessages : messages;\n};\n\nconst updateMessageContentById = (\n  messages: IStep[],\n  messageId: number | string,\n  updatedContent: string,\n  isSequence: boolean,\n  isInput: boolean\n): IStep[] => {\n  let hasChanges = false;\n  const nextMessages = messages.map((msg) => {\n    if (isEqual(msg.id, messageId)) {\n      hasChanges = true;\n      const newMsg = { ...msg };\n      if ('content' in newMsg && newMsg.content !== undefined) {\n        if (isSequence) {\n          newMsg.content = updatedContent;\n        } else {\n          newMsg.content += updatedContent;\n        }\n      } else if (isInput) {\n        if ('input' in newMsg && newMsg.input !== undefined) {\n          if (isSequence) {\n            newMsg.input = updatedContent;\n          } else {\n            newMsg.input += updatedContent;\n          }\n        }\n      } else {\n        if ('output' in newMsg && newMsg.output !== undefined) {\n          if (isSequence) {\n            newMsg.output = updatedContent;\n          } else {\n            newMsg.output += updatedContent;\n          }\n        }\n      }\n      return newMsg;\n    } else if (msg.steps) {\n      const updatedSteps = updateMessageContentById(\n        msg.steps,\n        messageId,\n        updatedContent,\n        isSequence,\n        isInput\n      );\n      if (updatedSteps !== msg.steps) {\n        hasChanges = true;\n        return { ...msg, steps: updatedSteps };\n      }\n    }\n    return msg;\n  });\n\n  return hasChanges ? nextMessages : messages;\n};\n\nexport {\n  addMessageToParent,\n  addMessage,\n  deleteMessageById,\n  hasMessageById,\n  isLastMessage,\n  nestMessages,\n  updateMessageById,\n  updateMessageContentById\n};\n","import { createContext } from 'react';\n\nimport { ChainlitAPI } from './api';\n\nconst defaultChainlitContext = undefined;\n\nconst ChainlitContext = createContext<ChainlitAPI>(\n  new ChainlitAPI('http://localhost:8000', 'webapp')\n);\n\nexport { ChainlitContext, defaultChainlitContext };\n","import { useEffect } from 'react';\nimport { IAuthConfig } from 'src/index';\n\nimport { useApi } from '../api';\nimport { useAuthState } from './state';\n\nexport const useAuthConfig = () => {\n  const { authConfig, setAuthConfig } = useAuthState();\n  const { data: authConfigData, isLoading } = useApi<IAuthConfig>(\n    authConfig ? null : '/auth/config'\n  );\n\n  useEffect(() => {\n    if (authConfigData) {\n      setAuthConfig(authConfigData);\n    }\n  }, [authConfigData, setAuthConfig]);\n\n  return { authConfig, isLoading };\n};\n","import { useContext, useMemo } from 'react';\nimport { ChainlitAPI } from 'src/api';\nimport { ChainlitContext } from 'src/context';\nimport useSWR, { SWRConfig, SWRConfiguration } from 'swr';\n\nimport { useAuthState } from './auth/state';\n\nconst fetcher = async (client: ChainlitAPI, endpoint: string) => {\n  const res = await client.get(endpoint);\n  return res?.json();\n};\n\nconst cloneClient = (client: ChainlitAPI): ChainlitAPI => {\n  // Shallow clone API client.\n  // TODO: Move me to core API.\n\n  // Create new client\n  const newClient = new ChainlitAPI('', 'webapp');\n\n  // Assign old properties to new client\n  Object.assign(newClient, client);\n\n  return newClient;\n};\n\n/**\n * React hook for cached API data fetching using SWR (stale-while-revalidate).\n * Optimized for GET requests with automatic caching and revalidation.\n *\n * Key features:\n * - Automatic data caching and revalidation\n * - Integration with React component lifecycle\n * - Loading state management\n * - Recoil state integration for global state\n * - Memoized fetcher function to prevent unnecessary rerenders\n *\n * @param path - API endpoint path or null to disable the request\n * @param config - Optional SWR configuration\n * @returns SWR response object containing:\n *          - data: The fetched data\n *          - error: Any error that occurred\n *          - isValidating: Whether a request is in progress\n *          - mutate: Function to mutate the cached data\n *\n * @example\n * const { data, error, isValidating } = useApi<UserData>('/user');\n */\nfunction useApi<T>(\n  path?: string | null,\n  { ...swrConfig }: SWRConfiguration = {}\n) {\n  const client = useContext(ChainlitContext);\n  const { setUser } = useAuthState();\n\n  // Memoize the fetcher function to avoid recreating it on every render\n  const memoizedFetcher = useMemo(\n    () =>\n      ([url]: [url: string]) => {\n        if (!swrConfig.onErrorRetry) {\n          swrConfig.onErrorRetry = (...args) => {\n            const [err] = args;\n\n            // Don't do automatic retry for 401 - it just means we're not logged in (yet).\n            if (err.status === 401) {\n              setUser(null);\n              return;\n            }\n\n            // Fall back to default behavior.\n            return SWRConfig.defaultValue.onErrorRetry(...args);\n          };\n        }\n\n        const useApiClient = cloneClient(client);\n        useApiClient.on401 = useApiClient.onError = undefined;\n        return fetcher(useApiClient, url);\n      },\n    [client]\n  );\n\n  // Use a stable key for useSWR\n  const swrKey = useMemo(() => {\n    return path ? [path] : null;\n  }, [path]);\n\n  return useSWR<T, Error>(swrKey, memoizedFetcher, swrConfig);\n}\n\nexport { useApi, fetcher };\n","import { useRecoilState, useSetRecoilState } from 'recoil';\nimport { authState, threadHistoryState, userState } from 'src/state';\n\nexport const useAuthState = () => {\n  const [authConfig, setAuthConfig] = useRecoilState(authState);\n  const [user, setUser] = useRecoilState(userState);\n  const setThreadHistory = useSetRecoilState(threadHistoryState);\n\n  return {\n    authConfig,\n    setAuthConfig,\n    user,\n    setUser,\n    setThreadHistory\n  };\n};\n","import { useContext } from 'react';\nimport { ChainlitContext } from 'src/index';\n\nimport { useAuthState } from './state';\n\nexport const useSessionManagement = () => {\n  const apiClient = useContext(ChainlitContext);\n  const { setUser, setThreadHistory } = useAuthState();\n\n  const logout = async (reload = false): Promise<void> => {\n    await apiClient.logout();\n    setUser(undefined);\n    setThreadHistory(undefined);\n\n    if (reload) {\n      window.location.reload();\n    }\n  };\n\n  return { logout };\n};\n","import { useEffect } from 'react';\nimport { IUser } from 'src/types';\n\nimport { useApi } from '../api';\nimport { useAuthState } from './state';\n\nexport const useUserManagement = () => {\n  const { user, setUser } = useAuthState();\n\n  const {\n    data: userData,\n    error,\n    mutate: setUserFromAPI\n  } = useApi<IUser>('/user');\n\n  useEffect(() => {\n    if (userData) {\n      setUser(userData);\n    }\n  }, [userData, setUser]);\n\n  useEffect(() => {\n    if (error) {\n      setUser(null);\n    }\n  }, [error]);\n\n  return { user, setUserFromAPI };\n};\n","import { IAuthConfig, IUser } from 'src/types';\n\nimport { useAuthConfig } from './config';\nimport { useSessionManagement } from './sessionManagement';\nimport { useUserManagement } from './userManagement';\n\nexport const useAuth = () => {\n  const { authConfig } = useAuthConfig();\n  const { logout } = useSessionManagement();\n  const { user, setUserFromAPI } = useUserManagement();\n\n  const isReady =\n    !!authConfig && (!authConfig.requireLogin || user !== undefined);\n\n  if (authConfig && !authConfig.requireLogin) {\n    return {\n      data: authConfig,\n      user: null,\n      isReady,\n      isAuthenticated: true,\n      logout: () => Promise.resolve(),\n      setUserFromAPI: () => Promise.resolve()\n    };\n  }\n\n  return {\n    data: authConfig,\n    user,\n    isReady,\n    isAuthenticated: !!user,\n    logout,\n    setUserFromAPI\n  };\n};\n\nexport type { IAuthConfig, IUser };\n","import { IElement, IThread, IUser } from 'src/types';\n\nimport { IAction } from 'src/types/action';\nimport { IFeedback } from 'src/types/feedback';\n\nexport * from './hooks/auth';\nexport * from './hooks/api';\n\nexport interface IThreadFilters {\n  search?: string;\n  feedback?: number;\n}\n\nexport interface IPageInfo {\n  hasNextPage: boolean;\n  endCursor?: string;\n}\n\nexport interface IPagination {\n  first: number;\n  cursor?: string | number;\n}\n\nexport class ClientError extends Error {\n  status: number;\n  detail?: string;\n\n  constructor(message: string, status: number, detail?: string) {\n    super(message);\n    this.status = status;\n    this.detail = detail;\n  }\n\n  toString() {\n    if (this.detail) {\n      return `${this.message}: ${this.detail}`;\n    } else {\n      return this.message;\n    }\n  }\n}\n\ntype Payload = FormData | any;\n\nexport class APIBase {\n  constructor(\n    public httpEndpoint: string,\n    public type: 'webapp' | 'copilot' | 'teams' | 'slack' | 'discord',\n    public additionalQueryParams?: Record<string, string>,\n    public on401?: () => void,\n    public onError?: (error: ClientError) => void\n  ) {}\n\n  buildEndpoint(path: string) {\n    let fullUrl = `${this.httpEndpoint}${path}`;\n    if (this.httpEndpoint.endsWith('/')) {\n      // remove trailing slash on httpEndpoint\n      fullUrl = `${this.httpEndpoint.slice(0, -1)}${path}`;\n    }\n\n    const url = new URL(fullUrl);\n\n    // Add additionalQueryParams for all API calls\n    if (this.additionalQueryParams) {\n      const params = new URLSearchParams(this.additionalQueryParams);\n      const separator = url.search ? '&' : '?';\n      url.search = url.search + `${separator}${params.toString()}`;\n    }\n\n    return url.toString();\n  }\n\n  private async getDetailFromErrorResponse(\n    res: Response\n  ): Promise<string | undefined> {\n    try {\n      const body = await res.json();\n      return body?.detail;\n    } catch (error: any) {\n      console.error('Unable to parse error response', error);\n    }\n    return undefined;\n  }\n\n  private handleRequestError(error: any) {\n    if (error instanceof ClientError) {\n      if (error.status === 401 && this.on401) {\n        this.on401();\n      }\n      if (this.onError) {\n        this.onError(error);\n      }\n    }\n    console.error(error);\n  }\n\n  /**\n   * Low-level HTTP request handler for direct API interactions.\n   * Provides full control over HTTP methods, request configuration, and error handling.\n   *\n   * Key features:\n   * - Supports all HTTP methods (GET, POST, PUT, PATCH, DELETE)\n   * - Handles both FormData and JSON payloads\n   * - Manages authentication headers\n   * - Custom error handling with ClientError class\n   * - Support for request cancellation via AbortSignal\n   *\n   * @param method - HTTP method to use (GET, POST, etc.)\n   * @param path - API endpoint path\n   * @param data - Optional request payload (FormData or JSON-serializable data)\n   * @param signal - Optional AbortSignal for request cancellation\n   * @returns Promise<Response>\n   * @throws ClientError for HTTP errors, including 401 unauthorized\n   */\n  async fetch(\n    method: string,\n    path: string,\n    data?: Payload,\n    signal?: AbortSignal,\n    headers: { Authorization?: string; 'Content-Type'?: string } = {}\n  ): Promise<Response> {\n    try {\n      let body;\n\n      if (data instanceof FormData) {\n        body = data;\n      } else {\n        headers['Content-Type'] = 'application/json';\n        body = data ? JSON.stringify(data) : null;\n      }\n\n      const res = await fetch(this.buildEndpoint(path), {\n        method,\n        credentials: 'include',\n        headers,\n        signal,\n        body\n      });\n\n      if (!res.ok) {\n        const detail = await this.getDetailFromErrorResponse(res);\n\n        throw new ClientError(res.statusText, res.status, detail);\n      }\n\n      return res;\n    } catch (error: any) {\n      this.handleRequestError(error);\n      throw error;\n    }\n  }\n\n  async get(endpoint: string) {\n    return await this.fetch('GET', endpoint);\n  }\n\n  async post(endpoint: string, data: Payload, signal?: AbortSignal) {\n    return await this.fetch('POST', endpoint, data, signal);\n  }\n\n  async put(endpoint: string, data: Payload) {\n    return await this.fetch('PUT', endpoint, data);\n  }\n\n  async patch(endpoint: string, data: Payload) {\n    return await this.fetch('PATCH', endpoint, data);\n  }\n\n  async delete(endpoint: string, data: Payload) {\n    return await this.fetch('DELETE', endpoint, data);\n  }\n}\n\nexport class ChainlitAPI extends APIBase {\n  async headerAuth() {\n    const res = await this.post(`/auth/header`, {});\n    return res.json();\n  }\n\n  async jwtAuth(token: string) {\n    const res = await this.fetch('POST', '/auth/jwt', undefined, undefined, {\n      Authorization: `Bearer ${token}`\n    });\n    return res.json();\n  }\n\n  async stickyCookie(sessionId: string) {\n    const res = await this.fetch('POST', '/set-session-cookie', {\n      session_id: sessionId\n    });\n    return res.json();\n  }\n\n  async passwordAuth(data: FormData) {\n    const res = await this.post(`/login`, data);\n    return res.json();\n  }\n\n  async getUser(): Promise<IUser> {\n    const res = await this.get(`/user`);\n    return res.json();\n  }\n\n  async logout() {\n    const res = await this.post(`/logout`, {});\n    return res.json();\n  }\n\n  async setFeedback(\n    feedback: IFeedback,\n    sessionId: string\n  ): Promise<{ success: boolean; feedbackId: string }> {\n    const res = await this.put(`/feedback`, { feedback, sessionId });\n    return res.json();\n  }\n\n  async deleteFeedback(feedbackId: string): Promise<{ success: boolean }> {\n    const res = await this.delete(`/feedback`, { feedbackId });\n    return res.json();\n  }\n\n  async listThreads(\n    pagination: IPagination,\n    filter: IThreadFilters\n  ): Promise<{\n    pageInfo: IPageInfo;\n    data: IThread[];\n  }> {\n    const res = await this.post(`/project/threads`, { pagination, filter });\n\n    return res.json();\n  }\n\n  async renameThread(threadId: string, name: string) {\n    const res = await this.put(`/project/thread`, { threadId, name });\n\n    return res.json();\n  }\n\n  async deleteThread(threadId: string) {\n    const res = await this.delete(`/project/thread`, { threadId });\n\n    return res.json();\n  }\n\n  uploadFile(\n    file: File,\n    onProgress: (progress: number) => void,\n    sessionId: string,\n    parentId?: string\n  ) {\n    const xhr = new XMLHttpRequest();\n    xhr.withCredentials = true;\n\n    const promise = new Promise<{ id: string }>((resolve, reject) => {\n      const formData = new FormData();\n      formData.append('file', file);\n\n      const ask_parent_id = parentId ? `&ask_parent_id=${parentId}` : '';\n      xhr.open(\n        'POST',\n        this.buildEndpoint(\n          `/project/file?session_id=${sessionId}${ask_parent_id}`\n        ),\n        true\n      );\n\n      // Track the progress of the upload\n      xhr.upload.onprogress = function (event) {\n        if (event.lengthComputable) {\n          const percentage = (event.loaded / event.total) * 100;\n          onProgress(percentage);\n        }\n      };\n\n      xhr.onload = function () {\n        if (xhr.status === 200) {\n          const response = JSON.parse(xhr.responseText);\n          resolve(response);\n          return;\n        }\n        const contentType = xhr.getResponseHeader('Content-Type');\n        if (contentType && contentType.includes('application/json')) {\n          const response = JSON.parse(xhr.responseText);\n          reject(response.detail);\n        } else {\n          reject('Upload failed');\n        }\n      };\n\n      xhr.onerror = function () {\n        reject('Upload error');\n      };\n\n      xhr.send(formData);\n    });\n\n    return { xhr, promise };\n  }\n\n  async callAction(action: IAction, sessionId: string) {\n    const res = await this.post(`/project/action`, { sessionId, action });\n\n    return res.json();\n  }\n\n  async updateElement(element: IElement, sessionId: string) {\n    const res = await this.put(`/project/element`, { sessionId, element });\n\n    return res.json();\n  }\n\n  async deleteElement(element: IElement, sessionId: string) {\n    const res = await this.delete(`/project/element`, { sessionId, element });\n\n    return res.json();\n  }\n\n  async connectStdioMCP(sessionId: string, name: string, fullCommand: string) {\n    const res = await this.post(`/mcp`, {\n      sessionId,\n      name,\n      fullCommand,\n      clientType: 'stdio'\n    });\n    return res.json();\n  }\n\n  async connectSseMCP(\n    sessionId: string,\n    name: string,\n    url: string,\n    headers?: Record<string, string>\n  ) {\n    const res = await this.post(`/mcp`, {\n      sessionId,\n      name,\n      url,\n      ...(headers ? { headers } : {}),\n      clientType: 'sse'\n    });\n    return res.json();\n  }\n\n  async connectStreamableHttpMCP(\n    sessionId: string,\n    name: string,\n    url: string,\n    headers?: Record<string, string>\n  ) {\n    const res = await this.post(`/mcp`, {\n      sessionId,\n      name,\n      url,\n      ...(headers ? { headers } : {}),\n      clientType: 'streamable-http'\n    });\n    return res.json();\n  }\n\n  async disconnectMcp(sessionId: string, name: string) {\n    const res = await this.delete(`/mcp`, { sessionId, name });\n    return res.json();\n  }\n\n  getElementUrl(id: string, sessionId: string) {\n    const queryParams = `?session_id=${sessionId}`;\n    return this.buildEndpoint(`/project/file/${id}${queryParams}`);\n  }\n\n  getLogoEndpoint(theme: string, configuredLogoUrl?: string) {\n    if (configuredLogoUrl) return configuredLogoUrl;\n    return this.buildEndpoint(`/logo?theme=${theme}`);\n  }\n\n  getOAuthEndpoint(provider: string) {\n    return this.buildEndpoint(`/auth/oauth/${provider}`);\n  }\n  async shareThread(\n    threadId: string,\n    isShared: boolean\n  ): Promise<{ success: boolean }> {\n    const res = await this.put(`/project/thread/share`, {\n      threadId,\n      isShared\n    });\n    return res.json();\n  }\n}\n","import { useRecoilValue } from 'recoil';\n\nimport {\n  currentThreadIdState,\n  firstUserInteraction,\n  messagesState\n} from './state';\n\nconst useChatMessages = () => {\n  const messages = useRecoilValue(messagesState);\n  const firstInteraction = useRecoilValue(firstUserInteraction);\n  const threadId = useRecoilValue(currentThreadIdState);\n\n  return {\n    threadId,\n    messages,\n    firstInteraction\n  };\n};\n\nexport { useChatMessages };\n","import { debounce } from 'lodash';\nimport { useCallback, useContext, useEffect } from 'react';\nimport {\n  useRecoilState,\n  useRecoilValue,\n  useResetRecoilState,\n  useSetRecoilState\n} from 'recoil';\nimport io from 'socket.io-client';\nimport { toast } from 'sonner';\nimport {\n  actionState,\n  askUserState,\n  audioConnectionState,\n  callFnState,\n  chatProfileState,\n  chatSettingsInputsState,\n  chatSettingsValueState,\n  commandsState,\n  currentThreadIdState,\n  elementState,\n  favoriteMessagesState,\n  firstUserInteraction,\n  isAiSpeakingState,\n  loadingState,\n  mcpState,\n  messagesState,\n  modesState,\n  resumeThreadErrorState,\n  sessionIdState,\n  sessionState,\n  sideViewState,\n  tasklistState,\n  threadIdToResumeState,\n  tokenCountState,\n  wavRecorderState,\n  wavStreamPlayerState\n} from 'src/state';\nimport {\n  IAction,\n  ICommand,\n  IElement,\n  IMessageElement,\n  IMode,\n  IStep,\n  ITasklistElement,\n  IThread\n} from 'src/types';\nimport {\n  addMessage,\n  deleteMessageById,\n  updateMessageById,\n  updateMessageContentById\n} from 'src/utils/message';\n\nimport { OutputAudioChunk } from './types/audio';\n\nimport { ChainlitContext } from './context';\nimport type { IToken } from './useChatData';\n\nconst useChatSession = () => {\n  const client = useContext(ChainlitContext);\n  const sessionId = useRecoilValue(sessionIdState);\n\n  const [session, setSession] = useRecoilState(sessionState);\n  const setIsAiSpeaking = useSetRecoilState(isAiSpeakingState);\n  const setAudioConnection = useSetRecoilState(audioConnectionState);\n  const resetChatSettingsValue = useResetRecoilState(chatSettingsValueState);\n  const setChatSettingsValue = useSetRecoilState(chatSettingsValueState);\n  const setFirstUserInteraction = useSetRecoilState(firstUserInteraction);\n  const setLoading = useSetRecoilState(loadingState);\n  const setMcps = useSetRecoilState(mcpState);\n  const wavStreamPlayer = useRecoilValue(wavStreamPlayerState);\n  const wavRecorder = useRecoilValue(wavRecorderState);\n  const setMessages = useSetRecoilState(messagesState);\n  const setAskUser = useSetRecoilState(askUserState);\n  const setCallFn = useSetRecoilState(callFnState);\n  const setCommands = useSetRecoilState(commandsState);\n  const setModes = useSetRecoilState(modesState);\n  const setSideView = useSetRecoilState(sideViewState);\n  const setElements = useSetRecoilState(elementState);\n  const setTasklists = useSetRecoilState(tasklistState);\n  const setActions = useSetRecoilState(actionState);\n  const setChatSettingsInputs = useSetRecoilState(chatSettingsInputsState);\n  const setTokenCount = useSetRecoilState(tokenCountState);\n  const [chatProfile, setChatProfile] = useRecoilState(chatProfileState);\n  const idToResume = useRecoilValue(threadIdToResumeState);\n  const setThreadResumeError = useSetRecoilState(resumeThreadErrorState);\n  const setFavoriteMessages = useSetRecoilState(favoriteMessagesState);\n\n  const [currentThreadId, setCurrentThreadId] =\n    useRecoilState(currentThreadIdState);\n\n  // Use currentThreadId as thread id in websocket header\n  useEffect(() => {\n    if (session?.socket) {\n      session.socket.auth['threadId'] = currentThreadId || '';\n    }\n  }, [currentThreadId]);\n\n  const _connect = useCallback(\n    async ({\n      transports,\n      userEnv\n    }: {\n      transports?: string[];\n      userEnv: Record<string, string>;\n    }) => {\n      const { protocol, host, pathname } = new URL(client.httpEndpoint);\n      const uri = `${protocol}//${host}`;\n      const path =\n        pathname && pathname !== '/'\n          ? `${pathname}/ws/socket.io`\n          : '/ws/socket.io';\n\n      try {\n        await client.stickyCookie(sessionId);\n      } catch (err) {\n        console.error(`Failed to set sticky session cookie: ${err}`);\n      }\n\n      const socket = io(uri, {\n        path,\n        withCredentials: true,\n        transports,\n        auth: {\n          clientType: client.type,\n          sessionId,\n          threadId: idToResume || '',\n          userEnv: JSON.stringify(userEnv),\n          chatProfile: chatProfile ? encodeURIComponent(chatProfile) : ''\n        }\n      });\n      setSession((old) => {\n        old?.socket?.removeAllListeners();\n        old?.socket?.close();\n        return {\n          socket\n        };\n      });\n\n      socket.on('connect', () => {\n        socket.emit('connection_successful');\n        setSession((s) => ({ ...s!, error: false }));\n        socket.emit('fetch_favorites');\n        setMcps((prev) =>\n          prev.map((mcp) => {\n            let promise;\n            if (mcp.clientType === 'sse') {\n              promise = client.connectSseMCP(sessionId, mcp.name, mcp.url!);\n            } else if (mcp.clientType === 'streamable-http') {\n              promise = client.connectStreamableHttpMCP(\n                sessionId,\n                mcp.name,\n                mcp.url!,\n                mcp.headers || {}\n              );\n            } else {\n              promise = client.connectStdioMCP(\n                sessionId,\n                mcp.name,\n                mcp.command!\n              );\n            }\n            promise\n              .then(async ({ success, mcp }) => {\n                setMcps((prev) =>\n                  prev.map((existingMcp) => {\n                    if (existingMcp.name === mcp.name) {\n                      return {\n                        ...existingMcp,\n                        status: success ? 'connected' : 'failed',\n                        tools: mcp ? mcp.tools : existingMcp.tools\n                      };\n                    }\n                    return existingMcp;\n                  })\n                );\n              })\n              .catch(() => {\n                setMcps((prev) =>\n                  prev.map((existingMcp) => {\n                    if (existingMcp.name === mcp.name) {\n                      return {\n                        ...existingMcp,\n                        status: 'failed'\n                      };\n                    }\n                    return existingMcp;\n                  })\n                );\n              });\n            return { ...mcp, status: 'connecting' };\n          })\n        );\n      });\n\n      socket.on('connect_error', (_) => {\n        setSession((s) => ({ ...s!, error: true }));\n      });\n\n      socket.on('task_start', () => {\n        setLoading(true);\n      });\n\n      socket.on('task_end', () => {\n        setLoading(false);\n      });\n\n      socket.on('reload', () => {\n        socket.emit('clear_session');\n        window.location.reload();\n      });\n\n      socket.on('audio_connection', async (state: 'on' | 'off') => {\n        if (state === 'on') {\n          let isFirstChunk = true;\n          const startTime = Date.now();\n          const mimeType = 'pcm16';\n          try {\n            await wavRecorder.begin();\n            await wavStreamPlayer.connect();\n            await wavRecorder.record(async (data) => {\n              const elapsedTime = Date.now() - startTime;\n              socket.emit('audio_chunk', {\n                isStart: isFirstChunk,\n                mimeType,\n                elapsedTime,\n                data: data.mono\n              });\n              isFirstChunk = false;\n            });\n            wavStreamPlayer.onStop = () => setIsAiSpeaking(false);\n          } catch {\n            try {\n              await wavRecorder.end();\n            } catch {\n              // ignored\n            }\n            await wavStreamPlayer.interrupt();\n            socket.emit('audio_end');\n            setAudioConnection('off');\n            return;\n          }\n        } else {\n          await wavRecorder.end();\n          await wavStreamPlayer.interrupt();\n        }\n        setAudioConnection(state);\n      });\n\n      socket.on('audio_chunk', (chunk: OutputAudioChunk) => {\n        wavStreamPlayer.add16BitPCM(chunk.data, chunk.track);\n        setIsAiSpeaking(true);\n      });\n\n      socket.on('audio_interrupt', () => {\n        wavStreamPlayer.interrupt();\n      });\n\n      socket.on('resume_thread', (thread: IThread) => {\n        const isReadOnlyView = Boolean(\n          (thread as any)?.metadata?.viewer_read_only\n        );\n        if (!isReadOnlyView && idToResume && thread.id !== idToResume) {\n          window.location.href = `/thread/${thread.id}`;\n        }\n        if (!isReadOnlyView && idToResume) {\n          setCurrentThreadId(thread.id);\n        }\n        let messages: IStep[] = [];\n        for (const step of thread.steps) {\n          messages = addMessage(messages, step);\n        }\n        if (thread.metadata?.chat_profile) {\n          setChatProfile(thread.metadata?.chat_profile);\n        }\n        if (thread.metadata?.chat_settings) {\n          setChatSettingsValue(thread.metadata?.chat_settings);\n        }\n        setMessages(messages);\n        const elements = thread.elements || [];\n        setTasklists(\n          (elements as ITasklistElement[]).filter((e) => e.type === 'tasklist')\n        );\n        setElements(\n          (elements as IMessageElement[]).filter(\n            (e) => ['avatar', 'tasklist'].indexOf(e.type) === -1\n          )\n        );\n      });\n\n      socket.on('resume_thread_error', (error?: string) => {\n        setThreadResumeError(error);\n      });\n\n      socket.on('new_message', (message: IStep) => {\n        setMessages((oldMessages) => addMessage(oldMessages, message));\n      });\n\n      socket.on(\n        'first_interaction',\n        (event: { interaction: string; thread_id: string }) => {\n          setFirstUserInteraction(event.interaction);\n          setCurrentThreadId(event.thread_id);\n        }\n      );\n\n      socket.on('update_message', (message: IStep) => {\n        setMessages((oldMessages) =>\n          updateMessageById(oldMessages, message.id, message)\n        );\n      });\n\n      socket.on('delete_message', (message: IStep) => {\n        setMessages((oldMessages) =>\n          deleteMessageById(oldMessages, message.id)\n        );\n      });\n\n      socket.on('stream_start', (message: IStep) => {\n        setMessages((oldMessages) => addMessage(oldMessages, message));\n      });\n\n      socket.on(\n        'stream_token',\n        ({ id, token, isSequence, isInput }: IToken) => {\n          setMessages((oldMessages) =>\n            updateMessageContentById(\n              oldMessages,\n              id,\n              token,\n              isSequence,\n              isInput\n            )\n          );\n        }\n      );\n\n      socket.on('ask', ({ msg, spec }, callback) => {\n        setAskUser({ spec, callback, parentId: msg.parentId });\n        setMessages((oldMessages) => addMessage(oldMessages, msg));\n\n        setLoading(false);\n      });\n\n      socket.on('ask_timeout', () => {\n        setAskUser(undefined);\n        setLoading(false);\n      });\n\n      socket.on('clear_ask', () => {\n        setAskUser(undefined);\n      });\n\n      socket.on('call_fn', ({ name, args }, callback) => {\n        setCallFn({ name, args, callback });\n      });\n\n      socket.on('clear_call_fn', () => {\n        setCallFn(undefined);\n      });\n\n      socket.on('call_fn_timeout', () => {\n        setCallFn(undefined);\n      });\n\n      socket.on('chat_settings', (inputs: any) => {\n        setChatSettingsInputs(inputs);\n        resetChatSettingsValue();\n      });\n\n      socket.on('set_commands', (commands: ICommand[]) => {\n        setCommands(commands);\n      });\n\n      socket.on('set_modes', (modes: IMode[]) => {\n        setModes(modes);\n      });\n\n      socket.on('set_favorites', (steps: IStep[]) => {\n        setFavoriteMessages(steps);\n      });\n\n      socket.on('set_sidebar_title', (title: string) => {\n        setSideView((prev) => {\n          if (prev?.title === title) return prev;\n          return { title, elements: prev?.elements || [] };\n        });\n      });\n\n      socket.on(\n        'set_sidebar_elements',\n        ({ elements, key }: { elements: IMessageElement[]; key?: string }) => {\n          if (!elements.length) {\n            setSideView(undefined);\n          } else {\n            elements.forEach((element) => {\n              if (!element.url && element.chainlitKey) {\n                element.url = client.getElementUrl(\n                  element.chainlitKey,\n                  sessionId\n                );\n              }\n            });\n            setSideView((prev) => {\n              if (prev?.key === key) return prev;\n              return { title: prev?.title || '', elements: elements, key };\n            });\n          }\n        }\n      );\n\n      socket.on('element', (element: IElement) => {\n        if (!element.url && element.chainlitKey) {\n          element.url = client.getElementUrl(element.chainlitKey, sessionId);\n        }\n\n        if (element.type === 'tasklist') {\n          setTasklists((old) => {\n            const index = old.findIndex((e) => e.id === element.id);\n            if (index === -1) {\n              return [...old, element];\n            } else {\n              return [...old.slice(0, index), element, ...old.slice(index + 1)];\n            }\n          });\n        } else {\n          setElements((old) => {\n            const index = old.findIndex((e) => e.id === element.id);\n            if (index === -1) {\n              return [...old, element];\n            } else {\n              return [...old.slice(0, index), element, ...old.slice(index + 1)];\n            }\n          });\n        }\n      });\n\n      socket.on('remove_element', (remove: { id: string }) => {\n        setElements((old) => {\n          return old.filter((e) => e.id !== remove.id);\n        });\n        setTasklists((old) => {\n          return old.filter((e) => e.id !== remove.id);\n        });\n      });\n\n      socket.on('action', (action: IAction) => {\n        setActions((old) => [...old, action]);\n      });\n\n      socket.on('remove_action', (action: IAction) => {\n        setActions((old) => {\n          const index = old.findIndex((a) => a.id === action.id);\n          if (index === -1) return old;\n          return [...old.slice(0, index), ...old.slice(index + 1)];\n        });\n      });\n\n      socket.on('token_usage', (count: number) => {\n        setTokenCount((old) => old + count);\n      });\n\n      socket.on('window_message', (data: any) => {\n        if (window.parent) {\n          window.parent.postMessage(data, '*');\n        }\n      });\n\n      socket.on('toast', (data: { message: string; type: string }) => {\n        if (!data.message) {\n          console.warn('No message received for toast.');\n          return;\n        }\n\n        switch (data.type) {\n          case 'info':\n            toast.info(data.message);\n            break;\n          case 'error':\n            toast.error(data.message);\n            break;\n          case 'success':\n            toast.success(data.message);\n            break;\n          case 'warning':\n            toast.warning(data.message);\n            break;\n          default:\n            toast(data.message);\n            break;\n        }\n      });\n    },\n    [setSession, sessionId, idToResume, chatProfile]\n  );\n\n  const connect = useCallback(debounce(_connect, 200), [_connect]);\n\n  const disconnect = useCallback(() => {\n    if (session?.socket) {\n      session.socket.removeAllListeners();\n      session.socket.close();\n    }\n  }, [session]);\n\n  return {\n    connect,\n    disconnect,\n    session,\n    sessionId,\n    chatProfile,\n    idToResume,\n    setChatProfile\n  };\n};\n\nexport { useChatSession };\n","import { useCallback } from 'react';\nimport { useRecoilState, useRecoilValue } from 'recoil';\n\nimport {\n  audioConnectionState,\n  isAiSpeakingState,\n  wavRecorderState,\n  wavStreamPlayerState\n} from './state';\nimport { useChatInteract } from './useChatInteract';\n\nconst useAudio = () => {\n  const [audioConnection, setAudioConnection] =\n    useRecoilState(audioConnectionState);\n  const wavRecorder = useRecoilValue(wavRecorderState);\n  const wavStreamPlayer = useRecoilValue(wavStreamPlayerState);\n  const isAiSpeaking = useRecoilValue(isAiSpeakingState);\n\n  const { startAudioStream, endAudioStream } = useChatInteract();\n\n  const startConversation = useCallback(async () => {\n    setAudioConnection('connecting');\n    await startAudioStream();\n  }, [startAudioStream]);\n\n  const endConversation = useCallback(async () => {\n    setAudioConnection('off');\n    await wavRecorder.end();\n    await wavStreamPlayer.interrupt();\n    await endAudioStream();\n  }, [endAudioStream, wavRecorder, wavStreamPlayer]);\n\n  return {\n    startConversation,\n    endConversation,\n    audioConnection,\n    isAiSpeaking,\n    wavRecorder,\n    wavStreamPlayer\n  };\n};\n\nexport { useAudio };\n","import { useEffect, useRef } from 'react';\nimport { useRecoilState, useRecoilValue } from 'recoil';\n\nimport { useApi, useAuth } from './api';\nimport { chatProfileState, configState } from './state';\nimport { IChainlitConfig } from './types';\n\nconst useConfig = () => {\n  const [config, setConfig] = useRecoilState(configState);\n  const { isAuthenticated } = useAuth();\n  const chatProfile = useRecoilValue(chatProfileState);\n  const language = navigator.language || 'en-US';\n  const prevChatProfileRef = useRef(chatProfile);\n\n  // Build the API URL with optional chat profile parameter\n  const apiUrl = isAuthenticated\n    ? `/project/settings?language=${language}${chatProfile ? `&chat_profile=${encodeURIComponent(chatProfile)}` : ''}`\n    : null;\n\n  // Always fetch if we don't have config and we're authenticated\n  const shouldFetch = isAuthenticated && !config;\n\n  const { data, error, isLoading } = useApi<IChainlitConfig>(\n    shouldFetch ? apiUrl : null\n  );\n\n  useEffect(() => {\n    if (!data) return;\n    setConfig(data);\n  }, [data, setConfig]);\n\n  // Clear config when chat profile changes to force re-fetch\n  useEffect(() => {\n    if (prevChatProfileRef.current !== chatProfile) {\n      setConfig(undefined);\n      prevChatProfileRef.current = chatProfile;\n    }\n  }, [chatProfile, setConfig]);\n\n  return { config, error, isLoading, language };\n};\n\nexport { useConfig };\n","export * from './useChatData';\nexport * from './useChatInteract';\nexport * from './useChatMessages';\nexport * from './useChatSession';\nexport * from './useAudio';\nexport * from './useConfig';\nexport * from './api';\nexport * from './types';\nexport * from './context';\nexport * from './state';\nexport * from './utils/message';\n\nexport { Socket } from 'socket.io-client';\n\nexport { WavRenderer } from './wavtools/wav_renderer';\n","const dataMap = new WeakMap();\n\n/**\n * Normalizes a Float32Array to Array(m): We use this to draw amplitudes on a graph\n * If we're rendering the same audio data, then we'll often be using\n * the same (data, m, downsamplePeaks) triplets so we give option to memoize\n */\nconst normalizeArray = (\n  data: Float32Array,\n  m: number,\n  downsamplePeaks: boolean = false,\n  memoize: boolean = false\n) => {\n  let cache, mKey, dKey;\n  if (memoize) {\n    mKey = m.toString();\n    dKey = downsamplePeaks.toString();\n    cache = dataMap.has(data) ? dataMap.get(data) : {};\n    dataMap.set(data, cache);\n    cache[mKey] = cache[mKey] || {};\n    if (cache[mKey][dKey]) {\n      return cache[mKey][dKey];\n    }\n  }\n  const n = data.length;\n  const result = new Array(m);\n  if (m <= n) {\n    // Downsampling\n    result.fill(0);\n    const count = new Array(m).fill(0);\n    for (let i = 0; i < n; i++) {\n      const index = Math.floor(i * (m / n));\n      if (downsamplePeaks) {\n        // take highest result in the set\n        result[index] = Math.max(result[index], Math.abs(data[i]));\n      } else {\n        result[index] += Math.abs(data[i]);\n      }\n      count[index]++;\n    }\n    if (!downsamplePeaks) {\n      for (let i = 0; i < result.length; i++) {\n        result[i] = result[i] / count[i];\n      }\n    }\n  } else {\n    for (let i = 0; i < m; i++) {\n      const index = (i * (n - 1)) / (m - 1);\n      const low = Math.floor(index);\n      const high = Math.ceil(index);\n      const t = index - low;\n      if (high >= n) {\n        result[i] = data[n - 1];\n      } else {\n        result[i] = data[low] * (1 - t) + data[high] * t;\n      }\n    }\n  }\n  if (memoize) {\n    cache[mKey as string][dKey as string] = result;\n  }\n  return result;\n};\n\nexport const WavRenderer = {\n  /**\n   * Renders a point-in-time snapshot of an audio sample, usually frequency values\n   * @param ctx\n   * @param data\n   * @param color\n   * @param cssWidth\n   * @param cssHeight\n   * @param pointCount number of bars to render\n   * @param barWidth width of bars in px\n   * @param barSpacing spacing between bars in px\n   * @param center vertically center the bars\n   */\n  drawBars: (\n    ctx: CanvasRenderingContext2D,\n    data: Float32Array,\n    cssWidth: number,\n    cssHeight: number,\n    color: string,\n    pointCount: number = 0,\n    barWidth: number = 0,\n    barSpacing: number = 0,\n    center: boolean = false\n  ) => {\n    pointCount = Math.floor(\n      Math.min(\n        pointCount,\n        (cssWidth - barSpacing) / (Math.max(barWidth, 1) + barSpacing)\n      )\n    );\n    if (!pointCount) {\n      pointCount = Math.floor(\n        (cssWidth - barSpacing) / (Math.max(barWidth, 1) + barSpacing)\n      );\n    }\n    if (!barWidth) {\n      barWidth = (cssWidth - barSpacing) / pointCount - barSpacing;\n    }\n    const points = normalizeArray(data, pointCount, true);\n    for (let i = 0; i < pointCount; i++) {\n      const amplitude = Math.abs(points[i]);\n      const height = Math.max(1, amplitude * cssHeight);\n      const x = barSpacing + i * (barWidth + barSpacing);\n      const y = center ? (cssHeight - height) / 2 : cssHeight - height;\n      const radius = Math.min(barWidth / 2, height / 2); // Calculate the radius for rounded corners\n\n      ctx.fillStyle = color;\n      ctx.beginPath();\n      ctx.moveTo(x + radius, y);\n      ctx.lineTo(x + barWidth - radius, y);\n      ctx.arcTo(x + barWidth, y, x + barWidth, y + radius, radius);\n      ctx.lineTo(x + barWidth, y + height - radius);\n      ctx.arcTo(\n        x + barWidth,\n        y + height,\n        x + barWidth - radius,\n        y + height,\n        radius\n      );\n      ctx.lineTo(x + radius, y + height);\n      ctx.arcTo(x, y + height, x, y + height - radius, radius);\n      ctx.lineTo(x, y + radius);\n      ctx.arcTo(x, y, x + radius, y, radius);\n      ctx.closePath();\n      ctx.fill();\n    }\n  }\n};\n"]}