@eka-care/medassist-core 1.0.71 → 1.0.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs DELETED
@@ -1,2 +0,0 @@
1
- var I=class{eventListeners=new Map;on(e,t){let n=this.eventListeners.get(e)||new Set;n.add(t),this.eventListeners.set(e,n);}off(e,t){let n=this.eventListeners.get(e);n&&(n.delete(t),n.size===0&&this.eventListeners.delete(e));}emit(e,...t){let n=this.eventListeners.get(e);n&&n.forEach(s=>s(...t));}removeAllListeners(){this.eventListeners.clear();}};var R={CONNECTING:"connecting",CONNECTED:"connected",NOT_CONNECTED:"not_connected"},O={CLIENT_CLOSED:"client_closed",SERVER_CLOSED:"server_closed",CONNECTION_ERROR:"connection_error",AUTHENTICATION_ERROR:"authentication_error",MAX_RECONNECT_ATTEMPTS:"max_reconnect_attempts",TIMEOUT:"timeout",NETWORK_ERROR:"network_error"};var M=class{status=R.CONNECTING;queue=[];eventEmitter=new I;disconnectionDetails=null;onErrorCallback=null;onDisconnectCallback=null;onMessageCallback=null;onOpenCallback=null;onStatusChangeCallback=null;getStatus(){return this.status}onOpen(e){this.onOpenCallback=e;}onMessage(e){if(this.onMessageCallback=e,this.queue.length>0){let t=[...this.queue];this.queue.length=0,queueMicrotask(()=>{t.forEach(n=>{this.onMessageCallback?.(n);});});}}onDisconnect(e){this.onDisconnectCallback=e;let t=this.disconnectionDetails;t&&queueMicrotask(()=>{this.onDisconnectCallback?.(t);});}onError(e){this.onErrorCallback=e;}on(e,t){this.eventEmitter.on(e,t);}off(e,t){this.eventEmitter.off(e,t);}emit(e,...t){this.eventEmitter.emit(e,...t);}onStatusChange(e){this.onStatusChangeCallback=e,queueMicrotask(()=>{e(this.status);});}disconnect(e){this.disconnectionDetails||(this.disconnectionDetails=e,this.updateStatus(R.NOT_CONNECTED),this.onDisconnectCallback?.(e));}handleMessage(e){this.onMessageCallback?this.onMessageCallback(e):this.queue.push(e);}updateStatus(e){this.status!==e&&(this.status=e,this.onStatusChangeCallback?.(e));}};var b={API:"API_ERROR",CONNECTION:"CONNECTION_ERROR",RECORDING:"RECORDING_ERROR",FILE:"FILE_ERROR",SESSION:"SESSION_ERROR",MESSAGE:"MESSAGE_ERROR",STORE:"STORE_ERROR",CONFIGURATION:"CONFIGURATION_ERROR",VALIDATION:"VALIDATION_ERROR",AUTH:"AUTH_ERROR",UNKNOWN:"UNKNOWN_ERROR"},u=class extends Error{code;timestamp;cause;context;hint;displayMessage;constructor(e,t=b.UNKNOWN,n={}){super(e),this.name="SynapseError",this.code=t,this.timestamp=new Date,this.cause=n.cause,this.context=n.context,this.hint=n.hint,this.displayMessage=n.displayMessage||n?.hint||e,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor);}},c=class r extends u{status;error;headers;constructor(e,t,n,s){let o=r.makeMessage(t,n,e);super(o,b.API,{cause:n,context:{status:t,hasBody:!!n},hint:t&&t>=500?"Retry the request or contact support if the issue persists.":void 0,displayMessage:e||"Something went wrong"}),this.name="APIError",this.status=t,this.error=n,this.headers=s;}static makeMessage(e,t,n){let s=t instanceof Error?t.message:n;return e&&s?`HTTP ${e}: ${s}`:e?`${e} status code (no body)`:s||"(no status code or body)"}static generate(e,t,n,s){if(!e)return new $({message:n});let o=t?.error,i=o&&typeof o=="object"&&!Array.isArray(o)?o:void 0;switch(e){case 400:return new W(n||"Bad Request",e,i,s);case 401:return new x(n||"Unauthorized",e,i,s);case 403:return new A(n||"Permission Denied",e,i,s);case 404:return new N(n||"Not Found",e,i,s);case 405:return new z(n||"Method Not Allowed",e,i,s);case 429:return new j(n||"Rate Limit Exceeded",e,i,s);case 500:return new X(n||"Internal Server Error",e,i,s);default:return new r(n||"API Error",e,i,s)}}},$=class extends c{constructor({message:e}={}){super(e||"Request was aborted.",void 0,void 0,void 0),this.name="APIUserAbortError";}},w=class extends c{constructor({message:e}={}){super(e||"Request timed out.",void 0,void 0,void 0),this.name="APIConnectionTimeoutError";}},W=class extends c{constructor(e,t,n,s){super(e,t,n,s),this.name="BadRequestError";}},x=class extends c{constructor(e,t,n,s){super(e,t,n,s),this.name="UnauthorizedError";}},A=class extends c{constructor(e,t,n,s){super(e,t,n,s),this.name="PermissionDeniedError";}},N=class extends c{constructor(e,t,n,s){super(e,t,n,s),this.name="NotFoundError";}},z=class extends c{constructor(e,t,n,s){super(e,t,n,s),this.name="MethodNotAllowedError";}},j=class extends c{constructor(e,t,n,s){super(e,t,n,s),this.name="RateLimitError";}},X=class extends c{constructor(e,t,n,s){super(e,t,n,s),this.name="InternalServerError";}},p=class extends u{constructor(e,t={}){super(e,b.CONNECTION,t),this.name="ConnectionError";}},h=class extends u{constructor(e,t={}){super(e,b.RECORDING,t),this.name="RecordingError";}};var v=class extends u{constructor(e,t={}){super(e,b.FILE,t),this.name="FileError";}},_=class extends u{constructor(e,t={}){super(e,b.SESSION,t),this.name="SessionError";}},C=class extends u{constructor(e,t={}){super(e,b.MESSAGE,t),this.name="MessageError";}};function T(r,e,t,n={}){if(r instanceof e)return r;let s={...n,context:{...r instanceof u?r.context:void 0,...n.context},hint:n.hint??(r instanceof u?r.hint:void 0),cause:n.cause??r};if(r instanceof u)return new e(r.message,s);let o=r instanceof Error&&r.message?r.message:t;return new e(o,s)}var L=class extends M{conversationId;socket=null;config;authenticated=false;constructor(e){super(),this.config={...e,reconnect:e.reconnect||true,reconnectAttempts:e.reconnectAttempts||3,reconnectDelay:e.reconnectDelay||1e3},this.conversationId=e.auth.sessionId,this.connect();}connect(){try{if(this.socket&&this.socket.readyState===WebSocket.OPEN||this.authenticated)return;this.updateStatus(R.CONNECTING);let e=this.buildConnectionUrl();this.socket=new WebSocket(e),this.socket.onopen=this.handleOpen.bind(this),this.socket.onmessage=this.handleSocketMessage.bind(this),this.socket.onerror=this.handleError.bind(this),this.socket.onclose=this.handleClose.bind(this);}catch(e){console.log("error from connect",e);let t=T(e,p,"Failed to establish WebSocket connection",{context:{stage:"connect"}});this.onErrorCallback?.(t),this.disconnect({code:1001,reason:O.CONNECTION_ERROR,message:t.message,timestamp:new Date});}}buildConnectionUrl(){let e=new URL(this.config.serverUrl);return e.pathname=`/reloaded/ws/med-assist/session/${this.config.auth.sessionId}/`,e.toString()}handleOpen(){this.authenticated||this.socket?.readyState!==WebSocket.OPEN||this.onOpenCallback?.();}handleSocketMessage(e){try{let t=JSON.parse(e.data);this.handleMessage(t);}catch(t){let n=T(t,C,"Failed to parse incoming WebSocket message",{context:{stage:"handleSocketMessage"}});this.onErrorCallback?.(n);}}handleError(e){console.log("handleError",e);}handleClose(e){let t=e.wasClean,n=e.code,s=e.reason,o,i;if(this.authenticated=false,this.isConnected()){console.log("WebSocket is already connected, skipping reconnection");return}n===1e3?(o=O.CLIENT_CLOSED,i="Connection closed normally"):n===1001||n===1006?(o=O.NETWORK_ERROR,i=e.reason||"Network connection lost"):n===4001||n===1008?e.reason==="timeout"||e.reason==="Authentication timeout"?(o=O.TIMEOUT,i="Connection timed out"):(o=O.AUTHENTICATION_ERROR,i=e.reason||"Authentication failed"):t?(o=O.SERVER_CLOSED,i=s||"Server closed connection"):(o=O.CONNECTION_ERROR,i=s||"Connection closed unexpectedly"),this.disconnect({reason:o,message:i,code:n,timestamp:new Date});}sendMessage(e){if(!this.socket||this.socket.readyState!==WebSocket.OPEN)throw new p("Cannot send message: connection not open",{context:{stage:"sendMessage",readyState:this.socket?.readyState},hint:"Ensure the WebSocket is open before sending messages."});try{this.socket.send(JSON.stringify(e));}catch(t){let n=T(t,p,"Failed to send WebSocket message",{context:{stage:"sendMessage"}});throw this.onErrorCallback?.(n),n}}close(){this.authenticated=false,this.socket&&(this.updateStatus(R.NOT_CONNECTED),this.socket.close(1e3,"Client closed connection"),this.socket=null);}isConnected(){return this.socket?.readyState===WebSocket.OPEN}handleConnected(){this.updateStatus(R.CONNECTED),this.authenticated=true;}};var F=class extends M{conversationId;config;connected=false;activeStreamController=null;constructor(e){super(),this.config=e,this.conversationId=e.auth.sessionId,this.connect();}connect(){this.updateStatus(R.CONNECTING),this.connected=true,setTimeout(()=>{this.onOpenCallback?.();},0);}onOpen(e){this.onOpenCallback=e,this.connected&&setTimeout(()=>e(),0);}buildChatUrl(){let e=new URL(this.config.serverUrl);return e.pathname=`${e.pathname.replace(/\/$/,"")}/med-assist/session/${this.config.auth.sessionId}/chat`,e.toString()}sendMessage(e){if(!this.connected){let n=new p("SSE connection is not open",{context:{stage:"sendMessage"}});this.onErrorCallback?.(n);return}this.activeStreamController?.abort();let t=new AbortController;this.activeStreamController=t,this.streamChat(e,t);}async streamChat(e,t){let n=this.buildChatUrl();try{let s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream","sess-token":this.config.auth.sessionToken,"x-agent-id":this.config.agentId},body:JSON.stringify(e),signal:t.signal});if(!s.ok||!s.body)throw new p(`SSE chat request failed with status ${s.status}`,{context:{stage:"streamChat",status:s.status}});let o=s.body.getReader(),i=new TextDecoder,a="";for(;;){let{done:l,value:g}=await o.read();if(l)break;a+=i.decode(g,{stream:!0}),a=this.extractJsonObjects(a);}a.trim().length>0&&this.extractJsonObjects(a);}catch(s){if(t.signal.aborted)return;let o=T(s,p,"SSE chat stream failed",{context:{stage:"streamChat"}});this.onErrorCallback?.(o);}finally{this.activeStreamController===t&&(this.activeStreamController=null);}}extractJsonObjects(e){let t=0;for(;t<e.length;){let n=e.indexOf("{",t);if(n===-1)return "";let s=this.findObjectEnd(e,n);if(s===-1)return e.slice(n);let o=e.slice(n,s+1);try{let i=JSON.parse(o);this.handleMessage(i);}catch(i){let a=T(i,C,"Failed to parse incoming SSE object",{context:{stage:"extractJsonObjects",objStr:o}});this.onErrorCallback?.(a);}t=s+1;}return ""}findObjectEnd(e,t){let n=0,s=false,o=false;for(let i=t;i<e.length;i++){let a=e[i];if(s){o?o=false:a==="\\"?o=true:a==='"'&&(s=false);continue}if(a==='"')s=true;else if(a==="{")n++;else if(a==="}"&&(n--,n===0))return i}return -1}close(){this.connected=false,this.activeStreamController?.abort(),this.activeStreamController=null,this.updateStatus(R.NOT_CONNECTED);}isConnected(){return this.connected}handleConnected(){this.updateStatus(R.CONNECTED);}};var E={SOCKET:"socket",SSE:"sse"},U=class{static async createConnection(e,t){switch(e){case E.SOCKET:return new L(t);case E.SSE:return new F(t);default:throw new p(`Unsupported connection type: ${e}`,{context:{type:e}})}}};var ie={WEBSOCKET_URL:"wss://matrix-ws.eka.care/reloaded",BASE_API_URL:"https://matrix.eka.care/reloaded"},ce={WEBSOCKET_URL:"wss://matrix-ws.dev.eka.care/reloaded",BASE_API_URL:"https://matrix.dev.eka.care/reloaded"},le={WEBSOCKET_URL:"wss://matrix-ws.dev.eka.care",BASE_API_URL:"https://matrix.dev.eka.care"},J=(r="production")=>r==="development"?ce:r==="production"?ie:r==="staging"?le:ie;var V=class{baseUrl;headers;timeout;maxRetries;constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.timeout=e.timeout||3e4,this.maxRetries=e.maxRetries||3,this.headers={"Content-Type":"application/json",...e.headers},e.authorization&&(this.headers.Authorization=e.authorization);}async request(e,t,n){let s=n?.retries??this.maxRetries,o;for(let i=0;i<=s;i++)try{let a=this.buildUrl(t,n?.params),l=await fetch(a,{method:e,headers:{...this.headers,...n?.headers},body:n?.body?JSON.stringify(n.body):void 0,signal:AbortSignal.timeout(this.timeout)});return l.ok||await this.handleError(l),l.json()}catch(a){if(o=a,i===s||!(a instanceof TypeError&&a.message==="Failed to fetch"||a instanceof DOMException&&a.name==="AbortError"||a instanceof SyntaxError))break;let g=Math.pow(2,i)*100;await new Promise(y=>setTimeout(y,g));}throw o?o instanceof TypeError&&o.message==="Failed to fetch"?new c("Network error: Unable to connect to the server. Please check your internet connection.",0,{type:"NETWORK_ERROR",originalError:o.message}):o instanceof DOMException&&o.name==="AbortError"?new w({message:`Request timed out after ${this.timeout}ms`}):o instanceof SyntaxError?new c("Invalid response format from server",502,{type:"PARSE_ERROR",originalError:o.message}):o instanceof c?o:new c(`Request failed: ${o.message||"Unknown error"}`,500,{type:"UNKNOWN_ERROR",originalError:o}):new c("Unknown error occurred",500,{type:"UNKNOWN_ERROR"})}async get(e,t,n){return this.request("GET",e,{params:t,...n})}async post(e,t,n){return this.request("POST",e,{body:t,...n})}async put(e,t,n){return this.request("PUT",e,{body:t,...n})}async delete(e,t){return this.request("DELETE",e,{...t})}async patch(e,t,n){return this.request("PATCH",e,{body:t,...n})}buildUrl(e,t){let n=`${this.baseUrl}${e}`;if(t){let s=new URLSearchParams(t).toString();n+=`?${s}`;}return n}async handleError(e){let t,n;try{n=await e.json();let s=n,o=s?.error;t=s?.message||s?.msg||o?.msg||o?.message||e.statusText;}catch{t=e.statusText;}throw c.generate(e.status,n,t,e.headers)}};var k=class{client;constructor(e){this.client=e;}async get(e,t,n){return this.client.get(e,t,n)}async post(e,t,n){return this.client.post(e,t,n)}async put(e,t,n){return this.client.put(e,t,n)}async delete(e,t){return this.client.delete(e,t)}async patch(e,t,n){return this.client.patch(e,t,n)}buildPath(e,t){let n=e;for(let[s,o]of Object.entries(t))n=n.replace(`:${s}`,encodeURIComponent(o));return n}};var G=class extends k{basePath="/med-assist/session";async create(e,t){return this.post(this.basePath,e,t?{headers:{"x-auth-token":t}}:void 0)}async retrieve(e){return this.get(`${this.basePath}/${e}`)}async refresh(e,t){return this.get(`${this.basePath}/${e}/refresh`,void 0,{headers:{"x-sess-token":t}})}async feedback(e,t,n,s){return this.put(`${this.basePath}/${e}/messages/${t}/feedback`,{feedback:n,feedback_reason:s})}async callTool(e,t,n,s,o){return this.post(`${this.basePath}/${e}/messages/${n}/tools/${t}`,{tool_params:o},{headers:{"x-sess-token":s}})}};var H=class extends k{basePath="/med-assist/agent-config";async retrieve(e){return this.get(`${this.basePath}/${e}`)}};var Z=class r extends k{static ICE_SERVERS_PATH="/med-assist/voice/ice-servers";static OFFER_PATH="/med-assist/voice/offer";async getIceServers(e,t){return this.get(r.ICE_SERVERS_PATH,{session_id:e,token:t})}async sendOffer(e){return this.post(r.OFFER_PATH,e)}};var K=class{resourceConfig;httpClient;session;config;voiceResource;constructor(e){this.resourceConfig=e,this.httpClient=new V({baseUrl:this.resourceConfig.serverUrl,headers:{"X-agent-id":this.resourceConfig.agentId,"ngrok-skip-browser-warning":"69420",...this.resourceConfig.authorization&&{Authorization:this.resourceConfig.authorization}}}),this.config=new H(this.httpClient),this.session=new G(this.httpClient),this.voiceResource=new Z(this.httpClient);}async createSession(e,t){try{let{profile:n,intent:s,user_location:o,referer:i,...a}=t||{},l={...e&&{user_id:e},...n&&{user_context:n},...(s||Object.keys(a).length>0)&&{session_context:{...s&&{intent:s},...o&&{user_location:o},...a}},...i&&{referer:i}},g=await this.session.create(l,this.resourceConfig.authToken);if(!g?.session_id||!g?.session_token)throw new c("Failed to start session.",500,void 0,void 0);return g}catch(n){throw n instanceof c?n:new c("Failed to start session.",500,void 0,void 0)}}async getAgentConfig(){this.config||(this.config=new H(this.httpClient));try{return await this.config.retrieve(this.resourceConfig.agentId)}catch{throw new c("Failed to get agent config.",500,void 0,void 0)}}async validateSession(e){try{let t=await this.session.retrieve(e);return t.msg&&t.msg==="Session Active"?{expired:!1,active:!0}:{expired:!0,active:!1}}catch(t){if(t instanceof c){if(t.status===401)return {expired:true,active:false};throw t}throw t}}async refreshSession(e,t){return await this.session.refresh(e,t)}async sendFeedback(e,t,n,s){return await this.session.feedback(e,t,n,s)}async callTool(e,t,n,s,o){return await this.session.callTool(e,t,n,s,o)}async getVoiceIceServers(e,t){return await this.voiceResource.getIceServers(e,t)}async sendVoiceOffer(e){return await this.voiceResource.sendOffer(e)}};var S={TEXT:"text",AUDIO:"audio",FILE:"file",TOOL_CALL:"tool",TIPS:"tips",AUDIO_TRANSCRIPT:"audio_transcript",TOOL_START:"tool_start",TOOL_END:"tool_end"},m={PING:"ping",PONG:"pong",CHAT:"chat",STREAM:"stream",AUTH:"auth",END_OF_STREAM:"eos",SYNC:"sync",ERROR:"err",CONNECTION_ESTABLISHED:"conn"};var de=3*1024*1024,Q=class{pendingFiles=[];pendingMessage="";pendingFormats=[];setFilesForUpload(e,t){this.pendingFiles.length>0&&this.clearPendingFilesState();let n=e.filter(s=>this.validateFile(s));if(n.length===0)throw new v("File not supported",{context:{stage:"setFilesForUpload"}});this.pendingFiles=n,t&&t.trim()&&(this.pendingMessage=t),this.pendingFormats=n.map(s=>s.type);}getPendingFileState(){return {files:this.pendingFiles,message:this.pendingMessage||"",formats:this.pendingFormats||[]}}async uploadFilesToPresignedUrl(e){let t=[],n=e.filter(s=>s.url&&s.url.trim());try{if(n.length===0)throw new v("No valid presigned URLs provided",{context:{stage:"uploadFilesToPresignedUrl"}});if(!this.pendingFiles.length)throw new v("No files to upload",{context:{stage:"uploadFilesToPresignedUrl"}});for(let s=0;s<n.length;s++){let o=n[s].url,i=await fetch(o,{method:"PUT",body:this.pendingFiles[s],headers:{"Content-Type":this.pendingFiles[s].type,"x-ms-blob-type":"BlockBlob"}});if(!i.ok)throw new v(`Failed to upload ${this.pendingFiles[s].name} to URL ${s+1}: ${i.status} ${i.statusText}`,{context:{stage:"uploadFilesToPresignedUrl"}});t.push(n[s].id);}return t}catch(s){if(t.length>0)return t;throw T(s,v,"Failed to upload files to presigned URL",{context:{stage:"uploadFilesToPresignedUrl"}})}}blobToFile(e,t){return new File([e],t,{type:e.type})}validateFile(e){return ["application/pdf","image/jpeg","image/png","image/jpg"].includes(e.type)&&e.size<de}clearPendingFilesState(){this.pendingFiles=[],this.pendingMessage="",this.pendingFormats=[];}};var pe=S,f={CONNECTED:"connected",DISCONNECTED:"disconnected",PROGRESS_MESSAGE:"progress_message",MESSAGE_CHUNK:"message_chunk",TIPS_MESSAGE:"tips_message",END_OF_STREAM:"end_of_stream",ERROR:"error",TOOL_CALL:"tool_call",AUDIO_TRANSCRIPT:"audio_transcript",TOOL_START:"tool_start",TOOL_END:"tool_end"},re={SESSION_INACTIVE:"session_not_found",SESSION_EXPIRED:"session_expired",INVALID_EVENT:"invalid_event",INVALID_CONTENT_TYPE:"invalid_content",PARSING_ERROR:"parsing",FILE_UPLOAD_INPROGRESS:"file_upload_inprogress",TIMEOUT:"timeout",SERVER_ERROR:"server_error",SESSION_TOKEN_MISMATCH:"session_token_mismatch",PROMPT_FETCH_ERROR:"prompt_fetch_error",INVALID_FILE_REQUEST:"invalid_file_request"},B={SESSION_EXPIRED:"session_expired"};var ee=class{mediaRecorder=null;mediaStream=null;recordingStartTime=0;autoPauseTimer=null;config;onAudioData=null;onAudioError=null;suppressCallbacks=false;constructor(e={}){this.config={mimeType:"audio/webm;codecs=opus",audioBitsPerSecond:128e3,maxRecordingDuration:9e5,autoPauseEnabled:true,...e};}async checkCurrentPermissionState(){if(!navigator.permissions||!navigator.permissions.query)return "prompt";try{let e=await navigator.permissions.query({name:"microphone"});if(e.state==="denied")throw new h("Microphone permission denied",{context:{permissionState:e.state},hint:"Ensure the browser has microphone access enabled for this site."});return e.state}catch(e){if(e instanceof Error&&e.name==="NotSupportedError")return "prompt"}return "prompt"}async start(e,t){try{if(!navigator.mediaDevices)throw new h("Media devices API is not available. This usually means the page is not served over HTTPS or there are browser restrictions.",{context:{feature:"mediaDevices"},hint:"Serve the app over HTTPS and verify browser/device microphone support.",displayMessage:"Microphone access is unavailable."});if(!window.MediaRecorder)throw new h("MediaRecorder is not supported in this browser",{context:{feature:"MediaRecorder"},hint:"Use a browser that supports the MediaRecorder API.",displayMessage:"Microphone access is unavailable."});let n=["audio/mp3","audio/ogg;codecs=opus","audio/mp4","audio/ogg","audio/wav"].filter(s=>MediaRecorder.isTypeSupported(s));if(n.length===0)throw new h("No supported audio formats found in this browser",{context:{requestedTypes:n},hint:"Verify codec support or adjust the requested MIME types.",displayMessage:"Microphone access is unavailable."});if(this.config.mimeType=n[0],await this.checkCurrentPermissionState(),this.onAudioData=e,this.onAudioError=t??null,this.suppressCallbacks=!1,this.mediaStream=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1,sampleRate:44100,channelCount:1}}),this.mediaRecorder=new MediaRecorder(this.mediaStream,{mimeType:this.config.mimeType,audioBitsPerSecond:this.config.audioBitsPerSecond}),this.mediaRecorder.state!=="inactive")throw new h("MediaRecorder is in an invalid state for start()",{context:{recorderState:this.mediaRecorder.state},displayMessage:"Failed to start recording"});this.setupMediaRecorderEvents(),this.mediaRecorder.start(),this.recordingStartTime=Date.now(),this.config.autoPauseEnabled&&this.setupAutoPauseTimer();}catch(n){throw n instanceof Error&&n.name==="NotAllowedError"?new h("Microphone permission denied",{context:{permissionState:"denied"},hint:"Ensure the browser or device has microphone access enabled for this site/app."}):this.toRecordingError(n,"Failed to start audio recording",{stage:"start"})}}async processAudioChunk(e){try{let t=await this.blobToBase64(e),n=Date.now();if(!this.onAudioData)return;let s={audio:t,format:this.config.mimeType,duration:this.recordingStartTime>0?n-this.recordingStartTime:0,timestamp:this.recordingStartTime>0?this.recordingStartTime:n};this.onAudioData(s);}catch(t){this.handleError(t,{stage:"process_audio_chunk"});}}toRecordingError(e,t,n){if(e instanceof h)return e;if(e instanceof u)return new h(e.message,{cause:e,context:{...e.context,...n},hint:e.hint});let s=e instanceof Error&&e.message?e.message:t;return new h(s,{cause:e,context:n})}handleError(e,t){let n=this.toRecordingError(e,"Unexpected recording error",t);if(this.onAudioError)try{this.onAudioError(n);}catch(s){console.error("Audio error callback failed:",s);}else console.error("AudioManager error:",n);}setupAutoPauseTimer(){this.autoPauseTimer&&clearTimeout(this.autoPauseTimer),this.autoPauseTimer=setTimeout(()=>{this.stop();},this.config.maxRecordingDuration);}setupMediaRecorderEvents(){this.mediaRecorder&&(this.mediaRecorder.ondataavailable=e=>{this.suppressCallbacks||e.data.size<=0||this.processAudioChunk(e.data).catch(t=>this.handleError(t,{stage:"media_recorder_ondataavailable",hasData:e.data.size>0}));},this.mediaRecorder.onstop=async()=>{this.recordingStartTime=0;},this.mediaRecorder.onerror=e=>{this.handleError(e.error instanceof Error?e.error:new Error("MediaRecorder encountered an unknown error"),{stage:"media_recorder_onerror"});},this.mediaRecorder.onstart=()=>{});}blobToBase64(e){return new Promise((t,n)=>{let s=new FileReader;s.onload=()=>{if(typeof s.result=="string"){let o=s.result.split(",")[1];t(o);}else n(new h("Failed to convert blob to base64",{context:{stage:"blob_to_base64"}}));},s.onerror=()=>n(new h("FileReader error while converting audio chunk to base64",{cause:s.error??void 0,context:{stage:"blob_to_base64"}})),s.readAsDataURL(e);})}stop(){if(this.mediaRecorder)try{this.autoPauseTimer&&(clearTimeout(this.autoPauseTimer),this.autoPauseTimer=null),this.mediaRecorder.state==="recording"&&this.mediaRecorder.stop(),this.mediaStream&&(this.mediaStream.getTracks().forEach(e=>e.stop()),this.mediaStream=null);}catch(e){throw this.toRecordingError(e,"Failed to stop audio recording",{stage:"stop"})}}cancel(){if(this.mediaRecorder)try{this.suppressCallbacks=!0,this.autoPauseTimer&&(clearTimeout(this.autoPauseTimer),this.autoPauseTimer=null),this.mediaRecorder.ondataavailable=null,this.mediaRecorder.state==="recording"&&this.mediaRecorder.stop(),this.mediaStream&&(this.mediaStream.getTracks().forEach(e=>e.stop()),this.mediaStream=null);}catch(e){throw this.toRecordingError(e,"Failed to cancel audio recording",{stage:"cancel"})}}destroy(){try{this.cancel(),this.mediaRecorder&&(this.mediaRecorder=null),this.mediaStream&&(this.mediaStream.getTracks().forEach(e=>e.stop()),this.mediaStream=null);}catch(e){throw this.toRecordingError(e,"Failed to destroy audio resources",{stage:"destroy"})}}};var q=class{connection=null;callbacks=null;fileManager=null;audioManager=null;outgoingBuffer=null;constructor(e){this.callbacks=e||null;}setConnection(e){this.connection=e;}handleFileUploadProcess({files:e,message:t,urls:n,tool_declined:s,tool_result:o}){this.fileManager||(this.fileManager=new Q);let i;if(e&&e.length>0)this.fileManager.setFilesForUpload(e,t),i={ev:m.CHAT,ct:S.FILE,_id:Date.now().toString(),ts:Date.now(),data:{extensions:this.fileManager.getPendingFileState().formats,...s&&{tool_declined:s},...o&&{tool_result:o}}};else if(n&&n.length>0){let a=this.fileManager.getPendingFileState().message;i={ev:m.CHAT,ct:S.FILE,_id:Date.now().toString(),ts:Date.now(),data:{urls:n,...a&&{text:a},...s&&{tool_declined:s},...o&&{tool_result:o}}},this.fileManager?.clearPendingFilesState();}return i}sendSocketMessage({message:e,files:t,audio:n,urls:s,tool_declined:o,tool_id:i,tool_result:a,initial_prompts:l}){if(!this.connection?.isConnected()){this.outgoingBuffer={...e!==void 0&&{message:e},...t&&{files:t},...n&&{audio:n},...s&&{urls:s},...o&&{tool_declined:o},...i&&{tool_id:i},...a&&{tool_result:a},...l&&{initial_prompts:l}};return}let g=this.connection,y;if(t&&t.length>0||s&&s.length>0){if(t&&t.length>3){let P=new C("Maximum 3 files are allowed to be sent at a time",{context:{stage:"sendSocketChatMessage"}});throw this.emitError(P),P}y=this.handleFileUploadProcess({files:t,message:e,urls:s,tool_declined:o,tool_result:a});}else e?y={ev:m.CHAT,ct:S.TEXT,_id:Date.now().toString(),ts:Date.now(),data:{text:e,...o&&{tool_declined:o},...i&&{tool_id:i},...l&&{initial_prompts:l},...a&&{tool_result:a}}}:n&&n?.audio&&n?.format?y={ev:m.CHAT,ct:S.AUDIO,_id:Date.now().toString(),ts:Date.now(),data:{audio:n?.audio,format:n?.format,...o&&{tool_declined:o},...a&&{tool_result:a}}}:a&&(y={ev:m.CHAT,ct:S.TEXT,_id:Date.now().toString(),ts:Date.now(),data:{text:"",tool_result:a}});if(!y){let P=new C("No message to send",{context:{stage:"sendSocketChatMessage"}});throw this.emitError(P),P}g.sendMessage(y);}handleIncomingSocketChatMessage(e){let t=this.assertConnection("handleIncomingSocketChatMessage");switch(e.ct){case S.FILE:{e?.data?.urls&&e.data.urls?.length>0&&this.fileManager?.uploadFilesToPresignedUrl(e.data.urls).then(n=>{this.sendSocketMessage({urls:n});}).catch(n=>{let s=this.toFileError(n,"Failed to upload files to presigned URL",{stage:"handleIncomingSocketChatMessage",urls:e.data?.urls?.length});this.emitError(s);});break}case S.TEXT:if(e.data.text&&e.data.text.trim()===""&&e._id){let n={data:{text:e.data.text},messageId:e._id,timestamp:e.ts};t.emit(f.MESSAGE_CHUNK,n);}break;case S.TOOL_CALL:if(e?.data?.tool_id&&e._id){let n={data:{...e.data},messageId:e._id,timestamp:e.ts};t.emit(f.TOOL_CALL,n);}break;case S.AUDIO_TRANSCRIPT:if(e?.data?.text){let n={data:{text:e.data.text},messageId:e._id,timestamp:e.ts};t.emit(f.AUDIO_TRANSCRIPT,n);}break;}}handleIncomingSocketStreamMessage(e){let t=this.assertConnection("handleIncomingSocketStreamMessage");switch(e.ct){case S.TEXT:if(e?.data?.progress_msg){let i={data:{text:e.data.progress_msg},messageId:e._id,timestamp:e.ts};t.emit(f.PROGRESS_MESSAGE,i);return}if(e?.data?.text){let i={data:{text:e.data.text},messageId:e._id,timestamp:e.ts};t.emit(f.MESSAGE_CHUNK,i);}break;case S.TIPS:if(e?.data?.tips){let i={data:{tips:e.data.tips},messageId:e._id,timestamp:e.ts};t.emit(f.TIPS_MESSAGE,i);return}break;case S.TOOL_CALL:if(e?.data?.tool_id&&e._id){let i={data:{...e.data},messageId:e._id,timestamp:e.ts};t.emit(f.TOOL_CALL,i);return}break;case S.TOOL_START:let n={data:e?.data,messageId:e._id||Date.now().toString()};t.emit(f.TOOL_START,n);break;case S.TOOL_END:let s={data:e?.data,messageId:e._id||Date.now().toString()};t.emit(f.TOOL_END,s);break;default:let o=new C(`Unsupported content type ${e?.ct}`,{context:{stage:"handleIncomingSocketStreamMessage",contentType:e.ct}});throw this.emitError(o),o}}handleDisconnect(e){this.connection?.emit?.(f.DISCONNECTED,e);}handleIncomingSocketEndOfStreamMessage(e){this.assertConnection("handleIncomingSocketEndOfStreamMessage").emit(f.END_OF_STREAM);}handleIncomingSocketErrorMessage(e){let t=this.assertConnection("handleIncomingSocketErrorMessage");if(e?.data?.code===re.SESSION_EXPIRED)t.emit(B.SESSION_EXPIRED);else {let n=new C(e?.data?.msg||"Socket error received",{context:{stage:"handleIncomingSocketErrorMessage",errorCode:e?.data?.code},hint:e?.data?.msg,cause:e,displayMessage:e?.data?.msg});console.log("error from socket",n),t.emit(f.ERROR,e);}}sendSocketAuthMessage(e){let t=this.assertConnection("sendSocketAuthMessage"),n={ev:m.AUTH,_id:Date.now().toString(),ts:Date.now(),data:{token:e}};t.sendMessage(n);}sendSocketPingMessage(){let e=this.assertConnection("sendSocketPingMessage"),t={ev:m.PING,_id:Date.now().toString(),ts:Date.now()};e.sendMessage(t);}async startRecording({onChunks:e,onError:t}){if(!e){let n=new h("onChunks is required",{context:{stage:"startRecording"},hint:"onChunks is required"});throw this.emitError(n),n}this.audioManager||(this.audioManager=new ee);try{await this.audioManager.start(e,n=>{let s=this.toRecordingError(n,"Failed to start audio recording",{stage:"startRecording"});t?.(s),this.emitError(s);});}catch(n){let s=this.toRecordingError(n,"Failed to start audio recording",{stage:"startRecording"});throw t?.(s),this.emitError(s),s}}endRecordingWithSocket(){if(!this.audioManager){let e=new h("Audio manager not set. Call startRecording() first.",{context:{stage:"stopRecording"}});throw this.emitError(e),e}try{this.audioManager.stop();}catch(e){let t=this.toRecordingError(e,"Failed to stop audio recording",{stage:"stopRecording"});throw this.emitError(t),t}}sendSocketPongMessage(){let e=this.assertConnection("sendSocketPongMessage"),t={ev:m.PONG,_id:Date.now().toString(),ts:Date.now()};e.sendMessage(t);}handleConnectionEstablished(){this.connection?.handleConnected(),this.connection?.emit(f.CONNECTED),this.flushOutgoingBuffer();}flushOutgoingBuffer(){if(!this.connection?.isConnected()||!this.outgoingBuffer)return;let e=this.outgoingBuffer;this.outgoingBuffer=null,this.sendSocketMessage(e);}cleanupMessageServerState(){this.outgoingBuffer=null,this.connection=null,this.fileManager&&(this.fileManager.clearPendingFilesState(),this.fileManager=null),this.audioManager&&(this.audioManager.destroy(),this.audioManager=null);}emitError(e){this.callbacks?.onError?.(e);}toFileError(e,t,n,s){return T(e,v,t,{context:n,hint:s})}toRecordingError(e,t,n,s){return T(e,h,t,{context:n,hint:s})}assertConnection(e){if(!this.connection){let t=new p("Connection not set. Please ensure the connection is established before calling this method.",{context:{stage:e}});throw this.emitError(t),t}return this.connection}};var D=class r{static isAPIError(e){return e instanceof c}static isNetworkError(e){return e instanceof c&&(e.status===0||e.status===void 0)}static isTimeoutError(e){return e instanceof w}static isAuthError(e){return e instanceof x||e instanceof A}static isClientError(e){return e instanceof c&&e.status!==void 0&&e.status>=400&&e.status<500}static isServerError(e){return e instanceof c&&e.status!==void 0&&e.status>=500}static getUserFriendlyMessage(e){return r.isNetworkError(e)?"Unable to connect to the server. Please check your internet connection.":r.isTimeoutError(e)?"Request timed out. Please try again.":r.isAuthError(e)?"Authentication failed. Please log in again.":r.isServerError(e)?"Server error occurred. Please try again later.":r.isAPIError(e)||e instanceof Error?e.message:"An unexpected error occurred."}static getErrorDetails(e){return r.isAPIError(e)?{type:e.name,message:e.message,code:e.code,status:e.status,timestamp:e.timestamp,stack:e.stack,context:e.context,hint:e.hint}:e instanceof u?{type:e.name,message:e.message,code:e.code,timestamp:e.timestamp,stack:e.stack,context:e.context,hint:e.hint}:e instanceof Error?{type:e.name,message:e.message,stack:e.stack}:{type:"Unknown",message:String(e)}}};var Y=class{audioCtx=null;animFrame=null;start(e,t,n){let s=new AudioContext;this.audioCtx=s;let o=s.createAnalyser();o.fftSize=256,s.createMediaStreamSource(e).connect(o);let i=new Uint8Array(o.frequencyBinCount),a=()=>{if(!this.audioCtx)return;o.getByteFrequencyData(i);let l=i.reduce((g,y)=>g+y,0)/i.length;n(l>t),this.animFrame=requestAnimationFrame(a);};a();}stop(){this.animFrame!==null&&(cancelAnimationFrame(this.animFrame),this.animFrame=null),this.audioCtx&&(this.audioCtx.close().catch(()=>{}),this.audioCtx=null);}};var d={IDLE:"idle",CONNECTING:"connecting",CONNECTED:"connected",LISTENING:"listening",THINKING:"thinking",SPEAKING:"speaking",MUTED:"muted",DISCONNECTING:"disconnecting",ERROR:"error"},ne={STATE_CHANGED:"voice:state_changed",ERROR:"voice:error"};var ge=3e3,ae=8,ue=3600*1e3,he=600;function Ee(r,e){return new Promise(t=>{if(r.iceGatheringState==="complete"){t();return}let n=setTimeout(t,e);r.onicegatheringstatechange=()=>{r.iceGatheringState==="complete"&&(clearTimeout(n),t());};})}var te=class{constructor(e,t,n){this.config=e;this.resourceManager=t;this.getCredentials=n;}config;resourceManager;getCredentials;emitter=new I;remoteAnalyser=new Y;localAnalyser=new Y;pc=null;pcId=null;dataChannel=null;localStream=null;remoteAudio=null;_state=d.IDLE;_isMuted=false;manuallyDisconnected=false;_hasConnectionFailureNotified=false;_userSpeaking=false;_silenceTimer=null;_cachedIceServers=null;_iceServersCachedAt=0;get state(){return this._state}get isMuted(){return this._isMuted}on(e,t){this.emitter.on(e,t);}off(e,t){this.emitter.off(e,t);}async connect(){let e=await this.getCredentials();this.setState(d.CONNECTING),this._hasConnectionFailureNotified=false;try{if(!navigator.mediaDevices?.getUserMedia)throw new Error("Microphone access is not available. Please ensure you are using a secure (HTTPS) connection.");let t=await navigator.mediaDevices.getUserMedia({audio:{channelCount:1,echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,sampleRate:16e3},video:!1});this.localStream=t;let n=await this.fetchIceServers(e),s=new RTCPeerConnection({iceServers:n,iceTransportPolicy:"all"});this.pc=s,this.dataChannel=s.createDataChannel("pipecat-events",{ordered:!0}),this.dataChannel.onopen=()=>console.log("data channel open"),this.dataChannel.onclose=()=>this.handleConnectionFailure(new Error("Data channel closed"),"Voice connection failed"),this.dataChannel.onerror=()=>this.handleConnectionFailure(new Error("Data channel error"),"Voice connection failed"),t.getAudioTracks().forEach(g=>s.addTrack(g,t)),s.ontrack=g=>this.handleRemoteTrack(g),s.onconnectionstatechange=()=>{s.connectionState==="connected"?(this.setState(d.LISTENING),this.startLocalAudioAnalysis(t)):(s.connectionState==="failed"||s.connectionState==="closed")&&(this.releaseResources(),this.setState(d.IDLE));},s.oniceconnectionstatechange=()=>{(s.iceConnectionState==="connected"||s.iceConnectionState==="completed")&&this._state===d.CONNECTING?(this.setState(d.LISTENING),this.startLocalAudioAnalysis(t)):s.iceConnectionState==="failed"&&(this.releaseResources(),this.setState(d.IDLE));};let o=await s.createOffer();await s.setLocalDescription(o);let i=this.config.iceGatheringTimeoutMs??ge;await Ee(s,i);let a=g=>({sdp:s.localDescription.sdp,type:s.localDescription.type,pc_id:this.pcId,request_data:{session_id:g.sessionId,token:g.sessionToken}}),l;try{l=await this.resourceManager.sendVoiceOffer(a(e));}catch(g){if(g instanceof c&&g.status===401&&this.config.handleRefresh){await this.config.handleRefresh();let y=await this.getCredentials();l=await this.resourceManager.sendVoiceOffer(a(y));}else throw g}if(!l)throw new Error("No answer received from voice offer");if(this.pcId=l.pc_id,s.signalingState==="closed")return;await s.setRemoteDescription(new RTCSessionDescription({sdp:l.sdp,type:l.type}));}catch(t){this.handleConnectionFailure(t);}}disconnect(){this.manuallyDisconnected=true,this.setState(d.DISCONNECTING),this.releaseResources(),this.setState(d.IDLE);}toggleMute(){if(!this.localStream)return;let e=this.localStream.getAudioTracks()[0];if(!e)return;let t=e.enabled;this.localStream.getAudioTracks().forEach(n=>{n.enabled=!t;}),this._isMuted=t,this.clearSilenceTimer(),this._userSpeaking=false,this.setState(t?d.MUTED:d.LISTENING);}reset(){this.setState(d.IDLE);}destroy(){this.releaseResources(),this.emitter.removeAllListeners(),this._state=d.IDLE;}async fetchIceServers(e){if(this.config.iceServers)return this.config.iceServers;let t=Date.now();if(this._cachedIceServers&&t-this._iceServersCachedAt<ue)return this._cachedIceServers;let n;try{n=await this.resourceManager.getVoiceIceServers(e.sessionId,e.sessionToken);}catch(s){if(s instanceof c&&s.status===401&&this.config.handleRefresh){await this.config.handleRefresh();let o=await this.getCredentials();n=await this.resourceManager.getVoiceIceServers(o.sessionId,o.sessionToken);}else throw s}if(!Array.isArray(n?.ice_servers)||n.ice_servers.length===0)throw new Error("ICE servers response is empty");return this._cachedIceServers=n.ice_servers,this._iceServersCachedAt=Date.now(),this._cachedIceServers}setState(e){this._state=e,this.emitter.emit(ne.STATE_CHANGED,e);}clearSilenceTimer(){this._silenceTimer!==null&&(clearTimeout(this._silenceTimer),this._silenceTimer=null);}handleConnectionFailure(e,t="Voice connection failed"){if(this._hasConnectionFailureNotified||this._state===d.DISCONNECTING||this.manuallyDisconnected)return;this._hasConnectionFailureNotified=true,console.error("voice connection failure",e),this.releaseResources(),this.setState(d.ERROR);let n={message:t,cause:e};this.emitter.emit(ne.ERROR,n);}releaseResources(){this.remoteAnalyser.stop(),this.localAnalyser.stop(),this.clearSilenceTimer(),this._userSpeaking=false,this.localStream&&(this.localStream.getTracks().forEach(e=>e.stop()),this.localStream=null),this.dataChannel&&(this.dataChannel.close(),this.dataChannel=null),this.pc&&(this.pc.onconnectionstatechange=null,this.pc.oniceconnectionstatechange=null,this.pc.ontrack=null,this.pc.onicecandidate=null,this.pc.ondatachannel=null,this.pc.close(),this.pc=null),this.pcId=null,this._isMuted=false,this.remoteAudio&&(this.remoteAudio.srcObject=null);}startLocalAudioAnalysis(e){let t=this.config.speakingThreshold??ae;this.localAnalyser.start(e,t,n=>{this._state!==d.LISTENING&&this._state!==d.THINKING||(n?(this._userSpeaking=true,this.clearSilenceTimer(),this._state===d.THINKING&&this.setState(d.LISTENING)):this._userSpeaking&&this._silenceTimer===null&&(this._silenceTimer=setTimeout(()=>{this._silenceTimer=null,this._userSpeaking&&this._state===d.LISTENING&&(this._userSpeaking=false,this.setState(d.THINKING));},he)));});}handleRemoteTrack(e){this.remoteAudio||(this.remoteAudio=new Audio,this.remoteAudio.autoplay=true);let t=e.streams[0];this.remoteAudio.srcObject=t;let n=this.config.speakingThreshold??ae;this.remoteAnalyser.start(t,n,s=>{s?(this.clearSilenceTimer(),this._userSpeaking=false,this._state!==d.SPEAKING&&this.setState(d.SPEAKING)):this._state===d.SPEAKING&&this.setState(d.LISTENING);});}};var se=class{connection=null;messageManager;resourceManager;sessionConfig=null;config;connectionType;isRefreshingSession=false;connectionAttempts=0;sdkEventEmitter=new I;_voice=null;constructor(e){this.config={...e,environment:e.environment||"production"},this.connectionType=e.connectionType||E.SSE;let t=J(this.config?.environment).BASE_API_URL;this.resourceManager=new K({agentId:this.config.agentId,serverUrl:this.config.serverUrl||t,...this.config.auth&&{authorization:this.config.auth},...this.config.authToken&&{authToken:this.config.authToken}}),this.messageManager=new q(this.config?.callbacks);}async startSession(e){try{let t=await this.manageSession(e);return await this.initializeConnection(t),this.setupEventHandlers(),t}catch(t){let n=D.getUserFriendlyMessage(t),s=D.getErrorDetails(t);if(t instanceof c&&(t.status===404||t.status===403))throw t;let o=this.toSessionError(t,n||"Failed to start session",{stage:"startSession",details:s},"Check network connectivity or recheck credentials before retrying.");throw this.emitError(o),o}}async sendMessage({message:e,files:t,audio:n,tool_declined:s,tool_id:o,initial_prompts:i,tool_result:a}){switch(this.connectionType){case E.SOCKET:case E.SSE:this.messageManager.sendSocketMessage({message:e,files:t,audio:n,...s&&{tool_declined:s},...o&&{tool_id:o},...i?.length&&{initial_prompts:i},...a&&Object.keys(a)?.length&&{tool_result:a}});break;default:let l=new p("Unsupported connection type",{context:{stage:"sendChatMessage",connectionType:this.connectionType}});throw this.emitError(l),l}}async sendFeedback(e,t,n){if(!this.connection){let s=new p("Connection not established. Session may not be initialized.",{context:{stage:"sendFeedback"},hint:"Call startSession() before attempting to send feedback."});throw this.emitError(s),s}if(!this.sessionConfig?.session_id){let s=new _("Session ID not found",{context:{stage:"sendFeedback"},hint:"Call startSession() before attempting to send feedback."});throw this.emitError(s),s}switch(this.connectionType){case E.SOCKET:case E.SSE:await this.resourceManager.sendFeedback(this.sessionConfig.session_id,e,t,n);break}}on(e,t){this.sdkEventEmitter.on(e,t);}off(e,t){this.sdkEventEmitter.off(e,t);}getSessionConfig(){if(!this.sessionConfig?.session_id||!this.sessionConfig?.session_token)throw new _("Session ID or token not found",{context:{stage:"getSessionConfig"},hint:"Ensure the session API returns both identifiers."});return this.sessionConfig}async callTool(e,t,n){if(!this.connection){let s=new p("Connection not established. Session may not be initialized.",{context:{stage:"callTool"},hint:"Call startSession() before attempting to call tool."});throw this.emitError(s),s}if(!this.sessionConfig?.session_id||!this.sessionConfig?.session_token){let s=new _("Session ID not found",{context:{stage:"callTool"},hint:"Call startSession() before attempting to call tool."});throw this.emitError(s),s}switch(this.connectionType){case E.SOCKET:case E.SSE:try{let o=await this.resourceManager.callTool(this.sessionConfig.session_id,e,t,this.sessionConfig.session_token,n);if(o.error)throw new c(o.error.msg,500,o.error);let i={data:{...o.data},messageId:o._id,timestamp:o.ts};this.connection.emit(f.TOOL_CALL,i);}catch(o){if(o instanceof c&&o?.status===401)return await this.handleSessionExpiry(),await this.callTool(e,t,n);throw o}break;default:let s=new p("Unsupported connection type",{context:{stage:"callTool",connectionType:this.connectionType}});throw this.emitError(s),s}}async startRecording({onChunks:e,onError:t}){switch(this.connectionType){case E.SOCKET:case E.SSE:try{await this.messageManager.startRecording({onChunks:e,onError:t});}catch(s){throw s}break;default:let n=new p("Unsupported connection type",{context:{stage:"sendAudio",connectionType:this.connectionType}});throw this.emitError(n),n}}endRecording(){switch(this.connectionType){case E.SOCKET:case E.SSE:this.messageManager.endRecordingWithSocket();break;default:let e=new p("Unsupported connection type",{context:{stage:"endRecording",connectionType:this.connectionType}});throw this.emitError(e),e}}async getAgentConfig(){return this.resourceManager.getAgentConfig()}isConnected(){return this.connection?.isConnected()??false}get voice(){return this._voice||(this._voice=new te(this.buildVoiceConfig(),this.resourceManager,async()=>{let e=await this.resourceManager.createSession();return {sessionId:e.session_id,sessionToken:e.session_token}})),this._voice}endSession(){this._voice?.destroy(),this._voice=null,this.closeConnection(),this.cleanup();}buildVoiceConfig(){return {offerUrl:`${this.config.serverUrl||J(this.config.environment).BASE_API_URL}/med-assist/voice/offer`,handleRefresh:async()=>{await this.handleSessionExpiry();}}}toClientError(e){return e instanceof c?{message:e.error?.msg||e.message,error:e.error,code:e.code,status:e.status,context:e.context}:e instanceof u?{message:e.displayMessage||e.message,code:e.code,context:e.context}:e instanceof Error?{message:e.message}:{message:"An unexpected error occurred"}}emitError(e){this.config.callbacks?.onError?.(this.toClientError(e));}toSessionError(e,t,n,s){return T(e,_,t,{context:n,hint:s})}async initializeConnection(e){if(this.closeConnection(),!e.session_id||!e.session_token)throw new _("Session ID or token not found",{context:{stage:"initializeConnection"},hint:"Ensure the session API returns both identifiers."});this.sessionConfig=e;let t=J(this.config?.environment),n=this.connectionType===E.SOCKET,s=n?t.WEBSOCKET_URL:t.BASE_API_URL,o=this.config.serverUrl?n?`wss://${this.config.serverUrl.split("://")[1]}`:this.config.serverUrl:null;this.connection=await U.createConnection(this.connectionType,{serverUrl:o||s,auth:{sessionId:e.session_id,sessionToken:e.session_token},agentId:this.config.agentId,userId:this.config.userId,overrides:this.config.overrides}),this.connectionAttempts++,this.messageManager.setConnection(this.connection);let i=this.connection.emit.bind(this.connection);this.connection.emit=(a,...l)=>{i(a,...l),this.sdkEventEmitter.emit(a,...l);};}async manageSession(e){try{if(!e?.session_id)return this.createNewSession();let t=await this.resourceManager.validateSession(e.session_id);if(t.active)return e;if(t.expired)return this.refreshSession(e.session_id,e.session_token);throw new c("Failed to create session",500,void 0,void 0)}catch(t){if(console.log("error",t,t instanceof c),t instanceof c){if(t.status===404||t.status===403)throw t}else if(t instanceof N&&t.status===404)throw t;throw this.toSessionError(t,"Failed to resolve session",{stage:"resolveSession"})}}async refreshSession(e,t){try{return await this.resourceManager.refreshSession(e,t)}catch(n){throw n instanceof c&&this.emitError(n),this.toSessionError(n,"Failed to refresh session",{stage:"refreshSession",sessionId:e})}}async createNewSession(){return await this.resourceManager.createSession(this.config.userId,this.config.context)}setupEventHandlers(){if(this.connection){switch(this.connectionType){case E.SOCKET:this.connection.onOpen(()=>{this.onSocketConnectionOpen();}),this.connection.onMessage(e=>{this.onIncomingSocketMessage(e);}),this.connection.onError(e=>{this.onSocketConnectionError(e);}),this.connection.on(B.SESSION_EXPIRED,()=>{this.handleSessionExpiry();});break;case E.SSE:this.connection.onOpen(()=>{this.messageManager.handleConnectionEstablished();}),this.connection.onMessage(e=>{this.onIncomingSocketMessage(e);}),this.connection.onError(e=>{this.onSocketConnectionError(e);}),this.connection.on(B.SESSION_EXPIRED,()=>{this.handleSessionExpiry();});break;default:throw new p("Unsupported connection type",{context:{stage:"setupEventHandlers",connectionType:this.connectionType},hint:"Use ConnectionType.SOCKET or provide a custom handler."})}this.connection.onDisconnect(async e=>{if(e.reason!==O.CLIENT_CLOSED)if(this.connectionAttempts<3&&this.sessionConfig?.session_id&&this.sessionConfig.session_token)try{await this.startSession({session_id:this.sessionConfig.session_id,session_token:this.sessionConfig.session_token});}catch{this.messageManager.handleDisconnect(e);}else this.messageManager.handleDisconnect(e);});}}onSocketConnectionError(e){this.connection?.emit(f.ERROR,e);let t=this.toConnectionError(e,"WebSocket connection error",{stage:"onSocketConnectionError"},"Verify network connectivity or attempt to reconnect.");this.emitError(t);}onSocketConnectionOpen(){if(!this.sessionConfig?.session_token){let e=new _("Session token not set. Call startSession() first.",{context:{stage:"onSocketConnectionOpen"},hint:"Ensure startSession() completes successfully before socket opens."});throw this.emitError(e),e}this.messageManager.sendSocketAuthMessage(this.sessionConfig.session_token);}onIncomingSocketMessage(e){switch(e.ev){case m.CHAT:this.messageManager.handleIncomingSocketChatMessage(e);break;case m.CONNECTION_ESTABLISHED:this.messageManager.handleConnectionEstablished();break;case m.STREAM:this.messageManager.handleIncomingSocketStreamMessage(e);break;case m.END_OF_STREAM:this.messageManager.handleIncomingSocketEndOfStreamMessage(e);break;case m.PING:this.messageManager.sendSocketPongMessage();break;case m.PONG:this.messageManager.sendSocketPingMessage();break;case m.SYNC:break;case m.ERROR:this.messageManager.handleIncomingSocketErrorMessage(e);break;default:let t=new C("Unsupported message type",{context:{stage:"onIncomingSocketMessage",event:e.ev??"unknown"},hint:"Ensure the server is sending supported socket events."});this.emitError(t);return}}async handleSessionExpiry(){if(this.isRefreshingSession){console.warn("Session is already being refreshed");return}try{if(this.closeConnection(),!this.sessionConfig?.session_id||!this.sessionConfig?.session_token){let t=new _("Session ID or token not found",{context:{stage:"handleSessionExpiry"}});throw this.emitError(t),t}this.isRefreshingSession=!0;let e=await this.refreshSession(this.sessionConfig.session_id,this.sessionConfig.session_token);if(!e.session_id||!e.session_token)throw new _("Session refresh failed",{context:{stage:"handleSessionExpiry"}});this.sessionConfig.session_id=e.session_id,this.sessionConfig.session_token=e.session_token,await this.initializeConnection(e),this.setupEventHandlers(),this.config.callbacks?.onSessionRefreshed?.(e);}catch(e){let t=this.toSessionError(e,"Session expired",{stage:"handleSessionExpiry"});this.emitError(t);}finally{this.isRefreshingSession=false;}}toConnectionError(e,t,n,s){return T(e,p,t,{context:n,hint:s})}closeConnection(){this.connection&&(this.connection.close(),this.connection=null);}cleanup(){this.connectionAttempts=0,this.sdkEventEmitter?.removeAllListeners?.(),this.messageManager?.cleanupMessageServerState?.();}};var Ut={LIKE:"LIKE",DISLIKE:"DISLIKE",NONE:"NONE"};var oe=class extends k{basePath="/med-assist/api-call-tool";async callTool(e,t,n){return this.post(`${this.basePath}?session_id=${e}&tool_name=${t}`,{tool_params:n})}};var me=(i=>(i.MOBILE_VERIFICATION="mobile_verification",i.AVAILABILITY_DATES="availability_dates",i.AVAILABILITY_SLOTS="availability_slots",i.DOCTOR_AVAILABILITY="doctor_availability",i.DOCTOR_DETAILS="doctor_details",i.GET_LOCATION="get_location",i))(me||{}),Se=(l=>(l.MOBILE="mobile_number",l.OTP="otp",l.EMAIL="email_address",l.PILL="pills",l.MULTI="multi",l.DOCTOR_CARD="doctor_card",l.CARD="card",l.MEDIA_CARD="media_card",l))(Se||{}),fe=(o=>(o.DOCTOR_AVAILABILITY="get_doctor_availability",o.AVAILABILITY_DATES="get_available_dates",o.AVAILABILITY_SLOTS="get_available_slots",o.MOBILE_VERIFICATION="verify_mobile_number",o.DOCTOR_DETAILS="get_doctor_details",o))(fe||{}),Te=(n=>(n.PROGRESS="progress",n.SUCCESS="success",n.FAILURE="failure",n))(Te||{});var Ce={NETWORK_ERROR:"NETWORK_ERROR",TIMEOUT_ERROR:"TIMEOUT_ERROR",API_ERROR:"API_ERROR",RATE_LIMIT_ERROR:"RATE_LIMIT_ERROR",SERVER_ERROR:"SERVER_ERROR",PARSE_ERROR:"PARSE_ERROR",UNKNOWN_ERROR:"UNKNOWN_ERROR"};var ye=(s=>(s.TEXT="text",s.FILE="file",s.AUDIO="audio",s.VOICE="voice",s))(ye||{});
2
- export{w as APIConnectionTimeoutError,c as APIError,$ as APIUserAbortError,W as BadRequestError,M as BaseConnection,U as ConnectionFactory,R as ConnectionStatus,E as ConnectionType,O as DisconnectionReason,Ce as ErrorType,D as ErrorUtils,V as HttpClient,X as InternalServerError,q as MessageManager,z as MethodNotAllowedError,N as NotFoundError,A as PermissionDeniedError,j as RateLimitError,K as ResourceManager,F as SSEConnection,Se as SYNAPSE_COMPONENTS,ye as SYNAPSE_CONVERSATION,Te as SYNAPSE_EICITATION_STATUS,pe as SYNAPSE_MESSAGE_TYPES,re as SYNAPSE_REALTIME_ERROR_CODES,f as SYNAPSE_REALTIME_EVENTS,B as SYNAPSE_REALTIME_RESERVED_EVENTS,fe as SYNAPSE_TOOL_CALLBACK_NAME,me as SYNAPSE_TOOL_NAME,G as Session,u as SynapseError,b as SynapseErrorCode,se as SynapseSDK,oe as ToolCall,Ut as USER_FEEDBACK,x as UnauthorizedError,ne as VOICE_AGENT_EVENTS,d as VOICE_AGENT_STATE,L as WebSocketConnection};