drift-ml 0.1.0 → 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.
Files changed (2) hide show
  1. package/bin/drift.js +23 -158
  2. package/package.json +7 -2
package/bin/drift.js CHANGED
@@ -1,175 +1,40 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { spawnSync, spawn } = require("child_process");
4
- const fs = require("fs");
5
- const path = require("path");
6
- const https = require("https");
7
- const http = require("http");
8
-
9
- const ENGINE_PORT = process.env.DRIFT_ENGINE_PORT || "8000";
10
- const ENGINE_BASE = process.env.DRIFT_ENGINE_BASE_URL || "https://github.com/lakshitsachdeva/drift/releases/latest/download";
11
- const HEALTH_URL = `http://127.0.0.1:${ENGINE_PORT}/health`;
12
- const HEALTH_TIMEOUT_MS = 2000;
13
- const HEALTH_POLL_MS = 500;
14
- const HEALTH_POLL_MAX = 60; // 30s
3
+ const { spawnSync } = require("child_process");
15
4
 
16
5
  function which(cmd) {
17
- const { status, stdout } = spawnSync("which", [cmd], { encoding: "utf8" });
18
- return status === 0 ? (stdout || "").trim() : null;
6
+ const isWindows = process.platform === "win32";
7
+ const whichCmd = isWindows ? "where" : "which";
8
+ const { status, stdout } = spawnSync(whichCmd, [cmd], { encoding: "utf8" });
9
+ return status === 0 ? (stdout || "").trim().split("\n")[0] : null;
19
10
  }
20
11
 
21
- function getPlatformKey() {
22
- const p = process.platform;
23
- const a = process.arch;
24
- const plat = p === "darwin" ? "macos" : p === "win32" ? "windows" : "linux";
25
- const arch = a === "arm64" || a === "aarch64" ? "arm64" : "x64";
26
- return { plat, arch };
27
- }
12
+ function main() {
13
+ // Check if drift binary exists on PATH
14
+ const driftPath = which("drift");
15
+
16
+ if (!driftPath) {
17
+ console.error(`
18
+ drift is not installed.
28
19
 
29
- function getEngineDir() {
30
- const home = process.env.HOME || process.env.USERPROFILE || process.env.HOMEPATH;
31
- if (!home) return null;
32
- return path.join(home, ".drift", "bin");
33
- }
20
+ Install it with:
34
21
 
35
- function getEnginePath() {
36
- const dir = getEngineDir();
37
- if (!dir) return null;
38
- const { plat, arch } = getPlatformKey();
39
- const ext = process.platform === "win32" ? ".exe" : "";
40
- return path.join(dir, `drift-engine-${plat}-${arch}${ext}`);
41
- }
22
+ pipx install drift-ml
42
23
 
43
- function fetchOk(url) {
44
- return new Promise((resolve, reject) => {
45
- const client = url.startsWith("https") ? https : http;
46
- const req = client.get(url, { timeout: HEALTH_TIMEOUT_MS }, (res) => {
47
- const redirect = res.statusCode >= 301 && res.statusCode <= 302 && res.headers.location;
48
- if (redirect) {
49
- fetchOk(redirect).then(resolve).catch(reject);
50
- return;
51
- }
52
- resolve(res.statusCode === 200);
53
- });
54
- req.on("error", () => resolve(false));
55
- req.on("timeout", () => { req.destroy(); resolve(false); });
56
- });
57
- }
24
+ Then run:
58
25
 
59
- function downloadFile(url, destPath) {
60
- return new Promise((resolve, reject) => {
61
- const client = url.startsWith("https") ? https : http;
62
- const req = client.get(url, (res) => {
63
- const redirect = res.statusCode >= 301 && res.statusCode <= 302 && res.headers.location;
64
- if (redirect) {
65
- downloadFile(redirect, destPath).then(resolve).catch(reject);
66
- return;
67
- }
68
- if (res.statusCode !== 200) {
69
- reject(new Error(`Download failed: ${res.statusCode}`));
70
- return;
71
- }
72
- const dir = path.dirname(destPath);
73
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
74
- const file = fs.createWriteStream(destPath);
75
- res.pipe(file);
76
- file.on("finish", () => { file.close(); resolve(); });
77
- file.on("error", reject);
78
- });
79
- req.on("error", reject);
80
- });
81
- }
82
-
83
- function engineRunning() {
84
- return fetchOk(HEALTH_URL);
85
- }
86
-
87
- function waitForEngine() {
88
- return new Promise((resolve) => {
89
- let n = 0;
90
- const t = setInterval(() => {
91
- n++;
92
- fetchOk(HEALTH_URL).then((ok) => {
93
- if (ok) { clearInterval(t); resolve(true); }
94
- else if (n >= HEALTH_POLL_MAX) { clearInterval(t); resolve(false); }
95
- });
96
- }, HEALTH_POLL_MS);
97
- });
98
- }
99
-
100
- async function ensureEngine() {
101
- const binPath = getEnginePath();
102
- const binDir = getEngineDir();
103
- if (!binPath || !binDir) {
104
- console.error("drift: Could not resolve engine directory (~/.drift/bin). Set HOME or USERPROFILE.");
105
- return false;
106
- }
107
- if (!fs.existsSync(binPath)) {
108
- const { plat, arch } = getPlatformKey();
109
- const ext = process.platform === "win32" ? ".exe" : "";
110
- const asset = `drift-engine-${plat}-${arch}${ext}`;
111
- const url = `${ENGINE_BASE}/${asset}`;
112
- process.stderr.write(`drift: Downloading engine (${asset})...\n`);
113
- try {
114
- await downloadFile(url, binPath);
115
- } catch (e) {
116
- console.error("drift: Download failed.", e.message);
117
- console.error("drift: Run the engine manually or set DRIFT_ENGINE_BASE_URL.");
118
- return false;
119
- }
120
- if (process.platform !== "win32") {
121
- try { fs.chmodSync(binPath, 0o755); } catch (_) {}
122
- }
123
- }
124
- const child = spawn(binPath, [], {
125
- detached: true,
126
- stdio: "ignore",
127
- cwd: binDir,
128
- env: { ...process.env, DRIFT_ENGINE_PORT: ENGINE_PORT },
129
- });
130
- child.unref();
131
- return waitForEngine();
132
- }
133
-
134
- async function main() {
135
- const userBackend = process.env.DRIFT_BACKEND_URL;
136
- if (userBackend) {
137
- // User runs engine elsewhere; skip download/start and connect to their URL.
138
- } else if (await engineRunning()) {
139
- // Engine already running locally.
140
- } else {
141
- const engineStarted = await ensureEngine().catch(() => false);
142
- if (!engineStarted) {
143
- console.error("drift: Engine did not start. Run the engine manually or set DRIFT_BACKEND_URL to a running engine URL.");
144
- process.exit(1);
145
- }
146
- }
147
-
148
- const python = which("python3") || which("python");
149
- if (!python) {
150
- console.error("drift: Python is required for the chat CLI. Install Python 3 and ensure `python` or `python3` is on your PATH.");
26
+ drift
27
+ `);
151
28
  process.exit(1);
152
29
  }
153
30
 
154
- const pip = spawnSync(python, ["-m", "pip", "install", "--quiet", "--upgrade", "drift"], {
155
- encoding: "utf8",
156
- stdio: ["inherit", "pipe", "inherit"],
157
- });
158
- if (pip.status !== 0) {
159
- console.error("drift: Failed to install or upgrade the drift Python package.");
160
- process.exit(pip.status === null ? 1 : pip.status);
161
- }
162
-
163
- const backendUrl = userBackend || `http://127.0.0.1:${ENGINE_PORT}`;
164
- const run = spawnSync(python, ["-m", "drift"], {
165
- encoding: "utf8",
31
+ // Run drift and forward stdin/stdout
32
+ const result = spawnSync(driftPath, process.argv.slice(2), {
166
33
  stdio: "inherit",
167
- env: { ...process.env, DRIFT_BACKEND_URL: backendUrl },
34
+ env: process.env,
168
35
  });
169
- process.exit(run.status === null ? (run.signal ? 128 + 9 : 1) : run.status);
36
+
37
+ process.exit(result.status === null ? (result.signal ? 128 + 9 : 1) : result.status);
170
38
  }
171
39
 
172
- main().catch((e) => {
173
- console.error("drift:", e.message);
174
- process.exit(1);
175
- });
40
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drift-ml",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
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).",
5
5
  "bin": {
6
6
  "drift": "./bin/drift.js"
@@ -9,5 +9,10 @@
9
9
  "node": ">=18"
10
10
  },
11
11
  "keywords": ["drift", "automl", "cli", "ml", "terminal", "local-first"],
12
- "license": "MIT"
12
+ "license": "MIT",
13
+ "author": "Lakshit Sachdeva",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/lakshitsachdeva/intent2model.git"
17
+ }
13
18
  }