@ikonai/sdk 1.4.0 → 1.5.0

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.
@@ -389,6 +389,10 @@ export declare const PROTOCOL_WORKER_CONNECT_TIMEOUT_MS = 30000;
389
389
  export declare const DEFAULT_RECONNECT_BACKOFF_MS = 2000;
390
390
  export declare const DEFAULT_MAX_RECONNECT_ATTEMPTS = 2;
391
391
  export declare const DEFAULT_ACTION_ACK_TIMEOUT_MS = 5000;
392
+ export declare const ACTION_ACK_RTT_MULTIPLIER = 3;
393
+ export declare const ACTION_ACK_RTT_SMOOTHING = 0.125;
394
+ export declare const MAX_ACTION_ACK_TIMEOUT_MS = 30000;
392
395
  export declare const DEFAULT_PROVISIONING_TIMEOUT_MS = 60000;
393
396
  export declare const OFFLINE_SOFT_RETRY_THRESHOLD_MS: number;
394
397
  export declare const RECONNECT_RETRY_INTERVAL_MS: number;
398
+ export declare const JOIN_COMPLETION_TIMEOUT_MS = 10000;
@@ -123,6 +123,7 @@ export declare class IkonClient {
123
123
  private readonly connectionTimeoutMs;
124
124
  private readonly actionAckTimeoutMs;
125
125
  private readonly _pendingActionAcks;
126
+ private _ackRttMs;
126
127
  private readonly _actionIdByCallId;
127
128
  private readonly _pendingActionResults;
128
129
  private readonly endpointSelector;
@@ -168,6 +169,7 @@ export declare class IkonClient {
168
169
  private _webRtcAudioStreams;
169
170
  private _webRtcVideoStreams;
170
171
  private _webRtcTrackMap;
172
+ private readonly _webRtcTrackMapListeners;
171
173
  private _pendingActiveAudioTracks;
172
174
  private _keepaliveLockAbort;
173
175
  private _fullReauthAttempted;
@@ -176,6 +178,7 @@ export declare class IkonClient {
176
178
  private _reauthInProgress;
177
179
  private _disconnectedAt;
178
180
  private _reconnectTimer;
181
+ private _joinWatchdogTimer;
179
182
  private _serverStopped;
180
183
  private _hasBeenConnected;
181
184
  private _waitForExternalConnectUrl;
@@ -261,8 +264,19 @@ export declare class IkonClient {
261
264
  get webRtcTrackMap(): Map<string, WebRTCTrackMapInfo>;
262
265
  /**
263
266
  * Callback fired when a WebRTC track map update is received from the server.
267
+ *
268
+ * Single-slot: assigning replaces the previous callback, so sharing it between
269
+ * components requires manual chaining. New code should prefer
270
+ * {@link addWebRtcTrackMapListener}, which supports any number of subscribers.
264
271
  */
265
272
  onWebRtcTrackMapChanged?: (info: WebRTCTrackMapInfo) => void;
273
+ /**
274
+ * Subscribe to WebRTC track map updates. Any number of listeners can subscribe
275
+ * independently — each call returns an unsubscribe function for its listener.
276
+ * Fired for every update alongside {@link onWebRtcTrackMapChanged}.
277
+ */
278
+ addWebRtcTrackMapListener(listener: (info: WebRTCTrackMapInfo) => void): () => void;
279
+ private notifyWebRtcTrackMapChanged;
266
280
  /**
267
281
  * Look up the WebRTC video MediaStream for a given app-level stream ID.
268
282
  * Checks remote tracks first, then falls back to local capture streams so single-user
@@ -379,12 +393,29 @@ export declare class IkonClient {
379
393
  */
380
394
  sendActionCallWithResult(actionId: string, payload?: string, timeoutMs?: number): Promise<ActionOutcome>;
381
395
  private sendActionCallCore;
396
+ /**
397
+ * How long to wait for this call's ack before treating the connection as dead.
398
+ *
399
+ * The short deadline exists for the user, not the protocol: a click that does nothing is the worst
400
+ * thing the UI can do, so the reconnecting overlay has to appear fast. But on a slow link the ack
401
+ * legitimately takes longer than the configured deadline, and firing then tears down a working
402
+ * connection and drops WebRTC — the reconnect makes the experience worse than the latency did.
403
+ * So the deadline follows the link: the configured value is the floor, and a slow link stretches
404
+ * it to a multiple of the observed round-trip, capped so a truly dead link is still caught quickly.
405
+ */
406
+ private getActionAckTimeoutMs;
407
+ /**
408
+ * Fold one ack round-trip into the smoothed estimate. Weighted like a TCP RTT estimator: recent
409
+ * samples move it, a single outlier does not.
410
+ */
411
+ private recordAckRtt;
382
412
  /**
383
413
  * Register an outstanding action call and start its ack-timeout timer. If the
384
- * server does not echo back an ActionCallAck for this CallId within
385
- * `actionAckTimeoutMs`, we assume the connection is dead and force reconnect.
414
+ * server does not echo back an ActionCallAck within the deadline, we assume the
415
+ * connection is dead and force reconnect.
386
416
  */
387
417
  private trackPendingActionAck;
418
+ private armActionAckTimer;
388
419
  private onActionAckTimeout;
389
420
  private clearPendingActionAcks;
390
421
  /**
@@ -665,6 +696,14 @@ export declare class IkonClient {
665
696
  * Try to handle joined state - only proceeds if both channels are connected and GlobalState is received.
666
697
  */
667
698
  private tryHandleJoined;
699
+ /**
700
+ * Connected channels are not a joined session: until GlobalState arrives, handleJoined has not run,
701
+ * so the function registry is detached and every inbound call is dropped without an ack while the UI
702
+ * keeps updating and actions keep dispatching. Nothing else notices — the transport is healthy, so no
703
+ * transport watchdog fires. Bound the wait and recover, whatever kept the payload from arriving.
704
+ */
705
+ private armJoinWatchdog;
706
+ private clearJoinWatchdog;
668
707
  /**
669
708
  * Handle joined state - attach function registry, call user's onJoined callback, then send ClientReady.
670
709
  * Called on every connect (including reconnects).