@moveo-ai/web-client 0.105.0-true.2 → 0.105.0-true.4
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/147.min.js.LICENSE.txt +1 -1
- package/dist/329.min.js.LICENSE.txt +1 -1
- package/dist/882.min.js +2 -0
- package/dist/882.min.js.LICENSE.txt +6 -0
- package/dist/882.min.js.map +1 -0
- package/dist/929.min.js +2 -0
- package/dist/929.min.js.LICENSE.txt +6 -0
- package/dist/929.min.js.map +1 -0
- package/dist/954.min.js +2 -0
- package/dist/954.min.js.LICENSE.txt +6 -0
- package/dist/954.min.js.map +1 -0
- package/dist/audio-client.min.js +1 -1
- package/dist/audio-client.min.js.LICENSE.txt +1 -1
- package/dist/audio-client.min.js.map +1 -1
- package/dist/iframe.min.js +1 -1
- package/dist/iframe.min.js.LICENSE.txt +1 -1
- package/dist/iframe.min.js.map +1 -1
- package/dist/iframe.v2.min.js +1 -1
- package/dist/iframe.v2.min.js.LICENSE.txt +1 -1
- package/dist/iframe.v2.min.js.map +1 -1
- package/dist/index.html +1 -1
- package/dist/preview/index.html +2 -2
- package/dist/preview.css.min.js.LICENSE.txt +1 -1
- package/dist/public/locales/en.json +7 -1
- package/dist/telnyx-client.min.js +1 -1
- package/dist/telnyx-client.min.js.LICENSE.txt +1 -1
- package/dist/telnyx-client.min.js.map +1 -1
- package/dist/web-client.min.js +1 -1
- package/dist/web-client.min.js.LICENSE.txt +1 -1
- package/dist/web-client.min.js.map +1 -1
- package/dist/webrtc-client.min.js +1 -1
- package/dist/webrtc-client.min.js.LICENSE.txt +1 -1
- package/dist/webrtc-client.min.js.map +1 -1
- package/package.json +1 -1
package/dist/882.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 882.min.js.LICENSE.txt */
|
|
2
|
+
"use strict";(this.webpackChunkMoveoAI=this.webpackChunkMoveoAI||[]).push([[882],{2229:function(e,t,i){i.d(t,{h:function(){return n}});class n{constructor(){this.analyserNode=null,this.audioSource=null,this.animationId=null,this.audioContext=null}start(e,t){try{this.audioContext=new AudioContext,this.audioSource=this.audioContext.createMediaStreamSource(e),this.analyserNode=this.audioContext.createAnalyser(),this.analyserNode.fftSize=256,this.analyserNode.smoothingTimeConstant=.3,this.audioSource.connect(this.analyserNode);const i=new Float32Array(this.analyserNode.fftSize),n=()=>{if(!this.analyserNode)return void this.stop();this.analyserNode.getFloatTimeDomainData(i);let e=0;for(const t of i)e+=t*t;const s=Math.sqrt(e/i.length),o=Math.min(1,10*s);t((o>.01?o:0).toFixed(3)),this.animationId=requestAnimationFrame(n)};n()}catch(e){}}stop(){if(null!==this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.audioSource){try{this.audioSource.disconnect()}catch(e){}this.audioSource=null}this.audioContext&&(this.audioContext.close().catch(()=>{}),this.audioContext=null),this.analyserNode=null}}},6815:function(e,t,i){i.d(t,{n:function(){return n}});const n={NotAllowedError:"Microphone permission denied",NotFoundError:"No microphone found",NotReadableError:"Microphone is in use by another application",OverconstrainedError:"Microphone does not support required settings"}},3564:function(e,t,i){i.d(t,{M:function(){return s}});const n={"high-rtt":"High network latency detected","low-mos":"Poor call quality detected","high-jitter":"Network instability detected","high-packet-loss":"Packet loss detected"};class s{constructor(e,t,i,n=5e3){this.pc=e,this.onWarning=t,this.onWarningCleared=i,this.pollIntervalMs=n,this.interval=null,this.prevStats=null,this.activeWarnings=new Set}start(){this.interval=setInterval(()=>{this.pollStats()},this.pollIntervalMs)}stop(){null!==this.interval&&(clearInterval(this.interval),this.interval=null),this.prevStats=null,this.activeWarnings.clear()}async pollStats(){try{const e=await this.pc.getStats();let t=null,i=null,n=0,s=0;e.forEach(e=>{var o,r,c;if("candidate-pair"===e.type&&e.nominated){const i=e.currentRoundTripTime;t=null!=i?1e3*i:null}if("inbound-rtp"===e.type&&"audio"===e.kind){const t=e;i=null!==(o=t.jitter)&&void 0!==o?o:null,n=null!==(r=t.packetsReceived)&&void 0!==r?r:0,s=null!==(c=t.packetsLost)&&void 0!==c?c:0}});let o=0;if(this.prevStats){const e=n-this.prevStats.packetsReceived,t=s-this.prevStats.packetsLost,i=e+t;o=i>0?t/i:0}if(this.prevStats={packetsReceived:n,packetsLost:s},this.checkWarning("high-rtt",null!==t&&t>400),this.checkWarning("high-jitter",null!==i&&i>.03),this.checkWarning("high-packet-loss",o>.03),null!==t&&null!==i){const e=93.2-1e3*i*2-100*o*40-.1*Math.max(0,t-150),n=1+.035*e+e*(e-60)*(100-e)*7e-6;this.checkWarning("low-mos",n<3)}}catch(e){}}checkWarning(e,t){t&&!this.activeWarnings.has(e)?(this.activeWarnings.add(e),this.onWarning(e,n[e]||e)):!t&&this.activeWarnings.has(e)&&(this.activeWarnings.delete(e),this.onWarningCleared(e))}}},6845:function(e,t,i){i.d(t,{P:function(){return n},X:function(){return s}});class n extends Error{constructor(e="Voice service is busy, please try again."){super(e),this.name="ServerBusyError"}}class s extends Error{constructor(e){super(e),this.name="ConfigUnavailableError"}}},4623:function(e,t,i){i.d(t,{g:function(){return n}});class n{constructor(e,t,i,n,s){this.url=e,this.sessionToken=t,this.onMessage=i,this.onClose=n,this.onError=s,this.ws=null}connect(){return new Promise((e,t)=>{const i=`${this.url}?token=${encodeURIComponent(this.sessionToken)}`;this.ws=new WebSocket(i);const n=setTimeout(()=>{var e;null===(e=this.ws)||void 0===e||e.close(),t(new Error("Signaling connection timed out"))},1e4);this.ws.onopen=()=>{},this.ws.onmessage=t=>{let i;try{i=JSON.parse(t.data)}catch(e){return}"welcome"===i.type&&(clearTimeout(n),e()),this.onMessage(i)},this.ws.onerror=e=>{clearTimeout(n),this.onError(e),t(new Error("Signaling WebSocket error"))},this.ws.onclose=e=>{clearTimeout(n),t(new Error("Signaling WebSocket closed before connection established")),this.onClose(e.code,e.reason)}})}connectForReconnect(e){return new Promise((t,i)=>{const n=`${this.url}?token=${encodeURIComponent(this.sessionToken)}`;this.ws=new WebSocket(n);let s=!1;const o=setTimeout(()=>{var e;s||(s=!0,null===(e=this.ws)||void 0===e||e.close(),i(new Error("Signaling reconnect timed out")))},1e4);this.ws.onopen=()=>{var t;null===(t=this.ws)||void 0===t||t.send(JSON.stringify(e))},this.ws.onmessage=e=>{let n;try{n=JSON.parse(e.data)}catch(e){return}this.onMessage(n),s||("reconnect_ack"===n.type?(s=!0,clearTimeout(o),t()):"error"===n.type&&(s=!0,clearTimeout(o),i(new Error(`reconnect rejected: ${n.error.code}`))))},this.ws.onerror=e=>{this.onError(e),s||(s=!0,clearTimeout(o),i(new Error("Signaling WebSocket error")))},this.ws.onclose=e=>{s||(s=!0,clearTimeout(o),i(new Error("Signaling WebSocket closed before reconnect established"))),this.onClose(e.code,e.reason)}})}send(e){this.ws&&this.ws.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e))}close(){this.ws&&(this.ws.onclose=null,this.ws.onerror=null,this.ws.onmessage=null,this.ws.close(1e3,"Client closed"),this.ws=null)}get isConnected(){var e;return(null===(e=this.ws)||void 0===e?void 0:e.readyState)===WebSocket.OPEN}}},5882:function(e,t,i){i.r(t),i.d(t,{WebRTCProvider:function(){return d}}),i(4954);var n=i(2229),s=i(6815),o=i(3564),r=i(6845),c=i(4623);const a=new Set(["session_expired","session_inactive","invalid_credential","max_recovery_exceeded","unexpected_first_frame"]),l={session_expired:"Your session has expired.",session_inactive:"The call has ended.",invalid_credential:"Could not resume the call.",max_recovery_exceeded:"Could not resume the call after several attempts.",unexpected_first_frame:"Could not resume the call."},h=Object.assign(Object.assign({},s.n),{setRemoteDescription:"Connection setup failed",setLocalDescription:"Connection setup failed",addIceCandidate:"Network configuration failed",createOffer:"Browser audio setup failed"});class d{constructor(e,t,i){this.config=e,this.wsUrl=t,this.fetchConfig=i,this.pc=null,this.signaling=null,this.localStream=null,this.remoteAudio=null,this.remoteAudioMonitor=null,this.audioMonitor=null,this.qualityMonitor=null,this.pendingCandidates=[],this.state="idle",this.eventListeners=new Map,this.disconnectTimeout=null,this.connectResolve=null,this.connectReject=null,this.drainReceived=!1,this.reconnectAttempts=0,this.reconnectErrorCode=null}async connect(){this.setState("connecting");try{this.localStream=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0}})}catch(e){const t=e instanceof Error?e.name:"",i=h[t]||"Microphone access failed";throw this.emitError(i),new Error(i)}this.signaling=new c.g(this.wsUrl,this.config.sessionToken,this.handleSignalingMessage.bind(this),this.handleSignalingClose.bind(this),this.handleSignalingError.bind(this));try{await this.signaling.connect()}catch(e){this.cleanupLocalStream();const t=e instanceof Error?e.message:"Signaling connection failed";throw this.emitError(t),new Error(t)}this.pc=new RTCPeerConnection({iceServers:this.config.iceServers,iceTransportPolicy:this.config.iceTransportPolicy||"relay"});const e=this.localStream.getAudioTracks()[0];this.pc.addTrack(e,this.localStream),this.pc.ontrack=this.handleRemoteTrack.bind(this),this.pc.onicecandidate=e=>{var t;e.candidate&&(null===(t=this.signaling)||void 0===t||t.send({type:"ice",candidate:e.candidate.toJSON()}))},this.pc.onconnectionstatechange=this.handleConnectionStateChange.bind(this);try{const e=await this.pc.createOffer();if(!e.sdp)throw new Error("createOffer returned no SDP");await this.pc.setLocalDescription(e),this.signaling.send({type:"offer",sdp:e.sdp})}catch(e){this.cleanup();const t=e instanceof Error?e.name:"createOffer",i=h[t]||"Failed to create call offer";throw this.emitError(i),new Error(i)}return this.audioMonitor=new n.h,this.audioMonitor.start(this.localStream,e=>{this.emit("audio-level",e,Number(e))}),new Promise((e,t)=>{this.connectResolve=e,this.connectReject=t})}disconnect(){this.disconnectInternal(!1)}disconnectInternal(e){var t,i,n,s,o,r;if(!e)try{null===(t=this.signaling)||void 0===t||t.send({type:"hangup"})}catch(e){}try{null===(i=this.qualityMonitor)||void 0===i||i.stop(),this.qualityMonitor=null}catch(e){}try{null===(n=this.audioMonitor)||void 0===n||n.stop(),this.audioMonitor=null}catch(e){}try{null===(s=this.remoteAudioMonitor)||void 0===s||s.stop(),this.remoteAudioMonitor=null}catch(e){}try{null===(o=this.pc)||void 0===o||o.close(),this.pc=null}catch(e){}this.cleanupLocalStream();try{null===(r=this.signaling)||void 0===r||r.close(),this.signaling=null}catch(e){}try{this.remoteAudio&&(this.remoteAudio.srcObject=null,this.remoteAudio.remove(),this.remoteAudio=null)}catch(e){}this.disconnectTimeout&&(clearTimeout(this.disconnectTimeout),this.disconnectTimeout=null),this.connectReject&&this.connectReject(new Error("Call disconnected before connection completed")),this.connectResolve=null,this.connectReject=null,this.drainReceived=!1,this.reconnectAttempts=0,this.reconnectErrorCode=null,this.originalSessionID=void 0,this.originalConnectionID=void 0,this.pendingCandidates=[],this.setState("idle")}toggleMute(){var e,t;const i=null===(e=this.localStream)||void 0===e?void 0:e.getAudioTracks()[0];if(i){i.enabled=!i.enabled;const e=!i.enabled;return null===(t=this.signaling)||void 0===t||t.send({type:"mute",muted:e}),e}return!1}isMuted(){var e,t,i;return!(null===(i=null===(t=null===(e=this.localStream)||void 0===e?void 0:e.getAudioTracks()[0])||void 0===t?void 0:t.enabled)||void 0===i||i)}getLocalStream(){return this.localStream}sendDigits(e){var t;for(const i of e)null===(t=this.signaling)||void 0===t||t.send({type:"dtmf",digit:i})}on(e,t){var i;const n=null!==(i=this.eventListeners.get(e))&&void 0!==i?i:new Set;return n.add(t),this.eventListeners.set(e,n),()=>this.off(e,t)}off(e,t){const i=this.eventListeners.get(e);i&&(i.delete(t),0===i.size&&this.eventListeners.delete(e))}handleRemoteTrack(e){this.remoteAudio=document.createElement("audio"),this.remoteAudio.srcObject=e.streams[0],this.remoteAudio.autoplay=!0,document.body.appendChild(this.remoteAudio),this.remoteAudioMonitor=new n.h,this.remoteAudioMonitor.start(e.streams[0],e=>{Number(e)>.02&&this.emit("remote-audio",e,Number(e))})}handleConnectionStateChange(){var e,t,i;if(this.pc)switch(this.pc.connectionState){case"connecting":this.setState("connecting");break;case"connected":this.setState("connected"),this.qualityMonitor=new o.M(this.pc,(e,t)=>this.emit("warning",t,e),e=>this.emit("warning-cleared",void 0,e)),this.qualityMonitor.start(),null===(e=this.connectResolve)||void 0===e||e.call(this),this.connectResolve=null,this.connectReject=null;break;case"disconnected":if(this.drainReceived)break;this.setState("reconnecting"),this.disconnectTimeout=setTimeout(()=>{this.emitError("Connection lost"),this.cleanup()},3e4);break;case"failed":if(this.drainReceived){null===(t=this.connectReject)||void 0===t||t.call(this,new Error("ICE connection failed")),this.connectResolve=null,this.connectReject=null;break}null===(i=this.connectReject)||void 0===i||i.call(this,new Error("ICE connection failed")),this.connectResolve=null,this.connectReject=null,this.emitError("Connection failed"),this.cleanup();break;case"closed":this.cleanup()}}handleSignalingMessage(e){var t;switch(e.type){case"answer":this.handleAnswer(e.sdp);break;case"ice":this.addIceCandidate(e.candidate);break;case"transcript":this.emit("transcript",e.text,{text:e.text,is_final:e.is_final});break;case"agent_response":this.emit("agent-response",e.text,{text:e.text,message_id:e.message_id});break;case"hangup":this.disconnectInternal(!0);break;case"session_ready":this.originalSessionID=e.session_id,this.originalConnectionID=e.connection_id;break;case"reconnect_ack":this.originalConnectionID=e.connection_id;break;case"drain":this.handleDrain(e);break;case"error":this.drainReceived?(this.reconnectErrorCode=e.error.code,null===(t=this.connectReject)||void 0===t||t.call(this,new Error(`reconnect rejected: ${e.error.code}`))):this.emitError(e.error.message)}}handleSignalingClose(e,t){var i;this.drainReceived?null===(i=this.connectReject)||void 0===i||i.call(this,new Error("Signaling closed during resume")):"idle"!==this.state&&this.disconnect()}handleSignalingError(e){"connected"===this.state&&this.emitError("Signaling error")}async handleDrain(e){if(this.drainReceived)return;if("connected"!==this.state||void 0===this.originalSessionID||void 0===this.originalConnectionID)return this.emitError("Could not resume the call."),void this.disconnectInternal(!0);this.drainReceived=!0,this.setState("reconnecting");const t=Math.max(0,e.reconnect_delay_ms||0);await this.sleep(Math.random()*t),this.drainReceived&&await this.reconnect()}async reconnect(){var e,t,i;try{null===(e=this.pc)||void 0===e||e.getSenders().forEach(e=>{var t;e.track&&(null===(t=this.pc)||void 0===t||t.removeTrack(e))})}catch(e){}const n=null===(t=this.localStream)||void 0===t?void 0:t.getAudioTracks()[0];if(!n||"live"!==n.readyState)return this.emitError("Microphone is no longer available."),void this.disconnectInternal(!0);for(this.teardownForReconnect();this.reconnectAttempts<3;){this.reconnectErrorCode=null;try{return this.config=await this.fetchConfig(),this.signaling=new c.g(this.wsUrl,this.config.sessionToken,this.handleSignalingMessage.bind(this),this.handleSignalingClose.bind(this),this.handleSignalingError.bind(this)),await this.signaling.connectForReconnect({type:"reconnect",session_id:this.originalSessionID,connection_id:this.originalConnectionID}),await this.buildReconnectPeerConnection(n),this.reconnectAttempts=0,this.drainReceived=!1,void this.emit("warning-cleared",void 0,"reconnect")}catch(e){const t=this.reconnectErrorCode;if(t&&a.has(t))return this.emitError(null!==(i=l[t])&&void 0!==i?i:"Could not resume the call."),void this.disconnectInternal(!0);if(e instanceof r.X)return this.emitError(e.message),void this.disconnectInternal(!0);const n=e instanceof r.P?e.message:"Reconnecting…";if(this.emit("warning",n,"reconnect"),this.teardownForReconnect(),this.reconnectAttempts++,this.reconnectAttempts>=3)break;if(await this.sleep(500*this.reconnectAttempts),!this.drainReceived)return}}this.emitError("Could not resume the call."),this.disconnectInternal(!0)}buildReconnectPeerConnection(e){return this.pc=new RTCPeerConnection({iceServers:this.config.iceServers,iceTransportPolicy:this.config.iceTransportPolicy||"relay"}),this.pc.addTrack(e,this.localStream),this.pc.ontrack=this.handleRemoteTrack.bind(this),this.pc.onicecandidate=e=>{var t;e.candidate&&(null===(t=this.signaling)||void 0===t||t.send({type:"ice",candidate:e.candidate.toJSON()}))},this.pc.onconnectionstatechange=this.handleConnectionStateChange.bind(this),this.audioMonitor=new n.h,this.audioMonitor.start(this.localStream,e=>{this.emit("audio-level",e,Number(e))}),new Promise((e,t)=>{const i=setTimeout(()=>{this.connectResolve=null,this.connectReject=null,t(new Error("Reconnect media resume timed out"))},15e3);this.connectResolve=()=>{clearTimeout(i),e()},this.connectReject=e=>{clearTimeout(i),t(e)},(async()=>{var e;try{const e=await this.pc.createOffer();if(!e.sdp)throw new Error("createOffer returned no SDP");await this.pc.setLocalDescription(e),this.signaling.send({type:"offer",sdp:e.sdp})}catch(t){const i=t instanceof Error?t.name:"createOffer";null===(e=this.connectReject)||void 0===e||e.call(this,new Error(h[i]||"Failed to create call offer"))}})()})}teardownForReconnect(){var e,t,i,n,s;try{null===(e=this.qualityMonitor)||void 0===e||e.stop(),this.qualityMonitor=null}catch(e){}try{null===(t=this.audioMonitor)||void 0===t||t.stop(),this.audioMonitor=null}catch(e){}try{null===(i=this.remoteAudioMonitor)||void 0===i||i.stop(),this.remoteAudioMonitor=null}catch(e){}try{null===(n=this.pc)||void 0===n||n.close(),this.pc=null}catch(e){}try{null===(s=this.signaling)||void 0===s||s.close(),this.signaling=null}catch(e){}try{this.remoteAudio&&(this.remoteAudio.srcObject=null,this.remoteAudio.remove(),this.remoteAudio=null)}catch(e){}this.disconnectTimeout&&(clearTimeout(this.disconnectTimeout),this.disconnectTimeout=null),this.connectResolve=null,this.connectReject=null,this.pendingCandidates=[]}sleep(e){return new Promise(t=>setTimeout(t,e))}async handleAnswer(e){if(this.pc)try{await this.pc.setRemoteDescription({type:"answer",sdp:e}),await this.flushPendingCandidates()}catch(e){this.emitError(h.setRemoteDescription)}}async addIceCandidate(e){var t;if(null===(t=this.pc)||void 0===t?void 0:t.remoteDescription)try{await this.pc.addIceCandidate(e)}catch(e){}else this.pendingCandidates.push(e)}async flushPendingCandidates(){for(const e of this.pendingCandidates){if(!this.pc)break;try{await this.pc.addIceCandidate(e)}catch(e){}}this.pendingCandidates=[]}cleanup(){this.disconnect()}cleanupLocalStream(){var e;try{null===(e=this.localStream)||void 0===e||e.getTracks().forEach(e=>e.stop()),this.localStream=null}catch(e){}}setState(e){this.state=e,this.emit("state-change",e,e)}emitError(e){this.emit("error",e),this.setState("error")}emit(e,t,i){const n={state:e,message:t,data:i},s=e=>{const t=this.eventListeners.get(e);t&&t.forEach(e=>{try{e(n)}catch(e){}})};s(e),s("any")}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"882.min.js","mappings":";uIAUO,MAAMA,EACT,WAAAC,GACIC,KAAKC,aAAe,KACpBD,KAAKE,YAAc,KACnBF,KAAKG,YAAc,KACnBH,KAAKI,aAAe,IACxB,CACA,KAAAC,CAAMC,EAAQC,GACV,IACIP,KAAKI,aAAe,IAAII,aACxBR,KAAKE,YAAcF,KAAKI,aAAaK,wBAAwBH,GAC7DN,KAAKC,aAAeD,KAAKI,aAAaM,iBACtCV,KAAKC,aAAaU,QAAU,IAC5BX,KAAKC,aAAaW,sBAAwB,GAC1CZ,KAAKE,YAAYW,QAAQb,KAAKC,cAC9B,MAAMa,EAAY,IAAIC,aAAaf,KAAKC,aAAaU,SAC/CK,EAAkB,KACpB,IAAKhB,KAAKC,aAEN,YADAD,KAAKiB,OAGTjB,KAAKC,aAAaiB,uBAAuBJ,GACzC,IAAIK,EAAM,EACV,IAAK,MAAMC,KAAaN,EACpBK,GAAOC,EAAYA,EAEvB,MAAMC,EAAMC,KAAKC,KAAKJ,EAAML,EAAUU,QAChCC,EAAkBH,KAAKI,IAAI,EAAS,GAANL,GAEpCd,GADmBkB,EAtCN,IAsC+CA,EAAkB,GAC3DE,QAAQ,IAC3B3B,KAAKG,YAAcyB,sBAAsBZ,IAE7CA,GACJ,CACA,MAAOa,GAEP,CACJ,CACA,IAAAZ,GAKI,GAJyB,OAArBjB,KAAKG,cACL2B,qBAAqB9B,KAAKG,aAC1BH,KAAKG,YAAc,MAEnBH,KAAKE,YAAa,CAClB,IACIF,KAAKE,YAAY6B,YACrB,CACA,MAAOF,GAEP,CACA7B,KAAKE,YAAc,IACvB,CACIF,KAAKI,eACAJ,KAAKI,aAAa4B,QAAQC,MAAM,QAGrCjC,KAAKI,aAAe,MAExBJ,KAAKC,aAAe,IACxB,E,uDChEG,MAAMiC,EAAe,CACxBC,gBAAiB,+BACjBC,cAAe,sBACfC,iBAAkB,8CAClBC,qBAAsB,gD,uDCT1B,MAAMC,EAAmB,CACrB,WAAY,gCACZ,UAAW,6BACX,cAAe,+BACf,mBAAoB,wBAYjB,MAAMC,EACT,WAAAzC,CAAY0C,EAAIC,EAAWC,EAAkBC,EAAiB,KAC1D5C,KAAKyC,GAAKA,EACVzC,KAAK0C,UAAYA,EACjB1C,KAAK2C,iBAAmBA,EACxB3C,KAAK4C,eAAiBA,EACtB5C,KAAK6C,SAAW,KAChB7C,KAAK8C,UAAY,KACjB9C,KAAK+C,eAAiB,IAAIC,GAC9B,CACA,KAAA3C,GACIL,KAAK6C,SAAWI,YAAY,KACnBjD,KAAKkD,aACXlD,KAAK4C,eACZ,CACA,IAAA3B,GAC0B,OAAlBjB,KAAK6C,WACLM,cAAcnD,KAAK6C,UACnB7C,KAAK6C,SAAW,MAEpB7C,KAAK8C,UAAY,KACjB9C,KAAK+C,eAAeK,OACxB,CACA,eAAMF,GACF,IACI,MAAMG,QAAcrD,KAAKyC,GAAGa,WAC5B,IAAIC,EAAM,KACNC,EAAS,KACTC,EAAkB,EAClBC,EAAc,EAClBL,EAAMM,QAASC,IACX,IAAI/B,EAAIgC,EAAIC,EACZ,GAAoB,mBAAhBF,EAAOG,MAA6BH,EAAOI,UAAW,CACtD,MAAMC,EAAML,EACPM,qBACLX,EAAa,MAAPU,EAAoB,IAANA,EAAa,IACrC,CACA,GAAoB,gBAAhBL,EAAOG,MAA0C,UAAhBH,EAAOO,KAAkB,CAC1D,MAAMC,EAAMR,EACZJ,EAA+B,QAArB3B,EAAKuC,EAAIZ,cAAgC,IAAZ3B,EAAgBA,EAAK,KAC5D4B,EAAiD,QAA9BI,EAAKO,EAAIX,uBAAyC,IAAZI,EAAgBA,EAAK,EAC9EH,EAAyC,QAA1BI,EAAKM,EAAIV,mBAAqC,IAAZI,EAAgBA,EAAK,CAC1E,IAGJ,IAAIO,EAAW,EACf,GAAIrE,KAAK8C,UAAW,CAChB,MAAMwB,EAAgBb,EAAkBzD,KAAK8C,UAAUW,gBACjDc,EAAYb,EAAc1D,KAAK8C,UAAUY,YACzCc,EAAQF,EAAgBC,EAC9BF,EAAWG,EAAQ,EAAID,EAAYC,EAAQ,CAC/C,CAOA,GANAxE,KAAK8C,UAAY,CAAEW,kBAAiBC,eAEpC1D,KAAKyE,aAAa,WAAoB,OAARlB,GAAgBA,EA/DjD,KAgEGvD,KAAKyE,aAAa,cAA0B,OAAXjB,GAAmBA,EA/DpD,KAgEAxD,KAAKyE,aAAa,mBAAoBJ,EA/DjC,KAiEO,OAARd,GAA2B,OAAXC,EAAiB,CACjC,MAEMkB,EAAI,KAFgB,IAATlB,EAEW,EADG,IAAXa,EAC0B,GAA8B,GAAzB/C,KAAKqD,IAAI,EAAGpB,EAAM,KAC/DqB,EAAM,EAAI,KAAQF,EAAIA,GAAKA,EAAI,KAAO,IAAMA,GAAK,KACvD1E,KAAKyE,aAAa,UAAWG,EArEpC,EAsEG,CACJ,CACA,MAAO/C,GAEP,CACJ,CACA,YAAA4C,CAAaI,EAAMC,GACXA,IAAe9E,KAAK+C,eAAegC,IAAIF,IACvC7E,KAAK+C,eAAeiC,IAAIH,GACxB7E,KAAK0C,UAAUmC,EAAMtC,EAAiBsC,IAASA,KAEzCC,GAAc9E,KAAK+C,eAAegC,IAAIF,KAC5C7E,KAAK+C,eAAekC,OAAOJ,GAC3B7E,KAAK2C,iBAAiBkC,GAE9B,E,8ECtFG,MAAMK,UAAwBC,MACjC,WAAApF,CAAYqF,EAAU,4CAClBC,MAAMD,GACNpF,KAAK6E,KAAO,iBAChB,EAMG,MAAMS,UAA+BH,MACxC,WAAApF,CAAYqF,GACRC,MAAMD,GACNpF,KAAK6E,KAAO,wBAChB,E,uDClBG,MAAMU,EACT,WAAAxF,CAAYyF,EAAKC,EAAcC,EAAWC,EAASC,GAC/C5F,KAAKwF,IAAMA,EACXxF,KAAKyF,aAAeA,EACpBzF,KAAK0F,UAAYA,EACjB1F,KAAK2F,QAAUA,EACf3F,KAAK4F,QAAUA,EACf5F,KAAK6F,GAAK,IACd,CACA,OAAAhF,GACI,OAAO,IAAIiF,QAAQ,CAACC,EAASC,KACzB,MAAMC,EAAQ,GAAGjG,KAAKwF,aAAaU,mBAAmBlG,KAAKyF,gBAC3DzF,KAAK6F,GAAK,IAAIM,UAAUF,GACxB,MAAMG,EAAUC,WAAW,KACvB,IAAIxE,EACe,QAAlBA,EAAK7B,KAAK6F,UAA4B,IAAZhE,GAAyBA,EAAGG,QACvDgE,EAAO,IAAIb,MAAM,oCArBN,KAuBfnF,KAAK6F,GAAGS,OAAS,OAGjBtG,KAAK6F,GAAGU,UAAaC,IACjB,IAAIC,EACJ,IACIA,EAAMC,KAAKC,MAAMH,EAAMI,KAC3B,CACA,MAAO/E,GAEH,MACJ,CACiB,YAAb4E,EAAI1C,OACJ8C,aAAaT,GACbL,KAEJ/F,KAAK0F,UAAUe,IAEnBzG,KAAK6F,GAAGiB,QAAWN,IACfK,aAAaT,GACbpG,KAAK4F,QAAQY,GACbR,EAAO,IAAIb,MAAM,+BAErBnF,KAAK6F,GAAGkB,QAAWP,IACfK,aAAaT,GACbJ,EAAO,IAAIb,MAAM,6DACjBnF,KAAK2F,QAAQa,EAAMQ,KAAMR,EAAMS,UAG3C,CAOA,mBAAAC,CAAoBC,GAChB,OAAO,IAAIrB,QAAQ,CAACC,EAASC,KACzB,MAAMC,EAAQ,GAAGjG,KAAKwF,aAAaU,mBAAmBlG,KAAKyF,gBAC3DzF,KAAK6F,GAAK,IAAIM,UAAUF,GACxB,IAAImB,GAAU,EACd,MAAMhB,EAAUC,WAAW,KACvB,IAAIxE,EACAuF,IAEJA,GAAU,EACS,QAAlBvF,EAAK7B,KAAK6F,UAA4B,IAAZhE,GAAyBA,EAAGG,QACvDgE,EAAO,IAAIb,MAAM,oCAtEN,KAwEfnF,KAAK6F,GAAGS,OAAS,KACb,IAAIzE,EAEe,QAAlBA,EAAK7B,KAAK6F,UAA4B,IAAZhE,GAAyBA,EAAGwF,KAAKX,KAAKY,UAAUH,KAE/EnH,KAAK6F,GAAGU,UAAaC,IACjB,IAAIC,EACJ,IACIA,EAAMC,KAAKC,MAAMH,EAAMI,KAC3B,CACA,MAAO/E,GAEH,MACJ,CAGA7B,KAAK0F,UAAUe,GACXW,IAEa,kBAAbX,EAAI1C,MACJqD,GAAU,EACVP,aAAaT,GACbL,KAEkB,UAAbU,EAAI1C,OAITqD,GAAU,EACVP,aAAaT,GACbJ,EAAO,IAAIb,MAAM,uBAAuBsB,EAAIc,MAAMP,YAG1DhH,KAAK6F,GAAGiB,QAAWN,IACfxG,KAAK4F,QAAQY,GACTY,IAEJA,GAAU,EACVP,aAAaT,GACbJ,EAAO,IAAIb,MAAM,gCAErBnF,KAAK6F,GAAGkB,QAAWP,IACVY,IACDA,GAAU,EACVP,aAAaT,GACbJ,EAAO,IAAIb,MAAM,6DAErBnF,KAAK2F,QAAQa,EAAMQ,KAAMR,EAAMS,UAG3C,CACA,IAAAI,CAAKZ,GACIzG,KAAK6F,IAAM7F,KAAK6F,GAAG2B,aAAerB,UAAUsB,MAGjDzH,KAAK6F,GAAGwB,KAAKX,KAAKY,UAAUb,GAChC,CACA,KAAAzE,GACQhC,KAAK6F,KACL7F,KAAK6F,GAAGkB,QAAU,KAClB/G,KAAK6F,GAAGiB,QAAU,KAClB9G,KAAK6F,GAAGU,UAAY,KACpBvG,KAAK6F,GAAG7D,MAAM,IAAM,iBACpBhC,KAAK6F,GAAK,KAElB,CACA,eAAI6B,GACA,IAAI7F,EACJ,OAA2B,QAAlBA,EAAK7B,KAAK6F,UAA4B,IAAZhE,OAAqB,EAAIA,EAAG2F,cAAgBrB,UAAUsB,IAC7F,E,yICvIJ,MAUME,EAA2B,IAAI3E,IAAI,CACrC,kBACA,mBACA,qBACA,wBACA,2BAGE4E,EAA2B,CAC7BC,gBAAiB,4BACjBC,iBAAkB,sBAClBC,mBAAoB,6BACpBC,sBAAuB,oDACvBC,uBAAwB,8BAGtBC,EAAgBC,OAAOC,OAAOD,OAAOC,OAAO,CAAC,EAAG,KAAe,CAAEC,qBAAsB,0BAA2BC,oBAAqB,0BAA2BC,gBAAiB,+BAAgCC,YAAa,+BAE/N,MAAMC,EACT,WAAA1I,CAAY2I,EAAQzC,EAGpB0C,GACI3I,KAAK0I,OAASA,EACd1I,KAAKiG,MAAQA,EACbjG,KAAK2I,YAAcA,EACnB3I,KAAKyC,GAAK,KACVzC,KAAK4I,UAAY,KACjB5I,KAAK6I,YAAc,KACnB7I,KAAK8I,YAAc,KACnB9I,KAAK+I,mBAAqB,KAC1B/I,KAAKgJ,aAAe,KACpBhJ,KAAKiJ,eAAiB,KACtBjJ,KAAKkJ,kBAAoB,GACzBlJ,KAAKmJ,MAAQ,OACbnJ,KAAKoJ,eAAiB,IAAIC,IAC1BrJ,KAAKsJ,kBAAoB,KACzBtJ,KAAKuJ,eAAiB,KACtBvJ,KAAKwJ,cAAgB,KAGrBxJ,KAAKyJ,eAAgB,EACrBzJ,KAAK0J,kBAAoB,EAEzB1J,KAAK2J,mBAAqB,IAC9B,CACA,aAAM9I,GACFb,KAAK4J,SAAS,cAEd,IACI5J,KAAK6I,kBAAoBgB,UAAUC,aAAaC,aAAa,CACzDC,MAAO,CACHC,kBAAkB,EAClBC,kBAAkB,EAClBC,iBAAiB,IAG7B,CACA,MAAO5C,GACH,MAAM1C,EAAO0C,aAAiBpC,MAAQoC,EAAM1C,KAAO,GAC7CO,EAAU8C,EAAcrD,IAAS,2BAEvC,MADA7E,KAAKoK,UAAUhF,GACT,IAAID,MAAMC,EACpB,CAEApF,KAAK4I,UAAY,IAAI,IAAgB5I,KAAKiG,MAAOjG,KAAK0I,OAAOjD,aAAczF,KAAKqK,uBAAuBC,KAAKtK,MAAOA,KAAKuK,qBAAqBD,KAAKtK,MAAOA,KAAKwK,qBAAqBF,KAAKtK,OACxL,UACUA,KAAK4I,UAAU/H,SACzB,CACA,MAAO0G,GACHvH,KAAKyK,qBACL,MAAMrF,EAAUmC,aAAiBpC,MAAQoC,EAAMnC,QAAU,8BAEzD,MADApF,KAAKoK,UAAUhF,GACT,IAAID,MAAMC,EACpB,CAEApF,KAAKyC,GAAK,IAAIiI,kBAAkB,CAC5BC,WAAY3K,KAAK0I,OAAOiC,WACxBC,mBAAoB5K,KAAK0I,OAAOkC,oBAAsB,UAG1D,MAAMC,EAAa7K,KAAK6I,YAAYiC,iBAAiB,GACrD9K,KAAKyC,GAAGsI,SAASF,EAAY7K,KAAK6I,aAElC7I,KAAKyC,GAAGuI,QAAUhL,KAAKiL,kBAAkBX,KAAKtK,MAC9CA,KAAKyC,GAAGyI,eAAkB1E,IACtB,IAAI3E,EACA2E,EAAM2E,YACoB,QAAzBtJ,EAAK7B,KAAK4I,iBAAmC,IAAZ/G,GAAyBA,EAAGwF,KAAK,CAC/DtD,KAAM,MACNoH,UAAW3E,EAAM2E,UAAUC,aAIvCpL,KAAKyC,GAAG4I,wBACJrL,KAAKsL,4BAA4BhB,KAAKtK,MAE1C,IACI,MAAMuL,QAAcvL,KAAKyC,GAAG+F,cAC5B,IAAK+C,EAAMC,IACP,MAAM,IAAIrG,MAAM,qCAEdnF,KAAKyC,GAAG6F,oBAAoBiD,GAClCvL,KAAK4I,UAAUvB,KAAK,CAAEtD,KAAM,QAASyH,IAAKD,EAAMC,KACpD,CACA,MAAOjE,GACHvH,KAAKyL,UACL,MAAM5G,EAAO0C,aAAiBpC,MAAQoC,EAAM1C,KAAO,cAC7CO,EAAU8C,EAAcrD,IAAS,8BAEvC,MADA7E,KAAKoK,UAAUhF,GACT,IAAID,MAAMC,EACpB,CAOA,OALApF,KAAKgJ,aAAe,IAAI,IACxBhJ,KAAKgJ,aAAa3I,MAAML,KAAK6I,YAAc6C,IACvC1L,KAAK2L,KAAK,cAAeD,EAAOE,OAAOF,MAGpC,IAAI5F,QAAQ,CAACC,EAASC,KACzBhG,KAAKuJ,eAAiBxD,EACtB/F,KAAKwJ,cAAgBxD,GAE7B,CACA,UAAAjE,GACI/B,KAAK6L,oBAAmB,EAC5B,CACA,kBAAAA,CAAmBC,GAEf,IAAIjK,EAAIgC,EAAIC,EAAIiI,EAAIC,EAAIC,EACxB,IAAKH,EACD,IAC8B,QAAzBjK,EAAK7B,KAAK4I,iBAAmC,IAAZ/G,GAAyBA,EAAGwF,KAAK,CAAEtD,KAAM,UAC/E,CACA,MAAOmI,GAEP,CAEJ,IACmC,QAA9BrI,EAAK7D,KAAKiJ,sBAAwC,IAAZpF,GAAyBA,EAAG5C,OACnEjB,KAAKiJ,eAAiB,IAC1B,CACA,MAAOkD,GAEP,CACA,IACiC,QAA5BrI,EAAK9D,KAAKgJ,oBAAsC,IAAZlF,GAAyBA,EAAG7C,OACjEjB,KAAKgJ,aAAe,IACxB,CACA,MAAOoD,GAEP,CACA,IACuC,QAAlCL,EAAK/L,KAAK+I,0BAA4C,IAAZgD,GAAyBA,EAAG9K,OACvEjB,KAAK+I,mBAAqB,IAC9B,CACA,MAAOsD,GAEP,CACA,IACuB,QAAlBL,EAAKhM,KAAKyC,UAA4B,IAAZuJ,GAAyBA,EAAGhK,QACvDhC,KAAKyC,GAAK,IACd,CACA,MAAO6J,GAEP,CACAtM,KAAKyK,qBACL,IAC8B,QAAzBwB,EAAKjM,KAAK4I,iBAAmC,IAAZqD,GAAyBA,EAAGjK,QAC9DhC,KAAK4I,UAAY,IACrB,CACA,MAAO2D,GAEP,CACA,IACQvM,KAAK8I,cACL9I,KAAK8I,YAAY0D,UAAY,KAC7BxM,KAAK8I,YAAY2D,SACjBzM,KAAK8I,YAAc,KAE3B,CACA,MAAO4D,GAEP,CACI1M,KAAKsJ,oBACLzC,aAAa7G,KAAKsJ,mBAClBtJ,KAAKsJ,kBAAoB,MAEzBtJ,KAAKwJ,eACLxJ,KAAKwJ,cAAc,IAAIrE,MAAM,kDAEjCnF,KAAKuJ,eAAiB,KACtBvJ,KAAKwJ,cAAgB,KAKrBxJ,KAAKyJ,eAAgB,EACrBzJ,KAAK0J,kBAAoB,EACzB1J,KAAK2J,mBAAqB,KAC1B3J,KAAK2M,uBAAoBC,EACzB5M,KAAK6M,0BAAuBD,EAC5B5M,KAAKkJ,kBAAoB,GACzBlJ,KAAK4J,SAAS,OAClB,CACA,UAAAkD,GACI,IAAIjL,EAAIgC,EACR,MAAMkJ,EAAoC,QAA3BlL,EAAK7B,KAAK6I,mBAAqC,IAAZhH,OAAqB,EAAIA,EAAGiJ,iBAAiB,GAC/F,GAAIiC,EAAO,CACPA,EAAMC,SAAWD,EAAMC,QACvB,MAAMC,GAASF,EAAMC,QAErB,OAD0B,QAAzBnJ,EAAK7D,KAAK4I,iBAAmC,IAAZ/E,GAAyBA,EAAGwD,KAAK,CAAEtD,KAAM,OAAQkJ,UAC5EA,CACX,CACA,OAAO,CACX,CACA,OAAAC,GACI,IAAIrL,EAAIgC,EAAIC,EACZ,QAA+J,QAArJA,EAAoG,QAA9FD,EAAiC,QAA3BhC,EAAK7B,KAAK6I,mBAAqC,IAAZhH,OAAqB,EAAIA,EAAGiJ,iBAAiB,UAA4B,IAAZjH,OAAqB,EAAIA,EAAGmJ,eAAiC,IAAZlJ,GAAgBA,EAC3L,CACA,cAAAqJ,GACI,OAAOnN,KAAK6I,WAChB,CACA,UAAAuE,CAAWC,GACP,IAAIxL,EAGJ,IAAK,MAAMyL,KAAMD,EACa,QAAzBxL,EAAK7B,KAAK4I,iBAAmC,IAAZ/G,GAAyBA,EAAGwF,KAAK,CAAEtD,KAAM,OAAQwJ,MAAOD,GAElG,CACA,EAAAE,CAAGhH,EAAOiH,GACN,IAAI5L,EACJ,MAAM6L,EAAsD,QAAzC7L,EAAK7B,KAAKoJ,eAAeuE,IAAInH,UAAgC,IAAZ3E,EAAgBA,EAAK,IAAImB,IAG7F,OAFA0K,EAAU1I,IAAIyI,GACdzN,KAAKoJ,eAAewE,IAAIpH,EAAOkH,GACxB,IAAM1N,KAAK6N,IAAIrH,EAAOiH,EACjC,CACA,GAAAI,CAAIrH,EAAOiH,GACP,MAAMC,EAAY1N,KAAKoJ,eAAeuE,IAAInH,GACrCkH,IAELA,EAAUzI,OAAOwI,GACM,IAAnBC,EAAUI,MACV9N,KAAKoJ,eAAenE,OAAOuB,GAEnC,CAEA,iBAAAyE,CAAkBzE,GACdxG,KAAK8I,YAAciF,SAASC,cAAc,SAC1ChO,KAAK8I,YAAY0D,UAAYhG,EAAMyH,QAAQ,GAC3CjO,KAAK8I,YAAYoF,UAAW,EAC5BH,SAASI,KAAKC,YAAYpO,KAAK8I,aAE/B9I,KAAK+I,mBAAqB,IAAI,IAC9B/I,KAAK+I,mBAAmB1I,MAAMmG,EAAMyH,QAAQ,GAAKvC,IACzCE,OAAOF,GAxQQ,KAyQf1L,KAAK2L,KAAK,eAAgBD,EAAOE,OAAOF,KAGpD,CACA,2BAAAJ,GACI,IAAIzJ,EAAIgC,EAAIC,EACZ,GAAK9D,KAAKyC,GAEV,OAAQzC,KAAKyC,GAAG4L,iBACZ,IAAK,aACDrO,KAAK4J,SAAS,cACd,MACJ,IAAK,YACD5J,KAAK4J,SAAS,aAEd5J,KAAKiJ,eAAiB,IAAI,IAAmBjJ,KAAKyC,GAAI,CAACoC,EAAMO,IAAYpF,KAAK2L,KAAK,UAAWvG,EAASP,GAAQA,GAAS7E,KAAK2L,KAAK,uBAAmBiB,EAAW/H,IAChK7E,KAAKiJ,eAAe5I,QAEW,QAA9BwB,EAAK7B,KAAKuJ,sBAAwC,IAAZ1H,GAAyBA,EAAGyM,KAAKtO,MACxEA,KAAKuJ,eAAiB,KACtBvJ,KAAKwJ,cAAgB,KACrB,MACJ,IAAK,eAGD,GAAIxJ,KAAKyJ,cACL,MAEJzJ,KAAK4J,SAAS,gBACd5J,KAAKsJ,kBAAoBjD,WAAW,KAChCrG,KAAKoK,UAAU,mBACfpK,KAAKyL,WAzSK,KA2Sd,MACJ,IAAK,SAGD,GAAIzL,KAAKyJ,cAAe,CACU,QAA7B5F,EAAK7D,KAAKwJ,qBAAuC,IAAZ3F,GAAyBA,EAAGyK,KAAKtO,KAAM,IAAImF,MAAM,0BACvFnF,KAAKuJ,eAAiB,KACtBvJ,KAAKwJ,cAAgB,KACrB,KACJ,CAC8B,QAA7B1F,EAAK9D,KAAKwJ,qBAAuC,IAAZ1F,GAAyBA,EAAGwK,KAAKtO,KAAM,IAAImF,MAAM,0BACvFnF,KAAKuJ,eAAiB,KACtBvJ,KAAKwJ,cAAgB,KACrBxJ,KAAKoK,UAAU,qBACfpK,KAAKyL,UACL,MACJ,IAAK,SACDzL,KAAKyL,UAGjB,CACA,sBAAApB,CAAuB5D,GACnB,IAAI5E,EACJ,OAAQ4E,EAAI1C,MACR,IAAK,SACI/D,KAAKuO,aAAa9H,EAAI+E,KAC3B,MACJ,IAAK,MACIxL,KAAKuI,gBAAgB9B,EAAI0E,WAC9B,MAIJ,IAAK,aACDnL,KAAK2L,KAAK,aAAclF,EAAI+H,KAAM,CAC9BA,KAAM/H,EAAI+H,KACVC,SAAUhI,EAAIgI,WAElB,MACJ,IAAK,iBACDzO,KAAK2L,KAAK,iBAAkBlF,EAAI+H,KAAM,CAClCA,KAAM/H,EAAI+H,KACVE,WAAYjI,EAAIiI,aAEpB,MACJ,IAAK,SACD1O,KAAK6L,oBAAmB,GACxB,MAGJ,IAAK,gBACD7L,KAAK2M,kBAAoBlG,EAAIkI,WAC7B3O,KAAK6M,qBAAuBpG,EAAImI,cAChC,MAEJ,IAAK,gBACD5O,KAAK6M,qBAAuBpG,EAAImI,cAChC,MACJ,IAAK,QACI5O,KAAK6O,YAAYpI,GACtB,MACJ,IAAK,QACGzG,KAAKyJ,eAILzJ,KAAK2J,mBAAqBlD,EAAIc,MAAMP,KACN,QAA7BnF,EAAK7B,KAAKwJ,qBAAuC,IAAZ3H,GAAyBA,EAAGyM,KAAKtO,KAAM,IAAImF,MAAM,uBAAuBsB,EAAIc,MAAMP,UAGxHhH,KAAKoK,UAAU3D,EAAIc,MAAMnC,SAIzC,CACA,oBAAAmF,CAAqBuE,EAAOC,GACxB,IAAIlN,EAIA7B,KAAKyJ,cACyB,QAA7B5H,EAAK7B,KAAKwJ,qBAAuC,IAAZ3H,GAAyBA,EAAGyM,KAAKtO,KAAM,IAAImF,MAAM,mCAGxE,SAAfnF,KAAKmJ,OACLnJ,KAAK+B,YAEb,CACA,oBAAAyI,CAAqBwE,GACE,cAAfhP,KAAKmJ,OACLnJ,KAAKoK,UAAU,kBAEvB,CAMA,iBAAMyE,CAAYpI,GAGd,GAAIzG,KAAKyJ,cACL,OAIJ,GAAmB,cAAfzJ,KAAKmJ,YACsByD,IAA3B5M,KAAK2M,wBACyBC,IAA9B5M,KAAK6M,qBAGL,OAFA7M,KAAKoK,UAAU,mCACfpK,KAAK6L,oBAAmB,GAG5B7L,KAAKyJ,eAAgB,EACrBzJ,KAAK4J,SAAS,gBAEd,MAAMqF,EAAU3N,KAAKqD,IAAI,EAAG8B,EAAIyI,oBAAsB,SAChDlP,KAAKmP,MAAM7N,KAAK8N,SAAWH,GAG5BjP,KAAKyJ,qBAGJzJ,KAAKqP,WACf,CAMA,eAAMA,GACF,IAAIxN,EAAIgC,EAAIC,EAGZ,IACuB,QAAlBjC,EAAK7B,KAAKyC,UAA4B,IAAZZ,GAAyBA,EAAGyN,aAAa3L,QAAS4L,IACzE,IAAI1N,EACA0N,EAAOxC,QACY,QAAlBlL,EAAK7B,KAAKyC,UAA4B,IAAZZ,GAAyBA,EAAG2N,YAAYD,KAG/E,CACA,MAAOxD,GAEP,CACA,MAAMgB,EAAoC,QAA3BlJ,EAAK7D,KAAK6I,mBAAqC,IAAZhF,OAAqB,EAAIA,EAAGiH,iBAAiB,GAC/F,IAAKiC,GAA8B,SAArBA,EAAMvF,WAGhB,OAFAxH,KAAKoK,UAAU,2CACfpK,KAAK6L,oBAAmB,GAK5B,IADA7L,KAAKyP,uBACEzP,KAAK0J,kBAjcO,GAiciC,CAChD1J,KAAK2J,mBAAqB,KAC1B,IAgBI,OAdA3J,KAAK0I,aAAe1I,KAAK2I,cACzB3I,KAAK4I,UAAY,IAAI,IAAgB5I,KAAKiG,MAAOjG,KAAK0I,OAAOjD,aAAczF,KAAKqK,uBAAuBC,KAAKtK,MAAOA,KAAKuK,qBAAqBD,KAAKtK,MAAOA,KAAKwK,qBAAqBF,KAAKtK,aAElLA,KAAK4I,UAAU1B,oBAAoB,CACrCnD,KAAM,YACN4K,WAAY3O,KAAK2M,kBACjBiC,cAAe5O,KAAK6M,6BAGlB7M,KAAK0P,6BAA6B3C,GACxC/M,KAAK0J,kBAAoB,EACzB1J,KAAKyJ,eAAgB,OAErBzJ,KAAK2L,KAAK,uBAAmBiB,EAAW,YAE5C,CACA,MAAOrF,GAGH,MAAMP,EAAOhH,KAAK2J,mBAClB,GAAI3C,GAAQW,EAAyB5C,IAAIiC,GAGrC,OAFAhH,KAAKoK,UAAoD,QAAzCtG,EAAK8D,EAAyBZ,UAA+B,IAAZlD,EAAgBA,EAAK,mCACtF9D,KAAK6L,oBAAmB,GAK5B,GAAItE,aAAiB,IAGjB,OAFAvH,KAAKoK,UAAU7C,EAAMnC,cACrBpF,KAAK6L,oBAAmB,GAI5B,MAAMzG,EAAUmC,aAAiB,IAAkBA,EAAMnC,QAAU,gBAInE,GAHApF,KAAK2L,KAAK,UAAWvG,EAAS,aAC9BpF,KAAKyP,uBACLzP,KAAK0J,oBACD1J,KAAK0J,mBA1eE,EA2eP,MAIJ,SAFM1J,KAAKmP,MA5eE,IA4e2BnP,KAAK0J,oBAExC1J,KAAKyJ,cACN,MAER,CACJ,CACAzJ,KAAKoK,UAAU,8BACfpK,KAAK6L,oBAAmB,EAC5B,CAMA,4BAAA6D,CAA6B7E,GAsBzB,OArBA7K,KAAKyC,GAAK,IAAIiI,kBAAkB,CAC5BC,WAAY3K,KAAK0I,OAAOiC,WACxBC,mBAAoB5K,KAAK0I,OAAOkC,oBAAsB,UAE1D5K,KAAKyC,GAAGsI,SAASF,EAAY7K,KAAK6I,aAClC7I,KAAKyC,GAAGuI,QAAUhL,KAAKiL,kBAAkBX,KAAKtK,MAC9CA,KAAKyC,GAAGyI,eAAkB1E,IACtB,IAAI3E,EACA2E,EAAM2E,YACoB,QAAzBtJ,EAAK7B,KAAK4I,iBAAmC,IAAZ/G,GAAyBA,EAAGwF,KAAK,CAC/DtD,KAAM,MACNoH,UAAW3E,EAAM2E,UAAUC,aAIvCpL,KAAKyC,GAAG4I,wBACJrL,KAAKsL,4BAA4BhB,KAAKtK,MAC1CA,KAAKgJ,aAAe,IAAI,IACxBhJ,KAAKgJ,aAAa3I,MAAML,KAAK6I,YAAc6C,IACvC1L,KAAK2L,KAAK,cAAeD,EAAOE,OAAOF,MAEpC,IAAI5F,QAAQ,CAACC,EAASC,KAIzB,MAAM2J,EAAQtJ,WAAW,KACrBrG,KAAKuJ,eAAiB,KACtBvJ,KAAKwJ,cAAgB,KACrBxD,EAAO,IAAIb,MAAM,sCArhBA,MAwhBrBnF,KAAKuJ,eAAiB,KAClB1C,aAAa8I,GACb5J,KAEJ/F,KAAKwJ,cAAiBjC,IAClBV,aAAa8I,GACb3J,EAAOuB,IAEN,WACD,IAAI1F,EACJ,IACI,MAAM0J,QAAcvL,KAAKyC,GAAG+F,cAC5B,IAAK+C,EAAMC,IACP,MAAM,IAAIrG,MAAM,qCAEdnF,KAAKyC,GAAG6F,oBAAoBiD,GAClCvL,KAAK4I,UAAUvB,KAAK,CAAEtD,KAAM,QAASyH,IAAKD,EAAMC,KACpD,CACA,MAAOjE,GACH,MAAM1C,EAAO0C,aAAiBpC,MAAQoC,EAAM1C,KAAO,cACrB,QAA7BhD,EAAK7B,KAAKwJ,qBAAuC,IAAZ3H,GAAyBA,EAAGyM,KAAKtO,KAAM,IAAImF,MAAM+C,EAAcrD,IAAS,+BAClH,CACH,EAdI,IAgBb,CAKA,oBAAA4K,GACI,IAAI5N,EAAIgC,EAAIC,EAAIiI,EAAIC,EACpB,IACmC,QAA9BnK,EAAK7B,KAAKiJ,sBAAwC,IAAZpH,GAAyBA,EAAGZ,OACnEjB,KAAKiJ,eAAiB,IAC1B,CACA,MAAOgD,GAEP,CACA,IACiC,QAA5BpI,EAAK7D,KAAKgJ,oBAAsC,IAAZnF,GAAyBA,EAAG5C,OACjEjB,KAAKgJ,aAAe,IACxB,CACA,MAAOkD,GAEP,CACA,IACuC,QAAlCpI,EAAK9D,KAAK+I,0BAA4C,IAAZjF,GAAyBA,EAAG7C,OACvEjB,KAAK+I,mBAAqB,IAC9B,CACA,MAAOoD,GAEP,CACA,IACuB,QAAlBJ,EAAK/L,KAAKyC,UAA4B,IAAZsJ,GAAyBA,EAAG/J,QACvDhC,KAAKyC,GAAK,IACd,CACA,MAAO2J,GAEP,CACA,IAC8B,QAAzBJ,EAAKhM,KAAK4I,iBAAmC,IAAZoD,GAAyBA,EAAGhK,QAC9DhC,KAAK4I,UAAY,IACrB,CACA,MAAOyD,GAEP,CACA,IACQrM,KAAK8I,cACL9I,KAAK8I,YAAY0D,UAAY,KAC7BxM,KAAK8I,YAAY2D,SACjBzM,KAAK8I,YAAc,KAE3B,CACA,MAAOwD,GAEP,CACItM,KAAKsJ,oBACLzC,aAAa7G,KAAKsJ,mBAClBtJ,KAAKsJ,kBAAoB,MAE7BtJ,KAAKuJ,eAAiB,KACtBvJ,KAAKwJ,cAAgB,KACrBxJ,KAAKkJ,kBAAoB,EAC7B,CACA,KAAAiG,CAAMS,GACF,OAAO,IAAI9J,QAASC,GAAYM,WAAWN,EAAS6J,GACxD,CACA,kBAAMrB,CAAa/C,GACf,GAAKxL,KAAKyC,GAEV,UACUzC,KAAKyC,GAAG4F,qBAAqB,CAAEtE,KAAM,SAAUyH,cAC/CxL,KAAK6P,wBACf,CACA,MAAOhO,GACH7B,KAAKoK,UAAUlC,EAAoC,qBACvD,CACJ,CACA,qBAAMK,CAAgB4C,GAClB,IAAItJ,EACJ,GAAuB,QAAlBA,EAAK7B,KAAKyC,UAA4B,IAAZZ,OAAqB,EAAIA,EAAGiO,kBACvD,UACU9P,KAAKyC,GAAG8F,gBAAgB4C,EAClC,CACA,MAAOtH,GAEP,MAGA7D,KAAKkJ,kBAAkB6G,KAAK5E,EAEpC,CACA,4BAAM0E,GACF,IAAK,MAAM1E,KAAanL,KAAKkJ,kBAAmB,CAC5C,IAAKlJ,KAAKyC,GACN,MACJ,UACUzC,KAAKyC,GAAG8F,gBAAgB4C,EAClC,CACA,MAAOtJ,GAEP,CACJ,CACA7B,KAAKkJ,kBAAoB,EAC7B,CACA,OAAAuC,GACIzL,KAAK+B,YACT,CACA,kBAAA0I,GACI,IAAI5I,EACJ,IACgC,QAA3BA,EAAK7B,KAAK6I,mBAAqC,IAAZhH,GAAyBA,EAAGmO,YAAYrM,QAASsM,GAAMA,EAAEhP,QAC7FjB,KAAK6I,YAAc,IACvB,CACA,MAAOhF,GAEP,CACJ,CACA,QAAA+F,CAASsG,GACLlQ,KAAKmJ,MAAQ+G,EACblQ,KAAK2L,KAAK,eAAgBuE,EAAUA,EACxC,CACA,SAAA9F,CAAUhF,GACNpF,KAAK2L,KAAK,QAASvG,GACnBpF,KAAK4J,SAAS,QAClB,CACA,IAAA+B,CAAKnF,EAAOpB,EAASwB,GACjB,MAAMuJ,EAAS,CAAEhH,MAAO3C,EAAOpB,UAASwB,QAClCwJ,EAAUvL,IACZ,MAAM6I,EAAY1N,KAAKoJ,eAAeuE,IAAI9I,GACrC6I,GAELA,EAAU/J,QAAS0M,IACf,IACIA,EAASF,EACb,CACA,MAAOtO,GAEP,KAGRuO,EAAO5J,GACP4J,EAAO,MACX,E","sources":["webpack://MoveoAI/./src/controller/shared/audio-level-monitor.ts","webpack://MoveoAI/./src/controller/shared/media-errors.ts","webpack://MoveoAI/./src/controller/webrtc/call-quality-monitor.ts","webpack://MoveoAI/./src/controller/webrtc/config-errors.ts","webpack://MoveoAI/./src/controller/webrtc/signaling-client.ts","webpack://MoveoAI/./src/controller/webrtc/webrtc-provider.ts"],"sourcesContent":["const NOISE_GATE_THRESHOLD = 0.01;\n/**\n * Monitors a MediaStream's audio level via Web Audio API.\n * Extracted from AudioController for reuse across voice providers.\n *\n * Uses AnalyserNode with RMS calculation:\n * fftSize: 256, smoothingTimeConstant: 0.3\n * Noise gate: 0.01 threshold\n * Normalized output: 0.0 - 1.0\n */\nexport class AudioLevelMonitor {\n constructor() {\n this.analyserNode = null;\n this.audioSource = null;\n this.animationId = null;\n this.audioContext = null;\n }\n start(stream, onLevel) {\n try {\n this.audioContext = new AudioContext();\n this.audioSource = this.audioContext.createMediaStreamSource(stream);\n this.analyserNode = this.audioContext.createAnalyser();\n this.analyserNode.fftSize = 256;\n this.analyserNode.smoothingTimeConstant = 0.3;\n this.audioSource.connect(this.analyserNode);\n const dataArray = new Float32Array(this.analyserNode.fftSize);\n const checkAudioLevel = () => {\n if (!this.analyserNode) {\n this.stop();\n return;\n }\n this.analyserNode.getFloatTimeDomainData(dataArray);\n let sum = 0;\n for (const amplitude of dataArray) {\n sum += amplitude * amplitude;\n }\n const rms = Math.sqrt(sum / dataArray.length);\n const normalizedLevel = Math.min(1, rms * 10);\n const gatedLevel = normalizedLevel > NOISE_GATE_THRESHOLD ? normalizedLevel : 0;\n onLevel(gatedLevel.toFixed(3));\n this.animationId = requestAnimationFrame(checkAudioLevel);\n };\n checkAudioLevel();\n }\n catch (_a) {\n // Silently fail — audio monitoring is non-critical\n }\n }\n stop() {\n if (this.animationId !== null) {\n cancelAnimationFrame(this.animationId);\n this.animationId = null;\n }\n if (this.audioSource) {\n try {\n this.audioSource.disconnect();\n }\n catch (_a) {\n // ignore\n }\n this.audioSource = null;\n }\n if (this.audioContext) {\n void this.audioContext.close().catch(() => {\n // ignore\n });\n this.audioContext = null;\n }\n this.analyserNode = null;\n }\n}\n","/**\n * User-friendly messages for the common getUserMedia DOMException names.\n * Shared across voice providers (native WebRTC, Telnyx) so a single string\n * surfaces in the widget regardless of provider.\n */\nexport const MEDIA_ERRORS = {\n NotAllowedError: 'Microphone permission denied',\n NotFoundError: 'No microphone found',\n NotReadableError: 'Microphone is in use by another application',\n OverconstrainedError: 'Microphone does not support required settings',\n};\n","const QUALITY_WARNINGS = {\n 'high-rtt': 'High network latency detected',\n 'low-mos': 'Poor call quality detected',\n 'high-jitter': 'Network instability detected',\n 'high-packet-loss': 'Packet loss detected',\n};\nconst THRESHOLDS = {\n RTT: 400, // ms\n JITTER: 0.03, // seconds (30ms)\n PACKET_LOSS: 0.03, // 3%\n MOS: 3.0,\n};\n/**\n * Replaces Twilio Voice Insights with standard WebRTC getStats().\n * Polls pc.getStats() and maps to warning events that AudioWidget handles.\n */\nexport class CallQualityMonitor {\n constructor(pc, onWarning, onWarningCleared, pollIntervalMs = 5000) {\n this.pc = pc;\n this.onWarning = onWarning;\n this.onWarningCleared = onWarningCleared;\n this.pollIntervalMs = pollIntervalMs;\n this.interval = null;\n this.prevStats = null;\n this.activeWarnings = new Set();\n }\n start() {\n this.interval = setInterval(() => {\n void this.pollStats();\n }, this.pollIntervalMs);\n }\n stop() {\n if (this.interval !== null) {\n clearInterval(this.interval);\n this.interval = null;\n }\n this.prevStats = null;\n this.activeWarnings.clear();\n }\n async pollStats() {\n try {\n const stats = await this.pc.getStats();\n let rtt = null;\n let jitter = null;\n let packetsReceived = 0;\n let packetsLost = 0;\n stats.forEach((report) => {\n var _a, _b, _c;\n if (report.type === 'candidate-pair' && report.nominated) {\n const crt = report\n .currentRoundTripTime;\n rtt = crt != null ? crt * 1000 : null;\n }\n if (report.type === 'inbound-rtp' && report.kind === 'audio') {\n const rtp = report;\n jitter = (_a = rtp.jitter) !== null && _a !== void 0 ? _a : null;\n packetsReceived = (_b = rtp.packetsReceived) !== null && _b !== void 0 ? _b : 0;\n packetsLost = (_c = rtp.packetsLost) !== null && _c !== void 0 ? _c : 0;\n }\n });\n // Compute packet loss rate over delta\n let lossRate = 0;\n if (this.prevStats) {\n const deltaReceived = packetsReceived - this.prevStats.packetsReceived;\n const deltaLost = packetsLost - this.prevStats.packetsLost;\n const total = deltaReceived + deltaLost;\n lossRate = total > 0 ? deltaLost / total : 0;\n }\n this.prevStats = { packetsReceived, packetsLost };\n // Check thresholds\n this.checkWarning('high-rtt', rtt !== null && rtt > THRESHOLDS.RTT);\n this.checkWarning('high-jitter', jitter !== null && jitter > THRESHOLDS.JITTER);\n this.checkWarning('high-packet-loss', lossRate > THRESHOLDS.PACKET_LOSS);\n // MOS estimation (simplified E-model)\n if (rtt !== null && jitter !== null) {\n const jitterMs = jitter * 1000;\n const lossPercent = lossRate * 100;\n const R = 93.2 - jitterMs * 2 - lossPercent * 40 - Math.max(0, rtt - 150) * 0.1;\n const mos = 1 + 0.035 * R + R * (R - 60) * (100 - R) * 7e-6;\n this.checkWarning('low-mos', mos < THRESHOLDS.MOS);\n }\n }\n catch (_a) {\n // pc may have closed mid-poll; quality stats are non-critical\n }\n }\n checkWarning(name, isExceeded) {\n if (isExceeded && !this.activeWarnings.has(name)) {\n this.activeWarnings.add(name);\n this.onWarning(name, QUALITY_WARNINGS[name] || name);\n }\n else if (!isExceeded && this.activeWarnings.has(name)) {\n this.activeWarnings.delete(name);\n this.onWarningCleared(name);\n }\n }\n}\n","/**\n * Typed errors for the GET /config flow, shared by WebRTCController (initial\n * connect) and WebRTCProvider (reconnect-time re-fetch) so both can branch on\n * a server-busy 503 without parsing message strings.\n */\n/**\n * Raised when /config returns 503 with error_code \"server_busy\" — the pod is at\n * its concurrent-session cap. Retryable with backoff against a sibling pod.\n */\nexport class ServerBusyError extends Error {\n constructor(message = 'Voice service is busy, please try again.') {\n super(message);\n this.name = 'ServerBusyError';\n }\n}\n/**\n * Raised when /config fails in a way retrying can't fix (e.g. TURN not\n * configured). Terminal — the reconnect loop must not burn retries on it.\n */\nexport class ConfigUnavailableError extends Error {\n constructor(message) {\n super(message);\n this.name = 'ConfigUnavailableError';\n }\n}\n","const CONNECT_TIMEOUT_MS = 10000;\n/**\n * JSON-over-WebSocket signaling for WebRTC voice sessions.\n * Stateless thin wrapper — all connection state lives in WebRTCProvider.\n */\nexport class SignalingClient {\n constructor(url, sessionToken, onMessage, onClose, onError) {\n this.url = url;\n this.sessionToken = sessionToken;\n this.onMessage = onMessage;\n this.onClose = onClose;\n this.onError = onError;\n this.ws = null;\n }\n connect() {\n return new Promise((resolve, reject) => {\n const wsUrl = `${this.url}?token=${encodeURIComponent(this.sessionToken)}`;\n this.ws = new WebSocket(wsUrl);\n const timeout = setTimeout(() => {\n var _a;\n (_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();\n reject(new Error('Signaling connection timed out'));\n }, CONNECT_TIMEOUT_MS);\n this.ws.onopen = () => {\n // Wait for welcome message before resolving\n };\n this.ws.onmessage = (event) => {\n let msg;\n try {\n msg = JSON.parse(event.data);\n }\n catch (_a) {\n // Ignore malformed JSON\n return;\n }\n if (msg.type === 'welcome') {\n clearTimeout(timeout);\n resolve();\n }\n this.onMessage(msg);\n };\n this.ws.onerror = (event) => {\n clearTimeout(timeout);\n this.onError(event);\n reject(new Error('Signaling WebSocket error'));\n };\n this.ws.onclose = (event) => {\n clearTimeout(timeout);\n reject(new Error('Signaling WebSocket closed before connection established'));\n this.onClose(event.code, event.reason);\n };\n });\n }\n /**\n * Open a fresh WS to resume a drained session. Sends `reconnect` as the\n * first frame on open and resolves on `reconnect_ack` (not `welcome` — a\n * resumed session does not re-issue welcome). The fresh-call `connect()`\n * path is intentionally left untouched.\n */\n connectForReconnect(reconnectFrame) {\n return new Promise((resolve, reject) => {\n const wsUrl = `${this.url}?token=${encodeURIComponent(this.sessionToken)}`;\n this.ws = new WebSocket(wsUrl);\n let settled = false;\n const timeout = setTimeout(() => {\n var _a;\n if (settled)\n return;\n settled = true;\n (_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();\n reject(new Error('Signaling reconnect timed out'));\n }, CONNECT_TIMEOUT_MS);\n this.ws.onopen = () => {\n var _a;\n // reconnect MUST be the first frame, before any offer.\n (_a = this.ws) === null || _a === void 0 ? void 0 : _a.send(JSON.stringify(reconnectFrame));\n };\n this.ws.onmessage = (event) => {\n let msg;\n try {\n msg = JSON.parse(event.data);\n }\n catch (_a) {\n // Ignore malformed JSON\n return;\n }\n // Deliver to the provider first so it records the credential rotation\n // (reconnect_ack) or the reject code (error) before we settle.\n this.onMessage(msg);\n if (settled)\n return;\n if (msg.type === 'reconnect_ack') {\n settled = true;\n clearTimeout(timeout);\n resolve();\n }\n else if (msg.type === 'error') {\n // Server rejected the resume. Settle now rather than waiting on the\n // WS close that follows — avoids a per-attempt CONNECT_TIMEOUT stall\n // and makes the reject deterministic w.r.t. the captured error code.\n settled = true;\n clearTimeout(timeout);\n reject(new Error(`reconnect rejected: ${msg.error.code}`));\n }\n };\n this.ws.onerror = (event) => {\n this.onError(event);\n if (settled)\n return;\n settled = true;\n clearTimeout(timeout);\n reject(new Error('Signaling WebSocket error'));\n };\n this.ws.onclose = (event) => {\n if (!settled) {\n settled = true;\n clearTimeout(timeout);\n reject(new Error('Signaling WebSocket closed before reconnect established'));\n }\n this.onClose(event.code, event.reason);\n };\n });\n }\n send(msg) {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n return;\n }\n this.ws.send(JSON.stringify(msg));\n }\n close() {\n if (this.ws) {\n this.ws.onclose = null;\n this.ws.onerror = null;\n this.ws.onmessage = null;\n this.ws.close(1000, 'Client closed');\n this.ws = null;\n }\n }\n get isConnected() {\n var _a;\n return ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN;\n }\n}\n","import 'webrtc-adapter';\nimport { AudioLevelMonitor } from '../shared/audio-level-monitor';\nimport { MEDIA_ERRORS } from '../shared/media-errors';\nimport { CallQualityMonitor } from './call-quality-monitor';\nimport { ConfigUnavailableError, ServerBusyError } from './config-errors';\nimport { SignalingClient } from './signaling-client';\nconst DISCONNECT_TIMEOUT_MS = 30000;\nconst REMOTE_AUDIO_THRESHOLD = 0.02;\n// Pod-drain reconnect bounds.\nconst MAX_CLIENT_RETRIES = 3;\nconst RECONNECT_BACKOFF_MS = 500; // scaled by attempt number\n// Settle window for the post-ack media resume; on the drain path the WS-close\n// teardown is disabled, so this is the only guard against a wedged resume.\nconst RECONNECT_ICE_TIMEOUT_MS = 15000;\n// Reconnect error codes that cannot be resumed — give up without retrying.\n// Any other failure (transient WS/ICE, server_busy) is retryable.\nconst TERMINAL_RECONNECT_CODES = new Set([\n 'session_expired',\n 'session_inactive',\n 'invalid_credential',\n 'max_recovery_exceeded',\n 'unexpected_first_frame',\n]);\n/** User-facing copy for terminal reconnect failures. Infra-agnostic. */\nconst RECONNECT_ERROR_MESSAGES = {\n session_expired: 'Your session has expired.',\n session_inactive: 'The call has ended.',\n invalid_credential: 'Could not resume the call.',\n max_recovery_exceeded: 'Could not resume the call after several attempts.',\n unexpected_first_frame: 'Could not resume the call.',\n};\n/** User-friendly error messages for WebRTC API failures */\nconst WEBRTC_ERRORS = Object.assign(Object.assign({}, MEDIA_ERRORS), { setRemoteDescription: 'Connection setup failed', setLocalDescription: 'Connection setup failed', addIceCandidate: 'Network configuration failed', createOffer: 'Browser audio setup failed' });\n/** Native WebRTC voice provider for Moveo web-voice integrations. */\nexport class WebRTCProvider {\n constructor(config, wsUrl, \n // Re-fetches /config (fresh TURN) for a resume; throws ServerBusyError on a\n // server-busy 503. Injected so signaling stays in the provider.\n fetchConfig) {\n this.config = config;\n this.wsUrl = wsUrl;\n this.fetchConfig = fetchConfig;\n this.pc = null;\n this.signaling = null;\n this.localStream = null;\n this.remoteAudio = null;\n this.remoteAudioMonitor = null;\n this.audioMonitor = null;\n this.qualityMonitor = null;\n this.pendingCandidates = [];\n this.state = 'idle';\n this.eventListeners = new Map();\n this.disconnectTimeout = null;\n this.connectResolve = null;\n this.connectReject = null;\n // Set between a drain frame and a completed resume; gates the ICE-level\n // disconnect/failed handlers so the drain flow owns teardown.\n this.drainReceived = false;\n this.reconnectAttempts = 0;\n // Captured from an error frame mid-resume to classify terminal vs retryable.\n this.reconnectErrorCode = null;\n }\n async connect() {\n this.setState('connecting');\n // 1. Get microphone access\n try {\n this.localStream = await navigator.mediaDevices.getUserMedia({\n audio: {\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n });\n }\n catch (error) {\n const name = error instanceof Error ? error.name : '';\n const message = WEBRTC_ERRORS[name] || 'Microphone access failed';\n this.emitError(message);\n throw new Error(message);\n }\n // 2. Open signaling WebSocket\n this.signaling = new SignalingClient(this.wsUrl, this.config.sessionToken, this.handleSignalingMessage.bind(this), this.handleSignalingClose.bind(this), this.handleSignalingError.bind(this));\n try {\n await this.signaling.connect();\n }\n catch (error) {\n this.cleanupLocalStream();\n const message = error instanceof Error ? error.message : 'Signaling connection failed';\n this.emitError(message);\n throw new Error(message);\n }\n // 3. Create PeerConnection\n this.pc = new RTCPeerConnection({\n iceServers: this.config.iceServers,\n iceTransportPolicy: this.config.iceTransportPolicy || 'relay',\n });\n // 4. Add local audio track\n const audioTrack = this.localStream.getAudioTracks()[0];\n this.pc.addTrack(audioTrack, this.localStream);\n // 5. Set up PC handlers\n this.pc.ontrack = this.handleRemoteTrack.bind(this);\n this.pc.onicecandidate = (event) => {\n var _a;\n if (event.candidate) {\n (_a = this.signaling) === null || _a === void 0 ? void 0 : _a.send({\n type: 'ice',\n candidate: event.candidate.toJSON(),\n });\n }\n };\n this.pc.onconnectionstatechange =\n this.handleConnectionStateChange.bind(this);\n // 6. Create and send offer\n try {\n const offer = await this.pc.createOffer();\n if (!offer.sdp) {\n throw new Error('createOffer returned no SDP');\n }\n await this.pc.setLocalDescription(offer);\n this.signaling.send({ type: 'offer', sdp: offer.sdp });\n }\n catch (error) {\n this.cleanup();\n const name = error instanceof Error ? error.name : 'createOffer';\n const message = WEBRTC_ERRORS[name] || 'Failed to create call offer';\n this.emitError(message);\n throw new Error(message);\n }\n // 7. Start local audio monitoring\n this.audioMonitor = new AudioLevelMonitor();\n this.audioMonitor.start(this.localStream, (level) => {\n this.emit('audio-level', level, Number(level));\n });\n // 8. Wait for PeerConnection to reach 'connected' state\n return new Promise((resolve, reject) => {\n this.connectResolve = resolve;\n this.connectReject = reject;\n });\n }\n disconnect() {\n this.disconnectInternal(false);\n }\n disconnectInternal(suppressOutboundHangup) {\n // Fault-tolerant disconnect: each step wrapped in try/catch\n var _a, _b, _c, _d, _e, _f;\n if (!suppressOutboundHangup) {\n try {\n (_a = this.signaling) === null || _a === void 0 ? void 0 : _a.send({ type: 'hangup' });\n }\n catch (_g) {\n // continue cleanup\n }\n }\n try {\n (_b = this.qualityMonitor) === null || _b === void 0 ? void 0 : _b.stop();\n this.qualityMonitor = null;\n }\n catch (_h) {\n // continue cleanup\n }\n try {\n (_c = this.audioMonitor) === null || _c === void 0 ? void 0 : _c.stop();\n this.audioMonitor = null;\n }\n catch (_j) {\n // continue cleanup\n }\n try {\n (_d = this.remoteAudioMonitor) === null || _d === void 0 ? void 0 : _d.stop();\n this.remoteAudioMonitor = null;\n }\n catch (_k) {\n // continue cleanup\n }\n try {\n (_e = this.pc) === null || _e === void 0 ? void 0 : _e.close();\n this.pc = null;\n }\n catch (_l) {\n // continue cleanup\n }\n this.cleanupLocalStream();\n try {\n (_f = this.signaling) === null || _f === void 0 ? void 0 : _f.close();\n this.signaling = null;\n }\n catch (_m) {\n // continue cleanup\n }\n try {\n if (this.remoteAudio) {\n this.remoteAudio.srcObject = null;\n this.remoteAudio.remove();\n this.remoteAudio = null;\n }\n }\n catch (_o) {\n // continue cleanup\n }\n if (this.disconnectTimeout) {\n clearTimeout(this.disconnectTimeout);\n this.disconnectTimeout = null;\n }\n if (this.connectReject) {\n this.connectReject(new Error('Call disconnected before connection completed'));\n }\n this.connectResolve = null;\n this.connectReject = null;\n // Clear pod-drain reconnect state so a torn-down provider can't leave\n // drainReceived stuck true (which would make handleSignalingClose swallow a\n // future legitimate close), carry a stale retry count, or resume a new call\n // with the prior session's credentials before its own session_ready lands.\n this.drainReceived = false;\n this.reconnectAttempts = 0;\n this.reconnectErrorCode = null;\n this.originalSessionID = undefined;\n this.originalConnectionID = undefined;\n this.pendingCandidates = [];\n this.setState('idle');\n }\n toggleMute() {\n var _a, _b;\n const track = (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];\n if (track) {\n track.enabled = !track.enabled;\n const muted = !track.enabled;\n (_b = this.signaling) === null || _b === void 0 ? void 0 : _b.send({ type: 'mute', muted });\n return muted;\n }\n return false;\n }\n isMuted() {\n var _a, _b, _c;\n return !((_c = (_b = (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0]) === null || _b === void 0 ? void 0 : _b.enabled) !== null && _c !== void 0 ? _c : true);\n }\n getLocalStream() {\n return this.localStream;\n }\n sendDigits(digits) {\n var _a;\n // Server expects one digit per signaling message (matches Twilio path,\n // which lets the SDK split a multi-char string internally).\n for (const ch of digits) {\n (_a = this.signaling) === null || _a === void 0 ? void 0 : _a.send({ type: 'dtmf', digit: ch });\n }\n }\n on(event, handler) {\n var _a;\n const listeners = (_a = this.eventListeners.get(event)) !== null && _a !== void 0 ? _a : new Set();\n listeners.add(handler);\n this.eventListeners.set(event, listeners);\n return () => this.off(event, handler);\n }\n off(event, handler) {\n const listeners = this.eventListeners.get(event);\n if (!listeners)\n return;\n listeners.delete(handler);\n if (listeners.size === 0) {\n this.eventListeners.delete(event);\n }\n }\n // --- Private methods ---\n handleRemoteTrack(event) {\n this.remoteAudio = document.createElement('audio');\n this.remoteAudio.srcObject = event.streams[0];\n this.remoteAudio.autoplay = true;\n document.body.appendChild(this.remoteAudio);\n // Remote audio monitoring via AnalyserNode for thinking indicator\n this.remoteAudioMonitor = new AudioLevelMonitor();\n this.remoteAudioMonitor.start(event.streams[0], (level) => {\n if (Number(level) > REMOTE_AUDIO_THRESHOLD) {\n this.emit('remote-audio', level, Number(level));\n }\n });\n }\n handleConnectionStateChange() {\n var _a, _b, _c;\n if (!this.pc)\n return;\n switch (this.pc.connectionState) {\n case 'connecting':\n this.setState('connecting');\n break;\n case 'connected':\n this.setState('connected');\n // Start quality monitoring\n this.qualityMonitor = new CallQualityMonitor(this.pc, (name, message) => this.emit('warning', message, name), (name) => this.emit('warning-cleared', undefined, name));\n this.qualityMonitor.start();\n // Resolve connect() promise\n (_a = this.connectResolve) === null || _a === void 0 ? void 0 : _a.call(this);\n this.connectResolve = null;\n this.connectReject = null;\n break;\n case 'disconnected':\n // A pod-drain resume owns the lifecycle; the ICE-blip 30s give-up\n // timer must not fire while we are intentionally tearing the PC down.\n if (this.drainReceived) {\n break;\n }\n this.setState('reconnecting');\n this.disconnectTimeout = setTimeout(() => {\n this.emitError('Connection lost');\n this.cleanup();\n }, DISCONNECT_TIMEOUT_MS);\n break;\n case 'failed':\n // During a resume, just fail the pending handshake; reconnect() handles\n // retry/teardown. Do not emitError or tear the call down here.\n if (this.drainReceived) {\n (_b = this.connectReject) === null || _b === void 0 ? void 0 : _b.call(this, new Error('ICE connection failed'));\n this.connectResolve = null;\n this.connectReject = null;\n break;\n }\n (_c = this.connectReject) === null || _c === void 0 ? void 0 : _c.call(this, new Error('ICE connection failed'));\n this.connectResolve = null;\n this.connectReject = null;\n this.emitError('Connection failed');\n this.cleanup();\n break;\n case 'closed':\n this.cleanup();\n break;\n }\n }\n handleSignalingMessage(msg) {\n var _a;\n switch (msg.type) {\n case 'answer':\n void this.handleAnswer(msg.sdp);\n break;\n case 'ice':\n void this.addIceCandidate(msg.candidate);\n break;\n // 'transcript' and 'agent_response' are forward-looking — channels\n // Phase 1 (PR #756) does not emit them over signaling. Kept so the\n // client is ready when channels wires them up.\n case 'transcript':\n this.emit('transcript', msg.text, {\n text: msg.text,\n is_final: msg.is_final,\n });\n break;\n case 'agent_response':\n this.emit('agent-response', msg.text, {\n text: msg.text,\n message_id: msg.message_id,\n });\n break;\n case 'hangup':\n this.disconnectInternal(true);\n break;\n // session_ready (not welcome) is the resume-eligible signal: cache the\n // credentials for a future reconnect.\n case 'session_ready':\n this.originalSessionID = msg.session_id;\n this.originalConnectionID = msg.connection_id;\n break;\n // Rotated credential for the next reconnect.\n case 'reconnect_ack':\n this.originalConnectionID = msg.connection_id;\n break;\n case 'drain':\n void this.handleDrain(msg);\n break;\n case 'error':\n if (this.drainReceived) {\n // Record for reconnect()'s terminal-vs-retryable check. If a resume\n // is awaiting ICE (connectReject set), fail it now so the retry loop\n // reacts immediately instead of waiting out RECONNECT_ICE_TIMEOUT_MS.\n this.reconnectErrorCode = msg.error.code;\n (_a = this.connectReject) === null || _a === void 0 ? void 0 : _a.call(this, new Error(`reconnect rejected: ${msg.error.code}`));\n }\n else {\n this.emitError(msg.error.message);\n }\n break;\n }\n }\n handleSignalingClose(_code, _reason) {\n var _a;\n // The reconnect flow owns teardown during a resume. If a resume is awaiting\n // ICE (connectReject set), fail it now so the retry loop reacts to the\n // dropped WS immediately; otherwise (pre-ack / jitter window) just ignore.\n if (this.drainReceived) {\n (_a = this.connectReject) === null || _a === void 0 ? void 0 : _a.call(this, new Error('Signaling closed during resume'));\n return;\n }\n if (this.state !== 'idle') {\n this.disconnect();\n }\n }\n handleSignalingError(_error) {\n if (this.state === 'connected') {\n this.emitError('Signaling error');\n }\n }\n /**\n * Server is draining this pod: resume the same session on a sibling after a\n * jittered delay. Distinct from the ICE-level 'disconnected' path (a blip) —\n * this is a server-initiated handoff.\n */\n async handleDrain(msg) {\n // Already resuming: a second drain (sibling pod drains before ICE connects)\n // is handled by the in-flight retry loop. Re-entering would hard-kill it.\n if (this.drainReceived) {\n return;\n }\n // Only a fully-established session is resumable: a drain before\n // session_ready (no cached credentials) or while not connected can't resume.\n if (this.state !== 'connected' ||\n this.originalSessionID === undefined ||\n this.originalConnectionID === undefined) {\n this.emitError('Could not resume the call.');\n this.disconnectInternal(true);\n return;\n }\n this.drainReceived = true;\n this.setState('reconnecting');\n // Jitter 0..delay to avoid a thundering herd against the sibling pods.\n const delayMs = Math.max(0, msg.reconnect_delay_ms || 0);\n await this.sleep(Math.random() * delayMs);\n // A teardown (user hangup / destroy) during the jitter clears drainReceived;\n // don't resurrect an ended call.\n if (!this.drainReceived) {\n return;\n }\n await this.reconnect();\n }\n /**\n * Tear down the pod-local PC/WS and resume on a sibling pod, reusing the\n * existing mic MediaStream (no second permission prompt). Retries transient\n * failures up to MAX_CLIENT_RETRIES; gives up on a terminal server rejection.\n */\n async reconnect() {\n var _a, _b, _c;\n // Detach senders before pc.close() (ghost-sender defense), then confirm the\n // mic track survived the drain (device unplug / OS reset / BT switch kill it).\n try {\n (_a = this.pc) === null || _a === void 0 ? void 0 : _a.getSenders().forEach((sender) => {\n var _a;\n if (sender.track) {\n (_a = this.pc) === null || _a === void 0 ? void 0 : _a.removeTrack(sender);\n }\n });\n }\n catch (_d) {\n // continue — closing the pc below releases the senders anyway\n }\n const track = (_b = this.localStream) === null || _b === void 0 ? void 0 : _b.getAudioTracks()[0];\n if (!track || track.readyState !== 'live') {\n this.emitError('Microphone is no longer available.');\n this.disconnectInternal(true);\n return;\n }\n // Drop pod-local resources but KEEP the MediaStream alive for reuse.\n this.teardownForReconnect();\n while (this.reconnectAttempts < MAX_CLIENT_RETRIES) {\n this.reconnectErrorCode = null;\n try {\n // Fresh /config → fresh TURN creds for the sibling pod.\n this.config = await this.fetchConfig();\n this.signaling = new SignalingClient(this.wsUrl, this.config.sessionToken, this.handleSignalingMessage.bind(this), this.handleSignalingClose.bind(this), this.handleSignalingError.bind(this));\n // Sends `reconnect` as the first frame; resolves on reconnect_ack.\n await this.signaling.connectForReconnect({\n type: 'reconnect',\n session_id: this.originalSessionID,\n connection_id: this.originalConnectionID,\n });\n // Resumed — rebuild the media plane and wait for ICE to reconnect.\n await this.buildReconnectPeerConnection(track);\n this.reconnectAttempts = 0;\n this.drainReceived = false;\n // Clear any \"reconnecting…\" banner raised by a retried attempt.\n this.emit('warning-cleared', undefined, 'reconnect');\n return;\n }\n catch (error) {\n // A terminal server rejection (bad credential, expired/ended session,\n // recovery cap) is not retryable — surface and stop.\n const code = this.reconnectErrorCode;\n if (code && TERMINAL_RECONNECT_CODES.has(code)) {\n this.emitError((_c = RECONNECT_ERROR_MESSAGES[code]) !== null && _c !== void 0 ? _c : 'Could not resume the call.');\n this.disconnectInternal(true);\n return;\n }\n // A terminal /config failure (e.g. TURN unavailable) won't fix by\n // retrying — surface its message and stop.\n if (error instanceof ConfigUnavailableError) {\n this.emitError(error.message);\n this.disconnectInternal(true);\n return;\n }\n // Transient (WS/ICE failure, server_busy 503) — back off and retry.\n const message = error instanceof ServerBusyError ? error.message : 'Reconnecting…';\n this.emit('warning', message, 'reconnect');\n this.teardownForReconnect();\n this.reconnectAttempts++;\n if (this.reconnectAttempts >= MAX_CLIENT_RETRIES) {\n break;\n }\n await this.sleep(RECONNECT_BACKOFF_MS * this.reconnectAttempts);\n // Torn down (hangup / destroy) during the backoff — stop retrying.\n if (!this.drainReceived) {\n return;\n }\n }\n }\n this.emitError('Could not resume the call.');\n this.disconnectInternal(true);\n }\n /**\n * Build a fresh PeerConnection for a resume using the existing audio track.\n * Mirrors the fresh-connect PC setup but rejects on offer failure so the\n * reconnect retry loop can decide what to do (the fresh path tears down).\n */\n buildReconnectPeerConnection(audioTrack) {\n this.pc = new RTCPeerConnection({\n iceServers: this.config.iceServers,\n iceTransportPolicy: this.config.iceTransportPolicy || 'relay',\n });\n this.pc.addTrack(audioTrack, this.localStream);\n this.pc.ontrack = this.handleRemoteTrack.bind(this);\n this.pc.onicecandidate = (event) => {\n var _a;\n if (event.candidate) {\n (_a = this.signaling) === null || _a === void 0 ? void 0 : _a.send({\n type: 'ice',\n candidate: event.candidate.toJSON(),\n });\n }\n };\n this.pc.onconnectionstatechange =\n this.handleConnectionStateChange.bind(this);\n this.audioMonitor = new AudioLevelMonitor();\n this.audioMonitor.start(this.localStream, (level) => {\n this.emit('audio-level', level, Number(level));\n });\n return new Promise((resolve, reject) => {\n // Bound the resume: if ICE never reaches 'connected' (stalled, or the\n // sibling-pod WS drops after the ack — both swallowed by the drain-path\n // handlers), reject so the retry loop can take over instead of hanging.\n const timer = setTimeout(() => {\n this.connectResolve = null;\n this.connectReject = null;\n reject(new Error('Reconnect media resume timed out'));\n }, RECONNECT_ICE_TIMEOUT_MS);\n // Resolved/rejected by handleConnectionStateChange ('connected'/'failed').\n this.connectResolve = () => {\n clearTimeout(timer);\n resolve();\n };\n this.connectReject = (error) => {\n clearTimeout(timer);\n reject(error);\n };\n void (async () => {\n var _a;\n try {\n const offer = await this.pc.createOffer();\n if (!offer.sdp) {\n throw new Error('createOffer returned no SDP');\n }\n await this.pc.setLocalDescription(offer);\n this.signaling.send({ type: 'offer', sdp: offer.sdp });\n }\n catch (error) {\n const name = error instanceof Error ? error.name : 'createOffer';\n (_a = this.connectReject) === null || _a === void 0 ? void 0 : _a.call(this, new Error(WEBRTC_ERRORS[name] || 'Failed to create call offer'));\n }\n })();\n });\n }\n /**\n * Stop pod-local resources (PC, signaling, monitors, remote audio element)\n * but deliberately KEEP localStream so the mic is reused across the resume.\n */\n teardownForReconnect() {\n var _a, _b, _c, _d, _e;\n try {\n (_a = this.qualityMonitor) === null || _a === void 0 ? void 0 : _a.stop();\n this.qualityMonitor = null;\n }\n catch (_f) {\n // continue cleanup\n }\n try {\n (_b = this.audioMonitor) === null || _b === void 0 ? void 0 : _b.stop();\n this.audioMonitor = null;\n }\n catch (_g) {\n // continue cleanup\n }\n try {\n (_c = this.remoteAudioMonitor) === null || _c === void 0 ? void 0 : _c.stop();\n this.remoteAudioMonitor = null;\n }\n catch (_h) {\n // continue cleanup\n }\n try {\n (_d = this.pc) === null || _d === void 0 ? void 0 : _d.close();\n this.pc = null;\n }\n catch (_j) {\n // continue cleanup\n }\n try {\n (_e = this.signaling) === null || _e === void 0 ? void 0 : _e.close();\n this.signaling = null;\n }\n catch (_k) {\n // continue cleanup\n }\n try {\n if (this.remoteAudio) {\n this.remoteAudio.srcObject = null;\n this.remoteAudio.remove();\n this.remoteAudio = null;\n }\n }\n catch (_l) {\n // continue cleanup\n }\n if (this.disconnectTimeout) {\n clearTimeout(this.disconnectTimeout);\n this.disconnectTimeout = null;\n }\n this.connectResolve = null;\n this.connectReject = null;\n this.pendingCandidates = [];\n }\n sleep(ms) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n async handleAnswer(sdp) {\n if (!this.pc)\n return;\n try {\n await this.pc.setRemoteDescription({ type: 'answer', sdp });\n await this.flushPendingCandidates();\n }\n catch (_a) {\n this.emitError(WEBRTC_ERRORS['setRemoteDescription']);\n }\n }\n async addIceCandidate(candidate) {\n var _a;\n if ((_a = this.pc) === null || _a === void 0 ? void 0 : _a.remoteDescription) {\n try {\n await this.pc.addIceCandidate(candidate);\n }\n catch (_b) {\n // Non-critical — log but don't fail\n }\n }\n else {\n this.pendingCandidates.push(candidate);\n }\n }\n async flushPendingCandidates() {\n for (const candidate of this.pendingCandidates) {\n if (!this.pc)\n break;\n try {\n await this.pc.addIceCandidate(candidate);\n }\n catch (_a) {\n // Non-critical\n }\n }\n this.pendingCandidates = [];\n }\n cleanup() {\n this.disconnect();\n }\n cleanupLocalStream() {\n var _a;\n try {\n (_a = this.localStream) === null || _a === void 0 ? void 0 : _a.getTracks().forEach((t) => t.stop());\n this.localStream = null;\n }\n catch (_b) {\n // continue cleanup\n }\n }\n setState(newState) {\n this.state = newState;\n this.emit('state-change', newState, newState);\n }\n emitError(message) {\n this.emit('error', message);\n this.setState('error');\n }\n emit(event, message, data) {\n const detail = { state: event, message, data };\n const invoke = (name) => {\n const listeners = this.eventListeners.get(name);\n if (!listeners)\n return;\n listeners.forEach((listener) => {\n try {\n listener(detail);\n }\n catch (_a) {\n // Ignore listener errors\n }\n });\n };\n invoke(event);\n invoke('any');\n }\n}\n"],"names":["AudioLevelMonitor","constructor","this","analyserNode","audioSource","animationId","audioContext","start","stream","onLevel","AudioContext","createMediaStreamSource","createAnalyser","fftSize","smoothingTimeConstant","connect","dataArray","Float32Array","checkAudioLevel","stop","getFloatTimeDomainData","sum","amplitude","rms","Math","sqrt","length","normalizedLevel","min","toFixed","requestAnimationFrame","_a","cancelAnimationFrame","disconnect","close","catch","MEDIA_ERRORS","NotAllowedError","NotFoundError","NotReadableError","OverconstrainedError","QUALITY_WARNINGS","CallQualityMonitor","pc","onWarning","onWarningCleared","pollIntervalMs","interval","prevStats","activeWarnings","Set","setInterval","pollStats","clearInterval","clear","stats","getStats","rtt","jitter","packetsReceived","packetsLost","forEach","report","_b","_c","type","nominated","crt","currentRoundTripTime","kind","rtp","lossRate","deltaReceived","deltaLost","total","checkWarning","R","max","mos","name","isExceeded","has","add","delete","ServerBusyError","Error","message","super","ConfigUnavailableError","SignalingClient","url","sessionToken","onMessage","onClose","onError","ws","Promise","resolve","reject","wsUrl","encodeURIComponent","WebSocket","timeout","setTimeout","onopen","onmessage","event","msg","JSON","parse","data","clearTimeout","onerror","onclose","code","reason","connectForReconnect","reconnectFrame","settled","send","stringify","error","readyState","OPEN","isConnected","TERMINAL_RECONNECT_CODES","RECONNECT_ERROR_MESSAGES","session_expired","session_inactive","invalid_credential","max_recovery_exceeded","unexpected_first_frame","WEBRTC_ERRORS","Object","assign","setRemoteDescription","setLocalDescription","addIceCandidate","createOffer","WebRTCProvider","config","fetchConfig","signaling","localStream","remoteAudio","remoteAudioMonitor","audioMonitor","qualityMonitor","pendingCandidates","state","eventListeners","Map","disconnectTimeout","connectResolve","connectReject","drainReceived","reconnectAttempts","reconnectErrorCode","setState","navigator","mediaDevices","getUserMedia","audio","echoCancellation","noiseSuppression","autoGainControl","emitError","handleSignalingMessage","bind","handleSignalingClose","handleSignalingError","cleanupLocalStream","RTCPeerConnection","iceServers","iceTransportPolicy","audioTrack","getAudioTracks","addTrack","ontrack","handleRemoteTrack","onicecandidate","candidate","toJSON","onconnectionstatechange","handleConnectionStateChange","offer","sdp","cleanup","level","emit","Number","disconnectInternal","suppressOutboundHangup","_d","_e","_f","_g","_h","_j","_k","_l","_m","srcObject","remove","_o","originalSessionID","undefined","originalConnectionID","toggleMute","track","enabled","muted","isMuted","getLocalStream","sendDigits","digits","ch","digit","on","handler","listeners","get","set","off","size","document","createElement","streams","autoplay","body","appendChild","connectionState","call","handleAnswer","text","is_final","message_id","session_id","connection_id","handleDrain","_code","_reason","_error","delayMs","reconnect_delay_ms","sleep","random","reconnect","getSenders","sender","removeTrack","teardownForReconnect","buildReconnectPeerConnection","timer","ms","flushPendingCandidates","remoteDescription","push","getTracks","t","newState","detail","invoke","listener"],"sourceRoot":""}
|
package/dist/929.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 929.min.js.LICENSE.txt */
|
|
2
|
+
"use strict";(this.webpackChunkMoveoAI=this.webpackChunkMoveoAI||[]).push([[929],{7929:function(e,t,n){n.r(t),n.d(t,{buildWebVoiceWsUrl:function(){return o},fetchWebVoiceConfig:function(){return i}});var r=n(6845);const o=(e,t)=>e.replace(/^https:/,"wss:").replace(/^http:/,"ws:")+`/v1/webvoice/${encodeURIComponent(t)}/rtc`,s=async(e,t)=>{const n=await fetch(((e,t)=>`${e}/v1/webvoice/${encodeURIComponent(t)}/config`)(e,t),{method:"GET"});if(!n.ok){if(404===n.status)throw new Error(`Integration ID "${t}" was not found.`);if(403===n.status)throw new r.X("Voice calling is currently unavailable.");if(503===n.status){let e;try{e=(await n.json()).error_code}catch(e){}if("turn_unavailable"===e)throw new r.X("Voice calling is unavailable on this deployment (TURN not configured).");if("server_busy"===e)throw new r.P}throw new Error(`Unable to fetch config (status ${n.status} ${n.statusText}).`)}const o=await n.json();if(!o.iceServers||!o.sessionToken)throw new Error("Invalid config response: missing iceServers or sessionToken");return o},i=async(e,t)=>{let n=0;for(;;)try{return await s(e,t)}catch(e){if(e instanceof r.P&&n<2){n++,await new Promise(e=>setTimeout(e,500*n));continue}throw e}}},6845:function(e,t,n){n.d(t,{P:function(){return r},X:function(){return o}});class r extends Error{constructor(e="Voice service is busy, please try again."){super(e),this.name="ServerBusyError"}}class o extends Error{constructor(e){super(e),this.name="ConfigUnavailableError"}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"929.min.js","mappings":";sNAEA,MAIaA,EAAqB,CAACC,EAAMC,IAAkBD,EAAKE,QAAQ,UAAW,QAAQA,QAAQ,SAAU,OACzG,gBAAgBC,mBAAmBF,SAEjCG,EAAYC,MAAOL,EAAMC,KAC3B,MAAMK,QAAiBC,MANJ,EAACP,EAAMC,IAAkB,GAAGD,iBAAoBG,mBAAmBF,YAMzDO,CAAeR,EAAMC,GAAgB,CAC9DQ,OAAQ,QAEZ,IAAKH,EAASI,GAAI,CACd,GAAwB,MAApBJ,EAASK,OACT,MAAM,IAAIC,MAAM,mBAAmBX,qBAKvC,GAAwB,MAApBK,EAASK,OACT,MAAM,IAAI,IAAuB,2CAErC,GAAwB,MAApBL,EAASK,OAAgB,CACzB,IAAIE,EACJ,IAEIA,SADoBP,EAASQ,QACZC,UACrB,CACA,MAAOC,GAEP,CACA,GAAkB,qBAAdH,EACA,MAAM,IAAI,IAAuB,0EAErC,GAAkB,gBAAdA,EACA,MAAM,IAAI,GAElB,CACA,MAAM,IAAID,MAAM,kCAAkCN,EAASK,UAAUL,EAASW,eAClF,CACA,MAAMC,QAAcZ,EAASQ,OAC7B,IAAKI,EAAKC,aAAeD,EAAKE,aAC1B,MAAM,IAAIR,MAAM,+DAEpB,OAAOM,GAMEG,EAAsBhB,MAAOL,EAAMC,KAC5C,IAAIqB,EAAU,EACd,OACI,IACI,aAAalB,EAAUJ,EAAMC,EACjC,CACA,MAAOsB,GACH,GAAIA,aAAiB,KAAmBD,EAAUE,EAAsB,CACpEF,UACM,IAAIG,QAASC,GAAYC,WAAWD,EAzDlC,IAyD6DJ,IACrE,QACJ,CACA,MAAMC,CACV,E,8ECvDD,MAAMK,UAAwBhB,MACjC,WAAAiB,CAAYC,EAAU,4CAClBC,MAAMD,GACNE,KAAKC,KAAO,iBAChB,EAMG,MAAMC,UAA+BtB,MACxC,WAAAiB,CAAYC,GACRC,MAAMD,GACNE,KAAKC,KAAO,wBAChB,E","sources":["webpack://MoveoAI/./src/controller/webrtc/config-client.ts","webpack://MoveoAI/./src/controller/webrtc/config-errors.ts"],"sourcesContent":["import { ConfigUnavailableError, ServerBusyError } from './config-errors';\n/** Initial-connect retries when the pod is at its session cap (server_busy). */\nconst MAX_INIT_RETRIES = 3;\nconst INIT_BACKOFF_MS = 500;\nconst buildConfigUrl = (host, integrationId) => `${host}/v1/webvoice/${encodeURIComponent(integrationId)}/config`;\n/** wss:// signaling endpoint for the given web-voice integration. */\nexport const buildWebVoiceWsUrl = (host, integrationId) => host.replace(/^https:/, 'wss:').replace(/^http:/, 'ws:') +\n `/v1/webvoice/${encodeURIComponent(integrationId)}/rtc`;\n/** Single GET /config attempt. Throws typed errors for the 503 cases. */\nconst fetchOnce = async (host, integrationId) => {\n const response = await fetch(buildConfigUrl(host, integrationId), {\n method: 'GET',\n });\n if (!response.ok) {\n if (response.status === 404) {\n throw new Error(`Integration ID \"${integrationId}\" was not found.`);\n }\n // The paired web-voice integration is disabled, or this origin isn't on its\n // allowlist. Either way voice can't start — surface it as unavailable rather\n // than a raw 403 (the pairing may be re-enabled later from tooling).\n if (response.status === 403) {\n throw new ConfigUnavailableError('Voice calling is currently unavailable.');\n }\n if (response.status === 503) {\n let errorCode;\n try {\n const body = (await response.json());\n errorCode = body.error_code;\n }\n catch (_a) {\n // Body not JSON; fall through to the generic error below.\n }\n if (errorCode === 'turn_unavailable') {\n throw new ConfigUnavailableError('Voice calling is unavailable on this deployment (TURN not configured).');\n }\n if (errorCode === 'server_busy') {\n throw new ServerBusyError();\n }\n }\n throw new Error(`Unable to fetch config (status ${response.status} ${response.statusText}).`);\n }\n const data = (await response.json());\n if (!data.iceServers || !data.sessionToken) {\n throw new Error('Invalid config response: missing iceServers or sessionToken');\n }\n return data;\n};\n/**\n * Fetch /config for an initial connect, retrying a server_busy 503 with\n * backoff. All other errors propagate immediately.\n */\nexport const fetchWebVoiceConfig = async (host, integrationId) => {\n let attempt = 0;\n for (;;) {\n try {\n return await fetchOnce(host, integrationId);\n }\n catch (error) {\n if (error instanceof ServerBusyError && attempt < MAX_INIT_RETRIES - 1) {\n attempt++;\n await new Promise((resolve) => setTimeout(resolve, INIT_BACKOFF_MS * attempt));\n continue;\n }\n throw error;\n }\n }\n};\n","/**\n * Typed errors for the GET /config flow, shared by WebRTCController (initial\n * connect) and WebRTCProvider (reconnect-time re-fetch) so both can branch on\n * a server-busy 503 without parsing message strings.\n */\n/**\n * Raised when /config returns 503 with error_code \"server_busy\" — the pod is at\n * its concurrent-session cap. Retryable with backoff against a sibling pod.\n */\nexport class ServerBusyError extends Error {\n constructor(message = 'Voice service is busy, please try again.') {\n super(message);\n this.name = 'ServerBusyError';\n }\n}\n/**\n * Raised when /config fails in a way retrying can't fix (e.g. TURN not\n * configured). Terminal — the reconnect loop must not burn retries on it.\n */\nexport class ConfigUnavailableError extends Error {\n constructor(message) {\n super(message);\n this.name = 'ConfigUnavailableError';\n }\n}\n"],"names":["buildWebVoiceWsUrl","host","integrationId","replace","encodeURIComponent","fetchOnce","async","response","fetch","buildConfigUrl","method","ok","status","Error","errorCode","json","error_code","_a","statusText","data","iceServers","sessionToken","fetchWebVoiceConfig","attempt","error","MAX_INIT_RETRIES","Promise","resolve","setTimeout","ServerBusyError","constructor","message","super","this","name","ConfigUnavailableError"],"sourceRoot":""}
|
package/dist/954.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 954.min.js.LICENSE.txt */
|
|
2
|
+
"use strict";(this.webpackChunkMoveoAI=this.webpackChunkMoveoAI||[]).push([[954],{1757:function(e){const t={generateIdentifier:function(){return Math.random().toString(36).substring(2,12)}};t.localCName=t.generateIdentifier(),t.splitLines=function(e){return e.trim().split("\n").map(e=>e.trim())},t.splitSections=function(e){return e.split("\nm=").map((e,t)=>(t>0?"m="+e:e).trim()+"\r\n")},t.getDescription=function(e){const n=t.splitSections(e);return n&&n[0]},t.getMediaSections=function(e){const n=t.splitSections(e);return n.shift(),n},t.matchPrefix=function(e,n){return t.splitLines(e).filter(e=>0===e.indexOf(n))},t.parseCandidate=function(e){let t;t=0===e.indexOf("a=candidate:")?e.substring(12).split(" "):e.substring(10).split(" ");const n={foundation:t[0],component:{1:"rtp",2:"rtcp"}[t[1]]||t[1],protocol:t[2].toLowerCase(),priority:parseInt(t[3],10),ip:t[4],address:t[4],port:parseInt(t[5],10),type:t[7]};for(let e=8;e<t.length;e+=2)switch(t[e]){case"raddr":n.relatedAddress=t[e+1];break;case"rport":n.relatedPort=parseInt(t[e+1],10);break;case"tcptype":n.tcpType=t[e+1];break;case"ufrag":n.ufrag=t[e+1],n.usernameFragment=t[e+1];break;default:void 0===n[t[e]]&&(n[t[e]]=t[e+1])}return n},t.writeCandidate=function(e){const t=[];t.push(e.foundation);const n=e.component;"rtp"===n?t.push(1):"rtcp"===n?t.push(2):t.push(n),t.push(e.protocol.toUpperCase()),t.push(e.priority),t.push(e.address||e.ip),t.push(e.port);const r=e.type;return t.push("typ"),t.push(r),"host"!==r&&e.relatedAddress&&void 0!==e.relatedPort&&(t.push("raddr"),t.push(e.relatedAddress),t.push("rport"),t.push(e.relatedPort)),e.tcpType&&"tcp"===e.protocol.toLowerCase()&&(t.push("tcptype"),t.push(e.tcpType)),(e.usernameFragment||e.ufrag)&&(t.push("ufrag"),t.push(e.usernameFragment||e.ufrag)),"candidate:"+t.join(" ")},t.parseIceOptions=function(e){return e.substring(14).split(" ")},t.parseRtpMap=function(e){let t=e.substring(9).split(" ");const n={payloadType:parseInt(t.shift(),10)};return t=t[0].split("/"),n.name=t[0],n.clockRate=parseInt(t[1],10),n.channels=3===t.length?parseInt(t[2],10):1,n.numChannels=n.channels,n},t.writeRtpMap=function(e){let t=e.payloadType;void 0!==e.preferredPayloadType&&(t=e.preferredPayloadType);const n=e.channels||e.numChannels||1;return"a=rtpmap:"+t+" "+e.name+"/"+e.clockRate+(1!==n?"/"+n:"")+"\r\n"},t.parseExtmap=function(e){const t=e.substring(9).split(" ");return{id:parseInt(t[0],10),direction:t[0].indexOf("/")>0?t[0].split("/")[1]:"sendrecv",uri:t[1],attributes:t.slice(2).join(" ")}},t.writeExtmap=function(e){return"a=extmap:"+(e.id||e.preferredId)+(e.direction&&"sendrecv"!==e.direction?"/"+e.direction:"")+" "+e.uri+(e.attributes?" "+e.attributes:"")+"\r\n"},t.parseFmtp=function(e){const t={};let n;const r=e.substring(e.indexOf(" ")+1).split(";");for(let e=0;e<r.length;e++)n=r[e].trim().split("="),t[n[0].trim()]=n[1];return t},t.writeFmtp=function(e){let t="",n=e.payloadType;if(void 0!==e.preferredPayloadType&&(n=e.preferredPayloadType),e.parameters&&Object.keys(e.parameters).length){const r=[];Object.keys(e.parameters).forEach(t=>{void 0!==e.parameters[t]?r.push(t+"="+e.parameters[t]):r.push(t)}),t+="a=fmtp:"+n+" "+r.join(";")+"\r\n"}return t},t.parseRtcpFb=function(e){const t=e.substring(e.indexOf(" ")+1).split(" ");return{type:t.shift(),parameter:t.join(" ")}},t.writeRtcpFb=function(e){let t="",n=e.payloadType;return void 0!==e.preferredPayloadType&&(n=e.preferredPayloadType),e.rtcpFeedback&&e.rtcpFeedback.length&&e.rtcpFeedback.forEach(e=>{t+="a=rtcp-fb:"+n+" "+e.type+(e.parameter&&e.parameter.length?" "+e.parameter:"")+"\r\n"}),t},t.parseSsrcMedia=function(e){const t=e.indexOf(" "),n={ssrc:parseInt(e.substring(7,t),10)},r=e.indexOf(":",t);return r>-1?(n.attribute=e.substring(t+1,r),n.value=e.substring(r+1)):n.attribute=e.substring(t+1),n},t.parseSsrcGroup=function(e){const t=e.substring(13).split(" ");return{semantics:t.shift(),ssrcs:t.map(e=>parseInt(e,10))}},t.getMid=function(e){const n=t.matchPrefix(e,"a=mid:")[0];if(n)return n.substring(6)},t.parseFingerprint=function(e){const t=e.substring(14).split(" ");return{algorithm:t[0].toLowerCase(),value:t[1].toUpperCase()}},t.getDtlsParameters=function(e,n){return{role:"auto",fingerprints:t.matchPrefix(e+n,"a=fingerprint:").map(t.parseFingerprint)}},t.writeDtlsParameters=function(e,t){let n="a=setup:"+t+"\r\n";return e.fingerprints.forEach(e=>{n+="a=fingerprint:"+e.algorithm+" "+e.value+"\r\n"}),n},t.parseCryptoLine=function(e){const t=e.substring(9).split(" ");return{tag:parseInt(t[0],10),cryptoSuite:t[1],keyParams:t[2],sessionParams:t.slice(3)}},t.writeCryptoLine=function(e){return"a=crypto:"+e.tag+" "+e.cryptoSuite+" "+("object"==typeof e.keyParams?t.writeCryptoKeyParams(e.keyParams):e.keyParams)+(e.sessionParams?" "+e.sessionParams.join(" "):"")+"\r\n"},t.parseCryptoKeyParams=function(e){if(0!==e.indexOf("inline:"))return null;const t=e.substring(7).split("|");return{keyMethod:"inline",keySalt:t[0],lifeTime:t[1],mkiValue:t[2]?t[2].split(":")[0]:void 0,mkiLength:t[2]?t[2].split(":")[1]:void 0}},t.writeCryptoKeyParams=function(e){return e.keyMethod+":"+e.keySalt+(e.lifeTime?"|"+e.lifeTime:"")+(e.mkiValue&&e.mkiLength?"|"+e.mkiValue+":"+e.mkiLength:"")},t.getCryptoParameters=function(e,n){return t.matchPrefix(e+n,"a=crypto:").map(t.parseCryptoLine)},t.getIceParameters=function(e,n){const r=t.matchPrefix(e+n,"a=ice-ufrag:")[0],i=t.matchPrefix(e+n,"a=ice-pwd:")[0];return r&&i?{usernameFragment:r.substring(12),password:i.substring(10)}:null},t.writeIceParameters=function(e){let t="a=ice-ufrag:"+e.usernameFragment+"\r\na=ice-pwd:"+e.password+"\r\n";return e.iceLite&&(t+="a=ice-lite\r\n"),t},t.parseRtpParameters=function(e){const n={codecs:[],headerExtensions:[],fecMechanisms:[],rtcp:[]},r=t.splitLines(e)[0].split(" ");n.profile=r[2];for(let i=3;i<r.length;i++){const o=r[i],s=t.matchPrefix(e,"a=rtpmap:"+o+" ")[0];if(s){const r=t.parseRtpMap(s),i=t.matchPrefix(e,"a=fmtp:"+o+" ");switch(r.parameters=i.length?t.parseFmtp(i[0]):{},r.rtcpFeedback=t.matchPrefix(e,"a=rtcp-fb:"+o+" ").map(t.parseRtcpFb),n.codecs.push(r),r.name.toUpperCase()){case"RED":case"ULPFEC":n.fecMechanisms.push(r.name.toUpperCase())}}}t.matchPrefix(e,"a=extmap:").forEach(e=>{n.headerExtensions.push(t.parseExtmap(e))});const i=t.matchPrefix(e,"a=rtcp-fb:* ").map(t.parseRtcpFb);return n.codecs.forEach(e=>{i.forEach(t=>{e.rtcpFeedback.find(e=>e.type===t.type&&e.parameter===t.parameter)||e.rtcpFeedback.push(t)})}),n},t.writeRtpDescription=function(e,n){let r="";r+="m="+e+" ",r+=n.codecs.length>0?"9":"0",r+=" "+(n.profile||"UDP/TLS/RTP/SAVPF")+" ",r+=n.codecs.map(e=>void 0!==e.preferredPayloadType?e.preferredPayloadType:e.payloadType).join(" ")+"\r\n",r+="c=IN IP4 0.0.0.0\r\n",r+="a=rtcp:9 IN IP4 0.0.0.0\r\n",n.codecs.forEach(e=>{r+=t.writeRtpMap(e),r+=t.writeFmtp(e),r+=t.writeRtcpFb(e)});let i=0;return n.codecs.forEach(e=>{e.maxptime>i&&(i=e.maxptime)}),i>0&&(r+="a=maxptime:"+i+"\r\n"),n.headerExtensions&&n.headerExtensions.forEach(e=>{r+=t.writeExtmap(e)}),r},t.parseRtpEncodingParameters=function(e){const n=[],r=t.parseRtpParameters(e),i=-1!==r.fecMechanisms.indexOf("RED"),o=-1!==r.fecMechanisms.indexOf("ULPFEC"),s=t.matchPrefix(e,"a=ssrc:").map(e=>t.parseSsrcMedia(e)).filter(e=>"cname"===e.attribute),a=s.length>0&&s[0].ssrc;let c;const p=t.matchPrefix(e,"a=ssrc-group:FID").map(e=>e.substring(17).split(" ").map(e=>parseInt(e,10)));p.length>0&&p[0].length>1&&p[0][0]===a&&(c=p[0][1]),r.codecs.forEach(e=>{if("RTX"===e.name.toUpperCase()&&e.parameters.apt){let t={ssrc:a,codecPayloadType:parseInt(e.parameters.apt,10)};a&&c&&(t.rtx={ssrc:c}),n.push(t),i&&(t=JSON.parse(JSON.stringify(t)),t.fec={ssrc:a,mechanism:o?"red+ulpfec":"red"},n.push(t))}}),0===n.length&&a&&n.push({ssrc:a});let d=t.matchPrefix(e,"b=");return d.length&&(d=0===d[0].indexOf("b=TIAS:")?parseInt(d[0].substring(7),10):0===d[0].indexOf("b=AS:")?1e3*parseInt(d[0].substring(5),10)*.95-16e3:void 0,n.forEach(e=>{e.maxBitrate=d})),n},t.parseRtcpParameters=function(e){const n={},r=t.matchPrefix(e,"a=ssrc:").map(e=>t.parseSsrcMedia(e)).filter(e=>"cname"===e.attribute)[0];r&&(n.cname=r.value,n.ssrc=r.ssrc);const i=t.matchPrefix(e,"a=rtcp-rsize");n.reducedSize=i.length>0,n.compound=0===i.length;const o=t.matchPrefix(e,"a=rtcp-mux");return n.mux=o.length>0,n},t.writeRtcpParameters=function(e){let t="";return e.reducedSize&&(t+="a=rtcp-rsize\r\n"),e.mux&&(t+="a=rtcp-mux\r\n"),void 0!==e.ssrc&&e.cname&&(t+="a=ssrc:"+e.ssrc+" cname:"+e.cname+"\r\n"),t},t.parseMsid=function(e){let n;const r=t.matchPrefix(e,"a=msid:");if(1===r.length)return n=r[0].substring(7).split(" "),{stream:n[0],track:n[1]};const i=t.matchPrefix(e,"a=ssrc:").map(e=>t.parseSsrcMedia(e)).filter(e=>"msid"===e.attribute);return i.length>0?(n=i[0].value.split(" "),{stream:n[0],track:n[1]}):void 0},t.parseSctpDescription=function(e){const n=t.parseMLine(e),r=t.matchPrefix(e,"a=max-message-size:");let i;r.length>0&&(i=parseInt(r[0].substring(19),10)),isNaN(i)&&(i=65536);const o=t.matchPrefix(e,"a=sctp-port:");if(o.length>0)return{port:parseInt(o[0].substring(12),10),protocol:n.fmt,maxMessageSize:i};const s=t.matchPrefix(e,"a=sctpmap:");if(s.length>0){const e=s[0].substring(10).split(" ");return{port:parseInt(e[0],10),protocol:e[1],maxMessageSize:i}}},t.writeSctpDescription=function(e,t){let n=[];return n="DTLS/SCTP"!==e.protocol?["m="+e.kind+" 9 "+e.protocol+" "+t.protocol+"\r\n","c=IN IP4 0.0.0.0\r\n","a=sctp-port:"+t.port+"\r\n"]:["m="+e.kind+" 9 "+e.protocol+" "+t.port+"\r\n","c=IN IP4 0.0.0.0\r\n","a=sctpmap:"+t.port+" "+t.protocol+" 65535\r\n"],void 0!==t.maxMessageSize&&n.push("a=max-message-size:"+t.maxMessageSize+"\r\n"),n.join("")},t.generateSessionId=function(){return Math.random().toString().substr(2,22)},t.writeSessionBoilerplate=function(e,n,r){let i;const o=void 0!==n?n:2;return i=e||t.generateSessionId(),"v=0\r\no="+(r||"thisisadapterortc")+" "+i+" "+o+" IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\n"},t.getDirection=function(e,n){const r=t.splitLines(e);for(let e=0;e<r.length;e++)switch(r[e]){case"a=sendrecv":case"a=sendonly":case"a=recvonly":case"a=inactive":return r[e].substring(2)}return n?t.getDirection(n):"sendrecv"},t.getKind=function(e){return t.splitLines(e)[0].split(" ")[0].substring(2)},t.isRejected=function(e){return"0"===e.split(" ",2)[1]},t.parseMLine=function(e){const n=t.splitLines(e)[0].substring(2).split(" ");return{kind:n[0],port:parseInt(n[1],10),protocol:n[2],fmt:n.slice(3).join(" ")}},t.parseOLine=function(e){const n=t.matchPrefix(e,"o=")[0].substring(2).split(" ");return{username:n[0],sessionId:n[1],sessionVersion:parseInt(n[2],10),netType:n[3],addressType:n[4],address:n[5]}},t.isValidSDP=function(e){if("string"!=typeof e||0===e.length)return!1;const n=t.splitLines(e);for(let e=0;e<n.length;e++)if(n[e].length<2||"="!==n[e].charAt(1))return!1;return!0},e.exports=t},4954:function(e,t,n){(0,n(575).a)({window:"undefined"==typeof window?void 0:window})},575:function(e,t,n){n.d(t,{a:function(){return d}});var r=n(5432),i=n(4002),o=n(6504),s=n(4054),a=n(1458),c=n(6298),p=n(1757);function d({window:e}={},t={shimChrome:!0,shimFirefox:!0,shimSafari:!0}){const n=r.Rm,d=r.cO(e),u={browserDetails:d,commonShim:c,extractVersion:r.Gr,disableLog:r.Rn,disableWarnings:r.co,sdp:p};switch(d.browser){case"chrome":if(!i||!i.shimPeerConnection||!t.shimChrome)return n("Chrome shim is not included in this adapter release."),u;if(null===d.version)return n("Chrome shim can not determine version, not shimming."),u;n("adapter.js shimming chrome."),u.browserShim=i,c.shimAddIceCandidateNullOrEmpty(e,d),c.shimParameterlessSetLocalDescription(e,d),i.shimGetUserMedia(e,d),i.shimMediaStream(e,d),i.shimPeerConnection(e,d),i.shimOnTrack(e,d),i.shimAddTrackRemoveTrack(e,d),i.shimGetSendersWithDtmf(e,d),i.shimSenderReceiverGetStats(e,d),i.fixNegotiationNeeded(e,d),c.shimRTCIceCandidate(e,d),c.shimRTCIceCandidateRelayProtocol(e,d),c.shimConnectionState(e,d),c.shimMaxMessageSize(e,d),c.shimSendThrowTypeError(e,d),c.removeExtmapAllowMixed(e,d);break;case"firefox":if(!o||!o.shimPeerConnection||!t.shimFirefox)return n("Firefox shim is not included in this adapter release."),u;n("adapter.js shimming firefox."),u.browserShim=o,c.shimAddIceCandidateNullOrEmpty(e,d),c.shimParameterlessSetLocalDescription(e,d),s.Z(e,d),o.shimPeerConnection(e,d),o.shimGetStats(e,d),o.shimOnTrack(e,d),o.shimRemoveStream(e,d),o.shimSenderGetStats(e,d),o.shimReceiverGetStats(e,d),o.shimRTCDataChannel(e,d),o.shimAddTransceiver(e,d),o.shimGetParameters(e,d),o.shimCreateOffer(e,d),o.shimCreateAnswer(e,d),c.shimRTCIceCandidate(e,d),c.shimConnectionState(e,d),c.shimMaxMessageSize(e,d),c.shimSendThrowTypeError(e,d);break;case"safari":if(!a||!t.shimSafari)return n("Safari shim is not included in this adapter release."),u;n("adapter.js shimming safari."),u.browserShim=a,c.shimAddIceCandidateNullOrEmpty(e,d),c.shimParameterlessSetLocalDescription(e,d),a.shimRTCIceServerUrls(e,d),a.shimCreateOfferLegacy(e,d),a.shimCallbacksAPI(e,d),a.shimLocalStreamsAPI(e,d),a.shimRemoteStreamsAPI(e,d),a.shimTrackEventTransceiver(e,d),a.shimGetUserMedia(e,d),a.shimAudioContext(e,d),c.shimRTCIceCandidate(e,d),c.shimRTCIceCandidateRelayProtocol(e,d),c.shimMaxMessageSize(e,d),c.shimSendThrowTypeError(e,d),c.removeExtmapAllowMixed(e,d);break;default:n("Unsupported browser!")}return u}},4002:function(e,t,n){n.r(t),n.d(t,{fixNegotiationNeeded:function(){return m},shimAddTrackRemoveTrack:function(){return d},shimAddTrackRemoveTrackWithNative:function(){return p},shimGetSendersWithDtmf:function(){return a},shimGetUserMedia:function(){return i.Z},shimMediaStream:function(){return o},shimOnTrack:function(){return s},shimPeerConnection:function(){return u},shimSenderReceiverGetStats:function(){return c}});var r=n(5432),i=n(8371);function o(e){e.MediaStream=e.MediaStream||e.webkitMediaStream}function s(e,t){if(!(t.version>102))if("object"==typeof e&&e.RTCPeerConnection&&!("ontrack"in e.RTCPeerConnection.prototype)){Object.defineProperty(e.RTCPeerConnection.prototype,"ontrack",{get(){return this._ontrack},set(e){this._ontrack&&this.removeEventListener("track",this._ontrack),this.addEventListener("track",this._ontrack=e)},enumerable:!0,configurable:!0});const t=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){return this._ontrackpoly||(this._ontrackpoly=t=>{t.stream.addEventListener("addtrack",n=>{let r;r=e.RTCPeerConnection.prototype.getReceivers?this.getReceivers().find(e=>e.track&&e.track.id===n.track.id):{track:n.track};const i=new Event("track");i.track=n.track,i.receiver=r,i.transceiver={receiver:r},i.streams=[t.stream],this.dispatchEvent(i)}),t.stream.getTracks().forEach(n=>{let r;r=e.RTCPeerConnection.prototype.getReceivers?this.getReceivers().find(e=>e.track&&e.track.id===n.id):{track:n};const i=new Event("track");i.track=n,i.receiver=r,i.transceiver={receiver:r},i.streams=[t.stream],this.dispatchEvent(i)})},this.addEventListener("addstream",this._ontrackpoly)),t.apply(this,arguments)}}else r.V1(e,"track",e=>(e.transceiver||Object.defineProperty(e,"transceiver",{value:{receiver:e.receiver}}),e))}function a(e){if("object"==typeof e&&e.RTCPeerConnection&&!("getSenders"in e.RTCPeerConnection.prototype)&&"createDTMFSender"in e.RTCPeerConnection.prototype){const t=function(e,t){return{track:t,get dtmf(){return void 0===this._dtmf&&("audio"===t.kind?this._dtmf=e.createDTMFSender(t):this._dtmf=null),this._dtmf},_pc:e}};if(!e.RTCPeerConnection.prototype.getSenders){e.RTCPeerConnection.prototype.getSenders=function(){return this._senders=this._senders||[],this._senders.slice()};const n=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addTrack=function(e,r){let i=n.apply(this,arguments);return i||(i=t(this,e),this._senders.push(i)),i};const r=e.RTCPeerConnection.prototype.removeTrack;e.RTCPeerConnection.prototype.removeTrack=function(e){r.apply(this,arguments);const t=this._senders.indexOf(e);-1!==t&&this._senders.splice(t,1)}}const n=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(e){this._senders=this._senders||[],n.apply(this,[e]),e.getTracks().forEach(e=>{this._senders.push(t(this,e))})};const r=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){this._senders=this._senders||[],r.apply(this,[e]),e.getTracks().forEach(e=>{const t=this._senders.find(t=>t.track===e);t&&this._senders.splice(this._senders.indexOf(t),1)})}}else if("object"==typeof e&&e.RTCPeerConnection&&"getSenders"in e.RTCPeerConnection.prototype&&"createDTMFSender"in e.RTCPeerConnection.prototype&&e.RTCRtpSender&&!("dtmf"in e.RTCRtpSender.prototype)){const t=e.RTCPeerConnection.prototype.getSenders;e.RTCPeerConnection.prototype.getSenders=function(){const e=t.apply(this,[]);return e.forEach(e=>e._pc=this),e},Object.defineProperty(e.RTCRtpSender.prototype,"dtmf",{get(){return void 0===this._dtmf&&("audio"===this.track.kind?this._dtmf=this._pc.createDTMFSender(this.track):this._dtmf=null),this._dtmf}})}}function c(e,t){if(t.version>=67)return;if(!("object"==typeof e&&e.RTCPeerConnection&&e.RTCRtpSender&&e.RTCRtpReceiver))return;if(!("getStats"in e.RTCRtpSender.prototype)){const t=e.RTCPeerConnection.prototype.getSenders;t&&(e.RTCPeerConnection.prototype.getSenders=function(){const e=t.apply(this,[]);return e.forEach(e=>e._pc=this),e});const n=e.RTCPeerConnection.prototype.addTrack;n&&(e.RTCPeerConnection.prototype.addTrack=function(){const e=n.apply(this,arguments);return e._pc=this,e}),e.RTCRtpSender.prototype.getStats=function(){const e=this;return this._pc.getStats().then(t=>r.sc(t,e.track,!0))}}if(!("getStats"in e.RTCRtpReceiver.prototype)){const t=e.RTCPeerConnection.prototype.getReceivers;t&&(e.RTCPeerConnection.prototype.getReceivers=function(){const e=t.apply(this,[]);return e.forEach(e=>e._pc=this),e}),r.V1(e,"track",e=>(e.receiver._pc=e.srcElement,e)),e.RTCRtpReceiver.prototype.getStats=function(){const e=this;return this._pc.getStats().then(t=>r.sc(t,e.track,!1))}}if(!("getStats"in e.RTCRtpSender.prototype)||!("getStats"in e.RTCRtpReceiver.prototype))return;const n=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){if(arguments.length>0&&arguments[0]instanceof e.MediaStreamTrack){const e=arguments[0];let t,n,r;return this.getSenders().forEach(n=>{n.track===e&&(t?r=!0:t=n)}),this.getReceivers().forEach(t=>(t.track===e&&(n?r=!0:n=t),t.track===e)),r||t&&n?Promise.reject(new DOMException("There are more than one sender or receiver for the track.","InvalidAccessError")):t?t.getStats():n?n.getStats():Promise.reject(new DOMException("There is no sender or receiver for the track.","InvalidAccessError"))}return n.apply(this,arguments)}}function p(e){e.RTCPeerConnection.prototype.getLocalStreams=function(){return this._shimmedLocalStreams=this._shimmedLocalStreams||{},Object.keys(this._shimmedLocalStreams).map(e=>this._shimmedLocalStreams[e][0])};const t=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addTrack=function(e,n){if(!n)return t.apply(this,arguments);this._shimmedLocalStreams=this._shimmedLocalStreams||{};const r=t.apply(this,arguments);return this._shimmedLocalStreams[n.id]?-1===this._shimmedLocalStreams[n.id].indexOf(r)&&this._shimmedLocalStreams[n.id].push(r):this._shimmedLocalStreams[n.id]=[n,r],r};const n=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(e){this._shimmedLocalStreams=this._shimmedLocalStreams||{},e.getTracks().forEach(e=>{if(this.getSenders().find(t=>t.track===e))throw new DOMException("Track already exists.","InvalidAccessError")});const t=this.getSenders();n.apply(this,arguments);const r=this.getSenders().filter(e=>-1===t.indexOf(e));this._shimmedLocalStreams[e.id]=[e].concat(r)};const r=e.RTCPeerConnection.prototype.removeStream;e.RTCPeerConnection.prototype.removeStream=function(e){return this._shimmedLocalStreams=this._shimmedLocalStreams||{},delete this._shimmedLocalStreams[e.id],r.apply(this,arguments)};const i=e.RTCPeerConnection.prototype.removeTrack;e.RTCPeerConnection.prototype.removeTrack=function(e){return this._shimmedLocalStreams=this._shimmedLocalStreams||{},e&&Object.keys(this._shimmedLocalStreams).forEach(t=>{const n=this._shimmedLocalStreams[t].indexOf(e);-1!==n&&this._shimmedLocalStreams[t].splice(n,1),1===this._shimmedLocalStreams[t].length&&delete this._shimmedLocalStreams[t]}),i.apply(this,arguments)}}function d(e,t){if(!e.RTCPeerConnection)return;if(e.RTCPeerConnection.prototype.addTrack&&t.version>=65)return p(e);const n=e.RTCPeerConnection.prototype.getLocalStreams;e.RTCPeerConnection.prototype.getLocalStreams=function(){const e=n.apply(this);return this._reverseStreams=this._reverseStreams||{},e.map(e=>this._reverseStreams[e.id])};const r=e.RTCPeerConnection.prototype.addStream;e.RTCPeerConnection.prototype.addStream=function(t){if(this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},t.getTracks().forEach(e=>{if(this.getSenders().find(t=>t.track===e))throw new DOMException("Track already exists.","InvalidAccessError")}),!this._reverseStreams[t.id]){const n=new e.MediaStream(t.getTracks());this._streams[t.id]=n,this._reverseStreams[n.id]=t,t=n}r.apply(this,[t])};const i=e.RTCPeerConnection.prototype.removeStream;function o(e,t){let n=t.sdp;return Object.keys(e._reverseStreams||[]).forEach(t=>{const r=e._reverseStreams[t],i=e._streams[r.id];n=n.replace(new RegExp(i.id,"g"),r.id)}),new RTCSessionDescription({type:t.type,sdp:n})}e.RTCPeerConnection.prototype.removeStream=function(e){this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{},i.apply(this,[this._streams[e.id]||e]),delete this._reverseStreams[this._streams[e.id]?this._streams[e.id].id:e.id],delete this._streams[e.id]},e.RTCPeerConnection.prototype.addTrack=function(t,n){if("closed"===this.signalingState)throw new DOMException("The RTCPeerConnection's signalingState is 'closed'.","InvalidStateError");const r=[].slice.call(arguments,1);if(1!==r.length||!r[0].getTracks().find(e=>e===t))throw new DOMException("The adapter.js addTrack polyfill only supports a single stream which is associated with the specified track.","NotSupportedError");if(this.getSenders().find(e=>e.track===t))throw new DOMException("Track already exists.","InvalidAccessError");this._streams=this._streams||{},this._reverseStreams=this._reverseStreams||{};const i=this._streams[n.id];if(i)i.addTrack(t),Promise.resolve().then(()=>{this.dispatchEvent(new Event("negotiationneeded"))});else{const r=new e.MediaStream([t]);this._streams[n.id]=r,this._reverseStreams[r.id]=n,this.addStream(r)}return this.getSenders().find(e=>e.track===t)},["createOffer","createAnswer"].forEach(function(t){const n=e.RTCPeerConnection.prototype[t],r={[t](){const e=arguments;return arguments.length&&"function"==typeof arguments[0]?n.apply(this,[t=>{const n=o(this,t);e[0].apply(null,[n])},t=>{e[1]&&e[1].apply(null,t)},arguments[2]]):n.apply(this,arguments).then(e=>o(this,e))}};e.RTCPeerConnection.prototype[t]=r[t]});const s=e.RTCPeerConnection.prototype.setLocalDescription;e.RTCPeerConnection.prototype.setLocalDescription=function(){return arguments.length&&arguments[0].type?(arguments[0]=function(e,t){let n=t.sdp;return Object.keys(e._reverseStreams||[]).forEach(t=>{const r=e._reverseStreams[t],i=e._streams[r.id];n=n.replace(new RegExp(r.id,"g"),i.id)}),new RTCSessionDescription({type:t.type,sdp:n})}(this,arguments[0]),s.apply(this,arguments)):s.apply(this,arguments)};const a=Object.getOwnPropertyDescriptor(e.RTCPeerConnection.prototype,"localDescription");Object.defineProperty(e.RTCPeerConnection.prototype,"localDescription",{get(){const e=a.get.apply(this);return""===e.type?e:o(this,e)}}),e.RTCPeerConnection.prototype.removeTrack=function(e){if("closed"===this.signalingState)throw new DOMException("The RTCPeerConnection's signalingState is 'closed'.","InvalidStateError");if(!e._pc)throw new DOMException("Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.","TypeError");if(e._pc!==this)throw new DOMException("Sender was not created by this connection.","InvalidAccessError");let t;this._streams=this._streams||{},Object.keys(this._streams).forEach(n=>{this._streams[n].getTracks().find(t=>e.track===t)&&(t=this._streams[n])}),t&&(1===t.getTracks().length?this.removeStream(this._reverseStreams[t.id]):t.removeTrack(e.track),this.dispatchEvent(new Event("negotiationneeded")))}}function u(e,t){!e.RTCPeerConnection&&e.webkitRTCPeerConnection&&(e.RTCPeerConnection=e.webkitRTCPeerConnection),e.RTCPeerConnection&&t.version<53&&["setLocalDescription","setRemoteDescription","addIceCandidate"].forEach(function(t){const n=e.RTCPeerConnection.prototype[t],r={[t](){return arguments[0]=new("addIceCandidate"===t?e.RTCIceCandidate:e.RTCSessionDescription)(arguments[0]),n.apply(this,arguments)}};e.RTCPeerConnection.prototype[t]=r[t]})}function m(e,t){t.version>102||r.V1(e,"negotiationneeded",e=>{const n=e.target;if(!(t.version<72||n.getConfiguration&&"plan-b"===n.getConfiguration().sdpSemantics)||"stable"===n.signalingState)return e})}},8371:function(e,t,n){n.d(t,{Z:function(){return i}});const r=n(5432).Rm;function i(e,t){const n=e&&e.navigator;if(!n.mediaDevices)return;const i=function(e){if("object"!=typeof e||e.mandatory||e.optional)return e;const t={};return Object.keys(e).forEach(n=>{if("require"===n||"advanced"===n||"mediaSource"===n)return;const r="object"==typeof e[n]?e[n]:{ideal:e[n]};void 0!==r.exact&&"number"==typeof r.exact&&(r.min=r.max=r.exact);const i=function(e,t){return e?e+t.charAt(0).toUpperCase()+t.slice(1):"deviceId"===t?"sourceId":t};if(void 0!==r.ideal){t.optional=t.optional||[];let e={};"number"==typeof r.ideal?(e[i("min",n)]=r.ideal,t.optional.push(e),e={},e[i("max",n)]=r.ideal,t.optional.push(e)):(e[i("",n)]=r.ideal,t.optional.push(e))}void 0!==r.exact&&"number"!=typeof r.exact?(t.mandatory=t.mandatory||{},t.mandatory[i("",n)]=r.exact):["min","max"].forEach(e=>{void 0!==r[e]&&(t.mandatory=t.mandatory||{},t.mandatory[i(e,n)]=r[e])})}),e.advanced&&(t.optional=(t.optional||[]).concat(e.advanced)),t},o=function(e,o){if(t.version>=61)return o(e);if((e=JSON.parse(JSON.stringify(e)))&&"object"==typeof e.audio){const t=function(e,t,n){t in e&&!(n in e)&&(e[n]=e[t],delete e[t])};t((e=JSON.parse(JSON.stringify(e))).audio,"autoGainControl","googAutoGainControl"),t(e.audio,"noiseSuppression","googNoiseSuppression"),e.audio=i(e.audio)}if(e&&"object"==typeof e.video){let s=e.video.facingMode;s=s&&("object"==typeof s?s:{ideal:s});const a=t.version<66;if(s&&("user"===s.exact||"environment"===s.exact||"user"===s.ideal||"environment"===s.ideal)&&(!n.mediaDevices.getSupportedConstraints||!n.mediaDevices.getSupportedConstraints().facingMode||a)){let t;if(delete e.video.facingMode,"environment"===s.exact||"environment"===s.ideal?t=["back","rear"]:"user"!==s.exact&&"user"!==s.ideal||(t=["front"]),t)return n.mediaDevices.enumerateDevices().then(n=>{let a=(n=n.filter(e=>"videoinput"===e.kind)).find(e=>t.some(t=>e.label.toLowerCase().includes(t)));return!a&&n.length&&t.includes("back")&&(a=n[n.length-1]),a&&(e.video.deviceId=s.exact?{exact:a.deviceId}:{ideal:a.deviceId}),e.video=i(e.video),r("chrome: "+JSON.stringify(e)),o(e)})}e.video=i(e.video)}return r("chrome: "+JSON.stringify(e)),o(e)},s=function(e){return t.version>=64?e:{name:{PermissionDeniedError:"NotAllowedError",PermissionDismissedError:"NotAllowedError",InvalidStateError:"NotAllowedError",DevicesNotFoundError:"NotFoundError",ConstraintNotSatisfiedError:"OverconstrainedError",TrackStartError:"NotReadableError",MediaDeviceFailedDueToShutdown:"NotAllowedError",MediaDeviceKillSwitchOn:"NotAllowedError",TabCaptureError:"AbortError",ScreenCaptureError:"AbortError",DeviceCaptureError:"AbortError"}[e.name]||e.name,message:e.message,constraint:e.constraint||e.constraintName,toString(){return this.name+(this.message&&": ")+this.message}}};if(n.getUserMedia=function(e,t,r){o(e,e=>{n.webkitGetUserMedia(e,t,e=>{r&&r(s(e))})})}.bind(n),n.mediaDevices.getUserMedia){const e=n.mediaDevices.getUserMedia.bind(n.mediaDevices);n.mediaDevices.getUserMedia=function(t){return o(t,t=>e(t).then(e=>{if(t.audio&&!e.getAudioTracks().length||t.video&&!e.getVideoTracks().length)throw e.getTracks().forEach(e=>{e.stop()}),new DOMException("","NotFoundError");return e},e=>Promise.reject(s(e))))}}}},6298:function(e,t,n){n.r(t),n.d(t,{removeExtmapAllowMixed:function(){return u},shimAddIceCandidateNullOrEmpty:function(){return m},shimConnectionState:function(){return d},shimMaxMessageSize:function(){return c},shimParameterlessSetLocalDescription:function(){return h},shimRTCIceCandidate:function(){return s},shimRTCIceCandidateRelayProtocol:function(){return a},shimSendThrowTypeError:function(){return p}});var r=n(1757),i=n.n(r),o=n(5432);function s(e){if(!e.RTCIceCandidate||e.RTCIceCandidate&&"foundation"in e.RTCIceCandidate.prototype)return;const t=e.RTCIceCandidate;e.RTCIceCandidate=function(e){if("object"==typeof e&&e.candidate&&0===e.candidate.indexOf("a=")&&((e=JSON.parse(JSON.stringify(e))).candidate=e.candidate.substring(2)),e.candidate&&e.candidate.length){const n=new t(e),r=i().parseCandidate(e.candidate);for(const e in r)e in n||Object.defineProperty(n,e,{value:r[e]});return n.toJSON=function(){return{candidate:n.candidate,sdpMid:n.sdpMid,sdpMLineIndex:n.sdpMLineIndex,usernameFragment:n.usernameFragment}},n}return new t(e)},e.RTCIceCandidate.prototype=t.prototype,o.V1(e,"icecandidate",t=>(t.candidate&&Object.defineProperty(t,"candidate",{value:new e.RTCIceCandidate(t.candidate),writable:"false"}),t))}function a(e){!e.RTCIceCandidate||e.RTCIceCandidate&&"relayProtocol"in e.RTCIceCandidate.prototype||o.V1(e,"icecandidate",e=>{if(e.candidate){const t=i().parseCandidate(e.candidate.candidate);"relay"===t.type&&(e.candidate.relayProtocol={0:"tls",1:"tcp",2:"udp"}[t.priority>>24])}return e})}function c(e,t){if(!e.RTCPeerConnection)return;"sctp"in e.RTCPeerConnection.prototype||Object.defineProperty(e.RTCPeerConnection.prototype,"sctp",{get(){return void 0===this._sctp?null:this._sctp}});const n=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){if(this._sctp=null,"chrome"===t.browser&&t.version>=76){const{sdpSemantics:e}=this.getConfiguration();"plan-b"===e&&Object.defineProperty(this,"sctp",{get(){return void 0===this._sctp?null:this._sctp},enumerable:!0,configurable:!0})}if(function(e){if(!e||!e.sdp)return!1;const t=i().splitSections(e.sdp);return t.shift(),t.some(e=>{const t=i().parseMLine(e);return t&&"application"===t.kind&&-1!==t.protocol.indexOf("SCTP")})}(arguments[0])){const e=function(e){const t=e.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);if(null===t||t.length<2)return-1;const n=parseInt(t[1],10);return n!=n?-1:n}(arguments[0]),n=function(e){let n=65536;return"firefox"===t.browser&&(n=t.version<57?-1===e?16384:2147483637:t.version<60?57===t.version?65535:65536:2147483637),n}(e),r=function(e,n){let r=65536;"firefox"===t.browser&&57===t.version&&(r=65535);const o=i().matchPrefix(e.sdp,"a=max-message-size:");return o.length>0?r=parseInt(o[0].substring(19),10):"firefox"===t.browser&&-1!==n&&(r=2147483637),r}(arguments[0],e);let o;o=0===n&&0===r?Number.POSITIVE_INFINITY:0===n||0===r?Math.max(n,r):Math.min(n,r);const s={};Object.defineProperty(s,"maxMessageSize",{get(){return o}}),this._sctp=s}return n.apply(this,arguments)}}function p(e,t){if(!e.RTCPeerConnection||!("createDataChannel"in e.RTCPeerConnection.prototype))return;if("chrome"===t.browser&&t.version>149)return;if("firefox"===t.browser&&t.version>60)return;function n(e,t){const n=e.send;e.send=function(){const r=arguments[0],i=r.length||r.size||r.byteLength;if("open"===e.readyState&&t.sctp&&i>t.sctp.maxMessageSize)throw new TypeError("Message too large (can send a maximum of "+t.sctp.maxMessageSize+" bytes)");return n.apply(e,arguments)}}const r=e.RTCPeerConnection.prototype.createDataChannel;e.RTCPeerConnection.prototype.createDataChannel=function(){const e=r.apply(this,arguments);return n(e,this),e},o.V1(e,"datachannel",e=>(n(e.channel,e.target),e))}function d(e){if(!e.RTCPeerConnection||"connectionState"in e.RTCPeerConnection.prototype)return;const t=e.RTCPeerConnection.prototype;Object.defineProperty(t,"connectionState",{get(){return{completed:"connected",checking:"connecting"}[this.iceConnectionState]||this.iceConnectionState},enumerable:!0,configurable:!0}),Object.defineProperty(t,"onconnectionstatechange",{get(){return this._onconnectionstatechange||null},set(e){this._onconnectionstatechange&&(this.removeEventListener("connectionstatechange",this._onconnectionstatechange),delete this._onconnectionstatechange),e&&this.addEventListener("connectionstatechange",this._onconnectionstatechange=e)},enumerable:!0,configurable:!0}),["setLocalDescription","setRemoteDescription"].forEach(e=>{const n=t[e];t[e]=function(){return this._connectionstatechangepoly||(this._connectionstatechangepoly=e=>{const t=e.target;if(t._lastConnectionState!==t.connectionState){t._lastConnectionState=t.connectionState;const n=new Event("connectionstatechange",e);t.dispatchEvent(n)}return e},this.addEventListener("iceconnectionstatechange",this._connectionstatechangepoly)),n.apply(this,arguments)}})}function u(e,t){if(!e.RTCPeerConnection)return;if("chrome"===t.browser&&t.version>=71)return;if("safari"===t.browser&&t._safariVersion>=13.1)return;const n=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(t){if(t&&t.sdp&&-1!==t.sdp.indexOf("\na=extmap-allow-mixed")){const n=t.sdp.split("\n").filter(e=>"a=extmap-allow-mixed"!==e.trim()).join("\n");e.RTCSessionDescription&&t instanceof e.RTCSessionDescription?arguments[0]=new e.RTCSessionDescription({type:t.type,sdp:n}):t.sdp=n}return n.apply(this,arguments)}}function m(e,t){if(!e.RTCPeerConnection||!e.RTCPeerConnection.prototype)return;const n=e.RTCPeerConnection.prototype.addIceCandidate;n&&0!==n.length&&(e.RTCPeerConnection.prototype.addIceCandidate=function(){return arguments[0]?("chrome"===t.browser&&t.version<78||"firefox"===t.browser&&t.version<68||"safari"===t.browser)&&arguments[0]&&""===arguments[0].candidate?Promise.resolve():n.apply(this,arguments):(arguments[1]&&arguments[1].apply(null),Promise.resolve())})}function h(e,t){if(!e.RTCPeerConnection||!e.RTCPeerConnection.prototype)return;const n=e.RTCPeerConnection.prototype.setLocalDescription;n&&0!==n.length&&(e.RTCPeerConnection.prototype.setLocalDescription=function(){let e=arguments[0]||{};if("object"!=typeof e||e.type&&e.sdp)return n.apply(this,arguments);if(e={type:e.type,sdp:e.sdp},!e.type)switch(this.signalingState){case"stable":case"have-local-offer":case"have-remote-pranswer":e.type="offer";break;default:e.type="answer"}return e.sdp||"offer"!==e.type&&"answer"!==e.type?n.apply(this,[e]):("offer"===e.type?this.createOffer:this.createAnswer).apply(this).then(e=>n.apply(this,[e]))})}},6504:function(e,t,n){n.r(t),n.d(t,{shimAddTransceiver:function(){return h},shimCreateAnswer:function(){return C},shimCreateOffer:function(){return l},shimGetDisplayMedia:function(){return o.a},shimGetParameters:function(){return f},shimGetStats:function(){return c},shimGetUserMedia:function(){return i.Z},shimOnTrack:function(){return s},shimPeerConnection:function(){return a},shimRTCDataChannel:function(){return m},shimReceiverGetStats:function(){return d},shimRemoveStream:function(){return u},shimSenderGetStats:function(){return p}});var r=n(5432),i=n(4054),o=n(9297);function s(e){"object"==typeof e&&e.RTCTrackEvent&&"receiver"in e.RTCTrackEvent.prototype&&!("transceiver"in e.RTCTrackEvent.prototype)&&Object.defineProperty(e.RTCTrackEvent.prototype,"transceiver",{get(){return{receiver:this.receiver}}})}function a(e,t){"object"==typeof e&&(e.RTCPeerConnection||e.mozRTCPeerConnection)&&(!e.RTCPeerConnection&&e.mozRTCPeerConnection&&(e.RTCPeerConnection=e.mozRTCPeerConnection),t.version<53&&["setLocalDescription","setRemoteDescription","addIceCandidate"].forEach(function(t){const n=e.RTCPeerConnection.prototype[t],r={[t](){return arguments[0]=new("addIceCandidate"===t?e.RTCIceCandidate:e.RTCSessionDescription)(arguments[0]),n.apply(this,arguments)}};e.RTCPeerConnection.prototype[t]=r[t]}))}function c(e,t){if("object"!=typeof e||!e.RTCPeerConnection&&!e.mozRTCPeerConnection)return;if(t.version>=151)return;const n={inboundrtp:"inbound-rtp",outboundrtp:"outbound-rtp",candidatepair:"candidate-pair",localcandidate:"local-candidate",remotecandidate:"remote-candidate"},r=e.RTCPeerConnection.prototype.getStats;e.RTCPeerConnection.prototype.getStats=function(){const[e,i,o]=arguments;return"closed"===this.signalingState?Promise.resolve(new Map):r.apply(this,[e||null]).then(e=>{if(t.version<53&&!i)try{e.forEach(e=>{e.type=n[e.type]||e.type})}catch(t){if("TypeError"!==t.name)throw t;e.forEach((t,r)=>{e.set(r,Object.assign({},t,{type:n[t.type]||t.type}))})}return e}).then(i,o)}}function p(e){if("object"!=typeof e||!e.RTCPeerConnection||!e.RTCRtpSender)return;if(e.RTCRtpSender&&"getStats"in e.RTCRtpSender.prototype)return;const t=e.RTCPeerConnection.prototype.getSenders;t&&(e.RTCPeerConnection.prototype.getSenders=function(){const e=t.apply(this,[]);return e.forEach(e=>e._pc=this),e});const n=e.RTCPeerConnection.prototype.addTrack;n&&(e.RTCPeerConnection.prototype.addTrack=function(){const e=n.apply(this,arguments);return e._pc=this,e}),e.RTCRtpSender.prototype.getStats=function(){return this.track?this._pc.getStats(this.track):Promise.resolve(new Map)}}function d(e){if("object"!=typeof e||!e.RTCPeerConnection||!e.RTCRtpSender)return;if(e.RTCRtpSender&&"getStats"in e.RTCRtpReceiver.prototype)return;const t=e.RTCPeerConnection.prototype.getReceivers;t&&(e.RTCPeerConnection.prototype.getReceivers=function(){const e=t.apply(this,[]);return e.forEach(e=>e._pc=this),e}),r.V1(e,"track",e=>(e.receiver._pc=e.srcElement,e)),e.RTCRtpReceiver.prototype.getStats=function(){return this._pc.getStats(this.track)}}function u(e){e.RTCPeerConnection&&!("removeStream"in e.RTCPeerConnection.prototype)&&(e.RTCPeerConnection.prototype.removeStream=function(e){r.io("removeStream","removeTrack"),this.getSenders().forEach(t=>{t.track&&e.getTracks().includes(t.track)&&this.removeTrack(t)})})}function m(e){e.DataChannel&&!e.RTCDataChannel&&(e.RTCDataChannel=e.DataChannel)}function h(e){if("object"!=typeof e||!e.RTCPeerConnection)return;const t=e.RTCPeerConnection.prototype.addTransceiver;t&&(e.RTCPeerConnection.prototype.addTransceiver=function(){this.setParametersPromises=[];let e=arguments[1]&&arguments[1].sendEncodings;void 0===e&&(e=[]),e=[...e];const n=e.length>0;n&&e.forEach(e=>{if("rid"in e&&!/^[a-z0-9]{0,16}$/i.test(e.rid))throw new TypeError("Invalid RID value provided.");if("scaleResolutionDownBy"in e&&!(parseFloat(e.scaleResolutionDownBy)>=1))throw new RangeError("scale_resolution_down_by must be >= 1.0");if("maxFramerate"in e&&!(parseFloat(e.maxFramerate)>=0))throw new RangeError("max_framerate must be >= 0.0")});const r=t.apply(this,arguments);if(n){const{sender:t}=r,n=t.getParameters();(!("encodings"in n)||1===n.encodings.length&&0===Object.keys(n.encodings[0]).length)&&(n.encodings=e,t.sendEncodings=e,this.setParametersPromises.push(t.setParameters(n).then(()=>{delete t.sendEncodings}).catch(()=>{delete t.sendEncodings})))}return r})}function f(e){if("object"!=typeof e||!e.RTCRtpSender)return;const t=e.RTCRtpSender.prototype.getParameters;t&&(e.RTCRtpSender.prototype.getParameters=function(){const e=t.apply(this,arguments);return"encodings"in e||(e.encodings=[].concat(this.sendEncodings||[{}])),e})}function l(e){if("object"!=typeof e||!e.RTCPeerConnection)return;const t=e.RTCPeerConnection.prototype.createOffer;e.RTCPeerConnection.prototype.createOffer=function(){return this.setParametersPromises&&this.setParametersPromises.length?Promise.all(this.setParametersPromises).then(()=>t.apply(this,arguments)).finally(()=>{this.setParametersPromises=[]}):t.apply(this,arguments)}}function C(e){if("object"!=typeof e||!e.RTCPeerConnection)return;const t=e.RTCPeerConnection.prototype.createAnswer;e.RTCPeerConnection.prototype.createAnswer=function(){return this.setParametersPromises&&this.setParametersPromises.length?Promise.all(this.setParametersPromises).then(()=>t.apply(this,arguments)).finally(()=>{this.setParametersPromises=[]}):t.apply(this,arguments)}}},9297:function(e,t,n){function r(e,t){e.navigator.mediaDevices&&"getDisplayMedia"in e.navigator.mediaDevices||e.navigator.mediaDevices&&(e.navigator.mediaDevices.getDisplayMedia=function(n){if(!n||!n.video){const e=new DOMException("getDisplayMedia without video constraints is undefined");return e.name="NotFoundError",e.code=8,Promise.reject(e)}return!0===n.video?n.video={mediaSource:t}:n.video.mediaSource=t,e.navigator.mediaDevices.getUserMedia(n)})}n.d(t,{a:function(){return r}})},4054:function(e,t,n){n.d(t,{Z:function(){return i}});var r=n(5432);function i(e,t){const n=e&&e.navigator,i=e&&e.MediaStreamTrack;if(n.getUserMedia=function(e,t,i){r.io("navigator.getUserMedia","navigator.mediaDevices.getUserMedia"),n.mediaDevices.getUserMedia(e).then(t,i)},!(t.version>55&&"autoGainControl"in n.mediaDevices.getSupportedConstraints())){const e=function(e,t,n){t in e&&!(n in e)&&(e[n]=e[t],delete e[t])},t=n.mediaDevices.getUserMedia.bind(n.mediaDevices);if(n.mediaDevices.getUserMedia=function(n){return"object"==typeof n&&"object"==typeof n.audio&&(n=JSON.parse(JSON.stringify(n)),e(n.audio,"autoGainControl","mozAutoGainControl"),e(n.audio,"noiseSuppression","mozNoiseSuppression")),t(n)},i&&i.prototype.getSettings){const t=i.prototype.getSettings;i.prototype.getSettings=function(){const n=t.apply(this,arguments);return e(n,"mozAutoGainControl","autoGainControl"),e(n,"mozNoiseSuppression","noiseSuppression"),n}}if(i&&i.prototype.applyConstraints){const t=i.prototype.applyConstraints;i.prototype.applyConstraints=function(n){return"audio"===this.kind&&"object"==typeof n&&(n=JSON.parse(JSON.stringify(n)),e(n,"autoGainControl","mozAutoGainControl"),e(n,"noiseSuppression","mozNoiseSuppression")),t.apply(this,[n])}}}}},1458:function(e,t,n){n.r(t),n.d(t,{shimAudioContext:function(){return m},shimCallbacksAPI:function(){return s},shimConstraints:function(){return c},shimCreateOfferLegacy:function(){return u},shimGetUserMedia:function(){return a},shimLocalStreamsAPI:function(){return i},shimRTCIceServerUrls:function(){return p},shimRemoteStreamsAPI:function(){return o},shimTrackEventTransceiver:function(){return d}});var r=n(5432);function i(e){if("object"==typeof e&&e.RTCPeerConnection){if("getLocalStreams"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.getLocalStreams=function(){return this._localStreams||(this._localStreams=[]),this._localStreams}),!("addStream"in e.RTCPeerConnection.prototype)){const t=e.RTCPeerConnection.prototype.addTrack;e.RTCPeerConnection.prototype.addStream=function(e){this._localStreams||(this._localStreams=[]),this._localStreams.includes(e)||this._localStreams.push(e),e.getAudioTracks().forEach(n=>t.call(this,n,e)),e.getVideoTracks().forEach(n=>t.call(this,n,e))},e.RTCPeerConnection.prototype.addTrack=function(e,...n){return n&&n.forEach(e=>{this._localStreams?this._localStreams.includes(e)||this._localStreams.push(e):this._localStreams=[e]}),t.apply(this,arguments)}}"removeStream"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.removeStream=function(e){this._localStreams||(this._localStreams=[]);const t=this._localStreams.indexOf(e);if(-1===t)return;this._localStreams.splice(t,1);const n=e.getTracks();this.getSenders().forEach(e=>{n.includes(e.track)&&this.removeTrack(e)})})}}function o(e){if("object"==typeof e&&e.RTCPeerConnection&&("getRemoteStreams"in e.RTCPeerConnection.prototype||(e.RTCPeerConnection.prototype.getRemoteStreams=function(){return this._remoteStreams?this._remoteStreams:[]}),!("onaddstream"in e.RTCPeerConnection.prototype))){Object.defineProperty(e.RTCPeerConnection.prototype,"onaddstream",{get(){return this._onaddstream},set(e){this._onaddstream&&(this.removeEventListener("addstream",this._onaddstream),this.removeEventListener("track",this._onaddstreampoly)),this.addEventListener("addstream",this._onaddstream=e),this.addEventListener("track",this._onaddstreampoly=e=>{e.streams.forEach(e=>{if(this._remoteStreams||(this._remoteStreams=[]),this._remoteStreams.includes(e))return;this._remoteStreams.push(e);const t=new Event("addstream");t.stream=e,this.dispatchEvent(t)})})}});const t=e.RTCPeerConnection.prototype.setRemoteDescription;e.RTCPeerConnection.prototype.setRemoteDescription=function(){const e=this;return this._onaddstreampoly||this.addEventListener("track",this._onaddstreampoly=function(t){t.streams.forEach(t=>{if(e._remoteStreams||(e._remoteStreams=[]),e._remoteStreams.indexOf(t)>=0)return;e._remoteStreams.push(t);const n=new Event("addstream");n.stream=t,e.dispatchEvent(n)})}),t.apply(e,arguments)}}}function s(e){if("object"!=typeof e||!e.RTCPeerConnection)return;const t=e.RTCPeerConnection.prototype,n=t.createOffer,r=t.createAnswer,i=t.setLocalDescription,o=t.setRemoteDescription,s=t.addIceCandidate;t.createOffer=function(e,t){const r=arguments.length>=2?arguments[2]:arguments[0],i=n.apply(this,[r]);return t?(i.then(e,t),Promise.resolve()):i},t.createAnswer=function(e,t){const n=arguments.length>=2?arguments[2]:arguments[0],i=r.apply(this,[n]);return t?(i.then(e,t),Promise.resolve()):i};let a=function(e,t,n){const r=i.apply(this,[e]);return n?(r.then(t,n),Promise.resolve()):r};t.setLocalDescription=a,a=function(e,t,n){const r=o.apply(this,[e]);return n?(r.then(t,n),Promise.resolve()):r},t.setRemoteDescription=a,a=function(e,t,n){const r=s.apply(this,[e]);return n?(r.then(t,n),Promise.resolve()):r},t.addIceCandidate=a}function a(e){const t=e&&e.navigator;if(t.mediaDevices&&t.mediaDevices.getUserMedia){const e=t.mediaDevices,n=e.getUserMedia.bind(e);t.mediaDevices.getUserMedia=e=>n(c(e))}!t.getUserMedia&&t.mediaDevices&&t.mediaDevices.getUserMedia&&(t.getUserMedia=function(e,n,r){t.mediaDevices.getUserMedia(e).then(n,r)}.bind(t))}function c(e){return e&&void 0!==e.video?Object.assign({},e,{video:r.BU(e.video)}):e}function p(e){if(!e.RTCPeerConnection)return;const t=e.RTCPeerConnection;e.RTCPeerConnection=function(e,n){if(e&&e.iceServers){const t=[];for(let n=0;n<e.iceServers.length;n++){let i=e.iceServers[n];void 0===i.urls&&i.url?(r.io("RTCIceServer.url","RTCIceServer.urls"),i=JSON.parse(JSON.stringify(i)),i.urls=i.url,delete i.url,t.push(i)):t.push(e.iceServers[n])}e.iceServers=t}return new t(e,n)},e.RTCPeerConnection.prototype=t.prototype,"generateCertificate"in t&&Object.defineProperty(e.RTCPeerConnection,"generateCertificate",{get(){return t.generateCertificate}})}function d(e){"object"==typeof e&&e.RTCTrackEvent&&"receiver"in e.RTCTrackEvent.prototype&&!("transceiver"in e.RTCTrackEvent.prototype)&&Object.defineProperty(e.RTCTrackEvent.prototype,"transceiver",{get(){return{receiver:this.receiver}}})}function u(e){const t=e.RTCPeerConnection.prototype.createOffer;e.RTCPeerConnection.prototype.createOffer=function(e){if(e){void 0!==e.offerToReceiveAudio&&(e.offerToReceiveAudio=!!e.offerToReceiveAudio);const t=this.getTransceivers().find(e=>"audio"===e.receiver.track.kind);!1===e.offerToReceiveAudio&&t?"sendrecv"===t.direction?t.setDirection?t.setDirection("sendonly"):t.direction="sendonly":"recvonly"===t.direction&&(t.setDirection?t.setDirection("inactive"):t.direction="inactive"):!0!==e.offerToReceiveAudio||t||this.addTransceiver("audio",{direction:"recvonly"}),void 0!==e.offerToReceiveVideo&&(e.offerToReceiveVideo=!!e.offerToReceiveVideo);const n=this.getTransceivers().find(e=>"video"===e.receiver.track.kind);!1===e.offerToReceiveVideo&&n?"sendrecv"===n.direction?n.setDirection?n.setDirection("sendonly"):n.direction="sendonly":"recvonly"===n.direction&&(n.setDirection?n.setDirection("inactive"):n.direction="inactive"):!0!==e.offerToReceiveVideo||n||this.addTransceiver("video",{direction:"recvonly"})}return t.apply(this,arguments)}}function m(e){"object"!=typeof e||e.AudioContext||(e.AudioContext=e.webkitAudioContext)}},5432:function(e,t,n){n.d(t,{BU:function(){return h},Gr:function(){return o},Rm:function(){return p},Rn:function(){return a},V1:function(){return s},cO:function(){return u},co:function(){return c},io:function(){return d},sc:function(){return l}});let r=!0,i=!0;function o(e,t,n){const r=e.match(t);return r&&r.length>=n&&parseFloat(r[n],10)}function s(e,t,n){if(!e.RTCPeerConnection)return;if(!Object.getOwnPropertyDescriptor(EventTarget.prototype,"addEventListener").writable)return void p("Unable to polyfill events");const r=e.RTCPeerConnection.prototype,i=r.addEventListener;r.addEventListener=function(e,r){if(e!==t)return i.apply(this,arguments);const o=e=>{const t=n(e);t&&(r.handleEvent?r.handleEvent(t):r(t))};return this._eventMap=this._eventMap||{},this._eventMap[t]||(this._eventMap[t]=new Map),this._eventMap[t].set(r,o),i.apply(this,[e,o])};const o=r.removeEventListener;r.removeEventListener=function(e,n){if(e!==t||!this._eventMap||!this._eventMap[t])return o.apply(this,arguments);if(!this._eventMap[t].has(n))return o.apply(this,arguments);const r=this._eventMap[t].get(n);return this._eventMap[t].delete(n),0===this._eventMap[t].size&&delete this._eventMap[t],0===Object.keys(this._eventMap).length&&delete this._eventMap,o.apply(this,[e,r])},Object.defineProperty(r,"on"+t,{get(){return this["_on"+t]},set(e){this["_on"+t]&&(this.removeEventListener(t,this["_on"+t]),delete this["_on"+t]),e&&this.addEventListener(t,this["_on"+t]=e)},enumerable:!0,configurable:!0})}function a(e){return"boolean"!=typeof e?new Error("Argument type: "+typeof e+". Please use a boolean."):(r=e,e?"adapter.js logging disabled":"adapter.js logging enabled")}function c(e){return"boolean"!=typeof e?new Error("Argument type: "+typeof e+". Please use a boolean."):(i=!e,"adapter.js deprecation warnings "+(e?"disabled":"enabled"))}function p(){if("object"==typeof window){if(r)return;"undefined"!=typeof console&&"function"==typeof console.log&&console.log.apply(console,arguments)}}function d(e,t){i&&console.warn(e+" is deprecated, please use "+t+" instead.")}function u(e){const t={browser:null,version:null};if(void 0===e||!e.navigator||!e.navigator.userAgent)return t.browser="Not a browser.",t;const{navigator:n}=e;if(n.userAgentData&&n.userAgentData.brands){const e=n.userAgentData.brands.find(e=>"Chromium"===e.brand);if(e)return{browser:"chrome",version:parseInt(e.version,10)}}if(n.mozGetUserMedia)t.browser="firefox",t.version=parseInt(o(n.userAgent,/Firefox\/(\d+)\./,1));else if(n.webkitGetUserMedia||!1===e.isSecureContext&&e.webkitRTCPeerConnection)t.browser="chrome",t.version=parseInt(o(n.userAgent,/Chrom(e|ium)\/(\d+)\./,2))||null;else{if(!e.RTCPeerConnection||!n.userAgent.match(/AppleWebKit\/(\d+)\./))return t.browser="Not a supported browser.",t;t.browser="safari",t.version=parseInt(o(n.userAgent,/AppleWebKit\/(\d+)\./,1)),t.supportsUnifiedPlan=e.RTCRtpTransceiver&&"currentDirection"in e.RTCRtpTransceiver.prototype,t._safariVersion=o(n.userAgent,/Version\/(\d+(\.?\d+))/,1)}return t}function m(e){return"[object Object]"===Object.prototype.toString.call(e)}function h(e){return m(e)?Object.keys(e).reduce(function(t,n){const r=m(e[n]),i=r?h(e[n]):e[n],o=r&&!Object.keys(i).length;return void 0===i||o?t:Object.assign(t,{[n]:i})},{}):e}function f(e,t,n){t&&!n.has(t.id)&&(n.set(t.id,t),Object.keys(t).forEach(r=>{r.endsWith("Id")?f(e,e.get(t[r]),n):r.endsWith("Ids")&&t[r].forEach(t=>{f(e,e.get(t),n)})}))}function l(e,t,n){const r=n?"outbound-rtp":"inbound-rtp",i=new Map;if(null===t)return i;const o=[];return e.forEach(e=>{"track"===e.type&&e.trackIdentifier===t.id&&o.push(e)}),o.forEach(t=>{e.forEach(n=>{n.type===r&&n.trackId===t.id&&f(e,n,i)})}),i}}}]);
|