mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
## What changed - Add `environment_hooks` to `EnvironmentConfig` for hooks from an environment's effective managed requirements. Initialize it empty for inferred thread configurations and report the handler count in debug output. - Move `HookEventsToml`, `MatcherGroup`, and `HookHandlerConfig` into `codex_protocol::hooks`, with re-exports from `codex_config::hook_config`. - Validate MCP hook input recursively to reject nulls and integers outside the signed 64-bit range without converting through `toml::Value`. GitOrigin-RevId: 410506c8e2b89c9519c81d86b44ccd760d751693
78 lines
2.2 KiB
Rust
78 lines
2.2 KiB
Rust
use std::collections::BTreeMap;
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
|
|
pub use codex_protocol::hooks::HookEventsToml;
|
|
pub use codex_protocol::hooks::HookHandlerConfig;
|
|
pub use codex_protocol::hooks::MatcherGroup;
|
|
use schemars::JsonSchema;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
|
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct HooksFile {
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub description: Option<String>,
|
|
#[serde(default)]
|
|
pub hooks: HookEventsToml,
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
|
pub struct HooksToml {
|
|
#[serde(flatten)]
|
|
pub events: HookEventsToml,
|
|
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
|
|
pub state: BTreeMap<String, HookStateToml>,
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
|
pub struct HookStateToml {
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub enabled: Option<bool>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub trusted_hash: Option<String>,
|
|
/// Approved plugin contents; kept separate for declaration-only clients.
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub trusted_content_hash: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct ManagedHooksRequirementsToml {
|
|
pub managed_dir: Option<PathBuf>,
|
|
pub windows_managed_dir: Option<PathBuf>,
|
|
#[serde(flatten)]
|
|
pub hooks: Box<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> {
|
|
#[cfg(windows)]
|
|
{
|
|
self.windows_managed_dir.as_deref()
|
|
}
|
|
|
|
#[cfg(not(windows))]
|
|
{
|
|
self.managed_dir.as_deref()
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "hooks_tests.rs"]
|
|
mod tests;
|