Agent Skills: Extension Support & Security Disclosure (#15834)

This commit is contained in:
N. Taylor Mullen
2026-01-04 14:45:07 -08:00
committed by GitHub
parent 12c7c9cc42
commit bdb349e7f6
9 changed files with 476 additions and 31 deletions
+35 -1
View File
@@ -9,6 +9,7 @@ import * as fs from 'node:fs/promises';
import * as os from 'node:os';
import * as path from 'node:path';
import { loadSkillsFromDir } from './skillLoader.js';
import { coreEvents } from '../utils/events.js';
describe('skillLoader', () => {
let testRootDir: string;
@@ -17,6 +18,7 @@ describe('skillLoader', () => {
testRootDir = await fs.mkdtemp(
path.join(os.tmpdir(), 'skill-loader-test-'),
);
vi.spyOn(coreEvents, 'emitFeedback');
});
afterEach(async () => {
@@ -40,18 +42,45 @@ describe('skillLoader', () => {
expect(skills[0].description).toBe('A test skill');
expect(skills[0].location).toBe(skillFile);
expect(skills[0].body).toBe('# Instructions\nDo something.');
expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
});
it('should emit feedback when no valid skills are found in a non-empty directory', async () => {
const notASkillDir = path.join(testRootDir, 'not-a-skill');
await fs.mkdir(notASkillDir, { recursive: true });
await fs.writeFile(path.join(notASkillDir, 'some-file.txt'), 'hello');
const skills = await loadSkillsFromDir(testRootDir);
expect(skills).toHaveLength(0);
expect(coreEvents.emitFeedback).toHaveBeenCalledWith(
'warning',
expect.stringContaining('Failed to load skills from'),
);
});
it('should ignore empty directories and not emit feedback', async () => {
const skills = await loadSkillsFromDir(testRootDir);
expect(skills).toHaveLength(0);
expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
});
it('should ignore directories without SKILL.md', async () => {
const notASkillDir = path.join(testRootDir, 'not-a-skill');
await fs.mkdir(notASkillDir, { recursive: true });
// With a subdirectory, even if empty, it might still trigger readdir
// But my current logic is if discoveredSkills.length === 0, then check readdir
// If readdir is empty, it's fine.
const skills = await loadSkillsFromDir(testRootDir);
expect(skills).toHaveLength(0);
// If notASkillDir is empty, no warning.
});
it('should ignore SKILL.md without valid frontmatter', async () => {
it('should ignore SKILL.md without valid frontmatter and emit warning if directory is not empty', async () => {
const skillDir = path.join(testRootDir, 'invalid-skill');
await fs.mkdir(skillDir, { recursive: true });
const skillFile = path.join(skillDir, 'SKILL.md');
@@ -60,10 +89,15 @@ describe('skillLoader', () => {
const skills = await loadSkillsFromDir(testRootDir);
expect(skills).toHaveLength(0);
expect(coreEvents.emitFeedback).toHaveBeenCalledWith(
'warning',
expect.stringContaining('Failed to load skills from'),
);
});
it('should return empty array for non-existent directory', async () => {
const skills = await loadSkillsFromDir('/non/existent/path');
expect(skills).toEqual([]);
expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
});
});