@reactor-team/js-sdk 1.0.17 → 1.0.19

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
@@ -15,6 +15,11 @@ declare const WaitingInfoDataSchema: z.ZodObject<{
15
15
  declare const SessionExpirationDataSchema: z.ZodObject<{
16
16
  expire: z.ZodNumber;
17
17
  }, z.core.$strip>;
18
+ declare const ReactorAuthSchema: z.ZodObject<{
19
+ insecureApiKey: z.ZodOptional<z.ZodString>;
20
+ jwtToken: z.ZodOptional<z.ZodString>;
21
+ }, z.core.$strip>;
22
+ type ReactorAuth = z.infer<typeof ReactorAuthSchema>;
18
23
 
19
24
  type ReactorStatus = "disconnected" | "connecting" | "waiting" | "ready";
20
25
  interface ReactorWaitingInfo extends z$1.infer<typeof WaitingInfoDataSchema> {
@@ -37,12 +42,6 @@ interface ReactorState$1 {
37
42
  type ReactorEvent = "statusChanged" | "waitingInfoChanged" | "newMessage" | "fps" | "streamChanged" | "error" | "sessionExpirationChanged";
38
43
 
39
44
  declare const OptionsSchema: z.ZodObject<{
40
- directConnection: z.ZodOptional<z.ZodObject<{
41
- livekitJwtToken: z.ZodString;
42
- livekitWsUrl: z.ZodString;
43
- }, z.core.$strip>>;
44
- insecureApiKey: z.ZodOptional<z.ZodString>;
45
- jwtToken: z.ZodOptional<z.ZodString>;
46
45
  coordinatorUrl: z.ZodDefault<z.ZodString>;
47
46
  modelName: z.ZodString;
48
47
  queueing: z.ZodDefault<z.ZodBoolean>;
@@ -57,13 +56,11 @@ declare class Reactor {
57
56
  private coordinatorUrl;
58
57
  private lastError?;
59
58
  private waitingInfo?;
60
- private jwtToken?;
61
- private insecureApiKey?;
62
- private directConnection?;
63
59
  private modelName;
64
60
  private modelVersion;
65
61
  private queueing;
66
62
  private sessionExpiration?;
63
+ private local;
67
64
  constructor(options: Options);
68
65
  private eventListeners;
69
66
  on(event: ReactorEvent, handler: EventHandler): void;
@@ -96,8 +93,9 @@ declare class Reactor {
96
93
  /**
97
94
  * Connects to the coordinator and waits for a GPU to be assigned.
98
95
  * Once a GPU is assigned, the Reactor will connect to the gpu machine via LiveKit.
96
+ * If no authentication is provided and not in local mode, an error is thrown.
99
97
  */
100
- connect(): Promise<void>;
98
+ connect(auth?: ReactorAuth): Promise<void>;
101
99
  /**
102
100
  * Disconnects from the coordinator and the gpu machine.
103
101
  * Ensures cleanup completes even if individual disconnections fail.
@@ -136,10 +134,12 @@ interface ReactorState {
136
134
  waitingInfo?: ReactorWaitingInfo;
137
135
  lastError?: ReactorError;
138
136
  sessionExpiration?: number;
137
+ insecureApiKey?: string;
138
+ jwtToken?: string;
139
139
  }
140
140
  interface ReactorActions {
141
141
  sendMessage(message: any): Promise<void>;
142
- connect(): Promise<void>;
142
+ connect(auth?: ReactorAuth): Promise<void>;
143
143
  disconnect(): Promise<void>;
144
144
  publishVideoStream(stream: MediaStream): Promise<void>;
145
145
  unpublishVideoStream(): Promise<void>;
@@ -151,13 +151,17 @@ type ReactorStore = ReactorState & ReactorActions & {
151
151
  internal: ReactorInternalState;
152
152
  };
153
153
  interface ReactorInitializationProps extends Options {
154
+ insecureApiKey?: string;
155
+ jwtToken?: string;
154
156
  }
155
157
 
156
158
  interface ReactorProviderProps extends ReactorInitializationProps {
157
159
  autoConnect?: boolean;
160
+ insecureApiKey?: string;
161
+ jwtToken?: string;
158
162
  children: ReactNode;
159
163
  }
160
- declare function ReactorProvider({ children, autoConnect, ...props }: ReactorProviderProps): react_jsx_runtime.JSX.Element;
164
+ declare function ReactorProvider({ children, autoConnect, insecureApiKey, jwtToken, ...props }: ReactorProviderProps): react_jsx_runtime.JSX.Element;
161
165
  declare function useReactorStore<T = ReactorStore>(selector: (state: ReactorStore) => T): T;
162
166
 
163
167
  interface ReactorViewProps {
package/dist/index.d.ts CHANGED
@@ -15,6 +15,11 @@ declare const WaitingInfoDataSchema: z.ZodObject<{
15
15
  declare const SessionExpirationDataSchema: z.ZodObject<{
16
16
  expire: z.ZodNumber;
17
17
  }, z.core.$strip>;
18
+ declare const ReactorAuthSchema: z.ZodObject<{
19
+ insecureApiKey: z.ZodOptional<z.ZodString>;
20
+ jwtToken: z.ZodOptional<z.ZodString>;
21
+ }, z.core.$strip>;
22
+ type ReactorAuth = z.infer<typeof ReactorAuthSchema>;
18
23
 
19
24
  type ReactorStatus = "disconnected" | "connecting" | "waiting" | "ready";
20
25
  interface ReactorWaitingInfo extends z$1.infer<typeof WaitingInfoDataSchema> {
@@ -37,12 +42,6 @@ interface ReactorState$1 {
37
42
  type ReactorEvent = "statusChanged" | "waitingInfoChanged" | "newMessage" | "fps" | "streamChanged" | "error" | "sessionExpirationChanged";
38
43
 
39
44
  declare const OptionsSchema: z.ZodObject<{
40
- directConnection: z.ZodOptional<z.ZodObject<{
41
- livekitJwtToken: z.ZodString;
42
- livekitWsUrl: z.ZodString;
43
- }, z.core.$strip>>;
44
- insecureApiKey: z.ZodOptional<z.ZodString>;
45
- jwtToken: z.ZodOptional<z.ZodString>;
46
45
  coordinatorUrl: z.ZodDefault<z.ZodString>;
47
46
  modelName: z.ZodString;
48
47
  queueing: z.ZodDefault<z.ZodBoolean>;
@@ -57,13 +56,11 @@ declare class Reactor {
57
56
  private coordinatorUrl;
58
57
  private lastError?;
59
58
  private waitingInfo?;
60
- private jwtToken?;
61
- private insecureApiKey?;
62
- private directConnection?;
63
59
  private modelName;
64
60
  private modelVersion;
65
61
  private queueing;
66
62
  private sessionExpiration?;
63
+ private local;
67
64
  constructor(options: Options);
68
65
  private eventListeners;
69
66
  on(event: ReactorEvent, handler: EventHandler): void;
@@ -96,8 +93,9 @@ declare class Reactor {
96
93
  /**
97
94
  * Connects to the coordinator and waits for a GPU to be assigned.
98
95
  * Once a GPU is assigned, the Reactor will connect to the gpu machine via LiveKit.
96
+ * If no authentication is provided and not in local mode, an error is thrown.
99
97
  */
100
- connect(): Promise<void>;
98
+ connect(auth?: ReactorAuth): Promise<void>;
101
99
  /**
102
100
  * Disconnects from the coordinator and the gpu machine.
103
101
  * Ensures cleanup completes even if individual disconnections fail.
@@ -136,10 +134,12 @@ interface ReactorState {
136
134
  waitingInfo?: ReactorWaitingInfo;
137
135
  lastError?: ReactorError;
138
136
  sessionExpiration?: number;
137
+ insecureApiKey?: string;
138
+ jwtToken?: string;
139
139
  }
140
140
  interface ReactorActions {
141
141
  sendMessage(message: any): Promise<void>;
142
- connect(): Promise<void>;
142
+ connect(auth?: ReactorAuth): Promise<void>;
143
143
  disconnect(): Promise<void>;
144
144
  publishVideoStream(stream: MediaStream): Promise<void>;
145
145
  unpublishVideoStream(): Promise<void>;
@@ -151,13 +151,17 @@ type ReactorStore = ReactorState & ReactorActions & {
151
151
  internal: ReactorInternalState;
152
152
  };
153
153
  interface ReactorInitializationProps extends Options {
154
+ insecureApiKey?: string;
155
+ jwtToken?: string;
154
156
  }
155
157
 
156
158
  interface ReactorProviderProps extends ReactorInitializationProps {
157
159
  autoConnect?: boolean;
160
+ insecureApiKey?: string;
161
+ jwtToken?: string;
158
162
  children: ReactNode;
159
163
  }
160
- declare function ReactorProvider({ children, autoConnect, ...props }: ReactorProviderProps): react_jsx_runtime.JSX.Element;
164
+ declare function ReactorProvider({ children, autoConnect, insecureApiKey, jwtToken, ...props }: ReactorProviderProps): react_jsx_runtime.JSX.Element;
161
165
  declare function useReactorStore<T = ReactorStore>(selector: (state: ReactorStore) => T): T;
162
166
 
163
167
  interface ReactorViewProps {
package/dist/index.js CHANGED
@@ -154,6 +154,12 @@ var SessionSetupMessageSchema = import_zod.z.object({
154
154
  modelVersion: import_zod.z.string().default("latest")
155
155
  })
156
156
  });
157
+ var ReactorAuthSchema = import_zod.z.object({
158
+ insecureApiKey: import_zod.z.string().optional(),
159
+ jwtToken: import_zod.z.string().optional()
160
+ }).refine((data) => data.insecureApiKey || data.jwtToken, {
161
+ message: "Either insecureApiKey or jwtToken must be provided"
162
+ });
157
163
 
158
164
  // src/core/CoordinatorClient.ts
159
165
  var import_zod2 = require("zod");
@@ -571,22 +577,11 @@ var LOCAL_COORDINATOR_URL = "ws://localhost:8080/ws";
571
577
  var LOCAL_INSECURE_API_KEY = "1234";
572
578
  var PROD_COORDINATOR_URL = "wss://api.reactor.inc/ws";
573
579
  var OptionsSchema2 = import_zod3.z.object({
574
- directConnection: import_zod3.z.object({
575
- livekitJwtToken: import_zod3.z.string(),
576
- livekitWsUrl: import_zod3.z.string()
577
- }).optional(),
578
- insecureApiKey: import_zod3.z.string().optional(),
579
- jwtToken: import_zod3.z.string().optional(),
580
580
  coordinatorUrl: import_zod3.z.string().default(PROD_COORDINATOR_URL),
581
581
  modelName: import_zod3.z.string(),
582
582
  queueing: import_zod3.z.boolean().default(false),
583
583
  local: import_zod3.z.boolean().default(false)
584
- }).refine(
585
- (data) => data.directConnection || data.insecureApiKey || data.jwtToken || data.local,
586
- {
587
- message: "At least one of directConnection, insecureApiKey, or jwtToken or local must be provided."
588
- }
589
- );
584
+ });
590
585
  var Reactor = class {
591
586
  constructor(options) {
592
587
  //client for the machine instance
@@ -595,15 +590,12 @@ var Reactor = class {
595
590
  this.eventListeners = /* @__PURE__ */ new Map();
596
591
  const validatedOptions = OptionsSchema2.parse(options);
597
592
  this.coordinatorUrl = validatedOptions.coordinatorUrl;
598
- this.jwtToken = validatedOptions.jwtToken;
599
- this.insecureApiKey = validatedOptions.insecureApiKey;
600
- this.directConnection = validatedOptions.directConnection;
601
593
  this.modelName = validatedOptions.modelName;
602
594
  this.queueing = validatedOptions.queueing;
603
595
  this.modelVersion = "1.0.0";
604
- if (validatedOptions.local) {
596
+ this.local = validatedOptions.local;
597
+ if (this.local) {
605
598
  this.coordinatorUrl = LOCAL_COORDINATOR_URL;
606
- this.insecureApiKey = LOCAL_INSECURE_API_KEY;
607
599
  }
608
600
  }
609
601
  // Event Emitter API
@@ -749,18 +741,21 @@ var Reactor = class {
749
741
  /**
750
742
  * Connects to the coordinator and waits for a GPU to be assigned.
751
743
  * Once a GPU is assigned, the Reactor will connect to the gpu machine via LiveKit.
744
+ * If no authentication is provided and not in local mode, an error is thrown.
752
745
  */
753
- connect() {
746
+ connect(auth) {
754
747
  return __async(this, null, function* () {
755
748
  console.debug("[Reactor] Connecting, status:", this.status);
749
+ if (auth == void 0) {
750
+ if (!this.local) {
751
+ throw new Error("No authentication provided and not in local mode");
752
+ }
753
+ auth = {
754
+ insecureApiKey: LOCAL_INSECURE_API_KEY
755
+ };
756
+ }
756
757
  if (this.status !== "disconnected")
757
758
  throw new Error("Already connected or connecting");
758
- if (this.directConnection) {
759
- return this.connectToGPUMachine(
760
- this.directConnection.livekitJwtToken,
761
- this.directConnection.livekitWsUrl
762
- );
763
- }
764
759
  this.setStatus("connecting");
765
760
  try {
766
761
  console.debug(
@@ -768,8 +763,8 @@ var Reactor = class {
768
763
  );
769
764
  this.coordinatorClient = new CoordinatorClient({
770
765
  wsUrl: this.coordinatorUrl,
771
- jwtToken: this.jwtToken,
772
- insecureApiKey: this.insecureApiKey,
766
+ jwtToken: auth.jwtToken,
767
+ insecureApiKey: auth.insecureApiKey,
773
768
  modelName: this.modelName,
774
769
  modelVersion: this.modelVersion,
775
770
  queueing: this.queueing
@@ -969,7 +964,9 @@ var defaultInitState = {
969
964
  fps: void 0,
970
965
  waitingInfo: void 0,
971
966
  lastError: void 0,
972
- sessionExpiration: void 0
967
+ sessionExpiration: void 0,
968
+ insecureApiKey: void 0,
969
+ jwtToken: void 0
973
970
  };
974
971
  var initReactorStore = (props) => {
975
972
  return __spreadValues(__spreadValues({}, defaultInitState), props);
@@ -977,6 +974,8 @@ var initReactorStore = (props) => {
977
974
  var createReactorStore = (initProps, publicState = defaultInitState) => {
978
975
  console.debug("[ReactorStore] Creating store", {
979
976
  coordinatorUrl: initProps.coordinatorUrl,
977
+ insecureApiKey: initProps.insecureApiKey,
978
+ jwtToken: initProps.jwtToken,
980
979
  initialState: publicState
981
980
  });
982
981
  return (0, import_react.create)()((set, get) => {
@@ -989,20 +988,26 @@ var createReactorStore = (initProps, publicState = defaultInitState) => {
989
988
  });
990
989
  set({ status: newStatus });
991
990
  });
992
- reactor.on("waitingInfoChanged", (newWaitingInfo) => {
993
- console.debug("[ReactorStore] Waiting info changed", {
994
- oldWaitingInfo: get().waitingInfo,
995
- newWaitingInfo
996
- });
997
- set({ waitingInfo: newWaitingInfo });
998
- });
999
- reactor.on("sessionExpirationChanged", (newSessionExpiration) => {
1000
- console.debug("[ReactorStore] Session expiration changed", {
1001
- oldSessionExpiration: get().sessionExpiration,
1002
- newSessionExpiration
1003
- });
1004
- set({ sessionExpiration: newSessionExpiration });
1005
- });
991
+ reactor.on(
992
+ "waitingInfoChanged",
993
+ (newWaitingInfo) => {
994
+ console.debug("[ReactorStore] Waiting info changed", {
995
+ oldWaitingInfo: get().waitingInfo,
996
+ newWaitingInfo
997
+ });
998
+ set({ waitingInfo: newWaitingInfo });
999
+ }
1000
+ );
1001
+ reactor.on(
1002
+ "sessionExpirationChanged",
1003
+ (newSessionExpiration) => {
1004
+ console.debug("[ReactorStore] Session expiration changed", {
1005
+ oldSessionExpiration: get().sessionExpiration,
1006
+ newSessionExpiration
1007
+ });
1008
+ set({ sessionExpiration: newSessionExpiration });
1009
+ }
1010
+ );
1006
1011
  reactor.on("streamChanged", (videoTrack) => {
1007
1012
  console.debug("[ReactorStore] Stream changed", {
1008
1013
  hasVideoTrack: !!videoTrack,
@@ -1020,6 +1025,9 @@ var createReactorStore = (initProps, publicState = defaultInitState) => {
1020
1025
  set({ lastError: error });
1021
1026
  });
1022
1027
  return __spreadProps(__spreadValues({}, publicState), {
1028
+ // Include auth credentials from initProps in the store state
1029
+ insecureApiKey: initProps.insecureApiKey,
1030
+ jwtToken: initProps.jwtToken,
1023
1031
  internal: { reactor },
1024
1032
  // actions
1025
1033
  onMessage: (handler) => {
@@ -1040,10 +1048,17 @@ var createReactorStore = (initProps, publicState = defaultInitState) => {
1040
1048
  throw error;
1041
1049
  }
1042
1050
  }),
1043
- connect: () => __async(null, null, function* () {
1044
- console.debug("[ReactorStore] Connect called");
1051
+ connect: (auth) => __async(null, null, function* () {
1052
+ console.debug("auth", auth);
1053
+ if (auth === void 0) {
1054
+ auth = {
1055
+ insecureApiKey: get().insecureApiKey,
1056
+ jwtToken: get().jwtToken
1057
+ };
1058
+ }
1059
+ console.debug("[ReactorStore] Connect called", { auth });
1045
1060
  try {
1046
- yield get().internal.reactor.connect();
1061
+ yield get().internal.reactor.connect(auth);
1047
1062
  console.debug("[ReactorStore] Connect completed successfully");
1048
1063
  } catch (error) {
1049
1064
  console.error("[ReactorStore] Connect failed:", error);
@@ -1098,37 +1113,41 @@ var import_jsx_runtime = require("react/jsx-runtime");
1098
1113
  function ReactorProvider(_a) {
1099
1114
  var _b = _a, {
1100
1115
  children,
1101
- autoConnect = true
1116
+ autoConnect = true,
1117
+ insecureApiKey,
1118
+ jwtToken
1102
1119
  } = _b, props = __objRest(_b, [
1103
1120
  "children",
1104
- "autoConnect"
1121
+ "autoConnect",
1122
+ "insecureApiKey",
1123
+ "jwtToken"
1105
1124
  ]);
1106
1125
  const storeRef = (0, import_react3.useRef)(void 0);
1107
1126
  const firstRender = (0, import_react3.useRef)(true);
1108
1127
  const [_storeVersion, setStoreVersion] = (0, import_react3.useState)(0);
1109
1128
  if (storeRef.current === void 0) {
1110
1129
  console.debug("[ReactorProvider] Creating new reactor store");
1111
- storeRef.current = createReactorStore(initReactorStore(props));
1130
+ storeRef.current = createReactorStore(
1131
+ initReactorStore(__spreadProps(__spreadValues({}, props), {
1132
+ insecureApiKey,
1133
+ jwtToken
1134
+ }))
1135
+ );
1112
1136
  console.debug("[ReactorProvider] Reactor store created successfully");
1113
1137
  }
1114
- const {
1115
- coordinatorUrl,
1116
- modelName,
1117
- jwtToken,
1118
- insecureApiKey,
1119
- directConnection,
1120
- queueing,
1121
- local
1122
- } = props;
1138
+ const { coordinatorUrl, modelName, queueing, local } = props;
1123
1139
  (0, import_react3.useEffect)(() => {
1124
1140
  if (firstRender.current) {
1125
1141
  firstRender.current = false;
1126
1142
  const current2 = storeRef.current;
1127
- if (autoConnect && current2.getState().status === "disconnected") {
1143
+ if (autoConnect && current2.getState().status === "disconnected" && (insecureApiKey || jwtToken)) {
1128
1144
  console.debug(
1129
1145
  "[ReactorProvider] Starting autoconnect in first render..."
1130
1146
  );
1131
- current2.getState().connect().then(() => {
1147
+ current2.getState().connect({
1148
+ insecureApiKey,
1149
+ jwtToken
1150
+ }).then(() => {
1132
1151
  console.debug(
1133
1152
  "[ReactorProvider] Autoconnect successful in first render"
1134
1153
  );
@@ -1160,11 +1179,10 @@ function ReactorProvider(_a) {
1160
1179
  initReactorStore({
1161
1180
  coordinatorUrl,
1162
1181
  modelName,
1163
- jwtToken,
1164
- insecureApiKey,
1165
- directConnection,
1166
1182
  queueing,
1167
- local
1183
+ local,
1184
+ insecureApiKey,
1185
+ jwtToken
1168
1186
  })
1169
1187
  );
1170
1188
  const current = storeRef.current;
@@ -1172,9 +1190,12 @@ function ReactorProvider(_a) {
1172
1190
  console.debug(
1173
1191
  "[ReactorProvider] Reactor store updated successfully, and increased version"
1174
1192
  );
1175
- if (autoConnect && current.getState().status === "disconnected") {
1193
+ if (autoConnect && current.getState().status === "disconnected" && (insecureApiKey || jwtToken)) {
1176
1194
  console.debug("[ReactorProvider] Starting autoconnect...");
1177
- current.getState().connect().then(() => {
1195
+ current.getState().connect({
1196
+ insecureApiKey,
1197
+ jwtToken
1198
+ }).then(() => {
1178
1199
  console.debug("[ReactorProvider] Autoconnect successful");
1179
1200
  }).catch((error) => {
1180
1201
  console.error("[ReactorProvider] Failed to autoconnect:", error);
@@ -1193,12 +1214,11 @@ function ReactorProvider(_a) {
1193
1214
  }, [
1194
1215
  coordinatorUrl,
1195
1216
  modelName,
1196
- jwtToken,
1197
- insecureApiKey,
1198
- directConnection,
1199
1217
  queueing,
1200
1218
  autoConnect,
1201
- local
1219
+ local,
1220
+ insecureApiKey,
1221
+ jwtToken
1202
1222
  ]);
1203
1223
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReactorContext.Provider, { value: storeRef.current, children });
1204
1224
  }
@@ -1353,7 +1373,7 @@ function ReactorController({
1353
1373
  setExpandedCommands({});
1354
1374
  }
1355
1375
  }, [status]);
1356
- import_react6.default.useEffect(() => {
1376
+ const requestCapabilities = (0, import_react6.useCallback)(() => {
1357
1377
  if (status === "ready") {
1358
1378
  sendMessage({
1359
1379
  type: "requestCapabilities",
@@ -1361,6 +1381,20 @@ function ReactorController({
1361
1381
  });
1362
1382
  }
1363
1383
  }, [status, sendMessage]);
1384
+ import_react6.default.useEffect(() => {
1385
+ if (status === "ready") {
1386
+ requestCapabilities();
1387
+ }
1388
+ }, [status, requestCapabilities]);
1389
+ import_react6.default.useEffect(() => {
1390
+ if (status !== "ready" || Object.keys(commands).length > 0) {
1391
+ return;
1392
+ }
1393
+ const interval = setInterval(() => {
1394
+ requestCapabilities();
1395
+ }, 5e3);
1396
+ return () => clearInterval(interval);
1397
+ }, [status, commands, requestCapabilities]);
1364
1398
  useReactorMessage((message) => {
1365
1399
  if (message && typeof message === "object" && "commands" in message) {
1366
1400
  const commandsMessage = message;