vskill 0.5.2 → 0.5.4

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,428 @@
1
+ import { describe, it, expect, vi, beforeEach, afterAll } from "vitest";
2
+ import { searchSkills, getSkill, submitSkill, getSubmission, reportInstall, reportInstallBatch, } from "./client.js";
3
+ // ---------------------------------------------------------------------------
4
+ // Mock global fetch
5
+ // ---------------------------------------------------------------------------
6
+ const mockFetch = vi.fn();
7
+ vi.stubGlobal("fetch", mockFetch);
8
+ // ---------------------------------------------------------------------------
9
+ // Helpers
10
+ // ---------------------------------------------------------------------------
11
+ function jsonResponse(data, status = 200, statusText = "OK") {
12
+ return {
13
+ ok: status >= 200 && status < 300,
14
+ status,
15
+ statusText,
16
+ json: () => Promise.resolve(data),
17
+ text: () => Promise.resolve(JSON.stringify(data)),
18
+ };
19
+ }
20
+ function errorResponse(status, statusText, body = "") {
21
+ return {
22
+ ok: false,
23
+ status,
24
+ statusText,
25
+ json: () => Promise.reject(new Error("not json")),
26
+ text: () => Promise.resolve(body),
27
+ };
28
+ }
29
+ const BASE_URL = "https://verified-skill.com";
30
+ // ---------------------------------------------------------------------------
31
+ // Tests
32
+ // ---------------------------------------------------------------------------
33
+ beforeEach(() => {
34
+ vi.clearAllMocks();
35
+ });
36
+ afterAll(() => {
37
+ vi.unstubAllGlobals();
38
+ });
39
+ describe("searchSkills", () => {
40
+ it("encodes the query and parses the response", async () => {
41
+ const apiData = {
42
+ results: [
43
+ {
44
+ name: "my-skill",
45
+ author: "alice",
46
+ certTier: "VERIFIED",
47
+ trustScore: 95,
48
+ description: "A great skill",
49
+ },
50
+ ],
51
+ };
52
+ mockFetch.mockResolvedValue(jsonResponse(apiData));
53
+ const response = await searchSkills("hello world");
54
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/skills/search?q=hello%20world&limit=7`, expect.objectContaining({
55
+ headers: expect.objectContaining({
56
+ "Content-Type": "application/json",
57
+ "User-Agent": "vskill-cli",
58
+ }),
59
+ }));
60
+ expect(response.results).toEqual([
61
+ {
62
+ name: "my-skill",
63
+ author: "alice",
64
+ repoUrl: undefined,
65
+ tier: "VERIFIED",
66
+ score: 95,
67
+ description: "A great skill",
68
+ installs: 0,
69
+ githubStars: 0,
70
+ command: null,
71
+ pluginName: null,
72
+ isTainted: false,
73
+ trustTier: undefined,
74
+ certTier: "VERIFIED",
75
+ isBlocked: false,
76
+ threatType: undefined,
77
+ severity: undefined,
78
+ vskillInstalls: undefined,
79
+ ownerSlug: undefined,
80
+ repoSlug: undefined,
81
+ skillSlug: undefined,
82
+ alternateRepos: undefined,
83
+ },
84
+ ]);
85
+ expect(response.hasMore).toBe(false);
86
+ });
87
+ it("returns empty results when results field is missing", async () => {
88
+ mockFetch.mockResolvedValue(jsonResponse({}));
89
+ const response = await searchSkills("nothing");
90
+ expect(response.results).toEqual([]);
91
+ expect(response.hasMore).toBe(false);
92
+ });
93
+ it("passes hasMore from pagination", async () => {
94
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s" }], pagination: { hasMore: true } }));
95
+ const response = await searchSkills("test");
96
+ expect(response.hasMore).toBe(true);
97
+ });
98
+ it("respects custom limit option", async () => {
99
+ mockFetch.mockResolvedValue(jsonResponse({ results: [] }));
100
+ await searchSkills("test", { limit: 20 });
101
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/skills/search?q=test&limit=20`, expect.any(Object));
102
+ });
103
+ it("falls back to 'tier' when 'certTier' is missing", async () => {
104
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s", tier: "VERIFIED" }] }));
105
+ const { results } = await searchSkills("test");
106
+ expect(results[0].tier).toBe("VERIFIED");
107
+ });
108
+ it("defaults tier to 'VERIFIED' when no tier field exists", async () => {
109
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s" }] }));
110
+ const { results } = await searchSkills("test");
111
+ expect(results[0].tier).toBe("VERIFIED");
112
+ });
113
+ it("uses trustScore as primary score source", async () => {
114
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s", trustScore: 80 }] }));
115
+ const { results } = await searchSkills("test");
116
+ expect(results[0].score).toBe(80);
117
+ });
118
+ it("falls back to 'certScore' when 'trustScore' is missing", async () => {
119
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s", certScore: 75 }] }));
120
+ const { results } = await searchSkills("test");
121
+ expect(results[0].score).toBe(75);
122
+ });
123
+ it("falls back to 'score' when 'trustScore' and 'certScore' are missing", async () => {
124
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s", score: 60 }] }));
125
+ const { results } = await searchSkills("test");
126
+ expect(results[0].score).toBe(60);
127
+ });
128
+ it("defaults score to 0 when no score field exists", async () => {
129
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s" }] }));
130
+ const { results } = await searchSkills("test");
131
+ expect(results[0].score).toBe(0);
132
+ });
133
+ it("maps vskillInstalls from API response", async () => {
134
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s", vskillInstalls: 500 }] }));
135
+ const { results } = await searchSkills("test");
136
+ expect(results[0].vskillInstalls).toBe(500);
137
+ });
138
+ it("handles missing vskillInstalls as undefined", async () => {
139
+ mockFetch.mockResolvedValue(jsonResponse({ results: [{ name: "s" }] }));
140
+ const { results } = await searchSkills("test");
141
+ expect(results[0].vskillInstalls).toBeUndefined();
142
+ });
143
+ });
144
+ describe("getSkill", () => {
145
+ it("unwraps the skill wrapper and normalizes field names", async () => {
146
+ const apiResponse = {
147
+ skill: {
148
+ name: "remotion-dev-skills-remotion",
149
+ author: "remotion-dev",
150
+ certTier: "VERIFIED",
151
+ certScore: null,
152
+ currentVersion: "1.0.0",
153
+ sha: "",
154
+ description: "A great skill",
155
+ vskillInstalls: 0,
156
+ updatedAt: "2026-02-20T00:00:00Z",
157
+ repoUrl: "https://github.com/remotion-dev/skills",
158
+ },
159
+ };
160
+ mockFetch.mockResolvedValue(jsonResponse(apiResponse));
161
+ const result = await getSkill("remotion-dev-skills-remotion");
162
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/skills/remotion-dev-skills-remotion`, expect.objectContaining({
163
+ headers: expect.objectContaining({
164
+ "Content-Type": "application/json",
165
+ "User-Agent": "vskill-cli",
166
+ }),
167
+ }));
168
+ expect(result.name).toBe("remotion-dev-skills-remotion");
169
+ expect(result.author).toBe("remotion-dev");
170
+ expect(result.tier).toBe("VERIFIED");
171
+ expect(result.score).toBe(0);
172
+ expect(result.version).toBe("1.0.0");
173
+ expect(result.installs).toBe(0);
174
+ expect(result.repoUrl).toBe("https://github.com/remotion-dev/skills");
175
+ expect(result.content).toBeUndefined();
176
+ });
177
+ it("falls back to flat response when no skill wrapper exists", async () => {
178
+ const detail = {
179
+ name: "test-skill",
180
+ author: "bob",
181
+ tier: "VERIFIED",
182
+ score: 50,
183
+ version: "1.2.3",
184
+ sha: "def456",
185
+ description: "Test skill",
186
+ installs: 300,
187
+ updatedAt: "2026-02-01T00:00:00Z",
188
+ };
189
+ mockFetch.mockResolvedValue(jsonResponse(detail));
190
+ const result = await getSkill("test-skill");
191
+ expect(result.name).toBe("test-skill");
192
+ expect(result.author).toBe("bob");
193
+ expect(result.tier).toBe("VERIFIED");
194
+ expect(result.score).toBe(50);
195
+ expect(result.version).toBe("1.2.3");
196
+ });
197
+ it("normalizes certTier and certScore field aliases", async () => {
198
+ mockFetch.mockResolvedValue(jsonResponse({
199
+ skill: { name: "s", author: "a", certTier: "CERTIFIED", certScore: 95, currentVersion: "2.0.0", vskillInstalls: 42 },
200
+ }));
201
+ const result = await getSkill("s");
202
+ expect(result.tier).toBe("CERTIFIED");
203
+ expect(result.score).toBe(95);
204
+ expect(result.version).toBe("2.0.0");
205
+ expect(result.installs).toBe(42);
206
+ });
207
+ it("returns content when present in response", async () => {
208
+ mockFetch.mockResolvedValue(jsonResponse({
209
+ skill: { name: "s", author: "a", content: "# My Skill\nDoes things." },
210
+ }));
211
+ const result = await getSkill("s");
212
+ expect(result.content).toBe("# My Skill\nDoes things.");
213
+ });
214
+ it("encodes special characters in skill name", async () => {
215
+ mockFetch.mockResolvedValue(jsonResponse({ name: "@org/skill" }));
216
+ await getSkill("@org/skill");
217
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/skills/%40org%2Fskill`, expect.any(Object));
218
+ });
219
+ });
220
+ describe("submitSkill", () => {
221
+ it("sends a POST request with JSON body", async () => {
222
+ const submission = {
223
+ repoUrl: "https://github.com/alice/skill-repo",
224
+ skillName: "my-skill",
225
+ email: "alice@example.com",
226
+ };
227
+ const responseData = {
228
+ id: "sub-123",
229
+ status: "pending",
230
+ trackingUrl: "https://verified-skill.com/submissions/sub-123",
231
+ };
232
+ mockFetch.mockResolvedValue(jsonResponse(responseData));
233
+ const result = await submitSkill(submission);
234
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/submissions`, expect.objectContaining({
235
+ method: "POST",
236
+ body: JSON.stringify(submission),
237
+ headers: expect.objectContaining({
238
+ "Content-Type": "application/json",
239
+ "User-Agent": "vskill-cli",
240
+ }),
241
+ }));
242
+ expect(result).toEqual(responseData);
243
+ });
244
+ });
245
+ describe("getSubmission", () => {
246
+ it("fetches submission by ID", async () => {
247
+ const data = { id: "sub-456", status: "completed", result: { ok: true } };
248
+ mockFetch.mockResolvedValue(jsonResponse(data));
249
+ const result = await getSubmission("sub-456");
250
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/submissions/sub-456`, expect.objectContaining({
251
+ headers: expect.objectContaining({
252
+ "Content-Type": "application/json",
253
+ "User-Agent": "vskill-cli",
254
+ }),
255
+ }));
256
+ expect(result).toEqual(data);
257
+ });
258
+ });
259
+ describe("error handling", () => {
260
+ it("throws on non-ok response with status info", async () => {
261
+ mockFetch.mockResolvedValue(errorResponse(404, "Not Found", "skill not found"));
262
+ await expect(getSkill("nonexistent")).rejects.toThrow(/API request failed: 404 Not Found/);
263
+ });
264
+ it("includes response body in error message", async () => {
265
+ mockFetch.mockResolvedValue(errorResponse(500, "Internal Server Error", "database error"));
266
+ await expect(searchSkills("test")).rejects.toThrow(/database error/);
267
+ });
268
+ it("handles empty error body gracefully", async () => {
269
+ mockFetch.mockResolvedValue(errorResponse(403, "Forbidden", ""));
270
+ await expect(submitSkill({ repoUrl: "https://x.com/r" })).rejects.toThrow(/API request failed: 403 Forbidden/);
271
+ });
272
+ it("propagates network errors when fetch throws", async () => {
273
+ mockFetch.mockRejectedValue(new TypeError("Failed to fetch"));
274
+ await expect(searchSkills("test")).rejects.toThrow("Failed to fetch");
275
+ });
276
+ });
277
+ describe("headers", () => {
278
+ it("sends correct Content-Type and User-Agent headers", async () => {
279
+ mockFetch.mockResolvedValue(jsonResponse({ results: [] }));
280
+ await searchSkills("test");
281
+ const callArgs = mockFetch.mock.calls[0];
282
+ const options = callArgs[1];
283
+ expect(options.headers["Content-Type"]).toBe("application/json");
284
+ expect(options.headers["User-Agent"]).toBe("vskill-cli");
285
+ });
286
+ });
287
+ describe("reportInstall", () => {
288
+ it("sends POST to correct URL", async () => {
289
+ mockFetch.mockResolvedValue(jsonResponse({ ok: true }));
290
+ await reportInstall("my-skill");
291
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/skills/my-skill/installs`, expect.objectContaining({
292
+ method: "POST",
293
+ headers: expect.objectContaining({
294
+ "User-Agent": "vskill-cli",
295
+ "Content-Type": "application/json",
296
+ }),
297
+ body: expect.any(String),
298
+ }));
299
+ // Body should include metadata fields
300
+ const body = JSON.parse(mockFetch.mock.calls[0][1].body);
301
+ expect(body.source).toBe("cli");
302
+ expect(body.platform).toBe(process.platform);
303
+ expect(body.cliVersion).toBeDefined();
304
+ });
305
+ it("sends repoUrl in body when provided", async () => {
306
+ mockFetch.mockResolvedValue(jsonResponse({ ok: true }));
307
+ await reportInstall("architect", "anton-abyzov/specweave");
308
+ const callArgs = mockFetch.mock.calls[0];
309
+ const body = JSON.parse(callArgs[1].body);
310
+ expect(body.repoUrl).toBe("anton-abyzov/specweave");
311
+ expect(body.source).toBe("cli");
312
+ });
313
+ it("encodes special characters in skill name", async () => {
314
+ mockFetch.mockResolvedValue(jsonResponse({ ok: true }));
315
+ await reportInstall("@org/my-skill");
316
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/skills/%40org%2Fmy-skill/installs`, expect.any(Object));
317
+ });
318
+ it("respects VSKILL_NO_TELEMETRY=1", async () => {
319
+ const orig = process.env.VSKILL_NO_TELEMETRY;
320
+ process.env.VSKILL_NO_TELEMETRY = "1";
321
+ try {
322
+ await reportInstall("my-skill");
323
+ expect(mockFetch).not.toHaveBeenCalled();
324
+ }
325
+ finally {
326
+ if (orig === undefined)
327
+ delete process.env.VSKILL_NO_TELEMETRY;
328
+ else
329
+ process.env.VSKILL_NO_TELEMETRY = orig;
330
+ }
331
+ });
332
+ it("swallows network errors silently", async () => {
333
+ mockFetch.mockRejectedValue(new TypeError("Failed to fetch"));
334
+ // Should not throw
335
+ await expect(reportInstall("my-skill")).resolves.toBeUndefined();
336
+ });
337
+ it("retries once on server error", async () => {
338
+ mockFetch
339
+ .mockResolvedValueOnce(errorResponse(500, "Internal Server Error"))
340
+ .mockResolvedValueOnce(jsonResponse({ ok: true }));
341
+ await reportInstall("my-skill");
342
+ expect(mockFetch).toHaveBeenCalledTimes(2);
343
+ });
344
+ it("retries once on network error then succeeds", async () => {
345
+ mockFetch
346
+ .mockRejectedValueOnce(new TypeError("Failed to fetch"))
347
+ .mockResolvedValueOnce(jsonResponse({ ok: true }));
348
+ await reportInstall("my-skill");
349
+ expect(mockFetch).toHaveBeenCalledTimes(2);
350
+ });
351
+ it("gives up after second failure", async () => {
352
+ mockFetch
353
+ .mockResolvedValueOnce(errorResponse(500, "Internal Server Error"))
354
+ .mockResolvedValueOnce(errorResponse(500, "Internal Server Error"));
355
+ // Should not throw
356
+ await expect(reportInstall("my-skill")).resolves.toBeUndefined();
357
+ expect(mockFetch).toHaveBeenCalledTimes(2);
358
+ });
359
+ it("passes an AbortSignal for timeout", async () => {
360
+ mockFetch.mockResolvedValue(jsonResponse({ ok: true }));
361
+ await reportInstall("my-skill");
362
+ const callArgs = mockFetch.mock.calls[0];
363
+ const options = callArgs[1];
364
+ expect(options.signal).toBeInstanceOf(AbortSignal);
365
+ });
366
+ });
367
+ describe("reportInstallBatch", () => {
368
+ it("sends POST to batch endpoint with skills array", async () => {
369
+ mockFetch.mockResolvedValue(jsonResponse({ ok: true, results: [] }));
370
+ await reportInstallBatch([
371
+ { skillName: "pm", repoUrl: "anton-abyzov/specweave" },
372
+ { skillName: "do", repoUrl: "anton-abyzov/specweave" },
373
+ ]);
374
+ expect(mockFetch).toHaveBeenCalledWith(`${BASE_URL}/api/v1/skills/installs`, expect.objectContaining({
375
+ method: "POST",
376
+ headers: expect.objectContaining({
377
+ "User-Agent": "vskill-cli",
378
+ "Content-Type": "application/json",
379
+ }),
380
+ body: expect.any(String),
381
+ }));
382
+ const body = JSON.parse(mockFetch.mock.calls[0][1].body);
383
+ expect(body.skills).toEqual([
384
+ { skillName: "pm", repoUrl: "anton-abyzov/specweave" },
385
+ { skillName: "do", repoUrl: "anton-abyzov/specweave" },
386
+ ]);
387
+ expect(body.source).toBe("cli");
388
+ expect(body.platform).toBe(process.platform);
389
+ expect(body.cliVersion).toBeDefined();
390
+ });
391
+ it("respects VSKILL_NO_TELEMETRY=1", async () => {
392
+ const orig = process.env.VSKILL_NO_TELEMETRY;
393
+ process.env.VSKILL_NO_TELEMETRY = "1";
394
+ try {
395
+ await reportInstallBatch([{ skillName: "pm" }]);
396
+ expect(mockFetch).not.toHaveBeenCalled();
397
+ }
398
+ finally {
399
+ if (orig === undefined)
400
+ delete process.env.VSKILL_NO_TELEMETRY;
401
+ else
402
+ process.env.VSKILL_NO_TELEMETRY = orig;
403
+ }
404
+ });
405
+ it("skips empty skills array", async () => {
406
+ await reportInstallBatch([]);
407
+ expect(mockFetch).not.toHaveBeenCalled();
408
+ });
409
+ it("retries once on server error", async () => {
410
+ mockFetch
411
+ .mockResolvedValueOnce(errorResponse(500, "Internal Server Error"))
412
+ .mockResolvedValueOnce(jsonResponse({ ok: true, results: [] }));
413
+ await reportInstallBatch([{ skillName: "pm" }]);
414
+ expect(mockFetch).toHaveBeenCalledTimes(2);
415
+ });
416
+ it("swallows errors silently", async () => {
417
+ mockFetch.mockRejectedValue(new TypeError("Failed to fetch"));
418
+ await expect(reportInstallBatch([{ skillName: "pm" }])).resolves.toBeUndefined();
419
+ });
420
+ it("passes an AbortSignal for timeout", async () => {
421
+ mockFetch.mockResolvedValue(jsonResponse({ ok: true, results: [] }));
422
+ await reportInstallBatch([{ skillName: "pm" }]);
423
+ const callArgs = mockFetch.mock.calls[0];
424
+ const options = callArgs[1];
425
+ expect(options.signal).toBeInstanceOf(AbortSignal);
426
+ });
427
+ });
428
+ //# sourceMappingURL=client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../src/api/client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,92 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { join } from "node:path";
3
+ import { discoverAuditFiles } from "./file-discovery.js";
4
+ import { runAuditScan } from "./audit-scanner.js";
5
+ import { createDefaultAuditConfig } from "./audit-types.js";
6
+ import { formatJson } from "./formatters/json-formatter.js";
7
+ import { formatSarif } from "./formatters/sarif-formatter.js";
8
+ import { attachFixSuggestions } from "./fix-suggestions.js";
9
+ import { loadAuditConfig } from "./config.js";
10
+ const FIXTURES = join(import.meta.dirname, "__fixtures__");
11
+ describe("audit integration", () => {
12
+ it("TC-054: clean project produces PASS verdict", async () => {
13
+ const config = createDefaultAuditConfig();
14
+ const files = await discoverAuditFiles(join(FIXTURES, "clean-project"), config);
15
+ const result = runAuditScan(files, config);
16
+ expect(result.findings).toHaveLength(0);
17
+ expect(result.summary.verdict).toBe("PASS");
18
+ expect(result.summary.score).toBe(100);
19
+ expect(result.filesScanned).toBe(2);
20
+ });
21
+ it("TC-055: vulnerable project detects all planted vulnerabilities", async () => {
22
+ const config = createDefaultAuditConfig();
23
+ const files = await discoverAuditFiles(join(FIXTURES, "vulnerable-project"), config);
24
+ const result = runAuditScan(files, config);
25
+ expect(result.findings.length).toBeGreaterThanOrEqual(5);
26
+ const ruleIds = result.findings.map((f) => f.ruleId);
27
+ // exec() detection
28
+ expect(ruleIds.some((id) => id.startsWith("CI-"))).toBe(true);
29
+ // eval() detection
30
+ expect(ruleIds.some((id) => id.startsWith("CE-"))).toBe(true);
31
+ // innerHTML detection
32
+ expect(ruleIds.some((id) => id.startsWith("XSS-"))).toBe(true);
33
+ // Hardcoded secret detection
34
+ expect(ruleIds.some((id) => id.startsWith("HS-"))).toBe(true);
35
+ // SQL injection detection
36
+ expect(ruleIds.some((id) => id.startsWith("SQLI-"))).toBe(true);
37
+ });
38
+ it("TC-056: JSON output is valid and complete", async () => {
39
+ const config = createDefaultAuditConfig();
40
+ const files = await discoverAuditFiles(join(FIXTURES, "mixed-project"), config);
41
+ const result = runAuditScan(files, config);
42
+ const json = formatJson(result);
43
+ const parsed = JSON.parse(json);
44
+ expect(parsed.findings).toBeDefined();
45
+ expect(parsed.summary).toBeDefined();
46
+ expect(parsed.summary.critical).toBeDefined();
47
+ expect(parsed.summary.high).toBeDefined();
48
+ expect(parsed.summary.medium).toBeDefined();
49
+ expect(parsed.summary.low).toBeDefined();
50
+ expect(parsed.summary.info).toBeDefined();
51
+ expect(parsed.summary.score).toBeGreaterThanOrEqual(0);
52
+ expect(parsed.summary.verdict).toBeDefined();
53
+ expect(parsed.filesScanned).toBe(2);
54
+ });
55
+ it("TC-057: SARIF output has correct structure", async () => {
56
+ const config = createDefaultAuditConfig();
57
+ const files = await discoverAuditFiles(join(FIXTURES, "vulnerable-project"), config);
58
+ const result = runAuditScan(files, config);
59
+ const sarif = formatSarif(result);
60
+ const parsed = JSON.parse(sarif);
61
+ expect(parsed.version).toBe("2.1.0");
62
+ expect(parsed.$schema).toContain("sarif");
63
+ expect(parsed.runs).toHaveLength(1);
64
+ expect(parsed.runs[0].tool.driver.name).toBe("vskill-audit");
65
+ expect(parsed.runs[0].results.length).toBeGreaterThanOrEqual(5);
66
+ // Each result has correct location structure
67
+ for (const r of parsed.runs[0].results) {
68
+ expect(r.ruleId).toBeDefined();
69
+ expect(r.message.text).toBeDefined();
70
+ expect(r.locations[0].physicalLocation.artifactLocation.uri).toBeDefined();
71
+ expect(r.locations[0].physicalLocation.region.startLine).toBeGreaterThan(0);
72
+ }
73
+ });
74
+ it("fix suggestions are attached when fix=true", async () => {
75
+ const config = createDefaultAuditConfig();
76
+ config.fix = true;
77
+ const files = await discoverAuditFiles(join(FIXTURES, "vulnerable-project"), config);
78
+ const result = runAuditScan(files, config);
79
+ const withFixes = attachFixSuggestions(result.findings, true);
80
+ // Every finding should have a suggestedFix
81
+ for (const f of withFixes) {
82
+ expect(f.suggestedFix).toBeDefined();
83
+ expect(f.suggestedFix.length).toBeGreaterThan(0);
84
+ }
85
+ });
86
+ it("config loading works end-to-end", async () => {
87
+ const config = await loadAuditConfig(join(FIXTURES, "clean-project"), {});
88
+ expect(config.maxFiles).toBe(500);
89
+ expect(config.excludePaths).toEqual([]);
90
+ });
91
+ });
92
+ //# sourceMappingURL=audit-integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-integration.test.js","sourceRoot":"","sources":["../../src/audit/audit-integration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAE3D,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAE3C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAE3C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAEzD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACrD,mBAAmB;QACnB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,mBAAmB;QACnB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,sBAAsB;QACtB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,6BAA6B;QAC7B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9D,0BAA0B;QAC1B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAElC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAEhE,6CAA6C;QAC7C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;YAC/B,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3E,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC;QAClB,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAC;QACrF,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAE9D,2CAA2C;QAC3C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;YACrC,MAAM,CAAC,CAAC,CAAC,YAAa,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};