drift-ml 0.2.1 → 0.2.5

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 +118 -16
  2. package/package.json +1 -1
package/bin/drift.js CHANGED
@@ -12,13 +12,13 @@ const http = require("http");
12
12
 
13
13
  const isWindows = process.platform === "win32";
14
14
  const ENGINE_PORT = process.env.DRIFT_ENGINE_PORT || "8000";
15
- const GITHUB_REPO = "lakshitsachdeva/drift"; // Engine binaries
16
- const ENGINE_TAG = "v0.2.0"; // Pinned — direct URL, no API, no rate limits
15
+ const GITHUB_REPO = "lakshitsachdeva/intent2model"; // Engine binaries (same repo)
16
+ const ENGINE_TAG = "v0.2.5"; // Pinned — direct URL, no API, no rate limits
17
17
  const ENGINE_BASE_URL = `https://github.com/${GITHUB_REPO}/releases/download/${ENGINE_TAG}`;
18
18
  const HEALTH_URL = `http://127.0.0.1:${ENGINE_PORT}/health`;
19
19
  const HEALTH_TIMEOUT_MS = 2000;
20
20
  const HEALTH_POLL_MS = 500;
21
- const HEALTH_POLL_MAX = 60;
21
+ const HEALTH_POLL_MAX = 120; // 60s — PyInstaller binary can take 30+ s to unpack on first run
22
22
  const isMac = process.platform === "darwin";
23
23
 
24
24
  function getPlatformKey() {
@@ -157,16 +157,101 @@ async function ensureEngine() {
157
157
  try {
158
158
  fs.chmodSync(binPath, 0o755);
159
159
  spawnSync("xattr", ["-dr", "com.apple.quarantine", binPath], { stdio: "pipe" });
160
+ // Ad-hoc sign so macOS Gatekeeper doesn't kill the binary
161
+ spawnSync("codesign", ["-s", "-", "--force", binPath], { stdio: "pipe" });
160
162
  } catch (_) {}
161
163
  }
162
- const child = spawn(binPath, [], {
163
- detached: true,
164
- stdio: "ignore",
165
- cwd: binDir,
166
- env: { ...process.env, DRIFT_ENGINE_PORT: ENGINE_PORT },
167
- });
168
- child.unref();
169
- return waitForEngine();
164
+
165
+ const absPath = path.resolve(binPath);
166
+ const env = { ...process.env, DRIFT_ENGINE_PORT: ENGINE_PORT };
167
+
168
+ // macOS: spawn a wrapper script instead of the binary directly (avoids -88)
169
+ // Windows: use batch file so engine starts reliably (inherits PATH for gemini etc.)
170
+ const binName = path.basename(binPath);
171
+ let toSpawn = absPath;
172
+ let spawnArgs = [];
173
+
174
+ if (isMac) {
175
+ const wrapperPath = path.join(binDir, "run-engine.sh");
176
+ const wrapperScript = `#!/bin/bash
177
+ cd "$(dirname "$0")"
178
+ export DRIFT_ENGINE_PORT="${ENGINE_PORT}"
179
+ exec ./${binName}
180
+ `;
181
+ if (!fs.existsSync(wrapperPath) || fs.readFileSync(wrapperPath, "utf8") !== wrapperScript) {
182
+ fs.writeFileSync(wrapperPath, wrapperScript);
183
+ fs.chmodSync(wrapperPath, 0o755);
184
+ }
185
+ toSpawn = "/bin/bash";
186
+ spawnArgs = [wrapperPath];
187
+ } else if (isWindows) {
188
+ const batPath = path.join(binDir, "run-engine.bat");
189
+ const batScript = `@echo off
190
+ cd /d "%~dp0"
191
+ set DRIFT_ENGINE_PORT=${ENGINE_PORT}
192
+ start /b "" ${binName}
193
+ `;
194
+ if (!fs.existsSync(batPath) || fs.readFileSync(batPath, "utf8") !== batScript) {
195
+ fs.writeFileSync(batPath, batScript);
196
+ }
197
+ toSpawn = "cmd";
198
+ spawnArgs = ["/c", batPath];
199
+ }
200
+
201
+ process.stderr.write("drift: Starting engine (first run may take 30s)...\n");
202
+
203
+ const stderrLog = path.join(binDir, ".engine-stderr.log");
204
+ let stderrFd;
205
+ try {
206
+ stderrFd = fs.openSync(stderrLog, "w");
207
+ } catch (_) {
208
+ stderrFd = "ignore";
209
+ }
210
+ const stdio = stderrFd === "ignore" ? "ignore" : ["ignore", "ignore", stderrFd];
211
+
212
+ function trySpawn(cmd, args) {
213
+ return new Promise((resolve, reject) => {
214
+ let child;
215
+ try {
216
+ child = spawn(cmd, args || [], {
217
+ detached: true,
218
+ stdio,
219
+ cwd: binDir,
220
+ env,
221
+ });
222
+ } catch (e) {
223
+ reject(e);
224
+ return;
225
+ }
226
+ child.on("error", (err) => reject(err));
227
+ child.unref();
228
+ waitForEngine().then(resolve);
229
+ });
230
+ }
231
+
232
+ try {
233
+ return await trySpawn(toSpawn, spawnArgs);
234
+ } catch (e) {
235
+ const isSpawn88 = (e.errno === -88 || (e.message && String(e.message).includes("-88")));
236
+ if (isMac && isSpawn88) {
237
+ process.stderr.write("drift: Spawn failed (-88). Trying nohup fallback...\n");
238
+ try {
239
+ const cmd = (isMac && wrapperPath) ? `"${wrapperPath}"` : `"${absPath}"`;
240
+ spawnSync("/bin/sh", ["-c", `nohup ${cmd} > /dev/null 2>&1 &`], {
241
+ cwd: binDir,
242
+ env: { ...process.env, DRIFT_ENGINE_PORT: ENGINE_PORT },
243
+ stdio: "pipe",
244
+ });
245
+ return await waitForEngine();
246
+ } catch (e2) {
247
+ console.error("drift: Engine failed. Run manually in another terminal:");
248
+ console.error(" ~/.drift/bin/drift-engine-macos-arm64");
249
+ console.error("Then run drift again.");
250
+ throw e2;
251
+ }
252
+ }
253
+ throw e;
254
+ }
170
255
  }
171
256
 
172
257
  function findPythonDrift() {
@@ -194,6 +279,21 @@ async function main() {
194
279
  });
195
280
  if (!started) {
196
281
  console.error("Failed to start drift engine.");
282
+ const binDir = getEngineDir();
283
+ if (binDir) {
284
+ const stderrLog = path.join(binDir, ".engine-stderr.log");
285
+ if (fs.existsSync(stderrLog)) {
286
+ const err = fs.readFileSync(stderrLog, "utf8").trim();
287
+ if (err) console.error("drift: Engine log:", err.slice(-500));
288
+ }
289
+ const enginePath = getEnginePath();
290
+ if (isWindows && enginePath) {
291
+ console.error("drift: On Windows (PowerShell), run manually to see the error:");
292
+ console.error(" cd $env:USERPROFILE\\.drift\\bin");
293
+ console.error(" .\\drift-engine-windows-x64.exe");
294
+ console.error("drift: Also install pipx: pip install pipx && pipx ensurepath, then pipx install drift-ml");
295
+ }
296
+ }
197
297
  process.exit(1);
198
298
  }
199
299
  }
@@ -201,11 +301,13 @@ async function main() {
201
301
 
202
302
  const driftPath = findPythonDrift();
203
303
  if (!driftPath) {
204
- console.error(`
205
- drift is not installed. Install it with:
206
-
207
- pipx install drift-ml
208
- `);
304
+ console.error("drift: Python CLI not found. Install with:");
305
+ if (isWindows) {
306
+ console.error(" pip install pipx");
307
+ console.error(" pipx ensurepath");
308
+ console.error(" (restart PowerShell)");
309
+ }
310
+ console.error(" pipx install drift-ml");
209
311
  process.exit(1);
210
312
  }
211
313
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drift-ml",
3
- "version": "0.2.1",
3
+ "version": "0.2.5",
4
4
  "description": "drift — terminal-first, chat-based AutoML. Open source. No tokens. No auth.",
5
5
  "bin": {
6
6
  "drift": "bin/drift.js"