Skip to main content

systemprompt_models/
hooks.rs

1//! Hook vocabulary: lifecycle events and categories.
2//!
3//! [`HookEvent`] enumerates the agent lifecycle points a hook can bind to and
4//! [`HookCategory`] separates platform hooks from custom ones. Both travel in
5//! the signed bridge manifest, so they live beside the other runtime models.
6//!
7//! Copyright (c) systemprompt.io — Business Source License 1.1.
8//! See <https://systemprompt.io> for licensing details.
9
10use std::fmt;
11use std::str::FromStr;
12
13use serde::{Deserialize, Serialize};
14
15use crate::errors::ParseEnumError;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
18#[serde(rename_all = "PascalCase")]
19pub enum HookEvent {
20    PreToolUse,
21    PostToolUse,
22    PostToolUseFailure,
23    SessionStart,
24    SessionEnd,
25    UserPromptSubmit,
26    Notification,
27    Stop,
28    SubagentStart,
29    SubagentStop,
30}
31
32impl HookEvent {
33    pub const ALL_VARIANTS: &'static [Self] = &[
34        Self::PreToolUse,
35        Self::PostToolUse,
36        Self::PostToolUseFailure,
37        Self::SessionStart,
38        Self::SessionEnd,
39        Self::UserPromptSubmit,
40        Self::Notification,
41        Self::Stop,
42        Self::SubagentStart,
43        Self::SubagentStop,
44    ];
45
46    pub const fn as_str(&self) -> &'static str {
47        match self {
48            Self::PreToolUse => "PreToolUse",
49            Self::PostToolUse => "PostToolUse",
50            Self::PostToolUseFailure => "PostToolUseFailure",
51            Self::SessionStart => "SessionStart",
52            Self::SessionEnd => "SessionEnd",
53            Self::UserPromptSubmit => "UserPromptSubmit",
54            Self::Notification => "Notification",
55            Self::Stop => "Stop",
56            Self::SubagentStart => "SubagentStart",
57            Self::SubagentStop => "SubagentStop",
58        }
59    }
60}
61
62impl fmt::Display for HookEvent {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        write!(f, "{}", self.as_str())
65    }
66}
67
68impl FromStr for HookEvent {
69    type Err = ParseEnumError;
70
71    fn from_str(s: &str) -> Result<Self, Self::Err> {
72        match s {
73            "PreToolUse" => Ok(Self::PreToolUse),
74            "PostToolUse" => Ok(Self::PostToolUse),
75            "PostToolUseFailure" => Ok(Self::PostToolUseFailure),
76            "SessionStart" => Ok(Self::SessionStart),
77            "SessionEnd" => Ok(Self::SessionEnd),
78            "UserPromptSubmit" => Ok(Self::UserPromptSubmit),
79            "Notification" => Ok(Self::Notification),
80            "Stop" => Ok(Self::Stop),
81            "SubagentStart" => Ok(Self::SubagentStart),
82            "SubagentStop" => Ok(Self::SubagentStop),
83            _ => Err(ParseEnumError::new("hook_event", s)),
84        }
85    }
86}
87
88#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
89#[serde(rename_all = "lowercase")]
90pub enum HookCategory {
91    System,
92    #[default]
93    Custom,
94}
95
96impl HookCategory {
97    pub const fn as_str(&self) -> &'static str {
98        match self {
99            Self::System => "system",
100            Self::Custom => "custom",
101        }
102    }
103}
104
105impl fmt::Display for HookCategory {
106    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107        write!(f, "{}", self.as_str())
108    }
109}
110
111impl FromStr for HookCategory {
112    type Err = ParseEnumError;
113
114    fn from_str(s: &str) -> Result<Self, Self::Err> {
115        match s {
116            "system" => Ok(Self::System),
117            "custom" => Ok(Self::Custom),
118            _ => Err(ParseEnumError::new("hook_category", s)),
119        }
120    }
121}