pub struct HookBus { /* private fields */ }Expand description
The central hook dispatcher.
Thread-safe: uses RwLock so multiple concurrent emitters can read
the handler list, and registration takes a write lock only briefly.
Implementations§
Source§impl HookBus
impl HookBus
Sourcepub async fn subscribe(
&self,
kind: HookKind,
handler: Arc<dyn ExtensionHandler>,
tool_filter: Option<String>,
matcher: Option<HookMatcher>,
permissions: PermissionSet,
) -> Result<(), String>
pub async fn subscribe( &self, kind: HookKind, handler: Arc<dyn ExtensionHandler>, tool_filter: Option<String>, matcher: Option<HookMatcher>, permissions: PermissionSet, ) -> Result<(), String>
Register a handler for a specific hook kind.
Returns an error if the handler’s permissions don’t allow subscribing to this hook kind.
Sourcepub async fn emit(&self, event: &HookEvent) -> HookResult
pub async fn emit(&self, event: &HookEvent) -> HookResult
Emit a hook event to all registered handlers.
Returns the first Block result if any handler blocks, otherwise
returns Continue. Handlers are called in registration order.
If no handlers are registered for this hook, returns immediately (the no-extensions fast path).
Sourcepub async fn emit_concurrent(&self, event: &HookEvent) -> HookResult
pub async fn emit_concurrent(&self, event: &HookEvent) -> HookResult
Emit a hook event to all registered handlers concurrently.
All handlers race under a single shared timeout (per_handler_timeout).
Results are collected and the first Block wins; injections are merged.
When to use this over emit():
Only safe for hook kinds whose handlers are order-independent — i.e. where no handler’s result depends on another’s execution. Currently that applies to:
on_session_end: onlyContinueis a valid result; handlers are fire-and-forget notification calls (deck, d20, jawz-widget, synaps-tasks all write to their own stores independently).
Do NOT use for before_tool_call / before_message hooks where
Block / Modify / Inject semantics require a defined winner when
two handlers disagree.
With N extensions and a 5 s per-handler timeout, serial emit takes up to N×5 s; concurrent emit collapses that to a single 5 s window regardless of N — critical for teardown budgets.
Sourcepub async fn unsubscribe_all(&self, extension_id: &str)
pub async fn unsubscribe_all(&self, extension_id: &str)
Remove all handlers for a given extension ID.
Sourcepub async fn handler_count(&self) -> usize
pub async fn handler_count(&self) -> usize
Number of registered handlers across all hooks.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for HookBus
impl !RefUnwindSafe for HookBus
impl !UnwindSafe for HookBus
impl Send for HookBus
impl Sync for HookBus
impl Unpin for HookBus
impl UnsafeUnpin for HookBus
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.