@gorlitzer-labs/seldon 0.1.10 → 0.1.12

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 +56 -9
  2. package/package.json +1 -1
package/bin/seldon.js CHANGED
@@ -253,6 +253,8 @@ function confirm(question) {
253
253
  readline.emitKeypressEvents(process.stdin);
254
254
  process.stdin.setRawMode(true);
255
255
  process.stdin.resume();
256
+ process.stdin.ref(); // a prior picker/prompt may have unref'd stdin; without
257
+ // this the loop empties and we exit before reading a key
256
258
  const onKey = (str, key) => {
257
259
  process.stdin.off("keypress", onKey);
258
260
  process.stdin.setRawMode(false);
@@ -379,14 +381,51 @@ function down() {
379
381
  console.log(stopped.length ? C.green("stopped: ") + stopped.join(", ") : C.dim("nothing was running."));
380
382
  }
381
383
 
384
+ // Version of a globally-installed node package, across pnpm / npm / bun roots.
385
+ function npmGlobalVersion(pkg) {
386
+ const roots = [];
387
+ for (const c of ["pnpm root -g", "npm root -g"]) {
388
+ try { roots.push(execSync(c, { stdio: ["ignore", "pipe", "ignore"] }).toString().trim()); } catch {}
389
+ }
390
+ roots.push(path.join(process.env.HOME, ".bun/install/global/node_modules"));
391
+ for (const r of roots) {
392
+ try { const pj = path.join(r, pkg, "package.json"); if (fs.existsSync(pj)) return JSON.parse(fs.readFileSync(pj, "utf8")).version; } catch {}
393
+ }
394
+ return "";
395
+ }
396
+ function bifrostVersion() {
397
+ for (const p of [path.join(process.env.HOME, "bin", "bifrost"), path.join(process.env.HOME, ".local/bin/bifrost")]) {
398
+ try { if (fs.existsSync(p)) { const mm = fs.readFileSync(p, "utf8").match(/BIFROST_VERSION=["']?([\d.]+)/); return mm ? mm[1] : "installed"; } } catch {}
399
+ }
400
+ return "";
401
+ }
402
+ function moduleInstalled(m) {
403
+ if (m.method === "python") return demerzelInstalled();
404
+ if (m.method === "shell") return has(m.bin) || fs.existsSync(path.join(process.env.HOME, "bin", m.bin)) || fs.existsSync(path.join(process.env.HOME, ".local/bin", m.bin));
405
+ return has(m.bin);
406
+ }
407
+
382
408
  function statusCmd() {
383
- console.log(C.bold("\nseldon services\n"));
384
- const rows = [["Voice (demerzel)", "demerzel"], ["Supervisor (factory watch)", "factory-watch"]];
385
- for (const [label, name] of rows) {
386
- const pid = daemonUp(name);
387
- console.log(` ${label.padEnd(28)} ${pid ? C.green("up") + C.dim(` (pid ${pid})`) : C.dim("down")}`);
409
+ console.log(C.bold("\n seldon — stack status\n"));
410
+ for (const m of MODULES) {
411
+ const inst = moduleInstalled(m);
412
+ const dot = inst ? C.green("●") : C.dim("○");
413
+ let detail;
414
+ if (!inst) detail = platformOk(m) ? C.dim(`not installed ${C.dim("· seldon install " + m.id)}`) : C.dim("not supported on this machine");
415
+ else if (m.method === "npm") detail = C.dim("v" + (npmGlobalVersion(m.pkg) || "?"));
416
+ else if (m.id === "bifrost") detail = C.dim("v" + (bifrostVersion() || "?"));
417
+ else if (m.id === "demerzel") detail = demerzelModelsReady() ? C.dim("venv + models ✓") : C.gold("venv ok · models not fetched (seldon up)");
418
+ else detail = C.dim("installed");
419
+
420
+ // service state for the two daemons
421
+ let svc = "";
422
+ if (m.id === "factory") { const p = daemonUp("factory-watch"); svc = p ? " " + C.green("supervisor up") + C.dim(` (pid ${p})`) : " " + C.dim("supervisor down"); }
423
+ if (m.id === "demerzel" && inst) { const p = daemonUp("demerzel"); svc = p ? " " + C.green("voice up") + " " + C.cyan("http://localhost:8770") : " " + C.dim("voice down"); }
424
+
425
+ console.log(` ${dot} ${C.bold(m.id.padEnd(11))} ${detail}${svc}`);
388
426
  }
389
- console.log(C.dim(`\n logs: ${RUN_DIR}/<service>.log\n`));
427
+ if (demerzelInstalled()) console.log(C.dim(`\n demerzel LLM: ${process.env.DEMERZEL_LLM || "mlx-community/Qwen3.6-35B-A3B-4bit (default)"}`));
428
+ console.log(C.dim(`\n start: seldon up · stop: seldon down · logs: ${RUN_DIR}/\n`));
390
429
  }
391
430
 
392
431
  // ---- the checklist TUI ------------------------------------------------------
@@ -400,7 +439,14 @@ const BANNER = [
400
439
  ];
401
440
  function tui() {
402
441
  return new Promise((resolve) => {
403
- const rows = MODULES.map((m) => ({ m, on: platformOk(m) && ["apiary", "foundation", "factory"].includes(m.id) }));
442
+ // Pre-check what's already installed so the picker mirrors reality. On a
443
+ // fresh machine (nothing installed) fall back to the recommended starter set.
444
+ const anyInstalled = MODULES.some((m) => moduleInstalled(m));
445
+ const rows = MODULES.map((m) => ({
446
+ m,
447
+ installed: moduleInstalled(m),
448
+ on: platformOk(m) && (anyInstalled ? moduleInstalled(m) : ["apiary", "foundation", "factory"].includes(m.id)),
449
+ }));
404
450
  let cur = 0;
405
451
  const methodTag = (m) => ({ npm: "npm", shell: "shell", python: "python" }[m.method]);
406
452
  const draw = () => {
@@ -408,7 +454,7 @@ function tui() {
408
454
  readline.clearScreenDown(process.stdout);
409
455
  const out = [];
410
456
  BANNER.forEach((l) => out.push(C.gold(l)));
411
- out.push(C.dim(" the AI-agent-factory stack — pick your tools"));
457
+ out.push(C.dim(" the AI-agent-factory stack — pick your tools ") + C.green("✓ = installed"));
412
458
  out.push(C.dim(" ↑↓ move · space toggle · a all · enter install · q quit\n"));
413
459
  rows.forEach((r, i) => {
414
460
  const sel = r.on ? C.green("[x]") : "[ ]";
@@ -417,7 +463,8 @@ function tui() {
417
463
  const name = i === cur ? C.bold(r.m.id.padEnd(11)) : r.m.id.padEnd(11);
418
464
  const deps = r.m.needs.map((d) => (depOk(d) ? d : C.red(d))).join(" ");
419
465
  const platNote = okp ? C.red(" (unsupported OS)") : "";
420
- out.push(` ${cursor} ${sel} ${name} ${C.dim(methodTag(r.m).padEnd(7))} ${C.dim(r.m.blurb)}${platNote}`);
466
+ const mark = r.installed ? C.green("✓") : " ";
467
+ out.push(` ${cursor} ${sel} ${mark} ${name} ${C.dim(methodTag(r.m).padEnd(7))} ${C.dim(r.m.blurb)}${platNote}`);
421
468
  if (i === cur) out.push(` ${C.dim("needs: " + (deps || "nothing"))}${r.m.requires.length ? C.dim(" · pulls in: " + r.m.requires.join(", ")) : ""}`);
422
469
  });
423
470
  process.stdout.write(out.join("\n") + "\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gorlitzer-labs/seldon",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
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": {