mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Add persisted hook enablement state (#19840)
## Why After `hooks/list` exposes the hook inventory, clients need a way to persist user hook preferences, make those changes effective in already-open sessions, and distinguish user-controllable hooks from managed requirements without adding another bespoke app-server write API. ## What - Extends `hooks/list` entries with effective `enabled` state. - Persists user-level hook state under `hooks.state.<hook-id>` so the model can grow beyond a single boolean over time. - Uses the existing `config/batchWrite` path for hook state updates instead of introducing a dedicated hook write RPC. - Refreshes live session hook engines after config writes so already-open threads observe updated enablement without a restart. ## Stack 1. openai/codex#19705 2. openai/codex#19778 3. This PR - openai/codex#19840 4. openai/codex#19882 ## Reviewer Notes The generated schema files account for much of the raw diff. The core behavior is in: - `hooks/src/config_rules.rs`, which resolves per-hook user state from the config layer stack. - `hooks/src/engine/discovery.rs`, which projects effective enablement into `hooks/list` from source-derived managedness. - `config/src/hook_config.rs`, which defines the new `hooks.state` representation. - `core/src/session/mod.rs`, which rebuilds live hook state after user config reloads. --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
@@ -1571,12 +1571,28 @@ pub enum HookSource {
|
||||
Mdm,
|
||||
SessionFlags,
|
||||
Plugin,
|
||||
CloudRequirements,
|
||||
LegacyManagedConfigFile,
|
||||
LegacyManagedConfigMdm,
|
||||
#[default]
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl HookSource {
|
||||
/// Returns whether hooks from this source are managed and therefore not
|
||||
/// user-configurable.
|
||||
pub fn is_managed(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::System
|
||||
| Self::Mdm
|
||||
| Self::CloudRequirements
|
||||
| Self::LegacyManagedConfigFile
|
||||
| Self::LegacyManagedConfigMdm
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum HookRunStatus {
|
||||
@@ -3991,6 +4007,20 @@ mod tests {
|
||||
use tempfile::NamedTempFile;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
fn hook_source_managedness_is_source_derived() {
|
||||
assert_eq!(HookSource::System.is_managed(), true);
|
||||
assert_eq!(HookSource::Mdm.is_managed(), true);
|
||||
assert_eq!(HookSource::CloudRequirements.is_managed(), true);
|
||||
assert_eq!(HookSource::LegacyManagedConfigFile.is_managed(), true);
|
||||
assert_eq!(HookSource::LegacyManagedConfigMdm.is_managed(), true);
|
||||
assert_eq!(HookSource::User.is_managed(), false);
|
||||
assert_eq!(HookSource::Project.is_managed(), false);
|
||||
assert_eq!(HookSource::SessionFlags.is_managed(), false);
|
||||
assert_eq!(HookSource::Plugin.is_managed(), false);
|
||||
assert_eq!(HookSource::Unknown.is_managed(), false);
|
||||
}
|
||||
|
||||
fn sorted_writable_roots(roots: Vec<WritableRoot>) -> Vec<(PathBuf, Vec<PathBuf>)> {
|
||||
let mut sorted_roots: Vec<(PathBuf, Vec<PathBuf>)> = roots
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user