add-skill-kit 3.2.7 → 3.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/kit.js +89 -89
- package/bin/lib/agents.js +208 -208
- package/bin/lib/commands/analyze.js +70 -70
- package/bin/lib/commands/cache.js +65 -65
- package/bin/lib/commands/doctor.js +75 -75
- package/bin/lib/commands/help.js +155 -155
- package/bin/lib/commands/info.js +38 -38
- package/bin/lib/commands/init.js +39 -39
- package/bin/lib/commands/install.js +803 -803
- package/bin/lib/commands/list.js +43 -43
- package/bin/lib/commands/lock.js +57 -57
- package/bin/lib/commands/uninstall.js +307 -307
- package/bin/lib/commands/update.js +55 -55
- package/bin/lib/commands/validate.js +69 -69
- package/bin/lib/commands/verify.js +56 -56
- package/bin/lib/config.js +81 -81
- package/bin/lib/helpers.js +196 -196
- package/bin/lib/helpers.test.js +60 -60
- package/bin/lib/installer.js +164 -164
- package/bin/lib/skills.js +119 -119
- package/bin/lib/skills.test.js +109 -109
- package/bin/lib/types.js +82 -82
- package/bin/lib/ui.js +329 -329
- package/package.json +1 -1
package/bin/lib/skills.test.js
CHANGED
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Tests for skills.js
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import path from "path";
|
|
7
|
-
import os from "os";
|
|
8
|
-
import { parseSkillMdFrontmatter, detectSkillStructure } from "./skills.js";
|
|
9
|
-
|
|
10
|
-
describe("parseSkillMdFrontmatter", () => {
|
|
11
|
-
let tempDir;
|
|
12
|
-
let skillMdPath;
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "skill-test-"));
|
|
16
|
-
skillMdPath = path.join(tempDir, "SKILL.md");
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("parses valid frontmatter", () => {
|
|
24
|
-
const content = `---
|
|
25
|
-
name: test-skill
|
|
26
|
-
description: A test skill for testing
|
|
27
|
-
version: 1.0.0
|
|
28
|
-
author: Test Author
|
|
29
|
-
tags: react, testing, patterns
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
# Test Skill
|
|
33
|
-
|
|
34
|
-
Some content here.
|
|
35
|
-
`;
|
|
36
|
-
fs.writeFileSync(skillMdPath, content);
|
|
37
|
-
|
|
38
|
-
const result = parseSkillMdFrontmatter(skillMdPath);
|
|
39
|
-
|
|
40
|
-
expect(result.name).toBe("test-skill");
|
|
41
|
-
expect(result.description).toBe("A test skill for testing");
|
|
42
|
-
expect(result.version).toBe("1.0.0");
|
|
43
|
-
expect(result.author).toBe("Test Author");
|
|
44
|
-
expect(result.tags).toEqual(["react", "testing", "patterns"]);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("returns empty object for no frontmatter", () => {
|
|
48
|
-
fs.writeFileSync(skillMdPath, "# Just a heading\n\nNo frontmatter here.");
|
|
49
|
-
|
|
50
|
-
const result = parseSkillMdFrontmatter(skillMdPath);
|
|
51
|
-
|
|
52
|
-
expect(result).toEqual({});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("returns empty object for non-existent file", () => {
|
|
56
|
-
const result = parseSkillMdFrontmatter("/non/existent/path/SKILL.md");
|
|
57
|
-
expect(result).toEqual({});
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe("detectSkillStructure", () => {
|
|
62
|
-
let tempDir;
|
|
63
|
-
|
|
64
|
-
beforeEach(() => {
|
|
65
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "skill-structure-"));
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
afterEach(() => {
|
|
69
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it("detects standard directories", () => {
|
|
73
|
-
fs.mkdirSync(path.join(tempDir, "resources"));
|
|
74
|
-
fs.mkdirSync(path.join(tempDir, "examples"));
|
|
75
|
-
fs.mkdirSync(path.join(tempDir, "scripts"));
|
|
76
|
-
fs.writeFileSync(path.join(tempDir, "SKILL.md"), "# Skill");
|
|
77
|
-
|
|
78
|
-
const result = detectSkillStructure(tempDir);
|
|
79
|
-
|
|
80
|
-
expect(result.hasResources).toBe(true);
|
|
81
|
-
expect(result.hasExamples).toBe(true);
|
|
82
|
-
expect(result.hasScripts).toBe(true);
|
|
83
|
-
expect(result.directories).toContain("resources");
|
|
84
|
-
expect(result.directories).toContain("examples");
|
|
85
|
-
expect(result.directories).toContain("scripts");
|
|
86
|
-
expect(result.files).toContain("SKILL.md");
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("detects governance directories", () => {
|
|
90
|
-
fs.mkdirSync(path.join(tempDir, "constitution"));
|
|
91
|
-
fs.mkdirSync(path.join(tempDir, "doctrines"));
|
|
92
|
-
fs.mkdirSync(path.join(tempDir, "enforcement"));
|
|
93
|
-
fs.mkdirSync(path.join(tempDir, "proposals"));
|
|
94
|
-
|
|
95
|
-
const result = detectSkillStructure(tempDir);
|
|
96
|
-
|
|
97
|
-
expect(result.hasConstitution).toBe(true);
|
|
98
|
-
expect(result.hasDoctrines).toBe(true);
|
|
99
|
-
expect(result.hasEnforcement).toBe(true);
|
|
100
|
-
expect(result.hasProposals).toBe(true);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("returns empty structure for non-existent dir", () => {
|
|
104
|
-
const result = detectSkillStructure("/non/existent/path");
|
|
105
|
-
|
|
106
|
-
expect(result.directories).toEqual([]);
|
|
107
|
-
expect(result.files).toEqual([]);
|
|
108
|
-
});
|
|
109
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for skills.js
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import os from "os";
|
|
8
|
+
import { parseSkillMdFrontmatter, detectSkillStructure } from "./skills.js";
|
|
9
|
+
|
|
10
|
+
describe("parseSkillMdFrontmatter", () => {
|
|
11
|
+
let tempDir;
|
|
12
|
+
let skillMdPath;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "skill-test-"));
|
|
16
|
+
skillMdPath = path.join(tempDir, "SKILL.md");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("parses valid frontmatter", () => {
|
|
24
|
+
const content = `---
|
|
25
|
+
name: test-skill
|
|
26
|
+
description: A test skill for testing
|
|
27
|
+
version: 1.0.0
|
|
28
|
+
author: Test Author
|
|
29
|
+
tags: react, testing, patterns
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# Test Skill
|
|
33
|
+
|
|
34
|
+
Some content here.
|
|
35
|
+
`;
|
|
36
|
+
fs.writeFileSync(skillMdPath, content);
|
|
37
|
+
|
|
38
|
+
const result = parseSkillMdFrontmatter(skillMdPath);
|
|
39
|
+
|
|
40
|
+
expect(result.name).toBe("test-skill");
|
|
41
|
+
expect(result.description).toBe("A test skill for testing");
|
|
42
|
+
expect(result.version).toBe("1.0.0");
|
|
43
|
+
expect(result.author).toBe("Test Author");
|
|
44
|
+
expect(result.tags).toEqual(["react", "testing", "patterns"]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("returns empty object for no frontmatter", () => {
|
|
48
|
+
fs.writeFileSync(skillMdPath, "# Just a heading\n\nNo frontmatter here.");
|
|
49
|
+
|
|
50
|
+
const result = parseSkillMdFrontmatter(skillMdPath);
|
|
51
|
+
|
|
52
|
+
expect(result).toEqual({});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("returns empty object for non-existent file", () => {
|
|
56
|
+
const result = parseSkillMdFrontmatter("/non/existent/path/SKILL.md");
|
|
57
|
+
expect(result).toEqual({});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("detectSkillStructure", () => {
|
|
62
|
+
let tempDir;
|
|
63
|
+
|
|
64
|
+
beforeEach(() => {
|
|
65
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "skill-structure-"));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterEach(() => {
|
|
69
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("detects standard directories", () => {
|
|
73
|
+
fs.mkdirSync(path.join(tempDir, "resources"));
|
|
74
|
+
fs.mkdirSync(path.join(tempDir, "examples"));
|
|
75
|
+
fs.mkdirSync(path.join(tempDir, "scripts"));
|
|
76
|
+
fs.writeFileSync(path.join(tempDir, "SKILL.md"), "# Skill");
|
|
77
|
+
|
|
78
|
+
const result = detectSkillStructure(tempDir);
|
|
79
|
+
|
|
80
|
+
expect(result.hasResources).toBe(true);
|
|
81
|
+
expect(result.hasExamples).toBe(true);
|
|
82
|
+
expect(result.hasScripts).toBe(true);
|
|
83
|
+
expect(result.directories).toContain("resources");
|
|
84
|
+
expect(result.directories).toContain("examples");
|
|
85
|
+
expect(result.directories).toContain("scripts");
|
|
86
|
+
expect(result.files).toContain("SKILL.md");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("detects governance directories", () => {
|
|
90
|
+
fs.mkdirSync(path.join(tempDir, "constitution"));
|
|
91
|
+
fs.mkdirSync(path.join(tempDir, "doctrines"));
|
|
92
|
+
fs.mkdirSync(path.join(tempDir, "enforcement"));
|
|
93
|
+
fs.mkdirSync(path.join(tempDir, "proposals"));
|
|
94
|
+
|
|
95
|
+
const result = detectSkillStructure(tempDir);
|
|
96
|
+
|
|
97
|
+
expect(result.hasConstitution).toBe(true);
|
|
98
|
+
expect(result.hasDoctrines).toBe(true);
|
|
99
|
+
expect(result.hasEnforcement).toBe(true);
|
|
100
|
+
expect(result.hasProposals).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("returns empty structure for non-existent dir", () => {
|
|
104
|
+
const result = detectSkillStructure("/non/existent/path");
|
|
105
|
+
|
|
106
|
+
expect(result.directories).toEqual([]);
|
|
107
|
+
expect(result.files).toEqual([]);
|
|
108
|
+
});
|
|
109
|
+
});
|
package/bin/lib/types.js
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview JSDoc Type Definitions for add-skill CLI
|
|
3
|
-
* Provides IDE autocomplete support
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @typedef {Object} SkillStructure
|
|
8
|
-
* @property {boolean} hasResources
|
|
9
|
-
* @property {boolean} hasExamples
|
|
10
|
-
* @property {boolean} hasScripts
|
|
11
|
-
* @property {boolean} hasConstitution
|
|
12
|
-
* @property {boolean} hasDoctrines
|
|
13
|
-
* @property {boolean} hasEnforcement
|
|
14
|
-
* @property {boolean} hasProposals
|
|
15
|
-
* @property {string[]} directories
|
|
16
|
-
* @property {string[]} files
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @typedef {Object} Skill
|
|
21
|
-
* @property {string} name - Skill folder name
|
|
22
|
-
* @property {string} path - Absolute path to skill
|
|
23
|
-
* @property {boolean} hasSkillMd - Has SKILL.md file
|
|
24
|
-
* @property {string} description - From SKILL.md frontmatter
|
|
25
|
-
* @property {string[]} tags - From SKILL.md frontmatter
|
|
26
|
-
* @property {string} author - Author or publisher
|
|
27
|
-
* @property {string} version - Version or ref
|
|
28
|
-
* @property {SkillStructure} structure - Directory structure
|
|
29
|
-
* @property {number} size - Total size in bytes
|
|
30
|
-
* @property {string} [repo] - Source repository
|
|
31
|
-
* @property {string} [skill] - Skill name in repo
|
|
32
|
-
* @property {string} [ref] - Git ref
|
|
33
|
-
* @property {string} [checksum] - Merkle hash
|
|
34
|
-
* @property {string} [installedAt] - ISO timestamp
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @typedef {Object} SkillMeta
|
|
39
|
-
* @property {string} [name]
|
|
40
|
-
* @property {string} [description]
|
|
41
|
-
* @property {string} [version]
|
|
42
|
-
* @property {string} [author]
|
|
43
|
-
* @property {string[]} [tags]
|
|
44
|
-
* @property {string} [type]
|
|
45
|
-
* @property {string} [authority]
|
|
46
|
-
* @property {string} [parent]
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @typedef {Object} ParsedSpec
|
|
51
|
-
* @property {string} org - GitHub org
|
|
52
|
-
* @property {string} repo - GitHub repo
|
|
53
|
-
* @property {string} [skill] - Skill name
|
|
54
|
-
* @property {string} [ref] - Git ref
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @typedef {Object} Backup
|
|
59
|
-
* @property {string} name
|
|
60
|
-
* @property {string} path
|
|
61
|
-
* @property {Date} createdAt
|
|
62
|
-
* @property {number} size
|
|
63
|
-
*/
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @typedef {Object} SkillLock
|
|
67
|
-
* @property {number} lockVersion
|
|
68
|
-
* @property {string} generatedAt
|
|
69
|
-
* @property {string} generator
|
|
70
|
-
* @property {Object.<string, SkillLockEntry>} skills
|
|
71
|
-
*/
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* @typedef {Object} SkillLockEntry
|
|
75
|
-
* @property {string} repo
|
|
76
|
-
* @property {string} skill
|
|
77
|
-
* @property {string} ref
|
|
78
|
-
* @property {string} checksum
|
|
79
|
-
* @property {string} [publisher]
|
|
80
|
-
*/
|
|
81
|
-
|
|
82
|
-
export { };
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview JSDoc Type Definitions for add-skill CLI
|
|
3
|
+
* Provides IDE autocomplete support
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} SkillStructure
|
|
8
|
+
* @property {boolean} hasResources
|
|
9
|
+
* @property {boolean} hasExamples
|
|
10
|
+
* @property {boolean} hasScripts
|
|
11
|
+
* @property {boolean} hasConstitution
|
|
12
|
+
* @property {boolean} hasDoctrines
|
|
13
|
+
* @property {boolean} hasEnforcement
|
|
14
|
+
* @property {boolean} hasProposals
|
|
15
|
+
* @property {string[]} directories
|
|
16
|
+
* @property {string[]} files
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {Object} Skill
|
|
21
|
+
* @property {string} name - Skill folder name
|
|
22
|
+
* @property {string} path - Absolute path to skill
|
|
23
|
+
* @property {boolean} hasSkillMd - Has SKILL.md file
|
|
24
|
+
* @property {string} description - From SKILL.md frontmatter
|
|
25
|
+
* @property {string[]} tags - From SKILL.md frontmatter
|
|
26
|
+
* @property {string} author - Author or publisher
|
|
27
|
+
* @property {string} version - Version or ref
|
|
28
|
+
* @property {SkillStructure} structure - Directory structure
|
|
29
|
+
* @property {number} size - Total size in bytes
|
|
30
|
+
* @property {string} [repo] - Source repository
|
|
31
|
+
* @property {string} [skill] - Skill name in repo
|
|
32
|
+
* @property {string} [ref] - Git ref
|
|
33
|
+
* @property {string} [checksum] - Merkle hash
|
|
34
|
+
* @property {string} [installedAt] - ISO timestamp
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {Object} SkillMeta
|
|
39
|
+
* @property {string} [name]
|
|
40
|
+
* @property {string} [description]
|
|
41
|
+
* @property {string} [version]
|
|
42
|
+
* @property {string} [author]
|
|
43
|
+
* @property {string[]} [tags]
|
|
44
|
+
* @property {string} [type]
|
|
45
|
+
* @property {string} [authority]
|
|
46
|
+
* @property {string} [parent]
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @typedef {Object} ParsedSpec
|
|
51
|
+
* @property {string} org - GitHub org
|
|
52
|
+
* @property {string} repo - GitHub repo
|
|
53
|
+
* @property {string} [skill] - Skill name
|
|
54
|
+
* @property {string} [ref] - Git ref
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @typedef {Object} Backup
|
|
59
|
+
* @property {string} name
|
|
60
|
+
* @property {string} path
|
|
61
|
+
* @property {Date} createdAt
|
|
62
|
+
* @property {number} size
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @typedef {Object} SkillLock
|
|
67
|
+
* @property {number} lockVersion
|
|
68
|
+
* @property {string} generatedAt
|
|
69
|
+
* @property {string} generator
|
|
70
|
+
* @property {Object.<string, SkillLockEntry>} skills
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @typedef {Object} SkillLockEntry
|
|
75
|
+
* @property {string} repo
|
|
76
|
+
* @property {string} skill
|
|
77
|
+
* @property {string} ref
|
|
78
|
+
* @property {string} checksum
|
|
79
|
+
* @property {string} [publisher]
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
export { };
|