@reactor-team/js-sdk 2.5.0 → 2.6.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.
package/dist/index.d.mts CHANGED
@@ -89,12 +89,17 @@ interface ReactorError {
89
89
  message: string;
90
90
  timestamp: number;
91
91
  recoverable: boolean;
92
- component: "coordinator" | "gpu" | "livekit";
92
+ component: "api" | "gpu";
93
93
  retryAfter?: number;
94
94
  }
95
95
  declare class ConflictError extends Error {
96
96
  constructor(message: string);
97
97
  }
98
+ declare class AbortError extends Error {
99
+ constructor(message: string);
100
+ }
101
+ /** Matches both our custom AbortError and the native DOMException thrown by fetch(). */
102
+ declare function isAbortError(error: unknown): boolean;
98
103
  interface ReactorState$1 {
99
104
  status: ReactorStatus;
100
105
  lastError?: ReactorError;
@@ -106,6 +111,25 @@ interface ConnectOptions {
106
111
  /** Maximum number of SDP polling attempts before giving up. Default: 6. */
107
112
  maxAttempts?: number;
108
113
  }
114
+ /**
115
+ * One-shot timing breakdown of the connect() handshake, recorded once per
116
+ * connection and included in every subsequent {@link ConnectionStats} update.
117
+ * All durations are in milliseconds (from `performance.now()`).
118
+ */
119
+ interface ConnectionTimings {
120
+ /** POST /sessions round-trip time */
121
+ sessionCreationMs: number;
122
+ /** Total time spent polling for the SDP answer */
123
+ sdpPollingMs: number;
124
+ /** Number of SDP poll requests made (1 = answered on first try) */
125
+ sdpPollingAttempts: number;
126
+ /** setRemoteDescription → RTCPeerConnection connectionState "connected" */
127
+ iceNegotiationMs: number;
128
+ /** setRemoteDescription → RTCDataChannel "open" */
129
+ dataChannelMs: number;
130
+ /** End-to-end: connect() invocation → status "ready" */
131
+ totalMs: number;
132
+ }
109
133
  interface ConnectionStats {
110
134
  /** ICE candidate-pair round-trip time in milliseconds */
111
135
  rtt?: number;
@@ -119,13 +143,15 @@ interface ConnectionStats {
119
143
  packetLossRatio?: number;
120
144
  /** Network jitter in seconds (from inbound-rtp) */
121
145
  jitter?: number;
146
+ /** Timing breakdown of the initial connection handshake (set once, persisted until disconnect) */
147
+ connectionTimings?: ConnectionTimings;
122
148
  timestamp: number;
123
149
  }
124
150
  type ReactorEvent = "statusChanged" | "sessionIdChanged" | "message" | "runtimeMessage" | "trackReceived" | "error" | "sessionExpirationChanged" | "statsUpdate";
125
151
 
126
- declare const PROD_COORDINATOR_URL = "https://api.reactor.inc";
152
+ declare const DEFAULT_BASE_URL = "https://api.reactor.inc";
127
153
  declare const OptionsSchema: z.ZodObject<{
128
- coordinatorUrl: z.ZodDefault<z.ZodString>;
154
+ apiUrl: z.ZodDefault<z.ZodString>;
129
155
  modelName: z.ZodString;
130
156
  local: z.ZodDefault<z.ZodBoolean>;
131
157
  receive: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -159,6 +185,8 @@ declare class Reactor {
159
185
  /** Tracks the client SENDS to the model (client → model). */
160
186
  private send;
161
187
  private sessionId?;
188
+ private connectStartTime?;
189
+ private connectionTimings?;
162
190
  constructor(options: Options);
163
191
  private eventListeners;
164
192
  on(event: ReactorEvent, handler: EventHandler): void;
@@ -200,6 +228,11 @@ declare class Reactor {
200
228
  connect(jwtToken?: string, options?: ConnectOptions): Promise<void>;
201
229
  /**
202
230
  * Sets up event handlers for the machine client.
231
+ *
232
+ * Each handler captures the client reference at registration time and
233
+ * ignores events if this.machineClient has since changed (e.g. after
234
+ * disconnect + reconnect), preventing stale WebRTC teardown events from
235
+ * interfering with a new connection.
203
236
  */
204
237
  private setupMachineClientHandlers;
205
238
  /**
@@ -225,6 +258,8 @@ declare class Reactor {
225
258
  */
226
259
  getLastError(): ReactorError | undefined;
227
260
  getStats(): ConnectionStats | undefined;
261
+ private resetConnectionTimings;
262
+ private finalizeConnectionTimings;
228
263
  /**
229
264
  * Create and store an error
230
265
  */
@@ -362,9 +397,9 @@ declare function useStats(): ConnectionStats | undefined;
362
397
  * In production, call /tokens from your server and pass the JWT to your frontend.
363
398
  *
364
399
  * @param apiKey - Your Reactor API key (will be exposed in client code!)
365
- * @param coordinatorUrl - Optional coordinator URL, defaults to production
400
+ * @param apiUrl - Optional API URL, defaults to production
366
401
  * @returns string containing the JWT token
367
402
  */
368
- declare function fetchInsecureJwtToken(apiKey: string, coordinatorUrl?: string): Promise<string>;
403
+ declare function fetchInsecureToken(apiKey: string, apiUrl?: string): Promise<string>;
369
404
 
370
- export { type AudioTrackOptions, ConflictError, type ConnectOptions, type ConnectionStats, type MessageScope, type Options, PROD_COORDINATOR_URL, Reactor, type ReactorConnectOptions, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type TrackConfig, type VideoTrackOptions, WebcamStream, type WebcamStreamProps, audio, fetchInsecureJwtToken, useReactor, useReactorInternalMessage, useReactorMessage, useReactorStore, useStats, video };
405
+ export { AbortError, type AudioTrackOptions, ConflictError, type ConnectOptions, type ConnectionStats, type ConnectionTimings, DEFAULT_BASE_URL, type MessageScope, type Options, Reactor, type ReactorConnectOptions, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type TrackConfig, type VideoTrackOptions, WebcamStream, type WebcamStreamProps, audio, fetchInsecureToken, isAbortError, useReactor, useReactorInternalMessage, useReactorMessage, useReactorStore, useStats, video };
package/dist/index.d.ts CHANGED
@@ -89,12 +89,17 @@ interface ReactorError {
89
89
  message: string;
90
90
  timestamp: number;
91
91
  recoverable: boolean;
92
- component: "coordinator" | "gpu" | "livekit";
92
+ component: "api" | "gpu";
93
93
  retryAfter?: number;
94
94
  }
95
95
  declare class ConflictError extends Error {
96
96
  constructor(message: string);
97
97
  }
98
+ declare class AbortError extends Error {
99
+ constructor(message: string);
100
+ }
101
+ /** Matches both our custom AbortError and the native DOMException thrown by fetch(). */
102
+ declare function isAbortError(error: unknown): boolean;
98
103
  interface ReactorState$1 {
99
104
  status: ReactorStatus;
100
105
  lastError?: ReactorError;
@@ -106,6 +111,25 @@ interface ConnectOptions {
106
111
  /** Maximum number of SDP polling attempts before giving up. Default: 6. */
107
112
  maxAttempts?: number;
108
113
  }
114
+ /**
115
+ * One-shot timing breakdown of the connect() handshake, recorded once per
116
+ * connection and included in every subsequent {@link ConnectionStats} update.
117
+ * All durations are in milliseconds (from `performance.now()`).
118
+ */
119
+ interface ConnectionTimings {
120
+ /** POST /sessions round-trip time */
121
+ sessionCreationMs: number;
122
+ /** Total time spent polling for the SDP answer */
123
+ sdpPollingMs: number;
124
+ /** Number of SDP poll requests made (1 = answered on first try) */
125
+ sdpPollingAttempts: number;
126
+ /** setRemoteDescription → RTCPeerConnection connectionState "connected" */
127
+ iceNegotiationMs: number;
128
+ /** setRemoteDescription → RTCDataChannel "open" */
129
+ dataChannelMs: number;
130
+ /** End-to-end: connect() invocation → status "ready" */
131
+ totalMs: number;
132
+ }
109
133
  interface ConnectionStats {
110
134
  /** ICE candidate-pair round-trip time in milliseconds */
111
135
  rtt?: number;
@@ -119,13 +143,15 @@ interface ConnectionStats {
119
143
  packetLossRatio?: number;
120
144
  /** Network jitter in seconds (from inbound-rtp) */
121
145
  jitter?: number;
146
+ /** Timing breakdown of the initial connection handshake (set once, persisted until disconnect) */
147
+ connectionTimings?: ConnectionTimings;
122
148
  timestamp: number;
123
149
  }
124
150
  type ReactorEvent = "statusChanged" | "sessionIdChanged" | "message" | "runtimeMessage" | "trackReceived" | "error" | "sessionExpirationChanged" | "statsUpdate";
125
151
 
126
- declare const PROD_COORDINATOR_URL = "https://api.reactor.inc";
152
+ declare const DEFAULT_BASE_URL = "https://api.reactor.inc";
127
153
  declare const OptionsSchema: z.ZodObject<{
128
- coordinatorUrl: z.ZodDefault<z.ZodString>;
154
+ apiUrl: z.ZodDefault<z.ZodString>;
129
155
  modelName: z.ZodString;
130
156
  local: z.ZodDefault<z.ZodBoolean>;
131
157
  receive: z.ZodDefault<z.ZodArray<z.ZodObject<{
@@ -159,6 +185,8 @@ declare class Reactor {
159
185
  /** Tracks the client SENDS to the model (client → model). */
160
186
  private send;
161
187
  private sessionId?;
188
+ private connectStartTime?;
189
+ private connectionTimings?;
162
190
  constructor(options: Options);
163
191
  private eventListeners;
164
192
  on(event: ReactorEvent, handler: EventHandler): void;
@@ -200,6 +228,11 @@ declare class Reactor {
200
228
  connect(jwtToken?: string, options?: ConnectOptions): Promise<void>;
201
229
  /**
202
230
  * Sets up event handlers for the machine client.
231
+ *
232
+ * Each handler captures the client reference at registration time and
233
+ * ignores events if this.machineClient has since changed (e.g. after
234
+ * disconnect + reconnect), preventing stale WebRTC teardown events from
235
+ * interfering with a new connection.
203
236
  */
204
237
  private setupMachineClientHandlers;
205
238
  /**
@@ -225,6 +258,8 @@ declare class Reactor {
225
258
  */
226
259
  getLastError(): ReactorError | undefined;
227
260
  getStats(): ConnectionStats | undefined;
261
+ private resetConnectionTimings;
262
+ private finalizeConnectionTimings;
228
263
  /**
229
264
  * Create and store an error
230
265
  */
@@ -362,9 +397,9 @@ declare function useStats(): ConnectionStats | undefined;
362
397
  * In production, call /tokens from your server and pass the JWT to your frontend.
363
398
  *
364
399
  * @param apiKey - Your Reactor API key (will be exposed in client code!)
365
- * @param coordinatorUrl - Optional coordinator URL, defaults to production
400
+ * @param apiUrl - Optional API URL, defaults to production
366
401
  * @returns string containing the JWT token
367
402
  */
368
- declare function fetchInsecureJwtToken(apiKey: string, coordinatorUrl?: string): Promise<string>;
403
+ declare function fetchInsecureToken(apiKey: string, apiUrl?: string): Promise<string>;
369
404
 
370
- export { type AudioTrackOptions, ConflictError, type ConnectOptions, type ConnectionStats, type MessageScope, type Options, PROD_COORDINATOR_URL, Reactor, type ReactorConnectOptions, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type TrackConfig, type VideoTrackOptions, WebcamStream, type WebcamStreamProps, audio, fetchInsecureJwtToken, useReactor, useReactorInternalMessage, useReactorMessage, useReactorStore, useStats, video };
405
+ export { AbortError, type AudioTrackOptions, ConflictError, type ConnectOptions, type ConnectionStats, type ConnectionTimings, DEFAULT_BASE_URL, type MessageScope, type Options, Reactor, type ReactorConnectOptions, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type TrackConfig, type VideoTrackOptions, WebcamStream, type WebcamStreamProps, audio, fetchInsecureToken, isAbortError, useReactor, useReactorInternalMessage, useReactorMessage, useReactorStore, useStats, video };