@gorlitzer-labs/seldon 0.1.1 → 0.1.3
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 +7 -0
- package/bin/seldon.js +62 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,6 +49,13 @@ It's a stack, not a bundle — install only what you use:
|
|
|
49
49
|
- **A team of agents** → add **apiary** (shared rooms) + **factory** (the supervisor).
|
|
50
50
|
- **Across machines / from your phone** → add **bifrost**.
|
|
51
51
|
|
|
52
|
+
## Package managers
|
|
53
|
+
|
|
54
|
+
Node tools install via **pnpm** or **bun** if present (much faster than npm), else npm —
|
|
55
|
+
override with `seldon install --pm=pnpm|bun|npm`. demerzel (Python) always installs into
|
|
56
|
+
its **own isolated venv** — never your system/active Python — using **uv** if available,
|
|
57
|
+
else `python3 -m venv` + pip.
|
|
58
|
+
|
|
52
59
|
## From a checkout
|
|
53
60
|
|
|
54
61
|
```bash
|
package/bin/seldon.js
CHANGED
|
@@ -52,14 +52,44 @@ function run(cmd, args, opts = {}) {
|
|
|
52
52
|
return r.status === 0;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// Is a command on PATH? (used to pick the fastest package manager)
|
|
56
|
+
const has = (bin) => { try { execSync(`command -v ${bin}`, { stdio: "ignore" }); return true; } catch { return false; } };
|
|
57
|
+
|
|
58
|
+
// pnpm can only `add -g` when a global bin dir is configured (else ERR_PNPM_NO_GLOBAL_BIN_DIR).
|
|
59
|
+
const pnpmGlobalReady = () => {
|
|
60
|
+
if (process.env.PNPM_HOME) return true;
|
|
61
|
+
try {
|
|
62
|
+
const d = execSync("pnpm config get global-bin-dir", { stdio: ["ignore", "pipe", "ignore"] }).toString().trim();
|
|
63
|
+
return !!d && d !== "undefined" && d !== "null";
|
|
64
|
+
} catch { return false; }
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Pick the node package manager: --pm=<x> override, else the fastest that can
|
|
68
|
+
// actually global-install; npm is the universal fallback.
|
|
69
|
+
function nodePM() {
|
|
70
|
+
const ov = (process.argv.find((a) => a.startsWith("--pm=")) || "").split("=")[1];
|
|
71
|
+
if (ov) return ov;
|
|
72
|
+
if (has("pnpm") && pnpmGlobalReady()) return "pnpm";
|
|
73
|
+
if (has("bun")) return "bun";
|
|
74
|
+
return "npm";
|
|
75
|
+
}
|
|
76
|
+
|
|
55
77
|
function installNpm(m, dev) {
|
|
78
|
+
const pm = nodePM();
|
|
56
79
|
if (dev && IN_CHECKOUT) {
|
|
57
80
|
const dir = path.join(REPO_ROOT, m.dir);
|
|
58
81
|
const pj = JSON.parse(fs.readFileSync(path.join(dir, "package.json")));
|
|
59
|
-
if (pj.scripts?.build) run(
|
|
60
|
-
|
|
82
|
+
if (pj.scripts?.build) run(pm, ["run", "build"], { cwd: dir });
|
|
83
|
+
const link = pm === "pnpm" ? ["link", "--global"] : ["link"]; // bun/npm: `link`
|
|
84
|
+
if (run(pm, link, { cwd: dir })) return true;
|
|
85
|
+
if (pm !== "npm") { console.log(C.dim(" falling back to npm link…")); return run("npm", ["link"], { cwd: dir }); }
|
|
86
|
+
return false;
|
|
61
87
|
}
|
|
62
|
-
|
|
88
|
+
// pnpm/bun: `add -g` · npm: `install -g` — a global CLI, no project touched
|
|
89
|
+
const add = pm === "npm" ? ["install", "-g", m.pkg] : ["add", "-g", m.pkg];
|
|
90
|
+
if (run(pm, add)) return true;
|
|
91
|
+
if (pm !== "npm") { console.log(C.dim(` ${pm} failed — falling back to npm…`)); return run("npm", ["install", "-g", m.pkg]); }
|
|
92
|
+
return false;
|
|
63
93
|
}
|
|
64
94
|
|
|
65
95
|
function installShell(m, dev) {
|
|
@@ -80,16 +110,32 @@ function installPython(m, dev) {
|
|
|
80
110
|
if (!(dev && IN_CHECKOUT)) {
|
|
81
111
|
console.log(C.dim(` fetching ${m.id} into ${dest}`));
|
|
82
112
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
83
|
-
if (
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
if (fs.existsSync(path.join(dest, ".git"))) {
|
|
114
|
+
run("git", ["-C", dest, "pull", "--ff-only"]); // already cloned → update in place
|
|
115
|
+
} else {
|
|
116
|
+
const tmp = dest + ".tmp";
|
|
117
|
+
fs.rmSync(tmp, { recursive: true, force: true }); // clear any stale tmp
|
|
118
|
+
if (!run("git", ["clone", "--depth", "1", `https://github.com/${MONOREPO}.git`, tmp])) return false;
|
|
119
|
+
fs.rmSync(dest, { recursive: true, force: true }); // dest must not exist before rename (fixes ENOTEMPTY)
|
|
120
|
+
fs.renameSync(path.join(tmp, m.dir), dest);
|
|
121
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
87
122
|
}
|
|
88
123
|
}
|
|
124
|
+
// Always a DEDICATED venv under the module dir — we never install into the
|
|
125
|
+
// user's system/global/active Python. uv (if present) is faster and can even
|
|
126
|
+
// fetch its own CPython, so it doesn't touch their interpreter at all; plain
|
|
127
|
+
// venv+pip is the isolated fallback. No `--system`, no active-env writes.
|
|
89
128
|
const venv = path.join(dest, ".venv");
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (
|
|
129
|
+
const req = path.join(dest, "requirements.txt");
|
|
130
|
+
let ok;
|
|
131
|
+
if (has("uv")) {
|
|
132
|
+
if (!run("uv", ["venv", venv])) return false;
|
|
133
|
+
ok = run("uv", ["pip", "install", "--python", path.join(venv, "bin", "python"), "-r", req]);
|
|
134
|
+
} else {
|
|
135
|
+
run("python3", ["-m", "venv", venv]);
|
|
136
|
+
ok = run(path.join(venv, "bin", "pip"), ["install", "-r", req]);
|
|
137
|
+
}
|
|
138
|
+
if (ok) console.log(C.dim(` run it: ${path.join(dest, m.bin)} (isolated venv at ${venv})`));
|
|
93
139
|
return ok;
|
|
94
140
|
}
|
|
95
141
|
|
|
@@ -138,7 +184,7 @@ function tui() {
|
|
|
138
184
|
const sel = r.on ? C.green("[x]") : "[ ]";
|
|
139
185
|
const cursor = i === cur ? C.gold("❯") : " ";
|
|
140
186
|
const okp = !platformOk(r.m);
|
|
141
|
-
const name =
|
|
187
|
+
const name = i === cur ? C.bold(r.m.id.padEnd(11)) : r.m.id.padEnd(11);
|
|
142
188
|
const deps = r.m.needs.map((d) => (depOk(d) ? d : C.red(d))).join(" ");
|
|
143
189
|
const platNote = okp ? C.red(" (unsupported OS)") : "";
|
|
144
190
|
out.push(` ${cursor} ${sel} ${name} ${C.dim(methodTag(r.m).padEnd(7))} ${C.dim(r.m.blurb)}${platNote}`);
|
|
@@ -186,6 +232,11 @@ ${C.bold("seldon")} — install the Seldon stack, pick what you use.
|
|
|
186
232
|
${C.bold("seldon doctor")} [ids…] check external deps (tmux, sops, age, tailscale, python…)
|
|
187
233
|
${C.bold("seldon list")} list the modules
|
|
188
234
|
${C.bold("seldon --dev")} link node modules from this checkout instead of npm
|
|
235
|
+
${C.bold("seldon install --pm=pnpm")} force the node package manager (pnpm|bun|npm; auto-detected)
|
|
236
|
+
|
|
237
|
+
${C.dim("node tools install via pnpm/bun if present (faster), else npm.")}
|
|
238
|
+
${C.dim("python (demerzel) installs into its own isolated venv — never your system Python;")}
|
|
239
|
+
${C.dim("uses uv if present, else python3 -m venv + pip.")}
|
|
189
240
|
|
|
190
241
|
modules: ${MODULES.map((m) => m.id).join(", ")}
|
|
191
242
|
`);
|