@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.mjs
CHANGED
|
@@ -9015,6 +9015,143 @@ var Destroyable = class {
|
|
|
9015
9015
|
}
|
|
9016
9016
|
};
|
|
9017
9017
|
|
|
9018
|
+
//#endregion
|
|
9019
|
+
//#region src/core/constants.ts
|
|
9020
|
+
const INVITE_VERSION = 1e3;
|
|
9021
|
+
const DEFAULT_ICE_CANDIDATE_TIMEOUT_MS = 600;
|
|
9022
|
+
const DEFAULT_ICE_GATHERING_TIMEOUT_MS = 6e3;
|
|
9023
|
+
const DEFAULT_RECONNECT_CALLS_TIMEOUT_MS = 300 * 1e3;
|
|
9024
|
+
const DEFAULT_CONNECTION_TIMEOUT_MS = 1e4;
|
|
9025
|
+
const DEFAULT_RECONNECT_DELAY_MIN_MS = 100;
|
|
9026
|
+
const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
|
|
9027
|
+
const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
|
|
9028
|
+
const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
|
|
9029
|
+
const PREFERENCES_STORAGE_KEY = "sw:preferences";
|
|
9030
|
+
/** Scope value that enables automatic token refresh. */
|
|
9031
|
+
const SAT_REFRESH_SCOPE = "sat:refresh";
|
|
9032
|
+
/** API endpoints for device token operations. */
|
|
9033
|
+
const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
|
|
9034
|
+
const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
|
|
9035
|
+
/** Default device token TTL in seconds (15 minutes). */
|
|
9036
|
+
const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
|
|
9037
|
+
/** Buffer time in milliseconds before expiry to trigger refresh. */
|
|
9038
|
+
const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
|
|
9039
|
+
/** Maximum retry attempts for device token refresh on transient failure. */
|
|
9040
|
+
const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
|
|
9041
|
+
/** Base delay in milliseconds for exponential backoff on refresh retry. */
|
|
9042
|
+
const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9043
|
+
/** Maximum retry attempts for developer credential refresh on transient failure. */
|
|
9044
|
+
const CREDENTIAL_REFRESH_MAX_RETRIES = 5;
|
|
9045
|
+
/** Base delay in milliseconds for exponential backoff on credential refresh retry. */
|
|
9046
|
+
const CREDENTIAL_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9047
|
+
/** Maximum delay in milliseconds for credential refresh backoff. */
|
|
9048
|
+
const CREDENTIAL_REFRESH_MAX_DELAY_MS = 3e4;
|
|
9049
|
+
/** Buffer in milliseconds before token expiry to trigger refresh. */
|
|
9050
|
+
const CREDENTIAL_REFRESH_BUFFER_MS = 5e3;
|
|
9051
|
+
/**
|
|
9052
|
+
* Maximum time the coordinator will wait for `DeviceTokenManager.activate()`
|
|
9053
|
+
* to resolve before treating the activation as failed and falling back to
|
|
9054
|
+
* the developer-provided refresh path. Prevents a wedged HTTP layer from
|
|
9055
|
+
* leaving the session with no active refresh mechanism.
|
|
9056
|
+
*/
|
|
9057
|
+
const CREDENTIAL_ACTIVATE_TIMEOUT_MS = 3e4;
|
|
9058
|
+
/** JSON-RPC error code for requester validation failure (corrupted auth state). */
|
|
9059
|
+
const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
|
|
9060
|
+
/** JSON-RPC error code for invalid params (e.g., missing authentication block). */
|
|
9061
|
+
const RPC_ERROR_INVALID_PARAMS = -32602;
|
|
9062
|
+
/** JSON-RPC error code for authentication failure (invalid token, missing DPoP, etc.). */
|
|
9063
|
+
const RPC_ERROR_AUTHENTICATION_FAILED = -32002;
|
|
9064
|
+
/** Error names browsers use for a media permission denial (user or policy). */
|
|
9065
|
+
const MEDIA_ACCESS_DENIAL_NAMES = [
|
|
9066
|
+
"NotAllowedError",
|
|
9067
|
+
"SecurityError",
|
|
9068
|
+
"PermissionDeniedError"
|
|
9069
|
+
];
|
|
9070
|
+
/** Default polling interval for RTCPeerConnection.getStats() in milliseconds. */
|
|
9071
|
+
const DEFAULT_STATS_POLLING_INTERVAL_MS = 1e3;
|
|
9072
|
+
/** Number of initial samples used to build a baseline for spike detection. */
|
|
9073
|
+
const DEFAULT_STATS_BASELINE_SAMPLES = 10;
|
|
9074
|
+
/** Duration in ms with no inbound audio packets before emitting a critical issue. */
|
|
9075
|
+
const DEFAULT_STATS_NO_PACKET_THRESHOLD_MS = 2e3;
|
|
9076
|
+
/** Multiplier applied to baseline RTT to detect a warning-level RTT spike. */
|
|
9077
|
+
const DEFAULT_STATS_RTT_SPIKE_MULTIPLIER = 3;
|
|
9078
|
+
/** Packet loss fraction (0-1) above which a warning is emitted. */
|
|
9079
|
+
const DEFAULT_STATS_PACKET_LOSS_THRESHOLD = .05;
|
|
9080
|
+
/** Multiplier applied to baseline jitter to detect a jitter spike. */
|
|
9081
|
+
const DEFAULT_STATS_JITTER_SPIKE_MULTIPLIER = 4;
|
|
9082
|
+
/** Number of seconds of metrics history to retain. */
|
|
9083
|
+
const DEFAULT_STATS_HISTORY_SIZE = 30;
|
|
9084
|
+
/** Maximum keyframe requests allowed within a single burst window. */
|
|
9085
|
+
const DEFAULT_KEYFRAME_MAX_BURST$1 = 3;
|
|
9086
|
+
/** Duration of the keyframe burst window in milliseconds. */
|
|
9087
|
+
const DEFAULT_KEYFRAME_BURST_WINDOW_MS$1 = 3e3;
|
|
9088
|
+
/** Cooldown period in ms after burst limit is reached before allowing more keyframes. */
|
|
9089
|
+
const DEFAULT_KEYFRAME_COOLDOWN_MS$1 = 1e4;
|
|
9090
|
+
/** Minimum time between re-INVITE attempts in milliseconds. */
|
|
9091
|
+
const DEFAULT_REINVITE_DEBOUNCE_TIME_MS = 1e4;
|
|
9092
|
+
/** Maximum number of re-INVITE attempts per call. */
|
|
9093
|
+
const DEFAULT_REINVITE_MAX_ATTEMPTS = 3;
|
|
9094
|
+
/** Timeout for a single re-INVITE attempt in milliseconds. */
|
|
9095
|
+
const DEFAULT_REINVITE_TIMEOUT_MS = 5e3;
|
|
9096
|
+
/** Debounce window in ms to collapse multiple detection signals into one trigger. */
|
|
9097
|
+
const DEFAULT_RECOVERY_DEBOUNCE_TIME_MS = 2e3;
|
|
9098
|
+
/** Cooldown period in ms between recovery attempts. */
|
|
9099
|
+
const DEFAULT_RECOVERY_COOLDOWN_MS = 1e4;
|
|
9100
|
+
/** Grace period in ms before treating ICE 'disconnected' as a failure. */
|
|
9101
|
+
const DEFAULT_ICE_DISCONNECTED_GRACE_PERIOD_MS = 3e3;
|
|
9102
|
+
/** Timeout for a single ICE restart attempt in milliseconds. */
|
|
9103
|
+
const DEFAULT_ICE_RESTART_TIMEOUT_MS$1 = 5e3;
|
|
9104
|
+
/** Maximum recovery attempts before emitting 'max_attempts_reached'. */
|
|
9105
|
+
const DEFAULT_MAX_RECOVERY_ATTEMPTS = 3;
|
|
9106
|
+
/** Upper bound in ms for waiting on iceGatheringState === 'complete' after an ICE restart. */
|
|
9107
|
+
const ICE_GATHERING_COMPLETE_TIMEOUT_MS = 1e4;
|
|
9108
|
+
/** Upper bound in ms for waiting on RTCPeerConnection.connectionState === 'connected' after a recovery ICE restart. */
|
|
9109
|
+
const PEER_CONNECTION_RECOVERY_WAIT_MS = 5e3;
|
|
9110
|
+
/** Polling interval in ms while waiting for RTCPeerConnection.connectionState to transition. */
|
|
9111
|
+
const PEER_CONNECTION_RECOVERY_POLL_MS = 100;
|
|
9112
|
+
/** Polling interval for LocalAudioPipeline.level$ (ms). ~30fps is smooth for meters. */
|
|
9113
|
+
const AUDIO_LEVEL_POLL_INTERVAL_MS = 33;
|
|
9114
|
+
/** RMS level threshold (0..1) above which the local participant is considered speaking. */
|
|
9115
|
+
const VAD_THRESHOLD = .03;
|
|
9116
|
+
/** Hold window in ms below the threshold before speaking$ flips back to false. */
|
|
9117
|
+
const VAD_HOLD_MS = 250;
|
|
9118
|
+
/** Whether to persist device selections to storage by default. */
|
|
9119
|
+
const DEFAULT_PERSIST_DEVICE_SELECTION = true;
|
|
9120
|
+
/** Whether to auto-apply device changes to active calls by default. */
|
|
9121
|
+
const DEFAULT_SYNC_DEVICES_TO_ACTIVE_CALLS = true;
|
|
9122
|
+
/** Storage keys for persisted device selections. */
|
|
9123
|
+
const DEVICE_STORAGE_KEY_AUDIO_INPUT = "sw:device:audioinput";
|
|
9124
|
+
const DEVICE_STORAGE_KEY_AUDIO_OUTPUT = "sw:device:audiooutput";
|
|
9125
|
+
const DEVICE_STORAGE_KEY_VIDEO_INPUT = "sw:device:videoinput";
|
|
9126
|
+
/** Whether to auto-mute video when the tab becomes hidden. */
|
|
9127
|
+
const DEFAULT_AUTO_MUTE_VIDEO_ON_HIDDEN = false;
|
|
9128
|
+
/** Whether to re-enumerate devices when the page becomes visible. */
|
|
9129
|
+
const DEFAULT_REFRESH_DEVICES_ON_VISIBLE = true;
|
|
9130
|
+
/** Whether to check peer connection health when the page becomes visible. */
|
|
9131
|
+
const DEFAULT_CHECK_CONNECTION_ON_VISIBLE = true;
|
|
9132
|
+
/** Whether automatic video degradation on low bandwidth is enabled. */
|
|
9133
|
+
const DEFAULT_ENABLE_AUTO_DEGRADATION = true;
|
|
9134
|
+
/** Bitrate in kbps below which video is automatically disabled. */
|
|
9135
|
+
const DEFAULT_DEGRADATION_BITRATE_THRESHOLD_KBPS = 150;
|
|
9136
|
+
/** Bitrate in kbps above which video is automatically re-enabled (hysteresis). */
|
|
9137
|
+
const DEFAULT_DEGRADATION_RECOVERY_THRESHOLD_KBPS = 300;
|
|
9138
|
+
/** Whether relay-only escalation is enabled as a last-resort recovery tier. */
|
|
9139
|
+
const DEFAULT_ENABLE_RELAY_FALLBACK = true;
|
|
9140
|
+
/** Whether to listen for browser online/offline/connection events. */
|
|
9141
|
+
const DEFAULT_ENABLE_NETWORK_CHANGE_DETECTION = true;
|
|
9142
|
+
/** Whether to intercept server-sent media-timeout hangups and attempt recovery. */
|
|
9143
|
+
const DEFAULT_ENABLE_SERVER_HANGUP_INTERCEPTION = true;
|
|
9144
|
+
/** Default video track constraints applied when video is enabled without explicit constraints. */
|
|
9145
|
+
const DEFAULT_VIDEO_CONSTRAINTS = {
|
|
9146
|
+
width: { ideal: 1280 },
|
|
9147
|
+
height: { ideal: 720 },
|
|
9148
|
+
aspectRatio: 16 / 9
|
|
9149
|
+
};
|
|
9150
|
+
/** Whether stereo Opus is enabled by default. */
|
|
9151
|
+
const DEFAULT_STEREO_AUDIO = false;
|
|
9152
|
+
/** Max average bitrate for stereo Opus in bits per second. */
|
|
9153
|
+
const DEFAULT_STEREO_MAX_AVERAGE_BITRATE = 51e4;
|
|
9154
|
+
|
|
9018
9155
|
//#endregion
|
|
9019
9156
|
//#region src/core/errors.ts
|
|
9020
9157
|
var UnexpectedError = class extends Error {
|
|
@@ -9224,6 +9361,33 @@ var MediaTrackError = class extends Error {
|
|
|
9224
9361
|
this.name = "MediaTrackError";
|
|
9225
9362
|
}
|
|
9226
9363
|
};
|
|
9364
|
+
/** True when a `getUserMedia`/`getDisplayMedia` rejection is a permission denial. */
|
|
9365
|
+
function isMediaAccessDenial(originalError) {
|
|
9366
|
+
return originalError instanceof Error && MEDIA_ACCESS_DENIAL_NAMES.includes(originalError.name);
|
|
9367
|
+
}
|
|
9368
|
+
/**
|
|
9369
|
+
* Failure to acquire local media (camera, microphone, or screen capture)
|
|
9370
|
+
* via `getUserMedia`/`getDisplayMedia`.
|
|
9371
|
+
*
|
|
9372
|
+
* Non-fatal by default: screenshare and additional-device failures never
|
|
9373
|
+
* end the call, and main-connection failures degrade to receive-only when
|
|
9374
|
+
* possible. The wrapping site sets `fatal` to `true` only when the call
|
|
9375
|
+
* cannot continue (receive-only fallback disabled or no receive intent).
|
|
9376
|
+
*/
|
|
9377
|
+
var MediaAccessError = class extends Error {
|
|
9378
|
+
constructor(operation, media, originalError, fatal = false) {
|
|
9379
|
+
super(`Media access ${isMediaAccessDenial(originalError) ? "denied" : "failed"} for ${operation} (${media})`, { cause: originalError instanceof Error ? originalError : void 0 });
|
|
9380
|
+
this.operation = operation;
|
|
9381
|
+
this.media = media;
|
|
9382
|
+
this.originalError = originalError;
|
|
9383
|
+
this.fatal = fatal;
|
|
9384
|
+
this.name = "MediaAccessError";
|
|
9385
|
+
}
|
|
9386
|
+
/** True when the underlying failure is a permission denial (user or policy). */
|
|
9387
|
+
get denied() {
|
|
9388
|
+
return isMediaAccessDenial(this.originalError);
|
|
9389
|
+
}
|
|
9390
|
+
};
|
|
9227
9391
|
var DPoPInitError = class extends Error {
|
|
9228
9392
|
constructor(originalError, message = "Failed to initialize DPoP key pair") {
|
|
9229
9393
|
super(message, { cause: originalError instanceof Error ? originalError : void 0 });
|
|
@@ -9873,137 +10037,6 @@ var DeviceHistoryManager = class {
|
|
|
9873
10037
|
}
|
|
9874
10038
|
};
|
|
9875
10039
|
|
|
9876
|
-
//#endregion
|
|
9877
|
-
//#region src/core/constants.ts
|
|
9878
|
-
const INVITE_VERSION = 1e3;
|
|
9879
|
-
const DEFAULT_ICE_CANDIDATE_TIMEOUT_MS = 600;
|
|
9880
|
-
const DEFAULT_ICE_GATHERING_TIMEOUT_MS = 6e3;
|
|
9881
|
-
const DEFAULT_RECONNECT_CALLS_TIMEOUT_MS = 300 * 1e3;
|
|
9882
|
-
const DEFAULT_CONNECTION_TIMEOUT_MS = 1e4;
|
|
9883
|
-
const DEFAULT_RECONNECT_DELAY_MIN_MS = 100;
|
|
9884
|
-
const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
|
|
9885
|
-
const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
|
|
9886
|
-
const DEFAULT_DEVICE_POLLING_INTERVAL_MS = 0;
|
|
9887
|
-
const PREFERENCES_STORAGE_KEY = "sw:preferences";
|
|
9888
|
-
/** Scope value that enables automatic token refresh. */
|
|
9889
|
-
const SAT_REFRESH_SCOPE = "sat:refresh";
|
|
9890
|
-
/** API endpoints for device token operations. */
|
|
9891
|
-
const DEVICE_TOKEN_ENDPOINT = "/api/fabric/subscriber/devices/token";
|
|
9892
|
-
const DEVICE_REFRESH_ENDPOINT = "/api/fabric/subscriber/devices/refresh";
|
|
9893
|
-
/** Default device token TTL in seconds (15 minutes). */
|
|
9894
|
-
const DEVICE_TOKEN_DEFAULT_EXPIRE_IN = 900;
|
|
9895
|
-
/** Buffer time in milliseconds before expiry to trigger refresh. */
|
|
9896
|
-
const DEVICE_TOKEN_REFRESH_BUFFER_MS = 3e4;
|
|
9897
|
-
/** Maximum retry attempts for device token refresh on transient failure. */
|
|
9898
|
-
const DEVICE_TOKEN_REFRESH_MAX_RETRIES = 3;
|
|
9899
|
-
/** Base delay in milliseconds for exponential backoff on refresh retry. */
|
|
9900
|
-
const DEVICE_TOKEN_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9901
|
-
/** Maximum retry attempts for developer credential refresh on transient failure. */
|
|
9902
|
-
const CREDENTIAL_REFRESH_MAX_RETRIES = 5;
|
|
9903
|
-
/** Base delay in milliseconds for exponential backoff on credential refresh retry. */
|
|
9904
|
-
const CREDENTIAL_REFRESH_RETRY_BASE_MS = 1e3;
|
|
9905
|
-
/** Maximum delay in milliseconds for credential refresh backoff. */
|
|
9906
|
-
const CREDENTIAL_REFRESH_MAX_DELAY_MS = 3e4;
|
|
9907
|
-
/** Buffer in milliseconds before token expiry to trigger refresh. */
|
|
9908
|
-
const CREDENTIAL_REFRESH_BUFFER_MS = 5e3;
|
|
9909
|
-
/**
|
|
9910
|
-
* Maximum time the coordinator will wait for `DeviceTokenManager.activate()`
|
|
9911
|
-
* to resolve before treating the activation as failed and falling back to
|
|
9912
|
-
* the developer-provided refresh path. Prevents a wedged HTTP layer from
|
|
9913
|
-
* leaving the session with no active refresh mechanism.
|
|
9914
|
-
*/
|
|
9915
|
-
const CREDENTIAL_ACTIVATE_TIMEOUT_MS = 3e4;
|
|
9916
|
-
/** JSON-RPC error code for requester validation failure (corrupted auth state). */
|
|
9917
|
-
const RPC_ERROR_REQUESTER_VALIDATION_FAILED = -32003;
|
|
9918
|
-
/** JSON-RPC error code for invalid params (e.g., missing authentication block). */
|
|
9919
|
-
const RPC_ERROR_INVALID_PARAMS = -32602;
|
|
9920
|
-
/** JSON-RPC error code for authentication failure (invalid token, missing DPoP, etc.). */
|
|
9921
|
-
const RPC_ERROR_AUTHENTICATION_FAILED = -32002;
|
|
9922
|
-
/** Default polling interval for RTCPeerConnection.getStats() in milliseconds. */
|
|
9923
|
-
const DEFAULT_STATS_POLLING_INTERVAL_MS = 1e3;
|
|
9924
|
-
/** Number of initial samples used to build a baseline for spike detection. */
|
|
9925
|
-
const DEFAULT_STATS_BASELINE_SAMPLES = 10;
|
|
9926
|
-
/** Duration in ms with no inbound audio packets before emitting a critical issue. */
|
|
9927
|
-
const DEFAULT_STATS_NO_PACKET_THRESHOLD_MS = 2e3;
|
|
9928
|
-
/** Multiplier applied to baseline RTT to detect a warning-level RTT spike. */
|
|
9929
|
-
const DEFAULT_STATS_RTT_SPIKE_MULTIPLIER = 3;
|
|
9930
|
-
/** Packet loss fraction (0-1) above which a warning is emitted. */
|
|
9931
|
-
const DEFAULT_STATS_PACKET_LOSS_THRESHOLD = .05;
|
|
9932
|
-
/** Multiplier applied to baseline jitter to detect a jitter spike. */
|
|
9933
|
-
const DEFAULT_STATS_JITTER_SPIKE_MULTIPLIER = 4;
|
|
9934
|
-
/** Number of seconds of metrics history to retain. */
|
|
9935
|
-
const DEFAULT_STATS_HISTORY_SIZE = 30;
|
|
9936
|
-
/** Maximum keyframe requests allowed within a single burst window. */
|
|
9937
|
-
const DEFAULT_KEYFRAME_MAX_BURST$1 = 3;
|
|
9938
|
-
/** Duration of the keyframe burst window in milliseconds. */
|
|
9939
|
-
const DEFAULT_KEYFRAME_BURST_WINDOW_MS$1 = 3e3;
|
|
9940
|
-
/** Cooldown period in ms after burst limit is reached before allowing more keyframes. */
|
|
9941
|
-
const DEFAULT_KEYFRAME_COOLDOWN_MS$1 = 1e4;
|
|
9942
|
-
/** Minimum time between re-INVITE attempts in milliseconds. */
|
|
9943
|
-
const DEFAULT_REINVITE_DEBOUNCE_TIME_MS = 1e4;
|
|
9944
|
-
/** Maximum number of re-INVITE attempts per call. */
|
|
9945
|
-
const DEFAULT_REINVITE_MAX_ATTEMPTS = 3;
|
|
9946
|
-
/** Timeout for a single re-INVITE attempt in milliseconds. */
|
|
9947
|
-
const DEFAULT_REINVITE_TIMEOUT_MS = 5e3;
|
|
9948
|
-
/** Debounce window in ms to collapse multiple detection signals into one trigger. */
|
|
9949
|
-
const DEFAULT_RECOVERY_DEBOUNCE_TIME_MS = 2e3;
|
|
9950
|
-
/** Cooldown period in ms between recovery attempts. */
|
|
9951
|
-
const DEFAULT_RECOVERY_COOLDOWN_MS = 1e4;
|
|
9952
|
-
/** Grace period in ms before treating ICE 'disconnected' as a failure. */
|
|
9953
|
-
const DEFAULT_ICE_DISCONNECTED_GRACE_PERIOD_MS = 3e3;
|
|
9954
|
-
/** Timeout for a single ICE restart attempt in milliseconds. */
|
|
9955
|
-
const DEFAULT_ICE_RESTART_TIMEOUT_MS$1 = 5e3;
|
|
9956
|
-
/** Maximum recovery attempts before emitting 'max_attempts_reached'. */
|
|
9957
|
-
const DEFAULT_MAX_RECOVERY_ATTEMPTS = 3;
|
|
9958
|
-
/** Upper bound in ms for waiting on iceGatheringState === 'complete' after an ICE restart. */
|
|
9959
|
-
const ICE_GATHERING_COMPLETE_TIMEOUT_MS = 1e4;
|
|
9960
|
-
/** Upper bound in ms for waiting on RTCPeerConnection.connectionState === 'connected' after a recovery ICE restart. */
|
|
9961
|
-
const PEER_CONNECTION_RECOVERY_WAIT_MS = 5e3;
|
|
9962
|
-
/** Polling interval in ms while waiting for RTCPeerConnection.connectionState to transition. */
|
|
9963
|
-
const PEER_CONNECTION_RECOVERY_POLL_MS = 100;
|
|
9964
|
-
/** Polling interval for LocalAudioPipeline.level$ (ms). ~30fps is smooth for meters. */
|
|
9965
|
-
const AUDIO_LEVEL_POLL_INTERVAL_MS = 33;
|
|
9966
|
-
/** RMS level threshold (0..1) above which the local participant is considered speaking. */
|
|
9967
|
-
const VAD_THRESHOLD = .03;
|
|
9968
|
-
/** Hold window in ms below the threshold before speaking$ flips back to false. */
|
|
9969
|
-
const VAD_HOLD_MS = 250;
|
|
9970
|
-
/** Whether to persist device selections to storage by default. */
|
|
9971
|
-
const DEFAULT_PERSIST_DEVICE_SELECTION = true;
|
|
9972
|
-
/** Whether to auto-apply device changes to active calls by default. */
|
|
9973
|
-
const DEFAULT_SYNC_DEVICES_TO_ACTIVE_CALLS = true;
|
|
9974
|
-
/** Storage keys for persisted device selections. */
|
|
9975
|
-
const DEVICE_STORAGE_KEY_AUDIO_INPUT = "sw:device:audioinput";
|
|
9976
|
-
const DEVICE_STORAGE_KEY_AUDIO_OUTPUT = "sw:device:audiooutput";
|
|
9977
|
-
const DEVICE_STORAGE_KEY_VIDEO_INPUT = "sw:device:videoinput";
|
|
9978
|
-
/** Whether to auto-mute video when the tab becomes hidden. */
|
|
9979
|
-
const DEFAULT_AUTO_MUTE_VIDEO_ON_HIDDEN = false;
|
|
9980
|
-
/** Whether to re-enumerate devices when the page becomes visible. */
|
|
9981
|
-
const DEFAULT_REFRESH_DEVICES_ON_VISIBLE = true;
|
|
9982
|
-
/** Whether to check peer connection health when the page becomes visible. */
|
|
9983
|
-
const DEFAULT_CHECK_CONNECTION_ON_VISIBLE = true;
|
|
9984
|
-
/** Whether automatic video degradation on low bandwidth is enabled. */
|
|
9985
|
-
const DEFAULT_ENABLE_AUTO_DEGRADATION = true;
|
|
9986
|
-
/** Bitrate in kbps below which video is automatically disabled. */
|
|
9987
|
-
const DEFAULT_DEGRADATION_BITRATE_THRESHOLD_KBPS = 150;
|
|
9988
|
-
/** Bitrate in kbps above which video is automatically re-enabled (hysteresis). */
|
|
9989
|
-
const DEFAULT_DEGRADATION_RECOVERY_THRESHOLD_KBPS = 300;
|
|
9990
|
-
/** Whether relay-only escalation is enabled as a last-resort recovery tier. */
|
|
9991
|
-
const DEFAULT_ENABLE_RELAY_FALLBACK = true;
|
|
9992
|
-
/** Whether to listen for browser online/offline/connection events. */
|
|
9993
|
-
const DEFAULT_ENABLE_NETWORK_CHANGE_DETECTION = true;
|
|
9994
|
-
/** Whether to intercept server-sent media-timeout hangups and attempt recovery. */
|
|
9995
|
-
const DEFAULT_ENABLE_SERVER_HANGUP_INTERCEPTION = true;
|
|
9996
|
-
/** Default video track constraints applied when video is enabled without explicit constraints. */
|
|
9997
|
-
const DEFAULT_VIDEO_CONSTRAINTS = {
|
|
9998
|
-
width: { ideal: 1280 },
|
|
9999
|
-
height: { ideal: 720 },
|
|
10000
|
-
aspectRatio: 16 / 9
|
|
10001
|
-
};
|
|
10002
|
-
/** Whether stereo Opus is enabled by default. */
|
|
10003
|
-
const DEFAULT_STEREO_AUDIO = false;
|
|
10004
|
-
/** Max average bitrate for stereo Opus in bits per second. */
|
|
10005
|
-
const DEFAULT_STEREO_MAX_AVERAGE_BITRATE = 51e4;
|
|
10006
|
-
|
|
10007
10040
|
//#endregion
|
|
10008
10041
|
//#region src/utils/time.ts
|
|
10009
10042
|
function fromSecToMs(seconds) {
|
|
@@ -13367,7 +13400,9 @@ const DEFAULT_MEMBER_CAPABILITIES = {
|
|
|
13367
13400
|
position: false,
|
|
13368
13401
|
meta: false,
|
|
13369
13402
|
remove: false,
|
|
13370
|
-
audioFlags: false
|
|
13403
|
+
audioFlags: false,
|
|
13404
|
+
denoise: false,
|
|
13405
|
+
lowbitrate: false
|
|
13371
13406
|
};
|
|
13372
13407
|
/**
|
|
13373
13408
|
* Default call capabilities with no permissions
|
|
@@ -13440,7 +13475,9 @@ function computeMemberCapabilities(flags, memberType) {
|
|
|
13440
13475
|
position: hasBooleanCapability(flags, memberType, null, "position"),
|
|
13441
13476
|
meta: hasBooleanCapability(flags, memberType, null, "meta"),
|
|
13442
13477
|
remove: hasBooleanCapability(flags, memberType, null, "remove"),
|
|
13443
|
-
audioFlags: hasBooleanCapability(flags, memberType, null, "audioflags")
|
|
13478
|
+
audioFlags: hasBooleanCapability(flags, memberType, null, "audioflags"),
|
|
13479
|
+
denoise: hasBooleanCapability(flags, memberType, null, "denoise"),
|
|
13480
|
+
lowbitrate: hasBooleanCapability(flags, memberType, null, "lowbitrate")
|
|
13444
13481
|
};
|
|
13445
13482
|
}
|
|
13446
13483
|
/**
|
|
@@ -13823,6 +13860,10 @@ var Participant = class extends Destroyable {
|
|
|
13823
13860
|
get nodeId() {
|
|
13824
13861
|
return this._state$.value.node_id;
|
|
13825
13862
|
}
|
|
13863
|
+
/** Call ID for this participant's leg, or `undefined` if not available. */
|
|
13864
|
+
get callId() {
|
|
13865
|
+
return this._state$.value.call_id;
|
|
13866
|
+
}
|
|
13826
13867
|
/** @internal */
|
|
13827
13868
|
get value() {
|
|
13828
13869
|
return this._state$.value;
|
|
@@ -13884,8 +13925,9 @@ var Participant = class extends Destroyable {
|
|
|
13884
13925
|
noise_suppression: !this.noiseSuppression
|
|
13885
13926
|
});
|
|
13886
13927
|
}
|
|
13928
|
+
/** Toggles low-bitrate mode for this participant's media. */
|
|
13887
13929
|
async toggleLowbitrate() {
|
|
13888
|
-
|
|
13930
|
+
await this.executeMethod(this.id, "call.lowbitrate.set", { lowbitrate: !this.lowbitrate });
|
|
13889
13931
|
}
|
|
13890
13932
|
/**
|
|
13891
13933
|
* Adjusts the **conference-only** microphone energy gate / sensitivity level
|
|
@@ -13932,10 +13974,27 @@ var Participant = class extends Destroyable {
|
|
|
13932
13974
|
}
|
|
13933
13975
|
/**
|
|
13934
13976
|
* Sets the participant's position in the video layout.
|
|
13977
|
+
*
|
|
13978
|
+
* Requires the `member.position` capability. The gateway keys positions by the
|
|
13979
|
+
* **target member's own** `call_id`/`node_id` (see issue #19400 and the legacy
|
|
13980
|
+
* `setPositions` implementation), so this sends the participant's own call
|
|
13981
|
+
* context — matching {@link Participant.remove}. A resolved promise does not
|
|
13982
|
+
* guarantee a visible change: the backend silently returns `200` (no-op) for
|
|
13983
|
+
* non-conference targets.
|
|
13984
|
+
*
|
|
13935
13985
|
* @param value - The {@link VideoPosition} to assign (e.g. `'auto'`, `'reserved-0'`).
|
|
13936
13986
|
*/
|
|
13937
13987
|
async setPosition(value) {
|
|
13938
|
-
|
|
13988
|
+
const state = this._state$.value;
|
|
13989
|
+
const target = {
|
|
13990
|
+
member_id: this.id,
|
|
13991
|
+
call_id: state.call_id ?? "",
|
|
13992
|
+
node_id: state.node_id ?? ""
|
|
13993
|
+
};
|
|
13994
|
+
await this.executeMethod(target, "call.member.position.set", { targets: [{
|
|
13995
|
+
target,
|
|
13996
|
+
position: value
|
|
13997
|
+
}] });
|
|
13939
13998
|
}
|
|
13940
13999
|
/** Removes this participant from the call. */
|
|
13941
14000
|
async remove() {
|
|
@@ -14025,12 +14084,21 @@ var SelfParticipant = class extends Participant {
|
|
|
14025
14084
|
noise_suppression: true
|
|
14026
14085
|
});
|
|
14027
14086
|
}
|
|
14028
|
-
/**
|
|
14087
|
+
/**
|
|
14088
|
+
* Starts sharing the local screen.
|
|
14089
|
+
*
|
|
14090
|
+
* The call is unaffected when acquisition fails.
|
|
14091
|
+
*
|
|
14092
|
+
* @throws The raw `getDisplayMedia` error. A dismissed picker or a
|
|
14093
|
+
* permission denial rejects with a `NotAllowedError` `DOMException` —
|
|
14094
|
+
* inspect `error.name` to tell benign cancels apart from real failures.
|
|
14095
|
+
*/
|
|
14029
14096
|
async startScreenShare() {
|
|
14030
14097
|
try {
|
|
14031
14098
|
await this.vertoManager.addScreenMedia();
|
|
14032
14099
|
} catch (error) {
|
|
14033
14100
|
logger$24.error("[Participant.startScreenShare] Screen share error:", error);
|
|
14101
|
+
throw error;
|
|
14034
14102
|
}
|
|
14035
14103
|
}
|
|
14036
14104
|
/** Observable of the current screen share status. */
|
|
@@ -14045,12 +14113,20 @@ var SelfParticipant = class extends Participant {
|
|
|
14045
14113
|
async stopScreenShare() {
|
|
14046
14114
|
return this.vertoManager.removeScreenMedia();
|
|
14047
14115
|
}
|
|
14048
|
-
/**
|
|
14116
|
+
/**
|
|
14117
|
+
* Adds an additional media input device to the call.
|
|
14118
|
+
*
|
|
14119
|
+
* The call is unaffected when acquisition fails.
|
|
14120
|
+
*
|
|
14121
|
+
* @throws The raw `getUserMedia` error (e.g. `NotAllowedError` on
|
|
14122
|
+
* permission denial) — inspect `error.name` to decide how to react.
|
|
14123
|
+
*/
|
|
14049
14124
|
async addAdditionalDevice(options) {
|
|
14050
14125
|
try {
|
|
14051
14126
|
await this.vertoManager.addInputDevice(options);
|
|
14052
14127
|
} catch (error) {
|
|
14053
|
-
logger$24.error("[Participant.
|
|
14128
|
+
logger$24.error("[Participant.addAdditionalDevice] Additional device error:", error);
|
|
14129
|
+
throw error;
|
|
14054
14130
|
}
|
|
14055
14131
|
}
|
|
14056
14132
|
/** Removes an additional media input device by ID. */
|
|
@@ -15682,7 +15758,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15682
15758
|
logger$17.debug(`[RTCPeerConnectionController] ${kind} input device selected:`, deviceInfo?.label);
|
|
15683
15759
|
} catch (error) {
|
|
15684
15760
|
logger$17.error(`[RTCPeerConnectionController] Failed to select ${kind} input device:`, error);
|
|
15685
|
-
this._errors$.next(
|
|
15761
|
+
this._errors$.next(new MediaTrackError("updateSelectedInputDevice", kind, error));
|
|
15686
15762
|
throw error;
|
|
15687
15763
|
}
|
|
15688
15764
|
};
|
|
@@ -15904,7 +15980,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15904
15980
|
case "main":
|
|
15905
15981
|
default: return {
|
|
15906
15982
|
...options,
|
|
15907
|
-
offerToReceiveAudio: true,
|
|
15983
|
+
offerToReceiveAudio: this.options.receiveAudio ?? true,
|
|
15908
15984
|
offerToReceiveVideo: this.options.receiveVideo ?? Boolean(this.inputVideoDeviceConstraints)
|
|
15909
15985
|
};
|
|
15910
15986
|
}
|
|
@@ -16058,13 +16134,14 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16058
16134
|
*/
|
|
16059
16135
|
async acceptInbound(mediaOverrides) {
|
|
16060
16136
|
if (mediaOverrides) {
|
|
16061
|
-
const { audio, video, receiveAudio, receiveVideo } = mediaOverrides;
|
|
16137
|
+
const { audio, video, receiveAudio, receiveVideo, fallbackToReceiveOnly } = mediaOverrides;
|
|
16062
16138
|
this.options = {
|
|
16063
16139
|
...this.options,
|
|
16064
16140
|
...audio !== void 0 ? { audio } : {},
|
|
16065
16141
|
...video !== void 0 ? { video } : {},
|
|
16066
16142
|
...receiveAudio !== void 0 ? { receiveAudio } : {},
|
|
16067
|
-
...receiveVideo !== void 0 ? { receiveVideo } : {}
|
|
16143
|
+
...receiveVideo !== void 0 ? { receiveVideo } : {},
|
|
16144
|
+
...fallbackToReceiveOnly !== void 0 ? { fallbackToReceiveOnly } : {}
|
|
16068
16145
|
};
|
|
16069
16146
|
this.transceiverController?.updateOptions({
|
|
16070
16147
|
receiveAudio: this.receiveAudio,
|
|
@@ -16221,7 +16298,19 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16221
16298
|
}
|
|
16222
16299
|
async setupLocalTracks() {
|
|
16223
16300
|
logger$17.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
16224
|
-
|
|
16301
|
+
if (this.hasNoLocalMediaToSend()) {
|
|
16302
|
+
if (!this.receiveAudio && !this.receiveVideo) throw new InvalidParams("Call requests no media: enable audio/video or receiveAudio/receiveVideo");
|
|
16303
|
+
logger$17.debug("[RTCPeerConnectionController] No local media requested; negotiating receive-only.");
|
|
16304
|
+
this.setupReceiveOnlyTransceivers();
|
|
16305
|
+
return;
|
|
16306
|
+
}
|
|
16307
|
+
let localStream;
|
|
16308
|
+
try {
|
|
16309
|
+
localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
16310
|
+
} catch (error) {
|
|
16311
|
+
this.handleLocalMediaFailure(error);
|
|
16312
|
+
return;
|
|
16313
|
+
}
|
|
16225
16314
|
if (this.transceiverController?.useAddStream ?? false) {
|
|
16226
16315
|
logger$17.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
16227
16316
|
this.peerConnection?.addStream(localStream);
|
|
@@ -16248,6 +16337,48 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16248
16337
|
}
|
|
16249
16338
|
}
|
|
16250
16339
|
}
|
|
16340
|
+
/** True for a main connection with no local media to send. */
|
|
16341
|
+
hasNoLocalMediaToSend() {
|
|
16342
|
+
const hasInputStreams = Boolean(this.options.inputAudioStream ?? this.options.inputVideoStream);
|
|
16343
|
+
return this.propose === "main" && !this.localStream && !hasInputStreams && !this.inputAudioDeviceConstraints && !this.inputVideoDeviceConstraints;
|
|
16344
|
+
}
|
|
16345
|
+
/** The media kinds this connection wants to send: 'audiovideo' | 'video' | 'audio'. */
|
|
16346
|
+
get requestedMediaKinds() {
|
|
16347
|
+
const wantsAudio = Boolean(this.inputAudioDeviceConstraints);
|
|
16348
|
+
const wantsVideo = Boolean(this.inputVideoDeviceConstraints);
|
|
16349
|
+
if (wantsAudio && wantsVideo) return "audiovideo";
|
|
16350
|
+
return wantsVideo ? "video" : "audio";
|
|
16351
|
+
}
|
|
16352
|
+
/**
|
|
16353
|
+
* Handle a local media acquisition failure with a typed, semantically
|
|
16354
|
+
* accurate MediaAccessError created at the acquisition site:
|
|
16355
|
+
* - Auxiliary connections (screenshare / additional-device) throw a
|
|
16356
|
+
* non-fatal error — VertoManager surfaces it and the call is unaffected.
|
|
16357
|
+
* - The main connection degrades to receive-only when allowed (default),
|
|
16358
|
+
* otherwise fails with a fatal error.
|
|
16359
|
+
*/
|
|
16360
|
+
handleLocalMediaFailure(error) {
|
|
16361
|
+
if (this.propose === "screenshare") throw new MediaAccessError("startScreenShare", "screen", error, false);
|
|
16362
|
+
if (this.propose === "additional-device") throw new MediaAccessError("addInputDevice", this.requestedMediaKinds, error, false);
|
|
16363
|
+
const canReceive = this.receiveAudio || this.receiveVideo;
|
|
16364
|
+
if (!((this.options.fallbackToReceiveOnly ?? true) && canReceive)) throw new MediaAccessError("acquireLocalMedia", this.requestedMediaKinds, error, true);
|
|
16365
|
+
logger$17.warn("[RTCPeerConnectionController] Local media unavailable; continuing receive-only:", error);
|
|
16366
|
+
this._errors$.next(new MediaAccessError("acquireLocalMedia", this.requestedMediaKinds, error, false));
|
|
16367
|
+
this.setupReceiveOnlyTransceivers();
|
|
16368
|
+
}
|
|
16369
|
+
/**
|
|
16370
|
+
* Negotiate receive-only m-lines when there are no local tracks to send.
|
|
16371
|
+
* Only offer-type connections add transceivers — answer-type connections
|
|
16372
|
+
* reuse the transceivers created from the remote offer.
|
|
16373
|
+
*/
|
|
16374
|
+
setupReceiveOnlyTransceivers() {
|
|
16375
|
+
if (this.type !== "offer") return;
|
|
16376
|
+
if (this.transceiverController?.useAddTransceivers ?? false) {
|
|
16377
|
+
this.peerConnection?.addTransceiver("audio", { direction: this.receiveAudio ? "recvonly" : "inactive" });
|
|
16378
|
+
this.peerConnection?.addTransceiver("video", { direction: this.receiveVideo ? "recvonly" : "inactive" });
|
|
16379
|
+
}
|
|
16380
|
+
if (!this.isNegotiating) this.negotiationNeeded$.next();
|
|
16381
|
+
}
|
|
16251
16382
|
async getUserMedia(constraints) {
|
|
16252
16383
|
return (this.options.webRTCApiProvider?.mediaDevices ?? navigator.mediaDevices).getUserMedia(constraints);
|
|
16253
16384
|
}
|
|
@@ -16284,7 +16415,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16284
16415
|
stream = await this.getUserMedia({ audio: constraints });
|
|
16285
16416
|
} catch (error) {
|
|
16286
16417
|
logger$17.error("[RTCPeerConnectionController] Failed to re-acquire mic for pipeline restore:", error);
|
|
16287
|
-
this._errors$.next(
|
|
16418
|
+
this._errors$.next(new MediaTrackError("restoreAudioPipelineInput", "audio", error));
|
|
16288
16419
|
return;
|
|
16289
16420
|
}
|
|
16290
16421
|
const newTrack = stream.getAudioTracks().at(0);
|
|
@@ -16346,7 +16477,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16346
16477
|
logger$17.debug(`[RTCPeerConnectionController] ${track.kind} track added:`, track.id);
|
|
16347
16478
|
} catch (error) {
|
|
16348
16479
|
logger$17.error(`[RTCPeerConnectionController] Failed to add ${track.kind} track:`, error);
|
|
16349
|
-
this._errors$.next(
|
|
16480
|
+
this._errors$.next(new MediaTrackError("addLocalTrack", track.kind, error));
|
|
16350
16481
|
throw error;
|
|
16351
16482
|
}
|
|
16352
16483
|
}
|
|
@@ -16371,7 +16502,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16371
16502
|
logger$17.debug(`[RTCPeerConnectionController] ${sender.track?.kind} track removed:`, trackId);
|
|
16372
16503
|
} catch (error) {
|
|
16373
16504
|
logger$17.error(`[RTCPeerConnectionController] Failed to remove ${sender.track?.kind} track:`, error);
|
|
16374
|
-
this._errors$.next(
|
|
16505
|
+
this._errors$.next(new MediaTrackError("removeLocalTrack", sender.track?.kind ?? "unknown", error));
|
|
16375
16506
|
throw error;
|
|
16376
16507
|
}
|
|
16377
16508
|
}
|
|
@@ -16481,7 +16612,11 @@ function isVertoInviteMessage(value) {
|
|
|
16481
16612
|
const msg = value;
|
|
16482
16613
|
return msg.method === "verto.invite" && isObject(msg.params) && hasProperty(msg.params, "sdp") && hasProperty(msg.params, "callID");
|
|
16483
16614
|
}
|
|
16484
|
-
|
|
16615
|
+
/**
|
|
16616
|
+
* Guards inbound `verto.bye` frames (server → client). Outbound bye messages are
|
|
16617
|
+
* built locally and never type-guarded, so only the inbound shape is asserted.
|
|
16618
|
+
*/
|
|
16619
|
+
function isVertoByeInboundMessage(value) {
|
|
16485
16620
|
if (!isVertoMethodMessage(value)) return false;
|
|
16486
16621
|
return value.method === "verto.bye";
|
|
16487
16622
|
}
|
|
@@ -16501,6 +16636,14 @@ function isVertoMediaParamsInnerParams(value) {
|
|
|
16501
16636
|
function isVertoPingInnerParams(value) {
|
|
16502
16637
|
return isObject(value) && hasProperty(value, "jsonrpc") && value.jsonrpc === "2.0" && hasProperty(value, "method") && value.method === "verto.ping";
|
|
16503
16638
|
}
|
|
16639
|
+
/**
|
|
16640
|
+
* Guards the params of an inbound `verto.bye` frame (top-level `callID`). Use
|
|
16641
|
+
* this to recognise the bye payload extracted by `vertoBye$`, e.g. when racing
|
|
16642
|
+
* it against a boolean answer/reject signal.
|
|
16643
|
+
*/
|
|
16644
|
+
function isVertoByeInboundParamsGuard(value) {
|
|
16645
|
+
return isObject(value) && hasProperty(value, "callID") && typeof value.callID === "string";
|
|
16646
|
+
}
|
|
16504
16647
|
|
|
16505
16648
|
//#endregion
|
|
16506
16649
|
//#region src/managers/VertoManager.ts
|
|
@@ -16839,7 +16982,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16839
16982
|
return this.cachedObservable("vertoMediaParams$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoMediaParamsInnerParams, "params"), (0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
16840
16983
|
}
|
|
16841
16984
|
get vertoBye$() {
|
|
16842
|
-
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(
|
|
16985
|
+
return this.cachedObservable("vertoBye$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoByeInboundMessage, "params"), (0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
16843
16986
|
}
|
|
16844
16987
|
get vertoAttach$() {
|
|
16845
16988
|
return this.cachedObservable("vertoAttach$", () => this.webRtcCallSession.webrtcMessages$.pipe(filterAs(isVertoAttachMessage, "params"), (0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
@@ -16968,6 +17111,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16968
17111
|
inputVideoStream: options.inputVideoStream,
|
|
16969
17112
|
receiveAudio: options.receiveAudio,
|
|
16970
17113
|
receiveVideo: options.receiveVideo,
|
|
17114
|
+
fallbackToReceiveOnly: options.fallbackToReceiveOnly,
|
|
16971
17115
|
webRTCApiProvider: this.webRTCApiProvider,
|
|
16972
17116
|
preferredVideoCodecs: options.preferredVideoCodecs,
|
|
16973
17117
|
preferredAudioCodecs: options.preferredAudioCodecs,
|
|
@@ -16992,7 +17136,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16992
17136
|
logger$16.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
16993
17137
|
return;
|
|
16994
17138
|
}
|
|
16995
|
-
if (
|
|
17139
|
+
if (isVertoByeInboundParamsGuard(vertoByeOrAccepted)) {
|
|
16996
17140
|
logger$16.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
16997
17141
|
this.callSession?.destroy();
|
|
16998
17142
|
} else if (!vertoByeOrAccepted) {
|
|
@@ -17094,7 +17238,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17094
17238
|
logger$16.debug("[WebRTCManager] Destroyed while waiting for call acceptance");
|
|
17095
17239
|
return;
|
|
17096
17240
|
}
|
|
17097
|
-
if (
|
|
17241
|
+
if (isVertoByeInboundParamsGuard(vertoByeOrAccepted)) {
|
|
17098
17242
|
logger$16.info("[WebRTCManager] Call ended before answer was sent.");
|
|
17099
17243
|
this.callSession?.destroy();
|
|
17100
17244
|
} else if (!vertoByeOrAccepted) {
|
|
@@ -17194,9 +17338,11 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17194
17338
|
await this.initAdditionalPeerConnection("screenshare", options);
|
|
17195
17339
|
}
|
|
17196
17340
|
async initAdditionalPeerConnection(propose, options) {
|
|
17341
|
+
const isScreenShare = propose === "screenshare";
|
|
17342
|
+
let firstPeerConnectionError;
|
|
17197
17343
|
let rtcPeerConnController = null;
|
|
17198
17344
|
try {
|
|
17199
|
-
this._screenShareStatus$.next("starting");
|
|
17345
|
+
if (isScreenShare) this._screenShareStatus$.next("starting");
|
|
17200
17346
|
rtcPeerConnController = new RTCPeerConnectionController({
|
|
17201
17347
|
...options,
|
|
17202
17348
|
...this.RTCPeerConnectionConfig,
|
|
@@ -17204,21 +17350,27 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17204
17350
|
webRTCApiProvider: this.webRTCApiProvider
|
|
17205
17351
|
}, void 0, this.deviceController);
|
|
17206
17352
|
this.setupLocalDescriptionHandler(rtcPeerConnController);
|
|
17207
|
-
if (
|
|
17353
|
+
if (isScreenShare) this._screenShareId = rtcPeerConnController.id;
|
|
17208
17354
|
this._rtcPeerConnectionsMap.set(rtcPeerConnController.id, rtcPeerConnController);
|
|
17209
17355
|
this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values()));
|
|
17210
17356
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
17211
|
-
|
|
17357
|
+
firstPeerConnectionError ??= error;
|
|
17358
|
+
this.onError?.(error, { fatal: false });
|
|
17212
17359
|
});
|
|
17213
17360
|
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$)));
|
|
17214
|
-
this._screenShareStatus$.next("started");
|
|
17215
|
-
logger$16.info(
|
|
17361
|
+
if (isScreenShare) this._screenShareStatus$.next("started");
|
|
17362
|
+
logger$16.info(`[WebRTCManager] Additional peer connection connected (${propose}).`);
|
|
17216
17363
|
return rtcPeerConnController.id;
|
|
17217
17364
|
} catch (error) {
|
|
17218
17365
|
logger$16.warn("[WebRTCManager] Error initializing additional peer connection:", error);
|
|
17219
|
-
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
17220
17366
|
if (rtcPeerConnController) rtcPeerConnController.destroy();
|
|
17221
|
-
this._screenShareStatus$.next("none");
|
|
17367
|
+
if (isScreenShare) this._screenShareStatus$.next("none");
|
|
17368
|
+
if (firstPeerConnectionError) throw firstPeerConnectionError instanceof MediaAccessError && firstPeerConnectionError.originalError instanceof Error ? firstPeerConnectionError.originalError : firstPeerConnectionError;
|
|
17369
|
+
if (error instanceof import_cjs$15.EmptyError) {
|
|
17370
|
+
logger$16.debug("[WebRTCManager] Additional peer connection aborted before connecting.");
|
|
17371
|
+
return;
|
|
17372
|
+
}
|
|
17373
|
+
throw error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
17222
17374
|
}
|
|
17223
17375
|
}
|
|
17224
17376
|
async removeInputDevices(id) {
|
|
@@ -18147,6 +18299,12 @@ function mosToQualityLevel(mos) {
|
|
|
18147
18299
|
var import_cjs$11 = require_cjs();
|
|
18148
18300
|
const logger$12 = getLogger();
|
|
18149
18301
|
/**
|
|
18302
|
+
* Verto method for setting member layout positions. Its gateway DTO requires a
|
|
18303
|
+
* `targets` array whose entries are `{ target, position }` (NOT bare targets),
|
|
18304
|
+
* so {@link WebRTCCall.buildMethodParams} special-cases it. See issue #19400.
|
|
18305
|
+
*/
|
|
18306
|
+
const POSITION_SET_METHOD = "call.member.position.set";
|
|
18307
|
+
/**
|
|
18150
18308
|
* Ratio between the critical and warning RTT spike multipliers.
|
|
18151
18309
|
* Warning threshold = baseline * warningMultiplier (default 3x)
|
|
18152
18310
|
* Critical threshold = baseline * warningMultiplier * RTT_CRITICAL_TO_WARNING_RATIO
|
|
@@ -18353,7 +18511,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18353
18511
|
* @throws {JSONRPCError} If the RPC call returns an error.
|
|
18354
18512
|
*/
|
|
18355
18513
|
async executeMethod(target, method, args) {
|
|
18356
|
-
const params = this.buildMethodParams(target, args);
|
|
18514
|
+
const params = this.buildMethodParams(target, args, method);
|
|
18357
18515
|
const request = buildRPCRequest({
|
|
18358
18516
|
method,
|
|
18359
18517
|
params
|
|
@@ -18367,12 +18525,16 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18367
18525
|
throw error;
|
|
18368
18526
|
}
|
|
18369
18527
|
}
|
|
18370
|
-
buildMethodParams(target, args) {
|
|
18528
|
+
buildMethodParams(target, args, method) {
|
|
18371
18529
|
const self = {
|
|
18372
18530
|
node_id: this.nodeId ?? "",
|
|
18373
18531
|
call_id: this.id,
|
|
18374
18532
|
member_id: this.vertoManager.selfId ?? ""
|
|
18375
18533
|
};
|
|
18534
|
+
if (method === POSITION_SET_METHOD) return {
|
|
18535
|
+
...args,
|
|
18536
|
+
self
|
|
18537
|
+
};
|
|
18376
18538
|
if (typeof target === "object") return {
|
|
18377
18539
|
...args,
|
|
18378
18540
|
self,
|
|
@@ -18938,10 +19100,21 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18938
19100
|
return this.deferEmission(this._answered$.asObservable());
|
|
18939
19101
|
}
|
|
18940
19102
|
/**
|
|
18941
|
-
* Sets the call layout and participant positions.
|
|
19103
|
+
* Sets the call layout and, optionally, individual participant positions.
|
|
19104
|
+
*
|
|
19105
|
+
* The gateway `call.layout.set` DTO has **no** `positions` member, so when
|
|
19106
|
+
* `positions` is provided this method issues a `call.member.position.set`
|
|
19107
|
+
* request per member (via {@link Participant.setPosition}, which keys each
|
|
19108
|
+
* position by that member's own call context) alongside `call.layout.set`
|
|
19109
|
+
* (issue #19400, Flag #6).
|
|
19110
|
+
*
|
|
19111
|
+
* **These operations are NOT atomic.** The layout is applied first, then each
|
|
19112
|
+
* member position sequentially, so members may briefly flash into their
|
|
19113
|
+
* default slots before being moved to the requested positions.
|
|
18942
19114
|
*
|
|
18943
19115
|
* @param layout - Layout name (must be one of {@link layouts}).
|
|
18944
|
-
* @param positions -
|
|
19116
|
+
* @param positions - Optional map of member IDs to {@link VideoPosition} values.
|
|
19117
|
+
* When omitted or empty, only the layout is changed.
|
|
18945
19118
|
* @throws {InvalidParams} If the layout is not in the available {@link layouts}.
|
|
18946
19119
|
*
|
|
18947
19120
|
* @example
|
|
@@ -18954,10 +19127,17 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18954
19127
|
async setLayout(layout, positions) {
|
|
18955
19128
|
if (!this.layouts.includes(layout)) throw new InvalidParams(`Layout ${layout} is not available in the current call layouts: ${this.layouts.join(", ")}`);
|
|
18956
19129
|
const selfId = await (0, import_cjs$11.firstValueFrom)(this.selfId$.pipe((0, import_cjs$11.filter)((id) => id !== null)));
|
|
18957
|
-
await this.executeMethod(selfId, "call.layout.set", {
|
|
18958
|
-
|
|
18959
|
-
|
|
18960
|
-
|
|
19130
|
+
await this.executeMethod(selfId, "call.layout.set", { layout });
|
|
19131
|
+
const positionEntries = Object.entries(positions ?? {});
|
|
19132
|
+
if (positionEntries.length === 0) return;
|
|
19133
|
+
for (const [memberId, position] of positionEntries) {
|
|
19134
|
+
const participant = this.participants.find((p) => p.id === memberId);
|
|
19135
|
+
if (!participant) {
|
|
19136
|
+
logger$12.warn(`[Call] setLayout: member ${memberId} not found in participants; skipping position ${position}`);
|
|
19137
|
+
continue;
|
|
19138
|
+
}
|
|
19139
|
+
await participant.setPosition(position);
|
|
19140
|
+
}
|
|
18961
19141
|
}
|
|
18962
19142
|
/**
|
|
18963
19143
|
* Transfers the call to another destination.
|
|
@@ -19131,6 +19311,7 @@ function inferCallErrorKind(error) {
|
|
|
19131
19311
|
if (error instanceof RPCTimeoutError) return "timeout";
|
|
19132
19312
|
if (error instanceof JSONRPCError) return "signaling";
|
|
19133
19313
|
if (error instanceof MediaTrackError) return "media";
|
|
19314
|
+
if (error instanceof MediaAccessError) return "media";
|
|
19134
19315
|
if (error instanceof WebSocketConnectionError || error instanceof TransportConnectionError) return "network";
|
|
19135
19316
|
return "internal";
|
|
19136
19317
|
}
|
|
@@ -19147,6 +19328,7 @@ const RECOVERABLE_RPC_CODES = new Set([
|
|
|
19147
19328
|
function isFatalError(error) {
|
|
19148
19329
|
if (error instanceof VertoPongError) return false;
|
|
19149
19330
|
if (error instanceof MediaTrackError) return false;
|
|
19331
|
+
if (error instanceof MediaAccessError) return error.fatal;
|
|
19150
19332
|
if (error instanceof RPCTimeoutError) return false;
|
|
19151
19333
|
if (error instanceof JSONRPCError && RECOVERABLE_RPC_CODES.has(error.code)) return false;
|
|
19152
19334
|
return true;
|
|
@@ -19172,10 +19354,10 @@ var CallFactory = class {
|
|
|
19172
19354
|
return {
|
|
19173
19355
|
vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, this.webRTCApiProvider, {
|
|
19174
19356
|
nodeId: options.nodeId,
|
|
19175
|
-
onError: (error) => {
|
|
19357
|
+
onError: (error, options$1) => {
|
|
19176
19358
|
const callError = {
|
|
19177
19359
|
kind: inferCallErrorKind(error),
|
|
19178
|
-
fatal: isFatalError(error),
|
|
19360
|
+
fatal: options$1?.fatal ?? isFatalError(error),
|
|
19179
19361
|
error,
|
|
19180
19362
|
callId: callInstance.id
|
|
19181
19363
|
};
|
|
@@ -19638,6 +19820,17 @@ var PendingRPC = class PendingRPC {
|
|
|
19638
19820
|
//#region src/managers/ClientSessionManager.ts
|
|
19639
19821
|
var import_cjs$7 = require_cjs();
|
|
19640
19822
|
const logger$9 = getLogger();
|
|
19823
|
+
/**
|
|
19824
|
+
* Decide whether an error emitted on `call.errors$` during dial should
|
|
19825
|
+
* abort the dial. A non-fatal MediaAccessError means the call degraded to
|
|
19826
|
+
* receive-only and still connects — everything else rejects `dial()` with
|
|
19827
|
+
* the real cause.
|
|
19828
|
+
*
|
|
19829
|
+
* Pure function — exported for unit testing.
|
|
19830
|
+
*/
|
|
19831
|
+
function shouldAbortDial(callError) {
|
|
19832
|
+
return callError.fatal || !(callError.error instanceof MediaAccessError);
|
|
19833
|
+
}
|
|
19641
19834
|
const getAddressSearchURI = (options) => {
|
|
19642
19835
|
const to = options.to?.split("?")[0];
|
|
19643
19836
|
const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
|
|
@@ -19876,11 +20069,41 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19876
20069
|
}
|
|
19877
20070
|
} else this._errors$.next(error);
|
|
19878
20071
|
}
|
|
20072
|
+
/**
|
|
20073
|
+
* Clear the resume state (authorization_state + protocol) only.
|
|
20074
|
+
*
|
|
20075
|
+
* This is the stale-auth-state recovery helper used by handleAuthError:
|
|
20076
|
+
* the server rejected a reconnect, so the resume state is discarded and a
|
|
20077
|
+
* fresh connect follows. Attach records are deliberately preserved — the
|
|
20078
|
+
* session lives on through the reconnect and reattachCalls() needs the
|
|
20079
|
+
* stored call references afterwards. Do NOT add detachAll() here.
|
|
20080
|
+
*
|
|
20081
|
+
* For public teardown (disconnect/destroy), use {@link teardownSessionState}
|
|
20082
|
+
* instead, which clears the attach records as well.
|
|
20083
|
+
*/
|
|
19879
20084
|
async cleanupStoredConnectionParams() {
|
|
19880
20085
|
await this.transport.setProtocol(void 0);
|
|
19881
20086
|
await this.updateAuthorizationStateInStorage(void 0);
|
|
19882
20087
|
this._authorization$.next(void 0);
|
|
19883
20088
|
}
|
|
20089
|
+
/**
|
|
20090
|
+
* Public-teardown helper for disconnect()/destroy(). Clears the resume
|
|
20091
|
+
* state (authorization_state + protocol) AND the attach records as one
|
|
20092
|
+
* atomic unit.
|
|
20093
|
+
*
|
|
20094
|
+
* The two stores are coupled: the backend only honors attach records
|
|
20095
|
+
* within the session identified by the resume state, so ending the
|
|
20096
|
+
* session must clear both. Clearing one without the other strands records
|
|
20097
|
+
* no future session can honor (disconnect) or revives a session the
|
|
20098
|
+
* developer explicitly ended (destroy).
|
|
20099
|
+
*
|
|
20100
|
+
* Distinct from {@link cleanupStoredConnectionParams}, which keeps the
|
|
20101
|
+
* attach records for the stale-auth-state recovery path.
|
|
20102
|
+
*/
|
|
20103
|
+
async teardownSessionState() {
|
|
20104
|
+
await this.cleanupStoredConnectionParams();
|
|
20105
|
+
await this.attachManager.detachAll();
|
|
20106
|
+
}
|
|
19884
20107
|
async updateAuthState(authorization_state) {
|
|
19885
20108
|
try {
|
|
19886
20109
|
await this.storage.setItem(this.authorizationStateKey, authorization_state);
|
|
@@ -19975,7 +20198,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
19975
20198
|
async disconnect() {
|
|
19976
20199
|
this.transport.disconnect();
|
|
19977
20200
|
this._authState$.next({ kind: "unauthenticated" });
|
|
19978
|
-
await this.
|
|
20201
|
+
await this.teardownSessionState();
|
|
19979
20202
|
}
|
|
19980
20203
|
async createInboundCall(invite) {
|
|
19981
20204
|
const callSession = await this.createCall({
|
|
@@ -20034,7 +20257,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
20034
20257
|
to: destinationURI,
|
|
20035
20258
|
...options
|
|
20036
20259
|
});
|
|
20037
|
-
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)))));
|
|
20260
|
+
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)))));
|
|
20038
20261
|
this._calls$.next({
|
|
20039
20262
|
[`${callSession.id}`]: callSession,
|
|
20040
20263
|
...this._calls$.value
|
|
@@ -21142,6 +21365,10 @@ var TransportManager = class extends Destroyable {
|
|
|
21142
21365
|
if (!isSignalwireRequest(message)) return true;
|
|
21143
21366
|
const eventChannel = message.params.event_channel;
|
|
21144
21367
|
if (!eventChannel) return true;
|
|
21368
|
+
if (message.params.event_type.startsWith("conversation.")) {
|
|
21369
|
+
logger$2.debug(`[Transport] Received conversation event: ${message.params.event_type} (event_channel: ${eventChannel})`);
|
|
21370
|
+
return true;
|
|
21371
|
+
}
|
|
21145
21372
|
const currentProtocol = this._currentProtocol;
|
|
21146
21373
|
if (!currentProtocol) return true;
|
|
21147
21374
|
if (!eventChannel.includes(currentProtocol)) {
|
|
@@ -21742,7 +21969,7 @@ var SignalWire = class extends Destroyable {
|
|
|
21742
21969
|
logger$1.warn("[SignalWire] Failed to initialize VisibilityController:", error);
|
|
21743
21970
|
}
|
|
21744
21971
|
try {
|
|
21745
|
-
this._diagnosticsCollector = new DiagnosticsCollector({ sdkVersion: "4.0.0-rc.
|
|
21972
|
+
this._diagnosticsCollector = new DiagnosticsCollector({ sdkVersion: "4.0.0-rc.2" });
|
|
21746
21973
|
} catch (error) {
|
|
21747
21974
|
logger$1.warn("[SignalWire] Failed to initialize DiagnosticsCollector:", error);
|
|
21748
21975
|
}
|
|
@@ -21750,6 +21977,14 @@ var SignalWire = class extends Destroyable {
|
|
|
21750
21977
|
/**
|
|
21751
21978
|
* Disconnects the WebSocket and tears down the current session.
|
|
21752
21979
|
*
|
|
21980
|
+
* Ends the session identified by the protocol and clears its persisted
|
|
21981
|
+
* resume state (`authorization_state` + protocol) and attach records
|
|
21982
|
+
* together — a later {@link connect} with the same credentials starts a
|
|
21983
|
+
* fresh session and cannot reattach to the ended session's calls.
|
|
21984
|
+
* Credentials and device preferences are preserved. To temporarily stop
|
|
21985
|
+
* receiving inbound calls while keeping the session alive, use
|
|
21986
|
+
* `unregister()` instead.
|
|
21987
|
+
*
|
|
21753
21988
|
* The client can be reconnected by calling {@link connect} again,
|
|
21754
21989
|
* which creates a fresh transport and session.
|
|
21755
21990
|
*/
|
|
@@ -22141,12 +22376,20 @@ var SignalWire = class extends Destroyable {
|
|
|
22141
22376
|
prefs.preferredVideoInput = null;
|
|
22142
22377
|
await this._deviceController.clearDeviceState();
|
|
22143
22378
|
}
|
|
22144
|
-
/**
|
|
22379
|
+
/**
|
|
22380
|
+
* Destroys the client, clearing timers and releasing all resources.
|
|
22381
|
+
*
|
|
22382
|
+
* Intentionally destroying the client ends its session: the resume state
|
|
22383
|
+
* (`authorization_state` + protocol) and the attach records are both
|
|
22384
|
+
* cleared. Credentials and device preferences are preserved — use
|
|
22385
|
+
* {@link resetToDefaults} for a full wipe. To temporarily stop receiving
|
|
22386
|
+
* inbound calls while keeping the session alive, use `unregister()`.
|
|
22387
|
+
*/
|
|
22145
22388
|
destroy() {
|
|
22146
22389
|
this._refreshCoordinator?.destroy();
|
|
22147
22390
|
this._refreshCoordinator = void 0;
|
|
22148
22391
|
this._dpopManager?.destroy();
|
|
22149
|
-
|
|
22392
|
+
this._clientSession.teardownSessionState();
|
|
22150
22393
|
this._transport.destroy();
|
|
22151
22394
|
this._clientSession.destroy();
|
|
22152
22395
|
try {
|
|
@@ -22261,7 +22504,7 @@ var StaticCredentialProvider = class {
|
|
|
22261
22504
|
/**
|
|
22262
22505
|
* Library version from package.json, injected at build time.
|
|
22263
22506
|
*/
|
|
22264
|
-
const version = "4.0.0-rc.
|
|
22507
|
+
const version = "4.0.0-rc.2";
|
|
22265
22508
|
/**
|
|
22266
22509
|
* Flag indicating the library has been loaded and is ready to use.
|
|
22267
22510
|
* For UMD builds: `window.SignalWire.ready`
|
|
@@ -22283,7 +22526,7 @@ const ready = true;
|
|
|
22283
22526
|
*/
|
|
22284
22527
|
const emitReadyEvent = () => {
|
|
22285
22528
|
if (typeof window !== "undefined") {
|
|
22286
|
-
const event = new CustomEvent("signalwire:js:ready", { detail: { version: "4.0.0-rc.
|
|
22529
|
+
const event = new CustomEvent("signalwire:js:ready", { detail: { version: "4.0.0-rc.2" } });
|
|
22287
22530
|
window.dispatchEvent(event);
|
|
22288
22531
|
}
|
|
22289
22532
|
};
|
|
@@ -22307,5 +22550,5 @@ emitReadyEvent();
|
|
|
22307
22550
|
if (typeof process === "undefined") globalThis.process = { env: { NODE_ENV: "production" } };
|
|
22308
22551
|
|
|
22309
22552
|
//#endregion
|
|
22310
|
-
export { Address, CallCreateError, ClientPreferences, CollectionFetchError, DPoPInitError, DeviceTokenError, EmbedTokenCredentialProvider, InvalidCredentialsError, MediaTrackError, MessageParseError, OverconstrainedFallbackError, Participant, PreflightError, RecoveryError, SelfCapabilities, SelfParticipant, SignalWire, StaticCredentialProvider, TokenRefreshError, UnexpectedError, User, VertoPongError, WebRTCCall, embeddableCall, getLogger, isSelfParticipant, ready, setDebugOptions, setLogLevel, setLogger, version };
|
|
22553
|
+
export { Address, CallCreateError, ClientPreferences, CollectionFetchError, DPoPInitError, DeviceTokenError, EmbedTokenCredentialProvider, InvalidCredentialsError, MediaAccessError, MediaTrackError, MessageParseError, OverconstrainedFallbackError, Participant, PreflightError, RecoveryError, SelfCapabilities, SelfParticipant, SignalWire, StaticCredentialProvider, TokenRefreshError, UnexpectedError, User, VertoPongError, WebRTCCall, embeddableCall, getLogger, isSelfParticipant, ready, setDebugOptions, setLogLevel, setLogger, version };
|
|
22311
22554
|
//# sourceMappingURL=browser.mjs.map
|