aixblock-voice-ai-deepgram
Version:
A React component for real-time transcription and voice agent interactions using Deepgram APIs
3 lines (2 loc) โข 40 kB
JavaScript
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react");function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=t(e),r=function(){return r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e},r.apply(this,arguments)};function i(e,t,n,r){return new(n||(n=Promise))((function(i,o){function a(e){try{c(r.next(e))}catch(e){o(e)}}function s(e){try{c(r.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,s)}c((r=r.apply(e,t||[])).next())}))}function o(e,t){var n,r,i,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[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,r&&(i=2&s[0]?r.return:s[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,s[1])).done)return i;switch(r=0,i&&(s=[2&s[0],i.value]),s[0]){case 0:case 1:i=s;break;case 4:return o.label++,{value:s[1],done:!1};case 5:o.label++,r=s[1],s=[0];continue;case 7:s=o.ops.pop(),o.trys.pop();continue;default:if(!(i=o.trys,(i=i.length>0&&i[i.length-1])||6!==s[0]&&2!==s[0])){o=0;continue}if(3===s[0]&&(!i||s[1]>i[0]&&s[1]<i[3])){o.label=s[1];break}if(6===s[0]&&o.label<i[1]){o.label=i[1],i=s;break}if(i&&o.label<i[2]){o.label=i[2],o.ops.push(s);break}i[2]&&o.ops.pop(),o.trys.pop();continue}s=t.call(e,o)}catch(e){s=[6,e],r=0}finally{n=i=0}if(5&s[0])throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}([s,c])}}}function a(e,t,n){if(n||2===arguments.length)for(var r,i=0,o=t.length;i<o;i++)!r&&i in t||(r||(r=Array.prototype.slice.call(t,0,i)),r[i]=t[i]);return e.concat(r||Array.prototype.slice.call(t))}"function"==typeof SuppressedError&&SuppressedError;var s={keepaliveInterval:1e4,connectionTimeout:1e4,debug:!1},c=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=r(r({},s),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,a(["[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],r=t[1];"boolean"==typeof r?!0===r&&e.searchParams.append(n,"true"):e.searchParams.append(n,String(r))})),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 r=e.buildUrl();e.log("Connecting to ".concat(r)),e.ws=new WebSocket(r,["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 u={sampleRate:16e3,outputSampleRate:24e3,normalizeVolume:!0,normalizationFactor:128,debug:!1},l=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=r(r({},u),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,a(["[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 i(this,void 0,void 0,(function(){var e,t,n;return o(this,(function(r){switch(r.label){case 0:if(this.isInitialized)return[2];e=null,r.label=1;case 1:return r.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 r.sent(),this.log("AudioWorklet loaded using Object URL"),this.isInitialized=!0,this.emit({type:"ready"}),[3,5];case 3:throw n=r.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 i(this,void 0,void 0,(function(){var e,t,n=this;return o(this,(function(r){switch(r.label){case 0:return this.isRecording?(this.log("Already recording"),[2]):this.isInitialized?[3,2]:[4,this.initialize()];case 1:r.sent(),r.label=2;case 2:return r.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=r.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:r.sent(),r.label=5;case 5:return this.workletNode.port.postMessage({type:"start"}),this.log("Recording started"),[3,7];case 6:throw t=r.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 i(this,void 0,void 0,(function(){var t,n,r,i,a=this;return o(this,(function(o){switch(o.label){case 0:return this.isInitialized?[3,2]:(this.log("AudioManager not initialized, initializing now..."),[4,this.initialize()]);case 1:o.sent(),this.log("AudioManager initialized from queueAudio"),o.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 r=new Int16Array(t);if(0!==r.length){for(var i=e.createBuffer(1,r.length,n),o=i.getChannelData(0),a=0;a<r.length;a++)o[a]=r[a]/32768;return i}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,r){var i=e.createBufferSource();i.buffer=t,r?(i.connect(r),r.connect(e.destination)):i.connect(e.destination);var o=e.currentTime;return n.current<o&&(n.current=o),i.start(n.current),n.current+=t.duration,i}(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)),r=n.onended,n.onended=function(e){var t=a.activeSourceNodes.indexOf(n);-1!==t?(a.activeSourceNodes.splice(t,1),a.log("[onended] Source removed. activeSourceNodes.length = ".concat(a.activeSourceNodes.length))):a.log("[onended] Source not found in activeSourceNodes (unusual)");try{r&&r.call(n,e)}catch(e){a.log("Error in original onended handler:",e)}},this.currentSource=n,i=this.isPlaying,this.isPlaying=!0,i||this.emit({type:"playing",isPlaying:!0}),this.currentSource.onended=function(){a.log("[currentSource.onended] Current audio source playback ended"),0===a.activeSourceNodes.length&&(a.log("[currentSource.onended] No more active sources, setting playing state to false"),a.isPlaying=!1,a.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 r=this.isPlaying;this.isPlaying=!1,this.log("๐ Set isPlaying state to false (was: ".concat(r,")")),r?(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 i=this.audioContext.createGain();i.connect(this.audioContext.destination),i.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 i(this,void 0,void 0,(function(){var e,t,n;return o(this,(function(r){switch(r.label){case 0:return r.trys.push([0,2,,3]),[4,navigator.mediaDevices.enumerateDevices()];case 1:return e=r.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=r.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}(),d={connections:{transcription:"closed",agent:"closed"},agentState:"idle",microphonePermission:"prompt",isRecording:!1,isPlaying:!1,isReady:!1,error:null};function p(e,t){var n;switch(t.type){case"CONNECTION_STATE_CHANGE":return r(r({},e),{connections:r(r({},e.connections),(n={},n[t.service]=t.state,n)),error:"connected"===t.state?null:e.error});case"AGENT_STATE_CHANGE":return r(r({},e),{agentState:t.state});case"MICROPHONE_PERMISSION_CHANGE":return r(r({},e),{microphonePermission:t.status});case"RECORDING_STATE_CHANGE":return r(r({},e),{isRecording:t.isRecording});case"PLAYBACK_STATE_CHANGE":return r(r({},e),{isPlaying:t.isPlaying});case"READY_STATE_CHANGE":return r(r({},e),{isReady:t.isReady});case"ERROR":return r(r({},e),{error:t.message});default:return e}}var g="wss://api.deepgram.com/v1/listen",h="wss://agent.deepgram.com/v1/agent/converse";var f,y,v,m,S=e.forwardRef((function(t,n){var s=this,u=t.apiKey,f=t.transcriptionOptions,y=t.agentOptions,v=t.endpointConfig,m=t.onReady,S=t.onConnectionStateChange,A=t.onAgentAudioUpdate,E=t.onTranscriptUpdate,T=t.onAgentStateChange,N=t.onAgentUtterance,R=t.onUserMessage,b=t.onUserStartedSpeaking,_=t.onUserStoppedSpeaking,C=t.onPlaybackStateChange,k=t.onError,w=t.debug,P=void 0!==w&&w,I=e.useReducer(p,d),O=I[0],M=I[1],x=e.useRef(O),G=e.useRef(null),U=e.useRef(null),D=e.useRef(null),z=e.useRef(!1),L=e.useRef(!1),H=e.useRef(void 0),B=e.useRef(void 0),W=e.useRef(void 0),K=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];P&&console.log.apply(console,a(["[DeepgramVoiceInteraction]"],e,!1))},F=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];P&&console.log.apply(console,a(["[SLEEP_CYCLE][CORE]"],e,!1))};e.useEffect((function(){if(x.current=O,"entering_sleep"===O.agentState){var e=setTimeout((function(){F("Transitioning from entering_sleep to sleeping after timeout"),"entering_sleep"===x.current.agentState&&M({type:"AGENT_STATE_CHANGE",state:"sleeping"})}),50);return function(){return clearTimeout(e)}}}),[O]);var j=function(e){K("Error:",e),M({type:"ERROR",message:e.message}),null==k||k(e)};e.useEffect((function(){var e;if(u){var t=!!f,n=!!y;if(!t&&!n)return K("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"});K("Initializing in ".concat(t&&n?"DUAL MODE":t?"TRANSCRIPTION-ONLY MODE":"AGENT-ONLY MODE"));var i=v||{},o={transcriptionUrl:i.transcriptionUrl||g,agentUrl:i.agentUrl||h},a=function(){},s=function(){},d=function(){};if(t){var p=o.transcriptionUrl,m={},A=r(r({},f),{sample_rate:f.sample_rate||16e3,encoding:f.encoding||"linear16",channels:f.channels||1}),E="nova-3"===A.model&&Array.isArray(A.keyterm)&&A.keyterm.length>0;if(E){K("Nova-3 and keyterms detected. Building transcription URL with keyterm parameters.");for(var T=new URL(p),N=new URLSearchParams,R=0,b=Object.entries(A);R<b.length;R++){var _=b[R],C=_[0],k=_[1];"keyterm"!==C&&void 0!==k&&N.append(C,String(k))}null===(e=A.keyterm)||void 0===e||e.forEach((function(e){e&&N.append("keyterm",e)})),T.search=N.toString(),p=T.toString(),K("Constructed transcription URL with keyterms:",p)}else{K("Not using keyterm prompting. Building queryParams object excluding array types."),A.keyterm,A.keywords;for(var w=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n}(A,["keyterm","keywords"]),I={},O=0,x=Object.entries(w);O<x.length;O++){var z=x[O];C=z[0];"string"==typeof(k=z[1])||"number"==typeof k||"boolean"==typeof k?I[C]=k:K("Skipping non-primitive param ".concat(C," for queryParams object."))}m=I}G.current=new c({url:p,apiKey:u,service:"transcription",queryParams:E?void 0:m,debug:P}),a=G.current.addEventListener((function(e){"state"===e.type?(K("Transcription state:",e.state),M({type:"CONNECTION_STATE_CHANGE",service:"transcription",state:e.state}),null==S||S("transcription",e.state)):"message"===e.type?q(e.data):"error"===e.type&&j(e.error)}))}else K("Transcription service not configured, skipping setup");return n?(U.current=new c({url:o.agentUrl,apiKey:u,service:"agent",debug:P}),s=U.current.addEventListener((function(e){"state"===e.type?(K("Agent state:",e.state),M({type:"CONNECTION_STATE_CHANGE",service:"agent",state:e.state}),null==S||S("agent",e.state),"connected"===e.state&&Y()):"message"===e.type?V(e.data):"binary"===e.type?J(e.data):"error"===e.type&&j(e.error)}))):K("Agent service not configured, skipping setup"),t||n?(D.current=new l({debug:P}),d=D.current.addEventListener((function(e){"ready"===e.type?K("Audio manager ready"):"recording"===e.type?(K("Recording state:",e.isRecording),M({type:"RECORDING_STATE_CHANGE",isRecording:e.isRecording})):"playing"===e.type?(K("Playing state:",e.isPlaying),M({type:"PLAYBACK_STATE_CHANGE",isPlaying:e.isPlaying})):"error"===e.type?j(e.error):"data"===e.type&&Q(e.data)})),D.current.initialize().then((function(){K("AudioManager initialized successfully in useEffect"),M({type:"READY_STATE_CHANGE",isReady:!0})})).catch((function(e){j({service:"transcription",code:"audio_init_error",message:"Failed to initialize audio",details:e}),M({type:"READY_STATE_CHANGE",isReady:!1})}))):K("Neither transcription nor agent configured, skipping audio setup"),function(){a(),s(),d(),G.current&&(G.current.close(),G.current=null),U.current&&(U.current.close(),U.current=null),D.current&&(D.current.dispose(),D.current=null),M({type:"READY_STATE_CHANGE",isReady:!1}),M({type:"CONNECTION_STATE_CHANGE",service:"transcription",state:"closed"}),M({type:"CONNECTION_STATE_CHANGE",service:"agent",state:"closed"}),M({type:"AGENT_STATE_CHANGE",state:"idle"}),M({type:"RECORDING_STATE_CHANGE",isRecording:!1}),M({type:"PLAYBACK_STATE_CHANGE",isPlaying:!1})}}j({service:"transcription",code:"invalid_api_key",message:"API key is required"})}),[u,f,y,v,P]),e.useEffect((function(){m&&O.isReady!==H.current&&(K("Notifying parent: isReady changed to",O.isReady),m(O.isReady),H.current=O.isReady)}),[O.isReady,m]),e.useEffect((function(){T&&O.agentState!==B.current&&(K("Notifying parent: agentState changed to",O.agentState),T(O.agentState),B.current=O.agentState)}),[O.agentState,T]),e.useEffect((function(){C&&O.isPlaying!==W.current&&(K("Notifying parent: isPlaying changed to",O.isPlaying),C(O.isPlaying),W.current=O.isPlaying)}),[O.isPlaying,C]);var q=function(e){if(G.current){var t=U.current&&("sleeping"===x.current.agentState||"entering_sleep"===x.current.agentState);if("VADEvent"===e.type){var n=e.is_speech;return t?void F("Ignoring VAD event (state:",x.current.agentState,")"):void(n&&!z.current?(z.current=!0,null==b||b()):!n&&z.current&&(z.current=!1,null==_||_()))}if("Results"===e.type||"Transcript"===e.type)return t?void F("Ignoring transcript (state:",x.current.agentState,")"):void(null==E||E(e))}else K("Received unexpected transcription message but service is not configured:",e)},Y=function(){if(U.current&&y){var e={type:"Settings",audio:{input:{encoding:"linear16",sample_rate:16e3},output:{encoding:"linear16",sample_rate:24e3}},agent:{language:y.language||"en",listen:{provider:{type:"deepgram",model:y.listenModel||"nova-2"}},think:r({provider:{type:y.thinkProviderType||"open_ai",model:y.thinkModel||"gpt-4o-mini"},prompt:y.instructions||"You are a helpful voice assistant."},y.thinkEndpointUrl&&y.thinkApiKey?{endpoint:{url:y.thinkEndpointUrl,headers:{authorization:"bearer ".concat(y.thinkApiKey)}}}:{}),speak:{provider:{type:"deepgram",model:y.voice||"aura-asteria-en"}},greeting:y.greeting}};K("Sending agent settings:",e),U.current.sendJSON(e)}else K("Cannot send agent settings: agent manager not initialized or agentOptions not provided")},V=function(e){if(U.current){var t="sleeping"===x.current.agentState||"entering_sleep"===x.current.agentState;if("UserStartedSpeaking"===e.type)return F("UserStartedSpeaking message received"),t?void F("Ignoring UserStartedSpeaking event (state:",x.current.agentState,")"):(K("Clearing audio queue (barge-in)"),ee(),null==b||b(),L.current&&(K("User started speaking after wake - resetting waiting flag"),L.current=!1),F("Dispatching AGENT_STATE_CHANGE to listening (from UserStartedSpeaking)"),void M({type:"AGENT_STATE_CHANGE",state:"listening"}));if("AgentThinking"===e.type)return F("Dispatching AGENT_STATE_CHANGE to thinking"),void M({type:"AGENT_STATE_CHANGE",state:"thinking"});if("AgentStartedSpeaking"===e.type)return F("Dispatching AGENT_STATE_CHANGE to speaking"),void M({type:"AGENT_STATE_CHANGE",state:"speaking"});if("AgentAudioDone"===e.type)return F("Dispatching AGENT_STATE_CHANGE to idle (from AgentAudioDone)"),void M({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==N||N(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||K("Agent warning:",e.description,"Code:",e.code):j({service:"agent",code:e.code||"agent_error",message:e.description||"Unknown agent error",details:e})}else K("Received unexpected agent message but service is not configured:",e)},J=function(e){U.current?(K("handleAgentAudio called! Received buffer of ".concat(e.byteLength," bytes")),L.current?K("Skipping audio playback because waiting for user voice after sleep"):(D.current?(K("Passing buffer to AudioManager.queueAudio()"),D.current.queueAudio(e).then((function(){K("Successfully queued audio buffer for playback")})).catch((function(e){K("Error queueing audio:",e)}))):K("Cannot queue audio: audioManagerRef.current is null"),A&&A(e))):K("Received unexpected agent audio but service is not configured")},Q=function(e){var t;if("connected"===(null===(t=G.current)||void 0===t?void 0:t.getState())&&G.current.sendBinary(e),U.current){var n="sleeping"===x.current.agentState||"entering_sleep"===x.current.agentState;"connected"!==U.current.getState()||n?n&&F("Skipping sendAudioData to agent (state:",x.current.agentState,")"):U.current.sendBinary(e)}},X=function(){return i(s,void 0,void 0,(function(){var e,t;return o(this,(function(n){switch(n.label){case 0:if(n.trys.push([0,14,,15]),K("Start method called"),!D.current)return[3,4];n.label=1;case 1:return n.trys.push([1,3,,4]),K("Ensuring AudioManager is initialized..."),[4,D.current.initialize()];case 2:return n.sent(),K("AudioManager initialized"),[3,4];case 3:throw e=n.sent(),K("Error initializing AudioManager:",e),e;case 4:return G.current?(K("Connecting Transcription WebSocket..."),[4,G.current.connect()]):[3,6];case 5:return n.sent(),K("Transcription WebSocket connected"),[3,7];case 6:K("Transcription manager not configured, skipping connection"),n.label=7;case 7:return U.current?(K("Connecting Agent WebSocket..."),[4,U.current.connect()]):[3,9];case 8:return n.sent(),K("Agent WebSocket connected"),[3,10];case 9:K("Agent manager not configured, skipping connection"),n.label=10;case 10:return D.current?(K("Starting recording..."),[4,D.current.startRecording()]):[3,12];case 11:return n.sent(),K("Recording started"),[3,13];case 12:throw K("AudioManager not initialized, cannot start recording"),new Error("Audio manager not available for recording");case 13:return K("Start method completed successfully"),[3,15];case 14:throw t=n.sent(),K("Error within start method:",t),j({service:"transcription",code:"start_error",message:"Failed to start voice interaction",details:t}),M({type:"READY_STATE_CHANGE",isReady:!1}),t;case 15:return[2]}}))}))},Z=function(){return i(s,void 0,void 0,(function(){var e;return o(this,(function(t){switch(t.label){case 0:K("Stopping voice interaction"),t.label=1;case 1:return t.trys.push([1,3,,4]),G.current&&(K("Sending CloseStream message to finalize transcription"),G.current.sendCloseStream()),D.current&&D.current.stopRecording(),[4,new Promise((function(e){return setTimeout(e,1e3)}))];case 2:return t.sent(),G.current&&G.current.close(),U.current&&U.current.close(),M({type:"READY_STATE_CHANGE",isReady:!1}),[2,Promise.resolve()];case 3:return e=t.sent(),K("Error stopping:",e),j({service:"transcription",code:"stop_error",message:"Error while stopping transcription",details:e}),M({type:"READY_STATE_CHANGE",isReady:!1}),[2,Promise.reject(e)];case 4:return[2]}}))}))},$=function(e){U.current?(K("Updating agent instructions:",e),U.current.sendJSON({type:"UpdatePrompt",prompt:e.instructions||e.context||""})):K("Cannot update instructions: agent manager not initialized or not configured")},ee=function(){if(K("๐ข clearAudio helper called"),D.current){try{if(K("๐ด Calling audioManager.clearAudioQueue()"),D.current.clearAudioQueue(),D.current.audioContext){K("๐ Manipulating audio context time reference");var e=D.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){K("โ ๏ธ Error creating silent buffer:",e)}}}catch(e){K("โ Error in clearAudio:",e)}K("๐ข clearAudio helper completed")}else K("โ Cannot clear audio: audioManagerRef.current is null")},te=function(){K("๐ด interruptAgent method called"),U.current?(ee(),K("๐ด Setting agent state to idle"),F("Dispatching AGENT_STATE_CHANGE to idle (from interruptAgent)"),M({type:"AGENT_STATE_CHANGE",state:"idle"}),K("๐ด interruptAgent method completed")):K("Cannot interrupt agent: agent manager not initialized or not configured")},ne=function(){U.current?(F("sleep() method called - initiating transition"),L.current=!0,ee(),F("Dispatching AGENT_STATE_CHANGE to entering_sleep (from sleep())"),M({type:"AGENT_STATE_CHANGE",state:"entering_sleep"})):K("Cannot put agent to sleep: agent manager not initialized or not configured")},re=function(){U.current?"sleeping"===x.current.agentState?(F("wake() method called from sleeping state"),L.current=!1,F("Dispatching AGENT_STATE_CHANGE to listening (from wake())"),M({type:"AGENT_STATE_CHANGE",state:"listening"})):F("wake() called but state is ".concat(x.current.agentState,", not 'sleeping'. Aborting wake.")):K("Cannot wake agent: agent manager not initialized or not configured")},ie=function(){U.current?(F("toggleSleep() method called. Current state via ref:",x.current.agentState),"sleeping"===x.current.agentState?re():"entering_sleep"!==x.current.agentState?ne():F("toggleSleep() called while already entering_sleep. No action."),F("Sleep toggle action dispatched or ignored")):K("Cannot toggle agent sleep state: agent manager not initialized or not configured")},oe=function(e){U.current?(K("Injecting agent message:",e),U.current.sendJSON({type:"InjectAgentMessage",content:e})):K("Cannot inject message: agent manager not initialized or not configured")};return e.useImperativeHandle(n,(function(){return{start:X,stop:Z,updateAgentInstructions:$,interruptAgent:te,sleep:ne,wake:re,toggleSleep:ie,injectAgentMessage:oe}})),null})),A=function(){this.auth="",this.voice="",this.greeting="",this.language="",this.thinkModel="",this.listenModel="",this.instructions="",this.thinkProvider="",this.provider={baseUrl:"",token:""}};function E(e){return void 0!==e.user}function T(e){return void 0!==e.assistant}exports.AgentMessageType=void 0,(f=exports.AgentMessageType||(exports.AgentMessageType={})).SETTINGS="Settings",f.UPDATE_PROMPT="UpdatePrompt",f.UPDATE_SPEAK="UpdateSpeak",f.INJECT_AGENT_MESSAGE="InjectAgentMessage",f.FUNCTION_CALL_RESPONSE="FunctionCallResponse",f.KEEP_ALIVE="KeepAlive",exports.AgentResponseType=void 0,(y=exports.AgentResponseType||(exports.AgentResponseType={})).WELCOME="Welcome",y.SETTINGS_APPLIED="SettingsApplied",y.PROMPT_UPDATED="PromptUpdated",y.SPEAK_UPDATED="SpeakUpdated",y.CONVERSATION_TEXT="ConversationText",y.USER_STARTED_SPEAKING="UserStartedSpeaking",y.AGENT_THINKING="AgentThinking",y.FUNCTION_CALL_REQUEST="FunctionCallRequest",y.FUNCTION_CALL_RESPONSE="FunctionCallResponse",y.AGENT_STARTED_SPEAKING="AgentStartedSpeaking",y.AGENT_AUDIO_DONE="AgentAudioDone",y.ERROR="Error",y.WARNING="Warning",exports.BehindScenesEventType=void 0,(v=exports.BehindScenesEventType||(exports.BehindScenesEventType={})).SETTINGS_APPLIED="SettingsApplied",v.AGENT_AUDIO_DONE="AgentAudioDone",v.USER_STARTED_SPEAKING="UserStartedSpeaking",v.AGENT_STARTED_SPEAKING="AgentStartedSpeaking",v.CONVERSATION_TEXT="ConversationText",v.END_OF_THOUGHT="EndOfThought",v.INTERRUPTION="Interruption",exports.VoiceBotActionType=void 0,(m=exports.VoiceBotActionType||(exports.VoiceBotActionType={})).START_LISTENING="start_listening",m.START_THINKING="start_thinking",m.START_SPEAKING="start_speaking",m.START_SLEEPING="start_sleeping",m.INCREMENT_SLEEP_TIMER="increment_sleep_timer",m.ADD_MESSAGE="add_message",m.ADD_BEHIND_SCENES_EVENT="add_behind_scenes_event",m.SET_PARAMS_ON_COPY_URL="set_attach_params_to_copy_url",exports.ConfigData=A,exports.DeepgramVoiceInteraction=S,exports.VoiceAI=function(t){var r=t.voiceConfig,a=t.onReady,s=t.onAgentUtterance,c=t.onTranscriptUpdate,u=t.onUserMessage,l=t.onError,d=t.deepgramRef,p=t.onAgentStateChange,g=t.onConnectionStateChange,h=t.onPlaybackStateChange,f=t.sleepOptions,y=t.onAgentAudioUpdate,v=t.debug,m=void 0!==v&&v,E=e.useState(new A),T=E[0],N=E[1];e.useEffect((function(){R()}),[r]);var R=function(){return i(void 0,void 0,void 0,(function(){var e;return o(this,(function(t){return e=window.atob(r),N(JSON.parse(e)),[2]}))}))},b=e.useMemo((function(){return{model:T.listenModel,language:T.language,smart_format:!0,interim_results:!0,diarize:!0,channels:1,keyterm:["Casella","Symbiosis","Kerfuffle","Supercalifragilisticexpialidocious"]}}),[T]),_=e.useMemo((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]),C=e.useMemo((function(){return{transcriptionUrl:"wss://api.deepgram.com/v1/listen",agentUrl:"wss://agent.deepgram.com/v1/agent/converse"}}),[]);return n.default.createElement(n.default.Fragment,null,n.default.createElement(S,{ref:d,apiKey:T.auth,transcriptionOptions:b,agentOptions:_,endpointConfig:C,onReady:a,onTranscriptUpdate:c,onAgentUtterance:s,onUserMessage:u,onAgentStateChange:p,onConnectionStateChange:g,onError:l,onPlaybackStateChange:h,debug:m,sleepOptions:f,onAgentAudioUpdate:y}))},exports.isAssistantMessage=T,exports.isConversationMessage=function(e){return E(e)||T(e)},exports.isLatencyMessage=function(e){return void 0!==e.tts_latency},exports.isUserMessage=E;
//# sourceMappingURL=index.js.map