mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
ff50b47dce
## Why Plugin analytics overloaded `plugin_id`: most events used the Codex `<plugin>@<marketplace>` identity, while remote install events used the backend plugin ID. That makes the same field change meaning across event types and complicates downstream identity resolution. This change makes the contract unambiguous: - `plugin_id`: the local Codex `<plugin>@<marketplace>` identity, when resolved - `remote_plugin_id`: the backend plugin identity, when available For a remote install failure that happens before plugin details resolve, `plugin_id` is `null` and `remote_plugin_id` remains populated. ## What changed All six plugin analytics events use the same identity contract: - `codex_plugin_installed` - `codex_plugin_install_failed` - `codex_plugin_uninstalled` - `codex_plugin_enabled` - `codex_plugin_disabled` - `codex_plugin_used` Remote identity is resolved from the current installed-plugin snapshot first, with persisted install metadata as fallback. The telemetry metadata type keeps local identity optional for failures that occur before remote details are available. The app-server test client's manual analytics smokes now find remote mutation events through `remote_plugin_id` and validate that `plugin_id` remains local. ## Remote uninstall Resolve and capture telemetry metadata before removing the local plugin cache, then emit `codex_plugin_uninstalled` after the backend confirms success. The event is also emitted when backend uninstall succeeds but local cache cleanup reports `CacheRemove`. If a concurrent remote-cache refresh removes the local bundle before telemetry capture, the already-fetched remote plugin detail supplies fallback capability metadata. ## Validation - `just test -p codex-analytics` — 82 passed - `just test -p codex-core-plugins` — 271 passed - `just test -p codex-app-server-test-client` — 5 passed - `just test -p codex-plugin` — 3 passed - `just test -p codex-app-server plugin_install` — 37 passed - `just test -p codex-app-server plugin_uninstall` — 10 passed The production app-server install/uninstall flow was also exercised against `plugins~Plugin_f1b845ac33888191ac156169c58733c2` (`build-ios-apps@openai-curated-remote`), and the plugin's original uninstalled state was restored.
80 lines
2.4 KiB
Rust
80 lines
2.4 KiB
Rust
//! Shared plugin package models, source providers, identifiers, and telemetry summaries.
|
|
|
|
use std::collections::HashSet;
|
|
|
|
pub use codex_utils_plugins::mention_syntax;
|
|
pub use codex_utils_plugins::plugin_namespace_for_skill_path;
|
|
|
|
mod load_outcome;
|
|
pub mod manifest;
|
|
mod plugin_id;
|
|
mod provider;
|
|
|
|
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;
|
|
pub use provider::PluginProvider;
|
|
pub use provider::PluginResourceLocator;
|
|
pub use provider::ResolvedPlugin;
|
|
pub use provider::ResolvedPluginError;
|
|
pub use provider::ResolvedPluginLocation;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub struct AppConnectorId(pub String);
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct AppDeclaration {
|
|
pub name: String,
|
|
pub connector_id: AppConnectorId,
|
|
pub category: Option<String>,
|
|
}
|
|
|
|
pub fn app_connector_ids_from_declarations<'a>(
|
|
app_declarations: impl IntoIterator<Item = &'a AppDeclaration>,
|
|
) -> Vec<AppConnectorId> {
|
|
let mut connector_ids = Vec::new();
|
|
let mut seen_connector_ids = HashSet::new();
|
|
for app in app_declarations {
|
|
if seen_connector_ids.insert(&app.connector_id) {
|
|
connector_ids.push(app.connector_id.clone());
|
|
}
|
|
}
|
|
connector_ids
|
|
}
|
|
|
|
#[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 {
|
|
/// Local plugin identifier used by Codex configuration and the plugin cache,
|
|
/// when it has been resolved.
|
|
pub plugin_id: Option<PluginId>,
|
|
/// Optional backend identifier for remote plugins.
|
|
pub remote_plugin_id: Option<String>,
|
|
pub capability_summary: Option<PluginCapabilitySummary>,
|
|
}
|