generateStream returns a Stream<LLMStreamEvent> directly. It is not a future, and there
is no wrapper object holding a separate token stream and metrics future.
LLMStreamEvent
LLMStreamFinalResult carries text, promptTokens, completionTokens, totalTokens,
totalTimeMs, timeToFirstTokenMs, tokensPerSecond, finishReason, promptEvalTimeMs,
and decodeTimeMs.
Final metrics
The terminal event usually carries anLLMStreamFinalResult. To collect the transcript and
metrics in one step as an LLMGenerationResult, hand the stream to
RunAnywhere.aggregateStream:
onToken receives the full transcript so far, not the individual delta, so it drops
straight into setState. It prefers the backend’s terminal aggregate when one is present
and falls back to locally concatenated text and wall-clock timings otherwise.
Request-shaped streaming
For multi-turn history or a conversation cache, stream from a request proto instead:Flutter Widget Example
Cancellation
Cancel ongoing generation at any time.cancelGeneration() is synchronous, returns void,
and is a best-effort no-op when nothing is in flight.
onCancel
hook calls into the same cancel path.
Best Practices
- Update UI incrementally: Append
event.tokento your state as events arrive - Show a cancel button: Let users stop long generations
- Handle cancellation gracefully: The stream completes when cancelled
- Get final metrics: Read
event.resulton the terminal event, or useaggregateStream
Generation starts when the first listener attaches, not when
generateStream is called, so no
tokens can be produced before your subscriber is ready.See Also
chat()
Simple one-liner
generate()
Non-streaming with metrics