@koi-design/callkit 2.0.5-beta.2 → 2.0.5-beta.3

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/README.md CHANGED
@@ -1,18 +1,20 @@
1
- # CallKit-1.0.21
1
+ # @koi-design/callkit
2
2
 
3
3
  SIP-based Web Phone Call Toolkit
4
4
 
5
+ Current Version: **2.0.5-beta.2**
6
+
5
7
  ## Installation
6
8
 
7
- ### Method 1: Full Import
9
+ ### NPM Installation
8
10
 
9
- ```html
10
- <script src="callkit/index.global.js"></script>
11
+ ```bash
12
+ pnpm add @koi-design/callkit
11
13
  ```
12
14
 
13
- ### Method 2: ESM/CJS Import
15
+ ### Dependencies
14
16
 
15
- Install the following dependencies:
17
+ This package requires the following peer dependencies:
16
18
 
17
19
  ```json
18
20
  {
@@ -26,30 +28,43 @@ Install the following dependencies:
26
28
 
27
29
  ## Quick Start
28
30
 
29
- ### Full Import Usage
31
+ ### Method 1: IIFE (Browser Global)
30
32
 
31
33
  ```html
32
- <script src="callkit/index.global.js"></script>
34
+ <script src="koi-design/callkit/dist/index.global.js"></script>
33
35
  <script>
34
36
  const callKit = new WebCall.CallKit({
35
37
  host: 'https://example.com',
36
38
  log: 'debug',
37
39
  audioRef: () => document.querySelector('#audioRef'),
38
- socket: 'wss://example.com/ws/in-call',
40
+ socket: 'wss://example.com/ws/in-call'
39
41
  });
40
42
  </script>
41
43
  ```
42
44
 
43
- ### ESM Import Usage
45
+ ### Method 2: ESM Import
44
46
 
45
47
  ```js
46
- import { CallKit } from 'CallKit';
48
+ import { CallKit } from '@koi-design/callkit';
47
49
 
48
50
  const callKit = new CallKit({
49
51
  host: 'https://example.com',
50
52
  log: 'debug',
51
53
  audioRef: () => document.querySelector('#audioRef'),
52
- socket: 'wss://example.com/ws/in-call',
54
+ socket: 'wss://example.com/ws/in-call'
55
+ });
56
+ ```
57
+
58
+ ### Method 3: CommonJS Import
59
+
60
+ ```js
61
+ const { CallKit } = require('@koi-design/callkit');
62
+
63
+ const callKit = new CallKit({
64
+ host: 'https://example.com',
65
+ log: 'debug',
66
+ audioRef: () => document.querySelector('#audioRef'),
67
+ socket: 'wss://example.com/ws/in-call'
53
68
  });
54
69
  ```
55
70
 
@@ -72,10 +87,40 @@ interface CallKitConfig {
72
87
  constrains?: WebrtcConstranis;
73
88
 
74
89
  // Log level
75
- log?: 'debug' | 'log' | 'warn' | 'error' | 'silent';
90
+ log?: 'info' | 'success' | 'warn' | 'error' | 'silent';
91
+
92
+ // Reconnection configuration
93
+ reconnect?: {
94
+ // SIP reconnection configuration
95
+ sip: {
96
+ enabled: boolean; // Enable SIP reconnection (default: true)
97
+ maxAttempts: number; // Maximum reconnection attempts (default: 5)
98
+ delay: number; // Reconnection delay in ms (default: 3000)
99
+ // In-call socket reconnection configuration
100
+ incall: {
101
+ enabled: boolean; // Enable in-call reconnection (default: true)
102
+ maxAttempts: number; // Maximum reconnection attempts (default: 5)
103
+ delay: number; // Reconnection delay in ms (default: 3000)
104
+ pingInterval: number; // Heartbeat interval in ms (default: 30000)
105
+ pingTimeout: number; // Heartbeat timeout in ms (default: 10000)
106
+ };
107
+ };
108
+
109
+ // Track logs configuration
110
+ trackLogs?: {
111
+ enabled: boolean; // Enable log tracking (default: false)
112
+ interval: number; // Log upload interval in ms (default: 10000)
113
+ maxSize: number; // Maximum log buffer size (default: 100)
114
+ };
115
+ }
76
116
 
77
- // User manually maintains sending user status requests
78
- isAutoUpdateUserStatus: boolean;
117
+ interface WebrtcConstranis {
118
+ audio: {
119
+ autoGainControl?: boolean;
120
+ noiseSuppression?: boolean;
121
+ echoCancellation?: boolean;
122
+ };
123
+ video: false;
79
124
  }
80
125
  ```
81
126
 
@@ -84,13 +129,29 @@ interface CallKitConfig {
84
129
  ```ts
85
130
  interface CallKit {
86
131
  // User login
87
- login(username: string, password: string): Promise<void>;
132
+ login(
133
+ username: string,
134
+ password: string,
135
+ extra?: {
136
+ encryptionMethod?: 'INTERNAL' | 'NONE';
137
+ [key: string]: any;
138
+ }
139
+ ): Promise<void>;
88
140
 
89
141
  // User logout
90
- logout(): Promise<void>;
142
+ logout(options?: { isReset?: boolean }): Promise<void>;
91
143
 
92
144
  // Initiate call
93
- call(): Promise<void>;
145
+ call(
146
+ extno: string | number,
147
+ options?: {
148
+ sourceType?: number;
149
+ workOrderId?: string;
150
+ }
151
+ ): Promise<void>;
152
+
153
+ // Transfer call
154
+ refer(uri: string, options?: any): Promise<void>;
94
155
 
95
156
  // SIP registration
96
157
  register(): Promise<void>;
@@ -107,52 +168,67 @@ interface CallKit {
107
168
  // Release hold
108
169
  unhold(): void;
109
170
 
110
- // Set free status
111
- setFree(): Promise<void>;
171
+ // Mute microphone
172
+ mute(): void;
112
173
 
113
- // Set nap status
114
- setSleep(): Promise<void>;
174
+ // Unmute microphone
175
+ unmute(): void;
115
176
 
116
- // Set busy status
117
- setBusy(): Promise<void>;
177
+ // Set user status (manually)
178
+ setUserStatus(status: number): Promise<void>;
118
179
 
119
180
  // Reset all states
120
- reset(): Promise<void>;
181
+ reset(config?: { force?: boolean }): Promise<void>;
121
182
 
122
183
  // Event listener
123
184
  on(event: string, callback: Function): void;
185
+
186
+ // Remove event listener
187
+ off(event: string, callback?: Function): void;
188
+
189
+ // Remove all event listeners
190
+ removeAllListeners(): void;
124
191
  }
125
192
  ```
126
193
 
127
194
  ### Event List
128
195
 
129
- #### Status Events
196
+ #### Status Change Events
130
197
 
131
- - `userStatusChange` - User status change
132
- - `loginChange` - Login status change
133
- - `registerChange` - Registration status change
134
- - `callStatusChange` - Call status change
135
- - `holdChange` - Hold status change
136
- - `muteChange` - Mute status change
198
+ - `loginChange` - Login status change (param: boolean)
199
+ - `registerChange` - Registration status change (param: boolean)
200
+ - `callStatusChange` - Call status change (param: CallStatus)
201
+ - `callIdChange` - Call ID change (param: string)
202
+ - `holdChange` - Hold status change (param: boolean)
203
+ - `muteChange` - Mute status change (param: boolean)
204
+ - `userStatusChange` - User status change (param: status)
137
205
 
138
206
  #### Call Events
139
207
 
140
- - `invite` - Received call invitation (with accept, reject, getInviteData callback functions)
141
- - `connecting` - Connecting (with timestamp parameter)
142
- - `ringing` - Remote party ringing (with timestamp parameter)
143
- - `pickUp` - Remote party answered (with timestamp parameter)
144
- - `agentPickUp` - Agent connected
145
- - `noAnswer` - No answer
146
- - `callEnd` - Call ended
147
- - `callCdr` - Call record push
208
+ - `invite` - Received incoming call invitation
209
+ - Callback params: `{ accept: Function, reject: Function, getInviteData: Function }`
210
+ - `outgoingInvite` - Received outgoing call invitation
211
+ - `connecting` - Call connecting (param: timestamp)
212
+ - `ringing` - Remote party ringing (param: timestamp)
213
+ - `pickUp` - Remote party answered (param: timestamp)
214
+ - `agentPickUp` - Agent connected (param: timestamp)
215
+ - `hangUp` - Remote party hung up (param: timestamp)
216
+ - `noAnswer` - No answer (param: timestamp)
217
+ - `callEnd` - Call ended (param: timestamp)
218
+ - `callCdr` - Call detail record push (param: CDR data)
148
219
 
149
- #### Error Events
220
+ #### Connection Events
150
221
 
151
- - `error` - Error occurred
222
+ - `IncallConnectEvent` - In-call socket connection event
223
+ - `sipConnectEvent` - SIP connection event
224
+ - `sipRegistererEvent` - SIP registerer event
225
+ - `sipSessionEvent` - SIP session event
152
226
 
153
- #### Server Socket Events
227
+ #### System Events
154
228
 
155
- - `socketEvent` Forward all socket events
229
+ - `log` - System log event
230
+ - `error` - Error occurred (param: { code: number, message: string })
231
+ - `socketEvent` - Forward all socket events (param: socket message)
156
232
 
157
233
  ## Status Codes
158
234
 
@@ -161,31 +237,40 @@ interface CallKit {
161
237
  ```js
162
238
  const CallStatus = {
163
239
  init: 0, // Initial state/hung up
164
- registered: 1, // Registered
165
240
  connecting: 2, // Connecting
166
- holding: 3, // Call hold
167
241
  ringing: 4, // Ringing
168
- calling: 5, // In call
242
+ calling: 5 // In call
169
243
  };
170
244
  ```
171
245
 
246
+ > Note: In version 2.0.0+, `registered` and `holding` statuses have been removed. Registration status is now tracked separately via the `registerChange` event.
247
+
172
248
  ### User Status
173
249
 
250
+ > Note: In version 2.0.0+, user status management has been removed from CallKit. You should maintain user status through your own application using the `setUserStatus` method.
251
+
174
252
  ```js
253
+ // Example user status codes (define as needed in your application)
175
254
  const UserStatus = {
176
255
  offline: 1, // Offline
177
256
  online: 2, // Online & Free
178
257
  catNap: 3, // Cat Nap
179
258
  busy: 4, // Busy
180
259
  training: 5, // Training
181
- processing: 6, // Processing
260
+ processing: 6 // Processing
182
261
  };
262
+
263
+ // Set user status manually
264
+ await callKit.setUserStatus(UserStatus.online);
183
265
  ```
184
266
 
185
267
  ### Error Codes
186
268
 
187
269
  ```js
188
270
  const ErrorCode = {
271
+ // Unknown error
272
+ UNKNOWN_ERROR: -1,
273
+
189
274
  // API errors (1000xxx)
190
275
  API_USER_LOGIN_ERROR: 1000001, // User login failed
191
276
  API_USER_STATUS_UPDATE_ERROR: 1000002, // Update user status failed
@@ -198,14 +283,19 @@ const ErrorCode = {
198
283
  WEBRTC_HOLE_STATUS_ERROR: 2000004, // Call hold failed
199
284
  WEBRTC_AUDIO_PLAYER_ERROR: 2000005, // Audio player does not exist
200
285
  WEBRTC_AUDIO_PLAY_ERROR: 2000006, // Audio playback failed
286
+ WEBRTC_USER_AGENT_ERROR: 2000007, // User agent startup failed
287
+ WEBRTC_CALL_INVITE_ERROR: 2000008, // Call request failed
288
+ WEBRTC_REGISTER_ERROR: 2000009, // Register request failed
289
+ WEBRTC_MUTE_STATUS_ERROR: 2000010, // Mute failed
290
+ WEBRTC_CANCEL_REGISTER_ERROR: 2000011, // Unregister failed
291
+ WEBRTC_MUTE_ERROR: 2000012, // Mute operation failed
201
292
 
202
293
  // WebSocket errors (3000xxx)
203
294
  SOCKET_CONNECT_ERROR: 3000001, // Connection exception
204
295
  SOCKET_PING_TIMEOUT: 3000002, // Ping timeout
205
296
  SOKET_SERVER_ERROR: 3000003, // Server exception
206
297
  SOCKET_CALL_ERROR: 3000004, // Call failed
207
-
208
- UNKNOWN_ERROR: -1, // Unknown error
298
+ SOCKET_RECONNECT_FAILED: 3000005 // Reconnection limit exceeded
209
299
  };
210
300
  ```
211
301
 
@@ -217,17 +307,26 @@ const ErrorCode = {
217
307
  callKit.on('callStatusChange', (status) => {
218
308
  const statusMap = {
219
309
  0: 'Initial state',
220
- 1: 'Registered',
221
310
  2: 'Connecting',
222
- 3: 'Call on hold',
223
311
  4: 'Ringing',
224
- 5: 'In call',
312
+ 5: 'In call'
225
313
  };
226
314
  console.log('Current status:', statusMap[status]);
227
315
  });
228
316
  ```
229
317
 
230
- ### Q2: How to get call duration?
318
+ ### Q2: How to listen for registration status changes?
319
+
320
+ ```js
321
+ callKit.on('registerChange', (isRegistered) => {
322
+ console.log(
323
+ 'Registration status:',
324
+ isRegistered ? 'Registered' : 'Unregistered'
325
+ );
326
+ });
327
+ ```
328
+
329
+ ### Q3: How to get call duration?
231
330
 
232
331
  ```js
233
332
  let startTime;
@@ -242,7 +341,23 @@ callKit.on('callEnd', (date) => {
242
341
  });
243
342
  ```
244
343
 
245
- ### Q3: How to handle errors?
344
+ ### Q4: How to handle incoming calls?
345
+
346
+ ```js
347
+ callKit.on('invite', ({ accept, reject, getInviteData }) => {
348
+ // Get call data
349
+ const inviteData = getInviteData();
350
+ console.log('Incoming call:', inviteData);
351
+
352
+ // Accept the call
353
+ accept();
354
+
355
+ // Or reject the call
356
+ // reject();
357
+ });
358
+ ```
359
+
360
+ ### Q5: How to handle errors?
246
361
 
247
362
  ```js
248
363
  callKit.on('error', (error) => {
@@ -256,17 +371,127 @@ callKit.on('error', (error) => {
256
371
  case 2000002:
257
372
  // Handle not logged in error
258
373
  break;
259
- // Remove CALL_FAILED default handling, at this stage, users need to handle it actively
374
+ case 3000005:
375
+ // Handle reconnection failure
376
+ break;
260
377
  // ...other error handling
261
378
  }
262
379
  });
263
380
  ```
264
381
 
382
+ ### Q6: How to handle reconnection?
383
+
384
+ ```js
385
+ // Listen to reconnection events
386
+ callKit.on('IncallConnectEvent', (event) => {
387
+ console.log('In-call connection event:', event);
388
+ });
389
+
390
+ callKit.on('sipConnectEvent', (event) => {
391
+ console.log('SIP connection event:', event);
392
+ });
393
+
394
+ // Configure reconnection options
395
+ const callKit = new CallKit({
396
+ host: 'https://example.com',
397
+ socket: 'wss://example.com/ws/in-call',
398
+ audioRef: () => document.querySelector('#audioRef'),
399
+ reconnect: {
400
+ sip: {
401
+ enabled: true,
402
+ maxAttempts: 5,
403
+ delay: 3000
404
+ },
405
+ incall: {
406
+ enabled: true,
407
+ maxAttempts: 5,
408
+ delay: 3000
409
+ }
410
+ }
411
+ });
412
+ ```
413
+
414
+ ### Q7: How to use mute/unmute?
415
+
416
+ ```js
417
+ // Mute microphone
418
+ callKit.mute();
419
+
420
+ // Unmute microphone
421
+ callKit.unmute();
422
+
423
+ // Listen to mute status changes
424
+ callKit.on('muteChange', (isMuted) => {
425
+ console.log('Mute status:', isMuted ? 'Muted' : 'Unmuted');
426
+ });
427
+ ```
428
+
429
+ ### Q8: How to use hold/unhold?
430
+
431
+ ```js
432
+ // Hold call
433
+ callKit.hold();
434
+
435
+ // Unhold call
436
+ callKit.unhold();
437
+
438
+ // Listen to hold status changes
439
+ callKit.on('holdChange', (isHeld) => {
440
+ console.log('Hold status:', isHeld ? 'On hold' : 'Active');
441
+ });
442
+ ```
443
+
265
444
  ## More Information
266
445
 
267
446
  For complete TypeScript type definitions, please refer to [index.d.ts](./dist/index.d.ts)
268
447
 
448
+ ## Breaking Changes in v2.0.0
449
+
450
+ ### Major Changes
451
+
452
+ 1. **User Status Management Removed**
453
+
454
+ - CallKit no longer automatically manages user status
455
+ - Use `setUserStatus()` method to manually maintain user status
456
+
457
+ 2. **Registration Status Separated**
458
+
459
+ - Registration status is no longer part of call status
460
+ - Use `registerChange` event to track registration status independently
461
+
462
+ 3. **Call Status Simplified**
463
+
464
+ - Removed `registered` (1) status - use `registerChange` event instead
465
+ - Removed `holding` (3) status - use `holdChange` event instead
466
+ - Current statuses: `init` (0), `connecting` (2), `ringing` (4), `calling` (5)
467
+
468
+ 4. **Enhanced Reconnection Mechanism**
469
+
470
+ - Completely refactored SIP and socket reconnection logic
471
+ - Added configurable reconnection options for both SIP and in-call connections
472
+ - New error code: `SOCKET_RECONNECT_FAILED` (3000005)
473
+
474
+ 5. **New Methods**
475
+
476
+ - `mute()` / `unmute()` - Control microphone muting
477
+ - `refer(uri, options)` - Transfer calls
478
+ - `off(event, callback)` - Remove specific event listeners
479
+ - `removeAllListeners()` - Remove all event listeners
480
+ - `setUserStatus(status)` - Manually set user status
481
+
482
+ 6. **New Events**
483
+ - `callIdChange` - Call ID change event
484
+ - `outgoingInvite` - Outgoing call invitation event
485
+ - `hangUp` - Remote party hang up event
486
+ - `IncallConnectEvent` - In-call socket connection event
487
+ - `sipConnectEvent` - SIP connection event
488
+ - `sipRegistererEvent` - SIP registerer event
489
+ - `sipSessionEvent` - SIP session event
490
+
491
+ ### Migration Guide
492
+
493
+ Please refer to [MIGRATION.md](./MIGRATION.md) for detailed migration instructions from v1.x to v2.0.
494
+
269
495
  ## License
270
496
 
271
497
  MIT
272
-
package/dist/index.d.ts CHANGED
@@ -133,8 +133,8 @@ interface IConfig {
133
133
  constrains: WebrtcConstranis;
134
134
  socket: string;
135
135
  reconnect?: {
136
- sip: Partial<SocketConfig>;
137
- incall: Partial<SocketConfig>;
136
+ sip?: Partial<SocketConfig>;
137
+ incall?: Partial<SocketConfig>;
138
138
  };
139
139
  userInfo: {
140
140
  wsUrl: string;
@@ -517,8 +517,8 @@ interface CallKitConfig {
517
517
  constrains?: WebrtcConstranis;
518
518
  log?: LoggerLevel;
519
519
  reconnect?: {
520
- sip: Partial<SocketConfig>;
521
- incall: Partial<SocketConfig>;
520
+ sip?: Partial<SocketConfig>;
521
+ incall?: Partial<SocketConfig>;
522
522
  };
523
523
  }
524
524
  type ConfigEntity = Partial<IConfig> & CallKitConfig;
@@ -3826,7 +3826,7 @@ var WebCall = (() => {
3826
3826
  // package.json
3827
3827
  var package_default = {
3828
3828
  name: "@koi-design/callkit",
3829
- version: "2.0.5-beta.2",
3829
+ version: "2.0.5-beta.3",
3830
3830
  description: "callkit",
3831
3831
  author: "koi",
3832
3832
  license: "ISC",
@@ -19242,14 +19242,15 @@ var WebCall = (() => {
19242
19242
  return;
19243
19243
  }
19244
19244
  await this.registerer.unregister({ all: true }).catch((err) => {
19245
- this.callKit.reset();
19246
- this.callKit.logger.error(err, {
19245
+ this.callKit.logger.warn(err, {
19247
19246
  caller: "Connect.unregister",
19248
19247
  type: "SIP",
19249
19248
  content: {
19250
19249
  errCode: ErrorCode.WEBRTC_CANCEL_REGISTER_ERROR
19251
19250
  }
19252
19251
  });
19252
+ }).finally(() => {
19253
+ this.setRegister(false);
19253
19254
  });
19254
19255
  await this.userAgent?.stop().catch((err) => {
19255
19256
  this.callKit.logger.warn(err, {
@@ -19260,7 +19261,6 @@ var WebCall = (() => {
19260
19261
  }
19261
19262
  });
19262
19263
  });
19263
- this.setRegister(false);
19264
19264
  }
19265
19265
  async call(callback) {
19266
19266
  this.callKit.logger.info("connect call", {