wyrm-mcp 5.2.1 → 5.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wyrm-mcp",
3
- "version": "5.2.1",
3
+ "version": "5.2.2",
4
4
  "description": "🐉 Wyrm - Persistent AI Memory System with encryption, full-text search, and infinite storage",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,21 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Termux / PRoot compatibility shim.
3
+ * Pre-install environment shim.
4
4
  *
5
- * On Termux (Bionic libc) and proot-distro'd Linux distros running on top of
6
- * it, the system compiler is a recent clang/gcc that rejects Node's bundled
7
- * `-flto=4` flag from its `common.gypi`. When `prebuild-install` times out
8
- * (which it often does on phone bandwidth or when GitHub releases are slow)
9
- * and node-gyp falls back to building `better-sqlite3` from source, the
10
- * compile dies with:
5
+ * Two things:
11
6
  *
12
- * cc: error: unsupported argument '4' to option '-flto='
7
+ * 1. **Termux / PRoot compatibility patch.** On Termux (Bionic libc) and
8
+ * proot-distro'd Linux distros running on top of it, the system compiler
9
+ * is a recent clang/gcc that rejects Node's bundled `-flto=4` flag from
10
+ * its `common.gypi`. When `prebuild-install` times out and node-gyp falls
11
+ * back to building `better-sqlite3` from source, the compile dies with:
13
12
  *
14
- * This script detects an Android/Termux/PRoot environment and rewrites the
15
- * relevant `common.gypi` so the build succeeds without manual intervention.
16
- * On every other platform it does nothing and exits 0.
13
+ * cc: error: unsupported argument '4' to option '-flto='
14
+ *
15
+ * We detect Android-like environments and rewrite the relevant
16
+ * `common.gypi` so the build succeeds without manual intervention.
17
+ *
18
+ * 2. **Build-tool hint.** On platforms where `better-sqlite3` ships no
19
+ * prebuilt binary (anything not in linux/macOS/Windows × x64/arm64), the
20
+ * install WILL invoke `node-gyp`. If `gcc`/`g++`/`make`/`python3` aren't
21
+ * on PATH, that fails with cryptic errors. We detect the gap up front and
22
+ * print the exact install command for the host's package manager.
17
23
  *
18
24
  * Idempotent. Safe to run multiple times. Failures never block the install.
25
+ * See TROUBLESHOOTING.md in this repo for the full failure-mode catalogue.
19
26
  */
20
27
 
21
28
  'use strict';
@@ -23,6 +30,7 @@
23
30
  const fs = require('fs');
24
31
  const path = require('path');
25
32
  const os = require('os');
33
+ const cp = require('child_process');
26
34
 
27
35
  const log = (msg) => process.stdout.write(`[wyrm-mcp preinstall] ${msg}\n`);
28
36
 
@@ -93,36 +101,131 @@ function patchGypi(file) {
93
101
  }
94
102
  }
95
103
 
96
- function main() {
97
- // Opt-out for users who don't want us touching node-gyp config.
98
- if (process.env.WYRM_SKIP_TERMUX_FIX) {
99
- return;
104
+ // ---------------------------------------------------------------------------
105
+ // Build-tool hint (for platforms with no prebuilt better-sqlite3 binary)
106
+ // ---------------------------------------------------------------------------
107
+
108
+ // Platforms where `better-sqlite3` ships a prebuilt binary. If we're on one of
109
+ // these, prebuild-install handles everything and no compiler is needed.
110
+ const PREBUILT_TARGETS = new Set([
111
+ 'linux-x64',
112
+ 'linux-arm64',
113
+ 'darwin-x64',
114
+ 'darwin-arm64',
115
+ 'win32-x64',
116
+ 'win32-arm64',
117
+ ]);
118
+
119
+ function hasOnPath(cmd) {
120
+ try {
121
+ cp.execFileSync(process.platform === 'win32' ? 'where' : 'which', [cmd], {
122
+ stdio: 'ignore',
123
+ });
124
+ return true;
125
+ } catch {
126
+ return false;
127
+ }
128
+ }
129
+
130
+ function detectPackageManager() {
131
+ if (process.platform === 'darwin') return { tool: 'brew', pkgs: 'python3' };
132
+ if (process.platform === 'win32') return null; // node-gyp handles MSVC differently
133
+ // Linux: sniff /etc/os-release.
134
+ let osRelease = '';
135
+ try {
136
+ osRelease = fs.readFileSync('/etc/os-release', 'utf8').toLowerCase();
137
+ } catch {
138
+ return null;
139
+ }
140
+ if (/\b(debian|ubuntu|raspbian|mint|kali|pop)\b/.test(osRelease)) {
141
+ return { tool: 'apt', pkgs: 'build-essential python3' };
100
142
  }
143
+ if (/\b(fedora|rhel|centos|rocky|alma)\b/.test(osRelease)) {
144
+ return { tool: 'dnf', pkgs: 'gcc gcc-c++ make python3' };
145
+ }
146
+ if (/\balpine\b/.test(osRelease)) {
147
+ return { tool: 'apk', pkgs: 'build-base python3' };
148
+ }
149
+ if (/\barch\b/.test(osRelease) || /\bmanjaro\b/.test(osRelease)) {
150
+ return { tool: 'pacman', pkgs: 'base-devel python' };
151
+ }
152
+ if (/\bopensuse\b/.test(osRelease) || /\bsuse\b/.test(osRelease)) {
153
+ return { tool: 'zypper', pkgs: 'gcc gcc-c++ make python3' };
154
+ }
155
+ return null;
156
+ }
101
157
 
102
- const env = detectAndroidLike();
103
- if (!env) {
104
- return; // Not Android/Termux/PRoot nothing to do.
158
+ function installCommand(pm) {
159
+ switch (pm.tool) {
160
+ case 'apt': return `sudo apt-get update && sudo apt-get install -y ${pm.pkgs}`;
161
+ case 'dnf': return `sudo dnf install -y ${pm.pkgs}`;
162
+ case 'apk': return `sudo apk add --no-cache ${pm.pkgs}`;
163
+ case 'pacman': return `sudo pacman -S --needed ${pm.pkgs}`;
164
+ case 'zypper': return `sudo zypper install -y ${pm.pkgs}`;
165
+ case 'brew': return `brew install ${pm.pkgs}`;
166
+ default: return `# install: ${pm.pkgs}`;
105
167
  }
168
+ }
106
169
 
107
- const gypis = findGypiCandidates();
108
- if (gypis.length === 0) {
109
- log(`detected ${env}, but no node-gyp common.gypi found yet — skipping.`);
110
- log(`if the native build fails later, re-run install or open an issue.`);
111
- return;
170
+ function checkBuildTools() {
171
+ if (process.env.WYRM_SKIP_BUILD_TOOL_HINT) return;
172
+
173
+ const target = `${process.platform}-${process.arch}`;
174
+ // On prebuilt platforms, prebuild-install handles it. No need to warn.
175
+ // (Exception: Termux/PRoot, where prebuild-install often times out and we
176
+ // fall back to source. The Android branch already ran above; if we get
177
+ // here on Android-like, the user already saw our other messages.)
178
+ if (PREBUILT_TARGETS.has(target) && !detectAndroidLike()) return;
179
+
180
+ // Source build is likely. Check the essentials.
181
+ const needed = process.platform === 'win32'
182
+ ? ['python']
183
+ : ['cc', 'make', 'python3'];
184
+ const missing = needed.filter((c) => !hasOnPath(c));
185
+ if (missing.length === 0) return;
186
+
187
+ log(`heads-up: on ${target} this install will compile better-sqlite3 from source,`);
188
+ log(`but the following build tools are missing on PATH: ${missing.join(', ')}.`);
189
+
190
+ const pm = detectPackageManager();
191
+ if (pm) {
192
+ log(`install them with:`);
193
+ log(` ${installCommand(pm)}`);
194
+ } else {
195
+ log(`install a C/C++ toolchain (gcc or clang), make, and python3 via your package manager.`);
112
196
  }
197
+ log(`see TROUBLESHOOTING.md for more. Suppress this hint with WYRM_SKIP_BUILD_TOOL_HINT=1.`);
198
+ }
199
+
200
+ // ---------------------------------------------------------------------------
113
201
 
114
- let patchedAny = false;
115
- for (const file of gypis) {
116
- if (patchGypi(file)) {
117
- log(`patched -flto=4 -> -flto in ${file}`);
118
- patchedAny = true;
202
+ function main() {
203
+ // 1. Termux/PRoot common.gypi patch (opt-out: WYRM_SKIP_TERMUX_FIX=1)
204
+ if (!process.env.WYRM_SKIP_TERMUX_FIX) {
205
+ const env = detectAndroidLike();
206
+ if (env) {
207
+ const gypis = findGypiCandidates();
208
+ if (gypis.length === 0) {
209
+ log(`detected ${env}, but no node-gyp common.gypi found yet — skipping.`);
210
+ log(`if the native build fails later, re-run install or open an issue.`);
211
+ } else {
212
+ let patchedAny = false;
213
+ for (const file of gypis) {
214
+ if (patchGypi(file)) {
215
+ log(`patched -flto=4 -> -flto in ${file}`);
216
+ patchedAny = true;
217
+ }
218
+ }
219
+ if (patchedAny) {
220
+ log(`Termux/PRoot compatibility fix applied. To revert, restore .wyrm-preinstall.bak.`);
221
+ log(`Disable on future installs with WYRM_SKIP_TERMUX_FIX=1.`);
222
+ }
223
+ }
119
224
  }
120
225
  }
121
226
 
122
- if (patchedAny) {
123
- log(`Termux/PRoot compatibility fix applied. To revert, restore .wyrm-preinstall.bak.`);
124
- log(`Disable on future installs with WYRM_SKIP_TERMUX_FIX=1.`);
125
- }
227
+ // 2. Build-tool hint (always runs unless suppressed)
228
+ checkBuildTools();
126
229
  }
127
230
 
128
231
  try {