Unify plugin skill loading with the host skill service (#37444)

## What changed

- Inject the host skill loader into `PluginsManager` so plugin discovery and agent turns use the same loading and product-policy behavior.
- Share plugin skill snapshots across those paths, preserving a consistent view of skills across workspaces.
- Apply migrated-command precedence after product filtering, allowing an eligible migrated command to replace a filtered native skill with the same name.

## Testing

- Add coverage for product-restricted plugin skills, native-versus-migrated command precedence, and the skills exposed to agent turns.

GitOrigin-RevId: f5ef0d0766ebeeb30d73ffaf044d003c2906ea4d
This commit is contained in:
felixxia-oai
2026-08-07 13:54:24 +00:00
committed by copyberry
parent e75a1888d7
commit e58d9ef447
30 changed files with 682 additions and 272 deletions
+13 -11
View File
@@ -416,21 +416,22 @@ impl ThreadManager {
let codex_home = config.codex_home.clone();
let restriction_product = session_source.restriction_product();
let (thread_created_tx, _) = broadcast::channel(THREAD_CREATED_CHANNEL_CAPACITY);
let skills_service = Arc::new(HostSkillsService::new_with_restriction_product(
codex_home.clone(),
config.bundled_skills_enabled(),
restriction_product,
));
let plugins_manager = Arc::new(PluginsManager::new_with_options(
codex_home.to_path_buf(),
restriction_product,
auth_manager.get_api_auth_mode(),
skills_service.clone(),
));
let mcp_manager = Arc::new(McpManager::new_with_extensions(
Arc::clone(&plugins_manager),
Arc::clone(&extensions),
codex_apps_tools_cache,
));
let skills_service = Arc::new(HostSkillsService::new_with_restriction_product(
codex_home,
config.bundled_skills_enabled(),
restriction_product,
));
let code_mode_session_provider: Arc<dyn CodeModeSessionProvider> =
if config.features.enabled(Feature::CodeModeHost)
|| config.code_mode.disable_in_process_fallback
@@ -562,17 +563,18 @@ impl ThreadManager {
};
let (thread_created_tx, _) = broadcast::channel(THREAD_CREATED_CHANNEL_CAPACITY);
let restriction_product = SessionSource::Exec.restriction_product();
let plugins_manager = Arc::new(PluginsManager::new_with_options(
codex_home.clone(),
restriction_product,
auth_manager.get_api_auth_mode(),
));
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
let skills_service = Arc::new(HostSkillsService::new_with_restriction_product(
absolute_codex_home.clone(),
/*bundled_skills_enabled*/ true,
restriction_product,
));
let plugins_manager = Arc::new(PluginsManager::new_with_options(
codex_home.clone(),
restriction_product,
auth_manager.get_api_auth_mode(),
skills_service.clone(),
));
let mcp_manager = Arc::new(McpManager::new(Arc::clone(&plugins_manager)));
// This test constructor has no Config input. Tests that need a non-local
// process store should construct ThreadManager::new with an explicit store.
let thread_store: Arc<dyn ThreadStore> = Arc::new(LocalThreadStore::new(