@deeplake/hivemind 0.7.31 → 0.7.32

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.
@@ -54,19 +54,19 @@ var init_index_marker_store = __esm({
54
54
 
55
55
  // dist/src/hooks/codex/pre-tool-use.js
56
56
  import { execFileSync } from "node:child_process";
57
- import { existsSync as existsSync4 } from "node:fs";
58
- import { join as join9, dirname as dirname2 } from "node:path";
57
+ import { existsSync as existsSync5 } from "node:fs";
58
+ import { join as join11, dirname as dirname3 } from "node:path";
59
59
  import { fileURLToPath as fileURLToPath3 } from "node:url";
60
60
 
61
61
  // dist/src/utils/stdin.js
62
62
  function readStdin() {
63
- return new Promise((resolve2, reject) => {
63
+ return new Promise((resolve3, reject) => {
64
64
  let data = "";
65
65
  process.stdin.setEncoding("utf-8");
66
66
  process.stdin.on("data", (chunk) => data += chunk);
67
67
  process.stdin.on("end", () => {
68
68
  try {
69
- resolve2(JSON.parse(data));
69
+ resolve3(JSON.parse(data));
70
70
  } catch (err) {
71
71
  reject(new Error(`Failed to parse hook input: ${err}`));
72
72
  }
@@ -182,7 +182,7 @@ function getQueryTimeoutMs() {
182
182
  return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
183
183
  }
184
184
  function sleep(ms) {
185
- return new Promise((resolve2) => setTimeout(resolve2, ms));
185
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
186
186
  }
187
187
  function isTimeoutError(error) {
188
188
  const name = error instanceof Error ? error.name.toLowerCase() : "";
@@ -212,7 +212,7 @@ var Semaphore = class {
212
212
  this.active++;
213
213
  return;
214
214
  }
215
- await new Promise((resolve2) => this.waiting.push(resolve2));
215
+ await new Promise((resolve3) => this.waiting.push(resolve3));
216
216
  }
217
217
  release() {
218
218
  this.active--;
@@ -1049,9 +1049,9 @@ function capOutputForClaude(output, options = {}) {
1049
1049
  // dist/src/embeddings/client.js
1050
1050
  import { connect } from "node:net";
1051
1051
  import { spawn } from "node:child_process";
1052
- import { openSync, closeSync, writeSync, unlinkSync, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
1053
- import { homedir as homedir3 } from "node:os";
1054
- import { join as join4 } from "node:path";
1052
+ import { openSync as openSync2, closeSync as closeSync2, writeSync, unlinkSync as unlinkSync2, existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
1053
+ import { homedir as homedir6 } from "node:os";
1054
+ import { join as join7 } from "node:path";
1055
1055
 
1056
1056
  // dist/src/embeddings/protocol.js
1057
1057
  var DEFAULT_SOCKET_DIR = "/tmp";
@@ -1064,13 +1064,234 @@ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
1064
1064
  return `${dir}/hivemind-embed-${uid}.pid`;
1065
1065
  }
1066
1066
 
1067
+ // dist/src/notifications/queue.js
1068
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync, mkdirSync as mkdirSync2, openSync, closeSync, unlinkSync, statSync } from "node:fs";
1069
+ import { join as join4, resolve } from "node:path";
1070
+ import { homedir as homedir3 } from "node:os";
1071
+ import { setTimeout as sleep2 } from "node:timers/promises";
1072
+ var log3 = (msg) => log("notifications-queue", msg);
1073
+ var LOCK_RETRY_MAX = 50;
1074
+ var LOCK_RETRY_BASE_MS = 5;
1075
+ var LOCK_STALE_MS = 5e3;
1076
+ function queuePath() {
1077
+ return join4(homedir3(), ".deeplake", "notifications-queue.json");
1078
+ }
1079
+ function lockPath() {
1080
+ return `${queuePath()}.lock`;
1081
+ }
1082
+ function readQueue() {
1083
+ try {
1084
+ const raw = readFileSync3(queuePath(), "utf-8");
1085
+ const parsed = JSON.parse(raw);
1086
+ if (!parsed || !Array.isArray(parsed.queue)) {
1087
+ log3(`queue malformed \u2192 treating as empty`);
1088
+ return { queue: [] };
1089
+ }
1090
+ return { queue: parsed.queue };
1091
+ } catch {
1092
+ return { queue: [] };
1093
+ }
1094
+ }
1095
+ function _isQueuePathInsideHome(path, home) {
1096
+ const r = resolve(path);
1097
+ const h = resolve(home);
1098
+ return r.startsWith(h + "/") || r === h;
1099
+ }
1100
+ function writeQueue(q) {
1101
+ const path = queuePath();
1102
+ const home = resolve(homedir3());
1103
+ if (!_isQueuePathInsideHome(path, home)) {
1104
+ throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
1105
+ }
1106
+ mkdirSync2(join4(home, ".deeplake"), { recursive: true, mode: 448 });
1107
+ const tmp = `${path}.${process.pid}.tmp`;
1108
+ writeFileSync2(tmp, JSON.stringify(q, null, 2), { mode: 384 });
1109
+ renameSync(tmp, path);
1110
+ }
1111
+ async function withQueueLock(fn) {
1112
+ const path = lockPath();
1113
+ mkdirSync2(join4(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
1114
+ let fd = null;
1115
+ for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
1116
+ try {
1117
+ fd = openSync(path, "wx", 384);
1118
+ break;
1119
+ } catch (e) {
1120
+ const code = e.code;
1121
+ if (code !== "EEXIST")
1122
+ throw e;
1123
+ try {
1124
+ const age = Date.now() - statSync(path).mtimeMs;
1125
+ if (age > LOCK_STALE_MS) {
1126
+ unlinkSync(path);
1127
+ continue;
1128
+ }
1129
+ } catch {
1130
+ }
1131
+ const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
1132
+ await sleep2(delay);
1133
+ }
1134
+ }
1135
+ if (fd === null) {
1136
+ log3(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
1137
+ return fn();
1138
+ }
1139
+ try {
1140
+ return fn();
1141
+ } finally {
1142
+ try {
1143
+ closeSync(fd);
1144
+ } catch {
1145
+ }
1146
+ try {
1147
+ unlinkSync(path);
1148
+ } catch {
1149
+ }
1150
+ }
1151
+ }
1152
+ function sameDedupKey(a, b) {
1153
+ if (a.id !== b.id)
1154
+ return false;
1155
+ return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
1156
+ }
1157
+ async function enqueueNotification(n) {
1158
+ await withQueueLock(() => {
1159
+ const q = readQueue();
1160
+ if (q.queue.some((existing) => sameDedupKey(existing, n))) {
1161
+ return;
1162
+ }
1163
+ q.queue.push(n);
1164
+ writeQueue(q);
1165
+ });
1166
+ }
1167
+
1168
+ // dist/src/embeddings/disable.js
1169
+ import { createRequire } from "node:module";
1170
+ import { homedir as homedir5 } from "node:os";
1171
+ import { join as join6 } from "node:path";
1172
+ import { pathToFileURL } from "node:url";
1173
+
1174
+ // dist/src/user-config.js
1175
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
1176
+ import { homedir as homedir4 } from "node:os";
1177
+ import { dirname, join as join5 } from "node:path";
1178
+ var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join5(homedir4(), ".deeplake", "config.json");
1179
+ var _cache = null;
1180
+ var _migrated = false;
1181
+ function readUserConfig() {
1182
+ if (_cache !== null)
1183
+ return _cache;
1184
+ const path = _configPath();
1185
+ if (!existsSync3(path)) {
1186
+ _cache = {};
1187
+ return _cache;
1188
+ }
1189
+ try {
1190
+ const raw = readFileSync4(path, "utf-8");
1191
+ const parsed = JSON.parse(raw);
1192
+ _cache = isPlainObject(parsed) ? parsed : {};
1193
+ } catch {
1194
+ _cache = {};
1195
+ }
1196
+ return _cache;
1197
+ }
1198
+ function writeUserConfig(patch) {
1199
+ const current = readUserConfig();
1200
+ const merged = deepMerge(current, patch);
1201
+ const path = _configPath();
1202
+ const dir = dirname(path);
1203
+ if (!existsSync3(dir))
1204
+ mkdirSync3(dir, { recursive: true });
1205
+ const tmp = `${path}.tmp.${process.pid}`;
1206
+ writeFileSync3(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
1207
+ renameSync2(tmp, path);
1208
+ _cache = merged;
1209
+ return merged;
1210
+ }
1211
+ function getEmbeddingsEnabled() {
1212
+ const cfg = readUserConfig();
1213
+ if (cfg.embeddings && typeof cfg.embeddings.enabled === "boolean") {
1214
+ return cfg.embeddings.enabled;
1215
+ }
1216
+ if (_migrated) {
1217
+ return migrationValueFromEnv();
1218
+ }
1219
+ _migrated = true;
1220
+ const enabled = migrationValueFromEnv();
1221
+ try {
1222
+ writeUserConfig({ embeddings: { enabled } });
1223
+ } catch {
1224
+ _cache = { ...cfg ?? {}, embeddings: { ...cfg?.embeddings ?? {}, enabled } };
1225
+ }
1226
+ return enabled;
1227
+ }
1228
+ function migrationValueFromEnv() {
1229
+ const raw = process.env.HIVEMIND_EMBEDDINGS;
1230
+ if (raw === void 0)
1231
+ return false;
1232
+ if (raw === "false")
1233
+ return false;
1234
+ return true;
1235
+ }
1236
+ function isPlainObject(value) {
1237
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1238
+ }
1239
+ function deepMerge(base, patch) {
1240
+ const out = { ...base };
1241
+ for (const key of Object.keys(patch)) {
1242
+ const patchVal = patch[key];
1243
+ const baseVal = base[key];
1244
+ if (isPlainObject(patchVal) && isPlainObject(baseVal)) {
1245
+ out[key] = { ...baseVal, ...patchVal };
1246
+ } else if (patchVal !== void 0) {
1247
+ out[key] = patchVal;
1248
+ }
1249
+ }
1250
+ return out;
1251
+ }
1252
+
1253
+ // dist/src/embeddings/disable.js
1254
+ var cachedStatus = null;
1255
+ function defaultResolveTransformers() {
1256
+ const sharedDir = join6(homedir5(), ".hivemind", "embed-deps");
1257
+ try {
1258
+ createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1259
+ return;
1260
+ } catch {
1261
+ }
1262
+ createRequire(import.meta.url).resolve("@huggingface/transformers");
1263
+ }
1264
+ var _resolve = defaultResolveTransformers;
1265
+ var _readEnabled = getEmbeddingsEnabled;
1266
+ function detectStatus() {
1267
+ if (!_readEnabled())
1268
+ return "user-disabled";
1269
+ try {
1270
+ _resolve();
1271
+ return "enabled";
1272
+ } catch {
1273
+ return "no-transformers";
1274
+ }
1275
+ }
1276
+ function embeddingsStatus() {
1277
+ if (cachedStatus !== null)
1278
+ return cachedStatus;
1279
+ cachedStatus = detectStatus();
1280
+ return cachedStatus;
1281
+ }
1282
+ function embeddingsDisabled() {
1283
+ return embeddingsStatus() !== "enabled";
1284
+ }
1285
+
1067
1286
  // dist/src/embeddings/client.js
1068
- var SHARED_DAEMON_PATH = join4(homedir3(), ".hivemind", "embed-deps", "embed-daemon.js");
1069
- var log3 = (m) => log("embed-client", m);
1287
+ var SHARED_DAEMON_PATH = join7(homedir6(), ".hivemind", "embed-deps", "embed-daemon.js");
1288
+ var log4 = (m) => log("embed-client", m);
1070
1289
  function getUid() {
1071
1290
  const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
1072
1291
  return uid !== void 0 ? String(uid) : process.env.USER ?? "default";
1073
1292
  }
1293
+ var _signalledMissingDeps = false;
1294
+ var _recycledStuckDaemon = false;
1074
1295
  var EmbedClient = class {
1075
1296
  socketPath;
1076
1297
  pidPath;
@@ -1079,13 +1300,14 @@ var EmbedClient = class {
1079
1300
  autoSpawn;
1080
1301
  spawnWaitMs;
1081
1302
  nextId = 0;
1303
+ helloVerified = false;
1082
1304
  constructor(opts = {}) {
1083
1305
  const uid = getUid();
1084
1306
  const dir = opts.socketDir ?? "/tmp";
1085
1307
  this.socketPath = socketPathFor(uid, dir);
1086
1308
  this.pidPath = pidPathFor(uid, dir);
1087
1309
  this.timeoutMs = opts.timeoutMs ?? DEFAULT_CLIENT_TIMEOUT_MS;
1088
- this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync3(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
1310
+ this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync4(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
1089
1311
  this.autoSpawn = opts.autoSpawn ?? true;
1090
1312
  this.spawnWaitMs = opts.spawnWaitMs ?? 5e3;
1091
1313
  }
@@ -1095,8 +1317,33 @@ var EmbedClient = class {
1095
1317
  *
1096
1318
  * Fire-and-forget spawn on miss: if the daemon isn't up, this call returns
1097
1319
  * null AND kicks off a background spawn. The next call finds a ready daemon.
1320
+ *
1321
+ * Stuck-daemon recycle: if the daemon returns a transformers-missing
1322
+ * error (typical after a marketplace upgrade left an older daemon process
1323
+ * alive but with no node_modules accessible from its bundle path), we
1324
+ * SIGTERM it and clear its sock/pid so the very next call spawns a fresh
1325
+ * daemon from the current bundle. Without this, the stuck daemon would
1326
+ * keep poisoning every session until its 10-minute idle-out fires.
1098
1327
  */
1099
1328
  async embed(text, kind = "document") {
1329
+ const v = await this.embedAttempt(text, kind);
1330
+ if (v !== "recycled")
1331
+ return v;
1332
+ if (!this.autoSpawn)
1333
+ return null;
1334
+ this.trySpawnDaemon();
1335
+ await this.waitForDaemonReady();
1336
+ const retry = await this.embedAttempt(text, kind);
1337
+ return retry === "recycled" ? null : retry;
1338
+ }
1339
+ /**
1340
+ * One round-trip: connect → verify → embed. Returns:
1341
+ * - number[] : embedding vector (happy path)
1342
+ * - null : timeout / daemon error / transformers-missing
1343
+ * - "recycled": verifyDaemonOnce killed the daemon mid-call;
1344
+ * caller should respawn and retry once.
1345
+ */
1346
+ async embedAttempt(text, kind) {
1100
1347
  let sock;
1101
1348
  try {
1102
1349
  sock = await this.connectOnce();
@@ -1106,17 +1353,25 @@ var EmbedClient = class {
1106
1353
  return null;
1107
1354
  }
1108
1355
  try {
1356
+ const recycled = await this.verifyDaemonOnce(sock);
1357
+ if (recycled) {
1358
+ return "recycled";
1359
+ }
1109
1360
  const id = String(++this.nextId);
1110
1361
  const req = { op: "embed", id, kind, text };
1111
1362
  const resp = await this.sendAndWait(sock, req);
1112
1363
  if (resp.error || !("embedding" in resp) || !resp.embedding) {
1113
- log3(`embed err: ${resp.error ?? "no embedding"}`);
1364
+ const err = resp.error ?? "no embedding";
1365
+ log4(`embed err: ${err}`);
1366
+ if (isTransformersMissingError(err)) {
1367
+ this.handleTransformersMissing(err);
1368
+ }
1114
1369
  return null;
1115
1370
  }
1116
1371
  return resp.embedding;
1117
1372
  } catch (e) {
1118
1373
  const err = e instanceof Error ? e.message : String(e);
1119
- log3(`embed failed: ${err}`);
1374
+ log4(`embed failed: ${err}`);
1120
1375
  return null;
1121
1376
  } finally {
1122
1377
  try {
@@ -1125,6 +1380,139 @@ var EmbedClient = class {
1125
1380
  }
1126
1381
  }
1127
1382
  }
1383
+ /**
1384
+ * Poll for the sock file to come back after `trySpawnDaemon` — used by
1385
+ * the recycle retry path. Best-effort: caps at `spawnWaitMs` and
1386
+ * returns regardless so the retry attempt can run.
1387
+ */
1388
+ async waitForDaemonReady() {
1389
+ const deadline = Date.now() + this.spawnWaitMs;
1390
+ while (Date.now() < deadline) {
1391
+ if (existsSync4(this.socketPath))
1392
+ return;
1393
+ await new Promise((r) => setTimeout(r, 50));
1394
+ }
1395
+ }
1396
+ /**
1397
+ * Send a `hello` on first successful connect per EmbedClient instance.
1398
+ * If the daemon answers with a path that doesn't match our configured
1399
+ * daemonEntry — typical after a marketplace upgrade replaced the bundle
1400
+ * — SIGTERM the daemon + clear sock/pid so the next call spawns from the
1401
+ * current bundle.
1402
+ *
1403
+ * `helloVerified` is set ONLY after we've seen a compatible response,
1404
+ * so a transient probe failure or a recycle-triggering mismatch leaves
1405
+ * the flag false; the next reconnect re-runs verification against
1406
+ * whatever daemon is then live (typically the fresh spawn).
1407
+ */
1408
+ async verifyDaemonOnce(sock) {
1409
+ if (this.helloVerified)
1410
+ return false;
1411
+ if (!this.daemonEntry) {
1412
+ this.helloVerified = true;
1413
+ return false;
1414
+ }
1415
+ const id = String(++this.nextId);
1416
+ const req = { op: "hello", id };
1417
+ let resp;
1418
+ try {
1419
+ resp = await this.sendAndWait(sock, req);
1420
+ } catch (e) {
1421
+ log4(`hello probe failed (inconclusive, will retry next connect): ${e instanceof Error ? e.message : String(e)}`);
1422
+ return false;
1423
+ }
1424
+ const hello = resp;
1425
+ if (_recycledStuckDaemon) {
1426
+ return false;
1427
+ }
1428
+ if (!hello.daemonPath) {
1429
+ _recycledStuckDaemon = true;
1430
+ log4(`daemon does not implement hello (older protocol); recycling`);
1431
+ this.recycleDaemon(hello.pid);
1432
+ return true;
1433
+ }
1434
+ if (hello.daemonPath !== this.daemonEntry && !existsSync4(hello.daemonPath)) {
1435
+ _recycledStuckDaemon = true;
1436
+ log4(`daemon path no longer on disk \u2014 running=${hello.daemonPath} (gone) expected=${this.daemonEntry}; recycling`);
1437
+ this.recycleDaemon(hello.pid);
1438
+ return true;
1439
+ }
1440
+ this.helloVerified = true;
1441
+ return false;
1442
+ }
1443
+ /**
1444
+ * On a transformers-missing error from the daemon, SIGTERM the stuck
1445
+ * daemon (the bundle daemon that can't find its deps) and clear
1446
+ * sock/pid so the next call spawns fresh. Also enqueue a one-time
1447
+ * notification telling the user to run `hivemind embeddings install`
1448
+ * — but only when the user has opted in. Suppressed when
1449
+ * embeddingsStatus() === "user-disabled" so we don't nag users who
1450
+ * explicitly chose to turn embeddings off.
1451
+ */
1452
+ handleTransformersMissing(detail) {
1453
+ if (!_recycledStuckDaemon) {
1454
+ _recycledStuckDaemon = true;
1455
+ this.recycleDaemon(null);
1456
+ }
1457
+ if (_signalledMissingDeps)
1458
+ return;
1459
+ _signalledMissingDeps = true;
1460
+ let status;
1461
+ try {
1462
+ status = embeddingsStatus();
1463
+ } catch {
1464
+ status = "enabled";
1465
+ }
1466
+ if (status === "user-disabled")
1467
+ return;
1468
+ enqueueNotification({
1469
+ id: "embed-deps-missing",
1470
+ severity: "warn",
1471
+ title: "Hivemind embeddings disabled \u2014 deps missing",
1472
+ body: `Semantic memory search is off because @huggingface/transformers is not installed where the daemon can find it. Run \`hivemind embeddings install\` to enable.`,
1473
+ dedupKey: { reason: "transformers-missing", detail: detail.slice(0, 200) }
1474
+ }).catch((e) => {
1475
+ log4(`enqueue embed-deps-missing failed: ${e instanceof Error ? e.message : String(e)}`);
1476
+ });
1477
+ }
1478
+ /**
1479
+ * Best-effort SIGTERM + sock/pid cleanup. Tolerant of every missing-file
1480
+ * combination and dead-PID cases.
1481
+ *
1482
+ * Identity check: gate the SIGTERM on the daemon's socket file still
1483
+ * existing. We know the daemon was alive moments ago (we either just
1484
+ * got a hello response or the caller saw a transformers-missing error
1485
+ * the daemon emitted), but if the socket file is gone by the time we
1486
+ * try to kill, the daemon process is also gone and the PID we
1487
+ * captured may already have been recycled by the OS to an unrelated
1488
+ * user process. Mirrors the gate added to `killEmbedDaemon` in the
1489
+ * CLI — same failure mode, rarer trigger.
1490
+ */
1491
+ recycleDaemon(reportedPid) {
1492
+ let pid = reportedPid;
1493
+ if (pid === null) {
1494
+ try {
1495
+ pid = Number.parseInt(readFileSync5(this.pidPath, "utf-8").trim(), 10);
1496
+ } catch {
1497
+ }
1498
+ }
1499
+ if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync4(this.socketPath)) {
1500
+ try {
1501
+ process.kill(pid, "SIGTERM");
1502
+ } catch {
1503
+ }
1504
+ } else if (pid !== null) {
1505
+ log4(`recycle: socket gone, skipping SIGTERM on possibly-stale pid ${pid}`);
1506
+ }
1507
+ try {
1508
+ unlinkSync2(this.socketPath);
1509
+ } catch {
1510
+ }
1511
+ try {
1512
+ unlinkSync2(this.pidPath);
1513
+ } catch {
1514
+ }
1515
+ }
1128
1516
  /**
1129
1517
  * Wait up to spawnWaitMs for the daemon to accept connections, spawning if
1130
1518
  * necessary. Meant for SessionStart / long-running batches — not the hot path.
@@ -1148,7 +1536,7 @@ var EmbedClient = class {
1148
1536
  }
1149
1537
  }
1150
1538
  connectOnce() {
1151
- return new Promise((resolve2, reject) => {
1539
+ return new Promise((resolve3, reject) => {
1152
1540
  const sock = connect(this.socketPath);
1153
1541
  const to = setTimeout(() => {
1154
1542
  sock.destroy();
@@ -1156,7 +1544,7 @@ var EmbedClient = class {
1156
1544
  }, this.timeoutMs);
1157
1545
  sock.once("connect", () => {
1158
1546
  clearTimeout(to);
1159
- resolve2(sock);
1547
+ resolve3(sock);
1160
1548
  });
1161
1549
  sock.once("error", (e) => {
1162
1550
  clearTimeout(to);
@@ -1167,16 +1555,16 @@ var EmbedClient = class {
1167
1555
  trySpawnDaemon() {
1168
1556
  let fd;
1169
1557
  try {
1170
- fd = openSync(this.pidPath, "wx", 384);
1558
+ fd = openSync2(this.pidPath, "wx", 384);
1171
1559
  writeSync(fd, String(process.pid));
1172
1560
  } catch (e) {
1173
1561
  if (this.isPidFileStale()) {
1174
1562
  try {
1175
- unlinkSync(this.pidPath);
1563
+ unlinkSync2(this.pidPath);
1176
1564
  } catch {
1177
1565
  }
1178
1566
  try {
1179
- fd = openSync(this.pidPath, "wx", 384);
1567
+ fd = openSync2(this.pidPath, "wx", 384);
1180
1568
  writeSync(fd, String(process.pid));
1181
1569
  } catch {
1182
1570
  return;
@@ -1185,11 +1573,11 @@ var EmbedClient = class {
1185
1573
  return;
1186
1574
  }
1187
1575
  }
1188
- if (!this.daemonEntry || !existsSync3(this.daemonEntry)) {
1189
- log3(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1576
+ if (!this.daemonEntry || !existsSync4(this.daemonEntry)) {
1577
+ log4(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1190
1578
  try {
1191
- closeSync(fd);
1192
- unlinkSync(this.pidPath);
1579
+ closeSync2(fd);
1580
+ unlinkSync2(this.pidPath);
1193
1581
  } catch {
1194
1582
  }
1195
1583
  return;
@@ -1201,14 +1589,14 @@ var EmbedClient = class {
1201
1589
  env: process.env
1202
1590
  });
1203
1591
  child.unref();
1204
- log3(`spawned daemon pid=${child.pid}`);
1592
+ log4(`spawned daemon pid=${child.pid}`);
1205
1593
  } finally {
1206
- closeSync(fd);
1594
+ closeSync2(fd);
1207
1595
  }
1208
1596
  }
1209
1597
  isPidFileStale() {
1210
1598
  try {
1211
- const raw = readFileSync3(this.pidPath, "utf-8").trim();
1599
+ const raw = readFileSync5(this.pidPath, "utf-8").trim();
1212
1600
  const pid = Number(raw);
1213
1601
  if (!pid || Number.isNaN(pid))
1214
1602
  return true;
@@ -1226,9 +1614,9 @@ var EmbedClient = class {
1226
1614
  const deadline = Date.now() + this.spawnWaitMs;
1227
1615
  let delay = 30;
1228
1616
  while (Date.now() < deadline) {
1229
- await sleep2(delay);
1617
+ await sleep3(delay);
1230
1618
  delay = Math.min(delay * 1.5, 300);
1231
- if (!existsSync3(this.socketPath))
1619
+ if (!existsSync4(this.socketPath))
1232
1620
  continue;
1233
1621
  try {
1234
1622
  return await this.connectOnce();
@@ -1238,7 +1626,7 @@ var EmbedClient = class {
1238
1626
  throw new Error("daemon did not become ready within spawnWaitMs");
1239
1627
  }
1240
1628
  sendAndWait(sock, req) {
1241
- return new Promise((resolve2, reject) => {
1629
+ return new Promise((resolve3, reject) => {
1242
1630
  let buf = "";
1243
1631
  const to = setTimeout(() => {
1244
1632
  sock.destroy();
@@ -1253,7 +1641,7 @@ var EmbedClient = class {
1253
1641
  const line = buf.slice(0, nl);
1254
1642
  clearTimeout(to);
1255
1643
  try {
1256
- resolve2(JSON.parse(line));
1644
+ resolve3(JSON.parse(line));
1257
1645
  } catch (e) {
1258
1646
  reject(e);
1259
1647
  }
@@ -1270,53 +1658,22 @@ var EmbedClient = class {
1270
1658
  });
1271
1659
  }
1272
1660
  };
1273
- function sleep2(ms) {
1661
+ function sleep3(ms) {
1274
1662
  return new Promise((r) => setTimeout(r, ms));
1275
1663
  }
1276
-
1277
- // dist/src/embeddings/disable.js
1278
- import { createRequire } from "node:module";
1279
- import { homedir as homedir4 } from "node:os";
1280
- import { join as join5 } from "node:path";
1281
- import { pathToFileURL } from "node:url";
1282
- var cachedStatus = null;
1283
- function defaultResolveTransformers() {
1284
- try {
1285
- createRequire(import.meta.url).resolve("@huggingface/transformers");
1286
- return;
1287
- } catch {
1288
- }
1289
- const sharedDir = join5(homedir4(), ".hivemind", "embed-deps");
1290
- createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1291
- }
1292
- var _resolve = defaultResolveTransformers;
1293
- function detectStatus() {
1294
- if (process.env.HIVEMIND_EMBEDDINGS === "false")
1295
- return "env-disabled";
1296
- try {
1297
- _resolve();
1298
- return "enabled";
1299
- } catch {
1300
- return "no-transformers";
1301
- }
1302
- }
1303
- function embeddingsStatus() {
1304
- if (cachedStatus !== null)
1305
- return cachedStatus;
1306
- cachedStatus = detectStatus();
1307
- return cachedStatus;
1308
- }
1309
- function embeddingsDisabled() {
1310
- return embeddingsStatus() !== "enabled";
1664
+ function isTransformersMissingError(err) {
1665
+ if (/hivemind embeddings install/i.test(err))
1666
+ return true;
1667
+ return /@huggingface\/transformers/i.test(err);
1311
1668
  }
1312
1669
 
1313
1670
  // dist/src/hooks/grep-direct.js
1314
1671
  import { fileURLToPath } from "node:url";
1315
- import { dirname, join as join6 } from "node:path";
1672
+ import { dirname as dirname2, join as join8 } from "node:path";
1316
1673
  var SEMANTIC_ENABLED = process.env.HIVEMIND_SEMANTIC_SEARCH !== "false" && !embeddingsDisabled();
1317
1674
  var SEMANTIC_TIMEOUT_MS = Number(process.env.HIVEMIND_SEMANTIC_EMBED_TIMEOUT_MS ?? "500");
1318
1675
  function resolveDaemonPath() {
1319
- return join6(dirname(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
1676
+ return join8(dirname2(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
1320
1677
  }
1321
1678
  var sharedEmbedClient = null;
1322
1679
  function getEmbedClient() {
@@ -2319,20 +2676,20 @@ async function executeCompiledBashCommand(api, memoryTable, sessionsTable, cmd,
2319
2676
  }
2320
2677
 
2321
2678
  // dist/src/hooks/query-cache.js
2322
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
2323
- import { join as join7 } from "node:path";
2324
- import { homedir as homedir5 } from "node:os";
2325
- var log4 = (msg) => log("query-cache", msg);
2326
- var DEFAULT_CACHE_ROOT = join7(homedir5(), ".deeplake", "query-cache");
2679
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync6, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
2680
+ import { join as join9 } from "node:path";
2681
+ import { homedir as homedir7 } from "node:os";
2682
+ var log5 = (msg) => log("query-cache", msg);
2683
+ var DEFAULT_CACHE_ROOT = join9(homedir7(), ".deeplake", "query-cache");
2327
2684
  var INDEX_CACHE_FILE = "index.md";
2328
2685
  function getSessionQueryCacheDir(sessionId, deps = {}) {
2329
2686
  const { cacheRoot = DEFAULT_CACHE_ROOT } = deps;
2330
- return join7(cacheRoot, sessionId);
2687
+ return join9(cacheRoot, sessionId);
2331
2688
  }
2332
2689
  function readCachedIndexContent(sessionId, deps = {}) {
2333
- const { logFn = log4 } = deps;
2690
+ const { logFn = log5 } = deps;
2334
2691
  try {
2335
- return readFileSync4(join7(getSessionQueryCacheDir(sessionId, deps), INDEX_CACHE_FILE), "utf-8");
2692
+ return readFileSync6(join9(getSessionQueryCacheDir(sessionId, deps), INDEX_CACHE_FILE), "utf-8");
2336
2693
  } catch (e) {
2337
2694
  if (e?.code === "ENOENT")
2338
2695
  return null;
@@ -2341,34 +2698,34 @@ function readCachedIndexContent(sessionId, deps = {}) {
2341
2698
  }
2342
2699
  }
2343
2700
  function writeCachedIndexContent(sessionId, content, deps = {}) {
2344
- const { logFn = log4 } = deps;
2701
+ const { logFn = log5 } = deps;
2345
2702
  try {
2346
2703
  const dir = getSessionQueryCacheDir(sessionId, deps);
2347
- mkdirSync2(dir, { recursive: true });
2348
- writeFileSync2(join7(dir, INDEX_CACHE_FILE), content, "utf-8");
2704
+ mkdirSync4(dir, { recursive: true });
2705
+ writeFileSync4(join9(dir, INDEX_CACHE_FILE), content, "utf-8");
2349
2706
  } catch (e) {
2350
2707
  logFn(`write failed for session=${sessionId}: ${e.message}`);
2351
2708
  }
2352
2709
  }
2353
2710
 
2354
2711
  // dist/src/utils/direct-run.js
2355
- import { resolve } from "node:path";
2712
+ import { resolve as resolve2 } from "node:path";
2356
2713
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2357
2714
  function isDirectRun(metaUrl) {
2358
2715
  const entry = process.argv[1];
2359
2716
  if (!entry)
2360
2717
  return false;
2361
2718
  try {
2362
- return resolve(fileURLToPath2(metaUrl)) === resolve(entry);
2719
+ return resolve2(fileURLToPath2(metaUrl)) === resolve2(entry);
2363
2720
  } catch {
2364
2721
  return false;
2365
2722
  }
2366
2723
  }
2367
2724
 
2368
2725
  // dist/src/hooks/memory-path-utils.js
2369
- import { homedir as homedir6 } from "node:os";
2370
- import { join as join8 } from "node:path";
2371
- var MEMORY_PATH = join8(homedir6(), ".deeplake", "memory");
2726
+ import { homedir as homedir8 } from "node:os";
2727
+ import { join as join10 } from "node:path";
2728
+ var MEMORY_PATH = join10(homedir8(), ".deeplake", "memory");
2372
2729
  var TILDE_PATH = "~/.deeplake/memory";
2373
2730
  var HOME_VAR_PATH = "$HOME/.deeplake/memory";
2374
2731
  var SAFE_BUILTINS = /* @__PURE__ */ new Set([
@@ -2484,13 +2841,13 @@ function rewritePaths(cmd) {
2484
2841
  }
2485
2842
 
2486
2843
  // dist/src/hooks/codex/pre-tool-use.js
2487
- var log5 = (msg) => log("codex-pre", msg);
2488
- var __bundleDir = dirname2(fileURLToPath3(import.meta.url));
2489
- var SHELL_BUNDLE = existsSync4(join9(__bundleDir, "shell", "deeplake-shell.js")) ? join9(__bundleDir, "shell", "deeplake-shell.js") : join9(__bundleDir, "..", "shell", "deeplake-shell.js");
2844
+ var log6 = (msg) => log("codex-pre", msg);
2845
+ var __bundleDir = dirname3(fileURLToPath3(import.meta.url));
2846
+ var SHELL_BUNDLE = existsSync5(join11(__bundleDir, "shell", "deeplake-shell.js")) ? join11(__bundleDir, "shell", "deeplake-shell.js") : join11(__bundleDir, "..", "shell", "deeplake-shell.js");
2490
2847
  function buildUnsupportedGuidance() {
2491
2848
  return "This command is not supported for ~/.deeplake/memory/ operations. Only bash builtins are available: cat, ls, grep, echo, jq, head, tail, sed, awk, wc, sort, find, etc. Do NOT use python, python3, node, curl, or other interpreters. Rewrite your command using only bash tools and retry.";
2492
2849
  }
2493
- function runVirtualShell(cmd, shellBundle = SHELL_BUNDLE, logFn = log5) {
2850
+ function runVirtualShell(cmd, shellBundle = SHELL_BUNDLE, logFn = log6) {
2494
2851
  try {
2495
2852
  return execFileSync("node", [shellBundle, "-c", cmd], {
2496
2853
  encoding: "utf-8",
@@ -2515,7 +2872,7 @@ function buildIndexContent(rows) {
2515
2872
  return lines.join("\n");
2516
2873
  }
2517
2874
  async function processCodexPreToolUse(input, deps = {}) {
2518
- const { config = loadConfig(), createApi = (table, activeConfig) => new DeeplakeApi(activeConfig.token, activeConfig.apiUrl, activeConfig.orgId, activeConfig.workspaceId, table), executeCompiledBashCommandFn = executeCompiledBashCommand, readVirtualPathContentsFn = readVirtualPathContents, readVirtualPathContentFn = readVirtualPathContent, listVirtualPathRowsFn = listVirtualPathRows, findVirtualPathsFn = findVirtualPaths, handleGrepDirectFn = handleGrepDirect, readCachedIndexContentFn = readCachedIndexContent, writeCachedIndexContentFn = writeCachedIndexContent, runVirtualShellFn = runVirtualShell, shellBundle = SHELL_BUNDLE, logFn = log5 } = deps;
2875
+ const { config = loadConfig(), createApi = (table, activeConfig) => new DeeplakeApi(activeConfig.token, activeConfig.apiUrl, activeConfig.orgId, activeConfig.workspaceId, table), executeCompiledBashCommandFn = executeCompiledBashCommand, readVirtualPathContentsFn = readVirtualPathContents, readVirtualPathContentFn = readVirtualPathContent, listVirtualPathRowsFn = listVirtualPathRows, findVirtualPathsFn = findVirtualPaths, handleGrepDirectFn = handleGrepDirect, readCachedIndexContentFn = readCachedIndexContent, writeCachedIndexContentFn = writeCachedIndexContent, runVirtualShellFn = runVirtualShell, shellBundle = SHELL_BUNDLE, logFn = log6 } = deps;
2519
2876
  const cmd = input.tool_input?.command ?? "";
2520
2877
  logFn(`hook fired: cmd=${cmd}`);
2521
2878
  if (!touchesMemory(cmd))
@@ -2725,7 +3082,7 @@ async function main() {
2725
3082
  }
2726
3083
  if (isDirectRun(import.meta.url)) {
2727
3084
  main().catch((e) => {
2728
- log5(`fatal: ${e.message}`);
3085
+ log6(`fatal: ${e.message}`);
2729
3086
  process.exit(0);
2730
3087
  });
2731
3088
  }