@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 as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
20
- import { join as join4 } 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 ?? join4(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 join4(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(readFileSync3(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
- mkdirSync2(getIndexMarkerDir(), { recursive: true });
44
- writeFileSync2(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({
@@ -151,6 +151,107 @@ function sqlIdent(name) {
151
151
  var SUMMARY_EMBEDDING_COL = "summary_embedding";
152
152
  var MESSAGE_EMBEDDING_COL = "message_embedding";
153
153
 
154
+ // dist/src/notifications/queue.js
155
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync, mkdirSync as mkdirSync2, openSync, closeSync, unlinkSync as unlinkSync2, statSync } from "node:fs";
156
+ import { join as join4, resolve } from "node:path";
157
+ import { homedir as homedir4 } from "node:os";
158
+ import { setTimeout as sleep } from "node:timers/promises";
159
+ var log2 = (msg) => log("notifications-queue", msg);
160
+ var LOCK_RETRY_MAX = 50;
161
+ var LOCK_RETRY_BASE_MS = 5;
162
+ var LOCK_STALE_MS = 5e3;
163
+ function queuePath() {
164
+ return join4(homedir4(), ".deeplake", "notifications-queue.json");
165
+ }
166
+ function lockPath() {
167
+ return `${queuePath()}.lock`;
168
+ }
169
+ function readQueue() {
170
+ try {
171
+ const raw = readFileSync3(queuePath(), "utf-8");
172
+ const parsed = JSON.parse(raw);
173
+ if (!parsed || !Array.isArray(parsed.queue)) {
174
+ log2(`queue malformed \u2192 treating as empty`);
175
+ return { queue: [] };
176
+ }
177
+ return { queue: parsed.queue };
178
+ } catch {
179
+ return { queue: [] };
180
+ }
181
+ }
182
+ function _isQueuePathInsideHome(path, home) {
183
+ const r = resolve(path);
184
+ const h = resolve(home);
185
+ return r.startsWith(h + "/") || r === h;
186
+ }
187
+ function writeQueue(q) {
188
+ const path = queuePath();
189
+ const home = resolve(homedir4());
190
+ if (!_isQueuePathInsideHome(path, home)) {
191
+ throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
192
+ }
193
+ mkdirSync2(join4(home, ".deeplake"), { recursive: true, mode: 448 });
194
+ const tmp = `${path}.${process.pid}.tmp`;
195
+ writeFileSync2(tmp, JSON.stringify(q, null, 2), { mode: 384 });
196
+ renameSync(tmp, path);
197
+ }
198
+ async function withQueueLock(fn) {
199
+ const path = lockPath();
200
+ mkdirSync2(join4(homedir4(), ".deeplake"), { recursive: true, mode: 448 });
201
+ let fd = null;
202
+ for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
203
+ try {
204
+ fd = openSync(path, "wx", 384);
205
+ break;
206
+ } catch (e) {
207
+ const code = e.code;
208
+ if (code !== "EEXIST")
209
+ throw e;
210
+ try {
211
+ const age = Date.now() - statSync(path).mtimeMs;
212
+ if (age > LOCK_STALE_MS) {
213
+ unlinkSync2(path);
214
+ continue;
215
+ }
216
+ } catch {
217
+ }
218
+ const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
219
+ await sleep(delay);
220
+ }
221
+ }
222
+ if (fd === null) {
223
+ log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
224
+ return fn();
225
+ }
226
+ try {
227
+ return fn();
228
+ } finally {
229
+ try {
230
+ closeSync(fd);
231
+ } catch {
232
+ }
233
+ try {
234
+ unlinkSync2(path);
235
+ } catch {
236
+ }
237
+ }
238
+ }
239
+ function sameDedupKey(a, b) {
240
+ if (a.id !== b.id)
241
+ return false;
242
+ return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
243
+ }
244
+ async function enqueueNotification(n) {
245
+ await withQueueLock(() => {
246
+ const q = readQueue();
247
+ if (q.queue.some((existing) => sameDedupKey(existing, n))) {
248
+ return;
249
+ }
250
+ q.queue.push(n);
251
+ writeQueue(q);
252
+ });
253
+ }
254
+
154
255
  // dist/src/deeplake-api.js
155
256
  var indexMarkerStorePromise = null;
156
257
  function getIndexMarkerStore() {
@@ -158,7 +259,7 @@ function getIndexMarkerStore() {
158
259
  indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
159
260
  return indexMarkerStorePromise;
160
261
  }
161
- var log2 = (msg) => log("sdk", msg);
262
+ var log3 = (msg) => log("sdk", msg);
162
263
  function summarizeSql(sql, maxLen = 220) {
163
264
  const compact = sql.replace(/\s+/g, " ").trim();
164
265
  return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
@@ -170,7 +271,38 @@ function traceSql(msg) {
170
271
  process.stderr.write(`[deeplake-sql] ${msg}
171
272
  `);
172
273
  if (process.env.HIVEMIND_DEBUG === "1")
173
- log2(msg);
274
+ log3(msg);
275
+ }
276
+ var _signalledBalanceExhausted = false;
277
+ function maybeSignalBalanceExhausted(status, bodyText) {
278
+ if (status !== 402)
279
+ return;
280
+ if (!bodyText.includes("balance_cents"))
281
+ return;
282
+ if (_signalledBalanceExhausted)
283
+ return;
284
+ _signalledBalanceExhausted = true;
285
+ log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
286
+ enqueueNotification({
287
+ id: "balance-exhausted",
288
+ severity: "warn",
289
+ transient: true,
290
+ title: "Hivemind credits exhausted \u2014 top up to keep capturing",
291
+ body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
292
+ dedupKey: { reason: "balance-zero" }
293
+ }).catch((e) => {
294
+ log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
295
+ });
296
+ }
297
+ function billingUrl() {
298
+ try {
299
+ const c = loadCredentials();
300
+ if (c?.orgName && c?.workspaceId) {
301
+ return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
302
+ }
303
+ } catch {
304
+ }
305
+ return "https://deeplake.ai";
174
306
  }
175
307
  var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
176
308
  var MAX_RETRIES = 3;
@@ -179,8 +311,8 @@ var MAX_CONCURRENCY = 5;
179
311
  function getQueryTimeoutMs() {
180
312
  return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
181
313
  }
182
- function sleep(ms) {
183
- return new Promise((resolve) => setTimeout(resolve, ms));
314
+ function sleep2(ms) {
315
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
184
316
  }
185
317
  function isTimeoutError(error) {
186
318
  const name = error instanceof Error ? error.name.toLowerCase() : "";
@@ -210,7 +342,7 @@ var Semaphore = class {
210
342
  this.active++;
211
343
  return;
212
344
  }
213
- await new Promise((resolve) => this.waiting.push(resolve));
345
+ await new Promise((resolve2) => this.waiting.push(resolve2));
214
346
  }
215
347
  release() {
216
348
  this.active--;
@@ -281,8 +413,8 @@ var DeeplakeApi = class {
281
413
  lastError = e instanceof Error ? e : new Error(String(e));
282
414
  if (attempt < MAX_RETRIES) {
283
415
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
284
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
285
- await sleep(delay);
416
+ log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
417
+ await sleep2(delay);
286
418
  continue;
287
419
  }
288
420
  throw lastError;
@@ -298,10 +430,11 @@ var DeeplakeApi = class {
298
430
  const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
299
431
  if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
300
432
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
301
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
302
- await sleep(delay);
433
+ log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
434
+ await sleep2(delay);
303
435
  continue;
304
436
  }
437
+ maybeSignalBalanceExhausted(resp.status, text);
305
438
  throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
306
439
  }
307
440
  throw lastError ?? new Error("Query failed: max retries exceeded");
@@ -322,7 +455,7 @@ var DeeplakeApi = class {
322
455
  const chunk = rows.slice(i, i + CONCURRENCY);
323
456
  await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
324
457
  }
325
- log2(`commit: ${rows.length} rows`);
458
+ log3(`commit: ${rows.length} rows`);
326
459
  }
327
460
  async upsertRowSql(row) {
328
461
  const ts = (/* @__PURE__ */ new Date()).toISOString();
@@ -378,7 +511,7 @@ var DeeplakeApi = class {
378
511
  markers.writeIndexMarker(markerPath);
379
512
  return;
380
513
  }
381
- log2(`index "${indexName}" skipped: ${e.message}`);
514
+ log3(`index "${indexName}" skipped: ${e.message}`);
382
515
  }
383
516
  }
384
517
  /**
@@ -468,13 +601,13 @@ var DeeplakeApi = class {
468
601
  };
469
602
  }
470
603
  if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
471
- await sleep(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
604
+ await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
472
605
  continue;
473
606
  }
474
607
  return { tables: [], cacheable: false };
475
608
  } catch {
476
609
  if (attempt < MAX_RETRIES) {
477
- await sleep(BASE_DELAY_MS * Math.pow(2, attempt));
610
+ await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
478
611
  continue;
479
612
  }
480
613
  return { tables: [], cacheable: false };
@@ -502,9 +635,9 @@ var DeeplakeApi = class {
502
635
  } catch (err) {
503
636
  lastErr = err;
504
637
  const msg = err instanceof Error ? err.message : String(err);
505
- log2(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
638
+ log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
506
639
  if (attempt < OUTER_BACKOFFS_MS.length) {
507
- await sleep(OUTER_BACKOFFS_MS[attempt]);
640
+ await sleep2(OUTER_BACKOFFS_MS[attempt]);
508
641
  }
509
642
  }
510
643
  }
@@ -515,9 +648,9 @@ var DeeplakeApi = class {
515
648
  const tbl = sqlIdent(name ?? this.tableName);
516
649
  const tables = await this.listTables();
517
650
  if (!tables.includes(tbl)) {
518
- log2(`table "${tbl}" not found, creating`);
651
+ log3(`table "${tbl}" not found, creating`);
519
652
  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);
520
- log2(`table "${tbl}" created`);
653
+ log3(`table "${tbl}" created`);
521
654
  if (!tables.includes(tbl))
522
655
  this._tablesCache = [...tables, tbl];
523
656
  }
@@ -530,9 +663,9 @@ var DeeplakeApi = class {
530
663
  const safe = sqlIdent(name);
531
664
  const tables = await this.listTables();
532
665
  if (!tables.includes(safe)) {
533
- log2(`table "${safe}" not found, creating`);
666
+ log3(`table "${safe}" not found, creating`);
534
667
  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);
535
- log2(`table "${safe}" created`);
668
+ log3(`table "${safe}" created`);
536
669
  if (!tables.includes(safe))
537
670
  this._tablesCache = [...tables, safe];
538
671
  }
@@ -555,9 +688,9 @@ var DeeplakeApi = class {
555
688
  const safe = sqlIdent(name);
556
689
  const tables = await this.listTables();
557
690
  if (!tables.includes(safe)) {
558
- log2(`table "${safe}" not found, creating`);
691
+ log3(`table "${safe}" not found, creating`);
559
692
  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);
560
- log2(`table "${safe}" created`);
693
+ log3(`table "${safe}" created`);
561
694
  if (!tables.includes(safe))
562
695
  this._tablesCache = [...tables, safe];
563
696
  }
@@ -595,16 +728,16 @@ function renderSkillifyCommands() {
595
728
  }
596
729
 
597
730
  // dist/src/skillify/local-manifest.js
598
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
599
- import { homedir as homedir4 } from "node:os";
600
- import { dirname, join as join5 } from "node:path";
601
- var LOCAL_MANIFEST_PATH = join5(homedir4(), ".claude", "hivemind", "local-mined.json");
602
- var LOCAL_MINE_LOCK_PATH = join5(homedir4(), ".claude", "hivemind", "local-mined.lock");
731
+ import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
732
+ import { homedir as homedir5 } from "node:os";
733
+ import { dirname, join as join6 } from "node:path";
734
+ var LOCAL_MANIFEST_PATH = join6(homedir5(), ".claude", "hivemind", "local-mined.json");
735
+ var LOCAL_MINE_LOCK_PATH = join6(homedir5(), ".claude", "hivemind", "local-mined.lock");
603
736
  function readLocalManifest(path = LOCAL_MANIFEST_PATH) {
604
737
  if (!existsSync3(path))
605
738
  return null;
606
739
  try {
607
- return JSON.parse(readFileSync4(path, "utf-8"));
740
+ return JSON.parse(readFileSync5(path, "utf-8"));
608
741
  } catch {
609
742
  return null;
610
743
  }
@@ -616,19 +749,19 @@ function countLocalManifestEntries(path = LOCAL_MANIFEST_PATH) {
616
749
 
617
750
  // dist/src/skillify/spawn-mine-local-worker.js
618
751
  import { execFileSync, spawn } from "node:child_process";
619
- import { closeSync, existsSync as existsSync4, mkdirSync as mkdirSync4, openSync, readdirSync, statSync, unlinkSync as unlinkSync2 } from "node:fs";
620
- import { homedir as homedir5 } from "node:os";
621
- import { dirname as dirname2, join as join6 } from "node:path";
752
+ import { closeSync as closeSync2, existsSync as existsSync4, mkdirSync as mkdirSync5, openSync as openSync2, readdirSync, statSync as statSync2, unlinkSync as unlinkSync3 } from "node:fs";
753
+ import { homedir as homedir6 } from "node:os";
754
+ import { dirname as dirname2, join as join7 } from "node:path";
622
755
  import { fileURLToPath } from "node:url";
623
- var HOME = homedir5();
624
- var HIVEMIND_DIR = join6(HOME, ".claude", "hivemind");
625
- var LOG_PATH = join6(HOME, ".claude", "hooks", "mine-local.log");
626
- var CLAUDE_PROJECTS_DIR = join6(HOME, ".claude", "projects");
627
- var LOCK_STALE_MS = 15 * 60 * 1e3;
756
+ var HOME = homedir6();
757
+ var HIVEMIND_DIR = join7(HOME, ".claude", "hivemind");
758
+ var LOG_PATH = join7(HOME, ".claude", "hooks", "mine-local.log");
759
+ var CLAUDE_PROJECTS_DIR = join7(HOME, ".claude", "projects");
760
+ var LOCK_STALE_MS2 = 15 * 60 * 1e3;
628
761
  function findBundledCliPath() {
629
762
  try {
630
763
  const thisDir = dirname2(fileURLToPath(import.meta.url));
631
- const cliPath = join6(thisDir, "..", "..", "bundle", "cli.js");
764
+ const cliPath = join7(thisDir, "..", "..", "bundle", "cli.js");
632
765
  return existsSync4(cliPath) ? cliPath : null;
633
766
  } catch {
634
767
  return null;
@@ -661,7 +794,7 @@ function hasLocalClaudeSessions() {
661
794
  for (const sub of subdirs) {
662
795
  let files;
663
796
  try {
664
- files = readdirSync(join6(CLAUDE_PROJECTS_DIR, sub));
797
+ files = readdirSync(join7(CLAUDE_PROJECTS_DIR, sub));
665
798
  } catch {
666
799
  continue;
667
800
  }
@@ -676,14 +809,14 @@ function maybeAutoMineLocal() {
676
809
  if (existsSync4(LOCAL_MINE_LOCK_PATH)) {
677
810
  let stale = false;
678
811
  try {
679
- const stats = statSync(LOCAL_MINE_LOCK_PATH);
680
- stale = Date.now() - stats.mtimeMs > LOCK_STALE_MS;
812
+ const stats = statSync2(LOCAL_MINE_LOCK_PATH);
813
+ stale = Date.now() - stats.mtimeMs > LOCK_STALE_MS2;
681
814
  } catch {
682
815
  }
683
816
  if (!stale)
684
817
  return { triggered: false, reason: "lock-exists" };
685
818
  try {
686
- unlinkSync2(LOCAL_MINE_LOCK_PATH);
819
+ unlinkSync3(LOCAL_MINE_LOCK_PATH);
687
820
  } catch {
688
821
  return { triggered: false, reason: "lock-exists" };
689
822
  }
@@ -694,27 +827,27 @@ function maybeAutoMineLocal() {
694
827
  if (!launcher)
695
828
  return { triggered: false, reason: "no-hivemind-bin" };
696
829
  try {
697
- mkdirSync4(HIVEMIND_DIR, { recursive: true });
698
- const fd = openSync(LOCAL_MINE_LOCK_PATH, "wx");
699
- closeSync(fd);
830
+ mkdirSync5(HIVEMIND_DIR, { recursive: true });
831
+ const fd = openSync2(LOCAL_MINE_LOCK_PATH, "wx");
832
+ closeSync2(fd);
700
833
  } catch {
701
834
  return { triggered: false, reason: "lock-acquire-failed" };
702
835
  }
703
836
  try {
704
- mkdirSync4(join6(HOME, ".claude", "hooks"), { recursive: true });
705
- const out = openSync(LOG_PATH, "a");
837
+ mkdirSync5(join7(HOME, ".claude", "hooks"), { recursive: true });
838
+ const out = openSync2(LOG_PATH, "a");
706
839
  const [cmd, args] = launcher.kind === "node-script" ? [process.execPath, [launcher.path, "skillify", "mine-local"]] : [launcher.path, ["skillify", "mine-local"]];
707
840
  const child = spawn(cmd, args, {
708
841
  detached: true,
709
842
  stdio: ["ignore", out, out],
710
843
  env: process.env
711
844
  });
712
- closeSync(out);
845
+ closeSync2(out);
713
846
  child.unref();
714
847
  return { triggered: true };
715
848
  } catch {
716
849
  try {
717
- unlinkSync2(LOCAL_MINE_LOCK_PATH);
850
+ unlinkSync3(LOCAL_MINE_LOCK_PATH);
718
851
  } catch {
719
852
  }
720
853
  return { triggered: false, reason: "spawn-failed" };
@@ -723,13 +856,13 @@ function maybeAutoMineLocal() {
723
856
 
724
857
  // dist/src/utils/stdin.js
725
858
  function readStdin() {
726
- return new Promise((resolve, reject) => {
859
+ return new Promise((resolve2, reject) => {
727
860
  let data = "";
728
861
  process.stdin.setEncoding("utf-8");
729
862
  process.stdin.on("data", (chunk) => data += chunk);
730
863
  process.stdin.on("end", () => {
731
864
  try {
732
- resolve(JSON.parse(data));
865
+ resolve2(JSON.parse(data));
733
866
  } catch (err) {
734
867
  reject(new Error(`Failed to parse hook input: ${err}`));
735
868
  }
@@ -739,18 +872,18 @@ function readStdin() {
739
872
  }
740
873
 
741
874
  // dist/src/utils/version-check.js
742
- import { readFileSync as readFileSync5 } from "node:fs";
743
- import { dirname as dirname3, join as join7 } from "node:path";
875
+ import { readFileSync as readFileSync6 } from "node:fs";
876
+ import { dirname as dirname3, join as join8 } from "node:path";
744
877
  function getInstalledVersion(bundleDir, pluginManifestDir) {
745
878
  try {
746
- const pluginJson = join7(bundleDir, "..", pluginManifestDir, "plugin.json");
747
- const plugin = JSON.parse(readFileSync5(pluginJson, "utf-8"));
879
+ const pluginJson = join8(bundleDir, "..", pluginManifestDir, "plugin.json");
880
+ const plugin = JSON.parse(readFileSync6(pluginJson, "utf-8"));
748
881
  if (plugin.version)
749
882
  return plugin.version;
750
883
  } catch {
751
884
  }
752
885
  try {
753
- const stamp = readFileSync5(join7(bundleDir, "..", ".hivemind_version"), "utf-8").trim();
886
+ const stamp = readFileSync6(join8(bundleDir, "..", ".hivemind_version"), "utf-8").trim();
754
887
  if (stamp)
755
888
  return stamp;
756
889
  } catch {
@@ -765,9 +898,9 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
765
898
  ]);
766
899
  let dir = bundleDir;
767
900
  for (let i = 0; i < 5; i++) {
768
- const candidate = join7(dir, "package.json");
901
+ const candidate = join8(dir, "package.json");
769
902
  try {
770
- const pkg = JSON.parse(readFileSync5(candidate, "utf-8"));
903
+ const pkg = JSON.parse(readFileSync6(candidate, "utf-8"));
771
904
  if (HIVEMIND_PKG_NAMES.has(pkg.name) && pkg.version)
772
905
  return pkg.version;
773
906
  } catch {
@@ -783,8 +916,8 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
783
916
  // dist/src/hooks/shared/autoupdate.js
784
917
  import { spawn as spawn2 } from "node:child_process";
785
918
  import { existsSync as existsSync5 } from "node:fs";
786
- import { join as join8 } from "node:path";
787
- var log3 = (msg) => log("autoupdate", msg);
919
+ import { join as join9 } from "node:path";
920
+ var log4 = (msg) => log("autoupdate", msg);
788
921
  var defaultSpawn = (cmd, args) => {
789
922
  const child = spawn2(cmd, args, {
790
923
  detached: true,
@@ -799,7 +932,7 @@ function findHivemindOnPath() {
799
932
  const PATH = process.env.PATH ?? "";
800
933
  const dirs = PATH.split(":").filter(Boolean);
801
934
  for (const dir of dirs) {
802
- const candidate = join8(dir, "hivemind");
935
+ const candidate = join9(dir, "hivemind");
803
936
  if (existsSync5(candidate))
804
937
  return candidate;
805
938
  }
@@ -807,41 +940,41 @@ function findHivemindOnPath() {
807
940
  }
808
941
  async function autoUpdate(creds, opts) {
809
942
  const t0 = Date.now();
810
- log3(`agent=${opts.agent} entered`);
943
+ log4(`agent=${opts.agent} entered`);
811
944
  if (!creds?.token) {
812
- log3(`agent=${opts.agent} skip: no creds.token (${Date.now() - t0}ms)`);
945
+ log4(`agent=${opts.agent} skip: no creds.token (${Date.now() - t0}ms)`);
813
946
  return;
814
947
  }
815
948
  if (creds.autoupdate === false) {
816
- log3(`agent=${opts.agent} skip: autoupdate=false (${Date.now() - t0}ms)`);
949
+ log4(`agent=${opts.agent} skip: autoupdate=false (${Date.now() - t0}ms)`);
817
950
  return;
818
951
  }
819
952
  const binaryPath = opts.hivemindBinaryPath !== void 0 ? opts.hivemindBinaryPath : findHivemindOnPath();
820
953
  if (!binaryPath) {
821
- log3(`agent=${opts.agent} skip: hivemind binary not on PATH (${Date.now() - t0}ms)`);
954
+ log4(`agent=${opts.agent} skip: hivemind binary not on PATH (${Date.now() - t0}ms)`);
822
955
  return;
823
956
  }
824
- log3(`agent=${opts.agent} binary=${binaryPath} \u2192 dispatching detached update`);
957
+ log4(`agent=${opts.agent} binary=${binaryPath} \u2192 dispatching detached update`);
825
958
  const spawnFn = opts.spawn ?? defaultSpawn;
826
959
  let pid;
827
960
  try {
828
961
  pid = spawnFn(binaryPath, ["update"]).pid;
829
962
  } catch (e) {
830
- log3(`agent=${opts.agent} dispatch threw: ${e?.message ?? e} (${Date.now() - t0}ms)`);
963
+ log4(`agent=${opts.agent} dispatch threw: ${e?.message ?? e} (${Date.now() - t0}ms)`);
831
964
  return;
832
965
  }
833
- log3(`agent=${opts.agent} dispatched (pid=${pid ?? "?"}) (${Date.now() - t0}ms total)`);
966
+ log4(`agent=${opts.agent} dispatched (pid=${pid ?? "?"}) (${Date.now() - t0}ms total)`);
834
967
  }
835
968
 
836
969
  // dist/src/skillify/pull.js
837
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, renameSync as renameSync3, lstatSync as lstatSync2, readlinkSync, symlinkSync, unlinkSync as unlinkSync4 } from "node:fs";
838
- import { homedir as homedir10 } from "node:os";
839
- import { dirname as dirname5, join as join13 } from "node:path";
970
+ import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, renameSync as renameSync4, lstatSync as lstatSync2, readlinkSync, symlinkSync, unlinkSync as unlinkSync5 } from "node:fs";
971
+ import { homedir as homedir11 } from "node:os";
972
+ import { dirname as dirname5, join as join14 } from "node:path";
840
973
 
841
974
  // dist/src/skillify/skill-writer.js
842
- import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
843
- import { homedir as homedir6 } from "node:os";
844
- import { join as join9 } from "node:path";
975
+ import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync7, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync5 } from "node:fs";
976
+ import { homedir as homedir7 } from "node:os";
977
+ import { join as join10 } from "node:path";
845
978
  function assertValidSkillName(name) {
846
979
  if (typeof name !== "string" || name.length === 0) {
847
980
  throw new Error(`invalid skill name: empty or non-string`);
@@ -907,29 +1040,29 @@ function parseFrontmatter(text) {
907
1040
  }
908
1041
 
909
1042
  // dist/src/skillify/manifest.js
910
- import { existsSync as existsSync8, lstatSync, mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
911
- import { homedir as homedir8 } from "node:os";
912
- import { dirname as dirname4, join as join11 } from "node:path";
1043
+ import { existsSync as existsSync8, lstatSync, mkdirSync as mkdirSync7, readFileSync as readFileSync8, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
1044
+ import { homedir as homedir9 } from "node:os";
1045
+ import { dirname as dirname4, join as join12 } from "node:path";
913
1046
 
914
1047
  // dist/src/skillify/legacy-migration.js
915
- import { existsSync as existsSync7, renameSync } from "node:fs";
916
- import { homedir as homedir7 } from "node:os";
917
- import { join as join10 } from "node:path";
1048
+ import { existsSync as existsSync7, renameSync as renameSync2 } from "node:fs";
1049
+ import { homedir as homedir8 } from "node:os";
1050
+ import { join as join11 } from "node:path";
918
1051
  var dlog = (msg) => log("skillify-migrate", msg);
919
1052
  var attempted = false;
920
1053
  function migrateLegacyStateDir() {
921
1054
  if (attempted)
922
1055
  return;
923
1056
  attempted = true;
924
- const root = join10(homedir7(), ".deeplake", "state");
925
- const legacy = join10(root, "skilify");
926
- const current = join10(root, "skillify");
1057
+ const root = join11(homedir8(), ".deeplake", "state");
1058
+ const legacy = join11(root, "skilify");
1059
+ const current = join11(root, "skillify");
927
1060
  if (!existsSync7(legacy))
928
1061
  return;
929
1062
  if (existsSync7(current))
930
1063
  return;
931
1064
  try {
932
- renameSync(legacy, current);
1065
+ renameSync2(legacy, current);
933
1066
  dlog(`migrated ${legacy} -> ${current}`);
934
1067
  } catch (err) {
935
1068
  const code = err.code;
@@ -946,7 +1079,7 @@ function emptyManifest() {
946
1079
  return { version: 1, entries: [] };
947
1080
  }
948
1081
  function manifestPath() {
949
- return join11(homedir8(), ".deeplake", "state", "skillify", "pulled.json");
1082
+ return join12(homedir9(), ".deeplake", "state", "skillify", "pulled.json");
950
1083
  }
951
1084
  function loadManifest(path = manifestPath()) {
952
1085
  migrateLegacyStateDir();
@@ -954,7 +1087,7 @@ function loadManifest(path = manifestPath()) {
954
1087
  return emptyManifest();
955
1088
  let raw;
956
1089
  try {
957
- raw = readFileSync7(path, "utf-8");
1090
+ raw = readFileSync8(path, "utf-8");
958
1091
  } catch {
959
1092
  return emptyManifest();
960
1093
  }
@@ -1001,10 +1134,10 @@ function loadManifest(path = manifestPath()) {
1001
1134
  }
1002
1135
  function saveManifest(m, path = manifestPath()) {
1003
1136
  migrateLegacyStateDir();
1004
- mkdirSync6(dirname4(path), { recursive: true });
1137
+ mkdirSync7(dirname4(path), { recursive: true });
1005
1138
  const tmp = `${path}.tmp`;
1006
- writeFileSync5(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
1007
- renameSync2(tmp, path);
1139
+ writeFileSync6(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
1140
+ renameSync3(tmp, path);
1008
1141
  }
1009
1142
  function recordPull(entry, path = manifestPath()) {
1010
1143
  const m = loadManifest(path);
@@ -1029,7 +1162,7 @@ function unlinkSymlinks(paths) {
1029
1162
  if (!st.isSymbolicLink())
1030
1163
  continue;
1031
1164
  try {
1032
- unlinkSync3(path);
1165
+ unlinkSync4(path);
1033
1166
  } catch {
1034
1167
  }
1035
1168
  }
@@ -1039,7 +1172,7 @@ function pruneOrphanedEntries(path = manifestPath()) {
1039
1172
  const live = [];
1040
1173
  let pruned = 0;
1041
1174
  for (const e of m.entries) {
1042
- if (existsSync8(join11(e.installRoot, e.dirName))) {
1175
+ if (existsSync8(join12(e.installRoot, e.dirName))) {
1043
1176
  live.push(e);
1044
1177
  continue;
1045
1178
  }
@@ -1053,25 +1186,25 @@ function pruneOrphanedEntries(path = manifestPath()) {
1053
1186
 
1054
1187
  // dist/src/skillify/agent-roots.js
1055
1188
  import { existsSync as existsSync9 } from "node:fs";
1056
- import { homedir as homedir9 } from "node:os";
1057
- import { join as join12 } from "node:path";
1189
+ import { homedir as homedir10 } from "node:os";
1190
+ import { join as join13 } from "node:path";
1058
1191
  function resolveDetected(home) {
1059
1192
  const out = [];
1060
- const codexInstalled = existsSync9(join12(home, ".codex"));
1061
- const piInstalled = existsSync9(join12(home, ".pi", "agent"));
1062
- const hermesInstalled = existsSync9(join12(home, ".hermes"));
1193
+ const codexInstalled = existsSync9(join13(home, ".codex"));
1194
+ const piInstalled = existsSync9(join13(home, ".pi", "agent"));
1195
+ const hermesInstalled = existsSync9(join13(home, ".hermes"));
1063
1196
  if (codexInstalled || piInstalled) {
1064
- out.push(join12(home, ".agents", "skills"));
1197
+ out.push(join13(home, ".agents", "skills"));
1065
1198
  }
1066
1199
  if (hermesInstalled) {
1067
- out.push(join12(home, ".hermes", "skills"));
1200
+ out.push(join13(home, ".hermes", "skills"));
1068
1201
  }
1069
1202
  if (piInstalled) {
1070
- out.push(join12(home, ".pi", "agent", "skills"));
1203
+ out.push(join13(home, ".pi", "agent", "skills"));
1071
1204
  }
1072
1205
  return out;
1073
1206
  }
1074
- function detectAgentSkillsRoots(canonicalRoot, home = homedir9()) {
1207
+ function detectAgentSkillsRoots(canonicalRoot, home = homedir10()) {
1075
1208
  return resolveDetected(home).filter((p) => p !== canonicalRoot);
1076
1209
  }
1077
1210
 
@@ -1115,15 +1248,15 @@ function isMissingTableError(message) {
1115
1248
  }
1116
1249
  function resolvePullDestination(install, cwd) {
1117
1250
  if (install === "global")
1118
- return join13(homedir10(), ".claude", "skills");
1251
+ return join14(homedir11(), ".claude", "skills");
1119
1252
  if (!cwd)
1120
1253
  throw new Error("install=project requires a cwd");
1121
- return join13(cwd, ".claude", "skills");
1254
+ return join14(cwd, ".claude", "skills");
1122
1255
  }
1123
1256
  function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
1124
1257
  const out = [];
1125
1258
  for (const root of agentRoots) {
1126
- const link = join13(root, dirName);
1259
+ const link = join14(root, dirName);
1127
1260
  let existing;
1128
1261
  try {
1129
1262
  existing = lstatSync2(link);
@@ -1145,13 +1278,13 @@ function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
1145
1278
  continue;
1146
1279
  }
1147
1280
  try {
1148
- unlinkSync4(link);
1281
+ unlinkSync5(link);
1149
1282
  } catch {
1150
1283
  continue;
1151
1284
  }
1152
1285
  }
1153
1286
  try {
1154
- mkdirSync7(dirname5(link), { recursive: true });
1287
+ mkdirSync8(dirname5(link), { recursive: true });
1155
1288
  symlinkSync(canonicalDir, link, "dir");
1156
1289
  out.push(link);
1157
1290
  } catch {
@@ -1166,7 +1299,7 @@ function backfillSymlinks(installRoot) {
1166
1299
  return;
1167
1300
  const detected = detectAgentSkillsRoots(installRoot);
1168
1301
  for (const entry of entries) {
1169
- const canonical = join13(entry.installRoot, entry.dirName);
1302
+ const canonical = join14(entry.installRoot, entry.dirName);
1170
1303
  if (!existsSync10(canonical))
1171
1304
  continue;
1172
1305
  const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
@@ -1280,7 +1413,7 @@ function readLocalVersion(path) {
1280
1413
  if (!existsSync10(path))
1281
1414
  return null;
1282
1415
  try {
1283
- const text = readFileSync8(path, "utf-8");
1416
+ const text = readFileSync9(path, "utf-8");
1284
1417
  const parsed = parseFrontmatter(text);
1285
1418
  if (!parsed)
1286
1419
  return null;
@@ -1375,8 +1508,8 @@ async function runPull(opts) {
1375
1508
  summary.skipped++;
1376
1509
  continue;
1377
1510
  }
1378
- const skillDir = join13(root, dirName);
1379
- const skillFile = join13(skillDir, "SKILL.md");
1511
+ const skillDir = join14(root, dirName);
1512
+ const skillFile = join14(skillDir, "SKILL.md");
1380
1513
  const remoteVersion = Number(row.version ?? 1);
1381
1514
  const localVersion = readLocalVersion(skillFile);
1382
1515
  const action = decideAction({
@@ -1387,14 +1520,14 @@ async function runPull(opts) {
1387
1520
  });
1388
1521
  let manifestError;
1389
1522
  if (action === "wrote") {
1390
- mkdirSync7(skillDir, { recursive: true });
1523
+ mkdirSync8(skillDir, { recursive: true });
1391
1524
  if (existsSync10(skillFile)) {
1392
1525
  try {
1393
- renameSync3(skillFile, `${skillFile}.bak`);
1526
+ renameSync4(skillFile, `${skillFile}.bak`);
1394
1527
  } catch {
1395
1528
  }
1396
1529
  }
1397
- writeFileSync6(skillFile, renderSkillFile(row));
1530
+ writeFileSync7(skillFile, renderSkillFile(row));
1398
1531
  const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir, dirName, detectAgentSkillsRoots(root)) : [];
1399
1532
  try {
1400
1533
  recordPull({
@@ -1436,7 +1569,7 @@ async function runPull(opts) {
1436
1569
  }
1437
1570
 
1438
1571
  // dist/src/skillify/auto-pull.js
1439
- var log4 = (msg) => log("skillify-autopull", msg);
1572
+ var log5 = (msg) => log("skillify-autopull", msg);
1440
1573
  var DEFAULT_TIMEOUT_MS = 5e3;
1441
1574
  function withTimeout(p, ms) {
1442
1575
  let timer = null;
@@ -1452,13 +1585,13 @@ function withTimeout(p, ms) {
1452
1585
  }
1453
1586
  async function autoPullSkills(deps = {}) {
1454
1587
  if (process.env.HIVEMIND_AUTOPULL_DISABLED === "1") {
1455
- log4("disabled via HIVEMIND_AUTOPULL_DISABLED=1");
1588
+ log5("disabled via HIVEMIND_AUTOPULL_DISABLED=1");
1456
1589
  return { pulled: 0, skipped: true, reason: "disabled" };
1457
1590
  }
1458
1591
  const loadFn = deps.loadConfigFn ?? loadConfig;
1459
1592
  const config = loadFn();
1460
1593
  if (!config) {
1461
- log4("skipped: not logged in");
1594
+ log5("skipped: not logged in");
1462
1595
  return { pulled: 0, skipped: true, reason: "not-logged-in" };
1463
1596
  }
1464
1597
  let query;
@@ -1480,16 +1613,16 @@ async function autoPullSkills(deps = {}) {
1480
1613
  dryRun: false,
1481
1614
  force: false
1482
1615
  }), timeoutMs);
1483
- log4(`pulled scanned=${summary.scanned} wrote=${summary.wrote} skipped=${summary.skipped}`);
1616
+ log5(`pulled scanned=${summary.scanned} wrote=${summary.wrote} skipped=${summary.skipped}`);
1484
1617
  return { pulled: summary.wrote, skipped: false };
1485
1618
  } catch (e) {
1486
- log4(`pull failed (swallowed): ${e?.message ?? e}`);
1619
+ log5(`pull failed (swallowed): ${e?.message ?? e}`);
1487
1620
  return { pulled: 0, skipped: true, reason: "error" };
1488
1621
  }
1489
1622
  }
1490
1623
 
1491
1624
  // dist/src/hooks/hermes/session-start.js
1492
- var log5 = (msg) => log("hermes-session-start", msg);
1625
+ var log6 = (msg) => log("hermes-session-start", msg);
1493
1626
  var __bundleDir = dirname6(fileURLToPath2(import.meta.url));
1494
1627
  var context = `DEEPLAKE MEMORY: Persistent memory at ~/.deeplake/memory/ shared across sessions, users, and agents.
1495
1628
 
@@ -1560,14 +1693,14 @@ async function main() {
1560
1693
  await api.ensureTable();
1561
1694
  await api.ensureSessionsTable(config.sessionsTableName);
1562
1695
  await createPlaceholder(api, config.tableName, sessionId, cwd, config.userName, config.orgName, config.workspaceId, pluginVersion);
1563
- log5("placeholder created");
1696
+ log6("placeholder created");
1564
1697
  }
1565
1698
  } catch (e) {
1566
- log5(`placeholder failed: ${e.message}`);
1699
+ log6(`placeholder failed: ${e.message}`);
1567
1700
  }
1568
1701
  }
1569
1702
  const pullResult = await autoPullSkills();
1570
- log5(`autopull: pulled=${pullResult.pulled} skipped=${pullResult.skipped}`);
1703
+ log6(`autopull: pulled=${pullResult.pulled} skipped=${pullResult.skipped}`);
1571
1704
  let versionNotice = "";
1572
1705
  if (current)
1573
1706
  versionNotice = `
@@ -1581,6 +1714,6 @@ Not logged in to Deeplake. Run: hivemind login${localMinedNote}${versionNotice}`
1581
1714
  console.log(JSON.stringify({ context: additional }));
1582
1715
  }
1583
1716
  main().catch((e) => {
1584
- log5(`fatal: ${e.message}`);
1717
+ log6(`fatal: ${e.message}`);
1585
1718
  process.exit(0);
1586
1719
  });