discoverSkills function
Future<List<Skill> >
discoverSkills(
- ExecutionEnv env, {
- List<
SkillRoot> projectRoots = const [], - List<
SkillRoot> userRoots = const [], - Set<
SkillSource> ? allowedSources, - List<
Skill> builtins = const [],
Discovers skills under projectRoots then userRoots (project wins on a
name clash, first-name-wins case-insensitively). Roots whose source is
not in allowedSources (defaults: everything) are skipped — hosts pass
the first-party set when the user has not granted third-party skills
access. Missing roots are silently skipped.
builtins are the package's compiled-in skills (issue #1151), merged
LAST so every project/user/third-party skill of the same name shadows
them (precedence ladder: project > user > third-party-granted > builtin).
Built-ins are first-party and never gated by allowedSources.
Implementation
Future<List<Skill>> discoverSkills(
ExecutionEnv env, {
List<SkillRoot> projectRoots = const [],
List<SkillRoot> userRoots = const [],
Set<SkillSource>? allowedSources,
List<Skill> builtins = const [],
}) {
bool allowed(SkillRoot root) =>
allowedSources == null || allowedSources.contains(root.source);
final skills = <Skill>[];
final seen = <String>{};
Future<void> scan(SkillScope scope, List<SkillRoot> roots) async {
for (final root in roots.where(allowed)) {
for (final skill in await _scanRoot(env, root, scope)) {
if (seen.add(skill.name.toLowerCase())) skills.add(skill);
}
}
}
return () async {
await scan(SkillScope.project, projectRoots);
await scan(SkillScope.user, userRoots);
for (final skill in builtins) {
if (seen.add(skill.name.toLowerCase())) skills.add(skill);
}
return skills;
}();
}