@gorlitzer-labs/seldon 0.1.20 → 0.1.21

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 (2) hide show
  1. package/bin/seldon.js +22 -5
  2. package/package.json +1 -1
package/bin/seldon.js CHANGED
@@ -158,7 +158,11 @@ function installPython(m, dev) {
158
158
  const venvArgs = ["venv", venv, "--seed"]; // --seed puts pip in the venv:
159
159
  // kokoro/misaki/spaCy shells out to pip at runtime to load its model, and a
160
160
  // bare uv venv has none (crashes the voice on start otherwise).
161
- if (m.pyVersion) venvArgs.push("--python", m.pyVersion); // uv fetches a standalone CPython
161
+ // uv fetches a standalone CPython — but only if told to. By default it PREFERS
162
+ // a matching system interpreter, and a python.org framework build ships with
163
+ // no CA bundle, so the venv's urllib failed every HTTPS download (the CAM++
164
+ // voiceprint model silently never arrived). only-managed makes the comment true.
165
+ if (m.pyVersion) venvArgs.push("--python", m.pyVersion, "--python-preference", "only-managed");
162
166
  if (!run(uv, venvArgs)) return false;
163
167
  ok = run(uv, ["pip", "install", "--python", path.join(venv, "bin", "python"), "-r", req]);
164
168
  } else {
@@ -344,11 +348,24 @@ function stopDaemon(name) {
344
348
  try { fs.rmSync(pidFile(name), { force: true }); } catch {}
345
349
  return true;
346
350
  }
347
- // demerzel needs its model set in the HF cache before it can serve.
348
- function demerzelModelsReady() {
351
+ // demerzel needs its model set before it can serve. Check each model it loads by
352
+ // name — "any models-- dir in the HF cache" was true after a fetch died halfway,
353
+ // so the one it died on (the CAM++ voiceprint, the last download) was never
354
+ // offered again. The LLM is not listed: which one depends on the brain, and
355
+ // bonsai brings its own. Returns the missing labels; [] means ready.
356
+ function demerzelModelsMissing() {
349
357
  const hub = path.join(process.env.HOME, ".cache", "huggingface", "hub");
350
- try { return fs.existsSync(hub) && fs.readdirSync(hub).some((d) => d.startsWith("models--")); } catch { return false; }
358
+ const snapshotOk = (repo) => {
359
+ const snaps = path.join(hub, "models--" + repo.replace("/", "--"), "snapshots");
360
+ try { return fs.readdirSync(snaps).some((d) => fs.readdirSync(path.join(snaps, d)).length > 0); } catch { return false; }
361
+ };
362
+ const missing = [];
363
+ if (!snapshotOk("mlx-community/Qwen3-ASR-1.7B-8bit")) missing.push("ears (Qwen3-ASR)");
364
+ if (!snapshotOk("hexgrad/Kokoro-82M")) missing.push("voice (Kokoro)");
365
+ if (!fs.existsSync(path.join(SELDON_HOME, "demerzel", "models", "campplus_en.onnx"))) missing.push("voiceprint (CAM++)");
366
+ return missing;
351
367
  }
368
+ const demerzelModelsReady = () => demerzelModelsMissing().length === 0;
352
369
  const demerzelInstalled = () => fs.existsSync(path.join(SELDON_HOME, "demerzel", ".venv", "bin", "python"));
353
370
 
354
371
  // This machine's Tailscale IPv4 (100.64.0.0/10), or null. Tries PATH then the
@@ -674,7 +691,7 @@ function statusCmd() {
674
691
  if (!inst) detail = platformOk(m) ? C.dim(`not installed ${C.dim("· seldon install " + m.id)}`) : C.dim("not supported on this machine");
675
692
  else if (m.method === "npm") detail = C.dim("v" + (npmGlobalVersion(m.pkg) || "?"));
676
693
  else if (m.id === "bifrost") detail = C.dim("v" + (bifrostVersion() || "?"));
677
- else if (m.id === "demerzel") detail = demerzelModelsReady() ? C.dim("venv + models ✓") : C.gold("venv ok · models not fetched (seldon up)");
694
+ else if (m.id === "demerzel") detail = demerzelModelsReady() ? C.dim("venv + models ✓") : C.gold(`venv ok · missing ${demerzelModelsMissing().join(", ")} (seldon up)`);
678
695
  else detail = C.dim("installed");
679
696
 
680
697
  // service state for the two daemons
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gorlitzer-labs/seldon",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Install the Seldon stack — pick your tools from a checklist; each installs via its native method.",
5
5
  "type": "module",
6
6
  "bin": {