@koi-design/callkit 2.3.0-beta.9 → 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 +264 -29
- package/dist/index.js +259 -24
- package/dist/index.mjs +259 -24
- 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.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
|
|
48
|
+
data: { ...params, browserVersion: navigator.userAgent }
|
|
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",
|
|
@@ -697,7 +701,7 @@ var Call = class {
|
|
|
697
701
|
// package.json
|
|
698
702
|
var package_default = {
|
|
699
703
|
name: "@koi-design/callkit",
|
|
700
|
-
version: "2.3.0
|
|
704
|
+
version: "2.3.0",
|
|
701
705
|
description: "callkit",
|
|
702
706
|
author: "koi",
|
|
703
707
|
license: "ISC",
|
|
@@ -15797,8 +15801,6 @@ var Connect = class {
|
|
|
15797
15801
|
});
|
|
15798
15802
|
return;
|
|
15799
15803
|
}
|
|
15800
|
-
const { userInfo } = this.callKit.config.getConfig();
|
|
15801
|
-
const { userPart, fsIp, fsPort } = userInfo;
|
|
15802
15804
|
const { registererOptions = {} } = this.reconnectConfig;
|
|
15803
15805
|
this.registerer = new Registerer(this.userAgent, registererOptions);
|
|
15804
15806
|
this.registerer.stateChange.addListener((state) => {
|
|
@@ -15832,27 +15834,26 @@ var Connect = class {
|
|
|
15832
15834
|
});
|
|
15833
15835
|
this.setRegister(true);
|
|
15834
15836
|
if (this.isReConnected) {
|
|
15835
|
-
if (this.
|
|
15836
|
-
const selfUri = `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
|
|
15837
|
+
if (this.canReferInCallToSelf()) {
|
|
15837
15838
|
this.callKit.logger.info(
|
|
15838
15839
|
"Reconnected, referring active session to self",
|
|
15839
15840
|
{
|
|
15840
15841
|
caller: "Connect.setupRegisterer.registererStateChange",
|
|
15841
15842
|
type: "SIP",
|
|
15842
15843
|
content: {
|
|
15843
|
-
selfUri,
|
|
15844
|
+
selfUri: this.getSelfReferUri(),
|
|
15844
15845
|
sessionState: this.currentSession.state,
|
|
15845
15846
|
connectStatus: this.connectStatus
|
|
15846
15847
|
}
|
|
15847
15848
|
}
|
|
15848
15849
|
);
|
|
15849
|
-
this.
|
|
15850
|
+
this.referInCallToSelf().catch((err) => {
|
|
15850
15851
|
this.callKit.logger.error(err, {
|
|
15851
15852
|
caller: "Connect.setupRegisterer.registererStateChange",
|
|
15852
15853
|
type: "SIP",
|
|
15853
15854
|
content: {
|
|
15854
15855
|
errCode: ErrorCode.WEBRTC_CALL_INVITE_ERROR,
|
|
15855
|
-
selfUri
|
|
15856
|
+
selfUri: this.getSelfReferUri()
|
|
15856
15857
|
}
|
|
15857
15858
|
});
|
|
15858
15859
|
});
|
|
@@ -16681,6 +16682,199 @@ var Connect = class {
|
|
|
16681
16682
|
}
|
|
16682
16683
|
this.currentSession.refer(target, extra?.sessionReferOptions);
|
|
16683
16684
|
}
|
|
16685
|
+
/**
|
|
16686
|
+
* Get the SIP URI for "refer to self" (same as reconnection refer logic).
|
|
16687
|
+
* Shared by referInCallToSelf and internal reconnection refer.
|
|
16688
|
+
*/
|
|
16689
|
+
getSelfReferUri() {
|
|
16690
|
+
const { userInfo } = this.callKit.config.getConfig();
|
|
16691
|
+
const { userPart, fsIp, fsPort } = userInfo;
|
|
16692
|
+
return `sip:manualCallAgent${userPart}@${fsIp}:${fsPort}`;
|
|
16693
|
+
}
|
|
16694
|
+
/**
|
|
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.
|
|
16697
|
+
*/
|
|
16698
|
+
canReferInCallToSelf() {
|
|
16699
|
+
return !!this.currentSession && (this.currentSession.state === SessionState2.Established || this.currentSession.state === SessionState2.Establishing) && this.isCalling();
|
|
16700
|
+
}
|
|
16701
|
+
/**
|
|
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.
|
|
16704
|
+
*/
|
|
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
|
+
}
|
|
16716
|
+
}
|
|
16717
|
+
);
|
|
16718
|
+
return;
|
|
16719
|
+
}
|
|
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;
|
|
16734
|
+
}
|
|
16735
|
+
const selfUri = this.getSelfReferUri();
|
|
16736
|
+
return this.referInCall(selfUri, extra);
|
|
16737
|
+
}
|
|
16738
|
+
};
|
|
16739
|
+
|
|
16740
|
+
// core/heartbeat-worker.ts
|
|
16741
|
+
var workerCode = `
|
|
16742
|
+
let timer = null;
|
|
16743
|
+
let interval = 30000;
|
|
16744
|
+
|
|
16745
|
+
self.onmessage = function(e) {
|
|
16746
|
+
const { type, interval: newInterval } = e.data;
|
|
16747
|
+
|
|
16748
|
+
if (type === 'start') {
|
|
16749
|
+
if (timer) {
|
|
16750
|
+
clearInterval(timer);
|
|
16751
|
+
}
|
|
16752
|
+
interval = newInterval || interval;
|
|
16753
|
+
timer = setInterval(() => {
|
|
16754
|
+
self.postMessage({ type: 'tick' });
|
|
16755
|
+
}, interval);
|
|
16756
|
+
}
|
|
16757
|
+
|
|
16758
|
+
if (type === 'stop') {
|
|
16759
|
+
if (timer) {
|
|
16760
|
+
clearInterval(timer);
|
|
16761
|
+
timer = null;
|
|
16762
|
+
}
|
|
16763
|
+
}
|
|
16764
|
+
|
|
16765
|
+
if (type === 'updateInterval') {
|
|
16766
|
+
interval = newInterval;
|
|
16767
|
+
if (timer) {
|
|
16768
|
+
clearInterval(timer);
|
|
16769
|
+
timer = setInterval(() => {
|
|
16770
|
+
self.postMessage({ type: 'tick' });
|
|
16771
|
+
}, interval);
|
|
16772
|
+
}
|
|
16773
|
+
}
|
|
16774
|
+
};
|
|
16775
|
+
`;
|
|
16776
|
+
function createHeartbeatWorker() {
|
|
16777
|
+
try {
|
|
16778
|
+
const blob = new Blob([workerCode], { type: "application/javascript" });
|
|
16779
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
16780
|
+
const worker = new Worker(workerUrl);
|
|
16781
|
+
URL.revokeObjectURL(workerUrl);
|
|
16782
|
+
return worker;
|
|
16783
|
+
} catch {
|
|
16784
|
+
return null;
|
|
16785
|
+
}
|
|
16786
|
+
}
|
|
16787
|
+
var HeartbeatManager = class {
|
|
16788
|
+
worker = null;
|
|
16789
|
+
fallbackTimer = null;
|
|
16790
|
+
interval = 3e4;
|
|
16791
|
+
onTick = null;
|
|
16792
|
+
isRunning = false;
|
|
16793
|
+
constructor() {
|
|
16794
|
+
this.worker = createHeartbeatWorker();
|
|
16795
|
+
if (this.worker) {
|
|
16796
|
+
this.worker.onmessage = (e) => {
|
|
16797
|
+
if (e.data.type === "tick" && this.onTick) {
|
|
16798
|
+
this.onTick();
|
|
16799
|
+
}
|
|
16800
|
+
};
|
|
16801
|
+
}
|
|
16802
|
+
}
|
|
16803
|
+
/**
|
|
16804
|
+
* Start the heartbeat
|
|
16805
|
+
* @param interval - Interval in milliseconds
|
|
16806
|
+
* @param onTick - Callback function to execute on each tick
|
|
16807
|
+
*/
|
|
16808
|
+
start(interval, onTick) {
|
|
16809
|
+
this.stop();
|
|
16810
|
+
this.interval = interval;
|
|
16811
|
+
this.onTick = onTick;
|
|
16812
|
+
this.isRunning = true;
|
|
16813
|
+
if (this.worker) {
|
|
16814
|
+
this.worker.postMessage({
|
|
16815
|
+
type: "start",
|
|
16816
|
+
interval
|
|
16817
|
+
});
|
|
16818
|
+
} else {
|
|
16819
|
+
this.fallbackTimer = setInterval(() => {
|
|
16820
|
+
if (this.onTick) {
|
|
16821
|
+
this.onTick();
|
|
16822
|
+
}
|
|
16823
|
+
}, interval);
|
|
16824
|
+
}
|
|
16825
|
+
}
|
|
16826
|
+
/**
|
|
16827
|
+
* Stop the heartbeat
|
|
16828
|
+
*/
|
|
16829
|
+
stop() {
|
|
16830
|
+
this.isRunning = false;
|
|
16831
|
+
this.onTick = null;
|
|
16832
|
+
if (this.worker) {
|
|
16833
|
+
this.worker.postMessage({ type: "stop" });
|
|
16834
|
+
}
|
|
16835
|
+
if (this.fallbackTimer) {
|
|
16836
|
+
clearInterval(this.fallbackTimer);
|
|
16837
|
+
this.fallbackTimer = null;
|
|
16838
|
+
}
|
|
16839
|
+
}
|
|
16840
|
+
/**
|
|
16841
|
+
* Update the heartbeat interval
|
|
16842
|
+
* @param interval - New interval in milliseconds
|
|
16843
|
+
*/
|
|
16844
|
+
updateInterval(interval) {
|
|
16845
|
+
this.interval = interval;
|
|
16846
|
+
if (!this.isRunning)
|
|
16847
|
+
return;
|
|
16848
|
+
if (this.worker) {
|
|
16849
|
+
this.worker.postMessage({
|
|
16850
|
+
type: "updateInterval",
|
|
16851
|
+
interval
|
|
16852
|
+
});
|
|
16853
|
+
} else if (this.fallbackTimer && this.onTick) {
|
|
16854
|
+
clearInterval(this.fallbackTimer);
|
|
16855
|
+
this.fallbackTimer = setInterval(() => {
|
|
16856
|
+
if (this.onTick) {
|
|
16857
|
+
this.onTick();
|
|
16858
|
+
}
|
|
16859
|
+
}, interval);
|
|
16860
|
+
}
|
|
16861
|
+
}
|
|
16862
|
+
/**
|
|
16863
|
+
* Destroy the heartbeat manager and release resources
|
|
16864
|
+
*/
|
|
16865
|
+
destroy() {
|
|
16866
|
+
this.stop();
|
|
16867
|
+
if (this.worker) {
|
|
16868
|
+
this.worker.terminate();
|
|
16869
|
+
this.worker = null;
|
|
16870
|
+
}
|
|
16871
|
+
}
|
|
16872
|
+
/**
|
|
16873
|
+
* Check if using Web Worker
|
|
16874
|
+
*/
|
|
16875
|
+
isUsingWorker() {
|
|
16876
|
+
return this.worker !== null;
|
|
16877
|
+
}
|
|
16684
16878
|
};
|
|
16685
16879
|
|
|
16686
16880
|
// core/socket.ts
|
|
@@ -16688,7 +16882,7 @@ var Socket = class {
|
|
|
16688
16882
|
callKit;
|
|
16689
16883
|
ws;
|
|
16690
16884
|
lastPingTime = void 0;
|
|
16691
|
-
|
|
16885
|
+
heartbeatManager;
|
|
16692
16886
|
/**
|
|
16693
16887
|
* @description reconnect timer
|
|
16694
16888
|
*/
|
|
@@ -16721,10 +16915,18 @@ var Socket = class {
|
|
|
16721
16915
|
}
|
|
16722
16916
|
constructor(callKit) {
|
|
16723
16917
|
this.callKit = callKit;
|
|
16918
|
+
this.heartbeatManager = new HeartbeatManager();
|
|
16724
16919
|
}
|
|
16725
16920
|
get reconnectConfig() {
|
|
16726
16921
|
return this.callKit.config.getReconnectConfig("incall");
|
|
16727
16922
|
}
|
|
16923
|
+
get pingInterval() {
|
|
16924
|
+
const { keepaliveInterval } = this.callKit.config.getConfig().userInfo;
|
|
16925
|
+
if (Number.isInteger(keepaliveInterval) && keepaliveInterval > 0) {
|
|
16926
|
+
return keepaliveInterval * 1e3;
|
|
16927
|
+
}
|
|
16928
|
+
return this.reconnectConfig.pingInterval;
|
|
16929
|
+
}
|
|
16728
16930
|
isConnected() {
|
|
16729
16931
|
return this.connectAuthState.isConnected;
|
|
16730
16932
|
}
|
|
@@ -16906,6 +17108,28 @@ var Socket = class {
|
|
|
16906
17108
|
this.setConnectAuthState("startConfirm", true);
|
|
16907
17109
|
this.cleanReconnectState();
|
|
16908
17110
|
}
|
|
17111
|
+
if (data.event === SocketReceiveEvent.AGENT_RTP_LOSS) {
|
|
17112
|
+
this.callKit.logger.warn("Agent RTP loss", {
|
|
17113
|
+
caller: "Socket.onMessage",
|
|
17114
|
+
type: "INCALL",
|
|
17115
|
+
content: {
|
|
17116
|
+
data: {
|
|
17117
|
+
callUuid,
|
|
17118
|
+
...content
|
|
17119
|
+
},
|
|
17120
|
+
event: SocketReceiveEvent.AGENT_RTP_LOSS
|
|
17121
|
+
}
|
|
17122
|
+
});
|
|
17123
|
+
if (callUuid) {
|
|
17124
|
+
this.callKit.connect.referInCallToSelf(callUuid).catch((err) => {
|
|
17125
|
+
this.callKit.logger.error(err, {
|
|
17126
|
+
caller: "Socket.onMessage:AGENT_RTP_LOSS",
|
|
17127
|
+
type: "INCALL",
|
|
17128
|
+
content: { callUuid, event: SocketReceiveEvent.AGENT_RTP_LOSS }
|
|
17129
|
+
});
|
|
17130
|
+
});
|
|
17131
|
+
}
|
|
17132
|
+
}
|
|
16909
17133
|
if (data.event === SocketReceiveEvent.CUSTOMER_RINGING) {
|
|
16910
17134
|
this.callKit.trigger(KitEvent.CALL_RINGING, {
|
|
16911
17135
|
time: /* @__PURE__ */ new Date(),
|
|
@@ -17059,8 +17283,8 @@ var Socket = class {
|
|
|
17059
17283
|
return;
|
|
17060
17284
|
this.send(SocketSendEvent.PING);
|
|
17061
17285
|
const now = Date.now();
|
|
17062
|
-
const {
|
|
17063
|
-
if (now - this.lastPingTime > pingInterval + pingTimeout) {
|
|
17286
|
+
const { pingTimeout } = this.reconnectConfig;
|
|
17287
|
+
if (now - this.lastPingTime > this.pingInterval + pingTimeout) {
|
|
17064
17288
|
this.callKit.logger.warn("Ping timeout not connected", {
|
|
17065
17289
|
caller: "Socket.ping",
|
|
17066
17290
|
type: "INCALL",
|
|
@@ -17075,23 +17299,27 @@ var Socket = class {
|
|
|
17075
17299
|
}
|
|
17076
17300
|
}
|
|
17077
17301
|
checkPing() {
|
|
17078
|
-
|
|
17079
|
-
clearInterval(this.pingTimer);
|
|
17080
|
-
}
|
|
17081
|
-
const { pingInterval } = this.reconnectConfig;
|
|
17082
|
-
this.pingTimer = setInterval(() => {
|
|
17302
|
+
this.heartbeatManager.start(this.pingInterval, () => {
|
|
17083
17303
|
this.ping();
|
|
17084
|
-
}
|
|
17304
|
+
});
|
|
17305
|
+
this.callKit.logger.info(
|
|
17306
|
+
`Heartbeat started with Worker: ${this.heartbeatManager.isUsingWorker()}`,
|
|
17307
|
+
{
|
|
17308
|
+
caller: "Socket.checkPing",
|
|
17309
|
+
type: "INCALL",
|
|
17310
|
+
content: {
|
|
17311
|
+
pingInterval: this.pingInterval,
|
|
17312
|
+
usingWorker: this.heartbeatManager.isUsingWorker()
|
|
17313
|
+
}
|
|
17314
|
+
}
|
|
17315
|
+
);
|
|
17085
17316
|
}
|
|
17086
17317
|
/**
|
|
17087
17318
|
* reset socket connection and all states
|
|
17088
17319
|
*/
|
|
17089
17320
|
async reset(config) {
|
|
17090
17321
|
const { force = false } = config || {};
|
|
17091
|
-
|
|
17092
|
-
clearInterval(this.pingTimer);
|
|
17093
|
-
this.pingTimer = void 0;
|
|
17094
|
-
}
|
|
17322
|
+
this.heartbeatManager.stop();
|
|
17095
17323
|
if (force) {
|
|
17096
17324
|
this.callKit.trigger(KitEvent.INCALL_CONNECT_EVENT, {
|
|
17097
17325
|
event: "INCALL_RESET"
|
|
@@ -17102,6 +17330,12 @@ var Socket = class {
|
|
|
17102
17330
|
this.setConnectAuthState("startConfirm", false);
|
|
17103
17331
|
this.clearWebSocket();
|
|
17104
17332
|
}
|
|
17333
|
+
/**
|
|
17334
|
+
* Destroy the heartbeat manager
|
|
17335
|
+
*/
|
|
17336
|
+
destroyHeartbeat() {
|
|
17337
|
+
this.heartbeatManager.destroy();
|
|
17338
|
+
}
|
|
17105
17339
|
attemptReconnect() {
|
|
17106
17340
|
if (this.reconnectTimer) {
|
|
17107
17341
|
clearTimeout(this.reconnectTimer);
|
|
@@ -17227,6 +17461,7 @@ var CallKit = class {
|
|
|
17227
17461
|
content: {
|
|
17228
17462
|
username,
|
|
17229
17463
|
password,
|
|
17464
|
+
ua: navigator.userAgent,
|
|
17230
17465
|
encryptionMethod,
|
|
17231
17466
|
encryptionPassword
|
|
17232
17467
|
}
|
|
@@ -17260,6 +17495,7 @@ var CallKit = class {
|
|
|
17260
17495
|
iceInfo: user.iceInfo,
|
|
17261
17496
|
iceGatheringTimeout: user.iceGatheringTimeout,
|
|
17262
17497
|
logGather: user.logGather,
|
|
17498
|
+
keepaliveInterval: user.keepaliveInterval,
|
|
17263
17499
|
phoneType: user.phoneType,
|
|
17264
17500
|
// encryptionType is in extra
|
|
17265
17501
|
...extra
|
|
@@ -17537,4 +17773,3 @@ var CallKit = class {
|
|
|
17537
17773
|
export {
|
|
17538
17774
|
CallKit
|
|
17539
17775
|
};
|
|
17540
|
-
//# sourceMappingURL=index.mjs.map
|