Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/generate-world.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@tanstack/ai': minor
'@tanstack/ai-event-client': patch
'@tanstack/ai-reactor': minor
---

Add `generateWorld()` for live, prompt-steerable world sessions, plus a first-party Reactor adapter (`reactorWorld`, `reactorVideo`) that mints a session-scoped token for Orbis, Helios, FastH3, and other Reactor world and video models. `generateVideo()` returns that token for live Reactor sessions instead of a download URL.
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ testing/

examples/ # Example applications
├── ts-react-chat/ # React chat example
├── ts-react-world/ # Live world generation (Reactor)
├── ts-solid-chat/ # Solid chat example
├── ts-vue-chat/ # Vue chat example
├── ts-svelte-chat/ # Svelte chat example
Expand Down
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ Learn more in the

- [Generations](https://tanstack.com/ai/latest/docs/media/generations) - one
pattern for image generation, text-to-speech, transcription, summarization,
audio generation, and video generation.
audio generation, video generation, and world generation.
- [Realtime Voice Chat](https://tanstack.com/ai/latest/docs/media/realtime-chat) -
build low-latency realtime voice experiences.
- [Code Mode](https://tanstack.com/ai/latest/docs/code-mode/code-mode) - let
Expand All @@ -202,20 +202,21 @@ Learn more in the

Official adapters include:

| Package | Use it for |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| [`@tanstack/ai-openrouter`](https://tanstack.com/ai/latest/docs/adapters/openrouter) | 300+ models through one OpenRouter API, with per-request cost tracking |
| [`@tanstack/ai-openai`](https://tanstack.com/ai/latest/docs/adapters/openai) | OpenAI chat, image, video, speech, transcription, realtime, and provider tools |
| [`@tanstack/ai-anthropic`](https://tanstack.com/ai/latest/docs/adapters/anthropic) | Anthropic Claude chat, thinking, tools, structured outputs, and Vertex Claude |
| [`@tanstack/ai-gemini`](https://tanstack.com/ai/latest/docs/adapters/gemini) | Google Gemini chat, image, speech, and audio generation |
| [`@tanstack/ai-vertex`](https://tanstack.com/ai/latest/docs/adapters/vertex) | Gemini on Vertex AI with regional endpoints and Google Cloud credentials |
| [`@tanstack/ai-ollama`](https://tanstack.com/ai/latest/docs/adapters/ollama) | Local Ollama models |
| [`@tanstack/ai-grok`](https://tanstack.com/ai/latest/docs/adapters/grok) | xAI Grok chat, images, and realtime |
| [`@tanstack/ai-groq`](https://tanstack.com/ai/latest/docs/adapters/groq) | Groq low-latency inference |
| [`@tanstack/ai-elevenlabs`](https://tanstack.com/ai/latest/docs/adapters/elevenlabs) | ElevenLabs realtime voice, speech, transcription, music, and sound effects |
| [`@tanstack/ai-byteplus`](https://tanstack.com/ai/latest/docs/adapters/byteplus) | BytePlus Seed chat, Seedance video, Seedream image, and Seed Speech TTS/ASR |
| [`@tanstack/ai-fal`](https://tanstack.com/ai/latest/docs/adapters/fal) | fal.ai image, video, audio, speech, and transcription models |
| [`@tanstack/ai-cloudflare`](https://tanstack.com/ai/latest/docs/adapters/cloudflare) | Cloudflare Workers AI chat, embeddings, image, speech, transcription, and AI Gateway |
| Package | Use it for |
| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
| [`@tanstack/ai-openrouter`](https://tanstack.com/ai/latest/docs/adapters/openrouter) | 300+ models through one OpenRouter API, with per-request cost tracking |
| [`@tanstack/ai-openai`](https://tanstack.com/ai/latest/docs/adapters/openai) | OpenAI chat, image, video, speech, transcription, realtime, and provider tools |
| [`@tanstack/ai-anthropic`](https://tanstack.com/ai/latest/docs/adapters/anthropic) | Anthropic Claude chat, thinking, tools, structured outputs, and Vertex Claude |
| [`@tanstack/ai-gemini`](https://tanstack.com/ai/latest/docs/adapters/gemini) | Google Gemini chat, image, speech, and audio generation |
| [`@tanstack/ai-vertex`](https://tanstack.com/ai/latest/docs/adapters/vertex) | Gemini on Vertex AI with regional endpoints and Google Cloud credentials |
| [`@tanstack/ai-ollama`](https://tanstack.com/ai/latest/docs/adapters/ollama) | Local Ollama models |
| [`@tanstack/ai-grok`](https://tanstack.com/ai/latest/docs/adapters/grok) | xAI Grok chat, images, and realtime |
| [`@tanstack/ai-groq`](https://tanstack.com/ai/latest/docs/adapters/groq) | Groq low-latency inference |
| [`@tanstack/ai-elevenlabs`](https://tanstack.com/ai/latest/docs/adapters/elevenlabs) | ElevenLabs realtime voice, speech, transcription, music, and sound effects |
| [`@tanstack/ai-byteplus`](https://tanstack.com/ai/latest/docs/adapters/byteplus) | BytePlus Seed chat, Seedance video, Seedream image, and Seed Speech TTS/ASR |
| [`@tanstack/ai-fal`](https://tanstack.com/ai/latest/docs/adapters/fal) | fal.ai image, video, audio, speech, and transcription models |
| [`@tanstack/ai-reactor`](https://tanstack.com/ai/latest/docs/adapters/reactor) | Reactor live world and video generation (Orbis, Happy Oyster, LingBot, Helios, FastH3) |
| [`@tanstack/ai-cloudflare`](https://tanstack.com/ai/latest/docs/adapters/cloudflare) | Cloudflare Workers AI chat, embeddings, image, speech, transcription, and AI Gateway |

The adapter system is tree-shakeable by activity. Import `openaiText` for chat,
`openaiImage` for images, `falVideo` for video, `geminiSpeech` for TTS, and so
Expand Down
157 changes: 157 additions & 0 deletions docs/adapters/reactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---
title: Reactor
id: reactor-adapter
description: "Generate live worlds and video with Reactor models in TanStack AI via the @tanstack/ai-reactor adapter."
keywords:
- tanstack ai
- reactor
- world generation
- video generation
- orbis
- helios
- generateWorld
- generateVideo
- adapter
---

Reactor hosts live world and video models. You describe a scene. Then you open a session and stream video. You can steer the stream with a new prompt.

Use `reactorWorld()` with `generateWorld()` for navigable worlds. Use `reactorVideo()` with `generateVideo()` for live video models. Both mint a session token. Neither supports `chat()`.

## Installation

<!-- ::start:tabs variant="package-manager" mode="install" -->

react: @tanstack/ai-reactor
vue: @tanstack/ai-reactor
solid: @tanstack/ai-reactor
svelte: @tanstack/ai-reactor
preact: @tanstack/ai-reactor
angular: @tanstack/ai-reactor
vanilla: @tanstack/ai-reactor
octane: @tanstack/ai-reactor

<!-- ::end:tabs -->

Peer dependency: `@tanstack/ai`. The browser also needs `@reactor-team/js-sdk` to connect and play the stream. See [World Generation](../media/world-generation) and [Video Generation](../media/video-generation).

A full working app is in [`examples/ts-react-world`](https://github.com/TanStack/ai/tree/main/examples/ts-react-world).

## API key

Create a key in the [Reactor dashboard](https://www.reactor.inc/dashboard). Keys start with `rk_`.

The example app uses [Bring Your Own Key](../advanced/byok). The browser pastes the key. The relay reads `x-byok-reactor`, then `REACTOR_API_KEY`.

```ts
import { generateWorld } from '@tanstack/ai'
import { byokMissing, getByokKey } from '@tanstack/ai/byok/server'
import { reactorWorld } from '@tanstack/ai-reactor'
import { reactorByok } from '@tanstack/ai-reactor/byok'

export async function POST(request: Request) {
const apiKey = getByokKey(request, reactorByok)
if (!apiKey) return byokMissing(reactorByok)

const world = await generateWorld({
adapter: reactorWorld('visko-orbis-stable', { apiKey }),
prompt: 'A neon cyberpunk city at night, slow aerial drift',
})

return Response.json({
token: world.token,
model: world.model,
prompt: world.prompt,
expiresAt: world.expiresAt,
})
}
```

The adapter mints a **session-scoped** token for that model only. Hand `world.token`, `world.model`, and `world.prompt` to the browser. Do not put the API key in the JSON body.

## Models

Pass a string literal so TypeScript can narrow options.

```ts
import { reactorWorld } from '@tanstack/ai-reactor'

const adapter = reactorWorld('visko-orbis-stable')
```

| Id | Connect slug |
| --- | --- |
| `visko-orbis-stable` | `reactor/visko-orbis-stable` |
| `visko-orbis-dynamic` | `reactor/visko-orbis-dynamic` |
| `happy-oyster-adventure` | `reactor/happy-oyster-adventure` |
| `happy-oyster-director` | `reactor/happy-oyster-director` |
| `lingbot-world-2` | `reactor/lingbot-world-2` |
| `lingbot` | `reactor/lingbot` |
| `helios` | `reactor/helios` |

`world.model` is the connect slug. Pass it to `new Reactor({ modelName })`.

## Video

Reactor video is a live stream, not a finished file. `generateVideo()` returns a token. The browser connects, sets the prompt, and plays the track. Do not call `getVideoJobStatus()` or wait for a download URL.

```ts
import { generateVideo } from '@tanstack/ai'
import { reactorVideo } from '@tanstack/ai-reactor'

const video = await generateVideo({
adapter: reactorVideo('helios', { apiKey }),
prompt: 'A neon cyberpunk city at night, slow aerial drift',
})
```

Hand `video.token`, `video.model`, and `video.prompt` to the browser. Connect the same way as in [World Generation](../media/world-generation).

| Id | Connect slug |
| --- | --- |
| `helios` | `reactor/helios` |
| `fast-h3` | `reactor/fast-h3` |
| `visko-orbis-stable` | `reactor/visko-orbis-stable` |
| `visko-orbis-dynamic` | `reactor/visko-orbis-dynamic` |
| `longlive-v2` | `reactor/longlive-v2` |
| `ltx2` | `reactor/ltx2` |

`helios` and Orbis also work with `reactorWorld()`. Pick `generateVideo()` when you want a video session. Pick `generateWorld()` when you want a navigable world.

Pass a text prompt only. Set a reference image in the browser with `uploadFile` and `set_image` after connect.

## Provider options

Orbis reads these on the next `start`. Put them in `modelOptions`. The browser applies them with `sendCommand` before `start`.

```ts
const world = await generateWorld({
adapter: reactorWorld('visko-orbis-stable'),
prompt: 'Black volcanic cliffs, slow aerial camera',
modelOptions: {
resolution: '2k',
seed: 42,
audioEnabled: true,
},
})
```

| Option | Meaning |
| --- | --- |
| `resolution` | `1080p`, `2k`, or `4k` delivery tier |
| `seed` | RNG seed for the next run |
| `audioEnabled` | When `false`, skip audio compute |
| `audioPrompt` | Sound description, or `""` for picture-driven audio |

## Custom endpoint

```ts
const adapter = reactorWorld('visko-orbis-stable', {
apiKey,
baseUrl: 'https://api.reactor.inc',
})
```

## What you have now

A server call that mints a scoped Reactor token for one world or video model. Next: connect in the browser as shown in [World Generation](../media/world-generation).
1 change: 1 addition & 0 deletions docs/advanced/otel.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ Each media call produces one `CLIENT` span tagged with the activity's `gen_ai.op
| `generateAudio` | `audio_generation` |
| `generateSpeech` | `text_to_speech` |
| `generateTranscription` | `transcription` |
| `generateWorld` | `world_generation` |
| `summarize` | `summarize` |

The span carries `gen_ai.system` and `gen_ai.request.model` at start and, on finish, the same `gen_ai.usage.*` / `tanstack.ai.usage.*` attributes documented above — including the `tanstack.ai.usage.billed_quantity` / `tanstack.ai.usage.billed_unit` pair for unit-billed media. When a `Meter` is supplied it records the `gen_ai.client.operation.duration` histogram, tagged per activity. For streaming video the span covers the full create → poll → complete lifecycle. Non-streaming video is two calls, so the submit itself emits no span — the run opens once the provider accepts the job, and the `getVideoJobStatus()` poll that observes a terminal state ends it. If a streaming video consumer abandons the stream before completion, the span is ended via `onAbort` (status `ERROR`, `tanstack.ai.completion.reason = cancelled`) rather than leaked.
Expand Down
20 changes: 16 additions & 4 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"label": "Overview",
"to": "getting-started/overview",
"addedAt": "2026-04-15",
"updatedAt": "2026-09-03"
"updatedAt": "2026-09-04"
},
{
"label": "Quick Start",
Expand Down Expand Up @@ -223,7 +223,7 @@
"label": "OpenTelemetry",
"to": "advanced/otel",
"addedAt": "2026-05-08",
"updatedAt": "2026-08-08"
"updatedAt": "2026-09-04"
},
{
"label": "Compaction",
Expand Down Expand Up @@ -567,7 +567,7 @@
"label": "Generations",
"to": "media/generations",
"addedAt": "2026-04-15",
"updatedAt": "2026-08-19"
"updatedAt": "2026-09-04"
},
{
"label": "Realtime Voice Chat",
Expand Down Expand Up @@ -609,7 +609,13 @@
"label": "Video Generation",
"to": "media/video-generation",
"addedAt": "2026-04-15",
"updatedAt": "2026-08-31"
"updatedAt": "2026-09-04"
},
{
"label": "World Generation",
"to": "media/world-generation",
"addedAt": "2026-09-04",
"updatedAt": "2026-09-04"
},
{
"label": "Generation Hooks",
Expand Down Expand Up @@ -1002,6 +1008,12 @@
"addedAt": "2026-04-15",
"updatedAt": "2026-08-20"
},
{
"label": "Reactor",
"to": "adapters/reactor",
"addedAt": "2026-09-04",
"updatedAt": "2026-09-04"
},
{
"label": "OpenRouter Adapter",
"to": "adapters/openrouter",
Expand Down
1 change: 1 addition & 0 deletions docs/getting-started/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ With the help of adapters, TanStack AI can connect to various LLM providers. Ava
- **@tanstack/ai-bedrock** - Amazon Bedrock (Claude, Nova, Llama, and more via AWS)
- **@tanstack/ai-byteplus** - BytePlus (Seed chat, Seedance video, Seedream image, Seed Speech)
- **@tanstack/ai-fal** - fal (image & video generation)
- **@tanstack/ai-reactor** - Reactor (live world and video generation: Orbis, Happy Oyster, LingBot, Helios, FastH3)
- **@tanstack/ai-llmgateway** - LLM Gateway (hundreds of models via one OpenAI-compatible endpoint, self-hostable)
- **@tanstack/ai-cloudflare** - Cloudflare Workers AI (chat, embeddings, image, speech, transcription) and AI Gateway routing
- **@tanstack/ai-lovable** - Lovable AI Gateway (Google and OpenAI chat, image, video, embeddings, and speech via one project key)
Expand Down
6 changes: 4 additions & 2 deletions docs/media/generations.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ keywords:

# Generations

You want an image, some speech, a transcript or a video, not a conversation. Every one
You want an image, some speech, a transcript, a video, or a live world, not a conversation. Every one
of those is a **generation**: one request, one result. They all share the same shape, so
learning one teaches you the rest.

For a live, prompt-steerable stream that does not end as a file, see [World Generation](./world-generation).

## The fastest path

A server route that streams the result:
Expand Down Expand Up @@ -88,7 +90,7 @@ streaming is handled for you. All three are written out in
| Summarization | `summarize()` | `useSummarize()` | - |
| Video generation | `generateVideo()` | `useGenerateVideo()` | [Video Generation](./video-generation) |

> **Note:** Video generation uses a jobs/polling architecture. The `useGenerateVideo` hook additionally exposes `jobId`, `videoStatus`, `onJobCreated`, and `onStatusUpdate` for tracking the polling lifecycle. See the [Video Generation](./video-generation) guide for details.
> **Note:** Most video adapters use a jobs/polling architecture. The `useGenerateVideo` hook additionally exposes `jobId`, `videoStatus`, `onJobCreated`, and `onStatusUpdate` for tracking the polling lifecycle. Reactor returns a live-session token. There is no download URL. See the [Video Generation](./video-generation) guide for details.

## Advanced

Expand Down
Loading
Loading