mirror of
https://github.com/openai/codex.git
synced 2026-11-06 08:31:30 +00:00
Attribute executor skill invocations to plugins (#39309)
## What changed - Carry selected plugin identities from MCP discovery into per-turn extension data, limited to capability roots that are ready for the turn. - Annotate executor skill catalog entries with the matching plugin ID and `user` scope. - Include that attribution in `skill_invocation` analytics for both explicit and implicit executor skill invocations. ## Testing - Extend the executor skills app-server test to verify plugin ID, skill scope, and invocation type for explicit and implicit analytics events. GitOrigin-RevId: 9345600ae29bcb8eb894fffd2d6f7b05f22ebf74
This commit is contained in:
1 parent
c97bd2dcb5
commit
280d56b1d8
17 files changed
+129
-18
No files matched your search
@@ -13,6 +13,8 @@ use codex_extension_api::ExtensionDataInit;
|
||||
use codex_extension_api::ExtensionRegistry;
|
||||
use codex_extension_api::McpServerContribution;
|
||||
use codex_extension_api::McpServerContributionContext;
|
||||
use codex_extension_api::SelectedPluginIdentity;
|
||||
use codex_extension_api::SelectedPluginSnapshot;
|
||||
use codex_login::CodexAuth;
|
||||
use codex_mcp::CODEX_APPS_MCP_SERVER_NAME;
|
||||
use codex_mcp::EffectiveMcpServer;
|
||||
@@ -35,6 +37,7 @@ const LEGACY_CODEX_APPS_REGISTRATION_ID: &str = "legacy_codex_apps";
|
||||
pub(crate) struct McpRuntimeProjection {
|
||||
pub(crate) config: McpConfig,
|
||||
pub(crate) plugins_available: bool,
|
||||
pub(crate) selected_plugins: SelectedPluginSnapshot,
|
||||
}
|
||||
|
||||
pub(crate) struct McpThreadIdentity<'a> {
|
||||
@@ -143,6 +146,7 @@ impl McpManager {
|
||||
let mut selected_plugin_available = false;
|
||||
let mut selected_plugin_connector_sources = Vec::new();
|
||||
let mut selected_plugin_registrations = Vec::new();
|
||||
let mut selected_plugins = Vec::new();
|
||||
let mut overlays = Vec::new();
|
||||
// A contributor can emit multiple ordered actions, so order each action globally rather
|
||||
// than enumerating contributors.
|
||||
@@ -173,11 +177,16 @@ impl McpManager {
|
||||
),
|
||||
),
|
||||
McpServerContribution::SelectedPluginPackage {
|
||||
selected_root_id,
|
||||
plugin_id,
|
||||
plugin_display_name,
|
||||
connector_ids,
|
||||
} => {
|
||||
selected_plugin_available = true;
|
||||
selected_plugins.push(SelectedPluginIdentity {
|
||||
selected_root_id,
|
||||
plugin_id: plugin_id.clone(),
|
||||
});
|
||||
if !connector_ids.is_empty() {
|
||||
selected_plugin_connector_sources.push(
|
||||
PluginConnectorSource::from_connector_ids(
|
||||
@@ -265,6 +274,9 @@ impl McpManager {
|
||||
McpRuntimeProjection {
|
||||
config: mcp_config,
|
||||
plugins_available,
|
||||
selected_plugins: SelectedPluginSnapshot {
|
||||
plugins: selected_plugins,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,6 +259,7 @@ impl Session {
|
||||
executor_capability_discovery.as_deref(),
|
||||
)
|
||||
.await;
|
||||
let selected_plugins = mcp_projection.selected_plugins.clone();
|
||||
let input = self.build_mcp_runtime_input(
|
||||
&desired,
|
||||
mcp_projection,
|
||||
@@ -269,7 +270,9 @@ impl Session {
|
||||
input.mcp_servers.contains_key(CODEX_APPS_MCP_SERVER_NAME),
|
||||
"unknown MCP server '{CODEX_APPS_MCP_SERVER_NAME}'"
|
||||
);
|
||||
self.services.mcp_runtime.replace_fresh(input).await
|
||||
let refreshed = self.services.mcp_runtime.replace_fresh(input).await;
|
||||
self.services.thread_extension_data.insert(selected_plugins);
|
||||
refreshed
|
||||
}
|
||||
|
||||
pub(super) fn mark_mcp_runtime_dirty(&self) {
|
||||
|
||||
@@ -141,6 +141,7 @@ impl Session {
|
||||
ready_selected_capability_roots: &[SelectedCapabilityRoot],
|
||||
elicitation_reviewer: Option<ElicitationReviewerHandle>,
|
||||
) {
|
||||
let selected_plugins = mcp_projection.selected_plugins.clone();
|
||||
let input = self.build_mcp_runtime_input(
|
||||
desired,
|
||||
mcp_projection,
|
||||
@@ -148,6 +149,7 @@ impl Session {
|
||||
elicitation_reviewer,
|
||||
);
|
||||
self.services.mcp_runtime.replace(input).await;
|
||||
self.services.thread_extension_data.insert(selected_plugins);
|
||||
}
|
||||
|
||||
pub(super) fn build_mcp_runtime_input(
|
||||
@@ -161,6 +163,7 @@ impl Session {
|
||||
let McpRuntimeProjection {
|
||||
mut config,
|
||||
plugins_available,
|
||||
selected_plugins: _,
|
||||
} = mcp_projection;
|
||||
config.approval_policy = desired.config.permissions.approval_policy.clone();
|
||||
config.permission_profile = desired.config.permissions.effective_permission_profile();
|
||||
|
||||
@@ -3193,6 +3193,19 @@ impl Session {
|
||||
}
|
||||
.or_cancel(cancellation_token)
|
||||
.await?;
|
||||
let mut selected_plugins = self
|
||||
.services
|
||||
.thread_extension_data
|
||||
.get::<codex_extension_api::SelectedPluginSnapshot>()
|
||||
.map(|snapshot| snapshot.as_ref().clone())
|
||||
.unwrap_or_default();
|
||||
selected_plugins.plugins.retain(|plugin| {
|
||||
ready_selected_capability_roots
|
||||
.iter()
|
||||
.any(|root| root.id == plugin.selected_root_id)
|
||||
});
|
||||
extension_data.insert(selected_plugins.clone());
|
||||
turn_context.extension_data.insert(selected_plugins);
|
||||
let tool_router = turn::built_tools(
|
||||
self.as_ref(),
|
||||
turn_context.as_ref(),
|
||||
|
||||
Reference in new issue
Block a user