@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.
- package/bin/seldon.js +22 -5
- 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
|
-
|
|
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
|
|
348
|
-
|
|
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
|
-
|
|
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(
|
|
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
|