feat(skills): validate manifest installer specs
This commit is contained in:
@@ -233,6 +233,75 @@ describe('loadSkill', () => {
|
||||
expect(skill!.manifest.tier).toBe('managed');
|
||||
});
|
||||
|
||||
it('accepts valid manifest installers definitions', () => {
|
||||
tmpDir = mkdtempSync(join(tmpdir(), 'flynn-test-'));
|
||||
const skillDir = join(tmpDir, 'installer-spec-skill');
|
||||
mkdirSync(skillDir);
|
||||
writeFileSync(
|
||||
join(skillDir, 'manifest.json'),
|
||||
JSON.stringify({
|
||||
name: 'installer-spec-skill',
|
||||
description: 'Has installer specs',
|
||||
version: '1.0.0',
|
||||
installers: [
|
||||
{ type: 'brew', packages: ['jq'] },
|
||||
{ type: 'node', packages: ['typescript'] },
|
||||
{ type: 'go', packages: ['golang.org/x/tools/cmd/stringer'] },
|
||||
{ type: 'download', url: 'https://example.com/tool.tgz', destination: '/tmp/tool.tgz' },
|
||||
],
|
||||
}),
|
||||
);
|
||||
writeFileSync(join(skillDir, 'SKILL.md'), '# Installer Spec Skill');
|
||||
|
||||
const skill = loadSkill(skillDir, 'bundled');
|
||||
|
||||
expect(skill).not.toBeNull();
|
||||
expect(skill!.manifest.installers).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('returns null when installers is not an array', () => {
|
||||
tmpDir = mkdtempSync(join(tmpdir(), 'flynn-test-'));
|
||||
const skillDir = join(tmpDir, 'invalid-installers-type');
|
||||
mkdirSync(skillDir);
|
||||
writeFileSync(
|
||||
join(skillDir, 'manifest.json'),
|
||||
JSON.stringify({
|
||||
name: 'invalid-installers-type',
|
||||
description: 'Invalid installers type',
|
||||
version: '1.0.0',
|
||||
installers: { type: 'brew', packages: ['jq'] },
|
||||
}),
|
||||
);
|
||||
writeFileSync(join(skillDir, 'SKILL.md'), '# Invalid Installers Type');
|
||||
|
||||
const skill = loadSkill(skillDir, 'bundled');
|
||||
|
||||
expect(skill).toBeNull();
|
||||
});
|
||||
|
||||
it('returns null when installer entries are invalid', () => {
|
||||
tmpDir = mkdtempSync(join(tmpdir(), 'flynn-test-'));
|
||||
const skillDir = join(tmpDir, 'invalid-installer-entry');
|
||||
mkdirSync(skillDir);
|
||||
writeFileSync(
|
||||
join(skillDir, 'manifest.json'),
|
||||
JSON.stringify({
|
||||
name: 'invalid-installer-entry',
|
||||
description: 'Invalid installer entry',
|
||||
version: '1.0.0',
|
||||
installers: [
|
||||
{ type: 'brew', packages: ['jq'] },
|
||||
{ type: 'download' },
|
||||
],
|
||||
}),
|
||||
);
|
||||
writeFileSync(join(skillDir, 'SKILL.md'), '# Invalid Installer Entry');
|
||||
|
||||
const skill = loadSkill(skillDir, 'bundled');
|
||||
|
||||
expect(skill).toBeNull();
|
||||
});
|
||||
|
||||
it('marks skill unavailable when requirements are not met', () => {
|
||||
// Negative: unmet requirements should set available=false with reasons.
|
||||
tmpDir = mkdtempSync(join(tmpdir(), 'flynn-test-'));
|
||||
|
||||
Reference in New Issue
Block a user