@signalwire/js 4.0.0-dev-20260410164129 → 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
  }
@@ -11839,7 +11852,7 @@ var PreflightRunner = class extends Destroyable {
11839
11852
  const candidateTypes = /* @__PURE__ */ new Set();
11840
11853
  const startTime = Date.now();
11841
11854
  const gatheringComplete = new Promise((resolve) => {
11842
- const timer$2 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
11855
+ const timer$3 = setTimeout(resolve, ICE_GATHERING_TIMEOUT_MS);
11843
11856
  peerConnection.onicecandidate = (event) => {
11844
11857
  if (event.candidate) {
11845
11858
  const candidateStr = event.candidate.candidate;
@@ -11847,7 +11860,7 @@ var PreflightRunner = class extends Destroyable {
11847
11860
  if (candidateStr.includes("typ srflx")) candidateTypes.add("srflx");
11848
11861
  if (candidateStr.includes("typ relay")) candidateTypes.add("relay");
11849
11862
  } else {
11850
- clearTimeout(timer$2);
11863
+ clearTimeout(timer$3);
11851
11864
  resolve();
11852
11865
  }
11853
11866
  };
@@ -11870,7 +11883,7 @@ var PreflightRunner = class extends Destroyable {
11870
11883
  rttMs
11871
11884
  };
11872
11885
  } catch (error) {
11873
- logger$23.warn("[PreflightRunner] ICE connectivity test failed:", error);
11886
+ logger$24.warn("[PreflightRunner] ICE connectivity test failed:", error);
11874
11887
  return {
11875
11888
  type: "failed",
11876
11889
  turnReachable: false,
@@ -11888,7 +11901,7 @@ var PreflightRunner = class extends Destroyable {
11888
11901
  audio: true,
11889
11902
  video: false
11890
11903
  });
11891
- 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)));
11892
11905
  const durationMs = this._options.duration * 1e3;
11893
11906
  await new Promise((resolve) => setTimeout(resolve, durationMs));
11894
11907
  const metrics = call.networkMetrics;
@@ -11917,8 +11930,8 @@ var PreflightRunner = class extends Destroyable {
11917
11930
 
11918
11931
  //#endregion
11919
11932
  //#region src/controllers/VisibilityController.ts
11920
- var import_cjs$22 = require_cjs();
11921
- const logger$22 = getLogger();
11933
+ var import_cjs$23 = require_cjs();
11934
+ const logger$23 = getLogger();
11922
11935
  /**
11923
11936
  * Checks whether the document visibility API is available.
11924
11937
  */
@@ -11955,15 +11968,15 @@ var VisibilityController = class extends Destroyable {
11955
11968
  this._boundHandler = this._handleVisibilityChange.bind(this);
11956
11969
  if (this._hasVisibilityApi) {
11957
11970
  document.addEventListener("visibilitychange", this._boundHandler);
11958
- logger$22.debug("VisibilityController: listening for visibilitychange events");
11959
- } 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");
11960
11973
  }
11961
11974
  /**
11962
11975
  * Observable of the current visibility state.
11963
11976
  * Emits 'visible' or 'hidden'. Always starts with the current state.
11964
11977
  */
11965
11978
  get visibility$() {
11966
- return this._visibility$.pipe((0, import_cjs$22.takeUntil)(this._destroyed$));
11979
+ return this._visibility$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
11967
11980
  }
11968
11981
  /**
11969
11982
  * The current visibility state value.
@@ -11976,12 +11989,12 @@ var VisibilityController = class extends Destroyable {
11976
11989
  * Each event includes the previous state, new state, and timestamp.
11977
11990
  */
11978
11991
  get visibilityChange$() {
11979
- return this._visibilityChange$.pipe((0, import_cjs$22.takeUntil)(this._destroyed$));
11992
+ return this._visibilityChange$.pipe((0, import_cjs$23.takeUntil)(this._destroyed$));
11980
11993
  }
11981
11994
  destroy() {
11982
11995
  if (this._hasVisibilityApi) {
11983
11996
  document.removeEventListener("visibilitychange", this._boundHandler);
11984
- logger$22.debug("VisibilityController: removed visibilitychange listener");
11997
+ logger$23.debug("VisibilityController: removed visibilitychange listener");
11985
11998
  }
11986
11999
  super.destroy();
11987
12000
  }
@@ -11999,7 +12012,7 @@ var VisibilityController = class extends Destroyable {
11999
12012
  timestamp: Date.now()
12000
12013
  };
12001
12014
  this._visibilityChange$.next(changeEvent);
12002
- logger$22.debug("VisibilityController: visibility changed", {
12015
+ logger$23.debug("VisibilityController: visibility changed", {
12003
12016
  from: previousState,
12004
12017
  to: newState
12005
12018
  });
@@ -12008,13 +12021,13 @@ var VisibilityController = class extends Destroyable {
12008
12021
 
12009
12022
  //#endregion
12010
12023
  //#region src/behaviors/Fetchable.ts
12011
- var import_cjs$21 = require_cjs();
12024
+ var import_cjs$22 = require_cjs();
12012
12025
  var Fetchable = class extends Destroyable {
12013
12026
  constructor(fromPath, http) {
12014
12027
  super();
12015
12028
  this.fromPath = fromPath;
12016
12029
  this.http = http;
12017
- 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$));
12018
12031
  }
12019
12032
  async fetch() {
12020
12033
  const response = await this.http.request({
@@ -12249,7 +12262,7 @@ const RPCEventAckResponse = (id) => makeRPCResponse({
12249
12262
 
12250
12263
  //#endregion
12251
12264
  //#region src/managers/AttachManager.ts
12252
- const logger$21 = getLogger();
12265
+ const logger$22 = getLogger();
12253
12266
  var AttachManager = class {
12254
12267
  constructor(storage, deviceController, reconnectCallsTimeout, attachKey) {
12255
12268
  this.storage = storage;
@@ -12261,6 +12274,7 @@ var AttachManager = class {
12261
12274
  const attached = await this.readAttached();
12262
12275
  for (const callId of Object.keys(attached)) await this.detach({
12263
12276
  id: callId,
12277
+ nodeId: attached[callId].nodeId,
12264
12278
  mediaDirections: attached[callId].mediaDirections
12265
12279
  });
12266
12280
  }
@@ -12271,7 +12285,7 @@ var AttachManager = class {
12271
12285
  try {
12272
12286
  return await this.storage.getItem(this.attachKey) ?? {};
12273
12287
  } catch (error) {
12274
- 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);
12275
12289
  return {};
12276
12290
  }
12277
12291
  }
@@ -12279,20 +12293,20 @@ var AttachManager = class {
12279
12293
  try {
12280
12294
  await this.storage.setItem(this.attachKey, attached);
12281
12295
  } catch (error) {
12282
- 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);
12283
12297
  }
12284
12298
  }
12285
12299
  async attach(call) {
12286
12300
  if (!call.to) {
12287
- logger$21.warn("[AttachManager] Skip attach for calls with no destination");
12301
+ logger$22.warn("[AttachManager] Skip attach for calls with no destination");
12288
12302
  return;
12289
12303
  }
12290
12304
  const attachment = {
12305
+ nodeId: call.nodeId,
12291
12306
  destination: call.to,
12292
12307
  mediaDirections: call.mediaDirections,
12293
12308
  audioInputDevice: call.mediaDirections.audio !== "inactive" ? this.deviceController.selectedAudioInputDevice : null,
12294
12309
  videoInputDevice: call.mediaDirections.video !== "inactive" ? this.deviceController.selectedVideoInputDevice : null,
12295
- nodeId: call.nodeId,
12296
12310
  attachedAt: Date.now()
12297
12311
  };
12298
12312
  const updated = {
@@ -12335,15 +12349,15 @@ var AttachManager = class {
12335
12349
  callId,
12336
12350
  ...options
12337
12351
  });
12338
- logger$21.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
12352
+ logger$22.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
12339
12353
  succeeded = true;
12340
12354
  break;
12341
12355
  } catch (error) {
12342
- 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);
12343
12357
  if (attempt < 3) await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
12344
12358
  }
12345
12359
  if (!succeeded) {
12346
- 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`);
12347
12361
  await this.detach({
12348
12362
  id: callId,
12349
12363
  mediaDirections: attachment.mediaDirections
@@ -12357,12 +12371,13 @@ var AttachManager = class {
12357
12371
  */
12358
12372
  buildCallOptions(attachment) {
12359
12373
  const { audio: audioDirection, video: videoDirection } = attachment.mediaDirections;
12360
- const { audioInputDevice, videoInputDevice } = attachment;
12374
+ const { audioInputDevice, videoInputDevice, nodeId } = attachment;
12361
12375
  const receiveAudio = audioDirection.includes("recv");
12362
12376
  const receiveVideo = videoDirection.includes("recv");
12363
12377
  const sendAudio = audioDirection.includes("send");
12364
12378
  const sendVideo = videoDirection.includes("send");
12365
12379
  return {
12380
+ nodeId,
12366
12381
  receiveAudio,
12367
12382
  receiveVideo,
12368
12383
  inputAudioDeviceConstraints: sendAudio ? {
@@ -12373,7 +12388,6 @@ var AttachManager = class {
12373
12388
  video: true,
12374
12389
  ...this.deviceController.deviceInfoToConstraints(videoInputDevice)
12375
12390
  } : void 0,
12376
- nodeId: attachment.nodeId ?? void 0,
12377
12391
  reattach: true
12378
12392
  };
12379
12393
  }
@@ -13249,7 +13263,7 @@ var require_operators = /* @__PURE__ */ __commonJSMin(((exports) => {
13249
13263
  //#endregion
13250
13264
  //#region src/operators/filterNull.ts
13251
13265
  var import_operators$1 = require_operators();
13252
- var import_cjs$20 = require_cjs();
13266
+ var import_cjs$21 = require_cjs();
13253
13267
  /**
13254
13268
  * RxJS operator that filters out `null` and `undefined` values with type narrowing.
13255
13269
  *
@@ -13261,7 +13275,7 @@ var import_cjs$20 = require_cjs();
13261
13275
  * ```
13262
13276
  */
13263
13277
  function filterNull() {
13264
- return (0, import_cjs$20.filter)((value) => value != null);
13278
+ return (0, import_cjs$21.filter)((value) => value != null);
13265
13279
  }
13266
13280
 
13267
13281
  //#endregion
@@ -13389,7 +13403,7 @@ function computeCapabilities(capabilities) {
13389
13403
 
13390
13404
  //#endregion
13391
13405
  //#region src/core/capabilities/SelfCapabilities.ts
13392
- var import_cjs$19 = require_cjs();
13406
+ var import_cjs$20 = require_cjs();
13393
13407
  /**
13394
13408
  * SelfCapabilities manages the capability state for the self participant.
13395
13409
  *
@@ -13425,7 +13439,7 @@ var SelfCapabilities = class extends Destroyable {
13425
13439
  }
13426
13440
  /** Observable for self member capabilities */
13427
13441
  get self$() {
13428
- 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)()));
13429
13443
  }
13430
13444
  /** Current self member capabilities */
13431
13445
  get self() {
@@ -13433,7 +13447,7 @@ var SelfCapabilities = class extends Destroyable {
13433
13447
  }
13434
13448
  /** Observable for other member capabilities */
13435
13449
  get member$() {
13436
- 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)()));
13437
13451
  }
13438
13452
  /** Current other member capabilities */
13439
13453
  get member() {
@@ -13441,7 +13455,7 @@ var SelfCapabilities = class extends Destroyable {
13441
13455
  }
13442
13456
  /** Observable for end call capability */
13443
13457
  get end$() {
13444
- 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)()));
13445
13459
  }
13446
13460
  /** Current end call capability */
13447
13461
  get end() {
@@ -13449,7 +13463,7 @@ var SelfCapabilities = class extends Destroyable {
13449
13463
  }
13450
13464
  /** Observable for set layout capability */
13451
13465
  get setLayout$() {
13452
- 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)()));
13453
13467
  }
13454
13468
  /** Current set layout capability */
13455
13469
  get setLayout() {
@@ -13457,7 +13471,7 @@ var SelfCapabilities = class extends Destroyable {
13457
13471
  }
13458
13472
  /** Observable for send digit capability */
13459
13473
  get sendDigit$() {
13460
- 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)()));
13461
13475
  }
13462
13476
  /** Current send digit capability */
13463
13477
  get sendDigit() {
@@ -13465,7 +13479,7 @@ var SelfCapabilities = class extends Destroyable {
13465
13479
  }
13466
13480
  /** Observable for vmuted hide capability */
13467
13481
  get vmutedHide$() {
13468
- 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)()));
13469
13483
  }
13470
13484
  /** Current vmuted hide capability */
13471
13485
  get vmutedHide() {
@@ -13473,7 +13487,7 @@ var SelfCapabilities = class extends Destroyable {
13473
13487
  }
13474
13488
  /** Observable for lock capability */
13475
13489
  get lock$() {
13476
- 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)()));
13477
13491
  }
13478
13492
  /** Current lock capability */
13479
13493
  get lock() {
@@ -13481,7 +13495,7 @@ var SelfCapabilities = class extends Destroyable {
13481
13495
  }
13482
13496
  /** Observable for device capability */
13483
13497
  get device$() {
13484
- 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)()));
13485
13499
  }
13486
13500
  /** Current device capability */
13487
13501
  get device() {
@@ -13489,7 +13503,7 @@ var SelfCapabilities = class extends Destroyable {
13489
13503
  }
13490
13504
  /** Observable for screenshare capability */
13491
13505
  get screenshare$() {
13492
- 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)()));
13493
13507
  }
13494
13508
  /** Current screenshare capability */
13495
13509
  get screenshare() {
@@ -13516,7 +13530,7 @@ function toggleHandraiseMethod(is) {
13516
13530
 
13517
13531
  //#endregion
13518
13532
  //#region src/core/entities/Participant.ts
13519
- const logger$20 = getLogger();
13533
+ const logger$21 = getLogger();
13520
13534
  const initialState = {};
13521
13535
  /**
13522
13536
  * Represents a participant in a call.
@@ -13894,7 +13908,7 @@ var SelfParticipant = class extends Participant {
13894
13908
  try {
13895
13909
  await this.vertoManager.addScreenMedia();
13896
13910
  } catch (error) {
13897
- logger$20.error("[Participant.startScreenShare] Screen share error:", error);
13911
+ logger$21.error("[Participant.startScreenShare] Screen share error:", error);
13898
13912
  }
13899
13913
  }
13900
13914
  /** Observable of the current screen share status. */
@@ -13914,7 +13928,7 @@ var SelfParticipant = class extends Participant {
13914
13928
  try {
13915
13929
  await this.vertoManager.addInputDevice(options);
13916
13930
  } catch (error) {
13917
- logger$20.error("[Participant.startScreenShare] Screen share error:", error);
13931
+ logger$21.error("[Participant.startScreenShare] Screen share error:", error);
13918
13932
  }
13919
13933
  }
13920
13934
  /** Removes an additional media input device by ID. */
@@ -13976,7 +13990,7 @@ var SelfParticipant = class extends Participant {
13976
13990
  */
13977
13991
  exitStudioModeIfActive() {
13978
13992
  if (this._studioAudio$.value) {
13979
- 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");
13980
13994
  this._studioAudio$.next(false);
13981
13995
  }
13982
13996
  }
@@ -14000,7 +14014,7 @@ var SelfParticipant = class extends Participant {
14000
14014
  try {
14001
14015
  await super.mute();
14002
14016
  } catch (error) {
14003
- 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);
14004
14018
  } finally {
14005
14019
  this.vertoManager.muteMainAudioInputDevice();
14006
14020
  }
@@ -14010,7 +14024,7 @@ var SelfParticipant = class extends Participant {
14010
14024
  try {
14011
14025
  await super.unmute();
14012
14026
  } catch (error) {
14013
- 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);
14014
14028
  } finally {
14015
14029
  await this.vertoManager.unmuteMainAudioInputDevice();
14016
14030
  }
@@ -14020,7 +14034,7 @@ var SelfParticipant = class extends Participant {
14020
14034
  try {
14021
14035
  await super.muteVideo();
14022
14036
  } catch (error) {
14023
- 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);
14024
14038
  } finally {
14025
14039
  this.vertoManager.muteMainVideoInputDevice();
14026
14040
  }
@@ -14030,7 +14044,7 @@ var SelfParticipant = class extends Participant {
14030
14044
  try {
14031
14045
  await super.unmuteVideo();
14032
14046
  } catch (error) {
14033
- 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);
14034
14048
  } finally {
14035
14049
  await this.vertoManager.unmuteMainVideoInputDevice();
14036
14050
  }
@@ -14134,7 +14148,7 @@ const getValueFrom = (obj, path, defaultValue) => {
14134
14148
 
14135
14149
  //#endregion
14136
14150
  //#region src/operators/filterEventAs.ts
14137
- var import_cjs$18 = require_cjs();
14151
+ var import_cjs$19 = require_cjs();
14138
14152
  var import_operators = require_operators();
14139
14153
  /**
14140
14154
  * RxJS operator that filters events based on a predicate and maps matching events.
@@ -14168,7 +14182,7 @@ var import_operators = require_operators();
14168
14182
  * ```
14169
14183
  */
14170
14184
  function ifIsMap(predicate, mapFn) {
14171
- 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));
14172
14186
  }
14173
14187
  /**
14174
14188
  * Generic RxJS operator that filters events using a type guard and extracts a property.
@@ -14210,38 +14224,38 @@ function ifIsMap(predicate, mapFn) {
14210
14224
  * ```
14211
14225
  */
14212
14226
  function filterAs(predicate, resultPath) {
14213
- return (0, import_cjs$18.pipe)(ifIsMap(predicate, (event) => {
14227
+ return (0, import_cjs$19.pipe)(ifIsMap(predicate, (event) => {
14214
14228
  return getValueFrom(event, resultPath);
14215
14229
  }), (0, import_operators.filter)((value) => value !== void 0));
14216
14230
  }
14217
14231
 
14218
14232
  //#endregion
14219
14233
  //#region src/operators/throwOnRPCError.ts
14220
- var import_cjs$17 = require_cjs();
14221
- const logger$19 = getLogger();
14234
+ var import_cjs$18 = require_cjs();
14235
+ const logger$20 = getLogger();
14222
14236
  /**
14223
14237
  * RxJS operator that throws a {@link JSONRPCError} when the RPC response contains an error.
14224
14238
  * Passes successful responses through unchanged.
14225
14239
  */
14226
14240
  function throwOnRPCError() {
14227
- return (0, import_cjs$17.map)((response) => {
14241
+ return (0, import_cjs$18.map)((response) => {
14228
14242
  if (response.error) {
14229
- logger$19.error("[throwOnRPCError] RPC error response:", {
14243
+ logger$20.error("[throwOnRPCError] RPC error response:", {
14230
14244
  code: response.error.code,
14231
14245
  message: response.error.message,
14232
14246
  data: response.error.data
14233
14247
  });
14234
14248
  throw new JSONRPCError(response.error.code, response.error.message, response.error.data);
14235
14249
  }
14236
- logger$19.debug("[throwOnRPCError] RPC successful response:", response);
14250
+ logger$20.debug("[throwOnRPCError] RPC successful response:", response);
14237
14251
  return response;
14238
14252
  });
14239
14253
  }
14240
14254
 
14241
14255
  //#endregion
14242
14256
  //#region src/managers/CallEventsManager.ts
14243
- var import_cjs$16 = require_cjs();
14244
- const logger$18 = getLogger();
14257
+ var import_cjs$17 = require_cjs();
14258
+ const logger$19 = getLogger();
14245
14259
  const initialSessionState = {};
14246
14260
  /** @internal */
14247
14261
  var CallEventsManager = class extends Destroyable {
@@ -14257,7 +14271,7 @@ var CallEventsManager = class extends Destroyable {
14257
14271
  this.initSubscriptions();
14258
14272
  }
14259
14273
  get participants$() {
14260
- 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))));
14261
14275
  }
14262
14276
  get participants() {
14263
14277
  return Object.values(this._participants$.value);
@@ -14275,40 +14289,40 @@ var CallEventsManager = class extends Destroyable {
14275
14289
  return this.callIds.has(callId);
14276
14290
  }
14277
14291
  get recording$() {
14278
- 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()));
14279
14293
  }
14280
14294
  get recordings$() {
14281
- 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()));
14282
14296
  }
14283
14297
  get streaming$() {
14284
- 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()));
14285
14299
  }
14286
14300
  get streams$() {
14287
- 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()));
14288
14302
  }
14289
14303
  get playbacks$() {
14290
- 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()));
14291
14305
  }
14292
14306
  get raiseHandPriority$() {
14293
- 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()));
14294
14308
  }
14295
14309
  get locked$() {
14296
- 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()));
14297
14311
  }
14298
14312
  get meta$() {
14299
- 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()));
14300
14314
  }
14301
14315
  get capabilities$() {
14302
- 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()));
14303
14317
  }
14304
14318
  get layout$() {
14305
- 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()));
14306
14320
  }
14307
14321
  get layouts$() {
14308
- 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()));
14309
14323
  }
14310
14324
  get layoutLayers$() {
14311
- 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()));
14312
14326
  }
14313
14327
  get self() {
14314
14328
  return this._self$.value;
@@ -14345,7 +14359,7 @@ var CallEventsManager = class extends Destroyable {
14345
14359
  }
14346
14360
  initSubscriptions() {
14347
14361
  this.subscribeTo(this.callJoinedEvent$, (callJoinedEvent) => {
14348
- 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:", {
14349
14363
  callId: callJoinedEvent.call_id,
14350
14364
  roomSessionId: callJoinedEvent.room_session_id
14351
14365
  });
@@ -14372,19 +14386,19 @@ var CallEventsManager = class extends Destroyable {
14372
14386
  if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
14373
14387
  });
14374
14388
  this.subscribeTo(this.memberUpdates$, (member) => {
14375
- 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);
14376
14390
  this.upsertParticipant(member);
14377
14391
  });
14378
14392
  this.subscribeTo(this.webRtcCallSession.memberLeft$, (memberLeftEvent) => {
14379
- 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);
14380
14394
  const participants = { ...this._participants$.value };
14381
14395
  if (memberLeftEvent.member.member_id in participants) {
14382
14396
  delete participants[memberLeftEvent.member.member_id];
14383
14397
  this._participants$.next(participants);
14384
- } 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}`);
14385
14399
  });
14386
14400
  this.subscribeTo(this.webRtcCallSession.callUpdated$, (callUpdatedEvent) => {
14387
- logger$18.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
14401
+ logger$19.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
14388
14402
  const roomSession = callUpdatedEvent.room_session;
14389
14403
  this._sessionState$.next({
14390
14404
  ...this._sessionState$.value,
@@ -14399,7 +14413,7 @@ var CallEventsManager = class extends Destroyable {
14399
14413
  });
14400
14414
  });
14401
14415
  this.subscribeTo(this.layoutChangedEvent$, (layoutChangedEvent) => {
14402
- logger$18.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
14416
+ logger$19.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
14403
14417
  this._sessionState$.next({
14404
14418
  ...this._sessionState$.value,
14405
14419
  layout_name: layoutChangedEvent.id,
@@ -14409,10 +14423,10 @@ var CallEventsManager = class extends Destroyable {
14409
14423
  });
14410
14424
  }
14411
14425
  updateParticipantPositions(layoutChangedEvent) {
14412
- 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.");
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.");
14413
14427
  layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
14414
14428
  if (!(layer.member_id in this._participants$.value)) {
14415
- logger$18.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
14429
+ logger$19.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
14416
14430
  return false;
14417
14431
  }
14418
14432
  return true;
@@ -14435,7 +14449,7 @@ var CallEventsManager = class extends Destroyable {
14435
14449
  layouts: response.result.layouts
14436
14450
  });
14437
14451
  }).catch((error) => {
14438
- logger$18.error("[CallEventsManager] Error fetching layouts:", error);
14452
+ logger$19.error("[CallEventsManager] Error fetching layouts:", error);
14439
14453
  });
14440
14454
  }
14441
14455
  updateParticipants(members) {
@@ -14451,7 +14465,7 @@ var CallEventsManager = class extends Destroyable {
14451
14465
  }
14452
14466
  const participant = this._participants$.value[member.member_id];
14453
14467
  const oldValue = participant.value;
14454
- logger$18.debug("[CallEventsManager] Updating participant:", member.member_id, {
14468
+ logger$19.debug("[CallEventsManager] Updating participant:", member.member_id, {
14455
14469
  oldValue,
14456
14470
  newValue: member
14457
14471
  });
@@ -14463,18 +14477,18 @@ var CallEventsManager = class extends Destroyable {
14463
14477
  this._participants$.next(this._participants$.value);
14464
14478
  }
14465
14479
  get callJoinedEvent$() {
14466
- return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$16.filter)(isCallJoinedPayload), (0, import_cjs$16.tap)((event) => {
14467
- 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);
14468
14482
  })));
14469
14483
  }
14470
14484
  get layoutChangedEvent$() {
14471
- return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$16.tap)((event) => {
14472
- 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);
14473
14487
  })));
14474
14488
  }
14475
14489
  get memberUpdates$() {
14476
- 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) => {
14477
- 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);
14478
14492
  })));
14479
14493
  }
14480
14494
  destroy() {
@@ -14730,8 +14744,8 @@ function appendStereoParams(fmtpLine, maxBitrate) {
14730
14744
 
14731
14745
  //#endregion
14732
14746
  //#region src/controllers/ICEGatheringController.ts
14733
- var import_cjs$15 = require_cjs();
14734
- const logger$17 = getLogger();
14747
+ var import_cjs$16 = require_cjs();
14748
+ const logger$18 = getLogger();
14735
14749
  var ICEGatheringController = class extends Destroyable {
14736
14750
  constructor(peerConnection, peerConnectionControllerNegotiating$, options = {}) {
14737
14751
  super();
@@ -14739,23 +14753,23 @@ var ICEGatheringController = class extends Destroyable {
14739
14753
  this.peerConnectionControllerNegotiating$ = peerConnectionControllerNegotiating$;
14740
14754
  this.onicegatheringstatechangeHandler = () => {
14741
14755
  const { iceGatheringState } = this.peerConnection;
14742
- logger$17.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
14756
+ logger$18.debug(`[ICEGatheringController] ICE gathering state changed to: ${iceGatheringState}`);
14743
14757
  if (iceGatheringState === "gathering") this._iceCandidatesState.next({
14744
14758
  state: "gathering",
14745
14759
  validSDP: false
14746
14760
  });
14747
14761
  };
14748
14762
  this.onicecandidateHandler = (event) => {
14749
- logger$17.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
14763
+ logger$18.debug("[ICEGatheringController] ICE candidate event received:", event.candidate);
14750
14764
  this.removeTimer("iceCandidateTimer");
14751
14765
  if (event.candidate) this.iceCandidateTimer = setTimeout(() => {
14752
14766
  if (this.peerConnection.iceGatheringState !== "complete") {
14753
- logger$17.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
14767
+ logger$18.warn("[ICEGatheringController] ICE candidate timeout, using current SDP");
14754
14768
  this.handleICECandidateTimeout();
14755
14769
  }
14756
14770
  }, this.iceCandidateTimeout);
14757
14771
  else {
14758
- logger$17.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
14772
+ logger$18.debug("[ICEGatheringController] ICE gathering completed: null candidate received");
14759
14773
  this.removeTimer("iceGatheringTimer");
14760
14774
  this.handleICEGatheringComplete();
14761
14775
  }
@@ -14768,12 +14782,12 @@ var ICEGatheringController = class extends Destroyable {
14768
14782
  this.iceGatheringTimeout = options.iceGatheringTimeout ?? DEFAULT_ICE_GATHERING_TIMEOUT_MS;
14769
14783
  this.relayOnly = options.relayOnly ?? false;
14770
14784
  this.setupEventListeners();
14771
- 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) => {
14772
14786
  if (isNegotiating) {
14773
14787
  this.setupEventListeners();
14774
14788
  this.iceGatheringTimer = setTimeout(() => {
14775
14789
  if (this.peerConnection.iceGatheringState !== "complete") {
14776
- logger$17.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
14790
+ logger$18.warn("[ICEGatheringController] ICE gathering timeout, using current SDP");
14777
14791
  this.handleICEGatheringTimeout();
14778
14792
  }
14779
14793
  }, this.iceGatheringTimeout);
@@ -14787,7 +14801,7 @@ var ICEGatheringController = class extends Destroyable {
14787
14801
  this.peerConnection.addEventListener("icegatheringstatechange", this.onicegatheringstatechangeHandler);
14788
14802
  }
14789
14803
  get iceCandidatesState$() {
14790
- 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));
14791
14805
  }
14792
14806
  get hasValidLocalDescriptionSDP() {
14793
14807
  const sdp = this.peerConnection.localDescription?.sdp;
@@ -14800,9 +14814,9 @@ var ICEGatheringController = class extends Destroyable {
14800
14814
  this.relayOnly = value;
14801
14815
  }
14802
14816
  handleICEGatheringComplete() {
14803
- logger$17.debug("[ICEGatheringController] Handling ICE gathering complete");
14804
- logger$17.debug(`[ICEGatheringController] Checking ICE gathering state: ${this.peerConnection.iceGatheringState}`);
14805
- 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");
14806
14820
  this._iceCandidatesState.next({
14807
14821
  state: "complete",
14808
14822
  validSDP: this.hasValidLocalDescriptionSDP
@@ -14818,21 +14832,21 @@ var ICEGatheringController = class extends Destroyable {
14818
14832
  this.removeTimer("iceGatheringTimer");
14819
14833
  const validSDP = this.hasValidLocalDescriptionSDP;
14820
14834
  if (validSDP) {
14821
- logger$17.debug("[ICEGatheringController] Local SDP is valid");
14835
+ logger$18.debug("[ICEGatheringController] Local SDP is valid");
14822
14836
  this._iceCandidatesState.next({
14823
14837
  state: "timeout",
14824
14838
  validSDP
14825
14839
  });
14826
14840
  this.stopGathering();
14827
- } 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);
14828
14842
  }
14829
14843
  handleICECandidateTimeout() {
14830
14844
  if (this.iceCandidateTimer) this.removeTimer("iceCandidateTimer");
14831
- logger$17.warn("[ICEGatheringController] ICE candidate timeout");
14845
+ logger$18.warn("[ICEGatheringController] ICE candidate timeout");
14832
14846
  const validSDP = this.hasValidLocalDescriptionSDP;
14833
14847
  if (!validSDP && !this.relayOnly) this.restartICEGatheringWithRelayOnly();
14834
14848
  else {
14835
- 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");
14836
14850
  this._iceCandidatesState.next({
14837
14851
  state: "timeout",
14838
14852
  validSDP
@@ -14841,7 +14855,7 @@ var ICEGatheringController = class extends Destroyable {
14841
14855
  }
14842
14856
  }
14843
14857
  restartICEGatheringWithRelayOnly() {
14844
- logger$17.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
14858
+ logger$18.debug("[ICEGatheringController] Restarting ICE gathering with relay-only candidates");
14845
14859
  this.relayOnly = true;
14846
14860
  this.peerConnection.setConfiguration({
14847
14861
  ...this.peerConnection.getConfiguration(),
@@ -14849,14 +14863,14 @@ var ICEGatheringController = class extends Destroyable {
14849
14863
  });
14850
14864
  if (!(this.peerConnection.connectionState === "connected")) this.peerConnection.restartIce();
14851
14865
  }
14852
- removeTimer(timer$2) {
14853
- if (this[timer$2]) {
14854
- clearTimeout(this[timer$2]);
14855
- 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;
14856
14870
  }
14857
14871
  }
14858
14872
  clearAllTimers() {
14859
- logger$17.debug("[ICEGatheringController] Clearing all timers");
14873
+ logger$18.debug("[ICEGatheringController] Clearing all timers");
14860
14874
  this.removeTimer("iceGatheringTimer");
14861
14875
  this.removeTimer("iceCandidateTimer");
14862
14876
  }
@@ -14865,7 +14879,7 @@ var ICEGatheringController = class extends Destroyable {
14865
14879
  this.peerConnection.removeEventListener("icecandidate", this.onicecandidateHandler);
14866
14880
  }
14867
14881
  destroy() {
14868
- logger$17.debug("[ICEGatheringController] Destroying ICEGatheringController");
14882
+ logger$18.debug("[ICEGatheringController] Destroying ICEGatheringController");
14869
14883
  this.clearAllTimers();
14870
14884
  this.removeEventListeners();
14871
14885
  super.destroy();
@@ -14874,8 +14888,8 @@ var ICEGatheringController = class extends Destroyable {
14874
14888
 
14875
14889
  //#endregion
14876
14890
  //#region src/controllers/LocalStreamController.ts
14877
- var import_cjs$14 = require_cjs();
14878
- const logger$16 = getLogger();
14891
+ var import_cjs$15 = require_cjs();
14892
+ const logger$17 = getLogger();
14879
14893
  var LocalStreamController = class extends Destroyable {
14880
14894
  constructor(options) {
14881
14895
  super();
@@ -14889,16 +14903,16 @@ var LocalStreamController = class extends Destroyable {
14889
14903
  this._mediaTrackEnded$ = this.createSubject();
14890
14904
  }
14891
14905
  get localStream$() {
14892
- 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$));
14893
14907
  }
14894
14908
  get localAudioTracks$() {
14895
- 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$));
14896
14910
  }
14897
14911
  get localVideoTracks$() {
14898
- 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$));
14899
14913
  }
14900
14914
  get mediaTrackEnded$() {
14901
- 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$));
14902
14916
  }
14903
14917
  get localStream() {
14904
14918
  return this._localStream$.value;
@@ -14913,26 +14927,26 @@ var LocalStreamController = class extends Destroyable {
14913
14927
  * Build the local media stream based on the provided options.
14914
14928
  */
14915
14929
  async buildLocalStream() {
14916
- logger$16.debug("[LocalStreamController] Building local media stream.");
14930
+ logger$17.debug("[LocalStreamController] Building local media stream.");
14917
14931
  let stream;
14918
14932
  if (this.options.inputAudioStream ?? this.options.inputVideoStream) {
14919
14933
  const tracks = [...this.options.inputAudioStream?.getTracks() ?? [], ...this.options.inputVideoStream?.getTracks() ?? []];
14920
14934
  stream = new MediaStream(tracks);
14921
14935
  } else if (this.options.propose === "screenshare") {
14922
- 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));
14923
14937
  stream = await this.options.getDisplayMedia({
14924
14938
  video: true,
14925
14939
  audio: Boolean(this.options.inputAudioDeviceConstraints)
14926
14940
  });
14927
- logger$16.debug("[LocalStreamController] Screen share media obtained:", stream);
14941
+ logger$17.debug("[LocalStreamController] Screen share media obtained:", stream);
14928
14942
  } else {
14929
14943
  const constraints = {
14930
14944
  audio: this.options.inputAudioDeviceConstraints,
14931
14945
  video: this.options.inputVideoDeviceConstraints
14932
14946
  };
14933
- logger$16.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
14947
+ logger$17.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
14934
14948
  stream = await this.options.getUserMedia(constraints);
14935
- logger$16.debug("[LocalStreamController] User media obtained:", stream);
14949
+ logger$17.debug("[LocalStreamController] User media obtained:", stream);
14936
14950
  }
14937
14951
  this._localStream$.next(stream);
14938
14952
  return stream;
@@ -14949,7 +14963,7 @@ var LocalStreamController = class extends Destroyable {
14949
14963
  this._localStream$.next(localStream);
14950
14964
  if (track.kind === "video") this._localVideoTracks$.next(localStream.getVideoTracks());
14951
14965
  else this._localAudioTracks$.next(localStream.getAudioTracks());
14952
- logger$16.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
14966
+ logger$17.debug(`[LocalStreamController] ${track.kind} track added:`, track.id);
14953
14967
  return localStream;
14954
14968
  }
14955
14969
  /**
@@ -14961,7 +14975,7 @@ var LocalStreamController = class extends Destroyable {
14961
14975
  const stream = this._localStream$.value;
14962
14976
  const track = stream?.getTracks().find((t) => t.id === trackId);
14963
14977
  if (!track) {
14964
- logger$16.debug(`[LocalStreamController] track not found: ${trackId}`);
14978
+ logger$17.debug(`[LocalStreamController] track not found: ${trackId}`);
14965
14979
  return;
14966
14980
  }
14967
14981
  track.removeEventListener("ended", this.mediaTrackEndedHandler);
@@ -14970,7 +14984,7 @@ var LocalStreamController = class extends Destroyable {
14970
14984
  this._localStream$.next(stream);
14971
14985
  if (track.kind === "video") this._localVideoTracks$.next(stream?.getVideoTracks() ?? []);
14972
14986
  else this._localAudioTracks$.next(stream?.getAudioTracks() ?? []);
14973
- logger$16.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
14987
+ logger$17.debug(`[LocalStreamController] ${track.kind} track removed:`, trackId);
14974
14988
  return track;
14975
14989
  }
14976
14990
  /**
@@ -15005,7 +15019,7 @@ var LocalStreamController = class extends Destroyable {
15005
15019
  */
15006
15020
  stopAllTracks() {
15007
15021
  this._localStream$.value?.getTracks().forEach((track) => {
15008
- logger$16.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
15022
+ logger$17.debug(`[LocalStreamController] Stopping local track: ${track.kind}`);
15009
15023
  track.removeEventListener("ended", this.mediaTrackEndedHandler);
15010
15024
  track.stop();
15011
15025
  });
@@ -15021,7 +15035,7 @@ var LocalStreamController = class extends Destroyable {
15021
15035
 
15022
15036
  //#endregion
15023
15037
  //#region src/controllers/TransceiverController.ts
15024
- const logger$15 = getLogger();
15038
+ const logger$16 = getLogger();
15025
15039
  const getDirection = (send, recv) => {
15026
15040
  if (send && recv) return "sendrecv";
15027
15041
  else if (send && !recv) return "sendonly";
@@ -15123,7 +15137,7 @@ var TransceiverController = class extends Destroyable {
15123
15137
  sendEncodings: isAudio ? void 0 : this.sendEncodings,
15124
15138
  streams: direction === "recvonly" ? void 0 : [localStream]
15125
15139
  };
15126
- 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:`, {
15127
15141
  transceiver,
15128
15142
  transceiverParams
15129
15143
  });
@@ -15131,11 +15145,11 @@ var TransceiverController = class extends Destroyable {
15131
15145
  await transceiver.sender.replaceTrack(track);
15132
15146
  transceiver.direction = transceiverParams.direction;
15133
15147
  if (transceiverParams.streams?.some((stream) => Boolean(stream))) {
15134
- 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);
15135
15149
  transceiver.sender.setStreams(...transceiverParams.streams);
15136
15150
  }
15137
15151
  } else {
15138
- 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);
15139
15153
  this.peerConnection.addTransceiver(track, transceiverParams);
15140
15154
  }
15141
15155
  }
@@ -15149,13 +15163,13 @@ var TransceiverController = class extends Destroyable {
15149
15163
  if (options.updateTransceiverDirection) transceiver.direction = "inactive";
15150
15164
  }
15151
15165
  } catch (error) {
15152
- logger$15.error("[TransceiverController] stopTrackSender error", kind, error);
15166
+ logger$16.error("[TransceiverController] stopTrackSender error", kind, error);
15153
15167
  this.options.onError?.(new MediaTrackError("stopTrackSender", kind, error));
15154
15168
  }
15155
15169
  }
15156
15170
  async restoreTrackSender(kind) {
15157
15171
  try {
15158
- logger$15.debug("[TransceiverController] restoreTrackSender called", kind);
15172
+ logger$16.debug("[TransceiverController] restoreTrackSender called", kind);
15159
15173
  const constraints = {};
15160
15174
  const transceivers = this.transceiverByKind(kind);
15161
15175
  for (const transceiver of transceivers) {
@@ -15165,23 +15179,23 @@ var TransceiverController = class extends Destroyable {
15165
15179
  if (trackKind === "audio" || trackKind === "video") constraints[trackKind] = this.getConstraintsFor(trackKind);
15166
15180
  }
15167
15181
  }
15168
- logger$15.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
15182
+ logger$16.debug("[TransceiverController] restoreTrackSender constraints:", constraints);
15169
15183
  if (Object.keys(constraints).length === 0) {
15170
- logger$15.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
15184
+ logger$16.warn("[TransceiverController] restoreTrackSender: no tracks need restoration", kind);
15171
15185
  return;
15172
15186
  }
15173
15187
  const newTracks = (await this.options.getUserMedia(constraints)).getTracks();
15174
- logger$15.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
15188
+ logger$16.debug("[TransceiverController] restoreTrackSender new tracks:", newTracks);
15175
15189
  for (const newTrack of newTracks) {
15176
15190
  this.options.localStreamController.addTrack(newTrack);
15177
15191
  const trackKind = newTrack.kind;
15178
15192
  const transceiverOfKind = this.transceiverByKind(trackKind)[0];
15179
15193
  transceiverOfKind.direction = trackKind === "audio" ? this.audioDirection : this.videoDirection;
15180
- logger$15.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
15194
+ logger$16.debug("[TransceiverController] restoreTrackSender setting direction for", trackKind, transceiverOfKind.direction);
15181
15195
  await transceiverOfKind.sender.replaceTrack(newTrack);
15182
15196
  }
15183
15197
  } catch (error) {
15184
- logger$15.error("[TransceiverController] restoreTrackSender error", kind, error);
15198
+ logger$16.error("[TransceiverController] restoreTrackSender error", kind, error);
15185
15199
  this.options.onError?.(new MediaTrackError("restoreTrackSender", kind, error));
15186
15200
  }
15187
15201
  }
@@ -15222,14 +15236,14 @@ var TransceiverController = class extends Destroyable {
15222
15236
  };
15223
15237
  try {
15224
15238
  await track.applyConstraints(constraintsToApply);
15225
- logger$15.debug(`[TransceiverController] Updated ${kind} sender constraints:`, constraintsToApply);
15226
- 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());
15227
15241
  } catch (error) {
15228
- 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);
15229
15243
  try {
15230
15244
  await this.replaceTrackFallback(sender, track, kind, constraintsToApply);
15231
15245
  } catch (fallbackError) {
15232
- 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);
15233
15247
  this.options.onError?.(new MediaTrackError("updateSendersConstraints", kind, fallbackError));
15234
15248
  }
15235
15249
  }
@@ -15257,7 +15271,7 @@ var TransceiverController = class extends Destroyable {
15257
15271
  if (!newTrack) throw new MediaTrackError("replaceTrackFallback", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
15258
15272
  await sender.replaceTrack(newTrack);
15259
15273
  this.options.localStreamController.addTrack(newTrack);
15260
- 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}`);
15261
15275
  }
15262
15276
  getMediaDirections() {
15263
15277
  if (this.peerConnection.connectionState === "connected") return this.peerConnection.getTransceivers().reduce((acc, transceiver) => {
@@ -15287,60 +15301,60 @@ var TransceiverController = class extends Destroyable {
15287
15301
 
15288
15302
  //#endregion
15289
15303
  //#region src/controllers/RTCPeerConnectionController.ts
15290
- var import_cjs$13 = require_cjs();
15291
- const logger$14 = getLogger();
15304
+ var import_cjs$14 = require_cjs();
15305
+ const logger$15 = getLogger();
15292
15306
  var RTCPeerConnectionController = class extends Destroyable {
15293
15307
  constructor(options = {}, remoteSessionDescription, deviceController) {
15294
15308
  super();
15295
15309
  this.options = options;
15296
15310
  this.firstSDPExchangeCompleted = false;
15297
15311
  this.negotiationNeeded$ = this.createSubject();
15298
- 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)(() => {
15299
15313
  this.negotiationEnded();
15300
- }), (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) => {
15301
15315
  if (desc.type === "answer") this._type = "offer";
15302
- }))), (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$));
15303
15317
  this.connectionTimeout = 3e3;
15304
15318
  this.oniceconnectionstatechangeHandler = () => {
15305
15319
  if (this.peerConnection) {
15306
15320
  const { iceConnectionState } = this.peerConnection;
15307
- logger$14.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
15321
+ logger$15.debug(`[RTCPeerConnectionController] ICE connection state changed to: ${iceConnectionState}`);
15308
15322
  this._iceConnectionState$.next(this.peerConnection.iceConnectionState);
15309
15323
  }
15310
15324
  };
15311
15325
  this.onconnectionstatechangeHandler = () => {
15312
15326
  if (this.peerConnection) {
15313
15327
  const { connectionState } = this.peerConnection;
15314
- logger$14.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
15328
+ logger$15.debug(`[RTCPeerConnectionController] Connection state changed to: ${connectionState}`);
15315
15329
  if (connectionState === "connected") this.removeConnectionTimer();
15316
15330
  this._connectionState$.next(this.peerConnection.connectionState);
15317
15331
  }
15318
15332
  };
15319
15333
  this.onsignalingstatechangeHandler = () => {
15320
- logger$14.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
15334
+ logger$15.debug(`[RTCPeerConnectionController] Signaling state changed to: ${this.peerConnection?.signalingState}`);
15321
15335
  };
15322
15336
  this.onicegatheringstatechangeHandler = () => {
15323
15337
  if (this.peerConnection) this._iceGatheringState$.next(this.peerConnection.iceGatheringState);
15324
15338
  };
15325
15339
  this.onnegotiationneededHandler = (event) => {
15326
- logger$14.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
15340
+ logger$15.debug("[RTCPeerConnectionController] Negotiation needed event received.", event);
15327
15341
  this.negotiationNeeded$.next();
15328
15342
  };
15329
15343
  this.updateSelectedInputDevice = async (kind, deviceInfo) => {
15330
15344
  try {
15331
15345
  const { localStream } = this;
15332
15346
  if (!localStream) {
15333
- 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.");
15334
15348
  return;
15335
15349
  }
15336
- logger$14.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
15350
+ logger$15.debug(`[RTCPeerConnectionController] Updating selected ${kind} input device:`, localStream.getTracks());
15337
15351
  const track = localStream.getTracks().find((track$1) => track$1.kind === kind);
15338
15352
  if (track) {
15339
15353
  this.transceiverController?.stopTrackSender(kind);
15340
15354
  this.localStream?.removeTrack(track);
15341
- 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());
15342
15356
  if (!deviceInfo) {
15343
- logger$14.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
15357
+ logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected: none`);
15344
15358
  return;
15345
15359
  }
15346
15360
  const streamTrack = (await this.getUserMedia({ [kind]: {
@@ -15348,15 +15362,15 @@ var RTCPeerConnectionController = class extends Destroyable {
15348
15362
  ...this.deviceController.deviceInfoToConstraints(deviceInfo)
15349
15363
  } })).getTracks().find((t) => t.kind === kind);
15350
15364
  if (streamTrack) {
15351
- logger$14.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
15365
+ logger$15.debug(`[RTCPeerConnectionController] Adding new ${kind} track: ${streamTrack.id}`);
15352
15366
  this.localStream?.addTrack(streamTrack);
15353
15367
  await this.transceiverController?.replaceSenderTrack(kind, streamTrack);
15354
- 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());
15355
15369
  }
15356
15370
  }
15357
- logger$14.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
15371
+ logger$15.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
15358
15372
  } catch (error) {
15359
- logger$14.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
15373
+ logger$15.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
15360
15374
  this._errors$.next(error);
15361
15375
  throw error;
15362
15376
  }
@@ -15442,43 +15456,43 @@ var RTCPeerConnectionController = class extends Destroyable {
15442
15456
  };
15443
15457
  }
15444
15458
  get iceGatheringState$() {
15445
- 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$)));
15446
15460
  }
15447
15461
  get mediaTrackEnded$() {
15448
- 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$)));
15449
15463
  }
15450
15464
  get errors$() {
15451
- 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$)));
15452
15466
  }
15453
15467
  get iceCandidates$() {
15454
- 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$)));
15455
15469
  }
15456
15470
  get initialized$() {
15457
- 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$)));
15458
15472
  }
15459
15473
  get remoteDescription$() {
15460
- 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$)));
15461
15475
  }
15462
15476
  get localStream$() {
15463
- 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$)));
15464
15478
  }
15465
15479
  get remoteStream$() {
15466
- 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$)));
15467
15481
  }
15468
15482
  get localAudioTracks$() {
15469
- 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$)));
15470
15484
  }
15471
15485
  get localVideoTracks$() {
15472
- 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$)));
15473
15487
  }
15474
15488
  get iceConnectionState$() {
15475
- 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$)));
15476
15490
  }
15477
15491
  get connectionState$() {
15478
- 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$)));
15479
15493
  }
15480
15494
  get signalingState$() {
15481
- 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$)));
15482
15496
  }
15483
15497
  get type() {
15484
15498
  return this._type;
@@ -15591,17 +15605,17 @@ var RTCPeerConnectionController = class extends Destroyable {
15591
15605
  async doInit() {
15592
15606
  try {
15593
15607
  this.setupPeerConnection();
15594
- 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())), {
15595
15609
  next: () => {
15596
- logger$14.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
15610
+ logger$15.debug("[RTCPeerConnectionController] Start Negotiation completed successfully");
15597
15611
  },
15598
15612
  error: (error) => {
15599
- logger$14.error("[RTCPeerConnectionController] Start Negotiation error:", error);
15613
+ logger$15.error("[RTCPeerConnectionController] Start Negotiation error:", error);
15600
15614
  this._errors$.next(error);
15601
15615
  }
15602
15616
  });
15603
- 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]) => {
15604
- 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:`, {
15605
15619
  kind,
15606
15620
  deviceInfo
15607
15621
  });
@@ -15618,7 +15632,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15618
15632
  this._initialized$.next(true);
15619
15633
  }
15620
15634
  } catch (error) {
15621
- logger$14.error("[RTCPeerConnectionController] Initialization error:", error);
15635
+ logger$15.error("[RTCPeerConnectionController] Initialization error:", error);
15622
15636
  this._errors$.next(error);
15623
15637
  this.destroy();
15624
15638
  }
@@ -15650,22 +15664,22 @@ var RTCPeerConnectionController = class extends Destroyable {
15650
15664
  }
15651
15665
  async startNegotiation() {
15652
15666
  if (this.isNegotiating) {
15653
- logger$14.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
15667
+ logger$15.debug("[RTCPeerConnectionController] Negotiation already in progress, skipping.");
15654
15668
  return;
15655
15669
  }
15656
15670
  this.setupEventListeners();
15657
15671
  if (this.type === "answer") {
15658
- 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.");
15659
15673
  return;
15660
15674
  }
15661
15675
  this._isNegotiating$.next(true);
15662
- logger$14.debug("[RTCPeerConnectionController] Starting negotiation.");
15676
+ logger$15.debug("[RTCPeerConnectionController] Starting negotiation.");
15663
15677
  try {
15664
15678
  const { offerOptions } = this;
15665
- logger$14.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
15679
+ logger$15.debug("[RTCPeerConnectionController] Creating offer with options:", offerOptions);
15666
15680
  await this.createOffer(offerOptions);
15667
15681
  } catch (error) {
15668
- logger$14.error("[RTCPeerConnectionController] Error during negotiation:", error);
15682
+ logger$15.error("[RTCPeerConnectionController] Error during negotiation:", error);
15669
15683
  this._errors$.next(error);
15670
15684
  }
15671
15685
  }
@@ -15681,14 +15695,14 @@ var RTCPeerConnectionController = class extends Destroyable {
15681
15695
  let readyToConnect = status !== "failed";
15682
15696
  try {
15683
15697
  if (status === "received" && sdp) {
15684
- logger$14.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
15698
+ logger$15.debug("[RTCPeerConnectionController] Received answer SDP:", sdp);
15685
15699
  await this._setRemoteDescription({
15686
15700
  type: "answer",
15687
15701
  sdp
15688
15702
  });
15689
15703
  }
15690
15704
  } catch (error) {
15691
- logger$14.error("[RTCPeerConnectionController] Error updating answer status:", error);
15705
+ logger$15.error("[RTCPeerConnectionController] Error updating answer status:", error);
15692
15706
  this._errors$.next(error);
15693
15707
  readyToConnect = false;
15694
15708
  } finally {
@@ -15707,7 +15721,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15707
15721
  await this.handleOfferReceived();
15708
15722
  break;
15709
15723
  case "failed":
15710
- logger$14.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
15724
+ logger$15.error("[RTCPeerConnectionController] Offer failed to be processed by remote.");
15711
15725
  break;
15712
15726
  case "sent":
15713
15727
  default:
@@ -15739,7 +15753,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15739
15753
  }
15740
15754
  await this.setupLocalTracks();
15741
15755
  const { answerOptions } = this;
15742
- logger$14.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
15756
+ logger$15.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
15743
15757
  await this.createAnswer(answerOptions);
15744
15758
  }
15745
15759
  async handleOfferReceived() {
@@ -15747,7 +15761,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15747
15761
  this._isNegotiating$.next(true);
15748
15762
  await this._setRemoteDescription(this.sdpInit);
15749
15763
  const { answerOptions } = this;
15750
- logger$14.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
15764
+ logger$15.debug("[RTCPeerConnectionController] Creating answer with options:", answerOptions);
15751
15765
  await this.createAnswer(answerOptions);
15752
15766
  }
15753
15767
  readyToConnect() {
@@ -15755,7 +15769,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15755
15769
  this.connectionTimer = setTimeout(() => {
15756
15770
  this.removeConnectionTimer();
15757
15771
  if (this.peerConnection?.connectionState !== "connected") {
15758
- 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.");
15759
15773
  this.iceGatheringController.restartICEGatheringWithRelayOnly();
15760
15774
  }
15761
15775
  }, this.connectionTimeout);
@@ -15777,14 +15791,14 @@ var RTCPeerConnectionController = class extends Destroyable {
15777
15791
  const stereo = this.options.stereo ?? PreferencesContainer.instance.stereoAudio;
15778
15792
  if (preferredAudioCodecs.length > 0 || preferredVideoCodecs.length > 0) {
15779
15793
  result = setCodecPreferences(result, preferredAudioCodecs, preferredVideoCodecs);
15780
- logger$14.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
15794
+ logger$15.debug("[RTCPeerConnectionController] Applied codec preferences to SDP", {
15781
15795
  preferredAudioCodecs,
15782
15796
  preferredVideoCodecs
15783
15797
  });
15784
15798
  }
15785
15799
  if (stereo) {
15786
15800
  result = enableStereoOpus(result);
15787
- logger$14.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP");
15801
+ logger$15.debug("[RTCPeerConnectionController] Applied stereo Opus to SDP");
15788
15802
  }
15789
15803
  return Promise.resolve(result);
15790
15804
  }
@@ -15843,18 +15857,18 @@ var RTCPeerConnectionController = class extends Destroyable {
15843
15857
  ...this.peerConnection.getConfiguration(),
15844
15858
  iceTransportPolicy: "relay"
15845
15859
  });
15846
- logger$14.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only");
15860
+ logger$15.debug("[RTCPeerConnectionController] ICE transport policy set to relay-only");
15847
15861
  } catch (error) {
15848
- logger$14.warn("[RTCPeerConnectionController] Failed to set relay-only policy:", error);
15862
+ logger$15.warn("[RTCPeerConnectionController] Failed to set relay-only policy:", error);
15849
15863
  }
15850
15864
  this.setupEventListeners();
15851
15865
  this._isNegotiating$.next(true);
15852
- logger$14.debug(`[RTCPeerConnectionController] Triggering ICE restart${relayOnly ? " (relay-only)" : ""}.`);
15866
+ logger$15.debug(`[RTCPeerConnectionController] Triggering ICE restart${relayOnly ? " (relay-only)" : ""}.`);
15853
15867
  try {
15854
15868
  const offer = await this.peerConnection.createOffer({ iceRestart: true });
15855
15869
  await this.setLocalDescription(offer);
15856
15870
  } catch (error) {
15857
- logger$14.error("[RTCPeerConnectionController] ICE restart offer failed:", error);
15871
+ logger$15.error("[RTCPeerConnectionController] ICE restart offer failed:", error);
15858
15872
  this._errors$.next(error);
15859
15873
  this.negotiationEnded();
15860
15874
  if (policyChanged) this.restoreIceTransportPolicy();
@@ -15868,9 +15882,9 @@ var RTCPeerConnectionController = class extends Destroyable {
15868
15882
  ...this.peerConnection.getConfiguration(),
15869
15883
  iceTransportPolicy: this.options.relayOnly ? "relay" : "all"
15870
15884
  });
15871
- logger$14.debug("[RTCPeerConnectionController] ICE transport policy restored");
15885
+ logger$15.debug("[RTCPeerConnectionController] ICE transport policy restored");
15872
15886
  } catch (error) {
15873
- logger$14.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:", error);
15887
+ logger$15.warn("[RTCPeerConnectionController] Failed to restore ICE transport policy:", error);
15874
15888
  }
15875
15889
  }
15876
15890
  /**
@@ -15882,13 +15896,13 @@ var RTCPeerConnectionController = class extends Destroyable {
15882
15896
  await this.setupRemoteTracks();
15883
15897
  }
15884
15898
  async setupLocalTracks() {
15885
- logger$14.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
15899
+ logger$15.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
15886
15900
  const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
15887
15901
  if (this.transceiverController?.useAddStream ?? false) {
15888
- 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.");
15889
15903
  this.peerConnection?.addStream(localStream);
15890
15904
  if (!this.isNegotiating) {
15891
- logger$14.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
15905
+ logger$15.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
15892
15906
  this.negotiationNeeded$.next();
15893
15907
  }
15894
15908
  return;
@@ -15904,7 +15918,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15904
15918
  const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
15905
15919
  await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
15906
15920
  } else {
15907
- 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);
15908
15922
  this.peerConnection?.addTrack(track, localStream);
15909
15923
  }
15910
15924
  }
@@ -15921,7 +15935,7 @@ var RTCPeerConnectionController = class extends Destroyable {
15921
15935
  async setupRemoteTracks() {
15922
15936
  if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
15923
15937
  this.peerConnection.ontrack = (event) => {
15924
- logger$14.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
15938
+ logger$15.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
15925
15939
  if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
15926
15940
  else {
15927
15941
  const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
@@ -15947,9 +15961,9 @@ var RTCPeerConnectionController = class extends Destroyable {
15947
15961
  try {
15948
15962
  const localStream = this.localStreamController.addTrack(track);
15949
15963
  this.peerConnection.addTrack(track, localStream);
15950
- logger$14.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
15964
+ logger$15.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
15951
15965
  } catch (error) {
15952
- logger$14.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
15966
+ logger$15.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
15953
15967
  this._errors$.next(error);
15954
15968
  throw error;
15955
15969
  }
@@ -15966,15 +15980,15 @@ var RTCPeerConnectionController = class extends Destroyable {
15966
15980
  }
15967
15981
  const sender = this.peerConnection.getSenders().find((sender$1) => sender$1.track?.id === trackId);
15968
15982
  if (!sender) {
15969
- logger$14.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
15983
+ logger$15.debug(`[RTCPeerConnectionController] track not found: ${trackId}`);
15970
15984
  return;
15971
15985
  }
15972
15986
  try {
15973
15987
  this.peerConnection.removeTrack(sender);
15974
15988
  this.localStreamController.removeTrack(trackId);
15975
- logger$14.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
15989
+ logger$15.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
15976
15990
  } catch (error) {
15977
- 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);
15978
15992
  this._errors$.next(error);
15979
15993
  throw error;
15980
15994
  }
@@ -16001,7 +16015,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16001
16015
  async replaceAudioTrackWithConstraints(constraints) {
16002
16016
  const senders = this.peerConnection?.getSenders().filter((s) => s.track?.kind === "audio" && s.track.readyState === "live");
16003
16017
  if (!senders || senders.length === 0) {
16004
- logger$14.warn("[RTCPeerConnectionController] No live audio sender to replace");
16018
+ logger$15.warn("[RTCPeerConnectionController] No live audio sender to replace");
16005
16019
  return;
16006
16020
  }
16007
16021
  for (const sender of senders) {
@@ -16019,7 +16033,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16019
16033
  const newTrack = (await this.getUserMedia({ audio: mergedConstraints })).getAudioTracks()[0];
16020
16034
  await sender.replaceTrack(newTrack);
16021
16035
  this.localStreamController.addTrack(newTrack);
16022
- 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}`);
16023
16037
  }
16024
16038
  }
16025
16039
  /**
@@ -16027,7 +16041,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16027
16041
  * Completes all observables to prevent memory leaks.
16028
16042
  */
16029
16043
  destroy() {
16030
- logger$14.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
16044
+ logger$15.debug(`[RTCPeerConnectionController] Destroying RTCPeerConnectionController. ${this.propose}`);
16031
16045
  this.removeConnectionTimer();
16032
16046
  this._iceGatheringController?.destroy();
16033
16047
  this.localStreamController.destroy();
@@ -16051,7 +16065,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16051
16065
  }
16052
16066
  stopRemoteTracks() {
16053
16067
  this._remoteStream$.value?.getTracks().forEach((track) => {
16054
- logger$14.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
16068
+ logger$15.debug(`[RTCPeerConnectionController] Stopping remote track: ${track.kind}`);
16055
16069
  track.stop();
16056
16070
  });
16057
16071
  }
@@ -16068,7 +16082,7 @@ var RTCPeerConnectionController = class extends Destroyable {
16068
16082
  ...params,
16069
16083
  sdp: finalRemote
16070
16084
  };
16071
- logger$14.debug("[RTCPeerConnectionController] Setting remote description:", answer);
16085
+ logger$15.debug("[RTCPeerConnectionController] Setting remote description:", answer);
16072
16086
  return this.peerConnection.setRemoteDescription(answer);
16073
16087
  }
16074
16088
  };
@@ -16106,8 +16120,8 @@ function isVertoPingInnerParams(value) {
16106
16120
 
16107
16121
  //#endregion
16108
16122
  //#region src/managers/VertoManager.ts
16109
- var import_cjs$12 = require_cjs();
16110
- const logger$13 = getLogger();
16123
+ var import_cjs$13 = require_cjs();
16124
+ const logger$14 = getLogger();
16111
16125
  var VertoManager = class extends Destroyable {
16112
16126
  constructor(callSession) {
16113
16127
  super();
@@ -16133,6 +16147,7 @@ var WebRTCVertoManager = class extends VertoManager {
16133
16147
  this._screenShareTimeoutMs = 5e4;
16134
16148
  this._nodeId$ = this.createBehaviorSubject(options.nodeId ?? null);
16135
16149
  this.onError = options.onError;
16150
+ this.onModifyFailed = options.onModifyFailed;
16136
16151
  this.initSubscriptions();
16137
16152
  this.initMainPeerConnection();
16138
16153
  }
@@ -16145,7 +16160,7 @@ var WebRTCVertoManager = class extends VertoManager {
16145
16160
  try {
16146
16161
  await this.executeVerto(vertoModifyMessage);
16147
16162
  } catch (error) {
16148
- 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);
16149
16164
  throw error;
16150
16165
  }
16151
16166
  }
@@ -16158,7 +16173,7 @@ var WebRTCVertoManager = class extends VertoManager {
16158
16173
  try {
16159
16174
  await this.executeVerto(vertoModifyMessage);
16160
16175
  } catch (error) {
16161
- 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);
16162
16177
  throw error;
16163
16178
  }
16164
16179
  }
@@ -16198,7 +16213,7 @@ var WebRTCVertoManager = class extends VertoManager {
16198
16213
  return rtcPeerConnection;
16199
16214
  }
16200
16215
  get signalingStatus$() {
16201
- 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) => [
16202
16217
  "connected",
16203
16218
  "disconnected",
16204
16219
  "failed"
@@ -16211,7 +16226,7 @@ var WebRTCVertoManager = class extends VertoManager {
16211
16226
  if (event.member_id) this.setSelfIdIfNull(event.member_id);
16212
16227
  });
16213
16228
  this.subscribeTo(this.vertoMedia$, (event) => {
16214
- 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);
16215
16230
  this._signalingStatus$.next("ringing");
16216
16231
  const { sdp, callID } = event;
16217
16232
  this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
@@ -16220,7 +16235,7 @@ var WebRTCVertoManager = class extends VertoManager {
16220
16235
  });
16221
16236
  });
16222
16237
  this.subscribeTo(this.vertoAnswer$, (event) => {
16223
- logger$13.debug("[WebRTCManager] Received Verto answer event:", event);
16238
+ logger$14.debug("[WebRTCManager] Received Verto answer event:", event);
16224
16239
  this._signalingStatus$.next("connecting");
16225
16240
  const { sdp, callID } = event;
16226
16241
  this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
@@ -16229,7 +16244,7 @@ var WebRTCVertoManager = class extends VertoManager {
16229
16244
  });
16230
16245
  });
16231
16246
  this.subscribeTo(this.vertoMediaParams$, (event) => {
16232
- logger$13.debug("[WebRTCManager] Received Verto mediaParams event:", event);
16247
+ logger$14.debug("[WebRTCManager] Received Verto mediaParams event:", event);
16233
16248
  const { mediaParams, callID } = event;
16234
16249
  const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callID);
16235
16250
  const { audio, video } = mediaParams;
@@ -16243,13 +16258,13 @@ var WebRTCVertoManager = class extends VertoManager {
16243
16258
  timestamp: Date.now()
16244
16259
  });
16245
16260
  } catch (error) {
16246
- logger$13.warn("[WebRTCManager] Error applying server-pushed media params:", error);
16261
+ logger$14.warn("[WebRTCManager] Error applying server-pushed media params:", error);
16247
16262
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16248
16263
  }
16249
16264
  })();
16250
16265
  });
16251
16266
  this.subscribeTo(this.vertoPing$, (vertoPing) => {
16252
- this.attachManager.attach(this.webRtcCallSession);
16267
+ this.attachManager.attach(this.buildAttachableCall());
16253
16268
  this.sendVertoPong(vertoPing);
16254
16269
  });
16255
16270
  }
@@ -16265,13 +16280,13 @@ var WebRTCVertoManager = class extends VertoManager {
16265
16280
  */
16266
16281
  setNodeIdIfNull(nodeId) {
16267
16282
  if (!this._nodeId$.value && nodeId) {
16268
- logger$13.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
16283
+ logger$14.debug(`[WebRTCManager] Early node_id set: ${nodeId}`);
16269
16284
  this._nodeId$.next(nodeId);
16270
16285
  }
16271
16286
  }
16272
16287
  setSelfIdIfNull(selfId) {
16273
16288
  if (!this._selfId$.value && selfId) {
16274
- logger$13.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
16289
+ logger$14.debug(`[WebRTCManager] Early selfId set: ${selfId}`);
16275
16290
  this._selfId$.next(selfId);
16276
16291
  }
16277
16292
  }
@@ -16280,7 +16295,7 @@ var WebRTCVertoManager = class extends VertoManager {
16280
16295
  const vertoPongMessage = VertoPong({ ...vertoPing });
16281
16296
  await this.executeVerto(vertoPongMessage);
16282
16297
  } catch (error) {
16283
- 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);
16284
16299
  this.onError?.(new VertoPongError(error));
16285
16300
  }
16286
16301
  }
@@ -16290,7 +16305,7 @@ var WebRTCVertoManager = class extends VertoManager {
16290
16305
  if (audio) await this.mainPeerConnection.updateSendersConstraints("audio", audio);
16291
16306
  if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
16292
16307
  } catch (error) {
16293
- logger$13.warn("[WebRTCManager] Error updating media constraints:", error);
16308
+ logger$14.warn("[WebRTCManager] Error updating media constraints:", error);
16294
16309
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16295
16310
  throw error;
16296
16311
  }
@@ -16298,6 +16313,15 @@ var WebRTCVertoManager = class extends VertoManager {
16298
16313
  get selfId() {
16299
16314
  return this._selfId$.value;
16300
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
+ }
16301
16325
  /**
16302
16326
  * Request a video keyframe via RTCP PLI/FIR.
16303
16327
  *
@@ -16311,20 +16335,20 @@ var WebRTCVertoManager = class extends VertoManager {
16311
16335
  try {
16312
16336
  const pc = this.mainPeerConnection.peerConnection;
16313
16337
  if (!pc) {
16314
- logger$13.warn("[WebRTCManager] No peer connection for keyframe request");
16338
+ logger$14.warn("[WebRTCManager] No peer connection for keyframe request");
16315
16339
  return;
16316
16340
  }
16317
16341
  const videoReceiver = pc.getReceivers().find((r) => r.track.kind === "video");
16318
16342
  if (!videoReceiver) {
16319
- logger$13.warn("[WebRTCManager] No video receiver for keyframe request");
16343
+ logger$14.warn("[WebRTCManager] No video receiver for keyframe request");
16320
16344
  return;
16321
16345
  }
16322
16346
  if (typeof videoReceiver.requestKeyFrame === "function") {
16323
16347
  videoReceiver.requestKeyFrame();
16324
- logger$13.debug("[WebRTCManager] Keyframe requested via RTCRtpReceiver.requestKeyFrame()");
16325
- } 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");
16326
16350
  } catch (error) {
16327
- logger$13.warn("[WebRTCManager] Keyframe request failed (non-fatal):", error);
16351
+ logger$14.warn("[WebRTCManager] Keyframe request failed (non-fatal):", error);
16328
16352
  }
16329
16353
  }
16330
16354
  /**
@@ -16342,13 +16366,13 @@ var WebRTCVertoManager = class extends VertoManager {
16342
16366
  try {
16343
16367
  const controller = this.mainPeerConnection;
16344
16368
  if (!controller.peerConnection) {
16345
- logger$13.warn("[WebRTCManager] No peer connection for ICE restart");
16369
+ logger$14.warn("[WebRTCManager] No peer connection for ICE restart");
16346
16370
  return;
16347
16371
  }
16348
16372
  await controller.triggerIceRestart(relayOnly);
16349
- logger$13.info(`[WebRTCManager] ICE restart initiated${relayOnly ? " (relay-only)" : ""}`);
16373
+ logger$14.info(`[WebRTCManager] ICE restart initiated${relayOnly ? " (relay-only)" : ""}`);
16350
16374
  } catch (error) {
16351
- logger$13.error("[WebRTCManager] ICE restart failed:", error);
16375
+ logger$14.error("[WebRTCManager] ICE restart failed:", error);
16352
16376
  throw error;
16353
16377
  }
16354
16378
  }
@@ -16366,13 +16390,13 @@ var WebRTCVertoManager = class extends VertoManager {
16366
16390
  const entries = Array.from(this._rtcPeerConnectionsMap.entries());
16367
16391
  for (const [id, controller] of entries) try {
16368
16392
  if (!controller.peerConnection) {
16369
- 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`);
16370
16394
  continue;
16371
16395
  }
16372
16396
  await controller.triggerIceRestart(relayOnly);
16373
- 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)" : ""}`);
16374
16398
  } catch (error) {
16375
- logger$13.warn(`[WebRTCManager] ICE restart failed for leg ${id}:`, error);
16399
+ logger$14.warn(`[WebRTCManager] ICE restart failed for leg ${id}:`, error);
16376
16400
  }
16377
16401
  }
16378
16402
  /**
@@ -16384,7 +16408,7 @@ var WebRTCVertoManager = class extends VertoManager {
16384
16408
  requestKeyframeAll() {
16385
16409
  for (const [id, controller] of this._rtcPeerConnectionsMap) {
16386
16410
  if (controller.isScreenShare) {
16387
- 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}`);
16388
16412
  continue;
16389
16413
  }
16390
16414
  try {
@@ -16394,33 +16418,33 @@ var WebRTCVertoManager = class extends VertoManager {
16394
16418
  if (!videoReceiver) continue;
16395
16419
  if (typeof videoReceiver.requestKeyFrame === "function") {
16396
16420
  videoReceiver.requestKeyFrame();
16397
- logger$13.debug(`[WebRTCManager] Keyframe requested for leg ${id}`);
16421
+ logger$14.debug(`[WebRTCManager] Keyframe requested for leg ${id}`);
16398
16422
  }
16399
16423
  } catch (error) {
16400
- 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);
16401
16425
  }
16402
16426
  }
16403
16427
  }
16404
16428
  get callJoinedEvent$() {
16405
- 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$));
16406
16430
  }
16407
16431
  get vertoMedia$() {
16408
- 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$));
16409
16433
  }
16410
16434
  get vertoAnswer$() {
16411
- 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$)));
16412
16436
  }
16413
16437
  get vertoMediaParams$() {
16414
- 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$)));
16415
16439
  }
16416
16440
  get vertoBye$() {
16417
- 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$)));
16418
16442
  }
16419
16443
  get vertoAttach$() {
16420
- 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$)));
16421
16445
  }
16422
16446
  get vertoPing$() {
16423
- 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$)));
16424
16448
  }
16425
16449
  async executeVerto(message, optionals = {}) {
16426
16450
  const webrtcVertoMessage = WebrtcVerto({
@@ -16445,7 +16469,7 @@ var WebRTCVertoManager = class extends VertoManager {
16445
16469
  }
16446
16470
  async sendLocalDescription(message, rtcPeerConnController) {
16447
16471
  const vertoMethod = message.method;
16448
- const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMethod);
16472
+ const optionalsParams = this.getSendLocalSDPOptionalParams(rtcPeerConnController, message);
16449
16473
  try {
16450
16474
  const response = await this.executeVerto(message, optionalsParams);
16451
16475
  switch (vertoMethod) {
@@ -16458,8 +16482,9 @@ var WebRTCVertoManager = class extends VertoManager {
16458
16482
  default:
16459
16483
  }
16460
16484
  } catch (error) {
16461
- logger$13.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
16485
+ logger$14.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
16462
16486
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16487
+ if (vertoMethod === "verto.modify") this.onModifyFailed?.();
16463
16488
  }
16464
16489
  }
16465
16490
  async processModifyResponse(response, rtcPeerConnController) {
@@ -16472,7 +16497,7 @@ var WebRTCVertoManager = class extends VertoManager {
16472
16497
  sdp
16473
16498
  });
16474
16499
  } catch (error) {
16475
- logger$13.warn("[WebRTCManager] Error processing modify response:", error);
16500
+ logger$14.warn("[WebRTCManager] Error processing modify response:", error);
16476
16501
  const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
16477
16502
  this.onError?.(modifyError);
16478
16503
  }
@@ -16484,19 +16509,24 @@ var WebRTCVertoManager = class extends VertoManager {
16484
16509
  this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
16485
16510
  const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
16486
16511
  const callId = getValueFrom(response, "result.result.result.callID") ?? null;
16487
- logger$13.debug("[WebRTCManager] Verto invite response:", {
16512
+ logger$14.debug("[WebRTCManager] Verto invite response:", {
16488
16513
  callId,
16489
16514
  memberId,
16490
16515
  response
16491
16516
  });
16492
16517
  this._selfId$.next(memberId);
16493
16518
  rtcPeerConnController.setMemberId(memberId);
16494
- if (callId) this.webRtcCallSession.addCallId(callId);
16495
- this.attachManager.attach(this.webRtcCallSession);
16496
- logger$13.info("[WebRTCManager] Verto invite successful");
16497
- 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}`);
16498
16528
  } else {
16499
- logger$13.error("[WebRTCManager] Verto invite failed:", response);
16529
+ logger$14.error("[WebRTCManager] Verto invite failed:", response);
16500
16530
  const inviteError = response.error ? new JSONRPCError(response.error.code, response.error.message, response.error.data) : /* @__PURE__ */ new Error("Verto invite failed: unexpected response");
16501
16531
  this.onError?.(inviteError);
16502
16532
  }
@@ -16541,17 +16571,17 @@ var WebRTCVertoManager = class extends VertoManager {
16541
16571
  if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
16542
16572
  }
16543
16573
  async handleInboundAnswer(rtcPeerConnController) {
16544
- logger$13.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
16545
- 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);
16546
16576
  if (vertoByeOrAccepted === null) {
16547
- logger$13.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
16577
+ logger$14.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
16548
16578
  return;
16549
16579
  }
16550
16580
  if (isVertoByeMessage(vertoByeOrAccepted)) {
16551
- logger$13.info("[WebRTCManager] Inbound call ended by remote before answer.");
16581
+ logger$14.info("[WebRTCManager] Inbound call ended by remote before answer.");
16552
16582
  this.callSession?.destroy();
16553
16583
  } else if (!vertoByeOrAccepted) {
16554
- logger$13.info("[WebRTCManager] Inbound call rejected by user.");
16584
+ logger$14.info("[WebRTCManager] Inbound call rejected by user.");
16555
16585
  try {
16556
16586
  await this.bye("USER_BUSY");
16557
16587
  } finally {
@@ -16559,21 +16589,22 @@ var WebRTCVertoManager = class extends VertoManager {
16559
16589
  this.callSession?.destroy();
16560
16590
  }
16561
16591
  } else {
16562
- logger$13.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
16592
+ logger$14.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
16563
16593
  const answerOptions = this.webRtcCallSession.answerMediaOptions;
16564
16594
  try {
16565
16595
  await rtcPeerConnController.acceptInbound(answerOptions);
16566
16596
  } catch (error) {
16567
- logger$13.error("[WebRTCManager] Error creating inbound answer:", error);
16597
+ logger$14.error("[WebRTCManager] Error creating inbound answer:", error);
16568
16598
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16569
16599
  }
16570
16600
  }
16571
16601
  }
16572
16602
  setupVertoAttachHandler() {
16573
16603
  this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
16574
- 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);
16575
16605
  const { callID } = vertoAttach;
16576
16606
  await this.attachManager.attach({
16607
+ nodeId: this.nodeId ?? void 0,
16577
16608
  id: callID,
16578
16609
  to: vertoAttach.callee_id_number,
16579
16610
  mediaDirections: {
@@ -16584,12 +16615,12 @@ var WebRTCVertoManager = class extends VertoManager {
16584
16615
  });
16585
16616
  }
16586
16617
  initObservables(rtcPeerConnController) {
16587
- 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$));
16588
- this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$12.takeUntil)(this.destroyed$));
16589
- 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$));
16590
16621
  }
16591
16622
  setupLocalDescriptionHandler(rtcPeerConnController) {
16592
- 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) => {
16593
16624
  const { type, sdp } = description;
16594
16625
  const dialogParams = this.dialogParams(rtcPeerConnController);
16595
16626
  const initial = !rtcPeerConnController.firstSDPExchangeCompleted;
@@ -16618,11 +16649,11 @@ var WebRTCVertoManager = class extends VertoManager {
16618
16649
  setupVertoByeHandler() {
16619
16650
  this.subscribeTo(this.vertoBye$, () => {
16620
16651
  this._signalingStatus$.next("disconnected");
16621
- this.attachManager.detach(this.webRtcCallSession);
16652
+ this.attachManager.detach(this.buildAttachableCall());
16622
16653
  this.callSession?.destroy();
16623
16654
  });
16624
16655
  }
16625
- getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMethod) {
16656
+ getSendLocalSDPOptionalParams(rtcPeerConnController, vertoMessage) {
16626
16657
  let subscribe = void 0;
16627
16658
  if (!rtcPeerConnController.firstSDPExchangeCompleted) {
16628
16659
  subscribe = [];
@@ -16630,7 +16661,7 @@ var WebRTCVertoManager = class extends VertoManager {
16630
16661
  else if (rtcPeerConnController.isAdditionalDevice) subscribe.push(...PreferencesContainer.instance.inviteSubscribeAdditionalDevice);
16631
16662
  else if (rtcPeerConnController.isScreenShare) subscribe.push(...PreferencesContainer.instance.inviteSubscribeScreenshare);
16632
16663
  }
16633
- const isInvite = vertoMethod === "verto.invite";
16664
+ const isInvite = isVertoInviteMessage(vertoMessage);
16634
16665
  const isReattach = isInvite && this.webRtcCallSession.options.reattach;
16635
16666
  return {
16636
16667
  callID: rtcPeerConnController.id,
@@ -16639,13 +16670,13 @@ var WebRTCVertoManager = class extends VertoManager {
16639
16670
  };
16640
16671
  }
16641
16672
  async sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnectionController) {
16642
- logger$13.debug("[WebRTCManager] Waiting for call to be accepted or ended before sending answer");
16643
- 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$));
16644
16675
  if (isVertoByeMessage(vertoByeOrAccepted)) {
16645
- logger$13.info("[WebRTCManager] Call ended before answer was sent.");
16676
+ logger$14.info("[WebRTCManager] Call ended before answer was sent.");
16646
16677
  this.callSession?.destroy();
16647
16678
  } else if (!vertoByeOrAccepted) {
16648
- logger$13.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
16679
+ logger$14.info("[WebRTCManager] Call was not accepted, sending verto.bye.");
16649
16680
  try {
16650
16681
  await this.bye("USER_BUSY");
16651
16682
  } finally {
@@ -16653,14 +16684,14 @@ var WebRTCVertoManager = class extends VertoManager {
16653
16684
  this.callSession?.destroy();
16654
16685
  }
16655
16686
  } else {
16656
- logger$13.debug("[WebRTCManager] Call accepted, sending answer");
16687
+ logger$14.debug("[WebRTCManager] Call accepted, sending answer");
16657
16688
  try {
16658
16689
  this._signalingStatus$.next("connecting");
16659
16690
  await this.sendLocalDescription(vertoMessageRequest, rtcPeerConnectionController);
16660
16691
  await rtcPeerConnectionController.updateAnswerStatus({ status: "sent" });
16661
- await this.attachManager.attach(this.webRtcCallSession);
16692
+ await this.attachManager.attach(this.buildAttachableCall());
16662
16693
  } catch (error) {
16663
- logger$13.error("[WebRTCManager] Error sending Verto answer:", error);
16694
+ logger$14.error("[WebRTCManager] Error sending Verto answer:", error);
16664
16695
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16665
16696
  await rtcPeerConnectionController.updateAnswerStatus({ status: "failed" });
16666
16697
  }
@@ -16749,12 +16780,12 @@ var WebRTCVertoManager = class extends VertoManager {
16749
16780
  this.subscribeTo(rtcPeerConnController.errors$, (error) => {
16750
16781
  this.onError?.(error);
16751
16782
  });
16752
- 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)));
16753
16784
  this._screenShareStatus$.next("started");
16754
- logger$13.info("[WebRTCManager] Screen share started successfully.");
16785
+ logger$14.info("[WebRTCManager] Screen share started successfully.");
16755
16786
  return rtcPeerConnController.id;
16756
16787
  } catch (error) {
16757
- logger$13.warn("[WebRTCManager] Error initializing additional peer connection:", error);
16788
+ logger$14.warn("[WebRTCManager] Error initializing additional peer connection:", error);
16758
16789
  this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
16759
16790
  if (rtcPeerConnController) rtcPeerConnController.destroy();
16760
16791
  this._screenShareStatus$.next("none");
@@ -16773,9 +16804,9 @@ var WebRTCVertoManager = class extends VertoManager {
16773
16804
  if (removeTrack) return this.mainPeerConnection.stopTrackSender(removeTrack, { updateTransceiverDirection: true });
16774
16805
  }
16775
16806
  async removeScreenMedia() {
16776
- 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.");
16777
16808
  if (!this._screenShareId) {
16778
- logger$13.debug("[WebRTCManager] No screen share peer connection found.");
16809
+ logger$14.debug("[WebRTCManager] No screen share peer connection found.");
16779
16810
  return;
16780
16811
  }
16781
16812
  this._screenShareStatus$.next("stopping");
@@ -16804,12 +16835,12 @@ var WebRTCVertoManager = class extends VertoManager {
16804
16835
  dialogParams: this.dialogParams(rtcPeerConnController)
16805
16836
  }));
16806
16837
  } catch (error) {
16807
- 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);
16808
16839
  throw error;
16809
16840
  }
16810
16841
  }
16811
16842
  async bye(cause) {
16812
- this.attachManager.detach(this.webRtcCallSession);
16843
+ this.attachManager.detach(this.buildAttachableCall());
16813
16844
  const rtcPeerConnController = this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id);
16814
16845
  if (rtcPeerConnController) await this.executeVertoBye(rtcPeerConnController, cause);
16815
16846
  }
@@ -16822,7 +16853,7 @@ var WebRTCVertoManager = class extends VertoManager {
16822
16853
  try {
16823
16854
  await this.executeVerto(vertoInfoMessage);
16824
16855
  } catch (error) {
16825
- logger$13.warn("[WebRTCManager] Error sending DTMF digits:", error);
16856
+ logger$14.warn("[WebRTCManager] Error sending DTMF digits:", error);
16826
16857
  throw error;
16827
16858
  }
16828
16859
  }
@@ -16833,10 +16864,10 @@ var WebRTCVertoManager = class extends VertoManager {
16833
16864
  action: "transfer"
16834
16865
  });
16835
16866
  try {
16836
- logger$13.debug("[WebRTCManager] Transferring call with options:", options);
16867
+ logger$14.debug("[WebRTCManager] Transferring call with options:", options);
16837
16868
  await this.executeVerto(message);
16838
16869
  } catch (error) {
16839
- logger$13.error("[WebRTCManager] Error transferring call:", error);
16870
+ logger$14.error("[WebRTCManager] Error transferring call:", error);
16840
16871
  throw error;
16841
16872
  }
16842
16873
  }
@@ -16852,8 +16883,8 @@ var WebRTCVertoManager = class extends VertoManager {
16852
16883
 
16853
16884
  //#endregion
16854
16885
  //#region src/controllers/RTCStatsMonitor.ts
16855
- var import_cjs$11 = require_cjs();
16856
- const logger$12 = getLogger();
16886
+ var import_cjs$12 = require_cjs();
16887
+ const logger$13 = getLogger();
16857
16888
  const DEFAULT_POLLING_INTERVAL_MS = 1e3;
16858
16889
  const DEFAULT_BASELINE_SAMPLES = 10;
16859
16890
  const DEFAULT_NO_AUDIO_PACKET_THRESHOLD_MS = 2e3;
@@ -16915,7 +16946,7 @@ var RTCStatsMonitor = class extends Destroyable {
16915
16946
  }
16916
16947
  /** Simple boolean health indicator. */
16917
16948
  get isNetworkHealthy$() {
16918
- 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$)));
16919
16950
  }
16920
16951
  /** Whether the network is currently healthy. */
16921
16952
  get isNetworkHealthy() {
@@ -16931,7 +16962,7 @@ var RTCStatsMonitor = class extends Destroyable {
16931
16962
  }
16932
16963
  /** Emits individual critical issues for the recovery pipeline. */
16933
16964
  get criticalIssue$() {
16934
- 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$)));
16935
16966
  }
16936
16967
  /** Emits each raw stats sample extracted from the peer connection. */
16937
16968
  get sample$() {
@@ -16943,32 +16974,32 @@ var RTCStatsMonitor = class extends Destroyable {
16943
16974
  const now = Date.now();
16944
16975
  this.lastAudioPacketChangeTime = now;
16945
16976
  this.lastVideoPacketChangeTime = now;
16946
- logger$12.debug("[RTCStatsMonitor] Starting stats monitoring");
16947
- 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) => {
16948
- logger$12.warn("[RTCStatsMonitor] Failed to get stats:", err);
16949
- return import_cjs$11.EMPTY;
16950
- }))), (0, import_cjs$11.filter)(() => this.running), (0, import_cjs$11.map)((report) => this.extractSample(report))), (sample$1) => this._sample$.next(sample$1));
16951
- 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) => ({
16952
16983
  rtt: samples.reduce((s, b) => s + b.roundTripTime, 0) / samples.length,
16953
16984
  jitter: samples.reduce((s, b) => s + b.audioJitter, 0) / samples.length,
16954
16985
  ready: true
16955
16986
  }))), (baseline) => {
16956
- 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`);
16957
16988
  this._baseline$.next(baseline);
16958
16989
  });
16959
- 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) => ({
16960
16991
  prev: acc.current,
16961
16992
  current: sample$1
16962
16993
  }), {
16963
16994
  prev: null,
16964
16995
  current: null
16965
- }), (0, import_cjs$11.filter)((pair) => pair.current !== null)), ({ prev, current }) => {
16996
+ }), (0, import_cjs$12.filter)((pair) => pair.current !== null)), ({ prev, current }) => {
16966
16997
  const now$1 = current.timestamp;
16967
16998
  this.updatePacketTracking(current, now$1);
16968
16999
  const issues = this.detectIssues(current, prev, now$1);
16969
17000
  this._networkIssues$.next(issues);
16970
17001
  });
16971
- 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) => {
16972
17003
  const cutoff = sample$1.timestamp - this.historyWindowSeconds * 1e3;
16973
17004
  const metrics = {
16974
17005
  timestamp: sample$1.timestamp,
@@ -16990,10 +17021,10 @@ var RTCStatsMonitor = class extends Destroyable {
16990
17021
  stop() {
16991
17022
  if (!this.running) return;
16992
17023
  this.running = false;
16993
- logger$12.debug("[RTCStatsMonitor] Stopping stats monitoring");
17024
+ logger$13.debug("[RTCStatsMonitor] Stopping stats monitoring");
16994
17025
  }
16995
17026
  destroy() {
16996
- logger$12.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor");
17027
+ logger$13.debug("[RTCStatsMonitor] Destroying RTCStatsMonitor");
16997
17028
  this.stop();
16998
17029
  super.destroy();
16999
17030
  }
@@ -17121,8 +17152,8 @@ var RTCStatsMonitor = class extends Destroyable {
17121
17152
 
17122
17153
  //#endregion
17123
17154
  //#region src/managers/CallRecoveryManager.ts
17124
- var import_cjs$10 = require_cjs();
17125
- const logger$11 = getLogger();
17155
+ var import_cjs$11 = require_cjs();
17156
+ const logger$12 = getLogger();
17126
17157
  const DEFAULT_DEBOUNCE_TIME_MS = 2e3;
17127
17158
  const DEFAULT_COOLDOWN_MS = 1e4;
17128
17159
  const DEFAULT_ICE_GRACE_PERIOD_MS = 3e3;
@@ -17158,7 +17189,7 @@ const DEGRADATION_ONLY_ISSUES = new Set([
17158
17189
  * A state machine tracks the pipeline: IDLE -> DEBOUNCING -> RECOVERING -> COOLDOWN.
17159
17190
  */
17160
17191
  var CallRecoveryManager = class extends Destroyable {
17161
- constructor(callbacks, config = {}) {
17192
+ constructor(callbacks, inputs, config = {}) {
17162
17193
  super();
17163
17194
  this._recoveryState$ = this.createBehaviorSubject("idle");
17164
17195
  this._recoveryEvent$ = this.createSubject();
@@ -17172,6 +17203,7 @@ var CallRecoveryManager = class extends Destroyable {
17172
17203
  this._cooldownUntil = 0;
17173
17204
  this._pipelineStop$ = this.createSubject();
17174
17205
  this._callbacks = callbacks;
17206
+ this._inputs = inputs;
17175
17207
  this._config = {
17176
17208
  debounceTimeMs: config.debounceTimeMs ?? DEFAULT_DEBOUNCE_TIME_MS,
17177
17209
  cooldownMs: config.cooldownMs ?? DEFAULT_COOLDOWN_MS,
@@ -17191,16 +17223,16 @@ var CallRecoveryManager = class extends Destroyable {
17191
17223
  this.initDegradationRecoveryPipeline();
17192
17224
  }
17193
17225
  get recoveryState$() {
17194
- 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$));
17195
17227
  }
17196
17228
  get recoveryState() {
17197
17229
  return this._recoveryState$.value;
17198
17230
  }
17199
17231
  get recoveryEvent$() {
17200
- 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$));
17201
17233
  }
17202
17234
  get bandwidthConstrained$() {
17203
- 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$));
17204
17236
  }
17205
17237
  get bandwidthConstrained() {
17206
17238
  return this._bandwidthConstrained$.value;
@@ -17218,10 +17250,10 @@ var CallRecoveryManager = class extends Destroyable {
17218
17250
  */
17219
17251
  async requestIceRestart() {
17220
17252
  if (this._recoveryState$.value === "recovering") {
17221
- 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");
17222
17254
  return;
17223
17255
  }
17224
- logger$11.info("CallRecoveryManager: manual ICE restart requested");
17256
+ logger$12.info("CallRecoveryManager: manual ICE restart requested");
17225
17257
  this.transitionTo("recovering");
17226
17258
  await this.executeIceRestart(false);
17227
17259
  this.startCooldown();
@@ -17237,7 +17269,7 @@ var CallRecoveryManager = class extends Destroyable {
17237
17269
  * WebSocket reconnect or call state recovers to 'connected'.
17238
17270
  */
17239
17271
  reset() {
17240
- logger$11.info("CallRecoveryManager: resetting counters");
17272
+ logger$12.info("CallRecoveryManager: resetting counters");
17241
17273
  this._attemptCount = 0;
17242
17274
  this._keyframeBurstCount = 0;
17243
17275
  this._keyframeBurstStart = 0;
@@ -17246,6 +17278,22 @@ var CallRecoveryManager = class extends Destroyable {
17246
17278
  this.transitionTo("idle");
17247
17279
  }
17248
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
+ /**
17249
17297
  * Feed bandwidth information for graceful degradation (Section 22).
17250
17298
  * Call this from the stats monitor with current available outgoing bitrate.
17251
17299
  */
@@ -17260,7 +17308,7 @@ var CallRecoveryManager = class extends Destroyable {
17260
17308
  reason: `bandwidth ${bitrateKbps}kbps below threshold ${this._config.degradationBitrateThreshold}kbps`,
17261
17309
  timestamp: Date.now()
17262
17310
  });
17263
- 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`);
17264
17312
  } else if (wasConstrained && bitrateKbps >= this._config.degradationRecoveryThreshold) {
17265
17313
  this._bandwidthConstrained$.next(false);
17266
17314
  this._callbacks.enableVideo();
@@ -17269,7 +17317,7 @@ var CallRecoveryManager = class extends Destroyable {
17269
17317
  reason: `bandwidth ${bitrateKbps}kbps recovered above ${this._config.degradationRecoveryThreshold}kbps`,
17270
17318
  timestamp: Date.now()
17271
17319
  });
17272
- 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`);
17273
17321
  }
17274
17322
  }
17275
17323
  /**
@@ -17288,14 +17336,14 @@ var CallRecoveryManager = class extends Destroyable {
17288
17336
  handleWebSocketReconnect() {
17289
17337
  const pcState = this._callbacks.getPeerConnectionState();
17290
17338
  if (pcState === "connected" || pcState === "completed") {
17291
- logger$11.info("CallRecoveryManager: signal-only reconnect — peer connection still alive");
17339
+ logger$12.info("CallRecoveryManager: signal-only reconnect — peer connection still alive");
17292
17340
  this.emitEvent({
17293
17341
  action: "signal_reconnect",
17294
17342
  reason: "WebSocket reconnected, peer connection still connected",
17295
17343
  timestamp: Date.now()
17296
17344
  });
17297
17345
  } else {
17298
- logger$11.info("CallRecoveryManager: full reconnect — peer connection also down");
17346
+ logger$12.info("CallRecoveryManager: full reconnect — peer connection also down");
17299
17347
  this.emitEvent({
17300
17348
  action: "full_reconnect",
17301
17349
  reason: "WebSocket reconnected, peer connection not connected — ICE restart needed",
@@ -17314,12 +17362,12 @@ var CallRecoveryManager = class extends Destroyable {
17314
17362
  super.destroy();
17315
17363
  }
17316
17364
  initPipeline() {
17317
- this.subscribeTo(this._trigger$.pipe((0, import_cjs$10.tap)(() => {
17365
+ this.subscribeTo(this._trigger$.pipe((0, import_cjs$11.tap)(() => {
17318
17366
  if (this._recoveryState$.value === "idle") this.transitionTo("debouncing");
17319
- }), (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$))), {
17320
17368
  next: () => {},
17321
17369
  error: (err) => {
17322
- logger$11.error("CallRecoveryManager: pipeline error", err);
17370
+ logger$12.error("CallRecoveryManager: pipeline error", err);
17323
17371
  this.transitionTo("idle");
17324
17372
  }
17325
17373
  });
@@ -17335,10 +17383,10 @@ var CallRecoveryManager = class extends Destroyable {
17335
17383
  initDegradationRecoveryPipeline() {
17336
17384
  if (!this._config.enableAutoDegradation) return;
17337
17385
  const delayMs = this._config.packetLossRecoveryDelaySec * 1e3;
17338
- this.subscribeTo((0, import_cjs$10.combineLatest)([this._bandwidthConstrained$, this._hasPacketLoss$]).pipe((0, import_cjs$10.switchMap)(([constrained, hasPacketLoss]) => {
17339
- if (constrained && !hasPacketLoss) return (0, import_cjs$10.timer)(delayMs);
17340
- return import_cjs$10.EMPTY;
17341
- }), (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$)), () => {
17342
17390
  this._bandwidthConstrained$.next(false);
17343
17391
  this._callbacks.enableVideo();
17344
17392
  this.emitEvent({
@@ -17346,27 +17394,27 @@ var CallRecoveryManager = class extends Destroyable {
17346
17394
  reason: `no packet loss for ${this._config.packetLossRecoveryDelaySec}s — restoring video`,
17347
17395
  timestamp: Date.now()
17348
17396
  });
17349
- 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`);
17350
17398
  });
17351
17399
  }
17352
- passGateChecks() {
17400
+ passGateChecks(signalingReady) {
17353
17401
  if (this._callbacks.isNegotiating()) {
17354
- logger$11.debug("CallRecoveryManager: gate blocked — negotiation in progress");
17402
+ logger$12.debug("CallRecoveryManager: gate blocked — negotiation in progress");
17355
17403
  this.transitionTo("idle");
17356
17404
  return false;
17357
17405
  }
17358
- if (!this._callbacks.isWebSocketConnected()) {
17359
- logger$11.debug("CallRecoveryManager: gate blocked — WebSocket not connected");
17406
+ if (!signalingReady) {
17407
+ logger$12.debug("CallRecoveryManager: gate blocked — signaling not ready");
17360
17408
  this.transitionTo("idle");
17361
17409
  return false;
17362
17410
  }
17363
17411
  if (!this._callbacks.isCallConnected()) {
17364
- logger$11.debug("CallRecoveryManager: gate blocked — call not connected");
17412
+ logger$12.debug("CallRecoveryManager: gate blocked — call not connected");
17365
17413
  this.transitionTo("idle");
17366
17414
  return false;
17367
17415
  }
17368
17416
  if (this.isCooldownActive()) {
17369
- logger$11.debug("CallRecoveryManager: gate blocked — cooldown active");
17417
+ logger$12.debug("CallRecoveryManager: gate blocked — cooldown active");
17370
17418
  this.transitionTo("cooldown");
17371
17419
  return false;
17372
17420
  }
@@ -17377,17 +17425,17 @@ var CallRecoveryManager = class extends Destroyable {
17377
17425
  }
17378
17426
  executeTieredRecovery(trigger) {
17379
17427
  this.transitionTo("recovering");
17380
- logger$11.info(`CallRecoveryManager: starting tiered recovery — source=${trigger.source} detail=${trigger.detail}`);
17381
- return (0, import_cjs$10.from)(this.runTiers(trigger)).pipe((0, import_cjs$10.tap)(() => this.startCooldown()), (0, import_cjs$10.catchError)((err) => {
17382
- 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);
17383
17431
  this.startCooldown();
17384
- return import_cjs$10.EMPTY;
17432
+ return import_cjs$11.EMPTY;
17385
17433
  }));
17386
17434
  }
17387
17435
  async runTiers(trigger) {
17388
17436
  this.executeKeyframe(trigger.detail);
17389
17437
  if (trigger.issueType && DEGRADATION_ONLY_ISSUES.has(trigger.issueType)) {
17390
- 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`);
17391
17439
  return;
17392
17440
  }
17393
17441
  if (this._attemptCount < this._config.maxAttempts) {
@@ -17404,13 +17452,13 @@ var CallRecoveryManager = class extends Destroyable {
17404
17452
  maxAttempts: this._config.maxAttempts,
17405
17453
  timestamp: Date.now()
17406
17454
  });
17407
- logger$11.warn("CallRecoveryManager: max recovery attempts reached");
17455
+ logger$12.warn("CallRecoveryManager: max recovery attempts reached");
17408
17456
  }
17409
17457
  }
17410
17458
  executeKeyframe(reason) {
17411
17459
  const now = Date.now();
17412
17460
  if (now < this._keyframeCooldownUntil) {
17413
- logger$11.debug("CallRecoveryManager: keyframe request skipped — cooldown active");
17461
+ logger$12.debug("CallRecoveryManager: keyframe request skipped — cooldown active");
17414
17462
  return;
17415
17463
  }
17416
17464
  if (now - this._keyframeBurstStart > this._config.keyframeBurstWindowMs) {
@@ -17419,7 +17467,7 @@ var CallRecoveryManager = class extends Destroyable {
17419
17467
  }
17420
17468
  if (this._keyframeBurstCount >= this._config.keyframeMaxBurst) {
17421
17469
  this._keyframeCooldownUntil = now + this._config.keyframeCooldownMs;
17422
- 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}`);
17423
17471
  return;
17424
17472
  }
17425
17473
  this._keyframeBurstCount += 1;
@@ -17429,12 +17477,12 @@ var CallRecoveryManager = class extends Destroyable {
17429
17477
  reason,
17430
17478
  timestamp: now
17431
17479
  });
17432
- 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})`);
17433
17481
  }
17434
17482
  async executeIceRestart(relayOnly) {
17435
17483
  this._attemptCount += 1;
17436
17484
  const tier = relayOnly ? "Tier 3 (relay-only)" : "Tier 2 (standard)";
17437
- 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}`);
17438
17486
  this.emitEvent({
17439
17487
  action: "reinvite_started",
17440
17488
  reason: `${tier} ICE restart`,
@@ -17451,7 +17499,7 @@ var CallRecoveryManager = class extends Destroyable {
17451
17499
  maxAttempts: this._config.maxAttempts,
17452
17500
  timestamp: Date.now()
17453
17501
  });
17454
- logger$11.info(`CallRecoveryManager: ${tier} ICE restart succeeded`);
17502
+ logger$12.info(`CallRecoveryManager: ${tier} ICE restart succeeded`);
17455
17503
  this._attemptCount = 0;
17456
17504
  return true;
17457
17505
  }
@@ -17462,7 +17510,7 @@ var CallRecoveryManager = class extends Destroyable {
17462
17510
  maxAttempts: this._config.maxAttempts,
17463
17511
  timestamp: Date.now()
17464
17512
  });
17465
- logger$11.warn(`CallRecoveryManager: ${tier} ICE restart failed`);
17513
+ logger$12.warn(`CallRecoveryManager: ${tier} ICE restart failed`);
17466
17514
  return false;
17467
17515
  } catch {
17468
17516
  this.emitEvent({
@@ -17472,7 +17520,7 @@ var CallRecoveryManager = class extends Destroyable {
17472
17520
  maxAttempts: this._config.maxAttempts,
17473
17521
  timestamp: Date.now()
17474
17522
  });
17475
- logger$11.warn(`CallRecoveryManager: ${tier} ICE restart timed out`);
17523
+ logger$12.warn(`CallRecoveryManager: ${tier} ICE restart timed out`);
17476
17524
  return false;
17477
17525
  }
17478
17526
  }
@@ -17493,7 +17541,7 @@ var CallRecoveryManager = class extends Destroyable {
17493
17541
  transitionTo(state) {
17494
17542
  const prev = this._recoveryState$.value;
17495
17543
  if (prev !== state) {
17496
- logger$11.debug(`CallRecoveryManager: state ${prev} -> ${state}`);
17544
+ logger$12.debug(`CallRecoveryManager: state ${prev} -> ${state}`);
17497
17545
  this._recoveryState$.next(state);
17498
17546
  }
17499
17547
  }
@@ -17501,7 +17549,7 @@ var CallRecoveryManager = class extends Destroyable {
17501
17549
  this._cooldownUntil = Date.now() + this._config.cooldownMs;
17502
17550
  this.transitionTo("cooldown");
17503
17551
  if (this._cooldownSubscription) this._cooldownSubscription.unsubscribe();
17504
- 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"));
17505
17553
  }
17506
17554
  emitEvent(event) {
17507
17555
  this._recoveryEvent$.next(event);
@@ -17595,8 +17643,8 @@ function mosToQualityLevel(mos) {
17595
17643
 
17596
17644
  //#endregion
17597
17645
  //#region src/core/entities/Call.ts
17598
- var import_cjs$9 = require_cjs();
17599
- const logger$10 = getLogger();
17646
+ var import_cjs$10 = require_cjs();
17647
+ const logger$11 = getLogger();
17600
17648
  /**
17601
17649
  * Ratio between the critical and warning RTT spike multipliers.
17602
17650
  * Warning threshold = baseline * warningMultiplier (default 3x)
@@ -17614,7 +17662,7 @@ const fromDestinationParams = (destination) => {
17614
17662
  });
17615
17663
  return params;
17616
17664
  } catch (error) {
17617
- logger$10.warn(`Failed to parse destination URI: ${destination}`, error);
17665
+ logger$11.warn(`Failed to parse destination URI: ${destination}`, error);
17618
17666
  return {};
17619
17667
  }
17620
17668
  };
@@ -17670,10 +17718,13 @@ var WebRTCCall = class extends Destroyable {
17670
17718
  const { deviceController, networkChange$ } = initialization;
17671
17719
  this._networkChange$ = networkChange$;
17672
17720
  this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
17673
- 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) => {
17674
17722
  this._lastMergedStatus = status;
17675
17723
  if (status === "connected" && !this._statsMonitor) this.initResilienceSubsystems();
17676
- 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();
17677
17728
  });
17678
17729
  }
17679
17730
  /** Observable stream of errors from media, signaling, and peer connection layers. */
@@ -17692,13 +17743,17 @@ var WebRTCCall = class extends Destroyable {
17692
17743
  this.destroy();
17693
17744
  }
17694
17745
  }
17746
+ /** Notify the recovery manager that a verto.modify signaling exchange failed. */
17747
+ notifyModifyFailed() {
17748
+ this._recoveryManager?.notifyModifyFailed();
17749
+ }
17695
17750
  /** Whether this call is `'inbound'` or `'outbound'`. */
17696
17751
  get direction() {
17697
17752
  return this.options.initOffer ? "inbound" : "outbound";
17698
17753
  }
17699
17754
  /** Observable of the address associated with this call. */
17700
17755
  get address$() {
17701
- 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$));
17702
17757
  }
17703
17758
  /** Display name of the caller. */
17704
17759
  get fromName() {
@@ -17777,7 +17832,7 @@ var WebRTCCall = class extends Destroyable {
17777
17832
  }
17778
17833
  /** Observable of layout layer positions for all participants. */
17779
17834
  get layoutLayers$() {
17780
- 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$));
17781
17836
  }
17782
17837
  /** Current snapshot of layout layers. */
17783
17838
  get layoutLayers() {
@@ -17805,7 +17860,7 @@ var WebRTCCall = class extends Destroyable {
17805
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);
17806
17861
  return response;
17807
17862
  } catch (error) {
17808
- 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);
17809
17864
  throw error;
17810
17865
  }
17811
17866
  }
@@ -17832,45 +17887,45 @@ var WebRTCCall = class extends Destroyable {
17832
17887
  }
17833
17888
  /** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
17834
17889
  get status$() {
17835
- 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) => {
17836
17891
  this._lastMergedStatus = status;
17837
17892
  })));
17838
17893
  }
17839
17894
  /** Observable of the participants list, emits on join/leave/update. */
17840
17895
  get participants$() {
17841
- 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$));
17842
17897
  }
17843
17898
  /** Observable of the local (self) participant. */
17844
17899
  get self$() {
17845
- 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$));
17846
17901
  }
17847
17902
  /** Observable indicating whether the call is being recorded. */
17848
17903
  get recording$() {
17849
- 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$));
17850
17905
  }
17851
17906
  /** Observable indicating whether the call is being streamed. */
17852
17907
  get streaming$() {
17853
- 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$));
17854
17909
  }
17855
17910
  /** Observable indicating whether raise-hand priority is active. */
17856
17911
  get raiseHandPriority$() {
17857
- 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$));
17858
17913
  }
17859
17914
  /** Observable indicating whether the call room is locked. */
17860
17915
  get locked$() {
17861
- 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$));
17862
17917
  }
17863
17918
  /** Observable of custom metadata associated with the call. */
17864
17919
  get meta$() {
17865
- 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$));
17866
17921
  }
17867
17922
  /** Observable of the call's capability flags. */
17868
17923
  get capabilities$() {
17869
- 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$));
17870
17925
  }
17871
17926
  /** Observable of the current layout name. */
17872
17927
  get layout$() {
17873
- 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$));
17874
17929
  }
17875
17930
  /** Current call status. */
17876
17931
  get status() {
@@ -17902,7 +17957,7 @@ var WebRTCCall = class extends Destroyable {
17902
17957
  }
17903
17958
  /** Observable of available layout names. */
17904
17959
  get layouts$() {
17905
- 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$));
17906
17961
  }
17907
17962
  /** Current snapshot of available layout names. */
17908
17963
  get layouts() {
@@ -17910,7 +17965,7 @@ var WebRTCCall = class extends Destroyable {
17910
17965
  }
17911
17966
  /** Observable of the local media stream (camera/microphone). */
17912
17967
  get localStream$() {
17913
- 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$));
17914
17969
  }
17915
17970
  /** Current local media stream, or `null` if not available. */
17916
17971
  get localStream() {
@@ -17918,7 +17973,7 @@ var WebRTCCall = class extends Destroyable {
17918
17973
  }
17919
17974
  /** Observable of the remote media stream from the far end. */
17920
17975
  get remoteStream$() {
17921
- 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$));
17922
17977
  }
17923
17978
  /** Current remote media stream, or `null` if not available. */
17924
17979
  get remoteStream() {
@@ -18008,9 +18063,9 @@ var WebRTCCall = class extends Destroyable {
18008
18063
  */
18009
18064
  initResilienceSubsystems() {
18010
18065
  const pc = this.rtcPeerConnection;
18011
- 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}`);
18012
18067
  if (!pc) {
18013
- logger$10.warn("[Call] No peer connection available, skipping resilience init");
18068
+ logger$11.warn("[Call] No peer connection available, skipping resilience init");
18014
18069
  return;
18015
18070
  }
18016
18071
  try {
@@ -18045,21 +18100,20 @@ var WebRTCCall = class extends Destroyable {
18045
18100
  disableVideo: () => {
18046
18101
  try {
18047
18102
  this.vertoManager.muteMainVideoInputDevice();
18048
- logger$10.debug("[Call] Recovery manager disabled video");
18103
+ logger$11.debug("[Call] Recovery manager disabled video");
18049
18104
  } catch {
18050
- logger$10.debug("[Call] Recovery manager failed to disable video");
18105
+ logger$11.debug("[Call] Recovery manager failed to disable video");
18051
18106
  }
18052
18107
  },
18053
18108
  enableVideo: () => {
18054
18109
  this.vertoManager.unmuteMainVideoInputDevice().catch(() => {
18055
- logger$10.debug("[Call] Recovery manager failed to enable video");
18110
+ logger$11.debug("[Call] Recovery manager failed to enable video");
18056
18111
  });
18057
18112
  },
18058
18113
  isNegotiating: () => this.vertoManager.mainPeerConnection.isNegotiating,
18059
- isWebSocketConnected: () => this._lastMergedStatus !== "disconnected",
18060
18114
  isCallConnected: () => this._lastMergedStatus === "connected",
18061
18115
  getPeerConnectionState: () => pc.connectionState
18062
- }, {
18116
+ }, { signalingReady$: this.clientSession.authenticated$ }, {
18063
18117
  debounceTimeMs: prefs.recoveryDebounceTime,
18064
18118
  cooldownMs: prefs.recoveryCooldown,
18065
18119
  iceGracePeriodMs: prefs.iceDisconnectedGracePeriod,
@@ -18102,6 +18156,15 @@ var WebRTCCall = class extends Destroyable {
18102
18156
  });
18103
18157
  this.subscribeTo(this._recoveryManager.recoveryEvent$, (event) => {
18104
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
+ }
18105
18168
  });
18106
18169
  this.subscribeTo(this._recoveryManager.bandwidthConstrained$, (constrained) => {
18107
18170
  this._bandwidthConstrained$.next(constrained);
@@ -18113,14 +18176,14 @@ var WebRTCCall = class extends Destroyable {
18113
18176
  });
18114
18177
  else if (event.type === "online") this._recoveryManager?.handleWebSocketReconnect();
18115
18178
  });
18116
- this.subscribeTo(this.clientSession.authenticated$.pipe((0, import_cjs$9.skip)(1), (0, import_cjs$9.filter)(Boolean)), () => {
18117
- 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");
18118
18181
  this._recoveryManager?.handleWebSocketReconnect();
18119
18182
  });
18120
18183
  this._statsMonitor.start();
18121
- logger$10.debug("[Call] Resilience subsystems initialized for call", this.id);
18184
+ logger$11.debug("[Call] Resilience subsystems initialized for call", this.id);
18122
18185
  } catch (error) {
18123
- logger$10.warn("[Call] Failed to initialize resilience subsystems:", error);
18186
+ logger$11.warn("[Call] Failed to initialize resilience subsystems:", error);
18124
18187
  }
18125
18188
  }
18126
18189
  /**
@@ -18142,14 +18205,14 @@ var WebRTCCall = class extends Destroyable {
18142
18205
  }
18143
18206
  /** Observable of the current audio/video send/receive directions. */
18144
18207
  get mediaDirections$() {
18145
- 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$));
18146
18209
  }
18147
18210
  /** Current audio/video send/receive directions. */
18148
18211
  get mediaDirections() {
18149
18212
  return this.vertoManager.mediaDirections;
18150
18213
  }
18151
18214
  get participantsId$() {
18152
- 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))));
18153
18216
  }
18154
18217
  /**
18155
18218
  * Executes a raw JSON-RPC request on the client session.
@@ -18182,48 +18245,48 @@ var WebRTCCall = class extends Destroyable {
18182
18245
  }
18183
18246
  isCallSessionEvent(event) {
18184
18247
  try {
18185
- 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);
18186
18249
  const callId = getValueFrom(event, "params.params.callID") ?? getValueFrom(event, "params.call_id");
18187
18250
  const roomSessionId = getValueFrom(event, "params.room_session_id");
18188
- 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:`);
18189
18252
  return callId === this.id || !!callId && this.callEventsManager.isCallIdValid(callId) || !!roomSessionId && this.callEventsManager.isRoomSessionIdValid(roomSessionId);
18190
18253
  } catch (error) {
18191
- 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);
18192
18255
  return false;
18193
18256
  }
18194
18257
  }
18195
18258
  get callSessionEvents$() {
18196
- return this.cachedObservable("callSessionEvents$", () => this.clientSession.signalingEvent$.pipe((0, import_cjs$9.filter)((event) => this.isCallSessionEvent(event)), (0, import_cjs$9.tap)((event) => {
18197
- logger$10.debug("[Call] Received call session event:", event);
18198
- }), (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)()));
18199
18262
  }
18200
18263
  /** Observable of call-updated events. */
18201
18264
  get callUpdated$() {
18202
- 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$)));
18203
18266
  }
18204
18267
  /** Observable of member-joined events, emitted when a remote participant joins the call. */
18205
18268
  get memberJoined$() {
18206
- 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$)));
18207
18270
  }
18208
18271
  /** Observable of member-left events, emitted when a participant leaves the call. */
18209
18272
  get memberLeft$() {
18210
- 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$)));
18211
18274
  }
18212
18275
  /** Observable of member-updated events (mute, volume, etc.). */
18213
18276
  get memberUpdated$() {
18214
- 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$)));
18215
18278
  }
18216
18279
  /** Observable of member-talking events (speech start/stop). */
18217
18280
  get memberTalking$() {
18218
- 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$)));
18219
18282
  }
18220
18283
  /** Observable of call state-change events. */
18221
18284
  get callStates$() {
18222
- 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$)));
18223
18286
  }
18224
18287
  /** Observable of layout-changed events. */
18225
18288
  get layoutUpdates$() {
18226
- 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$)));
18227
18290
  }
18228
18291
  /** Underlying `RTCPeerConnection`, for advanced use cases. */
18229
18292
  get rtcPeerConnection() {
@@ -18231,7 +18294,7 @@ var WebRTCCall = class extends Destroyable {
18231
18294
  }
18232
18295
  /** Observable of raw signaling events as plain objects. */
18233
18296
  get signalingEvent$() {
18234
- 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)))));
18235
18298
  }
18236
18299
  /**
18237
18300
  * Subscribe to a custom signaling event type on this call.
@@ -18259,16 +18322,16 @@ var WebRTCCall = class extends Destroyable {
18259
18322
  subscribe(eventType) {
18260
18323
  const cached = this._customSubscriptions.get(eventType);
18261
18324
  if (cached) return cached;
18262
- 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$));
18263
18326
  this._customSubscriptions.set(eventType, filtered$);
18264
18327
  this._sendVertoSubscribe(eventType);
18265
18328
  return filtered$;
18266
18329
  }
18267
18330
  get webrtcMessages$() {
18268
- 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)()));
18269
18332
  }
18270
18333
  get callEvent$() {
18271
- 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)()));
18272
18335
  }
18273
18336
  get layoutEvent$() {
18274
18337
  return this.cachedObservable("layoutEvent$", () => this.callEvent$.pipe(filterAs(isLayoutChangedMetadata, "params")));
@@ -18361,7 +18424,7 @@ var WebRTCCall = class extends Destroyable {
18361
18424
  */
18362
18425
  async setLayout(layout, positions) {
18363
18426
  if (!this.layouts.includes(layout)) throw new InvalidParams(`Layout ${layout} is not available in the current call layouts: ${this.layouts.join(", ")}`);
18364
- 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)));
18365
18428
  await this.executeMethod(selfId, "call.layout.set", {
18366
18429
  layout,
18367
18430
  positions
@@ -18402,10 +18465,10 @@ var WebRTCCall = class extends Destroyable {
18402
18465
  message
18403
18466
  };
18404
18467
  this.clientSession.execute(WebrtcVerto(params)).catch((error) => {
18405
- 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);
18406
18469
  });
18407
18470
  } catch (error) {
18408
- 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);
18409
18472
  }
18410
18473
  }
18411
18474
  };
@@ -18427,6 +18490,7 @@ function inferCallErrorKind(error) {
18427
18490
  function isFatalError(error) {
18428
18491
  if (error instanceof VertoPongError) return false;
18429
18492
  if (error instanceof MediaTrackError) return false;
18493
+ if (error instanceof RPCTimeoutError) return false;
18430
18494
  return true;
18431
18495
  }
18432
18496
  /**
@@ -18458,6 +18522,9 @@ var CallFactory = class {
18458
18522
  callId: callInstance.id
18459
18523
  };
18460
18524
  callInstance.emitError(callError);
18525
+ },
18526
+ onModifyFailed: () => {
18527
+ callInstance.notifyModifyFailed();
18461
18528
  }
18462
18529
  }),
18463
18530
  callEventsManager: new CallEventsManager(callInstance)
@@ -18471,8 +18538,8 @@ var CallFactory = class {
18471
18538
 
18472
18539
  //#endregion
18473
18540
  //#region src/behaviors/Collection.ts
18474
- var import_cjs$8 = require_cjs();
18475
- const logger$9 = getLogger();
18541
+ var import_cjs$9 = require_cjs();
18542
+ const logger$10 = getLogger();
18476
18543
  var Fetcher = class {
18477
18544
  constructor(endpoint, params, http) {
18478
18545
  this.endpoint = endpoint;
@@ -18496,7 +18563,7 @@ var Fetcher = class {
18496
18563
  this.hasMore = !!this.nextUrl;
18497
18564
  return result.data.filter(this.filter).map(this.mapper);
18498
18565
  }
18499
- logger$9.error("Failed to fetch entity");
18566
+ logger$10.error("Failed to fetch entity");
18500
18567
  return [];
18501
18568
  }
18502
18569
  async id(v) {
@@ -18537,10 +18604,10 @@ var EntityCollection = class extends Destroyable {
18537
18604
  this.values$.next(Array.from(this.collectionData.values()));
18538
18605
  };
18539
18606
  this._hasMore$ = this.createBehaviorSubject(true);
18540
- this._destroy$ = new import_cjs$8.Subject();
18607
+ this._destroy$ = new import_cjs$9.Subject();
18541
18608
  this.updateSubscription = this.update$.subscribe(this.upsertData);
18542
18609
  this.loading$.next(false);
18543
- 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$));
18544
18611
  }
18545
18612
  get loading() {
18546
18613
  return this.loading$.value;
@@ -18549,7 +18616,7 @@ var EntityCollection = class extends Destroyable {
18549
18616
  return this.fetchController.hasMore ?? true;
18550
18617
  }
18551
18618
  get updated$() {
18552
- 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$)));
18553
18620
  }
18554
18621
  get values() {
18555
18622
  return Array.from(this.collectionData.values());
@@ -18568,7 +18635,7 @@ var EntityCollection = class extends Destroyable {
18568
18635
  this._hasMore$.next(this.fetchController.hasMore ?? false);
18569
18636
  this.loading$.next(false);
18570
18637
  } catch (error) {
18571
- logger$9.error(`Failed to fetch initial collection data`, error);
18638
+ logger$10.error(`Failed to fetch initial collection data`, error);
18572
18639
  this._hasMore$.next(this.fetchController.hasMore ?? false);
18573
18640
  this.loading$.next(false);
18574
18641
  this.onError?.(new CollectionFetchError("fetchMore", error));
@@ -18582,14 +18649,14 @@ var EntityCollection = class extends Destroyable {
18582
18649
  if (data) this.upsertData(data);
18583
18650
  return data;
18584
18651
  } catch (error) {
18585
- 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);
18586
18653
  this.loading$.next(false);
18587
18654
  this.onError?.(new CollectionFetchError(`tryFetch(${String(key)})`, error));
18588
18655
  }
18589
18656
  }
18590
18657
  get$(id) {
18591
18658
  if (!this.observablesRegistry.has(id)) {
18592
- this.observablesRegistry.set(id, new import_cjs$8.ReplaySubject(1));
18659
+ this.observablesRegistry.set(id, new import_cjs$9.ReplaySubject(1));
18593
18660
  const data = this.collectionData.get(id);
18594
18661
  if (data) this.observablesRegistry.get(id)?.next(data);
18595
18662
  else this.tryFetch("id", id);
@@ -18613,9 +18680,9 @@ var EntityCollection = class extends Destroyable {
18613
18680
  }
18614
18681
  };
18615
18682
  var EntityCollectionTransformed = class {
18616
- constructor(originalCollection, filter$16 = (i) => !!i, mapper = (item) => item) {
18683
+ constructor(originalCollection, filter$17 = (i) => !!i, mapper = (item) => item) {
18617
18684
  this.originalCollection = originalCollection;
18618
- this.filter = filter$16;
18685
+ this.filter = filter$17;
18619
18686
  this.mapper = mapper;
18620
18687
  }
18621
18688
  get loading$() {
@@ -18634,15 +18701,15 @@ var EntityCollectionTransformed = class {
18634
18701
  return this.originalCollection.values.filter(this.filter).map(this.mapper);
18635
18702
  }
18636
18703
  get values$() {
18637
- 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)));
18638
18705
  }
18639
18706
  get$(id) {
18640
18707
  const original$ = this.originalCollection.get$(id);
18641
- 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)));
18642
18709
  }
18643
18710
  async find$(key, value) {
18644
18711
  const original$ = await this.originalCollection.find$(key, value);
18645
- 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)));
18646
18713
  }
18647
18714
  loadMore() {
18648
18715
  this.originalCollection.loadMore();
@@ -18654,7 +18721,7 @@ var EntityCollectionTransformed = class {
18654
18721
 
18655
18722
  //#endregion
18656
18723
  //#region src/core/entities/Address.ts
18657
- var import_cjs$7 = require_cjs();
18724
+ var import_cjs$8 = require_cjs();
18658
18725
  /**
18659
18726
  * Represents a contact or room in the directory.
18660
18727
  *
@@ -18672,8 +18739,8 @@ var Address = class extends Destroyable {
18672
18739
  if (this._conversationMessages.hasMore) this._conversationMessages.loadMore();
18673
18740
  return this._conversationMessages;
18674
18741
  };
18675
- 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$));
18676
- 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$));
18677
18744
  this._state$ = this.createBehaviorSubject(null);
18678
18745
  }
18679
18746
  /** @internal */
@@ -18708,7 +18775,7 @@ var Address = class extends Destroyable {
18708
18775
  }
18709
18776
  /** Observable of the human-readable display name. */
18710
18777
  get displayName$() {
18711
- 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$)));
18712
18779
  }
18713
18780
  /** Human-readable display name. */
18714
18781
  get displayName() {
@@ -18717,7 +18784,7 @@ var Address = class extends Destroyable {
18717
18784
  }
18718
18785
  /** Observable of the preview image URL. */
18719
18786
  get previewUrl$() {
18720
- 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$)));
18721
18788
  }
18722
18789
  /** Preview image URL. */
18723
18790
  get previewUrl() {
@@ -18726,7 +18793,7 @@ var Address = class extends Destroyable {
18726
18793
  }
18727
18794
  /** Observable of the cover image URL. */
18728
18795
  get coverUrl$() {
18729
- 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$)));
18730
18797
  }
18731
18798
  /** Cover image URL. */
18732
18799
  get coverUrl() {
@@ -18735,7 +18802,7 @@ var Address = class extends Destroyable {
18735
18802
  }
18736
18803
  /** Observable of the underlying resource ID. */
18737
18804
  get resourceId$() {
18738
- 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$)));
18739
18806
  }
18740
18807
  /** Underlying resource ID. */
18741
18808
  get resourceId() {
@@ -18744,7 +18811,7 @@ var Address = class extends Destroyable {
18744
18811
  }
18745
18812
  /** Observable of the resource type (e.g. `'room'`, `'subscriber'`). */
18746
18813
  get type$() {
18747
- 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$)));
18748
18815
  }
18749
18816
  /** Resource type (e.g. `'room'`, `'subscriber'`). */
18750
18817
  get type() {
@@ -18753,7 +18820,7 @@ var Address = class extends Destroyable {
18753
18820
  }
18754
18821
  /** Observable of available communication channels (audio, video, messaging). */
18755
18822
  get channels$() {
18756
- 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$)));
18757
18824
  }
18758
18825
  /** Available communication channels. */
18759
18826
  get channels() {
@@ -18767,7 +18834,7 @@ var Address = class extends Destroyable {
18767
18834
  }
18768
18835
  /** Observable indicating whether the address (room) is locked. */
18769
18836
  get locked$() {
18770
- 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$)));
18771
18838
  }
18772
18839
  /**
18773
18840
  * Sends a text message to this address.
@@ -18833,14 +18900,14 @@ var Address = class extends Destroyable {
18833
18900
 
18834
18901
  //#endregion
18835
18902
  //#region src/core/utils.ts
18836
- var import_cjs$6 = require_cjs();
18837
- const logger$8 = getLogger();
18903
+ var import_cjs$7 = require_cjs();
18904
+ const logger$9 = getLogger();
18838
18905
  const isRPCConnectResult = (e) => {
18839
- logger$8.debug("isRPCConnectResult check:", e);
18906
+ logger$9.debug("isRPCConnectResult check:", e);
18840
18907
  if (!e || typeof e !== "object") return false;
18841
18908
  const result = e;
18842
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";
18843
- logger$8.debug("isRPCConnectResult check result:", is);
18910
+ logger$9.debug("isRPCConnectResult check result:", is);
18844
18911
  return is;
18845
18912
  };
18846
18913
  var PendingRPC = class PendingRPC {
@@ -18849,7 +18916,7 @@ var PendingRPC = class PendingRPC {
18849
18916
  }
18850
18917
  constructor(request, responses$, options) {
18851
18918
  this.id = v4_default();
18852
- 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`);
18853
18920
  this.request = request;
18854
18921
  const timeoutMs = options?.timeoutMs ?? PendingRPC.defaultTimeoutMs;
18855
18922
  const signal = options?.signal;
@@ -18859,38 +18926,38 @@ var PendingRPC = class PendingRPC {
18859
18926
  return;
18860
18927
  }
18861
18928
  let isSettled = false;
18862
- 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) => {
18863
- 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(() => {
18864
18931
  subscriber.error(new RPCTimeoutError(request.id, timeoutMs));
18865
18932
  }, timeoutMs);
18866
- return () => clearTimeout(timer$2);
18867
- }), signal ? new import_cjs$6.Observable((subscriber) => {
18933
+ return () => clearTimeout(timer$3);
18934
+ }), signal ? new import_cjs$7.Observable((subscriber) => {
18868
18935
  const abortHandler = () => {
18869
18936
  subscriber.error(new DOMException("The operation was aborted", "AbortError"));
18870
18937
  };
18871
18938
  signal.addEventListener("abort", abortHandler);
18872
18939
  return () => signal.removeEventListener("abort", abortHandler);
18873
- }) : import_cjs$6.NEVER).subscribe({
18940
+ }) : import_cjs$7.NEVER).subscribe({
18874
18941
  next: (response) => {
18875
18942
  isSettled = true;
18876
18943
  if (response.error) {
18877
18944
  const rpcError = new JSONRPCError(response.error.code, response.error.message, response.error.data, void 0, request.id);
18878
- 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);
18879
18946
  reject(rpcError);
18880
18947
  } else {
18881
- 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);
18882
18949
  resolve(response);
18883
18950
  }
18884
18951
  subscription.unsubscribe();
18885
18952
  },
18886
18953
  error: (error) => {
18887
- 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);
18888
18955
  isSettled = true;
18889
18956
  reject(error);
18890
18957
  subscription.unsubscribe();
18891
18958
  },
18892
18959
  complete: () => {
18893
- logger$8.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
18960
+ logger$9.debug(`[PendingRPC(${this.id}) request:${request.id}] Observable completed`);
18894
18961
  if (!isSettled) reject(new RPCTimeoutError(request.id, timeoutMs));
18895
18962
  subscription.unsubscribe();
18896
18963
  }
@@ -18910,8 +18977,8 @@ var PendingRPC = class PendingRPC {
18910
18977
 
18911
18978
  //#endregion
18912
18979
  //#region src/managers/ClientSessionManager.ts
18913
- var import_cjs$5 = require_cjs();
18914
- const logger$7 = getLogger();
18980
+ var import_cjs$6 = require_cjs();
18981
+ const logger$8 = getLogger();
18915
18982
  const getAddressSearchURI = (options) => {
18916
18983
  const to = options.to?.split("?")[0];
18917
18984
  const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
@@ -18946,10 +19013,10 @@ var ClientSessionManager = class extends Destroyable {
18946
19013
  this._iceServers$ = this.createBehaviorSubject([]);
18947
19014
  attachManager.setSession(this);
18948
19015
  this.callFactory = new CallFactory(this, deviceController, attachManager, webRTCApiProvider, networkChange$);
18949
- 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$));
18950
19017
  }
18951
19018
  get incomingCalls$() {
18952
- 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"))));
18953
19020
  }
18954
19021
  get incomingCalls() {
18955
19022
  return Object.values(this._calls$.value).filter((call) => call.direction === "inbound");
@@ -18961,7 +19028,7 @@ var ClientSessionManager = class extends Destroyable {
18961
19028
  return this._subscriberInfo$.value;
18962
19029
  }
18963
19030
  get calls$() {
18964
- 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))));
18965
19032
  }
18966
19033
  get calls() {
18967
19034
  return Object.values(this._calls$.value);
@@ -19005,7 +19072,7 @@ var ClientSessionManager = class extends Destroyable {
19005
19072
  try {
19006
19073
  return await this.transport.execute(request, options);
19007
19074
  } catch (error) {
19008
- logger$7.debug("[Session] Execute Error", error);
19075
+ logger$8.debug("[Session] Execute Error", error);
19009
19076
  this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
19010
19077
  throw error;
19011
19078
  }
@@ -19019,40 +19086,40 @@ var ClientSessionManager = class extends Destroyable {
19019
19086
  return true;
19020
19087
  }
19021
19088
  setupMessageHandlers() {
19022
- logger$7.debug("[Session] Setting up message handlers");
19089
+ logger$8.debug("[Session] Setting up message handlers");
19023
19090
  this.subscribeTo(this.authStateEvent$, async (authStateEvent) => {
19024
- logger$7.debug("[Session] Authorization state event received:", authStateEvent);
19091
+ logger$8.debug("[Session] Authorization state event received:", authStateEvent);
19025
19092
  try {
19026
19093
  await this.updateAuthorizationStateInStorage(authStateEvent.authorization_state);
19027
19094
  } catch (error) {
19028
- logger$7.error("[Session] Failed to handle authorization state update:", error);
19095
+ logger$8.error("[Session] Failed to handle authorization state update:", error);
19029
19096
  this._errors$.next(new AuthStateHandlerError(error));
19030
19097
  }
19031
19098
  });
19032
- this.subscribeTo(this.transport.connectionStatus$.pipe((0, import_cjs$5.filter)((status) => status === "connected"), (0, import_cjs$5.exhaustMap)(() => {
19033
- logger$7.debug("[Session] Connection established, initiating authentication");
19034
- 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) => {
19035
19102
  this.handleAuthenticationError(error).catch((err) => {
19036
- logger$7.error("[Session] Error handling authentication failure:", err);
19103
+ logger$8.error("[Session] Error handling authentication failure:", err);
19037
19104
  });
19038
- return import_cjs$5.EMPTY;
19105
+ return import_cjs$6.EMPTY;
19039
19106
  }));
19040
19107
  })), void 0);
19041
19108
  this.subscribeTo(this.vertoInvite$, async (invite) => {
19042
- logger$7.debug("[Session] Verto invite received:", invite);
19109
+ logger$8.debug("[Session] Verto invite received:", invite);
19043
19110
  try {
19044
19111
  await this.createInboundCall(invite);
19045
19112
  } catch (error) {
19046
- logger$7.error("[Session] Error handling Verto invite:", error);
19113
+ logger$8.error("[Session] Error handling Verto invite:", error);
19047
19114
  this._errors$.next(new VertoInviteHandlerError(error));
19048
19115
  }
19049
19116
  });
19050
19117
  this.subscribeTo(this.vertoAttach$, async (attach) => {
19051
- logger$7.debug("[Session] Verto attach received:", attach);
19118
+ logger$8.debug("[Session] Verto attach received:", attach);
19052
19119
  try {
19053
19120
  await this.handleVertoAttach(attach);
19054
19121
  } catch (error) {
19055
- logger$7.error("[Session] Error handling Verto attach:", error);
19122
+ logger$8.error("[Session] Error handling Verto attach:", error);
19056
19123
  this._errors$.next(new VertoAttachHandlerError(error));
19057
19124
  }
19058
19125
  });
@@ -19062,49 +19129,49 @@ var ClientSessionManager = class extends Destroyable {
19062
19129
  const storedState = await this.storage.getItem(this.authorizationStateKey);
19063
19130
  this.authorizationState$.next(storedState ?? void 0);
19064
19131
  } catch (error) {
19065
- logger$7.error("Failed to retrieve authorization state from storage:", error);
19132
+ logger$8.error("Failed to retrieve authorization state from storage:", error);
19066
19133
  this.authorizationState$.next(void 0);
19067
19134
  }
19068
19135
  }
19069
19136
  async updateAuthorizationStateInStorage(authorizationState) {
19070
19137
  if (!authorizationState) {
19071
- logger$7.debug("[Session] Removing authorization state from storage");
19138
+ logger$8.debug("[Session] Removing authorization state from storage");
19072
19139
  try {
19073
19140
  await this.storage.removeItem(this.authorizationStateKey);
19074
19141
  this.authorizationState$.next(void 0);
19075
19142
  } catch (error) {
19076
- logger$7.error("Failed to remove authorization state from storage:", error);
19143
+ logger$8.error("Failed to remove authorization state from storage:", error);
19077
19144
  throw error;
19078
19145
  }
19079
19146
  return;
19080
19147
  }
19081
19148
  try {
19082
- logger$7.debug("[Session] Updating authorization state in storage");
19149
+ logger$8.debug("[Session] Updating authorization state in storage");
19083
19150
  await this.storage.setItem(this.authorizationStateKey, authorizationState);
19084
19151
  this.authorizationState$.next(authorizationState);
19085
19152
  } catch (error) {
19086
- logger$7.error("Failed to retrieve authorization state from storage:", error);
19153
+ logger$8.error("Failed to retrieve authorization state from storage:", error);
19087
19154
  throw error;
19088
19155
  }
19089
19156
  }
19090
19157
  get authStateEvent$() {
19091
- return this.cachedObservable("authStateEvent$", () => this.signalingEvent$.pipe((0, import_cjs$5.tap)((msg) => {
19092
- logger$7.debug("[Session] Received incoming message:", msg);
19093
- }), filterAs(isSignalwireAuthorizationStateMetadata, "params"), (0, import_cjs$5.tap)((event) => {
19094
- 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);
19095
19162
  })));
19096
19163
  }
19097
19164
  get signalingEvent$() {
19098
- 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)()));
19099
19166
  }
19100
19167
  get vertoInvite$() {
19101
- 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) => ({
19102
19169
  node_id: event.node_id,
19103
19170
  ...event.params.params
19104
19171
  }))));
19105
19172
  }
19106
19173
  get vertoAttach$() {
19107
- 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) => ({
19108
19175
  node_id: event.node_id,
19109
19176
  ...event.params.params
19110
19177
  }))));
@@ -19124,20 +19191,20 @@ var ClientSessionManager = class extends Destroyable {
19124
19191
  return { jwt_token: credential.token };
19125
19192
  }
19126
19193
  async connect() {
19127
- await (0, import_cjs$5.firstValueFrom)(this.initialized$);
19194
+ await (0, import_cjs$6.firstValueFrom)(this.initialized$);
19128
19195
  await this.transport.connect();
19129
- 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 })));
19130
19197
  }
19131
19198
  async handleAuthenticationError(error) {
19132
- logger$7.error("Authentication error:", error);
19199
+ logger$8.error("Authentication error:", error);
19133
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);
19134
- 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;
19135
19202
  if (isRecoverableAuthError && hasStoredState) {
19136
- 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");
19137
19204
  try {
19138
19205
  await this.cleanupStoredConnectionParams();
19139
19206
  } catch (cleanupError) {
19140
- logger$7.error("Failed to cleanup stored connection params:", cleanupError);
19207
+ logger$8.error("Failed to cleanup stored connection params:", cleanupError);
19141
19208
  } finally {
19142
19209
  this.transport.reconnect();
19143
19210
  }
@@ -19152,44 +19219,44 @@ var ClientSessionManager = class extends Destroyable {
19152
19219
  try {
19153
19220
  await this.storage.setItem(this.authorizationStateKey, authorization_state);
19154
19221
  } catch (error) {
19155
- logger$7.error("Failed to update authorization state in storage:", error);
19222
+ logger$8.error("Failed to update authorization state in storage:", error);
19156
19223
  this._errors$.next(new AuthStateHandlerError(error));
19157
19224
  }
19158
19225
  }
19159
19226
  async reauthenticate(token, dpopToken, options) {
19160
- logger$7.debug("[Session] Re-authenticating session");
19227
+ logger$8.debug("[Session] Re-authenticating session");
19161
19228
  try {
19162
19229
  let resolvedDpopToken = dpopToken;
19163
19230
  if (!resolvedDpopToken && this.dpopManager?.initialized) try {
19164
19231
  resolvedDpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.reauthenticate" });
19165
19232
  } catch (error) {
19166
19233
  if (this._clientBound) throw error;
19167
- 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);
19168
19235
  }
19169
19236
  const request = RPCReauthenticate({
19170
19237
  project: this._authorization$.value?.project_id ?? "",
19171
19238
  jwt_token: token,
19172
19239
  ...resolvedDpopToken ? { dpop_token: resolvedDpopToken } : {}
19173
19240
  });
19174
- 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) => {
19175
- 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);
19176
19243
  throw err;
19177
19244
  })));
19178
19245
  if (options?.clientBound) this._clientBound = true;
19179
- logger$7.debug("[Session] Re-authentication successful, updating stored auth state");
19246
+ logger$8.debug("[Session] Re-authentication successful, updating stored auth state");
19180
19247
  } catch (error) {
19181
- logger$7.error("[Session] Re-authentication failed:", error);
19248
+ logger$8.error("[Session] Re-authentication failed:", error);
19182
19249
  this._errors$.next(new AuthStateHandlerError(error));
19183
19250
  throw error;
19184
19251
  }
19185
19252
  }
19186
19253
  async authenticate() {
19187
- logger$7.debug("[Session] Starting authentication process");
19188
- 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)({
19189
19256
  protocol: this.transport.protocol$,
19190
19257
  authorization_state: this.authorizationState$
19191
- }).pipe((0, import_cjs$5.take)(1)));
19192
- logger$7.debug("[Session] Persisted params:\n", {
19258
+ }).pipe((0, import_cjs$6.take)(1)));
19259
+ logger$8.debug("[Session] Persisted params:\n", {
19193
19260
  protocol: persistedParams.protocol,
19194
19261
  authStateLength: persistedParams.authorization_state?.length
19195
19262
  });
@@ -19197,16 +19264,16 @@ var ClientSessionManager = class extends Destroyable {
19197
19264
  const storedToken = this.getCredential().token;
19198
19265
  const isReconnect = hasReconnectState && storedToken;
19199
19266
  let dpopToken;
19200
- 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");
19201
19268
  else if (this.onBeforeReconnect && this._clientBound) {
19202
- logger$7.debug("[Session] Refreshing credentials before fresh connect");
19269
+ logger$8.debug("[Session] Refreshing credentials before fresh connect");
19203
19270
  await this.onBeforeReconnect();
19204
19271
  }
19205
19272
  if ((!isReconnect || this._clientBound) && this.dpopManager?.initialized) try {
19206
19273
  dpopToken = await this.dpopManager.createRpcProof({ method: "signalwire.connect" });
19207
19274
  } catch (error) {
19208
19275
  if (this._clientBound) throw error;
19209
- 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);
19210
19277
  }
19211
19278
  const rpcConnectRequest = RPCConnect({
19212
19279
  authentication: isReconnect ? { jwt_token: storedToken } : this.authentication,
@@ -19222,13 +19289,13 @@ var ClientSessionManager = class extends Destroyable {
19222
19289
  protocol: persistedParams.protocol
19223
19290
  } : {}
19224
19291
  });
19225
- 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)(() => {
19226
- logger$7.debug("[Session] Response passed filter, processing authentication result");
19227
- }), (0, import_cjs$5.take)(1), (0, import_cjs$5.catchError)((err) => {
19228
- 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);
19229
19296
  throw err;
19230
19297
  })));
19231
- logger$7.debug("[Session] Processing authentication result:", {
19298
+ logger$8.debug("[Session] Processing authentication result:", {
19232
19299
  hasProtocol: !!response.protocol,
19233
19300
  hasAuthorization: !!response.authorization,
19234
19301
  hasIceServers: !!response.ice_servers
@@ -19237,7 +19304,7 @@ var ClientSessionManager = class extends Destroyable {
19237
19304
  this._authorization$.next(response.authorization);
19238
19305
  this._iceServers$.next(response.ice_servers ?? []);
19239
19306
  this._authenticated$.next(true);
19240
- logger$7.debug("[Session] Authentication completed successfully");
19307
+ logger$8.debug("[Session] Authentication completed successfully");
19241
19308
  }
19242
19309
  async disconnect() {
19243
19310
  this.transport.disconnect();
@@ -19256,7 +19323,7 @@ var ClientSessionManager = class extends Destroyable {
19256
19323
  displayDirection: invite.display_direction,
19257
19324
  userVariables: invite.userVariables
19258
19325
  });
19259
- await (0, import_cjs$5.firstValueFrom)(callSession.status$);
19326
+ await (0, import_cjs$6.firstValueFrom)(callSession.status$);
19260
19327
  this._calls$.next({
19261
19328
  [`${callSession.id}`]: callSession,
19262
19329
  ...this._calls$.value
@@ -19274,11 +19341,11 @@ var ClientSessionManager = class extends Destroyable {
19274
19341
  async handleVertoAttach(attach) {
19275
19342
  const { callID } = attach;
19276
19343
  if (callID in this._calls$.value) {
19277
- 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`);
19278
19345
  return;
19279
19346
  }
19280
19347
  const storedOptions = this.attachManager.consumePendingAttachment(callID);
19281
- logger$7.debug(`[Session] Creating reattached call for callID: ${callID}`);
19348
+ logger$8.debug(`[Session] Creating reattached call for callID: ${callID}`);
19282
19349
  const callSession = await this.createCall({
19283
19350
  nodeId: attach.node_id,
19284
19351
  callId: callID,
@@ -19289,7 +19356,7 @@ var ClientSessionManager = class extends Destroyable {
19289
19356
  reattach: true,
19290
19357
  ...storedOptions
19291
19358
  });
19292
- await (0, import_cjs$5.firstValueFrom)(callSession.status$);
19359
+ await (0, import_cjs$6.firstValueFrom)(callSession.status$);
19293
19360
  this._calls$.next({
19294
19361
  [`${callSession.id}`]: callSession,
19295
19362
  ...this._calls$.value
@@ -19303,16 +19370,16 @@ var ClientSessionManager = class extends Destroyable {
19303
19370
  to: destinationURI,
19304
19371
  ...options
19305
19372
  });
19306
- 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)))));
19307
19374
  this._calls$.next({
19308
19375
  [`${callSession.id}`]: callSession,
19309
19376
  ...this._calls$.value
19310
19377
  });
19311
19378
  return callSession;
19312
19379
  } catch (error) {
19313
- logger$7.error("[Session] Error creating outbound call:", error);
19380
+ logger$8.error("[Session] Error creating outbound call:", error);
19314
19381
  callSession?.destroy();
19315
- 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");
19316
19383
  this._errors$.next(callError);
19317
19384
  throw callError;
19318
19385
  }
@@ -19328,16 +19395,16 @@ var ClientSessionManager = class extends Destroyable {
19328
19395
  address = this._directory.get(addressId);
19329
19396
  if (!address) throw new DependencyError(`Address ID: ${addressId} not found`);
19330
19397
  } catch {
19331
- 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`);
19332
19399
  }
19333
19400
  const callSession = this.callFactory.createCall(address, { ...options });
19334
- 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)), () => {
19335
19402
  const { [`${callSession.id}`]: _, ...remainingCalls } = this._calls$.value;
19336
19403
  this._calls$.next(remainingCalls);
19337
19404
  });
19338
19405
  return callSession;
19339
19406
  } catch (error) {
19340
- logger$7.error("[Session] Error creating call session:", error);
19407
+ logger$8.error("[Session] Error creating call session:", error);
19341
19408
  throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
19342
19409
  }
19343
19410
  }
@@ -19385,8 +19452,8 @@ const isString = (obj) => typeof obj === "string";
19385
19452
 
19386
19453
  //#endregion
19387
19454
  //#region src/managers/ConversationsManager.ts
19388
- var import_cjs$4 = require_cjs();
19389
- const logger$6 = getLogger();
19455
+ var import_cjs$5 = require_cjs();
19456
+ const logger$7 = getLogger();
19390
19457
  var ConversationMessagesFetcher = class extends Fetcher {
19391
19458
  constructor(groupId, http) {
19392
19459
  super(`/api/fabric/conversations/${groupId}/messages`, "page_size=100", http);
@@ -19426,13 +19493,13 @@ var ConversationsManager = class {
19426
19493
  }
19427
19494
  throw new ConversationError("Join Failed - Unexpected response");
19428
19495
  } catch (error) {
19429
- logger$6.error("[ConversationsManager] Failed to join conversation:", error);
19496
+ logger$7.error("[ConversationsManager] Failed to join conversation:", error);
19430
19497
  throw error;
19431
19498
  }
19432
19499
  }
19433
19500
  async getConversationMessageCollection(addressId) {
19434
19501
  const groupId = this.groupIds.get(addressId) ?? await this.join(addressId);
19435
- 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));
19436
19503
  }
19437
19504
  async sendText(text, destinationAddressId) {
19438
19505
  const groupId = this.groupIds.get(destinationAddressId) ?? await this.join(destinationAddressId);
@@ -19449,12 +19516,222 @@ var ConversationsManager = class {
19449
19516
  })).ok) return;
19450
19517
  throw new ConversationError("Send Text Failed - Unexpected response");
19451
19518
  } catch (error) {
19452
- logger$6.error("[ConversationsManager] Failed to send text message:", error);
19519
+ logger$7.error("[ConversationsManager] Failed to send text message:", error);
19453
19520
  throw error;
19454
19521
  }
19455
19522
  }
19456
19523
  };
19457
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
+
19458
19735
  //#endregion
19459
19736
  //#region src/managers/DiagnosticsCollector.ts
19460
19737
  const logger$5 = getLogger();
@@ -20388,13 +20665,43 @@ var SignalWire = class extends Destroyable {
20388
20665
  this._errors$.next(error);
20389
20666
  });
20390
20667
  await this._clientSession.connect();
20391
- this.subscribeTo(this._clientSession.authenticated$.pipe((0, import_cjs.skip)(1), (0, import_cjs.filter)(Boolean)), () => {
20392
- logger$1.debug("[SignalWire] Re-registering subscriber after reconnect");
20393
- 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();
20394
20700
  logger$1.debug("[SignalWire] Subscriber re-registered successfully after reconnect");
20395
- }).catch((error) => {
20701
+ } catch (error) {
20396
20702
  logger$1.error("[SignalWire] Re-registration failed after reconnect:", error);
20397
- });
20703
+ this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
20704
+ }
20398
20705
  });
20399
20706
  const conversationManager = new ConversationsManager(this._clientSession, this._deps.http, () => this._deps.getSubscriberFromAddressId(), errorHandler);
20400
20707
  const directory = new DirectoryManager(this._deps.http, this._clientSession, conversationManager, errorHandler);