@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.
@@ -1736,7 +1736,7 @@ var WebCall = (() => {
1736
1736
  var require_follow_redirects = __commonJS({
1737
1737
  "../../node_modules/.pnpm/follow-redirects@1.15.9/node_modules/follow-redirects/index.js"(exports, module) {
1738
1738
  var url = __require("url");
1739
- var URL2 = url.URL;
1739
+ var URL = url.URL;
1740
1740
  var http = __require("http");
1741
1741
  var https = __require("https");
1742
1742
  var Writable = __require("stream").Writable;
@@ -1752,7 +1752,7 @@ var WebCall = (() => {
1752
1752
  })();
1753
1753
  var useNativeURL = false;
1754
1754
  try {
1755
- assert(new URL2(""));
1755
+ assert(new URL(""));
1756
1756
  } catch (error) {
1757
1757
  useNativeURL = error.code === "ERR_INVALID_URL";
1758
1758
  }
@@ -2132,7 +2132,7 @@ var WebCall = (() => {
2132
2132
  function parseUrl(input) {
2133
2133
  var parsed;
2134
2134
  if (useNativeURL) {
2135
- parsed = new URL2(input);
2135
+ parsed = new URL(input);
2136
2136
  } else {
2137
2137
  parsed = validateUrl(url.parse(input));
2138
2138
  if (!isString(parsed.protocol)) {
@@ -2142,7 +2142,7 @@ var WebCall = (() => {
2142
2142
  return parsed;
2143
2143
  }
2144
2144
  function resolveUrl(relative, base) {
2145
- return useNativeURL ? new URL2(relative, base) : parseUrl(url.resolve(base, relative));
2145
+ return useNativeURL ? new URL(relative, base) : parseUrl(url.resolve(base, relative));
2146
2146
  }
2147
2147
  function validateUrl(input) {
2148
2148
  if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) {
@@ -2221,7 +2221,7 @@ var WebCall = (() => {
2221
2221
  return typeof value === "object" && "length" in value;
2222
2222
  }
2223
2223
  function isURL(value) {
2224
- return URL2 && value instanceof URL2;
2224
+ return URL && value instanceof URL;
2225
2225
  }
2226
2226
  module.exports = wrap({ http, https });
2227
2227
  module.exports.wrap = wrap;
@@ -3237,7 +3237,7 @@ var WebCall = (() => {
3237
3237
  const res = await this.post({
3238
3238
  url: "/auth/agentUser/login",
3239
3239
  method: "post",
3240
- data: { ...params, browserVersion: navigator.userAgent }
3240
+ data: params
3241
3241
  });
3242
3242
  return res;
3243
3243
  } finally {
@@ -3700,7 +3700,11 @@ var WebCall = (() => {
3700
3700
  ERROR: "ERROR",
3701
3701
  SESSION_ERROR: "SESSION_ERROR",
3702
3702
  WAITING_QUEUE: "WAITING_QUEUE",
3703
- CUSTOMER_MATCH_BLACK_PHONE: "CUSTOMER_MATCH_BLACK_PHONE"
3703
+ CUSTOMER_MATCH_BLACK_PHONE: "CUSTOMER_MATCH_BLACK_PHONE",
3704
+ /**
3705
+ * Agent RTP loss
3706
+ */
3707
+ AGENT_RTP_LOSS: "AGENT_RTP_LOSS"
3704
3708
  };
3705
3709
  var EncryptionMethod = {
3706
3710
  NONE: "NONE",
@@ -3720,6 +3724,12 @@ var WebCall = (() => {
3720
3724
  phoneNum: 1,
3721
3725
  workOrderId: 2
3722
3726
  };
3727
+ var PhoneTypeEnum = {
3728
+ SIP: 0,
3729
+ TEL: 1,
3730
+ OUT: 2,
3731
+ SP: 5
3732
+ };
3723
3733
  var trackLogsDefaultConfig = {
3724
3734
  enabled: false,
3725
3735
  interval: 5e3,
@@ -3883,7 +3893,7 @@ var WebCall = (() => {
3883
3893
  // package.json
3884
3894
  var package_default = {
3885
3895
  name: "@koi-design/callkit",
3886
- version: "2.2.0-beta.4",
3896
+ version: "2.3.0-beta.10",
3887
3897
  description: "callkit",
3888
3898
  author: "koi",
3889
3899
  license: "ISC",
@@ -3960,6 +3970,7 @@ var WebCall = (() => {
3960
3970
  password: "",
3961
3971
  encryptionPassword: EncryptionMethod.INTERNAL,
3962
3972
  sourceType: CallSourceType.phoneNum,
3973
+ phoneType: PhoneTypeEnum.SIP,
3963
3974
  // Extension number
3964
3975
  extno: "",
3965
3976
  workOrderId: "",
@@ -4003,6 +4014,7 @@ var WebCall = (() => {
4003
4014
  encryptionPassword: "",
4004
4015
  userPart: "",
4005
4016
  sourceType: CallSourceType.phoneNum,
4017
+ phoneType: PhoneTypeEnum.SIP,
4006
4018
  extno: "",
4007
4019
  workOrderId: "",
4008
4020
  agentId: "",
@@ -18981,8 +18993,6 @@ ${log}` : log;
18981
18993
  });
18982
18994
  return;
18983
18995
  }
18984
- const { userInfo } = this.callKit.config.getConfig();
18985
- const { userPart, fsIp, fsPort } = userInfo;
18986
18996
  const { registererOptions = {} } = this.reconnectConfig;
18987
18997
  this.registerer = new Registerer(this.userAgent, registererOptions);
18988
18998
  this.registerer.stateChange.addListener((state) => {
@@ -19016,27 +19026,26 @@ ${log}` : log;
19016
19026
  });
19017
19027
  this.setRegister(true);
19018
19028
  if (this.isReConnected) {
19019
- if (this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling()) {
19020
- const selfUri = `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
19029
+ if (this.canReferInCallToSelf()) {
19021
19030
  this.callKit.logger.info(
19022
19031
  "Reconnected, referring active session to self",
19023
19032
  {
19024
19033
  caller: "Connect.setupRegisterer.registererStateChange",
19025
19034
  type: "SIP",
19026
19035
  content: {
19027
- selfUri,
19036
+ selfUri: this.getSelfReferUri(),
19028
19037
  sessionState: this.currentSession.state,
19029
19038
  connectStatus: this.connectStatus
19030
19039
  }
19031
19040
  }
19032
19041
  );
19033
- this.referInCall(selfUri).catch((err) => {
19042
+ this.referInCallToSelf().catch((err) => {
19034
19043
  this.callKit.logger.error(err, {
19035
19044
  caller: "Connect.setupRegisterer.registererStateChange",
19036
19045
  type: "SIP",
19037
19046
  content: {
19038
19047
  errCode: ErrorCode.WEBRTC_CALL_INVITE_ERROR,
19039
- selfUri
19048
+ selfUri: this.getSelfReferUri()
19040
19049
  }
19041
19050
  });
19042
19051
  });
@@ -19865,145 +19874,58 @@ ${log}` : log;
19865
19874
  }
19866
19875
  this.currentSession.refer(target, extra?.sessionReferOptions);
19867
19876
  }
19868
- };
19869
-
19870
- // core/heartbeat-worker.ts
19871
- var workerCode = `
19872
- let timer = null;
19873
- let interval = 30000;
19874
-
19875
- self.onmessage = function(e) {
19876
- const { type, interval: newInterval } = e.data;
19877
-
19878
- if (type === 'start') {
19879
- if (timer) {
19880
- clearInterval(timer);
19881
- }
19882
- interval = newInterval || interval;
19883
- timer = setInterval(() => {
19884
- self.postMessage({ type: 'tick' });
19885
- }, interval);
19886
- }
19887
-
19888
- if (type === 'stop') {
19889
- if (timer) {
19890
- clearInterval(timer);
19891
- timer = null;
19892
- }
19893
- }
19894
-
19895
- if (type === 'updateInterval') {
19896
- interval = newInterval;
19897
- if (timer) {
19898
- clearInterval(timer);
19899
- timer = setInterval(() => {
19900
- self.postMessage({ type: 'tick' });
19901
- }, interval);
19902
- }
19903
- }
19904
- };
19905
- `;
19906
- function createHeartbeatWorker() {
19907
- try {
19908
- const blob = new Blob([workerCode], { type: "application/javascript" });
19909
- const workerUrl = URL.createObjectURL(blob);
19910
- const worker = new Worker(workerUrl);
19911
- URL.revokeObjectURL(workerUrl);
19912
- return worker;
19913
- } catch {
19914
- return null;
19915
- }
19916
- }
19917
- var HeartbeatManager = class {
19918
- worker = null;
19919
- fallbackTimer = null;
19920
- interval = 3e4;
19921
- onTick = null;
19922
- isRunning = false;
19923
- constructor() {
19924
- this.worker = createHeartbeatWorker();
19925
- if (this.worker) {
19926
- this.worker.onmessage = (e) => {
19927
- if (e.data.type === "tick" && this.onTick) {
19928
- this.onTick();
19929
- }
19930
- };
19931
- }
19932
- }
19933
19877
  /**
19934
- * Start the heartbeat
19935
- * @param interval - Interval in milliseconds
19936
- * @param onTick - Callback function to execute on each tick
19878
+ * Get the SIP URI for "refer to self" (same as reconnection refer logic).
19879
+ * Shared by referInCallToSelf and internal reconnection refer.
19937
19880
  */
19938
- start(interval, onTick) {
19939
- this.stop();
19940
- this.interval = interval;
19941
- this.onTick = onTick;
19942
- this.isRunning = true;
19943
- if (this.worker) {
19944
- this.worker.postMessage({
19945
- type: "start",
19946
- interval
19947
- });
19948
- } else {
19949
- this.fallbackTimer = setInterval(() => {
19950
- if (this.onTick) {
19951
- this.onTick();
19952
- }
19953
- }, interval);
19954
- }
19881
+ getSelfReferUri() {
19882
+ const { userInfo } = this.callKit.config.getConfig();
19883
+ const { userPart, fsIp, fsPort } = userInfo;
19884
+ return `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
19955
19885
  }
19956
19886
  /**
19957
- * Stop the heartbeat
19887
+ * Whether we can refer the current call to self (has active session in Established/Establishing and is calling).
19888
+ * Shared by reconnection logic and referInCallToSelf.
19958
19889
  */
19959
- stop() {
19960
- this.isRunning = false;
19961
- this.onTick = null;
19962
- if (this.worker) {
19963
- this.worker.postMessage({ type: "stop" });
19964
- }
19965
- if (this.fallbackTimer) {
19966
- clearInterval(this.fallbackTimer);
19967
- this.fallbackTimer = null;
19968
- }
19890
+ canReferInCallToSelf() {
19891
+ return !!this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling();
19969
19892
  }
19970
19893
  /**
19971
- * Update the heartbeat interval
19972
- * @param interval - New interval in milliseconds
19894
+ * Refer the current call to self (e.g. Agent RTP loss recovery, post-reconnect recovery).
19895
+ * Socket and other callers can use this without constructing referTo.
19973
19896
  */
19974
- updateInterval(interval) {
19975
- this.interval = interval;
19976
- if (!this.isRunning)
19977
- return;
19978
- if (this.worker) {
19979
- this.worker.postMessage({
19980
- type: "updateInterval",
19981
- interval
19982
- });
19983
- } else if (this.fallbackTimer && this.onTick) {
19984
- clearInterval(this.fallbackTimer);
19985
- this.fallbackTimer = setInterval(() => {
19986
- if (this.onTick) {
19987
- this.onTick();
19897
+ async referInCallToSelf(callUuid, extra) {
19898
+ if (callUuid && this.currentCallId !== callUuid) {
19899
+ this.callKit.logger.warn(
19900
+ "Cannot refer in call to self: callUuid mismatch",
19901
+ {
19902
+ caller: "Connect.referInCallToSelf",
19903
+ type: "SIP",
19904
+ content: {
19905
+ currentCallId: this.currentCallId,
19906
+ callUuid
19907
+ }
19988
19908
  }
19989
- }, interval);
19909
+ );
19910
+ return;
19990
19911
  }
19991
- }
19992
- /**
19993
- * Destroy the heartbeat manager and release resources
19994
- */
19995
- destroy() {
19996
- this.stop();
19997
- if (this.worker) {
19998
- this.worker.terminate();
19999
- this.worker = null;
19912
+ if (!this.canReferInCallToSelf()) {
19913
+ this.callKit.logger.warn(
19914
+ "Cannot refer in call to self: preconditions not met",
19915
+ {
19916
+ caller: "Connect.referInCallToSelf",
19917
+ type: "SIP",
19918
+ content: {
19919
+ hasCurrentSession: !!this.currentSession,
19920
+ sessionState: this.currentSession?.state,
19921
+ isCalling: this.isCalling()
19922
+ }
19923
+ }
19924
+ );
19925
+ return;
20000
19926
  }
20001
- }
20002
- /**
20003
- * Check if using Web Worker
20004
- */
20005
- isUsingWorker() {
20006
- return this.worker !== null;
19927
+ const selfUri = this.getSelfReferUri();
19928
+ return this.referInCall(selfUri, extra);
20007
19929
  }
20008
19930
  };
20009
19931
 
@@ -20012,7 +19934,7 @@ self.onmessage = function(e) {
20012
19934
  callKit;
20013
19935
  ws;
20014
19936
  lastPingTime = void 0;
20015
- heartbeatManager;
19937
+ pingTimer;
20016
19938
  /**
20017
19939
  * @description reconnect timer
20018
19940
  */
@@ -20045,18 +19967,10 @@ self.onmessage = function(e) {
20045
19967
  }
20046
19968
  constructor(callKit) {
20047
19969
  this.callKit = callKit;
20048
- this.heartbeatManager = new HeartbeatManager();
20049
19970
  }
20050
19971
  get reconnectConfig() {
20051
19972
  return this.callKit.config.getReconnectConfig("incall");
20052
19973
  }
20053
- get pingInterval() {
20054
- const { keepaliveInterval } = this.callKit.config.getConfig().userInfo;
20055
- if (Number.isInteger(keepaliveInterval) && keepaliveInterval > 0) {
20056
- return keepaliveInterval * 1e3;
20057
- }
20058
- return this.reconnectConfig.pingInterval;
20059
- }
20060
19974
  isConnected() {
20061
19975
  return this.connectAuthState.isConnected;
20062
19976
  }
@@ -20238,6 +20152,28 @@ self.onmessage = function(e) {
20238
20152
  this.setConnectAuthState("startConfirm", true);
20239
20153
  this.cleanReconnectState();
20240
20154
  }
20155
+ if (data.event === SocketReceiveEvent.AGENT_RTP_LOSS) {
20156
+ this.callKit.logger.warn("Agent RTP loss", {
20157
+ caller: "Socket.onMessage",
20158
+ type: "INCALL",
20159
+ content: {
20160
+ data: {
20161
+ callUuid,
20162
+ ...content
20163
+ },
20164
+ event: SocketReceiveEvent.AGENT_RTP_LOSS
20165
+ }
20166
+ });
20167
+ if (callUuid) {
20168
+ this.callKit.connect.referInCallToSelf(callUuid).catch((err) => {
20169
+ this.callKit.logger.error(err, {
20170
+ caller: "Socket.onMessage:AGENT_RTP_LOSS",
20171
+ type: "INCALL",
20172
+ content: { callUuid, event: SocketReceiveEvent.AGENT_RTP_LOSS }
20173
+ });
20174
+ });
20175
+ }
20176
+ }
20241
20177
  if (data.event === SocketReceiveEvent.CUSTOMER_RINGING) {
20242
20178
  this.callKit.trigger(KitEvent.CALL_RINGING, {
20243
20179
  time: /* @__PURE__ */ new Date(),
@@ -20391,8 +20327,8 @@ self.onmessage = function(e) {
20391
20327
  return;
20392
20328
  this.send(SocketSendEvent.PING);
20393
20329
  const now = Date.now();
20394
- const { pingTimeout } = this.reconnectConfig;
20395
- if (now - this.lastPingTime > this.pingInterval + pingTimeout) {
20330
+ const { pingInterval, pingTimeout } = this.reconnectConfig;
20331
+ if (now - this.lastPingTime > pingInterval + pingTimeout) {
20396
20332
  this.callKit.logger.warn("Ping timeout not connected", {
20397
20333
  caller: "Socket.ping",
20398
20334
  type: "INCALL",
@@ -20407,27 +20343,23 @@ self.onmessage = function(e) {
20407
20343
  }
20408
20344
  }
20409
20345
  checkPing() {
20410
- this.heartbeatManager.start(this.pingInterval, () => {
20346
+ if (this.pingTimer) {
20347
+ clearInterval(this.pingTimer);
20348
+ }
20349
+ const { pingInterval } = this.reconnectConfig;
20350
+ this.pingTimer = setInterval(() => {
20411
20351
  this.ping();
20412
- });
20413
- this.callKit.logger.info(
20414
- `Heartbeat started with Worker: ${this.heartbeatManager.isUsingWorker()}`,
20415
- {
20416
- caller: "Socket.checkPing",
20417
- type: "INCALL",
20418
- content: {
20419
- pingInterval: this.pingInterval,
20420
- usingWorker: this.heartbeatManager.isUsingWorker()
20421
- }
20422
- }
20423
- );
20352
+ }, pingInterval);
20424
20353
  }
20425
20354
  /**
20426
20355
  * reset socket connection and all states
20427
20356
  */
20428
20357
  async reset(config) {
20429
20358
  const { force = false } = config || {};
20430
- this.heartbeatManager.stop();
20359
+ if (this.pingTimer) {
20360
+ clearInterval(this.pingTimer);
20361
+ this.pingTimer = void 0;
20362
+ }
20431
20363
  if (force) {
20432
20364
  this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
20433
20365
  event: "INCALL_RESET"
@@ -20438,12 +20370,6 @@ self.onmessage = function(e) {
20438
20370
  this.setConnectAuthState("startConfirm", false);
20439
20371
  this.clearWebSocket();
20440
20372
  }
20441
- /**
20442
- * Destroy the heartbeat manager
20443
- */
20444
- destroyHeartbeat() {
20445
- this.heartbeatManager.destroy();
20446
- }
20447
20373
  attemptReconnect() {
20448
20374
  if (this.reconnectTimer) {
20449
20375
  clearTimeout(this.reconnectTimer);
@@ -20569,7 +20495,6 @@ self.onmessage = function(e) {
20569
20495
  content: {
20570
20496
  username,
20571
20497
  password,
20572
- ua: navigator.userAgent,
20573
20498
  encryptionMethod,
20574
20499
  encryptionPassword
20575
20500
  }
@@ -20587,7 +20512,6 @@ self.onmessage = function(e) {
20587
20512
  password: encryptionPassword,
20588
20513
  timestamp: Date.now()
20589
20514
  });
20590
- console.log("user", user);
20591
20515
  if (user) {
20592
20516
  this.config.setConfig("userInfo", {
20593
20517
  wsUrl: `wss://${user.wsUrl}`,
@@ -20604,7 +20528,7 @@ self.onmessage = function(e) {
20604
20528
  iceInfo: user.iceInfo,
20605
20529
  iceGatheringTimeout: user.iceGatheringTimeout,
20606
20530
  logGather: user.logGather,
20607
- keepaliveInterval: user.keepaliveInterval,
20531
+ phoneType: user.phoneType,
20608
20532
  // encryptionType is in extra
20609
20533
  ...extra
20610
20534
  });
@@ -20701,7 +20625,10 @@ self.onmessage = function(e) {
20701
20625
  caller: "CallKit.register",
20702
20626
  content: {}
20703
20627
  });
20704
- this.connect.register();
20628
+ const { userInfo } = this.config.getConfig();
20629
+ if (userInfo.phoneType === PhoneTypeEnum.SIP) {
20630
+ this.connect.register();
20631
+ }
20705
20632
  }
20706
20633
  async unregister() {
20707
20634
  if (!this.config.check())
@@ -20811,10 +20738,13 @@ self.onmessage = function(e) {
20811
20738
  force
20812
20739
  }
20813
20740
  });
20814
- if (this.connect.isCalling()) {
20815
- await this.hangup();
20741
+ const { userInfo } = this.config.getConfig();
20742
+ if (userInfo.phoneType === PhoneTypeEnum.SIP) {
20743
+ if (this.connect.isCalling()) {
20744
+ await this.hangup();
20745
+ }
20746
+ await this.connect.reset({ force });
20816
20747
  }
20817
- await this.connect.reset({ force });
20818
20748
  if (this.config.isLogin()) {
20819
20749
  await this.logout({ isReset: false });
20820
20750
  } else {