@signalwire/js 4.0.0-dev-20260326210326 → 4.0.0-dev-20260401154549

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_operators = require('./operators-mm21prWr.cjs');
1
+ const require_operators = require('./operators-DuprVgnV.cjs');
2
2
  let jwt_decode = require("jwt-decode");
3
3
  let rxjs = require("rxjs");
4
4
  let uuid = require("uuid");
@@ -134,7 +134,7 @@ const asyncRetry = async ({ asyncCallable, maxRetries: retries = DEFAULT_MAX_RET
134
134
 
135
135
  //#endregion
136
136
  //#region src/controllers/HTTPRequestController.ts
137
- const logger$20 = require_operators.getLogger();
137
+ const logger$22 = require_operators.getLogger();
138
138
  const GET_PARAMS = {
139
139
  method: "GET",
140
140
  headers: { Accept: "application/json" }
@@ -159,9 +159,16 @@ var HTTPRequestController = class HTTPRequestController {
159
159
  static {
160
160
  this.defaultRequestTimeoutMs = 3e4;
161
161
  }
162
- constructor(baseURL, credential, options = {}) {
162
+ static {
163
+ this.SENSITIVE_BODY_FIELDS = new Set([
164
+ "dpop_token",
165
+ "token",
166
+ "jwt_token"
167
+ ]);
168
+ }
169
+ constructor(baseURL, getCredential, options = {}) {
163
170
  this.baseURL = baseURL;
164
- this.credential = credential;
171
+ this.getCredential = getCredential;
165
172
  this._responses$ = new rxjs.Subject();
166
173
  this._errors$ = new rxjs.Subject();
167
174
  this._status$ = new rxjs.BehaviorSubject("idle");
@@ -190,7 +197,7 @@ var HTTPRequestController = class HTTPRequestController {
190
197
  this._responses$.next(response);
191
198
  return response;
192
199
  } catch (error) {
193
- logger$20.error("[HTTPRequestController] Request error:", error);
200
+ logger$22.error("[HTTPRequestController] Request error:", error);
194
201
  this._status$.next("error");
195
202
  const err = error instanceof Error ? error : new Error("HTTP request failed", { cause: error });
196
203
  this._errors$.next(err);
@@ -217,14 +224,14 @@ var HTTPRequestController = class HTTPRequestController {
217
224
  const url = this.buildURL(request.url);
218
225
  const headers = this.buildHeaders(request.headers);
219
226
  const timeout$3 = request.timeout ?? this.requestTimeout;
220
- logger$20.debug("[HTTPRequestController] Executing request:", {
227
+ logger$22.debug("[HTTPRequestController] Executing request:", {
221
228
  method: request.method,
222
229
  url,
223
230
  headers: Object.keys(headers).reduce((acc, key) => {
224
231
  acc[key] = key === "Authorization" ? `${headers[key].substring(0, 20)}...` : headers[key];
225
232
  return acc;
226
233
  }, {}),
227
- body: request.body
234
+ body: this.sanitizeBody(request.body)
228
235
  });
229
236
  const controller = new AbortController();
230
237
  const timeoutId = setTimeout(() => controller.abort(), timeout$3);
@@ -237,7 +244,7 @@ var HTTPRequestController = class HTTPRequestController {
237
244
  });
238
245
  clearTimeout(timeoutId);
239
246
  const httpResponse = await this.convertResponse(response);
240
- logger$20.debug("[HTTPRequestController] Response received:", {
247
+ logger$22.debug("[HTTPRequestController] Response received:", {
241
248
  status: response.status,
242
249
  statusText: response.statusText,
243
250
  headers: [...response.headers.entries()],
@@ -247,7 +254,7 @@ var HTTPRequestController = class HTTPRequestController {
247
254
  } catch (error) {
248
255
  clearTimeout(timeoutId);
249
256
  if (error instanceof Error && error.name === "AbortError") throw new require_operators.RequestTimeoutError(`Request timeout after ${timeout$3}ms`, { cause: error });
250
- logger$20.error("[HTTPRequestController] Request failed:", error);
257
+ logger$22.error("[HTTPRequestController] Request failed:", error);
251
258
  throw error;
252
259
  }
253
260
  }
@@ -258,12 +265,26 @@ var HTTPRequestController = class HTTPRequestController {
258
265
  }
259
266
  buildHeaders(requestHeaders) {
260
267
  const headers = { ...requestHeaders ?? {} };
261
- if (this.credential.token) {
262
- headers.Authorization = `Bearer ${this.credential.token}`;
263
- logger$20.debug("[HTTPRequestController] Using Bearer token auth, token length:", this.credential.token.length);
264
- } else logger$20.warn("[HTTPRequestController] No credentials available for authentication");
268
+ const credential = this.getCredential();
269
+ if (credential.token) {
270
+ headers.Authorization = `Bearer ${credential.token}`;
271
+ logger$22.debug("[HTTPRequestController] Using Bearer token auth, token length:", credential.token.length);
272
+ } else logger$22.warn("[HTTPRequestController] No credentials available for authentication");
265
273
  return headers;
266
274
  }
275
+ /**
276
+ * Sanitizes a request body for debug logging by masking sensitive fields.
277
+ */
278
+ sanitizeBody(body) {
279
+ if (!body || typeof body !== "string") return body ? "(non-string body)" : void 0;
280
+ try {
281
+ const sanitized = { ...JSON.parse(body) };
282
+ for (const key of Object.keys(sanitized)) if (HTTPRequestController.SENSITIVE_BODY_FIELDS.has(key) && typeof sanitized[key] === "string") sanitized[key] = `${sanitized[key].substring(0, 20)}...[redacted]`;
283
+ return JSON.stringify(sanitized);
284
+ } catch {
285
+ return body.length > 200 ? `${body.substring(0, 200)}...` : body;
286
+ }
287
+ }
267
288
  async convertResponse(response) {
268
289
  const headers = {};
269
290
  response.headers.forEach((value, key) => {
@@ -293,6 +314,25 @@ const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
293
314
  const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
294
315
  const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
295
316
  const PREFERENCES_STORAGE_KEY = "sw:preferences";
317
+ /** Scope value that enables automatic token refresh. */
318
+ const SAT_REFRESH_SCOPE = "sat:refresh";
319
+ /** API endpoints for device token operations. */
320
+ const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
321
+ const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
322
+ /** Default device token TTL in seconds (15 minutes). */
323
+ const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
324
+ /** Buffer time in milliseconds before expiry to trigger refresh. */
325
+ const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
326
+ /** Maximum retry attempts for device token refresh on transient failure. */
327
+ const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
328
+ /** Base delay in milliseconds for exponential backoff on refresh retry. */
329
+ const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
330
+ /** JSON-RPC error code for requester validation failure (corrupted auth state). */
331
+ const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
332
+ /** JSON-RPC error code for invalid params (e.g., missing authentication block). */
333
+ const RPC_ERROR_INVALID_PARAMS = -32602;
334
+ /** JSON-RPC error code for authentication failure (invalid token, missing DPoP, etc.). */
335
+ const RPC_ERROR_AUTHENTICATION_FAILED = -32002;
296
336
 
297
337
  //#endregion
298
338
  //#region src/utils/time.ts
@@ -305,7 +345,7 @@ function fromMsToSec(milliseconds) {
305
345
 
306
346
  //#endregion
307
347
  //#region src/containers/PreferencesContainer.ts
308
- const logger$19 = require_operators.getLogger();
348
+ const logger$21 = require_operators.getLogger();
309
349
  var PreferencesContainer = class PreferencesContainer {
310
350
  static get instance() {
311
351
  this._instance ??= new PreferencesContainer();
@@ -599,7 +639,7 @@ var ClientPreferences = class {
599
639
  if (!this._storage) return;
600
640
  const data = collectStoredPreferences();
601
641
  this._storage.setItem(PREFERENCES_STORAGE_KEY, data, "local").catch((error) => {
602
- logger$19.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
642
+ logger$21.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
603
643
  });
604
644
  }
605
645
  /** Loads preferences from storage and applies them to the container. */
@@ -608,14 +648,14 @@ var ClientPreferences = class {
608
648
  this._storage.getItem(PREFERENCES_STORAGE_KEY, "local").then((stored) => {
609
649
  if (stored) applyStoredPreferences(stored);
610
650
  }).catch((error) => {
611
- logger$19.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
651
+ logger$21.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
612
652
  });
613
653
  }
614
654
  };
615
655
 
616
656
  //#endregion
617
657
  //#region src/controllers/NavigatorDeviceController.ts
618
- const logger$18 = require_operators.getLogger();
658
+ const logger$20 = require_operators.getLogger();
619
659
  const initialDevicesState = {
620
660
  audioinput: [],
621
661
  audiooutput: [],
@@ -636,7 +676,7 @@ var NavigatorDeviceController = class extends Destroyable {
636
676
  super();
637
677
  this.webRTCApiProvider = webRTCApiProvider;
638
678
  this.deviceChangeHandler = () => {
639
- logger$18.debug("[DeviceController] Device change detected");
679
+ logger$20.debug("[DeviceController] Device change detected");
640
680
  this.enumerateDevices();
641
681
  };
642
682
  this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
@@ -670,13 +710,13 @@ var NavigatorDeviceController = class extends Destroyable {
670
710
  return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, rxjs.map)((state) => state.videoinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$)));
671
711
  }
672
712
  get selectedAudioInputDevice$() {
673
- return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.audioinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected audio input device changed:", info))));
713
+ return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.audioinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$20.debug("[DeviceController] Selected audio input device changed:", info))));
674
714
  }
675
715
  get selectedAudioOutputDevice$() {
676
- return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.audiooutput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected audio output device changed:", info))));
716
+ return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.audiooutput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$20.debug("[DeviceController] Selected audio output device changed:", info))));
677
717
  }
678
718
  get selectedVideoInputDevice$() {
679
- return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.videoinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$18.debug("[DeviceController] Selected video input device changed:", info))));
719
+ return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, rxjs.map)((state) => state.videoinput), (0, rxjs.distinctUntilChanged)(), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.tap)((info) => logger$20.debug("[DeviceController] Selected video input device changed:", info))));
680
720
  }
681
721
  get selectedAudioInputDevice() {
682
722
  return this._selectedDevicesState$.value.audioinput;
@@ -703,7 +743,7 @@ var NavigatorDeviceController = class extends Destroyable {
703
743
  });
704
744
  }
705
745
  selectVideoInputDevice(device) {
706
- logger$18.debug("[DeviceController] Setting selected video input device:", device);
746
+ logger$20.debug("[DeviceController] Setting selected video input device:", device);
707
747
  this._selectedDevicesState$.next({
708
748
  ...this._selectedDevicesState$.value,
709
749
  videoinput: device
@@ -733,7 +773,7 @@ var NavigatorDeviceController = class extends Destroyable {
733
773
  this.disableDeviceMonitoring();
734
774
  this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
735
775
  if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, rxjs.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
736
- logger$18.debug("[DeviceController] Polling devices due to interval");
776
+ logger$20.debug("[DeviceController] Polling devices due to interval");
737
777
  this.enumerateDevices();
738
778
  });
739
779
  this.enumerateDevices();
@@ -756,13 +796,13 @@ var NavigatorDeviceController = class extends Destroyable {
756
796
  videoinput: []
757
797
  });
758
798
  this._devicesState$.next(devicesByKind);
759
- logger$18.debug("[DeviceController] Devices enumerated:", {
799
+ logger$20.debug("[DeviceController] Devices enumerated:", {
760
800
  audioInputs: devicesByKind.audioinput.length,
761
801
  audioOutputs: devicesByKind.audiooutput.length,
762
802
  videoInputs: devicesByKind.videoinput.length
763
803
  });
764
804
  } catch (error) {
765
- logger$18.error("[DeviceController] Failed to enumerate devices:", error);
805
+ logger$20.error("[DeviceController] Failed to enumerate devices:", error);
766
806
  this._errors$.next(error);
767
807
  }
768
808
  }
@@ -778,7 +818,7 @@ var NavigatorDeviceController = class extends Destroyable {
778
818
  stream.getTracks().forEach((t) => t.stop());
779
819
  return capabilities;
780
820
  } catch (error) {
781
- logger$18.error("[DeviceController] Failed to get device capabilities:", error);
821
+ logger$20.error("[DeviceController] Failed to get device capabilities:", error);
782
822
  this._errors$.next(error);
783
823
  throw error;
784
824
  }
@@ -925,7 +965,7 @@ var DependencyContainer = class {
925
965
  return this._storageManager;
926
966
  }
927
967
  get http() {
928
- this._httpRequestController ??= new HTTPRequestController(this._baseURL, this._credential);
968
+ this._httpRequestController ??= new HTTPRequestController(this._baseURL, () => this._credential);
929
969
  return this._httpRequestController;
930
970
  }
931
971
  get conversationManager() {
@@ -981,7 +1021,6 @@ var DependencyContainer = class {
981
1021
  }
982
1022
  set credential(credential) {
983
1023
  this._credential = credential;
984
- this._httpRequestController = void 0;
985
1024
  }
986
1025
  set storageImpl(storageImpl) {
987
1026
  this._storageImpl = storageImpl;
@@ -994,12 +1033,194 @@ var DependencyContainer = class {
994
1033
  this._host = ch.substring(0, firstDot);
995
1034
  this._domain = ch.substring(firstDot + 1);
996
1035
  }
1036
+ this._baseURL = this.apiHost;
1037
+ this._httpRequestController = void 0;
997
1038
  }
998
1039
  get relayHost() {
999
1040
  return `wss://${this._host ?? "puc"}.${this._domain ?? "signalwire.com"}`;
1000
1041
  }
1001
1042
  get apiHost() {
1002
- return `https://${this._host ?? "fabric"}.${this._domain ?? "signalwire.com"}`;
1043
+ return `https://fabric.${this._domain ?? "signalwire.com"}`;
1044
+ }
1045
+ };
1046
+
1047
+ //#endregion
1048
+ //#region src/controllers/CryptoController.ts
1049
+ const logger$19 = require_operators.getLogger();
1050
+ /**
1051
+ * Base64url-encodes an ArrayBuffer (no padding, URL-safe).
1052
+ */
1053
+ const base64url = (buffer) => {
1054
+ const bytes = new Uint8Array(buffer);
1055
+ let binary = "";
1056
+ for (const byte of bytes) binary += String.fromCharCode(byte);
1057
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1058
+ };
1059
+ /**
1060
+ * Base64url-encodes a UTF-8 string.
1061
+ */
1062
+ const base64urlEncode = (str) => {
1063
+ return base64url(new TextEncoder().encode(str).buffer);
1064
+ };
1065
+ /**
1066
+ * Computes the JWK Thumbprint per RFC 7638.
1067
+ *
1068
+ * Only supports RSA keys — the canonical JSON uses lexicographic member ordering: { e, kty, n }.
1069
+ * The thumbprint is SHA-256 of the canonical JSON, base64url-encoded.
1070
+ *
1071
+ * @throws {Error} If the JWK is not an RSA key.
1072
+ */
1073
+ const computeJwkThumbprint = async (jwk) => {
1074
+ if (jwk.kty !== "RSA") throw new Error(`Unsupported key type for JWK Thumbprint: ${jwk.kty}. Only RSA is supported.`);
1075
+ const canonical = JSON.stringify({
1076
+ e: jwk.e,
1077
+ kty: jwk.kty,
1078
+ n: jwk.n
1079
+ });
1080
+ return base64url(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(canonical)));
1081
+ };
1082
+ /**
1083
+ * Controls DPoP (Demonstrating Proof-of-Possession) cryptographic operations.
1084
+ *
1085
+ * Generates an ephemeral RSA-2048 key pair where the private key is
1086
+ * non-extractable, computes the JWK Thumbprint (RFC 7638) as the fingerprint,
1087
+ * and creates signed DPoP proof JWTs for both HTTP API requests and
1088
+ * WebSocket RPC calls.
1089
+ *
1090
+ * @example
1091
+ * ```typescript
1092
+ * const crypto = new CryptoController();
1093
+ * await crypto.init();
1094
+ *
1095
+ * // Get fingerprint for SAT issuance
1096
+ * const fingerprint = crypto.fingerprint;
1097
+ *
1098
+ * // Create proof for HTTP endpoint
1099
+ * const httpProof = await crypto.createHttpProof({
1100
+ * method: 'POST',
1101
+ * uri: '/api/fabric/subscriber/devices/token'
1102
+ * });
1103
+ *
1104
+ * // Create proof for RPC call
1105
+ * const rpcProof = await crypto.createRpcProof({
1106
+ * method: 'signalwire.connect'
1107
+ * });
1108
+ * ```
1109
+ */
1110
+ var CryptoController = class {
1111
+ constructor() {
1112
+ this._keyPair = null;
1113
+ this._publicJwk = null;
1114
+ this._fingerprint = null;
1115
+ this._initialized = false;
1116
+ }
1117
+ /**
1118
+ * Generates the ephemeral RSA key pair and computes the fingerprint.
1119
+ *
1120
+ * Must be called before any other method. The private key is generated
1121
+ * as non-extractable to prevent accidental exposure.
1122
+ *
1123
+ * @returns The JWK Thumbprint (fingerprint) for the generated key.
1124
+ */
1125
+ async init() {
1126
+ if (this._initialized) return this.fingerprint;
1127
+ logger$19.debug("[DPoP] Generating ephemeral RSA key pair");
1128
+ this._keyPair = await crypto.subtle.generateKey({
1129
+ name: "RSASSA-PKCS1-v1_5",
1130
+ modulusLength: 2048,
1131
+ publicExponent: new Uint8Array([
1132
+ 1,
1133
+ 0,
1134
+ 1
1135
+ ]),
1136
+ hash: "SHA-256"
1137
+ }, false, ["sign", "verify"]);
1138
+ this._publicJwk = await crypto.subtle.exportKey("jwk", this._keyPair.publicKey);
1139
+ this._fingerprint = await computeJwkThumbprint(this._publicJwk);
1140
+ this._initialized = true;
1141
+ logger$19.debug("[DPoP] Key pair generated, fingerprint computed");
1142
+ return this._fingerprint;
1143
+ }
1144
+ /**
1145
+ * The JWK Thumbprint (RFC 7638) of the public key.
1146
+ * Used as the `fingerprint` parameter when requesting scoped SATs.
1147
+ *
1148
+ * @throws {DPoPInitError} If {@link init} has not been called.
1149
+ */
1150
+ get fingerprint() {
1151
+ if (!this._fingerprint) throw new require_operators.DPoPInitError("CryptoController not initialized. Call init() first.");
1152
+ return this._fingerprint;
1153
+ }
1154
+ /**
1155
+ * Whether the controller has been initialized with a key pair.
1156
+ */
1157
+ get initialized() {
1158
+ return this._initialized;
1159
+ }
1160
+ /**
1161
+ * Creates a DPoP proof JWT for an HTTP API request.
1162
+ *
1163
+ * Used for Prime API endpoints like `/api/fabric/subscriber/devices/token`
1164
+ * and `/api/fabric/subscriber/devices/refresh`.
1165
+ *
1166
+ * @param params - HTTP method and URI for the proof.
1167
+ * @returns Signed DPoP proof JWT string.
1168
+ */
1169
+ async createHttpProof(params) {
1170
+ const payload = {
1171
+ jti: crypto.randomUUID(),
1172
+ htm: params.method,
1173
+ htu: params.uri,
1174
+ iat: Math.floor(Date.now() / 1e3)
1175
+ };
1176
+ if (params.accessToken) payload.ath = base64url(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(params.accessToken)));
1177
+ return this.signProof(payload);
1178
+ }
1179
+ /**
1180
+ * Creates a DPoP proof JWT for a WebSocket RPC call.
1181
+ *
1182
+ * Used for switchblade RPC methods like `signalwire.connect` and
1183
+ * `signalwire.reauthenticate`.
1184
+ *
1185
+ * @param params - RPC method name for the proof.
1186
+ * @returns Signed DPoP proof JWT string.
1187
+ */
1188
+ async createRpcProof(params) {
1189
+ const payload = {
1190
+ jti: crypto.randomUUID(),
1191
+ rpc: "request",
1192
+ mth: params.method,
1193
+ iat: Math.floor(Date.now() / 1e3)
1194
+ };
1195
+ return this.signProof(payload);
1196
+ }
1197
+ /**
1198
+ * Releases the key pair references.
1199
+ * After calling destroy, the controller must be re-initialized to be used again.
1200
+ */
1201
+ destroy() {
1202
+ this._keyPair = null;
1203
+ this._publicJwk = null;
1204
+ this._fingerprint = null;
1205
+ this._initialized = false;
1206
+ logger$19.debug("[DPoP] Controller destroyed");
1207
+ }
1208
+ get publicJwk() {
1209
+ if (!this._publicJwk) throw new require_operators.DPoPInitError("CryptoController not initialized. Call init() first.");
1210
+ return this._publicJwk;
1211
+ }
1212
+ get privateKey() {
1213
+ if (!this._keyPair) throw new require_operators.DPoPInitError("CryptoController not initialized. Call init() first.");
1214
+ return this._keyPair.privateKey;
1215
+ }
1216
+ async signProof(payload) {
1217
+ const header = {
1218
+ typ: "dpop+jwt",
1219
+ alg: "RS256",
1220
+ jwk: this.publicJwk
1221
+ };
1222
+ const signingInput = `${base64urlEncode(JSON.stringify(header))}.${base64urlEncode(JSON.stringify(payload))}`;
1223
+ return `${signingInput}.${base64url(await crypto.subtle.sign("RSASSA-PKCS1-v1_5", this.privateKey, new TextEncoder().encode(signingInput)))}`;
1003
1224
  }
1004
1225
  };
1005
1226
 
@@ -1056,6 +1277,7 @@ var Subscriber = class extends Fetchable {
1056
1277
  scopes: data.app_settings.scopes
1057
1278
  } : void 0;
1058
1279
  this.addresses = data.fabric_addresses;
1280
+ this.satClaims = data.sat_claims;
1059
1281
  }
1060
1282
  };
1061
1283
 
@@ -1095,10 +1317,14 @@ const RPCConnect = (params) => {
1095
1317
 
1096
1318
  //#endregion
1097
1319
  //#region src/core/RPCMessages/RPCReauthenticate.ts
1098
- const RPCReauthenticate = (authentication) => {
1320
+ const RPCReauthenticate = (params) => {
1321
+ const { dpop_token, ...authFields } = params;
1099
1322
  return buildRPCRequest({
1100
1323
  method: "signalwire.reauthenticate",
1101
- params: { authentication }
1324
+ params: {
1325
+ authentication: authFields,
1326
+ ...dpop_token ? { dpop_token } : {}
1327
+ }
1102
1328
  });
1103
1329
  };
1104
1330
 
@@ -1194,7 +1420,7 @@ const RPCEventAckResponse = (id) => makeRPCResponse({
1194
1420
 
1195
1421
  //#endregion
1196
1422
  //#region src/managers/AttachManager.ts
1197
- const logger$17 = require_operators.getLogger();
1423
+ const logger$18 = require_operators.getLogger();
1198
1424
  var AttachManager = class {
1199
1425
  constructor(storage, deviceController, reconnectCallsTimeout, attachKey) {
1200
1426
  this.storage = storage;
@@ -1216,7 +1442,7 @@ var AttachManager = class {
1216
1442
  try {
1217
1443
  return await this.storage.getItem(this.attachKey) ?? {};
1218
1444
  } catch (error) {
1219
- logger$17.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
1445
+ logger$18.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
1220
1446
  return {};
1221
1447
  }
1222
1448
  }
@@ -1224,12 +1450,12 @@ var AttachManager = class {
1224
1450
  try {
1225
1451
  await this.storage.setItem(this.attachKey, attached);
1226
1452
  } catch (error) {
1227
- logger$17.warn("[AttachManager] Failed to write attached calls to storage", error);
1453
+ logger$18.warn("[AttachManager] Failed to write attached calls to storage", error);
1228
1454
  }
1229
1455
  }
1230
1456
  async attach(call) {
1231
1457
  if (!call.to) {
1232
- logger$17.warn("[AttachManager] Skip attach for calls with no destination");
1458
+ logger$18.warn("[AttachManager] Skip attach for calls with no destination");
1233
1459
  return;
1234
1460
  }
1235
1461
  const attachment = {
@@ -1549,7 +1775,7 @@ function toggleHandraiseMethod(is) {
1549
1775
 
1550
1776
  //#endregion
1551
1777
  //#region src/core/entities/Participant.ts
1552
- const logger$16 = require_operators.getLogger();
1778
+ const logger$17 = require_operators.getLogger();
1553
1779
  const initialState = {};
1554
1780
  /**
1555
1781
  * Represents a participant in a call.
@@ -1892,7 +2118,7 @@ var SelfParticipant = class extends Participant {
1892
2118
  try {
1893
2119
  await this.vertoManager.addScreenMedia();
1894
2120
  } catch (error) {
1895
- logger$16.error("[Participant.startScreenShare] Screen share error:", error);
2121
+ logger$17.error("[Participant.startScreenShare] Screen share error:", error);
1896
2122
  }
1897
2123
  }
1898
2124
  /** Observable of the current screen share status. */
@@ -1912,7 +2138,7 @@ var SelfParticipant = class extends Participant {
1912
2138
  try {
1913
2139
  await this.vertoManager.addInputDevice(options);
1914
2140
  } catch (error) {
1915
- logger$16.error("[Participant.startScreenShare] Screen share error:", error);
2141
+ logger$17.error("[Participant.startScreenShare] Screen share error:", error);
1916
2142
  }
1917
2143
  }
1918
2144
  /** Removes an additional media input device by ID. */
@@ -1973,7 +2199,7 @@ var SelfParticipant = class extends Participant {
1973
2199
  try {
1974
2200
  await super.mute();
1975
2201
  } catch (error) {
1976
- logger$16.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
2202
+ logger$17.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
1977
2203
  } finally {
1978
2204
  this.vertoManager.muteMainAudioInputDevice();
1979
2205
  }
@@ -1983,7 +2209,7 @@ var SelfParticipant = class extends Participant {
1983
2209
  try {
1984
2210
  await super.unmute();
1985
2211
  } catch (error) {
1986
- logger$16.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
2212
+ logger$17.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
1987
2213
  } finally {
1988
2214
  await this.vertoManager.unmuteMainAudioInputDevice();
1989
2215
  }
@@ -1993,7 +2219,7 @@ var SelfParticipant = class extends Participant {
1993
2219
  try {
1994
2220
  await super.muteVideo();
1995
2221
  } catch (error) {
1996
- logger$16.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
2222
+ logger$17.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
1997
2223
  } finally {
1998
2224
  this.vertoManager.muteMainVideoInputDevice();
1999
2225
  }
@@ -2003,7 +2229,7 @@ var SelfParticipant = class extends Participant {
2003
2229
  try {
2004
2230
  await super.unmuteVideo();
2005
2231
  } catch (error) {
2006
- logger$16.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
2232
+ logger$17.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
2007
2233
  } finally {
2008
2234
  await this.vertoManager.unmuteMainVideoInputDevice();
2009
2235
  }
@@ -2034,6 +2260,7 @@ function isJSONRPCErrorResponse(value) {
2034
2260
 
2035
2261
  //#endregion
2036
2262
  //#region src/core/RPCMessages/guards/events.guards.ts
2263
+ /** @internal @packageDocumentation */
2037
2264
  /**
2038
2265
  * Factory function to create Request-level type guards.
2039
2266
  */
@@ -2057,6 +2284,7 @@ const isCallUpdatedRequest = createEventRequestGuard("call.updated");
2057
2284
  const isCallStateRequest = createEventRequestGuard("call.state");
2058
2285
  const isCallPlayRequest = createEventRequestGuard("call.play");
2059
2286
  const isCallConnectRequest = createEventRequestGuard("call.connect");
2287
+ const isRoomUpdatedRequest = createEventRequestGuard("room.updated");
2060
2288
  const isMemberUpdatedRequest = createEventRequestGuard("member.updated");
2061
2289
  const isMemberJoinedRequest = createEventRequestGuard("member.joined");
2062
2290
  const isMemberLeftRequest = createEventRequestGuard("member.left");
@@ -2068,7 +2296,7 @@ function isSignalwireMetadata(value) {
2068
2296
  return isObject(value) && hasProperty(value, "event_type") && typeof value.event_type === "string" && hasProperty(value, "params");
2069
2297
  }
2070
2298
  function isSignalwireCallMetadata(value) {
2071
- return isSignalwireMetadata(value) && (isCallJoinedMetadata(value) || isCallLeftMetadata(value) || isCallUpdatedMetadata(value) || isCallStateMetadata(value) || isCallPlayMetadata(value) || isCallConnectMetadata(value) || isMemberUpdatedMetadata(value) || isMemberJoinedMetadata(value) || isMemberLeftMetadata(value) || isMemberTalkingMetadata(value) || isLayoutChangedMetadata(value) || isWebrtcMessageMetadata(value) || isConversationMessageMetadata(value) || isConversationMessageUpdatedMetadata(value));
2299
+ return isSignalwireMetadata(value) && (isCallJoinedMetadata(value) || isCallLeftMetadata(value) || isCallUpdatedMetadata(value) || isCallStateMetadata(value) || isCallPlayMetadata(value) || isCallConnectMetadata(value) || isRoomUpdatedMetadata(value) || isMemberUpdatedMetadata(value) || isMemberJoinedMetadata(value) || isMemberLeftMetadata(value) || isMemberTalkingMetadata(value) || isLayoutChangedMetadata(value) || isWebrtcMessageMetadata(value) || isConversationMessageMetadata(value) || isConversationMessageUpdatedMetadata(value));
2072
2300
  }
2073
2301
  const isSignalwireAuthorizationStateMetadata = createEventMetadataGuard("signalwire.authorization.state");
2074
2302
  const isWebrtcMessageMetadata = createEventMetadataGuard("webrtc.message");
@@ -2078,6 +2306,7 @@ const isCallUpdatedMetadata = createEventMetadataGuard("call.updated");
2078
2306
  const isCallStateMetadata = createEventMetadataGuard("call.state");
2079
2307
  const isCallPlayMetadata = createEventMetadataGuard("call.play");
2080
2308
  const isCallConnectMetadata = createEventMetadataGuard("call.connect");
2309
+ const isRoomUpdatedMetadata = createEventMetadataGuard("room.updated");
2081
2310
  const isMemberUpdatedMetadata = createEventMetadataGuard("member.updated");
2082
2311
  const isMemberJoinedMetadata = createEventMetadataGuard("member.joined");
2083
2312
  const isMemberLeftMetadata = createEventMetadataGuard("member.left");
@@ -2094,8 +2323,9 @@ function isLayoutChangedPayload(value) {
2094
2323
 
2095
2324
  //#endregion
2096
2325
  //#region src/managers/CallEventsManager.ts
2097
- const logger$15 = require_operators.getLogger();
2326
+ const logger$16 = require_operators.getLogger();
2098
2327
  const initialSessionState = {};
2328
+ /** @internal */
2099
2329
  var CallEventsManager = class extends Destroyable {
2100
2330
  constructor(webRtcCallSession, options = {}) {
2101
2331
  super();
@@ -2197,7 +2427,7 @@ var CallEventsManager = class extends Destroyable {
2197
2427
  }
2198
2428
  initSubscriptions() {
2199
2429
  this.subscribeTo(this.callJoinedEvent$, (callJoinedEvent) => {
2200
- logger$15.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
2430
+ logger$16.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
2201
2431
  callId: callJoinedEvent.call_id,
2202
2432
  roomSessionId: callJoinedEvent.room_session_id
2203
2433
  });
@@ -2224,19 +2454,34 @@ var CallEventsManager = class extends Destroyable {
2224
2454
  if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
2225
2455
  });
2226
2456
  this.subscribeTo(this.memberUpdates$, (member) => {
2227
- logger$15.debug("[CallEventsManager] Handling member update event for member ID:", member);
2457
+ logger$16.debug("[CallEventsManager] Handling member update event for member ID:", member);
2228
2458
  this.upsertParticipant(member);
2229
2459
  });
2230
2460
  this.subscribeTo(this.webRtcCallSession.memberLeft$, (memberLeftEvent) => {
2231
- logger$15.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
2461
+ logger$16.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
2232
2462
  const participants = { ...this._participants$.value };
2233
2463
  if (memberLeftEvent.member.member_id in participants) {
2234
2464
  delete participants[memberLeftEvent.member.member_id];
2235
2465
  this._participants$.next(participants);
2236
- } else logger$15.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
2466
+ } else logger$16.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
2467
+ });
2468
+ this.subscribeTo(this.webRtcCallSession.callUpdated$, (callUpdatedEvent) => {
2469
+ logger$16.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
2470
+ const roomSession = callUpdatedEvent.room_session;
2471
+ this._sessionState$.next({
2472
+ ...this._sessionState$.value,
2473
+ recording: roomSession.recording,
2474
+ recordings: roomSession.recordings,
2475
+ streaming: roomSession.streaming,
2476
+ streams: roomSession.streams,
2477
+ playbacks: roomSession.playbacks,
2478
+ prioritize_handraise: roomSession.prioritize_handraise,
2479
+ locked: roomSession.locked,
2480
+ meta: roomSession.meta
2481
+ });
2237
2482
  });
2238
2483
  this.subscribeTo(this.layoutChangedEvent$, (layoutChangedEvent) => {
2239
- logger$15.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
2484
+ logger$16.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
2240
2485
  this._sessionState$.next({
2241
2486
  ...this._sessionState$.value,
2242
2487
  layout_name: layoutChangedEvent.id,
@@ -2246,7 +2491,7 @@ var CallEventsManager = class extends Destroyable {
2246
2491
  });
2247
2492
  }
2248
2493
  updateParticipantPositions(layoutChangedEvent) {
2249
- if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$15.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
2494
+ if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$16.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
2250
2495
  layoutChangedEvent.layers.filter((layer) => Boolean(layer.member_id)).map((layer) => {
2251
2496
  if (!layer.member_id) throw new require_operators.DependencyError("Layer member_id is required");
2252
2497
  this._participants$.value[layer.member_id].upnext({ position: layer });
@@ -2267,7 +2512,7 @@ var CallEventsManager = class extends Destroyable {
2267
2512
  layouts: response.result.layouts
2268
2513
  });
2269
2514
  }).catch((error) => {
2270
- logger$15.error("[CallEventsManager] Error fetching layouts:", error);
2515
+ logger$16.error("[CallEventsManager] Error fetching layouts:", error);
2271
2516
  });
2272
2517
  }
2273
2518
  updateParticipants(members) {
@@ -2283,7 +2528,7 @@ var CallEventsManager = class extends Destroyable {
2283
2528
  }
2284
2529
  const participant = this._participants$.value[member.member_id];
2285
2530
  const oldValue = participant.value;
2286
- logger$15.debug("[CallEventsManager] Updating participant:", member.member_id, {
2531
+ logger$16.debug("[CallEventsManager] Updating participant:", member.member_id, {
2287
2532
  oldValue,
2288
2533
  newValue: member
2289
2534
  });
@@ -2296,17 +2541,17 @@ var CallEventsManager = class extends Destroyable {
2296
2541
  }
2297
2542
  get callJoinedEvent$() {
2298
2543
  return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, rxjs.filter)(isCallJoinedPayload), (0, rxjs.tap)((event) => {
2299
- logger$15.debug("[CallEventsManager] Call joined event:", event);
2544
+ logger$16.debug("[CallEventsManager] Call joined event:", event);
2300
2545
  })));
2301
2546
  }
2302
2547
  get layoutChangedEvent$() {
2303
2548
  return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(require_operators.filterAs(isLayoutChangedPayload, "layout"), (0, rxjs.tap)((event) => {
2304
- logger$15.debug("[CallEventsManager] Layout changed event:", event);
2549
+ logger$16.debug("[CallEventsManager] Layout changed event:", event);
2305
2550
  })));
2306
2551
  }
2307
2552
  get memberUpdates$() {
2308
2553
  return this.cachedObservable("memberUpdates$", () => (0, rxjs.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, rxjs.map)((event) => event.member), (0, rxjs.tap)((event) => {
2309
- logger$15.debug("[CallEventsManager] Member update event:", event);
2554
+ logger$16.debug("[CallEventsManager] Member update event:", event);
2310
2555
  })));
2311
2556
  }
2312
2557
  destroy() {
@@ -2414,7 +2659,7 @@ function isValidLocalDescription(sdp) {
2414
2659
 
2415
2660
  //#endregion
2416
2661
  //#region src/controllers/ICEGatheringController.ts
2417
- const logger$14 = require_operators.getLogger();
2662
+ const logger$15 = require_operators.getLogger();
2418
2663
  var ICEGatheringController = class extends Destroyable {
2419
2664
  constructor(peerConnection, peerConnectionControllerNegotiating$, options = {}) {
2420
2665
  super();
@@ -2422,23 +2667,23 @@ var ICEGatheringController = class extends Destroyable {
2422
2667
  this.peerConnectionControllerNegotiating$ = peerConnectionControllerNegotiating$;
2423
2668
  this.onicegatheringstatechangeHandler = () => {
2424
2669
  const { iceGatheringState } = this.peerConnection;
2425
- logger$14.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
2670
+ logger$15.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
2426
2671
  if (iceGatheringState === "gathering") this._iceCandidatesState.next({
2427
2672
  state: "gathering",
2428
2673
  validSDP: false
2429
2674
  });
2430
2675
  };
2431
2676
  this.onicecandidateHandler = (event) => {
2432
- logger$14.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
2677
+ logger$15.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
2433
2678
  this.removeTimer("iceCandidateTimer");
2434
2679
  if (event.candidate) this.iceCandidateTimer = setTimeout(() => {
2435
2680
  if (this.peerConnection.iceGatheringState !== "complete") {
2436
- logger$14.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
2681
+ logger$15.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
2437
2682
  this.handleICECandidateTimeout();
2438
2683
  }
2439
2684
  }, this.iceCandidateTimeout);
2440
2685
  else {
2441
- logger$14.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
2686
+ logger$15.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
2442
2687
  this.removeTimer("iceGatheringTimer");
2443
2688
  this.handleICEGatheringComplete();
2444
2689
  }
@@ -2456,7 +2701,7 @@ var ICEGatheringController = class extends Destroyable {
2456
2701
  this.setupEventListeners();
2457
2702
  this.iceGatheringTimer = setTimeout(() => {
2458
2703
  if (this.peerConnection.iceGatheringState !== "complete") {
2459
- logger$14.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
2704
+ logger$15.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
2460
2705
  this.handleICEGatheringTimeout();
2461
2706
  }
2462
2707
  }, this.iceGatheringTimeout);
@@ -2483,9 +2728,9 @@ var ICEGatheringController = class extends Destroyable {
2483
2728
  this.relayOnly = value;
2484
2729
  }
2485
2730
  handleICEGatheringComplete() {
2486
- logger$14.debug("[ICEGatheringController] Handling ICE gathering complete");
2487
- logger$14.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
2488
- logger$14.debug("[ICEGatheringController] ICE gathering complete");
2731
+ logger$15.debug("[ICEGatheringController] Handling ICE gathering complete");
2732
+ logger$15.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
2733
+ logger$15.debug("[ICEGatheringController] ICE gathering complete");
2489
2734
  this._iceCandidatesState.next({
2490
2735
  state: "complete",
2491
2736
  validSDP: this.hasValidLocalDescriptionSDP
@@ -2501,21 +2746,21 @@ var ICEGatheringController = class extends Destroyable {
2501
2746
  this.removeTimer("iceGatheringTimer");
2502
2747
  const validSDP = this.hasValidLocalDescriptionSDP;
2503
2748
  if (validSDP) {
2504
- logger$14.debug("[ICEGatheringController] Local SDP is valid");
2749
+ logger$15.debug("[ICEGatheringController] Local SDP is valid");
2505
2750
  this._iceCandidatesState.next({
2506
2751
  state: "timeout",
2507
2752
  validSDP
2508
2753
  });
2509
2754
  this.stopGathering();
2510
- } else logger$14.debug("### ICE gathering timeout\n", this.peerConnection.localDescription?.sdp);
2755
+ } else logger$15.debug("### ICE gathering timeout\n", this.peerConnection.localDescription?.sdp);
2511
2756
  }
2512
2757
  handleICECandidateTimeout() {
2513
2758
  if (this.iceCandidateTimer) this.removeTimer("iceCandidateTimer");
2514
- logger$14.warn("[ICEGatheringController] ICE candidate timeout");
2759
+ logger$15.warn("[ICEGatheringController] ICE candidate timeout");
2515
2760
  const validSDP = this.hasValidLocalDescriptionSDP;
2516
2761
  if (!validSDP && !this.relayOnly) this.restartICEGatheringWithRelayOnly();
2517
2762
  else {
2518
- logger$14.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout");
2763
+ logger$15.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout");
2519
2764
  this._iceCandidatesState.next({
2520
2765
  state: "timeout",
2521
2766
  validSDP
@@ -2524,7 +2769,7 @@ var ICEGatheringController = class extends Destroyable {
2524
2769
  }
2525
2770
  }
2526
2771
  restartICEGatheringWithRelayOnly() {
2527
- logger$14.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
2772
+ logger$15.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
2528
2773
  this.relayOnly = true;
2529
2774
  this.peerConnection.setConfiguration({
2530
2775
  ...this.peerConnection.getConfiguration(),
@@ -2532,14 +2777,14 @@ var ICEGatheringController = class extends Destroyable {
2532
2777
  });
2533
2778
  if (!(this.peerConnection.connectionState === "connected")) this.peerConnection.restartIce();
2534
2779
  }
2535
- removeTimer(timer) {
2536
- if (this[timer]) {
2537
- clearTimeout(this[timer]);
2538
- this[timer] = void 0;
2780
+ removeTimer(timer$1) {
2781
+ if (this[timer$1]) {
2782
+ clearTimeout(this[timer$1]);
2783
+ this[timer$1] = void 0;
2539
2784
  }
2540
2785
  }
2541
2786
  clearAllTimers() {
2542
- logger$14.debug("[ICEGatheringController] Clearing all timers");
2787
+ logger$15.debug("[ICEGatheringController] Clearing all timers");
2543
2788
  this.removeTimer("iceGatheringTimer");
2544
2789
  this.removeTimer("iceCandidateTimer");
2545
2790
  }
@@ -2548,7 +2793,7 @@ var ICEGatheringController = class extends Destroyable {
2548
2793
  this.peerConnection.removeEventListener("icecandidate", this.onicecandidateHandler);
2549
2794
  }
2550
2795
  destroy() {
2551
- logger$14.debug("[ICEGatheringController] Destroying ICEGatheringController");
2796
+ logger$15.debug("[ICEGatheringController] Destroying ICEGatheringController");
2552
2797
  this.clearAllTimers();
2553
2798
  this.removeEventListeners();
2554
2799
  super.destroy();
@@ -2557,7 +2802,7 @@ var ICEGatheringController = class extends Destroyable {
2557
2802
 
2558
2803
  //#endregion
2559
2804
  //#region src/controllers/LocalStreamController.ts
2560
- const logger$13 = require_operators.getLogger();
2805
+ const logger$14 = require_operators.getLogger();
2561
2806
  var LocalStreamController = class extends Destroyable {
2562
2807
  constructor(options) {
2563
2808
  super();
@@ -2595,26 +2840,26 @@ var LocalStreamController = class extends Destroyable {
2595
2840
  * Build the local media stream based on the provided options.
2596
2841
  */
2597
2842
  async buildLocalStream() {
2598
- logger$13.debug("[LocalStreamController] Building local media stream.");
2843
+ logger$14.debug("[LocalStreamController] Building local media stream.");
2599
2844
  let stream;
2600
2845
  if (this.options.inputAudioStream ?? this.options.inputVideoStream) {
2601
2846
  const tracks = [...this.options.inputAudioStream?.getTracks() ?? [], ...this.options.inputVideoStream?.getTracks() ?? []];
2602
2847
  stream = new MediaStream(tracks);
2603
2848
  } else if (this.options.propose === "screenshare") {
2604
- logger$13.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
2849
+ logger$14.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
2605
2850
  stream = await this.options.getDisplayMedia({
2606
2851
  video: true,
2607
2852
  audio: Boolean(this.options.inputAudioDeviceConstraints)
2608
2853
  });
2609
- logger$13.debug("[LocalStreamController] Screen share media obtained:", stream);
2854
+ logger$14.debug("[LocalStreamController] Screen share media obtained:", stream);
2610
2855
  } else {
2611
2856
  const constraints = {
2612
2857
  audio: this.options.inputAudioDeviceConstraints,
2613
2858
  video: this.options.inputVideoDeviceConstraints
2614
2859
  };
2615
- logger$13.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
2860
+ logger$14.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
2616
2861
  stream = await this.options.getUserMedia(constraints);
2617
- logger$13.debug("[LocalStreamController] User media obtained:", stream);
2862
+ logger$14.debug("[LocalStreamController] User media obtained:", stream);
2618
2863
  }
2619
2864
  this._localStream$.next(stream);
2620
2865
  return stream;
@@ -2631,7 +2876,7 @@ var LocalStreamController = class extends Destroyable {
2631
2876
  this._localStream$.next(localStream);
2632
2877
  if (track.kind === "video") this._localVideoTracks$.next(localStream.getVideoTracks());
2633
2878
  else this._localAudioTracks$.next(localStream.getAudioTracks());
2634
- logger$13.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
2879
+ logger$14.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
2635
2880
  return localStream;
2636
2881
  }
2637
2882
  /**
@@ -2643,7 +2888,7 @@ var LocalStreamController = class extends Destroyable {
2643
2888
  const stream = this._localStream$.value;
2644
2889
  const track = stream?.getTracks().find((t) => t.id === trackId);
2645
2890
  if (!track) {
2646
- logger$13.debug(`[LocalStreamController] track not found: ${trackId}`);
2891
+ logger$14.debug(`[LocalStreamController] track not found: ${trackId}`);
2647
2892
  return;
2648
2893
  }
2649
2894
  track.removeEventListener("ended", this.mediaTrackEndedHandler);
@@ -2652,7 +2897,7 @@ var LocalStreamController = class extends Destroyable {
2652
2897
  this._localStream$.next(stream);
2653
2898
  if (track.kind === "video") this._localVideoTracks$.next(stream?.getVideoTracks() ?? []);
2654
2899
  else this._localAudioTracks$.next(stream?.getAudioTracks() ?? []);
2655
- logger$13.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
2900
+ logger$14.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
2656
2901
  return track;
2657
2902
  }
2658
2903
  /**
@@ -2687,7 +2932,7 @@ var LocalStreamController = class extends Destroyable {
2687
2932
  */
2688
2933
  stopAllTracks() {
2689
2934
  this._localStream$.value?.getTracks().forEach((track) => {
2690
- logger$13.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
2935
+ logger$14.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
2691
2936
  track.removeEventListener("ended", this.mediaTrackEndedHandler);
2692
2937
  track.stop();
2693
2938
  });
@@ -2703,7 +2948,7 @@ var LocalStreamController = class extends Destroyable {
2703
2948
 
2704
2949
  //#endregion
2705
2950
  //#region src/controllers/TransceiverController.ts
2706
- const logger$12 = require_operators.getLogger();
2951
+ const logger$13 = require_operators.getLogger();
2707
2952
  const getDirection = (send, recv) => {
2708
2953
  if (send && recv) return "sendrecv";
2709
2954
  else if (send && !recv) return "sendonly";
@@ -2805,7 +3050,7 @@ var TransceiverController = class extends Destroyable {
2805
3050
  sendEncodings: isAudio ? void 0 : this.sendEncodings,
2806
3051
  streams: direction === "recvonly" ? void 0 : [localStream]
2807
3052
  };
2808
- logger$12.debug(`[TransceiverController] Setting up transceiver sender for local ${track.kind} track:`, {
3053
+ logger$13.debug(`[TransceiverController] Setting up transceiver sender for local ${track.kind} track:`, {
2809
3054
  transceiver,
2810
3055
  transceiverParams
2811
3056
  });
@@ -2813,11 +3058,11 @@ var TransceiverController = class extends Destroyable {
2813
3058
  await transceiver.sender.replaceTrack(track);
2814
3059
  transceiver.direction = transceiverParams.direction;
2815
3060
  if (transceiverParams.streams?.some((stream) => Boolean(stream))) {
2816
- logger$12.debug(`[TransceiverController] Setting streams for transceiver sender for local ${track.kind} track:`, transceiverParams.streams);
3061
+ logger$13.debug(`[TransceiverController] Setting streams for transceiver sender for local ${track.kind} track:`, transceiverParams.streams);
2817
3062
  transceiver.sender.setStreams(...transceiverParams.streams);
2818
3063
  }
2819
3064
  } else {
2820
- logger$12.debug(`[TransceiverController] Adding new transceiver for local ${track.kind} track:`, track.id);
3065
+ logger$13.debug(`[TransceiverController] Adding new transceiver for local ${track.kind} track:`, track.id);
2821
3066
  this.peerConnection.addTransceiver(track, transceiverParams);
2822
3067
  }
2823
3068
  }
@@ -2831,13 +3076,13 @@ var TransceiverController = class extends Destroyable {
2831
3076
  if (options.updateTransceiverDirection) transceiver.direction = "inactive";
2832
3077
  }
2833
3078
  } catch (error) {
2834
- logger$12.error("[TransceiverController] stopTrackSender error", kind, error);
3079
+ logger$13.error("[TransceiverController] stopTrackSender error", kind, error);
2835
3080
  this.options.onError?.(new require_operators.MediaTrackError("stopTrackSender", kind, error));
2836
3081
  }
2837
3082
  }
2838
3083
  async restoreTrackSender(kind) {
2839
3084
  try {
2840
- logger$12.debug("[TransceiverController] restoreTrackSender called", kind);
3085
+ logger$13.debug("[TransceiverController] restoreTrackSender called", kind);
2841
3086
  const constraints = {};
2842
3087
  const transceivers = this.transceiverByKind(kind);
2843
3088
  for (const transceiver of transceivers) {
@@ -2847,23 +3092,23 @@ var TransceiverController = class extends Destroyable {
2847
3092
  if (trackKind === "audio" || trackKind === "video") constraints[trackKind] = this.getConstraintsFor(trackKind);
2848
3093
  }
2849
3094
  }
2850
- logger$12.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
3095
+ logger$13.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
2851
3096
  if (Object.keys(constraints).length === 0) {
2852
- logger$12.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
3097
+ logger$13.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
2853
3098
  return;
2854
3099
  }
2855
3100
  const newTracks = (await this.options.getUserMedia(constraints)).getTracks();
2856
- logger$12.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
3101
+ logger$13.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
2857
3102
  for (const newTrack of newTracks) {
2858
3103
  this.options.localStreamController.addTrack(newTrack);
2859
3104
  const trackKind = newTrack.kind;
2860
3105
  const transceiverOfKind = this.transceiverByKind(trackKind)[0];
2861
3106
  transceiverOfKind.direction = trackKind === "audio" ? this.audioDirection : this.videoDirection;
2862
- logger$12.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
3107
+ logger$13.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
2863
3108
  await transceiverOfKind.sender.replaceTrack(newTrack);
2864
3109
  }
2865
3110
  } catch (error) {
2866
- logger$12.error("[TransceiverController] restoreTrackSender error", kind, error);
3111
+ logger$13.error("[TransceiverController] restoreTrackSender error", kind, error);
2867
3112
  this.options.onError?.(new require_operators.MediaTrackError("restoreTrackSender", kind, error));
2868
3113
  }
2869
3114
  }
@@ -2904,10 +3149,10 @@ var TransceiverController = class extends Destroyable {
2904
3149
  };
2905
3150
  try {
2906
3151
  await track.applyConstraints(constraintsToApply);
2907
- logger$12.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
2908
- logger$12.debug(`[TransceiverController] Updated ${kind} sender constraints:`, track.getConstraints());
3152
+ logger$13.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
3153
+ logger$13.debug(`[TransceiverController] Updated ${kind} sender constraints:`, track.getConstraints());
2909
3154
  } catch (error) {
2910
- logger$12.warn(`[TransceiverController] Failed to apply constraints to ${kind} track ${track.id}:`, error);
3155
+ logger$13.warn(`[TransceiverController] Failed to apply constraints to ${kind} track ${track.id}:`, error);
2911
3156
  this.options.onError?.(new require_operators.MediaTrackError("updateSendersConstraints", kind, error));
2912
3157
  }
2913
3158
  }
@@ -2941,7 +3186,7 @@ var TransceiverController = class extends Destroyable {
2941
3186
 
2942
3187
  //#endregion
2943
3188
  //#region src/controllers/RTCPeerConnectionController.ts
2944
- const logger$11 = require_operators.getLogger();
3189
+ const logger$12 = require_operators.getLogger();
2945
3190
  var RTCPeerConnectionController = class extends Destroyable {
2946
3191
  constructor(options = {}, remoteSessionDescription, deviceController) {
2947
3192
  super();
@@ -2957,43 +3202,43 @@ var RTCPeerConnectionController = class extends Destroyable {
2957
3202
  this.oniceconnectionstatechangeHandler = () => {
2958
3203
  if (this.peerConnection) {
2959
3204
  const { iceConnectionState } = this.peerConnection;
2960
- logger$11.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
3205
+ logger$12.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
2961
3206
  this._iceConnectionState$.next(this.peerConnection.iceConnectionState);
2962
3207
  }
2963
3208
  };
2964
3209
  this.onconnectionstatechangeHandler = () => {
2965
3210
  if (this.peerConnection) {
2966
3211
  const { connectionState } = this.peerConnection;
2967
- logger$11.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
3212
+ logger$12.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
2968
3213
  if (connectionState === "connected") this.removeConnectionTimer();
2969
3214
  this._connectionState$.next(this.peerConnection.connectionState);
2970
3215
  }
2971
3216
  };
2972
3217
  this.onsignalingstatechangeHandler = () => {
2973
- logger$11.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
3218
+ logger$12.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
2974
3219
  };
2975
3220
  this.onicegatheringstatechangeHandler = () => {
2976
3221
  if (this.peerConnection) this._iceGatheringState$.next(this.peerConnection.iceGatheringState);
2977
3222
  };
2978
3223
  this.onnegotiationneededHandler = (event) => {
2979
- logger$11.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
3224
+ logger$12.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
2980
3225
  this.negotiationNeeded$.next();
2981
3226
  };
2982
3227
  this.updateSelectedInputDevice = async (kind, deviceInfo) => {
2983
3228
  try {
2984
3229
  const { localStream } = this;
2985
3230
  if (!localStream) {
2986
- logger$11.warn("[RTCPeerConnectionController] No local stream available to update input device.");
3231
+ logger$12.warn("[RTCPeerConnectionController] No local stream available to update input device.");
2987
3232
  return;
2988
3233
  }
2989
- logger$11.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
3234
+ logger$12.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
2990
3235
  const track = localStream.getTracks().find((track$1) => track$1.kind === kind);
2991
3236
  if (track) {
2992
3237
  this.transceiverController?.stopTrackSender(kind);
2993
3238
  this.localStream?.removeTrack(track);
2994
- logger$11.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
3239
+ logger$12.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
2995
3240
  if (!deviceInfo) {
2996
- logger$11.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
3241
+ logger$12.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
2997
3242
  return;
2998
3243
  }
2999
3244
  const streamTrack = (await this.getUserMedia({ [kind]: {
@@ -3001,15 +3246,15 @@ var RTCPeerConnectionController = class extends Destroyable {
3001
3246
  ...this.deviceController.deviceInfoToConstraints(deviceInfo)
3002
3247
  } })).getTracks().find((t) => t.kind === kind);
3003
3248
  if (streamTrack) {
3004
- logger$11.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
3249
+ logger$12.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
3005
3250
  this.localStream?.addTrack(streamTrack);
3006
3251
  await this.transceiverController?.replaceSenderTrack(kind, streamTrack);
3007
- logger$11.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
3252
+ logger$12.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
3008
3253
  }
3009
3254
  }
3010
- logger$11.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
3255
+ logger$12.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
3011
3256
  } catch (error) {
3012
- logger$11.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
3257
+ logger$12.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
3013
3258
  this._errors$.next(error);
3014
3259
  throw error;
3015
3260
  }
@@ -3238,15 +3483,15 @@ var RTCPeerConnectionController = class extends Destroyable {
3238
3483
  this.setupPeerConnection();
3239
3484
  this.subscribeTo(this.negotiationNeeded$.pipe((0, rxjs.auditTime)(0), (0, rxjs.exhaustMap)(async () => this.startNegotiation())), {
3240
3485
  next: () => {
3241
- logger$11.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
3486
+ logger$12.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
3242
3487
  },
3243
3488
  error: (error) => {
3244
- logger$11.error("[RTCPeerConnectionController] Start Negotiation error:", error);
3489
+ logger$12.error("[RTCPeerConnectionController] Start Negotiation error:", error);
3245
3490
  this._errors$.next(error);
3246
3491
  }
3247
3492
  });
3248
3493
  this.subscribeTo((0, rxjs.merge)(this.deviceController.selectedAudioInputDevice$.pipe((0, rxjs.map)((deviceInfo) => ["audio", deviceInfo])), this.deviceController.selectedVideoInputDevice$.pipe((0, rxjs.map)((deviceInfo) => ["video", deviceInfo]))).pipe((0, rxjs.skipWhile)(() => !this.localStreamController.localStream)), async ([kind, deviceInfo]) => {
3249
- logger$11.debug(`[RTCPeerConnectionController] Selected input device changed for:`, {
3494
+ logger$12.debug(`[RTCPeerConnectionController] Selected input device changed for:`, {
3250
3495
  kind,
3251
3496
  deviceInfo
3252
3497
  });
@@ -3263,7 +3508,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3263
3508
  this._initialized$.next(true);
3264
3509
  }
3265
3510
  } catch (error) {
3266
- logger$11.error("[RTCPeerConnectionController] Initialization error:", error);
3511
+ logger$12.error("[RTCPeerConnectionController] Initialization error:", error);
3267
3512
  this._errors$.next(error);
3268
3513
  this.destroy();
3269
3514
  }
@@ -3295,22 +3540,22 @@ var RTCPeerConnectionController = class extends Destroyable {
3295
3540
  }
3296
3541
  async startNegotiation() {
3297
3542
  if (this.isNegotiating) {
3298
- logger$11.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
3543
+ logger$12.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
3299
3544
  return;
3300
3545
  }
3301
3546
  this.setupEventListeners();
3302
3547
  if (this.type === "answer") {
3303
- logger$11.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");
3548
+ logger$12.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");
3304
3549
  return;
3305
3550
  }
3306
3551
  this._isNegotiating$.next(true);
3307
- logger$11.debug("[RTCPeerConnectionController] Starting negotiation.");
3552
+ logger$12.debug("[RTCPeerConnectionController] Starting negotiation.");
3308
3553
  try {
3309
3554
  const { offerOptions } = this;
3310
- logger$11.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
3555
+ logger$12.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
3311
3556
  await this.createOffer(offerOptions);
3312
3557
  } catch (error) {
3313
- logger$11.error("[RTCPeerConnectionController] Error during negotiation:", error);
3558
+ logger$12.error("[RTCPeerConnectionController] Error during negotiation:", error);
3314
3559
  this._errors$.next(error);
3315
3560
  }
3316
3561
  }
@@ -3326,14 +3571,14 @@ var RTCPeerConnectionController = class extends Destroyable {
3326
3571
  let readyToConnect = status !== "failed";
3327
3572
  try {
3328
3573
  if (status === "received" && sdp) {
3329
- logger$11.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
3574
+ logger$12.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
3330
3575
  await this._setRemoteDescription({
3331
3576
  type: "answer",
3332
3577
  sdp
3333
3578
  });
3334
3579
  }
3335
3580
  } catch (error) {
3336
- logger$11.error("[RTCPeerConnectionController] Error updating answer status:", error);
3581
+ logger$12.error("[RTCPeerConnectionController] Error updating answer status:", error);
3337
3582
  this._errors$.next(error);
3338
3583
  readyToConnect = false;
3339
3584
  } finally {
@@ -3352,7 +3597,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3352
3597
  await this.handleOfferReceived();
3353
3598
  break;
3354
3599
  case "failed":
3355
- logger$11.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
3600
+ logger$12.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
3356
3601
  break;
3357
3602
  case "sent":
3358
3603
  default:
@@ -3384,7 +3629,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3384
3629
  }
3385
3630
  await this.setupLocalTracks();
3386
3631
  const { answerOptions } = this;
3387
- logger$11.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
3632
+ logger$12.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
3388
3633
  await this.createAnswer(answerOptions);
3389
3634
  }
3390
3635
  async handleOfferReceived() {
@@ -3392,7 +3637,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3392
3637
  this._isNegotiating$.next(true);
3393
3638
  await this._setRemoteDescription(this.sdpInit);
3394
3639
  const { answerOptions } = this;
3395
- logger$11.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
3640
+ logger$12.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
3396
3641
  await this.createAnswer(answerOptions);
3397
3642
  }
3398
3643
  readyToConnect() {
@@ -3400,7 +3645,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3400
3645
  this.connectionTimer = setTimeout(() => {
3401
3646
  this.removeConnectionTimer();
3402
3647
  if (this.peerConnection?.connectionState !== "connected") {
3403
- logger$11.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only.");
3648
+ logger$12.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only.");
3404
3649
  this.iceGatheringController.restartICEGatheringWithRelayOnly();
3405
3650
  }
3406
3651
  }, this.connectionTimeout);
@@ -3460,13 +3705,13 @@ var RTCPeerConnectionController = class extends Destroyable {
3460
3705
  await this.setupRemoteTracks();
3461
3706
  }
3462
3707
  async setupLocalTracks() {
3463
- logger$11.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
3708
+ logger$12.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
3464
3709
  const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
3465
3710
  if (this.transceiverController?.useAddStream ?? false) {
3466
- logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
3711
+ logger$12.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
3467
3712
  this.peerConnection?.addStream(localStream);
3468
3713
  if (!this.isNegotiating) {
3469
- logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
3714
+ logger$12.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
3470
3715
  this.negotiationNeeded$.next();
3471
3716
  }
3472
3717
  return;
@@ -3482,7 +3727,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3482
3727
  const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
3483
3728
  await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
3484
3729
  } else {
3485
- logger$11.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
3730
+ logger$12.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
3486
3731
  this.peerConnection?.addTrack(track, localStream);
3487
3732
  }
3488
3733
  }
@@ -3499,7 +3744,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3499
3744
  async setupRemoteTracks() {
3500
3745
  if (!this.peerConnection) throw new require_operators.DependencyError("RTCPeerConnection is not initialized");
3501
3746
  this.peerConnection.ontrack = (event) => {
3502
- logger$11.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
3747
+ logger$12.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
3503
3748
  if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
3504
3749
  else {
3505
3750
  const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
@@ -3525,9 +3770,9 @@ var RTCPeerConnectionController = class extends Destroyable {
3525
3770
  try {
3526
3771
  const localStream = this.localStreamController.addTrack(track);
3527
3772
  this.peerConnection.addTrack(track, localStream);
3528
- logger$11.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
3773
+ logger$12.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
3529
3774
  } catch (error) {
3530
- logger$11.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
3775
+ logger$12.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
3531
3776
  this._errors$.next(error);
3532
3777
  throw error;
3533
3778
  }
@@ -3544,15 +3789,15 @@ var RTCPeerConnectionController = class extends Destroyable {
3544
3789
  }
3545
3790
  const sender = this.peerConnection.getSenders().find((sender$1) => sender$1.track?.id === trackId);
3546
3791
  if (!sender) {
3547
- logger$11.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
3792
+ logger$12.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
3548
3793
  return;
3549
3794
  }
3550
3795
  try {
3551
3796
  this.peerConnection.removeTrack(sender);
3552
3797
  this.localStreamController.removeTrack(trackId);
3553
- logger$11.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
3798
+ logger$12.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
3554
3799
  } catch (error) {
3555
- logger$11.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
3800
+ logger$12.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
3556
3801
  this._errors$.next(error);
3557
3802
  throw error;
3558
3803
  }
@@ -3575,7 +3820,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3575
3820
  * Completes all observables to prevent memory leaks.
3576
3821
  */
3577
3822
  destroy() {
3578
- logger$11.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
3823
+ logger$12.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
3579
3824
  this.removeConnectionTimer();
3580
3825
  this._iceGatheringController?.destroy();
3581
3826
  this.localStreamController.destroy();
@@ -3599,7 +3844,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3599
3844
  }
3600
3845
  stopRemoteTracks() {
3601
3846
  this._remoteStream$.value?.getTracks().forEach((track) => {
3602
- logger$11.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
3847
+ logger$12.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
3603
3848
  track.stop();
3604
3849
  });
3605
3850
  }
@@ -3616,7 +3861,7 @@ var RTCPeerConnectionController = class extends Destroyable {
3616
3861
  ...params,
3617
3862
  sdp: finalRemote
3618
3863
  };
3619
- logger$11.debug("[RTCPeerConnectionController] Setting remote description:", answer);
3864
+ logger$12.debug("[RTCPeerConnectionController] Setting remote description:", answer);
3620
3865
  return this.peerConnection.setRemoteDescription(answer);
3621
3866
  }
3622
3867
  };
@@ -3654,7 +3899,7 @@ function isVertoPingInnerParams(value) {
3654
3899
 
3655
3900
  //#endregion
3656
3901
  //#region src/managers/VertoManager.ts
3657
- const logger$10 = require_operators.getLogger();
3902
+ const logger$11 = require_operators.getLogger();
3658
3903
  var VertoManager = class extends Destroyable {
3659
3904
  constructor(callSession) {
3660
3905
  super();
@@ -3692,7 +3937,7 @@ var WebRTCVertoManager = class extends VertoManager {
3692
3937
  try {
3693
3938
  await this.executeVerto(vertoModifyMessage);
3694
3939
  } catch (error) {
3695
- logger$10.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:", error);
3940
+ logger$11.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:", error);
3696
3941
  throw error;
3697
3942
  }
3698
3943
  }
@@ -3705,7 +3950,7 @@ var WebRTCVertoManager = class extends VertoManager {
3705
3950
  try {
3706
3951
  await this.executeVerto(vertoModifyMessage);
3707
3952
  } catch (error) {
3708
- logger$10.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:", error);
3953
+ logger$11.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:", error);
3709
3954
  throw error;
3710
3955
  }
3711
3956
  }
@@ -3758,7 +4003,7 @@ var WebRTCVertoManager = class extends VertoManager {
3758
4003
  if (event.member_id) this.setSelfIdIfNull(event.member_id);
3759
4004
  });
3760
4005
  this.subscribeTo(this.vertoMedia$, (event) => {
3761
- logger$10.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
4006
+ logger$11.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
3762
4007
  this._signalingStatus$.next("ringing");
3763
4008
  const { sdp, callID } = event;
3764
4009
  this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
@@ -3767,7 +4012,7 @@ var WebRTCVertoManager = class extends VertoManager {
3767
4012
  });
3768
4013
  });
3769
4014
  this.subscribeTo(this.vertoAnswer$, (event) => {
3770
- logger$10.debug("[WebRTCManager] Received Verto answer event:", event);
4015
+ logger$11.debug("[WebRTCManager] Received Verto answer event:", event);
3771
4016
  this._signalingStatus$.next("connecting");
3772
4017
  const { sdp, callID } = event;
3773
4018
  this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
@@ -3776,7 +4021,7 @@ var WebRTCVertoManager = class extends VertoManager {
3776
4021
  });
3777
4022
  });
3778
4023
  this.subscribeTo(this.vertoMediaParams$, (event) => {
3779
- logger$10.debug("[WebRTCManager] Received Verto mediaParams event:", event);
4024
+ logger$11.debug("[WebRTCManager] Received Verto mediaParams event:", event);
3780
4025
  const { mediaParams, callID } = event;
3781
4026
  const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callID);
3782
4027
  const { audio, video } = mediaParams;
@@ -3800,13 +4045,13 @@ var WebRTCVertoManager = class extends VertoManager {
3800
4045
  */
3801
4046
  setNodeIdIfNull(nodeId) {
3802
4047
  if (!this._nodeId$.value && nodeId) {
3803
- logger$10.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
4048
+ logger$11.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
3804
4049
  this._nodeId$.next(nodeId);
3805
4050
  }
3806
4051
  }
3807
4052
  setSelfIdIfNull(selfId) {
3808
4053
  if (!this._selfId$.value && selfId) {
3809
- logger$10.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
4054
+ logger$11.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
3810
4055
  this._selfId$.next(selfId);
3811
4056
  }
3812
4057
  }
@@ -3815,7 +4060,7 @@ var WebRTCVertoManager = class extends VertoManager {
3815
4060
  const vertoPongMessage = VertoPong({ ...vertoPing });
3816
4061
  await this.executeVerto(vertoPongMessage);
3817
4062
  } catch (error) {
3818
- logger$10.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:", error);
4063
+ logger$11.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:", error);
3819
4064
  this.onError?.(new require_operators.VertoPongError(error));
3820
4065
  }
3821
4066
  }
@@ -3825,7 +4070,7 @@ var WebRTCVertoManager = class extends VertoManager {
3825
4070
  if (audio) await this.mainPeerConnection.updateSendersConstraints("audio", audio);
3826
4071
  if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
3827
4072
  } catch (error) {
3828
- logger$10.warn("[WebRTCManager] Error updating media constraints:", error);
4073
+ logger$11.warn("[WebRTCManager] Error updating media constraints:", error);
3829
4074
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
3830
4075
  throw error;
3831
4076
  }
@@ -3890,7 +4135,7 @@ var WebRTCVertoManager = class extends VertoManager {
3890
4135
  default:
3891
4136
  }
3892
4137
  } catch (error) {
3893
- logger$10.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
4138
+ logger$11.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
3894
4139
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
3895
4140
  }
3896
4141
  }
@@ -3904,7 +4149,7 @@ var WebRTCVertoManager = class extends VertoManager {
3904
4149
  sdp
3905
4150
  });
3906
4151
  } catch (error) {
3907
- logger$10.warn("[WebRTCManager] Error processing modify response:", error);
4152
+ logger$11.warn("[WebRTCManager] Error processing modify response:", error);
3908
4153
  const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
3909
4154
  this.onError?.(modifyError);
3910
4155
  }
@@ -3916,7 +4161,7 @@ var WebRTCVertoManager = class extends VertoManager {
3916
4161
  this._nodeId$.next(require_operators.getValueFrom(response, "result.node_id") ?? null);
3917
4162
  const memberId = require_operators.getValueFrom(response, "result.result.result.memberID") ?? null;
3918
4163
  const callId = require_operators.getValueFrom(response, "result.result.result.callID") ?? null;
3919
- logger$10.debug("[WebRTCManager] Verto invite response:", {
4164
+ logger$11.debug("[WebRTCManager] Verto invite response:", {
3920
4165
  callId,
3921
4166
  memberId,
3922
4167
  response
@@ -3925,10 +4170,10 @@ var WebRTCVertoManager = class extends VertoManager {
3925
4170
  rtcPeerConnController.setMemberId(memberId);
3926
4171
  if (callId) this.webRtcCallSession.addCallId(callId);
3927
4172
  this.attachManager.attach(this.webRtcCallSession);
3928
- logger$10.info("[WebRTCManager] Verto invite successful");
3929
- logger$10.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
4173
+ logger$11.info("[WebRTCManager] Verto invite successful");
4174
+ logger$11.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
3930
4175
  } else {
3931
- logger$10.error("[WebRTCManager] Verto invite failed:", response);
4176
+ logger$11.error("[WebRTCManager] Verto invite failed:", response);
3932
4177
  const inviteError = response.error ? new require_operators.JSONRPCError(response.error.code, response.error.message, response.error.data) : /* @__PURE__ */ new Error("Verto invite failed: unexpected response");
3933
4178
  this.onError?.(inviteError);
3934
4179
  }
@@ -3970,17 +4215,17 @@ var WebRTCVertoManager = class extends VertoManager {
3970
4215
  if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
3971
4216
  }
3972
4217
  async handleInboundAnswer(rtcPeerConnController) {
3973
- logger$10.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
4218
+ logger$11.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
3974
4219
  const vertoByeOrAccepted = await (0, rxjs.firstValueFrom)((0, rxjs.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, rxjs.takeUntil)(this.destroyed$))).catch(() => null);
3975
4220
  if (vertoByeOrAccepted === null) {
3976
- logger$10.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
4221
+ logger$11.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
3977
4222
  return;
3978
4223
  }
3979
4224
  if (isVertoByeMessage(vertoByeOrAccepted)) {
3980
- logger$10.info("[WebRTCManager] Inbound call ended by remote before answer.");
4225
+ logger$11.info("[WebRTCManager] Inbound call ended by remote before answer.");
3981
4226
  this.callSession?.destroy();
3982
4227
  } else if (!vertoByeOrAccepted) {
3983
- logger$10.info("[WebRTCManager] Inbound call rejected by user.");
4228
+ logger$11.info("[WebRTCManager] Inbound call rejected by user.");
3984
4229
  try {
3985
4230
  await this.bye("USER_BUSY");
3986
4231
  } finally {
@@ -3988,19 +4233,19 @@ var WebRTCVertoManager = class extends VertoManager {
3988
4233
  this.callSession?.destroy();
3989
4234
  }
3990
4235
  } else {
3991
- logger$10.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
4236
+ logger$11.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
3992
4237
  const answerOptions = this.webRtcCallSession.answerMediaOptions;
3993
4238
  try {
3994
4239
  await rtcPeerConnController.acceptInbound(answerOptions);
3995
4240
  } catch (error) {
3996
- logger$10.error("[WebRTCManager] Error creating inbound answer:", error);
4241
+ logger$11.error("[WebRTCManager] Error creating inbound answer:", error);
3997
4242
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
3998
4243
  }
3999
4244
  }
4000
4245
  }
4001
4246
  setupVertoAttachHandler() {
4002
4247
  this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
4003
- logger$10.debug("[WebRTCManager] Received Verto attach event:", vertoAttach);
4248
+ logger$11.debug("[WebRTCManager] Received Verto attach event:", vertoAttach);
4004
4249
  const { callID } = vertoAttach;
4005
4250
  await this.attachManager.attach({
4006
4251
  id: callID,
@@ -4068,13 +4313,13 @@ var WebRTCVertoManager = class extends VertoManager {
4068
4313
  };
4069
4314
  }
4070
4315
  async sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnectionController) {
4071
- logger$10.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
4316
+ logger$11.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
4072
4317
  const vertoByeOrAccepted = await (0, rxjs.firstValueFrom)((0, rxjs.race)(this.vertoBye$, this.webRtcCallSession.answered$));
4073
4318
  if (isVertoByeMessage(vertoByeOrAccepted)) {
4074
- logger$10.info("[WebRTCManager] Call ended before answer was sent.");
4319
+ logger$11.info("[WebRTCManager] Call ended before answer was sent.");
4075
4320
  this.callSession?.destroy();
4076
4321
  } else if (!vertoByeOrAccepted) {
4077
- logger$10.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
4322
+ logger$11.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
4078
4323
  try {
4079
4324
  await this.bye("USER_BUSY");
4080
4325
  } finally {
@@ -4082,14 +4327,14 @@ var WebRTCVertoManager = class extends VertoManager {
4082
4327
  this.callSession?.destroy();
4083
4328
  }
4084
4329
  } else {
4085
- logger$10.debug("[WebRTCManager] Call accepted, sending answer");
4330
+ logger$11.debug("[WebRTCManager] Call accepted, sending answer");
4086
4331
  try {
4087
4332
  this._signalingStatus$.next("connecting");
4088
4333
  await this.sendLocalDescription(vertoMessageRequest, rtcPeerConnectionController);
4089
4334
  await rtcPeerConnectionController.updateAnswerStatus({ status: "sent" });
4090
4335
  await this.attachManager.attach(this.webRtcCallSession);
4091
4336
  } catch (error) {
4092
- logger$10.error("[WebRTCManager] Error sending Verto answer:", error);
4337
+ logger$11.error("[WebRTCManager] Error sending Verto answer:", error);
4093
4338
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
4094
4339
  await rtcPeerConnectionController.updateAnswerStatus({ status: "failed" });
4095
4340
  }
@@ -4180,10 +4425,10 @@ var WebRTCVertoManager = class extends VertoManager {
4180
4425
  });
4181
4426
  await (0, rxjs.firstValueFrom)(rtcPeerConnController.connectionState$.pipe((0, rxjs.filter)((state) => state === "connected"), (0, rxjs.take)(1), (0, rxjs.timeout)(this._screenShareTimeoutMs)));
4182
4427
  this._screenShareStatus$.next("started");
4183
- logger$10.info("[WebRTCManager] Screen share started successfully.");
4428
+ logger$11.info("[WebRTCManager] Screen share started successfully.");
4184
4429
  return rtcPeerConnController.id;
4185
4430
  } catch (error) {
4186
- logger$10.warn("[WebRTCManager] Error initializing additional peer connection:", error);
4431
+ logger$11.warn("[WebRTCManager] Error initializing additional peer connection:", error);
4187
4432
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
4188
4433
  if (rtcPeerConnController) rtcPeerConnController.destroy();
4189
4434
  this._screenShareStatus$.next("none");
@@ -4202,9 +4447,9 @@ var WebRTCVertoManager = class extends VertoManager {
4202
4447
  if (removeTrack) return this.mainPeerConnection.stopTrackSender(removeTrack, { updateTransceiverDirection: true });
4203
4448
  }
4204
4449
  async removeScreenMedia() {
4205
- if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$10.warn("[WebRTCManager] No active screen share to stop.");
4450
+ if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$11.warn("[WebRTCManager] No active screen share to stop.");
4206
4451
  if (!this._screenShareId) {
4207
- logger$10.debug("[WebRTCManager] No screen share peer connection found.");
4452
+ logger$11.debug("[WebRTCManager] No screen share peer connection found.");
4208
4453
  return;
4209
4454
  }
4210
4455
  this._screenShareStatus$.next("stopping");
@@ -4233,7 +4478,7 @@ var WebRTCVertoManager = class extends VertoManager {
4233
4478
  dialogParams: this.dialogParams(rtcPeerConnController)
4234
4479
  }));
4235
4480
  } catch (error) {
4236
- logger$10.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
4481
+ logger$11.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
4237
4482
  throw error;
4238
4483
  }
4239
4484
  }
@@ -4251,7 +4496,7 @@ var WebRTCVertoManager = class extends VertoManager {
4251
4496
  try {
4252
4497
  await this.executeVerto(vertoInfoMessage);
4253
4498
  } catch (error) {
4254
- logger$10.warn("[WebRTCManager] Error sending DTMF digits:", error);
4499
+ logger$11.warn("[WebRTCManager] Error sending DTMF digits:", error);
4255
4500
  throw error;
4256
4501
  }
4257
4502
  }
@@ -4262,10 +4507,10 @@ var WebRTCVertoManager = class extends VertoManager {
4262
4507
  action: "transfer"
4263
4508
  });
4264
4509
  try {
4265
- logger$10.debug("[WebRTCManager] Transferring call with options:", options);
4510
+ logger$11.debug("[WebRTCManager] Transferring call with options:", options);
4266
4511
  await this.executeVerto(message);
4267
4512
  } catch (error) {
4268
- logger$10.error("[WebRTCManager] Error transferring call:", error);
4513
+ logger$11.error("[WebRTCManager] Error transferring call:", error);
4269
4514
  throw error;
4270
4515
  }
4271
4516
  }
@@ -4307,7 +4552,7 @@ var ParticipantFactory = class {
4307
4552
 
4308
4553
  //#endregion
4309
4554
  //#region src/core/entities/Call.ts
4310
- const logger$9 = require_operators.getLogger();
4555
+ const logger$10 = require_operators.getLogger();
4311
4556
  const fromDestinationParams = (destination) => {
4312
4557
  if (!destination) return {};
4313
4558
  try {
@@ -4318,7 +4563,7 @@ const fromDestinationParams = (destination) => {
4318
4563
  });
4319
4564
  return params;
4320
4565
  } catch (error) {
4321
- logger$9.warn(`Failed to parse destination URI: ${destination}`, error);
4566
+ logger$10.warn(`Failed to parse destination URI: ${destination}`, error);
4322
4567
  return {};
4323
4568
  }
4324
4569
  };
@@ -4493,7 +4738,7 @@ var WebRTCCall = class extends Destroyable {
4493
4738
  if (isJSONRPCErrorResponse(response)) throw new require_operators.JSONRPCError(parseInt(response.result?.code ?? "0"), `Error response from method ${method}: ${response.result?.code} ${response.result?.message}`, void 0, void 0, request.id);
4494
4739
  return response;
4495
4740
  } catch (error) {
4496
- logger$9.error(`[Call] Error executing method ${method} with params`, params, error);
4741
+ logger$10.error(`[Call] Error executing method ${method} with params`, params, error);
4497
4742
  throw error;
4498
4743
  }
4499
4744
  }
@@ -4674,18 +4919,20 @@ var WebRTCCall = class extends Destroyable {
4674
4919
  }
4675
4920
  isCallSessionEvent(event) {
4676
4921
  try {
4677
- logger$9.debug("[Call] Checking if event is for this call session:", event);
4922
+ logger$10.debug("[Call] Checking if event is for this call session:", event);
4678
4923
  const callId = require_operators.getValueFrom(event, "params.params.callID") ?? require_operators.getValueFrom(event, "params.call_id");
4679
4924
  const roomSessionId = require_operators.getValueFrom(event, "params.room_session_id");
4680
- logger$9.debug(`[Call] Extracted session identifiers callID: ${callId} and roomSessionID: ${roomSessionId} from event:`);
4925
+ logger$10.debug(`[Call] Extracted session identifiers callID: ${callId} and roomSessionID: ${roomSessionId} from event:`);
4681
4926
  return callId === this.id || !!callId && this.callEventsManager.isCallIdValid(callId) || !!roomSessionId && this.callEventsManager.isRoomSessionIdValid(roomSessionId);
4682
4927
  } catch (error) {
4683
- logger$9.error("[Call] Error checking if event is for this call session:", error);
4928
+ logger$10.error("[Call] Error checking if event is for this call session:", error);
4684
4929
  return false;
4685
4930
  }
4686
4931
  }
4687
4932
  get callSessionEvents$() {
4688
- return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, rxjs.filter)((event) => this.isCallSessionEvent(event)), (0, rxjs.tap)((event) => logger$9.debug("[Call] Received call session event:", event)), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
4933
+ return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, rxjs.filter)((event) => this.isCallSessionEvent(event)), (0, rxjs.tap)((event) => {
4934
+ logger$10.debug("[Call] Received call session event:", event);
4935
+ }), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
4689
4936
  }
4690
4937
  /** Observable of call-updated events. */
4691
4938
  get callUpdated$() {
@@ -4725,11 +4972,11 @@ var WebRTCCall = class extends Destroyable {
4725
4972
  }
4726
4973
  /** Observable of WebRTC-specific signaling messages. */
4727
4974
  get webrtcMessages$() {
4728
- return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isWebrtcMessageMetadata, "params"), (0, rxjs.tap)((event) => logger$9.debug("[Call] Event is a WebRTC message event:", event)), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
4975
+ return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isWebrtcMessageMetadata, "params"), (0, rxjs.tap)((event) => logger$10.debug("[Call] Event is a WebRTC message event:", event)), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
4729
4976
  }
4730
4977
  /** Observable of call-level signaling events. */
4731
4978
  get callEvent$() {
4732
- return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isSignalwireCallMetadata, "params"), (0, rxjs.tap)((event) => logger$9.debug("[Call] Event is a call event:", event)), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
4979
+ return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(require_operators.filterAs(isSignalwireCallMetadata, "params"), (0, rxjs.tap)((event) => logger$10.debug("[Call] Event is a call event:", event)), (0, rxjs.takeUntil)(this.destroyed$), (0, rxjs.share)()));
4733
4980
  }
4734
4981
  /** Observable of layout-changed signaling events. */
4735
4982
  get layoutEvent$() {
@@ -4904,7 +5151,7 @@ var CallFactory = class {
4904
5151
 
4905
5152
  //#endregion
4906
5153
  //#region src/behaviors/Collection.ts
4907
- const logger$8 = require_operators.getLogger();
5154
+ const logger$9 = require_operators.getLogger();
4908
5155
  var Fetcher = class {
4909
5156
  constructor(endpoint, params, http) {
4910
5157
  this.endpoint = endpoint;
@@ -4928,7 +5175,7 @@ var Fetcher = class {
4928
5175
  this.hasMore = !!this.nextUrl;
4929
5176
  return result.data.filter(this.filter).map(this.mapper);
4930
5177
  }
4931
- logger$8.error("Failed to fetch entity");
5178
+ logger$9.error("Failed to fetch entity");
4932
5179
  return [];
4933
5180
  }
4934
5181
  async id(v) {
@@ -4991,7 +5238,7 @@ var EntityCollection = class extends Destroyable {
4991
5238
  this._hasMore$.next(this.fetchController.hasMore ?? false);
4992
5239
  this.loading$.next(false);
4993
5240
  } catch (error) {
4994
- logger$8.error(`Failed to fetch initial collection data`, error);
5241
+ logger$9.error(`Failed to fetch initial collection data`, error);
4995
5242
  this._hasMore$.next(this.fetchController.hasMore ?? false);
4996
5243
  this.loading$.next(false);
4997
5244
  this.onError?.(new require_operators.CollectionFetchError("fetchMore", error));
@@ -5005,7 +5252,7 @@ var EntityCollection = class extends Destroyable {
5005
5252
  if (data) this.upsertData(data);
5006
5253
  return data;
5007
5254
  } catch (error) {
5008
- logger$8.error(`Failed to fetch data for (${String(key)}:${String(value)}) :`, error);
5255
+ logger$9.error(`Failed to fetch data for (${String(key)}:${String(value)}) :`, error);
5009
5256
  this.loading$.next(false);
5010
5257
  this.onError?.(new require_operators.CollectionFetchError(`tryFetch(${String(key)})`, error));
5011
5258
  }
@@ -5035,9 +5282,9 @@ var EntityCollection = class extends Destroyable {
5035
5282
  }
5036
5283
  };
5037
5284
  var EntityCollectionTransformed = class {
5038
- constructor(originalCollection, filter$10 = (i) => !!i, mapper = (item) => item) {
5285
+ constructor(originalCollection, filter$11 = (i) => !!i, mapper = (item) => item) {
5039
5286
  this.originalCollection = originalCollection;
5040
- this.filter = filter$10;
5287
+ this.filter = filter$11;
5041
5288
  this.mapper = mapper;
5042
5289
  }
5043
5290
  get loading$() {
@@ -5254,13 +5501,13 @@ var Address = class extends Destroyable {
5254
5501
 
5255
5502
  //#endregion
5256
5503
  //#region src/core/utils.ts
5257
- const logger$7 = require_operators.getLogger();
5504
+ const logger$8 = require_operators.getLogger();
5258
5505
  const isRPCConnectResult = (e) => {
5259
- logger$7.debug("isRPCConnectResult check:", e);
5506
+ logger$8.debug("isRPCConnectResult check:", e);
5260
5507
  if (!e || typeof e !== "object") return false;
5261
5508
  const result = e;
5262
5509
  const is = typeof result.identity === "string" && typeof result.protocol === "string" && typeof result.authorization === "object" && typeof result.authorization.jti === "string" && typeof result.authorization.project_id === "string" && typeof result.authorization.fabric_subscriber === "object";
5263
- logger$7.debug("isRPCConnectResult check result:", is);
5510
+ logger$8.debug("isRPCConnectResult check result:", is);
5264
5511
  return is;
5265
5512
  };
5266
5513
  var PendingRPC = class PendingRPC {
@@ -5269,7 +5516,7 @@ var PendingRPC = class PendingRPC {
5269
5516
  }
5270
5517
  constructor(request, responses$, options) {
5271
5518
  this.id = (0, uuid.v4)();
5272
- logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}: method:${request.method}] Creating PendingRPC`);
5519
+ logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}: method:${request.method}] Creating PendingRPC`);
5273
5520
  this.request = request;
5274
5521
  const timeoutMs = options?.timeoutMs ?? PendingRPC.defaultTimeoutMs;
5275
5522
  const signal = options?.signal;
@@ -5280,10 +5527,10 @@ var PendingRPC = class PendingRPC {
5280
5527
  }
5281
5528
  let isSettled = false;
5282
5529
  const subscription = (0, rxjs.race)(responses$.pipe((0, rxjs.filter)((result) => result.id === request.id), (0, rxjs.take)(1)), new rxjs.Observable((subscriber) => {
5283
- const timer = setTimeout(() => {
5530
+ const timer$1 = setTimeout(() => {
5284
5531
  subscriber.error(new require_operators.RPCTimeoutError(request.id, timeoutMs));
5285
5532
  }, timeoutMs);
5286
- return () => clearTimeout(timer);
5533
+ return () => clearTimeout(timer$1);
5287
5534
  }), signal ? new rxjs.Observable((subscriber) => {
5288
5535
  const abortHandler = () => {
5289
5536
  subscriber.error(new DOMException("The operation was aborted", "AbortError"));
@@ -5295,22 +5542,22 @@ var PendingRPC = class PendingRPC {
5295
5542
  isSettled = true;
5296
5543
  if (response.error) {
5297
5544
  const rpcError = new require_operators.JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
5298
- logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
5545
+ logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
5299
5546
  reject(rpcError);
5300
5547
  } else {
5301
- logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
5548
+ logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
5302
5549
  resolve(response);
5303
5550
  }
5304
5551
  subscription.unsubscribe();
5305
5552
  },
5306
5553
  error: (error) => {
5307
- logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with error:`, error);
5554
+ logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with error:`, error);
5308
5555
  isSettled = true;
5309
5556
  reject(error);
5310
5557
  subscription.unsubscribe();
5311
5558
  },
5312
5559
  complete: () => {
5313
- logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
5560
+ logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
5314
5561
  if (!isSettled) reject(new require_operators.RPCTimeoutError(request.id, timeoutMs));
5315
5562
  subscription.unsubscribe();
5316
5563
  }
@@ -5330,7 +5577,7 @@ var PendingRPC = class PendingRPC {
5330
5577
 
5331
5578
  //#endregion
5332
5579
  //#region src/managers/ClientSessionManager.ts
5333
- const logger$6 = require_operators.getLogger();
5580
+ const logger$7 = require_operators.getLogger();
5334
5581
  const getAddressSearchURI = (options) => {
5335
5582
  const to = options.to?.split("?")[0];
5336
5583
  const from$6 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
@@ -5339,13 +5586,14 @@ const getAddressSearchURI = (options) => {
5339
5586
  return name;
5340
5587
  };
5341
5588
  var ClientSessionManager = class extends Destroyable {
5342
- constructor(credential, transport, storage, authorizationStateKey, deviceController, attachManager, webRTCApiProvider) {
5589
+ constructor(getCredential, transport, storage, authorizationStateKey, deviceController, attachManager, webRTCApiProvider, dpopManager) {
5343
5590
  super();
5344
- this.credential = credential;
5591
+ this.getCredential = getCredential;
5345
5592
  this.transport = transport;
5346
5593
  this.storage = storage;
5347
5594
  this.authorizationStateKey = authorizationStateKey;
5348
5595
  this.attachManager = attachManager;
5596
+ this.dpopManager = dpopManager;
5349
5597
  this.callCreateTimeout = 6e3;
5350
5598
  this.agent = `signalwire-typescript-sdk/1.0.0`;
5351
5599
  this.eventAcks = true;
@@ -5358,6 +5606,7 @@ var ClientSessionManager = class extends Destroyable {
5358
5606
  this._authorization$ = this.createBehaviorSubject(void 0);
5359
5607
  this._errors$ = this.createReplaySubject(1);
5360
5608
  this._authenticated$ = this.createBehaviorSubject(false);
5609
+ this._clientBound = false;
5361
5610
  this._subscriberInfo$ = this.createBehaviorSubject(null);
5362
5611
  this._calls$ = this.createBehaviorSubject({});
5363
5612
  this._iceServers$ = this.createBehaviorSubject([]);
@@ -5402,6 +5651,15 @@ var ClientSessionManager = class extends Destroyable {
5402
5651
  return this._authenticated$.value;
5403
5652
  }
5404
5653
  /**
5654
+ * Whether this session is client-bound (using a Client Bound SAT).
5655
+ * When client-bound, DPoP proof creation failures are treated as
5656
+ * authentication errors rather than silently degraded.
5657
+ * @internal
5658
+ */
5659
+ get clientBound() {
5660
+ return this._clientBound;
5661
+ }
5662
+ /**
5405
5663
  * Set the directory instance
5406
5664
  * Called by SignalWire after directory is created
5407
5665
  * @internal
@@ -5413,7 +5671,7 @@ var ClientSessionManager = class extends Destroyable {
5413
5671
  try {
5414
5672
  return await this.transport.execute(request, options);
5415
5673
  } catch (error) {
5416
- logger$6.debug("[Session] Execute Error", error);
5674
+ logger$7.debug("[Session] Execute Error", error);
5417
5675
  this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
5418
5676
  throw error;
5419
5677
  }
@@ -5427,32 +5685,31 @@ var ClientSessionManager = class extends Destroyable {
5427
5685
  return true;
5428
5686
  }
5429
5687
  setupMessageHandlers() {
5430
- logger$6.debug("[Session] Setting up message handlers");
5688
+ logger$7.debug("[Session] Setting up message handlers");
5431
5689
  this.subscribeTo(this.authStateEvent$, async (authStateEvent) => {
5432
- logger$6.debug("[Session] Authorization state event received:", authStateEvent);
5690
+ logger$7.debug("[Session] Authorization state event received:", authStateEvent);
5433
5691
  try {
5434
5692
  await this.updateAuthorizationStateInStorage(authStateEvent.authorization_state);
5435
5693
  } catch (error) {
5436
- logger$6.error("[Session] Failed to handle authorization state update:", error);
5694
+ logger$7.error("[Session] Failed to handle authorization state update:", error);
5437
5695
  this._errors$.next(new require_operators.AuthStateHandlerError(error));
5438
5696
  }
5439
5697
  });
5440
- this.subscribeTo(this.transport.connectionStatus$.pipe((0, rxjs.filter)((status) => status === "connected")), async () => {
5441
- try {
5442
- logger$6.debug("[Session] Connection established, initiating authentication");
5443
- await this.authenticate();
5444
- } catch (error) {
5698
+ this.subscribeTo(this.transport.connectionStatus$.pipe((0, rxjs.filter)((status) => status === "connected"), (0, rxjs.exhaustMap)(() => {
5699
+ logger$7.debug("[Session] Connection established, initiating authentication");
5700
+ return (0, rxjs.from)(this.authenticate()).pipe((0, rxjs.catchError)((error) => {
5445
5701
  this.handleAuthenticationError(error).catch((err) => {
5446
- logger$6.error("[Session] Error handling authentication failure:", err);
5702
+ logger$7.error("[Session] Error handling authentication failure:", err);
5447
5703
  });
5448
- }
5449
- });
5704
+ return rxjs.EMPTY;
5705
+ }));
5706
+ })), void 0);
5450
5707
  this.subscribeTo(this.vertoInvite$, async (invite) => {
5451
- logger$6.debug("[Session] Verto invite received:", invite);
5708
+ logger$7.debug("[Session] Verto invite received:", invite);
5452
5709
  try {
5453
5710
  await this.createInboundCall(invite);
5454
5711
  } catch (error) {
5455
- logger$6.error("[Session] Error handling Verto invite:", error);
5712
+ logger$7.error("[Session] Error handling Verto invite:", error);
5456
5713
  this._errors$.next(new require_operators.VertoInviteHandlerError(error));
5457
5714
  }
5458
5715
  });
@@ -5462,35 +5719,35 @@ var ClientSessionManager = class extends Destroyable {
5462
5719
  const storedState = await this.storage.getItem(this.authorizationStateKey);
5463
5720
  this.authorizationState$.next(storedState ?? void 0);
5464
5721
  } catch (error) {
5465
- logger$6.error("Failed to retrieve authorization state from storage:", error);
5722
+ logger$7.error("Failed to retrieve authorization state from storage:", error);
5466
5723
  this.authorizationState$.next(void 0);
5467
5724
  }
5468
5725
  }
5469
5726
  async updateAuthorizationStateInStorage(authorizationState) {
5470
5727
  if (!authorizationState) {
5471
- logger$6.debug("[Session] Removing authorization state from storage");
5728
+ logger$7.debug("[Session] Removing authorization state from storage");
5472
5729
  try {
5473
5730
  await this.storage.removeItem(this.authorizationStateKey);
5474
5731
  } catch (error) {
5475
- logger$6.error("Failed to remove authorization state from storage:", error);
5732
+ logger$7.error("Failed to remove authorization state from storage:", error);
5476
5733
  throw error;
5477
5734
  }
5478
5735
  return;
5479
5736
  }
5480
5737
  try {
5481
- logger$6.debug("[Session] Updating authorization state in storage");
5738
+ logger$7.debug("[Session] Updating authorization state in storage");
5482
5739
  await this.storage.setItem(this.authorizationStateKey, authorizationState);
5483
5740
  this.authorizationState$.next(authorizationState);
5484
5741
  } catch (error) {
5485
- logger$6.error("Failed to retrieve authorization state from storage:", error);
5742
+ logger$7.error("Failed to retrieve authorization state from storage:", error);
5486
5743
  throw error;
5487
5744
  }
5488
5745
  }
5489
5746
  get authStateEvent$() {
5490
5747
  return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, rxjs.tap)((msg) => {
5491
- logger$6.debug("[Session] Received incoming message:", msg);
5748
+ logger$7.debug("[Session] Received incoming message:", msg);
5492
5749
  }), require_operators.filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, rxjs.tap)((event) => {
5493
- logger$6.debug("[Session] Authorization state event received:", event.authorization_state);
5750
+ logger$7.debug("[Session] Authorization state event received:", event.authorization_state);
5494
5751
  })));
5495
5752
  }
5496
5753
  get signalingEvent$() {
@@ -5512,86 +5769,118 @@ var ClientSessionManager = class extends Destroyable {
5512
5769
  return [];
5513
5770
  }
5514
5771
  get authentication() {
5515
- if (!this.credential.token) throw new require_operators.DependencyError("Credential token is undefined");
5516
- return { jwt_token: this.credential.token };
5772
+ const credential = this.getCredential();
5773
+ if (!credential.token) throw new require_operators.DependencyError("Credential token is undefined");
5774
+ return { jwt_token: credential.token };
5517
5775
  }
5518
5776
  async connect() {
5519
5777
  await (0, rxjs.firstValueFrom)(this.initialized$);
5520
5778
  await this.transport.connect();
5521
5779
  }
5522
5780
  async handleAuthenticationError(error) {
5523
- logger$6.error("Authentication error:", error);
5781
+ logger$7.error("Authentication error:", error);
5524
5782
  this._errors$.next(error);
5525
- if (error.message === "Requester validation failed") try {
5526
- await this.cleanupStoredConnectionParams();
5527
- } catch (error$1) {
5528
- logger$6.error("Failed to cleanup stored connection params:", error$1);
5529
- } finally {
5530
- this.transport.reconnect();
5783
+ const isRecoverableAuthError = error instanceof require_operators.JSONRPCError && (error.code === RPC_ERROR_REQUESTER_VALIDATION_FAILED || error.code === RPC_ERROR_INVALID_PARAMS || error.code === RPC_ERROR_AUTHENTICATION_FAILED);
5784
+ const hasStoredState = this._authorization$.value !== void 0;
5785
+ if (isRecoverableAuthError && hasStoredState) {
5786
+ logger$7.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");
5787
+ try {
5788
+ await this.cleanupStoredConnectionParams();
5789
+ } catch (cleanupError) {
5790
+ logger$7.error("Failed to cleanup stored connection params:", cleanupError);
5791
+ } finally {
5792
+ this.transport.reconnect();
5793
+ }
5531
5794
  }
5532
5795
  }
5533
5796
  async cleanupStoredConnectionParams() {
5534
5797
  await this.transport.setProtocol(void 0);
5535
5798
  await this.updateAuthorizationStateInStorage(void 0);
5799
+ this._authorization$.next(void 0);
5536
5800
  await this.attachManager.detachAll();
5537
5801
  }
5538
5802
  async updateAuthState(authorization_state) {
5539
5803
  try {
5540
5804
  await this.storage.setItem(this.authorizationStateKey, authorization_state);
5541
5805
  } catch (error) {
5542
- logger$6.error("Failed to update authorization state in storage:", error);
5806
+ logger$7.error("Failed to update authorization state in storage:", error);
5543
5807
  this._errors$.next(new require_operators.AuthStateHandlerError(error));
5544
5808
  }
5545
5809
  }
5546
- async reauthenticate(token) {
5547
- logger$6.debug("[Session] Re-authenticating session");
5810
+ async reauthenticate(token, dpopToken, options) {
5811
+ logger$7.debug("[Session] Re-authenticating session");
5548
5812
  try {
5813
+ let resolvedDpopToken = dpopToken;
5814
+ if (!resolvedDpopToken && this.dpopManager?.initialized) try {
5815
+ resolvedDpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
5816
+ } catch (error) {
5817
+ if (this._clientBound) throw error;
5818
+ logger$7.warn("[Session] Failed to create DPoP proof for reauthenticate:", error);
5819
+ }
5549
5820
  const request = RPCReauthenticate({
5550
5821
  project: this._authorization$.value?.project_id ?? "",
5551
- jwt_token: token
5822
+ jwt_token: token,
5823
+ ...resolvedDpopToken ? { dpop_token: resolvedDpopToken } : {}
5552
5824
  });
5553
5825
  await (0, rxjs.lastValueFrom)((0, rxjs.from)(this.transport.execute(request)).pipe(require_operators.throwOnRPCError(), (0, rxjs.take)(1), (0, rxjs.catchError)((err) => {
5554
- logger$6.error("[Session] Re-authentication RPC failed:", err);
5826
+ logger$7.error("[Session] Re-authentication RPC failed:", err);
5555
5827
  throw err;
5556
5828
  })));
5557
- logger$6.debug("[Session] Re-authentication successful, updating stored auth state");
5829
+ if (options?.clientBound) this._clientBound = true;
5830
+ logger$7.debug("[Session] Re-authentication successful, updating stored auth state");
5558
5831
  } catch (error) {
5559
- logger$6.error("[Session] Re-authentication failed:", error);
5832
+ logger$7.error("[Session] Re-authentication failed:", error);
5560
5833
  this._errors$.next(new require_operators.AuthStateHandlerError(error));
5561
5834
  throw error;
5562
5835
  }
5563
5836
  }
5564
5837
  async authenticate() {
5565
- logger$6.debug("[Session] Starting authentication process");
5566
- const params = {
5567
- authentication: this.authentication,
5568
- version: this.connectVersion,
5569
- agent: this.agent,
5570
- contexts: this.contexts,
5571
- eventing: this.eventing,
5572
- topics: this.topics,
5573
- event_acks: this.eventAcks
5574
- };
5838
+ logger$7.debug("[Session] Starting authentication process");
5575
5839
  const persistedParams = await (0, rxjs.firstValueFrom)((0, rxjs.combineLatest)({
5576
5840
  protocol: this.transport.protocol$,
5577
5841
  authorization_state: this.authorizationState$
5578
5842
  }).pipe((0, rxjs.take)(1)));
5579
- logger$6.debug("[Session] Persisted params:\n", {
5843
+ logger$7.debug("[Session] Persisted params:\n", {
5580
5844
  protocol: persistedParams.protocol,
5581
5845
  authStateLength: persistedParams.authorization_state?.length
5582
5846
  });
5847
+ this.transport.resetSessionEpoch();
5848
+ const hasReconnectState = persistedParams.authorization_state && persistedParams.protocol;
5849
+ const storedToken = this.getCredential().token;
5850
+ const isReconnect = hasReconnectState && storedToken;
5851
+ let dpopToken;
5852
+ if (isReconnect) logger$7.debug("[Session] Reconnecting with stored jwt_token + authorization_state");
5853
+ else if (this.onBeforeReconnect && this._clientBound) {
5854
+ logger$7.debug("[Session] Refreshing credentials before fresh connect");
5855
+ await this.onBeforeReconnect();
5856
+ }
5857
+ if (this.dpopManager?.initialized) try {
5858
+ dpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.connect" });
5859
+ } catch (error) {
5860
+ if (this._clientBound) throw error;
5861
+ logger$7.warn("[Session] Failed to create DPoP proof for connect, proceeding without:", error);
5862
+ }
5583
5863
  const rpcConnectRequest = RPCConnect({
5584
- ...params,
5585
- ...persistedParams
5864
+ authentication: isReconnect ? { jwt_token: storedToken } : this.authentication,
5865
+ version: this.connectVersion,
5866
+ agent: this.agent,
5867
+ contexts: this.contexts,
5868
+ eventing: this.eventing,
5869
+ topics: this.topics,
5870
+ event_acks: this.eventAcks,
5871
+ ...dpopToken ? { dpop_token: dpopToken } : {},
5872
+ ...isReconnect ? {
5873
+ authorization_state: persistedParams.authorization_state,
5874
+ protocol: persistedParams.protocol
5875
+ } : {}
5586
5876
  });
5587
- this.transport.resetSessionEpoch();
5588
5877
  const response = await (0, rxjs.lastValueFrom)((0, rxjs.from)(this.transport.execute(rpcConnectRequest)).pipe(require_operators.throwOnRPCError(), (0, rxjs.map)((res) => res.result), (0, rxjs.filter)(isRPCConnectResult), (0, rxjs.tap)(() => {
5589
- logger$6.debug("[Session] Response passed filter, processing authentication result");
5878
+ logger$7.debug("[Session] Response passed filter, processing authentication result");
5590
5879
  }), (0, rxjs.take)(1), (0, rxjs.catchError)((err) => {
5591
- logger$6.error("[Session] Authentication RPC failed:", err);
5880
+ logger$7.error("[Session] Authentication RPC failed:", err);
5592
5881
  throw err;
5593
5882
  })));
5594
- logger$6.debug("[Session] Processing authentication result:", {
5883
+ logger$7.debug("[Session] Processing authentication result:", {
5595
5884
  hasProtocol: !!response.protocol,
5596
5885
  hasAuthorization: !!response.authorization,
5597
5886
  hasIceServers: !!response.ice_servers
@@ -5600,7 +5889,7 @@ var ClientSessionManager = class extends Destroyable {
5600
5889
  this._authorization$.next(response.authorization);
5601
5890
  this._iceServers$.next(response.ice_servers ?? []);
5602
5891
  this._authenticated$.next(true);
5603
- logger$6.debug("[Session] Authentication completed successfully");
5892
+ logger$7.debug("[Session] Authentication completed successfully");
5604
5893
  }
5605
5894
  async disconnect() {
5606
5895
  this.transport.disconnect();
@@ -5640,7 +5929,7 @@ var ClientSessionManager = class extends Destroyable {
5640
5929
  });
5641
5930
  return callSession;
5642
5931
  } catch (error) {
5643
- logger$6.error("[Session] Error creating outbound call:", error);
5932
+ logger$7.error("[Session] Error creating outbound call:", error);
5644
5933
  callSession?.destroy();
5645
5934
  const callError = new require_operators.CallCreateError(error instanceof rxjs.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
5646
5935
  this._errors$.next(callError);
@@ -5657,8 +5946,8 @@ var ClientSessionManager = class extends Destroyable {
5657
5946
  if (!addressId) throw new require_operators.DependencyError(`Address name: ${addressURI} not found`);
5658
5947
  address = this._directory.get(addressId);
5659
5948
  if (!address) throw new require_operators.DependencyError(`Address ID: ${addressId} not found`);
5660
- } catch (error) {
5661
- logger$6.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
5949
+ } catch {
5950
+ logger$7.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
5662
5951
  }
5663
5952
  const callSession = this.callFactory.createCall(address, { ...options });
5664
5953
  callSession.status$.pipe((0, rxjs.filter)((status) => status === "destroyed"), (0, rxjs.take)(1)).subscribe(() => {
@@ -5667,7 +5956,7 @@ var ClientSessionManager = class extends Destroyable {
5667
5956
  });
5668
5957
  return callSession;
5669
5958
  } catch (error) {
5670
- logger$6.error("[Session] Error creating call session:", error);
5959
+ logger$7.error("[Session] Error creating call session:", error);
5671
5960
  throw new require_operators.CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
5672
5961
  }
5673
5962
  }
@@ -5715,7 +6004,7 @@ const isString = (obj) => typeof obj === "string";
5715
6004
 
5716
6005
  //#endregion
5717
6006
  //#region src/managers/ConversationsManager.ts
5718
- const logger$5 = require_operators.getLogger();
6007
+ const logger$6 = require_operators.getLogger();
5719
6008
  var ConversationMessagesFetcher = class extends Fetcher {
5720
6009
  constructor(groupId, http) {
5721
6010
  super(`/api/fabric/conversations/${groupId}/messages`, "page_size=100", http);
@@ -5755,13 +6044,13 @@ var ConversationsManager = class {
5755
6044
  }
5756
6045
  throw new require_operators.ConversationError("Join Failed - Unexpected response");
5757
6046
  } catch (error) {
5758
- logger$5.error("[ConversationsManager] Failed to join conversation:", error);
6047
+ logger$6.error("[ConversationsManager] Failed to join conversation:", error);
5759
6048
  throw error;
5760
6049
  }
5761
6050
  }
5762
6051
  async getConversationMessageCollection(addressId) {
5763
6052
  const groupId = this.groupIds.get(addressId) ?? await this.join(addressId);
5764
- return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(require_operators.filterAs(isConversationMessageMetadata, "params"), (0, rxjs.tap)((event) => logger$5.debug("[ConversationsManager ] Conversation Event:", event)), (0, rxjs.map)((params) => ({ ...params }))), this.http, this.onError));
6053
+ return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(require_operators.filterAs(isConversationMessageMetadata, "params"), (0, rxjs.tap)((event) => logger$6.debug("[ConversationsManager ] Conversation Event:", event)), (0, rxjs.map)((params) => ({ ...params }))), this.http, this.onError));
5765
6054
  }
5766
6055
  async sendText(text, destinationAddressId) {
5767
6056
  const groupId = this.groupIds.get(destinationAddressId) ?? await this.join(destinationAddressId);
@@ -5778,8 +6067,207 @@ var ConversationsManager = class {
5778
6067
  })).ok) return;
5779
6068
  throw new require_operators.ConversationError("Send Text Failed - Unexpected response");
5780
6069
  } catch (error) {
5781
- logger$5.error("[ConversationsManager] Failed to send text message:", error);
6070
+ logger$6.error("[ConversationsManager] Failed to send text message:", error);
6071
+ }
6072
+ }
6073
+ };
6074
+
6075
+ //#endregion
6076
+ //#region src/managers/DeviceTokenManager.ts
6077
+ const logger$5 = require_operators.getLogger();
6078
+ /**
6079
+ * Resolves the token expiry timestamp (epoch seconds) using a 3-tier priority chain:
6080
+ * 1. `data.expires_at` — server-provided absolute timestamp
6081
+ * 2. `data.expires_in` — server-provided relative lifetime
6082
+ * 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN` with a warning
6083
+ */
6084
+ function resolveExpiresAt(data) {
6085
+ if (data.expires_at) return data.expires_at;
6086
+ if (data.expires_in) return Math.floor(Date.now() / 1e3) + data.expires_in;
6087
+ logger$5.warn("[DeviceToken] Could not determine token expiry, using default");
6088
+ return Math.floor(Date.now() / 1e3) + DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
6089
+ }
6090
+ /**
6091
+ * Resolves the token TTL in seconds from a fresh response.
6092
+ * Called at token receive time so `expires_at - now` reflects the original lifetime.
6093
+ *
6094
+ * 1. `data.expires_in` — server-provided TTL directly
6095
+ * 2. `data.expires_at - now` — derive TTL from absolute timestamp
6096
+ * 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN`
6097
+ */
6098
+ function resolveExpireIn(data) {
6099
+ if (data.expires_in) return data.expires_in;
6100
+ if (data.expires_at) return Math.max(data.expires_at - Math.floor(Date.now() / 1e3), 1);
6101
+ return DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
6102
+ }
6103
+ /**
6104
+ * Manages the Client Bound SAT lifecycle: activation, token exchange,
6105
+ * reauthentication, and automatic refresh scheduling.
6106
+ *
6107
+ * Extends {@link Destroyable} for automatic RxJS subscription and subject cleanup.
6108
+ * Uses a reactive pipeline (`BehaviorSubject` + `switchMap(timer())`) instead of
6109
+ * raw `setTimeout` for refresh scheduling.
6110
+ */
6111
+ var DeviceTokenManager = class extends Destroyable {
6112
+ constructor(dpopManager, http, errorHandler, getCredential) {
6113
+ super();
6114
+ this.dpopManager = dpopManager;
6115
+ this.http = http;
6116
+ this.errorHandler = errorHandler;
6117
+ this.getCredential = getCredential;
6118
+ this._currentToken$ = this.createBehaviorSubject(null);
6119
+ this._refreshInProgress = false;
6120
+ this._effectiveExpireIn = DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
6121
+ this.subscribeTo(this._currentToken$.pipe((0, rxjs.filter)(Boolean), (0, rxjs.switchMap)((tokenData) => {
6122
+ const expiresAt = resolveExpiresAt(tokenData);
6123
+ const refreshIn = Math.max(expiresAt * 1e3 - Date.now() - DEVICE_TOKEN_REFRESH_BUFFER_MS, 1e3);
6124
+ logger$5.debug(`[DeviceToken] Scheduling Client Bound SAT refresh in ${refreshIn}ms`);
6125
+ return (0, rxjs.timer)(refreshIn);
6126
+ })), () => {
6127
+ this.executeRefresh();
6128
+ });
6129
+ }
6130
+ /**
6131
+ * Activates the Client Bound SAT flow when the subscriber's token has
6132
+ * `sat:refresh` scope.
6133
+ *
6134
+ * Steps:
6135
+ * 1. Check subscriber's `sat_claims` for `sat:refresh` scope
6136
+ * 2. Call `/api/fabric/subscriber/devices/token` with a DPoP proof
6137
+ * 3. Reauthenticate the session with the Client Bound SAT + DPoP proof
6138
+ * 4. Emit token to trigger the reactive refresh pipeline
6139
+ */
6140
+ async activate(subscriber, session, updateCredential) {
6141
+ const { satClaims } = subscriber;
6142
+ if (!satClaims?.scope?.includes(SAT_REFRESH_SCOPE)) {
6143
+ logger$5.debug("[DeviceToken] No sat:refresh scope, skipping Client Bound SAT activation");
6144
+ return;
6145
+ }
6146
+ this._session = session;
6147
+ this._updateCredential = updateCredential;
6148
+ try {
6149
+ const tokenData = await this.obtainToken();
6150
+ if (!tokenData.expires_at && !tokenData.expires_in && satClaims.expires_at) tokenData.expires_at = satClaims.expires_at;
6151
+ this._effectiveExpireIn = resolveExpireIn(tokenData);
6152
+ const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
6153
+ await session.reauthenticate(tokenData.token, rpcProof, { clientBound: true });
6154
+ updateCredential({ token: tokenData.token });
6155
+ logger$5.info("[DeviceToken] Client Bound SAT activated successfully");
6156
+ this._currentToken$.next(tokenData);
6157
+ } catch (error) {
6158
+ logger$5.error("[DeviceToken] Failed to activate Client Bound SAT:", error);
6159
+ this.errorHandler(new require_operators.DPoPInitError(error, "Failed to activate Client Bound SAT"));
6160
+ }
6161
+ }
6162
+ /**
6163
+ * Obtains a Client Bound SAT from `/api/fabric/subscriber/devices/token`.
6164
+ * Returns the full {@link DeviceTokenResponse} including expiry metadata.
6165
+ */
6166
+ async obtainToken() {
6167
+ const dpopProof = await this.dpopManager.createHttpProof({
6168
+ method: "POST",
6169
+ uri: DEVICE_TOKEN_ENDPOINT
6170
+ });
6171
+ const response = await this.http.request({
6172
+ url: DEVICE_TOKEN_ENDPOINT,
6173
+ ...POST_PARAMS,
6174
+ body: JSON.stringify({
6175
+ dpop_token: dpopProof,
6176
+ expire_in: DEVICE_TOKEN_DEFAULT_EXPIRE_IN
6177
+ })
6178
+ });
6179
+ if (!response.ok || !response.body) throw new require_operators.DeviceTokenError(`Failed to obtain device token: ${response.status} ${response.statusText}`);
6180
+ const data = JSON.parse(response.body);
6181
+ if (!data.token) throw new require_operators.DeviceTokenError("Device token response missing token field");
6182
+ return data;
6183
+ }
6184
+ /**
6185
+ * Refreshes the Client Bound SAT via `/api/fabric/subscriber/devices/refresh`.
6186
+ *
6187
+ * Creates a fresh DPoP proof, calls the refresh endpoint, reauthenticates
6188
+ * the WebSocket session, and returns the new token data (scheduling is
6189
+ * handled by the reactive pipeline).
6190
+ */
6191
+ async refreshToken(session, currentToken, updateCredential) {
6192
+ logger$5.debug("[DeviceToken] Refreshing Client Bound SAT");
6193
+ const dpopProof = await this.dpopManager.createHttpProof({
6194
+ method: "POST",
6195
+ uri: DEVICE_REFRESH_ENDPOINT,
6196
+ accessToken: currentToken
6197
+ });
6198
+ const response = await this.http.request({
6199
+ url: DEVICE_REFRESH_ENDPOINT,
6200
+ ...POST_PARAMS,
6201
+ body: JSON.stringify({
6202
+ dpop_token: dpopProof,
6203
+ expire_in: this._effectiveExpireIn
6204
+ })
6205
+ });
6206
+ if (!response.ok || !response.body) throw new require_operators.TokenRefreshError(`Failed to refresh device token: ${response.status} ${response.statusText}`);
6207
+ const data = JSON.parse(response.body);
6208
+ if (!data.token) throw new require_operators.TokenRefreshError("Device token refresh response missing token field");
6209
+ if (!data.expires_at && !data.expires_in) data.expires_in = this._effectiveExpireIn;
6210
+ this._effectiveExpireIn = resolveExpireIn(data);
6211
+ const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
6212
+ await session.reauthenticate(data.token, rpcProof);
6213
+ updateCredential({ token: data.token });
6214
+ logger$5.info("[DeviceToken] Client Bound SAT refreshed successfully");
6215
+ return data;
6216
+ }
6217
+ /**
6218
+ * Executes a refresh with retry and exponential backoff.
6219
+ * On success, emits to `_currentToken$` to schedule the next refresh.
6220
+ * On all retries exhausted, emits to `errorHandler`.
6221
+ */
6222
+ async executeRefresh() {
6223
+ if (this._refreshInProgress) {
6224
+ logger$5.debug("[DeviceToken] Refresh already in progress, skipping");
6225
+ return;
6226
+ }
6227
+ const session = this._session;
6228
+ const updateCredential = this._updateCredential;
6229
+ if (!session || !updateCredential) {
6230
+ logger$5.warn("[DeviceToken] Cannot refresh: session or updateCredential not set");
6231
+ return;
6232
+ }
6233
+ if (!session.authenticated) {
6234
+ logger$5.debug("[DeviceToken] Session not authenticated, deferring refresh");
6235
+ return;
6236
+ }
6237
+ this._refreshInProgress = true;
6238
+ try {
6239
+ const currentToken = this.getCredential().token;
6240
+ if (!currentToken) throw new require_operators.TokenRefreshError("No current token available for refresh");
6241
+ const newTokenData = await this.retryRefresh(session, currentToken, updateCredential);
6242
+ this._currentToken$.next(newTokenData);
6243
+ } catch (error) {
6244
+ logger$5.error("[DeviceToken] Automatic Client Bound SAT refresh failed:", error);
6245
+ this.errorHandler(error instanceof require_operators.TokenRefreshError ? error : new require_operators.TokenRefreshError("Automatic token refresh failed", error));
6246
+ } finally {
6247
+ this._refreshInProgress = false;
6248
+ }
6249
+ }
6250
+ /**
6251
+ * Retries `refreshToken()` up to `DEVICE_TOKEN_REFRESH_MAX_RETRIES` times
6252
+ * with exponential backoff (1s, 2s, 4s).
6253
+ */
6254
+ async retryRefresh(session, currentToken, updateCredential) {
6255
+ let lastError;
6256
+ for (let attempt = 0; attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES; attempt++) try {
6257
+ return await this.refreshToken(session, currentToken, updateCredential);
6258
+ } catch (error) {
6259
+ lastError = error;
6260
+ if (attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES - 1) {
6261
+ const delay = DEVICE_TOKEN_REFRESH_RETRY_BASE_MS * Math.pow(2, attempt);
6262
+ logger$5.warn(`[DeviceToken] Refresh attempt ${attempt + 1} failed, retrying in ${delay}ms`);
6263
+ await new Promise((resolve) => setTimeout(resolve, delay));
6264
+ }
5782
6265
  }
6266
+ throw lastError instanceof Error ? lastError : new require_operators.TokenRefreshError("All refresh retries exhausted", lastError);
6267
+ }
6268
+ /** Cleans up the manager, cancelling the reactive pipeline and all subscriptions. */
6269
+ destroy() {
6270
+ super.destroy();
5783
6271
  }
5784
6272
  };
5785
6273
 
@@ -5949,6 +6437,10 @@ var WebSocketController = class WebSocketController extends Destroyable {
5949
6437
  this.outgoingMessages$ = outgoingMessages$;
5950
6438
  this.messageQueue = [];
5951
6439
  this.shouldReconnect = false;
6440
+ this.boundHandleOpen = () => this.handleOpen();
6441
+ this.boundHandleClose = (event) => this.handleClose(event);
6442
+ this.boundHandleError = () => this.handleError();
6443
+ this.boundHandleMessage = (event) => this.handleMessage(event);
5952
6444
  this._status$ = this.createBehaviorSubject("disconnected");
5953
6445
  this._incomingMessages$ = this.createSubject();
5954
6446
  this._errors$ = this.createReplaySubject(1);
@@ -6004,6 +6496,7 @@ var WebSocketController = class WebSocketController extends Destroyable {
6004
6496
  }
6005
6497
  createWebSocket() {
6006
6498
  try {
6499
+ this.closeExistingSocket();
6007
6500
  this.socket = new this.WebSocketConstructor(this.endpoint);
6008
6501
  this.setupWebSocketListeners();
6009
6502
  this.startConnectionTimeout();
@@ -6013,12 +6506,33 @@ var WebSocketController = class WebSocketController extends Destroyable {
6013
6506
  this.handleConnectionError();
6014
6507
  }
6015
6508
  }
6509
+ /**
6510
+ * Closes the existing socket and removes its event listeners to prevent
6511
+ * phantom 'open'/'close' events from firing on the orphaned socket.
6512
+ */
6513
+ closeExistingSocket() {
6514
+ if (!this.socket) return;
6515
+ const oldSocket = this.socket;
6516
+ this.socket = void 0;
6517
+ this.removeWebSocketListeners(oldSocket);
6518
+ try {
6519
+ oldSocket.close();
6520
+ } catch {}
6521
+ }
6016
6522
  setupWebSocketListeners() {
6017
6523
  if (!this.socket) return;
6018
- this.socket.addEventListener("open", () => this.handleOpen());
6019
- this.socket.addEventListener("close", (event) => this.handleClose(event));
6020
- this.socket.addEventListener("error", () => this.handleError());
6021
- this.socket.addEventListener("message", (event) => this.handleMessage(event));
6524
+ this.socket.addEventListener("open", this.boundHandleOpen);
6525
+ this.socket.addEventListener("close", this.boundHandleClose);
6526
+ this.socket.addEventListener("error", this.boundHandleError);
6527
+ this.socket.addEventListener("message", this.boundHandleMessage);
6528
+ }
6529
+ removeWebSocketListeners(socket) {
6530
+ try {
6531
+ socket.removeEventListener("open", this.boundHandleOpen);
6532
+ socket.removeEventListener("close", this.boundHandleClose);
6533
+ socket.removeEventListener("error", this.boundHandleError);
6534
+ socket.removeEventListener("message", this.boundHandleMessage);
6535
+ } catch {}
6022
6536
  }
6023
6537
  handleOpen() {
6024
6538
  this.clearConnectionTimeout();
@@ -6363,6 +6877,7 @@ var SignalWire = class extends Destroyable {
6363
6877
  this._errors$ = this.createReplaySubject(1);
6364
6878
  this._options = {};
6365
6879
  this._deps = new DependencyContainer();
6880
+ this._credentialProvider = credentialProvider;
6366
6881
  this._options = {
6367
6882
  ...PreferencesContainer.instance.defaultSignalWireOptions,
6368
6883
  ...options
@@ -6386,8 +6901,25 @@ var SignalWire = class extends Destroyable {
6386
6901
  this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
6387
6902
  });
6388
6903
  }
6904
+ /**
6905
+ * Initializes DPoP if not already set up. Returns the fingerprint on success.
6906
+ */
6907
+ async initDPoP() {
6908
+ if (this._dpopManager?.initialized) return this._dpopManager.fingerprint;
6909
+ try {
6910
+ this._dpopManager = new CryptoController();
6911
+ const fingerprint = await this._dpopManager.init();
6912
+ logger$1.debug("[SignalWire] DPoP initialized, fingerprint available");
6913
+ return fingerprint;
6914
+ } catch (error) {
6915
+ logger$1.warn("[SignalWire] DPoP initialization failed, proceeding without DPoP:", error);
6916
+ this._dpopManager = void 0;
6917
+ return;
6918
+ }
6919
+ }
6389
6920
  async validateCredentials(credentialProvider, credentials) {
6390
- const _credentials = credentials ?? await credentialProvider.authenticate();
6921
+ const fingerprint = await this.initDPoP();
6922
+ const _credentials = credentials ?? await credentialProvider.authenticate(fingerprint ? { fingerprint } : void 0);
6391
6923
  if (_credentials.token) try {
6392
6924
  const decodeHeader = (0, jwt_decode.jwtDecode)(_credentials.token, { header: true });
6393
6925
  this._deps.ch = decodeHeader.ch;
@@ -6510,12 +7042,53 @@ var SignalWire = class extends Destroyable {
6510
7042
  };
6511
7043
  this._transport = new TransportManager(this._deps.storage, this._deps.protocolKey, this._deps.WebSocket, PreferencesContainer.instance.relayHost ?? this._deps.relayHost, errorHandler);
6512
7044
  this._attachManager = new AttachManager(this._deps.storage, this._deps.deviceController, PreferencesContainer.instance.reconnectCallsTimeout, this._deps.attachedCallsKey);
6513
- this._clientSession = new ClientSessionManager(this._deps.credential, this._transport, this._deps.storage, this._deps.authorizationStateKey, this._deps.deviceController, this._attachManager, this._deps.webRTCApiProvider);
7045
+ this._clientSession = new ClientSessionManager(() => this._deps.credential, this._transport, this._deps.storage, this._deps.authorizationStateKey, this._deps.deviceController, this._attachManager, this._deps.webRTCApiProvider, this._dpopManager);
6514
7046
  this._publicSession = new ClientSessionWrapper(this._clientSession);
7047
+ this._clientSession.onBeforeReconnect = async () => {
7048
+ if (!this._credentialProvider) return;
7049
+ try {
7050
+ const fingerprint = this._dpopManager?.initialized ? this._dpopManager.fingerprint : void 0;
7051
+ logger$1.debug("[SignalWire] Credential expired, refreshing before reconnect");
7052
+ const newCredentials = await this._credentialProvider.authenticate(fingerprint ? { fingerprint } : void 0);
7053
+ this._deps.credential = newCredentials;
7054
+ logger$1.debug("[SignalWire] Credential refreshed successfully for reconnect");
7055
+ } catch (error) {
7056
+ logger$1.error("[SignalWire] Failed to refresh credentials for reconnect:", error);
7057
+ }
7058
+ };
6515
7059
  this.subscribeTo(this._clientSession.errors$, (error) => {
6516
7060
  this._errors$.next(error);
6517
7061
  });
6518
7062
  await this._clientSession.connect();
7063
+ if (this._dpopManager?.initialized) {
7064
+ if (this._refreshTimerId) {
7065
+ clearTimeout(this._refreshTimerId);
7066
+ this._refreshTimerId = void 0;
7067
+ logger$1.debug("[SignalWire] Developer refresh disabled — Client Bound SAT activation starting");
7068
+ }
7069
+ this._deviceTokenManager = new DeviceTokenManager(this._dpopManager, this._deps.http, (error) => this._errors$.next(error), () => this._deps.credential);
7070
+ await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
7071
+ this._deps.credential = {
7072
+ ...this._deps.credential,
7073
+ ...cred
7074
+ };
7075
+ });
7076
+ this.subscribeTo(this._clientSession.authenticated$.pipe((0, rxjs.skip)(1), (0, rxjs.filter)(Boolean)), () => {
7077
+ logger$1.debug("[SignalWire] Re-activating Client Bound SAT after reconnect");
7078
+ this._deviceTokenManager?.activate(this._deps.subscriber, this._clientSession, (cred) => {
7079
+ this._deps.credential = {
7080
+ ...this._deps.credential,
7081
+ ...cred
7082
+ };
7083
+ });
7084
+ logger$1.debug("[SignalWire] Re-registering subscriber after reconnect");
7085
+ this.register().then(() => {
7086
+ logger$1.debug("[SignalWire] Subscriber re-registered successfully after reconnect");
7087
+ }).catch((error) => {
7088
+ logger$1.error("[SignalWire] Re-registration failed after reconnect:", error);
7089
+ });
7090
+ });
7091
+ }
6519
7092
  const conversationManager = new ConversationsManager(this._clientSession, this._deps.http, () => this._deps.getSubscriberFromAddressId(), errorHandler);
6520
7093
  const directory = new DirectoryManager(this._deps.http, this._clientSession, conversationManager, errorHandler);
6521
7094
  this._directory$.next(directory);
@@ -6793,6 +7366,8 @@ var SignalWire = class extends Destroyable {
6793
7366
  clearTimeout(this._refreshTimerId);
6794
7367
  this._refreshTimerId = void 0;
6795
7368
  }
7369
+ this._deviceTokenManager?.destroy();
7370
+ this._dpopManager?.destroy();
6796
7371
  super.destroy();
6797
7372
  }
6798
7373
  };
@@ -6919,6 +7494,8 @@ exports.Address = Address;
6919
7494
  exports.CallCreateError = require_operators.CallCreateError;
6920
7495
  exports.ClientPreferences = ClientPreferences;
6921
7496
  exports.CollectionFetchError = require_operators.CollectionFetchError;
7497
+ exports.DPoPInitError = require_operators.DPoPInitError;
7498
+ exports.DeviceTokenError = require_operators.DeviceTokenError;
6922
7499
  exports.InvalidCredentialsError = require_operators.InvalidCredentialsError;
6923
7500
  exports.MediaTrackError = require_operators.MediaTrackError;
6924
7501
  exports.MessageParseError = require_operators.MessageParseError;
@@ -6928,6 +7505,7 @@ exports.SelfParticipant = SelfParticipant;
6928
7505
  exports.SignalWire = SignalWire;
6929
7506
  exports.StaticCredentialProvider = StaticCredentialProvider;
6930
7507
  exports.Subscriber = Subscriber;
7508
+ exports.TokenRefreshError = require_operators.TokenRefreshError;
6931
7509
  exports.UnexpectedError = require_operators.UnexpectedError;
6932
7510
  exports.VertoPongError = require_operators.VertoPongError;
6933
7511
  exports.WebRTCCall = WebRTCCall;