@memlab/mcp-server 2.3.0 → 2.52.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 (205) hide show
  1. package/README.md +18 -14
  2. package/bin/.eslintrc.js +26 -0
  3. package/bin/memlab-cli.js +313 -0
  4. package/dist/artifact-classes.d.ts +86 -0
  5. package/dist/artifact-classes.d.ts.map +1 -0
  6. package/dist/artifact-classes.js +261 -0
  7. package/dist/artifact-classes.js.map +1 -0
  8. package/dist/capture-mode.d.ts +60 -0
  9. package/dist/capture-mode.d.ts.map +1 -0
  10. package/dist/capture-mode.js +39 -0
  11. package/dist/capture-mode.js.map +1 -0
  12. package/dist/guardrail.d.ts.map +1 -1
  13. package/dist/guardrail.js +13 -0
  14. package/dist/guardrail.js.map +1 -1
  15. package/dist/heap-state.d.ts +96 -2
  16. package/dist/heap-state.d.ts.map +1 -1
  17. package/dist/heap-state.js +197 -2
  18. package/dist/heap-state.js.map +1 -1
  19. package/dist/index.js +41 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/progress.d.ts +25 -0
  22. package/dist/progress.d.ts.map +1 -0
  23. package/dist/progress.js +46 -0
  24. package/dist/progress.js.map +1 -0
  25. package/dist/result-handles.d.ts +11 -0
  26. package/dist/result-handles.d.ts.map +1 -0
  27. package/dist/result-handles.js +77 -0
  28. package/dist/result-handles.js.map +1 -0
  29. package/dist/string-index.d.ts +55 -0
  30. package/dist/string-index.d.ts.map +1 -0
  31. package/dist/string-index.js +91 -0
  32. package/dist/string-index.js.map +1 -0
  33. package/dist/tool-registry.d.ts +42 -0
  34. package/dist/tool-registry.d.ts.map +1 -0
  35. package/dist/tool-registry.js +20 -0
  36. package/dist/tool-registry.js.map +1 -0
  37. package/dist/tools/analyze-run.d.ts +12 -0
  38. package/dist/tools/analyze-run.d.ts.map +1 -0
  39. package/dist/tools/analyze-run.js +343 -0
  40. package/dist/tools/analyze-run.js.map +1 -0
  41. package/dist/tools/app-heap.d.ts +12 -0
  42. package/dist/tools/app-heap.d.ts.map +1 -0
  43. package/dist/tools/app-heap.js +140 -0
  44. package/dist/tools/app-heap.js.map +1 -0
  45. package/dist/tools/auto-investigate.d.ts.map +1 -1
  46. package/dist/tools/auto-investigate.js +91 -49
  47. package/dist/tools/auto-investigate.js.map +1 -1
  48. package/dist/tools/batch.d.ts +12 -0
  49. package/dist/tools/batch.d.ts.map +1 -0
  50. package/dist/tools/batch.js +168 -0
  51. package/dist/tools/batch.js.map +1 -0
  52. package/dist/tools/cache-analysis.d.ts.map +1 -1
  53. package/dist/tools/cache-analysis.js +156 -5
  54. package/dist/tools/cache-analysis.js.map +1 -1
  55. package/dist/tools/class-histogram.d.ts.map +1 -1
  56. package/dist/tools/class-histogram.js +14 -3
  57. package/dist/tools/class-histogram.js.map +1 -1
  58. package/dist/tools/collection-trend.d.ts +55 -0
  59. package/dist/tools/collection-trend.d.ts.map +1 -0
  60. package/dist/tools/collection-trend.js +315 -0
  61. package/dist/tools/collection-trend.js.map +1 -0
  62. package/dist/tools/detached-dom.d.ts +2 -0
  63. package/dist/tools/detached-dom.d.ts.map +1 -1
  64. package/dist/tools/detached-dom.js +291 -20
  65. package/dist/tools/detached-dom.js.map +1 -1
  66. package/dist/tools/dev-artifacts.d.ts +62 -6
  67. package/dist/tools/dev-artifacts.d.ts.map +1 -1
  68. package/dist/tools/dev-artifacts.js +466 -23
  69. package/dist/tools/dev-artifacts.js.map +1 -1
  70. package/dist/tools/diff-snapshots.d.ts.map +1 -1
  71. package/dist/tools/diff-snapshots.js +101 -44
  72. package/dist/tools/diff-snapshots.js.map +1 -1
  73. package/dist/tools/dominator-attribution.d.ts +12 -0
  74. package/dist/tools/dominator-attribution.d.ts.map +1 -0
  75. package/dist/tools/dominator-attribution.js +189 -0
  76. package/dist/tools/dominator-attribution.js.map +1 -0
  77. package/dist/tools/dominator-chain.d.ts +12 -0
  78. package/dist/tools/dominator-chain.d.ts.map +1 -0
  79. package/dist/tools/dominator-chain.js +92 -0
  80. package/dist/tools/dominator-chain.js.map +1 -0
  81. package/dist/tools/duplicate-objects.d.ts +12 -0
  82. package/dist/tools/duplicate-objects.d.ts.map +1 -0
  83. package/dist/tools/duplicate-objects.js +172 -0
  84. package/dist/tools/duplicate-objects.js.map +1 -0
  85. package/dist/tools/duplicated-strings.d.ts.map +1 -1
  86. package/dist/tools/duplicated-strings.js +46 -38
  87. package/dist/tools/duplicated-strings.js.map +1 -1
  88. package/dist/tools/eval.d.ts +1 -0
  89. package/dist/tools/eval.d.ts.map +1 -1
  90. package/dist/tools/eval.js +787 -30
  91. package/dist/tools/eval.js.map +1 -1
  92. package/dist/tools/explain-delta.d.ts +12 -0
  93. package/dist/tools/explain-delta.d.ts.map +1 -0
  94. package/dist/tools/explain-delta.js +170 -0
  95. package/dist/tools/explain-delta.js.map +1 -0
  96. package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
  97. package/dist/tools/find-nodes-by-class.js +112 -13
  98. package/dist/tools/find-nodes-by-class.js.map +1 -1
  99. package/dist/tools/finding-index.d.ts +22 -0
  100. package/dist/tools/finding-index.d.ts.map +1 -0
  101. package/dist/tools/finding-index.js +247 -0
  102. package/dist/tools/finding-index.js.map +1 -0
  103. package/dist/tools/for-each.d.ts.map +1 -1
  104. package/dist/tools/for-each.js +15 -3
  105. package/dist/tools/for-each.js.map +1 -1
  106. package/dist/tools/get-references.d.ts.map +1 -1
  107. package/dist/tools/get-references.js +35 -6
  108. package/dist/tools/get-references.js.map +1 -1
  109. package/dist/tools/get-referrers.d.ts.map +1 -1
  110. package/dist/tools/get-referrers.js +52 -6
  111. package/dist/tools/get-referrers.js.map +1 -1
  112. package/dist/tools/hunt-report.d.ts +12 -0
  113. package/dist/tools/hunt-report.d.ts.map +1 -0
  114. package/dist/tools/hunt-report.js +186 -0
  115. package/dist/tools/hunt-report.js.map +1 -0
  116. package/dist/tools/hypothesis.d.ts +12 -0
  117. package/dist/tools/hypothesis.d.ts.map +1 -0
  118. package/dist/tools/hypothesis.js +221 -0
  119. package/dist/tools/hypothesis.js.map +1 -0
  120. package/dist/tools/intern-opportunities.d.ts.map +1 -1
  121. package/dist/tools/intern-opportunities.js +721 -75
  122. package/dist/tools/intern-opportunities.js.map +1 -1
  123. package/dist/tools/ladder.d.ts +33 -0
  124. package/dist/tools/ladder.d.ts.map +1 -0
  125. package/dist/tools/ladder.js +266 -0
  126. package/dist/tools/ladder.js.map +1 -0
  127. package/dist/tools/largest-objects.d.ts.map +1 -1
  128. package/dist/tools/largest-objects.js +43 -16
  129. package/dist/tools/largest-objects.js.map +1 -1
  130. package/dist/tools/leak-report.d.ts +12 -0
  131. package/dist/tools/leak-report.d.ts.map +1 -0
  132. package/dist/tools/leak-report.js +256 -0
  133. package/dist/tools/leak-report.js.map +1 -0
  134. package/dist/tools/load-snapshot.d.ts +78 -0
  135. package/dist/tools/load-snapshot.d.ts.map +1 -1
  136. package/dist/tools/load-snapshot.js +519 -29
  137. package/dist/tools/load-snapshot.js.map +1 -1
  138. package/dist/tools/map-entries.d.ts +12 -0
  139. package/dist/tools/map-entries.d.ts.map +1 -0
  140. package/dist/tools/map-entries.js +139 -0
  141. package/dist/tools/map-entries.js.map +1 -0
  142. package/dist/tools/match-object.d.ts +12 -0
  143. package/dist/tools/match-object.d.ts.map +1 -0
  144. package/dist/tools/match-object.js +165 -0
  145. package/dist/tools/match-object.js.map +1 -0
  146. package/dist/tools/object-shape.d.ts.map +1 -1
  147. package/dist/tools/object-shape.js +92 -30
  148. package/dist/tools/object-shape.js.map +1 -1
  149. package/dist/tools/population-diff.d.ts +57 -0
  150. package/dist/tools/population-diff.d.ts.map +1 -0
  151. package/dist/tools/population-diff.js +338 -0
  152. package/dist/tools/population-diff.js.map +1 -0
  153. package/dist/tools/quick-diagnosis.d.ts.map +1 -1
  154. package/dist/tools/quick-diagnosis.js +12 -4
  155. package/dist/tools/quick-diagnosis.js.map +1 -1
  156. package/dist/tools/retainer-layers.d.ts +23 -0
  157. package/dist/tools/retainer-layers.d.ts.map +1 -0
  158. package/dist/tools/retainer-layers.js +179 -0
  159. package/dist/tools/retainer-layers.js.map +1 -0
  160. package/dist/tools/retainer-summary.d.ts +1 -0
  161. package/dist/tools/retainer-summary.d.ts.map +1 -1
  162. package/dist/tools/retainer-summary.js +128 -32
  163. package/dist/tools/retainer-summary.js.map +1 -1
  164. package/dist/tools/retainer-trace.d.ts.map +1 -1
  165. package/dist/tools/retainer-trace.js +105 -25
  166. package/dist/tools/retainer-trace.js.map +1 -1
  167. package/dist/tools/search-nodes.d.ts.map +1 -1
  168. package/dist/tools/search-nodes.js +5 -1
  169. package/dist/tools/search-nodes.js.map +1 -1
  170. package/dist/tools/search-strings.d.ts.map +1 -1
  171. package/dist/tools/search-strings.js +53 -7
  172. package/dist/tools/search-strings.js.map +1 -1
  173. package/dist/tools/sequence-analysis.d.ts +49 -0
  174. package/dist/tools/sequence-analysis.d.ts.map +1 -1
  175. package/dist/tools/sequence-analysis.js +268 -78
  176. package/dist/tools/sequence-analysis.js.map +1 -1
  177. package/dist/tools/shape-histogram.d.ts.map +1 -1
  178. package/dist/tools/shape-histogram.js +9 -2
  179. package/dist/tools/shape-histogram.js.map +1 -1
  180. package/dist/tools/sliced-strings.d.ts.map +1 -1
  181. package/dist/tools/sliced-strings.js +22 -4
  182. package/dist/tools/sliced-strings.js.map +1 -1
  183. package/dist/tools/snapshot-header.d.ts +28 -0
  184. package/dist/tools/snapshot-header.d.ts.map +1 -0
  185. package/dist/tools/snapshot-header.js +111 -0
  186. package/dist/tools/snapshot-header.js.map +1 -0
  187. package/dist/tools/string-patterns.d.ts.map +1 -1
  188. package/dist/tools/string-patterns.js +5 -4
  189. package/dist/tools/string-patterns.js.map +1 -1
  190. package/dist/tools/tools-index.d.ts +12 -0
  191. package/dist/tools/tools-index.d.ts.map +1 -0
  192. package/dist/tools/tools-index.js +342 -0
  193. package/dist/tools/tools-index.js.map +1 -0
  194. package/dist/tools/verify-fix.d.ts +23 -0
  195. package/dist/tools/verify-fix.d.ts.map +1 -0
  196. package/dist/tools/verify-fix.js +211 -0
  197. package/dist/tools/verify-fix.js.map +1 -0
  198. package/dist/tools/weakmap-entries.d.ts.map +1 -1
  199. package/dist/tools/weakmap-entries.js +6 -1
  200. package/dist/tools/weakmap-entries.js.map +1 -1
  201. package/dist/utils.d.ts +204 -1
  202. package/dist/utils.d.ts.map +1 -1
  203. package/dist/utils.js +478 -8
  204. package/dist/utils.js.map +1 -1
  205. package/package.json +5 -4
@@ -0,0 +1,247 @@
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 crypto from 'crypto';
11
+ import fs from 'fs';
12
+ import path from 'path';
13
+ import { z } from 'zod';
14
+ import { formatNumber, markdownTable, errorResult, toolResult, } from '../utils.js';
15
+ /**
16
+ * A cross-round index of leak findings, keyed by a normalized retainer-path
17
+ * signature.
18
+ *
19
+ * The problem this solves is the most expensive one a hunt hits: rounds
20
+ * re-discover leaks that are already known or already fixed. One measured round
21
+ * produced three findings — a listener accumulation, a completion-map grower and
22
+ * a module-registry grower — all three of which were known, two already fixed
23
+ * behind gates, and the first only visible because the gated fixes were not
24
+ * enabled. That is an entire round spent re-deriving history.
25
+ *
26
+ * Why a retainer-path signature rather than the class name: the class that grows
27
+ * is rarely distinctive (`Object`, `Array`, `(object properties)` are the top
28
+ * growers in almost every heap), while the PATH that retains it is. Node ids,
29
+ * array indices and per-instance scope ids differ per capture, so they are
30
+ * stripped; what remains — the ordered edge names and class names — is stable
31
+ * across captures of the same leak and different between different leaks.
32
+ *
33
+ * Deliberately local (a JSON file), not a service: the index is only useful if
34
+ * it is written by default on every round, and anything requiring a backend
35
+ * would not be. It is seeded from prior runs' manifests.
36
+ */
37
+ const INDEX_PATH = path.join(process.env.HOME ?? '/tmp', '.memlab-mcp', 'findings.json');
38
+ function loadIndex() {
39
+ try {
40
+ if (fs.existsSync(INDEX_PATH)) {
41
+ const parsed = JSON.parse(fs.readFileSync(INDEX_PATH, 'utf8'));
42
+ if (parsed != null && typeof parsed === 'object') {
43
+ const idx = parsed;
44
+ return {
45
+ version: idx.version ?? 1,
46
+ findings: idx.findings ?? {},
47
+ combos_driven: idx.combos_driven ?? {},
48
+ };
49
+ }
50
+ }
51
+ }
52
+ catch {
53
+ // A corrupt index must not block a hunt — but it must not be silently
54
+ // erased either: returning empty here means the next `record` overwrites
55
+ // the file wholesale and every prior fingerprint is gone, which defeats the
56
+ // one thing this tool exists to do. Preserve it for recovery first.
57
+ try {
58
+ if (fs.existsSync(INDEX_PATH)) {
59
+ fs.renameSync(INDEX_PATH, `${INDEX_PATH}.corrupt`);
60
+ }
61
+ }
62
+ catch {
63
+ // Best effort; a failed rename must not block the hunt either.
64
+ }
65
+ }
66
+ return { version: 1, findings: {}, combos_driven: {} };
67
+ }
68
+ function saveIndex(idx) {
69
+ fs.mkdirSync(path.dirname(INDEX_PATH), { recursive: true });
70
+ fs.writeFileSync(INDEX_PATH, JSON.stringify(idx, null, 2));
71
+ }
72
+ /**
73
+ * Normalize a retainer path into a signature that is stable across captures.
74
+ *
75
+ * Strips exactly the things that differ per capture and nothing else:
76
+ * - `@12345` node ids, including the ` @…`-suffixed Context/scope names;
77
+ * - numeric array indices (`[47]`, `.47`), which depend on insertion order;
78
+ * - hex/long digit runs inside names (ids embedded in keys, e.g. a chat id).
79
+ */
80
+ export function normalizeRetainerPath(raw) {
81
+ return (raw
82
+ .replace(/@\d+/g, '@')
83
+ .replace(/\[\d+\]/g, '[i]')
84
+ // Broad lookahead: retainer paths carry trailing `)`, `]`, `>` and the
85
+ // separator inserted below, so a `\\s|$|\\.`-only lookahead leaves `.47)` /
86
+ // `.47>` unnormalized and feeds per-capture noise into the fingerprint.
87
+ .replace(/\.\d+(?=[^\w]|$)/g, '.i')
88
+ .replace(/\b\d{4,}\b/g, 'N')
89
+ .replace(/\s*(-->|--|→|->)\s*/g, ' > ')
90
+ // `-->` would otherwise match `--` and `->` in turn, doubling the separator.
91
+ .replace(/(?: > )+/g, ' > ')
92
+ .replace(/\s+/g, ' ')
93
+ .trim());
94
+ }
95
+ export function fingerprintOf(signature, classes) {
96
+ const material = `${signature}||${[...classes].sort().join(',')}`;
97
+ return crypto.createHash('sha1').update(material).digest('hex').slice(0, 12);
98
+ }
99
+ export function registerFindingIndex(server) {
100
+ server.tool('memlab_finding_index', 'Fingerprint a leak finding by its retainer path and check it against findings from previous rounds, so a hunt does not spend itself re-discovering a known or already-fixed leak. ' +
101
+ 'This is the highest-cost failure a leak hunt has: a measured round produced three findings that were all already known — two already fixed behind gates — which is an entire round spent re-deriving history. Class names cannot detect that (`Object` and `Array` top every heap); the retainer PATH can, so the fingerprint is a normalized path signature with node ids, array indices and per-capture scope ids stripped. ' +
102
+ 'Actions: "check" fingerprints a candidate and reports NEW / KNOWN / KNOWN-AND-FIXED; "record" adds it; "list" prints the index; "cover" records which combos a round drove, so the "do not repeat covered combos" rule stops depending on someone remembering. Stored in ~/.memlab-mcp/findings.json.', {
103
+ action: z
104
+ .enum(['check', 'record', 'list', 'cover'])
105
+ .describe('"check" (fingerprint + look up, no write), "record" (add/update), "list", "cover" (log combos driven in a round).'),
106
+ retainer_path: z
107
+ .string()
108
+ .optional()
109
+ .describe("The finding's retainer path, as printed by memlab_retainer_summary / memlab_retainer_trace. Required for check and record."),
110
+ growing_classes: z
111
+ .array(z.string())
112
+ .optional()
113
+ .default([])
114
+ .describe('Classes that grew across the ladder for this finding. Folded into the fingerprint so the same path holding a different class set is a different finding.'),
115
+ round: z
116
+ .string()
117
+ .optional()
118
+ .describe('Round identifier (e.g. "r59"), recorded as first/last seen.'),
119
+ status: z
120
+ .enum(['new', 'known', 'fixed'])
121
+ .optional()
122
+ .default('known')
123
+ .describe('Status to record. Use "fixed" together with fixed_behind.'),
124
+ fixed_behind: z
125
+ .string()
126
+ .optional()
127
+ .describe('Gate/ABProp the fix sits behind, if it is fixed.'),
128
+ note: z
129
+ .string()
130
+ .optional()
131
+ .describe('Free-text note stored with the finding.'),
132
+ combos: z
133
+ .array(z.string())
134
+ .optional()
135
+ .default([])
136
+ .describe('For action "cover": combo names driven in this round.'),
137
+ }, async ({ action, retainer_path, growing_classes, round, status, fixed_behind, note, combos, }) => {
138
+ try {
139
+ const index = loadIndex();
140
+ if (action === 'list') {
141
+ const all = Object.values(index.findings);
142
+ if (all.length === 0) {
143
+ return toolResult('The findings index is empty. Record findings as you confirm them ' +
144
+ '(`action: "record"`); the value is entirely in future rounds being ' +
145
+ 'able to recognize them.');
146
+ }
147
+ const rows = all
148
+ .sort((a, b) => b.seen_count - a.seen_count)
149
+ .slice(0, 40)
150
+ .map(f => [
151
+ f.fingerprint,
152
+ f.status === 'fixed'
153
+ ? `fixed (${f.fixed_behind ?? '?'})`
154
+ : f.status,
155
+ f.growing_classes.slice(0, 3).join(', ') || '—',
156
+ `${f.first_seen_round}${f.last_seen_round !== f.first_seen_round ? `→${f.last_seen_round}` : ''}`,
157
+ String(f.seen_count),
158
+ f.signature.length > 60
159
+ ? f.signature.slice(0, 57) + '…'
160
+ : f.signature,
161
+ ]);
162
+ // Sort by round id rather than trusting object insertion order: a
163
+ // re-recorded round moves in the object and "the last 8" silently
164
+ // stops meaning the most recent ones.
165
+ const covered = Object.entries(index.combos_driven)
166
+ .sort((a, b) => a[0].localeCompare(b[0], undefined, { numeric: true }))
167
+ .slice(-8)
168
+ .map(([r, c]) => `${r}: ${c.join(', ')}`);
169
+ return toolResult([
170
+ `## Findings index (${formatNumber(all.length)})`,
171
+ '',
172
+ markdownTable([
173
+ 'Fingerprint',
174
+ 'Status',
175
+ 'Classes',
176
+ 'Rounds',
177
+ 'Seen',
178
+ 'Signature',
179
+ ], rows, new Set([4])),
180
+ covered.length > 0 ? '\n### Combo coverage by round\n' : '',
181
+ ...covered.map(c => `- ${c}`),
182
+ ].join('\n'));
183
+ }
184
+ if (action === 'cover') {
185
+ if (!round)
186
+ return errorResult('action "cover" requires a round.');
187
+ index.combos_driven[round] = combos;
188
+ saveIndex(index);
189
+ return toolResult(`Recorded ${combos.length} combo(s) driven in ${round}: ${combos.join(', ') || '(none)'}.`);
190
+ }
191
+ if (!retainer_path) {
192
+ return errorResult(`action "${action}" requires a retainer_path.`);
193
+ }
194
+ const signature = normalizeRetainerPath(retainer_path);
195
+ const fingerprint = fingerprintOf(signature, growing_classes);
196
+ const existing = index.findings[fingerprint];
197
+ if (action === 'check') {
198
+ if (!existing) {
199
+ return toolResult([
200
+ `## NEW finding — fingerprint \`${fingerprint}\``,
201
+ '',
202
+ `Signature: \`${signature}\``,
203
+ '',
204
+ 'No previous round recorded this retainer path with this class set. ' +
205
+ 'Confirm it, then `action: "record"` so the next round recognizes it.',
206
+ ].join('\n'));
207
+ }
208
+ const label = existing.status === 'fixed'
209
+ ? `KNOWN-AND-FIXED-BEHIND(${existing.fixed_behind ?? 'unknown gate'})`
210
+ : `KNOWN (${existing.first_seen_round})`;
211
+ return toolResult([
212
+ `## ${label} — fingerprint \`${fingerprint}\``,
213
+ '',
214
+ `Signature: \`${signature}\``,
215
+ `First seen: ${existing.first_seen_round}; last seen: ${existing.last_seen_round}; seen ${existing.seen_count}×.`,
216
+ existing.note ? `Note: ${existing.note}` : '',
217
+ '',
218
+ existing.status === 'fixed'
219
+ ? `**Stop here.** This leak is already fixed behind \`${existing.fixed_behind}\`. If it is still reproducing, the gate is probably not enabled in this run — verify the gating state before treating it as a finding.`
220
+ : '**This is not a new finding.** Check whether the earlier round already root-caused it before spending the rest of this one on it.',
221
+ ]
222
+ .filter(Boolean)
223
+ .join('\n'));
224
+ }
225
+ // record
226
+ const roundId = round ?? 'unknown';
227
+ index.findings[fingerprint] = {
228
+ fingerprint,
229
+ signature,
230
+ growing_classes,
231
+ first_seen_round: existing?.first_seen_round ?? roundId,
232
+ last_seen_round: roundId,
233
+ status,
234
+ fixed_behind: fixed_behind ?? existing?.fixed_behind,
235
+ note: note ?? existing?.note,
236
+ seen_count: (existing?.seen_count ?? 0) + 1,
237
+ };
238
+ saveIndex(index);
239
+ return toolResult(`Recorded \`${fingerprint}\` as **${status}**${fixed_behind ? ` (behind \`${fixed_behind}\`)` : ''} for round ${roundId}. ` +
240
+ `Signature: \`${signature}\`. The index now holds ${formatNumber(Object.keys(index.findings).length)} finding(s).`);
241
+ }
242
+ catch (err) {
243
+ return errorResult(err);
244
+ }
245
+ });
246
+ }
247
+ //# sourceMappingURL=finding-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-index.js","sourceRoot":"","sources":["../../src/tools/finding-index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"for-each.d.ts","sourceRoot":"","sources":["../../src/tools/for-each.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA2BvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+MvD"}
1
+ {"version":3,"file":"for-each.d.ts","sourceRoot":"","sources":["../../src/tools/for-each.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA2BvE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+NvD"}
@@ -45,7 +45,7 @@ export function registerForEach(server) {
45
45
  initial_value: z
46
46
  .string()
47
47
  .optional()
48
- .describe('JSON string for the reduce initial accumulator value. ' +
48
+ .describe('JSON string for the reduce initial accumulator value; parsed with JSON.parse (must be valid JSON, not arbitrary code). ' +
49
49
  'Default: "[]" when reduce_code is present, ignored otherwise. ' +
50
50
  'Example: "0" or "{}"'),
51
51
  limit: z
@@ -105,6 +105,7 @@ export function registerForEach(server) {
105
105
  __map: null,
106
106
  __reduce: null,
107
107
  __result: undefined,
108
+ __initAcc: undefined,
108
109
  };
109
110
  const context = vm.createContext(sandbox);
110
111
  // Compile filter function
@@ -126,12 +127,23 @@ export function registerForEach(server) {
126
127
  }
127
128
  // Build and run the iteration logic
128
129
  const isReducing = reduce_code != null;
129
- const initVal = initial_value ?? (isReducing ? '[]' : undefined);
130
+ // Parse initial_value as JSON and pass it as a sandbox value rather than
131
+ // splicing it into the script source — interpolating it verbatim would
132
+ // let a caller inject executable code into the reduce path.
133
+ if (isReducing) {
134
+ try {
135
+ sandbox.__initAcc =
136
+ initial_value != null ? JSON.parse(initial_value) : [];
137
+ }
138
+ catch {
139
+ return errorResult(new Error(`initial_value must be a valid JSON string (e.g. "0", "{}", "[]"). Received: ${initial_value}`));
140
+ }
141
+ }
130
142
  let iterationCode;
131
143
  if (isReducing) {
132
144
  iterationCode = `
133
145
  (function() {
134
- var acc = ${initVal};
146
+ var acc = __initAcc;
135
147
  snapshot.nodes.forEach(function(node) {
136
148
  if (__filter(node)) {
137
149
  var item = __map(node);
@@ -1 +1 @@
1
- {"version":3,"file":"for-each.js","sourceRoot":"","sources":["../../src/tools/for-each.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"for-each.js","sourceRoot":"","sources":["../../src/tools/for-each.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-references.d.ts","sourceRoot":"","sources":["../../src/tools/get-references.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAYvE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoE7D"}
1
+ {"version":3,"file":"get-references.d.ts","sourceRoot":"","sources":["../../src/tools/get-references.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAYvE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+G7D"}
@@ -11,31 +11,53 @@ import { z } from 'zod';
11
11
  import { getSnapshot } from '../heap-state.js';
12
12
  import { formatBytes, formatNumber, markdownTable, truncateNodeName, errorResult, toolResult, } from '../utils.js';
13
13
  export function registerGetReferences(server) {
14
- server.tool('memlab_get_references', 'Get outgoing edges (references) from a heap node, sorted by target retained size. Shows what objects this node points to — its properties, elements, and closure captures. Complements memlab_get_referrers (incoming edges). Use memlab_object_shape for a quick property overview, or memlab_closure_inspection for closure-specific analysis.', {
14
+ server.tool('memlab_get_references', 'Get outgoing edges (references) from a heap node, sorted by target retained size. Shows what objects this node points to — its properties, elements, and closure captures. Supports edge_filter (match by edge name) and offset (pagination) so a node with thousands of references can be explored beyond the first page. Complements memlab_get_referrers (incoming edges). Use memlab_object_shape for a quick property overview, or memlab_closure_inspection for closure-specific analysis.', {
15
15
  node_id: z.number().describe('The numeric ID of the heap node'),
16
16
  limit: z
17
17
  .number()
18
18
  .optional()
19
19
  .default(30)
20
20
  .describe('Maximum number of references to return (default 30)'),
21
+ offset: z
22
+ .number()
23
+ .optional()
24
+ .default(0)
25
+ .describe('Number of (filtered, sorted) references to skip before returning — for paging past the first `limit` on high-degree nodes (default 0).'),
26
+ edge_filter: z
27
+ .string()
28
+ .optional()
29
+ .describe('Case-insensitive substring; only edges whose name/index contains it are returned (e.g. "context", or a specific property name). Applied before sort + pagination, so you can isolate one edge among thousands instead of scanning the top-N.'),
21
30
  compact: z
22
31
  .boolean()
23
32
  .optional()
24
33
  .default(true)
25
34
  .describe('Truncate target names to 60 chars to save tokens (default true). Set to false to see full names.'),
26
- }, async ({ node_id, limit, compact }) => {
35
+ }, async ({ node_id, limit, offset, edge_filter, compact }) => {
27
36
  try {
28
37
  const snapshot = getSnapshot();
29
38
  const node = snapshot.getNodeById(node_id);
30
39
  if (!node) {
31
40
  return errorResult(`Node with id ${node_id} not found`);
32
41
  }
33
- const edges = node.references
42
+ // Treat an empty / whitespace-only filter as "no filter" so the header
43
+ // doesn't advertise a filter that matches every edge, and clamp a
44
+ // negative offset to 0 rather than letting slice() read from the tail.
45
+ const activeFilter = edge_filter != null && edge_filter.trim() !== '' ? edge_filter : null;
46
+ const filterLc = activeFilter?.toLowerCase();
47
+ const safeOffset = Math.max(0, offset);
48
+ const matched = node.references
34
49
  .slice()
35
- .sort((a, b) => b.toNode.retainedSize - a.toNode.retainedSize)
36
- .slice(0, limit);
50
+ .filter(e => filterLc == null
51
+ ? true
52
+ : String(e.name_or_index).toLowerCase().includes(filterLc))
53
+ .sort((a, b) => b.toNode.retainedSize - a.toNode.retainedSize);
54
+ const edges = matched.slice(safeOffset, safeOffset + limit);
55
+ const filterNote = activeFilter != null
56
+ ? `, ${formatNumber(matched.length)} match "${activeFilter}"`
57
+ : '';
58
+ const offsetNote = safeOffset > 0 ? ` (from offset ${safeOffset})` : '';
37
59
  const lines = [
38
- `**@${node_id} ${node.name}** — ${formatNumber(node.edge_count)} total references, showing ${edges.length}`,
60
+ `**@${node_id} ${node.name}** — ${formatNumber(node.edge_count)} total references${filterNote}, showing ${edges.length}${offsetNote}`,
39
61
  '',
40
62
  ];
41
63
  const headers = [
@@ -57,6 +79,13 @@ export function registerGetReferences(server) {
57
79
  formatBytes(e.toNode.retainedSize),
58
80
  ]);
59
81
  lines.push(markdownTable(headers, rows, rightCols));
82
+ const shownEnd = safeOffset + edges.length;
83
+ if (shownEnd < matched.length) {
84
+ lines.push('', `_${formatNumber(matched.length - shownEnd)} more — pass offset=${shownEnd} for the next page._`);
85
+ }
86
+ else if (edges.length === 0 && safeOffset > 0 && matched.length > 0) {
87
+ lines.push('', `_offset ${safeOffset} is past the last of ${formatNumber(matched.length)} matched references — use a smaller offset._`);
88
+ }
60
89
  return toolResult(lines.join('\n'));
61
90
  }
62
91
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"get-references.js","sourceRoot":"","sources":["../../src/tools/get-references.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-references.js","sourceRoot":"","sources":["../../src/tools/get-references.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"get-referrers.d.ts","sourceRoot":"","sources":["../../src/tools/get-referrers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAYvE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoE5D"}
1
+ {"version":3,"file":"get-referrers.d.ts","sourceRoot":"","sources":["../../src/tools/get-referrers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAYvE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoI5D"}
@@ -11,31 +11,53 @@ import { z } from 'zod';
11
11
  import { getSnapshot } from '../heap-state.js';
12
12
  import { formatBytes, formatNumber, markdownTable, truncateNodeName, errorResult, toolResult, } from '../utils.js';
13
13
  export function registerGetReferrers(server) {
14
- server.tool('memlab_get_referrers', 'Get incoming edges (referrers) to a heap node, sorted by source retained size. Shows what objects hold references to this node. Complements memlab_get_references (outgoing edges). Use memlab_retainer_trace to see the full GC root path.', {
14
+ server.tool('memlab_get_referrers', 'Get incoming edges (referrers) to a heap node, sorted by source retained size. Shows what objects hold references to this node. Supports edge_filter (match by edge name) and offset (pagination) so a widely-referenced singleton can be explored beyond the first page — e.g. "which referrers are NOT the dev-only Debug alias?". Complements memlab_get_references (outgoing edges). Use memlab_retainer_trace to see the full GC root path.', {
15
15
  node_id: z.number().describe('The numeric ID of the heap node'),
16
16
  limit: z
17
17
  .number()
18
18
  .optional()
19
19
  .default(30)
20
20
  .describe('Maximum number of referrers to return (default 30)'),
21
+ offset: z
22
+ .number()
23
+ .optional()
24
+ .default(0)
25
+ .describe('Number of (filtered, sorted) referrers to skip before returning — for paging past the first `limit` on widely-referenced nodes (default 0).'),
26
+ edge_filter: z
27
+ .string()
28
+ .optional()
29
+ .describe('Case-insensitive substring; only referrers whose edge name/index contains it are returned. Applied before sort + pagination, so you can isolate one referrer among hundreds instead of scanning the top-N.'),
21
30
  compact: z
22
31
  .boolean()
23
32
  .optional()
24
33
  .default(true)
25
34
  .describe('Truncate source names to 60 chars to save tokens (default true). Set to false to see full names.'),
26
- }, async ({ node_id, limit, compact }) => {
35
+ }, async ({ node_id, limit, offset, edge_filter, compact }) => {
27
36
  try {
28
37
  const snapshot = getSnapshot();
29
38
  const node = snapshot.getNodeById(node_id);
30
39
  if (!node) {
31
40
  return errorResult(`Node with id ${node_id} not found`);
32
41
  }
33
- const edges = node.referrers
42
+ // Treat an empty / whitespace-only filter as "no filter" so the header
43
+ // doesn't advertise a filter that matches every referrer, and clamp a
44
+ // negative offset to 0 rather than letting slice() read from the tail.
45
+ const activeFilter = edge_filter != null && edge_filter.trim() !== '' ? edge_filter : null;
46
+ const filterLc = activeFilter?.toLowerCase();
47
+ const safeOffset = Math.max(0, offset);
48
+ const matched = node.referrers
34
49
  .slice()
35
- .sort((a, b) => b.fromNode.retainedSize - a.fromNode.retainedSize)
36
- .slice(0, limit);
50
+ .filter(e => filterLc == null
51
+ ? true
52
+ : String(e.name_or_index).toLowerCase().includes(filterLc))
53
+ .sort((a, b) => b.fromNode.retainedSize - a.fromNode.retainedSize);
54
+ const edges = matched.slice(safeOffset, safeOffset + limit);
55
+ const filterNote = activeFilter != null
56
+ ? `, ${formatNumber(matched.length)} match "${activeFilter}"`
57
+ : '';
58
+ const offsetNote = safeOffset > 0 ? ` (from offset ${safeOffset})` : '';
37
59
  const lines = [
38
- `**@${node_id} ${node.name}** — ${formatNumber(node.numOfReferrers)} total referrers, showing ${edges.length}`,
60
+ `**@${node_id} ${node.name}** — ${formatNumber(node.numOfReferrers)} total referrers${filterNote}, showing ${edges.length}${offsetNote}`,
39
61
  '',
40
62
  ];
41
63
  const headers = [
@@ -57,6 +79,30 @@ export function registerGetReferrers(server) {
57
79
  formatBytes(e.fromNode.retainedSize),
58
80
  ]);
59
81
  lines.push(markdownTable(headers, rows, rightCols));
82
+ // A widely-referenced node often has a long tail of byte-identical
83
+ // referrers (e.g. hundreds of `(sliced string) / parent` edges into one
84
+ // big string). Listing them row by row is pure token cost, so summarise
85
+ // the shape of the whole matched set — including the rows past `limit`.
86
+ const groups = new Map();
87
+ for (const e of matched) {
88
+ const k = `${e.fromNode.name} (${e.fromNode.type}) / ${String(e.name_or_index)} / ${e.type}`;
89
+ groups.set(k, (groups.get(k) ?? 0) + 1);
90
+ }
91
+ if (groups.size > 0 && groups.size < matched.length) {
92
+ const summary = [...groups.entries()]
93
+ .sort((a, b) => b[1] - a[1])
94
+ .slice(0, 6)
95
+ .map(([k, n]) => `${formatNumber(n)}× ${k}`)
96
+ .join(' · ');
97
+ lines.push('', `_Referrer shapes (all ${formatNumber(matched.length)} matched, not just the rows above): ${summary}${groups.size > 6 ? `, +${formatNumber(groups.size - 6)} more shapes` : ''}._`);
98
+ }
99
+ const shownEnd = safeOffset + edges.length;
100
+ if (shownEnd < matched.length) {
101
+ lines.push('', `_${formatNumber(matched.length - shownEnd)} more — pass offset=${shownEnd} for the next page._`);
102
+ }
103
+ else if (edges.length === 0 && safeOffset > 0 && matched.length > 0) {
104
+ lines.push('', `_offset ${safeOffset} is past the last of ${formatNumber(matched.length)} matched referrers — use a smaller offset._`);
105
+ }
60
106
  return toolResult(lines.join('\n'));
61
107
  }
62
108
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"get-referrers.js","sourceRoot":"","sources":["../../src/tools/get-referrers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-referrers.js","sourceRoot":"","sources":["../../src/tools/get-referrers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
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 { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ export declare function registerHuntReport(server: McpServer): void;
12
+ //# sourceMappingURL=hunt-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hunt-report.d.ts","sourceRoot":"","sources":["../../src/tools/hunt-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAoFvE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0L1D"}