@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,398 @@
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 { z } from 'zod';
11
+ import memlabHeapAnalysis from '@memlab/heap-analysis';
12
+ const { getFullHeapFromFile } = memlabHeapAnalysis;
13
+ import { errorResult, formatBytes, formatNumber, markdownTable, pathsHeader, toolResult, } from '../utils.js';
14
+ import { artifactLabel } from '../artifact-classes.js';
15
+ import { computeSequenceTrends, normalizeClassName, } from './sequence-analysis.js';
16
+ import { collectDevRoots, computeReachableWithoutDevRoots, } from './dev-artifacts.js';
17
+ import { getFirstNonFrameworkRetainer } from './detached-dom.js';
18
+ import { makeProgressReporter } from '../progress.js';
19
+ // Nodes kept per candidate class for the retainer sample. Small on purpose: the
20
+ // question is "what shape of thing holds these", and a handful of instances
21
+ // answers it — walking thousands would cost more than the trend pass itself.
22
+ const MAX_SAMPLES_PER_CLASS = 8;
23
+ const RETAINER_SAMPLES = 3;
24
+ // A class whose instances are overwhelmingly dev-root-retained is a measurement
25
+ // artifact in production terms, whatever its growth curve looks like. Matches
26
+ // the majority-not-any threshold intern_opportunities uses, for the same reason:
27
+ // a class can legitimately mix a few console-held instances with real data.
28
+ const DEV_ONLY_SHARE = 0.8;
29
+ // Deliberately NOT a sum of retainedSize across the class: retained sizes
30
+ // overlap wherever instances nest, so summing them reports figures larger than
31
+ // the heap (measured: 5.9 GB of `Object` in a 200 MB heap). Net self-size delta
32
+ // across the ladder is additive and is the growth the report is about anyway.
33
+ function displayName(row) {
34
+ return row.name.length > 0 ? row.name : `(unnamed ${row.type})`;
35
+ }
36
+ /**
37
+ * `displayName` for PROSE, where a class name is interpolated into a sentence.
38
+ *
39
+ * The table truncates its own cells; the suggestion trailers did not, and for a
40
+ * string-typed row the "class name" IS the string's content. A single measured
41
+ * `**Next:**` line carried a whole multi-line `Error: [ProxyState] …` value
42
+ * including three full bundle URLs with query strings — several hundred tokens
43
+ * of payload inside a line whose only job is to name the next tool to run. The
44
+ * newline collapse matters as much as the length cap: an embedded newline also
45
+ * breaks out of the markdown bullet it was sitting in.
46
+ */
47
+ const PROSE_NAME_MAX = 80;
48
+ function proseName(row) {
49
+ const flat = displayName(row).replace(/\s+/g, ' ').trim();
50
+ return flat.length > PROSE_NAME_MAX
51
+ ? `${flat.slice(0, PROSE_NAME_MAX - 1)}…`
52
+ : flat;
53
+ }
54
+ function modalRetainer(nodes) {
55
+ const counts = new Map();
56
+ let considered = 0;
57
+ for (const node of nodes.slice(0, RETAINER_SAMPLES)) {
58
+ considered++;
59
+ const label = getFirstNonFrameworkRetainer(node);
60
+ counts.set(label, (counts.get(label) ?? 0) + 1);
61
+ }
62
+ let best = '(unknown)';
63
+ let bestCount = 0;
64
+ for (const [label, c] of counts) {
65
+ if (c > bestCount) {
66
+ best = label;
67
+ bestCount = c;
68
+ }
69
+ }
70
+ return { label: best, votes: bestCount, of: considered };
71
+ }
72
+ /**
73
+ * The retainer to report for a GROWING class.
74
+ *
75
+ * This used to vote over instances sampled from the class's whole final
76
+ * population, which answers the wrong question: it reports whoever holds the
77
+ * MOST instances, not whoever holds the NEW ones. Those differ exactly when a
78
+ * large static collection coexists with a small accumulating one — which is the
79
+ * common case, and the case the report exists to diagnose.
80
+ *
81
+ * Measured failure this fixes: across three separate rounds the `Set` class was
82
+ * growing by ~2,000 instances and the column named `CometStyleXSheet
83
+ * .externalRules`, a collection that a per-rung trend pass shows is FLAT at
84
+ * 9,356 entries at every rung. It contributed none of the growth; it was simply
85
+ * the largest static Set population in the heap, so it won every vote. A reader
86
+ * who trusts the column chases a collection that is not moving.
87
+ *
88
+ * The growth cohort is approximated by node id: V8 assigns heap-snapshot ids
89
+ * monotonically as objects are allocated, so the highest-id instances of a class
90
+ * are its newest. That is a heuristic — ids are not a timestamp and a class can
91
+ * churn — so when the two cohorts disagree the report says so rather than
92
+ * silently preferring one.
93
+ */
94
+ function growthRetainer(ev) {
95
+ const growth = modalRetainer(ev.newest);
96
+ const population = modalRetainer(ev.samples);
97
+ return {
98
+ ...growth,
99
+ populationLabel: growth.label !== population.label && population.label !== '(unknown)'
100
+ ? population.label
101
+ : null,
102
+ };
103
+ }
104
+ /**
105
+ * Ratios that land on a whole number, and what they mean.
106
+ *
107
+ * Turning a delta into a mechanism is usually one division. The breakthrough on
108
+ * one investigation was noticing that a population grew by 19 rows per cycle on
109
+ * an account with exactly 19 chats: the leaked unit was one whole chat list, so
110
+ * the cost scaled with the USER'S data rather than with elapsed time — a
111
+ * different severity and a different fix from "grows over time". That division
112
+ * was done by eye, and only because someone happened to know the chat count.
113
+ *
114
+ * `tolerance` is an ABSOLUTE distance from the nearest integer, and has to be:
115
+ * scaling it by the ratio makes every large ratio trivially "integer", which is
116
+ * the difference between a signal and noise dressed as one. Measured against a
117
+ * real 3-rung ladder with a 2%-of-ratio tolerance, EVERY candidate row reported
118
+ * a clean whole number — `16,825 / 50 = 336.5` was announced as "337 per cycle"
119
+ * because 0.5 is comfortably inside 2% of 337. With an absolute 0.02 the same
120
+ * row is correctly rejected and only a ratio that really does land on an
121
+ * integer survives.
122
+ */
123
+ export function integerRatios(netCount, content, tolerance = 0.02) {
124
+ const out = [];
125
+ for (const [key, count] of Object.entries(content)) {
126
+ if (!Number.isFinite(count) || count <= 0)
127
+ continue;
128
+ const ratio = netCount / count;
129
+ if (ratio < 1)
130
+ continue;
131
+ const nearest = Math.round(ratio);
132
+ if (nearest >= 1 && Math.abs(ratio - nearest) <= tolerance) {
133
+ out.push({ key, per: nearest });
134
+ }
135
+ }
136
+ return out;
137
+ }
138
+ export function registerLeakReport(server) {
139
+ server.tool('memlab_leak_report', 'One-call leak triage across an ORDERED ladder of >=2 heap snapshots: runs the growth-trend pass, then gathers per-class EVIDENCE from the final snapshot and returns a single table — class, per-rung counts, Δ and Δ/cycle, how much of it is dev/automation-retained, the dominant retainer, and a verdict hint. ' +
140
+ 'Exists because the trend pass alone cannot tell a leak from an artifact: every hunt then ran memlab_dev_artifacts and a retainer trace by hand on each grower and joined the three outputs mentally, which is the step that gets skipped right before something is reported as a production leak. Composes memlab_sequence_analysis with memlab_dev_artifacts and a retainer sample; costs one extra snapshot load (the last rung) on top of the ladder pass. ' +
141
+ 'The verdict column is a HINT, not a conclusion — confirm a candidate with memlab_retainer_trace on the example node before calling it a leak. ' +
142
+ "The retainer column votes over the class's NEWEST instances (highest node ids = the growth cohort), NOT over its whole population: voting over the population names whoever holds the most instances, which is a large STATIC collection whenever one exists and is not what grew. Rows where the two disagree are listed under the table. Paths may be local, manifold:// URLs, or bare filenames.", {
143
+ paths: z
144
+ .array(z.string())
145
+ .min(1)
146
+ .describe('Ordered list of >=2 snapshot paths (oldest first): local absolute paths, manifold:// URLs, or bare snapshot filenames. A single ["ladder:<name>"] entry expands to a ladder saved with memlab_ladder.'),
147
+ cycles: z
148
+ .number()
149
+ .optional()
150
+ .describe('Number of interaction cycles driven between the FIRST and LAST snapshot. When provided, a "Δ/cycle" column is reported — a per-cycle rate is what says whether growth scales with interaction, which a total cannot.'),
151
+ content: z
152
+ .record(z.number())
153
+ .optional()
154
+ .describe('Counts of the CONTENT the driven surface contains — e.g. {"chats": 19, "messages": 40}. When given, each grower\'s net delta is also divided by these, and any ratio landing on a whole number is called out. This is what turns a number into a mechanism: a class growing by exactly one unit per chat is leaking a whole chat list per cycle, and scales with the user\'s data rather than with time.'),
155
+ limit: z
156
+ .number()
157
+ .optional()
158
+ .default(10)
159
+ .describe('Maximum number of growing classes to gather evidence for (default 10).'),
160
+ min_growth_count: z
161
+ .number()
162
+ .optional()
163
+ .default(50)
164
+ .describe('Only consider classes whose net instance-count growth is at least this (default 50).'),
165
+ monotonic_only: z
166
+ .boolean()
167
+ .optional()
168
+ .default(false)
169
+ .describe('Only consider classes that grew at EVERY step (default false: grew-net classes are included and flagged as noisy).'),
170
+ include_artifacts: z
171
+ .boolean()
172
+ .optional()
173
+ .default(false)
174
+ .describe('Include classes that are known measurement artifacts (CDP inspector retention, V8 JIT warmup, Blink a11y caches, captured Error stacks). Default false: they are counted in a one-line summary instead of consuming evidence slots, since none of them is an app leak.'),
175
+ max_file_size_mb: z
176
+ .number()
177
+ .optional()
178
+ .describe('Per-file size ceiling in MB, matching memlab_load_snapshot / memlab_sequence_analysis defaults. Snapshots are loaded one at a time and dropped before the next.'),
179
+ }, async ({ paths, cycles, content, limit, min_growth_count, monotonic_only, include_artifacts, max_file_size_mb, }, extra) => {
180
+ try {
181
+ const { steps, rows } = await computeSequenceTrends(paths, {
182
+ minGrowthCount: min_growth_count,
183
+ monotonicOnly: monotonic_only,
184
+ maxFileSizeMB: max_file_size_mb,
185
+ toolName: 'memlab_leak_report',
186
+ progress: makeProgressReporter(extra, 'leak_report'),
187
+ });
188
+ const n = steps.length;
189
+ const artifactRows = rows.filter(r => r.artifact != null);
190
+ const candidates = (include_artifacts ? rows : rows.filter(r => r.artifact == null)).slice(0, limit);
191
+ const heapNet = steps[n - 1].totalSize - steps[0].totalSize;
192
+ const lines = [
193
+ `## Leak report (${n} snapshots)`,
194
+ '',
195
+ `Heap self-size ${heapNet >= 0 ? 'grew' : 'shrank'} by ${formatBytes(Math.abs(heapNet))} across the ladder (${formatNumber(steps[0].nodeCount)} → ${formatNumber(steps[n - 1].nodeCount)} nodes).`,
196
+ '',
197
+ ];
198
+ if (n === 2) {
199
+ lines.push('> ⚠️ **Only 2 snapshots: "↑ every step" is monotonic by construction** and cannot separate a real trend from a single GC-band sample. Capture at least a third rung before treating anything here as a leak.', '');
200
+ }
201
+ if (candidates.length === 0) {
202
+ lines.push(`No non-artifact class grew by >= ${formatNumber(min_growth_count)} instances across the ladder — no unbounded-growth signal to report.`);
203
+ if (artifactRows.length > 0) {
204
+ lines.push('', `> 🧹 ${formatNumber(artifactRows.length)} growing class(es) were known measurement artifacts (pass \`include_artifacts: true\` to see them).`);
205
+ }
206
+ return toolResult(lines.join('\n'), pathsHeader(steps.map(s => s.label)));
207
+ }
208
+ // Evidence pass. The trend loop drops each graph before loading the
209
+ // next, so the final rung is re-opened here — one extra load, and the
210
+ // only way to ask retention questions about the classes the trend pass
211
+ // just identified.
212
+ const snapshot = await getFullHeapFromFile(steps[n - 1].localPath);
213
+ const devRoots = collectDevRoots(snapshot);
214
+ const reached = devRoots.byId.size > 0
215
+ ? computeReachableWithoutDevRoots(snapshot, devRoots)
216
+ : null;
217
+ const evidence = new Map();
218
+ for (const c of candidates) {
219
+ evidence.set(c.key, {
220
+ total: 0,
221
+ devOnly: 0,
222
+ samples: [],
223
+ newest: [],
224
+ example: null,
225
+ exampleRetained: -1,
226
+ anyExample: null,
227
+ });
228
+ }
229
+ snapshot.nodes.forEach(node => {
230
+ if (node.id <= 3)
231
+ return;
232
+ // Must key exactly as buildHistogram does, normalization included, or
233
+ // per-instance Context/scope classes never match their trend row.
234
+ const ev = evidence.get(`${node.type}::${normalizeClassName(node.name)}`);
235
+ if (!ev)
236
+ return;
237
+ ev.total++;
238
+ if (reached != null && reached[node.nodeIndex] === 0)
239
+ ev.devOnly++;
240
+ if (ev.anyExample == null)
241
+ ev.anyExample = node;
242
+ if (!node.hasPathEdge)
243
+ return;
244
+ if (ev.samples.length < MAX_SAMPLES_PER_CLASS)
245
+ ev.samples.push(node);
246
+ // Keep the highest-id traceable instances — the class's newest, i.e.
247
+ // the cohort the ladder's growth is made of. Insertion into a window
248
+ // this small (8) is cheaper than sorting the class at the end.
249
+ if (ev.newest.length < MAX_SAMPLES_PER_CLASS ||
250
+ node.id > ev.newest[ev.newest.length - 1].id) {
251
+ let i = ev.newest.length;
252
+ while (i > 0 && ev.newest[i - 1].id < node.id)
253
+ i--;
254
+ ev.newest.splice(i, 0, node);
255
+ if (ev.newest.length > MAX_SAMPLES_PER_CLASS)
256
+ ev.newest.pop();
257
+ }
258
+ if (node.retainedSize > ev.exampleRetained) {
259
+ ev.exampleRetained = node.retainedSize;
260
+ ev.example = node;
261
+ }
262
+ });
263
+ // The biggest traceable instance is the most informative one to walk, so
264
+ // put it at the head of every retainer sample.
265
+ for (const ev of evidence.values()) {
266
+ if (ev.example != null) {
267
+ ev.samples = [
268
+ ev.example,
269
+ ...ev.samples.filter(s => s.id !== ev.example.id),
270
+ ];
271
+ }
272
+ }
273
+ const perCycle = cycles != null && cycles > 0;
274
+ const showDevOnly = reached != null;
275
+ const headers = [
276
+ 'Class',
277
+ 'Type',
278
+ ...steps.map((_, i) => `#${i + 1}`),
279
+ 'Δ count',
280
+ ...(perCycle ? ['Δ/cycle'] : []),
281
+ 'Δ size',
282
+ ...(showDevOnly ? ['Dev-only'] : []),
283
+ 'Top retainer (newest instances)',
284
+ 'Verdict hint',
285
+ ];
286
+ const rightCols = new Set();
287
+ for (let i = 2; i < headers.length - 2; i++)
288
+ rightCols.add(i);
289
+ let leakCandidates = 0;
290
+ let devOnlyClasses = 0;
291
+ // Rows where the newest instances and the population at large are held
292
+ // by different things. That disagreement is the signal a static
293
+ // collection is masking the accumulating one, so it is reported rather
294
+ // than resolved silently.
295
+ const retainerSplits = [];
296
+ const tableRows = candidates.map(r => {
297
+ const ev = evidence.get(r.key);
298
+ const devShare = ev.total > 0 ? ev.devOnly / ev.total : 0;
299
+ const isDevOnly = showDevOnly && devShare >= DEV_ONLY_SHARE;
300
+ if (isDevOnly)
301
+ devOnlyClasses++;
302
+ let verdict;
303
+ if (r.artifact != null) {
304
+ verdict = artifactLabel(r.artifact);
305
+ }
306
+ else if (isDevOnly) {
307
+ verdict = '🛠 dev/automation-retained (not production)';
308
+ }
309
+ else if (r.trend === 'monotonic-up') {
310
+ verdict = '↑ every step — LEAK candidate';
311
+ leakCandidates++;
312
+ }
313
+ else {
314
+ verdict = 'grew net (noisy)';
315
+ }
316
+ const label = displayName(r);
317
+ return [
318
+ label.length > 34 ? label.slice(0, 31) + '…' : label,
319
+ r.type,
320
+ ...r.counts.map(c => formatNumber(c)),
321
+ `+${formatNumber(r.netCount)}`,
322
+ ...(perCycle ? [(r.netCount / cycles).toFixed(2)] : []),
323
+ `${r.netSize >= 0 ? '+' : ''}${formatBytes(r.netSize)}`,
324
+ ...(showDevOnly
325
+ ? [
326
+ ev.total === 0
327
+ ? '—'
328
+ : ev.devOnly === 0
329
+ ? '—'
330
+ : `${(devShare * 100).toFixed(0)}%`,
331
+ ]
332
+ : []),
333
+ (() => {
334
+ const g = growthRetainer(ev);
335
+ if (g.populationLabel != null) {
336
+ retainerSplits.push(`\`${label}\`: newest → \`${g.label}\`, population at large → \`${g.populationLabel}\``);
337
+ }
338
+ const shown = g.of > 1 ? `${g.label} (${g.votes}/${g.of})` : g.label;
339
+ return shown.length > 44 ? shown.slice(0, 41) + '…' : shown;
340
+ })(),
341
+ verdict,
342
+ ];
343
+ });
344
+ lines.push(markdownTable(headers, tableRows, rightCols));
345
+ if (content != null && Object.keys(content).length > 0) {
346
+ const hits = [];
347
+ for (const r of candidates) {
348
+ if (r.artifact != null)
349
+ continue;
350
+ for (const { key, per } of integerRatios(r.netCount, content)) {
351
+ hits.push(`- \`${proseName(r)}\` grew by **${formatNumber(per)} per ${key}** ` +
352
+ `(${formatNumber(r.netCount)} / ${formatNumber(content[key])}).`);
353
+ }
354
+ }
355
+ if (hits.length > 0) {
356
+ lines.push('', '### Growth that lands on a whole number per unit of content', '', ...hits, '', '_A clean integer ratio names the leaked UNIT, which a total cannot. It also changes the severity: ' +
357
+ 'a population that scales with the content the user already has grows with their data, not merely ' +
358
+ 'with how long they keep the tab open. Confirm by re-driving against an account with a different ' +
359
+ 'content count — the ratio should hold and the absolute number should not._');
360
+ }
361
+ }
362
+ lines.push('', '_"Top retainer" votes over the class\'s NEWEST instances (highest node ids — V8 allocates ids monotonically, so those are the growth cohort), not over its whole population. ' +
363
+ 'Voting over the population reports whoever holds the MOST instances, which is a large static collection whenever one exists, and is not what grew. ' +
364
+ 'It is a small sample of a heuristic cohort — confirm with `memlab_collection_trend` on the named collection before acting, since a retainer that is itself flat across the ladder contributed none of the growth._');
365
+ if (retainerSplits.length > 0) {
366
+ lines.push('', `⚠ **${retainerSplits.length} class(es) where the newest instances and the bulk population have DIFFERENT retainers.** ` +
367
+ 'That is the signature of a static collection sitting alongside an accumulating one; the newest-instance retainer is the one that grew:', ...retainerSplits.map(s => `- ${s}`));
368
+ }
369
+ lines.push('', `**${formatNumber(leakCandidates)} leak candidate(s)** of ${formatNumber(candidates.length)} growing class(es) examined` +
370
+ (devOnlyClasses > 0
371
+ ? `; ${formatNumber(devOnlyClasses)} ruled out as dev/automation-retained`
372
+ : '') +
373
+ (artifactRows.length > 0 && !include_artifacts
374
+ ? `; ${formatNumber(artifactRows.length)} known measurement artifact(s) not shown (\`include_artifacts: true\`)`
375
+ : '') +
376
+ '.');
377
+ if (!showDevOnly) {
378
+ lines.push('', '_No dev/automation roots were found in the final snapshot, so the dev-only column is omitted — nothing here is being attributed to the inspector._');
379
+ }
380
+ // Point at the single next call for the strongest candidate rather than
381
+ // a menu: the failure mode this tool exists to fix is a plausible
382
+ // grower being reported without anyone tracing it.
383
+ const strongest = candidates.find(r => r.artifact == null &&
384
+ r.trend === 'monotonic-up' &&
385
+ evidence.get(r.key)?.example != null);
386
+ if (strongest) {
387
+ const ev = evidence.get(strongest.key);
388
+ const example = ev.example;
389
+ lines.push('', `**Next:** confirm the top candidate before reporting it — \`memlab_retainer_trace({node_id: ${example.id}})\` on the largest traceable \`${proseName(strongest)}\` instance in the final rung, then \`memlab_dominator_chain\` on whatever owns it. Counts alone cannot distinguish a leak from a cache that grew and will be evicted.`);
390
+ }
391
+ return toolResult(lines.join('\n'), pathsHeader(steps.map(s => s.label)));
392
+ }
393
+ catch (err) {
394
+ return errorResult(err);
395
+ }
396
+ });
397
+ }
398
+ //# sourceMappingURL=leak-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"leak-report.js","sourceRoot":"","sources":["../../src/tools/leak-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,kBAAkB,MAAM,uBAAuB,CAAC;AACvD,MAAM,EAAC,mBAAmB,EAAC,GAAG,kBAAkB,CAAC;AACjD,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AACrD,OAAO,EACL,qBAAqB,EACrB,kBAAkB,GAEnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,eAAe,EACf,+BAA+B,GAChC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,4BAA4B,EAAC,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAC,oBAAoB,EAAC,MAAM,gBAAgB,CAAC;AAEpD,gFAAgF;AAChF,4EAA4E;AAC5E,6EAA6E;AAC7E,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAChC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,gFAAgF;AAChF,8EAA8E;AAC9E,iFAAiF;AACjF,4EAA4E;AAC5E,MAAM,cAAc,GAAG,GAAG,CAAC;AAuB3B,0EAA0E;AAC1E,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,SAAS,WAAW,CAAC,GAAiC;IACpD,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,IAAI,GAAG,CAAC;AAClE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,SAAS,SAAS,CAAC,GAAiC;IAClD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,OAAO,IAAI,CAAC,MAAM,GAAG,cAAc;QACjC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,GAAG,CAAC,CAAC,GAAG;QACzC,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,SAAS,aAAa,CAAC,KAA2B;IAKhD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,EAAE,CAAC;QACpD,UAAU,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,4BAA4B,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,IAAI,GAAG,WAAW,CAAC;IACvB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC;QAChC,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC;YAClB,IAAI,GAAG,KAAK,CAAC;YACb,SAAS,GAAG,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,EAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAS,cAAc,CAAC,EAAY;IAMlC,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO;QACL,GAAG,MAAM;QACT,eAAe,EACb,MAAM,CAAC,KAAK,KAAK,UAAU,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,KAAK,WAAW;YACnE,CAAC,CAAC,UAAU,CAAC,KAAK;YAClB,CAAC,CAAC,IAAI;KACX,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,OAA+B,EAC/B,SAAS,GAAG,IAAI;IAEhB,MAAM,GAAG,GAAsC,EAAE,CAAC;IAClD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;YAAE,SAAS;QACpD,MAAM,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;QAC/B,IAAI,KAAK,GAAG,CAAC;YAAE,SAAS;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;YAC3D,GAAG,CAAC,IAAI,CAAC,EAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAC,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,qTAAqT;QACnT,gcAAgc;QAChc,gJAAgJ;QAChJ,qYAAqY,EACvY;QACE,KAAK,EAAE,CAAC;aACL,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aACjB,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CACP,uMAAuM,CACxM;QACH,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sNAAsN,CACvN;QACH,OAAO,EAAE,CAAC;aACP,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aAClB,QAAQ,EAAE;aACV,QAAQ,CACP,0YAA0Y,CAC3Y;QACH,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CACP,wEAAwE,CACzE;QACH,gBAAgB,EAAE,CAAC;aAChB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CACP,sFAAsF,CACvF;QACH,cAAc,EAAE,CAAC;aACd,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,CACP,oHAAoH,CACrH;QACH,iBAAiB,EAAE,CAAC;aACjB,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,OAAO,CAAC,KAAK,CAAC;aACd,QAAQ,CACP,wQAAwQ,CACzQ;QACH,gBAAgB,EAAE,CAAC;aAChB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,iKAAiK,CAClK;KACJ,EACD,KAAK,EACH,EACE,KAAK,EACL,MAAM,EACN,OAAO,EACP,KAAK,EACL,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,GACjB,EACD,KAAK,EACL,EAAE;QACF,IAAI,CAAC;YACH,MAAM,EAAC,KAAK,EAAE,IAAI,EAAC,GAAG,MAAM,qBAAqB,CAAC,KAAK,EAAE;gBACvD,cAAc,EAAE,gBAAgB;gBAChC,aAAa,EAAE,cAAc;gBAC7B,aAAa,EAAE,gBAAgB;gBAC/B,QAAQ,EAAE,oBAAoB;gBAC9B,QAAQ,EAAE,oBAAoB,CAAC,KAAK,EAAE,aAAa,CAAC;aACrD,CAAC,CAAC;YAEH,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;YACvB,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC;YAC1D,MAAM,UAAU,GAAkB,CAChC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAChE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YAElB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC5D,MAAM,KAAK,GAAa;gBACtB,mBAAmB,CAAC,aAAa;gBACjC,EAAE;gBACF,kBAAkB,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,uBAAuB,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU;gBAClM,EAAE;aACH,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,IAAI,CACR,8MAA8M,EAC9M,EAAE,CACH,CAAC;YACJ,CAAC;YAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,KAAK,CAAC,IAAI,CACR,oCAAoC,YAAY,CAAC,gBAAgB,CAAC,sEAAsE,CACzI,CAAC;gBACF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5B,KAAK,CAAC,IAAI,CACR,EAAE,EACF,QAAQ,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,qGAAqG,CAC/I,CAAC;gBACJ,CAAC;gBACD,OAAO,UAAU,CACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAChB,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACrC,CAAC;YACJ,CAAC;YAED,oEAAoE;YACpE,sEAAsE;YACtE,uEAAuE;YACvE,mBAAmB;YACnB,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACnE,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;YAC3C,MAAM,OAAO,GACX,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;gBACpB,CAAC,CAAC,+BAA+B,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBACrD,CAAC,CAAC,IAAI,CAAC;YAEX,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;YAC7C,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;gBAC3B,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE;oBAClB,KAAK,EAAE,CAAC;oBACR,OAAO,EAAE,CAAC;oBACV,OAAO,EAAE,EAAE;oBACX,MAAM,EAAE,EAAE;oBACV,OAAO,EAAE,IAAI;oBACb,eAAe,EAAE,CAAC,CAAC;oBACnB,UAAU,EAAE,IAAI;iBACjB,CAAC,CAAC;YACL,CAAC;YACD,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBAC5B,IAAI,IAAI,CAAC,EAAE,IAAI,CAAC;oBAAE,OAAO;gBACzB,sEAAsE;gBACtE,kEAAkE;gBAClE,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CACrB,GAAG,IAAI,CAAC,IAAI,KAAK,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjD,CAAC;gBACF,IAAI,CAAC,EAAE;oBAAE,OAAO;gBAChB,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;oBAAE,EAAE,CAAC,OAAO,EAAE,CAAC;gBACnE,IAAI,EAAE,CAAC,UAAU,IAAI,IAAI;oBAAE,EAAE,CAAC,UAAU,GAAG,IAAI,CAAC;gBAChD,IAAI,CAAC,IAAI,CAAC,WAAW;oBAAE,OAAO;gBAC9B,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,qBAAqB;oBAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrE,qEAAqE;gBACrE,qEAAqE;gBACrE,+DAA+D;gBAC/D,IACE,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,qBAAqB;oBACxC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAC5C,CAAC;oBACD,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;oBACzB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE;wBAAE,CAAC,EAAE,CAAC;oBACnD,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;oBAC7B,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,qBAAqB;wBAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;gBAChE,CAAC;gBACD,IAAI,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC,eAAe,EAAE,CAAC;oBAC3C,EAAE,CAAC,eAAe,GAAG,IAAI,CAAC,YAAY,CAAC;oBACvC,EAAE,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpB,CAAC;YACH,CAAC,CAAC,CAAC;YACH,yEAAyE;YACzE,+CAA+C;YAC/C,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnC,IAAI,EAAE,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;oBACvB,EAAE,CAAC,OAAO,GAAG;wBACX,EAAE,CAAC,OAAO;wBACV,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAM,EAAE,CAAC,OAAqB,CAAC,EAAE,CAAC;qBACjE,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,IAAI,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC;YAC9C,MAAM,WAAW,GAAG,OAAO,IAAI,IAAI,CAAC;YACpC,MAAM,OAAO,GAAG;gBACd,OAAO;gBACP,MAAM;gBACN,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnC,SAAS;gBACT,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChC,QAAQ;gBACR,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpC,iCAAiC;gBACjC,cAAc;aACf,CAAC;YACF,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE;gBAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAE9D,IAAI,cAAc,GAAG,CAAC,CAAC;YACvB,IAAI,cAAc,GAAG,CAAC,CAAC;YACvB,uEAAuE;YACvE,gEAAgE;YAChE,uEAAuE;YACvE,0BAA0B;YAC1B,MAAM,cAAc,GAAa,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBACnC,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAa,CAAC;gBAC3C,MAAM,QAAQ,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC1D,MAAM,SAAS,GAAG,WAAW,IAAI,QAAQ,IAAI,cAAc,CAAC;gBAC5D,IAAI,SAAS;oBAAE,cAAc,EAAE,CAAC;gBAEhC,IAAI,OAAe,CAAC;gBACpB,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;oBACvB,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBACtC,CAAC;qBAAM,IAAI,SAAS,EAAE,CAAC;oBACrB,OAAO,GAAG,6CAA6C,CAAC;gBAC1D,CAAC;qBAAM,IAAI,CAAC,CAAC,KAAK,KAAK,cAAc,EAAE,CAAC;oBACtC,OAAO,GAAG,+BAA+B,CAAC;oBAC1C,cAAc,EAAE,CAAC;gBACnB,CAAC;qBAAM,CAAC;oBACN,OAAO,GAAG,kBAAkB,CAAC;gBAC/B,CAAC;gBAED,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;gBAC7B,OAAO;oBACL,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK;oBACpD,CAAC,CAAC,IAAI;oBACN,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;oBACrC,IAAI,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE;oBAC9B,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAI,MAAiB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACnE,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE;oBACvD,GAAG,CAAC,WAAW;wBACb,CAAC,CAAC;4BACE,EAAE,CAAC,KAAK,KAAK,CAAC;gCACZ,CAAC,CAAC,GAAG;gCACL,CAAC,CAAC,EAAE,CAAC,OAAO,KAAK,CAAC;oCAChB,CAAC,CAAC,GAAG;oCACL,CAAC,CAAC,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;yBACxC;wBACH,CAAC,CAAC,EAAE,CAAC;oBACP,CAAC,GAAG,EAAE;wBACJ,MAAM,CAAC,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;wBAC7B,IAAI,CAAC,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC;4BAC9B,cAAc,CAAC,IAAI,CACjB,KAAK,KAAK,kBAAkB,CAAC,CAAC,KAAK,+BAA+B,CAAC,CAAC,eAAe,IAAI,CACxF,CAAC;wBACJ,CAAC;wBACD,MAAM,KAAK,GACT,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;wBACzD,OAAO,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;oBAC9D,CAAC,CAAC,EAAE;oBACJ,OAAO;iBACR,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;YAEzD,IAAI,OAAO,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAI,GAAa,EAAE,CAAC;gBAC1B,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;oBAC3B,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI;wBAAE,SAAS;oBACjC,KAAK,MAAM,EAAC,GAAG,EAAE,GAAG,EAAC,IAAI,aAAa,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;wBAC5D,IAAI,CAAC,IAAI,CACP,OAAO,SAAS,CAAC,CAAC,CAAC,gBAAgB,YAAY,CAAC,GAAG,CAAC,QAAQ,GAAG,KAAK;4BAClE,IAAI,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CACnE,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpB,KAAK,CAAC,IAAI,CACR,EAAE,EACF,6DAA6D,EAC7D,EAAE,EACF,GAAG,IAAI,EACP,EAAE,EACF,oGAAoG;wBAClG,mGAAmG;wBACnG,kGAAkG;wBAClG,4EAA4E,CAC/E,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,KAAK,CAAC,IAAI,CACR,EAAE,EACF,+KAA+K;gBAC7K,qJAAqJ;gBACrJ,oNAAoN,CACvN,CAAC;YACF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,KAAK,CAAC,IAAI,CACR,EAAE,EACF,OAAO,cAAc,CAAC,MAAM,4FAA4F;oBACtH,wIAAwI,EAC1I,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CACrC,CAAC;YACJ,CAAC;YAED,KAAK,CAAC,IAAI,CACR,EAAE,EACF,KAAK,YAAY,CAAC,cAAc,CAAC,2BAA2B,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,6BAA6B;gBACtH,CAAC,cAAc,GAAG,CAAC;oBACjB,CAAC,CAAC,KAAK,YAAY,CAAC,cAAc,CAAC,uCAAuC;oBAC1E,CAAC,CAAC,EAAE,CAAC;gBACP,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,iBAAiB;oBAC5C,CAAC,CAAC,KAAK,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,wEAAwE;oBAChH,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CACN,CAAC;YAEF,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,KAAK,CAAC,IAAI,CACR,EAAE,EACF,oJAAoJ,CACrJ,CAAC;YACJ,CAAC;YAED,wEAAwE;YACxE,kEAAkE;YAClE,mDAAmD;YACnD,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,QAAQ,IAAI,IAAI;gBAClB,CAAC,CAAC,KAAK,KAAK,cAAc;gBAC1B,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,OAAO,IAAI,IAAI,CACvC,CAAC;YACF,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAa,CAAC;gBACnD,MAAM,OAAO,GAAG,EAAE,CAAC,OAAoB,CAAC;gBACxC,KAAK,CAAC,IAAI,CACR,EAAE,EACF,+FAA+F,OAAO,CAAC,EAAE,mCAAmC,SAAS,CAAC,SAAS,CAAC,wKAAwK,CACzU,CAAC;YACJ,CAAC;YAED,OAAO,UAAU,CACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAChB,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACrC,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -16,6 +16,24 @@ export declare const DEFAULT_MAX_EDGES = 24000000;
16
16
  export declare const WARN_NODE_COUNT = 2000000;
17
17
  export declare const NODES_PER_HEAP_MB = 1700;
18
18
  export declare const EDGES_PER_HEAP_MB = 6800;
19
+ export declare const LOAD_BYTES_PER_NODE = 200;
20
+ export declare const LOAD_BYTES_PER_EDGE = 40;
21
+ export declare const HEADROOM_SAFETY_FRACTION = 0.8;
22
+ /**
23
+ * Projected additional heap (MB) a full load of this graph will occupy.
24
+ * Light loads skip the dominator/retained-size arrays; the parsed graph still
25
+ * dominates, so the discount is modest and intentionally conservative.
26
+ */
27
+ export declare function estimateLoadHeapMB(counts: {
28
+ nodeCount: number;
29
+ edgeCount: number;
30
+ }, light: boolean): number;
31
+ /**
32
+ * Old-space headroom (MB) left for a new load: the configured limit minus what
33
+ * is already committed. Returns null when the limit can't be read, in which case
34
+ * the caller skips the guard rather than guessing.
35
+ */
36
+ export declare function getHeapHeadroomMB(): number | null;
19
37
  /**
20
38
  * Configured V8 old-space limit in MB (reflects --max-old-space-size). Returns 0
21
39
  * when it can't be read, so callers fall back to the fixed floors.
@@ -66,7 +84,18 @@ export declare function estimateMaxLoadableMB(counts: {
66
84
  * Resolve the effective max-file-size limit (MB). An explicit caller value always
67
85
  * wins; otherwise default by source — Manifold-fetched server snapshots get the
68
86
  * higher ceiling, local files keep the tighter guard.
87
+ *
88
+ * Both defaults are floors, not constants. They were sized for a 2 GB default
89
+ * old-space; on a server started with more heap they refuse files it could
90
+ * comfortably parse, and the refusal reads like a property of the snapshot
91
+ * rather than of the server's configuration. A 1.13 GB local browser capture
92
+ * on an 8 GB server is the case that matters: the guard fired, and the
93
+ * remedy — repeat the call with an explicit max_file_size_mb — has to be
94
+ * rediscovered every time, on every subsequent load call in the session.
95
+ * The cap therefore scales with the configured old-space limit and never
96
+ * drops below the historical fixed value.
69
97
  */
98
+ export declare const FILE_MB_PER_HEAP_MB = 0.25;
70
99
  export declare function resolveMaxFileSizeMB(explicit: number | undefined, fetchedFromManifold: boolean): number;
71
100
  /**
72
101
  * Resolve a `file_path` that may be a local path, a `manifold://bucket/key`
@@ -1 +1 @@
1
- {"version":3,"file":"load-snapshot.d.ts","sourceRoot":"","sources":["../../src/tools/load-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA4BvE,eAAO,MAAM,uBAAuB,sCAAsC,CAAC;AAU3E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAmBjD,eAAO,MAAM,iBAAiB,WAAa,CAAC;AAC5C,eAAO,MAAM,iBAAiB,WAAa,CAAC;AAC5C,eAAO,MAAM,eAAe,UAAY,CAAC;AAazC,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAM3C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,CAoBA;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAChB;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,GAAG,IAAI,CAgB/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,EAC9C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,GAC7C,MAAM,GAAG,IAAI,CASf;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,mBAAmB,EAAE,OAAO,GAC3B,MAAM,CAKR;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAsEA;AAmCD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAWhE;AAsGD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuV5D"}
1
+ {"version":3,"file":"load-snapshot.d.ts","sourceRoot":"","sources":["../../src/tools/load-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAwCvE,eAAO,MAAM,uBAAuB,sCAAsC,CAAC;AAU3E,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAmBjD,eAAO,MAAM,iBAAiB,WAAa,CAAC;AAC5C,eAAO,MAAM,iBAAiB,WAAa,CAAC;AAC5C,eAAO,MAAM,eAAe,UAAY,CAAC;AAazC,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAStC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAMtC,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,EAC9C,KAAK,EAAE,OAAO,GACb,MAAM,CAKR;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAUjD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAM3C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,CAoBA;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAChB;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,GAAG,IAAI,CAgB/C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,EAC9C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,GAC7C,MAAM,GAAG,IAAI,CASf;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,mBAAmB,EAAE,OAAO,GAC3B,MAAM,CAQR;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAsEA;AAmCD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAWhE;AAmJD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2iB5D"}