use crate::command::NodeOutput;
use crate::config::GraphConfig;
use crate::error::Result;
use crate::state::AgentState;
use async_trait::async_trait;
use std::future::Future;
use std::pin::Pin;
#[async_trait]
pub trait Node: Send + Sync {
async fn execute(&self, state: &AgentState, config: &GraphConfig) -> Result<NodeOutput>;
fn name(&self) -> Option<&str> {
None
}
}
pub struct FnNode<F>
where
F: Fn(&AgentState, &GraphConfig) -> Pin<Box<dyn Future<Output = Result<NodeOutput>> + Send>>
+ Send
+ Sync,
{
func: F,
name: Option<String>,
}
impl<F> FnNode<F>
where
F: Fn(&AgentState, &GraphConfig) -> Pin<Box<dyn Future<Output = Result<NodeOutput>> + Send>>
+ Send
+ Sync,
{
pub fn new(func: F) -> Self {
Self { func, name: None }
}
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
}
#[async_trait]
impl<F> Node for FnNode<F>
where
F: Fn(&AgentState, &GraphConfig) -> Pin<Box<dyn Future<Output = Result<NodeOutput>> + Send>>
+ Send
+ Sync,
{
async fn execute(&self, state: &AgentState, config: &GraphConfig) -> Result<NodeOutput> {
(self.func)(state, config).await
}
fn name(&self) -> Option<&str> {
self.name.as_deref()
}
}
#[macro_export]
macro_rules! node {
(|$state:ident| async move $body:block) => {
Box::new($crate::node::FnNode::new(
|__state: &$crate::state::AgentState, __config: &$crate::config::GraphConfig| {
let $state = __state.clone();
let _ = __config;
Box::pin(async move {
let __result = (|| async move { $body })().await;
__result.map(::std::convert::Into::into)
})
},
))
};
($name:expr, |$state:ident| async move $body:block) => {
Box::new(
$crate::node::FnNode::new(
|__state: &$crate::state::AgentState, __config: &$crate::config::GraphConfig| {
let $state = __state.clone();
let _ = __config;
Box::pin(async move {
let __result = (|| async move { $body })().await;
__result.map(::std::convert::Into::into)
})
},
)
.with_name($name),
)
};
(|$state:ident, $config:ident| async move $body:block) => {
Box::new($crate::node::FnNode::new(
|__state: &$crate::state::AgentState, __config: &$crate::config::GraphConfig| {
let $state = __state.clone();
let $config = __config.clone();
Box::pin(async move {
let __result = (|| async move { $body })().await;
__result.map(::std::convert::Into::into)
})
},
))
};
($name:expr, |$state:ident, $config:ident| async move $body:block) => {
Box::new(
$crate::node::FnNode::new(
|__state: &$crate::state::AgentState, __config: &$crate::config::GraphConfig| {
let $state = __state.clone();
let $config = __config.clone();
Box::pin(async move {
let __result = (|| async move { $body })().await;
__result.map(::std::convert::Into::into)
})
},
)
.with_name($name),
)
};
}