@reactor-team/js-sdk 2.0.2 → 2.2.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.js +182 -91
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +182 -91
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -57,6 +57,155 @@ 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["CREATED"] = 0] = "CREATED";
|
|
64
|
+
SessionState2[SessionState2["PENDING"] = 1] = "PENDING";
|
|
65
|
+
SessionState2[SessionState2["SUSPENDED"] = 2] = "SUSPENDED";
|
|
66
|
+
SessionState2[SessionState2["WAITING"] = 3] = "WAITING";
|
|
67
|
+
SessionState2[SessionState2["ACTIVE"] = 4] = "ACTIVE";
|
|
68
|
+
SessionState2[SessionState2["INACTIVE"] = 5] = "INACTIVE";
|
|
69
|
+
SessionState2[SessionState2["CLOSED"] = 6] = "CLOSED";
|
|
70
|
+
return SessionState2;
|
|
71
|
+
})(SessionState || {});
|
|
72
|
+
var ModelSchema = z.object({
|
|
73
|
+
name: z.string()
|
|
74
|
+
});
|
|
75
|
+
var CreateSessionRequestSchema = z.object({
|
|
76
|
+
model: ModelSchema,
|
|
77
|
+
sdp_offer: z.string(),
|
|
78
|
+
extra_args: z.record(z.string(), z.any())
|
|
79
|
+
// Dictionary
|
|
80
|
+
});
|
|
81
|
+
var CreateSessionResponseSchema = z.object({
|
|
82
|
+
session_id: z.uuidv4()
|
|
83
|
+
});
|
|
84
|
+
var SessionStatusResponseSchema = z.object({
|
|
85
|
+
session_id: z.uuidv4(),
|
|
86
|
+
state: SessionState
|
|
87
|
+
});
|
|
88
|
+
var SessionInfoResponseSchema = SessionStatusResponseSchema.extend({
|
|
89
|
+
session_info: CreateSessionRequestSchema.extend({
|
|
90
|
+
session_id: z.uuidv4()
|
|
91
|
+
})
|
|
92
|
+
});
|
|
93
|
+
var SDPParamsRequestSchema = z.object({
|
|
94
|
+
sdp_offer: z.string(),
|
|
95
|
+
extra_args: z.record(z.string(), z.any())
|
|
96
|
+
// Dictionary
|
|
97
|
+
});
|
|
98
|
+
var SDPParamsResponseSchema = z.object({
|
|
99
|
+
sdp_answer: z.string(),
|
|
100
|
+
extra_args: z.record(z.string(), z.any())
|
|
101
|
+
// Dictionary
|
|
102
|
+
});
|
|
103
|
+
var IceServersResponseSchema = z.object({
|
|
104
|
+
ice_servers: z.array(
|
|
105
|
+
z.object({
|
|
106
|
+
uris: z.array(z.string()),
|
|
107
|
+
credentials: z.object({
|
|
108
|
+
username: z.string(),
|
|
109
|
+
password: z.string()
|
|
110
|
+
}).optional()
|
|
111
|
+
})
|
|
112
|
+
)
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// src/utils/webrtc.ts
|
|
116
|
+
var DEFAULT_DATA_CHANNEL_LABEL = "data";
|
|
117
|
+
var FORCE_RELAY_MODE = false;
|
|
118
|
+
function createPeerConnection(config) {
|
|
119
|
+
return new RTCPeerConnection({
|
|
120
|
+
iceServers: config.iceServers,
|
|
121
|
+
iceTransportPolicy: FORCE_RELAY_MODE ? "relay" : "all"
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function createDataChannel(pc, label) {
|
|
125
|
+
return pc.createDataChannel(label != null ? label : DEFAULT_DATA_CHANNEL_LABEL);
|
|
126
|
+
}
|
|
127
|
+
function createOffer(pc) {
|
|
128
|
+
return __async(this, null, function* () {
|
|
129
|
+
const offer = yield pc.createOffer();
|
|
130
|
+
yield pc.setLocalDescription(offer);
|
|
131
|
+
yield waitForIceGathering(pc);
|
|
132
|
+
const localDescription = pc.localDescription;
|
|
133
|
+
if (!localDescription) {
|
|
134
|
+
throw new Error("Failed to create local description");
|
|
135
|
+
}
|
|
136
|
+
return localDescription.sdp;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function setRemoteDescription(pc, sdp) {
|
|
140
|
+
return __async(this, null, function* () {
|
|
141
|
+
const sessionDescription = new RTCSessionDescription({
|
|
142
|
+
sdp,
|
|
143
|
+
type: "answer"
|
|
144
|
+
});
|
|
145
|
+
yield pc.setRemoteDescription(sessionDescription);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function getLocalDescription(pc) {
|
|
149
|
+
const desc = pc.localDescription;
|
|
150
|
+
if (!desc) return void 0;
|
|
151
|
+
return desc.sdp;
|
|
152
|
+
}
|
|
153
|
+
function transformIceServers(response) {
|
|
154
|
+
return response.ice_servers.map((server) => {
|
|
155
|
+
const rtcServer = {
|
|
156
|
+
urls: server.uris
|
|
157
|
+
};
|
|
158
|
+
if (server.credentials) {
|
|
159
|
+
rtcServer.username = server.credentials.username;
|
|
160
|
+
rtcServer.credential = server.credentials.password;
|
|
161
|
+
}
|
|
162
|
+
return rtcServer;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
function waitForIceGathering(pc, timeoutMs = 5e3) {
|
|
166
|
+
return new Promise((resolve) => {
|
|
167
|
+
if (pc.iceGatheringState === "complete") {
|
|
168
|
+
resolve();
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const onGatheringStateChange = () => {
|
|
172
|
+
if (pc.iceGatheringState === "complete") {
|
|
173
|
+
pc.removeEventListener(
|
|
174
|
+
"icegatheringstatechange",
|
|
175
|
+
onGatheringStateChange
|
|
176
|
+
);
|
|
177
|
+
resolve();
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
pc.addEventListener("icegatheringstatechange", onGatheringStateChange);
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
pc.removeEventListener("icegatheringstatechange", onGatheringStateChange);
|
|
183
|
+
resolve();
|
|
184
|
+
}, timeoutMs);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function sendMessage(channel, command, data) {
|
|
188
|
+
if (channel.readyState !== "open") {
|
|
189
|
+
throw new Error(`Data channel not open: ${channel.readyState}`);
|
|
190
|
+
}
|
|
191
|
+
const jsonData = typeof data === "string" ? JSON.parse(data) : data;
|
|
192
|
+
const payload = { type: command, data: jsonData };
|
|
193
|
+
channel.send(JSON.stringify(payload));
|
|
194
|
+
}
|
|
195
|
+
function parseMessage(data) {
|
|
196
|
+
if (typeof data === "string") {
|
|
197
|
+
try {
|
|
198
|
+
return JSON.parse(data);
|
|
199
|
+
} catch (e) {
|
|
200
|
+
return data;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return data;
|
|
204
|
+
}
|
|
205
|
+
function closePeerConnection(pc) {
|
|
206
|
+
pc.close();
|
|
207
|
+
}
|
|
208
|
+
|
|
60
209
|
// src/core/CoordinatorClient.ts
|
|
61
210
|
var INITIAL_BACKOFF_MS = 500;
|
|
62
211
|
var MAX_BACKOFF_MS = 3e4;
|
|
@@ -75,9 +224,31 @@ var CoordinatorClient = class {
|
|
|
75
224
|
Authorization: `Bearer ${this.jwtToken}`
|
|
76
225
|
};
|
|
77
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Fetches ICE servers from the coordinator.
|
|
229
|
+
* @returns Array of RTCIceServer objects for WebRTC peer connection configuration
|
|
230
|
+
*/
|
|
78
231
|
getIceServers() {
|
|
79
232
|
return __async(this, null, function* () {
|
|
80
|
-
|
|
233
|
+
console.debug("[CoordinatorClient] Fetching ICE servers...");
|
|
234
|
+
const response = yield fetch(
|
|
235
|
+
`${this.baseUrl}/ice_servers?model=${this.model}`,
|
|
236
|
+
{
|
|
237
|
+
method: "GET",
|
|
238
|
+
headers: this.getAuthHeaders()
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
if (!response.ok) {
|
|
242
|
+
throw new Error(`Failed to fetch ICE servers: ${response.status}`);
|
|
243
|
+
}
|
|
244
|
+
const data = yield response.json();
|
|
245
|
+
const parsed = IceServersResponseSchema.parse(data);
|
|
246
|
+
const iceServers = transformIceServers(parsed);
|
|
247
|
+
console.debug(
|
|
248
|
+
"[CoordinatorClient] Received ICE servers:",
|
|
249
|
+
iceServers.length
|
|
250
|
+
);
|
|
251
|
+
return iceServers;
|
|
81
252
|
});
|
|
82
253
|
}
|
|
83
254
|
/**
|
|
@@ -89,7 +260,7 @@ var CoordinatorClient = class {
|
|
|
89
260
|
return __async(this, null, function* () {
|
|
90
261
|
console.debug("[CoordinatorClient] Creating session...");
|
|
91
262
|
const requestBody = {
|
|
92
|
-
model: this.model,
|
|
263
|
+
model: { name: this.model },
|
|
93
264
|
sdp_offer,
|
|
94
265
|
extra_args: {}
|
|
95
266
|
};
|
|
@@ -330,11 +501,13 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
|
|
|
330
501
|
throw new Error("Failed to get ICE servers from local coordinator.");
|
|
331
502
|
}
|
|
332
503
|
const data = yield response.json();
|
|
504
|
+
const parsed = IceServersResponseSchema.parse(data);
|
|
505
|
+
const iceServers = transformIceServers(parsed);
|
|
333
506
|
console.debug(
|
|
334
507
|
"[LocalCoordinatorClient] Received ICE servers:",
|
|
335
|
-
|
|
508
|
+
iceServers.length
|
|
336
509
|
);
|
|
337
|
-
return
|
|
510
|
+
return iceServers;
|
|
338
511
|
});
|
|
339
512
|
}
|
|
340
513
|
/**
|
|
@@ -397,88 +570,6 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
|
|
|
397
570
|
}
|
|
398
571
|
};
|
|
399
572
|
|
|
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
573
|
// src/core/GPUMachineClient.ts
|
|
483
574
|
var GPUMachineClient = class {
|
|
484
575
|
constructor(config) {
|
|
@@ -765,13 +856,13 @@ var GPUMachineClient = class {
|
|
|
765
856
|
};
|
|
766
857
|
|
|
767
858
|
// src/core/Reactor.ts
|
|
768
|
-
import { z } from "zod";
|
|
859
|
+
import { z as z2 } from "zod";
|
|
769
860
|
var LOCAL_COORDINATOR_URL = "http://localhost:8080";
|
|
770
861
|
var PROD_COORDINATOR_URL = "https://api.reactor.inc";
|
|
771
|
-
var OptionsSchema =
|
|
772
|
-
coordinatorUrl:
|
|
773
|
-
modelName:
|
|
774
|
-
local:
|
|
862
|
+
var OptionsSchema = z2.object({
|
|
863
|
+
coordinatorUrl: z2.string().default(PROD_COORDINATOR_URL),
|
|
864
|
+
modelName: z2.string(),
|
|
865
|
+
local: z2.boolean().default(false)
|
|
775
866
|
});
|
|
776
867
|
var Reactor = class {
|
|
777
868
|
constructor(options) {
|