@creeperhost/modlens-mcp 1.6.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 (382) hide show
  1. package/README.md +938 -0
  2. package/dist/access-flags.d.ts +58 -0
  3. package/dist/access-flags.d.ts.map +1 -0
  4. package/dist/access-flags.js +79 -0
  5. package/dist/access-flags.js.map +1 -0
  6. package/dist/access-flags.test.d.ts +2 -0
  7. package/dist/access-flags.test.d.ts.map +1 -0
  8. package/dist/access-flags.test.js +189 -0
  9. package/dist/access-flags.test.js.map +1 -0
  10. package/dist/batch-ingest.d.ts +2 -0
  11. package/dist/batch-ingest.d.ts.map +1 -0
  12. package/dist/batch-ingest.js +54 -0
  13. package/dist/batch-ingest.js.map +1 -0
  14. package/dist/batch-resolve-mixins.d.ts +2 -0
  15. package/dist/batch-resolve-mixins.d.ts.map +1 -0
  16. package/dist/batch-resolve-mixins.js +36 -0
  17. package/dist/batch-resolve-mixins.js.map +1 -0
  18. package/dist/cache.d.ts +16 -0
  19. package/dist/cache.d.ts.map +1 -0
  20. package/dist/cache.js +36 -0
  21. package/dist/cache.js.map +1 -0
  22. package/dist/cli.d.ts +2 -0
  23. package/dist/cli.d.ts.map +1 -0
  24. package/dist/cli.js +1318 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/curseforge.d.ts +53 -0
  27. package/dist/curseforge.d.ts.map +1 -0
  28. package/dist/curseforge.js +104 -0
  29. package/dist/curseforge.js.map +1 -0
  30. package/dist/db-backend.d.ts +17 -0
  31. package/dist/db-backend.d.ts.map +1 -0
  32. package/dist/db-backend.js +40 -0
  33. package/dist/db-backend.js.map +1 -0
  34. package/dist/db.d.ts +11 -0
  35. package/dist/db.d.ts.map +1 -0
  36. package/dist/db.js +55 -0
  37. package/dist/db.js.map +1 -0
  38. package/dist/embed-queue.d.ts +12 -0
  39. package/dist/embed-queue.d.ts.map +1 -0
  40. package/dist/embed-queue.js +103 -0
  41. package/dist/embed-queue.js.map +1 -0
  42. package/dist/embeddings.d.ts +21 -0
  43. package/dist/embeddings.d.ts.map +1 -0
  44. package/dist/embeddings.js +55 -0
  45. package/dist/embeddings.js.map +1 -0
  46. package/dist/env-path.d.ts +19 -0
  47. package/dist/env-path.d.ts.map +1 -0
  48. package/dist/env-path.js +40 -0
  49. package/dist/env-path.js.map +1 -0
  50. package/dist/fetch-utils.d.ts +24 -0
  51. package/dist/fetch-utils.d.ts.map +1 -0
  52. package/dist/fetch-utils.js +73 -0
  53. package/dist/fetch-utils.js.map +1 -0
  54. package/dist/fetch-utils.test.d.ts +2 -0
  55. package/dist/fetch-utils.test.d.ts.map +1 -0
  56. package/dist/fetch-utils.test.js +133 -0
  57. package/dist/fetch-utils.test.js.map +1 -0
  58. package/dist/generated/sqlite/browser.d.ts +55 -0
  59. package/dist/generated/sqlite/browser.d.ts.map +1 -0
  60. package/dist/generated/sqlite/browser.js +18 -0
  61. package/dist/generated/sqlite/browser.js.map +1 -0
  62. package/dist/generated/sqlite/client.d.ts +72 -0
  63. package/dist/generated/sqlite/client.d.ts.map +1 -0
  64. package/dist/generated/sqlite/client.js +33 -0
  65. package/dist/generated/sqlite/client.js.map +1 -0
  66. package/dist/generated/sqlite/commonInputTypes.d.ts +387 -0
  67. package/dist/generated/sqlite/commonInputTypes.d.ts.map +1 -0
  68. package/dist/generated/sqlite/commonInputTypes.js +11 -0
  69. package/dist/generated/sqlite/commonInputTypes.js.map +1 -0
  70. package/dist/generated/sqlite/enums.d.ts +2 -0
  71. package/dist/generated/sqlite/enums.d.ts.map +1 -0
  72. package/dist/generated/sqlite/enums.js +11 -0
  73. package/dist/generated/sqlite/enums.js.map +1 -0
  74. package/dist/generated/sqlite/internal/class.d.ts +226 -0
  75. package/dist/generated/sqlite/internal/class.d.ts.map +1 -0
  76. package/dist/generated/sqlite/internal/class.js +84 -0
  77. package/dist/generated/sqlite/internal/class.js.map +1 -0
  78. package/dist/generated/sqlite/internal/prismaNamespace.d.ts +1344 -0
  79. package/dist/generated/sqlite/internal/prismaNamespace.d.ts.map +1 -0
  80. package/dist/generated/sqlite/internal/prismaNamespace.js +220 -0
  81. package/dist/generated/sqlite/internal/prismaNamespace.js.map +1 -0
  82. package/dist/generated/sqlite/internal/prismaNamespaceBrowser.d.ts +204 -0
  83. package/dist/generated/sqlite/internal/prismaNamespaceBrowser.d.ts.map +1 -0
  84. package/dist/generated/sqlite/internal/prismaNamespaceBrowser.js +191 -0
  85. package/dist/generated/sqlite/internal/prismaNamespaceBrowser.js.map +1 -0
  86. package/dist/generated/sqlite/models/DocEntry.d.ts +1223 -0
  87. package/dist/generated/sqlite/models/DocEntry.d.ts.map +1 -0
  88. package/dist/generated/sqlite/models/DocEntry.js +2 -0
  89. package/dist/generated/sqlite/models/DocEntry.js.map +1 -0
  90. package/dist/generated/sqlite/models/McSourceFile.d.ts +1289 -0
  91. package/dist/generated/sqlite/models/McSourceFile.d.ts.map +1 -0
  92. package/dist/generated/sqlite/models/McSourceFile.js +2 -0
  93. package/dist/generated/sqlite/models/McSourceFile.js.map +1 -0
  94. package/dist/generated/sqlite/models/McVersion.d.ts +1315 -0
  95. package/dist/generated/sqlite/models/McVersion.d.ts.map +1 -0
  96. package/dist/generated/sqlite/models/McVersion.js +2 -0
  97. package/dist/generated/sqlite/models/McVersion.js.map +1 -0
  98. package/dist/generated/sqlite/models/McVersionDiff.d.ts +1061 -0
  99. package/dist/generated/sqlite/models/McVersionDiff.d.ts.map +1 -0
  100. package/dist/generated/sqlite/models/McVersionDiff.js +2 -0
  101. package/dist/generated/sqlite/models/McVersionDiff.js.map +1 -0
  102. package/dist/generated/sqlite/models/Mod.d.ts +2396 -0
  103. package/dist/generated/sqlite/models/Mod.d.ts.map +1 -0
  104. package/dist/generated/sqlite/models/Mod.js +2 -0
  105. package/dist/generated/sqlite/models/Mod.js.map +1 -0
  106. package/dist/generated/sqlite/models/ModClass.d.ts +1254 -0
  107. package/dist/generated/sqlite/models/ModClass.d.ts.map +1 -0
  108. package/dist/generated/sqlite/models/ModClass.js +2 -0
  109. package/dist/generated/sqlite/models/ModClass.js.map +1 -0
  110. package/dist/generated/sqlite/models/ModSourceFile.d.ts +1283 -0
  111. package/dist/generated/sqlite/models/ModSourceFile.d.ts.map +1 -0
  112. package/dist/generated/sqlite/models/ModSourceFile.js +2 -0
  113. package/dist/generated/sqlite/models/ModSourceFile.js.map +1 -0
  114. package/dist/generated/sqlite/models/ModTag.d.ts +1278 -0
  115. package/dist/generated/sqlite/models/ModTag.d.ts.map +1 -0
  116. package/dist/generated/sqlite/models/ModTag.js +2 -0
  117. package/dist/generated/sqlite/models/ModTag.js.map +1 -0
  118. package/dist/generated/sqlite/models/ModVersionDiff.d.ts +1073 -0
  119. package/dist/generated/sqlite/models/ModVersionDiff.d.ts.map +1 -0
  120. package/dist/generated/sqlite/models/ModVersionDiff.js +2 -0
  121. package/dist/generated/sqlite/models/ModVersionDiff.js.map +1 -0
  122. package/dist/generated/sqlite/models/Primer.d.ts +1319 -0
  123. package/dist/generated/sqlite/models/Primer.d.ts.map +1 -0
  124. package/dist/generated/sqlite/models/Primer.js +2 -0
  125. package/dist/generated/sqlite/models/Primer.js.map +1 -0
  126. package/dist/generated/sqlite/models.d.ts +12 -0
  127. package/dist/generated/sqlite/models.d.ts.map +1 -0
  128. package/dist/generated/sqlite/models.js +2 -0
  129. package/dist/generated/sqlite/models.js.map +1 -0
  130. package/dist/jar.d.ts +7 -0
  131. package/dist/jar.d.ts.map +1 -0
  132. package/dist/jar.js +52 -0
  133. package/dist/jar.js.map +1 -0
  134. package/dist/java-tools.d.ts +46 -0
  135. package/dist/java-tools.d.ts.map +1 -0
  136. package/dist/java-tools.js +263 -0
  137. package/dist/java-tools.js.map +1 -0
  138. package/dist/launcher.d.ts +3 -0
  139. package/dist/launcher.d.ts.map +1 -0
  140. package/dist/launcher.js +105 -0
  141. package/dist/launcher.js.map +1 -0
  142. package/dist/mappings.d.ts +95 -0
  143. package/dist/mappings.d.ts.map +1 -0
  144. package/dist/mappings.js +1094 -0
  145. package/dist/mappings.js.map +1 -0
  146. package/dist/mappings.test.d.ts +2 -0
  147. package/dist/mappings.test.d.ts.map +1 -0
  148. package/dist/mappings.test.js +161 -0
  149. package/dist/mappings.test.js.map +1 -0
  150. package/dist/minecraft.d.ts +21 -0
  151. package/dist/minecraft.d.ts.map +1 -0
  152. package/dist/minecraft.js +70 -0
  153. package/dist/minecraft.js.map +1 -0
  154. package/dist/modpacks-ch.d.ts +224 -0
  155. package/dist/modpacks-ch.d.ts.map +1 -0
  156. package/dist/modpacks-ch.js +146 -0
  157. package/dist/modpacks-ch.js.map +1 -0
  158. package/dist/modrinth.d.ts +67 -0
  159. package/dist/modrinth.d.ts.map +1 -0
  160. package/dist/modrinth.js +88 -0
  161. package/dist/modrinth.js.map +1 -0
  162. package/dist/platform-adapter.d.ts +23 -0
  163. package/dist/platform-adapter.d.ts.map +1 -0
  164. package/dist/platform-adapter.js +2 -0
  165. package/dist/platform-adapter.js.map +1 -0
  166. package/dist/platform.d.ts +47 -0
  167. package/dist/platform.d.ts.map +1 -0
  168. package/dist/platform.js +175 -0
  169. package/dist/platform.js.map +1 -0
  170. package/dist/processor.d.ts +51 -0
  171. package/dist/processor.d.ts.map +1 -0
  172. package/dist/processor.js +655 -0
  173. package/dist/processor.js.map +1 -0
  174. package/dist/processor.test.d.ts +2 -0
  175. package/dist/processor.test.d.ts.map +1 -0
  176. package/dist/processor.test.js +629 -0
  177. package/dist/processor.test.js.map +1 -0
  178. package/dist/repositories/embeddings-sqlite.d.ts +38 -0
  179. package/dist/repositories/embeddings-sqlite.d.ts.map +1 -0
  180. package/dist/repositories/embeddings-sqlite.js +208 -0
  181. package/dist/repositories/embeddings-sqlite.js.map +1 -0
  182. package/dist/repositories/embeddings.d.ts +40 -0
  183. package/dist/repositories/embeddings.d.ts.map +1 -0
  184. package/dist/repositories/embeddings.js +136 -0
  185. package/dist/repositories/embeddings.js.map +1 -0
  186. package/dist/repositories/index.d.ts +2 -0
  187. package/dist/repositories/index.d.ts.map +1 -0
  188. package/dist/repositories/index.js +15 -0
  189. package/dist/repositories/index.js.map +1 -0
  190. package/dist/repositories/mcVersion.d.ts +16 -0
  191. package/dist/repositories/mcVersion.d.ts.map +1 -0
  192. package/dist/repositories/mcVersion.js +52 -0
  193. package/dist/repositories/mcVersion.js.map +1 -0
  194. package/dist/repositories/mod.d.ts +241 -0
  195. package/dist/repositories/mod.d.ts.map +1 -0
  196. package/dist/repositories/mod.js +342 -0
  197. package/dist/repositories/mod.js.map +1 -0
  198. package/dist/repositories/packs.d.ts +44 -0
  199. package/dist/repositories/packs.d.ts.map +1 -0
  200. package/dist/repositories/packs.js +138 -0
  201. package/dist/repositories/packs.js.map +1 -0
  202. package/dist/search-adapter.d.ts +34 -0
  203. package/dist/search-adapter.d.ts.map +1 -0
  204. package/dist/search-adapter.js +195 -0
  205. package/dist/search-adapter.js.map +1 -0
  206. package/dist/search.d.ts +6 -0
  207. package/dist/search.d.ts.map +1 -0
  208. package/dist/search.js +54 -0
  209. package/dist/search.js.map +1 -0
  210. package/dist/search.test.d.ts +2 -0
  211. package/dist/search.test.d.ts.map +1 -0
  212. package/dist/search.test.js +71 -0
  213. package/dist/search.test.js.map +1 -0
  214. package/dist/security.d.ts +98 -0
  215. package/dist/security.d.ts.map +1 -0
  216. package/dist/security.js +446 -0
  217. package/dist/security.js.map +1 -0
  218. package/dist/security.test.d.ts +2 -0
  219. package/dist/security.test.d.ts.map +1 -0
  220. package/dist/security.test.js +687 -0
  221. package/dist/security.test.js.map +1 -0
  222. package/dist/server.d.ts +2 -0
  223. package/dist/server.d.ts.map +1 -0
  224. package/dist/server.js +1465 -0
  225. package/dist/server.js.map +1 -0
  226. package/dist/setup.d.ts +2 -0
  227. package/dist/setup.d.ts.map +1 -0
  228. package/dist/setup.js +1113 -0
  229. package/dist/setup.js.map +1 -0
  230. package/dist/tools/bytecode.d.ts +129 -0
  231. package/dist/tools/bytecode.d.ts.map +1 -0
  232. package/dist/tools/bytecode.js +679 -0
  233. package/dist/tools/bytecode.js.map +1 -0
  234. package/dist/tools/catalog.d.ts +54 -0
  235. package/dist/tools/catalog.d.ts.map +1 -0
  236. package/dist/tools/catalog.js +249 -0
  237. package/dist/tools/catalog.js.map +1 -0
  238. package/dist/tools/compat-check.d.ts +23 -0
  239. package/dist/tools/compat-check.d.ts.map +1 -0
  240. package/dist/tools/compat-check.js +250 -0
  241. package/dist/tools/compat-check.js.map +1 -0
  242. package/dist/tools/compat-check.test.d.ts +2 -0
  243. package/dist/tools/compat-check.test.d.ts.map +1 -0
  244. package/dist/tools/compat-check.test.js +179 -0
  245. package/dist/tools/compat-check.test.js.map +1 -0
  246. package/dist/tools/diagnostics.d.ts +10 -0
  247. package/dist/tools/diagnostics.d.ts.map +1 -0
  248. package/dist/tools/diagnostics.js +133 -0
  249. package/dist/tools/diagnostics.js.map +1 -0
  250. package/dist/tools/diagnostics.test.d.ts +2 -0
  251. package/dist/tools/diagnostics.test.d.ts.map +1 -0
  252. package/dist/tools/diagnostics.test.js +168 -0
  253. package/dist/tools/diagnostics.test.js.map +1 -0
  254. package/dist/tools/docs.d.ts +19 -0
  255. package/dist/tools/docs.d.ts.map +1 -0
  256. package/dist/tools/docs.js +230 -0
  257. package/dist/tools/docs.js.map +1 -0
  258. package/dist/tools/embed-registry.d.ts +125 -0
  259. package/dist/tools/embed-registry.d.ts.map +1 -0
  260. package/dist/tools/embed-registry.js +560 -0
  261. package/dist/tools/embed-registry.js.map +1 -0
  262. package/dist/tools/gradle.d.ts +16 -0
  263. package/dist/tools/gradle.d.ts.map +1 -0
  264. package/dist/tools/gradle.js +182 -0
  265. package/dist/tools/gradle.js.map +1 -0
  266. package/dist/tools/graphify.d.ts +144 -0
  267. package/dist/tools/graphify.d.ts.map +1 -0
  268. package/dist/tools/graphify.js +798 -0
  269. package/dist/tools/graphify.js.map +1 -0
  270. package/dist/tools/graphify.test.d.ts +2 -0
  271. package/dist/tools/graphify.test.d.ts.map +1 -0
  272. package/dist/tools/graphify.test.js +39 -0
  273. package/dist/tools/graphify.test.js.map +1 -0
  274. package/dist/tools/ingest.d.ts +85 -0
  275. package/dist/tools/ingest.d.ts.map +1 -0
  276. package/dist/tools/ingest.js +477 -0
  277. package/dist/tools/ingest.js.map +1 -0
  278. package/dist/tools/ingest.test.d.ts +2 -0
  279. package/dist/tools/ingest.test.d.ts.map +1 -0
  280. package/dist/tools/ingest.test.js +340 -0
  281. package/dist/tools/ingest.test.js.map +1 -0
  282. package/dist/tools/kubejs.d.ts +37 -0
  283. package/dist/tools/kubejs.d.ts.map +1 -0
  284. package/dist/tools/kubejs.js +245 -0
  285. package/dist/tools/kubejs.js.map +1 -0
  286. package/dist/tools/mappings.d.ts +17 -0
  287. package/dist/tools/mappings.d.ts.map +1 -0
  288. package/dist/tools/mappings.js +85 -0
  289. package/dist/tools/mappings.js.map +1 -0
  290. package/dist/tools/mc-fts.d.ts +101 -0
  291. package/dist/tools/mc-fts.d.ts.map +1 -0
  292. package/dist/tools/mc-fts.js +279 -0
  293. package/dist/tools/mc-fts.js.map +1 -0
  294. package/dist/tools/mcmeta.d.ts +41 -0
  295. package/dist/tools/mcmeta.d.ts.map +1 -0
  296. package/dist/tools/mcmeta.js +365 -0
  297. package/dist/tools/mcmeta.js.map +1 -0
  298. package/dist/tools/mixin-scan.d.ts +113 -0
  299. package/dist/tools/mixin-scan.d.ts.map +1 -0
  300. package/dist/tools/mixin-scan.js +433 -0
  301. package/dist/tools/mixin-scan.js.map +1 -0
  302. package/dist/tools/mod-data.d.ts +83 -0
  303. package/dist/tools/mod-data.d.ts.map +1 -0
  304. package/dist/tools/mod-data.js +630 -0
  305. package/dist/tools/mod-data.js.map +1 -0
  306. package/dist/tools/mod-tags.d.ts +59 -0
  307. package/dist/tools/mod-tags.d.ts.map +1 -0
  308. package/dist/tools/mod-tags.js +279 -0
  309. package/dist/tools/mod-tags.js.map +1 -0
  310. package/dist/tools/mod-tags.test.d.ts +2 -0
  311. package/dist/tools/mod-tags.test.d.ts.map +1 -0
  312. package/dist/tools/mod-tags.test.js +75 -0
  313. package/dist/tools/mod-tags.test.js.map +1 -0
  314. package/dist/tools/modpacks-ch.d.ts +257 -0
  315. package/dist/tools/modpacks-ch.d.ts.map +1 -0
  316. package/dist/tools/modpacks-ch.js +516 -0
  317. package/dist/tools/modpacks-ch.js.map +1 -0
  318. package/dist/tools/packtools.d.ts +113 -0
  319. package/dist/tools/packtools.d.ts.map +1 -0
  320. package/dist/tools/packtools.js +809 -0
  321. package/dist/tools/packtools.js.map +1 -0
  322. package/dist/tools/packtools.test.d.ts +2 -0
  323. package/dist/tools/packtools.test.d.ts.map +1 -0
  324. package/dist/tools/packtools.test.js +99 -0
  325. package/dist/tools/packtools.test.js.map +1 -0
  326. package/dist/tools/platform.d.ts +68 -0
  327. package/dist/tools/platform.d.ts.map +1 -0
  328. package/dist/tools/platform.js +452 -0
  329. package/dist/tools/platform.js.map +1 -0
  330. package/dist/tools/primers.d.ts +36 -0
  331. package/dist/tools/primers.d.ts.map +1 -0
  332. package/dist/tools/primers.js +451 -0
  333. package/dist/tools/primers.js.map +1 -0
  334. package/dist/tools/reports.d.ts +19 -0
  335. package/dist/tools/reports.d.ts.map +1 -0
  336. package/dist/tools/reports.js +573 -0
  337. package/dist/tools/reports.js.map +1 -0
  338. package/dist/tools/source.d.ts +10 -0
  339. package/dist/tools/source.d.ts.map +1 -0
  340. package/dist/tools/source.js +101 -0
  341. package/dist/tools/source.js.map +1 -0
  342. package/dist/tools/vanilla-data.d.ts +127 -0
  343. package/dist/tools/vanilla-data.d.ts.map +1 -0
  344. package/dist/tools/vanilla-data.js +824 -0
  345. package/dist/tools/vanilla-data.js.map +1 -0
  346. package/dist/tools/vanilla.d.ts +171 -0
  347. package/dist/tools/vanilla.d.ts.map +1 -0
  348. package/dist/tools/vanilla.js +612 -0
  349. package/dist/tools/vanilla.js.map +1 -0
  350. package/dist/tools/version-diff.d.ts +113 -0
  351. package/dist/tools/version-diff.d.ts.map +1 -0
  352. package/dist/tools/version-diff.js +519 -0
  353. package/dist/tools/version-diff.js.map +1 -0
  354. package/dist/tools/version-diff.test.d.ts +2 -0
  355. package/dist/tools/version-diff.test.d.ts.map +1 -0
  356. package/dist/tools/version-diff.test.js +102 -0
  357. package/dist/tools/version-diff.test.js.map +1 -0
  358. package/dist/validate.d.ts +19 -0
  359. package/dist/validate.d.ts.map +1 -0
  360. package/dist/validate.js +54 -0
  361. package/dist/validate.js.map +1 -0
  362. package/dist/validate.test.d.ts +2 -0
  363. package/dist/validate.test.d.ts.map +1 -0
  364. package/dist/validate.test.js +73 -0
  365. package/dist/validate.test.js.map +1 -0
  366. package/package.json +62 -0
  367. package/prisma/backends/schema.sqlite.prisma +215 -0
  368. package/prisma/backends/template.db +0 -0
  369. package/prisma/schema.prisma +303 -0
  370. package/scripts/backup.mjs +151 -0
  371. package/scripts/build-template-db.mjs +38 -0
  372. package/scripts/check-atm10.mjs +27 -0
  373. package/scripts/check-sync.mjs +13 -0
  374. package/scripts/create-fts-index.mjs +50 -0
  375. package/scripts/enable-pgvector.mjs +90 -0
  376. package/scripts/enable-sqlite-vec.mjs +158 -0
  377. package/scripts/migrate-backend.mjs +188 -0
  378. package/scripts/migrate-embed-provenance.mjs +80 -0
  379. package/scripts/migrate-metadata-source.mjs +62 -0
  380. package/scripts/migrate-mod-source-files.mjs +67 -0
  381. package/scripts/post-update.mjs +77 -0
  382. package/scripts/verify-atm10.mjs +63 -0
package/dist/cli.js ADDED
@@ -0,0 +1,1318 @@
1
+ /**
2
+ * modlens CLI — command-line interface for all modlens-mcp operations.
3
+ * Usage: node dist/cli.js <command> [args] [--flags]
4
+ * Run without arguments to see all commands.
5
+ */
6
+ import { ingestMod, decompileMod, decompileModStatus, reindexClasses, batchDecompileMods } from "./tools/ingest.js";
7
+ import { listMods, getModDetails, searchMods, getDbStats, getDependencies, findVersionConflicts, getDependencyGraph, listModSourceUrls, listModRegistryEntries } from "./tools/catalog.js";
8
+ import { getModSource, searchSource, decompileModClass } from "./tools/source.js";
9
+ import { searchModClass, getModClassMembers, getModClassBytecode, findModReferences, getModInheritance, diffModVersions, crossModRefs, findImplementors, scanModRegistrations, findAnnotatedClasses, findEventListeners, findOptionalIntegrations, findNetworkPayloads, extractConfigSchema, } from "./tools/bytecode.js";
10
+ import { getMixinTargets, getMixinConflicts, getAtEntries, getAwEntries, resolveMixinTargets, getMixinsTargetingPackage, findAtAwConflicts, listModsWithMixins, getMixinConflictMatrix, getMixinClassDetail, getMixinHotspots, batchResolveMixins, } from "./tools/mixin-scan.js";
11
+ import { syncModrinth, syncCurseforge, checkUpdates, downloadSource, batchSyncSources } from "./tools/platform.js";
12
+ import { listMcVersions, listNeoForgeVersions, listFabricApiVersions, downloadNeoForge, downloadFabricApi, downloadForge, } from "./platform.js";
13
+ import { searchMinecraftClass, getMinecraftSource, getMcClassBytecode, getMcClassMembers, findMcReferences, getMcInheritance, diffMcVersions, decompileMcVersion, decompileMcVersionStatus, searchMcCode, validateAccessWidener, analyzeMixin, searchEvents, } from "./tools/vanilla.js";
14
+ import { diffMcVersionsDetailed, diffModVersionsDetailed } from "./tools/version-diff.js";
15
+ import { indexMcVersion, searchMcIndexed, indexMcSourceSemantic, searchMcSourceSemantic, indexModSourceFts, indexModSourceSemantic, searchModSourceIndexed, } from "./tools/mc-fts.js";
16
+ import { findMapping, remapModJar, getParchment, listParchmentVersions, getParchmentSummary } from "./tools/mappings.js";
17
+ import { getDocumentation, searchDocumentation, listDocumentation, deleteDocumentation, seedDefaultDocumentation, semanticSearchDocumentation, backfillDocEmbeddings, } from "./tools/docs.js";
18
+ import { getPrimer, getPrimersByVersionRange, searchPrimers, listPrimers, deletePrimer, seedDefaultPrimers, semanticSearchPrimers, backfillPrimerEmbeddings, } from "./tools/primers.js";
19
+ import { getMcmetaVersions, getMcBlocks, getMcCommands, getMcRegistries, getMcSounds, getMcItemComponents, getMcDataFile, getMcAssetFile, listMcDataFiles, diffMcData, getMcAtlas, getMcmetaRaw, getRegistryEntries, compareVersions, getVersionChangelog, } from "./tools/mcmeta.js";
20
+ import { getMcTags, findTagsForEntry, listRecipes, getRecipe, findRecipesForItem, listLootTables, getLootTable, getLangEntries, getBlockstate, getMcModel, getModelTree, listBiomes, getBiome, listDamageTypes, listEnchantments, getEnchantment, listAdvancements, getAdvancement, listStructures, getStructureData, getMcParticles, getParticleData, getEntityAttributes, } from "./tools/vanilla-data.js";
21
+ import { indexModTags, indexAllModTags, listTagNamespaces, getTagContributors, getModTagList, findTagConflicts, searchModTags, expandTag, } from "./tools/mod-tags.js";
22
+ import { getModGradleFiles, searchGradleFiles, compareGradleDeps } from "./tools/gradle.js";
23
+ import { generateReport } from "./tools/reports.js";
24
+ import { findAssetConflicts, findVanillaOverrides, analyzeModSidedness, analyzePackSidedness, computeModComplexity, computePackChangelog, findDataConflicts } from "./tools/packtools.js";
25
+ import { indexKubeJsScripts, searchKubeJsScripts } from "./tools/kubejs.js";
26
+ import { searchPacksAction, featuredPacksAction, packInfoAction, packManifestAction, ftbModInfoAction, listPackVersionsAction, listPackFilesAction, findModInPacksAction, } from "./tools/modpacks-ch.js";
27
+ import { analyzeCrashLog, findMissingDeps } from "./tools/diagnostics.js";
28
+ import { checkModCompat } from "./tools/compat-check.js";
29
+ import { listModJarFiles, getModJarFile, getModLang, getModSounds, getModAtlas, getModManifest, listModConfigs, getModConfig, listModData, getModData, listModDataTags, getModDataTag, getModModel as getModModelData, diffModData, traceRecipeChain, } from "./tools/mod-data.js";
30
+ import { mcPaths } from "./minecraft.js";
31
+ import { findModById } from "./repositories/mod.js";
32
+ import { CACHE_ROOT } from "./cache.js";
33
+ import { getDb, disconnect } from "./db.js";
34
+ import { readdir, readFile } from "fs/promises";
35
+ import { join, resolve } from "path";
36
+ // ── Arg parsing ──────────────────────────────────────────────────────────────
37
+ const [, , command, ...rest] = process.argv;
38
+ function parseArgs(args) {
39
+ const flags = {};
40
+ const positional = [];
41
+ for (const arg of args) {
42
+ if (arg.startsWith("--")) {
43
+ const eq = arg.indexOf("=");
44
+ if (eq !== -1) {
45
+ const key = toCamel(arg.slice(2, eq));
46
+ const raw = arg.slice(eq + 1);
47
+ flags[key] = raw !== "" && !isNaN(Number(raw)) ? Number(raw) : raw;
48
+ }
49
+ else {
50
+ flags[toCamel(arg.slice(2))] = true;
51
+ }
52
+ }
53
+ else {
54
+ positional.push(arg);
55
+ }
56
+ }
57
+ return { flags, positional };
58
+ }
59
+ function toCamel(s) {
60
+ return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
61
+ }
62
+ function out(data) {
63
+ console.log(typeof data === "string" ? data : JSON.stringify(data, null, 2));
64
+ }
65
+ function die(msg) {
66
+ console.error(`Error: ${msg}`);
67
+ process.exit(1);
68
+ }
69
+ function requireArg(val, name) {
70
+ if (!val)
71
+ die(`<${name}> is required`);
72
+ return val;
73
+ }
74
+ function numArg(val, name) {
75
+ const n = Number(val);
76
+ if (!val || isNaN(n))
77
+ die(`<${name}> must be a number`);
78
+ return n;
79
+ }
80
+ function modIdArg(val, name) {
81
+ const s = requireArg(val, name);
82
+ const n = Number(s);
83
+ return isNaN(n) ? s : n;
84
+ }
85
+ // ── Help ─────────────────────────────────────────────────────────────────────
86
+ const HELP = `
87
+ modlens CLI — analyze Minecraft mod JARs
88
+
89
+ Usage: node dist/cli.js <command> [args] [--flags]
90
+
91
+ DATABASE & CATALOG
92
+ stats DB statistics (mod count, classes, loaders)
93
+ list List all mods
94
+ [--loader=] [--mc-version=] [--has-mixins] [--decompiled] [--limit=50]
95
+ get <modId|dbId> Get full metadata for a mod
96
+ search <query> Search mods by name/id [--loader=] [--mc-version=] [--limit=20]
97
+ deps <modId|dbId> List mod dependencies [--recursive]
98
+
99
+ INGEST
100
+ ingest <jarPath> Ingest a mod JAR [--skip-source] [--skip-index]
101
+ ingest-neoforge <version> Download + ingest NeoForge (e.g. 21.1.228) [--skip-index]
102
+ ingest-forge <version> Download + ingest Forge (e.g. 1.20.1-47.3.22) [--skip-index]
103
+ ingest-fabric-api <version> Download + ingest Fabric API (e.g. 0.116.11+1.21.1) [--skip-index]
104
+ batch-ingest <dir> Ingest all JARs in a directory [--index]
105
+ reindex Index class names for un-indexed mods [--db-id=N]
106
+
107
+ DECOMPILE & SOURCE
108
+ decompile <dbId> Decompile entire mod JAR with Vineflower
109
+ decompile-class <dbId> <class> Decompile a single class (faster)
110
+ source <dbId> [path] Browse or read decompiled source
111
+ search-source <query> Search decompiled source [--db-id=N] [--regex] [--limit=50]
112
+
113
+ BYTECODE ANALYSIS
114
+ search-class <dbId> <query> Search for a class by name
115
+ members <dbId> <class> List methods and fields of a class
116
+ bytecode <dbId> <class> Raw javap bytecode for a class
117
+ refs <dbId> <target> Find references to a class/method/field
118
+ inheritance <dbId> <class> Superclass, interfaces, subclasses
119
+ diff <dbIdA> <dbIdB> Compare two mod versions (added/removed classes)
120
+
121
+ MIXIN ANALYSIS
122
+ mixin-targets <modId|dbId> MC classes this mod injects into
123
+ resolve-mixins <dbId> Parse @Mixin bytecode and update DB targets
124
+ mixin-conflicts <targetClass> All mods injecting into the same MC class
125
+ at-entries <dbId> Access Transformer entries
126
+ aw-entries <dbId> Access Widener entries
127
+
128
+ PLATFORM
129
+ sync-modrinth <dbId> Look up mod on Modrinth
130
+ sync-curseforge <dbId> Look up mod on CurseForge
131
+ check-updates <dbId> Check for newer versions
132
+ download-source <dbId> Download GitHub/GitLab source
133
+
134
+ VERSIONS
135
+ mc-versions List Minecraft versions [--type=release|snapshot|all]
136
+ neoforge-versions List NeoForge versions [--mc-version=1.21.1] [--limit=20]
137
+ fabric-api-versions List Fabric API versions [--mc-version=1.21.1] [--limit=20]
138
+
139
+ BATCH
140
+ batch-resolve-mixins Resolve @Mixin targets for all mixin mods
141
+
142
+ MOD: ADDITIONAL ACTIONS
143
+ dep-graph Dependency graph for all ingested mods [--mc-version=]
144
+ version-conflicts Find mods with conflicting version requirements
145
+ source-urls [query] List Modrinth/CurseForge source URLs (filter by query)
146
+ decompile-status <dbId> Decompilation progress for a mod
147
+ batch-decompile Decompile all un-decompiled mods [--concurrency=2]
148
+ get-paths <dbId> JAR/decomp paths so you can grep natively
149
+ batch-sync Batch sync all mods from platform APIs
150
+ [--sync-modrinth] [--sync-curseforge] [--download-sources]
151
+ [--mod-id-filter=] [--limit=]
152
+
153
+ MOD BYTECODE: ADVANCED
154
+ cross-refs <target> Cross-mod references to a class/method/field
155
+ [--mc-version=] [--loader=] [--limit=]
156
+ diff-detailed <dbIdA> <dbIdB> AST-level method/field diff with breaking-change flags
157
+ [--packages=a/b,c/d] [--limit=200] [--semantic] [--cache] [--force]
158
+ find-implementors <target> Find all classes implementing an interface/extending a class
159
+ [--mod-id=] [--limit=] [--transitive]
160
+ scan-registrations <dbId> Scan mod for registry object registrations
161
+ annotated-by <annotation> Find classes annotated with a given annotation [--mod-id=] [--limit=]
162
+ event-listeners <event> Find event listener registrations [--mod-id=] [--limit=]
163
+ optional-integrations <dbId> Detect optional mod integrations (soft dependencies)
164
+ network-payloads <dbId> Extract network packet/payload types
165
+ config-schema <dbId> Extract configuration class schemas
166
+
167
+ MIXIN ANALYSIS: ADVANCED
168
+ targets-in-package <packagePrefix> All mods targeting a class within a package [--mc-version=]
169
+ at-conflicts AT/AW entries conflicting across mods [--mc-version=] [--loader=]
170
+
171
+ MIXIN SCAN (cross-mod conflict matrix)
172
+ mixin-scan list List mods with mixins [--loader=] [--mc-version=]
173
+ mixin-scan conflict-matrix Full mixin conflict matrix [--loader=] [--mc-version=] [--min-conflicts=]
174
+ mixin-scan class-detail <class> All mixins targeting a single MC class
175
+ mixin-scan hotspots Most-targeted MC classes [--top=N] [--loader=]
176
+ mixin-scan batch-resolve Resolve mixin targets for all mods [--loader=] [--mc-version=]
177
+
178
+ VANILLA MC SOURCE
179
+ mc-source search-class <ver> <q> Search for a vanilla class by name
180
+ mc-source get-source <ver> <class> Get decompiled vanilla source [--start-line=] [--end-line=] [--max-lines=]
181
+ mc-source bytecode <ver> <class> Raw javap bytecode for a vanilla class
182
+ mc-source class-members <ver> <c> Methods and fields of a vanilla class
183
+ mc-source find-refs <ver> <target> References to a class/method/field in vanilla
184
+ mc-source inheritance <ver> <c> Inheritance tree for a vanilla class
185
+ mc-source diff <verA> <verB> High-level diff between two MC versions
186
+ mc-source diff-detailed <A> <B> AST-level method/field diff [--packages=] [--limit=200] [--semantic] [--cache] [--force]
187
+ mc-source decompile <ver> Decompile MC version with Vineflower [--force]
188
+ mc-source decompile-status <ver> Check decompilation progress
189
+ mc-source search-code <ver> <q> Full-text search over vanilla source [--search-type=content|class|method|field|all] [--regex] [--limit=50]
190
+ mc-source index <ver> Index vanilla source for BM25 search [--force]
191
+ mc-source search-indexed <ver> <q> BM25-ranked FTS over vanilla source [--limit=20]
192
+ mc-source search-events <ver> Browse event classes [query] [--modloader=minecraft|neoforge|fabric|fabric-api]
193
+ mc-source validate-aw <ver> <file> Validate an .accesswidener file against vanilla
194
+ mc-source analyze-mixin <ver> <f> Analyze a mixin Java source file
195
+ mc-source search-semantic <ver> <q> Semantic search (requires Ollama + index) [--limit=10]
196
+ mc-source get-paths <ver> On-disk jar/decomp/index paths
197
+
198
+ MAPPINGS
199
+ mappings find <sym> <ver> <src> <tgt> Translate symbol between namespaces (official|intermediary|yarn|mojmap)
200
+ mappings remap <in.jar> <out.jar> <ver> <mapping> Remap a JAR between namespaces
201
+ mappings parchment <class> <mcVersion> Parchment parameter/javadoc for a class
202
+ mappings list-parchment <mcVersion> Available Parchment versions
203
+ mappings parchment-summary <mcVersion> Stats on Parchment coverage
204
+
205
+ DOCS
206
+ docs seed Seed built-in documentation entries
207
+ docs get <query> Get documentation by title/class
208
+ docs search <query> Keyword search [--category=] [--namespace=]
209
+ docs list List all docs [--category=] [--namespace=] [--tag=] [--limit=100]
210
+ docs delete <id> Delete a doc entry by ID
211
+ docs semantic-search <query> Semantic search (requires Ollama) [--limit=10]
212
+
213
+ PRIMERS (version migration guides)
214
+ primers seed Seed built-in porting primers
215
+ primers get <id> Get primer by ID
216
+ primers by-version <from> <to> Get primers for a version range [--modloader=]
217
+ primers search <query> Keyword search [--modloader=] [--limit=]
218
+ primers list List all primers [--modloader=] [--limit=]
219
+ primers delete <id> Delete a primer by ID
220
+ primers semantic-search <query> Semantic search (requires Ollama) [--limit=10]
221
+
222
+ MC REGISTRY
223
+ mc-registry blocks Vanilla block list [--version=]
224
+ mc-registry commands Vanilla command tree [--version=]
225
+ mc-registry registries Registry keys [--version=] [--registry=]
226
+ mc-registry sounds Sound event list [--version=]
227
+ mc-registry item-components Item component types [--version=]
228
+ mc-registry registry-entries <reg> Entries in a registry [--version=]
229
+ mc-registry mcmeta-versions Versions index [--filter=release|snapshot|all]
230
+
231
+ MC DATA
232
+ mc-data tags Vanilla data tags [--version=] [--registry=] [--tag-id=] [--namespace=]
233
+ mc-data find-tags-for <entry> Tags containing an entry --registry= [--version=] [--namespace=]
234
+ mc-data recipes Recipe list [--version=] [--type=] [--output-item=]
235
+ mc-data get-recipe <id> Single recipe [--version=]
236
+ mc-data find-recipes-for <item> Recipes producing an item [--version=]
237
+ mc-data loot-tables Loot table list [--version=] [--category=]
238
+ mc-data get-loot-table <path> Single loot table [--version=]
239
+ mc-data lang Language entries [--version=] [--filter=] [--limit=]
240
+ mc-data blockstate <block> Blockstate JSON [--version=]
241
+ mc-data model <path> Model JSON [--version=] [--resolve-parents]
242
+ mc-data model-tree <path> Model parent chain [--version=]
243
+ mc-data biomes Biome list [--version=]
244
+ mc-data get-biome <id> Biome data [--version=]
245
+ mc-data damage-types Damage type list [--version=]
246
+ mc-data enchantments Enchantment list [--version=]
247
+ mc-data get-enchantment <id> Enchantment data [--version=]
248
+ mc-data advancements Advancement list [--version=] [--category=]
249
+ mc-data get-advancement <id> Advancement data [--version=]
250
+ mc-data structures Structure list [--version=]
251
+ mc-data get-structure <id> Structure data [--version=]
252
+ mc-data particles Particle list [--version=]
253
+ mc-data get-particle <id> Particle data [--version=]
254
+ mc-data entity-attributes Entity attribute list [--entity=] [--version=] [--mod-id=]
255
+
256
+ MC FILES (misode/mcmeta assets)
257
+ mc-files get-data <path> Get a data-pack file [--version=] [--json-only]
258
+ mc-files get-asset <path> Get an assets file [--version=] [--json-only]
259
+ mc-files list-files <dir> List files in a branch dir --version= [--branch=]
260
+ mc-files diff <path> Diff a file across versions --version-a= --version-b= [--branch=data]
261
+ mc-files atlas Atlas sprite map [--version=] [--atlas=blocks]
262
+ mc-files raw <path> Raw file by git ref --ref=
263
+ mc-files compare Compare two versions summary --version-a= --version-b= [--branch=]
264
+ mc-files changelog Version changelog --version= [--branch=]
265
+
266
+ MOD JAR (file browser)
267
+ mod-jar list-files <modId> List files inside the JAR [--prefix=]
268
+ mod-jar get-file <modId> Read a JAR file --path=
269
+ mod-jar lang <modId> Language entries [--filter=] [--limit=]
270
+ mod-jar sounds <modId> Sound events [--namespace=]
271
+ mod-jar atlas <modId> Atlas sprite map [--atlas=] [--namespace=]
272
+ mod-jar registry-entries <modId> Custom registry entries [--type=] [--filter=] [--limit=]
273
+ mod-jar manifest <modId> mod.json / mods.toml / fabric.mod.json manifest
274
+ mod-jar list-configs <modId> List config files in JAR
275
+ mod-jar get-config <modId> Read a config file --path=
276
+
277
+ MOD DATA (structured data from JAR)
278
+ mod-data list <modId> <type> List data entries [--namespace=] [--filter=]
279
+ mod-data get <modId> <type> <id> Get a data entry [--namespace=] [--registry=] [--model-path=]
280
+ mod-data diff <dbIdA> <dbIdB> Diff data between two mod versions [--data-type=]
281
+ mod-data trace-item <itemId> Trace crafting recipe chain [--max-depth=]
282
+
283
+ MOD TAGS (cross-mod data-pack tags)
284
+ mod-tags index <modId> Index data-pack tags for one mod
285
+ mod-tags index-all Index tags for all ingested mods
286
+ mod-tags namespaces List all tag namespaces
287
+ mod-tags contributors <tagPath> Mods contributing to a tag [--registry=]
288
+ mod-tags expand <tagPath> Recursively expand a tag [--registry=] [--max-depth=]
289
+ mod-tags mod-list <modId> Tags provided by a mod [--registry=]
290
+ mod-tags find-conflicts Tags with replace:true conflicts [--registry=]
291
+ mod-tags search <query> Search tags [--registry=] [--limit=]
292
+
293
+ GRADLE
294
+ gradle get-files <modId> Extract Gradle build files
295
+ gradle search <query> Search Gradle files across mods [--mod-id-filter=] [--limit=]
296
+ gradle compare-deps Compare dependency versions across mods [--group-filter=] [--mod-id-filter=]
297
+
298
+ REPORTS (generate Markdown)
299
+ report mixin-conflicts [--loader=] [--mc-version=] [--min-conflicts=] [--save-path=]
300
+ report tag-conflicts [--registry=] [--save-path=]
301
+ report version-conflicts [--save-path=]
302
+ report mod-overview --mod-id= [--save-path=]
303
+ report gradle-deps [--group-filter=] [--mod-id-filter=] [--save-path=]
304
+ report pack-compat --mod-id= [--save-path=]
305
+ report dep-graph [--mc-version=] [--save-path=]
306
+ report sidedness [--db-ids=1,2,3] [--save-path=]
307
+ report mod-complexity [--db-ids=1,2,3] [--save-path=]
308
+ report pack-changelog --old-ids=1,2 --new-ids=3,4 [--save-path=]
309
+
310
+ PACK TOOLS
311
+ pack-tools asset-conflicts Asset path conflicts [--asset-type=textures|models|sounds|...] [--mc-version=] [--loader=] [--limit=]
312
+ pack-tools vanilla-overrides Mods overriding vanilla data/assets [--override-type=data|assets|all] [--data-subtype=] [--mc-version=] [--loader=]
313
+ pack-tools sidedness <modId> Classify a mod as client/common/server
314
+ pack-tools pack-sidedness Classify all mods by sidedness [--mc-version=] [--loader=]
315
+ pack-tools complexity Mod complexity scores [--mc-version=] [--loader=]
316
+ pack-tools pack-changelog Diff two pack snapshots --old-ids=1,2 --new-ids=3,4
317
+ pack-tools data-conflicts Data path conflicts [--data-type=recipe|loot_tables|...] [--mc-version=] [--loader=] [--limit=]
318
+
319
+ KUBEJS
320
+ kubejs index <scriptsDir> Index a kubejs/ scripts directory
321
+ kubejs search <scriptsDir> <query> Search indexed KubeJS scripts [--limit=]
322
+
323
+ MODPACKS.CH
324
+ modpacks search <query> Search modpacks [--namespace=ftb|curseforge] [--limit=20]
325
+ modpacks featured Featured packs [--limit=20]
326
+ modpacks info <packId> Pack metadata [--namespace=]
327
+ modpacks manifest <packId> <verId> Pack manifest [--namespace=]
328
+ modpacks list-versions Pack version list [--namespace=] [--pack-id=]
329
+ modpacks list-files Pack file list [--namespace=] [--pack-id=] [--version-id=] [--file-type=]
330
+ modpacks ftb-mod-info <modId> FTB mod info [--mc-version=] [--loader=]
331
+ modpacks find-mod Find a mod across packs [--mod-db-id=] [--cf-project=]
332
+
333
+ DIAGNOSTICS
334
+ crash-log <logPath> Analyze a crash log file (ranked suspect mods)
335
+ missing-deps Find declared deps not satisfied in DB [--mc-version=] [--loader=]
336
+ compat-check <jarPath> Quick mod compatibility check [--mc-version=] [--loader=]
337
+
338
+ FTS / INDEXED SEARCH (no Ollama required)
339
+ index-fts <dbId> Index decompiled mod source for BM25/FTS search
340
+ Works for all loaders: NeoForge, Fabric, Forge, Quilt
341
+ search-indexed <dbId> <query> BM25-ranked FTS search over indexed mod source [--limit=20]
342
+
343
+ SEMANTIC SEARCH (optional — requires Ollama)
344
+ backfill-embeddings Embed all docs/primers/mc-source for semantic search
345
+ [--type=docs|primers|source] [--version=<mc-version>]
346
+ (omit --type to run docs + primers; --type=source needs --version)
347
+
348
+ Environment:
349
+ DATABASE_URL PostgreSQL connection string (required)
350
+ OLLAMA_URL Ollama base URL for semantic search (optional, default http://localhost:11434)
351
+ OLLAMA_EMBED_MODEL Ollama embedding model (optional, default nomic-embed-text)
352
+ CURSEFORGE_API_KEY CurseForge API key (optional, needed for sync-curseforge)
353
+ `.trim();
354
+ // ── Commands ─────────────────────────────────────────────────────────────────
355
+ if (!command || command === "--help" || command === "-h") {
356
+ console.log(HELP);
357
+ process.exit(0);
358
+ }
359
+ const { flags, positional } = parseArgs(rest);
360
+ try {
361
+ switch (command) {
362
+ // ── Catalog ───────────────────────────────────────────────────────────
363
+ case "stats": {
364
+ out(await getDbStats());
365
+ break;
366
+ }
367
+ case "list": {
368
+ out(await listMods({
369
+ loader: flags.loader,
370
+ mcVersion: flags.mcVersion,
371
+ hasMixins: flags.hasMixins !== undefined ? !!(flags.hasMixins) : undefined,
372
+ decompiled: flags.decompiled !== undefined ? !!(flags.decompiled) : undefined,
373
+ limit: flags.limit ?? 50,
374
+ }));
375
+ break;
376
+ }
377
+ case "get": {
378
+ out(await getModDetails(modIdArg(positional[0], "modId")));
379
+ break;
380
+ }
381
+ case "search": {
382
+ out(await searchMods(requireArg(positional[0], "query"), {
383
+ loader: flags.loader,
384
+ mcVersion: flags.mcVersion,
385
+ limit: flags.limit ?? 20,
386
+ }));
387
+ break;
388
+ }
389
+ case "deps": {
390
+ out(await getDependencies(modIdArg(positional[0], "modId"), !!(flags.recursive)));
391
+ break;
392
+ }
393
+ // ── Ingest ────────────────────────────────────────────────────────────
394
+ case "ingest": {
395
+ const jarPath = requireArg(positional[0], "jarPath");
396
+ const result = await ingestMod(jarPath, !!(flags.skipSource));
397
+ out(result);
398
+ if (result.status === "ingested" && !flags.skipIndex) {
399
+ const mod = result.mod;
400
+ console.error("Indexing classes...");
401
+ out(await reindexClasses(mod.id));
402
+ }
403
+ break;
404
+ }
405
+ case "ingest-neoforge": {
406
+ const version = requireArg(positional[0], "version");
407
+ console.error(`Downloading NeoForge ${version}...`);
408
+ const jarPath = await downloadNeoForge(version);
409
+ const result = await ingestMod(jarPath, true);
410
+ out(result);
411
+ if (result.status === "ingested" && !flags.skipIndex) {
412
+ const mod = result.mod;
413
+ console.error("Indexing classes...");
414
+ out(await reindexClasses(mod.id));
415
+ }
416
+ break;
417
+ }
418
+ case "ingest-fabric-api": {
419
+ const version = requireArg(positional[0], "version");
420
+ console.error(`Downloading Fabric API ${version}...`);
421
+ const jarPath = await downloadFabricApi(version);
422
+ const result = await ingestMod(jarPath, true);
423
+ out(result);
424
+ if (result.status === "ingested" && !flags.skipIndex) {
425
+ const mod = result.mod;
426
+ console.error("Indexing classes...");
427
+ out(await reindexClasses(mod.id));
428
+ }
429
+ break;
430
+ }
431
+ case "ingest-forge": {
432
+ const version = requireArg(positional[0], "version");
433
+ console.error(`Downloading Forge ${version}...`);
434
+ const jarPath = await downloadForge(version, flags.mcVersion);
435
+ const result = await ingestMod(jarPath, true);
436
+ out(result);
437
+ if (result.status === "ingested" && !flags.skipIndex) {
438
+ const mod = result.mod;
439
+ console.error("Indexing classes...");
440
+ out(await reindexClasses(mod.id));
441
+ }
442
+ break;
443
+ }
444
+ case "batch-ingest": {
445
+ const dir = requireArg(positional[0], "directory");
446
+ const absDir = resolve(dir);
447
+ const entries = await readdir(absDir);
448
+ const jars = entries.filter((f) => f.endsWith(".jar")).sort();
449
+ console.log(`Found ${jars.length} JARs in ${absDir}\n`);
450
+ let ok = 0, skip = 0, fail = 0;
451
+ for (let i = 0; i < jars.length; i++) {
452
+ const jar = jars[i];
453
+ const jarPath = join(absDir, jar);
454
+ const prefix = `[${String(i + 1).padStart(3, " ")}/${jars.length}]`;
455
+ process.stdout.write(`${prefix} ${jar.padEnd(70)} `);
456
+ try {
457
+ const result = await ingestMod(jarPath, true);
458
+ if (result.status === "already_ingested" || result.status === "duplicate_version" || result.status === "duplicate_hash") {
459
+ console.log("SKIP");
460
+ skip++;
461
+ }
462
+ else {
463
+ const mod = result.mod;
464
+ console.log(`OK ${mod?.modId ?? "?"} (${mod?.loader ?? "?"} ${mod?.version ?? "?"})`);
465
+ ok++;
466
+ }
467
+ }
468
+ catch (e) {
469
+ console.log(`FAIL ${String(e instanceof Error ? e.message : e).slice(0, 80)}`);
470
+ fail++;
471
+ }
472
+ }
473
+ console.log(`\n✓ ingested: ${ok} skipped: ${skip} failed: ${fail}`);
474
+ if (flags.index) {
475
+ console.log("\nIndexing classes...");
476
+ const idx = await reindexClasses();
477
+ console.log(`✓ indexed: ${idx.indexed} already had classes: ${idx.skipped} failed: ${idx.failed}`);
478
+ }
479
+ break;
480
+ }
481
+ case "reindex": {
482
+ out(await reindexClasses(flags.dbId));
483
+ break;
484
+ }
485
+ // ── Source / decompile ────────────────────────────────────────────────
486
+ case "decompile": {
487
+ console.error("Decompiling (this may take a while)...");
488
+ out(await decompileMod(numArg(positional[0], "dbId")));
489
+ break;
490
+ }
491
+ case "decompile-class": {
492
+ out(await decompileModClass(numArg(positional[0], "dbId"), requireArg(positional[1], "className")));
493
+ break;
494
+ }
495
+ case "source": {
496
+ out(await getModSource(numArg(positional[0], "dbId"), positional[1]));
497
+ break;
498
+ }
499
+ case "search-source": {
500
+ out(await searchSource(requireArg(positional[0], "query"), flags.dbId, !!(flags.regex), flags.limit ?? 50));
501
+ break;
502
+ }
503
+ // ── Bytecode ──────────────────────────────────────────────────────────
504
+ case "search-class": {
505
+ const results = await searchModClass(numArg(positional[0], "dbId"), requireArg(positional[1], "query"));
506
+ out(results.length === 0 ? "No classes found." : results.join("\n"));
507
+ break;
508
+ }
509
+ case "members": {
510
+ out(await getModClassMembers(numArg(positional[0], "dbId"), requireArg(positional[1], "className")));
511
+ break;
512
+ }
513
+ case "bytecode": {
514
+ out(await getModClassBytecode(numArg(positional[0], "dbId"), requireArg(positional[1], "className")));
515
+ break;
516
+ }
517
+ case "refs": {
518
+ out(await findModReferences(numArg(positional[0], "dbId"), requireArg(positional[1], "target")));
519
+ break;
520
+ }
521
+ case "inheritance": {
522
+ out(await getModInheritance(numArg(positional[0], "dbId"), requireArg(positional[1], "className")));
523
+ break;
524
+ }
525
+ case "diff": {
526
+ out(await diffModVersions(numArg(positional[0], "dbIdA"), numArg(positional[1], "dbIdB")));
527
+ break;
528
+ }
529
+ // ── Mixins ────────────────────────────────────────────────────────────
530
+ case "mixin-targets": {
531
+ out(await getMixinTargets(modIdArg(positional[0], "modId")));
532
+ break;
533
+ }
534
+ case "resolve-mixins": {
535
+ out(await resolveMixinTargets(numArg(positional[0], "dbId")));
536
+ break;
537
+ }
538
+ case "mixin-conflicts": {
539
+ out(await getMixinConflicts(requireArg(positional[0], "targetClass")));
540
+ break;
541
+ }
542
+ case "at-entries": {
543
+ out(await getAtEntries(numArg(positional[0], "dbId")));
544
+ break;
545
+ }
546
+ case "aw-entries": {
547
+ out(await getAwEntries(numArg(positional[0], "dbId")));
548
+ break;
549
+ }
550
+ // ── Platform ──────────────────────────────────────────────────────────
551
+ case "sync-modrinth": {
552
+ out(await syncModrinth(numArg(positional[0], "dbId")));
553
+ break;
554
+ }
555
+ case "sync-curseforge": {
556
+ out(await syncCurseforge(numArg(positional[0], "dbId")));
557
+ break;
558
+ }
559
+ case "check-updates": {
560
+ out(await checkUpdates(numArg(positional[0], "dbId")));
561
+ break;
562
+ }
563
+ case "download-source": {
564
+ out(await downloadSource(numArg(positional[0], "dbId")));
565
+ break;
566
+ }
567
+ // ── Versions ──────────────────────────────────────────────────────────
568
+ case "mc-versions": {
569
+ out(await listMcVersions(flags.type ?? "release"));
570
+ break;
571
+ }
572
+ case "neoforge-versions": {
573
+ out(await listNeoForgeVersions(flags.mcVersion, flags.limit ?? 20));
574
+ break;
575
+ }
576
+ case "fabric-api-versions": {
577
+ out(await listFabricApiVersions(flags.mcVersion, flags.limit ?? 20));
578
+ break;
579
+ }
580
+ // ── Batch resolve mixins ───────────────────────────────────────────────
581
+ case "batch-resolve-mixins": {
582
+ const mods = await (await getDb()).mod.findMany({
583
+ where: { hasMixins: true },
584
+ select: { id: true, modId: true },
585
+ orderBy: { id: "asc" },
586
+ });
587
+ console.log(`Resolving mixin targets for ${mods.length} mods...\n`);
588
+ let ok = 0, none = 0, fail = 0;
589
+ for (const mod of mods) {
590
+ process.stdout.write(`[${String(mod.id).padStart(3, " ")}] ${mod.modId.padEnd(50)} `);
591
+ try {
592
+ const result = await resolveMixinTargets(mod.id);
593
+ if (result.targets.length === 0) {
594
+ console.log(`NONE (${result.skipped} skipped, ${result.failed} failed)`);
595
+ none++;
596
+ }
597
+ else {
598
+ console.log(`OK ${result.targets.length} targets (${result.resolved} resolved, ${result.failed} failed)`);
599
+ ok++;
600
+ }
601
+ }
602
+ catch (e) {
603
+ console.log(`FAIL ${String(e instanceof Error ? e.message : e).slice(0, 60)}`);
604
+ fail++;
605
+ }
606
+ }
607
+ console.log(`\n✓ resolved: ${ok} no targets found: ${none} failed: ${fail}`);
608
+ break;
609
+ }
610
+ case "index-fts": {
611
+ const dbId = numArg(positional[0], "dbId");
612
+ console.error(`Indexing mod source (FTS) for dbId=${dbId}...`);
613
+ out(await indexModSourceFts(dbId));
614
+ break;
615
+ }
616
+ case "search-indexed": {
617
+ const dbId = numArg(positional[0], "dbId");
618
+ const query = requireArg(positional[1], "query");
619
+ const limit = flags.limit ?? 20;
620
+ out(await searchModSourceIndexed(dbId, query, limit));
621
+ break;
622
+ }
623
+ // ── Mod: additional actions ───────────────────────────────────────────
624
+ case "dep-graph": {
625
+ out(await getDependencyGraph(flags.mcVersion));
626
+ break;
627
+ }
628
+ case "version-conflicts": {
629
+ out(await findVersionConflicts());
630
+ break;
631
+ }
632
+ case "source-urls": {
633
+ out(await listModSourceUrls(positional[0]));
634
+ break;
635
+ }
636
+ case "decompile-status": {
637
+ out(await decompileModStatus(numArg(positional[0], "dbId")));
638
+ break;
639
+ }
640
+ case "batch-decompile": {
641
+ const concurrency = flags.concurrency ?? 2;
642
+ const autoEmbed = flags["auto-embed"] === true ? true : flags["auto-embed"] === false ? false : undefined;
643
+ const autoGraph = flags["auto-graph"] === true ? true : flags["auto-graph"] === false ? false : undefined;
644
+ console.error(`Batch decompiling all un-decompiled mods (concurrency=${concurrency})...`);
645
+ out(await batchDecompileMods({ concurrency, autoEmbed, autoGraph }));
646
+ break;
647
+ }
648
+ case "get-paths": {
649
+ const mod = await findModById(numArg(positional[0], "dbId"));
650
+ if (!mod)
651
+ die(`Mod #${positional[0]} not found`);
652
+ out({ dbId: mod.id, modId: mod.modId, version: mod.version, jarPath: mod.jarPath, decompPath: mod.decompPath ?? null, cacheRoot: CACHE_ROOT });
653
+ break;
654
+ }
655
+ case "batch-sync": {
656
+ out(await batchSyncSources({
657
+ syncModrinth: flags.syncModrinth !== undefined ? !!(flags.syncModrinth) : undefined,
658
+ syncCurseforge: flags.syncCurseforge !== undefined ? !!(flags.syncCurseforge) : undefined,
659
+ downloadSources: !!(flags.downloadSources),
660
+ modIdFilter: flags.modIdFilter,
661
+ limit: flags.limit,
662
+ }));
663
+ break;
664
+ }
665
+ // ── Mod bytecode: advanced ────────────────────────────────────────────
666
+ case "cross-refs": {
667
+ out(await crossModRefs(requireArg(positional[0], "target"), flags.mcVersion, flags.loader, flags.limit));
668
+ break;
669
+ }
670
+ case "diff-detailed": {
671
+ const packages = flags.packages ? String(flags.packages).split(",") : undefined;
672
+ out(await diffModVersionsDetailed(numArg(positional[0], "dbIdA"), numArg(positional[1], "dbIdB"), packages, flags.limit ?? 200, !!(flags.semantic), flags.cache !== undefined ? !!(flags.cache) : !!(process.env.AUTO_CACHE_MOD_DIFFS), !!(flags.force)));
673
+ break;
674
+ }
675
+ case "find-implementors": {
676
+ out(await findImplementors(requireArg(positional[0], "target"), flags.modId, flags.limit, !!(flags.transitive)));
677
+ break;
678
+ }
679
+ case "scan-registrations": {
680
+ out(await scanModRegistrations(numArg(positional[0], "dbId")));
681
+ break;
682
+ }
683
+ case "annotated-by": {
684
+ out(await findAnnotatedClasses(requireArg(positional[0], "annotation"), flags.modId, flags.limit));
685
+ break;
686
+ }
687
+ case "event-listeners": {
688
+ out(await findEventListeners(requireArg(positional[0], "event"), flags.modId, flags.limit));
689
+ break;
690
+ }
691
+ case "optional-integrations": {
692
+ out(await findOptionalIntegrations(numArg(positional[0], "dbId")));
693
+ break;
694
+ }
695
+ case "network-payloads": {
696
+ out(await findNetworkPayloads(numArg(positional[0], "dbId")));
697
+ break;
698
+ }
699
+ case "config-schema": {
700
+ out(await extractConfigSchema(numArg(positional[0], "dbId")));
701
+ break;
702
+ }
703
+ // ── Mixin analysis: advanced ──────────────────────────────────────────
704
+ case "targets-in-package": {
705
+ out(await getMixinsTargetingPackage(requireArg(positional[0], "packagePrefix"), flags.mcVersion));
706
+ break;
707
+ }
708
+ case "at-conflicts": {
709
+ out(await findAtAwConflicts(flags.mcVersion, flags.loader));
710
+ break;
711
+ }
712
+ // ── Mixin scan ────────────────────────────────────────────────────────
713
+ case "mixin-scan": {
714
+ const sub = requireArg(positional[0], "mixin-scan action");
715
+ switch (sub) {
716
+ case "list":
717
+ out(await listModsWithMixins(flags.loader, flags.mcVersion));
718
+ break;
719
+ case "conflict-matrix":
720
+ out(await getMixinConflictMatrix(flags.loader, flags.mcVersion, flags.minConflicts));
721
+ break;
722
+ case "class-detail":
723
+ out(await getMixinClassDetail(requireArg(positional[1], "targetClass")));
724
+ break;
725
+ case "hotspots":
726
+ out(await getMixinHotspots(flags.top, flags.loader));
727
+ break;
728
+ case "batch-resolve":
729
+ out(await batchResolveMixins(flags.loader, flags.mcVersion));
730
+ break;
731
+ default:
732
+ die(`Unknown mixin-scan action: ${sub}. Use: list|conflict-matrix|class-detail|hotspots|batch-resolve`);
733
+ }
734
+ break;
735
+ }
736
+ // ── Vanilla MC source ─────────────────────────────────────────────────
737
+ case "mc-source": {
738
+ const sub = requireArg(positional[0], "mc-source action");
739
+ switch (sub) {
740
+ case "search-class":
741
+ out(await searchMinecraftClass(requireArg(positional[1], "version"), requireArg(positional[2], "query")));
742
+ break;
743
+ case "get-source":
744
+ out(await getMinecraftSource(requireArg(positional[1], "version"), requireArg(positional[2], "className"), flags.startLine, flags.endLine, flags.maxLines));
745
+ break;
746
+ case "bytecode":
747
+ out(await getMcClassBytecode(requireArg(positional[1], "version"), requireArg(positional[2], "className")));
748
+ break;
749
+ case "class-members":
750
+ out(await getMcClassMembers(requireArg(positional[1], "version"), requireArg(positional[2], "className")));
751
+ break;
752
+ case "find-refs":
753
+ out(await findMcReferences(requireArg(positional[1], "version"), requireArg(positional[2], "target")));
754
+ break;
755
+ case "inheritance":
756
+ out(await getMcInheritance(requireArg(positional[1], "version"), requireArg(positional[2], "className")));
757
+ break;
758
+ case "diff":
759
+ out(await diffMcVersions(requireArg(positional[1], "versionA"), requireArg(positional[2], "versionB")));
760
+ break;
761
+ case "diff-detailed": {
762
+ const pkgs = flags.packages ? String(flags.packages).split(",") : undefined;
763
+ out(await diffMcVersionsDetailed(requireArg(positional[1], "versionA"), requireArg(positional[2], "versionB"), pkgs, flags.limit ?? 200, !!(flags.force), !!(flags.semantic), flags.cache !== undefined ? !!(flags.cache) : true));
764
+ break;
765
+ }
766
+ case "decompile":
767
+ console.error("Decompiling MC (this may take a while)...");
768
+ out(await decompileMcVersion(requireArg(positional[1], "version"), !!(flags.force)));
769
+ break;
770
+ case "decompile-status":
771
+ out(await decompileMcVersionStatus(requireArg(positional[1], "version")));
772
+ break;
773
+ case "search-code":
774
+ out(await searchMcCode(requireArg(positional[1], "version"), requireArg(positional[2], "query"), flags.searchType ?? "content", !!(flags.regex), flags.limit ?? 50));
775
+ break;
776
+ case "index":
777
+ out(await indexMcVersion(requireArg(positional[1], "version"), !!(flags.force)));
778
+ break;
779
+ case "search-indexed":
780
+ out(await searchMcIndexed(requireArg(positional[2], "query"), requireArg(positional[1], "version"), flags.limit ?? 20));
781
+ break;
782
+ case "search-events":
783
+ out(await searchEvents(requireArg(positional[1], "version"), positional[2], flags.modloader));
784
+ break;
785
+ case "validate-aw": {
786
+ const awPath = requireArg(positional[2], "awFilePath");
787
+ const content = await readFile(awPath, "utf8");
788
+ out(await validateAccessWidener(content, requireArg(positional[1], "version")));
789
+ break;
790
+ }
791
+ case "analyze-mixin": {
792
+ const mixinPath = requireArg(positional[2], "mixinFilePath");
793
+ const source = await readFile(mixinPath, "utf8");
794
+ out(await analyzeMixin(source, requireArg(positional[1], "version")));
795
+ break;
796
+ }
797
+ case "search-semantic":
798
+ out(await searchMcSourceSemantic(requireArg(positional[2], "query"), requireArg(positional[1], "version"), flags.limit ?? 10));
799
+ break;
800
+ case "get-paths": {
801
+ const ver = requireArg(positional[1], "version");
802
+ out({ version: ver, jarPath: mcPaths.jar(ver), decompPath: mcPaths.decompiled(ver), indexPath: mcPaths.index(ver), cacheRoot: CACHE_ROOT });
803
+ break;
804
+ }
805
+ default:
806
+ die(`Unknown mc-source action: ${sub}. Run without args to see all commands.`);
807
+ }
808
+ break;
809
+ }
810
+ // ── Mappings ──────────────────────────────────────────────────────────
811
+ case "mappings": {
812
+ const sub = requireArg(positional[0], "mappings action");
813
+ switch (sub) {
814
+ case "find":
815
+ out(await findMapping(requireArg(positional[1], "symbol"), requireArg(positional[2], "version"), requireArg(positional[3], "sourceNs"), requireArg(positional[4], "targetNs")));
816
+ break;
817
+ case "remap":
818
+ out(await remapModJar(requireArg(positional[1], "inputJar"), requireArg(positional[2], "outputJar"), requireArg(positional[3], "version"), requireArg(positional[4], "toMapping")));
819
+ break;
820
+ case "parchment":
821
+ out(await getParchment(requireArg(positional[1], "className"), requireArg(positional[2], "mcVersion")));
822
+ break;
823
+ case "list-parchment":
824
+ out(await listParchmentVersions(requireArg(positional[1], "mcVersion")));
825
+ break;
826
+ case "parchment-summary":
827
+ out(await getParchmentSummary(requireArg(positional[1], "mcVersion")));
828
+ break;
829
+ default:
830
+ die(`Unknown mappings action: ${sub}. Use: find|remap|parchment|list-parchment|parchment-summary`);
831
+ }
832
+ break;
833
+ }
834
+ // ── Docs ──────────────────────────────────────────────────────────────
835
+ case "docs": {
836
+ const sub = requireArg(positional[0], "docs action");
837
+ switch (sub) {
838
+ case "seed":
839
+ out(await seedDefaultDocumentation());
840
+ break;
841
+ case "get":
842
+ out(await getDocumentation(requireArg(positional[1], "query")));
843
+ break;
844
+ case "search":
845
+ out(await searchDocumentation(requireArg(positional[1], "query"), flags.category, flags.namespace));
846
+ break;
847
+ case "list":
848
+ out(await listDocumentation(flags.category, flags.namespace, flags.tag, flags.limit ?? 100));
849
+ break;
850
+ case "delete":
851
+ out(await deleteDocumentation(numArg(positional[1], "id")));
852
+ break;
853
+ case "semantic-search":
854
+ out(await semanticSearchDocumentation(requireArg(positional[1], "query"), flags.limit ?? 10));
855
+ break;
856
+ default:
857
+ die(`Unknown docs action: ${sub}. Use: seed|get|search|list|delete|semantic-search`);
858
+ }
859
+ break;
860
+ }
861
+ // ── Primers ───────────────────────────────────────────────────────────
862
+ case "primers": {
863
+ const sub = requireArg(positional[0], "primers action");
864
+ switch (sub) {
865
+ case "seed":
866
+ out(await seedDefaultPrimers());
867
+ break;
868
+ case "get":
869
+ out(await getPrimer(numArg(positional[1], "id")));
870
+ break;
871
+ case "by-version":
872
+ out(await getPrimersByVersionRange(requireArg(positional[1], "fromVersion"), requireArg(positional[2], "toVersion"), flags.modloader));
873
+ break;
874
+ case "search":
875
+ out(await searchPrimers(requireArg(positional[1], "query"), flags.modloader, undefined, undefined, flags.limit));
876
+ break;
877
+ case "list":
878
+ out(await listPrimers(flags.modloader, flags.limit));
879
+ break;
880
+ case "delete":
881
+ out(await deletePrimer(numArg(positional[1], "id")));
882
+ break;
883
+ case "semantic-search":
884
+ out(await semanticSearchPrimers(requireArg(positional[1], "query"), flags.limit ?? 10));
885
+ break;
886
+ default:
887
+ die(`Unknown primers action: ${sub}. Use: seed|get|by-version|search|list|delete|semantic-search`);
888
+ }
889
+ break;
890
+ }
891
+ // ── MC Registry ───────────────────────────────────────────────────────
892
+ case "mc-registry": {
893
+ const sub = requireArg(positional[0], "mc-registry action");
894
+ const ver = flags.version;
895
+ switch (sub) {
896
+ case "blocks":
897
+ out(await getMcBlocks(ver));
898
+ break;
899
+ case "commands":
900
+ out(await getMcCommands(ver));
901
+ break;
902
+ case "registries":
903
+ out(await getMcRegistries(ver, flags.registry));
904
+ break;
905
+ case "sounds":
906
+ out(await getMcSounds(ver));
907
+ break;
908
+ case "item-components":
909
+ out(await getMcItemComponents(ver));
910
+ break;
911
+ case "registry-entries":
912
+ out(await getRegistryEntries(requireArg(positional[1] ?? String(flags.registry ?? ""), "registry"), ver));
913
+ break;
914
+ case "mcmeta-versions":
915
+ out(await getMcmetaVersions(flags.filter ?? "all"));
916
+ break;
917
+ default:
918
+ die(`Unknown mc-registry action: ${sub}. Use: blocks|commands|registries|sounds|item-components|registry-entries|mcmeta-versions`);
919
+ }
920
+ break;
921
+ }
922
+ // ── MC Data ───────────────────────────────────────────────────────────
923
+ case "mc-data": {
924
+ const sub = requireArg(positional[0], "mc-data action");
925
+ const ver = flags.version;
926
+ switch (sub) {
927
+ case "tags":
928
+ out(await getMcTags(ver, flags.registry, flags.tagId, flags.namespace));
929
+ break;
930
+ case "find-tags-for":
931
+ out(await findTagsForEntry(requireArg(positional[1], "entry"), requireArg(String(flags.registry ?? ""), "registry"), ver, flags.namespace));
932
+ break;
933
+ case "recipes":
934
+ out(await listRecipes(ver, flags.type, flags.outputItem));
935
+ break;
936
+ case "get-recipe":
937
+ out(await getRecipe(ver, requireArg(positional[1], "recipeId")));
938
+ break;
939
+ case "find-recipes-for":
940
+ out(await findRecipesForItem(requireArg(positional[1], "item"), ver));
941
+ break;
942
+ case "loot-tables":
943
+ out(await listLootTables(ver, flags.category));
944
+ break;
945
+ case "get-loot-table":
946
+ out(await getLootTable(ver, requireArg(positional[1], "path")));
947
+ break;
948
+ case "lang":
949
+ out(await getLangEntries(ver, flags.filter, flags.limit));
950
+ break;
951
+ case "blockstate":
952
+ out(await getBlockstate(ver, requireArg(positional[1], "block")));
953
+ break;
954
+ case "model":
955
+ out(await getMcModel(ver, requireArg(positional[1], "modelPath"), !!(flags.resolveParents)));
956
+ break;
957
+ case "model-tree":
958
+ out(await getModelTree(requireArg(positional[1], "modelPath"), ver));
959
+ break;
960
+ case "biomes":
961
+ out(await listBiomes(ver));
962
+ break;
963
+ case "get-biome":
964
+ out(await getBiome(ver, requireArg(positional[1], "biomeId")));
965
+ break;
966
+ case "damage-types":
967
+ out(await listDamageTypes(ver));
968
+ break;
969
+ case "enchantments":
970
+ out(await listEnchantments(ver));
971
+ break;
972
+ case "get-enchantment":
973
+ out(await getEnchantment(ver, requireArg(positional[1], "id")));
974
+ break;
975
+ case "advancements":
976
+ out(await listAdvancements(ver, flags.category));
977
+ break;
978
+ case "get-advancement":
979
+ out(await getAdvancement(ver, requireArg(positional[1], "id")));
980
+ break;
981
+ case "structures":
982
+ out(await listStructures(ver));
983
+ break;
984
+ case "get-structure":
985
+ out(await getStructureData(requireArg(positional[1], "id"), ver));
986
+ break;
987
+ case "particles":
988
+ out(await getMcParticles(ver));
989
+ break;
990
+ case "get-particle":
991
+ out(await getParticleData(requireArg(positional[1], "id"), ver));
992
+ break;
993
+ case "entity-attributes":
994
+ out(await getEntityAttributes(flags.entity, ver, flags.modId));
995
+ break;
996
+ default:
997
+ die(`Unknown mc-data action: ${sub}. Run without args to see all commands.`);
998
+ }
999
+ break;
1000
+ }
1001
+ // ── MC Files ──────────────────────────────────────────────────────────
1002
+ case "mc-files": {
1003
+ const sub = requireArg(positional[0], "mc-files action");
1004
+ const ver = flags.version;
1005
+ switch (sub) {
1006
+ case "get-data":
1007
+ out(await getMcDataFile(requireArg(positional[1], "filePath"), ver, !!(flags.jsonOnly)));
1008
+ break;
1009
+ case "get-asset":
1010
+ out(await getMcAssetFile(requireArg(positional[1], "filePath"), ver, !!(flags.jsonOnly)));
1011
+ break;
1012
+ case "list-files":
1013
+ out(await listMcDataFiles(requireArg(positional[1], "dirPath"), requireArg(ver ?? "", "version"), flags.branch));
1014
+ break;
1015
+ case "diff":
1016
+ out(await diffMcData(requireArg(positional[1], "filePath"), requireArg(String(flags.versionA ?? ""), "versionA"), requireArg(String(flags.versionB ?? ""), "versionB"), flags.branch ?? "data"));
1017
+ break;
1018
+ case "atlas":
1019
+ out(await getMcAtlas(ver, flags.atlas));
1020
+ break;
1021
+ case "raw":
1022
+ out(await getMcmetaRaw(requireArg(String(flags.ref ?? ""), "ref"), requireArg(positional[1], "filePath")));
1023
+ break;
1024
+ case "compare":
1025
+ out(await compareVersions(requireArg(String(flags.versionA ?? ""), "versionA"), requireArg(String(flags.versionB ?? ""), "versionB"), flags.branch));
1026
+ break;
1027
+ case "changelog":
1028
+ out(await getVersionChangelog(requireArg(ver ?? "", "version"), flags.branch));
1029
+ break;
1030
+ default:
1031
+ die(`Unknown mc-files action: ${sub}. Use: get-data|get-asset|list-files|diff|atlas|raw|compare|changelog`);
1032
+ }
1033
+ break;
1034
+ }
1035
+ // ── Mod JAR ───────────────────────────────────────────────────────────
1036
+ case "mod-jar": {
1037
+ const sub = requireArg(positional[0], "mod-jar action");
1038
+ const mid = modIdArg(positional[1], "modId");
1039
+ switch (sub) {
1040
+ case "list-files":
1041
+ out(await listModJarFiles(mid, flags.prefix));
1042
+ break;
1043
+ case "get-file":
1044
+ out(await getModJarFile(mid, requireArg(String(flags.path ?? positional[2] ?? ""), "path")));
1045
+ break;
1046
+ case "lang":
1047
+ out(await getModLang(mid, flags.filter, flags.limit));
1048
+ break;
1049
+ case "sounds":
1050
+ out(await getModSounds(mid, flags.namespace));
1051
+ break;
1052
+ case "atlas":
1053
+ out(await getModAtlas(mid, flags.atlas, flags.namespace));
1054
+ break;
1055
+ case "registry-entries":
1056
+ out(await listModRegistryEntries(mid, flags.type, flags.filter, flags.limit));
1057
+ break;
1058
+ case "manifest":
1059
+ out(await getModManifest(mid));
1060
+ break;
1061
+ case "list-configs":
1062
+ out(await listModConfigs(mid));
1063
+ break;
1064
+ case "get-config":
1065
+ out(await getModConfig(mid, requireArg(String(flags.path ?? positional[2] ?? ""), "path")));
1066
+ break;
1067
+ default:
1068
+ die(`Unknown mod-jar action: ${sub}. Use: list-files|get-file|lang|sounds|atlas|registry-entries|manifest|list-configs|get-config`);
1069
+ }
1070
+ break;
1071
+ }
1072
+ // ── Mod Data ──────────────────────────────────────────────────────────
1073
+ case "mod-data": {
1074
+ const sub = requireArg(positional[0], "mod-data action");
1075
+ switch (sub) {
1076
+ case "list": {
1077
+ const mid = modIdArg(positional[1], "modId");
1078
+ const type = requireArg(positional[2] ?? String(flags.type ?? ""), "type");
1079
+ if (type === "data_tag") {
1080
+ out(await listModDataTags(mid, flags.registry, flags.namespace, flags.filter));
1081
+ }
1082
+ else {
1083
+ out(await listModData(mid, type, { namespace: flags.namespace, filter: flags.filter }));
1084
+ }
1085
+ break;
1086
+ }
1087
+ case "get": {
1088
+ const mid = modIdArg(positional[1], "modId");
1089
+ const type = requireArg(positional[2] ?? String(flags.type ?? ""), "type");
1090
+ const id = requireArg(positional[3] ?? String(flags.id ?? ""), "id");
1091
+ if (type === "model") {
1092
+ out(await getModModelData(mid, flags.modelPath ?? id, flags.namespace));
1093
+ }
1094
+ else if (type === "data_tag") {
1095
+ out(await getModDataTag(mid, requireArg(String(flags.registry ?? ""), "registry"), id, flags.namespace));
1096
+ }
1097
+ else {
1098
+ out(await getModData(mid, type, id, { namespace: flags.namespace }));
1099
+ }
1100
+ break;
1101
+ }
1102
+ case "diff":
1103
+ out(await diffModData(numArg(positional[1], "dbIdA"), numArg(positional[2], "dbIdB"), flags.dataType));
1104
+ break;
1105
+ case "trace-item":
1106
+ out(await traceRecipeChain(requireArg(positional[1], "itemId"), flags.maxDepth));
1107
+ break;
1108
+ default:
1109
+ die(`Unknown mod-data action: ${sub}. Use: list|get|diff|trace-item`);
1110
+ }
1111
+ break;
1112
+ }
1113
+ // ── Mod Tags ──────────────────────────────────────────────────────────
1114
+ case "mod-tags": {
1115
+ const sub = requireArg(positional[0], "mod-tags action");
1116
+ switch (sub) {
1117
+ case "index":
1118
+ out(await indexModTags(modIdArg(positional[1], "modId")));
1119
+ break;
1120
+ case "index-all":
1121
+ out(await indexAllModTags());
1122
+ break;
1123
+ case "namespaces":
1124
+ out(await listTagNamespaces());
1125
+ break;
1126
+ case "contributors":
1127
+ out(await getTagContributors(requireArg(positional[1], "tagPath"), flags.registry));
1128
+ break;
1129
+ case "expand":
1130
+ out(await expandTag(requireArg(positional[1], "tagPath"), flags.registry, flags.maxDepth));
1131
+ break;
1132
+ case "mod-list":
1133
+ out(await getModTagList(modIdArg(positional[1], "modId"), flags.registry));
1134
+ break;
1135
+ case "find-conflicts":
1136
+ out(await findTagConflicts(flags.registry));
1137
+ break;
1138
+ case "search":
1139
+ out(await searchModTags(requireArg(positional[1], "query"), flags.registry, flags.limit));
1140
+ break;
1141
+ default:
1142
+ die(`Unknown mod-tags action: ${sub}. Use: index|index-all|namespaces|contributors|expand|mod-list|find-conflicts|search`);
1143
+ }
1144
+ break;
1145
+ }
1146
+ // ── Gradle ────────────────────────────────────────────────────────────
1147
+ case "gradle": {
1148
+ const sub = requireArg(positional[0], "gradle action");
1149
+ switch (sub) {
1150
+ case "get-files":
1151
+ out(await getModGradleFiles(modIdArg(positional[1], "modId")));
1152
+ break;
1153
+ case "search":
1154
+ out(await searchGradleFiles(requireArg(positional[1], "query"), flags.modIdFilter, flags.limit));
1155
+ break;
1156
+ case "compare-deps":
1157
+ out(await compareGradleDeps(flags.groupFilter, flags.modIdFilter));
1158
+ break;
1159
+ default:
1160
+ die(`Unknown gradle action: ${sub}. Use: get-files|search|compare-deps`);
1161
+ }
1162
+ break;
1163
+ }
1164
+ // ── Reports ───────────────────────────────────────────────────────────
1165
+ case "report": {
1166
+ const reportType = requireArg(positional[0], "report type");
1167
+ const dbIds = flags.dbIds ? String(flags.dbIds).split(",").map(Number) : undefined;
1168
+ const oldIds = flags.oldIds ? String(flags.oldIds).split(",").map(Number) : undefined;
1169
+ const newIds = flags.newIds ? String(flags.newIds).split(",").map(Number) : undefined;
1170
+ const result = await generateReport({
1171
+ report: reportType,
1172
+ savePath: flags.savePath,
1173
+ modId: flags.modId,
1174
+ loader: flags.loader,
1175
+ mcVersion: flags.mcVersion,
1176
+ registry: flags.registry,
1177
+ minConflicts: flags.minConflicts,
1178
+ groupFilter: flags.groupFilter,
1179
+ modIdFilter: flags.modIdFilter,
1180
+ dbIds, oldIds, newIds,
1181
+ });
1182
+ out(result.savedTo ? `Saved to: ${result.savedTo}\n\n${result.markdown}` : result.markdown);
1183
+ break;
1184
+ }
1185
+ // ── Pack Tools ────────────────────────────────────────────────────────
1186
+ case "pack-tools": {
1187
+ const sub = requireArg(positional[0], "pack-tools action");
1188
+ switch (sub) {
1189
+ case "asset-conflicts":
1190
+ out(await findAssetConflicts(flags.assetType, flags.mcVersion, flags.loader, flags.limit));
1191
+ break;
1192
+ case "vanilla-overrides":
1193
+ out(await findVanillaOverrides(flags.overrideType, flags.dataSubtype, flags.mcVersion, flags.loader));
1194
+ break;
1195
+ case "sidedness":
1196
+ out(await analyzeModSidedness(modIdArg(positional[1], "modId")));
1197
+ break;
1198
+ case "pack-sidedness":
1199
+ out(await analyzePackSidedness(flags.mcVersion, flags.loader));
1200
+ break;
1201
+ case "complexity":
1202
+ out(await computeModComplexity(flags.mcVersion, flags.loader));
1203
+ break;
1204
+ case "pack-changelog": {
1205
+ const oldI = flags.oldIds ? String(flags.oldIds).split(",").map(Number) : [];
1206
+ const newI = flags.newIds ? String(flags.newIds).split(",").map(Number) : [];
1207
+ out(await computePackChangelog(oldI, newI));
1208
+ break;
1209
+ }
1210
+ case "data-conflicts":
1211
+ out(await findDataConflicts(flags.dataType, flags.mcVersion, flags.loader, flags.limit));
1212
+ break;
1213
+ default:
1214
+ die(`Unknown pack-tools action: ${sub}. Use: asset-conflicts|vanilla-overrides|sidedness|pack-sidedness|complexity|pack-changelog|data-conflicts`);
1215
+ }
1216
+ break;
1217
+ }
1218
+ // ── KubeJS ────────────────────────────────────────────────────────────
1219
+ case "kubejs": {
1220
+ const sub = requireArg(positional[0], "kubejs action");
1221
+ const dir = requireArg(positional[1], "scriptsDir");
1222
+ switch (sub) {
1223
+ case "index":
1224
+ out(await indexKubeJsScripts(dir));
1225
+ break;
1226
+ case "search":
1227
+ out(await searchKubeJsScripts(dir, requireArg(positional[2], "query"), flags.limit));
1228
+ break;
1229
+ default: die(`Unknown kubejs action: ${sub}. Use: index|search`);
1230
+ }
1231
+ break;
1232
+ }
1233
+ // ── Modpacks.ch ───────────────────────────────────────────────────────
1234
+ case "modpacks": {
1235
+ const sub = requireArg(positional[0], "modpacks action");
1236
+ const ns = flags.namespace ?? "ftb";
1237
+ switch (sub) {
1238
+ case "search":
1239
+ out(await searchPacksAction(requireArg(positional[1], "query"), ns, flags.limit ?? 20));
1240
+ break;
1241
+ case "featured":
1242
+ out(await featuredPacksAction(flags.limit ?? 20));
1243
+ break;
1244
+ case "info":
1245
+ out(await packInfoAction(numArg(positional[1], "packId"), ns));
1246
+ break;
1247
+ case "manifest":
1248
+ out(await packManifestAction(numArg(positional[1], "packId"), numArg(positional[2], "versionId"), ns));
1249
+ break;
1250
+ case "list-versions":
1251
+ out(await listPackVersionsAction(flags.namespace, flags.packId));
1252
+ break;
1253
+ case "list-files":
1254
+ out(await listPackFilesAction({ namespace: flags.namespace, packId: flags.packId, versionId: flags.versionId, fileType: flags.fileType }));
1255
+ break;
1256
+ case "ftb-mod-info":
1257
+ out(await ftbModInfoAction(modIdArg(positional[1], "modId"), { mcVersion: flags.mcVersion, loader: flags.loader }));
1258
+ break;
1259
+ case "find-mod":
1260
+ out(await findModInPacksAction({ modDbId: flags.modDbId, cfProject: flags.cfProject }));
1261
+ break;
1262
+ default:
1263
+ die(`Unknown modpacks action: ${sub}. Use: search|featured|info|manifest|list-versions|list-files|ftb-mod-info|find-mod`);
1264
+ }
1265
+ break;
1266
+ }
1267
+ // ── Crash log ─────────────────────────────────────────────────────────
1268
+ case "crash-log": {
1269
+ const logPath = requireArg(positional[0], "logPath");
1270
+ const logText = await readFile(logPath, "utf8");
1271
+ out(await analyzeCrashLog(logText));
1272
+ break;
1273
+ }
1274
+ // ── Missing deps ──────────────────────────────────────────────────────
1275
+ case "missing-deps": {
1276
+ out(await findMissingDeps(flags.mcVersion, flags.loader));
1277
+ break;
1278
+ }
1279
+ // ── Compat check ──────────────────────────────────────────────────────
1280
+ case "compat-check": {
1281
+ out(await checkModCompat(requireArg(positional[0], "jarPath"), flags.mcVersion, flags.loader));
1282
+ break;
1283
+ }
1284
+ case "backfill-embeddings": {
1285
+ const type = flags.type;
1286
+ const version = flags.version;
1287
+ if (!type || type === "docs") {
1288
+ console.log("Embedding docs...");
1289
+ out(await backfillDocEmbeddings());
1290
+ }
1291
+ if (!type || type === "primers") {
1292
+ console.log("Embedding primers...");
1293
+ out(await backfillPrimerEmbeddings());
1294
+ }
1295
+ if (type === "source") {
1296
+ if (!version)
1297
+ die("--version=<mc-version> is required for --type=source");
1298
+ console.log(`Embedding MC source for ${version}...`);
1299
+ out(await indexMcSourceSemantic(version));
1300
+ }
1301
+ if (type === "mod") {
1302
+ const dbId = flags.dbId;
1303
+ if (!dbId)
1304
+ die("--db-id=<n> is required for --type=mod");
1305
+ const batchSize = flags.batchSize ?? 50;
1306
+ console.log(`Embedding mod source for dbId=${dbId} (batch=${batchSize})...`);
1307
+ out(await indexModSourceSemantic(dbId, batchSize));
1308
+ }
1309
+ break;
1310
+ }
1311
+ default:
1312
+ die(`Unknown command: ${command}\nRun without arguments to see all commands.`);
1313
+ }
1314
+ }
1315
+ finally {
1316
+ await disconnect();
1317
+ }
1318
+ //# sourceMappingURL=cli.js.map