use futures::StreamExt;
use molo::CancellationToken;
use molo::agent::{CancellableAgent, MessageChunk};
use molo::provider::{
ChatRequest, ChatResponse, FinishReason, Provider, ProviderError, StreamEvent,
};
use std::io::Write;
use std::time::Duration;
struct SlowProvider;
#[async_trait::async_trait]
impl Provider for SlowProvider {
async fn chat(&self, _request: ChatRequest) -> Result<ChatResponse, ProviderError> {
unreachable!("example uses streaming path only")
}
async fn stream_chat(
&self,
_request: ChatRequest,
) -> Result<
futures::stream::BoxStream<'static, Result<StreamEvent, ProviderError>>,
ProviderError,
> {
Ok(Box::pin(async_stream::stream! {
for chunk in ["Hello", ",", " this", " is", " a", " long", " reply"] {
yield Ok(StreamEvent::Delta(chunk.into()));
tokio::time::sleep(Duration::from_millis(40)).await;
}
yield Ok(StreamEvent::Done { reason: FinishReason::Stop, usage: None });
}))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut agent = molo::react_agent!(SlowProvider, "You are a helpful assistant");
println!("user: say something");
let token = CancellationToken::new();
tokio::spawn({
let token = token.clone();
async move {
tokio::time::sleep(Duration::from_millis(150)).await;
println!(" [Esc] stop the current reply");
token.cancel();
}
});
let mut stream = agent
.run_stream_cancellable("say something", &token)
.await?;
let mut got = String::new();
while let Some(event) = stream.next().await {
match event? {
MessageChunk::Delta(delta) => {
print!("{delta}");
std::io::stdout().flush()?;
got.push_str(&delta);
}
MessageChunk::ToolCall { .. } | MessageChunk::ToolResult { .. } => {}
MessageChunk::Done(_) => {
println!();
break;
}
MessageChunk::Cancelled => {
println!("\n [stopped]");
break;
}
_ => {}
}
}
println!(" partial reply emitted so far: {got:?}");
drop(stream);
println!("\nuser: continue");
let token = CancellationToken::new();
let mut stream = agent.run_stream_cancellable("continue", &token).await?;
while let Some(event) = stream.next().await {
match event? {
MessageChunk::Delta(delta) => {
print!("{delta}");
std::io::stdout().flush()?;
}
MessageChunk::ToolCall { .. } | MessageChunk::ToolResult { .. } => {}
MessageChunk::Done(_) => {
println!();
break;
}
MessageChunk::Cancelled => {
println!("\n [stopped]");
break;
}
_ => {}
}
}
Ok(())
}