vskill 0.5.2 → 0.5.3

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 (205) hide show
  1. package/dist/agents/agents-registry.test.d.ts +1 -0
  2. package/dist/agents/agents-registry.test.js +248 -0
  3. package/dist/agents/agents-registry.test.js.map +1 -0
  4. package/dist/api/client.test.d.ts +1 -0
  5. package/dist/api/client.test.js +428 -0
  6. package/dist/api/client.test.js.map +1 -0
  7. package/dist/audit/audit-integration.test.d.ts +1 -0
  8. package/dist/audit/audit-integration.test.js +92 -0
  9. package/dist/audit/audit-integration.test.js.map +1 -0
  10. package/dist/audit/audit-llm.test.d.ts +1 -0
  11. package/dist/audit/audit-llm.test.js +110 -0
  12. package/dist/audit/audit-llm.test.js.map +1 -0
  13. package/dist/audit/audit-patterns.test.d.ts +1 -0
  14. package/dist/audit/audit-patterns.test.js +91 -0
  15. package/dist/audit/audit-patterns.test.js.map +1 -0
  16. package/dist/audit/audit-scanner.test.d.ts +1 -0
  17. package/dist/audit/audit-scanner.test.js +112 -0
  18. package/dist/audit/audit-scanner.test.js.map +1 -0
  19. package/dist/audit/audit-types.test.d.ts +1 -0
  20. package/dist/audit/audit-types.test.js +140 -0
  21. package/dist/audit/audit-types.test.js.map +1 -0
  22. package/dist/audit/config.test.d.ts +1 -0
  23. package/dist/audit/config.test.js +44 -0
  24. package/dist/audit/config.test.js.map +1 -0
  25. package/dist/audit/file-discovery.test.d.ts +1 -0
  26. package/dist/audit/file-discovery.test.js +120 -0
  27. package/dist/audit/file-discovery.test.js.map +1 -0
  28. package/dist/audit/fix-suggestions.test.d.ts +1 -0
  29. package/dist/audit/fix-suggestions.test.js +35 -0
  30. package/dist/audit/fix-suggestions.test.js.map +1 -0
  31. package/dist/audit/formatters/json-formatter.test.d.ts +1 -0
  32. package/dist/audit/formatters/json-formatter.test.js +49 -0
  33. package/dist/audit/formatters/json-formatter.test.js.map +1 -0
  34. package/dist/audit/formatters/report-formatter.test.d.ts +1 -0
  35. package/dist/audit/formatters/report-formatter.test.js +51 -0
  36. package/dist/audit/formatters/report-formatter.test.js.map +1 -0
  37. package/dist/audit/formatters/sarif-formatter.test.d.ts +1 -0
  38. package/dist/audit/formatters/sarif-formatter.test.js +71 -0
  39. package/dist/audit/formatters/sarif-formatter.test.js.map +1 -0
  40. package/dist/audit/formatters/terminal-formatter.test.d.ts +1 -0
  41. package/dist/audit/formatters/terminal-formatter.test.js +51 -0
  42. package/dist/audit/formatters/terminal-formatter.test.js.map +1 -0
  43. package/dist/blocklist/blocklist-e2e.test.d.ts +1 -0
  44. package/dist/blocklist/blocklist-e2e.test.js +346 -0
  45. package/dist/blocklist/blocklist-e2e.test.js.map +1 -0
  46. package/dist/blocklist/blocklist.test.d.ts +1 -0
  47. package/dist/blocklist/blocklist.test.js +259 -0
  48. package/dist/blocklist/blocklist.test.js.map +1 -0
  49. package/dist/commands/__tests__/eval-router.test.d.ts +1 -0
  50. package/dist/commands/__tests__/eval-router.test.js +60 -0
  51. package/dist/commands/__tests__/eval-router.test.js.map +1 -0
  52. package/dist/commands/__tests__/eval-serve.test.d.ts +1 -0
  53. package/dist/commands/__tests__/eval-serve.test.js +23 -0
  54. package/dist/commands/__tests__/eval-serve.test.js.map +1 -0
  55. package/dist/commands/add-blocklist-e2e.test.d.ts +1 -0
  56. package/dist/commands/add-blocklist-e2e.test.js +397 -0
  57. package/dist/commands/add-blocklist-e2e.test.js.map +1 -0
  58. package/dist/commands/add-wizard.test.d.ts +1 -0
  59. package/dist/commands/add-wizard.test.js +392 -0
  60. package/dist/commands/add-wizard.test.js.map +1 -0
  61. package/dist/commands/add.test.d.ts +1 -0
  62. package/dist/commands/add.test.js +2365 -0
  63. package/dist/commands/add.test.js.map +1 -0
  64. package/dist/commands/audit.test.d.ts +1 -0
  65. package/dist/commands/audit.test.js +79 -0
  66. package/dist/commands/audit.test.js.map +1 -0
  67. package/dist/commands/blocklist.test.d.ts +1 -0
  68. package/dist/commands/blocklist.test.js +158 -0
  69. package/dist/commands/blocklist.test.js.map +1 -0
  70. package/dist/commands/eval/__tests__/coverage.test.d.ts +1 -0
  71. package/dist/commands/eval/__tests__/coverage.test.js +122 -0
  72. package/dist/commands/eval/__tests__/coverage.test.js.map +1 -0
  73. package/dist/commands/eval/__tests__/generate-all.test.d.ts +1 -0
  74. package/dist/commands/eval/__tests__/generate-all.test.js +133 -0
  75. package/dist/commands/eval/__tests__/generate-all.test.js.map +1 -0
  76. package/dist/commands/eval/__tests__/init.test.d.ts +1 -0
  77. package/dist/commands/eval/__tests__/init.test.js +116 -0
  78. package/dist/commands/eval/__tests__/init.test.js.map +1 -0
  79. package/dist/commands/eval/__tests__/run.test.d.ts +1 -0
  80. package/dist/commands/eval/__tests__/run.test.js +186 -0
  81. package/dist/commands/eval/__tests__/run.test.js.map +1 -0
  82. package/dist/commands/find.test.d.ts +1 -0
  83. package/dist/commands/find.test.js +481 -0
  84. package/dist/commands/find.test.js.map +1 -0
  85. package/dist/commands/marketplace.test.d.ts +1 -0
  86. package/dist/commands/marketplace.test.js +129 -0
  87. package/dist/commands/marketplace.test.js.map +1 -0
  88. package/dist/commands/remove.test.d.ts +1 -0
  89. package/dist/commands/remove.test.js +164 -0
  90. package/dist/commands/remove.test.js.map +1 -0
  91. package/dist/commands/should-skip.test.d.ts +1 -0
  92. package/dist/commands/should-skip.test.js +56 -0
  93. package/dist/commands/should-skip.test.js.map +1 -0
  94. package/dist/commands/submit.test.d.ts +1 -0
  95. package/dist/commands/submit.test.js +83 -0
  96. package/dist/commands/submit.test.js.map +1 -0
  97. package/dist/commands/update.test.d.ts +1 -0
  98. package/dist/commands/update.test.js +250 -0
  99. package/dist/commands/update.test.js.map +1 -0
  100. package/dist/discovery/github-tree.test.d.ts +1 -0
  101. package/dist/discovery/github-tree.test.js +372 -0
  102. package/dist/discovery/github-tree.test.js.map +1 -0
  103. package/dist/eval/__tests__/activation-tester.test.d.ts +1 -0
  104. package/dist/eval/__tests__/activation-tester.test.js +203 -0
  105. package/dist/eval/__tests__/activation-tester.test.js.map +1 -0
  106. package/dist/eval/__tests__/benchmark-history.test.d.ts +1 -0
  107. package/dist/eval/__tests__/benchmark-history.test.js +422 -0
  108. package/dist/eval/__tests__/benchmark-history.test.js.map +1 -0
  109. package/dist/eval/__tests__/benchmark.test.d.ts +1 -0
  110. package/dist/eval/__tests__/benchmark.test.js +94 -0
  111. package/dist/eval/__tests__/benchmark.test.js.map +1 -0
  112. package/dist/eval/__tests__/comparator.test.d.ts +1 -0
  113. package/dist/eval/__tests__/comparator.test.js +282 -0
  114. package/dist/eval/__tests__/comparator.test.js.map +1 -0
  115. package/dist/eval/__tests__/judge.test.d.ts +1 -0
  116. package/dist/eval/__tests__/judge.test.js +122 -0
  117. package/dist/eval/__tests__/judge.test.js.map +1 -0
  118. package/dist/eval/__tests__/llm.test.d.ts +1 -0
  119. package/dist/eval/__tests__/llm.test.js +543 -0
  120. package/dist/eval/__tests__/llm.test.js.map +1 -0
  121. package/dist/eval/__tests__/mcp-detector.test.d.ts +1 -0
  122. package/dist/eval/__tests__/mcp-detector.test.js +180 -0
  123. package/dist/eval/__tests__/mcp-detector.test.js.map +1 -0
  124. package/dist/eval/__tests__/prompt-builder.test.d.ts +1 -0
  125. package/dist/eval/__tests__/prompt-builder.test.js +142 -0
  126. package/dist/eval/__tests__/prompt-builder.test.js.map +1 -0
  127. package/dist/eval/__tests__/schema.test.d.ts +1 -0
  128. package/dist/eval/__tests__/schema.test.js +247 -0
  129. package/dist/eval/__tests__/schema.test.js.map +1 -0
  130. package/dist/eval/__tests__/skill-scanner.test.d.ts +1 -0
  131. package/dist/eval/__tests__/skill-scanner.test.js +228 -0
  132. package/dist/eval/__tests__/skill-scanner.test.js.map +1 -0
  133. package/dist/eval/__tests__/verdict.test.d.ts +1 -0
  134. package/dist/eval/__tests__/verdict.test.js +47 -0
  135. package/dist/eval/__tests__/verdict.test.js.map +1 -0
  136. package/dist/eval-server/__tests__/benchmark-runner.test.d.ts +1 -0
  137. package/dist/eval-server/__tests__/benchmark-runner.test.js +301 -0
  138. package/dist/eval-server/__tests__/benchmark-runner.test.js.map +1 -0
  139. package/dist/eval-server/__tests__/comparison-sse-events.test.d.ts +1 -0
  140. package/dist/eval-server/__tests__/comparison-sse-events.test.js +278 -0
  141. package/dist/eval-server/__tests__/comparison-sse-events.test.js.map +1 -0
  142. package/dist/eval-server/__tests__/sse-helpers.test.d.ts +1 -0
  143. package/dist/eval-server/__tests__/sse-helpers.test.js +128 -0
  144. package/dist/eval-server/__tests__/sse-helpers.test.js.map +1 -0
  145. package/dist/installer/canonical.test.d.ts +1 -0
  146. package/dist/installer/canonical.test.js +264 -0
  147. package/dist/installer/canonical.test.js.map +1 -0
  148. package/dist/lockfile/lockfile.test.d.ts +1 -0
  149. package/dist/lockfile/lockfile.test.js +204 -0
  150. package/dist/lockfile/lockfile.test.js.map +1 -0
  151. package/dist/lockfile/project-root.test.d.ts +1 -0
  152. package/dist/lockfile/project-root.test.js +49 -0
  153. package/dist/lockfile/project-root.test.js.map +1 -0
  154. package/dist/marketplace/marketplace.test.d.ts +1 -0
  155. package/dist/marketplace/marketplace.test.js +312 -0
  156. package/dist/marketplace/marketplace.test.js.map +1 -0
  157. package/dist/resolvers/source-resolver.test.d.ts +1 -0
  158. package/dist/resolvers/source-resolver.test.js +104 -0
  159. package/dist/resolvers/source-resolver.test.js.map +1 -0
  160. package/dist/resolvers/url-resolver.test.d.ts +1 -0
  161. package/dist/resolvers/url-resolver.test.js +49 -0
  162. package/dist/resolvers/url-resolver.test.js.map +1 -0
  163. package/dist/scanner/dci-integration.test.d.ts +1 -0
  164. package/dist/scanner/dci-integration.test.js +83 -0
  165. package/dist/scanner/dci-integration.test.js.map +1 -0
  166. package/dist/scanner/patterns.test.d.ts +1 -0
  167. package/dist/scanner/patterns.test.js +832 -0
  168. package/dist/scanner/patterns.test.js.map +1 -0
  169. package/dist/scanner/tier1.test.d.ts +1 -0
  170. package/dist/scanner/tier1.test.js +305 -0
  171. package/dist/scanner/tier1.test.js.map +1 -0
  172. package/dist/security/platform-security.test.d.ts +1 -0
  173. package/dist/security/platform-security.test.js +92 -0
  174. package/dist/security/platform-security.test.js.map +1 -0
  175. package/dist/settings/settings.test.d.ts +1 -0
  176. package/dist/settings/settings.test.js +103 -0
  177. package/dist/settings/settings.test.js.map +1 -0
  178. package/dist/updater/source-fetcher.test.d.ts +1 -0
  179. package/dist/updater/source-fetcher.test.js +192 -0
  180. package/dist/updater/source-fetcher.test.js.map +1 -0
  181. package/dist/utils/__tests__/paths.test.d.ts +1 -0
  182. package/dist/utils/__tests__/paths.test.js +22 -0
  183. package/dist/utils/__tests__/paths.test.js.map +1 -0
  184. package/dist/utils/__tests__/resolve-binary.integration.test.d.ts +1 -0
  185. package/dist/utils/__tests__/resolve-binary.integration.test.js +138 -0
  186. package/dist/utils/__tests__/resolve-binary.integration.test.js.map +1 -0
  187. package/dist/utils/__tests__/resolve-binary.test.d.ts +1 -0
  188. package/dist/utils/__tests__/resolve-binary.test.js +175 -0
  189. package/dist/utils/__tests__/resolve-binary.test.js.map +1 -0
  190. package/dist/utils/__tests__/validation.test.d.ts +1 -0
  191. package/dist/utils/__tests__/validation.test.js +107 -0
  192. package/dist/utils/__tests__/validation.test.js.map +1 -0
  193. package/dist/utils/agent-filter.test.d.ts +1 -0
  194. package/dist/utils/agent-filter.test.js +75 -0
  195. package/dist/utils/agent-filter.test.js.map +1 -0
  196. package/dist/utils/output.test.d.ts +1 -0
  197. package/dist/utils/output.test.js +28 -0
  198. package/dist/utils/output.test.js.map +1 -0
  199. package/dist/utils/project-root.test.d.ts +1 -0
  200. package/dist/utils/project-root.test.js +74 -0
  201. package/dist/utils/project-root.test.js.map +1 -0
  202. package/dist/utils/prompts.test.d.ts +1 -0
  203. package/dist/utils/prompts.test.js +285 -0
  204. package/dist/utils/prompts.test.js.map +1 -0
  205. package/package.json +1 -1
@@ -0,0 +1,107 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { validateRepoSegment, validateSkillName, parseGitHubSource, classifyIdentifier } from "../validation.js";
3
+ describe("validateRepoSegment (T-011)", () => {
4
+ it("TC-023: accepts valid owner/repo names", () => {
5
+ expect(validateRepoSegment("my-org")).toBe(true);
6
+ expect(validateRepoSegment("user.name")).toBe(true);
7
+ expect(validateRepoSegment("repo_123")).toBe(true);
8
+ expect(validateRepoSegment("A-Z_test.repo")).toBe(true);
9
+ });
10
+ it("TC-024: rejects path traversal", () => {
11
+ expect(validateRepoSegment("../etc/passwd")).toBe(false);
12
+ expect(validateRepoSegment("..")).toBe(false);
13
+ expect(validateRepoSegment("foo/../bar")).toBe(false);
14
+ });
15
+ it("TC-025: rejects null bytes", () => {
16
+ expect(validateRepoSegment("repo\x00name")).toBe(false);
17
+ });
18
+ it("rejects slashes", () => {
19
+ expect(validateRepoSegment("owner/repo")).toBe(false);
20
+ });
21
+ it("rejects empty string", () => {
22
+ expect(validateRepoSegment("")).toBe(false);
23
+ });
24
+ it("rejects spaces", () => {
25
+ expect(validateRepoSegment("my repo")).toBe(false);
26
+ });
27
+ });
28
+ describe("validateSkillName (T-011)", () => {
29
+ it("TC-026: accepts valid skill names", () => {
30
+ expect(validateSkillName("my-skill")).toBe(true);
31
+ expect(validateSkillName("skill_v2")).toBe(true);
32
+ expect(validateSkillName("code-review")).toBe(true);
33
+ });
34
+ it("TC-027: rejects path traversal", () => {
35
+ expect(validateSkillName("../../malicious")).toBe(false);
36
+ expect(validateSkillName("../..")).toBe(false);
37
+ expect(validateSkillName("skill/../../etc")).toBe(false);
38
+ });
39
+ it("rejects backslash traversal", () => {
40
+ expect(validateSkillName("..\\..\\malicious")).toBe(false);
41
+ });
42
+ it("rejects null bytes", () => {
43
+ expect(validateSkillName("skill\x00name")).toBe(false);
44
+ });
45
+ it("rejects empty string", () => {
46
+ expect(validateSkillName("")).toBe(false);
47
+ });
48
+ });
49
+ describe("parseGitHubSource", () => {
50
+ it("TC-006: parses owner/repo shorthand", () => {
51
+ expect(parseGitHubSource("myorg/myskill")).toEqual({ owner: "myorg", repo: "myskill" });
52
+ });
53
+ it("TC-007: parses full GitHub URL", () => {
54
+ expect(parseGitHubSource("https://github.com/myorg/myskill")).toEqual({ owner: "myorg", repo: "myskill" });
55
+ });
56
+ it("TC-008: strips .git suffix", () => {
57
+ expect(parseGitHubSource("https://github.com/myorg/myskill.git")).toEqual({ owner: "myorg", repo: "myskill" });
58
+ });
59
+ it("TC-009: strips trailing slash", () => {
60
+ expect(parseGitHubSource("https://github.com/myorg/myskill/")).toEqual({ owner: "myorg", repo: "myskill" });
61
+ });
62
+ it("TC-010: handles tree/branch path segments", () => {
63
+ expect(parseGitHubSource("https://github.com/myorg/myskill/tree/main/src")).toEqual({ owner: "myorg", repo: "myskill" });
64
+ });
65
+ it("TC-011: rejects non-GitHub URLs", () => {
66
+ expect(parseGitHubSource("https://gitlab.com/myorg/myskill")).toBeNull();
67
+ });
68
+ it("TC-012: rejects URLs with insufficient path segments", () => {
69
+ expect(parseGitHubSource("https://github.com/myorg")).toBeNull();
70
+ });
71
+ it("TC-013: rejects empty input", () => {
72
+ expect(parseGitHubSource("")).toBeNull();
73
+ });
74
+ });
75
+ describe("classifyIdentifier", () => {
76
+ it("classifies owner/repo as owner-repo", () => {
77
+ const r = classifyIdentifier("remotion-dev/skills");
78
+ expect(r).toEqual({ type: "owner-repo", owner: "remotion-dev", repo: "skills" });
79
+ });
80
+ it("classifies owner/repo/skill as owner-repo-skill", () => {
81
+ const r = classifyIdentifier("remotion-dev/skills/remotion");
82
+ expect(r).toEqual({ type: "owner-repo-skill", owner: "remotion-dev", repo: "skills", skill: "remotion" });
83
+ });
84
+ it("classifies flat name as flat", () => {
85
+ const r = classifyIdentifier("remotion-dev-skills-remotion");
86
+ expect(r).toEqual({ type: "flat", name: "remotion-dev-skills-remotion" });
87
+ });
88
+ it("classifies single word as flat", () => {
89
+ const r = classifyIdentifier("myskill");
90
+ expect(r).toEqual({ type: "flat", name: "myskill" });
91
+ });
92
+ it("classifies https URL as url", () => {
93
+ expect(classifyIdentifier("https://github.com/foo/bar").type).toBe("url");
94
+ });
95
+ it("classifies github.com shorthand as url", () => {
96
+ expect(classifyIdentifier("github.com/foo/bar").type).toBe("url");
97
+ });
98
+ it("classifies 4+ part paths as flat (not parseable)", () => {
99
+ const r = classifyIdentifier("a/b/c/d");
100
+ expect(r).toEqual({ type: "flat", name: "a/b/c/d" });
101
+ });
102
+ it("classifies empty string as flat", () => {
103
+ const r = classifyIdentifier("");
104
+ expect(r).toEqual({ type: "flat", name: "" });
105
+ });
106
+ });
107
+ //# sourceMappingURL=validation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/validation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { filterAgents } from "./agent-filter.js";
3
+ // ---------------------------------------------------------------------------
4
+ // Helpers
5
+ // ---------------------------------------------------------------------------
6
+ function makeAgent(overrides = {}) {
7
+ return {
8
+ id: "claude-code",
9
+ displayName: "Claude Code",
10
+ localSkillsDir: ".claude/commands",
11
+ globalSkillsDir: "~/.claude/commands",
12
+ isUniversal: false,
13
+ detectInstalled: "which claude",
14
+ parentCompany: "Anthropic",
15
+ featureSupport: {
16
+ slashCommands: true,
17
+ hooks: true,
18
+ mcp: true,
19
+ customSystemPrompt: true,
20
+ },
21
+ ...overrides,
22
+ };
23
+ }
24
+ const claudeAgent = makeAgent({ id: "claude-code", displayName: "Claude Code" });
25
+ const cursorAgent = makeAgent({ id: "cursor", displayName: "Cursor" });
26
+ const windsurf = makeAgent({ id: "windsurf", displayName: "Windsurf" });
27
+ const allAgents = [claudeAgent, cursorAgent, windsurf];
28
+ // ---------------------------------------------------------------------------
29
+ // Tests
30
+ // ---------------------------------------------------------------------------
31
+ describe("filterAgents", () => {
32
+ // TC-001: No filter returns all agents
33
+ it("returns all agents when requestedIds is undefined", () => {
34
+ const result = filterAgents(allAgents, undefined);
35
+ expect(result).toEqual(allAgents);
36
+ });
37
+ // TC-002: Single filter returns only matching
38
+ it("returns only the matching agent when filtering by single ID", () => {
39
+ const result = filterAgents(allAgents, ["claude-code"]);
40
+ expect(result).toHaveLength(1);
41
+ expect(result[0].id).toBe("claude-code");
42
+ });
43
+ // TC-003: Multiple filters returns all matching
44
+ it("returns all matching agents when filtering by multiple IDs", () => {
45
+ const result = filterAgents(allAgents, ["claude-code", "cursor"]);
46
+ expect(result).toHaveLength(2);
47
+ expect(result.map((a) => a.id)).toEqual(["claude-code", "cursor"]);
48
+ });
49
+ // TC-004: Unknown ID throws with available agents listed
50
+ it("throws error listing available agents when ID is unknown", () => {
51
+ expect(() => filterAgents(allAgents, ["nonexistent"])).toThrow(/Unknown agent\(s\): nonexistent/);
52
+ expect(() => filterAgents(allAgents, ["nonexistent"])).toThrow(/Available: claude-code, cursor, windsurf/);
53
+ });
54
+ // TC-005: Mix of valid and invalid throws
55
+ it("throws error mentioning only the invalid IDs", () => {
56
+ expect(() => filterAgents(allAgents, ["claude-code", "nonexistent"])).toThrow(/Unknown agent\(s\): nonexistent/);
57
+ });
58
+ // TC-006: Empty array returns all (same as undefined)
59
+ it("returns all agents when requestedIds is an empty array", () => {
60
+ const result = filterAgents(allAgents, []);
61
+ expect(result).toEqual(allAgents);
62
+ });
63
+ // TC-007: String input is coerced to array
64
+ it("handles single string input by coercing to array", () => {
65
+ const result = filterAgents(allAgents, "claude-code");
66
+ expect(result).toHaveLength(1);
67
+ expect(result[0].id).toBe("claude-code");
68
+ });
69
+ // TC-008: Empty string returns all agents
70
+ it("returns all agents when requestedIds is an empty string", () => {
71
+ const result = filterAgents(allAgents, "");
72
+ expect(result).toEqual(allAgents);
73
+ });
74
+ });
75
+ //# sourceMappingURL=agent-filter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-filter.test.js","sourceRoot":"","sources":["../../src/utils/agent-filter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { formatInstalls } from "./output.js";
3
+ describe("formatInstalls", () => {
4
+ it("returns raw number below 1000", () => {
5
+ expect(formatInstalls(0)).toBe("0");
6
+ expect(formatInstalls(999)).toBe("999");
7
+ });
8
+ it("formats exact thousands without decimal", () => {
9
+ expect(formatInstalls(1000)).toBe("1K");
10
+ });
11
+ it("formats thousands with one decimal", () => {
12
+ expect(formatInstalls(1200)).toBe("1.2K");
13
+ expect(formatInstalls(1250)).toBe("1.3K");
14
+ expect(formatInstalls(9999)).toBe("10K");
15
+ });
16
+ it("formats ten-thousands without decimal", () => {
17
+ expect(formatInstalls(10000)).toBe("10K");
18
+ expect(formatInstalls(999999)).toBe("999K");
19
+ });
20
+ it("formats exact millions without decimal", () => {
21
+ expect(formatInstalls(1000000)).toBe("1M");
22
+ });
23
+ it("formats millions with one decimal", () => {
24
+ expect(formatInstalls(3400000)).toBe("3.4M");
25
+ expect(formatInstalls(10000000)).toBe("10M");
26
+ });
27
+ });
28
+ //# sourceMappingURL=output.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.test.js","sourceRoot":"","sources":["../../src/utils/output.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,74 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { join } from "node:path";
3
+ // ---------------------------------------------------------------------------
4
+ // Mock node:fs — only existsSync is used by findProjectRoot
5
+ // ---------------------------------------------------------------------------
6
+ const mockExistsSync = vi.fn();
7
+ vi.mock("node:fs", () => ({
8
+ existsSync: (...args) => mockExistsSync(...args),
9
+ }));
10
+ // ---------------------------------------------------------------------------
11
+ // Import module under test AFTER mocks
12
+ // ---------------------------------------------------------------------------
13
+ const { findProjectRoot, PROJECT_MARKERS } = await import("./project-root.js");
14
+ // ---------------------------------------------------------------------------
15
+ // Helpers
16
+ // ---------------------------------------------------------------------------
17
+ /**
18
+ * Configure mockExistsSync to return true only for paths
19
+ * that are in the `existing` set.
20
+ */
21
+ function setExistingPaths(existing) {
22
+ mockExistsSync.mockImplementation((p) => existing.has(p));
23
+ }
24
+ // ---------------------------------------------------------------------------
25
+ // Tests
26
+ // ---------------------------------------------------------------------------
27
+ beforeEach(() => {
28
+ vi.clearAllMocks();
29
+ });
30
+ describe("findProjectRoot", () => {
31
+ // TC-001: Finds .git at parent when cwd is subdirectory
32
+ it("finds .git at parent when cwd is a subdirectory", () => {
33
+ const projectDir = "/home/user/project";
34
+ const startDir = join(projectDir, "src", "components");
35
+ setExistingPaths(new Set([join(projectDir, ".git")]));
36
+ expect(findProjectRoot(startDir)).toBe(projectDir);
37
+ });
38
+ // TC-002: Finds package.json at ancestor
39
+ it("finds package.json at ancestor directory", () => {
40
+ const projectDir = "/home/user/project";
41
+ const startDir = join(projectDir, "deep", "nested", "dir");
42
+ setExistingPaths(new Set([join(projectDir, "package.json")]));
43
+ expect(findProjectRoot(startDir)).toBe(projectDir);
44
+ });
45
+ // TC-003: Returns null when no markers anywhere
46
+ it("returns null when no markers exist anywhere up to root", () => {
47
+ setExistingPaths(new Set());
48
+ expect(findProjectRoot("/some/random/path")).toBeNull();
49
+ });
50
+ // TC-004: Nearest wins when markers at multiple levels
51
+ it("returns nearest directory when markers exist at multiple levels", () => {
52
+ const outer = "/home/user/project";
53
+ const inner = join(outer, "submodule");
54
+ const startDir = join(inner, "src");
55
+ setExistingPaths(new Set([join(outer, ".git"), join(inner, ".git")]));
56
+ expect(findProjectRoot(startDir)).toBe(inner);
57
+ });
58
+ // TC-005: Returns cwd itself when it has markers
59
+ it("returns cwd itself when it contains markers", () => {
60
+ const startDir = "/home/user/project";
61
+ setExistingPaths(new Set([join(startDir, ".git")]));
62
+ expect(findProjectRoot(startDir)).toBe(startDir);
63
+ });
64
+ // Additional: verifies all markers are recognized
65
+ it("recognizes every marker in PROJECT_MARKERS", () => {
66
+ for (const marker of PROJECT_MARKERS) {
67
+ vi.clearAllMocks();
68
+ const dir = "/home/user/project";
69
+ setExistingPaths(new Set([join(dir, marker)]));
70
+ expect(findProjectRoot(dir)).toBe(dir);
71
+ }
72
+ });
73
+ });
74
+ //# sourceMappingURL=project-root.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-root.test.js","sourceRoot":"","sources":["../../src/utils/project-root.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,285 @@
1
+ import { describe, it, expect, beforeEach } from "vitest";
2
+ import { Readable, Writable } from "node:stream";
3
+ import { isTTY, createPrompter, isEscapeSequence, parseToggleInput } from "./prompts.js";
4
+ describe("isTTY", () => {
5
+ it("returns false when stdin.isTTY is undefined", () => {
6
+ const original = process.stdin.isTTY;
7
+ Object.defineProperty(process.stdin, "isTTY", { value: undefined, configurable: true });
8
+ expect(isTTY()).toBe(false);
9
+ Object.defineProperty(process.stdin, "isTTY", { value: original, configurable: true });
10
+ });
11
+ it("returns true when both stdin and stdout are TTY", () => {
12
+ const origIn = process.stdin.isTTY;
13
+ const origOut = process.stdout.isTTY;
14
+ Object.defineProperty(process.stdin, "isTTY", { value: true, configurable: true });
15
+ Object.defineProperty(process.stdout, "isTTY", { value: true, configurable: true });
16
+ expect(isTTY()).toBe(true);
17
+ Object.defineProperty(process.stdin, "isTTY", { value: origIn, configurable: true });
18
+ Object.defineProperty(process.stdout, "isTTY", { value: origOut, configurable: true });
19
+ });
20
+ });
21
+ describe("createPrompter", () => {
22
+ let output;
23
+ let outputData;
24
+ beforeEach(() => {
25
+ outputData = "";
26
+ output = new Writable({
27
+ write(chunk, _encoding, callback) {
28
+ outputData += chunk.toString();
29
+ callback();
30
+ },
31
+ });
32
+ });
33
+ function makeInput(data) {
34
+ let pushed = false;
35
+ return new Readable({
36
+ read() {
37
+ if (!pushed) {
38
+ pushed = true;
39
+ this.push(data);
40
+ this.push(null);
41
+ }
42
+ },
43
+ });
44
+ }
45
+ describe("promptCheckboxList", () => {
46
+ it("returns all indices when user types 'a' then Enter", async () => {
47
+ const input = makeInput("a\n\n");
48
+ const prompter = createPrompter(input, output);
49
+ const result = await prompter.promptCheckboxList([
50
+ { label: "skill-one", description: "First skill" },
51
+ { label: "skill-two", description: "Second skill" },
52
+ { label: "skill-three", description: "Third skill" },
53
+ ]);
54
+ expect(result).toEqual([0, 1, 2]);
55
+ });
56
+ it("toggles individual items off when pre-checked", async () => {
57
+ const input = makeInput("2\n\n");
58
+ const prompter = createPrompter(input, output);
59
+ const result = await prompter.promptCheckboxList([
60
+ { label: "skill-one", checked: true },
61
+ { label: "skill-two", checked: true },
62
+ { label: "skill-three", checked: true },
63
+ ]);
64
+ // Item 2 (index 1) was toggled off
65
+ expect(result).toEqual([0, 2]);
66
+ });
67
+ it("toggles individual items on when unchecked", async () => {
68
+ const input = makeInput("2\n\n");
69
+ const prompter = createPrompter(input, output);
70
+ const result = await prompter.promptCheckboxList([
71
+ { label: "skill-one", checked: false },
72
+ { label: "skill-two", checked: false },
73
+ { label: "skill-three", checked: false },
74
+ ]);
75
+ // Only item 2 (index 1) was toggled on
76
+ expect(result).toEqual([1]);
77
+ });
78
+ it("displays title when provided", async () => {
79
+ const input = makeInput("a\n\n");
80
+ const prompter = createPrompter(input, output);
81
+ await prompter.promptCheckboxList([{ label: "test-skill" }], { title: "Select skills to install" });
82
+ expect(outputData).toContain("Select skills to install");
83
+ });
84
+ });
85
+ describe("promptChoice", () => {
86
+ it("returns selected index (0-based) for valid input", async () => {
87
+ const input = makeInput("2\n");
88
+ const prompter = createPrompter(input, output);
89
+ const result = await prompter.promptChoice("Install scope:", [
90
+ { label: "Project", hint: "recommended" },
91
+ { label: "Global", hint: "~/ directories" },
92
+ ]);
93
+ expect(result).toBe(1);
94
+ });
95
+ it("returns 0 for first choice", async () => {
96
+ const input = makeInput("1\n");
97
+ const prompter = createPrompter(input, output);
98
+ const result = await prompter.promptChoice("Method:", [
99
+ { label: "Symlink", hint: "recommended" },
100
+ { label: "Copy" },
101
+ ]);
102
+ expect(result).toBe(0);
103
+ });
104
+ it("displays choices with hints", async () => {
105
+ const input = makeInput("1\n");
106
+ const prompter = createPrompter(input, output);
107
+ await prompter.promptChoice("Scope:", [
108
+ { label: "Project", hint: "recommended" },
109
+ { label: "Global" },
110
+ ]);
111
+ expect(outputData).toContain("Project");
112
+ expect(outputData).toContain("recommended");
113
+ expect(outputData).toContain("Global");
114
+ });
115
+ });
116
+ describe("promptConfirm", () => {
117
+ it("returns true on 'y' input", async () => {
118
+ const input = makeInput("y\n");
119
+ const prompter = createPrompter(input, output);
120
+ const result = await prompter.promptConfirm("Proceed?", false);
121
+ expect(result).toBe(true);
122
+ });
123
+ it("returns false on 'n' input", async () => {
124
+ const input = makeInput("n\n");
125
+ const prompter = createPrompter(input, output);
126
+ const result = await prompter.promptConfirm("Proceed?", true);
127
+ expect(result).toBe(false);
128
+ });
129
+ it("returns default on empty input (defaultYes=true)", async () => {
130
+ const input = makeInput("\n");
131
+ const prompter = createPrompter(input, output);
132
+ const result = await prompter.promptConfirm("Proceed?", true);
133
+ expect(result).toBe(true);
134
+ });
135
+ it("returns default on empty input (defaultYes=false)", async () => {
136
+ const input = makeInput("\n");
137
+ const prompter = createPrompter(input, output);
138
+ const result = await prompter.promptConfirm("Proceed?", false);
139
+ expect(result).toBe(false);
140
+ });
141
+ it("displays question with Y/n when defaultYes is true", async () => {
142
+ const input = makeInput("y\n");
143
+ const prompter = createPrompter(input, output);
144
+ await prompter.promptConfirm("Proceed?", true);
145
+ expect(outputData).toContain("Y/n");
146
+ });
147
+ it("displays question with y/N when defaultYes is false", async () => {
148
+ const input = makeInput("y\n");
149
+ const prompter = createPrompter(input, output);
150
+ await prompter.promptConfirm("Proceed?", false);
151
+ expect(outputData).toContain("y/N");
152
+ });
153
+ });
154
+ describe("escape sequence handling in promptCheckboxList", () => {
155
+ it("ignores arrow key escape sequences and processes subsequent input", async () => {
156
+ // Simulate: up arrow (ignored), then toggle item 1, then confirm
157
+ const input = makeInput("\x1b[A\n1\n\n");
158
+ const prompter = createPrompter(input, output);
159
+ const result = await prompter.promptCheckboxList([
160
+ { label: "skill-one", checked: false },
161
+ { label: "skill-two", checked: false },
162
+ { label: "skill-three", checked: false },
163
+ ]);
164
+ // Arrow key ignored; only item 1 (index 0) toggled on
165
+ expect(result).toEqual([0]);
166
+ });
167
+ it("ignores mixed escape+input line like \\x1b[A\\x1b[B6 and parses the 6", async () => {
168
+ // Simulate what real terminal sends: arrow escapes + number on same readline
169
+ const input = makeInput("\x1b[A\x1b[B6\n\n");
170
+ const prompter = createPrompter(input, output);
171
+ const result = await prompter.promptCheckboxList([
172
+ { label: "s1", checked: false },
173
+ { label: "s2", checked: false },
174
+ { label: "s3", checked: false },
175
+ { label: "s4", checked: false },
176
+ { label: "s5", checked: false },
177
+ { label: "s6", checked: false },
178
+ ]);
179
+ // Escape sequences stripped; "6" parsed → item 6 (index 5) toggled
180
+ expect(result).toEqual([5]);
181
+ });
182
+ it("toggles a range of items with '1-2' input", async () => {
183
+ const input = makeInput("1-2\n\n");
184
+ const prompter = createPrompter(input, output);
185
+ const result = await prompter.promptCheckboxList([
186
+ { label: "skill-one", checked: false },
187
+ { label: "skill-two", checked: false },
188
+ { label: "skill-three", checked: false },
189
+ ]);
190
+ expect(result).toEqual([0, 1]);
191
+ });
192
+ it("toggles comma-separated items with '1,3' input", async () => {
193
+ const input = makeInput("1,3\n\n");
194
+ const prompter = createPrompter(input, output);
195
+ const result = await prompter.promptCheckboxList([
196
+ { label: "skill-one", checked: false },
197
+ { label: "skill-two", checked: false },
198
+ { label: "skill-three", checked: false },
199
+ ]);
200
+ expect(result).toEqual([0, 2]);
201
+ });
202
+ it("render output includes usage instructions", async () => {
203
+ const input = makeInput("\n");
204
+ const prompter = createPrompter(input, output);
205
+ await prompter.promptCheckboxList([{ label: "test-skill" }]);
206
+ expect(outputData).toContain("Enter=done");
207
+ });
208
+ });
209
+ describe("escape sequence handling in promptChoice", () => {
210
+ it("ignores arrow key escape sequences and waits for valid input", async () => {
211
+ // Down arrow (ignored), then "1"
212
+ const input = makeInput("\x1b[B\n1\n");
213
+ const prompter = createPrompter(input, output);
214
+ const result = await prompter.promptChoice("Scope:", [
215
+ { label: "Project" },
216
+ { label: "Global" },
217
+ ]);
218
+ // Arrow key ignored; "1" accepted → index 0
219
+ expect(result).toBe(0);
220
+ });
221
+ });
222
+ });
223
+ describe("isEscapeSequence", () => {
224
+ it("returns true for up arrow escape sequence", () => {
225
+ expect(isEscapeSequence("\x1b[A")).toBe(true);
226
+ });
227
+ it("returns true for down arrow escape sequence", () => {
228
+ expect(isEscapeSequence("\x1b[B")).toBe(true);
229
+ });
230
+ it("returns true for right arrow escape sequence", () => {
231
+ expect(isEscapeSequence("\x1b[C")).toBe(true);
232
+ });
233
+ it("returns true for left arrow escape sequence", () => {
234
+ expect(isEscapeSequence("\x1b[D")).toBe(true);
235
+ });
236
+ it("returns true for multiple chained escape sequences", () => {
237
+ expect(isEscapeSequence("\x1b[A\x1b[B")).toBe(true);
238
+ });
239
+ it("returns false for a normal number", () => {
240
+ expect(isEscapeSequence("1")).toBe(false);
241
+ });
242
+ it("returns false for toggle-all 'a'", () => {
243
+ expect(isEscapeSequence("a")).toBe(false);
244
+ });
245
+ it("returns false for empty string", () => {
246
+ expect(isEscapeSequence("")).toBe(false);
247
+ });
248
+ it("returns false for mixed escape + real input", () => {
249
+ // "\x1b[A6" has a real "6" after stripping → not purely escape sequences
250
+ expect(isEscapeSequence("\x1b[A6")).toBe(false);
251
+ });
252
+ });
253
+ describe("parseToggleInput", () => {
254
+ it("parses single number '2' → [1]", () => {
255
+ expect(parseToggleInput("2", 5)).toEqual([1]);
256
+ });
257
+ it("parses range '1-3' → [0, 1, 2]", () => {
258
+ expect(parseToggleInput("1-3", 5)).toEqual([0, 1, 2]);
259
+ });
260
+ it("parses comma-separated '1,3,5' → [0, 2, 4]", () => {
261
+ expect(parseToggleInput("1,3,5", 5)).toEqual([0, 2, 4]);
262
+ });
263
+ it("parses mixed '1-3,5' → [0, 1, 2, 4]", () => {
264
+ expect(parseToggleInput("1-3,5", 10)).toEqual([0, 1, 2, 4]);
265
+ });
266
+ it("rejects invalid range '5-2' → []", () => {
267
+ expect(parseToggleInput("5-2", 5)).toEqual([]);
268
+ });
269
+ it("rejects out-of-bounds '0' → []", () => {
270
+ expect(parseToggleInput("0", 5)).toEqual([]);
271
+ });
272
+ it("rejects out-of-bounds '999' with maxIndex 5 → []", () => {
273
+ expect(parseToggleInput("999", 5)).toEqual([]);
274
+ });
275
+ it("deduplicates '1,1,2' → [0, 1]", () => {
276
+ expect(parseToggleInput("1,1,2", 5)).toEqual([0, 1]);
277
+ });
278
+ it("returns empty for non-numeric input", () => {
279
+ expect(parseToggleInput("abc", 5)).toEqual([]);
280
+ });
281
+ it("returns sorted result for range", () => {
282
+ expect(parseToggleInput("3-5", 10)).toEqual([2, 3, 4]);
283
+ });
284
+ });
285
+ //# sourceMappingURL=prompts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.test.js","sourceRoot":"","sources":["../../src/utils/prompts.test.ts"],"names":[],"mappings":"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"}