@memlab/mcp-server 2.52.0 → 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 (277) hide show
  1. package/README.md +22 -2
  2. package/dist/anonymized-snapshot.d.ts +75 -0
  3. package/dist/anonymized-snapshot.d.ts.map +1 -0
  4. package/dist/anonymized-snapshot.js +101 -0
  5. package/dist/anonymized-snapshot.js.map +1 -0
  6. package/dist/eval-hints.d.ts +41 -0
  7. package/dist/eval-hints.d.ts.map +1 -0
  8. package/dist/eval-hints.js +115 -0
  9. package/dist/eval-hints.js.map +1 -0
  10. package/dist/heap-budget.d.ts +32 -0
  11. package/dist/heap-budget.d.ts.map +1 -0
  12. package/dist/heap-budget.js +90 -0
  13. package/dist/heap-budget.js.map +1 -0
  14. package/dist/heap-shapes.d.ts +148 -0
  15. package/dist/heap-shapes.d.ts.map +1 -0
  16. package/dist/heap-shapes.js +193 -0
  17. package/dist/heap-shapes.js.map +1 -0
  18. package/dist/heap-state.d.ts +20 -0
  19. package/dist/heap-state.d.ts.map +1 -1
  20. package/dist/heap-state.js +8 -1
  21. package/dist/heap-state.js.map +1 -1
  22. package/dist/index.js +64 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/react-shapes.d.ts +42 -0
  25. package/dist/react-shapes.d.ts.map +1 -0
  26. package/dist/react-shapes.js +149 -0
  27. package/dist/react-shapes.js.map +1 -0
  28. package/dist/server-version.d.ts +19 -0
  29. package/dist/server-version.d.ts.map +1 -0
  30. package/dist/server-version.js +19 -0
  31. package/dist/server-version.js.map +1 -0
  32. package/dist/snapshot-borrow.d.ts +67 -0
  33. package/dist/snapshot-borrow.d.ts.map +1 -0
  34. package/dist/snapshot-borrow.js +113 -0
  35. package/dist/snapshot-borrow.js.map +1 -0
  36. package/dist/string-index.d.ts.map +1 -1
  37. package/dist/string-index.js +8 -0
  38. package/dist/string-index.js.map +1 -1
  39. package/dist/tools/analyze-run.d.ts.map +1 -1
  40. package/dist/tools/analyze-run.js +79 -18
  41. package/dist/tools/analyze-run.js.map +1 -1
  42. package/dist/tools/anonymize-snapshot.d.ts +12 -0
  43. package/dist/tools/anonymize-snapshot.d.ts.map +1 -0
  44. package/dist/tools/anonymize-snapshot.js +159 -0
  45. package/dist/tools/anonymize-snapshot.js.map +1 -0
  46. package/dist/tools/app-config.d.ts +12 -0
  47. package/dist/tools/app-config.d.ts.map +1 -0
  48. package/dist/tools/app-config.js +217 -0
  49. package/dist/tools/app-config.js.map +1 -0
  50. package/dist/tools/app-heap.d.ts +18 -0
  51. package/dist/tools/app-heap.d.ts.map +1 -1
  52. package/dist/tools/app-heap.js +12 -46
  53. package/dist/tools/app-heap.js.map +1 -1
  54. package/dist/tools/artifact-budget.d.ts +12 -0
  55. package/dist/tools/artifact-budget.d.ts.map +1 -0
  56. package/dist/tools/artifact-budget.js +219 -0
  57. package/dist/tools/artifact-budget.js.map +1 -0
  58. package/dist/tools/async-census.d.ts +12 -0
  59. package/dist/tools/async-census.d.ts.map +1 -0
  60. package/dist/tools/async-census.js +243 -0
  61. package/dist/tools/async-census.js.map +1 -0
  62. package/dist/tools/auto-investigate.d.ts.map +1 -1
  63. package/dist/tools/auto-investigate.js +54 -5
  64. package/dist/tools/auto-investigate.js.map +1 -1
  65. package/dist/tools/batch.d.ts.map +1 -1
  66. package/dist/tools/batch.js +33 -5
  67. package/dist/tools/batch.js.map +1 -1
  68. package/dist/tools/cache-analysis.d.ts +15 -0
  69. package/dist/tools/cache-analysis.d.ts.map +1 -1
  70. package/dist/tools/cache-analysis.js +85 -10
  71. package/dist/tools/cache-analysis.js.map +1 -1
  72. package/dist/tools/census-diff.d.ts +55 -0
  73. package/dist/tools/census-diff.d.ts.map +1 -0
  74. package/dist/tools/census-diff.js +228 -0
  75. package/dist/tools/census-diff.js.map +1 -0
  76. package/dist/tools/chain-walk.d.ts +12 -0
  77. package/dist/tools/chain-walk.d.ts.map +1 -0
  78. package/dist/tools/chain-walk.js +184 -0
  79. package/dist/tools/chain-walk.js.map +1 -0
  80. package/dist/tools/collection-diff.d.ts +44 -0
  81. package/dist/tools/collection-diff.d.ts.map +1 -0
  82. package/dist/tools/collection-diff.js +343 -0
  83. package/dist/tools/collection-diff.js.map +1 -0
  84. package/dist/tools/collection-trend.d.ts.map +1 -1
  85. package/dist/tools/collection-trend.js +2 -2
  86. package/dist/tools/collection-trend.js.map +1 -1
  87. package/dist/tools/detached-dom.d.ts +3 -0
  88. package/dist/tools/detached-dom.d.ts.map +1 -1
  89. package/dist/tools/detached-dom.js +78 -3
  90. package/dist/tools/detached-dom.js.map +1 -1
  91. package/dist/tools/dev-artifacts.d.ts.map +1 -1
  92. package/dist/tools/dev-artifacts.js +221 -3
  93. package/dist/tools/dev-artifacts.js.map +1 -1
  94. package/dist/tools/diff-snapshots.d.ts.map +1 -1
  95. package/dist/tools/diff-snapshots.js +18 -2
  96. package/dist/tools/diff-snapshots.js.map +1 -1
  97. package/dist/tools/dom-audit.d.ts +37 -0
  98. package/dist/tools/dom-audit.d.ts.map +1 -0
  99. package/dist/tools/dom-audit.js +247 -0
  100. package/dist/tools/dom-audit.js.map +1 -0
  101. package/dist/tools/duplicated-strings.d.ts.map +1 -1
  102. package/dist/tools/duplicated-strings.js +3 -2
  103. package/dist/tools/duplicated-strings.js.map +1 -1
  104. package/dist/tools/eval-across.d.ts +12 -0
  105. package/dist/tools/eval-across.d.ts.map +1 -0
  106. package/dist/tools/eval-across.js +135 -0
  107. package/dist/tools/eval-across.js.map +1 -0
  108. package/dist/tools/eval.d.ts +78 -0
  109. package/dist/tools/eval.d.ts.map +1 -1
  110. package/dist/tools/eval.js +2270 -701
  111. package/dist/tools/eval.js.map +1 -1
  112. package/dist/tools/event-listener-leaks.d.ts.map +1 -1
  113. package/dist/tools/event-listener-leaks.js +42 -17
  114. package/dist/tools/event-listener-leaks.js.map +1 -1
  115. package/dist/tools/event-registry.d.ts.map +1 -1
  116. package/dist/tools/event-registry.js +42 -8
  117. package/dist/tools/event-registry.js.map +1 -1
  118. package/dist/tools/explain-delta.d.ts.map +1 -1
  119. package/dist/tools/explain-delta.js +61 -10
  120. package/dist/tools/explain-delta.js.map +1 -1
  121. package/dist/tools/finding-index.d.ts +181 -0
  122. package/dist/tools/finding-index.d.ts.map +1 -1
  123. package/dist/tools/finding-index.js +343 -24
  124. package/dist/tools/finding-index.js.map +1 -1
  125. package/dist/tools/get-value.d.ts +16 -0
  126. package/dist/tools/get-value.d.ts.map +1 -1
  127. package/dist/tools/get-value.js +96 -2
  128. package/dist/tools/get-value.js.map +1 -1
  129. package/dist/tools/hypothesis.d.ts.map +1 -1
  130. package/dist/tools/hypothesis.js +117 -58
  131. package/dist/tools/hypothesis.js.map +1 -1
  132. package/dist/tools/id-space-audit.d.ts +12 -0
  133. package/dist/tools/id-space-audit.d.ts.map +1 -0
  134. package/dist/tools/id-space-audit.js +262 -0
  135. package/dist/tools/id-space-audit.js.map +1 -0
  136. package/dist/tools/identify.d.ts +12 -0
  137. package/dist/tools/identify.d.ts.map +1 -0
  138. package/dist/tools/identify.js +205 -0
  139. package/dist/tools/identify.js.map +1 -0
  140. package/dist/tools/identity-diff.d.ts +12 -0
  141. package/dist/tools/identity-diff.d.ts.map +1 -0
  142. package/dist/tools/identity-diff.js +188 -0
  143. package/dist/tools/identity-diff.js.map +1 -0
  144. package/dist/tools/intern-opportunities.d.ts.map +1 -1
  145. package/dist/tools/intern-opportunities.js +4 -3
  146. package/dist/tools/intern-opportunities.js.map +1 -1
  147. package/dist/tools/ladder-probe.d.ts +65 -0
  148. package/dist/tools/ladder-probe.d.ts.map +1 -0
  149. package/dist/tools/ladder-probe.js +445 -0
  150. package/dist/tools/ladder-probe.js.map +1 -0
  151. package/dist/tools/ladder.d.ts.map +1 -1
  152. package/dist/tools/ladder.js +5 -5
  153. package/dist/tools/ladder.js.map +1 -1
  154. package/dist/tools/leak-report.d.ts +23 -0
  155. package/dist/tools/leak-report.d.ts.map +1 -1
  156. package/dist/tools/leak-report.js +153 -11
  157. package/dist/tools/leak-report.js.map +1 -1
  158. package/dist/tools/load-snapshot.d.ts +11 -0
  159. package/dist/tools/load-snapshot.d.ts.map +1 -1
  160. package/dist/tools/load-snapshot.js +83 -10
  161. package/dist/tools/load-snapshot.js.map +1 -1
  162. package/dist/tools/metric.d.ts +13 -0
  163. package/dist/tools/metric.d.ts.map +1 -0
  164. package/dist/tools/metric.js +185 -0
  165. package/dist/tools/metric.js.map +1 -0
  166. package/dist/tools/module-attribution.d.ts +36 -0
  167. package/dist/tools/module-attribution.d.ts.map +1 -0
  168. package/dist/tools/module-attribution.js +235 -0
  169. package/dist/tools/module-attribution.js.map +1 -0
  170. package/dist/tools/next-measurement.d.ts +26 -0
  171. package/dist/tools/next-measurement.d.ts.map +1 -0
  172. package/dist/tools/next-measurement.js +149 -0
  173. package/dist/tools/next-measurement.js.map +1 -0
  174. package/dist/tools/object-cost-breakdown.d.ts.map +1 -1
  175. package/dist/tools/object-cost-breakdown.js +64 -0
  176. package/dist/tools/object-cost-breakdown.js.map +1 -1
  177. package/dist/tools/population-vs-owners.d.ts +12 -0
  178. package/dist/tools/population-vs-owners.d.ts.map +1 -0
  179. package/dist/tools/population-vs-owners.js +183 -0
  180. package/dist/tools/population-vs-owners.js.map +1 -0
  181. package/dist/tools/property-names.d.ts +29 -0
  182. package/dist/tools/property-names.d.ts.map +1 -0
  183. package/dist/tools/property-names.js +131 -0
  184. package/dist/tools/property-names.js.map +1 -0
  185. package/dist/tools/quick-diagnosis.d.ts.map +1 -1
  186. package/dist/tools/quick-diagnosis.js +7 -1
  187. package/dist/tools/quick-diagnosis.js.map +1 -1
  188. package/dist/tools/react-owners.d.ts +12 -0
  189. package/dist/tools/react-owners.d.ts.map +1 -0
  190. package/dist/tools/react-owners.js +167 -0
  191. package/dist/tools/react-owners.js.map +1 -0
  192. package/dist/tools/react-update-queues.d.ts +12 -0
  193. package/dist/tools/react-update-queues.d.ts.map +1 -0
  194. package/dist/tools/react-update-queues.js +173 -0
  195. package/dist/tools/react-update-queues.js.map +1 -0
  196. package/dist/tools/replicate.d.ts +49 -0
  197. package/dist/tools/replicate.d.ts.map +1 -0
  198. package/dist/tools/replicate.js +241 -0
  199. package/dist/tools/replicate.js.map +1 -0
  200. package/dist/tools/retainer-diff.d.ts +12 -0
  201. package/dist/tools/retainer-diff.d.ts.map +1 -0
  202. package/dist/tools/retainer-diff.js +168 -0
  203. package/dist/tools/retainer-diff.js.map +1 -0
  204. package/dist/tools/retainer-summary.d.ts +17 -0
  205. package/dist/tools/retainer-summary.d.ts.map +1 -1
  206. package/dist/tools/retainer-summary.js +85 -22
  207. package/dist/tools/retainer-summary.js.map +1 -1
  208. package/dist/tools/retainer-trace.d.ts.map +1 -1
  209. package/dist/tools/retainer-trace.js +11 -1
  210. package/dist/tools/retainer-trace.js.map +1 -1
  211. package/dist/tools/round-audit.d.ts +66 -0
  212. package/dist/tools/round-audit.d.ts.map +1 -0
  213. package/dist/tools/round-audit.js +258 -0
  214. package/dist/tools/round-audit.js.map +1 -0
  215. package/dist/tools/round-digest.d.ts +12 -0
  216. package/dist/tools/round-digest.d.ts.map +1 -0
  217. package/dist/tools/round-digest.js +190 -0
  218. package/dist/tools/round-digest.js.map +1 -0
  219. package/dist/tools/script-census.d.ts +12 -0
  220. package/dist/tools/script-census.d.ts.map +1 -0
  221. package/dist/tools/script-census.js +182 -0
  222. package/dist/tools/script-census.js.map +1 -0
  223. package/dist/tools/sequence-analysis.d.ts +4 -0
  224. package/dist/tools/sequence-analysis.d.ts.map +1 -1
  225. package/dist/tools/sequence-analysis.js +53 -9
  226. package/dist/tools/sequence-analysis.js.map +1 -1
  227. package/dist/tools/server-status.d.ts.map +1 -1
  228. package/dist/tools/server-status.js +4 -1
  229. package/dist/tools/server-status.js.map +1 -1
  230. package/dist/tools/settle-check.d.ts +12 -0
  231. package/dist/tools/settle-check.d.ts.map +1 -0
  232. package/dist/tools/settle-check.js +188 -0
  233. package/dist/tools/settle-check.js.map +1 -0
  234. package/dist/tools/sliced-strings.d.ts.map +1 -1
  235. package/dist/tools/sliced-strings.js +2 -1
  236. package/dist/tools/sliced-strings.js.map +1 -1
  237. package/dist/tools/snapshots.d.ts.map +1 -1
  238. package/dist/tools/snapshots.js +24 -6
  239. package/dist/tools/snapshots.js.map +1 -1
  240. package/dist/tools/sparse-elements.d.ts +12 -0
  241. package/dist/tools/sparse-elements.d.ts.map +1 -0
  242. package/dist/tools/sparse-elements.js +215 -0
  243. package/dist/tools/sparse-elements.js.map +1 -0
  244. package/dist/tools/stale-collections.d.ts +17 -0
  245. package/dist/tools/stale-collections.d.ts.map +1 -1
  246. package/dist/tools/stale-collections.js +28 -0
  247. package/dist/tools/stale-collections.js.map +1 -1
  248. package/dist/tools/string-patterns.d.ts.map +1 -1
  249. package/dist/tools/string-patterns.js +2 -1
  250. package/dist/tools/string-patterns.js.map +1 -1
  251. package/dist/tools/tools-index.d.ts.map +1 -1
  252. package/dist/tools/tools-index.js +155 -5
  253. package/dist/tools/tools-index.js.map +1 -1
  254. package/dist/tools/trace-all.d.ts +42 -0
  255. package/dist/tools/trace-all.d.ts.map +1 -0
  256. package/dist/tools/trace-all.js +263 -0
  257. package/dist/tools/trace-all.js.map +1 -0
  258. package/dist/tools/unit-cost.d.ts +12 -0
  259. package/dist/tools/unit-cost.d.ts.map +1 -0
  260. package/dist/tools/unit-cost.js +219 -0
  261. package/dist/tools/unit-cost.js.map +1 -0
  262. package/dist/tools/verify-fix.d.ts.map +1 -1
  263. package/dist/tools/verify-fix.js +11 -3
  264. package/dist/tools/verify-fix.js.map +1 -1
  265. package/dist/tools/weakref-census.d.ts +15 -0
  266. package/dist/tools/weakref-census.d.ts.map +1 -0
  267. package/dist/tools/weakref-census.js +147 -0
  268. package/dist/tools/weakref-census.js.map +1 -0
  269. package/dist/tools/what-if.d.ts +12 -0
  270. package/dist/tools/what-if.d.ts.map +1 -0
  271. package/dist/tools/what-if.js +285 -0
  272. package/dist/tools/what-if.js.map +1 -0
  273. package/dist/utils.d.ts +92 -2
  274. package/dist/utils.d.ts.map +1 -1
  275. package/dist/utils.js +172 -5
  276. package/dist/utils.js.map +1 -1
  277. package/package.json +3 -3
@@ -0,0 +1,135 @@
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 { getCurrentHandle, getMetadataByHandle, listSnapshots, setCurrentSnapshot, } from '../heap-state.js';
12
+ import { errorResult, toolResult } from '../utils.js';
13
+ import { runEval } from './eval.js';
14
+ function textOf(result) {
15
+ const content = result?.content;
16
+ if (!Array.isArray(content))
17
+ return '(no output)';
18
+ return content
19
+ .map(c => (typeof c?.text === 'string' ? c.text : ''))
20
+ .join('\n')
21
+ .trim();
22
+ }
23
+ export function registerEvalAcross(server) {
24
+ server.tool('memlab_eval_across', 'Run ONE `memlab_eval` program against SEVERAL resident snapshots and return the results side by side. ' +
25
+ 'Exists because the interesting questions in a leak hunt are comparative — "how many of these were there at each rung?", ' +
26
+ '"did this collection grow?", "is the new population retained the same way as the old one?" — and answering them with ' +
27
+ '`memlab_eval` alone costs one switch + one paste + one manual diff per rung, which is enough friction that the question ' +
28
+ 'often just does not get asked. The code, the sandbox and the helper surface are identical to `memlab_eval` (this calls the ' +
29
+ 'same implementation, not a copy), so anything that runs there runs here.\n\n' +
30
+ 'Node ids are per-capture, so write code that computes COMPARABLE values (counts, sizes, shapes, string values) rather than ' +
31
+ 'code that hardcodes ids from one rung. `helpers.load(name)` still refuses cross-snapshot reads unless you pass ' +
32
+ '`{allowCrossSnapshot: true}`.\n\n' +
33
+ 'The active snapshot is restored when the run finishes, including on failure, so this does not disturb an in-progress investigation.', {
34
+ code: z
35
+ .string()
36
+ .describe('JavaScript to run against each snapshot. Same conventions as memlab_eval: assign to `result`, iterate with `snapshot.nodes.forEach`, use `helpers.*`. Run `memlab_eval({mode:"describe_env"})` for the full surface.'),
37
+ handles: z
38
+ .array(z.string())
39
+ .optional()
40
+ .describe('Snapshot handles to run against, in the order you want them reported (oldest rung first reads best). Defaults to every resident snapshot in load order.'),
41
+ timeout_ms: z
42
+ .number()
43
+ .optional()
44
+ .default(60000)
45
+ .describe('Execution timeout in milliseconds, applied PER snapshot (default 60000).'),
46
+ max_nodes: z
47
+ .number()
48
+ .int()
49
+ .min(1)
50
+ .optional()
51
+ .describe('Per-snapshot node-visit budget for full-heap walks. Defaults to a budget SCALED from each loaded graph (6 full passes, floored at 20,000,000). On overrun that rung reports a partial result instead of failing the whole run.'),
52
+ stop_on_error: z
53
+ .boolean()
54
+ .optional()
55
+ .default(false)
56
+ .describe('Stop at the first snapshot whose code throws (default false: record the error for that rung and continue, so one bad rung does not discard the others).'),
57
+ }, async ({ code, handles, timeout_ms, max_nodes, stop_on_error }) => {
58
+ const originalHandle = getCurrentHandle();
59
+ try {
60
+ const resident = listSnapshots().map(m => m.handle);
61
+ if (resident.length === 0) {
62
+ return errorResult(new Error('No snapshots are loaded. Load them with memlab_load_snapshot({keep_previous: true}) first — this tool compares snapshots that are already resident, it does not open files.'));
63
+ }
64
+ const targets = handles != null && handles.length > 0 ? handles : resident;
65
+ const unknown = targets.filter(h => getMetadataByHandle(h) == null);
66
+ if (unknown.length > 0) {
67
+ return errorResult(new Error(`Unknown snapshot handle(s): ${unknown.join(', ')}. Resident: ${resident.join(', ')}. ` +
68
+ 'Handles come from memlab_snapshots or the alias passed to memlab_load_snapshot.'));
69
+ }
70
+ if (targets.length < 2) {
71
+ // Not an error — a single-handle run is a legitimate way to script
72
+ // one rung — but the whole point of the tool is the comparison.
73
+ // Saying so beats silently returning a one-row report.
74
+ // (falls through and runs)
75
+ }
76
+ const sections = [];
77
+ let failures = 0;
78
+ for (const handle of targets) {
79
+ if (!setCurrentSnapshot(handle)) {
80
+ sections.push(`### ${handle}\n\n(could not switch to this snapshot)`);
81
+ failures++;
82
+ continue;
83
+ }
84
+ const meta = getMetadataByHandle(handle);
85
+ const header = `### ${handle}${meta ? ` — ${meta.fileName}` : ''}`;
86
+ try {
87
+ const res = await runEval({ code, timeout_ms, max_nodes });
88
+ const body = textOf(res);
89
+ if (/^Error:/m.test(body))
90
+ failures++;
91
+ sections.push(`${header}\n\n${body}`);
92
+ if (stop_on_error && /^Error:/m.test(body)) {
93
+ sections.push('_Stopped here: stop_on_error is set and this rung failed._');
94
+ break;
95
+ }
96
+ }
97
+ catch (err) {
98
+ failures++;
99
+ const msg = err instanceof Error ? err.message : String(err);
100
+ sections.push(`${header}\n\nError: ${msg}`);
101
+ if (stop_on_error) {
102
+ sections.push('_Stopped here: stop_on_error is set and this rung failed._');
103
+ break;
104
+ }
105
+ }
106
+ }
107
+ const lines = [
108
+ `## eval across ${targets.length} snapshot(s)`,
109
+ '',
110
+ `Order: ${targets.join(' → ')}${failures > 0 ? ` · ${failures} rung(s) reported an error` : ''}`,
111
+ '',
112
+ ...(targets.length < 2
113
+ ? [
114
+ '_Only one snapshot targeted — this tool exists for the comparison; load a second rung with `keep_previous: true` to get one._',
115
+ '',
116
+ ]
117
+ : []),
118
+ sections.join('\n\n'),
119
+ '',
120
+ '_Values are comparable across rungs; node IDS are not — they are assigned per capture. Compare counts, sizes, shapes and string values, never ids._',
121
+ ];
122
+ return toolResult(lines.join('\n'));
123
+ }
124
+ catch (err) {
125
+ return errorResult(err);
126
+ }
127
+ finally {
128
+ // Restore whatever the caller had active, so a comparison run is not a
129
+ // hidden state change for every tool that follows it.
130
+ if (originalHandle != null)
131
+ setCurrentSnapshot(originalHandle);
132
+ }
133
+ });
134
+ }
135
+ //# sourceMappingURL=eval-across.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval-across.js","sourceRoot":"","sources":["../../src/tools/eval-across.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,84 @@
8
8
  * @oncall memory_lab
9
9
  */
10
10
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ import { toolResult } from '../utils.js';
12
+ /**
13
+ * Wall-clock budget for one eval, scaled from the loaded graph.
14
+ *
15
+ * A fixed 60 s default is right for an indexed lookup and wrong for everything
16
+ * else: a full-heap walk on a 6M-node graph takes two to four minutes, so every
17
+ * large-snapshot eval aborted on its first attempt and had to be re-issued with
18
+ * an explicit `timeout_ms`. That is a guaranteed wasted call per question, and
19
+ * the node count needed to avoid it is already known.
20
+ *
21
+ * The floor stays at 60 s so small heaps behave exactly as before.
22
+ */
23
+ export declare function scaledEvalTimeoutMs(): number;
24
+ /**
25
+ * Default `max_nodes`, scaled to the loaded graph.
26
+ *
27
+ * A probe that makes several passes over the heap is the normal shape — one
28
+ * pass to census classes, one to match shapes, one to size things — so the
29
+ * budget has to be a MULTIPLE of the node count, not a constant. At the old
30
+ * flat 20,000,000 a routine two-pass probe on an 8.24M-node capture aborted
31
+ * mid-walk and returned a partial value; because the result was assigned after
32
+ * the loops, what came back was `undefined` with a note, which reads as a
33
+ * legitimate empty answer.
34
+ *
35
+ * Six passes is generous on purpose: the wall-clock timeout above is the real
36
+ * guard against a runaway eval, and this budget exists to stop pathological
37
+ * traversals, not ordinary multi-pass analysis.
38
+ */
39
+ export declare function scaledWalkBudget(): number;
40
+ /**
41
+ * Shorten a heap result STRUCTURALLY rather than mid-string.
42
+ *
43
+ * A census result is an array of rows or a `{key: count}` map, and cutting the
44
+ * JSON at a byte offset yields unparseable output plus a re-run with a
45
+ * hand-written limit — which is what actually happened to a detached-class
46
+ * census whose `blink::HeapVectorBacking<…>` keys blew the cap. Dropping whole
47
+ * entries keeps the value valid JSON and keeps the largest rows, which are the
48
+ * ones the question was about.
49
+ *
50
+ * Blink's C++ template names are elided first: they are frequently most of the
51
+ * payload and none of the information, and `abbreviateBlinkTypeName` is the same
52
+ * elision the table renderers already use.
53
+ */
54
+ export declare function shrinkResult(value: unknown, maxBytes: number): {
55
+ value: unknown;
56
+ truncated: boolean;
57
+ droppedEntries: number;
58
+ keptEntries: number;
59
+ };
11
60
  export declare function unwrapNode<T>(node: T): T;
12
61
  export declare function registerEval(server: McpServer): void;
62
+ export declare function runEval({ mode, code, section, timeout_ms, save_as, max_nodes, sample, restrict_to_ids, dry_run, max_result_bytes, ownsScanBudget, }: {
63
+ mode?: 'eval' | 'describe_env' | 'list_saved' | 'lint';
64
+ code?: string;
65
+ section?: string;
66
+ timeout_ms?: number;
67
+ save_as?: string;
68
+ max_nodes?: number;
69
+ /** Visit every Nth node in a full-heap walk. 1/undefined = every node. */
70
+ sample?: number;
71
+ /** Restrict `snapshot.nodes.forEach` to these node ids. */
72
+ restrict_to_ids?: number[];
73
+ dry_run?: boolean;
74
+ max_result_bytes?: number;
75
+ /**
76
+ * True only for a direct `memlab_eval` MCP call, which owns the scan budget
77
+ * the guardrail armed for it and may therefore re-arm it to a scaled value.
78
+ * Left false by every in-process caller — `memlab_eval_across`,
79
+ * `memlab_ladder_probe`, `memlab_batch` — because those run MANY evals inside
80
+ * ONE MCP call and each re-arm would reset the shared wall clock.
81
+ */
82
+ ownsScanBudget?: boolean;
83
+ }): Promise<ReturnType<typeof toolResult>>;
84
+ /**
85
+ * A result that says "none of them" — 0, `[]`, `{}`, or an empty Map/Set.
86
+ *
87
+ * `undefined`/`null` are deliberately NOT included: those mean "the code
88
+ * assigned nothing", which is a different failure and is already handled.
89
+ */
90
+ export declare function isEmptyCensusResult(v: unknown): boolean;
13
91
  //# sourceMappingURL=eval.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../src/tools/eval.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AA4EvE,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAMxC;AA0ID,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAy7BpD"}
1
+ {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../src/tools/eval.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAuBvE,OAAO,EAGL,UAAU,EAgBX,MAAM,aAAa,CAAC;AAYrB;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAG5C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAGzC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf;IACD,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB,CAkFA;AAwCD,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAMxC;AAiZD,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwIpD;AAqCD,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,UAAU,EACV,OAAO,EACP,SAAS,EACT,MAAM,EACN,eAAe,EACf,OAAO,EACP,gBAAgB,EAChB,cAAc,GACf,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,GAAG,YAAY,GAAG,MAAM,CAAC;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAywDzC;AA2HD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAQvD"}