@gorlitzer-labs/seldon 0.1.19 → 0.1.20

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/README.md CHANGED
@@ -37,7 +37,9 @@ seldon up # starts the voice (demerzel) + the supervisor (factory wat
37
37
  # then prints: Voice → http://localhost:8770, how to put agents
38
38
  # to work, rooms, phone access
39
39
  seldon up --tailnet # also expose the voice on your tailnet → reach it from your phone
40
- seldon status # what's running (pids)
40
+ seldon status # what's running (pids) — and warns if docker's daemon is down
41
+ seldon adopt [dir] # put an existing repo on the line (foundation · hive · supervised)
42
+ # and print what's next from its queue. Safe to re-run.
41
43
  seldon down # stop everything
42
44
  ```
43
45
 
package/bin/seldon.js CHANGED
@@ -330,7 +330,9 @@ function startDaemon(name, cmd, args, opts = {}) {
330
330
  if (daemonUp(name)) return { already: true, pid: readPid(name) };
331
331
  fs.mkdirSync(RUN_DIR, { recursive: true });
332
332
  const log = fs.openSync(path.join(RUN_DIR, name + ".log"), "a");
333
- const child = spawn(cmd, args, { detached: true, stdio: ["ignore", log, log], ...opts });
333
+ // cwd defaults to SELDON_HOME: a long-lived daemon must not pin whatever folder
334
+ // `seldon up` was typed in (it did — the supervisor held a project dir open).
335
+ const child = spawn(cmd, args, { detached: true, stdio: ["ignore", log, log], cwd: SELDON_HOME, ...opts });
334
336
  fs.writeFileSync(pidFile(name), String(child.pid));
335
337
  child.unref();
336
338
  return { pid: child.pid };
@@ -593,6 +595,7 @@ async function up() {
593
595
 
594
596
  // The rest are on-demand, not daemons — point at the command.
595
597
  if (has("factory")) go.push(`${C.bold("Put agents to work")} ${C.cyan('factory new "<your idea>"')} ${C.dim("→ repo · foundation · apiary hive")}`);
598
+ if (has("factory")) go.push(`${C.bold("An existing repo")} ${C.cyan("seldon adopt [dir]")} ${C.dim("→ foundation (keeps your docs) · hive · supervised")}`);
596
599
  if (has("apiary")) go.push(`${C.bold("Agent rooms")} ${C.cyan("apiary ps")} ${C.dim("(active rooms + join links)")}`);
597
600
  if (has("bifrost")) go.push(`${C.bold("Across machines / phone")} ${C.cyan("bifrost sessions")}`);
598
601
 
@@ -690,9 +693,31 @@ function statusCmd() {
690
693
  const phone = tailscaleServeUrl();
691
694
  if (phone) console.log(C.dim(" phone (HTTPS): ") + C.cyan(phone));
692
695
  }
696
+ const dk = dockerState();
697
+ if (dk === "down") console.log(C.gold("\n ⚠ docker: installed but the daemon is not running") + C.dim(" — factory box and containerised gates need it (open Docker Desktop)"));
698
+ else if (dk === "up") console.log(C.dim("\n docker: ") + C.green("up"));
693
699
  console.log(C.dim(`\n start: seldon up · stop: seldon down · logs: ${RUN_DIR}/\n`));
694
700
  }
695
701
 
702
+ // "none" (no docker CLI) | "down" (CLI but no daemon) | "up". Only shown when docker exists.
703
+ function dockerState() {
704
+ if (!has("docker")) return "none";
705
+ try { execSync("docker info", { stdio: "ignore", timeout: 8000 }); return "up"; } catch { return "down"; }
706
+ }
707
+
708
+ // ---- adopt: bring an existing repo onto the line ----------------------------
709
+ // factory owns the registry + hive, so this is a front door onto `factory adopt`.
710
+ function adopt(target) {
711
+ if (!has("factory")) {
712
+ console.log(C.red(" adopt needs factory — install it: ") + C.cyan("seldon install factory"));
713
+ process.exitCode = 1; return;
714
+ }
715
+ const passthru = process.argv.slice(3).filter((a) => a !== "--dev");
716
+ const r = spawnSync("factory", ["adopt", ...passthru], { stdio: "inherit" });
717
+ if (r.status !== 0) { process.exitCode = r.status || 1; return; }
718
+ if (!daemonUp("factory-watch")) console.log(C.gold(" the supervisor is not running — ") + C.cyan("seldon up") + C.dim(" starts it, so agents here get healed and nudged.") + "\n");
719
+ }
720
+
696
721
  // ---- the checklist TUI ------------------------------------------------------
697
722
  const BANNER = [
698
723
  " ███████╗███████╗██╗ ██████╗ ██████╗ ███╗ ██╗",
@@ -776,6 +801,8 @@ ${C.bold("seldon")} — install the Seldon stack, pick what you use.
776
801
  ${C.bold("seldon up --tailnet")} expose the voice over HTTPS (tailscale serve) so the mic works on your phone
777
802
  ${C.bold("seldon up --brain=X")} pick the voice brain: qwen (in-process) | bonsai (local server); remembered
778
803
  ${C.bold("seldon status")} what's running · ${C.bold("seldon down")} stop it
804
+ ${C.bold("seldon adopt")} [dir] put an existing repo on the line: foundation docs (never overwritten),
805
+ an apiary hive, supervised by factory — and print what's next. Safe to re-run.
779
806
  ${C.bold("seldon install")} [ids…] install everything picked, or the named modules
780
807
  ${C.bold("seldon uninstall")} ids… remove the named modules (global CLI / isolated venv)
781
808
  ${C.bold("seldon uninstall --all")} remove the whole stack (also drops ~/.seldon)
@@ -817,6 +844,7 @@ const ids = tokens.filter((id) => byId[id]); // only the valid module
817
844
  if (cmd === "up") return up();
818
845
  if (cmd === "down") return down();
819
846
  if (cmd === "status") return statusCmd();
847
+ if (cmd === "adopt") return adopt(tokens[0]);
820
848
  if (cmd && cmd !== "install") { help(); process.exitCode = 1; return; }
821
849
  // interactive
822
850
  if (!process.stdin.isTTY) { console.log(C.red("no TTY — use: seldon install <ids…>")); process.exitCode = 1; return; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gorlitzer-labs/seldon",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
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": {