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

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,78 +3,6 @@ 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. Defaults to `true` when not specified. */
61
- audio?: boolean;
62
- /** Enable video input. Defaults to `false` when not specified. */
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
79
7
  /** JSON-compatible value type for serializable data structures. */
80
8
  interface JSONSerializable {
@@ -174,6 +102,8 @@ interface Storage {
174
102
  setItem(key: string, value: string | null, scope: StorageScope): Promise<void>;
175
103
  getItem(key: string, scope: StorageScope): Promise<string | null>;
176
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>;
177
107
  }
178
108
  /**
179
109
  * Context provided by the SDK when calling {@link CredentialProvider.authenticate}.
@@ -319,6 +249,84 @@ declare class StorageManager {
319
249
  * @throws Error from underlying storage implementation
320
250
  */
321
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
+ private _change$;
266
+ destroy(): void;
267
+ protected cachedObservable<T>(key: string, factory: () => Observable<T>): Observable<T>;
268
+ /**
269
+ * Like `cachedObservable`, but defers emissions to the microtask queue
270
+ * via `observeOn(asapScheduler)`.
271
+ *
272
+ * Use ONLY for public-facing observable getters that external consumers
273
+ * subscribe to. Prevents a class of bugs where `BehaviorSubject` or
274
+ * `ReplaySubject` replays synchronously during `subscribe()`, before
275
+ * the subscription variable is assigned in the caller's scope.
276
+ *
277
+ * Do NOT use for observables consumed internally by the SDK — internal
278
+ * code using `subscribeTo()`, `firstValueFrom()`, or `withLatestFrom()`
279
+ * depends on synchronous emission delivery.
280
+ */
281
+ protected publicCachedObservable<T>(key: string, factory: () => Observable<T>): Observable<T>;
282
+ /**
283
+ * Wraps an observable so emissions are deferred to the microtask queue.
284
+ *
285
+ * Use ONLY for public-facing getters that expose a subject via
286
+ * `.asObservable()` without going through `cachedObservable`.
287
+ *
288
+ * Do NOT use for observables consumed internally by the SDK.
289
+ */
290
+ protected deferEmission<T>(observable: Observable<T>): Observable<T>;
291
+ protected subscribeTo<T>(observable: Observable<T>, observerOrNext: Partial<Observer<T>> | ((value: T) => void) | undefined): void;
292
+ protected createSubject<T>(): Subject<T>;
293
+ protected createReplaySubject<T>(bufferSize?: number, windowTime?: number): ReplaySubject<T>;
294
+ protected createBehaviorSubject<T>(initialValue: T): BehaviorSubject<T>;
295
+ get $(): Observable<this>;
296
+ /**
297
+ * Observable that emits when the instance is destroyed
298
+ */
299
+ get destroyed$(): Observable<void>;
300
+ }
301
+ //#endregion
302
+ //#region src/core/types/media.types.d.ts
303
+ /** WebRTC transceiver direction for a single media kind. */
304
+ type MediaDirection = RTCRtpTransceiverDirection;
305
+ /** Audio and video directions "inactive" | "recvonly" | "sendonly" | "sendrecv" | "stopped" */
306
+ interface MediaDirections {
307
+ /** Audio direction */
308
+ audio: MediaDirection;
309
+ /** Video direction */
310
+ video: MediaDirection;
311
+ }
312
+ /** Options controlling which media tracks to send and receive. */
313
+ interface MediaOptions {
314
+ /** Enable audio input. Defaults to `true` when not specified. */
315
+ audio?: boolean;
316
+ /** Enable video input. Defaults to `false` when not specified. */
317
+ video?: boolean;
318
+ /** Custom constraints for the audio input track. */
319
+ inputAudioDeviceConstraints?: MediaTrackConstraints;
320
+ /** Custom constraints for the video input track. */
321
+ inputVideoDeviceConstraints?: MediaTrackConstraints;
322
+ /** Pre-existing audio stream to use instead of `getUserMedia`. */
323
+ inputAudioStream?: MediaStream;
324
+ /** Pre-existing video stream to use instead of `getUserMedia`. */
325
+ inputVideoStream?: MediaStream;
326
+ /** Whether to receive remote audio. */
327
+ receiveAudio?: boolean;
328
+ /** Whether to receive remote video. */
329
+ receiveVideo?: boolean;
322
330
  }
323
331
  //#endregion
324
332
  //#region src/containers/PreferencesContainer.d.ts
@@ -398,6 +406,108 @@ declare class ClientPreferences {
398
406
  /** Custom user variables attached to calls. */
399
407
  get userVariables(): Record<string, unknown>;
400
408
  set userVariables(value: Record<string, unknown>);
409
+ /** Stats polling interval in milliseconds. */
410
+ get statsPollingInterval(): number;
411
+ set statsPollingInterval(value: number);
412
+ /** Number of baseline samples for stats monitoring. */
413
+ get statsBaselineSamples(): number;
414
+ set statsBaselineSamples(value: number);
415
+ /** Duration in ms with no inbound packets before a critical issue is emitted. */
416
+ get statsNoPacketThreshold(): number;
417
+ set statsNoPacketThreshold(value: number);
418
+ /** Multiplier for RTT spike detection relative to baseline. */
419
+ get statsRttSpikeMultiplier(): number;
420
+ set statsRttSpikeMultiplier(value: number);
421
+ /** Packet loss fraction threshold (0-1) for issue detection. */
422
+ get statsPacketLossThreshold(): number;
423
+ set statsPacketLossThreshold(value: number);
424
+ /** Multiplier for jitter spike detection relative to baseline. */
425
+ get statsJitterSpikeMultiplier(): number;
426
+ set statsJitterSpikeMultiplier(value: number);
427
+ /** Number of seconds of metrics history to retain. */
428
+ get statsHistorySize(): number;
429
+ set statsHistorySize(value: number);
430
+ /** Maximum keyframe requests in a burst window. */
431
+ get keyframeMaxBurst(): number;
432
+ set keyframeMaxBurst(value: number);
433
+ /** Keyframe burst window duration in milliseconds. */
434
+ get keyframeBurstWindow(): number;
435
+ set keyframeBurstWindow(value: number);
436
+ /** Cooldown period in ms after keyframe burst limit is reached. */
437
+ get keyframeCooldown(): number;
438
+ set keyframeCooldown(value: number);
439
+ /** Minimum time in ms between re-INVITE attempts. */
440
+ get reinviteDebounceTime(): number;
441
+ set reinviteDebounceTime(value: number);
442
+ /** Maximum re-INVITE attempts per call. */
443
+ get reinviteMaxAttempts(): number;
444
+ set reinviteMaxAttempts(value: number);
445
+ /** Timeout in ms for a single re-INVITE attempt. */
446
+ get reinviteTimeout(): number;
447
+ set reinviteTimeout(value: number);
448
+ /** Recovery signal debounce window in seconds. */
449
+ get recoveryDebounceTime(): number;
450
+ set recoveryDebounceTime(seconds: number);
451
+ /** Cooldown period between recovery attempts in seconds. */
452
+ get recoveryCooldown(): number;
453
+ set recoveryCooldown(seconds: number);
454
+ /** Grace period before treating ICE 'disconnected' as failure, in seconds. */
455
+ get iceDisconnectedGracePeriod(): number;
456
+ set iceDisconnectedGracePeriod(seconds: number);
457
+ /** Timeout for a single ICE restart attempt in seconds. */
458
+ get iceRestartTimeout(): number;
459
+ set iceRestartTimeout(seconds: number);
460
+ /** Maximum recovery attempts before giving up. */
461
+ get maxRecoveryAttempts(): number;
462
+ set maxRecoveryAttempts(value: number);
463
+ /** Whether relay-only escalation is enabled as a last-resort recovery tier. */
464
+ get enableRelayFallback(): boolean;
465
+ set enableRelayFallback(value: boolean);
466
+ /** Whether browser network change detection (online/offline) is enabled. */
467
+ get enableNetworkChangeDetection(): boolean;
468
+ set enableNetworkChangeDetection(value: boolean);
469
+ /** Whether server-sent media-timeout hangups are intercepted for recovery. */
470
+ get enableServerHangupInterception(): boolean;
471
+ set enableServerHangupInterception(value: boolean);
472
+ /** Whether device selections are persisted to storage. */
473
+ get persistDeviceSelection(): boolean;
474
+ set persistDeviceSelection(value: boolean);
475
+ /** Whether device changes are auto-applied to active calls. */
476
+ get syncDevicesToActiveCalls(): boolean;
477
+ set syncDevicesToActiveCalls(value: boolean);
478
+ /** Whether to auto-mute video when the tab becomes hidden. */
479
+ get autoMuteVideoOnHidden(): boolean;
480
+ set autoMuteVideoOnHidden(value: boolean);
481
+ /** Whether to re-enumerate devices when the page becomes visible. */
482
+ get refreshDevicesOnVisible(): boolean;
483
+ set refreshDevicesOnVisible(value: boolean);
484
+ /** Whether to check peer connection health when the page becomes visible. */
485
+ get checkConnectionOnVisible(): boolean;
486
+ set checkConnectionOnVisible(value: boolean);
487
+ /** Default audio track constraints applied when no explicit constraints are provided. */
488
+ get defaultAudioConstraints(): MediaTrackConstraints | undefined;
489
+ set defaultAudioConstraints(value: MediaTrackConstraints | undefined);
490
+ /** Default video track constraints applied when video is enabled without explicit constraints. */
491
+ get defaultVideoConstraints(): MediaTrackConstraints | undefined;
492
+ set defaultVideoConstraints(value: MediaTrackConstraints | undefined);
493
+ /** Whether stereo Opus is enabled globally. */
494
+ get stereoAudio(): boolean;
495
+ set stereoAudio(value: boolean);
496
+ /** Whether automatic video degradation on low bandwidth is enabled. */
497
+ get enableAutoDegradation(): boolean;
498
+ set enableAutoDegradation(value: boolean);
499
+ /** Bitrate in kbps below which video is automatically disabled. */
500
+ get degradationBitrateThreshold(): number;
501
+ set degradationBitrateThreshold(value: number);
502
+ /** Bitrate in kbps above which video is automatically re-enabled. */
503
+ get degradationRecoveryThreshold(): number;
504
+ set degradationRecoveryThreshold(value: number);
505
+ /** Preferred video codecs in priority order. */
506
+ get preferredVideoCodecs(): string[];
507
+ set preferredVideoCodecs(value: string[]);
508
+ /** Preferred audio codecs in priority order. */
509
+ get preferredAudioCodecs(): string[];
510
+ set preferredAudioCodecs(value: string[]);
401
511
  /** Saves current preferences to storage (fire-and-forget). */
402
512
  private _saveToStorage;
403
513
  /** Loads preferences from storage and applies them to the container. */
@@ -926,6 +1036,29 @@ declare class EntityCollectionTransformed<O extends Entity = Entity, T extends E
926
1036
  destroy(): void;
927
1037
  }
928
1038
  //#endregion
1039
+ //#region src/controllers/RTCStatsMonitor.d.ts
1040
+ interface NetworkIssue {
1041
+ type: 'no_inbound_audio' | 'no_inbound_video' | 'high_rtt' | 'high_packet_loss' | 'high_jitter' | 'ice_disconnected';
1042
+ severity: 'warning' | 'critical';
1043
+ timestamp: number;
1044
+ value?: number;
1045
+ threshold?: number;
1046
+ }
1047
+ interface NetworkMetrics {
1048
+ timestamp: number;
1049
+ audio: {
1050
+ packetsReceived: number;
1051
+ packetsLost: number;
1052
+ jitter: number;
1053
+ };
1054
+ video: {
1055
+ packetsReceived: number;
1056
+ packetsLost: number;
1057
+ };
1058
+ roundTripTime: number;
1059
+ availableOutgoingBitrate?: number;
1060
+ }
1061
+ //#endregion
929
1062
  //#region src/managers/types/verto-manager.types.d.ts
930
1063
  type ScreenShareStatus = 'none' | 'starting' | 'started' | 'stopping';
931
1064
  type SignalingStatus = Extract<CallStatus, 'trying' | 'ringing' | 'connecting' | 'connected' | 'disconnected' | 'failed'>;
@@ -1002,6 +1135,34 @@ declare class DPoPInitError extends Error {
1002
1135
  originalError: unknown;
1003
1136
  constructor(originalError: unknown, message?: string);
1004
1137
  }
1138
+ /**
1139
+ * Error thrown when a recovery attempt fails.
1140
+ *
1141
+ * Carries the recovery action and attempt number for diagnostic purposes.
1142
+ */
1143
+ declare class RecoveryError extends Error {
1144
+ action: string;
1145
+ attempt: number;
1146
+ originalError?: unknown | undefined;
1147
+ constructor(action: string, attempt: number, originalError?: unknown | undefined);
1148
+ }
1149
+ /**
1150
+ * Error thrown when getUserMedia fails with OverconstrainedError
1151
+ * and all fallback levels have been exhausted.
1152
+ */
1153
+ declare class OverconstrainedFallbackError extends Error {
1154
+ deviceKind: string;
1155
+ originalError?: unknown | undefined;
1156
+ constructor(deviceKind: string, originalError?: unknown | undefined);
1157
+ }
1158
+ /**
1159
+ * Error thrown when the preflight connectivity test fails.
1160
+ */
1161
+ declare class PreflightError extends Error {
1162
+ phase: string;
1163
+ originalError?: unknown | undefined;
1164
+ constructor(phase: string, originalError?: unknown | undefined);
1165
+ }
1005
1166
  declare class DeviceTokenError extends Error {
1006
1167
  originalError?: unknown | undefined;
1007
1168
  constructor(message: string, originalError?: unknown | undefined);
@@ -1011,6 +1172,248 @@ declare class TokenRefreshError extends Error {
1011
1172
  constructor(message: string, originalError?: unknown | undefined);
1012
1173
  }
1013
1174
  //#endregion
1175
+ //#region src/core/types/resilience.types.d.ts
1176
+ /**
1177
+ * Types for SDK resilience, recovery, diagnostics, and quality monitoring.
1178
+ *
1179
+ * These types support:
1180
+ * - WebRTC stats monitoring (Section 1)
1181
+ * - Tiered recovery system (Section 2)
1182
+ * - Device recovery events (Section 5)
1183
+ * - Tab visibility handling (Section 4)
1184
+ * - Audio/video constraint management (Section 16)
1185
+ * - Network resilience & recovery pipeline (Section 19)
1186
+ * - Preflight connectivity test (Section 20)
1187
+ * - Call quality score (Section 21)
1188
+ * - Graceful degradation (Section 22)
1189
+ * - Platform capability detection (Section 24)
1190
+ * - Structured diagnostic log export (Section 26)
1191
+ */
1192
+ /** Simplified quality level for UI indicators, derived from MOS score. */
1193
+ type QualityLevel = 'excellent' | 'good' | 'fair' | 'poor' | 'critical';
1194
+ /**
1195
+ * Extended call status that includes the 'recovering' state.
1196
+ *
1197
+ * Used when the SDK is attempting to recover a call after a network
1198
+ * disruption or media failure.
1199
+ */
1200
+ type ResilienceCallStatus = 'new' | 'trying' | 'ringing' | 'connecting' | 'connected' | 'recovering' | 'disconnecting' | 'disconnected' | 'failed' | 'destroyed';
1201
+ type NetworkMetrics$1 = NetworkMetrics;
1202
+ /** Event emitted when a recovery action is taken on a call. */
1203
+ interface RecoveryEvent {
1204
+ /** The recovery action that was taken. */
1205
+ 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';
1206
+ /** Human-readable description of why recovery was triggered. */
1207
+ readonly reason: string;
1208
+ /** Current attempt number (for multi-attempt recoveries). */
1209
+ readonly attempt?: number;
1210
+ /** Maximum number of attempts allowed. */
1211
+ readonly maxAttempts?: number;
1212
+ /** Timestamp when the event occurred (epoch ms). */
1213
+ readonly timestamp: number;
1214
+ }
1215
+ /** State of the recovery pipeline state machine (Section 19.7). */
1216
+ type RecoveryState = 'idle' | 'debouncing' | 'recovering' | 'cooldown';
1217
+ /** Event emitted when the SDK auto-switches a device. */
1218
+ interface DeviceRecoveryEvent {
1219
+ /** The kind of device that was switched. */
1220
+ readonly kind: 'audioinput' | 'audiooutput' | 'videoinput';
1221
+ /** The device that was previously selected (null if none). */
1222
+ readonly previousDevice: MediaDeviceInfo | null;
1223
+ /** The device that was selected as a replacement (null if none available). */
1224
+ readonly newDevice: MediaDeviceInfo | null;
1225
+ /** The reason for the device switch. */
1226
+ readonly reason: 'device_disconnected' | 'device_reconnected' | 'session_restored' | 'fallback_to_default' | 'default_changed' | 'ambiguous_match';
1227
+ }
1228
+ /**
1229
+ * Serializable subset of MediaDeviceInfo for persistence.
1230
+ *
1231
+ * The browser's MediaDeviceInfo interface is not serializable.
1232
+ * This stores the fields needed for device recovery across sessions.
1233
+ */
1234
+ interface StoredDevicePreference {
1235
+ /** The device ID. */
1236
+ readonly deviceId: string;
1237
+ /** The human-readable label. */
1238
+ readonly label: string;
1239
+ /** The device kind. */
1240
+ readonly kind: MediaDeviceKind;
1241
+ /** The group ID (identifies the physical device). */
1242
+ readonly groupId: string;
1243
+ }
1244
+ /** Result of a media permissions request (Section 5.10). */
1245
+ interface PermissionResult {
1246
+ /** Whether audio permission was granted. */
1247
+ readonly audio: boolean;
1248
+ /** Whether video permission was granted. */
1249
+ readonly video: boolean;
1250
+ /** The audio device the user selected in the browser picker, if any. */
1251
+ readonly selectedAudioDevice?: MediaDeviceInfo;
1252
+ /** The video device the user selected in the browser picker, if any. */
1253
+ readonly selectedVideoDevice?: MediaDeviceInfo;
1254
+ }
1255
+ /** Event emitted when getUserMedia falls back to looser constraints. */
1256
+ interface ConstraintFallbackEvent {
1257
+ /** The kind of input device. */
1258
+ readonly kind: 'audioinput' | 'videoinput';
1259
+ /** The device that was originally requested. */
1260
+ readonly requestedDevice: MediaDeviceInfo | null;
1261
+ /** The device that the browser actually provided. */
1262
+ readonly actualDevice: MediaDeviceInfo | null;
1263
+ /** The constraint level that succeeded. */
1264
+ readonly fallbackLevel: 'exact' | 'preferred' | 'default';
1265
+ }
1266
+ /** Browser/platform WebRTC capability flags. */
1267
+ interface PlatformCapabilities {
1268
+ /** Whether screen sharing is supported. */
1269
+ readonly screenShare: boolean;
1270
+ /** Whether screen share can include system audio (Chrome-only). */
1271
+ readonly screenShareAudio: boolean;
1272
+ /** Whether simulcast is supported. */
1273
+ readonly simulcast: boolean;
1274
+ /** Whether insertable streams / encoded transforms are available. */
1275
+ readonly insertableStreams: boolean;
1276
+ /** Whether setSinkId (audio output selection) is supported. */
1277
+ readonly audioOutputSelection: boolean;
1278
+ /** List of supported video codecs. */
1279
+ readonly videoCodecs: readonly string[];
1280
+ /** List of supported audio codecs. */
1281
+ readonly audioCodecs: readonly string[];
1282
+ /** Whether the browser supports WebRTC at all. */
1283
+ readonly webrtc: boolean;
1284
+ /** Whether getUserMedia is available. */
1285
+ readonly getUserMedia: boolean;
1286
+ /** Whether getDisplayMedia is available. */
1287
+ readonly getDisplayMedia: boolean;
1288
+ }
1289
+ /** Options for the preflight connectivity test. */
1290
+ interface PreflightOptions {
1291
+ /** How long to run the media test in seconds (default: 10). */
1292
+ readonly duration?: number;
1293
+ /** Skip the media/bandwidth test, only test signaling + TURN + devices. */
1294
+ readonly skipMediaTest?: boolean;
1295
+ /** Test a specific audio device instead of the currently selected one. */
1296
+ readonly audioDevice?: MediaDeviceInfo;
1297
+ /** Test a specific video device instead of the currently selected one. */
1298
+ readonly videoDevice?: MediaDeviceInfo;
1299
+ }
1300
+ /** Results of a preflight connectivity test. */
1301
+ interface PreflightResult {
1302
+ /** Overall pass/fail. */
1303
+ readonly ok: boolean;
1304
+ /** Signaling server reachability. */
1305
+ readonly signaling: {
1306
+ readonly reachable: boolean;
1307
+ readonly rttMs: number;
1308
+ };
1309
+ /** ICE/TURN connectivity. */
1310
+ readonly connectivity: {
1311
+ /** 'direct' = host/srflx worked, 'relay' = only TURN relay, 'failed' = nothing. */
1312
+ readonly type: 'direct' | 'relay' | 'failed';
1313
+ /** Whether TURN servers are reachable. */
1314
+ readonly turnReachable: boolean;
1315
+ /** Whether STUN servers are reachable. */
1316
+ readonly stunReachable: boolean;
1317
+ /** RTT to media server in ms. */
1318
+ readonly rttMs: number;
1319
+ };
1320
+ /** Bandwidth estimation (null if skipMediaTest). */
1321
+ readonly bandwidth: {
1322
+ readonly uploadKbps: number;
1323
+ readonly downloadKbps: number;
1324
+ } | null;
1325
+ /** Device test results. */
1326
+ readonly devices: {
1327
+ readonly audioInput: {
1328
+ readonly working: boolean;
1329
+ readonly device: MediaDeviceInfo | null;
1330
+ };
1331
+ readonly videoInput: {
1332
+ readonly working: boolean;
1333
+ readonly device: MediaDeviceInfo | null;
1334
+ };
1335
+ readonly audioOutput: {
1336
+ readonly available: boolean;
1337
+ readonly device: MediaDeviceInfo | null;
1338
+ };
1339
+ };
1340
+ /** Human-readable warnings. */
1341
+ readonly warnings: readonly string[];
1342
+ }
1343
+ /** Event emitted when audio constraints change on a call. */
1344
+ interface AudioConstraintsEvent {
1345
+ /** The new constraints applied. */
1346
+ readonly constraints: MediaTrackConstraints;
1347
+ /** How the constraints were applied. */
1348
+ readonly method: 'applyConstraints' | 'trackReplacement';
1349
+ /** Timestamp when the event occurred (epoch ms). */
1350
+ readonly timestamp: number;
1351
+ }
1352
+ /** Event emitted when server-pushed media params are applied. */
1353
+ interface MediaParamsEvent {
1354
+ /** Audio constraints pushed by the server, if any. */
1355
+ readonly audio?: MediaTrackConstraints;
1356
+ /** Video constraints pushed by the server, if any. */
1357
+ readonly video?: MediaTrackConstraints;
1358
+ /** Timestamp when the event occurred (epoch ms). */
1359
+ readonly timestamp: number;
1360
+ }
1361
+ /** Structured diagnostic bundle for a session. */
1362
+ interface SessionDiagnostics {
1363
+ /** SDK version. */
1364
+ readonly sdkVersion: string;
1365
+ /** Browser/platform user agent string. */
1366
+ readonly userAgent: string;
1367
+ /** Platform capabilities detected at construction time. */
1368
+ readonly capabilities: PlatformCapabilities;
1369
+ /** Timeline of significant events during the session. */
1370
+ readonly events: readonly DiagnosticEvent[];
1371
+ /** Quality summary per call. */
1372
+ readonly calls: readonly CallDiagnosticSummary[];
1373
+ /** Device changes that occurred during the session. */
1374
+ readonly deviceChanges: readonly DeviceRecoveryEvent[];
1375
+ /** Current device list snapshot. */
1376
+ readonly devices: {
1377
+ readonly audioInput: readonly MediaDeviceInfo[];
1378
+ readonly audioOutput: readonly MediaDeviceInfo[];
1379
+ readonly videoInput: readonly MediaDeviceInfo[];
1380
+ };
1381
+ }
1382
+ /** A single diagnostic event in the session timeline. */
1383
+ interface DiagnosticEvent {
1384
+ /** Timestamp when the event occurred (epoch ms). */
1385
+ readonly timestamp: number;
1386
+ /** Category of the event. */
1387
+ readonly category: 'connection' | 'call' | 'device' | 'recovery' | 'error';
1388
+ /** Event description string. */
1389
+ readonly event: string;
1390
+ /** Additional details about the event. */
1391
+ readonly details?: Readonly<Record<string, unknown>>;
1392
+ }
1393
+ /** Quality summary for a single call in the diagnostic bundle. */
1394
+ interface CallDiagnosticSummary {
1395
+ /** Unique call ID. */
1396
+ readonly callId: string;
1397
+ /** Whether the call was inbound or outbound. */
1398
+ readonly direction: 'inbound' | 'outbound';
1399
+ /** The destination dialed, if outbound. */
1400
+ readonly destination?: string;
1401
+ /** Total call duration in seconds. */
1402
+ readonly duration: number;
1403
+ /** Final call status. */
1404
+ readonly status: string;
1405
+ /** Average MOS quality score over the call. */
1406
+ readonly avgQualityScore: number;
1407
+ /** Worst (minimum) MOS quality score during the call. */
1408
+ readonly minQualityScore: number;
1409
+ /** Number of recovery attempts made during the call. */
1410
+ readonly recoveryAttempts: number;
1411
+ /** ICE candidate types that were used. */
1412
+ readonly iceCandidateTypes: readonly string[];
1413
+ /** Final network metrics snapshot at call end. */
1414
+ readonly finalMetrics: NetworkMetrics$1;
1415
+ }
1416
+ //#endregion
1014
1417
  //#region src/core/RPCMessages/RPCConnect.d.ts
1015
1418
  interface Authorization {
1016
1419
  jti: string;
@@ -1192,10 +1595,10 @@ interface DeviceController {
1192
1595
  readonly audioOutputDevices: MediaDeviceInfo[];
1193
1596
  /** Current snapshot of available video input devices. */
1194
1597
  readonly videoInputDevices: MediaDeviceInfo[];
1195
- /** Media track constraints for the selected audio input device. */
1196
- readonly selectedAudioInputDeviceConstraints: MediaTrackConstraints;
1197
- /** Media track constraints for the selected video input device. */
1198
- readonly selectedVideoInputDeviceConstraints: MediaTrackConstraints;
1598
+ /** Media track constraints for the selected audio input device. Returns `false` when disabled. */
1599
+ readonly selectedAudioInputDeviceConstraints: MediaTrackConstraints | boolean;
1600
+ /** Media track constraints for the selected video input device. Returns `false` when disabled. */
1601
+ readonly selectedVideoInputDeviceConstraints: MediaTrackConstraints | boolean;
1199
1602
  /**
1200
1603
  * Converts a {@link MediaDeviceInfo} to track constraints suitable for `getUserMedia`.
1201
1604
  * @param deviceInfo - The device to convert, or `null` for default constraints.
@@ -1234,6 +1637,33 @@ interface DeviceController {
1234
1637
  isValidDevice(deviceInfo: MediaDeviceInfo | null): Promise<boolean>;
1235
1638
  /** Observable stream of errors from device enumeration and monitoring. */
1236
1639
  readonly errors$: Observable<Error>;
1640
+ /**
1641
+ * Observable that emits when the SDK auto-switches a device due to
1642
+ * disconnect, reconnect, or recovery.
1643
+ */
1644
+ readonly deviceRecovered$: Observable<DeviceRecoveryEvent>;
1645
+ /** Disables audio input (receive-only mode). No track will be acquired. */
1646
+ disableAudioInput(): void;
1647
+ /** Re-enables audio input, restoring the last selection or auto-selecting. */
1648
+ enableAudioInput(): void;
1649
+ /** Disables video input (receive-only mode). No track will be acquired. */
1650
+ disableVideoInput(): void;
1651
+ /** Re-enables video input, restoring the last selection or auto-selecting. */
1652
+ enableVideoInput(): void;
1653
+ /** Observable that emits `true` when video input is disabled (receive-only). */
1654
+ readonly videoInputDisabled$: Observable<boolean>;
1655
+ /** Observable that emits `true` when audio input is disabled (receive-only). */
1656
+ readonly audioInputDisabled$: Observable<boolean>;
1657
+ /** Whether video input is currently disabled. */
1658
+ readonly videoInputDisabled: boolean;
1659
+ /** Whether audio input is currently disabled. */
1660
+ readonly audioInputDisabled: boolean;
1661
+ /** Injects the storage manager for device persistence. */
1662
+ setStorageManager(storageManager: StorageManager): void;
1663
+ /** Clears all device state (history, selections, persisted prefs) and re-enumerates. */
1664
+ clearDeviceState(): Promise<void>;
1665
+ /** Force a device re-enumeration. */
1666
+ enumerateDevices(): Promise<void>;
1237
1667
  }
1238
1668
  //#endregion
1239
1669
  //#region src/interfaces/VertoManager.d.ts
@@ -1444,9 +1874,29 @@ declare class SelfParticipant extends Participant implements CallSelfParticipant
1444
1874
  * Contains all capability flags as both observables and values.
1445
1875
  */
1446
1876
  readonly capabilities: SelfCapabilities;
1877
+ /**
1878
+ * Studio audio mode state. When enabled, all audio processing
1879
+ * (echo cancellation, noise suppression, auto gain control) is disabled
1880
+ * to provide raw/unprocessed audio for musicians, podcasters, etc.
1881
+ */
1882
+ private _studioAudio$;
1447
1883
  /** @internal */
1448
1884
  constructor(id: string, executeMethod: ExecuteMethod, vertoManager: VertoManager, deviceController: DeviceController);
1449
1885
  destroy(): void;
1886
+ /** Observable indicating whether studio audio (raw/unprocessed audio) mode is enabled. */
1887
+ get studioAudio$(): Observable<boolean>;
1888
+ /** Whether studio audio (raw/unprocessed audio) mode is currently enabled. */
1889
+ get studioAudio(): boolean;
1890
+ /**
1891
+ * Enables studio audio mode by disabling all audio processing.
1892
+ * Sets echoCancellation, noiseSuppression, and autoGainControl to false.
1893
+ */
1894
+ enableStudioAudio(): Promise<void>;
1895
+ /**
1896
+ * Disables studio audio mode by restoring all audio processing to enabled.
1897
+ * Sets echoCancellation, noiseSuppression, and autoGainControl to true.
1898
+ */
1899
+ disableStudioAudio(): Promise<void>;
1450
1900
  /** Starts sharing the local screen. */
1451
1901
  startScreenShare(): Promise<void>;
1452
1902
  /** Observable of the current screen share status. */
@@ -1492,6 +1942,17 @@ declare class SelfParticipant extends Participant implements CallSelfParticipant
1492
1942
  setVideoInputDeviceConstraints(constraints: MediaTrackConstraints): Promise<void>;
1493
1943
  /** Selects the audio output device. Optionally saves as a preference. */
1494
1944
  selectAudioOutputDevice(device: MediaDeviceInfo, options?: SelectDeviceOptions): void;
1945
+ /**
1946
+ * Exits studio audio mode without restoring defaults.
1947
+ * Called internally before individual audio flag toggles.
1948
+ */
1949
+ private exitStudioModeIfActive;
1950
+ /** Toggles echo cancellation. Exits studio mode if active. */
1951
+ toggleEchoCancellation(): Promise<void>;
1952
+ /** Toggles automatic gain control. Exits studio mode if active. */
1953
+ toggleAudioInputAutoGain(): Promise<void>;
1954
+ /** Toggles noise suppression. Exits studio mode if active. */
1955
+ toggleNoiseSuppression(): Promise<void>;
1495
1956
  /** Mutes local audio. Falls back to local device mute if the server RPC fails. */
1496
1957
  mute(): Promise<void>;
1497
1958
  /** Unmutes local audio. Falls back to local device unmute if the server RPC fails. */
@@ -1582,6 +2043,10 @@ interface CallParticipant {
1582
2043
  interface CallSelfParticipant extends CallParticipant {
1583
2044
  readonly screenShareStatus$: Observable<string>;
1584
2045
  readonly screenShareStatus: string;
2046
+ readonly studioAudio$: Observable<boolean>;
2047
+ readonly studioAudio: boolean;
2048
+ enableStudioAudio(): Promise<void>;
2049
+ disableStudioAudio(): Promise<void>;
1585
2050
  startScreenShare(): Promise<void>;
1586
2051
  stopScreenShare(): Promise<void>;
1587
2052
  selectAudioInputDevice(device: MediaDeviceInfo): void;
@@ -1608,7 +2073,7 @@ interface CallAddress {
1608
2073
  readonly textMessages$: Observable<CallTextMessageCollection | undefined>;
1609
2074
  }
1610
2075
  /** Lifecycle status of a call. */
1611
- type CallStatus = 'new' | 'trying' | 'ringing' | 'connecting' | 'connected' | 'disconnecting' | 'disconnected' | 'failed' | 'destroyed';
2076
+ type CallStatus = 'new' | 'trying' | 'ringing' | 'connecting' | 'connected' | 'recovering' | 'disconnecting' | 'disconnected' | 'failed' | 'destroyed';
1612
2077
  /** Configuration options for creating a call. */
1613
2078
  interface CallOptions extends MediaOptions {
1614
2079
  /** Target server node ID. */
@@ -1631,6 +2096,12 @@ interface CallOptions extends MediaOptions {
1631
2096
  readonly displayDirection?: string;
1632
2097
  /** Custom user variables sent with the call invite. */
1633
2098
  readonly userVariables?: Record<string, unknown>;
2099
+ /** Preferred video codecs for this call (overrides global preferences). */
2100
+ readonly preferredVideoCodecs?: string[];
2101
+ /** Preferred audio codecs for this call (overrides global preferences). */
2102
+ readonly preferredAudioCodecs?: string[];
2103
+ /** Enable stereo Opus for this call (overrides global preferences). */
2104
+ readonly stereo?: boolean;
1634
2105
  }
1635
2106
  /** Observable state of a call (status, recording, participants, etc.). */
1636
2107
  interface CallState {
@@ -1684,6 +2155,21 @@ interface Call extends CallState {
1684
2155
  readonly address$: Observable<CallAddress | undefined>;
1685
2156
  userVariables?: Record<string, unknown>;
1686
2157
  readonly userVariables$: Observable<Record<string, unknown>>;
2158
+ readonly networkIssues$: Observable<NetworkIssue[]>;
2159
+ readonly networkIssues: NetworkIssue[];
2160
+ readonly isNetworkHealthy$: Observable<boolean>;
2161
+ readonly isNetworkHealthy: boolean;
2162
+ readonly networkMetrics$: Observable<NetworkMetrics[]>;
2163
+ readonly networkMetrics: NetworkMetrics[];
2164
+ readonly qualityScore$: Observable<number>;
2165
+ readonly qualityLevel$: Observable<QualityLevel>;
2166
+ readonly recoveryState$: Observable<RecoveryState>;
2167
+ readonly recoveryEvent$: Observable<RecoveryEvent>;
2168
+ readonly bandwidthConstrained$: Observable<boolean>;
2169
+ readonly mediaParamsUpdated$: Observable<MediaParamsEvent>;
2170
+ requestKeyframe(): void;
2171
+ requestIceRestart(): Promise<void>;
2172
+ subscribe(eventType: string): Observable<Record<string, unknown>>;
1687
2173
  hangup(): Promise<void>;
1688
2174
  toggleLock(): Promise<void>;
1689
2175
  toggleHold(): Promise<void>;
@@ -1958,10 +2444,19 @@ interface AttachableCall {
1958
2444
  id: string;
1959
2445
  to?: string;
1960
2446
  mediaDirections: MediaDirections;
2447
+ nodeId?: string | null;
1961
2448
  }
1962
2449
  interface OutboundCallProvider {
1963
2450
  createOutboundCall(destination: string | Address, options?: CallOptions): Promise<Call>;
1964
2451
  }
2452
+ interface Attachment {
2453
+ destination: string;
2454
+ mediaDirections: MediaDirections;
2455
+ audioInputDevice: MediaDeviceInfo | null;
2456
+ videoInputDevice: MediaDeviceInfo | null;
2457
+ nodeId?: string | null;
2458
+ attachedAt: number;
2459
+ }
1965
2460
  declare class AttachManager {
1966
2461
  private readonly storage;
1967
2462
  private readonly deviceController;
@@ -1976,8 +2471,32 @@ declare class AttachManager {
1976
2471
  attach(call: AttachableCall): Promise<void>;
1977
2472
  detach(call: AttachableCall): Promise<void>;
1978
2473
  flush(): Promise<void>;
2474
+ /**
2475
+ * Reattach to previously active calls by sending verto.invite with
2476
+ * reattaching: true.
2477
+ *
2478
+ * NOTE: This currently fails with INVALID_CALL_REFERENCE because the
2479
+ * server's jsock UUID check rejects the new connection's UUID. A
2480
+ * server-side fix is needed: when reattaching: true is explicitly set
2481
+ * in dialogParams, FreeSWITCH's attempt_reattach() should update the
2482
+ * call's jsock reference to the new connection's UUID instead of
2483
+ * rejecting. Once that fix is deployed, this will work for both
2484
+ * page reloads and WebSocket reconnects.
2485
+ *
2486
+ * Failed reattach attempts are handled gracefully — the stale call
2487
+ * reference is cleaned up from storage.
2488
+ */
1979
2489
  reattachCalls(): Promise<void>;
1980
- private buildCallOptions;
2490
+ /**
2491
+ * Build CallOptions from stored attachment data for a call being reattached.
2492
+ * Also used by the session-level verto.attach handler.
2493
+ */
2494
+ buildCallOptions(attachment: Attachment): CallOptions;
2495
+ /**
2496
+ * Consume stored attachment data for a pending call (used by session-level
2497
+ * verto.attach handler as a future path when server supports it).
2498
+ */
2499
+ consumePendingAttachment(_callId: string): CallOptions | undefined;
1981
2500
  private detachExpired;
1982
2501
  }
1983
2502
  //#endregion
@@ -1986,22 +2505,6 @@ declare class TransportManager extends Destroyable {
1986
2505
  private readonly storage;
1987
2506
  private readonly protocolKey;
1988
2507
  private readonly onError?;
1989
- /**
1990
- * Normalise a server event timestamp to epoch seconds.
1991
- *
1992
- * The server uses two formats:
1993
- * - `webrtc.message`: float epoch seconds (e.g. 1774372099.022817)
1994
- * - all other events: int epoch microseconds (e.g. 1774372099925857)
1995
- *
1996
- * Values above 1e12 are treated as microseconds and divided by 1e6.
1997
- */
1998
- private static toEpochSeconds;
1999
- /**
2000
- * Extract the event timestamp from a signalwire.event message.
2001
- * Returns `null` for messages that have no timestamp
2002
- * (e.g. signalwire.authorization.state, RPC responses).
2003
- */
2004
- private static extractEventTimestamp;
2005
2508
  private initialized$;
2006
2509
  protocol$: rxjs0.ReplaySubject<string | undefined>;
2007
2510
  private isConnecting;
@@ -2009,29 +2512,21 @@ declare class TransportManager extends Destroyable {
2009
2512
  private ackEvent;
2010
2513
  private replySignalwirePing;
2011
2514
  /**
2012
- * Filter that drops events whose timestamp predates the current session.
2515
+ * Filter that drops events from a previous session after reconnect.
2013
2516
  *
2014
- * On each new connection the session epoch is reset (see `resetSessionEpoch`).
2015
- * The first timestamped event after reset establishes the epoch.
2016
- * Subsequent events with timestamps older than the epoch are discarded —
2017
- * this guards against stale events replayed by the server after a reconnect.
2018
- *
2019
- * Events without a timestamp (e.g. signalwire.authorization.state) and
2020
- * non-event messages (RPC responses) always pass through.
2517
+ * Compares the event's `event_channel` against the current protocol.
2518
+ * Events whose channel doesn't contain the current protocol are from
2519
+ * a stale session and are discarded. Events without an event_channel
2520
+ * (auth state events, RPC responses) always pass through.
2021
2521
  */
2022
2522
  private discardStaleEvents;
2023
- private _sessionEpoch;
2523
+ private _currentProtocol;
2024
2524
  private _outgoingMessages$;
2025
2525
  private _webSocketConnections;
2026
2526
  private _jsonRPCMessage$;
2027
2527
  private _jsonRPCResponse$;
2028
2528
  private _incomingEvent$;
2029
2529
  constructor(storage: StorageManager, protocolKey: string, webSocketConstructor: WebSocketAdapter | NodeSocketAdapter, relayHost: string, onError?: ((error: Error) => void) | undefined);
2030
- /**
2031
- * Reset the session epoch. Call this before each signalwire.connect
2032
- * so that the first event after authentication establishes the new baseline.
2033
- */
2034
- resetSessionEpoch(): void;
2035
2530
  setProtocol(protocol: string | undefined): Promise<void>;
2036
2531
  get incomingEvent$(): Observable<JSONRPCRequest | JSONRPCResponse>;
2037
2532
  get connectionStatus$(): Observable<string>;
@@ -2050,10 +2545,13 @@ declare class TransportManager extends Destroyable {
2050
2545
  /**
2051
2546
  * Controls DPoP (Demonstrating Proof-of-Possession) cryptographic operations.
2052
2547
  *
2053
- * Generates an ephemeral RSA-2048 key pair where the private key is
2054
- * non-extractable, computes the JWK Thumbprint (RFC 7638) as the fingerprint,
2055
- * and creates signed DPoP proof JWTs for both HTTP API requests and
2056
- * WebSocket RPC calls.
2548
+ * Generates an RSA-2048 key pair where the private key is non-extractable,
2549
+ * computes the JWK Thumbprint (RFC 7638) as the fingerprint, and creates
2550
+ * signed DPoP proof JWTs for both HTTP API requests and WebSocket RPC calls.
2551
+ *
2552
+ * The key pair is persisted in IndexedDB so the same fingerprint survives
2553
+ * page reloads. This keeps the Client Bound SAT and stored authorization_state
2554
+ * valid across reloads without needing to re-authenticate.
2057
2555
  *
2058
2556
  * @example
2059
2557
  * ```typescript
@@ -2081,12 +2579,13 @@ declare class CryptoController {
2081
2579
  private _fingerprint;
2082
2580
  private _initialized;
2083
2581
  /**
2084
- * Generates the ephemeral RSA key pair and computes the fingerprint.
2582
+ * Initializes the DPoP key pair. Loads an existing key from IndexedDB
2583
+ * if available, otherwise generates a new one and persists it.
2085
2584
  *
2086
- * Must be called before any other method. The private key is generated
2087
- * as non-extractable to prevent accidental exposure.
2585
+ * The private key is non-extractable IndexedDB stores the CryptoKey
2586
+ * handle via the structured clone algorithm without exposing key material.
2088
2587
  *
2089
- * @returns The JWK Thumbprint (fingerprint) for the generated key.
2588
+ * @returns The JWK Thumbprint (fingerprint) for the key.
2090
2589
  */
2091
2590
  init(): Promise<string>;
2092
2591
  /**
@@ -2121,7 +2620,7 @@ declare class CryptoController {
2121
2620
  */
2122
2621
  createRpcProof(params: DPoPRpcProofParams): Promise<string>;
2123
2622
  /**
2124
- * Releases the key pair references.
2623
+ * Releases the key pair references and removes the persisted key from IndexedDB.
2125
2624
  * After calling destroy, the controller must be re-initialized to be used again.
2126
2625
  */
2127
2626
  destroy(): void;
@@ -2130,6 +2629,13 @@ declare class CryptoController {
2130
2629
  private signProof;
2131
2630
  }
2132
2631
  //#endregion
2632
+ //#region src/controllers/NetworkMonitor.d.ts
2633
+ interface NetworkChangeEvent {
2634
+ type: 'online' | 'offline' | 'connection_change';
2635
+ timestamp: number;
2636
+ networkType?: string;
2637
+ }
2638
+ //#endregion
2133
2639
  //#region src/core/entities/Directory.d.ts
2134
2640
  /**
2135
2641
  * Directory interface for managing addresses
@@ -2203,6 +2709,12 @@ interface ClientSession {
2203
2709
  * Used by VertoManager to configure RTCPeerConnection
2204
2710
  */
2205
2711
  readonly iceServers: RTCIceServer[] | undefined;
2712
+ /**
2713
+ * Emits true when the session is authenticated, false when not.
2714
+ * Used by Call to detect WebSocket reconnections (skip(1) + filter(true)
2715
+ * indicates a re-authentication after the initial connect).
2716
+ */
2717
+ readonly authenticated$: Observable<boolean>;
2206
2718
  }
2207
2719
  //#endregion
2208
2720
  //#region src/interfaces/SessionState.d.ts
@@ -2267,7 +2779,7 @@ declare class ClientSessionManager extends Destroyable implements SessionState {
2267
2779
  private _subscriberInfo$;
2268
2780
  private _calls$;
2269
2781
  private _iceServers$;
2270
- constructor(getCredential: () => SDKCredential, transport: TransportManager, storage: StorageManager, authorizationStateKey: string, deviceController: DeviceController, attachManager: AttachManager, webRTCApiProvider: WebRTCApiProvider, dpopManager?: CryptoController | undefined);
2782
+ constructor(getCredential: () => SDKCredential, transport: TransportManager, storage: StorageManager, authorizationStateKey: string, deviceController: DeviceController, attachManager: AttachManager, webRTCApiProvider: WebRTCApiProvider, dpopManager?: CryptoController | undefined, networkChange$?: Observable<NetworkChangeEvent>);
2271
2783
  get incomingCalls$(): Observable<Call[]>;
2272
2784
  get incomingCalls(): Call[];
2273
2785
  get subscriberInfo$(): Observable<Address | null>;
@@ -2451,6 +2963,7 @@ declare class ClientSessionManager extends Destroyable implements SessionState {
2451
2963
  is_author: boolean;
2452
2964
  })>;
2453
2965
  private get vertoInvite$();
2966
+ private get vertoAttach$();
2454
2967
  private get contexts();
2455
2968
  private get eventing();
2456
2969
  private get topics();
@@ -2465,6 +2978,16 @@ declare class ClientSessionManager extends Destroyable implements SessionState {
2465
2978
  private authenticate;
2466
2979
  disconnect(): Promise<void>;
2467
2980
  private createInboundCall;
2981
+ /**
2982
+ * Handle a server-pushed verto.attach event at the session level.
2983
+ *
2984
+ * On page reload the server detects the reconnected session and pushes
2985
+ * verto.attach for any active calls. If a call object already exists
2986
+ * (network blip, no reload), the per-call handler in VertoManager deals
2987
+ * with it. This method only creates a new call object when no existing
2988
+ * one matches the callID.
2989
+ */
2990
+ private handleVertoAttach;
2468
2991
  createOutboundCall(destination: string | Address, options?: CallOptions): Promise<Call>;
2469
2992
  private createCall;
2470
2993
  destroy(): void;
@@ -2645,6 +3168,21 @@ interface SignalWireOptions {
2645
3168
  reconnectAttachedCalls?: boolean;
2646
3169
  /** Whether to save preferences. */
2647
3170
  savePreferences?: boolean;
3171
+ /**
3172
+ * Persist the session across page reloads.
3173
+ *
3174
+ * When `true`, credential, authorization state, and protocol are stored in
3175
+ * `localStorage` (survives reload). The DPoP key pair is persisted in
3176
+ * IndexedDB. On reload, the SDK restores the session from cache
3177
+ * without calling `credentialProvider.authenticate()`.
3178
+ *
3179
+ * When `false` (default), session data lives in `sessionStorage` and is
3180
+ * lost on reload.
3181
+ *
3182
+ * Call {@link SignalWire.destroy | destroy()} to clear all persisted state
3183
+ * (explicit logout).
3184
+ */
3185
+ persistSession?: boolean;
2648
3186
  /** Custom storage implementation for persistence. */
2649
3187
  storageImplementation?: Storage;
2650
3188
  /** Custom WebSocket constructor */
@@ -2653,7 +3191,14 @@ interface SignalWireOptions {
2653
3191
  webRTCApiProvider?: WebRTCApiProvider;
2654
3192
  }
2655
3193
  /** Options for {@link SignalWire.dial}. Extends {@link MediaOptions} with dial-specific settings. */
2656
- interface DialOptions extends MediaOptions {}
3194
+ interface DialOptions extends MediaOptions {
3195
+ /** Preferred video codecs for this call (overrides global preferences). */
3196
+ preferredVideoCodecs?: string[];
3197
+ /** Preferred audio codecs for this call (overrides global preferences). */
3198
+ preferredAudioCodecs?: string[];
3199
+ /** Enable stereo Opus for this call (overrides global preferences). */
3200
+ stereo?: boolean;
3201
+ }
2657
3202
  /**
2658
3203
  * Main entry point for the SignalWire Browser SDK.
2659
3204
  *
@@ -2685,18 +3230,33 @@ declare class SignalWire extends Destroyable implements DeviceController {
2685
3230
  private _deviceTokenManager?;
2686
3231
  private _credentialProvider?;
2687
3232
  private _deps;
3233
+ private _networkMonitor?;
3234
+ private _visibilityController?;
3235
+ private _diagnosticsCollector?;
3236
+ private _platformCapabilities?;
2688
3237
  /**
2689
3238
  * Creates a new SignalWire client and begins connecting.
2690
3239
  *
2691
3240
  * @param credentialProvider - Provider that supplies authentication credentials.
2692
3241
  * @param options - Configuration options (connection, device monitoring, preferences).
2693
3242
  */
2694
- constructor(credentialProvider: CredentialProvider, options?: SignalWireOptions);
3243
+ constructor(credentialProvider: CredentialProvider | undefined, options?: SignalWireOptions);
2695
3244
  /**
2696
3245
  * Initializes DPoP if not already set up. Returns the fingerprint on success.
2697
3246
  */
2698
3247
  private initDPoP;
3248
+ /**
3249
+ * Resolves credentials using cache-first strategy when persistSession is enabled.
3250
+ *
3251
+ * 1. If persistSession → check localStorage for cached credential
3252
+ * 2. If cached and not expired → use it (skip provider.authenticate())
3253
+ * 3. If no cache or expired → call provider.authenticate()
3254
+ * 4. If no provider AND no cache → throw
3255
+ */
3256
+ private resolveCredentials;
2699
3257
  private validateCredentials;
3258
+ /** Persist credential to localStorage when persistSession is enabled. */
3259
+ private persistCredential;
2700
3260
  private init;
2701
3261
  private handleAttachments;
2702
3262
  /**
@@ -2781,6 +3341,20 @@ declare class SignalWire extends Destroyable implements DeviceController {
2781
3341
  get ready$(): Observable<boolean>;
2782
3342
  /** Observable stream of errors from transport, authentication, and devices. */
2783
3343
  get errors$(): Observable<Error>;
3344
+ /** Platform WebRTC capabilities detected at construction time. */
3345
+ get platformCapabilities(): PlatformCapabilities;
3346
+ /** Observable that emits when the SDK auto-switches a device. */
3347
+ get deviceRecovered$(): Observable<DeviceRecoveryEvent>;
3348
+ /**
3349
+ * Export a structured diagnostic bundle for support/debugging.
3350
+ * Includes connection events, call summaries, and device changes.
3351
+ */
3352
+ exportDiagnostics(): SessionDiagnostics;
3353
+ /**
3354
+ * Initialize resilience subsystems. Non-fatal: any failure is logged and
3355
+ * the SDK continues working without the failing subsystem.
3356
+ */
3357
+ private initResilienceSubsystems;
2784
3358
  /**
2785
3359
  * Disconnects the WebSocket and tears down the current session.
2786
3360
  *
@@ -2829,6 +3403,27 @@ declare class SignalWire extends Destroyable implements DeviceController {
2829
3403
  * ```
2830
3404
  */
2831
3405
  dial(destination: string | Address, options?: DialOptions): Promise<Call>;
3406
+ /**
3407
+ * Runs a multi-phase connectivity test against the given destination.
3408
+ *
3409
+ * The test checks:
3410
+ * 1. **Signaling** -- WebSocket connected, RTT measurement
3411
+ * 2. **Devices** -- getUserMedia succeeds with selected (or specified) devices
3412
+ * 3. **ICE/TURN** -- gathers ICE candidates to verify STUN/TURN reachability
3413
+ * 4. **Media/bandwidth** (unless `skipMediaTest`) -- dials the destination,
3414
+ * collects getStats() for `duration` seconds, computes bandwidth estimates
3415
+ *
3416
+ * @param destination - A destination to dial for the media test (e.g. `'/private/network-test'`).
3417
+ * @param options - Preflight options (duration, skipMediaTest, device overrides).
3418
+ * @returns A {@link PreflightResult} describing connectivity health.
3419
+ *
3420
+ * @example
3421
+ * ```ts
3422
+ * const result = await client.preflight('/private/network-test', { duration: 5 });
3423
+ * if (!result.ok) console.warn('Connectivity issues:', result.warnings);
3424
+ * ```
3425
+ */
3426
+ preflight(destination: string, options?: PreflightOptions): Promise<PreflightResult>;
2832
3427
  /** The underlying client session for advanced RPC operations. */
2833
3428
  get session(): ClientSessionWrapper;
2834
3429
  /** Observable list of available audio input (microphone) devices. */
@@ -2855,10 +3450,10 @@ declare class SignalWire extends Destroyable implements DeviceController {
2855
3450
  get selectedAudioOutputDevice(): MediaDeviceInfo | null;
2856
3451
  /** Currently selected video input device, or `null` if none. */
2857
3452
  get selectedVideoInputDevice(): MediaDeviceInfo | null;
2858
- /** Media track constraints for the selected audio input device. */
2859
- get selectedAudioInputDeviceConstraints(): MediaTrackConstraints;
2860
- /** Media track constraints for the selected video input device. */
2861
- get selectedVideoInputDeviceConstraints(): MediaTrackConstraints;
3453
+ /** Media track constraints for the selected audio input device. Returns `false` when disabled. */
3454
+ get selectedAudioInputDeviceConstraints(): MediaTrackConstraints | boolean;
3455
+ /** Media track constraints for the selected video input device. Returns `false` when disabled. */
3456
+ get selectedVideoInputDeviceConstraints(): MediaTrackConstraints | boolean;
2862
3457
  /** Converts a `MediaDeviceInfo` to track constraints suitable for `getUserMedia`. */
2863
3458
  deviceInfoToConstraints(deviceInfo: MediaDeviceInfo | null): MediaTrackConstraints;
2864
3459
  /** Sets the preferred audio input device. */
@@ -2883,6 +3478,45 @@ declare class SignalWire extends Destroyable implements DeviceController {
2883
3478
  * @returns `true` if the device is valid and available. Returns `false` for `null`, audio output devices, or unavailable devices.
2884
3479
  */
2885
3480
  isValidDevice(deviceInfo: MediaDeviceInfo | null): Promise<boolean>;
3481
+ /** Injects a storage manager into the device controller for persistence. */
3482
+ setStorageManager(storageManager: StorageManager): void;
3483
+ /** Clears all device state and re-enumerates. */
3484
+ clearDeviceState(): Promise<void>;
3485
+ /** Forces a device re-enumeration. */
3486
+ enumerateDevices(): Promise<void>;
3487
+ /** Disables audio input (receive-only mode). No audio track will be acquired. */
3488
+ disableAudioInput(): void;
3489
+ /** Re-enables audio input, restoring the last selection or auto-selecting. */
3490
+ enableAudioInput(): void;
3491
+ /** Disables video input (receive-only mode). No video track will be acquired. */
3492
+ disableVideoInput(): void;
3493
+ /** Re-enables video input, restoring the last selection or auto-selecting. */
3494
+ enableVideoInput(): void;
3495
+ /** Observable that emits `true` when video input is disabled (receive-only). */
3496
+ get videoInputDisabled$(): Observable<boolean>;
3497
+ /** Observable that emits `true` when audio input is disabled (receive-only). */
3498
+ get audioInputDisabled$(): Observable<boolean>;
3499
+ /** Whether video input is currently disabled. */
3500
+ get videoInputDisabled(): boolean;
3501
+ /** Whether audio input is currently disabled. */
3502
+ get audioInputDisabled(): boolean;
3503
+ /**
3504
+ * Triggers the browser's media permission dialog and captures the user's device selections.
3505
+ *
3506
+ * @param options - Which permissions to request.
3507
+ * @returns The permission result with selected devices.
3508
+ */
3509
+ requestMediaPermissions(options?: {
3510
+ audio?: boolean;
3511
+ video?: boolean;
3512
+ }): Promise<PermissionResult>;
3513
+ /**
3514
+ * Clears all SDK-persisted state and resets to defaults.
3515
+ *
3516
+ * This clears device preferences, device history, authorization state,
3517
+ * attached call IDs, and all SDK storage keys, then re-enumerates devices.
3518
+ */
3519
+ resetToDefaults(): Promise<void>;
2886
3520
  /** Destroys the client, clearing timers and releasing all resources. */
2887
3521
  destroy(): void;
2888
3522
  }
@@ -2940,6 +3574,12 @@ interface RTCPeerConnectionControllerOptions extends MediaOptions {
2940
3574
  iceCandidateTimeout?: number;
2941
3575
  iceGatheringTimeout?: number;
2942
3576
  webRTCApiProvider?: WebRTCApiProvider;
3577
+ /** Per-call preferred video codecs (overrides global preferences). */
3578
+ preferredVideoCodecs?: string[];
3579
+ /** Per-call preferred audio codecs (overrides global preferences). */
3580
+ preferredAudioCodecs?: string[];
3581
+ /** Per-call stereo Opus setting (overrides global preferences). */
3582
+ stereo?: boolean;
2943
3583
  }
2944
3584
  type RTCPeerConnectionControllerOptionsPartial = Partial<RTCPeerConnectionControllerOptions>;
2945
3585
  interface UpdateSDPStatusParams {
@@ -3068,6 +3708,22 @@ declare class RTCPeerConnectionController extends Destroyable {
3068
3708
  private setupEventListeners;
3069
3709
  private negotiationEnded;
3070
3710
  restarIce(): void;
3711
+ /**
3712
+ * Trigger an ICE restart through the existing negotiation pipeline.
3713
+ *
3714
+ * This creates an offer with iceRestart: true and goes through the full
3715
+ * SDP pipeline (setLocalDescription → ICE gathering → localDescription$ emission).
3716
+ * The caller should NOT send the SDP manually — the existing
3717
+ * setupLocalDescriptionHandler in VertoManager will pick up the emission
3718
+ * from localDescription$ and send it as a verto.modify.
3719
+ *
3720
+ * Unlike calling pc.createOffer/setLocalDescription directly, this method:
3721
+ * - Sets _isNegotiating$ so ICEGatheringController arms its timers
3722
+ * - Waits for ICE gathering to complete before localDescription$ emits
3723
+ * - Goes through setLocalDescriptionBefore() for any SDP munging
3724
+ */
3725
+ triggerIceRestart(relayOnly?: boolean): Promise<void>;
3726
+ private restoreIceTransportPolicy;
3071
3727
  /**
3072
3728
  * Setup track handling for remote tracks.
3073
3729
  */
@@ -3094,6 +3750,13 @@ declare class RTCPeerConnectionController extends Destroyable {
3094
3750
  */
3095
3751
  setLocalTrack(track: MediaStreamTrack): void;
3096
3752
  updateSendersConstraints(kind: 'audio' | 'video', constraints?: MediaTrackConstraints): Promise<void>;
3753
+ /**
3754
+ * Replace the current audio track with a new one using the given constraints.
3755
+ * Used for server-pushed audio constraint changes where applyConstraints
3756
+ * fails on iOS Safari. Stops the current track, acquires a new one via
3757
+ * getUserMedia, and replaces the sender track.
3758
+ */
3759
+ replaceAudioTrackWithConstraints(constraints: MediaTrackConstraints): Promise<void>;
3097
3760
  /**
3098
3761
  * Clean up resources and close the peer connection.
3099
3762
  * Completes all observables to prevent memory leaks.
@@ -3132,6 +3795,14 @@ interface WebRTCVerto extends VertoManager {
3132
3795
  unhold(): Promise<void>;
3133
3796
  destroy(): void;
3134
3797
  transfer(options: TransferOptions): Promise<void>;
3798
+ /** Request a video keyframe via verto.modify. */
3799
+ requestKeyframe?: () => void;
3800
+ /** Request an ICE restart via verto.modify with iceRestart offer. */
3801
+ requestIceRestart?: (relayOnly?: boolean) => Promise<void>;
3802
+ /** Request an ICE restart on all active peer connections (multi-leg). */
3803
+ requestIceRestartAll?: (relayOnly?: boolean) => Promise<void>;
3804
+ /** Request keyframes on all video-receiving legs (skips send-only screen share). */
3805
+ requestKeyframeAll?: () => void;
3135
3806
  }
3136
3807
  //#endregion
3137
3808
  //#region src/managers/CallEventsManager.d.ts
@@ -3188,6 +3859,27 @@ declare class CallEventsManager extends Destroyable {
3188
3859
  destroy(): void;
3189
3860
  }
3190
3861
  //#endregion
3862
+ //#region src/managers/CallRecoveryManager.d.ts
3863
+ type RecoveryState$1 = 'idle' | 'debouncing' | 'recovering' | 'cooldown';
3864
+ interface RecoveryEvent$1 {
3865
+ action: 'keyframe_requested' | 'reinvite_started' | 'reinvite_succeeded' | 'reinvite_failed' | 'reinvite_timeout' | 'max_attempts_reached' | 'signal_reconnect' | 'full_reconnect' | 'video_disabled' | 'video_restored';
3866
+ reason: string;
3867
+ attempt?: number;
3868
+ maxAttempts?: number;
3869
+ timestamp: number;
3870
+ }
3871
+ //#endregion
3872
+ //#region src/utils/qualityScore.d.ts
3873
+ /**
3874
+ * MOS (Mean Opinion Score) quality computation based on the simplified
3875
+ * ITU-T G.107 E-model.
3876
+ *
3877
+ * Provides a single 1-5 number that applications can use for a
3878
+ * green / yellow / red quality indicator without understanding raw
3879
+ * jitter and packet-loss values.
3880
+ */
3881
+ type QualityLevel$1 = 'excellent' | 'good' | 'fair' | 'poor' | 'critical';
3882
+ //#endregion
3191
3883
  //#region src/core/entities/Call.d.ts
3192
3884
  /**
3193
3885
  * Manager instances returned by initialization callback
@@ -3215,6 +3907,10 @@ interface CallInitialization {
3215
3907
  * Device controller for media device access
3216
3908
  */
3217
3909
  deviceController: DeviceController;
3910
+ /**
3911
+ * Network change events for feeding recovery pipeline
3912
+ */
3913
+ networkChange$?: Observable<NetworkChangeEvent>;
3218
3914
  }
3219
3915
  /**
3220
3916
  * Concrete WebRTC call implementation.
@@ -3241,6 +3937,19 @@ declare class WebRTCCall extends Destroyable implements CallManager {
3241
3937
  private _answerMediaOptions?;
3242
3938
  private _holdState;
3243
3939
  private _userVariables$;
3940
+ private _statsMonitor?;
3941
+ private _recoveryManager?;
3942
+ private _networkChange$?;
3943
+ private _networkIssues$;
3944
+ private _networkMetrics$;
3945
+ private _isNetworkHealthy$;
3946
+ private _qualityScore$;
3947
+ private _qualityLevel$;
3948
+ private _recoveryState$;
3949
+ private _recoveryEvent$;
3950
+ private _bandwidthConstrained$;
3951
+ private _mediaParamsUpdated$;
3952
+ private _customSubscriptions;
3244
3953
  constructor(clientSession: ClientSession, options: CallOptions, initialization: CallInitialization, address?: Address | undefined);
3245
3954
  /** Observable stream of errors from media, signaling, and peer connection layers. */
3246
3955
  get errors$(): Observable<CallError>;
@@ -3364,6 +4073,49 @@ declare class WebRTCCall extends Destroyable implements CallManager {
3364
4073
  get userVariables(): Record<string, unknown>;
3365
4074
  /** Merge current custom user variables of the call. */
3366
4075
  set userVariables(variables: Record<string, unknown>);
4076
+ /** Observable of current network health issues (empty array = healthy). */
4077
+ get networkIssues$(): Observable<NetworkIssue[]>;
4078
+ /** Current snapshot of network issues. */
4079
+ get networkIssues(): NetworkIssue[];
4080
+ /** Simple boolean health indicator derived from stats monitor. */
4081
+ get isNetworkHealthy$(): Observable<boolean>;
4082
+ /** Whether the network is currently healthy. */
4083
+ get isNetworkHealthy(): boolean;
4084
+ /** Rolling history of raw network metrics (RTT, jitter, packet loss, bitrate). */
4085
+ get networkMetrics$(): Observable<NetworkMetrics[]>;
4086
+ /** Current snapshot of the metrics rolling window. */
4087
+ get networkMetrics(): NetworkMetrics[];
4088
+ /** Observable of MOS quality score (1-5) computed from stats metrics. */
4089
+ get qualityScore$(): Observable<number>;
4090
+ /** Observable of simplified quality level (excellent/good/fair/poor/critical). */
4091
+ get qualityLevel$(): Observable<QualityLevel$1>;
4092
+ /** Observable of the recovery pipeline state machine. */
4093
+ get recoveryState$(): Observable<RecoveryState$1>;
4094
+ /** Observable of recovery events (keyframe requested, ICE restart, etc.). */
4095
+ get recoveryEvent$(): Observable<RecoveryEvent$1>;
4096
+ /** Observable indicating whether the call is bandwidth-constrained. */
4097
+ get bandwidthConstrained$(): Observable<boolean>;
4098
+ /** Observable that emits when server-pushed media params are applied. */
4099
+ get mediaParamsUpdated$(): Observable<MediaParamsEvent>;
4100
+ /**
4101
+ * @internal Emit a media params update event.
4102
+ * Called by the VertoManager when server-pushed media params are applied.
4103
+ */
4104
+ emitMediaParamsUpdated(event: MediaParamsEvent): void;
4105
+ /** Request a video keyframe via RTCP PLI/FIR. */
4106
+ requestKeyframe(): void;
4107
+ /** Force an ICE restart / re-INVITE. */
4108
+ requestIceRestart(): Promise<void>;
4109
+ /**
4110
+ * @internal Initialize resilience subsystems when the call reaches 'connected'.
4111
+ * Called from within the status subscription to wire stats and recovery.
4112
+ */
4113
+ private initResilienceSubsystems;
4114
+ /**
4115
+ * @internal Stop and destroy resilience subsystems (on disconnect/destroy).
4116
+ * Clears references so they can be re-created on reconnect.
4117
+ */
4118
+ private stopResilienceSubsystems;
3367
4119
  /** @internal */
3368
4120
  createParticipant(memberId: string, selfId?: string | null): Participant | SelfParticipant;
3369
4121
  /** Observable of the current audio/video send/receive directions. */
@@ -3410,11 +4162,32 @@ declare class WebRTCCall extends Destroyable implements CallManager {
3410
4162
  get rtcPeerConnection(): RTCPeerConnection | undefined;
3411
4163
  /** Observable of raw signaling events as plain objects. */
3412
4164
  get signalingEvent$(): Observable<Record<string, unknown>>;
3413
- /** Observable of WebRTC-specific signaling messages. */
4165
+ /**
4166
+ * Subscribe to a custom signaling event type on this call.
4167
+ *
4168
+ * Returns a cached observable that filters `callSessionEvents$` for events
4169
+ * whose `event_type` matches the given string. The observable completes
4170
+ * when the call is destroyed.
4171
+ *
4172
+ * Unlike `signalingEvent$` (which only emits known call-level event types),
4173
+ * this method also matches custom/user-defined event types.
4174
+ *
4175
+ * The SDK does not validate event type strings --- the server decides
4176
+ * whether a given type is valid.
4177
+ *
4178
+ * @param eventType - The event type to subscribe to (e.g. `'my.custom.event'`).
4179
+ * @returns An observable that emits matching signaling events.
4180
+ *
4181
+ * @example
4182
+ * ```ts
4183
+ * call.subscribe('my.custom.event').subscribe(event => {
4184
+ * console.log('Custom event:', event);
4185
+ * });
4186
+ * ```
4187
+ */
4188
+ subscribe(eventType: string): Observable<Record<string, unknown>>;
3414
4189
  get webrtcMessages$(): Observable<WebrtcMessagePayload>;
3415
- /** Observable of call-level signaling events. */
3416
4190
  get callEvent$(): Observable<WebrtcMessagePayload | CallJoinedPayload | CallLeftPayload | CallUpdatedPayload | CallStatePayload | CallPlayPayload | CallConnectPayload | RoomUpdatedPayload | MemberUpdatedPayload | MemberJoinedPayload | MemberLeftPayload | MemberTalkingPayload | LayoutChangedPayload | ConversationMessagePayload>;
3417
- /** Observable of layout-changed signaling events. */
3418
4191
  get layoutEvent$(): Observable<LayoutChangedPayload>;
3419
4192
  /**
3420
4193
  * Hangs up the call and releases all resources.
@@ -3439,6 +4212,9 @@ declare class WebRTCCall extends Destroyable implements CallManager {
3439
4212
  * ```
3440
4213
  */
3441
4214
  sendDigits(dtmf: string): Promise<void>;
4215
+ /** Observable of WebRTC-specific signaling messages. */
4216
+ /** Observable of call-level signaling events. */
4217
+ /** Observable of layout-changed signaling events. */
3442
4218
  /**
3443
4219
  * Accepts an inbound call, optionally overriding media options for the answer.
3444
4220
  *
@@ -3491,6 +4267,12 @@ declare class WebRTCCall extends Destroyable implements CallManager {
3491
4267
  transfer(options: TransferOptions): Promise<void>;
3492
4268
  /** Destroys the call, releasing all resources and subscriptions. */
3493
4269
  destroy(): void;
4270
+ /**
4271
+ * @internal Send a verto.subscribe message to add an event type to the
4272
+ * server's subscription list for this call. Best-effort — failures are
4273
+ * logged but don't prevent the filtered observable from being returned.
4274
+ */
4275
+ private _sendVertoSubscribe;
3494
4276
  }
3495
4277
  //#endregion
3496
4278
  //#region src/index.d.ts
@@ -3505,5 +4287,5 @@ declare const version: string;
3505
4287
  */
3506
4288
  declare const ready: boolean;
3507
4289
  //#endregion
3508
- export { Address, type AddressHistory, type AuthenticateContext, 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, DPoPInitError, type DeviceController, DeviceTokenError, 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 SATClaims, type SDKCredential, SelfCapabilities, SelfParticipant, type SessionState, SignalWire, type SignalWireOptions, StaticCredentialProvider, type Storage, Subscriber, type TextMessage, TokenRefreshError, type TransferOptions, UnexpectedError, VertoPongError, type VideoPosition, type WebRTCApiProvider, WebRTCCall, type WebRTCMediaDevices, type WebSocketAdapter, embeddableCall, isSelfParticipant, ready, version };
4290
+ export { Address, type AddressHistory, type AudioConstraintsEvent, type AuthenticateContext, type Call, type CallAddress, type CallCapabilitiesState, CallCreateError, type CallDiagnosticSummary, 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, ClientPreferences, CollectionFetchError, type ConstraintFallbackEvent, type CredentialProvider, DPoPInitError, 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 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, SelfCapabilities, SelfParticipant, type SessionDiagnostics, type SessionState, SignalWire, type SignalWireOptions, StaticCredentialProvider, type Storage, type StoredDevicePreference, Subscriber, type TextMessage, TokenRefreshError, type TransferOptions, UnexpectedError, VertoPongError, type VideoPosition, type WebRTCApiProvider, WebRTCCall, type WebRTCMediaDevices, type WebSocketAdapter, embeddableCall, isSelfParticipant, ready, version };
3509
4291
  //# sourceMappingURL=index.d.mts.map