@sporesec/arcana 2.2.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 (181) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +219 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/audit.d.ts +17 -0
  6. package/dist/commands/audit.d.ts.map +1 -0
  7. package/dist/commands/audit.js +157 -0
  8. package/dist/commands/audit.js.map +1 -0
  9. package/dist/commands/audit.test.d.ts +2 -0
  10. package/dist/commands/audit.test.d.ts.map +1 -0
  11. package/dist/commands/audit.test.js +217 -0
  12. package/dist/commands/audit.test.js.map +1 -0
  13. package/dist/commands/clean.d.ts +5 -0
  14. package/dist/commands/clean.d.ts.map +1 -0
  15. package/dist/commands/clean.js +125 -0
  16. package/dist/commands/clean.js.map +1 -0
  17. package/dist/commands/config.d.ts +4 -0
  18. package/dist/commands/config.d.ts.map +1 -0
  19. package/dist/commands/config.js +135 -0
  20. package/dist/commands/config.js.map +1 -0
  21. package/dist/commands/create.d.ts +2 -0
  22. package/dist/commands/create.d.ts.map +1 -0
  23. package/dist/commands/create.js +100 -0
  24. package/dist/commands/create.js.map +1 -0
  25. package/dist/commands/doctor.d.ts +6 -0
  26. package/dist/commands/doctor.d.ts.map +1 -0
  27. package/dist/commands/doctor.js +213 -0
  28. package/dist/commands/doctor.js.map +1 -0
  29. package/dist/commands/info.d.ts +5 -0
  30. package/dist/commands/info.d.ts.map +1 -0
  31. package/dist/commands/info.js +114 -0
  32. package/dist/commands/info.js.map +1 -0
  33. package/dist/commands/init.d.ts +13 -0
  34. package/dist/commands/init.d.ts.map +1 -0
  35. package/dist/commands/init.js +216 -0
  36. package/dist/commands/init.js.map +1 -0
  37. package/dist/commands/install.d.ts +8 -0
  38. package/dist/commands/install.d.ts.map +1 -0
  39. package/dist/commands/install.js +404 -0
  40. package/dist/commands/install.js.map +1 -0
  41. package/dist/commands/list.d.ts +8 -0
  42. package/dist/commands/list.d.ts.map +1 -0
  43. package/dist/commands/list.js +100 -0
  44. package/dist/commands/list.js.map +1 -0
  45. package/dist/commands/providers.d.ts +6 -0
  46. package/dist/commands/providers.d.ts.map +1 -0
  47. package/dist/commands/providers.js +103 -0
  48. package/dist/commands/providers.js.map +1 -0
  49. package/dist/commands/scan.d.ts +5 -0
  50. package/dist/commands/scan.d.ts.map +1 -0
  51. package/dist/commands/scan.js +110 -0
  52. package/dist/commands/scan.js.map +1 -0
  53. package/dist/commands/search.d.ts +6 -0
  54. package/dist/commands/search.d.ts.map +1 -0
  55. package/dist/commands/search.js +58 -0
  56. package/dist/commands/search.js.map +1 -0
  57. package/dist/commands/stats.d.ts +4 -0
  58. package/dist/commands/stats.d.ts.map +1 -0
  59. package/dist/commands/stats.js +143 -0
  60. package/dist/commands/stats.js.map +1 -0
  61. package/dist/commands/uninstall.d.ts +6 -0
  62. package/dist/commands/uninstall.d.ts.map +1 -0
  63. package/dist/commands/uninstall.js +163 -0
  64. package/dist/commands/uninstall.js.map +1 -0
  65. package/dist/commands/update.d.ts +7 -0
  66. package/dist/commands/update.d.ts.map +1 -0
  67. package/dist/commands/update.js +348 -0
  68. package/dist/commands/update.js.map +1 -0
  69. package/dist/commands/validate.d.ts +6 -0
  70. package/dist/commands/validate.d.ts.map +1 -0
  71. package/dist/commands/validate.js +140 -0
  72. package/dist/commands/validate.js.map +1 -0
  73. package/dist/index.d.ts +3 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +39 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/interactive.d.ts +2 -0
  78. package/dist/interactive.d.ts.map +1 -0
  79. package/dist/interactive.js +812 -0
  80. package/dist/interactive.js.map +1 -0
  81. package/dist/providers/arcana.d.ts +5 -0
  82. package/dist/providers/arcana.d.ts.map +1 -0
  83. package/dist/providers/arcana.js +11 -0
  84. package/dist/providers/arcana.js.map +1 -0
  85. package/dist/providers/base.d.ts +11 -0
  86. package/dist/providers/base.d.ts.map +1 -0
  87. package/dist/providers/base.js +10 -0
  88. package/dist/providers/base.js.map +1 -0
  89. package/dist/providers/github.d.ts +25 -0
  90. package/dist/providers/github.d.ts.map +1 -0
  91. package/dist/providers/github.js +146 -0
  92. package/dist/providers/github.js.map +1 -0
  93. package/dist/registry.d.ts +9 -0
  94. package/dist/registry.d.ts.map +1 -0
  95. package/dist/registry.js +71 -0
  96. package/dist/registry.js.map +1 -0
  97. package/dist/types.d.ts +67 -0
  98. package/dist/types.d.ts.map +1 -0
  99. package/dist/types.js +2 -0
  100. package/dist/types.js.map +1 -0
  101. package/dist/utils/atomic.d.ts +2 -0
  102. package/dist/utils/atomic.d.ts.map +1 -0
  103. package/dist/utils/atomic.js +20 -0
  104. package/dist/utils/atomic.js.map +1 -0
  105. package/dist/utils/atomic.test.d.ts +2 -0
  106. package/dist/utils/atomic.test.d.ts.map +1 -0
  107. package/dist/utils/atomic.test.js +31 -0
  108. package/dist/utils/atomic.test.js.map +1 -0
  109. package/dist/utils/cache.d.ts +4 -0
  110. package/dist/utils/cache.d.ts.map +1 -0
  111. package/dist/utils/cache.js +47 -0
  112. package/dist/utils/cache.js.map +1 -0
  113. package/dist/utils/config.d.ts +6 -0
  114. package/dist/utils/config.d.ts.map +1 -0
  115. package/dist/utils/config.js +90 -0
  116. package/dist/utils/config.js.map +1 -0
  117. package/dist/utils/config.test.d.ts +2 -0
  118. package/dist/utils/config.test.d.ts.map +1 -0
  119. package/dist/utils/config.test.js +38 -0
  120. package/dist/utils/config.test.js.map +1 -0
  121. package/dist/utils/errors.d.ts +6 -0
  122. package/dist/utils/errors.d.ts.map +1 -0
  123. package/dist/utils/errors.js +11 -0
  124. package/dist/utils/errors.js.map +1 -0
  125. package/dist/utils/frontmatter.d.ts +12 -0
  126. package/dist/utils/frontmatter.d.ts.map +1 -0
  127. package/dist/utils/frontmatter.js +172 -0
  128. package/dist/utils/frontmatter.js.map +1 -0
  129. package/dist/utils/frontmatter.test.d.ts +2 -0
  130. package/dist/utils/frontmatter.test.d.ts.map +1 -0
  131. package/dist/utils/frontmatter.test.js +152 -0
  132. package/dist/utils/frontmatter.test.js.map +1 -0
  133. package/dist/utils/fs.d.ts +16 -0
  134. package/dist/utils/fs.d.ts.map +1 -0
  135. package/dist/utils/fs.js +118 -0
  136. package/dist/utils/fs.js.map +1 -0
  137. package/dist/utils/fs.test.d.ts +2 -0
  138. package/dist/utils/fs.test.d.ts.map +1 -0
  139. package/dist/utils/fs.test.js +145 -0
  140. package/dist/utils/fs.test.js.map +1 -0
  141. package/dist/utils/help.d.ts +6 -0
  142. package/dist/utils/help.d.ts.map +1 -0
  143. package/dist/utils/help.js +117 -0
  144. package/dist/utils/help.js.map +1 -0
  145. package/dist/utils/help.test.d.ts +2 -0
  146. package/dist/utils/help.test.d.ts.map +1 -0
  147. package/dist/utils/help.test.js +66 -0
  148. package/dist/utils/help.test.js.map +1 -0
  149. package/dist/utils/history.d.ts +10 -0
  150. package/dist/utils/history.d.ts.map +1 -0
  151. package/dist/utils/history.js +58 -0
  152. package/dist/utils/history.js.map +1 -0
  153. package/dist/utils/http.d.ts +17 -0
  154. package/dist/utils/http.d.ts.map +1 -0
  155. package/dist/utils/http.js +165 -0
  156. package/dist/utils/http.js.map +1 -0
  157. package/dist/utils/http.test.d.ts +2 -0
  158. package/dist/utils/http.test.d.ts.map +1 -0
  159. package/dist/utils/http.test.js +55 -0
  160. package/dist/utils/http.test.js.map +1 -0
  161. package/dist/utils/parallel.d.ts +2 -0
  162. package/dist/utils/parallel.d.ts.map +1 -0
  163. package/dist/utils/parallel.js +17 -0
  164. package/dist/utils/parallel.js.map +1 -0
  165. package/dist/utils/scanner.d.ts +27 -0
  166. package/dist/utils/scanner.d.ts.map +1 -0
  167. package/dist/utils/scanner.js +195 -0
  168. package/dist/utils/scanner.js.map +1 -0
  169. package/dist/utils/ui.d.ts +27 -0
  170. package/dist/utils/ui.d.ts.map +1 -0
  171. package/dist/utils/ui.js +99 -0
  172. package/dist/utils/ui.js.map +1 -0
  173. package/dist/utils/ui.test.d.ts +2 -0
  174. package/dist/utils/ui.test.d.ts.map +1 -0
  175. package/dist/utils/ui.test.js +31 -0
  176. package/dist/utils/ui.test.js.map +1 -0
  177. package/dist/utils/validate.d.ts +2 -0
  178. package/dist/utils/validate.d.ts.map +1 -0
  179. package/dist/utils/validate.js +7 -0
  180. package/dist/utils/validate.js.map +1 -0
  181. package/package.json +62 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/utils/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AACtD,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;AAE7C,SAAS,cAAc;IACrB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,SAAS,CAAI,GAAW,EAAE,WAAmB,WAAW;IACtE,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ;YAAE,OAAO,IAAI,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAM,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAI,GAAW,EAAE,IAAO;IAChD,IAAI,CAAC;QACH,cAAc,EAAE,CAAC;QACjB,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;IAC3E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC;YAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACvD,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ArcanaConfig, ProviderConfig } from "../types.js";
2
+ export declare function loadConfig(): ArcanaConfig;
3
+ export declare function saveConfig(config: ArcanaConfig): void;
4
+ export declare function addProvider(provider: ProviderConfig): void;
5
+ export declare function removeProvider(name: string): boolean;
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAuBhE,wBAAgB,UAAU,IAAI,YAAY,CAiBzC;AAuBD,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAMrD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAS1D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOpD"}
@@ -0,0 +1,90 @@
1
+ import { existsSync, readFileSync, mkdirSync } from "node:fs";
2
+ import { join, dirname, isAbsolute } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { ui } from "./ui.js";
5
+ import { atomicWriteSync } from "./atomic.js";
6
+ const CONFIG_PATH = join(homedir(), ".arcana", "config.json");
7
+ const DEFAULT_CONFIG = {
8
+ defaultProvider: "arcana",
9
+ installDir: join(homedir(), ".agents", "skills"),
10
+ providers: [
11
+ {
12
+ name: "arcana",
13
+ type: "github",
14
+ url: "mahdy-gribkov/arcana",
15
+ enabled: true,
16
+ },
17
+ ],
18
+ };
19
+ function cloneConfig(config) {
20
+ return { ...config, providers: config.providers.map(p => ({ ...p })) };
21
+ }
22
+ export function loadConfig() {
23
+ if (!existsSync(CONFIG_PATH)) {
24
+ return applyEnvOverrides(cloneConfig(DEFAULT_CONFIG));
25
+ }
26
+ try {
27
+ const raw = readFileSync(CONFIG_PATH, "utf-8");
28
+ const loaded = JSON.parse(raw);
29
+ const config = {
30
+ ...DEFAULT_CONFIG,
31
+ ...loaded,
32
+ providers: loaded.providers ?? DEFAULT_CONFIG.providers.map(p => ({ ...p })),
33
+ };
34
+ return applyEnvOverrides(config);
35
+ }
36
+ catch {
37
+ console.error(ui.warn(" Warning: Config file is corrupted, using defaults"));
38
+ return applyEnvOverrides(cloneConfig(DEFAULT_CONFIG));
39
+ }
40
+ }
41
+ function applyEnvOverrides(base) {
42
+ const config = { ...base, providers: base.providers };
43
+ const envInstallDir = process.env.ARCANA_INSTALL_DIR;
44
+ if (envInstallDir) {
45
+ if (!isAbsolute(envInstallDir)) {
46
+ console.error(ui.warn(" Warning: ARCANA_INSTALL_DIR must be an absolute path. Ignoring."));
47
+ }
48
+ else {
49
+ config.installDir = envInstallDir;
50
+ }
51
+ }
52
+ const envProvider = process.env.ARCANA_DEFAULT_PROVIDER;
53
+ if (envProvider) {
54
+ if (envProvider.trim().length === 0) {
55
+ console.error(ui.warn(" Warning: ARCANA_DEFAULT_PROVIDER is empty. Ignoring."));
56
+ }
57
+ else {
58
+ config.defaultProvider = envProvider.trim();
59
+ }
60
+ }
61
+ return config;
62
+ }
63
+ export function saveConfig(config) {
64
+ const dir = dirname(CONFIG_PATH);
65
+ if (!existsSync(dir)) {
66
+ mkdirSync(dir, { recursive: true });
67
+ }
68
+ atomicWriteSync(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", 0o600);
69
+ }
70
+ export function addProvider(provider) {
71
+ const config = loadConfig();
72
+ const existing = config.providers.findIndex((p) => p.name === provider.name);
73
+ if (existing >= 0) {
74
+ config.providers[existing] = provider;
75
+ }
76
+ else {
77
+ config.providers.push(provider);
78
+ }
79
+ saveConfig(config);
80
+ }
81
+ export function removeProvider(name) {
82
+ const config = loadConfig();
83
+ const idx = config.providers.findIndex((p) => p.name === name);
84
+ if (idx < 0)
85
+ return false;
86
+ config.providers.splice(idx, 1);
87
+ saveConfig(config);
88
+ return true;
89
+ }
90
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/utils/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { describe, it, expect } from "vitest";
2
+ // Test loadConfig indirectly: verify the config module exports expected types
3
+ // Deep env override testing requires FS mocking which is fragile in ESM.
4
+ // Instead, test the observable contract.
5
+ describe("config module", () => {
6
+ it("loadConfig returns valid config shape", async () => {
7
+ const { loadConfig } = await import("./config.js");
8
+ const config = loadConfig();
9
+ expect(config).toHaveProperty("defaultProvider");
10
+ expect(config).toHaveProperty("installDir");
11
+ expect(config).toHaveProperty("providers");
12
+ expect(typeof config.defaultProvider).toBe("string");
13
+ expect(typeof config.installDir).toBe("string");
14
+ expect(Array.isArray(config.providers)).toBe(true);
15
+ });
16
+ it("loadConfig returns arcana as default provider", async () => {
17
+ const { loadConfig } = await import("./config.js");
18
+ const config = loadConfig();
19
+ // Default provider should always be arcana unless overridden
20
+ expect(config.defaultProvider).toBe("arcana");
21
+ });
22
+ it("loadConfig providers include arcana", async () => {
23
+ const { loadConfig } = await import("./config.js");
24
+ const config = loadConfig();
25
+ const arcana = config.providers.find((p) => p.name === "arcana");
26
+ expect(arcana).toBeDefined();
27
+ expect(arcana.type).toBe("github");
28
+ expect(arcana.enabled).toBe(true);
29
+ });
30
+ it("installDir is an absolute path", async () => {
31
+ const { loadConfig } = await import("./config.js");
32
+ const config = loadConfig();
33
+ // On Windows: starts with drive letter, on Unix: starts with /
34
+ const isAbsolute = config.installDir.startsWith("/") || /^[A-Z]:\\/i.test(config.installDir);
35
+ expect(isAbsolute).toBe(true);
36
+ });
37
+ });
38
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/utils/config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAM9C,8EAA8E;AAC9E,yEAAyE;AACzE,yCAAyC;AAEzC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,6DAA6D;QAC7D,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACjE,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7B,MAAM,CAAC,MAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,MAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,+DAA+D;QAC/D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC7F,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare class CliError extends Error {
2
+ readonly code: string;
3
+ readonly exitCode: number;
4
+ constructor(message: string, code?: string, exitCode?: number);
5
+ }
6
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAS,SAAQ,KAAK;aAGf,IAAI,EAAE,MAAM;aACZ,QAAQ,EAAE,MAAM;gBAFhC,OAAO,EAAE,MAAM,EACC,IAAI,GAAE,MAAoB,EAC1B,QAAQ,GAAE,MAAU;CAKvC"}
@@ -0,0 +1,11 @@
1
+ export class CliError extends Error {
2
+ code;
3
+ exitCode;
4
+ constructor(message, code = "CLI_ERROR", exitCode = 1) {
5
+ super(message);
6
+ this.code = code;
7
+ this.exitCode = exitCode;
8
+ this.name = "CliError";
9
+ }
10
+ }
11
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGf;IACA;IAHlB,YACE,OAAe,EACC,OAAe,WAAW,EAC1B,WAAmB,CAAC;QAEpC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,SAAI,GAAJ,IAAI,CAAsB;QAC1B,aAAQ,GAAR,QAAQ,CAAY;QAGpC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import type { SkillFrontmatter, ValidationResult } from "../types.js";
2
+ export declare const MIN_DESC_LENGTH = 80;
3
+ export declare const MAX_DESC_LENGTH = 1024;
4
+ export declare const NAME_REGEX: RegExp;
5
+ export declare function extractFrontmatter(content: string): {
6
+ raw: string;
7
+ body: string;
8
+ } | null;
9
+ export declare function parseFrontmatter(raw: string): SkillFrontmatter | null;
10
+ export declare function fixSkillFrontmatter(content: string): string;
11
+ export declare function validateSkillDir(skillDir: string, skillName: string): ValidationResult;
12
+ //# sourceMappingURL=frontmatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGtE,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,eAAe,OAAO,CAAC;AACpC,eAAO,MAAM,UAAU,QAAsB,CAAC;AAE9C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAiBxF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CA0DrE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgB3D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,gBAAgB,CA2EtF"}
@@ -0,0 +1,172 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const FM_DELIMITER = "---";
4
+ export const MIN_DESC_LENGTH = 80;
5
+ export const MAX_DESC_LENGTH = 1024;
6
+ export const NAME_REGEX = /^[a-z][a-z0-9-]*$/;
7
+ export function extractFrontmatter(content) {
8
+ const lines = content.split("\n");
9
+ if (lines[0]?.trim() !== FM_DELIMITER)
10
+ return null;
11
+ let endIdx = -1;
12
+ for (let i = 1; i < lines.length; i++) {
13
+ if (lines[i]?.trim() === FM_DELIMITER) {
14
+ endIdx = i;
15
+ break;
16
+ }
17
+ }
18
+ if (endIdx < 0)
19
+ return null;
20
+ const raw = lines.slice(1, endIdx).join("\n");
21
+ const body = lines.slice(endIdx + 1).join("\n");
22
+ return { raw, body };
23
+ }
24
+ export function parseFrontmatter(raw) {
25
+ let name = "";
26
+ let description = "";
27
+ const lines = raw.split("\n");
28
+ for (let i = 0; i < lines.length; i++) {
29
+ const line = lines[i];
30
+ if (!line)
31
+ continue;
32
+ const trimmed = line.trim();
33
+ const nameMatch = trimmed.match(/^name:\s*["']?(.+?)["']?\s*$/);
34
+ if (nameMatch?.[1]) {
35
+ name = nameMatch[1];
36
+ name = name.replace(/^["']|["']$/g, "");
37
+ continue;
38
+ }
39
+ const descMatch = trimmed.match(/^description:\s*(.*)$/);
40
+ if (descMatch?.[1] !== undefined) {
41
+ let value = descMatch[1].trim();
42
+ // Handle YAML multiline: |, >, or bare indented continuation
43
+ if (value === "|" || value === ">" || value === "") {
44
+ const multilineLines = [];
45
+ for (let j = i + 1; j < lines.length; j++) {
46
+ const next = lines[j];
47
+ if (next === undefined)
48
+ break;
49
+ // Empty lines: check if a subsequent indented line follows
50
+ if (next === "") {
51
+ let hasMore = false;
52
+ for (let k = j + 1; k < lines.length; k++) {
53
+ const peek = lines[k];
54
+ if (peek === undefined || peek === "")
55
+ continue;
56
+ if (peek[0] === " " || peek[0] === "\t")
57
+ hasMore = true;
58
+ break;
59
+ }
60
+ if (hasMore) {
61
+ multilineLines.push("");
62
+ continue;
63
+ }
64
+ break;
65
+ }
66
+ // Continuation lines must be indented
67
+ if (next[0] === " " || next[0] === "\t") {
68
+ multilineLines.push(next.trim());
69
+ }
70
+ else {
71
+ break;
72
+ }
73
+ }
74
+ if (multilineLines.length > 0) {
75
+ description = multilineLines.join(value === "|" ? "\n" : " ");
76
+ }
77
+ }
78
+ else {
79
+ value = value.replace(/^["']|["']$/g, "");
80
+ description = value;
81
+ }
82
+ }
83
+ }
84
+ if (!name || !NAME_REGEX.test(name))
85
+ return null;
86
+ return { name, description };
87
+ }
88
+ export function fixSkillFrontmatter(content) {
89
+ const extracted = extractFrontmatter(content);
90
+ if (!extracted)
91
+ return content;
92
+ const parsed = parseFrontmatter(extracted.raw);
93
+ if (!parsed)
94
+ return content;
95
+ // Rebuild clean frontmatter with only name and description
96
+ const cleanFm = [
97
+ FM_DELIMITER,
98
+ `name: ${parsed.name}`,
99
+ `description: ${parsed.description}`,
100
+ FM_DELIMITER,
101
+ ].join("\n");
102
+ return cleanFm + "\n" + extracted.body.replace(/^\n+/, "\n");
103
+ }
104
+ export function validateSkillDir(skillDir, skillName) {
105
+ const result = {
106
+ skill: skillName,
107
+ valid: true,
108
+ errors: [],
109
+ warnings: [],
110
+ infos: [],
111
+ };
112
+ const skillMd = join(skillDir, "SKILL.md");
113
+ if (!existsSync(skillMd)) {
114
+ result.valid = false;
115
+ result.errors.push("Missing SKILL.md");
116
+ return result;
117
+ }
118
+ let content;
119
+ try {
120
+ content = readFileSync(skillMd, "utf-8");
121
+ }
122
+ catch {
123
+ result.valid = false;
124
+ result.errors.push("Cannot read SKILL.md");
125
+ return result;
126
+ }
127
+ const extracted = extractFrontmatter(content);
128
+ if (!extracted) {
129
+ result.valid = false;
130
+ result.errors.push("Missing or malformed frontmatter delimiters (---)");
131
+ return result;
132
+ }
133
+ const parsed = parseFrontmatter(extracted.raw);
134
+ if (!parsed) {
135
+ result.valid = false;
136
+ result.errors.push("Cannot parse name from frontmatter");
137
+ return result;
138
+ }
139
+ if (!parsed.description) {
140
+ result.warnings.push("Missing description in frontmatter");
141
+ }
142
+ else if (parsed.description.length < MIN_DESC_LENGTH) {
143
+ result.warnings.push(`Description too short (${parsed.description.length} chars, recommend ${MIN_DESC_LENGTH}+)`);
144
+ }
145
+ else if (parsed.description.length > MAX_DESC_LENGTH) {
146
+ result.warnings.push(`Description too long (${parsed.description.length} chars, max ${MAX_DESC_LENGTH})`);
147
+ }
148
+ // Check for non-standard fields
149
+ const standardFields = ["name", "description"];
150
+ for (const line of extracted.raw.split("\n")) {
151
+ const keyMatch = line.match(/^(\w[\w-]*):/);
152
+ if (keyMatch?.[1] && !standardFields.includes(keyMatch[1])) {
153
+ result.infos.push(`Non-standard field: ${keyMatch[1]}`);
154
+ }
155
+ }
156
+ if (parsed.name !== skillName) {
157
+ result.warnings.push(`Name mismatch: frontmatter says "${parsed.name}", directory is "${skillName}"`);
158
+ }
159
+ if (parsed.description && (parsed.description.startsWith('"') || parsed.description.startsWith("'"))) {
160
+ result.warnings.push("Description starts with a quote character (likely a YAML quoting issue)");
161
+ }
162
+ if (extracted.body.trim().length < 50) {
163
+ result.warnings.push("SKILL.md body is very short (less than 50 chars)");
164
+ }
165
+ if (extracted.body.trim().length >= 50 && !extracted.body.includes("##")) {
166
+ result.infos.push("Body has no ## headings (recommended for structure)");
167
+ }
168
+ if (result.errors.length > 0)
169
+ result.valid = false;
170
+ return result;
171
+ }
172
+ //# sourceMappingURL=frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=frontmatter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.test.d.ts","sourceRoot":"","sources":["../../src/utils/frontmatter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,152 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { mkdtempSync, writeFileSync, mkdirSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { tmpdir } from "node:os";
5
+ import { extractFrontmatter, parseFrontmatter, fixSkillFrontmatter, validateSkillDir, NAME_REGEX, MIN_DESC_LENGTH, } from "./frontmatter.js";
6
+ function makeTempSkill(name, content) {
7
+ const base = mkdtempSync(join(tmpdir(), "arcana-test-"));
8
+ const skillDir = join(base, name);
9
+ mkdirSync(skillDir, { recursive: true });
10
+ writeFileSync(join(skillDir, "SKILL.md"), content, "utf-8");
11
+ return skillDir;
12
+ }
13
+ describe("NAME_REGEX", () => {
14
+ it("accepts valid names", () => {
15
+ expect(NAME_REGEX.test("a")).toBe(true);
16
+ expect(NAME_REGEX.test("foo-bar")).toBe(true);
17
+ expect(NAME_REGEX.test("a1-b2")).toBe(true);
18
+ expect(NAME_REGEX.test("my-skill-123")).toBe(true);
19
+ });
20
+ it("rejects invalid names", () => {
21
+ expect(NAME_REGEX.test("Foo")).toBe(false);
22
+ expect(NAME_REGEX.test("-bar")).toBe(false);
23
+ expect(NAME_REGEX.test("foo_bar")).toBe(false);
24
+ expect(NAME_REGEX.test("1abc")).toBe(false);
25
+ expect(NAME_REGEX.test("")).toBe(false);
26
+ expect(NAME_REGEX.test("FOO")).toBe(false);
27
+ });
28
+ });
29
+ describe("extractFrontmatter", () => {
30
+ it("extracts valid frontmatter", () => {
31
+ const content = "---\nname: test\ndescription: hello\n---\n# Body";
32
+ const result = extractFrontmatter(content);
33
+ expect(result).not.toBeNull();
34
+ expect(result.raw).toBe("name: test\ndescription: hello");
35
+ expect(result.body).toBe("# Body");
36
+ });
37
+ it("returns null for missing opening delimiter", () => {
38
+ expect(extractFrontmatter("name: test\n---\n# Body")).toBeNull();
39
+ });
40
+ it("returns null for missing closing delimiter", () => {
41
+ expect(extractFrontmatter("---\nname: test\n# Body")).toBeNull();
42
+ });
43
+ it("returns null for empty content", () => {
44
+ expect(extractFrontmatter("")).toBeNull();
45
+ });
46
+ it("handles empty frontmatter block", () => {
47
+ const result = extractFrontmatter("---\n---\nBody");
48
+ expect(result).not.toBeNull();
49
+ expect(result.raw).toBe("");
50
+ expect(result.body).toBe("Body");
51
+ });
52
+ });
53
+ describe("parseFrontmatter", () => {
54
+ it("parses name and description", () => {
55
+ const result = parseFrontmatter("name: my-skill\ndescription: A useful skill");
56
+ expect(result).not.toBeNull();
57
+ expect(result.name).toBe("my-skill");
58
+ expect(result.description).toBe("A useful skill");
59
+ });
60
+ it("strips quotes from name", () => {
61
+ const result = parseFrontmatter('name: "my-skill"\ndescription: test');
62
+ expect(result).not.toBeNull();
63
+ expect(result.name).toBe("my-skill");
64
+ });
65
+ it("handles YAML | multiline description", () => {
66
+ const raw = "name: test\ndescription: |\n Line one\n Line two";
67
+ const result = parseFrontmatter(raw);
68
+ expect(result).not.toBeNull();
69
+ expect(result.description).toBe("Line one\nLine two");
70
+ });
71
+ it("handles YAML > folded description", () => {
72
+ const raw = "name: test\ndescription: >\n Line one\n Line two";
73
+ const result = parseFrontmatter(raw);
74
+ expect(result).not.toBeNull();
75
+ expect(result.description).toBe("Line one Line two");
76
+ });
77
+ it("handles bare indented continuation", () => {
78
+ const raw = "name: test\ndescription:\n Use this skill to do something great and wonderful";
79
+ const result = parseFrontmatter(raw);
80
+ expect(result).not.toBeNull();
81
+ expect(result.description).toBe("Use this skill to do something great and wonderful");
82
+ });
83
+ it("strips quotes from description", () => {
84
+ const result = parseFrontmatter('name: test\ndescription: "A quoted desc"');
85
+ expect(result).not.toBeNull();
86
+ expect(result.description).toBe("A quoted desc");
87
+ });
88
+ it("returns null for invalid name", () => {
89
+ expect(parseFrontmatter("name: INVALID\ndescription: test")).toBeNull();
90
+ expect(parseFrontmatter("name: -bad\ndescription: test")).toBeNull();
91
+ });
92
+ it("returns null when name is missing", () => {
93
+ expect(parseFrontmatter("description: test")).toBeNull();
94
+ });
95
+ });
96
+ describe("fixSkillFrontmatter", () => {
97
+ it("rebuilds clean frontmatter", () => {
98
+ const content = "---\nname: test\ndescription: hello\nextra: field\n---\n# Body";
99
+ const fixed = fixSkillFrontmatter(content);
100
+ expect(fixed).toContain("name: test");
101
+ expect(fixed).toContain("description: hello");
102
+ expect(fixed).not.toContain("extra: field");
103
+ });
104
+ it("preserves body content", () => {
105
+ const content = "---\nname: test\ndescription: hello\n---\n# My Body\nContent here";
106
+ const fixed = fixSkillFrontmatter(content);
107
+ expect(fixed).toContain("# My Body");
108
+ expect(fixed).toContain("Content here");
109
+ });
110
+ it("returns original when no frontmatter", () => {
111
+ const content = "No frontmatter here";
112
+ expect(fixSkillFrontmatter(content)).toBe(content);
113
+ });
114
+ it("returns original when name cannot be parsed", () => {
115
+ const content = "---\ndescription: no name\n---\nBody";
116
+ expect(fixSkillFrontmatter(content)).toBe(content);
117
+ });
118
+ });
119
+ describe("validateSkillDir", () => {
120
+ const longDesc = "A".repeat(MIN_DESC_LENGTH);
121
+ it("returns error for missing SKILL.md", () => {
122
+ const dir = mkdtempSync(join(tmpdir(), "arcana-test-"));
123
+ const result = validateSkillDir(dir, "test");
124
+ expect(result.valid).toBe(false);
125
+ expect(result.errors).toContain("Missing SKILL.md");
126
+ });
127
+ it("returns warning for short description", () => {
128
+ const dir = makeTempSkill("short-desc", "---\nname: short-desc\ndescription: Too short\n---\n# Body content goes here, needs at least 50 chars in the body section");
129
+ const result = validateSkillDir(dir, "short-desc");
130
+ expect(result.valid).toBe(true);
131
+ expect(result.warnings.some((w) => w.includes("too short"))).toBe(true);
132
+ });
133
+ it("returns warning for name mismatch", () => {
134
+ const dir = makeTempSkill("wrong-name", `---\nname: other-name\ndescription: ${longDesc}\n---\n## Heading\nBody content goes here, needs at least 50 chars in the body section`);
135
+ const result = validateSkillDir(dir, "wrong-name");
136
+ expect(result.warnings.some((w) => w.includes("mismatch"))).toBe(true);
137
+ });
138
+ it("passes valid skill with no warnings", () => {
139
+ const dir = makeTempSkill("valid-skill", `---\nname: valid-skill\ndescription: ${longDesc}\n---\n## Heading\nBody content goes here, needs at least 50 chars in the body section`);
140
+ const result = validateSkillDir(dir, "valid-skill");
141
+ expect(result.valid).toBe(true);
142
+ expect(result.errors).toHaveLength(0);
143
+ expect(result.warnings).toHaveLength(0);
144
+ });
145
+ it("returns error for malformed frontmatter", () => {
146
+ const dir = makeTempSkill("bad-fm", "no frontmatter here");
147
+ const result = validateSkillDir(dir, "bad-fm");
148
+ expect(result.valid).toBe(false);
149
+ expect(result.errors.some((e) => e.includes("frontmatter"))).toBe(true);
150
+ });
151
+ });
152
+ //# sourceMappingURL=frontmatter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.test.js","sourceRoot":"","sources":["../../src/utils/frontmatter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { SkillFile, SkillMeta } from "../types.js";
2
+ export declare function getInstallDir(): string;
3
+ export declare function getSkillDir(name: string): string;
4
+ export declare function getDirSize(dir: string): number;
5
+ export declare function installSkill(skillName: string, files: SkillFile[]): string;
6
+ export declare function isSkillInstalled(skillName: string): boolean;
7
+ export declare function readSkillMeta(skillName: string): SkillMeta | null;
8
+ export declare function writeSkillMeta(skillName: string, meta: SkillMeta): void;
9
+ export interface SymlinkInfo {
10
+ name: string;
11
+ fullPath: string;
12
+ target: string;
13
+ broken: boolean;
14
+ }
15
+ export declare function listSymlinks(): SymlinkInfo[];
16
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkB9C;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,CA4C1E;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D;AAID,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAQjE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAIvE;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,YAAY,IAAI,WAAW,EAAE,CAgB5C"}