@signalwire/js 4.0.0-beta.10 → 4.0.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -3,79 +3,8 @@ import * as rxjs0 from "rxjs";
3
3
  import { BehaviorSubject, Observable, Observer, ReplaySubject, Subject, Subscription } from "rxjs";
4
4
  import { URL as URL$1 } from "node:url";
5
5
 
6
- //#region src/behaviors/Destroyable.d.ts
7
- declare abstract class Destroyable {
8
- protected subscriptions: Subscription[];
9
- protected subjects: Subject<unknown>[];
10
- protected _destroyed$: Subject<void>;
11
- private _observableCache?;
12
- destroy(): void;
13
- protected cachedObservable<T>(key: string, factory: () => Observable<T>): Observable<T>;
14
- /**
15
- * Like `cachedObservable`, but defers emissions to the microtask queue
16
- * via `observeOn(asapScheduler)`.
17
- *
18
- * Use ONLY for public-facing observable getters that external consumers
19
- * subscribe to. Prevents a class of bugs where `BehaviorSubject` or
20
- * `ReplaySubject` replays synchronously during `subscribe()`, before
21
- * the subscription variable is assigned in the caller's scope.
22
- *
23
- * Do NOT use for observables consumed internally by the SDK — internal
24
- * code using `subscribeTo()`, `firstValueFrom()`, or `withLatestFrom()`
25
- * depends on synchronous emission delivery.
26
- */
27
- protected publicCachedObservable<T>(key: string, factory: () => Observable<T>): Observable<T>;
28
- /**
29
- * Wraps an observable so emissions are deferred to the microtask queue.
30
- *
31
- * Use ONLY for public-facing getters that expose a subject via
32
- * `.asObservable()` without going through `cachedObservable`.
33
- *
34
- * Do NOT use for observables consumed internally by the SDK.
35
- */
36
- protected deferEmission<T>(observable: Observable<T>): Observable<T>;
37
- protected subscribeTo<T>(observable: Observable<T>, observerOrNext: Partial<Observer<T>> | ((value: T) => void) | undefined): void;
38
- protected createSubject<T>(): Subject<T>;
39
- protected createReplaySubject<T>(bufferSize?: number, windowTime?: number): ReplaySubject<T>;
40
- protected createBehaviorSubject<T>(initialValue: T): BehaviorSubject<T>;
41
- get $(): Observable<this>;
42
- /**
43
- * Observable that emits when the instance is destroyed
44
- */
45
- get destroyed$(): Observable<void>;
46
- }
47
- //#endregion
48
- //#region src/core/types/media.types.d.ts
49
- /** WebRTC transceiver direction for a single media kind. */
50
- type MediaDirection = RTCRtpTransceiverDirection;
51
- /** Audio and video directions "inactive" | "recvonly" | "sendonly" | "sendrecv" | "stopped" */
52
- interface MediaDirections {
53
- /** Audio direction */
54
- audio: MediaDirection;
55
- /** Video direction */
56
- video: MediaDirection;
57
- }
58
- /** Options controlling which media tracks to send and receive. */
59
- interface MediaOptions {
60
- /** Enable audio input. */
61
- audio?: boolean;
62
- /** Enable video input. */
63
- video?: boolean;
64
- /** Custom constraints for the audio input track. */
65
- inputAudioDeviceConstraints?: MediaTrackConstraints;
66
- /** Custom constraints for the video input track. */
67
- inputVideoDeviceConstraints?: MediaTrackConstraints;
68
- /** Pre-existing audio stream to use instead of `getUserMedia`. */
69
- inputAudioStream?: MediaStream;
70
- /** Pre-existing video stream to use instead of `getUserMedia`. */
71
- inputVideoStream?: MediaStream;
72
- /** Whether to receive remote audio. */
73
- receiveAudio?: boolean;
74
- /** Whether to receive remote video. */
75
- receiveVideo?: boolean;
76
- }
77
- //#endregion
78
6
  //#region src/core/types/common.types.d.ts
7
+ /** JSON-compatible value type for serializable data structures. */
79
8
  interface JSONSerializable {
80
9
  [key: string]: JSONSerializable | string | number | boolean | null | undefined | JSONSerializable[];
81
10
  }
@@ -124,6 +53,7 @@ interface HTTPResponse<T extends HttpBody = string> {
124
53
  /** Final URL after any redirects */
125
54
  url: string;
126
55
  }
56
+ /** Browser-compatible WebSocket client interface. */
127
57
  interface WebSocketClient {
128
58
  addEventListener: WebSocket['addEventListener'];
129
59
  removeEventListener: WebSocket['removeEventListener'];
@@ -131,6 +61,7 @@ interface WebSocketClient {
131
61
  close: WebSocket['close'];
132
62
  readyState: WebSocket['readyState'];
133
63
  }
64
+ /** Node.js WebSocket client interface with event listener overloads. */
134
65
  interface NodeSocketClient extends WebSocketClient {
135
66
  addEventListener(method: 'open' | 'close' | 'error' | 'message', cb: (event: unknown) => void, options?: unknown): void;
136
67
  removeEventListener(method: 'open' | 'close' | 'error' | 'message', cb: (event: unknown) => void): void;
@@ -147,24 +78,52 @@ interface NodeSocketAdapter {
147
78
  }
148
79
  /** Browser-compatible WebSocket constructor type. */
149
80
  type WebSocketAdapter = new (url: string | URL, protocols?: string | string[]) => WebSocketClient;
150
- /** Authentication credentials for the SDK. */
81
+ /**
82
+ * Authentication credentials for the SDK.
83
+ *
84
+ * At least one of `token` or `authorizationState` must be provided.
85
+ */
151
86
  interface SDKCredential {
152
- /** JWT subscriber access token. */
87
+ /** JWT subscriber access token (SAT). */
153
88
  token?: string;
154
89
  /** Pre-authorized session state (alternative to token). */
155
90
  authorizationState?: string;
156
- /** Token expiry timestamp in milliseconds since epoch. */
91
+ /** Token expiry timestamp in milliseconds since epoch. When set, the SDK attempts credential refresh before expiry. */
157
92
  expiry_at?: number;
158
93
  }
159
94
  /** Types of addressable resources in the fabric. */
160
95
  type ResourceType = 'app' | 'call' | 'room' | 'subscriber';
161
96
  //#endregion
162
97
  //#region src/dependencies/interfaces.d.ts
98
+ /** Persistence scope: browser `localStorage` or `sessionStorage`. */
163
99
  type StorageScope = 'local' | 'session';
100
+ /** Key-value storage interface for persisting SDK preferences and state. */
164
101
  interface Storage {
165
102
  setItem(key: string, value: string | null, scope: StorageScope): Promise<void>;
166
103
  getItem(key: string, scope: StorageScope): Promise<string | null>;
167
104
  removeItem(key: string, scope: StorageScope): Promise<void>;
105
+ /** Clears all keys in the given scope. Implementations may scope the clear to SDK keys only. */
106
+ clear(scope: StorageScope): Promise<void>;
107
+ }
108
+ /**
109
+ * Context provided by the SDK when calling {@link CredentialProvider.authenticate}.
110
+ *
111
+ * Contains optional parameters the SDK generates internally (e.g., DPoP fingerprint)
112
+ * that the implementor can forward to their server-side token endpoint.
113
+ */
114
+ interface AuthenticateContext {
115
+ /**
116
+ * JWK Thumbprint (RFC 7638) of the SDK's ephemeral DPoP key pair.
117
+ *
118
+ * When present, the implementor should forward this value as the `fingerprint`
119
+ * parameter to the server-side SAT issuance endpoint alongside `scope: "sat:refresh"`.
120
+ * This enables the server to bind the SAT to the SDK's key pair, allowing
121
+ * automatic Client Bound SAT refresh without developer intervention.
122
+ *
123
+ * When absent (e.g., Web Crypto API not available), the implementor should
124
+ * proceed without DPoP binding.
125
+ */
126
+ fingerprint?: string;
168
127
  }
169
128
  /**
170
129
  * Provides authentication credentials to the SDK.
@@ -185,12 +144,14 @@ interface CredentialProvider {
185
144
  * Implementor responsibilities:
186
145
  * - Resolve with a valid {@link SDKCredential} on success.
187
146
  * - Reject (throw) on failure — this will cause client initialization to fail.
147
+ * - When `context.fingerprint` is provided, forward it to the server-side token
148
+ * endpoint with `scope: "sat:refresh"` to enable automatic token refresh.
188
149
  *
189
150
  * SDK behavior:
190
151
  * - Awaits this method before establishing the WebSocket connection.
191
152
  * - On rejection, propagates the error to the caller of `SignalWire()`.
192
153
  */
193
- authenticate(): Promise<SDKCredential>;
154
+ authenticate(context?: AuthenticateContext): Promise<SDKCredential>;
194
155
  /**
195
156
  * Obtains fresh credentials before the current ones expire. Optional.
196
157
  *
@@ -203,7 +164,10 @@ interface CredentialProvider {
203
164
  * - Scheduled automatically before expiry; implementors do not need to manage timing.
204
165
  * - On rejection, the refresh schedule stops and the session continues with the
205
166
  * current credentials until they expire.
206
- * - When not provided, the SDK uses the initial credentials for the entire session lifetime.
167
+ * - When not provided and the SAT includes a `sat:refresh` scope, the SDK
168
+ * automatically refreshes via Client Bound SAT (DPoP) without developer intervention.
169
+ * - When not provided and no refresh scope is present, the SDK uses the initial
170
+ * credentials for the entire session lifetime.
207
171
  */
208
172
  refresh?: () => Promise<SDKCredential>;
209
173
  }
@@ -285,6 +249,82 @@ declare class StorageManager {
285
249
  * @throws Error from underlying storage implementation
286
250
  */
287
251
  removeItem(key: string, scope?: StorageScope): Promise<void>;
252
+ /**
253
+ * Clears all SDK keys from both 'local' and 'session' scopes.
254
+ * @throws StorageWriteError if clearing fails
255
+ */
256
+ clearAll(): Promise<void>;
257
+ }
258
+ //#endregion
259
+ //#region src/behaviors/Destroyable.d.ts
260
+ declare abstract class Destroyable {
261
+ protected subscriptions: Subscription[];
262
+ protected subjects: Subject<unknown>[];
263
+ protected _destroyed$: Subject<void>;
264
+ private _observableCache?;
265
+ destroy(): void;
266
+ protected cachedObservable<T>(key: string, factory: () => Observable<T>): Observable<T>;
267
+ /**
268
+ * Like `cachedObservable`, but defers emissions to the microtask queue
269
+ * via `observeOn(asapScheduler)`.
270
+ *
271
+ * Use ONLY for public-facing observable getters that external consumers
272
+ * subscribe to. Prevents a class of bugs where `BehaviorSubject` or
273
+ * `ReplaySubject` replays synchronously during `subscribe()`, before
274
+ * the subscription variable is assigned in the caller's scope.
275
+ *
276
+ * Do NOT use for observables consumed internally by the SDK — internal
277
+ * code using `subscribeTo()`, `firstValueFrom()`, or `withLatestFrom()`
278
+ * depends on synchronous emission delivery.
279
+ */
280
+ protected publicCachedObservable<T>(key: string, factory: () => Observable<T>): Observable<T>;
281
+ /**
282
+ * Wraps an observable so emissions are deferred to the microtask queue.
283
+ *
284
+ * Use ONLY for public-facing getters that expose a subject via
285
+ * `.asObservable()` without going through `cachedObservable`.
286
+ *
287
+ * Do NOT use for observables consumed internally by the SDK.
288
+ */
289
+ protected deferEmission<T>(observable: Observable<T>): Observable<T>;
290
+ protected subscribeTo<T>(observable: Observable<T>, observerOrNext: Partial<Observer<T>> | ((value: T) => void) | undefined): void;
291
+ protected createSubject<T>(): Subject<T>;
292
+ protected createReplaySubject<T>(bufferSize?: number, windowTime?: number): ReplaySubject<T>;
293
+ protected createBehaviorSubject<T>(initialValue: T): BehaviorSubject<T>;
294
+ /**
295
+ * Observable that emits when the instance is destroyed
296
+ */
297
+ get destroyed$(): Observable<void>;
298
+ }
299
+ //#endregion
300
+ //#region src/core/types/media.types.d.ts
301
+ /** WebRTC transceiver direction for a single media kind. */
302
+ type MediaDirection = RTCRtpTransceiverDirection;
303
+ /** Audio and video directions "inactive" | "recvonly" | "sendonly" | "sendrecv" | "stopped" */
304
+ interface MediaDirections {
305
+ /** Audio direction */
306
+ audio: MediaDirection;
307
+ /** Video direction */
308
+ video: MediaDirection;
309
+ }
310
+ /** Options controlling which media tracks to send and receive. */
311
+ interface MediaOptions {
312
+ /** Enable audio input. Defaults to `true` when not specified. */
313
+ audio?: boolean;
314
+ /** Enable video input. Defaults to `false` when not specified. */
315
+ video?: boolean;
316
+ /** Custom constraints for the audio input track. */
317
+ inputAudioDeviceConstraints?: MediaTrackConstraints;
318
+ /** Custom constraints for the video input track. */
319
+ inputVideoDeviceConstraints?: MediaTrackConstraints;
320
+ /** Pre-existing audio stream to use instead of `getUserMedia`. */
321
+ inputAudioStream?: MediaStream;
322
+ /** Pre-existing video stream to use instead of `getUserMedia`. */
323
+ inputVideoStream?: MediaStream;
324
+ /** Whether to receive remote audio. */
325
+ receiveAudio?: boolean;
326
+ /** Whether to receive remote video. */
327
+ receiveVideo?: boolean;
288
328
  }
289
329
  //#endregion
290
330
  //#region src/containers/PreferencesContainer.d.ts
@@ -364,6 +404,108 @@ declare class ClientPreferences {
364
404
  /** Custom user variables attached to calls. */
365
405
  get userVariables(): Record<string, unknown>;
366
406
  set userVariables(value: Record<string, unknown>);
407
+ /** Stats polling interval in milliseconds. */
408
+ get statsPollingInterval(): number;
409
+ set statsPollingInterval(value: number);
410
+ /** Number of baseline samples for stats monitoring. */
411
+ get statsBaselineSamples(): number;
412
+ set statsBaselineSamples(value: number);
413
+ /** Duration in ms with no inbound packets before a critical issue is emitted. */
414
+ get statsNoPacketThreshold(): number;
415
+ set statsNoPacketThreshold(value: number);
416
+ /** Multiplier for RTT spike detection relative to baseline. */
417
+ get statsRttSpikeMultiplier(): number;
418
+ set statsRttSpikeMultiplier(value: number);
419
+ /** Packet loss fraction threshold (0-1) for issue detection. */
420
+ get statsPacketLossThreshold(): number;
421
+ set statsPacketLossThreshold(value: number);
422
+ /** Multiplier for jitter spike detection relative to baseline. */
423
+ get statsJitterSpikeMultiplier(): number;
424
+ set statsJitterSpikeMultiplier(value: number);
425
+ /** Number of seconds of metrics history to retain. */
426
+ get statsHistorySize(): number;
427
+ set statsHistorySize(value: number);
428
+ /** Maximum keyframe requests in a burst window. */
429
+ get keyframeMaxBurst(): number;
430
+ set keyframeMaxBurst(value: number);
431
+ /** Keyframe burst window duration in milliseconds. */
432
+ get keyframeBurstWindow(): number;
433
+ set keyframeBurstWindow(value: number);
434
+ /** Cooldown period in ms after keyframe burst limit is reached. */
435
+ get keyframeCooldown(): number;
436
+ set keyframeCooldown(value: number);
437
+ /** Minimum time in ms between re-INVITE attempts. */
438
+ get reinviteDebounceTime(): number;
439
+ set reinviteDebounceTime(value: number);
440
+ /** Maximum re-INVITE attempts per call. */
441
+ get reinviteMaxAttempts(): number;
442
+ set reinviteMaxAttempts(value: number);
443
+ /** Timeout in ms for a single re-INVITE attempt. */
444
+ get reinviteTimeout(): number;
445
+ set reinviteTimeout(value: number);
446
+ /** Recovery signal debounce window in seconds. */
447
+ get recoveryDebounceTime(): number;
448
+ set recoveryDebounceTime(seconds: number);
449
+ /** Cooldown period between recovery attempts in seconds. */
450
+ get recoveryCooldown(): number;
451
+ set recoveryCooldown(seconds: number);
452
+ /** Grace period before treating ICE 'disconnected' as failure, in seconds. */
453
+ get iceDisconnectedGracePeriod(): number;
454
+ set iceDisconnectedGracePeriod(seconds: number);
455
+ /** Timeout for a single ICE restart attempt in seconds. */
456
+ get iceRestartTimeout(): number;
457
+ set iceRestartTimeout(seconds: number);
458
+ /** Maximum recovery attempts before giving up. */
459
+ get maxRecoveryAttempts(): number;
460
+ set maxRecoveryAttempts(value: number);
461
+ /** Whether relay-only escalation is enabled as a last-resort recovery tier. */
462
+ get enableRelayFallback(): boolean;
463
+ set enableRelayFallback(value: boolean);
464
+ /** Whether browser network change detection (online/offline) is enabled. */
465
+ get enableNetworkChangeDetection(): boolean;
466
+ set enableNetworkChangeDetection(value: boolean);
467
+ /** Whether server-sent media-timeout hangups are intercepted for recovery. */
468
+ get enableServerHangupInterception(): boolean;
469
+ set enableServerHangupInterception(value: boolean);
470
+ /** Whether device selections are persisted to storage. */
471
+ get persistDeviceSelection(): boolean;
472
+ set persistDeviceSelection(value: boolean);
473
+ /** Whether device changes are auto-applied to active calls. */
474
+ get syncDevicesToActiveCalls(): boolean;
475
+ set syncDevicesToActiveCalls(value: boolean);
476
+ /** Whether to auto-mute video when the tab becomes hidden. */
477
+ get autoMuteVideoOnHidden(): boolean;
478
+ set autoMuteVideoOnHidden(value: boolean);
479
+ /** Whether to re-enumerate devices when the page becomes visible. */
480
+ get refreshDevicesOnVisible(): boolean;
481
+ set refreshDevicesOnVisible(value: boolean);
482
+ /** Whether to check peer connection health when the page becomes visible. */
483
+ get checkConnectionOnVisible(): boolean;
484
+ set checkConnectionOnVisible(value: boolean);
485
+ /** Default audio track constraints applied when no explicit constraints are provided. */
486
+ get defaultAudioConstraints(): MediaTrackConstraints | undefined;
487
+ set defaultAudioConstraints(value: MediaTrackConstraints | undefined);
488
+ /** Default video track constraints applied when video is enabled without explicit constraints. */
489
+ get defaultVideoConstraints(): MediaTrackConstraints | undefined;
490
+ set defaultVideoConstraints(value: MediaTrackConstraints | undefined);
491
+ /** Whether stereo Opus is enabled globally. */
492
+ get stereoAudio(): boolean;
493
+ set stereoAudio(value: boolean);
494
+ /** Whether automatic video degradation on low bandwidth is enabled. */
495
+ get enableAutoDegradation(): boolean;
496
+ set enableAutoDegradation(value: boolean);
497
+ /** Bitrate in kbps below which video is automatically disabled. */
498
+ get degradationBitrateThreshold(): number;
499
+ set degradationBitrateThreshold(value: number);
500
+ /** Bitrate in kbps above which video is automatically re-enabled. */
501
+ get degradationRecoveryThreshold(): number;
502
+ set degradationRecoveryThreshold(value: number);
503
+ /** Preferred video codecs in priority order. */
504
+ get preferredVideoCodecs(): string[];
505
+ set preferredVideoCodecs(value: string[]);
506
+ /** Preferred audio codecs in priority order. */
507
+ get preferredAudioCodecs(): string[];
508
+ set preferredAudioCodecs(value: string[]);
367
509
  /** Saves current preferences to storage (fire-and-forget). */
368
510
  private _saveToStorage;
369
511
  /** Loads preferences from storage and applies them to the container. */
@@ -380,11 +522,13 @@ interface HTTPRequestControllerOptions {
380
522
  }
381
523
  declare class HTTPRequestController {
382
524
  private baseURL;
383
- private credential;
525
+ private readonly getCredential;
384
526
  private static readonly defaultMaxRetries;
385
527
  private static readonly defaultRetryDelayMinMs;
386
528
  private static readonly defaultRetryDelayMaxMs;
387
529
  private static readonly defaultRequestTimeoutMs;
530
+ /** Sensitive field names to mask in debug logs. */
531
+ private static readonly SENSITIVE_BODY_FIELDS;
388
532
  private readonly maxRetries;
389
533
  private readonly retryDelayMin;
390
534
  private readonly retryDelayMax;
@@ -392,7 +536,7 @@ declare class HTTPRequestController {
392
536
  private _responses$;
393
537
  private _errors$;
394
538
  private _status$;
395
- constructor(baseURL: string, credential: SDKCredential, options?: HTTPRequestControllerOptions);
539
+ constructor(baseURL: string, getCredential: () => SDKCredential, options?: HTTPRequestControllerOptions);
396
540
  get status$(): Observable<HTTPRequestStatus>;
397
541
  get status(): HTTPRequestStatus;
398
542
  get responses$(): Observable<HTTPResponse>;
@@ -402,6 +546,10 @@ declare class HTTPRequestController {
402
546
  private executeRequest;
403
547
  private buildURL;
404
548
  private buildHeaders;
549
+ /**
550
+ * Sanitizes a request body for debug logging by masking sensitive fields.
551
+ */
552
+ private sanitizeBody;
405
553
  private convertResponse;
406
554
  }
407
555
  //#endregion
@@ -420,44 +568,105 @@ declare abstract class Fetchable<T = unknown> extends Destroyable {
420
568
  * Pure address-related types (no implementation dependencies)
421
569
  * Types that reference model implementations are in interfaces.ts
422
570
  */
571
+ /** Raw address response from the SignalWire Fabric API. */
423
572
  interface GetAddressResponse {
573
+ /** Unique address identifier. */
424
574
  id: string;
575
+ /** Human-readable display name. */
425
576
  display_name: string;
577
+ /** Resource name (used as a URI for dialing). */
426
578
  name: string;
579
+ /** URL for an avatar or preview image. */
427
580
  preview_url?: string;
581
+ /** URL for a cover image. */
428
582
  cover_url?: string;
583
+ /** Underlying resource identifier. */
429
584
  resource_id: string;
585
+ /** Type of the underlying resource. */
430
586
  type: ResourceType;
587
+ /** Available communication channels for this address. */
431
588
  channels: {
589
+ /** Audio-only channel URI. */
432
590
  audio?: string;
591
+ /** Messaging channel URI. */
433
592
  messaging?: string;
593
+ /** Video channel URI. */
434
594
  video?: string;
435
595
  };
596
+ /** Whether the address resource is currently locked. */
436
597
  locked: boolean;
598
+ /** ISO 8601 timestamp when the address was created. */
437
599
  created_at: string;
438
600
  }
439
601
  //#endregion
602
+ //#region src/core/types/crypto.types.d.ts
603
+ /** Parameters for creating an HTTP DPoP proof (for Prime API endpoints). */
604
+ interface DPoPHttpProofParams {
605
+ /** HTTP method (e.g., "POST"). */
606
+ readonly method: string;
607
+ /** Request URI — should be the full URL per RFC 9449 (e.g., "https://fabric.signalwire.com/api/..."). */
608
+ readonly uri: string;
609
+ /** Access token to bind via `ath` claim (SHA-256 hash). Used for resource endpoints, not token endpoints. */
610
+ readonly accessToken?: string;
611
+ }
612
+ /** Parameters for creating an RPC DPoP proof (for switchblade WebSocket methods). */
613
+ interface DPoPRpcProofParams {
614
+ /** RPC method name (e.g., "signalwire.connect" or "signalwire.reauthenticate"). */
615
+ readonly method: string;
616
+ }
617
+ /** SAT claims returned by /api/fabric/subscriber/info. */
618
+ interface SATClaims {
619
+ /** Token scopes (e.g., ["sat:refresh"]). */
620
+ scope?: string[];
621
+ /** Confirmation claim binding the token to a key. */
622
+ cnf?: {
623
+ jkt: string;
624
+ };
625
+ /** Token expiry timestamp in seconds since epoch. */
626
+ expires_at?: number;
627
+ }
628
+ //#endregion
440
629
  //#region src/core/types/subscriber.types.d.ts
630
+ /** Raw subscriber profile response from the SignalWire Fabric API. */
441
631
  interface GetSubscriberInfoResponse {
632
+ /** Unique subscriber identifier. */
442
633
  id: string;
634
+ /** Subscriber's email address. */
443
635
  email: string;
636
+ /** Subscriber's first name. */
444
637
  first_name?: string;
638
+ /** Subscriber's last name. */
445
639
  last_name?: string;
640
+ /** Subscriber's display name. */
446
641
  display_name?: string;
642
+ /** Subscriber's job title. */
447
643
  job_title?: string;
644
+ /** Subscriber's time zone offset. */
448
645
  time_zone?: number;
646
+ /** Subscriber's country. */
449
647
  country?: string;
648
+ /** Subscriber's region or state. */
450
649
  region?: string;
650
+ /** Subscriber's company name. */
451
651
  company_name?: string;
652
+ /** Key for push notification delivery. */
452
653
  push_notification_key: string;
654
+ /** Application-level settings for this subscriber. */
453
655
  app_settings?: {
656
+ /** Display name configured at the application level. */
454
657
  display_name: string;
658
+ /** Permission scopes granted to this subscriber. */
455
659
  scopes: string[];
456
660
  };
661
+ /** Fabric addresses associated with this subscriber. */
457
662
  fabric_addresses: GetAddressResponse[];
663
+ /** Filtered SAT claims (scope, cnf, expires_at) returned when the token has special capabilities. */
664
+ sat_claims?: SATClaims;
458
665
  }
459
666
  //#endregion
460
667
  //#region src/core/entities/Subscriber.d.ts
668
+ /** Subscriber online presence state. */
669
+ type SubscriberPresence = 'online' | 'offline' | 'busy';
461
670
  /**
462
671
  * Authenticated subscriber profile.
463
672
  *
@@ -494,37 +703,84 @@ declare class Subscriber extends Fetchable<GetSubscriberInfoResponse> {
494
703
  };
495
704
  /** Fabric addresses associated with this subscriber. */
496
705
  addresses: GetAddressResponse[];
706
+ /** Filtered SAT claims when the token has special capabilities (e.g., refresh scope). */
707
+ satClaims?: SATClaims;
497
708
  constructor(http: HTTPRequestController);
498
709
  protected populateInstance(data: GetSubscriberInfoResponse): void;
499
710
  }
500
711
  //#endregion
501
712
  //#region src/core/types/call.types.d.ts
713
+ /** SDP role for the peer connection negotiation. */
502
714
  type RTCPeerConnectionType = 'offer' | 'answer';
715
+ /** Purpose of the peer connection (primary call, screen share, or additional device). */
503
716
  type RTCPeerConnectionPropose = 'main' | 'screenshare' | 'additional-device';
717
+ /** States during call connection establishment. */
504
718
  type CallConnectStates = 'connecting' | 'connected';
719
+ /** Lifecycle states of the signaling protocol for a call. */
505
720
  type SignalingCallStates = 'created' | 'ringing' | 'answered' | 'ending' | 'ended';
721
+ /** Whether the call is inbound (received) or outbound (initiated). */
506
722
  type CallDirection = 'inbound' | 'outbound';
723
+ /** Playback state of media being played into a call. */
507
724
  type CallPlayState = 'playing' | 'paused' | 'finished';
725
+ /** Common parameters shared by all call device types. */
508
726
  interface CallDeviceCommonParams {
727
+ /** Optional SIP headers to include in the call setup. */
509
728
  headers?: unknown[];
510
729
  }
730
+ /** Parameters for a WebRTC or SIP call device. */
511
731
  interface CallDeviceWebRTCOrSIPParams extends CallDeviceCommonParams {
732
+ /** Source address or URI for the call. */
512
733
  from: string;
734
+ /** Destination address or URI for the call. */
513
735
  to: string;
514
736
  }
737
+ /** Parameters for a phone (PSTN) call device. */
515
738
  interface CallDevicePhoneParams extends CallDeviceCommonParams {
739
+ /** Caller phone number (E.164 format). */
516
740
  from_number: string;
741
+ /** Destination phone number (E.164 format). */
517
742
  to_number: string;
518
743
  }
744
+ /** A WebRTC or SIP call device descriptor. */
519
745
  interface CallDeviceWebRTCOrSIP {
746
+ /** Transport type for the device. */
520
747
  type: 'webrtc' | 'sip';
748
+ /** Connection parameters for the device. */
521
749
  params: CallDeviceWebRTCOrSIPParams;
522
750
  }
751
+ /** A phone (PSTN) call device descriptor. */
523
752
  interface CallDevicePhone {
753
+ /** Transport type for the device. */
524
754
  type: 'phone';
755
+ /** Connection parameters for the device. */
525
756
  params: CallDevicePhoneParams;
526
757
  }
758
+ /** Discriminated union of call device types (WebRTC, SIP, or phone). */
527
759
  type CallDevice = CallDeviceWebRTCOrSIP | CallDevicePhone;
760
+ /**
761
+ * Feature capability string that controls what actions a participant can perform.
762
+ *
763
+ * Capabilities are organized into categories:
764
+ * - **self.\*** — Actions the local participant can perform on themselves (mute, deaf, volume, position, meta).
765
+ * - **member.\*** — Actions that can be performed on other participants.
766
+ * - **layout.\*** — Layout management for the video canvas.
767
+ * - **digit.\*** — DTMF digit sending.
768
+ * - **vmuted.\*** — Visibility control for muted video participants.
769
+ * - **lock.\*** — Room lock/unlock control.
770
+ * - **device** / **screenshare** — Device and screen share capabilities.
771
+ * - **end** — Permission to end the call or room.
772
+ */
773
+ type Capability = 'self' | 'self.mute' | 'self.mute.audio' | 'self.mute.audio.on' | 'self.mute.audio.off' | 'self.mute.video' | 'self.mute.video.on' | 'self.mute.video.off' | 'self.deaf' | 'self.deaf.on' | 'self.deaf.off' | 'self.microphone' | 'self.microphone.volume.set' | 'self.microphone.sensitivity.set' | 'self.speaker' | 'self.speaker.volume.set' | 'self.position.set' | 'self.meta' | 'self.audioflags.set' | 'member' | 'member.mute' | 'member.mute.audio' | 'member.mute.audio.on' | 'member.mute.audio.off' | 'member.mute.video' | 'member.mute.video.on' | 'member.mute.video.off' | 'member.deaf' | 'member.deaf.on' | 'member.deaf.off' | 'member.microphone' | 'member.microphone.volume.set' | 'member.microphone.sensitivity.set' | 'member.speaker' | 'member.speaker.volume.set' | 'member.position.set' | 'member.meta' | 'member.audioflags.set' | 'layout' | 'layout.set' | 'digit' | 'digit.send' | 'vmuted' | 'vmuted.hide' | 'vmuted.hide.on' | 'vmuted.hide.off' | 'lock' | 'lock.on' | 'lock.off' | 'device' | 'screenshare' | 'end';
774
+ /**
775
+ * Position of a participant's video within the layout canvas.
776
+ *
777
+ * - `'auto'` — Automatically positioned by the layout engine.
778
+ * - `` `reserved-${number}` `` — A reserved slot in the layout (e.g., `'reserved-0'`).
779
+ * - `` `standard-${number}` `` — A standard slot in the layout (e.g., `'standard-1'`).
780
+ * - `'off-canvas'` — Participant is not visible in the layout.
781
+ * - `'playback'` — Playback position for media streams.
782
+ * - `'full-screen'` — Participant occupies the entire canvas.
783
+ */
528
784
  type VideoPosition = 'auto' | `reserved-${number}` | `standard-${number}` | 'off-canvas' | 'playback' | 'full-screen';
529
785
  //#endregion
530
786
  //#region src/core/RPCMessages/types/common.d.ts
@@ -674,6 +930,11 @@ interface CallUpdatedPayload {
674
930
  room_id: string;
675
931
  room_session_id: string;
676
932
  }
933
+ interface RoomUpdatedPayload {
934
+ room_session: RoomSession;
935
+ room_id: string;
936
+ room_session_id: string;
937
+ }
677
938
  interface CallStatePayload {
678
939
  call_id: string;
679
940
  node_id: string;
@@ -749,17 +1010,17 @@ declare class EntityCollection<T extends Entity = Entity> extends Destroyable im
749
1010
  private fetchController;
750
1011
  private update$;
751
1012
  private readonly onError?;
752
- loading$: rxjs0.BehaviorSubject<boolean>;
753
- values$: ReplaySubject<T[]>;
754
1013
  hasMore$: Observable<boolean>;
755
1014
  private collectionData;
756
1015
  private observablesRegistry;
757
- private updateSubscription;
758
1016
  private upsertData;
1017
+ private _loading$;
1018
+ private _values$;
759
1019
  private _hasMore$;
760
- private _destroy$;
761
1020
  constructor(fetchController: FetchController<T>, update$: Observable<Partial<T>>, onError?: ((error: Error) => void) | undefined);
1021
+ get loading$(): Observable<boolean>;
762
1022
  get loading(): boolean;
1023
+ get values$(): Observable<T[]>;
763
1024
  get hasMore(): boolean;
764
1025
  get updated$(): Observable<void>;
765
1026
  get values(): T[];
@@ -789,6 +1050,35 @@ declare class EntityCollectionTransformed<O extends Entity = Entity, T extends E
789
1050
  destroy(): void;
790
1051
  }
791
1052
  //#endregion
1053
+ //#region src/core/entities/types/participant.types.d.ts
1054
+ /** Options for selecting a media device. */
1055
+ interface SelectDeviceOptions {
1056
+ savePreference?: boolean;
1057
+ }
1058
+ //#endregion
1059
+ //#region src/controllers/RTCStatsMonitor.d.ts
1060
+ interface NetworkIssue {
1061
+ type: 'no_inbound_audio' | 'no_inbound_video' | 'high_rtt' | 'high_packet_loss' | 'high_jitter' | 'ice_disconnected';
1062
+ severity: 'warning' | 'critical';
1063
+ timestamp: number;
1064
+ value?: number;
1065
+ threshold?: number;
1066
+ }
1067
+ interface NetworkMetrics {
1068
+ timestamp: number;
1069
+ audio: {
1070
+ packetsReceived: number;
1071
+ packetsLost: number;
1072
+ jitter: number;
1073
+ };
1074
+ video: {
1075
+ packetsReceived: number;
1076
+ packetsLost: number;
1077
+ };
1078
+ roundTripTime: number;
1079
+ availableOutgoingBitrate?: number;
1080
+ }
1081
+ //#endregion
792
1082
  //#region src/managers/types/verto-manager.types.d.ts
793
1083
  type ScreenShareStatus = 'none' | 'starting' | 'started' | 'stopping';
794
1084
  type SignalingStatus = Extract<CallStatus, 'trying' | 'ringing' | 'connecting' | 'connected' | 'disconnected' | 'failed'>;
@@ -861,19 +1151,306 @@ declare class MediaTrackError extends Error {
861
1151
  originalError: unknown;
862
1152
  constructor(operation: string, kind: string, originalError: unknown);
863
1153
  }
1154
+ declare class DPoPInitError extends Error {
1155
+ originalError: unknown;
1156
+ constructor(originalError: unknown, message?: string);
1157
+ }
1158
+ /**
1159
+ * Error thrown when a recovery attempt fails.
1160
+ *
1161
+ * Carries the recovery action and attempt number for diagnostic purposes.
1162
+ */
1163
+ declare class RecoveryError extends Error {
1164
+ action: string;
1165
+ attempt: number;
1166
+ originalError?: unknown | undefined;
1167
+ constructor(action: string, attempt: number, originalError?: unknown | undefined);
1168
+ }
1169
+ /**
1170
+ * Error thrown when getUserMedia fails with OverconstrainedError
1171
+ * and all fallback levels have been exhausted.
1172
+ */
1173
+ declare class OverconstrainedFallbackError extends Error {
1174
+ deviceKind: string;
1175
+ originalError?: unknown | undefined;
1176
+ constructor(deviceKind: string, originalError?: unknown | undefined);
1177
+ }
1178
+ /**
1179
+ * Error thrown when the preflight connectivity test fails.
1180
+ */
1181
+ declare class PreflightError extends Error {
1182
+ phase: string;
1183
+ originalError?: unknown | undefined;
1184
+ constructor(phase: string, originalError?: unknown | undefined);
1185
+ }
1186
+ declare class DeviceTokenError extends Error {
1187
+ originalError?: unknown | undefined;
1188
+ constructor(message: string, originalError?: unknown | undefined);
1189
+ }
1190
+ declare class TokenRefreshError extends Error {
1191
+ originalError?: unknown | undefined;
1192
+ constructor(message: string, originalError?: unknown | undefined);
1193
+ }
1194
+ //#endregion
1195
+ //#region src/core/types/resilience.types.d.ts
1196
+ /**
1197
+ * Types for SDK resilience, recovery, diagnostics, and quality monitoring.
1198
+ *
1199
+ * These types support:
1200
+ * - WebRTC stats monitoring (Section 1)
1201
+ * - Tiered recovery system (Section 2)
1202
+ * - Device recovery events (Section 5)
1203
+ * - Tab visibility handling (Section 4)
1204
+ * - Audio/video constraint management (Section 16)
1205
+ * - Network resilience & recovery pipeline (Section 19)
1206
+ * - Preflight connectivity test (Section 20)
1207
+ * - Call quality score (Section 21)
1208
+ * - Graceful degradation (Section 22)
1209
+ * - Platform capability detection (Section 24)
1210
+ * - Structured diagnostic log export (Section 26)
1211
+ */
1212
+ /** Simplified quality level for UI indicators, derived from MOS score. */
1213
+ type QualityLevel = 'excellent' | 'good' | 'fair' | 'poor' | 'critical';
1214
+ /**
1215
+ * Extended call status that includes the 'recovering' state.
1216
+ *
1217
+ * Used when the SDK is attempting to recover a call after a network
1218
+ * disruption or media failure.
1219
+ */
1220
+ type ResilienceCallStatus = 'new' | 'trying' | 'ringing' | 'connecting' | 'connected' | 'recovering' | 'disconnecting' | 'disconnected' | 'failed' | 'destroyed';
1221
+ type NetworkMetrics$1 = NetworkMetrics;
1222
+ /** Event emitted when a recovery action is taken on a call. */
1223
+ interface RecoveryEvent {
1224
+ /** The recovery action that was taken. */
1225
+ readonly action: 'keyframe_requested' | 'reinvite_started' | 'reinvite_succeeded' | 'reinvite_failed' | 'reinvite_timeout' | 'max_attempts_reached' | 'call_recovering' | 'call_recovered' | 'call_recovery_failed' | 'signal_reconnect' | 'full_reconnect' | 'video_disabled' | 'video_restored';
1226
+ /** Human-readable description of why recovery was triggered. */
1227
+ readonly reason: string;
1228
+ /** Current attempt number (for multi-attempt recoveries). */
1229
+ readonly attempt?: number;
1230
+ /** Maximum number of attempts allowed. */
1231
+ readonly maxAttempts?: number;
1232
+ /** Timestamp when the event occurred (epoch ms). */
1233
+ readonly timestamp: number;
1234
+ }
1235
+ /** State of the recovery pipeline state machine (Section 19.7). */
1236
+ type RecoveryState = 'idle' | 'debouncing' | 'recovering' | 'cooldown';
1237
+ /** Event emitted when the SDK auto-switches a device. */
1238
+ interface DeviceRecoveryEvent {
1239
+ /** The kind of device that was switched. */
1240
+ readonly kind: 'audioinput' | 'audiooutput' | 'videoinput';
1241
+ /** The device that was previously selected (null if none). */
1242
+ readonly previousDevice: MediaDeviceInfo | null;
1243
+ /** The device that was selected as a replacement (null if none available). */
1244
+ readonly newDevice: MediaDeviceInfo | null;
1245
+ /** The reason for the device switch. */
1246
+ readonly reason: 'device_disconnected' | 'device_reconnected' | 'session_restored' | 'fallback_to_default' | 'default_changed' | 'ambiguous_match';
1247
+ }
1248
+ /**
1249
+ * Serializable subset of MediaDeviceInfo for persistence.
1250
+ *
1251
+ * The browser's MediaDeviceInfo interface is not serializable.
1252
+ * This stores the fields needed for device recovery across sessions.
1253
+ */
1254
+ interface StoredDevicePreference {
1255
+ /** The device ID. */
1256
+ readonly deviceId: string;
1257
+ /** The human-readable label. */
1258
+ readonly label: string;
1259
+ /** The device kind. */
1260
+ readonly kind: MediaDeviceKind;
1261
+ /** The group ID (identifies the physical device). */
1262
+ readonly groupId: string;
1263
+ }
1264
+ /** Result of a media permissions request (Section 5.10). */
1265
+ interface PermissionResult {
1266
+ /** Whether audio permission was granted. */
1267
+ readonly audio: boolean;
1268
+ /** Whether video permission was granted. */
1269
+ readonly video: boolean;
1270
+ /** The audio device the user selected in the browser picker, if any. */
1271
+ readonly selectedAudioDevice?: MediaDeviceInfo;
1272
+ /** The video device the user selected in the browser picker, if any. */
1273
+ readonly selectedVideoDevice?: MediaDeviceInfo;
1274
+ }
1275
+ /** Event emitted when getUserMedia falls back to looser constraints. */
1276
+ interface ConstraintFallbackEvent {
1277
+ /** The kind of input device. */
1278
+ readonly kind: 'audioinput' | 'videoinput';
1279
+ /** The device that was originally requested. */
1280
+ readonly requestedDevice: MediaDeviceInfo | null;
1281
+ /** The device that the browser actually provided. */
1282
+ readonly actualDevice: MediaDeviceInfo | null;
1283
+ /** The constraint level that succeeded. */
1284
+ readonly fallbackLevel: 'exact' | 'preferred' | 'default';
1285
+ }
1286
+ /** Browser/platform WebRTC capability flags. */
1287
+ interface PlatformCapabilities {
1288
+ /** Whether screen sharing is supported. */
1289
+ readonly screenShare: boolean;
1290
+ /** Whether screen share can include system audio (Chrome-only). */
1291
+ readonly screenShareAudio: boolean;
1292
+ /** Whether simulcast is supported. */
1293
+ readonly simulcast: boolean;
1294
+ /** Whether insertable streams / encoded transforms are available. */
1295
+ readonly insertableStreams: boolean;
1296
+ /** Whether setSinkId (audio output selection) is supported. */
1297
+ readonly audioOutputSelection: boolean;
1298
+ /** List of supported video codecs. */
1299
+ readonly videoCodecs: readonly string[];
1300
+ /** List of supported audio codecs. */
1301
+ readonly audioCodecs: readonly string[];
1302
+ /** Whether the browser supports WebRTC at all. */
1303
+ readonly webrtc: boolean;
1304
+ /** Whether getUserMedia is available. */
1305
+ readonly getUserMedia: boolean;
1306
+ /** Whether getDisplayMedia is available. */
1307
+ readonly getDisplayMedia: boolean;
1308
+ }
1309
+ /** Options for the preflight connectivity test. */
1310
+ interface PreflightOptions {
1311
+ /** How long to run the media test in seconds (default: 10). */
1312
+ readonly duration?: number;
1313
+ /** Skip the media/bandwidth test, only test signaling + TURN + devices. */
1314
+ readonly skipMediaTest?: boolean;
1315
+ /** Test a specific audio device instead of the currently selected one. */
1316
+ readonly audioDevice?: MediaDeviceInfo;
1317
+ /** Test a specific video device instead of the currently selected one. */
1318
+ readonly videoDevice?: MediaDeviceInfo;
1319
+ }
1320
+ /** Results of a preflight connectivity test. */
1321
+ interface PreflightResult {
1322
+ /** Overall pass/fail. */
1323
+ readonly ok: boolean;
1324
+ /** Signaling server reachability. */
1325
+ readonly signaling: {
1326
+ readonly reachable: boolean;
1327
+ readonly rttMs: number;
1328
+ };
1329
+ /** ICE/TURN connectivity. */
1330
+ readonly connectivity: {
1331
+ /** 'direct' = host/srflx worked, 'relay' = only TURN relay, 'failed' = nothing. */
1332
+ readonly type: 'direct' | 'relay' | 'failed';
1333
+ /** Whether TURN servers are reachable. */
1334
+ readonly turnReachable: boolean;
1335
+ /** Whether STUN servers are reachable. */
1336
+ readonly stunReachable: boolean;
1337
+ /** RTT to media server in ms. */
1338
+ readonly rttMs: number;
1339
+ };
1340
+ /** Bandwidth estimation (null if skipMediaTest). */
1341
+ readonly bandwidth: {
1342
+ readonly uploadKbps: number;
1343
+ readonly downloadKbps: number;
1344
+ } | null;
1345
+ /** Device test results. */
1346
+ readonly devices: {
1347
+ readonly audioInput: {
1348
+ readonly working: boolean;
1349
+ readonly device: MediaDeviceInfo | null;
1350
+ };
1351
+ readonly videoInput: {
1352
+ readonly working: boolean;
1353
+ readonly device: MediaDeviceInfo | null;
1354
+ };
1355
+ readonly audioOutput: {
1356
+ readonly available: boolean;
1357
+ readonly device: MediaDeviceInfo | null;
1358
+ };
1359
+ };
1360
+ /** Human-readable warnings. */
1361
+ readonly warnings: readonly string[];
1362
+ }
1363
+ /** Event emitted when audio constraints change on a call. */
1364
+ interface AudioConstraintsEvent {
1365
+ /** The new constraints applied. */
1366
+ readonly constraints: MediaTrackConstraints;
1367
+ /** How the constraints were applied. */
1368
+ readonly method: 'applyConstraints' | 'trackReplacement';
1369
+ /** Timestamp when the event occurred (epoch ms). */
1370
+ readonly timestamp: number;
1371
+ }
1372
+ /** Event emitted when server-pushed media params are applied. */
1373
+ interface MediaParamsEvent {
1374
+ /** Audio constraints pushed by the server, if any. */
1375
+ readonly audio?: MediaTrackConstraints;
1376
+ /** Video constraints pushed by the server, if any. */
1377
+ readonly video?: MediaTrackConstraints;
1378
+ /** Timestamp when the event occurred (epoch ms). */
1379
+ readonly timestamp: number;
1380
+ }
1381
+ /** Structured diagnostic bundle for a session. */
1382
+ interface SessionDiagnostics {
1383
+ /** SDK version. */
1384
+ readonly sdkVersion: string;
1385
+ /** Browser/platform user agent string. */
1386
+ readonly userAgent: string;
1387
+ /** Platform capabilities detected at construction time. */
1388
+ readonly capabilities: PlatformCapabilities;
1389
+ /** Timeline of significant events during the session. */
1390
+ readonly events: readonly DiagnosticEvent[];
1391
+ /** Quality summary per call. */
1392
+ readonly calls: readonly CallDiagnosticSummary[];
1393
+ /** Device changes that occurred during the session. */
1394
+ readonly deviceChanges: readonly DeviceRecoveryEvent[];
1395
+ /** Current device list snapshot. */
1396
+ readonly devices: {
1397
+ readonly audioInput: readonly MediaDeviceInfo[];
1398
+ readonly audioOutput: readonly MediaDeviceInfo[];
1399
+ readonly videoInput: readonly MediaDeviceInfo[];
1400
+ };
1401
+ }
1402
+ /** A single diagnostic event in the session timeline. */
1403
+ interface DiagnosticEvent {
1404
+ /** Timestamp when the event occurred (epoch ms). */
1405
+ readonly timestamp: number;
1406
+ /** Category of the event. */
1407
+ readonly category: 'connection' | 'call' | 'device' | 'recovery' | 'error';
1408
+ /** Event description string. */
1409
+ readonly event: string;
1410
+ /** Additional details about the event. */
1411
+ readonly details?: Readonly<Record<string, unknown>>;
1412
+ }
1413
+ /** Quality summary for a single call in the diagnostic bundle. */
1414
+ interface CallDiagnosticSummary {
1415
+ /** Unique call ID. */
1416
+ readonly callId: string;
1417
+ /** Whether the call was inbound or outbound. */
1418
+ readonly direction: 'inbound' | 'outbound';
1419
+ /** The destination dialed, if outbound. */
1420
+ readonly destination?: string;
1421
+ /** Total call duration in seconds. */
1422
+ readonly duration: number;
1423
+ /** Final call status. */
1424
+ readonly status: string;
1425
+ /** Average MOS quality score over the call. */
1426
+ readonly avgQualityScore: number;
1427
+ /** Worst (minimum) MOS quality score during the call. */
1428
+ readonly minQualityScore: number;
1429
+ /** Number of recovery attempts made during the call. */
1430
+ readonly recoveryAttempts: number;
1431
+ /** ICE candidate types that were used. */
1432
+ readonly iceCandidateTypes: readonly string[];
1433
+ /** Final network metrics snapshot at call end. */
1434
+ readonly finalMetrics: NetworkMetrics$1;
1435
+ }
864
1436
  //#endregion
865
1437
  //#region src/core/RPCMessages/RPCConnect.d.ts
866
1438
  interface Authorization {
867
1439
  jti: string;
868
1440
  project_id: string;
1441
+ data_zone?: string;
1442
+ scope?: string[];
869
1443
  fabric_subscriber: {
870
1444
  version: number;
871
1445
  expires_at: number;
872
1446
  subscriber_id: string;
873
- application_id: string;
1447
+ application_id: string | null;
874
1448
  project_id: string;
875
1449
  space_id: string;
876
1450
  };
1451
+ cnf?: {
1452
+ jkt: string;
1453
+ };
877
1454
  }
878
1455
  //#endregion
879
1456
  //#region src/core/utils.d.ts
@@ -1000,40 +1577,107 @@ declare class SelfCapabilities extends Destroyable {
1000
1577
  get state(): CallCapabilitiesState;
1001
1578
  }
1002
1579
  //#endregion
1003
- //#region src/core/entities/types/participant.types.d.ts
1004
- interface SelectDeviceOptions {
1005
- savePreference?: boolean;
1006
- }
1007
- //#endregion
1008
1580
  //#region src/interfaces/DeviceController.d.ts
1009
1581
  /**
1010
- * Device interface for media device management
1011
- * Provides access to media devices and device selection
1582
+ * Interface for media device management.
1583
+ *
1584
+ * Provides reactive access to available media devices, device selection,
1585
+ * and monitoring for device changes (connect/disconnect).
1012
1586
  */
1013
1587
  interface DeviceController {
1588
+ /** Observable list of available audio input (microphone) devices. */
1014
1589
  readonly audioInputDevices$: Observable<MediaDeviceInfo[]>;
1590
+ /** Observable list of available audio output (speaker) devices. */
1015
1591
  readonly audioOutputDevices$: Observable<MediaDeviceInfo[]>;
1592
+ /** Observable list of available video input (camera) devices. */
1016
1593
  readonly videoInputDevices$: Observable<MediaDeviceInfo[]>;
1594
+ /** Observable of the currently selected audio input device, or `null` if none. */
1017
1595
  readonly selectedAudioInputDevice$: Observable<MediaDeviceInfo | null>;
1596
+ /** Observable of the currently selected audio output device, or `null` if none. */
1018
1597
  readonly selectedAudioOutputDevice$: Observable<MediaDeviceInfo | null>;
1598
+ /** Observable of the currently selected video input device, or `null` if none. */
1019
1599
  readonly selectedVideoInputDevice$: Observable<MediaDeviceInfo | null>;
1600
+ /** Currently selected audio input device, or `null` if none. */
1020
1601
  readonly selectedAudioInputDevice: MediaDeviceInfo | null;
1602
+ /** Currently selected audio output device, or `null` if none. */
1021
1603
  readonly selectedAudioOutputDevice: MediaDeviceInfo | null;
1604
+ /** Currently selected video input device, or `null` if none. */
1022
1605
  readonly selectedVideoInputDevice: MediaDeviceInfo | null;
1606
+ /** Current snapshot of available audio input devices. */
1023
1607
  readonly audioInputDevices: MediaDeviceInfo[];
1608
+ /** Current snapshot of available audio output devices. */
1024
1609
  readonly audioOutputDevices: MediaDeviceInfo[];
1610
+ /** Current snapshot of available video input devices. */
1025
1611
  readonly videoInputDevices: MediaDeviceInfo[];
1026
- readonly selectedAudioInputDeviceConstraints: MediaTrackConstraints;
1027
- readonly selectedVideoInputDeviceConstraints: MediaTrackConstraints;
1612
+ /** Media track constraints for the selected audio input device. Returns `false` when disabled. */
1613
+ readonly selectedAudioInputDeviceConstraints: MediaTrackConstraints | boolean;
1614
+ /** Media track constraints for the selected video input device. Returns `false` when disabled. */
1615
+ readonly selectedVideoInputDeviceConstraints: MediaTrackConstraints | boolean;
1616
+ /**
1617
+ * Converts a {@link MediaDeviceInfo} to track constraints suitable for `getUserMedia`.
1618
+ * @param deviceInfo - The device to convert, or `null` for default constraints.
1619
+ */
1028
1620
  deviceInfoToConstraints(deviceInfo: MediaDeviceInfo | null): MediaTrackConstraints;
1621
+ /**
1622
+ * Sets the preferred audio input device for future calls.
1623
+ * @param device - The device to select, or `null` to use the system default.
1624
+ */
1029
1625
  selectAudioInputDevice(device: MediaDeviceInfo | null): void;
1626
+ /**
1627
+ * Sets the preferred video input device for future calls.
1628
+ * @param device - The device to select, or `null` to use the system default.
1629
+ */
1030
1630
  selectVideoInputDevice(device: MediaDeviceInfo | null): void;
1631
+ /**
1632
+ * Sets the preferred audio output device for future calls.
1633
+ * @param device - The device to select, or `null` to use the system default.
1634
+ */
1031
1635
  selectAudioOutputDevice(device: MediaDeviceInfo | null): void;
1636
+ /** Starts monitoring for media device changes (connect/disconnect). */
1032
1637
  enableDeviceMonitoring(): void;
1638
+ /** Stops monitoring for media device changes. */
1033
1639
  disableDeviceMonitoring(): void;
1640
+ /**
1641
+ * Returns the capabilities of a media device.
1642
+ * @param deviceInfo - The device to query.
1643
+ * @returns The device capabilities, or `null` if unavailable.
1644
+ */
1034
1645
  getDeviceCapabilities(deviceInfo: MediaDeviceInfo): Promise<MediaTrackCapabilities | null>;
1646
+ /**
1647
+ * Checks whether a device is still available and usable.
1648
+ * @param deviceInfo - The device to validate, or `null`.
1649
+ * @returns `true` if the device is valid and available. Returns `false` for `null`, audio output devices, or unavailable devices.
1650
+ */
1035
1651
  isValidDevice(deviceInfo: MediaDeviceInfo | null): Promise<boolean>;
1652
+ /** Observable stream of errors from device enumeration and monitoring. */
1036
1653
  readonly errors$: Observable<Error>;
1654
+ /**
1655
+ * Observable that emits when the SDK auto-switches a device due to
1656
+ * disconnect, reconnect, or recovery.
1657
+ */
1658
+ readonly deviceRecovered$: Observable<DeviceRecoveryEvent>;
1659
+ /** Disables audio input (receive-only mode). No track will be acquired. */
1660
+ disableAudioInput(): void;
1661
+ /** Re-enables audio input, restoring the last selection or auto-selecting. */
1662
+ enableAudioInput(): void;
1663
+ /** Disables video input (receive-only mode). No track will be acquired. */
1664
+ disableVideoInput(): void;
1665
+ /** Re-enables video input, restoring the last selection or auto-selecting. */
1666
+ enableVideoInput(): void;
1667
+ /** Observable that emits `true` when video input is disabled (receive-only). */
1668
+ readonly videoInputDisabled$: Observable<boolean>;
1669
+ /** Observable that emits `true` when audio input is disabled (receive-only). */
1670
+ readonly audioInputDisabled$: Observable<boolean>;
1671
+ /** Whether video input is currently disabled. */
1672
+ readonly videoInputDisabled: boolean;
1673
+ /** Whether audio input is currently disabled. */
1674
+ readonly audioInputDisabled: boolean;
1675
+ /** Injects the storage manager for device persistence. */
1676
+ setStorageManager(storageManager: StorageManager): void;
1677
+ /** Clears all device state (history, selections, persisted prefs) and re-enumerates. */
1678
+ clearDeviceState(): Promise<void>;
1679
+ /** Force a device re-enumeration. */
1680
+ enumerateDevices(): Promise<void>;
1037
1681
  }
1038
1682
  //#endregion
1039
1683
  //#region src/interfaces/VertoManager.d.ts
@@ -1085,45 +1729,45 @@ declare class Participant extends Destroyable implements CallParticipant {
1085
1729
  /** @internal */
1086
1730
  upnext(data: Partial<ParticipantState>): void;
1087
1731
  /** Observable of the participant's display name. */
1088
- get name$(): Observable<string>;
1732
+ get name$(): Observable<string | undefined>;
1089
1733
  /** Observable of the participant type (e.g. `'member'`, `'screen'`). */
1090
- get type$(): Observable<string>;
1734
+ get type$(): Observable<string | undefined>;
1091
1735
  /** Observable indicating whether the participant has raised their hand. */
1092
- get handraised$(): Observable<boolean>;
1736
+ get handraised$(): Observable<boolean | undefined>;
1093
1737
  /** Observable indicating whether the participant is visible in the layout. */
1094
- get visible$(): Observable<boolean>;
1738
+ get visible$(): Observable<boolean | undefined>;
1095
1739
  /** Observable indicating whether the participant's audio is muted. */
1096
- get audioMuted$(): Observable<boolean>;
1740
+ get audioMuted$(): Observable<boolean | undefined>;
1097
1741
  /** Observable indicating whether the participant's video is muted. */
1098
- get videoMuted$(): Observable<boolean>;
1742
+ get videoMuted$(): Observable<boolean | undefined>;
1099
1743
  /** Observable indicating whether the participant is deafened. */
1100
- get deaf$(): Observable<boolean>;
1744
+ get deaf$(): Observable<boolean | undefined>;
1101
1745
  /** Observable of the participant's microphone input volume. */
1102
- get inputVolume$(): Observable<number>;
1746
+ get inputVolume$(): Observable<number | undefined>;
1103
1747
  /** Observable of the participant's speaker output volume. */
1104
- get outputVolume$(): Observable<number>;
1748
+ get outputVolume$(): Observable<number | undefined>;
1105
1749
  /** Observable of the microphone input sensitivity level. */
1106
- get inputSensitivity$(): Observable<number>;
1750
+ get inputSensitivity$(): Observable<number | undefined>;
1107
1751
  /** Observable indicating whether echo cancellation is enabled. */
1108
- get echoCancellation$(): Observable<boolean>;
1752
+ get echoCancellation$(): Observable<boolean | undefined>;
1109
1753
  /** Observable indicating whether auto-gain control is enabled. */
1110
- get autoGain$(): Observable<boolean>;
1754
+ get autoGain$(): Observable<boolean | undefined>;
1111
1755
  /** Observable indicating whether noise suppression is enabled. */
1112
- get noiseSuppression$(): Observable<boolean>;
1756
+ get noiseSuppression$(): Observable<boolean | undefined>;
1113
1757
  /** Observable indicating whether low-bitrate mode is active. */
1114
- get lowbitrate$(): Observable<boolean>;
1758
+ get lowbitrate$(): Observable<boolean | undefined>;
1115
1759
  /** Observable indicating whether noise reduction is active. */
1116
- get denoise$(): Observable<boolean>;
1760
+ get denoise$(): Observable<boolean | undefined>;
1117
1761
  /** Observable of custom metadata for this participant. */
1118
- get meta$(): Observable<Record<string, unknown>>;
1762
+ get meta$(): Observable<Record<string, unknown> | undefined>;
1119
1763
  /** Observable of the participant's subscriber ID. */
1120
- get subscriberId$(): Observable<string>;
1764
+ get subscriberId$(): Observable<string | undefined>;
1121
1765
  /** Observable of the participant's address ID. */
1122
- get addressId$(): Observable<string>;
1766
+ get addressId$(): Observable<string | undefined>;
1123
1767
  /** Observable of the server node ID for this participant. */
1124
- get nodeId$(): Observable<string>;
1768
+ get nodeId$(): Observable<string | undefined>;
1125
1769
  /** Observable indicating whether the participant is currently speaking. */
1126
- get isTalking$(): Observable<boolean>;
1770
+ get isTalking$(): Observable<boolean | undefined>;
1127
1771
  /** Whether the participant is currently speaking. */
1128
1772
  get isTalking(): boolean;
1129
1773
  /** Observable of the participant's layout position. */
@@ -1136,22 +1780,39 @@ declare class Participant extends Destroyable implements CallParticipant {
1136
1780
  get name(): string | undefined;
1137
1781
  /** Participant type (e.g. `'member'`, `'screen'`). */
1138
1782
  get type(): string | undefined;
1783
+ /** Whether the participant has raised their hand. */
1139
1784
  get handraised(): boolean;
1785
+ /** Whether the participant is visible in the layout. */
1140
1786
  get visible(): boolean;
1787
+ /** Whether the participant's audio is muted. */
1141
1788
  get audioMuted(): boolean;
1789
+ /** Whether the participant's video is muted. */
1142
1790
  get videoMuted(): boolean;
1791
+ /** Whether the participant is deafened (incoming audio muted). */
1143
1792
  get deaf(): boolean;
1793
+ /** Current microphone input volume level, or `undefined` if not set. */
1144
1794
  get inputVolume(): number | undefined;
1795
+ /** Current speaker output volume level, or `undefined` if not set. */
1145
1796
  get outputVolume(): number | undefined;
1797
+ /** Current microphone input sensitivity level, or `undefined` if not set. */
1146
1798
  get inputSensitivity(): number | undefined;
1799
+ /** Whether echo cancellation is enabled. */
1147
1800
  get echoCancellation(): boolean;
1801
+ /** Whether automatic gain control is enabled. */
1148
1802
  get autoGain(): boolean;
1803
+ /** Whether noise suppression is enabled. */
1149
1804
  get noiseSuppression(): boolean;
1805
+ /** Whether low-bitrate mode is active. */
1150
1806
  get lowbitrate(): boolean;
1807
+ /** Whether noise reduction (denoise) is active. */
1151
1808
  get denoise(): boolean;
1809
+ /** Custom metadata for this participant, or `undefined` if not set. */
1152
1810
  get meta(): Record<string, unknown> | undefined;
1811
+ /** Subscriber ID of this participant, or `undefined` if not available. */
1153
1812
  get subscriberId(): string | undefined;
1813
+ /** Address ID of this participant, or `undefined` if not available. */
1154
1814
  get addressId(): string | undefined;
1815
+ /** Server node ID for this participant, or `undefined` if not available. */
1155
1816
  get nodeId(): string | undefined;
1156
1817
  /** @internal */
1157
1818
  get value(): Partial<Member>;
@@ -1180,18 +1841,38 @@ declare class Participant extends Destroyable implements CallParticipant {
1180
1841
  toggleLowbitrate(): Promise<void>;
1181
1842
  /** Sets the microphone input sensitivity level. */
1182
1843
  setAudioInputSensitivity(value: number): Promise<void>;
1183
- /** Sets the microphone input volume level. */
1844
+ /**
1845
+ * Sets the microphone input volume level.
1846
+ * @param value - Volume level (0-100).
1847
+ */
1184
1848
  setAudioInputVolume(value: number): Promise<void>;
1185
- /** Sets the speaker output volume level. */
1849
+ /**
1850
+ * Sets the speaker output volume level.
1851
+ * @param value - Volume level (0-100).
1852
+ */
1186
1853
  setAudioOutputVolume(value: number): Promise<void>;
1187
- /** Sets the participant's position in the video layout. */
1854
+ /**
1855
+ * Sets the participant's position in the video layout.
1856
+ * @param value - The {@link VideoPosition} to assign (e.g. `'auto'`, `'reserved-0'`).
1857
+ */
1188
1858
  setPosition(value: VideoPosition): Promise<void>;
1189
1859
  /** Removes this participant from the call. */
1190
1860
  remove(): Promise<void>;
1191
1861
  /** Ends the call for this participant. */
1192
1862
  end(): Promise<void>;
1863
+ /**
1864
+ * Replaces custom metadata for this participant.
1865
+ * @param _meta - Metadata object to set.
1866
+ * @throws {UnimplementedError} Not yet implemented.
1867
+ */
1193
1868
  setMeta(_meta: Record<string, unknown>): Promise<void>;
1869
+ /**
1870
+ * Merges values into custom metadata (unlike {@link setMeta} which replaces).
1871
+ * @param _meta - Metadata to merge.
1872
+ * @throws {UnimplementedError} Not yet implemented.
1873
+ */
1194
1874
  updateMeta(_meta: Record<string, unknown>): Promise<void>;
1875
+ /** Destroys the participant, releasing all subscriptions and references. */
1195
1876
  destroy(): void;
1196
1877
  }
1197
1878
  /**
@@ -1207,8 +1888,29 @@ declare class SelfParticipant extends Participant implements CallSelfParticipant
1207
1888
  * Contains all capability flags as both observables and values.
1208
1889
  */
1209
1890
  readonly capabilities: SelfCapabilities;
1891
+ /**
1892
+ * Studio audio mode state. When enabled, all audio processing
1893
+ * (echo cancellation, noise suppression, auto gain control) is disabled
1894
+ * to provide raw/unprocessed audio for musicians, podcasters, etc.
1895
+ */
1896
+ private _studioAudio$;
1897
+ /** @internal */
1210
1898
  constructor(id: string, executeMethod: ExecuteMethod, vertoManager: VertoManager, deviceController: DeviceController);
1211
1899
  destroy(): void;
1900
+ /** Observable indicating whether studio audio (raw/unprocessed audio) mode is enabled. */
1901
+ get studioAudio$(): Observable<boolean>;
1902
+ /** Whether studio audio (raw/unprocessed audio) mode is currently enabled. */
1903
+ get studioAudio(): boolean;
1904
+ /**
1905
+ * Enables studio audio mode by disabling all audio processing.
1906
+ * Sets echoCancellation, noiseSuppression, and autoGainControl to false.
1907
+ */
1908
+ enableStudioAudio(): Promise<void>;
1909
+ /**
1910
+ * Disables studio audio mode by restoring all audio processing to enabled.
1911
+ * Sets echoCancellation, noiseSuppression, and autoGainControl to true.
1912
+ */
1913
+ disableStudioAudio(): Promise<void>;
1212
1914
  /** Starts sharing the local screen. */
1213
1915
  startScreenShare(): Promise<void>;
1214
1916
  /** Observable of the current screen share status. */
@@ -1254,9 +1956,24 @@ declare class SelfParticipant extends Participant implements CallSelfParticipant
1254
1956
  setVideoInputDeviceConstraints(constraints: MediaTrackConstraints): Promise<void>;
1255
1957
  /** Selects the audio output device. Optionally saves as a preference. */
1256
1958
  selectAudioOutputDevice(device: MediaDeviceInfo, options?: SelectDeviceOptions): void;
1959
+ /**
1960
+ * Exits studio audio mode without restoring defaults.
1961
+ * Called internally before individual audio flag toggles.
1962
+ */
1963
+ private exitStudioModeIfActive;
1964
+ /** Toggles echo cancellation. Exits studio mode if active. */
1965
+ toggleEchoCancellation(): Promise<void>;
1966
+ /** Toggles automatic gain control. Exits studio mode if active. */
1967
+ toggleAudioInputAutoGain(): Promise<void>;
1968
+ /** Toggles noise suppression. Exits studio mode if active. */
1969
+ toggleNoiseSuppression(): Promise<void>;
1970
+ /** Mutes local audio. Falls back to local device mute if the server RPC fails. */
1257
1971
  mute(): Promise<void>;
1972
+ /** Unmutes local audio. Falls back to local device unmute if the server RPC fails. */
1258
1973
  unmute(): Promise<void>;
1974
+ /** Mutes local video. Falls back to local device mute if the server RPC fails. */
1259
1975
  muteVideo(): Promise<void>;
1976
+ /** Unmutes local video. Falls back to local device unmute if the server RPC fails. */
1260
1977
  unmuteVideo(): Promise<void>;
1261
1978
  }
1262
1979
  /** Type guard that checks if a participant is the local {@link SelfParticipant}. */
@@ -1269,26 +1986,26 @@ declare const isSelfParticipant: (participant: Participant) => participant is Se
1269
1986
  */
1270
1987
  interface CallParticipant {
1271
1988
  readonly id: string;
1272
- readonly name$: Observable<string>;
1273
- readonly type$: Observable<string>;
1274
- readonly handraised$: Observable<boolean>;
1275
- readonly visible$: Observable<boolean>;
1276
- readonly audioMuted$: Observable<boolean>;
1277
- readonly videoMuted$: Observable<boolean>;
1278
- readonly deaf$: Observable<boolean>;
1279
- readonly inputVolume$: Observable<number>;
1280
- readonly outputVolume$: Observable<number>;
1281
- readonly inputSensitivity$: Observable<number>;
1282
- readonly echoCancellation$: Observable<boolean>;
1283
- readonly autoGain$: Observable<boolean>;
1284
- readonly noiseSuppression$: Observable<boolean>;
1285
- readonly lowbitrate$: Observable<boolean>;
1286
- readonly denoise$: Observable<boolean>;
1287
- readonly meta$: Observable<Record<string, unknown>>;
1288
- readonly subscriberId$: Observable<string>;
1289
- readonly addressId$: Observable<string>;
1290
- readonly nodeId$: Observable<string>;
1291
- readonly isTalking$: Observable<boolean>;
1989
+ readonly name$: Observable<string | undefined>;
1990
+ readonly type$: Observable<string | undefined>;
1991
+ readonly handraised$: Observable<boolean | undefined>;
1992
+ readonly visible$: Observable<boolean | undefined>;
1993
+ readonly audioMuted$: Observable<boolean | undefined>;
1994
+ readonly videoMuted$: Observable<boolean | undefined>;
1995
+ readonly deaf$: Observable<boolean | undefined>;
1996
+ readonly inputVolume$: Observable<number | undefined>;
1997
+ readonly outputVolume$: Observable<number | undefined>;
1998
+ readonly inputSensitivity$: Observable<number | undefined>;
1999
+ readonly echoCancellation$: Observable<boolean | undefined>;
2000
+ readonly autoGain$: Observable<boolean | undefined>;
2001
+ readonly noiseSuppression$: Observable<boolean | undefined>;
2002
+ readonly lowbitrate$: Observable<boolean | undefined>;
2003
+ readonly denoise$: Observable<boolean | undefined>;
2004
+ readonly meta$: Observable<Record<string, unknown> | undefined>;
2005
+ readonly subscriberId$: Observable<string | undefined>;
2006
+ readonly addressId$: Observable<string | undefined>;
2007
+ readonly nodeId$: Observable<string | undefined>;
2008
+ readonly isTalking$: Observable<boolean | undefined>;
1292
2009
  readonly position$: Observable<LayoutLayer | undefined>;
1293
2010
  readonly name: string | undefined;
1294
2011
  readonly type: string | undefined;
@@ -1338,13 +2055,34 @@ interface CallParticipant {
1338
2055
  * Extends CallParticipant with methods for controlling the local participant
1339
2056
  */
1340
2057
  interface CallSelfParticipant extends CallParticipant {
1341
- readonly screenShareStatus$: Observable<string>;
1342
- readonly screenShareStatus: string;
2058
+ readonly screenShareStatus$: Observable<ScreenShareStatus>;
2059
+ readonly screenShareStatus: ScreenShareStatus;
2060
+ readonly studioAudio$: Observable<boolean>;
2061
+ readonly studioAudio: boolean;
2062
+ enableStudioAudio(): Promise<void>;
2063
+ disableStudioAudio(): Promise<void>;
1343
2064
  startScreenShare(): Promise<void>;
1344
2065
  stopScreenShare(): Promise<void>;
1345
- selectAudioInputDevice(device: MediaDeviceInfo): void;
1346
- selectVideoInputDevice(device: MediaDeviceInfo): void;
1347
- selectAudioOutputDevice(device: MediaDeviceInfo): void;
2066
+ selectAudioInputDevice(device: MediaDeviceInfo, options?: SelectDeviceOptions): void;
2067
+ selectVideoInputDevice(device: MediaDeviceInfo, options?: SelectDeviceOptions): void;
2068
+ selectAudioOutputDevice(device: MediaDeviceInfo, options?: SelectDeviceOptions): void;
2069
+ addAdditionalDevice(options: MediaOptions): Promise<void>;
2070
+ removeAdditionalDevice(id: string): Promise<void>;
2071
+ addAudioInputDevice(options?: {
2072
+ constraints?: MediaTrackConstraints;
2073
+ stream?: MediaStream;
2074
+ }): Promise<void>;
2075
+ addVideoInputDevice(options?: {
2076
+ constraints?: MediaTrackConstraints;
2077
+ stream?: MediaStream;
2078
+ }): Promise<void>;
2079
+ addInputDevices(options?: MediaOptions): Promise<void>;
2080
+ setAudioInputDeviceConstraints(constraints: MediaTrackConstraints): Promise<void>;
2081
+ setVideoInputDeviceConstraints(constraints: MediaTrackConstraints): Promise<void>;
2082
+ setInputDevicesConstraints(constraints: {
2083
+ audio: MediaTrackConstraints;
2084
+ video: MediaTrackConstraints;
2085
+ }): Promise<void>;
1348
2086
  }
1349
2087
  /**
1350
2088
  * Minimal interface for a collection with pagination
@@ -1366,7 +2104,7 @@ interface CallAddress {
1366
2104
  readonly textMessages$: Observable<CallTextMessageCollection | undefined>;
1367
2105
  }
1368
2106
  /** Lifecycle status of a call. */
1369
- type CallStatus = 'new' | 'trying' | 'ringing' | 'connecting' | 'connected' | 'disconnecting' | 'disconnected' | 'failed' | 'destroyed';
2107
+ type CallStatus = 'new' | 'trying' | 'ringing' | 'connecting' | 'connected' | 'recovering' | 'disconnecting' | 'disconnected' | 'failed' | 'destroyed';
1370
2108
  /** Configuration options for creating a call. */
1371
2109
  interface CallOptions extends MediaOptions {
1372
2110
  /** Target server node ID. */
@@ -1389,6 +2127,12 @@ interface CallOptions extends MediaOptions {
1389
2127
  readonly displayDirection?: string;
1390
2128
  /** Custom user variables sent with the call invite. */
1391
2129
  readonly userVariables?: Record<string, unknown>;
2130
+ /** Preferred video codecs for this call (overrides global preferences). */
2131
+ readonly preferredVideoCodecs?: string[];
2132
+ /** Preferred audio codecs for this call (overrides global preferences). */
2133
+ readonly preferredAudioCodecs?: string[];
2134
+ /** Enable stereo Opus for this call (overrides global preferences). */
2135
+ readonly stereo?: boolean;
1392
2136
  }
1393
2137
  /** Observable state of a call (status, recording, participants, etc.). */
1394
2138
  interface CallState {
@@ -1417,23 +2161,26 @@ interface CallState {
1417
2161
  * and control actions (hangup, mute, transfer, etc.).
1418
2162
  */
1419
2163
  interface Call extends CallState {
1420
- readonly capabilities$: Observable<string[]>;
1421
- readonly capabilities: string[];
2164
+ readonly capabilities$: Observable<Capability[]>;
2165
+ readonly capabilities: Capability[];
1422
2166
  readonly mediaDirections$: Observable<MediaDirections>;
1423
2167
  readonly mediaDirections: MediaDirections;
1424
2168
  readonly self$: Observable<CallSelfParticipant | null>;
1425
2169
  readonly self: CallSelfParticipant | null;
1426
2170
  readonly to?: string;
1427
- readonly direction: 'inbound' | 'outbound';
2171
+ readonly direction: CallDirection;
1428
2172
  readonly layouts$: Observable<string[]>;
1429
2173
  readonly layouts: string[];
1430
2174
  readonly layout$: Observable<string>;
1431
2175
  readonly layout?: string;
1432
2176
  readonly layoutLayers$: Observable<LayoutLayer[]>;
1433
2177
  readonly layoutLayers: LayoutLayer[];
1434
- readonly localStream$: Observable<MediaStream | null>;
2178
+ /** Observable that emits only non-null MediaStreams (waits until the stream exists). */
2179
+ readonly localStream$: Observable<MediaStream>;
2180
+ /** Sync getter — returns null before the stream is created. */
1435
2181
  readonly localStream: MediaStream | null;
1436
- readonly remoteStream$: Observable<MediaStream | null>;
2182
+ /** Observable that emits only non-null MediaStreams (waits until the stream exists). */
2183
+ readonly remoteStream$: Observable<MediaStream>;
1437
2184
  readonly remoteStream: MediaStream | null;
1438
2185
  readonly rtcPeerConnection: RTCPeerConnection | undefined;
1439
2186
  readonly errors$: Observable<CallError>;
@@ -1442,6 +2189,21 @@ interface Call extends CallState {
1442
2189
  readonly address$: Observable<CallAddress | undefined>;
1443
2190
  userVariables?: Record<string, unknown>;
1444
2191
  readonly userVariables$: Observable<Record<string, unknown>>;
2192
+ readonly networkIssues$: Observable<NetworkIssue[]>;
2193
+ readonly networkIssues: NetworkIssue[];
2194
+ readonly isNetworkHealthy$: Observable<boolean>;
2195
+ readonly isNetworkHealthy: boolean;
2196
+ readonly networkMetrics$: Observable<NetworkMetrics[]>;
2197
+ readonly networkMetrics: NetworkMetrics[];
2198
+ readonly qualityScore$: Observable<number>;
2199
+ readonly qualityLevel$: Observable<QualityLevel>;
2200
+ readonly recoveryState$: Observable<RecoveryState>;
2201
+ readonly recoveryEvent$: Observable<RecoveryEvent>;
2202
+ readonly bandwidthConstrained$: Observable<boolean>;
2203
+ readonly mediaParamsUpdated$: Observable<MediaParamsEvent>;
2204
+ requestKeyframe(): void;
2205
+ requestIceRestart(): Promise<void>;
2206
+ subscribe(eventType: string): Observable<Record<string, unknown>>;
1445
2207
  hangup(): Promise<void>;
1446
2208
  toggleLock(): Promise<void>;
1447
2209
  toggleHold(): Promise<void>;
@@ -1493,7 +2255,7 @@ interface CallManager extends Call {
1493
2255
  * This interface breaks the circular dependency between Address and Directory
1494
2256
  * by providing a minimal contract that Address needs from the Directory.
1495
2257
  *
1496
- * @typeParam TAddress - The Address type, defaults to never to enforce explicit typing
2258
+ * @template TAddress - The Address type, defaults to never to enforce explicit typing
1497
2259
  *
1498
2260
  * @remarks
1499
2261
  * Uses a generic type parameter to maintain type safety while avoiding
@@ -1514,7 +2276,7 @@ interface AddressProvider<TAddress = never> {
1514
2276
  * Address history entry from conversation messages
1515
2277
  * Contains a reference to the sender address as an observable
1516
2278
  *
1517
- * @typeParam TAddress - The Address type, provided by the implementation
2279
+ * @template TAddress - The Address type, provided by the implementation
1518
2280
  *
1519
2281
  * @remarks
1520
2282
  * Uses a generic type parameter to maintain type safety while avoiding
@@ -1532,7 +2294,7 @@ interface AddressHistory<TAddress = never> {
1532
2294
  * Text message from conversation
1533
2295
  * Contains a reference to the sender address as an observable
1534
2296
  *
1535
- * @typeParam TAddress - The Address type, provided by the implementation
2297
+ * @template TAddress - The Address type, provided by the implementation
1536
2298
  *
1537
2299
  * @remarks
1538
2300
  * Uses a generic type parameter to maintain type safety while avoiding
@@ -1675,11 +2437,35 @@ declare class Address extends Destroyable {
1675
2437
  get locked(): boolean;
1676
2438
  /** Observable indicating whether the address (room) is locked. */
1677
2439
  get locked$(): Observable<boolean>;
1678
- /** Sends a text message to this address. */
2440
+ /**
2441
+ * Sends a text message to this address.
2442
+ *
2443
+ * @param text - The message text to send.
2444
+ *
2445
+ * @example
2446
+ * ```ts
2447
+ * await address.sendText('Hello!');
2448
+ * ```
2449
+ */
1679
2450
  sendText(text: string): Promise<void>;
1680
- /** Collection of text messages for this address, with pagination support. */
2451
+ /**
2452
+ * Collection of text messages for this address, with pagination support.
2453
+ *
2454
+ * Returns `undefined` until {@link textMessages$} has been subscribed to (lazy-loaded).
2455
+ * Filters to `'chat'` subtype messages from the conversation.
2456
+ *
2457
+ * @see {@link textMessages$} to trigger lazy loading.
2458
+ * @see {@link sendText} to send a new message.
2459
+ */
1681
2460
  get textMessage(): EntityCollectionTransformed<GetConversationMessageResponse, TextMessage<Address>> | undefined;
1682
- /** Collection of call history entries for this address, with pagination support. */
2461
+ /**
2462
+ * Collection of call history entries for this address, with pagination support.
2463
+ *
2464
+ * Returns `undefined` until {@link history$} has been subscribed to (lazy-loaded).
2465
+ * Filters to `'log'` subtype messages including kind, status, start/end times.
2466
+ *
2467
+ * @see {@link history$} to trigger lazy loading.
2468
+ */
1683
2469
  get history(): EntityCollectionTransformed<GetConversationMessageResponse, AddressHistory<Address>> | undefined;
1684
2470
  /** Observable of active call states for this address. @throws {UnimplementedError} Requires presence support. */
1685
2471
  get activity$(): Observable<CallState[]>;
@@ -1692,10 +2478,19 @@ interface AttachableCall {
1692
2478
  id: string;
1693
2479
  to?: string;
1694
2480
  mediaDirections: MediaDirections;
2481
+ nodeId?: string;
1695
2482
  }
1696
2483
  interface OutboundCallProvider {
1697
2484
  createOutboundCall(destination: string | Address, options?: CallOptions): Promise<Call>;
1698
2485
  }
2486
+ interface Attachment {
2487
+ destination: string;
2488
+ mediaDirections: MediaDirections;
2489
+ audioInputDevice: MediaDeviceInfo | null;
2490
+ videoInputDevice: MediaDeviceInfo | null;
2491
+ nodeId?: string;
2492
+ attachedAt: number;
2493
+ }
1699
2494
  declare class AttachManager {
1700
2495
  private readonly storage;
1701
2496
  private readonly deviceController;
@@ -1710,8 +2505,32 @@ declare class AttachManager {
1710
2505
  attach(call: AttachableCall): Promise<void>;
1711
2506
  detach(call: AttachableCall): Promise<void>;
1712
2507
  flush(): Promise<void>;
2508
+ /**
2509
+ * Reattach to previously active calls by sending verto.invite with
2510
+ * reattaching: true.
2511
+ *
2512
+ * NOTE: This currently fails with INVALID_CALL_REFERENCE because the
2513
+ * server's jsock UUID check rejects the new connection's UUID. A
2514
+ * server-side fix is needed: when reattaching: true is explicitly set
2515
+ * in dialogParams, FreeSWITCH's attempt_reattach() should update the
2516
+ * call's jsock reference to the new connection's UUID instead of
2517
+ * rejecting. Once that fix is deployed, this will work for both
2518
+ * page reloads and WebSocket reconnects.
2519
+ *
2520
+ * Failed reattach attempts are handled gracefully — the stale call
2521
+ * reference is cleaned up from storage.
2522
+ */
1713
2523
  reattachCalls(): Promise<void>;
1714
- private buildCallOptions;
2524
+ /**
2525
+ * Build CallOptions from stored attachment data for a call being reattached.
2526
+ * Also used by the session-level verto.attach handler.
2527
+ */
2528
+ buildCallOptions(attachment: Attachment): CallOptions;
2529
+ /**
2530
+ * Consume stored attachment data for a pending call (used by session-level
2531
+ * verto.attach handler as a future path when server supports it).
2532
+ */
2533
+ consumePendingAttachment(_callId: string): CallOptions | undefined;
1715
2534
  private detachExpired;
1716
2535
  }
1717
2536
  //#endregion
@@ -1720,22 +2539,6 @@ declare class TransportManager extends Destroyable {
1720
2539
  private readonly storage;
1721
2540
  private readonly protocolKey;
1722
2541
  private readonly onError?;
1723
- /**
1724
- * Normalise a server event timestamp to epoch seconds.
1725
- *
1726
- * The server uses two formats:
1727
- * - `webrtc.message`: float epoch seconds (e.g. 1774372099.022817)
1728
- * - all other events: int epoch microseconds (e.g. 1774372099925857)
1729
- *
1730
- * Values above 1e12 are treated as microseconds and divided by 1e6.
1731
- */
1732
- private static toEpochSeconds;
1733
- /**
1734
- * Extract the event timestamp from a signalwire.event message.
1735
- * Returns `null` for messages that have no timestamp
1736
- * (e.g. signalwire.authorization.state, RPC responses).
1737
- */
1738
- private static extractEventTimestamp;
1739
2542
  private initialized$;
1740
2543
  protocol$: rxjs0.ReplaySubject<string | undefined>;
1741
2544
  private isConnecting;
@@ -1743,29 +2546,21 @@ declare class TransportManager extends Destroyable {
1743
2546
  private ackEvent;
1744
2547
  private replySignalwirePing;
1745
2548
  /**
1746
- * Filter that drops events whose timestamp predates the current session.
2549
+ * Filter that drops events from a previous session after reconnect.
1747
2550
  *
1748
- * On each new connection the session epoch is reset (see `resetSessionEpoch`).
1749
- * The first timestamped event after reset establishes the epoch.
1750
- * Subsequent events with timestamps older than the epoch are discarded —
1751
- * this guards against stale events replayed by the server after a reconnect.
1752
- *
1753
- * Events without a timestamp (e.g. signalwire.authorization.state) and
1754
- * non-event messages (RPC responses) always pass through.
2551
+ * Compares the event's `event_channel` against the current protocol.
2552
+ * Events whose channel doesn't contain the current protocol are from
2553
+ * a stale session and are discarded. Events without an event_channel
2554
+ * (auth state events, RPC responses) always pass through.
1755
2555
  */
1756
2556
  private discardStaleEvents;
1757
- private _sessionEpoch;
2557
+ private _currentProtocol;
1758
2558
  private _outgoingMessages$;
1759
2559
  private _webSocketConnections;
1760
2560
  private _jsonRPCMessage$;
1761
2561
  private _jsonRPCResponse$;
1762
2562
  private _incomingEvent$;
1763
2563
  constructor(storage: StorageManager, protocolKey: string, webSocketConstructor: WebSocketAdapter | NodeSocketAdapter, relayHost: string, onError?: ((error: Error) => void) | undefined);
1764
- /**
1765
- * Reset the session epoch. Call this before each signalwire.connect
1766
- * so that the first event after authentication establishes the new baseline.
1767
- */
1768
- resetSessionEpoch(): void;
1769
2564
  setProtocol(protocol: string | undefined): Promise<void>;
1770
2565
  get incomingEvent$(): Observable<JSONRPCRequest | JSONRPCResponse>;
1771
2566
  get connectionStatus$(): Observable<string>;
@@ -1780,6 +2575,101 @@ declare class TransportManager extends Destroyable {
1780
2575
  private _init;
1781
2576
  }
1782
2577
  //#endregion
2578
+ //#region src/controllers/CryptoController.d.ts
2579
+ /**
2580
+ * Controls DPoP (Demonstrating Proof-of-Possession) cryptographic operations.
2581
+ *
2582
+ * Generates an RSA-2048 key pair where the private key is non-extractable,
2583
+ * computes the JWK Thumbprint (RFC 7638) as the fingerprint, and creates
2584
+ * signed DPoP proof JWTs for both HTTP API requests and WebSocket RPC calls.
2585
+ *
2586
+ * The key pair is persisted in IndexedDB so the same fingerprint survives
2587
+ * page reloads. This keeps the Client Bound SAT and stored authorization_state
2588
+ * valid across reloads without needing to re-authenticate.
2589
+ *
2590
+ * @example
2591
+ * ```typescript
2592
+ * const crypto = new CryptoController();
2593
+ * await crypto.init();
2594
+ *
2595
+ * // Get fingerprint for SAT issuance
2596
+ * const fingerprint = crypto.fingerprint;
2597
+ *
2598
+ * // Create proof for HTTP endpoint
2599
+ * const httpProof = await crypto.createHttpProof({
2600
+ * method: 'POST',
2601
+ * uri: '/api/fabric/subscriber/devices/token'
2602
+ * });
2603
+ *
2604
+ * // Create proof for RPC call
2605
+ * const rpcProof = await crypto.createRpcProof({
2606
+ * method: 'signalwire.connect'
2607
+ * });
2608
+ * ```
2609
+ */
2610
+ declare class CryptoController {
2611
+ private _keyPair;
2612
+ private _publicJwk;
2613
+ private _fingerprint;
2614
+ private _initialized;
2615
+ /**
2616
+ * Initializes the DPoP key pair. Loads an existing key from IndexedDB
2617
+ * if available, otherwise generates a new one and persists it.
2618
+ *
2619
+ * The private key is non-extractable — IndexedDB stores the CryptoKey
2620
+ * handle via the structured clone algorithm without exposing key material.
2621
+ *
2622
+ * @returns The JWK Thumbprint (fingerprint) for the key.
2623
+ */
2624
+ init(): Promise<string>;
2625
+ /**
2626
+ * The JWK Thumbprint (RFC 7638) of the public key.
2627
+ * Used as the `fingerprint` parameter when requesting scoped SATs.
2628
+ *
2629
+ * @throws {DPoPInitError} If {@link init} has not been called.
2630
+ */
2631
+ get fingerprint(): string;
2632
+ /**
2633
+ * Whether the controller has been initialized with a key pair.
2634
+ */
2635
+ get initialized(): boolean;
2636
+ /**
2637
+ * Creates a DPoP proof JWT for an HTTP API request.
2638
+ *
2639
+ * Used for Prime API endpoints like `/api/fabric/subscriber/devices/token`
2640
+ * and `/api/fabric/subscriber/devices/refresh`.
2641
+ *
2642
+ * @param params - HTTP method and URI for the proof.
2643
+ * @returns Signed DPoP proof JWT string.
2644
+ */
2645
+ createHttpProof(params: DPoPHttpProofParams): Promise<string>;
2646
+ /**
2647
+ * Creates a DPoP proof JWT for a WebSocket RPC call.
2648
+ *
2649
+ * Used for switchblade RPC methods like `signalwire.connect` and
2650
+ * `signalwire.reauthenticate`.
2651
+ *
2652
+ * @param params - RPC method name for the proof.
2653
+ * @returns Signed DPoP proof JWT string.
2654
+ */
2655
+ createRpcProof(params: DPoPRpcProofParams): Promise<string>;
2656
+ /**
2657
+ * Releases the key pair references and removes the persisted key from IndexedDB.
2658
+ * After calling destroy, the controller must be re-initialized to be used again.
2659
+ */
2660
+ destroy(): void;
2661
+ private get publicJwk();
2662
+ private get privateKey();
2663
+ private signProof;
2664
+ }
2665
+ //#endregion
2666
+ //#region src/controllers/NetworkMonitor.d.ts
2667
+ interface NetworkChangeEvent {
2668
+ type: 'online' | 'offline' | 'connection_change';
2669
+ timestamp: number;
2670
+ networkType?: string;
2671
+ }
2672
+ //#endregion
1783
2673
  //#region src/core/entities/Directory.d.ts
1784
2674
  /**
1785
2675
  * Directory interface for managing addresses
@@ -1853,6 +2743,12 @@ interface ClientSession {
1853
2743
  * Used by VertoManager to configure RTCPeerConnection
1854
2744
  */
1855
2745
  readonly iceServers: RTCIceServer[] | undefined;
2746
+ /**
2747
+ * Emits true when the session is authenticated, false when not.
2748
+ * Used by Call to detect WebSocket reconnections (skip(1) + filter(true)
2749
+ * indicates a re-authentication after the initial connect).
2750
+ */
2751
+ readonly authenticated$: Observable<boolean>;
1856
2752
  }
1857
2753
  //#endregion
1858
2754
  //#region src/interfaces/SessionState.d.ts
@@ -1886,15 +2782,31 @@ interface SessionState extends ClientSession {
1886
2782
  * and `false` after disconnect.
1887
2783
  */
1888
2784
  readonly authenticated$: Observable<boolean>;
2785
+ /**
2786
+ * Current authentication state.
2787
+ * Returns `true` if the session is currently authenticated.
2788
+ */
2789
+ readonly authenticated: boolean;
1889
2790
  }
1890
2791
  //#endregion
1891
2792
  //#region src/managers/ClientSessionManager.d.ts
2793
+ /**
2794
+ * Discriminated union for session authentication state.
2795
+ * clientBound is tracked separately via _wasClientBound (sticky flag)
2796
+ * to avoid dual sources of truth.
2797
+ */
2798
+ type SessionAuthState = {
2799
+ kind: 'unauthenticated';
2800
+ } | {
2801
+ kind: 'authenticated';
2802
+ };
1892
2803
  declare class ClientSessionManager extends Destroyable implements SessionState {
1893
- private credential;
2804
+ private readonly getCredential;
1894
2805
  private readonly transport;
1895
2806
  private readonly storage;
1896
2807
  private readonly authorizationStateKey;
1897
2808
  private readonly attachManager;
2809
+ private readonly dpopManager?;
1898
2810
  private callFactory;
1899
2811
  private callCreateTimeout;
1900
2812
  private readonly agent;
@@ -1902,14 +2814,22 @@ declare class ClientSessionManager extends Destroyable implements SessionState {
1902
2814
  initialized$: Observable<boolean>;
1903
2815
  private authorizationState$;
1904
2816
  private connectVersion;
2817
+ /**
2818
+ * Optional hook called before a fresh connect on reconnect.
2819
+ * Used by SignalWire to refresh expired credentials before re-authenticating.
2820
+ * @internal
2821
+ */
2822
+ onBeforeReconnect?: () => Promise<void>;
1905
2823
  private _authorization$;
1906
2824
  private _errors$;
1907
2825
  private _directory?;
1908
- private _authenticated$;
2826
+ private _authState$;
2827
+ /** Sticky flag — once true, stays true for the session lifetime. */
2828
+ private _wasClientBound;
1909
2829
  private _subscriberInfo$;
1910
2830
  private _calls$;
1911
2831
  private _iceServers$;
1912
- constructor(credential: SDKCredential, transport: TransportManager, storage: StorageManager, authorizationStateKey: string, deviceController: DeviceController, attachManager: AttachManager, webRTCApiProvider: WebRTCApiProvider);
2832
+ constructor(getCredential: () => SDKCredential, transport: TransportManager, storage: StorageManager, authorizationStateKey: string, deviceController: DeviceController, attachManager: AttachManager, webRTCApiProvider: WebRTCApiProvider, dpopManager?: CryptoController | undefined, networkChange$?: Observable<NetworkChangeEvent>);
1913
2833
  get incomingCalls$(): Observable<Call[]>;
1914
2834
  get incomingCalls(): Call[];
1915
2835
  get subscriberInfo$(): Observable<Address | null>;
@@ -1922,6 +2842,15 @@ declare class ClientSessionManager extends Destroyable implements SessionState {
1922
2842
  get errors$(): Observable<Error>;
1923
2843
  get authenticated$(): Observable<boolean>;
1924
2844
  get authenticated(): boolean;
2845
+ /**
2846
+ * Whether this session is client-bound (using a Client Bound SAT).
2847
+ * When client-bound, DPoP proof creation failures are treated as
2848
+ * authentication errors rather than silently degraded.
2849
+ * @internal
2850
+ */
2851
+ get clientBound(): boolean;
2852
+ /** @internal Current auth state for debugging/testing. */
2853
+ get authState(): SessionAuthState;
1925
2854
  /**
1926
2855
  * Set the directory instance
1927
2856
  * Called by SignalWire after directory is created
@@ -2010,6 +2939,16 @@ declare class ClientSessionManager extends Destroyable implements SessionState {
2010
2939
  params: CallConnectPayload;
2011
2940
  }, "event_channel"> & {
2012
2941
  event_channel: string;
2942
+ }) | (Omit<{
2943
+ event_type: "room.updated";
2944
+ event_channel: EventChannel;
2945
+ timestamp: number;
2946
+ project_id?: string;
2947
+ node_id?: string;
2948
+ is_author?: boolean;
2949
+ params: RoomUpdatedPayload;
2950
+ }, "event_channel"> & {
2951
+ event_channel: string;
2013
2952
  }) | Omit<{
2014
2953
  event_type: "member.updated";
2015
2954
  event_channel: EventChannel;
@@ -2076,6 +3015,7 @@ declare class ClientSessionManager extends Destroyable implements SessionState {
2076
3015
  is_author: boolean;
2077
3016
  })>;
2078
3017
  private get vertoInvite$();
3018
+ private get vertoAttach$();
2079
3019
  private get contexts();
2080
3020
  private get eventing();
2081
3021
  private get topics();
@@ -2084,10 +3024,22 @@ declare class ClientSessionManager extends Destroyable implements SessionState {
2084
3024
  private handleAuthenticationError;
2085
3025
  cleanupStoredConnectionParams(): Promise<void>;
2086
3026
  protected updateAuthState(authorization_state: string): Promise<void>;
2087
- reauthenticate(token: string): Promise<void>;
3027
+ reauthenticate(token: string, dpopToken?: string, options?: {
3028
+ clientBound?: boolean;
3029
+ }): Promise<void>;
2088
3030
  private authenticate;
2089
3031
  disconnect(): Promise<void>;
2090
3032
  private createInboundCall;
3033
+ /**
3034
+ * Handle a server-pushed verto.attach event at the session level.
3035
+ *
3036
+ * On page reload the server detects the reconnected session and pushes
3037
+ * verto.attach for any active calls. If a call object already exists
3038
+ * (network blip, no reload), the per-call handler in VertoManager deals
3039
+ * with it. This method only creates a new call object when no existing
3040
+ * one matches the callID.
3041
+ */
3042
+ private handleVertoAttach;
2091
3043
  createOutboundCall(destination: string | Address, options?: CallOptions): Promise<Call>;
2092
3044
  private createCall;
2093
3045
  destroy(): void;
@@ -2172,6 +3124,16 @@ declare class ClientSessionWrapper implements SessionState {
2172
3124
  params: CallConnectPayload;
2173
3125
  }, "event_channel"> & {
2174
3126
  event_channel: string;
3127
+ }) | (Omit<{
3128
+ event_type: "room.updated";
3129
+ event_channel: EventChannel;
3130
+ timestamp: number;
3131
+ project_id?: string;
3132
+ node_id?: string;
3133
+ is_author?: boolean;
3134
+ params: RoomUpdatedPayload;
3135
+ }, "event_channel"> & {
3136
+ event_channel: string;
2175
3137
  }) | Omit<{
2176
3138
  event_type: "member.updated";
2177
3139
  event_channel: EventChannel;
@@ -2245,6 +3207,35 @@ declare class ClientSessionWrapper implements SessionState {
2245
3207
  get calls(): Call[];
2246
3208
  }
2247
3209
  //#endregion
3210
+ //#region src/utils/logger.d.ts
3211
+ /** Log level names supported by the SDK. */
3212
+ type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent';
3213
+ /**
3214
+ * Logger interface that consumers can implement to replace the built-in logger.
3215
+ * All methods accept variadic arguments matching the browser console API.
3216
+ */
3217
+ interface SDKLogger {
3218
+ error(...args: unknown[]): void;
3219
+ warn(...args: unknown[]): void;
3220
+ info(...args: unknown[]): void;
3221
+ debug(...args: unknown[]): void;
3222
+ trace(...args: unknown[]): void;
3223
+ }
3224
+ /** Debug options that control verbose SDK logging. */
3225
+ interface DebugOptions {
3226
+ /** Log all WebSocket send/recv traffic to the console. */
3227
+ logWsTraffic?: boolean;
3228
+ }
3229
+ /** Replace the built-in logger with a custom implementation. Pass `null` to restore defaults. */
3230
+ declare const setLogger: (logger: SDKLogger | null) => void;
3231
+ /** Configure debug options (e.g., `{ logWsTraffic: true }`). */
3232
+ declare const setDebugOptions: (options: DebugOptions | null) => void;
3233
+ /**
3234
+ * Set the log level for the built-in logger.
3235
+ * Has no effect when a custom logger is set via `setLogger()`.
3236
+ */
3237
+ declare const setLogLevel: (level: LogLevel) => void;
3238
+ //#endregion
2248
3239
  //#region src/clients/SignalWire.d.ts
2249
3240
  /** Options for constructing a {@link SignalWire}. */
2250
3241
  interface SignalWireOptions {
@@ -2258,15 +3249,56 @@ interface SignalWireOptions {
2258
3249
  reconnectAttachedCalls?: boolean;
2259
3250
  /** Whether to save preferences. */
2260
3251
  savePreferences?: boolean;
3252
+ /**
3253
+ * Persist the session across page reloads.
3254
+ *
3255
+ * When `true`, credential, authorization state, and protocol are stored in
3256
+ * `localStorage` (survives reload). The DPoP key pair is persisted in
3257
+ * IndexedDB. On reload, the SDK restores the session from cache
3258
+ * without calling `credentialProvider.authenticate()`.
3259
+ *
3260
+ * When `false` (default), session data lives in `sessionStorage` and is
3261
+ * lost on reload.
3262
+ *
3263
+ * Call {@link SignalWire.destroy | destroy()} to clear all persisted state
3264
+ * (explicit logout).
3265
+ */
3266
+ persistSession?: boolean;
2261
3267
  /** Custom storage implementation for persistence. */
2262
3268
  storageImplementation?: Storage;
2263
3269
  /** Custom WebSocket constructor */
2264
3270
  webSocketConstructor?: WebSocketAdapter | NodeSocketAdapter;
2265
3271
  /** Custom WebRTC API provider */
2266
3272
  webRTCApiProvider?: WebRTCApiProvider;
3273
+ /**
3274
+ * Custom logger implementation. Must implement the {@link SDKLogger} interface.
3275
+ * Pass `null` to restore the built-in logger.
3276
+ *
3277
+ * **Note:** Logger configuration is global — setting it on one instance affects all instances.
3278
+ */
3279
+ logger?: SDKLogger | null;
3280
+ /**
3281
+ * Log level for the built-in logger.
3282
+ * Default: `'warn'`. Set to `'debug'` for verbose SDK output.
3283
+ * Has no effect when a custom `logger` is provided.
3284
+ *
3285
+ * **Note:** Logger configuration is global — setting it on one instance affects all instances.
3286
+ */
3287
+ logLevel?: LogLevel;
3288
+ /** Debug options for verbose SDK diagnostics (e.g., `{ logWsTraffic: true }`). */
3289
+ debug?: DebugOptions;
2267
3290
  }
2268
3291
  /** Options for {@link SignalWire.dial}. Extends {@link MediaOptions} with dial-specific settings. */
2269
- interface DialOptions extends MediaOptions {}
3292
+ interface DialOptions extends MediaOptions {
3293
+ /** Preferred video codecs for this call (overrides global preferences). */
3294
+ preferredVideoCodecs?: string[];
3295
+ /** Preferred audio codecs for this call (overrides global preferences). */
3296
+ preferredAudioCodecs?: string[];
3297
+ /** Enable stereo Opus for this call (overrides global preferences). */
3298
+ stereo?: boolean;
3299
+ /** Optional node ID for routing the call */
3300
+ nodeId?: string;
3301
+ }
2270
3302
  /**
2271
3303
  * Main entry point for the SignalWire Browser SDK.
2272
3304
  *
@@ -2294,9 +3326,43 @@ declare class SignalWire extends Destroyable implements DeviceController {
2294
3326
  private _errors$;
2295
3327
  private _options;
2296
3328
  private _refreshTimerId?;
3329
+ private _dpopManager?;
3330
+ private _deviceTokenManager?;
3331
+ private _credentialProvider?;
2297
3332
  private _deps;
2298
- constructor(credentialProvider: CredentialProvider, options?: SignalWireOptions);
3333
+ private _networkMonitor?;
3334
+ private _visibilityController?;
3335
+ private _diagnosticsCollector?;
3336
+ private _platformCapabilities?;
3337
+ /**
3338
+ * Creates a new SignalWire client and begins connecting.
3339
+ *
3340
+ * @param credentialProvider - Provider that supplies authentication credentials.
3341
+ * @param options - Configuration options (connection, device monitoring, preferences).
3342
+ */
3343
+ constructor(credentialProvider: CredentialProvider | undefined, options?: SignalWireOptions);
3344
+ /**
3345
+ * Initializes DPoP if not already set up. Returns the fingerprint on success.
3346
+ */
3347
+ private initDPoP;
3348
+ /**
3349
+ * Resolves credentials using cache-first strategy when persistSession is enabled.
3350
+ *
3351
+ * 1. If persistSession → check localStorage for cached credential
3352
+ * 2. If cached and not expired → use it (skip provider.authenticate())
3353
+ * 3. If no cache or expired → call provider.authenticate()
3354
+ * 4. If no provider AND no cache → throw
3355
+ */
3356
+ private resolveCredentials;
2299
3357
  private validateCredentials;
3358
+ /**
3359
+ * Schedules credential refresh with exponential backoff retry on failure.
3360
+ * On success, resets attempt counter and schedules the next refresh.
3361
+ * After exhausting retries, emits TokenRefreshError and disconnects.
3362
+ */
3363
+ private scheduleCredentialRefresh;
3364
+ /** Persist credential to localStorage when persistSession is enabled. */
3365
+ private persistCredential;
2300
3366
  private init;
2301
3367
  private handleAttachments;
2302
3368
  /**
@@ -2309,9 +3375,9 @@ declare class SignalWire extends Destroyable implements DeviceController {
2309
3375
  * unexpectedly (e.g. network change, server restart). Reconnection uses an
2310
3376
  * **exponential back-off** strategy:
2311
3377
  *
2312
- * - First retry after `reconnectDelayMin` (default **1 s**).
3378
+ * - First retry after `reconnectDelayMin` (default **0.1 s**).
2313
3379
  * - Each subsequent retry doubles the delay up to `reconnectDelayMax`
2314
- * (default **30 s**).
3380
+ * (default **3 s**).
2315
3381
  * - The delay resets to `reconnectDelayMin` once a connection succeeds.
2316
3382
  * - A per-attempt `connectionTimeout` (default **10 s**) aborts the
2317
3383
  * attempt and schedules the next retry if the server does not respond.
@@ -2381,20 +3447,89 @@ declare class SignalWire extends Destroyable implements DeviceController {
2381
3447
  get ready$(): Observable<boolean>;
2382
3448
  /** Observable stream of errors from transport, authentication, and devices. */
2383
3449
  get errors$(): Observable<Error>;
2384
- /** Disconnects the WebSocket and tears down the session. */
3450
+ /** Platform WebRTC capabilities detected at construction time. */
3451
+ get platformCapabilities(): PlatformCapabilities;
3452
+ /** Observable that emits when the SDK auto-switches a device. */
3453
+ get deviceRecovered$(): Observable<DeviceRecoveryEvent>;
3454
+ /**
3455
+ * Export a structured diagnostic bundle for support/debugging.
3456
+ * Includes connection events, call summaries, and device changes.
3457
+ */
3458
+ exportDiagnostics(): SessionDiagnostics;
3459
+ /**
3460
+ * Initialize resilience subsystems. Non-fatal: any failure is logged and
3461
+ * the SDK continues working without the failing subsystem.
3462
+ */
3463
+ private initResilienceSubsystems;
3464
+ /**
3465
+ * Disconnects the WebSocket and tears down the current session.
3466
+ *
3467
+ * The client can be reconnected by calling {@link connect} again,
3468
+ * which creates a fresh transport and session.
3469
+ */
2385
3470
  disconnect(): Promise<void>;
2386
3471
  private waitAuthentication;
2387
- /** Registers the subscriber as online to receive inbound calls and events. */
3472
+ /**
3473
+ * Registers the subscriber as online to receive inbound calls and events.
3474
+ *
3475
+ * Waits for authentication to complete before sending the registration.
3476
+ * If the initial attempt fails, reauthentication is attempted automatically.
3477
+ *
3478
+ * @throws {InvalidCredentialsError} If registration and reauthentication both fail.
3479
+ */
2388
3480
  register(): Promise<void>;
2389
- /** Unregisters the subscriber, going offline for inbound calls. */
3481
+ /**
3482
+ * Unregisters the subscriber, going offline for inbound calls.
3483
+ *
3484
+ * The WebSocket connection remains open; use {@link disconnect} to fully close it.
3485
+ */
2390
3486
  unregister(): Promise<void>;
2391
3487
  /**
2392
3488
  * Places an outbound call to the given destination.
2393
- * @param destination - Address URI string or {@link Address} instance to call.
2394
- * @param options - Media and dial options (audio/video, constraints).
3489
+ *
3490
+ * Waits for authentication before dialing. Media options are merged from
3491
+ * saved preferences, destination query parameters (e.g. `?channel=video`),
3492
+ * and the provided `options` (highest priority).
3493
+ *
3494
+ * Returns a {@link Call} in `'ringing'` state. Subscribe to {@link Call.status$}
3495
+ * to track progression through `'connected'` → `'disconnected'`.
3496
+ *
3497
+ * @param destination - Address URI string (e.g. `'/public/my-room'`) or {@link Address} instance.
3498
+ * @param options - Media and dial options (audio/video, device constraints). Overrides defaults.
2395
3499
  * @returns The created {@link Call} instance.
3500
+ * @throws {Error} If authentication is not complete or call creation fails.
3501
+ *
3502
+ * @example
3503
+ * ```ts
3504
+ * const call = await client.dial('/public/conference', {
3505
+ * audio: true,
3506
+ * video: true,
3507
+ * });
3508
+ * call.status$.subscribe(status => console.log('Call:', status));
3509
+ * ```
2396
3510
  */
2397
3511
  dial(destination: string | Address, options?: DialOptions): Promise<Call>;
3512
+ /**
3513
+ * Runs a multi-phase connectivity test against the given destination.
3514
+ *
3515
+ * The test checks:
3516
+ * 1. **Signaling** -- WebSocket connected, RTT measurement
3517
+ * 2. **Devices** -- getUserMedia succeeds with selected (or specified) devices
3518
+ * 3. **ICE/TURN** -- gathers ICE candidates to verify STUN/TURN reachability
3519
+ * 4. **Media/bandwidth** (unless `skipMediaTest`) -- dials the destination,
3520
+ * collects getStats() for `duration` seconds, computes bandwidth estimates
3521
+ *
3522
+ * @param destination - A destination to dial for the media test (e.g. `'/private/network-test'`).
3523
+ * @param options - Preflight options (duration, skipMediaTest, device overrides).
3524
+ * @returns A {@link PreflightResult} describing connectivity health.
3525
+ *
3526
+ * @example
3527
+ * ```ts
3528
+ * const result = await client.preflight('/private/network-test', { duration: 5 });
3529
+ * if (!result.ok) console.warn('Connectivity issues:', result.warnings);
3530
+ * ```
3531
+ */
3532
+ preflight(destination: string, options?: PreflightOptions): Promise<PreflightResult>;
2398
3533
  /** The underlying client session for advanced RPC operations. */
2399
3534
  get session(): ClientSessionWrapper;
2400
3535
  /** Observable list of available audio input (microphone) devices. */
@@ -2421,10 +3556,10 @@ declare class SignalWire extends Destroyable implements DeviceController {
2421
3556
  get selectedAudioOutputDevice(): MediaDeviceInfo | null;
2422
3557
  /** Currently selected video input device, or `null` if none. */
2423
3558
  get selectedVideoInputDevice(): MediaDeviceInfo | null;
2424
- /** Media track constraints for the selected audio input device. */
2425
- get selectedAudioInputDeviceConstraints(): MediaTrackConstraints;
2426
- /** Media track constraints for the selected video input device. */
2427
- get selectedVideoInputDeviceConstraints(): MediaTrackConstraints;
3559
+ /** Media track constraints for the selected audio input device. Returns `false` when disabled. */
3560
+ get selectedAudioInputDeviceConstraints(): MediaTrackConstraints | boolean;
3561
+ /** Media track constraints for the selected video input device. Returns `false` when disabled. */
3562
+ get selectedVideoInputDeviceConstraints(): MediaTrackConstraints | boolean;
2428
3563
  /** Converts a `MediaDeviceInfo` to track constraints suitable for `getUserMedia`. */
2429
3564
  deviceInfoToConstraints(deviceInfo: MediaDeviceInfo | null): MediaTrackConstraints;
2430
3565
  /** Sets the preferred audio input device. */
@@ -2437,8 +3572,60 @@ declare class SignalWire extends Destroyable implements DeviceController {
2437
3572
  enableDeviceMonitoring(): void;
2438
3573
  /** Stops monitoring for media device changes. */
2439
3574
  disableDeviceMonitoring(): void;
3575
+ /**
3576
+ * Returns the capabilities of a media device.
3577
+ * @param deviceInfo - The device to query.
3578
+ * @returns The device capabilities, or `null` if unavailable.
3579
+ */
2440
3580
  getDeviceCapabilities(deviceInfo: MediaDeviceInfo): Promise<MediaTrackCapabilities | null>;
3581
+ /**
3582
+ * Checks whether a device is still available and usable.
3583
+ * @param deviceInfo - The device to validate, or `null`.
3584
+ * @returns `true` if the device is valid and available. Returns `false` for `null`, audio output devices, or unavailable devices.
3585
+ */
2441
3586
  isValidDevice(deviceInfo: MediaDeviceInfo | null): Promise<boolean>;
3587
+ /** Injects a storage manager into the device controller for persistence. */
3588
+ setStorageManager(storageManager: StorageManager): void;
3589
+ /** Clears all device state and re-enumerates. */
3590
+ clearDeviceState(): Promise<void>;
3591
+ /** Forces a device re-enumeration. */
3592
+ enumerateDevices(): Promise<void>;
3593
+ /** Disables audio input (receive-only mode). No audio track will be acquired. */
3594
+ disableAudioInput(): void;
3595
+ /** Re-enables audio input, restoring the last selection or auto-selecting. */
3596
+ enableAudioInput(): void;
3597
+ /** Disables video input (receive-only mode). No video track will be acquired. */
3598
+ disableVideoInput(): void;
3599
+ /** Re-enables video input, restoring the last selection or auto-selecting. */
3600
+ enableVideoInput(): void;
3601
+ /** Observable that emits `true` when video input is disabled (receive-only). */
3602
+ get videoInputDisabled$(): Observable<boolean>;
3603
+ /** Observable that emits `true` when audio input is disabled (receive-only). */
3604
+ get audioInputDisabled$(): Observable<boolean>;
3605
+ /** Whether video input is currently disabled. */
3606
+ get videoInputDisabled(): boolean;
3607
+ /** Whether audio input is currently disabled. */
3608
+ get audioInputDisabled(): boolean;
3609
+ /**
3610
+ * Triggers the browser's media permission dialog and captures the user's device selections.
3611
+ *
3612
+ * @param options - Which permissions to request.
3613
+ * @param options.audio - Whether to request audio permission.
3614
+ * @param options.video - Whether to request video permission.
3615
+ * @returns The permission result with selected devices.
3616
+ */
3617
+ requestMediaPermissions(options?: {
3618
+ audio?: boolean;
3619
+ video?: boolean;
3620
+ }): Promise<PermissionResult>;
3621
+ /**
3622
+ * Clears all SDK-persisted state and resets to defaults.
3623
+ *
3624
+ * This clears device preferences, device history, authorization state,
3625
+ * attached call IDs, and all SDK storage keys, then re-enumerates devices.
3626
+ */
3627
+ resetToDefaults(): Promise<void>;
3628
+ /** Destroys the client, clearing timers and releasing all resources. */
2442
3629
  destroy(): void;
2443
3630
  }
2444
3631
  //#endregion
@@ -2495,6 +3682,12 @@ interface RTCPeerConnectionControllerOptions extends MediaOptions {
2495
3682
  iceCandidateTimeout?: number;
2496
3683
  iceGatheringTimeout?: number;
2497
3684
  webRTCApiProvider?: WebRTCApiProvider;
3685
+ /** Per-call preferred video codecs (overrides global preferences). */
3686
+ preferredVideoCodecs?: string[];
3687
+ /** Per-call preferred audio codecs (overrides global preferences). */
3688
+ preferredAudioCodecs?: string[];
3689
+ /** Per-call stereo Opus setting (overrides global preferences). */
3690
+ stereo?: boolean;
2498
3691
  }
2499
3692
  type RTCPeerConnectionControllerOptionsPartial = Partial<RTCPeerConnectionControllerOptions>;
2500
3693
  interface UpdateSDPStatusParams {
@@ -2623,6 +3816,22 @@ declare class RTCPeerConnectionController extends Destroyable {
2623
3816
  private setupEventListeners;
2624
3817
  private negotiationEnded;
2625
3818
  restarIce(): void;
3819
+ /**
3820
+ * Trigger an ICE restart through the existing negotiation pipeline.
3821
+ *
3822
+ * This creates an offer with iceRestart: true and goes through the full
3823
+ * SDP pipeline (setLocalDescription → ICE gathering → localDescription$ emission).
3824
+ * The caller should NOT send the SDP manually — the existing
3825
+ * setupLocalDescriptionHandler in VertoManager will pick up the emission
3826
+ * from localDescription$ and send it as a verto.modify.
3827
+ *
3828
+ * Unlike calling pc.createOffer/setLocalDescription directly, this method:
3829
+ * - Sets _isNegotiating$ so ICEGatheringController arms its timers
3830
+ * - Waits for ICE gathering to complete before localDescription$ emits
3831
+ * - Goes through setLocalDescriptionBefore() for any SDP munging
3832
+ */
3833
+ triggerIceRestart(relayOnly?: boolean): Promise<void>;
3834
+ private restoreIceTransportPolicy;
2626
3835
  /**
2627
3836
  * Setup track handling for remote tracks.
2628
3837
  */
@@ -2649,6 +3858,13 @@ declare class RTCPeerConnectionController extends Destroyable {
2649
3858
  */
2650
3859
  setLocalTrack(track: MediaStreamTrack): void;
2651
3860
  updateSendersConstraints(kind: 'audio' | 'video', constraints?: MediaTrackConstraints): Promise<void>;
3861
+ /**
3862
+ * Replace the current audio track with a new one using the given constraints.
3863
+ * Used for server-pushed audio constraint changes where applyConstraints
3864
+ * fails on iOS Safari. Stops the current track, acquires a new one via
3865
+ * getUserMedia, and replaces the sender track.
3866
+ */
3867
+ replaceAudioTrackWithConstraints(constraints: MediaTrackConstraints): Promise<void>;
2652
3868
  /**
2653
3869
  * Clean up resources and close the peer connection.
2654
3870
  * Completes all observables to prevent memory leaks.
@@ -2687,10 +3903,19 @@ interface WebRTCVerto extends VertoManager {
2687
3903
  unhold(): Promise<void>;
2688
3904
  destroy(): void;
2689
3905
  transfer(options: TransferOptions): Promise<void>;
3906
+ /** Request a video keyframe via verto.modify. */
3907
+ requestKeyframe?: () => void;
3908
+ /** Request an ICE restart via verto.modify with iceRestart offer. */
3909
+ requestIceRestart?: (relayOnly?: boolean) => Promise<void>;
3910
+ /** Request an ICE restart on all active peer connections (multi-leg). */
3911
+ requestIceRestartAll?: (relayOnly?: boolean) => Promise<void>;
3912
+ /** Request keyframes on all video-receiving legs (skips send-only screen share). */
3913
+ requestKeyframeAll?: () => void;
2690
3914
  }
2691
3915
  //#endregion
2692
3916
  //#region src/managers/CallEventsManager.d.ts
2693
3917
  interface WebRTCCallEventManagerOptions {}
3918
+ /** @internal */
2694
3919
  declare class CallEventsManager extends Destroyable {
2695
3920
  protected webRtcCallSession: CallManager;
2696
3921
  protected options: WebRTCCallEventManagerOptions;
@@ -2716,7 +3941,7 @@ declare class CallEventsManager extends Destroyable {
2716
3941
  get raiseHandPriority$(): Observable<boolean>;
2717
3942
  get locked$(): Observable<boolean>;
2718
3943
  get meta$(): Observable<Record<string, unknown>>;
2719
- get capabilities$(): Observable<string[]>;
3944
+ get capabilities$(): Observable<Capability[]>;
2720
3945
  get layout$(): Observable<string>;
2721
3946
  get layouts$(): Observable<string[]>;
2722
3947
  get layoutLayers$(): Observable<LayoutLayer[]>;
@@ -2729,7 +3954,7 @@ declare class CallEventsManager extends Destroyable {
2729
3954
  get meta(): Record<string, unknown>;
2730
3955
  get layout(): string | undefined;
2731
3956
  get layouts(): string[];
2732
- get capabilities(): string[];
3957
+ get capabilities(): Capability[];
2733
3958
  isSessionEvent(id: string): boolean;
2734
3959
  protected initSubscriptions(): void;
2735
3960
  private updateParticipantPositions;
@@ -2742,6 +3967,27 @@ declare class CallEventsManager extends Destroyable {
2742
3967
  destroy(): void;
2743
3968
  }
2744
3969
  //#endregion
3970
+ //#region src/managers/CallRecoveryManager.d.ts
3971
+ type RecoveryState$1 = 'idle' | 'debouncing' | 'recovering' | 'cooldown';
3972
+ interface RecoveryEvent$1 {
3973
+ action: 'keyframe_requested' | 'reinvite_started' | 'reinvite_succeeded' | 'reinvite_failed' | 'reinvite_timeout' | 'max_attempts_reached' | 'signal_reconnect' | 'full_reconnect' | 'video_disabled' | 'video_restored';
3974
+ reason: string;
3975
+ attempt?: number;
3976
+ maxAttempts?: number;
3977
+ timestamp: number;
3978
+ }
3979
+ //#endregion
3980
+ //#region src/utils/qualityScore.d.ts
3981
+ /**
3982
+ * MOS (Mean Opinion Score) quality computation based on the simplified
3983
+ * ITU-T G.107 E-model.
3984
+ *
3985
+ * Provides a single 1-5 number that applications can use for a
3986
+ * green / yellow / red quality indicator without understanding raw
3987
+ * jitter and packet-loss values.
3988
+ */
3989
+ type QualityLevel$1 = 'excellent' | 'good' | 'fair' | 'poor' | 'critical';
3990
+ //#endregion
2745
3991
  //#region src/core/entities/Call.d.ts
2746
3992
  /**
2747
3993
  * Manager instances returned by initialization callback
@@ -2769,6 +4015,10 @@ interface CallInitialization {
2769
4015
  * Device controller for media device access
2770
4016
  */
2771
4017
  deviceController: DeviceController;
4018
+ /**
4019
+ * Network change events for feeding recovery pipeline
4020
+ */
4021
+ networkChange$?: Observable<NetworkChangeEvent>;
2772
4022
  }
2773
4023
  /**
2774
4024
  * Concrete WebRTC call implementation.
@@ -2795,6 +4045,19 @@ declare class WebRTCCall extends Destroyable implements CallManager {
2795
4045
  private _answerMediaOptions?;
2796
4046
  private _holdState;
2797
4047
  private _userVariables$;
4048
+ private _statsMonitor?;
4049
+ private _recoveryManager?;
4050
+ private _networkChange$?;
4051
+ private _networkIssues$;
4052
+ private _networkMetrics$;
4053
+ private _isNetworkHealthy$;
4054
+ private _qualityScore$;
4055
+ private _qualityLevel$;
4056
+ private _recoveryState$;
4057
+ private _recoveryEvent$;
4058
+ private _bandwidthConstrained$;
4059
+ private _mediaParamsUpdated$;
4060
+ private _customSubscriptions;
2798
4061
  constructor(clientSession: ClientSession, options: CallOptions, initialization: CallInitialization, address?: Address | undefined);
2799
4062
  /** Observable stream of errors from media, signaling, and peer connection layers. */
2800
4063
  get errors$(): Observable<CallError>;
@@ -2803,6 +4066,8 @@ declare class WebRTCCall extends Destroyable implements CallManager {
2803
4066
  * Fatal errors automatically transition the call to `'failed'` and destroy it.
2804
4067
  */
2805
4068
  emitError(callError: CallError): void;
4069
+ /** Notify the recovery manager that a verto.modify signaling exchange failed. */
4070
+ notifyModifyFailed(): void;
2806
4071
  /** Whether this call is `'inbound'` or `'outbound'`. */
2807
4072
  get direction(): CallDirection;
2808
4073
  /** Observable of the address associated with this call. */
@@ -2820,22 +4085,50 @@ declare class WebRTCCall extends Destroyable implements CallManager {
2820
4085
  /** @internal Registers an additional call ID for event routing. */
2821
4086
  addCallId(callId: string): void;
2822
4087
  /** List of capabilities available in the current call. */
2823
- get capabilities(): string[];
4088
+ get capabilities(): Capability[];
2824
4089
  /** Current snapshot of all participants in the call. */
2825
4090
  get participants(): CallParticipant[];
2826
4091
  /** The local participant, or `null` if not yet joined. */
2827
4092
  get self(): CallSelfParticipant | null;
4093
+ /** Toggles the call lock state, preventing or allowing new participants from joining. */
2828
4094
  toggleLock(): Promise<void>;
4095
+ /**
4096
+ * Toggles the hold state of the call (pauses/resumes local media transmission).
4097
+ *
4098
+ * Distinct from {@link Participant.toggleMute} which mutes individual tracks.
4099
+ */
2829
4100
  toggleHold(): Promise<void>;
4101
+ /** @throws {UnimplementedError} Not yet implemented. Status tracked via {@link recording$}. */
2830
4102
  startRecording(): Promise<void>;
4103
+ /** @throws {UnimplementedError} Not yet implemented. Status tracked via {@link streaming$}. */
2831
4104
  startStreaming(): Promise<void>;
4105
+ /**
4106
+ * Replaces the call's custom metadata.
4107
+ * @param _meta - Metadata object to set.
4108
+ * @throws {UnimplementedError} Not yet implemented.
4109
+ */
2832
4110
  setMeta(_meta: Record<string, unknown>): Promise<void>;
4111
+ /**
4112
+ * Merges values into the call's custom metadata (unlike {@link setMeta} which replaces).
4113
+ * @param _meta - Metadata to merge.
4114
+ * @throws {UnimplementedError} Not yet implemented.
4115
+ */
2833
4116
  updateMeta(_meta: Record<string, unknown>): Promise<void>;
2834
4117
  /** Observable of layout layer positions for all participants. */
2835
4118
  get layoutLayers$(): Observable<LayoutLayer[]>;
2836
4119
  /** Current snapshot of layout layers. */
2837
4120
  get layoutLayers(): LayoutLayer[];
2838
- /** Executes a Verto RPC method targeting a specific participant. */
4121
+ /**
4122
+ * Executes a Verto RPC method targeting a specific participant.
4123
+ *
4124
+ * Constructs call context (node_id, call_id, member_id) and sends the RPC request.
4125
+ *
4126
+ * @param target - Target member ID string, or a {@link MemberTarget} object.
4127
+ * @param method - Verto method name (e.g. `'call.mute'`, `'call.member.remove'`).
4128
+ * @param args - Parameters for the RPC method.
4129
+ * @returns The RPC response.
4130
+ * @throws {JSONRPCError} If the RPC call returns an error.
4131
+ */
2839
4132
  executeMethod<T extends JSONRPCResponse = JSONRPCResponse>(target: string | MemberTarget, method: string, args: Record<string, unknown>): Promise<T>;
2840
4133
  private buildMethodParams;
2841
4134
  /** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
@@ -2855,7 +4148,7 @@ declare class WebRTCCall extends Destroyable implements CallManager {
2855
4148
  /** Observable of custom metadata associated with the call. */
2856
4149
  get meta$(): Observable<Record<string, unknown>>;
2857
4150
  /** Observable of the call's capability flags. */
2858
- get capabilities$(): Observable<string[]>;
4151
+ get capabilities$(): Observable<Capability[]>;
2859
4152
  /** Observable of the current layout name. */
2860
4153
  get layout$(): Observable<string>;
2861
4154
  /** Current call status. */
@@ -2890,6 +4183,49 @@ declare class WebRTCCall extends Destroyable implements CallManager {
2890
4183
  get userVariables(): Record<string, unknown>;
2891
4184
  /** Merge current custom user variables of the call. */
2892
4185
  set userVariables(variables: Record<string, unknown>);
4186
+ /** Observable of current network health issues (empty array = healthy). */
4187
+ get networkIssues$(): Observable<NetworkIssue[]>;
4188
+ /** Current snapshot of network issues. */
4189
+ get networkIssues(): NetworkIssue[];
4190
+ /** Simple boolean health indicator derived from stats monitor. */
4191
+ get isNetworkHealthy$(): Observable<boolean>;
4192
+ /** Whether the network is currently healthy. */
4193
+ get isNetworkHealthy(): boolean;
4194
+ /** Rolling history of raw network metrics (RTT, jitter, packet loss, bitrate). */
4195
+ get networkMetrics$(): Observable<NetworkMetrics[]>;
4196
+ /** Current snapshot of the metrics rolling window. */
4197
+ get networkMetrics(): NetworkMetrics[];
4198
+ /** Observable of MOS quality score (1-5) computed from stats metrics. */
4199
+ get qualityScore$(): Observable<number>;
4200
+ /** Observable of simplified quality level (excellent/good/fair/poor/critical). */
4201
+ get qualityLevel$(): Observable<QualityLevel$1>;
4202
+ /** Observable of the recovery pipeline state machine. */
4203
+ get recoveryState$(): Observable<RecoveryState$1>;
4204
+ /** Observable of recovery events (keyframe requested, ICE restart, etc.). */
4205
+ get recoveryEvent$(): Observable<RecoveryEvent$1>;
4206
+ /** Observable indicating whether the call is bandwidth-constrained. */
4207
+ get bandwidthConstrained$(): Observable<boolean>;
4208
+ /** Observable that emits when server-pushed media params are applied. */
4209
+ get mediaParamsUpdated$(): Observable<MediaParamsEvent>;
4210
+ /**
4211
+ * @internal Emit a media params update event.
4212
+ * Called by the VertoManager when server-pushed media params are applied.
4213
+ */
4214
+ emitMediaParamsUpdated(event: MediaParamsEvent): void;
4215
+ /** Request a video keyframe via RTCP PLI/FIR. */
4216
+ requestKeyframe(): void;
4217
+ /** Force an ICE restart / re-INVITE. */
4218
+ requestIceRestart(): Promise<void>;
4219
+ /**
4220
+ * @internal Initialize resilience subsystems when the call reaches 'connected'.
4221
+ * Called from within the status subscription to wire stats and recovery.
4222
+ */
4223
+ private initResilienceSubsystems;
4224
+ /**
4225
+ * @internal Stop and destroy resilience subsystems (on disconnect/destroy).
4226
+ * Clears references so they can be re-created on reconnect.
4227
+ */
4228
+ private stopResilienceSubsystems;
2893
4229
  /** @internal */
2894
4230
  createParticipant(memberId: string, selfId?: string | null): Participant | SelfParticipant;
2895
4231
  /** Observable of the current audio/video send/receive directions. */
@@ -2897,7 +4233,16 @@ declare class WebRTCCall extends Destroyable implements CallManager {
2897
4233
  /** Current audio/video send/receive directions. */
2898
4234
  get mediaDirections(): MediaDirections;
2899
4235
  protected get participantsId$(): Observable<string[]>;
2900
- /** Executes a raw JSON-RPC request on the client session. */
4236
+ /**
4237
+ * Executes a raw JSON-RPC request on the client session.
4238
+ *
4239
+ * Lower-level than {@link executeMethod} — allows full control over the RPC request structure.
4240
+ *
4241
+ * @param request - Complete JSON-RPC request object.
4242
+ * @param options - Optional RPC execution options (timeout, etc.).
4243
+ * @returns The RPC response.
4244
+ * @throws {JSONRPCError} If the RPC call returns an error response.
4245
+ */
2901
4246
  execute<T extends JSONRPCResponse = JSONRPCResponse>(request: JSONRPCRequest, options?: PendingRPCOptions): Promise<T>;
2902
4247
  /** Observable of the local participant's member ID. */
2903
4248
  get selfId$(): Observable<string | null>;
@@ -2911,9 +4256,9 @@ declare class WebRTCCall extends Destroyable implements CallManager {
2911
4256
  private get callSessionEvents$();
2912
4257
  /** Observable of call-updated events. */
2913
4258
  get callUpdated$(): Observable<CallUpdatedPayload>;
2914
- /** Observable of member-joined events. */
4259
+ /** Observable of member-joined events, emitted when a remote participant joins the call. */
2915
4260
  get memberJoined$(): Observable<MemberJoinedPayload>;
2916
- /** Observable of member-left events. */
4261
+ /** Observable of member-left events, emitted when a participant leaves the call. */
2917
4262
  get memberLeft$(): Observable<MemberLeftPayload>;
2918
4263
  /** Observable of member-updated events (mute, volume, etc.). */
2919
4264
  get memberUpdated$(): Observable<MemberUpdatedPayload>;
@@ -2927,34 +4272,117 @@ declare class WebRTCCall extends Destroyable implements CallManager {
2927
4272
  get rtcPeerConnection(): RTCPeerConnection | undefined;
2928
4273
  /** Observable of raw signaling events as plain objects. */
2929
4274
  get signalingEvent$(): Observable<Record<string, unknown>>;
2930
- /** Observable of WebRTC-specific signaling messages. */
4275
+ /**
4276
+ * Subscribe to a custom signaling event type on this call.
4277
+ *
4278
+ * Returns a cached observable that filters `callSessionEvents$` for events
4279
+ * whose `event_type` matches the given string. The observable completes
4280
+ * when the call is destroyed.
4281
+ *
4282
+ * Unlike `signalingEvent$` (which only emits known call-level event types),
4283
+ * this method also matches custom/user-defined event types.
4284
+ *
4285
+ * The SDK does not validate event type strings --- the server decides
4286
+ * whether a given type is valid.
4287
+ *
4288
+ * @param eventType - The event type to subscribe to (e.g. `'my.custom.event'`).
4289
+ * @returns An observable that emits matching signaling events.
4290
+ *
4291
+ * @example
4292
+ * ```ts
4293
+ * call.subscribe('my.custom.event').subscribe(event => {
4294
+ * console.log('Custom event:', event);
4295
+ * });
4296
+ * ```
4297
+ */
4298
+ subscribe(eventType: string): Observable<Record<string, unknown>>;
2931
4299
  get webrtcMessages$(): Observable<WebrtcMessagePayload>;
2932
- /** Observable of call-level signaling events. */
2933
- get callEvent$(): Observable<WebrtcMessagePayload | CallJoinedPayload | CallLeftPayload | CallUpdatedPayload | CallStatePayload | CallPlayPayload | CallConnectPayload | MemberUpdatedPayload | MemberJoinedPayload | MemberLeftPayload | MemberTalkingPayload | LayoutChangedPayload | ConversationMessagePayload>;
2934
- /** Observable of layout-changed signaling events. */
4300
+ get callEvent$(): Observable<WebrtcMessagePayload | CallJoinedPayload | CallLeftPayload | CallUpdatedPayload | CallStatePayload | CallPlayPayload | CallConnectPayload | RoomUpdatedPayload | MemberUpdatedPayload | MemberJoinedPayload | MemberLeftPayload | MemberTalkingPayload | LayoutChangedPayload | ConversationMessagePayload>;
2935
4301
  get layoutEvent$(): Observable<LayoutChangedPayload>;
2936
- /** Hangs up the call and releases all resources. */
4302
+ /**
4303
+ * Hangs up the call and releases all resources.
4304
+ *
4305
+ * Sends a Verto `bye` to the server, transitions status to `'disconnecting'`,
4306
+ * then destroys the call. After this, the call instance is no longer usable.
4307
+ *
4308
+ * @example
4309
+ * ```ts
4310
+ * await call.hangup();
4311
+ * ```
4312
+ */
2937
4313
  hangup(): Promise<void>;
2938
- /** Sends DTMF digits (e.g. `'1234#'`) on the call. */
4314
+ /**
4315
+ * Sends DTMF digits on the call.
4316
+ *
4317
+ * @param dtmf - The digit string to send (e.g. `'1234#'`).
4318
+ *
4319
+ * @example
4320
+ * ```ts
4321
+ * await call.sendDigits('1234#');
4322
+ * ```
4323
+ */
2939
4324
  sendDigits(dtmf: string): Promise<void>;
2940
- /** Accepts an inbound call, optionally overriding media options for the answer. */
4325
+ /** Observable of WebRTC-specific signaling messages. */
4326
+ /** Observable of call-level signaling events. */
4327
+ /** Observable of layout-changed signaling events. */
4328
+ /**
4329
+ * Accepts an inbound call, optionally overriding media options for the answer.
4330
+ *
4331
+ * @param options - Optional media constraints for the answer (audio/video).
4332
+ *
4333
+ * @example
4334
+ * ```ts
4335
+ * // Accept with defaults
4336
+ * call.answer();
4337
+ *
4338
+ * // Accept audio-only
4339
+ * call.answer({ audio: true, video: false });
4340
+ * ```
4341
+ * @see {@link reject} to decline the call instead.
4342
+ * @see {@link answered$} to observe the acceptance state.
4343
+ */
2941
4344
  answer(options?: MediaOptions): void;
2942
4345
  /** Media options provided when answering. Used internally by the VertoManager. */
2943
4346
  get answerMediaOptions(): MediaOptions | undefined;
2944
- /** Rejects an inbound call. */
4347
+ /**
4348
+ * Rejects an inbound call, preventing media negotiation.
4349
+ *
4350
+ * @see {@link answer} to accept the call instead.
4351
+ * @see {@link answered$} to observe the rejection state.
4352
+ */
2945
4353
  reject(): void;
2946
4354
  /** Observable that emits `true` when answered, `false` when rejected. */
2947
4355
  get answered$(): Observable<boolean>;
2948
4356
  /**
2949
4357
  * Sets the call layout and participant positions.
4358
+ *
2950
4359
  * @param layout - Layout name (must be one of {@link layouts}).
2951
- * @param positions - Map of member IDs to video positions.
4360
+ * @param positions - Map of member IDs to {@link VideoPosition} values.
4361
+ * @throws {InvalidParams} If the layout is not in the available {@link layouts}.
4362
+ *
4363
+ * @example
4364
+ * ```ts
4365
+ * await call.setLayout('grid-responsive', {
4366
+ * [participantId]: 'reserved-0',
4367
+ * });
4368
+ * ```
2952
4369
  */
2953
4370
  setLayout(layout: string, positions: Record<string, VideoPosition>): Promise<void>;
2954
- /** Transfers the call to other participants. */
4371
+ /**
4372
+ * Transfers the call to another destination.
4373
+ *
4374
+ * @param options - Transfer configuration including the target destination.
4375
+ * @see {@link status$} to observe the transfer progress.
4376
+ */
2955
4377
  transfer(options: TransferOptions): Promise<void>;
2956
4378
  /** Destroys the call, releasing all resources and subscriptions. */
2957
4379
  destroy(): void;
4380
+ /**
4381
+ * @internal Send a verto.subscribe message to add an event type to the
4382
+ * server's subscription list for this call. Best-effort — failures are
4383
+ * logged but don't prevent the filtered observable from being returned.
4384
+ */
4385
+ private _sendVertoSubscribe;
2958
4386
  }
2959
4387
  //#endregion
2960
4388
  //#region src/index.d.ts
@@ -2969,5 +4397,5 @@ declare const version: string;
2969
4397
  */
2970
4398
  declare const ready: boolean;
2971
4399
  //#endregion
2972
- export { Address, type AddressHistory, type Call, type CallAddress, type CallCapabilitiesState, CallCreateError, type CallError, type CallErrorKind, type CallOptions, type CallParticipant, type CallSelfParticipant, type CallState, type CallStatus, ClientPreferences, CollectionFetchError, type CredentialProvider, type DeviceController, type DialOptions, type Directory, type ExecuteMethod, InvalidCredentialsError, type JSONRPCErrorResponse, type JSONRPCRequest, type JSONRPCResponse, type JSONRPCSuccessResponse, type LayoutLayer, type MediaDirection, type MediaDirections, type MediaOptions, MediaTrackError, type MemberCapabilities, MessageParseError, type NodeSocketAdapter, type OnOffCapability, Participant, type PendingRPCOptions, type SDKCredential, SelfCapabilities, SelfParticipant, type SessionState, SignalWire, type SignalWireOptions, StaticCredentialProvider, type Storage, Subscriber, type TextMessage, type TransferOptions, UnexpectedError, VertoPongError, type VideoPosition, type WebRTCApiProvider, WebRTCCall, type WebRTCMediaDevices, type WebSocketAdapter, embeddableCall, isSelfParticipant, ready, version };
4400
+ export { Address, type AddressHistory, type AudioConstraintsEvent, type AuthenticateContext, type Call, type CallAddress, type CallCapabilitiesState, CallCreateError, type CallDiagnosticSummary, type CallDirection, type CallError, type CallErrorKind, type NetworkIssue as CallNetworkIssue, type NetworkIssue, type NetworkMetrics as CallNetworkMetrics, type NetworkMetrics, type CallOptions, type CallParticipant, type CallSelfParticipant, type CallState, type CallStatus, type Capability, ClientPreferences, CollectionFetchError, type ConstraintFallbackEvent, type CredentialProvider, DPoPInitError, type DebugOptions, type DeviceController, type DeviceRecoveryEvent, DeviceTokenError, type DiagnosticEvent, type DialOptions, type Directory, type ExecuteMethod, InvalidCredentialsError, type JSONRPCErrorResponse, type JSONRPCRequest, type JSONRPCResponse, type JSONRPCSuccessResponse, type LayoutLayer, type LogLevel, type MediaDirection, type MediaDirections, type MediaOptions, type MediaParamsEvent, MediaTrackError, type MemberCapabilities, MessageParseError, type NodeSocketAdapter, type OnOffCapability, OverconstrainedFallbackError, Participant, type PendingRPCOptions, type PermissionResult, type PlatformCapabilities, PreflightError, type PreflightOptions, type PreflightResult, type QualityLevel, RecoveryError, type RecoveryEvent, type RecoveryState, type ResilienceCallStatus, type SATClaims, type SDKCredential, type SDKLogger, type ScreenShareStatus, type SelectDeviceOptions, SelfCapabilities, SelfParticipant, type SessionDiagnostics, type SessionState, SignalWire, type SignalWireOptions, StaticCredentialProvider, type Storage, type StoredDevicePreference, Subscriber, type SubscriberPresence, type TextMessage, TokenRefreshError, type TransferOptions, UnexpectedError, VertoPongError, type VideoPosition, type WebRTCApiProvider, WebRTCCall, type WebRTCMediaDevices, type WebSocketAdapter, embeddableCall, isSelfParticipant, ready, setDebugOptions, setLogLevel, setLogger, version };
2973
4401
  //# sourceMappingURL=index.d.mts.map