@elevenlabs/react-native
Version:
ElevenLabs React Native SDK for Conversational AI
3 lines (2 loc) • 10.5 kB
JavaScript
import e,{useRef as n,useCallback as t,useState as r,useEffect as o,useContext as c,createContext as a}from"react";import{AudioSession as l,useLocalParticipant as i,useDataChannel as s,LiveKitRoom as u,registerGlobals as d}from"@livekit/react-native";function v(){return v=Object.assign?Object.assign.bind():function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var r in t)({}).hasOwnProperty.call(t,r)&&(e[r]=t[r])}return e},v.apply(null,arguments)}var f="0.2.1",m=function(n){var t=n.onReady,r=n.isConnected,c=n.callbacks,a=n.sendMessage,l=n.clientTools,u=void 0===l?{}:l,d=n.updateCurrentEventId,v=i().localParticipant,f=e.useRef(1);return o(function(){r&&v&&t(v)},[r,v,t]),s(function(e){var n,t,r=new TextDecoder,o=JSON.parse(r.decode(e.payload));if(o.type){var l;if(null==c.onMessage||c.onMessage({message:o,source:null!=(n=e.from)&&n.isAgent?"ai":"user"}),null!=(t=e.from)&&t.isAgent&&(null==c.onModeChange||c.onModeChange({mode:null!=(l=e.from)&&l.isSpeaking?"speaking":"listening"}),"agent_response"===o.type&&d)){var i=f.current++;d(i)}switch(o.type){case"ping":a({type:"pong",event_id:o.ping_event.event_id});break;case"client_tool_call":!function(e){try{return Promise.resolve(function(){if(Object.prototype.hasOwnProperty.call(u,e.client_tool_call.tool_name)){var n=function(n,t){try{var r=Promise.resolve(u[e.client_tool_call.tool_name](e.client_tool_call.parameters)).then(function(n){var t="object"==typeof n?JSON.stringify(n):String(n);a({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:t,is_error:!1})})}catch(e){return t(e)}return r&&r.then?r.then(void 0,t):r}(0,function(n){null==c.onError||c.onError("Client tool execution failed with following error: "+(null==n?void 0:n.message),{clientToolName:e.client_tool_call.tool_name}),a({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(c.onUnhandledClientToolCall)return void c.onUnhandledClientToolCall(e);var t="Client tool with name "+e.client_tool_call.tool_name+" is not defined on client";null==c.onError||c.onError(t,{clientToolName:e.client_tool_call.tool_name}),a({type:"client_tool_result",tool_call_id:e.client_tool_call.tool_call_id,result:t,is_error:!0})}}())}catch(e){return Promise.reject(e)}}(o);break;default:null==c.onDebug||c.onDebug(o)}}else null==c.onDebug||c.onDebug({type:"invalid_event",message:o})}),null},h=function(n){var t=n.children;/*#__PURE__*/return e.createElement(u,{serverUrl:n.serverUrl,token:n.token,connect:n.connect,audio:!0,video:!1,options:{adaptiveStream:{pixelDensity:"screen"}},onConnected:n.onConnected,onDisconnected:n.onDisconnected,onError:n.onError},/*#__PURE__*/e.createElement(m,{onReady:n.onParticipantReady,isConnected:n.roomConnected,callbacks:n.callbacks,sendMessage:n.sendMessage,clientTools:n.clientTools,updateCurrentEventId:n.updateCurrentEventId}),t)},g=["serverUrl","tokenFetchUrl","clientTools"],_=/*#__PURE__*/a(null),p=function(n){void 0===n&&(n={});var t=c(_);if(!t)throw new Error("useConversation must be used within ElevenLabsProvider");var r=n.serverUrl,o=n.tokenFetchUrl,a=n.clientTools,l=function(e,n){if(null==e)return{};var t={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(-1!==n.indexOf(r))continue;t[r]=e[r]}return t}(n,g);return e.useEffect(function(){r&&t.setServerUrl(r)},[t,r]),e.useEffect(function(){o&&t.setTokenFetchUrl(o)},[t,o]),a&&t.setClientTools(a),t.setCallbacks(l),t.conversation},C=function(c){var a=c.children;d();var i=r(""),s=i[0],u=i[1],m=r(!1),g=m[0],p=m[1],C=r("disconnected"),k=C[0],y=C[1],b=r("wss://livekit.rtc.elevenlabs.io"),E=b[0],S=b[1],P=r(void 0),w=P[0],x=P[1],T=r(""),U=T[0],D=T[1],F=r(!1),I=F[0],M=F[1],R=r(!1),O=R[0],j=R[1],L=e.useRef(1),N=e.useRef(1),A=e.useRef({}),V=function(){var e=n({}),r=t(function(n){e.current=n},[]);return{callbacksRef:e,setCallbacks:r}}(),B=V.callbacksRef,J=V.setCallbacks,K=e.useCallback(function(e){var n=v({},e,{onModeChange:function(n){M("speaking"===n.mode),null==e.onModeChange||e.onModeChange(n)}});J(n)},[J]),q=function(e,n,o,c,a,l){var i=r({}),s=i[0],u=i[1],d=r(null),v=d[0],m=d[1],h=r({}),g=h[0],_=h[1];return{startSession:t(function(t){try{return Promise.resolve(function(r,i){try{var s=function(){function r(e){var n=function(e){try{var n,t;return(null==(t=((null==(n=JSON.parse(atob(e.split(".")[1])).video)?void 0:n.room)||"").match(/(conv_[a-zA-Z0-9]+)/))?void 0:t[0])||""}catch(e){return console.warn("Could not extract conversation ID from token"),""}}(i);a(n),c(i),o(!0)}var i;n("connecting"),null==e.current.onStatusChange||e.current.onStatusChange({status:"connecting"}),u(t.overrides||{}),m(t.customLlmExtraBody||null),_(t.dynamicVariables||{});var s=function(){if(!t.conversationToken)return function(){if(t.agentId)return console.info("Getting conversation token for agentId:",t.agentId),Promise.resolve(function(e,n){try{return Promise.resolve(fetch((n||"https://api.elevenlabs.io/v1/convai/conversation/token")+"?agent_id="+e+"&source=react_native_sdk&version="+f)).then(function(e){return Promise.resolve(e.json()).then(function(n){if(!e.ok)throw new Error("Failed to get conversation token: "+n.detail.message);if(!n.token)throw new Error("No conversation token received from API");return n.token})})}catch(e){return Promise.reject(e)}}(t.agentId,t.tokenFetchUrl||l)).then(function(e){i=e});throw new Error("Either conversationToken or agentId is required")}();i=t.conversationToken}();return s&&s.then?s.then(r):r()}()}catch(e){return i(e)}return s&&s.then?s.then(void 0,i):s}(0,function(t){throw n("disconnected"),null==e.current.onStatusChange||e.current.onStatusChange({status:"disconnected"}),null==e.current.onError||e.current.onError(t),t}))}catch(e){return Promise.reject(e)}},[e,n,o,c,a,l]),endSession:t(function(){try{try{o(!1),c(""),n("disconnected"),null==e.current.onStatusChange||e.current.onStatusChange({status:"disconnected"}),null==e.current.onDisconnect||e.current.onDisconnect("User ended conversation")}catch(n){throw null==e.current.onError||e.current.onError(n),n}return Promise.resolve()}catch(e){return Promise.reject(e)}},[e,o,c,n]),overrides:s,customLlmExtraBody:v,dynamicVariables:g}}(B,y,p,u,D,w),z=q.startSession,G=q.endSession,W=q.overrides,Z=q.customLlmExtraBody,H=q.dynamicVariables,Q=function(e,n,c){var a=r(!1),i=a[0],s=a[1],u=r(null),d=u[0],v=u[1];return o(function(){return function(){try{return Promise.resolve(l.startAudioSession()).then(function(){})}catch(e){return Promise.reject(e)}}(),function(){l.stopAudioSession()}},[]),{roomConnected:i,localParticipant:d,handleParticipantReady:t(function(e){v(e)},[]),handleConnected:t(function(){s(!0),n("connected"),null==e.current.onConnect||e.current.onConnect({conversationId:c})},[c,e,n]),handleDisconnected:t(function(){s(!1),n("disconnected"),v(null),null==e.current.onDisconnect||e.current.onDisconnect("disconnected")},[e,n]),handleError:t(function(n){console.error("LiveKit error:",n),null==e.current.onError||e.current.onError(n.message,void 0)},[e])}}(B,y,U),X=Q.roomConnected,Y=Q.localParticipant,$=Q.handleParticipantReady,ee=Q.handleConnected,ne=Q.handleDisconnected,te=Q.handleError,re=e.useCallback(function(){L.current=1,N.current=1,j(!1),null==B.current.onCanSendFeedbackChange||B.current.onCanSendFeedbackChange({canSendFeedback:!1}),ee()},[ee,B]),oe=e.useCallback(function(){j(!1),ne()},[ne]),ce=function(e,n,r){return{sendMessage:t(function(t){try{if("connected"!==e||!n)return console.warn("Cannot send message: room not connected or no local participant"),Promise.resolve();var o=function(e,r){try{var o=(c=(new TextEncoder).encode(JSON.stringify(t)),Promise.resolve(n.publishData(c,{reliable:!0})).then(function(){}))}catch(e){return r(e)}var c;return o&&o.then?o.then(void 0,r):o}(0,function(e){console.error("Failed to send message via WebRTC:",e),console.error("Error details:",e),null==r.current.onError||r.current.onError(e)});return Promise.resolve(o&&o.then?o.then(function(){}):void 0)}catch(e){return Promise.reject(e)}},[e,n,r])}}(k,Y,B),ae=ce.sendMessage,le=e.useCallback(function(){var e=L.current!==N.current;O!==e&&(j(e),null==B.current.onCanSendFeedbackChange||B.current.onCanSendFeedbackChange({canSendFeedback:e}))},[O,B]),ie=e.useCallback(function(e){O?(ae({type:"feedback",score:e?"like":"dislike",event_id:L.current}),N.current=L.current,le()):console.warn(0===N.current?"Cannot send feedback: the conversation has not started yet.":"Cannot send feedback: feedback has already been sent for the current response.")},[O,ae,le]);e.useCallback(function(e){console.warn("setVolume is not yet implemented in React Native SDK")},[]);var se=e.useCallback(function(e){L.current=e,le()},[le]),ue=e.useCallback(function(e){if($(e),Y){var n=function(e){var n,t,r,o,c,a,l={type:"conversation_initiation_client_data"};return e.overrides&&(l.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==(r=e.overrides.agent)?void 0:r.language},tts:{voice_id:null==(o=e.overrides.tts)?void 0:o.voiceId},conversation:{text_only:null==(c=e.overrides.conversation)?void 0:c.textOnly},source_info:{source:"react_native_sdk",version:(null==(a=e.overrides)||null==(a=a.client)?void 0:a.version)||f}}),e.customLlmExtraBody&&(l.custom_llm_extra_body=e.customLlmExtraBody),e.dynamicVariables&&(l.dynamic_variables=e.dynamicVariables),e.userId&&(l.user_id=e.userId),l}({overrides:W,customLlmExtraBody:Z,dynamicVariables:H});ae(n)}},[$,Y,W,Z,H,ae]),de={startSession:z,endSession:G,status:k,isSpeaking:I,canSendFeedback:O,getId:function(){return U},sendFeedback:ie,sendContextualUpdate:function(e){ae({type:"contextual_update",text:e})},sendUserMessage:function(e){ae({type:"user_message",text:e})},sendUserActivity:function(){ae({type:"user_activity"})}},ve=e.useCallback(function(e){A.current=e},[]);/*#__PURE__*/return e.createElement(_.Provider,{value:{conversation:de,callbacksRef:B,serverUrl:E,tokenFetchUrl:w,clientTools:A.current,setCallbacks:K,setServerUrl:S,setTokenFetchUrl:x,setClientTools:ve}},/*#__PURE__*/e.createElement(h,{serverUrl:E,token:s,connect:g,onConnected:re,onDisconnected:oe,onError:te,roomConnected:X,callbacks:B.current,onParticipantReady:ue,sendMessage:ae,clientTools:A.current,updateCurrentEventId:se},a))};export{C as ElevenLabsProvider,p as useConversation};
//# sourceMappingURL=lib.module.js.map