use std::future::Future;
use std::pin::Pin;
use crate::error::{DaimonError, Result};
use crate::model::types::ChatResponse;
use crate::tool::{ToolCall, ToolOutput};
pub struct AgentState {
pub iteration: usize,
pub max_iterations: usize,
}
pub trait AgentHook: Send + Sync {
fn on_iteration_start(&self, _state: &AgentState) -> impl Future<Output = Result<()>> + Send {
async { Ok(()) }
}
fn on_model_response(
&self,
_response: &ChatResponse,
) -> impl Future<Output = Result<()>> + Send {
async { Ok(()) }
}
fn on_tool_call(&self, _call: &ToolCall) -> impl Future<Output = Result<()>> + Send {
async { Ok(()) }
}
fn on_tool_result(
&self,
_call: &ToolCall,
_result: &ToolOutput,
) -> impl Future<Output = Result<()>> + Send {
async { Ok(()) }
}
fn on_iteration_end(&self, _state: &AgentState) -> impl Future<Output = Result<()>> + Send {
async { Ok(()) }
}
fn on_error(&self, _error: &DaimonError) -> impl Future<Output = Result<()>> + Send {
async { Ok(()) }
}
}
pub trait ErasedAgentHook: Send + Sync {
fn on_iteration_start_erased<'a>(
&'a self,
state: &'a AgentState,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
fn on_model_response_erased<'a>(
&'a self,
response: &'a ChatResponse,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
fn on_tool_call_erased<'a>(
&'a self,
call: &'a ToolCall,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
fn on_tool_result_erased<'a>(
&'a self,
call: &'a ToolCall,
result: &'a ToolOutput,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
fn on_iteration_end_erased<'a>(
&'a self,
state: &'a AgentState,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
fn on_error_erased<'a>(
&'a self,
error: &'a DaimonError,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
}
impl<T: AgentHook> ErasedAgentHook for T {
fn on_iteration_start_erased<'a>(
&'a self,
state: &'a AgentState,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(self.on_iteration_start(state))
}
fn on_model_response_erased<'a>(
&'a self,
response: &'a ChatResponse,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(self.on_model_response(response))
}
fn on_tool_call_erased<'a>(
&'a self,
call: &'a ToolCall,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(self.on_tool_call(call))
}
fn on_tool_result_erased<'a>(
&'a self,
call: &'a ToolCall,
result: &'a ToolOutput,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(self.on_tool_result(call, result))
}
fn on_iteration_end_erased<'a>(
&'a self,
state: &'a AgentState,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(self.on_iteration_end(state))
}
fn on_error_erased<'a>(
&'a self,
error: &'a DaimonError,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
Box::pin(self.on_error(error))
}
}
pub struct NoOpHook;
impl AgentHook for NoOpHook {}