> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reactor.inc/llms.txt
> Use this file to discover all available pages before exploring further.

# Reactor Class

> The base JavaScript class for connecting to any Reactor model

`Reactor` is the **base class** for every model on the platform. It speaks raw JSON over the wire: open a session, send commands by name, and receive generic message events.

Typed model SDKs like `HeliosModel` extend `Reactor` with named, schema-matched methods over the same wire protocol. See the [SDK Reference overview](/sdk-reference/using-the-sdk) for how the two layers relate, and the [Model API Reference](/model-api-reference/overview) for the commands and events a specific model accepts.

## Constructor

### `new Reactor()`

Creates a client for the given model. Call [`connect()`](#connect) afterward to open the session.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
new Reactor(options: ReactorOptions)
```

<ParamField path="modelName" type="string" required>
  The name of the model to connect to.
</ParamField>

<ParamField path="apiUrl" type="string" default="https://api.reactor.inc">
  The API URL.
</ParamField>

<ParamField path="local" type="boolean" default="false">
  If `true`, connects to a local runtime at `http://localhost:8080`. Ignores `apiUrl`.
</ParamField>

```typescript Example theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
import { Reactor } from "@reactor-team/js-sdk";

const reactor = new Reactor({
  modelName: "your-model-name",
});
```

***

## Methods

### `connect()`

Establishes a connection to the coordinator, waits for GPU assignment, and opens a WebRTC connection to the model.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.connect(jwtToken?: string, options?: ConnectOptions): Promise<void>
```

<ParamField path="jwtToken" type="string">
  Token for authentication. See [Authentication](/authentication).
</ParamField>

<ParamField path="options" type="ConnectOptions">
  Connection behavior options.
</ParamField>

<ParamField path="options.maxAttempts" type="number" default="6">
  Maximum SDP polling attempts before giving up.
</ParamField>

<ParamField path="options.autoResumeTracks" type="boolean" default="true">
  When `true`, every output (`recvonly`) track starts streaming as soon as the connection is established. Set to `false` to leave output tracks paused on connect and start them individually with [`resumeTrack()`](#resumetrack).
</ParamField>

<ParamField path="options.sessionId" type="string">
  Attach to a session that already exists (for example, one created by your backend) instead of creating a new one. The token passed to `connect()` must be valid for the account that owns the session. A client that adopts a session leaves it running on disconnect; its creator owns the lifecycle.
</ParamField>

<ParamField path="options.connectionId" type="number">
  Join the session using a specific WebRTC connection id already registered for it (for example, one your backend created and handed to this client). When omitted, the SDK registers a fresh connection and the server mints the id. `connect()` rejects if the id is unknown or already closed.
</ParamField>

### `disconnect()`

Closes the connection. Safe to call multiple times.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.disconnect(recoverable?: boolean): Promise<void>
```

<ParamField path="recoverable" type="boolean" default="false">
  If `true`, the session is kept alive on the server and can be resumed with `reconnect()`. If `false`, the session is terminated.
</ParamField>

### `reconnect()`

Reconnects to an existing session after a recoverable disconnect. Requires an active `sessionId` from a previous connection.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.reconnect(options?: ConnectOptions): Promise<void>
```

<ParamField path="options" type="ConnectOptions">
  Connection behavior options (e.g. `maxAttempts`).
</ParamField>

### `sendCommand()`

Sends a command to the model over the WebRTC data channel.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.sendCommand(command: string, data: any): Promise<void>
```

<ParamField path="command" type="string" required>
  The command name. Must match a command defined on the model.
</ParamField>

<ParamField path="data" type="object" required>
  The command payload. Shape depends on the command.
</ParamField>

```typescript Example theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
await reactor.sendCommand("set_prompt", { prompt: "a mountain landscape" });
```

Pass [`FileRef`](/sdk-reference/types#fileref) values from [`uploadFile()`](/sdk-reference/reactor-class#uploadfile) as parameters. See [File Uploads](/concepts/file-uploads) for details.

***

### `uploadFile()`

Uploads a file and returns a [`FileRef`](/sdk-reference/types#fileref) that can be passed into `sendCommand()`.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.uploadFile(file: File | Blob, options?: { name?: string }): Promise<FileRef>
```

<ParamField path="file" type="File | Blob" required>
  The file to upload.
</ParamField>

<ParamField path="options.name" type="string">
  Custom filename. Defaults to `file.name` for `File` objects, or `"upload"` for `Blob` objects.
</ParamField>

```typescript Example theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
const ref = await reactor.uploadFile(imageFile);
await reactor.sendCommand("set_image", { image: ref });
```

<Note>
  Can only be called when the status is `"ready"`.
</Note>

***

### `requestClip()`

Captures the last `durationSeconds` of the live session and resolves with a [`Clip`](/sdk-reference/types#clip).

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.requestClip(durationSeconds: number): Promise<Clip>
```

<ParamField path="durationSeconds" type="number" required>
  How many seconds back from "now" to capture. Capped server-side (5 minutes by default).
</ParamField>

```typescript Example theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
const clip = await reactor.requestClip(10);
```

Throws a [`RecordingError`](/sdk-reference/types#recordingerror) on invalid input, timeout, or disconnection. See [Recordings](/concepts/recordings).

<Note>
  Can only be called when the status is `"ready"`.
</Note>

***

### `requestRecording()`

Captures the entire session, from the start of recording up to "now", and resolves with a [`Clip`](/sdk-reference/types#clip).

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.requestRecording(): Promise<Clip>
```

```typescript Example theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
const clip = await reactor.requestRecording();
```

Behaves like [`requestClip()`](#requestclip) but covers the full session. See [Recordings](/concepts/recordings).

<Note>
  Can only be called when the status is `"ready"`.
</Note>

***

### `downloadClipAsFile()`

Downloads a [`Clip`](/sdk-reference/types#clip) as a single MP4. Triggers a browser download when `filename` is set, or returns the `Blob` when `filename` is `null`.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.downloadClipAsFile(
  clip: Clip,
  filename?: string | null,
  options?: DownloadClipOptions
): Promise<Blob>
```

<ParamField path="clip" type="Clip" required>
  The clip to download.
</ParamField>

<ParamField path="filename" type="string | null" default="&#x22;reactor-clip.mp4&#x22;">
  Filename to save. Pass `null` to skip the browser download and just receive the `Blob`.
</ParamField>

<ParamField path="options.jwt" type="string">
  JWT to authenticate the request. Required against `https://api.reactor.inc`. See [Authentication](/authentication).
</ParamField>

<ParamField path="options.signal" type="AbortSignal">
  Cancels both the metadata fetch and the segment downloads.
</ParamField>

<ParamField path="options.onProgress" type="(info: { fetched: number; total: number; bytes: number }) => void">
  Called after each segment completes. Use for progress UI.
</ParamField>

```typescript Example theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
const clip = await reactor.requestClip(10);
await reactor.downloadClipAsFile(clip, "highlight.mp4", { jwt });
```

<Tip>
  Reactor does not host clips. The URL on `clip.playlistUrl` expires after 24 hours, so download the bytes if you need them later. See [Recordings](/concepts/recordings).
</Tip>

***

### `publishTrack()`

**Direction:** client → model.

Publishes a media track to the model. The track name must match a `sendonly` track declared in the model's capabilities. Publishing is required and explicit: the model receives nothing on the track until you call this, and connecting alone never starts sending. Only one connection may publish a given input track at a time.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.publishTrack(name: string, track: MediaStreamTrack): Promise<void>
```

<ParamField path="name" type="string" required>
  Track name. Must match a `sendonly` track name from the model's capabilities.
</ParamField>

<ParamField path="track" type="MediaStreamTrack" required>
  A `MediaStreamTrack` from `getUserMedia()`, `getDisplayMedia()`, etc.
</ParamField>

```typescript Example theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
await reactor.publishTrack("webcam", stream.getVideoTracks()[0]);
```

***

### `unpublishTrack()`

**Direction:** client → model.

Stops publishing a track to the model, freeing the input track for another connection to publish.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.unpublishTrack(name: string): Promise<void>
```

<ParamField path="name" type="string" required>
  The name of the track to stop publishing.
</ParamField>

***

### `pauseTrack()`

**Direction:** model → client.

Unsubscribes from an output (`recvonly`) track so your client stops receiving it. The model keeps emitting frames to the track regardless; this only controls whether they reach you. Pair with `autoResumeTracks: false` to choose exactly which outputs you receive.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.pauseTrack(name: string): void
```

<ParamField path="name" type="string" required>
  The name of the output track to unsubscribe from.
</ParamField>

***

### `resumeTrack()`

**Direction:** model → client.

Subscribes to an output (`recvonly`) track so your client starts receiving it. This is a subscription, not a request to start generation: the model is already emitting frames, and there is no first-come ownership, so connections subscribe to the same output independently.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.resumeTrack(name: string): void
```

<ParamField path="name" type="string" required>
  The name of the output track to subscribe to.
</ParamField>

***

### `on()`

Registers an event listener.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.on(event: ReactorEvent, handler: (...args: any[]) => void): void
```

See [Events](/sdk-reference/events) for all available event types.

```typescript Example theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.on("statusChanged", (status) => console.log(status));
reactor.on("message", (msg) => console.log(msg));
```

***

### `off()`

Removes an event listener.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.off(event: ReactorEvent, handler: (...args: any[]) => void): void
```

***

### `getStatus()`

Returns the current connection status.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.getStatus(): ReactorStatus
```

Returns `"disconnected"`, `"connecting"`, `"waiting"`, or `"ready"`.

***

### `getState()`

Returns the current status and last error.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.getState(): ReactorState
```

***

### `getSessionId()`

Returns the current session ID, or `undefined` if not connected.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.getSessionId(): string | undefined
```

***

### `getLastError()`

Returns the most recent error, or `undefined` if no errors have occurred.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.getLastError(): ReactorError | undefined
```

***

### `getCapabilities()`

Returns the model's capabilities (tracks, commands, emission FPS), or `undefined` if not yet connected.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.getCapabilities(): Capabilities | undefined
```

***

### `getSessionInfo()`

Returns the full session response from the coordinator, or `undefined` if not connected.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.getSessionInfo(): SessionInfo | undefined
```

***

### `getStats()`

Returns the current WebRTC connection statistics, or `undefined` if not connected.

```typescript Signature theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
reactor.getStats(): ConnectionStats | undefined
```
