@reactor-team/js-sdk 2.0.1 → 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.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +226 -94
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +225 -94
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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,158 @@ __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
|
+
|
|
103
|
+
// src/core/types.ts
|
|
104
|
+
var import_zod = require("zod");
|
|
105
|
+
var SessionState = /* @__PURE__ */ ((SessionState2) => {
|
|
106
|
+
SessionState2[SessionState2["SESSION_STATE_UNKNOWN"] = 0] = "SESSION_STATE_UNKNOWN";
|
|
107
|
+
SessionState2[SessionState2["SESSION_STATE_WAITING"] = 1] = "SESSION_STATE_WAITING";
|
|
108
|
+
SessionState2[SessionState2["SESSION_STATE_ACTIVE"] = 2] = "SESSION_STATE_ACTIVE";
|
|
109
|
+
SessionState2[SessionState2["SESSION_STATE_DISCONNECTED"] = 3] = "SESSION_STATE_DISCONNECTED";
|
|
110
|
+
SessionState2[SessionState2["SESSION_STATE_CLOSED"] = 4] = "SESSION_STATE_CLOSED";
|
|
111
|
+
SessionState2[SessionState2["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
|
|
112
|
+
return SessionState2;
|
|
113
|
+
})(SessionState || {});
|
|
114
|
+
var CreateSessionRequestSchema = import_zod.z.object({
|
|
115
|
+
model: import_zod.z.string(),
|
|
116
|
+
sdp_offer: import_zod.z.string(),
|
|
117
|
+
extra_args: import_zod.z.record(import_zod.z.string(), import_zod.z.any())
|
|
118
|
+
// Dictionary
|
|
119
|
+
});
|
|
120
|
+
var CreateSessionResponseSchema = import_zod.z.object({
|
|
121
|
+
session_id: import_zod.z.uuidv4()
|
|
122
|
+
});
|
|
123
|
+
var SessionStatusResponseSchema = import_zod.z.object({
|
|
124
|
+
session_id: import_zod.z.uuidv4(),
|
|
125
|
+
state: SessionState
|
|
126
|
+
});
|
|
127
|
+
var SessionInfoResponseSchema = SessionStatusResponseSchema.extend({
|
|
128
|
+
session_info: CreateSessionRequestSchema.extend({
|
|
129
|
+
session_id: import_zod.z.uuidv4()
|
|
130
|
+
})
|
|
131
|
+
});
|
|
132
|
+
var SDPParamsRequestSchema = import_zod.z.object({
|
|
133
|
+
sdp_offer: import_zod.z.string(),
|
|
134
|
+
extra_args: import_zod.z.record(import_zod.z.string(), import_zod.z.any())
|
|
135
|
+
// Dictionary
|
|
136
|
+
});
|
|
137
|
+
var SDPParamsResponseSchema = import_zod.z.object({
|
|
138
|
+
sdp_answer: import_zod.z.string(),
|
|
139
|
+
extra_args: import_zod.z.record(import_zod.z.string(), import_zod.z.any())
|
|
140
|
+
// Dictionary
|
|
141
|
+
});
|
|
142
|
+
var IceServersResponseSchema = import_zod.z.object({
|
|
143
|
+
ice_servers: import_zod.z.array(
|
|
144
|
+
import_zod.z.object({
|
|
145
|
+
uris: import_zod.z.array(import_zod.z.string()),
|
|
146
|
+
credentials: import_zod.z.object({
|
|
147
|
+
username: import_zod.z.string(),
|
|
148
|
+
password: import_zod.z.string()
|
|
149
|
+
}).optional()
|
|
150
|
+
})
|
|
151
|
+
)
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// src/utils/webrtc.ts
|
|
155
|
+
var DEFAULT_DATA_CHANNEL_LABEL = "data";
|
|
156
|
+
var FORCE_RELAY_MODE = false;
|
|
157
|
+
function createPeerConnection(config) {
|
|
158
|
+
return new RTCPeerConnection({
|
|
159
|
+
iceServers: config.iceServers,
|
|
160
|
+
iceTransportPolicy: FORCE_RELAY_MODE ? "relay" : "all"
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function createDataChannel(pc, label) {
|
|
164
|
+
return pc.createDataChannel(label != null ? label : DEFAULT_DATA_CHANNEL_LABEL);
|
|
165
|
+
}
|
|
166
|
+
function createOffer(pc) {
|
|
167
|
+
return __async(this, null, function* () {
|
|
168
|
+
const offer = yield pc.createOffer();
|
|
169
|
+
yield pc.setLocalDescription(offer);
|
|
170
|
+
yield waitForIceGathering(pc);
|
|
171
|
+
const localDescription = pc.localDescription;
|
|
172
|
+
if (!localDescription) {
|
|
173
|
+
throw new Error("Failed to create local description");
|
|
174
|
+
}
|
|
175
|
+
return localDescription.sdp;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function setRemoteDescription(pc, sdp) {
|
|
179
|
+
return __async(this, null, function* () {
|
|
180
|
+
const sessionDescription = new RTCSessionDescription({
|
|
181
|
+
sdp,
|
|
182
|
+
type: "answer"
|
|
183
|
+
});
|
|
184
|
+
yield pc.setRemoteDescription(sessionDescription);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function getLocalDescription(pc) {
|
|
188
|
+
const desc = pc.localDescription;
|
|
189
|
+
if (!desc) return void 0;
|
|
190
|
+
return desc.sdp;
|
|
191
|
+
}
|
|
192
|
+
function transformIceServers(response) {
|
|
193
|
+
return response.ice_servers.map((server) => {
|
|
194
|
+
const rtcServer = {
|
|
195
|
+
urls: server.uris
|
|
196
|
+
};
|
|
197
|
+
if (server.credentials) {
|
|
198
|
+
rtcServer.username = server.credentials.username;
|
|
199
|
+
rtcServer.credential = server.credentials.password;
|
|
200
|
+
}
|
|
201
|
+
return rtcServer;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function waitForIceGathering(pc, timeoutMs = 5e3) {
|
|
205
|
+
return new Promise((resolve) => {
|
|
206
|
+
if (pc.iceGatheringState === "complete") {
|
|
207
|
+
resolve();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const onGatheringStateChange = () => {
|
|
211
|
+
if (pc.iceGatheringState === "complete") {
|
|
212
|
+
pc.removeEventListener(
|
|
213
|
+
"icegatheringstatechange",
|
|
214
|
+
onGatheringStateChange
|
|
215
|
+
);
|
|
216
|
+
resolve();
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
pc.addEventListener("icegatheringstatechange", onGatheringStateChange);
|
|
220
|
+
setTimeout(() => {
|
|
221
|
+
pc.removeEventListener("icegatheringstatechange", onGatheringStateChange);
|
|
222
|
+
resolve();
|
|
223
|
+
}, timeoutMs);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function sendMessage(channel, command, data) {
|
|
227
|
+
if (channel.readyState !== "open") {
|
|
228
|
+
throw new Error(`Data channel not open: ${channel.readyState}`);
|
|
229
|
+
}
|
|
230
|
+
const jsonData = typeof data === "string" ? JSON.parse(data) : data;
|
|
231
|
+
const payload = { type: command, data: jsonData };
|
|
232
|
+
channel.send(JSON.stringify(payload));
|
|
233
|
+
}
|
|
234
|
+
function parseMessage(data) {
|
|
235
|
+
if (typeof data === "string") {
|
|
236
|
+
try {
|
|
237
|
+
return JSON.parse(data);
|
|
238
|
+
} catch (e) {
|
|
239
|
+
return data;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return data;
|
|
243
|
+
}
|
|
244
|
+
function closePeerConnection(pc) {
|
|
245
|
+
pc.close();
|
|
246
|
+
}
|
|
247
|
+
|
|
95
248
|
// src/core/CoordinatorClient.ts
|
|
96
249
|
var INITIAL_BACKOFF_MS = 500;
|
|
97
250
|
var MAX_BACKOFF_MS = 3e4;
|
|
@@ -110,6 +263,33 @@ var CoordinatorClient = class {
|
|
|
110
263
|
Authorization: `Bearer ${this.jwtToken}`
|
|
111
264
|
};
|
|
112
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* Fetches ICE servers from the coordinator.
|
|
268
|
+
* @returns Array of RTCIceServer objects for WebRTC peer connection configuration
|
|
269
|
+
*/
|
|
270
|
+
getIceServers() {
|
|
271
|
+
return __async(this, null, function* () {
|
|
272
|
+
console.debug("[CoordinatorClient] Fetching ICE servers...");
|
|
273
|
+
const response = yield fetch(
|
|
274
|
+
`${this.baseUrl}/ice_servers?model=${this.model}`,
|
|
275
|
+
{
|
|
276
|
+
method: "GET",
|
|
277
|
+
headers: this.getAuthHeaders()
|
|
278
|
+
}
|
|
279
|
+
);
|
|
280
|
+
if (!response.ok) {
|
|
281
|
+
throw new Error(`Failed to fetch ICE servers: ${response.status}`);
|
|
282
|
+
}
|
|
283
|
+
const data = yield response.json();
|
|
284
|
+
const parsed = IceServersResponseSchema.parse(data);
|
|
285
|
+
const iceServers = transformIceServers(parsed);
|
|
286
|
+
console.debug(
|
|
287
|
+
"[CoordinatorClient] Received ICE servers:",
|
|
288
|
+
iceServers.length
|
|
289
|
+
);
|
|
290
|
+
return iceServers;
|
|
291
|
+
});
|
|
292
|
+
}
|
|
113
293
|
/**
|
|
114
294
|
* Creates a new session with the coordinator.
|
|
115
295
|
* Expects a 200 response and stores the session ID.
|
|
@@ -346,6 +526,29 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
|
|
|
346
526
|
});
|
|
347
527
|
this.localBaseUrl = baseUrl;
|
|
348
528
|
}
|
|
529
|
+
/**
|
|
530
|
+
* Gets ICE servers from the local HTTP runtime.
|
|
531
|
+
* @returns The ICE server configuration
|
|
532
|
+
*/
|
|
533
|
+
getIceServers() {
|
|
534
|
+
return __async(this, null, function* () {
|
|
535
|
+
console.debug("[LocalCoordinatorClient] Fetching ICE servers...");
|
|
536
|
+
const response = yield fetch(`${this.localBaseUrl}/ice_servers`, {
|
|
537
|
+
method: "GET"
|
|
538
|
+
});
|
|
539
|
+
if (!response.ok) {
|
|
540
|
+
throw new Error("Failed to get ICE servers from local coordinator.");
|
|
541
|
+
}
|
|
542
|
+
const data = yield response.json();
|
|
543
|
+
const parsed = IceServersResponseSchema.parse(data);
|
|
544
|
+
const iceServers = transformIceServers(parsed);
|
|
545
|
+
console.debug(
|
|
546
|
+
"[LocalCoordinatorClient] Received ICE servers:",
|
|
547
|
+
iceServers.length
|
|
548
|
+
);
|
|
549
|
+
return iceServers;
|
|
550
|
+
});
|
|
551
|
+
}
|
|
349
552
|
/**
|
|
350
553
|
* Creates a local session by posting to /start_session.
|
|
351
554
|
* @returns always "local"
|
|
@@ -386,6 +589,9 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
|
|
|
386
589
|
body: JSON.stringify(sdpBody)
|
|
387
590
|
});
|
|
388
591
|
if (!response.ok) {
|
|
592
|
+
if (response.status === 409) {
|
|
593
|
+
throw new ConflictError("Connection superseded by newer request");
|
|
594
|
+
}
|
|
389
595
|
throw new Error("Failed to get SDP answer from local coordinator.");
|
|
390
596
|
}
|
|
391
597
|
const sdpAnswer = yield response.json();
|
|
@@ -403,97 +609,12 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
|
|
|
403
609
|
}
|
|
404
610
|
};
|
|
405
611
|
|
|
406
|
-
// 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
|
-
var DEFAULT_DATA_CHANNEL_LABEL = "data";
|
|
412
|
-
function createPeerConnection(config) {
|
|
413
|
-
var _a;
|
|
414
|
-
return new RTCPeerConnection({
|
|
415
|
-
iceServers: (_a = config == null ? void 0 : config.iceServers) != null ? _a : DEFAULT_ICE_SERVERS
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
function createDataChannel(pc, label) {
|
|
419
|
-
return pc.createDataChannel(label != null ? label : DEFAULT_DATA_CHANNEL_LABEL);
|
|
420
|
-
}
|
|
421
|
-
function createOffer(pc) {
|
|
422
|
-
return __async(this, null, function* () {
|
|
423
|
-
const offer = yield pc.createOffer();
|
|
424
|
-
yield pc.setLocalDescription(offer);
|
|
425
|
-
yield waitForIceGathering(pc);
|
|
426
|
-
const localDescription = pc.localDescription;
|
|
427
|
-
if (!localDescription) {
|
|
428
|
-
throw new Error("Failed to create local description");
|
|
429
|
-
}
|
|
430
|
-
return localDescription.sdp;
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
function setRemoteDescription(pc, sdp) {
|
|
434
|
-
return __async(this, null, function* () {
|
|
435
|
-
const sessionDescription = new RTCSessionDescription({
|
|
436
|
-
sdp,
|
|
437
|
-
type: "answer"
|
|
438
|
-
});
|
|
439
|
-
yield pc.setRemoteDescription(sessionDescription);
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
function getLocalDescription(pc) {
|
|
443
|
-
const desc = pc.localDescription;
|
|
444
|
-
if (!desc) return void 0;
|
|
445
|
-
return desc.sdp;
|
|
446
|
-
}
|
|
447
|
-
function waitForIceGathering(pc, timeoutMs = 5e3) {
|
|
448
|
-
return new Promise((resolve) => {
|
|
449
|
-
if (pc.iceGatheringState === "complete") {
|
|
450
|
-
resolve();
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
const onGatheringStateChange = () => {
|
|
454
|
-
if (pc.iceGatheringState === "complete") {
|
|
455
|
-
pc.removeEventListener(
|
|
456
|
-
"icegatheringstatechange",
|
|
457
|
-
onGatheringStateChange
|
|
458
|
-
);
|
|
459
|
-
resolve();
|
|
460
|
-
}
|
|
461
|
-
};
|
|
462
|
-
pc.addEventListener("icegatheringstatechange", onGatheringStateChange);
|
|
463
|
-
setTimeout(() => {
|
|
464
|
-
pc.removeEventListener("icegatheringstatechange", onGatheringStateChange);
|
|
465
|
-
resolve();
|
|
466
|
-
}, timeoutMs);
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
function sendMessage(channel, command, data) {
|
|
470
|
-
if (channel.readyState !== "open") {
|
|
471
|
-
throw new Error(`Data channel not open: ${channel.readyState}`);
|
|
472
|
-
}
|
|
473
|
-
const jsonData = typeof data === "string" ? JSON.parse(data) : data;
|
|
474
|
-
const payload = { type: command, data: jsonData };
|
|
475
|
-
channel.send(JSON.stringify(payload));
|
|
476
|
-
}
|
|
477
|
-
function parseMessage(data) {
|
|
478
|
-
if (typeof data === "string") {
|
|
479
|
-
try {
|
|
480
|
-
return JSON.parse(data);
|
|
481
|
-
} catch (e) {
|
|
482
|
-
return data;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
return data;
|
|
486
|
-
}
|
|
487
|
-
function closePeerConnection(pc) {
|
|
488
|
-
pc.close();
|
|
489
|
-
}
|
|
490
|
-
|
|
491
612
|
// src/core/GPUMachineClient.ts
|
|
492
613
|
var GPUMachineClient = class {
|
|
493
614
|
constructor(config) {
|
|
494
615
|
this.eventListeners = /* @__PURE__ */ new Map();
|
|
495
616
|
this.status = "disconnected";
|
|
496
|
-
this.config = config
|
|
617
|
+
this.config = config;
|
|
497
618
|
}
|
|
498
619
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
499
620
|
// Event Emitter API
|
|
@@ -774,13 +895,13 @@ var GPUMachineClient = class {
|
|
|
774
895
|
};
|
|
775
896
|
|
|
776
897
|
// src/core/Reactor.ts
|
|
777
|
-
var
|
|
898
|
+
var import_zod2 = require("zod");
|
|
778
899
|
var LOCAL_COORDINATOR_URL = "http://localhost:8080";
|
|
779
900
|
var PROD_COORDINATOR_URL = "https://api.reactor.inc";
|
|
780
|
-
var OptionsSchema =
|
|
781
|
-
coordinatorUrl:
|
|
782
|
-
modelName:
|
|
783
|
-
local:
|
|
901
|
+
var OptionsSchema = import_zod2.z.object({
|
|
902
|
+
coordinatorUrl: import_zod2.z.string().default(PROD_COORDINATOR_URL),
|
|
903
|
+
modelName: import_zod2.z.string(),
|
|
904
|
+
local: import_zod2.z.boolean().default(false)
|
|
784
905
|
});
|
|
785
906
|
var Reactor = class {
|
|
786
907
|
constructor(options) {
|
|
@@ -890,9 +1011,14 @@ var Reactor = class {
|
|
|
890
1011
|
console.warn("[Reactor] No active session to reconnect to.");
|
|
891
1012
|
return;
|
|
892
1013
|
}
|
|
1014
|
+
if (this.status === "ready") {
|
|
1015
|
+
console.warn("[Reactor] Already connected, no need to reconnect.");
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
893
1018
|
this.setStatus("connecting");
|
|
894
1019
|
if (!this.machineClient) {
|
|
895
|
-
|
|
1020
|
+
const iceServers = yield this.coordinatorClient.getIceServers();
|
|
1021
|
+
this.machineClient = new GPUMachineClient({ iceServers });
|
|
896
1022
|
this.setupMachineClientHandlers();
|
|
897
1023
|
}
|
|
898
1024
|
const sdpOffer = yield this.machineClient.createOffer();
|
|
@@ -904,8 +1030,12 @@ var Reactor = class {
|
|
|
904
1030
|
yield this.machineClient.connect(sdpAnswer);
|
|
905
1031
|
this.setStatus("ready");
|
|
906
1032
|
} catch (error) {
|
|
1033
|
+
let recoverable = false;
|
|
1034
|
+
if (error instanceof ConflictError) {
|
|
1035
|
+
recoverable = true;
|
|
1036
|
+
}
|
|
907
1037
|
console.error("[Reactor] Failed to reconnect:", error);
|
|
908
|
-
this.disconnect(
|
|
1038
|
+
this.disconnect(recoverable);
|
|
909
1039
|
this.createError(
|
|
910
1040
|
"RECONNECTION_FAILED",
|
|
911
1041
|
`Failed to reconnect: ${error}`,
|
|
@@ -940,7 +1070,8 @@ var Reactor = class {
|
|
|
940
1070
|
// Safe: validated on line 186-188
|
|
941
1071
|
model: this.model
|
|
942
1072
|
});
|
|
943
|
-
|
|
1073
|
+
const iceServers = yield this.coordinatorClient.getIceServers();
|
|
1074
|
+
this.machineClient = new GPUMachineClient({ iceServers });
|
|
944
1075
|
this.setupMachineClientHandlers();
|
|
945
1076
|
const sdpOffer = yield this.machineClient.createOffer();
|
|
946
1077
|
const sessionId = yield this.coordinatorClient.createSession(sdpOffer);
|
|
@@ -2152,6 +2283,7 @@ function fetchInsecureJwtToken(_0) {
|
|
|
2152
2283
|
}
|
|
2153
2284
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2154
2285
|
0 && (module.exports = {
|
|
2286
|
+
ConflictError,
|
|
2155
2287
|
PROD_COORDINATOR_URL,
|
|
2156
2288
|
Reactor,
|
|
2157
2289
|
ReactorController,
|