| 1 | //! Lifecycle hooks for the Codewhale **TUI runtime**. |
| 2 | //! |
| 3 | //! Scope, stated plainly: every firing point in this system lives in the |
| 4 | //! interactive TUI (`crates/tui/src/tui/`) and the engine turn loop it drives. |
| 5 | //! `codewhale exec`, the CLI dispatcher, the app-server / ACP surfaces, and |
| 6 | //! the workflow tool do not fire these hooks. The unrelated `crates/hooks` |
| 7 | //! event-sink crate is a different mechanism and shares no configuration. |
| 8 | //! |
| 9 | //! Hooks execute user-defined shell commands at: |
| 10 | //! - Session start/end |
| 11 | //! - Tool call before/after |
| 12 | //! - Mode changes |
| 13 | //! - Message submission |
| 14 | //! - Error events |
| 15 | //! - Turn completion |
| 16 | //! - Sub-agent spawn/completion |
| 17 | //! - `exec_shell` environment collection |
| 18 | //! |
| 19 | //! Configuration is done via `[[hooks.hooks]]` in config.toml. See |
| 20 | //! `docs/HOOKS.md` for the per-event contract. |
| 21 | |
| 22 | mod config; |
| 23 | mod executor; |
| 24 | |
| 25 | #[cfg(test)] |
| 26 | pub use config::ALL_HOOK_EVENTS; |
| 27 | #[allow(unused_imports)] |
| 28 | pub use config::{Hook, HookCondition, HookConfigProblem, HookEvent, HookSteering, HooksConfig}; |
| 29 | pub(crate) use executor::{ |
| 30 | HOOK_CONTEXT_AGGREGATE_MAX_CHARS, HOOK_LABEL_MAX_CHARS, generic_unavailable_detail, |
| 31 | parse_tool_call_before_stdout, sanitize_hook_denial_reason, sanitize_hook_label, |
| 32 | sanitize_hook_line, sanitize_hook_text, |
| 33 | }; |
| 34 | #[cfg(test)] |
| 35 | pub(crate) use executor::{ |
| 36 | HOOK_MESSAGE_SUBMIT_PAYLOAD_MAX_BYTES, HOOK_TEXT_FIELD_MAX_CHARS, message_submit_payload, |
| 37 | }; |
| 38 | #[allow(unused_imports)] |
| 39 | pub use executor::{ |
| 40 | HookContext, HookExecutor, HookResult, MessageSubmitOutcome, ToolCallBeforeStdout, |
| 41 | ToolCallDecision, TurnEndPayloadInput, TurnEndTotals, turn_end_payload, |
| 42 | }; |
| 43 |