@chainlit/react-client 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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","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","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","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","err","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","clear","sendMessage","fileReferences","oldMessages","editMessage","windowMessage","startAudioStream","sendAudioChunk","isStart","mimeType","elapsedTime","endAudioStream","replyMessage","updateChatSettings","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","step","spec","commands","modes","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","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\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('default', {\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');\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 }\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 // eslint-disable-next-line no-console\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 }\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 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\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 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 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 };\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(threadId: string, isShared: boolean): 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 firstUserInteraction,\n isAiSpeakingState,\n loadingState,\n modesState,\n mcpState,\n messagesState,\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 IMode,\n IMessageElement,\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\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 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 // Connect to microphone\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 } 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((thread as any)?.metadata?.viewer_read_only);\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_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 { configState, chatProfileState } 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"]}
|
|
1
|
+
{"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","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","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","err","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","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\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('default', {\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');\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 }\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 // eslint-disable-next-line no-console\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 }\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 nextMessage: IStep = {\n ...message,\n metadata: {\n ...(message.metadata || {}),\n favorite\n }\n };\n\n setMessages((oldMessages) =>\n oldMessages.map((item) => (item.id === message.id ? nextMessage : item))\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(threadId: string, isShared: boolean): 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 { configState, chatProfileState } 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"]}
|