@16x/webphone-sdk 3.0.1

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +2 -0
  3. package/README.md +113 -0
  4. package/dist/CCBarClient-BdbynNBi.js +2515 -0
  5. package/dist/CCBarClient-DKWdvgf5.cjs +1 -0
  6. package/dist/CCBarError-CIqJE8zK.cjs +1 -0
  7. package/dist/CCBarError-DSbPw2dA.js +14 -0
  8. package/dist/Diagnostics-BYVvmxil.cjs +1 -0
  9. package/dist/Diagnostics-Cw2HVrCD.js +123 -0
  10. package/dist/JsSipAdapter-GHzVSCDh.js +304 -0
  11. package/dist/JsSipAdapter-jtGdoXrm.cjs +1 -0
  12. package/dist/SharedWorkerProtocol-BqUafs8d.js +73 -0
  13. package/dist/SharedWorkerProtocol-CYN0AprP.cjs +1 -0
  14. package/dist/api/WebPhoneApi.d.ts +28 -0
  15. package/dist/api/contracts.d.ts +94 -0
  16. package/dist/auth/TokenManager.d.ts +22 -0
  17. package/dist/core/CCBarCall.d.ts +94 -0
  18. package/dist/core/CCBarClient.d.ts +113 -0
  19. package/dist/core/CallManager.d.ts +93 -0
  20. package/dist/core/callId.d.ts +1 -0
  21. package/dist/core/mediaBridge.d.ts +17 -0
  22. package/dist/createJsSipFactory-2X4FBIU2.cjs +75 -0
  23. package/dist/createJsSipFactory-yttVU3d6.js +9662 -0
  24. package/dist/diagnostics/Diagnostics.d.ts +74 -0
  25. package/dist/diagnostics/RingBuffer.d.ts +7 -0
  26. package/dist/diagnostics/index.cjs +1 -0
  27. package/dist/diagnostics/index.d.ts +4 -0
  28. package/dist/diagnostics/index.js +6 -0
  29. package/dist/diagnostics/redact.d.ts +5 -0
  30. package/dist/errors/CCBarError.d.ts +15 -0
  31. package/dist/events/TypedEventBus.d.ts +9 -0
  32. package/dist/index.cjs +1 -0
  33. package/dist/index.d.ts +21 -0
  34. package/dist/index.js +152 -0
  35. package/dist/index.umd.js +75 -0
  36. package/dist/legacy/CCBarSDK.d.ts +29 -0
  37. package/dist/legacy/index.cjs +1 -0
  38. package/dist/legacy/index.d.ts +8 -0
  39. package/dist/legacy/index.js +108 -0
  40. package/dist/redact-Bq26pObO.cjs +1 -0
  41. package/dist/redact-DB3CMbsK.js +21 -0
  42. package/dist/shared/SharedCallTransport.d.ts +55 -0
  43. package/dist/shared/SharedWorkerClient.d.ts +20 -0
  44. package/dist/shared/SharedWorkerEntry.d.ts +3 -0
  45. package/dist/shared/SharedWorkerFactory.d.ts +29 -0
  46. package/dist/shared/SharedWorkerProtocol.d.ts +47 -0
  47. package/dist/shared/SharedWorkerRuntime.d.ts +35 -0
  48. package/dist/shared-worker.cjs +1 -0
  49. package/dist/shared-worker.d.ts +1 -0
  50. package/dist/shared-worker.js +185 -0
  51. package/dist/state/callStateMachine.d.ts +9 -0
  52. package/dist/styles.css +7 -0
  53. package/dist/types.d.ts +134 -0
  54. package/dist/ui/XCallCCBarElement.d.ts +23 -0
  55. package/dist/ui/controllers/mobileLifecycle.d.ts +18 -0
  56. package/dist/ui/controllers/phoneActions.d.ts +27 -0
  57. package/dist/ui/i18n/en-US.d.ts +2 -0
  58. package/dist/ui/i18n/index.d.ts +6 -0
  59. package/dist/ui/i18n/types.d.ts +53 -0
  60. package/dist/ui/i18n/zh-CN.d.ts +2 -0
  61. package/dist/ui/icons/index.d.ts +5 -0
  62. package/dist/ui/index.cjs +1 -0
  63. package/dist/ui/index.d.ts +3 -0
  64. package/dist/ui/index.js +1044 -0
  65. package/dist/ui/state/toPhoneViewModel.d.ts +54 -0
  66. package/dist/ui/views/dom.d.ts +11 -0
  67. package/dist/ui/views/messages.d.ts +5 -0
  68. package/dist/ui/views/renderActiveCall.d.ts +8 -0
  69. package/dist/ui/views/renderDesktop.d.ts +24 -0
  70. package/dist/ui/views/renderDialpad.d.ts +4 -0
  71. package/dist/ui/views/renderError.d.ts +6 -0
  72. package/dist/ui/views/renderIncoming.d.ts +8 -0
  73. package/dist/ui/views/renderMobile.d.ts +15 -0
  74. package/dist/ui/views/renderSetup.d.ts +6 -0
  75. package/package.json +107 -0
@@ -0,0 +1,2515 @@
1
+ import { t as e } from "./CCBarError-DSbPw2dA.js";
2
+ import { t } from "./Diagnostics-Cw2HVrCD.js";
3
+ //#region src/events/TypedEventBus.ts
4
+ var n = class {
5
+ handlers = /* @__PURE__ */ new Map();
6
+ on(e, t) {
7
+ let n = this.handlers.get(e) ?? /* @__PURE__ */ new Set();
8
+ n.add(t), this.handlers.set(e, n);
9
+ let r = !0;
10
+ return () => {
11
+ r && (r = !1, n.delete(t));
12
+ };
13
+ }
14
+ off(e, t) {
15
+ this.handlers.get(e)?.delete(t);
16
+ }
17
+ emit(e, t) {
18
+ [...this.handlers.get(e) ?? []].forEach((e) => {
19
+ try {
20
+ e(t);
21
+ } catch {}
22
+ });
23
+ }
24
+ listenerCount() {
25
+ return [...this.handlers.values()].reduce((e, t) => e + t.size, 0);
26
+ }
27
+ clear() {
28
+ this.handlers.clear();
29
+ }
30
+ }, r = {
31
+ new: /* @__PURE__ */ new Set([
32
+ "dialing",
33
+ "ringing",
34
+ "failed"
35
+ ]),
36
+ dialing: /* @__PURE__ */ new Set([
37
+ "ringing",
38
+ "connecting",
39
+ "ended",
40
+ "failed"
41
+ ]),
42
+ ringing: /* @__PURE__ */ new Set([
43
+ "connecting",
44
+ "ended",
45
+ "failed"
46
+ ]),
47
+ connecting: /* @__PURE__ */ new Set([
48
+ "active",
49
+ "ended",
50
+ "failed"
51
+ ]),
52
+ active: /* @__PURE__ */ new Set([
53
+ "held",
54
+ "ended",
55
+ "failed"
56
+ ]),
57
+ held: /* @__PURE__ */ new Set([
58
+ "active",
59
+ "ended",
60
+ "failed"
61
+ ]),
62
+ ended: /* @__PURE__ */ new Set(),
63
+ failed: /* @__PURE__ */ new Set()
64
+ }, i = (e, t) => r[e].has(t);
65
+ function a(e, t) {
66
+ if (!i(e, t)) throw new o(e, t);
67
+ return t;
68
+ }
69
+ var o = class extends e {
70
+ constructor(e, t) {
71
+ super("CALL_OPERATION_NOT_ALLOWED", "call", !1, { cause: {
72
+ from: e,
73
+ to: t
74
+ } });
75
+ }
76
+ }, s = a, c = 60, l = class {
77
+ tokenProvider;
78
+ cachedToken;
79
+ cachedRequestKey = "";
80
+ refreshing;
81
+ generation = 0;
82
+ constructor(e) {
83
+ this.tokenProvider = e;
84
+ }
85
+ getValidToken(e) {
86
+ let t = e?.extension?.trim() ?? "";
87
+ if (this.cachedToken && this.cachedRequestKey === t && !this.needsRefresh(this.cachedToken)) return Promise.resolve(this.cachedToken.accessToken);
88
+ if (!this.refreshing) {
89
+ let n = this.generation, r = this.refresh(e, t, n);
90
+ this.refreshing = r, r.then(() => this.clearRefresh(r), () => this.clearRefresh(r));
91
+ }
92
+ return this.refreshing;
93
+ }
94
+ invalidate() {
95
+ this.generation += 1, this.cachedToken = void 0, this.cachedRequestKey = "", this.refreshing = void 0;
96
+ }
97
+ needsRefresh(e) {
98
+ return e.expiresAt !== void 0 && e.expiresAt <= Math.floor(Date.now() / 1e3) + c;
99
+ }
100
+ async refresh(e, t, n) {
101
+ let r = await this.tokenProvider(e), i = typeof r == "string" ? { accessToken: r } : r;
102
+ return n === this.generation && (this.cachedToken = i, this.cachedRequestKey = t), i.accessToken;
103
+ }
104
+ clearRefresh(e) {
105
+ this.refreshing === e && (this.refreshing = void 0);
106
+ }
107
+ }, u = {
108
+ ORIGIN_NOT_ALLOWED: {
109
+ code: "CONFIG_ORIGIN_NOT_ALLOWED",
110
+ category: "configuration",
111
+ retryable: !1
112
+ },
113
+ CAPABILITY_DENIED: {
114
+ code: "CAPABILITY_NOT_SUPPORTED",
115
+ category: "capability",
116
+ retryable: !1
117
+ },
118
+ TOKEN_INVALID: {
119
+ code: "AUTH_TOKEN_UNAVAILABLE",
120
+ category: "auth",
121
+ retryable: !1
122
+ },
123
+ TOKEN_EXPIRED: {
124
+ code: "AUTH_TOKEN_EXPIRED",
125
+ category: "auth",
126
+ retryable: !1
127
+ },
128
+ INVALID_ARGUMENT: {
129
+ code: "CONFIG_INVALID",
130
+ category: "configuration",
131
+ retryable: !1
132
+ },
133
+ INVALID_EXTENSION: {
134
+ code: "CONFIG_INVALID",
135
+ category: "configuration",
136
+ retryable: !1
137
+ },
138
+ SEAT_NOT_FOUND: {
139
+ code: "AUTH_PERMISSION_DENIED",
140
+ category: "auth",
141
+ retryable: !1
142
+ },
143
+ SESSION_NOT_FOUND: {
144
+ code: "CALL_NOT_CONNECTED",
145
+ category: "call",
146
+ retryable: !1
147
+ },
148
+ SEAT_IN_USE: {
149
+ code: "CALL_ALREADY_EXISTS",
150
+ category: "call",
151
+ retryable: !1
152
+ },
153
+ SESSION_CONFLICT: {
154
+ code: "CALL_ALREADY_EXISTS",
155
+ category: "call",
156
+ retryable: !1
157
+ },
158
+ SEAT_NOT_ASSIGNED: {
159
+ code: "AUTH_PERMISSION_DENIED",
160
+ category: "auth",
161
+ retryable: !1
162
+ },
163
+ QUEUE_NOT_ASSIGNED: {
164
+ code: "CAPABILITY_NOT_SUPPORTED",
165
+ category: "capability",
166
+ retryable: !1
167
+ },
168
+ RATE_LIMITED: {
169
+ code: "NETWORK_OFFLINE",
170
+ category: "network",
171
+ retryable: !0
172
+ },
173
+ SIP_GATEWAY_UNAVAILABLE: {
174
+ code: "SIP_WS_UNAVAILABLE",
175
+ category: "registration",
176
+ retryable: !0
177
+ },
178
+ SERVICE_UNAVAILABLE: {
179
+ code: "NETWORK_OFFLINE",
180
+ category: "network",
181
+ retryable: !0
182
+ },
183
+ INTERNAL_ERROR: {
184
+ code: "SDK_INTERNAL_ERROR",
185
+ category: "internal",
186
+ retryable: !0
187
+ }
188
+ }, d = class {
189
+ tokenManager;
190
+ fetcher;
191
+ baseUrl;
192
+ timeoutMs;
193
+ constructor(e) {
194
+ this.tokenManager = new l(e.tokenProvider), this.fetcher = e.fetcher ?? fetch.bind(globalThis), this.baseUrl = e.baseUrl.replace(/\/$/, ""), this.timeoutMs = e.timeoutMs ?? 1e4;
195
+ }
196
+ invalidateToken() {
197
+ this.tokenManager.invalidate();
198
+ }
199
+ createSession(e) {
200
+ return this.request("POST", "/webphone/v1/sessions", e).then((e) => this.requireData(e));
201
+ }
202
+ refreshSession(e, t = { refresh: [
203
+ "sip_register_ticket",
204
+ "wss_ticket",
205
+ "turn_credentials"
206
+ ] }) {
207
+ return this.request("POST", `/webphone/v1/sessions/${encodeURIComponent(e)}/refresh`, t).then((e) => this.requireData(e));
208
+ }
209
+ deleteSession(e) {
210
+ return this.request("DELETE", `/webphone/v1/sessions/${encodeURIComponent(e)}`).then(() => void 0);
211
+ }
212
+ setAgentStatus(e) {
213
+ return this.request("PUT", "/webphone/v1/agents/me/status", e).then(() => void 0);
214
+ }
215
+ getCapabilities() {
216
+ return this.request("GET", "/webphone/v1/capabilities").then((e) => this.requireData(e));
217
+ }
218
+ async request(t, n, r) {
219
+ let i = new AbortController(), a = setTimeout(() => i.abort(), this.timeoutMs);
220
+ try {
221
+ let e = await this.tokenManager.getValidToken(), a = await this.fetcher(`${this.baseUrl}${n}`, {
222
+ method: t,
223
+ headers: {
224
+ Authorization: `Bearer ${e}`,
225
+ ...r === void 0 ? {} : { "Content-Type": "application/json" }
226
+ },
227
+ ...r === void 0 ? {} : { body: JSON.stringify(r) },
228
+ signal: i.signal
229
+ }), o = await this.parseResponse(a);
230
+ if (!a.ok || o.code !== "OK") throw this.toCCBarError(a.status, o);
231
+ return {
232
+ data: o.data,
233
+ requestId: o.requestId
234
+ };
235
+ } catch (t) {
236
+ throw t instanceof e ? t : t instanceof DOMException && t.name === "AbortError" ? new e("NETWORK_TIMEOUT", "network", !0, { cause: t }) : new e("NETWORK_OFFLINE", "network", !0, { cause: t });
237
+ } finally {
238
+ clearTimeout(a);
239
+ }
240
+ }
241
+ requireData(t) {
242
+ if (t.data === void 0 || t.data === null) throw new e("SDK_INTERNAL_ERROR", "internal", !1, { requestId: t.requestId });
243
+ return t.data;
244
+ }
245
+ async parseResponse(t) {
246
+ try {
247
+ return await t.json();
248
+ } catch (n) {
249
+ throw new e("SDK_INTERNAL_ERROR", "internal", t.status >= 500, { cause: n });
250
+ }
251
+ }
252
+ toCCBarError(t, n) {
253
+ let r = u[n.code ?? ""] ?? this.mapStatus(t);
254
+ return new e(r.code, r.category, r.retryable, { requestId: n.requestId });
255
+ }
256
+ mapStatus(e) {
257
+ return e === 401 ? {
258
+ code: "AUTH_TOKEN_EXPIRED",
259
+ category: "auth",
260
+ retryable: !1
261
+ } : e === 403 ? {
262
+ code: "AUTH_PERMISSION_DENIED",
263
+ category: "auth",
264
+ retryable: !1
265
+ } : e >= 500 ? {
266
+ code: "SDK_INTERNAL_ERROR",
267
+ category: "internal",
268
+ retryable: !0
269
+ } : {
270
+ code: "SDK_INTERNAL_ERROR",
271
+ category: "internal",
272
+ retryable: !1
273
+ };
274
+ }
275
+ }, f = [
276
+ "progress",
277
+ "accepted",
278
+ "confirmed",
279
+ "ended",
280
+ "failed",
281
+ "hold",
282
+ "unhold"
283
+ ], p = 3e4, m = class {
284
+ options;
285
+ currentState = "new";
286
+ sessionUnsubscribers = [];
287
+ capabilities;
288
+ disposed = !1;
289
+ pendingOperation;
290
+ incomingOperation;
291
+ ownerTabId;
292
+ ownerLost = !1;
293
+ id;
294
+ destination;
295
+ platform;
296
+ constructor(t) {
297
+ this.options = t, this.id = t.id, this.destination = t.destination, this.platform = t.platform, this.capabilities = t.capabilities ?? /* @__PURE__ */ new Set();
298
+ try {
299
+ f.forEach((e) => {
300
+ this.sessionUnsubscribers.push(t.session.on(e, (t) => this.handleSessionEvent(e, t)));
301
+ });
302
+ } catch (n) {
303
+ this.cleanupSessionListeners();
304
+ try {
305
+ t.session.terminate();
306
+ } catch {}
307
+ throw new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, {
308
+ callId: this.id,
309
+ cause: n
310
+ });
311
+ }
312
+ }
313
+ get state() {
314
+ return this.currentState;
315
+ }
316
+ getResourceCounts() {
317
+ return {
318
+ timers: this.pendingOperation?.timer === void 0 ? 0 : 1,
319
+ listeners: this.sessionUnsubscribers.length
320
+ };
321
+ }
322
+ async mute(e) {
323
+ this.assertNotDisposed(), this.assertOwner(e), this.assertMediaControlAllowed(), this.assertCapability("mute"), this.invoke(() => this.options.session.mute());
324
+ }
325
+ async unmute(e) {
326
+ this.assertNotDisposed(), this.assertOwner(e), this.assertMediaControlAllowed(), this.assertCapability("mute"), this.invoke(() => this.options.session.unmute());
327
+ }
328
+ async answer(e, t) {
329
+ if (this.assertNotDisposed(), this.assertOwner(t), this.assertIncomingCall(), this.platform === "mobile-web") throw this.capabilityError();
330
+ this.assertCapability("inbound"), this.assertIncomingOperationAvailable(), this.incomingOperation = "answer";
331
+ try {
332
+ this.options.session.answer(e);
333
+ } catch (e) {
334
+ throw this.incomingOperation = void 0, this.finishFailedIncomingOperation(e), this.operationError(e);
335
+ }
336
+ }
337
+ async reject(e = {}, t) {
338
+ this.assertNotDisposed(), this.assertOwner(t), this.assertIncomingCall(), this.assertIncomingOperationAvailable(), this.incomingOperation = "reject";
339
+ let n;
340
+ try {
341
+ this.options.session.terminate();
342
+ } catch (e) {
343
+ n = e;
344
+ } finally {
345
+ this.incomingOperation = void 0, this.transitionIfStillRinging("ended", { reason: e.reason?.trim() || "rejected" });
346
+ }
347
+ if (n !== void 0) throw this.operationError(n);
348
+ }
349
+ async hold(e) {
350
+ this.assertNotDisposed(), this.assertOwner(e), this.assertHoldCapability(), this.assertState("active"), this.assertCapability("hold"), await this.startPendingOperation("hold", "held", () => this.options.session.hold());
351
+ }
352
+ async resume(e) {
353
+ this.assertNotDisposed(), this.assertOwner(e), this.assertHoldCapability(), this.assertState("held"), this.assertCapability("hold"), await this.startPendingOperation("resume", "active", () => this.options.session.unhold());
354
+ }
355
+ async sendDtmf(e, t) {
356
+ if (this.assertNotDisposed(), this.assertOwner(t), !/^[0-9A-D*#]$/.test(e)) throw this.operationError();
357
+ this.assertState("active"), this.assertCapability("dtmf"), this.invoke(() => this.options.session.sendDtmf(e));
358
+ }
359
+ async transfer(e, t) {
360
+ if (this.assertNotDisposed(), this.assertOwner(t), this.assertTransferCapability(), this.assertState("active"), this.assertCapability("blind_transfer"), !g(e) || e.target.trim() === "") throw this.operationError();
361
+ this.invoke(() => this.options.session.refer(e.target.trim()));
362
+ }
363
+ async hangup(e) {
364
+ if (this.assertNotDisposed(), this.assertOwner(e), h(this.currentState)) throw this.operationError();
365
+ try {
366
+ this.options.session.terminate(), this.transitionTo("ended");
367
+ } catch (e) {
368
+ throw this.operationError(e);
369
+ }
370
+ }
371
+ beginOutbound() {
372
+ this.assertNotDisposed(), this.assertCapability("outbound"), this.transitionTo("dialing");
373
+ }
374
+ beginIncoming() {
375
+ this.assertNotDisposed(), this.transitionTo("ringing");
376
+ }
377
+ setOwnerTabId(e) {
378
+ this.ownerTabId = e, this.ownerLost = !1;
379
+ }
380
+ clearOwnerTabId(e = {}) {
381
+ this.ownerTabId = void 0, this.ownerLost = e.lost === !0;
382
+ }
383
+ getOwnerTabId() {
384
+ return this.ownerTabId;
385
+ }
386
+ assertOwnerForManager(e) {
387
+ this.assertOwner(e);
388
+ }
389
+ canBeReclaimed() {
390
+ return this.currentState === "new" || this.currentState === "dialing" || this.currentState === "ringing";
391
+ }
392
+ dispose() {
393
+ if (!this.disposed) {
394
+ if (this.rejectPendingOperation(), this.incomingOperation = void 0, this.disposed = !0, !h(this.currentState)) try {
395
+ this.options.session.terminate();
396
+ } catch (e) {
397
+ this.reportOperationError(e);
398
+ }
399
+ this.cleanupSessionListeners();
400
+ try {
401
+ this.options.onDisposed?.();
402
+ } catch {}
403
+ }
404
+ }
405
+ handleSessionEvent(e, t) {
406
+ if ((e === "accepted" || e === "confirmed" || e === "ended" || e === "failed") && (this.incomingOperation = void 0), !(this.disposed || h(this.currentState))) switch (e) {
407
+ case "progress":
408
+ this.transitionIfAllowed("ringing", t, e);
409
+ break;
410
+ case "accepted":
411
+ this.transitionIfAllowed("connecting", t, e);
412
+ break;
413
+ case "confirmed":
414
+ this.transitionToActive(t);
415
+ break;
416
+ case "hold":
417
+ this.transitionIfAllowed("held", t, e);
418
+ break;
419
+ case "unhold":
420
+ this.transitionIfAllowed("active", t, e);
421
+ break;
422
+ case "ended":
423
+ this.transitionIfAllowed("ended", t, e);
424
+ break;
425
+ case "failed": this.transitionIfAllowed("failed", t, e);
426
+ }
427
+ }
428
+ transitionToActive(e) {
429
+ this.currentState !== "active" && ((this.currentState === "dialing" || this.currentState === "ringing") && this.transitionTo("connecting", e), this.transitionIfAllowed("active", e, "confirmed"));
430
+ }
431
+ transitionIfAllowed(e, t, n) {
432
+ this.currentState !== e && (i(this.currentState, e) ? this.transitionTo(e, t) : this.reportIllegalTransition(e, n));
433
+ }
434
+ transitionIfStillRinging(e, t) {
435
+ this.currentState === "ringing" && this.transitionTo(e, t);
436
+ }
437
+ transitionTo(e, t) {
438
+ if (this.currentState === e) return;
439
+ if (!i(this.currentState, e)) throw this.operationError();
440
+ let n = this.currentState;
441
+ this.currentState = e, h(e) && this.rejectPendingOperation();
442
+ try {
443
+ this.options.onStateChanged?.({
444
+ callId: this.id,
445
+ from: n,
446
+ to: e
447
+ }, t);
448
+ } catch {} finally {
449
+ h(e) && this.dispose();
450
+ }
451
+ }
452
+ startPendingOperation(e, t, n) {
453
+ if (this.pendingOperation !== void 0) throw this.operationError();
454
+ return new Promise((r, i) => {
455
+ let a = {
456
+ kind: e,
457
+ nextState: t,
458
+ resolve: r,
459
+ reject: i
460
+ };
461
+ this.pendingOperation = a, a.timer = setTimeout(() => this.timeoutPendingOperation(a), p);
462
+ let o;
463
+ try {
464
+ o = n();
465
+ } catch (e) {
466
+ this.rejectPendingOperation(e);
467
+ return;
468
+ }
469
+ o.then(() => this.resolvePendingOperation(a), (e) => this.rejectPendingOperation(e, a));
470
+ });
471
+ }
472
+ resolvePendingOperation(e) {
473
+ if (this.pendingOperation === e) {
474
+ if (this.clearPendingTimer(e), this.pendingOperation = void 0, this.disposed || h(this.currentState)) {
475
+ e.reject(this.operationError());
476
+ return;
477
+ }
478
+ try {
479
+ this.transitionTo(e.nextState), e.resolve();
480
+ } catch (t) {
481
+ e.reject(this.operationError(t));
482
+ }
483
+ }
484
+ }
485
+ rejectPendingOperation(e, t) {
486
+ let n = this.pendingOperation;
487
+ n === void 0 || t !== void 0 && n !== t || (this.clearPendingTimer(n), this.pendingOperation = void 0, n.reject(this.operationError(e)));
488
+ }
489
+ timeoutPendingOperation(e) {
490
+ this.pendingOperation === e && (this.rejectPendingOperation(/* @__PURE__ */ Error(`${e.kind} operation timed out`), e), this.dispose());
491
+ }
492
+ clearPendingTimer(e) {
493
+ e.timer !== void 0 && (clearTimeout(e.timer), e.timer = void 0);
494
+ }
495
+ reportIllegalTransition(e, t) {
496
+ this.reportOperationError({
497
+ event: t,
498
+ from: this.currentState,
499
+ to: e
500
+ });
501
+ }
502
+ reportOperationError(t) {
503
+ let n = t instanceof e && t.callId === this.id ? t : this.operationError(t);
504
+ try {
505
+ this.options.onError?.(n);
506
+ } catch {}
507
+ }
508
+ finishFailedIncomingOperation(e) {
509
+ try {
510
+ this.options.session.terminate();
511
+ } catch (t) {
512
+ e = {
513
+ operation: e,
514
+ cleanup: t
515
+ };
516
+ }
517
+ this.transitionIfStillRinging("ended", {
518
+ reason: "incoming_operation_failed",
519
+ cause: e
520
+ });
521
+ }
522
+ cleanupSessionListeners() {
523
+ this.sessionUnsubscribers.splice(0).forEach((e) => {
524
+ try {
525
+ e();
526
+ } catch {}
527
+ });
528
+ }
529
+ assertState(e) {
530
+ if (this.currentState !== e) throw this.operationError();
531
+ }
532
+ assertMediaControlAllowed() {
533
+ if (this.currentState !== "active" && this.currentState !== "held") throw this.operationError();
534
+ }
535
+ assertHoldCapability() {
536
+ if (this.platform === "mobile-web") throw this.capabilityError();
537
+ }
538
+ assertTransferCapability() {
539
+ if (this.platform === "mobile-web") throw this.capabilityError();
540
+ }
541
+ assertIncomingCall() {
542
+ if (this.options.incoming !== !0 || this.currentState !== "ringing") throw this.operationError();
543
+ }
544
+ assertIncomingOperationAvailable() {
545
+ if (this.incomingOperation !== void 0) throw this.operationError();
546
+ }
547
+ assertCapability(e) {
548
+ if (!this.capabilities.has(e)) throw this.capabilityError();
549
+ }
550
+ invoke(e) {
551
+ try {
552
+ e();
553
+ } catch (e) {
554
+ throw this.operationError(e);
555
+ }
556
+ }
557
+ assertNotDisposed() {
558
+ if (this.disposed) throw this.operationError();
559
+ }
560
+ assertOwner(e) {
561
+ if (e !== void 0 && (this.ownerLost || this.ownerTabId !== void 0 && this.ownerTabId !== e)) throw this.operationError();
562
+ }
563
+ capabilityError() {
564
+ return new e("CAPABILITY_NOT_SUPPORTED", "capability", !1, { callId: this.id });
565
+ }
566
+ operationError(t) {
567
+ return new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, {
568
+ callId: this.id,
569
+ cause: t
570
+ });
571
+ }
572
+ };
573
+ function h(e) {
574
+ return e === "ended" || e === "failed";
575
+ }
576
+ function g(e) {
577
+ return typeof e == "object" && !!e && e.type === "blind" && typeof e.target == "string";
578
+ }
579
+ //#endregion
580
+ //#region src/core/callId.ts
581
+ var _ = 0;
582
+ function v() {
583
+ return _ += 1, `call_${Date.now().toString(36)}_${_.toString(36)}`;
584
+ }
585
+ //#endregion
586
+ //#region src/core/CallManager.ts
587
+ var y = class {
588
+ events = new b();
589
+ calls = /* @__PURE__ */ new Map();
590
+ options;
591
+ incomingUnsubscribe;
592
+ activeCallId = null;
593
+ incomingSessionSnapshot;
594
+ callSessions = /* @__PURE__ */ new Map();
595
+ callOwners = /* @__PURE__ */ new Map();
596
+ ownerLostCalls = /* @__PURE__ */ new Set();
597
+ pendingDialCount = 0;
598
+ pendingDestinations = /* @__PURE__ */ new Set();
599
+ activeOperationPromise = Promise.resolve();
600
+ operationGeneration = 0;
601
+ automaticActiveTransition;
602
+ disposed = !1;
603
+ terminalNotified = /* @__PURE__ */ new Set();
604
+ terminalOperations = /* @__PURE__ */ new Map();
605
+ disposeOperation;
606
+ constructor(t) {
607
+ this.options = t, this.incomingSessionSnapshot = t.session;
608
+ try {
609
+ this.incomingUnsubscribe = t.sip.onIncoming((e) => this.handleIncoming(e));
610
+ } catch (t) {
611
+ throw new e("SDK_INTERNAL_ERROR", "internal", !1, { cause: t });
612
+ }
613
+ }
614
+ on(e, t) {
615
+ return this.disposed ? () => void 0 : this.events.on(e, t);
616
+ }
617
+ async dial(t, n) {
618
+ this.assertNotDisposed();
619
+ let r = this.operationGeneration, i = t.destination.trim();
620
+ if (i === "") throw new e("CALL_INVALID_DESTINATION", "call", !1);
621
+ this.requireCapability(n, "outbound");
622
+ let a = this.callLimit(n);
623
+ if (this.options.platform === "mobile-web" && this.calls.size + this.pendingDialCount >= a) throw this.capabilityError();
624
+ if (this.calls.size + this.pendingDialCount >= a || this.pendingDestinations.has(i) || [...this.calls.values()].some((e) => e.destination === i)) throw new e("CALL_ALREADY_EXISTS", "call", !1);
625
+ this.pendingDialCount += 1, this.pendingDestinations.add(i);
626
+ let o = v(), s;
627
+ try {
628
+ s = await this.holdActiveCallForNewCall(), this.assertGeneration(r, o);
629
+ let e;
630
+ try {
631
+ e = this.options.sip.dial(i, this.dialOptions(o, n, t.type));
632
+ } catch (e) {
633
+ throw this.dialError(e, o);
634
+ }
635
+ this.assertGeneration(r, o);
636
+ let a;
637
+ try {
638
+ a = new m({
639
+ id: o,
640
+ destination: i,
641
+ platform: this.options.platform,
642
+ capabilities: this.effectiveCapabilities(n),
643
+ session: e,
644
+ onStateChanged: (e, t) => this.handleStateChanged(a, e, t),
645
+ onError: (e) => this.events.emit("error", { error: e }),
646
+ onDisposed: () => this.handleDisposed(a)
647
+ });
648
+ } catch (e) {
649
+ throw this.dialError(e, o);
650
+ }
651
+ if (!this.isCurrentGeneration(r)) throw a.dispose(), this.callOperationError(a.id);
652
+ this.calls.set(a.id, a), this.callSessions.set(a.id, e), this.options.onCallCreated?.(a.id, e);
653
+ try {
654
+ a.beginOutbound();
655
+ } catch (e) {
656
+ throw a.dispose(), this.calls.delete(a.id), this.callSessions.delete(a.id), this.dialError(e, a.id);
657
+ }
658
+ if (!this.isCurrentGeneration(r)) throw a.dispose(), this.calls.delete(a.id), this.callSessions.delete(a.id), this.callOperationError(a.id);
659
+ return this.events.emit("call.created", {
660
+ callId: a.id,
661
+ state: a.state
662
+ }), a;
663
+ } catch (e) {
664
+ if (this.isCurrentGeneration(r) && s !== void 0 && this.isManagedCall(s) && s.state === "held") try {
665
+ await s.resume();
666
+ } catch (t) {
667
+ throw this.compensationError(s.id, void 0, e, t);
668
+ }
669
+ throw e;
670
+ } finally {
671
+ --this.pendingDialCount, this.pendingDestinations.delete(i);
672
+ }
673
+ }
674
+ async answer(e, t, n, r) {
675
+ this.assertNotDisposed();
676
+ let i = this.requireCall(e);
677
+ if (this.options.platform === "mobile-web") throw this.capabilityError(e);
678
+ let a = {
679
+ iceServers: t.iceServers,
680
+ pcConfig: { iceServers: t.iceServers },
681
+ ...n === void 0 ? {} : { mediaConstraints: n }
682
+ };
683
+ await i.answer(a, r);
684
+ }
685
+ async reject(e, t, n) {
686
+ this.assertNotDisposed(), await this.requireCall(e).reject(t, n);
687
+ }
688
+ getCalls() {
689
+ return [...this.calls.values()];
690
+ }
691
+ hasNonTerminalCalls() {
692
+ return this.calls.size > 0;
693
+ }
694
+ getResourceCounts() {
695
+ let e = [...this.calls.values()].map((e) => e.getResourceCounts());
696
+ return {
697
+ timers: e.reduce((e, t) => e + t.timers, 0),
698
+ listeners: this.events.listenerCount() + e.reduce((e, t) => e + t.listeners, 0)
699
+ };
700
+ }
701
+ getActiveCall() {
702
+ return this.activeCallId === null ? void 0 : this.calls.get(this.activeCallId);
703
+ }
704
+ async setActiveCall(e, t) {
705
+ this.assertNotDisposed(), this.requireCall(e).assertOwnerForManager(t), await this.enqueueActiveOperation((t) => this.switchActiveCall(e, t));
706
+ }
707
+ async claimCall(e, t) {
708
+ this.assertNotDisposed();
709
+ let n = t.trim();
710
+ if (n === "") throw this.callOperationError(e);
711
+ let r = this.requireCall(e), i = this.callOwners.get(e);
712
+ if (i !== n) {
713
+ if (i !== void 0 || this.ownerLostCalls.has(e) && !r.canBeReclaimed()) throw this.callOperationError(e);
714
+ this.ownerLostCalls.delete(e), this.callOwners.set(e, n), r.setOwnerTabId(n), this.emitOwnershipChanged({
715
+ callId: e,
716
+ state: "owned",
717
+ ownerTabId: n
718
+ });
719
+ }
720
+ }
721
+ async releaseCall(e, t) {
722
+ this.assertNotDisposed();
723
+ let n = this.requireCall(e);
724
+ if (this.callOwners.get(e) !== t) throw this.callOperationError(e);
725
+ this.callOwners.delete(e);
726
+ let r = !n.canBeReclaimed();
727
+ r ? this.ownerLostCalls.add(e) : this.ownerLostCalls.delete(e), n.clearOwnerTabId({ lost: r }), this.emitOwnershipChanged({
728
+ callId: e,
729
+ state: r ? "owner-lost" : "released"
730
+ });
731
+ }
732
+ getCallOwner(e) {
733
+ return this.callOwners.get(e);
734
+ }
735
+ releaseOwnedCalls(e) {
736
+ for (let [t, n] of [...this.callOwners.entries()]) {
737
+ if (n !== e) continue;
738
+ let r = this.calls.get(t);
739
+ if (r === void 0) {
740
+ this.callOwners.delete(t), this.ownerLostCalls.delete(t);
741
+ continue;
742
+ }
743
+ this.callOwners.delete(t);
744
+ let i = !r.canBeReclaimed();
745
+ i ? this.ownerLostCalls.add(t) : this.ownerLostCalls.delete(t), r.clearOwnerTabId({ lost: i }), this.emitOwnershipChanged({
746
+ callId: t,
747
+ state: i ? "owner-lost" : "released"
748
+ });
749
+ }
750
+ }
751
+ dispose(e = {}) {
752
+ if (this.disposeOperation !== void 0) return this.disposeOperation;
753
+ this.disposed = !0, this.operationGeneration += 1, this.automaticActiveTransition = void 0, this.activeOperationPromise = Promise.resolve(), this.events.clear();
754
+ try {
755
+ this.incomingUnsubscribe();
756
+ } catch {}
757
+ this.activeCallId = null;
758
+ let t = [...this.calls.values()];
759
+ this.calls.clear(), this.callSessions.clear(), this.callOwners.clear(), this.ownerLostCalls.clear();
760
+ let n = Promise.all(t.map(async (t) => {
761
+ let n;
762
+ try {
763
+ e.terminateCalls === !0 && t.state !== "ended" && t.state !== "failed" ? await t.hangup() : t.dispose();
764
+ } catch (e) {
765
+ n = e, t.dispose();
766
+ }
767
+ try {
768
+ await this.notifyCallTerminal(t.id);
769
+ } catch (e) {
770
+ n ??= e;
771
+ }
772
+ if (n !== void 0) throw n;
773
+ })).then(() => void 0);
774
+ return this.disposeOperation = n, n;
775
+ }
776
+ updateSession(e) {
777
+ this.disposed || (this.incomingSessionSnapshot = e);
778
+ }
779
+ async switchActiveCall(e, t) {
780
+ this.assertGeneration(t, e);
781
+ let n = this.requireCall(e), r = this.getActiveCall();
782
+ if (r?.id === n.id) return;
783
+ if (n.state !== "held" && n.state !== "active") throw this.callOperationError(e);
784
+ let i = n.state === "held";
785
+ try {
786
+ if (r !== void 0 && await r.hold(), this.assertGeneration(t, n.id), n.state === "held" && await n.resume(), this.assertGeneration(t, n.id), !this.isManagedCall(n) || n.state !== "active") throw this.callOperationError(n.id);
787
+ this.commitActive(n, t);
788
+ } catch (a) {
789
+ if (!this.isCurrentGeneration(t)) throw this.callOperationError(n.id, a);
790
+ if (r === void 0) throw this.callOperationError(e, a);
791
+ try {
792
+ let e = n.state === "active";
793
+ i && e && this.isManagedCall(n) && await n.hold(), this.assertGeneration(t, n.id), r.state === "held" && this.isManagedCall(r) && await r.resume(), this.assertGeneration(t, r.id), r.state === "active" && this.isManagedCall(r) && this.commitActive(r, t);
794
+ } catch (e) {
795
+ throw this.compensationError(r.id, n.id, a, e);
796
+ }
797
+ throw this.isManagedCall(r) && r.state === "active" && this.commitActive(r, t), this.callOperationError(n.id, {
798
+ operation: a,
799
+ restoredCallId: r.id
800
+ });
801
+ }
802
+ }
803
+ handleStateChanged(e, t, n) {
804
+ if (this.disposed) return;
805
+ let r = this.callSessions.get(e.id);
806
+ if (r !== void 0 && this.options.onCallStateChanged?.(e.id, r), this.events.emit("call.stateChanged", t), t.to === "active" && this.activeCallId !== e.id) {
807
+ let t = this.getActiveCall();
808
+ if (this.options.autoHoldPreviousCall === !0 && t !== void 0 && t.id !== e.id && t.state === "active") {
809
+ let n = this.operationGeneration;
810
+ this.enqueueActiveOperation((n) => this.switchAutomaticActiveCall(t, e, n)).catch((e) => {
811
+ this.isCurrentGeneration(n) && this.events.emit("error", { error: e });
812
+ });
813
+ } else this.commitActive(e);
814
+ }
815
+ t.to === "held" && this.activeCallId === e.id && this.automaticActiveTransition?.previous.id !== e.id && (this.activeCallId = null, this.events.emit("call.activeChanged", { callId: null })), (t.to === "ended" || t.to === "failed") && (this.calls.delete(e.id), this.callSessions.delete(e.id), this.callOwners.delete(e.id), this.ownerLostCalls.delete(e.id), this.activeCallId === e.id && this.automaticActiveTransition?.previous.id !== e.id && (this.activeCallId = null, this.events.emit("call.activeChanged", { callId: null })), this.notifyCallTerminal(e.id), t.to === "ended" ? this.events.emit("call.ended", {
816
+ callId: e.id,
817
+ reason: x(n)
818
+ }) : this.events.emit("call.failed", {
819
+ callId: e.id,
820
+ error: S(n, e.id)
821
+ }));
822
+ }
823
+ async switchAutomaticActiveCall(e, t, n) {
824
+ this.automaticActiveTransition = {
825
+ previous: e,
826
+ target: t
827
+ };
828
+ let r;
829
+ try {
830
+ if (this.assertGeneration(n, t.id), !this.isManagedCall(t) || t.state !== "active") return;
831
+ if (!this.isManagedCall(e) || e.state !== "active") {
832
+ this.commitActive(t, n);
833
+ return;
834
+ }
835
+ if (await e.hold(), this.assertGeneration(n, t.id), !this.isManagedCall(e)) {
836
+ this.isManagedCall(t) && t.state === "active" && this.commitActive(t, n);
837
+ return;
838
+ }
839
+ if (!this.isManagedCall(t) || t.state !== "active") r = /* @__PURE__ */ Error("target call is no longer active");
840
+ else {
841
+ this.commitActive(t, n);
842
+ return;
843
+ }
844
+ } catch (e) {
845
+ r = e;
846
+ } finally {
847
+ this.automaticActiveTransition?.target.id === t.id && (this.automaticActiveTransition = void 0);
848
+ }
849
+ if (!this.isCurrentGeneration(n)) return;
850
+ if (!this.isManagedCall(e)) {
851
+ this.isManagedCall(t) && t.state === "active" && this.commitActive(t, n);
852
+ return;
853
+ }
854
+ let i = await this.restoreAutomaticActiveCall(e, t, r, n);
855
+ if (this.isCurrentGeneration(n)) {
856
+ if (i.error !== void 0) throw i.error;
857
+ if (!this.isManagedCall(e)) {
858
+ this.isManagedCall(t) && t.state === "active" && this.commitActive(t, n);
859
+ return;
860
+ }
861
+ throw this.callOperationError(t.id, {
862
+ operation: r,
863
+ restoredCallId: e.id
864
+ });
865
+ }
866
+ }
867
+ async restoreAutomaticActiveCall(e, t, n, r) {
868
+ if (!this.isCurrentGeneration(r)) return {};
869
+ if (!this.isManagedCall(e)) return this.isManagedCall(t) && t.state === "active" && this.commitActive(t, r), {};
870
+ let i;
871
+ try {
872
+ this.isManagedCall(t) && t.state === "active" && await t.hold(), this.assertGeneration(r, t.id), this.isManagedCall(e) && e.state === "held" && await e.resume(), this.assertGeneration(r, e.id);
873
+ } catch (e) {
874
+ i = e;
875
+ }
876
+ return this.isCurrentGeneration(r) ? this.isManagedCall(e) ? i === void 0 ? (e.state === "active" && this.commitActive(e, r), {}) : { error: this.compensationError(e.id, t.id, n, i) } : (this.isManagedCall(t) && t.state === "active" && this.commitActive(t, r), {}) : {};
877
+ }
878
+ handleDisposed(e) {
879
+ this.disposed || (this.calls.delete(e.id), this.callSessions.delete(e.id), this.callOwners.delete(e.id), this.ownerLostCalls.delete(e.id), this.notifyCallTerminal(e.id), this.activeCallId === e.id && (this.activeCallId = null, this.events.emit("call.activeChanged", { callId: null })));
880
+ }
881
+ commitActive(e, t = this.operationGeneration) {
882
+ this.isCurrentGeneration(t) && this.isManagedCall(e) && e.state === "active" && this.activeCallId !== e.id && (this.activeCallId = e.id, this.events.emit("call.activeChanged", { callId: e.id }));
883
+ }
884
+ handleIncoming(t) {
885
+ if (this.disposed) return;
886
+ let n = v();
887
+ if (this.options.platform === "mobile-web") {
888
+ this.terminateUnsupportedIncoming(t), this.events.emit("error", { error: this.capabilityError(n) });
889
+ return;
890
+ }
891
+ let r = this.incomingSessionSnapshot;
892
+ if (r === void 0 || !r.policy.incomingEnabled || !this.effectiveCapabilities(r).has("inbound")) {
893
+ this.terminateUnsupportedIncoming(t), this.events.emit("error", { error: this.capabilityError(n) });
894
+ return;
895
+ }
896
+ let i = t.from ?? t.id;
897
+ if (this.calls.size + this.pendingDialCount >= this.callLimit(r)) {
898
+ this.terminateUnsupportedIncoming(t), this.events.emit("error", { error: new e("CALL_ALREADY_EXISTS", "call", !1, { callId: n }) });
899
+ return;
900
+ }
901
+ let a;
902
+ try {
903
+ a = new m({
904
+ id: n,
905
+ destination: i,
906
+ platform: this.options.platform,
907
+ incoming: !0,
908
+ capabilities: this.effectiveCapabilities(r),
909
+ session: t,
910
+ onStateChanged: (e, t) => this.handleStateChanged(a, e, t),
911
+ onError: (e) => this.events.emit("error", { error: e }),
912
+ onDisposed: () => this.handleDisposed(a)
913
+ });
914
+ } catch (e) {
915
+ this.events.emit("error", { error: this.callOperationError(n, e) });
916
+ return;
917
+ }
918
+ this.calls.set(a.id, a), this.callSessions.set(a.id, t), this.options.onCallCreated?.(a.id, t);
919
+ try {
920
+ a.beginIncoming(), this.events.emit("call.incoming", {
921
+ callId: a.id,
922
+ from: i
923
+ });
924
+ } catch (e) {
925
+ a.dispose(), this.events.emit("error", { error: this.callOperationError(a.id, e) });
926
+ }
927
+ }
928
+ terminateUnsupportedIncoming(e) {
929
+ try {
930
+ e.terminate();
931
+ } catch {}
932
+ }
933
+ async holdActiveCallForNewCall() {
934
+ if (this.options.autoHoldPreviousCall !== !0) return;
935
+ let e = this.getActiveCall();
936
+ if (e !== void 0 && e.state === "active") return await e.hold(), e;
937
+ }
938
+ enqueueActiveOperation(e) {
939
+ let t = this.operationGeneration, n = () => this.isCurrentGeneration(t) ? e(t) : Promise.reject(this.callOperationError("")), r = this.activeOperationPromise.then(n, n);
940
+ return this.activeOperationPromise = r.catch(() => void 0), r;
941
+ }
942
+ isManagedCall(e) {
943
+ return !this.disposed && this.calls.get(e.id) === e && e.state !== "ended" && e.state !== "failed";
944
+ }
945
+ isCurrentGeneration(e) {
946
+ return !this.disposed && this.operationGeneration === e;
947
+ }
948
+ assertGeneration(e, t) {
949
+ if (!this.isCurrentGeneration(e)) throw this.callOperationError(t ?? "");
950
+ }
951
+ effectiveCapabilities(e) {
952
+ let t = new Set(e.capabilities);
953
+ return this.options.platform === "mobile-web" && (t.delete("inbound"), t.delete("hold"), t.delete("blind_transfer")), t;
954
+ }
955
+ requireCapability(e, t, n) {
956
+ if (!this.effectiveCapabilities(e).has(t)) throw this.capabilityError(n);
957
+ }
958
+ requireCall(e) {
959
+ let t = this.calls.get(e);
960
+ if (t === void 0) throw this.callOperationError(e);
961
+ return t;
962
+ }
963
+ emitOwnershipChanged(e) {
964
+ this.events.emit("call.ownershipChanged", e);
965
+ }
966
+ notifyCallTerminal(e) {
967
+ let t = this.terminalOperations.get(e);
968
+ if (t !== void 0) return t;
969
+ if (this.terminalNotified.has(e)) return Promise.resolve();
970
+ this.terminalNotified.add(e);
971
+ let n;
972
+ try {
973
+ n = this.options.onCallTerminal?.(e);
974
+ } catch (t) {
975
+ this.events.emit("error", { error: this.callOperationError(e, t) });
976
+ let n = Promise.reject(this.callOperationError(e, t));
977
+ return this.terminalOperations.set(e, n), n.catch(() => void 0), n;
978
+ }
979
+ let r = Promise.resolve(n).catch((t) => {
980
+ throw this.events.emit("error", { error: this.callOperationError(e, t) }), t;
981
+ });
982
+ return this.terminalOperations.set(e, r), r.catch(() => void 0), r;
983
+ }
984
+ assertNotDisposed() {
985
+ if (this.disposed) throw new e("SDK_ALREADY_DISPOSED", "internal", !1);
986
+ }
987
+ callOperationError(t, n) {
988
+ return new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, {
989
+ callId: t,
990
+ cause: n
991
+ });
992
+ }
993
+ capabilityError(t) {
994
+ return new e("CAPABILITY_NOT_SUPPORTED", "capability", !1, { callId: t });
995
+ }
996
+ compensationError(e, t, n, r) {
997
+ return this.callOperationError(e, {
998
+ operation: n,
999
+ rollback: r,
1000
+ originalCallId: e,
1001
+ targetCallId: t
1002
+ });
1003
+ }
1004
+ callLimit(e) {
1005
+ let t = this.options.platform === "mobile-web" ? 1 : 2, n = this.options.maxConcurrentCalls ?? t;
1006
+ return Math.min(t, Math.max(1, n), Math.max(1, e.policy.maxConcurrentCalls));
1007
+ }
1008
+ dialOptions(e, t, n) {
1009
+ return {
1010
+ iceServers: t.iceServers,
1011
+ extraHeaders: [`X-XCall-Call-ID: ${e}`, `X-XCall-Session-ID: ${t.sessionId}`],
1012
+ ...n === void 0 ? {} : { type: n }
1013
+ };
1014
+ }
1015
+ dialError(t, n) {
1016
+ return t instanceof e ? new e(t.code, t.category, t.retryable, {
1017
+ requestId: t.requestId,
1018
+ callId: n,
1019
+ cause: t.cause ?? t
1020
+ }) : new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, {
1021
+ callId: n,
1022
+ cause: t
1023
+ });
1024
+ }
1025
+ }, b = class {
1026
+ handlers = /* @__PURE__ */ new Map();
1027
+ on(e, t) {
1028
+ let n = this.handlers.get(e) ?? /* @__PURE__ */ new Set(), r = t;
1029
+ n.add(r), this.handlers.set(e, n);
1030
+ let i = !0;
1031
+ return () => {
1032
+ i && (i = !1, n.delete(r));
1033
+ };
1034
+ }
1035
+ emit(e, t) {
1036
+ let n = this.handlers.get(e);
1037
+ n !== void 0 && [...n].forEach((e) => {
1038
+ try {
1039
+ e(t);
1040
+ } catch {}
1041
+ });
1042
+ }
1043
+ listenerCount() {
1044
+ return [...this.handlers.values()].reduce((e, t) => e + t.size, 0);
1045
+ }
1046
+ clear() {
1047
+ this.handlers.clear();
1048
+ }
1049
+ };
1050
+ function x(e) {
1051
+ if (typeof e != "object" || !e || !("reason" in e)) return "ended";
1052
+ let t = e.reason;
1053
+ return typeof t == "string" && t !== "" ? t : "ended";
1054
+ }
1055
+ function S(t, n) {
1056
+ if (t instanceof e) return new e(t.code, t.category, t.retryable, {
1057
+ requestId: t.requestId,
1058
+ callId: n,
1059
+ cause: t.cause ?? t
1060
+ });
1061
+ if (typeof t == "object" && t && "error" in t) {
1062
+ let r = t.error;
1063
+ if (r instanceof e) return new e(r.code, r.category, r.retryable, {
1064
+ requestId: r.requestId,
1065
+ callId: n,
1066
+ cause: r.cause ?? r
1067
+ });
1068
+ if (r instanceof Error) return new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, {
1069
+ callId: n,
1070
+ cause: r
1071
+ });
1072
+ }
1073
+ return new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, {
1074
+ callId: n,
1075
+ cause: t
1076
+ });
1077
+ }
1078
+ //#endregion
1079
+ //#region src/media/DeviceManager.ts
1080
+ var C = class {
1081
+ mediaDevices;
1082
+ createAudioElement;
1083
+ outputCapability;
1084
+ outputDeviceId;
1085
+ outputGeneration = 0;
1086
+ outputTail;
1087
+ constructor(e = {}) {
1088
+ this.mediaDevices = e.mediaDevices === null ? void 0 : e.mediaDevices ?? w(), this.createAudioElement = e.createAudioElement;
1089
+ }
1090
+ async requestPermission(e = {}) {
1091
+ let t = this.requireMediaDevices(), n;
1092
+ try {
1093
+ n = await t.getUserMedia({ audio: e });
1094
+ } catch (e) {
1095
+ throw E(e);
1096
+ }
1097
+ T(n);
1098
+ }
1099
+ async getDevices() {
1100
+ if (this.mediaDevices === void 0) return [];
1101
+ try {
1102
+ return (await this.mediaDevices.enumerateDevices()).filter((e) => e.kind === "audioinput" || e.kind === "audiooutput" && this.supportsOutputSelection());
1103
+ } catch (e) {
1104
+ throw te(e);
1105
+ }
1106
+ }
1107
+ getCapabilities() {
1108
+ return {
1109
+ input: this.mediaDevices !== void 0,
1110
+ output: this.supportsOutputSelection()
1111
+ };
1112
+ }
1113
+ supportsOutputSelection() {
1114
+ if (this.outputCapability !== void 0) return this.outputCapability;
1115
+ let e = this.createAudioElementSafely();
1116
+ return this.outputCapability = e !== void 0 && typeof e.setSinkId == "function", this.outputCapability;
1117
+ }
1118
+ async setOutputDevice(t, n) {
1119
+ if (!this.supportsOutputSelection()) throw new e("CAPABILITY_NOT_SUPPORTED", "capability", !1);
1120
+ this.outputDeviceId = t;
1121
+ let r = ++this.outputGeneration;
1122
+ n !== void 0 && await this.enqueueOutput(async () => {
1123
+ r === this.outputGeneration && await this.applyOutputDevice(t, n);
1124
+ });
1125
+ }
1126
+ async applyConfiguredOutputDevice(e) {
1127
+ if (this.outputDeviceId === void 0 || e === void 0) return;
1128
+ let t = this.outputDeviceId, n = this.outputGeneration;
1129
+ await this.enqueueOutput(async () => {
1130
+ n === this.outputGeneration && await this.applyOutputDevice(t, e);
1131
+ });
1132
+ }
1133
+ getOutputDeviceId() {
1134
+ return this.outputDeviceId;
1135
+ }
1136
+ async applyOutputDevice(t, n) {
1137
+ let r = n;
1138
+ if (typeof r.setSinkId != "function") throw new e("CAPABILITY_NOT_SUPPORTED", "capability", !1);
1139
+ try {
1140
+ await r.setSinkId(t);
1141
+ } catch (e) {
1142
+ throw ne(e);
1143
+ }
1144
+ }
1145
+ enqueueOutput(e) {
1146
+ let t = this.outputTail, n = t === void 0 ? e() : t.then(e, e), r = n.catch(() => void 0);
1147
+ return this.outputTail = r, r.then(() => {
1148
+ this.outputTail === r && (this.outputTail = void 0);
1149
+ }), n;
1150
+ }
1151
+ async openInputStream(e) {
1152
+ let t = this.requireMediaDevices();
1153
+ try {
1154
+ return await t.getUserMedia({ audio: { deviceId: { exact: e } } });
1155
+ } catch (e) {
1156
+ throw ee(e);
1157
+ }
1158
+ }
1159
+ requireMediaDevices() {
1160
+ if (this.mediaDevices === void 0) throw new e("CAPABILITY_NOT_SUPPORTED", "capability", !1);
1161
+ return this.mediaDevices;
1162
+ }
1163
+ createAudioElementSafely() {
1164
+ if (this.createAudioElement !== void 0) try {
1165
+ return this.createAudioElement();
1166
+ } catch {
1167
+ return;
1168
+ }
1169
+ if (typeof document < "u") try {
1170
+ return document.createElement("audio");
1171
+ } catch {
1172
+ return;
1173
+ }
1174
+ }
1175
+ };
1176
+ function w() {
1177
+ return globalThis.navigator?.mediaDevices;
1178
+ }
1179
+ function T(e) {
1180
+ let t;
1181
+ try {
1182
+ t = e.getTracks();
1183
+ } catch {
1184
+ return;
1185
+ }
1186
+ t.forEach((e) => {
1187
+ try {
1188
+ e.stop();
1189
+ } catch {}
1190
+ });
1191
+ }
1192
+ function ee(t) {
1193
+ let n = D(t);
1194
+ return n === "NotFoundError" || n === "OverconstrainedError" ? new e("MEDIA_DEVICE_NOT_FOUND", "media", !1, { cause: t }) : n === "NotReadableError" || n === "AbortError" ? new e("MEDIA_DEVICE_IN_USE", "media", !0, { cause: t }) : n === "NotAllowedError" || n === "SecurityError" ? new e("MEDIA_PERMISSION_DENIED", "media", !1, { cause: t }) : new e("SDK_INTERNAL_ERROR", "internal", !1, { cause: t });
1195
+ }
1196
+ function E(t) {
1197
+ let n = D(t);
1198
+ return n === "NotFoundError" || n === "OverconstrainedError" ? new e("MEDIA_DEVICE_NOT_FOUND", "media", !1, { cause: t }) : n === "NotReadableError" || n === "AbortError" ? new e("MEDIA_DEVICE_IN_USE", "media", !0, { cause: t }) : n === "NotAllowedError" || n === "SecurityError" ? new e("MEDIA_PERMISSION_DENIED", "media", !1, { cause: t }) : new e("SDK_INTERNAL_ERROR", "internal", !1, { cause: t });
1199
+ }
1200
+ function te(t) {
1201
+ let n = D(t);
1202
+ return n === "NotFoundError" ? new e("MEDIA_DEVICE_NOT_FOUND", "media", !1, { cause: t }) : n === "NotAllowedError" || n === "SecurityError" ? new e("MEDIA_PERMISSION_DENIED", "media", !1, { cause: t }) : n === "AbortError" || n === "NotReadableError" ? new e("MEDIA_DEVICE_IN_USE", "media", !0, { cause: t }) : new e("SDK_INTERNAL_ERROR", "internal", !1, { cause: t });
1203
+ }
1204
+ function ne(t) {
1205
+ let n = D(t);
1206
+ return n === "NotFoundError" ? new e("MEDIA_DEVICE_NOT_FOUND", "media", !1, { cause: t }) : n === "NotAllowedError" || n === "SecurityError" ? new e("MEDIA_PERMISSION_DENIED", "media", !1, { cause: t }) : n === "AbortError" || n === "NotReadableError" ? new e("MEDIA_DEVICE_IN_USE", "media", !0, { cause: t }) : new e("SDK_INTERNAL_ERROR", "internal", !1, { cause: t });
1207
+ }
1208
+ function D(e) {
1209
+ if (typeof e != "object" || !e || !("name" in e)) return;
1210
+ let t = e.name;
1211
+ return typeof t == "string" ? t : void 0;
1212
+ }
1213
+ //#endregion
1214
+ //#region src/media/RemoteAudio.ts
1215
+ var O = class {
1216
+ createAudioElement;
1217
+ bindings = /* @__PURE__ */ new Map();
1218
+ audioOwners = /* @__PURE__ */ new Map();
1219
+ trackOwners = /* @__PURE__ */ new Map();
1220
+ generations = /* @__PURE__ */ new Map();
1221
+ pendingPlays = /* @__PURE__ */ new Map();
1222
+ constructor(e = k) {
1223
+ this.createAudioElement = e;
1224
+ }
1225
+ async bind(t, n) {
1226
+ let r = this.bindings.get(t);
1227
+ if (r?.stream === n) return;
1228
+ let i = A(t, n), a;
1229
+ try {
1230
+ a = this.createAudioElement();
1231
+ } catch (n) {
1232
+ throw j(i, this.trackOwners), new e("CAPABILITY_NOT_SUPPORTED", "capability", !1, {
1233
+ callId: t,
1234
+ cause: n
1235
+ });
1236
+ }
1237
+ let o = this.audioOwners.get(a);
1238
+ if (o !== void 0 && o !== t) throw j(i, this.trackOwners), new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, { callId: t });
1239
+ try {
1240
+ a.autoplay = !0, a.playsInline = !0;
1241
+ } catch (n) {
1242
+ throw j(i, this.trackOwners), new e("SDK_INTERNAL_ERROR", "internal", !1, {
1243
+ callId: t,
1244
+ cause: n
1245
+ });
1246
+ }
1247
+ try {
1248
+ a.srcObject = n;
1249
+ } catch (n) {
1250
+ throw j(i, this.trackOwners), new e("SDK_INTERNAL_ERROR", "internal", !1, {
1251
+ callId: t,
1252
+ cause: n
1253
+ });
1254
+ }
1255
+ this.acquireTracks(i), r !== void 0 && this.releaseBinding(r, r.audio !== a);
1256
+ let s = this.nextGeneration(t);
1257
+ this.audioOwners.set(a, t);
1258
+ let c = {
1259
+ callId: t,
1260
+ audio: a,
1261
+ stream: n,
1262
+ tracks: i,
1263
+ generation: s
1264
+ };
1265
+ this.bindings.set(t, c), this.beginPlay(t);
1266
+ try {
1267
+ await a.play();
1268
+ } catch (n) {
1269
+ if (!this.isCurrent(t, s)) return;
1270
+ throw new e("MEDIA_PLAYBACK_BLOCKED", "media", !1, {
1271
+ callId: t,
1272
+ cause: n
1273
+ });
1274
+ } finally {
1275
+ this.finishPlay(t);
1276
+ }
1277
+ this.isCurrent(t, s);
1278
+ }
1279
+ async play(t) {
1280
+ let n = this.bindings.get(t);
1281
+ if (n === void 0) throw new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, { callId: t });
1282
+ let r = n.generation;
1283
+ this.beginPlay(t);
1284
+ try {
1285
+ await n.audio.play();
1286
+ } catch (n) {
1287
+ if (!this.isCurrent(t, r)) return;
1288
+ throw new e("MEDIA_PLAYBACK_BLOCKED", "media", !1, {
1289
+ callId: t,
1290
+ cause: n
1291
+ });
1292
+ } finally {
1293
+ this.finishPlay(t);
1294
+ }
1295
+ this.isCurrent(t, r);
1296
+ }
1297
+ getAudioElement(e) {
1298
+ return this.bindings.get(e)?.audio;
1299
+ }
1300
+ getResourceCounts() {
1301
+ return {
1302
+ tracks: this.trackOwners.size,
1303
+ audioElements: this.audioOwners.size
1304
+ };
1305
+ }
1306
+ release(e) {
1307
+ this.nextGeneration(e);
1308
+ let t = this.bindings.get(e);
1309
+ t !== void 0 && this.releaseBinding(t), this.cleanupGeneration(e);
1310
+ }
1311
+ releaseAll() {
1312
+ [...this.bindings.keys()].forEach((e) => this.release(e));
1313
+ }
1314
+ releaseBinding(e, t = !0) {
1315
+ if (this.bindings.get(e.callId) === e && this.bindings.delete(e.callId), this.audioOwners.get(e.audio) === e.callId && this.audioOwners.delete(e.audio), t) try {
1316
+ e.audio.srcObject = null;
1317
+ } catch {}
1318
+ e.tracks.forEach((e) => this.releaseTrack(e));
1319
+ }
1320
+ acquireTracks(e) {
1321
+ e.forEach((e) => this.trackOwners.set(e, (this.trackOwners.get(e) ?? 0) + 1));
1322
+ }
1323
+ releaseTrack(e) {
1324
+ let t = this.trackOwners.get(e);
1325
+ if (t === void 0 || t <= 1) {
1326
+ this.trackOwners.delete(e), N(e);
1327
+ return;
1328
+ }
1329
+ this.trackOwners.set(e, t - 1);
1330
+ }
1331
+ beginPlay(e) {
1332
+ this.pendingPlays.set(e, (this.pendingPlays.get(e) ?? 0) + 1);
1333
+ }
1334
+ finishPlay(e) {
1335
+ let t = this.pendingPlays.get(e) ?? 0;
1336
+ t <= 1 ? this.pendingPlays.delete(e) : this.pendingPlays.set(e, t - 1), this.cleanupGeneration(e);
1337
+ }
1338
+ nextGeneration(e) {
1339
+ let t = (this.generations.get(e) ?? 0) + 1;
1340
+ return this.generations.set(e, t), t;
1341
+ }
1342
+ cleanupGeneration(e) {
1343
+ !this.bindings.has(e) && !this.pendingPlays.has(e) && this.generations.delete(e);
1344
+ }
1345
+ isCurrent(e, t) {
1346
+ return this.generations.get(e) === t && this.bindings.get(e)?.generation === t;
1347
+ }
1348
+ };
1349
+ function k() {
1350
+ if (typeof document > "u") throw new e("CAPABILITY_NOT_SUPPORTED", "capability", !1);
1351
+ return document.createElement("audio");
1352
+ }
1353
+ function A(t, n) {
1354
+ try {
1355
+ return [...new Set(n.getAudioTracks())].filter((e) => e.kind === "audio");
1356
+ } catch (r) {
1357
+ try {
1358
+ return [...new Set(n.getTracks())].filter((e) => e.kind === "audio");
1359
+ } catch (i) {
1360
+ throw M(n), new e("SDK_INTERNAL_ERROR", "internal", !1, {
1361
+ callId: t,
1362
+ cause: r ?? i
1363
+ });
1364
+ }
1365
+ }
1366
+ }
1367
+ function j(e, t) {
1368
+ e.forEach((e) => {
1369
+ (t.get(e) ?? 0) === 0 && N(e);
1370
+ });
1371
+ }
1372
+ function M(e) {
1373
+ try {
1374
+ [...new Set(e.getTracks())].filter((e) => e.kind === "audio").forEach(N);
1375
+ } catch {}
1376
+ }
1377
+ function N(e) {
1378
+ try {
1379
+ e.stop();
1380
+ } catch {}
1381
+ }
1382
+ //#endregion
1383
+ //#region src/media/MediaManager.ts
1384
+ var P = class {
1385
+ deviceManager;
1386
+ remoteAudio;
1387
+ getActiveCall;
1388
+ createRemoteStream;
1389
+ calls = /* @__PURE__ */ new Map();
1390
+ resources = /* @__PURE__ */ new Set();
1391
+ inputOperations = /* @__PURE__ */ new Map();
1392
+ senderQueues = /* @__PURE__ */ new Map();
1393
+ releaseOperations = /* @__PURE__ */ new Map();
1394
+ callReleaseOperations = /* @__PURE__ */ new Map();
1395
+ releaseErrors = /* @__PURE__ */ new WeakMap();
1396
+ releaseAllOperation;
1397
+ disposeOperation;
1398
+ disposing = !1;
1399
+ disposed = !1;
1400
+ constructor(e = {}) {
1401
+ let t = {
1402
+ mediaDevices: e.mediaDevices,
1403
+ createAudioElement: e.createAudioElement
1404
+ };
1405
+ this.deviceManager = new C(t), this.remoteAudio = new O(e.createAudioElement), this.getActiveCall = e.getActiveCall, this.createRemoteStream = e.createRemoteStream ?? V;
1406
+ }
1407
+ requestPermission(e) {
1408
+ return this.assertNotDisposed(), this.deviceManager.requestPermission(e);
1409
+ }
1410
+ getDevices() {
1411
+ return this.assertNotDisposed(), this.deviceManager.getDevices();
1412
+ }
1413
+ getCapabilities() {
1414
+ return this.assertNotDisposed(), this.deviceManager.getCapabilities();
1415
+ }
1416
+ supportsOutputSelection() {
1417
+ return this.assertNotDisposed(), this.deviceManager.supportsOutputSelection();
1418
+ }
1419
+ registerCallMedia(e, t) {
1420
+ this.assertNotDisposed();
1421
+ let n = this.calls.get(e);
1422
+ n !== void 0 && this.releaseResource(n).catch((e) => {
1423
+ this.releaseErrors.set(n, e);
1424
+ });
1425
+ let r = F(t) ? t : { peerConnection: t }, i = {
1426
+ callId: e,
1427
+ peerConnection: r.peerConnection,
1428
+ senders: /* @__PURE__ */ new Map(),
1429
+ localTracks: /* @__PURE__ */ new Set(),
1430
+ pendingTracks: /* @__PURE__ */ new Set(),
1431
+ generation: 1,
1432
+ released: !1,
1433
+ peerClosed: !1
1434
+ };
1435
+ if (this.captureSenders(i, r.getSenderKind), this.resources.add(i), r.localTracks?.forEach((e) => {
1436
+ e.kind === "audio" && i.localTracks.add(e);
1437
+ }), this.calls.set(e, i), r.trackSource !== void 0) try {
1438
+ i.trackSourceUnsubscribe = r.trackSource.onTrack((e) => this.handleTrackEvent(i, e));
1439
+ } catch {}
1440
+ return async () => {
1441
+ let e = this.releaseOperations.get(i);
1442
+ if (e !== void 0) await e;
1443
+ else if (this.releaseErrors.has(i)) throw this.releaseErrors.get(i);
1444
+ else await this.releaseResource(i);
1445
+ let t = this.releaseErrors.get(i);
1446
+ if (t !== void 0) throw t;
1447
+ };
1448
+ }
1449
+ async setInputDevice(e, t) {
1450
+ this.assertNotDisposed();
1451
+ let n = t ?? this.getActiveCall?.();
1452
+ this.assertActiveCall(n), this.assertDeviceSelectionCapability(n);
1453
+ let r = this.ensureCallMedia(n), i = (this.inputOperations.get(n.callId) ?? Promise.resolve()).then(() => this.performInputSwitch(e, n, r), () => this.performInputSwitch(e, n, r));
1454
+ this.inputOperations.set(n.callId, i);
1455
+ try {
1456
+ await i;
1457
+ } finally {
1458
+ this.inputOperations.get(n.callId) === i && this.inputOperations.delete(n.callId);
1459
+ }
1460
+ }
1461
+ setOutputDevice(e, t) {
1462
+ this.assertNotDisposed();
1463
+ let n = t ?? this.getActiveCall?.()?.callId, r = n === void 0 ? void 0 : this.remoteAudio.getAudioElement(n);
1464
+ return this.deviceManager.setOutputDevice(e, r);
1465
+ }
1466
+ async bindRemoteTrack(e, t) {
1467
+ this.assertNotDisposed();
1468
+ let n;
1469
+ try {
1470
+ await this.remoteAudio.bind(e, t);
1471
+ } catch (e) {
1472
+ n = e;
1473
+ }
1474
+ let r;
1475
+ try {
1476
+ await this.deviceManager.applyConfiguredOutputDevice(this.remoteAudio.getAudioElement(e));
1477
+ } catch (e) {
1478
+ r = e;
1479
+ }
1480
+ if (n !== void 0) throw n;
1481
+ if (r !== void 0) throw r;
1482
+ }
1483
+ playRemoteAudio(e) {
1484
+ return this.assertNotDisposed(), this.remoteAudio.play(e);
1485
+ }
1486
+ getResourceCounts() {
1487
+ let e = /* @__PURE__ */ new Set();
1488
+ this.resources.forEach((t) => {
1489
+ t.localTracks.forEach((t) => e.add(t)), t.pendingTracks.forEach((t) => e.add(t));
1490
+ });
1491
+ let t = this.remoteAudio.getResourceCounts();
1492
+ return {
1493
+ listeners: [...this.resources].filter((e) => e.trackSourceUnsubscribe !== void 0).length,
1494
+ tracks: e.size + t.tracks,
1495
+ peerConnections: this.resources.size,
1496
+ audioElements: t.audioElements
1497
+ };
1498
+ }
1499
+ releaseResource(t) {
1500
+ let n = this.releaseOperations.get(t);
1501
+ if (n !== void 0) return n;
1502
+ if (!this.resources.has(t)) return Promise.resolve();
1503
+ let r = t.callId;
1504
+ this.remoteAudio.release(r), this.releaseErrors.delete(t), this.calls.get(r) === t && this.calls.delete(r), t.generation += 1, t.released = !0, this.unsubscribeTrackSource(t);
1505
+ let i = /* @__PURE__ */ new Set([...t.localTracks, ...t.pendingTracks]), a = [...t.senders.values()].filter((e) => e.audio).map((e) => ({
1506
+ senderResource: e,
1507
+ promise: this.enqueueSender(t, e, () => L(e.sender), !0)
1508
+ })), o = Promise.all(a.map(async (e) => {
1509
+ try {
1510
+ return await e.promise, {
1511
+ senderResource: e.senderResource,
1512
+ cause: void 0
1513
+ };
1514
+ } catch (t) {
1515
+ return {
1516
+ senderResource: e.senderResource,
1517
+ cause: t
1518
+ };
1519
+ }
1520
+ })).then(async (n) => {
1521
+ let a = /* @__PURE__ */ new Set(), o = [];
1522
+ if (n.forEach((e) => {
1523
+ if (e.cause !== void 0) {
1524
+ o.push(e.cause);
1525
+ let t = I(e.senderResource.sender);
1526
+ t?.kind === "audio" && a.add(t);
1527
+ return;
1528
+ }
1529
+ let t = I(e.senderResource.sender);
1530
+ t?.kind === "audio" && i.add(t);
1531
+ }), i.forEach((e) => {
1532
+ a.has(e) || B(e);
1533
+ }), o.length > 0) throw t.localTracks.clear(), t.pendingTracks.clear(), a.forEach((e) => t.localTracks.add(e)), new e("SDK_INTERNAL_ERROR", "internal", !0, {
1534
+ callId: r,
1535
+ cause: o[0]
1536
+ });
1537
+ if (!t.peerClosed && t.peerConnection.close !== void 0) try {
1538
+ await t.peerConnection.close(), t.peerClosed = !0;
1539
+ } catch (n) {
1540
+ let i = [...t.senders.values()].map((e) => I(e.sender)).find((e) => e?.kind === "audio");
1541
+ throw t.localTracks.clear(), t.pendingTracks.clear(), i != null && t.localTracks.add(i), new e("SDK_INTERNAL_ERROR", "internal", !0, {
1542
+ callId: r,
1543
+ cause: n
1544
+ });
1545
+ }
1546
+ t.localTracks.clear(), t.pendingTracks.clear(), t.senders.clear(), this.resources.delete(t), this.releaseUnusedSenderQueues();
1547
+ }).catch((e) => {
1548
+ throw this.releaseErrors.set(t, e), this.calls.get(r) === void 0 && this.calls.set(r, t), e;
1549
+ }).finally(() => {
1550
+ this.releaseOperations.get(t) === o && this.releaseOperations.delete(t);
1551
+ });
1552
+ return this.releaseOperations.set(t, o), o;
1553
+ }
1554
+ releaseCall(e) {
1555
+ let t = this.callReleaseOperations.get(e);
1556
+ if (t !== void 0) return t;
1557
+ let n = [...this.resources].filter((t) => t.callId === e);
1558
+ if (n.length === 0) return Promise.resolve();
1559
+ let r = Promise.all(n.map(async (e) => {
1560
+ try {
1561
+ return await this.releaseResource(e), { cause: void 0 };
1562
+ } catch (e) {
1563
+ return { cause: e };
1564
+ }
1565
+ })).then((e) => {
1566
+ let t = e.find((e) => e.cause !== void 0)?.cause;
1567
+ if (t !== void 0) throw t;
1568
+ }).finally(() => {
1569
+ this.callReleaseOperations.get(e) === r && this.callReleaseOperations.delete(e);
1570
+ });
1571
+ return this.callReleaseOperations.set(e, r), r;
1572
+ }
1573
+ releaseAll() {
1574
+ if (this.releaseAllOperation !== void 0) return this.releaseAllOperation;
1575
+ this.remoteAudio.releaseAll();
1576
+ let e = new Set([...this.resources].map((e) => e.callId)), t = Promise.all([...e].map(async (e) => {
1577
+ try {
1578
+ return await this.releaseCall(e), { cause: void 0 };
1579
+ } catch (e) {
1580
+ return { cause: e };
1581
+ }
1582
+ })).then((e) => {
1583
+ let t = e.find((e) => e.cause !== void 0)?.cause;
1584
+ if (t !== void 0) throw t;
1585
+ }).finally(() => {
1586
+ this.releaseAllOperation === t && (this.releaseAllOperation = void 0);
1587
+ });
1588
+ return this.releaseAllOperation = t, t;
1589
+ }
1590
+ dispose() {
1591
+ if (this.disposeOperation !== void 0) return this.disposeOperation;
1592
+ this.disposing = !0;
1593
+ let e = this.releaseAll(), t = this.waitForInputOperations(), n = Promise.allSettled([e, t]).then((e) => {
1594
+ let t = e.find((e) => e.status === "rejected");
1595
+ if (t?.status === "rejected") throw t.reason;
1596
+ this.inputOperations.clear(), this.disposed = !0, this.disposing = !1;
1597
+ }).finally(() => {
1598
+ this.disposeOperation === n && !this.disposed && (this.disposeOperation = void 0), !this.disposed && this.disposeOperation === void 0 && (this.disposing = !1);
1599
+ });
1600
+ return this.disposeOperation = n, n;
1601
+ }
1602
+ async waitForInputOperations() {
1603
+ let e = [...this.inputOperations.values()];
1604
+ e.length !== 0 && await Promise.allSettled(e);
1605
+ }
1606
+ async performInputSwitch(t, n, r) {
1607
+ if (this.assertActiveCall(n), this.assertDeviceSelectionCapability(n), !this.isCurrentResource(r) || n.peerConnection !== r.peerConnection) throw this.callOperationError(n.callId);
1608
+ let i = this.findAudioSender(r), a = I(i.sender), o = r.generation, s = await this.deviceManager.openInputStream(t), c;
1609
+ try {
1610
+ c = s.getTracks();
1611
+ } catch (t) {
1612
+ throw R(s), new e("SDK_INTERNAL_ERROR", "internal", !1, {
1613
+ callId: n.callId,
1614
+ cause: t
1615
+ });
1616
+ }
1617
+ let l;
1618
+ try {
1619
+ l = s.getAudioTracks();
1620
+ } catch (t) {
1621
+ throw z(c), new e("SDK_INTERNAL_ERROR", "internal", !1, {
1622
+ callId: n.callId,
1623
+ cause: t
1624
+ });
1625
+ }
1626
+ let u = l[0];
1627
+ if (u === void 0) throw z(c), new e("MEDIA_DEVICE_NOT_FOUND", "media", !1, { callId: n.callId });
1628
+ if (!this.canCommitInputSwitch(n, r, i, a, o)) throw z(c), this.callOperationError(n.callId);
1629
+ c.forEach((e) => r.pendingTracks.add(e)), r.pendingTracks.add(u);
1630
+ try {
1631
+ await this.enqueueSender(r, i, () => i.sender.replaceTrack(u));
1632
+ } catch (t) {
1633
+ throw r.released ? this.callOperationError(n.callId) : (r.released || (c.forEach((e) => r.pendingTracks.delete(e)), r.pendingTracks.delete(u), await this.rollbackSender(r, i, a, u), z(c)), new e("MEDIA_DEVICE_IN_USE", "media", !0, {
1634
+ callId: n.callId,
1635
+ cause: t
1636
+ }));
1637
+ }
1638
+ if (!this.canCommitInputSwitch(n, r, i, u, o)) {
1639
+ if (!r.released) try {
1640
+ await this.enqueueSender(r, i, () => I(i.sender) === u ? L(i.sender) : Promise.resolve()), c.forEach((e) => r.pendingTracks.delete(e)), r.pendingTracks.delete(u), z(c);
1641
+ } catch (t) {
1642
+ throw new e("SDK_INTERNAL_ERROR", "internal", !0, {
1643
+ callId: n.callId,
1644
+ cause: t
1645
+ });
1646
+ }
1647
+ throw this.callOperationError(n.callId);
1648
+ }
1649
+ c.forEach((e) => r.pendingTracks.delete(e)), r.pendingTracks.delete(u), r.localTracks.add(u), a !== null && a !== u && (r.localTracks.delete(a), B(a)), c.forEach((e) => {
1650
+ e !== u && B(e);
1651
+ });
1652
+ }
1653
+ ensureCallMedia(e) {
1654
+ let t = this.calls.get(e.callId);
1655
+ if (t !== void 0 && t.peerConnection === e.peerConnection) return t;
1656
+ if (e.peerConnection === void 0) throw this.capabilityError(e.callId);
1657
+ this.registerCallMedia(e.callId, e.peerConnection);
1658
+ let n = this.calls.get(e.callId);
1659
+ if (n === void 0) throw this.callOperationError(e.callId);
1660
+ return n;
1661
+ }
1662
+ captureSenders(t, n) {
1663
+ let r;
1664
+ try {
1665
+ r = t.peerConnection.getSenders();
1666
+ } catch (n) {
1667
+ throw new e("SDK_INTERNAL_ERROR", "internal", !1, {
1668
+ callId: t.callId,
1669
+ cause: n
1670
+ });
1671
+ }
1672
+ r.forEach((r) => {
1673
+ let i = I(r), a;
1674
+ try {
1675
+ a = n?.(r) ?? r.senderKind ?? r.kind;
1676
+ } catch (n) {
1677
+ throw new e("SDK_INTERNAL_ERROR", "internal", !1, {
1678
+ callId: t.callId,
1679
+ cause: n
1680
+ });
1681
+ }
1682
+ t.senders.set(r, {
1683
+ sender: r,
1684
+ audio: a === "audio" || a === void 0 && i?.kind === "audio",
1685
+ queue: this.senderQueues.get(r) ?? this.createSenderQueue(r)
1686
+ }), i?.kind === "audio" && t.localTracks.add(i);
1687
+ });
1688
+ }
1689
+ findAudioSender(e) {
1690
+ let t = [...e.senders.values()].find((e) => e.audio && (I(e.sender)?.kind === "audio" || I(e.sender) === null));
1691
+ if (t === void 0) throw this.capabilityError(e.callId);
1692
+ return t;
1693
+ }
1694
+ handleTrackEvent(e, t) {
1695
+ if (!this.isCurrentResource(e) || t.track.kind !== "audio") return;
1696
+ let n = t.streams[0] ?? this.createRemoteStream(t.track);
1697
+ n !== void 0 && this.bindRemoteTrack(e.callId, n).catch(() => void 0);
1698
+ }
1699
+ canCommitInputSwitch(e, t, n, r, i) {
1700
+ if (this.disposed || !this.isCurrentResource(t, i) || e.state !== "active" || e.peerConnection !== t.peerConnection || !t.senders.has(n.sender)) return !1;
1701
+ try {
1702
+ if (!t.peerConnection.getSenders().includes(n.sender)) return !1;
1703
+ } catch {
1704
+ return !1;
1705
+ }
1706
+ return I(n.sender) === r;
1707
+ }
1708
+ enqueueSender(e, t, n, r = !1) {
1709
+ t.queue.pending += 1;
1710
+ let i = t.queue.chain.then(async () => {
1711
+ if (e.released && !r) throw this.callOperationError(e.callId);
1712
+ return n();
1713
+ }, async () => {
1714
+ if (e.released && !r) throw this.callOperationError(e.callId);
1715
+ return n();
1716
+ }), a = i.finally(() => {
1717
+ --t.queue.pending;
1718
+ });
1719
+ return t.queue.chain = a.catch(() => void 0), i;
1720
+ }
1721
+ createSenderQueue(e) {
1722
+ let t = {
1723
+ chain: Promise.resolve(),
1724
+ pending: 0
1725
+ };
1726
+ return this.senderQueues.set(e, t), t;
1727
+ }
1728
+ releaseUnusedSenderQueues() {
1729
+ let e = /* @__PURE__ */ new Set();
1730
+ this.resources.forEach((t) => t.senders.forEach((t) => e.add(t.sender))), this.senderQueues.forEach((t, n) => {
1731
+ t.pending === 0 && !e.has(n) && this.senderQueues.delete(n);
1732
+ });
1733
+ }
1734
+ async rollbackSender(e, t, n, r) {
1735
+ e.released || I(t.sender) !== r || await this.enqueueSender(e, t, () => t.sender.replaceTrack(n)).catch(() => void 0);
1736
+ }
1737
+ isCurrentResource(e, t = e.generation) {
1738
+ return !this.disposed && this.calls.get(e.callId) === e && e.generation === t;
1739
+ }
1740
+ unsubscribeTrackSource(e) {
1741
+ let t = e.trackSourceUnsubscribe;
1742
+ if (e.trackSourceUnsubscribe = void 0, t !== void 0) try {
1743
+ t();
1744
+ } catch {}
1745
+ }
1746
+ assertActiveCall(t) {
1747
+ if (t === void 0 || t.state !== "active") throw new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, { callId: t?.callId });
1748
+ }
1749
+ assertDeviceSelectionCapability(e) {
1750
+ if (e.capabilities === void 0 || !e.capabilities.has("device_selection")) throw this.capabilityError(e.callId);
1751
+ }
1752
+ capabilityError(t) {
1753
+ return new e("CAPABILITY_NOT_SUPPORTED", "capability", !1, { callId: t });
1754
+ }
1755
+ callOperationError(t) {
1756
+ return new e("CALL_OPERATION_NOT_ALLOWED", "call", !1, { callId: t });
1757
+ }
1758
+ assertNotDisposed() {
1759
+ if (this.disposed || this.disposing) throw new e("SDK_ALREADY_DISPOSED", "internal", !1);
1760
+ }
1761
+ };
1762
+ function F(e) {
1763
+ return "peerConnection" in e;
1764
+ }
1765
+ function I(e) {
1766
+ try {
1767
+ return e.track;
1768
+ } catch {
1769
+ return null;
1770
+ }
1771
+ }
1772
+ function L(e) {
1773
+ try {
1774
+ return e.replaceTrack(null);
1775
+ } catch (e) {
1776
+ return Promise.reject(e);
1777
+ }
1778
+ }
1779
+ function R(e) {
1780
+ try {
1781
+ z(e.getTracks());
1782
+ } catch {}
1783
+ }
1784
+ function z(e) {
1785
+ e.forEach(B);
1786
+ }
1787
+ function B(e) {
1788
+ try {
1789
+ e.stop();
1790
+ } catch {}
1791
+ }
1792
+ function V(e) {
1793
+ if (typeof MediaStream < "u") try {
1794
+ return new MediaStream([e]);
1795
+ } catch {
1796
+ return;
1797
+ }
1798
+ }
1799
+ //#endregion
1800
+ //#region src/core/mediaBridge.ts
1801
+ function H(t, n = {}) {
1802
+ let r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = n.ownershipRequired === !0, s = !1, c = !1, l, u = () => t(), d = new P({ getActiveCall: u });
1803
+ return {
1804
+ publicMedia: {
1805
+ requestPermission: () => (f(), d.requestPermission()),
1806
+ getDevices: () => (f(), d.getDevices()),
1807
+ getCapabilities: () => (f(), d.getCapabilities()),
1808
+ supportsOutputSelection: () => (f(), d.supportsOutputSelection()),
1809
+ setInputDevice: (e) => (f(), d.setInputDevice(e, u())),
1810
+ setOutputDevice: (e) => (f(), d.setOutputDevice(e)),
1811
+ playRemoteAudio: (e) => (f(), d.playRemoteAudio(e)),
1812
+ releaseAll: () => (f(), d.releaseAll())
1813
+ },
1814
+ registerCall(e, t) {
1815
+ s || c || !U(t) || (i.set(e, t), (!o || a.has(e)) && p(e, t));
1816
+ },
1817
+ async setCallOwnership(e, t) {
1818
+ if (s) return;
1819
+ if (t !== "owned") {
1820
+ a.delete(e), await d.releaseCall(e), r.delete(e);
1821
+ return;
1822
+ }
1823
+ a.add(e);
1824
+ let n = i.get(e);
1825
+ n !== void 0 && p(e, n);
1826
+ },
1827
+ contextFor(e, t, n) {
1828
+ let i = r.get(e);
1829
+ if (i !== void 0) return {
1830
+ callId: e,
1831
+ state: t,
1832
+ capabilities: n,
1833
+ peerConnection: i.peerConnection
1834
+ };
1835
+ },
1836
+ async releaseCall(e) {
1837
+ s || (await d.releaseCall(e), r.delete(e), i.delete(e), a.delete(e));
1838
+ },
1839
+ releaseAll: async () => {
1840
+ await d.releaseAll(), r.clear(), i.clear(), a.clear();
1841
+ },
1842
+ getResourceCounts: () => d.getResourceCounts(),
1843
+ dispose: () => {
1844
+ if (l !== void 0) return l;
1845
+ c = !0;
1846
+ let e = d.dispose().then(() => {
1847
+ s = !0, c = !1, r.clear(), i.clear(), a.clear();
1848
+ }).finally(() => {
1849
+ l === e && !s && (l = void 0, c = !1);
1850
+ });
1851
+ return l = e, e;
1852
+ }
1853
+ };
1854
+ function f() {
1855
+ if (s) throw new e("SDK_ALREADY_DISPOSED", "internal", !1);
1856
+ }
1857
+ function p(e, t) {
1858
+ if (!U(t) || typeof t.getMediaRegistration != "function") return;
1859
+ let n = t.getMediaRegistration();
1860
+ if (W(n) && r.get(e)?.peerConnection !== n.peerConnection) {
1861
+ r.set(e, n);
1862
+ try {
1863
+ d.registerCallMedia(e, n);
1864
+ } catch {
1865
+ r.delete(e);
1866
+ }
1867
+ }
1868
+ }
1869
+ }
1870
+ function U(e) {
1871
+ return typeof e == "object" && !!e;
1872
+ }
1873
+ function W(e) {
1874
+ return typeof e == "object" && !!e && "peerConnection" in e && typeof e.peerConnection == "object" && e.peerConnection !== null;
1875
+ }
1876
+ //#endregion
1877
+ //#region src/reconnect/backoff.ts
1878
+ var G = 1e3, K = 3e4;
1879
+ function q(e, t = Math.random) {
1880
+ let n = Math.min(K, G * 2 ** Math.max(0, Math.floor(e))), r = Math.min(1, Math.max(0, t()));
1881
+ return Math.round(n * (1 + r * .2));
1882
+ }
1883
+ //#endregion
1884
+ //#region src/reconnect/ReconnectManager.ts
1885
+ var J = class {
1886
+ recover;
1887
+ random;
1888
+ isOnline;
1889
+ onAttempt;
1890
+ attempt = 0;
1891
+ pendingTimer;
1892
+ running = !1;
1893
+ online = !0;
1894
+ generation = 0;
1895
+ disposed = !1;
1896
+ restartAfterRun = !1;
1897
+ constructor(e) {
1898
+ this.recover = e.recover, this.random = e.random ?? Math.random, this.isOnline = e.isOnline ?? (() => !0), this.onAttempt = e.onAttempt;
1899
+ }
1900
+ start() {
1901
+ if (this.disposed || !this.online || !this.isOnline() || this.pendingTimer !== void 0 || this.running) return;
1902
+ let e = this.generation, t = q(this.attempt, this.random);
1903
+ this.pendingTimer = setTimeout(() => {
1904
+ this.pendingTimer = void 0, this.run(e);
1905
+ }, t);
1906
+ }
1907
+ notifyOffline() {
1908
+ this.disposed || (this.online = !1, this.generation += 1, this.clearPendingTimer(), this.restartAfterRun = !1);
1909
+ }
1910
+ notifyOnline() {
1911
+ this.disposed || (this.online = !0, this.running && (this.restartAfterRun = !0), this.start());
1912
+ }
1913
+ cancel() {
1914
+ this.disposed || (this.generation += 1, this.clearPendingTimer(), this.attempt = 0, this.restartAfterRun = !1);
1915
+ }
1916
+ dispose() {
1917
+ this.disposed || (this.disposed = !0, this.generation += 1, this.clearPendingTimer(), this.restartAfterRun = !1);
1918
+ }
1919
+ getTimerCount() {
1920
+ return this.pendingTimer === void 0 ? 0 : 1;
1921
+ }
1922
+ async run(e) {
1923
+ if (this.disposed || !this.online || e !== this.generation || this.running) return;
1924
+ this.running = !0;
1925
+ try {
1926
+ this.onAttempt?.(this.attempt);
1927
+ } catch {}
1928
+ let t = !1;
1929
+ try {
1930
+ await this.recover(), this.isCurrent(e) && (this.attempt = 0);
1931
+ } catch {
1932
+ this.isCurrent(e) && (this.attempt += 1, t = !0);
1933
+ } finally {
1934
+ this.running = !1;
1935
+ }
1936
+ this.restartAfterRun ? (this.restartAfterRun = !1, this.isCurrent(this.generation) && this.start()) : t && this.isCurrent(e) && this.start();
1937
+ }
1938
+ isCurrent(e) {
1939
+ return !this.disposed && this.online && e === this.generation && this.isOnline();
1940
+ }
1941
+ clearPendingTimer() {
1942
+ this.pendingTimer !== void 0 && (clearTimeout(this.pendingTimer), this.pendingTimer = void 0);
1943
+ }
1944
+ }, Y = class r {
1945
+ media;
1946
+ options;
1947
+ api;
1948
+ suppliedSip;
1949
+ sip;
1950
+ events = new n();
1951
+ mediaBridge;
1952
+ reconnect;
1953
+ diagnostics;
1954
+ callManager;
1955
+ session;
1956
+ state = "idle";
1957
+ initialized = !1;
1958
+ disposed = !1;
1959
+ intentionalDisconnect = !1;
1960
+ deferredRebuild = !1;
1961
+ detectedPlatform;
1962
+ support;
1963
+ acceptingEvents = !0;
1964
+ connectOperation;
1965
+ disconnectOperation;
1966
+ refreshOperation;
1967
+ disposeOperation;
1968
+ refreshTimer;
1969
+ lifecycleGeneration = 0;
1970
+ managerUnsubscribers = [];
1971
+ sipUnsubscribe;
1972
+ networkUnsubscribers = [];
1973
+ sessionDeleteOperations = /* @__PURE__ */ new Map();
1974
+ deletedSessions = /* @__PURE__ */ new Set();
1975
+ ownedSessionIds = /* @__PURE__ */ new Set();
1976
+ terminalReleaseOperations = /* @__PURE__ */ new Map();
1977
+ tokenRequest = {};
1978
+ constructor(e) {
1979
+ this.options = e;
1980
+ let n = (e) => this.options.tokenProvider({
1981
+ ...e,
1982
+ ...this.tokenRequest
1983
+ });
1984
+ this.api = e.api === void 0 ? new d({
1985
+ baseUrl: e.baseUrl ?? "",
1986
+ tokenProvider: n
1987
+ }) : re(e.api), this.suppliedSip = e.sip === void 0 ? void 0 : ie(e.sip), this.mediaBridge = H(() => this.getActiveMediaContext()), this.media = this.mediaBridge.publicMedia, this.reconnect = new J({
1988
+ recover: () => this.recoverConnection(),
1989
+ onAttempt: (e) => {
1990
+ this.disposed || this.events.emit("connection.reconnecting", { attempt: e });
1991
+ }
1992
+ }), this.diagnostics = new t({
1993
+ getSnapshot: () => this.createDiagnosticsSnapshot(),
1994
+ getPermission: () => this.readMicrophonePermission(),
1995
+ getDeviceNames: async () => (await this.media.getDevices()).map((e) => e.label).filter((e) => e !== "")
1996
+ });
1997
+ }
1998
+ static async checkSupport() {
1999
+ let e = typeof navigator < "u" && navigator.mediaDevices !== void 0, t = typeof WebSocket < "u", n = Z(typeof navigator < "u" ? navigator.userAgent : "");
2000
+ return {
2001
+ supported: e && t,
2002
+ platform: n,
2003
+ hasMediaDevices: e,
2004
+ hasWebSocket: t,
2005
+ ...e && t ? {} : { reason: "当前运行环境缺少 WebPhone 所需的浏览器能力" }
2006
+ };
2007
+ }
2008
+ async initialize() {
2009
+ if (this.assertNotDisposed(), this.initialized) return;
2010
+ let e = await r.checkSupport();
2011
+ this.support = e, this.options.platform === void 0 && (e.platform === "web" || e.platform === "mobile-web") && (this.detectedPlatform = e.platform), this.assertNotDisposed(), this.initialized = !0;
2012
+ }
2013
+ connect(e) {
2014
+ this.assertNotDisposed();
2015
+ let t = e?.extension?.trim();
2016
+ if (this.tokenRequest = t === void 0 || t === "" ? {} : { extension: t }, this.api.invalidateToken?.(), this.connectOperation !== void 0) return this.connectOperation;
2017
+ if (this.state === "connected") return Promise.resolve();
2018
+ let n = this.lifecycleGeneration, r = this.performConnect(n).finally(() => {
2019
+ this.connectOperation === r && (this.connectOperation = void 0);
2020
+ });
2021
+ return this.connectOperation = r, r;
2022
+ }
2023
+ disconnect() {
2024
+ if (this.assertNotDisposed(), this.disconnectOperation !== void 0) return this.disconnectOperation;
2025
+ if (this.state === "idle" && this.connectOperation === void 0 || this.state === "disconnected" && this.connectOperation === void 0) return Promise.resolve();
2026
+ this.lifecycleGeneration += 1, this.acceptingEvents = !1;
2027
+ let e = this.performDisconnect().finally(() => {
2028
+ this.disconnectOperation === e && (this.disconnectOperation = void 0);
2029
+ });
2030
+ return this.disconnectOperation = e, e;
2031
+ }
2032
+ dispose() {
2033
+ if (this.disposeOperation !== void 0) return this.disposeOperation;
2034
+ this.disposed = !0, this.lifecycleGeneration += 1, this.intentionalDisconnect = !0, this.acceptingEvents = !1, this.reconnect.dispose(), this.clearRefreshTimer(), this.detachNetworkListeners(), this.state = "disconnected", this.diagnostics.log("info", "connection.stateChanged", { state: "disconnected" }), this.detachSipListener(), this.detachManagerListeners();
2035
+ let e = !1, t = this.performDispose().then(() => {
2036
+ e = !0;
2037
+ }).finally(() => {
2038
+ this.disposeOperation === t && !e && (this.disposeOperation = void 0);
2039
+ });
2040
+ return this.disposeOperation = t, t;
2041
+ }
2042
+ recover() {
2043
+ return this.assertNotDisposed(), this.recoverConnection();
2044
+ }
2045
+ dial(t) {
2046
+ this.assertConnected();
2047
+ let n = this.callManager, r = this.session;
2048
+ if (n === void 0 || r === void 0) throw new e("CALL_NOT_CONNECTED", "call", !1);
2049
+ return n.dial(t, r);
2050
+ }
2051
+ answer(t, n) {
2052
+ this.assertConnected();
2053
+ let r = this.callManager, i = this.session;
2054
+ if (r === void 0 || i === void 0) throw new e("CALL_NOT_CONNECTED", "call", !1);
2055
+ return r.answer(t, i, n);
2056
+ }
2057
+ setActiveCall(t) {
2058
+ this.assertConnected();
2059
+ let n = this.callManager;
2060
+ if (n === void 0) throw new e("CALL_NOT_CONNECTED", "call", !1);
2061
+ return n.setActiveCall(t);
2062
+ }
2063
+ getCalls() {
2064
+ return this.callManager?.getCalls() ?? [];
2065
+ }
2066
+ getActiveCall() {
2067
+ return this.callManager?.getActiveCall();
2068
+ }
2069
+ getAgent() {
2070
+ return this.session?.agent;
2071
+ }
2072
+ getDiagnostics(e = {}) {
2073
+ return this.diagnostics.getReport(e);
2074
+ }
2075
+ async setAgentStatus(e) {
2076
+ this.assertNotDisposed(), await this.api.setAgentStatus({
2077
+ status: e,
2078
+ reason: ""
2079
+ }), this.disposed || this.events.emit("agent.statusChanged", { status: e });
2080
+ }
2081
+ on(e, t) {
2082
+ return this.disposed ? () => void 0 : this.events.on(e, t);
2083
+ }
2084
+ off(e, t) {
2085
+ this.events.off(e, t);
2086
+ }
2087
+ async performConnect(e) {
2088
+ let t, n, r;
2089
+ try {
2090
+ await this.initialize(), this.assertGeneration(e);
2091
+ let i = this.resolvePlatform();
2092
+ this.intentionalDisconnect = !1, this.acceptingEvents = !0, this.setConnectionState("connecting"), t = await this.api.createSession({
2093
+ sdkVersion: "0.1.0",
2094
+ platform: i === "mobile-web" ? "mobile_web" : "web",
2095
+ ...this.options.locale === void 0 ? {} : { locale: this.options.locale },
2096
+ requestedCapabilities: [...this.options.requestedCapabilities ?? ce(i)]
2097
+ }), this.ownedSessionIds.add(t.sessionId), this.assertGeneration(e), n = await this.getSip(), this.assertGeneration(e), this.session = t;
2098
+ let a = this.callManager ?? this.createCallManager(n, t, i);
2099
+ this.callManager === void 0 && (r = a), a.updateSession(t), this.callManager = a, this.attachSipListener(n), this.attachNetworkListeners(), await n.connect(t), this.assertGeneration(e), this.setConnectionState("connected"), this.events.emit("connection.registered", { registered: !0 }), this.scheduleRefresh(t);
2100
+ } catch (i) {
2101
+ if (await this.rollbackConnect(t, n, r), this.disposed) throw this.disposedError();
2102
+ if (e !== this.lifecycleGeneration) throw i;
2103
+ let a = Q(i, "REGISTRATION_FAILED", "registration", !0);
2104
+ throw this.setConnectionState("failed"), this.events.emit("connection.failed", { error: a }), a;
2105
+ }
2106
+ }
2107
+ async performDisconnect() {
2108
+ let e, t = this.connectOperation;
2109
+ if (t !== void 0) try {
2110
+ await t;
2111
+ } catch (t) {
2112
+ $(t) || (e ??= t);
2113
+ }
2114
+ let n = this.refreshOperation;
2115
+ if (n !== void 0) try {
2116
+ await n;
2117
+ } catch (t) {
2118
+ $(t) || (e ??= t);
2119
+ }
2120
+ this.reconnect.cancel(), this.clearRefreshTimer(), this.intentionalDisconnect = !0, this.detachSipListener(), this.detachManagerListeners();
2121
+ let r = this.callManager, i = this.sip;
2122
+ this.callManager = void 0;
2123
+ try {
2124
+ await r?.dispose({ terminateCalls: !0 });
2125
+ } catch (t) {
2126
+ e ??= t;
2127
+ }
2128
+ try {
2129
+ await this.awaitMediaReleaseBarriers();
2130
+ } catch (t) {
2131
+ e ??= t;
2132
+ }
2133
+ try {
2134
+ i !== void 0 && await i.disconnect();
2135
+ } catch (t) {
2136
+ e ??= t;
2137
+ }
2138
+ this.session = void 0;
2139
+ try {
2140
+ await this.deleteOwnedSessions();
2141
+ } catch (t) {
2142
+ e ??= t;
2143
+ }
2144
+ if (this.disposed || (this.acceptingEvents = !0, this.setConnectionState("disconnected")), e !== void 0) throw e;
2145
+ }
2146
+ createCallManager(e, t, n) {
2147
+ let r = new y({
2148
+ sip: e,
2149
+ platform: n,
2150
+ session: t,
2151
+ maxConcurrentCalls: this.options.maxConcurrentCalls,
2152
+ autoHoldPreviousCall: this.options.autoHoldPreviousCall,
2153
+ onCallCreated: (e, t) => this.handleCallCreated(e, t),
2154
+ onCallStateChanged: (e, t) => this.handleCallStateChanged(e, t),
2155
+ onCallTerminal: (e) => this.handleCallTerminal(e)
2156
+ });
2157
+ return this.bindManagerEvents(r), r;
2158
+ }
2159
+ async rollbackConnect(e, t, n) {
2160
+ if (n !== void 0) {
2161
+ this.detachManagerListeners(), this.callManager === n && (this.callManager = void 0);
2162
+ try {
2163
+ await n.dispose({ terminateCalls: !0 });
2164
+ } catch {}
2165
+ }
2166
+ if (t !== void 0) {
2167
+ this.detachSipListener();
2168
+ try {
2169
+ await t.disconnect();
2170
+ } catch {}
2171
+ }
2172
+ if (this.session === e && (this.session = void 0), e !== void 0) try {
2173
+ await this.deleteSession(e.sessionId);
2174
+ } catch {}
2175
+ }
2176
+ async performDispose() {
2177
+ let e, t = [
2178
+ this.connectOperation,
2179
+ this.disconnectOperation,
2180
+ this.refreshOperation
2181
+ ].filter((e) => e !== void 0);
2182
+ for (let n of t) try {
2183
+ await n;
2184
+ } catch (t) {
2185
+ $(t) || (e ??= t);
2186
+ }
2187
+ let n = this.callManager;
2188
+ this.callManager = void 0;
2189
+ try {
2190
+ await n?.dispose({ terminateCalls: !0 });
2191
+ } catch (t) {
2192
+ e ??= t;
2193
+ }
2194
+ try {
2195
+ await this.awaitMediaReleaseBarriers();
2196
+ } catch (t) {
2197
+ e ??= t;
2198
+ }
2199
+ try {
2200
+ await this.media.releaseAll();
2201
+ } catch (t) {
2202
+ ae(t) || (e ??= t);
2203
+ }
2204
+ try {
2205
+ await this.mediaBridge.dispose();
2206
+ } catch (t) {
2207
+ e ??= t;
2208
+ }
2209
+ try {
2210
+ await this.sip?.dispose();
2211
+ } catch (t) {
2212
+ e ??= t;
2213
+ }
2214
+ try {
2215
+ await this.deleteOwnedSessions();
2216
+ } catch (t) {
2217
+ e ??= t;
2218
+ }
2219
+ if (this.session = void 0, this.sipUnsubscribe = void 0, this.events.clear(), e !== void 0) throw e;
2220
+ }
2221
+ async awaitMediaReleaseBarriers() {
2222
+ let e;
2223
+ for (let [t, n] of [...this.terminalReleaseOperations]) try {
2224
+ await n, this.terminalReleaseOperations.delete(t);
2225
+ } catch (n) {
2226
+ try {
2227
+ await this.mediaBridge.releaseCall(t), this.terminalReleaseOperations.delete(t);
2228
+ } catch (t) {
2229
+ e ??= t ?? n;
2230
+ }
2231
+ }
2232
+ if (e !== void 0) throw e;
2233
+ }
2234
+ detachSipListener() {
2235
+ let e = this.sipUnsubscribe;
2236
+ this.sipUnsubscribe = void 0;
2237
+ try {
2238
+ e?.();
2239
+ } catch {}
2240
+ }
2241
+ detachManagerListeners() {
2242
+ this.managerUnsubscribers.splice(0).forEach((e) => {
2243
+ try {
2244
+ e();
2245
+ } catch {}
2246
+ });
2247
+ }
2248
+ bindManagerEvents(e) {
2249
+ [
2250
+ "call.created",
2251
+ "call.incoming",
2252
+ "call.stateChanged",
2253
+ "call.activeChanged",
2254
+ "call.ended",
2255
+ "call.failed",
2256
+ "error"
2257
+ ].forEach((t) => {
2258
+ let n = e.on(t, (e) => {
2259
+ this.acceptingEvents && !this.disposed && (this.diagnostics.log(t === "error" || t === "call.failed" ? "error" : "info", String(t), e), this.events.emit(t, e));
2260
+ });
2261
+ this.managerUnsubscribers.push(n);
2262
+ });
2263
+ }
2264
+ handleCallCreated(e, t) {
2265
+ this.acceptingEvents && !this.disposed && this.mediaBridge.registerCall(e, t);
2266
+ }
2267
+ handleCallStateChanged(e, t) {
2268
+ this.acceptingEvents && !this.disposed && this.mediaBridge.registerCall(e, t);
2269
+ }
2270
+ handleCallTerminal(e) {
2271
+ let t = this.startTerminalRelease(e);
2272
+ return this.deferredRebuild && !this.hasNonTerminalCalls() && this.startDeferredRecovery(), t;
2273
+ }
2274
+ startTerminalRelease(e) {
2275
+ let t = this.terminalReleaseOperations.get(e);
2276
+ if (t !== void 0) return t;
2277
+ let n = this.mediaBridge.releaseCall(e).then(() => {
2278
+ this.terminalReleaseOperations.get(e) === n && this.terminalReleaseOperations.delete(e);
2279
+ }).catch((t) => {
2280
+ throw this.acceptingEvents && !this.disposed && this.events.emit("error", { error: Q(t, "SDK_INTERNAL_ERROR", "internal", !0, e) }), t;
2281
+ });
2282
+ return this.terminalReleaseOperations.set(e, n), n;
2283
+ }
2284
+ async startDeferredRecovery() {
2285
+ try {
2286
+ await this.awaitMediaReleaseBarriers(), this.deferredRebuild && !this.hasNonTerminalCalls() && !this.disposed && (this.deferredRebuild = !1, this.clearRefreshTimer(), this.reconnect.start());
2287
+ } catch {
2288
+ this.disposed || this.reconnect.start();
2289
+ }
2290
+ }
2291
+ async refreshAndRebuild() {
2292
+ if (this.refreshOperation !== void 0) return this.refreshOperation;
2293
+ let e = this.performRefreshAndRebuild().finally(() => {
2294
+ this.refreshOperation === e && (this.refreshOperation = void 0);
2295
+ });
2296
+ return this.refreshOperation = e, e;
2297
+ }
2298
+ async performRefreshAndRebuild() {
2299
+ if (this.disposed || this.session === void 0) return;
2300
+ let e = this.lifecycleGeneration, t = this.session;
2301
+ try {
2302
+ let n = await this.api.refreshSession(t.sessionId);
2303
+ if (!this.isCurrentGeneration(e) || this.session !== t) return;
2304
+ if (this.session = n, this.callManager?.updateSession(n), this.events.emit("token.refreshed", { expiresAt: n.expiresAt }), this.hasNonTerminalCalls()) {
2305
+ this.deferredRebuild = !0, this.scheduleRefresh(n);
2306
+ return;
2307
+ }
2308
+ let r = await this.getSip();
2309
+ if (!this.isCurrentGeneration(e)) return;
2310
+ await r.connect(n), this.isCurrentGeneration(e) && (this.deferredRebuild = !1, this.setConnectionState("connected"), this.scheduleRefresh(n));
2311
+ } catch (n) {
2312
+ if (!this.isCurrentGeneration(e)) return;
2313
+ throw this.handleRefreshFailure(t, n), n;
2314
+ }
2315
+ }
2316
+ handleRefreshFailure(e, t) {
2317
+ if (this.disposed) return;
2318
+ let n = Q(t, "NETWORK_OFFLINE", "network", !0);
2319
+ this.events.emit("token.expiring", { expiresAt: e.expiresAt }), this.events.emit("error", { error: n }), this.deferredRebuild = !0, this.hasNonTerminalCalls() || this.reconnect.start();
2320
+ }
2321
+ scheduleRefresh(e) {
2322
+ this.clearRefreshTimer();
2323
+ let t = e.expiresAt * 1e3 - Date.now() - 6e4, n = Math.max(1e3, t);
2324
+ this.refreshTimer = setTimeout(() => {
2325
+ this.refreshTimer = void 0, this.refreshAndRebuild().catch(() => void 0);
2326
+ }, n);
2327
+ }
2328
+ async recoverConnection() {
2329
+ this.disposed || this.hasNonTerminalCalls() || (await this.awaitMediaReleaseBarriers(), await this.refreshAndRebuild());
2330
+ }
2331
+ async getSip() {
2332
+ if (this.sip !== void 0) return this.sip;
2333
+ if (this.suppliedSip !== void 0) return this.sip = this.suppliedSip, this.sip;
2334
+ let [e, t] = await Promise.all([import("./createJsSipFactory-yttVU3d6.js"), import("./JsSipAdapter-GHzVSCDh.js")]);
2335
+ return this.sip = new t.JsSipAdapter(e.createJsSipFactory(), this.options.baseUrl), this.sip;
2336
+ }
2337
+ attachSipListener(e) {
2338
+ this.sipUnsubscribe === void 0 && e.onConnectionStateChanged !== void 0 && (this.sipUnsubscribe = e.onConnectionStateChanged((e, t) => {
2339
+ if (!(this.disposed || this.intentionalDisconnect || !this.acceptingEvents)) {
2340
+ if (e === "registered") {
2341
+ this.setConnectionState("connected");
2342
+ return;
2343
+ }
2344
+ this.state === "connected" && (this.setConnectionState("reconnecting"), this.reconnect.start(), t !== void 0 && this.events.emit("error", { error: Q(t, "SIP_WS_UNAVAILABLE", "registration", !0) }));
2345
+ }
2346
+ }));
2347
+ }
2348
+ attachNetworkListeners() {
2349
+ if (this.networkUnsubscribers.length > 0 || typeof window > "u") return;
2350
+ let e = window, t = () => this.reconnect.notifyOnline(), n = () => this.reconnect.notifyOffline();
2351
+ e.addEventListener("online", t), e.addEventListener("offline", n), this.networkUnsubscribers = [() => e.removeEventListener("online", t), () => e.removeEventListener("offline", n)];
2352
+ }
2353
+ detachNetworkListeners() {
2354
+ this.networkUnsubscribers.splice(0).forEach((e) => e());
2355
+ }
2356
+ getActiveMediaContext() {
2357
+ let e = this.callManager?.getActiveCall();
2358
+ return e === void 0 ? void 0 : this.mediaBridge.contextFor(e.id, e.state, new Set(this.session?.capabilities ?? []));
2359
+ }
2360
+ hasNonTerminalCalls() {
2361
+ return this.callManager?.hasNonTerminalCalls() ?? !1;
2362
+ }
2363
+ clearRefreshTimer() {
2364
+ this.refreshTimer !== void 0 && (clearTimeout(this.refreshTimer), this.refreshTimer = void 0);
2365
+ }
2366
+ createDiagnosticsSnapshot() {
2367
+ let e = this.session;
2368
+ return {
2369
+ connectionState: this.state,
2370
+ calls: this.getCalls().map((e) => ({
2371
+ callId: e.id,
2372
+ state: e.state,
2373
+ destination: e.destination
2374
+ })),
2375
+ permission: this.support?.hasMediaDevices === !1 ? "unsupported" : "unknown",
2376
+ ice: X(e),
2377
+ wss: {
2378
+ configured: e !== void 0,
2379
+ secure: e?.transport.wssUrl.toLowerCase().startsWith("wss://") ?? !1,
2380
+ state: this.state
2381
+ },
2382
+ resources: this.getDiagnosticsResourceCounts()
2383
+ };
2384
+ }
2385
+ getDiagnosticsResourceCounts() {
2386
+ let e = this.mediaBridge.getResourceCounts(), t = this.callManager?.getResourceCounts() ?? {
2387
+ timers: 0,
2388
+ listeners: 0
2389
+ }, n = this.sip?.getResourceCounts?.(), r = (this.callManager === void 0 ? 0 : 1) + (this.sipUnsubscribe === void 0 ? 0 : 1), i = this.session !== void 0 && this.state !== "idle" && this.state !== "disconnected";
2390
+ return {
2391
+ timers: (this.refreshTimer === void 0 ? 0 : 1) + this.reconnect.getTimerCount() + t.timers,
2392
+ listeners: this.events.listenerCount() + t.listeners + e.listeners + this.networkUnsubscribers.length + (n?.listeners ?? r),
2393
+ tracks: e.tracks,
2394
+ peerConnections: e.peerConnections,
2395
+ audioElements: e.audioElements,
2396
+ webSockets: n?.webSockets ?? +!!i
2397
+ };
2398
+ }
2399
+ async readMicrophonePermission() {
2400
+ if (typeof navigator > "u" || navigator.mediaDevices === void 0) return "unsupported";
2401
+ if (navigator.permissions === void 0) return "unknown";
2402
+ try {
2403
+ return (await navigator.permissions.query({ name: "microphone" })).state;
2404
+ } catch {
2405
+ return "unknown";
2406
+ }
2407
+ }
2408
+ deleteSession(e) {
2409
+ if (this.deletedSessions.has(e)) return Promise.resolve();
2410
+ let t = this.sessionDeleteOperations.get(e);
2411
+ if (t !== void 0) return t;
2412
+ let n = this.api.deleteSession(e).then(() => {
2413
+ this.deletedSessions.add(e);
2414
+ }).finally(() => {
2415
+ this.sessionDeleteOperations.get(e) === n && this.sessionDeleteOperations.delete(e);
2416
+ });
2417
+ return this.sessionDeleteOperations.set(e, n), n;
2418
+ }
2419
+ async deleteOwnedSessions() {
2420
+ let e;
2421
+ for (let t of [...this.ownedSessionIds]) try {
2422
+ await this.deleteSession(t), this.ownedSessionIds.delete(t);
2423
+ } catch (t) {
2424
+ e ??= t;
2425
+ }
2426
+ if (e !== void 0) throw e;
2427
+ }
2428
+ resolvePlatform() {
2429
+ let t = this.options.platform ?? this.detectedPlatform;
2430
+ if (t === void 0) throw new e("CONFIG_INVALID", "configuration", !1, { cause: this.support?.platform ?? "unknown" });
2431
+ return t;
2432
+ }
2433
+ setConnectionState(e) {
2434
+ this.state === e || this.disposed || (this.state = e, this.diagnostics.log("info", "connection.stateChanged", { state: e }), this.events.emit("connection.stateChanged", { state: e === "disconnected" || e === "idle" ? "offline" : e }));
2435
+ }
2436
+ assertConnected() {
2437
+ if (this.assertNotDisposed(), this.state !== "connected" || this.callManager === void 0 || this.session === void 0) throw new e("CALL_NOT_CONNECTED", "call", !1);
2438
+ }
2439
+ assertGeneration(t) {
2440
+ if (this.disposed) throw this.disposedError();
2441
+ if (t !== this.lifecycleGeneration) throw new e("CALL_NOT_CONNECTED", "call", !1);
2442
+ }
2443
+ isCurrentGeneration(e) {
2444
+ return !this.disposed && e === this.lifecycleGeneration;
2445
+ }
2446
+ assertNotDisposed() {
2447
+ if (this.disposed) throw this.disposedError();
2448
+ }
2449
+ disposedError() {
2450
+ return new e("SDK_ALREADY_DISPOSED", "internal", !1);
2451
+ }
2452
+ };
2453
+ function X(e) {
2454
+ if (e === void 0) return {
2455
+ configured: !1,
2456
+ serverCount: 0,
2457
+ stunServerCount: 0,
2458
+ turnServerCount: 0
2459
+ };
2460
+ let t = 0, n = 0;
2461
+ return e.iceServers.forEach((e) => {
2462
+ let r = e.urls.map((e) => e.toLowerCase());
2463
+ r.some((e) => e.startsWith("stun:")) && (t += 1), r.some((e) => e.startsWith("turn:") || e.startsWith("turns:")) && (n += 1);
2464
+ }), {
2465
+ configured: e.iceServers.length > 0,
2466
+ serverCount: e.iceServers.length,
2467
+ stunServerCount: t,
2468
+ turnServerCount: n
2469
+ };
2470
+ }
2471
+ function Z(e) {
2472
+ return e === "" ? "unknown" : /iPhone|iPad|Android/i.test(e) ? "mobile-web" : "web";
2473
+ }
2474
+ function re(t) {
2475
+ if (typeof t != "object" || !t) throw new e("CONFIG_INVALID", "configuration", !1);
2476
+ return t;
2477
+ }
2478
+ function ie(t) {
2479
+ if (typeof t != "object" || !t) throw new e("CONFIG_INVALID", "configuration", !1);
2480
+ return t;
2481
+ }
2482
+ function Q(t, n, r, i, a) {
2483
+ return t instanceof e ? new e(t.code, t.category, t.retryable, {
2484
+ requestId: t.requestId,
2485
+ callId: a ?? t.callId,
2486
+ cause: t.cause ?? t
2487
+ }) : new e(n, r, i, {
2488
+ callId: a,
2489
+ cause: t
2490
+ });
2491
+ }
2492
+ function ae(t) {
2493
+ return t instanceof e && t.code === "SDK_ALREADY_DISPOSED";
2494
+ }
2495
+ function $(t) {
2496
+ return t instanceof e && (t.code === "SDK_ALREADY_DISPOSED" || t.code === "CALL_NOT_CONNECTED");
2497
+ }
2498
+ var oe = [
2499
+ "outbound",
2500
+ "inbound",
2501
+ "mute",
2502
+ "hold",
2503
+ "dtmf",
2504
+ "blind_transfer",
2505
+ "device_selection"
2506
+ ], se = [
2507
+ "outbound",
2508
+ "mute",
2509
+ "dtmf"
2510
+ ];
2511
+ function ce(e) {
2512
+ return e === "mobile-web" ? se : oe;
2513
+ }
2514
+ //#endregion
2515
+ export { l as a, i as c, n as d, d as i, s as l, y as n, o, m as r, a as s, Y as t, r as u };