@koi-design/callkit 2.0.0-beta.5 → 2.0.0-beta.7

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 CHANGED
@@ -20,27 +20,124 @@ declare class Api {
20
20
  private post;
21
21
  }
22
22
 
23
- declare class Call {
23
+ type LoggerLevel = 'info' | 'success' | 'warn' | 'error' | 'silent';
24
+ interface Log {
25
+ timestamp: string;
26
+ level: LoggerLevel;
27
+ type?: 'INCALL' | 'SIP' | 'API' | 'OTHER';
28
+ message: string;
29
+ caller: string;
30
+ content: Record<string, any>;
31
+ }
32
+ type LogEntity = Omit<Log, 'timestamp' | 'level' | 'message'>;
33
+ declare class Logger {
34
+ prefix: string;
35
+ level: LoggerLevel;
36
+ private pendingTrackLogs;
37
+ private trackLogsTimer;
24
38
  private callKit;
39
+ constructor(callKit: CallKit, level?: LoggerLevel);
40
+ private startTrackLogsTimer;
41
+ private flushTrackLogs;
42
+ destroy(): void;
43
+ setLevel(level: LoggerLevel): void;
44
+ info(msg: string, extra: LogEntity): void;
45
+ success(msg: string, extra: LogEntity): void;
46
+ warn(msg: string, extra: LogEntity): void;
47
+ error(msg: string | Error, extra: LogEntity): void;
48
+ private catchLog;
49
+ }
50
+
51
+ type SocketSendEventType = (typeof SocketSendEvent)[keyof typeof SocketSendEvent];
52
+ interface SocketConfig {
53
+ enabled: boolean;
54
+ maxAttempts: number;
55
+ delay: number;
56
+ backoffMultiplier: number;
57
+ pingInterval: number;
58
+ pingTimeout: number;
59
+ }
60
+ declare class Socket {
61
+ private callKit;
62
+ private ws?;
63
+ private socketConfig;
64
+ lastPingTime: any;
65
+ isConnected: boolean;
66
+ pingTimer?: number;
67
+ satrtConfirm: boolean;
68
+ private reconnectTimer?;
69
+ private isReconnecting;
70
+ private reconnectAttempts;
71
+ private socketError;
25
72
  constructor(callKit: CallKit);
26
- callStart(): Promise<void>;
27
- /**
28
- * Refer
29
- * @param referTo - The referral target. If a `Session`, a REFER w/Replaces is sent.
30
- * @returns
31
- */
32
- callRefer(referTo: string, options?: any): Promise<void>;
73
+ init(): void;
74
+ private handleDisconnect;
75
+ private connect;
76
+ private onOpen;
77
+ private resetReconnectState;
78
+ private onClose;
79
+ private onError;
80
+ private confirmAck;
81
+ private onMessage;
82
+ send(event: SocketSendEventType, message?: any): void;
83
+ sendMessage(event: SocketSendEventType, message?: any): Promise<void>;
84
+ private ping;
85
+ private checkPing;
33
86
  /**
34
- * Hang up
35
- * @param isUnprompted Whether to actively hang up
36
- * @param isError Whether an error occurred
37
- * @returns
87
+ * reset socket connection and all states
38
88
  */
39
- callEnd(isUnprompted?: boolean, isError?: boolean): Promise<void>;
40
- callHold(): Promise<void>;
41
- callUnhold(): Promise<void>;
42
- callMute(): Promise<void>;
43
- callUnmute(): Promise<void>;
89
+ reset(): Promise<void>;
90
+ private attemptReconnect;
91
+ }
92
+
93
+ interface WebrtcConstranis {
94
+ audio: {
95
+ autoGainControl?: boolean;
96
+ noiseSuppression?: boolean;
97
+ echoCancellation?: boolean;
98
+ };
99
+ video: false;
100
+ }
101
+ interface IConfig {
102
+ version: string;
103
+ host: string;
104
+ log: LoggerLevel;
105
+ trackLogs: boolean;
106
+ audioRef?: HTMLAudioElement | (() => HTMLAudioElement);
107
+ constrains: WebrtcConstranis;
108
+ socket: string;
109
+ reconnect?: SocketConfig;
110
+ userInfo: {
111
+ wsUrl: string;
112
+ sessionId: string;
113
+ username: string;
114
+ password: string;
115
+ encryptionPassword: string;
116
+ sourceType: (typeof CallSourceType)[keyof typeof CallSourceType];
117
+ extno: string;
118
+ workOrderId: string;
119
+ userPart: string;
120
+ agentId: string;
121
+ fsUserId: string;
122
+ fsPassword: string;
123
+ fsIp: string;
124
+ fsPort: string;
125
+ iceInfo: string[];
126
+ iceGatheringTimeout: number;
127
+ encryptionMethod: EncryptionMethodType;
128
+ };
129
+ }
130
+ declare class Config {
131
+ callKit: CallKit;
132
+ constructor(callKit: CallKit);
133
+ config: IConfig;
134
+ getConfig: () => IConfig;
135
+ setConfig: (key: string, value: any) => Promise<void>;
136
+ setUserInfo: (key: string, value: any) => Promise<void>;
137
+ reset: () => Promise<void>;
138
+ validate: () => boolean;
139
+ isLogin: () => boolean;
140
+ check(): boolean;
44
141
  }
45
142
 
46
143
  declare const CallStatus: {
@@ -208,124 +305,34 @@ declare const CallSourceType: {
208
305
  workOrderId: number;
209
306
  };
210
307
 
211
- type LoggerLevel = 'info' | 'success' | 'warn' | 'error' | 'silent';
212
- interface Log {
213
- timestamp: string;
214
- level: LoggerLevel;
215
- type?: 'INCALL' | 'SIP' | 'API' | 'OTHER';
216
- message: string;
217
- caller: string;
218
- content: Record<string, any>;
219
- }
220
- type LogEntity = Omit<Log, 'timestamp' | 'level' | 'message'>;
221
- declare class Logger {
222
- prefix: string;
223
- level: LoggerLevel;
224
- private pendingTrackLogs;
225
- private trackLogsTimer;
226
- private callKit;
227
- constructor(callKit: CallKit, level?: LoggerLevel);
228
- private startTrackLogsTimer;
229
- private flushTrackLogs;
230
- destroy(): void;
231
- setLevel(level: LoggerLevel): void;
232
- info(msg: string, extra: LogEntity): void;
233
- success(msg: string, extra: LogEntity): void;
234
- warn(msg: string, extra: LogEntity): void;
235
- error(msg: string | Error, extra: LogEntity): void;
236
- private catchLog;
237
- }
238
-
239
- type SocketSendEventType = (typeof SocketSendEvent)[keyof typeof SocketSendEvent];
240
- interface SocketConfig {
241
- enabled: boolean;
242
- maxAttempts: number;
243
- delay: number;
244
- backoffMultiplier: number;
245
- pingInterval: number;
246
- pingTimeout: number;
308
+ interface CallParams {
309
+ agentId: string;
310
+ sourceType: (typeof CallSourceType)[keyof typeof CallSourceType];
311
+ phoneNum?: string;
312
+ workOrderId?: string;
313
+ extra?: any;
247
314
  }
248
- declare class Socket {
315
+ declare class Call {
249
316
  private callKit;
250
- private ws?;
251
- private socketConfig;
252
- lastPingTime: any;
253
- isConnected: boolean;
254
- pingTimer?: number;
255
- satrtConfirm: boolean;
256
- private reconnectTimer?;
257
- private isReconnecting;
258
- private reconnectAttempts;
259
- private socketError;
260
317
  constructor(callKit: CallKit);
261
- init(): void;
262
- private handleDisconnect;
263
- private connect;
264
- private onOpen;
265
- private resetReconnectState;
266
- private onClose;
267
- private onError;
268
- private confirmAck;
269
- private onMessage;
270
- send(event: SocketSendEventType, message?: any): void;
271
- sendMessage(event: SocketSendEventType, message?: any): Promise<void>;
272
- private ping;
273
- private checkPing;
318
+ callStart(params: Partial<CallParams>): Promise<void>;
274
319
  /**
275
- * reset socket connection and all states
320
+ * Refer
321
+ * @param referTo - The referral target. If a `Session`, a REFER w/Replaces is sent.
322
+ * @returns
276
323
  */
277
- reset(): Promise<void>;
278
- private attemptReconnect;
279
- }
280
-
281
- interface WebrtcConstranis {
282
- audio: {
283
- autoGainControl?: boolean;
284
- noiseSuppression?: boolean;
285
- echoCancellation?: boolean;
286
- };
287
- video: false;
288
- }
289
- interface IConfig {
290
- version: string;
291
- host: string;
292
- log: LoggerLevel;
293
- trackLogs: boolean;
294
- audioRef?: HTMLAudioElement | (() => HTMLAudioElement);
295
- constrains: WebrtcConstranis;
296
- socket: string;
297
- reconnect?: SocketConfig;
298
- userInfo: {
299
- wsUrl: string;
300
- sessionId: string;
301
- username: string;
302
- password: string;
303
- encryptionPassword: string;
304
- sourceType: (typeof CallSourceType)[keyof typeof CallSourceType];
305
- extno: string;
306
- workOrderId: string;
307
- userPart: string;
308
- agentId: string;
309
- fsUserId: string;
310
- fsPassword: string;
311
- fsIp: string;
312
- fsPort: string;
313
- iceInfo: string[];
314
- iceGatheringTimeout: number;
315
- encryptionMethod: EncryptionMethodType;
316
- };
317
- }
318
- declare class Config {
319
- callKit: CallKit;
320
- constructor(callKit: CallKit);
321
- config: IConfig;
322
- getConfig: () => IConfig;
323
- setConfig: (key: string, value: any) => Promise<void>;
324
- setUserInfo: (key: string, value: any) => Promise<void>;
325
- reset: () => void;
326
- validate: () => boolean;
327
- isLogin: () => boolean;
328
- check(): boolean;
324
+ callRefer(referTo: string, options?: any): Promise<void>;
325
+ /**
326
+ * Hang up
327
+ * @param isUnprompted Whether to actively hang up
328
+ * @param isError Whether an error occurred
329
+ * @returns
330
+ */
331
+ callEnd(isUnprompted?: boolean, isError?: boolean): Promise<void>;
332
+ callHold(): Promise<void>;
333
+ callUnhold(): Promise<void>;
334
+ callMute(): Promise<void>;
335
+ callUnmute(): Promise<void>;
329
336
  }
330
337
 
331
338
  type CallStatusType = (typeof CallStatus)[keyof typeof CallStatus];
@@ -368,7 +375,7 @@ declare class Connect {
368
375
  */
369
376
  private isHold;
370
377
  constructor(callKit: CallKit);
371
- reset(): void;
378
+ reset(): Promise<void>;
372
379
  private getAduioReference;
373
380
  permission(): Promise<void>;
374
381
  /**
@@ -405,6 +412,7 @@ declare class Connect {
405
412
  clearObserveOptionsHeartbeatInterval(): void;
406
413
  heartbeatFlag: number;
407
414
  startHeartbeat(): void;
415
+ socketTriggerHangup(callId: string): void;
408
416
  register(): Promise<void>;
409
417
  private reconnectTimer?;
410
418
  private reconnectAttempts;
@@ -453,11 +461,6 @@ interface Listener {
453
461
  event: kitEventType;
454
462
  callback: (...args: any[]) => void;
455
463
  }
456
- interface CallOptions {
457
- sourceType: (typeof CallSourceType)[keyof typeof CallSourceType];
458
- phoneNum?: string;
459
- workOrderId?: string;
460
- }
461
464
  declare class CallKit {
462
465
  api: Api;
463
466
  config: Config;
@@ -470,8 +473,10 @@ declare class CallKit {
470
473
  login(username: string, password: string, extra?: {
471
474
  [key: string]: any;
472
475
  }): Promise<void>;
473
- logout(): Promise<void>;
474
- call(extno?: string | number, options?: CallOptions): Promise<void>;
476
+ logout({ isReset }?: {
477
+ isReset?: boolean;
478
+ }): Promise<void>;
479
+ call(extno?: string | number, options?: Partial<CallParams>): Promise<void>;
475
480
  refer(uri: string, options?: any): Promise<void>;
476
481
  register(): Promise<void>;
477
482
  unregister(): Promise<void>;
@@ -3640,7 +3640,7 @@ var WebCall = (() => {
3640
3640
  constructor(callKit) {
3641
3641
  this.callKit = callKit;
3642
3642
  }
3643
- async callStart() {
3643
+ async callStart(params) {
3644
3644
  if (!this.callKit.config.check())
3645
3645
  return;
3646
3646
  this.callKit.logger.info("callStart", {
@@ -3659,19 +3659,15 @@ var WebCall = (() => {
3659
3659
  return;
3660
3660
  }
3661
3661
  this.callKit.connect.call(async (user) => {
3662
- let queryTrain = {};
3662
+ const queryTrain = {
3663
+ ...params?.extra || {},
3664
+ agentId: user.agentId,
3665
+ sourceType: user.sourceType
3666
+ };
3663
3667
  if (user.sourceType === CallSourceType.phoneNum) {
3664
- queryTrain = {
3665
- agentId: user.agentId,
3666
- phoneNum: user.extno,
3667
- sourceType: user.sourceType
3668
- };
3668
+ queryTrain.phoneNum = user.extno;
3669
3669
  } else if (user.sourceType === CallSourceType.workOrderId) {
3670
- queryTrain = {
3671
- agentId: user.agentId,
3672
- workOrderId: user.workOrderId,
3673
- sourceType: user.sourceType
3674
- };
3670
+ queryTrain.workOrderId = user.workOrderId;
3675
3671
  }
3676
3672
  this.callKit.socket.send(SocketSendEvent.CALL, queryTrain);
3677
3673
  });
@@ -3819,7 +3815,7 @@ var WebCall = (() => {
3819
3815
  }
3820
3816
  });
3821
3817
  };
3822
- reset = () => {
3818
+ reset = async () => {
3823
3819
  if (this.isLogin()) {
3824
3820
  this.config.userInfo = {
3825
3821
  wsUrl: "",
@@ -18402,6 +18398,21 @@ var WebCall = (() => {
18402
18398
  }
18403
18399
  };
18404
18400
 
18401
+ // package/utils.ts
18402
+ var formatGetInviteData = (inviteData) => {
18403
+ const extendInfoStr = inviteData["x-antaios-manual-extend_info"] || inviteData["x-antaios-manual-extend-info"];
18404
+ let extendInfoObj = null;
18405
+ try {
18406
+ if (extendInfoStr && typeof extendInfoStr === "string") {
18407
+ const cleanedStr = extendInfoStr.replace(/\\/g, "");
18408
+ extendInfoObj = JSON.parse(cleanedStr);
18409
+ return extendInfoObj;
18410
+ }
18411
+ } catch (error) {
18412
+ return {};
18413
+ }
18414
+ };
18415
+
18405
18416
  // package/connect.ts
18406
18417
  var DEFAULT_RECONNECT_CONFIG = {
18407
18418
  maxAttempts: 3,
@@ -18484,7 +18495,7 @@ var WebCall = (() => {
18484
18495
  ...reconnect
18485
18496
  };
18486
18497
  }
18487
- reset() {
18498
+ async reset() {
18488
18499
  if (this.isHolding()) {
18489
18500
  this.setHold(false);
18490
18501
  }
@@ -18500,6 +18511,7 @@ var WebCall = (() => {
18500
18511
  this.registerer = void 0;
18501
18512
  this.isOutgoing = false;
18502
18513
  this.isUnprompted = false;
18514
+ this.currentCallId = void 0;
18503
18515
  if (this.mediaStream) {
18504
18516
  try {
18505
18517
  closeStream(this.mediaStream);
@@ -18515,7 +18527,6 @@ var WebCall = (() => {
18515
18527
  });
18516
18528
  }
18517
18529
  }
18518
- this.callKit.config.reset();
18519
18530
  this.setConnectStatus(CallStatus.init);
18520
18531
  this.clearObserveOptionsHeartbeatInterval();
18521
18532
  }
@@ -18601,6 +18612,18 @@ var WebCall = (() => {
18601
18612
  }
18602
18613
  }, 1e3);
18603
18614
  }
18615
+ socketTriggerHangup(callId) {
18616
+ if (!this.isCalling() || callId !== this.currentCallId)
18617
+ return;
18618
+ this.callKit.logger.info("socketHangup trigger hangup", {
18619
+ caller: "Connect.socketHangup",
18620
+ content: {
18621
+ callId,
18622
+ currentCallId: this.currentCallId
18623
+ }
18624
+ });
18625
+ this.callKit.hangup();
18626
+ }
18604
18627
  async register() {
18605
18628
  if (this.connectStatus !== CallStatus.init) {
18606
18629
  if (this.isRegistered()) {
@@ -18882,24 +18905,40 @@ var WebCall = (() => {
18882
18905
  alwaysAcquireMediaFirst: true
18883
18906
  }
18884
18907
  };
18908
+ const getInviteData = () => {
18909
+ const { request: request2 } = this.currentSession;
18910
+ const headerNames = Object.keys(request2.headers);
18911
+ const xHeaders = {};
18912
+ headerNames.filter((name) => name.toLocaleLowerCase().startsWith("x-antaios")).forEach((name) => {
18913
+ xHeaders[name.toLocaleLowerCase()] = request2.getHeader(name);
18914
+ });
18915
+ this.callKit.logger.info("get invite data", {
18916
+ caller: "Connect.register.onInvite",
18917
+ content: xHeaders
18918
+ });
18919
+ return xHeaders;
18920
+ };
18921
+ const info = getInviteData();
18922
+ try {
18923
+ const inviteData = formatGetInviteData(info);
18924
+ this.currentCallId = inviteData?.callUuid;
18925
+ this.callKit.logger.info("get invite data", {
18926
+ caller: "Connect.register.onInvite",
18927
+ content: {
18928
+ inviteData,
18929
+ currentCallId: this.currentCallId
18930
+ }
18931
+ });
18932
+ } catch (error) {
18933
+ this.callKit.logger.info(error, {
18934
+ caller: "Connect.register.onInvite",
18935
+ content: info
18936
+ });
18937
+ }
18885
18938
  if (this.isOutgoing) {
18886
18939
  this.currentSession.accept(options);
18887
18940
  this.callKit.trigger(KitEvent.KIT_OUTGOING_INVITE, {
18888
- getInviteData: () => {
18889
- const { request: request2 } = this.currentSession;
18890
- const headerNames = Object.keys(request2.headers);
18891
- const xHeaders = {};
18892
- headerNames.filter(
18893
- (name) => name.toLocaleLowerCase().startsWith("x-antaios")
18894
- ).forEach((name) => {
18895
- xHeaders[name.toLocaleLowerCase()] = request2.getHeader(name);
18896
- });
18897
- this.callKit.logger.info("get invite data", {
18898
- caller: "Connect.register.onInvite",
18899
- content: xHeaders
18900
- });
18901
- return xHeaders;
18902
- }
18941
+ getInviteData
18903
18942
  });
18904
18943
  } else {
18905
18944
  const reject = () => {
@@ -18913,21 +18952,7 @@ var WebCall = (() => {
18913
18952
  this.currentSession.accept(options);
18914
18953
  },
18915
18954
  reject,
18916
- getInviteData: () => {
18917
- const { request: request2 } = this.currentSession;
18918
- const headerNames = Object.keys(request2.headers);
18919
- const xHeaders = {};
18920
- headerNames.filter(
18921
- (name) => name.toLocaleLowerCase().startsWith("x-antaios")
18922
- ).forEach((name) => {
18923
- xHeaders[name.toLocaleLowerCase()] = request2.getHeader(name);
18924
- });
18925
- this.callKit.logger.info("get invite data", {
18926
- caller: "Connect.register",
18927
- content: xHeaders
18928
- });
18929
- return xHeaders;
18930
- }
18955
+ getInviteData
18931
18956
  });
18932
18957
  }
18933
18958
  },
@@ -19568,6 +19593,9 @@ var WebCall = (() => {
19568
19593
  }
19569
19594
  });
19570
19595
  this.callKit.trigger(KitEvent.CALL_HANG_UP, /* @__PURE__ */ new Date());
19596
+ if (data.data?.callUuid) {
19597
+ this.callKit.connect.socketTriggerHangup(data.data.callUuid);
19598
+ }
19571
19599
  }
19572
19600
  if (data.event === SocketReceiveEvent.CUSTOMER_NO_ANSWER) {
19573
19601
  this.callKit.logger.info(data.msg, {
@@ -19579,6 +19607,9 @@ var WebCall = (() => {
19579
19607
  }
19580
19608
  });
19581
19609
  this.callKit.trigger(KitEvent.CALL_NO_ANSWER);
19610
+ if (data.data?.callUuid) {
19611
+ this.callKit.connect.socketTriggerHangup(data.data.callUuid);
19612
+ }
19582
19613
  }
19583
19614
  if (data.event === SocketReceiveEvent.CALL_CDR) {
19584
19615
  this.callKit.logger.info(data.msg, {
@@ -19620,6 +19651,7 @@ var WebCall = (() => {
19620
19651
  data: data.data
19621
19652
  }
19622
19653
  });
19654
+ this.socketError = true;
19623
19655
  this.callKit.reset();
19624
19656
  }
19625
19657
  if (data.event === SocketReceiveEvent.AGENT_NO_ANSWER) {
@@ -19630,6 +19662,9 @@ var WebCall = (() => {
19630
19662
  event: SocketReceiveEvent.AGENT_NO_ANSWER
19631
19663
  }
19632
19664
  });
19665
+ if (data.data?.callUuid) {
19666
+ this.callKit.connect.socketTriggerHangup(data.data.callUuid);
19667
+ }
19633
19668
  }
19634
19669
  this.callKit.trigger(KitEvent.SERVER_SOCKET_EVENT, data);
19635
19670
  }
@@ -19911,7 +19946,7 @@ var WebCall = (() => {
19911
19946
  });
19912
19947
  }
19913
19948
  }
19914
- async logout() {
19949
+ async logout({ isReset = true } = { isReset: true }) {
19915
19950
  if (!this.config.check())
19916
19951
  return;
19917
19952
  const { userInfo } = this.config.getConfig();
@@ -19934,10 +19969,9 @@ var WebCall = (() => {
19934
19969
  });
19935
19970
  }
19936
19971
  }
19937
- await this.hangup();
19938
- this.connect.reset();
19939
- this.socket.reset();
19940
- this.config.reset();
19972
+ if (isReset) {
19973
+ await this.reset();
19974
+ }
19941
19975
  this.trigger(KitEvent.KIT_LOGIN_CHANGE, false);
19942
19976
  }
19943
19977
  async call(extno = "", options = {
@@ -19971,7 +20005,7 @@ var WebCall = (() => {
19971
20005
  options
19972
20006
  }
19973
20007
  });
19974
- this.callCenter.callStart();
20008
+ this.callCenter.callStart(options);
19975
20009
  }
19976
20010
  async refer(uri, options) {
19977
20011
  if (!this.config.check())
@@ -20088,7 +20122,15 @@ var WebCall = (() => {
20088
20122
  connectStatus: this.connect.connectStatus
20089
20123
  }
20090
20124
  });
20091
- this.connect.reset();
20125
+ if (this.connect.isCalling()) {
20126
+ await this.hangup();
20127
+ }
20128
+ await this.connect.reset();
20129
+ if (this.config.isLogin()) {
20130
+ await this.logout({ isReset: false });
20131
+ }
20132
+ await this.config.reset();
20133
+ await this.socket.reset();
20092
20134
  }
20093
20135
  on(event, callback) {
20094
20136
  this.listener.push({