Download codex-rs/config/src/hook_config.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 8.23 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/config/src/hook_config.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/config/src/hook_config.rs
-
curl -L -o hook_config.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/config/src/hook_config.rs
8.23 kB
| use std::collections::BTreeMap; | |
| use std::path::Path; | |
| use std::path::PathBuf; | |
| use codex_protocol::protocol::HookEventName; | |
| use schemars::JsonSchema; | |
| use serde::Deserialize; | |
| use serde::Serialize; | |
| pub struct HooksFile { | |
| pub description: Option<String>, | |
| pub hooks: HookEventsToml, | |
| } | |
| pub struct HooksToml { | |
| pub events: HookEventsToml, | |
| pub state: BTreeMap<String, HookStateToml>, | |
| } | |
| pub struct HookStateToml { | |
| pub enabled: Option<bool>, | |
| pub trusted_hash: Option<String>, | |
| } | |
| pub struct HookEventsToml { | |
| pub pre_tool_use: Vec<MatcherGroup>, | |
| pub permission_request: Vec<MatcherGroup>, | |
| pub post_tool_use: Vec<MatcherGroup>, | |
| pub pre_compact: Vec<MatcherGroup>, | |
| pub post_compact: Vec<MatcherGroup>, | |
| pub session_start: Vec<MatcherGroup>, | |
| pub session_end: Vec<MatcherGroup>, | |
| pub user_prompt_submit: Vec<MatcherGroup>, | |
| pub subagent_start: Vec<MatcherGroup>, | |
| pub subagent_stop: Vec<MatcherGroup>, | |
| pub stop: Vec<MatcherGroup>, | |
| pub interrupt: Vec<MatcherGroup>, | |
| } | |
| impl HookEventsToml { | |
| pub fn is_empty(&self) -> bool { | |
| let Self { | |
| pre_tool_use, | |
| permission_request, | |
| post_tool_use, | |
| pre_compact, | |
| post_compact, | |
| session_start, | |
| session_end, | |
| user_prompt_submit, | |
| subagent_start, | |
| subagent_stop, | |
| stop, | |
| interrupt, | |
| } = self; | |
| pre_tool_use.is_empty() | |
| && permission_request.is_empty() | |
| && post_tool_use.is_empty() | |
| && pre_compact.is_empty() | |
| && post_compact.is_empty() | |
| && session_start.is_empty() | |
| && session_end.is_empty() | |
| && user_prompt_submit.is_empty() | |
| && subagent_start.is_empty() | |
| && subagent_stop.is_empty() | |
| && stop.is_empty() | |
| && interrupt.is_empty() | |
| } | |
| pub fn handler_count(&self) -> usize { | |
| let Self { | |
| pre_tool_use, | |
| permission_request, | |
| post_tool_use, | |
| pre_compact, | |
| post_compact, | |
| session_start, | |
| session_end, | |
| user_prompt_submit, | |
| subagent_start, | |
| subagent_stop, | |
| stop, | |
| interrupt, | |
| } = self; | |
| [ | |
| pre_tool_use, | |
| permission_request, | |
| post_tool_use, | |
| pre_compact, | |
| post_compact, | |
| session_start, | |
| session_end, | |
| user_prompt_submit, | |
| subagent_start, | |
| subagent_stop, | |
| stop, | |
| interrupt, | |
| ] | |
| .into_iter() | |
| .flatten() | |
| .map(|group| group.hooks.len()) | |
| .sum() | |
| } | |
| pub fn into_matcher_groups(mut self) -> [(HookEventName, Vec<MatcherGroup>); 12] { | |
| self.matcher_groups_mut() | |
| .map(|(event, groups)| (event, std::mem::take(groups))) | |
| } | |
| pub fn matcher_groups_mut(&mut self) -> [(HookEventName, &mut Vec<MatcherGroup>); 12] { | |
| use HookEventName as Event; | |
| [ | |
| (Event::PreToolUse, &mut self.pre_tool_use), | |
| (Event::PermissionRequest, &mut self.permission_request), | |
| (Event::PostToolUse, &mut self.post_tool_use), | |
| (Event::PreCompact, &mut self.pre_compact), | |
| (Event::PostCompact, &mut self.post_compact), | |
| (Event::SessionStart, &mut self.session_start), | |
| (Event::SessionEnd, &mut self.session_end), | |
| (Event::UserPromptSubmit, &mut self.user_prompt_submit), | |
| (Event::SubagentStart, &mut self.subagent_start), | |
| (Event::SubagentStop, &mut self.subagent_stop), | |
| (Event::Stop, &mut self.stop), | |
| (Event::Interrupt, &mut self.interrupt), | |
| ] | |
| } | |
| } | |
| pub struct MatcherGroup { | |
| pub matcher: Option<String>, | |
| pub hooks: Vec<HookHandlerConfig>, | |
| } | |
| pub enum HookHandlerConfig { | |
| Command { | |
| command: String, | |
| command_windows: Option<String>, | |
| timeout_sec: Option<u64>, | |
| r#async: bool, | |
| status_message: Option<String>, | |
| /// Approximate token threshold for spilling this hook's `additionalContext` to disk. | |
| /// Unset uses 2,500 tokens; `0` disables spilling for this hook. The threshold is | |
| /// evaluated against the original context; a spilled preview also includes recovery | |
| /// metadata. | |
| additional_context_limit: Option<usize>, | |
| }, | |
| McpTool { | |
| server: String, | |
| tool: String, | |
| input: serde_json::Map<String, serde_json::Value>, | |
| timeout_sec: Option<u64>, | |
| status_message: Option<String>, | |
| }, | |
| Prompt {}, | |
| Agent {}, | |
| } | |
| // Reject values such as null that cannot be represented in TOML for trust hashing. | |
| fn deserialize_mcp_tool_input<'de, D>( | |
| deserializer: D, | |
| ) -> Result<serde_json::Map<String, serde_json::Value>, D::Error> | |
| where | |
| D: serde::Deserializer<'de>, | |
| { | |
| let input = serde_json::Map::deserialize(deserializer)?; | |
| toml::Value::try_from(&input).map_err(|error| { | |
| serde::de::Error::custom(format!( | |
| "MCP hook input must be representable as TOML: {error}" | |
| )) | |
| })?; | |
| Ok(input) | |
| } | |
| pub struct ManagedHooksRequirementsToml { | |
| pub managed_dir: Option<PathBuf>, | |
| pub windows_managed_dir: Option<PathBuf>, | |
| pub hooks: HookEventsToml, | |
| } | |
| impl ManagedHooksRequirementsToml { | |
| pub fn is_empty(&self) -> bool { | |
| let Self { | |
| managed_dir, | |
| windows_managed_dir, | |
| hooks, | |
| } = self; | |
| managed_dir.is_none() && windows_managed_dir.is_none() && hooks.is_empty() | |
| } | |
| pub fn handler_count(&self) -> usize { | |
| self.hooks.handler_count() | |
| } | |
| pub fn managed_dir_for_current_platform(&self) -> Option<&Path> { | |
| { | |
| self.windows_managed_dir.as_deref() | |
| } | |
| { | |
| self.managed_dir.as_deref() | |
| } | |
| } | |
| } | |
| mod tests; | |