@deeplake/hivemind 0.7.31 → 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({
@@ -54,19 +54,19 @@ var init_index_marker_store = __esm({
54
54
 
55
55
  // dist/src/hooks/codex/pre-tool-use.js
56
56
  import { execFileSync } from "node:child_process";
57
- import { existsSync as existsSync4 } from "node:fs";
58
- import { join as join9, dirname as dirname2 } from "node:path";
57
+ import { existsSync as existsSync5 } from "node:fs";
58
+ import { join as 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
62
62
  function readStdin() {
63
- return new Promise((resolve2, reject) => {
63
+ return new Promise((resolve3, reject) => {
64
64
  let data = "";
65
65
  process.stdin.setEncoding("utf-8");
66
66
  process.stdin.on("data", (chunk) => data += chunk);
67
67
  process.stdin.on("end", () => {
68
68
  try {
69
- resolve2(JSON.parse(data));
69
+ resolve3(JSON.parse(data));
70
70
  } catch (err) {
71
71
  reject(new Error(`Failed to parse hook input: ${err}`));
72
72
  }
@@ -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,8 +331,8 @@ 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) {
185
- return new Promise((resolve2) => setTimeout(resolve2, ms));
334
+ function sleep2(ms) {
335
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
186
336
  }
187
337
  function isTimeoutError(error) {
188
338
  const name = error instanceof Error ? error.name.toLowerCase() : "";
@@ -212,7 +362,7 @@ var Semaphore = class {
212
362
  this.active++;
213
363
  return;
214
364
  }
215
- await new Promise((resolve2) => this.waiting.push(resolve2));
365
+ await new Promise((resolve3) => this.waiting.push(resolve3));
216
366
  }
217
367
  release() {
218
368
  this.active--;
@@ -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, closeSync, writeSync, unlinkSync, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
1053
- import { homedir as homedir3 } from "node:os";
1054
- import { join as join4 } from "node:path";
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";
@@ -1065,12 +1216,13 @@ function pidPathFor(uid, dir = DEFAULT_SOCKET_DIR) {
1065
1216
  }
1066
1217
 
1067
1218
  // dist/src/embeddings/client.js
1068
- var SHARED_DAEMON_PATH = join4(homedir3(), ".hivemind", "embed-deps", "embed-daemon.js");
1069
- var log3 = (m) => log("embed-client", m);
1219
+ var SHARED_DAEMON_PATH = join6(homedir5(), ".hivemind", "embed-deps", "embed-daemon.js");
1220
+ var log4 = (m) => log("embed-client", m);
1070
1221
  function getUid() {
1071
1222
  const uid = typeof process.getuid === "function" ? process.getuid() : void 0;
1072
1223
  return uid !== void 0 ? String(uid) : process.env.USER ?? "default";
1073
1224
  }
1225
+ var _recycledStuckDaemon = false;
1074
1226
  var EmbedClient = class {
1075
1227
  socketPath;
1076
1228
  pidPath;
@@ -1079,6 +1231,7 @@ var EmbedClient = class {
1079
1231
  autoSpawn;
1080
1232
  spawnWaitMs;
1081
1233
  nextId = 0;
1234
+ helloVerified = false;
1082
1235
  constructor(opts = {}) {
1083
1236
  const uid = getUid();
1084
1237
  const dir = opts.socketDir ?? "/tmp";
@@ -1095,8 +1248,33 @@ var EmbedClient = class {
1095
1248
  *
1096
1249
  * Fire-and-forget spawn on miss: if the daemon isn't up, this call returns
1097
1250
  * null AND kicks off a background spawn. The next call finds a ready daemon.
1251
+ *
1252
+ * Stuck-daemon recycle: if the daemon returns a transformers-missing
1253
+ * error (typical after a marketplace upgrade left an older daemon process
1254
+ * alive but with no node_modules accessible from its bundle path), we
1255
+ * SIGTERM it and clear its sock/pid so the very next call spawns a fresh
1256
+ * daemon from the current bundle. Without this, the stuck daemon would
1257
+ * keep poisoning every session until its 10-minute idle-out fires.
1098
1258
  */
1099
1259
  async embed(text, kind = "document") {
1260
+ const v = await this.embedAttempt(text, kind);
1261
+ if (v !== "recycled")
1262
+ return v;
1263
+ if (!this.autoSpawn)
1264
+ return null;
1265
+ this.trySpawnDaemon();
1266
+ await this.waitForDaemonReady();
1267
+ const retry = await this.embedAttempt(text, kind);
1268
+ return retry === "recycled" ? null : retry;
1269
+ }
1270
+ /**
1271
+ * One round-trip: connect → verify → embed. Returns:
1272
+ * - number[] : embedding vector (happy path)
1273
+ * - null : timeout / daemon error / transformers-missing
1274
+ * - "recycled": verifyDaemonOnce killed the daemon mid-call;
1275
+ * caller should respawn and retry once.
1276
+ */
1277
+ async embedAttempt(text, kind) {
1100
1278
  let sock;
1101
1279
  try {
1102
1280
  sock = await this.connectOnce();
@@ -1106,17 +1284,25 @@ var EmbedClient = class {
1106
1284
  return null;
1107
1285
  }
1108
1286
  try {
1287
+ const recycled = await this.verifyDaemonOnce(sock);
1288
+ if (recycled) {
1289
+ return "recycled";
1290
+ }
1109
1291
  const id = String(++this.nextId);
1110
1292
  const req = { op: "embed", id, kind, text };
1111
1293
  const resp = await this.sendAndWait(sock, req);
1112
1294
  if (resp.error || !("embedding" in resp) || !resp.embedding) {
1113
- log3(`embed err: ${resp.error ?? "no embedding"}`);
1295
+ const err = resp.error ?? "no embedding";
1296
+ log4(`embed err: ${err}`);
1297
+ if (isTransformersMissingError(err)) {
1298
+ this.handleTransformersMissing(err);
1299
+ }
1114
1300
  return null;
1115
1301
  }
1116
1302
  return resp.embedding;
1117
1303
  } catch (e) {
1118
1304
  const err = e instanceof Error ? e.message : String(e);
1119
- log3(`embed failed: ${err}`);
1305
+ log4(`embed failed: ${err}`);
1120
1306
  return null;
1121
1307
  } finally {
1122
1308
  try {
@@ -1125,6 +1311,123 @@ var EmbedClient = class {
1125
1311
  }
1126
1312
  }
1127
1313
  }
1314
+ /**
1315
+ * Poll for the sock file to come back after `trySpawnDaemon` — used by
1316
+ * the recycle retry path. Best-effort: caps at `spawnWaitMs` and
1317
+ * returns regardless so the retry attempt can run.
1318
+ */
1319
+ async waitForDaemonReady() {
1320
+ const deadline = Date.now() + this.spawnWaitMs;
1321
+ while (Date.now() < deadline) {
1322
+ if (existsSync3(this.socketPath))
1323
+ return;
1324
+ await new Promise((r) => setTimeout(r, 50));
1325
+ }
1326
+ }
1327
+ /**
1328
+ * Send a `hello` on first successful connect per EmbedClient instance.
1329
+ * If the daemon answers with a path that doesn't match our configured
1330
+ * daemonEntry — typical after a marketplace upgrade replaced the bundle
1331
+ * — SIGTERM the daemon + clear sock/pid so the next call spawns from the
1332
+ * current bundle.
1333
+ *
1334
+ * `helloVerified` is set ONLY after we've seen a compatible response,
1335
+ * so a transient probe failure or a recycle-triggering mismatch leaves
1336
+ * the flag false; the next reconnect re-runs verification against
1337
+ * whatever daemon is then live (typically the fresh spawn).
1338
+ */
1339
+ async verifyDaemonOnce(sock) {
1340
+ if (this.helloVerified)
1341
+ return false;
1342
+ if (!this.daemonEntry) {
1343
+ this.helloVerified = true;
1344
+ return false;
1345
+ }
1346
+ const id = String(++this.nextId);
1347
+ const req = { op: "hello", id };
1348
+ let resp;
1349
+ try {
1350
+ resp = await this.sendAndWait(sock, req);
1351
+ } catch (e) {
1352
+ log4(`hello probe failed (inconclusive, will retry next connect): ${e instanceof Error ? e.message : String(e)}`);
1353
+ return false;
1354
+ }
1355
+ const hello = resp;
1356
+ if (_recycledStuckDaemon) {
1357
+ return false;
1358
+ }
1359
+ if (!hello.daemonPath) {
1360
+ _recycledStuckDaemon = true;
1361
+ log4(`daemon does not implement hello (older protocol); recycling`);
1362
+ this.recycleDaemon(hello.pid);
1363
+ return true;
1364
+ }
1365
+ if (hello.daemonPath !== this.daemonEntry && !existsSync3(hello.daemonPath)) {
1366
+ _recycledStuckDaemon = true;
1367
+ log4(`daemon path no longer on disk \u2014 running=${hello.daemonPath} (gone) expected=${this.daemonEntry}; recycling`);
1368
+ this.recycleDaemon(hello.pid);
1369
+ return true;
1370
+ }
1371
+ this.helloVerified = true;
1372
+ return false;
1373
+ }
1374
+ /**
1375
+ * On a transformers-missing error from the daemon, SIGTERM the stuck
1376
+ * daemon (the bundle daemon that can't find its deps) and clear
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.
1386
+ */
1387
+ handleTransformersMissing(_detail) {
1388
+ if (!_recycledStuckDaemon) {
1389
+ _recycledStuckDaemon = true;
1390
+ this.recycleDaemon(null);
1391
+ }
1392
+ }
1393
+ /**
1394
+ * Best-effort SIGTERM + sock/pid cleanup. Tolerant of every missing-file
1395
+ * combination and dead-PID cases.
1396
+ *
1397
+ * Identity check: gate the SIGTERM on the daemon's socket file still
1398
+ * existing. We know the daemon was alive moments ago (we either just
1399
+ * got a hello response or the caller saw a transformers-missing error
1400
+ * the daemon emitted), but if the socket file is gone by the time we
1401
+ * try to kill, the daemon process is also gone and the PID we
1402
+ * captured may already have been recycled by the OS to an unrelated
1403
+ * user process. Mirrors the gate added to `killEmbedDaemon` in the
1404
+ * CLI — same failure mode, rarer trigger.
1405
+ */
1406
+ recycleDaemon(reportedPid) {
1407
+ let pid = reportedPid;
1408
+ if (pid === null) {
1409
+ try {
1410
+ pid = Number.parseInt(readFileSync5(this.pidPath, "utf-8").trim(), 10);
1411
+ } catch {
1412
+ }
1413
+ }
1414
+ if (Number.isFinite(pid) && pid !== null && pid > 0 && existsSync3(this.socketPath)) {
1415
+ try {
1416
+ process.kill(pid, "SIGTERM");
1417
+ } catch {
1418
+ }
1419
+ } else if (pid !== null) {
1420
+ log4(`recycle: socket gone, skipping SIGTERM on possibly-stale pid ${pid}`);
1421
+ }
1422
+ try {
1423
+ unlinkSync3(this.socketPath);
1424
+ } catch {
1425
+ }
1426
+ try {
1427
+ unlinkSync3(this.pidPath);
1428
+ } catch {
1429
+ }
1430
+ }
1128
1431
  /**
1129
1432
  * Wait up to spawnWaitMs for the daemon to accept connections, spawning if
1130
1433
  * necessary. Meant for SessionStart / long-running batches — not the hot path.
@@ -1148,7 +1451,7 @@ var EmbedClient = class {
1148
1451
  }
1149
1452
  }
1150
1453
  connectOnce() {
1151
- return new Promise((resolve2, reject) => {
1454
+ return new Promise((resolve3, reject) => {
1152
1455
  const sock = connect(this.socketPath);
1153
1456
  const to = setTimeout(() => {
1154
1457
  sock.destroy();
@@ -1156,7 +1459,7 @@ var EmbedClient = class {
1156
1459
  }, this.timeoutMs);
1157
1460
  sock.once("connect", () => {
1158
1461
  clearTimeout(to);
1159
- resolve2(sock);
1462
+ resolve3(sock);
1160
1463
  });
1161
1464
  sock.once("error", (e) => {
1162
1465
  clearTimeout(to);
@@ -1167,16 +1470,16 @@ var EmbedClient = class {
1167
1470
  trySpawnDaemon() {
1168
1471
  let fd;
1169
1472
  try {
1170
- fd = openSync(this.pidPath, "wx", 384);
1473
+ fd = openSync2(this.pidPath, "wx", 384);
1171
1474
  writeSync(fd, String(process.pid));
1172
1475
  } catch (e) {
1173
1476
  if (this.isPidFileStale()) {
1174
1477
  try {
1175
- unlinkSync(this.pidPath);
1478
+ unlinkSync3(this.pidPath);
1176
1479
  } catch {
1177
1480
  }
1178
1481
  try {
1179
- fd = openSync(this.pidPath, "wx", 384);
1482
+ fd = openSync2(this.pidPath, "wx", 384);
1180
1483
  writeSync(fd, String(process.pid));
1181
1484
  } catch {
1182
1485
  return;
@@ -1186,10 +1489,10 @@ var EmbedClient = class {
1186
1489
  }
1187
1490
  }
1188
1491
  if (!this.daemonEntry || !existsSync3(this.daemonEntry)) {
1189
- log3(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1492
+ log4(`daemonEntry not configured or missing: ${this.daemonEntry}`);
1190
1493
  try {
1191
- closeSync(fd);
1192
- unlinkSync(this.pidPath);
1494
+ closeSync2(fd);
1495
+ unlinkSync3(this.pidPath);
1193
1496
  } catch {
1194
1497
  }
1195
1498
  return;
@@ -1201,14 +1504,14 @@ var EmbedClient = class {
1201
1504
  env: process.env
1202
1505
  });
1203
1506
  child.unref();
1204
- log3(`spawned daemon pid=${child.pid}`);
1507
+ log4(`spawned daemon pid=${child.pid}`);
1205
1508
  } finally {
1206
- closeSync(fd);
1509
+ closeSync2(fd);
1207
1510
  }
1208
1511
  }
1209
1512
  isPidFileStale() {
1210
1513
  try {
1211
- const raw = readFileSync3(this.pidPath, "utf-8").trim();
1514
+ const raw = readFileSync5(this.pidPath, "utf-8").trim();
1212
1515
  const pid = Number(raw);
1213
1516
  if (!pid || Number.isNaN(pid))
1214
1517
  return true;
@@ -1226,7 +1529,7 @@ var EmbedClient = class {
1226
1529
  const deadline = Date.now() + this.spawnWaitMs;
1227
1530
  let delay = 30;
1228
1531
  while (Date.now() < deadline) {
1229
- await sleep2(delay);
1532
+ await sleep3(delay);
1230
1533
  delay = Math.min(delay * 1.5, 300);
1231
1534
  if (!existsSync3(this.socketPath))
1232
1535
  continue;
@@ -1238,7 +1541,7 @@ var EmbedClient = class {
1238
1541
  throw new Error("daemon did not become ready within spawnWaitMs");
1239
1542
  }
1240
1543
  sendAndWait(sock, req) {
1241
- return new Promise((resolve2, reject) => {
1544
+ return new Promise((resolve3, reject) => {
1242
1545
  let buf = "";
1243
1546
  const to = setTimeout(() => {
1244
1547
  sock.destroy();
@@ -1253,7 +1556,7 @@ var EmbedClient = class {
1253
1556
  const line = buf.slice(0, nl);
1254
1557
  clearTimeout(to);
1255
1558
  try {
1256
- resolve2(JSON.parse(line));
1559
+ resolve3(JSON.parse(line));
1257
1560
  } catch (e) {
1258
1561
  reject(e);
1259
1562
  }
@@ -1270,29 +1573,116 @@ var EmbedClient = class {
1270
1573
  });
1271
1574
  }
1272
1575
  };
1273
- function sleep2(ms) {
1576
+ function sleep3(ms) {
1274
1577
  return new Promise((r) => setTimeout(r, ms));
1275
1578
  }
1579
+ function isTransformersMissingError(err) {
1580
+ if (/hivemind embeddings install/i.test(err))
1581
+ return true;
1582
+ return /@huggingface\/transformers/i.test(err);
1583
+ }
1276
1584
 
1277
1585
  // dist/src/embeddings/disable.js
1278
1586
  import { createRequire } from "node:module";
1279
- import { homedir as homedir4 } from "node:os";
1280
- import { join as join5 } from "node:path";
1587
+ import { homedir as homedir7 } from "node:os";
1588
+ import { join as join8 } from "node:path";
1281
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
1282
1671
  var cachedStatus = null;
1283
1672
  function defaultResolveTransformers() {
1673
+ const sharedDir = join8(homedir7(), ".hivemind", "embed-deps");
1284
1674
  try {
1285
- createRequire(import.meta.url).resolve("@huggingface/transformers");
1675
+ createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1286
1676
  return;
1287
1677
  } catch {
1288
1678
  }
1289
- const sharedDir = join5(homedir4(), ".hivemind", "embed-deps");
1290
- createRequire(pathToFileURL(`${sharedDir}/`).href).resolve("@huggingface/transformers");
1679
+ createRequire(import.meta.url).resolve("@huggingface/transformers");
1291
1680
  }
1292
1681
  var _resolve = defaultResolveTransformers;
1682
+ var _readEnabled = getEmbeddingsEnabled;
1293
1683
  function detectStatus() {
1294
- if (process.env.HIVEMIND_EMBEDDINGS === "false")
1295
- return "env-disabled";
1684
+ if (!_readEnabled())
1685
+ return "user-disabled";
1296
1686
  try {
1297
1687
  _resolve();
1298
1688
  return "enabled";
@@ -1312,11 +1702,11 @@ function embeddingsDisabled() {
1312
1702
 
1313
1703
  // dist/src/hooks/grep-direct.js
1314
1704
  import { fileURLToPath } from "node:url";
1315
- import { dirname, join as join6 } from "node:path";
1705
+ import { dirname as dirname2, join as join9 } from "node:path";
1316
1706
  var SEMANTIC_ENABLED = process.env.HIVEMIND_SEMANTIC_SEARCH !== "false" && !embeddingsDisabled();
1317
1707
  var SEMANTIC_TIMEOUT_MS = Number(process.env.HIVEMIND_SEMANTIC_EMBED_TIMEOUT_MS ?? "500");
1318
1708
  function resolveDaemonPath() {
1319
- return join6(dirname(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
1709
+ return join9(dirname2(fileURLToPath(import.meta.url)), "..", "embeddings", "embed-daemon.js");
1320
1710
  }
1321
1711
  var sharedEmbedClient = null;
1322
1712
  function getEmbedClient() {
@@ -2319,20 +2709,20 @@ async function executeCompiledBashCommand(api, memoryTable, sessionsTable, cmd,
2319
2709
  }
2320
2710
 
2321
2711
  // dist/src/hooks/query-cache.js
2322
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
2323
- import { join as join7 } from "node:path";
2324
- import { homedir as homedir5 } from "node:os";
2325
- var log4 = (msg) => log("query-cache", msg);
2326
- var DEFAULT_CACHE_ROOT = join7(homedir5(), ".deeplake", "query-cache");
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";
2715
+ var log5 = (msg) => log("query-cache", msg);
2716
+ var DEFAULT_CACHE_ROOT = join10(homedir8(), ".deeplake", "query-cache");
2327
2717
  var INDEX_CACHE_FILE = "index.md";
2328
2718
  function getSessionQueryCacheDir(sessionId, deps = {}) {
2329
2719
  const { cacheRoot = DEFAULT_CACHE_ROOT } = deps;
2330
- return join7(cacheRoot, sessionId);
2720
+ return join10(cacheRoot, sessionId);
2331
2721
  }
2332
2722
  function readCachedIndexContent(sessionId, deps = {}) {
2333
- const { logFn = log4 } = deps;
2723
+ const { logFn = log5 } = deps;
2334
2724
  try {
2335
- return readFileSync4(join7(getSessionQueryCacheDir(sessionId, deps), INDEX_CACHE_FILE), "utf-8");
2725
+ return readFileSync7(join10(getSessionQueryCacheDir(sessionId, deps), INDEX_CACHE_FILE), "utf-8");
2336
2726
  } catch (e) {
2337
2727
  if (e?.code === "ENOENT")
2338
2728
  return null;
@@ -2341,34 +2731,34 @@ function readCachedIndexContent(sessionId, deps = {}) {
2341
2731
  }
2342
2732
  }
2343
2733
  function writeCachedIndexContent(sessionId, content, deps = {}) {
2344
- const { logFn = log4 } = deps;
2734
+ const { logFn = log5 } = deps;
2345
2735
  try {
2346
2736
  const dir = getSessionQueryCacheDir(sessionId, deps);
2347
- mkdirSync2(dir, { recursive: true });
2348
- writeFileSync2(join7(dir, INDEX_CACHE_FILE), content, "utf-8");
2737
+ mkdirSync5(dir, { recursive: true });
2738
+ writeFileSync5(join10(dir, INDEX_CACHE_FILE), content, "utf-8");
2349
2739
  } catch (e) {
2350
2740
  logFn(`write failed for session=${sessionId}: ${e.message}`);
2351
2741
  }
2352
2742
  }
2353
2743
 
2354
2744
  // dist/src/utils/direct-run.js
2355
- import { resolve } from "node:path";
2745
+ import { resolve as resolve2 } from "node:path";
2356
2746
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2357
2747
  function isDirectRun(metaUrl) {
2358
2748
  const entry = process.argv[1];
2359
2749
  if (!entry)
2360
2750
  return false;
2361
2751
  try {
2362
- return resolve(fileURLToPath2(metaUrl)) === resolve(entry);
2752
+ return resolve2(fileURLToPath2(metaUrl)) === resolve2(entry);
2363
2753
  } catch {
2364
2754
  return false;
2365
2755
  }
2366
2756
  }
2367
2757
 
2368
2758
  // dist/src/hooks/memory-path-utils.js
2369
- import { homedir as homedir6 } from "node:os";
2370
- import { join as join8 } from "node:path";
2371
- var MEMORY_PATH = join8(homedir6(), ".deeplake", "memory");
2759
+ import { homedir as homedir9 } from "node:os";
2760
+ import { join as join11 } from "node:path";
2761
+ var MEMORY_PATH = join11(homedir9(), ".deeplake", "memory");
2372
2762
  var TILDE_PATH = "~/.deeplake/memory";
2373
2763
  var HOME_VAR_PATH = "$HOME/.deeplake/memory";
2374
2764
  var SAFE_BUILTINS = /* @__PURE__ */ new Set([
@@ -2484,13 +2874,13 @@ function rewritePaths(cmd) {
2484
2874
  }
2485
2875
 
2486
2876
  // dist/src/hooks/codex/pre-tool-use.js
2487
- var log5 = (msg) => log("codex-pre", msg);
2488
- var __bundleDir = dirname2(fileURLToPath3(import.meta.url));
2489
- var SHELL_BUNDLE = existsSync4(join9(__bundleDir, "shell", "deeplake-shell.js")) ? join9(__bundleDir, "shell", "deeplake-shell.js") : join9(__bundleDir, "..", "shell", "deeplake-shell.js");
2877
+ var log6 = (msg) => log("codex-pre", msg);
2878
+ var __bundleDir = dirname3(fileURLToPath3(import.meta.url));
2879
+ var SHELL_BUNDLE = existsSync5(join12(__bundleDir, "shell", "deeplake-shell.js")) ? join12(__bundleDir, "shell", "deeplake-shell.js") : join12(__bundleDir, "..", "shell", "deeplake-shell.js");
2490
2880
  function buildUnsupportedGuidance() {
2491
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.";
2492
2882
  }
2493
- function runVirtualShell(cmd, shellBundle = SHELL_BUNDLE, logFn = log5) {
2883
+ function runVirtualShell(cmd, shellBundle = SHELL_BUNDLE, logFn = log6) {
2494
2884
  try {
2495
2885
  return execFileSync("node", [shellBundle, "-c", cmd], {
2496
2886
  encoding: "utf-8",
@@ -2515,7 +2905,7 @@ function buildIndexContent(rows) {
2515
2905
  return lines.join("\n");
2516
2906
  }
2517
2907
  async function processCodexPreToolUse(input, deps = {}) {
2518
- const { config = loadConfig(), createApi = (table, activeConfig) => new DeeplakeApi(activeConfig.token, activeConfig.apiUrl, activeConfig.orgId, activeConfig.workspaceId, table), executeCompiledBashCommandFn = executeCompiledBashCommand, readVirtualPathContentsFn = readVirtualPathContents, readVirtualPathContentFn = readVirtualPathContent, listVirtualPathRowsFn = listVirtualPathRows, findVirtualPathsFn = findVirtualPaths, handleGrepDirectFn = handleGrepDirect, readCachedIndexContentFn = readCachedIndexContent, writeCachedIndexContentFn = writeCachedIndexContent, runVirtualShellFn = runVirtualShell, shellBundle = SHELL_BUNDLE, logFn = log5 } = deps;
2908
+ const { config = loadConfig(), createApi = (table, activeConfig) => new DeeplakeApi(activeConfig.token, activeConfig.apiUrl, activeConfig.orgId, activeConfig.workspaceId, table), executeCompiledBashCommandFn = executeCompiledBashCommand, readVirtualPathContentsFn = readVirtualPathContents, readVirtualPathContentFn = readVirtualPathContent, listVirtualPathRowsFn = listVirtualPathRows, findVirtualPathsFn = findVirtualPaths, handleGrepDirectFn = handleGrepDirect, readCachedIndexContentFn = readCachedIndexContent, writeCachedIndexContentFn = writeCachedIndexContent, runVirtualShellFn = runVirtualShell, shellBundle = SHELL_BUNDLE, logFn = log6 } = deps;
2519
2909
  const cmd = input.tool_input?.command ?? "";
2520
2910
  logFn(`hook fired: cmd=${cmd}`);
2521
2911
  if (!touchesMemory(cmd))
@@ -2725,7 +3115,7 @@ async function main() {
2725
3115
  }
2726
3116
  if (isDirectRun(import.meta.url)) {
2727
3117
  main().catch((e) => {
2728
- log5(`fatal: ${e.message}`);
3118
+ log6(`fatal: ${e.message}`);
2729
3119
  process.exit(0);
2730
3120
  });
2731
3121
  }