@reactor-team/js-sdk 2.4.0 → 2.5.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 CHANGED
@@ -9,6 +9,81 @@ type ReactorStatus = "disconnected" | "connecting" | "waiting" | "ready";
9
9
  * - "runtime": platform-level control messages (e.g., capabilities exchange).
10
10
  */
11
11
  type MessageScope = "application" | "runtime";
12
+ /**
13
+ * Describes a single named media track for SDP negotiation.
14
+ *
15
+ * Track names must exactly match the class attribute names defined on the
16
+ * model's Python code. The name is encoded as the SDP MID so both sides
17
+ * can route media by name rather than by positional index.
18
+ *
19
+ * Use the {@link video} and {@link audio} helper functions to create
20
+ * instances instead of constructing this interface directly.
21
+ */
22
+ interface TrackConfig {
23
+ name: string;
24
+ kind: "audio" | "video";
25
+ }
26
+ /**
27
+ * Optional configuration for a video track (reserved for future use).
28
+ */
29
+ interface VideoTrackOptions {
30
+ /** Maximum framerate constraint for the video track. */
31
+ maxFramerate?: number;
32
+ }
33
+ /**
34
+ * Optional configuration for an audio track (reserved for future use).
35
+ */
36
+ interface AudioTrackOptions {
37
+ /** Sample rate constraint for the audio track. */
38
+ sampleRate?: number;
39
+ }
40
+ /**
41
+ * Creates a **video** {@link TrackConfig}.
42
+ *
43
+ * A track declared in the **`receive`** array means the client will
44
+ * **RECEIVE** video frames **from the model** (model → client).
45
+ *
46
+ * A track declared in the **`send`** array means the client will
47
+ * **SEND** video frames **to the model** (client → model).
48
+ *
49
+ * Track names must be unique across both arrays — the same name cannot
50
+ * appear in `receive` and `send`.
51
+ *
52
+ * @param name - The track name. Must match the model's declared track attribute name.
53
+ * @param options - Reserved for future constraints (e.g. `maxFramerate`).
54
+ *
55
+ * When no `receive` array is provided to the Reactor constructor, a single
56
+ * `video("main_video")` track is used by default.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * receive: [video("main_video")] // receive video from the model
61
+ * send: [video("webcam")] // send webcam video to the model
62
+ * ```
63
+ */
64
+ declare function video(name: string, _options?: VideoTrackOptions): TrackConfig;
65
+ /**
66
+ * Creates an **audio** {@link TrackConfig}.
67
+ *
68
+ * A track declared in the **`receive`** array means the client will
69
+ * **RECEIVE** audio samples **from the model** (model → client).
70
+ *
71
+ * A track declared in the **`send`** array means the client will
72
+ * **SEND** audio samples **to the model** (client → model).
73
+ *
74
+ * Track names must be unique across both arrays — the same name cannot
75
+ * appear in `receive` and `send`.
76
+ *
77
+ * @param name - The track name. Must match the model's declared track attribute name.
78
+ * @param options - Reserved for future constraints (e.g. `sampleRate`).
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * receive: [audio("main_audio")] // receive audio from the model
83
+ * send: [audio("mic")] // send microphone audio to the model
84
+ * ```
85
+ */
86
+ declare function audio(name: string, _options?: AudioTrackOptions): TrackConfig;
12
87
  interface ReactorError {
13
88
  code: string;
14
89
  message: string;
@@ -20,6 +95,11 @@ interface ReactorError {
20
95
  declare class ConflictError extends Error {
21
96
  constructor(message: string);
22
97
  }
98
+ declare class AbortError extends Error {
99
+ constructor(message: string);
100
+ }
101
+ /** Matches both our custom AbortError and the native DOMException thrown by fetch(). */
102
+ declare function isAbortError(error: unknown): boolean;
23
103
  interface ReactorState$1 {
24
104
  status: ReactorStatus;
25
105
  lastError?: ReactorError;
@@ -46,13 +126,27 @@ interface ConnectionStats {
46
126
  jitter?: number;
47
127
  timestamp: number;
48
128
  }
49
- type ReactorEvent = "statusChanged" | "sessionIdChanged" | "message" | "runtimeMessage" | "streamChanged" | "error" | "sessionExpirationChanged" | "statsUpdate";
129
+ type ReactorEvent = "statusChanged" | "sessionIdChanged" | "message" | "runtimeMessage" | "trackReceived" | "error" | "sessionExpirationChanged" | "statsUpdate";
50
130
 
51
131
  declare const PROD_COORDINATOR_URL = "https://api.reactor.inc";
52
132
  declare const OptionsSchema: z.ZodObject<{
53
133
  coordinatorUrl: z.ZodDefault<z.ZodString>;
54
134
  modelName: z.ZodString;
55
135
  local: z.ZodDefault<z.ZodBoolean>;
136
+ receive: z.ZodDefault<z.ZodArray<z.ZodObject<{
137
+ name: z.ZodString;
138
+ kind: z.ZodEnum<{
139
+ audio: "audio";
140
+ video: "video";
141
+ }>;
142
+ }, z.core.$strip>>>;
143
+ send: z.ZodDefault<z.ZodArray<z.ZodObject<{
144
+ name: z.ZodString;
145
+ kind: z.ZodEnum<{
146
+ audio: "audio";
147
+ video: "video";
148
+ }>;
149
+ }, z.core.$strip>>>;
56
150
  }, z.core.$strip>;
57
151
  type Options = z.input<typeof OptionsSchema>;
58
152
  type EventHandler = (...args: any[]) => void;
@@ -65,6 +159,10 @@ declare class Reactor {
65
159
  private model;
66
160
  private sessionExpiration?;
67
161
  private local;
162
+ /** Tracks the client RECEIVES from the model (model → client). */
163
+ private receive;
164
+ /** Tracks the client SENDS to the model (client → model). */
165
+ private send;
68
166
  private sessionId?;
69
167
  constructor(options: Options);
70
168
  private eventListeners;
@@ -72,24 +170,26 @@ declare class Reactor {
72
170
  off(event: ReactorEvent, handler: EventHandler): void;
73
171
  emit(event: ReactorEvent, ...args: any[]): void;
74
172
  /**
75
- * Public method to send a message to the machine.
76
- * Wraps the message in the specified channel envelope (defaults to "application").
77
- * @param command The command name to send.
173
+ * Sends a command to the model via the data channel.
174
+ *
175
+ * @param command The command name.
78
176
  * @param data The command payload.
79
- * @param scope The envelope scope – "application" (default) for model commands,
80
- * "runtime" for platform-level messages (e.g. requestCapabilities).
81
- * @throws Error if not in ready state
177
+ * @param scope "application" (default) for model commands, "runtime" for platform messages.
82
178
  */
83
179
  sendCommand(command: string, data: any, scope?: MessageScope): Promise<void>;
84
180
  /**
85
- * Public method to publish a track to the machine.
86
- * @param track The track to send to the machine.
181
+ * Publishes a MediaStreamTrack to a named send track.
182
+ *
183
+ * @param name The declared send track name (e.g. "webcam").
184
+ * @param track The MediaStreamTrack to publish.
87
185
  */
88
- publishTrack(track: MediaStreamTrack): Promise<void>;
186
+ publishTrack(name: string, track: MediaStreamTrack): Promise<void>;
89
187
  /**
90
- * Public method to unpublish the currently published track.
188
+ * Unpublishes the track with the given name.
189
+ *
190
+ * @param name The declared send track name to unpublish.
91
191
  */
92
- unpublishTrack(): Promise<void>;
192
+ unpublishTrack(name: string): Promise<void>;
93
193
  /**
94
194
  * Public method for reconnecting to an existing session, that may have been interrupted but can be recovered.
95
195
  * @param options Optional connect options (e.g. maxAttempts for SDP polling)
@@ -105,6 +205,11 @@ declare class Reactor {
105
205
  connect(jwtToken?: string, options?: ConnectOptions): Promise<void>;
106
206
  /**
107
207
  * Sets up event handlers for the machine client.
208
+ *
209
+ * Each handler captures the client reference at registration time and
210
+ * ignores events if this.machineClient has since changed (e.g. after
211
+ * disconnect + reconnect), preventing stale WebRTC teardown events from
212
+ * interfering with a new connection.
108
213
  */
109
214
  private setupMachineClientHandlers;
110
215
  /**
@@ -138,19 +243,24 @@ declare class Reactor {
138
243
 
139
244
  interface ReactorState {
140
245
  status: ReactorStatus;
141
- videoTrack: MediaStreamTrack | null;
246
+ /**
247
+ * Media tracks received from the model, keyed by track name.
248
+ *
249
+ * Each entry maps a declared **receive** track name (e.g. `"main_video"`,
250
+ * `"main_audio"`) to the live `MediaStreamTrack` delivered by the model.
251
+ */
252
+ tracks: Record<string, MediaStreamTrack>;
142
253
  lastError?: ReactorError;
143
254
  sessionId?: string;
144
255
  sessionExpiration?: number;
145
- insecureApiKey?: string;
146
256
  jwtToken?: string;
147
257
  }
148
258
  interface ReactorActions {
149
259
  sendCommand(command: string, data: any, scope?: MessageScope): Promise<void>;
150
260
  connect(jwtToken?: string, options?: ConnectOptions): Promise<void>;
151
261
  disconnect(recoverable?: boolean): Promise<void>;
152
- publishVideoStream(stream: MediaStream): Promise<void>;
153
- unpublishVideoStream(): Promise<void>;
262
+ publish(name: string, track: MediaStreamTrack): Promise<void>;
263
+ unpublish(name: string): Promise<void>;
154
264
  reconnect(options?: ConnectOptions): Promise<void>;
155
265
  }
156
266
  interface ReactorInternalState {
@@ -180,13 +290,26 @@ declare function ReactorProvider({ children, connectOptions, jwtToken, ...props
180
290
  declare function useReactorStore<T = ReactorStore>(selector: (state: ReactorStore) => T): T;
181
291
 
182
292
  interface ReactorViewProps {
293
+ /**
294
+ * The name of the **receive** track to render.
295
+ * Must match a track name declared in the `receive` array (model → client).
296
+ * Defaults to `"main_video"`.
297
+ */
298
+ track?: string;
299
+ /**
300
+ * Optional name of a **receive** audio track to play alongside the video
301
+ * (e.g. `"main_audio"`). The audio is mixed into the same `<video>` element.
302
+ */
303
+ audioTrack?: string;
183
304
  width?: number;
184
305
  height?: number;
185
306
  className?: string;
186
307
  style?: React.CSSProperties;
187
308
  videoObjectFit?: NonNullable<React.VideoHTMLAttributes<HTMLVideoElement>["style"]>["objectFit"];
309
+ /** Controls whether inbound audio plays. Default true (muted) to satisfy browser autoplay policies. */
310
+ muted?: boolean;
188
311
  }
189
- declare function ReactorView({ width, height, className, style, videoObjectFit, }: ReactorViewProps): react_jsx_runtime.JSX.Element;
312
+ declare function ReactorView({ track, audioTrack, width, height, className, style, videoObjectFit, muted, }: ReactorViewProps): react_jsx_runtime.JSX.Element;
190
313
 
191
314
  interface ReactorControllerProps {
192
315
  className?: string;
@@ -194,14 +317,19 @@ interface ReactorControllerProps {
194
317
  }
195
318
  declare function ReactorController({ className, style, }: ReactorControllerProps): react_jsx_runtime.JSX.Element;
196
319
 
197
- interface Props {
320
+ interface WebcamStreamProps {
321
+ /**
322
+ * The name of the **send** track to publish the webcam to.
323
+ * Must match a track name declared in the `send` array (client → model).
324
+ */
325
+ track: string;
198
326
  className?: string;
199
327
  style?: React.CSSProperties;
200
328
  videoConstraints?: MediaTrackConstraints;
201
329
  showWebcam?: boolean;
202
330
  videoObjectFit?: NonNullable<React.VideoHTMLAttributes<HTMLVideoElement>["style"]>["objectFit"];
203
331
  }
204
- declare function WebcamStream({ className, style, videoConstraints, showWebcam, videoObjectFit, }: Props): react_jsx_runtime.JSX.Element;
332
+ declare function WebcamStream({ track, className, style, videoConstraints, showWebcam, videoObjectFit, }: WebcamStreamProps): react_jsx_runtime.JSX.Element;
205
333
 
206
334
  /**
207
335
  * Generic hook for accessing selected parts of the Reactor store.
@@ -249,4 +377,4 @@ declare function useStats(): ConnectionStats | undefined;
249
377
  */
250
378
  declare function fetchInsecureJwtToken(apiKey: string, coordinatorUrl?: string): Promise<string>;
251
379
 
252
- export { ConflictError, type ConnectOptions, type ConnectionStats, type MessageScope, type Options, PROD_COORDINATOR_URL, Reactor, type ReactorConnectOptions, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, WebcamStream, fetchInsecureJwtToken, useReactor, useReactorInternalMessage, useReactorMessage, useReactorStore, useStats };
380
+ export { AbortError, type AudioTrackOptions, ConflictError, type ConnectOptions, type ConnectionStats, type MessageScope, type Options, PROD_COORDINATOR_URL, Reactor, type ReactorConnectOptions, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type TrackConfig, type VideoTrackOptions, WebcamStream, type WebcamStreamProps, audio, fetchInsecureJwtToken, isAbortError, useReactor, useReactorInternalMessage, useReactorMessage, useReactorStore, useStats, video };
package/dist/index.d.ts CHANGED
@@ -9,6 +9,81 @@ type ReactorStatus = "disconnected" | "connecting" | "waiting" | "ready";
9
9
  * - "runtime": platform-level control messages (e.g., capabilities exchange).
10
10
  */
11
11
  type MessageScope = "application" | "runtime";
12
+ /**
13
+ * Describes a single named media track for SDP negotiation.
14
+ *
15
+ * Track names must exactly match the class attribute names defined on the
16
+ * model's Python code. The name is encoded as the SDP MID so both sides
17
+ * can route media by name rather than by positional index.
18
+ *
19
+ * Use the {@link video} and {@link audio} helper functions to create
20
+ * instances instead of constructing this interface directly.
21
+ */
22
+ interface TrackConfig {
23
+ name: string;
24
+ kind: "audio" | "video";
25
+ }
26
+ /**
27
+ * Optional configuration for a video track (reserved for future use).
28
+ */
29
+ interface VideoTrackOptions {
30
+ /** Maximum framerate constraint for the video track. */
31
+ maxFramerate?: number;
32
+ }
33
+ /**
34
+ * Optional configuration for an audio track (reserved for future use).
35
+ */
36
+ interface AudioTrackOptions {
37
+ /** Sample rate constraint for the audio track. */
38
+ sampleRate?: number;
39
+ }
40
+ /**
41
+ * Creates a **video** {@link TrackConfig}.
42
+ *
43
+ * A track declared in the **`receive`** array means the client will
44
+ * **RECEIVE** video frames **from the model** (model → client).
45
+ *
46
+ * A track declared in the **`send`** array means the client will
47
+ * **SEND** video frames **to the model** (client → model).
48
+ *
49
+ * Track names must be unique across both arrays — the same name cannot
50
+ * appear in `receive` and `send`.
51
+ *
52
+ * @param name - The track name. Must match the model's declared track attribute name.
53
+ * @param options - Reserved for future constraints (e.g. `maxFramerate`).
54
+ *
55
+ * When no `receive` array is provided to the Reactor constructor, a single
56
+ * `video("main_video")` track is used by default.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * receive: [video("main_video")] // receive video from the model
61
+ * send: [video("webcam")] // send webcam video to the model
62
+ * ```
63
+ */
64
+ declare function video(name: string, _options?: VideoTrackOptions): TrackConfig;
65
+ /**
66
+ * Creates an **audio** {@link TrackConfig}.
67
+ *
68
+ * A track declared in the **`receive`** array means the client will
69
+ * **RECEIVE** audio samples **from the model** (model → client).
70
+ *
71
+ * A track declared in the **`send`** array means the client will
72
+ * **SEND** audio samples **to the model** (client → model).
73
+ *
74
+ * Track names must be unique across both arrays — the same name cannot
75
+ * appear in `receive` and `send`.
76
+ *
77
+ * @param name - The track name. Must match the model's declared track attribute name.
78
+ * @param options - Reserved for future constraints (e.g. `sampleRate`).
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * receive: [audio("main_audio")] // receive audio from the model
83
+ * send: [audio("mic")] // send microphone audio to the model
84
+ * ```
85
+ */
86
+ declare function audio(name: string, _options?: AudioTrackOptions): TrackConfig;
12
87
  interface ReactorError {
13
88
  code: string;
14
89
  message: string;
@@ -20,6 +95,11 @@ interface ReactorError {
20
95
  declare class ConflictError extends Error {
21
96
  constructor(message: string);
22
97
  }
98
+ declare class AbortError extends Error {
99
+ constructor(message: string);
100
+ }
101
+ /** Matches both our custom AbortError and the native DOMException thrown by fetch(). */
102
+ declare function isAbortError(error: unknown): boolean;
23
103
  interface ReactorState$1 {
24
104
  status: ReactorStatus;
25
105
  lastError?: ReactorError;
@@ -46,13 +126,27 @@ interface ConnectionStats {
46
126
  jitter?: number;
47
127
  timestamp: number;
48
128
  }
49
- type ReactorEvent = "statusChanged" | "sessionIdChanged" | "message" | "runtimeMessage" | "streamChanged" | "error" | "sessionExpirationChanged" | "statsUpdate";
129
+ type ReactorEvent = "statusChanged" | "sessionIdChanged" | "message" | "runtimeMessage" | "trackReceived" | "error" | "sessionExpirationChanged" | "statsUpdate";
50
130
 
51
131
  declare const PROD_COORDINATOR_URL = "https://api.reactor.inc";
52
132
  declare const OptionsSchema: z.ZodObject<{
53
133
  coordinatorUrl: z.ZodDefault<z.ZodString>;
54
134
  modelName: z.ZodString;
55
135
  local: z.ZodDefault<z.ZodBoolean>;
136
+ receive: z.ZodDefault<z.ZodArray<z.ZodObject<{
137
+ name: z.ZodString;
138
+ kind: z.ZodEnum<{
139
+ audio: "audio";
140
+ video: "video";
141
+ }>;
142
+ }, z.core.$strip>>>;
143
+ send: z.ZodDefault<z.ZodArray<z.ZodObject<{
144
+ name: z.ZodString;
145
+ kind: z.ZodEnum<{
146
+ audio: "audio";
147
+ video: "video";
148
+ }>;
149
+ }, z.core.$strip>>>;
56
150
  }, z.core.$strip>;
57
151
  type Options = z.input<typeof OptionsSchema>;
58
152
  type EventHandler = (...args: any[]) => void;
@@ -65,6 +159,10 @@ declare class Reactor {
65
159
  private model;
66
160
  private sessionExpiration?;
67
161
  private local;
162
+ /** Tracks the client RECEIVES from the model (model → client). */
163
+ private receive;
164
+ /** Tracks the client SENDS to the model (client → model). */
165
+ private send;
68
166
  private sessionId?;
69
167
  constructor(options: Options);
70
168
  private eventListeners;
@@ -72,24 +170,26 @@ declare class Reactor {
72
170
  off(event: ReactorEvent, handler: EventHandler): void;
73
171
  emit(event: ReactorEvent, ...args: any[]): void;
74
172
  /**
75
- * Public method to send a message to the machine.
76
- * Wraps the message in the specified channel envelope (defaults to "application").
77
- * @param command The command name to send.
173
+ * Sends a command to the model via the data channel.
174
+ *
175
+ * @param command The command name.
78
176
  * @param data The command payload.
79
- * @param scope The envelope scope – "application" (default) for model commands,
80
- * "runtime" for platform-level messages (e.g. requestCapabilities).
81
- * @throws Error if not in ready state
177
+ * @param scope "application" (default) for model commands, "runtime" for platform messages.
82
178
  */
83
179
  sendCommand(command: string, data: any, scope?: MessageScope): Promise<void>;
84
180
  /**
85
- * Public method to publish a track to the machine.
86
- * @param track The track to send to the machine.
181
+ * Publishes a MediaStreamTrack to a named send track.
182
+ *
183
+ * @param name The declared send track name (e.g. "webcam").
184
+ * @param track The MediaStreamTrack to publish.
87
185
  */
88
- publishTrack(track: MediaStreamTrack): Promise<void>;
186
+ publishTrack(name: string, track: MediaStreamTrack): Promise<void>;
89
187
  /**
90
- * Public method to unpublish the currently published track.
188
+ * Unpublishes the track with the given name.
189
+ *
190
+ * @param name The declared send track name to unpublish.
91
191
  */
92
- unpublishTrack(): Promise<void>;
192
+ unpublishTrack(name: string): Promise<void>;
93
193
  /**
94
194
  * Public method for reconnecting to an existing session, that may have been interrupted but can be recovered.
95
195
  * @param options Optional connect options (e.g. maxAttempts for SDP polling)
@@ -105,6 +205,11 @@ declare class Reactor {
105
205
  connect(jwtToken?: string, options?: ConnectOptions): Promise<void>;
106
206
  /**
107
207
  * Sets up event handlers for the machine client.
208
+ *
209
+ * Each handler captures the client reference at registration time and
210
+ * ignores events if this.machineClient has since changed (e.g. after
211
+ * disconnect + reconnect), preventing stale WebRTC teardown events from
212
+ * interfering with a new connection.
108
213
  */
109
214
  private setupMachineClientHandlers;
110
215
  /**
@@ -138,19 +243,24 @@ declare class Reactor {
138
243
 
139
244
  interface ReactorState {
140
245
  status: ReactorStatus;
141
- videoTrack: MediaStreamTrack | null;
246
+ /**
247
+ * Media tracks received from the model, keyed by track name.
248
+ *
249
+ * Each entry maps a declared **receive** track name (e.g. `"main_video"`,
250
+ * `"main_audio"`) to the live `MediaStreamTrack` delivered by the model.
251
+ */
252
+ tracks: Record<string, MediaStreamTrack>;
142
253
  lastError?: ReactorError;
143
254
  sessionId?: string;
144
255
  sessionExpiration?: number;
145
- insecureApiKey?: string;
146
256
  jwtToken?: string;
147
257
  }
148
258
  interface ReactorActions {
149
259
  sendCommand(command: string, data: any, scope?: MessageScope): Promise<void>;
150
260
  connect(jwtToken?: string, options?: ConnectOptions): Promise<void>;
151
261
  disconnect(recoverable?: boolean): Promise<void>;
152
- publishVideoStream(stream: MediaStream): Promise<void>;
153
- unpublishVideoStream(): Promise<void>;
262
+ publish(name: string, track: MediaStreamTrack): Promise<void>;
263
+ unpublish(name: string): Promise<void>;
154
264
  reconnect(options?: ConnectOptions): Promise<void>;
155
265
  }
156
266
  interface ReactorInternalState {
@@ -180,13 +290,26 @@ declare function ReactorProvider({ children, connectOptions, jwtToken, ...props
180
290
  declare function useReactorStore<T = ReactorStore>(selector: (state: ReactorStore) => T): T;
181
291
 
182
292
  interface ReactorViewProps {
293
+ /**
294
+ * The name of the **receive** track to render.
295
+ * Must match a track name declared in the `receive` array (model → client).
296
+ * Defaults to `"main_video"`.
297
+ */
298
+ track?: string;
299
+ /**
300
+ * Optional name of a **receive** audio track to play alongside the video
301
+ * (e.g. `"main_audio"`). The audio is mixed into the same `<video>` element.
302
+ */
303
+ audioTrack?: string;
183
304
  width?: number;
184
305
  height?: number;
185
306
  className?: string;
186
307
  style?: React.CSSProperties;
187
308
  videoObjectFit?: NonNullable<React.VideoHTMLAttributes<HTMLVideoElement>["style"]>["objectFit"];
309
+ /** Controls whether inbound audio plays. Default true (muted) to satisfy browser autoplay policies. */
310
+ muted?: boolean;
188
311
  }
189
- declare function ReactorView({ width, height, className, style, videoObjectFit, }: ReactorViewProps): react_jsx_runtime.JSX.Element;
312
+ declare function ReactorView({ track, audioTrack, width, height, className, style, videoObjectFit, muted, }: ReactorViewProps): react_jsx_runtime.JSX.Element;
190
313
 
191
314
  interface ReactorControllerProps {
192
315
  className?: string;
@@ -194,14 +317,19 @@ interface ReactorControllerProps {
194
317
  }
195
318
  declare function ReactorController({ className, style, }: ReactorControllerProps): react_jsx_runtime.JSX.Element;
196
319
 
197
- interface Props {
320
+ interface WebcamStreamProps {
321
+ /**
322
+ * The name of the **send** track to publish the webcam to.
323
+ * Must match a track name declared in the `send` array (client → model).
324
+ */
325
+ track: string;
198
326
  className?: string;
199
327
  style?: React.CSSProperties;
200
328
  videoConstraints?: MediaTrackConstraints;
201
329
  showWebcam?: boolean;
202
330
  videoObjectFit?: NonNullable<React.VideoHTMLAttributes<HTMLVideoElement>["style"]>["objectFit"];
203
331
  }
204
- declare function WebcamStream({ className, style, videoConstraints, showWebcam, videoObjectFit, }: Props): react_jsx_runtime.JSX.Element;
332
+ declare function WebcamStream({ track, className, style, videoConstraints, showWebcam, videoObjectFit, }: WebcamStreamProps): react_jsx_runtime.JSX.Element;
205
333
 
206
334
  /**
207
335
  * Generic hook for accessing selected parts of the Reactor store.
@@ -249,4 +377,4 @@ declare function useStats(): ConnectionStats | undefined;
249
377
  */
250
378
  declare function fetchInsecureJwtToken(apiKey: string, coordinatorUrl?: string): Promise<string>;
251
379
 
252
- export { ConflictError, type ConnectOptions, type ConnectionStats, type MessageScope, type Options, PROD_COORDINATOR_URL, Reactor, type ReactorConnectOptions, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, WebcamStream, fetchInsecureJwtToken, useReactor, useReactorInternalMessage, useReactorMessage, useReactorStore, useStats };
380
+ export { AbortError, type AudioTrackOptions, ConflictError, type ConnectOptions, type ConnectionStats, type MessageScope, type Options, PROD_COORDINATOR_URL, Reactor, type ReactorConnectOptions, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type TrackConfig, type VideoTrackOptions, WebcamStream, type WebcamStreamProps, audio, fetchInsecureJwtToken, isAbortError, useReactor, useReactorInternalMessage, useReactorMessage, useReactorStore, useStats, video };