use std::time::Duration;
use anyhow::Result;
use async_trait::async_trait;
use sein::{AgentEngine, NodeTrait};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum AppNode {
Thinking,
GreetTool,
Exit,
}
struct CounterContext {
current: u32,
max: u32,
}
struct ThinkingNode;
#[async_trait]
impl NodeTrait<CounterContext> for ThinkingNode {
async fn enter(&self, ctx: &mut CounterContext) -> Result<()> {
tokio::time::sleep(Duration::from_millis(500)).await;
println!("Thinking... current count: {}/{}", ctx.current, ctx.max);
Ok(())
}
}
struct GreetToolNode;
#[async_trait]
impl NodeTrait<CounterContext> for GreetToolNode {
async fn enter(&self, ctx: &mut CounterContext) -> Result<()> {
tokio::time::sleep(Duration::from_secs(1)).await;
ctx.current += 1;
println!("Hello! This is greeting number {}", ctx.current);
Ok(())
}
}
struct ExitNode;
#[async_trait]
impl NodeTrait<CounterContext> for ExitNode {
async fn enter(&self, _ctx: &mut CounterContext) -> Result<()> {
println!("Done! Exiting...");
Ok(())
}
}
#[tokio::main]
async fn main() -> Result<()> {
let mut engine = AgentEngine::builder(CounterContext { current: 0, max: 3 })
.with_node(AppNode::Thinking, ThinkingNode)
.with_node(AppNode::GreetTool, GreetToolNode)
.with_node(AppNode::Exit, ExitNode)
.with_transition(AppNode::Thinking, AppNode::GreetTool, |ctx| ctx.current < ctx.max)?
.with_transition(AppNode::Thinking, AppNode::Exit, |ctx| ctx.current >= ctx.max)?
.with_transition(AppNode::GreetTool, AppNode::Thinking, |_| true)?
.with_start_node(AppNode::Thinking)
.build()?;
engine.run().await?;
Ok(())
}