@koi-design/callkit 2.2.0-beta.4 → 2.3.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -45,7 +45,7 @@ var Api = class {
45
45
  const res = await this.post({
46
46
  url: "/auth/agentUser/login",
47
47
  method: "post",
48
- data: { ...params, browserVersion: navigator.userAgent }
48
+ data: params
49
49
  });
50
50
  return res;
51
51
  } finally {
@@ -508,7 +508,11 @@ var SocketReceiveEvent = {
508
508
  ERROR: "ERROR",
509
509
  SESSION_ERROR: "SESSION_ERROR",
510
510
  WAITING_QUEUE: "WAITING_QUEUE",
511
- CUSTOMER_MATCH_BLACK_PHONE: "CUSTOMER_MATCH_BLACK_PHONE"
511
+ CUSTOMER_MATCH_BLACK_PHONE: "CUSTOMER_MATCH_BLACK_PHONE",
512
+ /**
513
+ * Agent RTP loss
514
+ */
515
+ AGENT_RTP_LOSS: "AGENT_RTP_LOSS"
512
516
  };
513
517
  var EncryptionMethod = {
514
518
  NONE: "NONE",
@@ -528,6 +532,12 @@ var CallSourceType = {
528
532
  phoneNum: 1,
529
533
  workOrderId: 2
530
534
  };
535
+ var PhoneTypeEnum = {
536
+ SIP: 0,
537
+ TEL: 1,
538
+ OUT: 2,
539
+ SP: 5
540
+ };
531
541
  var trackLogsDefaultConfig = {
532
542
  enabled: false,
533
543
  interval: 5e3,
@@ -691,7 +701,7 @@ var Call = class {
691
701
  // package.json
692
702
  var package_default = {
693
703
  name: "@koi-design/callkit",
694
- version: "2.2.0-beta.4",
704
+ version: "2.3.0-beta.10",
695
705
  description: "callkit",
696
706
  author: "koi",
697
707
  license: "ISC",
@@ -768,6 +778,7 @@ var Config = class {
768
778
  password: "",
769
779
  encryptionPassword: EncryptionMethod.INTERNAL,
770
780
  sourceType: CallSourceType.phoneNum,
781
+ phoneType: PhoneTypeEnum.SIP,
771
782
  // Extension number
772
783
  extno: "",
773
784
  workOrderId: "",
@@ -811,6 +822,7 @@ var Config = class {
811
822
  encryptionPassword: "",
812
823
  userPart: "",
813
824
  sourceType: CallSourceType.phoneNum,
825
+ phoneType: PhoneTypeEnum.SIP,
814
826
  extno: "",
815
827
  workOrderId: "",
816
828
  agentId: "",
@@ -15789,8 +15801,6 @@ var Connect = class {
15789
15801
  });
15790
15802
  return;
15791
15803
  }
15792
- const { userInfo } = this.callKit.config.getConfig();
15793
- const { userPart, fsIp, fsPort } = userInfo;
15794
15804
  const { registererOptions = {} } = this.reconnectConfig;
15795
15805
  this.registerer = new Registerer(this.userAgent, registererOptions);
15796
15806
  this.registerer.stateChange.addListener((state) => {
@@ -15824,27 +15834,26 @@ var Connect = class {
15824
15834
  });
15825
15835
  this.setRegister(true);
15826
15836
  if (this.isReConnected) {
15827
- if (this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling()) {
15828
- const selfUri = `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
15837
+ if (this.canReferInCallToSelf()) {
15829
15838
  this.callKit.logger.info(
15830
15839
  "Reconnected, referring active session to self",
15831
15840
  {
15832
15841
  caller: "Connect.setupRegisterer.registererStateChange",
15833
15842
  type: "SIP",
15834
15843
  content: {
15835
- selfUri,
15844
+ selfUri: this.getSelfReferUri(),
15836
15845
  sessionState: this.currentSession.state,
15837
15846
  connectStatus: this.connectStatus
15838
15847
  }
15839
15848
  }
15840
15849
  );
15841
- this.referInCall(selfUri).catch((err) => {
15850
+ this.referInCallToSelf().catch((err) => {
15842
15851
  this.callKit.logger.error(err, {
15843
15852
  caller: "Connect.setupRegisterer.registererStateChange",
15844
15853
  type: "SIP",
15845
15854
  content: {
15846
15855
  errCode: ErrorCode.WEBRTC_CALL_INVITE_ERROR,
15847
- selfUri
15856
+ selfUri: this.getSelfReferUri()
15848
15857
  }
15849
15858
  });
15850
15859
  });
@@ -16673,145 +16682,58 @@ var Connect = class {
16673
16682
  }
16674
16683
  this.currentSession.refer(target, extra?.sessionReferOptions);
16675
16684
  }
16676
- };
16677
-
16678
- // core/heartbeat-worker.ts
16679
- var workerCode = `
16680
- let timer = null;
16681
- let interval = 30000;
16682
-
16683
- self.onmessage = function(e) {
16684
- const { type, interval: newInterval } = e.data;
16685
-
16686
- if (type === 'start') {
16687
- if (timer) {
16688
- clearInterval(timer);
16689
- }
16690
- interval = newInterval || interval;
16691
- timer = setInterval(() => {
16692
- self.postMessage({ type: 'tick' });
16693
- }, interval);
16694
- }
16695
-
16696
- if (type === 'stop') {
16697
- if (timer) {
16698
- clearInterval(timer);
16699
- timer = null;
16700
- }
16701
- }
16702
-
16703
- if (type === 'updateInterval') {
16704
- interval = newInterval;
16705
- if (timer) {
16706
- clearInterval(timer);
16707
- timer = setInterval(() => {
16708
- self.postMessage({ type: 'tick' });
16709
- }, interval);
16710
- }
16711
- }
16712
- };
16713
- `;
16714
- function createHeartbeatWorker() {
16715
- try {
16716
- const blob = new Blob([workerCode], { type: "application/javascript" });
16717
- const workerUrl = URL.createObjectURL(blob);
16718
- const worker = new Worker(workerUrl);
16719
- URL.revokeObjectURL(workerUrl);
16720
- return worker;
16721
- } catch {
16722
- return null;
16723
- }
16724
- }
16725
- var HeartbeatManager = class {
16726
- worker = null;
16727
- fallbackTimer = null;
16728
- interval = 3e4;
16729
- onTick = null;
16730
- isRunning = false;
16731
- constructor() {
16732
- this.worker = createHeartbeatWorker();
16733
- if (this.worker) {
16734
- this.worker.onmessage = (e) => {
16735
- if (e.data.type === "tick" && this.onTick) {
16736
- this.onTick();
16737
- }
16738
- };
16739
- }
16740
- }
16741
16685
  /**
16742
- * Start the heartbeat
16743
- * @param interval - Interval in milliseconds
16744
- * @param onTick - Callback function to execute on each tick
16686
+ * Get the SIP URI for "refer to self" (same as reconnection refer logic).
16687
+ * Shared by referInCallToSelf and internal reconnection refer.
16745
16688
  */
16746
- start(interval, onTick) {
16747
- this.stop();
16748
- this.interval = interval;
16749
- this.onTick = onTick;
16750
- this.isRunning = true;
16751
- if (this.worker) {
16752
- this.worker.postMessage({
16753
- type: "start",
16754
- interval
16755
- });
16756
- } else {
16757
- this.fallbackTimer = setInterval(() => {
16758
- if (this.onTick) {
16759
- this.onTick();
16760
- }
16761
- }, interval);
16762
- }
16689
+ getSelfReferUri() {
16690
+ const { userInfo } = this.callKit.config.getConfig();
16691
+ const { userPart, fsIp, fsPort } = userInfo;
16692
+ return `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
16763
16693
  }
16764
16694
  /**
16765
- * Stop the heartbeat
16695
+ * Whether we can refer the current call to self (has active session in Established/Establishing and is calling).
16696
+ * Shared by reconnection logic and referInCallToSelf.
16766
16697
  */
16767
- stop() {
16768
- this.isRunning = false;
16769
- this.onTick = null;
16770
- if (this.worker) {
16771
- this.worker.postMessage({ type: "stop" });
16772
- }
16773
- if (this.fallbackTimer) {
16774
- clearInterval(this.fallbackTimer);
16775
- this.fallbackTimer = null;
16776
- }
16698
+ canReferInCallToSelf() {
16699
+ return !!this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling();
16777
16700
  }
16778
16701
  /**
16779
- * Update the heartbeat interval
16780
- * @param interval - New interval in milliseconds
16702
+ * Refer the current call to self (e.g. Agent RTP loss recovery, post-reconnect recovery).
16703
+ * Socket and other callers can use this without constructing referTo.
16781
16704
  */
16782
- updateInterval(interval) {
16783
- this.interval = interval;
16784
- if (!this.isRunning)
16785
- return;
16786
- if (this.worker) {
16787
- this.worker.postMessage({
16788
- type: "updateInterval",
16789
- interval
16790
- });
16791
- } else if (this.fallbackTimer && this.onTick) {
16792
- clearInterval(this.fallbackTimer);
16793
- this.fallbackTimer = setInterval(() => {
16794
- if (this.onTick) {
16795
- this.onTick();
16705
+ async referInCallToSelf(callUuid, extra) {
16706
+ if (callUuid && this.currentCallId !== callUuid) {
16707
+ this.callKit.logger.warn(
16708
+ "Cannot refer in call to self: callUuid mismatch",
16709
+ {
16710
+ caller: "Connect.referInCallToSelf",
16711
+ type: "SIP",
16712
+ content: {
16713
+ currentCallId: this.currentCallId,
16714
+ callUuid
16715
+ }
16796
16716
  }
16797
- }, interval);
16717
+ );
16718
+ return;
16798
16719
  }
16799
- }
16800
- /**
16801
- * Destroy the heartbeat manager and release resources
16802
- */
16803
- destroy() {
16804
- this.stop();
16805
- if (this.worker) {
16806
- this.worker.terminate();
16807
- this.worker = null;
16720
+ if (!this.canReferInCallToSelf()) {
16721
+ this.callKit.logger.warn(
16722
+ "Cannot refer in call to self: preconditions not met",
16723
+ {
16724
+ caller: "Connect.referInCallToSelf",
16725
+ type: "SIP",
16726
+ content: {
16727
+ hasCurrentSession: !!this.currentSession,
16728
+ sessionState: this.currentSession?.state,
16729
+ isCalling: this.isCalling()
16730
+ }
16731
+ }
16732
+ );
16733
+ return;
16808
16734
  }
16809
- }
16810
- /**
16811
- * Check if using Web Worker
16812
- */
16813
- isUsingWorker() {
16814
- return this.worker !== null;
16735
+ const selfUri = this.getSelfReferUri();
16736
+ return this.referInCall(selfUri, extra);
16815
16737
  }
16816
16738
  };
16817
16739
 
@@ -16820,7 +16742,7 @@ var Socket = class {
16820
16742
  callKit;
16821
16743
  ws;
16822
16744
  lastPingTime = void 0;
16823
- heartbeatManager;
16745
+ pingTimer;
16824
16746
  /**
16825
16747
  * @description reconnect timer
16826
16748
  */
@@ -16853,18 +16775,10 @@ var Socket = class {
16853
16775
  }
16854
16776
  constructor(callKit) {
16855
16777
  this.callKit = callKit;
16856
- this.heartbeatManager = new HeartbeatManager();
16857
16778
  }
16858
16779
  get reconnectConfig() {
16859
16780
  return this.callKit.config.getReconnectConfig("incall");
16860
16781
  }
16861
- get pingInterval() {
16862
- const { keepaliveInterval } = this.callKit.config.getConfig().userInfo;
16863
- if (Number.isInteger(keepaliveInterval) && keepaliveInterval > 0) {
16864
- return keepaliveInterval * 1e3;
16865
- }
16866
- return this.reconnectConfig.pingInterval;
16867
- }
16868
16782
  isConnected() {
16869
16783
  return this.connectAuthState.isConnected;
16870
16784
  }
@@ -17046,6 +16960,28 @@ var Socket = class {
17046
16960
  this.setConnectAuthState("startConfirm", true);
17047
16961
  this.cleanReconnectState();
17048
16962
  }
16963
+ if (data.event === SocketReceiveEvent.AGENT_RTP_LOSS) {
16964
+ this.callKit.logger.warn("Agent RTP loss", {
16965
+ caller: "Socket.onMessage",
16966
+ type: "INCALL",
16967
+ content: {
16968
+ data: {
16969
+ callUuid,
16970
+ ...content
16971
+ },
16972
+ event: SocketReceiveEvent.AGENT_RTP_LOSS
16973
+ }
16974
+ });
16975
+ if (callUuid) {
16976
+ this.callKit.connect.referInCallToSelf(callUuid).catch((err) => {
16977
+ this.callKit.logger.error(err, {
16978
+ caller: "Socket.onMessage:AGENT_RTP_LOSS",
16979
+ type: "INCALL",
16980
+ content: { callUuid, event: SocketReceiveEvent.AGENT_RTP_LOSS }
16981
+ });
16982
+ });
16983
+ }
16984
+ }
17049
16985
  if (data.event === SocketReceiveEvent.CUSTOMER_RINGING) {
17050
16986
  this.callKit.trigger(KitEvent.CALL_RINGING, {
17051
16987
  time: /* @__PURE__ */ new Date(),
@@ -17199,8 +17135,8 @@ var Socket = class {
17199
17135
  return;
17200
17136
  this.send(SocketSendEvent.PING);
17201
17137
  const now = Date.now();
17202
- const { pingTimeout } = this.reconnectConfig;
17203
- if (now - this.lastPingTime > this.pingInterval + pingTimeout) {
17138
+ const { pingInterval, pingTimeout } = this.reconnectConfig;
17139
+ if (now - this.lastPingTime > pingInterval + pingTimeout) {
17204
17140
  this.callKit.logger.warn("Ping timeout not connected", {
17205
17141
  caller: "Socket.ping",
17206
17142
  type: "INCALL",
@@ -17215,27 +17151,23 @@ var Socket = class {
17215
17151
  }
17216
17152
  }
17217
17153
  checkPing() {
17218
- this.heartbeatManager.start(this.pingInterval, () => {
17154
+ if (this.pingTimer) {
17155
+ clearInterval(this.pingTimer);
17156
+ }
17157
+ const { pingInterval } = this.reconnectConfig;
17158
+ this.pingTimer = setInterval(() => {
17219
17159
  this.ping();
17220
- });
17221
- this.callKit.logger.info(
17222
- `Heartbeat started with Worker: ${this.heartbeatManager.isUsingWorker()}`,
17223
- {
17224
- caller: "Socket.checkPing",
17225
- type: "INCALL",
17226
- content: {
17227
- pingInterval: this.pingInterval,
17228
- usingWorker: this.heartbeatManager.isUsingWorker()
17229
- }
17230
- }
17231
- );
17160
+ }, pingInterval);
17232
17161
  }
17233
17162
  /**
17234
17163
  * reset socket connection and all states
17235
17164
  */
17236
17165
  async reset(config) {
17237
17166
  const { force = false } = config || {};
17238
- this.heartbeatManager.stop();
17167
+ if (this.pingTimer) {
17168
+ clearInterval(this.pingTimer);
17169
+ this.pingTimer = void 0;
17170
+ }
17239
17171
  if (force) {
17240
17172
  this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
17241
17173
  event: "INCALL_RESET"
@@ -17246,12 +17178,6 @@ var Socket = class {
17246
17178
  this.setConnectAuthState("startConfirm", false);
17247
17179
  this.clearWebSocket();
17248
17180
  }
17249
- /**
17250
- * Destroy the heartbeat manager
17251
- */
17252
- destroyHeartbeat() {
17253
- this.heartbeatManager.destroy();
17254
- }
17255
17181
  attemptReconnect() {
17256
17182
  if (this.reconnectTimer) {
17257
17183
  clearTimeout(this.reconnectTimer);
@@ -17377,7 +17303,6 @@ var CallKit = class {
17377
17303
  content: {
17378
17304
  username,
17379
17305
  password,
17380
- ua: navigator.userAgent,
17381
17306
  encryptionMethod,
17382
17307
  encryptionPassword
17383
17308
  }
@@ -17395,7 +17320,6 @@ var CallKit = class {
17395
17320
  password: encryptionPassword,
17396
17321
  timestamp: Date.now()
17397
17322
  });
17398
- console.log("user", user);
17399
17323
  if (user) {
17400
17324
  this.config.setConfig("userInfo", {
17401
17325
  wsUrl: `wss://${user.wsUrl}`,
@@ -17412,7 +17336,7 @@ var CallKit = class {
17412
17336
  iceInfo: user.iceInfo,
17413
17337
  iceGatheringTimeout: user.iceGatheringTimeout,
17414
17338
  logGather: user.logGather,
17415
- keepaliveInterval: user.keepaliveInterval,
17339
+ phoneType: user.phoneType,
17416
17340
  // encryptionType is in extra
17417
17341
  ...extra
17418
17342
  });
@@ -17509,7 +17433,10 @@ var CallKit = class {
17509
17433
  caller: "CallKit.register",
17510
17434
  content: {}
17511
17435
  });
17512
- this.connect.register();
17436
+ const { userInfo } = this.config.getConfig();
17437
+ if (userInfo.phoneType === PhoneTypeEnum.SIP) {
17438
+ this.connect.register();
17439
+ }
17513
17440
  }
17514
17441
  async unregister() {
17515
17442
  if (!this.config.check())
@@ -17619,10 +17546,13 @@ var CallKit = class {
17619
17546
  force
17620
17547
  }
17621
17548
  });
17622
- if (this.connect.isCalling()) {
17623
- await this.hangup();
17549
+ const { userInfo } = this.config.getConfig();
17550
+ if (userInfo.phoneType === PhoneTypeEnum.SIP) {
17551
+ if (this.connect.isCalling()) {
17552
+ await this.hangup();
17553
+ }
17554
+ await this.connect.reset({ force });
17624
17555
  }
17625
- await this.connect.reset({ force });
17626
17556
  if (this.config.isLogin()) {
17627
17557
  await this.logout({ isReset: false });
17628
17558
  } else {