@signalwire/js 4.0.0-dev-20260410161919 → 4.0.0-dev-20260413184400

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/browser.mjs CHANGED
@@ -3390,7 +3390,7 @@ var require_map = /* @__PURE__ */ __commonJSMin(((exports) => {
3390
3390
  exports.map = void 0;
3391
3391
  var lift_1$64 = require_lift();
3392
3392
  var OperatorSubscriber_1$54 = require_OperatorSubscriber();
3393
- function map$18(project, thisArg) {
3393
+ function map$19(project, thisArg) {
3394
3394
  return lift_1$64.operate(function(source, subscriber) {
3395
3395
  var index = 0;
3396
3396
  source.subscribe(OperatorSubscriber_1$54.createOperatorSubscriber(subscriber, function(value) {
@@ -3398,7 +3398,7 @@ var require_map = /* @__PURE__ */ __commonJSMin(((exports) => {
3398
3398
  }));
3399
3399
  });
3400
3400
  }
3401
- exports.map = map$18;
3401
+ exports.map = map$19;
3402
3402
  }));
3403
3403
 
3404
3404
  //#endregion
@@ -4140,7 +4140,7 @@ var require_timer = /* @__PURE__ */ __commonJSMin(((exports) => {
4140
4140
  var async_1$11 = require_async();
4141
4141
  var isScheduler_1 = require_isScheduler();
4142
4142
  var isDate_1$1 = require_isDate();
4143
- function timer$1(dueTime, intervalOrScheduler, scheduler) {
4143
+ function timer$2(dueTime, intervalOrScheduler, scheduler) {
4144
4144
  if (dueTime === void 0) dueTime = 0;
4145
4145
  if (scheduler === void 0) scheduler = async_1$11.async;
4146
4146
  var intervalDuration = -1;
@@ -4159,7 +4159,7 @@ var require_timer = /* @__PURE__ */ __commonJSMin(((exports) => {
4159
4159
  }, due);
4160
4160
  });
4161
4161
  }
4162
- exports.timer = timer$1;
4162
+ exports.timer = timer$2;
4163
4163
  }));
4164
4164
 
4165
4165
  //#endregion
@@ -4293,7 +4293,7 @@ var require_filter = /* @__PURE__ */ __commonJSMin(((exports) => {
4293
4293
  exports.filter = void 0;
4294
4294
  var lift_1$62 = require_lift();
4295
4295
  var OperatorSubscriber_1$49 = require_OperatorSubscriber();
4296
- function filter$15(predicate, thisArg) {
4296
+ function filter$16(predicate, thisArg) {
4297
4297
  return lift_1$62.operate(function(source, subscriber) {
4298
4298
  var index = 0;
4299
4299
  source.subscribe(OperatorSubscriber_1$49.createOperatorSubscriber(subscriber, function(value) {
@@ -4301,7 +4301,7 @@ var require_filter = /* @__PURE__ */ __commonJSMin(((exports) => {
4301
4301
  }));
4302
4302
  });
4303
4303
  }
4304
- exports.filter = filter$15;
4304
+ exports.filter = filter$16;
4305
4305
  }));
4306
4306
 
4307
4307
  //#endregion
@@ -6934,7 +6934,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
6934
6934
  var innerFrom_1$6 = require_innerFrom();
6935
6935
  var lift_1$13 = require_lift();
6936
6936
  var OperatorSubscriber_1$11 = require_OperatorSubscriber();
6937
- function switchMap$6(project, resultSelector) {
6937
+ function switchMap$7(project, resultSelector) {
6938
6938
  return lift_1$13.operate(function(source, subscriber) {
6939
6939
  var innerSubscriber = null;
6940
6940
  var index = 0;
@@ -6958,7 +6958,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
6958
6958
  }));
6959
6959
  });
6960
6960
  }
6961
- exports.switchMap = switchMap$6;
6961
+ exports.switchMap = switchMap$7;
6962
6962
  }));
6963
6963
 
6964
6964
  //#endregion
@@ -7582,7 +7582,7 @@ var require_withLatestFrom = /* @__PURE__ */ __commonJSMin(((exports) => {
7582
7582
  var identity_1$1 = require_identity();
7583
7583
  var noop_1$1 = require_noop();
7584
7584
  var args_1 = require_args();
7585
- function withLatestFrom$1() {
7585
+ function withLatestFrom$2() {
7586
7586
  var inputs = [];
7587
7587
  for (var _i = 0; _i < arguments.length; _i++) inputs[_i] = arguments[_i];
7588
7588
  var project = args_1.popResultSelector(inputs);
@@ -7611,7 +7611,7 @@ var require_withLatestFrom = /* @__PURE__ */ __commonJSMin(((exports) => {
7611
7611
  }));
7612
7612
  });
7613
7613
  }
7614
- exports.withLatestFrom = withLatestFrom$1;
7614
+ exports.withLatestFrom = withLatestFrom$2;
7615
7615
  }));
7616
7616
 
7617
7617
  //#endregion
@@ -8933,13 +8933,13 @@ var require_cjs = /* @__PURE__ */ __commonJSMin(((exports) => {
8933
8933
 
8934
8934
  //#endregion
8935
8935
  //#region src/behaviors/Destroyable.ts
8936
- var import_cjs$27 = require_cjs();
8936
+ var import_cjs$28 = require_cjs();
8937
8937
  var Destroyable = class {
8938
8938
  constructor() {
8939
8939
  this.subscriptions = [];
8940
8940
  this.subjects = [];
8941
- this._destroyed$ = new import_cjs$27.Subject();
8942
- this._change$ = new import_cjs$27.Subject();
8941
+ this._destroyed$ = new import_cjs$28.Subject();
8942
+ this._change$ = new import_cjs$28.Subject();
8943
8943
  }
8944
8944
  destroy() {
8945
8945
  this._observableCache?.clear();
@@ -8976,7 +8976,7 @@ var Destroyable = class {
8976
8976
  this._observableCache ??= /* @__PURE__ */ new Map();
8977
8977
  let cached = this._observableCache.get(publicKey);
8978
8978
  if (!cached) {
8979
- cached = factory().pipe((0, import_cjs$27.observeOn)(import_cjs$27.asapScheduler));
8979
+ cached = factory().pipe((0, import_cjs$28.observeOn)(import_cjs$28.asapScheduler));
8980
8980
  this._observableCache.set(publicKey, cached);
8981
8981
  }
8982
8982
  return cached;
@@ -8990,32 +8990,32 @@ var Destroyable = class {
8990
8990
  * Do NOT use for observables consumed internally by the SDK.
8991
8991
  */
8992
8992
  deferEmission(observable) {
8993
- return observable.pipe((0, import_cjs$27.observeOn)(import_cjs$27.asapScheduler));
8993
+ return observable.pipe((0, import_cjs$28.observeOn)(import_cjs$28.asapScheduler));
8994
8994
  }
8995
8995
  subscribeTo(observable, observerOrNext) {
8996
8996
  const subscription = observable.subscribe(observerOrNext);
8997
8997
  this.subscriptions.push(subscription);
8998
8998
  }
8999
8999
  createSubject() {
9000
- const subject = new import_cjs$27.Subject();
9000
+ const subject = new import_cjs$28.Subject();
9001
9001
  this.subjects.push(subject);
9002
- this.subscriptions.push(subject.pipe((0, import_cjs$27.map)(() => void 0)).subscribe(this._change$));
9002
+ this.subscriptions.push(subject.pipe((0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
9003
9003
  return subject;
9004
9004
  }
9005
9005
  createReplaySubject(bufferSize, windowTime$1) {
9006
- const subject = new import_cjs$27.ReplaySubject(bufferSize, windowTime$1);
9006
+ const subject = new import_cjs$28.ReplaySubject(bufferSize, windowTime$1);
9007
9007
  this.subjects.push(subject);
9008
- this.subscriptions.push(subject.pipe((0, import_cjs$27.map)(() => void 0)).subscribe(this._change$));
9008
+ this.subscriptions.push(subject.pipe((0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
9009
9009
  return subject;
9010
9010
  }
9011
9011
  createBehaviorSubject(initialValue) {
9012
- const subject = new import_cjs$27.BehaviorSubject(initialValue);
9012
+ const subject = new import_cjs$28.BehaviorSubject(initialValue);
9013
9013
  this.subjects.push(subject);
9014
- this.subscriptions.push(subject.pipe((0, import_cjs$27.skip)(1), (0, import_cjs$27.map)(() => void 0)).subscribe(this._change$));
9014
+ this.subscriptions.push(subject.pipe((0, import_cjs$28.skip)(1), (0, import_cjs$28.map)(() => void 0)).subscribe(this._change$));
9015
9015
  return subject;
9016
9016
  }
9017
9017
  get $() {
9018
- return this._change$.pipe((0, import_cjs$27.map)(() => this));
9018
+ return this._change$.pipe((0, import_cjs$28.map)(() => this));
9019
9019
  }
9020
9020
  /**
9021
9021
  * Observable that emits when the instance is destroyed
@@ -9474,9 +9474,9 @@ var require_loglevel = /* @__PURE__ */ __commonJSMin(((exports, module) => {
9474
9474
  defaultLogger$1 = new Logger();
9475
9475
  defaultLogger$1.getLogger = function getLogger$1(name) {
9476
9476
  if (typeof name !== "symbol" && typeof name !== "string" || name === "") throw new TypeError("You must supply a name when creating a logger.");
9477
- var logger$29 = _loggersByName[name];
9478
- if (!logger$29) logger$29 = _loggersByName[name] = new Logger(name, defaultLogger$1.methodFactory);
9479
- return logger$29;
9477
+ var logger$30 = _loggersByName[name];
9478
+ if (!logger$30) logger$30 = _loggersByName[name] = new Logger(name, defaultLogger$1.methodFactory);
9479
+ return logger$30;
9480
9480
  };
9481
9481
  var _log = typeof window !== undefinedType ? window.log : void 0;
9482
9482
  defaultLogger$1.noConflict = function() {
@@ -9516,15 +9516,15 @@ const shouldStringify = (payload) => {
9516
9516
  return true;
9517
9517
  };
9518
9518
  const wsTraffic = ({ type, payload }) => {
9519
- const logger$29 = getLoggerInstance();
9519
+ const logger$30 = getLoggerInstance();
9520
9520
  const { logWsTraffic } = debugOptions ?? {};
9521
9521
  if (!logWsTraffic) return;
9522
9522
  const msg = shouldStringify(payload) ? JSON.stringify(payload, null, 2) : payload;
9523
- return logger$29.debug(`${type.toUpperCase()}: \n`, msg, "\n");
9523
+ return logger$30.debug(`${type.toUpperCase()}: \n`, msg, "\n");
9524
9524
  };
9525
9525
  const getLogger = () => {
9526
- const logger$29 = getLoggerInstance();
9527
- return new Proxy(logger$29, { get(target, prop, receiver) {
9526
+ const logger$30 = getLoggerInstance();
9527
+ return new Proxy(logger$30, { get(target, prop, receiver) {
9528
9528
  if (prop === "wsTraffic") return wsTraffic;
9529
9529
  return Reflect.get(target, prop, receiver);
9530
9530
  } });
@@ -9573,8 +9573,8 @@ const asyncRetry = async ({ asyncCallable, maxRetries: retries = DEFAULT_MAX_RET
9573
9573
 
9574
9574
  //#endregion
9575
9575
  //#region src/controllers/HTTPRequestController.ts
9576
- var import_cjs$26 = require_cjs();
9577
- const logger$28 = getLogger();
9576
+ var import_cjs$27 = require_cjs();
9577
+ const logger$29 = getLogger();
9578
9578
  const GET_PARAMS = {
9579
9579
  method: "GET",
9580
9580
  headers: { Accept: "application/json" }
@@ -9609,9 +9609,9 @@ var HTTPRequestController = class HTTPRequestController {
9609
9609
  constructor(baseURL, getCredential, options = {}) {
9610
9610
  this.baseURL = baseURL;
9611
9611
  this.getCredential = getCredential;
9612
- this._responses$ = new import_cjs$26.Subject();
9613
- this._errors$ = new import_cjs$26.Subject();
9614
- this._status$ = new import_cjs$26.BehaviorSubject("idle");
9612
+ this._responses$ = new import_cjs$27.Subject();
9613
+ this._errors$ = new import_cjs$27.Subject();
9614
+ this._status$ = new import_cjs$27.BehaviorSubject("idle");
9615
9615
  this.maxRetries = options.maxRetries ?? HTTPRequestController.defaultMaxRetries;
9616
9616
  this.retryDelayMin = options.retryDelayMin ?? HTTPRequestController.defaultRetryDelayMinMs;
9617
9617
  this.retryDelayMax = options.retryDelayMax ?? HTTPRequestController.defaultRetryDelayMaxMs;
@@ -9637,7 +9637,7 @@ var HTTPRequestController = class HTTPRequestController {
9637
9637
  this._responses$.next(response);
9638
9638
  return response;
9639
9639
  } catch (error) {
9640
- logger$28.error("[HTTPRequestController] Request error:", error);
9640
+ logger$29.error("[HTTPRequestController] Request error:", error);
9641
9641
  this._status$.next("error");
9642
9642
  const err = error instanceof Error ? error : new Error("HTTP request failed", { cause: error });
9643
9643
  this._errors$.next(err);
@@ -9664,7 +9664,7 @@ var HTTPRequestController = class HTTPRequestController {
9664
9664
  const url = this.buildURL(request.url);
9665
9665
  const headers = this.buildHeaders(request.headers);
9666
9666
  const timeout$5 = request.timeout ?? this.requestTimeout;
9667
- logger$28.debug("[HTTPRequestController] Executing request:", {
9667
+ logger$29.debug("[HTTPRequestController] Executing request:", {
9668
9668
  method: request.method,
9669
9669
  url,
9670
9670
  headers: Object.keys(headers).reduce((acc, key) => {
@@ -9684,7 +9684,7 @@ var HTTPRequestController = class HTTPRequestController {
9684
9684
  });
9685
9685
  clearTimeout(timeoutId);
9686
9686
  const httpResponse = await this.convertResponse(response);
9687
- logger$28.debug("[HTTPRequestController] Response received:", {
9687
+ logger$29.debug("[HTTPRequestController] Response received:", {
9688
9688
  status: response.status,
9689
9689
  statusText: response.statusText,
9690
9690
  headers: [...response.headers.entries()],
@@ -9694,7 +9694,7 @@ var HTTPRequestController = class HTTPRequestController {
9694
9694
  } catch (error) {
9695
9695
  clearTimeout(timeoutId);
9696
9696
  if (error instanceof Error && error.name === "AbortError") throw new RequestTimeoutError(`Request timeout after ${timeout$5}ms`, { cause: error });
9697
- logger$28.error("[HTTPRequestController] Request failed:", error);
9697
+ logger$29.error("[HTTPRequestController] Request failed:", error);
9698
9698
  throw error;
9699
9699
  }
9700
9700
  }
@@ -9708,8 +9708,8 @@ var HTTPRequestController = class HTTPRequestController {
9708
9708
  const credential = this.getCredential();
9709
9709
  if (credential.token) {
9710
9710
  headers.Authorization = `Bearer ${credential.token}`;
9711
- logger$28.debug("[HTTPRequestController] Using Bearer token auth, token length:", credential.token.length);
9712
- } else logger$28.warn("[HTTPRequestController] No credentials available for authentication");
9711
+ logger$29.debug("[HTTPRequestController] Using Bearer token auth, token length:", credential.token.length);
9712
+ } else logger$29.warn("[HTTPRequestController] No credentials available for authentication");
9713
9713
  return headers;
9714
9714
  }
9715
9715
  /**
@@ -9858,6 +9858,19 @@ const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
9858
9858
  const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
9859
9859
  const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
9860
9860
  const PREFERENCES_STORAGE_KEY = "sw:preferences";
9861
+ /** Scope value that enables automatic token refresh. */
9862
+ const SAT_REFRESH_SCOPE = "sat:refresh";
9863
+ /** API endpoints for device token operations. */
9864
+ const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
9865
+ const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
9866
+ /** Default device token TTL in seconds (15 minutes). */
9867
+ const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
9868
+ /** Buffer time in milliseconds before expiry to trigger refresh. */
9869
+ const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
9870
+ /** Maximum retry attempts for device token refresh on transient failure. */
9871
+ const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
9872
+ /** Base delay in milliseconds for exponential backoff on refresh retry. */
9873
+ const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
9861
9874
  /** JSON-RPC error code for requester validation failure (corrupted auth state). */
9862
9875
  const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
9863
9876
  /** JSON-RPC error code for invalid params (e.g., missing authentication block). */
@@ -9948,7 +9961,7 @@ function fromMsToSec(milliseconds) {
9948
9961
 
9949
9962
  //#endregion
9950
9963
  //#region src/containers/PreferencesContainer.ts
9951
- const logger$27 = getLogger();
9964
+ const logger$28 = getLogger();
9952
9965
  var PreferencesContainer = class PreferencesContainer {
9953
9966
  static get instance() {
9954
9967
  this._instance ??= new PreferencesContainer();
@@ -10610,7 +10623,7 @@ var ClientPreferences = class {
10610
10623
  if (!this._storage) return;
10611
10624
  const data = collectStoredPreferences();
10612
10625
  this._storage.setItem(PREFERENCES_STORAGE_KEY, data, "local").catch((error) => {
10613
- logger$27.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
10626
+ logger$28.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
10614
10627
  });
10615
10628
  }
10616
10629
  /** Loads preferences from storage and applies them to the container. */
@@ -10619,15 +10632,15 @@ var ClientPreferences = class {
10619
10632
  this._storage.getItem(PREFERENCES_STORAGE_KEY, "local").then((stored) => {
10620
10633
  if (stored) applyStoredPreferences(stored);
10621
10634
  }).catch((error) => {
10622
- logger$27.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
10635
+ logger$28.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
10623
10636
  });
10624
10637
  }
10625
10638
  };
10626
10639
 
10627
10640
  //#endregion
10628
10641
  //#region src/controllers/NavigatorDeviceController.ts
10629
- var import_cjs$25 = require_cjs();
10630
- const logger$26 = getLogger();
10642
+ var import_cjs$26 = require_cjs();
10643
+ const logger$27 = getLogger();
10631
10644
  /** Maps a device kind to its storage key. */
10632
10645
  const DEVICE_STORAGE_KEYS = {
10633
10646
  audioinput: DEVICE_STORAGE_KEY_AUDIO_INPUT,
@@ -10649,7 +10662,7 @@ var NavigatorDeviceController = class extends Destroyable {
10649
10662
  super();
10650
10663
  this.webRTCApiProvider = webRTCApiProvider;
10651
10664
  this.deviceChangeHandler = () => {
10652
- logger$26.debug("[DeviceController] Device change detected");
10665
+ logger$27.debug("[DeviceController] Device change detected");
10653
10666
  this.enumerateDevices();
10654
10667
  };
10655
10668
  this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
@@ -10686,17 +10699,17 @@ var NavigatorDeviceController = class extends Destroyable {
10686
10699
  return {};
10687
10700
  }
10688
10701
  get errors$() {
10689
- return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$25.takeUntil)(this.destroyed$)));
10702
+ return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$26.takeUntil)(this.destroyed$)));
10690
10703
  }
10691
10704
  /** Observable that emits when the SDK auto-switches a device. */
10692
10705
  get deviceRecovered$() {
10693
- return this._deviceRecovered$.asObservable().pipe((0, import_cjs$25.takeUntil)(this.destroyed$));
10706
+ return this._deviceRecovered$.asObservable().pipe((0, import_cjs$26.takeUntil)(this.destroyed$));
10694
10707
  }
10695
10708
  get videoInputDisabled$() {
10696
- return this.cachedObservable("videoInputDisabled$", () => this._videoInputDisabled$.asObservable().pipe((0, import_cjs$25.distinctUntilChanged)(), (0, import_cjs$25.takeUntil)(this.destroyed$)));
10709
+ return this.cachedObservable("videoInputDisabled$", () => this._videoInputDisabled$.asObservable().pipe((0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
10697
10710
  }
10698
10711
  get audioInputDisabled$() {
10699
- return this.cachedObservable("audioInputDisabled$", () => this._audioInputDisabled$.asObservable().pipe((0, import_cjs$25.distinctUntilChanged)(), (0, import_cjs$25.takeUntil)(this.destroyed$)));
10712
+ return this.cachedObservable("audioInputDisabled$", () => this._audioInputDisabled$.asObservable().pipe((0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
10700
10713
  }
10701
10714
  get videoInputDisabled() {
10702
10715
  return this._videoInputDisabled$.value;
@@ -10705,22 +10718,22 @@ var NavigatorDeviceController = class extends Destroyable {
10705
10718
  return this._audioInputDisabled$.value;
10706
10719
  }
10707
10720
  get audioInputDevices$() {
10708
- return this.cachedObservable("audioInputDevices$", () => this._devicesState$.pipe((0, import_cjs$25.map)((state) => state.audioinput), (0, import_cjs$25.distinctUntilChanged)(), (0, import_cjs$25.takeUntil)(this.destroyed$)));
10721
+ return this.cachedObservable("audioInputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.audioinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
10709
10722
  }
10710
10723
  get audioOutputDevices$() {
10711
- return this.cachedObservable("audioOutputDevices$", () => this._devicesState$.pipe((0, import_cjs$25.map)((state) => state.audiooutput), (0, import_cjs$25.distinctUntilChanged)(), (0, import_cjs$25.takeUntil)(this.destroyed$)));
10724
+ return this.cachedObservable("audioOutputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.audiooutput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
10712
10725
  }
10713
10726
  get videoInputDevices$() {
10714
- return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$25.map)((state) => state.videoinput), (0, import_cjs$25.distinctUntilChanged)(), (0, import_cjs$25.takeUntil)(this.destroyed$)));
10727
+ return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$26.map)((state) => state.videoinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$)));
10715
10728
  }
10716
10729
  get selectedAudioInputDevice$() {
10717
- return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$25.map)((state) => state.audioinput), (0, import_cjs$25.distinctUntilChanged)(), (0, import_cjs$25.takeUntil)(this.destroyed$), (0, import_cjs$25.tap)((info) => logger$26.debug("[DeviceController] Selected audio input device changed:", info))));
10730
+ return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.audioinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected audio input device changed:", info))));
10718
10731
  }
10719
10732
  get selectedAudioOutputDevice$() {
10720
- return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$25.map)((state) => state.audiooutput), (0, import_cjs$25.distinctUntilChanged)(), (0, import_cjs$25.takeUntil)(this.destroyed$), (0, import_cjs$25.tap)((info) => logger$26.debug("[DeviceController] Selected audio output device changed:", info))));
10733
+ return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.audiooutput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected audio output device changed:", info))));
10721
10734
  }
10722
10735
  get selectedVideoInputDevice$() {
10723
- return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$25.map)((state) => state.videoinput), (0, import_cjs$25.distinctUntilChanged)(), (0, import_cjs$25.takeUntil)(this.destroyed$), (0, import_cjs$25.tap)((info) => logger$26.debug("[DeviceController] Selected video input device changed:", info))));
10736
+ return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$26.map)((state) => state.videoinput), (0, import_cjs$26.distinctUntilChanged)(), (0, import_cjs$26.takeUntil)(this.destroyed$), (0, import_cjs$26.tap)((info) => logger$27.debug("[DeviceController] Selected video input device changed:", info))));
10724
10737
  }
10725
10738
  get selectedAudioInputDevice() {
10726
10739
  if (this._audioInputDisabled$.value) return null;
@@ -10795,7 +10808,7 @@ var NavigatorDeviceController = class extends Destroyable {
10795
10808
  if (device) this.persistDeviceSelection("audioinput", device);
10796
10809
  }
10797
10810
  selectVideoInputDevice(device) {
10798
- logger$26.debug("[DeviceController] Setting selected video input device:", device);
10811
+ logger$27.debug("[DeviceController] Setting selected video input device:", device);
10799
10812
  if (this._videoInputDisabled$.value && device) this._videoInputDisabled$.next(false);
10800
10813
  const previous = this._selectedDevicesState$.value.videoinput;
10801
10814
  if (previous && previous.deviceId !== device?.deviceId) this._deviceHistory.push("videoinput", previous);
@@ -10816,7 +10829,7 @@ var NavigatorDeviceController = class extends Destroyable {
10816
10829
  }
10817
10830
  init() {
10818
10831
  this.loadPersistedDevices();
10819
- this.subscribeTo(this._devicesState$.pipe((0, import_cjs$25.debounceTime)(PreferencesContainer.instance.deviceDebounceTime)), (devicesState) => {
10832
+ this.subscribeTo(this._devicesState$.pipe((0, import_cjs$26.debounceTime)(PreferencesContainer.instance.deviceDebounceTime)), (devicesState) => {
10820
10833
  const currentSelected = this._selectedDevicesState$.value;
10821
10834
  const newAudioInput = this._audioInputDisabled$.value ? null : this.resolveDevice("audioinput", devicesState.audioinput, currentSelected.audioinput, PreferencesContainer.instance.preferredAudioInput);
10822
10835
  const newAudioOutput = this.resolveDevice("audiooutput", devicesState.audiooutput, currentSelected.audiooutput, PreferencesContainer.instance.preferredAudioOutput);
@@ -10852,7 +10865,7 @@ var NavigatorDeviceController = class extends Destroyable {
10852
10865
  }
10853
10866
  const fromHistory = this._deviceHistory.findInHistory(kind, devices);
10854
10867
  if (fromHistory) {
10855
- logger$26.debug(`[DeviceController] Device disappeared, falling back to history: ${fromHistory.label}`);
10868
+ logger$27.debug(`[DeviceController] Device disappeared, falling back to history: ${fromHistory.label}`);
10856
10869
  this.emitDeviceRecovered(kind, selected, fromHistory, "device_disconnected");
10857
10870
  return fromHistory;
10858
10871
  }
@@ -10905,7 +10918,7 @@ var NavigatorDeviceController = class extends Destroyable {
10905
10918
  try {
10906
10919
  await this._storageManager.setItem(DEVICE_STORAGE_KEYS[kind], stored, "local");
10907
10920
  } catch (error) {
10908
- logger$26.error(`[DeviceController] Failed to persist device selection for ${kind}:`, error);
10921
+ logger$27.error(`[DeviceController] Failed to persist device selection for ${kind}:`, error);
10909
10922
  }
10910
10923
  }
10911
10924
  async loadPersistedDevices() {
@@ -10921,7 +10934,7 @@ var NavigatorDeviceController = class extends Destroyable {
10921
10934
  [kind]: stored
10922
10935
  };
10923
10936
  } catch (error) {
10924
- logger$26.error(`[DeviceController] Failed to load persisted device for ${kind}:`, error);
10937
+ logger$27.error(`[DeviceController] Failed to load persisted device for ${kind}:`, error);
10925
10938
  }
10926
10939
  }
10927
10940
  /** Clears device history, persisted selections, and re-enumerates devices. */
@@ -10938,8 +10951,8 @@ var NavigatorDeviceController = class extends Destroyable {
10938
10951
  enableDeviceMonitoring() {
10939
10952
  this.disableDeviceMonitoring();
10940
10953
  this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
10941
- if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$25.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
10942
- logger$26.debug("[DeviceController] Polling devices due to interval");
10954
+ if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$26.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
10955
+ logger$27.debug("[DeviceController] Polling devices due to interval");
10943
10956
  this.enumerateDevices();
10944
10957
  });
10945
10958
  this.enumerateDevices();
@@ -10965,13 +10978,13 @@ var NavigatorDeviceController = class extends Destroyable {
10965
10978
  videoinput: []
10966
10979
  });
10967
10980
  this._devicesState$.next(devicesByKind);
10968
- logger$26.debug("[DeviceController] Devices enumerated:", {
10981
+ logger$27.debug("[DeviceController] Devices enumerated:", {
10969
10982
  audioInputs: devicesByKind.audioinput.length,
10970
10983
  audioOutputs: devicesByKind.audiooutput.length,
10971
10984
  videoInputs: devicesByKind.videoinput.length
10972
10985
  });
10973
10986
  } catch (error) {
10974
- logger$26.error("[DeviceController] Failed to enumerate devices:", error);
10987
+ logger$27.error("[DeviceController] Failed to enumerate devices:", error);
10975
10988
  this._errors$.next(error);
10976
10989
  }
10977
10990
  }
@@ -10987,7 +11000,7 @@ var NavigatorDeviceController = class extends Destroyable {
10987
11000
  stream.getTracks().forEach((t) => t.stop());
10988
11001
  return capabilities;
10989
11002
  } catch (error) {
10990
- logger$26.error("[DeviceController] Failed to get device capabilities:", error);
11003
+ logger$27.error("[DeviceController] Failed to get device capabilities:", error);
10991
11004
  this._errors$.next(error);
10992
11005
  throw error;
10993
11006
  }
@@ -11238,7 +11251,7 @@ var DependencyContainer = class {
11238
11251
 
11239
11252
  //#endregion
11240
11253
  //#region src/controllers/CryptoController.ts
11241
- const logger$25 = getLogger();
11254
+ const logger$26 = getLogger();
11242
11255
  const DPOP_DB_NAME = "sw-dpop";
11243
11256
  const DPOP_DB_VERSION = 1;
11244
11257
  const DPOP_STORE_NAME = "keys";
@@ -11297,7 +11310,7 @@ async function loadKeyPairFromDB() {
11297
11310
  tx.oncomplete = () => db.close();
11298
11311
  });
11299
11312
  } catch (error) {
11300
- logger$25.warn("[DPoP] Failed to load key pair from IndexedDB:", error);
11313
+ logger$26.warn("[DPoP] Failed to load key pair from IndexedDB:", error);
11301
11314
  return null;
11302
11315
  }
11303
11316
  }
@@ -11317,7 +11330,7 @@ async function saveKeyPairToDB(keyPair) {
11317
11330
  };
11318
11331
  });
11319
11332
  } catch (error) {
11320
- logger$25.warn("[DPoP] Failed to save key pair to IndexedDB:", error);
11333
+ logger$26.warn("[DPoP] Failed to save key pair to IndexedDB:", error);
11321
11334
  }
11322
11335
  }
11323
11336
  async function deleteKeyPairFromDB() {
@@ -11336,7 +11349,7 @@ async function deleteKeyPairFromDB() {
11336
11349
  };
11337
11350
  });
11338
11351
  } catch (error) {
11339
- logger$25.warn("[DPoP] Failed to delete key pair from IndexedDB:", error);
11352
+ logger$26.warn("[DPoP] Failed to delete key pair from IndexedDB:", error);
11340
11353
  }
11341
11354
  }
11342
11355
  /**
@@ -11396,13 +11409,13 @@ var CryptoController = class {
11396
11409
  this._publicJwk = await crypto.subtle.exportKey("jwk", stored.publicKey);
11397
11410
  this._fingerprint = await computeJwkThumbprint(this._publicJwk);
11398
11411
  this._initialized = true;
11399
- logger$25.debug("[DPoP] Key pair restored from IndexedDB, fingerprint:", this._fingerprint);
11412
+ logger$26.debug("[DPoP] Key pair restored from IndexedDB, fingerprint:", this._fingerprint);
11400
11413
  return this._fingerprint;
11401
11414
  } catch (error) {
11402
- logger$25.warn("[DPoP] Stored key pair unusable, generating new one:", error);
11415
+ logger$26.warn("[DPoP] Stored key pair unusable, generating new one:", error);
11403
11416
  await deleteKeyPairFromDB();
11404
11417
  }
11405
- logger$25.debug("[DPoP] Generating RSA key pair");
11418
+ logger$26.debug("[DPoP] Generating RSA key pair");
11406
11419
  this._keyPair = await crypto.subtle.generateKey({
11407
11420
  name: "RSASSA-PKCS1-v1_5",
11408
11421
  modulusLength: 2048,
@@ -11417,7 +11430,7 @@ var CryptoController = class {
11417
11430
  this._fingerprint = await computeJwkThumbprint(this._publicJwk);
11418
11431
  this._initialized = true;
11419
11432
  await saveKeyPairToDB(this._keyPair);
11420
- logger$25.debug("[DPoP] Key pair generated and persisted, fingerprint:", this._fingerprint);
11433
+ logger$26.debug("[DPoP] Key pair generated and persisted, fingerprint:", this._fingerprint);
11421
11434
  return this._fingerprint;
11422
11435
  }
11423
11436
  /**
@@ -11483,7 +11496,7 @@ var CryptoController = class {
11483
11496
  this._fingerprint = null;
11484
11497
  this._initialized = false;
11485
11498
  deleteKeyPairFromDB();
11486
- logger$25.debug("[DPoP] Controller destroyed");
11499
+ logger$26.debug("[DPoP] Controller destroyed");
11487
11500
  }
11488
11501
  get publicJwk() {
11489
11502
  if (!this._publicJwk) throw new DPoPInitError("CryptoController not initialized. Call init() first.");
@@ -11506,8 +11519,8 @@ var CryptoController = class {
11506
11519
 
11507
11520
  //#endregion
11508
11521
  //#region src/controllers/NetworkMonitor.ts
11509
- var import_cjs$24 = require_cjs();
11510
- const logger$24 = getLogger();
11522
+ var import_cjs$25 = require_cjs();
11523
+ const logger$25 = getLogger();
11511
11524
  /**
11512
11525
  * Safely check whether we are running in a browser environment
11513
11526
  * with `window` and the relevant event targets.
@@ -11550,13 +11563,13 @@ var NetworkMonitor = class extends Destroyable {
11550
11563
  this.attachListeners();
11551
11564
  }
11552
11565
  get isOnline$() {
11553
- return this._isOnline$.asObservable().pipe((0, import_cjs$24.takeUntil)(this._destroyed$));
11566
+ return this._isOnline$.asObservable().pipe((0, import_cjs$25.takeUntil)(this._destroyed$));
11554
11567
  }
11555
11568
  get isOnline() {
11556
11569
  return this._isOnline$.value;
11557
11570
  }
11558
11571
  get networkChange$() {
11559
- return this._networkChange$.asObservable().pipe((0, import_cjs$24.takeUntil)(this._destroyed$));
11572
+ return this._networkChange$.asObservable().pipe((0, import_cjs$25.takeUntil)(this._destroyed$));
11560
11573
  }
11561
11574
  destroy() {
11562
11575
  this.removeListeners();
@@ -11564,7 +11577,7 @@ var NetworkMonitor = class extends Destroyable {
11564
11577
  }
11565
11578
  attachListeners() {
11566
11579
  if (!hasBrowserNetworkEvents()) {
11567
- logger$24.debug("NetworkMonitor: no browser environment detected, skipping event listeners");
11580
+ logger$25.debug("NetworkMonitor: no browser environment detected, skipping event listeners");
11568
11581
  return;
11569
11582
  }
11570
11583
  window.addEventListener("online", this._onOnline);
@@ -11572,7 +11585,7 @@ var NetworkMonitor = class extends Destroyable {
11572
11585
  const connection = getNetworkConnection();
11573
11586
  if (connection) connection.addEventListener("change", this._onConnectionChange);
11574
11587
  this._listenersAttached = true;
11575
- logger$24.debug("NetworkMonitor: event listeners attached");
11588
+ logger$25.debug("NetworkMonitor: event listeners attached");
11576
11589
  }
11577
11590
  removeListeners() {
11578
11591
  if (!this._listenersAttached) return;
@@ -11583,10 +11596,10 @@ var NetworkMonitor = class extends Destroyable {
11583
11596
  if (connection) connection.removeEventListener("change", this._onConnectionChange);
11584
11597
  }
11585
11598
  this._listenersAttached = false;
11586
- logger$24.debug("NetworkMonitor: event listeners removed");
11599
+ logger$25.debug("NetworkMonitor: event listeners removed");
11587
11600
  }
11588
11601
  handleOnline() {
11589
- logger$24.info("NetworkMonitor: browser went online");
11602
+ logger$25.info("NetworkMonitor: browser went online");
11590
11603
  this._isOnline$.next(true);
11591
11604
  this._networkChange$.next({
11592
11605
  type: "online",
@@ -11595,7 +11608,7 @@ var NetworkMonitor = class extends Destroyable {
11595
11608
  });
11596
11609
  }
11597
11610
  handleOffline() {
11598
- logger$24.info("NetworkMonitor: browser went offline");
11611
+ logger$25.info("NetworkMonitor: browser went offline");
11599
11612
  this._isOnline$.next(false);
11600
11613
  this._networkChange$.next({
11601
11614
  type: "offline",
@@ -11604,7 +11617,7 @@ var NetworkMonitor = class extends Destroyable {
11604
11617
  }
11605
11618
  handleConnectionChange() {
11606
11619
  const networkType = getNetworkType();
11607
- logger$24.info(`NetworkMonitor: connection changed — effectiveType=${networkType ?? "unknown"}`);
11620
+ logger$25.info(`NetworkMonitor: connection changed — effectiveType=${networkType ?? "unknown"}`);
11608
11621
  this._networkChange$.next({
11609
11622
  type: "connection_change",
11610
11623
  timestamp: Date.now(),
@@ -11719,8 +11732,8 @@ function getNavigatorMediaDevices() {
11719
11732
 
11720
11733
  //#endregion
11721
11734
  //#region src/controllers/PreflightRunner.ts
11722
- var import_cjs$23 = require_cjs();
11723
- const logger$23 = getLogger();
11735
+ var import_cjs$24 = require_cjs();
11736
+ const logger$24 = getLogger();
11724
11737
  const DEFAULT_MEDIA_TEST_DURATION_S = 10;
11725
11738
  const ICE_GATHERING_TIMEOUT_MS = 1e4;
11726
11739
  const SIGNALING_RTT_TIMEOUT_MS = 5e3;
@@ -11769,7 +11782,7 @@ var PreflightRunner = class extends Destroyable {
11769
11782
  if (!this._options.skipMediaTest) try {
11770
11783
  bandwidth = await this.testMediaBandwidth(destination);
11771
11784
  } catch (error) {
11772
- logger$23.warn("[PreflightRunner] Media bandwidth test failed:", error);
11785
+ logger$24.warn("[PreflightRunner] Media bandwidth test failed:", error);
11773
11786
  warnings.push("Media bandwidth test failed");
11774
11787
  }
11775
11788
  return {
@@ -11781,7 +11794,7 @@ var PreflightRunner = class extends Destroyable {
11781
11794
  warnings
11782
11795
  };
11783
11796
  } catch (error) {
11784
- logger$23.error("[PreflightRunner] Preflight test failed:", error);
11797
+ logger$24.error("[PreflightRunner] Preflight test failed:", error);
11785
11798
  throw new PreflightError("preflight", error instanceof Error ? error : new Error(String(error)));
11786
11799
  } finally {
11787
11800
  this.destroy();
@@ -11812,7 +11825,7 @@ var PreflightRunner = class extends Destroyable {
11812
11825
  if (track.kind === "video" && track.readyState === "live") videoWorking = true;
11813
11826
  }
11814
11827
  } catch (error) {
11815
- logger$23.warn("[PreflightRunner] Device test failed:", error);
11828
+ logger$24.warn("[PreflightRunner] Device test failed:", error);
11816
11829
  } finally {
11817
11830
  if (audioStream) audioStream.getTracks().forEach((t) => t.stop());
11818
11831
  }
@@ -11835,18 +11848,19 @@ var PreflightRunner = class extends Destroyable {
11835
11848
  let pc;
11836
11849
  try {
11837
11850
  pc = new RTCPeerConnection({ iceServers: this.iceServers });
11851
+ const peerConnection = pc;
11838
11852
  const candidateTypes = /* @__PURE__ */ new Set();
11839
11853
  const startTime = Date.now();
11840
11854
  const gatheringComplete = new Promise((resolve) => {
11841
- const timer$2 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
11842
- pc.onicecandidate = (event) => {
11855
+ const timer$3 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
11856
+ peerConnection.onicecandidate = (event) => {
11843
11857
  if (event.candidate) {
11844
11858
  const candidateStr = event.candidate.candidate;
11845
11859
  if (candidateStr.includes("typ host")) candidateTypes.add("host");
11846
11860
  if (candidateStr.includes("typ srflx")) candidateTypes.add("srflx");
11847
11861
  if (candidateStr.includes("typ relay")) candidateTypes.add("relay");
11848
11862
  } else {
11849
- clearTimeout(timer$2);
11863
+ clearTimeout(timer$3);
11850
11864
  resolve();
11851
11865
  }
11852
11866
  };
@@ -11869,7 +11883,7 @@ var PreflightRunner = class extends Destroyable {
11869
11883
  rttMs
11870
11884
  };
11871
11885
  } catch (error) {
11872
- logger$23.warn("[PreflightRunner] ICE connectivity test failed:", error);
11886
+ logger$24.warn("[PreflightRunner] ICE connectivity test failed:", error);
11873
11887
  return {
11874
11888
  type: "failed",
11875
11889
  turnReachable: false,
@@ -11887,7 +11901,7 @@ var PreflightRunner = class extends Destroyable {
11887
11901
  audio: true,
11888
11902
  video: false
11889
11903
  });
11890
- await (0, import_cjs$23.firstValueFrom)(call.status$.pipe((0, import_cjs$23.filter)((s) => s === "connected"), (0, import_cjs$23.take)(1), (0, import_cjs$23.timeout)(SIGNALING_RTT_TIMEOUT_MS)));
11904
+ await (0, import_cjs$24.firstValueFrom)(call.status$.pipe((0, import_cjs$24.filter)((s) => s === "connected"), (0, import_cjs$24.take)(1), (0, import_cjs$24.timeout)(SIGNALING_RTT_TIMEOUT_MS)));
11891
11905
  const durationMs = this._options.duration * 1e3;
11892
11906
  await new Promise((resolve) => setTimeout(resolve, durationMs));
11893
11907
  const metrics = call.networkMetrics;
@@ -11916,8 +11930,8 @@ var PreflightRunner = class extends Destroyable {
11916
11930
 
11917
11931
  //#endregion
11918
11932
  //#region src/controllers/VisibilityController.ts
11919
- var import_cjs$22 = require_cjs();
11920
- const logger$22 = getLogger();
11933
+ var import_cjs$23 = require_cjs();
11934
+ const logger$23 = getLogger();
11921
11935
  /**
11922
11936
  * Checks whether the document visibility API is available.
11923
11937
  */
@@ -11954,15 +11968,15 @@ var VisibilityController = class extends Destroyable {
11954
11968
  this._boundHandler = this._handleVisibilityChange.bind(this);
11955
11969
  if (this._hasVisibilityApi) {
11956
11970
  document.addEventListener("visibilitychange", this._boundHandler);
11957
- logger$22.debug("VisibilityController: listening for visibilitychange events");
11958
- } else logger$22.debug("VisibilityController: document visibility API not available, defaulting to visible");
11971
+ logger$23.debug("VisibilityController: listening for visibilitychange events");
11972
+ } else logger$23.debug("VisibilityController: document visibility API not available, defaulting to visible");
11959
11973
  }
11960
11974
  /**
11961
11975
  * Observable of the current visibility state.
11962
11976
  * Emits 'visible' or 'hidden'. Always starts with the current state.
11963
11977
  */
11964
11978
  get visibility$() {
11965
- return this._visibility$.pipe((0, import_cjs$22.takeUntil)(this._destroyed$));
11979
+ return this._visibility$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
11966
11980
  }
11967
11981
  /**
11968
11982
  * The current visibility state value.
@@ -11975,12 +11989,12 @@ var VisibilityController = class extends Destroyable {
11975
11989
  * Each event includes the previous state, new state, and timestamp.
11976
11990
  */
11977
11991
  get visibilityChange$() {
11978
- return this._visibilityChange$.pipe((0, import_cjs$22.takeUntil)(this._destroyed$));
11992
+ return this._visibilityChange$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
11979
11993
  }
11980
11994
  destroy() {
11981
11995
  if (this._hasVisibilityApi) {
11982
11996
  document.removeEventListener("visibilitychange", this._boundHandler);
11983
- logger$22.debug("VisibilityController: removed visibilitychange listener");
11997
+ logger$23.debug("VisibilityController: removed visibilitychange listener");
11984
11998
  }
11985
11999
  super.destroy();
11986
12000
  }
@@ -11998,7 +12012,7 @@ var VisibilityController = class extends Destroyable {
11998
12012
  timestamp: Date.now()
11999
12013
  };
12000
12014
  this._visibilityChange$.next(changeEvent);
12001
- logger$22.debug("VisibilityController: visibility changed", {
12015
+ logger$23.debug("VisibilityController: visibility changed", {
12002
12016
  from: previousState,
12003
12017
  to: newState
12004
12018
  });
@@ -12007,13 +12021,13 @@ var VisibilityController = class extends Destroyable {
12007
12021
 
12008
12022
  //#endregion
12009
12023
  //#region src/behaviors/Fetchable.ts
12010
- var import_cjs$21 = require_cjs();
12024
+ var import_cjs$22 = require_cjs();
12011
12025
  var Fetchable = class extends Destroyable {
12012
12026
  constructor(fromPath, http) {
12013
12027
  super();
12014
12028
  this.fromPath = fromPath;
12015
12029
  this.http = http;
12016
- this.fetched$ = (0, import_cjs$21.defer)(() => (0, import_cjs$21.from)(this.fetch())).pipe((0, import_cjs$21.shareReplay)(1), (0, import_cjs$21.takeUntil)(this.destroyed$));
12030
+ this.fetched$ = (0, import_cjs$22.defer)(() => (0, import_cjs$22.from)(this.fetch())).pipe((0, import_cjs$22.shareReplay)(1), (0, import_cjs$22.takeUntil)(this.destroyed$));
12017
12031
  }
12018
12032
  async fetch() {
12019
12033
  const response = await this.http.request({
@@ -12248,7 +12262,7 @@ const RPCEventAckResponse = (id) => makeRPCResponse({
12248
12262
 
12249
12263
  //#endregion
12250
12264
  //#region src/managers/AttachManager.ts
12251
- const logger$21 = getLogger();
12265
+ const logger$22 = getLogger();
12252
12266
  var AttachManager = class {
12253
12267
  constructor(storage, deviceController, reconnectCallsTimeout, attachKey) {
12254
12268
  this.storage = storage;
@@ -12260,6 +12274,7 @@ var AttachManager = class {
12260
12274
  const attached = await this.readAttached();
12261
12275
  for (const callId of Object.keys(attached)) await this.detach({
12262
12276
  id: callId,
12277
+ nodeId: attached[callId].nodeId,
12263
12278
  mediaDirections: attached[callId].mediaDirections
12264
12279
  });
12265
12280
  }
@@ -12270,7 +12285,7 @@ var AttachManager = class {
12270
12285
  try {
12271
12286
  return await this.storage.getItem(this.attachKey) ?? {};
12272
12287
  } catch (error) {
12273
- logger$21.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
12288
+ logger$22.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
12274
12289
  return {};
12275
12290
  }
12276
12291
  }
@@ -12278,20 +12293,20 @@ var AttachManager = class {
12278
12293
  try {
12279
12294
  await this.storage.setItem(this.attachKey, attached);
12280
12295
  } catch (error) {
12281
- logger$21.warn("[AttachManager] Failed to write attached calls to storage", error);
12296
+ logger$22.warn("[AttachManager] Failed to write attached calls to storage", error);
12282
12297
  }
12283
12298
  }
12284
12299
  async attach(call) {
12285
12300
  if (!call.to) {
12286
- logger$21.warn("[AttachManager] Skip attach for calls with no destination");
12301
+ logger$22.warn("[AttachManager] Skip attach for calls with no destination");
12287
12302
  return;
12288
12303
  }
12289
12304
  const attachment = {
12305
+ nodeId: call.nodeId,
12290
12306
  destination: call.to,
12291
12307
  mediaDirections: call.mediaDirections,
12292
12308
  audioInputDevice: call.mediaDirections.audio !== "inactive" ? this.deviceController.selectedAudioInputDevice : null,
12293
12309
  videoInputDevice: call.mediaDirections.video !== "inactive" ? this.deviceController.selectedVideoInputDevice : null,
12294
- nodeId: call.nodeId,
12295
12310
  attachedAt: Date.now()
12296
12311
  };
12297
12312
  const updated = {
@@ -12334,15 +12349,15 @@ var AttachManager = class {
12334
12349
  callId,
12335
12350
  ...options
12336
12351
  });
12337
- logger$21.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
12352
+ logger$22.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
12338
12353
  succeeded = true;
12339
12354
  break;
12340
12355
  } catch (error) {
12341
- logger$21.warn(`[AttachManager] Reattach attempt ${attempt}/3 failed for call ${callId}:`, error);
12356
+ logger$22.warn(`[AttachManager] Reattach attempt ${attempt}/3 failed for call ${callId}:`, error);
12342
12357
  if (attempt < 3) await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
12343
12358
  }
12344
12359
  if (!succeeded) {
12345
- logger$21.warn(`[AttachManager] Reattach failed after 3 attempts for call ${callId}, removing reference`);
12360
+ logger$22.warn(`[AttachManager] Reattach failed after 3 attempts for call ${callId}, removing reference`);
12346
12361
  await this.detach({
12347
12362
  id: callId,
12348
12363
  mediaDirections: attachment.mediaDirections
@@ -12356,12 +12371,13 @@ var AttachManager = class {
12356
12371
  */
12357
12372
  buildCallOptions(attachment) {
12358
12373
  const { audio: audioDirection, video: videoDirection } = attachment.mediaDirections;
12359
- const { audioInputDevice, videoInputDevice } = attachment;
12374
+ const { audioInputDevice, videoInputDevice, nodeId } = attachment;
12360
12375
  const receiveAudio = audioDirection.includes("recv");
12361
12376
  const receiveVideo = videoDirection.includes("recv");
12362
12377
  const sendAudio = audioDirection.includes("send");
12363
12378
  const sendVideo = videoDirection.includes("send");
12364
12379
  return {
12380
+ nodeId,
12365
12381
  receiveAudio,
12366
12382
  receiveVideo,
12367
12383
  inputAudioDeviceConstraints: sendAudio ? {
@@ -12372,7 +12388,6 @@ var AttachManager = class {
12372
12388
  video: true,
12373
12389
  ...this.deviceController.deviceInfoToConstraints(videoInputDevice)
12374
12390
  } : void 0,
12375
- nodeId: attachment.nodeId ?? void 0,
12376
12391
  reattach: true
12377
12392
  };
12378
12393
  }
@@ -13248,7 +13263,7 @@ var require_operators = /* @__PURE__ */ __commonJSMin(((exports) => {
13248
13263
  //#endregion
13249
13264
  //#region src/operators/filterNull.ts
13250
13265
  var import_operators$1 = require_operators();
13251
- var import_cjs$20 = require_cjs();
13266
+ var import_cjs$21 = require_cjs();
13252
13267
  /**
13253
13268
  * RxJS operator that filters out `null` and `undefined` values with type narrowing.
13254
13269
  *
@@ -13260,7 +13275,7 @@ var import_cjs$20 = require_cjs();
13260
13275
  * ```
13261
13276
  */
13262
13277
  function filterNull() {
13263
- return (0, import_cjs$20.filter)((value) => value != null);
13278
+ return (0, import_cjs$21.filter)((value) => value != null);
13264
13279
  }
13265
13280
 
13266
13281
  //#endregion
@@ -13388,7 +13403,7 @@ function computeCapabilities(capabilities) {
13388
13403
 
13389
13404
  //#endregion
13390
13405
  //#region src/core/capabilities/SelfCapabilities.ts
13391
- var import_cjs$19 = require_cjs();
13406
+ var import_cjs$20 = require_cjs();
13392
13407
  /**
13393
13408
  * SelfCapabilities manages the capability state for the self participant.
13394
13409
  *
@@ -13424,7 +13439,7 @@ var SelfCapabilities = class extends Destroyable {
13424
13439
  }
13425
13440
  /** Observable for self member capabilities */
13426
13441
  get self$() {
13427
- return this.cachedObservable("self$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.self), (0, import_cjs$19.distinctUntilChanged)()));
13442
+ return this.cachedObservable("self$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.self), (0, import_cjs$20.distinctUntilChanged)()));
13428
13443
  }
13429
13444
  /** Current self member capabilities */
13430
13445
  get self() {
@@ -13432,7 +13447,7 @@ var SelfCapabilities = class extends Destroyable {
13432
13447
  }
13433
13448
  /** Observable for other member capabilities */
13434
13449
  get member$() {
13435
- return this.cachedObservable("member$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.member), (0, import_cjs$19.distinctUntilChanged)()));
13450
+ return this.cachedObservable("member$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.member), (0, import_cjs$20.distinctUntilChanged)()));
13436
13451
  }
13437
13452
  /** Current other member capabilities */
13438
13453
  get member() {
@@ -13440,7 +13455,7 @@ var SelfCapabilities = class extends Destroyable {
13440
13455
  }
13441
13456
  /** Observable for end call capability */
13442
13457
  get end$() {
13443
- return this.cachedObservable("end$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.end), (0, import_cjs$19.distinctUntilChanged)()));
13458
+ return this.cachedObservable("end$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.end), (0, import_cjs$20.distinctUntilChanged)()));
13444
13459
  }
13445
13460
  /** Current end call capability */
13446
13461
  get end() {
@@ -13448,7 +13463,7 @@ var SelfCapabilities = class extends Destroyable {
13448
13463
  }
13449
13464
  /** Observable for set layout capability */
13450
13465
  get setLayout$() {
13451
- return this.cachedObservable("setLayout$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.setLayout), (0, import_cjs$19.distinctUntilChanged)()));
13466
+ return this.cachedObservable("setLayout$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.setLayout), (0, import_cjs$20.distinctUntilChanged)()));
13452
13467
  }
13453
13468
  /** Current set layout capability */
13454
13469
  get setLayout() {
@@ -13456,7 +13471,7 @@ var SelfCapabilities = class extends Destroyable {
13456
13471
  }
13457
13472
  /** Observable for send digit capability */
13458
13473
  get sendDigit$() {
13459
- return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.sendDigit), (0, import_cjs$19.distinctUntilChanged)()));
13474
+ return this.cachedObservable("sendDigit$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.sendDigit), (0, import_cjs$20.distinctUntilChanged)()));
13460
13475
  }
13461
13476
  /** Current send digit capability */
13462
13477
  get sendDigit() {
@@ -13464,7 +13479,7 @@ var SelfCapabilities = class extends Destroyable {
13464
13479
  }
13465
13480
  /** Observable for vmuted hide capability */
13466
13481
  get vmutedHide$() {
13467
- return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.vmutedHide), (0, import_cjs$19.distinctUntilChanged)()));
13482
+ return this.cachedObservable("vmutedHide$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.vmutedHide), (0, import_cjs$20.distinctUntilChanged)()));
13468
13483
  }
13469
13484
  /** Current vmuted hide capability */
13470
13485
  get vmutedHide() {
@@ -13472,7 +13487,7 @@ var SelfCapabilities = class extends Destroyable {
13472
13487
  }
13473
13488
  /** Observable for lock capability */
13474
13489
  get lock$() {
13475
- return this.cachedObservable("lock$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.lock), (0, import_cjs$19.distinctUntilChanged)()));
13490
+ return this.cachedObservable("lock$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.lock), (0, import_cjs$20.distinctUntilChanged)()));
13476
13491
  }
13477
13492
  /** Current lock capability */
13478
13493
  get lock() {
@@ -13480,7 +13495,7 @@ var SelfCapabilities = class extends Destroyable {
13480
13495
  }
13481
13496
  /** Observable for device capability */
13482
13497
  get device$() {
13483
- return this.cachedObservable("device$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.device), (0, import_cjs$19.distinctUntilChanged)()));
13498
+ return this.cachedObservable("device$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.device), (0, import_cjs$20.distinctUntilChanged)()));
13484
13499
  }
13485
13500
  /** Current device capability */
13486
13501
  get device() {
@@ -13488,7 +13503,7 @@ var SelfCapabilities = class extends Destroyable {
13488
13503
  }
13489
13504
  /** Observable for screenshare capability */
13490
13505
  get screenshare$() {
13491
- return this.cachedObservable("screenshare$", () => this._state$.pipe((0, import_cjs$19.map)((state) => state.screenshare), (0, import_cjs$19.distinctUntilChanged)()));
13506
+ return this.cachedObservable("screenshare$", () => this._state$.pipe((0, import_cjs$20.map)((state) => state.screenshare), (0, import_cjs$20.distinctUntilChanged)()));
13492
13507
  }
13493
13508
  /** Current screenshare capability */
13494
13509
  get screenshare() {
@@ -13515,7 +13530,7 @@ function toggleHandraiseMethod(is) {
13515
13530
 
13516
13531
  //#endregion
13517
13532
  //#region src/core/entities/Participant.ts
13518
- const logger$20 = getLogger();
13533
+ const logger$21 = getLogger();
13519
13534
  const initialState = {};
13520
13535
  /**
13521
13536
  * Represents a participant in a call.
@@ -13893,7 +13908,7 @@ var SelfParticipant = class extends Participant {
13893
13908
  try {
13894
13909
  await this.vertoManager.addScreenMedia();
13895
13910
  } catch (error) {
13896
- logger$20.error("[Participant.startScreenShare] Screen share error:", error);
13911
+ logger$21.error("[Participant.startScreenShare] Screen share error:", error);
13897
13912
  }
13898
13913
  }
13899
13914
  /** Observable of the current screen share status. */
@@ -13913,7 +13928,7 @@ var SelfParticipant = class extends Participant {
13913
13928
  try {
13914
13929
  await this.vertoManager.addInputDevice(options);
13915
13930
  } catch (error) {
13916
- logger$20.error("[Participant.startScreenShare] Screen share error:", error);
13931
+ logger$21.error("[Participant.startScreenShare] Screen share error:", error);
13917
13932
  }
13918
13933
  }
13919
13934
  /** Removes an additional media input device by ID. */
@@ -13975,7 +13990,7 @@ var SelfParticipant = class extends Participant {
13975
13990
  */
13976
13991
  exitStudioModeIfActive() {
13977
13992
  if (this._studioAudio$.value) {
13978
- logger$20.debug("[SelfParticipant] Exiting studio audio mode due to individual flag toggle");
13993
+ logger$21.debug("[SelfParticipant] Exiting studio audio mode due to individual flag toggle");
13979
13994
  this._studioAudio$.next(false);
13980
13995
  }
13981
13996
  }
@@ -13999,7 +14014,7 @@ var SelfParticipant = class extends Participant {
13999
14014
  try {
14000
14015
  await super.mute();
14001
14016
  } catch (error) {
14002
- logger$20.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
14017
+ logger$21.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
14003
14018
  } finally {
14004
14019
  this.vertoManager.muteMainAudioInputDevice();
14005
14020
  }
@@ -14009,7 +14024,7 @@ var SelfParticipant = class extends Participant {
14009
14024
  try {
14010
14025
  await super.unmute();
14011
14026
  } catch (error) {
14012
- logger$20.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
14027
+ logger$21.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
14013
14028
  } finally {
14014
14029
  await this.vertoManager.unmuteMainAudioInputDevice();
14015
14030
  }
@@ -14019,7 +14034,7 @@ var SelfParticipant = class extends Participant {
14019
14034
  try {
14020
14035
  await super.muteVideo();
14021
14036
  } catch (error) {
14022
- logger$20.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
14037
+ logger$21.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
14023
14038
  } finally {
14024
14039
  this.vertoManager.muteMainVideoInputDevice();
14025
14040
  }
@@ -14029,7 +14044,7 @@ var SelfParticipant = class extends Participant {
14029
14044
  try {
14030
14045
  await super.unmuteVideo();
14031
14046
  } catch (error) {
14032
- logger$20.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
14047
+ logger$21.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
14033
14048
  } finally {
14034
14049
  await this.vertoManager.unmuteMainVideoInputDevice();
14035
14050
  }
@@ -14133,7 +14148,7 @@ const getValueFrom = (obj, path, defaultValue) => {
14133
14148
 
14134
14149
  //#endregion
14135
14150
  //#region src/operators/filterEventAs.ts
14136
- var import_cjs$18 = require_cjs();
14151
+ var import_cjs$19 = require_cjs();
14137
14152
  var import_operators = require_operators();
14138
14153
  /**
14139
14154
  * RxJS operator that filters events based on a predicate and maps matching events.
@@ -14167,7 +14182,7 @@ var import_operators = require_operators();
14167
14182
  * ```
14168
14183
  */
14169
14184
  function ifIsMap(predicate, mapFn) {
14170
- return (0, import_cjs$18.pipe)((0, import_operators.filter)(predicate), (0, import_operators.map)(mapFn));
14185
+ return (0, import_cjs$19.pipe)((0, import_operators.filter)(predicate), (0, import_operators.map)(mapFn));
14171
14186
  }
14172
14187
  /**
14173
14188
  * Generic RxJS operator that filters events using a type guard and extracts a property.
@@ -14209,38 +14224,38 @@ function ifIsMap(predicate, mapFn) {
14209
14224
  * ```
14210
14225
  */
14211
14226
  function filterAs(predicate, resultPath) {
14212
- return (0, import_cjs$18.pipe)(ifIsMap(predicate, (event) => {
14227
+ return (0, import_cjs$19.pipe)(ifIsMap(predicate, (event) => {
14213
14228
  return getValueFrom(event, resultPath);
14214
14229
  }), (0, import_operators.filter)((value) => value !== void 0));
14215
14230
  }
14216
14231
 
14217
14232
  //#endregion
14218
14233
  //#region src/operators/throwOnRPCError.ts
14219
- var import_cjs$17 = require_cjs();
14220
- const logger$19 = getLogger();
14234
+ var import_cjs$18 = require_cjs();
14235
+ const logger$20 = getLogger();
14221
14236
  /**
14222
14237
  * RxJS operator that throws a {@link JSONRPCError} when the RPC response contains an error.
14223
14238
  * Passes successful responses through unchanged.
14224
14239
  */
14225
14240
  function throwOnRPCError() {
14226
- return (0, import_cjs$17.map)((response) => {
14241
+ return (0, import_cjs$18.map)((response) => {
14227
14242
  if (response.error) {
14228
- logger$19.error("[throwOnRPCError] RPC error response:", {
14243
+ logger$20.error("[throwOnRPCError] RPC error response:", {
14229
14244
  code: response.error.code,
14230
14245
  message: response.error.message,
14231
14246
  data: response.error.data
14232
14247
  });
14233
14248
  throw new JSONRPCError(response.error.code, response.error.message, response.error.data);
14234
14249
  }
14235
- logger$19.debug("[throwOnRPCError] RPC successful response:", response);
14250
+ logger$20.debug("[throwOnRPCError] RPC successful response:", response);
14236
14251
  return response;
14237
14252
  });
14238
14253
  }
14239
14254
 
14240
14255
  //#endregion
14241
14256
  //#region src/managers/CallEventsManager.ts
14242
- var import_cjs$16 = require_cjs();
14243
- const logger$18 = getLogger();
14257
+ var import_cjs$17 = require_cjs();
14258
+ const logger$19 = getLogger();
14244
14259
  const initialSessionState = {};
14245
14260
  /** @internal */
14246
14261
  var CallEventsManager = class extends Destroyable {
@@ -14256,7 +14271,7 @@ var CallEventsManager = class extends Destroyable {
14256
14271
  this.initSubscriptions();
14257
14272
  }
14258
14273
  get participants$() {
14259
- return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$16.map)((participantsRecord) => Object.values(participantsRecord))));
14274
+ return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$17.map)((participantsRecord) => Object.values(participantsRecord))));
14260
14275
  }
14261
14276
  get participants() {
14262
14277
  return Object.values(this._participants$.value);
@@ -14274,40 +14289,40 @@ var CallEventsManager = class extends Destroyable {
14274
14289
  return this.callIds.has(callId);
14275
14290
  }
14276
14291
  get recording$() {
14277
- return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.recording), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14292
+ return this.cachedObservable("recording$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.recording), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14278
14293
  }
14279
14294
  get recordings$() {
14280
- return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.recordings), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14295
+ return this.cachedObservable("recordings$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.recordings), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14281
14296
  }
14282
14297
  get streaming$() {
14283
- return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.streaming), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14298
+ return this.cachedObservable("streaming$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.streaming), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14284
14299
  }
14285
14300
  get streams$() {
14286
- return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.streams), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14301
+ return this.cachedObservable("streams$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.streams), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14287
14302
  }
14288
14303
  get playbacks$() {
14289
- return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.playbacks), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14304
+ return this.cachedObservable("playbacks$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.playbacks), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14290
14305
  }
14291
14306
  get raiseHandPriority$() {
14292
- return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.prioritize_handraise), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14307
+ return this.cachedObservable("raiseHandPriority$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.prioritize_handraise), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14293
14308
  }
14294
14309
  get locked$() {
14295
- return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.locked), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14310
+ return this.cachedObservable("locked$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.locked), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14296
14311
  }
14297
14312
  get meta$() {
14298
- return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.meta), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14313
+ return this.cachedObservable("meta$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.meta), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14299
14314
  }
14300
14315
  get capabilities$() {
14301
- return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.capabilities), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14316
+ return this.cachedObservable("capabilities$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.capabilities), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14302
14317
  }
14303
14318
  get layout$() {
14304
- return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.layout_name), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14319
+ return this.cachedObservable("layout$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layout_name), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14305
14320
  }
14306
14321
  get layouts$() {
14307
- return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.layouts), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14322
+ return this.cachedObservable("layouts$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layouts), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14308
14323
  }
14309
14324
  get layoutLayers$() {
14310
- return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, import_cjs$16.map)((state) => state.layout_layers), (0, import_cjs$16.distinctUntilChanged)(), filterNull()));
14325
+ return this.cachedObservable("layoutLayers$", () => this._sessionState$.pipe((0, import_cjs$17.map)((state) => state.layout_layers), (0, import_cjs$17.distinctUntilChanged)(), filterNull()));
14311
14326
  }
14312
14327
  get self() {
14313
14328
  return this._self$.value;
@@ -14344,7 +14359,7 @@ var CallEventsManager = class extends Destroyable {
14344
14359
  }
14345
14360
  initSubscriptions() {
14346
14361
  this.subscribeTo(this.callJoinedEvent$, (callJoinedEvent) => {
14347
- logger$18.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
14362
+ logger$19.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
14348
14363
  callId: callJoinedEvent.call_id,
14349
14364
  roomSessionId: callJoinedEvent.room_session_id
14350
14365
  });
@@ -14371,19 +14386,19 @@ var CallEventsManager = class extends Destroyable {
14371
14386
  if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
14372
14387
  });
14373
14388
  this.subscribeTo(this.memberUpdates$, (member) => {
14374
- logger$18.debug("[CallEventsManager] Handling member update event for member ID:", member);
14389
+ logger$19.debug("[CallEventsManager] Handling member update event for member ID:", member);
14375
14390
  this.upsertParticipant(member);
14376
14391
  });
14377
14392
  this.subscribeTo(this.webRtcCallSession.memberLeft$, (memberLeftEvent) => {
14378
- logger$18.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
14393
+ logger$19.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
14379
14394
  const participants = { ...this._participants$.value };
14380
14395
  if (memberLeftEvent.member.member_id in participants) {
14381
14396
  delete participants[memberLeftEvent.member.member_id];
14382
14397
  this._participants$.next(participants);
14383
- } else logger$18.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
14398
+ } else logger$19.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
14384
14399
  });
14385
14400
  this.subscribeTo(this.webRtcCallSession.callUpdated$, (callUpdatedEvent) => {
14386
- logger$18.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
14401
+ logger$19.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
14387
14402
  const roomSession = callUpdatedEvent.room_session;
14388
14403
  this._sessionState$.next({
14389
14404
  ...this._sessionState$.value,
@@ -14398,7 +14413,7 @@ var CallEventsManager = class extends Destroyable {
14398
14413
  });
14399
14414
  });
14400
14415
  this.subscribeTo(this.layoutChangedEvent$, (layoutChangedEvent) => {
14401
- logger$18.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
14416
+ logger$19.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
14402
14417
  this._sessionState$.next({
14403
14418
  ...this._sessionState$.value,
14404
14419
  layout_name: layoutChangedEvent.id,
@@ -14408,10 +14423,10 @@ var CallEventsManager = class extends Destroyable {
14408
14423
  });
14409
14424
  }
14410
14425
  updateParticipantPositions(layoutChangedEvent) {
14411
- if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$18.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
14412
- layoutChangedEvent.layers.filter((layer) => Boolean(layer.member_id)).filter((layer) => {
14413
- if (!layer.member_id || !(layer.member_id in this._participants$.value)) {
14414
- logger$18.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
14426
+ if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$19.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
14427
+ layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
14428
+ if (!(layer.member_id in this._participants$.value)) {
14429
+ logger$19.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
14415
14430
  return false;
14416
14431
  }
14417
14432
  return true;
@@ -14434,7 +14449,7 @@ var CallEventsManager = class extends Destroyable {
14434
14449
  layouts: response.result.layouts
14435
14450
  });
14436
14451
  }).catch((error) => {
14437
- logger$18.error("[CallEventsManager] Error fetching layouts:", error);
14452
+ logger$19.error("[CallEventsManager] Error fetching layouts:", error);
14438
14453
  });
14439
14454
  }
14440
14455
  updateParticipants(members) {
@@ -14450,7 +14465,7 @@ var CallEventsManager = class extends Destroyable {
14450
14465
  }
14451
14466
  const participant = this._participants$.value[member.member_id];
14452
14467
  const oldValue = participant.value;
14453
- logger$18.debug("[CallEventsManager] Updating participant:", member.member_id, {
14468
+ logger$19.debug("[CallEventsManager] Updating participant:", member.member_id, {
14454
14469
  oldValue,
14455
14470
  newValue: member
14456
14471
  });
@@ -14462,18 +14477,18 @@ var CallEventsManager = class extends Destroyable {
14462
14477
  this._participants$.next(this._participants$.value);
14463
14478
  }
14464
14479
  get callJoinedEvent$() {
14465
- return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$16.filter)(isCallJoinedPayload), (0, import_cjs$16.tap)((event) => {
14466
- logger$18.debug("[CallEventsManager] Call joined event:", event);
14480
+ return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$17.filter)(isCallJoinedPayload), (0, import_cjs$17.tap)((event) => {
14481
+ logger$19.debug("[CallEventsManager] Call joined event:", event);
14467
14482
  })));
14468
14483
  }
14469
14484
  get layoutChangedEvent$() {
14470
- return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$16.tap)((event) => {
14471
- logger$18.debug("[CallEventsManager] Layout changed event:", event);
14485
+ return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$17.tap)((event) => {
14486
+ logger$19.debug("[CallEventsManager] Layout changed event:", event);
14472
14487
  })));
14473
14488
  }
14474
14489
  get memberUpdates$() {
14475
- return this.cachedObservable("memberUpdates$", () => (0, import_cjs$16.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, import_cjs$16.map)((event) => event.member), (0, import_cjs$16.tap)((event) => {
14476
- logger$18.debug("[CallEventsManager] Member update event:", event);
14490
+ return this.cachedObservable("memberUpdates$", () => (0, import_cjs$17.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, import_cjs$17.map)((event) => event.member), (0, import_cjs$17.tap)((event) => {
14491
+ logger$19.debug("[CallEventsManager] Member update event:", event);
14477
14492
  })));
14478
14493
  }
14479
14494
  destroy() {
@@ -14729,8 +14744,8 @@ function appendStereoParams(fmtpLine, maxBitrate) {
14729
14744
 
14730
14745
  //#endregion
14731
14746
  //#region src/controllers/ICEGatheringController.ts
14732
- var import_cjs$15 = require_cjs();
14733
- const logger$17 = getLogger();
14747
+ var import_cjs$16 = require_cjs();
14748
+ const logger$18 = getLogger();
14734
14749
  var ICEGatheringController = class extends Destroyable {
14735
14750
  constructor(peerConnection, peerConnectionControllerNegotiating$, options = {}) {
14736
14751
  super();
@@ -14738,23 +14753,23 @@ var ICEGatheringController = class extends Destroyable {
14738
14753
  this.peerConnectionControllerNegotiating$ = peerConnectionControllerNegotiating$;
14739
14754
  this.onicegatheringstatechangeHandler = () => {
14740
14755
  const { iceGatheringState } = this.peerConnection;
14741
- logger$17.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
14756
+ logger$18.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
14742
14757
  if (iceGatheringState === "gathering") this._iceCandidatesState.next({
14743
14758
  state: "gathering",
14744
14759
  validSDP: false
14745
14760
  });
14746
14761
  };
14747
14762
  this.onicecandidateHandler = (event) => {
14748
- logger$17.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
14763
+ logger$18.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
14749
14764
  this.removeTimer("iceCandidateTimer");
14750
14765
  if (event.candidate) this.iceCandidateTimer = setTimeout(() => {
14751
14766
  if (this.peerConnection.iceGatheringState !== "complete") {
14752
- logger$17.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
14767
+ logger$18.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
14753
14768
  this.handleICECandidateTimeout();
14754
14769
  }
14755
14770
  }, this.iceCandidateTimeout);
14756
14771
  else {
14757
- logger$17.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
14772
+ logger$18.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
14758
14773
  this.removeTimer("iceGatheringTimer");
14759
14774
  this.handleICEGatheringComplete();
14760
14775
  }
@@ -14767,12 +14782,12 @@ var ICEGatheringController = class extends Destroyable {
14767
14782
  this.iceGatheringTimeout = options.iceGatheringTimeout ?? DEFAULT_ICE_GATHERING_TIMEOUT_MS;
14768
14783
  this.relayOnly = options.relayOnly ?? false;
14769
14784
  this.setupEventListeners();
14770
- this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe((0, import_cjs$15.filter)((isNegotiating) => isNegotiating)), (isNegotiating) => {
14785
+ this.subscribeTo(this.peerConnectionControllerNegotiating$.pipe((0, import_cjs$16.filter)((isNegotiating) => isNegotiating)), (isNegotiating) => {
14771
14786
  if (isNegotiating) {
14772
14787
  this.setupEventListeners();
14773
14788
  this.iceGatheringTimer = setTimeout(() => {
14774
14789
  if (this.peerConnection.iceGatheringState !== "complete") {
14775
- logger$17.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
14790
+ logger$18.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
14776
14791
  this.handleICEGatheringTimeout();
14777
14792
  }
14778
14793
  }, this.iceGatheringTimeout);
@@ -14786,7 +14801,7 @@ var ICEGatheringController = class extends Destroyable {
14786
14801
  this.peerConnection.addEventListener("icegatheringstatechange", this.onicegatheringstatechangeHandler);
14787
14802
  }
14788
14803
  get iceCandidatesState$() {
14789
- return this._iceCandidatesState.pipe((0, import_cjs$15.withLatestFrom)(this.peerConnectionControllerNegotiating$), (0, import_cjs$15.filter)(([_, isNegotiating]) => isNegotiating), (0, import_cjs$15.map)(([state, _]) => state.state));
14804
+ return this._iceCandidatesState.pipe((0, import_cjs$16.withLatestFrom)(this.peerConnectionControllerNegotiating$), (0, import_cjs$16.filter)(([_, isNegotiating]) => isNegotiating), (0, import_cjs$16.map)(([state, _]) => state.state));
14790
14805
  }
14791
14806
  get hasValidLocalDescriptionSDP() {
14792
14807
  const sdp = this.peerConnection.localDescription?.sdp;
@@ -14799,9 +14814,9 @@ var ICEGatheringController = class extends Destroyable {
14799
14814
  this.relayOnly = value;
14800
14815
  }
14801
14816
  handleICEGatheringComplete() {
14802
- logger$17.debug("[ICEGatheringController] Handling ICE gathering complete");
14803
- logger$17.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
14804
- logger$17.debug("[ICEGatheringController] ICE gathering complete");
14817
+ logger$18.debug("[ICEGatheringController] Handling ICE gathering complete");
14818
+ logger$18.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
14819
+ logger$18.debug("[ICEGatheringController] ICE gathering complete");
14805
14820
  this._iceCandidatesState.next({
14806
14821
  state: "complete",
14807
14822
  validSDP: this.hasValidLocalDescriptionSDP
@@ -14817,21 +14832,21 @@ var ICEGatheringController = class extends Destroyable {
14817
14832
  this.removeTimer("iceGatheringTimer");
14818
14833
  const validSDP = this.hasValidLocalDescriptionSDP;
14819
14834
  if (validSDP) {
14820
- logger$17.debug("[ICEGatheringController] Local SDP is valid");
14835
+ logger$18.debug("[ICEGatheringController] Local SDP is valid");
14821
14836
  this._iceCandidatesState.next({
14822
14837
  state: "timeout",
14823
14838
  validSDP
14824
14839
  });
14825
14840
  this.stopGathering();
14826
- } else logger$17.debug("### ICE gathering timeout\n", this.peerConnection.localDescription?.sdp);
14841
+ } else logger$18.debug("### ICE gathering timeout\n", this.peerConnection.localDescription?.sdp);
14827
14842
  }
14828
14843
  handleICECandidateTimeout() {
14829
14844
  if (this.iceCandidateTimer) this.removeTimer("iceCandidateTimer");
14830
- logger$17.warn("[ICEGatheringController] ICE candidate timeout");
14845
+ logger$18.warn("[ICEGatheringController] ICE candidate timeout");
14831
14846
  const validSDP = this.hasValidLocalDescriptionSDP;
14832
14847
  if (!validSDP && !this.relayOnly) this.restartICEGatheringWithRelayOnly();
14833
14848
  else {
14834
- logger$17.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout");
14849
+ logger$18.debug("[ICEGatheringController] Using current SDP due to ICE candidate timeout");
14835
14850
  this._iceCandidatesState.next({
14836
14851
  state: "timeout",
14837
14852
  validSDP
@@ -14840,7 +14855,7 @@ var ICEGatheringController = class extends Destroyable {
14840
14855
  }
14841
14856
  }
14842
14857
  restartICEGatheringWithRelayOnly() {
14843
- logger$17.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
14858
+ logger$18.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
14844
14859
  this.relayOnly = true;
14845
14860
  this.peerConnection.setConfiguration({
14846
14861
  ...this.peerConnection.getConfiguration(),
@@ -14848,14 +14863,14 @@ var ICEGatheringController = class extends Destroyable {
14848
14863
  });
14849
14864
  if (!(this.peerConnection.connectionState === "connected")) this.peerConnection.restartIce();
14850
14865
  }
14851
- removeTimer(timer$2) {
14852
- if (this[timer$2]) {
14853
- clearTimeout(this[timer$2]);
14854
- this[timer$2] = void 0;
14866
+ removeTimer(timer$3) {
14867
+ if (this[timer$3]) {
14868
+ clearTimeout(this[timer$3]);
14869
+ this[timer$3] = void 0;
14855
14870
  }
14856
14871
  }
14857
14872
  clearAllTimers() {
14858
- logger$17.debug("[ICEGatheringController] Clearing all timers");
14873
+ logger$18.debug("[ICEGatheringController] Clearing all timers");
14859
14874
  this.removeTimer("iceGatheringTimer");
14860
14875
  this.removeTimer("iceCandidateTimer");
14861
14876
  }
@@ -14864,7 +14879,7 @@ var ICEGatheringController = class extends Destroyable {
14864
14879
  this.peerConnection.removeEventListener("icecandidate", this.onicecandidateHandler);
14865
14880
  }
14866
14881
  destroy() {
14867
- logger$17.debug("[ICEGatheringController] Destroying ICEGatheringController");
14882
+ logger$18.debug("[ICEGatheringController] Destroying ICEGatheringController");
14868
14883
  this.clearAllTimers();
14869
14884
  this.removeEventListeners();
14870
14885
  super.destroy();
@@ -14873,8 +14888,8 @@ var ICEGatheringController = class extends Destroyable {
14873
14888
 
14874
14889
  //#endregion
14875
14890
  //#region src/controllers/LocalStreamController.ts
14876
- var import_cjs$14 = require_cjs();
14877
- const logger$16 = getLogger();
14891
+ var import_cjs$15 = require_cjs();
14892
+ const logger$17 = getLogger();
14878
14893
  var LocalStreamController = class extends Destroyable {
14879
14894
  constructor(options) {
14880
14895
  super();
@@ -14888,16 +14903,16 @@ var LocalStreamController = class extends Destroyable {
14888
14903
  this._mediaTrackEnded$ = this.createSubject();
14889
14904
  }
14890
14905
  get localStream$() {
14891
- return this._localStream$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$));
14906
+ return this._localStream$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
14892
14907
  }
14893
14908
  get localAudioTracks$() {
14894
- return this._localAudioTracks$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$));
14909
+ return this._localAudioTracks$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
14895
14910
  }
14896
14911
  get localVideoTracks$() {
14897
- return this._localVideoTracks$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$));
14912
+ return this._localVideoTracks$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
14898
14913
  }
14899
14914
  get mediaTrackEnded$() {
14900
- return this._mediaTrackEnded$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$));
14915
+ return this._mediaTrackEnded$.asObservable().pipe((0, import_cjs$15.takeUntil)(this.destroyed$));
14901
14916
  }
14902
14917
  get localStream() {
14903
14918
  return this._localStream$.value;
@@ -14912,26 +14927,26 @@ var LocalStreamController = class extends Destroyable {
14912
14927
  * Build the local media stream based on the provided options.
14913
14928
  */
14914
14929
  async buildLocalStream() {
14915
- logger$16.debug("[LocalStreamController] Building local media stream.");
14930
+ logger$17.debug("[LocalStreamController] Building local media stream.");
14916
14931
  let stream;
14917
14932
  if (this.options.inputAudioStream ?? this.options.inputVideoStream) {
14918
14933
  const tracks = [...this.options.inputAudioStream?.getTracks() ?? [], ...this.options.inputVideoStream?.getTracks() ?? []];
14919
14934
  stream = new MediaStream(tracks);
14920
14935
  } else if (this.options.propose === "screenshare") {
14921
- logger$16.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
14936
+ logger$17.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
14922
14937
  stream = await this.options.getDisplayMedia({
14923
14938
  video: true,
14924
14939
  audio: Boolean(this.options.inputAudioDeviceConstraints)
14925
14940
  });
14926
- logger$16.debug("[LocalStreamController] Screen share media obtained:", stream);
14941
+ logger$17.debug("[LocalStreamController] Screen share media obtained:", stream);
14927
14942
  } else {
14928
14943
  const constraints = {
14929
14944
  audio: this.options.inputAudioDeviceConstraints,
14930
14945
  video: this.options.inputVideoDeviceConstraints
14931
14946
  };
14932
- logger$16.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
14947
+ logger$17.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
14933
14948
  stream = await this.options.getUserMedia(constraints);
14934
- logger$16.debug("[LocalStreamController] User media obtained:", stream);
14949
+ logger$17.debug("[LocalStreamController] User media obtained:", stream);
14935
14950
  }
14936
14951
  this._localStream$.next(stream);
14937
14952
  return stream;
@@ -14948,7 +14963,7 @@ var LocalStreamController = class extends Destroyable {
14948
14963
  this._localStream$.next(localStream);
14949
14964
  if (track.kind === "video") this._localVideoTracks$.next(localStream.getVideoTracks());
14950
14965
  else this._localAudioTracks$.next(localStream.getAudioTracks());
14951
- logger$16.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
14966
+ logger$17.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
14952
14967
  return localStream;
14953
14968
  }
14954
14969
  /**
@@ -14960,7 +14975,7 @@ var LocalStreamController = class extends Destroyable {
14960
14975
  const stream = this._localStream$.value;
14961
14976
  const track = stream?.getTracks().find((t) => t.id === trackId);
14962
14977
  if (!track) {
14963
- logger$16.debug(`[LocalStreamController] track not found: ${trackId}`);
14978
+ logger$17.debug(`[LocalStreamController] track not found: ${trackId}`);
14964
14979
  return;
14965
14980
  }
14966
14981
  track.removeEventListener("ended", this.mediaTrackEndedHandler);
@@ -14969,7 +14984,7 @@ var LocalStreamController = class extends Destroyable {
14969
14984
  this._localStream$.next(stream);
14970
14985
  if (track.kind === "video") this._localVideoTracks$.next(stream?.getVideoTracks() ?? []);
14971
14986
  else this._localAudioTracks$.next(stream?.getAudioTracks() ?? []);
14972
- logger$16.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
14987
+ logger$17.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
14973
14988
  return track;
14974
14989
  }
14975
14990
  /**
@@ -15004,7 +15019,7 @@ var LocalStreamController = class extends Destroyable {
15004
15019
  */
15005
15020
  stopAllTracks() {
15006
15021
  this._localStream$.value?.getTracks().forEach((track) => {
15007
- logger$16.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
15022
+ logger$17.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
15008
15023
  track.removeEventListener("ended", this.mediaTrackEndedHandler);
15009
15024
  track.stop();
15010
15025
  });
@@ -15020,7 +15035,7 @@ var LocalStreamController = class extends Destroyable {
15020
15035
 
15021
15036
  //#endregion
15022
15037
  //#region src/controllers/TransceiverController.ts
15023
- const logger$15 = getLogger();
15038
+ const logger$16 = getLogger();
15024
15039
  const getDirection = (send, recv) => {
15025
15040
  if (send && recv) return "sendrecv";
15026
15041
  else if (send && !recv) return "sendonly";
@@ -15122,7 +15137,7 @@ var TransceiverController = class extends Destroyable {
15122
15137
  sendEncodings: isAudio ? void 0 : this.sendEncodings,
15123
15138
  streams: direction === "recvonly" ? void 0 : [localStream]
15124
15139
  };
15125
- logger$15.debug(`[TransceiverController] Setting up transceiver sender for local ${track.kind} track:`, {
15140
+ logger$16.debug(`[TransceiverController] Setting up transceiver sender for local ${track.kind} track:`, {
15126
15141
  transceiver,
15127
15142
  transceiverParams
15128
15143
  });
@@ -15130,11 +15145,11 @@ var TransceiverController = class extends Destroyable {
15130
15145
  await transceiver.sender.replaceTrack(track);
15131
15146
  transceiver.direction = transceiverParams.direction;
15132
15147
  if (transceiverParams.streams?.some((stream) => Boolean(stream))) {
15133
- logger$15.debug(`[TransceiverController] Setting streams for transceiver sender for local ${track.kind} track:`, transceiverParams.streams);
15148
+ logger$16.debug(`[TransceiverController] Setting streams for transceiver sender for local ${track.kind} track:`, transceiverParams.streams);
15134
15149
  transceiver.sender.setStreams(...transceiverParams.streams);
15135
15150
  }
15136
15151
  } else {
15137
- logger$15.debug(`[TransceiverController] Adding new transceiver for local ${track.kind} track:`, track.id);
15152
+ logger$16.debug(`[TransceiverController] Adding new transceiver for local ${track.kind} track:`, track.id);
15138
15153
  this.peerConnection.addTransceiver(track, transceiverParams);
15139
15154
  }
15140
15155
  }
@@ -15148,13 +15163,13 @@ var TransceiverController = class extends Destroyable {
15148
15163
  if (options.updateTransceiverDirection) transceiver.direction = "inactive";
15149
15164
  }
15150
15165
  } catch (error) {
15151
- logger$15.error("[TransceiverController] stopTrackSender error", kind, error);
15166
+ logger$16.error("[TransceiverController] stopTrackSender error", kind, error);
15152
15167
  this.options.onError?.(new MediaTrackError("stopTrackSender", kind, error));
15153
15168
  }
15154
15169
  }
15155
15170
  async restoreTrackSender(kind) {
15156
15171
  try {
15157
- logger$15.debug("[TransceiverController] restoreTrackSender called", kind);
15172
+ logger$16.debug("[TransceiverController] restoreTrackSender called", kind);
15158
15173
  const constraints = {};
15159
15174
  const transceivers = this.transceiverByKind(kind);
15160
15175
  for (const transceiver of transceivers) {
@@ -15164,23 +15179,23 @@ var TransceiverController = class extends Destroyable {
15164
15179
  if (trackKind === "audio" || trackKind === "video") constraints[trackKind] = this.getConstraintsFor(trackKind);
15165
15180
  }
15166
15181
  }
15167
- logger$15.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
15182
+ logger$16.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
15168
15183
  if (Object.keys(constraints).length === 0) {
15169
- logger$15.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
15184
+ logger$16.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
15170
15185
  return;
15171
15186
  }
15172
15187
  const newTracks = (await this.options.getUserMedia(constraints)).getTracks();
15173
- logger$15.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
15188
+ logger$16.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
15174
15189
  for (const newTrack of newTracks) {
15175
15190
  this.options.localStreamController.addTrack(newTrack);
15176
15191
  const trackKind = newTrack.kind;
15177
15192
  const transceiverOfKind = this.transceiverByKind(trackKind)[0];
15178
15193
  transceiverOfKind.direction = trackKind === "audio" ? this.audioDirection : this.videoDirection;
15179
- logger$15.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
15194
+ logger$16.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
15180
15195
  await transceiverOfKind.sender.replaceTrack(newTrack);
15181
15196
  }
15182
15197
  } catch (error) {
15183
- logger$15.error("[TransceiverController] restoreTrackSender error", kind, error);
15198
+ logger$16.error("[TransceiverController] restoreTrackSender error", kind, error);
15184
15199
  this.options.onError?.(new MediaTrackError("restoreTrackSender", kind, error));
15185
15200
  }
15186
15201
  }
@@ -15221,14 +15236,14 @@ var TransceiverController = class extends Destroyable {
15221
15236
  };
15222
15237
  try {
15223
15238
  await track.applyConstraints(constraintsToApply);
15224
- logger$15.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
15225
- logger$15.debug(`[TransceiverController] Updated ${kind} sender constraints:`, track.getConstraints());
15239
+ logger$16.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
15240
+ logger$16.debug(`[TransceiverController] Updated ${kind} sender constraints:`, track.getConstraints());
15226
15241
  } catch (error) {
15227
- logger$15.warn(`[TransceiverController] applyConstraints failed for ${kind} track ${track.id}, attempting track replacement fallback:`, error);
15242
+ logger$16.warn(`[TransceiverController] applyConstraints failed for ${kind} track ${track.id}, attempting track replacement fallback:`, error);
15228
15243
  try {
15229
15244
  await this.replaceTrackFallback(sender, track, kind, constraintsToApply);
15230
15245
  } catch (fallbackError) {
15231
- logger$15.warn(`[TransceiverController] Track replacement fallback also failed for ${kind} track:`, fallbackError);
15246
+ logger$16.warn(`[TransceiverController] Track replacement fallback also failed for ${kind} track:`, fallbackError);
15232
15247
  this.options.onError?.(new MediaTrackError("updateSendersConstraints", kind, fallbackError));
15233
15248
  }
15234
15249
  }
@@ -15256,7 +15271,7 @@ var TransceiverController = class extends Destroyable {
15256
15271
  if (!newTrack) throw new MediaTrackError("replaceTrackFallback", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
15257
15272
  await sender.replaceTrack(newTrack);
15258
15273
  this.options.localStreamController.addTrack(newTrack);
15259
- logger$15.debug(`[TransceiverController] Track replacement fallback succeeded for ${kind}. New track: ${newTrack.id}`);
15274
+ logger$16.debug(`[TransceiverController] Track replacement fallback succeeded for ${kind}. New track: ${newTrack.id}`);
15260
15275
  }
15261
15276
  getMediaDirections() {
15262
15277
  if (this.peerConnection.connectionState === "connected") return this.peerConnection.getTransceivers().reduce((acc, transceiver) => {
@@ -15286,60 +15301,60 @@ var TransceiverController = class extends Destroyable {
15286
15301
 
15287
15302
  //#endregion
15288
15303
  //#region src/controllers/RTCPeerConnectionController.ts
15289
- var import_cjs$13 = require_cjs();
15290
- const logger$14 = getLogger();
15304
+ var import_cjs$14 = require_cjs();
15305
+ const logger$15 = getLogger();
15291
15306
  var RTCPeerConnectionController = class extends Destroyable {
15292
15307
  constructor(options = {}, remoteSessionDescription, deviceController) {
15293
15308
  super();
15294
15309
  this.options = options;
15295
15310
  this.firstSDPExchangeCompleted = false;
15296
15311
  this.negotiationNeeded$ = this.createSubject();
15297
- this.localDescription$ = (0, import_cjs$13.defer)(() => (0, import_cjs$13.from)(this.init())).pipe((0, import_cjs$13.switchMap)(() => this.iceGatheringController.iceCandidatesState$.pipe((0, import_cjs$13.filter)((iceCandidateState) => !["new", "gathering"].includes(iceCandidateState)), (0, import_cjs$13.tap)(() => {
15312
+ this.localDescription$ = (0, import_cjs$14.defer)(() => (0, import_cjs$14.from)(this.init())).pipe((0, import_cjs$14.switchMap)(() => this.iceGatheringController.iceCandidatesState$.pipe((0, import_cjs$14.filter)((iceCandidateState) => !["new", "gathering"].includes(iceCandidateState)), (0, import_cjs$14.tap)(() => {
15298
15313
  this.negotiationEnded();
15299
- }), (0, import_cjs$13.filter)(() => this.shouldEmitLocalDescription), (0, import_cjs$13.map)(() => this.peerConnection?.localDescription), filterNull(), (0, import_cjs$13.tap)((desc) => {
15314
+ }), (0, import_cjs$14.filter)(() => this.shouldEmitLocalDescription), (0, import_cjs$14.map)(() => this.peerConnection?.localDescription), filterNull(), (0, import_cjs$14.tap)((desc) => {
15300
15315
  if (desc.type === "answer") this._type = "offer";
15301
- }))), (0, import_cjs$13.shareReplay)(1), (0, import_cjs$13.takeUntil)(this.destroyed$));
15316
+ }))), (0, import_cjs$14.shareReplay)(1), (0, import_cjs$14.takeUntil)(this.destroyed$));
15302
15317
  this.connectionTimeout = 3e3;
15303
15318
  this.oniceconnectionstatechangeHandler = () => {
15304
15319
  if (this.peerConnection) {
15305
15320
  const { iceConnectionState } = this.peerConnection;
15306
- logger$14.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
15321
+ logger$15.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
15307
15322
  this._iceConnectionState$.next(this.peerConnection.iceConnectionState);
15308
15323
  }
15309
15324
  };
15310
15325
  this.onconnectionstatechangeHandler = () => {
15311
15326
  if (this.peerConnection) {
15312
15327
  const { connectionState } = this.peerConnection;
15313
- logger$14.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
15328
+ logger$15.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
15314
15329
  if (connectionState === "connected") this.removeConnectionTimer();
15315
15330
  this._connectionState$.next(this.peerConnection.connectionState);
15316
15331
  }
15317
15332
  };
15318
15333
  this.onsignalingstatechangeHandler = () => {
15319
- logger$14.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
15334
+ logger$15.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
15320
15335
  };
15321
15336
  this.onicegatheringstatechangeHandler = () => {
15322
15337
  if (this.peerConnection) this._iceGatheringState$.next(this.peerConnection.iceGatheringState);
15323
15338
  };
15324
15339
  this.onnegotiationneededHandler = (event) => {
15325
- logger$14.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
15340
+ logger$15.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
15326
15341
  this.negotiationNeeded$.next();
15327
15342
  };
15328
15343
  this.updateSelectedInputDevice = async (kind, deviceInfo) => {
15329
15344
  try {
15330
15345
  const { localStream } = this;
15331
15346
  if (!localStream) {
15332
- logger$14.warn("[RTCPeerConnectionController] No local stream available to update input device.");
15347
+ logger$15.warn("[RTCPeerConnectionController] No local stream available to update input device.");
15333
15348
  return;
15334
15349
  }
15335
- logger$14.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
15350
+ logger$15.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
15336
15351
  const track = localStream.getTracks().find((track$1) => track$1.kind === kind);
15337
15352
  if (track) {
15338
15353
  this.transceiverController?.stopTrackSender(kind);
15339
15354
  this.localStream?.removeTrack(track);
15340
- logger$14.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
15355
+ logger$15.debug(`[RTCPeerConnectionController] Stopped existing ${kind} track: ${track.id}`, localStream.getTracks());
15341
15356
  if (!deviceInfo) {
15342
- logger$14.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
15357
+ logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
15343
15358
  return;
15344
15359
  }
15345
15360
  const streamTrack = (await this.getUserMedia({ [kind]: {
@@ -15347,15 +15362,15 @@ var RTCPeerConnectionController = class extends Destroyable {
15347
15362
  ...this.deviceController.deviceInfoToConstraints(deviceInfo)
15348
15363
  } })).getTracks().find((t) => t.kind === kind);
15349
15364
  if (streamTrack) {
15350
- logger$14.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
15365
+ logger$15.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
15351
15366
  this.localStream?.addTrack(streamTrack);
15352
15367
  await this.transceiverController?.replaceSenderTrack(kind, streamTrack);
15353
- logger$14.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
15368
+ logger$15.debug(`[RTCPeerConnectionController] Added new ${kind} track: ${streamTrack.id}`, this.localStream?.getTracks());
15354
15369
  }
15355
15370
  }
15356
- logger$14.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
15371
+ logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
15357
15372
  } catch (error) {
15358
- logger$14.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
15373
+ logger$15.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
15359
15374
  this._errors$.next(error);
15360
15375
  throw error;
15361
15376
  }
@@ -15441,43 +15456,43 @@ var RTCPeerConnectionController = class extends Destroyable {
15441
15456
  };
15442
15457
  }
15443
15458
  get iceGatheringState$() {
15444
- return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15459
+ return this.cachedObservable("iceGatheringState$", () => this._iceGatheringState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15445
15460
  }
15446
15461
  get mediaTrackEnded$() {
15447
- return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15462
+ return this.cachedObservable("mediaTrackEnded$", () => this.localStreamController.mediaTrackEnded$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15448
15463
  }
15449
15464
  get errors$() {
15450
- return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15465
+ return this.cachedObservable("errors$", () => this._errors$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15451
15466
  }
15452
15467
  get iceCandidates$() {
15453
- return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15468
+ return this.cachedObservable("iceCandidates$", () => this._iceCandidates$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15454
15469
  }
15455
15470
  get initialized$() {
15456
- return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, import_cjs$13.filter)((initialized) => initialized), (0, import_cjs$13.takeUntil)(this.destroyed$)));
15471
+ return this.cachedObservable("initialized$", () => this._initialized$.asObservable().pipe((0, import_cjs$14.filter)((initialized) => initialized), (0, import_cjs$14.takeUntil)(this.destroyed$)));
15457
15472
  }
15458
15473
  get remoteDescription$() {
15459
- return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15474
+ return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15460
15475
  }
15461
15476
  get localStream$() {
15462
- return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15477
+ return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15463
15478
  }
15464
15479
  get remoteStream$() {
15465
- return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15480
+ return this.cachedObservable("remoteStream$", () => this._remoteStream$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15466
15481
  }
15467
15482
  get localAudioTracks$() {
15468
- return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15483
+ return this.cachedObservable("localAudioTracks$", () => this.localStreamController.localAudioTracks$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15469
15484
  }
15470
15485
  get localVideoTracks$() {
15471
- return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15486
+ return this.cachedObservable("localVideoTracks$", () => this.localStreamController.localVideoTracks$.pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15472
15487
  }
15473
15488
  get iceConnectionState$() {
15474
- return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15489
+ return this.cachedObservable("iceConnectionState$", () => this._iceConnectionState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15475
15490
  }
15476
15491
  get connectionState$() {
15477
- return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15492
+ return this.cachedObservable("connectionState$", () => this._connectionState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15478
15493
  }
15479
15494
  get signalingState$() {
15480
- return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, import_cjs$13.takeUntil)(this.destroyed$)));
15495
+ return this.cachedObservable("signalingState$", () => this._signalingState$.asObservable().pipe((0, import_cjs$14.takeUntil)(this.destroyed$)));
15481
15496
  }
15482
15497
  get type() {
15483
15498
  return this._type;
@@ -15590,17 +15605,17 @@ var RTCPeerConnectionController = class extends Destroyable {
15590
15605
  async doInit() {
15591
15606
  try {
15592
15607
  this.setupPeerConnection();
15593
- this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$13.auditTime)(0), (0, import_cjs$13.exhaustMap)(async () => this.startNegotiation())), {
15608
+ this.subscribeTo(this.negotiationNeeded$.pipe((0, import_cjs$14.auditTime)(0), (0, import_cjs$14.exhaustMap)(async () => this.startNegotiation())), {
15594
15609
  next: () => {
15595
- logger$14.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
15610
+ logger$15.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
15596
15611
  },
15597
15612
  error: (error) => {
15598
- logger$14.error("[RTCPeerConnectionController] Start Negotiation error:", error);
15613
+ logger$15.error("[RTCPeerConnectionController] Start Negotiation error:", error);
15599
15614
  this._errors$.next(error);
15600
15615
  }
15601
15616
  });
15602
- this.subscribeTo((0, import_cjs$13.merge)(this.deviceController.selectedAudioInputDevice$.pipe((0, import_cjs$13.map)((deviceInfo) => ["audio", deviceInfo])), this.deviceController.selectedVideoInputDevice$.pipe((0, import_cjs$13.map)((deviceInfo) => ["video", deviceInfo]))).pipe((0, import_cjs$13.skipWhile)(() => !this.localStreamController.localStream)), async ([kind, deviceInfo]) => {
15603
- logger$14.debug(`[RTCPeerConnectionController] Selected input device changed for:`, {
15617
+ this.subscribeTo((0, import_cjs$14.merge)(this.deviceController.selectedAudioInputDevice$.pipe((0, import_cjs$14.map)((deviceInfo) => ["audio", deviceInfo])), this.deviceController.selectedVideoInputDevice$.pipe((0, import_cjs$14.map)((deviceInfo) => ["video", deviceInfo]))).pipe((0, import_cjs$14.skipWhile)(() => !this.localStreamController.localStream)), async ([kind, deviceInfo]) => {
15618
+ logger$15.debug(`[RTCPeerConnectionController] Selected input device changed for:`, {
15604
15619
  kind,
15605
15620
  deviceInfo
15606
15621
  });
@@ -15617,7 +15632,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15617
15632
  this._initialized$.next(true);
15618
15633
  }
15619
15634
  } catch (error) {
15620
- logger$14.error("[RTCPeerConnectionController] Initialization error:", error);
15635
+ logger$15.error("[RTCPeerConnectionController] Initialization error:", error);
15621
15636
  this._errors$.next(error);
15622
15637
  this.destroy();
15623
15638
  }
@@ -15649,22 +15664,22 @@ var RTCPeerConnectionController = class extends Destroyable {
15649
15664
  }
15650
15665
  async startNegotiation() {
15651
15666
  if (this.isNegotiating) {
15652
- logger$14.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
15667
+ logger$15.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
15653
15668
  return;
15654
15669
  }
15655
15670
  this.setupEventListeners();
15656
15671
  if (this.type === "answer") {
15657
- logger$14.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");
15672
+ logger$15.debug("[RTCPeerConnectionController] This is an answer type still, skipping offer creation.");
15658
15673
  return;
15659
15674
  }
15660
15675
  this._isNegotiating$.next(true);
15661
- logger$14.debug("[RTCPeerConnectionController] Starting negotiation.");
15676
+ logger$15.debug("[RTCPeerConnectionController] Starting negotiation.");
15662
15677
  try {
15663
15678
  const { offerOptions } = this;
15664
- logger$14.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
15679
+ logger$15.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
15665
15680
  await this.createOffer(offerOptions);
15666
15681
  } catch (error) {
15667
- logger$14.error("[RTCPeerConnectionController] Error during negotiation:", error);
15682
+ logger$15.error("[RTCPeerConnectionController] Error during negotiation:", error);
15668
15683
  this._errors$.next(error);
15669
15684
  }
15670
15685
  }
@@ -15680,14 +15695,14 @@ var RTCPeerConnectionController = class extends Destroyable {
15680
15695
  let readyToConnect = status !== "failed";
15681
15696
  try {
15682
15697
  if (status === "received" && sdp) {
15683
- logger$14.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
15698
+ logger$15.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
15684
15699
  await this._setRemoteDescription({
15685
15700
  type: "answer",
15686
15701
  sdp
15687
15702
  });
15688
15703
  }
15689
15704
  } catch (error) {
15690
- logger$14.error("[RTCPeerConnectionController] Error updating answer status:", error);
15705
+ logger$15.error("[RTCPeerConnectionController] Error updating answer status:", error);
15691
15706
  this._errors$.next(error);
15692
15707
  readyToConnect = false;
15693
15708
  } finally {
@@ -15706,7 +15721,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15706
15721
  await this.handleOfferReceived();
15707
15722
  break;
15708
15723
  case "failed":
15709
- logger$14.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
15724
+ logger$15.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
15710
15725
  break;
15711
15726
  case "sent":
15712
15727
  default:
@@ -15738,7 +15753,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15738
15753
  }
15739
15754
  await this.setupLocalTracks();
15740
15755
  const { answerOptions } = this;
15741
- logger$14.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
15756
+ logger$15.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
15742
15757
  await this.createAnswer(answerOptions);
15743
15758
  }
15744
15759
  async handleOfferReceived() {
@@ -15746,7 +15761,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15746
15761
  this._isNegotiating$.next(true);
15747
15762
  await this._setRemoteDescription(this.sdpInit);
15748
15763
  const { answerOptions } = this;
15749
- logger$14.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
15764
+ logger$15.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
15750
15765
  await this.createAnswer(answerOptions);
15751
15766
  }
15752
15767
  readyToConnect() {
@@ -15754,7 +15769,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15754
15769
  this.connectionTimer = setTimeout(() => {
15755
15770
  this.removeConnectionTimer();
15756
15771
  if (this.peerConnection?.connectionState !== "connected") {
15757
- logger$14.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only.");
15772
+ logger$15.debug("[RTCPeerConnectionController] Connection timeout, restarting ICE gathering with relay only.");
15758
15773
  this.iceGatheringController.restartICEGatheringWithRelayOnly();
15759
15774
  }
15760
15775
  }, this.connectionTimeout);
@@ -15776,14 +15791,14 @@ var RTCPeerConnectionController = class extends Destroyable {
15776
15791
  const stereo = this.options.stereo ?? PreferencesContainer.instance.stereoAudio;
15777
15792
  if (preferredAudioCodecs.length > 0 || preferredVideoCodecs.length > 0) {
15778
15793
  result = setCodecPreferences(result, preferredAudioCodecs, preferredVideoCodecs);
15779
- logger$14.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
15794
+ logger$15.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
15780
15795
  preferredAudioCodecs,
15781
15796
  preferredVideoCodecs
15782
15797
  });
15783
15798
  }
15784
15799
  if (stereo) {
15785
15800
  result = enableStereoOpus(result);
15786
- logger$14.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP");
15801
+ logger$15.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP");
15787
15802
  }
15788
15803
  return Promise.resolve(result);
15789
15804
  }
@@ -15842,18 +15857,18 @@ var RTCPeerConnectionController = class extends Destroyable {
15842
15857
  ...this.peerConnection.getConfiguration(),
15843
15858
  iceTransportPolicy: "relay"
15844
15859
  });
15845
- logger$14.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only");
15860
+ logger$15.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only");
15846
15861
  } catch (error) {
15847
- logger$14.warn("[RTCPeerConnectionController] Failed to set relay-only policy:", error);
15862
+ logger$15.warn("[RTCPeerConnectionController] Failed to set relay-only policy:", error);
15848
15863
  }
15849
15864
  this.setupEventListeners();
15850
15865
  this._isNegotiating$.next(true);
15851
- logger$14.debug(`[RTCPeerConnectionController] Triggering ICE restart${relayOnly ? " (relay-only)" : ""}.`);
15866
+ logger$15.debug(`[RTCPeerConnectionController] Triggering ICE restart${relayOnly ? " (relay-only)" : ""}.`);
15852
15867
  try {
15853
15868
  const offer = await this.peerConnection.createOffer({ iceRestart: true });
15854
15869
  await this.setLocalDescription(offer);
15855
15870
  } catch (error) {
15856
- logger$14.error("[RTCPeerConnectionController] ICE restart offer failed:", error);
15871
+ logger$15.error("[RTCPeerConnectionController] ICE restart offer failed:", error);
15857
15872
  this._errors$.next(error);
15858
15873
  this.negotiationEnded();
15859
15874
  if (policyChanged) this.restoreIceTransportPolicy();
@@ -15867,9 +15882,9 @@ var RTCPeerConnectionController = class extends Destroyable {
15867
15882
  ...this.peerConnection.getConfiguration(),
15868
15883
  iceTransportPolicy: this.options.relayOnly ? "relay" : "all"
15869
15884
  });
15870
- logger$14.debug("[RTCPeerConnectionController] ICE transport policy restored");
15885
+ logger$15.debug("[RTCPeerConnectionController] ICE transport policy restored");
15871
15886
  } catch (error) {
15872
- logger$14.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:", error);
15887
+ logger$15.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:", error);
15873
15888
  }
15874
15889
  }
15875
15890
  /**
@@ -15881,13 +15896,13 @@ var RTCPeerConnectionController = class extends Destroyable {
15881
15896
  await this.setupRemoteTracks();
15882
15897
  }
15883
15898
  async setupLocalTracks() {
15884
- logger$14.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
15899
+ logger$15.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
15885
15900
  const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
15886
15901
  if (this.transceiverController?.useAddStream ?? false) {
15887
- logger$14.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
15902
+ logger$15.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
15888
15903
  this.peerConnection?.addStream(localStream);
15889
15904
  if (!this.isNegotiating) {
15890
- logger$14.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
15905
+ logger$15.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
15891
15906
  this.negotiationNeeded$.next();
15892
15907
  }
15893
15908
  return;
@@ -15903,7 +15918,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15903
15918
  const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
15904
15919
  await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
15905
15920
  } else {
15906
- logger$14.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
15921
+ logger$15.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
15907
15922
  this.peerConnection?.addTrack(track, localStream);
15908
15923
  }
15909
15924
  }
@@ -15920,7 +15935,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15920
15935
  async setupRemoteTracks() {
15921
15936
  if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
15922
15937
  this.peerConnection.ontrack = (event) => {
15923
- logger$14.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
15938
+ logger$15.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
15924
15939
  if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
15925
15940
  else {
15926
15941
  const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
@@ -15946,9 +15961,9 @@ var RTCPeerConnectionController = class extends Destroyable {
15946
15961
  try {
15947
15962
  const localStream = this.localStreamController.addTrack(track);
15948
15963
  this.peerConnection.addTrack(track, localStream);
15949
- logger$14.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
15964
+ logger$15.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
15950
15965
  } catch (error) {
15951
- logger$14.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
15966
+ logger$15.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
15952
15967
  this._errors$.next(error);
15953
15968
  throw error;
15954
15969
  }
@@ -15965,15 +15980,15 @@ var RTCPeerConnectionController = class extends Destroyable {
15965
15980
  }
15966
15981
  const sender = this.peerConnection.getSenders().find((sender$1) => sender$1.track?.id === trackId);
15967
15982
  if (!sender) {
15968
- logger$14.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
15983
+ logger$15.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
15969
15984
  return;
15970
15985
  }
15971
15986
  try {
15972
15987
  this.peerConnection.removeTrack(sender);
15973
15988
  this.localStreamController.removeTrack(trackId);
15974
- logger$14.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
15989
+ logger$15.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
15975
15990
  } catch (error) {
15976
- logger$14.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
15991
+ logger$15.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
15977
15992
  this._errors$.next(error);
15978
15993
  throw error;
15979
15994
  }
@@ -16000,7 +16015,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16000
16015
  async replaceAudioTrackWithConstraints(constraints) {
16001
16016
  const senders = this.peerConnection?.getSenders().filter((s) => s.track?.kind === "audio" && s.track.readyState === "live");
16002
16017
  if (!senders || senders.length === 0) {
16003
- logger$14.warn("[RTCPeerConnectionController] No live audio sender to replace");
16018
+ logger$15.warn("[RTCPeerConnectionController] No live audio sender to replace");
16004
16019
  return;
16005
16020
  }
16006
16021
  for (const sender of senders) {
@@ -16018,7 +16033,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16018
16033
  const newTrack = (await this.getUserMedia({ audio: mergedConstraints })).getAudioTracks()[0];
16019
16034
  await sender.replaceTrack(newTrack);
16020
16035
  this.localStreamController.addTrack(newTrack);
16021
- logger$14.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
16036
+ logger$15.debug(`[RTCPeerConnectionController] Audio track replaced for server-pushed params. New track: ${newTrack.id}`);
16022
16037
  }
16023
16038
  }
16024
16039
  /**
@@ -16026,7 +16041,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16026
16041
  * Completes all observables to prevent memory leaks.
16027
16042
  */
16028
16043
  destroy() {
16029
- logger$14.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
16044
+ logger$15.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
16030
16045
  this.removeConnectionTimer();
16031
16046
  this._iceGatheringController?.destroy();
16032
16047
  this.localStreamController.destroy();
@@ -16050,7 +16065,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16050
16065
  }
16051
16066
  stopRemoteTracks() {
16052
16067
  this._remoteStream$.value?.getTracks().forEach((track) => {
16053
- logger$14.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
16068
+ logger$15.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
16054
16069
  track.stop();
16055
16070
  });
16056
16071
  }
@@ -16067,7 +16082,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16067
16082
  ...params,
16068
16083
  sdp: finalRemote
16069
16084
  };
16070
- logger$14.debug("[RTCPeerConnectionController] Setting remote description:", answer);
16085
+ logger$15.debug("[RTCPeerConnectionController] Setting remote description:", answer);
16071
16086
  return this.peerConnection.setRemoteDescription(answer);
16072
16087
  }
16073
16088
  };
@@ -16105,8 +16120,8 @@ function isVertoPingInnerParams(value) {
16105
16120
 
16106
16121
  //#endregion
16107
16122
  //#region src/managers/VertoManager.ts
16108
- var import_cjs$12 = require_cjs();
16109
- const logger$13 = getLogger();
16123
+ var import_cjs$13 = require_cjs();
16124
+ const logger$14 = getLogger();
16110
16125
  var VertoManager = class extends Destroyable {
16111
16126
  constructor(callSession) {
16112
16127
  super();
@@ -16132,6 +16147,7 @@ var WebRTCVertoManager = class extends VertoManager {
16132
16147
  this._screenShareTimeoutMs = 5e4;
16133
16148
  this._nodeId$ = this.createBehaviorSubject(options.nodeId ?? null);
16134
16149
  this.onError = options.onError;
16150
+ this.onModifyFailed = options.onModifyFailed;
16135
16151
  this.initSubscriptions();
16136
16152
  this.initMainPeerConnection();
16137
16153
  }
@@ -16144,7 +16160,7 @@ var WebRTCVertoManager = class extends VertoManager {
16144
16160
  try {
16145
16161
  await this.executeVerto(vertoModifyMessage);
16146
16162
  } catch (error) {
16147
- logger$13.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:", error);
16163
+ logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto hold:", error);
16148
16164
  throw error;
16149
16165
  }
16150
16166
  }
@@ -16157,7 +16173,7 @@ var WebRTCVertoManager = class extends VertoManager {
16157
16173
  try {
16158
16174
  await this.executeVerto(vertoModifyMessage);
16159
16175
  } catch (error) {
16160
- logger$13.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:", error);
16176
+ logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto unhold:", error);
16161
16177
  throw error;
16162
16178
  }
16163
16179
  }
@@ -16197,7 +16213,7 @@ var WebRTCVertoManager = class extends VertoManager {
16197
16213
  return rtcPeerConnection;
16198
16214
  }
16199
16215
  get signalingStatus$() {
16200
- return this.cachedObservable("signalingStatus$", () => (0, import_cjs$12.merge)(this._signalingStatus$.pipe(filterNull()), this.mainPeerConnection.connectionState$.pipe((0, import_cjs$12.filter)((connectionState) => [
16216
+ return this.cachedObservable("signalingStatus$", () => (0, import_cjs$13.merge)(this._signalingStatus$.pipe(filterNull()), this.mainPeerConnection.connectionState$.pipe((0, import_cjs$13.filter)((connectionState) => [
16201
16217
  "connected",
16202
16218
  "disconnected",
16203
16219
  "failed"
@@ -16210,7 +16226,7 @@ var WebRTCVertoManager = class extends VertoManager {
16210
16226
  if (event.member_id) this.setSelfIdIfNull(event.member_id);
16211
16227
  });
16212
16228
  this.subscribeTo(this.vertoMedia$, (event) => {
16213
- logger$13.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
16229
+ logger$14.debug("[WebRTCManager] Received Verto media event (early media SDP):", event);
16214
16230
  this._signalingStatus$.next("ringing");
16215
16231
  const { sdp, callID } = event;
16216
16232
  this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
@@ -16219,7 +16235,7 @@ var WebRTCVertoManager = class extends VertoManager {
16219
16235
  });
16220
16236
  });
16221
16237
  this.subscribeTo(this.vertoAnswer$, (event) => {
16222
- logger$13.debug("[WebRTCManager] Received Verto answer event:", event);
16238
+ logger$14.debug("[WebRTCManager] Received Verto answer event:", event);
16223
16239
  this._signalingStatus$.next("connecting");
16224
16240
  const { sdp, callID } = event;
16225
16241
  this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
@@ -16228,7 +16244,7 @@ var WebRTCVertoManager = class extends VertoManager {
16228
16244
  });
16229
16245
  });
16230
16246
  this.subscribeTo(this.vertoMediaParams$, (event) => {
16231
- logger$13.debug("[WebRTCManager] Received Verto mediaParams event:", event);
16247
+ logger$14.debug("[WebRTCManager] Received Verto mediaParams event:", event);
16232
16248
  const { mediaParams, callID } = event;
16233
16249
  const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callID);
16234
16250
  const { audio, video } = mediaParams;
@@ -16242,13 +16258,13 @@ var WebRTCVertoManager = class extends VertoManager {
16242
16258
  timestamp: Date.now()
16243
16259
  });
16244
16260
  } catch (error) {
16245
- logger$13.warn("[WebRTCManager] Error applying server-pushed media params:", error);
16261
+ logger$14.warn("[WebRTCManager] Error applying server-pushed media params:", error);
16246
16262
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16247
16263
  }
16248
16264
  })();
16249
16265
  });
16250
16266
  this.subscribeTo(this.vertoPing$, (vertoPing) => {
16251
- this.attachManager.attach(this.webRtcCallSession);
16267
+ this.attachManager.attach(this.buildAttachableCall());
16252
16268
  this.sendVertoPong(vertoPing);
16253
16269
  });
16254
16270
  }
@@ -16264,13 +16280,13 @@ var WebRTCVertoManager = class extends VertoManager {
16264
16280
  */
16265
16281
  setNodeIdIfNull(nodeId) {
16266
16282
  if (!this._nodeId$.value && nodeId) {
16267
- logger$13.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
16283
+ logger$14.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
16268
16284
  this._nodeId$.next(nodeId);
16269
16285
  }
16270
16286
  }
16271
16287
  setSelfIdIfNull(selfId) {
16272
16288
  if (!this._selfId$.value && selfId) {
16273
- logger$13.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
16289
+ logger$14.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
16274
16290
  this._selfId$.next(selfId);
16275
16291
  }
16276
16292
  }
@@ -16279,7 +16295,7 @@ var WebRTCVertoManager = class extends VertoManager {
16279
16295
  const vertoPongMessage = VertoPong({ ...vertoPing });
16280
16296
  await this.executeVerto(vertoPongMessage);
16281
16297
  } catch (error) {
16282
- logger$13.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:", error);
16298
+ logger$14.warn("[WebRTCManager] Call might disconnect, error sending Verto pong:", error);
16283
16299
  this.onError?.(new VertoPongError(error));
16284
16300
  }
16285
16301
  }
@@ -16289,7 +16305,7 @@ var WebRTCVertoManager = class extends VertoManager {
16289
16305
  if (audio) await this.mainPeerConnection.updateSendersConstraints("audio", audio);
16290
16306
  if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
16291
16307
  } catch (error) {
16292
- logger$13.warn("[WebRTCManager] Error updating media constraints:", error);
16308
+ logger$14.warn("[WebRTCManager] Error updating media constraints:", error);
16293
16309
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16294
16310
  throw error;
16295
16311
  }
@@ -16297,6 +16313,15 @@ var WebRTCVertoManager = class extends VertoManager {
16297
16313
  get selfId() {
16298
16314
  return this._selfId$.value;
16299
16315
  }
16316
+ /** Build an AttachableCall from the current call state. */
16317
+ buildAttachableCall(idOverride) {
16318
+ return {
16319
+ nodeId: this.nodeId ?? void 0,
16320
+ id: idOverride ?? this.webRtcCallSession.id,
16321
+ to: this.webRtcCallSession.to,
16322
+ mediaDirections: this.webRtcCallSession.mediaDirections
16323
+ };
16324
+ }
16300
16325
  /**
16301
16326
  * Request a video keyframe via RTCP PLI/FIR.
16302
16327
  *
@@ -16310,20 +16335,20 @@ var WebRTCVertoManager = class extends VertoManager {
16310
16335
  try {
16311
16336
  const pc = this.mainPeerConnection.peerConnection;
16312
16337
  if (!pc) {
16313
- logger$13.warn("[WebRTCManager] No peer connection for keyframe request");
16338
+ logger$14.warn("[WebRTCManager] No peer connection for keyframe request");
16314
16339
  return;
16315
16340
  }
16316
16341
  const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
16317
16342
  if (!videoReceiver) {
16318
- logger$13.warn("[WebRTCManager] No video receiver for keyframe request");
16343
+ logger$14.warn("[WebRTCManager] No video receiver for keyframe request");
16319
16344
  return;
16320
16345
  }
16321
16346
  if (typeof videoReceiver.requestKeyFrame === "function") {
16322
16347
  videoReceiver.requestKeyFrame();
16323
- logger$13.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()");
16324
- } else logger$13.debug("[WebRTCManager] requestKeyFrame() not supported, skipping");
16348
+ logger$14.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()");
16349
+ } else logger$14.debug("[WebRTCManager] requestKeyFrame() not supported, skipping");
16325
16350
  } catch (error) {
16326
- logger$13.warn("[WebRTCManager] Keyframe request failed (non-fatal):", error);
16351
+ logger$14.warn("[WebRTCManager] Keyframe request failed (non-fatal):", error);
16327
16352
  }
16328
16353
  }
16329
16354
  /**
@@ -16341,13 +16366,13 @@ var WebRTCVertoManager = class extends VertoManager {
16341
16366
  try {
16342
16367
  const controller = this.mainPeerConnection;
16343
16368
  if (!controller.peerConnection) {
16344
- logger$13.warn("[WebRTCManager] No peer connection for ICE restart");
16369
+ logger$14.warn("[WebRTCManager] No peer connection for ICE restart");
16345
16370
  return;
16346
16371
  }
16347
16372
  await controller.triggerIceRestart(relayOnly);
16348
- logger$13.info(`[WebRTCManager] ICE restart initiated${relayOnly ? " (relay-only)" : ""}`);
16373
+ logger$14.info(`[WebRTCManager] ICE restart initiated${relayOnly ? " (relay-only)" : ""}`);
16349
16374
  } catch (error) {
16350
- logger$13.error("[WebRTCManager] ICE restart failed:", error);
16375
+ logger$14.error("[WebRTCManager] ICE restart failed:", error);
16351
16376
  throw error;
16352
16377
  }
16353
16378
  }
@@ -16365,13 +16390,13 @@ var WebRTCVertoManager = class extends VertoManager {
16365
16390
  const entries = Array.from(this._rtcPeerConnectionsMap.entries());
16366
16391
  for (const [id, controller] of entries) try {
16367
16392
  if (!controller.peerConnection) {
16368
- logger$13.debug(`[WebRTCManager] No peer connection for leg ${id}, skipping ICE restart`);
16393
+ logger$14.debug(`[WebRTCManager] No peer connection for leg ${id}, skipping ICE restart`);
16369
16394
  continue;
16370
16395
  }
16371
16396
  await controller.triggerIceRestart(relayOnly);
16372
- logger$13.info(`[WebRTCManager] ICE restart initiated for leg ${id}${relayOnly ? " (relay-only)" : ""}`);
16397
+ logger$14.info(`[WebRTCManager] ICE restart initiated for leg ${id}${relayOnly ? " (relay-only)" : ""}`);
16373
16398
  } catch (error) {
16374
- logger$13.warn(`[WebRTCManager] ICE restart failed for leg ${id}:`, error);
16399
+ logger$14.warn(`[WebRTCManager] ICE restart failed for leg ${id}:`, error);
16375
16400
  }
16376
16401
  }
16377
16402
  /**
@@ -16383,7 +16408,7 @@ var WebRTCVertoManager = class extends VertoManager {
16383
16408
  requestKeyframeAll() {
16384
16409
  for (const [id, controller] of this._rtcPeerConnectionsMap) {
16385
16410
  if (controller.isScreenShare) {
16386
- logger$13.debug(`[WebRTCManager] Skipping keyframe for send-only screen share leg ${id}`);
16411
+ logger$14.debug(`[WebRTCManager] Skipping keyframe for send-only screen share leg ${id}`);
16387
16412
  continue;
16388
16413
  }
16389
16414
  try {
@@ -16393,33 +16418,33 @@ var WebRTCVertoManager = class extends VertoManager {
16393
16418
  if (!videoReceiver) continue;
16394
16419
  if (typeof videoReceiver.requestKeyFrame === "function") {
16395
16420
  videoReceiver.requestKeyFrame();
16396
- logger$13.debug(`[WebRTCManager] Keyframe requested for leg ${id}`);
16421
+ logger$14.debug(`[WebRTCManager] Keyframe requested for leg ${id}`);
16397
16422
  }
16398
16423
  } catch (error) {
16399
- logger$13.warn(`[WebRTCManager] Keyframe request failed for leg ${id} (non-fatal):`, error);
16424
+ logger$14.warn(`[WebRTCManager] Keyframe request failed for leg ${id} (non-fatal):`, error);
16400
16425
  }
16401
16426
  }
16402
16427
  }
16403
16428
  get callJoinedEvent$() {
16404
- return this.webRtcCallSession.callEvent$.pipe((0, import_cjs$12.filter)(isCallJoinedPayload), (0, import_cjs$12.takeUntil)(this.destroyed$));
16429
+ return this.webRtcCallSession.callEvent$.pipe((0, import_cjs$13.filter)(isCallJoinedPayload), (0, import_cjs$13.takeUntil)(this.destroyed$));
16405
16430
  }
16406
16431
  get vertoMedia$() {
16407
- return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$12.takeUntil)(this.destroyed$));
16432
+ return this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$));
16408
16433
  }
16409
16434
  get vertoAnswer$() {
16410
- return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$12.takeUntil)(this.destroyed$)));
16435
+ return this.cachedObservable("vertoAnswer$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAnswerInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
16411
16436
  }
16412
16437
  get vertoMediaParams$() {
16413
- return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$12.takeUntil)(this.destroyed$)));
16438
+ return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
16414
16439
  }
16415
16440
  get vertoBye$() {
16416
- return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeMessage, "params"), (0, import_cjs$12.takeUntil)(this.destroyed$)));
16441
+ return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeMessage, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
16417
16442
  }
16418
16443
  get vertoAttach$() {
16419
- return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$12.takeUntil)(this.destroyed$)));
16444
+ return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
16420
16445
  }
16421
16446
  get vertoPing$() {
16422
- return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoPingInnerParams, "params"), (0, import_cjs$12.takeUntil)(this.destroyed$)));
16447
+ return this.cachedObservable("vertoPing$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoPingInnerParams, "params"), (0, import_cjs$13.takeUntil)(this.destroyed$)));
16423
16448
  }
16424
16449
  async executeVerto(message, optionals = {}) {
16425
16450
  const webrtcVertoMessage = WebrtcVerto({
@@ -16444,7 +16469,7 @@ var WebRTCVertoManager = class extends VertoManager {
16444
16469
  }
16445
16470
  async sendLocalDescription(message, rtcPeerConnController) {
16446
16471
  const vertoMethod = message.method;
16447
- const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMethod);
16472
+ const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, message);
16448
16473
  try {
16449
16474
  const response = await this.executeVerto(message, optionalsParams);
16450
16475
  switch (vertoMethod) {
@@ -16457,8 +16482,9 @@ var WebRTCVertoManager = class extends VertoManager {
16457
16482
  default:
16458
16483
  }
16459
16484
  } catch (error) {
16460
- logger$13.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
16485
+ logger$14.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
16461
16486
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16487
+ if (vertoMethod === "verto.modify") this.onModifyFailed?.();
16462
16488
  }
16463
16489
  }
16464
16490
  async processModifyResponse(response, rtcPeerConnController) {
@@ -16471,7 +16497,7 @@ var WebRTCVertoManager = class extends VertoManager {
16471
16497
  sdp
16472
16498
  });
16473
16499
  } catch (error) {
16474
- logger$13.warn("[WebRTCManager] Error processing modify response:", error);
16500
+ logger$14.warn("[WebRTCManager] Error processing modify response:", error);
16475
16501
  const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
16476
16502
  this.onError?.(modifyError);
16477
16503
  }
@@ -16483,19 +16509,24 @@ var WebRTCVertoManager = class extends VertoManager {
16483
16509
  this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
16484
16510
  const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
16485
16511
  const callId = getValueFrom(response, "result.result.result.callID") ?? null;
16486
- logger$13.debug("[WebRTCManager] Verto invite response:", {
16512
+ logger$14.debug("[WebRTCManager] Verto invite response:", {
16487
16513
  callId,
16488
16514
  memberId,
16489
16515
  response
16490
16516
  });
16491
16517
  this._selfId$.next(memberId);
16492
16518
  rtcPeerConnController.setMemberId(memberId);
16493
- if (callId) this.webRtcCallSession.addCallId(callId);
16494
- this.attachManager.attach(this.webRtcCallSession);
16495
- logger$13.info("[WebRTCManager] Verto invite successful");
16496
- logger$13.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
16519
+ if (callId) {
16520
+ this.webRtcCallSession.addCallId(callId);
16521
+ this.attachManager.attach(this.buildAttachableCall(callId));
16522
+ } else logger$14.warn("[WebRTCManager] Cannot attach call, missing callId:", {
16523
+ nodeId: this.nodeId,
16524
+ callId
16525
+ });
16526
+ logger$14.info("[WebRTCManager] Verto invite successful");
16527
+ logger$14.debug(`[WebRTCManager] nodeid: ${this._nodeId$.value}, selfId: ${this._selfId$.value}`);
16497
16528
  } else {
16498
- logger$13.error("[WebRTCManager] Verto invite failed:", response);
16529
+ logger$14.error("[WebRTCManager] Verto invite failed:", response);
16499
16530
  const inviteError = response.error ? new JSONRPCError(response.error.code, response.error.message, response.error.data) : /* @__PURE__ */ new Error("Verto invite failed: unexpected response");
16500
16531
  this.onError?.(inviteError);
16501
16532
  }
@@ -16540,17 +16571,17 @@ var WebRTCVertoManager = class extends VertoManager {
16540
16571
  if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
16541
16572
  }
16542
16573
  async handleInboundAnswer(rtcPeerConnController) {
16543
- logger$13.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
16544
- const vertoByeOrAccepted = await (0, import_cjs$12.firstValueFrom)((0, import_cjs$12.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, import_cjs$12.takeUntil)(this.destroyed$))).catch(() => null);
16574
+ logger$14.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
16575
+ const vertoByeOrAccepted = await (0, import_cjs$13.firstValueFrom)((0, import_cjs$13.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, import_cjs$13.takeUntil)(this.destroyed$))).catch(() => null);
16545
16576
  if (vertoByeOrAccepted === null) {
16546
- logger$13.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
16577
+ logger$14.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
16547
16578
  return;
16548
16579
  }
16549
16580
  if (isVertoByeMessage(vertoByeOrAccepted)) {
16550
- logger$13.info("[WebRTCManager] Inbound call ended by remote before answer.");
16581
+ logger$14.info("[WebRTCManager] Inbound call ended by remote before answer.");
16551
16582
  this.callSession?.destroy();
16552
16583
  } else if (!vertoByeOrAccepted) {
16553
- logger$13.info("[WebRTCManager] Inbound call rejected by user.");
16584
+ logger$14.info("[WebRTCManager] Inbound call rejected by user.");
16554
16585
  try {
16555
16586
  await this.bye("USER_BUSY");
16556
16587
  } finally {
@@ -16558,21 +16589,22 @@ var WebRTCVertoManager = class extends VertoManager {
16558
16589
  this.callSession?.destroy();
16559
16590
  }
16560
16591
  } else {
16561
- logger$13.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
16592
+ logger$14.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
16562
16593
  const answerOptions = this.webRtcCallSession.answerMediaOptions;
16563
16594
  try {
16564
16595
  await rtcPeerConnController.acceptInbound(answerOptions);
16565
16596
  } catch (error) {
16566
- logger$13.error("[WebRTCManager] Error creating inbound answer:", error);
16597
+ logger$14.error("[WebRTCManager] Error creating inbound answer:", error);
16567
16598
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16568
16599
  }
16569
16600
  }
16570
16601
  }
16571
16602
  setupVertoAttachHandler() {
16572
16603
  this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
16573
- logger$13.debug("[WebRTCManager] Received Verto attach event for existing call:", vertoAttach);
16604
+ logger$14.debug("[WebRTCManager] Received Verto attach event for existing call:", vertoAttach);
16574
16605
  const { callID } = vertoAttach;
16575
16606
  await this.attachManager.attach({
16607
+ nodeId: this.nodeId ?? void 0,
16576
16608
  id: callID,
16577
16609
  to: vertoAttach.callee_id_number,
16578
16610
  mediaDirections: {
@@ -16583,12 +16615,12 @@ var WebRTCVertoManager = class extends VertoManager {
16583
16615
  });
16584
16616
  }
16585
16617
  initObservables(rtcPeerConnController) {
16586
- this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$12.filter)((state) => state === "connected"), (0, import_cjs$12.map)(() => rtcPeerConnController.mediaDirections), (0, import_cjs$12.startWith)(rtcPeerConnController.mediaDirections), (0, import_cjs$12.takeUntil)(this.destroyed$));
16587
- this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$12.takeUntil)(this.destroyed$));
16588
- this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$12.takeUntil)(this.destroyed$));
16618
+ this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$13.filter)((state) => state === "connected"), (0, import_cjs$13.map)(() => rtcPeerConnController.mediaDirections), (0, import_cjs$13.startWith)(rtcPeerConnController.mediaDirections), (0, import_cjs$13.takeUntil)(this.destroyed$));
16619
+ this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$13.takeUntil)(this.destroyed$));
16620
+ this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$13.takeUntil)(this.destroyed$));
16589
16621
  }
16590
16622
  setupLocalDescriptionHandler(rtcPeerConnController) {
16591
- this.subscribeTo(rtcPeerConnController.localDescription$.pipe((0, import_cjs$12.filter)((description) => description !== null), (0, import_cjs$12.takeUntil)(this.destroyed$)), (description) => {
16623
+ this.subscribeTo(rtcPeerConnController.localDescription$.pipe((0, import_cjs$13.filter)((description) => description !== null), (0, import_cjs$13.takeUntil)(this.destroyed$)), (description) => {
16592
16624
  const { type, sdp } = description;
16593
16625
  const dialogParams = this.dialogParams(rtcPeerConnController);
16594
16626
  const initial = !rtcPeerConnController.firstSDPExchangeCompleted;
@@ -16617,11 +16649,11 @@ var WebRTCVertoManager = class extends VertoManager {
16617
16649
  setupVertoByeHandler() {
16618
16650
  this.subscribeTo(this.vertoBye$, () => {
16619
16651
  this._signalingStatus$.next("disconnected");
16620
- this.attachManager.detach(this.webRtcCallSession);
16652
+ this.attachManager.detach(this.buildAttachableCall());
16621
16653
  this.callSession?.destroy();
16622
16654
  });
16623
16655
  }
16624
- getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMethod) {
16656
+ getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMessage) {
16625
16657
  let subscribe = void 0;
16626
16658
  if (!rtcPeerConnController.firstSDPExchangeCompleted) {
16627
16659
  subscribe = [];
@@ -16629,7 +16661,7 @@ var WebRTCVertoManager = class extends VertoManager {
16629
16661
  else if (rtcPeerConnController.isAdditionalDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeAdditionalDevice);
16630
16662
  else if (rtcPeerConnController.isScreenShare) subscribe.push(...PreferencesContainer.instance.inviteSubscribeScreenshare);
16631
16663
  }
16632
- const isInvite = vertoMethod === "verto.invite";
16664
+ const isInvite = isVertoInviteMessage(vertoMessage);
16633
16665
  const isReattach = isInvite && this.webRtcCallSession.options.reattach;
16634
16666
  return {
16635
16667
  callID: rtcPeerConnController.id,
@@ -16638,13 +16670,13 @@ var WebRTCVertoManager = class extends VertoManager {
16638
16670
  };
16639
16671
  }
16640
16672
  async sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnectionController) {
16641
- logger$13.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
16642
- const vertoByeOrAccepted = await (0, import_cjs$12.firstValueFrom)((0, import_cjs$12.race)(this.vertoBye$, this.webRtcCallSession.answered$));
16673
+ logger$14.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
16674
+ const vertoByeOrAccepted = await (0, import_cjs$13.firstValueFrom)((0, import_cjs$13.race)(this.vertoBye$, this.webRtcCallSession.answered$));
16643
16675
  if (isVertoByeMessage(vertoByeOrAccepted)) {
16644
- logger$13.info("[WebRTCManager] Call ended before answer was sent.");
16676
+ logger$14.info("[WebRTCManager] Call ended before answer was sent.");
16645
16677
  this.callSession?.destroy();
16646
16678
  } else if (!vertoByeOrAccepted) {
16647
- logger$13.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
16679
+ logger$14.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
16648
16680
  try {
16649
16681
  await this.bye("USER_BUSY");
16650
16682
  } finally {
@@ -16652,14 +16684,14 @@ var WebRTCVertoManager = class extends VertoManager {
16652
16684
  this.callSession?.destroy();
16653
16685
  }
16654
16686
  } else {
16655
- logger$13.debug("[WebRTCManager] Call accepted, sending answer");
16687
+ logger$14.debug("[WebRTCManager] Call accepted, sending answer");
16656
16688
  try {
16657
16689
  this._signalingStatus$.next("connecting");
16658
16690
  await this.sendLocalDescription(vertoMessageRequest, rtcPeerConnectionController);
16659
16691
  await rtcPeerConnectionController.updateAnswerStatus({ status: "sent" });
16660
- await this.attachManager.attach(this.webRtcCallSession);
16692
+ await this.attachManager.attach(this.buildAttachableCall());
16661
16693
  } catch (error) {
16662
- logger$13.error("[WebRTCManager] Error sending Verto answer:", error);
16694
+ logger$14.error("[WebRTCManager] Error sending Verto answer:", error);
16663
16695
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16664
16696
  await rtcPeerConnectionController.updateAnswerStatus({ status: "failed" });
16665
16697
  }
@@ -16748,12 +16780,12 @@ var WebRTCVertoManager = class extends VertoManager {
16748
16780
  this.subscribeTo(rtcPeerConnController.errors$, (error) => {
16749
16781
  this.onError?.(error);
16750
16782
  });
16751
- await (0, import_cjs$12.firstValueFrom)(rtcPeerConnController.connectionState$.pipe((0, import_cjs$12.filter)((state) => state === "connected"), (0, import_cjs$12.take)(1), (0, import_cjs$12.timeout)(this._screenShareTimeoutMs)));
16783
+ await (0, import_cjs$13.firstValueFrom)(rtcPeerConnController.connectionState$.pipe((0, import_cjs$13.filter)((state) => state === "connected"), (0, import_cjs$13.take)(1), (0, import_cjs$13.timeout)(this._screenShareTimeoutMs)));
16752
16784
  this._screenShareStatus$.next("started");
16753
- logger$13.info("[WebRTCManager] Screen share started successfully.");
16785
+ logger$14.info("[WebRTCManager] Screen share started successfully.");
16754
16786
  return rtcPeerConnController.id;
16755
16787
  } catch (error) {
16756
- logger$13.warn("[WebRTCManager] Error initializing additional peer connection:", error);
16788
+ logger$14.warn("[WebRTCManager] Error initializing additional peer connection:", error);
16757
16789
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16758
16790
  if (rtcPeerConnController) rtcPeerConnController.destroy();
16759
16791
  this._screenShareStatus$.next("none");
@@ -16772,9 +16804,9 @@ var WebRTCVertoManager = class extends VertoManager {
16772
16804
  if (removeTrack) return this.mainPeerConnection.stopTrackSender(removeTrack, { updateTransceiverDirection: true });
16773
16805
  }
16774
16806
  async removeScreenMedia() {
16775
- if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$13.warn("[WebRTCManager] No active screen share to stop.");
16807
+ if (!["starting", "started"].includes(this._screenShareStatus$.value)) logger$14.warn("[WebRTCManager] No active screen share to stop.");
16776
16808
  if (!this._screenShareId) {
16777
- logger$13.debug("[WebRTCManager] No screen share peer connection found.");
16809
+ logger$14.debug("[WebRTCManager] No screen share peer connection found.");
16778
16810
  return;
16779
16811
  }
16780
16812
  this._screenShareStatus$.next("stopping");
@@ -16803,12 +16835,12 @@ var WebRTCVertoManager = class extends VertoManager {
16803
16835
  dialogParams: this.dialogParams(rtcPeerConnController)
16804
16836
  }));
16805
16837
  } catch (error) {
16806
- logger$13.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
16838
+ logger$14.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
16807
16839
  throw error;
16808
16840
  }
16809
16841
  }
16810
16842
  async bye(cause) {
16811
- this.attachManager.detach(this.webRtcCallSession);
16843
+ this.attachManager.detach(this.buildAttachableCall());
16812
16844
  const rtcPeerConnController = this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);
16813
16845
  if (rtcPeerConnController) await this.executeVertoBye(rtcPeerConnController, cause);
16814
16846
  }
@@ -16821,7 +16853,7 @@ var WebRTCVertoManager = class extends VertoManager {
16821
16853
  try {
16822
16854
  await this.executeVerto(vertoInfoMessage);
16823
16855
  } catch (error) {
16824
- logger$13.warn("[WebRTCManager] Error sending DTMF digits:", error);
16856
+ logger$14.warn("[WebRTCManager] Error sending DTMF digits:", error);
16825
16857
  throw error;
16826
16858
  }
16827
16859
  }
@@ -16832,10 +16864,10 @@ var WebRTCVertoManager = class extends VertoManager {
16832
16864
  action: "transfer"
16833
16865
  });
16834
16866
  try {
16835
- logger$13.debug("[WebRTCManager] Transferring call with options:", options);
16867
+ logger$14.debug("[WebRTCManager] Transferring call with options:", options);
16836
16868
  await this.executeVerto(message);
16837
16869
  } catch (error) {
16838
- logger$13.error("[WebRTCManager] Error transferring call:", error);
16870
+ logger$14.error("[WebRTCManager] Error transferring call:", error);
16839
16871
  throw error;
16840
16872
  }
16841
16873
  }
@@ -16851,8 +16883,8 @@ var WebRTCVertoManager = class extends VertoManager {
16851
16883
 
16852
16884
  //#endregion
16853
16885
  //#region src/controllers/RTCStatsMonitor.ts
16854
- var import_cjs$11 = require_cjs();
16855
- const logger$12 = getLogger();
16886
+ var import_cjs$12 = require_cjs();
16887
+ const logger$13 = getLogger();
16856
16888
  const DEFAULT_POLLING_INTERVAL_MS = 1e3;
16857
16889
  const DEFAULT_BASELINE_SAMPLES = 10;
16858
16890
  const DEFAULT_NO_AUDIO_PACKET_THRESHOLD_MS = 2e3;
@@ -16868,6 +16900,12 @@ function computePacketLossPercent(lost, received) {
16868
16900
  if (total === 0) return 0;
16869
16901
  return lost / total * 100;
16870
16902
  }
16903
+ function isInboundRtpStat(stat) {
16904
+ return typeof stat === "object" && stat !== null && "type" in stat && stat.type === "inbound-rtp";
16905
+ }
16906
+ function isCandidatePairStat(stat) {
16907
+ return typeof stat === "object" && stat !== null && "type" in stat && stat.type === "candidate-pair";
16908
+ }
16871
16909
  var RTCStatsMonitor = class extends Destroyable {
16872
16910
  constructor(peerConnection, config = {}) {
16873
16911
  super();
@@ -16908,7 +16946,7 @@ var RTCStatsMonitor = class extends Destroyable {
16908
16946
  }
16909
16947
  /** Simple boolean health indicator. */
16910
16948
  get isNetworkHealthy$() {
16911
- return this.cachedObservable("isNetworkHealthy$", () => this._networkIssues$.pipe((0, import_cjs$11.map)((issues) => issues.length === 0), (0, import_cjs$11.distinctUntilChanged)(), (0, import_cjs$11.takeUntil)(this.destroyed$)));
16949
+ return this.cachedObservable("isNetworkHealthy$", () => this._networkIssues$.pipe((0, import_cjs$12.map)((issues) => issues.length === 0), (0, import_cjs$12.distinctUntilChanged)(), (0, import_cjs$12.takeUntil)(this.destroyed$)));
16912
16950
  }
16913
16951
  /** Whether the network is currently healthy. */
16914
16952
  get isNetworkHealthy() {
@@ -16924,7 +16962,7 @@ var RTCStatsMonitor = class extends Destroyable {
16924
16962
  }
16925
16963
  /** Emits individual critical issues for the recovery pipeline. */
16926
16964
  get criticalIssue$() {
16927
- return this.cachedObservable("criticalIssue$", () => this._networkIssues$.pipe((0, import_cjs$11.mergeMap)((issues) => (0, import_cjs$11.from)(issues.filter((i) => i.severity === "critical"))), (0, import_cjs$11.takeUntil)(this.destroyed$)));
16965
+ return this.cachedObservable("criticalIssue$", () => this._networkIssues$.pipe((0, import_cjs$12.mergeMap)((issues) => (0, import_cjs$12.from)(issues.filter((i) => i.severity === "critical"))), (0, import_cjs$12.takeUntil)(this.destroyed$)));
16928
16966
  }
16929
16967
  /** Emits each raw stats sample extracted from the peer connection. */
16930
16968
  get sample$() {
@@ -16936,32 +16974,32 @@ var RTCStatsMonitor = class extends Destroyable {
16936
16974
  const now = Date.now();
16937
16975
  this.lastAudioPacketChangeTime = now;
16938
16976
  this.lastVideoPacketChangeTime = now;
16939
- logger$12.debug("[RTCStatsMonitor] Starting stats monitoring");
16940
- this.subscribeTo((0, import_cjs$11.interval)(this.pollingIntervalMs).pipe((0, import_cjs$11.filter)(() => this.running), (0, import_cjs$11.switchMap)(() => (0, import_cjs$11.from)(this.peerConnection.getStats()).pipe((0, import_cjs$11.catchError)((err) => {
16941
- logger$12.warn("[RTCStatsMonitor] Failed to get stats:", err);
16942
- return import_cjs$11.EMPTY;
16943
- }))), (0, import_cjs$11.filter)(() => this.running), (0, import_cjs$11.map)((report) => this.extractSample(report))), (sample$1) => this._sample$.next(sample$1));
16944
- this.subscribeTo(this._sample$.pipe((0, import_cjs$11.take)(this.baselineSampleCount), (0, import_cjs$11.toArray)(), (0, import_cjs$11.map)((samples) => ({
16977
+ logger$13.debug("[RTCStatsMonitor] Starting stats monitoring");
16978
+ this.subscribeTo((0, import_cjs$12.interval)(this.pollingIntervalMs).pipe((0, import_cjs$12.filter)(() => this.running), (0, import_cjs$12.switchMap)(() => (0, import_cjs$12.from)(this.peerConnection.getStats()).pipe((0, import_cjs$12.catchError)((err) => {
16979
+ logger$13.warn("[RTCStatsMonitor] Failed to get stats:", err);
16980
+ return import_cjs$12.EMPTY;
16981
+ }))), (0, import_cjs$12.filter)(() => this.running), (0, import_cjs$12.map)((report) => this.extractSample(report))), (sample$1) => this._sample$.next(sample$1));
16982
+ this.subscribeTo(this._sample$.pipe((0, import_cjs$12.take)(this.baselineSampleCount), (0, import_cjs$12.toArray)(), (0, import_cjs$12.map)((samples) => ({
16945
16983
  rtt: samples.reduce((s, b) => s + b.roundTripTime, 0) / samples.length,
16946
16984
  jitter: samples.reduce((s, b) => s + b.audioJitter, 0) / samples.length,
16947
16985
  ready: true
16948
16986
  }))), (baseline) => {
16949
- logger$12.debug(`[RTCStatsMonitor] Baseline established: rtt=${baseline.rtt.toFixed(1)}ms, jitter=${baseline.jitter.toFixed(1)}ms`);
16987
+ logger$13.debug(`[RTCStatsMonitor] Baseline established: rtt=${baseline.rtt.toFixed(1)}ms, jitter=${baseline.jitter.toFixed(1)}ms`);
16950
16988
  this._baseline$.next(baseline);
16951
16989
  });
16952
- this.subscribeTo(this._sample$.pipe((0, import_cjs$11.scan)((acc, sample$1) => ({
16990
+ this.subscribeTo(this._sample$.pipe((0, import_cjs$12.scan)((acc, sample$1) => ({
16953
16991
  prev: acc.current,
16954
16992
  current: sample$1
16955
16993
  }), {
16956
16994
  prev: null,
16957
16995
  current: null
16958
- }), (0, import_cjs$11.filter)((pair) => pair.current !== null)), ({ prev, current }) => {
16996
+ }), (0, import_cjs$12.filter)((pair) => pair.current !== null)), ({ prev, current }) => {
16959
16997
  const now$1 = current.timestamp;
16960
16998
  this.updatePacketTracking(current, now$1);
16961
16999
  const issues = this.detectIssues(current, prev, now$1);
16962
17000
  this._networkIssues$.next(issues);
16963
17001
  });
16964
- this.subscribeTo(this._sample$.pipe((0, import_cjs$11.scan)((history, sample$1) => {
17002
+ this.subscribeTo(this._sample$.pipe((0, import_cjs$12.scan)((history, sample$1) => {
16965
17003
  const cutoff = sample$1.timestamp - this.historyWindowSeconds * 1e3;
16966
17004
  const metrics = {
16967
17005
  timestamp: sample$1.timestamp,
@@ -16983,10 +17021,10 @@ var RTCStatsMonitor = class extends Destroyable {
16983
17021
  stop() {
16984
17022
  if (!this.running) return;
16985
17023
  this.running = false;
16986
- logger$12.debug("[RTCStatsMonitor] Stopping stats monitoring");
17024
+ logger$13.debug("[RTCStatsMonitor] Stopping stats monitoring");
16987
17025
  }
16988
17026
  destroy() {
16989
- logger$12.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor");
17027
+ logger$13.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor");
16990
17028
  this.stop();
16991
17029
  super.destroy();
16992
17030
  }
@@ -16999,17 +17037,15 @@ var RTCStatsMonitor = class extends Destroyable {
16999
17037
  let roundTripTime = 0;
17000
17038
  let availableOutgoingBitrate;
17001
17039
  report.forEach((stat) => {
17002
- if (stat.type === "inbound-rtp") {
17003
- if (stat.kind === "audio") {
17004
- audioPacketsReceived += stat.packetsReceived ?? this.lastAudioPacketsReceived;
17005
- audioPacketsLost += stat.packetsLost ?? 0;
17006
- audioJitter = Math.max(audioJitter, (stat.jitter ?? 0) * 1e3);
17007
- } else if (stat.kind === "video") {
17008
- videoPacketsReceived += stat.packetsReceived ?? this.lastVideoPacketsReceived;
17009
- videoPacketsLost += stat.packetsLost ?? 0;
17010
- }
17040
+ if (isInboundRtpStat(stat)) if (stat.kind === "audio") {
17041
+ audioPacketsReceived += stat.packetsReceived ?? this.lastAudioPacketsReceived;
17042
+ audioPacketsLost += stat.packetsLost ?? 0;
17043
+ audioJitter = Math.max(audioJitter, (stat.jitter ?? 0) * 1e3);
17044
+ } else {
17045
+ videoPacketsReceived += stat.packetsReceived ?? this.lastVideoPacketsReceived;
17046
+ videoPacketsLost += stat.packetsLost ?? 0;
17011
17047
  }
17012
- if (stat.type === "candidate-pair" && stat.state === "succeeded" && stat.nominated) {
17048
+ if (isCandidatePairStat(stat) && stat.state === "succeeded" && stat.nominated) {
17013
17049
  roundTripTime = stat.currentRoundTripTime ? stat.currentRoundTripTime * 1e3 : this.lastRoundTripTime;
17014
17050
  availableOutgoingBitrate = stat.availableOutgoingBitrate ?? this.lastAvailableOutgoingBitrate;
17015
17051
  }
@@ -17116,8 +17152,8 @@ var RTCStatsMonitor = class extends Destroyable {
17116
17152
 
17117
17153
  //#endregion
17118
17154
  //#region src/managers/CallRecoveryManager.ts
17119
- var import_cjs$10 = require_cjs();
17120
- const logger$11 = getLogger();
17155
+ var import_cjs$11 = require_cjs();
17156
+ const logger$12 = getLogger();
17121
17157
  const DEFAULT_DEBOUNCE_TIME_MS = 2e3;
17122
17158
  const DEFAULT_COOLDOWN_MS = 1e4;
17123
17159
  const DEFAULT_ICE_GRACE_PERIOD_MS = 3e3;
@@ -17153,7 +17189,7 @@ const DEGRADATION_ONLY_ISSUES = new Set([
17153
17189
  * A state machine tracks the pipeline: IDLE -> DEBOUNCING -> RECOVERING -> COOLDOWN.
17154
17190
  */
17155
17191
  var CallRecoveryManager = class extends Destroyable {
17156
- constructor(callbacks, config = {}) {
17192
+ constructor(callbacks, inputs, config = {}) {
17157
17193
  super();
17158
17194
  this._recoveryState$ = this.createBehaviorSubject("idle");
17159
17195
  this._recoveryEvent$ = this.createSubject();
@@ -17167,6 +17203,7 @@ var CallRecoveryManager = class extends Destroyable {
17167
17203
  this._cooldownUntil = 0;
17168
17204
  this._pipelineStop$ = this.createSubject();
17169
17205
  this._callbacks = callbacks;
17206
+ this._inputs = inputs;
17170
17207
  this._config = {
17171
17208
  debounceTimeMs: config.debounceTimeMs ?? DEFAULT_DEBOUNCE_TIME_MS,
17172
17209
  cooldownMs: config.cooldownMs ?? DEFAULT_COOLDOWN_MS,
@@ -17186,16 +17223,16 @@ var CallRecoveryManager = class extends Destroyable {
17186
17223
  this.initDegradationRecoveryPipeline();
17187
17224
  }
17188
17225
  get recoveryState$() {
17189
- return this._recoveryState$.asObservable().pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17226
+ return this._recoveryState$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
17190
17227
  }
17191
17228
  get recoveryState() {
17192
17229
  return this._recoveryState$.value;
17193
17230
  }
17194
17231
  get recoveryEvent$() {
17195
- return this._recoveryEvent$.asObservable().pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17232
+ return this._recoveryEvent$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
17196
17233
  }
17197
17234
  get bandwidthConstrained$() {
17198
- return this._bandwidthConstrained$.asObservable().pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17235
+ return this._bandwidthConstrained$.asObservable().pipe((0, import_cjs$11.takeUntil)(this._destroyed$));
17199
17236
  }
17200
17237
  get bandwidthConstrained() {
17201
17238
  return this._bandwidthConstrained$.value;
@@ -17213,10 +17250,10 @@ var CallRecoveryManager = class extends Destroyable {
17213
17250
  */
17214
17251
  async requestIceRestart() {
17215
17252
  if (this._recoveryState$.value === "recovering") {
17216
- logger$11.info("CallRecoveryManager: manual ICE restart skipped — recovery already in progress");
17253
+ logger$12.info("CallRecoveryManager: manual ICE restart skipped — recovery already in progress");
17217
17254
  return;
17218
17255
  }
17219
- logger$11.info("CallRecoveryManager: manual ICE restart requested");
17256
+ logger$12.info("CallRecoveryManager: manual ICE restart requested");
17220
17257
  this.transitionTo("recovering");
17221
17258
  await this.executeIceRestart(false);
17222
17259
  this.startCooldown();
@@ -17232,7 +17269,7 @@ var CallRecoveryManager = class extends Destroyable {
17232
17269
  * WebSocket reconnect or call state recovers to 'connected'.
17233
17270
  */
17234
17271
  reset() {
17235
- logger$11.info("CallRecoveryManager: resetting counters");
17272
+ logger$12.info("CallRecoveryManager: resetting counters");
17236
17273
  this._attemptCount = 0;
17237
17274
  this._keyframeBurstCount = 0;
17238
17275
  this._keyframeBurstStart = 0;
@@ -17241,6 +17278,22 @@ var CallRecoveryManager = class extends Destroyable {
17241
17278
  this.transitionTo("idle");
17242
17279
  }
17243
17280
  /**
17281
+ * Notify the recovery manager that a verto.modify (ICE restart SDP exchange)
17282
+ * failed at the signaling layer. Resets cooldown and pushes a new trigger
17283
+ * so recovery can re-attempt.
17284
+ */
17285
+ notifyModifyFailed() {
17286
+ if (this._recoveryState$.value === "cooldown" || this._recoveryState$.value === "idle") {
17287
+ logger$12.info("CallRecoveryManager: verto.modify failed — re-entering recovery");
17288
+ this._cooldownUntil = 0;
17289
+ this.transitionTo("idle");
17290
+ this.pushTrigger({
17291
+ source: "network",
17292
+ detail: "modify_failed_during_recovery"
17293
+ });
17294
+ }
17295
+ }
17296
+ /**
17244
17297
  * Feed bandwidth information for graceful degradation (Section 22).
17245
17298
  * Call this from the stats monitor with current available outgoing bitrate.
17246
17299
  */
@@ -17255,7 +17308,7 @@ var CallRecoveryManager = class extends Destroyable {
17255
17308
  reason: `bandwidth ${bitrateKbps}kbps below threshold ${this._config.degradationBitrateThreshold}kbps`,
17256
17309
  timestamp: Date.now()
17257
17310
  });
17258
- logger$11.warn(`CallRecoveryManager: disabling video — bandwidth ${bitrateKbps}kbps < ${this._config.degradationBitrateThreshold}kbps`);
17311
+ logger$12.warn(`CallRecoveryManager: disabling video — bandwidth ${bitrateKbps}kbps < ${this._config.degradationBitrateThreshold}kbps`);
17259
17312
  } else if (wasConstrained && bitrateKbps >= this._config.degradationRecoveryThreshold) {
17260
17313
  this._bandwidthConstrained$.next(false);
17261
17314
  this._callbacks.enableVideo();
@@ -17264,7 +17317,7 @@ var CallRecoveryManager = class extends Destroyable {
17264
17317
  reason: `bandwidth ${bitrateKbps}kbps recovered above ${this._config.degradationRecoveryThreshold}kbps`,
17265
17318
  timestamp: Date.now()
17266
17319
  });
17267
- logger$11.info(`CallRecoveryManager: restoring video — bandwidth ${bitrateKbps}kbps >= ${this._config.degradationRecoveryThreshold}kbps`);
17320
+ logger$12.info(`CallRecoveryManager: restoring video — bandwidth ${bitrateKbps}kbps >= ${this._config.degradationRecoveryThreshold}kbps`);
17268
17321
  }
17269
17322
  }
17270
17323
  /**
@@ -17283,14 +17336,14 @@ var CallRecoveryManager = class extends Destroyable {
17283
17336
  handleWebSocketReconnect() {
17284
17337
  const pcState = this._callbacks.getPeerConnectionState();
17285
17338
  if (pcState === "connected" || pcState === "completed") {
17286
- logger$11.info("CallRecoveryManager: signal-only reconnect — peer connection still alive");
17339
+ logger$12.info("CallRecoveryManager: signal-only reconnect — peer connection still alive");
17287
17340
  this.emitEvent({
17288
17341
  action: "signal_reconnect",
17289
17342
  reason: "WebSocket reconnected, peer connection still connected",
17290
17343
  timestamp: Date.now()
17291
17344
  });
17292
17345
  } else {
17293
- logger$11.info("CallRecoveryManager: full reconnect — peer connection also down");
17346
+ logger$12.info("CallRecoveryManager: full reconnect — peer connection also down");
17294
17347
  this.emitEvent({
17295
17348
  action: "full_reconnect",
17296
17349
  reason: "WebSocket reconnected, peer connection not connected — ICE restart needed",
@@ -17309,12 +17362,12 @@ var CallRecoveryManager = class extends Destroyable {
17309
17362
  super.destroy();
17310
17363
  }
17311
17364
  initPipeline() {
17312
- this.subscribeTo(this._trigger$.pipe((0, import_cjs$10.tap)(() => {
17365
+ this.subscribeTo(this._trigger$.pipe((0, import_cjs$11.tap)(() => {
17313
17366
  if (this._recoveryState$.value === "idle") this.transitionTo("debouncing");
17314
- }), (0, import_cjs$10.debounceTime)(this._config.debounceTimeMs), (0, import_cjs$10.filter)(() => this.passGateChecks()), (0, import_cjs$10.exhaustMap)((trigger) => this.executeTieredRecovery(trigger)), (0, import_cjs$10.takeUntil)((0, import_cjs$10.merge)(this._destroyed$, this._pipelineStop$))), {
17367
+ }), (0, import_cjs$11.debounceTime)(this._config.debounceTimeMs), (0, import_cjs$11.withLatestFrom)(this._inputs.signalingReady$), (0, import_cjs$11.filter)(([, signalingReady]) => this.passGateChecks(signalingReady)), (0, import_cjs$11.map)(([trigger]) => trigger), (0, import_cjs$11.exhaustMap)((trigger) => this.executeTieredRecovery(trigger)), (0, import_cjs$11.takeUntil)((0, import_cjs$11.merge)(this._destroyed$, this._pipelineStop$))), {
17315
17368
  next: () => {},
17316
17369
  error: (err) => {
17317
- logger$11.error("CallRecoveryManager: pipeline error", err);
17370
+ logger$12.error("CallRecoveryManager: pipeline error", err);
17318
17371
  this.transitionTo("idle");
17319
17372
  }
17320
17373
  });
@@ -17330,10 +17383,10 @@ var CallRecoveryManager = class extends Destroyable {
17330
17383
  initDegradationRecoveryPipeline() {
17331
17384
  if (!this._config.enableAutoDegradation) return;
17332
17385
  const delayMs = this._config.packetLossRecoveryDelaySec * 1e3;
17333
- this.subscribeTo((0, import_cjs$10.combineLatest)([this._bandwidthConstrained$, this._hasPacketLoss$]).pipe((0, import_cjs$10.switchMap)(([constrained, hasPacketLoss]) => {
17334
- if (constrained && !hasPacketLoss) return (0, import_cjs$10.timer)(delayMs);
17335
- return import_cjs$10.EMPTY;
17336
- }), (0, import_cjs$10.takeUntil)(this._destroyed$)), () => {
17386
+ this.subscribeTo((0, import_cjs$11.combineLatest)([this._bandwidthConstrained$, this._hasPacketLoss$]).pipe((0, import_cjs$11.switchMap)(([constrained, hasPacketLoss]) => {
17387
+ if (constrained && !hasPacketLoss) return (0, import_cjs$11.timer)(delayMs);
17388
+ return import_cjs$11.EMPTY;
17389
+ }), (0, import_cjs$11.takeUntil)(this._destroyed$)), () => {
17337
17390
  this._bandwidthConstrained$.next(false);
17338
17391
  this._callbacks.enableVideo();
17339
17392
  this.emitEvent({
@@ -17341,27 +17394,27 @@ var CallRecoveryManager = class extends Destroyable {
17341
17394
  reason: `no packet loss for ${this._config.packetLossRecoveryDelaySec}s — restoring video`,
17342
17395
  timestamp: Date.now()
17343
17396
  });
17344
- logger$11.info(`CallRecoveryManager: restoring video — no packet loss for ${this._config.packetLossRecoveryDelaySec}s`);
17397
+ logger$12.info(`CallRecoveryManager: restoring video — no packet loss for ${this._config.packetLossRecoveryDelaySec}s`);
17345
17398
  });
17346
17399
  }
17347
- passGateChecks() {
17400
+ passGateChecks(signalingReady) {
17348
17401
  if (this._callbacks.isNegotiating()) {
17349
- logger$11.debug("CallRecoveryManager: gate blocked — negotiation in progress");
17402
+ logger$12.debug("CallRecoveryManager: gate blocked — negotiation in progress");
17350
17403
  this.transitionTo("idle");
17351
17404
  return false;
17352
17405
  }
17353
- if (!this._callbacks.isWebSocketConnected()) {
17354
- logger$11.debug("CallRecoveryManager: gate blocked — WebSocket not connected");
17406
+ if (!signalingReady) {
17407
+ logger$12.debug("CallRecoveryManager: gate blocked — signaling not ready");
17355
17408
  this.transitionTo("idle");
17356
17409
  return false;
17357
17410
  }
17358
17411
  if (!this._callbacks.isCallConnected()) {
17359
- logger$11.debug("CallRecoveryManager: gate blocked — call not connected");
17412
+ logger$12.debug("CallRecoveryManager: gate blocked — call not connected");
17360
17413
  this.transitionTo("idle");
17361
17414
  return false;
17362
17415
  }
17363
17416
  if (this.isCooldownActive()) {
17364
- logger$11.debug("CallRecoveryManager: gate blocked — cooldown active");
17417
+ logger$12.debug("CallRecoveryManager: gate blocked — cooldown active");
17365
17418
  this.transitionTo("cooldown");
17366
17419
  return false;
17367
17420
  }
@@ -17372,17 +17425,17 @@ var CallRecoveryManager = class extends Destroyable {
17372
17425
  }
17373
17426
  executeTieredRecovery(trigger) {
17374
17427
  this.transitionTo("recovering");
17375
- logger$11.info(`CallRecoveryManager: starting tiered recovery — source=${trigger.source} detail=${trigger.detail}`);
17376
- return (0, import_cjs$10.from)(this.runTiers(trigger)).pipe((0, import_cjs$10.tap)(() => this.startCooldown()), (0, import_cjs$10.catchError)((err) => {
17377
- logger$11.error("CallRecoveryManager: tiered recovery failed", err);
17428
+ logger$12.info(`CallRecoveryManager: starting tiered recovery — source=${trigger.source} detail=${trigger.detail}`);
17429
+ return (0, import_cjs$11.from)(this.runTiers(trigger)).pipe((0, import_cjs$11.tap)(() => this.startCooldown()), (0, import_cjs$11.catchError)((err) => {
17430
+ logger$12.error("CallRecoveryManager: tiered recovery failed", err);
17378
17431
  this.startCooldown();
17379
- return import_cjs$10.EMPTY;
17432
+ return import_cjs$11.EMPTY;
17380
17433
  }));
17381
17434
  }
17382
17435
  async runTiers(trigger) {
17383
17436
  this.executeKeyframe(trigger.detail);
17384
17437
  if (trigger.issueType && DEGRADATION_ONLY_ISSUES.has(trigger.issueType)) {
17385
- logger$11.debug(`CallRecoveryManager: degradation-only issue (${trigger.issueType}) — Tier 1 only, skipping ICE restart`);
17438
+ logger$12.debug(`CallRecoveryManager: degradation-only issue (${trigger.issueType}) — Tier 1 only, skipping ICE restart`);
17386
17439
  return;
17387
17440
  }
17388
17441
  if (this._attemptCount < this._config.maxAttempts) {
@@ -17399,13 +17452,13 @@ var CallRecoveryManager = class extends Destroyable {
17399
17452
  maxAttempts: this._config.maxAttempts,
17400
17453
  timestamp: Date.now()
17401
17454
  });
17402
- logger$11.warn("CallRecoveryManager: max recovery attempts reached");
17455
+ logger$12.warn("CallRecoveryManager: max recovery attempts reached");
17403
17456
  }
17404
17457
  }
17405
17458
  executeKeyframe(reason) {
17406
17459
  const now = Date.now();
17407
17460
  if (now < this._keyframeCooldownUntil) {
17408
- logger$11.debug("CallRecoveryManager: keyframe request skipped — cooldown active");
17461
+ logger$12.debug("CallRecoveryManager: keyframe request skipped — cooldown active");
17409
17462
  return;
17410
17463
  }
17411
17464
  if (now - this._keyframeBurstStart > this._config.keyframeBurstWindowMs) {
@@ -17414,7 +17467,7 @@ var CallRecoveryManager = class extends Destroyable {
17414
17467
  }
17415
17468
  if (this._keyframeBurstCount >= this._config.keyframeMaxBurst) {
17416
17469
  this._keyframeCooldownUntil = now + this._config.keyframeCooldownMs;
17417
- logger$11.debug(`CallRecoveryManager: keyframe burst limit reached (${this._config.keyframeMaxBurst}), cooldown until ${this._keyframeCooldownUntil}`);
17470
+ logger$12.debug(`CallRecoveryManager: keyframe burst limit reached (${this._config.keyframeMaxBurst}), cooldown until ${this._keyframeCooldownUntil}`);
17418
17471
  return;
17419
17472
  }
17420
17473
  this._keyframeBurstCount += 1;
@@ -17424,12 +17477,12 @@ var CallRecoveryManager = class extends Destroyable {
17424
17477
  reason,
17425
17478
  timestamp: now
17426
17479
  });
17427
- logger$11.debug(`CallRecoveryManager: keyframe requested (burst ${this._keyframeBurstCount}/${this._config.keyframeMaxBurst})`);
17480
+ logger$12.debug(`CallRecoveryManager: keyframe requested (burst ${this._keyframeBurstCount}/${this._config.keyframeMaxBurst})`);
17428
17481
  }
17429
17482
  async executeIceRestart(relayOnly) {
17430
17483
  this._attemptCount += 1;
17431
17484
  const tier = relayOnly ? "Tier 3 (relay-only)" : "Tier 2 (standard)";
17432
- logger$11.info(`CallRecoveryManager: ${tier} ICE restart — attempt ${this._attemptCount}/${this._config.maxAttempts}`);
17485
+ logger$12.info(`CallRecoveryManager: ${tier} ICE restart — attempt ${this._attemptCount}/${this._config.maxAttempts}`);
17433
17486
  this.emitEvent({
17434
17487
  action: "reinvite_started",
17435
17488
  reason: `${tier} ICE restart`,
@@ -17446,7 +17499,7 @@ var CallRecoveryManager = class extends Destroyable {
17446
17499
  maxAttempts: this._config.maxAttempts,
17447
17500
  timestamp: Date.now()
17448
17501
  });
17449
- logger$11.info(`CallRecoveryManager: ${tier} ICE restart succeeded`);
17502
+ logger$12.info(`CallRecoveryManager: ${tier} ICE restart succeeded`);
17450
17503
  this._attemptCount = 0;
17451
17504
  return true;
17452
17505
  }
@@ -17457,7 +17510,7 @@ var CallRecoveryManager = class extends Destroyable {
17457
17510
  maxAttempts: this._config.maxAttempts,
17458
17511
  timestamp: Date.now()
17459
17512
  });
17460
- logger$11.warn(`CallRecoveryManager: ${tier} ICE restart failed`);
17513
+ logger$12.warn(`CallRecoveryManager: ${tier} ICE restart failed`);
17461
17514
  return false;
17462
17515
  } catch {
17463
17516
  this.emitEvent({
@@ -17467,7 +17520,7 @@ var CallRecoveryManager = class extends Destroyable {
17467
17520
  maxAttempts: this._config.maxAttempts,
17468
17521
  timestamp: Date.now()
17469
17522
  });
17470
- logger$11.warn(`CallRecoveryManager: ${tier} ICE restart timed out`);
17523
+ logger$12.warn(`CallRecoveryManager: ${tier} ICE restart timed out`);
17471
17524
  return false;
17472
17525
  }
17473
17526
  }
@@ -17488,7 +17541,7 @@ var CallRecoveryManager = class extends Destroyable {
17488
17541
  transitionTo(state) {
17489
17542
  const prev = this._recoveryState$.value;
17490
17543
  if (prev !== state) {
17491
- logger$11.debug(`CallRecoveryManager: state ${prev} -> ${state}`);
17544
+ logger$12.debug(`CallRecoveryManager: state ${prev} -> ${state}`);
17492
17545
  this._recoveryState$.next(state);
17493
17546
  }
17494
17547
  }
@@ -17496,7 +17549,7 @@ var CallRecoveryManager = class extends Destroyable {
17496
17549
  this._cooldownUntil = Date.now() + this._config.cooldownMs;
17497
17550
  this.transitionTo("cooldown");
17498
17551
  if (this._cooldownSubscription) this._cooldownSubscription.unsubscribe();
17499
- this._cooldownSubscription = (0, import_cjs$10.timer)(this._config.cooldownMs).pipe((0, import_cjs$10.take)(1), (0, import_cjs$10.takeUntil)(this._destroyed$), (0, import_cjs$10.filter)(() => this._recoveryState$.value === "cooldown")).subscribe(() => this.transitionTo("idle"));
17552
+ this._cooldownSubscription = (0, import_cjs$11.timer)(this._config.cooldownMs).pipe((0, import_cjs$11.take)(1), (0, import_cjs$11.takeUntil)(this._destroyed$), (0, import_cjs$11.filter)(() => this._recoveryState$.value === "cooldown")).subscribe(() => this.transitionTo("idle"));
17500
17553
  }
17501
17554
  emitEvent(event) {
17502
17555
  this._recoveryEvent$.next(event);
@@ -17590,8 +17643,8 @@ function mosToQualityLevel(mos) {
17590
17643
 
17591
17644
  //#endregion
17592
17645
  //#region src/core/entities/Call.ts
17593
- var import_cjs$9 = require_cjs();
17594
- const logger$10 = getLogger();
17646
+ var import_cjs$10 = require_cjs();
17647
+ const logger$11 = getLogger();
17595
17648
  /**
17596
17649
  * Ratio between the critical and warning RTT spike multipliers.
17597
17650
  * Warning threshold = baseline * warningMultiplier (default 3x)
@@ -17609,7 +17662,7 @@ const fromDestinationParams = (destination) => {
17609
17662
  });
17610
17663
  return params;
17611
17664
  } catch (error) {
17612
- logger$10.warn(`Failed to parse destination URI: ${destination}`, error);
17665
+ logger$11.warn(`Failed to parse destination URI: ${destination}`, error);
17613
17666
  return {};
17614
17667
  }
17615
17668
  };
@@ -17665,10 +17718,13 @@ var WebRTCCall = class extends Destroyable {
17665
17718
  const { deviceController, networkChange$ } = initialization;
17666
17719
  this._networkChange$ = networkChange$;
17667
17720
  this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
17668
- this.subscribeTo((0, import_cjs$9.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.takeUntil)(this._destroyed$)), (status) => {
17721
+ this.subscribeTo((0, import_cjs$10.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$10.distinctUntilChanged)(), (0, import_cjs$10.takeUntil)(this._destroyed$)), (status) => {
17669
17722
  this._lastMergedStatus = status;
17670
17723
  if (status === "connected" && !this._statsMonitor) this.initResilienceSubsystems();
17671
- else if (status === "disconnected" || status === "destroyed" || status === "failed") this.stopResilienceSubsystems();
17724
+ else if (status === "disconnected") {
17725
+ this._statsMonitor?.destroy();
17726
+ this._statsMonitor = void 0;
17727
+ } else if (status === "destroyed" || status === "failed") this.stopResilienceSubsystems();
17672
17728
  });
17673
17729
  }
17674
17730
  /** Observable stream of errors from media, signaling, and peer connection layers. */
@@ -17687,13 +17743,17 @@ var WebRTCCall = class extends Destroyable {
17687
17743
  this.destroy();
17688
17744
  }
17689
17745
  }
17746
+ /** Notify the recovery manager that a verto.modify signaling exchange failed. */
17747
+ notifyModifyFailed() {
17748
+ this._recoveryManager?.notifyModifyFailed();
17749
+ }
17690
17750
  /** Whether this call is `'inbound'` or `'outbound'`. */
17691
17751
  get direction() {
17692
17752
  return this.options.initOffer ? "inbound" : "outbound";
17693
17753
  }
17694
17754
  /** Observable of the address associated with this call. */
17695
17755
  get address$() {
17696
- return this.deferEmission((0, import_cjs$9.from)([this.address])).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17756
+ return this.deferEmission((0, import_cjs$10.from)([this.address])).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17697
17757
  }
17698
17758
  /** Display name of the caller. */
17699
17759
  get fromName() {
@@ -17772,7 +17832,7 @@ var WebRTCCall = class extends Destroyable {
17772
17832
  }
17773
17833
  /** Observable of layout layer positions for all participants. */
17774
17834
  get layoutLayers$() {
17775
- return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17835
+ return this.deferEmission(this.callEventsManager.layoutLayers$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17776
17836
  }
17777
17837
  /** Current snapshot of layout layers. */
17778
17838
  get layoutLayers() {
@@ -17800,7 +17860,7 @@ var WebRTCCall = class extends Destroyable {
17800
17860
  if (isJSONRPCErrorResponse(response)) throw new JSONRPCError(parseInt(response.result?.code ?? "0"), `Error response from method ${method}: ${response.result?.code} ${response.result?.message}`, void 0, void 0, request.id);
17801
17861
  return response;
17802
17862
  } catch (error) {
17803
- logger$10.error(`[Call] Error executing method ${method} with params`, params, error);
17863
+ logger$11.error(`[Call] Error executing method ${method} with params`, params, error);
17804
17864
  throw error;
17805
17865
  }
17806
17866
  }
@@ -17827,45 +17887,45 @@ var WebRTCCall = class extends Destroyable {
17827
17887
  }
17828
17888
  /** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
17829
17889
  get status$() {
17830
- return this.publicCachedObservable("status$", () => (0, import_cjs$9.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.tap)((status) => {
17890
+ return this.publicCachedObservable("status$", () => (0, import_cjs$10.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$10.distinctUntilChanged)(), (0, import_cjs$10.tap)((status) => {
17831
17891
  this._lastMergedStatus = status;
17832
17892
  })));
17833
17893
  }
17834
17894
  /** Observable of the participants list, emits on join/leave/update. */
17835
17895
  get participants$() {
17836
- return this.deferEmission(this.callEventsManager.participants$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17896
+ return this.deferEmission(this.callEventsManager.participants$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17837
17897
  }
17838
17898
  /** Observable of the local (self) participant. */
17839
17899
  get self$() {
17840
- return this.deferEmission(this.callEventsManager.self$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17900
+ return this.deferEmission(this.callEventsManager.self$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17841
17901
  }
17842
17902
  /** Observable indicating whether the call is being recorded. */
17843
17903
  get recording$() {
17844
- return this.deferEmission(this.callEventsManager.recording$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17904
+ return this.deferEmission(this.callEventsManager.recording$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17845
17905
  }
17846
17906
  /** Observable indicating whether the call is being streamed. */
17847
17907
  get streaming$() {
17848
- return this.deferEmission(this.callEventsManager.streaming$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17908
+ return this.deferEmission(this.callEventsManager.streaming$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17849
17909
  }
17850
17910
  /** Observable indicating whether raise-hand priority is active. */
17851
17911
  get raiseHandPriority$() {
17852
- return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17912
+ return this.deferEmission(this.callEventsManager.raiseHandPriority$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17853
17913
  }
17854
17914
  /** Observable indicating whether the call room is locked. */
17855
17915
  get locked$() {
17856
- return this.deferEmission(this.callEventsManager.locked$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17916
+ return this.deferEmission(this.callEventsManager.locked$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17857
17917
  }
17858
17918
  /** Observable of custom metadata associated with the call. */
17859
17919
  get meta$() {
17860
- return this.deferEmission(this.callEventsManager.meta$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17920
+ return this.deferEmission(this.callEventsManager.meta$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17861
17921
  }
17862
17922
  /** Observable of the call's capability flags. */
17863
17923
  get capabilities$() {
17864
- return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17924
+ return this.deferEmission(this.callEventsManager.capabilities$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17865
17925
  }
17866
17926
  /** Observable of the current layout name. */
17867
17927
  get layout$() {
17868
- return this.deferEmission(this.callEventsManager.layout$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17928
+ return this.deferEmission(this.callEventsManager.layout$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17869
17929
  }
17870
17930
  /** Current call status. */
17871
17931
  get status() {
@@ -17897,7 +17957,7 @@ var WebRTCCall = class extends Destroyable {
17897
17957
  }
17898
17958
  /** Observable of available layout names. */
17899
17959
  get layouts$() {
17900
- return this.deferEmission(this.callEventsManager.layouts$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17960
+ return this.deferEmission(this.callEventsManager.layouts$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17901
17961
  }
17902
17962
  /** Current snapshot of available layout names. */
17903
17963
  get layouts() {
@@ -17905,7 +17965,7 @@ var WebRTCCall = class extends Destroyable {
17905
17965
  }
17906
17966
  /** Observable of the local media stream (camera/microphone). */
17907
17967
  get localStream$() {
17908
- return this.deferEmission(this.vertoManager.localStream$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17968
+ return this.deferEmission(this.vertoManager.localStream$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17909
17969
  }
17910
17970
  /** Current local media stream, or `null` if not available. */
17911
17971
  get localStream() {
@@ -17913,7 +17973,7 @@ var WebRTCCall = class extends Destroyable {
17913
17973
  }
17914
17974
  /** Observable of the remote media stream from the far end. */
17915
17975
  get remoteStream$() {
17916
- return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
17976
+ return this.deferEmission(this.vertoManager.remoteStream$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
17917
17977
  }
17918
17978
  /** Current remote media stream, or `null` if not available. */
17919
17979
  get remoteStream() {
@@ -18003,9 +18063,9 @@ var WebRTCCall = class extends Destroyable {
18003
18063
  */
18004
18064
  initResilienceSubsystems() {
18005
18065
  const pc = this.rtcPeerConnection;
18006
- logger$10.debug(`[Call] initResilienceSubsystems: pc=${pc ? "exists" : "undefined"}, connectionState=${pc?.connectionState}`);
18066
+ logger$11.debug(`[Call] initResilienceSubsystems: pc=${pc ? "exists" : "undefined"}, connectionState=${pc?.connectionState}`);
18007
18067
  if (!pc) {
18008
- logger$10.warn("[Call] No peer connection available, skipping resilience init");
18068
+ logger$11.warn("[Call] No peer connection available, skipping resilience init");
18009
18069
  return;
18010
18070
  }
18011
18071
  try {
@@ -18040,21 +18100,20 @@ var WebRTCCall = class extends Destroyable {
18040
18100
  disableVideo: () => {
18041
18101
  try {
18042
18102
  this.vertoManager.muteMainVideoInputDevice();
18043
- logger$10.debug("[Call] Recovery manager disabled video");
18103
+ logger$11.debug("[Call] Recovery manager disabled video");
18044
18104
  } catch {
18045
- logger$10.debug("[Call] Recovery manager failed to disable video");
18105
+ logger$11.debug("[Call] Recovery manager failed to disable video");
18046
18106
  }
18047
18107
  },
18048
18108
  enableVideo: () => {
18049
18109
  this.vertoManager.unmuteMainVideoInputDevice().catch(() => {
18050
- logger$10.debug("[Call] Recovery manager failed to enable video");
18110
+ logger$11.debug("[Call] Recovery manager failed to enable video");
18051
18111
  });
18052
18112
  },
18053
18113
  isNegotiating: () => this.vertoManager.mainPeerConnection.isNegotiating,
18054
- isWebSocketConnected: () => this._lastMergedStatus !== "disconnected",
18055
18114
  isCallConnected: () => this._lastMergedStatus === "connected",
18056
18115
  getPeerConnectionState: () => pc.connectionState
18057
- }, {
18116
+ }, { signalingReady$: this.clientSession.authenticated$ }, {
18058
18117
  debounceTimeMs: prefs.recoveryDebounceTime,
18059
18118
  cooldownMs: prefs.recoveryCooldown,
18060
18119
  iceGracePeriodMs: prefs.iceDisconnectedGracePeriod,
@@ -18097,6 +18156,15 @@ var WebRTCCall = class extends Destroyable {
18097
18156
  });
18098
18157
  this.subscribeTo(this._recoveryManager.recoveryEvent$, (event) => {
18099
18158
  this._recoveryEvent$.next(event);
18159
+ if (event.action === "max_attempts_reached") {
18160
+ logger$11.warn("[Call] All recovery attempts exhausted, terminating call");
18161
+ this.emitError({
18162
+ kind: "network",
18163
+ fatal: true,
18164
+ error: /* @__PURE__ */ new Error("Call recovery failed: all attempts exhausted"),
18165
+ callId: this.id
18166
+ });
18167
+ }
18100
18168
  });
18101
18169
  this.subscribeTo(this._recoveryManager.bandwidthConstrained$, (constrained) => {
18102
18170
  this._bandwidthConstrained$.next(constrained);
@@ -18108,14 +18176,14 @@ var WebRTCCall = class extends Destroyable {
18108
18176
  });
18109
18177
  else if (event.type === "online") this._recoveryManager?.handleWebSocketReconnect();
18110
18178
  });
18111
- this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$9.skip)(1), (0, import_cjs$9.filter)(Boolean)), () => {
18112
- logger$10.debug("[Call] WebSocket reconnected — notifying recovery manager");
18179
+ this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$10.skip)(1), (0, import_cjs$10.filter)(Boolean)), () => {
18180
+ logger$11.debug("[Call] WebSocket reconnected — notifying recovery manager");
18113
18181
  this._recoveryManager?.handleWebSocketReconnect();
18114
18182
  });
18115
18183
  this._statsMonitor.start();
18116
- logger$10.debug("[Call] Resilience subsystems initialized for call", this.id);
18184
+ logger$11.debug("[Call] Resilience subsystems initialized for call", this.id);
18117
18185
  } catch (error) {
18118
- logger$10.warn("[Call] Failed to initialize resilience subsystems:", error);
18186
+ logger$11.warn("[Call] Failed to initialize resilience subsystems:", error);
18119
18187
  }
18120
18188
  }
18121
18189
  /**
@@ -18137,14 +18205,14 @@ var WebRTCCall = class extends Destroyable {
18137
18205
  }
18138
18206
  /** Observable of the current audio/video send/receive directions. */
18139
18207
  get mediaDirections$() {
18140
- return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, import_cjs$9.takeUntil)(this._destroyed$));
18208
+ return this.deferEmission(this.vertoManager.mediaDirections$).pipe((0, import_cjs$10.takeUntil)(this._destroyed$));
18141
18209
  }
18142
18210
  /** Current audio/video send/receive directions. */
18143
18211
  get mediaDirections() {
18144
18212
  return this.vertoManager.mediaDirections;
18145
18213
  }
18146
18214
  get participantsId$() {
18147
- return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, import_cjs$9.map)((participants) => participants.map((participant) => participant.id))));
18215
+ return this.cachedObservable("participantsId$", () => this.participants$.pipe((0, import_cjs$10.map)((participants) => participants.map((participant) => participant.id))));
18148
18216
  }
18149
18217
  /**
18150
18218
  * Executes a raw JSON-RPC request on the client session.
@@ -18177,48 +18245,48 @@ var WebRTCCall = class extends Destroyable {
18177
18245
  }
18178
18246
  isCallSessionEvent(event) {
18179
18247
  try {
18180
- logger$10.debug("[Call] Checking if event is for this call session:", event);
18248
+ logger$11.debug("[Call] Checking if event is for this call session:", event);
18181
18249
  const callId = getValueFrom(event, "params.params.callID") ?? getValueFrom(event, "params.call_id");
18182
18250
  const roomSessionId = getValueFrom(event, "params.room_session_id");
18183
- logger$10.debug(`[Call] Extracted session identifiers callID: ${callId} and roomSessionID: ${roomSessionId} from event:`);
18251
+ logger$11.debug(`[Call] Extracted session identifiers callID: ${callId} and roomSessionID: ${roomSessionId} from event:`);
18184
18252
  return callId === this.id || !!callId && this.callEventsManager.isCallIdValid(callId) || !!roomSessionId && this.callEventsManager.isRoomSessionIdValid(roomSessionId);
18185
18253
  } catch (error) {
18186
- logger$10.error("[Call] Error checking if event is for this call session:", error);
18254
+ logger$11.error("[Call] Error checking if event is for this call session:", error);
18187
18255
  return false;
18188
18256
  }
18189
18257
  }
18190
18258
  get callSessionEvents$() {
18191
- return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$9.filter)((event) => this.isCallSessionEvent(event)), (0, import_cjs$9.tap)((event) => {
18192
- logger$10.debug("[Call] Received call session event:", event);
18193
- }), (0, import_cjs$9.takeUntil)(this.destroyed$), (0, import_cjs$9.share)()));
18259
+ return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$10.filter)((event) => this.isCallSessionEvent(event)), (0, import_cjs$10.tap)((event) => {
18260
+ logger$11.debug("[Call] Received call session event:", event);
18261
+ }), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
18194
18262
  }
18195
18263
  /** Observable of call-updated events. */
18196
18264
  get callUpdated$() {
18197
- return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(filterAs(isCallUpdatedMetadata, "params"), (0, import_cjs$9.takeUntil)(this.destroyed$)));
18265
+ return this.publicCachedObservable("callUpdated$", () => this.callSessionEvents$.pipe(filterAs(isCallUpdatedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
18198
18266
  }
18199
18267
  /** Observable of member-joined events, emitted when a remote participant joins the call. */
18200
18268
  get memberJoined$() {
18201
- return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(filterAs(isMemberJoinedMetadata, "params"), (0, import_cjs$9.takeUntil)(this.destroyed$)));
18269
+ return this.publicCachedObservable("memberJoined$", () => this.callSessionEvents$.pipe(filterAs(isMemberJoinedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
18202
18270
  }
18203
18271
  /** Observable of member-left events, emitted when a participant leaves the call. */
18204
18272
  get memberLeft$() {
18205
- return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(filterAs(isMemberLeftMetadata, "params"), (0, import_cjs$9.takeUntil)(this.destroyed$)));
18273
+ return this.publicCachedObservable("memberLeft$", () => this.callSessionEvents$.pipe(filterAs(isMemberLeftMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
18206
18274
  }
18207
18275
  /** Observable of member-updated events (mute, volume, etc.). */
18208
18276
  get memberUpdated$() {
18209
- return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(filterAs(isMemberUpdatedMetadata, "params"), (0, import_cjs$9.takeUntil)(this.destroyed$)));
18277
+ return this.publicCachedObservable("memberUpdated$", () => this.callSessionEvents$.pipe(filterAs(isMemberUpdatedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
18210
18278
  }
18211
18279
  /** Observable of member-talking events (speech start/stop). */
18212
18280
  get memberTalking$() {
18213
- return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(filterAs(isMemberTalkingMetadata, "params"), (0, import_cjs$9.takeUntil)(this.destroyed$)));
18281
+ return this.publicCachedObservable("memberTalking$", () => this.callSessionEvents$.pipe(filterAs(isMemberTalkingMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
18214
18282
  }
18215
18283
  /** Observable of call state-change events. */
18216
18284
  get callStates$() {
18217
- return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(filterAs(isCallStateMetadata, "params"), (0, import_cjs$9.takeUntil)(this.destroyed$)));
18285
+ return this.publicCachedObservable("callStates$", () => this.callSessionEvents$.pipe(filterAs(isCallStateMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
18218
18286
  }
18219
18287
  /** Observable of layout-changed events. */
18220
18288
  get layoutUpdates$() {
18221
- return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(filterAs(isLayoutChangedMetadata, "params"), (0, import_cjs$9.takeUntil)(this.destroyed$)));
18289
+ return this.publicCachedObservable("layoutUpdates$", () => this.callSessionEvents$.pipe(filterAs(isLayoutChangedMetadata, "params"), (0, import_cjs$10.takeUntil)(this.destroyed$)));
18222
18290
  }
18223
18291
  /** Underlying `RTCPeerConnection`, for advanced use cases. */
18224
18292
  get rtcPeerConnection() {
@@ -18226,7 +18294,7 @@ var WebRTCCall = class extends Destroyable {
18226
18294
  }
18227
18295
  /** Observable of raw signaling events as plain objects. */
18228
18296
  get signalingEvent$() {
18229
- return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, import_cjs$9.map)((event) => JSON.parse(JSON.stringify(event)))));
18297
+ return this.publicCachedObservable("signalingEvent$", () => this.callEvent$.pipe((0, import_cjs$10.map)((event) => JSON.parse(JSON.stringify(event)))));
18230
18298
  }
18231
18299
  /**
18232
18300
  * Subscribe to a custom signaling event type on this call.
@@ -18254,16 +18322,16 @@ var WebRTCCall = class extends Destroyable {
18254
18322
  subscribe(eventType) {
18255
18323
  const cached = this._customSubscriptions.get(eventType);
18256
18324
  if (cached) return cached;
18257
- const filtered$ = this.callSessionEvents$.pipe((0, import_cjs$9.filter)((event) => event.event_type === eventType), (0, import_cjs$9.map)((event) => JSON.parse(JSON.stringify(event))), (0, import_cjs$9.takeUntil)(this._destroyed$));
18325
+ const filtered$ = this.callSessionEvents$.pipe((0, import_cjs$10.filter)((event) => event.event_type === eventType), (0, import_cjs$10.map)((event) => JSON.parse(JSON.stringify(event))), (0, import_cjs$10.takeUntil)(this._destroyed$));
18258
18326
  this._customSubscriptions.set(eventType, filtered$);
18259
18327
  this._sendVertoSubscribe(eventType);
18260
18328
  return filtered$;
18261
18329
  }
18262
18330
  get webrtcMessages$() {
18263
- return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$9.tap)((event) => logger$10.debug("[Call] Event is a WebRTC message event:", event)), (0, import_cjs$9.takeUntil)(this.destroyed$), (0, import_cjs$9.share)()));
18331
+ return this.cachedObservable("webrtcMessages$", () => this.callSessionEvents$.pipe(filterAs(isWebrtcMessageMetadata, "params"), (0, import_cjs$10.tap)((event) => logger$11.debug("[Call] Event is a WebRTC message event:", event)), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
18264
18332
  }
18265
18333
  get callEvent$() {
18266
- return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$9.tap)((event) => logger$10.debug("[Call] Event is a call event:", event)), (0, import_cjs$9.takeUntil)(this.destroyed$), (0, import_cjs$9.share)()));
18334
+ return this.cachedObservable("callEvent$", () => this.callSessionEvents$.pipe(filterAs(isSignalwireCallMetadata, "params"), (0, import_cjs$10.tap)((event) => logger$11.debug("[Call] Event is a call event:", event)), (0, import_cjs$10.takeUntil)(this.destroyed$), (0, import_cjs$10.share)()));
18267
18335
  }
18268
18336
  get layoutEvent$() {
18269
18337
  return this.cachedObservable("layoutEvent$", () => this.callEvent$.pipe(filterAs(isLayoutChangedMetadata, "params")));
@@ -18356,7 +18424,7 @@ var WebRTCCall = class extends Destroyable {
18356
18424
  */
18357
18425
  async setLayout(layout, positions) {
18358
18426
  if (!this.layouts.includes(layout)) throw new InvalidParams(`Layout ${layout} is not available in the current call layouts: ${this.layouts.join(", ")}`);
18359
- const selfId = await (0, import_cjs$9.firstValueFrom)(this.selfId$.pipe((0, import_cjs$9.filter)((id) => id !== null)));
18427
+ const selfId = await (0, import_cjs$10.firstValueFrom)(this.selfId$.pipe((0, import_cjs$10.filter)((id) => id !== null)));
18360
18428
  await this.executeMethod(selfId, "call.layout.set", {
18361
18429
  layout,
18362
18430
  positions
@@ -18397,10 +18465,10 @@ var WebRTCCall = class extends Destroyable {
18397
18465
  message
18398
18466
  };
18399
18467
  this.clientSession.execute(WebrtcVerto(params)).catch((error) => {
18400
- logger$10.warn(`[Call] verto.subscribe for '${eventType}' failed (non-fatal):`, error);
18468
+ logger$11.warn(`[Call] verto.subscribe for '${eventType}' failed (non-fatal):`, error);
18401
18469
  });
18402
18470
  } catch (error) {
18403
- logger$10.warn(`[Call] Failed to send verto.subscribe for '${eventType}':`, error);
18471
+ logger$11.warn(`[Call] Failed to send verto.subscribe for '${eventType}':`, error);
18404
18472
  }
18405
18473
  }
18406
18474
  };
@@ -18422,6 +18490,7 @@ function inferCallErrorKind(error) {
18422
18490
  function isFatalError(error) {
18423
18491
  if (error instanceof VertoPongError) return false;
18424
18492
  if (error instanceof MediaTrackError) return false;
18493
+ if (error instanceof RPCTimeoutError) return false;
18425
18494
  return true;
18426
18495
  }
18427
18496
  /**
@@ -18453,6 +18522,9 @@ var CallFactory = class {
18453
18522
  callId: callInstance.id
18454
18523
  };
18455
18524
  callInstance.emitError(callError);
18525
+ },
18526
+ onModifyFailed: () => {
18527
+ callInstance.notifyModifyFailed();
18456
18528
  }
18457
18529
  }),
18458
18530
  callEventsManager: new CallEventsManager(callInstance)
@@ -18466,8 +18538,8 @@ var CallFactory = class {
18466
18538
 
18467
18539
  //#endregion
18468
18540
  //#region src/behaviors/Collection.ts
18469
- var import_cjs$8 = require_cjs();
18470
- const logger$9 = getLogger();
18541
+ var import_cjs$9 = require_cjs();
18542
+ const logger$10 = getLogger();
18471
18543
  var Fetcher = class {
18472
18544
  constructor(endpoint, params, http) {
18473
18545
  this.endpoint = endpoint;
@@ -18491,7 +18563,7 @@ var Fetcher = class {
18491
18563
  this.hasMore = !!this.nextUrl;
18492
18564
  return result.data.filter(this.filter).map(this.mapper);
18493
18565
  }
18494
- logger$9.error("Failed to fetch entity");
18566
+ logger$10.error("Failed to fetch entity");
18495
18567
  return [];
18496
18568
  }
18497
18569
  async id(v) {
@@ -18532,10 +18604,10 @@ var EntityCollection = class extends Destroyable {
18532
18604
  this.values$.next(Array.from(this.collectionData.values()));
18533
18605
  };
18534
18606
  this._hasMore$ = this.createBehaviorSubject(true);
18535
- this._destroy$ = new import_cjs$8.Subject();
18607
+ this._destroy$ = new import_cjs$9.Subject();
18536
18608
  this.updateSubscription = this.update$.subscribe(this.upsertData);
18537
18609
  this.loading$.next(false);
18538
- this.hasMore$ = (0, import_cjs$8.defer)(() => (0, import_cjs$8.from)(this.init())).pipe((0, import_cjs$8.switchMap)(() => this._hasMore$), (0, import_cjs$8.distinctUntilChanged)(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this._destroy$));
18610
+ this.hasMore$ = (0, import_cjs$9.defer)(() => (0, import_cjs$9.from)(this.init())).pipe((0, import_cjs$9.switchMap)(() => this._hasMore$), (0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.shareReplay)(1), (0, import_cjs$9.takeUntil)(this._destroy$));
18539
18611
  }
18540
18612
  get loading() {
18541
18613
  return this.loading$.value;
@@ -18544,7 +18616,7 @@ var EntityCollection = class extends Destroyable {
18544
18616
  return this.fetchController.hasMore ?? true;
18545
18617
  }
18546
18618
  get updated$() {
18547
- return this.cachedObservable("updated$", () => this.loading$.pipe((0, import_cjs$8.distinctUntilChanged)(), (0, import_cjs$8.skip)(1), (0, import_cjs$8.filter)((loading) => !loading), (0, import_cjs$8.map)(() => void 0), (0, import_cjs$8.takeUntil)(this._destroy$)));
18619
+ return this.cachedObservable("updated$", () => this.loading$.pipe((0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.skip)(1), (0, import_cjs$9.filter)((loading) => !loading), (0, import_cjs$9.map)(() => void 0), (0, import_cjs$9.takeUntil)(this._destroy$)));
18548
18620
  }
18549
18621
  get values() {
18550
18622
  return Array.from(this.collectionData.values());
@@ -18563,7 +18635,7 @@ var EntityCollection = class extends Destroyable {
18563
18635
  this._hasMore$.next(this.fetchController.hasMore ?? false);
18564
18636
  this.loading$.next(false);
18565
18637
  } catch (error) {
18566
- logger$9.error(`Failed to fetch initial collection data`, error);
18638
+ logger$10.error(`Failed to fetch initial collection data`, error);
18567
18639
  this._hasMore$.next(this.fetchController.hasMore ?? false);
18568
18640
  this.loading$.next(false);
18569
18641
  this.onError?.(new CollectionFetchError("fetchMore", error));
@@ -18577,14 +18649,14 @@ var EntityCollection = class extends Destroyable {
18577
18649
  if (data) this.upsertData(data);
18578
18650
  return data;
18579
18651
  } catch (error) {
18580
- logger$9.error(`Failed to fetch data for (${String(key)}:${String(value)}) :`, error);
18652
+ logger$10.error(`Failed to fetch data for (${String(key)}:${String(value)}) :`, error);
18581
18653
  this.loading$.next(false);
18582
18654
  this.onError?.(new CollectionFetchError(`tryFetch(${String(key)})`, error));
18583
18655
  }
18584
18656
  }
18585
18657
  get$(id) {
18586
18658
  if (!this.observablesRegistry.has(id)) {
18587
- this.observablesRegistry.set(id, new import_cjs$8.ReplaySubject(1));
18659
+ this.observablesRegistry.set(id, new import_cjs$9.ReplaySubject(1));
18588
18660
  const data = this.collectionData.get(id);
18589
18661
  if (data) this.observablesRegistry.get(id)?.next(data);
18590
18662
  else this.tryFetch("id", id);
@@ -18608,9 +18680,9 @@ var EntityCollection = class extends Destroyable {
18608
18680
  }
18609
18681
  };
18610
18682
  var EntityCollectionTransformed = class {
18611
- constructor(originalCollection, filter$16 = (i) => !!i, mapper = (item) => item) {
18683
+ constructor(originalCollection, filter$17 = (i) => !!i, mapper = (item) => item) {
18612
18684
  this.originalCollection = originalCollection;
18613
- this.filter = filter$16;
18685
+ this.filter = filter$17;
18614
18686
  this.mapper = mapper;
18615
18687
  }
18616
18688
  get loading$() {
@@ -18629,15 +18701,15 @@ var EntityCollectionTransformed = class {
18629
18701
  return this.originalCollection.values.filter(this.filter).map(this.mapper);
18630
18702
  }
18631
18703
  get values$() {
18632
- return this._values$ ??= this.originalCollection.values$.pipe((0, import_cjs$8.map)((values) => values.filter(this.filter).map(this.mapper)));
18704
+ return this._values$ ??= this.originalCollection.values$.pipe((0, import_cjs$9.map)((values) => values.filter(this.filter).map(this.mapper)));
18633
18705
  }
18634
18706
  get$(id) {
18635
18707
  const original$ = this.originalCollection.get$(id);
18636
- return !original$ ? original$ : original$.pipe((0, import_cjs$8.pipe)((0, import_cjs$8.filter)(this.filter), (0, import_cjs$8.map)(this.mapper)));
18708
+ return !original$ ? original$ : original$.pipe((0, import_cjs$9.pipe)((0, import_cjs$9.filter)(this.filter), (0, import_cjs$9.map)(this.mapper)));
18637
18709
  }
18638
18710
  async find$(key, value) {
18639
18711
  const original$ = await this.originalCollection.find$(key, value);
18640
- return !original$ ? original$ : original$.pipe((0, import_cjs$8.pipe)((0, import_cjs$8.filter)(this.filter), (0, import_cjs$8.map)(this.mapper)));
18712
+ return !original$ ? original$ : original$.pipe((0, import_cjs$9.pipe)((0, import_cjs$9.filter)(this.filter), (0, import_cjs$9.map)(this.mapper)));
18641
18713
  }
18642
18714
  loadMore() {
18643
18715
  this.originalCollection.loadMore();
@@ -18649,7 +18721,7 @@ var EntityCollectionTransformed = class {
18649
18721
 
18650
18722
  //#endregion
18651
18723
  //#region src/core/entities/Address.ts
18652
- var import_cjs$7 = require_cjs();
18724
+ var import_cjs$8 = require_cjs();
18653
18725
  /**
18654
18726
  * Represents a contact or room in the directory.
18655
18727
  *
@@ -18667,8 +18739,8 @@ var Address = class extends Destroyable {
18667
18739
  if (this._conversationMessages.hasMore) this._conversationMessages.loadMore();
18668
18740
  return this._conversationMessages;
18669
18741
  };
18670
- this.textMessages$ = (0, import_cjs$7.defer)(this.initConversationMessages).pipe((0, import_cjs$7.map)(() => this.textMessage), (0, import_cjs$7.shareReplay)(1), (0, import_cjs$7.takeUntil)(this.destroyed$));
18671
- this.history$ = (0, import_cjs$7.defer)(this.initConversationMessages).pipe((0, import_cjs$7.map)(() => this.history), (0, import_cjs$7.shareReplay)(1), (0, import_cjs$7.takeUntil)(this.destroyed$));
18742
+ this.textMessages$ = (0, import_cjs$8.defer)(this.initConversationMessages).pipe((0, import_cjs$8.map)(() => this.textMessage), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this.destroyed$));
18743
+ this.history$ = (0, import_cjs$8.defer)(this.initConversationMessages).pipe((0, import_cjs$8.map)(() => this.history), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.takeUntil)(this.destroyed$));
18672
18744
  this._state$ = this.createBehaviorSubject(null);
18673
18745
  }
18674
18746
  /** @internal */
@@ -18703,7 +18775,7 @@ var Address = class extends Destroyable {
18703
18775
  }
18704
18776
  /** Observable of the human-readable display name. */
18705
18777
  get displayName$() {
18706
- return this.cachedObservable("displayName$", () => this._state$.pipe(filterNull(), (0, import_cjs$7.map)((state) => state.display_name), (0, import_cjs$7.takeUntil)(this.destroyed$)));
18778
+ return this.cachedObservable("displayName$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.map)((state) => state.display_name), (0, import_cjs$8.takeUntil)(this.destroyed$)));
18707
18779
  }
18708
18780
  /** Human-readable display name. */
18709
18781
  get displayName() {
@@ -18712,7 +18784,7 @@ var Address = class extends Destroyable {
18712
18784
  }
18713
18785
  /** Observable of the preview image URL. */
18714
18786
  get previewUrl$() {
18715
- return this.cachedObservable("previewUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$7.map)((state) => state.preview_url), (0, import_cjs$7.takeUntil)(this.destroyed$)));
18787
+ return this.cachedObservable("previewUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.map)((state) => state.preview_url), (0, import_cjs$8.takeUntil)(this.destroyed$)));
18716
18788
  }
18717
18789
  /** Preview image URL. */
18718
18790
  get previewUrl() {
@@ -18721,7 +18793,7 @@ var Address = class extends Destroyable {
18721
18793
  }
18722
18794
  /** Observable of the cover image URL. */
18723
18795
  get coverUrl$() {
18724
- return this.cachedObservable("coverUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$7.shareReplay)(1), (0, import_cjs$7.map)((state) => state.cover_url), (0, import_cjs$7.takeUntil)(this.destroyed$)));
18796
+ return this.cachedObservable("coverUrl$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.cover_url), (0, import_cjs$8.takeUntil)(this.destroyed$)));
18725
18797
  }
18726
18798
  /** Cover image URL. */
18727
18799
  get coverUrl() {
@@ -18730,7 +18802,7 @@ var Address = class extends Destroyable {
18730
18802
  }
18731
18803
  /** Observable of the underlying resource ID. */
18732
18804
  get resourceId$() {
18733
- return this.cachedObservable("resourceId$", () => this._state$.pipe(filterNull(), (0, import_cjs$7.shareReplay)(1), (0, import_cjs$7.map)((state) => state.resource_id), (0, import_cjs$7.takeUntil)(this.destroyed$)));
18805
+ return this.cachedObservable("resourceId$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.resource_id), (0, import_cjs$8.takeUntil)(this.destroyed$)));
18734
18806
  }
18735
18807
  /** Underlying resource ID. */
18736
18808
  get resourceId() {
@@ -18739,7 +18811,7 @@ var Address = class extends Destroyable {
18739
18811
  }
18740
18812
  /** Observable of the resource type (e.g. `'room'`, `'subscriber'`). */
18741
18813
  get type$() {
18742
- return this.cachedObservable("type$", () => this._state$.pipe(filterNull(), (0, import_cjs$7.shareReplay)(1), (0, import_cjs$7.map)((state) => state.type), (0, import_cjs$7.takeUntil)(this.destroyed$)));
18814
+ return this.cachedObservable("type$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.type), (0, import_cjs$8.takeUntil)(this.destroyed$)));
18743
18815
  }
18744
18816
  /** Resource type (e.g. `'room'`, `'subscriber'`). */
18745
18817
  get type() {
@@ -18748,7 +18820,7 @@ var Address = class extends Destroyable {
18748
18820
  }
18749
18821
  /** Observable of available communication channels (audio, video, messaging). */
18750
18822
  get channels$() {
18751
- return this.cachedObservable("channels$", () => this._state$.pipe(filterNull(), (0, import_cjs$7.shareReplay)(1), (0, import_cjs$7.map)((state) => state.channels), (0, import_cjs$7.takeUntil)(this.destroyed$)));
18823
+ return this.cachedObservable("channels$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.channels), (0, import_cjs$8.takeUntil)(this.destroyed$)));
18752
18824
  }
18753
18825
  /** Available communication channels. */
18754
18826
  get channels() {
@@ -18762,7 +18834,7 @@ var Address = class extends Destroyable {
18762
18834
  }
18763
18835
  /** Observable indicating whether the address (room) is locked. */
18764
18836
  get locked$() {
18765
- return this.cachedObservable("locked$", () => this._state$.pipe(filterNull(), (0, import_cjs$7.shareReplay)(1), (0, import_cjs$7.map)((state) => state.locked), (0, import_cjs$7.takeUntil)(this.destroyed$)));
18837
+ return this.cachedObservable("locked$", () => this._state$.pipe(filterNull(), (0, import_cjs$8.shareReplay)(1), (0, import_cjs$8.map)((state) => state.locked), (0, import_cjs$8.takeUntil)(this.destroyed$)));
18766
18838
  }
18767
18839
  /**
18768
18840
  * Sends a text message to this address.
@@ -18828,14 +18900,14 @@ var Address = class extends Destroyable {
18828
18900
 
18829
18901
  //#endregion
18830
18902
  //#region src/core/utils.ts
18831
- var import_cjs$6 = require_cjs();
18832
- const logger$8 = getLogger();
18903
+ var import_cjs$7 = require_cjs();
18904
+ const logger$9 = getLogger();
18833
18905
  const isRPCConnectResult = (e) => {
18834
- logger$8.debug("isRPCConnectResult check:", e);
18906
+ logger$9.debug("isRPCConnectResult check:", e);
18835
18907
  if (!e || typeof e !== "object") return false;
18836
18908
  const result = e;
18837
18909
  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";
18838
- logger$8.debug("isRPCConnectResult check result:", is);
18910
+ logger$9.debug("isRPCConnectResult check result:", is);
18839
18911
  return is;
18840
18912
  };
18841
18913
  var PendingRPC = class PendingRPC {
@@ -18844,7 +18916,7 @@ var PendingRPC = class PendingRPC {
18844
18916
  }
18845
18917
  constructor(request, responses$, options) {
18846
18918
  this.id = v4_default();
18847
- logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}: method:${request.method}] Creating PendingRPC`);
18919
+ logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}: method:${request.method}] Creating PendingRPC`);
18848
18920
  this.request = request;
18849
18921
  const timeoutMs = options?.timeoutMs ?? PendingRPC.defaultTimeoutMs;
18850
18922
  const signal = options?.signal;
@@ -18854,38 +18926,38 @@ var PendingRPC = class PendingRPC {
18854
18926
  return;
18855
18927
  }
18856
18928
  let isSettled = false;
18857
- const subscription = (0, import_cjs$6.race)(responses$.pipe((0, import_cjs$6.filter)((result) => result.id === request.id), (0, import_cjs$6.take)(1)), new import_cjs$6.Observable((subscriber) => {
18858
- const timer$2 = setTimeout(() => {
18929
+ const subscription = (0, import_cjs$7.race)(responses$.pipe((0, import_cjs$7.filter)((result) => result.id === request.id), (0, import_cjs$7.take)(1)), new import_cjs$7.Observable((subscriber) => {
18930
+ const timer$3 = setTimeout(() => {
18859
18931
  subscriber.error(new RPCTimeoutError(request.id, timeoutMs));
18860
18932
  }, timeoutMs);
18861
- return () => clearTimeout(timer$2);
18862
- }), signal ? new import_cjs$6.Observable((subscriber) => {
18933
+ return () => clearTimeout(timer$3);
18934
+ }), signal ? new import_cjs$7.Observable((subscriber) => {
18863
18935
  const abortHandler = () => {
18864
18936
  subscriber.error(new DOMException("The operation was aborted", "AbortError"));
18865
18937
  };
18866
18938
  signal.addEventListener("abort", abortHandler);
18867
18939
  return () => signal.removeEventListener("abort", abortHandler);
18868
- }) : import_cjs$6.NEVER).subscribe({
18940
+ }) : import_cjs$7.NEVER).subscribe({
18869
18941
  next: (response) => {
18870
18942
  isSettled = true;
18871
18943
  if (response.error) {
18872
18944
  const rpcError = new JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
18873
- logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
18945
+ logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
18874
18946
  reject(rpcError);
18875
18947
  } else {
18876
- logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
18948
+ logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
18877
18949
  resolve(response);
18878
18950
  }
18879
18951
  subscription.unsubscribe();
18880
18952
  },
18881
18953
  error: (error) => {
18882
- logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with error:`, error);
18954
+ logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with error:`, error);
18883
18955
  isSettled = true;
18884
18956
  reject(error);
18885
18957
  subscription.unsubscribe();
18886
18958
  },
18887
18959
  complete: () => {
18888
- logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
18960
+ logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
18889
18961
  if (!isSettled) reject(new RPCTimeoutError(request.id, timeoutMs));
18890
18962
  subscription.unsubscribe();
18891
18963
  }
@@ -18905,8 +18977,8 @@ var PendingRPC = class PendingRPC {
18905
18977
 
18906
18978
  //#endregion
18907
18979
  //#region src/managers/ClientSessionManager.ts
18908
- var import_cjs$5 = require_cjs();
18909
- const logger$7 = getLogger();
18980
+ var import_cjs$6 = require_cjs();
18981
+ const logger$8 = getLogger();
18910
18982
  const getAddressSearchURI = (options) => {
18911
18983
  const to = options.to?.split("?")[0];
18912
18984
  const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
@@ -18941,10 +19013,10 @@ var ClientSessionManager = class extends Destroyable {
18941
19013
  this._iceServers$ = this.createBehaviorSubject([]);
18942
19014
  attachManager.setSession(this);
18943
19015
  this.callFactory = new CallFactory(this, deviceController, attachManager, webRTCApiProvider, networkChange$);
18944
- this.initialized$ = (0, import_cjs$5.defer)(() => (0, import_cjs$5.from)(this.init())).pipe((0, import_cjs$5.shareReplay)(1), (0, import_cjs$5.takeUntil)(this.destroyed$));
19016
+ this.initialized$ = (0, import_cjs$6.defer)(() => (0, import_cjs$6.from)(this.init())).pipe((0, import_cjs$6.shareReplay)(1), (0, import_cjs$6.takeUntil)(this.destroyed$));
18945
19017
  }
18946
19018
  get incomingCalls$() {
18947
- return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, import_cjs$5.map)((calls) => calls.filter((call) => call.direction === "inbound"))));
19019
+ return this.cachedObservable("incomingCalls$", () => this.calls$.pipe((0, import_cjs$6.map)((calls) => calls.filter((call) => call.direction === "inbound"))));
18948
19020
  }
18949
19021
  get incomingCalls() {
18950
19022
  return Object.values(this._calls$.value).filter((call) => call.direction === "inbound");
@@ -18956,7 +19028,7 @@ var ClientSessionManager = class extends Destroyable {
18956
19028
  return this._subscriberInfo$.value;
18957
19029
  }
18958
19030
  get calls$() {
18959
- return this.cachedObservable("calls$", () => this._calls$.pipe((0, import_cjs$5.map)((calls) => Object.values(calls))));
19031
+ return this.cachedObservable("calls$", () => this._calls$.pipe((0, import_cjs$6.map)((calls) => Object.values(calls))));
18960
19032
  }
18961
19033
  get calls() {
18962
19034
  return Object.values(this._calls$.value);
@@ -19000,7 +19072,7 @@ var ClientSessionManager = class extends Destroyable {
19000
19072
  try {
19001
19073
  return await this.transport.execute(request, options);
19002
19074
  } catch (error) {
19003
- logger$7.debug("[Session] Execute Error", error);
19075
+ logger$8.debug("[Session] Execute Error", error);
19004
19076
  this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
19005
19077
  throw error;
19006
19078
  }
@@ -19014,40 +19086,40 @@ var ClientSessionManager = class extends Destroyable {
19014
19086
  return true;
19015
19087
  }
19016
19088
  setupMessageHandlers() {
19017
- logger$7.debug("[Session] Setting up message handlers");
19089
+ logger$8.debug("[Session] Setting up message handlers");
19018
19090
  this.subscribeTo(this.authStateEvent$, async (authStateEvent) => {
19019
- logger$7.debug("[Session] Authorization state event received:", authStateEvent);
19091
+ logger$8.debug("[Session] Authorization state event received:", authStateEvent);
19020
19092
  try {
19021
19093
  await this.updateAuthorizationStateInStorage(authStateEvent.authorization_state);
19022
19094
  } catch (error) {
19023
- logger$7.error("[Session] Failed to handle authorization state update:", error);
19095
+ logger$8.error("[Session] Failed to handle authorization state update:", error);
19024
19096
  this._errors$.next(new AuthStateHandlerError(error));
19025
19097
  }
19026
19098
  });
19027
- this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$5.filter)((status) => status === "connected"), (0, import_cjs$5.exhaustMap)(() => {
19028
- logger$7.debug("[Session] Connection established, initiating authentication");
19029
- return (0, import_cjs$5.from)(this.authenticate()).pipe((0, import_cjs$5.catchError)((error) => {
19099
+ this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$6.filter)((status) => status === "connected"), (0, import_cjs$6.exhaustMap)(() => {
19100
+ logger$8.debug("[Session] Connection established, initiating authentication");
19101
+ return (0, import_cjs$6.from)(this.authenticate()).pipe((0, import_cjs$6.catchError)((error) => {
19030
19102
  this.handleAuthenticationError(error).catch((err) => {
19031
- logger$7.error("[Session] Error handling authentication failure:", err);
19103
+ logger$8.error("[Session] Error handling authentication failure:", err);
19032
19104
  });
19033
- return import_cjs$5.EMPTY;
19105
+ return import_cjs$6.EMPTY;
19034
19106
  }));
19035
19107
  })), void 0);
19036
19108
  this.subscribeTo(this.vertoInvite$, async (invite) => {
19037
- logger$7.debug("[Session] Verto invite received:", invite);
19109
+ logger$8.debug("[Session] Verto invite received:", invite);
19038
19110
  try {
19039
19111
  await this.createInboundCall(invite);
19040
19112
  } catch (error) {
19041
- logger$7.error("[Session] Error handling Verto invite:", error);
19113
+ logger$8.error("[Session] Error handling Verto invite:", error);
19042
19114
  this._errors$.next(new VertoInviteHandlerError(error));
19043
19115
  }
19044
19116
  });
19045
19117
  this.subscribeTo(this.vertoAttach$, async (attach) => {
19046
- logger$7.debug("[Session] Verto attach received:", attach);
19118
+ logger$8.debug("[Session] Verto attach received:", attach);
19047
19119
  try {
19048
19120
  await this.handleVertoAttach(attach);
19049
19121
  } catch (error) {
19050
- logger$7.error("[Session] Error handling Verto attach:", error);
19122
+ logger$8.error("[Session] Error handling Verto attach:", error);
19051
19123
  this._errors$.next(new VertoAttachHandlerError(error));
19052
19124
  }
19053
19125
  });
@@ -19057,49 +19129,49 @@ var ClientSessionManager = class extends Destroyable {
19057
19129
  const storedState = await this.storage.getItem(this.authorizationStateKey);
19058
19130
  this.authorizationState$.next(storedState ?? void 0);
19059
19131
  } catch (error) {
19060
- logger$7.error("Failed to retrieve authorization state from storage:", error);
19132
+ logger$8.error("Failed to retrieve authorization state from storage:", error);
19061
19133
  this.authorizationState$.next(void 0);
19062
19134
  }
19063
19135
  }
19064
19136
  async updateAuthorizationStateInStorage(authorizationState) {
19065
19137
  if (!authorizationState) {
19066
- logger$7.debug("[Session] Removing authorization state from storage");
19138
+ logger$8.debug("[Session] Removing authorization state from storage");
19067
19139
  try {
19068
19140
  await this.storage.removeItem(this.authorizationStateKey);
19069
19141
  this.authorizationState$.next(void 0);
19070
19142
  } catch (error) {
19071
- logger$7.error("Failed to remove authorization state from storage:", error);
19143
+ logger$8.error("Failed to remove authorization state from storage:", error);
19072
19144
  throw error;
19073
19145
  }
19074
19146
  return;
19075
19147
  }
19076
19148
  try {
19077
- logger$7.debug("[Session] Updating authorization state in storage");
19149
+ logger$8.debug("[Session] Updating authorization state in storage");
19078
19150
  await this.storage.setItem(this.authorizationStateKey, authorizationState);
19079
19151
  this.authorizationState$.next(authorizationState);
19080
19152
  } catch (error) {
19081
- logger$7.error("Failed to retrieve authorization state from storage:", error);
19153
+ logger$8.error("Failed to retrieve authorization state from storage:", error);
19082
19154
  throw error;
19083
19155
  }
19084
19156
  }
19085
19157
  get authStateEvent$() {
19086
- return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$5.tap)((msg) => {
19087
- logger$7.debug("[Session] Received incoming message:", msg);
19088
- }), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$5.tap)((event) => {
19089
- logger$7.debug("[Session] Authorization state event received:", event.authorization_state);
19158
+ return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$6.tap)((msg) => {
19159
+ logger$8.debug("[Session] Received incoming message:", msg);
19160
+ }), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$6.tap)((event) => {
19161
+ logger$8.debug("[Session] Authorization state event received:", event.authorization_state);
19090
19162
  })));
19091
19163
  }
19092
19164
  get signalingEvent$() {
19093
- return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(filterAs(isSignalwireRequest, "params"), (0, import_cjs$5.share)()));
19165
+ return this.cachedObservable("signalingEvent$", () => this.transport.incomingEvent$.pipe(filterAs(isSignalwireRequest, "params"), (0, import_cjs$6.share)()));
19094
19166
  }
19095
19167
  get vertoInvite$() {
19096
- return this.cachedObservable("vertoInvite$", () => this.signalingEvent$.pipe((0, import_cjs$5.filter)(isWebrtcMessageMetadata), (0, import_cjs$5.filter)((event) => isVertoInviteMessage(event.params)), (0, import_cjs$5.map)((event) => ({
19168
+ return this.cachedObservable("vertoInvite$", () => this.signalingEvent$.pipe((0, import_cjs$6.filter)(isWebrtcMessageMetadata), (0, import_cjs$6.filter)((event) => isVertoInviteMessage(event.params)), (0, import_cjs$6.map)((event) => ({
19097
19169
  node_id: event.node_id,
19098
19170
  ...event.params.params
19099
19171
  }))));
19100
19172
  }
19101
19173
  get vertoAttach$() {
19102
- return this.cachedObservable("vertoAttach$", () => this.signalingEvent$.pipe((0, import_cjs$5.filter)(isWebrtcMessageMetadata), (0, import_cjs$5.filter)((event) => isVertoAttachMessage(event.params)), (0, import_cjs$5.map)((event) => ({
19174
+ return this.cachedObservable("vertoAttach$", () => this.signalingEvent$.pipe((0, import_cjs$6.filter)(isWebrtcMessageMetadata), (0, import_cjs$6.filter)((event) => isVertoAttachMessage(event.params)), (0, import_cjs$6.map)((event) => ({
19103
19175
  node_id: event.node_id,
19104
19176
  ...event.params.params
19105
19177
  }))));
@@ -19119,20 +19191,20 @@ var ClientSessionManager = class extends Destroyable {
19119
19191
  return { jwt_token: credential.token };
19120
19192
  }
19121
19193
  async connect() {
19122
- await (0, import_cjs$5.firstValueFrom)(this.initialized$);
19194
+ await (0, import_cjs$6.firstValueFrom)(this.initialized$);
19123
19195
  await this.transport.connect();
19124
- await (0, import_cjs$5.firstValueFrom)(this.authenticated$.pipe((0, import_cjs$5.takeUntil)(this.destroyed$), (0, import_cjs$5.filter)(Boolean), (0, import_cjs$5.take)(1), (0, import_cjs$5.timeout)({ first: 15e3 })));
19196
+ await (0, import_cjs$6.firstValueFrom)(this.authenticated$.pipe((0, import_cjs$6.takeUntil)(this.destroyed$), (0, import_cjs$6.filter)(Boolean), (0, import_cjs$6.take)(1), (0, import_cjs$6.timeout)({ first: 15e3 })));
19125
19197
  }
19126
19198
  async handleAuthenticationError(error) {
19127
- logger$7.error("Authentication error:", error);
19199
+ logger$8.error("Authentication error:", error);
19128
19200
  const isRecoverableAuthError = error instanceof JSONRPCError && (error.code === RPC_ERROR_REQUESTER_VALIDATION_FAILED || error.code === RPC_ERROR_INVALID_PARAMS || error.code === RPC_ERROR_AUTHENTICATION_FAILED);
19129
- const hasStoredState = await (0, import_cjs$5.firstValueFrom)(this.authorizationState$.pipe((0, import_cjs$5.take)(1))) !== void 0;
19201
+ const hasStoredState = await (0, import_cjs$6.firstValueFrom)(this.authorizationState$.pipe((0, import_cjs$6.take)(1))) !== void 0;
19130
19202
  if (isRecoverableAuthError && hasStoredState) {
19131
- logger$7.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");
19203
+ logger$8.debug("[Session] Recoverable auth error — cleaning up stored state and reconnecting fresh");
19132
19204
  try {
19133
19205
  await this.cleanupStoredConnectionParams();
19134
19206
  } catch (cleanupError) {
19135
- logger$7.error("Failed to cleanup stored connection params:", cleanupError);
19207
+ logger$8.error("Failed to cleanup stored connection params:", cleanupError);
19136
19208
  } finally {
19137
19209
  this.transport.reconnect();
19138
19210
  }
@@ -19147,44 +19219,44 @@ var ClientSessionManager = class extends Destroyable {
19147
19219
  try {
19148
19220
  await this.storage.setItem(this.authorizationStateKey, authorization_state);
19149
19221
  } catch (error) {
19150
- logger$7.error("Failed to update authorization state in storage:", error);
19222
+ logger$8.error("Failed to update authorization state in storage:", error);
19151
19223
  this._errors$.next(new AuthStateHandlerError(error));
19152
19224
  }
19153
19225
  }
19154
19226
  async reauthenticate(token, dpopToken, options) {
19155
- logger$7.debug("[Session] Re-authenticating session");
19227
+ logger$8.debug("[Session] Re-authenticating session");
19156
19228
  try {
19157
19229
  let resolvedDpopToken = dpopToken;
19158
19230
  if (!resolvedDpopToken && this.dpopManager?.initialized) try {
19159
19231
  resolvedDpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
19160
19232
  } catch (error) {
19161
19233
  if (this._clientBound) throw error;
19162
- logger$7.warn("[Session] Failed to create DPoP proof for reauthenticate:", error);
19234
+ logger$8.warn("[Session] Failed to create DPoP proof for reauthenticate:", error);
19163
19235
  }
19164
19236
  const request = RPCReauthenticate({
19165
19237
  project: this._authorization$.value?.project_id ?? "",
19166
19238
  jwt_token: token,
19167
19239
  ...resolvedDpopToken ? { dpop_token: resolvedDpopToken } : {}
19168
19240
  });
19169
- await (0, import_cjs$5.lastValueFrom)((0, import_cjs$5.from)(this.transport.execute(request)).pipe(throwOnRPCError(), (0, import_cjs$5.take)(1), (0, import_cjs$5.catchError)((err) => {
19170
- logger$7.error("[Session] Re-authentication RPC failed:", err);
19241
+ await (0, import_cjs$6.lastValueFrom)((0, import_cjs$6.from)(this.transport.execute(request)).pipe(throwOnRPCError(), (0, import_cjs$6.take)(1), (0, import_cjs$6.catchError)((err) => {
19242
+ logger$8.error("[Session] Re-authentication RPC failed:", err);
19171
19243
  throw err;
19172
19244
  })));
19173
19245
  if (options?.clientBound) this._clientBound = true;
19174
- logger$7.debug("[Session] Re-authentication successful, updating stored auth state");
19246
+ logger$8.debug("[Session] Re-authentication successful, updating stored auth state");
19175
19247
  } catch (error) {
19176
- logger$7.error("[Session] Re-authentication failed:", error);
19248
+ logger$8.error("[Session] Re-authentication failed:", error);
19177
19249
  this._errors$.next(new AuthStateHandlerError(error));
19178
19250
  throw error;
19179
19251
  }
19180
19252
  }
19181
19253
  async authenticate() {
19182
- logger$7.debug("[Session] Starting authentication process");
19183
- const persistedParams = await (0, import_cjs$5.firstValueFrom)((0, import_cjs$5.combineLatest)({
19254
+ logger$8.debug("[Session] Starting authentication process");
19255
+ const persistedParams = await (0, import_cjs$6.firstValueFrom)((0, import_cjs$6.combineLatest)({
19184
19256
  protocol: this.transport.protocol$,
19185
19257
  authorization_state: this.authorizationState$
19186
- }).pipe((0, import_cjs$5.take)(1)));
19187
- logger$7.debug("[Session] Persisted params:\n", {
19258
+ }).pipe((0, import_cjs$6.take)(1)));
19259
+ logger$8.debug("[Session] Persisted params:\n", {
19188
19260
  protocol: persistedParams.protocol,
19189
19261
  authStateLength: persistedParams.authorization_state?.length
19190
19262
  });
@@ -19192,16 +19264,16 @@ var ClientSessionManager = class extends Destroyable {
19192
19264
  const storedToken = this.getCredential().token;
19193
19265
  const isReconnect = hasReconnectState && storedToken;
19194
19266
  let dpopToken;
19195
- if (isReconnect) logger$7.debug("[Session] Reconnecting with stored jwt_token + authorization_state");
19267
+ if (isReconnect) logger$8.debug("[Session] Reconnecting with stored jwt_token + authorization_state");
19196
19268
  else if (this.onBeforeReconnect && this._clientBound) {
19197
- logger$7.debug("[Session] Refreshing credentials before fresh connect");
19269
+ logger$8.debug("[Session] Refreshing credentials before fresh connect");
19198
19270
  await this.onBeforeReconnect();
19199
19271
  }
19200
19272
  if ((!isReconnect || this._clientBound) && this.dpopManager?.initialized) try {
19201
19273
  dpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.connect" });
19202
19274
  } catch (error) {
19203
19275
  if (this._clientBound) throw error;
19204
- logger$7.warn("[Session] Failed to create DPoP proof for connect, proceeding without:", error);
19276
+ logger$8.warn("[Session] Failed to create DPoP proof for connect, proceeding without:", error);
19205
19277
  }
19206
19278
  const rpcConnectRequest = RPCConnect({
19207
19279
  authentication: isReconnect ? { jwt_token: storedToken } : this.authentication,
@@ -19217,13 +19289,13 @@ var ClientSessionManager = class extends Destroyable {
19217
19289
  protocol: persistedParams.protocol
19218
19290
  } : {}
19219
19291
  });
19220
- const response = await (0, import_cjs$5.lastValueFrom)((0, import_cjs$5.from)(this.transport.execute(rpcConnectRequest)).pipe(throwOnRPCError(), (0, import_cjs$5.map)((res) => res.result), (0, import_cjs$5.filter)(isRPCConnectResult), (0, import_cjs$5.tap)(() => {
19221
- logger$7.debug("[Session] Response passed filter, processing authentication result");
19222
- }), (0, import_cjs$5.take)(1), (0, import_cjs$5.catchError)((err) => {
19223
- logger$7.error("[Session] Authentication RPC failed:", err);
19292
+ const response = await (0, import_cjs$6.lastValueFrom)((0, import_cjs$6.from)(this.transport.execute(rpcConnectRequest)).pipe(throwOnRPCError(), (0, import_cjs$6.map)((res) => res.result), (0, import_cjs$6.filter)(isRPCConnectResult), (0, import_cjs$6.tap)(() => {
19293
+ logger$8.debug("[Session] Response passed filter, processing authentication result");
19294
+ }), (0, import_cjs$6.take)(1), (0, import_cjs$6.catchError)((err) => {
19295
+ logger$8.error("[Session] Authentication RPC failed:", err);
19224
19296
  throw err;
19225
19297
  })));
19226
- logger$7.debug("[Session] Processing authentication result:", {
19298
+ logger$8.debug("[Session] Processing authentication result:", {
19227
19299
  hasProtocol: !!response.protocol,
19228
19300
  hasAuthorization: !!response.authorization,
19229
19301
  hasIceServers: !!response.ice_servers
@@ -19232,7 +19304,7 @@ var ClientSessionManager = class extends Destroyable {
19232
19304
  this._authorization$.next(response.authorization);
19233
19305
  this._iceServers$.next(response.ice_servers ?? []);
19234
19306
  this._authenticated$.next(true);
19235
- logger$7.debug("[Session] Authentication completed successfully");
19307
+ logger$8.debug("[Session] Authentication completed successfully");
19236
19308
  }
19237
19309
  async disconnect() {
19238
19310
  this.transport.disconnect();
@@ -19251,7 +19323,7 @@ var ClientSessionManager = class extends Destroyable {
19251
19323
  displayDirection: invite.display_direction,
19252
19324
  userVariables: invite.userVariables
19253
19325
  });
19254
- await (0, import_cjs$5.firstValueFrom)(callSession.status$);
19326
+ await (0, import_cjs$6.firstValueFrom)(callSession.status$);
19255
19327
  this._calls$.next({
19256
19328
  [`${callSession.id}`]: callSession,
19257
19329
  ...this._calls$.value
@@ -19269,11 +19341,11 @@ var ClientSessionManager = class extends Destroyable {
19269
19341
  async handleVertoAttach(attach) {
19270
19342
  const { callID } = attach;
19271
19343
  if (callID in this._calls$.value) {
19272
- logger$7.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
19344
+ logger$8.debug(`[Session] Verto attach for existing call ${callID}, deferring to per-call handler`);
19273
19345
  return;
19274
19346
  }
19275
19347
  const storedOptions = this.attachManager.consumePendingAttachment(callID);
19276
- logger$7.debug(`[Session] Creating reattached call for callID: ${callID}`);
19348
+ logger$8.debug(`[Session] Creating reattached call for callID: ${callID}`);
19277
19349
  const callSession = await this.createCall({
19278
19350
  nodeId: attach.node_id,
19279
19351
  callId: callID,
@@ -19284,7 +19356,7 @@ var ClientSessionManager = class extends Destroyable {
19284
19356
  reattach: true,
19285
19357
  ...storedOptions
19286
19358
  });
19287
- await (0, import_cjs$5.firstValueFrom)(callSession.status$);
19359
+ await (0, import_cjs$6.firstValueFrom)(callSession.status$);
19288
19360
  this._calls$.next({
19289
19361
  [`${callSession.id}`]: callSession,
19290
19362
  ...this._calls$.value
@@ -19298,16 +19370,16 @@ var ClientSessionManager = class extends Destroyable {
19298
19370
  to: destinationURI,
19299
19371
  ...options
19300
19372
  });
19301
- await (0, import_cjs$5.firstValueFrom)((0, import_cjs$5.race)(callSession.selfId$.pipe((0, import_cjs$5.filter)((id) => Boolean(id)), (0, import_cjs$5.take)(1), (0, import_cjs$5.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, import_cjs$5.take)(1), (0, import_cjs$5.switchMap)((callError) => (0, import_cjs$5.throwError)(() => callError.error)))));
19373
+ await (0, import_cjs$6.firstValueFrom)((0, import_cjs$6.race)(callSession.selfId$.pipe((0, import_cjs$6.filter)((id) => Boolean(id)), (0, import_cjs$6.take)(1), (0, import_cjs$6.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, import_cjs$6.take)(1), (0, import_cjs$6.switchMap)((callError) => (0, import_cjs$6.throwError)(() => callError.error)))));
19302
19374
  this._calls$.next({
19303
19375
  [`${callSession.id}`]: callSession,
19304
19376
  ...this._calls$.value
19305
19377
  });
19306
19378
  return callSession;
19307
19379
  } catch (error) {
19308
- logger$7.error("[Session] Error creating outbound call:", error);
19380
+ logger$8.error("[Session] Error creating outbound call:", error);
19309
19381
  callSession?.destroy();
19310
- const callError = new CallCreateError(error instanceof import_cjs$5.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
19382
+ const callError = new CallCreateError(error instanceof import_cjs$6.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
19311
19383
  this._errors$.next(callError);
19312
19384
  throw callError;
19313
19385
  }
@@ -19323,16 +19395,16 @@ var ClientSessionManager = class extends Destroyable {
19323
19395
  address = this._directory.get(addressId);
19324
19396
  if (!address) throw new DependencyError(`Address ID: ${addressId} not found`);
19325
19397
  } catch {
19326
- logger$7.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
19398
+ logger$8.warn(`[Session] Directory lookup failed for ${addressURI}, proceeding with raw URI`);
19327
19399
  }
19328
19400
  const callSession = this.callFactory.createCall(address, { ...options });
19329
- this.subscribeTo(callSession.status$.pipe((0, import_cjs$5.filter)((status) => status === "destroyed"), (0, import_cjs$5.take)(1)), () => {
19401
+ this.subscribeTo(callSession.status$.pipe((0, import_cjs$6.filter)((status) => status === "destroyed"), (0, import_cjs$6.take)(1)), () => {
19330
19402
  const { [`${callSession.id}`]: _, ...remainingCalls } = this._calls$.value;
19331
19403
  this._calls$.next(remainingCalls);
19332
19404
  });
19333
19405
  return callSession;
19334
19406
  } catch (error) {
19335
- logger$7.error("[Session] Error creating call session:", error);
19407
+ logger$8.error("[Session] Error creating call session:", error);
19336
19408
  throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
19337
19409
  }
19338
19410
  }
@@ -19380,8 +19452,8 @@ const isString = (obj) => typeof obj === "string";
19380
19452
 
19381
19453
  //#endregion
19382
19454
  //#region src/managers/ConversationsManager.ts
19383
- var import_cjs$4 = require_cjs();
19384
- const logger$6 = getLogger();
19455
+ var import_cjs$5 = require_cjs();
19456
+ const logger$7 = getLogger();
19385
19457
  var ConversationMessagesFetcher = class extends Fetcher {
19386
19458
  constructor(groupId, http) {
19387
19459
  super(`/api/fabric/conversations/${groupId}/messages`, "page_size=100", http);
@@ -19421,13 +19493,13 @@ var ConversationsManager = class {
19421
19493
  }
19422
19494
  throw new ConversationError("Join Failed - Unexpected response");
19423
19495
  } catch (error) {
19424
- logger$6.error("[ConversationsManager] Failed to join conversation:", error);
19496
+ logger$7.error("[ConversationsManager] Failed to join conversation:", error);
19425
19497
  throw error;
19426
19498
  }
19427
19499
  }
19428
19500
  async getConversationMessageCollection(addressId) {
19429
19501
  const groupId = this.groupIds.get(addressId) ?? await this.join(addressId);
19430
- return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$4.tap)((event) => logger$6.debug("[ConversationsManager ] Conversation Event:", event)), (0, import_cjs$4.map)((params) => ({ ...params }))), this.http, this.onError));
19502
+ return Promise.resolve(new ConversationMessageCollection(groupId, this.clientSession.signalingEvent$.pipe(filterAs(isConversationMessageMetadata, "params"), (0, import_cjs$5.tap)((event) => logger$7.debug("[ConversationsManager ] Conversation Event:", event)), (0, import_cjs$5.map)((params) => ({ ...params }))), this.http, this.onError));
19431
19503
  }
19432
19504
  async sendText(text, destinationAddressId) {
19433
19505
  const groupId = this.groupIds.get(destinationAddressId) ?? await this.join(destinationAddressId);
@@ -19444,12 +19516,222 @@ var ConversationsManager = class {
19444
19516
  })).ok) return;
19445
19517
  throw new ConversationError("Send Text Failed - Unexpected response");
19446
19518
  } catch (error) {
19447
- logger$6.error("[ConversationsManager] Failed to send text message:", error);
19519
+ logger$7.error("[ConversationsManager] Failed to send text message:", error);
19448
19520
  throw error;
19449
19521
  }
19450
19522
  }
19451
19523
  };
19452
19524
 
19525
+ //#endregion
19526
+ //#region src/managers/DeviceTokenManager.ts
19527
+ var import_cjs$4 = require_cjs();
19528
+ const logger$6 = getLogger();
19529
+ /**
19530
+ * Resolves the token expiry timestamp (epoch seconds) using a 3-tier priority chain:
19531
+ * 1. `data.expires_at` — server-provided absolute timestamp
19532
+ * 2. `data.expires_in` — server-provided relative lifetime
19533
+ * 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN` with a warning
19534
+ */
19535
+ function resolveExpiresAt(data) {
19536
+ if (data.expires_at) return data.expires_at;
19537
+ if (data.expires_in) return Math.floor(Date.now() / 1e3) + data.expires_in;
19538
+ logger$6.warn("[DeviceToken] Could not determine token expiry, using default");
19539
+ return Math.floor(Date.now() / 1e3) + DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
19540
+ }
19541
+ /**
19542
+ * Resolves the token TTL in seconds from a fresh response.
19543
+ * Called at token receive time so `expires_at - now` reflects the original lifetime.
19544
+ *
19545
+ * 1. `data.expires_in` — server-provided TTL directly
19546
+ * 2. `data.expires_at - now` — derive TTL from absolute timestamp
19547
+ * 3. Fallback to `DEVICE_TOKEN_DEFAULT_EXPIRE_IN`
19548
+ */
19549
+ function resolveExpireIn(data) {
19550
+ if (data.expires_in) return data.expires_in;
19551
+ if (data.expires_at) return Math.max(data.expires_at - Math.floor(Date.now() / 1e3), 1);
19552
+ return DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
19553
+ }
19554
+ /**
19555
+ * Manages the Client Bound SAT lifecycle: activation, token exchange,
19556
+ * reauthentication, and automatic refresh scheduling.
19557
+ *
19558
+ * Extends {@link Destroyable} for automatic RxJS subscription and subject cleanup.
19559
+ * Uses a reactive pipeline (`BehaviorSubject` + `switchMap(timer())`) instead of
19560
+ * raw `setTimeout` for refresh scheduling.
19561
+ */
19562
+ var DeviceTokenManager = class extends Destroyable {
19563
+ constructor(dpopManager, http, errorHandler, getCredential) {
19564
+ super();
19565
+ this.dpopManager = dpopManager;
19566
+ this.http = http;
19567
+ this.errorHandler = errorHandler;
19568
+ this.getCredential = getCredential;
19569
+ this._currentToken$ = this.createBehaviorSubject(null);
19570
+ this._refreshInProgress = false;
19571
+ this._effectiveExpireIn = DEVICE_TOKEN_DEFAULT_EXPIRE_IN;
19572
+ this.subscribeTo(this._currentToken$.pipe((0, import_cjs$4.filter)(Boolean), (0, import_cjs$4.switchMap)((tokenData) => {
19573
+ const expiresAt = resolveExpiresAt(tokenData);
19574
+ const refreshIn = Math.max(expiresAt * 1e3 - Date.now() - DEVICE_TOKEN_REFRESH_BUFFER_MS, 1e3);
19575
+ logger$6.debug(`[DeviceToken] Scheduling Client Bound SAT refresh in ${refreshIn}ms`);
19576
+ return (0, import_cjs$4.timer)(refreshIn);
19577
+ })), () => {
19578
+ this.executeRefresh();
19579
+ });
19580
+ }
19581
+ /** Current token TTL in milliseconds. Used to extend cached credential expiry on refresh. */
19582
+ get effectiveExpireIn() {
19583
+ return this._effectiveExpireIn;
19584
+ }
19585
+ /**
19586
+ * Activates the Client Bound SAT flow when the subscriber's token has
19587
+ * `sat:refresh` scope.
19588
+ *
19589
+ * Steps:
19590
+ * 1. Check subscriber's `sat_claims` for `sat:refresh` scope
19591
+ * 2. Call `/api/fabric/subscriber/devices/token` with a DPoP proof
19592
+ * 3. Reauthenticate the session with the Client Bound SAT + DPoP proof
19593
+ * 4. Emit token to trigger the reactive refresh pipeline
19594
+ */
19595
+ async activate(subscriber, session, updateCredential) {
19596
+ const { satClaims } = subscriber;
19597
+ if (!satClaims?.scope?.includes(SAT_REFRESH_SCOPE)) {
19598
+ logger$6.debug("[DeviceToken] No sat:refresh scope, skipping Client Bound SAT activation");
19599
+ return;
19600
+ }
19601
+ this._session = session;
19602
+ this._updateCredential = updateCredential;
19603
+ try {
19604
+ const tokenData = await this.obtainToken();
19605
+ if (!tokenData.expires_at && !tokenData.expires_in && satClaims.expires_at) tokenData.expires_at = satClaims.expires_at;
19606
+ this._effectiveExpireIn = resolveExpireIn(tokenData);
19607
+ const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
19608
+ await session.reauthenticate(tokenData.token, rpcProof, { clientBound: true });
19609
+ updateCredential({ token: tokenData.token });
19610
+ logger$6.info("[DeviceToken] Client Bound SAT activated successfully");
19611
+ this._currentToken$.next(tokenData);
19612
+ } catch (error) {
19613
+ logger$6.error("[DeviceToken] Failed to activate Client Bound SAT:", error);
19614
+ this.errorHandler(new DPoPInitError(error, "Failed to activate Client Bound SAT"));
19615
+ const credential = this.getCredential();
19616
+ const expiresAt = satClaims.expires_at ?? (credential.expiry_at ? credential.expiry_at / 1e3 : Date.now() / 1e3 + DEVICE_TOKEN_DEFAULT_EXPIRE_IN / 1e3);
19617
+ this._currentToken$.next({
19618
+ token: credential.token ?? "",
19619
+ expires_at: expiresAt
19620
+ });
19621
+ }
19622
+ }
19623
+ /**
19624
+ * Obtains a Client Bound SAT from `/api/fabric/subscriber/devices/token`.
19625
+ * Returns the full {@link DeviceTokenResponse} including expiry metadata.
19626
+ */
19627
+ async obtainToken() {
19628
+ const dpopProof = await this.dpopManager.createHttpProof({
19629
+ method: "POST",
19630
+ uri: DEVICE_TOKEN_ENDPOINT
19631
+ });
19632
+ const response = await this.http.request({
19633
+ url: DEVICE_TOKEN_ENDPOINT,
19634
+ ...POST_PARAMS,
19635
+ body: JSON.stringify({
19636
+ dpop_token: dpopProof,
19637
+ expire_in: DEVICE_TOKEN_DEFAULT_EXPIRE_IN
19638
+ })
19639
+ });
19640
+ if (!response.ok || !response.body) throw new DeviceTokenError(`Failed to obtain device token: ${response.status} ${response.statusText}`);
19641
+ const data = JSON.parse(response.body);
19642
+ if (!data.token) throw new DeviceTokenError("Device token response missing token field");
19643
+ return data;
19644
+ }
19645
+ /**
19646
+ * Refreshes the Client Bound SAT via `/api/fabric/subscriber/devices/refresh`.
19647
+ *
19648
+ * Creates a fresh DPoP proof, calls the refresh endpoint, reauthenticates
19649
+ * the WebSocket session, and returns the new token data (scheduling is
19650
+ * handled by the reactive pipeline).
19651
+ */
19652
+ async refreshToken(session, currentToken, updateCredential) {
19653
+ logger$6.debug("[DeviceToken] Refreshing Client Bound SAT");
19654
+ const dpopProof = await this.dpopManager.createHttpProof({
19655
+ method: "POST",
19656
+ uri: DEVICE_REFRESH_ENDPOINT,
19657
+ accessToken: currentToken
19658
+ });
19659
+ const response = await this.http.request({
19660
+ url: DEVICE_REFRESH_ENDPOINT,
19661
+ ...POST_PARAMS,
19662
+ body: JSON.stringify({
19663
+ dpop_token: dpopProof,
19664
+ expire_in: this._effectiveExpireIn
19665
+ })
19666
+ });
19667
+ if (!response.ok || !response.body) throw new TokenRefreshError(`Failed to refresh device token: ${response.status} ${response.statusText}`);
19668
+ const data = JSON.parse(response.body);
19669
+ if (!data.token) throw new TokenRefreshError("Device token refresh response missing token field");
19670
+ if (!data.expires_at && !data.expires_in) data.expires_in = this._effectiveExpireIn;
19671
+ this._effectiveExpireIn = resolveExpireIn(data);
19672
+ const rpcProof = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
19673
+ await session.reauthenticate(data.token, rpcProof);
19674
+ updateCredential({ token: data.token });
19675
+ logger$6.info("[DeviceToken] Client Bound SAT refreshed successfully");
19676
+ return data;
19677
+ }
19678
+ /**
19679
+ * Executes a refresh with retry and exponential backoff.
19680
+ * On success, emits to `_currentToken$` to schedule the next refresh.
19681
+ * On all retries exhausted, emits to `errorHandler`.
19682
+ */
19683
+ async executeRefresh() {
19684
+ if (this._refreshInProgress) {
19685
+ logger$6.debug("[DeviceToken] Refresh already in progress, skipping");
19686
+ return;
19687
+ }
19688
+ const session = this._session;
19689
+ const updateCredential = this._updateCredential;
19690
+ if (!session || !updateCredential) {
19691
+ logger$6.warn("[DeviceToken] Cannot refresh: session or updateCredential not set");
19692
+ return;
19693
+ }
19694
+ if (!session.authenticated) {
19695
+ logger$6.debug("[DeviceToken] Session not authenticated, deferring refresh");
19696
+ return;
19697
+ }
19698
+ this._refreshInProgress = true;
19699
+ try {
19700
+ const currentToken = this.getCredential().token;
19701
+ if (!currentToken) throw new TokenRefreshError("No current token available for refresh");
19702
+ const newTokenData = await this.retryRefresh(session, currentToken, updateCredential);
19703
+ this._currentToken$.next(newTokenData);
19704
+ } catch (error) {
19705
+ logger$6.error("[DeviceToken] Automatic Client Bound SAT refresh failed:", error);
19706
+ this.errorHandler(error instanceof TokenRefreshError ? error : new TokenRefreshError("Automatic token refresh failed", error));
19707
+ } finally {
19708
+ this._refreshInProgress = false;
19709
+ }
19710
+ }
19711
+ /**
19712
+ * Retries `refreshToken()` up to `DEVICE_TOKEN_REFRESH_MAX_RETRIES` times
19713
+ * with exponential backoff (1s, 2s, 4s).
19714
+ */
19715
+ async retryRefresh(session, currentToken, updateCredential) {
19716
+ let lastError;
19717
+ for (let attempt = 0; attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES; attempt++) try {
19718
+ return await this.refreshToken(session, currentToken, updateCredential);
19719
+ } catch (error) {
19720
+ lastError = error;
19721
+ if (attempt < DEVICE_TOKEN_REFRESH_MAX_RETRIES - 1) {
19722
+ const delay$1 = DEVICE_TOKEN_REFRESH_RETRY_BASE_MS * Math.pow(2, attempt);
19723
+ logger$6.warn(`[DeviceToken] Refresh attempt ${attempt + 1} failed, retrying in ${delay$1}ms`);
19724
+ await new Promise((resolve) => setTimeout(resolve, delay$1));
19725
+ }
19726
+ }
19727
+ throw lastError instanceof Error ? lastError : new TokenRefreshError("All refresh retries exhausted", lastError);
19728
+ }
19729
+ /** Cleans up the manager, cancelling the reactive pipeline and all subscriptions. */
19730
+ destroy() {
19731
+ super.destroy();
19732
+ }
19733
+ };
19734
+
19453
19735
  //#endregion
19454
19736
  //#region src/managers/DiagnosticsCollector.ts
19455
19737
  const logger$5 = getLogger();
@@ -20383,13 +20665,43 @@ var SignalWire = class extends Destroyable {
20383
20665
  this._errors$.next(error);
20384
20666
  });
20385
20667
  await this._clientSession.connect();
20386
- this.subscribeTo(this._clientSession.authenticated$.pipe((0, import_cjs.skip)(1), (0, import_cjs.filter)(Boolean)), () => {
20387
- logger$1.debug("[SignalWire] Re-registering subscriber after reconnect");
20388
- this.register().then(() => {
20668
+ if (this._dpopManager?.initialized) {
20669
+ if (this._refreshTimerId) {
20670
+ clearTimeout(this._refreshTimerId);
20671
+ this._refreshTimerId = void 0;
20672
+ logger$1.debug("[SignalWire] Developer refresh disabled — Client Bound SAT activation starting");
20673
+ }
20674
+ this._deviceTokenManager = new DeviceTokenManager(this._dpopManager, this._deps.http, (error) => this._errors$.next(error), () => this._deps.credential);
20675
+ await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
20676
+ this._deps.credential = {
20677
+ ...this._deps.credential,
20678
+ ...cred
20679
+ };
20680
+ });
20681
+ }
20682
+ this.subscribeTo(this._clientSession.authenticated$.pipe((0, import_cjs.skip)(1), (0, import_cjs.filter)(Boolean)), async () => {
20683
+ try {
20684
+ if (this._deviceTokenManager) {
20685
+ await this._deviceTokenManager.activate(this._deps.subscriber, this._clientSession, (cred) => {
20686
+ this._deps.credential = {
20687
+ ...this._deps.credential,
20688
+ ...cred
20689
+ };
20690
+ });
20691
+ logger$1.debug("[SignalWire] Client Bound SAT re-activated after reconnect");
20692
+ }
20693
+ } catch (error) {
20694
+ logger$1.error("[SignalWire] Client Bound SAT re-activation failed (non-fatal):", error);
20695
+ this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
20696
+ }
20697
+ try {
20698
+ logger$1.debug("[SignalWire] Re-registering subscriber after reconnect");
20699
+ await this.register();
20389
20700
  logger$1.debug("[SignalWire] Subscriber re-registered successfully after reconnect");
20390
- }).catch((error) => {
20701
+ } catch (error) {
20391
20702
  logger$1.error("[SignalWire] Re-registration failed after reconnect:", error);
20392
- });
20703
+ this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
20704
+ }
20393
20705
  });
20394
20706
  const conversationManager = new ConversationsManager(this._clientSession, this._deps.http, () => this._deps.getSubscriberFromAddressId(), errorHandler);
20395
20707
  const directory = new DirectoryManager(this._deps.http, this._clientSession, conversationManager, errorHandler);
@@ -20812,6 +21124,8 @@ var SignalWire = class extends Destroyable {
20812
21124
  * Triggers the browser's media permission dialog and captures the user's device selections.
20813
21125
  *
20814
21126
  * @param options - Which permissions to request.
21127
+ * @param options.audio - Whether to request audio permission.
21128
+ * @param options.video - Whether to request video permission.
20815
21129
  * @returns The permission result with selected devices.
20816
21130
  */
20817
21131
  async requestMediaPermissions(options = {
@@ -20843,8 +21157,14 @@ var SignalWire = class extends Destroyable {
20843
21157
  logger$1.warn("[SignalWire] Media permission request failed:", error);
20844
21158
  }
20845
21159
  await this._deviceController.enumerateDevices();
20846
- if (audioGranted && selectedAudioDevice) selectedAudioDevice = this.audioInputDevices.find((d) => d.deviceId === selectedAudioDevice.deviceId) ?? selectedAudioDevice;
20847
- if (videoGranted && selectedVideoDevice) selectedVideoDevice = this.videoInputDevices.find((d) => d.deviceId === selectedVideoDevice.deviceId) ?? selectedVideoDevice;
21160
+ if (audioGranted && selectedAudioDevice) {
21161
+ const audioDeviceId = selectedAudioDevice.deviceId;
21162
+ selectedAudioDevice = this.audioInputDevices.find((d) => d.deviceId === audioDeviceId) ?? selectedAudioDevice;
21163
+ }
21164
+ if (videoGranted && selectedVideoDevice) {
21165
+ const videoDeviceId = selectedVideoDevice.deviceId;
21166
+ selectedVideoDevice = this.videoInputDevices.find((d) => d.deviceId === videoDeviceId) ?? selectedVideoDevice;
21167
+ }
20848
21168
  if (audioGranted && selectedAudioDevice && !this.selectedAudioInputDevice) this.selectAudioInputDevice(selectedAudioDevice);
20849
21169
  if (videoGranted && selectedVideoDevice && !this.selectedVideoInputDevice) this.selectVideoInputDevice(selectedVideoDevice);
20850
21170
  return {