@signalwire/js 4.0.0-rc.0 → 4.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +418 -175
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +418 -174
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +331 -251
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +175 -19
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +175 -19
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +256 -177
- package/dist/index.mjs.map +1 -1
- package/dist/operators/index.cjs +1 -1
- package/dist/operators/index.mjs +1 -1
- package/dist/{operators-D6a2J1KA.cjs → operators-B8ipd4Xl.cjs} +561 -1
- package/dist/operators-B8ipd4Xl.cjs.map +1 -0
- package/dist/{operators-CX_lCCJm.mjs → operators-BlUtq-t0.mjs} +166 -2
- package/dist/operators-BlUtq-t0.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/operators-CX_lCCJm.mjs.map +0 -1
- package/dist/operators-D6a2J1KA.cjs.map +0 -1
package/dist/browser.umd.js
CHANGED
|
@@ -9021,6 +9021,143 @@ var Destroyable = class {
|
|
|
9021
9021
|
}
|
|
9022
9022
|
};
|
|
9023
9023
|
|
|
9024
|
+
//#endregion
|
|
9025
|
+
//#region src/core/constants.ts
|
|
9026
|
+
const INVITE_VERSION = 1e3;
|
|
9027
|
+
const DEFAULT_ICE_CANDIDATE_TIMEOUT_MS = 600;
|
|
9028
|
+
const DEFAULT_ICE_GATHERING_TIMEOUT_MS = 6e3;
|
|
9029
|
+
const DEFAULT_RECONNECT_CALLS_TIMEOUT_MS = 300 * 1e3;
|
|
9030
|
+
const DEFAULT_CONNECTION_TIMEOUT_MS = 1e4;
|
|
9031
|
+
const DEFAULT_RECONNECT_DELAY_MIN_MS = 100;
|
|
9032
|
+
const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
|
|
9033
|
+
const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
|
|
9034
|
+
const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
|
|
9035
|
+
const PREFERENCES_STORAGE_KEY = "sw:preferences";
|
|
9036
|
+
/** Scope value that enables automatic token refresh. */
|
|
9037
|
+
const SAT_REFRESH_SCOPE = "sat:refresh";
|
|
9038
|
+
/** API endpoints for device token operations. */
|
|
9039
|
+
const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
|
|
9040
|
+
const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
|
|
9041
|
+
/** Default device token TTL in seconds (15 minutes). */
|
|
9042
|
+
const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
|
|
9043
|
+
/** Buffer time in milliseconds before expiry to trigger refresh. */
|
|
9044
|
+
const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
|
|
9045
|
+
/** Maximum retry attempts for device token refresh on transient failure. */
|
|
9046
|
+
const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
|
|
9047
|
+
/** Base delay in milliseconds for exponential backoff on refresh retry. */
|
|
9048
|
+
const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9049
|
+
/** Maximum retry attempts for developer credential refresh on transient failure. */
|
|
9050
|
+
const CREDENTIAL_REFRESH_MAX_RETRIES = 5;
|
|
9051
|
+
/** Base delay in milliseconds for exponential backoff on credential refresh retry. */
|
|
9052
|
+
const CREDENTIAL_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9053
|
+
/** Maximum delay in milliseconds for credential refresh backoff. */
|
|
9054
|
+
const CREDENTIAL_REFRESH_MAX_DELAY_MS = 3e4;
|
|
9055
|
+
/** Buffer in milliseconds before token expiry to trigger refresh. */
|
|
9056
|
+
const CREDENTIAL_REFRESH_BUFFER_MS = 5e3;
|
|
9057
|
+
/**
|
|
9058
|
+
* Maximum time the coordinator will wait for `DeviceTokenManager.activate()`
|
|
9059
|
+
* to resolve before treating the activation as failed and falling back to
|
|
9060
|
+
* the developer-provided refresh path. Prevents a wedged HTTP layer from
|
|
9061
|
+
* leaving the session with no active refresh mechanism.
|
|
9062
|
+
*/
|
|
9063
|
+
const CREDENTIAL_ACTIVATE_TIMEOUT_MS = 3e4;
|
|
9064
|
+
/** JSON-RPC error code for requester validation failure (corrupted auth state). */
|
|
9065
|
+
const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
|
|
9066
|
+
/** JSON-RPC error code for invalid params (e.g., missing authentication block). */
|
|
9067
|
+
const RPC_ERROR_INVALID_PARAMS = -32602;
|
|
9068
|
+
/** JSON-RPC error code for authentication failure (invalid token, missing DPoP, etc.). */
|
|
9069
|
+
const RPC_ERROR_AUTHENTICATION_FAILED = -32002;
|
|
9070
|
+
/** Error names browsers use for a media permission denial (user or policy). */
|
|
9071
|
+
const MEDIA_ACCESS_DENIAL_NAMES = [
|
|
9072
|
+
"NotAllowedError",
|
|
9073
|
+
"SecurityError",
|
|
9074
|
+
"PermissionDeniedError"
|
|
9075
|
+
];
|
|
9076
|
+
/** Default polling interval for RTCPeerConnection.getStats() in milliseconds. */
|
|
9077
|
+
const DEFAULT_STATS_POLLING_INTERVAL_MS = 1e3;
|
|
9078
|
+
/** Number of initial samples used to build a baseline for spike detection. */
|
|
9079
|
+
const DEFAULT_STATS_BASELINE_SAMPLES = 10;
|
|
9080
|
+
/** Duration in ms with no inbound audio packets before emitting a critical issue. */
|
|
9081
|
+
const DEFAULT_STATS_NO_PACKET_THRESHOLD_MS = 2e3;
|
|
9082
|
+
/** Multiplier applied to baseline RTT to detect a warning-level RTT spike. */
|
|
9083
|
+
const DEFAULT_STATS_RTT_SPIKE_MULTIPLIER = 3;
|
|
9084
|
+
/** Packet loss fraction (0-1) above which a warning is emitted. */
|
|
9085
|
+
const DEFAULT_STATS_PACKET_LOSS_THRESHOLD = .05;
|
|
9086
|
+
/** Multiplier applied to baseline jitter to detect a jitter spike. */
|
|
9087
|
+
const DEFAULT_STATS_JITTER_SPIKE_MULTIPLIER = 4;
|
|
9088
|
+
/** Number of seconds of metrics history to retain. */
|
|
9089
|
+
const DEFAULT_STATS_HISTORY_SIZE = 30;
|
|
9090
|
+
/** Maximum keyframe requests allowed within a single burst window. */
|
|
9091
|
+
const DEFAULT_KEYFRAME_MAX_BURST$1 = 3;
|
|
9092
|
+
/** Duration of the keyframe burst window in milliseconds. */
|
|
9093
|
+
const DEFAULT_KEYFRAME_BURST_WINDOW_MS$1 = 3e3;
|
|
9094
|
+
/** Cooldown period in ms after burst limit is reached before allowing more keyframes. */
|
|
9095
|
+
const DEFAULT_KEYFRAME_COOLDOWN_MS$1 = 1e4;
|
|
9096
|
+
/** Minimum time between re-INVITE attempts in milliseconds. */
|
|
9097
|
+
const DEFAULT_REINVITE_DEBOUNCE_TIME_MS = 1e4;
|
|
9098
|
+
/** Maximum number of re-INVITE attempts per call. */
|
|
9099
|
+
const DEFAULT_REINVITE_MAX_ATTEMPTS = 3;
|
|
9100
|
+
/** Timeout for a single re-INVITE attempt in milliseconds. */
|
|
9101
|
+
const DEFAULT_REINVITE_TIMEOUT_MS = 5e3;
|
|
9102
|
+
/** Debounce window in ms to collapse multiple detection signals into one trigger. */
|
|
9103
|
+
const DEFAULT_RECOVERY_DEBOUNCE_TIME_MS = 2e3;
|
|
9104
|
+
/** Cooldown period in ms between recovery attempts. */
|
|
9105
|
+
const DEFAULT_RECOVERY_COOLDOWN_MS = 1e4;
|
|
9106
|
+
/** Grace period in ms before treating ICE 'disconnected' as a failure. */
|
|
9107
|
+
const DEFAULT_ICE_DISCONNECTED_GRACE_PERIOD_MS = 3e3;
|
|
9108
|
+
/** Timeout for a single ICE restart attempt in milliseconds. */
|
|
9109
|
+
const DEFAULT_ICE_RESTART_TIMEOUT_MS$1 = 5e3;
|
|
9110
|
+
/** Maximum recovery attempts before emitting 'max_attempts_reached'. */
|
|
9111
|
+
const DEFAULT_MAX_RECOVERY_ATTEMPTS = 3;
|
|
9112
|
+
/** Upper bound in ms for waiting on iceGatheringState === 'complete' after an ICE restart. */
|
|
9113
|
+
const ICE_GATHERING_COMPLETE_TIMEOUT_MS = 1e4;
|
|
9114
|
+
/** Upper bound in ms for waiting on RTCPeerConnection.connectionState === 'connected' after a recovery ICE restart. */
|
|
9115
|
+
const PEER_CONNECTION_RECOVERY_WAIT_MS = 5e3;
|
|
9116
|
+
/** Polling interval in ms while waiting for RTCPeerConnection.connectionState to transition. */
|
|
9117
|
+
const PEER_CONNECTION_RECOVERY_POLL_MS = 100;
|
|
9118
|
+
/** Polling interval for LocalAudioPipeline.level$ (ms). ~30fps is smooth for meters. */
|
|
9119
|
+
const AUDIO_LEVEL_POLL_INTERVAL_MS = 33;
|
|
9120
|
+
/** RMS level threshold (0..1) above which the local participant is considered speaking. */
|
|
9121
|
+
const VAD_THRESHOLD = .03;
|
|
9122
|
+
/** Hold window in ms below the threshold before speaking$ flips back to false. */
|
|
9123
|
+
const VAD_HOLD_MS = 250;
|
|
9124
|
+
/** Whether to persist device selections to storage by default. */
|
|
9125
|
+
const DEFAULT_PERSIST_DEVICE_SELECTION = true;
|
|
9126
|
+
/** Whether to auto-apply device changes to active calls by default. */
|
|
9127
|
+
const DEFAULT_SYNC_DEVICES_TO_ACTIVE_CALLS = true;
|
|
9128
|
+
/** Storage keys for persisted device selections. */
|
|
9129
|
+
const DEVICE_STORAGE_KEY_AUDIO_INPUT = "sw:device:audioinput";
|
|
9130
|
+
const DEVICE_STORAGE_KEY_AUDIO_OUTPUT = "sw:device:audiooutput";
|
|
9131
|
+
const DEVICE_STORAGE_KEY_VIDEO_INPUT = "sw:device:videoinput";
|
|
9132
|
+
/** Whether to auto-mute video when the tab becomes hidden. */
|
|
9133
|
+
const DEFAULT_AUTO_MUTE_VIDEO_ON_HIDDEN = false;
|
|
9134
|
+
/** Whether to re-enumerate devices when the page becomes visible. */
|
|
9135
|
+
const DEFAULT_REFRESH_DEVICES_ON_VISIBLE = true;
|
|
9136
|
+
/** Whether to check peer connection health when the page becomes visible. */
|
|
9137
|
+
const DEFAULT_CHECK_CONNECTION_ON_VISIBLE = true;
|
|
9138
|
+
/** Whether automatic video degradation on low bandwidth is enabled. */
|
|
9139
|
+
const DEFAULT_ENABLE_AUTO_DEGRADATION = true;
|
|
9140
|
+
/** Bitrate in kbps below which video is automatically disabled. */
|
|
9141
|
+
const DEFAULT_DEGRADATION_BITRATE_THRESHOLD_KBPS = 150;
|
|
9142
|
+
/** Bitrate in kbps above which video is automatically re-enabled (hysteresis). */
|
|
9143
|
+
const DEFAULT_DEGRADATION_RECOVERY_THRESHOLD_KBPS = 300;
|
|
9144
|
+
/** Whether relay-only escalation is enabled as a last-resort recovery tier. */
|
|
9145
|
+
const DEFAULT_ENABLE_RELAY_FALLBACK = true;
|
|
9146
|
+
/** Whether to listen for browser online/offline/connection events. */
|
|
9147
|
+
const DEFAULT_ENABLE_NETWORK_CHANGE_DETECTION = true;
|
|
9148
|
+
/** Whether to intercept server-sent media-timeout hangups and attempt recovery. */
|
|
9149
|
+
const DEFAULT_ENABLE_SERVER_HANGUP_INTERCEPTION = true;
|
|
9150
|
+
/** Default video track constraints applied when video is enabled without explicit constraints. */
|
|
9151
|
+
const DEFAULT_VIDEO_CONSTRAINTS = {
|
|
9152
|
+
width: { ideal: 1280 },
|
|
9153
|
+
height: { ideal: 720 },
|
|
9154
|
+
aspectRatio: 16 / 9
|
|
9155
|
+
};
|
|
9156
|
+
/** Whether stereo Opus is enabled by default. */
|
|
9157
|
+
const DEFAULT_STEREO_AUDIO = false;
|
|
9158
|
+
/** Max average bitrate for stereo Opus in bits per second. */
|
|
9159
|
+
const DEFAULT_STEREO_MAX_AVERAGE_BITRATE = 51e4;
|
|
9160
|
+
|
|
9024
9161
|
//#endregion
|
|
9025
9162
|
//#region src/core/errors.ts
|
|
9026
9163
|
var UnexpectedError = class extends Error {
|
|
@@ -9230,6 +9367,33 @@ var MediaTrackError = class extends Error {
|
|
|
9230
9367
|
this.name = "MediaTrackError";
|
|
9231
9368
|
}
|
|
9232
9369
|
};
|
|
9370
|
+
/** True when a `getUserMedia`/`getDisplayMedia` rejection is a permission denial. */
|
|
9371
|
+
function isMediaAccessDenial(originalError) {
|
|
9372
|
+
return originalError instanceof Error && MEDIA_ACCESS_DENIAL_NAMES.includes(originalError.name);
|
|
9373
|
+
}
|
|
9374
|
+
/**
|
|
9375
|
+
* Failure to acquire local media (camera, microphone, or screen capture)
|
|
9376
|
+
* via `getUserMedia`/`getDisplayMedia`.
|
|
9377
|
+
*
|
|
9378
|
+
* Non-fatal by default: screenshare and additional-device failures never
|
|
9379
|
+
* end the call, and main-connection failures degrade to receive-only when
|
|
9380
|
+
* possible. The wrapping site sets `fatal` to `true` only when the call
|
|
9381
|
+
* cannot continue (receive-only fallback disabled or no receive intent).
|
|
9382
|
+
*/
|
|
9383
|
+
var MediaAccessError = class extends Error {
|
|
9384
|
+
constructor(operation, media, originalError, fatal = false) {
|
|
9385
|
+
super(`Media access ${isMediaAccessDenial(originalError) ? "denied" : "failed"} for ${operation} (${media})`, { cause: originalError instanceof Error ? originalError : void 0 });
|
|
9386
|
+
this.operation = operation;
|
|
9387
|
+
this.media = media;
|
|
9388
|
+
this.originalError = originalError;
|
|
9389
|
+
this.fatal = fatal;
|
|
9390
|
+
this.name = "MediaAccessError";
|
|
9391
|
+
}
|
|
9392
|
+
/** True when the underlying failure is a permission denial (user or policy). */
|
|
9393
|
+
get denied() {
|
|
9394
|
+
return isMediaAccessDenial(this.originalError);
|
|
9395
|
+
}
|
|
9396
|
+
};
|
|
9233
9397
|
var DPoPInitError = class extends Error {
|
|
9234
9398
|
constructor(originalError, message = "Failed to initialize DPoP key pair") {
|
|
9235
9399
|
super(message, { cause: originalError instanceof Error ? originalError : void 0 });
|
|
@@ -9879,137 +10043,6 @@ var DeviceHistoryManager = class {
|
|
|
9879
10043
|
}
|
|
9880
10044
|
};
|
|
9881
10045
|
|
|
9882
|
-
//#endregion
|
|
9883
|
-
//#region src/core/constants.ts
|
|
9884
|
-
const INVITE_VERSION = 1e3;
|
|
9885
|
-
const DEFAULT_ICE_CANDIDATE_TIMEOUT_MS = 600;
|
|
9886
|
-
const DEFAULT_ICE_GATHERING_TIMEOUT_MS = 6e3;
|
|
9887
|
-
const DEFAULT_RECONNECT_CALLS_TIMEOUT_MS = 300 * 1e3;
|
|
9888
|
-
const DEFAULT_CONNECTION_TIMEOUT_MS = 1e4;
|
|
9889
|
-
const DEFAULT_RECONNECT_DELAY_MIN_MS = 100;
|
|
9890
|
-
const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
|
|
9891
|
-
const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
|
|
9892
|
-
const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
|
|
9893
|
-
const PREFERENCES_STORAGE_KEY = "sw:preferences";
|
|
9894
|
-
/** Scope value that enables automatic token refresh. */
|
|
9895
|
-
const SAT_REFRESH_SCOPE = "sat:refresh";
|
|
9896
|
-
/** API endpoints for device token operations. */
|
|
9897
|
-
const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
|
|
9898
|
-
const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
|
|
9899
|
-
/** Default device token TTL in seconds (15 minutes). */
|
|
9900
|
-
const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
|
|
9901
|
-
/** Buffer time in milliseconds before expiry to trigger refresh. */
|
|
9902
|
-
const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
|
|
9903
|
-
/** Maximum retry attempts for device token refresh on transient failure. */
|
|
9904
|
-
const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
|
|
9905
|
-
/** Base delay in milliseconds for exponential backoff on refresh retry. */
|
|
9906
|
-
const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9907
|
-
/** Maximum retry attempts for developer credential refresh on transient failure. */
|
|
9908
|
-
const CREDENTIAL_REFRESH_MAX_RETRIES = 5;
|
|
9909
|
-
/** Base delay in milliseconds for exponential backoff on credential refresh retry. */
|
|
9910
|
-
const CREDENTIAL_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9911
|
-
/** Maximum delay in milliseconds for credential refresh backoff. */
|
|
9912
|
-
const CREDENTIAL_REFRESH_MAX_DELAY_MS = 3e4;
|
|
9913
|
-
/** Buffer in milliseconds before token expiry to trigger refresh. */
|
|
9914
|
-
const CREDENTIAL_REFRESH_BUFFER_MS = 5e3;
|
|
9915
|
-
/**
|
|
9916
|
-
* Maximum time the coordinator will wait for `DeviceTokenManager.activate()`
|
|
9917
|
-
* to resolve before treating the activation as failed and falling back to
|
|
9918
|
-
* the developer-provided refresh path. Prevents a wedged HTTP layer from
|
|
9919
|
-
* leaving the session with no active refresh mechanism.
|
|
9920
|
-
*/
|
|
9921
|
-
const CREDENTIAL_ACTIVATE_TIMEOUT_MS = 3e4;
|
|
9922
|
-
/** JSON-RPC error code for requester validation failure (corrupted auth state). */
|
|
9923
|
-
const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
|
|
9924
|
-
/** JSON-RPC error code for invalid params (e.g., missing authentication block). */
|
|
9925
|
-
const RPC_ERROR_INVALID_PARAMS = -32602;
|
|
9926
|
-
/** JSON-RPC error code for authentication failure (invalid token, missing DPoP, etc.). */
|
|
9927
|
-
const RPC_ERROR_AUTHENTICATION_FAILED = -32002;
|
|
9928
|
-
/** Default polling interval for RTCPeerConnection.getStats() in milliseconds. */
|
|
9929
|
-
const DEFAULT_STATS_POLLING_INTERVAL_MS = 1e3;
|
|
9930
|
-
/** Number of initial samples used to build a baseline for spike detection. */
|
|
9931
|
-
const DEFAULT_STATS_BASELINE_SAMPLES = 10;
|
|
9932
|
-
/** Duration in ms with no inbound audio packets before emitting a critical issue. */
|
|
9933
|
-
const DEFAULT_STATS_NO_PACKET_THRESHOLD_MS = 2e3;
|
|
9934
|
-
/** Multiplier applied to baseline RTT to detect a warning-level RTT spike. */
|
|
9935
|
-
const DEFAULT_STATS_RTT_SPIKE_MULTIPLIER = 3;
|
|
9936
|
-
/** Packet loss fraction (0-1) above which a warning is emitted. */
|
|
9937
|
-
const DEFAULT_STATS_PACKET_LOSS_THRESHOLD = .05;
|
|
9938
|
-
/** Multiplier applied to baseline jitter to detect a jitter spike. */
|
|
9939
|
-
const DEFAULT_STATS_JITTER_SPIKE_MULTIPLIER = 4;
|
|
9940
|
-
/** Number of seconds of metrics history to retain. */
|
|
9941
|
-
const DEFAULT_STATS_HISTORY_SIZE = 30;
|
|
9942
|
-
/** Maximum keyframe requests allowed within a single burst window. */
|
|
9943
|
-
const DEFAULT_KEYFRAME_MAX_BURST$1 = 3;
|
|
9944
|
-
/** Duration of the keyframe burst window in milliseconds. */
|
|
9945
|
-
const DEFAULT_KEYFRAME_BURST_WINDOW_MS$1 = 3e3;
|
|
9946
|
-
/** Cooldown period in ms after burst limit is reached before allowing more keyframes. */
|
|
9947
|
-
const DEFAULT_KEYFRAME_COOLDOWN_MS$1 = 1e4;
|
|
9948
|
-
/** Minimum time between re-INVITE attempts in milliseconds. */
|
|
9949
|
-
const DEFAULT_REINVITE_DEBOUNCE_TIME_MS = 1e4;
|
|
9950
|
-
/** Maximum number of re-INVITE attempts per call. */
|
|
9951
|
-
const DEFAULT_REINVITE_MAX_ATTEMPTS = 3;
|
|
9952
|
-
/** Timeout for a single re-INVITE attempt in milliseconds. */
|
|
9953
|
-
const DEFAULT_REINVITE_TIMEOUT_MS = 5e3;
|
|
9954
|
-
/** Debounce window in ms to collapse multiple detection signals into one trigger. */
|
|
9955
|
-
const DEFAULT_RECOVERY_DEBOUNCE_TIME_MS = 2e3;
|
|
9956
|
-
/** Cooldown period in ms between recovery attempts. */
|
|
9957
|
-
const DEFAULT_RECOVERY_COOLDOWN_MS = 1e4;
|
|
9958
|
-
/** Grace period in ms before treating ICE 'disconnected' as a failure. */
|
|
9959
|
-
const DEFAULT_ICE_DISCONNECTED_GRACE_PERIOD_MS = 3e3;
|
|
9960
|
-
/** Timeout for a single ICE restart attempt in milliseconds. */
|
|
9961
|
-
const DEFAULT_ICE_RESTART_TIMEOUT_MS$1 = 5e3;
|
|
9962
|
-
/** Maximum recovery attempts before emitting 'max_attempts_reached'. */
|
|
9963
|
-
const DEFAULT_MAX_RECOVERY_ATTEMPTS = 3;
|
|
9964
|
-
/** Upper bound in ms for waiting on iceGatheringState === 'complete' after an ICE restart. */
|
|
9965
|
-
const ICE_GATHERING_COMPLETE_TIMEOUT_MS = 1e4;
|
|
9966
|
-
/** Upper bound in ms for waiting on RTCPeerConnection.connectionState === 'connected' after a recovery ICE restart. */
|
|
9967
|
-
const PEER_CONNECTION_RECOVERY_WAIT_MS = 5e3;
|
|
9968
|
-
/** Polling interval in ms while waiting for RTCPeerConnection.connectionState to transition. */
|
|
9969
|
-
const PEER_CONNECTION_RECOVERY_POLL_MS = 100;
|
|
9970
|
-
/** Polling interval for LocalAudioPipeline.level$ (ms). ~30fps is smooth for meters. */
|
|
9971
|
-
const AUDIO_LEVEL_POLL_INTERVAL_MS = 33;
|
|
9972
|
-
/** RMS level threshold (0..1) above which the local participant is considered speaking. */
|
|
9973
|
-
const VAD_THRESHOLD = .03;
|
|
9974
|
-
/** Hold window in ms below the threshold before speaking$ flips back to false. */
|
|
9975
|
-
const VAD_HOLD_MS = 250;
|
|
9976
|
-
/** Whether to persist device selections to storage by default. */
|
|
9977
|
-
const DEFAULT_PERSIST_DEVICE_SELECTION = true;
|
|
9978
|
-
/** Whether to auto-apply device changes to active calls by default. */
|
|
9979
|
-
const DEFAULT_SYNC_DEVICES_TO_ACTIVE_CALLS = true;
|
|
9980
|
-
/** Storage keys for persisted device selections. */
|
|
9981
|
-
const DEVICE_STORAGE_KEY_AUDIO_INPUT = "sw:device:audioinput";
|
|
9982
|
-
const DEVICE_STORAGE_KEY_AUDIO_OUTPUT = "sw:device:audiooutput";
|
|
9983
|
-
const DEVICE_STORAGE_KEY_VIDEO_INPUT = "sw:device:videoinput";
|
|
9984
|
-
/** Whether to auto-mute video when the tab becomes hidden. */
|
|
9985
|
-
const DEFAULT_AUTO_MUTE_VIDEO_ON_HIDDEN = false;
|
|
9986
|
-
/** Whether to re-enumerate devices when the page becomes visible. */
|
|
9987
|
-
const DEFAULT_REFRESH_DEVICES_ON_VISIBLE = true;
|
|
9988
|
-
/** Whether to check peer connection health when the page becomes visible. */
|
|
9989
|
-
const DEFAULT_CHECK_CONNECTION_ON_VISIBLE = true;
|
|
9990
|
-
/** Whether automatic video degradation on low bandwidth is enabled. */
|
|
9991
|
-
const DEFAULT_ENABLE_AUTO_DEGRADATION = true;
|
|
9992
|
-
/** Bitrate in kbps below which video is automatically disabled. */
|
|
9993
|
-
const DEFAULT_DEGRADATION_BITRATE_THRESHOLD_KBPS = 150;
|
|
9994
|
-
/** Bitrate in kbps above which video is automatically re-enabled (hysteresis). */
|
|
9995
|
-
const DEFAULT_DEGRADATION_RECOVERY_THRESHOLD_KBPS = 300;
|
|
9996
|
-
/** Whether relay-only escalation is enabled as a last-resort recovery tier. */
|
|
9997
|
-
const DEFAULT_ENABLE_RELAY_FALLBACK = true;
|
|
9998
|
-
/** Whether to listen for browser online/offline/connection events. */
|
|
9999
|
-
const DEFAULT_ENABLE_NETWORK_CHANGE_DETECTION = true;
|
|
10000
|
-
/** Whether to intercept server-sent media-timeout hangups and attempt recovery. */
|
|
10001
|
-
const DEFAULT_ENABLE_SERVER_HANGUP_INTERCEPTION = true;
|
|
10002
|
-
/** Default video track constraints applied when video is enabled without explicit constraints. */
|
|
10003
|
-
const DEFAULT_VIDEO_CONSTRAINTS = {
|
|
10004
|
-
width: { ideal: 1280 },
|
|
10005
|
-
height: { ideal: 720 },
|
|
10006
|
-
aspectRatio: 16 / 9
|
|
10007
|
-
};
|
|
10008
|
-
/** Whether stereo Opus is enabled by default. */
|
|
10009
|
-
const DEFAULT_STEREO_AUDIO = false;
|
|
10010
|
-
/** Max average bitrate for stereo Opus in bits per second. */
|
|
10011
|
-
const DEFAULT_STEREO_MAX_AVERAGE_BITRATE = 51e4;
|
|
10012
|
-
|
|
10013
10046
|
//#endregion
|
|
10014
10047
|
//#region src/utils/time.ts
|
|
10015
10048
|
function fromSecToMs(seconds) {
|
|
@@ -13373,7 +13406,9 @@ const DEFAULT_MEMBER_CAPABILITIES = {
|
|
|
13373
13406
|
position: false,
|
|
13374
13407
|
meta: false,
|
|
13375
13408
|
remove: false,
|
|
13376
|
-
audioFlags: false
|
|
13409
|
+
audioFlags: false,
|
|
13410
|
+
denoise: false,
|
|
13411
|
+
lowbitrate: false
|
|
13377
13412
|
};
|
|
13378
13413
|
/**
|
|
13379
13414
|
* Default call capabilities with no permissions
|
|
@@ -13446,7 +13481,9 @@ function computeMemberCapabilities(flags, memberType) {
|
|
|
13446
13481
|
position: hasBooleanCapability(flags, memberType, null, "position"),
|
|
13447
13482
|
meta: hasBooleanCapability(flags, memberType, null, "meta"),
|
|
13448
13483
|
remove: hasBooleanCapability(flags, memberType, null, "remove"),
|
|
13449
|
-
audioFlags: hasBooleanCapability(flags, memberType, null, "audioflags")
|
|
13484
|
+
audioFlags: hasBooleanCapability(flags, memberType, null, "audioflags"),
|
|
13485
|
+
denoise: hasBooleanCapability(flags, memberType, null, "denoise"),
|
|
13486
|
+
lowbitrate: hasBooleanCapability(flags, memberType, null, "lowbitrate")
|
|
13450
13487
|
};
|
|
13451
13488
|
}
|
|
13452
13489
|
/**
|
|
@@ -13829,6 +13866,10 @@ var Participant = class extends Destroyable {
|
|
|
13829
13866
|
get nodeId() {
|
|
13830
13867
|
return this._state$.value.node_id;
|
|
13831
13868
|
}
|
|
13869
|
+
/** Call ID for this participant's leg, or `undefined` if not available. */
|
|
13870
|
+
get callId() {
|
|
13871
|
+
return this._state$.value.call_id;
|
|
13872
|
+
}
|
|
13832
13873
|
/** @internal */
|
|
13833
13874
|
get value() {
|
|
13834
13875
|
return this._state$.value;
|
|
@@ -13890,8 +13931,9 @@ var Participant = class extends Destroyable {
|
|
|
13890
13931
|
noise_suppression: !this.noiseSuppression
|
|
13891
13932
|
});
|
|
13892
13933
|
}
|
|
13934
|
+
/** Toggles low-bitrate mode for this participant's media. */
|
|
13893
13935
|
async toggleLowbitrate() {
|
|
13894
|
-
|
|
13936
|
+
await this.executeMethod(this.id, "call.lowbitrate.set", { lowbitrate: !this.lowbitrate });
|
|
13895
13937
|
}
|
|
13896
13938
|
/**
|
|
13897
13939
|
* Adjusts the **conference-only** microphone energy gate / sensitivity level
|
|
@@ -13938,10 +13980,27 @@ var Participant = class extends Destroyable {
|
|
|
13938
13980
|
}
|
|
13939
13981
|
/**
|
|
13940
13982
|
* Sets the participant's position in the video layout.
|
|
13983
|
+
*
|
|
13984
|
+
* Requires the `member.position` capability. The gateway keys positions by the
|
|
13985
|
+
* **target member's own** `call_id`/`node_id` (see issue #19400 and the legacy
|
|
13986
|
+
* `setPositions` implementation), so this sends the participant's own call
|
|
13987
|
+
* context — matching {@link Participant.remove}. A resolved promise does not
|
|
13988
|
+
* guarantee a visible change: the backend silently returns `200` (no-op) for
|
|
13989
|
+
* non-conference targets.
|
|
13990
|
+
*
|
|
13941
13991
|
* @param value - The {@link VideoPosition} to assign (e.g. `'auto'`, `'reserved-0'`).
|
|
13942
13992
|
*/
|
|
13943
13993
|
async setPosition(value) {
|
|
13944
|
-
|
|
13994
|
+
const state = this._state$.value;
|
|
13995
|
+
const target = {
|
|
13996
|
+
member_id: this.id,
|
|
13997
|
+
call_id: state.call_id ?? "",
|
|
13998
|
+
node_id: state.node_id ?? ""
|
|
13999
|
+
};
|
|
14000
|
+
await this.executeMethod(target, "call.member.position.set", { targets: [{
|
|
14001
|
+
target,
|
|
14002
|
+
position: value
|
|
14003
|
+
}] });
|
|
13945
14004
|
}
|
|
13946
14005
|
/** Removes this participant from the call. */
|
|
13947
14006
|
async remove() {
|
|
@@ -14031,12 +14090,21 @@ var SelfParticipant = class extends Participant {
|
|
|
14031
14090
|
noise_suppression: true
|
|
14032
14091
|
});
|
|
14033
14092
|
}
|
|
14034
|
-
/**
|
|
14093
|
+
/**
|
|
14094
|
+
* Starts sharing the local screen.
|
|
14095
|
+
*
|
|
14096
|
+
* The call is unaffected when acquisition fails.
|
|
14097
|
+
*
|
|
14098
|
+
* @throws The raw `getDisplayMedia` error. A dismissed picker or a
|
|
14099
|
+
* permission denial rejects with a `NotAllowedError` `DOMException` —
|
|
14100
|
+
* inspect `error.name` to tell benign cancels apart from real failures.
|
|
14101
|
+
*/
|
|
14035
14102
|
async startScreenShare() {
|
|
14036
14103
|
try {
|
|
14037
14104
|
await this.vertoManager.addScreenMedia();
|
|
14038
14105
|
} catch (error) {
|
|
14039
14106
|
logger$24.error("[Participant.startScreenShare] Screen share error:", error);
|
|
14107
|
+
throw error;
|
|
14040
14108
|
}
|
|
14041
14109
|
}
|
|
14042
14110
|
/** Observable of the current screen share status. */
|
|
@@ -14051,12 +14119,20 @@ var SelfParticipant = class extends Participant {
|
|
|
14051
14119
|
async stopScreenShare() {
|
|
14052
14120
|
return this.vertoManager.removeScreenMedia();
|
|
14053
14121
|
}
|
|
14054
|
-
/**
|
|
14122
|
+
/**
|
|
14123
|
+
* Adds an additional media input device to the call.
|
|
14124
|
+
*
|
|
14125
|
+
* The call is unaffected when acquisition fails.
|
|
14126
|
+
*
|
|
14127
|
+
* @throws The raw `getUserMedia` error (e.g. `NotAllowedError` on
|
|
14128
|
+
* permission denial) — inspect `error.name` to decide how to react.
|
|
14129
|
+
*/
|
|
14055
14130
|
async addAdditionalDevice(options) {
|
|
14056
14131
|
try {
|
|
14057
14132
|
await this.vertoManager.addInputDevice(options);
|
|
14058
14133
|
} catch (error) {
|
|
14059
|
-
logger$24.error("[Participant.
|
|
14134
|
+
logger$24.error("[Participant.addAdditionalDevice] Additional device error:", error);
|
|
14135
|
+
throw error;
|
|
14060
14136
|
}
|
|
14061
14137
|
}
|
|
14062
14138
|
/** Removes an additional media input device by ID. */
|
|
@@ -15688,7 +15764,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15688
15764
|
logger$17.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
|
|
15689
15765
|
} catch (error) {
|
|
15690
15766
|
logger$17.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
|
|
15691
|
-
this._errors$.next(
|
|
15767
|
+
this._errors$.next(new MediaTrackError("updateSelectedInputDevice", kind, error));
|
|
15692
15768
|
throw error;
|
|
15693
15769
|
}
|
|
15694
15770
|
};
|
|
@@ -15910,7 +15986,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15910
15986
|
case "main":
|
|
15911
15987
|
default: return {
|
|
15912
15988
|
...options,
|
|
15913
|
-
offerToReceiveAudio: true,
|
|
15989
|
+
offerToReceiveAudio: this.options.receiveAudio ?? true,
|
|
15914
15990
|
offerToReceiveVideo: this.options.receiveVideo ?? Boolean(this.inputVideoDeviceConstraints)
|
|
15915
15991
|
};
|
|
15916
15992
|
}
|
|
@@ -16064,13 +16140,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16064
16140
|
*/
|
|
16065
16141
|
async acceptInbound(mediaOverrides) {
|
|
16066
16142
|
if (mediaOverrides) {
|
|
16067
|
-
const { audio, video, receiveAudio, receiveVideo } = mediaOverrides;
|
|
16143
|
+
const { audio, video, receiveAudio, receiveVideo, fallbackToReceiveOnly } = mediaOverrides;
|
|
16068
16144
|
this.options = {
|
|
16069
16145
|
...this.options,
|
|
16070
16146
|
...audio !== void 0 ? { audio } : {},
|
|
16071
16147
|
...video !== void 0 ? { video } : {},
|
|
16072
16148
|
...receiveAudio !== void 0 ? { receiveAudio } : {},
|
|
16073
|
-
...receiveVideo !== void 0 ? { receiveVideo } : {}
|
|
16149
|
+
...receiveVideo !== void 0 ? { receiveVideo } : {},
|
|
16150
|
+
...fallbackToReceiveOnly !== void 0 ? { fallbackToReceiveOnly } : {}
|
|
16074
16151
|
};
|
|
16075
16152
|
this.transceiverController?.updateOptions({
|
|
16076
16153
|
receiveAudio: this.receiveAudio,
|
|
@@ -16227,7 +16304,19 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16227
16304
|
}
|
|
16228
16305
|
async setupLocalTracks() {
|
|
16229
16306
|
logger$17.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
16230
|
-
|
|
16307
|
+
if (this.hasNoLocalMediaToSend()) {
|
|
16308
|
+
if (!this.receiveAudio && !this.receiveVideo) throw new InvalidParams("Call requests no media: enable audio/video or receiveAudio/receiveVideo");
|
|
16309
|
+
logger$17.debug("[RTCPeerConnectionController] No local media requested; negotiating receive-only.");
|
|
16310
|
+
this.setupReceiveOnlyTransceivers();
|
|
16311
|
+
return;
|
|
16312
|
+
}
|
|
16313
|
+
let localStream;
|
|
16314
|
+
try {
|
|
16315
|
+
localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
16316
|
+
} catch (error) {
|
|
16317
|
+
this.handleLocalMediaFailure(error);
|
|
16318
|
+
return;
|
|
16319
|
+
}
|
|
16231
16320
|
if (this.transceiverController?.useAddStream ?? false) {
|
|
16232
16321
|
logger$17.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
16233
16322
|
this.peerConnection?.addStream(localStream);
|
|
@@ -16254,6 +16343,48 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16254
16343
|
}
|
|
16255
16344
|
}
|
|
16256
16345
|
}
|
|
16346
|
+
/** True for a main connection with no local media to send. */
|
|
16347
|
+
hasNoLocalMediaToSend() {
|
|
16348
|
+
const hasInputStreams = Boolean(this.options.inputAudioStream ?? this.options.inputVideoStream);
|
|
16349
|
+
return this.propose === "main" && !this.localStream && !hasInputStreams && !this.inputAudioDeviceConstraints && !this.inputVideoDeviceConstraints;
|
|
16350
|
+
}
|
|
16351
|
+
/** The media kinds this connection wants to send: 'audiovideo' | 'video' | 'audio'. */
|
|
16352
|
+
get requestedMediaKinds() {
|
|
16353
|
+
const wantsAudio = Boolean(this.inputAudioDeviceConstraints);
|
|
16354
|
+
const wantsVideo = Boolean(this.inputVideoDeviceConstraints);
|
|
16355
|
+
if (wantsAudio && wantsVideo) return "audiovideo";
|
|
16356
|
+
return wantsVideo ? "video" : "audio";
|
|
16357
|
+
}
|
|
16358
|
+
/**
|
|
16359
|
+
* Handle a local media acquisition failure with a typed, semantically
|
|
16360
|
+
* accurate MediaAccessError created at the acquisition site:
|
|
16361
|
+
* - Auxiliary connections (screenshare / additional-device) throw a
|
|
16362
|
+
* non-fatal error — VertoManager surfaces it and the call is unaffected.
|
|
16363
|
+
* - The main connection degrades to receive-only when allowed (default),
|
|
16364
|
+
* otherwise fails with a fatal error.
|
|
16365
|
+
*/
|
|
16366
|
+
handleLocalMediaFailure(error) {
|
|
16367
|
+
if (this.propose === "screenshare") throw new MediaAccessError("startScreenShare", "screen", error, false);
|
|
16368
|
+
if (this.propose === "additional-device") throw new MediaAccessError("addInputDevice", this.requestedMediaKinds, error, false);
|
|
16369
|
+
const canReceive = this.receiveAudio || this.receiveVideo;
|
|
16370
|
+
if (!((this.options.fallbackToReceiveOnly ?? true) && canReceive)) throw new MediaAccessError("acquireLocalMedia", this.requestedMediaKinds, error, true);
|
|
16371
|
+
logger$17.warn("[RTCPeerConnectionController] Local media unavailable; continuing receive-only:", error);
|
|
16372
|
+
this._errors$.next(new MediaAccessError("acquireLocalMedia", this.requestedMediaKinds, error, false));
|
|
16373
|
+
this.setupReceiveOnlyTransceivers();
|
|
16374
|
+
}
|
|
16375
|
+
/**
|
|
16376
|
+
* Negotiate receive-only m-lines when there are no local tracks to send.
|
|
16377
|
+
* Only offer-type connections add transceivers — answer-type connections
|
|
16378
|
+
* reuse the transceivers created from the remote offer.
|
|
16379
|
+
*/
|
|
16380
|
+
setupReceiveOnlyTransceivers() {
|
|
16381
|
+
if (this.type !== "offer") return;
|
|
16382
|
+
if (this.transceiverController?.useAddTransceivers ?? false) {
|
|
16383
|
+
this.peerConnection?.addTransceiver("audio", { direction: this.receiveAudio ? "recvonly" : "inactive" });
|
|
16384
|
+
this.peerConnection?.addTransceiver("video", { direction: this.receiveVideo ? "recvonly" : "inactive" });
|
|
16385
|
+
}
|
|
16386
|
+
if (!this.isNegotiating) this.negotiationNeeded$.next();
|
|
16387
|
+
}
|
|
16257
16388
|
async getUserMedia(constraints) {
|
|
16258
16389
|
return (this.options.webRTCApiProvider?.mediaDevices ?? navigator.mediaDevices).getUserMedia(constraints);
|
|
16259
16390
|
}
|
|
@@ -16290,7 +16421,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16290
16421
|
stream = await this.getUserMedia({ audio: constraints });
|
|
16291
16422
|
} catch (error) {
|
|
16292
16423
|
logger$17.error("[RTCPeerConnectionController] Failed to re-acquire mic for pipeline restore:", error);
|
|
16293
|
-
this._errors$.next(
|
|
16424
|
+
this._errors$.next(new MediaTrackError("restoreAudioPipelineInput", "audio", error));
|
|
16294
16425
|
return;
|
|
16295
16426
|
}
|
|
16296
16427
|
const newTrack = stream.getAudioTracks().at(0);
|
|
@@ -16352,7 +16483,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16352
16483
|
logger$17.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
|
|
16353
16484
|
} catch (error) {
|
|
16354
16485
|
logger$17.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
|
|
16355
|
-
this._errors$.next(
|
|
16486
|
+
this._errors$.next(new MediaTrackError("addLocalTrack", track.kind, error));
|
|
16356
16487
|
throw error;
|
|
16357
16488
|
}
|
|
16358
16489
|
}
|
|
@@ -16377,7 +16508,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16377
16508
|
logger$17.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
|
|
16378
16509
|
} catch (error) {
|
|
16379
16510
|
logger$17.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
|
|
16380
|
-
this._errors$.next(
|
|
16511
|
+
this._errors$.next(new MediaTrackError("removeLocalTrack", sender.track?.kind ?? "unknown", error));
|
|
16381
16512
|
throw error;
|
|
16382
16513
|
}
|
|
16383
16514
|
}
|
|
@@ -16487,7 +16618,11 @@ function isVertoInviteMessage(value) {
|
|
|
16487
16618
|
const msg = value;
|
|
16488
16619
|
return msg.method === "verto.invite" && isObject(msg.params) && hasProperty(msg.params, "sdp") && hasProperty(msg.params, "callID");
|
|
16489
16620
|
}
|
|
16490
|
-
|
|
16621
|
+
/**
|
|
16622
|
+
* Guards inbound `verto.bye` frames (server → client). Outbound bye messages are
|
|
16623
|
+
* built locally and never type-guarded, so only the inbound shape is asserted.
|
|
16624
|
+
*/
|
|
16625
|
+
function isVertoByeInboundMessage(value) {
|
|
16491
16626
|
if (!isVertoMethodMessage(value)) return false;
|
|
16492
16627
|
return value.method === "verto.bye";
|
|
16493
16628
|
}
|
|
@@ -16507,6 +16642,14 @@ function isVertoMediaParamsInnerParams(value) {
|
|
|
16507
16642
|
function isVertoPingInnerParams(value) {
|
|
16508
16643
|
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.ping";
|
|
16509
16644
|
}
|
|
16645
|
+
/**
|
|
16646
|
+
* Guards the params of an inbound `verto.bye` frame (top-level `callID`). Use
|
|
16647
|
+
* this to recognise the bye payload extracted by `vertoBye$`, e.g. when racing
|
|
16648
|
+
* it against a boolean answer/reject signal.
|
|
16649
|
+
*/
|
|
16650
|
+
function isVertoByeInboundParamsGuard(value) {
|
|
16651
|
+
return isObject(value) && hasProperty(value, "callID") && typeof value.callID === "string";
|
|
16652
|
+
}
|
|
16510
16653
|
|
|
16511
16654
|
//#endregion
|
|
16512
16655
|
//#region src/managers/VertoManager.ts
|
|
@@ -16845,7 +16988,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16845
16988
|
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
16846
16989
|
}
|
|
16847
16990
|
get vertoBye$() {
|
|
16848
|
-
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(
|
|
16991
|
+
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeInboundMessage, "params"), (0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
16849
16992
|
}
|
|
16850
16993
|
get vertoAttach$() {
|
|
16851
16994
|
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
@@ -16974,6 +17117,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16974
17117
|
inputVideoStream: options.inputVideoStream,
|
|
16975
17118
|
receiveAudio: options.receiveAudio,
|
|
16976
17119
|
receiveVideo: options.receiveVideo,
|
|
17120
|
+
fallbackToReceiveOnly: options.fallbackToReceiveOnly,
|
|
16977
17121
|
webRTCApiProvider: this.webRTCApiProvider,
|
|
16978
17122
|
preferredVideoCodecs: options.preferredVideoCodecs,
|
|
16979
17123
|
preferredAudioCodecs: options.preferredAudioCodecs,
|
|
@@ -16998,7 +17142,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16998
17142
|
logger$16.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
16999
17143
|
return;
|
|
17000
17144
|
}
|
|
17001
|
-
if (
|
|
17145
|
+
if (isVertoByeInboundParamsGuard(vertoByeOrAccepted)) {
|
|
17002
17146
|
logger$16.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
17003
17147
|
this.callSession?.destroy();
|
|
17004
17148
|
} else if (!vertoByeOrAccepted) {
|
|
@@ -17100,7 +17244,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17100
17244
|
logger$16.debug("[WebRTCManager] Destroyed while waiting for call acceptance");
|
|
17101
17245
|
return;
|
|
17102
17246
|
}
|
|
17103
|
-
if (
|
|
17247
|
+
if (isVertoByeInboundParamsGuard(vertoByeOrAccepted)) {
|
|
17104
17248
|
logger$16.info("[WebRTCManager] Call ended before answer was sent.");
|
|
17105
17249
|
this.callSession?.destroy();
|
|
17106
17250
|
} else if (!vertoByeOrAccepted) {
|
|
@@ -17200,9 +17344,11 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17200
17344
|
await this.initAdditionalPeerConnection("screenshare", options);
|
|
17201
17345
|
}
|
|
17202
17346
|
async initAdditionalPeerConnection(propose, options) {
|
|
17347
|
+
const isScreenShare = propose === "screenshare";
|
|
17348
|
+
let firstPeerConnectionError;
|
|
17203
17349
|
let rtcPeerConnController = null;
|
|
17204
17350
|
try {
|
|
17205
|
-
this._screenShareStatus$.next("starting");
|
|
17351
|
+
if (isScreenShare) this._screenShareStatus$.next("starting");
|
|
17206
17352
|
rtcPeerConnController = new RTCPeerConnectionController({
|
|
17207
17353
|
...options,
|
|
17208
17354
|
...this.RTCPeerConnectionConfig,
|
|
@@ -17210,21 +17356,27 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17210
17356
|
webRTCApiProvider: this.webRTCApiProvider
|
|
17211
17357
|
}, void 0, this.deviceController);
|
|
17212
17358
|
this.setupLocalDescriptionHandler(rtcPeerConnController);
|
|
17213
|
-
if (
|
|
17359
|
+
if (isScreenShare) this._screenShareId = rtcPeerConnController.id;
|
|
17214
17360
|
this._rtcPeerConnectionsMap.set(rtcPeerConnController.id, rtcPeerConnController);
|
|
17215
17361
|
this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values()));
|
|
17216
17362
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
17217
|
-
|
|
17363
|
+
firstPeerConnectionError ??= error;
|
|
17364
|
+
this.onError?.(error, { fatal: false });
|
|
17218
17365
|
});
|
|
17219
17366
|
await (0, import_cjs$15.firstValueFrom)(rtcPeerConnController.connectionState$.pipe((0, import_cjs$15.filter)((state) => state === "connected"), (0, import_cjs$15.take)(1), (0, import_cjs$15.timeout)(this._screenShareTimeoutMs), (0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
17220
|
-
this._screenShareStatus$.next("started");
|
|
17221
|
-
logger$16.info(
|
|
17367
|
+
if (isScreenShare) this._screenShareStatus$.next("started");
|
|
17368
|
+
logger$16.info(`[WebRTCManager] Additional peer connection connected (${propose}).`);
|
|
17222
17369
|
return rtcPeerConnController.id;
|
|
17223
17370
|
} catch (error) {
|
|
17224
17371
|
logger$16.warn("[WebRTCManager] Error initializing additional peer connection:", error);
|
|
17225
|
-
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
17226
17372
|
if (rtcPeerConnController) rtcPeerConnController.destroy();
|
|
17227
|
-
this._screenShareStatus$.next("none");
|
|
17373
|
+
if (isScreenShare) this._screenShareStatus$.next("none");
|
|
17374
|
+
if (firstPeerConnectionError) throw firstPeerConnectionError instanceof MediaAccessError && firstPeerConnectionError.originalError instanceof Error ? firstPeerConnectionError.originalError : firstPeerConnectionError;
|
|
17375
|
+
if (error instanceof import_cjs$15.EmptyError) {
|
|
17376
|
+
logger$16.debug("[WebRTCManager] Additional peer connection aborted before connecting.");
|
|
17377
|
+
return;
|
|
17378
|
+
}
|
|
17379
|
+
throw error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
17228
17380
|
}
|
|
17229
17381
|
}
|
|
17230
17382
|
async removeInputDevices(id) {
|
|
@@ -18153,6 +18305,12 @@ function mosToQualityLevel(mos) {
|
|
|
18153
18305
|
var import_cjs$11 = require_cjs();
|
|
18154
18306
|
const logger$12 = getLogger();
|
|
18155
18307
|
/**
|
|
18308
|
+
* Verto method for setting member layout positions. Its gateway DTO requires a
|
|
18309
|
+
* `targets` array whose entries are `{ target, position }` (NOT bare targets),
|
|
18310
|
+
* so {@link WebRTCCall.buildMethodParams} special-cases it. See issue #19400.
|
|
18311
|
+
*/
|
|
18312
|
+
const POSITION_SET_METHOD = "call.member.position.set";
|
|
18313
|
+
/**
|
|
18156
18314
|
* Ratio between the critical and warning RTT spike multipliers.
|
|
18157
18315
|
* Warning threshold = baseline * warningMultiplier (default 3x)
|
|
18158
18316
|
* Critical threshold = baseline * warningMultiplier * RTT_CRITICAL_TO_WARNING_RATIO
|
|
@@ -18359,7 +18517,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18359
18517
|
* @throws {JSONRPCError} If the RPC call returns an error.
|
|
18360
18518
|
*/
|
|
18361
18519
|
async executeMethod(target, method, args) {
|
|
18362
|
-
const params = this.buildMethodParams(target, args);
|
|
18520
|
+
const params = this.buildMethodParams(target, args, method);
|
|
18363
18521
|
const request = buildRPCRequest({
|
|
18364
18522
|
method,
|
|
18365
18523
|
params
|
|
@@ -18373,12 +18531,16 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18373
18531
|
throw error;
|
|
18374
18532
|
}
|
|
18375
18533
|
}
|
|
18376
|
-
buildMethodParams(target, args) {
|
|
18534
|
+
buildMethodParams(target, args, method) {
|
|
18377
18535
|
const self = {
|
|
18378
18536
|
node_id: this.nodeId ?? "",
|
|
18379
18537
|
call_id: this.id,
|
|
18380
18538
|
member_id: this.vertoManager.selfId ?? ""
|
|
18381
18539
|
};
|
|
18540
|
+
if (method === POSITION_SET_METHOD) return {
|
|
18541
|
+
...args,
|
|
18542
|
+
self
|
|
18543
|
+
};
|
|
18382
18544
|
if (typeof target === "object") return {
|
|
18383
18545
|
...args,
|
|
18384
18546
|
self,
|
|
@@ -18944,10 +19106,21 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18944
19106
|
return this.deferEmission(this._answered$.asObservable());
|
|
18945
19107
|
}
|
|
18946
19108
|
/**
|
|
18947
|
-
* Sets the call layout and participant positions.
|
|
19109
|
+
* Sets the call layout and, optionally, individual participant positions.
|
|
19110
|
+
*
|
|
19111
|
+
* The gateway `call.layout.set` DTO has **no** `positions` member, so when
|
|
19112
|
+
* `positions` is provided this method issues a `call.member.position.set`
|
|
19113
|
+
* request per member (via {@link Participant.setPosition}, which keys each
|
|
19114
|
+
* position by that member's own call context) alongside `call.layout.set`
|
|
19115
|
+
* (issue #19400, Flag #6).
|
|
19116
|
+
*
|
|
19117
|
+
* **These operations are NOT atomic.** The layout is applied first, then each
|
|
19118
|
+
* member position sequentially, so members may briefly flash into their
|
|
19119
|
+
* default slots before being moved to the requested positions.
|
|
18948
19120
|
*
|
|
18949
19121
|
* @param layout - Layout name (must be one of {@link layouts}).
|
|
18950
|
-
* @param positions -
|
|
19122
|
+
* @param positions - Optional map of member IDs to {@link VideoPosition} values.
|
|
19123
|
+
* When omitted or empty, only the layout is changed.
|
|
18951
19124
|
* @throws {InvalidParams} If the layout is not in the available {@link layouts}.
|
|
18952
19125
|
*
|
|
18953
19126
|
* @example
|
|
@@ -18960,10 +19133,17 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18960
19133
|
async setLayout(layout, positions) {
|
|
18961
19134
|
if (!this.layouts.includes(layout)) throw new InvalidParams(`Layout ${layout} is not available in the current call layouts: ${this.layouts.join(", ")}`);
|
|
18962
19135
|
const selfId = await (0, import_cjs$11.firstValueFrom)(this.selfId$.pipe((0, import_cjs$11.filter)((id) => id !== null)));
|
|
18963
|
-
await this.executeMethod(selfId, "call.layout.set", {
|
|
18964
|
-
|
|
18965
|
-
|
|
18966
|
-
|
|
19136
|
+
await this.executeMethod(selfId, "call.layout.set", { layout });
|
|
19137
|
+
const positionEntries = Object.entries(positions ?? {});
|
|
19138
|
+
if (positionEntries.length === 0) return;
|
|
19139
|
+
for (const [memberId, position] of positionEntries) {
|
|
19140
|
+
const participant = this.participants.find((p) => p.id === memberId);
|
|
19141
|
+
if (!participant) {
|
|
19142
|
+
logger$12.warn(`[Call] setLayout: member ${memberId} not found in participants; skipping position ${position}`);
|
|
19143
|
+
continue;
|
|
19144
|
+
}
|
|
19145
|
+
await participant.setPosition(position);
|
|
19146
|
+
}
|
|
18967
19147
|
}
|
|
18968
19148
|
/**
|
|
18969
19149
|
* Transfers the call to another destination.
|
|
@@ -19137,6 +19317,7 @@ function inferCallErrorKind(error) {
|
|
|
19137
19317
|
if (error instanceof RPCTimeoutError) return "timeout";
|
|
19138
19318
|
if (error instanceof JSONRPCError) return "signaling";
|
|
19139
19319
|
if (error instanceof MediaTrackError) return "media";
|
|
19320
|
+
if (error instanceof MediaAccessError) return "media";
|
|
19140
19321
|
if (error instanceof WebSocketConnectionError || error instanceof TransportConnectionError) return "network";
|
|
19141
19322
|
return "internal";
|
|
19142
19323
|
}
|
|
@@ -19153,6 +19334,7 @@ const RECOVERABLE_RPC_CODES = new Set([
|
|
|
19153
19334
|
function isFatalError(error) {
|
|
19154
19335
|
if (error instanceof VertoPongError) return false;
|
|
19155
19336
|
if (error instanceof MediaTrackError) return false;
|
|
19337
|
+
if (error instanceof MediaAccessError) return error.fatal;
|
|
19156
19338
|
if (error instanceof RPCTimeoutError) return false;
|
|
19157
19339
|
if (error instanceof JSONRPCError && RECOVERABLE_RPC_CODES.has(error.code)) return false;
|
|
19158
19340
|
return true;
|
|
@@ -19178,10 +19360,10 @@ var CallFactory = class {
|
|
|
19178
19360
|
return {
|
|
19179
19361
|
vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, this.webRTCApiProvider, {
|
|
19180
19362
|
nodeId: options.nodeId,
|
|
19181
|
-
onError: (error) => {
|
|
19363
|
+
onError: (error, options$1) => {
|
|
19182
19364
|
const callError = {
|
|
19183
19365
|
kind: inferCallErrorKind(error),
|
|
19184
|
-
fatal: isFatalError(error),
|
|
19366
|
+
fatal: options$1?.fatal ?? isFatalError(error),
|
|
19185
19367
|
error,
|
|
19186
19368
|
callId: callInstance.id
|
|
19187
19369
|
};
|
|
@@ -19644,6 +19826,17 @@ var PendingRPC = class PendingRPC {
|
|
|
19644
19826
|
//#region src/managers/ClientSessionManager.ts
|
|
19645
19827
|
var import_cjs$7 = require_cjs();
|
|
19646
19828
|
const logger$9 = getLogger();
|
|
19829
|
+
/**
|
|
19830
|
+
* Decide whether an error emitted on `call.errors$` during dial should
|
|
19831
|
+
* abort the dial. A non-fatal MediaAccessError means the call degraded to
|
|
19832
|
+
* receive-only and still connects — everything else rejects `dial()` with
|
|
19833
|
+
* the real cause.
|
|
19834
|
+
*
|
|
19835
|
+
* Pure function — exported for unit testing.
|
|
19836
|
+
*/
|
|
19837
|
+
function shouldAbortDial(callError) {
|
|
19838
|
+
return callError.fatal || !(callError.error instanceof MediaAccessError);
|
|
19839
|
+
}
|
|
19647
19840
|
const getAddressSearchURI = (options) => {
|
|
19648
19841
|
const to = options.to?.split("?")[0];
|
|
19649
19842
|
const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
|
|
@@ -19882,11 +20075,41 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19882
20075
|
}
|
|
19883
20076
|
} else this._errors$.next(error);
|
|
19884
20077
|
}
|
|
20078
|
+
/**
|
|
20079
|
+
* Clear the resume state (authorization_state + protocol) only.
|
|
20080
|
+
*
|
|
20081
|
+
* This is the stale-auth-state recovery helper used by handleAuthError:
|
|
20082
|
+
* the server rejected a reconnect, so the resume state is discarded and a
|
|
20083
|
+
* fresh connect follows. Attach records are deliberately preserved — the
|
|
20084
|
+
* session lives on through the reconnect and reattachCalls() needs the
|
|
20085
|
+
* stored call references afterwards. Do NOT add detachAll() here.
|
|
20086
|
+
*
|
|
20087
|
+
* For public teardown (disconnect/destroy), use {@link teardownSessionState}
|
|
20088
|
+
* instead, which clears the attach records as well.
|
|
20089
|
+
*/
|
|
19885
20090
|
async cleanupStoredConnectionParams() {
|
|
19886
20091
|
await this.transport.setProtocol(void 0);
|
|
19887
20092
|
await this.updateAuthorizationStateInStorage(void 0);
|
|
19888
20093
|
this._authorization$.next(void 0);
|
|
19889
20094
|
}
|
|
20095
|
+
/**
|
|
20096
|
+
* Public-teardown helper for disconnect()/destroy(). Clears the resume
|
|
20097
|
+
* state (authorization_state + protocol) AND the attach records as one
|
|
20098
|
+
* atomic unit.
|
|
20099
|
+
*
|
|
20100
|
+
* The two stores are coupled: the backend only honors attach records
|
|
20101
|
+
* within the session identified by the resume state, so ending the
|
|
20102
|
+
* session must clear both. Clearing one without the other strands records
|
|
20103
|
+
* no future session can honor (disconnect) or revives a session the
|
|
20104
|
+
* developer explicitly ended (destroy).
|
|
20105
|
+
*
|
|
20106
|
+
* Distinct from {@link cleanupStoredConnectionParams}, which keeps the
|
|
20107
|
+
* attach records for the stale-auth-state recovery path.
|
|
20108
|
+
*/
|
|
20109
|
+
async teardownSessionState() {
|
|
20110
|
+
await this.cleanupStoredConnectionParams();
|
|
20111
|
+
await this.attachManager.detachAll();
|
|
20112
|
+
}
|
|
19890
20113
|
async updateAuthState(authorization_state) {
|
|
19891
20114
|
try {
|
|
19892
20115
|
await this.storage.setItem(this.authorizationStateKey, authorization_state);
|
|
@@ -19981,7 +20204,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19981
20204
|
async disconnect() {
|
|
19982
20205
|
this.transport.disconnect();
|
|
19983
20206
|
this._authState$.next({ kind: "unauthenticated" });
|
|
19984
|
-
await this.
|
|
20207
|
+
await this.teardownSessionState();
|
|
19985
20208
|
}
|
|
19986
20209
|
async createInboundCall(invite) {
|
|
19987
20210
|
const callSession = await this.createCall({
|
|
@@ -20040,7 +20263,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
20040
20263
|
to: destinationURI,
|
|
20041
20264
|
...options
|
|
20042
20265
|
});
|
|
20043
|
-
await (0, import_cjs$7.firstValueFrom)((0, import_cjs$7.race)(callSession.selfId$.pipe((0, import_cjs$7.filter)((id) => Boolean(id)), (0, import_cjs$7.take)(1), (0, import_cjs$7.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, import_cjs$7.take)(1), (0, import_cjs$7.switchMap)((callError) => (0, import_cjs$7.throwError)(() => callError.error)))));
|
|
20266
|
+
await (0, import_cjs$7.firstValueFrom)((0, import_cjs$7.race)(callSession.selfId$.pipe((0, import_cjs$7.filter)((id) => Boolean(id)), (0, import_cjs$7.take)(1), (0, import_cjs$7.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, import_cjs$7.filter)(shouldAbortDial), (0, import_cjs$7.take)(1), (0, import_cjs$7.switchMap)((callError) => (0, import_cjs$7.throwError)(() => callError.error)))));
|
|
20044
20267
|
this._calls$.next({
|
|
20045
20268
|
[`${callSession.id}`]: callSession,
|
|
20046
20269
|
...this._calls$.value
|
|
@@ -21148,6 +21371,10 @@ var TransportManager = class extends Destroyable {
|
|
|
21148
21371
|
if (!isSignalwireRequest(message)) return true;
|
|
21149
21372
|
const eventChannel = message.params.event_channel;
|
|
21150
21373
|
if (!eventChannel) return true;
|
|
21374
|
+
if (message.params.event_type.startsWith("conversation.")) {
|
|
21375
|
+
logger$2.debug(`[Transport] Received conversation event: ${message.params.event_type} (event_channel: ${eventChannel})`);
|
|
21376
|
+
return true;
|
|
21377
|
+
}
|
|
21151
21378
|
const currentProtocol = this._currentProtocol;
|
|
21152
21379
|
if (!currentProtocol) return true;
|
|
21153
21380
|
if (!eventChannel.includes(currentProtocol)) {
|
|
@@ -21748,7 +21975,7 @@ var SignalWire = class extends Destroyable {
|
|
|
21748
21975
|
logger$1.warn("[SignalWire] Failed to initialize VisibilityController:", error);
|
|
21749
21976
|
}
|
|
21750
21977
|
try {
|
|
21751
|
-
this._diagnosticsCollector = new DiagnosticsCollector({ sdkVersion: "4.0.0-rc.
|
|
21978
|
+
this._diagnosticsCollector = new DiagnosticsCollector({ sdkVersion: "4.0.0-rc.2" });
|
|
21752
21979
|
} catch (error) {
|
|
21753
21980
|
logger$1.warn("[SignalWire] Failed to initialize DiagnosticsCollector:", error);
|
|
21754
21981
|
}
|
|
@@ -21756,6 +21983,14 @@ var SignalWire = class extends Destroyable {
|
|
|
21756
21983
|
/**
|
|
21757
21984
|
* Disconnects the WebSocket and tears down the current session.
|
|
21758
21985
|
*
|
|
21986
|
+
* Ends the session identified by the protocol and clears its persisted
|
|
21987
|
+
* resume state (`authorization_state` + protocol) and attach records
|
|
21988
|
+
* together — a later {@link connect} with the same credentials starts a
|
|
21989
|
+
* fresh session and cannot reattach to the ended session's calls.
|
|
21990
|
+
* Credentials and device preferences are preserved. To temporarily stop
|
|
21991
|
+
* receiving inbound calls while keeping the session alive, use
|
|
21992
|
+
* `unregister()` instead.
|
|
21993
|
+
*
|
|
21759
21994
|
* The client can be reconnected by calling {@link connect} again,
|
|
21760
21995
|
* which creates a fresh transport and session.
|
|
21761
21996
|
*/
|
|
@@ -22147,12 +22382,20 @@ var SignalWire = class extends Destroyable {
|
|
|
22147
22382
|
prefs.preferredVideoInput = null;
|
|
22148
22383
|
await this._deviceController.clearDeviceState();
|
|
22149
22384
|
}
|
|
22150
|
-
/**
|
|
22385
|
+
/**
|
|
22386
|
+
* Destroys the client, clearing timers and releasing all resources.
|
|
22387
|
+
*
|
|
22388
|
+
* Intentionally destroying the client ends its session: the resume state
|
|
22389
|
+
* (`authorization_state` + protocol) and the attach records are both
|
|
22390
|
+
* cleared. Credentials and device preferences are preserved — use
|
|
22391
|
+
* {@link resetToDefaults} for a full wipe. To temporarily stop receiving
|
|
22392
|
+
* inbound calls while keeping the session alive, use `unregister()`.
|
|
22393
|
+
*/
|
|
22151
22394
|
destroy() {
|
|
22152
22395
|
this._refreshCoordinator?.destroy();
|
|
22153
22396
|
this._refreshCoordinator = void 0;
|
|
22154
22397
|
this._dpopManager?.destroy();
|
|
22155
|
-
|
|
22398
|
+
this._clientSession.teardownSessionState();
|
|
22156
22399
|
this._transport.destroy();
|
|
22157
22400
|
this._clientSession.destroy();
|
|
22158
22401
|
try {
|
|
@@ -22267,7 +22510,7 @@ var StaticCredentialProvider = class {
|
|
|
22267
22510
|
/**
|
|
22268
22511
|
* Library version from package.json, injected at build time.
|
|
22269
22512
|
*/
|
|
22270
|
-
const version = "4.0.0-rc.
|
|
22513
|
+
const version = "4.0.0-rc.2";
|
|
22271
22514
|
/**
|
|
22272
22515
|
* Flag indicating the library has been loaded and is ready to use.
|
|
22273
22516
|
* For UMD builds: `window.SignalWire.ready`
|
|
@@ -22289,7 +22532,7 @@ const ready = true;
|
|
|
22289
22532
|
*/
|
|
22290
22533
|
const emitReadyEvent = () => {
|
|
22291
22534
|
if (typeof window !== "undefined") {
|
|
22292
|
-
const event = new CustomEvent("signalwire:js:ready", { detail: { version: "4.0.0-rc.
|
|
22535
|
+
const event = new CustomEvent("signalwire:js:ready", { detail: { version: "4.0.0-rc.2" } });
|
|
22293
22536
|
window.dispatchEvent(event);
|
|
22294
22537
|
}
|
|
22295
22538
|
};
|
|
@@ -22321,6 +22564,7 @@ exports.DPoPInitError = DPoPInitError;
|
|
|
22321
22564
|
exports.DeviceTokenError = DeviceTokenError;
|
|
22322
22565
|
exports.EmbedTokenCredentialProvider = EmbedTokenCredentialProvider;
|
|
22323
22566
|
exports.InvalidCredentialsError = InvalidCredentialsError;
|
|
22567
|
+
exports.MediaAccessError = MediaAccessError;
|
|
22324
22568
|
exports.MediaTrackError = MediaTrackError;
|
|
22325
22569
|
exports.MessageParseError = MessageParseError;
|
|
22326
22570
|
exports.OverconstrainedFallbackError = OverconstrainedFallbackError;
|