@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.js CHANGED
@@ -72,7 +72,7 @@ var Api = class {
72
72
  const res = await this.post({
73
73
  url: "/auth/agentUser/login",
74
74
  method: "post",
75
- data: { ...params, browserVersion: navigator.userAgent }
75
+ data: params
76
76
  });
77
77
  return res;
78
78
  } finally {
@@ -535,7 +535,11 @@ var SocketReceiveEvent = {
535
535
  ERROR: "ERROR",
536
536
  SESSION_ERROR: "SESSION_ERROR",
537
537
  WAITING_QUEUE: "WAITING_QUEUE",
538
- CUSTOMER_MATCH_BLACK_PHONE: "CUSTOMER_MATCH_BLACK_PHONE"
538
+ CUSTOMER_MATCH_BLACK_PHONE: "CUSTOMER_MATCH_BLACK_PHONE",
539
+ /**
540
+ * Agent RTP loss
541
+ */
542
+ AGENT_RTP_LOSS: "AGENT_RTP_LOSS"
539
543
  };
540
544
  var EncryptionMethod = {
541
545
  NONE: "NONE",
@@ -555,6 +559,12 @@ var CallSourceType = {
555
559
  phoneNum: 1,
556
560
  workOrderId: 2
557
561
  };
562
+ var PhoneTypeEnum = {
563
+ SIP: 0,
564
+ TEL: 1,
565
+ OUT: 2,
566
+ SP: 5
567
+ };
558
568
  var trackLogsDefaultConfig = {
559
569
  enabled: false,
560
570
  interval: 5e3,
@@ -718,7 +728,7 @@ var Call = class {
718
728
  // package.json
719
729
  var package_default = {
720
730
  name: "@koi-design/callkit",
721
- version: "2.2.0-beta.4",
731
+ version: "2.3.0-beta.10",
722
732
  description: "callkit",
723
733
  author: "koi",
724
734
  license: "ISC",
@@ -795,6 +805,7 @@ var Config = class {
795
805
  password: "",
796
806
  encryptionPassword: EncryptionMethod.INTERNAL,
797
807
  sourceType: CallSourceType.phoneNum,
808
+ phoneType: PhoneTypeEnum.SIP,
798
809
  // Extension number
799
810
  extno: "",
800
811
  workOrderId: "",
@@ -838,6 +849,7 @@ var Config = class {
838
849
  encryptionPassword: "",
839
850
  userPart: "",
840
851
  sourceType: CallSourceType.phoneNum,
852
+ phoneType: PhoneTypeEnum.SIP,
841
853
  extno: "",
842
854
  workOrderId: "",
843
855
  agentId: "",
@@ -15816,8 +15828,6 @@ var Connect = class {
15816
15828
  });
15817
15829
  return;
15818
15830
  }
15819
- const { userInfo } = this.callKit.config.getConfig();
15820
- const { userPart, fsIp, fsPort } = userInfo;
15821
15831
  const { registererOptions = {} } = this.reconnectConfig;
15822
15832
  this.registerer = new Registerer(this.userAgent, registererOptions);
15823
15833
  this.registerer.stateChange.addListener((state) => {
@@ -15851,27 +15861,26 @@ var Connect = class {
15851
15861
  });
15852
15862
  this.setRegister(true);
15853
15863
  if (this.isReConnected) {
15854
- if (this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling()) {
15855
- const selfUri = `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
15864
+ if (this.canReferInCallToSelf()) {
15856
15865
  this.callKit.logger.info(
15857
15866
  "Reconnected, referring active session to self",
15858
15867
  {
15859
15868
  caller: "Connect.setupRegisterer.registererStateChange",
15860
15869
  type: "SIP",
15861
15870
  content: {
15862
- selfUri,
15871
+ selfUri: this.getSelfReferUri(),
15863
15872
  sessionState: this.currentSession.state,
15864
15873
  connectStatus: this.connectStatus
15865
15874
  }
15866
15875
  }
15867
15876
  );
15868
- this.referInCall(selfUri).catch((err) => {
15877
+ this.referInCallToSelf().catch((err) => {
15869
15878
  this.callKit.logger.error(err, {
15870
15879
  caller: "Connect.setupRegisterer.registererStateChange",
15871
15880
  type: "SIP",
15872
15881
  content: {
15873
15882
  errCode: ErrorCode.WEBRTC_CALL_INVITE_ERROR,
15874
- selfUri
15883
+ selfUri: this.getSelfReferUri()
15875
15884
  }
15876
15885
  });
15877
15886
  });
@@ -16700,145 +16709,58 @@ var Connect = class {
16700
16709
  }
16701
16710
  this.currentSession.refer(target, extra?.sessionReferOptions);
16702
16711
  }
16703
- };
16704
-
16705
- // core/heartbeat-worker.ts
16706
- var workerCode = `
16707
- let timer = null;
16708
- let interval = 30000;
16709
-
16710
- self.onmessage = function(e) {
16711
- const { type, interval: newInterval } = e.data;
16712
-
16713
- if (type === 'start') {
16714
- if (timer) {
16715
- clearInterval(timer);
16716
- }
16717
- interval = newInterval || interval;
16718
- timer = setInterval(() => {
16719
- self.postMessage({ type: 'tick' });
16720
- }, interval);
16721
- }
16722
-
16723
- if (type === 'stop') {
16724
- if (timer) {
16725
- clearInterval(timer);
16726
- timer = null;
16727
- }
16728
- }
16729
-
16730
- if (type === 'updateInterval') {
16731
- interval = newInterval;
16732
- if (timer) {
16733
- clearInterval(timer);
16734
- timer = setInterval(() => {
16735
- self.postMessage({ type: 'tick' });
16736
- }, interval);
16737
- }
16738
- }
16739
- };
16740
- `;
16741
- function createHeartbeatWorker() {
16742
- try {
16743
- const blob = new Blob([workerCode], { type: "application/javascript" });
16744
- const workerUrl = URL.createObjectURL(blob);
16745
- const worker = new Worker(workerUrl);
16746
- URL.revokeObjectURL(workerUrl);
16747
- return worker;
16748
- } catch {
16749
- return null;
16750
- }
16751
- }
16752
- var HeartbeatManager = class {
16753
- worker = null;
16754
- fallbackTimer = null;
16755
- interval = 3e4;
16756
- onTick = null;
16757
- isRunning = false;
16758
- constructor() {
16759
- this.worker = createHeartbeatWorker();
16760
- if (this.worker) {
16761
- this.worker.onmessage = (e) => {
16762
- if (e.data.type === "tick" && this.onTick) {
16763
- this.onTick();
16764
- }
16765
- };
16766
- }
16767
- }
16768
16712
  /**
16769
- * Start the heartbeat
16770
- * @param interval - Interval in milliseconds
16771
- * @param onTick - Callback function to execute on each tick
16713
+ * Get the SIP URI for "refer to self" (same as reconnection refer logic).
16714
+ * Shared by referInCallToSelf and internal reconnection refer.
16772
16715
  */
16773
- start(interval, onTick) {
16774
- this.stop();
16775
- this.interval = interval;
16776
- this.onTick = onTick;
16777
- this.isRunning = true;
16778
- if (this.worker) {
16779
- this.worker.postMessage({
16780
- type: "start",
16781
- interval
16782
- });
16783
- } else {
16784
- this.fallbackTimer = setInterval(() => {
16785
- if (this.onTick) {
16786
- this.onTick();
16787
- }
16788
- }, interval);
16789
- }
16716
+ getSelfReferUri() {
16717
+ const { userInfo } = this.callKit.config.getConfig();
16718
+ const { userPart, fsIp, fsPort } = userInfo;
16719
+ return `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
16790
16720
  }
16791
16721
  /**
16792
- * Stop the heartbeat
16722
+ * Whether we can refer the current call to self (has active session in Established/Establishing and is calling).
16723
+ * Shared by reconnection logic and referInCallToSelf.
16793
16724
  */
16794
- stop() {
16795
- this.isRunning = false;
16796
- this.onTick = null;
16797
- if (this.worker) {
16798
- this.worker.postMessage({ type: "stop" });
16799
- }
16800
- if (this.fallbackTimer) {
16801
- clearInterval(this.fallbackTimer);
16802
- this.fallbackTimer = null;
16803
- }
16725
+ canReferInCallToSelf() {
16726
+ return !!this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling();
16804
16727
  }
16805
16728
  /**
16806
- * Update the heartbeat interval
16807
- * @param interval - New interval in milliseconds
16729
+ * Refer the current call to self (e.g. Agent RTP loss recovery, post-reconnect recovery).
16730
+ * Socket and other callers can use this without constructing referTo.
16808
16731
  */
16809
- updateInterval(interval) {
16810
- this.interval = interval;
16811
- if (!this.isRunning)
16812
- return;
16813
- if (this.worker) {
16814
- this.worker.postMessage({
16815
- type: "updateInterval",
16816
- interval
16817
- });
16818
- } else if (this.fallbackTimer && this.onTick) {
16819
- clearInterval(this.fallbackTimer);
16820
- this.fallbackTimer = setInterval(() => {
16821
- if (this.onTick) {
16822
- this.onTick();
16732
+ async referInCallToSelf(callUuid, extra) {
16733
+ if (callUuid && this.currentCallId !== callUuid) {
16734
+ this.callKit.logger.warn(
16735
+ "Cannot refer in call to self: callUuid mismatch",
16736
+ {
16737
+ caller: "Connect.referInCallToSelf",
16738
+ type: "SIP",
16739
+ content: {
16740
+ currentCallId: this.currentCallId,
16741
+ callUuid
16742
+ }
16823
16743
  }
16824
- }, interval);
16744
+ );
16745
+ return;
16825
16746
  }
16826
- }
16827
- /**
16828
- * Destroy the heartbeat manager and release resources
16829
- */
16830
- destroy() {
16831
- this.stop();
16832
- if (this.worker) {
16833
- this.worker.terminate();
16834
- this.worker = null;
16747
+ if (!this.canReferInCallToSelf()) {
16748
+ this.callKit.logger.warn(
16749
+ "Cannot refer in call to self: preconditions not met",
16750
+ {
16751
+ caller: "Connect.referInCallToSelf",
16752
+ type: "SIP",
16753
+ content: {
16754
+ hasCurrentSession: !!this.currentSession,
16755
+ sessionState: this.currentSession?.state,
16756
+ isCalling: this.isCalling()
16757
+ }
16758
+ }
16759
+ );
16760
+ return;
16835
16761
  }
16836
- }
16837
- /**
16838
- * Check if using Web Worker
16839
- */
16840
- isUsingWorker() {
16841
- return this.worker !== null;
16762
+ const selfUri = this.getSelfReferUri();
16763
+ return this.referInCall(selfUri, extra);
16842
16764
  }
16843
16765
  };
16844
16766
 
@@ -16847,7 +16769,7 @@ var Socket = class {
16847
16769
  callKit;
16848
16770
  ws;
16849
16771
  lastPingTime = void 0;
16850
- heartbeatManager;
16772
+ pingTimer;
16851
16773
  /**
16852
16774
  * @description reconnect timer
16853
16775
  */
@@ -16880,18 +16802,10 @@ var Socket = class {
16880
16802
  }
16881
16803
  constructor(callKit) {
16882
16804
  this.callKit = callKit;
16883
- this.heartbeatManager = new HeartbeatManager();
16884
16805
  }
16885
16806
  get reconnectConfig() {
16886
16807
  return this.callKit.config.getReconnectConfig("incall");
16887
16808
  }
16888
- get pingInterval() {
16889
- const { keepaliveInterval } = this.callKit.config.getConfig().userInfo;
16890
- if (Number.isInteger(keepaliveInterval) && keepaliveInterval > 0) {
16891
- return keepaliveInterval * 1e3;
16892
- }
16893
- return this.reconnectConfig.pingInterval;
16894
- }
16895
16809
  isConnected() {
16896
16810
  return this.connectAuthState.isConnected;
16897
16811
  }
@@ -17073,6 +16987,28 @@ var Socket = class {
17073
16987
  this.setConnectAuthState("startConfirm", true);
17074
16988
  this.cleanReconnectState();
17075
16989
  }
16990
+ if (data.event === SocketReceiveEvent.AGENT_RTP_LOSS) {
16991
+ this.callKit.logger.warn("Agent RTP loss", {
16992
+ caller: "Socket.onMessage",
16993
+ type: "INCALL",
16994
+ content: {
16995
+ data: {
16996
+ callUuid,
16997
+ ...content
16998
+ },
16999
+ event: SocketReceiveEvent.AGENT_RTP_LOSS
17000
+ }
17001
+ });
17002
+ if (callUuid) {
17003
+ this.callKit.connect.referInCallToSelf(callUuid).catch((err) => {
17004
+ this.callKit.logger.error(err, {
17005
+ caller: "Socket.onMessage:AGENT_RTP_LOSS",
17006
+ type: "INCALL",
17007
+ content: { callUuid, event: SocketReceiveEvent.AGENT_RTP_LOSS }
17008
+ });
17009
+ });
17010
+ }
17011
+ }
17076
17012
  if (data.event === SocketReceiveEvent.CUSTOMER_RINGING) {
17077
17013
  this.callKit.trigger(KitEvent.CALL_RINGING, {
17078
17014
  time: /* @__PURE__ */ new Date(),
@@ -17226,8 +17162,8 @@ var Socket = class {
17226
17162
  return;
17227
17163
  this.send(SocketSendEvent.PING);
17228
17164
  const now = Date.now();
17229
- const { pingTimeout } = this.reconnectConfig;
17230
- if (now - this.lastPingTime > this.pingInterval + pingTimeout) {
17165
+ const { pingInterval, pingTimeout } = this.reconnectConfig;
17166
+ if (now - this.lastPingTime > pingInterval + pingTimeout) {
17231
17167
  this.callKit.logger.warn("Ping timeout not connected", {
17232
17168
  caller: "Socket.ping",
17233
17169
  type: "INCALL",
@@ -17242,27 +17178,23 @@ var Socket = class {
17242
17178
  }
17243
17179
  }
17244
17180
  checkPing() {
17245
- this.heartbeatManager.start(this.pingInterval, () => {
17181
+ if (this.pingTimer) {
17182
+ clearInterval(this.pingTimer);
17183
+ }
17184
+ const { pingInterval } = this.reconnectConfig;
17185
+ this.pingTimer = setInterval(() => {
17246
17186
  this.ping();
17247
- });
17248
- this.callKit.logger.info(
17249
- `Heartbeat started with Worker: ${this.heartbeatManager.isUsingWorker()}`,
17250
- {
17251
- caller: "Socket.checkPing",
17252
- type: "INCALL",
17253
- content: {
17254
- pingInterval: this.pingInterval,
17255
- usingWorker: this.heartbeatManager.isUsingWorker()
17256
- }
17257
- }
17258
- );
17187
+ }, pingInterval);
17259
17188
  }
17260
17189
  /**
17261
17190
  * reset socket connection and all states
17262
17191
  */
17263
17192
  async reset(config) {
17264
17193
  const { force = false } = config || {};
17265
- this.heartbeatManager.stop();
17194
+ if (this.pingTimer) {
17195
+ clearInterval(this.pingTimer);
17196
+ this.pingTimer = void 0;
17197
+ }
17266
17198
  if (force) {
17267
17199
  this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
17268
17200
  event: "INCALL_RESET"
@@ -17273,12 +17205,6 @@ var Socket = class {
17273
17205
  this.setConnectAuthState("startConfirm", false);
17274
17206
  this.clearWebSocket();
17275
17207
  }
17276
- /**
17277
- * Destroy the heartbeat manager
17278
- */
17279
- destroyHeartbeat() {
17280
- this.heartbeatManager.destroy();
17281
- }
17282
17208
  attemptReconnect() {
17283
17209
  if (this.reconnectTimer) {
17284
17210
  clearTimeout(this.reconnectTimer);
@@ -17404,7 +17330,6 @@ var CallKit = class {
17404
17330
  content: {
17405
17331
  username,
17406
17332
  password,
17407
- ua: navigator.userAgent,
17408
17333
  encryptionMethod,
17409
17334
  encryptionPassword
17410
17335
  }
@@ -17422,7 +17347,6 @@ var CallKit = class {
17422
17347
  password: encryptionPassword,
17423
17348
  timestamp: Date.now()
17424
17349
  });
17425
- console.log("user", user);
17426
17350
  if (user) {
17427
17351
  this.config.setConfig("userInfo", {
17428
17352
  wsUrl: `wss://${user.wsUrl}`,
@@ -17439,7 +17363,7 @@ var CallKit = class {
17439
17363
  iceInfo: user.iceInfo,
17440
17364
  iceGatheringTimeout: user.iceGatheringTimeout,
17441
17365
  logGather: user.logGather,
17442
- keepaliveInterval: user.keepaliveInterval,
17366
+ phoneType: user.phoneType,
17443
17367
  // encryptionType is in extra
17444
17368
  ...extra
17445
17369
  });
@@ -17536,7 +17460,10 @@ var CallKit = class {
17536
17460
  caller: "CallKit.register",
17537
17461
  content: {}
17538
17462
  });
17539
- this.connect.register();
17463
+ const { userInfo } = this.config.getConfig();
17464
+ if (userInfo.phoneType === PhoneTypeEnum.SIP) {
17465
+ this.connect.register();
17466
+ }
17540
17467
  }
17541
17468
  async unregister() {
17542
17469
  if (!this.config.check())
@@ -17646,10 +17573,13 @@ var CallKit = class {
17646
17573
  force
17647
17574
  }
17648
17575
  });
17649
- if (this.connect.isCalling()) {
17650
- await this.hangup();
17576
+ const { userInfo } = this.config.getConfig();
17577
+ if (userInfo.phoneType === PhoneTypeEnum.SIP) {
17578
+ if (this.connect.isCalling()) {
17579
+ await this.hangup();
17580
+ }
17581
+ await this.connect.reset({ force });
17651
17582
  }
17652
- await this.connect.reset({ force });
17653
17583
  if (this.config.isLogin()) {
17654
17584
  await this.logout({ isReset: false });
17655
17585
  } else {