@polyskill/cli 0.1.0

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 (59) hide show
  1. package/dist/__tests__/build.test.d.ts +2 -0
  2. package/dist/__tests__/build.test.d.ts.map +1 -0
  3. package/dist/__tests__/build.test.js +58 -0
  4. package/dist/__tests__/build.test.js.map +1 -0
  5. package/dist/__tests__/fixtures.d.ts +5 -0
  6. package/dist/__tests__/fixtures.d.ts.map +1 -0
  7. package/dist/__tests__/fixtures.js +51 -0
  8. package/dist/__tests__/fixtures.js.map +1 -0
  9. package/dist/__tests__/init.test.d.ts +2 -0
  10. package/dist/__tests__/init.test.d.ts.map +1 -0
  11. package/dist/__tests__/init.test.js +94 -0
  12. package/dist/__tests__/init.test.js.map +1 -0
  13. package/dist/__tests__/install.test.d.ts +2 -0
  14. package/dist/__tests__/install.test.d.ts.map +1 -0
  15. package/dist/__tests__/install.test.js +107 -0
  16. package/dist/__tests__/install.test.js.map +1 -0
  17. package/dist/__tests__/publish.test.d.ts +2 -0
  18. package/dist/__tests__/publish.test.d.ts.map +1 -0
  19. package/dist/__tests__/publish.test.js +102 -0
  20. package/dist/__tests__/publish.test.js.map +1 -0
  21. package/dist/__tests__/validate.test.d.ts +2 -0
  22. package/dist/__tests__/validate.test.d.ts.map +1 -0
  23. package/dist/__tests__/validate.test.js +45 -0
  24. package/dist/__tests__/validate.test.js.map +1 -0
  25. package/dist/commands/build.d.ts +3 -0
  26. package/dist/commands/build.d.ts.map +1 -0
  27. package/dist/commands/build.js +44 -0
  28. package/dist/commands/build.js.map +1 -0
  29. package/dist/commands/init.d.ts +3 -0
  30. package/dist/commands/init.d.ts.map +1 -0
  31. package/dist/commands/init.js +55 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/install.d.ts +3 -0
  34. package/dist/commands/install.d.ts.map +1 -0
  35. package/dist/commands/install.js +96 -0
  36. package/dist/commands/install.js.map +1 -0
  37. package/dist/commands/publish.d.ts +3 -0
  38. package/dist/commands/publish.d.ts.map +1 -0
  39. package/dist/commands/publish.js +80 -0
  40. package/dist/commands/publish.js.map +1 -0
  41. package/dist/commands/validate.d.ts +3 -0
  42. package/dist/commands/validate.d.ts.map +1 -0
  43. package/dist/commands/validate.js +19 -0
  44. package/dist/commands/validate.js.map +1 -0
  45. package/dist/config.d.ts +3 -0
  46. package/dist/config.d.ts.map +1 -0
  47. package/dist/config.js +3 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/index.d.ts +3 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +19 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/templates/instructions.md.template +1 -0
  54. package/dist/templates/skill.json.template +17 -0
  55. package/dist/templates/templates/instructions.md.template +1 -0
  56. package/dist/templates/templates/skill.json.template +17 -0
  57. package/dist/templates/templates/tools.json.template +18 -0
  58. package/dist/templates/tools.json.template +18 -0
  59. package/package.json +33 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=build.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/build.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ vi.mock("@skillstore/core", () => ({
3
+ loadSkill: vi.fn(),
4
+ getAdapter: vi.fn(),
5
+ }));
6
+ vi.mock("node:fs/promises", () => ({
7
+ writeFile: vi.fn(),
8
+ mkdir: vi.fn(),
9
+ }));
10
+ import { buildCommand } from "../commands/build.js";
11
+ import { loadSkill, getAdapter } from "@skillstore/core";
12
+ import { writeFile, mkdir } from "node:fs/promises";
13
+ import { mockSkill, mockTranspileResult } from "./fixtures.js";
14
+ beforeEach(() => {
15
+ vi.clearAllMocks();
16
+ vi.spyOn(console, "log").mockImplementation(() => { });
17
+ });
18
+ describe("build command", () => {
19
+ it("builds adapter outputs for each platform", async () => {
20
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
21
+ vi.mocked(getAdapter).mockReturnValue({
22
+ name: "openai",
23
+ transpile: vi.fn().mockReturnValue(mockTranspileResult),
24
+ });
25
+ await buildCommand.parseAsync(["/tmp/test-skill"], { from: "user" });
26
+ expect(mkdir).toHaveBeenCalledWith("/tmp/test-skill/dist", { recursive: true });
27
+ // 2 adapters in mockSkill.manifest: openai, anthropic
28
+ expect(writeFile).toHaveBeenCalledTimes(2);
29
+ expect(writeFile).toHaveBeenCalledWith("/tmp/test-skill/dist/openai.json", expect.any(String));
30
+ expect(writeFile).toHaveBeenCalledWith("/tmp/test-skill/dist/anthropic.json", expect.any(String));
31
+ });
32
+ it("skips unknown adapters with a warning", async () => {
33
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
34
+ vi.mocked(getAdapter)
35
+ .mockReturnValueOnce(null) // openai → unknown
36
+ .mockReturnValueOnce({
37
+ name: "anthropic",
38
+ transpile: vi.fn().mockReturnValue(mockTranspileResult),
39
+ });
40
+ await buildCommand.parseAsync(["/tmp/test-skill"], { from: "user" });
41
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Skipping unknown adapter"));
42
+ expect(writeFile).toHaveBeenCalledTimes(1);
43
+ });
44
+ it("creates dist directory with recursive flag", async () => {
45
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
46
+ vi.mocked(getAdapter).mockReturnValue({
47
+ name: "openai",
48
+ transpile: vi.fn().mockReturnValue(mockTranspileResult),
49
+ });
50
+ await buildCommand.parseAsync(["/tmp/test-skill"], { from: "user" });
51
+ expect(mkdir).toHaveBeenCalledWith(expect.stringContaining("dist"), { recursive: true });
52
+ });
53
+ it("propagates loadSkill errors", async () => {
54
+ vi.mocked(loadSkill).mockRejectedValue(new Error("Missing skill.json"));
55
+ await expect(buildCommand.parseAsync(["/tmp/bad-skill"], { from: "user" })).rejects.toThrow("Missing skill.json");
56
+ });
57
+ });
58
+ //# sourceMappingURL=build.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.test.js","sourceRoot":"","sources":["../../src/__tests__/build.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { SkillManifest, SkillDefinition, TranspileResult } from "@skillstore/core";
2
+ export declare const mockManifest: SkillManifest;
3
+ export declare const mockSkill: SkillDefinition;
4
+ export declare const mockTranspileResult: TranspileResult;
5
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/__tests__/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExF,eAAO,MAAM,YAAY,EAAE,aAY1B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,eAgBvB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,eAmBjC,CAAC"}
@@ -0,0 +1,51 @@
1
+ export const mockManifest = {
2
+ name: "@test/my-skill",
3
+ version: "1.0.0",
4
+ description: "A test skill",
5
+ type: "tool",
6
+ license: "MIT",
7
+ author: { name: "Test Author" },
8
+ skill: {
9
+ instructions: "./instructions.md",
10
+ tools: "./tools.json",
11
+ },
12
+ adapters: ["openai", "anthropic"],
13
+ };
14
+ export const mockSkill = {
15
+ manifest: mockManifest,
16
+ tools: [
17
+ {
18
+ name: "test_tool",
19
+ description: "A test tool",
20
+ parameters: {
21
+ type: "object",
22
+ properties: {
23
+ input: { type: "string", description: "Test input" },
24
+ },
25
+ required: ["input"],
26
+ },
27
+ },
28
+ ],
29
+ instructions: "You are a test assistant.",
30
+ };
31
+ export const mockTranspileResult = {
32
+ platform: "openai",
33
+ systemPrompt: "You are a test assistant.",
34
+ tools: [
35
+ {
36
+ type: "function",
37
+ function: {
38
+ name: "test_tool",
39
+ description: "A test tool",
40
+ parameters: {
41
+ type: "object",
42
+ properties: {
43
+ input: { type: "string", description: "Test input" },
44
+ },
45
+ required: ["input"],
46
+ },
47
+ },
48
+ },
49
+ ],
50
+ };
51
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/__tests__/fixtures.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,cAAc;IAC3B,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE;IAC/B,KAAK,EAAE;QACL,YAAY,EAAE,mBAAmB;QACjC,KAAK,EAAE,cAAc;KACtB;IACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;CAClC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAoB;IACxC,QAAQ,EAAE,YAAY;IACtB,KAAK,EAAE;QACL;YACE,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,aAAa;YAC1B,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE;iBACrD;gBACD,QAAQ,EAAE,CAAC,OAAO,CAAC;aACpB;SACF;KACF;IACD,YAAY,EAAE,2BAA2B;CAC1C,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAoB;IAClD,QAAQ,EAAE,QAAQ;IAClB,YAAY,EAAE,2BAA2B;IACzC,KAAK,EAAE;QACL;YACE,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE;gBACR,IAAI,EAAE,WAAW;gBACjB,WAAW,EAAE,aAAa;gBAC1B,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE;qBACrD;oBACD,QAAQ,EAAE,CAAC,OAAO,CAAC;iBACpB;aACF;SACF;KACF;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=init.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/init.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,94 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ vi.mock("@inquirer/prompts", () => ({
3
+ input: vi.fn(),
4
+ }));
5
+ vi.mock("node:fs/promises", () => ({
6
+ readFile: vi.fn(),
7
+ writeFile: vi.fn(),
8
+ mkdir: vi.fn(),
9
+ }));
10
+ import { initCommand } from "../commands/init.js";
11
+ import { input } from "@inquirer/prompts";
12
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
13
+ beforeEach(() => {
14
+ vi.clearAllMocks();
15
+ vi.spyOn(console, "log").mockImplementation(() => { });
16
+ });
17
+ describe("init command", () => {
18
+ it("scaffolds a skill with all template files", async () => {
19
+ vi.mocked(input)
20
+ .mockResolvedValueOnce("@test/my-skill") // name
21
+ .mockResolvedValueOnce("A test skill") // description
22
+ .mockResolvedValueOnce("Test Author"); // author
23
+ vi.mocked(readFile)
24
+ .mockResolvedValueOnce('{"name":"{{name}}","description":"{{description}}","author":{"name":"{{authorName}}"}}')
25
+ .mockResolvedValueOnce('{"tools":[]}')
26
+ .mockResolvedValueOnce("# Instructions");
27
+ await initCommand.parseAsync(["/tmp/new-skill"], { from: "user" });
28
+ expect(mkdir).toHaveBeenCalledWith("/tmp/new-skill", { recursive: true });
29
+ expect(writeFile).toHaveBeenCalledTimes(3);
30
+ // skill.json should have variables substituted
31
+ const skillJsonCall = vi.mocked(writeFile).mock.calls.find((c) => c[0].endsWith("skill.json"));
32
+ expect(skillJsonCall).toBeDefined();
33
+ expect(skillJsonCall[1]).toContain("@test/my-skill");
34
+ expect(skillJsonCall[1]).toContain("A test skill");
35
+ expect(skillJsonCall[1]).toContain("Test Author");
36
+ });
37
+ it("creates target directory with recursive flag", async () => {
38
+ vi.mocked(input)
39
+ .mockResolvedValueOnce("@test/my-skill")
40
+ .mockResolvedValueOnce("A test skill")
41
+ .mockResolvedValueOnce("Test Author");
42
+ vi.mocked(readFile)
43
+ .mockResolvedValueOnce("{}")
44
+ .mockResolvedValueOnce("{}")
45
+ .mockResolvedValueOnce("");
46
+ await initCommand.parseAsync(["/tmp/nested/dir"], { from: "user" });
47
+ expect(mkdir).toHaveBeenCalledWith("/tmp/nested/dir", { recursive: true });
48
+ });
49
+ it("validates skill name must be scoped format", async () => {
50
+ // Extract the validate function from the first input() call
51
+ vi.mocked(input).mockImplementation(async (opts) => {
52
+ if (opts.message.includes("Skill name")) {
53
+ // Test the validate function
54
+ const validate = opts.validate;
55
+ expect(validate("@scope/name")).toBe(true);
56
+ expect(validate("bad-name")).toBe("Must be scoped: @scope/name (lowercase, hyphens)");
57
+ expect(validate("@UPPER/case")).toBe("Must be scoped: @scope/name (lowercase, hyphens)");
58
+ return "@test/my-skill";
59
+ }
60
+ return "placeholder";
61
+ });
62
+ vi.mocked(readFile).mockResolvedValue("{}");
63
+ await initCommand.parseAsync(["/tmp/test"], { from: "user" });
64
+ });
65
+ it("validates description is not empty", async () => {
66
+ vi.mocked(input).mockImplementation(async (opts) => {
67
+ if (opts.message.includes("Description")) {
68
+ const validate = opts.validate;
69
+ expect(validate("")).toBe("Description is required");
70
+ expect(validate("Valid description")).toBe(true);
71
+ return "A description";
72
+ }
73
+ return "@test/my-skill";
74
+ });
75
+ vi.mocked(readFile).mockResolvedValue("{}");
76
+ await initCommand.parseAsync(["/tmp/test"], { from: "user" });
77
+ });
78
+ it("writes tools.json and instructions.md without variable substitution", async () => {
79
+ vi.mocked(input)
80
+ .mockResolvedValueOnce("@test/my-skill")
81
+ .mockResolvedValueOnce("A test skill")
82
+ .mockResolvedValueOnce("Test Author");
83
+ vi.mocked(readFile)
84
+ .mockResolvedValueOnce('{"name":"{{name}}"}') // skill.json template
85
+ .mockResolvedValueOnce('{"tools":[]}') // tools.json template
86
+ .mockResolvedValueOnce("# Instructions template"); // instructions.md template
87
+ await initCommand.parseAsync(["/tmp/test"], { from: "user" });
88
+ const toolsCall = vi.mocked(writeFile).mock.calls.find((c) => c[0].endsWith("tools.json"));
89
+ expect(toolsCall[1]).toBe('{"tools":[]}');
90
+ const instructionsCall = vi.mocked(writeFile).mock.calls.find((c) => c[0].endsWith("instructions.md"));
91
+ expect(instructionsCall[1]).toBe("# Instructions template");
92
+ });
93
+ });
94
+ //# sourceMappingURL=init.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.test.js","sourceRoot":"","sources":["../../src/__tests__/init.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=install.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/install.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ vi.mock("node:fs/promises", () => ({
3
+ writeFile: vi.fn(),
4
+ mkdir: vi.fn(),
5
+ }));
6
+ vi.mock("../config.js", () => ({
7
+ REGISTRY_URL: "http://localhost:3000",
8
+ }));
9
+ import { installCommand } from "../commands/install.js";
10
+ import { writeFile, mkdir } from "node:fs/promises";
11
+ class ExitError extends Error {
12
+ code;
13
+ constructor(code) {
14
+ super(`process.exit(${code})`);
15
+ this.code = code;
16
+ }
17
+ }
18
+ beforeEach(() => {
19
+ vi.clearAllMocks();
20
+ vi.spyOn(console, "log").mockImplementation(() => { });
21
+ vi.spyOn(process, "exit").mockImplementation((code) => {
22
+ throw new ExitError(code);
23
+ });
24
+ vi.stubGlobal("fetch", vi.fn());
25
+ });
26
+ const fullSkillResponse = {
27
+ name: "@test/my-skill",
28
+ version: "1.0.0",
29
+ manifest: { name: "@test/my-skill", version: "1.0.0" },
30
+ tools: { tools: [{ name: "test_tool" }] },
31
+ instructions: "You are a test assistant.",
32
+ adapters: { openai: { platform: "openai" } },
33
+ verified: true,
34
+ };
35
+ function mockFetchResponse(status, body) {
36
+ vi.mocked(fetch).mockResolvedValue({
37
+ ok: status >= 200 && status < 300,
38
+ status,
39
+ statusText: status === 404 ? "Not Found" : "Internal Server Error",
40
+ json: () => Promise.resolve(body),
41
+ });
42
+ }
43
+ describe("install command", () => {
44
+ it("writes all files when skill has tools, instructions, and adapters", async () => {
45
+ mockFetchResponse(200, fullSkillResponse);
46
+ await installCommand.parseAsync(["@test/my-skill", "--output", "/tmp/output"], { from: "user" });
47
+ // skill.json
48
+ expect(writeFile).toHaveBeenCalledWith(expect.stringContaining("skill.json"), expect.any(String));
49
+ // tools.json
50
+ expect(writeFile).toHaveBeenCalledWith(expect.stringContaining("tools.json"), expect.any(String));
51
+ // instructions.md
52
+ expect(writeFile).toHaveBeenCalledWith(expect.stringContaining("instructions.md"), "You are a test assistant.");
53
+ // adapter output in dist/
54
+ expect(writeFile).toHaveBeenCalledWith(expect.stringContaining("dist/openai.json"), expect.any(String));
55
+ // dist directory created
56
+ expect(mkdir).toHaveBeenCalledWith(expect.stringContaining("dist"), { recursive: true });
57
+ });
58
+ it("writes only skill.json when skill has no tools/instructions/adapters", async () => {
59
+ mockFetchResponse(200, {
60
+ name: "@test/minimal",
61
+ version: "1.0.0",
62
+ manifest: { name: "@test/minimal" },
63
+ tools: null,
64
+ instructions: null,
65
+ adapters: null,
66
+ verified: true,
67
+ });
68
+ await installCommand.parseAsync(["@test/minimal", "--output", "/tmp/output"], { from: "user" });
69
+ // Only skill.json should be written
70
+ expect(writeFile).toHaveBeenCalledTimes(1);
71
+ expect(writeFile).toHaveBeenCalledWith(expect.stringContaining("skill.json"), expect.any(String));
72
+ });
73
+ it("shows green badge for verified skills", async () => {
74
+ mockFetchResponse(200, { ...fullSkillResponse, verified: true });
75
+ await installCommand.parseAsync(["@test/my-skill", "--output", "/tmp/output"], { from: "user" });
76
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("verified"));
77
+ // Should NOT print the unverified warning
78
+ const calls = vi.mocked(console.log).mock.calls.map((c) => String(c[0]));
79
+ const warningCall = calls.find((c) => c.includes("Warning"));
80
+ expect(warningCall).toBeUndefined();
81
+ });
82
+ it("shows yellow badge and warning for unverified skills", async () => {
83
+ mockFetchResponse(200, { ...fullSkillResponse, verified: false });
84
+ await installCommand.parseAsync(["@test/my-skill", "--output", "/tmp/output"], { from: "user" });
85
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("unverified"));
86
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Warning"));
87
+ });
88
+ it("prints error and exits on 404", async () => {
89
+ mockFetchResponse(404, {});
90
+ await expect(installCommand.parseAsync(["@test/nonexistent", "--output", "/tmp/output"], { from: "user" })).rejects.toThrow(ExitError);
91
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Skill not found"));
92
+ expect(process.exit).toHaveBeenCalledWith(1);
93
+ });
94
+ it("prints error and exits on 500", async () => {
95
+ mockFetchResponse(500, {});
96
+ await expect(installCommand.parseAsync(["@test/my-skill", "--output", "/tmp/output"], { from: "user" })).rejects.toThrow(ExitError);
97
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Failed to fetch"));
98
+ expect(process.exit).toHaveBeenCalledWith(1);
99
+ });
100
+ it("creates directory with scoped name replacing / with __", async () => {
101
+ mockFetchResponse(200, fullSkillResponse);
102
+ await installCommand.parseAsync(["@test/my-skill", "--output", "/tmp/output"], { from: "user" });
103
+ // Should create skills/@test__my-skill directory
104
+ expect(mkdir).toHaveBeenCalledWith(expect.stringContaining("@test__my-skill"), { recursive: true });
105
+ });
106
+ });
107
+ //# sourceMappingURL=install.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.test.js","sourceRoot":"","sources":["../../src/__tests__/install.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=publish.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/publish.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,102 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ vi.mock("@skillstore/core", () => ({
3
+ loadSkill: vi.fn(),
4
+ getAdapter: vi.fn(),
5
+ }));
6
+ vi.mock("../config.js", () => ({
7
+ REGISTRY_URL: "http://localhost:3000",
8
+ }));
9
+ import { publishCommand } from "../commands/publish.js";
10
+ import { loadSkill, getAdapter } from "@skillstore/core";
11
+ import { mockSkill, mockTranspileResult } from "./fixtures.js";
12
+ class ExitError extends Error {
13
+ code;
14
+ constructor(code) {
15
+ super(`process.exit(${code})`);
16
+ this.code = code;
17
+ }
18
+ }
19
+ beforeEach(() => {
20
+ vi.clearAllMocks();
21
+ vi.spyOn(console, "log").mockImplementation(() => { });
22
+ vi.spyOn(process, "exit").mockImplementation((code) => {
23
+ throw new ExitError(code);
24
+ });
25
+ vi.stubGlobal("fetch", vi.fn());
26
+ });
27
+ function mockFetchResponse(status, body) {
28
+ vi.mocked(fetch).mockResolvedValue({
29
+ ok: status >= 200 && status < 300,
30
+ status,
31
+ statusText: status === 500 ? "Internal Server Error" : "Error",
32
+ json: () => Promise.resolve(body),
33
+ });
34
+ }
35
+ describe("publish command", () => {
36
+ it("prints success on 201 response", async () => {
37
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
38
+ vi.mocked(getAdapter).mockReturnValue({
39
+ name: "openai",
40
+ transpile: vi.fn().mockReturnValue(mockTranspileResult),
41
+ });
42
+ mockFetchResponse(201, { id: "test-uuid" });
43
+ await publishCommand.parseAsync(["/tmp/test-skill"], { from: "user" });
44
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Published @test/my-skill@1.0.0"));
45
+ expect(process.exit).not.toHaveBeenCalled();
46
+ });
47
+ it("prints error and exits on 409 conflict", async () => {
48
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
49
+ vi.mocked(getAdapter).mockReturnValue(null);
50
+ mockFetchResponse(409, { error: "Conflict", message: "Version already exists" });
51
+ await expect(publishCommand.parseAsync(["/tmp/test-skill"], { from: "user" })).rejects.toThrow(ExitError);
52
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Publish failed"));
53
+ expect(process.exit).toHaveBeenCalledWith(1);
54
+ });
55
+ it("prints details array on 400 response", async () => {
56
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
57
+ vi.mocked(getAdapter).mockReturnValue(null);
58
+ mockFetchResponse(400, {
59
+ error: "Bad Request",
60
+ message: "Invalid manifest",
61
+ details: ["missing name", "missing version"],
62
+ });
63
+ await expect(publishCommand.parseAsync(["/tmp/test-skill"], { from: "user" })).rejects.toThrow(ExitError);
64
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("missing name"));
65
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("missing version"));
66
+ expect(process.exit).toHaveBeenCalledWith(1);
67
+ });
68
+ it("prints error and exits on 500 response", async () => {
69
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
70
+ vi.mocked(getAdapter).mockReturnValue(null);
71
+ mockFetchResponse(500, { message: "Internal Server Error" });
72
+ await expect(publishCommand.parseAsync(["/tmp/test-skill"], { from: "user" })).rejects.toThrow(ExitError);
73
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Publish failed"));
74
+ expect(process.exit).toHaveBeenCalledWith(1);
75
+ });
76
+ it("sends correct request body to registry", async () => {
77
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
78
+ vi.mocked(getAdapter).mockReturnValue({
79
+ name: "openai",
80
+ transpile: vi.fn().mockReturnValue(mockTranspileResult),
81
+ });
82
+ mockFetchResponse(201, { id: "test-uuid" });
83
+ await publishCommand.parseAsync(["/tmp/test-skill"], { from: "user" });
84
+ expect(fetch).toHaveBeenCalledWith("http://localhost:3000/api/skills", expect.objectContaining({
85
+ method: "POST",
86
+ headers: { "Content-Type": "application/json" },
87
+ }));
88
+ const callBody = JSON.parse(vi.mocked(fetch).mock.calls[0][1].body);
89
+ expect(callBody.manifest).toEqual(mockSkill.manifest);
90
+ expect(callBody.tools).toEqual({ tools: mockSkill.tools });
91
+ expect(callBody.instructions).toBe("You are a test assistant.");
92
+ expect(callBody.adapters).toBeDefined();
93
+ });
94
+ it("prints error and exits when loadSkill fails", async () => {
95
+ vi.mocked(loadSkill).mockRejectedValue(new Error("File not found"));
96
+ await expect(publishCommand.parseAsync(["/tmp/bad-skill"], { from: "user" })).rejects.toThrow(ExitError);
97
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("File not found"));
98
+ expect(process.exit).toHaveBeenCalledWith(1);
99
+ expect(fetch).not.toHaveBeenCalled();
100
+ });
101
+ });
102
+ //# sourceMappingURL=publish.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.test.js","sourceRoot":"","sources":["../../src/__tests__/publish.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ vi.mock("@skillstore/core", () => ({
3
+ loadSkill: vi.fn(),
4
+ }));
5
+ import { validateCommand } from "../commands/validate.js";
6
+ import { loadSkill } from "@skillstore/core";
7
+ import { mockSkill } from "./fixtures.js";
8
+ class ExitError extends Error {
9
+ code;
10
+ constructor(code) {
11
+ super(`process.exit(${code})`);
12
+ this.code = code;
13
+ }
14
+ }
15
+ beforeEach(() => {
16
+ vi.clearAllMocks();
17
+ vi.spyOn(console, "log").mockImplementation(() => { });
18
+ vi.spyOn(process, "exit").mockImplementation((code) => {
19
+ throw new ExitError(code);
20
+ });
21
+ });
22
+ describe("validate command", () => {
23
+ it("prints success when loadSkill resolves", async () => {
24
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
25
+ await validateCommand.parseAsync(["/tmp/test-skill"], { from: "user" });
26
+ expect(loadSkill).toHaveBeenCalledWith("/tmp/test-skill");
27
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("All checks passed"));
28
+ expect(process.exit).not.toHaveBeenCalled();
29
+ });
30
+ it("prints error and exits when loadSkill throws", async () => {
31
+ vi.mocked(loadSkill).mockRejectedValue(new Error("Invalid manifest"));
32
+ await expect(validateCommand.parseAsync(["/tmp/bad-skill"], { from: "user" })).rejects.toThrow(ExitError);
33
+ expect(console.log).toHaveBeenCalledWith(expect.stringContaining("Invalid manifest"));
34
+ expect(process.exit).toHaveBeenCalledWith(1);
35
+ });
36
+ it("resolves relative directory to absolute path", async () => {
37
+ vi.mocked(loadSkill).mockResolvedValue(mockSkill);
38
+ await validateCommand.parseAsync(["my-skill"], { from: "user" });
39
+ const calledWith = vi.mocked(loadSkill).mock.calls[0][0];
40
+ // Should be an absolute path, not "my-skill"
41
+ expect(calledWith).toMatch(/^\//);
42
+ expect(calledWith).toContain("my-skill");
43
+ });
44
+ });
45
+ //# sourceMappingURL=validate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.js","sourceRoot":"","sources":["../../src/__tests__/validate.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const buildCommand: Command;
3
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,YAAY,SAmCrB,CAAC"}
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Build flow state machine:
3
+ *
4
+ * LOAD_SKILL ──→ CREATE_DIST ──→ TRANSPILE_EACH ──→ SUCCESS
5
+ * │ │ │
6
+ * ▼ ▼ ▼
7
+ * LOAD_ERR DIR_ERR WRITE_ERR
8
+ */
9
+ import { Command } from "commander";
10
+ import { writeFile, mkdir } from "node:fs/promises";
11
+ import { join, resolve } from "node:path";
12
+ import chalk from "chalk";
13
+ import { loadSkill, getAdapter } from "@polyskill/core";
14
+ export const buildCommand = new Command("build")
15
+ .description("Build platform-specific adapter outputs")
16
+ .argument("[directory]", "Skill directory to build", ".")
17
+ .action(async (directory) => {
18
+ const skillDir = resolve(process.cwd(), directory);
19
+ console.log(chalk.bold("\nBuilding skill..."));
20
+ try {
21
+ // Load and validate skill
22
+ const skill = await loadSkill(skillDir);
23
+ const distDir = join(skillDir, "dist");
24
+ await mkdir(distDir, { recursive: true });
25
+ const adapters = skill.manifest.adapters;
26
+ for (const platform of adapters) {
27
+ const adapter = getAdapter(platform);
28
+ if (!adapter) {
29
+ console.log(chalk.yellow(` Skipping unknown adapter: ${platform}`));
30
+ continue;
31
+ }
32
+ const result = adapter.transpile(skill);
33
+ const outputPath = join(distDir, `${platform}.json`);
34
+ await writeFile(outputPath, JSON.stringify(result, null, 2));
35
+ console.log(chalk.green(` Built ${platform} → ${outputPath}`));
36
+ }
37
+ console.log(chalk.green("\nBuild complete.\n"));
38
+ }
39
+ catch (err) {
40
+ console.log(chalk.red(`\n${err.message}\n`));
41
+ process.exit(1);
42
+ }
43
+ });
44
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,yCAAyC,CAAC;KACtD,QAAQ,CAAC,aAAa,EAAE,0BAA0B,EAAE,GAAG,CAAC;KACxD,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,EAAE;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IAEnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAE/C,IAAI,CAAC;QACH,0BAA0B;QAC1B,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACzC,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;YACrC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,+BAA+B,QAAQ,EAAE,CAAC,CACxD,CAAC;gBACF,SAAS;YACX,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACxC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;YACrD,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,QAAQ,MAAM,UAAU,EAAE,CAAC,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const initCommand: Command;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBpC,eAAO,MAAM,WAAW,SAkDpB,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { Command } from "commander";
2
+ import { input } from "@inquirer/prompts";
3
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
4
+ import { join, dirname, resolve } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import chalk from "chalk";
7
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
+ const templatesDir = join(__dirname, "..", "templates");
9
+ async function loadTemplate(name) {
10
+ return readFile(join(templatesDir, `${name}.template`), "utf-8");
11
+ }
12
+ function fillTemplate(template, vars) {
13
+ let result = template;
14
+ for (const [key, value] of Object.entries(vars)) {
15
+ result = result.replaceAll(`{{${key}}}`, value);
16
+ }
17
+ return result;
18
+ }
19
+ export const initCommand = new Command("init")
20
+ .description("Scaffold a new Skill project")
21
+ .argument("[directory]", "Directory to create the skill in", ".")
22
+ .action(async (directory) => {
23
+ console.log(chalk.bold("\nSkillStore — Create a new Skill\n"));
24
+ const skillName = await input({
25
+ message: "Skill name (e.g. @yourname/my-skill):",
26
+ validate: (val) => /^@[a-z0-9-]+\/[a-z0-9-]+$/.test(val) ||
27
+ "Must be scoped: @scope/name (lowercase, hyphens)",
28
+ });
29
+ const description = await input({
30
+ message: "Description:",
31
+ validate: (val) => val.length > 0 || "Description is required",
32
+ });
33
+ const authorName = await input({
34
+ message: "Author name:",
35
+ validate: (val) => val.length > 0 || "Author name is required",
36
+ });
37
+ const targetDir = resolve(process.cwd(), directory);
38
+ await mkdir(targetDir, { recursive: true });
39
+ const vars = { name: skillName, description, authorName };
40
+ // Write skill.json
41
+ const manifestTemplate = await loadTemplate("skill.json");
42
+ await writeFile(join(targetDir, "skill.json"), fillTemplate(manifestTemplate, vars));
43
+ // Write tools.json
44
+ const toolsTemplate = await loadTemplate("tools.json");
45
+ await writeFile(join(targetDir, "tools.json"), toolsTemplate);
46
+ // Write instructions.md
47
+ const instructionsTemplate = await loadTemplate("instructions.md");
48
+ await writeFile(join(targetDir, "instructions.md"), instructionsTemplate);
49
+ console.log(chalk.green("\nSkill scaffolded successfully!"));
50
+ console.log(` ${chalk.dim(join(targetDir, "skill.json"))}`);
51
+ console.log(` ${chalk.dim(join(targetDir, "tools.json"))}`);
52
+ console.log(` ${chalk.dim(join(targetDir, "instructions.md"))}`);
53
+ console.log(`\nNext steps:\n 1. Edit tools.json with your tool definitions\n 2. Edit instructions.md with your system prompt\n 3. Run ${chalk.cyan("skillstore validate")} to check\n 4. Run ${chalk.cyan("skillstore build")} to generate adapters\n`);
54
+ });
55
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const installCommand: Command;
3
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,cAAc,SA2GxB,CAAC"}
@@ -0,0 +1,96 @@
1
+ /*
2
+ * Install flow state machine:
3
+ *
4
+ * FETCH_REGISTRY ──→ CREATE_DIRS ──→ WRITE_FILES ──→ SUCCESS
5
+ * │
6
+ * ├──→ NOT_FOUND / HTTP_ERR
7
+ * │
8
+ * ▼
9
+ * NETWORK_ERR (DNS / timeout / refused)
10
+ */
11
+ import { Command } from "commander";
12
+ import { writeFile, mkdir } from "node:fs/promises";
13
+ import { join, resolve } from "node:path";
14
+ import chalk from "chalk";
15
+ import { REGISTRY_URL } from "../config.js";
16
+ export const installCommand = new Command("install")
17
+ .description("Install a Skill from the SkillStore registry")
18
+ .argument("<name>", "Skill name (e.g. @author/skill-name)")
19
+ .argument("[version]", "Specific version (defaults to latest)")
20
+ .option("--registry <url>", "Registry URL", REGISTRY_URL)
21
+ .option("-o, --output <dir>", "Output directory", ".")
22
+ .action(async (name, version, options) => {
23
+ const registryUrl = options.registry;
24
+ const outputDir = resolve(process.cwd(), options.output);
25
+ console.log(chalk.bold(`\nInstalling ${name}${version ? `@${version}` : ""}...`));
26
+ // Fetch from registry
27
+ const encodedName = encodeURIComponent(name);
28
+ const url = version
29
+ ? `${registryUrl}/api/skills/${encodedName}/${version}`
30
+ : `${registryUrl}/api/skills/${encodedName}`;
31
+ let res;
32
+ try {
33
+ res = await fetch(url, { signal: AbortSignal.timeout(30_000) });
34
+ }
35
+ catch (err) {
36
+ const msg = err.name === "TimeoutError"
37
+ ? "Request timed out — is the registry running?"
38
+ : `Network error: ${err.message}`;
39
+ console.log(chalk.red(`\n${msg}\n`));
40
+ process.exit(1);
41
+ }
42
+ if (!res.ok) {
43
+ if (res.status === 404) {
44
+ console.log(chalk.red(`\nSkill not found: ${name}`));
45
+ }
46
+ else {
47
+ console.log(chalk.red(`\nFailed to fetch skill: ${res.statusText}`));
48
+ }
49
+ process.exit(1);
50
+ }
51
+ const skill = (await res.json());
52
+ // Track download (fire-and-forget for the user, but await for correctness)
53
+ try {
54
+ await fetch(`${registryUrl}/api/skills/${encodedName}/download`, {
55
+ method: "POST",
56
+ signal: AbortSignal.timeout(5_000),
57
+ });
58
+ }
59
+ catch (_) {
60
+ // Non-critical — don't block the install
61
+ }
62
+ // Create skill directory
63
+ const skillDir = join(outputDir, "skills", skill.name.replaceAll("/", "__"));
64
+ await mkdir(skillDir, { recursive: true });
65
+ // Write manifest
66
+ await writeFile(join(skillDir, "skill.json"), JSON.stringify(skill.manifest, null, 2));
67
+ // Write tools if present
68
+ if (skill.tools) {
69
+ await writeFile(join(skillDir, "tools.json"), JSON.stringify(skill.tools, null, 2));
70
+ }
71
+ // Write instructions if present
72
+ if (skill.instructions) {
73
+ await writeFile(join(skillDir, "instructions.md"), skill.instructions);
74
+ }
75
+ // Write adapter outputs
76
+ const adapterEntries = skill.adapters && typeof skill.adapters === "object"
77
+ ? Object.entries(skill.adapters)
78
+ : [];
79
+ if (adapterEntries.length > 0) {
80
+ const distDir = join(skillDir, "dist");
81
+ await mkdir(distDir, { recursive: true });
82
+ for (const [platform, output] of adapterEntries) {
83
+ await writeFile(join(distDir, `${platform}.json`), JSON.stringify(output, null, 2));
84
+ }
85
+ }
86
+ const badge = skill.verified
87
+ ? chalk.green("[verified]")
88
+ : chalk.yellow("[unverified]");
89
+ console.log(chalk.green(`\nInstalled ${skill.name}@${skill.version}`) + ` ${badge}`);
90
+ if (!skill.verified) {
91
+ console.log(chalk.yellow(" Warning: This skill has not been verified"));
92
+ }
93
+ console.log(chalk.dim(` Location: ${skillDir}`));
94
+ console.log();
95
+ });
96
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const publishCommand: Command;
3
+ //# sourceMappingURL=publish.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,cAAc,SA8EvB,CAAC"}
@@ -0,0 +1,80 @@
1
+ /*
2
+ * Publish flow state machine:
3
+ *
4
+ * LOAD_SKILL ──→ BUILD_ADAPTERS ──→ POST_REGISTRY ──→ SUCCESS
5
+ * │ │
6
+ * ▼ ├──→ HTTP_ERR (409 / 400 / 5xx)
7
+ * LOAD_ERR │
8
+ * ▼
9
+ * NETWORK_ERR (DNS / timeout / refused)
10
+ */
11
+ import { Command } from "commander";
12
+ import { resolve } from "node:path";
13
+ import chalk from "chalk";
14
+ import { loadSkill, getAdapter } from "@polyskill/core";
15
+ import { REGISTRY_URL } from "../config.js";
16
+ export const publishCommand = new Command("publish")
17
+ .description("Publish a Skill to the SkillStore registry")
18
+ .argument("[directory]", "Skill directory to publish", ".")
19
+ .option("--registry <url>", "Registry URL", REGISTRY_URL)
20
+ .action(async (directory, options) => {
21
+ const skillDir = resolve(process.cwd(), directory);
22
+ const registryUrl = options.registry;
23
+ console.log(chalk.bold("\nPublishing skill..."));
24
+ // Load and validate skill
25
+ let skill;
26
+ try {
27
+ skill = await loadSkill(skillDir);
28
+ }
29
+ catch (err) {
30
+ console.log(chalk.red(`\n${err.message}\n`));
31
+ process.exit(1);
32
+ }
33
+ // Build adapter outputs
34
+ const adapters = {};
35
+ for (const platform of skill.manifest.adapters) {
36
+ const adapter = getAdapter(platform);
37
+ if (adapter) {
38
+ adapters[platform] = adapter.transpile(skill);
39
+ }
40
+ }
41
+ // Publish to registry
42
+ const body = {
43
+ manifest: skill.manifest,
44
+ tools: skill.tools.length > 0 ? { tools: skill.tools } : null,
45
+ instructions: skill.instructions,
46
+ adapters,
47
+ };
48
+ let res;
49
+ try {
50
+ res = await fetch(`${registryUrl}/api/skills`, {
51
+ method: "POST",
52
+ headers: { "Content-Type": "application/json" },
53
+ body: JSON.stringify(body),
54
+ signal: AbortSignal.timeout(30_000),
55
+ });
56
+ }
57
+ catch (err) {
58
+ const msg = err.name === "TimeoutError"
59
+ ? "Request timed out — is the registry running?"
60
+ : `Network error: ${err.message}`;
61
+ console.log(chalk.red(`\n${msg}\n`));
62
+ process.exit(1);
63
+ }
64
+ if (!res.ok) {
65
+ const error = await res.json().catch(() => ({ message: res.statusText }));
66
+ console.log(chalk.red(`\nPublish failed: ${error.error || error.message}`));
67
+ if (error.details) {
68
+ for (const detail of error.details) {
69
+ console.log(chalk.red(` - ${detail}`));
70
+ }
71
+ }
72
+ process.exit(1);
73
+ }
74
+ const result = await res.json();
75
+ console.log(chalk.green(`\nPublished ${skill.manifest.name}@${skill.manifest.version}`));
76
+ console.log(chalk.dim(` ID: ${result.id}`));
77
+ console.log(chalk.dim(` Registry: ${registryUrl}`));
78
+ console.log(`\nInstall with: ${chalk.cyan(`skillstore install ${skill.manifest.name}`)}\n`);
79
+ });
80
+ //# sourceMappingURL=publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const validateCommand: Command;
3
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,eAAe,SAaxB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { Command } from "commander";
2
+ import { resolve } from "node:path";
3
+ import chalk from "chalk";
4
+ import { loadSkill } from "@polyskill/core";
5
+ export const validateCommand = new Command("validate")
6
+ .description("Validate a Skill project")
7
+ .argument("[directory]", "Skill directory to validate", ".")
8
+ .action(async (directory) => {
9
+ const skillDir = resolve(process.cwd(), directory);
10
+ try {
11
+ await loadSkill(skillDir);
12
+ console.log(chalk.green("\nAll checks passed.\n"));
13
+ }
14
+ catch (err) {
15
+ console.log(chalk.red(`\n${err.message}\n`));
16
+ process.exit(1);
17
+ }
18
+ });
19
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;KACnD,WAAW,CAAC,0BAA0B,CAAC;KACvC,QAAQ,CAAC,aAAa,EAAE,6BAA6B,EAAE,GAAG,CAAC;KAC3D,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,EAAE;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IAEnD,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Default registry URL — overridable via SKILLSTORE_REGISTRY env var */
2
+ export declare const REGISTRY_URL: string;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,eAAO,MAAM,YAAY,QACgE,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,3 @@
1
+ /** Default registry URL — overridable via SKILLSTORE_REGISTRY env var */
2
+ export const REGISTRY_URL = process.env.SKILLSTORE_REGISTRY || "https://skillmarketplace-production.up.railway.app";
3
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,MAAM,CAAC,MAAM,YAAY,GACvB,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,oDAAoD,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { initCommand } from "./commands/init.js";
4
+ import { validateCommand } from "./commands/validate.js";
5
+ import { buildCommand } from "./commands/build.js";
6
+ import { publishCommand } from "./commands/publish.js";
7
+ import { installCommand } from "./commands/install.js";
8
+ const program = new Command();
9
+ program
10
+ .name("skillstore")
11
+ .description("CLI for the SkillStore marketplace")
12
+ .version("0.1.0");
13
+ program.addCommand(initCommand);
14
+ program.addCommand(validateCommand);
15
+ program.addCommand(buildCommand);
16
+ program.addCommand(publishCommand);
17
+ program.addCommand(installCommand);
18
+ program.parse();
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AAEnC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1 @@
1
+ You are a helpful assistant with access to the tools defined in this skill. Use them when appropriate to fulfill user requests.
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "1.0.0",
4
+ "description": "{{description}}",
5
+ "type": "tool",
6
+ "license": "MIT",
7
+ "author": {
8
+ "name": "{{authorName}}"
9
+ },
10
+ "main": "./src/index.ts",
11
+ "skill": {
12
+ "instructions": "./instructions.md",
13
+ "tools": "./tools.json"
14
+ },
15
+ "adapters": ["openai", "anthropic"],
16
+ "keywords": []
17
+ }
@@ -0,0 +1 @@
1
+ You are a helpful assistant with access to the tools defined in this skill. Use them when appropriate to fulfill user requests.
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "1.0.0",
4
+ "description": "{{description}}",
5
+ "type": "tool",
6
+ "license": "MIT",
7
+ "author": {
8
+ "name": "{{authorName}}"
9
+ },
10
+ "main": "./src/index.ts",
11
+ "skill": {
12
+ "instructions": "./instructions.md",
13
+ "tools": "./tools.json"
14
+ },
15
+ "adapters": ["openai", "anthropic"],
16
+ "keywords": []
17
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "tools": [
3
+ {
4
+ "name": "example_tool",
5
+ "description": "An example tool — replace with your own",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "input": {
10
+ "type": "string",
11
+ "description": "Example input parameter"
12
+ }
13
+ },
14
+ "required": ["input"]
15
+ }
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "tools": [
3
+ {
4
+ "name": "example_tool",
5
+ "description": "An example tool — replace with your own",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "input": {
10
+ "type": "string",
11
+ "description": "Example input parameter"
12
+ }
13
+ },
14
+ "required": ["input"]
15
+ }
16
+ }
17
+ ]
18
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@polyskill/cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI for creating, validating, and publishing SkillStore skills",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "skillstore": "dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc && cp -r src/templates dist/templates",
13
+ "dev": "tsx src/index.ts",
14
+ "test": "vitest run",
15
+ "clean": "rm -rf dist"
16
+ },
17
+ "dependencies": {
18
+ "@polyskill/core": "workspace:*",
19
+ "commander": "^13.0.0",
20
+ "chalk": "^5.4.0",
21
+ "@inquirer/prompts": "^7.0.0"
22
+ },
23
+ "files": ["dist"],
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "devDependencies": {
28
+ "typescript": "^5.7.0",
29
+ "tsx": "^4.19.0",
30
+ "@types/node": "^22.0.0",
31
+ "vitest": "^3.0.0"
32
+ }
33
+ }