Skip to main content
generateStream returns an AsyncIterable<LLMStreamEvent> synchronously. It is not a promise and it does not resolve to a { stream, result } pair.
Options are the same LLMGenerationOptions that generate() takes, with the same defaults.
Hermes does not support for await...of over NitroModules async iterables. It silently fails to iterate, so no tokens arrive and the UI hangs. Always drive the iterator with manual iterator.next() calls.

Basic usage

Calling iterator.return() cancels the native generation. Breaking out of the loop without it leaves the backend running, so put it in a finally.

LLMStreamEvent

LLMStreamFinalResult carries text, promptTokens, completionTokens, totalTokens, totalTimeMs, timeToFirstTokenMs, tokensPerSecond, finishReason, promptEvalTimeMs, and decodeTimeMs. An event with a non-empty errorMessage is followed by the iterator throwing that error, so wrap the loop in try.

aggregateStream

aggregateStream drives the iterator for you, tallies tokens and timing, and returns a populated LLMGenerationResult. It uses the manual-iterator pattern internally and tears the subscription down on early exit.
The onToken callback receives the full accumulated transcript, not the individual token, which is what you want for a React state setter.

React component

StreamingChat.tsx

Cancelling

iterator.return() already calls the native cancel and awaits it, so back-to-back cancel-then-generate sequences are safe. Call cancelGeneration() directly when you hold no iterator reference, for example from a global stop button.

Throttling UI updates

Very fast generation can outrun React. Batch state writes to one animation frame.

Generate

Non-streaming generation and options

Chat

Multi-turn conversations

System Prompts

Control model behavior

Configuration

Events and logging