@deeplake/hivemind 0.7.33 → 0.7.35

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.
@@ -4,6 +4,10 @@ import {
4
4
  saveCredentials
5
5
  } from "./chunks/chunk-OSD5GJJ5.js";
6
6
 
7
+ // stub:node:child_process
8
+ var spawn = () => {
9
+ };
10
+
7
11
  // src/utils/client-header.ts
8
12
  var DEEPLAKE_CLIENT_HEADER = "X-Deeplake-Client";
9
13
  function deeplakeClientValue() {
@@ -1153,10 +1157,232 @@ async function readVirtualPathContent(api2, memoryTable2, sessionsTable2, virtua
1153
1157
  return (await readVirtualPathContents(api2, memoryTable2, sessionsTable2, [virtualPath])).get(virtualPath) ?? null;
1154
1158
  }
1155
1159
 
1160
+ // src/embeddings/standalone-embed-client.ts
1161
+ import { connect } from "node:net";
1162
+ import {
1163
+ openSync as openSync2,
1164
+ closeSync as closeSync2,
1165
+ writeSync,
1166
+ unlinkSync as unlinkSync2,
1167
+ existsSync,
1168
+ readFileSync as readFileSync2
1169
+ } from "node:fs";
1170
+ import { homedir as homedir3 } from "node:os";
1171
+ import { join as join3 } from "node:path";
1172
+
1173
+ // src/embeddings/protocol.ts
1174
+ var DEFAULT_SOCKET_DIR = "/tmp";
1175
+ var DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1e3;
1176
+ var DEFAULT_CLIENT_TIMEOUT_MS = 2e3;
1177
+ function socketPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
1178
+ return `${dir}/hivemind-embed-${uid}.sock`;
1179
+ }
1180
+ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
1181
+ return `${dir}/hivemind-embed-${uid}.pid`;
1182
+ }
1183
+
1184
+ // src/embeddings/standalone-embed-client.ts
1185
+ var SHARED_DAEMON_PATH = join3(homedir3(), ".hivemind", "embed-deps", "embed-daemon.js");
1186
+ var _spawn = spawn;
1187
+ function getUid() {
1188
+ const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
1189
+ return uid !== void 0 ? String(uid) : "default";
1190
+ }
1191
+ function isPidAlive(pid) {
1192
+ if (!Number.isFinite(pid) || pid <= 0) return false;
1193
+ try {
1194
+ process.kill(pid, 0);
1195
+ return true;
1196
+ } catch {
1197
+ return false;
1198
+ }
1199
+ }
1200
+ function readPidFile(path) {
1201
+ let raw;
1202
+ try {
1203
+ raw = readFileSync2(path, "utf-8").trim();
1204
+ } catch {
1205
+ return null;
1206
+ }
1207
+ if (raw === "") return "empty";
1208
+ const pid = Number(raw);
1209
+ if (!pid || Number.isNaN(pid)) return null;
1210
+ return pid;
1211
+ }
1212
+ function connectOnce(socketPath, timeoutMs) {
1213
+ return new Promise((resolve2, reject) => {
1214
+ const sock = connect(socketPath);
1215
+ const to = setTimeout(() => {
1216
+ sock.destroy();
1217
+ reject(new Error("connect timeout"));
1218
+ }, timeoutMs);
1219
+ sock.once("connect", () => {
1220
+ clearTimeout(to);
1221
+ resolve2(sock);
1222
+ });
1223
+ sock.once("error", (e) => {
1224
+ clearTimeout(to);
1225
+ reject(e);
1226
+ });
1227
+ });
1228
+ }
1229
+ function sendAndWait(sock, req, timeoutMs) {
1230
+ return new Promise((resolve2, reject) => {
1231
+ let buf = "";
1232
+ const to = setTimeout(() => {
1233
+ sock.destroy();
1234
+ reject(new Error("request timeout"));
1235
+ }, timeoutMs);
1236
+ sock.setEncoding("utf-8");
1237
+ sock.on("data", (chunk) => {
1238
+ buf += chunk;
1239
+ const nl = buf.indexOf("\n");
1240
+ if (nl === -1) return;
1241
+ clearTimeout(to);
1242
+ try {
1243
+ resolve2(JSON.parse(buf.slice(0, nl)));
1244
+ } catch (e) {
1245
+ reject(e);
1246
+ }
1247
+ });
1248
+ sock.on("error", (e) => {
1249
+ clearTimeout(to);
1250
+ reject(e);
1251
+ });
1252
+ sock.on("end", () => {
1253
+ clearTimeout(to);
1254
+ reject(new Error("connection closed without response"));
1255
+ });
1256
+ sock.write(JSON.stringify(req) + "\n");
1257
+ });
1258
+ }
1259
+ function trySpawnDaemon(daemonEntry, pidPath) {
1260
+ let fd;
1261
+ try {
1262
+ fd = openSync2(pidPath, "wx", 384);
1263
+ writeSync(fd, String(process.pid));
1264
+ } catch {
1265
+ const existing = readPidFile(pidPath);
1266
+ if (existing === "empty") return false;
1267
+ if (existing !== null && isPidAlive(existing)) {
1268
+ return false;
1269
+ }
1270
+ try {
1271
+ unlinkSync2(pidPath);
1272
+ } catch {
1273
+ }
1274
+ try {
1275
+ fd = openSync2(pidPath, "wx", 384);
1276
+ writeSync(fd, String(process.pid));
1277
+ } catch {
1278
+ return false;
1279
+ }
1280
+ }
1281
+ try {
1282
+ const child = _spawn(process.execPath, [daemonEntry], {
1283
+ detached: true,
1284
+ stdio: "ignore"
1285
+ });
1286
+ child.unref();
1287
+ return true;
1288
+ } catch {
1289
+ try {
1290
+ unlinkSync2(pidPath);
1291
+ } catch {
1292
+ }
1293
+ return false;
1294
+ } finally {
1295
+ try {
1296
+ closeSync2(fd);
1297
+ } catch {
1298
+ }
1299
+ }
1300
+ }
1301
+ function maybeCleanupOwnPlaceholder(pidPath) {
1302
+ const existing = readPidFile(pidPath);
1303
+ if (existing === process.pid || existing === "empty") {
1304
+ try {
1305
+ unlinkSync2(pidPath);
1306
+ } catch {
1307
+ }
1308
+ }
1309
+ }
1310
+ async function waitForSocket(socketPath, deadline, connectTimeoutMs) {
1311
+ let delay = 30;
1312
+ while (Date.now() < deadline) {
1313
+ await new Promise((r) => setTimeout(r, delay));
1314
+ delay = Math.min(delay * 1.5, 300);
1315
+ if (!existsSync(socketPath)) continue;
1316
+ try {
1317
+ return await connectOnce(socketPath, connectTimeoutMs);
1318
+ } catch {
1319
+ }
1320
+ }
1321
+ return null;
1322
+ }
1323
+ async function tryEmbedStandalone(text, kind, opts = {}) {
1324
+ const socketDir = opts.socketDir ?? "/tmp";
1325
+ const daemonEntry = opts.daemonEntry ?? SHARED_DAEMON_PATH;
1326
+ const requestTimeoutMs = opts.requestTimeoutMs ?? DEFAULT_CLIENT_TIMEOUT_MS;
1327
+ const spawnWaitMs = opts.spawnWaitMs ?? 5e3;
1328
+ const uid = getUid();
1329
+ const socketPath = socketPathFor(uid, socketDir);
1330
+ const pidPath = pidPathFor(uid, socketDir);
1331
+ let sock = null;
1332
+ try {
1333
+ sock = await connectOnce(socketPath, requestTimeoutMs);
1334
+ } catch {
1335
+ }
1336
+ if (!sock) {
1337
+ if (!existsSync(daemonEntry)) {
1338
+ return null;
1339
+ }
1340
+ trySpawnDaemon(daemonEntry, pidPath);
1341
+ const deadline = Date.now() + spawnWaitMs;
1342
+ sock = await waitForSocket(socketPath, deadline, requestTimeoutMs);
1343
+ if (!sock) {
1344
+ maybeCleanupOwnPlaceholder(pidPath);
1345
+ return null;
1346
+ }
1347
+ }
1348
+ try {
1349
+ const req = { op: "embed", id: "1", kind, text };
1350
+ const resp = await sendAndWait(sock, req, requestTimeoutMs);
1351
+ if (resp.error || !resp.embedding || !Array.isArray(resp.embedding)) {
1352
+ return null;
1353
+ }
1354
+ for (const v of resp.embedding) {
1355
+ if (typeof v !== "number" || !Number.isFinite(v)) return null;
1356
+ }
1357
+ return resp.embedding;
1358
+ } catch {
1359
+ return null;
1360
+ } finally {
1361
+ try {
1362
+ sock.end();
1363
+ } catch {
1364
+ }
1365
+ }
1366
+ }
1367
+ function _setSpawnImpl(fn) {
1368
+ _spawn = fn ?? spawn;
1369
+ }
1370
+
1371
+ // src/embeddings/sql.ts
1372
+ function embeddingSqlLiteral(vec) {
1373
+ if (!vec || vec.length === 0) return "NULL";
1374
+ const parts = [];
1375
+ for (const v of vec) {
1376
+ if (!Number.isFinite(v)) return "NULL";
1377
+ parts.push(String(v));
1378
+ }
1379
+ return `ARRAY[${parts.join(",")}]::float4[]`;
1380
+ }
1381
+
1156
1382
  // openclaw/src/index.ts
1157
1383
  import { fileURLToPath } from "node:url";
1158
1384
  import { join as joinPath, dirname as dirnamePath } from "node:path";
1159
- import { homedir as homedir3, tmpdir } from "node:os";
1385
+ import { homedir as homedir4, tmpdir } from "node:os";
1160
1386
  import {
1161
1387
  existsSync as fsExists,
1162
1388
  mkdirSync as fsMkdir,
@@ -1202,6 +1428,7 @@ async function loadConfig() {
1202
1428
  }
1203
1429
  var requireFromOpenclaw = createRequire(import.meta.url);
1204
1430
  var { spawn: realSpawn, execFileSync: realExecFileSync } = requireFromOpenclaw("node:child_process");
1431
+ _setSpawnImpl(realSpawn);
1205
1432
  var inheritedEnv = process;
1206
1433
  function applyOpenclawTuning(pluginConfig) {
1207
1434
  const cfg = pluginConfig ?? {};
@@ -1239,7 +1466,7 @@ function extractLatestVersion(body) {
1239
1466
  return typeof v === "string" && v.length > 0 ? v : null;
1240
1467
  }
1241
1468
  function getInstalledVersion() {
1242
- return "0.7.33".length > 0 ? "0.7.33" : null;
1469
+ return "0.7.35".length > 0 ? "0.7.35" : null;
1243
1470
  }
1244
1471
  function isNewer(latest, current) {
1245
1472
  const parse = (v) => v.replace(/-.*$/, "").split(".").map(Number);
@@ -1346,8 +1573,8 @@ var skillifySpawnedFor = /* @__PURE__ */ new Set();
1346
1573
  var __openclaw_filename = fileURLToPath(import.meta.url);
1347
1574
  var __openclaw_dirname = dirnamePath(__openclaw_filename);
1348
1575
  var OPENCLAW_SKILLIFY_WORKER_PATH = joinPath(__openclaw_dirname, "skillify-worker.js");
1349
- var OPENCLAW_SKILLIFY_STATE_DIR = joinPath(homedir3(), ".deeplake", "state", "skillify");
1350
- var OPENCLAW_SKILLIFY_LEGACY_STATE_DIR = joinPath(homedir3(), ".deeplake", "state", "skilify");
1576
+ var OPENCLAW_SKILLIFY_STATE_DIR = joinPath(homedir4(), ".deeplake", "state", "skillify");
1577
+ var OPENCLAW_SKILLIFY_LEGACY_STATE_DIR = joinPath(homedir4(), ".deeplake", "state", "skilify");
1351
1578
  var openclawSkillifyMigrationAttempted = false;
1352
1579
  function migrateOpenclawSkillifyLegacyStateDir() {
1353
1580
  if (openclawSkillifyMigrationAttempted) return;
@@ -1463,7 +1690,7 @@ function spawnOpenclawSkillifyWorker(a) {
1463
1690
  sessionsTable,
1464
1691
  skillsTable,
1465
1692
  userName: a.userName,
1466
- cwd: homedir3(),
1693
+ cwd: homedir4(),
1467
1694
  // sentinel — only used by worker if install=project
1468
1695
  projectKey,
1469
1696
  project,
@@ -1479,7 +1706,7 @@ function spawnOpenclawSkillifyWorker(a) {
1479
1706
  cursorModel: void 0,
1480
1707
  hermesProvider: void 0,
1481
1708
  hermesModel: void 0,
1482
- skillifyLog: joinPath(homedir3(), ".deeplake", "hivemind-openclaw-skillify.log"),
1709
+ skillifyLog: joinPath(homedir4(), ".deeplake", "hivemind-openclaw-skillify.log"),
1483
1710
  currentSessionId: a.sessionId,
1484
1711
  // Pass the tuning dispatch through so the worker can repopulate its
1485
1712
  // own globalThis (each process has its own globalThis). The worker
@@ -2018,7 +2245,9 @@ One brain for every agent on your team.
2018
2245
  };
2019
2246
  const line = JSON.stringify(entry);
2020
2247
  const jsonForSql = line.replace(/'/g, "''");
2021
- const insertSql = `INSERT INTO "${sessionsTable}" (id, path, filename, message, author, size_bytes, project, description, agent, plugin_version, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(sessionPath)}', '${sqlStr(filename)}', '${jsonForSql}'::jsonb, '${sqlStr(cfg.userName)}', ${Buffer.byteLength(line, "utf-8")}, '${sqlStr(projectName)}', '${sqlStr(msg.role)}', 'openclaw', '${sqlStr(getInstalledVersion() ?? "")}', '${ts}', '${ts}')`;
2248
+ const embedding = await tryEmbedStandalone(line, "document");
2249
+ const embeddingSql = embeddingSqlLiteral(embedding);
2250
+ const insertSql = `INSERT INTO "${sessionsTable}" (id, path, filename, message, message_embedding, author, size_bytes, project, description, agent, plugin_version, creation_date, last_update_date) VALUES ('${crypto.randomUUID()}', '${sqlStr(sessionPath)}', '${sqlStr(filename)}', '${jsonForSql}'::jsonb, ${embeddingSql}, '${sqlStr(cfg.userName)}', ${Buffer.byteLength(line, "utf-8")}, '${sqlStr(projectName)}', '${sqlStr(msg.role)}', 'openclaw', '${sqlStr(getInstalledVersion() ?? "")}', '${ts}', '${ts}')`;
2022
2251
  try {
2023
2252
  await dl.query(insertSql);
2024
2253
  } catch (e) {
@@ -3,7 +3,7 @@ globalThis.__hivemind_tuning__ ??= {};
3
3
 
4
4
  // dist/src/skillify/skillify-worker.js
5
5
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync5, appendFileSync as appendFileSync2, rmSync } from "node:fs";
6
- import { join as join6 } from "node:path";
6
+ import { join as join7 } from "node:path";
7
7
 
8
8
  // dist/src/utils/debug.js
9
9
  import { appendFileSync } from "node:fs";
@@ -562,25 +562,34 @@ function resolveRecordScope(args) {
562
562
  }
563
563
 
564
564
  // dist/src/skillify/state.js
565
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, writeSync, mkdirSync as mkdirSync2, renameSync as renameSync2, existsSync as existsSync4, unlinkSync, openSync, closeSync } from "node:fs";
565
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, writeSync, mkdirSync as mkdirSync2, renameSync as renameSync2, rmdirSync, existsSync as existsSync4, lstatSync, unlinkSync, openSync, closeSync } from "node:fs";
566
566
  import { execSync } from "node:child_process";
567
- import { homedir as homedir5 } from "node:os";
568
567
  import { createHash } from "node:crypto";
569
- import { join as join5, basename } from "node:path";
568
+ import { join as join6, basename } from "node:path";
570
569
 
571
570
  // dist/src/skillify/legacy-migration.js
572
571
  import { existsSync as existsSync3, renameSync } from "node:fs";
572
+ import { dirname, join as join5 } from "node:path";
573
+
574
+ // dist/src/skillify/state-dir.js
573
575
  import { homedir as homedir4 } from "node:os";
574
576
  import { join as join4 } from "node:path";
577
+ function getStateDir() {
578
+ const override = globalThis.__hivemind_tuning__.HIVEMIND_STATE_DIR?.trim();
579
+ return override && override.length > 0 ? override : join4(homedir4(), ".deeplake", "state", "skillify");
580
+ }
581
+
582
+ // dist/src/skillify/legacy-migration.js
575
583
  var dlog = (msg) => log("skillify-migrate", msg);
576
584
  var attempted = false;
577
585
  function migrateLegacyStateDir() {
586
+ if (globalThis.__hivemind_tuning__.HIVEMIND_STATE_DIR?.trim())
587
+ return;
578
588
  if (attempted)
579
589
  return;
580
590
  attempted = true;
581
- const root = join4(homedir4(), ".deeplake", "state");
582
- const legacy = join4(root, "skilify");
583
- const current = join4(root, "skillify");
591
+ const current = getStateDir();
592
+ const legacy = join5(dirname(current), "skilify");
584
593
  if (!existsSync3(legacy))
585
594
  return;
586
595
  if (existsSync3(current))
@@ -590,8 +599,8 @@ function migrateLegacyStateDir() {
590
599
  dlog(`migrated ${legacy} -> ${current}`);
591
600
  } catch (err) {
592
601
  const code = err.code;
593
- if (code === "EXDEV" || code === "EPERM") {
594
- dlog(`migration failed (${code}); leaving legacy dir in place`);
602
+ if (code === "EXDEV" || code === "EPERM" || code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") {
603
+ dlog(`migration skipped (${code}); legacy dir left as-is or another process handled it`);
595
604
  return;
596
605
  }
597
606
  throw err;
@@ -600,17 +609,16 @@ function migrateLegacyStateDir() {
600
609
 
601
610
  // dist/src/skillify/state.js
602
611
  var dlog2 = (msg) => log("skillify-state", msg);
603
- var STATE_DIR = join5(homedir5(), ".deeplake", "state", "skillify");
604
612
  var YIELD_BUF = new Int32Array(new SharedArrayBuffer(4));
605
613
  var TRIGGER_THRESHOLD = (() => {
606
614
  const n = Number(globalThis.__hivemind_tuning__.HIVEMIND_SKILLIFY_EVERY_N_TURNS ?? "");
607
615
  return Number.isInteger(n) && n > 0 ? n : 20;
608
616
  })();
609
617
  function statePath(projectKey) {
610
- return join5(STATE_DIR, `${projectKey}.json`);
618
+ return join6(getStateDir(), `${projectKey}.json`);
611
619
  }
612
620
  function lockPath(projectKey) {
613
- return join5(STATE_DIR, `${projectKey}.lock`);
621
+ return join6(getStateDir(), `${projectKey}.lock`);
614
622
  }
615
623
  function readState(projectKey) {
616
624
  migrateLegacyStateDir();
@@ -625,7 +633,7 @@ function readState(projectKey) {
625
633
  }
626
634
  function writeState(projectKey, state) {
627
635
  migrateLegacyStateDir();
628
- mkdirSync2(STATE_DIR, { recursive: true });
636
+ mkdirSync2(getStateDir(), { recursive: true });
629
637
  const p = statePath(projectKey);
630
638
  const tmp = `${p}.${process.pid}.${Date.now()}.tmp`;
631
639
  writeFileSync2(tmp, JSON.stringify(state, null, 2));
@@ -633,7 +641,7 @@ function writeState(projectKey, state) {
633
641
  }
634
642
  function withRmwLock(projectKey, fn) {
635
643
  migrateLegacyStateDir();
636
- mkdirSync2(STATE_DIR, { recursive: true });
644
+ mkdirSync2(getStateDir(), { recursive: true });
637
645
  const rmw = lockPath(projectKey) + ".rmw";
638
646
  const deadline = Date.now() + 2e3;
639
647
  let fd = null;
@@ -706,8 +714,8 @@ function releaseWorkerLock(projectKey) {
706
714
  var cfg = JSON.parse(readFileSync3(process.argv[2], "utf-8"));
707
715
  globalThis.__hivemind_tuning__ = cfg.tuning ?? {};
708
716
  var tmpDir = cfg.tmpDir;
709
- var verdictPath = join6(tmpDir, "verdict.json");
710
- var promptPath = join6(tmpDir, "prompt.txt");
717
+ var verdictPath = join7(tmpDir, "verdict.json");
718
+ var promptPath = join7(tmpDir, "prompt.txt");
711
719
  var SESSIONS_TO_MINE = 10;
712
720
  var PAIR_CHAR_CAP = 2e3;
713
721
  var TOTAL_PAIRS_CHAR_CAP = 4e4;
@@ -954,9 +962,9 @@ async function main() {
954
962
  timeoutMs: 12e4
955
963
  });
956
964
  try {
957
- writeFileSync3(join6(tmpDir, "gate-stdout.txt"), gate.stdout);
965
+ writeFileSync3(join7(tmpDir, "gate-stdout.txt"), gate.stdout);
958
966
  if (gate.stderr)
959
- writeFileSync3(join6(tmpDir, "gate-stderr.txt"), gate.stderr);
967
+ writeFileSync3(join7(tmpDir, "gate-stderr.txt"), gate.stderr);
960
968
  } catch {
961
969
  }
962
970
  if (gate.errored) {
@@ -52,5 +52,5 @@
52
52
  }
53
53
  }
54
54
  },
55
- "version": "0.7.33"
55
+ "version": "0.7.35"
56
56
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hivemind",
3
- "version": "0.7.33",
3
+ "version": "0.7.35",
4
4
  "type": "module",
5
5
  "description": "Hivemind — cloud-backed persistent shared memory for AI agents, powered by DeepLake",
6
6
  "license": "Apache-2.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeplake/hivemind",
3
- "version": "0.7.33",
3
+ "version": "0.7.35",
4
4
  "description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
5
5
  "type": "module",
6
6
  "repository": {