@gorlitzer-labs/seldon 0.1.0 → 0.1.2
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 +58 -11
- package/bin/seldon.js +50 -8
- package/package.json +24 -6
package/README.md
CHANGED
|
@@ -1,18 +1,65 @@
|
|
|
1
1
|
# @gorlitzer-labs/seldon
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
```
|
|
4
|
+
███████╗███████╗██╗ ██████╗ ██████╗ ███╗ ██╗
|
|
5
|
+
██╔════╝██╔════╝██║ ██╔══██╗██╔═══██╗████╗ ██║
|
|
6
|
+
███████╗█████╗ ██║ ██║ ██║██║ ██║██╔██╗ ██║
|
|
7
|
+
╚════██║██╔══╝ ██║ ██║ ██║██║ ██║██║╚██╗██║
|
|
8
|
+
███████║███████╗███████╗██████╔╝╚██████╔╝██║ ╚████║
|
|
9
|
+
╚══════╝╚══════╝╚══════╝╚═════╝ ╚═════╝ ╚═╝ ╚═══╝
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**The installer for the Seldon stack** — a software factory of AI agents.
|
|
13
|
+
Pick the tools you want from a checklist; each installs via its native method
|
|
14
|
+
(npm for the Node tools, a shell installer for bifrost, a venv for demerzel).
|
|
15
|
+
|
|
16
|
+
## Install
|
|
6
17
|
|
|
7
18
|
```bash
|
|
8
19
|
npm i -g @gorlitzer-labs/seldon
|
|
9
|
-
seldon # open the checklist — space
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
20
|
+
seldon # open the checklist — ↑↓ move · space pick · a all · enter install
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or name the modules directly:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
seldon install foundation comb # install just these
|
|
27
|
+
seldon doctor # check external deps (tmux, sops, age, tailscale, python)
|
|
28
|
+
seldon list # everything available
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## The stack
|
|
32
|
+
|
|
33
|
+
| module | what it is | ships via |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| **foundation** | the seam — a deterministic plan agents follow | npm |
|
|
36
|
+
| **apiary** | the conversation — shared rooms where agents coordinate | npm |
|
|
37
|
+
| **comb** | the vault — keys by name, never by value | npm |
|
|
38
|
+
| **factory** | the floor — 24/7 supervisor + sandboxed agents | npm |
|
|
39
|
+
| **bifrost** | the bridge — many machines, one workspace | shell |
|
|
40
|
+
| **demerzel** | the voice — a fully-local voice assistant | python (macOS / Apple silicon) |
|
|
41
|
+
|
|
42
|
+
Ticking **factory** auto-includes **apiary** + **foundation** (it needs them on PATH).
|
|
43
|
+
|
|
44
|
+
## Pick the combo for the job
|
|
45
|
+
|
|
46
|
+
It's a stack, not a bundle — install only what you use:
|
|
47
|
+
|
|
48
|
+
- **Solo, one agent** → `seldon install foundation comb` — a plan + secured keys. Add **factory** for the sandbox, **demerzel** for voice.
|
|
49
|
+
- **A team of agents** → add **apiary** (shared rooms) + **factory** (the supervisor).
|
|
50
|
+
- **Across machines / from your phone** → add **bifrost**.
|
|
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
|
+
|
|
59
|
+
## From a checkout
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
seldon --dev # link Node modules from a monorepo checkout instead of npm
|
|
14
63
|
```
|
|
15
64
|
|
|
16
|
-
|
|
17
|
-
Ticking `factory` auto-includes `apiary` + `foundation` (it needs them on PATH).
|
|
18
|
-
`demerzel` is offered only on macOS / Apple silicon.
|
|
65
|
+
Part of the [seldon](https://github.com/gorlitzer-labs/seldon) monorepo.
|
package/bin/seldon.js
CHANGED
|
@@ -52,14 +52,31 @@ 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
|
+
// Pick the node package manager: --pm=<x> override, else the fastest present.
|
|
59
|
+
// pnpm/bun install globally far faster than npm; npm is the universal fallback.
|
|
60
|
+
function nodePM() {
|
|
61
|
+
const ov = (process.argv.find((a) => a.startsWith("--pm=")) || "").split("=")[1];
|
|
62
|
+
if (ov) return ov;
|
|
63
|
+
if (has("pnpm")) return "pnpm";
|
|
64
|
+
if (has("bun")) return "bun";
|
|
65
|
+
return "npm";
|
|
66
|
+
}
|
|
67
|
+
|
|
55
68
|
function installNpm(m, dev) {
|
|
69
|
+
const pm = nodePM();
|
|
56
70
|
if (dev && IN_CHECKOUT) {
|
|
57
71
|
const dir = path.join(REPO_ROOT, m.dir);
|
|
58
72
|
const pj = JSON.parse(fs.readFileSync(path.join(dir, "package.json")));
|
|
59
|
-
if (pj.scripts?.build) run(
|
|
60
|
-
|
|
73
|
+
if (pj.scripts?.build) run(pm, ["run", "build"], { cwd: dir });
|
|
74
|
+
const link = pm === "pnpm" ? ["link", "--global"] : ["link"]; // bun/npm: `link`
|
|
75
|
+
return run(pm, link, { cwd: dir });
|
|
61
76
|
}
|
|
62
|
-
|
|
77
|
+
// pnpm/bun: `add -g` · npm: `install -g` — a global CLI, no project touched
|
|
78
|
+
const add = pm === "npm" ? ["install", "-g", m.pkg] : ["add", "-g", m.pkg];
|
|
79
|
+
return run(pm, add);
|
|
63
80
|
}
|
|
64
81
|
|
|
65
82
|
function installShell(m, dev) {
|
|
@@ -86,10 +103,21 @@ function installPython(m, dev) {
|
|
|
86
103
|
fs.rmSync(dest + ".tmp", { recursive: true, force: true });
|
|
87
104
|
}
|
|
88
105
|
}
|
|
106
|
+
// Always a DEDICATED venv under the module dir — we never install into the
|
|
107
|
+
// user's system/global/active Python. uv (if present) is faster and can even
|
|
108
|
+
// fetch its own CPython, so it doesn't touch their interpreter at all; plain
|
|
109
|
+
// venv+pip is the isolated fallback. No `--system`, no active-env writes.
|
|
89
110
|
const venv = path.join(dest, ".venv");
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (
|
|
111
|
+
const req = path.join(dest, "requirements.txt");
|
|
112
|
+
let ok;
|
|
113
|
+
if (has("uv")) {
|
|
114
|
+
if (!run("uv", ["venv", venv])) return false;
|
|
115
|
+
ok = run("uv", ["pip", "install", "--python", path.join(venv, "bin", "python"), "-r", req]);
|
|
116
|
+
} else {
|
|
117
|
+
run("python3", ["-m", "venv", venv]);
|
|
118
|
+
ok = run(path.join(venv, "bin", "pip"), ["install", "-r", req]);
|
|
119
|
+
}
|
|
120
|
+
if (ok) console.log(C.dim(` run it: ${path.join(dest, m.bin)} (isolated venv at ${venv})`));
|
|
93
121
|
return ok;
|
|
94
122
|
}
|
|
95
123
|
|
|
@@ -114,6 +142,14 @@ function doInstall(ids, { dev } = {}) {
|
|
|
114
142
|
}
|
|
115
143
|
|
|
116
144
|
// ---- the checklist TUI ------------------------------------------------------
|
|
145
|
+
const BANNER = [
|
|
146
|
+
" ███████╗███████╗██╗ ██████╗ ██████╗ ███╗ ██╗",
|
|
147
|
+
" ██╔════╝██╔════╝██║ ██╔══██╗██╔═══██╗████╗ ██║",
|
|
148
|
+
" ███████╗█████╗ ██║ ██║ ██║██║ ██║██╔██╗ ██║",
|
|
149
|
+
" ╚════██║██╔══╝ ██║ ██║ ██║██║ ██║██║╚██╗██║",
|
|
150
|
+
" ███████║███████╗███████╗██████╔╝╚██████╔╝██║ ╚████║",
|
|
151
|
+
" ╚══════╝╚══════╝╚══════╝╚═════╝ ╚═════╝ ╚═╝ ╚═══╝",
|
|
152
|
+
];
|
|
117
153
|
function tui() {
|
|
118
154
|
return new Promise((resolve) => {
|
|
119
155
|
const rows = MODULES.map((m) => ({ m, on: platformOk(m) && ["apiary", "foundation", "factory"].includes(m.id) }));
|
|
@@ -123,13 +159,14 @@ function tui() {
|
|
|
123
159
|
readline.cursorTo(process.stdout, 0, 0);
|
|
124
160
|
readline.clearScreenDown(process.stdout);
|
|
125
161
|
const out = [];
|
|
126
|
-
out.push(C.
|
|
162
|
+
BANNER.forEach((l) => out.push(C.gold(l)));
|
|
163
|
+
out.push(C.dim(" the AI-agent-factory stack — pick your tools"));
|
|
127
164
|
out.push(C.dim(" ↑↓ move · space toggle · a all · enter install · q quit\n"));
|
|
128
165
|
rows.forEach((r, i) => {
|
|
129
166
|
const sel = r.on ? C.green("[x]") : "[ ]";
|
|
130
167
|
const cursor = i === cur ? C.gold("❯") : " ";
|
|
131
168
|
const okp = !platformOk(r.m);
|
|
132
|
-
const name =
|
|
169
|
+
const name = i === cur ? C.bold(r.m.id.padEnd(11)) : r.m.id.padEnd(11);
|
|
133
170
|
const deps = r.m.needs.map((d) => (depOk(d) ? d : C.red(d))).join(" ");
|
|
134
171
|
const platNote = okp ? C.red(" (unsupported OS)") : "";
|
|
135
172
|
out.push(` ${cursor} ${sel} ${name} ${C.dim(methodTag(r.m).padEnd(7))} ${C.dim(r.m.blurb)}${platNote}`);
|
|
@@ -177,6 +214,11 @@ ${C.bold("seldon")} — install the Seldon stack, pick what you use.
|
|
|
177
214
|
${C.bold("seldon doctor")} [ids…] check external deps (tmux, sops, age, tailscale, python…)
|
|
178
215
|
${C.bold("seldon list")} list the modules
|
|
179
216
|
${C.bold("seldon --dev")} link node modules from this checkout instead of npm
|
|
217
|
+
${C.bold("seldon install --pm=pnpm")} force the node package manager (pnpm|bun|npm; auto-detected)
|
|
218
|
+
|
|
219
|
+
${C.dim("node tools install via pnpm/bun if present (faster), else npm.")}
|
|
220
|
+
${C.dim("python (demerzel) installs into its own isolated venv — never your system Python;")}
|
|
221
|
+
${C.dim("uses uv if present, else python3 -m venv + pip.")}
|
|
180
222
|
|
|
181
223
|
modules: ${MODULES.map((m) => m.id).join(", ")}
|
|
182
224
|
`);
|
package/package.json
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gorlitzer-labs/seldon",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Install the Seldon stack — pick your tools from a checklist; each installs via its native method.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"bin": {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
6
|
+
"bin": {
|
|
7
|
+
"seldon": "bin/seldon.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"modules.mjs",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"ai",
|
|
19
|
+
"agents",
|
|
20
|
+
"installer",
|
|
21
|
+
"cli",
|
|
22
|
+
"seldon",
|
|
23
|
+
"apiary",
|
|
24
|
+
"factory"
|
|
25
|
+
],
|
|
10
26
|
"author": "Franco Berardi",
|
|
11
27
|
"license": "MIT",
|
|
12
|
-
"publishConfig": {
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
}
|
|
13
31
|
}
|