MCPcopy Create free account
hub / github.com/MoonshotAI/kimi-code / walkSkillDir

Function walkSkillDir

packages/agent-core/src/skill/scanner.ts:143–251  ·  view source on GitHub ↗
(
    dirPath: string,
    root: SkillRoot,
    isTopLevel: boolean,
    depth: number,
    subSkillParentName?: string,
  )

Source from the content-addressed store, hash-verified

141 const byName = new Map<string, SkillDefinition>();
142
143 async function walkSkillDir(
144 dirPath: string,
145 root: SkillRoot,
146 isTopLevel: boolean,
147 depth: number,
148 subSkillParentName?: string,
149 ): Promise<void> {
150 if (depth > MAX_SKILL_SCAN_DEPTH) return;
151
152 let entries: readonly string[];
153 try {
154 // Sorted so first-wins collision resolution across sibling directories
155 // is deterministic rather than dependent on filesystem readdir order.
156 entries = [...(await readdir(dirPath))].toSorted();
157 } catch (error) {
158 warn(`Failed to read skill directory ${dirPath}`, error);
159 return;
160 }
161
162 const directorySkills = new Set<string>();
163 const subdirs: string[] = [];
164 for (const entry of entries) {
165 const entryPath = path.join(dirPath, entry);
166 // A directory holding SKILL.md is a skill bundle: register it, then keep
167 // descending so nested SKILL.md bundles remain discoverable as sub-skills.
168 if (await isFile(path.join(entryPath, 'SKILL.md'))) {
169 directorySkills.add(entry);
170 }
171 if (entry === 'node_modules' || entry.startsWith('.')) continue;
172 if (await isDir(entryPath)) subdirs.push(entry);
173 }
174
175 const allowedSubSkillBundles = new Map<string, string>();
176 for (const entry of directorySkills) {
177 const skill = await parseAndRegister({
178 parse,
179 byName,
180 skillMdPath: path.join(dirPath, entry, 'SKILL.md'),
181 skillDirName: entry,
182 root,
183 onDiscoveredSkill: options.onDiscoveredSkill,
184 warn,
185 skip,
186 subSkillParentName,
187 });
188 if (skill !== undefined && hasSubSkillEnabled(skill)) {
189 allowedSubSkillBundles.set(entry, skill.name);
190 }
191 }
192
193 // Flat .md skills count only at a root's top level; deeper .md files are
194 // skill payload (e.g. references/foo.md), not skills.
195 if (isTopLevel) {
196 // A SKILL.md placed directly at a plugin skill root (e.g. plugin root fallback)
197 // is treated as a single skill bundle. This only applies to plugin-derived roots,
198 // not to user/project skill directories.
199 if (root.plugin !== undefined) {
200 const rootSkillMd = path.join(dirPath, 'SKILL.md');

Callers 1

discoverSkillsFunction · 0.85

Calls 10

isDirFunction · 0.85
parseAndRegisterFunction · 0.85
hasSubSkillEnabledFunction · 0.85
addMethod · 0.65
setMethod · 0.65
hasMethod · 0.65
getMethod · 0.65
readdirFunction · 0.50
isFileFunction · 0.50
pushMethod · 0.45

Tested by

no test coverage detected