#[non_exhaustive]pub enum StreamEvent {
Block(ContentBlock),
Reasoning(String),
Finish(FinishReason),
}Expand description
One item in the stream returned by query().
Before 0.8.0 the stream yielded bare ContentBlocks, which left no room for anything
that is not content — most importantly the reason generation stopped. StreamEvent makes
that explicit: content arrives as StreamEvent::Block, and the stream always ends with
exactly one StreamEvent::Finish.
§Guarantees
- Exactly one
StreamEvent::Finishis emitted per stream, and it is the final event. StreamEvent::Reasoningis emitted only whenAgentOptions::include_reasoningis enabled, and never carries text that also appears in aContentBlock::Text.
The enum is #[non_exhaustive]: future channels can be added without another breaking
release, so match with a _ arm.
§Examples
use futures::StreamExt;
use open_agent::{AgentOptions, ContentBlock, FinishReason, StreamEvent, query};
let options = AgentOptions::builder()
.model("deepseek-reasoner")
.base_url("http://localhost:1234/v1")
.build()?;
let mut answer = String::new();
let mut stream = query("Reply with JSON.", &options).await?;
while let Some(event) = stream.next().await {
match event? {
StreamEvent::Block(ContentBlock::Text(text)) => answer.push_str(&text.text),
StreamEvent::Finish(FinishReason::Length) => {
// Truncated at the token cap: retry with a larger budget rather than
// treating the unparseable body as a refusal.
}
_ => {}
}
}Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Block(ContentBlock)
One content fragment: a piece of assistant text as it arrives, or a fully assembled tool call.
Text arrives split across as many events as the server sent deltas, in order. Join them to reconstruct the answer.
Reasoning(String)
One fragment of reasoning/chain-of-thought text from the model’s side channel.
Opt in with
AgentOptions::builder().include_reasoning(true).
This text is never merged into a ContentBlock::Text and never enters conversation
history.
Finish(FinishReason)
The stream has ended; carries why generation stopped.
Implementations§
Source§impl StreamEvent
impl StreamEvent
Sourcepub fn as_block(&self) -> Option<&ContentBlock>
pub fn as_block(&self) -> Option<&ContentBlock>
Returns the content block if this event carries one.
Sourcepub fn into_block(self) -> Option<ContentBlock>
pub fn into_block(self) -> Option<ContentBlock>
Consumes the event, returning its content block if it carries one.
This is the shortest migration path from the pre-0.8.0 block stream:
let mut stream = query("hi", &options).await?;
while let Some(event) = stream.next().await {
if let Some(ContentBlock::Text(text)) = event?.into_block() {
print!("{}", text.text);
}
}Sourcepub fn as_text(&self) -> Option<&str>
pub fn as_text(&self) -> Option<&str>
Returns the text if this event carries a ContentBlock::Text.
Sourcepub fn as_reasoning(&self) -> Option<&str>
pub fn as_reasoning(&self) -> Option<&str>
Returns the reasoning text if this event carries one.
Sourcepub fn finish_reason(&self) -> Option<&FinishReason>
pub fn finish_reason(&self) -> Option<&FinishReason>
Returns the finish reason if this is the terminating event.
Trait Implementations§
Source§impl Clone for StreamEvent
impl Clone for StreamEvent
Source§fn clone(&self) -> StreamEvent
fn clone(&self) -> StreamEvent
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more