@signalwire/web-components 4.0.0-dev-20260721161304 → 4.0.0-dev-20260722194940

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.
@@ -69,8 +69,8 @@
69
69
  `)}return n.join(`\r
70
70
  `)}function Jg(t,e=[],i=[]){return Zg(t,i,e)}function $g(t){return t.split(/(?=m=)/)}function Ac(t,e){var h;const i=t.split(/\r?\n/),r=i[0].split(" ");if(r.length<4)return t;const n=r.slice(3),s=new Map;for(const p of i){const v=/^a=rtpmap:(\d+)\s+([^\s/]+)/.exec(p);v&&s.set(v[1],v[2])}const a=e.map(p=>p.toUpperCase()),o=[],c=[];for(const p of n){const v=((h=s.get(p))==null?void 0:h.toUpperCase())??"";a.indexOf(v)>=0?o.push(p):c.push(p)}o.sort((p,v)=>{var A,R;const C=((A=s.get(p))==null?void 0:A.toUpperCase())??"",_=((R=s.get(v))==null?void 0:R.toUpperCase())??"";return a.indexOf(C)-a.indexOf(_)});const u=[...o,...c];return[[...r.slice(0,3),...u].join(" "),...i.slice(1)].join(`\r
71
71
  `)}function ef(t){const e=/a=rtpmap:(\d+)\s+opus\/48000/i.exec(t);return e?e[1]:null}function tf(t,e){let i=t;return i.includes("stereo=")||(i+=";stereo=1"),i.includes("sprop-stereo=")||(i+=";sprop-stereo=1"),i.includes("maxaveragebitrate=")||(i+=`;maxaveragebitrate=${e}`),i}const He=G();var rf=class extends se{constructor(t,e,i={}){super(),this.peerConnection=t,this.peerConnectionControllerNegotiating$=e,this.onicegatheringstatechangeHandler=()=>{const{iceGatheringState:r}=this.peerConnection;He.debug(`[ICEGatheringController] ICE gathering state changed to: ${r}`),r==="gathering"&&this._iceCandidatesState.next({state:"gathering",validSDP:!1})},this.onicecandidateHandler=r=>{He.debug("[ICEGatheringController] ICE candidate event received:",r.candidate),this.removeTimer("iceCandidateTimer"),r.candidate?this.iceCandidateTimer=setTimeout(()=>{this.peerConnection.iceGatheringState!=="complete"&&(He.warn("[ICEGatheringController] ICE candidate timeout, using current SDP"),this.handleICECandidateTimeout())},this.iceCandidateTimeout):(He.debug("[ICEGatheringController] ICE gathering completed: null candidate received"),this.removeTimer("iceGatheringTimer"),this.handleICEGatheringComplete())},this._iceCandidatesState=this.createBehaviorSubject({state:"new",validSDP:!1}),this.iceCandidateTimeout=i.iceCandidateTimeout??Co,this.iceGatheringTimeout=i.iceGatheringTimeout??Ao,this.relayOnly=i.relayOnly??!1,this.setupEventListeners(),this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe(B(r=>r)),r=>{r&&(this.setupEventListeners(),this.iceGatheringTimer=setTimeout(()=>{this.peerConnection.iceGatheringState!=="complete"&&(He.warn("[ICEGatheringController] ICE gathering timeout, using current SDP"),this.handleICEGatheringTimeout())},this.iceGatheringTimeout))})}setupEventListeners(){this.peerConnection.removeEventListener("icecandidate",this.onicecandidateHandler),this.peerConnection.addEventListener("icecandidate",this.onicecandidateHandler),this.peerConnection.removeEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.addEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler)}get iceCandidatesState$(){return this._iceCandidatesState.pipe(yo(this.peerConnectionControllerNegotiating$),B(([t,e])=>e),x(([t,e])=>t.state))}get hasValidLocalDescriptionSDP(){var e;const t=(e=this.peerConnection.localDescription)==null?void 0:e.sdp;return Cc(t??"")}get isRelayOnly(){return this.relayOnly}setRelayOnly(t){this.relayOnly=t}handleICEGatheringComplete(){He.debug("[ICEGatheringController] Handling ICE gathering complete"),He.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`),He.debug("[ICEGatheringController] ICE gathering complete"),this._iceCandidatesState.next({state:"complete",validSDP:this.hasValidLocalDescriptionSDP}),this.stopGathering()}stopGathering(){this.peerConnection.removeEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.removeEventListener("icecandidate",this.onicecandidateHandler),this.clearAllTimers()}handleICEGatheringTimeout(){var e;this.removeTimer("iceGatheringTimer");const t=this.hasValidLocalDescriptionSDP;t?(He.debug("[ICEGatheringController] Local SDP is valid"),this._iceCandidatesState.next({state:"timeout",validSDP:t}),this.stopGathering()):He.debug(`### ICE gathering timeout
72
- `,(e=this.peerConnection.localDescription)==null?void 0:e.sdp)}handleICECandidateTimeout(){this.iceCandidateTimer&&this.removeTimer("iceCandidateTimer"),He.warn("[ICEGatheringController] ICE candidate timeout");const t=this.hasValidLocalDescriptionSDP;!t&&!this.relayOnly?this.restartICEGatheringWithRelayOnly():(He.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout"),this._iceCandidatesState.next({state:"timeout",validSDP:t}),this.stopGathering())}restartICEGatheringWithRelayOnly(){He.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates"),this.relayOnly=!0,this.peerConnection.setConfiguration({...this.peerConnection.getConfiguration(),iceTransportPolicy:"relay"}),this.peerConnection.restartIce()}removeTimer(t){this[t]&&(clearTimeout(this[t]),this[t]=void 0)}clearAllTimers(){He.debug("[ICEGatheringController] Clearing all timers"),this.removeTimer("iceGatheringTimer"),this.removeTimer("iceCandidateTimer")}removeEventListeners(){this.peerConnection.removeEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.removeEventListener("icecandidate",this.onicecandidateHandler)}destroy(){He.debug("[ICEGatheringController] Destroying ICEGatheringController"),this.clearAllTimers(),this.removeEventListeners(),super.destroy()}};const xs=G();var nf=class extends se{constructor(t={}){super(),this._inputSource=null,this._inputStream=null,this._lastSpokeAt=0,this._gain$=this.createBehaviorSubject(1),this._pttMultiplier=1,this._audioContext=(t.audioContextFactory??(()=>new AudioContext))(),this._gainNode=this._audioContext.createGain(),this._analyser=this._audioContext.createAnalyser(),this._analyser.fftSize=2048,this._analyser.smoothingTimeConstant=.3,this._analyserBuffer=new Uint8Array(new ArrayBuffer(this._analyser.fftSize)),this._destination=this._audioContext.createMediaStreamDestination(),this._gainNode.connect(this._analyser),this._analyser.connect(this._destination),this._speakingThreshold=t.speakingThreshold??Vh,this._speakingHoldMs=t.speakingHoldMs??Hh,this._pollIntervalMs=t.pollIntervalMs??Ro;const e=t.initialGain??1;this._gain$.next(e),this.applyEffectiveGain()}get gain$(){return this._gain$.asObservable()}get gain(){return this._gain$.value}get outputTrack(){const[t]=this._destination.stream.getAudioTracks();return t}get level$(){return this.deferEmission(en(this._pollIntervalMs,qa).pipe(x(()=>this.computeLevel())))}get speaking$(){return this.deferEmission(this.level$.pipe(x(t=>this.evaluateSpeaking(t)),U()))}setGain(t){const e=Math.max(0,Math.min(2,t));this._gain$.next(e),this.applyEffectiveGain()}setPTTActive(t){this._pttMultiplier=t?1:0,this.applyEffectiveGain()}applyEffectiveGain(){this._gainNode.gain.value=this._gain$.value*this._pttMultiplier}setInputTrack(t){if(this._inputSource){try{this._inputSource.disconnect()}catch(e){xs.debug("[LocalAudioPipeline] input disconnect warning:",e)}this._inputSource=null}this._inputStream&&(this._inputStream=null),t&&(this._inputStream=new MediaStream([t]),this._inputSource=this._audioContext.createMediaStreamSource(this._inputStream),this._inputSource.connect(this._gainNode),this._audioContext.state==="suspended"&&this._audioContext.resume().catch(e=>{xs.warn("[LocalAudioPipeline] AudioContext resume failed:",e)}))}destroy(){if(this._inputSource){try{this._inputSource.disconnect()}catch{}this._inputSource=null}try{this._gainNode.disconnect(),this._analyser.disconnect()}catch{}this._audioContext.close().catch(t=>{xs.debug("[LocalAudioPipeline] audio context close warning:",t)}),super.destroy()}computeLevel(){if(!this._inputSource)return 0;this._analyser.getByteTimeDomainData(this._analyserBuffer);let t=0;for(const e of this._analyserBuffer){const i=(e-128)/128;t+=i*i}return Math.sqrt(t/this._analyserBuffer.length)}evaluateSpeaking(t){const e=Date.now();return t>=this._speakingThreshold?(this._lastSpokeAt=e,!0):e-this._lastSpokeAt<this._speakingHoldMs}};const Nt=G();var sf=class extends se{constructor(t){super(),this.options=t,this.mediaTrackEndedHandler=e=>{this._mediaTrackEnded$.next(e)},this._localStream$=this.createBehaviorSubject(null),this._localAudioTracks$=this.createBehaviorSubject([]),this._localVideoTracks$=this.createBehaviorSubject([]),this._mediaTrackEnded$=this.createSubject()}get localStream$(){return this._localStream$.asObservable().pipe(S(this.destroyed$))}get localAudioTracks$(){return this._localAudioTracks$.asObservable().pipe(S(this.destroyed$))}get localVideoTracks$(){return this._localVideoTracks$.asObservable().pipe(S(this.destroyed$))}get mediaTrackEnded$(){return this._mediaTrackEnded$.asObservable().pipe(S(this.destroyed$))}get localStream(){return this._localStream$.value}get localAudioTracks(){return this._localAudioTracks$.value}get localVideoTracks(){return this._localVideoTracks$.value}async buildLocalStream(){var e,i;Nt.debug("[LocalStreamController] Building local media stream.");let t;if(this.options.inputAudioStream??this.options.inputVideoStream){const r=[...((e=this.options.inputAudioStream)==null?void 0:e.getTracks())??[],...((i=this.options.inputVideoStream)==null?void 0:i.getTracks())??[]];t=new MediaStream(r)}else if(this.options.propose==="screenshare")Nt.debug("[LocalStreamController] Requesting display media for screen sharing with audio:",!!this.options.inputAudioDeviceConstraints),t=await this.options.getDisplayMedia({video:!0,audio:!!this.options.inputAudioDeviceConstraints}),Nt.debug("[LocalStreamController] Screen share media obtained:",t);else{const r={audio:this.options.inputAudioDeviceConstraints,video:this.options.inputVideoDeviceConstraints};Nt.debug("[LocalStreamController] Requesting user media with constraints:",r),t=await this.options.getUserMedia(r),Nt.debug("[LocalStreamController] User media obtained:",t)}return this._localStream$.next(t),this._localAudioTracks$.next(t.getAudioTracks()),this._localVideoTracks$.next(t.getVideoTracks()),t}addTrack(t){const e=this._localStream$.value??new MediaStream;return t.addEventListener("ended",this.mediaTrackEndedHandler),e.addTrack(t),this._localStream$.next(e),t.kind==="video"?this._localVideoTracks$.next(e.getVideoTracks()):this._localAudioTracks$.next(e.getAudioTracks()),Nt.debug(`[LocalStreamController] ${t.kind} track added:`,t.id),e}removeTrack(t){const e=this._localStream$.value,i=e==null?void 0:e.getTracks().find(r=>r.id===t);if(!i){Nt.debug(`[LocalStreamController] track not found: ${t}`);return}return i.removeEventListener("ended",this.mediaTrackEndedHandler),e==null||e.removeTrack(i),i.stop(),this._localStream$.next(e),i.kind==="video"?this._localVideoTracks$.next((e==null?void 0:e.getVideoTracks())??[]):this._localAudioTracks$.next((e==null?void 0:e.getAudioTracks())??[]),Nt.debug(`[LocalStreamController] ${i.kind} track removed:`,t),i}getOrCreateLocalStream(){return this._localStream$.value??new MediaStream}setLocalStream(t){this._localStream$.next(t)}addTrackEndedListener(t){t.addEventListener("ended",this.mediaTrackEndedHandler)}updateOptions(t){this.options={...this.options,...t}}stopAllTracks(){var t;(t=this._localStream$.value)==null||t.getTracks().forEach(e=>{Nt.debug(`[LocalStreamController] Stopping local track: ${e.kind}`),e.removeEventListener("ended",this.mediaTrackEndedHandler),e.stop()})}destroy(){this.stopAllTracks(),super.destroy()}};const je=G(),Tc=(t,e)=>t&&e?"sendrecv":t&&!e?"sendonly":!t&&e?"recvonly":"inactive";var af=class extends se{constructor(t){super(),this.peerConnection=t.peerConnection,this.options=t}get useAddTransceivers(){return typeof this.peerConnection.addTransceiver=="function"}get useAddTrack(){return typeof this.peerConnection.addTrack=="function"}get useAddStream(){return typeof this.peerConnection.addStream=="function"&&!this.useAddTransceivers&&!this.useAddTrack}get propose(){return this.options.propose}get isAdditionalDevice(){return this.propose==="additional-device"}get isScreenShare(){return this.propose==="screenshare"}get isSimulcast(){return!!this.options.simulcast}get isSFU(){return!!this.options.sfu}get receiveVideo(){return!!this.options.receiveVideo}get receiveAudio(){return!!this.options.receiveAudio}get localStream(){return this.options.localStreamController.localStream}get inputAudioDeviceConstraints(){return this.options.getInputAudioDeviceConstraints()}get inputVideoDeviceConstraints(){return this.options.getInputVideoDeviceConstraints()}get audioDirection(){if(this.isAdditionalDevice)return"sendonly";const{localStream:t}=this,e=t==null?void 0:t.getAudioTracks().some(n=>n.enabled),i=!!this.inputAudioDeviceConstraints,r=!!this.receiveAudio;return Tc(e||i,r)}get videoDirection(){if(this.isAdditionalDevice||this.isScreenShare)return"sendonly";if(this.isSFU)return"recvonly";const{localStream:t}=this,e=t==null?void 0:t.getVideoTracks().some(n=>n.enabled),i=!!this.inputVideoDeviceConstraints,r=!!this.receiveVideo;return Tc(e||i,r)}get sendEncodings(){if(this.isSimulcast)return["0","1","2"].map(t=>({active:!0,rid:t,scaleResolutionDownBy:Number(t)*6||1}))}getConstraintsFor(t){const e=t==="audio"?this.inputAudioDeviceConstraints:this.inputVideoDeviceConstraints;return typeof e=="boolean"?{}:e}transceiverByKind(t){return this.peerConnection.getTransceivers().filter(e=>t==="both"||e.receiver.track.kind===t)}get audioTransceivers(){return this.transceiverByKind("audio")}get videoTransceivers(){return this.transceiverByKind("video")}async setupTransceiverSender(t,e,i){var a;const r=t.kind==="audio",n=r?this.audioDirection:this.videoDirection,s={direction:n,sendEncodings:r?void 0:this.sendEncodings,streams:n==="recvonly"?void 0:[e]};je.debug(`[TransceiverController] Setting up transceiver sender for local ${t.kind} track:`,{transceiver:i,transceiverParams:s}),s.direction&&["sendonly","sendrecv"].includes(s.direction)&&(i?(await i.sender.replaceTrack(t),i.direction=s.direction,(a=s.streams)!=null&&a.some(o=>!!o)&&(je.debug(`[TransceiverController] Setting streams for transceiver sender for local ${t.kind} track:`,s.streams),i.sender.setStreams(...s.streams))):(je.debug(`[TransceiverController] Adding new transceiver for local ${t.kind} track:`,t.id),this.peerConnection.addTransceiver(t,s)))}stopTrackSender(t,e={updateTransceiverDirection:!1}){var i,r,n;try{const s=this.transceiverByKind(t);for(const a of s)if(((i=a.sender.track)==null?void 0:i.readyState)==="live"){const o=a.sender.track.id;a.sender.track.stop(),this.options.localStreamController.removeTrack(o),e.updateTransceiverDirection&&(a.direction="inactive")}}catch(s){je.error("[TransceiverController] stopTrackSender error",t,s),(n=(r=this.options).onError)==null||n.call(r,new kt("stopTrackSender",t,s))}}async restoreTrackSender(t){var e,i;try{je.debug("[TransceiverController] restoreTrackSender called",t);const r={},n=this.transceiverByKind(t);for(const a of n){const{track:o}=a.sender;if(!o||o.readyState==="ended"){const c=(o==null?void 0:o.kind)??a.receiver.track.kind;(c==="audio"||c==="video")&&(r[c]=this.getConstraintsFor(c))}}if(je.debug("[TransceiverController] restoreTrackSender constraints:",r),Object.keys(r).length===0){je.warn("[TransceiverController] restoreTrackSender: no tracks need restoration",t);return}const s=(await this.options.getUserMedia(r)).getTracks();je.debug("[TransceiverController] restoreTrackSender new tracks:",s);for(const a of s){this.options.localStreamController.addTrack(a);const o=a.kind,c=this.transceiverByKind(o)[0];c.direction=o==="audio"?this.audioDirection:this.videoDirection,je.debug("[TransceiverController] restoreTrackSender setting direction for",o,c.direction),await c.sender.replaceTrack(a)}}catch(r){je.error("[TransceiverController] restoreTrackSender error",t,r),(i=(e=this.options).onError)==null||i.call(e,new kt("restoreTrackSender",t,r))}}async replaceSenderTrack(t,e){const i=t==="audio"?this.audioTransceivers:this.videoTransceivers;for(const r of i)await r.sender.replaceTrack(e)}async setupRemoteTransceivers(t){if(t!=="answer"){for(const e of["audio","video"]){const i=e==="audio"?this.audioTransceivers:this.videoTransceivers;for(const r of i){const n=e==="audio"?this.audioDirection:this.videoDirection;["inactive","recvonly"].includes(n)&&(r.direction=n,await r.sender.replaceTrack(null),r.sender.setStreams())}}if(this.videoDirection==="recvonly"&&this.isSFU&&this.useAddTransceivers){const{msStreamsNumber:e=5}=this.options;for(let i=0;i<Number(e);i++)this.peerConnection.addTransceiver("video",{direction:"recvonly"})}}}async updateSendersConstraints(t,e){var r,n;if(!e)return this.stopTrackSender(t),Promise.resolve();const i=this.peerConnection.getSenders().filter(s=>{var a;return((a=s.track)==null?void 0:a.kind)===t&&s.track.readyState==="live"});for(const s of i){const{track:a}=s;if(a){const o={...a.getConstraints(),...e};try{await a.applyConstraints(o),je.debug(`[TransceiverController] Updated ${t} sender constraints:`,o),je.debug(`[TransceiverController] Updated ${t} sender constraints:`,a.getConstraints())}catch(c){je.warn(`[TransceiverController] applyConstraints failed for ${t} track ${a.id}, attempting track replacement fallback:`,c);try{await this.replaceTrackFallback(s,a,t,o)}catch(u){je.warn(`[TransceiverController] Track replacement fallback also failed for ${t} track:`,u),(n=(r=this.options).onError)==null||n.call(r,new kt("updateSendersConstraints",t,u))}}}}}async replaceTrackFallback(t,e,i,r){const{deviceId:n}=e.getSettings(),s={...r,...n?{deviceId:{exact:n}}:{}},a=e.id;e.stop(),this.options.localStreamController.removeTrack(a);const o=(await this.options.getUserMedia({[i]:s})).getTracks().find(c=>c.kind===i);if(!o)throw new kt("replaceTrackFallback",i,new Error("getUserMedia returned no track of the requested kind"));await t.replaceTrack(o),this.options.localStreamController.addTrack(o),je.debug(`[TransceiverController] Track replacement fallback succeeded for ${i}. New track: ${o.id}`)}getMediaDirections(){return this.peerConnection.connectionState==="connected"?this.peerConnection.getTransceivers().reduce((t,e)=>({...t,[e.receiver.track.kind]:e.direction}),{audio:"inactive",video:"inactive"}):{audio:this.audioDirection,video:this.videoDirection}}updatePeerConnection(t){this.peerConnection=t}updateOptions(t){this.options={...this.options,...t}}};const z=G();var Ec=class extends se{constructor(t={},e,i){super(),this.options=t,this.firstSDPExchangeCompleted=!1,this.negotiationNeeded$=this.createSubject(),this.localDescription$=li(()=>_e(this.init())).pipe(Je(()=>this.iceGatheringController.iceCandidatesState$.pipe(B(n=>!["new","gathering"].includes(n)),Ee(()=>{this.negotiationEnded()}),B(()=>this.shouldEmitLocalDescription),x(()=>{var n;return(n=this.peerConnection)==null?void 0:n.localDescription}),ve(),Ee(n=>{n.type==="answer"&&(this._type="offer")}))),st(1),S(this.destroyed$)),this.connectionTimeout=3e3,this.oniceconnectionstatechangeHandler=()=>{if(this.peerConnection){const{iceConnectionState:n}=this.peerConnection;z.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${n}`),this._iceConnectionState$.next(this.peerConnection.iceConnectionState)}},this.onconnectionstatechangeHandler=()=>{if(this.peerConnection){const{connectionState:n}=this.peerConnection;z.debug(`[RTCPeerConnectionController] Connection state changed to: ${n}`),n==="connected"&&this.removeConnectionTimer(),this._connectionState$.next(this.peerConnection.connectionState)}},this.onsignalingstatechangeHandler=()=>{var n;z.debug(`[RTCPeerConnectionController] Signaling state changed to: ${(n=this.peerConnection)==null?void 0:n.signalingState}`)},this.onicegatheringstatechangeHandler=()=>{this.peerConnection&&this._iceGatheringState$.next(this.peerConnection.iceGatheringState)},this.onnegotiationneededHandler=n=>{z.debug("[RTCPeerConnectionController] Negotiation needed event received.",n),this.negotiationNeeded$.next()},this.updateSelectedInputDevice=async(n,s)=>{var a,o,c;try{const{localStream:u}=this;if(!u){z.warn("[RTCPeerConnectionController] No local stream available to update input device.");return}z.debug(`[RTCPeerConnectionController] Updating selected ${n} input device:`,u.getTracks());const h=u.getTracks().find(p=>p.kind===n);if(h){if((a=this.transceiverController)==null||a.stopTrackSender(n),this.localStreamController.removeTrack(h.id),z.debug(`[RTCPeerConnectionController] Stopped existing ${n} track: ${h.id}`,u.getTracks()),!s){z.debug(`[RTCPeerConnectionController] ${n} input device selected: none`);return}const p=(await this.getUserMedia({[n]:{...h.getConstraints(),...this.deviceController.deviceInfoToConstraints(s)}})).getTracks().find(v=>v.kind===n);p&&(z.debug(`[RTCPeerConnectionController] Adding new ${n} track: ${p.id}`),this.localStreamController.addTrack(p),await((o=this.transceiverController)==null?void 0:o.replaceSenderTrack(n,p)),z.debug(`[RTCPeerConnectionController] Added new ${n} track: ${p.id}`,(c=this.localStream)==null?void 0:c.getTracks()))}z.debug(`[RTCPeerConnectionController] ${n} input device selected:`,s==null?void 0:s.label)}catch(u){throw z.error(`[RTCPeerConnectionController] Failed to select ${n} input device:`,u),this._errors$.next(new kt("updateSelectedInputDevice",n,u)),u}},this._isNegotiating$=this.createBehaviorSubject(!1),this._memberId=null,this._iceConnectionState$=this.createReplaySubject(1),this._connectionState$=this.createReplaySubject(1),this._signalingState$=this.createReplaySubject(1),this._iceGatheringState$=this.createReplaySubject(1),this._errors$=this.createReplaySubject(1),this._iceCandidates$=this.createReplaySubject(1),this._initialized$=this.createReplaySubject(1),this._remoteDescription$=this.createReplaySubject(1),this._remoteStream$=this.createBehaviorSubject(null),this._remoteOfferMediaDirections=null,this._localAudioPipeline=null,this.deviceController=i??{},this.id=t.callId??dn(),this._type=e?"answer":"offer",this.sdpInit=e?{type:"offer",sdp:e}:void 0,this._remoteOfferMediaDirections=e?Kg(e):null;const r=this._remoteOfferMediaDirections?{audio:this._remoteOfferMediaDirections.audio.includes("recv"),video:this._remoteOfferMediaDirections.video.includes("recv"),receiveAudio:this._remoteOfferMediaDirections.audio.includes("send"),receiveVideo:this._remoteOfferMediaDirections.video.includes("send")}:{};this.options={...t,audio:t.audio??r.audio,video:t.video??r.video,receiveAudio:t.receiveAudio??r.receiveAudio??f.instance.receiveAudio,receiveVideo:t.receiveVideo??r.receiveVideo??f.instance.receiveVideo},this.localStreamController=new sf({propose:this.propose,inputAudioStream:this.options.inputAudioStream,inputVideoStream:this.options.inputVideoStream,inputAudioDeviceConstraints:this.inputAudioDeviceConstraints,inputVideoDeviceConstraints:this.inputVideoDeviceConstraints,getUserMedia:async n=>this.getUserMedia(n),getDisplayMedia:async n=>this.getDisplayMedia(n)})}get iceGatheringController(){if(!this._iceGatheringController)throw new te("ICEGatheringController is not initialized");return this._iceGatheringController}get shouldEmitLocalDescription(){if(!this.peerConnection)return!1;const{localDescription:t,signalingState:e}=this.peerConnection;return!t||!Cc(t.sdp)?!1:t.type==="offer"&&e==="have-local-offer"||t.type==="answer"&&e==="stable"}removeConnectionTimer(){this.connectionTimer&&(clearTimeout(this.connectionTimer),this.connectionTimer=void 0)}setMemberId(t){this._memberId=t}get memberId(){return this._memberId}stopTrackSender(t,e={updateTransceiverDirection:!1}){var r,n,s;const i=t==="audio"||t==="both";i&&this._localAudioPipeline&&this.stopRawAudioInputForPipeline(),i?t==="both"?(n=this.transceiverController)==null||n.stopTrackSender("video",e):this._localAudioPipeline||(s=this.transceiverController)==null||s.stopTrackSender(t,e):(r=this.transceiverController)==null||r.stopTrackSender(t,e)}stopRawAudioInputForPipeline(){var e;const t=this.localStreamController.localAudioTracks;for(const i of t)i.readyState==="live"&&(i.stop(),this.localStreamController.removeTrack(i.id));(e=this._localAudioPipeline)==null||e.setInputTrack(null)}get isNegotiating$(){return this._isNegotiating$.asObservable()}get isNegotiating(){return this._isNegotiating$.value}updateMediaDevicesOptions(t){this.options={...this.options,...t}}get iceGatheringState$(){return this.cachedObservable("iceGatheringState$",()=>this._iceGatheringState$.asObservable().pipe(S(this.destroyed$)))}get mediaTrackEnded$(){return this.cachedObservable("mediaTrackEnded$",()=>this.localStreamController.mediaTrackEnded$.pipe(S(this.destroyed$)))}get errors$(){return this.cachedObservable("errors$",()=>this._errors$.asObservable().pipe(S(this.destroyed$)))}get iceCandidates$(){return this.cachedObservable("iceCandidates$",()=>this._iceCandidates$.asObservable().pipe(S(this.destroyed$)))}get initialized$(){return this.cachedObservable("initialized$",()=>this._initialized$.asObservable().pipe(B(t=>t),S(this.destroyed$)))}get remoteDescription$(){return this.cachedObservable("remoteDescription$",()=>this._remoteDescription$.asObservable().pipe(S(this.destroyed$)))}get localStream$(){return this.cachedObservable("localStream$",()=>this.localStreamController.localStream$.pipe(S(this.destroyed$)))}get remoteStream$(){return this.cachedObservable("remoteStream$",()=>this._remoteStream$.asObservable().pipe(S(this.destroyed$)))}get localAudioTracks$(){return this.cachedObservable("localAudioTracks$",()=>this.localStreamController.localAudioTracks$.pipe(S(this.destroyed$)))}get localVideoTracks$(){return this.cachedObservable("localVideoTracks$",()=>this.localStreamController.localVideoTracks$.pipe(S(this.destroyed$)))}get iceConnectionState$(){return this.cachedObservable("iceConnectionState$",()=>this._iceConnectionState$.asObservable().pipe(S(this.destroyed$)))}get connectionState$(){return this.cachedObservable("connectionState$",()=>this._connectionState$.asObservable().pipe(S(this.destroyed$)))}get signalingState$(){return this.cachedObservable("signalingState$",()=>this._signalingState$.asObservable().pipe(S(this.destroyed$)))}get type(){return this._type}get propose(){return this.options.propose??"main"}get isAdditionalDevice(){return this.propose==="additional-device"}get isMainDevice(){return this.propose==="main"}get isScreenShare(){return this.propose==="screenshare"}get iceServers(){if(!this.options.disableUdpIceServers)return this.options.iceServers??[];const t="transport=tcp";return(this.options.iceServers??[]).map(e=>{const i=Array.isArray(e.urls)?e.urls:[e.urls];return{...e,urls:i.filter(r=>r.includes(t))}})}get rtcConfiguration(){const{iceServers:t,...e}=this.options;return{bundlePolicy:"max-compat",iceCandidatePoolSize:10,iceServers:this.iceServers,iceTransportPolicy:this.options.relayOnly?"relay":"all",sdpSemantics:"unified-plan",...e}}get receiveVideo(){return!!this.options.receiveVideo}get receiveAudio(){return!!this.options.receiveAudio}get localStream(){return this.localStreamController.localStream}get remoteStream(){return this._remoteStream$.value}get inputAudioDeviceConstraints(){if(this.options.audio===!1&&!this.options.inputAudioDeviceConstraints)return!1;const t=this.deviceController.selectedAudioInputDeviceConstraints;return t===!1?!1:{...typeof this.options.inputAudioDeviceConstraints=="object"?this.options.inputAudioDeviceConstraints:{},...typeof t=="object"?t:{}}}get inputVideoDeviceConstraints(){if(!this.options.video&&!this.options.inputVideoDeviceConstraints)return!1;const t=this.deviceController.selectedVideoInputDeviceConstraints;return t===!1?!1:{...typeof this.options.inputVideoDeviceConstraints=="object"?this.options.inputVideoDeviceConstraints:{},...typeof t=="object"?t:{}}}get WebRTCPeerConnectionConstructor(){var t;return((t=this.options.webRTCApiProvider)==null?void 0:t.RTCPeerConnection)??RTCPeerConnection}get offerOptions(){const t={iceRestart:this.firstSDPExchangeCompleted?!0:void 0};switch(this.propose){case"screenshare":case"additional-device":return{...t,offerToReceiveAudio:!1,offerToReceiveVideo:!1};case"main":default:return{...t,offerToReceiveAudio:this.options.receiveAudio??!0,offerToReceiveVideo:this.options.receiveVideo??!!this.inputVideoDeviceConstraints}}}get answerOptions(){return{iceRestart:this.firstSDPExchangeCompleted?!0:void 0}}async init(){return this.initPromise??(this.initPromise=this.doInit()),this.initPromise}async doInit(){try{this.setupPeerConnection(),this.subscribeTo(this.negotiationNeeded$.pipe(qd(0),ls(async()=>this.startNegotiation())),{next:()=>{z.debug("[RTCPeerConnectionController] Start Negotiation completed successfully")},error:t=>{z.error("[RTCPeerConnectionController] Start Negotiation error:",t),this._errors$.next(hi(t))}}),this.subscribeTo(Ni(this.deviceController.selectedAudioInputDevice$.pipe(x(t=>["audio",t])),this.deviceController.selectedVideoInputDevice$.pipe(x(t=>["video",t]))).pipe(eh(()=>!this.localStreamController.localStream)),async([t,e])=>{z.debug("[RTCPeerConnectionController] Selected input device changed for:",{kind:t,deviceInfo:e}),await this.updateSelectedInputDevice(t,e)}),this.type==="answer"&&this.sdpInit?(await this.setupRemoteTracks(),this._initialized$.next(!0),this.setupEventListeners(),this._isNegotiating$.next(!0),await this._setRemoteDescription(this.sdpInit)):(await this.setupTrackHandling(),this._initialized$.next(!0))}catch(t){z.error("[RTCPeerConnectionController] Initialization error:",t),this._errors$.next(hi(t)),this.destroy()}}setupPeerConnection(){this.peerConnection=new this.WebRTCPeerConnectionConstructor(this.rtcConfiguration),this.peerConnection.addEventListener("negotiationneeded",this.onnegotiationneededHandler),this._iceGatheringController=new rf(this.peerConnection,this.isNegotiating$,{iceCandidateTimeout:this.options.iceCandidateTimeout,iceGatheringTimeout:this.options.iceGatheringTimeout,relayOnly:this.options.relayOnly}),this.transceiverController=new af({peerConnection:this.peerConnection,propose:this.propose,simulcast:this.options.simulcast,sfu:this.options.sfu,msStreamsNumber:this.options.msStreamsNumber,receiveAudio:this.receiveAudio,receiveVideo:this.receiveVideo,localStreamController:this.localStreamController,getInputAudioDeviceConstraints:()=>this.inputAudioDeviceConstraints,getInputVideoDeviceConstraints:()=>this.inputVideoDeviceConstraints,getUserMedia:async t=>this.getUserMedia(t),onError:t=>{this._errors$.next(t)}})}async startNegotiation(){if(this.isNegotiating){z.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");return}if(this.setupEventListeners(),this.type==="answer"){z.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");return}this._isNegotiating$.next(!0),z.debug("[RTCPeerConnectionController] Starting negotiation.");try{const{offerOptions:t}=this;z.debug("[RTCPeerConnectionController] Creating offer with options:",t),await this.createOffer(t)}catch(t){z.error("[RTCPeerConnectionController] Error during negotiation:",t),this._errors$.next(hi(t))}}async createOffer(t){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");const e=await this.peerConnection.createOffer(t);await this.setLocalDescription(e)}async updateAnswerStatus({status:t,sdp:e}){let i=t!=="failed";try{t==="received"&&e&&(z.debug("[RTCPeerConnectionController] Received answer SDP:",e),await this._setRemoteDescription({type:"answer",sdp:e}))}catch(r){z.error("[RTCPeerConnectionController] Error updating answer status:",r),this._errors$.next(hi(r)),i=!1}finally{i?this.readyToConnect():this.iceGatheringController.restartICEGatheringWithRelayOnly()}}async updateOfferStatus({status:t,sdp:e}){switch(t){case"received":this._type="answer",this.sdpInit={type:"offer",sdp:e},await this.handleOfferReceived();break;case"failed":z.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");break}}async acceptInbound(t){var i;if(t){const{audio:r,video:n,receiveAudio:s,receiveVideo:a,fallbackToReceiveOnly:o}=t;this.options={...this.options,...r!==void 0?{audio:r}:{},...n!==void 0?{video:n}:{},...s!==void 0?{receiveAudio:s}:{},...a!==void 0?{receiveVideo:a}:{},...o!==void 0?{fallbackToReceiveOnly:o}:{}},(i=this.transceiverController)==null||i.updateOptions({receiveAudio:this.receiveAudio,receiveVideo:this.receiveVideo}),this.localStreamController.updateOptions({inputAudioDeviceConstraints:this.inputAudioDeviceConstraints,inputVideoDeviceConstraints:this.inputVideoDeviceConstraints})}await this.setupLocalTracks();const{answerOptions:e}=this;z.debug("[RTCPeerConnectionController] Creating inbound answer with options:",e),await this.createAnswer(e)}async handleOfferReceived(){if(!this.sdpInit)throw new te("SDP initialization parameters are not set");this._isNegotiating$.next(!0),await this._setRemoteDescription(this.sdpInit);const{answerOptions:t}=this;z.debug("[RTCPeerConnectionController] Creating answer with options:",t),await this.createAnswer(t)}readyToConnect(){this.firstSDPExchangeCompleted=!0,this.connectionTimer=setTimeout(()=>{var t;this.removeConnectionTimer(),((t=this.peerConnection)==null?void 0:t.connectionState)!=="connected"&&(z.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only."),this.iceGatheringController.restartICEGatheringWithRelayOnly())},this.connectionTimeout)}async setRemoteDescriptionBefore(t=""){return Promise.resolve(t)}async setLocalDescription(t){var i;const e=await this.setLocalDescriptionBefore(t.sdp);return(i=this.peerConnection)==null?void 0:i.setLocalDescription({...t,sdp:e})}async setLocalDescriptionBefore(t=""){let e=t;const i=this.options.preferredAudioCodecs??f.instance.preferredAudioCodecs,r=this.options.preferredVideoCodecs??f.instance.preferredVideoCodecs,n=this.options.stereo??f.instance.stereoAudio;return(i.length>0||r.length>0)&&(e=Jg(e,i,r),z.debug("[RTCPeerConnectionController] Applied codec preferences to SDP",{preferredAudioCodecs:i,preferredVideoCodecs:r})),n&&(e=Qg(e),z.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP")),Promise.resolve(e)}async createAnswer(t){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");const e=await this.peerConnection.createAnswer(t);await this.setLocalDescription(e)}setupEventListeners(){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");this._iceConnectionState$.next(this.peerConnection.iceConnectionState),this._connectionState$.next(this.peerConnection.connectionState),this._signalingState$.next(this.peerConnection.signalingState),this._iceGatheringState$.next(this.peerConnection.iceGatheringState),this._remoteDescription$.next(this.peerConnection.remoteDescription),this.peerConnection.removeEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.addEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.removeEventListener("iceconnectionstatechange",this.oniceconnectionstatechangeHandler),this.peerConnection.addEventListener("iceconnectionstatechange",this.oniceconnectionstatechangeHandler),this.peerConnection.removeEventListener("connectionstatechange",this.onconnectionstatechangeHandler),this.peerConnection.addEventListener("connectionstatechange",this.onconnectionstatechangeHandler),this.peerConnection.removeEventListener("signalingstatechange",this.onsignalingstatechangeHandler),this.peerConnection.addEventListener("signalingstatechange",this.onsignalingstatechangeHandler)}negotiationEnded(){this._isNegotiating$.next(!1)}async triggerIceRestart(t){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");const e=t&&!this.options.relayOnly;if(e)try{this.peerConnection.setConfiguration({...this.peerConnection.getConfiguration(),iceTransportPolicy:"relay"}),z.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only")}catch(i){z.warn("[RTCPeerConnectionController] Failed to set relay-only policy:",i)}this.setupEventListeners(),this._isNegotiating$.next(!0),z.debug(`[RTCPeerConnectionController] Triggering ICE restart${t?" (relay-only)":""}.`);try{const i=await this.peerConnection.createOffer({iceRestart:!0});await this.setLocalDescription(i)}catch(i){throw z.error("[RTCPeerConnectionController] ICE restart offer failed:",i),this._errors$.next(hi(i)),this.negotiationEnded(),e&&this.restoreIceTransportPolicy(),i}e&&Ze(Cr(this._iceGatheringState$.pipe(B(i=>i==="complete"),Oe(1)),Fi(Uh).pipe(x(()=>"timeout")))).then(()=>this.restoreIceTransportPolicy()).catch(i=>{z.warn("[RTCPeerConnectionController] Error waiting for ICE gathering to complete:",i),this.restoreIceTransportPolicy()})}restoreIceTransportPolicy(){var t;try{(t=this.peerConnection)==null||t.setConfiguration({...this.peerConnection.getConfiguration(),iceTransportPolicy:this.options.relayOnly?"relay":"all"}),z.debug("[RTCPeerConnectionController] ICE transport policy restored")}catch(e){z.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:",e)}}async setupTrackHandling(){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");await this.setupLocalTracks(),await this.setupRemoteTracks()}async setupLocalTracks(){var e,i,r,n,s,a,o;if(z.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers."),this.hasNoLocalMediaToSend()){if(!this.receiveAudio&&!this.receiveVideo)throw new on("Call requests no media: enable audio/video or receiveAudio/receiveVideo");z.debug("[RTCPeerConnectionController] No local media requested; negotiating receive-only."),this.setupReceiveOnlyTransceivers();return}let t;try{t=this.localStream??await this.localStreamController.buildLocalStream()}catch(c){this.handleLocalMediaFailure(c);return}if(((e=this.transceiverController)==null?void 0:e.useAddStream)??!1){z.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream."),(i=this.peerConnection)==null||i.addStream(t),this.isNegotiating||(z.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup."),this.negotiationNeeded$.next());return}for(const c of["audio","video"]){const u=(c==="audio"?t.getAudioTracks():t.getVideoTracks()).map((h,p)=>({index:p,track:h}));for(const{index:h,track:p}of u)if(this.localStreamController.addTrackEndedListener(p),((r=this.transceiverController)==null?void 0:r.useAddTransceivers)??!1){const v=(c==="audio"?(n=this.transceiverController)==null?void 0:n.audioTransceivers:(s=this.transceiverController)==null?void 0:s.videoTransceivers)??[];await((a=this.transceiverController)==null?void 0:a.setupTransceiverSender(p,t,v[h]))}else z.debug(`[RTCPeerConnectionController] Using addTrack for local ${c} track:`,p.id),(o=this.peerConnection)==null||o.addTrack(p,t)}}hasNoLocalMediaToSend(){const t=!!(this.options.inputAudioStream??this.options.inputVideoStream);return this.propose==="main"&&!this.localStream&&!t&&!this.inputAudioDeviceConstraints&&!this.inputVideoDeviceConstraints}get requestedMediaKinds(){const t=!!this.inputAudioDeviceConstraints,e=!!this.inputVideoDeviceConstraints;return t&&e?"audiovideo":e?"video":"audio"}handleLocalMediaFailure(t){if(this.propose==="screenshare")throw new Gt("startScreenShare","screen",t,!1);if(this.propose==="additional-device")throw new Gt("addInputDevice",this.requestedMediaKinds,t,!1);const e=this.receiveAudio||this.receiveVideo;if(!((this.options.fallbackToReceiveOnly??!0)&&e))throw new Gt("acquireLocalMedia",this.requestedMediaKinds,t,!0);z.warn("[RTCPeerConnectionController] Local media unavailable; continuing receive-only:",t),this._errors$.next(new Gt("acquireLocalMedia",this.requestedMediaKinds,t,!1)),this.setupReceiveOnlyTransceivers()}setupReceiveOnlyTransceivers(){var t,e,i;this.type==="offer"&&((((t=this.transceiverController)==null?void 0:t.useAddTransceivers)??!1)&&((e=this.peerConnection)==null||e.addTransceiver("audio",{direction:this.receiveAudio?"recvonly":"inactive"}),(i=this.peerConnection)==null||i.addTransceiver("video",{direction:this.receiveVideo?"recvonly":"inactive"})),this.isNegotiating||this.negotiationNeeded$.next())}async getUserMedia(t){var e;return(((e=this.options.webRTCApiProvider)==null?void 0:e.mediaDevices)??navigator.mediaDevices).getUserMedia(t)}async getDisplayMedia(t){var i;const e=((i=this.options.webRTCApiProvider)==null?void 0:i.mediaDevices)??navigator.mediaDevices;if(!e.getDisplayMedia)throw new te("getDisplayMedia is not supported by the current WebRTC provider");return e.getDisplayMedia(t)}async setupRemoteTracks(){var t;if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");this.peerConnection.ontrack=e=>{var i;if(z.debug("[RTCPeerConnectionController] Remote track received:",e.track.kind),e.streams[0])this._remoteStream$.next(e.streams[0]);else{const r=((i=this._remoteStream$.value)==null?void 0:i.getTracks())??[],n=new MediaStream([...r,e.track]);this._remoteStream$.next(n)}},await((t=this.transceiverController)==null?void 0:t.setupRemoteTransceivers(this.type))}async restoreTrackSender(t){var i,r,n;const e=t==="audio"||t==="both";e&&this._localAudioPipeline&&await this.restoreRawAudioInputForPipeline(),e?t==="both"?await((r=this.transceiverController)==null?void 0:r.restoreTrackSender("video")):this._localAudioPipeline||await((n=this.transceiverController)==null?void 0:n.restoreTrackSender(t)):await((i=this.transceiverController)==null?void 0:i.restoreTrackSender(t))}async restoreRawAudioInputForPipeline(){var r;if(!this._localAudioPipeline)return;const t=((r=this.transceiverController)==null?void 0:r.getConstraintsFor("audio"))??{};let e;try{e=await this.getUserMedia({audio:t})}catch(n){z.error("[RTCPeerConnectionController] Failed to re-acquire mic for pipeline restore:",n),this._errors$.next(new kt("restoreAudioPipelineInput","audio",n));return}const i=e.getAudioTracks().at(0);i&&(this.localStreamController.addTrack(i),this._localAudioPipeline.setInputTrack(i))}ensureLocalAudioPipeline(){if(this._localAudioPipeline)return this._localAudioPipeline;if(!this.peerConnection)return null;try{this._localAudioPipeline=new nf}catch(t){return z.warn("[RTCPeerConnectionController] Failed to create LocalAudioPipeline:",t),null}return this.subscribeTo(this.localStreamController.localAudioTracks$,()=>{this.applyLocalAudioPipelineToSender()}),this.applyLocalAudioPipelineToSender(),this._localAudioPipeline}get localAudioPipeline(){return this._localAudioPipeline}async applyLocalAudioPipelineToSender(){var i,r;if(!this._localAudioPipeline||!this.peerConnection)return;const t=this.localStreamController.localAudioTracks.at(0);this._localAudioPipeline.setInputTrack(t??null);const e=((r=(i=this.transceiverController)==null?void 0:i.audioTransceivers.at(0))==null?void 0:r.sender)??this.peerConnection.getSenders().find(n=>{var s;return((s=n.track)==null?void 0:s.kind)==="audio"});if(!(!e||!t))try{await e.replaceTrack(this._localAudioPipeline.outputTrack)}catch(n){z.warn("[RTCPeerConnectionController] Failed to route audio sender through pipeline:",n)}}addLocalTrack(t){if(!this.peerConnection){const e=new te("RTCPeerConnection is not initialized");throw this._errors$.next(e),e}try{const e=this.localStreamController.addTrack(t);this.peerConnection.addTrack(t,e),z.debug(`[RTCPeerConnectionController] ${t.kind} track added:`,t.id)}catch(e){throw z.error(`[RTCPeerConnectionController] Failed to add ${t.kind} track:`,e),this._errors$.next(new kt("addLocalTrack",t.kind,e)),e}}removeLocalTrack(t){var i,r,n;if(!this.peerConnection){const s=new te("RTCPeerConnection is not initialized");throw this._errors$.next(s),s}const e=this.peerConnection.getSenders().find(s=>{var a;return((a=s.track)==null?void 0:a.id)===t});if(!e){z.debug(`[RTCPeerConnectionController] track not found: ${t}`);return}try{this.peerConnection.removeTrack(e),this.localStreamController.removeTrack(t),z.debug(`[RTCPeerConnectionController] ${(i=e.track)==null?void 0:i.kind} track removed:`,t)}catch(s){throw z.error(`[RTCPeerConnectionController] Failed to remove ${(r=e.track)==null?void 0:r.kind} track:`,s),this._errors$.next(new kt("removeLocalTrack",((n=e.track)==null?void 0:n.kind)??"unknown",s)),s}}setLocalTrack(t){const e=[...t.kind==="audio"?this.localStreamController.localAudioTracks:this.localStreamController.localVideoTracks];for(const i of e)this.removeLocalTrack(i.id);this.addLocalTrack(t)}async updateSendersConstraints(t,e){var i;await((i=this.transceiverController)==null?void 0:i.updateSendersConstraints(t,e))}async replaceAudioTrackWithConstraints(t){var i;const e=(i=this.peerConnection)==null?void 0:i.getSenders().filter(r=>{var n;return((n=r.track)==null?void 0:n.kind)==="audio"&&r.track.readyState==="live"});if(!e||e.length===0){z.warn("[RTCPeerConnectionController] No live audio sender to replace");return}for(const r of e){const n=r.track;if(!n)continue;const{deviceId:s}=n.getSettings(),a={...n.getConstraints(),...t,...s?{deviceId:{exact:s}}:{}},o=n.id;n.stop(),this.localStreamController.removeTrack(o);const c=(await this.getUserMedia({audio:a})).getAudioTracks()[0];await r.replaceTrack(c),this.localStreamController.addTrack(c),z.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${c.id}`)}}destroy(){var t,e,i;z.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`),this.removeConnectionTimer(),(t=this._iceGatheringController)==null||t.destroy(),(e=this._localAudioPipeline)==null||e.destroy(),this._localAudioPipeline=null,this.localStreamController.destroy(),(i=this.transceiverController)==null||i.destroy(),this.peerConnection&&(this.stopRemoteTracks(),this.removeAllListeners(),this.peerConnection.close(),this.peerConnection=void 0),super.destroy()}removeAllListeners(){this.peerConnection&&(this.peerConnection.removeEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.removeEventListener("iceconnectionstatechange",this.oniceconnectionstatechangeHandler),this.peerConnection.removeEventListener("connectionstatechange",this.onconnectionstatechangeHandler),this.peerConnection.removeEventListener("signalingstatechange",this.onsignalingstatechangeHandler),this.peerConnection.removeEventListener("negotiationneeded",this.onnegotiationneededHandler))}stopRemoteTracks(){var t;(t=this._remoteStream$.value)==null||t.getTracks().forEach(e=>{z.debug(`[RTCPeerConnectionController] Stopping remote track: ${e.kind}`),e.stop()})}get mediaDirections(){var t;return((t=this.transceiverController)==null?void 0:t.getMediaDirections())??this._remoteOfferMediaDirections??{audio:"inactive",video:"inactive"}}async _setRemoteDescription(t){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");const e=await this.setRemoteDescriptionBefore(t.sdp),i={...t,sdp:e};return z.debug("[RTCPeerConnectionController] Setting remote description:",i),this.peerConnection.setRemoteDescription(i)}};function Ds(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"id")}function kc(t){if(!Ds(t))return!1;const e=t;return e.method==="verto.invite"&&ke(e.params)&&K(e.params,"sdp")&&K(e.params,"callID")}function of(t){return Ds(t)?t.method==="verto.bye":!1}function xc(t){return Ds(t)?t.method==="verto.attach":!1}function cf(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"method")&&t.method==="verto.answer"&&ke(t.params)&&K(t.params,"callID")}function lf(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"method")&&t.method==="verto.media"&&ke(t.params)&&K(t.params,"callID")&&K(t.params,"sdp")}function uf(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"method")&&t.method==="verto.mediaParams"&&ke(t.params)&&K(t.params,"mediaParams")}function df(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"method")&&t.method==="verto.ping"}function Dc(t){return ke(t)&&K(t,"callID")&&typeof t.callID=="string"}const H=G();function hf(t){return t.isInvite&&!t.reattach&&!t.explicitNodeId?"":t.currentNodeId??""}var pf=class extends se{constructor(t){super(),this.callSession=t}destroy(){this.callSession=void 0,super.destroy()}},gf=class extends pf{constructor(t,e,i,r,n={}){super(t),this.webRtcCallSession=t,this.attachManager=e,this.deviceController=i,this.webRTCApiProvider=r,this._rtcPeerConnections$=this.createBehaviorSubject([]),this._selfId$=this.createBehaviorSubject(null),this._signalingStatus$=this.createReplaySubject(1),this._screenShareStatus$=this.createBehaviorSubject("none"),this._rtcPeerConnectionsMap=new Map,this._screenShareTimeoutMs=5e4,this._nodeId$=this.createBehaviorSubject(n.nodeId??null),this.onError=n.onError,this.onModifyFailed=n.onModifyFailed,this.initSubscriptions(),this.initMainPeerConnection()}async hold(){const t=vn({sessid:this.webRtcCallSession.id,dialogParams:{callID:this.webRtcCallSession.id},action:"hold"});try{await this.executeVerto(t)}catch(e){throw H.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:",e),e}}async unhold(){const t=vn({sessid:this.webRtcCallSession.id,dialogParams:{callID:this.webRtcCallSession.id},action:"unhold"});try{await this.executeVerto(t)}catch(e){throw H.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:",e),e}}get mediaDirections(){return this.mainPeerConnection.mediaDirections}get rtcPeerConnections$(){return this._rtcPeerConnections$.asObservable()}get rtcPeerConnections(){return this._rtcPeerConnections$.value}get nodeId$(){return this._nodeId$.asObservable()}get selfId$(){return this._selfId$.asObservable()}get localStream(){var t;return((t=this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id))==null?void 0:t.localStream)??null}get remoteStream(){var t;return((t=this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id))==null?void 0:t.remoteStream)??null}get nodeId(){return this._nodeId$.value}get screenShareStatus(){return this._screenShareStatus$.value}get screenShareStatus$(){return this._screenShareStatus$.asObservable()}get mainPeerConnection(){const t=this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);if(!t)throw new te("Main peer connection not found");return t}get signalingStatus$(){return this.cachedObservable("signalingStatus$",()=>Ni(this._signalingStatus$.asObservable(),this.mainPeerConnection.connectionState$.pipe(B(t=>["connected","disconnected","failed"].includes(t)))))}initSubscriptions(){this.subscribeTo(this.callJoinedEvent$,t=>{var i;const e=(i=t.room_session.members.find(r=>r.call_id===t.call_id))==null?void 0:i.node_id;e&&this.setNodeIdIfNull(e),t.member_id&&this.setSelfIdIfNull(t.member_id)}),this.subscribeTo(this.vertoMedia$,t=>{var r;H.debug("[WebRTCManager] Received Verto media event (early media SDP):",t);const{sdp:e,callID:i}=t;this.emitMainSignalingStatus(i,"ringing"),(r=this._rtcPeerConnectionsMap.get(i))==null||r.updateAnswerStatus({status:"received",sdp:e})}),this.subscribeTo(this.vertoAnswer$,t=>{var r;H.debug("[WebRTCManager] Received Verto answer event:",t);const{sdp:e,callID:i}=t;this.emitMainSignalingStatus(i,"connecting"),(r=this._rtcPeerConnectionsMap.get(i))==null||r.updateAnswerStatus({status:"received",sdp:e})}),this.subscribeTo(this.vertoMediaParams$,t=>{H.debug("[WebRTCManager] Received Verto mediaParams event:",t);const{mediaParams:e,callID:i}=t,r=this._rtcPeerConnectionsMap.get(i),{audio:n,video:s}=e;(async()=>{var a;try{n&&r&&await r.replaceAudioTrackWithConstraints(n),s&&await(r==null?void 0:r.updateSendersConstraints("video",s)),this.webRtcCallSession.emitMediaParamsUpdated({audio:n,video:s,timestamp:Date.now()})}catch(o){H.warn("[WebRTCManager] Error applying server-pushed media params:",o),(a=this.onError)==null||a.call(this,o instanceof Error?o:new Error(String(o),{cause:o}))}})()}),this.subscribeTo(this.vertoPing$,t=>{this.attachManager.attach(this.buildAttachableCall()),this.sendVertoPong(t)})}setNodeIdIfNull(t){!this._nodeId$.value&&t&&(H.debug(`[WebRTCManager] Early node_id set: ${t}`),this._nodeId$.next(t))}setSelfIdIfNull(t){!this._selfId$.value&&t&&(H.debug(`[WebRTCManager] Early selfId set: ${t}`),this._selfId$.next(t))}async sendVertoPong(t){var e;try{const i=Dg({...t});await this.executeVerto(i)}catch(i){H.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:",i),(e=this.onError)==null||e.call(this,new No(i))}}async updateMediaConstraints(t={}){var r;const{audio:e,video:i}=t;try{e&&await this.mainPeerConnection.updateSendersConstraints("audio",e),i&&await this.mainPeerConnection.updateSendersConstraints("video",i)}catch(n){throw H.warn("[WebRTCManager] Error updating media constraints:",n),(r=this.onError)==null||r.call(this,n instanceof Error?n:new Error(String(n),{cause:n})),n}}get selfId(){return this._selfId$.value}buildAttachableCall(t){return{nodeId:this.nodeId??void 0,id:t??this.webRtcCallSession.id,to:this.webRtcCallSession.to,mediaDirections:this.webRtcCallSession.mediaDirections}}requestKeyframe(){try{const t=this.mainPeerConnection.peerConnection;if(!t){H.warn("[WebRTCManager] No peer connection for keyframe request");return}const e=t.getReceivers().find(i=>i.track.kind==="video");if(!e){H.warn("[WebRTCManager] No video receiver for keyframe request");return}typeof e.requestKeyFrame=="function"?(e.requestKeyFrame(),H.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()")):H.debug("[WebRTCManager] requestKeyFrame() not supported, skipping")}catch(t){H.warn("[WebRTCManager] Keyframe request failed (non-fatal):",t)}}async requestIceRestart(t){try{const e=this.mainPeerConnection;if(!e.peerConnection){H.warn("[WebRTCManager] No peer connection for ICE restart");return}await e.triggerIceRestart(t),H.info(`[WebRTCManager] ICE restart initiated${t?" (relay-only)":""}`)}catch(e){throw H.error("[WebRTCManager] ICE restart failed:",e),e}}async requestIceRestartAll(t){const e=Array.from(this._rtcPeerConnectionsMap.entries());for(const[i,r]of e)try{if(!r.peerConnection){H.debug(`[WebRTCManager] No peer connection for leg ${i}, skipping ICE restart`);continue}await r.triggerIceRestart(t),H.info(`[WebRTCManager] ICE restart initiated for leg ${i}${t?" (relay-only)":""}`)}catch(n){H.warn(`[WebRTCManager] ICE restart failed for leg ${i}:`,n)}}requestKeyframeAll(){for(const[t,e]of this._rtcPeerConnectionsMap){if(e.isScreenShare){H.debug(`[WebRTCManager] Skipping keyframe for send-only screen share leg ${t}`);continue}try{const i=e.peerConnection;if(!i)continue;const r=i.getReceivers().find(n=>n.track.kind==="video");if(!r)continue;typeof r.requestKeyFrame=="function"&&(r.requestKeyFrame(),H.debug(`[WebRTCManager] Keyframe requested for leg ${t}`))}catch(i){H.warn(`[WebRTCManager] Keyframe request failed for leg ${t} (non-fatal):`,i)}}}get callJoinedEvent$(){return this.webRtcCallSession.callEvent$.pipe(B(Sc),S(this.destroyed$))}get vertoMedia$(){return this.webRtcCallSession.webrtcMessages$.pipe(Se(lf,"params"),S(this.destroyed$))}get vertoAnswer$(){return this.cachedObservable("vertoAnswer$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(cf,"params"),S(this.destroyed$)))}get vertoMediaParams$(){return this.cachedObservable("vertoMediaParams$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(uf,"params"),S(this.destroyed$)))}get vertoBye$(){return this.cachedObservable("vertoBye$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(of,"params"),S(this.destroyed$)))}get vertoAttach$(){return this.cachedObservable("vertoAttach$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(xc,"params"),S(this.destroyed$)))}get vertoPing$(){return this.cachedObservable("vertoPing$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(df,"params"),S(this.destroyed$)))}async executeVerto(t,e={}){var s,a;const i=sc({callID:e.callID??this.webRtcCallSession.id,node_id:e.node_id??this._nodeId$.value??"",message:t,subscribe:e.subscribe}),r=await this.webRtcCallSession.execute(i);if(r.error){const o=new Et(r.error.code,r.error.message,r.error.data);return(s=this.onError)==null||s.call(this,o),r}const n=at(r,"result.result");if(n!=null&&n.error){const o=new Et(n.error.code,n.error.message,n.error.data);return(a=this.onError)==null||a.call(this,o),r}return r}async sendLocalDescription(t,e){var n,s;const i=t.method,r=this.getSendLocalSDPOptionalParams(e,t);try{const a=await this.executeVerto(t,r);switch(i){case"verto.invite":this.processInviteResponse(a,e);break;case"verto.modify":await this.processModifyResponse(a,e);break;default:}}catch(a){H.error(`[WebRTCManager] Error sending Verto ${i}:`,a),(n=this.onError)==null||n.call(this,a instanceof Error?a:new Error(String(a),{cause:a})),i==="verto.modify"&&((s=this.onModifyFailed)==null||s.call(this))}}async processModifyResponse(t,e){var i;if(!t.error){const r=at(t,"result.result.result.action"),n=at(t,"result.result.result.sdp");if(r==="updateMedia"&&n)try{await e.updateAnswerStatus({status:"received",sdp:n})}catch(s){H.warn("[WebRTCManager] Error processing modify response:",s);const a=s instanceof Error?s:new Error(String(s),{cause:s});(i=this.onError)==null||i.call(this,a)}}}emitMainSignalingStatus(t,e){var r;const i=this._rtcPeerConnectionsMap.get(t);if(!i){const n=new te(`Cannot emit signaling status, RTCPeerConnectionController not found for callID: ${t}`);H.error("[WebRTCManager] Failed to emit signaling status:",{callId:t,status:e,signalingError:n}),(r=this.onError)==null||r.call(this,n);return}i.isMainDevice&&this._signalingStatus$.next(e)}processInviteResponse(t,e){var i;if(!t.error&&at(t,"result.result.result.message")==="CALL CREATED"){this.emitMainSignalingStatus(e.id,"trying"),this._nodeId$.next(at(t,"result.node_id")??null);const r=at(t,"result.result.result.memberID")??null,n=at(t,"result.result.result.callID")??null;H.debug("[WebRTCManager] Verto invite response:",{callId:n,memberId:r,response:t}),this._selfId$.next(r),e.setMemberId(r),n?(this.webRtcCallSession.addCallId(n),this.attachManager.attach(this.buildAttachableCall(n))):H.warn("[WebRTCManager] Cannot attach call, missing callId:",{nodeId:this.nodeId,callId:n}),H.info("[WebRTCManager] Verto invite successful"),H.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`)}else{H.error("[WebRTCManager] Verto invite failed:",t);const r=t.error?new Et(t.error.code,t.error.message,t.error.data):new Error("Verto invite failed: unexpected response");(i=this.onError)==null||i.call(this,r)}}get RTCPeerConnectionConfig(){return{iceServers:this.webRtcCallSession.clientSession.iceServers??f.instance.iceServers,relayOnly:f.instance.relayOnly||f.instance.disableUdpIceServers,disableUdpIceServers:f.instance.disableUdpIceServers,iceCandidateTimeout:f.instance.iceCandidateTimeout,iceGatheringTimeout:f.instance.iceGatheringTimeout}}initMainPeerConnection(){const{options:t}=this.webRtcCallSession,e=new Ec({propose:"main",callId:this.webRtcCallSession.id,audio:t.audio,video:t.video,inputAudioDeviceConstraints:t.inputAudioDeviceConstraints,inputVideoDeviceConstraints:t.inputVideoDeviceConstraints,inputAudioStream:t.inputAudioStream,inputVideoStream:t.inputVideoStream,receiveAudio:t.receiveAudio,receiveVideo:t.receiveVideo,fallbackToReceiveOnly:t.fallbackToReceiveOnly,webRTCApiProvider:this.webRTCApiProvider,preferredVideoCodecs:t.preferredVideoCodecs,preferredAudioCodecs:t.preferredAudioCodecs,stereo:t.stereo,...this.RTCPeerConnectionConfig},t.initOffer,this.deviceController);this.setupLocalDescriptionHandler(e),this.setupVertoByeHandler(),this.setupVertoAttachHandler(),this.initObservables(e),this._rtcPeerConnectionsMap.set(e.id,e),this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values())),this.subscribeTo(e.errors$,i=>{var r;(r=this.onError)==null||r.call(this,i)}),t.initOffer&&this.handleInboundAnswer(e)}async handleInboundAnswer(t){var i,r,n;H.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");const e=await Ze(Cr(this.vertoBye$,this.webRtcCallSession.answered$).pipe(S(this.destroyed$))).catch(()=>null);if(e===null){H.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");return}if(Dc(e))H.info("[WebRTCManager] Inbound call ended by remote before answer."),(i=this.callSession)==null||i.destroy();else if(e){H.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");const s=this.webRtcCallSession.answerMediaOptions;try{await t.acceptInbound(s)}catch(a){H.error("[WebRTCManager] Error creating inbound answer:",a),(n=this.onError)==null||n.call(this,a instanceof Error?a:new Error(String(a),{cause:a}))}}else{H.info("[WebRTCManager] Inbound call rejected by user.");try{await this.bye("USER_BUSY")}finally{this._signalingStatus$.next("disconnected"),(r=this.callSession)==null||r.destroy()}}}setupVertoAttachHandler(){this.subscribeTo(this.vertoAttach$,async t=>{H.debug("[WebRTCManager] Received Verto attach event for existing call:",t);const{callID:e}=t;await this.attachManager.attach({nodeId:this.nodeId??void 0,id:e,to:t.callee_id_number,mediaDirections:{audio:"sendrecv",video:"inactive"}})})}initObservables(t){this.mediaDirections$=t.connectionState$.pipe(B(e=>e==="connected"),x(()=>t.mediaDirections),th(t.mediaDirections),S(this.destroyed$)),this.localStream$=t.localStream$.pipe(ve(),S(this.destroyed$)),this.remoteStream$=t.remoteStream$.pipe(ve(),S(this.destroyed$))}setupLocalDescriptionHandler(t){this.subscribeTo(t.localDescription$.pipe(B(e=>e!==null),S(this.destroyed$)),e=>{const{type:i,sdp:r}=e,n=this.dialogParams(t),s=!t.firstSDPExchangeCompleted;if(i==="answer"){const a=kg({dialogParams:n,sdp:r});this.sendLocalDescriptionOnceAccepted(a,t)}else if(s){const a=Ag({dialogParams:n,sdp:r});this.sendLocalDescription(a,t)}else{const a=vn({dialogParams:n,sdp:r,action:"updateMedia"});this.sendLocalDescription(a,t)}})}setupVertoByeHandler(){this.subscribeTo(this.vertoBye$,()=>{var t;this._signalingStatus$.next("disconnected"),this.attachManager.detach(this.buildAttachableCall()),(t=this.callSession)==null||t.destroy()})}getSendLocalSDPOptionalParams(t,e){let i;return t.firstSDPExchangeCompleted||(i=[],t.isMainDevice?i.push(...f.instance.inviteSubscribeMainDevice):t.isAdditionalDevice?i.push(...f.instance.inviteSubscribeAdditionalDevice):t.isScreenShare&&i.push(...f.instance.inviteSubscribeScreenshare)),{callID:t.id,node_id:hf({isInvite:kc(e),reattach:this.webRtcCallSession.options.reattach===!0,explicitNodeId:this.webRtcCallSession.options.nodeId,currentNodeId:this._nodeId$.value}),subscribe:i}}async sendLocalDescriptionOnceAccepted(t,e){var r,n,s;H.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");const i=await Ze(Cr(this.vertoBye$,this.webRtcCallSession.answered$).pipe(S(this.destroyed$))).catch(()=>null);if(i===null){H.debug("[WebRTCManager] Destroyed while waiting for call acceptance");return}if(Dc(i))H.info("[WebRTCManager] Call ended before answer was sent."),(r=this.callSession)==null||r.destroy();else if(i){H.debug("[WebRTCManager] Call accepted, sending answer");try{this.emitMainSignalingStatus(e.id,"connecting"),await this.sendLocalDescription(t,e),await e.updateAnswerStatus({status:"sent"}),await this.attachManager.attach(this.buildAttachableCall())}catch(a){H.error("[WebRTCManager] Error sending Verto answer:",a),(s=this.onError)==null||s.call(this,a instanceof Error?a:new Error(String(a),{cause:a})),await e.updateAnswerStatus({status:"failed"})}}else{H.info("[WebRTCManager] Call was not accepted, sending verto.bye.");try{await this.bye("USER_BUSY")}finally{this._signalingStatus$.next("disconnected"),(n=this.callSession)==null||n.destroy()}}}dialogParams(t){const e=t.memberId??this._selfId$.value??void 0,i=t.propose==="main"&&!t.firstSDPExchangeCompleted&&this.webRtcCallSession.options.reattach;return{id:t.isMainDevice?this.webRtcCallSession.id:t.id,destinationNumber:this.webRtcCallSession.to??this.webRtcCallSession.from,attach:i,reattaching:i,callerName:this.webRtcCallSession.fromName,callerNumber:this.webRtcCallSession.from,remoteCallerName:this.webRtcCallSession.toName,remoteCallerNumber:this.webRtcCallSession.to,userVariables:{memberCallId:this.webRtcCallSession.id,memberId:e,...this.webRtcCallSession.userVariables},screenShare:t.isScreenShare,additionalDevice:t.isAdditionalDevice,pingSupported:!0,version:ah}}muteMainAudioInputDevice(){return this.mainPeerConnection.stopTrackSender("audio")}muteMainVideoInputDevice(){return this.mainPeerConnection.stopTrackSender("video")}async unmuteMainAudioInputDevice(){return this.mainPeerConnection.restoreTrackSender("audio")}async unmuteMainVideoInputDevice(){return this.mainPeerConnection.restoreTrackSender("video")}ensureLocalAudioPipeline(){return this.mainPeerConnection.ensureLocalAudioPipeline()}get localAudioPipeline(){return this.mainPeerConnection.localAudioPipeline}async addInputDevice(t={audio:!1,video:!0}){return this.initAdditionalPeerConnection("additional-device",t)}async addMainInputDevices(t={audio:!0}){var r;let e;const{mediaDirections:i}=this.mainPeerConnection;if((t.audio??t.inputAudioDeviceConstraints??(t.inputAudioStream&&i.audio.startsWith("send")))&&(e="audio"),(t.video??t.inputVideoDeviceConstraints??(t.inputVideoStream&&!i.video.startsWith("send")))&&(e=e==="audio"?"both":"video"),e)this.mainPeerConnection.updateMediaDevicesOptions(t),await this.mainPeerConnection.restoreTrackSender(e);else{const n=new on("No valid device to be added");throw(r=this.onError)==null||r.call(this,n),n}}async addScreenMedia(t={audio:!1}){await this.initAdditionalPeerConnection("screenshare",t)}async initAdditionalPeerConnection(t,e){const i=t==="screenshare";let r,n=null;try{return i&&this._screenShareStatus$.next("starting"),n=new Ec({...e,...this.RTCPeerConnectionConfig,propose:t,webRTCApiProvider:this.webRTCApiProvider},void 0,this.deviceController),this.setupLocalDescriptionHandler(n),i&&(this._screenShareId=n.id),this._rtcPeerConnectionsMap.set(n.id,n),this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values())),this.subscribeTo(n.errors$,s=>{var a;r??(r=s),(a=this.onError)==null||a.call(this,s,{fatal:!1})}),await Ze(n.connectionState$.pipe(B(s=>s==="connected"),Oe(1),Sr(this._screenShareTimeoutMs),S(this.destroyed$))),i&&this._screenShareStatus$.next("started"),H.info(`[WebRTCManager] Additional peer connection connected (${t}).`),n.id}catch(s){if(H.warn("[WebRTCManager] Error initializing additional peer connection:",s),n&&n.destroy(),i&&this._screenShareStatus$.next("none"),r)throw r instanceof Gt&&r.originalError instanceof Error?r.originalError:r;if(s instanceof wr){H.debug("[WebRTCManager] Additional peer connection aborted before connecting.");return}throw s instanceof Error?s:new Error(String(s),{cause:s})}}async removeInputDevices(t){return this.removeAdditionalPeerConnection(t)}removeMainInputDevice(t={removeAudio:!1,removeVideo:!0}){let e;if(t.removeAudio&&(e="audio"),t.removeVideo&&(e=e==="audio"?"both":"video"),e)return this.mainPeerConnection.stopTrackSender(e,{updateTransceiverDirection:!0})}async removeScreenMedia(){if(["starting","started"].includes(this._screenShareStatus$.value)||H.warn("[WebRTCManager] No active screen share to stop."),!this._screenShareId){H.debug("[WebRTCManager] No screen share peer connection found.");return}this._screenShareStatus$.next("stopping"),await this.removeAdditionalPeerConnection(this._screenShareId),this._screenShareId=void 0,this._screenShareStatus$.next("none")}async removeAdditionalPeerConnection(t){const e=this._rtcPeerConnectionsMap.get(t);try{e&&await this.executeVertoBye(e)}finally{e==null||e.destroy(),this._rtcPeerConnectionsMap.delete(t),this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values()))}}async executeVertoBye(t,e){try{const i=e?{cause:e,causeCode:Ig[e]}:{};await this.executeVerto(Tg({...i,dialogParams:this.dialogParams(t)}))}catch(i){throw H.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:",i),i}}async bye(t){this.attachManager.detach(this.buildAttachableCall());const e=this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);e&&await this.executeVertoBye(e,t)}async sendDigits(t){const e=Eg({sessid:this.webRtcCallSession.id,dialogParams:{callID:this.webRtcCallSession.id},dtmf:t});try{await this.executeVerto(e)}catch(i){throw H.warn("[WebRTCManager] Error sending DTMF digits:",i),i}}async transfer(t){const e=vn({...t,dialogParams:this.dialogParams(this.mainPeerConnection),action:"transfer"});try{H.debug("[WebRTCManager] Transferring call with options:",t),await this.executeVerto(e)}catch(i){throw H.error("[WebRTCManager] Error transferring call:",i),i}}destroy(){this._rtcPeerConnectionsMap.forEach(t=>{t.destroy()}),this._rtcPeerConnectionsMap.clear(),this._rtcPeerConnections$.complete(),super.destroy()}};const Ic=G();var ff=class extends se{constructor(t={}){super(),this._source=null,this._stream=null,this._audioContext=(t.audioContextFactory??(()=>new AudioContext))(),this._analyser=this._audioContext.createAnalyser(),this._analyser.fftSize=2048,this._analyser.smoothingTimeConstant=.3,this._analyserBuffer=new Uint8Array(new ArrayBuffer(this._analyser.fftSize)),this._pollIntervalMs=t.pollIntervalMs??Ro}get level$(){return this.deferEmission(en(this._pollIntervalMs,qa).pipe(x(()=>this.computeLevel())))}setStream(t){if(this._source){try{this._source.disconnect()}catch(e){Ic.debug("[RemoteAudioMeter] source disconnect warning:",e)}this._source=null,this._stream=null}!t||t.getAudioTracks().length===0||(this._stream=new MediaStream(t.getAudioTracks()),this._source=this._audioContext.createMediaStreamSource(this._stream))}destroy(){if(this._source){try{this._source.disconnect()}catch{}this._source=null}this._audioContext.close().catch(t=>{Ic.debug("[RemoteAudioMeter] audio context close warning:",t)}),super.destroy()}computeLevel(){if(!this._source)return 0;this._analyser.getByteTimeDomainData(this._analyserBuffer);let t=0;for(const e of this._analyserBuffer){const i=(e-128)/128;t+=i*i}return Math.sqrt(t/this._analyserBuffer.length)}};const Tr=G(),vf=1e3,bf=10,mf=2e3,yf=3e3,wf=3,Sf=5,Cf=5,Af=10,Tf=4,Ef=30;function kf(t,e){const i=t+e;return i===0?0:t/i*100}function xf(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="inbound-rtp"}function Df(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="candidate-pair"}var If=class extends se{constructor(t,e={}){super(),this.peerConnection=t,this.running=!1,this.lastAudioPacketsReceived=0,this.lastAudioPacketChangeTime=0,this.lastVideoPacketsReceived=0,this.lastVideoPacketChangeTime=0,this.lastRoundTripTime=0,this.lastAvailableOutgoingBitrate=void 0,this._sample$=this.createReplaySubject(1),this._baseline$=this.createBehaviorSubject({rtt:0,jitter:0,ready:!1}),this._networkIssues$=this.createBehaviorSubject([]),this._networkMetrics$=this.createBehaviorSubject([]),this.pollingIntervalMs=e.pollingIntervalMs??vf,this.baselineSampleCount=e.baselineSamples??bf,this.noAudioPacketThresholdMs=e.noAudioPacketThresholdMs??mf,this.noVideoPacketThresholdMs=e.noVideoPacketThresholdMs??yf,this.rttSpikeWarningMultiplier=e.rttSpikeWarningMultiplier??wf,this.rttSpikeCriticalMultiplier=e.rttSpikeCriticalMultiplier??Sf,this.packetLossWarningPercent=e.packetLossWarningPercent??Cf,this.packetLossCriticalPercent=e.packetLossCriticalPercent??Af,this.jitterSpikeMultiplier=e.jitterSpikeMultiplier??Tf,this.historyWindowSeconds=e.historyWindowSeconds??Ef}get networkIssues$(){return this._networkIssues$.asObservable()}get networkIssues(){return[...this._networkIssues$.value]}get isNetworkHealthy$(){return this.cachedObservable("isNetworkHealthy$",()=>this._networkIssues$.pipe(x(t=>t.length===0),U(),S(this.destroyed$)))}get isNetworkHealthy(){return this._networkIssues$.value.length===0}get networkMetrics$(){return this._networkMetrics$.asObservable()}get networkMetrics(){return[...this._networkMetrics$.value]}get criticalIssue$(){return this.cachedObservable("criticalIssue$",()=>this._networkIssues$.pipe(cs(t=>_e(t.filter(e=>e.severity==="critical"))),S(this.destroyed$)))}get sample$(){return this._sample$.asObservable()}start(){if(this.running)return;this.running=!0;const t=Date.now();this.lastAudioPacketChangeTime=t,this.lastVideoPacketChangeTime=t,Tr.debug("[RTCStatsMonitor] Starting stats monitoring"),this.subscribeTo(en(this.pollingIntervalMs).pipe(B(()=>this.running),Je(()=>_e(this.peerConnection.getStats()).pipe(ui(e=>(Tr.warn("[RTCStatsMonitor] Failed to get stats:",e),ci)))),B(()=>this.running),x(e=>this.extractSample(e))),e=>this._sample$.next(e)),this.subscribeTo(this._sample$.pipe(Oe(this.baselineSampleCount),Kd(),x(e=>({rtt:e.reduce((i,r)=>i+r.roundTripTime,0)/e.length,jitter:e.reduce((i,r)=>i+r.audioJitter,0)/e.length,ready:!0}))),e=>{Tr.debug(`[RTCStatsMonitor] Baseline established: rtt=${e.rtt.toFixed(1)}ms, jitter=${e.jitter.toFixed(1)}ms`),this._baseline$.next(e)}),this.subscribeTo(this._sample$.pipe(mo((e,i)=>({prev:e.current,current:i}),{prev:null,current:null}),B(e=>e.current!==null)),({prev:e,current:i})=>{const r=i.timestamp;this.updatePacketTracking(i,r);const n=this.detectIssues(i,e,r);this._networkIssues$.next(n)}),this.subscribeTo(this._sample$.pipe(mo((e,i)=>{const r=i.timestamp-this.historyWindowSeconds*1e3,n={timestamp:i.timestamp,audio:{packetsReceived:i.audioPacketsReceived,packetsLost:i.audioPacketsLost,jitter:i.audioJitter},video:{packetsReceived:i.videoPacketsReceived,packetsLost:i.videoPacketsLost},roundTripTime:i.roundTripTime,availableOutgoingBitrate:i.availableOutgoingBitrate};return[...e.filter(s=>s.timestamp>r),n]},[])),e=>this._networkMetrics$.next(e))}stop(){this.running&&(this.running=!1,Tr.debug("[RTCStatsMonitor] Stopping stats monitoring"))}destroy(){Tr.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor"),this.stop(),super.destroy()}extractSample(t){let e=0,i=0,r=0,n=0,s=0,a=0,o;return t.forEach(c=>{xf(c)&&(c.kind==="audio"?(e+=c.packetsReceived??0,i+=c.packetsLost??0,r=Math.max(r,(c.jitter??0)*1e3)):(n+=c.packetsReceived??0,s+=c.packetsLost??0)),Df(c)&&c.state==="succeeded"&&c.nominated&&(a=c.currentRoundTripTime?c.currentRoundTripTime*1e3:this.lastRoundTripTime,o=c.availableOutgoingBitrate??this.lastAvailableOutgoingBitrate)}),{audioPacketsReceived:e,audioPacketsLost:i,audioJitter:r,videoPacketsReceived:n,videoPacketsLost:s,roundTripTime:a,availableOutgoingBitrate:o,timestamp:Date.now()}}updatePacketTracking(t,e){t.audioPacketsReceived!==this.lastAudioPacketsReceived&&(this.lastAudioPacketsReceived=t.audioPacketsReceived,this.lastAudioPacketChangeTime=e),t.videoPacketsReceived!==this.lastVideoPacketsReceived&&(this.lastVideoPacketsReceived=t.videoPacketsReceived,this.lastVideoPacketChangeTime=e),t.roundTripTime>0&&(this.lastRoundTripTime=t.roundTripTime),t.availableOutgoingBitrate!==void 0&&(this.lastAvailableOutgoingBitrate=t.availableOutgoingBitrate)}detectIssues(t,e,i){const r=[],n=this._baseline$.value,s=i-this.lastAudioPacketChangeTime;s>this.noAudioPacketThresholdMs&&r.push({type:"no_inbound_audio",severity:"critical",timestamp:i,value:s,threshold:this.noAudioPacketThresholdMs});const a=i-this.lastVideoPacketChangeTime;if(a>this.noVideoPacketThresholdMs&&r.push({type:"no_inbound_video",severity:"warning",timestamp:i,value:a,threshold:this.noVideoPacketThresholdMs}),n.ready){const o=t.roundTripTime,c=n.rtt;if(c>0){const p=o/c;p>this.rttSpikeCriticalMultiplier?r.push({type:"high_rtt",severity:"critical",timestamp:i,value:o,threshold:c*this.rttSpikeCriticalMultiplier}):p>this.rttSpikeWarningMultiplier&&r.push({type:"high_rtt",severity:"warning",timestamp:i,value:o,threshold:c*this.rttSpikeWarningMultiplier})}const u=t.audioJitter,h=n.jitter;h>0&&u/h>this.jitterSpikeMultiplier&&r.push({type:"high_jitter",severity:"warning",timestamp:i,value:u,threshold:h*this.jitterSpikeMultiplier})}if(e){const o=Math.max(0,t.audioPacketsReceived-e.audioPacketsReceived),c=Math.max(0,t.audioPacketsLost-e.audioPacketsLost),u=Math.max(0,t.videoPacketsReceived-e.videoPacketsReceived),h=Math.max(0,t.videoPacketsLost-e.videoPacketsLost),p=o+u,v=kf(c+h,p);v>this.packetLossCriticalPercent?r.push({type:"high_packet_loss",severity:"critical",timestamp:i,value:v,threshold:this.packetLossCriticalPercent}):v>this.packetLossWarningPercent&&r.push({type:"high_packet_loss",severity:"warning",timestamp:i,value:v,threshold:this.packetLossWarningPercent})}return r}};const de=G(),Mf=2e3,Rf=1e4,Pf=3e3,_f=5e3,Of=3,Lf=3,Ff=3e3,Nf=1e4,Uf=150,Bf=300,zf=5,Vf=new Set(["high_rtt","high_jitter","high_packet_loss"]);var Hf=class extends se{constructor(t,e,i={}){super(),this._recoveryState$=this.createBehaviorSubject("idle"),this._recoveryEvent$=this.createSubject(),this._bandwidthConstrained$=this.createBehaviorSubject(!1),this._hasPacketLoss$=this.createBehaviorSubject(!1),this._trigger$=this.createSubject(),this._attemptCount=0,this._keyframeBurstCount=0,this._keyframeBurstStart=0,this._keyframeCooldownUntil=0,this._cooldownUntil=0,this._pipelineStop$=this.createSubject(),this._callbacks=t,this._inputs=e,this._config={debounceTimeMs:i.debounceTimeMs??Mf,cooldownMs:i.cooldownMs??Rf,iceGracePeriodMs:i.iceGracePeriodMs??Pf,iceRestartTimeoutMs:i.iceRestartTimeoutMs??_f,maxAttempts:i.maxAttempts??Of,enableRelayFallback:i.enableRelayFallback??!0,keyframeMaxBurst:i.keyframeMaxBurst??Lf,keyframeBurstWindowMs:i.keyframeBurstWindowMs??Ff,keyframeCooldownMs:i.keyframeCooldownMs??Nf,degradationBitrateThreshold:i.degradationBitrateThreshold??Uf,degradationRecoveryThreshold:i.degradationRecoveryThreshold??Bf,enableAutoDegradation:i.enableAutoDegradation??!0,packetLossRecoveryDelaySec:i.packetLossRecoveryDelaySec??zf},this.initPipeline(),this.initDegradationRecoveryPipeline()}get recoveryState$(){return this._recoveryState$.asObservable().pipe(S(this._destroyed$))}get recoveryState(){return this._recoveryState$.value}get recoveryEvent$(){return this._recoveryEvent$.asObservable().pipe(S(this._destroyed$))}get bandwidthConstrained$(){return this._bandwidthConstrained$.asObservable().pipe(S(this._destroyed$))}get bandwidthConstrained(){return this._bandwidthConstrained$.value}pushTrigger(t){this._trigger$.next(t)}async requestIceRestart(){if(this._recoveryState$.value==="recovering"){de.info("CallRecoveryManager: manual ICE restart skipped — recovery already in progress");return}de.info("CallRecoveryManager: manual ICE restart requested"),this.transitionTo("recovering"),await this.executeIceRestart(!1),this.startCooldown()}requestKeyframe(){this.executeKeyframe("manual request")}reset(){de.info("CallRecoveryManager: resetting counters"),this._attemptCount=0,this._keyframeBurstCount=0,this._keyframeBurstStart=0,this._keyframeCooldownUntil=0,this._cooldownUntil=0,this.transitionTo("idle")}notifyModifyFailed(){(this._recoveryState$.value==="cooldown"||this._recoveryState$.value==="idle")&&(de.info("CallRecoveryManager: verto.modify failed — re-entering recovery"),this._cooldownUntil=0,this.transitionTo("idle"),this.pushTrigger({source:"network",detail:"modify_failed_during_recovery"}))}reportBandwidth(t){if(!this._config.enableAutoDegradation)return;const e=this._bandwidthConstrained$.value;!e&&t<this._config.degradationBitrateThreshold?(this._bandwidthConstrained$.next(!0),this._callbacks.disableVideo(),this.emitEvent({action:"video_disabled",reason:`bandwidth ${t}kbps below threshold ${this._config.degradationBitrateThreshold}kbps`,timestamp:Date.now()}),de.warn(`CallRecoveryManager: disabling video — bandwidth ${t}kbps < ${this._config.degradationBitrateThreshold}kbps`)):e&&t>=this._config.degradationRecoveryThreshold&&(this._bandwidthConstrained$.next(!1),this._callbacks.enableVideo(),this.emitEvent({action:"video_restored",reason:`bandwidth ${t}kbps recovered above ${this._config.degradationRecoveryThreshold}kbps`,timestamp:Date.now()}),de.info(`CallRecoveryManager: restoring video — bandwidth ${t}kbps >= ${this._config.degradationRecoveryThreshold}kbps`))}reportNetworkIssues(t){const e=t.some(i=>i.type==="high_packet_loss");e!==this._hasPacketLoss$.value&&this._hasPacketLoss$.next(e)}handleWebSocketReconnect(){const t=this._callbacks.getPeerConnectionState();t==="connected"||t==="completed"?(de.info("CallRecoveryManager: signal-only reconnect — peer connection still alive"),this.emitEvent({action:"signal_reconnect",reason:"WebSocket reconnected, peer connection still connected",timestamp:Date.now()})):(de.info("CallRecoveryManager: full reconnect — peer connection also down"),this.emitEvent({action:"full_reconnect",reason:"WebSocket reconnected, peer connection not connected — ICE restart needed",timestamp:Date.now()}),this.pushTrigger({source:"network",detail:"full_reconnect_after_ws"})),this.reset()}destroy(){this._pipelineStop$.next(),this._pipelineStop$.complete(),super.destroy()}initPipeline(){this.subscribeTo(this._trigger$.pipe(Ee(()=>{this._recoveryState$.value==="idle"&&this.transitionTo("debouncing")}),vo(this._config.debounceTimeMs),yo(this._inputs.signalingReady$),B(([,t])=>this.passGateChecks(t)),x(([t])=>t),ls(t=>this.executeTieredRecovery(t)),S(Ni(this._destroyed$,this._pipelineStop$))),{next:()=>{},error:t=>{de.error("CallRecoveryManager: pipeline error",t),this.transitionTo("idle")}})}initDegradationRecoveryPipeline(){if(!this._config.enableAutoDegradation)return;const t=this._config.packetLossRecoveryDelaySec*1e3;this.subscribeTo(uo([this._bandwidthConstrained$,this._hasPacketLoss$]).pipe(Je(([e,i])=>e&&!i?Fi(t):ci),S(this._destroyed$)),()=>{this._bandwidthConstrained$.next(!1),this._callbacks.enableVideo(),this.emitEvent({action:"video_restored",reason:`no packet loss for ${this._config.packetLossRecoveryDelaySec}s — restoring video`,timestamp:Date.now()}),de.info(`CallRecoveryManager: restoring video — no packet loss for ${this._config.packetLossRecoveryDelaySec}s`)})}passGateChecks(t){return this._callbacks.isNegotiating()?(de.debug("CallRecoveryManager: gate blocked — negotiation in progress"),this.transitionTo("idle"),!1):t?this._callbacks.isCallConnected()?this.isCooldownActive()?(de.debug("CallRecoveryManager: gate blocked — cooldown active"),this.transitionTo("cooldown"),!1):!0:(de.debug("CallRecoveryManager: gate blocked — call not connected"),this.transitionTo("idle"),!1):(de.debug("CallRecoveryManager: gate blocked — signaling not ready"),this.transitionTo("idle"),!1)}isCooldownActive(){return Date.now()<this._cooldownUntil}executeTieredRecovery(t){return this.transitionTo("recovering"),de.info(`CallRecoveryManager: starting tiered recovery — source=${t.source} detail=${t.detail}`),_e(this.runTiers(t)).pipe(Ee(()=>this.startCooldown()),ui(e=>(de.error("CallRecoveryManager: tiered recovery failed",e),this.startCooldown(),ci)))}async runTiers(t){if(this.executeKeyframe(t.detail),t.issueType&&Vf.has(t.issueType)){de.debug(`CallRecoveryManager: degradation-only issue (${t.issueType}) — Tier 1 only, skipping ICE restart`);return}this._attemptCount<this._config.maxAttempts&&await this.executeIceRestart(!1)||this._config.enableRelayFallback&&this._attemptCount<this._config.maxAttempts&&await this.executeIceRestart(!0)||this._attemptCount>=this._config.maxAttempts&&(this.emitEvent({action:"max_attempts_reached",reason:`all ${this._config.maxAttempts} recovery attempts exhausted`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()}),de.warn("CallRecoveryManager: max recovery attempts reached"))}executeKeyframe(t){const e=Date.now();if(e<this._keyframeCooldownUntil){de.debug("CallRecoveryManager: keyframe request skipped — cooldown active");return}if(e-this._keyframeBurstStart>this._config.keyframeBurstWindowMs&&(this._keyframeBurstCount=0,this._keyframeBurstStart=e),this._keyframeBurstCount>=this._config.keyframeMaxBurst){this._keyframeCooldownUntil=e+this._config.keyframeCooldownMs,de.debug(`CallRecoveryManager: keyframe burst limit reached (${this._config.keyframeMaxBurst}), cooldown until ${this._keyframeCooldownUntil}`);return}this._keyframeBurstCount+=1,this._callbacks.requestKeyframe(),this.emitEvent({action:"keyframe_requested",reason:t,timestamp:e}),de.debug(`CallRecoveryManager: keyframe requested (burst ${this._keyframeBurstCount}/${this._config.keyframeMaxBurst})`)}async executeIceRestart(t){this._attemptCount+=1;const e=t?"Tier 3 (relay-only)":"Tier 2 (standard)";de.info(`CallRecoveryManager: ${e} ICE restart — attempt ${this._attemptCount}/${this._config.maxAttempts}`),this.emitEvent({action:"reinvite_started",reason:`${e} ICE restart`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()});try{return await this.withTimeout(this._callbacks.requestIceRestart(t),this._config.iceRestartTimeoutMs)?(this.emitEvent({action:"reinvite_succeeded",reason:`${e} ICE restart succeeded`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()}),de.info(`CallRecoveryManager: ${e} ICE restart succeeded`),this._attemptCount=0,!0):(this.emitEvent({action:"reinvite_failed",reason:`${e} ICE restart returned false`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()}),de.warn(`CallRecoveryManager: ${e} ICE restart failed`),!1)}catch{return this.emitEvent({action:"reinvite_timeout",reason:`${e} ICE restart timed out after ${this._config.iceRestartTimeoutMs}ms`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()}),de.warn(`CallRecoveryManager: ${e} ICE restart timed out`),!1}}async withTimeout(t,e){return new Promise((i,r)=>{const n=setTimeout(()=>{r(new Error(`Timeout after ${e}ms`))},e);t.then(s=>{clearTimeout(n),i(s)},s=>{clearTimeout(n),r(s instanceof Error?s:new Error(String(s)))})})}transitionTo(t){const e=this._recoveryState$.value;e!==t&&(de.debug(`CallRecoveryManager: state ${e} -> ${t}`),this._recoveryState$.next(t))}startCooldown(){this._cooldownUntil=Date.now()+this._config.cooldownMs,this.transitionTo("cooldown"),this._cooldownSubscription&&this._cooldownSubscription.unsubscribe(),this._cooldownSubscription=Fi(this._config.cooldownMs).pipe(Oe(1),S(this._destroyed$),B(()=>this._recoveryState$.value==="cooldown")).subscribe(()=>this.transitionTo("idle"))}emitEvent(t){this._recoveryEvent$.next(t)}},jf=class{constructor(t,e,i){this.executeMethod=t,this.vertoManager=e,this.deviceController=i}createSelfParticipant(t){return new uc(t,this.executeMethod,this.vertoManager,this.deviceController)}createParticipant(t){return new lc(t,this.executeMethod,this.deviceController)}};const Wf=93.2,Gf=.024,qf=2.5,Xf=0,Yf=100,Kf=1,Zf=5,Qf=4,Jf=3.5,$f=3,ev=2;function tv(t,e,i){const r=Wf-(t/2+e)*Gf-i*qf,n=Math.min(Yf,Math.max(Xf,r)),s=1+.035*n+n*(n-60)*(100-n)*7e-6;return Math.min(Zf,Math.max(Kf,s))}function iv(t){return t>=Qf?"excellent":t>=Jf?"good":t>=$f?"fair":t>=ev?"poor":"critical"}const Ce=G(),rv=5/3,nv=t=>{if(!t)return{};try{const e=new URL(`destination:${t}`),i={};return e.searchParams.forEach((r,n)=>{i[n]=r}),i}catch(e){return Ce.warn(`Failed to parse destination URI: ${t}`,e),{}}};var sv=class extends se{constructor(t,e,i,r){super(),this.clientSession=t,this.options=e,this.address=r,this._errors$=this.createReplaySubject(1),this._lastMergedStatus="new",this._answered$=this.createReplaySubject(),this._holdState=!1,this._userVariables$=this.createBehaviorSubject({...f.instance.userVariables}),this._networkIssues$=this.createBehaviorSubject([]),this._networkMetrics$=this.createBehaviorSubject([]),this._isNetworkHealthy$=this.createBehaviorSubject(!0),this._qualityScore$=this.createBehaviorSubject(5),this._qualityLevel$=this.createBehaviorSubject("excellent"),this._recoveryState$=this.createBehaviorSubject("idle"),this._recoveryEvent$=this.createSubject(),this._bandwidthConstrained$=this.createBehaviorSubject(!1),this._mediaParamsUpdated$=this.createSubject(),this._customSubscriptions=new Map,this._pushToTalkEnabled=!1,this._remoteAudioMeter=null,this.id=e.callId??dn(),this.to=e.to,this._userVariables$.next({...this._userVariables$.value,...nv(e.to),...e.userVariables}),this.subscribeTo(this.webrtcMessages$,o=>{const c=at(o,"params.userVariables");c&&this._userVariables$.next({...this._userVariables$.value,...c})});const n=i.initializeManagers(this);this.vertoManager=n.vertoManager,this.callEventsManager=n.callEventsManager,e.initOffer?(this._status$=this.createBehaviorSubject("ringing"),this._lastMergedStatus="ringing"):this._status$=this.createBehaviorSubject("new");const{deviceController:s,networkChange$:a}=i;this._networkChange$=a,this.participantFactory=new jf(this.executeMethod.bind(this),this.vertoManager,s),this.subscribeTo(Ni(this._status$.asObservable(),this.vertoManager.signalingStatus$).pipe(U(),S(this._destroyed$)),o=>{var c;this._lastMergedStatus=o,o==="connected"&&!this._statsMonitor?this.initResilienceSubsystems():o==="disconnected"?((c=this._statsMonitor)==null||c.destroy(),this._statsMonitor=void 0):(o==="destroyed"||o==="failed")&&this.stopResilienceSubsystems()})}get errors$(){return this.deferEmission(this._errors$.asObservable())}emitError(t){this._status$.value==="destroyed"||this._status$.value==="failed"||(this._errors$.next(t),t.fatal&&(this._status$.next("failed"),this.destroy()))}notifyModifyFailed(){var t;(t=this._recoveryManager)==null||t.notifyModifyFailed()}get direction(){return this.options.initOffer?"inbound":"outbound"}get address$(){return this.deferEmission(_e([this.address])).pipe(S(this._destroyed$))}get fromName(){return this.options.fromName}get from(){return this.options.from}get toName(){return this.options.toName}async toggleIncomingVideo(){throw new Tt}async toggleIncomingAudio(){throw new Tt}addCallId(t){this.callEventsManager.addCallId(t)}get capabilities(){return this.callEventsManager.capabilities}get participants(){return this.callEventsManager.participants}get self(){return this.callEventsManager.self}async toggleLock(){const t=this.locked?"call.unlock":"call.lock";await this.executeMethod(this.callSelf,t,{})}async toggleHold(){this._holdState?await this.vertoManager.unhold():await this.vertoManager.hold(),this._holdState=!this._holdState}async startRecording(){throw new Tt}async startStreaming(){throw new Tt}async setMeta(t){throw new Tt}async updateMeta(t){throw new Tt}get layoutLayers$(){return this.deferEmission(this.callEventsManager.layoutLayers$).pipe(S(this._destroyed$))}get layoutLayers(){return this.callEventsManager.layoutLayers}async executeMethod(t,e,i){var a,o,c;const r=this.callSelf;if(typeof t=="string"&&t!==r.member_id)throw new on(`Target member ID ${t} does not match call's self member ID ${r.member_id}`);const n={...i,self:r,target:typeof t=="string"?r:t},s=Hi({method:e,params:n});try{const u=await this.clientSession.execute(s);if(Ng(u))throw new Et(parseInt(((a=u.result)==null?void 0:a.code)??"0"),`Error response from method ${e}: ${(o=u.result)==null?void 0:o.code} ${(c=u.result)==null?void 0:c.message}`,void 0,void 0,s.id);return u}catch(u){throw Ce.error(`[Call] Error executing method ${e} with params`,n,u),u}}get callSelf(){const t=this.nodeId,e=this.vertoManager.selfId;if(!t||!e)throw new up(this.id);return{node_id:t,call_id:this.id,member_id:e}}get status$(){return this.publicCachedObservable("status$",()=>Ni(this._status$.asObservable(),this.vertoManager.signalingStatus$).pipe(U(),Ee(t=>{this._lastMergedStatus=t})))}get participants$(){return this.deferEmission(this.callEventsManager.participants$).pipe(S(this._destroyed$))}get self$(){return this.deferEmission(this.callEventsManager.self$).pipe(S(this._destroyed$))}get recording$(){return this.deferEmission(this.callEventsManager.recording$).pipe(S(this._destroyed$))}get streaming$(){return this.deferEmission(this.callEventsManager.streaming$).pipe(S(this._destroyed$))}get raiseHandPriority$(){return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe(S(this._destroyed$))}get locked$(){return this.deferEmission(this.callEventsManager.locked$).pipe(S(this._destroyed$))}get meta$(){return this.deferEmission(this.callEventsManager.meta$).pipe(S(this._destroyed$))}get capabilities$(){return this.deferEmission(this.callEventsManager.capabilities$).pipe(S(this._destroyed$))}get layout$(){return this.deferEmission(this.callEventsManager.layout$).pipe(S(this._destroyed$))}get status(){return this._lastMergedStatus}get recording(){return this.callEventsManager.recording}get streaming(){return this.callEventsManager.streaming}get raiseHandPriority(){return this.callEventsManager.raiseHandPriority}get locked(){return this.callEventsManager.locked}get meta(){return this.callEventsManager.meta}get layout(){return this.callEventsManager.layout}get layouts$(){return this.deferEmission(this.callEventsManager.layouts$).pipe(S(this._destroyed$))}get layouts(){return this.callEventsManager.layouts}get localStream$(){return this.deferEmission(this.vertoManager.localStream$).pipe(S(this._destroyed$))}get localStream(){return this.vertoManager.localStream}get remoteStream$(){return this.deferEmission(this.vertoManager.remoteStream$).pipe(S(this._destroyed$))}get remoteStream(){return this.vertoManager.remoteStream}get userVariables$(){return this.deferEmission(this._userVariables$.asObservable())}get userVariables(){return{...this._userVariables$.value}}set userVariables(t){this._userVariables$.next({...this._userVariables$.value,...t})}get networkIssues$(){return this.deferEmission(this._networkIssues$.asObservable())}get networkIssues(){return this._networkIssues$.value}get isNetworkHealthy$(){return this.deferEmission(this._isNetworkHealthy$.asObservable())}get isNetworkHealthy(){return this._isNetworkHealthy$.value}get networkMetrics$(){return this.deferEmission(this._networkMetrics$.asObservable())}get networkMetrics(){return this._networkMetrics$.value}get qualityScore$(){return this.deferEmission(this._qualityScore$.asObservable())}get qualityLevel$(){return this.deferEmission(this._qualityLevel$.asObservable())}get recoveryState$(){return this.deferEmission(this._recoveryState$.asObservable())}get recoveryEvent$(){return this.deferEmission(this._recoveryEvent$.asObservable())}get bandwidthConstrained$(){return this.deferEmission(this._bandwidthConstrained$.asObservable())}get mediaParamsUpdated$(){return this.deferEmission(this._mediaParamsUpdated$.asObservable())}emitMediaParamsUpdated(t){this._mediaParamsUpdated$.next(t)}requestKeyframe(){var t,e;(e=(t=this.vertoManager).requestKeyframe)==null||e.call(t)}async requestIceRestart(){var t,e;await((e=(t=this.vertoManager).requestIceRestart)==null?void 0:e.call(t))}initResilienceSubsystems(){const t=this.rtcPeerConnection;if(Ce.debug(`[Call] initResilienceSubsystems: pc=${t?"exists":"undefined"}, connectionState=${t==null?void 0:t.connectionState}`),!t){Ce.warn("[Call] No peer connection available, skipping resilience init");return}try{const e=f.instance;this._statsMonitor=new If(t,{pollingIntervalMs:e.statsPollingInterval,baselineSamples:e.statsBaselineSamples,noAudioPacketThresholdMs:e.statsNoPacketThreshold,rttSpikeWarningMultiplier:e.statsRttSpikeMultiplier,rttSpikeCriticalMultiplier:e.statsRttSpikeMultiplier*rv,packetLossWarningPercent:e.statsPacketLossThreshold*100,packetLossCriticalPercent:e.statsPacketLossThreshold*200,jitterSpikeMultiplier:e.statsJitterSpikeMultiplier,historyWindowSeconds:e.statsHistorySize}),this._recoveryManager=new Hf({requestKeyframe:()=>{var i,r;try{this.vertoManager.requestKeyframeAll?this.vertoManager.requestKeyframeAll():(r=(i=this.vertoManager).requestKeyframe)==null||r.call(i)}catch{}},requestIceRestart:async i=>{var r,n;try{this.vertoManager.requestIceRestartAll?await this.vertoManager.requestIceRestartAll(i):await((n=(r=this.vertoManager).requestIceRestart)==null?void 0:n.call(r,i))}catch{return!1}return this.waitForPeerConnectionConnected()},disableVideo:()=>{try{this.vertoManager.muteMainVideoInputDevice(),Ce.debug("[Call] Recovery manager disabled video")}catch{Ce.debug("[Call] Recovery manager failed to disable video")}},enableVideo:()=>{this.vertoManager.unmuteMainVideoInputDevice().catch(()=>{Ce.debug("[Call] Recovery manager failed to enable video")})},isNegotiating:()=>this.vertoManager.mainPeerConnection.isNegotiating,isCallConnected:()=>this._lastMergedStatus==="connected",getPeerConnectionState:()=>t.connectionState},{signalingReady$:this.clientSession.authenticated$},{debounceTimeMs:e.recoveryDebounceTime,cooldownMs:e.recoveryCooldown,iceGracePeriodMs:e.iceDisconnectedGracePeriod,iceRestartTimeoutMs:e.iceRestartTimeout,maxAttempts:e.maxRecoveryAttempts,enableRelayFallback:e.enableRelayFallback,keyframeMaxBurst:e.keyframeMaxBurst,keyframeBurstWindowMs:e.keyframeBurstWindow,keyframeCooldownMs:e.keyframeCooldown}),this.subscribeTo(this._statsMonitor.networkIssues$,i=>{var r;this._networkIssues$.next(i),(r=this._recoveryManager)==null||r.reportNetworkIssues(i)}),this.subscribeTo(this._statsMonitor.isNetworkHealthy$,i=>{this._isNetworkHealthy$.next(i)}),this.subscribeTo(this._statsMonitor.networkMetrics$,i=>{var r;if(this._networkMetrics$.next(i),i.length>0){const n=i[i.length-1],s=n.audio.packetsReceived+n.video.packetsReceived,a=n.audio.packetsLost+n.video.packetsLost,o=s+a>0?a/(s+a)*100:0,c=tv(n.roundTripTime,n.audio.jitter,o);this._qualityScore$.next(c),this._qualityLevel$.next(iv(c)),n.availableOutgoingBitrate!==void 0&&((r=this._recoveryManager)==null||r.reportBandwidth(n.availableOutgoingBitrate/1e3))}}),this.subscribeTo(this._statsMonitor.criticalIssue$,i=>{var r;(r=this._recoveryManager)==null||r.pushTrigger({source:"stats",detail:`${i.type}: ${i.severity}`,issueType:i.type})}),this.subscribeTo(this._recoveryManager.recoveryState$,i=>{this._recoveryState$.next(i)}),this.subscribeTo(this._recoveryManager.recoveryEvent$,i=>{this._recoveryEvent$.next(i),i.action==="max_attempts_reached"&&(Ce.warn("[Call] All recovery attempts exhausted, terminating call"),this.emitError({kind:"network",fatal:!0,error:new Error("Call recovery failed: all attempts exhausted"),callId:this.id}))}),this.subscribeTo(this._recoveryManager.bandwidthConstrained$,i=>{this._bandwidthConstrained$.next(i)}),this._networkChange$&&this.subscribeTo(this._networkChange$,i=>{var r,n;i.type==="offline"?(r=this._recoveryManager)==null||r.pushTrigger({source:"network",detail:"browser went offline"}):i.type==="online"&&((n=this._recoveryManager)==null||n.handleWebSocketReconnect())}),this.subscribeTo(this.clientSession.authenticated$.pipe(tn(1),B(Boolean)),()=>{var i;Ce.debug("[Call] WebSocket reconnected — notifying recovery manager"),(i=this._recoveryManager)==null||i.handleWebSocketReconnect()}),this._statsMonitor.start(),Ce.debug("[Call] Resilience subsystems initialized for call",this.id)}catch(e){Ce.warn("[Call] Failed to initialize resilience subsystems:",e)}}async waitForPeerConnectionConnected(){const t=this.rtcPeerConnection;if(!t)return!1;const e=Date.now()+Bh;for(;;){const i=t.connectionState;if(i==="connected")return!0;if(i==="failed"||i==="closed"||Date.now()>=e)return!1;await new Promise(r=>setTimeout(r,zh))}}stopResilienceSubsystems(){var t,e;try{(t=this._statsMonitor)==null||t.destroy(),(e=this._recoveryManager)==null||e.destroy()}catch{}this._statsMonitor=void 0,this._recoveryManager=void 0}createParticipant(t,e){return t===(e??this.vertoManager.selfId)?this.participantFactory.createSelfParticipant(t):this.participantFactory.createParticipant(t)}get mediaDirections$(){return this.deferEmission(this.vertoManager.mediaDirections$).pipe(S(this._destroyed$))}get mediaDirections(){return this.vertoManager.mediaDirections}get participantsId$(){return this.cachedObservable("participantsId$",()=>this.participants$.pipe(x(t=>t.map(e=>e.id))))}async execute(t,e){return this.clientSession.execute(t,e)}get selfId$(){return this.vertoManager.selfId$}get selfId(){return this.vertoManager.selfId}get nodeId$(){return this.vertoManager.nodeId$}get nodeId(){return this.vertoManager.nodeId}isCallSessionEvent(t){try{Ce.debug("[Call] Checking if event is for this call session:",t);const e=at(t,"params.params.callID")??at(t,"params.call_id"),i=at(t,"params.room_session_id");return Ce.debug(`[Call] Extracted session identifiers callID: ${e} and roomSessionID: ${i} from event:`),e===this.id||!!e&&this.callEventsManager.isCallIdValid(e)||!!i&&this.callEventsManager.isRoomSessionIdValid(i)}catch(e){return Ce.error("[Call] Error checking if event is for this call session:",e),!1}}get callSessionEvents$(){return this.cachedObservable("callSessionEvents$",()=>this.clientSession.signalingEvent$.pipe(B(t=>this.isCallSessionEvent(t)),Ee(t=>{Ce.debug("[Call] Received call session event:",t)}),S(this.destroyed$),At()))}get callUpdated$(){return this.publicCachedObservable("callUpdated$",()=>this.callSessionEvents$.pipe(Se(pc,"params"),S(this.destroyed$)))}get memberJoined$(){return this.publicCachedObservable("memberJoined$",()=>this.callSessionEvents$.pipe(Se(vc,"params"),S(this.destroyed$)))}get memberLeft$(){return this.publicCachedObservable("memberLeft$",()=>this.callSessionEvents$.pipe(Se(bc,"params"),S(this.destroyed$)))}get memberUpdated$(){return this.publicCachedObservable("memberUpdated$",()=>this.callSessionEvents$.pipe(Se(fc,"params"),S(this.destroyed$)))}get memberTalking$(){return this.publicCachedObservable("memberTalking$",()=>this.callSessionEvents$.pipe(Se(mc,"params"),S(this.destroyed$)))}get callStates$(){return this.publicCachedObservable("callStates$",()=>this.callSessionEvents$.pipe(Se(gc,"params"),S(this.destroyed$)))}get layoutUpdates$(){return this.publicCachedObservable("layoutUpdates$",()=>this.callSessionEvents$.pipe(Se(ks,"params"),S(this.destroyed$)))}get rtcPeerConnection(){return this.vertoManager.mainPeerConnection.peerConnection}get signalingEvent$(){return this.publicCachedObservable("signalingEvent$",()=>this.callEvent$.pipe(x(t=>JSON.parse(JSON.stringify(t)))))}subscribe(t){const e=this._customSubscriptions.get(t);if(e)return e;const i=this.callSessionEvents$.pipe(B(r=>r.event_type===t),x(r=>JSON.parse(JSON.stringify(r))),S(this._destroyed$));return this._sendVertoSubscribe(t).then(()=>{this._customSubscriptions.set(t,i)},r=>{this._customSubscriptions.delete(t),Ce.warn(`[Call] verto.subscribe for '${t}' failed, not caching:`,r)}),this._customSubscriptions.set(t,i),i}get webrtcMessages$(){return this.cachedObservable("webrtcMessages$",()=>this.callSessionEvents$.pipe(Se(bn,"params"),Ee(t=>Ce.debug("[Call] Event is a WebRTC message event:",t)),S(this.destroyed$),At()))}get callEvent$(){return this.cachedObservable("callEvent$",()=>this.callSessionEvents$.pipe(Se(Ug,"params"),Ee(t=>Ce.debug("[Call] Event is a call event:",t)),S(this.destroyed$),At()))}get layoutEvent$(){return this.cachedObservable("layoutEvent$",()=>this.callEvent$.pipe(Se(ks,"params")))}async hangup(){this._status$.next("disconnecting");try{await this.vertoManager.bye()}finally{this.destroy()}}async sendDigits(t){return this.vertoManager.sendDigits(t)}answer(t){this._answerMediaOptions=t,this._answered$.next(!0)}get answerMediaOptions(){return this._answerMediaOptions}reject(){this._answered$.next(!1)}get answered$(){return this.deferEmission(this._answered$.asObservable())}async setLayout(t,e){if(!this.layouts.includes(t))throw new on(`Layout ${t} is not available in the current call layouts: ${this.layouts.join(", ")}`);const i=[];for(const[n,s]of Object.entries(e??{})){const a=this.participants.find(o=>o.id===n);if(!a){Ce.warn(`[Call] setLayout: member ${n} not found in participants; skipping position ${s}`);continue}a.target,i.push([a,s])}const r=await Ze(this.selfId$.pipe(B(n=>n!==null)));await this.executeMethod(r,"call.layout.set",{layout:t});for(const[n,s]of i)await n.setPosition(s)}async transfer(t){return this.vertoManager.transfer(t)}setLocalMicrophoneGain(t){const e=this.vertoManager.ensureLocalAudioPipeline();if(!e){Ce.warn("[Call] setLocalMicrophoneGain: audio pipeline unavailable");return}const i=Math.max(0,Math.min(200,t));e.setGain(i/100)}get localMicrophoneGain$(){const t=this.vertoManager.ensureLocalAudioPipeline();return t?this.publicCachedObservable("localMicrophoneGain$",()=>t.gain$.pipe(x(e=>e*100),S(this._destroyed$))):Ct(100).pipe(S(this._destroyed$))}get localAudioLevel$(){const t=this.vertoManager.ensureLocalAudioPipeline();return t?this.publicCachedObservable("localAudioLevel$",()=>t.level$.pipe(S(this._destroyed$),At())):Ct(0).pipe(S(this._destroyed$))}get localSpeaking$(){const t=this.vertoManager.ensureLocalAudioPipeline();return t?this.publicCachedObservable("localSpeaking$",()=>t.speaking$.pipe(S(this._destroyed$),At())):Ct(!1).pipe(S(this._destroyed$))}enablePushToTalk(){const t=this.vertoManager.ensureLocalAudioPipeline();if(!t){Ce.warn("[Call] enablePushToTalk: audio pipeline unavailable");return}t.setPTTActive(!1),this._pushToTalkEnabled=!0}disablePushToTalk(){var t;(t=this.vertoManager.localAudioPipeline)==null||t.setPTTActive(!0),this._pushToTalkEnabled=!1}setPushToTalkActive(t){var e;this._pushToTalkEnabled&&((e=this.vertoManager.localAudioPipeline)==null||e.setPTTActive(t))}async setEchoCancellation(t){await this.vertoManager.updateMediaConstraints({audio:{echoCancellation:t}})}async setNoiseSuppression(t){await this.vertoManager.updateMediaConstraints({audio:{noiseSuppression:t}})}async setAutoGainControl(t){await this.vertoManager.updateMediaConstraints({audio:{autoGainControl:t}})}get remoteAudioLevel$(){return this.publicCachedObservable("remoteAudioLevel$",()=>{this._remoteAudioMeter??(this._remoteAudioMeter=new ff);const t=this._remoteAudioMeter;return this.subscribeTo(this.vertoManager.remoteStream$,e=>{t.setStream(e)}),t.level$.pipe(S(this._destroyed$),At())})}destroy(){var t;this._status$.value!=="destroyed"&&(this._status$.next("destroyed"),this.stopResilienceSubsystems(),(t=this._remoteAudioMeter)==null||t.destroy(),this._remoteAudioMeter=null,this.vertoManager.destroy(),this.callEventsManager.destroy(),super.destroy())}async _sendVertoSubscribe(t){const e=xg({sessid:this.id,eventChannel:[t]}),i={callID:this.id,node_id:this.vertoManager.nodeId??"",message:e};await this.clientSession.execute(sc(i))}};function av(t){return t instanceof an?"timeout":t instanceof Et?"signaling":t instanceof kt||t instanceof Gt?"media":t instanceof Po||t instanceof _o?"network":"internal"}const ov=new Set([hs,ps,Mo]);function cv(t){return t instanceof No||t instanceof kt?!1:t instanceof Gt?t.fatal:!(t instanceof an||t instanceof Et&&ov.has(t.code))}var lv=class{constructor(t,e,i,r,n){this.sessionManager=t,this.deviceController=e,this.attachManager=i,this.webRTCApiProvider=r,this.networkChange$=n}createCall(t,e){return new sv(this.sessionManager,e,{initializeManagers:i=>({vertoManager:new gf(i,this.attachManager,this.deviceController,this.webRTCApiProvider,{nodeId:e.nodeId,onError:(r,n)=>{const s={kind:av(r),fatal:(n==null?void 0:n.fatal)??cv(r),error:r,callId:i.id};i.emitError(s)},onModifyFailed:()=>{i.notifyModifyFailed()}}),callEventsManager:new Xg(i)}),deviceController:this.deviceController,networkChange$:this.networkChange$},t)}};const Is=G();var Mc=class{constructor(t,e,i){this.endpoint=t,this.http=i,this.filter=r=>!0,this.mapper=r=>r,this.nextUrl=`${this.endpoint}?${e}`}async next(){if(!this.nextUrl)return this.hasMore=!1,[];const t=await this.http.request({...ms,url:this.nextUrl});if(t.ok&&t.body){const e=JSON.parse(t.body);return this.nextUrl=e.links.next,this.hasMore=!!this.nextUrl,e.data.filter(this.filter).map(this.mapper)}return Is.error("Failed to fetch entity"),[]}async id(t){const e=await this.http.request({...ms,url:`${this.endpoint}/${String(t)}`});if(e.ok&&e.body)return JSON.parse(e.body)}},Rc=class extends se{constructor(t,e,i){super(),this.fetchController=t,this.update$=e,this.onError=i,this.collectionData=new Map,this.observablesRegistry=new Map,this.upsertData=r=>{var o;if(!r.id)return;const n=this.collectionData.get(r.id)??{},s={},a=new Set([...Object.keys(n),...Object.keys(r)]);for(const c of a){const u=n[c],h=r[c];h!==void 0&&u!==void 0&&typeof u=="object"&&u!==null&&!Array.isArray(u)&&typeof h=="object"&&h!==null&&!Array.isArray(h)?s[c]={...u,...h}:h!==void 0?s[c]=h:s[c]=u}this.collectionData.set(r.id,s),(o=this.observablesRegistry.get(r.id))==null||o.next(s),this._values$.next(Array.from(this.collectionData.values()))},this._loading$=this.createBehaviorSubject(!1),this._values$=this.createReplaySubject(1),this._hasMore$=this.createBehaviorSubject(!0),this.subscribeTo(this.update$,this.upsertData),this.hasMore$=li(()=>_e(this.init())).pipe(Je(()=>this._hasMore$),U(),st(1),S(this.destroyed$))}get loading$(){return this._loading$.asObservable()}get loading(){return this._loading$.value}get values$(){return this._values$.asObservable()}get hasMore(){return this.fetchController.hasMore??!0}get updated$(){return this.cachedObservable("updated$",()=>this._loading$.pipe(U(),tn(1),B(t=>!t),x(()=>{}),S(this.destroyed$)))}get values(){return Array.from(this.collectionData.values())}async init(){if(this.fetchController.hasMore===!1){this._hasMore$.next(!1);return}await this.fetchMore()}async fetchMore(){var t;try{this._loading$.next(!0),(await this.fetchController.next()).forEach(this.upsertData),this._hasMore$.next(this.fetchController.hasMore??!1),this._loading$.next(!1)}catch(e){Is.error("Failed to fetch initial collection data",e),this._hasMore$.next(this.fetchController.hasMore??!1),this._loading$.next(!1),(t=this.onError)==null||t.call(this,new Uo("fetchMore",e))}}async tryFetch(t,e){var i,r,n;try{this._loading$.next(!0);const s=await((r=(i=this.fetchController)[t])==null?void 0:r.call(i,e));return this._loading$.next(!1),s&&this.upsertData(s),s}catch(s){Is.error(`Failed to fetch data for (${String(t)}:${String(e)}) :`,s),this._loading$.next(!1),(n=this.onError)==null||n.call(this,new Uo(`tryFetch(${String(t)})`,s))}}get$(t){var e,i;if(!this.observablesRegistry.has(t)){this.observablesRegistry.set(t,new is(1));const r=this.collectionData.get(t);r?(e=this.observablesRegistry.get(t))==null||e.next(r):this.tryFetch("id",t)}return(i=this.observablesRegistry.get(t))==null?void 0:i.asObservable()}async find$(t,e){const i=Array.from(this.collectionData.values()).find(r=>r[t]===e)??await this.tryFetch(t,e);return i?this.get$(i.id):void 0}loadMore(){this.fetchController.hasMore!==!1&&this.fetchMore()}destroy(){this.observablesRegistry.forEach(t=>t.complete()),this.observablesRegistry.clear(),super.destroy()}},Pc=class{constructor(t,e=r=>!!r,i=r=>r){this.originalCollection=t,this.filter=e,this.mapper=i}get loading$(){return this.originalCollection.loading$}get loading(){return this.originalCollection.loading}get hasMore$(){return this.originalCollection.hasMore$}get hasMore(){return this.originalCollection.hasMore}get values(){return this.originalCollection.values.filter(this.filter).map(this.mapper)}get values$(){return this._values$??(this._values$=this.originalCollection.values$.pipe(x(t=>t.filter(this.filter).map(this.mapper))))}get$(t){const e=this.originalCollection.get$(t);return e&&e.pipe(Jr(B(this.filter),x(this.mapper)))}async find$(t,e){const i=await this.originalCollection.find$(t,e);return i&&i.pipe(Jr(B(this.filter),x(this.mapper)))}loadMore(){this.originalCollection.loadMore()}destroy(){this.originalCollection.destroy()}},_c=class extends se{constructor(t,e,i){super(),this.addressId=t,this.conversationManager=e,this.addressProvider=i,this.initConversationMessages=async()=>(this._conversationMessages=this._conversationMessages??await this.conversationManager.getConversationMessageCollection(this.id),this._conversationMessages.hasMore&&this._conversationMessages.loadMore(),this._conversationMessages),this.textMessages$=li(this.initConversationMessages).pipe(x(()=>this.textMessage),st(1),S(this.destroyed$)),this.history$=li(this.initConversationMessages).pipe(x(()=>this.history),st(1),S(this.destroyed$)),this._state$=this.createBehaviorSubject(null)}upnext(t){const e={...this._state$.value,...t};this._state$.next(e)}get state(){return this._state$.value}get id(){return this.addressId}get name(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.name}get createdAt(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.created_at}get defaultChannel(){return this.type==="room"?this.channels.video:this.channels.audio}get displayName$(){return this.cachedObservable("displayName$",()=>this._state$.pipe(ve(),x(t=>t.display_name),S(this.destroyed$)))}get displayName(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.display_name}get previewUrl$(){return this.cachedObservable("previewUrl$",()=>this._state$.pipe(ve(),x(t=>t.preview_url),S(this.destroyed$)))}get previewUrl(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.preview_url}get coverUrl$(){return this.cachedObservable("coverUrl$",()=>this._state$.pipe(ve(),st(1),x(t=>t.cover_url),S(this.destroyed$)))}get coverUrl(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.cover_url}get resourceId$(){return this.cachedObservable("resourceId$",()=>this._state$.pipe(ve(),st(1),x(t=>t.resource_id),S(this.destroyed$)))}get resourceId(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.resource_id}get type$(){return this.cachedObservable("type$",()=>this._state$.pipe(ve(),st(1),x(t=>t.type),S(this.destroyed$)))}get type(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.type}get channels$(){return this.cachedObservable("channels$",()=>this._state$.pipe(ve(),st(1),x(t=>t.channels),S(this.destroyed$)))}get channels(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.channels}get locked(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.locked}get locked$(){return this.cachedObservable("locked$",()=>this._state$.pipe(ve(),st(1),x(t=>t.locked),S(this.destroyed$)))}async sendText(t){return this.conversationManager.sendText(t,this.id)}get textMessage(){if(this._conversationMessages)return this._textMessages$=this._textMessages$??new Pc(this._conversationMessages,t=>t.subtype==="chat",t=>({id:t.id,text:t.text,created:t.ts,fromAddress$:this.addressProvider.get$(t.from_fabric_address_id)})),this._textMessages$}get history(){if(this._conversationMessages)return this._history$=this._history$??new Pc(this._conversationMessages,t=>t.subtype==="log",t=>({id:t.id,kind:t.kind,status:t.details.status,started:t.details.start_time,ended:t.details.end_time,fromAddress$:this.addressProvider.get$(t.from_fabric_address_id)})),this._history$}get activity$(){throw new Tt}get activity(){throw new Tt}};const vi=G(),uv=t=>{if(vi.debug("isRPCConnectResult check:",t),!t||typeof t!="object")return!1;const e=t,i=typeof e.identity=="string"&&typeof e.protocol=="string"&&typeof e.authorization=="object"&&typeof e.authorization.jti=="string"&&typeof e.authorization.project_id=="string"&&typeof e.authorization.fabric_subscriber=="object";return vi.debug("isRPCConnectResult check result:",i),i};var dv=(Ai=class{constructor(e,i,r){this.id=dn(),vi.debug(`[PendingRPC(${this.id}) request:${e.id}: method:${e.method}] Creating PendingRPC`),this.request=e;const n=(r==null?void 0:r.timeoutMs)??Ai.defaultTimeoutMs,s=r==null?void 0:r.signal;this.promise=new Promise((a,o)=>{if(s!=null&&s.aborted){o(new DOMException("The operation was aborted","AbortError"));return}let c=!1;const u=Cr(i.pipe(B(h=>h.id===e.id),Oe(1)),new Ae(h=>{const p=setTimeout(()=>{h.error(new an(e.id,n))},n);return()=>clearTimeout(p)}),s?new Ae(h=>{const p=()=>{h.error(new DOMException("The operation was aborted","AbortError"))};return s.addEventListener("abort",p),()=>s.removeEventListener("abort",p)}):Vd).subscribe({next:h=>{if(c=!0,h.error){const p=new Et(h.error.code,h.error.message,h.error.data,void 0,e.id);vi.debug(`[PendingRPC(${this.id}) request:${e.id}] Rejecting promise with RPC error:`,p),o(p)}else vi.debug(`[PendingRPC(${this.id}) request:${e.id}] Resolving promise with response:`,h),a(h);u.unsubscribe()},error:h=>{vi.debug(`[PendingRPC(${this.id}) request:${e.id}] Rejecting promise with error:`,h),c=!0,o(h),u.unsubscribe()},complete:()=>{vi.debug(`[PendingRPC(${this.id}) request:${e.id}] Observable completed`),c||o(new an(e.id,n)),u.unsubscribe()}})})}async then(e,i){return this.promise.then(e,i)}async catch(e){return this.promise.catch(e)}async finally(e){return this.promise.finally(e)}},Ai.defaultTimeoutMs=5e3,Ai);const Z=G();function hv(t){return t.fatal||!(t.error instanceof Gt)}const pv=t=>{var n,s;const e=(n=t.to)==null?void 0:n.split("?")[0],i=(s=t.from)!=null&&s.startsWith("subscriber://")?t.from.replace("subscriber://",""):t.from,r=e??i;if(!r)throw new Ui("Error building Address name");return r};var gv=class extends se{constructor(t,e,i,r,n,s,a,o,c){super(),this.getCredential=t,this.transport=e,this.storage=i,this.authorizationStateKey=r,this.attachManager=s,this.dpopManager=o,this.callCreateTimeout=6e3,this.agent="signalwire-js/4.0.0",this.eventAcks=!0,this.authorizationState$=this.createReplaySubject(1),this.connectVersion={major:4,minor:0,revision:0},this._authorization$=this.createBehaviorSubject(void 0),this._errors$=this.createReplaySubject(1),this._authState$=this.createBehaviorSubject({kind:"unauthenticated"}),this._wasClientBound=!1,this._userInfo$=this.createBehaviorSubject(null),this._calls$=this.createBehaviorSubject({}),this._iceServers$=this.createBehaviorSubject([]),s.setSession(this),this.callFactory=new lv(this,n,s,a,c),this.initialized$=li(()=>_e(this.init())).pipe(st(1),S(this.destroyed$))}get incomingCalls$(){return this.cachedObservable("incomingCalls$",()=>this.calls$.pipe(x(t=>t.filter(e=>e.direction==="inbound"))))}get incomingCalls(){return Object.values(this._calls$.value).filter(t=>t.direction==="inbound")}get userInfo$(){return this._userInfo$.asObservable()}get userInfo(){return this._userInfo$.value}get calls$(){return this.cachedObservable("calls$",()=>this._calls$.pipe(x(t=>Object.values(t))))}get calls(){return Object.values(this._calls$.value)}get iceServers(){return this._iceServers$.value}get authorization$(){return this._authorization$.asObservable()}get authorization(){return this._authorization$.value}get errors$(){return this._errors$.asObservable()}get authenticated$(){return this._authState$.pipe(x(t=>t.kind==="authenticated"),U())}get authenticated(){return this._authState$.value.kind==="authenticated"}get clientBound(){return this._wasClientBound}get authState(){return this._authState$.value}setDirectory(t){this._directory=t}async execute(t,e){try{return await this.transport.execute(t,e)}catch(i){throw Z.debug("[Session] Execute Error",i),this._errors$.next(i instanceof Error?i:new Error(String(i),{cause:i})),i}}send(t){this.transport.send(t)}async init(){return await this.loadAuthorizationStateFromStorage(),this.setupMessageHandlers(),!0}setupMessageHandlers(){Z.debug("[Session] Setting up message handlers"),this.subscribeTo(this.authStateEvent$,async t=>{Z.debug("[Session] Authorization state event received:",t);try{await this.updateAuthorizationStateInStorage(t.authorization_state)}catch(e){Z.error("[Session] Failed to handle authorization state update:",e),this._errors$.next(new gs(e))}}),this.subscribeTo(this.transport.connectionStatus$.pipe(B(t=>t==="disconnected"||t==="reconnecting")),()=>{this._authState$.value.kind==="authenticated"&&this._authState$.next({kind:"unauthenticated"})}),this.subscribeTo(this.transport.connectionStatus$.pipe(B(t=>t==="connected"),ls(()=>(Z.debug("[Session] Connection established, initiating authentication"),_e(this.authenticate()).pipe(ui(t=>(this.handleAuthenticationError(t).catch(e=>{Z.error("[Session] Error handling authentication failure:",e)}),ci)))))),void 0),this.subscribeTo(this.vertoInvite$,async t=>{Z.debug("[Session] Verto invite received:",t);try{await this.createInboundCall(t)}catch(e){Z.error("[Session] Error handling Verto invite:",e),this._errors$.next(new hp(e))}}),this.subscribeTo(this.vertoAttach$,async t=>{Z.debug("[Session] Verto attach received:",t);try{await this.handleVertoAttach(t)}catch(e){Z.error("[Session] Error handling Verto attach:",e),this._errors$.next(new pp(e))}})}async loadAuthorizationStateFromStorage(){try{const t=await this.storage.getItem(this.authorizationStateKey);this.authorizationState$.next(t??void 0)}catch(t){Z.error("Failed to retrieve authorization state from storage:",t),this.authorizationState$.next(void 0)}}async updateAuthorizationStateInStorage(t){if(!t){Z.debug("[Session] Removing authorization state from storage");try{await this.storage.removeItem(this.authorizationStateKey),this.authorizationState$.next(void 0)}catch(e){throw Z.error("Failed to remove authorization state from storage:",e),e}return}try{Z.debug("[Session] Updating authorization state in storage"),await this.storage.setItem(this.authorizationStateKey,t),this.authorizationState$.next(t)}catch(e){throw Z.error("Failed to retrieve authorization state from storage:",e),e}}get authStateEvent$(){return this.cachedObservable("authStateEvent$",()=>this.signalingEvent$.pipe(Ee(t=>{Z.debug("[Session] Received incoming message:",t)}),Se(Bg,"params"),Ee(t=>{Z.debug("[Session] Authorization state event received:",t.authorization_state)})))}get signalingEvent$(){return this.cachedObservable("signalingEvent$",()=>this.transport.incomingEvent$.pipe(Se(Es,"params"),At()))}get vertoInvite$(){return this.cachedObservable("vertoInvite$",()=>this.signalingEvent$.pipe(B(bn),B(t=>kc(t.params)),x(t=>({node_id:t.node_id,...t.params.params}))))}get vertoAttach$(){return this.cachedObservable("vertoAttach$",()=>this.signalingEvent$.pipe(B(bn),B(t=>xc(t.params)),x(t=>({node_id:t.node_id,...t.params.params}))))}get contexts(){return[]}get eventing(){return[]}get topics(){return[]}get authentication(){const t=this.getCredential();if(!t.token)throw new te("Credential token is undefined");return{jwt_token:t.token}}async connect(){await Ze(this.initialized$),await this.transport.connect(),await Ze(this.authenticated$.pipe(S(this.destroyed$),B(Boolean),Oe(1),Sr({first:15e3})))}async handleAuthenticationError(t){Z.error("Authentication error:",t);const e=t instanceof Et&&(t.code===hs||t.code===Mo||t.code===ps),i=await Ze(this.authorizationState$.pipe(Oe(1)))!==void 0;if(e&&i){Z.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");try{await this.cleanupStoredConnectionParams()}catch(r){Z.error("Failed to cleanup stored connection params:",r)}finally{this.transport.reconnect()}}else this._errors$.next(t)}async cleanupStoredConnectionParams(){await this.transport.setProtocol(void 0),await this.updateAuthorizationStateInStorage(void 0),this._authorization$.next(void 0)}async teardownSessionState(){await this.cleanupStoredConnectionParams(),await this.attachManager.detachAll()}async updateAuthState(t){try{await this.storage.setItem(this.authorizationStateKey,t)}catch(e){Z.error("Failed to update authorization state in storage:",e),this._errors$.next(new gs(e))}}async reauthenticate(t,e,i){var r,n;Z.debug("[Session] Re-authenticating session");try{let s=e;if(!s&&((r=this.dpopManager)!=null&&r.initialized))try{s=await this.dpopManager.createRpcProof({method:"signalwire.reauthenticate"})}catch(o){if(this.clientBound)throw o;Z.warn("[Session] Failed to create DPoP proof for reauthenticate:",o)}const a=mg({project:((n=this._authorization$.value)==null?void 0:n.project_id)??"",jwt_token:t,...s?{dpop_token:s}:{}});await oo(_e(this.transport.execute(a)).pipe(jo(),Oe(1),ui(o=>{throw Z.error("[Session] Re-authentication RPC failed:",o),o}))),i!=null&&i.clientBound&&(this._wasClientBound=!0),Z.debug("[Session] Re-authentication successful, updating stored auth state")}catch(s){throw Z.error("[Session] Re-authentication failed:",s),this._errors$.next(new gs(s)),s}}async authenticate(){var o,c;Z.debug("[Session] Starting authentication process");const t=await Ze(uo({protocol:this.transport.protocol$,authorization_state:this.authorizationState$}).pipe(Oe(1)));Z.debug(`[Session] Persisted params:
73
- `,{protocol:t.protocol,authStateLength:(o=t.authorization_state)==null?void 0:o.length});const e=t.authorization_state&&t.protocol,i=this.getCredential().token,r=e&&i;let n;if(r)Z.debug("[Session] Reconnecting with stored jwt_token + authorization_state");else{const u=this.getCredential(),h=u.expiry_at!==void 0&&u.expiry_at<=Date.now()+bh;this.onBeforeReconnect&&(this.clientBound||h)&&(Z.debug("[Session] Refreshing credentials before fresh connect"),await this.onBeforeReconnect())}if((!r||this.clientBound)&&((c=this.dpopManager)!=null&&c.initialized))try{n=await this.dpopManager.createRpcProof({method:"signalwire.connect"})}catch(u){if(this.clientBound)throw u;Z.warn("[Session] Failed to create DPoP proof for connect, proceeding without:",u)}const s=bg({authentication:r?{jwt_token:i}:this.authentication,version:this.connectVersion,agent:this.agent,contexts:this.contexts,eventing:this.eventing,topics:this.topics,event_acks:this.eventAcks,...n?{dpop_token:n}:{},...r?{authorization_state:t.authorization_state,protocol:t.protocol}:{}}),a=await oo(_e(this.transport.execute(s)).pipe(jo(),x(u=>u.result),B(uv),Ee(()=>{Z.debug("[Session] Response passed filter, processing authentication result")}),Oe(1),ui(u=>{throw Z.error("[Session] Authentication RPC failed:",u),u})));Z.debug("[Session] Processing authentication result:",{hasProtocol:!!a.protocol,hasAuthorization:!!a.authorization,hasIceServers:!!a.ice_servers}),a.protocol&&await this.transport.setProtocol(a.protocol),this._authorization$.next(a.authorization),this._iceServers$.next(a.ice_servers??[]),this._authState$.next({kind:"authenticated"}),Z.debug("[Session] Authentication completed successfully")}async disconnect(){this.transport.disconnect(),this._authState$.next({kind:"unauthenticated"}),await this.teardownSessionState()}async createInboundCall(t){const e=await this.createCall({nodeId:t.node_id,callId:t.callID,initOffer:t.sdp,toName:t.callee_id_name,to:t.callee_id_number,fromName:t.caller_id_name,from:t.caller_id_number,displayDirection:t.display_direction,userVariables:t.userVariables});this._calls$.next({[`${e.id}`]:e,...this._calls$.value})}async handleVertoAttach(t){const{callID:e}=t;if(e in this._calls$.value){Z.debug(`[Session] Verto attach for existing call ${e}, deferring to per-call handler`);return}const i=await this.attachManager.consumePendingAttachment(e);Z.debug(`[Session] Creating reattached call for callID: ${e}`);const r=await this.createCall({nodeId:t.node_id,callId:e,toName:t.callee_id_name,to:t.callee_id_number,fromName:t.caller_id_name,from:t.caller_id_number,reattach:!0,...i});this._calls$.next({[`${r.id}`]:r,...this._calls$.value})}async createOutboundCall(t,e={}){const i=t instanceof _c?t.defaultChannel:t;let r;try{return r=await this.createCall({to:i,...e}),await Ze(Cr(r.selfId$.pipe(B(n=>!!n),Oe(1),Sr(this.callCreateTimeout)),r.errors$.pipe(B(hv),Oe(1),Je(n=>kd(()=>n.error))))),this._calls$.next({[`${r.id}`]:r,...this._calls$.value}),r}catch(n){Z.error("[Session] Error creating outbound call:",n),r==null||r.destroy();const s=new Lo(n instanceof lo?"Call create timeout":"Call creation failed",n,"outbound");throw this._errors$.next(s),s}}async createCall(t={}){try{const e=pv(t);let i;try{if(!this._directory)throw new te("Directory not initialized");const n=await this._directory.findAddressIdByURI(e);if(!n)throw new te(`Address name: ${e} not found`);if(i=this._directory.get(n),!i)throw new te(`Address ID: ${n} not found`)}catch{Z.warn(`[Session] Directory lookup failed for ${e}, proceeding with raw URI`)}const r=this.callFactory.createCall(i,{...t});return this.subscribeTo(r.status$.pipe(B(n=>n==="destroyed"),Oe(1)),()=>{const{[`${r.id}`]:n,...s}=this._calls$.value;this._calls$.next(s)}),r}catch(e){throw Z.error("[Session] Error creating call session:",e),new Lo("Call create error",e,t.initOffer?"inbound":"outbound")}}destroy(){for(const t of Object.values(this._calls$.value))t.hangup();super.destroy()}},fv=class{constructor(t){this.clientSessionManager=t}get authenticated$(){return this.clientSessionManager.authenticated$}get authenticated(){return this.clientSessionManager.authenticated}get signalingEvent$(){return this.clientSessionManager.signalingEvent$}get iceServers(){return this.clientSessionManager.iceServers}async execute(t,e){return this.clientSessionManager.execute(t,e)}get incomingCalls$(){return this.clientSessionManager.incomingCalls$}get incomingCalls(){return this.clientSessionManager.incomingCalls}get calls$(){return this.clientSessionManager.calls$}get calls(){return this.clientSessionManager.calls}};const vv=t=>typeof t=="string",Ms=G();var bv=class extends Mc{constructor(t,e){super(`/api/fabric/conversations/${t}/messages`,"page_size=100",e),this.groupId=t}},mv=class extends Rc{constructor(t,e,i,r){super(new bv(t,i),e,r)}},yv=class{constructor(t,e,i,r){this.clientSession=t,this.http=e,this.getUserAddressId=i,this.onError=r,this.groupIds=new Map}async join(t){const e=this.getUserAddressId();try{const i=await this.http.request({...hn,url:"/api/fabric/conversations/join",body:JSON.stringify({from_fabric_address_id:e,fabric_address_ids:[t,e]})});if(i.ok&&i.body){const r=JSON.parse(i.body);if(vv(r.group_id))return this.groupIds.set(t,r.group_id),r.group_id}throw new Fo("Join Failed - Unexpected response")}catch(i){throw Ms.error("[ConversationsManager] Failed to join conversation:",i),i}}async getConversationMessageCollection(t){const e=this.groupIds.get(t)??await this.join(t);return Promise.resolve(new mv(e,this.clientSession.signalingEvent$.pipe(Se(yc,"params"),Ee(i=>Ms.debug("[ConversationsManager ] Conversation Event:",i)),x(i=>({...i}))),this.http,this.onError))}async sendText(t,e){const i=this.groupIds.get(e)??await this.join(e),r=this.getUserAddressId();try{if((await this.http.request({...hn,url:"/api/fabric/messages",body:JSON.stringify({group_id:i,from_fabric_address_id:r,text:t})})).ok)return;throw new Fo("Send Text Failed - Unexpected response")}catch(n){throw Ms.error("[ConversationsManager] Failed to send text message:",n),n}}};const We=G();function mn(t){return t.expires_at?t.expires_at:t.expires_in?Math.floor(Date.now()/1e3)+t.expires_in:(We.warn("[DeviceToken] Could not determine token expiry, using default"),Math.floor(Date.now()/1e3)+sn)}function Oc(t){return t.expires_in?t.expires_in:t.expires_at?Math.max(t.expires_at-Math.floor(Date.now()/1e3),1):sn}var wv=class extends se{constructor(t,e,i,r){super(),this.dpopManager=t,this.http=e,this.errorHandler=i,this.getCredential=r,this._currentToken$=this.createBehaviorSubject(null),this._refreshInProgress=!1,this._paused=!1,this._effectiveExpireIn=sn,this.subscribeTo(this._currentToken$.pipe(B(Boolean),Je(n=>{const s=mn(n),a=Math.max(s*1e3-Date.now()-ds,1e3);return We.debug(`[DeviceToken] Scheduling Client Bound SAT refresh in ${a}ms`),Fi(a)})),()=>{this.executeRefresh()})}get effectiveExpireIn(){return this._effectiveExpireIn}async activate(t,e,i){var n;const{satClaims:r}=t;if(!((n=r==null?void 0:r.scope)!=null&&n.includes(ph)))return We.debug("[DeviceToken] No sat:refresh scope, skipping Client Bound SAT activation"),{activated:!1,reason:"no-scope"};this._session=e,this._updateCredential=i;try{const s=this._currentToken$.value;if(s&&this.isTokenFresh(s)){We.debug("[DeviceToken] Reusing cached Client Bound SAT — skipping /devices/token");const c=await this.dpopManager.createRpcProof({method:"signalwire.reauthenticate"});return await e.reauthenticate(s.token,c,{clientBound:!0}),i({token:s.token}),{activated:!0}}const a=await this.obtainToken();!a.expires_at&&!a.expires_in&&r.expires_at&&(a.expires_at=r.expires_at),this._effectiveExpireIn=Oc(a);const o=await this.dpopManager.createRpcProof({method:"signalwire.reauthenticate"});return await e.reauthenticate(a.token,o,{clientBound:!0}),i({token:a.token}),We.info("[DeviceToken] Client Bound SAT activated successfully"),this.emitCurrentToken(a),{activated:!0}}catch(s){return We.error("[DeviceToken] Failed to activate Client Bound SAT:",s),this.errorHandler(new ln(s,"Failed to activate Client Bound SAT")),{activated:!1,reason:"endpoint-failed"}}}emitCurrentToken(t){const e=t.expires_at?t:{...t,expires_at:mn(t)};this._currentToken$.next(e)}isTokenFresh(t){return mn(t)*1e3-Date.now()>ds}async obtainToken(){const t=await this.dpopManager.createHttpProof({method:"POST",uri:Eo}),e=await this.http.request({url:Eo,...hn,body:JSON.stringify({dpop_token:t,expire_in:sn})});if(!e.ok||!e.body)throw new zo(`Failed to obtain device token: ${e.status} ${e.statusText}`);const i=JSON.parse(e.body);if(!i.token)throw new zo("Device token response missing token field");return i}async refreshToken(t,e,i){We.debug("[DeviceToken] Refreshing Client Bound SAT");const r=await this.dpopManager.createHttpProof({method:"POST",uri:ko,accessToken:e}),n=await this.http.request({url:ko,...hn,body:JSON.stringify({dpop_token:r,expire_in:this._effectiveExpireIn})});if(!n.ok||!n.body)throw new di(`Failed to refresh device token: ${n.status} ${n.statusText}`);const s=JSON.parse(n.body);if(!s.token)throw new di("Device token refresh response missing token field");!s.expires_at&&!s.expires_in&&(s.expires_in=this._effectiveExpireIn),this._effectiveExpireIn=Oc(s);const a=await this.dpopManager.createRpcProof({method:"signalwire.reauthenticate"});return await t.reauthenticate(s.token,a),i({token:s.token}),We.info("[DeviceToken] Client Bound SAT refreshed successfully"),s}async executeRefresh(){if(this._paused){We.debug("[DeviceToken] Manager paused, skipping refresh");return}if(this._refreshInProgress){We.debug("[DeviceToken] Refresh already in progress, skipping");return}const t=this._session,e=this._updateCredential;if(!t||!e){We.warn("[DeviceToken] Cannot refresh: session or updateCredential not set");return}if(!t.authenticated){We.debug("[DeviceToken] Session not authenticated, deferring refresh");return}this._refreshInProgress=!0;try{const i=this.getCredential().token;if(!i)throw new di("No current token available for refresh");const r=await this.retryRefresh(t,i,e);this.emitCurrentToken(r)}catch(i){We.error("[DeviceToken] Automatic Client Bound SAT refresh failed:",i),this.errorHandler(i instanceof di?i:new di("Automatic token refresh failed",i))}finally{this._refreshInProgress=!1}}async retryRefresh(t,e,i){let r;for(let n=0;n<xo;n++)try{return await this.refreshToken(t,e,i)}catch(s){if(r=s,n<xo-1){const a=gh*Math.pow(2,n);We.warn(`[DeviceToken] Refresh attempt ${n+1} failed, retrying in ${a}ms`),await new Promise(o=>setTimeout(o,a))}}throw r instanceof Error?r:new di("All refresh retries exhausted",r)}refreshNowIfDue(){const t=this._currentToken$.value;t&&mn(t)*1e3-Date.now()<=ds&&(We.debug("[DeviceToken] Resume: cached SAT past refresh window; refreshing now"),this.executeRefresh())}pause(){this._paused=!0}resume(){this._paused=!1}destroy(){super.destroy()}};const vt=G(),Sv=(t,e,i,r)=>new wv(t,e,i,r);var Cv=class extends se{constructor(t,e){super(),this.deps=e,this._activating=!1,this._activationGeneration=0,this._developerRefreshInProgress=!1,t!=null&&t.initialized&&(this._deviceTokenManager=(e.deviceTokenManagerFactory??Sv)(t,e.http,i=>e.notifier.onError(i),()=>e.store.read()))}get clientBoundSATAvailable(){return this._deviceTokenManager!==void 0}get developerRefreshArmed(){return this._developerTimerId!==void 0}scheduleDeveloperRefresh(t,e,i=0){this._activeProvider=t,this._developerTimerId!==void 0&&clearTimeout(this._developerTimerId);const r=i===0?Math.max(e-Date.now()-Io,1e3):Math.min(fh*Math.pow(2,i)*(.5+Math.random()*.5),vh);this._developerTimerId=setTimeout(()=>{this._developerTimerId=void 0,this.executeDeveloperRefresh(t,e,i)},r)}async executeDeveloperRefresh(t,e,i){if(this._developerRefreshInProgress){vt.debug("[Coordinator] Developer refresh already in progress; skipping");return}this._developerRefreshInProgress=!0;try{const r=await this.refreshCredential(t);this.deps.store.write(r),this.deps.store.persist(r);try{await this.deps.notifier.onCredentialRefreshed(r)}catch(n){vt.warn("[Coordinator] onCredentialRefreshed rejected (non-fatal):",n)}vt.info("[Coordinator] Credentials refreshed successfully."),r.expiry_at&&this.scheduleDeveloperRefresh(t,r.expiry_at,0)}catch(r){const n=i+1;vt.error(`[Coordinator] Credential refresh failed (attempt ${n}/${Do}):`,r),this.deps.notifier.onError(r instanceof Error?r:new Error(String(r),{cause:r})),n<Do?this.scheduleDeveloperRefresh(t,e,n):(vt.error("[Coordinator] Credential refresh exhausted all retries. Disconnecting."),this.deps.notifier.onError(new di("Credential refresh failed after max retries")),this.deps.notifier.onRefreshExhausted())}finally{this._developerRefreshInProgress=!1}}forceRefreshIfDue(){var t;if(this._developerTimerId!==void 0&&this._activeProvider){const e=this.deps.store.read().expiry_at;e!==void 0&&Date.now()>=e-Io&&(vt.debug("[Coordinator] Resume: credential past refresh window; forcing refresh"),clearTimeout(this._developerTimerId),this._developerTimerId=void 0,this.executeDeveloperRefresh(this._activeProvider,e,0));return}(t=this._deviceTokenManager)==null||t.refreshNowIfDue()}syncExpiryFromAuthorization(t,e){var a;const i=(a=t==null?void 0:t.fabric_subscriber)==null?void 0:a.expires_at;if(!i)return;const r=i*1e3,n=this.deps.store.read();if(n.expiry_at===r)return;vt.debug(`[Coordinator] Correcting credential expiry from server authorization: ${new Date(r).toISOString()}`);const s={...n,expiry_at:r};this.deps.store.write(s),this.deps.store.persist(s),e!=null&&e.refresh&&this.scheduleDeveloperRefresh(e,r)}async refreshCredential(t){if(this._refreshInFlight)return this._refreshInFlight;if(!t.refresh)throw new Wt("Credential provider does not support refresh");const e=t.refresh();this._refreshInFlight=e;const i=()=>{this._refreshInFlight===e&&(this._refreshInFlight=void 0)};return e.then(i,i),e}cancelDeveloperRefresh(){this._developerTimerId!==void 0&&(clearTimeout(this._developerTimerId),this._developerTimerId=void 0)}suspend(){var t;this.cancelDeveloperRefresh(),(t=this._deviceTokenManager)==null||t.pause()}async activate(t,e){if(this._activating){vt.debug("[Coordinator] activate() in flight; ignoring re-entrant call");return}if(!this._deviceTokenManager)return;this._deviceTokenManager.resume();const i=++this._activationGeneration;this._activating=!0;try{const r=await this.withActivationTimeout(this._deviceTokenManager.activate(t,e,n=>this.deps.store.merge(n)));if(i!==this._activationGeneration){vt.debug("[Coordinator] activate() result discarded (preempted by newer activation)");return}if(r.activated){this.cancelDeveloperRefresh(),vt.debug("[Coordinator] Developer refresh disabled — Client Bound SAT owns refresh");return}vt.warn(`[SignalWire] [SW-REFRESH-FALLBACK] Client Bound SAT declined (reason=${r.reason}); using developer-provided refresh handler.`),this.deps.notifier.onWarning({code:"credential_refresh_fallback",source:"CredentialProvider",reason:r.reason,message:`Client Bound SAT activation declined (${r.reason}); using developer-provided refresh.`})}finally{this._activating=!1}}destroy(){var t;this.cancelDeveloperRefresh(),(t=this._deviceTokenManager)==null||t.destroy(),this._deviceTokenManager=void 0,super.destroy()}async withActivationTimeout(t){return new Promise(e=>{const i=setTimeout(()=>{var r;(r=this._deviceTokenManager)==null||r.pause(),e({activated:!1,reason:"activation-timeout"})},mh);t.then(r=>{clearTimeout(i),e(r)},r=>{clearTimeout(i),this.deps.notifier.onError(r instanceof Error?r:new Error(String(r))),e({activated:!1,reason:"endpoint-failed"})})})}};const Rs=G(),Av=1e3;function Tv(){try{if(typeof navigator<"u"&&navigator.userAgent)return navigator.userAgent}catch{}return"unknown"}var Ev=class extends se{constructor(t){super(),this._events=[],this._calls=[],this._deviceChanges=[],this._eventRecorded$=this.createSubject(),this._sdkVersion=t.sdkVersion,this._maxEvents=t.maxEvents??Av,Rs.debug("DiagnosticsCollector initialized",{sdkVersion:this._sdkVersion,maxEvents:this._maxEvents})}get eventRecorded$(){return this._eventRecorded$.asObservable()}record(t,e,i){const r={timestamp:Date.now(),category:t,event:e,...i!==void 0?{details:i}:{}};this._events=this._appendToBuffer(this._events,r),this._eventRecorded$.next(r)}recordDeviceChange(t,e){const i={timestamp:Date.now(),category:"device",event:t,...e!==void 0?{details:e}:{}};this._deviceChanges=this._appendToBuffer(this._deviceChanges,i),this._events=this._appendToBuffer(this._events,i),this._eventRecorded$.next(i)}recordCallSummary(t){this._calls=this._appendCallToBuffer(this._calls,t),this.record("call","call_summary",{callId:t.callId,direction:t.direction,duration:t.duration,finalStatus:t.finalStatus})}export(){return{sdkVersion:this._sdkVersion,userAgent:Tv(),exportedAt:Date.now(),events:[...this._events],calls:[...this._calls],deviceChanges:[...this._deviceChanges]}}clear(){this._events=[],this._calls=[],this._deviceChanges=[],Rs.debug("DiagnosticsCollector buffers cleared")}destroy(){Rs.debug("DiagnosticsCollector destroyed"),super.destroy()}_appendToBuffer(t,e){const i=[...t,e];return i.length>this._maxEvents?i.slice(i.length-this._maxEvents):i}_appendCallToBuffer(t,e){const i=[...t,e];return i.length>this._maxEvents?i.slice(i.length-this._maxEvents):i}};const Lc=t=>((t==null?void 0:t.length)??0)===0,kv=t=>{t.pipe(Oe(1)).subscribe()},xv=G();var Dv=class extends Mc{constructor(t){super("/api/fabric/addresses","sort_by=name&sort_order=asc",t)}async name(t){const e=await this.http.request({...ms,url:`${this.endpoint}?name=${encodeURIComponent(t)}`});if(e.ok&&e.body){const i=JSON.parse(e.body);if(!Lc(i.data))return i.data[0]}xv.error("Failed to fetch addresses")}},Iv=class extends Rc{constructor(t,e,i){super(new Dv(e),t,i)}},Mv=class extends se{constructor(t,e,i,r){super(),this.http=t,this.conversationManager=i,this.onError=r,this.addNewAddress=n=>{var o;const s=new _c(n,this.conversationManager,this),a=(o=this._statesCollection.get$(n))==null?void 0:o.pipe(ve(),x(c=>(s.upnext(c),s)));a&&(kv(a),this._observableRegistry.set(n,a)),this._addressesInstances.set(n,s)},this._addresses$=this.createBehaviorSubject([]),this._addressesInstances=new Map,this._observableRegistry=new Map,this._statesCollection=new Iv(e.signalingEvent$.pipe(Se(wc,"params"),x(n=>({}))),this.http,this.onError),this.initSubscriptions()}get loading(){return this._statesCollection.loading}initSubscriptions(){this.subscribeTo(this._statesCollection.updated$,()=>{const t=Array.from(this._addressesInstances.values().map(i=>i.id)),e=this._statesCollection.values.filter(i=>!t.includes(i.id));Lc(e)||(e.forEach(i=>this.addNewAddress(i.id)),this._addresses$.next(Array.from(this._addressesInstances.values())))})}get addresses$(){return this._addresses$.asObservable()}get addresses(){return this._addresses$.value}get hasMore$(){return this._statesCollection.hasMore$}get loading$(){return this._statesCollection.loading$}loadMore(){this._statesCollection.hasMore&&this._statesCollection.loadMore()}get$(t){return this._observableRegistry.has(t)||this.addNewAddress(t),this._observableRegistry.get(t)}get(t){return this._addressesInstances.get(t)}async findAddressIdByURI(t){var i;let e=(i=this._addressesInstances.values().find(r=>r.name===t))==null?void 0:i.id;if(!e){const r=await this._statesCollection.find$("name",t);if(r){const n=await Ze(r);this.addNewAddress(n.id),e=n.id}}return e}};const Fc=G();var Rv=(yt=class extends se{constructor(e,i,r,n={}){super(),this.WebSocketConstructor=e,this.endpoint=i,this.outgoingMessages$=r,this.messageQueue=[],this.shouldReconnect=!1,this.boundHandleOpen=()=>this.handleOpen(),this.boundHandleClose=s=>this.handleClose(s),this.boundHandleError=()=>this.handleError(),this.boundHandleMessage=s=>this.handleMessage(s),this._status$=this.createBehaviorSubject("disconnected"),this._incomingMessages$=this.createSubject(),this._errors$=this.createReplaySubject(1),this.reconnectDelayMin=n.reconnectDelayMin??yt.DEFAULT_RECONNECT_DELAY_MIN_MS,this.reconnectDelayMax=n.reconnectDelayMax??yt.DEFAULT_RECONNECT_DELAY_MAX_MS,this.connectionTimeout=n.connectionTimeout??yt.DEFAULT_CONNECTION_TIMEOUT_MS,this.currentReconnectDelay=this.reconnectDelayMin,this.subscriptions.push(this.outgoingMessages$.subscribe(s=>{this.send(s)}))}get status$(){return this._status$.asObservable()}get incomingMessages$(){return this._incomingMessages$.asObservable()}get errors$(){return this._errors$.asObservable()}connect(){this._status$.value==="connecting"||this._status$.value==="connected"||(this.shouldReconnect=!0,this._status$.next("connecting"),this.createWebSocket())}disconnect(){this.shouldReconnect=!1,this.clearReconnectTimer(),this.clearConnectionTimeout();const e=this._status$.value;e==="connected"||e==="connecting"||e==="reconnecting"?this.socket?(this._status$.next("disconnecting"),this.socket.close()):this._status$.next("disconnected"):this._status$.next("disconnected")}reconnect(){this.shouldReconnect=!0,this._status$.next("reconnecting"),this.scheduleReconnection()}send(e){var i;this._status$.value==="connected"&&((i=this.socket)==null?void 0:i.readyState)===1?(Fc.wsTraffic({type:"send",raw:e}),this.socket.send(e)):this.messageQueue.push(e)}createWebSocket(){try{this.closeExistingSocket(),this.socket=new this.WebSocketConstructor(this.endpoint),this.setupWebSocketListeners(),this.startConnectionTimeout()}catch(e){const i=e instanceof Error?e:new Ui("Failed to create WebSocket");this._errors$.next(i),this.handleConnectionError()}}closeExistingSocket(){if(!this.socket)return;const e=this.socket;this.socket=void 0,this.removeWebSocketListeners(e);try{e.close()}catch{}}setupWebSocketListeners(){this.socket&&(this.socket.addEventListener("open",this.boundHandleOpen),this.socket.addEventListener("close",this.boundHandleClose),this.socket.addEventListener("error",this.boundHandleError),this.socket.addEventListener("message",this.boundHandleMessage))}removeWebSocketListeners(e){try{e.removeEventListener("open",this.boundHandleOpen),e.removeEventListener("close",this.boundHandleClose),e.removeEventListener("error",this.boundHandleError),e.removeEventListener("message",this.boundHandleMessage)}catch{}}handleOpen(){this.clearConnectionTimeout(),this._status$.next("connected"),this.currentReconnectDelay=this.reconnectDelayMin,this.flushMessageQueue()}handleClose(e){this.clearConnectionTimeout(),this.shouldReconnect?(this._status$.next("reconnecting"),this.scheduleReconnection()):this._status$.next("disconnected")}handleError(){const e=new Po("WebSocket connection error");this._errors$.next(e),this.handleConnectionError()}handleMessage(e){Fc.wsTraffic({type:"recv",raw:e.data}),this._incomingMessages$.next(e)}handleConnectionError(){this.reconnect()}scheduleReconnection(){this.clearReconnectTimer();const e=this.currentReconnectDelay*(.5+Math.random()*.5);this.reconnectTimer=setTimeout(()=>{this.shouldReconnect&&(this._status$.next("connecting"),this.createWebSocket(),this.increaseReconnectDelay())},e)}increaseReconnectDelay(){this.currentReconnectDelay=Math.min(this.currentReconnectDelay*2,this.reconnectDelayMax)}startConnectionTimeout(){this.clearConnectionTimeout(),this.connectionTimeoutTimer=setTimeout(()=>{if(this._status$.value==="connecting"){const e=new sp("WebSocket connection timeout");this._errors$.next(e),this.socket&&this.socket.close()}},this.connectionTimeout)}clearConnectionTimeout(){this.connectionTimeoutTimer&&(clearTimeout(this.connectionTimeoutTimer),this.connectionTimeoutTimer=void 0)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0)}flushMessageQueue(){var e;for(;this.messageQueue.length>0&&((e=this.socket)==null?void 0:e.readyState)===1;){const i=this.messageQueue.shift();i!==void 0&&this.socket.send(i)}}},yt.DEFAULT_RECONNECT_DELAY_MIN_MS=1e3,yt.DEFAULT_RECONNECT_DELAY_MAX_MS=3e4,yt.DEFAULT_CONNECTION_TIMEOUT_MS=1e4,yt);function Pv(t){return As(t)&&t.method==="signalwire.ping"}const De=G();var _v=class extends se{constructor(t,e,i,r,n){super(),this.storage=t,this.protocolKey=e,this.onError=n,this.protocol$=this.createReplaySubject(1),this.isConnecting=!1,this.isConnected=!1,this.ackEvent=()=>Ee(s=>{if(Es(s))try{De.debug("[Transport] Sending event ack",{eventId:s.id}),this.send(Mg(s.id))}catch(a){De.error("[Transport] Failed to send event acknowledgment:",a)}}),this.replySignalwirePing=()=>B(s=>{if(Pv(s)){try{De.debug("[Transport] Received ping, sending pong",{pingId:s.id}),this.send(yg(s.id))}catch(a){De.error("[Transport] Failed to send ping response:",a)}return!1}return!0}),this.discardStaleEvents=()=>B(s=>{if(!Es(s))return!0;const a=s.params.event_channel;if(!a)return!0;if(s.params.event_type.startsWith("conversation."))return De.debug(`[Transport] Received conversation event: ${s.params.event_type} (event_channel: ${a})`),!0;const o=this._currentProtocol;if(!o)return!0;if(!a.includes(o)){const c=s.params.event_type;return De.warn(`[Transport] Discarding stale event: ${c} (event_channel does not match current protocol)`),!1}return!0}),this._outgoingMessages$=this.createSubject(),this._webSocketConnections=new Rv(i,r,this._outgoingMessages$.asObservable(),{connectionTimeout:f.instance.connectionTimeout,reconnectDelayMin:f.instance.reconnectDelayMin,reconnectDelayMax:f.instance.reconnectDelayMax}),this.subscribeTo(this._webSocketConnections.errors$,s=>{var a;(a=this.onError)==null||a.call(this,s)}),this.initialized$=li(()=>_e(this._init())).pipe(st(1),S(this.destroyed$)),this._jsonRPCMessage$=this._webSocketConnections.incomingMessages$.pipe(x(s=>{var a;try{return JSON.parse(s.data)}catch(o){return De.error("[Transport] Failed to parse incoming message:",o),(a=this.onError)==null||a.call(this,new gp(o)),null}}),B(s=>s!==null&&(Ts(s)||As(s))),ui(s=>{var a;return De.error("[Transport] Message processing error:",s),(a=this.onError)==null||a.call(this,s instanceof Error?s:new Error(String(s),{cause:s})),ci}),At(),S(this.destroyed$)),this._jsonRPCResponse$=this._jsonRPCMessage$.pipe(B(Ts)),this._incomingEvent$=this._jsonRPCMessage$.pipe(this.ackEvent(),this.replySignalwirePing(),B(s=>!Ts(s)),this.discardStaleEvents(),At(),S(this.destroyed$))}async setProtocol(t){this._currentProtocol=t,this.protocol$.next(t),await this._updateProtocolInStorage(t)}get incomingEvent$(){return this._incomingEvent$}get connectionStatus$(){return this._webSocketConnections.status$}async connect(){return this.isConnecting||this.isConnected?(De.warn("[Transport] Already connecting or connected"),Promise.resolve()):new Promise((t,e)=>{this.isConnecting=!0,this.subscribeTo(this.initialized$,()=>{this._webSocketConnections.connect();const i=this._webSocketConnections.status$.pipe(B(r=>r==="connected"||r==="disconnected"),Oe(1),Sr(1e4)).subscribe({next:r=>{var n;if(r==="connected")this.isConnecting=!1,this.isConnected=!0,De.debug("[Transport] Connection established"),t();else{this.isConnecting=!1;const s=new _o("Failed to connect");De.error("[Transport] Connection failed"),(n=this.onError)==null||n.call(this,s),e(s)}},error:r=>{var n;this.isConnecting=!1,De.error("[Transport] Connection error:",r),(n=this.onError)==null||n.call(this,r instanceof Error?r:new Error(String(r),{cause:r})),e(r)}});this.subscriptions.push(i),this.subscribeTo(this._webSocketConnections.status$.pipe(B(r=>r==="disconnected")),()=>{De.debug("[Transport] Disconnected"),this.isConnected=!1})})})}reconnect(){this._webSocketConnections.reconnect()}async execute(t,e){return this.send(t),new dv(t,this._jsonRPCResponse$,e).promise}send(t){const e=JSON.stringify(t);this._outgoingMessages$.next(e)}disconnect(){De.debug("[Transport] Disconnecting"),this.isConnected=!1,this.isConnecting=!1,this._webSocketConnections.disconnect()}destroy(){De.debug("[Transport] Destroying"),this.disconnect(),super.destroy(),this._webSocketConnections.destroy()}async _loadProtocolFromStorage(){try{const t=await this.storage.getItem(this.protocolKey);this._currentProtocol=t??void 0,this.protocol$.next(t??void 0)}catch(t){throw De.error("Failed to retrieve protocol from storage:",t),t}}async _updateProtocolInStorage(t){if(!t){try{await this.storage.removeItem(this.protocolKey)}catch(e){throw De.error("Failed to remove protocol from storage:",e),e}return}try{const e=await this.storage.getItem(this.protocolKey);(!e||e!==t)&&await this.storage.setItem(this.protocolKey,t)}catch(e){throw De.error("Failed to update protocol in storage:",e),e}}async _init(){return await this._loadProtocolFromStorage(),!0}};function Ov(t){const e=new Set;let i=t;for(;i instanceof Error&&!e.has(i);){if(e.add(i),i instanceof Et)return i;i=i.error??i.cause}}function Nc(t){const e=Ov(t);return e!==void 0&&(e.code===hs||e.code===ps)}const Y=G(),Lv=t=>{if(typeof t=="string"){const e=t.indexOf("?");if(e!==-1){const i=t.substring(e+1),r=new URLSearchParams(i).get("channel");if(r==="video")return{audio:!0,video:!0,receiveVideo:!0};if(r==="audio")return{audio:!0,video:!1}}}return{}};var Uc=class extends se{constructor(t,e={}){super(),this.preferences=new Gp,this._user$=this.createBehaviorSubject(void 0),this._directory$=this.createBehaviorSubject(void 0),this._isConnected$=this.createBehaviorSubject(!1),this._isRegistered$=this.createBehaviorSubject(!1),this._errors$=this.createReplaySubject(1),this._warnings$=this.createReplaySubject(10),this._options={},this._deps=new Kp,this._credentialProvider=t,this._options={...f.instance.defaultSignalWireOptions,...e},this._options.storageImplementation&&(this._deps.storageImpl=this._options.storageImplementation),this._options.persistSession&&(this._deps.persistSession=!0),this._options.webSocketConstructor&&(this._deps.WebSocket=this._options.webSocketConstructor),this._options.savePreferences&&this.preferences.enableSavePreferences(this._deps.storage),this._options.webRTCApiProvider&&(this._deps.webRTCApiProvider=this._options.webRTCApiProvider),this._options.logger!==void 0&&yp(this._options.logger),this._options.logLevel&&Sp(this._options.logLevel),this._options.debug&&wp(this._options.debug),this._deviceController=this._deps.deviceController,this._options.skipDeviceMonitoring||this._deviceController.enableDeviceMonitoring(),this.subscribeTo(this._deviceController.errors$,i=>{this._errors$.next(i)}),this.initResilienceSubsystems(),this.resolveCredentials().then(()=>{this.init().catch(i=>{Y.error("[SignalWire] Initialization error:",i),this._deps.storage.removeItem("sw:cached_credential"),this._deps.storage.removeItem("sw:cached_credential","local"),this._errors$.next(i instanceof Error?i:new Error(String(i),{cause:i}))})}).catch(i=>{Y.error("[SignalWire] Initialization error:",i),this._errors$.next(i instanceof Error?i:new Error(String(i),{cause:i}))})}async initDPoP(){var t;if((t=this._dpopManager)!=null&&t.initialized)return this._dpopManager.fingerprint;try{this._dpopManager=new eg;const e=await this._dpopManager.init();return Y.debug("[SignalWire] DPoP initialized, fingerprint available"),e}catch(e){Y.warn("[SignalWire] DPoP initialization failed, proceeding without DPoP:",e),this._dpopManager=void 0;return}}async resolveCredentials(){const t=await this.initDPoP();if(this._refreshCoordinator=new Cv(this._dpopManager,{http:this._deps.http,notifier:{onError:e=>this._errors$.next(e),onWarning:e=>this._warnings$.next(e),onRefreshExhausted:()=>void this.disconnect(),onCredentialRefreshed:async e=>this.reauthenticateLiveSession(e)},store:{read:()=>this._deps.credential,write:e=>{this._deps.credential=e},merge:e=>{this._deps.credential={...this._deps.credential,...e}},persist:e=>this.persistCredential(e)}}),this._credentialProvider)return this.validateCredentials(this._credentialProvider,void 0,t);for(const e of this._deps.persistSession?["local","session"]:["session"])try{const i=await this._deps.storage.getItem("sw:cached_credential",e);if(i!=null&&i.token)return Y.debug(`[SignalWire] Using cached credential from ${e}Storage`),await this.validateCredentials(void 0,i)}catch{}throw new Wt("No credential provider and no cached session. Provide a CredentialProvider or enable persistSession with a prior login.")}async validateCredentials(t,e,i){var s,a;const r=i??((s=this._dpopManager)!=null&&s.initialized?this._dpopManager.fingerprint:void 0),n=e??(t?await t.authenticate(r?{fingerprint:r}:void 0):void 0);if(!n)throw new Wt("No credentials available.");if(n.token)try{const o=xp(n.token,{header:!0});this._deps.ch=o.ch}catch(o){throw Y.error("[SignalWire] Invalid JWT token provided in credentials:",o),new Wt("Invalid JWT token provided in credentials.",{cause:o})}if(!n.token&&!n.authorizationState)throw Y.error("[SignalWire] No valid authentication credentials provided."),new Wt("No valid authentication credentials provided.");if(!this._deps.persistSession&&n.expiry_at&&n.expiry_at<Date.now())throw Y.error("[SignalWire] Provided credentials have expired."),new Wt("Provided credentials have expired.");n.expiry_at&&(t!=null&&t.refresh)?(a=this._refreshCoordinator)==null||a.scheduleDeveloperRefresh(t,n.expiry_at):n.expiry_at&&!(t!=null&&t.refresh)&&(Y.warn(`[SignalWire] [SW-NO-REFRESH-HANDLER] Credential has expiry_at=${n.expiry_at} but no refresh handler. Session will terminate at expiry unless the SAT has 'sat:refresh' scope.`),this._warnings$.next({code:"credential_no_refresh_handler",source:"CredentialProvider",message:"Credential has expiry_at but no refresh handler. Session will terminate at expiry unless the SAT carries 'sat:refresh' scope.",expiresAt:n.expiry_at})),this._deps.credential=n,this.persistCredential(n),await this.reauthenticateLiveSession(n)}async reauthenticateLiveSession(t){if(!(!this.isConnected||!this._clientSession.authenticated||!t.token))try{await this._clientSession.reauthenticate(t.token),Y.info("[SignalWire] Session refreshed with new credentials.")}catch(e){Y.error("[SignalWire] Failed to refresh session with new credentials:",e),this._errors$.next(e instanceof Error?e:new Error(String(e),{cause:e}))}}async recoverStaleCredential(t=!0){var i,r;const e=this._deps.credential.token;if(e)try{return await this._clientSession.reauthenticate(e),!0}catch(n){Y.debug("[SignalWire] In-memory reauth failed during recovery:",n)}if(!t||this._clientSession.clientBound||!((i=this._credentialProvider)!=null&&i.refresh))return!1;try{const n=await this.remintCredential(this._credentialProvider);return n.token?(this._deps.credential=n,this.persistCredential(n),await this._clientSession.reauthenticate(n.token),n.expiry_at&&((r=this._refreshCoordinator)==null||r.scheduleDeveloperRefresh(this._credentialProvider,n.expiry_at)),!0):!1}catch(n){return Y.error("[SignalWire] Credential recovery failed:",n),!1}}async remintCredential(t){if(this._refreshCoordinator)return this._refreshCoordinator.refreshCredential(t);if(!t.refresh)throw new Wt("Credential provider does not support refresh");return t.refresh()}async refreshCredentialForReconnect(){var t,e;if(this._credentialProvider)try{let i;if(this._clientSession.clientBound){const r=(t=this._dpopManager)!=null&&t.initialized?this._dpopManager.fingerprint:void 0;Y.debug("[SignalWire] Re-minting client-bound base SAT before reconnect"),i=await this._credentialProvider.authenticate(r?{fingerprint:r}:void 0)}else if(this._credentialProvider.refresh)Y.debug("[SignalWire] Refreshing unbound credential before reconnect"),i=await this.remintCredential(this._credentialProvider);else{Y.warn("[SignalWire] [SW-NO-REFRESH-HANDLER] Token expired on reconnect but no refresh handler; reconnecting with the existing token.");return}if(!i.token){Y.warn("[SignalWire] Re-minted credential has no token; keeping the existing credential for reconnect.");return}this._deps.credential=i,this.persistCredential(i),i.expiry_at&&this._credentialProvider.refresh&&((e=this._refreshCoordinator)==null||e.scheduleDeveloperRefresh(this._credentialProvider,i.expiry_at)),Y.debug("[SignalWire] Credential refreshed successfully for reconnect")}catch(i){throw Y.error("[SignalWire] Failed to refresh credentials for reconnect:",i),this._errors$.next(i instanceof Error?i:new Error(String(i),{cause:i})),i}}persistCredential(t){t.token&&(this._deps.storage.setItem("sw:cached_credential",t),this._deps.persistSession&&this._deps.storage.setItem("sw:cached_credential",t,"local"))}async init(){if(this._user$.next(new fg(this._deps.http)),this._options.skipConnection||await this.connect(),!this._options.reconnectAttachedCalls&&this._attachManager&&await this._attachManager.flush(),!this._options.skipRegister)try{await this.register()}catch(t){Y.error("[SignalWire] Registration failed:",t),this._errors$.next(t instanceof Error?t:new Error(String(t),{cause:t}))}this.handleAttachments()}async handleAttachments(){if(!this._attachManager){Y.error("[SignalWire] AttachManager not initialized");return}if(this._options.reconnectAttachedCalls)try{await this._attachManager.reattachCalls()}catch(t){Y.error("[SignalWire] Failed to reattach calls:",t),this._errors$.next(t instanceof Error?t:new Error(String(t),{cause:t}))}}async connect(){var r,n,s;await this.teardownTransportAndSession();try{const a=this._user$.value;if(!a)throw new Ui("User not initialized before connect");if(!await Ze(a.fetched$))throw new Ui("Failed to fetch user information - fetched$ emitted false");this._deps.user=a}catch(a){throw Y.error(`[SignalWire] Failed to fetch user information: ${a instanceof Error?a.message:"Unknown error"}. This usually means the user token is invalid or expired.`),new Ui("Error fetching user information",{cause:a})}const t=a=>{this._errors$.next(a)};this._transport=new _v(this._deps.storage,this._deps.protocolKey,this._deps.WebSocket,f.instance.relayHost??this._deps.relayHost,t),this._attachManager=new Rg(this._deps.storage,this._deps.deviceController,f.instance.reconnectCallsTimeout,this._deps.attachedCallsKey),this._clientSession=new gv(()=>this._deps.credential,this._transport,this._deps.storage,this._deps.authorizationStateKey,this._deps.deviceController,this._attachManager,this._deps.webRTCApiProvider,this._dpopManager,(r=this._networkMonitor)==null?void 0:r.networkChange$),this._publicSession=new fv(this._clientSession),this._clientSession.onBeforeReconnect=async()=>this.refreshCredentialForReconnect(),this.subscribeTo(this._clientSession.errors$,a=>{this._errors$.next(a)}),this.subscribeTo(this._clientSession.authorization$,a=>{var o;(o=this._refreshCoordinator)==null||o.syncExpiryFromAuthorization(a,this._credentialProvider)}),await this._clientSession.connect(),await((n=this._refreshCoordinator)==null?void 0:n.activate(this._deps.user,this._clientSession)),this.subscribeTo(this._clientSession.authenticated$.pipe(tn(1),B(Boolean)),async()=>{var a;try{await((a=this._refreshCoordinator)==null?void 0:a.activate(this._deps.user,this._clientSession))}catch(o){Y.error("[SignalWire] Refresh re-arm after reconnect failed (non-fatal):",o),this._errors$.next(o instanceof Error?o:new Error(String(o),{cause:o}))}try{Y.debug("[SignalWire] Re-registering user after reconnect"),await this.register(),Y.debug("[SignalWire] User re-registered successfully after reconnect")}catch(o){Y.error("[SignalWire] Re-registration failed after reconnect:",o),this._errors$.next(o instanceof Error?o:new Error(String(o),{cause:o}))}});const e=new yv(this._clientSession,this._deps.http,()=>this._deps.getUserFromAddressId(),t),i=new Mv(this._deps.http,this._clientSession,e,t);this._directory$.next(i),this._clientSession.setDirectory(i),this._isConnected$.next(!0),(s=this._diagnosticsCollector)==null||s.record("connection","connected"),this.subscribeTo(this._clientSession.authenticated$.pipe(tn(2),B(Boolean)),()=>{var a;(a=this._diagnosticsCollector)==null||a.record("connection","reconnected")})}get user$(){return this.deferEmission(this._user$.asObservable())}get user(){return this._user$.value}get directory$(){return this.deferEmission(this._directory$.asObservable())}get directory(){return this._directory$.value}get isRegistered$(){return this.deferEmission(this._isRegistered$.asObservable())}get isRegistered(){return this._isRegistered$.value}get isConnected(){return this._isConnected$.value}get isConnected$(){return this.deferEmission(this._isConnected$.asObservable())}get ready$(){return this.publicCachedObservable("ready$",()=>this._isConnected$.pipe(Je(t=>t?this._clientSession.authenticated$:Ct(!1))))}get errors$(){return this.deferEmission(this._errors$.asObservable())}get warnings$(){return this.deferEmission(this._warnings$.asObservable())}get platformCapabilities(){return this._platformCapabilities??(this._platformCapabilities=tc(this._options.webRTCApiProvider)),this._platformCapabilities}get deviceRecovered$(){return this.deferEmission(this._deviceController.deviceRecovered$)}exportDiagnostics(){const t={audioInput:this.audioInputDevices,audioOutput:this.audioOutputDevices,videoInput:this.videoInputDevices},e={sdkVersion:"unknown",userAgent:typeof navigator<"u"?navigator.userAgent:"unknown",capabilities:this.platformCapabilities,events:[],calls:[],deviceChanges:[],devices:t};if(!this._diagnosticsCollector)return e;const i=this._diagnosticsCollector.export();return{...e,sdkVersion:i.sdkVersion,userAgent:i.userAgent,events:i.events,calls:i.calls,deviceChanges:i.deviceChanges,devices:t}}initResilienceSubsystems(){try{this._platformCapabilities=tc(this._options.webRTCApiProvider)}catch(t){Y.warn("[SignalWire] Failed to detect platform capabilities:",t)}try{this._networkMonitor=new tg}catch(t){Y.warn("[SignalWire] Failed to initialize NetworkMonitor:",t)}try{this._visibilityController=new pg,this.subscribeTo(this._visibilityController.visibilityChange$.pipe(B(t=>t.to==="visible")),()=>{var t;try{(t=this._refreshCoordinator)==null||t.forceRefreshIfDue()}catch(e){Y.warn("[SignalWire] Resume credential revalidation failed (non-fatal):",e)}}),this.subscribeTo(this._visibilityController.visibilityChange$.pipe(B(t=>t.to==="visible"&&f.instance.refreshDevicesOnVisible)),()=>{Y.debug("[SignalWire] Page visible, re-enumerating devices");try{this._deviceController.disableDeviceMonitoring(),this._deviceController.enableDeviceMonitoring()}catch{}})}catch(t){Y.warn("[SignalWire] Failed to initialize VisibilityController:",t)}try{this._diagnosticsCollector=new Ev({sdkVersion:"4.0.0-rc.2"})}catch(t){Y.warn("[SignalWire] Failed to initialize DiagnosticsCollector:",t)}}async disconnect(){var t,e;(t=this._refreshCoordinator)==null||t.suspend(),(e=this._diagnosticsCollector)==null||e.record("connection","disconnected"),await this.teardownTransportAndSession(),this._isConnected$.next(!1)}async teardownTransportAndSession(){const t=this._clientSession,e=this._transport;if(t){try{await t.disconnect()}catch(i){Y.warn("[SignalWire] Error disconnecting previous session:",i)}t.destroy()}e&&e.destroy(),this._clientSession=void 0,this._publicSession=void 0,this._transport=void 0,this._attachManager=void 0}async waitAuthentication(){await Ze(this.ready$.pipe(B(t=>t===!0)))}async register(){try{await this.waitAuthentication(),await this._transport.execute(Ss({method:"subscriber.online",params:{}})),this._isRegistered$.next(!0);return}catch(t){if(!this._deps.credential.token)throw this._errors$.next(t instanceof Error?t:new Error(String(t),{cause:t})),t;Y.debug("[SignalWire] Failed to register user, attempting credential recovery...");let e=t;if(await this.recoverStaleCredential(Nc(t)))try{Y.debug("[SignalWire] Recovery succeeded, retrying register()"),await this._transport.execute(Ss({method:"subscriber.online",params:{}})),this._isRegistered$.next(!0);return}catch(r){Y.error("[SignalWire] Register retry after recovery failed:",r),e=r}const i=new Wt("Failed to register user, and credential recovery also failed. Please check your credentials.",{cause:e instanceof Error?e:new Error(String(e),{cause:e})});throw this._errors$.next(i),i}}async unregister(){try{await this._transport.execute(Ss({method:"subscriber.offline",params:{}})),this._isRegistered$.next(!1)}catch(t){throw Y.error("[SignalWire] Failed to unregister user:",t),this._errors$.next(t instanceof Error?t:new Error(String(t),{cause:t})),t}}async dial(t,e={}){const i={...f.instance.preferredMediaOptions,...Lv(t),...e};await this.waitAuthentication(),Y.debug("[SignalWire] Dialing with options:",i);try{return await this._clientSession.createOutboundCall(t,i)}catch(r){if(!Nc(r)||(Y.debug("[SignalWire] Dial hit a recoverable auth error; recovering credential and retrying once"),!await this.recoverStaleCredential()))throw r;return await this.waitAuthentication(),this._clientSession.createOutboundCall(t,i)}}async preflight(t,e){const i=this._clientSession.iceServers??f.instance.iceServers??[],r=this._isConnected$.value;return new dg(this._deviceController,i,r,0,async(n,s)=>this.dial(n,s),e).run(t)}get session(){return this._publicSession}get audioInputDevices$(){return this.deferEmission(this._deviceController.audioInputDevices$)}get audioInputDevices(){return this._deviceController.audioInputDevices}get audioOutputDevices$(){return this.deferEmission(this._deviceController.audioOutputDevices$)}get audioOutputDevices(){return this._deviceController.audioOutputDevices}get videoInputDevices$(){return this.deferEmission(this._deviceController.videoInputDevices$)}get videoInputDevices(){return this._deviceController.videoInputDevices}get selectedAudioInputDevice$(){return this.deferEmission(this._deviceController.selectedAudioInputDevice$)}get selectedAudioOutputDevice$(){return this.deferEmission(this._deviceController.selectedAudioOutputDevice$)}get selectedVideoInputDevice$(){return this.deferEmission(this._deviceController.selectedVideoInputDevice$)}get selectedAudioInputDevice(){return this._deviceController.selectedAudioInputDevice}get selectedAudioOutputDevice(){return this._deviceController.selectedAudioOutputDevice}get selectedVideoInputDevice(){return this._deviceController.selectedVideoInputDevice}get selectedAudioInputDeviceConstraints(){return this._deviceController.selectedAudioInputDeviceConstraints}get selectedVideoInputDeviceConstraints(){return this._deviceController.selectedVideoInputDeviceConstraints}deviceInfoToConstraints(t){return this._deviceController.deviceInfoToConstraints(t)}selectAudioInputDevice(t){this._deviceController.selectAudioInputDevice(t)}selectVideoInputDevice(t){this._deviceController.selectVideoInputDevice(t)}selectAudioOutputDevice(t){this._deviceController.selectAudioOutputDevice(t)}async applySelectedAudioOutputDevice(t){const e=this._deviceController.selectedAudioOutputDevice;if(!(e!=null&&e.deviceId))return!1;const i=t;if(typeof i.setSinkId!="function")return Y.warn("[SignalWire] setSinkId not supported on this element / browser"),!1;try{return await i.setSinkId(e.deviceId),!0}catch(r){return Y.warn("[SignalWire] Failed to apply audio output device:",r),!1}}enableDeviceMonitoring(){this._deviceController.enableDeviceMonitoring()}disableDeviceMonitoring(){this._deviceController.disableDeviceMonitoring()}async getDeviceCapabilities(t){return this._deviceController.getDeviceCapabilities(t)}async isValidDevice(t){return this._deviceController.isValidDevice(t)}setStorageManager(t){this._deviceController.setStorageManager(t)}async clearDeviceState(){return this._deviceController.clearDeviceState()}async enumerateDevices(){return this._deviceController.enumerateDevices()}disableAudioInput(){this._deviceController.disableAudioInput()}enableAudioInput(){this._deviceController.enableAudioInput()}disableVideoInput(){this._deviceController.disableVideoInput()}enableVideoInput(){this._deviceController.enableVideoInput()}get videoInputDisabled$(){return this.deferEmission(this._deviceController.videoInputDisabled$)}get audioInputDisabled$(){return this.deferEmission(this._deviceController.audioInputDisabled$)}get videoInputDisabled(){return this._deviceController.videoInputDisabled}get audioInputDisabled(){return this._deviceController.audioInputDisabled}async requestMediaPermissions(t={audio:!0,video:!0}){const e={audio:t.audio??!1,video:t.video??!1};let i=!1,r=!1,n,s;try{const a=(await this._deps.webRTCApiProvider.mediaDevices.getUserMedia(e)).getTracks();for(const o of a){const c=o.getSettings();o.kind==="audio"?(i=!0,c.deviceId&&(n=this.audioInputDevices.find(u=>u.deviceId===c.deviceId))):o.kind==="video"&&(r=!0,c.deviceId&&(s=this.videoInputDevices.find(u=>u.deviceId===c.deviceId))),o.stop()}}catch(a){Y.warn("[SignalWire] Media permission request failed:",a)}if(await this._deviceController.enumerateDevices(),i&&n){const a=n.deviceId;n=this.audioInputDevices.find(o=>o.deviceId===a)??n}if(r&&s){const a=s.deviceId;s=this.videoInputDevices.find(o=>o.deviceId===a)??s}return i&&n&&!this.selectedAudioInputDevice&&this.selectAudioInputDevice(n),r&&s&&!this.selectedVideoInputDevice&&this.selectVideoInputDevice(s),{audio:i,video:r,selectedAudioDevice:n,selectedVideoDevice:s}}async resetToDefaults(){await this._deps.storage.clearAll();const t=f.instance;t.preferredAudioInput=null,t.preferredAudioOutput=null,t.preferredVideoInput=null,await this._deviceController.clearDeviceState()}destroy(){var t,e,i,r,n;(t=this._refreshCoordinator)==null||t.destroy(),this._refreshCoordinator=void 0,(e=this._dpopManager)==null||e.destroy(),this._clientSession.teardownSessionState(),this._transport.destroy(),this._clientSession.destroy();try{(i=this._networkMonitor)==null||i.destroy()}catch{}try{(r=this._visibilityController)==null||r.destroy()}catch{}try{(n=this._diagnosticsCollector)==null||n.destroy()}catch{}this._networkMonitor=void 0,this._visibilityController=void 0,this._diagnosticsCollector=void 0,super.destroy()}};const Fv=G();var Bc=class{constructor(t,e){this.host=t,this.embedToken=e}async fetchSAT(){const t=`https://${this.host}/api/fabric/embeds/tokens`,e=1e4,i=new AbortController,r=setTimeout(()=>i.abort(),e);try{const n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:this.embedToken}),signal:i.signal});if(clearTimeout(r),n.ok)return(await n.json()).token;throw new ap(`Failed to fetch SAT using embed token: ${n.status} ${n.statusText}`)}catch(n){throw clearTimeout(r),n instanceof Error&&n.name==="AbortError"?new Oo(`Request timeout after ${e}ms`,{cause:n}):(Fv.error("[EmbedCredentialProvider] Request failed:",n),n)}}async authenticate(){return{token:await this.fetchSAT(),expiry_at:Date.now()+3600*1e3}}async refresh(){return this.authenticate()}},zc=class{constructor(t){this.credentials=t}async authenticate(){return Promise.resolve(this.credentials)}};(()=>{if(typeof window<"u"){const t=new CustomEvent("signalwire:js:ready",{detail:{version:"4.0.0-rc.2"}});window.dispatchEvent(t)}})();var Nv=Object.defineProperty,Uv=Object.getOwnPropertyDescriptor,Er=(t,e,i,r)=>{for(var n=r>1?void 0:r?Uv(e,i):e,s=t.length-1,a;s>=0;s--)(a=t[s])&&(n=(r?a(e,i,n):a(n))||n);return r&&n&&Nv(e,i,n),n};const Bv=G();l.SwCallMedia=class extends ee{constructor(){super(...arguments),this.stream=null,this._remoteStreamValue=null,this._lastTrackSignature="",this._subscriptions=[]}connectedCallback(){super.connectedCallback(),!this.stream&&this.call&&this._setupDirectSubscriptions(),this.stream&&(this._remoteStreamValue=this.stream,this._lastTrackSignature=this._computeTrackSignature(this.stream))}updated(e){var i,r,n,s,a;if(super.updated(e),e.has("call")&&(this._cleanupDirectSubscriptions(),!this.stream&&this.call&&this._setupDirectSubscriptions()),e.has("stream")){this._cleanupDirectSubscriptions();const o=this.stream,c=this._computeTrackSignature(o);if(o!==this._remoteStreamValue||c!==this._lastTrackSignature){this._remoteStreamValue=o,this._lastTrackSignature=c;const u=(i=this.shadowRoot)==null?void 0:i.querySelector("video.mcu-video");u&&Xr(u,o)}}if(!this.stream&&!this.call&&e.has("_callState")){const o=((r=this._callState)==null?void 0:r.remoteStream)??null,c=this._computeTrackSignature(o);if(o!==this._remoteStreamValue||c!==this._lastTrackSignature){this._remoteStreamValue=o,this._lastTrackSignature=c;const u=(n=this.shadowRoot)==null?void 0:n.querySelector("video.mcu-video");u&&Xr(u,o)}}e.has("_devicesState")&&this._applySinkId(((a=(s=this._devicesState)==null?void 0:s.selectedAudioOutput)==null?void 0:a.deviceId)??"")}disconnectedCallback(){super.disconnectedCallback(),this._cleanupDirectSubscriptions(),this._cleanupVideoElement()}_setupDirectSubscriptions(){this.call&&this._subscriptions.push(this.call.remoteStream$.subscribe(e=>{var n;const i=this._computeTrackSignature(e);if(e===this._remoteStreamValue&&i===this._lastTrackSignature)return;this._remoteStreamValue=e,this._lastTrackSignature=i,this.requestUpdate();const r=(n=this.shadowRoot)==null?void 0:n.querySelector("video.mcu-video");r&&Xr(r,e)}))}_computeTrackSignature(e){return e?e.getTracks().map(i=>`${i.kind}:${i.id}`).sort().join("|"):""}_cleanupDirectSubscriptions(){this._subscriptions.forEach(e=>e.unsubscribe()),this._subscriptions=[]}_applySinkId(e){var r;const i=(r=this.shadowRoot)==null?void 0:r.querySelector("video.mcu-video");i!=null&&i.setSinkId&&i.setSinkId(e).catch(n=>{Bv.error("[SwCallMedia] Failed to set audio output device:",n)})}_cleanupVideoElement(){var i;const e=(i=this.shadowRoot)==null?void 0:i.querySelector("video.mcu-video");e&&Ma(e)}render(){return I`
72
+ `,(e=this.peerConnection.localDescription)==null?void 0:e.sdp)}handleICECandidateTimeout(){this.iceCandidateTimer&&this.removeTimer("iceCandidateTimer"),He.warn("[ICEGatheringController] ICE candidate timeout");const t=this.hasValidLocalDescriptionSDP;!t&&!this.relayOnly?this.restartICEGatheringWithRelayOnly():(He.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout"),this._iceCandidatesState.next({state:"timeout",validSDP:t}),this.stopGathering())}restartICEGatheringWithRelayOnly(){He.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates"),this.relayOnly=!0,this.peerConnection.setConfiguration({...this.peerConnection.getConfiguration(),iceTransportPolicy:"relay"}),this.peerConnection.restartIce()}removeTimer(t){this[t]&&(clearTimeout(this[t]),this[t]=void 0)}clearAllTimers(){He.debug("[ICEGatheringController] Clearing all timers"),this.removeTimer("iceGatheringTimer"),this.removeTimer("iceCandidateTimer")}removeEventListeners(){this.peerConnection.removeEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.removeEventListener("icecandidate",this.onicecandidateHandler)}destroy(){He.debug("[ICEGatheringController] Destroying ICEGatheringController"),this.clearAllTimers(),this.removeEventListeners(),super.destroy()}};const xs=G();var nf=class extends se{constructor(t={}){super(),this._inputSource=null,this._inputStream=null,this._lastSpokeAt=0,this._gain$=this.createBehaviorSubject(1),this._pttMultiplier=1,this._audioContext=(t.audioContextFactory??(()=>new AudioContext))(),this._gainNode=this._audioContext.createGain(),this._analyser=this._audioContext.createAnalyser(),this._analyser.fftSize=2048,this._analyser.smoothingTimeConstant=.3,this._analyserBuffer=new Uint8Array(new ArrayBuffer(this._analyser.fftSize)),this._destination=this._audioContext.createMediaStreamDestination(),this._gainNode.connect(this._analyser),this._analyser.connect(this._destination),this._speakingThreshold=t.speakingThreshold??Vh,this._speakingHoldMs=t.speakingHoldMs??Hh,this._pollIntervalMs=t.pollIntervalMs??Ro;const e=t.initialGain??1;this._gain$.next(e),this.applyEffectiveGain()}get gain$(){return this._gain$.asObservable()}get gain(){return this._gain$.value}get outputTrack(){const[t]=this._destination.stream.getAudioTracks();return t}get level$(){return this.deferEmission(en(this._pollIntervalMs,qa).pipe(x(()=>this.computeLevel())))}get speaking$(){return this.deferEmission(this.level$.pipe(x(t=>this.evaluateSpeaking(t)),U()))}setGain(t){const e=Math.max(0,Math.min(2,t));this._gain$.next(e),this.applyEffectiveGain()}setPTTActive(t){this._pttMultiplier=t?1:0,this.applyEffectiveGain()}applyEffectiveGain(){this._gainNode.gain.value=this._gain$.value*this._pttMultiplier}setInputTrack(t){if(this._inputSource){try{this._inputSource.disconnect()}catch(e){xs.debug("[LocalAudioPipeline] input disconnect warning:",e)}this._inputSource=null}this._inputStream&&(this._inputStream=null),t&&(this._inputStream=new MediaStream([t]),this._inputSource=this._audioContext.createMediaStreamSource(this._inputStream),this._inputSource.connect(this._gainNode),this._audioContext.state==="suspended"&&this._audioContext.resume().catch(e=>{xs.warn("[LocalAudioPipeline] AudioContext resume failed:",e)}))}destroy(){if(this._inputSource){try{this._inputSource.disconnect()}catch{}this._inputSource=null}try{this._gainNode.disconnect(),this._analyser.disconnect()}catch{}this._audioContext.close().catch(t=>{xs.debug("[LocalAudioPipeline] audio context close warning:",t)}),super.destroy()}computeLevel(){if(!this._inputSource)return 0;this._analyser.getByteTimeDomainData(this._analyserBuffer);let t=0;for(const e of this._analyserBuffer){const i=(e-128)/128;t+=i*i}return Math.sqrt(t/this._analyserBuffer.length)}evaluateSpeaking(t){const e=Date.now();return t>=this._speakingThreshold?(this._lastSpokeAt=e,!0):e-this._lastSpokeAt<this._speakingHoldMs}};const Nt=G();var sf=class extends se{constructor(t){super(),this.options=t,this.mediaTrackEndedHandler=e=>{this._mediaTrackEnded$.next(e)},this._localStream$=this.createBehaviorSubject(null),this._localAudioTracks$=this.createBehaviorSubject([]),this._localVideoTracks$=this.createBehaviorSubject([]),this._mediaTrackEnded$=this.createSubject()}get localStream$(){return this._localStream$.asObservable().pipe(S(this.destroyed$))}get localAudioTracks$(){return this._localAudioTracks$.asObservable().pipe(S(this.destroyed$))}get localVideoTracks$(){return this._localVideoTracks$.asObservable().pipe(S(this.destroyed$))}get mediaTrackEnded$(){return this._mediaTrackEnded$.asObservable().pipe(S(this.destroyed$))}get localStream(){return this._localStream$.value}get localAudioTracks(){return this._localAudioTracks$.value}get localVideoTracks(){return this._localVideoTracks$.value}async buildLocalStream(){var e,i;Nt.debug("[LocalStreamController] Building local media stream.");let t;if(this.options.inputAudioStream??this.options.inputVideoStream){const r=[...((e=this.options.inputAudioStream)==null?void 0:e.getTracks())??[],...((i=this.options.inputVideoStream)==null?void 0:i.getTracks())??[]];t=new MediaStream(r)}else if(this.options.propose==="screenshare")Nt.debug("[LocalStreamController] Requesting display media for screen sharing with audio:",!!this.options.inputAudioDeviceConstraints),t=await this.options.getDisplayMedia({video:!0,audio:!!this.options.inputAudioDeviceConstraints}),Nt.debug("[LocalStreamController] Screen share media obtained:",t);else{const r={audio:this.options.inputAudioDeviceConstraints,video:this.options.inputVideoDeviceConstraints};Nt.debug("[LocalStreamController] Requesting user media with constraints:",r),t=await this.options.getUserMedia(r),Nt.debug("[LocalStreamController] User media obtained:",t)}return this._localStream$.next(t),this._localAudioTracks$.next(t.getAudioTracks()),this._localVideoTracks$.next(t.getVideoTracks()),t}addTrack(t){const e=this._localStream$.value??new MediaStream;return t.addEventListener("ended",this.mediaTrackEndedHandler),e.addTrack(t),this._localStream$.next(e),t.kind==="video"?this._localVideoTracks$.next(e.getVideoTracks()):this._localAudioTracks$.next(e.getAudioTracks()),Nt.debug(`[LocalStreamController] ${t.kind} track added:`,t.id),e}removeTrack(t){const e=this._localStream$.value,i=e==null?void 0:e.getTracks().find(r=>r.id===t);if(!i){Nt.debug(`[LocalStreamController] track not found: ${t}`);return}return i.removeEventListener("ended",this.mediaTrackEndedHandler),e==null||e.removeTrack(i),i.stop(),this._localStream$.next(e),i.kind==="video"?this._localVideoTracks$.next((e==null?void 0:e.getVideoTracks())??[]):this._localAudioTracks$.next((e==null?void 0:e.getAudioTracks())??[]),Nt.debug(`[LocalStreamController] ${i.kind} track removed:`,t),i}getOrCreateLocalStream(){return this._localStream$.value??new MediaStream}setLocalStream(t){this._localStream$.next(t)}addTrackEndedListener(t){t.addEventListener("ended",this.mediaTrackEndedHandler)}updateOptions(t){this.options={...this.options,...t}}stopAllTracks(){var t;(t=this._localStream$.value)==null||t.getTracks().forEach(e=>{Nt.debug(`[LocalStreamController] Stopping local track: ${e.kind}`),e.removeEventListener("ended",this.mediaTrackEndedHandler),e.stop()})}destroy(){this.stopAllTracks(),super.destroy()}};const je=G(),Tc=(t,e)=>t&&e?"sendrecv":t&&!e?"sendonly":!t&&e?"recvonly":"inactive";var af=class extends se{constructor(t){super(),this.peerConnection=t.peerConnection,this.options=t}get useAddTransceivers(){return typeof this.peerConnection.addTransceiver=="function"}get useAddTrack(){return typeof this.peerConnection.addTrack=="function"}get useAddStream(){return typeof this.peerConnection.addStream=="function"&&!this.useAddTransceivers&&!this.useAddTrack}get propose(){return this.options.propose}get isAdditionalDevice(){return this.propose==="additional-device"}get isScreenShare(){return this.propose==="screenshare"}get isSimulcast(){return!!this.options.simulcast}get isSFU(){return!!this.options.sfu}get receiveVideo(){return!!this.options.receiveVideo}get receiveAudio(){return!!this.options.receiveAudio}get localStream(){return this.options.localStreamController.localStream}get inputAudioDeviceConstraints(){return this.options.getInputAudioDeviceConstraints()}get inputVideoDeviceConstraints(){return this.options.getInputVideoDeviceConstraints()}get audioDirection(){if(this.isAdditionalDevice)return"sendonly";const{localStream:t}=this,e=t==null?void 0:t.getAudioTracks().some(n=>n.enabled),i=!!this.inputAudioDeviceConstraints,r=!!this.receiveAudio;return Tc(e||i,r)}get videoDirection(){if(this.isAdditionalDevice||this.isScreenShare)return"sendonly";if(this.isSFU)return"recvonly";const{localStream:t}=this,e=t==null?void 0:t.getVideoTracks().some(n=>n.enabled),i=!!this.inputVideoDeviceConstraints,r=!!this.receiveVideo;return Tc(e||i,r)}get sendEncodings(){if(this.isSimulcast)return["0","1","2"].map(t=>({active:!0,rid:t,scaleResolutionDownBy:Number(t)*6||1}))}getConstraintsFor(t){const e=t==="audio"?this.inputAudioDeviceConstraints:this.inputVideoDeviceConstraints;return typeof e=="boolean"?{}:e}transceiverByKind(t){return this.peerConnection.getTransceivers().filter(e=>t==="both"||e.receiver.track.kind===t)}get audioTransceivers(){return this.transceiverByKind("audio")}get videoTransceivers(){return this.transceiverByKind("video")}async setupTransceiverSender(t,e,i){var a;const r=t.kind==="audio",n=r?this.audioDirection:this.videoDirection,s={direction:n,sendEncodings:r?void 0:this.sendEncodings,streams:n==="recvonly"?void 0:[e]};je.debug(`[TransceiverController] Setting up transceiver sender for local ${t.kind} track:`,{transceiver:i,transceiverParams:s}),s.direction&&["sendonly","sendrecv"].includes(s.direction)&&(i?(await i.sender.replaceTrack(t),i.direction=s.direction,(a=s.streams)!=null&&a.some(o=>!!o)&&(je.debug(`[TransceiverController] Setting streams for transceiver sender for local ${t.kind} track:`,s.streams),i.sender.setStreams(...s.streams))):(je.debug(`[TransceiverController] Adding new transceiver for local ${t.kind} track:`,t.id),this.peerConnection.addTransceiver(t,s)))}stopTrackSender(t,e={updateTransceiverDirection:!1}){var i,r,n;try{const s=this.transceiverByKind(t);for(const a of s)if(((i=a.sender.track)==null?void 0:i.readyState)==="live"){const o=a.sender.track.id;a.sender.track.stop(),this.options.localStreamController.removeTrack(o),e.updateTransceiverDirection&&(a.direction="inactive")}}catch(s){je.error("[TransceiverController] stopTrackSender error",t,s),(n=(r=this.options).onError)==null||n.call(r,new kt("stopTrackSender",t,s))}}async restoreTrackSender(t){var e,i;try{je.debug("[TransceiverController] restoreTrackSender called",t);const r={},n=this.transceiverByKind(t);for(const a of n){const{track:o}=a.sender;if(!o||o.readyState==="ended"){const c=(o==null?void 0:o.kind)??a.receiver.track.kind;(c==="audio"||c==="video")&&(r[c]=this.getConstraintsFor(c))}}if(je.debug("[TransceiverController] restoreTrackSender constraints:",r),Object.keys(r).length===0){je.warn("[TransceiverController] restoreTrackSender: no tracks need restoration",t);return}const s=(await this.options.getUserMedia(r)).getTracks();je.debug("[TransceiverController] restoreTrackSender new tracks:",s);for(const a of s){this.options.localStreamController.addTrack(a);const o=a.kind,c=this.transceiverByKind(o)[0];c.direction=o==="audio"?this.audioDirection:this.videoDirection,je.debug("[TransceiverController] restoreTrackSender setting direction for",o,c.direction),await c.sender.replaceTrack(a)}}catch(r){je.error("[TransceiverController] restoreTrackSender error",t,r),(i=(e=this.options).onError)==null||i.call(e,new kt("restoreTrackSender",t,r))}}async replaceSenderTrack(t,e){const i=t==="audio"?this.audioTransceivers:this.videoTransceivers;for(const r of i)await r.sender.replaceTrack(e)}async setupRemoteTransceivers(t){if(t!=="answer"){for(const e of["audio","video"]){const i=e==="audio"?this.audioTransceivers:this.videoTransceivers;for(const r of i){const n=e==="audio"?this.audioDirection:this.videoDirection;["inactive","recvonly"].includes(n)&&(r.direction=n,await r.sender.replaceTrack(null),r.sender.setStreams())}}if(this.videoDirection==="recvonly"&&this.isSFU&&this.useAddTransceivers){const{msStreamsNumber:e=5}=this.options;for(let i=0;i<Number(e);i++)this.peerConnection.addTransceiver("video",{direction:"recvonly"})}}}async updateSendersConstraints(t,e){var r,n;if(!e)return this.stopTrackSender(t),Promise.resolve();const i=this.peerConnection.getSenders().filter(s=>{var a;return((a=s.track)==null?void 0:a.kind)===t&&s.track.readyState==="live"});for(const s of i){const{track:a}=s;if(a){const o={...a.getConstraints(),...e};try{await a.applyConstraints(o),je.debug(`[TransceiverController] Updated ${t} sender constraints:`,o),je.debug(`[TransceiverController] Updated ${t} sender constraints:`,a.getConstraints())}catch(c){je.warn(`[TransceiverController] applyConstraints failed for ${t} track ${a.id}, attempting track replacement fallback:`,c);try{await this.replaceTrackFallback(s,a,t,o)}catch(u){je.warn(`[TransceiverController] Track replacement fallback also failed for ${t} track:`,u),(n=(r=this.options).onError)==null||n.call(r,new kt("updateSendersConstraints",t,u))}}}}}async replaceTrackFallback(t,e,i,r){const{deviceId:n}=e.getSettings(),s={...r,...n?{deviceId:{exact:n}}:{}},a=e.id;e.stop(),this.options.localStreamController.removeTrack(a);const o=(await this.options.getUserMedia({[i]:s})).getTracks().find(c=>c.kind===i);if(!o)throw new kt("replaceTrackFallback",i,new Error("getUserMedia returned no track of the requested kind"));await t.replaceTrack(o),this.options.localStreamController.addTrack(o),je.debug(`[TransceiverController] Track replacement fallback succeeded for ${i}. New track: ${o.id}`)}getMediaDirections(){return this.peerConnection.connectionState==="connected"?this.peerConnection.getTransceivers().reduce((t,e)=>({...t,[e.receiver.track.kind]:e.direction}),{audio:"inactive",video:"inactive"}):{audio:this.audioDirection,video:this.videoDirection}}updatePeerConnection(t){this.peerConnection=t}updateOptions(t){this.options={...this.options,...t}}};const z=G();var Ec=class extends se{constructor(t={},e,i){super(),this.options=t,this.firstSDPExchangeCompleted=!1,this.negotiationNeeded$=this.createSubject(),this.localDescription$=li(()=>_e(this.init())).pipe(Je(()=>this.iceGatheringController.iceCandidatesState$.pipe(B(n=>!["new","gathering"].includes(n)),Ee(()=>{this.negotiationEnded()}),B(()=>this.shouldEmitLocalDescription),x(()=>{var n;return(n=this.peerConnection)==null?void 0:n.localDescription}),ve(),Ee(n=>{n.type==="answer"&&(this._type="offer")}))),st(1),S(this.destroyed$)),this.connectionTimeout=3e3,this.oniceconnectionstatechangeHandler=()=>{if(this.peerConnection){const{iceConnectionState:n}=this.peerConnection;z.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${n}`),this._iceConnectionState$.next(this.peerConnection.iceConnectionState)}},this.onconnectionstatechangeHandler=()=>{if(this.peerConnection){const{connectionState:n}=this.peerConnection;z.debug(`[RTCPeerConnectionController] Connection state changed to: ${n}`),n==="connected"&&this.removeConnectionTimer(),this._connectionState$.next(this.peerConnection.connectionState)}},this.onsignalingstatechangeHandler=()=>{var n;z.debug(`[RTCPeerConnectionController] Signaling state changed to: ${(n=this.peerConnection)==null?void 0:n.signalingState}`)},this.onicegatheringstatechangeHandler=()=>{this.peerConnection&&this._iceGatheringState$.next(this.peerConnection.iceGatheringState)},this.onnegotiationneededHandler=n=>{z.debug("[RTCPeerConnectionController] Negotiation needed event received.",n),this.negotiationNeeded$.next()},this.updateSelectedInputDevice=async(n,s)=>{var a,o,c;try{const{localStream:u}=this;if(!u){z.warn("[RTCPeerConnectionController] No local stream available to update input device.");return}z.debug(`[RTCPeerConnectionController] Updating selected ${n} input device:`,u.getTracks());const h=u.getTracks().find(p=>p.kind===n);if(h){if((a=this.transceiverController)==null||a.stopTrackSender(n),this.localStreamController.removeTrack(h.id),z.debug(`[RTCPeerConnectionController] Stopped existing ${n} track: ${h.id}`,u.getTracks()),!s){z.debug(`[RTCPeerConnectionController] ${n} input device selected: none`);return}const p=(await this.getUserMedia({[n]:{...h.getConstraints(),...this.deviceController.deviceInfoToConstraints(s)}})).getTracks().find(v=>v.kind===n);p&&(z.debug(`[RTCPeerConnectionController] Adding new ${n} track: ${p.id}`),this.localStreamController.addTrack(p),await((o=this.transceiverController)==null?void 0:o.replaceSenderTrack(n,p)),z.debug(`[RTCPeerConnectionController] Added new ${n} track: ${p.id}`,(c=this.localStream)==null?void 0:c.getTracks()))}z.debug(`[RTCPeerConnectionController] ${n} input device selected:`,s==null?void 0:s.label)}catch(u){throw z.error(`[RTCPeerConnectionController] Failed to select ${n} input device:`,u),this._errors$.next(new kt("updateSelectedInputDevice",n,u)),u}},this._isNegotiating$=this.createBehaviorSubject(!1),this._memberId=null,this._iceConnectionState$=this.createReplaySubject(1),this._connectionState$=this.createReplaySubject(1),this._signalingState$=this.createReplaySubject(1),this._iceGatheringState$=this.createReplaySubject(1),this._errors$=this.createReplaySubject(1),this._iceCandidates$=this.createReplaySubject(1),this._initialized$=this.createReplaySubject(1),this._remoteDescription$=this.createReplaySubject(1),this._remoteStream$=this.createBehaviorSubject(null),this._remoteOfferMediaDirections=null,this._localAudioPipeline=null,this.deviceController=i??{},this.id=t.callId??dn(),this._type=e?"answer":"offer",this.sdpInit=e?{type:"offer",sdp:e}:void 0,this._remoteOfferMediaDirections=e?Kg(e):null;const r=this._remoteOfferMediaDirections?{audio:this._remoteOfferMediaDirections.audio.includes("recv"),video:this._remoteOfferMediaDirections.video.includes("recv"),receiveAudio:this._remoteOfferMediaDirections.audio.includes("send"),receiveVideo:this._remoteOfferMediaDirections.video.includes("send")}:{};this.options={...t,audio:t.audio??r.audio,video:t.video??r.video,receiveAudio:t.receiveAudio??r.receiveAudio??f.instance.receiveAudio,receiveVideo:t.receiveVideo??r.receiveVideo??f.instance.receiveVideo},this.localStreamController=new sf({propose:this.propose,inputAudioStream:this.options.inputAudioStream,inputVideoStream:this.options.inputVideoStream,inputAudioDeviceConstraints:this.inputAudioDeviceConstraints,inputVideoDeviceConstraints:this.inputVideoDeviceConstraints,getUserMedia:async n=>this.getUserMedia(n),getDisplayMedia:async n=>this.getDisplayMedia(n)})}get iceGatheringController(){if(!this._iceGatheringController)throw new te("ICEGatheringController is not initialized");return this._iceGatheringController}get shouldEmitLocalDescription(){if(!this.peerConnection)return!1;const{localDescription:t,signalingState:e}=this.peerConnection;return!t||!Cc(t.sdp)?!1:t.type==="offer"&&e==="have-local-offer"||t.type==="answer"&&e==="stable"}removeConnectionTimer(){this.connectionTimer&&(clearTimeout(this.connectionTimer),this.connectionTimer=void 0)}setMemberId(t){this._memberId=t}get memberId(){return this._memberId}stopTrackSender(t,e={updateTransceiverDirection:!1}){var r,n,s;const i=t==="audio"||t==="both";i&&this._localAudioPipeline&&this.stopRawAudioInputForPipeline(),i?t==="both"?(n=this.transceiverController)==null||n.stopTrackSender("video",e):this._localAudioPipeline||(s=this.transceiverController)==null||s.stopTrackSender(t,e):(r=this.transceiverController)==null||r.stopTrackSender(t,e)}stopRawAudioInputForPipeline(){var e;const t=this.localStreamController.localAudioTracks;for(const i of t)i.readyState==="live"&&(i.stop(),this.localStreamController.removeTrack(i.id));(e=this._localAudioPipeline)==null||e.setInputTrack(null)}get isNegotiating$(){return this._isNegotiating$.asObservable()}get isNegotiating(){return this._isNegotiating$.value}updateMediaDevicesOptions(t){this.options={...this.options,...t}}get iceGatheringState$(){return this.cachedObservable("iceGatheringState$",()=>this._iceGatheringState$.asObservable().pipe(S(this.destroyed$)))}get mediaTrackEnded$(){return this.cachedObservable("mediaTrackEnded$",()=>this.localStreamController.mediaTrackEnded$.pipe(S(this.destroyed$)))}get errors$(){return this.cachedObservable("errors$",()=>this._errors$.asObservable().pipe(S(this.destroyed$)))}get iceCandidates$(){return this.cachedObservable("iceCandidates$",()=>this._iceCandidates$.asObservable().pipe(S(this.destroyed$)))}get initialized$(){return this.cachedObservable("initialized$",()=>this._initialized$.asObservable().pipe(B(t=>t),S(this.destroyed$)))}get remoteDescription$(){return this.cachedObservable("remoteDescription$",()=>this._remoteDescription$.asObservable().pipe(S(this.destroyed$)))}get localStream$(){return this.cachedObservable("localStream$",()=>this.localStreamController.localStream$.pipe(S(this.destroyed$)))}get remoteStream$(){return this.cachedObservable("remoteStream$",()=>this._remoteStream$.asObservable().pipe(S(this.destroyed$)))}get localAudioTracks$(){return this.cachedObservable("localAudioTracks$",()=>this.localStreamController.localAudioTracks$.pipe(S(this.destroyed$)))}get localVideoTracks$(){return this.cachedObservable("localVideoTracks$",()=>this.localStreamController.localVideoTracks$.pipe(S(this.destroyed$)))}get iceConnectionState$(){return this.cachedObservable("iceConnectionState$",()=>this._iceConnectionState$.asObservable().pipe(S(this.destroyed$)))}get connectionState$(){return this.cachedObservable("connectionState$",()=>this._connectionState$.asObservable().pipe(S(this.destroyed$)))}get signalingState$(){return this.cachedObservable("signalingState$",()=>this._signalingState$.asObservable().pipe(S(this.destroyed$)))}get type(){return this._type}get propose(){return this.options.propose??"main"}get isAdditionalDevice(){return this.propose==="additional-device"}get isMainDevice(){return this.propose==="main"}get isScreenShare(){return this.propose==="screenshare"}get iceServers(){if(!this.options.disableUdpIceServers)return this.options.iceServers??[];const t="transport=tcp";return(this.options.iceServers??[]).map(e=>{const i=Array.isArray(e.urls)?e.urls:[e.urls];return{...e,urls:i.filter(r=>r.includes(t))}})}get rtcConfiguration(){const{iceServers:t,...e}=this.options;return{bundlePolicy:"max-compat",iceCandidatePoolSize:10,iceServers:this.iceServers,iceTransportPolicy:this.options.relayOnly?"relay":"all",sdpSemantics:"unified-plan",...e}}get receiveVideo(){return!!this.options.receiveVideo}get receiveAudio(){return!!this.options.receiveAudio}get localStream(){return this.localStreamController.localStream}get remoteStream(){return this._remoteStream$.value}get inputAudioDeviceConstraints(){if(this.options.audio===!1&&!this.options.inputAudioDeviceConstraints)return!1;const t=this.deviceController.selectedAudioInputDeviceConstraints;return t===!1?!1:{...typeof this.options.inputAudioDeviceConstraints=="object"?this.options.inputAudioDeviceConstraints:{},...typeof t=="object"?t:{}}}get inputVideoDeviceConstraints(){if(!this.options.video&&!this.options.inputVideoDeviceConstraints)return!1;const t=this.deviceController.selectedVideoInputDeviceConstraints;return t===!1?!1:{...typeof this.options.inputVideoDeviceConstraints=="object"?this.options.inputVideoDeviceConstraints:{},...typeof t=="object"?t:{}}}get WebRTCPeerConnectionConstructor(){var t;return((t=this.options.webRTCApiProvider)==null?void 0:t.RTCPeerConnection)??RTCPeerConnection}get offerOptions(){const t={iceRestart:this.firstSDPExchangeCompleted?!0:void 0};switch(this.propose){case"screenshare":case"additional-device":return{...t,offerToReceiveAudio:!1,offerToReceiveVideo:!1};case"main":default:return{...t,offerToReceiveAudio:this.options.receiveAudio??!0,offerToReceiveVideo:this.options.receiveVideo??!!this.inputVideoDeviceConstraints}}}get answerOptions(){return{iceRestart:this.firstSDPExchangeCompleted?!0:void 0}}async init(){return this.initPromise??(this.initPromise=this.doInit()),this.initPromise}async doInit(){try{this.setupPeerConnection(),this.subscribeTo(this.negotiationNeeded$.pipe(qd(0),ls(async()=>this.startNegotiation())),{next:()=>{z.debug("[RTCPeerConnectionController] Start Negotiation completed successfully")},error:t=>{z.error("[RTCPeerConnectionController] Start Negotiation error:",t),this._errors$.next(hi(t))}}),this.subscribeTo(Ni(this.deviceController.selectedAudioInputDevice$.pipe(x(t=>["audio",t])),this.deviceController.selectedVideoInputDevice$.pipe(x(t=>["video",t]))).pipe(eh(()=>!this.localStreamController.localStream)),async([t,e])=>{z.debug("[RTCPeerConnectionController] Selected input device changed for:",{kind:t,deviceInfo:e}),await this.updateSelectedInputDevice(t,e)}),this.type==="answer"&&this.sdpInit?(await this.setupRemoteTracks(),this._initialized$.next(!0),this.setupEventListeners(),this._isNegotiating$.next(!0),await this._setRemoteDescription(this.sdpInit)):(await this.setupTrackHandling(),this._initialized$.next(!0))}catch(t){z.error("[RTCPeerConnectionController] Initialization error:",t),this._errors$.next(hi(t)),this.destroy()}}setupPeerConnection(){this.peerConnection=new this.WebRTCPeerConnectionConstructor(this.rtcConfiguration),this.peerConnection.addEventListener("negotiationneeded",this.onnegotiationneededHandler),this._iceGatheringController=new rf(this.peerConnection,this.isNegotiating$,{iceCandidateTimeout:this.options.iceCandidateTimeout,iceGatheringTimeout:this.options.iceGatheringTimeout,relayOnly:this.options.relayOnly}),this.transceiverController=new af({peerConnection:this.peerConnection,propose:this.propose,simulcast:this.options.simulcast,sfu:this.options.sfu,msStreamsNumber:this.options.msStreamsNumber,receiveAudio:this.receiveAudio,receiveVideo:this.receiveVideo,localStreamController:this.localStreamController,getInputAudioDeviceConstraints:()=>this.inputAudioDeviceConstraints,getInputVideoDeviceConstraints:()=>this.inputVideoDeviceConstraints,getUserMedia:async t=>this.getUserMedia(t),onError:t=>{this._errors$.next(t)}})}async startNegotiation(){if(this.isNegotiating){z.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");return}if(this.setupEventListeners(),this.type==="answer"){z.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");return}this._isNegotiating$.next(!0),z.debug("[RTCPeerConnectionController] Starting negotiation.");try{const{offerOptions:t}=this;z.debug("[RTCPeerConnectionController] Creating offer with options:",t),await this.createOffer(t)}catch(t){z.error("[RTCPeerConnectionController] Error during negotiation:",t),this._errors$.next(hi(t))}}async createOffer(t){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");const e=await this.peerConnection.createOffer(t);await this.setLocalDescription(e)}async updateAnswerStatus({status:t,sdp:e}){let i=t!=="failed";try{t==="received"&&e&&(z.debug("[RTCPeerConnectionController] Received answer SDP:",e),await this._setRemoteDescription({type:"answer",sdp:e}))}catch(r){z.error("[RTCPeerConnectionController] Error updating answer status:",r),this._errors$.next(hi(r)),i=!1}finally{i?this.readyToConnect():this.iceGatheringController.restartICEGatheringWithRelayOnly()}}async updateOfferStatus({status:t,sdp:e}){switch(t){case"received":this._type="answer",this.sdpInit={type:"offer",sdp:e},await this.handleOfferReceived();break;case"failed":z.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");break}}async acceptInbound(t){var i;if(t){const{audio:r,video:n,receiveAudio:s,receiveVideo:a,fallbackToReceiveOnly:o}=t;this.options={...this.options,...r!==void 0?{audio:r}:{},...n!==void 0?{video:n}:{},...s!==void 0?{receiveAudio:s}:{},...a!==void 0?{receiveVideo:a}:{},...o!==void 0?{fallbackToReceiveOnly:o}:{}},(i=this.transceiverController)==null||i.updateOptions({receiveAudio:this.receiveAudio,receiveVideo:this.receiveVideo}),this.localStreamController.updateOptions({inputAudioDeviceConstraints:this.inputAudioDeviceConstraints,inputVideoDeviceConstraints:this.inputVideoDeviceConstraints})}await this.setupLocalTracks();const{answerOptions:e}=this;z.debug("[RTCPeerConnectionController] Creating inbound answer with options:",e),await this.createAnswer(e)}async handleOfferReceived(){if(!this.sdpInit)throw new te("SDP initialization parameters are not set");this._isNegotiating$.next(!0),await this._setRemoteDescription(this.sdpInit);const{answerOptions:t}=this;z.debug("[RTCPeerConnectionController] Creating answer with options:",t),await this.createAnswer(t)}readyToConnect(){this.firstSDPExchangeCompleted=!0,this.connectionTimer=setTimeout(()=>{var t;this.removeConnectionTimer(),((t=this.peerConnection)==null?void 0:t.connectionState)!=="connected"&&(z.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only."),this.iceGatheringController.restartICEGatheringWithRelayOnly())},this.connectionTimeout)}async setRemoteDescriptionBefore(t=""){return Promise.resolve(t)}async setLocalDescription(t){var i;const e=await this.setLocalDescriptionBefore(t.sdp);return(i=this.peerConnection)==null?void 0:i.setLocalDescription({...t,sdp:e})}async setLocalDescriptionBefore(t=""){let e=t;const i=this.options.preferredAudioCodecs??f.instance.preferredAudioCodecs,r=this.options.preferredVideoCodecs??f.instance.preferredVideoCodecs,n=this.options.stereo??f.instance.stereoAudio;return(i.length>0||r.length>0)&&(e=Jg(e,i,r),z.debug("[RTCPeerConnectionController] Applied codec preferences to SDP",{preferredAudioCodecs:i,preferredVideoCodecs:r})),n&&(e=Qg(e),z.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP")),Promise.resolve(e)}async createAnswer(t){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");const e=await this.peerConnection.createAnswer(t);await this.setLocalDescription(e)}setupEventListeners(){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");this._iceConnectionState$.next(this.peerConnection.iceConnectionState),this._connectionState$.next(this.peerConnection.connectionState),this._signalingState$.next(this.peerConnection.signalingState),this._iceGatheringState$.next(this.peerConnection.iceGatheringState),this._remoteDescription$.next(this.peerConnection.remoteDescription),this.peerConnection.removeEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.addEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.removeEventListener("iceconnectionstatechange",this.oniceconnectionstatechangeHandler),this.peerConnection.addEventListener("iceconnectionstatechange",this.oniceconnectionstatechangeHandler),this.peerConnection.removeEventListener("connectionstatechange",this.onconnectionstatechangeHandler),this.peerConnection.addEventListener("connectionstatechange",this.onconnectionstatechangeHandler),this.peerConnection.removeEventListener("signalingstatechange",this.onsignalingstatechangeHandler),this.peerConnection.addEventListener("signalingstatechange",this.onsignalingstatechangeHandler)}negotiationEnded(){this._isNegotiating$.next(!1)}async triggerIceRestart(t){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");const e=t&&!this.options.relayOnly;if(e)try{this.peerConnection.setConfiguration({...this.peerConnection.getConfiguration(),iceTransportPolicy:"relay"}),z.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only")}catch(i){z.warn("[RTCPeerConnectionController] Failed to set relay-only policy:",i)}this.setupEventListeners(),this._isNegotiating$.next(!0),z.debug(`[RTCPeerConnectionController] Triggering ICE restart${t?" (relay-only)":""}.`);try{const i=await this.peerConnection.createOffer({iceRestart:!0});await this.setLocalDescription(i)}catch(i){throw z.error("[RTCPeerConnectionController] ICE restart offer failed:",i),this._errors$.next(hi(i)),this.negotiationEnded(),e&&this.restoreIceTransportPolicy(),i}e&&Ze(Cr(this._iceGatheringState$.pipe(B(i=>i==="complete"),Oe(1)),Fi(Uh).pipe(x(()=>"timeout")))).then(()=>this.restoreIceTransportPolicy()).catch(i=>{z.warn("[RTCPeerConnectionController] Error waiting for ICE gathering to complete:",i),this.restoreIceTransportPolicy()})}restoreIceTransportPolicy(){var t;try{(t=this.peerConnection)==null||t.setConfiguration({...this.peerConnection.getConfiguration(),iceTransportPolicy:this.options.relayOnly?"relay":"all"}),z.debug("[RTCPeerConnectionController] ICE transport policy restored")}catch(e){z.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:",e)}}async setupTrackHandling(){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");await this.setupLocalTracks(),await this.setupRemoteTracks()}async setupLocalTracks(){var e,i,r,n,s,a,o;if(z.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers."),this.hasNoLocalMediaToSend()){if(!this.receiveAudio&&!this.receiveVideo)throw new on("Call requests no media: enable audio/video or receiveAudio/receiveVideo");z.debug("[RTCPeerConnectionController] No local media requested; negotiating receive-only."),this.setupReceiveOnlyTransceivers();return}let t;try{t=this.localStream??await this.localStreamController.buildLocalStream()}catch(c){this.handleLocalMediaFailure(c);return}if(((e=this.transceiverController)==null?void 0:e.useAddStream)??!1){z.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream."),(i=this.peerConnection)==null||i.addStream(t),this.isNegotiating||(z.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup."),this.negotiationNeeded$.next());return}for(const c of["audio","video"]){const u=(c==="audio"?t.getAudioTracks():t.getVideoTracks()).map((h,p)=>({index:p,track:h}));for(const{index:h,track:p}of u)if(this.localStreamController.addTrackEndedListener(p),((r=this.transceiverController)==null?void 0:r.useAddTransceivers)??!1){const v=(c==="audio"?(n=this.transceiverController)==null?void 0:n.audioTransceivers:(s=this.transceiverController)==null?void 0:s.videoTransceivers)??[];await((a=this.transceiverController)==null?void 0:a.setupTransceiverSender(p,t,v[h]))}else z.debug(`[RTCPeerConnectionController] Using addTrack for local ${c} track:`,p.id),(o=this.peerConnection)==null||o.addTrack(p,t)}}hasNoLocalMediaToSend(){const t=!!(this.options.inputAudioStream??this.options.inputVideoStream);return this.propose==="main"&&!this.localStream&&!t&&!this.inputAudioDeviceConstraints&&!this.inputVideoDeviceConstraints}get requestedMediaKinds(){const t=!!this.inputAudioDeviceConstraints,e=!!this.inputVideoDeviceConstraints;return t&&e?"audiovideo":e?"video":"audio"}handleLocalMediaFailure(t){if(this.propose==="screenshare")throw new Gt("startScreenShare","screen",t,!1);if(this.propose==="additional-device")throw new Gt("addInputDevice",this.requestedMediaKinds,t,!1);const e=this.receiveAudio||this.receiveVideo;if(!((this.options.fallbackToReceiveOnly??!0)&&e))throw new Gt("acquireLocalMedia",this.requestedMediaKinds,t,!0);z.warn("[RTCPeerConnectionController] Local media unavailable; continuing receive-only:",t),this._errors$.next(new Gt("acquireLocalMedia",this.requestedMediaKinds,t,!1)),this.setupReceiveOnlyTransceivers()}setupReceiveOnlyTransceivers(){var t,e,i;this.type==="offer"&&((((t=this.transceiverController)==null?void 0:t.useAddTransceivers)??!1)&&((e=this.peerConnection)==null||e.addTransceiver("audio",{direction:this.receiveAudio?"recvonly":"inactive"}),(i=this.peerConnection)==null||i.addTransceiver("video",{direction:this.receiveVideo?"recvonly":"inactive"})),this.isNegotiating||this.negotiationNeeded$.next())}async getUserMedia(t){var e;return(((e=this.options.webRTCApiProvider)==null?void 0:e.mediaDevices)??navigator.mediaDevices).getUserMedia(t)}async getDisplayMedia(t){var i;const e=((i=this.options.webRTCApiProvider)==null?void 0:i.mediaDevices)??navigator.mediaDevices;if(!e.getDisplayMedia)throw new te("getDisplayMedia is not supported by the current WebRTC provider");return e.getDisplayMedia(t)}async setupRemoteTracks(){var t;if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");this.peerConnection.ontrack=e=>{var i;if(z.debug("[RTCPeerConnectionController] Remote track received:",e.track.kind),e.streams[0])this._remoteStream$.next(e.streams[0]);else{const r=((i=this._remoteStream$.value)==null?void 0:i.getTracks())??[],n=new MediaStream([...r,e.track]);this._remoteStream$.next(n)}},await((t=this.transceiverController)==null?void 0:t.setupRemoteTransceivers(this.type))}async restoreTrackSender(t){var i,r,n;const e=t==="audio"||t==="both";e&&this._localAudioPipeline&&await this.restoreRawAudioInputForPipeline(),e?t==="both"?await((r=this.transceiverController)==null?void 0:r.restoreTrackSender("video")):this._localAudioPipeline||await((n=this.transceiverController)==null?void 0:n.restoreTrackSender(t)):await((i=this.transceiverController)==null?void 0:i.restoreTrackSender(t))}async restoreRawAudioInputForPipeline(){var r;if(!this._localAudioPipeline)return;const t=((r=this.transceiverController)==null?void 0:r.getConstraintsFor("audio"))??{};let e;try{e=await this.getUserMedia({audio:t})}catch(n){z.error("[RTCPeerConnectionController] Failed to re-acquire mic for pipeline restore:",n),this._errors$.next(new kt("restoreAudioPipelineInput","audio",n));return}const i=e.getAudioTracks().at(0);i&&(this.localStreamController.addTrack(i),this._localAudioPipeline.setInputTrack(i))}ensureLocalAudioPipeline(){if(this._localAudioPipeline)return this._localAudioPipeline;if(!this.peerConnection)return null;try{this._localAudioPipeline=new nf}catch(t){return z.warn("[RTCPeerConnectionController] Failed to create LocalAudioPipeline:",t),null}return this.subscribeTo(this.localStreamController.localAudioTracks$,()=>{this.applyLocalAudioPipelineToSender()}),this.applyLocalAudioPipelineToSender(),this._localAudioPipeline}get localAudioPipeline(){return this._localAudioPipeline}async applyLocalAudioPipelineToSender(){var i,r;if(!this._localAudioPipeline||!this.peerConnection)return;const t=this.localStreamController.localAudioTracks.at(0);this._localAudioPipeline.setInputTrack(t??null);const e=((r=(i=this.transceiverController)==null?void 0:i.audioTransceivers.at(0))==null?void 0:r.sender)??this.peerConnection.getSenders().find(n=>{var s;return((s=n.track)==null?void 0:s.kind)==="audio"});if(!(!e||!t))try{await e.replaceTrack(this._localAudioPipeline.outputTrack)}catch(n){z.warn("[RTCPeerConnectionController] Failed to route audio sender through pipeline:",n)}}addLocalTrack(t){if(!this.peerConnection){const e=new te("RTCPeerConnection is not initialized");throw this._errors$.next(e),e}try{const e=this.localStreamController.addTrack(t);this.peerConnection.addTrack(t,e),z.debug(`[RTCPeerConnectionController] ${t.kind} track added:`,t.id)}catch(e){throw z.error(`[RTCPeerConnectionController] Failed to add ${t.kind} track:`,e),this._errors$.next(new kt("addLocalTrack",t.kind,e)),e}}removeLocalTrack(t){var i,r,n;if(!this.peerConnection){const s=new te("RTCPeerConnection is not initialized");throw this._errors$.next(s),s}const e=this.peerConnection.getSenders().find(s=>{var a;return((a=s.track)==null?void 0:a.id)===t});if(!e){z.debug(`[RTCPeerConnectionController] track not found: ${t}`);return}try{this.peerConnection.removeTrack(e),this.localStreamController.removeTrack(t),z.debug(`[RTCPeerConnectionController] ${(i=e.track)==null?void 0:i.kind} track removed:`,t)}catch(s){throw z.error(`[RTCPeerConnectionController] Failed to remove ${(r=e.track)==null?void 0:r.kind} track:`,s),this._errors$.next(new kt("removeLocalTrack",((n=e.track)==null?void 0:n.kind)??"unknown",s)),s}}setLocalTrack(t){const e=[...t.kind==="audio"?this.localStreamController.localAudioTracks:this.localStreamController.localVideoTracks];for(const i of e)this.removeLocalTrack(i.id);this.addLocalTrack(t)}async updateSendersConstraints(t,e){var i;await((i=this.transceiverController)==null?void 0:i.updateSendersConstraints(t,e))}async replaceAudioTrackWithConstraints(t){var i;const e=(i=this.peerConnection)==null?void 0:i.getSenders().filter(r=>{var n;return((n=r.track)==null?void 0:n.kind)==="audio"&&r.track.readyState==="live"});if(!e||e.length===0){z.warn("[RTCPeerConnectionController] No live audio sender to replace");return}for(const r of e){const n=r.track;if(!n)continue;const{deviceId:s}=n.getSettings(),a={...n.getConstraints(),...t,...s?{deviceId:{exact:s}}:{}},o=n.id;n.stop(),this.localStreamController.removeTrack(o);const c=(await this.getUserMedia({audio:a})).getAudioTracks()[0];await r.replaceTrack(c),this.localStreamController.addTrack(c),z.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${c.id}`)}}destroy(){var t,e,i;z.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`),this.removeConnectionTimer(),(t=this._iceGatheringController)==null||t.destroy(),(e=this._localAudioPipeline)==null||e.destroy(),this._localAudioPipeline=null,this.localStreamController.destroy(),(i=this.transceiverController)==null||i.destroy(),this.peerConnection&&(this.stopRemoteTracks(),this.removeAllListeners(),this.peerConnection.close(),this.peerConnection=void 0),super.destroy()}removeAllListeners(){this.peerConnection&&(this.peerConnection.removeEventListener("icegatheringstatechange",this.onicegatheringstatechangeHandler),this.peerConnection.removeEventListener("iceconnectionstatechange",this.oniceconnectionstatechangeHandler),this.peerConnection.removeEventListener("connectionstatechange",this.onconnectionstatechangeHandler),this.peerConnection.removeEventListener("signalingstatechange",this.onsignalingstatechangeHandler),this.peerConnection.removeEventListener("negotiationneeded",this.onnegotiationneededHandler))}stopRemoteTracks(){var t;(t=this._remoteStream$.value)==null||t.getTracks().forEach(e=>{z.debug(`[RTCPeerConnectionController] Stopping remote track: ${e.kind}`),e.stop()})}get mediaDirections(){var t;return((t=this.transceiverController)==null?void 0:t.getMediaDirections())??this._remoteOfferMediaDirections??{audio:"inactive",video:"inactive"}}async _setRemoteDescription(t){if(!this.peerConnection)throw new te("RTCPeerConnection is not initialized");const e=await this.setRemoteDescriptionBefore(t.sdp),i={...t,sdp:e};return z.debug("[RTCPeerConnectionController] Setting remote description:",i),this.peerConnection.setRemoteDescription(i)}};function Ds(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"id")}function kc(t){if(!Ds(t))return!1;const e=t;return e.method==="verto.invite"&&ke(e.params)&&K(e.params,"sdp")&&K(e.params,"callID")}function of(t){return Ds(t)?t.method==="verto.bye":!1}function xc(t){return Ds(t)?t.method==="verto.attach":!1}function cf(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"method")&&t.method==="verto.answer"&&ke(t.params)&&K(t.params,"callID")}function lf(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"method")&&t.method==="verto.media"&&ke(t.params)&&K(t.params,"callID")&&K(t.params,"sdp")}function uf(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"method")&&t.method==="verto.mediaParams"&&ke(t.params)&&K(t.params,"mediaParams")}function df(t){return ke(t)&&K(t,"jsonrpc")&&t.jsonrpc==="2.0"&&K(t,"method")&&t.method==="verto.ping"}function Dc(t){return ke(t)&&K(t,"callID")&&typeof t.callID=="string"}const H=G();function hf(t){return t.isInvite&&!t.reattach&&!t.explicitNodeId?"":t.currentNodeId??""}var pf=class extends se{constructor(t){super(),this.callSession=t}destroy(){this.callSession=void 0,super.destroy()}},gf=class extends pf{constructor(t,e,i,r,n={}){super(t),this.webRtcCallSession=t,this.attachManager=e,this.deviceController=i,this.webRTCApiProvider=r,this._rtcPeerConnections$=this.createBehaviorSubject([]),this._selfId$=this.createBehaviorSubject(null),this._signalingStatus$=this.createReplaySubject(1),this._screenShareStatus$=this.createBehaviorSubject("none"),this._rtcPeerConnectionsMap=new Map,this._screenShareTimeoutMs=5e4,this._nodeId$=this.createBehaviorSubject(n.nodeId??null),this.onError=n.onError,this.onModifyFailed=n.onModifyFailed,this.initSubscriptions(),this.initMainPeerConnection()}async hold(){const t=vn({sessid:this.webRtcCallSession.id,dialogParams:{callID:this.webRtcCallSession.id},action:"hold"});try{await this.executeVerto(t)}catch(e){throw H.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:",e),e}}async unhold(){const t=vn({sessid:this.webRtcCallSession.id,dialogParams:{callID:this.webRtcCallSession.id},action:"unhold"});try{await this.executeVerto(t)}catch(e){throw H.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:",e),e}}get mediaDirections(){return this.mainPeerConnection.mediaDirections}get rtcPeerConnections$(){return this._rtcPeerConnections$.asObservable()}get rtcPeerConnections(){return this._rtcPeerConnections$.value}get nodeId$(){return this._nodeId$.asObservable()}get selfId$(){return this._selfId$.asObservable()}get localStream(){var t;return((t=this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id))==null?void 0:t.localStream)??null}get remoteStream(){var t;return((t=this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id))==null?void 0:t.remoteStream)??null}get nodeId(){return this._nodeId$.value}get screenShareStatus(){return this._screenShareStatus$.value}get screenShareStatus$(){return this._screenShareStatus$.asObservable()}get mainPeerConnection(){const t=this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);if(!t)throw new te("Main peer connection not found");return t}get signalingStatus$(){return this.cachedObservable("signalingStatus$",()=>Ni(this._signalingStatus$.asObservable(),this.mainPeerConnection.connectionState$.pipe(B(t=>["connected","disconnected","failed"].includes(t)))))}initSubscriptions(){this.subscribeTo(this.callJoinedEvent$,t=>{var i;const e=(i=t.room_session.members.find(r=>r.call_id===t.call_id))==null?void 0:i.node_id;e&&this.setNodeIdIfNull(e),t.member_id&&this.setSelfIdIfNull(t.member_id)}),this.subscribeTo(this.vertoMedia$,t=>{var r;H.debug("[WebRTCManager] Received Verto media event (early media SDP):",t);const{sdp:e,callID:i}=t;this.emitMainSignalingStatus(i,"ringing"),(r=this._rtcPeerConnectionsMap.get(i))==null||r.updateAnswerStatus({status:"received",sdp:e})}),this.subscribeTo(this.vertoAnswer$,t=>{var r;H.debug("[WebRTCManager] Received Verto answer event:",t);const{sdp:e,callID:i}=t;this.emitMainSignalingStatus(i,"connecting"),(r=this._rtcPeerConnectionsMap.get(i))==null||r.updateAnswerStatus({status:"received",sdp:e})}),this.subscribeTo(this.vertoMediaParams$,t=>{H.debug("[WebRTCManager] Received Verto mediaParams event:",t);const{mediaParams:e,callID:i}=t,r=this._rtcPeerConnectionsMap.get(i),{audio:n,video:s}=e;(async()=>{var a;try{n&&r&&await r.replaceAudioTrackWithConstraints(n),s&&await(r==null?void 0:r.updateSendersConstraints("video",s)),this.webRtcCallSession.emitMediaParamsUpdated({audio:n,video:s,timestamp:Date.now()})}catch(o){H.warn("[WebRTCManager] Error applying server-pushed media params:",o),(a=this.onError)==null||a.call(this,o instanceof Error?o:new Error(String(o),{cause:o}))}})()}),this.subscribeTo(this.vertoPing$,t=>{this.attachManager.attach(this.buildAttachableCall()),this.sendVertoPong(t)})}setNodeIdIfNull(t){!this._nodeId$.value&&t&&(H.debug(`[WebRTCManager] Early node_id set: ${t}`),this._nodeId$.next(t))}setSelfIdIfNull(t){!this._selfId$.value&&t&&(H.debug(`[WebRTCManager] Early selfId set: ${t}`),this._selfId$.next(t))}async sendVertoPong(t){var e;try{const i=Dg({...t});await this.executeVerto(i)}catch(i){H.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:",i),(e=this.onError)==null||e.call(this,new No(i))}}async updateMediaConstraints(t={}){var r;const{audio:e,video:i}=t;try{e&&await this.mainPeerConnection.updateSendersConstraints("audio",e),i&&await this.mainPeerConnection.updateSendersConstraints("video",i)}catch(n){throw H.warn("[WebRTCManager] Error updating media constraints:",n),(r=this.onError)==null||r.call(this,n instanceof Error?n:new Error(String(n),{cause:n})),n}}get selfId(){return this._selfId$.value}buildAttachableCall(t){return{nodeId:this.nodeId??void 0,id:t??this.webRtcCallSession.id,to:this.webRtcCallSession.to,mediaDirections:this.webRtcCallSession.mediaDirections}}requestKeyframe(){try{const t=this.mainPeerConnection.peerConnection;if(!t){H.warn("[WebRTCManager] No peer connection for keyframe request");return}const e=t.getReceivers().find(i=>i.track.kind==="video");if(!e){H.warn("[WebRTCManager] No video receiver for keyframe request");return}typeof e.requestKeyFrame=="function"?(e.requestKeyFrame(),H.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()")):H.debug("[WebRTCManager] requestKeyFrame() not supported, skipping")}catch(t){H.warn("[WebRTCManager] Keyframe request failed (non-fatal):",t)}}async requestIceRestart(t){try{const e=this.mainPeerConnection;if(!e.peerConnection){H.warn("[WebRTCManager] No peer connection for ICE restart");return}await e.triggerIceRestart(t),H.info(`[WebRTCManager] ICE restart initiated${t?" (relay-only)":""}`)}catch(e){throw H.error("[WebRTCManager] ICE restart failed:",e),e}}async requestIceRestartAll(t){const e=Array.from(this._rtcPeerConnectionsMap.entries());for(const[i,r]of e)try{if(!r.peerConnection){H.debug(`[WebRTCManager] No peer connection for leg ${i}, skipping ICE restart`);continue}await r.triggerIceRestart(t),H.info(`[WebRTCManager] ICE restart initiated for leg ${i}${t?" (relay-only)":""}`)}catch(n){H.warn(`[WebRTCManager] ICE restart failed for leg ${i}:`,n)}}requestKeyframeAll(){for(const[t,e]of this._rtcPeerConnectionsMap){if(e.isScreenShare){H.debug(`[WebRTCManager] Skipping keyframe for send-only screen share leg ${t}`);continue}try{const i=e.peerConnection;if(!i)continue;const r=i.getReceivers().find(n=>n.track.kind==="video");if(!r)continue;typeof r.requestKeyFrame=="function"&&(r.requestKeyFrame(),H.debug(`[WebRTCManager] Keyframe requested for leg ${t}`))}catch(i){H.warn(`[WebRTCManager] Keyframe request failed for leg ${t} (non-fatal):`,i)}}}get callJoinedEvent$(){return this.webRtcCallSession.callEvent$.pipe(B(Sc),S(this.destroyed$))}get vertoMedia$(){return this.webRtcCallSession.webrtcMessages$.pipe(Se(lf,"params"),S(this.destroyed$))}get vertoAnswer$(){return this.cachedObservable("vertoAnswer$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(cf,"params"),S(this.destroyed$)))}get vertoMediaParams$(){return this.cachedObservable("vertoMediaParams$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(uf,"params"),S(this.destroyed$)))}get vertoBye$(){return this.cachedObservable("vertoBye$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(of,"params"),S(this.destroyed$)))}get vertoAttach$(){return this.cachedObservable("vertoAttach$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(xc,"params"),S(this.destroyed$)))}get vertoPing$(){return this.cachedObservable("vertoPing$",()=>this.webRtcCallSession.webrtcMessages$.pipe(Se(df,"params"),S(this.destroyed$)))}async executeVerto(t,e={}){var s,a;const i=sc({callID:e.callID??this.webRtcCallSession.id,node_id:e.node_id??this._nodeId$.value??"",message:t,subscribe:e.subscribe}),r=await this.webRtcCallSession.execute(i);if(r.error){const o=new Et(r.error.code,r.error.message,r.error.data);return(s=this.onError)==null||s.call(this,o),r}const n=at(r,"result.result");if(n!=null&&n.error){const o=new Et(n.error.code,n.error.message,n.error.data);return(a=this.onError)==null||a.call(this,o),r}return r}async sendLocalDescription(t,e){var n,s;const i=t.method,r=this.getSendLocalSDPOptionalParams(e,t);try{const a=await this.executeVerto(t,r);switch(i){case"verto.invite":this.processInviteResponse(a,e);break;case"verto.modify":await this.processModifyResponse(a,e);break;default:}}catch(a){H.error(`[WebRTCManager] Error sending Verto ${i}:`,a),(n=this.onError)==null||n.call(this,a instanceof Error?a:new Error(String(a),{cause:a})),i==="verto.modify"&&((s=this.onModifyFailed)==null||s.call(this))}}async processModifyResponse(t,e){var i;if(!t.error){const r=at(t,"result.result.result.action"),n=at(t,"result.result.result.sdp");if(r==="updateMedia"&&n)try{await e.updateAnswerStatus({status:"received",sdp:n})}catch(s){H.warn("[WebRTCManager] Error processing modify response:",s);const a=s instanceof Error?s:new Error(String(s),{cause:s});(i=this.onError)==null||i.call(this,a)}}}emitMainSignalingStatus(t,e){var r;const i=this._rtcPeerConnectionsMap.get(t);if(!i){const n=new te(`Cannot emit signaling status, RTCPeerConnectionController not found for callID: ${t}`);H.error("[WebRTCManager] Failed to emit signaling status:",{callId:t,status:e,signalingError:n}),(r=this.onError)==null||r.call(this,n);return}i.isMainDevice&&this._signalingStatus$.next(e)}processInviteResponse(t,e){var i;if(!t.error&&at(t,"result.result.result.message")==="CALL CREATED"){this.emitMainSignalingStatus(e.id,"trying"),this._nodeId$.next(at(t,"result.node_id")??null);const r=at(t,"result.result.result.memberID")??null,n=at(t,"result.result.result.callID")??null;H.debug("[WebRTCManager] Verto invite response:",{callId:n,memberId:r,response:t}),this._selfId$.next(r),e.setMemberId(r),n?(this.webRtcCallSession.addCallId(n),this.attachManager.attach(this.buildAttachableCall(n))):H.warn("[WebRTCManager] Cannot attach call, missing callId:",{nodeId:this.nodeId,callId:n}),H.info("[WebRTCManager] Verto invite successful"),H.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`)}else{H.error("[WebRTCManager] Verto invite failed:",t);const r=t.error?new Et(t.error.code,t.error.message,t.error.data):new Error("Verto invite failed: unexpected response");(i=this.onError)==null||i.call(this,r)}}get RTCPeerConnectionConfig(){return{iceServers:this.webRtcCallSession.clientSession.iceServers??f.instance.iceServers,relayOnly:f.instance.relayOnly||f.instance.disableUdpIceServers,disableUdpIceServers:f.instance.disableUdpIceServers,iceCandidateTimeout:f.instance.iceCandidateTimeout,iceGatheringTimeout:f.instance.iceGatheringTimeout}}initMainPeerConnection(){const{options:t}=this.webRtcCallSession,e=new Ec({propose:"main",callId:this.webRtcCallSession.id,audio:t.audio,video:t.video,inputAudioDeviceConstraints:t.inputAudioDeviceConstraints,inputVideoDeviceConstraints:t.inputVideoDeviceConstraints,inputAudioStream:t.inputAudioStream,inputVideoStream:t.inputVideoStream,receiveAudio:t.receiveAudio,receiveVideo:t.receiveVideo,fallbackToReceiveOnly:t.fallbackToReceiveOnly,webRTCApiProvider:this.webRTCApiProvider,preferredVideoCodecs:t.preferredVideoCodecs,preferredAudioCodecs:t.preferredAudioCodecs,stereo:t.stereo,...this.RTCPeerConnectionConfig},t.initOffer,this.deviceController);this.setupLocalDescriptionHandler(e),this.setupVertoByeHandler(),this.setupVertoAttachHandler(),this.initObservables(e),this._rtcPeerConnectionsMap.set(e.id,e),this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values())),this.subscribeTo(e.errors$,i=>{var r;(r=this.onError)==null||r.call(this,i)}),t.initOffer&&this.handleInboundAnswer(e)}async handleInboundAnswer(t){var i,r,n;H.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");const e=await Ze(Cr(this.vertoBye$,this.webRtcCallSession.answered$).pipe(S(this.destroyed$))).catch(()=>null);if(e===null){H.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");return}if(Dc(e))H.info("[WebRTCManager] Inbound call ended by remote before answer."),(i=this.callSession)==null||i.destroy();else if(e){H.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");const s=this.webRtcCallSession.answerMediaOptions;try{await t.acceptInbound(s)}catch(a){H.error("[WebRTCManager] Error creating inbound answer:",a),(n=this.onError)==null||n.call(this,a instanceof Error?a:new Error(String(a),{cause:a}))}}else{H.info("[WebRTCManager] Inbound call rejected by user.");try{await this.bye("USER_BUSY")}finally{this._signalingStatus$.next("disconnected"),(r=this.callSession)==null||r.destroy()}}}setupVertoAttachHandler(){this.subscribeTo(this.vertoAttach$,async t=>{H.debug("[WebRTCManager] Received Verto attach event for existing call:",t);const{callID:e}=t;await this.attachManager.attach({nodeId:this.nodeId??void 0,id:e,to:t.callee_id_number,mediaDirections:{audio:"sendrecv",video:"inactive"}})})}initObservables(t){this.mediaDirections$=t.connectionState$.pipe(B(e=>e==="connected"),x(()=>t.mediaDirections),th(t.mediaDirections),S(this.destroyed$)),this.localStream$=t.localStream$.pipe(ve(),S(this.destroyed$)),this.remoteStream$=t.remoteStream$.pipe(ve(),S(this.destroyed$))}setupLocalDescriptionHandler(t){this.subscribeTo(t.localDescription$.pipe(B(e=>e!==null),S(this.destroyed$)),e=>{const{type:i,sdp:r}=e,n=this.dialogParams(t),s=!t.firstSDPExchangeCompleted;if(i==="answer"){const a=kg({dialogParams:n,sdp:r});this.sendLocalDescriptionOnceAccepted(a,t)}else if(s){const a=Ag({dialogParams:n,sdp:r});this.sendLocalDescription(a,t)}else{const a=vn({dialogParams:n,sdp:r,action:"updateMedia"});this.sendLocalDescription(a,t)}})}setupVertoByeHandler(){this.subscribeTo(this.vertoBye$,()=>{var t;this._signalingStatus$.next("disconnected"),this.attachManager.detach(this.buildAttachableCall()),(t=this.callSession)==null||t.destroy()})}getSendLocalSDPOptionalParams(t,e){let i;return t.firstSDPExchangeCompleted||(i=[],t.isMainDevice?i.push(...f.instance.inviteSubscribeMainDevice):t.isAdditionalDevice?i.push(...f.instance.inviteSubscribeAdditionalDevice):t.isScreenShare&&i.push(...f.instance.inviteSubscribeScreenshare)),{callID:t.id,node_id:hf({isInvite:kc(e),reattach:this.webRtcCallSession.options.reattach===!0,explicitNodeId:this.webRtcCallSession.options.nodeId,currentNodeId:this._nodeId$.value}),subscribe:i}}async sendLocalDescriptionOnceAccepted(t,e){var r,n,s;H.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");const i=await Ze(Cr(this.vertoBye$,this.webRtcCallSession.answered$).pipe(S(this.destroyed$))).catch(()=>null);if(i===null){H.debug("[WebRTCManager] Destroyed while waiting for call acceptance");return}if(Dc(i))H.info("[WebRTCManager] Call ended before answer was sent."),(r=this.callSession)==null||r.destroy();else if(i){H.debug("[WebRTCManager] Call accepted, sending answer");try{this.emitMainSignalingStatus(e.id,"connecting"),await this.sendLocalDescription(t,e),await e.updateAnswerStatus({status:"sent"}),await this.attachManager.attach(this.buildAttachableCall())}catch(a){H.error("[WebRTCManager] Error sending Verto answer:",a),(s=this.onError)==null||s.call(this,a instanceof Error?a:new Error(String(a),{cause:a})),await e.updateAnswerStatus({status:"failed"})}}else{H.info("[WebRTCManager] Call was not accepted, sending verto.bye.");try{await this.bye("USER_BUSY")}finally{this._signalingStatus$.next("disconnected"),(n=this.callSession)==null||n.destroy()}}}dialogParams(t){const e=t.memberId??this._selfId$.value??void 0,i=t.propose==="main"&&!t.firstSDPExchangeCompleted&&this.webRtcCallSession.options.reattach;return{id:t.isMainDevice?this.webRtcCallSession.id:t.id,destinationNumber:this.webRtcCallSession.to??this.webRtcCallSession.from,attach:i,reattaching:i,callerName:this.webRtcCallSession.fromName,callerNumber:this.webRtcCallSession.from,remoteCallerName:this.webRtcCallSession.toName,remoteCallerNumber:this.webRtcCallSession.to,userVariables:{memberCallId:this.webRtcCallSession.id,memberId:e,...this.webRtcCallSession.userVariables},screenShare:t.isScreenShare,additionalDevice:t.isAdditionalDevice,pingSupported:!0,version:ah}}muteMainAudioInputDevice(){return this.mainPeerConnection.stopTrackSender("audio")}muteMainVideoInputDevice(){return this.mainPeerConnection.stopTrackSender("video")}async unmuteMainAudioInputDevice(){return this.mainPeerConnection.restoreTrackSender("audio")}async unmuteMainVideoInputDevice(){return this.mainPeerConnection.restoreTrackSender("video")}ensureLocalAudioPipeline(){return this.mainPeerConnection.ensureLocalAudioPipeline()}get localAudioPipeline(){return this.mainPeerConnection.localAudioPipeline}async addInputDevice(t={audio:!1,video:!0}){return this.initAdditionalPeerConnection("additional-device",t)}async addMainInputDevices(t={audio:!0}){var r;let e;const{mediaDirections:i}=this.mainPeerConnection;if((t.audio??t.inputAudioDeviceConstraints??(t.inputAudioStream&&i.audio.startsWith("send")))&&(e="audio"),(t.video??t.inputVideoDeviceConstraints??(t.inputVideoStream&&!i.video.startsWith("send")))&&(e=e==="audio"?"both":"video"),e)this.mainPeerConnection.updateMediaDevicesOptions(t),await this.mainPeerConnection.restoreTrackSender(e);else{const n=new on("No valid device to be added");throw(r=this.onError)==null||r.call(this,n),n}}async addScreenMedia(t={audio:!1}){await this.initAdditionalPeerConnection("screenshare",t)}async initAdditionalPeerConnection(t,e){const i=t==="screenshare";let r,n=null;try{return i&&this._screenShareStatus$.next("starting"),n=new Ec({...e,...this.RTCPeerConnectionConfig,propose:t,webRTCApiProvider:this.webRTCApiProvider},void 0,this.deviceController),this.setupLocalDescriptionHandler(n),i&&(this._screenShareId=n.id),this._rtcPeerConnectionsMap.set(n.id,n),this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values())),this.subscribeTo(n.errors$,s=>{var a;r??(r=s),(a=this.onError)==null||a.call(this,s,{fatal:!1})}),await Ze(n.connectionState$.pipe(B(s=>s==="connected"),Oe(1),Sr(this._screenShareTimeoutMs),S(this.destroyed$))),i&&this._screenShareStatus$.next("started"),H.info(`[WebRTCManager] Additional peer connection connected (${t}).`),n.id}catch(s){if(H.warn("[WebRTCManager] Error initializing additional peer connection:",s),n&&n.destroy(),i&&this._screenShareStatus$.next("none"),r)throw r instanceof Gt&&r.originalError instanceof Error?r.originalError:r;if(s instanceof wr){H.debug("[WebRTCManager] Additional peer connection aborted before connecting.");return}throw s instanceof Error?s:new Error(String(s),{cause:s})}}async removeInputDevices(t){return this.removeAdditionalPeerConnection(t)}removeMainInputDevice(t={removeAudio:!1,removeVideo:!0}){let e;if(t.removeAudio&&(e="audio"),t.removeVideo&&(e=e==="audio"?"both":"video"),e)return this.mainPeerConnection.stopTrackSender(e,{updateTransceiverDirection:!0})}async removeScreenMedia(){if(["starting","started"].includes(this._screenShareStatus$.value)||H.warn("[WebRTCManager] No active screen share to stop."),!this._screenShareId){H.debug("[WebRTCManager] No screen share peer connection found.");return}this._screenShareStatus$.next("stopping"),await this.removeAdditionalPeerConnection(this._screenShareId),this._screenShareId=void 0,this._screenShareStatus$.next("none")}async removeAdditionalPeerConnection(t){const e=this._rtcPeerConnectionsMap.get(t);try{e&&await this.executeVertoBye(e)}finally{e==null||e.destroy(),this._rtcPeerConnectionsMap.delete(t),this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values()))}}async executeVertoBye(t,e){try{const i=e?{cause:e,causeCode:Ig[e]}:{};await this.executeVerto(Tg({...i,dialogParams:this.dialogParams(t)}))}catch(i){throw H.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:",i),i}}async bye(t){this.attachManager.detach(this.buildAttachableCall());const e=this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);e&&await this.executeVertoBye(e,t)}async sendDigits(t){const e=Eg({sessid:this.webRtcCallSession.id,dialogParams:{callID:this.webRtcCallSession.id},dtmf:t});try{await this.executeVerto(e)}catch(i){throw H.warn("[WebRTCManager] Error sending DTMF digits:",i),i}}async transfer(t){const e=vn({...t,dialogParams:this.dialogParams(this.mainPeerConnection),action:"transfer"});try{H.debug("[WebRTCManager] Transferring call with options:",t),await this.executeVerto(e)}catch(i){throw H.error("[WebRTCManager] Error transferring call:",i),i}}destroy(){this._rtcPeerConnectionsMap.forEach(t=>{t.destroy()}),this._rtcPeerConnectionsMap.clear(),this._rtcPeerConnections$.complete(),super.destroy()}};const Ic=G();var ff=class extends se{constructor(t={}){super(),this._source=null,this._stream=null,this._audioContext=(t.audioContextFactory??(()=>new AudioContext))(),this._analyser=this._audioContext.createAnalyser(),this._analyser.fftSize=2048,this._analyser.smoothingTimeConstant=.3,this._analyserBuffer=new Uint8Array(new ArrayBuffer(this._analyser.fftSize)),this._pollIntervalMs=t.pollIntervalMs??Ro}get level$(){return this.deferEmission(en(this._pollIntervalMs,qa).pipe(x(()=>this.computeLevel())))}setStream(t){if(this._source){try{this._source.disconnect()}catch(e){Ic.debug("[RemoteAudioMeter] source disconnect warning:",e)}this._source=null,this._stream=null}!t||t.getAudioTracks().length===0||(this._stream=new MediaStream(t.getAudioTracks()),this._source=this._audioContext.createMediaStreamSource(this._stream))}destroy(){if(this._source){try{this._source.disconnect()}catch{}this._source=null}this._audioContext.close().catch(t=>{Ic.debug("[RemoteAudioMeter] audio context close warning:",t)}),super.destroy()}computeLevel(){if(!this._source)return 0;this._analyser.getByteTimeDomainData(this._analyserBuffer);let t=0;for(const e of this._analyserBuffer){const i=(e-128)/128;t+=i*i}return Math.sqrt(t/this._analyserBuffer.length)}};const Tr=G(),vf=1e3,bf=10,mf=2e3,yf=3e3,wf=3,Sf=5,Cf=5,Af=10,Tf=4,Ef=30;function kf(t,e){const i=t+e;return i===0?0:t/i*100}function xf(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="inbound-rtp"}function Df(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="candidate-pair"}var If=class extends se{constructor(t,e={}){super(),this.peerConnection=t,this.running=!1,this.lastAudioPacketsReceived=0,this.lastAudioPacketChangeTime=0,this.lastVideoPacketsReceived=0,this.lastVideoPacketChangeTime=0,this.lastRoundTripTime=0,this.lastAvailableOutgoingBitrate=void 0,this._sample$=this.createReplaySubject(1),this._baseline$=this.createBehaviorSubject({rtt:0,jitter:0,ready:!1}),this._networkIssues$=this.createBehaviorSubject([]),this._networkMetrics$=this.createBehaviorSubject([]),this.pollingIntervalMs=e.pollingIntervalMs??vf,this.baselineSampleCount=e.baselineSamples??bf,this.noAudioPacketThresholdMs=e.noAudioPacketThresholdMs??mf,this.noVideoPacketThresholdMs=e.noVideoPacketThresholdMs??yf,this.rttSpikeWarningMultiplier=e.rttSpikeWarningMultiplier??wf,this.rttSpikeCriticalMultiplier=e.rttSpikeCriticalMultiplier??Sf,this.packetLossWarningPercent=e.packetLossWarningPercent??Cf,this.packetLossCriticalPercent=e.packetLossCriticalPercent??Af,this.jitterSpikeMultiplier=e.jitterSpikeMultiplier??Tf,this.historyWindowSeconds=e.historyWindowSeconds??Ef}get networkIssues$(){return this._networkIssues$.asObservable()}get networkIssues(){return[...this._networkIssues$.value]}get isNetworkHealthy$(){return this.cachedObservable("isNetworkHealthy$",()=>this._networkIssues$.pipe(x(t=>t.length===0),U(),S(this.destroyed$)))}get isNetworkHealthy(){return this._networkIssues$.value.length===0}get networkMetrics$(){return this._networkMetrics$.asObservable()}get networkMetrics(){return[...this._networkMetrics$.value]}get criticalIssue$(){return this.cachedObservable("criticalIssue$",()=>this._networkIssues$.pipe(cs(t=>_e(t.filter(e=>e.severity==="critical"))),S(this.destroyed$)))}get sample$(){return this._sample$.asObservable()}start(){if(this.running)return;this.running=!0;const t=Date.now();this.lastAudioPacketChangeTime=t,this.lastVideoPacketChangeTime=t,Tr.debug("[RTCStatsMonitor] Starting stats monitoring"),this.subscribeTo(en(this.pollingIntervalMs).pipe(B(()=>this.running),Je(()=>_e(this.peerConnection.getStats()).pipe(ui(e=>(Tr.warn("[RTCStatsMonitor] Failed to get stats:",e),ci)))),B(()=>this.running),x(e=>this.extractSample(e))),e=>this._sample$.next(e)),this.subscribeTo(this._sample$.pipe(Oe(this.baselineSampleCount),Kd(),x(e=>({rtt:e.reduce((i,r)=>i+r.roundTripTime,0)/e.length,jitter:e.reduce((i,r)=>i+r.audioJitter,0)/e.length,ready:!0}))),e=>{Tr.debug(`[RTCStatsMonitor] Baseline established: rtt=${e.rtt.toFixed(1)}ms, jitter=${e.jitter.toFixed(1)}ms`),this._baseline$.next(e)}),this.subscribeTo(this._sample$.pipe(mo((e,i)=>({prev:e.current,current:i}),{prev:null,current:null}),B(e=>e.current!==null)),({prev:e,current:i})=>{const r=i.timestamp;this.updatePacketTracking(i,r);const n=this.detectIssues(i,e,r);this._networkIssues$.next(n)}),this.subscribeTo(this._sample$.pipe(mo((e,i)=>{const r=i.timestamp-this.historyWindowSeconds*1e3,n={timestamp:i.timestamp,audio:{packetsReceived:i.audioPacketsReceived,packetsLost:i.audioPacketsLost,jitter:i.audioJitter},video:{packetsReceived:i.videoPacketsReceived,packetsLost:i.videoPacketsLost},roundTripTime:i.roundTripTime,availableOutgoingBitrate:i.availableOutgoingBitrate};return[...e.filter(s=>s.timestamp>r),n]},[])),e=>this._networkMetrics$.next(e))}stop(){this.running&&(this.running=!1,Tr.debug("[RTCStatsMonitor] Stopping stats monitoring"))}destroy(){Tr.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor"),this.stop(),super.destroy()}extractSample(t){let e=0,i=0,r=0,n=0,s=0,a=0,o;return t.forEach(c=>{xf(c)&&(c.kind==="audio"?(e+=c.packetsReceived??0,i+=c.packetsLost??0,r=Math.max(r,(c.jitter??0)*1e3)):(n+=c.packetsReceived??0,s+=c.packetsLost??0)),Df(c)&&c.state==="succeeded"&&c.nominated&&(a=c.currentRoundTripTime?c.currentRoundTripTime*1e3:this.lastRoundTripTime,o=c.availableOutgoingBitrate??this.lastAvailableOutgoingBitrate)}),{audioPacketsReceived:e,audioPacketsLost:i,audioJitter:r,videoPacketsReceived:n,videoPacketsLost:s,roundTripTime:a,availableOutgoingBitrate:o,timestamp:Date.now()}}updatePacketTracking(t,e){t.audioPacketsReceived!==this.lastAudioPacketsReceived&&(this.lastAudioPacketsReceived=t.audioPacketsReceived,this.lastAudioPacketChangeTime=e),t.videoPacketsReceived!==this.lastVideoPacketsReceived&&(this.lastVideoPacketsReceived=t.videoPacketsReceived,this.lastVideoPacketChangeTime=e),t.roundTripTime>0&&(this.lastRoundTripTime=t.roundTripTime),t.availableOutgoingBitrate!==void 0&&(this.lastAvailableOutgoingBitrate=t.availableOutgoingBitrate)}detectIssues(t,e,i){const r=[],n=this._baseline$.value,s=i-this.lastAudioPacketChangeTime;s>this.noAudioPacketThresholdMs&&r.push({type:"no_inbound_audio",severity:"critical",timestamp:i,value:s,threshold:this.noAudioPacketThresholdMs});const a=i-this.lastVideoPacketChangeTime;if(a>this.noVideoPacketThresholdMs&&r.push({type:"no_inbound_video",severity:"warning",timestamp:i,value:a,threshold:this.noVideoPacketThresholdMs}),n.ready){const o=t.roundTripTime,c=n.rtt;if(c>0){const p=o/c;p>this.rttSpikeCriticalMultiplier?r.push({type:"high_rtt",severity:"critical",timestamp:i,value:o,threshold:c*this.rttSpikeCriticalMultiplier}):p>this.rttSpikeWarningMultiplier&&r.push({type:"high_rtt",severity:"warning",timestamp:i,value:o,threshold:c*this.rttSpikeWarningMultiplier})}const u=t.audioJitter,h=n.jitter;h>0&&u/h>this.jitterSpikeMultiplier&&r.push({type:"high_jitter",severity:"warning",timestamp:i,value:u,threshold:h*this.jitterSpikeMultiplier})}if(e){const o=Math.max(0,t.audioPacketsReceived-e.audioPacketsReceived),c=Math.max(0,t.audioPacketsLost-e.audioPacketsLost),u=Math.max(0,t.videoPacketsReceived-e.videoPacketsReceived),h=Math.max(0,t.videoPacketsLost-e.videoPacketsLost),p=o+u,v=kf(c+h,p);v>this.packetLossCriticalPercent?r.push({type:"high_packet_loss",severity:"critical",timestamp:i,value:v,threshold:this.packetLossCriticalPercent}):v>this.packetLossWarningPercent&&r.push({type:"high_packet_loss",severity:"warning",timestamp:i,value:v,threshold:this.packetLossWarningPercent})}return r}};const de=G(),Mf=2e3,Rf=1e4,Pf=3e3,_f=5e3,Of=3,Lf=3,Ff=3e3,Nf=1e4,Uf=150,Bf=300,zf=5,Vf=new Set(["high_rtt","high_jitter","high_packet_loss"]);var Hf=class extends se{constructor(t,e,i={}){super(),this._recoveryState$=this.createBehaviorSubject("idle"),this._recoveryEvent$=this.createSubject(),this._bandwidthConstrained$=this.createBehaviorSubject(!1),this._hasPacketLoss$=this.createBehaviorSubject(!1),this._trigger$=this.createSubject(),this._attemptCount=0,this._keyframeBurstCount=0,this._keyframeBurstStart=0,this._keyframeCooldownUntil=0,this._cooldownUntil=0,this._pipelineStop$=this.createSubject(),this._callbacks=t,this._inputs=e,this._config={debounceTimeMs:i.debounceTimeMs??Mf,cooldownMs:i.cooldownMs??Rf,iceGracePeriodMs:i.iceGracePeriodMs??Pf,iceRestartTimeoutMs:i.iceRestartTimeoutMs??_f,maxAttempts:i.maxAttempts??Of,enableRelayFallback:i.enableRelayFallback??!0,keyframeMaxBurst:i.keyframeMaxBurst??Lf,keyframeBurstWindowMs:i.keyframeBurstWindowMs??Ff,keyframeCooldownMs:i.keyframeCooldownMs??Nf,degradationBitrateThreshold:i.degradationBitrateThreshold??Uf,degradationRecoveryThreshold:i.degradationRecoveryThreshold??Bf,enableAutoDegradation:i.enableAutoDegradation??!0,packetLossRecoveryDelaySec:i.packetLossRecoveryDelaySec??zf},this.initPipeline(),this.initDegradationRecoveryPipeline()}get recoveryState$(){return this._recoveryState$.asObservable().pipe(S(this._destroyed$))}get recoveryState(){return this._recoveryState$.value}get recoveryEvent$(){return this._recoveryEvent$.asObservable().pipe(S(this._destroyed$))}get bandwidthConstrained$(){return this._bandwidthConstrained$.asObservable().pipe(S(this._destroyed$))}get bandwidthConstrained(){return this._bandwidthConstrained$.value}pushTrigger(t){this._trigger$.next(t)}async requestIceRestart(){if(this._recoveryState$.value==="recovering"){de.info("CallRecoveryManager: manual ICE restart skipped — recovery already in progress");return}de.info("CallRecoveryManager: manual ICE restart requested"),this.transitionTo("recovering"),await this.executeIceRestart(!1),this.startCooldown()}requestKeyframe(){this.executeKeyframe("manual request")}reset(){de.info("CallRecoveryManager: resetting counters"),this._attemptCount=0,this._keyframeBurstCount=0,this._keyframeBurstStart=0,this._keyframeCooldownUntil=0,this._cooldownUntil=0,this.transitionTo("idle")}notifyModifyFailed(){(this._recoveryState$.value==="cooldown"||this._recoveryState$.value==="idle")&&(de.info("CallRecoveryManager: verto.modify failed — re-entering recovery"),this._cooldownUntil=0,this.transitionTo("idle"),this.pushTrigger({source:"network",detail:"modify_failed_during_recovery"}))}reportBandwidth(t){if(!this._config.enableAutoDegradation)return;const e=this._bandwidthConstrained$.value;!e&&t<this._config.degradationBitrateThreshold?(this._bandwidthConstrained$.next(!0),this._callbacks.disableVideo(),this.emitEvent({action:"video_disabled",reason:`bandwidth ${t}kbps below threshold ${this._config.degradationBitrateThreshold}kbps`,timestamp:Date.now()}),de.warn(`CallRecoveryManager: disabling video — bandwidth ${t}kbps < ${this._config.degradationBitrateThreshold}kbps`)):e&&t>=this._config.degradationRecoveryThreshold&&(this._bandwidthConstrained$.next(!1),this._callbacks.enableVideo(),this.emitEvent({action:"video_restored",reason:`bandwidth ${t}kbps recovered above ${this._config.degradationRecoveryThreshold}kbps`,timestamp:Date.now()}),de.info(`CallRecoveryManager: restoring video — bandwidth ${t}kbps >= ${this._config.degradationRecoveryThreshold}kbps`))}reportNetworkIssues(t){const e=t.some(i=>i.type==="high_packet_loss");e!==this._hasPacketLoss$.value&&this._hasPacketLoss$.next(e)}handleWebSocketReconnect(){const t=this._callbacks.getPeerConnectionState();t==="connected"||t==="completed"?(de.info("CallRecoveryManager: signal-only reconnect — peer connection still alive"),this.emitEvent({action:"signal_reconnect",reason:"WebSocket reconnected, peer connection still connected",timestamp:Date.now()})):(de.info("CallRecoveryManager: full reconnect — peer connection also down"),this.emitEvent({action:"full_reconnect",reason:"WebSocket reconnected, peer connection not connected — ICE restart needed",timestamp:Date.now()}),this.pushTrigger({source:"network",detail:"full_reconnect_after_ws"})),this.reset()}destroy(){this._pipelineStop$.next(),this._pipelineStop$.complete(),super.destroy()}initPipeline(){this.subscribeTo(this._trigger$.pipe(Ee(()=>{this._recoveryState$.value==="idle"&&this.transitionTo("debouncing")}),vo(this._config.debounceTimeMs),yo(this._inputs.signalingReady$),B(([,t])=>this.passGateChecks(t)),x(([t])=>t),ls(t=>this.executeTieredRecovery(t)),S(Ni(this._destroyed$,this._pipelineStop$))),{next:()=>{},error:t=>{de.error("CallRecoveryManager: pipeline error",t),this.transitionTo("idle")}})}initDegradationRecoveryPipeline(){if(!this._config.enableAutoDegradation)return;const t=this._config.packetLossRecoveryDelaySec*1e3;this.subscribeTo(uo([this._bandwidthConstrained$,this._hasPacketLoss$]).pipe(Je(([e,i])=>e&&!i?Fi(t):ci),S(this._destroyed$)),()=>{this._bandwidthConstrained$.next(!1),this._callbacks.enableVideo(),this.emitEvent({action:"video_restored",reason:`no packet loss for ${this._config.packetLossRecoveryDelaySec}s — restoring video`,timestamp:Date.now()}),de.info(`CallRecoveryManager: restoring video — no packet loss for ${this._config.packetLossRecoveryDelaySec}s`)})}passGateChecks(t){return this._callbacks.isNegotiating()?(de.debug("CallRecoveryManager: gate blocked — negotiation in progress"),this.transitionTo("idle"),!1):t?this._callbacks.isCallConnected()?this.isCooldownActive()?(de.debug("CallRecoveryManager: gate blocked — cooldown active"),this.transitionTo("cooldown"),!1):!0:(de.debug("CallRecoveryManager: gate blocked — call not connected"),this.transitionTo("idle"),!1):(de.debug("CallRecoveryManager: gate blocked — signaling not ready"),this.transitionTo("idle"),!1)}isCooldownActive(){return Date.now()<this._cooldownUntil}executeTieredRecovery(t){return this.transitionTo("recovering"),de.info(`CallRecoveryManager: starting tiered recovery — source=${t.source} detail=${t.detail}`),_e(this.runTiers(t)).pipe(Ee(()=>this.startCooldown()),ui(e=>(de.error("CallRecoveryManager: tiered recovery failed",e),this.startCooldown(),ci)))}async runTiers(t){if(this.executeKeyframe(t.detail),t.issueType&&Vf.has(t.issueType)){de.debug(`CallRecoveryManager: degradation-only issue (${t.issueType}) — Tier 1 only, skipping ICE restart`);return}this._attemptCount<this._config.maxAttempts&&await this.executeIceRestart(!1)||this._config.enableRelayFallback&&this._attemptCount<this._config.maxAttempts&&await this.executeIceRestart(!0)||this._attemptCount>=this._config.maxAttempts&&(this.emitEvent({action:"max_attempts_reached",reason:`all ${this._config.maxAttempts} recovery attempts exhausted`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()}),de.warn("CallRecoveryManager: max recovery attempts reached"))}executeKeyframe(t){const e=Date.now();if(e<this._keyframeCooldownUntil){de.debug("CallRecoveryManager: keyframe request skipped — cooldown active");return}if(e-this._keyframeBurstStart>this._config.keyframeBurstWindowMs&&(this._keyframeBurstCount=0,this._keyframeBurstStart=e),this._keyframeBurstCount>=this._config.keyframeMaxBurst){this._keyframeCooldownUntil=e+this._config.keyframeCooldownMs,de.debug(`CallRecoveryManager: keyframe burst limit reached (${this._config.keyframeMaxBurst}), cooldown until ${this._keyframeCooldownUntil}`);return}this._keyframeBurstCount+=1,this._callbacks.requestKeyframe(),this.emitEvent({action:"keyframe_requested",reason:t,timestamp:e}),de.debug(`CallRecoveryManager: keyframe requested (burst ${this._keyframeBurstCount}/${this._config.keyframeMaxBurst})`)}async executeIceRestart(t){this._attemptCount+=1;const e=t?"Tier 3 (relay-only)":"Tier 2 (standard)";de.info(`CallRecoveryManager: ${e} ICE restart — attempt ${this._attemptCount}/${this._config.maxAttempts}`),this.emitEvent({action:"reinvite_started",reason:`${e} ICE restart`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()});try{return await this.withTimeout(this._callbacks.requestIceRestart(t),this._config.iceRestartTimeoutMs)?(this.emitEvent({action:"reinvite_succeeded",reason:`${e} ICE restart succeeded`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()}),de.info(`CallRecoveryManager: ${e} ICE restart succeeded`),this._attemptCount=0,!0):(this.emitEvent({action:"reinvite_failed",reason:`${e} ICE restart returned false`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()}),de.warn(`CallRecoveryManager: ${e} ICE restart failed`),!1)}catch{return this.emitEvent({action:"reinvite_timeout",reason:`${e} ICE restart timed out after ${this._config.iceRestartTimeoutMs}ms`,attempt:this._attemptCount,maxAttempts:this._config.maxAttempts,timestamp:Date.now()}),de.warn(`CallRecoveryManager: ${e} ICE restart timed out`),!1}}async withTimeout(t,e){return new Promise((i,r)=>{const n=setTimeout(()=>{r(new Error(`Timeout after ${e}ms`))},e);t.then(s=>{clearTimeout(n),i(s)},s=>{clearTimeout(n),r(s instanceof Error?s:new Error(String(s)))})})}transitionTo(t){const e=this._recoveryState$.value;e!==t&&(de.debug(`CallRecoveryManager: state ${e} -> ${t}`),this._recoveryState$.next(t))}startCooldown(){this._cooldownUntil=Date.now()+this._config.cooldownMs,this.transitionTo("cooldown"),this._cooldownSubscription&&this._cooldownSubscription.unsubscribe(),this._cooldownSubscription=Fi(this._config.cooldownMs).pipe(Oe(1),S(this._destroyed$),B(()=>this._recoveryState$.value==="cooldown")).subscribe(()=>this.transitionTo("idle"))}emitEvent(t){this._recoveryEvent$.next(t)}},jf=class{constructor(t,e,i){this.executeMethod=t,this.vertoManager=e,this.deviceController=i}createSelfParticipant(t){return new uc(t,this.executeMethod,this.vertoManager,this.deviceController)}createParticipant(t){return new lc(t,this.executeMethod,this.deviceController)}};const Wf=93.2,Gf=.024,qf=2.5,Xf=0,Yf=100,Kf=1,Zf=5,Qf=4,Jf=3.5,$f=3,ev=2;function tv(t,e,i){const r=Wf-(t/2+e)*Gf-i*qf,n=Math.min(Yf,Math.max(Xf,r)),s=1+.035*n+n*(n-60)*(100-n)*7e-6;return Math.min(Zf,Math.max(Kf,s))}function iv(t){return t>=Qf?"excellent":t>=Jf?"good":t>=$f?"fair":t>=ev?"poor":"critical"}const Ce=G(),rv=5/3,nv=t=>{if(!t)return{};try{const e=new URL(`destination:${t}`),i={};return e.searchParams.forEach((r,n)=>{i[n]=r}),i}catch(e){return Ce.warn(`Failed to parse destination URI: ${t}`,e),{}}};var sv=class extends se{constructor(t,e,i,r){super(),this.clientSession=t,this.options=e,this.address=r,this._errors$=this.createReplaySubject(1),this._lastMergedStatus="new",this._answered$=this.createReplaySubject(),this._holdState=!1,this._userVariables$=this.createBehaviorSubject({...f.instance.userVariables}),this._networkIssues$=this.createBehaviorSubject([]),this._networkMetrics$=this.createBehaviorSubject([]),this._isNetworkHealthy$=this.createBehaviorSubject(!0),this._qualityScore$=this.createBehaviorSubject(5),this._qualityLevel$=this.createBehaviorSubject("excellent"),this._recoveryState$=this.createBehaviorSubject("idle"),this._recoveryEvent$=this.createSubject(),this._bandwidthConstrained$=this.createBehaviorSubject(!1),this._mediaParamsUpdated$=this.createSubject(),this._customSubscriptions=new Map,this._pushToTalkEnabled=!1,this._remoteAudioMeter=null,this.id=e.callId??dn(),this.to=e.to,this._userVariables$.next({...this._userVariables$.value,...nv(e.to),...e.userVariables}),this.subscribeTo(this.webrtcMessages$,o=>{const c=at(o,"params.userVariables");c&&this._userVariables$.next({...this._userVariables$.value,...c})});const n=i.initializeManagers(this);this.vertoManager=n.vertoManager,this.callEventsManager=n.callEventsManager,e.initOffer?(this._status$=this.createBehaviorSubject("ringing"),this._lastMergedStatus="ringing"):this._status$=this.createBehaviorSubject("new");const{deviceController:s,networkChange$:a}=i;this._networkChange$=a,this.participantFactory=new jf(this.executeMethod.bind(this),this.vertoManager,s),this.subscribeTo(Ni(this._status$.asObservable(),this.vertoManager.signalingStatus$).pipe(U(),S(this._destroyed$)),o=>{var c;this._lastMergedStatus=o,o==="connected"&&!this._statsMonitor?this.initResilienceSubsystems():o==="disconnected"?((c=this._statsMonitor)==null||c.destroy(),this._statsMonitor=void 0):(o==="destroyed"||o==="failed")&&this.stopResilienceSubsystems()})}get errors$(){return this.deferEmission(this._errors$.asObservable())}emitError(t){this._status$.value==="destroyed"||this._status$.value==="failed"||(this._errors$.next(t),t.fatal&&(this._status$.next("failed"),this.destroy()))}notifyModifyFailed(){var t;(t=this._recoveryManager)==null||t.notifyModifyFailed()}get direction(){return this.options.initOffer?"inbound":"outbound"}get address$(){return this.deferEmission(_e([this.address])).pipe(S(this._destroyed$))}get fromName(){return this.options.fromName}get from(){return this.options.from}get toName(){return this.options.toName}async toggleIncomingVideo(){throw new Tt}async toggleIncomingAudio(){throw new Tt}addCallId(t){this.callEventsManager.addCallId(t)}get capabilities(){return this.callEventsManager.capabilities}get participants(){return this.callEventsManager.participants}get self(){return this.callEventsManager.self}async toggleLock(){const t=this.locked?"call.unlock":"call.lock";await this.executeMethod(this.callSelf,t,{})}async toggleHold(){this._holdState?await this.vertoManager.unhold():await this.vertoManager.hold(),this._holdState=!this._holdState}async startRecording(){throw new Tt}async startStreaming(){throw new Tt}async setMeta(t){throw new Tt}async updateMeta(t){throw new Tt}get layoutLayers$(){return this.deferEmission(this.callEventsManager.layoutLayers$).pipe(S(this._destroyed$))}get layoutLayers(){return this.callEventsManager.layoutLayers}async executeMethod(t,e,i){var a,o,c;const r=this.callSelf;if(typeof t=="string"&&t!==r.member_id)throw new on(`Target member ID ${t} does not match call's self member ID ${r.member_id}`);const n={...i,self:r,target:typeof t=="string"?r:t},s=Hi({method:e,params:n});try{const u=await this.clientSession.execute(s);if(Ng(u))throw new Et(parseInt(((a=u.result)==null?void 0:a.code)??"0"),`Error response from method ${e}: ${(o=u.result)==null?void 0:o.code} ${(c=u.result)==null?void 0:c.message}`,void 0,void 0,s.id);return u}catch(u){throw Ce.error(`[Call] Error executing method ${e} with params`,n,u),u}}get callSelf(){const t=this.nodeId,e=this.vertoManager.selfId;if(!t||!e)throw new up(this.id);return{node_id:t,call_id:this.id,member_id:e}}get status$(){return this.publicCachedObservable("status$",()=>Ni(this._status$.asObservable(),this.vertoManager.signalingStatus$).pipe(U(),Ee(t=>{this._lastMergedStatus=t})))}get participants$(){return this.deferEmission(this.callEventsManager.participants$).pipe(S(this._destroyed$))}get self$(){return this.deferEmission(this.callEventsManager.self$).pipe(S(this._destroyed$))}get recording$(){return this.deferEmission(this.callEventsManager.recording$).pipe(S(this._destroyed$))}get streaming$(){return this.deferEmission(this.callEventsManager.streaming$).pipe(S(this._destroyed$))}get raiseHandPriority$(){return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe(S(this._destroyed$))}get locked$(){return this.deferEmission(this.callEventsManager.locked$).pipe(S(this._destroyed$))}get meta$(){return this.deferEmission(this.callEventsManager.meta$).pipe(S(this._destroyed$))}get capabilities$(){return this.deferEmission(this.callEventsManager.capabilities$).pipe(S(this._destroyed$))}get layout$(){return this.deferEmission(this.callEventsManager.layout$).pipe(S(this._destroyed$))}get status(){return this._lastMergedStatus}get recording(){return this.callEventsManager.recording}get streaming(){return this.callEventsManager.streaming}get raiseHandPriority(){return this.callEventsManager.raiseHandPriority}get locked(){return this.callEventsManager.locked}get meta(){return this.callEventsManager.meta}get layout(){return this.callEventsManager.layout}get layouts$(){return this.deferEmission(this.callEventsManager.layouts$).pipe(S(this._destroyed$))}get layouts(){return this.callEventsManager.layouts}get localStream$(){return this.deferEmission(this.vertoManager.localStream$).pipe(S(this._destroyed$))}get localStream(){return this.vertoManager.localStream}get remoteStream$(){return this.deferEmission(this.vertoManager.remoteStream$).pipe(S(this._destroyed$))}get remoteStream(){return this.vertoManager.remoteStream}get userVariables$(){return this.deferEmission(this._userVariables$.asObservable())}get userVariables(){return{...this._userVariables$.value}}set userVariables(t){this._userVariables$.next({...this._userVariables$.value,...t})}get networkIssues$(){return this.deferEmission(this._networkIssues$.asObservable())}get networkIssues(){return this._networkIssues$.value}get isNetworkHealthy$(){return this.deferEmission(this._isNetworkHealthy$.asObservable())}get isNetworkHealthy(){return this._isNetworkHealthy$.value}get networkMetrics$(){return this.deferEmission(this._networkMetrics$.asObservable())}get networkMetrics(){return this._networkMetrics$.value}get qualityScore$(){return this.deferEmission(this._qualityScore$.asObservable())}get qualityLevel$(){return this.deferEmission(this._qualityLevel$.asObservable())}get recoveryState$(){return this.deferEmission(this._recoveryState$.asObservable())}get recoveryEvent$(){return this.deferEmission(this._recoveryEvent$.asObservable())}get bandwidthConstrained$(){return this.deferEmission(this._bandwidthConstrained$.asObservable())}get mediaParamsUpdated$(){return this.deferEmission(this._mediaParamsUpdated$.asObservable())}emitMediaParamsUpdated(t){this._mediaParamsUpdated$.next(t)}requestKeyframe(){var t,e;(e=(t=this.vertoManager).requestKeyframe)==null||e.call(t)}async requestIceRestart(){var t,e;await((e=(t=this.vertoManager).requestIceRestart)==null?void 0:e.call(t))}initResilienceSubsystems(){const t=this.rtcPeerConnection;if(Ce.debug(`[Call] initResilienceSubsystems: pc=${t?"exists":"undefined"}, connectionState=${t==null?void 0:t.connectionState}`),!t){Ce.warn("[Call] No peer connection available, skipping resilience init");return}try{const e=f.instance;this._statsMonitor=new If(t,{pollingIntervalMs:e.statsPollingInterval,baselineSamples:e.statsBaselineSamples,noAudioPacketThresholdMs:e.statsNoPacketThreshold,rttSpikeWarningMultiplier:e.statsRttSpikeMultiplier,rttSpikeCriticalMultiplier:e.statsRttSpikeMultiplier*rv,packetLossWarningPercent:e.statsPacketLossThreshold*100,packetLossCriticalPercent:e.statsPacketLossThreshold*200,jitterSpikeMultiplier:e.statsJitterSpikeMultiplier,historyWindowSeconds:e.statsHistorySize}),this._recoveryManager=new Hf({requestKeyframe:()=>{var i,r;try{this.vertoManager.requestKeyframeAll?this.vertoManager.requestKeyframeAll():(r=(i=this.vertoManager).requestKeyframe)==null||r.call(i)}catch{}},requestIceRestart:async i=>{var r,n;try{this.vertoManager.requestIceRestartAll?await this.vertoManager.requestIceRestartAll(i):await((n=(r=this.vertoManager).requestIceRestart)==null?void 0:n.call(r,i))}catch{return!1}return this.waitForPeerConnectionConnected()},disableVideo:()=>{try{this.vertoManager.muteMainVideoInputDevice(),Ce.debug("[Call] Recovery manager disabled video")}catch{Ce.debug("[Call] Recovery manager failed to disable video")}},enableVideo:()=>{this.vertoManager.unmuteMainVideoInputDevice().catch(()=>{Ce.debug("[Call] Recovery manager failed to enable video")})},isNegotiating:()=>this.vertoManager.mainPeerConnection.isNegotiating,isCallConnected:()=>this._lastMergedStatus==="connected",getPeerConnectionState:()=>t.connectionState},{signalingReady$:this.clientSession.authenticated$},{debounceTimeMs:e.recoveryDebounceTime,cooldownMs:e.recoveryCooldown,iceGracePeriodMs:e.iceDisconnectedGracePeriod,iceRestartTimeoutMs:e.iceRestartTimeout,maxAttempts:e.maxRecoveryAttempts,enableRelayFallback:e.enableRelayFallback,keyframeMaxBurst:e.keyframeMaxBurst,keyframeBurstWindowMs:e.keyframeBurstWindow,keyframeCooldownMs:e.keyframeCooldown}),this.subscribeTo(this._statsMonitor.networkIssues$,i=>{var r;this._networkIssues$.next(i),(r=this._recoveryManager)==null||r.reportNetworkIssues(i)}),this.subscribeTo(this._statsMonitor.isNetworkHealthy$,i=>{this._isNetworkHealthy$.next(i)}),this.subscribeTo(this._statsMonitor.networkMetrics$,i=>{var r;if(this._networkMetrics$.next(i),i.length>0){const n=i[i.length-1],s=n.audio.packetsReceived+n.video.packetsReceived,a=n.audio.packetsLost+n.video.packetsLost,o=s+a>0?a/(s+a)*100:0,c=tv(n.roundTripTime,n.audio.jitter,o);this._qualityScore$.next(c),this._qualityLevel$.next(iv(c)),n.availableOutgoingBitrate!==void 0&&((r=this._recoveryManager)==null||r.reportBandwidth(n.availableOutgoingBitrate/1e3))}}),this.subscribeTo(this._statsMonitor.criticalIssue$,i=>{var r;(r=this._recoveryManager)==null||r.pushTrigger({source:"stats",detail:`${i.type}: ${i.severity}`,issueType:i.type})}),this.subscribeTo(this._recoveryManager.recoveryState$,i=>{this._recoveryState$.next(i)}),this.subscribeTo(this._recoveryManager.recoveryEvent$,i=>{this._recoveryEvent$.next(i),i.action==="max_attempts_reached"&&(Ce.warn("[Call] All recovery attempts exhausted, terminating call"),this.emitError({kind:"network",fatal:!0,error:new Error("Call recovery failed: all attempts exhausted"),callId:this.id}))}),this.subscribeTo(this._recoveryManager.bandwidthConstrained$,i=>{this._bandwidthConstrained$.next(i)}),this._networkChange$&&this.subscribeTo(this._networkChange$,i=>{var r,n;i.type==="offline"?(r=this._recoveryManager)==null||r.pushTrigger({source:"network",detail:"browser went offline"}):i.type==="online"&&((n=this._recoveryManager)==null||n.handleWebSocketReconnect())}),this.subscribeTo(this.clientSession.authenticated$.pipe(tn(1),B(Boolean)),()=>{var i;Ce.debug("[Call] WebSocket reconnected — notifying recovery manager"),(i=this._recoveryManager)==null||i.handleWebSocketReconnect()}),this._statsMonitor.start(),Ce.debug("[Call] Resilience subsystems initialized for call",this.id)}catch(e){Ce.warn("[Call] Failed to initialize resilience subsystems:",e)}}async waitForPeerConnectionConnected(){const t=this.rtcPeerConnection;if(!t)return!1;const e=Date.now()+Bh;for(;;){const i=t.connectionState;if(i==="connected")return!0;if(i==="failed"||i==="closed"||Date.now()>=e)return!1;await new Promise(r=>setTimeout(r,zh))}}stopResilienceSubsystems(){var t,e;try{(t=this._statsMonitor)==null||t.destroy(),(e=this._recoveryManager)==null||e.destroy()}catch{}this._statsMonitor=void 0,this._recoveryManager=void 0}createParticipant(t,e){return t===(e??this.vertoManager.selfId)?this.participantFactory.createSelfParticipant(t):this.participantFactory.createParticipant(t)}get mediaDirections$(){return this.deferEmission(this.vertoManager.mediaDirections$).pipe(S(this._destroyed$))}get mediaDirections(){return this.vertoManager.mediaDirections}get participantsId$(){return this.cachedObservable("participantsId$",()=>this.participants$.pipe(x(t=>t.map(e=>e.id))))}async execute(t,e){return this.clientSession.execute(t,e)}get selfId$(){return this.vertoManager.selfId$}get selfId(){return this.vertoManager.selfId}get nodeId$(){return this.vertoManager.nodeId$}get nodeId(){return this.vertoManager.nodeId}isCallSessionEvent(t){try{Ce.debug("[Call] Checking if event is for this call session:",t);const e=at(t,"params.params.callID")??at(t,"params.call_id"),i=at(t,"params.room_session_id");return Ce.debug(`[Call] Extracted session identifiers callID: ${e} and roomSessionID: ${i} from event:`),e===this.id||!!e&&this.callEventsManager.isCallIdValid(e)||!!i&&this.callEventsManager.isRoomSessionIdValid(i)}catch(e){return Ce.error("[Call] Error checking if event is for this call session:",e),!1}}get callSessionEvents$(){return this.cachedObservable("callSessionEvents$",()=>this.clientSession.signalingEvent$.pipe(B(t=>this.isCallSessionEvent(t)),Ee(t=>{Ce.debug("[Call] Received call session event:",t)}),S(this.destroyed$),At()))}get callUpdated$(){return this.publicCachedObservable("callUpdated$",()=>this.callSessionEvents$.pipe(Se(pc,"params"),S(this.destroyed$)))}get memberJoined$(){return this.publicCachedObservable("memberJoined$",()=>this.callSessionEvents$.pipe(Se(vc,"params"),S(this.destroyed$)))}get memberLeft$(){return this.publicCachedObservable("memberLeft$",()=>this.callSessionEvents$.pipe(Se(bc,"params"),S(this.destroyed$)))}get memberUpdated$(){return this.publicCachedObservable("memberUpdated$",()=>this.callSessionEvents$.pipe(Se(fc,"params"),S(this.destroyed$)))}get memberTalking$(){return this.publicCachedObservable("memberTalking$",()=>this.callSessionEvents$.pipe(Se(mc,"params"),S(this.destroyed$)))}get callStates$(){return this.publicCachedObservable("callStates$",()=>this.callSessionEvents$.pipe(Se(gc,"params"),S(this.destroyed$)))}get layoutUpdates$(){return this.publicCachedObservable("layoutUpdates$",()=>this.callSessionEvents$.pipe(Se(ks,"params"),S(this.destroyed$)))}get rtcPeerConnection(){return this.vertoManager.mainPeerConnection.peerConnection}get signalingEvent$(){return this.publicCachedObservable("signalingEvent$",()=>this.callEvent$.pipe(x(t=>JSON.parse(JSON.stringify(t)))))}subscribe(t){const e=this._customSubscriptions.get(t);if(e)return e;const i=this.callSessionEvents$.pipe(B(r=>r.event_type===t),x(r=>JSON.parse(JSON.stringify(r))),S(this._destroyed$));return this._sendVertoSubscribe(t).then(()=>{this._customSubscriptions.set(t,i)},r=>{this._customSubscriptions.delete(t),Ce.warn(`[Call] verto.subscribe for '${t}' failed, not caching:`,r)}),this._customSubscriptions.set(t,i),i}get webrtcMessages$(){return this.cachedObservable("webrtcMessages$",()=>this.callSessionEvents$.pipe(Se(bn,"params"),Ee(t=>Ce.debug("[Call] Event is a WebRTC message event:",t)),S(this.destroyed$),At()))}get callEvent$(){return this.cachedObservable("callEvent$",()=>this.callSessionEvents$.pipe(Se(Ug,"params"),Ee(t=>Ce.debug("[Call] Event is a call event:",t)),S(this.destroyed$),At()))}get layoutEvent$(){return this.cachedObservable("layoutEvent$",()=>this.callEvent$.pipe(Se(ks,"params")))}async hangup(){this._status$.next("disconnecting");try{await this.vertoManager.bye()}finally{this.destroy()}}async sendDigits(t){return this.vertoManager.sendDigits(t)}answer(t){this._answerMediaOptions=t,this._answered$.next(!0)}get answerMediaOptions(){return this._answerMediaOptions}reject(){this._answered$.next(!1)}get answered$(){return this.deferEmission(this._answered$.asObservable())}async setLayout(t,e){if(!this.layouts.includes(t))throw new on(`Layout ${t} is not available in the current call layouts: ${this.layouts.join(", ")}`);const i=[];for(const[n,s]of Object.entries(e??{})){const a=this.participants.find(o=>o.id===n);if(!a){Ce.warn(`[Call] setLayout: member ${n} not found in participants; skipping position ${s}`);continue}a.target,i.push([a,s])}const r=await Ze(this.selfId$.pipe(B(n=>n!==null)));await this.executeMethod(r,"call.layout.set",{layout:t});for(const[n,s]of i)await n.setPosition(s)}async transfer(t){return this.vertoManager.transfer(t)}setLocalMicrophoneGain(t){const e=this.vertoManager.ensureLocalAudioPipeline();if(!e){Ce.warn("[Call] setLocalMicrophoneGain: audio pipeline unavailable");return}const i=Math.max(0,Math.min(200,t));e.setGain(i/100)}get localMicrophoneGain$(){const t=this.vertoManager.ensureLocalAudioPipeline();return t?this.publicCachedObservable("localMicrophoneGain$",()=>t.gain$.pipe(x(e=>e*100),S(this._destroyed$))):Ct(100).pipe(S(this._destroyed$))}get localAudioLevel$(){const t=this.vertoManager.ensureLocalAudioPipeline();return t?this.publicCachedObservable("localAudioLevel$",()=>t.level$.pipe(S(this._destroyed$),At())):Ct(0).pipe(S(this._destroyed$))}get localSpeaking$(){const t=this.vertoManager.ensureLocalAudioPipeline();return t?this.publicCachedObservable("localSpeaking$",()=>t.speaking$.pipe(S(this._destroyed$),At())):Ct(!1).pipe(S(this._destroyed$))}enablePushToTalk(){const t=this.vertoManager.ensureLocalAudioPipeline();if(!t){Ce.warn("[Call] enablePushToTalk: audio pipeline unavailable");return}t.setPTTActive(!1),this._pushToTalkEnabled=!0}disablePushToTalk(){var t;(t=this.vertoManager.localAudioPipeline)==null||t.setPTTActive(!0),this._pushToTalkEnabled=!1}setPushToTalkActive(t){var e;this._pushToTalkEnabled&&((e=this.vertoManager.localAudioPipeline)==null||e.setPTTActive(t))}async setEchoCancellation(t){await this.vertoManager.updateMediaConstraints({audio:{echoCancellation:t}})}async setNoiseSuppression(t){await this.vertoManager.updateMediaConstraints({audio:{noiseSuppression:t}})}async setAutoGainControl(t){await this.vertoManager.updateMediaConstraints({audio:{autoGainControl:t}})}get remoteAudioLevel$(){return this.publicCachedObservable("remoteAudioLevel$",()=>{this._remoteAudioMeter??(this._remoteAudioMeter=new ff);const t=this._remoteAudioMeter;return this.subscribeTo(this.vertoManager.remoteStream$,e=>{t.setStream(e)}),t.level$.pipe(S(this._destroyed$),At())})}destroy(){var t;this._status$.value!=="destroyed"&&(this._status$.next("destroyed"),this.stopResilienceSubsystems(),(t=this._remoteAudioMeter)==null||t.destroy(),this._remoteAudioMeter=null,this.vertoManager.destroy(),this.callEventsManager.destroy(),super.destroy())}async _sendVertoSubscribe(t){const e=xg({sessid:this.id,eventChannel:[t]}),i={callID:this.id,node_id:this.vertoManager.nodeId??"",message:e};await this.clientSession.execute(sc(i))}};function av(t){return t instanceof an?"timeout":t instanceof Et?"signaling":t instanceof kt||t instanceof Gt?"media":t instanceof Po||t instanceof _o?"network":"internal"}const ov=new Set([hs,ps,Mo]);function cv(t){return t instanceof No||t instanceof kt?!1:t instanceof Gt?t.fatal:!(t instanceof an||t instanceof Et&&ov.has(t.code))}var lv=class{constructor(t,e,i,r,n){this.sessionManager=t,this.deviceController=e,this.attachManager=i,this.webRTCApiProvider=r,this.networkChange$=n}createCall(t,e){return new sv(this.sessionManager,e,{initializeManagers:i=>({vertoManager:new gf(i,this.attachManager,this.deviceController,this.webRTCApiProvider,{nodeId:e.nodeId,onError:(r,n)=>{const s={kind:av(r),fatal:(n==null?void 0:n.fatal)??cv(r),error:r,callId:i.id};i.emitError(s)},onModifyFailed:()=>{i.notifyModifyFailed()}}),callEventsManager:new Xg(i)}),deviceController:this.deviceController,networkChange$:this.networkChange$},t)}};const Is=G();var Mc=class{constructor(t,e,i){this.endpoint=t,this.http=i,this.filter=r=>!0,this.mapper=r=>r,this.nextUrl=`${this.endpoint}?${e}`}async next(){if(!this.nextUrl)return this.hasMore=!1,[];const t=await this.http.request({...ms,url:this.nextUrl});if(t.ok&&t.body){const e=JSON.parse(t.body);return this.nextUrl=e.links.next,this.hasMore=!!this.nextUrl,e.data.filter(this.filter).map(this.mapper)}return Is.error("Failed to fetch entity"),[]}async id(t){const e=await this.http.request({...ms,url:`${this.endpoint}/${String(t)}`});if(e.ok&&e.body)return JSON.parse(e.body)}},Rc=class extends se{constructor(t,e,i){super(),this.fetchController=t,this.update$=e,this.onError=i,this.collectionData=new Map,this.observablesRegistry=new Map,this.upsertData=r=>{var o;if(!r.id)return;const n=this.collectionData.get(r.id)??{},s={},a=new Set([...Object.keys(n),...Object.keys(r)]);for(const c of a){const u=n[c],h=r[c];h!==void 0&&u!==void 0&&typeof u=="object"&&u!==null&&!Array.isArray(u)&&typeof h=="object"&&h!==null&&!Array.isArray(h)?s[c]={...u,...h}:h!==void 0?s[c]=h:s[c]=u}this.collectionData.set(r.id,s),(o=this.observablesRegistry.get(r.id))==null||o.next(s),this._values$.next(Array.from(this.collectionData.values()))},this._loading$=this.createBehaviorSubject(!1),this._values$=this.createReplaySubject(1),this._hasMore$=this.createBehaviorSubject(!0),this.subscribeTo(this.update$,this.upsertData),this.hasMore$=li(()=>_e(this.init())).pipe(Je(()=>this._hasMore$),U(),st(1),S(this.destroyed$))}get loading$(){return this._loading$.asObservable()}get loading(){return this._loading$.value}get values$(){return this._values$.asObservable()}get hasMore(){return this.fetchController.hasMore??!0}get updated$(){return this.cachedObservable("updated$",()=>this._loading$.pipe(U(),tn(1),B(t=>!t),x(()=>{}),S(this.destroyed$)))}get values(){return Array.from(this.collectionData.values())}async init(){if(this.fetchController.hasMore===!1){this._hasMore$.next(!1);return}await this.fetchMore()}async fetchMore(){var t;try{this._loading$.next(!0),(await this.fetchController.next()).forEach(this.upsertData),this._hasMore$.next(this.fetchController.hasMore??!1),this._loading$.next(!1)}catch(e){Is.error("Failed to fetch initial collection data",e),this._hasMore$.next(this.fetchController.hasMore??!1),this._loading$.next(!1),(t=this.onError)==null||t.call(this,new Uo("fetchMore",e))}}async tryFetch(t,e){var i,r,n;try{this._loading$.next(!0);const s=await((r=(i=this.fetchController)[t])==null?void 0:r.call(i,e));return this._loading$.next(!1),s&&this.upsertData(s),s}catch(s){Is.error(`Failed to fetch data for (${String(t)}:${String(e)}) :`,s),this._loading$.next(!1),(n=this.onError)==null||n.call(this,new Uo(`tryFetch(${String(t)})`,s))}}get$(t){var e,i;if(!this.observablesRegistry.has(t)){this.observablesRegistry.set(t,new is(1));const r=this.collectionData.get(t);r?(e=this.observablesRegistry.get(t))==null||e.next(r):this.tryFetch("id",t)}return(i=this.observablesRegistry.get(t))==null?void 0:i.asObservable()}async find$(t,e){const i=Array.from(this.collectionData.values()).find(r=>r[t]===e)??await this.tryFetch(t,e);return i?this.get$(i.id):void 0}loadMore(){this.fetchController.hasMore!==!1&&this.fetchMore()}destroy(){this.observablesRegistry.forEach(t=>t.complete()),this.observablesRegistry.clear(),super.destroy()}},Pc=class{constructor(t,e=r=>!!r,i=r=>r){this.originalCollection=t,this.filter=e,this.mapper=i}get loading$(){return this.originalCollection.loading$}get loading(){return this.originalCollection.loading}get hasMore$(){return this.originalCollection.hasMore$}get hasMore(){return this.originalCollection.hasMore}get values(){return this.originalCollection.values.filter(this.filter).map(this.mapper)}get values$(){return this._values$??(this._values$=this.originalCollection.values$.pipe(x(t=>t.filter(this.filter).map(this.mapper))))}get$(t){const e=this.originalCollection.get$(t);return e&&e.pipe(Jr(B(this.filter),x(this.mapper)))}async find$(t,e){const i=await this.originalCollection.find$(t,e);return i&&i.pipe(Jr(B(this.filter),x(this.mapper)))}loadMore(){this.originalCollection.loadMore()}destroy(){this.originalCollection.destroy()}},_c=class extends se{constructor(t,e,i){super(),this.addressId=t,this.conversationManager=e,this.addressProvider=i,this.initConversationMessages=async()=>(this._conversationMessages=this._conversationMessages??await this.conversationManager.getConversationMessageCollection(this.id),this._conversationMessages.hasMore&&this._conversationMessages.loadMore(),this._conversationMessages),this.textMessages$=li(this.initConversationMessages).pipe(x(()=>this.textMessage),st(1),S(this.destroyed$)),this.history$=li(this.initConversationMessages).pipe(x(()=>this.history),st(1),S(this.destroyed$)),this._state$=this.createBehaviorSubject(null)}upnext(t){const e={...this._state$.value,...t};this._state$.next(e)}get state(){return this._state$.value}get id(){return this.addressId}get name(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.name}get createdAt(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.created_at}get defaultChannel(){return this.type==="room"?this.channels.video:this.channels.audio}get displayName$(){return this.cachedObservable("displayName$",()=>this._state$.pipe(ve(),x(t=>t.display_name),S(this.destroyed$)))}get displayName(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.display_name}get previewUrl$(){return this.cachedObservable("previewUrl$",()=>this._state$.pipe(ve(),x(t=>t.preview_url),S(this.destroyed$)))}get previewUrl(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.preview_url}get coverUrl$(){return this.cachedObservable("coverUrl$",()=>this._state$.pipe(ve(),st(1),x(t=>t.cover_url),S(this.destroyed$)))}get coverUrl(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.cover_url}get resourceId$(){return this.cachedObservable("resourceId$",()=>this._state$.pipe(ve(),st(1),x(t=>t.resource_id),S(this.destroyed$)))}get resourceId(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.resource_id}get type$(){return this.cachedObservable("type$",()=>this._state$.pipe(ve(),st(1),x(t=>t.type),S(this.destroyed$)))}get type(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.type}get channels$(){return this.cachedObservable("channels$",()=>this._state$.pipe(ve(),st(1),x(t=>t.channels),S(this.destroyed$)))}get channels(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.channels}get locked(){if(!this._state$.value)throw new te("state not initialized");return this._state$.value.locked}get locked$(){return this.cachedObservable("locked$",()=>this._state$.pipe(ve(),st(1),x(t=>t.locked),S(this.destroyed$)))}async sendText(t){return this.conversationManager.sendText(t,this.id)}get textMessage(){if(this._conversationMessages)return this._textMessages$=this._textMessages$??new Pc(this._conversationMessages,t=>t.subtype==="chat",t=>({id:t.id,text:t.text,created:t.ts,fromAddress$:this.addressProvider.get$(t.from_fabric_address_id)})),this._textMessages$}get history(){if(this._conversationMessages)return this._history$=this._history$??new Pc(this._conversationMessages,t=>t.subtype==="log",t=>({id:t.id,kind:t.kind,status:t.details.status,started:t.details.start_time,ended:t.details.end_time,fromAddress$:this.addressProvider.get$(t.from_fabric_address_id)})),this._history$}get activity$(){throw new Tt}get activity(){throw new Tt}};const vi=G(),uv=t=>{if(vi.debug("isRPCConnectResult check:",t),!t||typeof t!="object")return!1;const e=t,i=typeof e.identity=="string"&&typeof e.protocol=="string"&&typeof e.authorization=="object"&&typeof e.authorization.jti=="string"&&typeof e.authorization.project_id=="string"&&typeof e.authorization.fabric_subscriber=="object";return vi.debug("isRPCConnectResult check result:",i),i};var dv=(Ai=class{constructor(e,i,r){this.id=dn(),vi.debug(`[PendingRPC(${this.id}) request:${e.id}: method:${e.method}] Creating PendingRPC`),this.request=e;const n=(r==null?void 0:r.timeoutMs)??Ai.defaultTimeoutMs,s=r==null?void 0:r.signal;this.promise=new Promise((a,o)=>{if(s!=null&&s.aborted){o(new DOMException("The operation was aborted","AbortError"));return}let c=!1;const u=Cr(i.pipe(B(h=>h.id===e.id),Oe(1)),new Ae(h=>{const p=setTimeout(()=>{h.error(new an(e.id,n))},n);return()=>clearTimeout(p)}),s?new Ae(h=>{const p=()=>{h.error(new DOMException("The operation was aborted","AbortError"))};return s.addEventListener("abort",p),()=>s.removeEventListener("abort",p)}):Vd).subscribe({next:h=>{if(c=!0,h.error){const p=new Et(h.error.code,h.error.message,h.error.data,void 0,e.id);vi.debug(`[PendingRPC(${this.id}) request:${e.id}] Rejecting promise with RPC error:`,p),o(p)}else vi.debug(`[PendingRPC(${this.id}) request:${e.id}] Resolving promise with response:`,h),a(h);u.unsubscribe()},error:h=>{vi.debug(`[PendingRPC(${this.id}) request:${e.id}] Rejecting promise with error:`,h),c=!0,o(h),u.unsubscribe()},complete:()=>{vi.debug(`[PendingRPC(${this.id}) request:${e.id}] Observable completed`),c||o(new an(e.id,n)),u.unsubscribe()}})})}async then(e,i){return this.promise.then(e,i)}async catch(e){return this.promise.catch(e)}async finally(e){return this.promise.finally(e)}},Ai.defaultTimeoutMs=5e3,Ai);const Z=G();function hv(t){return t.fatal||!(t.error instanceof Gt)}const pv=t=>{var n,s;const e=(n=t.to)==null?void 0:n.split("?")[0],i=(s=t.from)!=null&&s.startsWith("subscriber://")?t.from.replace("subscriber://",""):t.from,r=e??i;if(!r)throw new Ui("Error building Address name");return r};var gv=class extends se{constructor(t,e,i,r,n,s,a,o,c){super(),this.getCredential=t,this.transport=e,this.storage=i,this.authorizationStateKey=r,this.attachManager=s,this.dpopManager=o,this.callCreateTimeout=6e3,this.agent="signalwire-js/4.0.0",this.eventAcks=!0,this.authorizationState$=this.createReplaySubject(1),this.connectVersion={major:4,minor:0,revision:0},this._authorization$=this.createBehaviorSubject(void 0),this._errors$=this.createReplaySubject(1),this._authState$=this.createBehaviorSubject({kind:"unauthenticated"}),this._wasClientBound=!1,this._userInfo$=this.createBehaviorSubject(null),this._calls$=this.createBehaviorSubject({}),this._iceServers$=this.createBehaviorSubject([]),s.setSession(this),this.callFactory=new lv(this,n,s,a,c),this.initialized$=li(()=>_e(this.init())).pipe(st(1),S(this.destroyed$))}get incomingCalls$(){return this.cachedObservable("incomingCalls$",()=>this.calls$.pipe(x(t=>t.filter(e=>e.direction==="inbound"))))}get incomingCalls(){return Object.values(this._calls$.value).filter(t=>t.direction==="inbound")}get userInfo$(){return this._userInfo$.asObservable()}get userInfo(){return this._userInfo$.value}get calls$(){return this.cachedObservable("calls$",()=>this._calls$.pipe(x(t=>Object.values(t))))}get calls(){return Object.values(this._calls$.value)}get iceServers(){return this._iceServers$.value}get authorization$(){return this._authorization$.asObservable()}get authorization(){return this._authorization$.value}get errors$(){return this._errors$.asObservable()}get authenticated$(){return this._authState$.pipe(x(t=>t.kind==="authenticated"),U())}get authenticated(){return this._authState$.value.kind==="authenticated"}get clientBound(){return this._wasClientBound}get authState(){return this._authState$.value}setDirectory(t){this._directory=t}async execute(t,e){try{return await this.transport.execute(t,e)}catch(i){throw Z.debug("[Session] Execute Error",i),this._errors$.next(i instanceof Error?i:new Error(String(i),{cause:i})),i}}send(t){this.transport.send(t)}async init(){return await this.loadAuthorizationStateFromStorage(),this.setupMessageHandlers(),!0}setupMessageHandlers(){Z.debug("[Session] Setting up message handlers"),this.subscribeTo(this.authStateEvent$,async t=>{Z.debug("[Session] Authorization state event received:",t);try{await this.updateAuthorizationStateInStorage(t.authorization_state)}catch(e){Z.error("[Session] Failed to handle authorization state update:",e),this._errors$.next(new gs(e))}}),this.subscribeTo(this.transport.connectionStatus$.pipe(B(t=>t==="disconnected"||t==="reconnecting")),()=>{this._authState$.value.kind==="authenticated"&&this._authState$.next({kind:"unauthenticated"})}),this.subscribeTo(this.transport.connectionStatus$.pipe(B(t=>t==="connected"),ls(()=>(Z.debug("[Session] Connection established, initiating authentication"),_e(this.authenticate()).pipe(ui(t=>(this.handleAuthenticationError(t).catch(e=>{Z.error("[Session] Error handling authentication failure:",e)}),ci)))))),void 0),this.subscribeTo(this.vertoInvite$,async t=>{Z.debug("[Session] Verto invite received:",t);try{await this.createInboundCall(t)}catch(e){Z.error("[Session] Error handling Verto invite:",e),this._errors$.next(new hp(e))}}),this.subscribeTo(this.vertoAttach$,async t=>{Z.debug("[Session] Verto attach received:",t);try{await this.handleVertoAttach(t)}catch(e){Z.error("[Session] Error handling Verto attach:",e),this._errors$.next(new pp(e))}})}async loadAuthorizationStateFromStorage(){try{const t=await this.storage.getItem(this.authorizationStateKey);this.authorizationState$.next(t??void 0)}catch(t){Z.error("Failed to retrieve authorization state from storage:",t),this.authorizationState$.next(void 0)}}async updateAuthorizationStateInStorage(t){if(!t){Z.debug("[Session] Removing authorization state from storage");try{await this.storage.removeItem(this.authorizationStateKey),this.authorizationState$.next(void 0)}catch(e){throw Z.error("Failed to remove authorization state from storage:",e),e}return}try{Z.debug("[Session] Updating authorization state in storage"),await this.storage.setItem(this.authorizationStateKey,t),this.authorizationState$.next(t)}catch(e){throw Z.error("Failed to retrieve authorization state from storage:",e),e}}get authStateEvent$(){return this.cachedObservable("authStateEvent$",()=>this.signalingEvent$.pipe(Ee(t=>{Z.debug("[Session] Received incoming message:",t)}),Se(Bg,"params"),Ee(t=>{Z.debug("[Session] Authorization state event received:",t.authorization_state)})))}get signalingEvent$(){return this.cachedObservable("signalingEvent$",()=>this.transport.incomingEvent$.pipe(Se(Es,"params"),At()))}get vertoInvite$(){return this.cachedObservable("vertoInvite$",()=>this.signalingEvent$.pipe(B(bn),B(t=>kc(t.params)),x(t=>({node_id:t.node_id,...t.params.params}))))}get vertoAttach$(){return this.cachedObservable("vertoAttach$",()=>this.signalingEvent$.pipe(B(bn),B(t=>xc(t.params)),x(t=>({node_id:t.node_id,...t.params.params}))))}get contexts(){return[]}get eventing(){return[]}get topics(){return[]}get authentication(){const t=this.getCredential();if(!t.token)throw new te("Credential token is undefined");return{jwt_token:t.token}}async connect(){await Ze(this.initialized$),await this.transport.connect(),await Ze(this.authenticated$.pipe(S(this.destroyed$),B(Boolean),Oe(1),Sr({first:15e3})))}async handleAuthenticationError(t){Z.error("Authentication error:",t);const e=t instanceof Et&&(t.code===hs||t.code===Mo||t.code===ps),i=await Ze(this.authorizationState$.pipe(Oe(1)))!==void 0;if(e&&i){Z.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");try{await this.cleanupStoredConnectionParams()}catch(r){Z.error("Failed to cleanup stored connection params:",r)}finally{this.transport.reconnect()}}else this._errors$.next(t)}async cleanupStoredConnectionParams(){await this.transport.setProtocol(void 0),await this.updateAuthorizationStateInStorage(void 0),this._authorization$.next(void 0)}async teardownSessionState(){await this.cleanupStoredConnectionParams(),await this.attachManager.detachAll()}async updateAuthState(t){try{await this.storage.setItem(this.authorizationStateKey,t)}catch(e){Z.error("Failed to update authorization state in storage:",e),this._errors$.next(new gs(e))}}async reauthenticate(t,e,i){var r,n;Z.debug("[Session] Re-authenticating session");try{let s=e;if(!s&&((r=this.dpopManager)!=null&&r.initialized))try{s=await this.dpopManager.createRpcProof({method:"signalwire.reauthenticate"})}catch(o){if(this.clientBound)throw o;Z.warn("[Session] Failed to create DPoP proof for reauthenticate:",o)}const a=mg({project:((n=this._authorization$.value)==null?void 0:n.project_id)??"",jwt_token:t,...s?{dpop_token:s}:{}});await oo(_e(this.transport.execute(a)).pipe(jo(),Oe(1),ui(o=>{throw Z.error("[Session] Re-authentication RPC failed:",o),o}))),i!=null&&i.clientBound&&(this._wasClientBound=!0),Z.debug("[Session] Re-authentication successful, updating stored auth state")}catch(s){throw Z.error("[Session] Re-authentication failed:",s),this._errors$.next(new gs(s)),s}}async authenticate(){var o,c,u;Z.debug("[Session] Starting authentication process");const t=await Ze(uo({protocol:this.transport.protocol$,authorization_state:this.authorizationState$}).pipe(Oe(1)));Z.debug(`[Session] Persisted params:
73
+ `,{protocol:t.protocol,authStateLength:(o=t.authorization_state)==null?void 0:o.length});const e=t.authorization_state&&t.protocol,i=this.getCredential().token,r=e&&i;let n;if(r)Z.debug("[Session] Reconnecting with stored jwt_token + authorization_state");else{const h=this.getCredential(),p=h.expiry_at!==void 0&&h.expiry_at<=Date.now()+bh;this.onBeforeReconnect&&(this.clientBound||p)&&(Z.debug("[Session] Refreshing credentials before fresh connect"),await this.onBeforeReconnect())}if((c=this.dpopManager)!=null&&c.initialized)try{n=await this.dpopManager.createRpcProof({method:"signalwire.connect"})}catch(h){if(this.clientBound)throw h;Z.warn("[Session] Failed to create DPoP proof for connect, proceeding without:",h)}const s=bg({authentication:r?{jwt_token:i}:this.authentication,version:this.connectVersion,agent:this.agent,contexts:this.contexts,eventing:this.eventing,topics:this.topics,event_acks:this.eventAcks,...n?{dpop_token:n}:{},...r?{authorization_state:t.authorization_state,protocol:t.protocol}:{}}),a=await oo(_e(this.transport.execute(s)).pipe(jo(),x(h=>h.result),B(uv),Ee(()=>{Z.debug("[Session] Response passed filter, processing authentication result")}),Oe(1),ui(h=>{throw Z.error("[Session] Authentication RPC failed:",h),h})));Z.debug("[Session] Processing authentication result:",{hasProtocol:!!a.protocol,hasAuthorization:!!a.authorization,hasIceServers:!!a.ice_servers}),a.protocol&&await this.transport.setProtocol(a.protocol),this._authorization$.next(a.authorization),(u=a.authorization.cnf)!=null&&u.jkt&&(this._wasClientBound=!0),this._iceServers$.next(a.ice_servers??[]),this._authState$.next({kind:"authenticated"}),Z.debug("[Session] Authentication completed successfully")}async disconnect(){this.transport.disconnect(),this._authState$.next({kind:"unauthenticated"}),await this.teardownSessionState()}async createInboundCall(t){const e=await this.createCall({nodeId:t.node_id,callId:t.callID,initOffer:t.sdp,toName:t.callee_id_name,to:t.callee_id_number,fromName:t.caller_id_name,from:t.caller_id_number,displayDirection:t.display_direction,userVariables:t.userVariables});this._calls$.next({[`${e.id}`]:e,...this._calls$.value})}async handleVertoAttach(t){const{callID:e}=t;if(e in this._calls$.value){Z.debug(`[Session] Verto attach for existing call ${e}, deferring to per-call handler`);return}const i=await this.attachManager.consumePendingAttachment(e);Z.debug(`[Session] Creating reattached call for callID: ${e}`);const r=await this.createCall({nodeId:t.node_id,callId:e,toName:t.callee_id_name,to:t.callee_id_number,fromName:t.caller_id_name,from:t.caller_id_number,reattach:!0,...i});this._calls$.next({[`${r.id}`]:r,...this._calls$.value})}async createOutboundCall(t,e={}){const i=t instanceof _c?t.defaultChannel:t;let r;try{return r=await this.createCall({to:i,...e}),await Ze(Cr(r.selfId$.pipe(B(n=>!!n),Oe(1),Sr(this.callCreateTimeout)),r.errors$.pipe(B(hv),Oe(1),Je(n=>kd(()=>n.error))))),this._calls$.next({[`${r.id}`]:r,...this._calls$.value}),r}catch(n){Z.error("[Session] Error creating outbound call:",n),r==null||r.destroy();const s=new Lo(n instanceof lo?"Call create timeout":"Call creation failed",n,"outbound");throw this._errors$.next(s),s}}async createCall(t={}){try{const e=pv(t);let i;try{if(!this._directory)throw new te("Directory not initialized");const n=await this._directory.findAddressIdByURI(e);if(!n)throw new te(`Address name: ${e} not found`);if(i=this._directory.get(n),!i)throw new te(`Address ID: ${n} not found`)}catch{Z.warn(`[Session] Directory lookup failed for ${e}, proceeding with raw URI`)}const r=this.callFactory.createCall(i,{...t});return this.subscribeTo(r.status$.pipe(B(n=>n==="destroyed"),Oe(1)),()=>{const{[`${r.id}`]:n,...s}=this._calls$.value;this._calls$.next(s)}),r}catch(e){throw Z.error("[Session] Error creating call session:",e),new Lo("Call create error",e,t.initOffer?"inbound":"outbound")}}destroy(){for(const t of Object.values(this._calls$.value))t.hangup();super.destroy()}},fv=class{constructor(t){this.clientSessionManager=t}get authenticated$(){return this.clientSessionManager.authenticated$}get authenticated(){return this.clientSessionManager.authenticated}get clientBound(){return this.clientSessionManager.clientBound}get signalingEvent$(){return this.clientSessionManager.signalingEvent$}get iceServers(){return this.clientSessionManager.iceServers}async execute(t,e){return this.clientSessionManager.execute(t,e)}get incomingCalls$(){return this.clientSessionManager.incomingCalls$}get incomingCalls(){return this.clientSessionManager.incomingCalls}get calls$(){return this.clientSessionManager.calls$}get calls(){return this.clientSessionManager.calls}};const vv=t=>typeof t=="string",Ms=G();var bv=class extends Mc{constructor(t,e){super(`/api/fabric/conversations/${t}/messages`,"page_size=100",e),this.groupId=t}},mv=class extends Rc{constructor(t,e,i,r){super(new bv(t,i),e,r)}},yv=class{constructor(t,e,i,r){this.clientSession=t,this.http=e,this.getUserAddressId=i,this.onError=r,this.groupIds=new Map}async join(t){const e=this.getUserAddressId();try{const i=await this.http.request({...hn,url:"/api/fabric/conversations/join",body:JSON.stringify({from_fabric_address_id:e,fabric_address_ids:[t,e]})});if(i.ok&&i.body){const r=JSON.parse(i.body);if(vv(r.group_id))return this.groupIds.set(t,r.group_id),r.group_id}throw new Fo("Join Failed - Unexpected response")}catch(i){throw Ms.error("[ConversationsManager] Failed to join conversation:",i),i}}async getConversationMessageCollection(t){const e=this.groupIds.get(t)??await this.join(t);return Promise.resolve(new mv(e,this.clientSession.signalingEvent$.pipe(Se(yc,"params"),Ee(i=>Ms.debug("[ConversationsManager ] Conversation Event:",i)),x(i=>({...i}))),this.http,this.onError))}async sendText(t,e){const i=this.groupIds.get(e)??await this.join(e),r=this.getUserAddressId();try{if((await this.http.request({...hn,url:"/api/fabric/messages",body:JSON.stringify({group_id:i,from_fabric_address_id:r,text:t})})).ok)return;throw new Fo("Send Text Failed - Unexpected response")}catch(n){throw Ms.error("[ConversationsManager] Failed to send text message:",n),n}}};const We=G();function mn(t){return t.expires_at?t.expires_at:t.expires_in?Math.floor(Date.now()/1e3)+t.expires_in:(We.warn("[DeviceToken] Could not determine token expiry, using default"),Math.floor(Date.now()/1e3)+sn)}function Oc(t){return t.expires_in?t.expires_in:t.expires_at?Math.max(t.expires_at-Math.floor(Date.now()/1e3),1):sn}var wv=class extends se{constructor(t,e,i,r){super(),this.dpopManager=t,this.http=e,this.errorHandler=i,this.getCredential=r,this._currentToken$=this.createBehaviorSubject(null),this._refreshInProgress=!1,this._paused=!1,this._effectiveExpireIn=sn,this.subscribeTo(this._currentToken$.pipe(B(Boolean),Je(n=>{const s=mn(n),a=Math.max(s*1e3-Date.now()-ds,1e3);return We.debug(`[DeviceToken] Scheduling Client Bound SAT refresh in ${a}ms`),Fi(a)})),()=>{this.executeRefresh()})}get effectiveExpireIn(){return this._effectiveExpireIn}async activate(t,e,i){var n;const{satClaims:r}=t;if(!((n=r==null?void 0:r.scope)!=null&&n.includes(ph)))return We.debug("[DeviceToken] No sat:refresh scope, skipping Client Bound SAT activation"),{activated:!1,reason:"no-scope"};this._session=e,this._updateCredential=i;try{const s=this._currentToken$.value;if(s&&this.isTokenFresh(s)){We.debug("[DeviceToken] Reusing cached Client Bound SAT — skipping /devices/token");const c=await this.dpopManager.createRpcProof({method:"signalwire.reauthenticate"});return await e.reauthenticate(s.token,c,{clientBound:!0}),i({token:s.token}),{activated:!0}}const a=await this.obtainToken();!a.expires_at&&!a.expires_in&&r.expires_at&&(a.expires_at=r.expires_at),this._effectiveExpireIn=Oc(a);const o=await this.dpopManager.createRpcProof({method:"signalwire.reauthenticate"});return await e.reauthenticate(a.token,o,{clientBound:!0}),i({token:a.token}),We.info("[DeviceToken] Client Bound SAT activated successfully"),this.emitCurrentToken(a),{activated:!0}}catch(s){return We.error("[DeviceToken] Failed to activate Client Bound SAT:",s),this.errorHandler(new ln(s,"Failed to activate Client Bound SAT")),{activated:!1,reason:"endpoint-failed"}}}emitCurrentToken(t){const e=t.expires_at?t:{...t,expires_at:mn(t)};this._currentToken$.next(e)}isTokenFresh(t){return mn(t)*1e3-Date.now()>ds}async obtainToken(){const t=await this.dpopManager.createHttpProof({method:"POST",uri:Eo}),e=await this.http.request({url:Eo,...hn,body:JSON.stringify({dpop_token:t,expire_in:sn})});if(!e.ok||!e.body)throw new zo(`Failed to obtain device token: ${e.status} ${e.statusText}`);const i=JSON.parse(e.body);if(!i.token)throw new zo("Device token response missing token field");return i}async refreshToken(t,e,i){We.debug("[DeviceToken] Refreshing Client Bound SAT");const r=await this.dpopManager.createHttpProof({method:"POST",uri:ko,accessToken:e}),n=await this.http.request({url:ko,...hn,body:JSON.stringify({dpop_token:r,expire_in:this._effectiveExpireIn})});if(!n.ok||!n.body)throw new di(`Failed to refresh device token: ${n.status} ${n.statusText}`);const s=JSON.parse(n.body);if(!s.token)throw new di("Device token refresh response missing token field");!s.expires_at&&!s.expires_in&&(s.expires_in=this._effectiveExpireIn),this._effectiveExpireIn=Oc(s);const a=await this.dpopManager.createRpcProof({method:"signalwire.reauthenticate"});return await t.reauthenticate(s.token,a),i({token:s.token}),We.info("[DeviceToken] Client Bound SAT refreshed successfully"),s}async executeRefresh(){if(this._paused){We.debug("[DeviceToken] Manager paused, skipping refresh");return}if(this._refreshInProgress){We.debug("[DeviceToken] Refresh already in progress, skipping");return}const t=this._session,e=this._updateCredential;if(!t||!e){We.warn("[DeviceToken] Cannot refresh: session or updateCredential not set");return}if(!t.authenticated){We.debug("[DeviceToken] Session not authenticated, deferring refresh");return}this._refreshInProgress=!0;try{const i=this.getCredential().token;if(!i)throw new di("No current token available for refresh");const r=await this.retryRefresh(t,i,e);this.emitCurrentToken(r)}catch(i){We.error("[DeviceToken] Automatic Client Bound SAT refresh failed:",i),this.errorHandler(i instanceof di?i:new di("Automatic token refresh failed",i))}finally{this._refreshInProgress=!1}}async retryRefresh(t,e,i){let r;for(let n=0;n<xo;n++)try{return await this.refreshToken(t,e,i)}catch(s){if(r=s,n<xo-1){const a=gh*Math.pow(2,n);We.warn(`[DeviceToken] Refresh attempt ${n+1} failed, retrying in ${a}ms`),await new Promise(o=>setTimeout(o,a))}}throw r instanceof Error?r:new di("All refresh retries exhausted",r)}refreshNowIfDue(){const t=this._currentToken$.value;t&&mn(t)*1e3-Date.now()<=ds&&(We.debug("[DeviceToken] Resume: cached SAT past refresh window; refreshing now"),this.executeRefresh())}pause(){this._paused=!0}resume(){this._paused=!1}destroy(){super.destroy()}};const vt=G(),Sv=(t,e,i,r)=>new wv(t,e,i,r);var Cv=class extends se{constructor(t,e){super(),this.deps=e,this._activating=!1,this._activationGeneration=0,this._developerRefreshInProgress=!1,t!=null&&t.initialized&&(this._deviceTokenManager=(e.deviceTokenManagerFactory??Sv)(t,e.http,i=>e.notifier.onError(i),()=>e.store.read()))}get clientBoundSATAvailable(){return this._deviceTokenManager!==void 0}get developerRefreshArmed(){return this._developerTimerId!==void 0}scheduleDeveloperRefresh(t,e,i=0){this._activeProvider=t,this._developerTimerId!==void 0&&clearTimeout(this._developerTimerId);const r=i===0?Math.max(e-Date.now()-Io,1e3):Math.min(fh*Math.pow(2,i)*(.5+Math.random()*.5),vh);this._developerTimerId=setTimeout(()=>{this._developerTimerId=void 0,this.executeDeveloperRefresh(t,e,i)},r)}async executeDeveloperRefresh(t,e,i){if(this._developerRefreshInProgress){vt.debug("[Coordinator] Developer refresh already in progress; skipping");return}this._developerRefreshInProgress=!0;try{const r=await this.refreshCredential(t);this.deps.store.write(r),this.deps.store.persist(r);try{await this.deps.notifier.onCredentialRefreshed(r)}catch(n){vt.warn("[Coordinator] onCredentialRefreshed rejected (non-fatal):",n)}vt.info("[Coordinator] Credentials refreshed successfully."),r.expiry_at&&this.scheduleDeveloperRefresh(t,r.expiry_at,0)}catch(r){const n=i+1;vt.error(`[Coordinator] Credential refresh failed (attempt ${n}/${Do}):`,r),this.deps.notifier.onError(r instanceof Error?r:new Error(String(r),{cause:r})),n<Do?this.scheduleDeveloperRefresh(t,e,n):(vt.error("[Coordinator] Credential refresh exhausted all retries. Disconnecting."),this.deps.notifier.onError(new di("Credential refresh failed after max retries")),this.deps.notifier.onRefreshExhausted())}finally{this._developerRefreshInProgress=!1}}forceRefreshIfDue(){var t;if(this._developerTimerId!==void 0&&this._activeProvider){const e=this.deps.store.read().expiry_at;e!==void 0&&Date.now()>=e-Io&&(vt.debug("[Coordinator] Resume: credential past refresh window; forcing refresh"),clearTimeout(this._developerTimerId),this._developerTimerId=void 0,this.executeDeveloperRefresh(this._activeProvider,e,0));return}(t=this._deviceTokenManager)==null||t.refreshNowIfDue()}syncExpiryFromAuthorization(t,e){var a;const i=(a=t==null?void 0:t.fabric_subscriber)==null?void 0:a.expires_at;if(!i)return;const r=i*1e3,n=this.deps.store.read();if(n.expiry_at===r)return;vt.debug(`[Coordinator] Correcting credential expiry from server authorization: ${new Date(r).toISOString()}`);const s={...n,expiry_at:r};this.deps.store.write(s),this.deps.store.persist(s),e!=null&&e.refresh&&this.scheduleDeveloperRefresh(e,r)}async refreshCredential(t){if(this._refreshInFlight)return this._refreshInFlight;if(!t.refresh)throw new Wt("Credential provider does not support refresh");const e=t.refresh();this._refreshInFlight=e;const i=()=>{this._refreshInFlight===e&&(this._refreshInFlight=void 0)};return e.then(i,i),e}cancelDeveloperRefresh(){this._developerTimerId!==void 0&&(clearTimeout(this._developerTimerId),this._developerTimerId=void 0)}suspend(){var t;this.cancelDeveloperRefresh(),(t=this._deviceTokenManager)==null||t.pause()}async activate(t,e){if(this._activating){vt.debug("[Coordinator] activate() in flight; ignoring re-entrant call");return}if(!this._deviceTokenManager)return;this._deviceTokenManager.resume();const i=++this._activationGeneration;this._activating=!0;try{const r=await this.withActivationTimeout(this._deviceTokenManager.activate(t,e,n=>this.deps.store.merge(n)));if(i!==this._activationGeneration){vt.debug("[Coordinator] activate() result discarded (preempted by newer activation)");return}if(r.activated){this.cancelDeveloperRefresh(),vt.debug("[Coordinator] Developer refresh disabled — Client Bound SAT owns refresh");return}vt.warn(`[SignalWire] [SW-REFRESH-FALLBACK] Client Bound SAT declined (reason=${r.reason}); using developer-provided refresh handler.`),this.deps.notifier.onWarning({code:"credential_refresh_fallback",source:"CredentialProvider",reason:r.reason,message:`Client Bound SAT activation declined (${r.reason}); using developer-provided refresh.`})}finally{this._activating=!1}}destroy(){var t;this.cancelDeveloperRefresh(),(t=this._deviceTokenManager)==null||t.destroy(),this._deviceTokenManager=void 0,super.destroy()}async withActivationTimeout(t){return new Promise(e=>{const i=setTimeout(()=>{var r;(r=this._deviceTokenManager)==null||r.pause(),e({activated:!1,reason:"activation-timeout"})},mh);t.then(r=>{clearTimeout(i),e(r)},r=>{clearTimeout(i),this.deps.notifier.onError(r instanceof Error?r:new Error(String(r))),e({activated:!1,reason:"endpoint-failed"})})})}};const Rs=G(),Av=1e3;function Tv(){try{if(typeof navigator<"u"&&navigator.userAgent)return navigator.userAgent}catch{}return"unknown"}var Ev=class extends se{constructor(t){super(),this._events=[],this._calls=[],this._deviceChanges=[],this._eventRecorded$=this.createSubject(),this._sdkVersion=t.sdkVersion,this._maxEvents=t.maxEvents??Av,Rs.debug("DiagnosticsCollector initialized",{sdkVersion:this._sdkVersion,maxEvents:this._maxEvents})}get eventRecorded$(){return this._eventRecorded$.asObservable()}record(t,e,i){const r={timestamp:Date.now(),category:t,event:e,...i!==void 0?{details:i}:{}};this._events=this._appendToBuffer(this._events,r),this._eventRecorded$.next(r)}recordDeviceChange(t,e){const i={timestamp:Date.now(),category:"device",event:t,...e!==void 0?{details:e}:{}};this._deviceChanges=this._appendToBuffer(this._deviceChanges,i),this._events=this._appendToBuffer(this._events,i),this._eventRecorded$.next(i)}recordCallSummary(t){this._calls=this._appendCallToBuffer(this._calls,t),this.record("call","call_summary",{callId:t.callId,direction:t.direction,duration:t.duration,finalStatus:t.finalStatus})}export(){return{sdkVersion:this._sdkVersion,userAgent:Tv(),exportedAt:Date.now(),events:[...this._events],calls:[...this._calls],deviceChanges:[...this._deviceChanges]}}clear(){this._events=[],this._calls=[],this._deviceChanges=[],Rs.debug("DiagnosticsCollector buffers cleared")}destroy(){Rs.debug("DiagnosticsCollector destroyed"),super.destroy()}_appendToBuffer(t,e){const i=[...t,e];return i.length>this._maxEvents?i.slice(i.length-this._maxEvents):i}_appendCallToBuffer(t,e){const i=[...t,e];return i.length>this._maxEvents?i.slice(i.length-this._maxEvents):i}};const Lc=t=>((t==null?void 0:t.length)??0)===0,kv=t=>{t.pipe(Oe(1)).subscribe()},xv=G();var Dv=class extends Mc{constructor(t){super("/api/fabric/addresses","sort_by=name&sort_order=asc",t)}async name(t){const e=await this.http.request({...ms,url:`${this.endpoint}?name=${encodeURIComponent(t)}`});if(e.ok&&e.body){const i=JSON.parse(e.body);if(!Lc(i.data))return i.data[0]}xv.error("Failed to fetch addresses")}},Iv=class extends Rc{constructor(t,e,i){super(new Dv(e),t,i)}},Mv=class extends se{constructor(t,e,i,r){super(),this.http=t,this.conversationManager=i,this.onError=r,this.addNewAddress=n=>{var o;const s=new _c(n,this.conversationManager,this),a=(o=this._statesCollection.get$(n))==null?void 0:o.pipe(ve(),x(c=>(s.upnext(c),s)));a&&(kv(a),this._observableRegistry.set(n,a)),this._addressesInstances.set(n,s)},this._addresses$=this.createBehaviorSubject([]),this._addressesInstances=new Map,this._observableRegistry=new Map,this._statesCollection=new Iv(e.signalingEvent$.pipe(Se(wc,"params"),x(n=>({}))),this.http,this.onError),this.initSubscriptions()}get loading(){return this._statesCollection.loading}initSubscriptions(){this.subscribeTo(this._statesCollection.updated$,()=>{const t=Array.from(this._addressesInstances.values().map(i=>i.id)),e=this._statesCollection.values.filter(i=>!t.includes(i.id));Lc(e)||(e.forEach(i=>this.addNewAddress(i.id)),this._addresses$.next(Array.from(this._addressesInstances.values())))})}get addresses$(){return this._addresses$.asObservable()}get addresses(){return this._addresses$.value}get hasMore$(){return this._statesCollection.hasMore$}get loading$(){return this._statesCollection.loading$}loadMore(){this._statesCollection.hasMore&&this._statesCollection.loadMore()}get$(t){return this._observableRegistry.has(t)||this.addNewAddress(t),this._observableRegistry.get(t)}get(t){return this._addressesInstances.get(t)}async findAddressIdByURI(t){var i;let e=(i=this._addressesInstances.values().find(r=>r.name===t))==null?void 0:i.id;if(!e){const r=await this._statesCollection.find$("name",t);if(r){const n=await Ze(r);this.addNewAddress(n.id),e=n.id}}return e}};const Fc=G();var Rv=(yt=class extends se{constructor(e,i,r,n={}){super(),this.WebSocketConstructor=e,this.endpoint=i,this.outgoingMessages$=r,this.messageQueue=[],this.shouldReconnect=!1,this.boundHandleOpen=()=>this.handleOpen(),this.boundHandleClose=s=>this.handleClose(s),this.boundHandleError=()=>this.handleError(),this.boundHandleMessage=s=>this.handleMessage(s),this._status$=this.createBehaviorSubject("disconnected"),this._incomingMessages$=this.createSubject(),this._errors$=this.createReplaySubject(1),this.reconnectDelayMin=n.reconnectDelayMin??yt.DEFAULT_RECONNECT_DELAY_MIN_MS,this.reconnectDelayMax=n.reconnectDelayMax??yt.DEFAULT_RECONNECT_DELAY_MAX_MS,this.connectionTimeout=n.connectionTimeout??yt.DEFAULT_CONNECTION_TIMEOUT_MS,this.currentReconnectDelay=this.reconnectDelayMin,this.subscriptions.push(this.outgoingMessages$.subscribe(s=>{this.send(s)}))}get status$(){return this._status$.asObservable()}get incomingMessages$(){return this._incomingMessages$.asObservable()}get errors$(){return this._errors$.asObservable()}connect(){this._status$.value==="connecting"||this._status$.value==="connected"||(this.shouldReconnect=!0,this._status$.next("connecting"),this.createWebSocket())}disconnect(){this.shouldReconnect=!1,this.clearReconnectTimer(),this.clearConnectionTimeout();const e=this._status$.value;e==="connected"||e==="connecting"||e==="reconnecting"?this.socket?(this._status$.next("disconnecting"),this.socket.close()):this._status$.next("disconnected"):this._status$.next("disconnected")}reconnect(){this.shouldReconnect=!0,this._status$.next("reconnecting"),this.scheduleReconnection()}send(e){var i;this._status$.value==="connected"&&((i=this.socket)==null?void 0:i.readyState)===1?(Fc.wsTraffic({type:"send",raw:e}),this.socket.send(e)):this.messageQueue.push(e)}createWebSocket(){try{this.closeExistingSocket(),this.socket=new this.WebSocketConstructor(this.endpoint),this.setupWebSocketListeners(),this.startConnectionTimeout()}catch(e){const i=e instanceof Error?e:new Ui("Failed to create WebSocket");this._errors$.next(i),this.handleConnectionError()}}closeExistingSocket(){if(!this.socket)return;const e=this.socket;this.socket=void 0,this.removeWebSocketListeners(e);try{e.close()}catch{}}setupWebSocketListeners(){this.socket&&(this.socket.addEventListener("open",this.boundHandleOpen),this.socket.addEventListener("close",this.boundHandleClose),this.socket.addEventListener("error",this.boundHandleError),this.socket.addEventListener("message",this.boundHandleMessage))}removeWebSocketListeners(e){try{e.removeEventListener("open",this.boundHandleOpen),e.removeEventListener("close",this.boundHandleClose),e.removeEventListener("error",this.boundHandleError),e.removeEventListener("message",this.boundHandleMessage)}catch{}}handleOpen(){this.clearConnectionTimeout(),this._status$.next("connected"),this.currentReconnectDelay=this.reconnectDelayMin,this.flushMessageQueue()}handleClose(e){this.clearConnectionTimeout(),this.shouldReconnect?(this._status$.next("reconnecting"),this.scheduleReconnection()):this._status$.next("disconnected")}handleError(){const e=new Po("WebSocket connection error");this._errors$.next(e),this.handleConnectionError()}handleMessage(e){Fc.wsTraffic({type:"recv",raw:e.data}),this._incomingMessages$.next(e)}handleConnectionError(){this.reconnect()}scheduleReconnection(){this.clearReconnectTimer();const e=this.currentReconnectDelay*(.5+Math.random()*.5);this.reconnectTimer=setTimeout(()=>{this.shouldReconnect&&(this._status$.next("connecting"),this.createWebSocket(),this.increaseReconnectDelay())},e)}increaseReconnectDelay(){this.currentReconnectDelay=Math.min(this.currentReconnectDelay*2,this.reconnectDelayMax)}startConnectionTimeout(){this.clearConnectionTimeout(),this.connectionTimeoutTimer=setTimeout(()=>{if(this._status$.value==="connecting"){const e=new sp("WebSocket connection timeout");this._errors$.next(e),this.socket&&this.socket.close()}},this.connectionTimeout)}clearConnectionTimeout(){this.connectionTimeoutTimer&&(clearTimeout(this.connectionTimeoutTimer),this.connectionTimeoutTimer=void 0)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0)}flushMessageQueue(){var e;for(;this.messageQueue.length>0&&((e=this.socket)==null?void 0:e.readyState)===1;){const i=this.messageQueue.shift();i!==void 0&&this.socket.send(i)}}},yt.DEFAULT_RECONNECT_DELAY_MIN_MS=1e3,yt.DEFAULT_RECONNECT_DELAY_MAX_MS=3e4,yt.DEFAULT_CONNECTION_TIMEOUT_MS=1e4,yt);function Pv(t){return As(t)&&t.method==="signalwire.ping"}const De=G();var _v=class extends se{constructor(t,e,i,r,n){super(),this.storage=t,this.protocolKey=e,this.onError=n,this.protocol$=this.createReplaySubject(1),this.isConnecting=!1,this.isConnected=!1,this.ackEvent=()=>Ee(s=>{if(Es(s))try{De.debug("[Transport] Sending event ack",{eventId:s.id}),this.send(Mg(s.id))}catch(a){De.error("[Transport] Failed to send event acknowledgment:",a)}}),this.replySignalwirePing=()=>B(s=>{if(Pv(s)){try{De.debug("[Transport] Received ping, sending pong",{pingId:s.id}),this.send(yg(s.id))}catch(a){De.error("[Transport] Failed to send ping response:",a)}return!1}return!0}),this.discardStaleEvents=()=>B(s=>{if(!Es(s))return!0;const a=s.params.event_channel;if(!a)return!0;if(s.params.event_type.startsWith("conversation."))return De.debug(`[Transport] Received conversation event: ${s.params.event_type} (event_channel: ${a})`),!0;const o=this._currentProtocol;if(!o)return!0;if(!a.includes(o)){const c=s.params.event_type;return De.warn(`[Transport] Discarding stale event: ${c} (event_channel does not match current protocol)`),!1}return!0}),this._outgoingMessages$=this.createSubject(),this._webSocketConnections=new Rv(i,r,this._outgoingMessages$.asObservable(),{connectionTimeout:f.instance.connectionTimeout,reconnectDelayMin:f.instance.reconnectDelayMin,reconnectDelayMax:f.instance.reconnectDelayMax}),this.subscribeTo(this._webSocketConnections.errors$,s=>{var a;(a=this.onError)==null||a.call(this,s)}),this.initialized$=li(()=>_e(this._init())).pipe(st(1),S(this.destroyed$)),this._jsonRPCMessage$=this._webSocketConnections.incomingMessages$.pipe(x(s=>{var a;try{return JSON.parse(s.data)}catch(o){return De.error("[Transport] Failed to parse incoming message:",o),(a=this.onError)==null||a.call(this,new gp(o)),null}}),B(s=>s!==null&&(Ts(s)||As(s))),ui(s=>{var a;return De.error("[Transport] Message processing error:",s),(a=this.onError)==null||a.call(this,s instanceof Error?s:new Error(String(s),{cause:s})),ci}),At(),S(this.destroyed$)),this._jsonRPCResponse$=this._jsonRPCMessage$.pipe(B(Ts)),this._incomingEvent$=this._jsonRPCMessage$.pipe(this.ackEvent(),this.replySignalwirePing(),B(s=>!Ts(s)),this.discardStaleEvents(),At(),S(this.destroyed$))}async setProtocol(t){this._currentProtocol=t,this.protocol$.next(t),await this._updateProtocolInStorage(t)}get incomingEvent$(){return this._incomingEvent$}get connectionStatus$(){return this._webSocketConnections.status$}async connect(){return this.isConnecting||this.isConnected?(De.warn("[Transport] Already connecting or connected"),Promise.resolve()):new Promise((t,e)=>{this.isConnecting=!0,this.subscribeTo(this.initialized$,()=>{this._webSocketConnections.connect();const i=this._webSocketConnections.status$.pipe(B(r=>r==="connected"||r==="disconnected"),Oe(1),Sr(1e4)).subscribe({next:r=>{var n;if(r==="connected")this.isConnecting=!1,this.isConnected=!0,De.debug("[Transport] Connection established"),t();else{this.isConnecting=!1;const s=new _o("Failed to connect");De.error("[Transport] Connection failed"),(n=this.onError)==null||n.call(this,s),e(s)}},error:r=>{var n;this.isConnecting=!1,De.error("[Transport] Connection error:",r),(n=this.onError)==null||n.call(this,r instanceof Error?r:new Error(String(r),{cause:r})),e(r)}});this.subscriptions.push(i),this.subscribeTo(this._webSocketConnections.status$.pipe(B(r=>r==="disconnected")),()=>{De.debug("[Transport] Disconnected"),this.isConnected=!1})})})}reconnect(){this._webSocketConnections.reconnect()}async execute(t,e){return this.send(t),new dv(t,this._jsonRPCResponse$,e).promise}send(t){const e=JSON.stringify(t);this._outgoingMessages$.next(e)}disconnect(){De.debug("[Transport] Disconnecting"),this.isConnected=!1,this.isConnecting=!1,this._webSocketConnections.disconnect()}destroy(){De.debug("[Transport] Destroying"),this.disconnect(),super.destroy(),this._webSocketConnections.destroy()}async _loadProtocolFromStorage(){try{const t=await this.storage.getItem(this.protocolKey);this._currentProtocol=t??void 0,this.protocol$.next(t??void 0)}catch(t){throw De.error("Failed to retrieve protocol from storage:",t),t}}async _updateProtocolInStorage(t){if(!t){try{await this.storage.removeItem(this.protocolKey)}catch(e){throw De.error("Failed to remove protocol from storage:",e),e}return}try{const e=await this.storage.getItem(this.protocolKey);(!e||e!==t)&&await this.storage.setItem(this.protocolKey,t)}catch(e){throw De.error("Failed to update protocol in storage:",e),e}}async _init(){return await this._loadProtocolFromStorage(),!0}};function Ov(t){const e=new Set;let i=t;for(;i instanceof Error&&!e.has(i);){if(e.add(i),i instanceof Et)return i;i=i.error??i.cause}}function Nc(t){const e=Ov(t);return e!==void 0&&(e.code===hs||e.code===ps)}const Y=G(),Lv=t=>{if(typeof t=="string"){const e=t.indexOf("?");if(e!==-1){const i=t.substring(e+1),r=new URLSearchParams(i).get("channel");if(r==="video")return{audio:!0,video:!0,receiveVideo:!0};if(r==="audio")return{audio:!0,video:!1}}}return{}};var Uc=class extends se{constructor(t,e={}){super(),this.preferences=new Gp,this._user$=this.createBehaviorSubject(void 0),this._directory$=this.createBehaviorSubject(void 0),this._isConnected$=this.createBehaviorSubject(!1),this._isRegistered$=this.createBehaviorSubject(!1),this._errors$=this.createReplaySubject(1),this._warnings$=this.createReplaySubject(10),this._options={},this._deps=new Kp,this._credentialProvider=t,this._options={...f.instance.defaultSignalWireOptions,...e},this._options.storageImplementation&&(this._deps.storageImpl=this._options.storageImplementation),this._options.persistSession&&(this._deps.persistSession=!0),this._options.webSocketConstructor&&(this._deps.WebSocket=this._options.webSocketConstructor),this._options.savePreferences&&this.preferences.enableSavePreferences(this._deps.storage),this._options.webRTCApiProvider&&(this._deps.webRTCApiProvider=this._options.webRTCApiProvider),this._options.logger!==void 0&&yp(this._options.logger),this._options.logLevel&&Sp(this._options.logLevel),this._options.debug&&wp(this._options.debug),this._deviceController=this._deps.deviceController,this._options.skipDeviceMonitoring||this._deviceController.enableDeviceMonitoring(),this.subscribeTo(this._deviceController.errors$,i=>{this._errors$.next(i)}),this.initResilienceSubsystems(),this.resolveCredentials().then(()=>{this.init().catch(i=>{Y.error("[SignalWire] Initialization error:",i),this._deps.storage.removeItem("sw:cached_credential"),this._deps.storage.removeItem("sw:cached_credential","local"),this._errors$.next(i instanceof Error?i:new Error(String(i),{cause:i}))})}).catch(i=>{Y.error("[SignalWire] Initialization error:",i),this._errors$.next(i instanceof Error?i:new Error(String(i),{cause:i}))})}async initDPoP(){var t;if((t=this._dpopManager)!=null&&t.initialized)return this._dpopManager.fingerprint;try{this._dpopManager=new eg;const e=await this._dpopManager.init();return Y.debug("[SignalWire] DPoP initialized, fingerprint available"),e}catch(e){Y.warn("[SignalWire] DPoP initialization failed, proceeding without DPoP:",e),this._dpopManager=void 0;return}}async resolveCredentials(){const t=await this.initDPoP();if(this._refreshCoordinator=new Cv(this._dpopManager,{http:this._deps.http,notifier:{onError:e=>this._errors$.next(e),onWarning:e=>this._warnings$.next(e),onRefreshExhausted:()=>void this.disconnect(),onCredentialRefreshed:async e=>this.reauthenticateLiveSession(e)},store:{read:()=>this._deps.credential,write:e=>{this._deps.credential=e},merge:e=>{this._deps.credential={...this._deps.credential,...e},this.persistCredential(this._deps.credential)},persist:e=>this.persistCredential(e)}}),this._credentialProvider)return this.validateCredentials(this._credentialProvider,void 0,t);for(const e of this._deps.persistSession?["local","session"]:["session"])try{const i=await this._deps.storage.getItem("sw:cached_credential",e);if(i!=null&&i.token)return Y.debug(`[SignalWire] Using cached credential from ${e}Storage`),await this.validateCredentials(void 0,i)}catch{}throw new Wt("No credential provider and no cached session. Provide a CredentialProvider or enable persistSession with a prior login.")}async validateCredentials(t,e,i){var s,a;const r=i??((s=this._dpopManager)!=null&&s.initialized?this._dpopManager.fingerprint:void 0),n=e??(t?await t.authenticate(r?{fingerprint:r}:void 0):void 0);if(!n)throw new Wt("No credentials available.");if(n.token)try{const o=xp(n.token,{header:!0});this._deps.ch=o.ch}catch(o){throw Y.error("[SignalWire] Invalid JWT token provided in credentials:",o),new Wt("Invalid JWT token provided in credentials.",{cause:o})}if(!n.token&&!n.authorizationState)throw Y.error("[SignalWire] No valid authentication credentials provided."),new Wt("No valid authentication credentials provided.");if(!this._deps.persistSession&&n.expiry_at&&n.expiry_at<Date.now())throw Y.error("[SignalWire] Provided credentials have expired."),new Wt("Provided credentials have expired.");n.expiry_at&&(t!=null&&t.refresh)?(a=this._refreshCoordinator)==null||a.scheduleDeveloperRefresh(t,n.expiry_at):n.expiry_at&&!(t!=null&&t.refresh)&&(Y.warn(`[SignalWire] [SW-NO-REFRESH-HANDLER] Credential has expiry_at=${n.expiry_at} but no refresh handler. Session will terminate at expiry unless the SAT has 'sat:refresh' scope.`),this._warnings$.next({code:"credential_no_refresh_handler",source:"CredentialProvider",message:"Credential has expiry_at but no refresh handler. Session will terminate at expiry unless the SAT carries 'sat:refresh' scope.",expiresAt:n.expiry_at})),this._deps.credential=n,this.persistCredential(n),await this.reauthenticateLiveSession(n)}async reauthenticateLiveSession(t){if(!(!this.isConnected||!this._clientSession.authenticated||!t.token))try{await this._clientSession.reauthenticate(t.token),Y.info("[SignalWire] Session refreshed with new credentials.")}catch(e){Y.error("[SignalWire] Failed to refresh session with new credentials:",e),this._errors$.next(e instanceof Error?e:new Error(String(e),{cause:e}))}}async recoverStaleCredential(t=!0){var i,r;const e=this._deps.credential.token;if(e)try{return await this._clientSession.reauthenticate(e),!0}catch(n){Y.debug("[SignalWire] In-memory reauth failed during recovery:",n)}if(!t||this._clientSession.clientBound||!((i=this._credentialProvider)!=null&&i.refresh))return!1;try{const n=await this.remintCredential(this._credentialProvider);return n.token?(this._deps.credential=n,this.persistCredential(n),await this._clientSession.reauthenticate(n.token),n.expiry_at&&((r=this._refreshCoordinator)==null||r.scheduleDeveloperRefresh(this._credentialProvider,n.expiry_at)),!0):!1}catch(n){return Y.error("[SignalWire] Credential recovery failed:",n),!1}}async remintCredential(t){if(this._refreshCoordinator)return this._refreshCoordinator.refreshCredential(t);if(!t.refresh)throw new Wt("Credential provider does not support refresh");return t.refresh()}async refreshCredentialForReconnect(){var t,e;if(this._credentialProvider)try{let i;if(this._clientSession.clientBound){const r=(t=this._dpopManager)!=null&&t.initialized?this._dpopManager.fingerprint:void 0;Y.debug("[SignalWire] Re-minting client-bound base SAT before reconnect"),i=await this._credentialProvider.authenticate(r?{fingerprint:r}:void 0)}else if(this._credentialProvider.refresh)Y.debug("[SignalWire] Refreshing unbound credential before reconnect"),i=await this.remintCredential(this._credentialProvider);else{Y.warn("[SignalWire] [SW-NO-REFRESH-HANDLER] Token expired on reconnect but no refresh handler; reconnecting with the existing token.");return}if(!i.token){Y.warn("[SignalWire] Re-minted credential has no token; keeping the existing credential for reconnect.");return}this._deps.credential=i,this.persistCredential(i),i.expiry_at&&this._credentialProvider.refresh&&((e=this._refreshCoordinator)==null||e.scheduleDeveloperRefresh(this._credentialProvider,i.expiry_at)),Y.debug("[SignalWire] Credential refreshed successfully for reconnect")}catch(i){throw Y.error("[SignalWire] Failed to refresh credentials for reconnect:",i),this._errors$.next(i instanceof Error?i:new Error(String(i),{cause:i})),i}}persistCredential(t){t.token&&(this._deps.storage.setItem("sw:cached_credential",t),this._deps.persistSession&&this._deps.storage.setItem("sw:cached_credential",t,"local"))}async init(){if(this._user$.next(new fg(this._deps.http)),this._options.skipConnection||await this.connect(),!this._options.reconnectAttachedCalls&&this._attachManager&&await this._attachManager.flush(),!this._options.skipRegister)try{await this.register()}catch(t){Y.error("[SignalWire] Registration failed:",t),this._errors$.next(t instanceof Error?t:new Error(String(t),{cause:t}))}this.handleAttachments()}async handleAttachments(){if(!this._attachManager){Y.error("[SignalWire] AttachManager not initialized");return}if(this._options.reconnectAttachedCalls)try{await this._attachManager.reattachCalls()}catch(t){Y.error("[SignalWire] Failed to reattach calls:",t),this._errors$.next(t instanceof Error?t:new Error(String(t),{cause:t}))}}async connect(){var r,n,s;await this.teardownTransportAndSession();try{const a=this._user$.value;if(!a)throw new Ui("User not initialized before connect");if(!await Ze(a.fetched$))throw new Ui("Failed to fetch user information - fetched$ emitted false");this._deps.user=a}catch(a){throw Y.error(`[SignalWire] Failed to fetch user information: ${a instanceof Error?a.message:"Unknown error"}. This usually means the user token is invalid or expired.`),new Ui("Error fetching user information",{cause:a})}const t=a=>{this._errors$.next(a)};this._transport=new _v(this._deps.storage,this._deps.protocolKey,this._deps.WebSocket,f.instance.relayHost??this._deps.relayHost,t),this._attachManager=new Rg(this._deps.storage,this._deps.deviceController,f.instance.reconnectCallsTimeout,this._deps.attachedCallsKey),this._clientSession=new gv(()=>this._deps.credential,this._transport,this._deps.storage,this._deps.authorizationStateKey,this._deps.deviceController,this._attachManager,this._deps.webRTCApiProvider,this._dpopManager,(r=this._networkMonitor)==null?void 0:r.networkChange$),this._publicSession=new fv(this._clientSession),this._clientSession.onBeforeReconnect=async()=>this.refreshCredentialForReconnect(),this.subscribeTo(this._clientSession.errors$,a=>{this._errors$.next(a)}),this.subscribeTo(this._clientSession.authorization$,a=>{var o;(o=this._refreshCoordinator)==null||o.syncExpiryFromAuthorization(a,this._credentialProvider)}),await this._clientSession.connect(),await((n=this._refreshCoordinator)==null?void 0:n.activate(this._deps.user,this._clientSession)),this.subscribeTo(this._clientSession.authenticated$.pipe(tn(1),B(Boolean)),async()=>{var a;try{await((a=this._refreshCoordinator)==null?void 0:a.activate(this._deps.user,this._clientSession))}catch(o){Y.error("[SignalWire] Refresh re-arm after reconnect failed (non-fatal):",o),this._errors$.next(o instanceof Error?o:new Error(String(o),{cause:o}))}try{Y.debug("[SignalWire] Re-registering user after reconnect"),await this.register(),Y.debug("[SignalWire] User re-registered successfully after reconnect")}catch(o){Y.error("[SignalWire] Re-registration failed after reconnect:",o),this._errors$.next(o instanceof Error?o:new Error(String(o),{cause:o}))}});const e=new yv(this._clientSession,this._deps.http,()=>this._deps.getUserFromAddressId(),t),i=new Mv(this._deps.http,this._clientSession,e,t);this._directory$.next(i),this._clientSession.setDirectory(i),this._isConnected$.next(!0),(s=this._diagnosticsCollector)==null||s.record("connection","connected"),this.subscribeTo(this._clientSession.authenticated$.pipe(tn(2),B(Boolean)),()=>{var a;(a=this._diagnosticsCollector)==null||a.record("connection","reconnected")})}get user$(){return this.deferEmission(this._user$.asObservable())}get user(){return this._user$.value}get directory$(){return this.deferEmission(this._directory$.asObservable())}get directory(){return this._directory$.value}get isRegistered$(){return this.deferEmission(this._isRegistered$.asObservable())}get isRegistered(){return this._isRegistered$.value}get isConnected(){return this._isConnected$.value}get isConnected$(){return this.deferEmission(this._isConnected$.asObservable())}get ready$(){return this.publicCachedObservable("ready$",()=>this._isConnected$.pipe(Je(t=>t?this._clientSession.authenticated$:Ct(!1))))}get errors$(){return this.deferEmission(this._errors$.asObservable())}get warnings$(){return this.deferEmission(this._warnings$.asObservable())}get platformCapabilities(){return this._platformCapabilities??(this._platformCapabilities=tc(this._options.webRTCApiProvider)),this._platformCapabilities}get deviceRecovered$(){return this.deferEmission(this._deviceController.deviceRecovered$)}exportDiagnostics(){const t={audioInput:this.audioInputDevices,audioOutput:this.audioOutputDevices,videoInput:this.videoInputDevices},e={sdkVersion:"unknown",userAgent:typeof navigator<"u"?navigator.userAgent:"unknown",capabilities:this.platformCapabilities,events:[],calls:[],deviceChanges:[],devices:t};if(!this._diagnosticsCollector)return e;const i=this._diagnosticsCollector.export();return{...e,sdkVersion:i.sdkVersion,userAgent:i.userAgent,events:i.events,calls:i.calls,deviceChanges:i.deviceChanges,devices:t}}initResilienceSubsystems(){try{this._platformCapabilities=tc(this._options.webRTCApiProvider)}catch(t){Y.warn("[SignalWire] Failed to detect platform capabilities:",t)}try{this._networkMonitor=new tg}catch(t){Y.warn("[SignalWire] Failed to initialize NetworkMonitor:",t)}try{this._visibilityController=new pg,this.subscribeTo(this._visibilityController.visibilityChange$.pipe(B(t=>t.to==="visible")),()=>{var t;try{(t=this._refreshCoordinator)==null||t.forceRefreshIfDue()}catch(e){Y.warn("[SignalWire] Resume credential revalidation failed (non-fatal):",e)}}),this.subscribeTo(this._visibilityController.visibilityChange$.pipe(B(t=>t.to==="visible"&&f.instance.refreshDevicesOnVisible)),()=>{Y.debug("[SignalWire] Page visible, re-enumerating devices");try{this._deviceController.disableDeviceMonitoring(),this._deviceController.enableDeviceMonitoring()}catch{}})}catch(t){Y.warn("[SignalWire] Failed to initialize VisibilityController:",t)}try{this._diagnosticsCollector=new Ev({sdkVersion:"4.0.0-rc.2"})}catch(t){Y.warn("[SignalWire] Failed to initialize DiagnosticsCollector:",t)}}async disconnect(){var t,e;(t=this._refreshCoordinator)==null||t.suspend(),(e=this._diagnosticsCollector)==null||e.record("connection","disconnected"),await this.teardownTransportAndSession(),this._isConnected$.next(!1)}async teardownTransportAndSession(){const t=this._clientSession,e=this._transport;if(t){try{await t.disconnect()}catch(i){Y.warn("[SignalWire] Error disconnecting previous session:",i)}t.destroy()}e&&e.destroy(),this._clientSession=void 0,this._publicSession=void 0,this._transport=void 0,this._attachManager=void 0}async waitAuthentication(){await Ze(this.ready$.pipe(B(t=>t===!0)))}async register(){try{await this.waitAuthentication(),await this._transport.execute(Ss({method:"subscriber.online",params:{}})),this._isRegistered$.next(!0);return}catch(t){if(!this._deps.credential.token)throw this._errors$.next(t instanceof Error?t:new Error(String(t),{cause:t})),t;Y.debug("[SignalWire] Failed to register user, attempting credential recovery...");let e=t;if(await this.recoverStaleCredential(Nc(t)))try{Y.debug("[SignalWire] Recovery succeeded, retrying register()"),await this._transport.execute(Ss({method:"subscriber.online",params:{}})),this._isRegistered$.next(!0);return}catch(r){Y.error("[SignalWire] Register retry after recovery failed:",r),e=r}const i=new Wt("Failed to register user, and credential recovery also failed. Please check your credentials.",{cause:e instanceof Error?e:new Error(String(e),{cause:e})});throw this._errors$.next(i),i}}async unregister(){try{await this._transport.execute(Ss({method:"subscriber.offline",params:{}})),this._isRegistered$.next(!1)}catch(t){throw Y.error("[SignalWire] Failed to unregister user:",t),this._errors$.next(t instanceof Error?t:new Error(String(t),{cause:t})),t}}async dial(t,e={}){const i={...f.instance.preferredMediaOptions,...Lv(t),...e};await this.waitAuthentication(),Y.debug("[SignalWire] Dialing with options:",i);try{return await this._clientSession.createOutboundCall(t,i)}catch(r){if(!Nc(r)||(Y.debug("[SignalWire] Dial hit a recoverable auth error; recovering credential and retrying once"),!await this.recoverStaleCredential()))throw r;return await this.waitAuthentication(),this._clientSession.createOutboundCall(t,i)}}async preflight(t,e){const i=this._clientSession.iceServers??f.instance.iceServers??[],r=this._isConnected$.value;return new dg(this._deviceController,i,r,0,async(n,s)=>this.dial(n,s),e).run(t)}get session(){return this._publicSession}get audioInputDevices$(){return this.deferEmission(this._deviceController.audioInputDevices$)}get audioInputDevices(){return this._deviceController.audioInputDevices}get audioOutputDevices$(){return this.deferEmission(this._deviceController.audioOutputDevices$)}get audioOutputDevices(){return this._deviceController.audioOutputDevices}get videoInputDevices$(){return this.deferEmission(this._deviceController.videoInputDevices$)}get videoInputDevices(){return this._deviceController.videoInputDevices}get selectedAudioInputDevice$(){return this.deferEmission(this._deviceController.selectedAudioInputDevice$)}get selectedAudioOutputDevice$(){return this.deferEmission(this._deviceController.selectedAudioOutputDevice$)}get selectedVideoInputDevice$(){return this.deferEmission(this._deviceController.selectedVideoInputDevice$)}get selectedAudioInputDevice(){return this._deviceController.selectedAudioInputDevice}get selectedAudioOutputDevice(){return this._deviceController.selectedAudioOutputDevice}get selectedVideoInputDevice(){return this._deviceController.selectedVideoInputDevice}get selectedAudioInputDeviceConstraints(){return this._deviceController.selectedAudioInputDeviceConstraints}get selectedVideoInputDeviceConstraints(){return this._deviceController.selectedVideoInputDeviceConstraints}deviceInfoToConstraints(t){return this._deviceController.deviceInfoToConstraints(t)}selectAudioInputDevice(t){this._deviceController.selectAudioInputDevice(t)}selectVideoInputDevice(t){this._deviceController.selectVideoInputDevice(t)}selectAudioOutputDevice(t){this._deviceController.selectAudioOutputDevice(t)}async applySelectedAudioOutputDevice(t){const e=this._deviceController.selectedAudioOutputDevice;if(!(e!=null&&e.deviceId))return!1;const i=t;if(typeof i.setSinkId!="function")return Y.warn("[SignalWire] setSinkId not supported on this element / browser"),!1;try{return await i.setSinkId(e.deviceId),!0}catch(r){return Y.warn("[SignalWire] Failed to apply audio output device:",r),!1}}enableDeviceMonitoring(){this._deviceController.enableDeviceMonitoring()}disableDeviceMonitoring(){this._deviceController.disableDeviceMonitoring()}async getDeviceCapabilities(t){return this._deviceController.getDeviceCapabilities(t)}async isValidDevice(t){return this._deviceController.isValidDevice(t)}setStorageManager(t){this._deviceController.setStorageManager(t)}async clearDeviceState(){return this._deviceController.clearDeviceState()}async enumerateDevices(){return this._deviceController.enumerateDevices()}disableAudioInput(){this._deviceController.disableAudioInput()}enableAudioInput(){this._deviceController.enableAudioInput()}disableVideoInput(){this._deviceController.disableVideoInput()}enableVideoInput(){this._deviceController.enableVideoInput()}get videoInputDisabled$(){return this.deferEmission(this._deviceController.videoInputDisabled$)}get audioInputDisabled$(){return this.deferEmission(this._deviceController.audioInputDisabled$)}get videoInputDisabled(){return this._deviceController.videoInputDisabled}get audioInputDisabled(){return this._deviceController.audioInputDisabled}async requestMediaPermissions(t={audio:!0,video:!0}){const e={audio:t.audio??!1,video:t.video??!1};let i=!1,r=!1,n,s;try{const a=(await this._deps.webRTCApiProvider.mediaDevices.getUserMedia(e)).getTracks();for(const o of a){const c=o.getSettings();o.kind==="audio"?(i=!0,c.deviceId&&(n=this.audioInputDevices.find(u=>u.deviceId===c.deviceId))):o.kind==="video"&&(r=!0,c.deviceId&&(s=this.videoInputDevices.find(u=>u.deviceId===c.deviceId))),o.stop()}}catch(a){Y.warn("[SignalWire] Media permission request failed:",a)}if(await this._deviceController.enumerateDevices(),i&&n){const a=n.deviceId;n=this.audioInputDevices.find(o=>o.deviceId===a)??n}if(r&&s){const a=s.deviceId;s=this.videoInputDevices.find(o=>o.deviceId===a)??s}return i&&n&&!this.selectedAudioInputDevice&&this.selectAudioInputDevice(n),r&&s&&!this.selectedVideoInputDevice&&this.selectVideoInputDevice(s),{audio:i,video:r,selectedAudioDevice:n,selectedVideoDevice:s}}async resetToDefaults(){await this._deps.storage.clearAll();const t=f.instance;t.preferredAudioInput=null,t.preferredAudioOutput=null,t.preferredVideoInput=null,await this._deviceController.clearDeviceState()}destroy(){var e,i,r,n,s,a;(e=this._refreshCoordinator)==null||e.destroy(),this._refreshCoordinator=void 0,(i=this._dpopManager)==null||i.destroy();const t=this._clientSession;t==null||t.teardownSessionState(),(r=this._transport)==null||r.destroy(),t==null||t.destroy();try{(n=this._networkMonitor)==null||n.destroy()}catch{}try{(s=this._visibilityController)==null||s.destroy()}catch{}try{(a=this._diagnosticsCollector)==null||a.destroy()}catch{}this._networkMonitor=void 0,this._visibilityController=void 0,this._diagnosticsCollector=void 0,super.destroy()}};const Fv=G();var Bc=class{constructor(t,e){this.host=t,this.embedToken=e}async fetchSAT(){const t=`https://${this.host}/api/fabric/embeds/tokens`,e=1e4,i=new AbortController,r=setTimeout(()=>i.abort(),e);try{const n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:this.embedToken}),signal:i.signal});if(clearTimeout(r),n.ok)return(await n.json()).token;throw new ap(`Failed to fetch SAT using embed token: ${n.status} ${n.statusText}`)}catch(n){throw clearTimeout(r),n instanceof Error&&n.name==="AbortError"?new Oo(`Request timeout after ${e}ms`,{cause:n}):(Fv.error("[EmbedCredentialProvider] Request failed:",n),n)}}async authenticate(){return{token:await this.fetchSAT(),expiry_at:Date.now()+3600*1e3}}async refresh(){return this.authenticate()}},zc=class{constructor(t){this.credentials=t}async authenticate(){return Promise.resolve(this.credentials)}};(()=>{if(typeof window<"u"){const t=new CustomEvent("signalwire:js:ready",{detail:{version:"4.0.0-rc.2"}});window.dispatchEvent(t)}})();var Nv=Object.defineProperty,Uv=Object.getOwnPropertyDescriptor,Er=(t,e,i,r)=>{for(var n=r>1?void 0:r?Uv(e,i):e,s=t.length-1,a;s>=0;s--)(a=t[s])&&(n=(r?a(e,i,n):a(n))||n);return r&&n&&Nv(e,i,n),n};const Bv=G();l.SwCallMedia=class extends ee{constructor(){super(...arguments),this.stream=null,this._remoteStreamValue=null,this._lastTrackSignature="",this._subscriptions=[]}connectedCallback(){super.connectedCallback(),!this.stream&&this.call&&this._setupDirectSubscriptions(),this.stream&&(this._remoteStreamValue=this.stream,this._lastTrackSignature=this._computeTrackSignature(this.stream))}updated(e){var i,r,n,s,a;if(super.updated(e),e.has("call")&&(this._cleanupDirectSubscriptions(),!this.stream&&this.call&&this._setupDirectSubscriptions()),e.has("stream")){this._cleanupDirectSubscriptions();const o=this.stream,c=this._computeTrackSignature(o);if(o!==this._remoteStreamValue||c!==this._lastTrackSignature){this._remoteStreamValue=o,this._lastTrackSignature=c;const u=(i=this.shadowRoot)==null?void 0:i.querySelector("video.mcu-video");u&&Xr(u,o)}}if(!this.stream&&!this.call&&e.has("_callState")){const o=((r=this._callState)==null?void 0:r.remoteStream)??null,c=this._computeTrackSignature(o);if(o!==this._remoteStreamValue||c!==this._lastTrackSignature){this._remoteStreamValue=o,this._lastTrackSignature=c;const u=(n=this.shadowRoot)==null?void 0:n.querySelector("video.mcu-video");u&&Xr(u,o)}}e.has("_devicesState")&&this._applySinkId(((a=(s=this._devicesState)==null?void 0:s.selectedAudioOutput)==null?void 0:a.deviceId)??"")}disconnectedCallback(){super.disconnectedCallback(),this._cleanupDirectSubscriptions(),this._cleanupVideoElement()}_setupDirectSubscriptions(){this.call&&this._subscriptions.push(this.call.remoteStream$.subscribe(e=>{var n;const i=this._computeTrackSignature(e);if(e===this._remoteStreamValue&&i===this._lastTrackSignature)return;this._remoteStreamValue=e,this._lastTrackSignature=i,this.requestUpdate();const r=(n=this.shadowRoot)==null?void 0:n.querySelector("video.mcu-video");r&&Xr(r,e)}))}_computeTrackSignature(e){return e?e.getTracks().map(i=>`${i.kind}:${i.id}`).sort().join("|"):""}_cleanupDirectSubscriptions(){this._subscriptions.forEach(e=>e.unsubscribe()),this._subscriptions=[]}_applySinkId(e){var r;const i=(r=this.shadowRoot)==null?void 0:r.querySelector("video.mcu-video");i!=null&&i.setSinkId&&i.setSinkId(e).catch(n=>{Bv.error("[SwCallMedia] Failed to set audio output device:",n)})}_cleanupVideoElement(){var i;const e=(i=this.shadowRoot)==null?void 0:i.querySelector("video.mcu-video");e&&Ma(e)}render(){return I`
74
74
  <div class="mcu-content" part="container">
75
75
  <div class="padding-wrapper">
76
76
  <div class="mcu-wrapper">