talos_plugin/handler.rs
1//! Hook handler traits and context.
2
3use std::path::PathBuf;
4use std::time::Duration;
5
6use async_trait::async_trait;
7
8use crate::event::{HookEvent, HookEventKind, TurnId};
9
10/// Shared context passed to every hook handler invocation.
11#[derive(Debug, Clone)]
12pub struct HookContext {
13 /// Current turn identifier.
14 pub turn_id: TurnId,
15 /// Workspace root associated with the agent.
16 pub workspace_root: PathBuf,
17}
18
19impl HookContext {
20 /// Creates a new hook context.
21 #[must_use]
22 pub fn new(turn_id: TurnId, workspace_root: PathBuf) -> Self {
23 Self {
24 turn_id,
25 workspace_root,
26 }
27 }
28}
29
30/// The outcome returned by an individual hook handler.
31#[derive(Debug)]
32pub enum HookResult {
33 /// Continue dispatching to the next subscribed handler.
34 Continue,
35 /// Stop dispatching and ask the caller to skip the wrapped action.
36 Skip,
37 /// Stop dispatching and deny the wrapped action.
38 Deny {
39 /// Human-readable denial reason.
40 reason: String,
41 },
42 /// Replace the current event and continue dispatching.
43 Modify(HookEvent<'static>),
44}
45
46/// A lifecycle hook handler.
47#[async_trait]
48pub trait HookHandler: Send + Sync {
49 /// Stable handler name used in logs and tests.
50 fn name(&self) -> &str;
51
52 /// Events this handler subscribes to.
53 fn subscribed(&self) -> &'static [HookEventKind];
54
55 /// Maximum time the framework will wait for `on_event`.
56 fn timeout(&self) -> Duration {
57 Duration::from_millis(500)
58 }
59
60 /// Handles a runtime event.
61 async fn on_event(&self, ctx: &HookContext, event: &mut HookEvent<'_>) -> HookResult;
62}