Scan skill roots concurrently (#33369)

## What changed

- Scan up to eight skill roots concurrently instead of loading them one at a time.
- Share scan capacity across host-skill and plugin-skill loads to bound aggregate filesystem work.
- Merge completed scans in input order so root precedence and error ordering remain deterministic.
- Skip canonicalization and parsing work for empty roots.

## Testing

- Add coverage for out-of-order scan completion and shared-capacity blocking.

GitOrigin-RevId: 33a47aaa02aee7fe31a050bb04d51c1e2043d6ae
This commit is contained in:
Adam Perry @ OpenAI authored and copyberry committed 2026-07-15 15:56:53 +00:00
1 parent c28770a42f
commit 2e4f55608b
11 files changed
+288 -48

No files matched your search

+12 -1
View File
@@ -70,6 +70,7 @@ use codex_core_skills::PluginSkillSnapshots;
use codex_core_skills::SkillMetadata;
use codex_core_skills::config_rules::SkillConfigRules;
use codex_core_skills::config_rules::skill_config_rules_from_stack;
use codex_core_skills::loader::MAX_CONCURRENT_ROOT_SCANS;
use codex_hooks::plugin_hook_declarations;
use codex_login::AuthManager;
use codex_login::CodexAuth;
@@ -376,6 +377,7 @@ pub struct PluginsManager {
// Keep the cache auth-independent so auth changes only need to resolve capabilities again.
loaded_plugins_cache: RwLock<LoadedPluginsCache>,
loaded_plugins_load_semaphore: Semaphore,
skill_root_scan_slots: Arc<Semaphore>,
tool_suggest_metadata_cache: ToolSuggestMetadataCache,
remote_installed_plugins_cache: RwLock<Option<Vec<RemoteInstalledPlugin>>>,
remote_installed_plugins_cache_refresh_state: RwLock<RemoteInstalledPluginsCacheRefreshState>,
@@ -452,6 +454,7 @@ impl PluginsManager {
non_curated_cache_refresh_state: RwLock::new(NonCuratedCacheRefreshState::default()),
loaded_plugins_cache: RwLock::new(LoadedPluginsCache::default()),
loaded_plugins_load_semaphore: Semaphore::new(/*permits*/ 1),
skill_root_scan_slots: Arc::new(Semaphore::new(MAX_CONCURRENT_ROOT_SCANS)),
tool_suggest_metadata_cache: ToolSuggestMetadataCache::new(),
remote_installed_plugins_cache: RwLock::new(None),
remote_installed_plugins_cache_refresh_state: RwLock::new(
@@ -585,6 +588,7 @@ impl PluginsManager {
Some(&plugin_skill_snapshots),
self.restriction_product,
remote_global_catalog_active,
Arc::clone(&self.skill_root_scan_slots),
)
.await;
log_plugin_load_errors(&plugins);
@@ -670,6 +674,7 @@ impl PluginsManager {
/*plugin_skill_snapshots*/ None,
self.restriction_product,
self.remote_global_catalog_active(config),
Arc::clone(&self.skill_root_scan_slots),
)
.await;
self.resolve_loaded_plugins_for_auth(plugins)
@@ -1708,7 +1713,12 @@ impl PluginsManager {
) -> Result<PluginCapabilitySummary, MarketplaceError> {
let fragment = self
.tool_suggest_metadata_cache
.metadata_for_plugin(marketplace_name, plugin, self.restriction_product)
.metadata_for_plugin(
marketplace_name,
plugin,
self.restriction_product,
Arc::clone(&self.skill_root_scan_slots),
)
.await?;
Ok(fragment.project(skill_config_rules, self.auth_mode()))
}
@@ -1890,6 +1900,7 @@ impl PluginsManager {
&config.config_layer_stack,
),
/*plugin_skill_snapshots*/ None,
Arc::clone(&self.skill_root_scan_slots),
)
.await;
let plugin_data_root = self.store.plugin_data_root(&plugin_id);