memtrace 0.3.55 → 0.3.67
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/install.js +136 -9
- package/package.json +6 -4
package/install.js
CHANGED
|
@@ -9,6 +9,16 @@ const { platformBinary, spawnOptionsForPlatform } = require("./lib/spawn-helper"
|
|
|
9
9
|
const { installToFs } = require("./lib/claude-integration");
|
|
10
10
|
|
|
11
11
|
// ── Platform binary resolution (preserved from legacy) ───────────────────────
|
|
12
|
+
//
|
|
13
|
+
// Two parallel package families on x86_64:
|
|
14
|
+
// • default — bundles MS prebuilt libonnxruntime (AVX2 baseline)
|
|
15
|
+
// • `*-noavx2` — bundles a from-source build with AVX/AVX2/AVX-512
|
|
16
|
+
// codegen disabled, for Ivy Bridge / Xeon E5 v2 etc.
|
|
17
|
+
// Apple Silicon and Linux ARM don't need the split (no AVX in the ISA).
|
|
18
|
+
//
|
|
19
|
+
// The choice is made at install time by `hasAvx2()`. Users can force the
|
|
20
|
+
// no-AVX2 variant via `MEMTRACE_FORCE_NOAVX2=1` (handy for testing or
|
|
21
|
+
// when CPU detection is unreliable in containerised envs).
|
|
12
22
|
|
|
13
23
|
const PLATFORM_MAP = {
|
|
14
24
|
"darwin-arm64": "@memtrace/darwin-arm64",
|
|
@@ -18,13 +28,94 @@ const PLATFORM_MAP = {
|
|
|
18
28
|
"win32-x64": "@memtrace/win32-x64",
|
|
19
29
|
};
|
|
20
30
|
|
|
31
|
+
const NOAVX2_PLATFORM_MAP = {
|
|
32
|
+
"linux-x64": "@memtrace/linux-x64-noavx2",
|
|
33
|
+
"win32-x64": "@memtrace/win32-x64-noavx2",
|
|
34
|
+
};
|
|
35
|
+
|
|
21
36
|
function getPlatformKey() {
|
|
22
37
|
return `${os.platform()}-${os.arch()}`;
|
|
23
38
|
}
|
|
24
39
|
|
|
40
|
+
// Best-effort runtime AVX2 check. Returns `true` (AVX2 present) when we
|
|
41
|
+
// can't tell — the AVX2 path is the common case and the runtime gate in
|
|
42
|
+
// the binary catches the wrong choice with a clean error if we guess
|
|
43
|
+
// wrong. This is install-time best-effort; the actual bullet-proof check
|
|
44
|
+
// happens at process start.
|
|
45
|
+
function hasAvx2() {
|
|
46
|
+
if (process.env.MEMTRACE_FORCE_NOAVX2 === "1") {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (process.env.MEMTRACE_FORCE_AVX2 === "1") {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
const arch = os.arch();
|
|
53
|
+
// Only x86_64 CPUs have AVX as a concept. ARM hosts skip the check.
|
|
54
|
+
if (arch !== "x64") {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
const platform = os.platform();
|
|
58
|
+
try {
|
|
59
|
+
if (platform === "linux") {
|
|
60
|
+
const cpuinfo = fs.readFileSync("/proc/cpuinfo", "utf8");
|
|
61
|
+
// `flags` line on Intel, `Features` on some emulators.
|
|
62
|
+
return /\b(avx2)\b/.test(cpuinfo);
|
|
63
|
+
}
|
|
64
|
+
if (platform === "win32") {
|
|
65
|
+
// PowerShell exposes ProcessorFeaturePresent via the kernel32 API
|
|
66
|
+
// through the PROCESSOR_FEATURE enum. PF_AVX2_INSTRUCTIONS_AVAILABLE
|
|
67
|
+
// is feature ID 40. A fresh PS process is ~300 ms — fine for an
|
|
68
|
+
// install-time hook that only runs once.
|
|
69
|
+
const result = spawnSync(
|
|
70
|
+
"powershell",
|
|
71
|
+
[
|
|
72
|
+
"-NoProfile",
|
|
73
|
+
"-NonInteractive",
|
|
74
|
+
"-Command",
|
|
75
|
+
"[System.Reflection.Assembly]::Load('mscorlib') | Out-Null; " +
|
|
76
|
+
"Add-Type -MemberDefinition '[DllImport(\"kernel32\")] " +
|
|
77
|
+
"public static extern bool IsProcessorFeaturePresent(uint f);' " +
|
|
78
|
+
"-Name PF -Namespace Memtrace; " +
|
|
79
|
+
"[Memtrace.PF]::IsProcessorFeaturePresent(40)",
|
|
80
|
+
],
|
|
81
|
+
{ encoding: "utf8", timeout: 5000 }
|
|
82
|
+
);
|
|
83
|
+
const out = (result.stdout || "").trim().toLowerCase();
|
|
84
|
+
if (out === "true") return true;
|
|
85
|
+
if (out === "false") return false;
|
|
86
|
+
return true; // ambiguous → assume AVX2
|
|
87
|
+
}
|
|
88
|
+
if (platform === "darwin") {
|
|
89
|
+
// sysctl exposes CPU feature leaves directly. macOS x86_64 was only
|
|
90
|
+
// ever shipped on Sandy Bridge → Coffee Lake; AVX2 lands in Haswell
|
|
91
|
+
// (mid-2013), which lines up with the 2013+ Mac Pro and every Mac
|
|
92
|
+
// Apple sold from late 2013 onward. We probe explicitly anyway in
|
|
93
|
+
// case someone is running on a Hackintosh with an older CPU.
|
|
94
|
+
const result = spawnSync("sysctl", ["-n", "machdep.cpu.leaf7_features"], {
|
|
95
|
+
encoding: "utf8",
|
|
96
|
+
timeout: 2000,
|
|
97
|
+
});
|
|
98
|
+
const out = (result.stdout || "").toUpperCase();
|
|
99
|
+
return /AVX2/.test(out);
|
|
100
|
+
}
|
|
101
|
+
} catch (_) {
|
|
102
|
+
// Detection failed (locked-down container, missing /proc, sysctl
|
|
103
|
+
// gone, etc.). Default to the AVX2 path — the runtime gate will
|
|
104
|
+
// catch a wrong guess with a clean error.
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function platformPackageName(key) {
|
|
110
|
+
if (!hasAvx2() && Object.prototype.hasOwnProperty.call(NOAVX2_PLATFORM_MAP, key)) {
|
|
111
|
+
return NOAVX2_PLATFORM_MAP[key];
|
|
112
|
+
}
|
|
113
|
+
return PLATFORM_MAP[key];
|
|
114
|
+
}
|
|
115
|
+
|
|
25
116
|
function getBinaryPath() {
|
|
26
117
|
const key = getPlatformKey();
|
|
27
|
-
const pkg =
|
|
118
|
+
const pkg = platformPackageName(key);
|
|
28
119
|
if (!pkg) {
|
|
29
120
|
throw new Error(
|
|
30
121
|
`Memtrace does not support platform: ${key}\n` +
|
|
@@ -33,16 +124,42 @@ function getBinaryPath() {
|
|
|
33
124
|
}
|
|
34
125
|
const ext = os.platform() === "win32" ? ".exe" : "";
|
|
35
126
|
const binaryName = `memtrace${ext}`;
|
|
127
|
+
try {
|
|
128
|
+
return require.resolve(`${pkg}/bin/${binaryName}`);
|
|
129
|
+
} catch {
|
|
130
|
+
selfHealPlatformPackage();
|
|
131
|
+
}
|
|
36
132
|
try {
|
|
37
133
|
return require.resolve(`${pkg}/bin/${binaryName}`);
|
|
38
134
|
} catch {
|
|
39
135
|
throw new Error(
|
|
40
|
-
`Could not find memtrace binary for ${key}.\n` +
|
|
136
|
+
`Could not find memtrace binary for ${key} (package ${pkg}).\n` +
|
|
41
137
|
`Try reinstalling: npm install -g memtrace`
|
|
42
138
|
);
|
|
43
139
|
}
|
|
44
140
|
}
|
|
45
141
|
|
|
142
|
+
function buildSelfHealInstallArgs(packageDir, versioned) {
|
|
143
|
+
return ["install", "--prefix", packageDir, "--no-save", "--include=optional", versioned];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function buildSelfHealEnv(env) {
|
|
147
|
+
const next = { ...env };
|
|
148
|
+
|
|
149
|
+
// During `npm install -g memtrace`, npm exposes global-mode config through
|
|
150
|
+
// the environment. A nested `npm install` can inherit that and install the
|
|
151
|
+
// platform package into the global prefix instead of this package directory.
|
|
152
|
+
delete next.npm_config_global;
|
|
153
|
+
delete next.NPM_CONFIG_GLOBAL;
|
|
154
|
+
next.npm_config_global = "false";
|
|
155
|
+
|
|
156
|
+
return next;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function getPinnedPlatformVersion(packageJson, platformPackage) {
|
|
160
|
+
return packageJson.optionalDependencies?.[platformPackage] ?? packageJson.version;
|
|
161
|
+
}
|
|
162
|
+
|
|
46
163
|
// ── Optional-dep self-heal ───────────────────────────────────────────────────
|
|
47
164
|
//
|
|
48
165
|
// `optionalDependencies` is supposed to fan out platform binaries
|
|
@@ -56,16 +173,16 @@ function getBinaryPath() {
|
|
|
56
173
|
// versioned name comes from the same map the runtime resolver uses.
|
|
57
174
|
function selfHealPlatformPackage() {
|
|
58
175
|
const key = getPlatformKey();
|
|
59
|
-
const pkg =
|
|
60
|
-
if (!pkg) return; // unsupported platform — getBinaryPath will surface it later
|
|
176
|
+
const pkg = platformPackageName(key);
|
|
177
|
+
if (!pkg) return false; // unsupported platform — getBinaryPath will surface it later
|
|
61
178
|
try {
|
|
62
179
|
require.resolve(`${pkg}/package.json`);
|
|
63
|
-
return; // already installed via optionalDependencies
|
|
180
|
+
return true; // already installed via optionalDependencies
|
|
64
181
|
} catch (_) {
|
|
65
182
|
// not installed — fall through to install
|
|
66
183
|
}
|
|
67
184
|
const ourPkg = require("./package.json");
|
|
68
|
-
const versioned = `${pkg}@${ourPkg
|
|
185
|
+
const versioned = `${pkg}@${getPinnedPlatformVersion(ourPkg, pkg)}`;
|
|
69
186
|
console.log(
|
|
70
187
|
`memtrace: optional platform dep ${pkg} was not installed; ` +
|
|
71
188
|
`running 'npm install ${versioned}' to fetch it…`
|
|
@@ -78,11 +195,11 @@ function selfHealPlatformPackage() {
|
|
|
78
195
|
// `test/spawn-helper.test.js` for the full regression coverage.
|
|
79
196
|
const result = spawnSync(
|
|
80
197
|
platformBinary("npm", process.platform),
|
|
81
|
-
|
|
198
|
+
buildSelfHealInstallArgs(__dirname, versioned),
|
|
82
199
|
spawnOptionsForPlatform(process.platform, {
|
|
83
200
|
cwd: __dirname,
|
|
84
201
|
stdio: "inherit",
|
|
85
|
-
env: process.env,
|
|
202
|
+
env: buildSelfHealEnv(process.env),
|
|
86
203
|
})
|
|
87
204
|
);
|
|
88
205
|
if (result.status !== 0) {
|
|
@@ -90,7 +207,9 @@ function selfHealPlatformPackage() {
|
|
|
90
207
|
`memtrace: self-heal install of ${versioned} failed (exit ${result.status}). ` +
|
|
91
208
|
`Run manually: npm install -g memtrace --include=optional`
|
|
92
209
|
);
|
|
210
|
+
return false;
|
|
93
211
|
}
|
|
212
|
+
return true;
|
|
94
213
|
}
|
|
95
214
|
|
|
96
215
|
// ── Main postinstall ─────────────────────────────────────────────────────────
|
|
@@ -176,4 +295,12 @@ if (require.main === module) {
|
|
|
176
295
|
}
|
|
177
296
|
}
|
|
178
297
|
|
|
179
|
-
module.exports = {
|
|
298
|
+
module.exports = {
|
|
299
|
+
getBinaryPath,
|
|
300
|
+
selfHealPlatformPackage,
|
|
301
|
+
buildSelfHealEnv,
|
|
302
|
+
buildSelfHealInstallArgs,
|
|
303
|
+
getPinnedPlatformVersion,
|
|
304
|
+
hasAvx2,
|
|
305
|
+
platformPackageName,
|
|
306
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memtrace",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.67",
|
|
4
4
|
"description": "Code intelligence graph — MCP server + AI agent skills + visualization UI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -39,9 +39,11 @@
|
|
|
39
39
|
"fs-extra": "^11.0.0"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
|
-
"@memtrace/darwin-arm64": "0.3.
|
|
43
|
-
"@memtrace/linux-x64": "0.3.
|
|
44
|
-
"@memtrace/win32-x64": "0.3.
|
|
42
|
+
"@memtrace/darwin-arm64": "0.3.67",
|
|
43
|
+
"@memtrace/linux-x64": "0.3.67",
|
|
44
|
+
"@memtrace/win32-x64": "0.3.67",
|
|
45
|
+
"@memtrace/linux-x64-noavx2": "0.3.67",
|
|
46
|
+
"@memtrace/win32-x64-noavx2": "0.3.67"
|
|
45
47
|
},
|
|
46
48
|
"engines": {
|
|
47
49
|
"node": ">=18"
|