@koi-design/callkit 2.3.0-beta.8 → 2.3.0
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.d.ts +22 -1
- package/dist/index.global.js +274 -33
- package/dist/index.js +269 -28
- package/dist/index.mjs +269 -28
- package/package.json +1 -1
- package/dist/index.global.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
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
|
|
75
|
+
data: { ...params, browserVersion: navigator.userAgent }
|
|
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",
|
|
@@ -724,7 +728,7 @@ var Call = class {
|
|
|
724
728
|
// package.json
|
|
725
729
|
var package_default = {
|
|
726
730
|
name: "@koi-design/callkit",
|
|
727
|
-
version: "2.3.0
|
|
731
|
+
version: "2.3.0",
|
|
728
732
|
description: "callkit",
|
|
729
733
|
author: "koi",
|
|
730
734
|
license: "ISC",
|
|
@@ -15824,8 +15828,6 @@ var Connect = class {
|
|
|
15824
15828
|
});
|
|
15825
15829
|
return;
|
|
15826
15830
|
}
|
|
15827
|
-
const { userInfo } = this.callKit.config.getConfig();
|
|
15828
|
-
const { userPart, fsIp, fsPort } = userInfo;
|
|
15829
15831
|
const { registererOptions = {} } = this.reconnectConfig;
|
|
15830
15832
|
this.registerer = new Registerer(this.userAgent, registererOptions);
|
|
15831
15833
|
this.registerer.stateChange.addListener((state) => {
|
|
@@ -15859,27 +15861,26 @@ var Connect = class {
|
|
|
15859
15861
|
});
|
|
15860
15862
|
this.setRegister(true);
|
|
15861
15863
|
if (this.isReConnected) {
|
|
15862
|
-
if (this.
|
|
15863
|
-
const selfUri = `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
|
|
15864
|
+
if (this.canReferInCallToSelf()) {
|
|
15864
15865
|
this.callKit.logger.info(
|
|
15865
15866
|
"Reconnected, referring active session to self",
|
|
15866
15867
|
{
|
|
15867
15868
|
caller: "Connect.setupRegisterer.registererStateChange",
|
|
15868
15869
|
type: "SIP",
|
|
15869
15870
|
content: {
|
|
15870
|
-
selfUri,
|
|
15871
|
+
selfUri: this.getSelfReferUri(),
|
|
15871
15872
|
sessionState: this.currentSession.state,
|
|
15872
15873
|
connectStatus: this.connectStatus
|
|
15873
15874
|
}
|
|
15874
15875
|
}
|
|
15875
15876
|
);
|
|
15876
|
-
this.
|
|
15877
|
+
this.referInCallToSelf().catch((err) => {
|
|
15877
15878
|
this.callKit.logger.error(err, {
|
|
15878
15879
|
caller: "Connect.setupRegisterer.registererStateChange",
|
|
15879
15880
|
type: "SIP",
|
|
15880
15881
|
content: {
|
|
15881
15882
|
errCode: ErrorCode.WEBRTC_CALL_INVITE_ERROR,
|
|
15882
|
-
selfUri
|
|
15883
|
+
selfUri: this.getSelfReferUri()
|
|
15883
15884
|
}
|
|
15884
15885
|
});
|
|
15885
15886
|
});
|
|
@@ -16708,6 +16709,199 @@ var Connect = class {
|
|
|
16708
16709
|
}
|
|
16709
16710
|
this.currentSession.refer(target, extra?.sessionReferOptions);
|
|
16710
16711
|
}
|
|
16712
|
+
/**
|
|
16713
|
+
* Get the SIP URI for "refer to self" (same as reconnection refer logic).
|
|
16714
|
+
* Shared by referInCallToSelf and internal reconnection refer.
|
|
16715
|
+
*/
|
|
16716
|
+
getSelfReferUri() {
|
|
16717
|
+
const { userInfo } = this.callKit.config.getConfig();
|
|
16718
|
+
const { userPart, fsIp, fsPort } = userInfo;
|
|
16719
|
+
return `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
|
|
16720
|
+
}
|
|
16721
|
+
/**
|
|
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.
|
|
16724
|
+
*/
|
|
16725
|
+
canReferInCallToSelf() {
|
|
16726
|
+
return !!this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling();
|
|
16727
|
+
}
|
|
16728
|
+
/**
|
|
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.
|
|
16731
|
+
*/
|
|
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
|
+
}
|
|
16743
|
+
}
|
|
16744
|
+
);
|
|
16745
|
+
return;
|
|
16746
|
+
}
|
|
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;
|
|
16761
|
+
}
|
|
16762
|
+
const selfUri = this.getSelfReferUri();
|
|
16763
|
+
return this.referInCall(selfUri, extra);
|
|
16764
|
+
}
|
|
16765
|
+
};
|
|
16766
|
+
|
|
16767
|
+
// core/heartbeat-worker.ts
|
|
16768
|
+
var workerCode = `
|
|
16769
|
+
let timer = null;
|
|
16770
|
+
let interval = 30000;
|
|
16771
|
+
|
|
16772
|
+
self.onmessage = function(e) {
|
|
16773
|
+
const { type, interval: newInterval } = e.data;
|
|
16774
|
+
|
|
16775
|
+
if (type === 'start') {
|
|
16776
|
+
if (timer) {
|
|
16777
|
+
clearInterval(timer);
|
|
16778
|
+
}
|
|
16779
|
+
interval = newInterval || interval;
|
|
16780
|
+
timer = setInterval(() => {
|
|
16781
|
+
self.postMessage({ type: 'tick' });
|
|
16782
|
+
}, interval);
|
|
16783
|
+
}
|
|
16784
|
+
|
|
16785
|
+
if (type === 'stop') {
|
|
16786
|
+
if (timer) {
|
|
16787
|
+
clearInterval(timer);
|
|
16788
|
+
timer = null;
|
|
16789
|
+
}
|
|
16790
|
+
}
|
|
16791
|
+
|
|
16792
|
+
if (type === 'updateInterval') {
|
|
16793
|
+
interval = newInterval;
|
|
16794
|
+
if (timer) {
|
|
16795
|
+
clearInterval(timer);
|
|
16796
|
+
timer = setInterval(() => {
|
|
16797
|
+
self.postMessage({ type: 'tick' });
|
|
16798
|
+
}, interval);
|
|
16799
|
+
}
|
|
16800
|
+
}
|
|
16801
|
+
};
|
|
16802
|
+
`;
|
|
16803
|
+
function createHeartbeatWorker() {
|
|
16804
|
+
try {
|
|
16805
|
+
const blob = new Blob([workerCode], { type: "application/javascript" });
|
|
16806
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
16807
|
+
const worker = new Worker(workerUrl);
|
|
16808
|
+
URL.revokeObjectURL(workerUrl);
|
|
16809
|
+
return worker;
|
|
16810
|
+
} catch {
|
|
16811
|
+
return null;
|
|
16812
|
+
}
|
|
16813
|
+
}
|
|
16814
|
+
var HeartbeatManager = class {
|
|
16815
|
+
worker = null;
|
|
16816
|
+
fallbackTimer = null;
|
|
16817
|
+
interval = 3e4;
|
|
16818
|
+
onTick = null;
|
|
16819
|
+
isRunning = false;
|
|
16820
|
+
constructor() {
|
|
16821
|
+
this.worker = createHeartbeatWorker();
|
|
16822
|
+
if (this.worker) {
|
|
16823
|
+
this.worker.onmessage = (e) => {
|
|
16824
|
+
if (e.data.type === "tick" && this.onTick) {
|
|
16825
|
+
this.onTick();
|
|
16826
|
+
}
|
|
16827
|
+
};
|
|
16828
|
+
}
|
|
16829
|
+
}
|
|
16830
|
+
/**
|
|
16831
|
+
* Start the heartbeat
|
|
16832
|
+
* @param interval - Interval in milliseconds
|
|
16833
|
+
* @param onTick - Callback function to execute on each tick
|
|
16834
|
+
*/
|
|
16835
|
+
start(interval, onTick) {
|
|
16836
|
+
this.stop();
|
|
16837
|
+
this.interval = interval;
|
|
16838
|
+
this.onTick = onTick;
|
|
16839
|
+
this.isRunning = true;
|
|
16840
|
+
if (this.worker) {
|
|
16841
|
+
this.worker.postMessage({
|
|
16842
|
+
type: "start",
|
|
16843
|
+
interval
|
|
16844
|
+
});
|
|
16845
|
+
} else {
|
|
16846
|
+
this.fallbackTimer = setInterval(() => {
|
|
16847
|
+
if (this.onTick) {
|
|
16848
|
+
this.onTick();
|
|
16849
|
+
}
|
|
16850
|
+
}, interval);
|
|
16851
|
+
}
|
|
16852
|
+
}
|
|
16853
|
+
/**
|
|
16854
|
+
* Stop the heartbeat
|
|
16855
|
+
*/
|
|
16856
|
+
stop() {
|
|
16857
|
+
this.isRunning = false;
|
|
16858
|
+
this.onTick = null;
|
|
16859
|
+
if (this.worker) {
|
|
16860
|
+
this.worker.postMessage({ type: "stop" });
|
|
16861
|
+
}
|
|
16862
|
+
if (this.fallbackTimer) {
|
|
16863
|
+
clearInterval(this.fallbackTimer);
|
|
16864
|
+
this.fallbackTimer = null;
|
|
16865
|
+
}
|
|
16866
|
+
}
|
|
16867
|
+
/**
|
|
16868
|
+
* Update the heartbeat interval
|
|
16869
|
+
* @param interval - New interval in milliseconds
|
|
16870
|
+
*/
|
|
16871
|
+
updateInterval(interval) {
|
|
16872
|
+
this.interval = interval;
|
|
16873
|
+
if (!this.isRunning)
|
|
16874
|
+
return;
|
|
16875
|
+
if (this.worker) {
|
|
16876
|
+
this.worker.postMessage({
|
|
16877
|
+
type: "updateInterval",
|
|
16878
|
+
interval
|
|
16879
|
+
});
|
|
16880
|
+
} else if (this.fallbackTimer && this.onTick) {
|
|
16881
|
+
clearInterval(this.fallbackTimer);
|
|
16882
|
+
this.fallbackTimer = setInterval(() => {
|
|
16883
|
+
if (this.onTick) {
|
|
16884
|
+
this.onTick();
|
|
16885
|
+
}
|
|
16886
|
+
}, interval);
|
|
16887
|
+
}
|
|
16888
|
+
}
|
|
16889
|
+
/**
|
|
16890
|
+
* Destroy the heartbeat manager and release resources
|
|
16891
|
+
*/
|
|
16892
|
+
destroy() {
|
|
16893
|
+
this.stop();
|
|
16894
|
+
if (this.worker) {
|
|
16895
|
+
this.worker.terminate();
|
|
16896
|
+
this.worker = null;
|
|
16897
|
+
}
|
|
16898
|
+
}
|
|
16899
|
+
/**
|
|
16900
|
+
* Check if using Web Worker
|
|
16901
|
+
*/
|
|
16902
|
+
isUsingWorker() {
|
|
16903
|
+
return this.worker !== null;
|
|
16904
|
+
}
|
|
16711
16905
|
};
|
|
16712
16906
|
|
|
16713
16907
|
// core/socket.ts
|
|
@@ -16715,7 +16909,7 @@ var Socket = class {
|
|
|
16715
16909
|
callKit;
|
|
16716
16910
|
ws;
|
|
16717
16911
|
lastPingTime = void 0;
|
|
16718
|
-
|
|
16912
|
+
heartbeatManager;
|
|
16719
16913
|
/**
|
|
16720
16914
|
* @description reconnect timer
|
|
16721
16915
|
*/
|
|
@@ -16748,10 +16942,18 @@ var Socket = class {
|
|
|
16748
16942
|
}
|
|
16749
16943
|
constructor(callKit) {
|
|
16750
16944
|
this.callKit = callKit;
|
|
16945
|
+
this.heartbeatManager = new HeartbeatManager();
|
|
16751
16946
|
}
|
|
16752
16947
|
get reconnectConfig() {
|
|
16753
16948
|
return this.callKit.config.getReconnectConfig("incall");
|
|
16754
16949
|
}
|
|
16950
|
+
get pingInterval() {
|
|
16951
|
+
const { keepaliveInterval } = this.callKit.config.getConfig().userInfo;
|
|
16952
|
+
if (Number.isInteger(keepaliveInterval) && keepaliveInterval > 0) {
|
|
16953
|
+
return keepaliveInterval * 1e3;
|
|
16954
|
+
}
|
|
16955
|
+
return this.reconnectConfig.pingInterval;
|
|
16956
|
+
}
|
|
16755
16957
|
isConnected() {
|
|
16756
16958
|
return this.connectAuthState.isConnected;
|
|
16757
16959
|
}
|
|
@@ -16933,6 +17135,28 @@ var Socket = class {
|
|
|
16933
17135
|
this.setConnectAuthState("startConfirm", true);
|
|
16934
17136
|
this.cleanReconnectState();
|
|
16935
17137
|
}
|
|
17138
|
+
if (data.event === SocketReceiveEvent.AGENT_RTP_LOSS) {
|
|
17139
|
+
this.callKit.logger.warn("Agent RTP loss", {
|
|
17140
|
+
caller: "Socket.onMessage",
|
|
17141
|
+
type: "INCALL",
|
|
17142
|
+
content: {
|
|
17143
|
+
data: {
|
|
17144
|
+
callUuid,
|
|
17145
|
+
...content
|
|
17146
|
+
},
|
|
17147
|
+
event: SocketReceiveEvent.AGENT_RTP_LOSS
|
|
17148
|
+
}
|
|
17149
|
+
});
|
|
17150
|
+
if (callUuid) {
|
|
17151
|
+
this.callKit.connect.referInCallToSelf(callUuid).catch((err) => {
|
|
17152
|
+
this.callKit.logger.error(err, {
|
|
17153
|
+
caller: "Socket.onMessage:AGENT_RTP_LOSS",
|
|
17154
|
+
type: "INCALL",
|
|
17155
|
+
content: { callUuid, event: SocketReceiveEvent.AGENT_RTP_LOSS }
|
|
17156
|
+
});
|
|
17157
|
+
});
|
|
17158
|
+
}
|
|
17159
|
+
}
|
|
16936
17160
|
if (data.event === SocketReceiveEvent.CUSTOMER_RINGING) {
|
|
16937
17161
|
this.callKit.trigger(KitEvent.CALL_RINGING, {
|
|
16938
17162
|
time: /* @__PURE__ */ new Date(),
|
|
@@ -17086,8 +17310,8 @@ var Socket = class {
|
|
|
17086
17310
|
return;
|
|
17087
17311
|
this.send(SocketSendEvent.PING);
|
|
17088
17312
|
const now = Date.now();
|
|
17089
|
-
const {
|
|
17090
|
-
if (now - this.lastPingTime > pingInterval + pingTimeout) {
|
|
17313
|
+
const { pingTimeout } = this.reconnectConfig;
|
|
17314
|
+
if (now - this.lastPingTime > this.pingInterval + pingTimeout) {
|
|
17091
17315
|
this.callKit.logger.warn("Ping timeout not connected", {
|
|
17092
17316
|
caller: "Socket.ping",
|
|
17093
17317
|
type: "INCALL",
|
|
@@ -17102,23 +17326,27 @@ var Socket = class {
|
|
|
17102
17326
|
}
|
|
17103
17327
|
}
|
|
17104
17328
|
checkPing() {
|
|
17105
|
-
|
|
17106
|
-
clearInterval(this.pingTimer);
|
|
17107
|
-
}
|
|
17108
|
-
const { pingInterval } = this.reconnectConfig;
|
|
17109
|
-
this.pingTimer = setInterval(() => {
|
|
17329
|
+
this.heartbeatManager.start(this.pingInterval, () => {
|
|
17110
17330
|
this.ping();
|
|
17111
|
-
}
|
|
17331
|
+
});
|
|
17332
|
+
this.callKit.logger.info(
|
|
17333
|
+
`Heartbeat started with Worker: ${this.heartbeatManager.isUsingWorker()}`,
|
|
17334
|
+
{
|
|
17335
|
+
caller: "Socket.checkPing",
|
|
17336
|
+
type: "INCALL",
|
|
17337
|
+
content: {
|
|
17338
|
+
pingInterval: this.pingInterval,
|
|
17339
|
+
usingWorker: this.heartbeatManager.isUsingWorker()
|
|
17340
|
+
}
|
|
17341
|
+
}
|
|
17342
|
+
);
|
|
17112
17343
|
}
|
|
17113
17344
|
/**
|
|
17114
17345
|
* reset socket connection and all states
|
|
17115
17346
|
*/
|
|
17116
17347
|
async reset(config) {
|
|
17117
17348
|
const { force = false } = config || {};
|
|
17118
|
-
|
|
17119
|
-
clearInterval(this.pingTimer);
|
|
17120
|
-
this.pingTimer = void 0;
|
|
17121
|
-
}
|
|
17349
|
+
this.heartbeatManager.stop();
|
|
17122
17350
|
if (force) {
|
|
17123
17351
|
this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
|
|
17124
17352
|
event: "INCALL_RESET"
|
|
@@ -17129,6 +17357,12 @@ var Socket = class {
|
|
|
17129
17357
|
this.setConnectAuthState("startConfirm", false);
|
|
17130
17358
|
this.clearWebSocket();
|
|
17131
17359
|
}
|
|
17360
|
+
/**
|
|
17361
|
+
* Destroy the heartbeat manager
|
|
17362
|
+
*/
|
|
17363
|
+
destroyHeartbeat() {
|
|
17364
|
+
this.heartbeatManager.destroy();
|
|
17365
|
+
}
|
|
17132
17366
|
attemptReconnect() {
|
|
17133
17367
|
if (this.reconnectTimer) {
|
|
17134
17368
|
clearTimeout(this.reconnectTimer);
|
|
@@ -17254,6 +17488,7 @@ var CallKit = class {
|
|
|
17254
17488
|
content: {
|
|
17255
17489
|
username,
|
|
17256
17490
|
password,
|
|
17491
|
+
ua: navigator.userAgent,
|
|
17257
17492
|
encryptionMethod,
|
|
17258
17493
|
encryptionPassword
|
|
17259
17494
|
}
|
|
@@ -17287,6 +17522,7 @@ var CallKit = class {
|
|
|
17287
17522
|
iceInfo: user.iceInfo,
|
|
17288
17523
|
iceGatheringTimeout: user.iceGatheringTimeout,
|
|
17289
17524
|
logGather: user.logGather,
|
|
17525
|
+
keepaliveInterval: user.keepaliveInterval,
|
|
17290
17526
|
phoneType: user.phoneType,
|
|
17291
17527
|
// encryptionType is in extra
|
|
17292
17528
|
...extra
|
|
@@ -17384,7 +17620,10 @@ var CallKit = class {
|
|
|
17384
17620
|
caller: "CallKit.register",
|
|
17385
17621
|
content: {}
|
|
17386
17622
|
});
|
|
17387
|
-
this.
|
|
17623
|
+
const { userInfo } = this.config.getConfig();
|
|
17624
|
+
if (userInfo.phoneType === PhoneTypeEnum.SIP) {
|
|
17625
|
+
this.connect.register();
|
|
17626
|
+
}
|
|
17388
17627
|
}
|
|
17389
17628
|
async unregister() {
|
|
17390
17629
|
if (!this.config.check())
|
|
@@ -17494,10 +17733,13 @@ var CallKit = class {
|
|
|
17494
17733
|
force
|
|
17495
17734
|
}
|
|
17496
17735
|
});
|
|
17497
|
-
|
|
17498
|
-
|
|
17736
|
+
const { userInfo } = this.config.getConfig();
|
|
17737
|
+
if (userInfo.phoneType === PhoneTypeEnum.SIP) {
|
|
17738
|
+
if (this.connect.isCalling()) {
|
|
17739
|
+
await this.hangup();
|
|
17740
|
+
}
|
|
17741
|
+
await this.connect.reset({ force });
|
|
17499
17742
|
}
|
|
17500
|
-
await this.connect.reset({ force });
|
|
17501
17743
|
if (this.config.isLogin()) {
|
|
17502
17744
|
await this.logout({ isReset: false });
|
|
17503
17745
|
} else {
|
|
@@ -17559,4 +17801,3 @@ var CallKit = class {
|
|
|
17559
17801
|
0 && (module.exports = {
|
|
17560
17802
|
CallKit
|
|
17561
17803
|
});
|
|
17562
|
-
//# sourceMappingURL=index.js.map
|