@reactor-team/js-sdk 2.0.2 → 2.1.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.mjs CHANGED
@@ -57,6 +57,151 @@ var ConflictError = class extends Error {
57
57
  }
58
58
  };
59
59
 
60
+ // src/core/types.ts
61
+ import { z } from "zod";
62
+ var SessionState = /* @__PURE__ */ ((SessionState2) => {
63
+ SessionState2[SessionState2["SESSION_STATE_UNKNOWN"] = 0] = "SESSION_STATE_UNKNOWN";
64
+ SessionState2[SessionState2["SESSION_STATE_WAITING"] = 1] = "SESSION_STATE_WAITING";
65
+ SessionState2[SessionState2["SESSION_STATE_ACTIVE"] = 2] = "SESSION_STATE_ACTIVE";
66
+ SessionState2[SessionState2["SESSION_STATE_DISCONNECTED"] = 3] = "SESSION_STATE_DISCONNECTED";
67
+ SessionState2[SessionState2["SESSION_STATE_CLOSED"] = 4] = "SESSION_STATE_CLOSED";
68
+ SessionState2[SessionState2["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
69
+ return SessionState2;
70
+ })(SessionState || {});
71
+ var CreateSessionRequestSchema = z.object({
72
+ model: z.string(),
73
+ sdp_offer: z.string(),
74
+ extra_args: z.record(z.string(), z.any())
75
+ // Dictionary
76
+ });
77
+ var CreateSessionResponseSchema = z.object({
78
+ session_id: z.uuidv4()
79
+ });
80
+ var SessionStatusResponseSchema = z.object({
81
+ session_id: z.uuidv4(),
82
+ state: SessionState
83
+ });
84
+ var SessionInfoResponseSchema = SessionStatusResponseSchema.extend({
85
+ session_info: CreateSessionRequestSchema.extend({
86
+ session_id: z.uuidv4()
87
+ })
88
+ });
89
+ var SDPParamsRequestSchema = z.object({
90
+ sdp_offer: z.string(),
91
+ extra_args: z.record(z.string(), z.any())
92
+ // Dictionary
93
+ });
94
+ var SDPParamsResponseSchema = z.object({
95
+ sdp_answer: z.string(),
96
+ extra_args: z.record(z.string(), z.any())
97
+ // Dictionary
98
+ });
99
+ var IceServersResponseSchema = z.object({
100
+ ice_servers: z.array(
101
+ z.object({
102
+ uris: z.array(z.string()),
103
+ credentials: z.object({
104
+ username: z.string(),
105
+ password: z.string()
106
+ }).optional()
107
+ })
108
+ )
109
+ });
110
+
111
+ // src/utils/webrtc.ts
112
+ var DEFAULT_DATA_CHANNEL_LABEL = "data";
113
+ var FORCE_RELAY_MODE = false;
114
+ function createPeerConnection(config) {
115
+ return new RTCPeerConnection({
116
+ iceServers: config.iceServers,
117
+ iceTransportPolicy: FORCE_RELAY_MODE ? "relay" : "all"
118
+ });
119
+ }
120
+ function createDataChannel(pc, label) {
121
+ return pc.createDataChannel(label != null ? label : DEFAULT_DATA_CHANNEL_LABEL);
122
+ }
123
+ function createOffer(pc) {
124
+ return __async(this, null, function* () {
125
+ const offer = yield pc.createOffer();
126
+ yield pc.setLocalDescription(offer);
127
+ yield waitForIceGathering(pc);
128
+ const localDescription = pc.localDescription;
129
+ if (!localDescription) {
130
+ throw new Error("Failed to create local description");
131
+ }
132
+ return localDescription.sdp;
133
+ });
134
+ }
135
+ function setRemoteDescription(pc, sdp) {
136
+ return __async(this, null, function* () {
137
+ const sessionDescription = new RTCSessionDescription({
138
+ sdp,
139
+ type: "answer"
140
+ });
141
+ yield pc.setRemoteDescription(sessionDescription);
142
+ });
143
+ }
144
+ function getLocalDescription(pc) {
145
+ const desc = pc.localDescription;
146
+ if (!desc) return void 0;
147
+ return desc.sdp;
148
+ }
149
+ function transformIceServers(response) {
150
+ return response.ice_servers.map((server) => {
151
+ const rtcServer = {
152
+ urls: server.uris
153
+ };
154
+ if (server.credentials) {
155
+ rtcServer.username = server.credentials.username;
156
+ rtcServer.credential = server.credentials.password;
157
+ }
158
+ return rtcServer;
159
+ });
160
+ }
161
+ function waitForIceGathering(pc, timeoutMs = 5e3) {
162
+ return new Promise((resolve) => {
163
+ if (pc.iceGatheringState === "complete") {
164
+ resolve();
165
+ return;
166
+ }
167
+ const onGatheringStateChange = () => {
168
+ if (pc.iceGatheringState === "complete") {
169
+ pc.removeEventListener(
170
+ "icegatheringstatechange",
171
+ onGatheringStateChange
172
+ );
173
+ resolve();
174
+ }
175
+ };
176
+ pc.addEventListener("icegatheringstatechange", onGatheringStateChange);
177
+ setTimeout(() => {
178
+ pc.removeEventListener("icegatheringstatechange", onGatheringStateChange);
179
+ resolve();
180
+ }, timeoutMs);
181
+ });
182
+ }
183
+ function sendMessage(channel, command, data) {
184
+ if (channel.readyState !== "open") {
185
+ throw new Error(`Data channel not open: ${channel.readyState}`);
186
+ }
187
+ const jsonData = typeof data === "string" ? JSON.parse(data) : data;
188
+ const payload = { type: command, data: jsonData };
189
+ channel.send(JSON.stringify(payload));
190
+ }
191
+ function parseMessage(data) {
192
+ if (typeof data === "string") {
193
+ try {
194
+ return JSON.parse(data);
195
+ } catch (e) {
196
+ return data;
197
+ }
198
+ }
199
+ return data;
200
+ }
201
+ function closePeerConnection(pc) {
202
+ pc.close();
203
+ }
204
+
60
205
  // src/core/CoordinatorClient.ts
61
206
  var INITIAL_BACKOFF_MS = 500;
62
207
  var MAX_BACKOFF_MS = 3e4;
@@ -75,9 +220,31 @@ var CoordinatorClient = class {
75
220
  Authorization: `Bearer ${this.jwtToken}`
76
221
  };
77
222
  }
223
+ /**
224
+ * Fetches ICE servers from the coordinator.
225
+ * @returns Array of RTCIceServer objects for WebRTC peer connection configuration
226
+ */
78
227
  getIceServers() {
79
228
  return __async(this, null, function* () {
80
- return [{ urls: "stun:stun.l.google.com:19302" }];
229
+ console.debug("[CoordinatorClient] Fetching ICE servers...");
230
+ const response = yield fetch(
231
+ `${this.baseUrl}/ice_servers?model=${this.model}`,
232
+ {
233
+ method: "GET",
234
+ headers: this.getAuthHeaders()
235
+ }
236
+ );
237
+ if (!response.ok) {
238
+ throw new Error(`Failed to fetch ICE servers: ${response.status}`);
239
+ }
240
+ const data = yield response.json();
241
+ const parsed = IceServersResponseSchema.parse(data);
242
+ const iceServers = transformIceServers(parsed);
243
+ console.debug(
244
+ "[CoordinatorClient] Received ICE servers:",
245
+ iceServers.length
246
+ );
247
+ return iceServers;
81
248
  });
82
249
  }
83
250
  /**
@@ -330,11 +497,13 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
330
497
  throw new Error("Failed to get ICE servers from local coordinator.");
331
498
  }
332
499
  const data = yield response.json();
500
+ const parsed = IceServersResponseSchema.parse(data);
501
+ const iceServers = transformIceServers(parsed);
333
502
  console.debug(
334
503
  "[LocalCoordinatorClient] Received ICE servers:",
335
- data.ice_servers
504
+ iceServers.length
336
505
  );
337
- return data.ice_servers;
506
+ return iceServers;
338
507
  });
339
508
  }
340
509
  /**
@@ -397,88 +566,6 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
397
566
  }
398
567
  };
399
568
 
400
- // src/utils/webrtc.ts
401
- var DEFAULT_DATA_CHANNEL_LABEL = "data";
402
- var FORCE_RELAY_MODE = false;
403
- function createPeerConnection(config) {
404
- return new RTCPeerConnection({
405
- iceServers: config.iceServers,
406
- iceTransportPolicy: FORCE_RELAY_MODE ? "relay" : "all"
407
- });
408
- }
409
- function createDataChannel(pc, label) {
410
- return pc.createDataChannel(label != null ? label : DEFAULT_DATA_CHANNEL_LABEL);
411
- }
412
- function createOffer(pc) {
413
- return __async(this, null, function* () {
414
- const offer = yield pc.createOffer();
415
- yield pc.setLocalDescription(offer);
416
- yield waitForIceGathering(pc);
417
- const localDescription = pc.localDescription;
418
- if (!localDescription) {
419
- throw new Error("Failed to create local description");
420
- }
421
- return localDescription.sdp;
422
- });
423
- }
424
- function setRemoteDescription(pc, sdp) {
425
- return __async(this, null, function* () {
426
- const sessionDescription = new RTCSessionDescription({
427
- sdp,
428
- type: "answer"
429
- });
430
- yield pc.setRemoteDescription(sessionDescription);
431
- });
432
- }
433
- function getLocalDescription(pc) {
434
- const desc = pc.localDescription;
435
- if (!desc) return void 0;
436
- return desc.sdp;
437
- }
438
- function waitForIceGathering(pc, timeoutMs = 5e3) {
439
- return new Promise((resolve) => {
440
- if (pc.iceGatheringState === "complete") {
441
- resolve();
442
- return;
443
- }
444
- const onGatheringStateChange = () => {
445
- if (pc.iceGatheringState === "complete") {
446
- pc.removeEventListener(
447
- "icegatheringstatechange",
448
- onGatheringStateChange
449
- );
450
- resolve();
451
- }
452
- };
453
- pc.addEventListener("icegatheringstatechange", onGatheringStateChange);
454
- setTimeout(() => {
455
- pc.removeEventListener("icegatheringstatechange", onGatheringStateChange);
456
- resolve();
457
- }, timeoutMs);
458
- });
459
- }
460
- function sendMessage(channel, command, data) {
461
- if (channel.readyState !== "open") {
462
- throw new Error(`Data channel not open: ${channel.readyState}`);
463
- }
464
- const jsonData = typeof data === "string" ? JSON.parse(data) : data;
465
- const payload = { type: command, data: jsonData };
466
- channel.send(JSON.stringify(payload));
467
- }
468
- function parseMessage(data) {
469
- if (typeof data === "string") {
470
- try {
471
- return JSON.parse(data);
472
- } catch (e) {
473
- return data;
474
- }
475
- }
476
- return data;
477
- }
478
- function closePeerConnection(pc) {
479
- pc.close();
480
- }
481
-
482
569
  // src/core/GPUMachineClient.ts
483
570
  var GPUMachineClient = class {
484
571
  constructor(config) {
@@ -765,13 +852,13 @@ var GPUMachineClient = class {
765
852
  };
766
853
 
767
854
  // src/core/Reactor.ts
768
- import { z } from "zod";
855
+ import { z as z2 } from "zod";
769
856
  var LOCAL_COORDINATOR_URL = "http://localhost:8080";
770
857
  var PROD_COORDINATOR_URL = "https://api.reactor.inc";
771
- var OptionsSchema = z.object({
772
- coordinatorUrl: z.string().default(PROD_COORDINATOR_URL),
773
- modelName: z.string(),
774
- local: z.boolean().default(false)
858
+ var OptionsSchema = z2.object({
859
+ coordinatorUrl: z2.string().default(PROD_COORDINATOR_URL),
860
+ modelName: z2.string(),
861
+ local: z2.boolean().default(false)
775
862
  });
776
863
  var Reactor = class {
777
864
  constructor(options) {