@bacnh85/agent-skills 0.1.1

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.
Files changed (52) hide show
  1. package/README.md +229 -0
  2. package/dist/src/cli.d.ts +12 -0
  3. package/dist/src/cli.js +224 -0
  4. package/dist/src/cli.js.map +1 -0
  5. package/dist/src/config.d.ts +9 -0
  6. package/dist/src/config.js +14 -0
  7. package/dist/src/config.js.map +1 -0
  8. package/dist/src/discovery.d.ts +16 -0
  9. package/dist/src/discovery.js +161 -0
  10. package/dist/src/discovery.js.map +1 -0
  11. package/dist/src/installer.d.ts +9 -0
  12. package/dist/src/installer.js +131 -0
  13. package/dist/src/installer.js.map +1 -0
  14. package/dist/src/manager.d.ts +8 -0
  15. package/dist/src/manager.js +229 -0
  16. package/dist/src/manager.js.map +1 -0
  17. package/dist/src/registry.d.ts +5 -0
  18. package/dist/src/registry.js +46 -0
  19. package/dist/src/registry.js.map +1 -0
  20. package/dist/src/skill.d.ts +2 -0
  21. package/dist/src/skill.js +50 -0
  22. package/dist/src/skill.js.map +1 -0
  23. package/dist/src/types.d.ts +39 -0
  24. package/dist/src/types.js +2 -0
  25. package/dist/src/types.js.map +1 -0
  26. package/dist/src/ui.d.ts +14 -0
  27. package/dist/src/ui.js +70 -0
  28. package/dist/src/ui.js.map +1 -0
  29. package/dist/test/cli.test.d.ts +1 -0
  30. package/dist/test/cli.test.js +168 -0
  31. package/dist/test/cli.test.js.map +1 -0
  32. package/dist/test/config.test.d.ts +1 -0
  33. package/dist/test/config.test.js +12 -0
  34. package/dist/test/config.test.js.map +1 -0
  35. package/dist/test/discovery.test.d.ts +1 -0
  36. package/dist/test/discovery.test.js +42 -0
  37. package/dist/test/discovery.test.js.map +1 -0
  38. package/dist/test/installer.test.d.ts +1 -0
  39. package/dist/test/installer.test.js +159 -0
  40. package/dist/test/installer.test.js.map +1 -0
  41. package/dist/test/manager.test.d.ts +1 -0
  42. package/dist/test/manager.test.js +150 -0
  43. package/dist/test/manager.test.js.map +1 -0
  44. package/dist/test/skill.test.d.ts +1 -0
  45. package/dist/test/skill.test.js +27 -0
  46. package/dist/test/skill.test.js.map +1 -0
  47. package/dist/test/ui.test.d.ts +1 -0
  48. package/dist/test/ui.test.js +28 -0
  49. package/dist/test/ui.test.js.map +1 -0
  50. package/package.json +54 -0
  51. package/skills/frontend-design/LICENSE.txt +177 -0
  52. package/skills/frontend-design/SKILL.md +55 -0
@@ -0,0 +1,50 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync, readdirSync, realpathSync } from "node:fs";
3
+ import { isAbsolute, join, relative, sep } from "node:path";
4
+ function isWithin(root, path) {
5
+ const rel = relative(root, path);
6
+ return rel === "" || (rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
7
+ }
8
+ export function validateSkill(source, expectedName, sourceRoot = source) {
9
+ const root = realpathSync(source);
10
+ if (!isWithin(realpathSync(sourceRoot), root)) {
11
+ throw new Error(`Skill path escapes source root: ${source}`);
12
+ }
13
+ const skillFile = join(root, "SKILL.md");
14
+ let content;
15
+ try {
16
+ content = readFileSync(skillFile, "utf8");
17
+ }
18
+ catch {
19
+ throw new Error(`Missing SKILL.md in ${source}.`);
20
+ }
21
+ const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
22
+ const name = frontmatter?.[1].match(/^name:\s*(.+)\s*$/m)?.[1].trim();
23
+ const description = frontmatter?.[1].match(/^description:\s*(.+)\s*$/m)?.[1].trim();
24
+ if (!name || !description) {
25
+ throw new Error(`SKILL.md for "${expectedName}" requires name and description.`);
26
+ }
27
+ if (name !== expectedName) {
28
+ throw new Error(`Skill name "${name}" does not match directory name "${expectedName}".`);
29
+ }
30
+ return content;
31
+ }
32
+ export function hashDirectory(root) {
33
+ const hash = createHash("sha256");
34
+ const visit = (directory) => {
35
+ for (const entry of readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
36
+ const path = join(directory, entry.name);
37
+ const rel = relative(root, path).split(sep).join("/");
38
+ hash.update(`${entry.isDirectory() ? "d" : entry.isSymbolicLink() ? "l" : "f"}:${rel}\0`);
39
+ if (entry.isDirectory())
40
+ visit(path);
41
+ else if (entry.isSymbolicLink())
42
+ hash.update(realpathSync(path));
43
+ else
44
+ hash.update(readFileSync(path));
45
+ }
46
+ };
47
+ visit(root);
48
+ return hash.digest("hex");
49
+ }
50
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export type SourceType = "git" | "local";
2
+ export interface DiscoveredSkill {
3
+ name: string;
4
+ absolutePath: string;
5
+ relativePath: string;
6
+ }
7
+ export interface ResolvedSource {
8
+ source: string;
9
+ sourceType: SourceType;
10
+ root: string;
11
+ ref?: string;
12
+ commit?: string;
13
+ directPath?: string;
14
+ cleanup(): void;
15
+ }
16
+ export interface RegistryEntry {
17
+ name: string;
18
+ path: string;
19
+ source: string;
20
+ sourceType: SourceType;
21
+ sourcePath?: string;
22
+ ref?: string;
23
+ commit?: string;
24
+ hash: string;
25
+ addedAt: string;
26
+ updatedAt: string;
27
+ updatable: boolean;
28
+ }
29
+ export interface Registry {
30
+ version: 2;
31
+ skills: Record<string, RegistryEntry>;
32
+ }
33
+ export interface OperationResult {
34
+ name: string;
35
+ action: "added" | "updated" | "removed" | "unchanged" | "skipped";
36
+ message?: string;
37
+ path?: string;
38
+ hash?: string;
39
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import type { DiscoveredSkill, OperationResult, RegistryEntry } from "./types.js";
2
+ export interface OperationProgress {
3
+ message(message: string): void;
4
+ }
5
+ export declare function runOperation(startMessage: string, stopMessage: string, interactive: boolean, operation: (progress: OperationProgress) => OperationResult[]): OperationResult[];
6
+ export declare function formatOperationResult(result: OperationResult): string;
7
+ export declare function skillOptions(skills: DiscoveredSkill[]): {
8
+ value: string;
9
+ label: string;
10
+ hint: string;
11
+ }[];
12
+ export declare function selectDiscoveredSkills(skills: DiscoveredSkill[], action?: "add" | "install"): Promise<DiscoveredSkill[]>;
13
+ export declare function selectRegistrySkills(entries: RegistryEntry[]): Promise<string[]>;
14
+ export declare function selectInstalledSkills(skills: DiscoveredSkill[]): Promise<string[]>;
package/dist/src/ui.js ADDED
@@ -0,0 +1,70 @@
1
+ import { isCancel, multiselect, spinner } from "@clack/prompts";
2
+ import pc from "picocolors";
3
+ export function runOperation(startMessage, stopMessage, interactive, operation) {
4
+ if (!interactive)
5
+ return operation({ message() { } });
6
+ const progress = spinner();
7
+ progress.start(startMessage);
8
+ try {
9
+ const results = operation({ message: (message) => progress.message(message) });
10
+ progress.stop(stopMessage);
11
+ return results;
12
+ }
13
+ catch (error) {
14
+ progress.stop("Operation failed", 1);
15
+ throw error;
16
+ }
17
+ }
18
+ export function formatOperationResult(result) {
19
+ const action = {
20
+ added: pc.green("added"),
21
+ updated: pc.green("updated"),
22
+ removed: pc.green("removed"),
23
+ unchanged: pc.dim("unchanged"),
24
+ skipped: pc.yellow("skipped")
25
+ }[result.action];
26
+ return `${action}: ${pc.cyan(result.name)}${result.path ? ` ${pc.dim(`-> ${result.path}`)}` : ""}${result.message ? ` ${pc.dim(`(${result.message})`)}` : ""}`;
27
+ }
28
+ export function skillOptions(skills) {
29
+ return skills.map((skill) => ({
30
+ value: skill.relativePath,
31
+ label: skill.name,
32
+ hint: skill.relativePath
33
+ }));
34
+ }
35
+ export async function selectDiscoveredSkills(skills, action = "add") {
36
+ const selected = await multiselect({
37
+ message: `Select skills to ${action}`,
38
+ options: skillOptions(skills),
39
+ required: true
40
+ });
41
+ if (isCancel(selected))
42
+ return [];
43
+ const paths = new Set(selected);
44
+ return skills.filter((skill) => paths.has(skill.relativePath));
45
+ }
46
+ export async function selectRegistrySkills(entries) {
47
+ const selected = await multiselect({
48
+ message: "Select skills to remove",
49
+ options: entries.map((entry) => ({
50
+ value: entry.name,
51
+ label: entry.name,
52
+ hint: entry.path
53
+ })),
54
+ required: true
55
+ });
56
+ return isCancel(selected) ? [] : selected;
57
+ }
58
+ export async function selectInstalledSkills(skills) {
59
+ const selected = await multiselect({
60
+ message: "Select skills to uninstall",
61
+ options: skills.map((skill) => ({
62
+ value: skill.name,
63
+ label: skill.name,
64
+ hint: skill.absolutePath
65
+ })),
66
+ required: true
67
+ });
68
+ return isCancel(selected) ? [] : selected;
69
+ }
70
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/ui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,168 @@
1
+ import assert from "node:assert/strict";
2
+ import { execFileSync } from "node:child_process";
3
+ import { mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import test from "node:test";
7
+ import { pathToFileURL } from "node:url";
8
+ import { formatRegistryList, isCliEntrypoint, parseArgs } from "../src/cli.js";
9
+ function registryEntry(overrides) {
10
+ return {
11
+ name: "example",
12
+ path: "skills/example",
13
+ source: "owner/repo",
14
+ sourceType: "git",
15
+ hash: "hash",
16
+ addedAt: "2026-01-01T00:00:00.000Z",
17
+ updatedAt: "2026-01-02T00:00:00.000Z",
18
+ updatable: true,
19
+ ...overrides
20
+ };
21
+ }
22
+ test("parser accepts repository management and install commands", () => {
23
+ assert.deepEqual(parseArgs(["add", "./skills"]), {
24
+ command: "add",
25
+ values: ["./skills"]
26
+ });
27
+ assert.deepEqual(parseArgs(["remove", "a", "b"]), {
28
+ command: "remove",
29
+ values: ["a", "b"]
30
+ });
31
+ assert.deepEqual(parseArgs(["list"]), { command: "list", values: [] });
32
+ assert.deepEqual(parseArgs(["update"]), { command: "update", values: [] });
33
+ assert.deepEqual(parseArgs(["install"]), {
34
+ command: "install",
35
+ values: [],
36
+ all: false,
37
+ global: false
38
+ });
39
+ assert.deepEqual(parseArgs(["install", "-g", "--all"]), {
40
+ command: "install",
41
+ values: [],
42
+ all: true,
43
+ global: true
44
+ });
45
+ assert.deepEqual(parseArgs(["uninstall", "demo", "notes", "-g"]), {
46
+ command: "uninstall",
47
+ values: ["demo", "notes"],
48
+ all: false,
49
+ global: true
50
+ });
51
+ assert.deepEqual(parseArgs(["uninstall"]), {
52
+ command: "uninstall",
53
+ values: [],
54
+ all: false,
55
+ global: false
56
+ });
57
+ assert.deepEqual(parseArgs(["uninstall", "--all", "-g"]), {
58
+ command: "uninstall",
59
+ values: [],
60
+ all: true,
61
+ global: true
62
+ });
63
+ assert.throws(() => parseArgs(["promote"]), /Unknown command/);
64
+ assert.throws(() => parseArgs(["add", "x", "--yes"]), /Unknown option/);
65
+ assert.throws(() => parseArgs(["list", "-g"]), /Unknown option: -g/);
66
+ assert.throws(() => parseArgs(["list", "extra"]), /does not accept arguments/);
67
+ assert.throws(() => parseArgs(["install", "--yes"]), /Unknown option/);
68
+ assert.throws(() => parseArgs(["install", "demo"]), /does not accept arguments/);
69
+ assert.throws(() => parseArgs(["uninstall", "--yes"]), /Unknown option/);
70
+ assert.throws(() => parseArgs(["uninstall", "demo", "--all"]), /does not accept names with --all/);
71
+ });
72
+ test("registry list sorts entries and aligns labeled fields", () => {
73
+ const output = formatRegistryList([
74
+ registryEntry({
75
+ name: "z",
76
+ path: "skills/z",
77
+ source: "long-owner/long-repository",
78
+ ref: "main",
79
+ commit: "1234567890abcdef",
80
+ updatedAt: "2026-02-03T04:05:06.000Z"
81
+ }),
82
+ registryEntry({
83
+ name: "alpha",
84
+ path: "skills/category/alpha",
85
+ source: "repo",
86
+ ref: "dev",
87
+ commit: "abcdef1234567890",
88
+ updatedAt: "2026-01-02T03:04:05.000Z"
89
+ })
90
+ ]);
91
+ const lines = output.split("\n");
92
+ assert.equal(lines[0], "Project Skills");
93
+ assert.equal(lines[1], "");
94
+ assert.match(lines[2], /^alpha\s+skills\/category\/alpha\s+Source: repo/);
95
+ assert.match(lines[3], /^z\s+skills\/z\s+Source: long-owner\/long-repository/);
96
+ for (const label of ["Source:", "Ref:", "Commit:", "Updated:"]) {
97
+ assert.equal(lines[2].indexOf(label), lines[3].indexOf(label));
98
+ }
99
+ assert.match(lines[2], /Commit: abcdef123456/);
100
+ assert.match(lines[3], /Commit: 1234567890ab/);
101
+ });
102
+ test("registry list represents missing fields with fallbacks", () => {
103
+ const output = formatRegistryList([
104
+ registryEntry({
105
+ source: "",
106
+ ref: undefined,
107
+ commit: undefined,
108
+ updatedAt: ""
109
+ })
110
+ ]);
111
+ assert.match(output, /Source: -\s+Ref: -\s+Commit: -\s+Updated: -/);
112
+ });
113
+ test("registry list reports an empty registry", () => {
114
+ assert.equal(formatRegistryList([]), "No project skills found.");
115
+ });
116
+ test("CLI entrypoint detection follows install symlinks", () => {
117
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-cli-"));
118
+ try {
119
+ const target = join(root, "package", "cli.js");
120
+ const link = join(root, "bin", "agent-skills");
121
+ mkdirSync(join(root, "package"), { recursive: true });
122
+ mkdirSync(join(root, "bin"));
123
+ writeFileSync(target, "#!/usr/bin/env node\n");
124
+ symlinkSync(target, link);
125
+ assert.equal(isCliEntrypoint(pathToFileURL(target).href, link), true);
126
+ }
127
+ finally {
128
+ rmSync(root, { recursive: true, force: true });
129
+ }
130
+ });
131
+ test("uninstall CLI reports empty targets before requiring interactive input", () => {
132
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-cli-uninstall-empty-"));
133
+ try {
134
+ assert.throws(() => execFileSync(process.execPath, [join(process.cwd(), "dist/src/cli.js"), "uninstall"], {
135
+ cwd: root,
136
+ encoding: "utf8",
137
+ stdio: ["ignore", "pipe", "pipe"]
138
+ }), /No installed skills found/);
139
+ }
140
+ finally {
141
+ rmSync(root, { recursive: true, force: true });
142
+ }
143
+ });
144
+ test("uninstall CLI rejects interactive selection without a TTY", () => {
145
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-cli-uninstall-tty-"));
146
+ try {
147
+ const skill = join(root, ".agents", "skills", "demo");
148
+ mkdirSync(skill, { recursive: true });
149
+ writeFileSync(join(skill, "SKILL.md"), "---\nname: demo\ndescription: Demo skill.\n---\n");
150
+ assert.throws(() => execFileSync(process.execPath, [join(process.cwd(), "dist/src/cli.js"), "uninstall"], {
151
+ cwd: root,
152
+ encoding: "utf8",
153
+ stdio: ["ignore", "pipe", "pipe"]
154
+ }), /Interactive skill selection requires a TTY/);
155
+ }
156
+ finally {
157
+ rmSync(root, { recursive: true, force: true });
158
+ }
159
+ });
160
+ test("package has a git-install-safe prepare script and committed CLI entrypoint", () => {
161
+ const manifest = JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf8"));
162
+ assert.equal(manifest.scripts.prepare, "node scripts/prepare-package.cjs");
163
+ assert.match(manifest.scripts.install, /npm_package_resolved/);
164
+ assert.match(manifest.scripts.install, /dist\/src\/cli\.js/);
165
+ assert.equal(manifest.scripts.prepack, "npm run build");
166
+ assert.equal(manifest.bin["agent-skills"], "./dist/src/cli.js");
167
+ });
168
+ //# sourceMappingURL=cli.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../../test/cli.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { resolveInstallTarget, resolveTargetRepo } from "../src/config.js";
4
+ test("target repository uses environment then current working directory", () => {
5
+ assert.equal(resolveTargetRepo({ cwd: "/work/project", env: { AGENT_SKILLS_REPO: "../central" } }), "/work/central");
6
+ assert.equal(resolveTargetRepo({ cwd: "/work/project", env: {} }), "/work/project");
7
+ });
8
+ test("install target resolves project and global skill directories", () => {
9
+ assert.equal(resolveInstallTarget({ cwd: "/work/project" }), "/work/project/.agents/skills");
10
+ assert.equal(resolveInstallTarget({ global: true, home: "/home/user" }), "/home/user/.agents/skills");
11
+ });
12
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../test/config.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,IAAI,CAAC,mEAAmE,EAAE,GAAG,EAAE;IAC7E,MAAM,CAAC,KAAK,CACV,iBAAiB,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,EAAE,iBAAiB,EAAE,YAAY,EAAE,EAAE,CAAC,EACrF,eAAe,CAChB,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;AACtF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8DAA8D,EAAE,GAAG,EAAE;IACxE,MAAM,CAAC,KAAK,CACV,oBAAoB,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE,CAAC,EAC9C,8BAA8B,CAC/B,CAAC;IACF,MAAM,CAAC,KAAK,CACV,oBAAoB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAC1D,2BAA2B,CAC5B,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+ import { discoverSkills, parseSource, resolveSource } from "../src/discovery.js";
7
+ function skill(path, name) {
8
+ mkdirSync(path, { recursive: true });
9
+ writeFileSync(join(path, "SKILL.md"), `---\nname: ${name}\ndescription: ${name} skill.\n---\n`);
10
+ }
11
+ test("source parser supports GitHub shorthand, tree URLs, git URLs, and local paths", () => {
12
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-source-"));
13
+ try {
14
+ assert.equal(parseSource("vercel-labs/skills").cloneUrl, "https://github.com/vercel-labs/skills.git");
15
+ assert.deepEqual(parseSource("https://github.com/acme/repo/tree/main/skills/demo"), {
16
+ type: "git",
17
+ normalized: "https://github.com/acme/repo.git",
18
+ cloneUrl: "https://github.com/acme/repo.git",
19
+ ref: "main",
20
+ directPath: "skills/demo"
21
+ });
22
+ assert.equal(parseSource("git@example.com:acme/repo.git").type, "git");
23
+ assert.equal(parseSource(root).type, "local");
24
+ }
25
+ finally {
26
+ rmSync(root, { recursive: true, force: true });
27
+ }
28
+ });
29
+ test("discovery uses standard containers, recursive fallback, and direct skill paths", () => {
30
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-discover-"));
31
+ try {
32
+ skill(join(root, "skills", "nested", "alpha"), "alpha");
33
+ skill(join(root, "skills", "beta"), "beta");
34
+ const source = resolveSource(root);
35
+ assert.deepEqual(discoverSkills(source).map((item) => [item.name, item.relativePath]), [["beta", "skills/beta"], ["alpha", "skills/nested/alpha"]]);
36
+ assert.deepEqual(discoverSkills({ ...source, directPath: "skills/beta" }).map((item) => item.name), ["beta"]);
37
+ }
38
+ finally {
39
+ rmSync(root, { recursive: true, force: true });
40
+ }
41
+ });
42
+ //# sourceMappingURL=discovery.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.test.js","sourceRoot":"","sources":["../../test/discovery.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,159 @@
1
+ import assert from "node:assert/strict";
2
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+ import { discoverSkills, resolveSource } from "../src/discovery.js";
7
+ import { discoverInstalledSkills, installSkills, uninstallSkills } from "../src/installer.js";
8
+ function createSkill(root, relativePath, name, body) {
9
+ const path = join(root, relativePath);
10
+ mkdirSync(path, { recursive: true });
11
+ writeFileSync(join(path, "SKILL.md"), `---\nname: ${name}\ndescription: ${name} skill.\n---\n\n${body}\n`);
12
+ }
13
+ test("install flattens nested skills and preserves unrelated destinations", () => {
14
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-install-"));
15
+ try {
16
+ const repo = join(root, "repo");
17
+ createSkill(repo, "skills/development/demo", "demo", "first");
18
+ createSkill(repo, "skills/productivity/notes", "notes", "notes");
19
+ const source = resolveSource(join(repo, "skills"));
20
+ const target = join(root, "project", ".agents", "skills");
21
+ createSkill(target, "custom", "custom", "custom");
22
+ const results = installSkills(target, discoverSkills(source));
23
+ assert.deepEqual(results.map((result) => [result.name, result.action]), [["demo", "added"], ["notes", "added"]]);
24
+ assert.ok(existsSync(join(target, "demo", "SKILL.md")));
25
+ assert.ok(existsSync(join(target, "notes", "SKILL.md")));
26
+ assert.ok(existsSync(join(target, "custom", "SKILL.md")));
27
+ }
28
+ finally {
29
+ rmSync(root, { recursive: true, force: true });
30
+ }
31
+ });
32
+ test("install atomically replaces selected existing skills", () => {
33
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-reinstall-"));
34
+ try {
35
+ const repo = join(root, "repo");
36
+ createSkill(repo, "skills/demo", "demo", "new");
37
+ const target = join(root, "target");
38
+ createSkill(target, "demo", "demo", "old");
39
+ writeFileSync(join(target, "demo", "stale.txt"), "stale");
40
+ const source = resolveSource(join(repo, "skills"));
41
+ const result = installSkills(target, discoverSkills(source))[0];
42
+ assert.equal(result.action, "updated");
43
+ assert.match(readFileSync(join(target, "demo", "SKILL.md"), "utf8"), /new/);
44
+ assert.equal(existsSync(join(target, "demo", "stale.txt")), false);
45
+ }
46
+ finally {
47
+ rmSync(root, { recursive: true, force: true });
48
+ }
49
+ });
50
+ test("install rejects duplicate skill names before writing", () => {
51
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-install-duplicates-"));
52
+ try {
53
+ const first = join(root, "first");
54
+ const second = join(root, "second");
55
+ createSkill(first, "demo", "demo", "first");
56
+ createSkill(second, "demo", "demo", "second");
57
+ const skills = [
58
+ { name: "demo", absolutePath: join(first, "demo"), relativePath: "first/demo" },
59
+ { name: "demo", absolutePath: join(second, "demo"), relativePath: "second/demo" }
60
+ ];
61
+ const target = join(root, "target");
62
+ assert.throws(() => installSkills(target, skills), /Duplicate skill name/);
63
+ assert.equal(existsSync(join(target, "demo")), false);
64
+ }
65
+ finally {
66
+ rmSync(root, { recursive: true, force: true });
67
+ }
68
+ });
69
+ test("installed skill discovery accepts only valid immediate directories", () => {
70
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-uninstall-discovery-"));
71
+ try {
72
+ const target = join(root, ".agents", "skills");
73
+ createSkill(target, "demo", "demo", "demo");
74
+ createSkill(target, "nested/notes", "notes", "notes");
75
+ mkdirSync(join(target, "invalid"), { recursive: true });
76
+ writeFileSync(join(target, "file.txt"), "unrelated");
77
+ symlinkSync(join(target, "demo"), join(target, "linked"));
78
+ assert.deepEqual(discoverInstalledSkills(target).map((skill) => skill.name), ["demo"]);
79
+ assert.deepEqual(discoverInstalledSkills(join(root, "missing")), []);
80
+ }
81
+ finally {
82
+ rmSync(root, { recursive: true, force: true });
83
+ }
84
+ });
85
+ test("uninstall removes selected skills and preserves other target entries", () => {
86
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-uninstall-selected-"));
87
+ try {
88
+ const target = join(root, ".agents", "skills");
89
+ createSkill(target, "demo", "demo", "demo");
90
+ createSkill(target, "notes", "notes", "notes");
91
+ writeFileSync(join(target, "unrelated.txt"), "keep");
92
+ const results = uninstallSkills(target, ["demo"]);
93
+ assert.deepEqual(results, [{
94
+ name: "demo",
95
+ action: "removed",
96
+ path: join(target, "demo")
97
+ }]);
98
+ assert.equal(existsSync(join(target, "demo")), false);
99
+ assert.ok(existsSync(join(target, "notes", "SKILL.md")));
100
+ assert.ok(existsSync(join(target, "unrelated.txt")));
101
+ assert.ok(existsSync(target));
102
+ }
103
+ finally {
104
+ rmSync(root, { recursive: true, force: true });
105
+ }
106
+ });
107
+ test("uninstall removes all discovered skills from a global target", () => {
108
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-uninstall-all-"));
109
+ try {
110
+ const target = join(root, "home", ".agents", "skills");
111
+ createSkill(target, "demo", "demo", "demo");
112
+ createSkill(target, "notes", "notes", "notes");
113
+ const names = discoverInstalledSkills(target).map((skill) => skill.name);
114
+ uninstallSkills(target, names);
115
+ assert.equal(discoverInstalledSkills(target).length, 0);
116
+ assert.ok(existsSync(target));
117
+ }
118
+ finally {
119
+ rmSync(root, { recursive: true, force: true });
120
+ }
121
+ });
122
+ test("uninstall reports every missing name before mutation", () => {
123
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-uninstall-missing-"));
124
+ try {
125
+ const target = join(root, "target");
126
+ createSkill(target, "demo", "demo", "demo");
127
+ assert.throws(() => uninstallSkills(target, ["demo", "missing", "also-missing"]), /missing, also-missing/);
128
+ assert.ok(existsSync(join(target, "demo", "SKILL.md")));
129
+ }
130
+ finally {
131
+ rmSync(root, { recursive: true, force: true });
132
+ }
133
+ });
134
+ test("uninstall restores moved skills when a transaction operation fails", () => {
135
+ const root = mkdtempSync(join(tmpdir(), "agent-skills-uninstall-rollback-"));
136
+ try {
137
+ const target = join(root, "target");
138
+ createSkill(target, "demo", "demo", "demo");
139
+ createSkill(target, "notes", "notes", "notes");
140
+ let moves = 0;
141
+ assert.throws(() => uninstallSkills(target, ["demo", "notes"], {
142
+ rename(source, destination) {
143
+ moves += 1;
144
+ if (moves === 2)
145
+ throw new Error("simulated failure");
146
+ renameSync(source, destination);
147
+ },
148
+ remove(path) {
149
+ rmSync(path, { recursive: true, force: true });
150
+ }
151
+ }), /simulated failure/);
152
+ assert.ok(existsSync(join(target, "demo", "SKILL.md")));
153
+ assert.ok(existsSync(join(target, "notes", "SKILL.md")));
154
+ }
155
+ finally {
156
+ rmSync(root, { recursive: true, force: true });
157
+ }
158
+ });
159
+ //# sourceMappingURL=installer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.test.js","sourceRoot":"","sources":["../../test/installer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};