@11labs/client 0.1.3 → 0.2.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/README.md +118 -15
- package/dist/BaseConversation.d.ts +76 -0
- package/dist/TextConversation.d.ts +4 -0
- package/dist/VoiceConversation.d.ts +27 -0
- package/dist/dist/BaseConversation.d.ts +80 -0
- package/dist/dist/TextConversation.d.ts +4 -0
- package/dist/dist/VoiceConversation.d.ts +27 -0
- package/dist/dist/index.d.ts +12 -0
- package/dist/dist/lib.cjs +2 -0
- package/dist/dist/lib.cjs.map +1 -0
- package/dist/dist/lib.modern.js +2 -0
- package/dist/dist/lib.modern.js.map +1 -0
- package/dist/dist/lib.module.js +2 -0
- package/dist/dist/lib.module.js.map +1 -0
- package/dist/dist/lib.umd.js +2 -0
- package/dist/dist/lib.umd.js.map +1 -0
- package/dist/dist/utils/BaseConnection.d.ts +99 -0
- package/dist/dist/utils/ConnectionFactory.d.ts +2 -0
- package/dist/dist/utils/WebRTCConnection.d.ts +23 -0
- package/dist/dist/utils/WebSocketConnection.d.ts +13 -0
- package/dist/dist/utils/applyDelay.d.ts +2 -0
- package/dist/dist/utils/audio.d.ts +2 -0
- package/dist/dist/utils/audioConcatProcessor.d.ts +1 -0
- package/dist/dist/utils/compatibility.d.ts +2 -0
- package/dist/dist/utils/createWorkletModuleLoader.d.ts +1 -0
- package/dist/dist/utils/events.d.ts +125 -0
- package/dist/dist/utils/input.d.ts +14 -0
- package/dist/dist/utils/output.d.ts +10 -0
- package/dist/dist/utils/overrides.d.ts +4 -0
- package/dist/dist/utils/postOverallFeedback.d.ts +1 -0
- package/dist/dist/utils/rawAudioProcessor.d.ts +1 -0
- package/dist/dist/version.d.ts +1 -0
- package/dist/index.d.ts +9 -77
- package/dist/lib.cjs +1 -1
- package/dist/lib.cjs.map +1 -1
- package/dist/lib.modern.js +1 -1
- package/dist/lib.modern.js.map +1 -1
- package/dist/lib.module.js +1 -1
- package/dist/lib.module.js.map +1 -1
- package/dist/lib.umd.js +1 -1
- package/dist/lib.umd.js.map +1 -1
- package/dist/utils/BaseConnection.d.ts +94 -0
- package/dist/utils/ConnectionFactory.d.ts +2 -0
- package/dist/utils/WebRTCConnection.d.ts +19 -0
- package/dist/utils/WebSocketConnection.d.ts +12 -0
- package/dist/utils/applyDelay.d.ts +2 -0
- package/dist/utils/events.d.ts +20 -3
- package/dist/utils/input.d.ts +1 -1
- package/dist/utils/output.d.ts +1 -1
- package/dist/utils/overrides.d.ts +4 -0
- package/dist/utils/postOverallFeedback.d.ts +1 -0
- package/dist/version.d.ts +1 -0
- package/package.json +17 -12
- package/LICENSE +0 -21
- package/dist/utils/connection.d.ts +0 -65
package/dist/lib.module.js
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
function e(){return e=Object.assign?Object.assign.bind():function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var o in t)({}).hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},e.apply(null,arguments)}function n(e){for(var n=window.atob(e),t=n.length,o=new Uint8Array(t),r=0;r<t;r++)o[r]=n.charCodeAt(r);return o.buffer}function t(e,n){try{var t=e()}catch(e){return n(e)}return t&&t.then?t.then(void 0,n):t}var o=new Map;function r(e,n){return function(r){try{var i,a=function(a){return i?a:t(function(){var t="data:application/javascript;base64,"+btoa(n);return Promise.resolve(r.addModule(t)).then(function(){o.set(e,t)})},function(){throw new Error("Failed to load the "+e+" worklet module. Make sure the browser supports AudioWorklets.")})},s=o.get(e);if(s)return Promise.resolve(r.addModule(s));var u=new Blob([n],{type:"application/javascript"}),c=URL.createObjectURL(u),l=t(function(){return Promise.resolve(r.addModule(c)).then(function(){o.set(e,c),i=1})},function(){URL.revokeObjectURL(c)});return Promise.resolve(l&&l.then?l.then(a):a(l))}catch(e){return Promise.reject(e)}}}var i=r("raw-audio-processor",'\nconst BIAS = 0x84;\nconst CLIP = 32635;\nconst encodeTable = [\n 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,\n 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\n];\n\nfunction encodeSample(sample) {\n let sign;\n let exponent;\n let mantissa;\n let muLawSample;\n sign = (sample >> 8) & 0x80;\n if (sign !== 0) sample = -sample;\n sample = sample + BIAS;\n if (sample > CLIP) sample = CLIP;\n exponent = encodeTable[(sample>>7) & 0xFF];\n mantissa = (sample >> (exponent+3)) & 0x0F;\n muLawSample = ~(sign | (exponent << 4) | mantissa);\n \n return muLawSample;\n}\n\nclass RawAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case "setFormat":\n this.isMuted = false;\n this.buffer = []; // Initialize an empty buffer\n this.bufferSize = data.sampleRate / 4;\n this.format = data.format;\n\n if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) {\n globalThis.LibSampleRate.create(1, sampleRate, data.sampleRate).then(resampler => {\n this.resampler = resampler;\n });\n }\n break;\n case "setMuted":\n this.isMuted = data.isMuted;\n break;\n }\n };\n }\n process(inputs) {\n if (!this.buffer) {\n return true;\n }\n \n const input = inputs[0]; // Get the first input node\n if (input.length > 0) {\n let channelData = input[0]; // Get the first channel\'s data\n\n // Resample the audio if necessary\n if (this.resampler) {\n channelData = this.resampler.full(channelData);\n }\n\n // Add channel data to the buffer\n this.buffer.push(...channelData);\n // Get max volume \n let sum = 0.0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const maxVolume = Math.sqrt(sum / channelData.length);\n // Check if buffer size has reached or exceeded the threshold\n if (this.buffer.length >= this.bufferSize) {\n const float32Array = this.isMuted \n ? new Float32Array(this.buffer.length)\n : new Float32Array(this.buffer);\n\n let encodedArray = this.format === "ulaw"\n ? new Uint8Array(float32Array.length)\n : new Int16Array(float32Array.length);\n\n // Iterate through the Float32Array and convert each sample to PCM16\n for (let i = 0; i < float32Array.length; i++) {\n // Clamp the value to the range [-1, 1]\n let sample = Math.max(-1, Math.min(1, float32Array[i]));\n\n // Scale the sample to the range [-32768, 32767]\n let value = sample < 0 ? sample * 32768 : sample * 32767;\n if (this.format === "ulaw") {\n value = encodeSample(Math.round(value));\n }\n\n encodedArray[i] = value;\n }\n\n // Send the buffered data to the main script\n this.port.postMessage([encodedArray, maxVolume]);\n\n // Clear the buffer after sending\n this.buffer = [];\n }\n }\n return true; // Continue processing\n }\n}\nregisterProcessor("raw-audio-processor", RawAudioProcessor);\n');function a(){return["iPad Simulator","iPhone Simulator","iPod Simulator","iPad","iPhone","iPod"].includes(navigator.platform)||navigator.userAgent.includes("Mac")&&"ontouchend"in document}var s=/*#__PURE__*/function(){function e(e,n,t,o){this.context=void 0,this.analyser=void 0,this.worklet=void 0,this.inputStream=void 0,this.context=e,this.analyser=n,this.worklet=t,this.inputStream=o}e.create=function(n){var t=n.sampleRate,o=n.format,r=n.preferHeadphonesForIosDevices;try{var s=null,u=null;return Promise.resolve(function(n,c){try{var l=function(){function n(){function n(){return Promise.resolve(i(s.audioWorklet)).then(function(){return Promise.resolve(navigator.mediaDevices.getUserMedia({audio:c})).then(function(n){var r=s.createMediaStreamSource(u=n),i=new AudioWorkletNode(s,"raw-audio-processor");return i.port.postMessage({type:"setFormat",format:o,sampleRate:t}),r.connect(a),a.connect(i),Promise.resolve(s.resume()).then(function(){return new e(s,a,i,u)})})})}var r=navigator.mediaDevices.getSupportedConstraints().sampleRate,a=(s=new window.AudioContext(r?{sampleRate:t}:{})).createAnalyser(),l=function(){if(!r)return Promise.resolve(s.audioWorklet.addModule("https://cdn.jsdelivr.net/npm/@alexanderolsen/libsamplerate-js@2.1.2/dist/libsamplerate.worklet.js")).then(function(){})}();return l&&l.then?l.then(n):n()}var c={sampleRate:{ideal:t},echoCancellation:{ideal:!0},noiseSuppression:{ideal:!0}},l=function(){if(a()&&r)return Promise.resolve(window.navigator.mediaDevices.enumerateDevices()).then(function(e){var n=e.find(function(e){return"audioinput"===e.kind&&["airpod","headphone","earphone"].find(function(n){return e.label.toLowerCase().includes(n)})});n&&(c.deviceId={ideal:n.deviceId})})}();return l&&l.then?l.then(n):n()}()}catch(e){return c(e)}return l&&l.then?l.then(void 0,c):l}(0,function(e){var n,t;throw null==(n=u)||n.getTracks().forEach(function(e){return e.stop()}),null==(t=s)||t.close(),e}))}catch(e){return Promise.reject(e)}};var n=e.prototype;return n.close=function(){try{return this.inputStream.getTracks().forEach(function(e){return e.stop()}),Promise.resolve(this.context.close()).then(function(){})}catch(e){return Promise.reject(e)}},n.setMuted=function(e){this.worklet.port.postMessage({type:"setMuted",isMuted:e})},e}(),u=r("audio-concat-processor",'\nconst decodeTable = [0,132,396,924,1980,4092,8316,16764];\n\nexport function decodeSample(muLawSample) {\n let sign;\n let exponent;\n let mantissa;\n let sample;\n muLawSample = ~muLawSample;\n sign = (muLawSample & 0x80);\n exponent = (muLawSample >> 4) & 0x07;\n mantissa = muLawSample & 0x0F;\n sample = decodeTable[exponent] + (mantissa << (exponent+3));\n if (sign !== 0) sample = -sample;\n\n return sample;\n}\n\nclass AudioConcatProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffers = []; // Initialize an empty buffer\n this.cursor = 0;\n this.currentBuffer = null;\n this.wasInterrupted = false;\n this.finished = false;\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case "setFormat":\n this.format = data.format;\n break;\n case "buffer":\n this.wasInterrupted = false;\n this.buffers.push(\n this.format === "ulaw"\n ? new Uint8Array(data.buffer)\n : new Int16Array(data.buffer)\n );\n break;\n case "interrupt":\n this.wasInterrupted = true;\n break;\n case "clearInterrupted":\n if (this.wasInterrupted) {\n this.wasInterrupted = false;\n this.buffers = [];\n this.currentBuffer = null;\n }\n }\n };\n }\n process(_, outputs) {\n let finished = false;\n const output = outputs[0][0];\n for (let i = 0; i < output.length; i++) {\n if (!this.currentBuffer) {\n if (this.buffers.length === 0) {\n finished = true;\n break;\n }\n this.currentBuffer = this.buffers.shift();\n this.cursor = 0;\n }\n\n let value = this.currentBuffer[this.cursor];\n if (this.format === "ulaw") {\n value = decodeSample(value);\n }\n output[i] = value / 32768;\n this.cursor++;\n\n if (this.cursor >= this.currentBuffer.length) {\n this.currentBuffer = null;\n }\n }\n\n if (this.finished !== finished) {\n this.finished = finished;\n this.port.postMessage({ type: "process", finished });\n }\n\n return true; // Continue processing\n }\n}\n\nregisterProcessor("audio-concat-processor", AudioConcatProcessor);\n'),c=/*#__PURE__*/function(){function e(e,n,t,o){this.context=void 0,this.analyser=void 0,this.gain=void 0,this.worklet=void 0,this.context=e,this.analyser=n,this.gain=t,this.worklet=o}return e.create=function(n){var t=n.sampleRate,o=n.format;try{var r=null;return Promise.resolve(function(n,i){try{var a=(s=(r=new AudioContext({sampleRate:t})).createAnalyser(),(c=r.createGain()).connect(s),s.connect(r.destination),Promise.resolve(u(r.audioWorklet)).then(function(){var n=new AudioWorkletNode(r,"audio-concat-processor");return n.port.postMessage({type:"setFormat",format:o}),n.connect(c),Promise.resolve(r.resume()).then(function(){return new e(r,s,c,n)})}))}catch(e){return i(e)}var s,c;return a&&a.then?a.then(void 0,i):a}(0,function(e){var n;throw null==(n=r)||n.close(),e}))}catch(e){return Promise.reject(e)}},e.prototype.close=function(){try{return Promise.resolve(this.context.close()).then(function(){})}catch(e){return Promise.reject(e)}},e}();function l(e){return!!e.type}var d=/*#__PURE__*/function(){function e(e,n,t,o){var r=this;this.socket=void 0,this.conversationId=void 0,this.inputFormat=void 0,this.outputFormat=void 0,this.queue=[],this.disconnectionDetails=null,this.onDisconnectCallback=null,this.onMessageCallback=null,this.socket=e,this.conversationId=n,this.inputFormat=t,this.outputFormat=o,this.socket.addEventListener("error",function(e){setTimeout(function(){return r.disconnect({reason:"error",message:"The connection was closed due to a socket error.",context:e})},0)}),this.socket.addEventListener("close",function(e){r.disconnect(1e3===e.code?{reason:"agent",context:e}:{reason:"error",message:e.reason||"The connection was closed by the server.",context:e})}),this.socket.addEventListener("message",function(e){try{var n=JSON.parse(e.data);if(!l(n))return;r.onMessageCallback?r.onMessageCallback(n):r.queue.push(n)}catch(e){}})}e.create=function(n){try{var t=null;return Promise.resolve(function(o,r){try{var i=(s=null!=(a=n.origin)?a:"wss://api.elevenlabs.io",u=n.signedUrl?n.signedUrl:s+"/v1/convai/conversation?agent_id="+n.agentId,c=["convai"],n.authorization&&c.push("bearer."+n.authorization),t=new WebSocket(u,c),Promise.resolve(new Promise(function(e,o){t.addEventListener("open",function(){var e,o,r,i,a,s={type:"conversation_initiation_client_data"};n.overrides&&(s.conversation_config_override={agent:{prompt:null==(o=n.overrides.agent)?void 0:o.prompt,first_message:null==(r=n.overrides.agent)?void 0:r.firstMessage,language:null==(i=n.overrides.agent)?void 0:i.language},tts:{voice_id:null==(a=n.overrides.tts)?void 0:a.voiceId}}),n.customLlmExtraBody&&(s.custom_llm_extra_body=n.customLlmExtraBody),n.dynamicVariables&&(s.dynamic_variables=n.dynamicVariables),null==(e=t)||e.send(JSON.stringify(s))},{once:!0}),t.addEventListener("error",function(e){setTimeout(function(){return o(e)},0)}),t.addEventListener("close",o),t.addEventListener("message",function(n){var t=JSON.parse(n.data);l(t)&&("conversation_initiation_metadata"===t.type?e(t.conversation_initiation_metadata_event):console.warn("First received message is not conversation metadata."))},{once:!0})})).then(function(n){var o=n.conversation_id,r=n.agent_output_audio_format,i=n.user_input_audio_format,a=h(null!=i?i:"pcm_16000"),s=h(r);return new e(t,o,a,s)}))}catch(e){return r(e)}var a,s,u,c;return i&&i.then?i.then(void 0,r):i}(0,function(e){var n;throw null==(n=t)||n.close(),e}))}catch(e){return Promise.reject(e)}};var n=e.prototype;return n.close=function(){this.socket.close()},n.sendMessage=function(e){this.socket.send(JSON.stringify(e))},n.onMessage=function(e){this.onMessageCallback=e,this.queue.forEach(e),this.queue=[]},n.onDisconnect=function(e){this.onDisconnectCallback=e,this.disconnectionDetails&&e(this.disconnectionDetails)},n.disconnect=function(e){var n;this.disconnectionDetails||(this.disconnectionDetails=e,null==(n=this.onDisconnectCallback)||n.call(this,e))},e}();function h(e){var n=e.split("_"),t=n[0],o=n[1];if(!["pcm","ulaw"].includes(t))throw new Error("Invalid format: "+e);var r=parseInt(o);if(isNaN(r))throw new Error("Invalid sample rate: "+o);return{format:t,sampleRate:r}}function f(e,n){try{var t=e()}catch(e){return n(e)}return t&&t.then?t.then(void 0,n):t}var p={clientTools:{}},m={onConnect:function(){},onDebug:function(){},onDisconnect:function(){},onError:function(){},onMessage:function(){},onAudio:function(){},onModeChange:function(){},onStatusChange:function(){},onCanSendFeedbackChange:function(){}},v=/*#__PURE__*/function(){function t(e,t,o,r,i){var a=this,s=this,u=this;this.options=void 0,this.connection=void 0,this.input=void 0,this.output=void 0,this.wakeLock=void 0,this.lastInterruptTimestamp=0,this.mode="listening",this.status="connecting",this.inputFrequencyData=void 0,this.outputFrequencyData=void 0,this.volume=1,this.currentEventId=1,this.lastFeedbackEventId=1,this.canSendFeedback=!1,this.endSession=function(){return u.endSessionWithDetails({reason:"user"})},this.endSessionWithDetails=function(e){try{var n=function(){return a.connection.close(),Promise.resolve(a.input.close()).then(function(){return Promise.resolve(a.output.close()).then(function(){a.updateStatus("disconnected"),a.options.onDisconnect(e)})})};if("connected"!==a.status&&"connecting"!==a.status)return Promise.resolve();a.updateStatus("disconnecting");var t=f(function(){var e;return Promise.resolve(null==(e=a.wakeLock)?void 0:e.release()).then(function(){a.wakeLock=null})},function(){});return Promise.resolve(t&&t.then?t.then(n):n())}catch(e){return Promise.reject(e)}},this.updateMode=function(e){e!==u.mode&&(u.mode=e,u.options.onModeChange({mode:e}))},this.updateStatus=function(e){e!==u.status&&(u.status=e,u.options.onStatusChange({status:e}))},this.updateCanSendFeedback=function(){var e=u.currentEventId!==u.lastFeedbackEventId;u.canSendFeedback!==e&&(u.canSendFeedback=e,u.options.onCanSendFeedbackChange({canSendFeedback:e}))},this.onMessage=function(e){try{switch(e.type){case"interruption":return e.interruption_event&&(s.lastInterruptTimestamp=e.interruption_event.event_id),s.fadeOutAudio(),Promise.resolve();case"agent_response":return s.options.onMessage({source:"ai",message:e.agent_response_event.agent_response}),Promise.resolve();case"user_transcript":return s.options.onMessage({source:"user",message:e.user_transcription_event.user_transcript}),Promise.resolve();case"internal_tentative_agent_response":return s.options.onDebug({type:"tentative_agent_response",response:e.tentative_agent_response_internal_event.tentative_agent_response}),Promise.resolve();case"client_tool_call":return Promise.resolve(function(){if(s.options.clientTools.hasOwnProperty(e.client_tool_call.tool_name)){var n=f(function(){return Promise.resolve(s.options.clientTools[e.client_tool_call.tool_name](e.client_tool_call.parameters)).then(function(n){var t="object"==typeof n?JSON.stringify(n):String(n);s.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:t,is_error:!1})})},function(n){s.onError("Client tool execution failed with following error: "+(null==n?void 0:n.message),{clientToolName:e.client_tool_call.tool_name}),s.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:"Client tool execution failed: "+(null==n?void 0:n.message),is_error:!0})});if(n&&n.then)return n.then(function(){})}else{if(s.options.onUnhandledClientToolCall)return void s.options.onUnhandledClientToolCall(e.client_tool_call);s.onError("Client tool with name "+e.client_tool_call.tool_name+" is not defined on client",{clientToolName:e.client_tool_call.tool_name}),s.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:"Client tool with name "+e.client_tool_call.tool_name+" is not defined on client",is_error:!0})}}());case"audio":return s.lastInterruptTimestamp<=e.audio_event.event_id&&(s.options.onAudio(e.audio_event.audio_base_64),s.addAudioBase64Chunk(e.audio_event.audio_base_64),s.currentEventId=e.audio_event.event_id,s.updateCanSendFeedback(),s.updateMode("speaking")),Promise.resolve();case"ping":return s.connection.sendMessage({type:"pong",event_id:e.ping_event.event_id}),Promise.resolve();default:return s.options.onDebug(e),Promise.resolve()}}catch(e){return Promise.reject(e)}},this.onInputWorkletMessage=function(e){var n,t;"connected"===u.status&&u.connection.sendMessage({user_audio_chunk:(n=e.data[0].buffer,t=new Uint8Array(n),window.btoa(String.fromCharCode.apply(String,t)))})},this.onOutputWorkletMessage=function(e){var n=e.data;"process"===n.type&&u.updateMode(n.finished?"listening":"speaking")},this.addAudioBase64Chunk=function(e){u.output.gain.gain.value=u.volume,u.output.worklet.port.postMessage({type:"clearInterrupted"}),u.output.worklet.port.postMessage({type:"buffer",buffer:n(e)})},this.fadeOutAudio=function(){u.updateMode("listening"),u.output.worklet.port.postMessage({type:"interrupt"}),u.output.gain.gain.exponentialRampToValueAtTime(1e-4,u.output.context.currentTime+2),setTimeout(function(){u.output.gain.gain.value=u.volume,u.output.worklet.port.postMessage({type:"clearInterrupted"})},2e3)},this.onError=function(e,n){console.error(e,n),u.options.onError(e,n)},this.calculateVolume=function(e){if(0===e.length)return 0;for(var n=0,t=0;t<e.length;t++)n+=e[t]/255;return(n/=e.length)<0?0:n>1?1:n},this.getId=function(){return u.connection.conversationId},this.isOpen=function(){return"connected"===u.status},this.setVolume=function(e){u.volume=e.volume},this.setMicMuted=function(e){u.input.setMuted(e)},this.getInputByteFrequencyData=function(){return null!=u.inputFrequencyData||(u.inputFrequencyData=new Uint8Array(u.input.analyser.frequencyBinCount)),u.input.analyser.getByteFrequencyData(u.inputFrequencyData),u.inputFrequencyData},this.getOutputByteFrequencyData=function(){return null!=u.outputFrequencyData||(u.outputFrequencyData=new Uint8Array(u.output.analyser.frequencyBinCount)),u.output.analyser.getByteFrequencyData(u.outputFrequencyData),u.outputFrequencyData},this.getInputVolume=function(){return u.calculateVolume(u.getInputByteFrequencyData())},this.getOutputVolume=function(){return u.calculateVolume(u.getOutputByteFrequencyData())},this.sendFeedback=function(e){u.canSendFeedback?(u.connection.sendMessage({type:"feedback",score:e?"like":"dislike",event_id:u.currentEventId}),u.lastFeedbackEventId=u.currentEventId,u.updateCanSendFeedback()):console.warn(0===u.lastFeedbackEventId?"Cannot send feedback: the conversation has not started yet.":"Cannot send feedback: feedback has already been sent for the current response.")},this.sendContextualUpdate=function(e){u.connection.sendMessage({type:"contextual_update",text:e})},this.options=e,this.connection=t,this.input=o,this.output=r,this.wakeLock=i,this.options.onConnect({conversationId:t.conversationId}),this.connection.onDisconnect(this.endSessionWithDetails),this.connection.onMessage(this.onMessage),this.input.worklet.port.onmessage=this.onInputWorkletMessage,this.output.worklet.port.onmessage=this.onOutputWorkletMessage,this.updateStatus("connected")}return t.startSession=function(n){try{var o=function(){return f(function(){return Promise.resolve(navigator.mediaDevices.getUserMedia({audio:!0})).then(function(o){var f;function p(){return Promise.resolve(d.create(n)).then(function(o){return u=o,Promise.resolve(Promise.all([s.create(e({},u.inputFormat,{preferHeadphonesForIosDevices:n.preferHeadphonesForIosDevices})),c.create(u.outputFormat)])).then(function(e){var n;return i=e[0],l=e[1],null==(n=h)||n.getTracks().forEach(function(e){return e.stop()}),h=null,new t(r,u,i,l,v)})})}h=o;var m,g=null!=(f=n.connectionDelay)?f:{default:0,android:3e3},y=g.default;if(/android/i.test(navigator.userAgent))y=null!=(m=g.android)?m:y;else if(a()){var _;y=null!=(_=g.ios)?_:y}var b=function(){if(y>0)return Promise.resolve(new Promise(function(e){return setTimeout(e,y)})).then(function(){})}();return b&&b.then?b.then(p):p()})},function(e){var n,t,o;return r.onStatusChange({status:"disconnected"}),null==(n=h)||n.getTracks().forEach(function(e){return e.stop()}),null==(t=u)||t.close(),Promise.resolve(null==(o=i)?void 0:o.close()).then(function(){var n;return Promise.resolve(null==(n=l)?void 0:n.close()).then(function(){function n(){throw e}var t=f(function(){var e;return Promise.resolve(null==(e=v)?void 0:e.release()).then(function(){v=null})},function(){});return t&&t.then?t.then(n):n()})})})},r=e({},p,m,n);r.onStatusChange({status:"connecting"}),r.onCanSendFeedbackChange({canSendFeedback:!1});var i=null,u=null,l=null,h=null,v=null,g=function(e){if(null==(e=n.useWakeLock)||e){var t=f(function(){return Promise.resolve(navigator.wakeLock.request("screen")).then(function(e){v=e})},function(){});if(t&&t.then)return t.then(function(){})}}();return Promise.resolve(g&&g.then?g.then(o):o())}catch(e){return Promise.reject(e)}},t}();function g(e,n,t){return void 0===t&&(t="https://api.elevenlabs.io"),fetch(t+"/v1/convai/conversations/"+e+"/feedback",{method:"POST",body:JSON.stringify({feedback:n?"like":"dislike"}),headers:{"Content-Type":"application/json"}})}export{v as Conversation,g as postOverallFeedback};
|
1
|
+
import{Room as e,RoomEvent as n,ConnectionState as t,Track as o}from"livekit-client";function r(){return r=Object.assign?Object.assign.bind():function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var o in t)({}).hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e},r.apply(null,arguments)}function i(e,n){e.prototype=Object.create(n.prototype),e.prototype.constructor=e,s(e,n)}function s(e,n){return s=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,n){return e.__proto__=n,e},s(e,n)}var a=new Uint8Array(0),u=/*#__PURE__*/function(){function e(e,n){var t=this,o=this,r=this;this.options=void 0,this.connection=void 0,this.lastInterruptTimestamp=0,this.mode="listening",this.status="connecting",this.volume=1,this.currentEventId=1,this.lastFeedbackEventId=1,this.canSendFeedback=!1,this.endSessionWithDetails=function(e){try{return"connected"!==o.status&&"connecting"!==o.status?Promise.resolve():(o.updateStatus("disconnecting"),Promise.resolve(o.handleEndSession()).then(function(){o.updateStatus("disconnected"),o.options.onDisconnect(e)}))}catch(e){return Promise.reject(e)}},this.onMessage=function(e){try{switch(e.type){case"interruption":return r.handleInterruption(e),Promise.resolve();case"agent_response":return r.handleAgentResponse(e),Promise.resolve();case"user_transcript":return r.handleUserTranscript(e),Promise.resolve();case"internal_tentative_agent_response":return r.handleTentativeAgentResponse(e),Promise.resolve();case"client_tool_call":return Promise.resolve(r.handleClientToolCall(e)).then(function(){});case"audio":return r.handleAudio(e),Promise.resolve();case"ping":return r.connection.sendMessage({type:"pong",event_id:e.ping_event.event_id}),Promise.resolve();default:return r.options.onDebug(e),Promise.resolve()}}catch(e){return Promise.reject(e)}},this.setVolume=function(e){t.volume=e.volume},this.options=e,this.connection=n,this.options.onConnect({conversationId:n.conversationId}),this.connection.onMessage(this.onMessage),this.connection.onDisconnect(this.endSessionWithDetails),this.updateStatus("connected")}e.getFullOptions=function(e){return r({clientTools:{},onConnect:function(){},onDebug:function(){},onDisconnect:function(){},onError:function(){},onMessage:function(){},onAudio:function(){},onModeChange:function(){},onStatusChange:function(){},onCanSendFeedbackChange:function(){}},e)};var n=e.prototype;return n.endSession=function(){return this.endSessionWithDetails({reason:"user"})},n.handleEndSession=function(){try{return this.connection.close(),Promise.resolve()}catch(e){return Promise.reject(e)}},n.updateMode=function(e){e!==this.mode&&(this.mode=e,this.options.onModeChange({mode:e}))},n.updateStatus=function(e){e!==this.status&&(this.status=e,this.options.onStatusChange({status:e}))},n.updateCanSendFeedback=function(){var e=this.currentEventId!==this.lastFeedbackEventId;this.canSendFeedback!==e&&(this.canSendFeedback=e,this.options.onCanSendFeedbackChange({canSendFeedback:e}))},n.handleInterruption=function(e){e.interruption_event&&(this.lastInterruptTimestamp=e.interruption_event.event_id)},n.handleAgentResponse=function(e){this.options.onMessage({source:"ai",message:e.agent_response_event.agent_response})},n.handleUserTranscript=function(e){this.options.onMessage({source:"user",message:e.user_transcription_event.user_transcript})},n.handleTentativeAgentResponse=function(e){this.options.onDebug({type:"tentative_agent_response",response:e.tentative_agent_response_internal_event.tentative_agent_response})},n.handleClientToolCall=function(e){try{var n=this;return Promise.resolve(function(){if(Object.prototype.hasOwnProperty.call(n.options.clientTools,e.client_tool_call.tool_name)){var t=function(t,o){try{var r=Promise.resolve(n.options.clientTools[e.client_tool_call.tool_name](e.client_tool_call.parameters)).then(function(t){var o="object"==typeof t?JSON.stringify(t):String(t);n.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:o,is_error:!1})})}catch(e){return o(e)}return r&&r.then?r.then(void 0,o):r}(0,function(t){n.onError("Client tool execution failed with following error: "+(null==t?void 0:t.message),{clientToolName:e.client_tool_call.tool_name}),n.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:"Client tool execution failed: "+(null==t?void 0:t.message),is_error:!0})});if(t&&t.then)return t.then(function(){})}else{if(n.options.onUnhandledClientToolCall)return void n.options.onUnhandledClientToolCall(e.client_tool_call);n.onError("Client tool with name "+e.client_tool_call.tool_name+" is not defined on client",{clientToolName:e.client_tool_call.tool_name}),n.connection.sendMessage({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:"Client tool with name "+e.client_tool_call.tool_name+" is not defined on client",is_error:!0})}}())}catch(e){return Promise.reject(e)}},n.handleAudio=function(e){},n.onError=function(e,n){console.error(e,n),this.options.onError(e,n)},n.getId=function(){return this.connection.conversationId},n.isOpen=function(){return"connected"===this.status},n.setMicMuted=function(e){},n.getInputByteFrequencyData=function(){return a},n.getOutputByteFrequencyData=function(){return a},n.getInputVolume=function(){return 0},n.getOutputVolume=function(){return 0},n.sendFeedback=function(e){this.canSendFeedback?(this.connection.sendMessage({type:"feedback",score:e?"like":"dislike",event_id:this.currentEventId}),this.lastFeedbackEventId=this.currentEventId,this.updateCanSendFeedback()):console.warn(0===this.lastFeedbackEventId?"Cannot send feedback: the conversation has not started yet.":"Cannot send feedback: feedback has already been sent for the current response.")},n.sendContextualUpdate=function(e){this.connection.sendMessage({type:"contextual_update",text:e})},n.sendUserMessage=function(e){this.connection.sendMessage({type:"user_message",text:e})},n.sendUserActivity=function(){this.connection.sendMessage({type:"user_activity"})},n.sendMCPToolApprovalResult=function(e,n){this.connection.sendMessage({type:"mcp_tool_approval_result",tool_call_id:e,is_approved:n})},e}(),c=/*#__PURE__*/function(){function e(e){void 0===e&&(e={}),this.queue=[],this.disconnectionDetails=null,this.onDisconnectCallback=null,this.onMessageCallback=null,this.onDebug=void 0,this.onDebug=e.onDebug}var n=e.prototype;return n.debug=function(e){this.onDebug&&this.onDebug(e)},n.onMessage=function(e){this.onMessageCallback=e;var n=this.queue;this.queue=[],n.length>0&&queueMicrotask(function(){n.forEach(e)})},n.onDisconnect=function(e){this.onDisconnectCallback=e;var n=this.disconnectionDetails;n&&queueMicrotask(function(){e(n)})},n.disconnect=function(e){var n;this.disconnectionDetails||(this.disconnectionDetails=e,null==(n=this.onDisconnectCallback)||n.call(this,e))},n.handleMessage=function(e){this.onMessageCallback?this.onMessageCallback(e):this.queue.push(e)},e}();function l(e){var n=e.split("_"),t=n[0],o=n[1];if(!["pcm","ulaw"].includes(t))throw new Error("Invalid format: "+e);var r=Number.parseInt(o);if(Number.isNaN(r))throw new Error("Invalid sample rate: "+o);return{format:t,sampleRate:r}}var d="0.4.0";function h(e){return!!e.type}var f="conversation_initiation_client_data";function p(e){var n,t,o,r,i,s={type:f};return e.overrides&&(s.conversation_config_override={agent:{prompt:null==(n=e.overrides.agent)?void 0:n.prompt,first_message:null==(t=e.overrides.agent)?void 0:t.firstMessage,language:null==(o=e.overrides.agent)?void 0:o.language},tts:{voice_id:null==(r=e.overrides.tts)?void 0:r.voiceId},conversation:{text_only:null==(i=e.overrides.conversation)?void 0:i.textOnly}}),e.customLlmExtraBody&&(s.custom_llm_extra_body=e.customLlmExtraBody),e.dynamicVariables&&(s.dynamic_variables=e.dynamicVariables),e.userId&&(s.user_id=e.userId),s}var v=/*#__PURE__*/function(e){function n(n,t,o,r){var i;return(i=e.call(this)||this).socket=void 0,i.conversationId=void 0,i.inputFormat=void 0,i.outputFormat=void 0,i.socket=n,i.conversationId=t,i.inputFormat=o,i.outputFormat=r,i.socket.addEventListener("error",function(e){setTimeout(function(){return i.disconnect({reason:"error",message:"The connection was closed due to a socket error.",context:e})},0)}),i.socket.addEventListener("close",function(e){i.disconnect(1e3===e.code?{reason:"agent",context:e}:{reason:"error",message:e.reason||"The connection was closed by the server.",context:e})}),i.socket.addEventListener("message",function(e){try{var n=JSON.parse(e.data);if(!h(n))return;i.handleMessage(n)}catch(e){}}),i}i(n,e),n.create=function(e){try{var t=null;return Promise.resolve(function(o,r){try{var i=function(){var o,r,i,s,a=null!=(o=e.origin)?o:"wss://api.elevenlabs.io",u=(null==(r=e.overrides)||null==(r=r.client)?void 0:r.version)||d,c=(null==(i=e.overrides)||null==(i=i.client)?void 0:i.source)||"js_sdk";if(e.signedUrl){var f=e.signedUrl.includes("?")?"&":"?";s=""+e.signedUrl+f+"source="+c+"&version="+u}else s=a+"/v1/convai/conversation?agent_id="+e.agentId+"&source="+c+"&version="+u;var v=["convai"];return e.authorization&&v.push("bearer."+e.authorization),t=new WebSocket(s,v),Promise.resolve(new Promise(function(n,o){t.addEventListener("open",function(){var n,o=p(e);null==(n=t)||n.send(JSON.stringify(o))},{once:!0}),t.addEventListener("error",function(e){setTimeout(function(){return o(e)},0)}),t.addEventListener("close",o),t.addEventListener("message",function(e){var t=JSON.parse(e.data);h(t)&&("conversation_initiation_metadata"===t.type?n(t.conversation_initiation_metadata_event):console.warn("First received message is not conversation metadata."))},{once:!0})})).then(function(e){var o=e.conversation_id,r=e.agent_output_audio_format,i=e.user_input_audio_format,s=l(null!=i?i:"pcm_16000"),a=l(r);return new n(t,o,s,a)})}()}catch(e){return r(e)}return i&&i.then?i.then(void 0,r):i}(0,function(e){var n;throw null==(n=t)||n.close(),e}))}catch(e){return Promise.reject(e)}};var t=n.prototype;return t.close=function(){this.socket.close()},t.sendMessage=function(e){this.socket.send(JSON.stringify(e))},n}(c);function m(e,n){try{var t=e()}catch(e){return n(e)}return t&&t.then?t.then(void 0,n):t}var g=/*#__PURE__*/function(r){function s(e,n,t,o,i){var s;return void 0===i&&(i={}),(s=r.call(this,i)||this).conversationId=void 0,s.inputFormat=void 0,s.outputFormat=void 0,s.room=void 0,s.isConnected=!1,s.room=e,s.conversationId=n,s.inputFormat=t,s.outputFormat=o,s.setupRoomEventListeners(),s}i(s,r),s.create=function(t){try{var o,r=function(r){var i=new e;return m(function(){var e="webrtc-"+Date.now(),r=l("pcm_48000"),a=l("pcm_48000"),u=new s(i,e,r,a,t);return Promise.resolve(i.connect(t.livekitUrl||"wss://livekit.rtc.elevenlabs.io",o)).then(function(){return Promise.resolve(new Promise(function(e){if(u.isConnected)e();else{var t=function(){i.off(n.Connected,t),e()};i.on(n.Connected,t)}})).then(function(){return i.name&&(u.conversationId=i.name),Promise.resolve(i.localParticipant.setMicrophoneEnabled(!0)).then(function(){var e=p(t);return u.debug({type:f,message:e}),Promise.resolve(u.sendMessage(e)).then(function(){return u})})})})},function(e){return Promise.resolve(i.disconnect()).then(function(){throw e})})},i=function(){if(!("conversationToken"in t)||!t.conversationToken)return function(){if("agentId"in t&&t.agentId)return m(function(){var e,n,r=(null==(e=t.overrides)||null==(e=e.client)?void 0:e.version)||d,i=(null==(n=t.overrides)||null==(n=n.client)?void 0:n.source)||"js_sdk";return Promise.resolve(fetch("https://api.elevenlabs.io/v1/convai/conversation/token?agent_id="+t.agentId+"&source="+i+"&version="+r)).then(function(e){if(!e.ok)throw new Error("ElevenLabs API returned "+e.status+" "+e.statusText);return Promise.resolve(e.json()).then(function(e){if(!(o=e.token))throw new Error("No conversation token received from API")})})},function(e){var n=e instanceof Error?e.message:String(e);throw e instanceof Error&&e.message.includes("401")&&(n="Your agent has authentication enabled, but no signed URL or conversation token was provided."),new Error("Failed to fetch conversation token for agent "+t.agentId+": "+n)});throw new Error("Either conversationToken or agentId is required for WebRTC connection")}();o=t.conversationToken}();return Promise.resolve(i&&i.then?i.then(r):r())}catch(e){return Promise.reject(e)}};var a=s.prototype;return a.setupRoomEventListeners=function(){var e=this,r=this;this.room.on(n.Connected,function(){try{return r.isConnected=!0,console.info("WebRTC room connected"),Promise.resolve()}catch(e){return Promise.reject(e)}}),this.room.on(n.Disconnected,function(n){e.isConnected=!1,e.disconnect({reason:"agent",context:new CloseEvent("close",{reason:null==n?void 0:n.toString()})})}),this.room.on(n.ConnectionStateChanged,function(n){n===t.Disconnected&&(e.isConnected=!1,e.disconnect({reason:"error",message:"LiveKit connection state changed to "+n,context:new Event("connection_state_changed")}))}),this.room.on(n.DataReceived,function(n,t){try{var o=JSON.parse((new TextDecoder).decode(n));if("audio"===o.type)return;h(o)?e.handleMessage(o):console.warn("Invalid socket event received:",o)}catch(e){console.warn("Failed to parse incoming data message:",e),console.warn("Raw payload:",(new TextDecoder).decode(n))}}),this.room.on(n.TrackSubscribed,function(e,n,t){try{if(e.kind===o.Kind.Audio&&t.identity.includes("agent")){var r=e.attach();r.autoplay=!0,r.controls=!1,r.style.display="none",document.body.appendChild(r)}return Promise.resolve()}catch(e){return Promise.reject(e)}})},a.close=function(){this.isConnected&&this.room.disconnect()},a.sendMessage=function(e){try{var n=this;if(!n.isConnected||!n.room.localParticipant)return console.warn("Cannot send message: room not connected or no local participant"),Promise.resolve();if("user_audio_chunk"in e)return Promise.resolve();var t=m(function(){var t=(new TextEncoder).encode(JSON.stringify(e));return Promise.resolve(n.room.localParticipant.publishData(t,{reliable:!0})).then(function(){})},function(t){n.debug({type:"send_message_error",message:{message:e,error:t}}),console.error("Failed to send message via WebRTC:",t)});return Promise.resolve(t&&t.then?t.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},a.getRoom=function(){return this.room},s}(c),y=function(e){try{var n=function(e){return e.connectionType?e.connectionType:"conversationToken"in e&&e.conversationToken?"webrtc":"websocket"}(e);switch(n){case"websocket":return Promise.resolve(v.create(e));case"webrtc":return Promise.resolve(g.create(e));default:throw new Error("Unknown connection type: "+n)}}catch(e){return Promise.reject(e)}};function _(){return["iPad Simulator","iPhone Simulator","iPod Simulator","iPad","iPhone","iPod"].includes(navigator.platform)||navigator.userAgent.includes("Mac")&&"ontouchend"in document}var b=function(e){void 0===e&&(e={default:0,android:3e3});try{var n,t=e.default;if(/android/i.test(navigator.userAgent))t=null!=(n=e.android)?n:t;else if(_()){var o;t=null!=(o=e.ios)?o:t}var r=function(){if(t>0)return Promise.resolve(new Promise(function(e){return setTimeout(e,t)})).then(function(){})}();return Promise.resolve(r&&r.then?r.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},w=/*#__PURE__*/function(e){function n(){return e.apply(this,arguments)||this}return i(n,e),n.startSession=function(e){try{var t=u.getFullOptions(e);t.onStatusChange({status:"connecting"}),t.onCanSendFeedbackChange({canSendFeedback:!1});var o=null;return Promise.resolve(function(r,i){try{var s=Promise.resolve(b(t.connectionDelay)).then(function(){return Promise.resolve(y(e)).then(function(e){return new n(t,o=e)})})}catch(e){return i(e)}return s&&s.then?s.then(void 0,i):s}(0,function(e){var n;throw t.onStatusChange({status:"disconnected"}),null==(n=o)||n.close(),e}))}catch(e){return Promise.reject(e)}},n}(u);function k(e){for(var n=window.atob(e),t=n.length,o=new Uint8Array(t),r=0;r<t;r++)o[r]=n.charCodeAt(r);return o.buffer}function P(e,n){try{var t=e()}catch(e){return n(e)}return t&&t.then?t.then(void 0,n):t}var C=new Map;function S(e,n){return function(t){try{var o,r=function(r){return o?r:P(function(){var o="data:application/javascript;base64,"+btoa(n);return Promise.resolve(t.addModule(o)).then(function(){C.set(e,o)})},function(){throw new Error("Failed to load the "+e+" worklet module. Make sure the browser supports AudioWorklets.")})},i=C.get(e);if(i)return Promise.resolve(t.addModule(i));var s=new Blob([n],{type:"application/javascript"}),a=URL.createObjectURL(s),u=P(function(){return Promise.resolve(t.addModule(a)).then(function(){C.set(e,a),o=1})},function(){URL.revokeObjectURL(a)});return Promise.resolve(u&&u.then?u.then(r):r(u))}catch(e){return Promise.reject(e)}}}var M=S("raw-audio-processor",'\nconst BIAS = 0x84;\nconst CLIP = 32635;\nconst encodeTable = [\n 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,\n 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\n];\n\nfunction encodeSample(sample) {\n let sign;\n let exponent;\n let mantissa;\n let muLawSample;\n sign = (sample >> 8) & 0x80;\n if (sign !== 0) sample = -sample;\n sample = sample + BIAS;\n if (sample > CLIP) sample = CLIP;\n exponent = encodeTable[(sample>>7) & 0xFF];\n mantissa = (sample >> (exponent+3)) & 0x0F;\n muLawSample = ~(sign | (exponent << 4) | mantissa);\n \n return muLawSample;\n}\n\nclass RawAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case "setFormat":\n this.isMuted = false;\n this.buffer = []; // Initialize an empty buffer\n this.bufferSize = data.sampleRate / 4;\n this.format = data.format;\n\n if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) {\n globalThis.LibSampleRate.create(1, sampleRate, data.sampleRate).then(resampler => {\n this.resampler = resampler;\n });\n }\n break;\n case "setMuted":\n this.isMuted = data.isMuted;\n break;\n }\n };\n }\n process(inputs) {\n if (!this.buffer) {\n return true;\n }\n \n const input = inputs[0]; // Get the first input node\n if (input.length > 0) {\n let channelData = input[0]; // Get the first channel\'s data\n\n // Resample the audio if necessary\n if (this.resampler) {\n channelData = this.resampler.full(channelData);\n }\n\n // Add channel data to the buffer\n this.buffer.push(...channelData);\n // Get max volume \n let sum = 0.0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const maxVolume = Math.sqrt(sum / channelData.length);\n // Check if buffer size has reached or exceeded the threshold\n if (this.buffer.length >= this.bufferSize) {\n const float32Array = this.isMuted \n ? new Float32Array(this.buffer.length)\n : new Float32Array(this.buffer);\n\n let encodedArray = this.format === "ulaw"\n ? new Uint8Array(float32Array.length)\n : new Int16Array(float32Array.length);\n\n // Iterate through the Float32Array and convert each sample to PCM16\n for (let i = 0; i < float32Array.length; i++) {\n // Clamp the value to the range [-1, 1]\n let sample = Math.max(-1, Math.min(1, float32Array[i]));\n\n // Scale the sample to the range [-32768, 32767]\n let value = sample < 0 ? sample * 32768 : sample * 32767;\n if (this.format === "ulaw") {\n value = encodeSample(Math.round(value));\n }\n\n encodedArray[i] = value;\n }\n\n // Send the buffered data to the main script\n this.port.postMessage([encodedArray, maxVolume]);\n\n // Clear the buffer after sending\n this.buffer = [];\n }\n }\n return true; // Continue processing\n }\n}\nregisterProcessor("raw-audio-processor", RawAudioProcessor);\n'),I=/*#__PURE__*/function(){function e(e,n,t,o){this.context=void 0,this.analyser=void 0,this.worklet=void 0,this.inputStream=void 0,this.context=e,this.analyser=n,this.worklet=t,this.inputStream=o}e.create=function(n){var t=n.sampleRate,o=n.format,r=n.preferHeadphonesForIosDevices;try{var i=null,s=null;return Promise.resolve(function(n,a){try{var u=function(){function n(){function n(){return Promise.resolve(M(i.audioWorklet)).then(function(){return Promise.resolve(navigator.mediaDevices.getUserMedia({audio:a})).then(function(n){var r=i.createMediaStreamSource(s=n),a=new AudioWorkletNode(i,"raw-audio-processor");return a.port.postMessage({type:"setFormat",format:o,sampleRate:t}),r.connect(u),u.connect(a),Promise.resolve(i.resume()).then(function(){return new e(i,u,a,s)})})})}var r=navigator.mediaDevices.getSupportedConstraints().sampleRate,u=(i=new window.AudioContext(r?{sampleRate:t}:{})).createAnalyser(),c=function(){if(!r)return Promise.resolve(i.audioWorklet.addModule("https://cdn.jsdelivr.net/npm/@alexanderolsen/libsamplerate-js@2.1.2/dist/libsamplerate.worklet.js")).then(function(){})}();return c&&c.then?c.then(n):n()}var a={sampleRate:{ideal:t},echoCancellation:{ideal:!0},noiseSuppression:{ideal:!0}},u=function(){if(_()&&r)return Promise.resolve(window.navigator.mediaDevices.enumerateDevices()).then(function(e){var n=e.find(function(e){return"audioinput"===e.kind&&["airpod","headphone","earphone"].find(function(n){return e.label.toLowerCase().includes(n)})});n&&(a.deviceId={ideal:n.deviceId})})}();return u&&u.then?u.then(n):n()}()}catch(e){return a(e)}return u&&u.then?u.then(void 0,a):u}(0,function(e){var n,t;throw null==(n=s)||n.getTracks().forEach(function(e){return e.stop()}),null==(t=i)||t.close(),e}))}catch(e){return Promise.reject(e)}};var n=e.prototype;return n.close=function(){try{return this.inputStream.getTracks().forEach(function(e){return e.stop()}),Promise.resolve(this.context.close()).then(function(){})}catch(e){return Promise.reject(e)}},n.setMuted=function(e){this.worklet.port.postMessage({type:"setMuted",isMuted:e})},e}(),F=S("audio-concat-processor",'\nconst decodeTable = [0,132,396,924,1980,4092,8316,16764];\n\nexport function decodeSample(muLawSample) {\n let sign;\n let exponent;\n let mantissa;\n let sample;\n muLawSample = ~muLawSample;\n sign = (muLawSample & 0x80);\n exponent = (muLawSample >> 4) & 0x07;\n mantissa = muLawSample & 0x0F;\n sample = decodeTable[exponent] + (mantissa << (exponent+3));\n if (sign !== 0) sample = -sample;\n\n return sample;\n}\n\nclass AudioConcatProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffers = []; // Initialize an empty buffer\n this.cursor = 0;\n this.currentBuffer = null;\n this.wasInterrupted = false;\n this.finished = false;\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case "setFormat":\n this.format = data.format;\n break;\n case "buffer":\n this.wasInterrupted = false;\n this.buffers.push(\n this.format === "ulaw"\n ? new Uint8Array(data.buffer)\n : new Int16Array(data.buffer)\n );\n break;\n case "interrupt":\n this.wasInterrupted = true;\n break;\n case "clearInterrupted":\n if (this.wasInterrupted) {\n this.wasInterrupted = false;\n this.buffers = [];\n this.currentBuffer = null;\n }\n }\n };\n }\n process(_, outputs) {\n let finished = false;\n const output = outputs[0][0];\n for (let i = 0; i < output.length; i++) {\n if (!this.currentBuffer) {\n if (this.buffers.length === 0) {\n finished = true;\n break;\n }\n this.currentBuffer = this.buffers.shift();\n this.cursor = 0;\n }\n\n let value = this.currentBuffer[this.cursor];\n if (this.format === "ulaw") {\n value = decodeSample(value);\n }\n output[i] = value / 32768;\n this.cursor++;\n\n if (this.cursor >= this.currentBuffer.length) {\n this.currentBuffer = null;\n }\n }\n\n if (this.finished !== finished) {\n this.finished = finished;\n this.port.postMessage({ type: "process", finished });\n }\n\n return true; // Continue processing\n }\n}\n\nregisterProcessor("audio-concat-processor", AudioConcatProcessor);\n'),D=/*#__PURE__*/function(){function e(e,n,t,o){this.context=void 0,this.analyser=void 0,this.gain=void 0,this.worklet=void 0,this.context=e,this.analyser=n,this.gain=t,this.worklet=o}return e.create=function(n){var t=n.sampleRate,o=n.format;try{var r=null;return Promise.resolve(function(n,i){try{var s=(a=(r=new AudioContext({sampleRate:t})).createAnalyser(),(u=r.createGain()).connect(a),a.connect(r.destination),Promise.resolve(F(r.audioWorklet)).then(function(){var n=new AudioWorkletNode(r,"audio-concat-processor");return n.port.postMessage({type:"setFormat",format:o}),n.connect(u),Promise.resolve(r.resume()).then(function(){return new e(r,a,u,n)})}))}catch(e){return i(e)}var a,u;return s&&s.then?s.then(void 0,i):s}(0,function(e){var n;throw null==(n=r)||n.close(),e}))}catch(e){return Promise.reject(e)}},e.prototype.close=function(){try{return Promise.resolve(this.context.close()).then(function(){})}catch(e){return Promise.reject(e)}},e}();function A(e,n){try{var t=e()}catch(e){return n(e)}return t&&t.then?t.then(void 0,n):t}var x=/*#__PURE__*/function(e){function n(n,t,o,r,i){var s;return(s=e.call(this,n,t)||this).input=void 0,s.output=void 0,s.wakeLock=void 0,s.inputFrequencyData=void 0,s.outputFrequencyData=void 0,s.onInputWorkletMessage=function(e){var n,t;"connected"===s.status&&s.connection.sendMessage({user_audio_chunk:(n=e.data[0].buffer,t=new Uint8Array(n),window.btoa(String.fromCharCode.apply(String,t)))})},s.onOutputWorkletMessage=function(e){var n=e.data;"process"===n.type&&s.updateMode(n.finished?"listening":"speaking")},s.addAudioBase64Chunk=function(e){s.output.gain.gain.value=s.volume,s.output.worklet.port.postMessage({type:"clearInterrupted"}),s.output.worklet.port.postMessage({type:"buffer",buffer:k(e)})},s.fadeOutAudio=function(){s.updateMode("listening"),s.output.worklet.port.postMessage({type:"interrupt"}),s.output.gain.gain.exponentialRampToValueAtTime(1e-4,s.output.context.currentTime+2),setTimeout(function(){s.output.gain.gain.value=s.volume,s.output.worklet.port.postMessage({type:"clearInterrupted"})},2e3)},s.calculateVolume=function(e){if(0===e.length)return 0;for(var n=0,t=0;t<e.length;t++)n+=e[t]/255;return(n/=e.length)<0?0:n>1?1:n},s.input=o,s.output=r,s.wakeLock=i,s.input.worklet.port.onmessage=s.onInputWorkletMessage,s.output.worklet.port.onmessage=s.onOutputWorkletMessage,s}i(n,e),n.startSession=function(e){try{var t=function(){return A(function(){return Promise.resolve(navigator.mediaDevices.getUserMedia({audio:!0})).then(function(t){return c=t,Promise.resolve(b(o.connectionDelay)).then(function(){return Promise.resolve(y(e)).then(function(t){return s=t,Promise.resolve(Promise.all([I.create(r({},s.inputFormat,{preferHeadphonesForIosDevices:e.preferHeadphonesForIosDevices})),D.create(s.outputFormat)])).then(function(e){var t;return i=e[0],a=e[1],null==(t=c)||t.getTracks().forEach(function(e){return e.stop()}),c=null,new n(o,s,i,a,l)})})})})},function(e){var n,t,r;return o.onStatusChange({status:"disconnected"}),null==(n=c)||n.getTracks().forEach(function(e){return e.stop()}),null==(t=s)||t.close(),Promise.resolve(null==(r=i)?void 0:r.close()).then(function(){var n;return Promise.resolve(null==(n=a)?void 0:n.close()).then(function(){function n(){throw e}var t=A(function(){var e;return Promise.resolve(null==(e=l)?void 0:e.release()).then(function(){l=null})},function(){});return t&&t.then?t.then(n):n()})})})},o=u.getFullOptions(e);o.onStatusChange({status:"connecting"}),o.onCanSendFeedbackChange({canSendFeedback:!1});var i=null,s=null,a=null,c=null,l=null,d=function(n){if(null==(n=e.useWakeLock)||n){var t=A(function(){return Promise.resolve(navigator.wakeLock.request("screen")).then(function(e){l=e})},function(){});if(t&&t.then)return t.then(function(){})}}();return Promise.resolve(d&&d.then?d.then(t):t())}catch(e){return Promise.reject(e)}};var t=n.prototype;return t.handleEndSession=function(){try{var n=this;return Promise.resolve(e.prototype.handleEndSession.call(n)).then(function(){function e(){return Promise.resolve(n.input.close()).then(function(){return Promise.resolve(n.output.close()).then(function(){})})}var t=A(function(){var e;return Promise.resolve(null==(e=n.wakeLock)?void 0:e.release()).then(function(){n.wakeLock=null})},function(){});return t&&t.then?t.then(e):e()})}catch(e){return Promise.reject(e)}},t.handleInterruption=function(n){e.prototype.handleInterruption.call(this,n),this.fadeOutAudio()},t.handleAudio=function(e){this.lastInterruptTimestamp<=e.audio_event.event_id&&(this.options.onAudio(e.audio_event.audio_base_64),this.addAudioBase64Chunk(e.audio_event.audio_base_64),this.currentEventId=e.audio_event.event_id,this.updateCanSendFeedback(),this.updateMode("speaking"))},t.setMicMuted=function(e){this.input.setMuted(e)},t.getInputByteFrequencyData=function(){return null!=this.inputFrequencyData||(this.inputFrequencyData=new Uint8Array(this.input.analyser.frequencyBinCount)),this.input.analyser.getByteFrequencyData(this.inputFrequencyData),this.inputFrequencyData},t.getOutputByteFrequencyData=function(){return null!=this.outputFrequencyData||(this.outputFrequencyData=new Uint8Array(this.output.analyser.frequencyBinCount)),this.output.analyser.getByteFrequencyData(this.outputFrequencyData),this.outputFrequencyData},t.getInputVolume=function(){return this.calculateVolume(this.getInputByteFrequencyData())},t.getOutputVolume=function(){return this.calculateVolume(this.getOutputByteFrequencyData())},n}(u);function T(e,n,t){return void 0===t&&(t="https://api.elevenlabs.io"),fetch(t+"/v1/convai/conversations/"+e+"/feedback",{method:"POST",body:JSON.stringify({feedback:n?"like":"dislike"}),headers:{"Content-Type":"application/json"}})}var E=/*#__PURE__*/function(e){function n(){return e.apply(this,arguments)||this}return i(n,e),n.startSession=function(e){return e.textOnly?w.startSession(e):x.startSession(e)},n}(u);export{E as Conversation,g as WebRTCConnection,v as WebSocketConnection,y as createConnection,T as postOverallFeedback};
|
2
2
|
//# sourceMappingURL=lib.module.js.map
|
package/dist/lib.module.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"lib.module.js","sources":["../src/utils/audio.ts","../src/utils/createWorkletModuleLoader.ts","../src/utils/rawAudioProcessor.ts","../src/utils/compatibility.ts","../src/utils/input.ts","../src/utils/audioConcatProcessor.ts","../src/utils/output.ts","../src/utils/events.ts","../src/utils/connection.ts","../src/index.ts"],"sourcesContent":["export function arrayBufferToBase64(b: ArrayBufferLike) {\n const buffer = new Uint8Array(b);\n // @ts-ignore\n const base64Data = window.btoa(String.fromCharCode(...buffer));\n return base64Data;\n}\n\nexport function base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binaryString = window.atob(base64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n","const URLCache = new Map<string, string>();\n\nexport function createWorkletModuleLoader(name: string, sourceCode: string) {\n return async (worklet: AudioWorklet) => {\n const url = URLCache.get(name);\n if (url) {\n return worklet.addModule(url);\n }\n\n const blob = new Blob([sourceCode], { type: \"application/javascript\" });\n const blobURL = URL.createObjectURL(blob);\n try {\n await worklet.addModule(blobURL);\n URLCache.set(name, blobURL);\n return;\n } catch {\n URL.revokeObjectURL(blobURL);\n }\n\n try {\n // Attempting to start a conversation in Safari inside an iframe will\n // throw a CORS error because the blob:// protocol is considered\n // cross-origin. In such cases, fall back to using a base64 data URL:\n const base64 = btoa(sourceCode);\n const moduleURL = `data:application/javascript;base64,${base64}`;\n await worklet.addModule(moduleURL);\n URLCache.set(name, moduleURL);\n } catch (error) {\n throw new Error(\n `Failed to load the ${name} worklet module. Make sure the browser supports AudioWorklets.`\n );\n }\n };\n}\n","/*\n * ulaw encoding logic taken from the wavefile library\n * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js\n */\n\nimport { createWorkletModuleLoader } from \"./createWorkletModuleLoader\";\n\nexport const loadRawAudioProcessor = createWorkletModuleLoader(\n \"raw-audio-processor\",\n // language=JavaScript\n `\nconst BIAS = 0x84;\nconst CLIP = 32635;\nconst encodeTable = [\n 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,\n 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\n];\n\nfunction encodeSample(sample) {\n let sign;\n let exponent;\n let mantissa;\n let muLawSample;\n sign = (sample >> 8) & 0x80;\n if (sign !== 0) sample = -sample;\n sample = sample + BIAS;\n if (sample > CLIP) sample = CLIP;\n exponent = encodeTable[(sample>>7) & 0xFF];\n mantissa = (sample >> (exponent+3)) & 0x0F;\n muLawSample = ~(sign | (exponent << 4) | mantissa);\n \n return muLawSample;\n}\n\nclass RawAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case \"setFormat\":\n this.isMuted = false;\n this.buffer = []; // Initialize an empty buffer\n this.bufferSize = data.sampleRate / 4;\n this.format = data.format;\n\n if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) {\n globalThis.LibSampleRate.create(1, sampleRate, data.sampleRate).then(resampler => {\n this.resampler = resampler;\n });\n }\n break;\n case \"setMuted\":\n this.isMuted = data.isMuted;\n break;\n }\n };\n }\n process(inputs) {\n if (!this.buffer) {\n return true;\n }\n \n const input = inputs[0]; // Get the first input node\n if (input.length > 0) {\n let channelData = input[0]; // Get the first channel's data\n\n // Resample the audio if necessary\n if (this.resampler) {\n channelData = this.resampler.full(channelData);\n }\n\n // Add channel data to the buffer\n this.buffer.push(...channelData);\n // Get max volume \n let sum = 0.0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const maxVolume = Math.sqrt(sum / channelData.length);\n // Check if buffer size has reached or exceeded the threshold\n if (this.buffer.length >= this.bufferSize) {\n const float32Array = this.isMuted \n ? new Float32Array(this.buffer.length)\n : new Float32Array(this.buffer);\n\n let encodedArray = this.format === \"ulaw\"\n ? new Uint8Array(float32Array.length)\n : new Int16Array(float32Array.length);\n\n // Iterate through the Float32Array and convert each sample to PCM16\n for (let i = 0; i < float32Array.length; i++) {\n // Clamp the value to the range [-1, 1]\n let sample = Math.max(-1, Math.min(1, float32Array[i]));\n\n // Scale the sample to the range [-32768, 32767]\n let value = sample < 0 ? sample * 32768 : sample * 32767;\n if (this.format === \"ulaw\") {\n value = encodeSample(Math.round(value));\n }\n\n encodedArray[i] = value;\n }\n\n // Send the buffered data to the main script\n this.port.postMessage([encodedArray, maxVolume]);\n\n // Clear the buffer after sending\n this.buffer = [];\n }\n }\n return true; // Continue processing\n }\n}\nregisterProcessor(\"raw-audio-processor\", RawAudioProcessor);\n`\n);\n","export function isIosDevice() {\n return (\n [\n \"iPad Simulator\",\n \"iPhone Simulator\",\n \"iPod Simulator\",\n \"iPad\",\n \"iPhone\",\n \"iPod\",\n ].includes(navigator.platform) ||\n // iPad on iOS 13 detection\n (navigator.userAgent.includes(\"Mac\") && \"ontouchend\" in document)\n );\n}\n\nexport function isAndroidDevice() {\n return /android/i.test(navigator.userAgent);\n}\n","import { loadRawAudioProcessor } from \"./rawAudioProcessor\";\nimport { FormatConfig } from \"./connection\";\nimport { isIosDevice } from \"./compatibility\";\n\nexport type InputConfig = {\n preferHeadphonesForIosDevices?: boolean;\n};\n\nconst LIBSAMPLERATE_JS =\n \"https://cdn.jsdelivr.net/npm/@alexanderolsen/libsamplerate-js@2.1.2/dist/libsamplerate.worklet.js\";\n\nexport class Input {\n public static async create({\n sampleRate,\n format,\n preferHeadphonesForIosDevices,\n }: FormatConfig & InputConfig): Promise<Input> {\n let context: AudioContext | null = null;\n let inputStream: MediaStream | null = null;\n\n try {\n const options: MediaTrackConstraints = {\n sampleRate: { ideal: sampleRate },\n echoCancellation: { ideal: true },\n noiseSuppression: { ideal: true },\n };\n\n if (isIosDevice() && preferHeadphonesForIosDevices) {\n const availableDevices =\n await window.navigator.mediaDevices.enumerateDevices();\n const idealDevice = availableDevices.find(\n d =>\n // cautious to include \"bluetooth\" in the search\n // as might trigger bluetooth speakers\n d.kind === \"audioinput\" &&\n [\"airpod\", \"headphone\", \"earphone\"].find(keyword =>\n d.label.toLowerCase().includes(keyword)\n )\n );\n if (idealDevice) {\n options.deviceId = { ideal: idealDevice.deviceId };\n }\n }\n\n const supportsSampleRateConstraint =\n navigator.mediaDevices.getSupportedConstraints().sampleRate;\n\n context = new window.AudioContext(\n supportsSampleRateConstraint ? { sampleRate } : {}\n );\n const analyser = context.createAnalyser();\n if (!supportsSampleRateConstraint) {\n await context.audioWorklet.addModule(LIBSAMPLERATE_JS);\n }\n await loadRawAudioProcessor(context.audioWorklet);\n\n inputStream = await navigator.mediaDevices.getUserMedia({\n audio: options,\n });\n\n const source = context.createMediaStreamSource(inputStream);\n const worklet = new AudioWorkletNode(context, \"raw-audio-processor\");\n worklet.port.postMessage({ type: \"setFormat\", format, sampleRate });\n\n source.connect(analyser);\n analyser.connect(worklet);\n\n await context.resume();\n\n return new Input(context, analyser, worklet, inputStream);\n } catch (error) {\n inputStream?.getTracks().forEach(track => track.stop());\n context?.close();\n throw error;\n }\n }\n\n private constructor(\n public readonly context: AudioContext,\n public readonly analyser: AnalyserNode,\n public readonly worklet: AudioWorkletNode,\n public readonly inputStream: MediaStream\n ) {}\n\n public async close() {\n this.inputStream.getTracks().forEach(track => track.stop());\n await this.context.close();\n }\n\n public setMuted(isMuted: boolean) {\n this.worklet.port.postMessage({ type: \"setMuted\", isMuted });\n }\n}\n","/*\n * ulaw decoding logic taken from the wavefile library\n * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js\n */\n\nimport { createWorkletModuleLoader } from \"./createWorkletModuleLoader\";\n\nexport const loadAudioConcatProcessor = createWorkletModuleLoader(\n \"audio-concat-processor\",\n // language=JavaScript\n `\nconst decodeTable = [0,132,396,924,1980,4092,8316,16764];\n\nexport function decodeSample(muLawSample) {\n let sign;\n let exponent;\n let mantissa;\n let sample;\n muLawSample = ~muLawSample;\n sign = (muLawSample & 0x80);\n exponent = (muLawSample >> 4) & 0x07;\n mantissa = muLawSample & 0x0F;\n sample = decodeTable[exponent] + (mantissa << (exponent+3));\n if (sign !== 0) sample = -sample;\n\n return sample;\n}\n\nclass AudioConcatProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffers = []; // Initialize an empty buffer\n this.cursor = 0;\n this.currentBuffer = null;\n this.wasInterrupted = false;\n this.finished = false;\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case \"setFormat\":\n this.format = data.format;\n break;\n case \"buffer\":\n this.wasInterrupted = false;\n this.buffers.push(\n this.format === \"ulaw\"\n ? new Uint8Array(data.buffer)\n : new Int16Array(data.buffer)\n );\n break;\n case \"interrupt\":\n this.wasInterrupted = true;\n break;\n case \"clearInterrupted\":\n if (this.wasInterrupted) {\n this.wasInterrupted = false;\n this.buffers = [];\n this.currentBuffer = null;\n }\n }\n };\n }\n process(_, outputs) {\n let finished = false;\n const output = outputs[0][0];\n for (let i = 0; i < output.length; i++) {\n if (!this.currentBuffer) {\n if (this.buffers.length === 0) {\n finished = true;\n break;\n }\n this.currentBuffer = this.buffers.shift();\n this.cursor = 0;\n }\n\n let value = this.currentBuffer[this.cursor];\n if (this.format === \"ulaw\") {\n value = decodeSample(value);\n }\n output[i] = value / 32768;\n this.cursor++;\n\n if (this.cursor >= this.currentBuffer.length) {\n this.currentBuffer = null;\n }\n }\n\n if (this.finished !== finished) {\n this.finished = finished;\n this.port.postMessage({ type: \"process\", finished });\n }\n\n return true; // Continue processing\n }\n}\n\nregisterProcessor(\"audio-concat-processor\", AudioConcatProcessor);\n`\n);\n","import { loadAudioConcatProcessor } from \"./audioConcatProcessor\";\nimport { FormatConfig } from \"./connection\";\n\nexport class Output {\n public static async create({\n sampleRate,\n format,\n }: FormatConfig): Promise<Output> {\n let context: AudioContext | null = null;\n try {\n context = new AudioContext({ sampleRate });\n const analyser = context.createAnalyser();\n const gain = context.createGain();\n gain.connect(analyser);\n analyser.connect(context.destination);\n await loadAudioConcatProcessor(context.audioWorklet);\n const worklet = new AudioWorkletNode(context, \"audio-concat-processor\");\n worklet.port.postMessage({ type: \"setFormat\", format });\n worklet.connect(gain);\n\n await context.resume();\n\n return new Output(context, analyser, gain, worklet);\n } catch (error) {\n context?.close();\n throw error;\n }\n }\n\n private constructor(\n public readonly context: AudioContext,\n public readonly analyser: AnalyserNode,\n public readonly gain: GainNode,\n public readonly worklet: AudioWorkletNode\n ) {}\n\n public async close() {\n await this.context.close();\n }\n}\n","import { Language } from \"./connection\";\n\nexport type UserTranscriptionEvent = {\n type: \"user_transcript\";\n user_transcription_event: { user_transcript: string };\n};\nexport type AgentResponseEvent = {\n type: \"agent_response\";\n agent_response_event: { agent_response: string };\n};\nexport type AgentAudioEvent = {\n type: \"audio\";\n audio_event: {\n audio_base_64: string;\n event_id: number;\n };\n};\nexport type InterruptionEvent = {\n type: \"interruption\";\n interruption_event: {\n event_id: number;\n };\n};\nexport type InternalTentativeAgentResponseEvent = {\n type: \"internal_tentative_agent_response\";\n tentative_agent_response_internal_event: {\n tentative_agent_response: string;\n };\n};\nexport type ConfigEvent = {\n type: \"conversation_initiation_metadata\";\n conversation_initiation_metadata_event: {\n conversation_id: string;\n agent_output_audio_format: string;\n user_input_audio_format?: string;\n };\n};\nexport type PingEvent = {\n type: \"ping\";\n ping_event: {\n event_id: number;\n ping_ms?: number;\n };\n};\nexport type ClientToolCallEvent = {\n type: \"client_tool_call\";\n client_tool_call: {\n tool_name: string;\n tool_call_id: string;\n parameters: any;\n expects_response: boolean;\n };\n};\n\n// TODO correction missing\nexport type IncomingSocketEvent =\n | UserTranscriptionEvent\n | AgentResponseEvent\n | AgentAudioEvent\n | InterruptionEvent\n | InternalTentativeAgentResponseEvent\n | ConfigEvent\n | PingEvent\n | ClientToolCallEvent;\n\nexport type PongEvent = {\n type: \"pong\";\n event_id: number;\n};\nexport type UserAudioEvent = {\n user_audio_chunk: string;\n};\nexport type UserFeedbackEvent = {\n type: \"feedback\";\n score: \"like\" | \"dislike\";\n event_id: number;\n};\nexport type ClientToolResultEvent = {\n type: \"client_tool_result\";\n tool_call_id: string;\n result: any;\n is_error: boolean;\n};\nexport type InitiationClientDataEvent = {\n type: \"conversation_initiation_client_data\";\n conversation_config_override?: {\n agent?: {\n prompt?: {\n prompt?: string;\n };\n first_message?: string;\n language?: Language;\n };\n tts?: {\n voice_id?: string;\n };\n };\n custom_llm_extra_body?: any;\n dynamic_variables?: Record<string, string | number | boolean>;\n};\nexport type ContextualUpdateEvent = {\n type: \"contextual_update\";\n text: string;\n};\nexport type OutgoingSocketEvent =\n | PongEvent\n | UserAudioEvent\n | InitiationClientDataEvent\n | UserFeedbackEvent\n | ClientToolResultEvent\n | ContextualUpdateEvent;\n\nexport function isValidSocketEvent(event: any): event is IncomingSocketEvent {\n return !!event.type;\n}\n","import {\n InitiationClientDataEvent,\n ConfigEvent,\n isValidSocketEvent,\n OutgoingSocketEvent,\n IncomingSocketEvent,\n} from \"./events\";\n\nconst MAIN_PROTOCOL = \"convai\";\n\nexport type Language =\n | \"en\"\n | \"ja\"\n | \"zh\"\n | \"de\"\n | \"hi\"\n | \"fr\"\n | \"ko\"\n | \"pt\"\n | \"pt-br\"\n | \"it\"\n | \"es\"\n | \"id\"\n | \"nl\"\n | \"tr\"\n | \"pl\"\n | \"sv\"\n | \"bg\"\n | \"ro\"\n | \"ar\"\n | \"cs\"\n | \"el\"\n | \"fi\"\n | \"ms\"\n | \"da\"\n | \"ta\"\n | \"uk\"\n | \"ru\"\n | \"hu\"\n | \"no\"\n | \"vi\";\nexport type SessionConfig = {\n origin?: string;\n authorization?: string;\n overrides?: {\n agent?: {\n prompt?: {\n prompt?: string;\n };\n firstMessage?: string;\n language?: Language;\n };\n tts?: {\n voiceId?: string;\n };\n };\n customLlmExtraBody?: any;\n dynamicVariables?: Record<string, string | number | boolean>;\n useWakeLock?: boolean;\n connectionDelay?: {\n default: number;\n android?: number;\n ios?: number;\n };\n} & (\n | { signedUrl: string; agentId?: undefined }\n | { agentId: string; signedUrl?: undefined }\n);\nexport type FormatConfig = {\n format: \"pcm\" | \"ulaw\";\n sampleRate: number;\n};\nexport type DisconnectionDetails =\n | {\n reason: \"error\";\n message: string;\n context: Event;\n }\n | {\n reason: \"agent\";\n context: CloseEvent;\n }\n | {\n reason: \"user\";\n };\nexport type OnDisconnectCallback = (details: DisconnectionDetails) => void;\nexport type OnMessageCallback = (event: IncomingSocketEvent) => void;\n\nconst WSS_API_ORIGIN = \"wss://api.elevenlabs.io\";\nconst WSS_API_PATHNAME = \"/v1/convai/conversation?agent_id=\";\n\nexport class Connection {\n public static async create(config: SessionConfig): Promise<Connection> {\n let socket: WebSocket | null = null;\n\n try {\n const origin = config.origin ?? WSS_API_ORIGIN;\n const url = config.signedUrl\n ? config.signedUrl\n : origin + WSS_API_PATHNAME + config.agentId;\n\n const protocols = [MAIN_PROTOCOL];\n if (config.authorization) {\n protocols.push(`bearer.${config.authorization}`);\n }\n socket = new WebSocket(url, protocols);\n const conversationConfig = await new Promise<\n ConfigEvent[\"conversation_initiation_metadata_event\"]\n >((resolve, reject) => {\n socket!.addEventListener(\n \"open\",\n () => {\n const overridesEvent: InitiationClientDataEvent = {\n type: \"conversation_initiation_client_data\",\n };\n\n if (config.overrides) {\n overridesEvent.conversation_config_override = {\n agent: {\n prompt: config.overrides.agent?.prompt,\n first_message: config.overrides.agent?.firstMessage,\n language: config.overrides.agent?.language,\n },\n tts: {\n voice_id: config.overrides.tts?.voiceId,\n },\n };\n }\n\n if (config.customLlmExtraBody) {\n overridesEvent.custom_llm_extra_body = config.customLlmExtraBody;\n }\n\n if (config.dynamicVariables) {\n overridesEvent.dynamic_variables = config.dynamicVariables;\n }\n\n socket?.send(JSON.stringify(overridesEvent));\n },\n { once: true }\n );\n socket!.addEventListener(\"error\", event => {\n // In case the error event is followed by a close event, we want the\n // latter to be the one that rejects the promise as it contains more\n // useful information.\n setTimeout(() => reject(event), 0);\n });\n socket!.addEventListener(\"close\", reject);\n socket!.addEventListener(\n \"message\",\n (event: MessageEvent) => {\n const message = JSON.parse(event.data);\n\n if (!isValidSocketEvent(message)) {\n return;\n }\n\n if (message.type === \"conversation_initiation_metadata\") {\n resolve(message.conversation_initiation_metadata_event);\n } else {\n console.warn(\n \"First received message is not conversation metadata.\"\n );\n }\n },\n { once: true }\n );\n });\n\n const {\n conversation_id,\n agent_output_audio_format,\n user_input_audio_format,\n } = conversationConfig;\n\n const inputFormat = parseFormat(user_input_audio_format ?? \"pcm_16000\");\n const outputFormat = parseFormat(agent_output_audio_format);\n\n return new Connection(socket, conversation_id, inputFormat, outputFormat);\n } catch (error) {\n socket?.close();\n throw error;\n }\n }\n\n private queue: IncomingSocketEvent[] = [];\n private disconnectionDetails: DisconnectionDetails | null = null;\n private onDisconnectCallback: OnDisconnectCallback | null = null;\n private onMessageCallback: OnMessageCallback | null = null;\n\n private constructor(\n public readonly socket: WebSocket,\n public readonly conversationId: string,\n public readonly inputFormat: FormatConfig,\n public readonly outputFormat: FormatConfig\n ) {\n this.socket.addEventListener(\"error\", event => {\n // In case the error event is followed by a close event, we want the\n // latter to be the one that disconnects the session as it contains more\n // useful information.\n setTimeout(\n () =>\n this.disconnect({\n reason: \"error\",\n message: \"The connection was closed due to a socket error.\",\n context: event,\n }),\n 0\n );\n });\n this.socket.addEventListener(\"close\", event => {\n this.disconnect(\n event.code === 1000\n ? {\n reason: \"agent\",\n context: event,\n }\n : {\n reason: \"error\",\n message:\n event.reason || \"The connection was closed by the server.\",\n context: event,\n }\n );\n });\n this.socket.addEventListener(\"message\", event => {\n try {\n const parsedEvent = JSON.parse(event.data);\n if (!isValidSocketEvent(parsedEvent)) {\n return;\n }\n\n if (this.onMessageCallback) {\n this.onMessageCallback(parsedEvent);\n } else {\n this.queue.push(parsedEvent);\n }\n } catch (_) {}\n });\n }\n\n public close() {\n this.socket.close();\n }\n\n public sendMessage(message: OutgoingSocketEvent) {\n this.socket.send(JSON.stringify(message));\n }\n\n public onMessage(callback: OnMessageCallback) {\n this.onMessageCallback = callback;\n this.queue.forEach(callback);\n this.queue = [];\n }\n\n public onDisconnect(callback: OnDisconnectCallback) {\n this.onDisconnectCallback = callback;\n if (this.disconnectionDetails) {\n callback(this.disconnectionDetails);\n }\n }\n\n private disconnect(details: DisconnectionDetails) {\n if (!this.disconnectionDetails) {\n this.disconnectionDetails = details;\n this.onDisconnectCallback?.(details);\n }\n }\n}\n\nfunction parseFormat(format: string): FormatConfig {\n const [formatPart, sampleRatePart] = format.split(\"_\");\n if (![\"pcm\", \"ulaw\"].includes(formatPart)) {\n throw new Error(`Invalid format: ${format}`);\n }\n\n const sampleRate = parseInt(sampleRatePart);\n if (isNaN(sampleRate)) {\n throw new Error(`Invalid sample rate: ${sampleRatePart}`);\n }\n\n return {\n format: formatPart as FormatConfig[\"format\"],\n sampleRate,\n };\n}\n","import { arrayBufferToBase64, base64ToArrayBuffer } from \"./utils/audio\";\nimport { Input, InputConfig } from \"./utils/input\";\nimport { Output } from \"./utils/output\";\nimport {\n Connection,\n DisconnectionDetails,\n OnDisconnectCallback,\n SessionConfig,\n} from \"./utils/connection\";\nimport { ClientToolCallEvent, IncomingSocketEvent } from \"./utils/events\";\nimport { isAndroidDevice, isIosDevice } from \"./utils/compatibility\";\n\nexport type { InputConfig } from \"./utils/input\";\nexport type { IncomingSocketEvent } from \"./utils/events\";\nexport type {\n SessionConfig,\n DisconnectionDetails,\n Language,\n} from \"./utils/connection\";\nexport type Role = \"user\" | \"ai\";\nexport type Mode = \"speaking\" | \"listening\";\nexport type Status =\n | \"connecting\"\n | \"connected\"\n | \"disconnecting\"\n | \"disconnected\";\nexport type Options = SessionConfig &\n Callbacks &\n ClientToolsConfig &\n InputConfig;\nexport type ClientToolsConfig = {\n clientTools: Record<\n string,\n (\n parameters: any\n ) => Promise<string | number | void> | string | number | void\n >;\n};\nexport type Callbacks = {\n onConnect: (props: { conversationId: string }) => void;\n // internal debug events, not to be used\n onDebug: (props: any) => void;\n onDisconnect: OnDisconnectCallback;\n onError: (message: string, context?: any) => void;\n onMessage: (props: { message: string; source: Role }) => void;\n onAudio: (base64Audio: string) => void;\n onModeChange: (prop: { mode: Mode }) => void;\n onStatusChange: (prop: { status: Status }) => void;\n onCanSendFeedbackChange: (prop: { canSendFeedback: boolean }) => void;\n onUnhandledClientToolCall?: (\n params: ClientToolCallEvent[\"client_tool_call\"]\n ) => void;\n};\n\nconst defaultClientTools = { clientTools: {} };\nconst defaultCallbacks: Callbacks = {\n onConnect: () => {},\n onDebug: () => {},\n onDisconnect: () => {},\n onError: () => {},\n onMessage: () => {},\n onAudio: () => {},\n onModeChange: () => {},\n onStatusChange: () => {},\n onCanSendFeedbackChange: () => {},\n};\n\nconst HTTPS_API_ORIGIN = \"https://api.elevenlabs.io\";\n\nexport class Conversation {\n public static async startSession(\n options: SessionConfig &\n Partial<Callbacks> &\n Partial<ClientToolsConfig> &\n Partial<InputConfig>\n ): Promise<Conversation> {\n const fullOptions: Options = {\n ...defaultClientTools,\n ...defaultCallbacks,\n ...options,\n };\n\n fullOptions.onStatusChange({ status: \"connecting\" });\n fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });\n\n let input: Input | null = null;\n let connection: Connection | null = null;\n let output: Output | null = null;\n let preliminaryInputStream: MediaStream | null = null;\n\n let wakeLock: WakeLockSentinel | null = null;\n if (options.useWakeLock ?? true) {\n try {\n wakeLock = await navigator.wakeLock.request(\"screen\");\n } catch (e) {\n // Wake Lock is not required for the conversation to work\n }\n }\n\n try {\n // some browsers won't allow calling getSupportedConstraints or enumerateDevices\n // before getting approval for microphone access\n preliminaryInputStream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n });\n\n const delayConfig = options.connectionDelay ?? {\n default: 0,\n // Give the Android AudioManager enough time to switch to the correct audio mode\n android: 3_000,\n };\n let delay = delayConfig.default;\n if (isAndroidDevice()) {\n delay = delayConfig.android ?? delay;\n } else if (isIosDevice()) {\n delay = delayConfig.ios ?? delay;\n }\n\n if (delay > 0) {\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n\n connection = await Connection.create(options);\n [input, output] = await Promise.all([\n Input.create({\n ...connection.inputFormat,\n preferHeadphonesForIosDevices: options.preferHeadphonesForIosDevices,\n }),\n Output.create(connection.outputFormat),\n ]);\n\n preliminaryInputStream?.getTracks().forEach(track => track.stop());\n preliminaryInputStream = null;\n\n return new Conversation(fullOptions, connection, input, output, wakeLock);\n } catch (error) {\n fullOptions.onStatusChange({ status: \"disconnected\" });\n preliminaryInputStream?.getTracks().forEach(track => track.stop());\n connection?.close();\n await input?.close();\n await output?.close();\n try {\n await wakeLock?.release();\n wakeLock = null;\n } catch (e) {}\n throw error;\n }\n }\n\n private lastInterruptTimestamp: number = 0;\n private mode: Mode = \"listening\";\n private status: Status = \"connecting\";\n private inputFrequencyData?: Uint8Array;\n private outputFrequencyData?: Uint8Array;\n private volume: number = 1;\n private currentEventId: number = 1;\n private lastFeedbackEventId: number = 1;\n private canSendFeedback: boolean = false;\n\n private constructor(\n private readonly options: Options,\n private readonly connection: Connection,\n public readonly input: Input,\n public readonly output: Output,\n public wakeLock: WakeLockSentinel | null\n ) {\n this.options.onConnect({ conversationId: connection.conversationId });\n\n this.connection.onDisconnect(this.endSessionWithDetails);\n this.connection.onMessage(this.onMessage);\n\n this.input.worklet.port.onmessage = this.onInputWorkletMessage;\n this.output.worklet.port.onmessage = this.onOutputWorkletMessage;\n this.updateStatus(\"connected\");\n }\n\n public endSession = () => this.endSessionWithDetails({ reason: \"user\" });\n\n private endSessionWithDetails = async (details: DisconnectionDetails) => {\n if (this.status !== \"connected\" && this.status !== \"connecting\") return;\n this.updateStatus(\"disconnecting\");\n\n try {\n await this.wakeLock?.release();\n this.wakeLock = null;\n } catch (e) {}\n\n this.connection.close();\n await this.input.close();\n await this.output.close();\n\n this.updateStatus(\"disconnected\");\n this.options.onDisconnect(details);\n };\n\n private updateMode = (mode: Mode) => {\n if (mode !== this.mode) {\n this.mode = mode;\n this.options.onModeChange({ mode });\n }\n };\n\n private updateStatus = (status: Status) => {\n if (status !== this.status) {\n this.status = status;\n this.options.onStatusChange({ status });\n }\n };\n\n private updateCanSendFeedback = () => {\n const canSendFeedback = this.currentEventId !== this.lastFeedbackEventId;\n if (this.canSendFeedback !== canSendFeedback) {\n this.canSendFeedback = canSendFeedback;\n this.options.onCanSendFeedbackChange({ canSendFeedback });\n }\n };\n\n private onMessage = async (parsedEvent: IncomingSocketEvent) => {\n switch (parsedEvent.type) {\n case \"interruption\": {\n if (parsedEvent.interruption_event) {\n this.lastInterruptTimestamp = parsedEvent.interruption_event.event_id;\n }\n this.fadeOutAudio();\n return;\n }\n\n case \"agent_response\": {\n this.options.onMessage({\n source: \"ai\",\n message: parsedEvent.agent_response_event.agent_response,\n });\n return;\n }\n\n case \"user_transcript\": {\n this.options.onMessage({\n source: \"user\",\n message: parsedEvent.user_transcription_event.user_transcript,\n });\n return;\n }\n\n case \"internal_tentative_agent_response\": {\n this.options.onDebug({\n type: \"tentative_agent_response\",\n response:\n parsedEvent.tentative_agent_response_internal_event\n .tentative_agent_response,\n });\n return;\n }\n\n case \"client_tool_call\": {\n if (\n this.options.clientTools.hasOwnProperty(\n parsedEvent.client_tool_call.tool_name\n )\n ) {\n try {\n const result =\n (await this.options.clientTools[\n parsedEvent.client_tool_call.tool_name\n ](parsedEvent.client_tool_call.parameters)) ??\n \"Client tool execution successful.\"; // default client-tool call response\n\n // The API expects result to be a string, so we need to convert it if it's not already a string\n const formattedResult =\n typeof result === \"object\"\n ? JSON.stringify(result)\n : String(result);\n\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: parsedEvent.client_tool_call.tool_call_id,\n result: formattedResult,\n is_error: false,\n });\n } catch (e) {\n this.onError(\n \"Client tool execution failed with following error: \" +\n (e as Error)?.message,\n {\n clientToolName: parsedEvent.client_tool_call.tool_name,\n }\n );\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: parsedEvent.client_tool_call.tool_call_id,\n result: \"Client tool execution failed: \" + (e as Error)?.message,\n is_error: true,\n });\n }\n } else {\n if (this.options.onUnhandledClientToolCall) {\n this.options.onUnhandledClientToolCall(\n parsedEvent.client_tool_call\n );\n\n return;\n }\n\n this.onError(\n `Client tool with name ${parsedEvent.client_tool_call.tool_name} is not defined on client`,\n {\n clientToolName: parsedEvent.client_tool_call.tool_name,\n }\n );\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: parsedEvent.client_tool_call.tool_call_id,\n result: `Client tool with name ${parsedEvent.client_tool_call.tool_name} is not defined on client`,\n is_error: true,\n });\n }\n\n return;\n }\n\n case \"audio\": {\n if (this.lastInterruptTimestamp <= parsedEvent.audio_event.event_id) {\n this.options.onAudio(parsedEvent.audio_event.audio_base_64);\n this.addAudioBase64Chunk(parsedEvent.audio_event.audio_base_64);\n this.currentEventId = parsedEvent.audio_event.event_id;\n this.updateCanSendFeedback();\n this.updateMode(\"speaking\");\n }\n return;\n }\n\n case \"ping\": {\n this.connection.sendMessage({\n type: \"pong\",\n event_id: parsedEvent.ping_event.event_id,\n });\n // parsedEvent.ping_event.ping_ms can be used on client side, for example\n // to warn if ping is too high that experience might be degraded.\n return;\n }\n\n // unhandled events are expected to be internal events\n default: {\n this.options.onDebug(parsedEvent);\n return;\n }\n }\n };\n\n private onInputWorkletMessage = (event: MessageEvent): void => {\n const rawAudioPcmData = event.data[0];\n const maxVolume = event.data[1];\n\n // check if the sound was loud enough, so we don't send unnecessary chunks\n // then forward audio to websocket\n //if (maxVolume > 0.001) {\n if (this.status === \"connected\") {\n this.connection.sendMessage({\n user_audio_chunk: arrayBufferToBase64(rawAudioPcmData.buffer),\n //sample_rate: this.inputAudioContext?.inputSampleRate || this.inputSampleRate,\n });\n }\n //}\n };\n\n private onOutputWorkletMessage = ({ data }: MessageEvent): void => {\n if (data.type === \"process\") {\n this.updateMode(data.finished ? \"listening\" : \"speaking\");\n }\n };\n\n private addAudioBase64Chunk = (chunk: string) => {\n this.output.gain.gain.value = this.volume;\n this.output.worklet.port.postMessage({ type: \"clearInterrupted\" });\n this.output.worklet.port.postMessage({\n type: \"buffer\",\n buffer: base64ToArrayBuffer(chunk),\n });\n };\n\n private fadeOutAudio = () => {\n // mute agent\n this.updateMode(\"listening\");\n this.output.worklet.port.postMessage({ type: \"interrupt\" });\n this.output.gain.gain.exponentialRampToValueAtTime(\n 0.0001,\n this.output.context.currentTime + 2\n );\n\n // reset volume back\n setTimeout(() => {\n this.output.gain.gain.value = this.volume;\n this.output.worklet.port.postMessage({ type: \"clearInterrupted\" });\n }, 2000); // Adjust the duration as needed\n };\n\n private onError = (message: string, context?: any) => {\n console.error(message, context);\n this.options.onError(message, context);\n };\n\n private calculateVolume = (frequencyData: Uint8Array) => {\n if (frequencyData.length === 0) {\n return 0;\n }\n\n // TODO: Currently this averages all frequencies, but we should probably\n // bias towards the frequencies that are more typical for human voice\n let volume = 0;\n for (let i = 0; i < frequencyData.length; i++) {\n volume += frequencyData[i] / 255;\n }\n volume /= frequencyData.length;\n\n return volume < 0 ? 0 : volume > 1 ? 1 : volume;\n };\n\n public getId = () => this.connection.conversationId;\n\n public isOpen = () => this.status === \"connected\";\n\n public setVolume = ({ volume }: { volume: number }) => {\n this.volume = volume;\n };\n\n public setMicMuted = (isMuted: boolean) => {\n this.input.setMuted(isMuted);\n };\n\n public getInputByteFrequencyData = () => {\n this.inputFrequencyData ??= new Uint8Array(\n this.input.analyser.frequencyBinCount\n );\n this.input.analyser.getByteFrequencyData(this.inputFrequencyData);\n return this.inputFrequencyData;\n };\n\n public getOutputByteFrequencyData = () => {\n this.outputFrequencyData ??= new Uint8Array(\n this.output.analyser.frequencyBinCount\n );\n this.output.analyser.getByteFrequencyData(this.outputFrequencyData);\n return this.outputFrequencyData;\n };\n\n public getInputVolume = () => {\n return this.calculateVolume(this.getInputByteFrequencyData());\n };\n\n public getOutputVolume = () => {\n return this.calculateVolume(this.getOutputByteFrequencyData());\n };\n\n public sendFeedback = (like: boolean) => {\n if (!this.canSendFeedback) {\n console.warn(\n this.lastFeedbackEventId === 0\n ? \"Cannot send feedback: the conversation has not started yet.\"\n : \"Cannot send feedback: feedback has already been sent for the current response.\"\n );\n return;\n }\n\n this.connection.sendMessage({\n type: \"feedback\",\n score: like ? \"like\" : \"dislike\",\n event_id: this.currentEventId,\n });\n this.lastFeedbackEventId = this.currentEventId;\n this.updateCanSendFeedback();\n };\n\n public sendContextualUpdate = (text: string) => {\n this.connection.sendMessage({\n type: \"contextual_update\",\n text,\n });\n };\n}\n\nexport function postOverallFeedback(\n conversationId: string,\n like: boolean,\n origin: string = HTTPS_API_ORIGIN\n) {\n return fetch(`${origin}/v1/convai/conversations/${conversationId}/feedback`, {\n method: \"POST\",\n body: JSON.stringify({\n feedback: like ? \"like\" : \"dislike\",\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n}\n"],"names":["base64ToArrayBuffer","base64","binaryString","window","atob","len","length","bytes","Uint8Array","i","charCodeAt","buffer","URLCache","Map","createWorkletModuleLoader","name","sourceCode","worklet","_exit","_temp2","_result","_catch","moduleURL","btoa","Promise","resolve","addModule","then","set","Error","url","get","blob","Blob","type","blobURL","URL","createObjectURL","_temp","revokeObjectURL","e","reject","loadRawAudioProcessor","isIosDevice","includes","navigator","platform","userAgent","document","Input","context","analyser","inputStream","this","create","_ref","sampleRate","format","preferHeadphonesForIosDevices","_temp4","audioWorklet","mediaDevices","getUserMedia","audio","options","_navigator$mediaDevic","source","createMediaStreamSource","AudioWorkletNode","port","postMessage","connect","resume","supportsSampleRateConstraint","getSupportedConstraints","AudioContext","createAnalyser","ideal","echoCancellation","noiseSuppression","_temp3","enumerateDevices","availableDevices","idealDevice","find","d","kind","keyword","label","toLowerCase","deviceId","error","_inputStream","_context","getTracks","forEach","track","stop","close","_proto","prototype","setMuted","isMuted","loadAudioConcatProcessor","Output","gain","createGain","destination","isValidSocketEvent","event","Connection","socket","conversationId","inputFormat","outputFormat","_this","queue","disconnectionDetails","onDisconnectCallback","onMessageCallback","addEventListener","setTimeout","disconnect","reason","message","code","parsedEvent","JSON","parse","data","push","_","config","origin","_config$origin","signedUrl","agentId","protocols","authorization","WebSocket","_socket","_config$overrides$age","_config$overrides$age2","_config$overrides$age3","_config$overrides$tts","overridesEvent","overrides","conversation_config_override","agent","prompt","first_message","firstMessage","language","tts","voice_id","voiceId","customLlmExtraBody","custom_llm_extra_body","dynamicVariables","dynamic_variables","send","stringify","once","conversation_initiation_metadata_event","console","warn","conversationConfig","conversation_id","agent_output_audio_format","user_input_audio_format","parseFormat","_socket2","sendMessage","onMessage","callback","onDisconnect","details","_this$onDisconnectCal","call","_format$split","split","formatPart","sampleRatePart","parseInt","isNaN","defaultClientTools","clientTools","defaultCallbacks","onConnect","onDebug","onError","onAudio","onModeChange","onStatusChange","onCanSendFeedbackChange","Conversation","connection","input","output","wakeLock","_this2","_this3","lastInterruptTimestamp","mode","status","inputFrequencyData","outputFrequencyData","volume","currentEventId","lastFeedbackEventId","canSendFeedback","endSession","endSessionWithDetails","updateStatus","_this2$wakeLock","release","updateMode","updateCanSendFeedback","interruption_event","event_id","fadeOutAudio","agent_response_event","agent_response","user_transcription_event","user_transcript","response","tentative_agent_response_internal_event","tentative_agent_response","hasOwnProperty","client_tool_call","tool_name","parameters","result","formattedResult","String","tool_call_id","is_error","clientToolName","onUnhandledClientToolCall","audio_event","audio_base_64","addAudioBase64Chunk","ping_event","onInputWorkletMessage","b","user_audio_chunk","fromCharCode","apply","onOutputWorkletMessage","finished","chunk","value","exponentialRampToValueAtTime","currentTime","calculateVolume","frequencyData","getId","isOpen","setVolume","_ref2","setMicMuted","getInputByteFrequencyData","frequencyBinCount","getByteFrequencyData","getOutputByteFrequencyData","_this$outputFrequency","getInputVolume","getOutputVolume","sendFeedback","like","score","sendContextualUpdate","text","onmessage","startSession","_temp10","_options$connectionDe","_temp6","_Connection$create","all","_extends","_Promise$all","_preliminaryInputStre","preliminaryInputStream","fullOptions","_delayConfig$android","delayConfig","connectionDelay","default","android","delay","test","_delayConfig$ios","ios","_temp5","_preliminaryInputStre2","_connection","_input","_output","_temp8","_temp7","_wakeLock","_temp9","_options$useWakeLock","useWakeLock","request","_navigator$wakeLock$r","postOverallFeedback","fetch","method","body","feedback","headers"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"lib.module.js","sources":["../src/BaseConversation.ts","../src/utils/BaseConnection.ts","../src/version.ts","../src/utils/events.ts","../src/utils/overrides.ts","../src/utils/WebSocketConnection.ts","../src/utils/WebRTCConnection.ts","../src/utils/ConnectionFactory.ts","../src/utils/compatibility.ts","../src/utils/applyDelay.ts","../src/TextConversation.ts","../src/utils/audio.ts","../src/utils/createWorkletModuleLoader.ts","../src/utils/rawAudioProcessor.ts","../src/utils/input.ts","../src/utils/audioConcatProcessor.ts","../src/utils/output.ts","../src/VoiceConversation.ts","../src/utils/postOverallFeedback.ts","../src/index.ts"],"sourcesContent":["import type {\n BaseConnection,\n DisconnectionDetails,\n OnDisconnectCallback,\n SessionConfig,\n} from \"./utils/BaseConnection\";\nimport type {\n AgentAudioEvent,\n AgentResponseEvent,\n ClientToolCallEvent,\n IncomingSocketEvent,\n InternalTentativeAgentResponseEvent,\n InterruptionEvent,\n UserTranscriptionEvent,\n} from \"./utils/events\";\nimport type { InputConfig } from \"./utils/input\";\n\nexport type Role = \"user\" | \"ai\";\n\nexport type Mode = \"speaking\" | \"listening\";\n\nexport type Status =\n | \"connecting\"\n | \"connected\"\n | \"disconnecting\"\n | \"disconnected\";\n\nexport type Options = SessionConfig &\n Callbacks &\n ClientToolsConfig &\n InputConfig;\n\nexport type PartialOptions = SessionConfig &\n Partial<Callbacks> &\n Partial<ClientToolsConfig> &\n Partial<InputConfig>;\n\nexport type ClientToolsConfig = {\n clientTools: Record<\n string,\n (\n parameters: any\n ) => Promise<string | number | void> | string | number | void\n >;\n};\n\nexport type Callbacks = {\n onConnect: (props: { conversationId: string }) => void;\n // internal debug events, not to be used\n onDebug: (props: any) => void;\n onDisconnect: OnDisconnectCallback;\n onError: (message: string, context?: any) => void;\n onMessage: (props: { message: string; source: Role }) => void;\n onAudio: (base64Audio: string) => void;\n onModeChange: (prop: { mode: Mode }) => void;\n onStatusChange: (prop: { status: Status }) => void;\n onCanSendFeedbackChange: (prop: { canSendFeedback: boolean }) => void;\n onUnhandledClientToolCall?: (\n params: ClientToolCallEvent[\"client_tool_call\"]\n ) => void;\n};\n\nconst EMPTY_FREQUENCY_DATA = new Uint8Array(0);\n\nexport class BaseConversation {\n protected lastInterruptTimestamp = 0;\n protected mode: Mode = \"listening\";\n protected status: Status = \"connecting\";\n protected volume = 1;\n protected currentEventId = 1;\n protected lastFeedbackEventId = 1;\n protected canSendFeedback = false;\n\n protected static getFullOptions(partialOptions: PartialOptions): Options {\n return {\n clientTools: {},\n onConnect: () => {},\n onDebug: () => {},\n onDisconnect: () => {},\n onError: () => {},\n onMessage: () => {},\n onAudio: () => {},\n onModeChange: () => {},\n onStatusChange: () => {},\n onCanSendFeedbackChange: () => {},\n ...partialOptions,\n };\n }\n\n protected constructor(\n protected readonly options: Options,\n protected readonly connection: BaseConnection\n ) {\n this.options.onConnect({ conversationId: connection.conversationId });\n this.connection.onMessage(this.onMessage);\n this.connection.onDisconnect(this.endSessionWithDetails);\n this.updateStatus(\"connected\");\n }\n\n public endSession() {\n return this.endSessionWithDetails({ reason: \"user\" });\n }\n\n private endSessionWithDetails = async (details: DisconnectionDetails) => {\n if (this.status !== \"connected\" && this.status !== \"connecting\") return;\n this.updateStatus(\"disconnecting\");\n await this.handleEndSession();\n this.updateStatus(\"disconnected\");\n this.options.onDisconnect(details);\n };\n\n protected async handleEndSession() {\n this.connection.close();\n }\n\n protected updateMode(mode: Mode) {\n if (mode !== this.mode) {\n this.mode = mode;\n this.options.onModeChange({ mode });\n }\n }\n\n protected updateStatus(status: Status) {\n if (status !== this.status) {\n this.status = status;\n this.options.onStatusChange({ status });\n }\n }\n\n protected updateCanSendFeedback() {\n const canSendFeedback = this.currentEventId !== this.lastFeedbackEventId;\n if (this.canSendFeedback !== canSendFeedback) {\n this.canSendFeedback = canSendFeedback;\n this.options.onCanSendFeedbackChange({ canSendFeedback });\n }\n }\n\n protected handleInterruption(event: InterruptionEvent) {\n if (event.interruption_event) {\n this.lastInterruptTimestamp = event.interruption_event.event_id;\n }\n }\n\n protected handleAgentResponse(event: AgentResponseEvent) {\n this.options.onMessage({\n source: \"ai\",\n message: event.agent_response_event.agent_response,\n });\n }\n\n protected handleUserTranscript(event: UserTranscriptionEvent) {\n this.options.onMessage({\n source: \"user\",\n message: event.user_transcription_event.user_transcript,\n });\n }\n\n protected handleTentativeAgentResponse(\n event: InternalTentativeAgentResponseEvent\n ) {\n this.options.onDebug({\n type: \"tentative_agent_response\",\n response:\n event.tentative_agent_response_internal_event.tentative_agent_response,\n });\n }\n\n protected async handleClientToolCall(event: ClientToolCallEvent) {\n if (\n Object.prototype.hasOwnProperty.call(\n this.options.clientTools,\n event.client_tool_call.tool_name\n )\n ) {\n try {\n const result =\n (await this.options.clientTools[event.client_tool_call.tool_name](\n event.client_tool_call.parameters\n )) ?? \"Client tool execution successful.\"; // default client-tool call response\n\n // The API expects result to be a string, so we need to convert it if it's not already a string\n const formattedResult =\n typeof result === \"object\" ? JSON.stringify(result) : String(result);\n\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: formattedResult,\n is_error: false,\n });\n } catch (e) {\n this.onError(\n `Client tool execution failed with following error: ${(e as Error)?.message}`,\n {\n clientToolName: event.client_tool_call.tool_name,\n }\n );\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: `Client tool execution failed: ${(e as Error)?.message}`,\n is_error: true,\n });\n }\n } else {\n if (this.options.onUnhandledClientToolCall) {\n this.options.onUnhandledClientToolCall(event.client_tool_call);\n\n return;\n }\n\n this.onError(\n `Client tool with name ${event.client_tool_call.tool_name} is not defined on client`,\n {\n clientToolName: event.client_tool_call.tool_name,\n }\n );\n this.connection.sendMessage({\n type: \"client_tool_result\",\n tool_call_id: event.client_tool_call.tool_call_id,\n result: `Client tool with name ${event.client_tool_call.tool_name} is not defined on client`,\n is_error: true,\n });\n }\n }\n\n protected handleAudio(event: AgentAudioEvent) {}\n\n private onMessage = async (parsedEvent: IncomingSocketEvent) => {\n switch (parsedEvent.type) {\n case \"interruption\": {\n this.handleInterruption(parsedEvent);\n return;\n }\n case \"agent_response\": {\n this.handleAgentResponse(parsedEvent);\n return;\n }\n case \"user_transcript\": {\n this.handleUserTranscript(parsedEvent);\n return;\n }\n case \"internal_tentative_agent_response\": {\n this.handleTentativeAgentResponse(parsedEvent);\n return;\n }\n case \"client_tool_call\": {\n await this.handleClientToolCall(parsedEvent);\n return;\n }\n case \"audio\": {\n this.handleAudio(parsedEvent);\n return;\n }\n\n case \"ping\": {\n this.connection.sendMessage({\n type: \"pong\",\n event_id: parsedEvent.ping_event.event_id,\n });\n // parsedEvent.ping_event.ping_ms can be used on client side, for example\n // to warn if ping is too high that experience might be degraded.\n return;\n }\n\n // unhandled events are expected to be internal events\n default: {\n this.options.onDebug(parsedEvent);\n return;\n }\n }\n };\n\n private onError(message: string, context?: any) {\n console.error(message, context);\n this.options.onError(message, context);\n }\n\n public getId() {\n return this.connection.conversationId;\n }\n\n public isOpen() {\n return this.status === \"connected\";\n }\n\n public setVolume = ({ volume }: { volume: number }) => {\n this.volume = volume;\n };\n\n public setMicMuted(isMuted: boolean) {}\n\n public getInputByteFrequencyData() {\n return EMPTY_FREQUENCY_DATA;\n }\n\n public getOutputByteFrequencyData() {\n return EMPTY_FREQUENCY_DATA;\n }\n\n public getInputVolume() {\n return 0;\n }\n\n public getOutputVolume() {\n return 0;\n }\n\n public sendFeedback(like: boolean) {\n if (!this.canSendFeedback) {\n console.warn(\n this.lastFeedbackEventId === 0\n ? \"Cannot send feedback: the conversation has not started yet.\"\n : \"Cannot send feedback: feedback has already been sent for the current response.\"\n );\n return;\n }\n\n this.connection.sendMessage({\n type: \"feedback\",\n score: like ? \"like\" : \"dislike\",\n event_id: this.currentEventId,\n });\n this.lastFeedbackEventId = this.currentEventId;\n this.updateCanSendFeedback();\n }\n\n public sendContextualUpdate(text: string) {\n this.connection.sendMessage({\n type: \"contextual_update\",\n text,\n });\n }\n\n public sendUserMessage(text: string) {\n this.connection.sendMessage({\n type: \"user_message\",\n text,\n });\n }\n\n public sendUserActivity() {\n this.connection.sendMessage({\n type: \"user_activity\",\n });\n }\n\n public sendMCPToolApprovalResult(toolCallId: string, isApproved: boolean) {\n this.connection.sendMessage({\n type: \"mcp_tool_approval_result\",\n tool_call_id: toolCallId,\n is_approved: isApproved,\n });\n }\n}\n","import type { IncomingSocketEvent, OutgoingSocketEvent } from \"./events\";\n\nexport type Language =\n | \"en\"\n | \"ja\"\n | \"zh\"\n | \"de\"\n | \"hi\"\n | \"fr\"\n | \"ko\"\n | \"pt\"\n | \"pt-br\"\n | \"it\"\n | \"es\"\n | \"id\"\n | \"nl\"\n | \"tr\"\n | \"pl\"\n | \"sv\"\n | \"bg\"\n | \"ro\"\n | \"ar\"\n | \"cs\"\n | \"el\"\n | \"fi\"\n | \"ms\"\n | \"da\"\n | \"ta\"\n | \"uk\"\n | \"ru\"\n | \"hu\"\n | \"hr\"\n | \"sk\"\n | \"no\"\n | \"vi\";\n\nexport type DelayConfig = {\n default: number;\n android?: number;\n ios?: number;\n};\n\nexport type FormatConfig = {\n format: \"pcm\" | \"ulaw\";\n sampleRate: number;\n};\n\nexport type DisconnectionDetails =\n | {\n reason: \"error\";\n message: string;\n context: Event;\n }\n | {\n reason: \"agent\";\n context: CloseEvent;\n }\n | {\n reason: \"user\";\n };\n\nexport type OnDisconnectCallback = (details: DisconnectionDetails) => void;\nexport type OnMessageCallback = (event: IncomingSocketEvent) => void;\n\nexport type BaseSessionConfig = {\n origin?: string;\n authorization?: string;\n livekitUrl?: string;\n overrides?: {\n agent?: {\n prompt?: {\n prompt?: string;\n };\n firstMessage?: string;\n language?: Language;\n };\n tts?: {\n voiceId?: string;\n };\n conversation?: {\n textOnly?: boolean;\n };\n client?: {\n source?: string;\n version?: string;\n };\n };\n customLlmExtraBody?: unknown;\n dynamicVariables?: Record<string, string | number | boolean>;\n useWakeLock?: boolean;\n connectionDelay?: DelayConfig;\n textOnly?: boolean;\n userId?: string;\n};\n\nexport type ConnectionType = \"websocket\" | \"webrtc\";\n\nexport type PublicSessionConfig = BaseSessionConfig & {\n agentId: string;\n connectionType: ConnectionType;\n signedUrl?: never;\n conversationToken?: never;\n};\n\nexport type PrivateWebSocketSessionConfig = BaseSessionConfig & {\n signedUrl: string;\n connectionType?: \"websocket\";\n agentId?: never;\n conversationToken?: never;\n};\n\nexport type PrivateWebRTCSessionConfig = BaseSessionConfig & {\n conversationToken: string;\n connectionType?: \"webrtc\";\n agentId?: never;\n signedUrl?: never;\n};\n\n// Union type for all possible session configurations\nexport type SessionConfig =\n | PublicSessionConfig\n | PrivateWebSocketSessionConfig\n | PrivateWebRTCSessionConfig;\n\nexport abstract class BaseConnection {\n public abstract readonly conversationId: string;\n public abstract readonly inputFormat: FormatConfig;\n public abstract readonly outputFormat: FormatConfig;\n\n protected queue: IncomingSocketEvent[] = [];\n protected disconnectionDetails: DisconnectionDetails | null = null;\n protected onDisconnectCallback: OnDisconnectCallback | null = null;\n protected onMessageCallback: OnMessageCallback | null = null;\n protected onDebug?: (info: unknown) => void;\n\n constructor(config: { onDebug?: (info: unknown) => void } = {}) {\n this.onDebug = config.onDebug;\n }\n\n protected debug(info: unknown) {\n if (this.onDebug) this.onDebug(info);\n }\n\n public abstract close(): void;\n public abstract sendMessage(message: OutgoingSocketEvent): void;\n\n public onMessage(callback: OnMessageCallback) {\n this.onMessageCallback = callback;\n const queue = this.queue;\n this.queue = [];\n\n if (queue.length > 0) {\n // Make sure the queue is flushed after the constructors finishes and\n // classes are initialized.\n queueMicrotask(() => {\n queue.forEach(callback);\n });\n }\n }\n\n public onDisconnect(callback: OnDisconnectCallback) {\n this.onDisconnectCallback = callback;\n const details = this.disconnectionDetails;\n if (details) {\n // Make sure the event is triggered after the constructors finishes and\n // classes are initialized.\n queueMicrotask(() => {\n callback(details);\n });\n }\n }\n\n protected disconnect(details: DisconnectionDetails) {\n if (!this.disconnectionDetails) {\n this.disconnectionDetails = details;\n this.onDisconnectCallback?.(details);\n }\n }\n\n protected handleMessage(parsedEvent: IncomingSocketEvent) {\n if (this.onMessageCallback) {\n this.onMessageCallback(parsedEvent);\n } else {\n this.queue.push(parsedEvent);\n }\n }\n}\n\nexport function parseFormat(format: string): FormatConfig {\n const [formatPart, sampleRatePart] = format.split(\"_\");\n if (![\"pcm\", \"ulaw\"].includes(formatPart)) {\n throw new Error(`Invalid format: ${format}`);\n }\n\n const sampleRate = Number.parseInt(sampleRatePart);\n if (Number.isNaN(sampleRate)) {\n throw new Error(`Invalid sample rate: ${sampleRatePart}`);\n }\n\n return {\n format: formatPart as FormatConfig[\"format\"],\n sampleRate,\n };\n}\n","// This file is auto-generated during build\nexport const PACKAGE_VERSION = \"0.4.0\";\n","import type { Language } from \"./connection\";\nimport type { CONVERSATION_INITIATION_CLIENT_DATA_TYPE } from \"./overrides\";\n\nexport type UserTranscriptionEvent = {\n type: \"user_transcript\";\n user_transcription_event: { user_transcript: string };\n};\nexport type AgentResponseEvent = {\n type: \"agent_response\";\n agent_response_event: { agent_response: string };\n};\nexport type AgentAudioEvent = {\n type: \"audio\";\n audio_event: {\n audio_base_64: string;\n event_id: number;\n };\n};\nexport type InterruptionEvent = {\n type: \"interruption\";\n interruption_event: {\n event_id: number;\n };\n};\nexport type InternalTentativeAgentResponseEvent = {\n type: \"internal_tentative_agent_response\";\n tentative_agent_response_internal_event: {\n tentative_agent_response: string;\n };\n};\nexport type ConfigEvent = {\n type: \"conversation_initiation_metadata\";\n conversation_initiation_metadata_event: {\n conversation_id: string;\n agent_output_audio_format: string;\n user_input_audio_format?: string;\n };\n};\nexport type PingEvent = {\n type: \"ping\";\n ping_event: {\n event_id: number;\n ping_ms?: number;\n };\n};\nexport type ClientToolCallEvent = {\n type: \"client_tool_call\";\n client_tool_call: {\n tool_name: string;\n tool_call_id: string;\n parameters: any;\n expects_response: boolean;\n };\n};\n\n// TODO correction missing\nexport type IncomingSocketEvent =\n | UserTranscriptionEvent\n | AgentResponseEvent\n | AgentAudioEvent\n | InterruptionEvent\n | InternalTentativeAgentResponseEvent\n | ConfigEvent\n | PingEvent\n | ClientToolCallEvent;\n\nexport type PongEvent = {\n type: \"pong\";\n event_id: number;\n};\nexport type UserAudioEvent = {\n user_audio_chunk: string;\n};\nexport type UserFeedbackEvent = {\n type: \"feedback\";\n score: \"like\" | \"dislike\";\n event_id: number;\n};\nexport type ClientToolResultEvent = {\n type: \"client_tool_result\";\n tool_call_id: string;\n result: any;\n is_error: boolean;\n};\nexport type InitiationClientDataEvent = {\n type: typeof CONVERSATION_INITIATION_CLIENT_DATA_TYPE;\n conversation_config_override?: {\n agent?: {\n prompt?: {\n prompt?: string;\n };\n first_message?: string;\n language?: Language;\n };\n tts?: {\n voice_id?: string;\n };\n conversation?: {\n text_only?: boolean;\n };\n };\n custom_llm_extra_body?: any;\n dynamic_variables?: Record<string, string | number | boolean>;\n user_id?: string;\n};\nexport type ContextualUpdateEvent = {\n type: \"contextual_update\";\n text: string;\n};\nexport type UserMessageEvent = {\n type: \"user_message\";\n text: string;\n};\nexport type UserActivityEvent = {\n type: \"user_activity\";\n};\nexport type MCPToolApprovalResultEvent = {\n type: \"mcp_tool_approval_result\";\n tool_call_id: string;\n is_approved: boolean;\n};\nexport type OutgoingSocketEvent =\n | PongEvent\n | UserAudioEvent\n | InitiationClientDataEvent\n | UserFeedbackEvent\n | ClientToolResultEvent\n | ContextualUpdateEvent\n | UserMessageEvent\n | UserActivityEvent\n | MCPToolApprovalResultEvent;\n\nexport function isValidSocketEvent(event: any): event is IncomingSocketEvent {\n return !!event.type;\n}\n","import type { SessionConfig } from \"./BaseConnection\";\nimport type { InitiationClientDataEvent } from \"./events\";\n\nexport const CONVERSATION_INITIATION_CLIENT_DATA_TYPE =\n \"conversation_initiation_client_data\";\n\nexport function constructOverrides(\n config: SessionConfig\n): InitiationClientDataEvent {\n const overridesEvent: InitiationClientDataEvent = {\n type: CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n };\n\n if (config.overrides) {\n overridesEvent.conversation_config_override = {\n agent: {\n prompt: config.overrides.agent?.prompt,\n first_message: config.overrides.agent?.firstMessage,\n language: config.overrides.agent?.language,\n },\n tts: {\n voice_id: config.overrides.tts?.voiceId,\n },\n conversation: {\n text_only: config.overrides.conversation?.textOnly,\n },\n };\n }\n\n if (config.customLlmExtraBody) {\n overridesEvent.custom_llm_extra_body = config.customLlmExtraBody;\n }\n\n if (config.dynamicVariables) {\n overridesEvent.dynamic_variables = config.dynamicVariables;\n }\n\n if (config.userId) {\n overridesEvent.user_id = config.userId;\n }\n\n return overridesEvent;\n}\n","import {\n BaseConnection,\n type SessionConfig,\n type FormatConfig,\n parseFormat,\n} from \"./BaseConnection\";\nimport { PACKAGE_VERSION } from \"../version\";\nimport {\n type ConfigEvent,\n isValidSocketEvent,\n type OutgoingSocketEvent,\n} from \"./events\";\nimport { constructOverrides } from \"./overrides\";\n\nconst MAIN_PROTOCOL = \"convai\";\nconst WSS_API_ORIGIN = \"wss://api.elevenlabs.io\";\nconst WSS_API_PATHNAME = \"/v1/convai/conversation?agent_id=\";\n\nexport class WebSocketConnection extends BaseConnection {\n public readonly conversationId: string;\n public readonly inputFormat: FormatConfig;\n public readonly outputFormat: FormatConfig;\n\n private constructor(\n private readonly socket: WebSocket,\n conversationId: string,\n inputFormat: FormatConfig,\n outputFormat: FormatConfig\n ) {\n super();\n this.conversationId = conversationId;\n this.inputFormat = inputFormat;\n this.outputFormat = outputFormat;\n\n this.socket.addEventListener(\"error\", event => {\n // In case the error event is followed by a close event, we want the\n // latter to be the one that disconnects the session as it contains more\n // useful information.\n setTimeout(\n () =>\n this.disconnect({\n reason: \"error\",\n message: \"The connection was closed due to a socket error.\",\n context: event,\n }),\n 0\n );\n });\n\n this.socket.addEventListener(\"close\", event => {\n this.disconnect(\n event.code === 1000\n ? {\n reason: \"agent\",\n context: event,\n }\n : {\n reason: \"error\",\n message:\n event.reason || \"The connection was closed by the server.\",\n context: event,\n }\n );\n });\n\n this.socket.addEventListener(\"message\", event => {\n try {\n const parsedEvent = JSON.parse(event.data);\n if (!isValidSocketEvent(parsedEvent)) {\n return;\n }\n this.handleMessage(parsedEvent);\n } catch (_) {}\n });\n }\n\n public static async create(\n config: SessionConfig\n ): Promise<WebSocketConnection> {\n let socket: WebSocket | null = null;\n\n try {\n const origin = config.origin ?? WSS_API_ORIGIN;\n let url: string;\n\n const version = config.overrides?.client?.version || PACKAGE_VERSION;\n const source = config.overrides?.client?.source || \"js_sdk\";\n\n if (config.signedUrl) {\n const separator = config.signedUrl.includes(\"?\") ? \"&\" : \"?\";\n url = `${config.signedUrl}${separator}source=${source}&version=${version}`;\n } else {\n url = `${origin}${WSS_API_PATHNAME}${config.agentId}&source=${source}&version=${version}`;\n }\n\n const protocols = [MAIN_PROTOCOL];\n if (config.authorization) {\n protocols.push(`bearer.${config.authorization}`);\n }\n socket = new WebSocket(url, protocols);\n\n const conversationConfig = await new Promise<\n ConfigEvent[\"conversation_initiation_metadata_event\"]\n >((resolve, reject) => {\n socket!.addEventListener(\n \"open\",\n () => {\n const overridesEvent = constructOverrides(config);\n\n socket?.send(JSON.stringify(overridesEvent));\n },\n { once: true }\n );\n\n socket!.addEventListener(\"error\", event => {\n // In case the error event is followed by a close event, we want the\n // latter to be the one that rejects the promise as it contains more\n // useful information.\n setTimeout(() => reject(event), 0);\n });\n\n socket!.addEventListener(\"close\", reject);\n\n socket!.addEventListener(\n \"message\",\n (event: MessageEvent) => {\n const message = JSON.parse(event.data);\n\n if (!isValidSocketEvent(message)) {\n return;\n }\n\n if (message.type === \"conversation_initiation_metadata\") {\n resolve(message.conversation_initiation_metadata_event);\n } else {\n console.warn(\n \"First received message is not conversation metadata.\"\n );\n }\n },\n { once: true }\n );\n });\n\n const {\n conversation_id,\n agent_output_audio_format,\n user_input_audio_format,\n } = conversationConfig;\n\n const inputFormat = parseFormat(user_input_audio_format ?? \"pcm_16000\");\n const outputFormat = parseFormat(agent_output_audio_format);\n\n return new WebSocketConnection(\n socket,\n conversation_id,\n inputFormat,\n outputFormat\n );\n } catch (error) {\n socket?.close();\n throw error;\n }\n }\n\n public close() {\n this.socket.close();\n }\n\n public sendMessage(message: OutgoingSocketEvent) {\n this.socket.send(JSON.stringify(message));\n }\n}\n","import {\n BaseConnection,\n type SessionConfig,\n type FormatConfig,\n parseFormat,\n} from \"./BaseConnection\";\nimport { PACKAGE_VERSION } from \"../version\";\nimport { isValidSocketEvent, type OutgoingSocketEvent } from \"./events\";\nimport { Room, RoomEvent, Track, ConnectionState } from \"livekit-client\";\nimport type {\n RemoteAudioTrack,\n Participant,\n TrackPublication,\n} from \"livekit-client\";\nimport {\n constructOverrides,\n CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n} from \"./overrides\";\n\nconst DEFAULT_LIVEKIT_WS_URL = \"wss://livekit.rtc.elevenlabs.io\";\n\nexport type ConnectionConfig = SessionConfig & {\n onDebug?: (info: unknown) => void;\n};\n\nexport class WebRTCConnection extends BaseConnection {\n public conversationId: string;\n public readonly inputFormat: FormatConfig;\n public readonly outputFormat: FormatConfig;\n\n private room: Room;\n private isConnected = false;\n\n private constructor(\n room: Room,\n conversationId: string,\n inputFormat: FormatConfig,\n outputFormat: FormatConfig,\n config: { onDebug?: (info: unknown) => void } = {}\n ) {\n super(config);\n this.room = room;\n this.conversationId = conversationId;\n this.inputFormat = inputFormat;\n this.outputFormat = outputFormat;\n\n this.setupRoomEventListeners();\n }\n\n public static async create(\n config: ConnectionConfig\n ): Promise<WebRTCConnection> {\n let conversationToken: string;\n\n // Handle different authentication scenarios\n if (\"conversationToken\" in config && config.conversationToken) {\n // Direct token provided\n conversationToken = config.conversationToken;\n } else if (\"agentId\" in config && config.agentId) {\n // Agent ID provided - fetch token from API\n try {\n const version = config.overrides?.client?.version || PACKAGE_VERSION;\n const source = config.overrides?.client?.source || \"js_sdk\";\n const url = `https://api.elevenlabs.io/v1/convai/conversation/token?agent_id=${config.agentId}&source=${source}&version=${version}`;\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(\n `ElevenLabs API returned ${response.status} ${response.statusText}`\n );\n }\n\n const data = await response.json();\n conversationToken = data.token;\n\n if (!conversationToken) {\n throw new Error(\"No conversation token received from API\");\n }\n } catch (error) {\n let msg = error instanceof Error ? error.message : String(error);\n if (error instanceof Error && error.message.includes(\"401\")) {\n msg =\n \"Your agent has authentication enabled, but no signed URL or conversation token was provided.\";\n }\n\n throw new Error(\n `Failed to fetch conversation token for agent ${config.agentId}: ${msg}`\n );\n }\n } else {\n throw new Error(\n \"Either conversationToken or agentId is required for WebRTC connection\"\n );\n }\n\n const room = new Room();\n\n try {\n // Create connection instance first to set up event listeners\n const conversationId = `webrtc-${Date.now()}`;\n const inputFormat = parseFormat(\"pcm_48000\");\n const outputFormat = parseFormat(\"pcm_48000\");\n const connection = new WebRTCConnection(\n room,\n conversationId,\n inputFormat,\n outputFormat,\n config\n );\n\n // Use configurable LiveKit URL or default if not provided\n const livekitUrl = config.livekitUrl || DEFAULT_LIVEKIT_WS_URL;\n\n // Connect to the LiveKit room and wait for the Connected event\n await room.connect(livekitUrl, conversationToken);\n\n // Wait for the Connected event to ensure isConnected is true\n await new Promise<void>(resolve => {\n if (connection.isConnected) {\n resolve();\n } else {\n const onConnected = () => {\n room.off(RoomEvent.Connected, onConnected);\n resolve();\n };\n room.on(RoomEvent.Connected, onConnected);\n }\n });\n\n // Update conversation ID with actual room name if available\n if (room.name) {\n connection.conversationId = room.name;\n }\n\n // Enable microphone and send overrides\n await room.localParticipant.setMicrophoneEnabled(true);\n\n const overridesEvent = constructOverrides(config);\n\n connection.debug({\n type: CONVERSATION_INITIATION_CLIENT_DATA_TYPE,\n message: overridesEvent,\n });\n\n await connection.sendMessage(overridesEvent);\n\n return connection;\n } catch (error) {\n await room.disconnect();\n throw error;\n }\n }\n\n private setupRoomEventListeners() {\n this.room.on(RoomEvent.Connected, async () => {\n this.isConnected = true;\n console.info(\"WebRTC room connected\");\n });\n\n this.room.on(RoomEvent.Disconnected, reason => {\n this.isConnected = false;\n this.disconnect({\n reason: \"agent\",\n context: new CloseEvent(\"close\", { reason: reason?.toString() }),\n });\n });\n\n this.room.on(RoomEvent.ConnectionStateChanged, state => {\n if (state === ConnectionState.Disconnected) {\n this.isConnected = false;\n this.disconnect({\n reason: \"error\",\n message: `LiveKit connection state changed to ${state}`,\n context: new Event(\"connection_state_changed\"),\n });\n }\n });\n\n // Handle incoming data messages\n this.room.on(RoomEvent.DataReceived, (payload: Uint8Array, participant) => {\n try {\n const message = JSON.parse(new TextDecoder().decode(payload));\n\n // Filter out audio messages for WebRTC - they're handled via audio tracks\n if (message.type === \"audio\") {\n return;\n }\n\n if (isValidSocketEvent(message)) {\n this.handleMessage(message);\n } else {\n console.warn(\"Invalid socket event received:\", message);\n }\n } catch (error) {\n console.warn(\"Failed to parse incoming data message:\", error);\n console.warn(\"Raw payload:\", new TextDecoder().decode(payload));\n }\n });\n\n this.room.on(\n RoomEvent.TrackSubscribed,\n async (\n track: Track,\n publication: TrackPublication,\n participant: Participant\n ) => {\n if (\n track.kind === Track.Kind.Audio &&\n participant.identity.includes(\"agent\")\n ) {\n // Play the audio track\n const remoteAudioTrack = track as RemoteAudioTrack;\n const audioElement = remoteAudioTrack.attach();\n audioElement.autoplay = true;\n audioElement.controls = false;\n\n // Add to DOM (hidden) to ensure it plays\n audioElement.style.display = \"none\";\n document.body.appendChild(audioElement);\n }\n }\n );\n }\n\n public close() {\n if (this.isConnected) {\n this.room.disconnect();\n }\n }\n\n public async sendMessage(message: OutgoingSocketEvent) {\n if (!this.isConnected || !this.room.localParticipant) {\n console.warn(\n \"Cannot send message: room not connected or no local participant\"\n );\n return;\n }\n\n // In WebRTC mode, audio is sent via published tracks, not data messages\n if (\"user_audio_chunk\" in message) {\n // Ignore audio data messages - audio flows through WebRTC tracks\n return;\n }\n\n try {\n const encoder = new TextEncoder();\n const data = encoder.encode(JSON.stringify(message));\n\n await this.room.localParticipant.publishData(data, { reliable: true });\n } catch (error) {\n this.debug({\n type: \"send_message_error\",\n message: {\n message,\n error,\n },\n });\n console.error(\"Failed to send message via WebRTC:\", error);\n }\n }\n\n // Get the room instance for advanced usage\n public getRoom(): Room {\n return this.room;\n }\n}\n","import type {\n BaseConnection,\n SessionConfig,\n ConnectionType,\n} from \"./BaseConnection\";\nimport { WebSocketConnection } from \"./WebSocketConnection\";\nimport { WebRTCConnection } from \"./WebRTCConnection\";\n\nfunction determineConnectionType(config: SessionConfig): ConnectionType {\n // If connectionType is explicitly specified, use it\n if (config.connectionType) {\n return config.connectionType;\n }\n\n // If conversationToken is provided, use WebRTC\n if (\"conversationToken\" in config && config.conversationToken) {\n return \"webrtc\";\n }\n\n // Default to WebSocket for backward compatibility\n return \"websocket\";\n}\n\nexport async function createConnection(\n config: SessionConfig\n): Promise<BaseConnection> {\n const connectionType = determineConnectionType(config);\n\n switch (connectionType) {\n case \"websocket\":\n return WebSocketConnection.create(config);\n case \"webrtc\":\n return WebRTCConnection.create(config);\n default:\n throw new Error(`Unknown connection type: ${connectionType}`);\n }\n}\n","export function isIosDevice() {\n return (\n [\n \"iPad Simulator\",\n \"iPhone Simulator\",\n \"iPod Simulator\",\n \"iPad\",\n \"iPhone\",\n \"iPod\",\n ].includes(navigator.platform) ||\n // iPad on iOS 13 detection\n (navigator.userAgent.includes(\"Mac\") && \"ontouchend\" in document)\n );\n}\n\nexport function isAndroidDevice() {\n return /android/i.test(navigator.userAgent);\n}\n","import { isAndroidDevice, isIosDevice } from \"./compatibility\";\nimport type { DelayConfig } from \"./connection\";\n\nexport async function applyDelay(\n delayConfig: DelayConfig = {\n default: 0,\n // Give the Android AudioManager enough time to switch to the correct audio mode\n android: 3_000,\n }\n) {\n let delay = delayConfig.default;\n if (isAndroidDevice()) {\n delay = delayConfig.android ?? delay;\n } else if (isIosDevice()) {\n delay = delayConfig.ios ?? delay;\n }\n\n if (delay > 0) {\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n}\n","import { createConnection } from \"./utils/ConnectionFactory\";\nimport type { BaseConnection } from \"./utils/BaseConnection\";\nimport { applyDelay } from \"./utils/applyDelay\";\nimport { BaseConversation, type PartialOptions } from \"./BaseConversation\";\n\nexport class TextConversation extends BaseConversation {\n public static async startSession(\n options: PartialOptions\n ): Promise<TextConversation> {\n const fullOptions = BaseConversation.getFullOptions(options);\n\n fullOptions.onStatusChange({ status: \"connecting\" });\n fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });\n\n let connection: BaseConnection | null = null;\n try {\n await applyDelay(fullOptions.connectionDelay);\n connection = await createConnection(options);\n return new TextConversation(fullOptions, connection);\n } catch (error) {\n fullOptions.onStatusChange({ status: \"disconnected\" });\n connection?.close();\n throw error;\n }\n }\n}\n","export function arrayBufferToBase64(b: ArrayBufferLike) {\n const buffer = new Uint8Array(b);\n // @ts-ignore\n const base64Data = window.btoa(String.fromCharCode(...buffer));\n return base64Data;\n}\n\nexport function base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binaryString = window.atob(base64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n","const URLCache = new Map<string, string>();\n\nexport function createWorkletModuleLoader(name: string, sourceCode: string) {\n return async (worklet: AudioWorklet) => {\n const url = URLCache.get(name);\n if (url) {\n return worklet.addModule(url);\n }\n\n const blob = new Blob([sourceCode], { type: \"application/javascript\" });\n const blobURL = URL.createObjectURL(blob);\n try {\n await worklet.addModule(blobURL);\n URLCache.set(name, blobURL);\n return;\n } catch {\n URL.revokeObjectURL(blobURL);\n }\n\n try {\n // Attempting to start a conversation in Safari inside an iframe will\n // throw a CORS error because the blob:// protocol is considered\n // cross-origin. In such cases, fall back to using a base64 data URL:\n const base64 = btoa(sourceCode);\n const moduleURL = `data:application/javascript;base64,${base64}`;\n await worklet.addModule(moduleURL);\n URLCache.set(name, moduleURL);\n } catch (error) {\n throw new Error(\n `Failed to load the ${name} worklet module. Make sure the browser supports AudioWorklets.`\n );\n }\n };\n}\n","/*\n * ulaw encoding logic taken from the wavefile library\n * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js\n */\n\nimport { createWorkletModuleLoader } from \"./createWorkletModuleLoader\";\n\nexport const loadRawAudioProcessor = createWorkletModuleLoader(\n \"raw-audio-processor\",\n // language=JavaScript\n `\nconst BIAS = 0x84;\nconst CLIP = 32635;\nconst encodeTable = [\n 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,\n 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7\n];\n\nfunction encodeSample(sample) {\n let sign;\n let exponent;\n let mantissa;\n let muLawSample;\n sign = (sample >> 8) & 0x80;\n if (sign !== 0) sample = -sample;\n sample = sample + BIAS;\n if (sample > CLIP) sample = CLIP;\n exponent = encodeTable[(sample>>7) & 0xFF];\n mantissa = (sample >> (exponent+3)) & 0x0F;\n muLawSample = ~(sign | (exponent << 4) | mantissa);\n \n return muLawSample;\n}\n\nclass RawAudioProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case \"setFormat\":\n this.isMuted = false;\n this.buffer = []; // Initialize an empty buffer\n this.bufferSize = data.sampleRate / 4;\n this.format = data.format;\n\n if (globalThis.LibSampleRate && sampleRate !== data.sampleRate) {\n globalThis.LibSampleRate.create(1, sampleRate, data.sampleRate).then(resampler => {\n this.resampler = resampler;\n });\n }\n break;\n case \"setMuted\":\n this.isMuted = data.isMuted;\n break;\n }\n };\n }\n process(inputs) {\n if (!this.buffer) {\n return true;\n }\n \n const input = inputs[0]; // Get the first input node\n if (input.length > 0) {\n let channelData = input[0]; // Get the first channel's data\n\n // Resample the audio if necessary\n if (this.resampler) {\n channelData = this.resampler.full(channelData);\n }\n\n // Add channel data to the buffer\n this.buffer.push(...channelData);\n // Get max volume \n let sum = 0.0;\n for (let i = 0; i < channelData.length; i++) {\n sum += channelData[i] * channelData[i];\n }\n const maxVolume = Math.sqrt(sum / channelData.length);\n // Check if buffer size has reached or exceeded the threshold\n if (this.buffer.length >= this.bufferSize) {\n const float32Array = this.isMuted \n ? new Float32Array(this.buffer.length)\n : new Float32Array(this.buffer);\n\n let encodedArray = this.format === \"ulaw\"\n ? new Uint8Array(float32Array.length)\n : new Int16Array(float32Array.length);\n\n // Iterate through the Float32Array and convert each sample to PCM16\n for (let i = 0; i < float32Array.length; i++) {\n // Clamp the value to the range [-1, 1]\n let sample = Math.max(-1, Math.min(1, float32Array[i]));\n\n // Scale the sample to the range [-32768, 32767]\n let value = sample < 0 ? sample * 32768 : sample * 32767;\n if (this.format === \"ulaw\") {\n value = encodeSample(Math.round(value));\n }\n\n encodedArray[i] = value;\n }\n\n // Send the buffered data to the main script\n this.port.postMessage([encodedArray, maxVolume]);\n\n // Clear the buffer after sending\n this.buffer = [];\n }\n }\n return true; // Continue processing\n }\n}\nregisterProcessor(\"raw-audio-processor\", RawAudioProcessor);\n`\n);\n","import { loadRawAudioProcessor } from \"./rawAudioProcessor\";\nimport type { FormatConfig } from \"./connection\";\nimport { isIosDevice } from \"./compatibility\";\n\nexport type InputConfig = {\n preferHeadphonesForIosDevices?: boolean;\n};\n\nconst LIBSAMPLERATE_JS =\n \"https://cdn.jsdelivr.net/npm/@alexanderolsen/libsamplerate-js@2.1.2/dist/libsamplerate.worklet.js\";\n\nexport class Input {\n public static async create({\n sampleRate,\n format,\n preferHeadphonesForIosDevices,\n }: FormatConfig & InputConfig): Promise<Input> {\n let context: AudioContext | null = null;\n let inputStream: MediaStream | null = null;\n\n try {\n const options: MediaTrackConstraints = {\n sampleRate: { ideal: sampleRate },\n echoCancellation: { ideal: true },\n noiseSuppression: { ideal: true },\n };\n\n if (isIosDevice() && preferHeadphonesForIosDevices) {\n const availableDevices =\n await window.navigator.mediaDevices.enumerateDevices();\n const idealDevice = availableDevices.find(\n d =>\n // cautious to include \"bluetooth\" in the search\n // as might trigger bluetooth speakers\n d.kind === \"audioinput\" &&\n [\"airpod\", \"headphone\", \"earphone\"].find(keyword =>\n d.label.toLowerCase().includes(keyword)\n )\n );\n if (idealDevice) {\n options.deviceId = { ideal: idealDevice.deviceId };\n }\n }\n\n const supportsSampleRateConstraint =\n navigator.mediaDevices.getSupportedConstraints().sampleRate;\n\n context = new window.AudioContext(\n supportsSampleRateConstraint ? { sampleRate } : {}\n );\n const analyser = context.createAnalyser();\n if (!supportsSampleRateConstraint) {\n await context.audioWorklet.addModule(LIBSAMPLERATE_JS);\n }\n await loadRawAudioProcessor(context.audioWorklet);\n\n inputStream = await navigator.mediaDevices.getUserMedia({\n audio: options,\n });\n\n const source = context.createMediaStreamSource(inputStream);\n const worklet = new AudioWorkletNode(context, \"raw-audio-processor\");\n worklet.port.postMessage({ type: \"setFormat\", format, sampleRate });\n\n source.connect(analyser);\n analyser.connect(worklet);\n\n await context.resume();\n\n return new Input(context, analyser, worklet, inputStream);\n } catch (error) {\n inputStream?.getTracks().forEach(track => track.stop());\n context?.close();\n throw error;\n }\n }\n\n private constructor(\n public readonly context: AudioContext,\n public readonly analyser: AnalyserNode,\n public readonly worklet: AudioWorkletNode,\n public readonly inputStream: MediaStream\n ) {}\n\n public async close() {\n this.inputStream.getTracks().forEach(track => track.stop());\n await this.context.close();\n }\n\n public setMuted(isMuted: boolean) {\n this.worklet.port.postMessage({ type: \"setMuted\", isMuted });\n }\n}\n","/*\n * ulaw decoding logic taken from the wavefile library\n * https://github.com/rochars/wavefile/blob/master/lib/codecs/mulaw.js\n */\n\nimport { createWorkletModuleLoader } from \"./createWorkletModuleLoader\";\n\nexport const loadAudioConcatProcessor = createWorkletModuleLoader(\n \"audio-concat-processor\",\n // language=JavaScript\n `\nconst decodeTable = [0,132,396,924,1980,4092,8316,16764];\n\nexport function decodeSample(muLawSample) {\n let sign;\n let exponent;\n let mantissa;\n let sample;\n muLawSample = ~muLawSample;\n sign = (muLawSample & 0x80);\n exponent = (muLawSample >> 4) & 0x07;\n mantissa = muLawSample & 0x0F;\n sample = decodeTable[exponent] + (mantissa << (exponent+3));\n if (sign !== 0) sample = -sample;\n\n return sample;\n}\n\nclass AudioConcatProcessor extends AudioWorkletProcessor {\n constructor() {\n super();\n this.buffers = []; // Initialize an empty buffer\n this.cursor = 0;\n this.currentBuffer = null;\n this.wasInterrupted = false;\n this.finished = false;\n \n this.port.onmessage = ({ data }) => {\n switch (data.type) {\n case \"setFormat\":\n this.format = data.format;\n break;\n case \"buffer\":\n this.wasInterrupted = false;\n this.buffers.push(\n this.format === \"ulaw\"\n ? new Uint8Array(data.buffer)\n : new Int16Array(data.buffer)\n );\n break;\n case \"interrupt\":\n this.wasInterrupted = true;\n break;\n case \"clearInterrupted\":\n if (this.wasInterrupted) {\n this.wasInterrupted = false;\n this.buffers = [];\n this.currentBuffer = null;\n }\n }\n };\n }\n process(_, outputs) {\n let finished = false;\n const output = outputs[0][0];\n for (let i = 0; i < output.length; i++) {\n if (!this.currentBuffer) {\n if (this.buffers.length === 0) {\n finished = true;\n break;\n }\n this.currentBuffer = this.buffers.shift();\n this.cursor = 0;\n }\n\n let value = this.currentBuffer[this.cursor];\n if (this.format === \"ulaw\") {\n value = decodeSample(value);\n }\n output[i] = value / 32768;\n this.cursor++;\n\n if (this.cursor >= this.currentBuffer.length) {\n this.currentBuffer = null;\n }\n }\n\n if (this.finished !== finished) {\n this.finished = finished;\n this.port.postMessage({ type: \"process\", finished });\n }\n\n return true; // Continue processing\n }\n}\n\nregisterProcessor(\"audio-concat-processor\", AudioConcatProcessor);\n`\n);\n","import { loadAudioConcatProcessor } from \"./audioConcatProcessor\";\nimport type { FormatConfig } from \"./connection\";\n\nexport class Output {\n public static async create({\n sampleRate,\n format,\n }: FormatConfig): Promise<Output> {\n let context: AudioContext | null = null;\n try {\n context = new AudioContext({ sampleRate });\n const analyser = context.createAnalyser();\n const gain = context.createGain();\n gain.connect(analyser);\n analyser.connect(context.destination);\n await loadAudioConcatProcessor(context.audioWorklet);\n const worklet = new AudioWorkletNode(context, \"audio-concat-processor\");\n worklet.port.postMessage({ type: \"setFormat\", format });\n worklet.connect(gain);\n\n await context.resume();\n\n return new Output(context, analyser, gain, worklet);\n } catch (error) {\n context?.close();\n throw error;\n }\n }\n\n private constructor(\n public readonly context: AudioContext,\n public readonly analyser: AnalyserNode,\n public readonly gain: GainNode,\n public readonly worklet: AudioWorkletNode\n ) {}\n\n public async close() {\n await this.context.close();\n }\n}\n","import { arrayBufferToBase64, base64ToArrayBuffer } from \"./utils/audio\";\nimport { Input } from \"./utils/input\";\nimport { Output } from \"./utils/output\";\nimport { createConnection } from \"./utils/ConnectionFactory\";\nimport type { BaseConnection } from \"./utils/BaseConnection\";\nimport type { AgentAudioEvent, InterruptionEvent } from \"./utils/events\";\nimport { applyDelay } from \"./utils/applyDelay\";\nimport {\n BaseConversation,\n type Options,\n type PartialOptions,\n} from \"./BaseConversation\";\n\nexport class VoiceConversation extends BaseConversation {\n public static async startSession(\n options: PartialOptions\n ): Promise<VoiceConversation> {\n const fullOptions = BaseConversation.getFullOptions(options);\n\n fullOptions.onStatusChange({ status: \"connecting\" });\n fullOptions.onCanSendFeedbackChange({ canSendFeedback: false });\n\n let input: Input | null = null;\n let connection: BaseConnection | null = null;\n let output: Output | null = null;\n let preliminaryInputStream: MediaStream | null = null;\n\n let wakeLock: WakeLockSentinel | null = null;\n if (options.useWakeLock ?? true) {\n try {\n wakeLock = await navigator.wakeLock.request(\"screen\");\n } catch (e) {\n // Wake Lock is not required for the conversation to work\n }\n }\n\n try {\n // some browsers won't allow calling getSupportedConstraints or enumerateDevices\n // before getting approval for microphone access\n preliminaryInputStream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n });\n\n await applyDelay(fullOptions.connectionDelay);\n connection = await createConnection(options);\n [input, output] = await Promise.all([\n Input.create({\n ...connection.inputFormat,\n preferHeadphonesForIosDevices: options.preferHeadphonesForIosDevices,\n }),\n Output.create(connection.outputFormat),\n ]);\n\n preliminaryInputStream?.getTracks().forEach(track => track.stop());\n preliminaryInputStream = null;\n\n return new VoiceConversation(\n fullOptions,\n connection,\n input,\n output,\n wakeLock\n );\n } catch (error) {\n fullOptions.onStatusChange({ status: \"disconnected\" });\n preliminaryInputStream?.getTracks().forEach(track => track.stop());\n connection?.close();\n await input?.close();\n await output?.close();\n try {\n await wakeLock?.release();\n wakeLock = null;\n } catch (e) {}\n throw error;\n }\n }\n\n private inputFrequencyData?: Uint8Array;\n private outputFrequencyData?: Uint8Array;\n\n protected constructor(\n options: Options,\n connection: BaseConnection,\n public readonly input: Input,\n public readonly output: Output,\n public wakeLock: WakeLockSentinel | null\n ) {\n super(options, connection);\n this.input.worklet.port.onmessage = this.onInputWorkletMessage;\n this.output.worklet.port.onmessage = this.onOutputWorkletMessage;\n }\n\n protected override async handleEndSession() {\n await super.handleEndSession();\n try {\n await this.wakeLock?.release();\n this.wakeLock = null;\n } catch (e) {}\n\n await this.input.close();\n await this.output.close();\n }\n\n protected override handleInterruption(event: InterruptionEvent) {\n super.handleInterruption(event);\n this.fadeOutAudio();\n }\n\n protected override handleAudio(event: AgentAudioEvent) {\n if (this.lastInterruptTimestamp <= event.audio_event.event_id) {\n this.options.onAudio(event.audio_event.audio_base_64);\n this.addAudioBase64Chunk(event.audio_event.audio_base_64);\n this.currentEventId = event.audio_event.event_id;\n this.updateCanSendFeedback();\n this.updateMode(\"speaking\");\n }\n }\n\n private onInputWorkletMessage = (event: MessageEvent): void => {\n const rawAudioPcmData = event.data[0];\n\n // TODO: When supported, maxVolume can be used to avoid sending silent audio\n // const maxVolume = event.data[1];\n\n if (this.status === \"connected\") {\n this.connection.sendMessage({\n user_audio_chunk: arrayBufferToBase64(rawAudioPcmData.buffer),\n });\n }\n };\n\n private onOutputWorkletMessage = ({ data }: MessageEvent): void => {\n if (data.type === \"process\") {\n this.updateMode(data.finished ? \"listening\" : \"speaking\");\n }\n };\n\n private addAudioBase64Chunk = (chunk: string) => {\n this.output.gain.gain.value = this.volume;\n this.output.worklet.port.postMessage({ type: \"clearInterrupted\" });\n this.output.worklet.port.postMessage({\n type: \"buffer\",\n buffer: base64ToArrayBuffer(chunk),\n });\n };\n\n private fadeOutAudio = () => {\n // mute agent\n this.updateMode(\"listening\");\n this.output.worklet.port.postMessage({ type: \"interrupt\" });\n this.output.gain.gain.exponentialRampToValueAtTime(\n 0.0001,\n this.output.context.currentTime + 2\n );\n\n // reset volume back\n setTimeout(() => {\n this.output.gain.gain.value = this.volume;\n this.output.worklet.port.postMessage({ type: \"clearInterrupted\" });\n }, 2000); // Adjust the duration as needed\n };\n\n private calculateVolume = (frequencyData: Uint8Array) => {\n if (frequencyData.length === 0) {\n return 0;\n }\n\n // TODO: Currently this averages all frequencies, but we should probably\n // bias towards the frequencies that are more typical for human voice\n let volume = 0;\n for (let i = 0; i < frequencyData.length; i++) {\n volume += frequencyData[i] / 255;\n }\n volume /= frequencyData.length;\n\n return volume < 0 ? 0 : volume > 1 ? 1 : volume;\n };\n\n public setMicMuted(isMuted: boolean) {\n this.input.setMuted(isMuted);\n }\n\n public getInputByteFrequencyData() {\n this.inputFrequencyData ??= new Uint8Array(\n this.input.analyser.frequencyBinCount\n );\n this.input.analyser.getByteFrequencyData(this.inputFrequencyData);\n return this.inputFrequencyData;\n }\n\n public getOutputByteFrequencyData() {\n this.outputFrequencyData ??= new Uint8Array(\n this.output.analyser.frequencyBinCount\n );\n this.output.analyser.getByteFrequencyData(this.outputFrequencyData);\n return this.outputFrequencyData;\n }\n\n public getInputVolume() {\n return this.calculateVolume(this.getInputByteFrequencyData());\n }\n\n public getOutputVolume() {\n return this.calculateVolume(this.getOutputByteFrequencyData());\n }\n}\n","const HTTPS_API_ORIGIN = \"https://api.elevenlabs.io\";\n\nexport function postOverallFeedback(\n conversationId: string,\n like: boolean,\n origin: string = HTTPS_API_ORIGIN\n) {\n return fetch(`${origin}/v1/convai/conversations/${conversationId}/feedback`, {\n method: \"POST\",\n body: JSON.stringify({\n feedback: like ? \"like\" : \"dislike\",\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n}\n","import { BaseConversation, type PartialOptions } from \"./BaseConversation\";\nimport { TextConversation } from \"./TextConversation\";\nimport { VoiceConversation } from \"./VoiceConversation\";\n\nexport type {\n Mode,\n Role,\n Options,\n PartialOptions,\n ClientToolsConfig,\n Callbacks,\n Status,\n} from \"./BaseConversation\";\nexport type { InputConfig } from \"./utils/input\";\nexport type { IncomingSocketEvent } from \"./utils/events\";\nexport type {\n SessionConfig,\n BaseSessionConfig,\n DisconnectionDetails,\n Language,\n ConnectionType,\n} from \"./utils/BaseConnection\";\nexport { createConnection } from \"./utils/ConnectionFactory\";\nexport { WebSocketConnection } from \"./utils/WebSocketConnection\";\nexport { WebRTCConnection } from \"./utils/WebRTCConnection\";\nexport { postOverallFeedback } from \"./utils/postOverallFeedback\";\n\nexport class Conversation extends BaseConversation {\n public static startSession(options: PartialOptions): Promise<Conversation> {\n return options.textOnly\n ? TextConversation.startSession(options)\n : VoiceConversation.startSession(options);\n }\n}\n"],"names":["EMPTY_FREQUENCY_DATA","Uint8Array","BaseConversation","options","connection","_this3","_this","this","_this2","lastInterruptTimestamp","mode","status","volume","currentEventId","lastFeedbackEventId","canSendFeedback","endSessionWithDetails","details","Promise","resolve","updateStatus","handleEndSession","then","onDisconnect","e","reject","onMessage","parsedEvent","type","handleInterruption","handleAgentResponse","handleUserTranscript","handleTentativeAgentResponse","handleClientToolCall","handleAudio","sendMessage","event_id","ping_event","onDebug","setVolume","_ref","onConnect","conversationId","getFullOptions","partialOptions","_extends","clientTools","onError","onAudio","onModeChange","onStatusChange","onCanSendFeedbackChange","_proto","prototype","endSession","reason","close","updateMode","updateCanSendFeedback","event","interruption_event","source","message","agent_response_event","agent_response","user_transcription_event","user_transcript","response","tentative_agent_response_internal_event","tentative_agent_response","_this5","Object","hasOwnProperty","call","client_tool_call","tool_name","_temp","parameters","result","formattedResult","JSON","stringify","String","tool_call_id","is_error","_catch","clientToolName","onUnhandledClientToolCall","context","console","error","getId","isOpen","setMicMuted","isMuted","getInputByteFrequencyData","getOutputByteFrequencyData","getInputVolume","getOutputVolume","sendFeedback","like","score","warn","sendContextualUpdate","text","sendUserMessage","sendUserActivity","sendMCPToolApprovalResult","toolCallId","isApproved","is_approved","BaseConnection","config","queue","disconnectionDetails","onDisconnectCallback","onMessageCallback","debug","info","callback","length","queueMicrotask","forEach","disconnect","_this$onDisconnectCal","handleMessage","push","parseFormat","format","_format$split","split","formatPart","sampleRatePart","includes","Error","sampleRate","Number","parseInt","isNaN","PACKAGE_VERSION","isValidSocketEvent","CONVERSATION_INITIATION_CLIENT_DATA_TYPE","constructOverrides","_config$overrides$age","_config$overrides$age2","_config$overrides$age3","_config$overrides$tts","_config$overrides$con","overridesEvent","overrides","conversation_config_override","agent","prompt","first_message","firstMessage","language","tts","voice_id","voiceId","conversation","text_only","textOnly","customLlmExtraBody","custom_llm_extra_body","dynamicVariables","dynamic_variables","userId","user_id","WebSocketConnection","_BaseConnection","socket","inputFormat","outputFormat","addEventListener","setTimeout","code","parse","data","_","_inheritsLoose","create","_config$origin","_config$overrides","_config$overrides2","url","origin","version","client","signedUrl","separator","agentId","protocols","authorization","WebSocket","_socket","send","once","conversation_initiation_metadata_event","conversationConfig","conversation_id","agent_output_audio_format","user_input_audio_format","_socket2","WebRTCConnection","room","isConnected","setupRoomEventListeners","conversationToken","_temp2","_result3","Room","Date","now","connect","livekitUrl","onConnected","off","RoomEvent","Connected","on","name","localParticipant","setMicrophoneEnabled","_exit","fetch","ok","statusText","json","token","msg","Disconnected","CloseEvent","toString","ConnectionStateChanged","state","ConnectionState","Event","DataReceived","payload","participant","TextDecoder","decode","TrackSubscribed","track","publication","kind","Track","Kind","Audio","identity","audioElement","attach","autoplay","controls","style","display","document","body","appendChild","_this4","_temp3","TextEncoder","encode","publishData","reliable","getRoom","createConnection","connectionType","determineConnectionType","isIosDevice","navigator","platform","userAgent","applyDelay","delayConfig","default","android","_delayConfig$android","delay","test","_delayConfig$ios","ios","TextConversation","_BaseConversation","apply","arguments","startSession","fullOptions","connectionDelay","_createConnection","_connection","base64ToArrayBuffer","base64","binaryString","window","atob","len","bytes","i","charCodeAt","buffer","URLCache","Map","createWorkletModuleLoader","sourceCode","worklet","_result","moduleURL","btoa","addModule","set","get","blob","Blob","blobURL","URL","createObjectURL","revokeObjectURL","loadRawAudioProcessor","Input","analyser","inputStream","preferHeadphonesForIosDevices","_temp4","audioWorklet","mediaDevices","getUserMedia","audio","_navigator$mediaDevic","createMediaStreamSource","AudioWorkletNode","port","postMessage","resume","supportsSampleRateConstraint","getSupportedConstraints","AudioContext","createAnalyser","ideal","echoCancellation","noiseSuppression","enumerateDevices","availableDevices","idealDevice","find","d","keyword","label","toLowerCase","deviceId","_inputStream","_context","getTracks","stop","setMuted","loadAudioConcatProcessor","Output","gain","createGain","destination","VoiceConversation","input","output","wakeLock","inputFrequencyData","outputFrequencyData","onInputWorkletMessage","b","user_audio_chunk","fromCharCode","onOutputWorkletMessage","finished","addAudioBase64Chunk","chunk","value","fadeOutAudio","exponentialRampToValueAtTime","currentTime","calculateVolume","frequencyData","onmessage","_temp5","preliminaryInputStream","all","_Promise$all","_preliminaryInputStre","_preliminaryInputStre2","_input","_output","_wakeLock","release","_options$useWakeLock","useWakeLock","request","_navigator$wakeLock$r","_temp7","_temp6","_this2$wakeLock","audio_event","audio_base_64","_this$inputFrequencyD","frequencyBinCount","getByteFrequencyData","postOverallFeedback","method","feedback","headers","Conversation"],"mappings":"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"}
|