Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fix-nested-skill-discovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/intent': patch
---

Fix skill discovery so skills nested under intermediate grouping directories (directories without their own SKILL.md) are found by the scanner.
4 changes: 3 additions & 1 deletion packages/intent/src/library-scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@ function discoverSkills(skillsDir: string): Array<SkillEntry> {
framework:
typeof fm?.framework === 'string' ? fm.framework : undefined,
})
walk(childDir)
}
// Always recurse into subdirectories so skills nested under
// intermediate grouping directories (dirs without SKILL.md) are found.
walk(childDir)
}
}

Expand Down
5 changes: 3 additions & 2 deletions packages/intent/src/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,10 @@ function discoverSkills(
framework:
typeof fm?.framework === 'string' ? fm.framework : undefined,
})
// Recurse for sub-skills
walk(childDir)
}
// Always recurse into subdirectories so skills nested under
// intermediate grouping directories (dirs without SKILL.md) are found.
walk(childDir)
}
}

Expand Down
22 changes: 22 additions & 0 deletions packages/intent/tests/library-scanner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,28 @@ describe('scanLibrary', () => {
expect(names).toContain('routing/nested-routes')
})

it('discovers skills nested under intermediate dirs without SKILL.md', () => {
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'router')
writeJson(join(pkgDir, 'package.json'), {
name: '@tanstack/router',
version: '1.0.0',
keywords: ['tanstack-intent'],
})
// intermediate directory has no SKILL.md
const groupDir = createDir(pkgDir, 'skills', 'group')
const nestedDir = createDir(groupDir, 'nested-skill')
writeSkillMd(nestedDir, {
name: 'group/nested-skill',
description: 'A nested skill under a grouping dir',
})

const result = scanLibrary(scriptPath(pkgDir), root)

const skills = result.packages[0]!.skills
expect(skills).toHaveLength(1)
expect(skills[0]!.name).toBe('group/nested-skill')
})

it('handles missing package name without producing double slashes in paths', () => {
const pkgDir = createDir(root, 'node_modules', 'no-name-pkg')
writeJson(join(pkgDir, 'package.json'), {
Expand Down
21 changes: 21 additions & 0 deletions packages/intent/tests/scanner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,27 @@ describe('scanForIntents', () => {
expect(names).toContain('db-core/live-queries')
})

it('discovers skills nested under intermediate dirs without SKILL.md', () => {
const pkgDir = createDir(root, 'node_modules', '@tanstack', 'db')
writeJson(join(pkgDir, 'package.json'), {
name: '@tanstack/db',
version: '0.5.2',
intent: { version: 1, repo: 'TanStack/db', docs: 'docs/' },
})
// intermediate directory has no SKILL.md
const groupDir = createDir(pkgDir, 'skills', 'group')
const nestedDir = createDir(groupDir, 'nested-skill')
writeSkillMd(nestedDir, {
name: 'group/nested-skill',
description: 'A nested skill under a grouping dir',
})

const result = scanForIntents(root)
expect(result.packages).toHaveLength(1)
expect(result.packages[0]!.skills).toHaveLength(1)
expect(result.packages[0]!.skills[0]!.name).toBe('group/nested-skill')
})

it('warns on skills/ dir without valid intent field', () => {
const pkgDir = createDir(root, 'node_modules', 'bad-pkg')
writeJson(join(pkgDir, 'package.json'), {
Expand Down
Loading