mirror of
https://github.com/openai/codex.git
synced 2026-05-15 16:53:05 +00:00
## Why Plugins can bundle lifecycle hooks, but Codex previously only discovered hooks from user, project, and managed config layers. This adds the plugin discovery and runtime plumbing needed for plugin-bundled hooks while keeping execution behind the `plugin_hooks` feature flag. ## What - Discovers plugin hook sources from each plugin's default `hooks/hooks.json`. - Supports `plugin.json` manifest `hooks` entries as either relative paths or inline hook objects. - Plumbs discovered plugin hook sources through plugin loading into the hook runtime when `plugin_hooks` is enabled. - Marks plugin-originated hook runs as `HookSource::Plugin`. - Injects `PLUGIN_ROOT` and `CLAUDE_PLUGIN_ROOT` into plugin hook command environments. - Updates generated schemas and hook source metadata for the plugin hook source. ## Stack 1. This PR - openai/codex#19705 2. openai/codex#19778 3. openai/codex#19840 4. openai/codex#19882 ## Reviewer Notes - Core logic is in `codex-rs/core-plugins/src/loader.rs` and `codex-rs/hooks/src/engine/discovery.rs` - Moved existing / adding new tests to `codex-rs/core-plugins/src/loader_tests.rs` hence the large diff there - Otherwise mostly plumbing and minor schema updates ### Core Changes The `codex-rs/core` changes are limited to wiring plugin hook support into existing core flows: - `core/src/session/session.rs` conditionally pulls effective plugin hook sources and plugin hook load warnings from `PluginsManager` when `plugin_hooks` is enabled, then passes them into `HooksConfig`. - `core/src/hook_runtime.rs` adds the `plugin` metric tag for `HookSource::Plugin`. - `core/config.schema.json` picks up the new `plugin_hooks` feature flag, and `core/src/plugins/manager_tests.rs` updates fixtures for the added plugin hook fields. --------- Co-authored-by: Codex <noreply@openai.com>
67 lines
1.9 KiB
Rust
67 lines
1.9 KiB
Rust
//! Shared plugin identifiers and telemetry-facing summaries.
|
|
|
|
pub use codex_utils_plugins::mention_syntax;
|
|
pub use codex_utils_plugins::plugin_namespace_for_skill_path;
|
|
|
|
mod load_outcome;
|
|
mod plugin_id;
|
|
|
|
use codex_config::HookEventsToml;
|
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
|
pub use load_outcome::EffectiveSkillRoots;
|
|
pub use load_outcome::LoadedPlugin;
|
|
pub use load_outcome::PluginLoadOutcome;
|
|
pub use load_outcome::prompt_safe_plugin_description;
|
|
pub use plugin_id::PluginId;
|
|
pub use plugin_id::PluginIdError;
|
|
pub use plugin_id::validate_plugin_segment;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub struct AppConnectorId(pub String);
|
|
|
|
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
|
pub struct PluginCapabilitySummary {
|
|
pub config_name: String,
|
|
pub display_name: String,
|
|
pub description: Option<String>,
|
|
pub has_skills: bool,
|
|
pub mcp_server_names: Vec<String>,
|
|
pub app_connector_ids: Vec<AppConnectorId>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct PluginHookSource {
|
|
pub plugin_id: PluginId,
|
|
pub plugin_root: AbsolutePathBuf,
|
|
pub plugin_data_root: AbsolutePathBuf,
|
|
pub source_path: AbsolutePathBuf,
|
|
pub source_relative_path: String,
|
|
pub hooks: HookEventsToml,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct PluginTelemetryMetadata {
|
|
pub plugin_id: PluginId,
|
|
pub capability_summary: Option<PluginCapabilitySummary>,
|
|
}
|
|
|
|
impl PluginTelemetryMetadata {
|
|
pub fn from_plugin_id(plugin_id: &PluginId) -> Self {
|
|
Self {
|
|
plugin_id: plugin_id.clone(),
|
|
capability_summary: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PluginCapabilitySummary {
|
|
pub fn telemetry_metadata(&self) -> Option<PluginTelemetryMetadata> {
|
|
PluginId::parse(&self.config_name)
|
|
.ok()
|
|
.map(|plugin_id| PluginTelemetryMetadata {
|
|
plugin_id,
|
|
capability_summary: Some(self.clone()),
|
|
})
|
|
}
|
|
}
|