@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,691 @@
1
+ /**
2
+ * Tests for doctor command - written FIRST following TDD
3
+ *
4
+ * The doctor command checks system health and offers to fix issues:
5
+ * - Checks if global mycelium dir exists
6
+ * - Checks if manifest.yaml is valid
7
+ * - Checks if each configured tool path exists
8
+ * - Detects broken symlinks
9
+ * - Validates MCP config JSON syntax
10
+ * - Validates MCP config YAML syntax
11
+ * - Reports all issues found
12
+ * - Shows green checkmarks for passing checks
13
+ * - Shows red X for failing checks
14
+ * - Offers fix suggestions
15
+ */
16
+ import { describe, it, expect, vi, beforeEach } from "vitest";
17
+ import * as path from "node:path";
18
+ // Mock fs/promises module
19
+ vi.mock("node:fs/promises", () => ({
20
+ mkdir: vi.fn(),
21
+ writeFile: vi.fn(),
22
+ access: vi.fn(),
23
+ readFile: vi.fn(),
24
+ readdir: vi.fn(),
25
+ lstat: vi.fn(),
26
+ stat: vi.fn(),
27
+ readlink: vi.fn(),
28
+ }));
29
+ // Mock @mycelish/core
30
+ vi.mock("@mycelish/core", () => ({
31
+ expandPath: (p) => {
32
+ if (p.startsWith("~")) {
33
+ return path.join("/mock/home", p.slice(1));
34
+ }
35
+ return p;
36
+ },
37
+ ensureDir: vi.fn(),
38
+ pathExists: vi.fn(),
39
+ TOOL_REGISTRY: {
40
+ "claude-code": {
41
+ id: "claude-code",
42
+ display: { name: "Claude Code", icon: "claude", color: "#D97706" },
43
+ cli: { command: "claude" },
44
+ paths: {
45
+ mcp: "~/.claude.json",
46
+ projectMcp: null,
47
+ skills: "~/.claude/skills",
48
+ projectSkills: null,
49
+ globalMemory: "~/.claude/CLAUDE.md",
50
+ projectMemory: null,
51
+ agents: null,
52
+ projectAgents: null,
53
+ rules: null,
54
+ hooks: null,
55
+ backupDirs: [],
56
+ },
57
+ mcp: { format: "json", key: "mcpServers", entryShape: "standard" },
58
+ scopes: ["shared", "coding"],
59
+ capabilities: ["mcp", "skills", "memory", "hooks"],
60
+ enabled: true,
61
+ memoryMaxLines: 200,
62
+ },
63
+ codex: {
64
+ id: "codex",
65
+ display: { name: "Codex CLI", icon: "codex", color: "#10B981" },
66
+ cli: { command: "codex" },
67
+ paths: {
68
+ mcp: "~/.codex/config.toml",
69
+ projectMcp: null,
70
+ skills: "~/.codex/skills",
71
+ projectSkills: null,
72
+ globalMemory: "~/.codex/AGENTS.md",
73
+ projectMemory: null,
74
+ agents: null,
75
+ projectAgents: null,
76
+ rules: null,
77
+ hooks: null,
78
+ backupDirs: [],
79
+ },
80
+ mcp: { format: "toml", key: "mcp.servers", entryShape: "standard" },
81
+ scopes: ["shared", "coding"],
82
+ capabilities: ["mcp", "skills", "memory"],
83
+ enabled: true,
84
+ memoryMaxLines: null,
85
+ },
86
+ "gemini-cli": {
87
+ id: "gemini-cli",
88
+ display: { name: "Gemini CLI", icon: "gemini", color: "#4285F4" },
89
+ cli: { command: "gemini" },
90
+ paths: {
91
+ mcp: "~/.gemini/settings.json",
92
+ projectMcp: null,
93
+ skills: "~/.gemini/extensions",
94
+ projectSkills: null,
95
+ globalMemory: "~/.gemini/GEMINI.md",
96
+ projectMemory: null,
97
+ agents: null,
98
+ projectAgents: null,
99
+ rules: null,
100
+ hooks: null,
101
+ backupDirs: [],
102
+ },
103
+ mcp: { format: "json", key: "mcpServers", entryShape: "standard" },
104
+ scopes: ["shared", "coding"],
105
+ capabilities: ["mcp", "skills", "memory"],
106
+ enabled: true,
107
+ memoryMaxLines: null,
108
+ },
109
+ opencode: {
110
+ id: "opencode",
111
+ display: { name: "OpenCode", icon: "opencode", color: "#8B5CF6" },
112
+ cli: { command: "opencode" },
113
+ paths: {
114
+ mcp: "~/.config/opencode/opencode.json",
115
+ projectMcp: null,
116
+ skills: "~/.config/opencode/plugin",
117
+ projectSkills: null,
118
+ globalMemory: "~/.opencode/context.md",
119
+ projectMemory: null,
120
+ agents: null,
121
+ projectAgents: null,
122
+ rules: null,
123
+ hooks: null,
124
+ backupDirs: [],
125
+ },
126
+ mcp: { format: "json", key: "mcp", entryShape: "opencode" },
127
+ scopes: ["shared", "coding"],
128
+ capabilities: ["mcp", "skills", "memory"],
129
+ enabled: true,
130
+ memoryMaxLines: null,
131
+ },
132
+ openclaw: {
133
+ id: "openclaw",
134
+ display: { name: "OpenClaw", icon: "openclaw", color: "#EC4899" },
135
+ cli: null,
136
+ paths: {
137
+ mcp: "~/.openclaw/openclaw.json",
138
+ projectMcp: null,
139
+ skills: "~/.openclaw/skills",
140
+ projectSkills: null,
141
+ globalMemory: "~/.openclaw/MEMORY.md",
142
+ projectMemory: null,
143
+ agents: null,
144
+ projectAgents: null,
145
+ rules: null,
146
+ hooks: null,
147
+ backupDirs: [],
148
+ },
149
+ mcp: { format: "json", key: "plugins.entries", entryShape: "openclaw" },
150
+ scopes: ["shared", "personal"],
151
+ capabilities: ["mcp", "skills", "memory"],
152
+ enabled: true,
153
+ memoryMaxLines: null,
154
+ },
155
+ aider: {
156
+ id: "aider",
157
+ display: { name: "Aider", icon: "aider", color: "#F59E0B" },
158
+ cli: { command: "aider" },
159
+ paths: {
160
+ mcp: "~/.aider.conf.yml",
161
+ projectMcp: null,
162
+ skills: "~/.aider/plugins",
163
+ projectSkills: null,
164
+ globalMemory: "~/.aider/MEMORY.md",
165
+ projectMemory: null,
166
+ agents: null,
167
+ projectAgents: null,
168
+ rules: null,
169
+ hooks: null,
170
+ backupDirs: [],
171
+ },
172
+ mcp: { format: "yaml", key: "mcps", entryShape: "standard" },
173
+ scopes: ["shared", "coding"],
174
+ capabilities: ["mcp", "memory"],
175
+ enabled: true,
176
+ memoryMaxLines: null,
177
+ },
178
+ },
179
+ ALL_TOOL_IDS: ["claude-code", "codex", "gemini-cli", "opencode", "openclaw", "aider"],
180
+ resolvePath: (p) => {
181
+ if (p === null)
182
+ return null;
183
+ if (typeof p === "string") {
184
+ if (p.startsWith("~"))
185
+ return path.join("/mock/home", p.slice(1));
186
+ return p;
187
+ }
188
+ const platform = process.platform;
189
+ const val = p[platform] ?? p.linux;
190
+ if (val?.startsWith("~"))
191
+ return path.join("/mock/home", val.slice(1));
192
+ return val;
193
+ },
194
+ toolsForScope: (scope) => {
195
+ // Simple mock for test purposes
196
+ const registry = {
197
+ "claude-code": { id: "claude-code", scopes: ["shared", "coding"] },
198
+ codex: { id: "codex", scopes: ["shared", "coding"] },
199
+ "gemini-cli": { id: "gemini-cli", scopes: ["shared", "coding"] },
200
+ opencode: { id: "opencode", scopes: ["shared", "coding"] },
201
+ openclaw: { id: "openclaw", scopes: ["shared", "personal"] },
202
+ aider: { id: "aider", scopes: ["shared", "coding"] },
203
+ };
204
+ return Object.values(registry).filter((t) => t.scopes.includes(scope));
205
+ },
206
+ }));
207
+ // ============================================================================
208
+ // Test Suites
209
+ // ============================================================================
210
+ describe("doctor command", () => {
211
+ beforeEach(() => {
212
+ vi.resetAllMocks();
213
+ });
214
+ describe("checkGlobalMyceliumExists", () => {
215
+ it("returns pass when ~/.mycelium exists", async () => {
216
+ const { pathExists } = await import("@mycelish/core");
217
+ vi.mocked(pathExists).mockResolvedValue(true);
218
+ const { checkGlobalMyceliumExists } = await import("./doctor.js");
219
+ const result = await checkGlobalMyceliumExists();
220
+ expect(result.status).toBe("pass");
221
+ expect(result.name).toBe("Global Mycelium Directory");
222
+ expect(result.message).toContain("exists");
223
+ });
224
+ it("returns fail when ~/.mycelium does not exist", async () => {
225
+ const { pathExists } = await import("@mycelish/core");
226
+ vi.mocked(pathExists).mockResolvedValue(false);
227
+ const { checkGlobalMyceliumExists } = await import("./doctor.js");
228
+ const result = await checkGlobalMyceliumExists();
229
+ expect(result.status).toBe("fail");
230
+ expect(result.message).toContain("not found");
231
+ expect(result.fix).toContain("mycelium init --global");
232
+ });
233
+ });
234
+ describe("checkManifestValid", () => {
235
+ it("returns pass when manifest.yaml is valid", async () => {
236
+ const { pathExists } = await import("@mycelish/core");
237
+ const fs = await import("node:fs/promises");
238
+ vi.mocked(pathExists).mockResolvedValue(true);
239
+ vi.mocked(fs.readFile).mockResolvedValue(`
240
+ version: "1.0"
241
+ tools:
242
+ claude-code:
243
+ enabled: true
244
+ memory:
245
+ scopes:
246
+ shared:
247
+ sync_to: [claude-code]
248
+ path: global/memory/shared/
249
+ `);
250
+ const { checkManifestValid } = await import("./doctor.js");
251
+ const result = await checkManifestValid();
252
+ expect(result.status).toBe("pass");
253
+ expect(result.name).toBe("Manifest Configuration");
254
+ expect(result.message).toContain("valid");
255
+ });
256
+ it("returns fail when manifest.yaml does not exist", async () => {
257
+ const { pathExists } = await import("@mycelish/core");
258
+ vi.mocked(pathExists).mockResolvedValue(false);
259
+ const { checkManifestValid } = await import("./doctor.js");
260
+ const result = await checkManifestValid();
261
+ expect(result.status).toBe("fail");
262
+ expect(result.message).toContain("not found");
263
+ expect(result.fix).toContain("mycelium init --global");
264
+ });
265
+ it("returns fail when manifest.yaml has invalid YAML syntax", async () => {
266
+ const { pathExists } = await import("@mycelish/core");
267
+ const fs = await import("node:fs/promises");
268
+ vi.mocked(pathExists).mockResolvedValue(true);
269
+ vi.mocked(fs.readFile).mockResolvedValue(`
270
+ version: "1.0"
271
+ tools:
272
+ claude-code:
273
+ enabled: [true # Invalid YAML - unclosed bracket
274
+ `);
275
+ const { checkManifestValid } = await import("./doctor.js");
276
+ const result = await checkManifestValid();
277
+ expect(result.status).toBe("fail");
278
+ expect(result.message).toContain("Invalid");
279
+ });
280
+ });
281
+ describe("checkToolPathExists", () => {
282
+ it("returns pass when tool skills directory exists", async () => {
283
+ const { pathExists } = await import("@mycelish/core");
284
+ vi.mocked(pathExists).mockResolvedValue(true);
285
+ const { checkToolPathExists } = await import("./doctor.js");
286
+ const result = await checkToolPathExists("claude-code");
287
+ expect(result.status).toBe("pass");
288
+ expect(result.name).toContain("Claude Code");
289
+ });
290
+ it("returns warn when tool skills directory does not exist", async () => {
291
+ const { pathExists } = await import("@mycelish/core");
292
+ vi.mocked(pathExists).mockResolvedValue(false);
293
+ const { checkToolPathExists } = await import("./doctor.js");
294
+ const result = await checkToolPathExists("claude-code");
295
+ expect(result.status).toBe("warn");
296
+ expect(result.message).toContain("not found");
297
+ expect(result.fix).toContain("mycelium sync");
298
+ });
299
+ });
300
+ describe("checkBrokenSymlinks", () => {
301
+ it("returns pass when no symlinks are broken", async () => {
302
+ const { pathExists } = await import("@mycelish/core");
303
+ const fs = await import("node:fs/promises");
304
+ vi.mocked(pathExists).mockResolvedValue(true);
305
+ vi.mocked(fs.readdir).mockResolvedValue([
306
+ { name: "skill1", isSymbolicLink: () => true },
307
+ { name: "skill2", isSymbolicLink: () => true },
308
+ ]);
309
+ // Both symlinks resolve correctly
310
+ vi.mocked(fs.stat).mockResolvedValue({ isDirectory: () => true });
311
+ const { checkBrokenSymlinks } = await import("./doctor.js");
312
+ const result = await checkBrokenSymlinks("/mock/home/.claude/skills");
313
+ expect(result.status).toBe("pass");
314
+ expect(result.message).toContain("valid");
315
+ });
316
+ it("returns fail when symlinks are broken", async () => {
317
+ const { pathExists } = await import("@mycelish/core");
318
+ const fs = await import("node:fs/promises");
319
+ vi.mocked(pathExists).mockResolvedValue(true);
320
+ vi.mocked(fs.readdir).mockResolvedValue([
321
+ { name: "skill1", isSymbolicLink: () => true },
322
+ { name: "broken_skill", isSymbolicLink: () => true },
323
+ ]);
324
+ // First symlink works, second is broken
325
+ vi.mocked(fs.stat)
326
+ .mockResolvedValueOnce({ isDirectory: () => true })
327
+ .mockRejectedValueOnce(new Error("ENOENT"));
328
+ const { checkBrokenSymlinks } = await import("./doctor.js");
329
+ const result = await checkBrokenSymlinks("/mock/home/.claude/skills");
330
+ expect(result.status).toBe("fail");
331
+ expect(result.message).toContain("broken");
332
+ expect(result.fix).toContain("mycelium sync");
333
+ });
334
+ it("returns pass when directory does not exist", async () => {
335
+ const { pathExists } = await import("@mycelish/core");
336
+ vi.mocked(pathExists).mockResolvedValue(false);
337
+ const { checkBrokenSymlinks } = await import("./doctor.js");
338
+ const result = await checkBrokenSymlinks("/mock/home/.claude/skills");
339
+ expect(result.status).toBe("pass");
340
+ expect(result.message).toContain("not present");
341
+ });
342
+ });
343
+ describe("checkMcpConfigJson", () => {
344
+ it("returns pass when MCP JSON config is valid", async () => {
345
+ const { pathExists } = await import("@mycelish/core");
346
+ const fs = await import("node:fs/promises");
347
+ vi.mocked(pathExists).mockResolvedValue(true);
348
+ vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({
349
+ mcpServers: {
350
+ "mcp-server-1": { command: "npx", args: ["-y", "mcp-server-1"] },
351
+ },
352
+ }));
353
+ const { checkMcpConfigJson } = await import("./doctor.js");
354
+ const result = await checkMcpConfigJson("/mock/home/.claude/mcp.json");
355
+ expect(result.status).toBe("pass");
356
+ expect(result.message).toContain("valid");
357
+ });
358
+ it("returns fail when MCP JSON config has invalid syntax", async () => {
359
+ const { pathExists } = await import("@mycelish/core");
360
+ const fs = await import("node:fs/promises");
361
+ vi.mocked(pathExists).mockResolvedValue(true);
362
+ vi.mocked(fs.readFile).mockResolvedValue('{ "mcpServers": { invalid }');
363
+ const { checkMcpConfigJson } = await import("./doctor.js");
364
+ const result = await checkMcpConfigJson("/mock/home/.claude/mcp.json");
365
+ expect(result.status).toBe("fail");
366
+ expect(result.message).toContain("Invalid JSON");
367
+ });
368
+ it("returns pass when config file does not exist (not required)", async () => {
369
+ const { pathExists } = await import("@mycelish/core");
370
+ vi.mocked(pathExists).mockResolvedValue(false);
371
+ const { checkMcpConfigJson } = await import("./doctor.js");
372
+ const result = await checkMcpConfigJson("/mock/home/.claude/mcp.json");
373
+ expect(result.status).toBe("pass");
374
+ expect(result.message).toContain("not present");
375
+ });
376
+ });
377
+ describe("checkMcpConfigYaml", () => {
378
+ it("returns pass when MCP YAML config is valid", async () => {
379
+ const { pathExists } = await import("@mycelish/core");
380
+ const fs = await import("node:fs/promises");
381
+ vi.mocked(pathExists).mockResolvedValue(true);
382
+ vi.mocked(fs.readFile).mockResolvedValue(`
383
+ mcps:
384
+ mcp-server-1:
385
+ command: npx
386
+ args:
387
+ - -y
388
+ - mcp-server-1
389
+ `);
390
+ const { checkMcpConfigYaml } = await import("./doctor.js");
391
+ const result = await checkMcpConfigYaml("/mock/home/.config/opencode/config.yaml");
392
+ expect(result.status).toBe("pass");
393
+ expect(result.message).toContain("valid");
394
+ });
395
+ it("returns fail when MCP YAML config has invalid syntax", async () => {
396
+ const { pathExists } = await import("@mycelish/core");
397
+ const fs = await import("node:fs/promises");
398
+ vi.mocked(pathExists).mockResolvedValue(true);
399
+ vi.mocked(fs.readFile).mockResolvedValue(`
400
+ mcps:
401
+ mcp-server-1:
402
+ command: npx
403
+ args: [invalid # Unclosed bracket
404
+ `);
405
+ const { checkMcpConfigYaml } = await import("./doctor.js");
406
+ const result = await checkMcpConfigYaml("/mock/home/.config/opencode/config.yaml");
407
+ expect(result.status).toBe("fail");
408
+ expect(result.message).toContain("Invalid YAML");
409
+ });
410
+ it("returns pass when config file does not exist (not required)", async () => {
411
+ const { pathExists } = await import("@mycelish/core");
412
+ vi.mocked(pathExists).mockResolvedValue(false);
413
+ const { checkMcpConfigYaml } = await import("./doctor.js");
414
+ const result = await checkMcpConfigYaml("/mock/home/.config/opencode/config.yaml");
415
+ expect(result.status).toBe("pass");
416
+ expect(result.message).toContain("not present");
417
+ });
418
+ });
419
+ describe("checkMemoryFilesExist", () => {
420
+ it("returns pass when memory directories have files", async () => {
421
+ const { pathExists } = await import("@mycelish/core");
422
+ const fs = await import("node:fs/promises");
423
+ vi.mocked(pathExists).mockResolvedValue(true);
424
+ vi.mocked(fs.readdir).mockResolvedValue(["memory1.md", "memory2.md"]);
425
+ const { checkMemoryFilesExist } = await import("./doctor.js");
426
+ const result = await checkMemoryFilesExist();
427
+ expect(result.status).toBe("pass");
428
+ expect(result.message).toContain("memory files found");
429
+ });
430
+ it("returns warn when no memory files exist", async () => {
431
+ const { pathExists } = await import("@mycelish/core");
432
+ const fs = await import("node:fs/promises");
433
+ vi.mocked(pathExists).mockResolvedValue(true);
434
+ vi.mocked(fs.readdir).mockResolvedValue([]);
435
+ const { checkMemoryFilesExist } = await import("./doctor.js");
436
+ const result = await checkMemoryFilesExist();
437
+ expect(result.status).toBe("warn");
438
+ expect(result.message).toContain("No memory files");
439
+ });
440
+ it("returns warn when memory directory does not exist", async () => {
441
+ const { pathExists } = await import("@mycelish/core");
442
+ vi.mocked(pathExists).mockResolvedValue(false);
443
+ const { checkMemoryFilesExist } = await import("./doctor.js");
444
+ const result = await checkMemoryFilesExist();
445
+ expect(result.status).toBe("warn");
446
+ expect(result.message).toContain("directory not found");
447
+ });
448
+ });
449
+ describe("checkOrphanedConfigs", () => {
450
+ it("returns pass when no orphaned configs exist", async () => {
451
+ const { pathExists } = await import("@mycelish/core");
452
+ const fs = await import("node:fs/promises");
453
+ // Manifest has claude-code enabled
454
+ vi.mocked(pathExists).mockResolvedValue(true);
455
+ vi.mocked(fs.readFile).mockResolvedValue(`
456
+ version: "1.0"
457
+ tools:
458
+ claude-code:
459
+ enabled: true
460
+ `);
461
+ // Skills directory has skill for enabled tool
462
+ vi.mocked(fs.readdir).mockResolvedValue([
463
+ { name: "skill1", isSymbolicLink: () => true },
464
+ ]);
465
+ const { checkOrphanedConfigs } = await import("./doctor.js");
466
+ const result = await checkOrphanedConfigs();
467
+ expect(result.status).toBe("pass");
468
+ });
469
+ it("returns warn when orphaned skill symlinks exist for disabled tools", async () => {
470
+ const { pathExists } = await import("@mycelish/core");
471
+ const fs = await import("node:fs/promises");
472
+ // Manifest has claude-code disabled
473
+ vi.mocked(pathExists).mockResolvedValue(true);
474
+ vi.mocked(fs.readFile).mockResolvedValue(`
475
+ version: "1.0"
476
+ tools:
477
+ claude-code:
478
+ enabled: false
479
+ `);
480
+ // But skills still exist in tool directory
481
+ vi.mocked(fs.readdir).mockResolvedValue([
482
+ { name: "skill1", isSymbolicLink: () => true },
483
+ ]);
484
+ const { checkOrphanedConfigs } = await import("./doctor.js");
485
+ const result = await checkOrphanedConfigs();
486
+ expect(result.status).toBe("warn");
487
+ expect(result.message).toContain("orphaned");
488
+ expect(result.fix).toContain("mycelium sync");
489
+ });
490
+ });
491
+ describe("runAllChecks", () => {
492
+ it("runs all diagnostic checks and returns summary", async () => {
493
+ const { pathExists } = await import("@mycelish/core");
494
+ const fs = await import("node:fs/promises");
495
+ // Setup: everything is healthy
496
+ vi.mocked(pathExists).mockResolvedValue(true);
497
+ vi.mocked(fs.readFile).mockResolvedValue(`
498
+ version: "1.0"
499
+ tools:
500
+ claude-code:
501
+ enabled: true
502
+ memory:
503
+ scopes:
504
+ shared:
505
+ sync_to: [claude-code]
506
+ path: global/memory/shared/
507
+ `);
508
+ vi.mocked(fs.readdir).mockResolvedValue(["memory1.md"]);
509
+ vi.mocked(fs.stat).mockResolvedValue({ isDirectory: () => true });
510
+ const { runAllChecks } = await import("./doctor.js");
511
+ const result = await runAllChecks();
512
+ expect(result.checks).toBeDefined();
513
+ expect(result.checks.length).toBeGreaterThan(0);
514
+ expect(result.summary).toBeDefined();
515
+ expect(result.summary.passed).toBeGreaterThanOrEqual(0);
516
+ expect(result.summary.failed).toBeGreaterThanOrEqual(0);
517
+ expect(result.summary.warnings).toBeGreaterThanOrEqual(0);
518
+ });
519
+ it("reports all issues found", async () => {
520
+ const { pathExists } = await import("@mycelish/core");
521
+ // Setup: mycelium not initialized
522
+ vi.mocked(pathExists).mockResolvedValue(false);
523
+ const { runAllChecks } = await import("./doctor.js");
524
+ const result = await runAllChecks();
525
+ // Should have at least one failure
526
+ expect(result.summary.failed).toBeGreaterThanOrEqual(1);
527
+ // First check should be about global directory
528
+ expect(result.checks[0].status).toBe("fail");
529
+ });
530
+ });
531
+ describe("formatDoctorOutput", () => {
532
+ it("shows green checkmarks for passing checks", async () => {
533
+ const { formatDoctorOutput } = await import("./doctor.js");
534
+ const result = {
535
+ success: true,
536
+ checks: [
537
+ { name: "Test Check", status: "pass", message: "All good" },
538
+ ],
539
+ summary: { passed: 1, failed: 0, warnings: 0 },
540
+ };
541
+ const output = formatDoctorOutput(result);
542
+ // Should contain green color code and checkmark
543
+ expect(output).toContain("\u001b[32m"); // Green
544
+ expect(output).toContain("\u2714"); // Checkmark
545
+ });
546
+ it("shows red X for failing checks", async () => {
547
+ const { formatDoctorOutput } = await import("./doctor.js");
548
+ const result = {
549
+ success: false,
550
+ checks: [
551
+ {
552
+ name: "Test Check",
553
+ status: "fail",
554
+ message: "Something broke",
555
+ fix: "Run this command",
556
+ },
557
+ ],
558
+ summary: { passed: 0, failed: 1, warnings: 0 },
559
+ };
560
+ const output = formatDoctorOutput(result);
561
+ // Should contain red color code and X mark
562
+ expect(output).toContain("\u001b[31m"); // Red
563
+ expect(output).toContain("\u2718"); // X mark
564
+ });
565
+ it("shows yellow warning for warnings", async () => {
566
+ const { formatDoctorOutput } = await import("./doctor.js");
567
+ const result = {
568
+ success: true,
569
+ checks: [
570
+ { name: "Test Check", status: "warn", message: "Minor issue" },
571
+ ],
572
+ summary: { passed: 0, failed: 0, warnings: 1 },
573
+ };
574
+ const output = formatDoctorOutput(result);
575
+ // Should contain yellow color code and warning symbol
576
+ expect(output).toContain("\u001b[33m"); // Yellow
577
+ expect(output).toContain("\u26A0"); // Warning
578
+ });
579
+ it("shows fix suggestions for failed checks", async () => {
580
+ const { formatDoctorOutput } = await import("./doctor.js");
581
+ const result = {
582
+ success: false,
583
+ checks: [
584
+ {
585
+ name: "Test Check",
586
+ status: "fail",
587
+ message: "Something broke",
588
+ fix: "mycelium init --global",
589
+ },
590
+ ],
591
+ summary: { passed: 0, failed: 1, warnings: 0 },
592
+ };
593
+ const output = formatDoctorOutput(result);
594
+ expect(output).toContain("Fix:");
595
+ expect(output).toContain("mycelium init --global");
596
+ });
597
+ it("shows summary at the end", async () => {
598
+ const { formatDoctorOutput } = await import("./doctor.js");
599
+ const result = {
600
+ success: true,
601
+ checks: [
602
+ { name: "Check 1", status: "pass", message: "OK" },
603
+ { name: "Check 2", status: "warn", message: "Minor" },
604
+ { name: "Check 3", status: "fail", message: "Bad", fix: "Fix it" },
605
+ ],
606
+ summary: { passed: 1, failed: 1, warnings: 1 },
607
+ };
608
+ const output = formatDoctorOutput(result);
609
+ expect(output).toContain("Summary:");
610
+ expect(output).toContain("1 passed");
611
+ expect(output).toContain("1 failed");
612
+ expect(output).toContain("1 warning");
613
+ });
614
+ });
615
+ describe("checkMcpServerConnectivity", () => {
616
+ it("returns pass for valid command", async () => {
617
+ const { checkMcpServerConnectivity } = await import("./doctor.js");
618
+ const result = await checkMcpServerConnectivity("echo", ["hello"]);
619
+ expect(result.status).toBe("pass");
620
+ });
621
+ it("returns fail for invalid command", async () => {
622
+ const { checkMcpServerConnectivity } = await import("./doctor.js");
623
+ const result = await checkMcpServerConnectivity("nonexistent-cmd-xyz", []);
624
+ expect(result.status).toBe("fail");
625
+ });
626
+ it("includes command name in message", async () => {
627
+ const { checkMcpServerConnectivity } = await import("./doctor.js");
628
+ const result = await checkMcpServerConnectivity("echo", ["test"]);
629
+ expect(result.message).toContain("echo");
630
+ });
631
+ });
632
+ describe("checkToolVersions", () => {
633
+ it("returns a diagnostic result", async () => {
634
+ const { checkToolVersions } = await import("./doctor.js");
635
+ const result = await checkToolVersions();
636
+ expect(result.status).toBeDefined();
637
+ expect(result.name).toContain("Tool Versions");
638
+ });
639
+ });
640
+ describe("checkMemoryFileSize", () => {
641
+ it("returns pass when memory files are within limits", async () => {
642
+ const { pathExists } = await import("@mycelish/core");
643
+ const fs = await import("node:fs/promises");
644
+ vi.mocked(pathExists).mockResolvedValue(true);
645
+ vi.mocked(fs.readFile).mockResolvedValue("Line 1\nLine 2\nLine 3");
646
+ const { checkMemoryFileSize } = await import("./doctor.js");
647
+ const result = await checkMemoryFileSize("/mock/path/MEMORY.md", 200);
648
+ expect(result.status).toBe("pass");
649
+ });
650
+ it("returns warn when memory file exceeds limit", async () => {
651
+ const { pathExists } = await import("@mycelish/core");
652
+ const fs = await import("node:fs/promises");
653
+ vi.mocked(pathExists).mockResolvedValue(true);
654
+ const longContent = Array.from({ length: 250 }, (_, i) => `Line ${i}`).join("\n");
655
+ vi.mocked(fs.readFile).mockResolvedValue(longContent);
656
+ const { checkMemoryFileSize } = await import("./doctor.js");
657
+ const result = await checkMemoryFileSize("/mock/path/MEMORY.md", 200);
658
+ expect(result.status).toBe("warn");
659
+ expect(result.message).toContain("250");
660
+ });
661
+ it("returns pass when file does not exist", async () => {
662
+ const { pathExists } = await import("@mycelish/core");
663
+ vi.mocked(pathExists).mockResolvedValue(false);
664
+ const { checkMemoryFileSize } = await import("./doctor.js");
665
+ const result = await checkMemoryFileSize("/mock/path/MEMORY.md", 200);
666
+ expect(result.status).toBe("pass");
667
+ });
668
+ });
669
+ describe("doctorCommand (Commander.js)", () => {
670
+ it("exports a Command instance", async () => {
671
+ const { doctorCommand } = await import("./doctor.js");
672
+ expect(doctorCommand).toBeDefined();
673
+ expect(doctorCommand.name()).toBe("doctor");
674
+ });
675
+ it("has --json option", async () => {
676
+ const { doctorCommand } = await import("./doctor.js");
677
+ const jsonOption = doctorCommand.options.find((opt) => opt.short === "-j" || opt.long === "--json");
678
+ expect(jsonOption).toBeDefined();
679
+ });
680
+ it("has --fix option", async () => {
681
+ const { doctorCommand } = await import("./doctor.js");
682
+ const fixOption = doctorCommand.options.find((opt) => opt.short === "-f" || opt.long === "--fix");
683
+ expect(fixOption).toBeDefined();
684
+ });
685
+ it("has description", async () => {
686
+ const { doctorCommand } = await import("./doctor.js");
687
+ expect(doctorCommand.description()).toContain("health");
688
+ });
689
+ });
690
+ });
691
+ //# sourceMappingURL=doctor.test.js.map