drift-ml 0.1.13 → 0.2.1
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 +27 -51
- package/bin/drift.js +26 -53
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,84 +1,60 @@
|
|
|
1
|
-
# drift
|
|
1
|
+
# drift
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Terminal-first, chat-based AutoML.** Open source. No tokens. No auth. Works fully local.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Install
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
Requires Node.js ≥ 18 and Python 3 on your PATH.
|
|
14
|
-
|
|
15
|
-
2. **Run drift**
|
|
16
|
-
```bash
|
|
17
|
-
drift
|
|
18
|
-
```
|
|
19
|
-
On first run, the CLI detects your OS and architecture, downloads the correct engine binary into `~/.drift/bin/`, and starts the engine in the background. You’ll see a short welcome and instructions in the terminal.
|
|
20
|
-
|
|
21
|
-
3. **Use a local LLM**
|
|
22
|
-
Training and planning use an LLM. You need one of:
|
|
23
|
-
- **Gemini CLI** — install it and set `GEMINI_API_KEY` or have `gemini` on your PATH.
|
|
24
|
-
- **Ollama** — run `ollama run llama2` (or another model).
|
|
25
|
-
- Another local LLM the engine supports.
|
|
26
|
-
|
|
27
|
-
4. **Chat**
|
|
28
|
-
- `load path/to/data.csv`
|
|
29
|
-
- `predict price` (or any column)
|
|
30
|
-
- `try something stronger`
|
|
31
|
-
- `why is accuracy capped`
|
|
32
|
-
- `quit` to exit.
|
|
33
|
-
|
|
34
|
-
That’s it. The engine runs locally. The web app (if you use it) can be hosted on Vercel; the engine stays on your machine.
|
|
35
|
-
|
|
36
|
-
---
|
|
9
|
+
```bash
|
|
10
|
+
pipx install drift-ml
|
|
11
|
+
```
|
|
37
12
|
|
|
38
|
-
|
|
13
|
+
Or with npm (also requires pipx for the CLI):
|
|
39
14
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
15
|
+
```bash
|
|
16
|
+
pipx install drift-ml
|
|
17
|
+
npm install -g drift-ml
|
|
18
|
+
```
|
|
43
19
|
|
|
44
20
|
---
|
|
45
21
|
|
|
46
|
-
##
|
|
22
|
+
## Run
|
|
47
23
|
|
|
48
24
|
```bash
|
|
49
|
-
npm install -g drift-ml
|
|
50
25
|
drift
|
|
51
26
|
```
|
|
52
27
|
|
|
53
|
-
|
|
28
|
+
That's it. On first run, drift downloads and starts the engine automatically. No backend setup. No config.
|
|
54
29
|
|
|
55
|
-
|
|
30
|
+
---
|
|
56
31
|
|
|
57
|
-
|
|
58
|
-
pipx install drift-ml
|
|
59
|
-
drift
|
|
60
|
-
```
|
|
32
|
+
## How it works
|
|
61
33
|
|
|
62
|
-
**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
(PowerShell on Windows: same command.)
|
|
34
|
+
- **Local-first** — Engine runs on your machine. Data never leaves.
|
|
35
|
+
- **Chat-based** — `load data.csv`, `predict price`, `try something stronger`
|
|
36
|
+
- **Auto-start** — Engine downloads and starts in the background. You never touch it.
|
|
37
|
+
- **No tokens** — No API keys for drift. (You need an LLM for training: Ollama, Gemini CLI, etc.)
|
|
67
38
|
|
|
68
39
|
---
|
|
69
40
|
|
|
70
|
-
## Example
|
|
41
|
+
## Example
|
|
71
42
|
|
|
72
43
|
```text
|
|
73
44
|
drift › load iris.csv
|
|
74
|
-
drift › predict
|
|
45
|
+
drift › predict variety
|
|
75
46
|
drift › try something stronger
|
|
76
|
-
drift › why is accuracy capped
|
|
77
47
|
drift › quit
|
|
78
48
|
```
|
|
79
49
|
|
|
80
50
|
---
|
|
81
51
|
|
|
52
|
+
## Philosophy
|
|
53
|
+
|
|
54
|
+
drift should feel like `git`, `docker`, `brew` — a tool you trust immediately. Zero friction. Open source.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
82
58
|
## License
|
|
83
59
|
|
|
84
60
|
MIT
|
package/bin/drift.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// FINAL FLOW: (1) If no DRIFT_BACKEND_URL, ensure engine at 127.0.0.1:8000 (download + start if needed).
|
|
7
|
-
// (2) Locate Python drift ONLY in ~/.local/bin (macOS/Linux) or %USERPROFILE%\.local\bin (Windows).
|
|
8
|
-
// (3) Spawn that binary with DRIFT_BACKEND_URL set; never run drift.cmd/drift.ps1/drift.js (self).
|
|
3
|
+
// drift — terminal-first AutoML. Engine auto-starts locally.
|
|
4
|
+
// No tokens. No auth. No backend setup.
|
|
9
5
|
//
|
|
10
6
|
|
|
11
7
|
const { spawnSync, spawn } = require("child_process");
|
|
@@ -16,15 +12,13 @@ const http = require("http");
|
|
|
16
12
|
|
|
17
13
|
const isWindows = process.platform === "win32";
|
|
18
14
|
const ENGINE_PORT = process.env.DRIFT_ENGINE_PORT || "8000";
|
|
19
|
-
|
|
20
|
-
const ENGINE_TAG = "v0.
|
|
21
|
-
const
|
|
22
|
-
const ENGINE_BASE_URL = process.env.DRIFT_ENGINE_BASE_URL || `https://github.com/${GITHUB_REPO}/releases/download/${ENGINE_TAG}`;
|
|
23
|
-
const GITHUB_API_RELEASE = `https://api.github.com/repos/${GITHUB_REPO}/releases/tags/${ENGINE_TAG}`;
|
|
15
|
+
const GITHUB_REPO = "lakshitsachdeva/drift"; // Engine binaries
|
|
16
|
+
const ENGINE_TAG = "v0.2.0"; // Pinned — direct URL, no API, no rate limits
|
|
17
|
+
const ENGINE_BASE_URL = `https://github.com/${GITHUB_REPO}/releases/download/${ENGINE_TAG}`;
|
|
24
18
|
const HEALTH_URL = `http://127.0.0.1:${ENGINE_PORT}/health`;
|
|
25
19
|
const HEALTH_TIMEOUT_MS = 2000;
|
|
26
20
|
const HEALTH_POLL_MS = 500;
|
|
27
|
-
const HEALTH_POLL_MAX = 60;
|
|
21
|
+
const HEALTH_POLL_MAX = 60;
|
|
28
22
|
const isMac = process.platform === "darwin";
|
|
29
23
|
|
|
30
24
|
function getPlatformKey() {
|
|
@@ -65,44 +59,32 @@ function fetchOk(url) {
|
|
|
65
59
|
});
|
|
66
60
|
}
|
|
67
61
|
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
62
|
+
function getAssetUrl(assetName) {
|
|
63
|
+
const baseUrl = process.env.DRIFT_ENGINE_BASE_URL;
|
|
64
|
+
if (baseUrl) {
|
|
65
|
+
return `${baseUrl.replace(/\/$/, "")}/${assetName}`;
|
|
66
|
+
}
|
|
67
|
+
return `${ENGINE_BASE_URL}/${assetName}`;
|
|
68
|
+
}
|
|
73
69
|
|
|
74
|
-
|
|
75
|
-
function getGitHubAssetUrl(assetName) {
|
|
70
|
+
function downloadWithCurl(url, destPath) {
|
|
76
71
|
return new Promise((resolve, reject) => {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
let body = "";
|
|
83
|
-
res.on("data", (chunk) => { body += chunk; });
|
|
84
|
-
res.on("end", () => {
|
|
85
|
-
try {
|
|
86
|
-
const data = JSON.parse(body);
|
|
87
|
-
const asset = (data.assets || []).find((a) => a.name === assetName);
|
|
88
|
-
if (!asset || !asset.url) {
|
|
89
|
-
reject(new Error(`Asset not found: ${assetName}`));
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
resolve(asset.url);
|
|
93
|
-
} catch (e) {
|
|
94
|
-
reject(e);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
72
|
+
const result = spawnSync("curl", ["-fsSL", "-o", destPath, url], {
|
|
73
|
+
stdio: "pipe",
|
|
74
|
+
timeout: 120000,
|
|
97
75
|
});
|
|
98
|
-
|
|
76
|
+
if (result.status !== 0) {
|
|
77
|
+
reject(new Error("Download failed"));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
resolve();
|
|
99
81
|
});
|
|
100
82
|
}
|
|
101
83
|
|
|
102
84
|
function downloadFile(url, destPath) {
|
|
103
85
|
return new Promise((resolve, reject) => {
|
|
104
86
|
const client = url.startsWith("https") ? https : http;
|
|
105
|
-
const req = client.get(url, { headers:
|
|
87
|
+
const req = client.get(url, { headers: { "User-Agent": "Drift/1.0" } }, (res) => {
|
|
106
88
|
const redirect = res.statusCode >= 301 && res.statusCode <= 302 && res.headers.location;
|
|
107
89
|
if (redirect) {
|
|
108
90
|
downloadFile(redirect, destPath).then(resolve).catch(reject);
|
|
@@ -154,16 +136,12 @@ async function ensureEngine() {
|
|
|
154
136
|
const { plat, arch } = getPlatformKey();
|
|
155
137
|
const ext = isWindows ? ".exe" : "";
|
|
156
138
|
const asset = `drift-engine-${plat}-${arch}${ext}`;
|
|
157
|
-
const
|
|
158
|
-
const url = isDefaultGitHub
|
|
159
|
-
? await getGitHubAssetUrl(asset)
|
|
160
|
-
: `${ENGINE_BASE_URL.replace(/\/$/, "")}/${asset}`;
|
|
139
|
+
const url = getAssetUrl(asset);
|
|
161
140
|
process.stderr.write(`drift: Downloading engine (${asset})...\n`);
|
|
162
141
|
try {
|
|
163
|
-
await downloadFile(url, binPath);
|
|
142
|
+
await downloadWithCurl(url, binPath).catch(() => downloadFile(url, binPath));
|
|
164
143
|
} catch (e) {
|
|
165
144
|
console.error("drift: Download failed.", e.message);
|
|
166
|
-
console.error("drift: Set DRIFT_ENGINE_BASE_URL or run the engine manually.");
|
|
167
145
|
return false;
|
|
168
146
|
}
|
|
169
147
|
if (!isWindows) {
|
|
@@ -175,7 +153,6 @@ async function ensureEngine() {
|
|
|
175
153
|
} catch (_) {}
|
|
176
154
|
}
|
|
177
155
|
}
|
|
178
|
-
// On macOS, always ensure binary is executable and not quarantined before spawn (covers existing binaries).
|
|
179
156
|
if (isMac && binPath) {
|
|
180
157
|
try {
|
|
181
158
|
fs.chmodSync(binPath, 0o755);
|
|
@@ -192,7 +169,6 @@ async function ensureEngine() {
|
|
|
192
169
|
return waitForEngine();
|
|
193
170
|
}
|
|
194
171
|
|
|
195
|
-
// Locate Python drift ONLY in pipx bin dir. Never search PATH (avoids running drift.cmd/drift.ps1/drift.js).
|
|
196
172
|
function findPythonDrift() {
|
|
197
173
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
198
174
|
if (!home) return null;
|
|
@@ -218,7 +194,6 @@ async function main() {
|
|
|
218
194
|
});
|
|
219
195
|
if (!started) {
|
|
220
196
|
console.error("Failed to start drift engine.");
|
|
221
|
-
console.error("Please check permissions or download the engine manually.");
|
|
222
197
|
process.exit(1);
|
|
223
198
|
}
|
|
224
199
|
}
|
|
@@ -227,9 +202,7 @@ async function main() {
|
|
|
227
202
|
const driftPath = findPythonDrift();
|
|
228
203
|
if (!driftPath) {
|
|
229
204
|
console.error(`
|
|
230
|
-
drift is not installed.
|
|
231
|
-
|
|
232
|
-
Install it with:
|
|
205
|
+
drift is not installed. Install it with:
|
|
233
206
|
|
|
234
207
|
pipx install drift-ml
|
|
235
208
|
`);
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drift-ml",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "drift — terminal-first, chat-based AutoML. Open source. No tokens. No auth.",
|
|
5
5
|
"bin": {
|
|
6
|
-
"drift": "
|
|
6
|
+
"drift": "bin/drift.js"
|
|
7
7
|
},
|
|
8
|
+
"files": ["bin", "README.md"],
|
|
8
9
|
"engines": {
|
|
9
10
|
"node": ">=18"
|
|
10
11
|
},
|
|
11
|
-
"keywords": ["drift", "automl", "cli", "ml", "terminal", "local-first"],
|
|
12
|
+
"keywords": ["drift", "automl", "cli", "ml", "terminal", "local-first", "ai", "open-source"],
|
|
12
13
|
"license": "MIT",
|
|
13
14
|
"author": "Lakshit Sachdeva",
|
|
14
15
|
"repository": {
|