aixblock-voice-ai-deepgram
Version:
A React component for real-time transcription and voice agent interactions using Deepgram APIs
3 lines (2 loc) โข 39.5 kB
JavaScript
import e,{forwardRef as t,useReducer as n,useRef as i,useEffect as r,useImperativeHandle as o,useState as a,useMemo as s}from"react";var c=function(){return c=Object.assign||function(e){for(var t,n=1,i=arguments.length;n<i;n++)for(var r in t=arguments[n])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e},c.apply(this,arguments)};function u(e,t,n,i){return new(n||(n=Promise))((function(r,o){function a(e){try{c(i.next(e))}catch(e){o(e)}}function s(e){try{c(i.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}c((i=i.apply(e,t||[])).next())}))}function l(e,t){var n,i,r,o={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=s(0),a.throw=s(1),a.return=s(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(s){return function(c){return function(s){if(n)throw new TypeError("Generator is already executing.");for(;a&&(a=0,s[0]&&(o=0)),o;)try{if(n=1,i&&(r=2&s[0]?i.return:s[0]?i.throw||((r=i.return)&&r.call(i),0):i.next)&&!(r=r.call(i,s[1])).done)return r;switch(i=0,r&&(s=[2&s[0],r.value]),s[0]){case 0:case 1:r=s;break;case 4:return o.label++,{value:s[1],done:!1};case 5:o.label++,i=s[1],s=[0];continue;case 7:s=o.ops.pop(),o.trys.pop();continue;default:if(!(r=o.trys,(r=r.length>0&&r[r.length-1])||6!==s[0]&&2!==s[0])){o=0;continue}if(3===s[0]&&(!r||s[1]>r[0]&&s[1]<r[3])){o.label=s[1];break}if(6===s[0]&&o.label<r[1]){o.label=r[1],r=s;break}if(r&&o.label<r[2]){o.label=r[2],o.ops.push(s);break}r[2]&&o.ops.pop(),o.trys.pop();continue}s=t.call(e,o)}catch(e){s=[6,e],i=0}finally{n=r=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,c])}}}function d(e,t,n){if(n||2===arguments.length)for(var i,r=0,o=t.length;r<o;r++)!i&&r in t||(i||(i=Array.prototype.slice.call(t,0,r)),i[r]=t[r]);return e.concat(i||Array.prototype.slice.call(t))}"function"==typeof SuppressedError&&SuppressedError;var p={keepaliveInterval:1e4,connectionTimeout:1e4,debug:!1},g=function(){function e(e){this.ws=null,this.eventListeners=[],this.keepaliveIntervalId=null,this.connectionTimeoutId=null,this.connectionState="closed",this.reconnectAttempts=0,this.maxReconnectAttempts=5,this.reconnectDelay=1e3,this.options=c(c({},p),e),this.log("WebSocketManager created")}return e.prototype.log=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this.options.debug&&console.log.apply(console,d(["[WebSocketManager:".concat(this.options.service,"]")],e,!1))},e.prototype.buildUrl=function(){var e=new URL(this.options.url);return this.options.queryParams&&Object.entries(this.options.queryParams).forEach((function(t){var n=t[0],i=t[1];"boolean"==typeof i?!0===i&&e.searchParams.append(n,"true"):e.searchParams.append(n,String(i))})),this.log("Built URL with params:",e.toString()),e.toString()},e.prototype.addEventListener=function(e){var t=this;return this.eventListeners.push(e),function(){t.eventListeners=t.eventListeners.filter((function(t){return t!==e}))}},e.prototype.emit=function(e){this.eventListeners.forEach((function(t){try{t(e)}catch(e){console.error("Error in WebSocketManager event listener:",e)}}))},e.prototype.updateState=function(e){this.connectionState=e,this.emit({type:"state",state:e})},e.prototype.connect=function(){var e=this;return!this.ws||this.ws.readyState!==WebSocket.OPEN&&this.ws.readyState!==WebSocket.CONNECTING?(this.log("Connecting to WebSocket..."),this.updateState("connecting"),new Promise((function(t,n){try{var i=e.buildUrl();e.log("Connecting to ".concat(i)),e.ws=new WebSocket(i,["token",e.options.apiKey]),e.log("Initial readyState:",e.ws.readyState),e.connectionTimeoutId=window.setTimeout((function(){if("connecting"===e.connectionState){var t={service:e.options.service,code:"connection_timeout",message:"Connection timed out"};e.log("Connection timeout reached"),e.emit({type:"error",error:t}),e.updateState("error"),e.close(),n(new Error("Connection timed out"))}}),e.options.connectionTimeout),e.ws.onopen=function(){e.log("WebSocket connected"),window.clearTimeout(e.connectionTimeoutId),e.connectionTimeoutId=null,e.updateState("connected"),e.startKeepalive(),e.reconnectAttempts=0,t()},e.ws.onmessage=function(t){if(e.log("Received message data type: ".concat(typeof t.data,", is ArrayBuffer: ").concat(t.data instanceof ArrayBuffer,", is Blob: ").concat(t.data instanceof Blob)),"string"==typeof t.data)try{e.log("Received raw string message:",t.data);var n=JSON.parse(t.data);e.log("Parsed message into JSON:",n),e.emit({type:"message",data:n})}catch(t){e.log("Error parsing message:",t),e.emit({type:"error",error:{service:e.options.service,code:"parse_error",message:"Failed to parse WebSocket message",details:t}})}else t.data instanceof ArrayBuffer?(e.log("Received ArrayBuffer binary data, emitting binary event..."),e.emit({type:"binary",data:t.data})):t.data instanceof Blob?(e.log("Received Blob binary data (size: ".concat(t.data.size,"), converting to ArrayBuffer...")),t.data.arrayBuffer().then((function(t){e.log("Converted Blob to ArrayBuffer (byteLength: ".concat(t.byteLength,"), emitting binary event...")),e.emit({type:"binary",data:t})})).catch((function(t){e.log("Error converting Blob to ArrayBuffer:",t),e.emit({type:"error",error:{service:e.options.service,code:"blob_conversion_error",message:"Failed to convert Blob to ArrayBuffer",details:t}})}))):e.log("Received message data of unexpected type:",t.data)},e.ws.onerror=function(t){e.log("WebSocket error:",t),e.emit({type:"error",error:{service:e.options.service,code:"websocket_error",message:"WebSocket connection error",details:t}}),e.updateState("error"),n(t)},e.ws.onclose=function(t){e.log("WebSocket closed: code=".concat(t.code,", reason='").concat(t.reason,"', wasClean=").concat(t.wasClean)),e.stopKeepalive(),window.clearTimeout(e.connectionTimeoutId),e.connectionTimeoutId=null,e.updateState("closed"),"connected"===e.connectionState&&e.reconnectAttempts<e.maxReconnectAttempts&&e.attemptReconnect()}}catch(t){e.log("Failed to create WebSocket:",t),e.updateState("error"),n(t)}}))):(this.log("WebSocket already connected or connecting"),Promise.resolve())},e.prototype.attemptReconnect=function(){var e=this;this.reconnectAttempts++;var t=Math.min(3e4,this.reconnectDelay*Math.pow(1.5,this.reconnectAttempts-1));this.log("Reconnecting in ".concat(t,"ms (attempt ").concat(this.reconnectAttempts,"/").concat(this.maxReconnectAttempts,")")),setTimeout((function(){e.connect().catch((function(t){e.log("Reconnection failed:",t)}))}),t)},e.prototype.startKeepalive=function(){var e=this;null!==this.keepaliveIntervalId&&this.stopKeepalive(),this.keepaliveIntervalId=window.setInterval((function(){e.sendKeepalive()}),this.options.keepaliveInterval),this.log("Started keepalive interval")},e.prototype.stopKeepalive=function(){null!==this.keepaliveIntervalId&&(window.clearInterval(this.keepaliveIntervalId),this.keepaliveIntervalId=null,this.log("Stopped keepalive interval"))},e.prototype.sendKeepalive=function(){if(this.ws&&this.ws.readyState===WebSocket.OPEN){this.log("Sending keepalive");try{this.ws.send(JSON.stringify({type:"KeepAlive"}))}catch(e){this.log("Error sending keepalive:",e)}}},e.prototype.sendJSON=function(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)return this.log("Cannot send message, WebSocket not open"),!1;try{return this.log("Sending JSON:",e),this.ws.send(JSON.stringify(e)),!0}catch(e){return this.log("Error sending JSON:",e),!1}},e.prototype.sendBinary=function(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)return this.log("Cannot send binary data, WebSocket not open"),!1;try{return this.log("Sending binary data: ".concat(e instanceof ArrayBuffer?e.byteLength:e.size," bytes")),this.ws.send(e),!0}catch(e){return this.log("Error sending binary data:",e),!1}},e.prototype.sendCloseStream=function(){return this.sendJSON({type:"CloseStream"})},e.prototype.close=function(){if(this.log("Closing WebSocket"),this.stopKeepalive(),null!==this.connectionTimeoutId&&(window.clearTimeout(this.connectionTimeoutId),this.connectionTimeoutId=null),this.ws){try{this.ws.close(1e3,"Closed by client")}catch(e){this.log("Error closing WebSocket:",e)}this.ws=null}this.updateState("closed")},e.prototype.getState=function(){return this.connectionState},e}();var h={sampleRate:16e3,outputSampleRate:24e3,normalizeVolume:!0,normalizationFactor:128,debug:!1},f=function(){function e(e){this.audioContext=null,this.workletNode=null,this.microphoneStream=null,this.sourceNode=null,this.isRecording=!1,this.isPlaying=!1,this.isInitialized=!1,this.eventListeners=[],this.startTimeRef={current:0},this.analyzer=null,this.analyzerData=null,this.currentSource=null,this.activeSourceNodes=[],this.options=c(c({},h),e),this.log("AudioManager created")}return e.prototype.log=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this.options.debug&&console.log.apply(console,d(["[AudioManager]"],e,!1))},e.prototype.addEventListener=function(e){var t=this;return this.eventListeners.push(e),function(){t.eventListeners=t.eventListeners.filter((function(t){return t!==e}))}},e.prototype.emit=function(e){this.eventListeners.forEach((function(t){try{t(e)}catch(e){console.error("Error in AudioManager event listener:",e)}}))},e.prototype.initialize=function(){return u(this,void 0,void 0,(function(){var e,t,n;return l(this,(function(i){switch(i.label){case 0:if(this.isInitialized)return[2];e=null,i.label=1;case 1:return i.trys.push([1,3,4,5]),this.log("Initializing AudioManager"),this.audioContext=new AudioContext({sampleRate:this.options.sampleRate,latencyHint:"interactive"}),this.options.normalizeVolume&&(this.analyzer=this.audioContext.createAnalyser(),this.analyzer.fftSize=1024,this.analyzerData=new Uint8Array(this.analyzer.frequencyBinCount),this.log("Created audio analyzer for volume normalization")),this.startTimeRef.current=0,t=new Blob(["/**\n * AudioWorkletProcessor for microphone capture and processing\n * \n * This processor captures audio from the microphone, resamples it to 16kHz,\n * and converts it to Linear PCM format for sending to Deepgram.\n */\nclass MicrophoneProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n \n // State\n this.isRecording = false;\n this.sampleRate = 16000; // Target sample rate\n this.bufferSize = 4096; // Buffer size in samples\n this.buffer = new Float32Array(this.bufferSize);\n this.bufferIndex = 0;\n \n // Set up message handler\n this.port.onmessage = (event) => this.onMessage(event.data);\n }\n \n /**\n * Handles messages from the main thread\n */\n onMessage(message) {\n if (message.type === 'start') {\n this.isRecording = true;\n this.port.postMessage({ type: 'started' });\n } else if (message.type === 'stop') {\n this.isRecording = false;\n this.port.postMessage({ type: 'stopped' });\n }\n }\n \n /**\n * Processes audio input and sends it to the main thread\n */\n process(inputs, outputs, parameters) {\n if (!this.isRecording || !inputs[0] || !inputs[0][0]) {\n return true;\n }\n \n const input = inputs[0][0];\n \n // Add input samples to our buffer\n for (let i = 0; i < input.length; i++) {\n this.buffer[this.bufferIndex++] = input[i];\n \n // When buffer is full, send it to the main thread\n if (this.bufferIndex >= this.bufferSize) {\n this.sendBufferToMainThread();\n this.bufferIndex = 0;\n }\n }\n \n return true;\n }\n \n /**\n * Converts the buffer to the required format and sends it to the main thread\n */\n sendBufferToMainThread() {\n // Create a copy of the buffer\n const audioData = this.buffer.slice(0, this.bufferIndex);\n \n // Convert to 16-bit PCM\n const pcmData = new Int16Array(audioData.length);\n for (let i = 0; i < audioData.length; i++) {\n // Convert float [-1.0, 1.0] to 16-bit PCM [-32768, 32767]\n const s = Math.max(-1, Math.min(1, audioData[i]));\n pcmData[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;\n }\n \n // Send the PCM data to the main thread\n this.port.postMessage({\n type: 'audio',\n data: pcmData.buffer\n }, [pcmData.buffer]);\n }\n}\n\n// Register the processor\nregisterProcessor('microphone-processor', MicrophoneProcessor);"],{type:"application/javascript"}),e=URL.createObjectURL(t),this.log("Created Object URL for AudioWorklet:",e),[4,this.audioContext.audioWorklet.addModule(e)];case 2:return i.sent(),this.log("AudioWorklet loaded using Object URL"),this.isInitialized=!0,this.emit({type:"ready"}),[3,5];case 3:throw n=i.sent(),this.log("Failed to initialize AudioManager:",n),this.emit({type:"error",error:{service:"transcription",code:"audio_init_error",message:"Failed to initialize audio",details:n}}),n;case 4:return e&&(this.log("Revoking Object URL:",e),URL.revokeObjectURL(e)),[7];case 5:return[2]}}))}))},e.prototype.startRecording=function(){return u(this,void 0,void 0,(function(){var e,t,n=this;return l(this,(function(i){switch(i.label){case 0:return this.isRecording?(this.log("Already recording"),[2]):this.isInitialized?[3,2]:[4,this.initialize()];case 1:i.sent(),i.label=2;case 2:return i.trys.push([2,6,,7]),this.log("Requesting microphone access"),e=this,[4,navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0},video:!1})];case 3:return e.microphoneStream=i.sent(),this.sourceNode=this.audioContext.createMediaStreamSource(this.microphoneStream),this.workletNode=new AudioWorkletNode(this.audioContext,"microphone-processor"),this.workletNode.port.onmessage=function(e){var t=e.data;"audio"===t.type?(n.log("Received audio data from worklet"),n.emit({type:"data",data:t.data})):"started"===t.type?(n.log("Recording started"),n.isRecording=!0,n.emit({type:"recording",isRecording:!0})):"stopped"===t.type?(n.log("Recording stopped"),n.isRecording=!1,n.emit({type:"recording",isRecording:!1})):"log"===t.type&&n.log("[AudioWorklet] ".concat(t.message))},this.sourceNode.connect(this.workletNode),this.workletNode.connect(this.audioContext.destination),"suspended"!==this.audioContext.state?[3,5]:[4,this.audioContext.resume()];case 4:i.sent(),i.label=5;case 5:return this.workletNode.port.postMessage({type:"start"}),this.log("Recording started"),[3,7];case 6:throw t=i.sent(),this.log("Failed to start recording:",t),this.emit({type:"error",error:{service:"transcription",code:"microphone_error",message:t instanceof DOMException&&"NotAllowedError"===t.name?"Microphone permission denied":"Failed to access microphone",details:t}}),t;case 7:return[2]}}))}))},e.prototype.stopRecording=function(){this.isRecording&&(this.log("Stopping recording"),this.workletNode&&(this.workletNode.port.postMessage({type:"stop"}),this.workletNode.disconnect(),this.workletNode=null),this.sourceNode&&(this.sourceNode.disconnect(),this.sourceNode=null),this.microphoneStream&&(this.microphoneStream.getTracks().forEach((function(e){return e.stop()})),this.microphoneStream=null),this.isRecording=!1,this.emit({type:"recording",isRecording:!1}))},e.prototype.queueAudio=function(e){return u(this,void 0,void 0,(function(){var t,n,i,r,o=this;return l(this,(function(a){switch(a.label){case 0:return this.isInitialized?[3,2]:(this.log("AudioManager not initialized, initializing now..."),[4,this.initialize()]);case 1:a.sent(),this.log("AudioManager initialized from queueAudio"),a.label=2;case 2:try{if(this.log("Processing audio data (".concat(e.byteLength," bytes)...")),this.log("[queueAudio] Before: activeSourceNodes.length = ".concat(this.activeSourceNodes.length,", startTimeRef.current = ").concat(this.startTimeRef.current)),t=function(e,t,n){void 0===n&&(n=24e3);var i=new Int16Array(t);if(0!==i.length){for(var r=e.createBuffer(1,i.length,n),o=r.getChannelData(0),a=0;a<i.length;a++)o[a]=i[a]/32768;return r}console.error("Received audio data is empty.")}(this.audioContext,e,this.options.outputSampleRate),!t)throw new Error("Failed to create audio buffer: buffer is undefined");this.log("[queueAudio] Created audio buffer (".concat(t.duration.toFixed(3),"s)")),n=function(e,t,n,i){var r=e.createBufferSource();r.buffer=t,i?(r.connect(i),i.connect(e.destination)):r.connect(e.destination);var o=e.currentTime;return n.current<o&&(n.current=o),r.start(n.current),n.current+=t.duration,r}(this.audioContext,t,this.startTimeRef,this.analyzer||void 0),this.log("[queueAudio] Scheduled source to start at ".concat(this.startTimeRef.current-t.duration," (duration: ").concat(t.duration,")")),this.activeSourceNodes.push(n),this.log("[queueAudio] Added source. activeSourceNodes.length = ".concat(this.activeSourceNodes.length)),i=n.onended,n.onended=function(e){var t=o.activeSourceNodes.indexOf(n);-1!==t?(o.activeSourceNodes.splice(t,1),o.log("[onended] Source removed. activeSourceNodes.length = ".concat(o.activeSourceNodes.length))):o.log("[onended] Source not found in activeSourceNodes (unusual)");try{i&&i.call(n,e)}catch(e){o.log("Error in original onended handler:",e)}},this.currentSource=n,r=this.isPlaying,this.isPlaying=!0,r||this.emit({type:"playing",isPlaying:!0}),this.currentSource.onended=function(){o.log("[currentSource.onended] Current audio source playback ended"),0===o.activeSourceNodes.length&&(o.log("[currentSource.onended] No more active sources, setting playing state to false"),o.isPlaying=!1,o.emit({type:"playing",isPlaying:!1}))},this.log("[queueAudio] After: activeSourceNodes.length = ".concat(this.activeSourceNodes.length,", startTimeRef.current = ").concat(this.startTimeRef.current)),this.log("Audio scheduled to play at ".concat(this.startTimeRef.current.toFixed(3),"s, current time: ").concat(this.audioContext.currentTime.toFixed(3),"s, active sources: ").concat(this.activeSourceNodes.length))}catch(e){throw this.log("Failed to process audio:",e),this.emit({type:"error",error:{service:"agent",code:"audio_process_error",message:"Failed to process audio data",details:e}}),e}return[2]}}))}))},e.prototype.clearAudioQueue=function(){var e=this;if(this.log("๐จ CLEARING AUDIO QUEUE - EMERGENCY STOP ๐จ"),this.log("[clearAudioQueue] Before: activeSourceNodes.length = ".concat(this.activeSourceNodes.length,", startTimeRef.current = ").concat(this.startTimeRef.current)),this.audioContext){var t=this.startTimeRef.current;this.startTimeRef.current=this.audioContext.currentTime,this.log("โฑ๏ธ Reset timing reference from ".concat(t.toFixed(3),"s to ").concat(this.startTimeRef.current.toFixed(3),"s")),this.log("๐ Attempting to stop ".concat(this.activeSourceNodes.length," active audio sources")),0===this.activeSourceNodes.length&&this.log("โน๏ธ No active sources found to stop"),this.activeSourceNodes.forEach((function(t,n){try{e.log("๐ Stopping source ".concat(n+1,"/").concat(e.activeSourceNodes.length)),t.onended=null,t.stop(),t.disconnect(),e.log("โ
Source ".concat(n+1," stopped and disconnected"))}catch(t){e.log("โ Error stopping audio source ".concat(n+1,":"),t)}}));var n=this.activeSourceNodes.length;this.activeSourceNodes=[],this.log("๐งน Cleared ".concat(n," active sources from tracking array")),this.currentSource?(this.log("๐งน Cleared currentSource reference"),this.currentSource=null):this.log("โน๏ธ No currentSource reference to clear");var i=this.isPlaying;this.isPlaying=!1,this.log("๐ Set isPlaying state to false (was: ".concat(i,")")),i?(this.log("๐ข Emitting playing=false event"),this.emit({type:"playing",isPlaying:!1})):this.log("โน๏ธ Not emitting playing event since we weren't playing");try{if("closed"!==this.audioContext.state){this.log("๐ Attempting to flush the audio context");var r=this.audioContext.createGain();r.connect(this.audioContext.destination),r.disconnect()}}catch(e){this.log("โ ๏ธ Error while flushing audio context:",e)}this.log("[clearAudioQueue] After: activeSourceNodes.length = ".concat(this.activeSourceNodes.length,", startTimeRef.current = ").concat(this.startTimeRef.current)),this.log("โ
Audio queue cleared, all playback should have stopped")}else this.log("โ No audioContext available")},e.checkMicrophonePermissions=function(){return u(this,void 0,void 0,(function(){var e,t,n;return l(this,(function(i){switch(i.label){case 0:return i.trys.push([0,2,,3]),[4,navigator.mediaDevices.enumerateDevices()];case 1:return e=i.sent(),0===(t=e.filter((function(e){return"audioinput"===e.kind}))).length?[2,!1]:[2,t.some((function(e){return""!==e.label}))];case 2:return n=i.sent(),console.error("Error checking microphone permissions:",n),[2,!1];case 3:return[2]}}))}))},e.prototype.dispose=function(){this.log("Disposing AudioManager"),this.stopRecording(),this.clearAudioQueue(),this.analyzer&&(this.analyzer.disconnect(),this.analyzer=null,this.analyzerData=null),this.audioContext&&(this.audioContext.close(),this.audioContext=null),this.isInitialized=!1,this.eventListeners=[]},e.prototype.isRecordingActive=function(){return this.isRecording},e.prototype.isPlaybackActive=function(){return this.isPlaying},e}(),y={connections:{transcription:"closed",agent:"closed"},agentState:"idle",microphonePermission:"prompt",isRecording:!1,isPlaying:!1,isReady:!1,error:null};function m(e,t){var n;switch(t.type){case"CONNECTION_STATE_CHANGE":return c(c({},e),{connections:c(c({},e.connections),(n={},n[t.service]=t.state,n)),error:"connected"===t.state?null:e.error});case"AGENT_STATE_CHANGE":return c(c({},e),{agentState:t.state});case"MICROPHONE_PERMISSION_CHANGE":return c(c({},e),{microphonePermission:t.status});case"RECORDING_STATE_CHANGE":return c(c({},e),{isRecording:t.isRecording});case"PLAYBACK_STATE_CHANGE":return c(c({},e),{isPlaying:t.isPlaying});case"READY_STATE_CHANGE":return c(c({},e),{isReady:t.isReady});case"ERROR":return c(c({},e),{error:t.message});default:return e}}var v="wss://api.deepgram.com/v1/listen",S="wss://agent.deepgram.com/v1/agent/converse";var A,E,T,N,b=t((function(e,t){var a=this,s=e.apiKey,p=e.transcriptionOptions,h=e.agentOptions,A=e.endpointConfig,E=e.onReady,T=e.onConnectionStateChange,N=e.onAgentAudioUpdate,b=e.onTranscriptUpdate,_=e.onAgentStateChange,C=e.onAgentUtterance,R=e.onUserMessage,k=e.onUserStartedSpeaking,w=e.onUserStoppedSpeaking,P=e.onPlaybackStateChange,I=e.onError,O=e.debug,G=void 0!==O&&O,M=n(m,y),U=M[0],D=M[1],x=i(U),z=i(null),L=i(null),H=i(null),B=i(!1),W=i(!1),K=i(void 0),F=i(void 0),j=i(void 0),q=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];G&&console.log.apply(console,d(["[DeepgramVoiceInteraction]"],e,!1))},Y=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];G&&console.log.apply(console,d(["[SLEEP_CYCLE][CORE]"],e,!1))};r((function(){if(x.current=U,"entering_sleep"===U.agentState){var e=setTimeout((function(){Y("Transitioning from entering_sleep to sleeping after timeout"),"entering_sleep"===x.current.agentState&&D({type:"AGENT_STATE_CHANGE",state:"sleeping"})}),50);return function(){return clearTimeout(e)}}}),[U]);var J=function(e){q("Error:",e),D({type:"ERROR",message:e.message}),null==I||I(e)};r((function(){var e;if(s){var t=!!p,n=!!h;if(!t&&!n)return q("No services configured! Either transcriptionOptions or agentOptions must be provided."),void J({service:"transcription",code:"invalid_configuration",message:"Either transcriptionOptions or agentOptions must be provided"});q("Initializing in ".concat(t&&n?"DUAL MODE":t?"TRANSCRIPTION-ONLY MODE":"AGENT-ONLY MODE"));var i=A||{},r={transcriptionUrl:i.transcriptionUrl||v,agentUrl:i.agentUrl||S},o=function(){},a=function(){},u=function(){};if(t){var l=r.transcriptionUrl,d={},y=c(c({},p),{sample_rate:p.sample_rate||16e3,encoding:p.encoding||"linear16",channels:p.channels||1}),m="nova-3"===y.model&&Array.isArray(y.keyterm)&&y.keyterm.length>0;if(m){q("Nova-3 and keyterms detected. Building transcription URL with keyterm parameters.");for(var E=new URL(l),N=new URLSearchParams,b=0,_=Object.entries(y);b<_.length;b++){var C=_[b],R=C[0],k=C[1];"keyterm"!==R&&void 0!==k&&N.append(R,String(k))}null===(e=y.keyterm)||void 0===e||e.forEach((function(e){e&&N.append("keyterm",e)})),E.search=N.toString(),l=E.toString(),q("Constructed transcription URL with keyterms:",l)}else{q("Not using keyterm prompting. Building queryParams object excluding array types."),y.keyterm,y.keywords;for(var w=function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.indexOf(i)<0&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(i=Object.getOwnPropertySymbols(e);r<i.length;r++)t.indexOf(i[r])<0&&Object.prototype.propertyIsEnumerable.call(e,i[r])&&(n[i[r]]=e[i[r]])}return n}(y,["keyterm","keywords"]),P={},I=0,O=Object.entries(w);I<O.length;I++){var M=O[I];R=M[0];"string"==typeof(k=M[1])||"number"==typeof k||"boolean"==typeof k?P[R]=k:q("Skipping non-primitive param ".concat(R," for queryParams object."))}d=P}z.current=new g({url:l,apiKey:s,service:"transcription",queryParams:m?void 0:d,debug:G}),o=z.current.addEventListener((function(e){"state"===e.type?(q("Transcription state:",e.state),D({type:"CONNECTION_STATE_CHANGE",service:"transcription",state:e.state}),null==T||T("transcription",e.state)):"message"===e.type?V(e.data):"error"===e.type&&J(e.error)}))}else q("Transcription service not configured, skipping setup");return n?(L.current=new g({url:r.agentUrl,apiKey:s,service:"agent",debug:G}),a=L.current.addEventListener((function(e){"state"===e.type?(q("Agent state:",e.state),D({type:"CONNECTION_STATE_CHANGE",service:"agent",state:e.state}),null==T||T("agent",e.state),"connected"===e.state&&Q()):"message"===e.type?X(e.data):"binary"===e.type?Z(e.data):"error"===e.type&&J(e.error)}))):q("Agent service not configured, skipping setup"),t||n?(H.current=new f({debug:G}),u=H.current.addEventListener((function(e){"ready"===e.type?q("Audio manager ready"):"recording"===e.type?(q("Recording state:",e.isRecording),D({type:"RECORDING_STATE_CHANGE",isRecording:e.isRecording})):"playing"===e.type?(q("Playing state:",e.isPlaying),D({type:"PLAYBACK_STATE_CHANGE",isPlaying:e.isPlaying})):"error"===e.type?J(e.error):"data"===e.type&&$(e.data)})),H.current.initialize().then((function(){q("AudioManager initialized successfully in useEffect"),D({type:"READY_STATE_CHANGE",isReady:!0})})).catch((function(e){J({service:"transcription",code:"audio_init_error",message:"Failed to initialize audio",details:e}),D({type:"READY_STATE_CHANGE",isReady:!1})}))):q("Neither transcription nor agent configured, skipping audio setup"),function(){o(),a(),u(),z.current&&(z.current.close(),z.current=null),L.current&&(L.current.close(),L.current=null),H.current&&(H.current.dispose(),H.current=null),D({type:"READY_STATE_CHANGE",isReady:!1}),D({type:"CONNECTION_STATE_CHANGE",service:"transcription",state:"closed"}),D({type:"CONNECTION_STATE_CHANGE",service:"agent",state:"closed"}),D({type:"AGENT_STATE_CHANGE",state:"idle"}),D({type:"RECORDING_STATE_CHANGE",isRecording:!1}),D({type:"PLAYBACK_STATE_CHANGE",isPlaying:!1})}}J({service:"transcription",code:"invalid_api_key",message:"API key is required"})}),[s,p,h,A,G]),r((function(){E&&U.isReady!==K.current&&(q("Notifying parent: isReady changed to",U.isReady),E(U.isReady),K.current=U.isReady)}),[U.isReady,E]),r((function(){_&&U.agentState!==F.current&&(q("Notifying parent: agentState changed to",U.agentState),_(U.agentState),F.current=U.agentState)}),[U.agentState,_]),r((function(){P&&U.isPlaying!==j.current&&(q("Notifying parent: isPlaying changed to",U.isPlaying),P(U.isPlaying),j.current=U.isPlaying)}),[U.isPlaying,P]);var V=function(e){if(z.current){var t=L.current&&("sleeping"===x.current.agentState||"entering_sleep"===x.current.agentState);if("VADEvent"===e.type){var n=e.is_speech;return t?void Y("Ignoring VAD event (state:",x.current.agentState,")"):void(n&&!B.current?(B.current=!0,null==k||k()):!n&&B.current&&(B.current=!1,null==w||w()))}if("Results"===e.type||"Transcript"===e.type)return t?void Y("Ignoring transcript (state:",x.current.agentState,")"):void(null==b||b(e))}else q("Received unexpected transcription message but service is not configured:",e)},Q=function(){if(L.current&&h){var e={type:"Settings",audio:{input:{encoding:"linear16",sample_rate:16e3},output:{encoding:"linear16",sample_rate:24e3}},agent:{language:h.language||"en",listen:{provider:{type:"deepgram",model:h.listenModel||"nova-2"}},think:c({provider:{type:h.thinkProviderType||"open_ai",model:h.thinkModel||"gpt-4o-mini"},prompt:h.instructions||"You are a helpful voice assistant."},h.thinkEndpointUrl&&h.thinkApiKey?{endpoint:{url:h.thinkEndpointUrl,headers:{authorization:"bearer ".concat(h.thinkApiKey)}}}:{}),speak:{provider:{type:"deepgram",model:h.voice||"aura-asteria-en"}},greeting:h.greeting}};q("Sending agent settings:",e),L.current.sendJSON(e)}else q("Cannot send agent settings: agent manager not initialized or agentOptions not provided")},X=function(e){if(L.current){var t="sleeping"===x.current.agentState||"entering_sleep"===x.current.agentState;if("UserStartedSpeaking"===e.type)return Y("UserStartedSpeaking message received"),t?void Y("Ignoring UserStartedSpeaking event (state:",x.current.agentState,")"):(q("Clearing audio queue (barge-in)"),ie(),null==k||k(),W.current&&(q("User started speaking after wake - resetting waiting flag"),W.current=!1),Y("Dispatching AGENT_STATE_CHANGE to listening (from UserStartedSpeaking)"),void D({type:"AGENT_STATE_CHANGE",state:"listening"}));if("AgentThinking"===e.type)return Y("Dispatching AGENT_STATE_CHANGE to thinking"),void D({type:"AGENT_STATE_CHANGE",state:"thinking"});if("AgentStartedSpeaking"===e.type)return Y("Dispatching AGENT_STATE_CHANGE to speaking"),void D({type:"AGENT_STATE_CHANGE",state:"speaking"});if("AgentAudioDone"===e.type)return Y("Dispatching AGENT_STATE_CHANGE to idle (from AgentAudioDone)"),void D({type:"AGENT_STATE_CHANGE",state:"idle"});if("ConversationText"===e.type){if("assistant"===e.role){var n={type:"llm",text:e.content||"",metadata:e};return void(null==C||C(n))}if("user"===e.role){n={type:"user",text:e.content||"",metadata:e};return void(null==R||R(n))}}"Error"!==e.type?"Warning"!==e.type||q("Agent warning:",e.description,"Code:",e.code):J({service:"agent",code:e.code||"agent_error",message:e.description||"Unknown agent error",details:e})}else q("Received unexpected agent message but service is not configured:",e)},Z=function(e){L.current?(q("handleAgentAudio called! Received buffer of ".concat(e.byteLength," bytes")),W.current?q("Skipping audio playback because waiting for user voice after sleep"):(H.current?(q("Passing buffer to AudioManager.queueAudio()"),H.current.queueAudio(e).then((function(){q("Successfully queued audio buffer for playback")})).catch((function(e){q("Error queueing audio:",e)}))):q("Cannot queue audio: audioManagerRef.current is null"),N&&N(e))):q("Received unexpected agent audio but service is not configured")},$=function(e){var t;if("connected"===(null===(t=z.current)||void 0===t?void 0:t.getState())&&z.current.sendBinary(e),L.current){var n="sleeping"===x.current.agentState||"entering_sleep"===x.current.agentState;"connected"!==L.current.getState()||n?n&&Y("Skipping sendAudioData to agent (state:",x.current.agentState,")"):L.current.sendBinary(e)}},ee=function(){return u(a,void 0,void 0,(function(){var e,t;return l(this,(function(n){switch(n.label){case 0:if(n.trys.push([0,14,,15]),q("Start method called"),!H.current)return[3,4];n.label=1;case 1:return n.trys.push([1,3,,4]),q("Ensuring AudioManager is initialized..."),[4,H.current.initialize()];case 2:return n.sent(),q("AudioManager initialized"),[3,4];case 3:throw e=n.sent(),q("Error initializing AudioManager:",e),e;case 4:return z.current?(q("Connecting Transcription WebSocket..."),[4,z.current.connect()]):[3,6];case 5:return n.sent(),q("Transcription WebSocket connected"),[3,7];case 6:q("Transcription manager not configured, skipping connection"),n.label=7;case 7:return L.current?(q("Connecting Agent WebSocket..."),[4,L.current.connect()]):[3,9];case 8:return n.sent(),q("Agent WebSocket connected"),[3,10];case 9:q("Agent manager not configured, skipping connection"),n.label=10;case 10:return H.current?(q("Starting recording..."),[4,H.current.startRecording()]):[3,12];case 11:return n.sent(),q("Recording started"),[3,13];case 12:throw q("AudioManager not initialized, cannot start recording"),new Error("Audio manager not available for recording");case 13:return q("Start method completed successfully"),[3,15];case 14:throw t=n.sent(),q("Error within start method:",t),J({service:"transcription",code:"start_error",message:"Failed to start voice interaction",details:t}),D({type:"READY_STATE_CHANGE",isReady:!1}),t;case 15:return[2]}}))}))},te=function(){return u(a,void 0,void 0,(function(){var e;return l(this,(function(t){switch(t.label){case 0:q("Stopping voice interaction"),t.label=1;case 1:return t.trys.push([1,3,,4]),z.current&&(q("Sending CloseStream message to finalize transcription"),z.current.sendCloseStream()),H.current&&H.current.stopRecording(),[4,new Promise((function(e){return setTimeout(e,1e3)}))];case 2:return t.sent(),z.current&&z.current.close(),L.current&&L.current.close(),D({type:"READY_STATE_CHANGE",isReady:!1}),[2,Promise.resolve()];case 3:return e=t.sent(),q("Error stopping:",e),J({service:"transcription",code:"stop_error",message:"Error while stopping transcription",details:e}),D({type:"READY_STATE_CHANGE",isReady:!1}),[2,Promise.reject(e)];case 4:return[2]}}))}))},ne=function(e){L.current?(q("Updating agent instructions:",e),L.current.sendJSON({type:"UpdatePrompt",prompt:e.instructions||e.context||""})):q("Cannot update instructions: agent manager not initialized or not configured")},ie=function(){if(q("๐ข clearAudio helper called"),H.current){try{if(q("๐ด Calling audioManager.clearAudioQueue()"),H.current.clearAudioQueue(),H.current.audioContext){q("๐ Manipulating audio context time reference");var e=H.current.audioContext;try{var t=e.createBuffer(1,1024,e.sampleRate),n=e.createBufferSource();n.buffer=t,n.connect(e.destination),n.start()}catch(e){q("โ ๏ธ Error creating silent buffer:",e)}}}catch(e){q("โ Error in clearAudio:",e)}q("๐ข clearAudio helper completed")}else q("โ Cannot clear audio: audioManagerRef.current is null")},re=function(){q("๐ด interruptAgent method called"),L.current?(ie(),q("๐ด Setting agent state to idle"),Y("Dispatching AGENT_STATE_CHANGE to idle (from interruptAgent)"),D({type:"AGENT_STATE_CHANGE",state:"idle"}),q("๐ด interruptAgent method completed")):q("Cannot interrupt agent: agent manager not initialized or not configured")},oe=function(){L.current?(Y("sleep() method called - initiating transition"),W.current=!0,ie(),Y("Dispatching AGENT_STATE_CHANGE to entering_sleep (from sleep())"),D({type:"AGENT_STATE_CHANGE",state:"entering_sleep"})):q("Cannot put agent to sleep: agent manager not initialized or not configured")},ae=function(){L.current?"sleeping"===x.current.agentState?(Y("wake() method called from sleeping state"),W.current=!1,Y("Dispatching AGENT_STATE_CHANGE to listening (from wake())"),D({type:"AGENT_STATE_CHANGE",state:"listening"})):Y("wake() called but state is ".concat(x.current.agentState,", not 'sleeping'. Aborting wake.")):q("Cannot wake agent: agent manager not initialized or not configured")},se=function(){L.current?(Y("toggleSleep() method called. Current state via ref:",x.current.agentState),"sleeping"===x.current.agentState?ae():"entering_sleep"!==x.current.agentState?oe():Y("toggleSleep() called while already entering_sleep. No action."),Y("Sleep toggle action dispatched or ignored")):q("Cannot toggle agent sleep state: agent manager not initialized or not configured")},ce=function(e){L.current?(q("Injecting agent message:",e),L.current.sendJSON({type:"InjectAgentMessage",content:e})):q("Cannot inject message: agent manager not initialized or not configured")};return o(t,(function(){return{start:ee,stop:te,updateAgentInstructions:ne,interruptAgent:re,sleep:oe,wake:ae,toggleSleep:se,injectAgentMessage:ce}})),null})),_=function(){this.auth="",this.voice="",this.greeting="",this.language="",this.thinkModel="",this.listenModel="",this.instructions="",this.thinkProvider="",this.provider={baseUrl:"",token:""}},C=function(t){var n=t.voiceConfig,i=t.onReady,o=t.onAgentUtterance,c=t.onTranscriptUpdate,d=t.onUserMessage,p=t.onError,g=t.deepgramRef,h=t.onAgentStateChange,f=t.onConnectionStateChange,y=t.onPlaybackStateChange,m=t.sleepOptions,v=t.onAgentAudioUpdate,S=t.debug,A=void 0!==S&&S,E=a(new _),T=E[0],N=E[1];r((function(){C()}),[n]);var C=function(){return u(void 0,void 0,void 0,(function(){var e;return l(this,(function(t){return e=window.atob(n),N(JSON.parse(e)),[2]}))}))},R=s((function(){return{model:T.listenModel,language:T.language,smart_format:!0,interim_results:!0,diarize:!0,channels:1,keyterm:["Casella","Symbiosis","Kerfuffle","Supercalifragilisticexpialidocious"]}}),[T]),k=s((function(){return{language:T.language,listenModel:T.listenModel,thinkProviderType:(e=T.thinkModel,{openai:"open_ai",anthropic:"anthropic",replicate:"replicate"}[e]),thinkModel:T.thinkModel,thinkApiKey:T.provider.token,voice:T.voice,instructions:T.instructions,greeting:T.greeting};var e}),[T]),w=s((function(){return{transcriptionUrl:"wss://api.deepgram.com/v1/listen",agentUrl:"wss://agent.deepgram.com/v1/agent/converse"}}),[]);return e.createElement(e.Fragment,null,e.createElement(b,{ref:g,apiKey:T.auth,transcriptionOptions:R,agentOptions:k,endpointConfig:w,onReady:i,onTranscriptUpdate:c,onAgentUtterance:o,onUserMessage:d,onAgentStateChange:h,onConnectionStateChange:f,onError:p,onPlaybackStateChange:y,debug:A,sleepOptions:m,onAgentAudioUpdate:v}))};function R(e){return w(e)||P(e)}function k(e){return void 0!==e.tts_latency}function w(e){return void 0!==e.user}function P(e){return void 0!==e.assistant}!function(e){e.SETTINGS="Settings",e.UPDATE_PROMPT="UpdatePrompt",e.UPDATE_SPEAK="UpdateSpeak",e.INJECT_AGENT_MESSAGE="InjectAgentMessage",e.FUNCTION_CALL_RESPONSE="FunctionCallResponse",e.KEEP_ALIVE="KeepAlive"}(A||(A={})),function(e){e.WELCOME="Welcome",e.SETTINGS_APPLIED="SettingsApplied",e.PROMPT_UPDATED="PromptUpdated",e.SPEAK_UPDATED="SpeakUpdated",e.CONVERSATION_TEXT="ConversationText",e.USER_STARTED_SPEAKING="UserStartedSpeaking",e.AGENT_THINKING="AgentThinking",e.FUNCTION_CALL_REQUEST="FunctionCallRequest",e.FUNCTION_CALL_RESPONSE="FunctionCallResponse",e.AGENT_STARTED_SPEAKING="AgentStartedSpeaking",e.AGENT_AUDIO_DONE="AgentAudioDone",e.ERROR="Error",e.WARNING="Warning"}(E||(E={})),function(e){e.SETTINGS_APPLIED="SettingsApplied",e.AGENT_AUDIO_DONE="AgentAudioDone",e.USER_STARTED_SPEAKING="UserStartedSpeaking",e.AGENT_STARTED_SPEAKING="AgentStartedSpeaking",e.CONVERSATION_TEXT="ConversationText",e.END_OF_THOUGHT="EndOfThought",e.INTERRUPTION="Interruption"}(T||(T={})),function(e){e.START_LISTENING="start_listening",e.START_THINKING="start_thinking",e.START_SPEAKING="start_speaking",e.START_SLEEPING="start_sleeping",e.INCREMENT_SLEEP_TIMER="increment_sleep_timer",e.ADD_MESSAGE="add_message",e.ADD_BEHIND_SCENES_EVENT="add_behind_scenes_event",e.SET_PARAMS_ON_COPY_URL="set_attach_params_to_copy_url"}(N||(N={}));export{A as AgentMessageType,E as AgentResponseType,T as BehindScenesEventType,_ as ConfigData,b as DeepgramVoiceInteraction,C as VoiceAI,N as VoiceBotActionType,P as isAssistantMessage,R as isConversationMessage,k as isLatencyMessage,w as isUserMessage};
//# sourceMappingURL=index.esm.js.map