@memlab/mcp-server 2.18.1 → 2.86.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 (374) hide show
  1. package/README.md +30 -16
  2. package/bin/.eslintrc.js +26 -0
  3. package/bin/memlab-cli.js +313 -0
  4. package/dist/anonymized-snapshot.d.ts +75 -0
  5. package/dist/anonymized-snapshot.d.ts.map +1 -0
  6. package/dist/anonymized-snapshot.js +101 -0
  7. package/dist/anonymized-snapshot.js.map +1 -0
  8. package/dist/artifact-classes.d.ts +86 -0
  9. package/dist/artifact-classes.d.ts.map +1 -0
  10. package/dist/artifact-classes.js +261 -0
  11. package/dist/artifact-classes.js.map +1 -0
  12. package/dist/capture-mode.d.ts +60 -0
  13. package/dist/capture-mode.d.ts.map +1 -0
  14. package/dist/capture-mode.js +39 -0
  15. package/dist/capture-mode.js.map +1 -0
  16. package/dist/eval-hints.d.ts +41 -0
  17. package/dist/eval-hints.d.ts.map +1 -0
  18. package/dist/eval-hints.js +115 -0
  19. package/dist/eval-hints.js.map +1 -0
  20. package/dist/guardrail.d.ts.map +1 -1
  21. package/dist/guardrail.js +13 -0
  22. package/dist/guardrail.js.map +1 -1
  23. package/dist/heap-budget.d.ts +32 -0
  24. package/dist/heap-budget.d.ts.map +1 -0
  25. package/dist/heap-budget.js +90 -0
  26. package/dist/heap-budget.js.map +1 -0
  27. package/dist/heap-shapes.d.ts +148 -0
  28. package/dist/heap-shapes.d.ts.map +1 -0
  29. package/dist/heap-shapes.js +193 -0
  30. package/dist/heap-shapes.js.map +1 -0
  31. package/dist/heap-state.d.ts +109 -2
  32. package/dist/heap-state.d.ts.map +1 -1
  33. package/dist/heap-state.js +194 -3
  34. package/dist/heap-state.js.map +1 -1
  35. package/dist/index.js +102 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/progress.d.ts +25 -0
  38. package/dist/progress.d.ts.map +1 -0
  39. package/dist/progress.js +46 -0
  40. package/dist/progress.js.map +1 -0
  41. package/dist/react-shapes.d.ts +42 -0
  42. package/dist/react-shapes.d.ts.map +1 -0
  43. package/dist/react-shapes.js +149 -0
  44. package/dist/react-shapes.js.map +1 -0
  45. package/dist/result-handles.d.ts +11 -0
  46. package/dist/result-handles.d.ts.map +1 -0
  47. package/dist/result-handles.js +77 -0
  48. package/dist/result-handles.js.map +1 -0
  49. package/dist/server-version.d.ts +19 -0
  50. package/dist/server-version.d.ts.map +1 -0
  51. package/dist/server-version.js +19 -0
  52. package/dist/server-version.js.map +1 -0
  53. package/dist/snapshot-borrow.d.ts +67 -0
  54. package/dist/snapshot-borrow.d.ts.map +1 -0
  55. package/dist/snapshot-borrow.js +113 -0
  56. package/dist/snapshot-borrow.js.map +1 -0
  57. package/dist/string-index.d.ts +55 -0
  58. package/dist/string-index.d.ts.map +1 -0
  59. package/dist/string-index.js +99 -0
  60. package/dist/string-index.js.map +1 -0
  61. package/dist/tool-registry.d.ts +42 -0
  62. package/dist/tool-registry.d.ts.map +1 -0
  63. package/dist/tool-registry.js +20 -0
  64. package/dist/tool-registry.js.map +1 -0
  65. package/dist/tools/analyze-run.d.ts +12 -0
  66. package/dist/tools/analyze-run.d.ts.map +1 -0
  67. package/dist/tools/analyze-run.js +404 -0
  68. package/dist/tools/analyze-run.js.map +1 -0
  69. package/dist/tools/anonymize-snapshot.d.ts +12 -0
  70. package/dist/tools/anonymize-snapshot.d.ts.map +1 -0
  71. package/dist/tools/anonymize-snapshot.js +159 -0
  72. package/dist/tools/anonymize-snapshot.js.map +1 -0
  73. package/dist/tools/app-config.d.ts +12 -0
  74. package/dist/tools/app-config.d.ts.map +1 -0
  75. package/dist/tools/app-config.js +217 -0
  76. package/dist/tools/app-config.js.map +1 -0
  77. package/dist/tools/app-heap.d.ts +30 -0
  78. package/dist/tools/app-heap.d.ts.map +1 -0
  79. package/dist/tools/app-heap.js +106 -0
  80. package/dist/tools/app-heap.js.map +1 -0
  81. package/dist/tools/artifact-budget.d.ts +12 -0
  82. package/dist/tools/artifact-budget.d.ts.map +1 -0
  83. package/dist/tools/artifact-budget.js +219 -0
  84. package/dist/tools/artifact-budget.js.map +1 -0
  85. package/dist/tools/async-census.d.ts +12 -0
  86. package/dist/tools/async-census.d.ts.map +1 -0
  87. package/dist/tools/async-census.js +243 -0
  88. package/dist/tools/async-census.js.map +1 -0
  89. package/dist/tools/auto-investigate.d.ts.map +1 -1
  90. package/dist/tools/auto-investigate.js +54 -5
  91. package/dist/tools/auto-investigate.js.map +1 -1
  92. package/dist/tools/batch.d.ts +12 -0
  93. package/dist/tools/batch.d.ts.map +1 -0
  94. package/dist/tools/batch.js +196 -0
  95. package/dist/tools/batch.js.map +1 -0
  96. package/dist/tools/cache-analysis.d.ts +15 -0
  97. package/dist/tools/cache-analysis.d.ts.map +1 -1
  98. package/dist/tools/cache-analysis.js +240 -14
  99. package/dist/tools/cache-analysis.js.map +1 -1
  100. package/dist/tools/census-diff.d.ts +55 -0
  101. package/dist/tools/census-diff.d.ts.map +1 -0
  102. package/dist/tools/census-diff.js +228 -0
  103. package/dist/tools/census-diff.js.map +1 -0
  104. package/dist/tools/chain-walk.d.ts +12 -0
  105. package/dist/tools/chain-walk.d.ts.map +1 -0
  106. package/dist/tools/chain-walk.js +184 -0
  107. package/dist/tools/chain-walk.js.map +1 -0
  108. package/dist/tools/class-histogram.d.ts.map +1 -1
  109. package/dist/tools/class-histogram.js +14 -3
  110. package/dist/tools/class-histogram.js.map +1 -1
  111. package/dist/tools/collection-diff.d.ts +44 -0
  112. package/dist/tools/collection-diff.d.ts.map +1 -0
  113. package/dist/tools/collection-diff.js +343 -0
  114. package/dist/tools/collection-diff.js.map +1 -0
  115. package/dist/tools/collection-trend.d.ts +55 -0
  116. package/dist/tools/collection-trend.d.ts.map +1 -0
  117. package/dist/tools/collection-trend.js +315 -0
  118. package/dist/tools/collection-trend.js.map +1 -0
  119. package/dist/tools/detached-dom.d.ts +5 -0
  120. package/dist/tools/detached-dom.d.ts.map +1 -1
  121. package/dist/tools/detached-dom.js +368 -22
  122. package/dist/tools/detached-dom.js.map +1 -1
  123. package/dist/tools/dev-artifacts.d.ts +62 -6
  124. package/dist/tools/dev-artifacts.d.ts.map +1 -1
  125. package/dist/tools/dev-artifacts.js +685 -24
  126. package/dist/tools/dev-artifacts.js.map +1 -1
  127. package/dist/tools/diff-snapshots.d.ts.map +1 -1
  128. package/dist/tools/diff-snapshots.js +18 -2
  129. package/dist/tools/diff-snapshots.js.map +1 -1
  130. package/dist/tools/dom-audit.d.ts +37 -0
  131. package/dist/tools/dom-audit.d.ts.map +1 -0
  132. package/dist/tools/dom-audit.js +247 -0
  133. package/dist/tools/dom-audit.js.map +1 -0
  134. package/dist/tools/dominator-attribution.d.ts +12 -0
  135. package/dist/tools/dominator-attribution.d.ts.map +1 -0
  136. package/dist/tools/dominator-attribution.js +189 -0
  137. package/dist/tools/dominator-attribution.js.map +1 -0
  138. package/dist/tools/dominator-chain.d.ts +12 -0
  139. package/dist/tools/dominator-chain.d.ts.map +1 -0
  140. package/dist/tools/dominator-chain.js +92 -0
  141. package/dist/tools/dominator-chain.js.map +1 -0
  142. package/dist/tools/duplicate-objects.d.ts +12 -0
  143. package/dist/tools/duplicate-objects.d.ts.map +1 -0
  144. package/dist/tools/duplicate-objects.js +172 -0
  145. package/dist/tools/duplicate-objects.js.map +1 -0
  146. package/dist/tools/duplicated-strings.d.ts.map +1 -1
  147. package/dist/tools/duplicated-strings.js +49 -40
  148. package/dist/tools/duplicated-strings.js.map +1 -1
  149. package/dist/tools/eval-across.d.ts +12 -0
  150. package/dist/tools/eval-across.d.ts.map +1 -0
  151. package/dist/tools/eval-across.js +135 -0
  152. package/dist/tools/eval-across.js.map +1 -0
  153. package/dist/tools/eval.d.ts +79 -0
  154. package/dist/tools/eval.d.ts.map +1 -1
  155. package/dist/tools/eval.js +2523 -197
  156. package/dist/tools/eval.js.map +1 -1
  157. package/dist/tools/event-listener-leaks.d.ts.map +1 -1
  158. package/dist/tools/event-listener-leaks.js +42 -17
  159. package/dist/tools/event-listener-leaks.js.map +1 -1
  160. package/dist/tools/event-registry.d.ts.map +1 -1
  161. package/dist/tools/event-registry.js +42 -8
  162. package/dist/tools/event-registry.js.map +1 -1
  163. package/dist/tools/explain-delta.d.ts +12 -0
  164. package/dist/tools/explain-delta.d.ts.map +1 -0
  165. package/dist/tools/explain-delta.js +221 -0
  166. package/dist/tools/explain-delta.js.map +1 -0
  167. package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
  168. package/dist/tools/find-nodes-by-class.js +112 -13
  169. package/dist/tools/find-nodes-by-class.js.map +1 -1
  170. package/dist/tools/finding-index.d.ts +203 -0
  171. package/dist/tools/finding-index.d.ts.map +1 -0
  172. package/dist/tools/finding-index.js +566 -0
  173. package/dist/tools/finding-index.js.map +1 -0
  174. package/dist/tools/for-each.d.ts.map +1 -1
  175. package/dist/tools/for-each.js +15 -3
  176. package/dist/tools/for-each.js.map +1 -1
  177. package/dist/tools/get-referrers.d.ts.map +1 -1
  178. package/dist/tools/get-referrers.js +17 -0
  179. package/dist/tools/get-referrers.js.map +1 -1
  180. package/dist/tools/get-value.d.ts +16 -0
  181. package/dist/tools/get-value.d.ts.map +1 -1
  182. package/dist/tools/get-value.js +96 -2
  183. package/dist/tools/get-value.js.map +1 -1
  184. package/dist/tools/hunt-report.d.ts +12 -0
  185. package/dist/tools/hunt-report.d.ts.map +1 -0
  186. package/dist/tools/hunt-report.js +186 -0
  187. package/dist/tools/hunt-report.js.map +1 -0
  188. package/dist/tools/hypothesis.d.ts +12 -0
  189. package/dist/tools/hypothesis.d.ts.map +1 -0
  190. package/dist/tools/hypothesis.js +280 -0
  191. package/dist/tools/hypothesis.js.map +1 -0
  192. package/dist/tools/id-space-audit.d.ts +12 -0
  193. package/dist/tools/id-space-audit.d.ts.map +1 -0
  194. package/dist/tools/id-space-audit.js +262 -0
  195. package/dist/tools/id-space-audit.js.map +1 -0
  196. package/dist/tools/identify.d.ts +12 -0
  197. package/dist/tools/identify.d.ts.map +1 -0
  198. package/dist/tools/identify.js +205 -0
  199. package/dist/tools/identify.js.map +1 -0
  200. package/dist/tools/identity-diff.d.ts +12 -0
  201. package/dist/tools/identity-diff.d.ts.map +1 -0
  202. package/dist/tools/identity-diff.js +188 -0
  203. package/dist/tools/identity-diff.js.map +1 -0
  204. package/dist/tools/intern-opportunities.d.ts.map +1 -1
  205. package/dist/tools/intern-opportunities.js +116 -50
  206. package/dist/tools/intern-opportunities.js.map +1 -1
  207. package/dist/tools/ladder-probe.d.ts +65 -0
  208. package/dist/tools/ladder-probe.d.ts.map +1 -0
  209. package/dist/tools/ladder-probe.js +445 -0
  210. package/dist/tools/ladder-probe.js.map +1 -0
  211. package/dist/tools/ladder.d.ts +33 -0
  212. package/dist/tools/ladder.d.ts.map +1 -0
  213. package/dist/tools/ladder.js +266 -0
  214. package/dist/tools/ladder.js.map +1 -0
  215. package/dist/tools/largest-objects.d.ts.map +1 -1
  216. package/dist/tools/largest-objects.js +6 -2
  217. package/dist/tools/largest-objects.js.map +1 -1
  218. package/dist/tools/leak-report.d.ts +35 -0
  219. package/dist/tools/leak-report.d.ts.map +1 -0
  220. package/dist/tools/leak-report.js +398 -0
  221. package/dist/tools/leak-report.js.map +1 -0
  222. package/dist/tools/load-snapshot.d.ts +29 -0
  223. package/dist/tools/load-snapshot.d.ts.map +1 -1
  224. package/dist/tools/load-snapshot.js +294 -23
  225. package/dist/tools/load-snapshot.js.map +1 -1
  226. package/dist/tools/map-entries.d.ts +12 -0
  227. package/dist/tools/map-entries.d.ts.map +1 -0
  228. package/dist/tools/map-entries.js +139 -0
  229. package/dist/tools/map-entries.js.map +1 -0
  230. package/dist/tools/match-object.d.ts +12 -0
  231. package/dist/tools/match-object.d.ts.map +1 -0
  232. package/dist/tools/match-object.js +165 -0
  233. package/dist/tools/match-object.js.map +1 -0
  234. package/dist/tools/metric.d.ts +13 -0
  235. package/dist/tools/metric.d.ts.map +1 -0
  236. package/dist/tools/metric.js +185 -0
  237. package/dist/tools/metric.js.map +1 -0
  238. package/dist/tools/module-attribution.d.ts +36 -0
  239. package/dist/tools/module-attribution.d.ts.map +1 -0
  240. package/dist/tools/module-attribution.js +235 -0
  241. package/dist/tools/module-attribution.js.map +1 -0
  242. package/dist/tools/next-measurement.d.ts +26 -0
  243. package/dist/tools/next-measurement.d.ts.map +1 -0
  244. package/dist/tools/next-measurement.js +149 -0
  245. package/dist/tools/next-measurement.js.map +1 -0
  246. package/dist/tools/object-cost-breakdown.d.ts.map +1 -1
  247. package/dist/tools/object-cost-breakdown.js +64 -0
  248. package/dist/tools/object-cost-breakdown.js.map +1 -1
  249. package/dist/tools/object-shape.d.ts.map +1 -1
  250. package/dist/tools/object-shape.js +53 -5
  251. package/dist/tools/object-shape.js.map +1 -1
  252. package/dist/tools/population-diff.d.ts +57 -0
  253. package/dist/tools/population-diff.d.ts.map +1 -0
  254. package/dist/tools/population-diff.js +338 -0
  255. package/dist/tools/population-diff.js.map +1 -0
  256. package/dist/tools/population-vs-owners.d.ts +12 -0
  257. package/dist/tools/population-vs-owners.d.ts.map +1 -0
  258. package/dist/tools/population-vs-owners.js +183 -0
  259. package/dist/tools/population-vs-owners.js.map +1 -0
  260. package/dist/tools/property-names.d.ts +29 -0
  261. package/dist/tools/property-names.d.ts.map +1 -0
  262. package/dist/tools/property-names.js +131 -0
  263. package/dist/tools/property-names.js.map +1 -0
  264. package/dist/tools/quick-diagnosis.d.ts.map +1 -1
  265. package/dist/tools/quick-diagnosis.js +7 -1
  266. package/dist/tools/quick-diagnosis.js.map +1 -1
  267. package/dist/tools/react-owners.d.ts +12 -0
  268. package/dist/tools/react-owners.d.ts.map +1 -0
  269. package/dist/tools/react-owners.js +167 -0
  270. package/dist/tools/react-owners.js.map +1 -0
  271. package/dist/tools/react-update-queues.d.ts +12 -0
  272. package/dist/tools/react-update-queues.d.ts.map +1 -0
  273. package/dist/tools/react-update-queues.js +173 -0
  274. package/dist/tools/react-update-queues.js.map +1 -0
  275. package/dist/tools/replicate.d.ts +49 -0
  276. package/dist/tools/replicate.d.ts.map +1 -0
  277. package/dist/tools/replicate.js +241 -0
  278. package/dist/tools/replicate.js.map +1 -0
  279. package/dist/tools/retainer-diff.d.ts +12 -0
  280. package/dist/tools/retainer-diff.d.ts.map +1 -0
  281. package/dist/tools/retainer-diff.js +168 -0
  282. package/dist/tools/retainer-diff.js.map +1 -0
  283. package/dist/tools/retainer-layers.d.ts +23 -0
  284. package/dist/tools/retainer-layers.d.ts.map +1 -0
  285. package/dist/tools/retainer-layers.js +179 -0
  286. package/dist/tools/retainer-layers.js.map +1 -0
  287. package/dist/tools/retainer-summary.d.ts +18 -0
  288. package/dist/tools/retainer-summary.d.ts.map +1 -1
  289. package/dist/tools/retainer-summary.js +210 -51
  290. package/dist/tools/retainer-summary.js.map +1 -1
  291. package/dist/tools/retainer-trace.d.ts.map +1 -1
  292. package/dist/tools/retainer-trace.js +14 -2
  293. package/dist/tools/retainer-trace.js.map +1 -1
  294. package/dist/tools/round-audit.d.ts +66 -0
  295. package/dist/tools/round-audit.d.ts.map +1 -0
  296. package/dist/tools/round-audit.js +258 -0
  297. package/dist/tools/round-audit.js.map +1 -0
  298. package/dist/tools/round-digest.d.ts +12 -0
  299. package/dist/tools/round-digest.d.ts.map +1 -0
  300. package/dist/tools/round-digest.js +190 -0
  301. package/dist/tools/round-digest.js.map +1 -0
  302. package/dist/tools/script-census.d.ts +12 -0
  303. package/dist/tools/script-census.d.ts.map +1 -0
  304. package/dist/tools/script-census.js +182 -0
  305. package/dist/tools/script-census.js.map +1 -0
  306. package/dist/tools/search-nodes.d.ts.map +1 -1
  307. package/dist/tools/search-nodes.js +5 -1
  308. package/dist/tools/search-nodes.js.map +1 -1
  309. package/dist/tools/search-strings.d.ts.map +1 -1
  310. package/dist/tools/search-strings.js +53 -7
  311. package/dist/tools/search-strings.js.map +1 -1
  312. package/dist/tools/sequence-analysis.d.ts +53 -0
  313. package/dist/tools/sequence-analysis.d.ts.map +1 -1
  314. package/dist/tools/sequence-analysis.js +313 -89
  315. package/dist/tools/sequence-analysis.js.map +1 -1
  316. package/dist/tools/server-status.d.ts.map +1 -1
  317. package/dist/tools/server-status.js +4 -1
  318. package/dist/tools/server-status.js.map +1 -1
  319. package/dist/tools/settle-check.d.ts +12 -0
  320. package/dist/tools/settle-check.d.ts.map +1 -0
  321. package/dist/tools/settle-check.js +188 -0
  322. package/dist/tools/settle-check.js.map +1 -0
  323. package/dist/tools/shape-histogram.d.ts.map +1 -1
  324. package/dist/tools/shape-histogram.js +9 -2
  325. package/dist/tools/shape-histogram.js.map +1 -1
  326. package/dist/tools/sliced-strings.d.ts.map +1 -1
  327. package/dist/tools/sliced-strings.js +2 -1
  328. package/dist/tools/sliced-strings.js.map +1 -1
  329. package/dist/tools/snapshots.d.ts.map +1 -1
  330. package/dist/tools/snapshots.js +24 -6
  331. package/dist/tools/snapshots.js.map +1 -1
  332. package/dist/tools/sparse-elements.d.ts +12 -0
  333. package/dist/tools/sparse-elements.d.ts.map +1 -0
  334. package/dist/tools/sparse-elements.js +215 -0
  335. package/dist/tools/sparse-elements.js.map +1 -0
  336. package/dist/tools/stale-collections.d.ts +17 -0
  337. package/dist/tools/stale-collections.d.ts.map +1 -1
  338. package/dist/tools/stale-collections.js +28 -0
  339. package/dist/tools/stale-collections.js.map +1 -1
  340. package/dist/tools/string-patterns.d.ts.map +1 -1
  341. package/dist/tools/string-patterns.js +7 -5
  342. package/dist/tools/string-patterns.js.map +1 -1
  343. package/dist/tools/tools-index.d.ts +12 -0
  344. package/dist/tools/tools-index.d.ts.map +1 -0
  345. package/dist/tools/tools-index.js +492 -0
  346. package/dist/tools/tools-index.js.map +1 -0
  347. package/dist/tools/trace-all.d.ts +42 -0
  348. package/dist/tools/trace-all.d.ts.map +1 -0
  349. package/dist/tools/trace-all.js +263 -0
  350. package/dist/tools/trace-all.js.map +1 -0
  351. package/dist/tools/unit-cost.d.ts +12 -0
  352. package/dist/tools/unit-cost.d.ts.map +1 -0
  353. package/dist/tools/unit-cost.js +219 -0
  354. package/dist/tools/unit-cost.js.map +1 -0
  355. package/dist/tools/verify-fix.d.ts +23 -0
  356. package/dist/tools/verify-fix.d.ts.map +1 -0
  357. package/dist/tools/verify-fix.js +219 -0
  358. package/dist/tools/verify-fix.js.map +1 -0
  359. package/dist/tools/weakmap-entries.d.ts.map +1 -1
  360. package/dist/tools/weakmap-entries.js +6 -1
  361. package/dist/tools/weakmap-entries.js.map +1 -1
  362. package/dist/tools/weakref-census.d.ts +15 -0
  363. package/dist/tools/weakref-census.d.ts.map +1 -0
  364. package/dist/tools/weakref-census.js +147 -0
  365. package/dist/tools/weakref-census.js.map +1 -0
  366. package/dist/tools/what-if.d.ts +12 -0
  367. package/dist/tools/what-if.d.ts.map +1 -0
  368. package/dist/tools/what-if.js +285 -0
  369. package/dist/tools/what-if.js.map +1 -0
  370. package/dist/utils.d.ts +238 -3
  371. package/dist/utils.d.ts.map +1 -1
  372. package/dist/utils.js +507 -15
  373. package/dist/utils.js.map +1 -1
  374. package/package.json +7 -6
@@ -0,0 +1,343 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @oncall memory_lab
9
+ */
10
+ import fs from 'fs';
11
+ import memlabCore from '@memlab/core';
12
+ import { z } from 'zod';
13
+ import { errorResult, formatNumber, markdownTable, pathsHeader, toolResult, } from '../utils.js';
14
+ import { countEntries } from './collection-trend.js';
15
+ import { resolveLadderPaths } from './ladder.js';
16
+ import { resolveMaxFileSizeMB, resolveSnapshotPath } from './load-snapshot.js';
17
+ const { utils: memlabUtils } = memlabCore;
18
+ /**
19
+ * Class names that carry no information as an owner label. A signature built on
20
+ * one of these is not distinguishable from thousands of others, so the walk
21
+ * keeps climbing to find something nameable.
22
+ */
23
+ const GENERIC_OWNER_NAMES = new Set([
24
+ '',
25
+ 'Object',
26
+ 'Array',
27
+ 'Map',
28
+ 'Set',
29
+ 'WeakMap',
30
+ 'WeakSet',
31
+ '(object elements)',
32
+ '(object properties)',
33
+ ]);
34
+ /** JS-level collections a caller can actually act on. */
35
+ const COLLECTION_CLASS_NAMES = new Set([
36
+ 'Map',
37
+ 'Set',
38
+ 'WeakMap',
39
+ 'WeakSet',
40
+ 'Array',
41
+ ]);
42
+ const MAX_OWNER_HOPS = 4;
43
+ function isGenericOwner(name) {
44
+ if (GENERIC_OWNER_NAMES.has(name))
45
+ return true;
46
+ // `system / Context / scope @805823` — the scope id is per-capture, so the
47
+ // name is both generic AND unstable. Collapsed to `<context>` below.
48
+ if (name.startsWith('system / Context'))
49
+ return true;
50
+ if (name.startsWith('system /'))
51
+ return true;
52
+ return false;
53
+ }
54
+ function edgeLabel(edge) {
55
+ const raw = String(edge.name_or_index);
56
+ if (raw === '' || /^\d+$/.test(raw))
57
+ return null;
58
+ if (raw === '__proto__' || raw === 'map' || raw === 'elements')
59
+ return null;
60
+ return raw;
61
+ }
62
+ /**
63
+ * A per-capture-stable name for one collection, in the SAME `<Owner>.<property>`
64
+ * form `memlab_collection_trend` takes as a locator.
65
+ *
66
+ * That shared shape is the point of this tool: discovery hands you a locator you
67
+ * can paste straight into the trend tool to confirm and to track a fix, instead
68
+ * of a node id that means nothing in the next capture.
69
+ *
70
+ * Node ids, array indices and V8 scope numbers are all per-capture, so none of
71
+ * them can appear in the signature. The walk climbs referrers (not the dominator
72
+ * tree — this runs on a LIGHT parse with no dominators) until it finds a class
73
+ * name worth printing, and falls back to `<context>` for a module-scope closure
74
+ * binding, which is where most module singletons live.
75
+ */
76
+ export function collectionSignature(node) {
77
+ let binding = null;
78
+ let owner = null;
79
+ // Prefer a `property` binding, then a closure `context` binding; both name the
80
+ // field the collection is stored in, which is what a reader needs.
81
+ for (const pass of ['property', 'context', 'any']) {
82
+ for (const edge of node.referrers) {
83
+ if (pass !== 'any' && edge.type !== pass)
84
+ continue;
85
+ if (edge.type === 'hidden' || edge.type === 'internal')
86
+ continue;
87
+ const label = edgeLabel(edge);
88
+ if (label == null)
89
+ continue;
90
+ const from = edge.fromNode;
91
+ if (from == null || from.id <= 3)
92
+ continue;
93
+ binding = label;
94
+ owner = from;
95
+ break;
96
+ }
97
+ if (binding != null)
98
+ break;
99
+ }
100
+ if (binding == null || owner == null)
101
+ return null;
102
+ // Climb until the owner has a name worth printing.
103
+ let hops = 0;
104
+ const prefixParts = [];
105
+ let cur = owner;
106
+ while (cur != null && hops < MAX_OWNER_HOPS && isGenericOwner(cur.name)) {
107
+ let next = null;
108
+ let nextLabel = null;
109
+ for (const edge of cur.referrers) {
110
+ if (edge.type === 'hidden' || edge.type === 'internal')
111
+ continue;
112
+ const label = edgeLabel(edge);
113
+ if (label == null)
114
+ continue;
115
+ const from = edge.fromNode ?? null;
116
+ if (from == null || from.id <= 3)
117
+ continue;
118
+ next = from;
119
+ nextLabel = label;
120
+ break;
121
+ }
122
+ if (next == null)
123
+ break;
124
+ if (nextLabel != null)
125
+ prefixParts.unshift(nextLabel);
126
+ cur = next;
127
+ hops++;
128
+ }
129
+ let ownerLabel;
130
+ if (cur == null) {
131
+ ownerLabel = 'Object';
132
+ }
133
+ else if (cur.name.startsWith('system / Context')) {
134
+ ownerLabel = '<context>';
135
+ }
136
+ else if (isGenericOwner(cur.name)) {
137
+ ownerLabel = cur.name.length > 0 ? cur.name : 'Object';
138
+ }
139
+ else {
140
+ ownerLabel = cur.name;
141
+ }
142
+ return [ownerLabel, ...prefixParts, binding].join('.');
143
+ }
144
+ /**
145
+ * Census every JS collection in one snapshot, keyed by signature.
146
+ *
147
+ * Deliberately does NOT filter by size. The whole point is to catch the
148
+ * collection that is small now and unbounded later: one of the three
149
+ * never-drained telemetry stores this tool was written for held 2 entries at the
150
+ * baseline rung and 1,260 at the last one, so any size floor would have hidden
151
+ * it. Growth is the filter, and growth needs the ladder.
152
+ */
153
+ export function censusCollections(snapshot) {
154
+ const out = new Map();
155
+ snapshot.nodes.forEach((node) => {
156
+ if (node.id <= 3)
157
+ return;
158
+ if (!COLLECTION_CLASS_NAMES.has(node.name))
159
+ return;
160
+ const n = countEntries(node);
161
+ if (n == null || n === 0)
162
+ return;
163
+ const sig = collectionSignature(node);
164
+ if (sig == null)
165
+ return;
166
+ let s = out.get(sig);
167
+ if (!s) {
168
+ s = { instances: 0, entries: 0, maxEntries: 0, kinds: new Set() };
169
+ out.set(sig, s);
170
+ }
171
+ s.instances++;
172
+ s.entries += n;
173
+ if (n > s.maxEntries)
174
+ s.maxEntries = n;
175
+ s.kinds.add(node.name);
176
+ });
177
+ return out;
178
+ }
179
+ function buildRows(perRung, minGrowth) {
180
+ const sigs = new Set();
181
+ for (const m of perRung)
182
+ for (const k of m.keys())
183
+ sigs.add(k);
184
+ const rows = [];
185
+ for (const sig of sigs) {
186
+ const series = perRung.map(m => m.get(sig)?.entries ?? 0);
187
+ const instances = perRung.map(m => m.get(sig)?.instances ?? 0);
188
+ const delta = series[series.length - 1] - series[0];
189
+ if (delta < minGrowth)
190
+ continue;
191
+ let monotonic = true;
192
+ for (let i = 1; i < series.length; i++) {
193
+ if (series[i] <= series[i - 1])
194
+ monotonic = false;
195
+ }
196
+ const kinds = new Set();
197
+ for (const m of perRung) {
198
+ const s = m.get(sig);
199
+ if (s)
200
+ for (const k of s.kinds)
201
+ kinds.add(k);
202
+ }
203
+ rows.push({
204
+ sig,
205
+ kind: [...kinds].sort().join('/'),
206
+ series,
207
+ instances,
208
+ maxEntries: Math.max(...perRung.map(m => m.get(sig)?.maxEntries ?? 0)),
209
+ delta,
210
+ monotonic,
211
+ });
212
+ }
213
+ rows.sort((a, b) => {
214
+ if (a.monotonic !== b.monotonic)
215
+ return a.monotonic ? -1 : 1;
216
+ return b.delta - a.delta;
217
+ });
218
+ return rows;
219
+ }
220
+ export function registerCollectionDiff(server) {
221
+ server.tool('memlab_collection_diff', 'Find WHICH collections grew across a snapshot ladder, WITHOUT being told their names. Censuses every Map/Set/WeakMap/WeakSet/Array on every rung, keys each by a per-capture-STABLE `<Owner>.<property>` signature, and diffs the entry counts. ' +
222
+ 'This is the discovery half of memlab_collection_trend, which is excellent but requires a locator you must already know — so every accumulating collection had to be found first by hand-tracing a retainer path, and the ones nobody thought to trace were never found at all. ' +
223
+ 'It is also the answer to the case the single-snapshot tools structurally cannot see: memlab_cache_analysis and memlab_growth_signals rank by SIZE on one rung, so they surface big-and-static collections and miss the small-but-unbounded one. This tool applies NO size floor — growth is the filter — because the store that matters most may hold 2 entries at the baseline. ' +
224
+ 'The signatures it emits are valid memlab_collection_trend locators: confirm a candidate, and later verify a fix, by pasting one straight in. ' +
225
+ 'Loads each rung transiently in LIGHT mode (one graph resident at a time), so it is safe on ladders too large to hold in memory at once.', {
226
+ paths: z
227
+ .array(z.string())
228
+ .min(1)
229
+ .describe('Ordered snapshot paths, OLDEST FIRST (>=2). A single ["ladder:<name>"] element expands to a saved ladder (see memlab_ladder).'),
230
+ cycles: z
231
+ .number()
232
+ .optional()
233
+ .describe('Interaction cycles driven between the FIRST and LAST rung. When given, a Δ/cycle column is reported — the per-cycle rate is what says whether a collection scales with interaction.'),
234
+ min_growth: z
235
+ .number()
236
+ .optional()
237
+ .default(20)
238
+ .describe('Only report collections whose total entry count grew by at least this across the ladder (default 20). This is a GROWTH floor, not a size floor — a collection that went 2 -> 1,260 is reported, one that sits flat at 9,356 is not.'),
239
+ limit: z
240
+ .number()
241
+ .optional()
242
+ .default(30)
243
+ .describe('Maximum number of collections to report (default 30).'),
244
+ monotonic_only: z
245
+ .boolean()
246
+ .optional()
247
+ .default(false)
248
+ .describe('Only report collections that grew at EVERY rung (default false: grew-net collections are included and flagged).'),
249
+ max_file_size_mb: z
250
+ .number()
251
+ .optional()
252
+ .describe('Per-file size limit override (MB).'),
253
+ }, async ({ paths, cycles, min_growth, limit, monotonic_only, max_file_size_mb, }) => {
254
+ try {
255
+ const { paths: resolved } = resolveLadderPaths(paths);
256
+ if (resolved.length < 2) {
257
+ return errorResult('memlab_collection_diff needs at least 2 snapshots — it diffs collection sizes across a ladder. For a single snapshot use memlab_cache_analysis or memlab_growth_signals.');
258
+ }
259
+ const labels = [];
260
+ const perRung = [];
261
+ for (const p of resolved) {
262
+ let local;
263
+ let fetchedFrom = null;
264
+ try {
265
+ const r = resolveSnapshotPath(p);
266
+ local = r.localPath;
267
+ fetchedFrom = r.fetchedFrom;
268
+ }
269
+ catch (e) {
270
+ return errorResult(`Failed to resolve "${p}": ${e instanceof Error ? e.message : String(e)}`);
271
+ }
272
+ if (!fs.existsSync(local)) {
273
+ return errorResult(`File not found: ${local}`);
274
+ }
275
+ const sizeMB = fs.statSync(local).size / (1024 * 1024);
276
+ const cap = resolveMaxFileSizeMB(max_file_size_mb, fetchedFrom != null);
277
+ if (sizeMB > cap) {
278
+ return errorResult(`${p} is ${sizeMB.toFixed(0)} MB — exceeds the ${cap} MB per-file safety limit. Raise it with max_file_size_mb: ${Math.ceil(sizeMB + 100)}.`);
279
+ }
280
+ const snapshot = await memlabUtils.getSnapshotFromFile(local, {
281
+ buildNodeIdIndex: true,
282
+ verbose: false,
283
+ });
284
+ labels.push(fetchedFrom ?? p.replace(/^.*\//, ''));
285
+ perRung.push(censusCollections(snapshot));
286
+ }
287
+ let rows = buildRows(perRung, min_growth);
288
+ if (monotonic_only)
289
+ rows = rows.filter(r => r.monotonic);
290
+ const shown = rows.slice(0, limit);
291
+ const perCycle = cycles != null && cycles > 0;
292
+ const lines = [
293
+ `## Collection diff across ${resolved.length} rung(s)`,
294
+ '',
295
+ ];
296
+ if (shown.length === 0) {
297
+ lines.push(`No collection grew by ${formatNumber(min_growth)} or more entries across this ladder.`, '', '_That is a real negative for unbounded-collection growth specifically — it does not cover detached DOM, listener records, string accumulation or retained-size growth with a flat entry count. Lower `min_growth` to see smaller movers._');
298
+ return toolResult(lines.join('\n'), pathsHeader(labels));
299
+ }
300
+ const headers = [
301
+ 'Collection (usable as a collection_trend locator)',
302
+ 'Kind',
303
+ ...labels.map((_, i) => `r${i}`),
304
+ 'Δ',
305
+ ...(perCycle ? ['Δ/cycle'] : []),
306
+ 'Instances',
307
+ 'Largest',
308
+ 'Trend',
309
+ ];
310
+ const right = new Set();
311
+ for (let i = 2; i < headers.length - 1; i++)
312
+ right.add(i);
313
+ const table = shown.map(r => [
314
+ r.sig.length > 52 ? r.sig.slice(0, 49) + '…' : r.sig,
315
+ r.kind,
316
+ ...r.series.map(v => formatNumber(v)),
317
+ `+${formatNumber(r.delta)}`,
318
+ ...(perCycle ? [(r.delta / cycles).toFixed(2)] : []),
319
+ `${formatNumber(r.instances[0])} → ${formatNumber(r.instances[r.instances.length - 1])}`,
320
+ formatNumber(r.maxEntries),
321
+ r.monotonic ? '↑ every rung' : 'grew net',
322
+ ]);
323
+ lines.push(markdownTable(headers, table, right));
324
+ const mono = shown.filter(r => r.monotonic);
325
+ lines.push('', `**${formatNumber(mono.length)} of ${formatNumber(shown.length)} shown grew at EVERY rung** — monotonic growth under a repeated interaction is the signature of an unbounded collection.` +
326
+ (rows.length > shown.length
327
+ ? ` ${formatNumber(rows.length - shown.length)} more above the growth floor were not shown (raise \`limit\`).`
328
+ : ''));
329
+ if (mono.length > 0) {
330
+ lines.push('', '**Next:** confirm one with the trend tool, which measures the same collection per rung and reports owners separately from entries:', '```', `memlab_collection_trend({paths: [...], locators: [${mono
331
+ .slice(0, 4)
332
+ .map(r => `"${r.sig}"`)
333
+ .join(', ')}]${perCycle ? `, cycles: ${cycles}` : ''}})`, '```', 'Then `memlab_retainer_trace` the owner to name what holds it, and check whether the entries are distinct rather than one object re-added.');
334
+ }
335
+ lines.push('', '_Instances is the count of DISTINCT collections sharing a signature. When instances grow but the largest single collection does not, the OWNERS are accumulating, not the collection — a different fix (stop minting owners) from bounding one container._', '_Signatures are structural, not identities: two unrelated collections bound to the same-named field of the same-named class share a row. The `Instances` column is what exposes that._');
336
+ return toolResult(lines.join('\n'), pathsHeader(labels));
337
+ }
338
+ catch (error) {
339
+ return errorResult(`Failed to diff collections: ${error instanceof Error ? error.message : String(error)}`);
340
+ }
341
+ });
342
+ }
343
+ //# sourceMappingURL=collection-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-diff.js","sourceRoot":"","sources":["../../src/tools/collection-diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @format
8
+ * @oncall memory_lab
9
+ */
10
+ import type { IHeapNode, IHeapSnapshot } from '@memlab/core';
11
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
12
+ /**
13
+ * A locator names a collection by the OWNER CLASS and the property path that
14
+ * reaches it — `LoggerImpl.logs`, `Store.cache.entries`.
15
+ *
16
+ * Deliberately not a node id: ids are per-capture, so an id-keyed ladder query
17
+ * silently tracks a different object (or nothing) at every rung, which is the
18
+ * failure this tool exists to remove. Matching by class + path is what makes a
19
+ * collection comparable across snapshots at all.
20
+ */
21
+ export interface Locator {
22
+ ownerClass: string;
23
+ path: string[];
24
+ raw: string;
25
+ }
26
+ export declare function parseLocator(spec: string): Locator;
27
+ export declare function resolvePath(owner: IHeapNode, path: string[]): IHeapNode | null;
28
+ /**
29
+ * Number of entries held by a collection node, by V8 kind.
30
+ *
31
+ * Returns null when the node is not a container — reported as "not a
32
+ * collection" rather than as 0 entries, because those two read identically in a
33
+ * table and mean opposite things (an empty cache vs a mistyped locator).
34
+ */
35
+ export declare function countEntries(node: IHeapNode): number | null;
36
+ export interface LocatorMeasurement {
37
+ owners: number;
38
+ resolved: number;
39
+ entries: number;
40
+ maxEntries: number;
41
+ nonCollection: boolean;
42
+ }
43
+ export declare function measureLocators(snapshot: IHeapSnapshot, locators: Locator[]): Map<string, LocatorMeasurement>;
44
+ /**
45
+ * Load each rung, measure the locators, drop the graph. Uses the LIGHT parse:
46
+ * entry counts come from backing-store edges, so the dominator/retained-size
47
+ * pass this tool would otherwise pay for on every rung buys nothing (measured
48
+ * on a 380 MB capture: 18s → 8s per rung).
49
+ */
50
+ export declare function measureLadder(paths: string[], locators: Locator[], maxFileSizeMB?: number): Promise<{
51
+ labels: string[];
52
+ perRung: Map<string, LocatorMeasurement>[];
53
+ }>;
54
+ export declare function registerCollectionTrend(server: McpServer): void;
55
+ //# sourceMappingURL=collection-trend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-trend.d.ts","sourceRoot":"","sources":["../../src/tools/collection-trend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAE,aAAa,EAAC,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAkBvE;;;;;;;;GAQG;AACH,MAAM,WAAW,OAAO;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWlD;AAmBD,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,MAAM,EAAE,GACb,SAAS,GAAG,IAAI,CAOlB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAyC3D;AAED,MAAM,WAAW,kBAAkB;IAEjC,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC;IAGhB,UAAU,EAAE,MAAM,CAAC;IAEnB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,OAAO,EAAE,GAClB,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAsCjC;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,OAAO,EAAE,EACnB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,EAAE,CAAA;CAAC,CAAC,CA+BzE;AAeD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiK/D"}