use std::{fmt, future::Future, pin::Pin, sync::Arc};
use crate::{services::llm::models::chat::ChatResponse, Agent, AgentError, Message};
pub type InvokeFn = for<'a> fn(&'a mut Agent, String) -> InvokeFuture<'a>;
pub type InvokeFuture<'a> = Pin<Box<dyn Future<Output = Result<ChatResponse, AgentError>> + Send + 'a>>;
pub type CustomFlowFn = for<'a> fn(&'a mut Agent, String) -> FlowFuture<'a>;
pub type ClosureFlowFn = Arc<dyn for<'a> Fn(&'a mut Agent, String) -> FlowFuture<'a> + Send + Sync>;
pub type FlowFn = Arc<dyn for<'a> Fn(&'a mut Agent, String) -> FlowFuture<'a> + Send + Sync>;
pub type FlowFuture<'a> = Pin<Box<dyn Future<Output = Result<Message, AgentError>> + Send + 'a>>;
#[derive(Clone)]
pub enum Flow {
Default,
Custom(CustomFlowFn),
CustomClosure(ClosureFlowFn),
}
impl Flow {
pub fn new_closure<F>(f: F) -> Self
where
F: for<'a> Fn(&'a mut Agent, String) -> FlowFuture<'a> + Send + Sync + 'static,
{
let flow_fn = Arc::new(f);
Flow::CustomClosure(flow_fn)
}
}
#[derive(Clone)]
pub(crate) enum InternalFlow {
Default,
Custom(FlowFn),
}
impl From<Flow> for InternalFlow {
fn from(flow: Flow) -> Self {
match flow {
Flow::Default => InternalFlow::Default,
Flow::Custom(custom_fn_ptr) => {
InternalFlow::Custom(Arc::new(custom_fn_ptr))
}
Flow::CustomClosure(flow_fn) => InternalFlow::Custom(flow_fn),
}
}
}
impl fmt::Debug for InternalFlow {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InternalFlow::Default => f.write_str("InternalFlow::Default"),
InternalFlow::Custom(_) => f.write_str("InternalFlow::Custom(<flow_fn>)"),
}
}
}
impl fmt::Debug for Flow {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Flow::Default => write!(f, "Simple"),
Flow::Custom(func_ptr) => f.debug_tuple("Custom").field(func_ptr).finish(),
Flow::CustomClosure(_) => write!(f, "CustomClosure(<closure>)"),
}
}
}