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.
Files changed (3) hide show
  1. package/README.md +27 -51
  2. package/bin/drift.js +26 -53
  3. package/package.json +5 -4
package/README.md CHANGED
@@ -1,84 +1,60 @@
1
- # drift-ml
1
+ # drift
2
2
 
3
- **Drift** by Lakshit Sachdeva — terminal-first, chat-based AutoML. Same engine as the web app. Local-first: the engine runs on your machine; no commands to memorize.
3
+ **Terminal-first, chat-based AutoML.** Open source. No tokens. No auth. Works fully local.
4
4
 
5
5
  ---
6
6
 
7
- ## Exactly what to do
7
+ ## Install
8
8
 
9
- 1. **Install drift**
10
- ```bash
11
- npm install -g drift-ml
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
- ## What is drift?
13
+ Or with npm (also requires pipx for the CLI):
39
14
 
40
- - **Local-first** — The engine runs on your machine. Training and planning stay local; you never send data to our servers.
41
- - **Terminal-first, chat-based** — Same engine as the web app. No commands to memorize; chat in natural language.
42
- - **Engine** On first run the CLI downloads and starts the engine from `~/.drift/bin/`. Or set `DRIFT_BACKEND_URL` to a running engine URL.
15
+ ```bash
16
+ pipx install drift-ml
17
+ npm install -g drift-ml
18
+ ```
43
19
 
44
20
  ---
45
21
 
46
- ## Install (details)
22
+ ## Run
47
23
 
48
24
  ```bash
49
- npm install -g drift-ml
50
25
  drift
51
26
  ```
52
27
 
53
- The `drift` command installs or upgrades the chat CLI (Python) and runs it. You get the welcome and instructions every time.
28
+ That's it. On first run, drift downloads and starts the engine automatically. No backend setup. No config.
54
29
 
55
- ### Alternative: pipx (Python only — macOS, Linux, Windows)
30
+ ---
56
31
 
57
- ```bash
58
- pipx install drift-ml
59
- drift
60
- ```
32
+ ## How it works
61
33
 
62
- **Update (pipx):**
63
- ```bash
64
- pipx upgrade drift-ml
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 usage
41
+ ## Example
71
42
 
72
43
  ```text
73
44
  drift › load iris.csv
74
- drift › predict sepal.length
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
- // REMOVED: Any pip/pipx/python -m pip install or upgrade logic.
4
- // WHY: PEP 668 and user envs; we must not modify Python. User installs CLI via pipx once.
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
- // Pinned tag: draft releases are invisible to /releases/latest.
20
- const ENGINE_TAG = "v0.1.1";
21
- const GITHUB_REPO = "lakshitsachdeva/intent2model";
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; // 30 seconds total
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
- const API_HEADERS = { "User-Agent": "Drift-Engine-Launcher/1.0", Accept: "application/vnd.github+json" };
69
- const DOWNLOAD_HEADERS = {
70
- "User-Agent": "Drift-Engine-Launcher/1.0",
71
- Accept: "application/octet-stream",
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
- // Resolve GitHub release asset to API download URL (browser_download_url returns 404 for scripts).
75
- function getGitHubAssetUrl(assetName) {
70
+ function downloadWithCurl(url, destPath) {
76
71
  return new Promise((resolve, reject) => {
77
- const req = https.get(GITHUB_API_RELEASE, { headers: API_HEADERS }, (res) => {
78
- if (res.statusCode !== 200) {
79
- reject(new Error(`Release not found: ${res.statusCode}`));
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
- req.on("error", reject);
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: DOWNLOAD_HEADERS }, (res) => {
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 isDefaultGitHub = !process.env.DRIFT_ENGINE_BASE_URL;
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.13",
4
- "description": "Drift — terminal-first, chat-based AutoML. Same engine as the web app. On first run: downloads and starts the engine locally (never exposes engine source).",
3
+ "version": "0.2.1",
4
+ "description": "drift — terminal-first, chat-based AutoML. Open source. No tokens. No auth.",
5
5
  "bin": {
6
- "drift": "./bin/drift.js"
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": {