Load plugin skill roots through the host skills service (#37440)

## What changed

- Implement `SkillRootLoader<PluginSkillRoot>` for `HostSkillsService`.
- Load roots concurrently while preserving request order, product restrictions, cached snapshots, skill errors, and per-skill filesystem metadata.
- Deduplicate overlapping roots and prefer native plugin skills over migrated commands with the same plugin ID and skill name.

## Testing

- Cover native and migrated skill precedence, nested and overlapping roots, product filtering, snapshot reuse, error propagation, and symlinked migration roots.

GitOrigin-RevId: 2270d10616b3a0463852c563ee071c524cd11e6b
This commit is contained in:
felixxia-oai authored and copyberry committed 2026-08-07 13:23:23 +00:00
1 parent a4b129eb3e
commit e75a1888d7
10 files changed
+634 -24

No files matched your search

+22
View File
@@ -31,6 +31,28 @@ pub struct SkillLoadOutcome {
}
impl SkillLoadOutcome {
/// Builds an already-composed outcome while retaining the filesystem that supplied each skill.
pub fn from_parts(
skills: Vec<SkillMetadata>,
errors: Vec<SkillError>,
skill_roots: Vec<AbsolutePathBuf>,
skill_root_by_path: HashMap<AbsolutePathBuf, AbsolutePathBuf>,
skill_discovery_path_by_path: HashMap<AbsolutePathBuf, AbsolutePathBuf>,
agent_plugin_skill_paths: HashSet<AbsolutePathBuf>,
file_systems_by_skill_path: HashMap<AbsolutePathBuf, Arc<dyn ExecutorFileSystem>>,
) -> Self {
Self {
skills,
errors,
skill_roots,
skill_root_by_path: Arc::new(skill_root_by_path),
skill_discovery_path_by_path: Arc::new(skill_discovery_path_by_path),
agent_plugin_skill_paths,
file_systems_by_skill_path: SkillFileSystemsByPath::new(file_systems_by_skill_path),
..Self::default()
}
}
pub fn is_skill_enabled(&self, skill: &SkillMetadata) -> bool {
!self.disabled_paths.contains(&skill.path_to_skills_md)
}