use std::future::Future;
use std::pin::Pin;
use tokio_util::sync::CancellationToken;
use crate::loop_types::AgentError;
use crate::message::AgentMessage;
pub struct BeforeToolCallContext {
pub tool_call_id: String,
pub tool_name: String,
pub args: serde_json::Value,
pub messages: Vec<AgentMessage>,
}
#[non_exhaustive]
pub enum BeforeToolCallResult {
Allow,
Deny { reason: String },
}
pub struct AfterToolCallContext {
pub tool_call_id: String,
pub tool_name: String,
pub result: crate::tool::ToolResult,
}
#[non_exhaustive]
pub enum AfterToolCallResult {
Keep,
Replace(crate::tool::ToolResult),
}
pub struct ShouldStopAfterTurnContext {
pub messages: Vec<AgentMessage>,
pub tool_results: Vec<opi_ai::message::ToolResultMessage>,
}
pub struct PrepareNextTurnContext {
pub messages: Vec<AgentMessage>,
pub turn: u32,
}
pub trait AgentHooks: Send + Sync {
fn convert_to_llm(
&self,
messages: &[AgentMessage],
) -> Result<Vec<opi_ai::message::Message>, AgentError>;
fn transform_context(
&self,
messages: Vec<AgentMessage>,
_signal: CancellationToken,
) -> Pin<Box<dyn Future<Output = Result<Vec<AgentMessage>, AgentError>> + Send>> {
Box::pin(async { Ok(messages) })
}
fn should_stop_after_turn(
&self,
_ctx: ShouldStopAfterTurnContext,
) -> Pin<Box<dyn Future<Output = bool> + Send>> {
Box::pin(async { false })
}
fn before_tool_call(
&self,
_ctx: BeforeToolCallContext,
) -> Pin<Box<dyn Future<Output = BeforeToolCallResult> + Send>> {
Box::pin(async { BeforeToolCallResult::Allow })
}
fn after_tool_call(
&self,
_ctx: AfterToolCallContext,
) -> Pin<Box<dyn Future<Output = AfterToolCallResult> + Send>> {
Box::pin(async { AfterToolCallResult::Keep })
}
fn prepare_next_turn(
&self,
_ctx: PrepareNextTurnContext,
) -> Pin<Box<dyn Future<Output = Option<crate::loop_types::AgentLoopTurnUpdate>> + Send>> {
Box::pin(async { None })
}
}