#[derive(Clone, Default)]
pub struct Hooks {
pub pre_tool_use: Vec<PreToolUseHandler>,
pub post_tool_use: Vec<PostToolUseHandler>,
pub user_prompt_submit: Vec<UserPromptSubmitHandler>,
}
impl Hooks {
pub fn new() -> Self {
Self::default()
}
pub fn add_pre_tool_use<F, Fut>(mut self, handler: F) -> Self
where
F: Fn(PreToolUseEvent) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Option<HookDecision>> + Send + 'static,
{
self.pre_tool_use
.push(Arc::new(move |event| Box::pin(handler(event))));
self
}
pub fn add_post_tool_use<F, Fut>(mut self, handler: F) -> Self
where
F: Fn(PostToolUseEvent) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Option<HookDecision>> + Send + 'static,
{
self.post_tool_use
.push(Arc::new(move |event| Box::pin(handler(event))));
self
}
pub fn add_user_prompt_submit<F, Fut>(mut self, handler: F) -> Self
where
F: Fn(UserPromptSubmitEvent) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Option<HookDecision>> + Send + 'static,
{
self.user_prompt_submit
.push(Arc::new(move |event| Box::pin(handler(event))));
self
}
pub async fn execute_pre_tool_use(&self, event: PreToolUseEvent) -> Option<HookDecision> {
let (last, preceding) = self.pre_tool_use.split_last()?;
for handler in preceding {
let decision = handler(event.clone()).await;
if decision.is_some() {
return decision;
}
}
last(event).await
}
pub async fn execute_post_tool_use(&self, event: PostToolUseEvent) -> Option<HookDecision> {
let (last, preceding) = self.post_tool_use.split_last()?;
for handler in preceding {
let decision = handler(event.clone()).await;
if decision.is_some() {
return decision;
}
}
last(event).await
}
pub async fn execute_user_prompt_submit(
&self,
event: UserPromptSubmitEvent,
) -> Option<HookDecision> {
let (last, preceding) = self.user_prompt_submit.split_last()?;
for handler in preceding {
let decision = handler(event.clone()).await;
if decision.is_some() {
return decision;
}
}
last(event).await
}
}
impl std::fmt::Debug for Hooks {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Hooks")
.field(
"pre_tool_use",
&format!("{} handlers", self.pre_tool_use.len()),
)
.field(
"post_tool_use",
&format!("{} handlers", self.post_tool_use.len()),
)
.field(
"user_prompt_submit",
&format!("{} handlers", self.user_prompt_submit.len()),
)
.finish()
}
}
pub const HOOK_PRE_TOOL_USE: &str = "pre_tool_use";
pub const HOOK_POST_TOOL_USE: &str = "post_tool_use";
pub const HOOK_USER_PROMPT_SUBMIT: &str = "user_prompt_submit";