@reactor-models/helios
v0.9.7
Published
Strongly-typed SDK for the Helios model on Reactor
Downloads
1,187
Maintainers
Readme
@reactor-models/helios
Typed JavaScript + React SDK for the Helios model on Reactor. Version v0.9.7.
Get started
Scaffold a starter app for Helios with create-reactor-app:
npx create-reactor-app my-app --model=heliospnpm dlx create-reactor-app my-app --model=heliosInstall
npm install @reactor-models/heliospnpm add @reactor-models/heliosThe package exports a plain-JavaScript client and a set of React bindings. Import whichever you need from @reactor-models/helios:
import { HeliosModel } from "@reactor-models/helios";import { HeliosProvider, useHelios } from "@reactor-models/helios";React 18 or later is required when using the provider and hooks. The token-loading examples below use React 19's use(); on React 18, fetch the JWT in a useEffect and pass it to the provider once it resolves.
Authenticate
Reactor uses short-lived JWTs for session auth. You hold your API key on your server, mint a token on demand, and the client never sees the raw key. Tokens are valid for 6 hours — if one leaks, it expires on its own.
Mint a JWT with POST https://api.reactor.inc/tokens and the Reactor-API-Key header; the response JSON is { "jwt": "..." }.
JavaScript (Next.js route handler)
// app/api/reactor/token/route.ts
import { NextResponse } from "next/server";
export async function POST() {
const res = await fetch("https://api.reactor.inc/tokens", {
method: "POST",
headers: { "Reactor-API-Key": process.env.REACTOR_API_KEY! },
});
const { jwt } = await res.json();
return NextResponse.json({ jwt });
}React (provider)
Call the /api/reactor/token route above from a client component and pass the result to the provider:
"use client";
import { use } from "react";
import { HeliosProvider } from "@reactor-models/helios";
import { ReactorView } from "@reactor-team/js-sdk";
async function getToken() {
const r = await fetch("/api/reactor/token", { method: "POST" });
const { jwt } = await r.json();
return jwt;
}
const tokenPromise = getToken();
export default function App() {
const token = use(tokenPromise);
return (
<HeliosProvider jwtToken={token} connectOptions={{ autoConnect: true }}>
<ReactorView className="w-full aspect-video" />
</HeliosProvider>
);
}Connect
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);React
The provider takes the JWT as a prop; fetch it from the same /api/reactor/token route the Authenticate example mints:
"use client";
import { use } from "react";
import { HeliosProvider, useHelios } from "@reactor-models/helios";
async function getToken() {
const r = await fetch("/api/reactor/token", { method: "POST" });
const { jwt } = await r.json();
return jwt;
}
const tokenPromise = getToken();
function Controller() {
const { status } = useHelios();
return <span>Status: {status}</span>;
}
export default function App() {
const token = use(tokenPromise);
return (
<HeliosProvider jwtToken={token}>
<Controller />
</HeliosProvider>
);
}Events
Client-to-model commands. The typed surface is HeliosModel (one method per event) in plain JS, and useHelios() in React — every field name below matches the parameter name the method accepts.
pause
Pause generation after the current chunk finishes. Frames stop streaming on main_video until resume is called. Requires generation to be active. Emits generation_paused on success, or command_error if not generating or already paused.
Emits: generation_paused, command_error
No parameters.
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.pause();React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { pause } = useHelios();
return <button onClick={() => pause()}>pause</button>;
}reset
Clear all session conditions (prompt, reference image, chunk index) and return the session to the initial waiting state. After reset, a new prompt must be set before start can be called again.
No parameters.
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.reset();React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { reset } = useHelios();
return <button onClick={() => reset()}>reset</button>;
}start
Begin generating video on main_video. Requires that a prompt has been set via set_prompt or schedule_prompt. Emits generation_started on success, or command_error if no prompt is set. Has no effect while already generating.
Emits: generation_started, command_error
No parameters.
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.start();React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { start } = useHelios();
return <button onClick={() => start()}>start</button>;
}resume
Resume generation from the exact state at which pause was issued. Emits generation_resumed on success, or command_error if not currently paused.
Emits: generation_resumed, command_error
No parameters.
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.resume();React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { resume } = useHelios();
return <button onClick={() => resume()}>resume</button>;
}setSeed
Set seed
| Parameter | Type | Required | Description |
|---|---|---|---|
| seed | number | | Seed for the random generator used to sample the initial noise. Use -1 to draw a fresh random seed. Read once when generation begins; later changes take effect only after reset followed by a new start. (default 0) |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.setSeed({ seed: 0 });React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { setSeed } = useHelios();
return <button onClick={() => setSeed({ seed: 0 })}>setSeed</button>;
}setImage
Provide a reference image that anchors generation (image-to-video). Can be set before start or replaced during generation; a new image applies from the next chunk onward. Exactly one of image (preferred) or image_b64 must be provided. Emits image_accepted and conditions_ready on success, or command_error if the file is missing or not an image. When both a prompt and an image are needed before start, prefer set_conditioning — it commits both atomically and avoids the ordering race between set_prompt and set_image.
Emits: image_accepted, conditions_ready, command_error
| Parameter | Type | Required | Description |
|---|---|---|---|
| image | FileRef | | Reference to a file uploaded via the Reactor presigned-URL protocol. (default null) |
| image_b64 | string | | Deprecated. Base64-encoded reference image (PNG or JPEG), optionally prefixed with a data: URI. Provided for backward compatibility; use image instead. Ignored when image is also present. (default "") |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
const fileRef = await helios.uploadFile(blob);
await helios.setImage({ image: fileRef, image_b64: "" });React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { setImage, uploadFile } = useHelios();
async function handlePick(file: File) {
const ref = await uploadFile(file);
await setImage({ image: ref, image_b64: "" });
}
return <input type="file" onChange={(e) => handlePick(e.target.files![0])} />;
}setPrompt
Set the scene prompt. Valid at any time: call before start to arm generation, or hot-swap during generation to steer the next chunk. Emits prompt_accepted and conditions_ready on success. When you also need to set a reference image before the first start, use set_conditioning instead to commit both atomically.
Emits: prompt_accepted, conditions_ready
| Parameter | Type | Required | Description |
|---|---|---|---|
| prompt | string | | Natural-language description of the scene to generate. Replaces any previously active prompt and takes effect on the next chunk. (default "") |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.setPrompt({ prompt: "A sunset over the ocean" });React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { setPrompt } = useHelios();
return <button onClick={() => setPrompt({ prompt: "A sunset over the ocean" })}>setPrompt</button>;
}setSrScale
Set sr_scale
| Parameter | Type | Required | Description |
|---|---|---|---|
| sr_scale | "off" \| "2x" \| "4x" | | Super-resolution factor applied to each emitted frame. off disables upscaling, 2x and 4x upscale the output. May be changed at any time; the new scale applies to the next emitted chunk. (default "2x") |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.setSrScale({ sr_scale: "off" });React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { setSrScale } = useHelios();
return <button onClick={() => setSrScale({ sr_scale: "off" })}>setSrScale</button>;
}schedulePrompt
Queue a prompt to take effect at a specific future chunk index. Multiple prompts can be queued; at each chunk boundary the latest scheduled prompt at or before the current chunk wins. Scheduling a prompt for a past chunk applies it on the next chunk. Emits prompt_accepted.
Emits: prompt_accepted
| Parameter | Type | Required | Description |
|---|---|---|---|
| chunk | number | | Zero-based chunk index at which the prompt takes effect. Chunk indices match those reported by chunk_complete. (min 0, default 0) |
| prompt | string | | Natural-language description of the scene that should become active starting at the given chunk. (default "") |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.schedulePrompt({ chunk: 0, prompt: "A sunset over the ocean" });React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { schedulePrompt } = useHelios();
return <button onClick={() => schedulePrompt({ chunk: 0, prompt: "A sunset over the ocean" })}>schedulePrompt</button>;
}setConditioning
Atomically commit a prompt and a reference image together, in a single command. Use this in place of separate set_prompt and set_image calls when both are required before start — the combined command can't be split across the wire, so it removes the race where start is processed before the image upload has been resolved. Both prompt and image are required. Emits prompt_accepted, image_accepted, and conditions_ready on success, or command_error if any input is missing or invalid (no state is mutated on error).
Emits: prompt_accepted, image_accepted, conditions_ready, command_error
| Parameter | Type | Required | Description |
|---|---|---|---|
| image | FileRef | | Reference to a file uploaded via the Reactor presigned-URL protocol. (default null) |
| prompt | string | | Natural-language description of the scene to generate. Replaces any previously active prompt and takes effect on the next chunk. (default "") |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
const fileRef = await helios.uploadFile(blob);
await helios.setConditioning({ image: fileRef, prompt: "A sunset over the ocean" });React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { setConditioning, uploadFile } = useHelios();
async function handlePick(file: File) {
const ref = await uploadFile(file);
await setConditioning({ image: ref, prompt: "A sunset over the ocean" });
}
return <input type="file" onChange={(e) => handlePick(e.target.files![0])} />;
}setImageStrength
Set image_strength
| Parameter | Type | Required | Description |
|---|---|---|---|
| image_strength | number | | How strongly the reference image anchors the generated video. 1.0 locks the first frame to the reference; lower values let the scene drift further from it. Ignored when no reference image has been set. May be changed at any time; the new value is read at the start of the next chunk. (min 0, max 1, default 1) |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
await helios.connect(jwt);
await helios.setImageStrength({ image_strength: 1 });React
"use client";
import { useHelios } from "@reactor-models/helios";
function Example() {
const { setImageStrength } = useHelios();
return <button onClick={() => setImageStrength({ image_strength: 1 })}>setImageStrength</button>;
}Messages
Model-to-client messages. Register a typed listener with on… on HeliosModel, or a useHelios… hook in React, to receive only the messages you care about.
state
Snapshot of the session's observable state.
Emitted after every completed chunk and after any command that mutates session state (set_prompt, schedule_prompt, set_image, start, pause, resume, reset). Clients can treat this as the single source of truth for driving UI, without having to track every individual command and message themselves.
Wire envelope ------------- Published with type: "state" (the snake-cased class name) so the envelope matches the pre-0.8 Helios protocol and existing clients (public-demos, the docs examples, older SDK consumers) keep working unchanged. Field names mirror the pre-0.8 contract one-for-one; the only addition is started, which the old shape couldn't express (running=False collapsed "never started" and "paused" into the same bit).
Listener: onState · React hook: useHeliosState
| Field | Type | Description |
|---|---|---|
| paused | boolean | True while generation is paused via pause. |
| running | boolean | True while the chunk loop is actively producing frames — equivalent to started and not paused. False both before start and while paused; read started to disambiguate. |
| started | boolean | True once start has been accepted. Remains true while paused; reset to false by reset. Distinguishes a paused run (started=True, paused=True) from a session that has never started (started=False, paused=False) — the running flag collapses both of those to False. |
| image_set | boolean | True once a reference image has been set for the session. |
| current_chunk | number | Zero-based index of the chunk the model is currently working on. 0 for a fresh session or after reset. |
| current_frame | number | Running total of frames emitted on main_video since the last reset (or session connect). Resets to 0 on reset. |
| current_prompt | unknown | The prompt currently driving generation, or null if no prompt has been applied yet (e.g. before start). |
| image_strength | number | Current value of the image_strength input field (0.0–1.0). Ignored when no reference image is set. |
| scheduled_prompts | Record<string, unknown> | Pending scheduled prompts, keyed by the chunk index at which they take effect. Entries are removed once applied. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onState((msg) => {
console.log(
"state",
msg.paused,
msg.running,
msg.started,
msg.image_set,
msg.current_chunk,
msg.current_frame,
msg.current_prompt,
msg.image_strength,
msg.scheduled_prompts,
);
});
await helios.connect(jwt);React
import { useHeliosState } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosState((msg) => {
console.log(
"state",
msg.paused,
msg.running,
msg.started,
msg.image_set,
msg.current_chunk,
msg.current_frame,
msg.current_prompt,
msg.image_strength,
msg.scheduled_prompts,
);
});command_error
Emitted when a command is rejected because preconditions are not met.
Listener: onCommandError · React hook: useHeliosCommandError
| Field | Type | Description |
|---|---|---|
| reason | string | Human-readable explanation of why the command was rejected. |
| command | string | Name of the command that was rejected. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onCommandError((msg) => {
console.log("command_error", msg.reason, msg.command);
});
await helios.connect(jwt);React
import { useHeliosCommandError } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosCommandError((msg) => {
console.log("command_error", msg.reason, msg.command);
});chunk_complete
Emitted once per completed 33-frame chunk of main_video.
Listener: onChunkComplete · React hook: useHeliosChunkComplete
| Field | Type | Description |
|---|---|---|
| chunk_index | number | Zero-based index of the chunk that just completed. |
| active_prompt | string | The prompt used to generate this chunk. |
| frames_emitted | number | Running total of frames emitted on main_video up to and including this chunk. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onChunkComplete((msg) => {
console.log(
"chunk_complete",
msg.chunk_index,
msg.active_prompt,
msg.frames_emitted,
);
});
await helios.connect(jwt);React
import { useHeliosChunkComplete } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosChunkComplete((msg) => {
console.log(
"chunk_complete",
msg.chunk_index,
msg.active_prompt,
msg.frames_emitted,
);
});image_accepted
Emitted after set_image successfully loads a reference image.
Listener: onImageAccepted · React hook: useHeliosImageAccepted
| Field | Type | Description |
|---|---|---|
| width | number | Width in pixels of the reference image after it was center-cropped and resized to the model's output resolution. |
| height | number | Height in pixels of the reference image after it was center-cropped and resized to the model's output resolution. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onImageAccepted((msg) => {
console.log("image_accepted", msg.width, msg.height);
});
await helios.connect(jwt);React
import { useHeliosImageAccepted } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosImageAccepted((msg) => {
console.log("image_accepted", msg.width, msg.height);
});prompt_accepted
Emitted after set_prompt or schedule_prompt is accepted.
Listener: onPromptAccepted · React hook: useHeliosPromptAccepted
| Field | Type | Description |
|---|---|---|
| prompt | string | The prompt text that was accepted. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onPromptAccepted((msg) => {
console.log("prompt_accepted", msg.prompt);
});
await helios.connect(jwt);React
import { useHeliosPromptAccepted } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosPromptAccepted((msg) => {
console.log("prompt_accepted", msg.prompt);
});conditions_ready
Emitted after set_prompt or set_image so the client can tell at a glance whether start will succeed.
Listener: onConditionsReady · React hook: useHeliosConditionsReady
| Field | Type | Description |
|---|---|---|
| has_image | boolean | True once a reference image has been set for the session. |
| has_prompt | boolean | True once at least one prompt has been set for the session. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onConditionsReady((msg) => {
console.log("conditions_ready", msg.has_image, msg.has_prompt);
});
await helios.connect(jwt);React
import { useHeliosConditionsReady } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosConditionsReady((msg) => {
console.log("conditions_ready", msg.has_image, msg.has_prompt);
});generation_paused
Emitted in response to pause, once the current chunk finishes.
Listener: onGenerationPaused · React hook: useHeliosGenerationPaused
| Field | Type | Description |
|---|---|---|
| chunk_index | number | Index of the last completed chunk before pausing. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onGenerationPaused((msg) => {
console.log("generation_paused", msg.chunk_index);
});
await helios.connect(jwt);React
import { useHeliosGenerationPaused } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosGenerationPaused((msg) => {
console.log("generation_paused", msg.chunk_index);
});generation_resumed
Emitted in response to resume when leaving the paused state.
Listener: onGenerationResumed · React hook: useHeliosGenerationResumed
| Field | Type | Description |
|---|---|---|
| chunk_index | number | Index of the next chunk to be generated. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onGenerationResumed((msg) => {
console.log("generation_resumed", msg.chunk_index);
});
await helios.connect(jwt);React
import { useHeliosGenerationResumed } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosGenerationResumed((msg) => {
console.log("generation_resumed", msg.chunk_index);
});generation_started
Emitted once when start succeeds and frames begin streaming.
Listener: onGenerationStarted · React hook: useHeliosGenerationStarted
| Field | Type | Description |
|---|---|---|
| prompt | string | The prompt active at the start of generation. |
| chunk_index | number | Chunk index at which generation begins. Always 0 for a fresh session or after a reset. |
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onGenerationStarted((msg) => {
console.log("generation_started", msg.prompt, msg.chunk_index);
});
await helios.connect(jwt);React
import { useHeliosGenerationStarted } from "@reactor-models/helios";
// Inside a React component wrapped by <HeliosProvider>:
useHeliosGenerationStarted((msg) => {
console.log("generation_started", msg.prompt, msg.chunk_index);
});Tracks
Named media channels between your app and the Helios model. Use the typed helpers below — HeliosModel.publish<Track> / on<Track> in plain JS, and useHeliosTrack or the per-track <Helios<Track>View> components in React — so track names are checked at compile time.
main_video
A video channel you subscribe to — the model publishes this for your app to render.
JavaScript
import { HeliosModel } from "@reactor-models/helios";
const helios = new HeliosModel();
helios.onMainVideo((track, stream) => {
// attach to a <video> element, pipe to a canvas, etc.
videoEl.srcObject = stream;
});
await helios.connect(jwt);React
"use client";
import { HeliosMainVideoView } from "@reactor-models/helios";
// Inside a component wrapped by <HeliosProvider>:
export function Example() {
return <HeliosMainVideoView className="w-full aspect-video" />;
}