@mycelish/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/LICENSE +21 -0
  2. package/dist/__tests__/init-auto.test.d.ts +2 -0
  3. package/dist/__tests__/init-auto.test.d.ts.map +1 -0
  4. package/dist/__tests__/init-auto.test.js +60 -0
  5. package/dist/__tests__/init-auto.test.js.map +1 -0
  6. package/dist/commands/add.d.ts +20 -0
  7. package/dist/commands/add.d.ts.map +1 -0
  8. package/dist/commands/add.js +99 -0
  9. package/dist/commands/add.js.map +1 -0
  10. package/dist/commands/add.test.d.ts +25 -0
  11. package/dist/commands/add.test.d.ts.map +1 -0
  12. package/dist/commands/add.test.js +574 -0
  13. package/dist/commands/add.test.js.map +1 -0
  14. package/dist/commands/disable.d.ts +33 -0
  15. package/dist/commands/disable.d.ts.map +1 -0
  16. package/dist/commands/disable.js +201 -0
  17. package/dist/commands/disable.js.map +1 -0
  18. package/dist/commands/disable.test.d.ts +6 -0
  19. package/dist/commands/disable.test.d.ts.map +1 -0
  20. package/dist/commands/disable.test.js +290 -0
  21. package/dist/commands/disable.test.js.map +1 -0
  22. package/dist/commands/doctor.d.ts +11 -0
  23. package/dist/commands/doctor.d.ts.map +1 -0
  24. package/dist/commands/doctor.js +33 -0
  25. package/dist/commands/doctor.js.map +1 -0
  26. package/dist/commands/doctor.test.d.ts +17 -0
  27. package/dist/commands/doctor.test.d.ts.map +1 -0
  28. package/dist/commands/doctor.test.js +691 -0
  29. package/dist/commands/doctor.test.js.map +1 -0
  30. package/dist/commands/enable.d.ts +33 -0
  31. package/dist/commands/enable.d.ts.map +1 -0
  32. package/dist/commands/enable.js +199 -0
  33. package/dist/commands/enable.js.map +1 -0
  34. package/dist/commands/enable.test.d.ts +6 -0
  35. package/dist/commands/enable.test.d.ts.map +1 -0
  36. package/dist/commands/enable.test.js +301 -0
  37. package/dist/commands/enable.test.js.map +1 -0
  38. package/dist/commands/health-checks/config-check.d.ts +34 -0
  39. package/dist/commands/health-checks/config-check.d.ts.map +1 -0
  40. package/dist/commands/health-checks/config-check.js +267 -0
  41. package/dist/commands/health-checks/config-check.js.map +1 -0
  42. package/dist/commands/health-checks/formatter.d.ts +13 -0
  43. package/dist/commands/health-checks/formatter.d.ts.map +1 -0
  44. package/dist/commands/health-checks/formatter.js +72 -0
  45. package/dist/commands/health-checks/formatter.js.map +1 -0
  46. package/dist/commands/health-checks/index.d.ts +8 -0
  47. package/dist/commands/health-checks/index.d.ts.map +1 -0
  48. package/dist/commands/health-checks/index.js +7 -0
  49. package/dist/commands/health-checks/index.js.map +1 -0
  50. package/dist/commands/health-checks/mcp-check.d.ts +9 -0
  51. package/dist/commands/health-checks/mcp-check.d.ts.map +1 -0
  52. package/dist/commands/health-checks/mcp-check.js +37 -0
  53. package/dist/commands/health-checks/mcp-check.js.map +1 -0
  54. package/dist/commands/health-checks/memory-check.d.ts +15 -0
  55. package/dist/commands/health-checks/memory-check.d.ts.map +1 -0
  56. package/dist/commands/health-checks/memory-check.js +92 -0
  57. package/dist/commands/health-checks/memory-check.js.map +1 -0
  58. package/dist/commands/health-checks/runner.d.ts +9 -0
  59. package/dist/commands/health-checks/runner.d.ts.map +1 -0
  60. package/dist/commands/health-checks/runner.js +74 -0
  61. package/dist/commands/health-checks/runner.js.map +1 -0
  62. package/dist/commands/health-checks/tool-version-check.d.ts +9 -0
  63. package/dist/commands/health-checks/tool-version-check.d.ts.map +1 -0
  64. package/dist/commands/health-checks/tool-version-check.js +35 -0
  65. package/dist/commands/health-checks/tool-version-check.js.map +1 -0
  66. package/dist/commands/health-checks/types.d.ts +16 -0
  67. package/dist/commands/health-checks/types.d.ts.map +1 -0
  68. package/dist/commands/health-checks/types.js +2 -0
  69. package/dist/commands/health-checks/types.js.map +1 -0
  70. package/dist/commands/init.d.ts +120 -0
  71. package/dist/commands/init.d.ts.map +1 -0
  72. package/dist/commands/init.js +436 -0
  73. package/dist/commands/init.js.map +1 -0
  74. package/dist/commands/init.test.d.ts +16 -0
  75. package/dist/commands/init.test.d.ts.map +1 -0
  76. package/dist/commands/init.test.js +286 -0
  77. package/dist/commands/init.test.js.map +1 -0
  78. package/dist/commands/marketplace.d.ts +13 -0
  79. package/dist/commands/marketplace.d.ts.map +1 -0
  80. package/dist/commands/marketplace.js +85 -0
  81. package/dist/commands/marketplace.js.map +1 -0
  82. package/dist/commands/marketplace.test.d.ts +2 -0
  83. package/dist/commands/marketplace.test.d.ts.map +1 -0
  84. package/dist/commands/marketplace.test.js +78 -0
  85. package/dist/commands/marketplace.test.js.map +1 -0
  86. package/dist/commands/migrate.d.ts +15 -0
  87. package/dist/commands/migrate.d.ts.map +1 -0
  88. package/dist/commands/migrate.js +179 -0
  89. package/dist/commands/migrate.js.map +1 -0
  90. package/dist/commands/migrate.test.d.ts +2 -0
  91. package/dist/commands/migrate.test.d.ts.map +1 -0
  92. package/dist/commands/migrate.test.js +109 -0
  93. package/dist/commands/migrate.test.js.map +1 -0
  94. package/dist/commands/preset.d.ts +11 -0
  95. package/dist/commands/preset.d.ts.map +1 -0
  96. package/dist/commands/preset.js +99 -0
  97. package/dist/commands/preset.js.map +1 -0
  98. package/dist/commands/preset.test.d.ts +2 -0
  99. package/dist/commands/preset.test.d.ts.map +1 -0
  100. package/dist/commands/preset.test.js +106 -0
  101. package/dist/commands/preset.test.js.map +1 -0
  102. package/dist/commands/remote.d.ts +9 -0
  103. package/dist/commands/remote.d.ts.map +1 -0
  104. package/dist/commands/remote.js +212 -0
  105. package/dist/commands/remote.js.map +1 -0
  106. package/dist/commands/remote.test.d.ts +2 -0
  107. package/dist/commands/remote.test.d.ts.map +1 -0
  108. package/dist/commands/remote.test.js +125 -0
  109. package/dist/commands/remote.test.js.map +1 -0
  110. package/dist/commands/remove.d.ts +34 -0
  111. package/dist/commands/remove.d.ts.map +1 -0
  112. package/dist/commands/remove.js +296 -0
  113. package/dist/commands/remove.js.map +1 -0
  114. package/dist/commands/remove.test.d.ts +2 -0
  115. package/dist/commands/remove.test.d.ts.map +1 -0
  116. package/dist/commands/remove.test.js +109 -0
  117. package/dist/commands/remove.test.js.map +1 -0
  118. package/dist/commands/serve.d.ts +3 -0
  119. package/dist/commands/serve.d.ts.map +1 -0
  120. package/dist/commands/serve.js +29 -0
  121. package/dist/commands/serve.js.map +1 -0
  122. package/dist/commands/serve.test.d.ts +2 -0
  123. package/dist/commands/serve.test.d.ts.map +1 -0
  124. package/dist/commands/serve.test.js +74 -0
  125. package/dist/commands/serve.test.js.map +1 -0
  126. package/dist/commands/status.d.ts +49 -0
  127. package/dist/commands/status.d.ts.map +1 -0
  128. package/dist/commands/status.js +272 -0
  129. package/dist/commands/status.js.map +1 -0
  130. package/dist/commands/status.test.d.ts +11 -0
  131. package/dist/commands/status.test.d.ts.map +1 -0
  132. package/dist/commands/status.test.js +334 -0
  133. package/dist/commands/status.test.js.map +1 -0
  134. package/dist/commands/sync.d.ts +38 -0
  135. package/dist/commands/sync.d.ts.map +1 -0
  136. package/dist/commands/sync.js +286 -0
  137. package/dist/commands/sync.js.map +1 -0
  138. package/dist/commands/sync.test.d.ts +6 -0
  139. package/dist/commands/sync.test.d.ts.map +1 -0
  140. package/dist/commands/sync.test.js +341 -0
  141. package/dist/commands/sync.test.js.map +1 -0
  142. package/dist/commands/teams.d.ts +18 -0
  143. package/dist/commands/teams.d.ts.map +1 -0
  144. package/dist/commands/teams.js +68 -0
  145. package/dist/commands/teams.js.map +1 -0
  146. package/dist/commands/teams.test.d.ts +2 -0
  147. package/dist/commands/teams.test.d.ts.map +1 -0
  148. package/dist/commands/teams.test.js +94 -0
  149. package/dist/commands/teams.test.js.map +1 -0
  150. package/dist/core/adapter-base.d.ts +51 -0
  151. package/dist/core/adapter-base.d.ts.map +1 -0
  152. package/dist/core/adapter-base.js +89 -0
  153. package/dist/core/adapter-base.js.map +1 -0
  154. package/dist/core/add-helpers.d.ts +55 -0
  155. package/dist/core/add-helpers.d.ts.map +1 -0
  156. package/dist/core/add-helpers.js +273 -0
  157. package/dist/core/add-helpers.js.map +1 -0
  158. package/dist/core/agent-teams.d.ts +10 -0
  159. package/dist/core/agent-teams.d.ts.map +1 -0
  160. package/dist/core/agent-teams.js +40 -0
  161. package/dist/core/agent-teams.js.map +1 -0
  162. package/dist/core/agent-teams.test.d.ts +2 -0
  163. package/dist/core/agent-teams.test.d.ts.map +1 -0
  164. package/dist/core/agent-teams.test.js +64 -0
  165. package/dist/core/agent-teams.test.js.map +1 -0
  166. package/dist/core/auto-adapter.d.ts +27 -0
  167. package/dist/core/auto-adapter.d.ts.map +1 -0
  168. package/dist/core/auto-adapter.js +324 -0
  169. package/dist/core/auto-adapter.js.map +1 -0
  170. package/dist/core/auto-adapter.test.d.ts +2 -0
  171. package/dist/core/auto-adapter.test.d.ts.map +1 -0
  172. package/dist/core/auto-adapter.test.js +125 -0
  173. package/dist/core/auto-adapter.test.js.map +1 -0
  174. package/dist/core/config-merger.d.ts +33 -0
  175. package/dist/core/config-merger.d.ts.map +1 -0
  176. package/dist/core/config-merger.js +238 -0
  177. package/dist/core/config-merger.js.map +1 -0
  178. package/dist/core/config-merger.test.d.ts +10 -0
  179. package/dist/core/config-merger.test.d.ts.map +1 -0
  180. package/dist/core/config-merger.test.js +406 -0
  181. package/dist/core/config-merger.test.js.map +1 -0
  182. package/dist/core/conflict-detector.d.ts +23 -0
  183. package/dist/core/conflict-detector.d.ts.map +1 -0
  184. package/dist/core/conflict-detector.js +58 -0
  185. package/dist/core/conflict-detector.js.map +1 -0
  186. package/dist/core/conflict-detector.test.d.ts +2 -0
  187. package/dist/core/conflict-detector.test.d.ts.map +1 -0
  188. package/dist/core/conflict-detector.test.js +40 -0
  189. package/dist/core/conflict-detector.test.js.map +1 -0
  190. package/dist/core/env-template.d.ts +22 -0
  191. package/dist/core/env-template.d.ts.map +1 -0
  192. package/dist/core/env-template.js +125 -0
  193. package/dist/core/env-template.js.map +1 -0
  194. package/dist/core/env-template.test.d.ts +2 -0
  195. package/dist/core/env-template.test.d.ts.map +1 -0
  196. package/dist/core/env-template.test.js +145 -0
  197. package/dist/core/env-template.test.js.map +1 -0
  198. package/dist/core/fs-helpers.d.ts +8 -0
  199. package/dist/core/fs-helpers.d.ts.map +1 -0
  200. package/dist/core/fs-helpers.js +26 -0
  201. package/dist/core/fs-helpers.js.map +1 -0
  202. package/dist/core/fs-helpers.test.d.ts +2 -0
  203. package/dist/core/fs-helpers.test.d.ts.map +1 -0
  204. package/dist/core/fs-helpers.test.js +51 -0
  205. package/dist/core/fs-helpers.test.js.map +1 -0
  206. package/dist/core/machine-overrides.d.ts +13 -0
  207. package/dist/core/machine-overrides.d.ts.map +1 -0
  208. package/dist/core/machine-overrides.js +155 -0
  209. package/dist/core/machine-overrides.js.map +1 -0
  210. package/dist/core/machine-overrides.test.d.ts +2 -0
  211. package/dist/core/machine-overrides.test.d.ts.map +1 -0
  212. package/dist/core/machine-overrides.test.js +160 -0
  213. package/dist/core/machine-overrides.test.js.map +1 -0
  214. package/dist/core/marketplace-registry.d.ts +14 -0
  215. package/dist/core/marketplace-registry.d.ts.map +1 -0
  216. package/dist/core/marketplace-registry.js +215 -0
  217. package/dist/core/marketplace-registry.js.map +1 -0
  218. package/dist/core/marketplace-registry.test.d.ts +2 -0
  219. package/dist/core/marketplace-registry.test.d.ts.map +1 -0
  220. package/dist/core/marketplace-registry.test.js +232 -0
  221. package/dist/core/marketplace-registry.test.js.map +1 -0
  222. package/dist/core/marketplace-sources.d.ts +39 -0
  223. package/dist/core/marketplace-sources.d.ts.map +1 -0
  224. package/dist/core/marketplace-sources.js +199 -0
  225. package/dist/core/marketplace-sources.js.map +1 -0
  226. package/dist/core/marketplace.d.ts +18 -0
  227. package/dist/core/marketplace.d.ts.map +1 -0
  228. package/dist/core/marketplace.js +211 -0
  229. package/dist/core/marketplace.js.map +1 -0
  230. package/dist/core/marketplace.test.d.ts +2 -0
  231. package/dist/core/marketplace.test.d.ts.map +1 -0
  232. package/dist/core/marketplace.test.js +177 -0
  233. package/dist/core/marketplace.test.js.map +1 -0
  234. package/dist/core/mcp-injector.d.ts +43 -0
  235. package/dist/core/mcp-injector.d.ts.map +1 -0
  236. package/dist/core/mcp-injector.js +164 -0
  237. package/dist/core/mcp-injector.js.map +1 -0
  238. package/dist/core/mcp-injector.test.d.ts +6 -0
  239. package/dist/core/mcp-injector.test.d.ts.map +1 -0
  240. package/dist/core/mcp-injector.test.js +315 -0
  241. package/dist/core/mcp-injector.test.js.map +1 -0
  242. package/dist/core/mcp-registry.d.ts +17 -0
  243. package/dist/core/mcp-registry.d.ts.map +1 -0
  244. package/dist/core/mcp-registry.js +52 -0
  245. package/dist/core/mcp-registry.js.map +1 -0
  246. package/dist/core/mcp-registry.test.d.ts +2 -0
  247. package/dist/core/mcp-registry.test.d.ts.map +1 -0
  248. package/dist/core/mcp-registry.test.js +78 -0
  249. package/dist/core/mcp-registry.test.js.map +1 -0
  250. package/dist/core/mcp-router.d.ts +21 -0
  251. package/dist/core/mcp-router.d.ts.map +1 -0
  252. package/dist/core/mcp-router.js +67 -0
  253. package/dist/core/mcp-router.js.map +1 -0
  254. package/dist/core/mcp-router.test.d.ts +2 -0
  255. package/dist/core/mcp-router.test.d.ts.map +1 -0
  256. package/dist/core/mcp-router.test.js +40 -0
  257. package/dist/core/mcp-router.test.js.map +1 -0
  258. package/dist/core/memory-scoper.d.ts +43 -0
  259. package/dist/core/memory-scoper.d.ts.map +1 -0
  260. package/dist/core/memory-scoper.js +165 -0
  261. package/dist/core/memory-scoper.js.map +1 -0
  262. package/dist/core/memory-scoper.test.d.ts +6 -0
  263. package/dist/core/memory-scoper.test.d.ts.map +1 -0
  264. package/dist/core/memory-scoper.test.js +467 -0
  265. package/dist/core/memory-scoper.test.js.map +1 -0
  266. package/dist/core/migrator/executor.d.ts +9 -0
  267. package/dist/core/migrator/executor.d.ts.map +1 -0
  268. package/dist/core/migrator/executor.js +233 -0
  269. package/dist/core/migrator/executor.js.map +1 -0
  270. package/dist/core/migrator/index.d.ts +8 -0
  271. package/dist/core/migrator/index.d.ts.map +1 -0
  272. package/dist/core/migrator/index.js +12 -0
  273. package/dist/core/migrator/index.js.map +1 -0
  274. package/dist/core/migrator/manifest.d.ts +8 -0
  275. package/dist/core/migrator/manifest.d.ts.map +1 -0
  276. package/dist/core/migrator/manifest.js +83 -0
  277. package/dist/core/migrator/manifest.js.map +1 -0
  278. package/dist/core/migrator/planner.d.ts +6 -0
  279. package/dist/core/migrator/planner.d.ts.map +1 -0
  280. package/dist/core/migrator/planner.js +112 -0
  281. package/dist/core/migrator/planner.js.map +1 -0
  282. package/dist/core/migrator/scanners.d.ts +19 -0
  283. package/dist/core/migrator/scanners.d.ts.map +1 -0
  284. package/dist/core/migrator/scanners.js +612 -0
  285. package/dist/core/migrator/scanners.js.map +1 -0
  286. package/dist/core/migrator/scanners.test.d.ts +2 -0
  287. package/dist/core/migrator/scanners.test.d.ts.map +1 -0
  288. package/dist/core/migrator/scanners.test.js +257 -0
  289. package/dist/core/migrator/scanners.test.js.map +1 -0
  290. package/dist/core/migrator.test.d.ts +2 -0
  291. package/dist/core/migrator.test.d.ts.map +1 -0
  292. package/dist/core/migrator.test.js +451 -0
  293. package/dist/core/migrator.test.js.map +1 -0
  294. package/dist/core/plugin-scanner.d.ts +30 -0
  295. package/dist/core/plugin-scanner.d.ts.map +1 -0
  296. package/dist/core/plugin-scanner.js +174 -0
  297. package/dist/core/plugin-scanner.js.map +1 -0
  298. package/dist/core/plugin-scanner.test.d.ts +2 -0
  299. package/dist/core/plugin-scanner.test.d.ts.map +1 -0
  300. package/dist/core/plugin-scanner.test.js +279 -0
  301. package/dist/core/plugin-scanner.test.js.map +1 -0
  302. package/dist/core/presets.d.ts +55 -0
  303. package/dist/core/presets.d.ts.map +1 -0
  304. package/dist/core/presets.js +84 -0
  305. package/dist/core/presets.js.map +1 -0
  306. package/dist/core/presets.test.d.ts +2 -0
  307. package/dist/core/presets.test.d.ts.map +1 -0
  308. package/dist/core/presets.test.js +40 -0
  309. package/dist/core/presets.test.js.map +1 -0
  310. package/dist/core/skill-parser.d.ts +21 -0
  311. package/dist/core/skill-parser.d.ts.map +1 -0
  312. package/dist/core/skill-parser.js +53 -0
  313. package/dist/core/skill-parser.js.map +1 -0
  314. package/dist/core/skill-parser.test.d.ts +2 -0
  315. package/dist/core/skill-parser.test.d.ts.map +1 -0
  316. package/dist/core/skill-parser.test.js +83 -0
  317. package/dist/core/skill-parser.test.js.map +1 -0
  318. package/dist/core/smart-memory.d.ts +22 -0
  319. package/dist/core/smart-memory.d.ts.map +1 -0
  320. package/dist/core/smart-memory.js +72 -0
  321. package/dist/core/smart-memory.js.map +1 -0
  322. package/dist/core/smart-memory.test.d.ts +2 -0
  323. package/dist/core/smart-memory.test.d.ts.map +1 -0
  324. package/dist/core/smart-memory.test.js +114 -0
  325. package/dist/core/smart-memory.test.js.map +1 -0
  326. package/dist/core/snapshot.d.ts +6 -0
  327. package/dist/core/snapshot.d.ts.map +1 -0
  328. package/dist/core/snapshot.js +179 -0
  329. package/dist/core/snapshot.js.map +1 -0
  330. package/dist/core/snapshot.test.d.ts +2 -0
  331. package/dist/core/snapshot.test.d.ts.map +1 -0
  332. package/dist/core/snapshot.test.js +132 -0
  333. package/dist/core/snapshot.test.js.map +1 -0
  334. package/dist/core/symlink-manager.d.ts +78 -0
  335. package/dist/core/symlink-manager.d.ts.map +1 -0
  336. package/dist/core/symlink-manager.js +227 -0
  337. package/dist/core/symlink-manager.js.map +1 -0
  338. package/dist/core/symlink-manager.test.d.ts +8 -0
  339. package/dist/core/symlink-manager.test.d.ts.map +1 -0
  340. package/dist/core/symlink-manager.test.js +354 -0
  341. package/dist/core/symlink-manager.test.js.map +1 -0
  342. package/dist/core/sync-writer.d.ts +20 -0
  343. package/dist/core/sync-writer.d.ts.map +1 -0
  344. package/dist/core/sync-writer.js +150 -0
  345. package/dist/core/sync-writer.js.map +1 -0
  346. package/dist/core/sync-writer.test.d.ts +2 -0
  347. package/dist/core/sync-writer.test.d.ts.map +1 -0
  348. package/dist/core/sync-writer.test.js +134 -0
  349. package/dist/core/sync-writer.test.js.map +1 -0
  350. package/dist/core/toml-helpers.d.ts +9 -0
  351. package/dist/core/toml-helpers.d.ts.map +1 -0
  352. package/dist/core/toml-helpers.js +33 -0
  353. package/dist/core/toml-helpers.js.map +1 -0
  354. package/dist/core/tool-adapter.d.ts +24 -0
  355. package/dist/core/tool-adapter.d.ts.map +1 -0
  356. package/dist/core/tool-adapter.js +156 -0
  357. package/dist/core/tool-adapter.js.map +1 -0
  358. package/dist/core/tool-adapter.test.d.ts +2 -0
  359. package/dist/core/tool-adapter.test.d.ts.map +1 -0
  360. package/dist/core/tool-adapter.test.js +264 -0
  361. package/dist/core/tool-adapter.test.js.map +1 -0
  362. package/dist/core/tool-detector.d.ts +31 -0
  363. package/dist/core/tool-detector.d.ts.map +1 -0
  364. package/dist/core/tool-detector.js +67 -0
  365. package/dist/core/tool-detector.js.map +1 -0
  366. package/dist/core/tool-detector.test.d.ts +2 -0
  367. package/dist/core/tool-detector.test.d.ts.map +1 -0
  368. package/dist/core/tool-detector.test.js +126 -0
  369. package/dist/core/tool-detector.test.js.map +1 -0
  370. package/dist/core/watcher.d.ts +22 -0
  371. package/dist/core/watcher.d.ts.map +1 -0
  372. package/dist/core/watcher.js +68 -0
  373. package/dist/core/watcher.js.map +1 -0
  374. package/dist/core/watcher.test.d.ts +2 -0
  375. package/dist/core/watcher.test.d.ts.map +1 -0
  376. package/dist/core/watcher.test.js +26 -0
  377. package/dist/core/watcher.test.js.map +1 -0
  378. package/dist/index.d.ts +9 -0
  379. package/dist/index.d.ts.map +1 -0
  380. package/dist/index.js +47 -0
  381. package/dist/index.js.map +1 -0
  382. package/dist/routes/async-handler.d.ts +6 -0
  383. package/dist/routes/async-handler.d.ts.map +1 -0
  384. package/dist/routes/async-handler.js +9 -0
  385. package/dist/routes/async-handler.js.map +1 -0
  386. package/dist/routes/marketplace.d.ts +3 -0
  387. package/dist/routes/marketplace.d.ts.map +1 -0
  388. package/dist/routes/marketplace.js +51 -0
  389. package/dist/routes/marketplace.js.map +1 -0
  390. package/dist/routes/migrate.d.ts +3 -0
  391. package/dist/routes/migrate.d.ts.map +1 -0
  392. package/dist/routes/migrate.js +22 -0
  393. package/dist/routes/migrate.js.map +1 -0
  394. package/dist/routes/plugin-map.d.ts +11 -0
  395. package/dist/routes/plugin-map.d.ts.map +1 -0
  396. package/dist/routes/plugin-map.js +37 -0
  397. package/dist/routes/plugin-map.js.map +1 -0
  398. package/dist/routes/plugins.d.ts +3 -0
  399. package/dist/routes/plugins.d.ts.map +1 -0
  400. package/dist/routes/plugins.js +51 -0
  401. package/dist/routes/plugins.js.map +1 -0
  402. package/dist/routes/remove.d.ts +3 -0
  403. package/dist/routes/remove.d.ts.map +1 -0
  404. package/dist/routes/remove.js +27 -0
  405. package/dist/routes/remove.js.map +1 -0
  406. package/dist/routes/state.d.ts +3 -0
  407. package/dist/routes/state.d.ts.map +1 -0
  408. package/dist/routes/state.js +177 -0
  409. package/dist/routes/state.js.map +1 -0
  410. package/dist/routes/sync.d.ts +3 -0
  411. package/dist/routes/sync.d.ts.map +1 -0
  412. package/dist/routes/sync.js +12 -0
  413. package/dist/routes/sync.js.map +1 -0
  414. package/dist/server.d.ts +4 -0
  415. package/dist/server.d.ts.map +1 -0
  416. package/dist/server.js +59 -0
  417. package/dist/server.js.map +1 -0
  418. package/package.json +48 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Snapshot — create, restore, list, and delete config snapshots
3
+ */
4
+ import * as fs from "node:fs/promises";
5
+ import * as path from "node:path";
6
+ import { mkdirp, MYCELIUM_HOME } from "./fs-helpers.js";
7
+ function getMyceliumDir() {
8
+ return MYCELIUM_HOME;
9
+ }
10
+ function getSnapshotsDir() {
11
+ return path.join(getMyceliumDir(), "snapshots");
12
+ }
13
+ /** Files to capture relative to getMyceliumDir() */
14
+ const SNAPSHOT_FILES = [
15
+ "global/mcps.yaml",
16
+ "global/hooks.yaml",
17
+ "migration-manifest.json",
18
+ "marketplaces.yaml",
19
+ ];
20
+ const VALID_NAME = /^[a-zA-Z0-9-]+$/;
21
+ // ============================================================================
22
+ // Helpers
23
+ // ============================================================================
24
+ async function copyIfExists(src, dest) {
25
+ try {
26
+ await mkdirp(path.dirname(dest));
27
+ await fs.copyFile(src, dest);
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ async function copyDirRecursive(src, dest) {
35
+ const files = [];
36
+ try {
37
+ const entries = await fs.readdir(src, { withFileTypes: true });
38
+ await mkdirp(dest);
39
+ for (const entry of entries) {
40
+ const srcPath = path.join(src, entry.name);
41
+ const destPath = path.join(dest, entry.name);
42
+ if (entry.isDirectory()) {
43
+ files.push(...(await copyDirRecursive(srcPath, destPath)));
44
+ }
45
+ else {
46
+ await fs.copyFile(srcPath, destPath);
47
+ files.push(entry.name);
48
+ }
49
+ }
50
+ }
51
+ catch {
52
+ // directory doesn't exist, skip
53
+ }
54
+ return files;
55
+ }
56
+ async function rmrf(dir) {
57
+ await fs.rm(dir, { recursive: true, force: true });
58
+ }
59
+ // ============================================================================
60
+ // Public API
61
+ // ============================================================================
62
+ export async function createSnapshot(name, description) {
63
+ if (!VALID_NAME.test(name)) {
64
+ throw new Error(`Invalid snapshot name "${name}": only alphanumeric characters and hyphens are allowed`);
65
+ }
66
+ const snapshotDir = path.join(getSnapshotsDir(), name);
67
+ // Check for duplicates
68
+ try {
69
+ await fs.access(snapshotDir);
70
+ throw new Error(`Snapshot "${name}" already exists`);
71
+ }
72
+ catch (err) {
73
+ if (err.message.includes("already exists"))
74
+ throw err;
75
+ // ENOENT is expected
76
+ }
77
+ await mkdirp(snapshotDir);
78
+ const fileList = [];
79
+ // Copy individual files
80
+ for (const relPath of SNAPSHOT_FILES) {
81
+ const src = path.join(getMyceliumDir(), relPath);
82
+ const dest = path.join(snapshotDir, relPath);
83
+ if (await copyIfExists(src, dest)) {
84
+ fileList.push(relPath);
85
+ }
86
+ }
87
+ // Copy memory directory
88
+ const memoryFiles = await copyDirRecursive(path.join(getMyceliumDir(), "memory"), path.join(snapshotDir, "memory"));
89
+ for (const f of memoryFiles) {
90
+ fileList.push(`memory/${f}`);
91
+ }
92
+ // Read symlinks in global/skills/
93
+ const skillSymlinks = {};
94
+ const skillsDir = path.join(getMyceliumDir(), "global", "skills");
95
+ try {
96
+ const entries = await fs.readdir(skillsDir);
97
+ for (const entry of entries) {
98
+ const fullPath = path.join(skillsDir, entry);
99
+ try {
100
+ const target = await fs.readlink(fullPath);
101
+ skillSymlinks[entry] = target;
102
+ }
103
+ catch {
104
+ // Not a symlink, skip
105
+ }
106
+ }
107
+ }
108
+ catch {
109
+ // skills dir doesn't exist
110
+ }
111
+ const metadata = {
112
+ name,
113
+ createdAt: new Date().toISOString(),
114
+ description,
115
+ skillSymlinks,
116
+ fileList,
117
+ };
118
+ await fs.writeFile(path.join(snapshotDir, "metadata.json"), JSON.stringify(metadata, null, 2));
119
+ return metadata;
120
+ }
121
+ export async function restoreSnapshot(name) {
122
+ const snapshotDir = path.join(getSnapshotsDir(), name);
123
+ let raw;
124
+ try {
125
+ raw = await fs.readFile(path.join(snapshotDir, "metadata.json"), "utf-8");
126
+ }
127
+ catch {
128
+ throw new Error(`Snapshot "${name}" not found`);
129
+ }
130
+ const metadata = JSON.parse(raw);
131
+ // Remove current config files
132
+ for (const relPath of SNAPSHOT_FILES) {
133
+ await fs.rm(path.join(getMyceliumDir(), relPath), { force: true });
134
+ }
135
+ await rmrf(path.join(getMyceliumDir(), "memory"));
136
+ await rmrf(path.join(getMyceliumDir(), "global", "skills"));
137
+ // Restore files
138
+ for (const relPath of metadata.fileList) {
139
+ const src = path.join(snapshotDir, relPath);
140
+ const dest = path.join(getMyceliumDir(), relPath);
141
+ await copyIfExists(src, dest);
142
+ }
143
+ // Recreate symlinks
144
+ const skillsDir = path.join(getMyceliumDir(), "global", "skills");
145
+ await mkdirp(skillsDir);
146
+ for (const [linkName, target] of Object.entries(metadata.skillSymlinks)) {
147
+ await fs.symlink(target, path.join(skillsDir, linkName));
148
+ }
149
+ }
150
+ export async function listSnapshots() {
151
+ const results = [];
152
+ try {
153
+ const entries = await fs.readdir(getSnapshotsDir());
154
+ for (const entry of entries) {
155
+ try {
156
+ const raw = await fs.readFile(path.join(getSnapshotsDir(), entry, "metadata.json"), "utf-8");
157
+ results.push(JSON.parse(raw));
158
+ }
159
+ catch {
160
+ // skip invalid entries
161
+ }
162
+ }
163
+ }
164
+ catch {
165
+ // snapshots dir doesn't exist yet
166
+ }
167
+ return results.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
168
+ }
169
+ export async function deleteSnapshot(name) {
170
+ const snapshotDir = path.join(getSnapshotsDir(), name);
171
+ try {
172
+ await fs.access(snapshotDir);
173
+ }
174
+ catch {
175
+ throw new Error(`Snapshot "${name}" not found`);
176
+ }
177
+ await rmrf(snapshotDir);
178
+ }
179
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/core/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=snapshot.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.test.d.ts","sourceRoot":"","sources":["../../src/core/snapshot.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Tests for the Snapshot module
3
+ */
4
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
5
+ import * as fs from "node:fs/promises";
6
+ import * as path from "node:path";
7
+ import * as os from "node:os";
8
+ // We mock os.homedir to point to a temp directory so snapshot.ts operates in isolation
9
+ let tmpDir;
10
+ vi.mock("node:os", async () => {
11
+ const actual = await vi.importActual("node:os");
12
+ return {
13
+ ...actual,
14
+ homedir: () => tmpDir,
15
+ };
16
+ });
17
+ // Mock fs-helpers to avoid MYCELIUM_HOME evaluation at import time (os.homedir() is undefined then)
18
+ vi.mock("./fs-helpers.js", async () => {
19
+ const fsp = await import("node:fs/promises");
20
+ const osMod = await import("node:os");
21
+ const pathMod = await import("node:path");
22
+ return {
23
+ mkdirp: (dir) => fsp.mkdir(dir, { recursive: true }),
24
+ get MYCELIUM_HOME() { return pathMod.join(osMod.homedir(), ".mycelium"); },
25
+ DEFAULT_PORT: 3378,
26
+ MEMORY_LINE_LIMIT: 200,
27
+ readFileIfExists: vi.fn(),
28
+ };
29
+ });
30
+ // Must import after mock setup
31
+ const { createSnapshot, restoreSnapshot, listSnapshots, deleteSnapshot } = await import("./snapshot.js");
32
+ async function setupMyceliumDir() {
33
+ const myceliumDir = path.join(tmpDir, ".mycelium");
34
+ await fs.mkdir(path.join(myceliumDir, "global", "skills"), { recursive: true });
35
+ await fs.mkdir(path.join(myceliumDir, "memory"), { recursive: true });
36
+ await fs.writeFile(path.join(myceliumDir, "global", "mcps.yaml"), "mcps:\n test: {}\n");
37
+ await fs.writeFile(path.join(myceliumDir, "global", "hooks.yaml"), "hooks: []\n");
38
+ await fs.writeFile(path.join(myceliumDir, "memory", "shared.md"), "# Shared memory\n");
39
+ await fs.writeFile(path.join(myceliumDir, "migration-manifest.json"), '{"version":"1","entries":[]}');
40
+ await fs.writeFile(path.join(myceliumDir, "marketplaces.yaml"), "sources: {}\n");
41
+ // Create a symlink in skills
42
+ const targetDir = path.join(tmpDir, "skill-target");
43
+ await fs.mkdir(targetDir, { recursive: true });
44
+ await fs.symlink(targetDir, path.join(myceliumDir, "global", "skills", "my-skill"));
45
+ return myceliumDir;
46
+ }
47
+ beforeEach(async () => {
48
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "snapshot-test-"));
49
+ });
50
+ afterEach(async () => {
51
+ await fs.rm(tmpDir, { recursive: true, force: true });
52
+ });
53
+ describe("createSnapshot", () => {
54
+ it("captures files and symlink targets in metadata", async () => {
55
+ await setupMyceliumDir();
56
+ const meta = await createSnapshot("test-snap", "A test snapshot");
57
+ expect(meta.name).toBe("test-snap");
58
+ expect(meta.description).toBe("A test snapshot");
59
+ expect(meta.fileList).toContain("global/mcps.yaml");
60
+ expect(meta.fileList).toContain("memory/shared.md");
61
+ expect(meta.skillSymlinks["my-skill"]).toBeDefined();
62
+ // Verify metadata.json was written
63
+ const raw = await fs.readFile(path.join(tmpDir, ".mycelium", "snapshots", "test-snap", "metadata.json"), "utf-8");
64
+ const saved = JSON.parse(raw);
65
+ expect(saved.name).toBe("test-snap");
66
+ });
67
+ it("throws on duplicate name", async () => {
68
+ await setupMyceliumDir();
69
+ await createSnapshot("dup");
70
+ await expect(createSnapshot("dup")).rejects.toThrow("already exists");
71
+ });
72
+ it("throws on invalid name with spaces", async () => {
73
+ await setupMyceliumDir();
74
+ await expect(createSnapshot("bad name")).rejects.toThrow("Invalid snapshot name");
75
+ });
76
+ it("throws on invalid name with slashes", async () => {
77
+ await setupMyceliumDir();
78
+ await expect(createSnapshot("bad/name")).rejects.toThrow("Invalid snapshot name");
79
+ });
80
+ });
81
+ describe("restoreSnapshot", () => {
82
+ it("recreates files and symlinks", async () => {
83
+ const myceliumDir = await setupMyceliumDir();
84
+ await createSnapshot("restore-test");
85
+ // Delete the originals
86
+ await fs.rm(path.join(myceliumDir, "global", "mcps.yaml"));
87
+ await fs.rm(path.join(myceliumDir, "global", "skills", "my-skill"));
88
+ await fs.rm(path.join(myceliumDir, "memory"), { recursive: true });
89
+ await restoreSnapshot("restore-test");
90
+ // Verify restored
91
+ const mcps = await fs.readFile(path.join(myceliumDir, "global", "mcps.yaml"), "utf-8");
92
+ expect(mcps).toContain("mcps:");
93
+ const symlinkTarget = await fs.readlink(path.join(myceliumDir, "global", "skills", "my-skill"));
94
+ expect(symlinkTarget).toContain("skill-target");
95
+ });
96
+ it("throws on non-existent snapshot", async () => {
97
+ await setupMyceliumDir();
98
+ await expect(restoreSnapshot("nope")).rejects.toThrow("not found");
99
+ });
100
+ });
101
+ describe("listSnapshots", () => {
102
+ it("returns snapshots sorted by date descending", async () => {
103
+ await setupMyceliumDir();
104
+ await createSnapshot("first");
105
+ // Small delay to ensure different timestamps
106
+ await new Promise((r) => setTimeout(r, 10));
107
+ await createSnapshot("second");
108
+ const list = await listSnapshots();
109
+ expect(list).toHaveLength(2);
110
+ expect(list[0].name).toBe("second");
111
+ expect(list[1].name).toBe("first");
112
+ });
113
+ it("returns empty array when no snapshots exist", async () => {
114
+ await setupMyceliumDir();
115
+ const list = await listSnapshots();
116
+ expect(list).toEqual([]);
117
+ });
118
+ });
119
+ describe("deleteSnapshot", () => {
120
+ it("removes snapshot directory", async () => {
121
+ await setupMyceliumDir();
122
+ await createSnapshot("to-delete");
123
+ await deleteSnapshot("to-delete");
124
+ const list = await listSnapshots();
125
+ expect(list).toHaveLength(0);
126
+ });
127
+ it("throws on non-existent snapshot", async () => {
128
+ await setupMyceliumDir();
129
+ await expect(deleteSnapshot("nope")).rejects.toThrow("not found");
130
+ });
131
+ });
132
+ //# sourceMappingURL=snapshot.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.test.js","sourceRoot":"","sources":["../../src/core/snapshot.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Symlink Manager for Mycelium
3
+ *
4
+ * Handles creating, updating, and removing symlinks from the global
5
+ * skills directory to tool-specific directories.
6
+ */
7
+ export interface CreateSymlinkResult {
8
+ success: boolean;
9
+ action: "created" | "updated" | "replaced" | "unchanged" | "error";
10
+ backupPath?: string;
11
+ error?: string;
12
+ }
13
+ export interface RemoveSymlinkResult {
14
+ success: boolean;
15
+ existed: boolean;
16
+ error?: string;
17
+ }
18
+ export interface SymlinkValidation {
19
+ valid: boolean;
20
+ exists?: boolean;
21
+ isSymlink?: boolean;
22
+ currentTarget?: string;
23
+ expectedTarget?: string;
24
+ }
25
+ export interface SkillSymlinkStatus {
26
+ skillName: string;
27
+ skillPath: string;
28
+ symlinkPath: string;
29
+ exists: boolean;
30
+ valid: boolean;
31
+ currentTarget?: string;
32
+ }
33
+ export interface Skill {
34
+ name: string;
35
+ path: string;
36
+ manifest: {
37
+ name: string;
38
+ enabled?: boolean;
39
+ };
40
+ }
41
+ export interface SyncOptions {
42
+ removeOrphans?: boolean;
43
+ }
44
+ export interface SyncResult {
45
+ success: boolean;
46
+ created: string[];
47
+ updated: string[];
48
+ removed: string[];
49
+ unchanged: string[];
50
+ errors: Array<{
51
+ skill: string;
52
+ error: string;
53
+ }>;
54
+ }
55
+ /**
56
+ * Create a symlink from a skill source path to a tool directory location.
57
+ * Handles existing symlinks, files, and directories appropriately.
58
+ */
59
+ export declare function createSkillSymlink(sourcePath: string, symlinkPath: string): Promise<CreateSymlinkResult>;
60
+ /**
61
+ * Remove a symlink. Only removes actual symlinks, not regular files/directories.
62
+ */
63
+ export declare function removeSkillSymlink(symlinkPath: string): Promise<RemoveSymlinkResult>;
64
+ /**
65
+ * Check if a symlink exists and points to the expected target.
66
+ */
67
+ export declare function isSymlinkValid(symlinkPath: string, expectedTarget: string): Promise<SymlinkValidation>;
68
+ /**
69
+ * Get the status of symlinks for a list of skills in a tool directory.
70
+ */
71
+ export declare function getSymlinkStatus(skills: Skill[], toolSkillsDir: string): Promise<SkillSymlinkStatus[]>;
72
+ /**
73
+ * Sync all skills to a specific tool directory.
74
+ * Creates symlinks for enabled skills, removes symlinks for disabled skills,
75
+ * and optionally removes orphaned symlinks.
76
+ */
77
+ export declare function syncSkillsToTool(skills: Skill[], toolSkillsDir: string, options?: SyncOptions): Promise<SyncResult>;
78
+ //# sourceMappingURL=symlink-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symlink-manager.d.ts","sourceRoot":"","sources":["../../src/core/symlink-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAMD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CA4C9B;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CA6B9B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,iBAAiB,CAAC,CAgC5B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,KAAK,EAAE,EACf,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAkB/B;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,KAAK,EAAE,EACf,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAsFrB"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Symlink Manager for Mycelium
3
+ *
4
+ * Handles creating, updating, and removing symlinks from the global
5
+ * skills directory to tool-specific directories.
6
+ */
7
+ import * as fs from "node:fs/promises";
8
+ import * as path from "node:path";
9
+ // ============================================================================
10
+ // Core Functions
11
+ // ============================================================================
12
+ /**
13
+ * Create a symlink from a skill source path to a tool directory location.
14
+ * Handles existing symlinks, files, and directories appropriately.
15
+ */
16
+ export async function createSkillSymlink(sourcePath, symlinkPath) {
17
+ try {
18
+ // Ensure parent directory exists
19
+ const parentDir = path.dirname(symlinkPath);
20
+ await fs.mkdir(parentDir, { recursive: true });
21
+ // Check if something exists at the symlink path
22
+ let stats;
23
+ try {
24
+ stats = await fs.lstat(symlinkPath);
25
+ }
26
+ catch {
27
+ // Path doesn't exist, create new symlink
28
+ await fs.symlink(sourcePath, symlinkPath);
29
+ return { success: true, action: "created" };
30
+ }
31
+ // Something exists at the path
32
+ if (stats.isSymbolicLink()) {
33
+ // Check if it points to the correct target
34
+ const currentTarget = await fs.readlink(symlinkPath);
35
+ if (currentTarget === sourcePath) {
36
+ return { success: true, action: "unchanged" };
37
+ }
38
+ // Update symlink to new target
39
+ await fs.unlink(symlinkPath);
40
+ await fs.symlink(sourcePath, symlinkPath);
41
+ return { success: true, action: "updated" };
42
+ }
43
+ // Not a symlink - backup and replace
44
+ const backupPath = `${symlinkPath}.backup.${Date.now()}`;
45
+ await fs.rename(symlinkPath, backupPath);
46
+ await fs.symlink(sourcePath, symlinkPath);
47
+ return { success: true, action: "replaced", backupPath };
48
+ }
49
+ catch (error) {
50
+ return {
51
+ success: false,
52
+ action: "error",
53
+ error: error instanceof Error ? error.message : String(error),
54
+ };
55
+ }
56
+ }
57
+ /**
58
+ * Remove a symlink. Only removes actual symlinks, not regular files/directories.
59
+ */
60
+ export async function removeSkillSymlink(symlinkPath) {
61
+ try {
62
+ // Check if path exists
63
+ let stats;
64
+ try {
65
+ stats = await fs.lstat(symlinkPath);
66
+ }
67
+ catch {
68
+ // Path doesn't exist
69
+ return { success: true, existed: false };
70
+ }
71
+ // Only remove if it's a symlink
72
+ if (!stats.isSymbolicLink()) {
73
+ return {
74
+ success: false,
75
+ existed: true,
76
+ error: `Path exists but is not a symlink: ${symlinkPath}`,
77
+ };
78
+ }
79
+ await fs.unlink(symlinkPath);
80
+ return { success: true, existed: true };
81
+ }
82
+ catch (error) {
83
+ return {
84
+ success: false,
85
+ existed: true,
86
+ error: error instanceof Error ? error.message : String(error),
87
+ };
88
+ }
89
+ }
90
+ /**
91
+ * Check if a symlink exists and points to the expected target.
92
+ */
93
+ export async function isSymlinkValid(symlinkPath, expectedTarget) {
94
+ try {
95
+ // Check if path exists
96
+ let stats;
97
+ try {
98
+ stats = await fs.lstat(symlinkPath);
99
+ }
100
+ catch {
101
+ return { valid: false, exists: false };
102
+ }
103
+ // Check if it's a symlink
104
+ if (!stats.isSymbolicLink()) {
105
+ return { valid: false, exists: true, isSymlink: false };
106
+ }
107
+ // Check if it points to the correct target
108
+ const currentTarget = await fs.readlink(symlinkPath);
109
+ if (currentTarget === expectedTarget) {
110
+ return { valid: true, currentTarget };
111
+ }
112
+ return {
113
+ valid: false,
114
+ exists: true,
115
+ isSymlink: true,
116
+ currentTarget,
117
+ expectedTarget,
118
+ };
119
+ }
120
+ catch (error) {
121
+ return { valid: false };
122
+ }
123
+ }
124
+ /**
125
+ * Get the status of symlinks for a list of skills in a tool directory.
126
+ */
127
+ export async function getSymlinkStatus(skills, toolSkillsDir) {
128
+ const statuses = [];
129
+ for (const skill of skills) {
130
+ const symlinkPath = path.join(toolSkillsDir, skill.name);
131
+ const validation = await isSymlinkValid(symlinkPath, skill.path);
132
+ statuses.push({
133
+ skillName: skill.name,
134
+ skillPath: skill.path,
135
+ symlinkPath,
136
+ exists: validation.exists !== false,
137
+ valid: validation.valid,
138
+ currentTarget: validation.currentTarget,
139
+ });
140
+ }
141
+ return statuses;
142
+ }
143
+ /**
144
+ * Sync all skills to a specific tool directory.
145
+ * Creates symlinks for enabled skills, removes symlinks for disabled skills,
146
+ * and optionally removes orphaned symlinks.
147
+ */
148
+ export async function syncSkillsToTool(skills, toolSkillsDir, options = {}) {
149
+ const result = {
150
+ success: true,
151
+ created: [],
152
+ updated: [],
153
+ removed: [],
154
+ unchanged: [],
155
+ errors: [],
156
+ };
157
+ // Ensure tool skills directory exists
158
+ await fs.mkdir(toolSkillsDir, { recursive: true });
159
+ // Build set of skill names for orphan detection
160
+ const skillNames = new Set(skills.map((s) => s.name));
161
+ // Process each skill
162
+ for (const skill of skills) {
163
+ const symlinkPath = path.join(toolSkillsDir, skill.name);
164
+ const isEnabled = skill.manifest.enabled !== false;
165
+ if (isEnabled) {
166
+ // Create or update symlink
167
+ const createResult = await createSkillSymlink(skill.path, symlinkPath);
168
+ if (createResult.success) {
169
+ switch (createResult.action) {
170
+ case "created":
171
+ result.created.push(skill.name);
172
+ break;
173
+ case "updated":
174
+ case "replaced":
175
+ result.updated.push(skill.name);
176
+ break;
177
+ case "unchanged":
178
+ result.unchanged.push(skill.name);
179
+ break;
180
+ }
181
+ }
182
+ else {
183
+ result.success = false;
184
+ result.errors.push({ skill: skill.name, error: createResult.error || "Unknown error" });
185
+ }
186
+ }
187
+ else {
188
+ // Remove symlink for disabled skill
189
+ const removeResult = await removeSkillSymlink(symlinkPath);
190
+ if (removeResult.existed) {
191
+ result.removed.push(skill.name);
192
+ }
193
+ if (!removeResult.success && removeResult.existed) {
194
+ result.errors.push({ skill: skill.name, error: removeResult.error || "Unknown error" });
195
+ }
196
+ }
197
+ }
198
+ // Handle orphaned symlinks
199
+ if (options.removeOrphans) {
200
+ try {
201
+ const entries = await fs.readdir(toolSkillsDir, { withFileTypes: true });
202
+ for (const entry of entries) {
203
+ // Skip if this is a known skill
204
+ if (skillNames.has(entry.name)) {
205
+ continue;
206
+ }
207
+ const entryPath = path.join(toolSkillsDir, entry.name);
208
+ // Only remove symlinks
209
+ try {
210
+ const stats = await fs.lstat(entryPath);
211
+ if (stats.isSymbolicLink()) {
212
+ await fs.unlink(entryPath);
213
+ result.removed.push(entry.name);
214
+ }
215
+ }
216
+ catch {
217
+ // Ignore errors for individual entries
218
+ }
219
+ }
220
+ }
221
+ catch {
222
+ // Ignore errors reading directory
223
+ }
224
+ }
225
+ return result;
226
+ }
227
+ //# sourceMappingURL=symlink-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symlink-manager.js","sourceRoot":"","sources":["../../src/core/symlink-manager.ts"],"names":[],"mappings":"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"}