@reactor-team/js-sdk 2.2.2 → 2.3.1
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 +20 -7
- package/dist/index.d.ts +20 -7
- package/dist/index.js +76 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +76 -27
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -184,12 +184,13 @@ function waitForIceGathering(pc, timeoutMs = 5e3) {
|
|
|
184
184
|
}, timeoutMs);
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
|
-
function sendMessage(channel, command, data) {
|
|
187
|
+
function sendMessage(channel, command, data, scope = "application") {
|
|
188
188
|
if (channel.readyState !== "open") {
|
|
189
189
|
throw new Error(`Data channel not open: ${channel.readyState}`);
|
|
190
190
|
}
|
|
191
191
|
const jsonData = typeof data === "string" ? JSON.parse(data) : data;
|
|
192
|
-
const
|
|
192
|
+
const inner = { type: command, data: jsonData };
|
|
193
|
+
const payload = { scope, data: inner };
|
|
193
194
|
channel.send(JSON.stringify(payload));
|
|
194
195
|
}
|
|
195
196
|
function parseMessage(data) {
|
|
@@ -571,6 +572,7 @@ var LocalCoordinatorClient = class extends CoordinatorClient {
|
|
|
571
572
|
};
|
|
572
573
|
|
|
573
574
|
// src/core/GPUMachineClient.ts
|
|
575
|
+
var PING_INTERVAL_MS = 5e3;
|
|
574
576
|
var GPUMachineClient = class {
|
|
575
577
|
constructor(config) {
|
|
576
578
|
this.eventListeners = /* @__PURE__ */ new Map();
|
|
@@ -653,6 +655,7 @@ var GPUMachineClient = class {
|
|
|
653
655
|
*/
|
|
654
656
|
disconnect() {
|
|
655
657
|
return __async(this, null, function* () {
|
|
658
|
+
this.stopPing();
|
|
656
659
|
if (this.publishedTrack) {
|
|
657
660
|
yield this.unpublishTrack();
|
|
658
661
|
}
|
|
@@ -693,13 +696,14 @@ var GPUMachineClient = class {
|
|
|
693
696
|
* Sends a command to the GPU machine via the data channel.
|
|
694
697
|
* @param command The command to send
|
|
695
698
|
* @param data The data to send with the command. These are the parameters for the command, matching the scheme in the capabilities dictionary.
|
|
699
|
+
* @param scope The message scope – "application" (default) for model commands, "runtime" for platform-level messages.
|
|
696
700
|
*/
|
|
697
|
-
sendCommand(command, data) {
|
|
701
|
+
sendCommand(command, data, scope = "application") {
|
|
698
702
|
if (!this.dataChannel) {
|
|
699
703
|
throw new Error("[GPUMachineClient] Data channel not available");
|
|
700
704
|
}
|
|
701
705
|
try {
|
|
702
|
-
sendMessage(this.dataChannel, command, data);
|
|
706
|
+
sendMessage(this.dataChannel, command, data, scope);
|
|
703
707
|
} catch (error) {
|
|
704
708
|
console.warn("[GPUMachineClient] Failed to send message:", error);
|
|
705
709
|
}
|
|
@@ -780,6 +784,34 @@ var GPUMachineClient = class {
|
|
|
780
784
|
return new MediaStream(tracks);
|
|
781
785
|
}
|
|
782
786
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
787
|
+
// Ping (Client Liveness)
|
|
788
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
789
|
+
/**
|
|
790
|
+
* Starts sending periodic "ping" messages on the runtime channel so the
|
|
791
|
+
* server can detect stale connections quickly.
|
|
792
|
+
*/
|
|
793
|
+
startPing() {
|
|
794
|
+
this.stopPing();
|
|
795
|
+
this.pingInterval = setInterval(() => {
|
|
796
|
+
var _a;
|
|
797
|
+
if (((_a = this.dataChannel) == null ? void 0 : _a.readyState) === "open") {
|
|
798
|
+
try {
|
|
799
|
+
sendMessage(this.dataChannel, "ping", {}, "runtime");
|
|
800
|
+
} catch (e) {
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}, PING_INTERVAL_MS);
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Stops the periodic ping.
|
|
807
|
+
*/
|
|
808
|
+
stopPing() {
|
|
809
|
+
if (this.pingInterval !== void 0) {
|
|
810
|
+
clearInterval(this.pingInterval);
|
|
811
|
+
this.pingInterval = void 0;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
783
815
|
// Private Helpers
|
|
784
816
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
785
817
|
setStatus(newStatus) {
|
|
@@ -833,18 +865,29 @@ var GPUMachineClient = class {
|
|
|
833
865
|
if (!this.dataChannel) return;
|
|
834
866
|
this.dataChannel.onopen = () => {
|
|
835
867
|
console.debug("[GPUMachineClient] Data channel open");
|
|
868
|
+
this.startPing();
|
|
836
869
|
};
|
|
837
870
|
this.dataChannel.onclose = () => {
|
|
838
871
|
console.debug("[GPUMachineClient] Data channel closed");
|
|
872
|
+
this.stopPing();
|
|
839
873
|
};
|
|
840
874
|
this.dataChannel.onerror = (error) => {
|
|
841
875
|
console.error("[GPUMachineClient] Data channel error:", error);
|
|
842
876
|
};
|
|
843
877
|
this.dataChannel.onmessage = (event) => {
|
|
844
|
-
const
|
|
845
|
-
console.debug("[GPUMachineClient] Received message:",
|
|
878
|
+
const rawData = parseMessage(event.data);
|
|
879
|
+
console.debug("[GPUMachineClient] Received message:", rawData);
|
|
846
880
|
try {
|
|
847
|
-
|
|
881
|
+
if ((rawData == null ? void 0 : rawData.scope) === "application" && (rawData == null ? void 0 : rawData.data) !== void 0) {
|
|
882
|
+
this.emit("message", rawData.data, "application");
|
|
883
|
+
} else if ((rawData == null ? void 0 : rawData.scope) === "runtime" && (rawData == null ? void 0 : rawData.data) !== void 0) {
|
|
884
|
+
this.emit("message", rawData.data, "runtime");
|
|
885
|
+
} else {
|
|
886
|
+
console.warn(
|
|
887
|
+
"[GPUMachineClient] Received message without envelope, treating as application"
|
|
888
|
+
);
|
|
889
|
+
this.emit("message", rawData, "application");
|
|
890
|
+
}
|
|
848
891
|
} catch (error) {
|
|
849
892
|
console.error(
|
|
850
893
|
"[GPUMachineClient] Failed to parse/validate message:",
|
|
@@ -894,11 +937,14 @@ var Reactor = class {
|
|
|
894
937
|
}
|
|
895
938
|
/**
|
|
896
939
|
* Public method to send a message to the machine.
|
|
897
|
-
*
|
|
898
|
-
* @param
|
|
940
|
+
* Wraps the message in the specified channel envelope (defaults to "application").
|
|
941
|
+
* @param command The command name to send.
|
|
942
|
+
* @param data The command payload.
|
|
943
|
+
* @param scope The envelope scope – "application" (default) for model commands,
|
|
944
|
+
* "runtime" for platform-level messages (e.g. requestCapabilities).
|
|
899
945
|
* @throws Error if not in ready state
|
|
900
946
|
*/
|
|
901
|
-
sendCommand(command, data) {
|
|
947
|
+
sendCommand(command, data, scope = "application") {
|
|
902
948
|
return __async(this, null, function* () {
|
|
903
949
|
var _a;
|
|
904
950
|
if (process.env.NODE_ENV !== "development" && this.status !== "ready") {
|
|
@@ -907,7 +953,7 @@ var Reactor = class {
|
|
|
907
953
|
return;
|
|
908
954
|
}
|
|
909
955
|
try {
|
|
910
|
-
(_a = this.machineClient) == null ? void 0 : _a.sendCommand(command, data);
|
|
956
|
+
(_a = this.machineClient) == null ? void 0 : _a.sendCommand(command, data, scope);
|
|
911
957
|
} catch (error) {
|
|
912
958
|
console.error("[Reactor] Failed to send message:", error);
|
|
913
959
|
this.createError(
|
|
@@ -1057,12 +1103,8 @@ var Reactor = class {
|
|
|
1057
1103
|
*/
|
|
1058
1104
|
setupMachineClientHandlers() {
|
|
1059
1105
|
if (!this.machineClient) return;
|
|
1060
|
-
this.machineClient.on("
|
|
1061
|
-
|
|
1062
|
-
this.emit("newMessage", message.data);
|
|
1063
|
-
} else {
|
|
1064
|
-
this.emit("newMessage", message);
|
|
1065
|
-
}
|
|
1106
|
+
this.machineClient.on("message", (message, scope) => {
|
|
1107
|
+
this.emit("newMessage", message, scope);
|
|
1066
1108
|
});
|
|
1067
1109
|
this.machineClient.on("statusChanged", (status) => {
|
|
1068
1110
|
switch (status) {
|
|
@@ -1269,10 +1311,14 @@ var createReactorStore = (initProps, publicState = defaultInitState) => {
|
|
|
1269
1311
|
get().internal.reactor.off("newMessage", handler);
|
|
1270
1312
|
};
|
|
1271
1313
|
},
|
|
1272
|
-
sendCommand: (command, data) => __async(null, null, function* () {
|
|
1273
|
-
console.debug("[ReactorStore] Sending command", {
|
|
1314
|
+
sendCommand: (command, data, scope) => __async(null, null, function* () {
|
|
1315
|
+
console.debug("[ReactorStore] Sending command", {
|
|
1316
|
+
command,
|
|
1317
|
+
data,
|
|
1318
|
+
scope
|
|
1319
|
+
});
|
|
1274
1320
|
try {
|
|
1275
|
-
yield get().internal.reactor.sendCommand(command, data);
|
|
1321
|
+
yield get().internal.reactor.sendCommand(command, data, scope);
|
|
1276
1322
|
console.debug("[ReactorStore] Command sent successfully");
|
|
1277
1323
|
} catch (error) {
|
|
1278
1324
|
console.error("[ReactorStore] Failed to send command:", error);
|
|
@@ -1475,9 +1521,12 @@ function useReactorMessage(handler) {
|
|
|
1475
1521
|
}, [handler]);
|
|
1476
1522
|
useEffect2(() => {
|
|
1477
1523
|
console.debug("[useReactorMessage] Setting up message subscription");
|
|
1478
|
-
const stableHandler = (message) => {
|
|
1479
|
-
console.debug("[useReactorMessage] Message received", {
|
|
1480
|
-
|
|
1524
|
+
const stableHandler = (message, scope) => {
|
|
1525
|
+
console.debug("[useReactorMessage] Message received", {
|
|
1526
|
+
message,
|
|
1527
|
+
scope
|
|
1528
|
+
});
|
|
1529
|
+
handlerRef.current(message, scope);
|
|
1481
1530
|
};
|
|
1482
1531
|
reactor.on("newMessage", stableHandler);
|
|
1483
1532
|
console.debug("[useReactorMessage] Message handler registered");
|
|
@@ -1606,7 +1655,7 @@ function ReactorController({
|
|
|
1606
1655
|
}, [status]);
|
|
1607
1656
|
const requestCapabilities = useCallback(() => {
|
|
1608
1657
|
if (status === "ready") {
|
|
1609
|
-
sendCommand("requestCapabilities", {});
|
|
1658
|
+
sendCommand("requestCapabilities", {}, "runtime");
|
|
1610
1659
|
}
|
|
1611
1660
|
}, [status, sendCommand]);
|
|
1612
1661
|
React.useEffect(() => {
|
|
@@ -1623,9 +1672,9 @@ function ReactorController({
|
|
|
1623
1672
|
}, 5e3);
|
|
1624
1673
|
return () => clearInterval(interval);
|
|
1625
1674
|
}, [status, commands, requestCapabilities]);
|
|
1626
|
-
useReactorMessage((message) => {
|
|
1627
|
-
if (message && typeof message === "object" && "commands" in message) {
|
|
1628
|
-
const commandsMessage = message;
|
|
1675
|
+
useReactorMessage((message, scope) => {
|
|
1676
|
+
if (scope === "runtime" && message && typeof message === "object" && message.type === "modelCapabilities" && message.data && "commands" in message.data) {
|
|
1677
|
+
const commandsMessage = message.data;
|
|
1629
1678
|
setCommands(commandsMessage.commands);
|
|
1630
1679
|
const initialValues = {};
|
|
1631
1680
|
const initialExpanded = {};
|