@koi-design/callkit 2.0.5-beta.13 → 2.0.5-beta.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- var nt=Object.create;var w=Object.defineProperty;var st=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames;var ot=Object.getPrototypeOf,ct=Object.prototype.hasOwnProperty;var at=(s,t)=>{for(var e in t)w(s,e,{get:t[e],enumerable:!0})},J=(s,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of rt(t))!ct.call(s,n)&&n!==e&&w(s,n,{get:()=>t[n],enumerable:!(i=st(t,n))||i.enumerable});return s};var V=(s,t,e)=>(e=s!=null?nt(ot(s)):{},J(t||!s||!s.__esModule?w(e,"default",{value:s,enumerable:!0}):e,s)),lt=s=>J(w({},"__esModule",{value:!0}),s);var dt={};at(dt,{CallKit:()=>q});module.exports=lt(dt);var v=V(require("blueimp-md5"));var Y=V(require("axios")),j=Y.default.create({headers:{"Content-Type":"application/x-www-form-urlencoded"},timeout:6e4});j.interceptors.request.use(s=>s);j.interceptors.response.use(s=>s.data,s=>Promise.reject(s));var gt=s=>j.request(s),X=gt;var U=class{callKit;constructor(t){this.callKit=t}isLogining=!1;isLoginOuting=!1;async login(t){if(this.isLogining){this.callKit.logger.info("login is already in progress cancel",{caller:"Api.login",content:{userName:t.userName,timestamp:t.timestamp}});return}this.isLogining=!0;try{return await this.post({url:"/auth/agentUser/login",method:"post",data:t})}finally{this.isLogining=!1}}async loginOut(t){if(this.isLoginOuting){this.callKit.logger.info("loginOut is already in progress cancel",{caller:"Api.loginOut",content:{sessionId:t.sessionId,timestamp:t.timestamp}});return}this.isLoginOuting=!0;try{return await this.post({url:"/auth/agentUser/loginOut",method:"post",data:t})}finally{this.isLoginOuting=!1}}async trackLogs(t){return this.post({url:"/agent/user/sdkLog",method:"post",data:{content:[t]}},{useFormData:!0,skipLog:!0})}async updateUserStatus(t){return this.post({url:"/agent/user/changeStatus",method:"post",data:t})}async post(t,e={skipLog:!1}){let{userInfo:i,host:n}=this.callKit.config.getConfig(),{sessionId:l}=i;if(t.url=`${n}${t.url}`,t.headers={"Content-Type":"application/x-www-form-urlencoded",...t.headers},t.headers["Content-Type"]==="application/x-www-form-urlencoded"&&e.useFormData){let P=new FormData,K=t.data||{};for(let c in K)Object.prototype.hasOwnProperty.call(K,c)&&P.append(c,K[c]);t.data=P}else t.data=new URLSearchParams(t.data).toString();l&&(t.headers.sessionId=l);let o=Date.now();e.skipLog||this.callKit.logger.info("API Request Start",{type:"API",caller:"API.Request",content:{url:t.url,headers:t.headers,data:t.data,extra:e,startTime:o}});let C=await X(t).catch(()=>{this.callKit.config.reset()}),u=Date.now();if(e.skipLog||this.callKit.logger.info("API Request Finish",{type:"API",caller:"API.Request",content:{url:t.url,duration:`${u-o}ms`,response:C}}),!C)throw this.callKit.reset(),new Error("Network error");let{code:d,data:k,message:F}=C;if(d==="000000")return k;throw d==="100013"&&this.callKit.config.reset(),new Error(F??"Request failed")}};var f={init:0,connecting:2,ringing:4,calling:5},r={KIT_LOG:"log",KIT_USER_STATUS_CHANGE:"userStatusChange",KIT_LOGIN_CHANGE:"loginChange",KIT_REGISTER_CHANGE:"registerChange",KIT_CALL_STATUS_CHANGE:"callStatusChange",KIT_SET_HOLD:"holdChange",KIT_SET_MUTE:"muteChange",KIT_CALL_ID_CHANGE:"callIdChange",KIT_ERROR:"error",KIT_INVITE:"invite",KIT_OUTGOING_INVITE:"outgoingInvite",CALL_CONNECTING:"connecting",CALL_RINGING:"ringing",AGENT_PICK_UP:"agentPickUp",CALL_PICK_UP:"pickUp",CALL_NO_ANSWER:"noAnswer",CALL_HANG_UP:"hangUp",CALL_END:"callEnd",CALL_CDR:"callCdr",SERVER_SOCKET_EVENT:"socketEvent",USER_STATUS_CHANGE:"userStatusChange",INCALL_CONNECT_EVENT:"IncallConnectEvent",SIP_CONNECT_EVENT:"sipConnectEvent",SIP_REGISTERER_EVENT:"sipRegistererEvent",SIP_SESSION_EVENT:"sipSessionEvent"},a={UNKNOWN_ERROR:-1,API_USER_LOGIN_ERROR:1000001,API_USER_STATUS_UPDATE_ERROR:1000002,API_USER_LOGOUT_ERROR:1000003,CONNECT_CALL_STATUS_ERROR:2000001,USER_NOT_LOGIN:2000002,WEBRTC_USER_MEDIA_ERROR:2000003,WEBRTC_HOLE_STATUS_ERROR:2000004,WEBRTC_AUDIO_PLAYER_ERROR:2000005,WEBRTC_AUDIO_PLAY_ERROR:2000006,WEBRTC_USER_AGENT_ERROR:2000007,WEBRTC_CALL_INVITE_ERROR:2000008,WEBRTC_REGISTER_ERROR:2000009,WEBRTC_MUTE_STATUS_ERROR:2000010,WEBRTC_CANCEL_REGISTER_ERROR:2000011,WEBRTC_MUTE_ERROR:2000012,SOCKET_CONNECT_ERROR:3000001,SOCKET_PING_TIMEOUT:3000002,SOKET_SERVER_ERROR:3000003,SOCKET_CALL_ERROR:3000004,SOCKET_RECONNECT_FAILED:3000005},Z={info:9,success:4,warn:3,error:2,silent:1},R={PING:"PING",START:"START",AGENT_HANGUP:"AGENT_HANG_UP",CALL_CANCEL:"AGENT_CANCEL",HOLD:"AGENT_HOLD",UNHOLD:"AGENT_UN_HOLD",MUTE:"AGENT_MUTE",UNMUTE:"AGENT_UN_MUTE",CALL:"CALL",END:"STOP",AGENT_TRANSFER:"AGENT_TRANSFER",HANG_UP_REASON:"HANG_UP_REASON",ACK:"ACK"},S={PONG:"PONG",START_CONFIRM:"START_CONFIRM",CALL_SUCCESS:"CALL_SUCCESS",CALL_FAILED:"CALL_FAILED",CUSTOMER_RINGING:"CUSTOMER_RINGING",AGENT_PICK_UP:"AGENT_PICK_UP",CUSTOMER_PICK_UP:"CUSTOMER_PICK_UP",CUSTOMER_NO_ANSWER:"CUSTOMER_NO_ANSWER",CUSTOMER_HANG_UP:"CUSTOMER_HANG_UP",AGENT_NO_ANSWER:"AGENT_NO_ANSWER",AGENT_HANG_UP:"AGENT_HANG_UP",CALL_CDR:"CALL_CDR",STOP_CONFIRM:"STOP_CONFIRM",CLOSE:"CLOSE",ERROR:"ERROR",SESSION_ERROR:"SESSION_ERROR"},_={NONE:"NONE",INTERNAL:"INTERNAL"},G={audio:{autoGainControl:!0,noiseSuppression:!0,echoCancellation:!0},video:!1},m={phoneNum:1,workOrderId:2},L={enabled:!1,interval:5e3,maxSize:8192},A={enabled:!0,maxAttempts:3,delay:1e3,pingInterval:3e4,pingTimeout:5e3},O={enabled:!0,maxAttempts:3,delay:1e3};var b=class{callKit;constructor(t){this.callKit=t}async callStart(t){if(this.callKit.config.check()){if(this.callKit.logger.info("callStart",{caller:"Call.callStart",content:{startConfirm:this.callKit.socket.startConfirm}}),!this.callKit.socket.startConfirm){this.callKit.logger.warn("server not confirm start",{caller:"Call.callStart",content:{startConfirm:this.callKit.socket.startConfirm}});return}this.callKit.connect.call(async e=>{let i={...t?.extra||{},agentId:e.agentId,sourceType:e.sourceType};e.sourceType===m.phoneNum?i.phoneNum=e.extno:e.sourceType===m.workOrderId&&(i.workOrderId=e.workOrderId),this.callKit.socket.send(R.CALL,i)})}}async callRefer(t,e){this.callKit.config.check()&&(this.callKit.logger.info("callRefer",{caller:"Call.callRefer",content:{referTo:t,options:e}}),this.callKit.connect.refer(t,e))}async callEnd(t=!1,e=!1){this.callKit.connect.connectStatus!==f.init&&this.callKit.config.check()&&(this.callKit.logger.info("callEnd",{caller:"Call.callEnd",content:{isUnprompted:t,isError:e,connectStatus:this.callKit.connect.connectStatus}}),this.callKit.connect.hangup(t,e))}async callHold(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be held",{caller:"Call.callHold",content:{isHold:this.callKit.connect.isHolding(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setHold(!0)}}async callUnhold(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot unhold",{caller:"Call.callUnhold",content:{isHold:this.callKit.connect.isHolding(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setHold(!1)}}async callMute(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be muted",{caller:"Call.callMute",content:{isMuted:this.callKit.connect.isMuted(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setMute(!0)}}async callUnmute(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be unmuted",{caller:"Call.callUnmute",content:{isMuted:this.callKit.connect.isMuted(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setMute(!1)}}};var Q={name:"@koi-design/callkit",version:"2.0.5-beta.13",description:"callkit",author:"koi",license:"ISC",scripts:{build:"tsup",start:"vite",dev:"tsup --watch",lint:"eslint -c ../../.eslintrc.js --ext .jsx,.js,.tsx,.ts ./package --fix",release:"tsup && node scripts/pkg.js"},exports:{".":{types:"./dist/index.d.ts",require:"./dist/index.js",import:"./dist/index.mjs"}},main:"./dist/index.js",module:"./dist/index.mjs",types:"./dist/index.d.ts",files:["dist"],dependencies:{axios:"~0.26.1","blueimp-md5":"^2.12.0","eslint-plugin-jsonc":"^2.21.0","json-stringify-safe":"^5.0.1","sip.js":"^0.21.2"},devDependencies:{"@commitlint/cli":"^9.1.2","@commitlint/config-conventional":"^9.1.2","@koi-design/eslint-config-ts":"^0.0.14","@types/blueimp-md5":"^2.18.2",archiver:"^5.3.1",consola:"^3.4.2",eslint:"~8.29.0","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.0",husky:"^8.0.3","lint-staged":"^10.5.4",prettier:"^2.6.2",tsup:"6.6.3",typescript:"^4.6.3",vite:"^4"}};var M=class{callKit;constructor(t){this.callKit=t}config={version:`V${Q.version}`,host:"",log:"info",trackLogs:L,audioRef:void 0,constrains:G,socket:"",reconnect:{sip:O,incall:A},userInfo:{wsUrl:"",logGather:!1,sessionId:"",username:"",password:"",encryptionPassword:_.INTERNAL,sourceType:m.phoneNum,extno:"",workOrderId:"",userPart:"",agentId:"",fsUserId:"",fsPassword:"",fsIp:"",fsPort:"",iceInfo:[],iceGatheringTimeout:0,encryptionMethod:_.INTERNAL}};getConfig=()=>this.config;setConfig=async(t,e)=>{this.config[t]=e};setUserInfo=async(t,e)=>{this.config.userInfo[t]=e,this.callKit.logger.info("setUserInfo",{caller:"Config.setUserInfo",content:{key:t,value:e}})};reset=async()=>{this.isLogin()&&(this.config.userInfo={wsUrl:"",sessionId:"",username:"",password:"",encryptionPassword:"",userPart:"",sourceType:m.phoneNum,extno:"",workOrderId:"",agentId:"",fsUserId:"",fsPassword:"",fsIp:"",fsPort:"",iceInfo:[],iceGatheringTimeout:this.config.userInfo.iceGatheringTimeout,encryptionMethod:_.INTERNAL,logGather:!1},this.callKit.trigger(r.KIT_LOGIN_CHANGE,!1))};validate=()=>{let{userPart:t,fsIp:e,fsPassword:i,fsPort:n}=this.config.userInfo;return!(!t||!e||!n||!i)};isLogin=()=>this.validate();check(){return this.isLogin()?!0:(this.callKit.logger.warn("User not logged in",{caller:"Config.check",content:{errCode:a.USER_NOT_LOGIN}}),!1)}getTrackLogsConfig(){return{...L,...this.config?.trackLogs}}getReconnectConfig(t){return{...this.config?.reconnect?.[t]??(t==="sip"?O:A)}}enableTrackLogs(t){this.config.trackLogs.enabled=t}};var et=V(require("json-stringify-safe"));function y(s){return Z[s]}function ft(s){let{timestamp:t,level:e,type:i="OTHER",message:n,caller:l,content:o}=s,C=String(e).toUpperCase();return`${t} [${C}] [${i}] [${l??"unknown"}] [${n}] ${(0,et.default)(o)}`.trim()}function tt(s){return new Blob([s]).size}var D=class{prefix="CallKit";level="info";pendingTrackLogs=[];trackLogsTimer=null;callKit;constructor(t,e){this.callKit=t,this.level=e||"info",this.startTrackLogsTimer()}startTrackLogsTimer(){let{interval:t}=this.callKit.config.getTrackLogsConfig();this.trackLogsTimer||(this.trackLogsTimer=setInterval(()=>{this.flushTrackLogs()},t))}flushTrackLogs(){if(this.pendingTrackLogs.length===0)return;let{enabled:t,maxSize:e}=this.callKit.config.getTrackLogsConfig();if(t)try{let i=[],n=[],l=0;for(let o of this.pendingTrackLogs){let C=tt(o),u=n.length>0?`
1
+ var nt=Object.create;var w=Object.defineProperty;var st=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames;var ot=Object.getPrototypeOf,ct=Object.prototype.hasOwnProperty;var at=(s,t)=>{for(var e in t)w(s,e,{get:t[e],enumerable:!0})},Y=(s,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of rt(t))!ct.call(s,n)&&n!==e&&w(s,n,{get:()=>t[n],enumerable:!(i=st(t,n))||i.enumerable});return s};var V=(s,t,e)=>(e=s!=null?nt(ot(s)):{},Y(t||!s||!s.__esModule?w(e,"default",{value:s,enumerable:!0}):e,s)),lt=s=>Y(w({},"__esModule",{value:!0}),s);var dt={};at(dt,{CallKit:()=>z});module.exports=lt(dt);var v=V(require("blueimp-md5"));var X=V(require("axios")),j=X.default.create({headers:{"Content-Type":"application/x-www-form-urlencoded"},timeout:6e4});j.interceptors.request.use(s=>s);j.interceptors.response.use(s=>s.data,s=>Promise.reject(s));var gt=s=>j.request(s),B=gt;var U=class{callKit;constructor(t){this.callKit=t}isLogining=!1;isLoginOuting=!1;async login(t){if(this.isLogining){this.callKit.logger.info("login is already in progress cancel",{caller:"Api.login",content:{userName:t.userName,timestamp:t.timestamp}});return}this.isLogining=!0;try{return await this.post({url:"/auth/agentUser/login",method:"post",data:t})}finally{this.isLogining=!1}}async loginOut(t){if(this.isLoginOuting){this.callKit.logger.info("loginOut is already in progress cancel",{caller:"Api.loginOut",content:{sessionId:t.sessionId,timestamp:t.timestamp}});return}this.isLoginOuting=!0;try{return await this.post({url:"/auth/agentUser/loginOut",method:"post",data:t})}finally{this.isLoginOuting=!1}}async trackLogs(t){try{let{userInfo:e,host:i}=this.callKit.config.getConfig(),{sessionId:n}=e,l=new FormData;l.append("content",JSON.stringify([t]));let o={url:`${i}/agent/user/sdkLog`,method:"post",data:l,headers:{...n?{sessionId:n}:{}}};await B(o).catch(()=>{})}catch{}}async updateUserStatus(t){return this.post({url:"/agent/user/changeStatus",method:"post",data:t})}async post(t,e={skipLog:!1}){let{userInfo:i,host:n}=this.callKit.config.getConfig(),{sessionId:l}=i;if(t.url=`${n}${t.url}`,t.headers={"Content-Type":"application/x-www-form-urlencoded",...t.headers},t.headers["Content-Type"]==="application/x-www-form-urlencoded"&&e.useFormData){let P=new FormData,K=t.data||{};for(let c in K)Object.prototype.hasOwnProperty.call(K,c)&&P.append(c,K[c]);t.data=P}else t.data=new URLSearchParams(t.data).toString();l&&(t.headers.sessionId=l);let o=Date.now();e.skipLog||this.callKit.logger.info("API Request Start",{type:"API",caller:"API.Request",content:{url:t.url,headers:t.headers,data:t.data,extra:e,startTime:o}});let C=await B(t).catch(()=>{this.callKit.config.reset("api request error")}),u=Date.now();if(e.skipLog||this.callKit.logger.info("API Request Finish",{type:"API",caller:"API.Request",content:{url:t.url,duration:`${u-o}ms`,response:C}}),!C)throw this.callKit.reset(),new Error("Network error");let{code:d,data:k,message:F}=C;if(d==="000000")return k;throw d==="100013"&&this.callKit.config.reset("api request error"),new Error(F??"Request failed")}};var f={init:0,connecting:2,ringing:4,calling:5},r={KIT_LOG:"log",KIT_USER_STATUS_CHANGE:"userStatusChange",KIT_LOGIN_CHANGE:"loginChange",KIT_REGISTER_CHANGE:"registerChange",KIT_CALL_STATUS_CHANGE:"callStatusChange",KIT_SET_HOLD:"holdChange",KIT_SET_MUTE:"muteChange",KIT_CALL_ID_CHANGE:"callIdChange",KIT_ERROR:"error",KIT_INVITE:"invite",KIT_OUTGOING_INVITE:"outgoingInvite",CALL_CONNECTING:"connecting",CALL_RINGING:"ringing",AGENT_PICK_UP:"agentPickUp",CALL_PICK_UP:"pickUp",CALL_NO_ANSWER:"noAnswer",CALL_HANG_UP:"hangUp",CALL_END:"callEnd",CALL_CDR:"callCdr",SERVER_SOCKET_EVENT:"socketEvent",USER_STATUS_CHANGE:"userStatusChange",INCALL_CONNECT_EVENT:"IncallConnectEvent",SIP_CONNECT_EVENT:"sipConnectEvent",SIP_REGISTERER_EVENT:"sipRegistererEvent",SIP_SESSION_EVENT:"sipSessionEvent"},a={UNKNOWN_ERROR:-1,API_USER_LOGIN_ERROR:1000001,API_USER_STATUS_UPDATE_ERROR:1000002,API_USER_LOGOUT_ERROR:1000003,CONNECT_CALL_STATUS_ERROR:2000001,USER_NOT_LOGIN:2000002,WEBRTC_USER_MEDIA_ERROR:2000003,WEBRTC_HOLE_STATUS_ERROR:2000004,WEBRTC_AUDIO_PLAYER_ERROR:2000005,WEBRTC_AUDIO_PLAY_ERROR:2000006,WEBRTC_USER_AGENT_ERROR:2000007,WEBRTC_CALL_INVITE_ERROR:2000008,WEBRTC_REGISTER_ERROR:2000009,WEBRTC_MUTE_STATUS_ERROR:2000010,WEBRTC_CANCEL_REGISTER_ERROR:2000011,WEBRTC_MUTE_ERROR:2000012,SOCKET_CONNECT_ERROR:3000001,SOCKET_PING_TIMEOUT:3000002,SOKET_SERVER_ERROR:3000003,SOCKET_CALL_ERROR:3000004,SOCKET_RECONNECT_FAILED:3000005},Z={info:9,success:4,warn:3,error:2,silent:1},R={PING:"PING",START:"START",AGENT_HANGUP:"AGENT_HANG_UP",CALL_CANCEL:"AGENT_CANCEL",HOLD:"AGENT_HOLD",UNHOLD:"AGENT_UN_HOLD",MUTE:"AGENT_MUTE",UNMUTE:"AGENT_UN_MUTE",CALL:"CALL",END:"STOP",AGENT_TRANSFER:"AGENT_TRANSFER",HANG_UP_REASON:"HANG_UP_REASON",ACK:"ACK"},S={PONG:"PONG",START_CONFIRM:"START_CONFIRM",CALL_SUCCESS:"CALL_SUCCESS",CALL_FAILED:"CALL_FAILED",CUSTOMER_RINGING:"CUSTOMER_RINGING",AGENT_PICK_UP:"AGENT_PICK_UP",CUSTOMER_PICK_UP:"CUSTOMER_PICK_UP",CUSTOMER_NO_ANSWER:"CUSTOMER_NO_ANSWER",CUSTOMER_HANG_UP:"CUSTOMER_HANG_UP",AGENT_NO_ANSWER:"AGENT_NO_ANSWER",AGENT_HANG_UP:"AGENT_HANG_UP",CALL_CDR:"CALL_CDR",STOP_CONFIRM:"STOP_CONFIRM",CLOSE:"CLOSE",ERROR:"ERROR",SESSION_ERROR:"SESSION_ERROR"},_={NONE:"NONE",INTERNAL:"INTERNAL"},G={audio:{autoGainControl:!0,noiseSuppression:!0,echoCancellation:!0},video:!1},m={phoneNum:1,workOrderId:2},L={enabled:!1,interval:5e3,maxSize:8192},A={enabled:!0,maxAttempts:3,delay:1e3,pingInterval:3e4,pingTimeout:5e3},O={enabled:!0,maxAttempts:3,delay:1e3};var b=class{callKit;constructor(t){this.callKit=t}async callStart(t){if(this.callKit.config.check()){if(this.callKit.logger.info("callStart",{caller:"Call.callStart",content:{startConfirm:this.callKit.socket.startConfirm}}),!this.callKit.socket.startConfirm){this.callKit.logger.warn("server not confirm start",{caller:"Call.callStart",content:{startConfirm:this.callKit.socket.startConfirm}});return}this.callKit.connect.call(async e=>{let i={...t?.extra||{},agentId:e.agentId,sourceType:e.sourceType};e.sourceType===m.phoneNum?i.phoneNum=e.extno:e.sourceType===m.workOrderId&&(i.workOrderId=e.workOrderId),this.callKit.socket.send(R.CALL,i)})}}async callRefer(t,e){this.callKit.config.check()&&(this.callKit.logger.info("callRefer",{caller:"Call.callRefer",content:{referTo:t,options:e}}),this.callKit.connect.refer(t,e))}async callEnd(t=!1,e=!1){this.callKit.connect.connectStatus!==f.init&&this.callKit.config.check()&&(this.callKit.logger.info("callEnd",{caller:"Call.callEnd",content:{isUnprompted:t,isError:e,connectStatus:this.callKit.connect.connectStatus}}),this.callKit.connect.hangup(t,e))}async callHold(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be held",{caller:"Call.callHold",content:{isHold:this.callKit.connect.isHolding(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setHold(!0)}}async callUnhold(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot unhold",{caller:"Call.callUnhold",content:{isHold:this.callKit.connect.isHolding(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setHold(!1)}}async callMute(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be muted",{caller:"Call.callMute",content:{isMuted:this.callKit.connect.isMuted(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setMute(!0)}}async callUnmute(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be unmuted",{caller:"Call.callUnmute",content:{isMuted:this.callKit.connect.isMuted(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setMute(!1)}}};var Q={name:"@koi-design/callkit",version:"2.0.5-beta.15",description:"callkit",author:"koi",license:"ISC",scripts:{build:"tsup",start:"vite",dev:"tsup --watch",lint:"eslint -c ../../.eslintrc.js --ext .jsx,.js,.tsx,.ts ./package --fix",release:"tsup && node scripts/pkg.js"},exports:{".":{types:"./dist/index.d.ts",require:"./dist/index.js",import:"./dist/index.mjs"}},main:"./dist/index.js",module:"./dist/index.mjs",types:"./dist/index.d.ts",files:["dist"],dependencies:{axios:"~0.26.1","blueimp-md5":"^2.12.0","eslint-plugin-jsonc":"^2.21.0","json-stringify-safe":"^5.0.1","sip.js":"^0.21.2"},devDependencies:{"@commitlint/cli":"^9.1.2","@commitlint/config-conventional":"^9.1.2","@koi-design/eslint-config-ts":"^0.0.14","@types/blueimp-md5":"^2.18.2",archiver:"^5.3.1",consola:"^3.4.2",eslint:"~8.29.0","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.0",husky:"^8.0.3","lint-staged":"^10.5.4",prettier:"^2.6.2",tsup:"6.6.3",typescript:"^4.6.3",vite:"^4"}};var M=class{callKit;constructor(t){this.callKit=t}config={version:`V${Q.version}`,host:"",log:"info",trackLogs:L,audioRef:void 0,constrains:G,socket:"",reconnect:{sip:O,incall:A},userInfo:{wsUrl:"",logGather:!1,sessionId:"",username:"",password:"",encryptionPassword:_.INTERNAL,sourceType:m.phoneNum,extno:"",workOrderId:"",userPart:"",agentId:"",fsUserId:"",fsPassword:"",fsIp:"",fsPort:"",iceInfo:[],iceGatheringTimeout:0,encryptionMethod:_.INTERNAL}};getConfig=()=>this.config;setConfig=async(t,e)=>{this.config[t]=e};setUserInfo=async(t,e)=>{this.config.userInfo[t]=e,this.callKit.logger.info("setUserInfo",{caller:"Config.setUserInfo",content:{key:t,value:e}})};reset=async t=>{this.callKit.logger.info(`Reset User Info ${t}`,{caller:"Config.reset",type:"OTHER",content:{}}),this.isLogin()&&(this.config.userInfo={wsUrl:"",sessionId:"",username:"",password:"",encryptionPassword:"",userPart:"",sourceType:m.phoneNum,extno:"",workOrderId:"",agentId:"",fsUserId:"",fsPassword:"",fsIp:"",fsPort:"",iceInfo:[],iceGatheringTimeout:this.config.userInfo.iceGatheringTimeout,encryptionMethod:_.INTERNAL,logGather:!1},this.callKit.trigger(r.KIT_LOGIN_CHANGE,!1))};validate=()=>{let{userPart:t,fsIp:e,fsPassword:i,fsPort:n}=this.config.userInfo;return!(!t||!e||!n||!i)};isLogin=()=>this.validate();check(){return this.isLogin()?!0:(this.callKit.logger.warn("User not logged in",{caller:"Config.check",content:{errCode:a.USER_NOT_LOGIN}}),!1)}getTrackLogsConfig(){return{...L,...this.config?.trackLogs}}getReconnectConfig(t){return{...this.config?.reconnect?.[t]??(t==="sip"?O:A)}}enableTrackLogs(t){this.config.trackLogs.enabled=t}};var et=V(require("json-stringify-safe"));function y(s){return Z[s]}function ft(s){let{timestamp:t,level:e,type:i="OTHER",message:n,caller:l,content:o}=s,C=String(e).toUpperCase();return`${t} [${C}] [${i}] [${l??"unknown"}] [${n}] ${(0,et.default)(o)}`.trim()}function tt(s){return new Blob([s]).size}var D=class{prefix="CallKit";level="info";pendingTrackLogs=[];trackLogsTimer=null;callKit;constructor(t,e){this.callKit=t,this.level=e||"info",this.startTrackLogsTimer()}startTrackLogsTimer(){let{interval:t}=this.callKit.config.getTrackLogsConfig();this.trackLogsTimer||(this.trackLogsTimer=setInterval(()=>{this.flushTrackLogs()},t))}flushTrackLogs(){if(this.pendingTrackLogs.length===0)return;let{enabled:t,maxSize:e}=this.callKit.config.getTrackLogsConfig();if(t)try{let i=[],n=[],l=0;for(let o of this.pendingTrackLogs){let C=tt(o),u=n.length>0?`
2
2
  `:"",d=tt(u);l+C+d>e&&n.length>0?(i.push(n.join(`
3
3
  `)),n=[o],l=C):(n.push(o),l+=C+d)}n.length>0&&i.push(n.join(`
4
- `));for(let o of i)this.callKit.api.trackLogs(o);this.pendingTrackLogs=[]}catch(i){console.error(i)}}destroy(){this.trackLogsTimer&&(clearInterval(this.trackLogsTimer),this.trackLogsTimer=null),this.flushTrackLogs()}setLevel(t){this.level=t}info(t,e){let i=this.catchLog(t,e,"info");y(this.level)>=y("info")&&console.log(`%c${i}`,"color: gray;")}success(t,e){let i=this.catchLog(t,e,"success");y(this.level)>=y("success")&&console.log(`%c${i}`,"color: green;")}warn(t,e){let i=this.catchLog(t,e,"warn");y(this.level)>=y("warn")&&console.log(`%c${i}`,"color: orange;")}error(t,e,i=!1){let n=t instanceof Error?t.message:t,l=this.catchLog(n,e,"error");y(this.level)>=y("error")&&console.log(`%c${l}`,"color: red;");let{errCode:o,...C}=e?.content??{},u=o??a.UNKNOWN_ERROR;i||this.callKit.trigger(r.KIT_ERROR,{code:u,msg:n,data:C});let d=new Error(n);throw d.name="CallKitError",d.code=u,d.data=C,d}catchLog(t,e,i){let n=new Date,{enabled:l}=this.callKit.config.getTrackLogsConfig(),{userInfo:o}=this.callKit.config.getConfig(),C={agentId:o?.agentId,sessionId:o?.sessionId,...e?.content??{}},u={timestamp:n.toLocaleString().replace("T"," ").replace(".000Z",""),level:i,message:t,caller:e?.caller,type:e?.type,content:C},d=ft(u);return l&&this.pendingTrackLogs.push(d),this.callKit.trigger(r.KIT_LOG,d,!0),d}};var g=require("sip.js");var it=s=>{let t=s["x-antaios-manual-extend_info"]||s["x-antaios-manual-extend-info"],e=null;try{if(t&&typeof t=="string"){let i=t.replace(/\\/g,"");return e=JSON.parse(i),e}}catch{return{}}};var x=6;function Ct(s){return s.replace(/(\w+):\s*'(.*?)'/g,'"$1": "$2"').replace(/'/g,'"')}var B=s=>{s&&s.getTracks().forEach(t=>t.stop())},ut=()=>{typeof navigator.mediaDevices>"u"&&(navigator.mediaDevices={}),typeof navigator.mediaDevices.getUserMedia>"u"&&(navigator.mediaDevices.getUserMedia=s=>{let t=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia;return t?new Promise((e,i)=>{t.call(navigator,s,e,i)}):Promise.reject(new Error("Unable to obtain device permissions. Please check your browser settings or device permissions."))})},H=class{callKit;isMute=!1;isRegister=!1;isHold=!1;connectStatus=f.init;currentSession;mediaStream;userAgent;registerer;isReConnected=!1;isOutgoing=!1;isUnprompted=!1;hasInvite=!1;constructor(t){this.callKit=t}get reconnectConfig(){return this.callKit.config.getReconnectConfig("sip")}currentCallId=null;getCurrentCallId(){return this.currentCallId}setOutgoing(t){this.isOutgoing!==t&&(this.callKit.logger.info("setOutgoing",{caller:"Connect.setOutgoing",content:{outgoing:t}}),this.isOutgoing=t)}setCallId(t){this.callKit.logger.info("setCallId",{caller:"Connect.setCallId",content:{callId:t}}),this.currentCallId=t,this.callKit.trigger(r.KIT_CALL_ID_CHANGE,t)}async reset(){if(this.setOutgoing(!1),this.isUnprompted=!1,this.hasInvite=!1,this.isHolding()&&await this.setHold(!1),this.isMuted()&&await this.setMute(!1),this.connectStatus!==f.init&&this.setConnectStatus(f.init),this.isRegistered()&&await this.unregister(),this.currentCallId&&this.setCallId(null),this.currentSession=void 0,this.mediaStream=void 0,this.userAgent=void 0,this.registerer=void 0,this.mediaStream)try{B(this.mediaStream);let t=this.getAduioReference();t&&(t.pause(),t.srcObject=null)}catch(t){this.callKit.logger.error(t,{caller:"Connect.reset",content:{}})}this.setConnectStatus(f.init),this.clearHeartbeat()}getAduioReference(){let{audioRef:t}=this.callKit.config.getConfig();return typeof t=="function"?t():t}async permission(){this.callKit.logger.info("permission",{caller:"Connect.permission",content:{permission:!0}}),ut();let t=await navigator.mediaDevices.getUserMedia({audio:!0});B(t)}isConnecting(){return this.connectStatus===f.connecting}isCalling(){return this.connectStatus===f.calling}isRinging(){return this.connectStatus===f.ringing}isHolding(){return this.isHold}isRegistered(){return this.isRegister}isMuted(){return this.isMute}isInit(){return this.connectStatus===f.init}heartbeatInterval;heartbeatFlag=x;clearHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null),this.heartbeatFlag=x}startHeartbeat(){this.heartbeatFlag=x,this.clearHeartbeat(),this.heartbeatInterval=setInterval(()=>{this.heartbeatFlag-=1,this.heartbeatFlag<=0&&(this.heartbeatFlag=x,this.callKit.trigger(r.SIP_CONNECT_EVENT,{event:"OPTIONS_HEARTBEAT_EXPIRED"}))},1e3)}socketTriggerHangup(t){!this.isCalling()||t!==this.currentCallId||(this.callKit.logger.info("socketHangup trigger hangup",{caller:"Connect.socketHangup",content:{callId:t,currentCallId:this.currentCallId}}),this.callKit.hangup())}async register(){if(this.connectStatus!==f.init){if(this.isRegistered()){this.callKit.logger.warn("connectStatus is registered",{caller:"Connect.register",content:{errCode:a.CONNECT_CALL_STATUS_ERROR}});return}this.callKit.reset(),this.callKit.logger.error("connectStatus is not init",{caller:"Connect.register",content:{errCode:a.CONNECT_CALL_STATUS_ERROR}});return}this.callKit.logger.info("connect register",{caller:"Connect.register",content:{connectStatus:this.connectStatus}}),await this.permission().catch(c=>{this.callKit.reset(),this.callKit.logger.error(c,{caller:"Connect.register",content:{errCode:a.WEBRTC_USER_MEDIA_ERROR}})});let{userInfo:t,constrains:e}=this.callKit.config.getConfig(),i=async()=>(this.mediaStream=await navigator.mediaDevices.getUserMedia(e),this.mediaStream),{userPart:n,fsIp:l,fsPort:o,iceInfo:C,wsUrl:u}=t,d={uri:g.UserAgent.makeURI(`sip:${n}@${l}:${o}`),displayName:n,transportOptions:{wsServers:[u],traceSip:!0},logLevel:"error",allowLegacyNotifications:!0,contactName:n,sessionDescriptionHandlerFactory:g.Web.defaultSessionDescriptionHandlerFactory(i),sessionDescriptionHandlerFactoryOptions:{constraints:e,iceGatheringTimeout:t.iceGatheringTimeout,peerConnectionConfiguration:{iceServers:JSON.parse(Ct(C))}}};this.callKit.logger.info("connect connectConfig",{caller:"Connect.register",content:d}),this.userAgent=new g.UserAgent(d);let k=new MediaStream,F=c=>{let I=this.getAduioReference();this.callKit.logger.info("connect setupRemoteMedia",{caller:"Connect.register.setupRemoteMedia",content:I}),c.sessionDescriptionHandler.peerConnection.getReceivers().forEach(E=>{E.track&&k.addTrack(E.track)}),I?(I.srcObject=k,I.play().catch(E=>{this.callKit.logger.error(E.message,{caller:"Connect.register.setupRemoteMedia",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})})):this.callKit.logger.error("video is not exist",{caller:"Connect.register",content:{errCode:a.WEBRTC_AUDIO_PLAYER_ERROR}})},P=(c,I)=>{let{that:E=this}=I,T=c.userAgentCore,h=T.receiveIncomingRequestFromTransport.bind(T);T.receiveIncomingRequestFromTransport=p=>(p.method==="OPTIONS"&&E.startHeartbeat(),E.callKit.logger.info(`SIP Receive: ${p?.method}`,{caller:"Connect.register.observeSocketStatus.receiveRequest",type:"SIP",content:{request:p}}),h(p));let $=T.receiveIncomingResponseFromTransport.bind(T);T.receiveIncomingResponseFromTransport=p=>(E.callKit.logger.info(`SIP Receive Response: ${p?.statusCode} ${p?.reasonPhrase}`,{caller:"Connect.register.observeSocketStatus.receiveResponse",type:"SIP",content:{response:p}}),$(p));let{transport:N}=c;if(N){let p=N.send.bind(N);N.send=z=>(E.callKit.logger.info("SIP send message",{caller:"Connect.register.observeSocketStatus",type:"SIP",content:{message:z.toString()}}),p(z))}},K={};this.registerer=new g.Registerer(this.userAgent,K),this.registerer.stateChange.addListener(c=>{switch(c){case g.RegistererState.Initial:this.callKit.logger.info("registerer stateChange Initial",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!1),this.setConnectStatus(f.init),this.callKit.trigger(r.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case g.RegistererState.Registered:this.callKit.logger.info("registerer stateChange Registered",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!0),this.callKit.trigger(r.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case g.RegistererState.Terminated:this.callKit.logger.info("registerer stateChange Terminated",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!1),this.setConnectStatus(f.init),this.callKit.trigger(r.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case g.RegistererState.Unregistered:this.callKit.logger.info("registerer stateChange Unregistered",{caller:"Connect.register.registererStateChange",type:"SIP",content:{isRegistered:this.isRegistered(),registererState:c}}),this.setRegister(!1),this.setConnectStatus(f.init),this.callKit.trigger(r.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;default:break}}),this.userAgent.delegate={onInvite:c=>{this.callKit.logger.info("connect onInvite",{type:"SIP",caller:"Connect.register.onInvite",content:{invite:c,isRegistered:this.isRegistered(),isOutgoing:this.isOutgoing}}),this.currentSession=c,this.currentSession.stateChange.addListener(h=>{switch(h){case g.SessionState.Establishing:this.callKit.logger.info("connect Establishing",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:h}}),this.setConnectStatus(f.ringing),this.callKit.trigger(r.SIP_SESSION_EVENT,{sessionState:h,isRegistered:this.isRegistered()});break;case g.SessionState.Established:this.callKit.logger.info("connect Established",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:h}}),this.callKit.connect.setConnectStatus(f.calling),this.callKit.trigger(r.SIP_SESSION_EVENT,{sessionState:h,isRegistered:this.isRegistered()}),F(this.currentSession);break;case g.SessionState.Terminating:this.callKit.trigger(r.SIP_SESSION_EVENT,{sessionState:h,isRegistered:this.isRegistered()});break;case g.SessionState.Terminated:this.callKit.logger.info("connect Terminated",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:h}}),this.hasInvite=!1,this.isUnprompted||this.callKit.callCenter.callEnd(),this.isUnprompted=!1,this.callKit.trigger(r.SIP_SESSION_EVENT,{sessionState:h,isRegistered:this.isRegistered()});break;default:break}});let I={sessionDescriptionHandlerOptions:{constraints:e,alwaysAcquireMediaFirst:!0}},E=()=>{let{request:h}=this.currentSession,$=Object.keys(h.headers),N={};return $.filter(p=>p.toLocaleLowerCase().startsWith("x-antaios")).forEach(p=>{N[p.toLocaleLowerCase()]=h.getHeader(p)}),this.callKit.logger.info("get invite data",{caller:"Connect.register.onInvite",content:N}),N},T=E();try{let h=it(T);h?.callUuid?this.setCallId(h.callUuid):(this.setCallId(null),this.callKit.logger.warn("call id is not exist",{caller:"Connect.register.onInvite",content:{inviteData:h}}))}catch(h){this.callKit.logger.info(h,{caller:"Connect.register.onInvite",content:T})}if(this.isOutgoing)this.currentSession.accept(I),this.callKit.trigger(r.KIT_OUTGOING_INVITE,{getInviteData:E});else{this.hasInvite=!0;let h=()=>{this.currentSession?.state!==g.SessionState.Terminated&&this.currentSession?.state!==g.SessionState.Terminating&&this.currentSession.reject(),this.hasInvite=!1,this.callKit.callCenter.callEnd(!0,!1)};this.callKit.trigger(r.KIT_INVITE,{accept:()=>{this.callKit.trigger(r.CALL_CONNECTING,new Date),this.hasInvite=!1,this.currentSession.accept(I)},reject:h,getInviteData:E})}},onConnect:async()=>{this.reconnectAttempts=0,this.reconnectTimer=null,this.callKit.logger.info("connect onConnect",{caller:"Connect.register",type:"SIP",content:{version:`${this.callKit.config.getConfig().version}`}}),await this.registerer.register().catch(async c=>{this.callKit.reset(),this.callKit.logger.error(c?.message,{caller:"Connect.register",type:"SIP",content:{errCode:a.WEBRTC_REGISTER_ERROR}})})},onDisconnect:c=>{c?(this.callKit.logger.warn("SIP User Agent Disconnected with error",{caller:"Connect.register",type:"SIP",content:{err:c.message,errCode:a.WEBRTC_USER_AGENT_ERROR}}),this.startReconnectTimer()):this.callKit.logger.warn("SIP User Agent Disconnected",{caller:"Connect.register",type:"SIP",content:{}})},onRegister:()=>{this.callKit.logger.info("connect onRegister",{caller:"Connect.register",type:"SIP",content:{version:`V${this.callKit.config.getConfig().version}`}})}},P(this.userAgent,{that:this}),await this.userAgent.start().catch(c=>{this.callKit.reset(),this.callKit.logger.error(c,{caller:"Connect.register",type:"SIP",content:{errCode:a.WEBRTC_USER_AGENT_ERROR}})})}reconnectTimer;reconnectAttempts=0;startReconnectTimer(){if(this.reconnectAttempts>=this.reconnectConfig.maxAttempts&&this.callKit.config.isLogin()){this.callKit.reset(),this.callKit.logger.error("Reconnect failed max attempts",{caller:"Connect.startReconnectTimer",type:"SIP",content:{errCode:a.SOCKET_RECONNECT_FAILED,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}});return}this.callKit.logger.info("Reconnect timer started",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}}),this.reconnectAttempts+=1,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer&&this.callKit.config.isLogin()?(this.userAgent?.reconnect(),this.callKit.logger.info("Reconnect attempt",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}})):this.callKit.logger.info("Reconnect timer already expired",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}})},this.reconnectConfig.delay)}async stop(){await this.userAgent.stop()}async unregister(){if(this.callKit.logger.info("connect unregister",{caller:"Connect.unregister",type:"SIP",content:{isRegistered:this.isRegistered()}}),!this.isRegistered()||!this.registerer){this.callKit.logger.warn("No registerer to unregister.",{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}});return}await this.registerer.unregister({all:!0}).catch(t=>{this.callKit.logger.warn(t,{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}})}).finally(()=>{this.setRegister(!1)}),await this.userAgent?.stop().catch(t=>{this.callKit.logger.warn(t,{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}})})}async call(t){this.callKit.logger.info("connect call",{caller:"Connect.call",type:"SIP",content:{callback:t}}),this.setOutgoing(!0),this.isRegistered()||await this.register(),this.setConnectStatus(f.connecting),this.callKit.trigger(r.CALL_CONNECTING,new Date);let{userInfo:e}=this.callKit.config.getConfig();t(e)}setRegister(t){this.isRegister!==t&&(this.callKit.logger.info("connect setRegister",{caller:"Connect.setRegister",type:"SIP",content:{register:t}}),this.isRegister=t,this.callKit.trigger(r.KIT_REGISTER_CHANGE,t))}setConnectStatus(t){this.callKit.logger.info("connect setConnectStatus",{caller:"Connect.setConnectStatus",type:"SIP",content:{status:t}}),this.connectStatus=t,this.callKit.trigger(r.KIT_CALL_STATUS_CHANGE,t)}async hangup(t=!1,e=!1){if(this.callKit.logger.info("connect hangup",{caller:"Connect.hangup",type:"SIP",content:{isUnprompted:t,isError:e,connectStatus:this.connectStatus}}),this.setOutgoing(!1),this.isUnprompted=t,this.setHold(!1),this.setMute(!1),this.connectStatus!==f.init)try{t&&(this.isRinging()||this.isCalling())&&(this.hasInvite?(this.currentSession?.state!==g.SessionState.Terminated&&this.currentSession?.state!==g.SessionState.Terminating&&this.currentSession.reject(),this.hasInvite=!1):await this.currentSession?.bye()),B(this.mediaStream);let i=this.getAduioReference();i&&(i.pause(),i.srcObject=null),this.setConnectStatus(f.init),this.callKit.trigger(r.CALL_END,new Date),this.setCallId(null)}catch(i){this.callKit.trigger(r.CALL_END,new Date),this.callKit.reset(),this.callKit.logger.error(i,{caller:"Connect.hangup",type:"SIP",content:{connectStatus:this.connectStatus,isError:e,isUnprompted:t}})}}getRemoteMediaStream(t){this.callKit.logger.info("connect getRemoteMediaStream",{caller:"Connect.getRemoteMediaStream",type:"SIP",content:{session:t}});let e=t.sessionDescriptionHandler;if(e)return e.remoteMediaStream}setupRemoteMedia(t){this.callKit.logger.info("connect setupRemoteMedia",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{session:t}});let e=this.getRemoteMediaStream(t),i=this.getAduioReference();i?(i.autoplay=!0,i.srcObject=e,i.play().catch(n=>{this.callKit.logger.error(n.message,{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})}),e.onaddtrack=()=>{this.callKit.logger.info("Remote media onaddtrack",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{session:t}}),i.load(),i.play().catch(n=>{this.callKit.logger.error(n.message,{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})})}):this.callKit.logger.error("video is not exist",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAYER_ERROR}})}async setHold(t){if(this.isHold===t){this.callKit.logger.warn("Already holding",{caller:"Connect.setHold",type:"SIP",content:{isHold:this.isHold}});return}this.callKit.socket.send(t?R.HOLD:R.UNHOLD),this.isHold=t,this.callKit.logger.info("connect setHold",{caller:"Connect.setHold",type:"SIP",content:{hold:t}}),this.callKit.trigger(r.KIT_SET_HOLD,t)}async setMute(t){if(this.isMute===t){this.callKit.logger.warn("Already muted",{caller:"Connect.setMute",type:"SIP",content:{isCalling:this.isCalling(),isMuted:this.isMuted()}});return}this.callKit.socket.send(t?R.MUTE:R.UNMUTE),this.isMute=t,this.callKit.trigger(r.KIT_SET_MUTE,t)}async refer(t,e){this.callKit.logger.info("connect refer",{caller:"Connect.refer",type:"SIP",content:{referTo:t,extra:e}});let i;t&&(i=g.UserAgent.makeURI(t)),this.currentSession.refer(i,e?.sessionReferOptions)}};var W=class{callKit;ws;lastPingTime=void 0;pingTimer;reconnectTimer;reconnectAttempts=0;connectAuthState={startConfirm:!1,isConnected:!1,isReconnecting:!1,isError:!1};get startConfirm(){return this.connectAuthState.startConfirm}get isError(){return this.connectAuthState.isError}constructor(t){this.callKit=t}get reconnectConfig(){return this.callKit.config.getReconnectConfig("incall")}init(){let{socket:t}=this.callKit.config.getConfig();this.callKit.logger.info(`socket init: ${t}`,{caller:"Socket.init",type:"INCALL",content:{socket:t}}),this.connect(t)}setConnectAuthState(t,e){this.connectAuthState[t]!==e&&(this.connectAuthState[t]=e)}handleDisconnect(){this.setConnectAuthState("isConnected",!1);let{enabled:t}=this.reconnectConfig;if(!this.callKit.config.isLogin()||!t){this.callKit.reset(),this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_NOT_CONNECTED"});return}this.connectAuthState.isReconnecting||this.connectAuthState.isError||this.attemptReconnect()}clearWebSocket(){this.ws&&(this.ws.onopen=null,this.ws.onclose=null,this.ws.onerror=null,this.ws.onmessage=null),(this.ws?.readyState===WebSocket.CONNECTING||this.ws?.readyState===WebSocket.OPEN)&&(this.ws?.close(1e3,"socket close"),this.callKit.logger.info("socket clear",{caller:"Socket.clearWebSocket",type:"INCALL",content:{}})),this.ws=void 0,this.setConnectAuthState("isConnected",!1)}connect(t){this.ws&&this.clearWebSocket(),this.ws=new WebSocket(t),this.ws.onopen=e=>this.onOpen(e),this.ws.onclose=e=>this.onClose(e),this.ws.onerror=e=>this.onError(e),this.ws.onmessage=e=>this.onMessage(e)}onOpen(t){this.callKit.logger.info("socket onOpen",{caller:"Socket.onOpen",type:"INCALL",content:{ev:t}}),this.setConnectAuthState("isConnected",!0),this.lastPingTime=Date.now(),this.checkPing(),this.send(R.START),this.connectAuthState.isReconnecting&&(this.setConnectAuthState("isReconnecting",!1),this.callKit.logger.info("reconnect success",{caller:"Socket.onOpen",type:"INCALL",content:{event:"INCALL_RECONNECT_SUCCESS",reconnectAttempts:this.reconnectAttempts}}),this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_SUCCESS"}))}cleanReconnectState(){this.reconnectAttempts=0,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.setConnectAuthState("isReconnecting",!1),this.setConnectAuthState("isError",!1)}resetConnectState(){this.connectAuthState={startConfirm:!1,isConnected:!1,isReconnecting:!1,isError:!1},this.cleanReconnectState(),this.callKit.logger.info("reset connect state",{caller:"Socket.resetConnectState",type:"INCALL",content:{reconnectAttempts:this.reconnectAttempts,connectAuthState:this.connectAuthState}})}onClose(t){this.callKit.logger.info("socket onClose",{caller:"Socket.onClose",type:"INCALL",content:{ev:t}}),this.handleDisconnect()}onError(t){this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_CONNECT_ERROR",err:t}),this.callKit.logger.error("socket onError",{caller:"Socket.onError",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR,data:t}})}confirmAck(t){let{ack:e,messageId:i}=t;e&&this.send(R.ACK,{messageId:i})}onMessage(t){let e=JSON.parse(t.data),i=e.data;try{typeof e.data=="string"&&e.data&&(i=JSON.parse(e.data))}catch{this.callKit.logger.info("socket onMessage parse error",{caller:"Socket.onMessage",type:"INCALL",content:{data:e.data}})}this.callKit.logger.info(`socket onMessage: ${e.event}`,{caller:"Socket.onMessage",type:"INCALL",content:{data:i,event:e.event}}),this.confirmAck(e);let n=i?.callUuid||"";if(e.event===S.PONG){this.lastPingTime=Date.now();return}if(e.event===S.START_CONFIRM&&(this.setConnectAuthState("startConfirm",!0),this.cleanReconnectState()),e.event===S.CUSTOMER_RINGING&&this.callKit.trigger(r.CALL_RINGING,{time:new Date,callUuid:n}),e.event===S.CUSTOMER_PICK_UP&&this.callKit.trigger(r.CALL_PICK_UP,{time:new Date,callUuid:n}),e.event===S.AGENT_PICK_UP&&this.callKit.trigger(r.AGENT_PICK_UP,{time:new Date,callUuid:n}),e.event===S.CUSTOMER_HANG_UP&&(this.callKit.trigger(r.CALL_HANG_UP,{time:new Date,callUuid:n}),n&&this.callKit.connect.socketTriggerHangup(n)),e.event===S.CUSTOMER_NO_ANSWER&&(this.callKit.trigger(r.CALL_NO_ANSWER,{time:new Date,callUuid:n}),n&&this.callKit.connect.socketTriggerHangup(n)),e.event===S.CALL_CDR&&this.callKit.trigger(r.CALL_CDR,{time:new Date,callUuid:n,...i}),e.event===S.CLOSE){let{userInfo:l}=this.callKit.config.getConfig();this.send(R.END,{agentId:l.agentId,callUuid:n})}e.event===S.ERROR&&(this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error(e.msg,{caller:`Socket.onMessage:${e.event}`,type:"INCALL",content:{errCode:a.SOKET_SERVER_ERROR,data:i,callUuid:n}})),e.event===S.SESSION_ERROR&&(this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error(e.msg,{caller:`Socket.onMessage:${e.event}`,type:"INCALL",content:{data:i,event:S.SESSION_ERROR,callUuid:n}})),e.event===S.AGENT_NO_ANSWER&&n&&this.callKit.connect.socketTriggerHangup(n),e.event===S.AGENT_HANG_UP&&n&&this.callKit.connect.socketTriggerHangup(n),this.callKit.trigger(r.SERVER_SOCKET_EVENT,{...e,callUuid:n})}send(t,e){if(!this.connectAuthState.isConnected){this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_NOT_CONNECTED"}),this.callKit.reset(),this.callKit.logger.error("socket not connected",{caller:"Socket.send",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR}});return}let{userInfo:i,version:n}=this.callKit.config.getConfig(),{sessionId:l,extno:o,agentId:C}=i;if(this.callKit.logger.info("Socket send",{caller:"Socket.send",type:"INCALL",content:{agentId:C,sessionId:l,userInfo:i}}),!l){this.callKit.logger.error("sessionId is empty",{caller:"Socket.send",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR}});return}let u={event:t,sessionId:l,version:n,...e};R.CALL===t&&(u.phoneNum=o,u.agentId=C,e?.sourceType===m.phoneNum?delete u.workOrderId:e?.sourceType===m.workOrderId&&delete u.phoneNum),this.callKit.logger.info("socket send",{caller:"Socket.send",type:"INCALL",content:{...u}}),this.ws?.send(JSON.stringify({event:t,...u}))}ping(){if(!this.connectAuthState.isConnected)return;this.send(R.PING);let t=Date.now(),{pingInterval:e,pingTimeout:i}=this.reconnectConfig;t-this.lastPingTime>e+i&&(this.ws&&this.connectAuthState.isConnected?this.ws.close(4001,"ping timeout"):this.callKit.reset(),this.callKit.logger.error("socket ping timeout",{caller:"Socket.ping",type:"INCALL",content:{errCode:a.SOCKET_PING_TIMEOUT}}),this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_PING_TIMEOUT"}))}checkPing(){this.pingTimer&&clearInterval(this.pingTimer);let{pingInterval:t}=this.reconnectConfig;this.pingTimer=setInterval(()=>{this.ping()},t)}async reset(t){let{force:e=!1}=t||{};this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=void 0),e&&(this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_RESET"}),this.resetConnectState()),this.lastPingTime=void 0,this.setConnectAuthState("startConfirm",!1),this.clearWebSocket()}attemptReconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0);let{maxAttempts:t}=this.reconnectConfig;if(this.reconnectAttempts>=t){this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_ERROR"}),this.callKit.reset(),this.callKit.logger.error("Maximum reconnection attempts reached",{caller:"Socket.attemptReconnect",type:"INCALL",content:{errCode:a.SOCKET_RECONNECT_FAILED,reconnectAttempts:this.reconnectAttempts}});return}this.reconnectAttempts===0&&this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_START"}),this.setConnectAuthState("isReconnecting",!0),this.reconnectAttempts+=1;let{delay:e}=this.reconnectConfig;this.callKit.logger.info(`Preparing reconnection attempt ${this.reconnectAttempts}/${t}, delay: ${e}ms`,{caller:"Socket.attemptReconnect",type:"INCALL",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:t,delay:e}}),this.reconnectTimer=setTimeout(()=>{let{socket:i}=this.callKit.config.getConfig();this.connect(i)},e)}};var q=class{api;config;logger;callCenter;connect;socket;listener=[];constructor(t){this.config=new M(this),this.api=new U(this),this.connect=new H(this),this.callCenter=new b(this),this.socket=new W(this),this.logger=new D(this,t.log),t.log&&this.config.setConfig("log",t.log),t.trackLogs&&this.config.setConfig("trackLogs",{...L,...t.trackLogs}),t.audioRef&&this.config.setConfig("audioRef",t.audioRef),t.host&&this.config.setConfig("host",t.host),this.config.setConfig("constrains",t.constrains||G),this.config.setConfig("socket",t.socket),this.config.setConfig("reconnect",{sip:{...O,...t.reconnect?.sip||{}},incall:{...A,...t.reconnect?.incall||{}}}),this.logger.info("callKit init",{caller:"CallKit.init",content:t})}async login(t,e,i={encryptionMethod:_.INTERNAL}){if(this.config.isLogin()){this.logger.warn("already login",{caller:"CallKit.login",content:{username:t,password:e,extra:i}});return}let n="",{encryptionMethod:l=_.INTERNAL}=i;switch(l){case _.NONE:n=e;break;case _.INTERNAL:n=(0,v.default)(t+(0,v.default)(e));break;default:n=(0,v.default)(t+(0,v.default)(e));break}if(this.logger.info("login info:",{caller:"CallKit.login",content:{username:t,password:e,encryptionMethod:l,encryptionPassword:n}}),this.socket.isError){this.logger.warn("socket is error",{caller:"CallKit.login",content:{username:t,password:e,extra:i,socketError:this.socket.isError}});return}try{let o=await this.api.login({userName:t,password:n,timestamp:Date.now()});o&&(this.config.setConfig("userInfo",{wsUrl:`wss://${o.wsUrl}`,sessionId:o.sessionId,username:t,password:n,encryptionPassword:n,agentId:o.agentId,fsUserId:o.fsUserId,userPart:o.userPart,fsPassword:o.fsPassword,fsIp:o.fsIp,fsPort:o.fsPort,iceInfo:o.iceInfo,iceGatheringTimeout:o.iceGatheringTimeout,logGather:o.logGather,...i}),this.socket.init(),this.trigger(r.KIT_LOGIN_CHANGE,!0))}catch(o){this.logger.error(o,{caller:"CallKit.login",content:{errCode:a.API_USER_LOGIN_ERROR}})}}async logout({isReset:t=!0}={isReset:!0}){if(!this.config.check())return;let{userInfo:e}=this.config.getConfig();if(this.logger.info("logout",{caller:"CallKit.logout",content:{sessionId:e.sessionId}}),this.config.isLogin()){let{sessionId:i}=e;try{await this.api.loginOut({sessionId:i,timestamp:Date.now()})}catch(n){this.logger.warn(n,{caller:"CallKit.logout",content:{errCode:a.API_USER_LOGOUT_ERROR}})}}t?await this.reset():this.config.reset()}async call(t="",e={sourceType:m.phoneNum,workOrderId:""}){if(!this.config.check())return;if(!this.connect.isRegistered){this.logger.warn("Currently not registered",{caller:"CallKit.call",content:{extno:t,options:e}});return}let{sourceType:i,workOrderId:n}=e;this.config.setUserInfo("sourceType",i),i===m.phoneNum?t&&this.config.setUserInfo("extno",t):i===m.workOrderId&&n&&this.config.setUserInfo("workOrderId",n),this.logger.info("call",{caller:"CallKit.call",content:{extno:t,options:e}}),this.callCenter.callStart(e)}async refer(t,e){this.config.check()&&(this.logger.info("refer",{caller:"CallKit.refer",content:{uri:t,options:e}}),this.callCenter.callRefer(t,e))}async register(){this.config.check()&&(this.logger.info("register",{caller:"CallKit.register",content:{}}),this.connect.register())}async unregister(){this.config.check()&&(this.logger.info("unregister",{caller:"CallKit.unregister",content:{}}),this.connect.unregister())}async hangup(){if(this.config.check()){if(this.logger.info("hangup",{caller:"CallKit.hangup",content:{connectStatus:this.connect.connectStatus}}),!this.connect.isConnecting()&&!this.connect.isRinging()&&!this.connect.isCalling()&&!this.connect.isHolding()){this.logger.warn("Currently not in a call",{caller:"CallKit.hangup",content:{connectStatus:this.connect.connectStatus}});return}await this.callCenter.callEnd(!0)}}hold(){this.config.check()&&(this.logger.info("hold",{caller:"CallKit.hold",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callHold())}unhold(){this.config.check()&&(this.logger.info("unhold",{caller:"CallKit.unhold",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callUnhold())}mute(){this.config.check()&&(this.logger.info("mute",{caller:"CallKit.mute",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callMute())}unmute(){this.config.check()&&(this.logger.info("unmute",{caller:"CallKit.unmute",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callUnmute())}async setUserStatus(t,e={}){let{agentId:i}=this.config.getConfig().userInfo;this.logger.info("setUserStatus",{caller:"CallKit.setUserStatus",content:{status:t,agentId:i}}),await this.api.updateUserStatus({agentId:i,userStatus:t,timestamp:Date.now(),...e})}async reset(t){let{force:e=!1}=t||{};this.logger.info("reset",{caller:"CallKit.reset",content:{connectStatus:this.connect.connectStatus,force:e}}),this.connect.isCalling()&&await this.hangup(),await this.connect.reset(),this.config.isLogin()?await this.logout({isReset:!1}):await this.config.reset(),await this.socket.reset({force:e})}on(t,e){this.listener.push({event:t,callback:e})}off(t,e){this.logger.info(`off ${t}`,{caller:"CallKit.off",content:{event:t}}),e?this.listener=this.listener.filter(i=>!(i.event===t&&i.callback===e)):this.listener=this.listener.filter(i=>i.event!==t)}removeAllListeners(){this.listener=this.listener.splice(0,this.listener.length),this.logger.info("removeAllListeners",{caller:"CallKit.removeAllListeners",content:{listener:this.listener}})}trigger(t,e,i=!1){i||this.logger.info(`Trigger Event: ${t}`,{caller:"CallKit.trigger",content:e}),this.listener.forEach(n=>{if(n.event===t)try{n.callback(e)}catch(l){this.logger.error(`Event callback error: ${t}`,l,!0)}})}};0&&(module.exports={CallKit});
4
+ `));for(let o of i)this.callKit.api.trackLogs(o);this.pendingTrackLogs=[]}catch(i){console.error(i)}}destroy(){this.trackLogsTimer&&(clearInterval(this.trackLogsTimer),this.trackLogsTimer=null),this.flushTrackLogs()}setLevel(t){this.level=t}info(t,e){let i=this.catchLog(t,e,"info");y(this.level)>=y("info")&&console.log(`%c${i}`,"color: gray;")}success(t,e){let i=this.catchLog(t,e,"success");y(this.level)>=y("success")&&console.log(`%c${i}`,"color: green;")}warn(t,e){let i=this.catchLog(t,e,"warn");y(this.level)>=y("warn")&&console.log(`%c${i}`,"color: orange;")}error(t,e,i=!1){let n=t instanceof Error?t.message:t,l=this.catchLog(n,e,"error");y(this.level)>=y("error")&&console.log(`%c${l}`,"color: red;");let{errCode:o,...C}=e?.content??{},u=o??a.UNKNOWN_ERROR;i||this.callKit.trigger(r.KIT_ERROR,{code:u,msg:n,data:C});let d=new Error(n);throw d.name="CallKitError",d.code=u,d.data=C,d}catchLog(t,e,i){let n=new Date,{enabled:l}=this.callKit.config.getTrackLogsConfig(),{userInfo:o}=this.callKit.config.getConfig(),C={agentId:o?.agentId,sessionId:o?.sessionId,...e?.content??{}},u={timestamp:n.toLocaleString().replace("T"," ").replace(".000Z",""),level:i,message:t,caller:e?.caller,type:e?.type,content:C},d=ft(u);return l&&this.pendingTrackLogs.push(d),this.callKit.trigger(r.KIT_LOG,d,!0),d}};var g=require("sip.js");var it=s=>{let t=s["x-antaios-manual-extend_info"]||s["x-antaios-manual-extend-info"],e=null;try{if(t&&typeof t=="string"){let i=t.replace(/\\/g,"");return e=JSON.parse(i),e}}catch{return{}}};var x=6;function Ct(s){return s.replace(/(\w+):\s*'(.*?)'/g,'"$1": "$2"').replace(/'/g,'"')}var q=s=>{s&&s.getTracks().forEach(t=>t.stop())},ut=()=>{typeof navigator.mediaDevices>"u"&&(navigator.mediaDevices={}),typeof navigator.mediaDevices.getUserMedia>"u"&&(navigator.mediaDevices.getUserMedia=s=>{let t=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia;return t?new Promise((e,i)=>{t.call(navigator,s,e,i)}):Promise.reject(new Error("Unable to obtain device permissions. Please check your browser settings or device permissions."))})},H=class{callKit;isMute=!1;isRegister=!1;isHold=!1;connectStatus=f.init;currentSession;mediaStream;userAgent;registerer;isReConnected=!1;isOutgoing=!1;isUnprompted=!1;hasInvite=!1;constructor(t){this.callKit=t}get reconnectConfig(){return this.callKit.config.getReconnectConfig("sip")}currentCallId=null;getCurrentCallId(){return this.currentCallId}setOutgoing(t){this.isOutgoing!==t&&(this.callKit.logger.info("setOutgoing",{caller:"Connect.setOutgoing",content:{outgoing:t}}),this.isOutgoing=t)}setCallId(t){this.callKit.logger.info("setCallId",{caller:"Connect.setCallId",content:{callId:t}}),this.currentCallId=t,this.callKit.trigger(r.KIT_CALL_ID_CHANGE,t)}async reset(){if(this.setOutgoing(!1),this.isUnprompted=!1,this.hasInvite=!1,this.isHolding()&&await this.setHold(!1),this.isMuted()&&await this.setMute(!1),this.connectStatus!==f.init&&this.setConnectStatus(f.init),this.isRegistered()&&await this.unregister(),this.currentCallId&&this.setCallId(null),this.currentSession=void 0,this.mediaStream=void 0,this.userAgent=void 0,this.registerer=void 0,this.mediaStream)try{q(this.mediaStream);let t=this.getAduioReference();t&&(t.pause(),t.srcObject=null)}catch(t){this.callKit.logger.error(t,{caller:"Connect.reset",content:{}})}this.setConnectStatus(f.init),this.clearHeartbeat()}getAduioReference(){let{audioRef:t}=this.callKit.config.getConfig();return typeof t=="function"?t():t}async permission(){this.callKit.logger.info("permission",{caller:"Connect.permission",content:{permission:!0}}),ut();let t=await navigator.mediaDevices.getUserMedia({audio:!0});q(t)}isConnecting(){return this.connectStatus===f.connecting}isCalling(){return this.connectStatus===f.calling}isRinging(){return this.connectStatus===f.ringing}isHolding(){return this.isHold}isRegistered(){return this.isRegister}isMuted(){return this.isMute}isInit(){return this.connectStatus===f.init}heartbeatInterval;heartbeatFlag=x;clearHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null),this.heartbeatFlag=x}startHeartbeat(){this.heartbeatFlag=x,this.clearHeartbeat(),this.heartbeatInterval=setInterval(()=>{this.heartbeatFlag-=1,this.heartbeatFlag<=0&&(this.heartbeatFlag=x,this.callKit.trigger(r.SIP_CONNECT_EVENT,{event:"OPTIONS_HEARTBEAT_EXPIRED"}))},1e3)}socketTriggerHangup(t){!this.isCalling()||t!==this.currentCallId||(this.callKit.logger.info("socketHangup trigger hangup",{caller:"Connect.socketHangup",content:{callId:t,currentCallId:this.currentCallId}}),this.callKit.hangup())}async register(){if(this.connectStatus!==f.init){if(this.isRegistered()){this.callKit.logger.warn("connectStatus is registered",{caller:"Connect.register",content:{errCode:a.CONNECT_CALL_STATUS_ERROR}});return}this.callKit.reset(),this.callKit.logger.error("connectStatus is not init",{caller:"Connect.register",content:{errCode:a.CONNECT_CALL_STATUS_ERROR}});return}this.callKit.logger.info("connect register",{caller:"Connect.register",content:{connectStatus:this.connectStatus}}),await this.permission().catch(c=>{this.callKit.reset(),this.callKit.logger.error(c,{caller:"Connect.register",content:{errCode:a.WEBRTC_USER_MEDIA_ERROR}})});let{userInfo:t,constrains:e}=this.callKit.config.getConfig(),i=async()=>(this.mediaStream=await navigator.mediaDevices.getUserMedia(e),this.mediaStream),{userPart:n,fsIp:l,fsPort:o,iceInfo:C,wsUrl:u}=t,d={uri:g.UserAgent.makeURI(`sip:${n}@${l}:${o}`),displayName:n,transportOptions:{wsServers:[u],traceSip:!0},logLevel:"error",allowLegacyNotifications:!0,contactName:n,sessionDescriptionHandlerFactory:g.Web.defaultSessionDescriptionHandlerFactory(i),sessionDescriptionHandlerFactoryOptions:{constraints:e,iceGatheringTimeout:t.iceGatheringTimeout,peerConnectionConfiguration:{iceServers:JSON.parse(Ct(C))}}};this.callKit.logger.info("connect connectConfig",{caller:"Connect.register",content:d}),this.userAgent=new g.UserAgent(d);let k=new MediaStream,F=c=>{let I=this.getAduioReference();this.callKit.logger.info("connect setupRemoteMedia",{caller:"Connect.register.setupRemoteMedia",content:I}),c.sessionDescriptionHandler.peerConnection.getReceivers().forEach(E=>{E.track&&k.addTrack(E.track)}),I?(I.srcObject=k,I.play().catch(E=>{this.callKit.logger.error(E.message,{caller:"Connect.register.setupRemoteMedia",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})})):this.callKit.logger.error("video is not exist",{caller:"Connect.register",content:{errCode:a.WEBRTC_AUDIO_PLAYER_ERROR}})},P=(c,I)=>{let{that:E=this}=I,T=c.userAgentCore,h=T.receiveIncomingRequestFromTransport.bind(T);T.receiveIncomingRequestFromTransport=p=>(p.method==="OPTIONS"&&E.startHeartbeat(),E.callKit.logger.info(`SIP Receive: ${p?.method}`,{caller:"Connect.register.observeSocketStatus.receiveRequest",type:"SIP",content:{request:p}}),h(p));let $=T.receiveIncomingResponseFromTransport.bind(T);T.receiveIncomingResponseFromTransport=p=>(E.callKit.logger.info(`SIP Receive Response: ${p?.statusCode} ${p?.reasonPhrase}`,{caller:"Connect.register.observeSocketStatus.receiveResponse",type:"SIP",content:{response:p}}),$(p));let{transport:N}=c;if(N){let p=N.send.bind(N);N.send=J=>(E.callKit.logger.info("SIP send message",{caller:"Connect.register.observeSocketStatus",type:"SIP",content:{message:J.toString()}}),p(J))}},K={};this.registerer=new g.Registerer(this.userAgent,K),this.registerer.stateChange.addListener(c=>{switch(c){case g.RegistererState.Initial:this.callKit.logger.info("registerer stateChange Initial",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!1),this.setConnectStatus(f.init),this.callKit.trigger(r.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case g.RegistererState.Registered:this.callKit.logger.info("registerer stateChange Registered",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!0),this.callKit.trigger(r.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case g.RegistererState.Terminated:this.callKit.logger.info("registerer stateChange Terminated",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!1),this.setConnectStatus(f.init),this.callKit.trigger(r.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case g.RegistererState.Unregistered:this.callKit.logger.info("registerer stateChange Unregistered",{caller:"Connect.register.registererStateChange",type:"SIP",content:{isRegistered:this.isRegistered(),registererState:c}}),this.setRegister(!1),this.setConnectStatus(f.init),this.callKit.trigger(r.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;default:break}}),this.userAgent.delegate={onInvite:c=>{this.callKit.logger.info("connect onInvite",{type:"SIP",caller:"Connect.register.onInvite",content:{invite:c,isRegistered:this.isRegistered(),isOutgoing:this.isOutgoing}}),this.currentSession=c,this.currentSession.stateChange.addListener(h=>{switch(h){case g.SessionState.Establishing:this.callKit.logger.info("connect Establishing",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:h}}),this.setConnectStatus(f.ringing),this.callKit.trigger(r.SIP_SESSION_EVENT,{sessionState:h,isRegistered:this.isRegistered()});break;case g.SessionState.Established:this.callKit.logger.info("connect Established",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:h}}),this.callKit.connect.setConnectStatus(f.calling),this.callKit.trigger(r.SIP_SESSION_EVENT,{sessionState:h,isRegistered:this.isRegistered()}),F(this.currentSession);break;case g.SessionState.Terminating:this.callKit.trigger(r.SIP_SESSION_EVENT,{sessionState:h,isRegistered:this.isRegistered()});break;case g.SessionState.Terminated:this.callKit.logger.info("connect Terminated",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:h}}),this.hasInvite=!1,this.isUnprompted||this.callKit.callCenter.callEnd(),this.isUnprompted=!1,this.callKit.trigger(r.SIP_SESSION_EVENT,{sessionState:h,isRegistered:this.isRegistered()});break;default:break}});let I={sessionDescriptionHandlerOptions:{constraints:e,alwaysAcquireMediaFirst:!0}},E=()=>{let{request:h}=this.currentSession,$=Object.keys(h.headers),N={};return $.filter(p=>p.toLocaleLowerCase().startsWith("x-antaios")).forEach(p=>{N[p.toLocaleLowerCase()]=h.getHeader(p)}),this.callKit.logger.info("get invite data",{caller:"Connect.register.onInvite",content:N}),N},T=E();try{let h=it(T);h?.callUuid?this.setCallId(h.callUuid):(this.setCallId(null),this.callKit.logger.warn("call id is not exist",{caller:"Connect.register.onInvite",content:{inviteData:h}}))}catch(h){this.callKit.logger.info(h,{caller:"Connect.register.onInvite",content:T})}if(this.isOutgoing)this.currentSession.accept(I),this.callKit.trigger(r.KIT_OUTGOING_INVITE,{getInviteData:E});else{this.hasInvite=!0;let h=()=>{this.currentSession?.state!==g.SessionState.Terminated&&this.currentSession?.state!==g.SessionState.Terminating&&this.currentSession.reject(),this.hasInvite=!1,this.callKit.callCenter.callEnd(!0,!1)};this.callKit.trigger(r.KIT_INVITE,{accept:()=>{this.callKit.trigger(r.CALL_CONNECTING,new Date),this.hasInvite=!1,this.currentSession.accept(I)},reject:h,getInviteData:E})}},onConnect:async()=>{this.reconnectAttempts=0,this.reconnectTimer=null,this.callKit.logger.info("connect onConnect",{caller:"Connect.register",type:"SIP",content:{version:`${this.callKit.config.getConfig().version}`}}),await this.registerer.register().catch(async c=>{this.callKit.reset(),this.callKit.logger.error(c?.message,{caller:"Connect.register",type:"SIP",content:{errCode:a.WEBRTC_REGISTER_ERROR}})})},onDisconnect:c=>{c?(this.callKit.logger.warn("SIP User Agent Disconnected with error",{caller:"Connect.register",type:"SIP",content:{err:c.message,errCode:a.WEBRTC_USER_AGENT_ERROR}}),this.startReconnectTimer()):this.callKit.logger.warn("SIP User Agent Disconnected",{caller:"Connect.register",type:"SIP",content:{}})},onRegister:()=>{this.callKit.logger.info("connect onRegister",{caller:"Connect.register",type:"SIP",content:{version:`V${this.callKit.config.getConfig().version}`}})}},P(this.userAgent,{that:this}),await this.userAgent.start().catch(c=>{this.callKit.reset(),this.callKit.logger.error(c,{caller:"Connect.register",type:"SIP",content:{errCode:a.WEBRTC_USER_AGENT_ERROR}})})}reconnectTimer;reconnectAttempts=0;startReconnectTimer(){if(this.reconnectAttempts>=this.reconnectConfig.maxAttempts&&this.callKit.config.isLogin()){this.callKit.reset(),this.callKit.logger.error("Reconnect failed max attempts",{caller:"Connect.startReconnectTimer",type:"SIP",content:{errCode:a.SOCKET_RECONNECT_FAILED,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}});return}this.callKit.logger.info("Reconnect timer started",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}}),this.reconnectAttempts+=1,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer&&this.callKit.config.isLogin()?(this.userAgent?.reconnect(),this.callKit.logger.info("Reconnect attempt",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}})):this.callKit.logger.info("Reconnect timer already expired",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}})},this.reconnectConfig.delay)}async stop(){await this.userAgent.stop()}async unregister(){if(this.callKit.logger.info("connect unregister",{caller:"Connect.unregister",type:"SIP",content:{isRegistered:this.isRegistered()}}),!this.isRegistered()||!this.registerer){this.callKit.logger.warn("No registerer to unregister.",{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}});return}await this.registerer.unregister({all:!0}).catch(t=>{this.callKit.logger.warn(t,{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}})}).finally(()=>{this.setRegister(!1)}),await this.userAgent?.stop().catch(t=>{this.callKit.logger.warn(t,{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}})})}async call(t){this.callKit.logger.info("connect call",{caller:"Connect.call",type:"SIP",content:{callback:t}}),this.setOutgoing(!0),this.isRegistered()||await this.register(),this.setConnectStatus(f.connecting),this.callKit.trigger(r.CALL_CONNECTING,new Date);let{userInfo:e}=this.callKit.config.getConfig();t(e)}setRegister(t){this.isRegister!==t&&(this.callKit.logger.info("connect setRegister",{caller:"Connect.setRegister",type:"SIP",content:{register:t}}),this.isRegister=t,this.callKit.trigger(r.KIT_REGISTER_CHANGE,t))}setConnectStatus(t){this.callKit.logger.info("connect setConnectStatus",{caller:"Connect.setConnectStatus",type:"SIP",content:{status:t}}),this.connectStatus=t,this.callKit.trigger(r.KIT_CALL_STATUS_CHANGE,t)}async hangup(t=!1,e=!1){if(this.callKit.logger.info("connect hangup",{caller:"Connect.hangup",type:"SIP",content:{isUnprompted:t,isError:e,connectStatus:this.connectStatus}}),this.setOutgoing(!1),this.isUnprompted=t,this.setHold(!1),this.setMute(!1),this.connectStatus!==f.init)try{t&&(this.isRinging()||this.isCalling())&&(this.hasInvite?(this.currentSession?.state!==g.SessionState.Terminated&&this.currentSession?.state!==g.SessionState.Terminating&&this.currentSession.reject(),this.hasInvite=!1):await this.currentSession?.bye()),q(this.mediaStream);let i=this.getAduioReference();i&&(i.pause(),i.srcObject=null),this.setConnectStatus(f.init),this.callKit.trigger(r.CALL_END,new Date),this.setCallId(null)}catch(i){this.callKit.trigger(r.CALL_END,new Date),this.callKit.reset(),this.callKit.logger.error(i,{caller:"Connect.hangup",type:"SIP",content:{connectStatus:this.connectStatus,isError:e,isUnprompted:t}})}}getRemoteMediaStream(t){this.callKit.logger.info("connect getRemoteMediaStream",{caller:"Connect.getRemoteMediaStream",type:"SIP",content:{session:t}});let e=t.sessionDescriptionHandler;if(e)return e.remoteMediaStream}setupRemoteMedia(t){this.callKit.logger.info("connect setupRemoteMedia",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{session:t}});let e=this.getRemoteMediaStream(t),i=this.getAduioReference();i?(i.autoplay=!0,i.srcObject=e,i.play().catch(n=>{this.callKit.logger.error(n.message,{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})}),e.onaddtrack=()=>{this.callKit.logger.info("Remote media onaddtrack",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{session:t}}),i.load(),i.play().catch(n=>{this.callKit.logger.error(n.message,{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})})}):this.callKit.logger.error("video is not exist",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAYER_ERROR}})}async setHold(t){if(this.isHold===t){this.callKit.logger.warn("Already holding",{caller:"Connect.setHold",type:"SIP",content:{isHold:this.isHold}});return}this.callKit.socket.send(t?R.HOLD:R.UNHOLD),this.isHold=t,this.callKit.logger.info("connect setHold",{caller:"Connect.setHold",type:"SIP",content:{hold:t}}),this.callKit.trigger(r.KIT_SET_HOLD,t)}async setMute(t){if(this.isMute===t){this.callKit.logger.warn("Already muted",{caller:"Connect.setMute",type:"SIP",content:{isCalling:this.isCalling(),isMuted:this.isMuted()}});return}this.callKit.socket.send(t?R.MUTE:R.UNMUTE),this.isMute=t,this.callKit.trigger(r.KIT_SET_MUTE,t)}async refer(t,e){this.callKit.logger.info("connect refer",{caller:"Connect.refer",type:"SIP",content:{referTo:t,extra:e}});let i;t&&(i=g.UserAgent.makeURI(t)),this.currentSession.refer(i,e?.sessionReferOptions)}};var W=class{callKit;ws;lastPingTime=void 0;pingTimer;reconnectTimer;reconnectAttempts=0;connectAuthState={startConfirm:!1,isConnected:!1,isReconnecting:!1,isError:!1};get startConfirm(){return this.connectAuthState.startConfirm}get isError(){return this.connectAuthState.isError}constructor(t){this.callKit=t}get reconnectConfig(){return this.callKit.config.getReconnectConfig("incall")}init(){let{socket:t}=this.callKit.config.getConfig();this.callKit.logger.info(`socket init: ${t}`,{caller:"Socket.init",type:"INCALL",content:{socket:t}}),this.connect(t)}setConnectAuthState(t,e){this.connectAuthState[t]!==e&&(this.connectAuthState[t]=e)}handleDisconnect(){this.setConnectAuthState("isConnected",!1);let{enabled:t}=this.reconnectConfig;if(!this.callKit.config.isLogin()||!t){this.callKit.reset(),this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_NOT_CONNECTED"});return}this.connectAuthState.isReconnecting||this.connectAuthState.isError||this.attemptReconnect()}clearWebSocket(){this.ws&&(this.ws.onopen=null,this.ws.onclose=null,this.ws.onerror=null,this.ws.onmessage=null),(this.ws?.readyState===WebSocket.CONNECTING||this.ws?.readyState===WebSocket.OPEN)&&(this.ws?.close(1e3,"socket close"),this.callKit.logger.info("socket clear",{caller:"Socket.clearWebSocket",type:"INCALL",content:{}})),this.ws=void 0,this.setConnectAuthState("isConnected",!1)}connect(t){this.ws&&this.clearWebSocket(),this.ws=new WebSocket(t),this.ws.onopen=e=>this.onOpen(e),this.ws.onclose=e=>this.onClose(e),this.ws.onerror=e=>this.onError(e),this.ws.onmessage=e=>this.onMessage(e)}onOpen(t){this.callKit.logger.info("socket onOpen",{caller:"Socket.onOpen",type:"INCALL",content:{ev:t}}),this.setConnectAuthState("isConnected",!0),this.lastPingTime=Date.now(),this.checkPing(),this.send(R.START),this.connectAuthState.isReconnecting&&(this.setConnectAuthState("isReconnecting",!1),this.callKit.logger.info("reconnect success",{caller:"Socket.onOpen",type:"INCALL",content:{event:"INCALL_RECONNECT_SUCCESS",reconnectAttempts:this.reconnectAttempts}}),this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_SUCCESS"}))}cleanReconnectState(){this.reconnectAttempts=0,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.setConnectAuthState("isReconnecting",!1),this.setConnectAuthState("isError",!1)}resetConnectState(){this.connectAuthState={startConfirm:!1,isConnected:!1,isReconnecting:!1,isError:!1},this.cleanReconnectState(),this.callKit.logger.info("reset connect state",{caller:"Socket.resetConnectState",type:"INCALL",content:{reconnectAttempts:this.reconnectAttempts,connectAuthState:this.connectAuthState}})}onClose(t){this.callKit.logger.info("socket onClose",{caller:"Socket.onClose",type:"INCALL",content:{ev:t}}),this.handleDisconnect()}onError(t){this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_CONNECT_ERROR",err:t}),this.callKit.logger.error("socket onError",{caller:"Socket.onError",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR,data:t}})}confirmAck(t){let{ack:e,messageId:i}=t;e&&this.send(R.ACK,{messageId:i})}onMessage(t){let e=JSON.parse(t.data),i=e.data;try{typeof e.data=="string"&&e.data&&(i=JSON.parse(e.data))}catch{this.callKit.logger.info("socket onMessage parse error",{caller:"Socket.onMessage",type:"INCALL",content:{data:e.data}})}this.callKit.logger.info(`socket onMessage: ${e.event}`,{caller:"Socket.onMessage",type:"INCALL",content:{data:i,event:e.event}}),this.confirmAck(e);let n=i?.callUuid||"";if(e.event===S.PONG){this.lastPingTime=Date.now();return}if(e.event===S.START_CONFIRM&&(this.setConnectAuthState("startConfirm",!0),this.cleanReconnectState()),e.event===S.CUSTOMER_RINGING&&this.callKit.trigger(r.CALL_RINGING,{time:new Date,callUuid:n}),e.event===S.CUSTOMER_PICK_UP&&this.callKit.trigger(r.CALL_PICK_UP,{time:new Date,callUuid:n}),e.event===S.AGENT_PICK_UP&&this.callKit.trigger(r.AGENT_PICK_UP,{time:new Date,callUuid:n}),e.event===S.CUSTOMER_HANG_UP&&(this.callKit.trigger(r.CALL_HANG_UP,{time:new Date,callUuid:n}),n&&this.callKit.connect.socketTriggerHangup(n)),e.event===S.CUSTOMER_NO_ANSWER&&(this.callKit.trigger(r.CALL_NO_ANSWER,{time:new Date,callUuid:n}),n&&this.callKit.connect.socketTriggerHangup(n)),e.event===S.CALL_CDR&&this.callKit.trigger(r.CALL_CDR,{time:new Date,callUuid:n,...i}),e.event===S.CLOSE){let{userInfo:l}=this.callKit.config.getConfig();this.send(R.END,{agentId:l.agentId,callUuid:n})}e.event===S.ERROR&&(this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error(e.msg,{caller:`Socket.onMessage:${e.event}`,type:"INCALL",content:{errCode:a.SOKET_SERVER_ERROR,data:i,callUuid:n}})),e.event===S.SESSION_ERROR&&(this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error(e.msg,{caller:`Socket.onMessage:${e.event}`,type:"INCALL",content:{data:i,event:S.SESSION_ERROR,callUuid:n}})),e.event===S.AGENT_NO_ANSWER&&n&&this.callKit.connect.socketTriggerHangup(n),e.event===S.AGENT_HANG_UP&&n&&this.callKit.connect.socketTriggerHangup(n),this.callKit.trigger(r.SERVER_SOCKET_EVENT,{...e,callUuid:n})}send(t,e){if(!this.connectAuthState.isConnected){this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_NOT_CONNECTED"}),this.callKit.reset(),this.callKit.logger.error("socket not connected",{caller:"Socket.send",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR}});return}let{userInfo:i,version:n}=this.callKit.config.getConfig(),{sessionId:l,extno:o,agentId:C}=i;if(this.callKit.logger.info("Socket send",{caller:"Socket.send",type:"INCALL",content:{agentId:C,sessionId:l,userInfo:i}}),!l){this.callKit.logger.error("sessionId is empty",{caller:"Socket.send",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR}});return}let u={event:t,sessionId:l,version:n,...e};R.CALL===t&&(u.phoneNum=o,u.agentId=C,e?.sourceType===m.phoneNum?delete u.workOrderId:e?.sourceType===m.workOrderId&&delete u.phoneNum),this.callKit.logger.info("socket send",{caller:"Socket.send",type:"INCALL",content:{...u}}),this.ws?.send(JSON.stringify({event:t,...u}))}ping(){if(!this.connectAuthState.isConnected)return;this.send(R.PING);let t=Date.now(),{pingInterval:e,pingTimeout:i}=this.reconnectConfig;t-this.lastPingTime>e+i&&(this.ws&&this.connectAuthState.isConnected?this.ws.close(4001,"ping timeout"):this.callKit.reset(),this.callKit.logger.error("socket ping timeout",{caller:"Socket.ping",type:"INCALL",content:{errCode:a.SOCKET_PING_TIMEOUT}}),this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_PING_TIMEOUT"}))}checkPing(){this.pingTimer&&clearInterval(this.pingTimer);let{pingInterval:t}=this.reconnectConfig;this.pingTimer=setInterval(()=>{this.ping()},t)}async reset(t){let{force:e=!1}=t||{};this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=void 0),e&&(this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_RESET"}),this.resetConnectState()),this.lastPingTime=void 0,this.setConnectAuthState("startConfirm",!1),this.clearWebSocket()}attemptReconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0);let{maxAttempts:t}=this.reconnectConfig;if(this.reconnectAttempts>=t){this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_ERROR"}),this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error("Maximum reconnection attempts reached",{caller:"Socket.attemptReconnect",type:"INCALL",content:{errCode:a.SOCKET_RECONNECT_FAILED,reconnectAttempts:this.reconnectAttempts}});return}this.reconnectAttempts===0&&this.callKit.trigger(r.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_START"}),this.setConnectAuthState("isReconnecting",!0),this.reconnectAttempts+=1;let{delay:e}=this.reconnectConfig;this.callKit.logger.info(`Preparing reconnection attempt ${this.reconnectAttempts}/${t}, delay: ${e}ms`,{caller:"Socket.attemptReconnect",type:"INCALL",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:t,delay:e}}),this.reconnectTimer=setTimeout(()=>{let{socket:i}=this.callKit.config.getConfig();this.connect(i)},e)}};var z=class{api;config;logger;callCenter;connect;socket;listener=[];constructor(t){this.config=new M(this),this.api=new U(this),this.connect=new H(this),this.callCenter=new b(this),this.socket=new W(this),this.logger=new D(this,t.log),t.log&&this.config.setConfig("log",t.log),t.trackLogs&&this.config.setConfig("trackLogs",{...L,...t.trackLogs}),t.audioRef&&this.config.setConfig("audioRef",t.audioRef),t.host&&this.config.setConfig("host",t.host),this.config.setConfig("constrains",t.constrains||G),this.config.setConfig("socket",t.socket),this.config.setConfig("reconnect",{sip:{...O,...t.reconnect?.sip||{}},incall:{...A,...t.reconnect?.incall||{}}}),this.logger.info("callKit init",{caller:"CallKit.init",content:t})}async login(t,e,i={encryptionMethod:_.INTERNAL}){if(this.config.isLogin()){this.logger.warn("already login",{caller:"CallKit.login",content:{username:t,password:e,extra:i}});return}let n="",{encryptionMethod:l=_.INTERNAL}=i;switch(l){case _.NONE:n=e;break;case _.INTERNAL:n=(0,v.default)(t+(0,v.default)(e));break;default:n=(0,v.default)(t+(0,v.default)(e));break}if(this.logger.info("login info:",{caller:"CallKit.login",content:{username:t,password:e,encryptionMethod:l,encryptionPassword:n}}),this.socket.isError){this.logger.warn("socket is error",{caller:"CallKit.login",content:{username:t,password:e,extra:i,socketError:this.socket.isError}});return}try{let o=await this.api.login({userName:t,password:n,timestamp:Date.now()});o&&(this.config.setConfig("userInfo",{wsUrl:`wss://${o.wsUrl}`,sessionId:o.sessionId,username:t,password:n,encryptionPassword:n,agentId:o.agentId,fsUserId:o.fsUserId,userPart:o.userPart,fsPassword:o.fsPassword,fsIp:o.fsIp,fsPort:o.fsPort,iceInfo:o.iceInfo,iceGatheringTimeout:o.iceGatheringTimeout,logGather:o.logGather,...i}),this.socket.init(),this.trigger(r.KIT_LOGIN_CHANGE,!0))}catch(o){this.logger.error(o,{caller:"CallKit.login",content:{errCode:a.API_USER_LOGIN_ERROR}})}}async logout({isReset:t=!0}={isReset:!0}){if(!this.config.check())return;let{userInfo:e}=this.config.getConfig();if(this.logger.info("logout",{caller:"CallKit.logout",content:{sessionId:e.sessionId}}),this.config.isLogin()){let{sessionId:i}=e;try{await this.api.loginOut({sessionId:i,timestamp:Date.now()})}catch(n){this.logger.warn(n,{caller:"CallKit.logout",content:{errCode:a.API_USER_LOGOUT_ERROR}})}}t?await this.reset():this.config.reset("logout")}async call(t="",e={sourceType:m.phoneNum,workOrderId:""}){if(!this.config.check())return;if(!this.connect.isRegistered){this.logger.warn("Currently not registered",{caller:"CallKit.call",content:{extno:t,options:e}});return}let{sourceType:i,workOrderId:n}=e;this.config.setUserInfo("sourceType",i),i===m.phoneNum?t&&this.config.setUserInfo("extno",t):i===m.workOrderId&&n&&this.config.setUserInfo("workOrderId",n),this.logger.info("call",{caller:"CallKit.call",content:{extno:t,options:e}}),this.callCenter.callStart(e)}async refer(t,e){this.config.check()&&(this.logger.info("refer",{caller:"CallKit.refer",content:{uri:t,options:e}}),this.callCenter.callRefer(t,e))}async register(){this.config.check()&&(this.logger.info("register",{caller:"CallKit.register",content:{}}),this.connect.register())}async unregister(){this.config.check()&&(this.logger.info("unregister",{caller:"CallKit.unregister",content:{}}),this.connect.unregister())}async hangup(){if(this.config.check()){if(this.logger.info("hangup",{caller:"CallKit.hangup",content:{connectStatus:this.connect.connectStatus}}),!this.connect.isConnecting()&&!this.connect.isRinging()&&!this.connect.isCalling()&&!this.connect.isHolding()){this.logger.warn("Currently not in a call",{caller:"CallKit.hangup",content:{connectStatus:this.connect.connectStatus}});return}await this.callCenter.callEnd(!0)}}hold(){this.config.check()&&(this.logger.info("hold",{caller:"CallKit.hold",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callHold())}unhold(){this.config.check()&&(this.logger.info("unhold",{caller:"CallKit.unhold",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callUnhold())}mute(){this.config.check()&&(this.logger.info("mute",{caller:"CallKit.mute",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callMute())}unmute(){this.config.check()&&(this.logger.info("unmute",{caller:"CallKit.unmute",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callUnmute())}async setUserStatus(t,e={}){let{agentId:i}=this.config.getConfig().userInfo;this.logger.info("setUserStatus",{caller:"CallKit.setUserStatus",content:{status:t,agentId:i}}),await this.api.updateUserStatus({agentId:i,userStatus:t,timestamp:Date.now(),...e})}async reset(t){let{force:e=!1}=t||{};this.logger.info("reset",{caller:"CallKit.reset",content:{connectStatus:this.connect.connectStatus,force:e}}),this.connect.isCalling()&&await this.hangup(),await this.connect.reset(),this.config.isLogin()?await this.logout({isReset:!1}):await this.config.reset("reset"),await this.socket.reset({force:e})}on(t,e){this.listener.push({event:t,callback:e})}off(t,e){this.logger.info(`off ${t}`,{caller:"CallKit.off",content:{event:t}}),e?this.listener=this.listener.filter(i=>!(i.event===t&&i.callback===e)):this.listener=this.listener.filter(i=>i.event!==t)}removeAllListeners(){this.listener=this.listener.splice(0,this.listener.length),this.logger.info("removeAllListeners",{caller:"CallKit.removeAllListeners",content:{listener:this.listener}})}trigger(t,e,i=!1){i||this.logger.info(`Trigger Event: ${t}`,{caller:"CallKit.trigger",content:e}),this.listener.forEach(n=>{if(n.event===t)try{n.callback(e)}catch(l){this.logger.error(`Event callback error: ${t}`,l,!0)}})}};0&&(module.exports={CallKit});
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import W from"blueimp-md5";import tt from"axios";var V=tt.create({headers:{"Content-Type":"application/x-www-form-urlencoded"},timeout:6e4});V.interceptors.request.use(o=>o);V.interceptors.response.use(o=>o.data,o=>Promise.reject(o));var et=o=>V.request(o),z=et;var P=class{callKit;constructor(t){this.callKit=t}isLogining=!1;isLoginOuting=!1;async login(t){if(this.isLogining){this.callKit.logger.info("login is already in progress cancel",{caller:"Api.login",content:{userName:t.userName,timestamp:t.timestamp}});return}this.isLogining=!0;try{return await this.post({url:"/auth/agentUser/login",method:"post",data:t})}finally{this.isLogining=!1}}async loginOut(t){if(this.isLoginOuting){this.callKit.logger.info("loginOut is already in progress cancel",{caller:"Api.loginOut",content:{sessionId:t.sessionId,timestamp:t.timestamp}});return}this.isLoginOuting=!0;try{return await this.post({url:"/auth/agentUser/loginOut",method:"post",data:t})}finally{this.isLoginOuting=!1}}async trackLogs(t){return this.post({url:"/agent/user/sdkLog",method:"post",data:{content:[t]}},{useFormData:!0,skipLog:!0})}async updateUserStatus(t){return this.post({url:"/agent/user/changeStatus",method:"post",data:t})}async post(t,e={skipLog:!1}){let{userInfo:i,host:n}=this.callKit.config.getConfig(),{sessionId:l}=i;if(t.url=`${n}${t.url}`,t.headers={"Content-Type":"application/x-www-form-urlencoded",...t.headers},t.headers["Content-Type"]==="application/x-www-form-urlencoded"&&e.useFormData){let k=new FormData,K=t.data||{};for(let c in K)Object.prototype.hasOwnProperty.call(K,c)&&k.append(c,K[c]);t.data=k}else t.data=new URLSearchParams(t.data).toString();l&&(t.headers.sessionId=l);let r=Date.now();e.skipLog||this.callKit.logger.info("API Request Start",{type:"API",caller:"API.Request",content:{url:t.url,headers:t.headers,data:t.data,extra:e,startTime:r}});let f=await z(t).catch(()=>{this.callKit.config.reset()}),C=Date.now();if(e.skipLog||this.callKit.logger.info("API Request Finish",{type:"API",caller:"API.Request",content:{url:t.url,duration:`${C-r}ms`,response:f}}),!f)throw this.callKit.reset(),new Error("Network error");let{code:u,data:v,message:F}=f;if(u==="000000")return v;throw u==="100013"&&this.callKit.config.reset(),new Error(F??"Request failed")}};var h={init:0,connecting:2,ringing:4,calling:5},s={KIT_LOG:"log",KIT_USER_STATUS_CHANGE:"userStatusChange",KIT_LOGIN_CHANGE:"loginChange",KIT_REGISTER_CHANGE:"registerChange",KIT_CALL_STATUS_CHANGE:"callStatusChange",KIT_SET_HOLD:"holdChange",KIT_SET_MUTE:"muteChange",KIT_CALL_ID_CHANGE:"callIdChange",KIT_ERROR:"error",KIT_INVITE:"invite",KIT_OUTGOING_INVITE:"outgoingInvite",CALL_CONNECTING:"connecting",CALL_RINGING:"ringing",AGENT_PICK_UP:"agentPickUp",CALL_PICK_UP:"pickUp",CALL_NO_ANSWER:"noAnswer",CALL_HANG_UP:"hangUp",CALL_END:"callEnd",CALL_CDR:"callCdr",SERVER_SOCKET_EVENT:"socketEvent",USER_STATUS_CHANGE:"userStatusChange",INCALL_CONNECT_EVENT:"IncallConnectEvent",SIP_CONNECT_EVENT:"sipConnectEvent",SIP_REGISTERER_EVENT:"sipRegistererEvent",SIP_SESSION_EVENT:"sipSessionEvent"},a={UNKNOWN_ERROR:-1,API_USER_LOGIN_ERROR:1000001,API_USER_STATUS_UPDATE_ERROR:1000002,API_USER_LOGOUT_ERROR:1000003,CONNECT_CALL_STATUS_ERROR:2000001,USER_NOT_LOGIN:2000002,WEBRTC_USER_MEDIA_ERROR:2000003,WEBRTC_HOLE_STATUS_ERROR:2000004,WEBRTC_AUDIO_PLAYER_ERROR:2000005,WEBRTC_AUDIO_PLAY_ERROR:2000006,WEBRTC_USER_AGENT_ERROR:2000007,WEBRTC_CALL_INVITE_ERROR:2000008,WEBRTC_REGISTER_ERROR:2000009,WEBRTC_MUTE_STATUS_ERROR:2000010,WEBRTC_CANCEL_REGISTER_ERROR:2000011,WEBRTC_MUTE_ERROR:2000012,SOCKET_CONNECT_ERROR:3000001,SOCKET_PING_TIMEOUT:3000002,SOKET_SERVER_ERROR:3000003,SOCKET_CALL_ERROR:3000004,SOCKET_RECONNECT_FAILED:3000005},J={info:9,success:4,warn:3,error:2,silent:1},E={PING:"PING",START:"START",AGENT_HANGUP:"AGENT_HANG_UP",CALL_CANCEL:"AGENT_CANCEL",HOLD:"AGENT_HOLD",UNHOLD:"AGENT_UN_HOLD",MUTE:"AGENT_MUTE",UNMUTE:"AGENT_UN_MUTE",CALL:"CALL",END:"STOP",AGENT_TRANSFER:"AGENT_TRANSFER",HANG_UP_REASON:"HANG_UP_REASON",ACK:"ACK"},p={PONG:"PONG",START_CONFIRM:"START_CONFIRM",CALL_SUCCESS:"CALL_SUCCESS",CALL_FAILED:"CALL_FAILED",CUSTOMER_RINGING:"CUSTOMER_RINGING",AGENT_PICK_UP:"AGENT_PICK_UP",CUSTOMER_PICK_UP:"CUSTOMER_PICK_UP",CUSTOMER_NO_ANSWER:"CUSTOMER_NO_ANSWER",CUSTOMER_HANG_UP:"CUSTOMER_HANG_UP",AGENT_NO_ANSWER:"AGENT_NO_ANSWER",AGENT_HANG_UP:"AGENT_HANG_UP",CALL_CDR:"CALL_CDR",STOP_CONFIRM:"STOP_CONFIRM",CLOSE:"CLOSE",ERROR:"ERROR",SESSION_ERROR:"SESSION_ERROR"},T={NONE:"NONE",INTERNAL:"INTERNAL"},w={audio:{autoGainControl:!0,noiseSuppression:!0,echoCancellation:!0},video:!1},R={phoneNum:1,workOrderId:2},L={enabled:!1,interval:5e3,maxSize:8192},A={enabled:!0,maxAttempts:3,delay:1e3,pingInterval:3e4,pingTimeout:5e3},O={enabled:!0,maxAttempts:3,delay:1e3};var U=class{callKit;constructor(t){this.callKit=t}async callStart(t){if(this.callKit.config.check()){if(this.callKit.logger.info("callStart",{caller:"Call.callStart",content:{startConfirm:this.callKit.socket.startConfirm}}),!this.callKit.socket.startConfirm){this.callKit.logger.warn("server not confirm start",{caller:"Call.callStart",content:{startConfirm:this.callKit.socket.startConfirm}});return}this.callKit.connect.call(async e=>{let i={...t?.extra||{},agentId:e.agentId,sourceType:e.sourceType};e.sourceType===R.phoneNum?i.phoneNum=e.extno:e.sourceType===R.workOrderId&&(i.workOrderId=e.workOrderId),this.callKit.socket.send(E.CALL,i)})}}async callRefer(t,e){this.callKit.config.check()&&(this.callKit.logger.info("callRefer",{caller:"Call.callRefer",content:{referTo:t,options:e}}),this.callKit.connect.refer(t,e))}async callEnd(t=!1,e=!1){this.callKit.connect.connectStatus!==h.init&&this.callKit.config.check()&&(this.callKit.logger.info("callEnd",{caller:"Call.callEnd",content:{isUnprompted:t,isError:e,connectStatus:this.callKit.connect.connectStatus}}),this.callKit.connect.hangup(t,e))}async callHold(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be held",{caller:"Call.callHold",content:{isHold:this.callKit.connect.isHolding(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setHold(!0)}}async callUnhold(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot unhold",{caller:"Call.callUnhold",content:{isHold:this.callKit.connect.isHolding(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setHold(!1)}}async callMute(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be muted",{caller:"Call.callMute",content:{isMuted:this.callKit.connect.isMuted(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setMute(!0)}}async callUnmute(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be unmuted",{caller:"Call.callUnmute",content:{isMuted:this.callKit.connect.isMuted(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setMute(!1)}}};var Y={name:"@koi-design/callkit",version:"2.0.5-beta.13",description:"callkit",author:"koi",license:"ISC",scripts:{build:"tsup",start:"vite",dev:"tsup --watch",lint:"eslint -c ../../.eslintrc.js --ext .jsx,.js,.tsx,.ts ./package --fix",release:"tsup && node scripts/pkg.js"},exports:{".":{types:"./dist/index.d.ts",require:"./dist/index.js",import:"./dist/index.mjs"}},main:"./dist/index.js",module:"./dist/index.mjs",types:"./dist/index.d.ts",files:["dist"],dependencies:{axios:"~0.26.1","blueimp-md5":"^2.12.0","eslint-plugin-jsonc":"^2.21.0","json-stringify-safe":"^5.0.1","sip.js":"^0.21.2"},devDependencies:{"@commitlint/cli":"^9.1.2","@commitlint/config-conventional":"^9.1.2","@koi-design/eslint-config-ts":"^0.0.14","@types/blueimp-md5":"^2.18.2",archiver:"^5.3.1",consola:"^3.4.2",eslint:"~8.29.0","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.0",husky:"^8.0.3","lint-staged":"^10.5.4",prettier:"^2.6.2",tsup:"6.6.3",typescript:"^4.6.3",vite:"^4"}};var G=class{callKit;constructor(t){this.callKit=t}config={version:`V${Y.version}`,host:"",log:"info",trackLogs:L,audioRef:void 0,constrains:w,socket:"",reconnect:{sip:O,incall:A},userInfo:{wsUrl:"",logGather:!1,sessionId:"",username:"",password:"",encryptionPassword:T.INTERNAL,sourceType:R.phoneNum,extno:"",workOrderId:"",userPart:"",agentId:"",fsUserId:"",fsPassword:"",fsIp:"",fsPort:"",iceInfo:[],iceGatheringTimeout:0,encryptionMethod:T.INTERNAL}};getConfig=()=>this.config;setConfig=async(t,e)=>{this.config[t]=e};setUserInfo=async(t,e)=>{this.config.userInfo[t]=e,this.callKit.logger.info("setUserInfo",{caller:"Config.setUserInfo",content:{key:t,value:e}})};reset=async()=>{this.isLogin()&&(this.config.userInfo={wsUrl:"",sessionId:"",username:"",password:"",encryptionPassword:"",userPart:"",sourceType:R.phoneNum,extno:"",workOrderId:"",agentId:"",fsUserId:"",fsPassword:"",fsIp:"",fsPort:"",iceInfo:[],iceGatheringTimeout:this.config.userInfo.iceGatheringTimeout,encryptionMethod:T.INTERNAL,logGather:!1},this.callKit.trigger(s.KIT_LOGIN_CHANGE,!1))};validate=()=>{let{userPart:t,fsIp:e,fsPassword:i,fsPort:n}=this.config.userInfo;return!(!t||!e||!n||!i)};isLogin=()=>this.validate();check(){return this.isLogin()?!0:(this.callKit.logger.warn("User not logged in",{caller:"Config.check",content:{errCode:a.USER_NOT_LOGIN}}),!1)}getTrackLogsConfig(){return{...L,...this.config?.trackLogs}}getReconnectConfig(t){return{...this.config?.reconnect?.[t]??(t==="sip"?O:A)}}enableTrackLogs(t){this.config.trackLogs.enabled=t}};import nt from"json-stringify-safe";function N(o){return J[o]}function st(o){let{timestamp:t,level:e,type:i="OTHER",message:n,caller:l,content:r}=o,f=String(e).toUpperCase();return`${t} [${f}] [${i}] [${l??"unknown"}] [${n}] ${nt(r)}`.trim()}function X(o){return new Blob([o]).size}var b=class{prefix="CallKit";level="info";pendingTrackLogs=[];trackLogsTimer=null;callKit;constructor(t,e){this.callKit=t,this.level=e||"info",this.startTrackLogsTimer()}startTrackLogsTimer(){let{interval:t}=this.callKit.config.getTrackLogsConfig();this.trackLogsTimer||(this.trackLogsTimer=setInterval(()=>{this.flushTrackLogs()},t))}flushTrackLogs(){if(this.pendingTrackLogs.length===0)return;let{enabled:t,maxSize:e}=this.callKit.config.getTrackLogsConfig();if(t)try{let i=[],n=[],l=0;for(let r of this.pendingTrackLogs){let f=X(r),C=n.length>0?`
1
+ import W from"blueimp-md5";import tt from"axios";var V=tt.create({headers:{"Content-Type":"application/x-www-form-urlencoded"},timeout:6e4});V.interceptors.request.use(o=>o);V.interceptors.response.use(o=>o.data,o=>Promise.reject(o));var et=o=>V.request(o),j=et;var P=class{callKit;constructor(t){this.callKit=t}isLogining=!1;isLoginOuting=!1;async login(t){if(this.isLogining){this.callKit.logger.info("login is already in progress cancel",{caller:"Api.login",content:{userName:t.userName,timestamp:t.timestamp}});return}this.isLogining=!0;try{return await this.post({url:"/auth/agentUser/login",method:"post",data:t})}finally{this.isLogining=!1}}async loginOut(t){if(this.isLoginOuting){this.callKit.logger.info("loginOut is already in progress cancel",{caller:"Api.loginOut",content:{sessionId:t.sessionId,timestamp:t.timestamp}});return}this.isLoginOuting=!0;try{return await this.post({url:"/auth/agentUser/loginOut",method:"post",data:t})}finally{this.isLoginOuting=!1}}async trackLogs(t){try{let{userInfo:e,host:i}=this.callKit.config.getConfig(),{sessionId:n}=e,l=new FormData;l.append("content",JSON.stringify([t]));let r={url:`${i}/agent/user/sdkLog`,method:"post",data:l,headers:{...n?{sessionId:n}:{}}};await j(r).catch(()=>{})}catch{}}async updateUserStatus(t){return this.post({url:"/agent/user/changeStatus",method:"post",data:t})}async post(t,e={skipLog:!1}){let{userInfo:i,host:n}=this.callKit.config.getConfig(),{sessionId:l}=i;if(t.url=`${n}${t.url}`,t.headers={"Content-Type":"application/x-www-form-urlencoded",...t.headers},t.headers["Content-Type"]==="application/x-www-form-urlencoded"&&e.useFormData){let k=new FormData,K=t.data||{};for(let c in K)Object.prototype.hasOwnProperty.call(K,c)&&k.append(c,K[c]);t.data=k}else t.data=new URLSearchParams(t.data).toString();l&&(t.headers.sessionId=l);let r=Date.now();e.skipLog||this.callKit.logger.info("API Request Start",{type:"API",caller:"API.Request",content:{url:t.url,headers:t.headers,data:t.data,extra:e,startTime:r}});let f=await j(t).catch(()=>{this.callKit.config.reset("api request error")}),C=Date.now();if(e.skipLog||this.callKit.logger.info("API Request Finish",{type:"API",caller:"API.Request",content:{url:t.url,duration:`${C-r}ms`,response:f}}),!f)throw this.callKit.reset(),new Error("Network error");let{code:u,data:v,message:F}=f;if(u==="000000")return v;throw u==="100013"&&this.callKit.config.reset("api request error"),new Error(F??"Request failed")}};var h={init:0,connecting:2,ringing:4,calling:5},s={KIT_LOG:"log",KIT_USER_STATUS_CHANGE:"userStatusChange",KIT_LOGIN_CHANGE:"loginChange",KIT_REGISTER_CHANGE:"registerChange",KIT_CALL_STATUS_CHANGE:"callStatusChange",KIT_SET_HOLD:"holdChange",KIT_SET_MUTE:"muteChange",KIT_CALL_ID_CHANGE:"callIdChange",KIT_ERROR:"error",KIT_INVITE:"invite",KIT_OUTGOING_INVITE:"outgoingInvite",CALL_CONNECTING:"connecting",CALL_RINGING:"ringing",AGENT_PICK_UP:"agentPickUp",CALL_PICK_UP:"pickUp",CALL_NO_ANSWER:"noAnswer",CALL_HANG_UP:"hangUp",CALL_END:"callEnd",CALL_CDR:"callCdr",SERVER_SOCKET_EVENT:"socketEvent",USER_STATUS_CHANGE:"userStatusChange",INCALL_CONNECT_EVENT:"IncallConnectEvent",SIP_CONNECT_EVENT:"sipConnectEvent",SIP_REGISTERER_EVENT:"sipRegistererEvent",SIP_SESSION_EVENT:"sipSessionEvent"},a={UNKNOWN_ERROR:-1,API_USER_LOGIN_ERROR:1000001,API_USER_STATUS_UPDATE_ERROR:1000002,API_USER_LOGOUT_ERROR:1000003,CONNECT_CALL_STATUS_ERROR:2000001,USER_NOT_LOGIN:2000002,WEBRTC_USER_MEDIA_ERROR:2000003,WEBRTC_HOLE_STATUS_ERROR:2000004,WEBRTC_AUDIO_PLAYER_ERROR:2000005,WEBRTC_AUDIO_PLAY_ERROR:2000006,WEBRTC_USER_AGENT_ERROR:2000007,WEBRTC_CALL_INVITE_ERROR:2000008,WEBRTC_REGISTER_ERROR:2000009,WEBRTC_MUTE_STATUS_ERROR:2000010,WEBRTC_CANCEL_REGISTER_ERROR:2000011,WEBRTC_MUTE_ERROR:2000012,SOCKET_CONNECT_ERROR:3000001,SOCKET_PING_TIMEOUT:3000002,SOKET_SERVER_ERROR:3000003,SOCKET_CALL_ERROR:3000004,SOCKET_RECONNECT_FAILED:3000005},J={info:9,success:4,warn:3,error:2,silent:1},E={PING:"PING",START:"START",AGENT_HANGUP:"AGENT_HANG_UP",CALL_CANCEL:"AGENT_CANCEL",HOLD:"AGENT_HOLD",UNHOLD:"AGENT_UN_HOLD",MUTE:"AGENT_MUTE",UNMUTE:"AGENT_UN_MUTE",CALL:"CALL",END:"STOP",AGENT_TRANSFER:"AGENT_TRANSFER",HANG_UP_REASON:"HANG_UP_REASON",ACK:"ACK"},p={PONG:"PONG",START_CONFIRM:"START_CONFIRM",CALL_SUCCESS:"CALL_SUCCESS",CALL_FAILED:"CALL_FAILED",CUSTOMER_RINGING:"CUSTOMER_RINGING",AGENT_PICK_UP:"AGENT_PICK_UP",CUSTOMER_PICK_UP:"CUSTOMER_PICK_UP",CUSTOMER_NO_ANSWER:"CUSTOMER_NO_ANSWER",CUSTOMER_HANG_UP:"CUSTOMER_HANG_UP",AGENT_NO_ANSWER:"AGENT_NO_ANSWER",AGENT_HANG_UP:"AGENT_HANG_UP",CALL_CDR:"CALL_CDR",STOP_CONFIRM:"STOP_CONFIRM",CLOSE:"CLOSE",ERROR:"ERROR",SESSION_ERROR:"SESSION_ERROR"},T={NONE:"NONE",INTERNAL:"INTERNAL"},w={audio:{autoGainControl:!0,noiseSuppression:!0,echoCancellation:!0},video:!1},R={phoneNum:1,workOrderId:2},L={enabled:!1,interval:5e3,maxSize:8192},A={enabled:!0,maxAttempts:3,delay:1e3,pingInterval:3e4,pingTimeout:5e3},O={enabled:!0,maxAttempts:3,delay:1e3};var U=class{callKit;constructor(t){this.callKit=t}async callStart(t){if(this.callKit.config.check()){if(this.callKit.logger.info("callStart",{caller:"Call.callStart",content:{startConfirm:this.callKit.socket.startConfirm}}),!this.callKit.socket.startConfirm){this.callKit.logger.warn("server not confirm start",{caller:"Call.callStart",content:{startConfirm:this.callKit.socket.startConfirm}});return}this.callKit.connect.call(async e=>{let i={...t?.extra||{},agentId:e.agentId,sourceType:e.sourceType};e.sourceType===R.phoneNum?i.phoneNum=e.extno:e.sourceType===R.workOrderId&&(i.workOrderId=e.workOrderId),this.callKit.socket.send(E.CALL,i)})}}async callRefer(t,e){this.callKit.config.check()&&(this.callKit.logger.info("callRefer",{caller:"Call.callRefer",content:{referTo:t,options:e}}),this.callKit.connect.refer(t,e))}async callEnd(t=!1,e=!1){this.callKit.connect.connectStatus!==h.init&&this.callKit.config.check()&&(this.callKit.logger.info("callEnd",{caller:"Call.callEnd",content:{isUnprompted:t,isError:e,connectStatus:this.callKit.connect.connectStatus}}),this.callKit.connect.hangup(t,e))}async callHold(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be held",{caller:"Call.callHold",content:{isHold:this.callKit.connect.isHolding(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setHold(!0)}}async callUnhold(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot unhold",{caller:"Call.callUnhold",content:{isHold:this.callKit.connect.isHolding(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setHold(!1)}}async callMute(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be muted",{caller:"Call.callMute",content:{isMuted:this.callKit.connect.isMuted(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setMute(!0)}}async callUnmute(){if(this.callKit.config.check()){if(!this.callKit.connect.isCalling()){this.callKit.logger.warn("Current state cannot be unmuted",{caller:"Call.callUnmute",content:{isMuted:this.callKit.connect.isMuted(),isCalling:this.callKit.connect.isCalling()}});return}this.callKit.connect.setMute(!1)}}};var Y={name:"@koi-design/callkit",version:"2.0.5-beta.15",description:"callkit",author:"koi",license:"ISC",scripts:{build:"tsup",start:"vite",dev:"tsup --watch",lint:"eslint -c ../../.eslintrc.js --ext .jsx,.js,.tsx,.ts ./package --fix",release:"tsup && node scripts/pkg.js"},exports:{".":{types:"./dist/index.d.ts",require:"./dist/index.js",import:"./dist/index.mjs"}},main:"./dist/index.js",module:"./dist/index.mjs",types:"./dist/index.d.ts",files:["dist"],dependencies:{axios:"~0.26.1","blueimp-md5":"^2.12.0","eslint-plugin-jsonc":"^2.21.0","json-stringify-safe":"^5.0.1","sip.js":"^0.21.2"},devDependencies:{"@commitlint/cli":"^9.1.2","@commitlint/config-conventional":"^9.1.2","@koi-design/eslint-config-ts":"^0.0.14","@types/blueimp-md5":"^2.18.2",archiver:"^5.3.1",consola:"^3.4.2",eslint:"~8.29.0","eslint-config-prettier":"^10.1.5","eslint-plugin-prettier":"^5.5.0",husky:"^8.0.3","lint-staged":"^10.5.4",prettier:"^2.6.2",tsup:"6.6.3",typescript:"^4.6.3",vite:"^4"}};var G=class{callKit;constructor(t){this.callKit=t}config={version:`V${Y.version}`,host:"",log:"info",trackLogs:L,audioRef:void 0,constrains:w,socket:"",reconnect:{sip:O,incall:A},userInfo:{wsUrl:"",logGather:!1,sessionId:"",username:"",password:"",encryptionPassword:T.INTERNAL,sourceType:R.phoneNum,extno:"",workOrderId:"",userPart:"",agentId:"",fsUserId:"",fsPassword:"",fsIp:"",fsPort:"",iceInfo:[],iceGatheringTimeout:0,encryptionMethod:T.INTERNAL}};getConfig=()=>this.config;setConfig=async(t,e)=>{this.config[t]=e};setUserInfo=async(t,e)=>{this.config.userInfo[t]=e,this.callKit.logger.info("setUserInfo",{caller:"Config.setUserInfo",content:{key:t,value:e}})};reset=async t=>{this.callKit.logger.info(`Reset User Info ${t}`,{caller:"Config.reset",type:"OTHER",content:{}}),this.isLogin()&&(this.config.userInfo={wsUrl:"",sessionId:"",username:"",password:"",encryptionPassword:"",userPart:"",sourceType:R.phoneNum,extno:"",workOrderId:"",agentId:"",fsUserId:"",fsPassword:"",fsIp:"",fsPort:"",iceInfo:[],iceGatheringTimeout:this.config.userInfo.iceGatheringTimeout,encryptionMethod:T.INTERNAL,logGather:!1},this.callKit.trigger(s.KIT_LOGIN_CHANGE,!1))};validate=()=>{let{userPart:t,fsIp:e,fsPassword:i,fsPort:n}=this.config.userInfo;return!(!t||!e||!n||!i)};isLogin=()=>this.validate();check(){return this.isLogin()?!0:(this.callKit.logger.warn("User not logged in",{caller:"Config.check",content:{errCode:a.USER_NOT_LOGIN}}),!1)}getTrackLogsConfig(){return{...L,...this.config?.trackLogs}}getReconnectConfig(t){return{...this.config?.reconnect?.[t]??(t==="sip"?O:A)}}enableTrackLogs(t){this.config.trackLogs.enabled=t}};import nt from"json-stringify-safe";function N(o){return J[o]}function st(o){let{timestamp:t,level:e,type:i="OTHER",message:n,caller:l,content:r}=o,f=String(e).toUpperCase();return`${t} [${f}] [${i}] [${l??"unknown"}] [${n}] ${nt(r)}`.trim()}function X(o){return new Blob([o]).size}var b=class{prefix="CallKit";level="info";pendingTrackLogs=[];trackLogsTimer=null;callKit;constructor(t,e){this.callKit=t,this.level=e||"info",this.startTrackLogsTimer()}startTrackLogsTimer(){let{interval:t}=this.callKit.config.getTrackLogsConfig();this.trackLogsTimer||(this.trackLogsTimer=setInterval(()=>{this.flushTrackLogs()},t))}flushTrackLogs(){if(this.pendingTrackLogs.length===0)return;let{enabled:t,maxSize:e}=this.callKit.config.getTrackLogsConfig();if(t)try{let i=[],n=[],l=0;for(let r of this.pendingTrackLogs){let f=X(r),C=n.length>0?`
2
2
  `:"",u=X(C);l+f+u>e&&n.length>0?(i.push(n.join(`
3
3
  `)),n=[r],l=f):(n.push(r),l+=f+u)}n.length>0&&i.push(n.join(`
4
- `));for(let r of i)this.callKit.api.trackLogs(r);this.pendingTrackLogs=[]}catch(i){console.error(i)}}destroy(){this.trackLogsTimer&&(clearInterval(this.trackLogsTimer),this.trackLogsTimer=null),this.flushTrackLogs()}setLevel(t){this.level=t}info(t,e){let i=this.catchLog(t,e,"info");N(this.level)>=N("info")&&console.log(`%c${i}`,"color: gray;")}success(t,e){let i=this.catchLog(t,e,"success");N(this.level)>=N("success")&&console.log(`%c${i}`,"color: green;")}warn(t,e){let i=this.catchLog(t,e,"warn");N(this.level)>=N("warn")&&console.log(`%c${i}`,"color: orange;")}error(t,e,i=!1){let n=t instanceof Error?t.message:t,l=this.catchLog(n,e,"error");N(this.level)>=N("error")&&console.log(`%c${l}`,"color: red;");let{errCode:r,...f}=e?.content??{},C=r??a.UNKNOWN_ERROR;i||this.callKit.trigger(s.KIT_ERROR,{code:C,msg:n,data:f});let u=new Error(n);throw u.name="CallKitError",u.code=C,u.data=f,u}catchLog(t,e,i){let n=new Date,{enabled:l}=this.callKit.config.getTrackLogsConfig(),{userInfo:r}=this.callKit.config.getConfig(),f={agentId:r?.agentId,sessionId:r?.sessionId,...e?.content??{}},C={timestamp:n.toLocaleString().replace("T"," ").replace(".000Z",""),level:i,message:t,caller:e?.caller,type:e?.type,content:f},u=st(C);return l&&this.pendingTrackLogs.push(u),this.callKit.trigger(s.KIT_LOG,u,!0),u}};import{UserAgent as j,Web as rt,Registerer as ot,SessionState as y,RegistererState as M}from"sip.js";var Z=o=>{let t=o["x-antaios-manual-extend_info"]||o["x-antaios-manual-extend-info"],e=null;try{if(t&&typeof t=="string"){let i=t.replace(/\\/g,"");return e=JSON.parse(i),e}}catch{return{}}};var D=6;function ct(o){return o.replace(/(\w+):\s*'(.*?)'/g,'"$1": "$2"').replace(/'/g,'"')}var B=o=>{o&&o.getTracks().forEach(t=>t.stop())},at=()=>{typeof navigator.mediaDevices>"u"&&(navigator.mediaDevices={}),typeof navigator.mediaDevices.getUserMedia>"u"&&(navigator.mediaDevices.getUserMedia=o=>{let t=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia;return t?new Promise((e,i)=>{t.call(navigator,o,e,i)}):Promise.reject(new Error("Unable to obtain device permissions. Please check your browser settings or device permissions."))})},x=class{callKit;isMute=!1;isRegister=!1;isHold=!1;connectStatus=h.init;currentSession;mediaStream;userAgent;registerer;isReConnected=!1;isOutgoing=!1;isUnprompted=!1;hasInvite=!1;constructor(t){this.callKit=t}get reconnectConfig(){return this.callKit.config.getReconnectConfig("sip")}currentCallId=null;getCurrentCallId(){return this.currentCallId}setOutgoing(t){this.isOutgoing!==t&&(this.callKit.logger.info("setOutgoing",{caller:"Connect.setOutgoing",content:{outgoing:t}}),this.isOutgoing=t)}setCallId(t){this.callKit.logger.info("setCallId",{caller:"Connect.setCallId",content:{callId:t}}),this.currentCallId=t,this.callKit.trigger(s.KIT_CALL_ID_CHANGE,t)}async reset(){if(this.setOutgoing(!1),this.isUnprompted=!1,this.hasInvite=!1,this.isHolding()&&await this.setHold(!1),this.isMuted()&&await this.setMute(!1),this.connectStatus!==h.init&&this.setConnectStatus(h.init),this.isRegistered()&&await this.unregister(),this.currentCallId&&this.setCallId(null),this.currentSession=void 0,this.mediaStream=void 0,this.userAgent=void 0,this.registerer=void 0,this.mediaStream)try{B(this.mediaStream);let t=this.getAduioReference();t&&(t.pause(),t.srcObject=null)}catch(t){this.callKit.logger.error(t,{caller:"Connect.reset",content:{}})}this.setConnectStatus(h.init),this.clearHeartbeat()}getAduioReference(){let{audioRef:t}=this.callKit.config.getConfig();return typeof t=="function"?t():t}async permission(){this.callKit.logger.info("permission",{caller:"Connect.permission",content:{permission:!0}}),at();let t=await navigator.mediaDevices.getUserMedia({audio:!0});B(t)}isConnecting(){return this.connectStatus===h.connecting}isCalling(){return this.connectStatus===h.calling}isRinging(){return this.connectStatus===h.ringing}isHolding(){return this.isHold}isRegistered(){return this.isRegister}isMuted(){return this.isMute}isInit(){return this.connectStatus===h.init}heartbeatInterval;heartbeatFlag=D;clearHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null),this.heartbeatFlag=D}startHeartbeat(){this.heartbeatFlag=D,this.clearHeartbeat(),this.heartbeatInterval=setInterval(()=>{this.heartbeatFlag-=1,this.heartbeatFlag<=0&&(this.heartbeatFlag=D,this.callKit.trigger(s.SIP_CONNECT_EVENT,{event:"OPTIONS_HEARTBEAT_EXPIRED"}))},1e3)}socketTriggerHangup(t){!this.isCalling()||t!==this.currentCallId||(this.callKit.logger.info("socketHangup trigger hangup",{caller:"Connect.socketHangup",content:{callId:t,currentCallId:this.currentCallId}}),this.callKit.hangup())}async register(){if(this.connectStatus!==h.init){if(this.isRegistered()){this.callKit.logger.warn("connectStatus is registered",{caller:"Connect.register",content:{errCode:a.CONNECT_CALL_STATUS_ERROR}});return}this.callKit.reset(),this.callKit.logger.error("connectStatus is not init",{caller:"Connect.register",content:{errCode:a.CONNECT_CALL_STATUS_ERROR}});return}this.callKit.logger.info("connect register",{caller:"Connect.register",content:{connectStatus:this.connectStatus}}),await this.permission().catch(c=>{this.callKit.reset(),this.callKit.logger.error(c,{caller:"Connect.register",content:{errCode:a.WEBRTC_USER_MEDIA_ERROR}})});let{userInfo:t,constrains:e}=this.callKit.config.getConfig(),i=async()=>(this.mediaStream=await navigator.mediaDevices.getUserMedia(e),this.mediaStream),{userPart:n,fsIp:l,fsPort:r,iceInfo:f,wsUrl:C}=t,u={uri:j.makeURI(`sip:${n}@${l}:${r}`),displayName:n,transportOptions:{wsServers:[C],traceSip:!0},logLevel:"error",allowLegacyNotifications:!0,contactName:n,sessionDescriptionHandlerFactory:rt.defaultSessionDescriptionHandlerFactory(i),sessionDescriptionHandlerFactoryOptions:{constraints:e,iceGatheringTimeout:t.iceGatheringTimeout,peerConnectionConfiguration:{iceServers:JSON.parse(ct(f))}}};this.callKit.logger.info("connect connectConfig",{caller:"Connect.register",content:u}),this.userAgent=new j(u);let v=new MediaStream,F=c=>{let m=this.getAduioReference();this.callKit.logger.info("connect setupRemoteMedia",{caller:"Connect.register.setupRemoteMedia",content:m}),c.sessionDescriptionHandler.peerConnection.getReceivers().forEach(S=>{S.track&&v.addTrack(S.track)}),m?(m.srcObject=v,m.play().catch(S=>{this.callKit.logger.error(S.message,{caller:"Connect.register.setupRemoteMedia",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})})):this.callKit.logger.error("video is not exist",{caller:"Connect.register",content:{errCode:a.WEBRTC_AUDIO_PLAYER_ERROR}})},k=(c,m)=>{let{that:S=this}=m,I=c.userAgentCore,g=I.receiveIncomingRequestFromTransport.bind(I);I.receiveIncomingRequestFromTransport=d=>(d.method==="OPTIONS"&&S.startHeartbeat(),S.callKit.logger.info(`SIP Receive: ${d?.method}`,{caller:"Connect.register.observeSocketStatus.receiveRequest",type:"SIP",content:{request:d}}),g(d));let $=I.receiveIncomingResponseFromTransport.bind(I);I.receiveIncomingResponseFromTransport=d=>(S.callKit.logger.info(`SIP Receive Response: ${d?.statusCode} ${d?.reasonPhrase}`,{caller:"Connect.register.observeSocketStatus.receiveResponse",type:"SIP",content:{response:d}}),$(d));let{transport:_}=c;if(_){let d=_.send.bind(_);_.send=q=>(S.callKit.logger.info("SIP send message",{caller:"Connect.register.observeSocketStatus",type:"SIP",content:{message:q.toString()}}),d(q))}},K={};this.registerer=new ot(this.userAgent,K),this.registerer.stateChange.addListener(c=>{switch(c){case M.Initial:this.callKit.logger.info("registerer stateChange Initial",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!1),this.setConnectStatus(h.init),this.callKit.trigger(s.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case M.Registered:this.callKit.logger.info("registerer stateChange Registered",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!0),this.callKit.trigger(s.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case M.Terminated:this.callKit.logger.info("registerer stateChange Terminated",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!1),this.setConnectStatus(h.init),this.callKit.trigger(s.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case M.Unregistered:this.callKit.logger.info("registerer stateChange Unregistered",{caller:"Connect.register.registererStateChange",type:"SIP",content:{isRegistered:this.isRegistered(),registererState:c}}),this.setRegister(!1),this.setConnectStatus(h.init),this.callKit.trigger(s.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;default:break}}),this.userAgent.delegate={onInvite:c=>{this.callKit.logger.info("connect onInvite",{type:"SIP",caller:"Connect.register.onInvite",content:{invite:c,isRegistered:this.isRegistered(),isOutgoing:this.isOutgoing}}),this.currentSession=c,this.currentSession.stateChange.addListener(g=>{switch(g){case y.Establishing:this.callKit.logger.info("connect Establishing",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:g}}),this.setConnectStatus(h.ringing),this.callKit.trigger(s.SIP_SESSION_EVENT,{sessionState:g,isRegistered:this.isRegistered()});break;case y.Established:this.callKit.logger.info("connect Established",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:g}}),this.callKit.connect.setConnectStatus(h.calling),this.callKit.trigger(s.SIP_SESSION_EVENT,{sessionState:g,isRegistered:this.isRegistered()}),F(this.currentSession);break;case y.Terminating:this.callKit.trigger(s.SIP_SESSION_EVENT,{sessionState:g,isRegistered:this.isRegistered()});break;case y.Terminated:this.callKit.logger.info("connect Terminated",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:g}}),this.hasInvite=!1,this.isUnprompted||this.callKit.callCenter.callEnd(),this.isUnprompted=!1,this.callKit.trigger(s.SIP_SESSION_EVENT,{sessionState:g,isRegistered:this.isRegistered()});break;default:break}});let m={sessionDescriptionHandlerOptions:{constraints:e,alwaysAcquireMediaFirst:!0}},S=()=>{let{request:g}=this.currentSession,$=Object.keys(g.headers),_={};return $.filter(d=>d.toLocaleLowerCase().startsWith("x-antaios")).forEach(d=>{_[d.toLocaleLowerCase()]=g.getHeader(d)}),this.callKit.logger.info("get invite data",{caller:"Connect.register.onInvite",content:_}),_},I=S();try{let g=Z(I);g?.callUuid?this.setCallId(g.callUuid):(this.setCallId(null),this.callKit.logger.warn("call id is not exist",{caller:"Connect.register.onInvite",content:{inviteData:g}}))}catch(g){this.callKit.logger.info(g,{caller:"Connect.register.onInvite",content:I})}if(this.isOutgoing)this.currentSession.accept(m),this.callKit.trigger(s.KIT_OUTGOING_INVITE,{getInviteData:S});else{this.hasInvite=!0;let g=()=>{this.currentSession?.state!==y.Terminated&&this.currentSession?.state!==y.Terminating&&this.currentSession.reject(),this.hasInvite=!1,this.callKit.callCenter.callEnd(!0,!1)};this.callKit.trigger(s.KIT_INVITE,{accept:()=>{this.callKit.trigger(s.CALL_CONNECTING,new Date),this.hasInvite=!1,this.currentSession.accept(m)},reject:g,getInviteData:S})}},onConnect:async()=>{this.reconnectAttempts=0,this.reconnectTimer=null,this.callKit.logger.info("connect onConnect",{caller:"Connect.register",type:"SIP",content:{version:`${this.callKit.config.getConfig().version}`}}),await this.registerer.register().catch(async c=>{this.callKit.reset(),this.callKit.logger.error(c?.message,{caller:"Connect.register",type:"SIP",content:{errCode:a.WEBRTC_REGISTER_ERROR}})})},onDisconnect:c=>{c?(this.callKit.logger.warn("SIP User Agent Disconnected with error",{caller:"Connect.register",type:"SIP",content:{err:c.message,errCode:a.WEBRTC_USER_AGENT_ERROR}}),this.startReconnectTimer()):this.callKit.logger.warn("SIP User Agent Disconnected",{caller:"Connect.register",type:"SIP",content:{}})},onRegister:()=>{this.callKit.logger.info("connect onRegister",{caller:"Connect.register",type:"SIP",content:{version:`V${this.callKit.config.getConfig().version}`}})}},k(this.userAgent,{that:this}),await this.userAgent.start().catch(c=>{this.callKit.reset(),this.callKit.logger.error(c,{caller:"Connect.register",type:"SIP",content:{errCode:a.WEBRTC_USER_AGENT_ERROR}})})}reconnectTimer;reconnectAttempts=0;startReconnectTimer(){if(this.reconnectAttempts>=this.reconnectConfig.maxAttempts&&this.callKit.config.isLogin()){this.callKit.reset(),this.callKit.logger.error("Reconnect failed max attempts",{caller:"Connect.startReconnectTimer",type:"SIP",content:{errCode:a.SOCKET_RECONNECT_FAILED,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}});return}this.callKit.logger.info("Reconnect timer started",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}}),this.reconnectAttempts+=1,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer&&this.callKit.config.isLogin()?(this.userAgent?.reconnect(),this.callKit.logger.info("Reconnect attempt",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}})):this.callKit.logger.info("Reconnect timer already expired",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}})},this.reconnectConfig.delay)}async stop(){await this.userAgent.stop()}async unregister(){if(this.callKit.logger.info("connect unregister",{caller:"Connect.unregister",type:"SIP",content:{isRegistered:this.isRegistered()}}),!this.isRegistered()||!this.registerer){this.callKit.logger.warn("No registerer to unregister.",{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}});return}await this.registerer.unregister({all:!0}).catch(t=>{this.callKit.logger.warn(t,{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}})}).finally(()=>{this.setRegister(!1)}),await this.userAgent?.stop().catch(t=>{this.callKit.logger.warn(t,{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}})})}async call(t){this.callKit.logger.info("connect call",{caller:"Connect.call",type:"SIP",content:{callback:t}}),this.setOutgoing(!0),this.isRegistered()||await this.register(),this.setConnectStatus(h.connecting),this.callKit.trigger(s.CALL_CONNECTING,new Date);let{userInfo:e}=this.callKit.config.getConfig();t(e)}setRegister(t){this.isRegister!==t&&(this.callKit.logger.info("connect setRegister",{caller:"Connect.setRegister",type:"SIP",content:{register:t}}),this.isRegister=t,this.callKit.trigger(s.KIT_REGISTER_CHANGE,t))}setConnectStatus(t){this.callKit.logger.info("connect setConnectStatus",{caller:"Connect.setConnectStatus",type:"SIP",content:{status:t}}),this.connectStatus=t,this.callKit.trigger(s.KIT_CALL_STATUS_CHANGE,t)}async hangup(t=!1,e=!1){if(this.callKit.logger.info("connect hangup",{caller:"Connect.hangup",type:"SIP",content:{isUnprompted:t,isError:e,connectStatus:this.connectStatus}}),this.setOutgoing(!1),this.isUnprompted=t,this.setHold(!1),this.setMute(!1),this.connectStatus!==h.init)try{t&&(this.isRinging()||this.isCalling())&&(this.hasInvite?(this.currentSession?.state!==y.Terminated&&this.currentSession?.state!==y.Terminating&&this.currentSession.reject(),this.hasInvite=!1):await this.currentSession?.bye()),B(this.mediaStream);let i=this.getAduioReference();i&&(i.pause(),i.srcObject=null),this.setConnectStatus(h.init),this.callKit.trigger(s.CALL_END,new Date),this.setCallId(null)}catch(i){this.callKit.trigger(s.CALL_END,new Date),this.callKit.reset(),this.callKit.logger.error(i,{caller:"Connect.hangup",type:"SIP",content:{connectStatus:this.connectStatus,isError:e,isUnprompted:t}})}}getRemoteMediaStream(t){this.callKit.logger.info("connect getRemoteMediaStream",{caller:"Connect.getRemoteMediaStream",type:"SIP",content:{session:t}});let e=t.sessionDescriptionHandler;if(e)return e.remoteMediaStream}setupRemoteMedia(t){this.callKit.logger.info("connect setupRemoteMedia",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{session:t}});let e=this.getRemoteMediaStream(t),i=this.getAduioReference();i?(i.autoplay=!0,i.srcObject=e,i.play().catch(n=>{this.callKit.logger.error(n.message,{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})}),e.onaddtrack=()=>{this.callKit.logger.info("Remote media onaddtrack",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{session:t}}),i.load(),i.play().catch(n=>{this.callKit.logger.error(n.message,{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})})}):this.callKit.logger.error("video is not exist",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAYER_ERROR}})}async setHold(t){if(this.isHold===t){this.callKit.logger.warn("Already holding",{caller:"Connect.setHold",type:"SIP",content:{isHold:this.isHold}});return}this.callKit.socket.send(t?E.HOLD:E.UNHOLD),this.isHold=t,this.callKit.logger.info("connect setHold",{caller:"Connect.setHold",type:"SIP",content:{hold:t}}),this.callKit.trigger(s.KIT_SET_HOLD,t)}async setMute(t){if(this.isMute===t){this.callKit.logger.warn("Already muted",{caller:"Connect.setMute",type:"SIP",content:{isCalling:this.isCalling(),isMuted:this.isMuted()}});return}this.callKit.socket.send(t?E.MUTE:E.UNMUTE),this.isMute=t,this.callKit.trigger(s.KIT_SET_MUTE,t)}async refer(t,e){this.callKit.logger.info("connect refer",{caller:"Connect.refer",type:"SIP",content:{referTo:t,extra:e}});let i;t&&(i=j.makeURI(t)),this.currentSession.refer(i,e?.sessionReferOptions)}};var H=class{callKit;ws;lastPingTime=void 0;pingTimer;reconnectTimer;reconnectAttempts=0;connectAuthState={startConfirm:!1,isConnected:!1,isReconnecting:!1,isError:!1};get startConfirm(){return this.connectAuthState.startConfirm}get isError(){return this.connectAuthState.isError}constructor(t){this.callKit=t}get reconnectConfig(){return this.callKit.config.getReconnectConfig("incall")}init(){let{socket:t}=this.callKit.config.getConfig();this.callKit.logger.info(`socket init: ${t}`,{caller:"Socket.init",type:"INCALL",content:{socket:t}}),this.connect(t)}setConnectAuthState(t,e){this.connectAuthState[t]!==e&&(this.connectAuthState[t]=e)}handleDisconnect(){this.setConnectAuthState("isConnected",!1);let{enabled:t}=this.reconnectConfig;if(!this.callKit.config.isLogin()||!t){this.callKit.reset(),this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_NOT_CONNECTED"});return}this.connectAuthState.isReconnecting||this.connectAuthState.isError||this.attemptReconnect()}clearWebSocket(){this.ws&&(this.ws.onopen=null,this.ws.onclose=null,this.ws.onerror=null,this.ws.onmessage=null),(this.ws?.readyState===WebSocket.CONNECTING||this.ws?.readyState===WebSocket.OPEN)&&(this.ws?.close(1e3,"socket close"),this.callKit.logger.info("socket clear",{caller:"Socket.clearWebSocket",type:"INCALL",content:{}})),this.ws=void 0,this.setConnectAuthState("isConnected",!1)}connect(t){this.ws&&this.clearWebSocket(),this.ws=new WebSocket(t),this.ws.onopen=e=>this.onOpen(e),this.ws.onclose=e=>this.onClose(e),this.ws.onerror=e=>this.onError(e),this.ws.onmessage=e=>this.onMessage(e)}onOpen(t){this.callKit.logger.info("socket onOpen",{caller:"Socket.onOpen",type:"INCALL",content:{ev:t}}),this.setConnectAuthState("isConnected",!0),this.lastPingTime=Date.now(),this.checkPing(),this.send(E.START),this.connectAuthState.isReconnecting&&(this.setConnectAuthState("isReconnecting",!1),this.callKit.logger.info("reconnect success",{caller:"Socket.onOpen",type:"INCALL",content:{event:"INCALL_RECONNECT_SUCCESS",reconnectAttempts:this.reconnectAttempts}}),this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_SUCCESS"}))}cleanReconnectState(){this.reconnectAttempts=0,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.setConnectAuthState("isReconnecting",!1),this.setConnectAuthState("isError",!1)}resetConnectState(){this.connectAuthState={startConfirm:!1,isConnected:!1,isReconnecting:!1,isError:!1},this.cleanReconnectState(),this.callKit.logger.info("reset connect state",{caller:"Socket.resetConnectState",type:"INCALL",content:{reconnectAttempts:this.reconnectAttempts,connectAuthState:this.connectAuthState}})}onClose(t){this.callKit.logger.info("socket onClose",{caller:"Socket.onClose",type:"INCALL",content:{ev:t}}),this.handleDisconnect()}onError(t){this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_CONNECT_ERROR",err:t}),this.callKit.logger.error("socket onError",{caller:"Socket.onError",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR,data:t}})}confirmAck(t){let{ack:e,messageId:i}=t;e&&this.send(E.ACK,{messageId:i})}onMessage(t){let e=JSON.parse(t.data),i=e.data;try{typeof e.data=="string"&&e.data&&(i=JSON.parse(e.data))}catch{this.callKit.logger.info("socket onMessage parse error",{caller:"Socket.onMessage",type:"INCALL",content:{data:e.data}})}this.callKit.logger.info(`socket onMessage: ${e.event}`,{caller:"Socket.onMessage",type:"INCALL",content:{data:i,event:e.event}}),this.confirmAck(e);let n=i?.callUuid||"";if(e.event===p.PONG){this.lastPingTime=Date.now();return}if(e.event===p.START_CONFIRM&&(this.setConnectAuthState("startConfirm",!0),this.cleanReconnectState()),e.event===p.CUSTOMER_RINGING&&this.callKit.trigger(s.CALL_RINGING,{time:new Date,callUuid:n}),e.event===p.CUSTOMER_PICK_UP&&this.callKit.trigger(s.CALL_PICK_UP,{time:new Date,callUuid:n}),e.event===p.AGENT_PICK_UP&&this.callKit.trigger(s.AGENT_PICK_UP,{time:new Date,callUuid:n}),e.event===p.CUSTOMER_HANG_UP&&(this.callKit.trigger(s.CALL_HANG_UP,{time:new Date,callUuid:n}),n&&this.callKit.connect.socketTriggerHangup(n)),e.event===p.CUSTOMER_NO_ANSWER&&(this.callKit.trigger(s.CALL_NO_ANSWER,{time:new Date,callUuid:n}),n&&this.callKit.connect.socketTriggerHangup(n)),e.event===p.CALL_CDR&&this.callKit.trigger(s.CALL_CDR,{time:new Date,callUuid:n,...i}),e.event===p.CLOSE){let{userInfo:l}=this.callKit.config.getConfig();this.send(E.END,{agentId:l.agentId,callUuid:n})}e.event===p.ERROR&&(this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error(e.msg,{caller:`Socket.onMessage:${e.event}`,type:"INCALL",content:{errCode:a.SOKET_SERVER_ERROR,data:i,callUuid:n}})),e.event===p.SESSION_ERROR&&(this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error(e.msg,{caller:`Socket.onMessage:${e.event}`,type:"INCALL",content:{data:i,event:p.SESSION_ERROR,callUuid:n}})),e.event===p.AGENT_NO_ANSWER&&n&&this.callKit.connect.socketTriggerHangup(n),e.event===p.AGENT_HANG_UP&&n&&this.callKit.connect.socketTriggerHangup(n),this.callKit.trigger(s.SERVER_SOCKET_EVENT,{...e,callUuid:n})}send(t,e){if(!this.connectAuthState.isConnected){this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_NOT_CONNECTED"}),this.callKit.reset(),this.callKit.logger.error("socket not connected",{caller:"Socket.send",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR}});return}let{userInfo:i,version:n}=this.callKit.config.getConfig(),{sessionId:l,extno:r,agentId:f}=i;if(this.callKit.logger.info("Socket send",{caller:"Socket.send",type:"INCALL",content:{agentId:f,sessionId:l,userInfo:i}}),!l){this.callKit.logger.error("sessionId is empty",{caller:"Socket.send",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR}});return}let C={event:t,sessionId:l,version:n,...e};E.CALL===t&&(C.phoneNum=r,C.agentId=f,e?.sourceType===R.phoneNum?delete C.workOrderId:e?.sourceType===R.workOrderId&&delete C.phoneNum),this.callKit.logger.info("socket send",{caller:"Socket.send",type:"INCALL",content:{...C}}),this.ws?.send(JSON.stringify({event:t,...C}))}ping(){if(!this.connectAuthState.isConnected)return;this.send(E.PING);let t=Date.now(),{pingInterval:e,pingTimeout:i}=this.reconnectConfig;t-this.lastPingTime>e+i&&(this.ws&&this.connectAuthState.isConnected?this.ws.close(4001,"ping timeout"):this.callKit.reset(),this.callKit.logger.error("socket ping timeout",{caller:"Socket.ping",type:"INCALL",content:{errCode:a.SOCKET_PING_TIMEOUT}}),this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_PING_TIMEOUT"}))}checkPing(){this.pingTimer&&clearInterval(this.pingTimer);let{pingInterval:t}=this.reconnectConfig;this.pingTimer=setInterval(()=>{this.ping()},t)}async reset(t){let{force:e=!1}=t||{};this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=void 0),e&&(this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_RESET"}),this.resetConnectState()),this.lastPingTime=void 0,this.setConnectAuthState("startConfirm",!1),this.clearWebSocket()}attemptReconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0);let{maxAttempts:t}=this.reconnectConfig;if(this.reconnectAttempts>=t){this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_ERROR"}),this.callKit.reset(),this.callKit.logger.error("Maximum reconnection attempts reached",{caller:"Socket.attemptReconnect",type:"INCALL",content:{errCode:a.SOCKET_RECONNECT_FAILED,reconnectAttempts:this.reconnectAttempts}});return}this.reconnectAttempts===0&&this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_START"}),this.setConnectAuthState("isReconnecting",!0),this.reconnectAttempts+=1;let{delay:e}=this.reconnectConfig;this.callKit.logger.info(`Preparing reconnection attempt ${this.reconnectAttempts}/${t}, delay: ${e}ms`,{caller:"Socket.attemptReconnect",type:"INCALL",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:t,delay:e}}),this.reconnectTimer=setTimeout(()=>{let{socket:i}=this.callKit.config.getConfig();this.connect(i)},e)}};var Q=class{api;config;logger;callCenter;connect;socket;listener=[];constructor(t){this.config=new G(this),this.api=new P(this),this.connect=new x(this),this.callCenter=new U(this),this.socket=new H(this),this.logger=new b(this,t.log),t.log&&this.config.setConfig("log",t.log),t.trackLogs&&this.config.setConfig("trackLogs",{...L,...t.trackLogs}),t.audioRef&&this.config.setConfig("audioRef",t.audioRef),t.host&&this.config.setConfig("host",t.host),this.config.setConfig("constrains",t.constrains||w),this.config.setConfig("socket",t.socket),this.config.setConfig("reconnect",{sip:{...O,...t.reconnect?.sip||{}},incall:{...A,...t.reconnect?.incall||{}}}),this.logger.info("callKit init",{caller:"CallKit.init",content:t})}async login(t,e,i={encryptionMethod:T.INTERNAL}){if(this.config.isLogin()){this.logger.warn("already login",{caller:"CallKit.login",content:{username:t,password:e,extra:i}});return}let n="",{encryptionMethod:l=T.INTERNAL}=i;switch(l){case T.NONE:n=e;break;case T.INTERNAL:n=W(t+W(e));break;default:n=W(t+W(e));break}if(this.logger.info("login info:",{caller:"CallKit.login",content:{username:t,password:e,encryptionMethod:l,encryptionPassword:n}}),this.socket.isError){this.logger.warn("socket is error",{caller:"CallKit.login",content:{username:t,password:e,extra:i,socketError:this.socket.isError}});return}try{let r=await this.api.login({userName:t,password:n,timestamp:Date.now()});r&&(this.config.setConfig("userInfo",{wsUrl:`wss://${r.wsUrl}`,sessionId:r.sessionId,username:t,password:n,encryptionPassword:n,agentId:r.agentId,fsUserId:r.fsUserId,userPart:r.userPart,fsPassword:r.fsPassword,fsIp:r.fsIp,fsPort:r.fsPort,iceInfo:r.iceInfo,iceGatheringTimeout:r.iceGatheringTimeout,logGather:r.logGather,...i}),this.socket.init(),this.trigger(s.KIT_LOGIN_CHANGE,!0))}catch(r){this.logger.error(r,{caller:"CallKit.login",content:{errCode:a.API_USER_LOGIN_ERROR}})}}async logout({isReset:t=!0}={isReset:!0}){if(!this.config.check())return;let{userInfo:e}=this.config.getConfig();if(this.logger.info("logout",{caller:"CallKit.logout",content:{sessionId:e.sessionId}}),this.config.isLogin()){let{sessionId:i}=e;try{await this.api.loginOut({sessionId:i,timestamp:Date.now()})}catch(n){this.logger.warn(n,{caller:"CallKit.logout",content:{errCode:a.API_USER_LOGOUT_ERROR}})}}t?await this.reset():this.config.reset()}async call(t="",e={sourceType:R.phoneNum,workOrderId:""}){if(!this.config.check())return;if(!this.connect.isRegistered){this.logger.warn("Currently not registered",{caller:"CallKit.call",content:{extno:t,options:e}});return}let{sourceType:i,workOrderId:n}=e;this.config.setUserInfo("sourceType",i),i===R.phoneNum?t&&this.config.setUserInfo("extno",t):i===R.workOrderId&&n&&this.config.setUserInfo("workOrderId",n),this.logger.info("call",{caller:"CallKit.call",content:{extno:t,options:e}}),this.callCenter.callStart(e)}async refer(t,e){this.config.check()&&(this.logger.info("refer",{caller:"CallKit.refer",content:{uri:t,options:e}}),this.callCenter.callRefer(t,e))}async register(){this.config.check()&&(this.logger.info("register",{caller:"CallKit.register",content:{}}),this.connect.register())}async unregister(){this.config.check()&&(this.logger.info("unregister",{caller:"CallKit.unregister",content:{}}),this.connect.unregister())}async hangup(){if(this.config.check()){if(this.logger.info("hangup",{caller:"CallKit.hangup",content:{connectStatus:this.connect.connectStatus}}),!this.connect.isConnecting()&&!this.connect.isRinging()&&!this.connect.isCalling()&&!this.connect.isHolding()){this.logger.warn("Currently not in a call",{caller:"CallKit.hangup",content:{connectStatus:this.connect.connectStatus}});return}await this.callCenter.callEnd(!0)}}hold(){this.config.check()&&(this.logger.info("hold",{caller:"CallKit.hold",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callHold())}unhold(){this.config.check()&&(this.logger.info("unhold",{caller:"CallKit.unhold",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callUnhold())}mute(){this.config.check()&&(this.logger.info("mute",{caller:"CallKit.mute",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callMute())}unmute(){this.config.check()&&(this.logger.info("unmute",{caller:"CallKit.unmute",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callUnmute())}async setUserStatus(t,e={}){let{agentId:i}=this.config.getConfig().userInfo;this.logger.info("setUserStatus",{caller:"CallKit.setUserStatus",content:{status:t,agentId:i}}),await this.api.updateUserStatus({agentId:i,userStatus:t,timestamp:Date.now(),...e})}async reset(t){let{force:e=!1}=t||{};this.logger.info("reset",{caller:"CallKit.reset",content:{connectStatus:this.connect.connectStatus,force:e}}),this.connect.isCalling()&&await this.hangup(),await this.connect.reset(),this.config.isLogin()?await this.logout({isReset:!1}):await this.config.reset(),await this.socket.reset({force:e})}on(t,e){this.listener.push({event:t,callback:e})}off(t,e){this.logger.info(`off ${t}`,{caller:"CallKit.off",content:{event:t}}),e?this.listener=this.listener.filter(i=>!(i.event===t&&i.callback===e)):this.listener=this.listener.filter(i=>i.event!==t)}removeAllListeners(){this.listener=this.listener.splice(0,this.listener.length),this.logger.info("removeAllListeners",{caller:"CallKit.removeAllListeners",content:{listener:this.listener}})}trigger(t,e,i=!1){i||this.logger.info(`Trigger Event: ${t}`,{caller:"CallKit.trigger",content:e}),this.listener.forEach(n=>{if(n.event===t)try{n.callback(e)}catch(l){this.logger.error(`Event callback error: ${t}`,l,!0)}})}};export{Q as CallKit};
4
+ `));for(let r of i)this.callKit.api.trackLogs(r);this.pendingTrackLogs=[]}catch(i){console.error(i)}}destroy(){this.trackLogsTimer&&(clearInterval(this.trackLogsTimer),this.trackLogsTimer=null),this.flushTrackLogs()}setLevel(t){this.level=t}info(t,e){let i=this.catchLog(t,e,"info");N(this.level)>=N("info")&&console.log(`%c${i}`,"color: gray;")}success(t,e){let i=this.catchLog(t,e,"success");N(this.level)>=N("success")&&console.log(`%c${i}`,"color: green;")}warn(t,e){let i=this.catchLog(t,e,"warn");N(this.level)>=N("warn")&&console.log(`%c${i}`,"color: orange;")}error(t,e,i=!1){let n=t instanceof Error?t.message:t,l=this.catchLog(n,e,"error");N(this.level)>=N("error")&&console.log(`%c${l}`,"color: red;");let{errCode:r,...f}=e?.content??{},C=r??a.UNKNOWN_ERROR;i||this.callKit.trigger(s.KIT_ERROR,{code:C,msg:n,data:f});let u=new Error(n);throw u.name="CallKitError",u.code=C,u.data=f,u}catchLog(t,e,i){let n=new Date,{enabled:l}=this.callKit.config.getTrackLogsConfig(),{userInfo:r}=this.callKit.config.getConfig(),f={agentId:r?.agentId,sessionId:r?.sessionId,...e?.content??{}},C={timestamp:n.toLocaleString().replace("T"," ").replace(".000Z",""),level:i,message:t,caller:e?.caller,type:e?.type,content:f},u=st(C);return l&&this.pendingTrackLogs.push(u),this.callKit.trigger(s.KIT_LOG,u,!0),u}};import{UserAgent as B,Web as rt,Registerer as ot,SessionState as y,RegistererState as M}from"sip.js";var Z=o=>{let t=o["x-antaios-manual-extend_info"]||o["x-antaios-manual-extend-info"],e=null;try{if(t&&typeof t=="string"){let i=t.replace(/\\/g,"");return e=JSON.parse(i),e}}catch{return{}}};var D=6;function ct(o){return o.replace(/(\w+):\s*'(.*?)'/g,'"$1": "$2"').replace(/'/g,'"')}var q=o=>{o&&o.getTracks().forEach(t=>t.stop())},at=()=>{typeof navigator.mediaDevices>"u"&&(navigator.mediaDevices={}),typeof navigator.mediaDevices.getUserMedia>"u"&&(navigator.mediaDevices.getUserMedia=o=>{let t=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia;return t?new Promise((e,i)=>{t.call(navigator,o,e,i)}):Promise.reject(new Error("Unable to obtain device permissions. Please check your browser settings or device permissions."))})},x=class{callKit;isMute=!1;isRegister=!1;isHold=!1;connectStatus=h.init;currentSession;mediaStream;userAgent;registerer;isReConnected=!1;isOutgoing=!1;isUnprompted=!1;hasInvite=!1;constructor(t){this.callKit=t}get reconnectConfig(){return this.callKit.config.getReconnectConfig("sip")}currentCallId=null;getCurrentCallId(){return this.currentCallId}setOutgoing(t){this.isOutgoing!==t&&(this.callKit.logger.info("setOutgoing",{caller:"Connect.setOutgoing",content:{outgoing:t}}),this.isOutgoing=t)}setCallId(t){this.callKit.logger.info("setCallId",{caller:"Connect.setCallId",content:{callId:t}}),this.currentCallId=t,this.callKit.trigger(s.KIT_CALL_ID_CHANGE,t)}async reset(){if(this.setOutgoing(!1),this.isUnprompted=!1,this.hasInvite=!1,this.isHolding()&&await this.setHold(!1),this.isMuted()&&await this.setMute(!1),this.connectStatus!==h.init&&this.setConnectStatus(h.init),this.isRegistered()&&await this.unregister(),this.currentCallId&&this.setCallId(null),this.currentSession=void 0,this.mediaStream=void 0,this.userAgent=void 0,this.registerer=void 0,this.mediaStream)try{q(this.mediaStream);let t=this.getAduioReference();t&&(t.pause(),t.srcObject=null)}catch(t){this.callKit.logger.error(t,{caller:"Connect.reset",content:{}})}this.setConnectStatus(h.init),this.clearHeartbeat()}getAduioReference(){let{audioRef:t}=this.callKit.config.getConfig();return typeof t=="function"?t():t}async permission(){this.callKit.logger.info("permission",{caller:"Connect.permission",content:{permission:!0}}),at();let t=await navigator.mediaDevices.getUserMedia({audio:!0});q(t)}isConnecting(){return this.connectStatus===h.connecting}isCalling(){return this.connectStatus===h.calling}isRinging(){return this.connectStatus===h.ringing}isHolding(){return this.isHold}isRegistered(){return this.isRegister}isMuted(){return this.isMute}isInit(){return this.connectStatus===h.init}heartbeatInterval;heartbeatFlag=D;clearHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null),this.heartbeatFlag=D}startHeartbeat(){this.heartbeatFlag=D,this.clearHeartbeat(),this.heartbeatInterval=setInterval(()=>{this.heartbeatFlag-=1,this.heartbeatFlag<=0&&(this.heartbeatFlag=D,this.callKit.trigger(s.SIP_CONNECT_EVENT,{event:"OPTIONS_HEARTBEAT_EXPIRED"}))},1e3)}socketTriggerHangup(t){!this.isCalling()||t!==this.currentCallId||(this.callKit.logger.info("socketHangup trigger hangup",{caller:"Connect.socketHangup",content:{callId:t,currentCallId:this.currentCallId}}),this.callKit.hangup())}async register(){if(this.connectStatus!==h.init){if(this.isRegistered()){this.callKit.logger.warn("connectStatus is registered",{caller:"Connect.register",content:{errCode:a.CONNECT_CALL_STATUS_ERROR}});return}this.callKit.reset(),this.callKit.logger.error("connectStatus is not init",{caller:"Connect.register",content:{errCode:a.CONNECT_CALL_STATUS_ERROR}});return}this.callKit.logger.info("connect register",{caller:"Connect.register",content:{connectStatus:this.connectStatus}}),await this.permission().catch(c=>{this.callKit.reset(),this.callKit.logger.error(c,{caller:"Connect.register",content:{errCode:a.WEBRTC_USER_MEDIA_ERROR}})});let{userInfo:t,constrains:e}=this.callKit.config.getConfig(),i=async()=>(this.mediaStream=await navigator.mediaDevices.getUserMedia(e),this.mediaStream),{userPart:n,fsIp:l,fsPort:r,iceInfo:f,wsUrl:C}=t,u={uri:B.makeURI(`sip:${n}@${l}:${r}`),displayName:n,transportOptions:{wsServers:[C],traceSip:!0},logLevel:"error",allowLegacyNotifications:!0,contactName:n,sessionDescriptionHandlerFactory:rt.defaultSessionDescriptionHandlerFactory(i),sessionDescriptionHandlerFactoryOptions:{constraints:e,iceGatheringTimeout:t.iceGatheringTimeout,peerConnectionConfiguration:{iceServers:JSON.parse(ct(f))}}};this.callKit.logger.info("connect connectConfig",{caller:"Connect.register",content:u}),this.userAgent=new B(u);let v=new MediaStream,F=c=>{let m=this.getAduioReference();this.callKit.logger.info("connect setupRemoteMedia",{caller:"Connect.register.setupRemoteMedia",content:m}),c.sessionDescriptionHandler.peerConnection.getReceivers().forEach(S=>{S.track&&v.addTrack(S.track)}),m?(m.srcObject=v,m.play().catch(S=>{this.callKit.logger.error(S.message,{caller:"Connect.register.setupRemoteMedia",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})})):this.callKit.logger.error("video is not exist",{caller:"Connect.register",content:{errCode:a.WEBRTC_AUDIO_PLAYER_ERROR}})},k=(c,m)=>{let{that:S=this}=m,I=c.userAgentCore,g=I.receiveIncomingRequestFromTransport.bind(I);I.receiveIncomingRequestFromTransport=d=>(d.method==="OPTIONS"&&S.startHeartbeat(),S.callKit.logger.info(`SIP Receive: ${d?.method}`,{caller:"Connect.register.observeSocketStatus.receiveRequest",type:"SIP",content:{request:d}}),g(d));let $=I.receiveIncomingResponseFromTransport.bind(I);I.receiveIncomingResponseFromTransport=d=>(S.callKit.logger.info(`SIP Receive Response: ${d?.statusCode} ${d?.reasonPhrase}`,{caller:"Connect.register.observeSocketStatus.receiveResponse",type:"SIP",content:{response:d}}),$(d));let{transport:_}=c;if(_){let d=_.send.bind(_);_.send=z=>(S.callKit.logger.info("SIP send message",{caller:"Connect.register.observeSocketStatus",type:"SIP",content:{message:z.toString()}}),d(z))}},K={};this.registerer=new ot(this.userAgent,K),this.registerer.stateChange.addListener(c=>{switch(c){case M.Initial:this.callKit.logger.info("registerer stateChange Initial",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!1),this.setConnectStatus(h.init),this.callKit.trigger(s.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case M.Registered:this.callKit.logger.info("registerer stateChange Registered",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!0),this.callKit.trigger(s.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case M.Terminated:this.callKit.logger.info("registerer stateChange Terminated",{caller:"Connect.register.registererStateChange",type:"SIP",content:{registererState:c,isRegistered:this.isRegistered()}}),this.setRegister(!1),this.setConnectStatus(h.init),this.callKit.trigger(s.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;case M.Unregistered:this.callKit.logger.info("registerer stateChange Unregistered",{caller:"Connect.register.registererStateChange",type:"SIP",content:{isRegistered:this.isRegistered(),registererState:c}}),this.setRegister(!1),this.setConnectStatus(h.init),this.callKit.trigger(s.SIP_REGISTERER_EVENT,{registererState:c,isRegistered:this.isRegistered()});break;default:break}}),this.userAgent.delegate={onInvite:c=>{this.callKit.logger.info("connect onInvite",{type:"SIP",caller:"Connect.register.onInvite",content:{invite:c,isRegistered:this.isRegistered(),isOutgoing:this.isOutgoing}}),this.currentSession=c,this.currentSession.stateChange.addListener(g=>{switch(g){case y.Establishing:this.callKit.logger.info("connect Establishing",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:g}}),this.setConnectStatus(h.ringing),this.callKit.trigger(s.SIP_SESSION_EVENT,{sessionState:g,isRegistered:this.isRegistered()});break;case y.Established:this.callKit.logger.info("connect Established",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:g}}),this.callKit.connect.setConnectStatus(h.calling),this.callKit.trigger(s.SIP_SESSION_EVENT,{sessionState:g,isRegistered:this.isRegistered()}),F(this.currentSession);break;case y.Terminating:this.callKit.trigger(s.SIP_SESSION_EVENT,{sessionState:g,isRegistered:this.isRegistered()});break;case y.Terminated:this.callKit.logger.info("connect Terminated",{caller:"Connect.register.onInvite",type:"SIP",content:{sessionState:g}}),this.hasInvite=!1,this.isUnprompted||this.callKit.callCenter.callEnd(),this.isUnprompted=!1,this.callKit.trigger(s.SIP_SESSION_EVENT,{sessionState:g,isRegistered:this.isRegistered()});break;default:break}});let m={sessionDescriptionHandlerOptions:{constraints:e,alwaysAcquireMediaFirst:!0}},S=()=>{let{request:g}=this.currentSession,$=Object.keys(g.headers),_={};return $.filter(d=>d.toLocaleLowerCase().startsWith("x-antaios")).forEach(d=>{_[d.toLocaleLowerCase()]=g.getHeader(d)}),this.callKit.logger.info("get invite data",{caller:"Connect.register.onInvite",content:_}),_},I=S();try{let g=Z(I);g?.callUuid?this.setCallId(g.callUuid):(this.setCallId(null),this.callKit.logger.warn("call id is not exist",{caller:"Connect.register.onInvite",content:{inviteData:g}}))}catch(g){this.callKit.logger.info(g,{caller:"Connect.register.onInvite",content:I})}if(this.isOutgoing)this.currentSession.accept(m),this.callKit.trigger(s.KIT_OUTGOING_INVITE,{getInviteData:S});else{this.hasInvite=!0;let g=()=>{this.currentSession?.state!==y.Terminated&&this.currentSession?.state!==y.Terminating&&this.currentSession.reject(),this.hasInvite=!1,this.callKit.callCenter.callEnd(!0,!1)};this.callKit.trigger(s.KIT_INVITE,{accept:()=>{this.callKit.trigger(s.CALL_CONNECTING,new Date),this.hasInvite=!1,this.currentSession.accept(m)},reject:g,getInviteData:S})}},onConnect:async()=>{this.reconnectAttempts=0,this.reconnectTimer=null,this.callKit.logger.info("connect onConnect",{caller:"Connect.register",type:"SIP",content:{version:`${this.callKit.config.getConfig().version}`}}),await this.registerer.register().catch(async c=>{this.callKit.reset(),this.callKit.logger.error(c?.message,{caller:"Connect.register",type:"SIP",content:{errCode:a.WEBRTC_REGISTER_ERROR}})})},onDisconnect:c=>{c?(this.callKit.logger.warn("SIP User Agent Disconnected with error",{caller:"Connect.register",type:"SIP",content:{err:c.message,errCode:a.WEBRTC_USER_AGENT_ERROR}}),this.startReconnectTimer()):this.callKit.logger.warn("SIP User Agent Disconnected",{caller:"Connect.register",type:"SIP",content:{}})},onRegister:()=>{this.callKit.logger.info("connect onRegister",{caller:"Connect.register",type:"SIP",content:{version:`V${this.callKit.config.getConfig().version}`}})}},k(this.userAgent,{that:this}),await this.userAgent.start().catch(c=>{this.callKit.reset(),this.callKit.logger.error(c,{caller:"Connect.register",type:"SIP",content:{errCode:a.WEBRTC_USER_AGENT_ERROR}})})}reconnectTimer;reconnectAttempts=0;startReconnectTimer(){if(this.reconnectAttempts>=this.reconnectConfig.maxAttempts&&this.callKit.config.isLogin()){this.callKit.reset(),this.callKit.logger.error("Reconnect failed max attempts",{caller:"Connect.startReconnectTimer",type:"SIP",content:{errCode:a.SOCKET_RECONNECT_FAILED,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}});return}this.callKit.logger.info("Reconnect timer started",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}}),this.reconnectAttempts+=1,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer&&this.callKit.config.isLogin()?(this.userAgent?.reconnect(),this.callKit.logger.info("Reconnect attempt",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}})):this.callKit.logger.info("Reconnect timer already expired",{caller:"Connect.startReconnectTimer",type:"SIP",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:this.reconnectConfig.maxAttempts,delay:this.reconnectConfig.delay}})},this.reconnectConfig.delay)}async stop(){await this.userAgent.stop()}async unregister(){if(this.callKit.logger.info("connect unregister",{caller:"Connect.unregister",type:"SIP",content:{isRegistered:this.isRegistered()}}),!this.isRegistered()||!this.registerer){this.callKit.logger.warn("No registerer to unregister.",{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}});return}await this.registerer.unregister({all:!0}).catch(t=>{this.callKit.logger.warn(t,{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}})}).finally(()=>{this.setRegister(!1)}),await this.userAgent?.stop().catch(t=>{this.callKit.logger.warn(t,{caller:"Connect.unregister",type:"SIP",content:{errCode:a.WEBRTC_CANCEL_REGISTER_ERROR}})})}async call(t){this.callKit.logger.info("connect call",{caller:"Connect.call",type:"SIP",content:{callback:t}}),this.setOutgoing(!0),this.isRegistered()||await this.register(),this.setConnectStatus(h.connecting),this.callKit.trigger(s.CALL_CONNECTING,new Date);let{userInfo:e}=this.callKit.config.getConfig();t(e)}setRegister(t){this.isRegister!==t&&(this.callKit.logger.info("connect setRegister",{caller:"Connect.setRegister",type:"SIP",content:{register:t}}),this.isRegister=t,this.callKit.trigger(s.KIT_REGISTER_CHANGE,t))}setConnectStatus(t){this.callKit.logger.info("connect setConnectStatus",{caller:"Connect.setConnectStatus",type:"SIP",content:{status:t}}),this.connectStatus=t,this.callKit.trigger(s.KIT_CALL_STATUS_CHANGE,t)}async hangup(t=!1,e=!1){if(this.callKit.logger.info("connect hangup",{caller:"Connect.hangup",type:"SIP",content:{isUnprompted:t,isError:e,connectStatus:this.connectStatus}}),this.setOutgoing(!1),this.isUnprompted=t,this.setHold(!1),this.setMute(!1),this.connectStatus!==h.init)try{t&&(this.isRinging()||this.isCalling())&&(this.hasInvite?(this.currentSession?.state!==y.Terminated&&this.currentSession?.state!==y.Terminating&&this.currentSession.reject(),this.hasInvite=!1):await this.currentSession?.bye()),q(this.mediaStream);let i=this.getAduioReference();i&&(i.pause(),i.srcObject=null),this.setConnectStatus(h.init),this.callKit.trigger(s.CALL_END,new Date),this.setCallId(null)}catch(i){this.callKit.trigger(s.CALL_END,new Date),this.callKit.reset(),this.callKit.logger.error(i,{caller:"Connect.hangup",type:"SIP",content:{connectStatus:this.connectStatus,isError:e,isUnprompted:t}})}}getRemoteMediaStream(t){this.callKit.logger.info("connect getRemoteMediaStream",{caller:"Connect.getRemoteMediaStream",type:"SIP",content:{session:t}});let e=t.sessionDescriptionHandler;if(e)return e.remoteMediaStream}setupRemoteMedia(t){this.callKit.logger.info("connect setupRemoteMedia",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{session:t}});let e=this.getRemoteMediaStream(t),i=this.getAduioReference();i?(i.autoplay=!0,i.srcObject=e,i.play().catch(n=>{this.callKit.logger.error(n.message,{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})}),e.onaddtrack=()=>{this.callKit.logger.info("Remote media onaddtrack",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{session:t}}),i.load(),i.play().catch(n=>{this.callKit.logger.error(n.message,{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAY_ERROR}})})}):this.callKit.logger.error("video is not exist",{caller:"Connect.setupRemoteMedia",type:"SIP",content:{errCode:a.WEBRTC_AUDIO_PLAYER_ERROR}})}async setHold(t){if(this.isHold===t){this.callKit.logger.warn("Already holding",{caller:"Connect.setHold",type:"SIP",content:{isHold:this.isHold}});return}this.callKit.socket.send(t?E.HOLD:E.UNHOLD),this.isHold=t,this.callKit.logger.info("connect setHold",{caller:"Connect.setHold",type:"SIP",content:{hold:t}}),this.callKit.trigger(s.KIT_SET_HOLD,t)}async setMute(t){if(this.isMute===t){this.callKit.logger.warn("Already muted",{caller:"Connect.setMute",type:"SIP",content:{isCalling:this.isCalling(),isMuted:this.isMuted()}});return}this.callKit.socket.send(t?E.MUTE:E.UNMUTE),this.isMute=t,this.callKit.trigger(s.KIT_SET_MUTE,t)}async refer(t,e){this.callKit.logger.info("connect refer",{caller:"Connect.refer",type:"SIP",content:{referTo:t,extra:e}});let i;t&&(i=B.makeURI(t)),this.currentSession.refer(i,e?.sessionReferOptions)}};var H=class{callKit;ws;lastPingTime=void 0;pingTimer;reconnectTimer;reconnectAttempts=0;connectAuthState={startConfirm:!1,isConnected:!1,isReconnecting:!1,isError:!1};get startConfirm(){return this.connectAuthState.startConfirm}get isError(){return this.connectAuthState.isError}constructor(t){this.callKit=t}get reconnectConfig(){return this.callKit.config.getReconnectConfig("incall")}init(){let{socket:t}=this.callKit.config.getConfig();this.callKit.logger.info(`socket init: ${t}`,{caller:"Socket.init",type:"INCALL",content:{socket:t}}),this.connect(t)}setConnectAuthState(t,e){this.connectAuthState[t]!==e&&(this.connectAuthState[t]=e)}handleDisconnect(){this.setConnectAuthState("isConnected",!1);let{enabled:t}=this.reconnectConfig;if(!this.callKit.config.isLogin()||!t){this.callKit.reset(),this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_NOT_CONNECTED"});return}this.connectAuthState.isReconnecting||this.connectAuthState.isError||this.attemptReconnect()}clearWebSocket(){this.ws&&(this.ws.onopen=null,this.ws.onclose=null,this.ws.onerror=null,this.ws.onmessage=null),(this.ws?.readyState===WebSocket.CONNECTING||this.ws?.readyState===WebSocket.OPEN)&&(this.ws?.close(1e3,"socket close"),this.callKit.logger.info("socket clear",{caller:"Socket.clearWebSocket",type:"INCALL",content:{}})),this.ws=void 0,this.setConnectAuthState("isConnected",!1)}connect(t){this.ws&&this.clearWebSocket(),this.ws=new WebSocket(t),this.ws.onopen=e=>this.onOpen(e),this.ws.onclose=e=>this.onClose(e),this.ws.onerror=e=>this.onError(e),this.ws.onmessage=e=>this.onMessage(e)}onOpen(t){this.callKit.logger.info("socket onOpen",{caller:"Socket.onOpen",type:"INCALL",content:{ev:t}}),this.setConnectAuthState("isConnected",!0),this.lastPingTime=Date.now(),this.checkPing(),this.send(E.START),this.connectAuthState.isReconnecting&&(this.setConnectAuthState("isReconnecting",!1),this.callKit.logger.info("reconnect success",{caller:"Socket.onOpen",type:"INCALL",content:{event:"INCALL_RECONNECT_SUCCESS",reconnectAttempts:this.reconnectAttempts}}),this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_SUCCESS"}))}cleanReconnectState(){this.reconnectAttempts=0,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0),this.setConnectAuthState("isReconnecting",!1),this.setConnectAuthState("isError",!1)}resetConnectState(){this.connectAuthState={startConfirm:!1,isConnected:!1,isReconnecting:!1,isError:!1},this.cleanReconnectState(),this.callKit.logger.info("reset connect state",{caller:"Socket.resetConnectState",type:"INCALL",content:{reconnectAttempts:this.reconnectAttempts,connectAuthState:this.connectAuthState}})}onClose(t){this.callKit.logger.info("socket onClose",{caller:"Socket.onClose",type:"INCALL",content:{ev:t}}),this.handleDisconnect()}onError(t){this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_CONNECT_ERROR",err:t}),this.callKit.logger.error("socket onError",{caller:"Socket.onError",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR,data:t}})}confirmAck(t){let{ack:e,messageId:i}=t;e&&this.send(E.ACK,{messageId:i})}onMessage(t){let e=JSON.parse(t.data),i=e.data;try{typeof e.data=="string"&&e.data&&(i=JSON.parse(e.data))}catch{this.callKit.logger.info("socket onMessage parse error",{caller:"Socket.onMessage",type:"INCALL",content:{data:e.data}})}this.callKit.logger.info(`socket onMessage: ${e.event}`,{caller:"Socket.onMessage",type:"INCALL",content:{data:i,event:e.event}}),this.confirmAck(e);let n=i?.callUuid||"";if(e.event===p.PONG){this.lastPingTime=Date.now();return}if(e.event===p.START_CONFIRM&&(this.setConnectAuthState("startConfirm",!0),this.cleanReconnectState()),e.event===p.CUSTOMER_RINGING&&this.callKit.trigger(s.CALL_RINGING,{time:new Date,callUuid:n}),e.event===p.CUSTOMER_PICK_UP&&this.callKit.trigger(s.CALL_PICK_UP,{time:new Date,callUuid:n}),e.event===p.AGENT_PICK_UP&&this.callKit.trigger(s.AGENT_PICK_UP,{time:new Date,callUuid:n}),e.event===p.CUSTOMER_HANG_UP&&(this.callKit.trigger(s.CALL_HANG_UP,{time:new Date,callUuid:n}),n&&this.callKit.connect.socketTriggerHangup(n)),e.event===p.CUSTOMER_NO_ANSWER&&(this.callKit.trigger(s.CALL_NO_ANSWER,{time:new Date,callUuid:n}),n&&this.callKit.connect.socketTriggerHangup(n)),e.event===p.CALL_CDR&&this.callKit.trigger(s.CALL_CDR,{time:new Date,callUuid:n,...i}),e.event===p.CLOSE){let{userInfo:l}=this.callKit.config.getConfig();this.send(E.END,{agentId:l.agentId,callUuid:n})}e.event===p.ERROR&&(this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error(e.msg,{caller:`Socket.onMessage:${e.event}`,type:"INCALL",content:{errCode:a.SOKET_SERVER_ERROR,data:i,callUuid:n}})),e.event===p.SESSION_ERROR&&(this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error(e.msg,{caller:`Socket.onMessage:${e.event}`,type:"INCALL",content:{data:i,event:p.SESSION_ERROR,callUuid:n}})),e.event===p.AGENT_NO_ANSWER&&n&&this.callKit.connect.socketTriggerHangup(n),e.event===p.AGENT_HANG_UP&&n&&this.callKit.connect.socketTriggerHangup(n),this.callKit.trigger(s.SERVER_SOCKET_EVENT,{...e,callUuid:n})}send(t,e){if(!this.connectAuthState.isConnected){this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_NOT_CONNECTED"}),this.callKit.reset(),this.callKit.logger.error("socket not connected",{caller:"Socket.send",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR}});return}let{userInfo:i,version:n}=this.callKit.config.getConfig(),{sessionId:l,extno:r,agentId:f}=i;if(this.callKit.logger.info("Socket send",{caller:"Socket.send",type:"INCALL",content:{agentId:f,sessionId:l,userInfo:i}}),!l){this.callKit.logger.error("sessionId is empty",{caller:"Socket.send",type:"INCALL",content:{errCode:a.SOCKET_CONNECT_ERROR}});return}let C={event:t,sessionId:l,version:n,...e};E.CALL===t&&(C.phoneNum=r,C.agentId=f,e?.sourceType===R.phoneNum?delete C.workOrderId:e?.sourceType===R.workOrderId&&delete C.phoneNum),this.callKit.logger.info("socket send",{caller:"Socket.send",type:"INCALL",content:{...C}}),this.ws?.send(JSON.stringify({event:t,...C}))}ping(){if(!this.connectAuthState.isConnected)return;this.send(E.PING);let t=Date.now(),{pingInterval:e,pingTimeout:i}=this.reconnectConfig;t-this.lastPingTime>e+i&&(this.ws&&this.connectAuthState.isConnected?this.ws.close(4001,"ping timeout"):this.callKit.reset(),this.callKit.logger.error("socket ping timeout",{caller:"Socket.ping",type:"INCALL",content:{errCode:a.SOCKET_PING_TIMEOUT}}),this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_PING_TIMEOUT"}))}checkPing(){this.pingTimer&&clearInterval(this.pingTimer);let{pingInterval:t}=this.reconnectConfig;this.pingTimer=setInterval(()=>{this.ping()},t)}async reset(t){let{force:e=!1}=t||{};this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=void 0),e&&(this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_RESET"}),this.resetConnectState()),this.lastPingTime=void 0,this.setConnectAuthState("startConfirm",!1),this.clearWebSocket()}attemptReconnect(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=void 0);let{maxAttempts:t}=this.reconnectConfig;if(this.reconnectAttempts>=t){this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_ERROR"}),this.setConnectAuthState("isError",!0),this.callKit.reset(),this.callKit.logger.error("Maximum reconnection attempts reached",{caller:"Socket.attemptReconnect",type:"INCALL",content:{errCode:a.SOCKET_RECONNECT_FAILED,reconnectAttempts:this.reconnectAttempts}});return}this.reconnectAttempts===0&&this.callKit.trigger(s.INCALL_CONNECT_EVENT,{event:"INCALL_RECONNECT_START"}),this.setConnectAuthState("isReconnecting",!0),this.reconnectAttempts+=1;let{delay:e}=this.reconnectConfig;this.callKit.logger.info(`Preparing reconnection attempt ${this.reconnectAttempts}/${t}, delay: ${e}ms`,{caller:"Socket.attemptReconnect",type:"INCALL",content:{reconnectAttempts:this.reconnectAttempts,maxAttempts:t,delay:e}}),this.reconnectTimer=setTimeout(()=>{let{socket:i}=this.callKit.config.getConfig();this.connect(i)},e)}};var Q=class{api;config;logger;callCenter;connect;socket;listener=[];constructor(t){this.config=new G(this),this.api=new P(this),this.connect=new x(this),this.callCenter=new U(this),this.socket=new H(this),this.logger=new b(this,t.log),t.log&&this.config.setConfig("log",t.log),t.trackLogs&&this.config.setConfig("trackLogs",{...L,...t.trackLogs}),t.audioRef&&this.config.setConfig("audioRef",t.audioRef),t.host&&this.config.setConfig("host",t.host),this.config.setConfig("constrains",t.constrains||w),this.config.setConfig("socket",t.socket),this.config.setConfig("reconnect",{sip:{...O,...t.reconnect?.sip||{}},incall:{...A,...t.reconnect?.incall||{}}}),this.logger.info("callKit init",{caller:"CallKit.init",content:t})}async login(t,e,i={encryptionMethod:T.INTERNAL}){if(this.config.isLogin()){this.logger.warn("already login",{caller:"CallKit.login",content:{username:t,password:e,extra:i}});return}let n="",{encryptionMethod:l=T.INTERNAL}=i;switch(l){case T.NONE:n=e;break;case T.INTERNAL:n=W(t+W(e));break;default:n=W(t+W(e));break}if(this.logger.info("login info:",{caller:"CallKit.login",content:{username:t,password:e,encryptionMethod:l,encryptionPassword:n}}),this.socket.isError){this.logger.warn("socket is error",{caller:"CallKit.login",content:{username:t,password:e,extra:i,socketError:this.socket.isError}});return}try{let r=await this.api.login({userName:t,password:n,timestamp:Date.now()});r&&(this.config.setConfig("userInfo",{wsUrl:`wss://${r.wsUrl}`,sessionId:r.sessionId,username:t,password:n,encryptionPassword:n,agentId:r.agentId,fsUserId:r.fsUserId,userPart:r.userPart,fsPassword:r.fsPassword,fsIp:r.fsIp,fsPort:r.fsPort,iceInfo:r.iceInfo,iceGatheringTimeout:r.iceGatheringTimeout,logGather:r.logGather,...i}),this.socket.init(),this.trigger(s.KIT_LOGIN_CHANGE,!0))}catch(r){this.logger.error(r,{caller:"CallKit.login",content:{errCode:a.API_USER_LOGIN_ERROR}})}}async logout({isReset:t=!0}={isReset:!0}){if(!this.config.check())return;let{userInfo:e}=this.config.getConfig();if(this.logger.info("logout",{caller:"CallKit.logout",content:{sessionId:e.sessionId}}),this.config.isLogin()){let{sessionId:i}=e;try{await this.api.loginOut({sessionId:i,timestamp:Date.now()})}catch(n){this.logger.warn(n,{caller:"CallKit.logout",content:{errCode:a.API_USER_LOGOUT_ERROR}})}}t?await this.reset():this.config.reset("logout")}async call(t="",e={sourceType:R.phoneNum,workOrderId:""}){if(!this.config.check())return;if(!this.connect.isRegistered){this.logger.warn("Currently not registered",{caller:"CallKit.call",content:{extno:t,options:e}});return}let{sourceType:i,workOrderId:n}=e;this.config.setUserInfo("sourceType",i),i===R.phoneNum?t&&this.config.setUserInfo("extno",t):i===R.workOrderId&&n&&this.config.setUserInfo("workOrderId",n),this.logger.info("call",{caller:"CallKit.call",content:{extno:t,options:e}}),this.callCenter.callStart(e)}async refer(t,e){this.config.check()&&(this.logger.info("refer",{caller:"CallKit.refer",content:{uri:t,options:e}}),this.callCenter.callRefer(t,e))}async register(){this.config.check()&&(this.logger.info("register",{caller:"CallKit.register",content:{}}),this.connect.register())}async unregister(){this.config.check()&&(this.logger.info("unregister",{caller:"CallKit.unregister",content:{}}),this.connect.unregister())}async hangup(){if(this.config.check()){if(this.logger.info("hangup",{caller:"CallKit.hangup",content:{connectStatus:this.connect.connectStatus}}),!this.connect.isConnecting()&&!this.connect.isRinging()&&!this.connect.isCalling()&&!this.connect.isHolding()){this.logger.warn("Currently not in a call",{caller:"CallKit.hangup",content:{connectStatus:this.connect.connectStatus}});return}await this.callCenter.callEnd(!0)}}hold(){this.config.check()&&(this.logger.info("hold",{caller:"CallKit.hold",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callHold())}unhold(){this.config.check()&&(this.logger.info("unhold",{caller:"CallKit.unhold",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callUnhold())}mute(){this.config.check()&&(this.logger.info("mute",{caller:"CallKit.mute",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callMute())}unmute(){this.config.check()&&(this.logger.info("unmute",{caller:"CallKit.unmute",content:{connectStatus:this.connect.connectStatus}}),this.callCenter.callUnmute())}async setUserStatus(t,e={}){let{agentId:i}=this.config.getConfig().userInfo;this.logger.info("setUserStatus",{caller:"CallKit.setUserStatus",content:{status:t,agentId:i}}),await this.api.updateUserStatus({agentId:i,userStatus:t,timestamp:Date.now(),...e})}async reset(t){let{force:e=!1}=t||{};this.logger.info("reset",{caller:"CallKit.reset",content:{connectStatus:this.connect.connectStatus,force:e}}),this.connect.isCalling()&&await this.hangup(),await this.connect.reset(),this.config.isLogin()?await this.logout({isReset:!1}):await this.config.reset("reset"),await this.socket.reset({force:e})}on(t,e){this.listener.push({event:t,callback:e})}off(t,e){this.logger.info(`off ${t}`,{caller:"CallKit.off",content:{event:t}}),e?this.listener=this.listener.filter(i=>!(i.event===t&&i.callback===e)):this.listener=this.listener.filter(i=>i.event!==t)}removeAllListeners(){this.listener=this.listener.splice(0,this.listener.length),this.logger.info("removeAllListeners",{caller:"CallKit.removeAllListeners",content:{listener:this.listener}})}trigger(t,e,i=!1){i||this.logger.info(`Trigger Event: ${t}`,{caller:"CallKit.trigger",content:e}),this.listener.forEach(n=>{if(n.event===t)try{n.callback(e)}catch(l){this.logger.error(`Event callback error: ${t}`,l,!0)}})}};export{Q as CallKit};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koi-design/callkit",
3
- "version": "2.0.5-beta.13",
3
+ "version": "2.0.5-beta.15",
4
4
  "description": "callkit",
5
5
  "author": "koi",
6
6
  "license": "ISC",