modelstat 0.0.31 → 0.0.32
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 +1 -1
- package/scripts/postinstall.mjs +102 -0
package/package.json
CHANGED
package/scripts/postinstall.mjs
CHANGED
|
@@ -196,6 +196,16 @@ async function rebootServiceIfInstalled() {
|
|
|
196
196
|
);
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
// The bundle is portable EXCEPT for `node-llama-cpp` and its
|
|
200
|
+
// platform-specific native sub-packages — they're marked external
|
|
201
|
+
// in tsup so they're resolved at runtime via Node's `node_modules`
|
|
202
|
+
// walk-up. From `~/.modelstat/bin/modelstat.mjs` there's no parent
|
|
203
|
+
// `node_modules` to find them in, so the bundled summariser dies
|
|
204
|
+
// at preflight with "Cannot find package 'node-llama-cpp'". Set up
|
|
205
|
+
// a sibling `node_modules` directory containing the runtime
|
|
206
|
+
// dependencies, sourced from this package's own install location.
|
|
207
|
+
await setupNativeNodeModules(installedBundle);
|
|
208
|
+
|
|
199
209
|
// Start back up. `modelstat start` re-runs preflight (incl. the
|
|
200
210
|
// processing-version reconcile that wipes cursors when we ship a
|
|
201
211
|
// new pipeline), so the upgrade picks up the new behaviour
|
|
@@ -209,6 +219,98 @@ async function rebootServiceIfInstalled() {
|
|
|
209
219
|
console.log("[modelstat] ✓ background service restarted with new build");
|
|
210
220
|
}
|
|
211
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Make `node-llama-cpp` and its platform-specific native sibling
|
|
224
|
+
* packages reachable from `~/.modelstat/bin/modelstat.mjs` so the
|
|
225
|
+
* bundle's runtime `import("node-llama-cpp")` resolves.
|
|
226
|
+
*
|
|
227
|
+
* Strategy:
|
|
228
|
+
* - Find the source `node_modules` directory in this package's
|
|
229
|
+
* install (npm flat layout puts it at <pkg>/.. for global
|
|
230
|
+
* installs; pnpm/bun layouts vary but the same walk-up works
|
|
231
|
+
* since postinstall always runs from the package root).
|
|
232
|
+
* - For each runtime dep we care about (`node-llama-cpp` plus
|
|
233
|
+
* every `@node-llama-cpp/*` and `@reflink/*` sub-package),
|
|
234
|
+
* symlink it into `~/.modelstat/bin/node_modules/<name>`.
|
|
235
|
+
* Symlinks are free + fast; if symlinking fails (filesystem
|
|
236
|
+
* boundary, permissions) fall back to a recursive copy with
|
|
237
|
+
* `dereference:true` so the resulting tree has no dangling
|
|
238
|
+
* refs into the source location.
|
|
239
|
+
*
|
|
240
|
+
* Idempotent: each upgrade clears the destination first.
|
|
241
|
+
*/
|
|
242
|
+
async function setupNativeNodeModules(installedBundle) {
|
|
243
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
244
|
+
// Find a parent `node_modules` containing `node-llama-cpp`. The
|
|
245
|
+
// walk handles npm flat (<prefix>/lib/node_modules), pnpm flat
|
|
246
|
+
// (<prefix>/lib/node_modules with peer hoisting), and the npx
|
|
247
|
+
// cache layout (~/.npm/_npx/<hash>/node_modules).
|
|
248
|
+
let srcNodeModules = null;
|
|
249
|
+
for (let dir = here, i = 0; i < 8; i++) {
|
|
250
|
+
const probe = join(dir, "node_modules", "node-llama-cpp", "package.json");
|
|
251
|
+
if (existsSync(probe)) {
|
|
252
|
+
srcNodeModules = join(dir, "node_modules");
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
const up = resolve(dir, "..");
|
|
256
|
+
if (up === dir) break;
|
|
257
|
+
dir = up;
|
|
258
|
+
}
|
|
259
|
+
if (!srcNodeModules) {
|
|
260
|
+
console.warn(
|
|
261
|
+
"[modelstat] couldn't locate node-llama-cpp in this install — bundled summariser will fail at preflight. Re-install with `npm i -g modelstat` or report a bug.",
|
|
262
|
+
);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const fs = await import("node:fs/promises");
|
|
267
|
+
const destDir = join(dirname(installedBundle), "node_modules");
|
|
268
|
+
await fs.mkdir(destDir, { recursive: true });
|
|
269
|
+
|
|
270
|
+
// Discover every native package we need: the main one + every
|
|
271
|
+
// platform-specific sibling (the binary blob is in one of the
|
|
272
|
+
// `@node-llama-cpp/*` packages chosen by node-llama-cpp's
|
|
273
|
+
// optional-dependencies resolution at install time).
|
|
274
|
+
const wanted = new Set(["node-llama-cpp"]);
|
|
275
|
+
const all = await fs
|
|
276
|
+
.readdir(srcNodeModules, { withFileTypes: true })
|
|
277
|
+
.catch(() => []);
|
|
278
|
+
for (const e of all) {
|
|
279
|
+
if (!e.isDirectory()) continue;
|
|
280
|
+
if (!e.name.startsWith("@")) continue;
|
|
281
|
+
if (
|
|
282
|
+
e.name === "@node-llama-cpp" ||
|
|
283
|
+
e.name === "@reflink"
|
|
284
|
+
) {
|
|
285
|
+
// Scoped dirs contain multiple packages — copy/symlink the
|
|
286
|
+
// whole scope dir so all platform variants are reachable.
|
|
287
|
+
wanted.add(e.name);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
for (const pkg of wanted) {
|
|
292
|
+
const src = join(srcNodeModules, pkg);
|
|
293
|
+
const dest = join(destDir, pkg);
|
|
294
|
+
if (!existsSync(src)) continue;
|
|
295
|
+
try {
|
|
296
|
+
await fs.rm(dest, { recursive: true, force: true });
|
|
297
|
+
} catch {
|
|
298
|
+
/* ignore */
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
await fs.symlink(src, dest, "dir");
|
|
302
|
+
} catch {
|
|
303
|
+
try {
|
|
304
|
+
await fs.cp(src, dest, { recursive: true, dereference: true });
|
|
305
|
+
} catch (err2) {
|
|
306
|
+
console.warn(
|
|
307
|
+
`[modelstat] couldn't link ${pkg}: ${err2 && err2.message ? err2.message : err2}`,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
212
314
|
/**
|
|
213
315
|
* Kill any daemon process the service supervisor didn't reap.
|
|
214
316
|
* Reads ~/.modelstat/daemon.lock for the PID, sends SIGTERM, then
|