@deeplake/hivemind 0.7.32 → 0.7.33

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.
@@ -16,21 +16,21 @@ __export(index_marker_store_exports, {
16
16
  hasFreshIndexMarker: () => hasFreshIndexMarker,
17
17
  writeIndexMarker: () => writeIndexMarker
18
18
  });
19
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
20
- import { join as join3 } from "node:path";
19
+ import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
20
+ import { join as join5 } from "node:path";
21
21
  import { tmpdir } from "node:os";
22
22
  function getIndexMarkerDir() {
23
- return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join3(tmpdir(), "hivemind-deeplake-indexes");
23
+ return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join5(tmpdir(), "hivemind-deeplake-indexes");
24
24
  }
25
25
  function buildIndexMarkerPath(workspaceId, orgId, table, suffix) {
26
26
  const markerKey = [workspaceId, orgId, table, suffix].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
27
- return join3(getIndexMarkerDir(), `${markerKey}.json`);
27
+ return join5(getIndexMarkerDir(), `${markerKey}.json`);
28
28
  }
29
29
  function hasFreshIndexMarker(markerPath) {
30
30
  if (!existsSync2(markerPath))
31
31
  return false;
32
32
  try {
33
- const raw = JSON.parse(readFileSync2(markerPath, "utf-8"));
33
+ const raw = JSON.parse(readFileSync4(markerPath, "utf-8"));
34
34
  const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
35
35
  if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS)
36
36
  return false;
@@ -40,8 +40,8 @@ function hasFreshIndexMarker(markerPath) {
40
40
  }
41
41
  }
42
42
  function writeIndexMarker(markerPath) {
43
- mkdirSync(getIndexMarkerDir(), { recursive: true });
44
- writeFileSync(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
43
+ mkdirSync3(getIndexMarkerDir(), { recursive: true });
44
+ writeFileSync3(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
45
45
  }
46
46
  var INDEX_MARKER_TTL_MS;
47
47
  var init_index_marker_store = __esm({
@@ -146,6 +146,125 @@ function deeplakeClientHeader() {
146
146
  return { [DEEPLAKE_CLIENT_HEADER]: deeplakeClientValue() };
147
147
  }
148
148
 
149
+ // dist/src/notifications/queue.js
150
+ import { readFileSync as readFileSync2, writeFileSync, renameSync, mkdirSync, openSync, closeSync, unlinkSync, statSync } from "node:fs";
151
+ import { join as join3, resolve } from "node:path";
152
+ import { homedir as homedir3 } from "node:os";
153
+ import { setTimeout as sleep } from "node:timers/promises";
154
+ var log2 = (msg) => log("notifications-queue", msg);
155
+ var LOCK_RETRY_MAX = 50;
156
+ var LOCK_RETRY_BASE_MS = 5;
157
+ var LOCK_STALE_MS = 5e3;
158
+ function queuePath() {
159
+ return join3(homedir3(), ".deeplake", "notifications-queue.json");
160
+ }
161
+ function lockPath() {
162
+ return `${queuePath()}.lock`;
163
+ }
164
+ function readQueue() {
165
+ try {
166
+ const raw = readFileSync2(queuePath(), "utf-8");
167
+ const parsed = JSON.parse(raw);
168
+ if (!parsed || !Array.isArray(parsed.queue)) {
169
+ log2(`queue malformed \u2192 treating as empty`);
170
+ return { queue: [] };
171
+ }
172
+ return { queue: parsed.queue };
173
+ } catch {
174
+ return { queue: [] };
175
+ }
176
+ }
177
+ function _isQueuePathInsideHome(path, home) {
178
+ const r = resolve(path);
179
+ const h = resolve(home);
180
+ return r.startsWith(h + "/") || r === h;
181
+ }
182
+ function writeQueue(q) {
183
+ const path = queuePath();
184
+ const home = resolve(homedir3());
185
+ if (!_isQueuePathInsideHome(path, home)) {
186
+ throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
187
+ }
188
+ mkdirSync(join3(home, ".deeplake"), { recursive: true, mode: 448 });
189
+ const tmp = `${path}.${process.pid}.tmp`;
190
+ writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
191
+ renameSync(tmp, path);
192
+ }
193
+ async function withQueueLock(fn) {
194
+ const path = lockPath();
195
+ mkdirSync(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
196
+ let fd = null;
197
+ for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
198
+ try {
199
+ fd = openSync(path, "wx", 384);
200
+ break;
201
+ } catch (e) {
202
+ const code = e.code;
203
+ if (code !== "EEXIST")
204
+ throw e;
205
+ try {
206
+ const age = Date.now() - statSync(path).mtimeMs;
207
+ if (age > LOCK_STALE_MS) {
208
+ unlinkSync(path);
209
+ continue;
210
+ }
211
+ } catch {
212
+ }
213
+ const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
214
+ await sleep(delay);
215
+ }
216
+ }
217
+ if (fd === null) {
218
+ log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
219
+ return fn();
220
+ }
221
+ try {
222
+ return fn();
223
+ } finally {
224
+ try {
225
+ closeSync(fd);
226
+ } catch {
227
+ }
228
+ try {
229
+ unlinkSync(path);
230
+ } catch {
231
+ }
232
+ }
233
+ }
234
+ function sameDedupKey(a, b) {
235
+ if (a.id !== b.id)
236
+ return false;
237
+ return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
238
+ }
239
+ async function enqueueNotification(n) {
240
+ await withQueueLock(() => {
241
+ const q = readQueue();
242
+ if (q.queue.some((existing) => sameDedupKey(existing, n))) {
243
+ return;
244
+ }
245
+ q.queue.push(n);
246
+ writeQueue(q);
247
+ });
248
+ }
249
+
250
+ // dist/src/commands/auth-creds.js
251
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2 } from "node:fs";
252
+ import { join as join4 } from "node:path";
253
+ import { homedir as homedir4 } from "node:os";
254
+ function configDir() {
255
+ return join4(homedir4(), ".deeplake");
256
+ }
257
+ function credsPath() {
258
+ return join4(configDir(), "credentials.json");
259
+ }
260
+ function loadCredentials() {
261
+ try {
262
+ return JSON.parse(readFileSync3(credsPath(), "utf-8"));
263
+ } catch {
264
+ return null;
265
+ }
266
+ }
267
+
149
268
  // dist/src/deeplake-api.js
150
269
  var indexMarkerStorePromise = null;
151
270
  function getIndexMarkerStore() {
@@ -153,7 +272,7 @@ function getIndexMarkerStore() {
153
272
  indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
154
273
  return indexMarkerStorePromise;
155
274
  }
156
- var log2 = (msg) => log("sdk", msg);
275
+ var log3 = (msg) => log("sdk", msg);
157
276
  function summarizeSql(sql, maxLen = 220) {
158
277
  const compact = sql.replace(/\s+/g, " ").trim();
159
278
  return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
@@ -165,7 +284,38 @@ function traceSql(msg) {
165
284
  process.stderr.write(`[deeplake-sql] ${msg}
166
285
  `);
167
286
  if (process.env.HIVEMIND_DEBUG === "1")
168
- log2(msg);
287
+ log3(msg);
288
+ }
289
+ var _signalledBalanceExhausted = false;
290
+ function maybeSignalBalanceExhausted(status, bodyText) {
291
+ if (status !== 402)
292
+ return;
293
+ if (!bodyText.includes("balance_cents"))
294
+ return;
295
+ if (_signalledBalanceExhausted)
296
+ return;
297
+ _signalledBalanceExhausted = true;
298
+ log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
299
+ enqueueNotification({
300
+ id: "balance-exhausted",
301
+ severity: "warn",
302
+ transient: true,
303
+ title: "Hivemind credits exhausted \u2014 top up to keep capturing",
304
+ body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
305
+ dedupKey: { reason: "balance-zero" }
306
+ }).catch((e) => {
307
+ log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
308
+ });
309
+ }
310
+ function billingUrl() {
311
+ try {
312
+ const c = loadCredentials();
313
+ if (c?.orgName && c?.workspaceId) {
314
+ return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
315
+ }
316
+ } catch {
317
+ }
318
+ return "https://deeplake.ai";
169
319
  }
170
320
  var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
171
321
  var MAX_RETRIES = 3;
@@ -174,7 +324,7 @@ var MAX_CONCURRENCY = 5;
174
324
  function getQueryTimeoutMs() {
175
325
  return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
176
326
  }
177
- function sleep(ms) {
327
+ function sleep2(ms) {
178
328
  return new Promise((resolve2) => setTimeout(resolve2, ms));
179
329
  }
180
330
  function isTimeoutError(error) {
@@ -276,8 +426,8 @@ var DeeplakeApi = class {
276
426
  lastError = e instanceof Error ? e : new Error(String(e));
277
427
  if (attempt < MAX_RETRIES) {
278
428
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
279
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
280
- await sleep(delay);
429
+ log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
430
+ await sleep2(delay);
281
431
  continue;
282
432
  }
283
433
  throw lastError;
@@ -293,10 +443,11 @@ var DeeplakeApi = class {
293
443
  const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
294
444
  if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
295
445
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
296
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
297
- await sleep(delay);
446
+ log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
447
+ await sleep2(delay);
298
448
  continue;
299
449
  }
450
+ maybeSignalBalanceExhausted(resp.status, text);
300
451
  throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
301
452
  }
302
453
  throw lastError ?? new Error("Query failed: max retries exceeded");
@@ -317,7 +468,7 @@ var DeeplakeApi = class {
317
468
  const chunk = rows.slice(i, i + CONCURRENCY);
318
469
  await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
319
470
  }
320
- log2(`commit: ${rows.length} rows`);
471
+ log3(`commit: ${rows.length} rows`);
321
472
  }
322
473
  async upsertRowSql(row) {
323
474
  const ts = (/* @__PURE__ */ new Date()).toISOString();
@@ -373,7 +524,7 @@ var DeeplakeApi = class {
373
524
  markers.writeIndexMarker(markerPath);
374
525
  return;
375
526
  }
376
- log2(`index "${indexName}" skipped: ${e.message}`);
527
+ log3(`index "${indexName}" skipped: ${e.message}`);
377
528
  }
378
529
  }
379
530
  /**
@@ -463,13 +614,13 @@ var DeeplakeApi = class {
463
614
  };
464
615
  }
465
616
  if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
466
- await sleep(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
617
+ await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
467
618
  continue;
468
619
  }
469
620
  return { tables: [], cacheable: false };
470
621
  } catch {
471
622
  if (attempt < MAX_RETRIES) {
472
- await sleep(BASE_DELAY_MS * Math.pow(2, attempt));
623
+ await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
473
624
  continue;
474
625
  }
475
626
  return { tables: [], cacheable: false };
@@ -497,9 +648,9 @@ var DeeplakeApi = class {
497
648
  } catch (err) {
498
649
  lastErr = err;
499
650
  const msg = err instanceof Error ? err.message : String(err);
500
- log2(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
651
+ log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
501
652
  if (attempt < OUTER_BACKOFFS_MS.length) {
502
- await sleep(OUTER_BACKOFFS_MS[attempt]);
653
+ await sleep2(OUTER_BACKOFFS_MS[attempt]);
503
654
  }
504
655
  }
505
656
  }
@@ -510,9 +661,9 @@ var DeeplakeApi = class {
510
661
  const tbl = sqlIdent(name ?? this.tableName);
511
662
  const tables = await this.listTables();
512
663
  if (!tables.includes(tbl)) {
513
- log2(`table "${tbl}" not found, creating`);
664
+ log3(`table "${tbl}" not found, creating`);
514
665
  await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${tbl}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', summary TEXT NOT NULL DEFAULT '', summary_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'text/plain', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, tbl);
515
- log2(`table "${tbl}" created`);
666
+ log3(`table "${tbl}" created`);
516
667
  if (!tables.includes(tbl))
517
668
  this._tablesCache = [...tables, tbl];
518
669
  }
@@ -525,9 +676,9 @@ var DeeplakeApi = class {
525
676
  const safe = sqlIdent(name);
526
677
  const tables = await this.listTables();
527
678
  if (!tables.includes(safe)) {
528
- log2(`table "${safe}" not found, creating`);
679
+ log3(`table "${safe}" not found, creating`);
529
680
  await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', path TEXT NOT NULL DEFAULT '', filename TEXT NOT NULL DEFAULT '', message JSONB, message_embedding FLOAT4[], author TEXT NOT NULL DEFAULT '', mime_type TEXT NOT NULL DEFAULT 'application/json', size_bytes BIGINT NOT NULL DEFAULT 0, project TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', agent TEXT NOT NULL DEFAULT '', plugin_version TEXT NOT NULL DEFAULT '', creation_date TEXT NOT NULL DEFAULT '', last_update_date TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
530
- log2(`table "${safe}" created`);
681
+ log3(`table "${safe}" created`);
531
682
  if (!tables.includes(safe))
532
683
  this._tablesCache = [...tables, safe];
533
684
  }
@@ -550,9 +701,9 @@ var DeeplakeApi = class {
550
701
  const safe = sqlIdent(name);
551
702
  const tables = await this.listTables();
552
703
  if (!tables.includes(safe)) {
553
- log2(`table "${safe}" not found, creating`);
704
+ log3(`table "${safe}" not found, creating`);
554
705
  await this.createTableWithRetry(`CREATE TABLE IF NOT EXISTS "${safe}" (id TEXT NOT NULL DEFAULT '', name TEXT NOT NULL DEFAULT '', project TEXT NOT NULL DEFAULT '', project_key TEXT NOT NULL DEFAULT '', local_path TEXT NOT NULL DEFAULT '', install TEXT NOT NULL DEFAULT 'project', source_sessions TEXT NOT NULL DEFAULT '[]', source_agent TEXT NOT NULL DEFAULT '', scope TEXT NOT NULL DEFAULT 'me', author TEXT NOT NULL DEFAULT '', description TEXT NOT NULL DEFAULT '', trigger_text TEXT NOT NULL DEFAULT '', body TEXT NOT NULL DEFAULT '', version BIGINT NOT NULL DEFAULT 1, created_at TEXT NOT NULL DEFAULT '', updated_at TEXT NOT NULL DEFAULT '') USING deeplake`, safe);
555
- log2(`table "${safe}" created`);
706
+ log3(`table "${safe}" created`);
556
707
  if (!tables.includes(safe))
557
708
  this._tablesCache = [...tables, safe];
558
709
  }
@@ -1042,9 +1193,9 @@ function capOutputForClaude(output, options = {}) {
1042
1193
  // dist/src/embeddings/client.js
1043
1194
  import { connect } from "node:net";
1044
1195
  import { spawn } from "node:child_process";
1045
- import { openSync as openSync2, closeSync as closeSync2, writeSync, unlinkSync as unlinkSync2, existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
1046
- import { homedir as homedir6 } from "node:os";
1047
- import { join as join7 } from "node:path";
1196
+ import { openSync as openSync2, closeSync as closeSync2, writeSync, unlinkSync as unlinkSync3, existsSync as existsSync3, readFileSync as readFileSync5 } from "node:fs";
1197
+ import { homedir as homedir5 } from "node:os";
1198
+ import { join as join6 } from "node:path";
1048
1199
 
1049
1200
  // dist/src/embeddings/protocol.js
1050
1201
  var DEFAULT_SOCKET_DIR = "/tmp";
@@ -1057,233 +1208,13 @@ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
1057
1208
  return `${dir}/hivemind-embed-${uid}.pid`;
1058
1209
  }
1059
1210
 
1060
- // dist/src/notifications/queue.js
1061
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync, mkdirSync as mkdirSync2, openSync, closeSync, unlinkSync, statSync } from "node:fs";
1062
- import { join as join4, resolve } from "node:path";
1063
- import { homedir as homedir3 } from "node:os";
1064
- import { setTimeout as sleep2 } from "node:timers/promises";
1065
- var log3 = (msg) => log("notifications-queue", msg);
1066
- var LOCK_RETRY_MAX = 50;
1067
- var LOCK_RETRY_BASE_MS = 5;
1068
- var LOCK_STALE_MS = 5e3;
1069
- function queuePath() {
1070
- return join4(homedir3(), ".deeplake", "notifications-queue.json");
1071
- }
1072
- function lockPath() {
1073
- return `${queuePath()}.lock`;
1074
- }
1075
- function readQueue() {
1076
- try {
1077
- const raw = readFileSync3(queuePath(), "utf-8");
1078
- const parsed = JSON.parse(raw);
1079
- if (!parsed || !Array.isArray(parsed.queue)) {
1080
- log3(`queue malformed \u2192 treating as empty`);
1081
- return { queue: [] };
1082
- }
1083
- return { queue: parsed.queue };
1084
- } catch {
1085
- return { queue: [] };
1086
- }
1087
- }
1088
- function _isQueuePathInsideHome(path, home) {
1089
- const r = resolve(path);
1090
- const h = resolve(home);
1091
- return r.startsWith(h + "/") || r === h;
1092
- }
1093
- function writeQueue(q) {
1094
- const path = queuePath();
1095
- const home = resolve(homedir3());
1096
- if (!_isQueuePathInsideHome(path, home)) {
1097
- throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
1098
- }
1099
- mkdirSync2(join4(home, ".deeplake"), { recursive: true, mode: 448 });
1100
- const tmp = `${path}.${process.pid}.tmp`;
1101
- writeFileSync2(tmp, JSON.stringify(q, null, 2), { mode: 384 });
1102
- renameSync(tmp, path);
1103
- }
1104
- async function withQueueLock(fn) {
1105
- const path = lockPath();
1106
- mkdirSync2(join4(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
1107
- let fd = null;
1108
- for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
1109
- try {
1110
- fd = openSync(path, "wx", 384);
1111
- break;
1112
- } catch (e) {
1113
- const code = e.code;
1114
- if (code !== "EEXIST")
1115
- throw e;
1116
- try {
1117
- const age = Date.now() - statSync(path).mtimeMs;
1118
- if (age > LOCK_STALE_MS) {
1119
- unlinkSync(path);
1120
- continue;
1121
- }
1122
- } catch {
1123
- }
1124
- const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
1125
- await sleep2(delay);
1126
- }
1127
- }
1128
- if (fd === null) {
1129
- log3(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
1130
- return fn();
1131
- }
1132
- try {
1133
- return fn();
1134
- } finally {
1135
- try {
1136
- closeSync(fd);
1137
- } catch {
1138
- }
1139
- try {
1140
- unlinkSync(path);
1141
- } catch {
1142
- }
1143
- }
1144
- }
1145
- function sameDedupKey(a, b) {
1146
- if (a.id !== b.id)
1147
- return false;
1148
- return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
1149
- }
1150
- async function enqueueNotification(n) {
1151
- await withQueueLock(() => {
1152
- const q = readQueue();
1153
- if (q.queue.some((existing) => sameDedupKey(existing, n))) {
1154
- return;
1155
- }
1156
- q.queue.push(n);
1157
- writeQueue(q);
1158
- });
1159
- }
1160
-
1161
- // dist/src/embeddings/disable.js
1162
- import { createRequire } from "node:module";
1163
- import { homedir as homedir5 } from "node:os";
1164
- import { join as join6 } from "node:path";
1165
- import { pathToFileURL } from "node:url";
1166
-
1167
- // dist/src/user-config.js
1168
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
1169
- import { homedir as homedir4 } from "node:os";
1170
- import { dirname, join as join5 } from "node:path";
1171
- var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join5(homedir4(), ".deeplake", "config.json");
1172
- var _cache = null;
1173
- var _migrated = false;
1174
- function readUserConfig() {
1175
- if (_cache !== null)
1176
- return _cache;
1177
- const path = _configPath();
1178
- if (!existsSync3(path)) {
1179
- _cache = {};
1180
- return _cache;
1181
- }
1182
- try {
1183
- const raw = readFileSync4(path, "utf-8");
1184
- const parsed = JSON.parse(raw);
1185
- _cache = isPlainObject(parsed) ? parsed : {};
1186
- } catch {
1187
- _cache = {};
1188
- }
1189
- return _cache;
1190
- }
1191
- function writeUserConfig(patch) {
1192
- const current = readUserConfig();
1193
- const merged = deepMerge(current, patch);
1194
- const path = _configPath();
1195
- const dir = dirname(path);
1196
- if (!existsSync3(dir))
1197
- mkdirSync3(dir, { recursive: true });
1198
- const tmp = `${path}.tmp.${process.pid}`;
1199
- writeFileSync3(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
1200
- renameSync2(tmp, path);
1201
- _cache = merged;
1202
- return merged;
1203
- }
1204
- function getEmbeddingsEnabled() {
1205
- const cfg = readUserConfig();
1206
- if (cfg.embeddings && typeof cfg.embeddings.enabled === "boolean") {
1207
- return cfg.embeddings.enabled;
1208
- }
1209
- if (_migrated) {
1210
- return migrationValueFromEnv();
1211
- }
1212
- _migrated = true;
1213
- const enabled = migrationValueFromEnv();
1214
- try {
1215
- writeUserConfig({ embeddings: { enabled } });
1216
- } catch {
1217
- _cache = { ...cfg ?? {}, embeddings: { ...cfg?.embeddings ?? {}, enabled } };
1218
- }
1219
- return enabled;
1220
- }
1221
- function migrationValueFromEnv() {
1222
- const raw = process.env.HIVEMIND_EMBEDDINGS;
1223
- if (raw === void 0)
1224
- return false;
1225
- if (raw === "false")
1226
- return false;
1227
- return true;
1228
- }
1229
- function isPlainObject(value) {
1230
- return typeof value === "object" && value !== null && !Array.isArray(value);
1231
- }
1232
- function deepMerge(base, patch) {
1233
- const out = { ...base };
1234
- for (const key of Object.keys(patch)) {
1235
- const patchVal = patch[key];
1236
- const baseVal = base[key];
1237
- if (isPlainObject(patchVal) && isPlainObject(baseVal)) {
1238
- out[key] = { ...baseVal, ...patchVal };
1239
- } else if (patchVal !== void 0) {
1240
- out[key] = patchVal;
1241
- }
1242
- }
1243
- return out;
1244
- }
1245
-
1246
- // dist/src/embeddings/disable.js
1247
- var cachedStatus = null;
1248
- function defaultResolveTransformers() {
1249
- const sharedDir = join6(homedir5(), ".hivemind", "embed-deps");
1250
- try {
1251
- createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1252
- return;
1253
- } catch {
1254
- }
1255
- createRequire(import.meta.url).resolve("@huggingface/transformers");
1256
- }
1257
- var _resolve = defaultResolveTransformers;
1258
- var _readEnabled = getEmbeddingsEnabled;
1259
- function detectStatus() {
1260
- if (!_readEnabled())
1261
- return "user-disabled";
1262
- try {
1263
- _resolve();
1264
- return "enabled";
1265
- } catch {
1266
- return "no-transformers";
1267
- }
1268
- }
1269
- function embeddingsStatus() {
1270
- if (cachedStatus !== null)
1271
- return cachedStatus;
1272
- cachedStatus = detectStatus();
1273
- return cachedStatus;
1274
- }
1275
- function embeddingsDisabled() {
1276
- return embeddingsStatus() !== "enabled";
1277
- }
1278
-
1279
1211
  // dist/src/embeddings/client.js
1280
- var SHARED_DAEMON_PATH = join7(homedir6(), ".hivemind", "embed-deps", "embed-daemon.js");
1212
+ var SHARED_DAEMON_PATH = join6(homedir5(), ".hivemind", "embed-deps", "embed-daemon.js");
1281
1213
  var log4 = (m) => log("embed-client", m);
1282
1214
  function getUid() {
1283
1215
  const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
1284
1216
  return uid !== void 0 ? String(uid) : process.env.USER ?? "default";
1285
1217
  }
1286
- var _signalledMissingDeps = false;
1287
1218
  var _recycledStuckDaemon = false;
1288
1219
  var EmbedClient = class {
1289
1220
  socketPath;
@@ -1300,7 +1231,7 @@ var EmbedClient = class {
1300
1231
  this.socketPath = socketPathFor(uid, dir);
1301
1232
  this.pidPath = pidPathFor(uid, dir);
1302
1233
  this.timeoutMs = opts.timeoutMs ?? DEFAULT_CLIENT_TIMEOUT_MS;
1303
- this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync4(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
1234
+ this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync3(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
1304
1235
  this.autoSpawn = opts.autoSpawn ?? true;
1305
1236
  this.spawnWaitMs = opts.spawnWaitMs ?? 5e3;
1306
1237
  }
@@ -1381,7 +1312,7 @@ var EmbedClient = class {
1381
1312
  async waitForDaemonReady() {
1382
1313
  const deadline = Date.now() + this.spawnWaitMs;
1383
1314
  while (Date.now() < deadline) {
1384
- if (existsSync4(this.socketPath))
1315
+ if (existsSync3(this.socketPath))
1385
1316
  return;
1386
1317
  await new Promise((r) => setTimeout(r, 50));
1387
1318
  }
@@ -1424,7 +1355,7 @@ var EmbedClient = class {
1424
1355
  this.recycleDaemon(hello.pid);
1425
1356
  return true;
1426
1357
  }
1427
- if (hello.daemonPath !== this.daemonEntry && !existsSync4(hello.daemonPath)) {
1358
+ if (hello.daemonPath !== this.daemonEntry && !existsSync3(hello.daemonPath)) {
1428
1359
  _recycledStuckDaemon = true;
1429
1360
  log4(`daemon path no longer on disk \u2014 running=${hello.daemonPath} (gone) expected=${this.daemonEntry}; recycling`);
1430
1361
  this.recycleDaemon(hello.pid);
@@ -1436,37 +1367,21 @@ var EmbedClient = class {
1436
1367
  /**
1437
1368
  * On a transformers-missing error from the daemon, SIGTERM the stuck
1438
1369
  * daemon (the bundle daemon that can't find its deps) and clear
1439
- * sock/pid so the next call spawns fresh. Also enqueue a one-time
1440
- * notification telling the user to run `hivemind embeddings install`
1441
- * but only when the user has opted in. Suppressed when
1442
- * embeddingsStatus() === "user-disabled" so we don't nag users who
1443
- * explicitly chose to turn embeddings off.
1370
+ * sock/pid so the next call spawns fresh.
1371
+ *
1372
+ * Previously this also enqueued a user-visible "Hivemind embeddings
1373
+ * disabled deps missing" notification telling the user to run
1374
+ * `hivemind embeddings install`. The notification was removed because
1375
+ * (a) the recycle alone often fixes the issue silently, and (b) the
1376
+ * warning kept stacking on top of the primary session-start banner
1377
+ * which clashed with the single-slot priority model. The `detail`
1378
+ * argument is retained for future telemetry / debug logging.
1444
1379
  */
1445
- handleTransformersMissing(detail) {
1380
+ handleTransformersMissing(_detail) {
1446
1381
  if (!_recycledStuckDaemon) {
1447
1382
  _recycledStuckDaemon = true;
1448
1383
  this.recycleDaemon(null);
1449
1384
  }
1450
- if (_signalledMissingDeps)
1451
- return;
1452
- _signalledMissingDeps = true;
1453
- let status;
1454
- try {
1455
- status = embeddingsStatus();
1456
- } catch {
1457
- status = "enabled";
1458
- }
1459
- if (status === "user-disabled")
1460
- return;
1461
- enqueueNotification({
1462
- id: "embed-deps-missing",
1463
- severity: "warn",
1464
- title: "Hivemind embeddings disabled \u2014 deps missing",
1465
- body: `Semantic memory search is off because @huggingface/transformers is not installed where the daemon can find it. Run \`hivemind embeddings install\` to enable.`,
1466
- dedupKey: { reason: "transformers-missing", detail: detail.slice(0, 200) }
1467
- }).catch((e) => {
1468
- log4(`enqueue embed-deps-missing failed: ${e instanceof Error ? e.message : String(e)}`);
1469
- });
1470
1385
  }
1471
1386
  /**
1472
1387
  * Best-effort SIGTERM + sock/pid cleanup. Tolerant of every missing-file
@@ -1489,7 +1404,7 @@ var EmbedClient = class {
1489
1404
  } catch {
1490
1405
  }
1491
1406
  }
1492
- if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync4(this.socketPath)) {
1407
+ if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync3(this.socketPath)) {
1493
1408
  try {
1494
1409
  process.kill(pid, "SIGTERM");
1495
1410
  } catch {
@@ -1498,11 +1413,11 @@ var EmbedClient = class {
1498
1413
  log4(`recycle: socket gone, skipping SIGTERM on possibly-stale pid ${pid}`);
1499
1414
  }
1500
1415
  try {
1501
- unlinkSync2(this.socketPath);
1416
+ unlinkSync3(this.socketPath);
1502
1417
  } catch {
1503
1418
  }
1504
1419
  try {
1505
- unlinkSync2(this.pidPath);
1420
+ unlinkSync3(this.pidPath);
1506
1421
  } catch {
1507
1422
  }
1508
1423
  }
@@ -1553,7 +1468,7 @@ var EmbedClient = class {
1553
1468
  } catch (e) {
1554
1469
  if (this.isPidFileStale()) {
1555
1470
  try {
1556
- unlinkSync2(this.pidPath);
1471
+ unlinkSync3(this.pidPath);
1557
1472
  } catch {
1558
1473
  }
1559
1474
  try {
@@ -1566,11 +1481,11 @@ var EmbedClient = class {
1566
1481
  return;
1567
1482
  }
1568
1483
  }
1569
- if (!this.daemonEntry || !existsSync4(this.daemonEntry)) {
1484
+ if (!this.daemonEntry || !existsSync3(this.daemonEntry)) {
1570
1485
  log4(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1571
1486
  try {
1572
1487
  closeSync2(fd);
1573
- unlinkSync2(this.pidPath);
1488
+ unlinkSync3(this.pidPath);
1574
1489
  } catch {
1575
1490
  }
1576
1491
  return;
@@ -1609,7 +1524,7 @@ var EmbedClient = class {
1609
1524
  while (Date.now() < deadline) {
1610
1525
  await sleep3(delay);
1611
1526
  delay = Math.min(delay * 1.5, 300);
1612
- if (!existsSync4(this.socketPath))
1527
+ if (!existsSync3(this.socketPath))
1613
1528
  continue;
1614
1529
  try {
1615
1530
  return await this.connectOnce();
@@ -1660,13 +1575,131 @@ function isTransformersMissingError(err) {
1660
1575
  return /@huggingface\/transformers/i.test(err);
1661
1576
  }
1662
1577
 
1578
+ // dist/src/embeddings/disable.js
1579
+ import { createRequire } from "node:module";
1580
+ import { homedir as homedir7 } from "node:os";
1581
+ import { join as join8 } from "node:path";
1582
+ import { pathToFileURL } from "node:url";
1583
+
1584
+ // dist/src/user-config.js
1585
+ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
1586
+ import { homedir as homedir6 } from "node:os";
1587
+ import { dirname, join as join7 } from "node:path";
1588
+ var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join7(homedir6(), ".deeplake", "config.json");
1589
+ var _cache = null;
1590
+ var _migrated = false;
1591
+ function readUserConfig() {
1592
+ if (_cache !== null)
1593
+ return _cache;
1594
+ const path = _configPath();
1595
+ if (!existsSync4(path)) {
1596
+ _cache = {};
1597
+ return _cache;
1598
+ }
1599
+ try {
1600
+ const raw = readFileSync6(path, "utf-8");
1601
+ const parsed = JSON.parse(raw);
1602
+ _cache = isPlainObject(parsed) ? parsed : {};
1603
+ } catch {
1604
+ _cache = {};
1605
+ }
1606
+ return _cache;
1607
+ }
1608
+ function writeUserConfig(patch) {
1609
+ const current = readUserConfig();
1610
+ const merged = deepMerge(current, patch);
1611
+ const path = _configPath();
1612
+ const dir = dirname(path);
1613
+ if (!existsSync4(dir))
1614
+ mkdirSync4(dir, { recursive: true });
1615
+ const tmp = `${path}.tmp.${process.pid}`;
1616
+ writeFileSync4(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
1617
+ renameSync2(tmp, path);
1618
+ _cache = merged;
1619
+ return merged;
1620
+ }
1621
+ function getEmbeddingsEnabled() {
1622
+ const cfg = readUserConfig();
1623
+ if (cfg.embeddings && typeof cfg.embeddings.enabled === "boolean") {
1624
+ return cfg.embeddings.enabled;
1625
+ }
1626
+ if (_migrated) {
1627
+ return migrationValueFromEnv();
1628
+ }
1629
+ _migrated = true;
1630
+ const enabled = migrationValueFromEnv();
1631
+ try {
1632
+ writeUserConfig({ embeddings: { enabled } });
1633
+ } catch {
1634
+ _cache = { ...cfg ?? {}, embeddings: { ...cfg?.embeddings ?? {}, enabled } };
1635
+ }
1636
+ return enabled;
1637
+ }
1638
+ function migrationValueFromEnv() {
1639
+ const raw = process.env.HIVEMIND_EMBEDDINGS;
1640
+ if (raw === void 0)
1641
+ return false;
1642
+ if (raw === "false")
1643
+ return false;
1644
+ return true;
1645
+ }
1646
+ function isPlainObject(value) {
1647
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1648
+ }
1649
+ function deepMerge(base, patch) {
1650
+ const out = { ...base };
1651
+ for (const key of Object.keys(patch)) {
1652
+ const patchVal = patch[key];
1653
+ const baseVal = base[key];
1654
+ if (isPlainObject(patchVal) && isPlainObject(baseVal)) {
1655
+ out[key] = { ...baseVal, ...patchVal };
1656
+ } else if (patchVal !== void 0) {
1657
+ out[key] = patchVal;
1658
+ }
1659
+ }
1660
+ return out;
1661
+ }
1662
+
1663
+ // dist/src/embeddings/disable.js
1664
+ var cachedStatus = null;
1665
+ function defaultResolveTransformers() {
1666
+ const sharedDir = join8(homedir7(), ".hivemind", "embed-deps");
1667
+ try {
1668
+ createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1669
+ return;
1670
+ } catch {
1671
+ }
1672
+ createRequire(import.meta.url).resolve("@huggingface/transformers");
1673
+ }
1674
+ var _resolve = defaultResolveTransformers;
1675
+ var _readEnabled = getEmbeddingsEnabled;
1676
+ function detectStatus() {
1677
+ if (!_readEnabled())
1678
+ return "user-disabled";
1679
+ try {
1680
+ _resolve();
1681
+ return "enabled";
1682
+ } catch {
1683
+ return "no-transformers";
1684
+ }
1685
+ }
1686
+ function embeddingsStatus() {
1687
+ if (cachedStatus !== null)
1688
+ return cachedStatus;
1689
+ cachedStatus = detectStatus();
1690
+ return cachedStatus;
1691
+ }
1692
+ function embeddingsDisabled() {
1693
+ return embeddingsStatus() !== "enabled";
1694
+ }
1695
+
1663
1696
  // dist/src/hooks/grep-direct.js
1664
1697
  import { fileURLToPath } from "node:url";
1665
- import { dirname as dirname2, join as join8 } from "node:path";
1698
+ import { dirname as dirname2, join as join9 } from "node:path";
1666
1699
  var SEMANTIC_ENABLED = process.env.HIVEMIND_SEMANTIC_SEARCH !== "false" && !embeddingsDisabled();
1667
1700
  var SEMANTIC_TIMEOUT_MS = Number(process.env.HIVEMIND_SEMANTIC_EMBED_TIMEOUT_MS ?? "500");
1668
1701
  function resolveDaemonPath() {
1669
- return join8(dirname2(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
1702
+ return join9(dirname2(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
1670
1703
  }
1671
1704
  var sharedEmbedClient = null;
1672
1705
  function getEmbedClient() {
@@ -2019,9 +2052,9 @@ async function handleGrepDirect(api, table, sessionsTable, params) {
2019
2052
  }
2020
2053
 
2021
2054
  // dist/src/hooks/memory-path-utils.js
2022
- import { homedir as homedir7 } from "node:os";
2023
- import { join as join9 } from "node:path";
2024
- var MEMORY_PATH = join9(homedir7(), ".deeplake", "memory");
2055
+ import { homedir as homedir8 } from "node:os";
2056
+ import { join as join10 } from "node:path";
2057
+ var MEMORY_PATH = join10(homedir8(), ".deeplake", "memory");
2025
2058
  var TILDE_PATH = "~/.deeplake/memory";
2026
2059
  var HOME_VAR_PATH = "$HOME/.deeplake/memory";
2027
2060
  function touchesMemory(p) {