a3s_code_core/hooks/
binding.rs1use std::fmt;
2use std::sync::Arc;
3
4use super::{Hook, HookEventType, HookHandler};
5
6pub struct HookBinding {
11 hook: Arc<Hook>,
12 handler: Arc<dyn HookHandler>,
13}
14
15impl HookBinding {
16 pub fn new(hook: Hook, handler: Arc<dyn HookHandler>) -> Self {
17 Self {
18 hook: Arc::new(hook),
19 handler,
20 }
21 }
22
23 pub fn hook(&self) -> &Hook {
24 &self.hook
25 }
26
27 pub fn handler(&self) -> &dyn HookHandler {
28 self.handler.as_ref()
29 }
30
31 pub(crate) fn hook_arc(&self) -> &Arc<Hook> {
32 &self.hook
33 }
34
35 pub(crate) fn handler_arc(&self) -> &Arc<dyn HookHandler> {
36 &self.handler
37 }
38
39 pub(crate) fn validate_run_scope(&self) -> Result<(), &'static str> {
40 match self.hook.event_type {
41 HookEventType::SessionStart | HookEventType::SessionEnd => {
42 Err("Session lifecycle Hook events are outside Run-scoped capability projection")
43 }
44 HookEventType::SkillLoad | HookEventType::SkillUnload => {
45 Err("Skill lifecycle Hook events have no Run-scoped production emitter")
46 }
47 _ => Ok(()),
48 }
49 }
50}
51
52impl fmt::Debug for HookBinding {
53 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
54 formatter
55 .debug_struct("HookBinding")
56 .field("hook", &self.hook)
57 .finish_non_exhaustive()
58 }
59}