@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.
- package/README.md +18 -14
- package/bin/.eslintrc.js +26 -0
- package/bin/memlab-cli.js +313 -0
- package/dist/artifact-classes.d.ts +86 -0
- package/dist/artifact-classes.d.ts.map +1 -0
- package/dist/artifact-classes.js +261 -0
- package/dist/artifact-classes.js.map +1 -0
- package/dist/capture-mode.d.ts +60 -0
- package/dist/capture-mode.d.ts.map +1 -0
- package/dist/capture-mode.js +39 -0
- package/dist/capture-mode.js.map +1 -0
- package/dist/guardrail.d.ts.map +1 -1
- package/dist/guardrail.js +13 -0
- package/dist/guardrail.js.map +1 -1
- package/dist/heap-state.d.ts +96 -2
- package/dist/heap-state.d.ts.map +1 -1
- package/dist/heap-state.js +197 -2
- package/dist/heap-state.js.map +1 -1
- package/dist/index.js +41 -1
- package/dist/index.js.map +1 -1
- package/dist/progress.d.ts +25 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +46 -0
- package/dist/progress.js.map +1 -0
- package/dist/result-handles.d.ts +11 -0
- package/dist/result-handles.d.ts.map +1 -0
- package/dist/result-handles.js +77 -0
- package/dist/result-handles.js.map +1 -0
- package/dist/string-index.d.ts +55 -0
- package/dist/string-index.d.ts.map +1 -0
- package/dist/string-index.js +91 -0
- package/dist/string-index.js.map +1 -0
- package/dist/tool-registry.d.ts +42 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +20 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tools/analyze-run.d.ts +12 -0
- package/dist/tools/analyze-run.d.ts.map +1 -0
- package/dist/tools/analyze-run.js +343 -0
- package/dist/tools/analyze-run.js.map +1 -0
- package/dist/tools/app-heap.d.ts +12 -0
- package/dist/tools/app-heap.d.ts.map +1 -0
- package/dist/tools/app-heap.js +140 -0
- package/dist/tools/app-heap.js.map +1 -0
- package/dist/tools/auto-investigate.d.ts.map +1 -1
- package/dist/tools/auto-investigate.js +91 -49
- package/dist/tools/auto-investigate.js.map +1 -1
- package/dist/tools/batch.d.ts +12 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +168 -0
- package/dist/tools/batch.js.map +1 -0
- package/dist/tools/cache-analysis.d.ts.map +1 -1
- package/dist/tools/cache-analysis.js +156 -5
- package/dist/tools/cache-analysis.js.map +1 -1
- package/dist/tools/class-histogram.d.ts.map +1 -1
- package/dist/tools/class-histogram.js +14 -3
- package/dist/tools/class-histogram.js.map +1 -1
- package/dist/tools/collection-trend.d.ts +55 -0
- package/dist/tools/collection-trend.d.ts.map +1 -0
- package/dist/tools/collection-trend.js +315 -0
- package/dist/tools/collection-trend.js.map +1 -0
- package/dist/tools/detached-dom.d.ts +2 -0
- package/dist/tools/detached-dom.d.ts.map +1 -1
- package/dist/tools/detached-dom.js +291 -20
- package/dist/tools/detached-dom.js.map +1 -1
- package/dist/tools/dev-artifacts.d.ts +62 -6
- package/dist/tools/dev-artifacts.d.ts.map +1 -1
- package/dist/tools/dev-artifacts.js +466 -23
- package/dist/tools/dev-artifacts.js.map +1 -1
- package/dist/tools/diff-snapshots.d.ts.map +1 -1
- package/dist/tools/diff-snapshots.js +101 -44
- package/dist/tools/diff-snapshots.js.map +1 -1
- package/dist/tools/dominator-attribution.d.ts +12 -0
- package/dist/tools/dominator-attribution.d.ts.map +1 -0
- package/dist/tools/dominator-attribution.js +189 -0
- package/dist/tools/dominator-attribution.js.map +1 -0
- package/dist/tools/dominator-chain.d.ts +12 -0
- package/dist/tools/dominator-chain.d.ts.map +1 -0
- package/dist/tools/dominator-chain.js +92 -0
- package/dist/tools/dominator-chain.js.map +1 -0
- package/dist/tools/duplicate-objects.d.ts +12 -0
- package/dist/tools/duplicate-objects.d.ts.map +1 -0
- package/dist/tools/duplicate-objects.js +172 -0
- package/dist/tools/duplicate-objects.js.map +1 -0
- package/dist/tools/duplicated-strings.d.ts.map +1 -1
- package/dist/tools/duplicated-strings.js +46 -38
- package/dist/tools/duplicated-strings.js.map +1 -1
- package/dist/tools/eval.d.ts +1 -0
- package/dist/tools/eval.d.ts.map +1 -1
- package/dist/tools/eval.js +787 -30
- package/dist/tools/eval.js.map +1 -1
- package/dist/tools/explain-delta.d.ts +12 -0
- package/dist/tools/explain-delta.d.ts.map +1 -0
- package/dist/tools/explain-delta.js +170 -0
- package/dist/tools/explain-delta.js.map +1 -0
- package/dist/tools/find-nodes-by-class.d.ts.map +1 -1
- package/dist/tools/find-nodes-by-class.js +112 -13
- package/dist/tools/find-nodes-by-class.js.map +1 -1
- package/dist/tools/finding-index.d.ts +22 -0
- package/dist/tools/finding-index.d.ts.map +1 -0
- package/dist/tools/finding-index.js +247 -0
- package/dist/tools/finding-index.js.map +1 -0
- package/dist/tools/for-each.d.ts.map +1 -1
- package/dist/tools/for-each.js +15 -3
- package/dist/tools/for-each.js.map +1 -1
- package/dist/tools/get-references.d.ts.map +1 -1
- package/dist/tools/get-references.js +35 -6
- package/dist/tools/get-references.js.map +1 -1
- package/dist/tools/get-referrers.d.ts.map +1 -1
- package/dist/tools/get-referrers.js +52 -6
- package/dist/tools/get-referrers.js.map +1 -1
- package/dist/tools/hunt-report.d.ts +12 -0
- package/dist/tools/hunt-report.d.ts.map +1 -0
- package/dist/tools/hunt-report.js +186 -0
- package/dist/tools/hunt-report.js.map +1 -0
- package/dist/tools/hypothesis.d.ts +12 -0
- package/dist/tools/hypothesis.d.ts.map +1 -0
- package/dist/tools/hypothesis.js +221 -0
- package/dist/tools/hypothesis.js.map +1 -0
- package/dist/tools/intern-opportunities.d.ts.map +1 -1
- package/dist/tools/intern-opportunities.js +721 -75
- package/dist/tools/intern-opportunities.js.map +1 -1
- package/dist/tools/ladder.d.ts +33 -0
- package/dist/tools/ladder.d.ts.map +1 -0
- package/dist/tools/ladder.js +266 -0
- package/dist/tools/ladder.js.map +1 -0
- package/dist/tools/largest-objects.d.ts.map +1 -1
- package/dist/tools/largest-objects.js +43 -16
- package/dist/tools/largest-objects.js.map +1 -1
- package/dist/tools/leak-report.d.ts +12 -0
- package/dist/tools/leak-report.d.ts.map +1 -0
- package/dist/tools/leak-report.js +256 -0
- package/dist/tools/leak-report.js.map +1 -0
- package/dist/tools/load-snapshot.d.ts +78 -0
- package/dist/tools/load-snapshot.d.ts.map +1 -1
- package/dist/tools/load-snapshot.js +519 -29
- package/dist/tools/load-snapshot.js.map +1 -1
- package/dist/tools/map-entries.d.ts +12 -0
- package/dist/tools/map-entries.d.ts.map +1 -0
- package/dist/tools/map-entries.js +139 -0
- package/dist/tools/map-entries.js.map +1 -0
- package/dist/tools/match-object.d.ts +12 -0
- package/dist/tools/match-object.d.ts.map +1 -0
- package/dist/tools/match-object.js +165 -0
- package/dist/tools/match-object.js.map +1 -0
- package/dist/tools/object-shape.d.ts.map +1 -1
- package/dist/tools/object-shape.js +92 -30
- package/dist/tools/object-shape.js.map +1 -1
- package/dist/tools/population-diff.d.ts +57 -0
- package/dist/tools/population-diff.d.ts.map +1 -0
- package/dist/tools/population-diff.js +338 -0
- package/dist/tools/population-diff.js.map +1 -0
- package/dist/tools/quick-diagnosis.d.ts.map +1 -1
- package/dist/tools/quick-diagnosis.js +12 -4
- package/dist/tools/quick-diagnosis.js.map +1 -1
- package/dist/tools/retainer-layers.d.ts +23 -0
- package/dist/tools/retainer-layers.d.ts.map +1 -0
- package/dist/tools/retainer-layers.js +179 -0
- package/dist/tools/retainer-layers.js.map +1 -0
- package/dist/tools/retainer-summary.d.ts +1 -0
- package/dist/tools/retainer-summary.d.ts.map +1 -1
- package/dist/tools/retainer-summary.js +128 -32
- package/dist/tools/retainer-summary.js.map +1 -1
- package/dist/tools/retainer-trace.d.ts.map +1 -1
- package/dist/tools/retainer-trace.js +105 -25
- package/dist/tools/retainer-trace.js.map +1 -1
- package/dist/tools/search-nodes.d.ts.map +1 -1
- package/dist/tools/search-nodes.js +5 -1
- package/dist/tools/search-nodes.js.map +1 -1
- package/dist/tools/search-strings.d.ts.map +1 -1
- package/dist/tools/search-strings.js +53 -7
- package/dist/tools/search-strings.js.map +1 -1
- package/dist/tools/sequence-analysis.d.ts +49 -0
- package/dist/tools/sequence-analysis.d.ts.map +1 -1
- package/dist/tools/sequence-analysis.js +268 -78
- package/dist/tools/sequence-analysis.js.map +1 -1
- package/dist/tools/shape-histogram.d.ts.map +1 -1
- package/dist/tools/shape-histogram.js +9 -2
- package/dist/tools/shape-histogram.js.map +1 -1
- package/dist/tools/sliced-strings.d.ts.map +1 -1
- package/dist/tools/sliced-strings.js +22 -4
- package/dist/tools/sliced-strings.js.map +1 -1
- package/dist/tools/snapshot-header.d.ts +28 -0
- package/dist/tools/snapshot-header.d.ts.map +1 -0
- package/dist/tools/snapshot-header.js +111 -0
- package/dist/tools/snapshot-header.js.map +1 -0
- package/dist/tools/string-patterns.d.ts.map +1 -1
- package/dist/tools/string-patterns.js +5 -4
- package/dist/tools/string-patterns.js.map +1 -1
- package/dist/tools/tools-index.d.ts +12 -0
- package/dist/tools/tools-index.d.ts.map +1 -0
- package/dist/tools/tools-index.js +342 -0
- package/dist/tools/tools-index.js.map +1 -0
- package/dist/tools/verify-fix.d.ts +23 -0
- package/dist/tools/verify-fix.d.ts.map +1 -0
- package/dist/tools/verify-fix.js +211 -0
- package/dist/tools/verify-fix.js.map +1 -0
- package/dist/tools/weakmap-entries.d.ts.map +1 -1
- package/dist/tools/weakmap-entries.js +6 -1
- package/dist/tools/weakmap-entries.js.map +1 -1
- package/dist/utils.d.ts +204 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +478 -8
- package/dist/utils.js.map +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall memory_lab
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import { formatNumber, markdownTable, errorResult, toolResult, } from '../utils.js';
|
|
13
|
+
/**
|
|
14
|
+
* Render a hunt's `run.json` into the report the skill prescribes.
|
|
15
|
+
*
|
|
16
|
+
* The report was assembled by hand every time, including re-deriving per-cycle
|
|
17
|
+
* rates from the heartbeat log — which is both slow and the step where a caveat
|
|
18
|
+
* quietly fails to make it into the writeup. Everything the report needs is
|
|
19
|
+
* already in the manifest the runner writes; this is the mechanical half.
|
|
20
|
+
*
|
|
21
|
+
* The parts that matter most are the ones a hand-written report tends to drop:
|
|
22
|
+
* the rung table with its per-cycle rate, the off-heap series (the documented
|
|
23
|
+
* real OOM causes are invisible to a heap snapshot), and the caveats — an
|
|
24
|
+
* under-seeded or under-fired run is still worth reporting, but only if it says
|
|
25
|
+
* so.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* A number field read from an untrusted manifest.
|
|
29
|
+
*
|
|
30
|
+
* `run.json` is JSON.parse of a file this tool does not own: it may come from an
|
|
31
|
+
* older manifest_version, or from a run the lease killed mid-rung. Calling
|
|
32
|
+
* `.toFixed()` on a missing field throws — crashing report generation for
|
|
33
|
+
* precisely the aborted run the tool exists to salvage.
|
|
34
|
+
*/
|
|
35
|
+
function num(value, digits, suffix = '') {
|
|
36
|
+
return typeof value === 'number' && Number.isFinite(value)
|
|
37
|
+
? `${value.toFixed(digits)}${suffix}`
|
|
38
|
+
: '—';
|
|
39
|
+
}
|
|
40
|
+
function comboTable(log) {
|
|
41
|
+
const per = new Map();
|
|
42
|
+
for (const entry of log) {
|
|
43
|
+
if (entry == null || typeof entry.combo !== 'string')
|
|
44
|
+
continue;
|
|
45
|
+
const e = per.get(entry.combo) ?? { ok: 0, fail: 0 };
|
|
46
|
+
if (entry.ok)
|
|
47
|
+
e.ok++;
|
|
48
|
+
else
|
|
49
|
+
e.fail++;
|
|
50
|
+
per.set(entry.combo, e);
|
|
51
|
+
}
|
|
52
|
+
if (per.size === 0)
|
|
53
|
+
return '_No interaction log recorded._';
|
|
54
|
+
return markdownTable(['Combo', 'Landed', 'Missed', 'Land rate'], [...per.entries()].map(([name, v]) => {
|
|
55
|
+
const total = v.ok + v.fail;
|
|
56
|
+
return [
|
|
57
|
+
name,
|
|
58
|
+
formatNumber(v.ok),
|
|
59
|
+
formatNumber(v.fail),
|
|
60
|
+
total > 0 ? `${((v.ok / total) * 100).toFixed(0)}%` : '—',
|
|
61
|
+
];
|
|
62
|
+
}), new Set([1, 2, 3]));
|
|
63
|
+
}
|
|
64
|
+
export function registerHuntReport(server) {
|
|
65
|
+
server.tool('memlab_hunt_report', "Render a leak hunt's run.json into the prescribed report: configuration, the rung ladder with per-cycle rates, per-combo land rates, the off-heap series, caveats and the stop reason. " +
|
|
66
|
+
'The report was hand-assembled on every round, including re-deriving per-cycle rates from the heartbeat log — slow, and the step where a caveat quietly fails to reach the writeup. An under-fired or under-seeded run is still worth reporting, but only if it says so, which is why caveats and land rates are rendered first-class rather than left to memory. ' +
|
|
67
|
+
'Takes the manifest written by the hunt runner; pair with memlab_leak_report for the analysis half and memlab_finding_index to label each finding NEW or KNOWN.', {
|
|
68
|
+
run_json: z
|
|
69
|
+
.string()
|
|
70
|
+
.describe('Path to the run.json written by the hunt runner.'),
|
|
71
|
+
include_interaction_log: z
|
|
72
|
+
.boolean()
|
|
73
|
+
.optional()
|
|
74
|
+
.default(false)
|
|
75
|
+
.describe('Append the raw ordered interaction log (default false: the per-combo summary is what a reader acts on).'),
|
|
76
|
+
}, async ({ run_json, include_interaction_log }) => {
|
|
77
|
+
try {
|
|
78
|
+
if (!fs.existsSync(run_json)) {
|
|
79
|
+
return errorResult(`No manifest at ${run_json}. The hunt runner writes run.json into its --outdir after every rung, so an aborted run still has one.`);
|
|
80
|
+
}
|
|
81
|
+
let manifest;
|
|
82
|
+
try {
|
|
83
|
+
manifest = JSON.parse(fs.readFileSync(run_json, 'utf8'));
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
return errorResult(`${run_json} is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
87
|
+
}
|
|
88
|
+
const rungs = manifest.rungs ?? [];
|
|
89
|
+
const totals = manifest.totals ?? {};
|
|
90
|
+
const cycles = totals.cycles ?? 0;
|
|
91
|
+
const elapsed = manifest.elapsed_s ?? 0;
|
|
92
|
+
const cfg = manifest.config ?? {};
|
|
93
|
+
const lines = [
|
|
94
|
+
`# Leak hunt report — ${manifest.run_id ?? 'unnamed run'}`,
|
|
95
|
+
'',
|
|
96
|
+
'## 1. Configuration',
|
|
97
|
+
'',
|
|
98
|
+
markdownTable(['Setting', 'Value'], Object.entries(cfg).map(([k, v]) => [
|
|
99
|
+
k,
|
|
100
|
+
Array.isArray(v) ? v.join(', ') : String(v ?? '—'),
|
|
101
|
+
])),
|
|
102
|
+
'',
|
|
103
|
+
'## 2. What was driven',
|
|
104
|
+
'',
|
|
105
|
+
`${formatNumber(cycles)} cycles in ${(elapsed / 60).toFixed(1)} min ` +
|
|
106
|
+
`(${formatNumber(totals.ok ?? 0)} landed, ${formatNumber(totals.fail ?? 0)} missed` +
|
|
107
|
+
`${cycles > 0 ? `, ${(elapsed / cycles).toFixed(2)}s/cycle` : ''}). ` +
|
|
108
|
+
`Stopped because: **${manifest.stop_reason ?? 'unknown'}**.`,
|
|
109
|
+
'',
|
|
110
|
+
comboTable(manifest.interaction_log ?? []),
|
|
111
|
+
'',
|
|
112
|
+
'## 3. Rung ladder',
|
|
113
|
+
'',
|
|
114
|
+
];
|
|
115
|
+
if (rungs.length === 0) {
|
|
116
|
+
lines.push('_No rungs captured — there is nothing to analyze._');
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const first = rungs[0];
|
|
120
|
+
const last = rungs[rungs.length - 1];
|
|
121
|
+
lines.push(markdownTable(['#', 'Cycles', 'Post-GC heap', 'Elapsed', 'Trigger', 'Snapshot'], rungs.map(r => [
|
|
122
|
+
String(r.index ?? '—'),
|
|
123
|
+
typeof r.cycles === 'number' ? formatNumber(r.cycles) : '—',
|
|
124
|
+
num(r.post_gc_heap_mb, 1, ' MB'),
|
|
125
|
+
num(typeof r.elapsed_s === 'number'
|
|
126
|
+
? r.elapsed_s / 60
|
|
127
|
+
: undefined, 1, ' min'),
|
|
128
|
+
r.reason ?? '—',
|
|
129
|
+
(r.path ?? '').split('/').pop() || '—',
|
|
130
|
+
]), new Set([1, 2, 3])), '');
|
|
131
|
+
const haveHeap = typeof first.post_gc_heap_mb === 'number' &&
|
|
132
|
+
typeof last.post_gc_heap_mb === 'number';
|
|
133
|
+
const deltaMb = haveHeap
|
|
134
|
+
? last.post_gc_heap_mb - first.post_gc_heap_mb
|
|
135
|
+
: 0;
|
|
136
|
+
const deltaCycles = (last.cycles ?? 0) - (first.cycles ?? 0);
|
|
137
|
+
lines.push((haveHeap
|
|
138
|
+
? `Post-GC heap moved **${deltaMb >= 0 ? '+' : ''}${deltaMb.toFixed(1)} MB** across `
|
|
139
|
+
: 'Post-GC heap is not recorded in this manifest; cycles measured across ') +
|
|
140
|
+
`${formatNumber(deltaCycles)} cycles` +
|
|
141
|
+
(deltaCycles > 0
|
|
142
|
+
? ` (${((deltaMb * 1024) / deltaCycles).toFixed(1)} KB/cycle)`
|
|
143
|
+
: '') +
|
|
144
|
+
'.', '', '_Aggregate heap is context, not a verdict: a measured round found a real leak while this number FELL. Judge by the per-class trend from `memlab_leak_report`._', '');
|
|
145
|
+
if (rungs.length < 3) {
|
|
146
|
+
lines.push(`> ⚠️ Only ${rungs.length} rung(s). With fewer than 3, "grew at every step" is not distinguishable from a single GC-band sample; treat any trend below as unconfirmed.`, '');
|
|
147
|
+
}
|
|
148
|
+
const offHeapRows = rungs
|
|
149
|
+
.filter(r => r.off_heap && Object.keys(r.off_heap).length > 0)
|
|
150
|
+
.map(r => [
|
|
151
|
+
String(r.index ?? '—'),
|
|
152
|
+
String(r.off_heap?.storage_usage_mb ?? '—'),
|
|
153
|
+
String(r.off_heap?.js_heap_mb ?? '—'),
|
|
154
|
+
String(r.off_heap?.longtasks ?? '—'),
|
|
155
|
+
// every cell must be a string: markdownTable pads them, so a
|
|
156
|
+
// single undefined from a partial manifest throws
|
|
157
|
+
]);
|
|
158
|
+
if (offHeapRows.length > 0) {
|
|
159
|
+
lines.push('## 4. Off-heap series', '', '_The documented real OOM causes — IndexedDB, decoded media, WASM — are invisible to a heap snapshot. These are sampled per rung so the blind spot is at least tracked._', '', markdownTable(['Rung', 'Storage (MB)', 'JS heap (MB)', 'Longtasks'], offHeapRows, new Set([1, 2, 3])), '');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const caveats = manifest.caveats ?? [];
|
|
163
|
+
lines.push('## 5. Caveats', '');
|
|
164
|
+
if (caveats.length === 0) {
|
|
165
|
+
lines.push('_None recorded._');
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
for (const c of caveats)
|
|
169
|
+
lines.push(`- ⚠️ ${c}`);
|
|
170
|
+
lines.push('', '_Caveats are part of the finding, not a footnote: an under-fired or under-seeded run can look exactly like an app that does not leak._');
|
|
171
|
+
}
|
|
172
|
+
if (include_interaction_log) {
|
|
173
|
+
const log = manifest.interaction_log ?? [];
|
|
174
|
+
lines.push('', '## Appendix — interaction log', '', '```', ...log
|
|
175
|
+
.slice(0, 200)
|
|
176
|
+
.map(e => `${e.i}\t${e.combo}\t${e.ok ? 'ok' : 'miss'}`), log.length > 200 ? `… ${formatNumber(log.length - 200)} more` : '', '```');
|
|
177
|
+
}
|
|
178
|
+
lines.push('', '---', '', '**Next:** run `memlab_leak_report` over the rung paths above for the per-class trend, then `memlab_finding_index({action: "check"})` on each candidate before writing it up — a round that re-reports a known leak costs as much as one that finds nothing.');
|
|
179
|
+
return toolResult(lines.join('\n'));
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
return errorResult(err);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=hunt-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hunt-report.js","sourceRoot":"","sources":["../../src/tools/hunt-report.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 registerHypothesis(server: McpServer): void;
|
|
12
|
+
//# sourceMappingURL=hypothesis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hypothesis.d.ts","sourceRoot":"","sources":["../../src/tools/hypothesis.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAiDvE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4N1D"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @format
|
|
8
|
+
* @oncall memory_lab
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import vm from 'vm';
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import memlabHeapAnalysis from '@memlab/heap-analysis';
|
|
14
|
+
const { getFullHeapFromFile } = memlabHeapAnalysis;
|
|
15
|
+
import { resolveSnapshotPath } from './load-snapshot.js';
|
|
16
|
+
import { resolveLadderPaths } from './ladder.js';
|
|
17
|
+
import { formatBytes, formatNumber, markdownTable, errorResult, toolResult, } from '../utils.js';
|
|
18
|
+
// Property names used to fingerprint a shape, matching the other shape tools.
|
|
19
|
+
const SHAPE_PROP_CAP = 12;
|
|
20
|
+
// Shapes tracked per rung. Once this many distinct shapes are seen, tracking
|
|
21
|
+
// STOPS and the tail is uncounted (not folded into an "(other)" bucket) — the
|
|
22
|
+
// report says so explicitly. A heap with a million distinct shapes must not turn
|
|
23
|
+
// this into a memory problem of its own.
|
|
24
|
+
const MAX_SHAPES = 2000;
|
|
25
|
+
function shapeKey(node) {
|
|
26
|
+
if (node.edge_count > 1024)
|
|
27
|
+
return `${node.name} (too wide)`;
|
|
28
|
+
const props = [];
|
|
29
|
+
node.forEachReference(edge => {
|
|
30
|
+
if (edge.type === 'property') {
|
|
31
|
+
props.push(String(edge.name_or_index));
|
|
32
|
+
if (props.length >= SHAPE_PROP_CAP)
|
|
33
|
+
return { stop: true };
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
props.sort();
|
|
37
|
+
return `${node.name} {${props.join(',')}}`;
|
|
38
|
+
}
|
|
39
|
+
function trendOf(counts) {
|
|
40
|
+
let up = true;
|
|
41
|
+
for (let i = 1; i < counts.length; i++) {
|
|
42
|
+
if (counts[i] <= counts[i - 1])
|
|
43
|
+
up = false;
|
|
44
|
+
}
|
|
45
|
+
const net = counts[counts.length - 1] - counts[0];
|
|
46
|
+
if (up && net > 0)
|
|
47
|
+
return '↑ every step';
|
|
48
|
+
if (net > 0)
|
|
49
|
+
return 'grew net';
|
|
50
|
+
if (net < 0)
|
|
51
|
+
return 'shrank';
|
|
52
|
+
return 'flat';
|
|
53
|
+
}
|
|
54
|
+
export function registerHypothesis(server) {
|
|
55
|
+
server.tool('memlab_hypothesis', 'Test one hypothesis against EVERY rung of a snapshot ladder in a single call: supply a JavaScript predicate over heap nodes and get its match count, total self size, and trend per rung. ' +
|
|
56
|
+
'This is the "is my theory true across the whole ladder?" tool. Without it, confirming a specific theory — "the growth is Maps with a `_pending` field", "it is closures capturing `chatId`" — meant loading each rung separately and re-running a query by hand, at minutes per rung, which is why theories tended to be checked against one snapshot and generalized. ' +
|
|
57
|
+
'Set group_by_shape to break matches down by property shape per rung instead of a single count, which answers "WHICH variant of this class is the one accumulating?" — the shape sweep that otherwise required a separate pass. Snapshots are loaded one at a time and released, so a long ladder is memory-safe.', {
|
|
58
|
+
paths: z
|
|
59
|
+
.array(z.string())
|
|
60
|
+
.min(1)
|
|
61
|
+
.describe('Ordered snapshot paths (oldest first). Local paths, manifold:// URLs, bare filenames, or a single ["ladder:<name>"] reference to a ladder saved with memlab_ladder.'),
|
|
62
|
+
predicate: z
|
|
63
|
+
.string()
|
|
64
|
+
.describe('JavaScript expression over `node` returning a boolean, e.g. `node.name === "Map" && node.retainedSize > 10000`, or `node.type === "closure" && node.name.includes("chat")`. Evaluated in a sandbox with no I/O; only the node is exposed. Compiled once and applied per node, so keep it cheap — avoid walking `node.references` for every node in a multi-million-node heap.'),
|
|
65
|
+
group_by_shape: z
|
|
66
|
+
.boolean()
|
|
67
|
+
.optional()
|
|
68
|
+
.default(false)
|
|
69
|
+
.describe('Break matches down by property-shape fingerprint per rung (default false: one count per rung). Use to find which variant of a class is accumulating.'),
|
|
70
|
+
limit: z
|
|
71
|
+
.number()
|
|
72
|
+
.optional()
|
|
73
|
+
.default(15)
|
|
74
|
+
.describe('Maximum shape rows to report when group_by_shape is set.'),
|
|
75
|
+
max_file_size_mb: z
|
|
76
|
+
.number()
|
|
77
|
+
.optional()
|
|
78
|
+
.describe('Per-file size ceiling in MB; see memlab_load_snapshot.'),
|
|
79
|
+
}, async ({ paths, predicate, group_by_shape, limit, max_file_size_mb }) => {
|
|
80
|
+
try {
|
|
81
|
+
let test;
|
|
82
|
+
try {
|
|
83
|
+
// Compiled ONCE, in a context with nothing in it: the predicate gets
|
|
84
|
+
// the node it is called with and no ambient capability.
|
|
85
|
+
test = vm.runInNewContext(`(function(node){ return !!(${predicate}); })`, Object.create(null), { timeout: 1000 });
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
return errorResult(`Could not compile predicate: ${e instanceof Error ? e.message : String(e)}. It must be a JavaScript EXPRESSION over \`node\` (no statements, no return).`);
|
|
89
|
+
}
|
|
90
|
+
const rungs = [];
|
|
91
|
+
const { paths: rungPaths } = resolveLadderPaths(paths);
|
|
92
|
+
for (const p of rungPaths) {
|
|
93
|
+
const { localPath, fetchedFrom } = resolveSnapshotPath(p);
|
|
94
|
+
if (!fs.existsSync(localPath)) {
|
|
95
|
+
return errorResult(`File not found: ${localPath}`);
|
|
96
|
+
}
|
|
97
|
+
const sizeMB = fs.statSync(localPath).size / (1024 * 1024);
|
|
98
|
+
if (max_file_size_mb != null && sizeMB > max_file_size_mb) {
|
|
99
|
+
return errorResult(`${p} is ${sizeMB.toFixed(0)} MB, over the ${max_file_size_mb} MB limit.`);
|
|
100
|
+
}
|
|
101
|
+
const snapshot = await getFullHeapFromFile(localPath);
|
|
102
|
+
let matched = 0;
|
|
103
|
+
let selfBytes = 0;
|
|
104
|
+
let scanned = 0;
|
|
105
|
+
let predicateError = null;
|
|
106
|
+
// memlab's nodes.forEach has no early exit, so a predicate that throws
|
|
107
|
+
// on the first node would otherwise still walk every remaining node in
|
|
108
|
+
// a multi-million-node heap before the error is reported. Throwing a
|
|
109
|
+
// sentinel out of the callback actually stops the walk.
|
|
110
|
+
class AbortWalk extends Error {
|
|
111
|
+
}
|
|
112
|
+
const shapes = new Map();
|
|
113
|
+
try {
|
|
114
|
+
snapshot.nodes.forEach(node => {
|
|
115
|
+
scanned++;
|
|
116
|
+
let hit = false;
|
|
117
|
+
try {
|
|
118
|
+
hit = test(node);
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
// Report the predicate's own failure rather than a silent zero:
|
|
122
|
+
// a predicate that throws on the first node would otherwise look
|
|
123
|
+
// exactly like a hypothesis that is simply false.
|
|
124
|
+
predicateError = e instanceof Error ? e.message : String(e);
|
|
125
|
+
throw new AbortWalk();
|
|
126
|
+
}
|
|
127
|
+
if (!hit)
|
|
128
|
+
return;
|
|
129
|
+
matched++;
|
|
130
|
+
selfBytes += node.self_size;
|
|
131
|
+
if (group_by_shape && shapes.size < MAX_SHAPES) {
|
|
132
|
+
const k = shapeKey(node);
|
|
133
|
+
shapes.set(k, (shapes.get(k) ?? 0) + 1);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
catch (e) {
|
|
138
|
+
if (!(e instanceof AbortWalk))
|
|
139
|
+
throw e;
|
|
140
|
+
}
|
|
141
|
+
if (predicateError != null) {
|
|
142
|
+
return errorResult(`Predicate threw while scanning ${p}: ${predicateError}. Guard against missing fields — it is applied to every node in the heap, not just the ones you have in mind.`);
|
|
143
|
+
}
|
|
144
|
+
rungs.push({
|
|
145
|
+
label: fetchedFrom ?? p.replace(/^.*\//, ''),
|
|
146
|
+
matched,
|
|
147
|
+
selfBytes,
|
|
148
|
+
scanned,
|
|
149
|
+
shapes,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const counts = rungs.map(r => r.matched);
|
|
153
|
+
const net = counts[counts.length - 1] - counts[0];
|
|
154
|
+
const lines = [
|
|
155
|
+
`## Hypothesis across ${rungs.length} snapshot(s)`,
|
|
156
|
+
'',
|
|
157
|
+
`\`${predicate}\``,
|
|
158
|
+
'',
|
|
159
|
+
markdownTable(['#', 'Snapshot', 'Matches', 'Self size', 'Scanned'], rungs.map((r, i) => [
|
|
160
|
+
String(i + 1),
|
|
161
|
+
r.label.length > 38 ? '…' + r.label.slice(-37) : r.label,
|
|
162
|
+
formatNumber(r.matched),
|
|
163
|
+
formatBytes(r.selfBytes),
|
|
164
|
+
formatNumber(r.scanned),
|
|
165
|
+
]), new Set([2, 3, 4])),
|
|
166
|
+
'',
|
|
167
|
+
];
|
|
168
|
+
if (rungs.length > 1) {
|
|
169
|
+
lines.push(`**Verdict: ${trendOf(counts)}** — ${net >= 0 ? '+' : '−'}${formatNumber(Math.abs(net))} matches across the ladder (${formatNumber(counts[0])} → ${formatNumber(counts[counts.length - 1])}).`);
|
|
170
|
+
if (rungs.length === 2) {
|
|
171
|
+
lines.push('', '> ⚠️ With 2 rungs "↑ every step" is the same statement as "grew overall" and cannot separate a trend from a single GC-band sample. Add a third rung.');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
lines.push('_Single snapshot: this is a count, not a trend. Pass an ordered ladder to test whether the hypothesis holds over time._');
|
|
176
|
+
}
|
|
177
|
+
if (counts.every(c => c === 0)) {
|
|
178
|
+
lines.push('', '_Zero matches in every rung. The predicate compiled and ran against every node, so this is a real negative — the hypothesis is false as written, or the property/class is named differently than assumed (check with `memlab_class_histogram`)._');
|
|
179
|
+
}
|
|
180
|
+
if (group_by_shape) {
|
|
181
|
+
const allShapes = new Set();
|
|
182
|
+
for (const r of rungs)
|
|
183
|
+
for (const k of r.shapes.keys())
|
|
184
|
+
allShapes.add(k);
|
|
185
|
+
const shapeRows = [...allShapes]
|
|
186
|
+
.map(k => ({
|
|
187
|
+
shape: k,
|
|
188
|
+
per: rungs.map(r => r.shapes.get(k) ?? 0),
|
|
189
|
+
}))
|
|
190
|
+
.map(x => ({
|
|
191
|
+
...x,
|
|
192
|
+
net: x.per[x.per.length - 1] - x.per[0],
|
|
193
|
+
}))
|
|
194
|
+
.sort((a, b) => b.net - a.net ||
|
|
195
|
+
b.per[b.per.length - 1] - a.per[a.per.length - 1])
|
|
196
|
+
.slice(0, limit);
|
|
197
|
+
if (shapeRows.length > 0) {
|
|
198
|
+
lines.push('', '### Matches by shape', '', markdownTable([
|
|
199
|
+
'Shape',
|
|
200
|
+
...rungs.map((_, i) => `#${i + 1}`),
|
|
201
|
+
'Δ',
|
|
202
|
+
...(rungs.length > 1 ? ['Trend'] : []),
|
|
203
|
+
], shapeRows.map(r => [
|
|
204
|
+
r.shape.length > 56 ? r.shape.slice(0, 53) + '…}' : r.shape,
|
|
205
|
+
...r.per.map(c => formatNumber(c)),
|
|
206
|
+
`${r.net >= 0 ? '+' : '−'}${formatNumber(Math.abs(r.net))}`,
|
|
207
|
+
...(rungs.length > 1 ? [trendOf(r.per)] : []),
|
|
208
|
+
]), new Set(rungs.map((_, i) => i + 1).concat([rungs.length + 1]))));
|
|
209
|
+
if (rungs.some(r => r.shapes.size >= MAX_SHAPES)) {
|
|
210
|
+
lines.push('', `_⚠ Shape tracking capped at ${formatNumber(MAX_SHAPES)} distinct shapes per rung; the tail is not counted. Narrow the predicate._`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return toolResult(lines.join('\n'));
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
return errorResult(err);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=hypothesis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hypothesis.js","sourceRoot":"","sources":["../../src/tools/hypothesis.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intern-opportunities.d.ts","sourceRoot":"","sources":["../../src/tools/intern-opportunities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"intern-opportunities.d.ts","sourceRoot":"","sources":["../../src/tools/intern-opportunities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAmPvE,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAq8BnE"}
|