@reactor-team/js-sdk 2.0.1 → 2.0.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/index.d.mts CHANGED
@@ -11,6 +11,9 @@ interface ReactorError {
11
11
  component: "coordinator" | "gpu" | "livekit";
12
12
  retryAfter?: number;
13
13
  }
14
+ declare class ConflictError extends Error {
15
+ constructor(message: string);
16
+ }
14
17
  interface ReactorState$1 {
15
18
  status: ReactorStatus;
16
19
  lastError?: ReactorError;
@@ -184,4 +187,4 @@ declare function useReactorMessage(handler: (message: any) => void): void;
184
187
  */
185
188
  declare function fetchInsecureJwtToken(apiKey: string, coordinatorUrl?: string): Promise<string>;
186
189
 
187
- export { type Options, PROD_COORDINATOR_URL, Reactor, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, WebcamStream, fetchInsecureJwtToken, useReactor, useReactorMessage, useReactorStore };
190
+ export { ConflictError, type Options, PROD_COORDINATOR_URL, Reactor, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, WebcamStream, fetchInsecureJwtToken, useReactor, useReactorMessage, useReactorStore };
package/dist/index.d.ts CHANGED
@@ -11,6 +11,9 @@ interface ReactorError {
11
11
  component: "coordinator" | "gpu" | "livekit";
12
12
  retryAfter?: number;
13
13
  }
14
+ declare class ConflictError extends Error {
15
+ constructor(message: string);
16
+ }
14
17
  interface ReactorState$1 {
15
18
  status: ReactorStatus;
16
19
  lastError?: ReactorError;
@@ -184,4 +187,4 @@ declare function useReactorMessage(handler: (message: any) => void): void;
184
187
  */
185
188
  declare function fetchInsecureJwtToken(apiKey: string, coordinatorUrl?: string): Promise<string>;
186
189
 
187
- export { type Options, PROD_COORDINATOR_URL, Reactor, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, WebcamStream, fetchInsecureJwtToken, useReactor, useReactorMessage, useReactorStore };
190
+ export { ConflictError, type Options, PROD_COORDINATOR_URL, Reactor, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, WebcamStream, fetchInsecureJwtToken, useReactor, useReactorMessage, useReactorStore };
package/dist/index.js CHANGED
@@ -79,6 +79,7 @@ var __async = (__this, __arguments, generator) => {
79
79
  // src/index.ts
80
80
  var index_exports = {};
81
81
  __export(index_exports, {
82
+ ConflictError: () => ConflictError,
82
83
  PROD_COORDINATOR_URL: () => PROD_COORDINATOR_URL,
83
84
  Reactor: () => Reactor,
84
85
  ReactorController: () => ReactorController,
@@ -92,6 +93,13 @@ __export(index_exports, {
92
93
  });
93
94
  module.exports = __toCommonJS(index_exports);
94
95
 
96
+ // src/types.ts
97
+ var ConflictError = class extends Error {
98
+ constructor(message) {
99
+ super(message);
100
+ }
101
+ };
102
+
95
103
  // src/core/CoordinatorClient.ts
96
104
  var INITIAL_BACKOFF_MS = 500;
97
105
  var MAX_BACKOFF_MS = 3e4;
@@ -110,6 +118,11 @@ var CoordinatorClient = class {
110
118
  Authorization: `Bearer ${this.jwtToken}`
111
119
  };
112
120
  }
121
+ getIceServers() {
122
+ return __async(this, null, function* () {
123
+ return [{ urls: "stun:stun.l.google.com:19302" }];
124
+ });
125
+ }
113
126
  /**
114
127
  * Creates a new session with the coordinator.
115
128
  * Expects a 200 response and stores the session ID.
@@ -346,6 +359,27 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
346
359
  });
347
360
  this.localBaseUrl = baseUrl;
348
361
  }
362
+ /**
363
+ * Gets ICE servers from the local HTTP runtime.
364
+ * @returns The ICE server configuration
365
+ */
366
+ getIceServers() {
367
+ return __async(this, null, function* () {
368
+ console.debug("[LocalCoordinatorClient] Fetching ICE servers...");
369
+ const response = yield fetch(`${this.localBaseUrl}/ice_servers`, {
370
+ method: "GET"
371
+ });
372
+ if (!response.ok) {
373
+ throw new Error("Failed to get ICE servers from local coordinator.");
374
+ }
375
+ const data = yield response.json();
376
+ console.debug(
377
+ "[LocalCoordinatorClient] Received ICE servers:",
378
+ data.ice_servers
379
+ );
380
+ return data.ice_servers;
381
+ });
382
+ }
349
383
  /**
350
384
  * Creates a local session by posting to /start_session.
351
385
  * @returns always "local"
@@ -386,6 +420,9 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
386
420
  body: JSON.stringify(sdpBody)
387
421
  });
388
422
  if (!response.ok) {
423
+ if (response.status === 409) {
424
+ throw new ConflictError("Connection superseded by newer request");
425
+ }
389
426
  throw new Error("Failed to get SDP answer from local coordinator.");
390
427
  }
391
428
  const sdpAnswer = yield response.json();
@@ -404,15 +441,12 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
404
441
  };
405
442
 
406
443
  // src/utils/webrtc.ts
407
- var DEFAULT_ICE_SERVERS = [
408
- { urls: "stun:stun.l.google.com:19302" },
409
- { urls: "stun:stun1.l.google.com:19302" }
410
- ];
411
444
  var DEFAULT_DATA_CHANNEL_LABEL = "data";
445
+ var FORCE_RELAY_MODE = false;
412
446
  function createPeerConnection(config) {
413
- var _a;
414
447
  return new RTCPeerConnection({
415
- iceServers: (_a = config == null ? void 0 : config.iceServers) != null ? _a : DEFAULT_ICE_SERVERS
448
+ iceServers: config.iceServers,
449
+ iceTransportPolicy: FORCE_RELAY_MODE ? "relay" : "all"
416
450
  });
417
451
  }
418
452
  function createDataChannel(pc, label) {
@@ -493,7 +527,7 @@ var GPUMachineClient = class {
493
527
  constructor(config) {
494
528
  this.eventListeners = /* @__PURE__ */ new Map();
495
529
  this.status = "disconnected";
496
- this.config = config != null ? config : {};
530
+ this.config = config;
497
531
  }
498
532
  // ─────────────────────────────────────────────────────────────────────────────
499
533
  // Event Emitter API
@@ -890,9 +924,14 @@ var Reactor = class {
890
924
  console.warn("[Reactor] No active session to reconnect to.");
891
925
  return;
892
926
  }
927
+ if (this.status === "ready") {
928
+ console.warn("[Reactor] Already connected, no need to reconnect.");
929
+ return;
930
+ }
893
931
  this.setStatus("connecting");
894
932
  if (!this.machineClient) {
895
- this.machineClient = new GPUMachineClient();
933
+ const iceServers = yield this.coordinatorClient.getIceServers();
934
+ this.machineClient = new GPUMachineClient({ iceServers });
896
935
  this.setupMachineClientHandlers();
897
936
  }
898
937
  const sdpOffer = yield this.machineClient.createOffer();
@@ -904,8 +943,12 @@ var Reactor = class {
904
943
  yield this.machineClient.connect(sdpAnswer);
905
944
  this.setStatus("ready");
906
945
  } catch (error) {
946
+ let recoverable = false;
947
+ if (error instanceof ConflictError) {
948
+ recoverable = true;
949
+ }
907
950
  console.error("[Reactor] Failed to reconnect:", error);
908
- this.disconnect(false);
951
+ this.disconnect(recoverable);
909
952
  this.createError(
910
953
  "RECONNECTION_FAILED",
911
954
  `Failed to reconnect: ${error}`,
@@ -940,7 +983,8 @@ var Reactor = class {
940
983
  // Safe: validated on line 186-188
941
984
  model: this.model
942
985
  });
943
- this.machineClient = new GPUMachineClient();
986
+ const iceServers = yield this.coordinatorClient.getIceServers();
987
+ this.machineClient = new GPUMachineClient({ iceServers });
944
988
  this.setupMachineClientHandlers();
945
989
  const sdpOffer = yield this.machineClient.createOffer();
946
990
  const sessionId = yield this.coordinatorClient.createSession(sdpOffer);
@@ -2152,6 +2196,7 @@ function fetchInsecureJwtToken(_0) {
2152
2196
  }
2153
2197
  // Annotate the CommonJS export names for ESM import in node:
2154
2198
  0 && (module.exports = {
2199
+ ConflictError,
2155
2200
  PROD_COORDINATOR_URL,
2156
2201
  Reactor,
2157
2202
  ReactorController,