@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.
@@ -17,21 +17,21 @@ __export(index_marker_store_exports, {
17
17
  hasFreshIndexMarker: () => hasFreshIndexMarker,
18
18
  writeIndexMarker: () => writeIndexMarker
19
19
  });
20
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
21
- import { join as join3 } from "node:path";
20
+ import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
21
+ import { join as join5 } from "node:path";
22
22
  import { tmpdir } from "node:os";
23
23
  function getIndexMarkerDir() {
24
- return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join3(tmpdir(), "hivemind-deeplake-indexes");
24
+ return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join5(tmpdir(), "hivemind-deeplake-indexes");
25
25
  }
26
26
  function buildIndexMarkerPath(workspaceId, orgId, table, suffix) {
27
27
  const markerKey = [workspaceId, orgId, table, suffix].join("__").replace(/[^a-zA-Z0-9_.-]/g, "_");
28
- return join3(getIndexMarkerDir(), `${markerKey}.json`);
28
+ return join5(getIndexMarkerDir(), `${markerKey}.json`);
29
29
  }
30
30
  function hasFreshIndexMarker(markerPath) {
31
31
  if (!existsSync2(markerPath))
32
32
  return false;
33
33
  try {
34
- const raw = JSON.parse(readFileSync2(markerPath, "utf-8"));
34
+ const raw = JSON.parse(readFileSync4(markerPath, "utf-8"));
35
35
  const updatedAt = raw.updatedAt ? new Date(raw.updatedAt).getTime() : NaN;
36
36
  if (!Number.isFinite(updatedAt) || Date.now() - updatedAt > INDEX_MARKER_TTL_MS)
37
37
  return false;
@@ -41,8 +41,8 @@ function hasFreshIndexMarker(markerPath) {
41
41
  }
42
42
  }
43
43
  function writeIndexMarker(markerPath) {
44
- mkdirSync(getIndexMarkerDir(), { recursive: true });
45
- writeFileSync(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
44
+ mkdirSync3(getIndexMarkerDir(), { recursive: true });
45
+ writeFileSync3(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
46
46
  }
47
47
  var INDEX_MARKER_TTL_MS;
48
48
  var init_index_marker_store = __esm({
@@ -55,7 +55,7 @@ var init_index_marker_store = __esm({
55
55
  // dist/src/hooks/codex/pre-tool-use.js
56
56
  import { execFileSync } from "node:child_process";
57
57
  import { existsSync as existsSync5 } from "node:fs";
58
- import { join as join11, dirname as dirname3 } from "node:path";
58
+ import { join as join12, dirname as dirname3 } from "node:path";
59
59
  import { fileURLToPath as fileURLToPath3 } from "node:url";
60
60
 
61
61
  // dist/src/utils/stdin.js
@@ -153,6 +153,125 @@ function deeplakeClientHeader() {
153
153
  return { [DEEPLAKE_CLIENT_HEADER]: deeplakeClientValue() };
154
154
  }
155
155
 
156
+ // dist/src/notifications/queue.js
157
+ import { readFileSync as readFileSync2, writeFileSync, renameSync, mkdirSync, openSync, closeSync, unlinkSync, statSync } from "node:fs";
158
+ import { join as join3, resolve } from "node:path";
159
+ import { homedir as homedir3 } from "node:os";
160
+ import { setTimeout as sleep } from "node:timers/promises";
161
+ var log2 = (msg) => log("notifications-queue", msg);
162
+ var LOCK_RETRY_MAX = 50;
163
+ var LOCK_RETRY_BASE_MS = 5;
164
+ var LOCK_STALE_MS = 5e3;
165
+ function queuePath() {
166
+ return join3(homedir3(), ".deeplake", "notifications-queue.json");
167
+ }
168
+ function lockPath() {
169
+ return `${queuePath()}.lock`;
170
+ }
171
+ function readQueue() {
172
+ try {
173
+ const raw = readFileSync2(queuePath(), "utf-8");
174
+ const parsed = JSON.parse(raw);
175
+ if (!parsed || !Array.isArray(parsed.queue)) {
176
+ log2(`queue malformed \u2192 treating as empty`);
177
+ return { queue: [] };
178
+ }
179
+ return { queue: parsed.queue };
180
+ } catch {
181
+ return { queue: [] };
182
+ }
183
+ }
184
+ function _isQueuePathInsideHome(path, home) {
185
+ const r = resolve(path);
186
+ const h = resolve(home);
187
+ return r.startsWith(h + "/") || r === h;
188
+ }
189
+ function writeQueue(q) {
190
+ const path = queuePath();
191
+ const home = resolve(homedir3());
192
+ if (!_isQueuePathInsideHome(path, home)) {
193
+ throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
194
+ }
195
+ mkdirSync(join3(home, ".deeplake"), { recursive: true, mode: 448 });
196
+ const tmp = `${path}.${process.pid}.tmp`;
197
+ writeFileSync(tmp, JSON.stringify(q, null, 2), { mode: 384 });
198
+ renameSync(tmp, path);
199
+ }
200
+ async function withQueueLock(fn) {
201
+ const path = lockPath();
202
+ mkdirSync(join3(homedir3(), ".deeplake"), { recursive: true, mode: 448 });
203
+ let fd = null;
204
+ for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
205
+ try {
206
+ fd = openSync(path, "wx", 384);
207
+ break;
208
+ } catch (e) {
209
+ const code = e.code;
210
+ if (code !== "EEXIST")
211
+ throw e;
212
+ try {
213
+ const age = Date.now() - statSync(path).mtimeMs;
214
+ if (age > LOCK_STALE_MS) {
215
+ unlinkSync(path);
216
+ continue;
217
+ }
218
+ } catch {
219
+ }
220
+ const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
221
+ await sleep(delay);
222
+ }
223
+ }
224
+ if (fd === null) {
225
+ log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
226
+ return fn();
227
+ }
228
+ try {
229
+ return fn();
230
+ } finally {
231
+ try {
232
+ closeSync(fd);
233
+ } catch {
234
+ }
235
+ try {
236
+ unlinkSync(path);
237
+ } catch {
238
+ }
239
+ }
240
+ }
241
+ function sameDedupKey(a, b) {
242
+ if (a.id !== b.id)
243
+ return false;
244
+ return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
245
+ }
246
+ async function enqueueNotification(n) {
247
+ await withQueueLock(() => {
248
+ const q = readQueue();
249
+ if (q.queue.some((existing) => sameDedupKey(existing, n))) {
250
+ return;
251
+ }
252
+ q.queue.push(n);
253
+ writeQueue(q);
254
+ });
255
+ }
256
+
257
+ // dist/src/commands/auth-creds.js
258
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2 } from "node:fs";
259
+ import { join as join4 } from "node:path";
260
+ import { homedir as homedir4 } from "node:os";
261
+ function configDir() {
262
+ return join4(homedir4(), ".deeplake");
263
+ }
264
+ function credsPath() {
265
+ return join4(configDir(), "credentials.json");
266
+ }
267
+ function loadCredentials() {
268
+ try {
269
+ return JSON.parse(readFileSync3(credsPath(), "utf-8"));
270
+ } catch {
271
+ return null;
272
+ }
273
+ }
274
+
156
275
  // dist/src/deeplake-api.js
157
276
  var indexMarkerStorePromise = null;
158
277
  function getIndexMarkerStore() {
@@ -160,7 +279,7 @@ function getIndexMarkerStore() {
160
279
  indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
161
280
  return indexMarkerStorePromise;
162
281
  }
163
- var log2 = (msg) => log("sdk", msg);
282
+ var log3 = (msg) => log("sdk", msg);
164
283
  function summarizeSql(sql, maxLen = 220) {
165
284
  const compact = sql.replace(/\s+/g, " ").trim();
166
285
  return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
@@ -172,7 +291,38 @@ function traceSql(msg) {
172
291
  process.stderr.write(`[deeplake-sql] ${msg}
173
292
  `);
174
293
  if (process.env.HIVEMIND_DEBUG === "1")
175
- log2(msg);
294
+ log3(msg);
295
+ }
296
+ var _signalledBalanceExhausted = false;
297
+ function maybeSignalBalanceExhausted(status, bodyText) {
298
+ if (status !== 402)
299
+ return;
300
+ if (!bodyText.includes("balance_cents"))
301
+ return;
302
+ if (_signalledBalanceExhausted)
303
+ return;
304
+ _signalledBalanceExhausted = true;
305
+ log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
306
+ enqueueNotification({
307
+ id: "balance-exhausted",
308
+ severity: "warn",
309
+ transient: true,
310
+ title: "Hivemind credits exhausted \u2014 top up to keep capturing",
311
+ body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
312
+ dedupKey: { reason: "balance-zero" }
313
+ }).catch((e) => {
314
+ log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
315
+ });
316
+ }
317
+ function billingUrl() {
318
+ try {
319
+ const c = loadCredentials();
320
+ if (c?.orgName && c?.workspaceId) {
321
+ return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
322
+ }
323
+ } catch {
324
+ }
325
+ return "https://deeplake.ai";
176
326
  }
177
327
  var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
178
328
  var MAX_RETRIES = 3;
@@ -181,7 +331,7 @@ var MAX_CONCURRENCY = 5;
181
331
  function getQueryTimeoutMs() {
182
332
  return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
183
333
  }
184
- function sleep(ms) {
334
+ function sleep2(ms) {
185
335
  return new Promise((resolve3) => setTimeout(resolve3, ms));
186
336
  }
187
337
  function isTimeoutError(error) {
@@ -283,8 +433,8 @@ var DeeplakeApi = class {
283
433
  lastError = e instanceof Error ? e : new Error(String(e));
284
434
  if (attempt < MAX_RETRIES) {
285
435
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
286
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
287
- await sleep(delay);
436
+ log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
437
+ await sleep2(delay);
288
438
  continue;
289
439
  }
290
440
  throw lastError;
@@ -300,10 +450,11 @@ var DeeplakeApi = class {
300
450
  const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
301
451
  if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
302
452
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
303
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
304
- await sleep(delay);
453
+ log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
454
+ await sleep2(delay);
305
455
  continue;
306
456
  }
457
+ maybeSignalBalanceExhausted(resp.status, text);
307
458
  throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
308
459
  }
309
460
  throw lastError ?? new Error("Query failed: max retries exceeded");
@@ -324,7 +475,7 @@ var DeeplakeApi = class {
324
475
  const chunk = rows.slice(i, i + CONCURRENCY);
325
476
  await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
326
477
  }
327
- log2(`commit: ${rows.length} rows`);
478
+ log3(`commit: ${rows.length} rows`);
328
479
  }
329
480
  async upsertRowSql(row) {
330
481
  const ts = (/* @__PURE__ */ new Date()).toISOString();
@@ -380,7 +531,7 @@ var DeeplakeApi = class {
380
531
  markers.writeIndexMarker(markerPath);
381
532
  return;
382
533
  }
383
- log2(`index "${indexName}" skipped: ${e.message}`);
534
+ log3(`index "${indexName}" skipped: ${e.message}`);
384
535
  }
385
536
  }
386
537
  /**
@@ -470,13 +621,13 @@ var DeeplakeApi = class {
470
621
  };
471
622
  }
472
623
  if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
473
- await sleep(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
624
+ await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
474
625
  continue;
475
626
  }
476
627
  return { tables: [], cacheable: false };
477
628
  } catch {
478
629
  if (attempt < MAX_RETRIES) {
479
- await sleep(BASE_DELAY_MS * Math.pow(2, attempt));
630
+ await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
480
631
  continue;
481
632
  }
482
633
  return { tables: [], cacheable: false };
@@ -504,9 +655,9 @@ var DeeplakeApi = class {
504
655
  } catch (err) {
505
656
  lastErr = err;
506
657
  const msg = err instanceof Error ? err.message : String(err);
507
- log2(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
658
+ log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
508
659
  if (attempt < OUTER_BACKOFFS_MS.length) {
509
- await sleep(OUTER_BACKOFFS_MS[attempt]);
660
+ await sleep2(OUTER_BACKOFFS_MS[attempt]);
510
661
  }
511
662
  }
512
663
  }
@@ -517,9 +668,9 @@ var DeeplakeApi = class {
517
668
  const tbl = sqlIdent(name ?? this.tableName);
518
669
  const tables = await this.listTables();
519
670
  if (!tables.includes(tbl)) {
520
- log2(`table "${tbl}" not found, creating`);
671
+ log3(`table "${tbl}" not found, creating`);
521
672
  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);
522
- log2(`table "${tbl}" created`);
673
+ log3(`table "${tbl}" created`);
523
674
  if (!tables.includes(tbl))
524
675
  this._tablesCache = [...tables, tbl];
525
676
  }
@@ -532,9 +683,9 @@ var DeeplakeApi = class {
532
683
  const safe = sqlIdent(name);
533
684
  const tables = await this.listTables();
534
685
  if (!tables.includes(safe)) {
535
- log2(`table "${safe}" not found, creating`);
686
+ log3(`table "${safe}" not found, creating`);
536
687
  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);
537
- log2(`table "${safe}" created`);
688
+ log3(`table "${safe}" created`);
538
689
  if (!tables.includes(safe))
539
690
  this._tablesCache = [...tables, safe];
540
691
  }
@@ -557,9 +708,9 @@ var DeeplakeApi = class {
557
708
  const safe = sqlIdent(name);
558
709
  const tables = await this.listTables();
559
710
  if (!tables.includes(safe)) {
560
- log2(`table "${safe}" not found, creating`);
711
+ log3(`table "${safe}" not found, creating`);
561
712
  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);
562
- log2(`table "${safe}" created`);
713
+ log3(`table "${safe}" created`);
563
714
  if (!tables.includes(safe))
564
715
  this._tablesCache = [...tables, safe];
565
716
  }
@@ -1049,9 +1200,9 @@ function capOutputForClaude(output, options = {}) {
1049
1200
  // dist/src/embeddings/client.js
1050
1201
  import { connect } from "node:net";
1051
1202
  import { spawn } from "node:child_process";
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";
1203
+ import { openSync as openSync2, closeSync as closeSync2, writeSync, unlinkSync as unlinkSync3, existsSync as existsSync3, readFileSync as readFileSync5 } from "node:fs";
1204
+ import { homedir as homedir5 } from "node:os";
1205
+ import { join as join6 } from "node:path";
1055
1206
 
1056
1207
  // dist/src/embeddings/protocol.js
1057
1208
  var DEFAULT_SOCKET_DIR = "/tmp";
@@ -1064,233 +1215,13 @@ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
1064
1215
  return `${dir}/hivemind-embed-${uid}.pid`;
1065
1216
  }
1066
1217
 
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
-
1286
1218
  // dist/src/embeddings/client.js
1287
- var SHARED_DAEMON_PATH = join7(homedir6(), ".hivemind", "embed-deps", "embed-daemon.js");
1219
+ var SHARED_DAEMON_PATH = join6(homedir5(), ".hivemind", "embed-deps", "embed-daemon.js");
1288
1220
  var log4 = (m) => log("embed-client", m);
1289
1221
  function getUid() {
1290
1222
  const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
1291
1223
  return uid !== void 0 ? String(uid) : process.env.USER ?? "default";
1292
1224
  }
1293
- var _signalledMissingDeps = false;
1294
1225
  var _recycledStuckDaemon = false;
1295
1226
  var EmbedClient = class {
1296
1227
  socketPath;
@@ -1307,7 +1238,7 @@ var EmbedClient = class {
1307
1238
  this.socketPath = socketPathFor(uid, dir);
1308
1239
  this.pidPath = pidPathFor(uid, dir);
1309
1240
  this.timeoutMs = opts.timeoutMs ?? DEFAULT_CLIENT_TIMEOUT_MS;
1310
- this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync4(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
1241
+ this.daemonEntry = opts.daemonEntry ?? process.env.HIVEMIND_EMBED_DAEMON ?? (existsSync3(SHARED_DAEMON_PATH) ? SHARED_DAEMON_PATH : void 0);
1311
1242
  this.autoSpawn = opts.autoSpawn ?? true;
1312
1243
  this.spawnWaitMs = opts.spawnWaitMs ?? 5e3;
1313
1244
  }
@@ -1388,7 +1319,7 @@ var EmbedClient = class {
1388
1319
  async waitForDaemonReady() {
1389
1320
  const deadline = Date.now() + this.spawnWaitMs;
1390
1321
  while (Date.now() < deadline) {
1391
- if (existsSync4(this.socketPath))
1322
+ if (existsSync3(this.socketPath))
1392
1323
  return;
1393
1324
  await new Promise((r) => setTimeout(r, 50));
1394
1325
  }
@@ -1431,7 +1362,7 @@ var EmbedClient = class {
1431
1362
  this.recycleDaemon(hello.pid);
1432
1363
  return true;
1433
1364
  }
1434
- if (hello.daemonPath !== this.daemonEntry && !existsSync4(hello.daemonPath)) {
1365
+ if (hello.daemonPath !== this.daemonEntry && !existsSync3(hello.daemonPath)) {
1435
1366
  _recycledStuckDaemon = true;
1436
1367
  log4(`daemon path no longer on disk \u2014 running=${hello.daemonPath} (gone) expected=${this.daemonEntry}; recycling`);
1437
1368
  this.recycleDaemon(hello.pid);
@@ -1443,37 +1374,21 @@ var EmbedClient = class {
1443
1374
  /**
1444
1375
  * On a transformers-missing error from the daemon, SIGTERM the stuck
1445
1376
  * 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.
1377
+ * sock/pid so the next call spawns fresh.
1378
+ *
1379
+ * Previously this also enqueued a user-visible "Hivemind embeddings
1380
+ * disabled deps missing" notification telling the user to run
1381
+ * `hivemind embeddings install`. The notification was removed because
1382
+ * (a) the recycle alone often fixes the issue silently, and (b) the
1383
+ * warning kept stacking on top of the primary session-start banner
1384
+ * which clashed with the single-slot priority model. The `detail`
1385
+ * argument is retained for future telemetry / debug logging.
1451
1386
  */
1452
- handleTransformersMissing(detail) {
1387
+ handleTransformersMissing(_detail) {
1453
1388
  if (!_recycledStuckDaemon) {
1454
1389
  _recycledStuckDaemon = true;
1455
1390
  this.recycleDaemon(null);
1456
1391
  }
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
1392
  }
1478
1393
  /**
1479
1394
  * Best-effort SIGTERM + sock/pid cleanup. Tolerant of every missing-file
@@ -1496,7 +1411,7 @@ var EmbedClient = class {
1496
1411
  } catch {
1497
1412
  }
1498
1413
  }
1499
- if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync4(this.socketPath)) {
1414
+ if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync3(this.socketPath)) {
1500
1415
  try {
1501
1416
  process.kill(pid, "SIGTERM");
1502
1417
  } catch {
@@ -1505,11 +1420,11 @@ var EmbedClient = class {
1505
1420
  log4(`recycle: socket gone, skipping SIGTERM on possibly-stale pid ${pid}`);
1506
1421
  }
1507
1422
  try {
1508
- unlinkSync2(this.socketPath);
1423
+ unlinkSync3(this.socketPath);
1509
1424
  } catch {
1510
1425
  }
1511
1426
  try {
1512
- unlinkSync2(this.pidPath);
1427
+ unlinkSync3(this.pidPath);
1513
1428
  } catch {
1514
1429
  }
1515
1430
  }
@@ -1560,7 +1475,7 @@ var EmbedClient = class {
1560
1475
  } catch (e) {
1561
1476
  if (this.isPidFileStale()) {
1562
1477
  try {
1563
- unlinkSync2(this.pidPath);
1478
+ unlinkSync3(this.pidPath);
1564
1479
  } catch {
1565
1480
  }
1566
1481
  try {
@@ -1573,11 +1488,11 @@ var EmbedClient = class {
1573
1488
  return;
1574
1489
  }
1575
1490
  }
1576
- if (!this.daemonEntry || !existsSync4(this.daemonEntry)) {
1491
+ if (!this.daemonEntry || !existsSync3(this.daemonEntry)) {
1577
1492
  log4(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1578
1493
  try {
1579
1494
  closeSync2(fd);
1580
- unlinkSync2(this.pidPath);
1495
+ unlinkSync3(this.pidPath);
1581
1496
  } catch {
1582
1497
  }
1583
1498
  return;
@@ -1616,7 +1531,7 @@ var EmbedClient = class {
1616
1531
  while (Date.now() < deadline) {
1617
1532
  await sleep3(delay);
1618
1533
  delay = Math.min(delay * 1.5, 300);
1619
- if (!existsSync4(this.socketPath))
1534
+ if (!existsSync3(this.socketPath))
1620
1535
  continue;
1621
1536
  try {
1622
1537
  return await this.connectOnce();
@@ -1667,13 +1582,131 @@ function isTransformersMissingError(err) {
1667
1582
  return /@huggingface\/transformers/i.test(err);
1668
1583
  }
1669
1584
 
1585
+ // dist/src/embeddings/disable.js
1586
+ import { createRequire } from "node:module";
1587
+ import { homedir as homedir7 } from "node:os";
1588
+ import { join as join8 } from "node:path";
1589
+ import { pathToFileURL } from "node:url";
1590
+
1591
+ // dist/src/user-config.js
1592
+ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
1593
+ import { homedir as homedir6 } from "node:os";
1594
+ import { dirname, join as join7 } from "node:path";
1595
+ var _configPath = () => process.env.HIVEMIND_CONFIG_PATH ?? join7(homedir6(), ".deeplake", "config.json");
1596
+ var _cache = null;
1597
+ var _migrated = false;
1598
+ function readUserConfig() {
1599
+ if (_cache !== null)
1600
+ return _cache;
1601
+ const path = _configPath();
1602
+ if (!existsSync4(path)) {
1603
+ _cache = {};
1604
+ return _cache;
1605
+ }
1606
+ try {
1607
+ const raw = readFileSync6(path, "utf-8");
1608
+ const parsed = JSON.parse(raw);
1609
+ _cache = isPlainObject(parsed) ? parsed : {};
1610
+ } catch {
1611
+ _cache = {};
1612
+ }
1613
+ return _cache;
1614
+ }
1615
+ function writeUserConfig(patch) {
1616
+ const current = readUserConfig();
1617
+ const merged = deepMerge(current, patch);
1618
+ const path = _configPath();
1619
+ const dir = dirname(path);
1620
+ if (!existsSync4(dir))
1621
+ mkdirSync4(dir, { recursive: true });
1622
+ const tmp = `${path}.tmp.${process.pid}`;
1623
+ writeFileSync4(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
1624
+ renameSync2(tmp, path);
1625
+ _cache = merged;
1626
+ return merged;
1627
+ }
1628
+ function getEmbeddingsEnabled() {
1629
+ const cfg = readUserConfig();
1630
+ if (cfg.embeddings && typeof cfg.embeddings.enabled === "boolean") {
1631
+ return cfg.embeddings.enabled;
1632
+ }
1633
+ if (_migrated) {
1634
+ return migrationValueFromEnv();
1635
+ }
1636
+ _migrated = true;
1637
+ const enabled = migrationValueFromEnv();
1638
+ try {
1639
+ writeUserConfig({ embeddings: { enabled } });
1640
+ } catch {
1641
+ _cache = { ...cfg ?? {}, embeddings: { ...cfg?.embeddings ?? {}, enabled } };
1642
+ }
1643
+ return enabled;
1644
+ }
1645
+ function migrationValueFromEnv() {
1646
+ const raw = process.env.HIVEMIND_EMBEDDINGS;
1647
+ if (raw === void 0)
1648
+ return false;
1649
+ if (raw === "false")
1650
+ return false;
1651
+ return true;
1652
+ }
1653
+ function isPlainObject(value) {
1654
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1655
+ }
1656
+ function deepMerge(base, patch) {
1657
+ const out = { ...base };
1658
+ for (const key of Object.keys(patch)) {
1659
+ const patchVal = patch[key];
1660
+ const baseVal = base[key];
1661
+ if (isPlainObject(patchVal) && isPlainObject(baseVal)) {
1662
+ out[key] = { ...baseVal, ...patchVal };
1663
+ } else if (patchVal !== void 0) {
1664
+ out[key] = patchVal;
1665
+ }
1666
+ }
1667
+ return out;
1668
+ }
1669
+
1670
+ // dist/src/embeddings/disable.js
1671
+ var cachedStatus = null;
1672
+ function defaultResolveTransformers() {
1673
+ const sharedDir = join8(homedir7(), ".hivemind", "embed-deps");
1674
+ try {
1675
+ createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1676
+ return;
1677
+ } catch {
1678
+ }
1679
+ createRequire(import.meta.url).resolve("@huggingface/transformers");
1680
+ }
1681
+ var _resolve = defaultResolveTransformers;
1682
+ var _readEnabled = getEmbeddingsEnabled;
1683
+ function detectStatus() {
1684
+ if (!_readEnabled())
1685
+ return "user-disabled";
1686
+ try {
1687
+ _resolve();
1688
+ return "enabled";
1689
+ } catch {
1690
+ return "no-transformers";
1691
+ }
1692
+ }
1693
+ function embeddingsStatus() {
1694
+ if (cachedStatus !== null)
1695
+ return cachedStatus;
1696
+ cachedStatus = detectStatus();
1697
+ return cachedStatus;
1698
+ }
1699
+ function embeddingsDisabled() {
1700
+ return embeddingsStatus() !== "enabled";
1701
+ }
1702
+
1670
1703
  // dist/src/hooks/grep-direct.js
1671
1704
  import { fileURLToPath } from "node:url";
1672
- import { dirname as dirname2, join as join8 } from "node:path";
1705
+ import { dirname as dirname2, join as join9 } from "node:path";
1673
1706
  var SEMANTIC_ENABLED = process.env.HIVEMIND_SEMANTIC_SEARCH !== "false" && !embeddingsDisabled();
1674
1707
  var SEMANTIC_TIMEOUT_MS = Number(process.env.HIVEMIND_SEMANTIC_EMBED_TIMEOUT_MS ?? "500");
1675
1708
  function resolveDaemonPath() {
1676
- return join8(dirname2(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
1709
+ return join9(dirname2(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
1677
1710
  }
1678
1711
  var sharedEmbedClient = null;
1679
1712
  function getEmbedClient() {
@@ -2676,20 +2709,20 @@ async function executeCompiledBashCommand(api, memoryTable, sessionsTable, cmd,
2676
2709
  }
2677
2710
 
2678
2711
  // dist/src/hooks/query-cache.js
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";
2712
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync7, rmSync, writeFileSync as writeFileSync5 } from "node:fs";
2713
+ import { join as join10 } from "node:path";
2714
+ import { homedir as homedir8 } from "node:os";
2682
2715
  var log5 = (msg) => log("query-cache", msg);
2683
- var DEFAULT_CACHE_ROOT = join9(homedir7(), ".deeplake", "query-cache");
2716
+ var DEFAULT_CACHE_ROOT = join10(homedir8(), ".deeplake", "query-cache");
2684
2717
  var INDEX_CACHE_FILE = "index.md";
2685
2718
  function getSessionQueryCacheDir(sessionId, deps = {}) {
2686
2719
  const { cacheRoot = DEFAULT_CACHE_ROOT } = deps;
2687
- return join9(cacheRoot, sessionId);
2720
+ return join10(cacheRoot, sessionId);
2688
2721
  }
2689
2722
  function readCachedIndexContent(sessionId, deps = {}) {
2690
2723
  const { logFn = log5 } = deps;
2691
2724
  try {
2692
- return readFileSync6(join9(getSessionQueryCacheDir(sessionId, deps), INDEX_CACHE_FILE), "utf-8");
2725
+ return readFileSync7(join10(getSessionQueryCacheDir(sessionId, deps), INDEX_CACHE_FILE), "utf-8");
2693
2726
  } catch (e) {
2694
2727
  if (e?.code === "ENOENT")
2695
2728
  return null;
@@ -2701,8 +2734,8 @@ function writeCachedIndexContent(sessionId, content, deps = {}) {
2701
2734
  const { logFn = log5 } = deps;
2702
2735
  try {
2703
2736
  const dir = getSessionQueryCacheDir(sessionId, deps);
2704
- mkdirSync4(dir, { recursive: true });
2705
- writeFileSync4(join9(dir, INDEX_CACHE_FILE), content, "utf-8");
2737
+ mkdirSync5(dir, { recursive: true });
2738
+ writeFileSync5(join10(dir, INDEX_CACHE_FILE), content, "utf-8");
2706
2739
  } catch (e) {
2707
2740
  logFn(`write failed for session=${sessionId}: ${e.message}`);
2708
2741
  }
@@ -2723,9 +2756,9 @@ function isDirectRun(metaUrl) {
2723
2756
  }
2724
2757
 
2725
2758
  // dist/src/hooks/memory-path-utils.js
2726
- import { homedir as homedir8 } from "node:os";
2727
- import { join as join10 } from "node:path";
2728
- var MEMORY_PATH = join10(homedir8(), ".deeplake", "memory");
2759
+ import { homedir as homedir9 } from "node:os";
2760
+ import { join as join11 } from "node:path";
2761
+ var MEMORY_PATH = join11(homedir9(), ".deeplake", "memory");
2729
2762
  var TILDE_PATH = "~/.deeplake/memory";
2730
2763
  var HOME_VAR_PATH = "$HOME/.deeplake/memory";
2731
2764
  var SAFE_BUILTINS = /* @__PURE__ */ new Set([
@@ -2843,7 +2876,7 @@ function rewritePaths(cmd) {
2843
2876
  // dist/src/hooks/codex/pre-tool-use.js
2844
2877
  var log6 = (msg) => log("codex-pre", msg);
2845
2878
  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");
2879
+ var SHELL_BUNDLE = existsSync5(join12(__bundleDir, "shell", "deeplake-shell.js")) ? join12(__bundleDir, "shell", "deeplake-shell.js") : join12(__bundleDir, "..", "shell", "deeplake-shell.js");
2847
2880
  function buildUnsupportedGuidance() {
2848
2881
  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.";
2849
2882
  }