@deeplake/hivemind 0.7.32 → 0.7.34

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.
Files changed (34) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/bundle/cli.js +332 -189
  4. package/codex/bundle/capture.js +365 -332
  5. package/codex/bundle/commands/auth-login.js +163 -30
  6. package/codex/bundle/pre-tool-use.js +334 -301
  7. package/codex/bundle/session-start-setup.js +193 -60
  8. package/codex/bundle/session-start.js +229 -87
  9. package/codex/bundle/shell/deeplake-shell.js +328 -295
  10. package/codex/bundle/skillify-worker.js +26 -18
  11. package/codex/bundle/stop.js +450 -394
  12. package/codex/bundle/wiki-worker.js +174 -292
  13. package/cursor/bundle/capture.js +448 -392
  14. package/cursor/bundle/commands/auth-login.js +163 -30
  15. package/cursor/bundle/pre-tool-use.js +324 -291
  16. package/cursor/bundle/session-end.js +43 -20
  17. package/cursor/bundle/session-start.js +272 -130
  18. package/cursor/bundle/shell/deeplake-shell.js +328 -295
  19. package/cursor/bundle/skillify-worker.js +26 -18
  20. package/cursor/bundle/wiki-worker.js +174 -292
  21. package/hermes/bundle/capture.js +448 -392
  22. package/hermes/bundle/commands/auth-login.js +163 -30
  23. package/hermes/bundle/pre-tool-use.js +324 -291
  24. package/hermes/bundle/session-end.js +43 -20
  25. package/hermes/bundle/session-start.js +269 -127
  26. package/hermes/bundle/shell/deeplake-shell.js +328 -295
  27. package/hermes/bundle/skillify-worker.js +26 -18
  28. package/hermes/bundle/wiki-worker.js +174 -292
  29. package/mcp/bundle/server.js +190 -57
  30. package/openclaw/dist/index.js +160 -32
  31. package/openclaw/dist/skillify-worker.js +26 -18
  32. package/openclaw/openclaw.plugin.json +1 -1
  33. package/openclaw/package.json +1 -1
  34. package/package.json +1 -1
@@ -17,21 +17,21 @@ __export(index_marker_store_exports, {
17
17
  hasFreshIndexMarker: () => hasFreshIndexMarker,
18
18
  writeIndexMarker: () => writeIndexMarker
19
19
  });
20
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
21
- import { join as join7 } from "node:path";
20
+ import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
21
+ import { join as join8 } from "node:path";
22
22
  import { tmpdir } from "node:os";
23
23
  function getIndexMarkerDir() {
24
- return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join7(tmpdir(), "hivemind-deeplake-indexes");
24
+ return process.env.HIVEMIND_INDEX_MARKER_DIR ?? join8(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 join7(getIndexMarkerDir(), `${markerKey}.json`);
28
+ return join8(getIndexMarkerDir(), `${markerKey}.json`);
29
29
  }
30
30
  function hasFreshIndexMarker(markerPath) {
31
31
  if (!existsSync4(markerPath))
32
32
  return false;
33
33
  try {
34
- const raw = JSON.parse(readFileSync5(markerPath, "utf-8"));
34
+ const raw = JSON.parse(readFileSync6(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
- mkdirSync4(getIndexMarkerDir(), { recursive: true });
45
- writeFileSync3(markerPath, JSON.stringify({ updatedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf-8");
44
+ mkdirSync5(getIndexMarkerDir(), { recursive: true });
45
+ writeFileSync4(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/session-start.js
56
56
  import { spawn as spawn2 } from "node:child_process";
57
57
  import { fileURLToPath as fileURLToPath2 } from "node:url";
58
- import { dirname as dirname6, join as join13 } from "node:path";
58
+ import { dirname as dirname7, join as join15 } from "node:path";
59
59
 
60
60
  // dist/src/commands/auth.js
61
61
  import { execSync } from "node:child_process";
@@ -89,13 +89,13 @@ function loadCredentials() {
89
89
 
90
90
  // dist/src/utils/stdin.js
91
91
  function readStdin() {
92
- return new Promise((resolve, reject) => {
92
+ return new Promise((resolve2, reject) => {
93
93
  let data = "";
94
94
  process.stdin.setEncoding("utf-8");
95
95
  process.stdin.on("data", (chunk) => data += chunk);
96
96
  process.stdin.on("end", () => {
97
97
  try {
98
- resolve(JSON.parse(data));
98
+ resolve2(JSON.parse(data));
99
99
  } catch (err) {
100
100
  reject(new Error(`Failed to parse hook input: ${err}`));
101
101
  }
@@ -339,6 +339,107 @@ function sqlIdent(name) {
339
339
  var SUMMARY_EMBEDDING_COL = "summary_embedding";
340
340
  var MESSAGE_EMBEDDING_COL = "message_embedding";
341
341
 
342
+ // dist/src/notifications/queue.js
343
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync, mkdirSync as mkdirSync4, openSync as openSync2, closeSync as closeSync2, unlinkSync as unlinkSync3, statSync as statSync2 } from "node:fs";
344
+ import { join as join7, resolve } from "node:path";
345
+ import { homedir as homedir6 } from "node:os";
346
+ import { setTimeout as sleep } from "node:timers/promises";
347
+ var log2 = (msg) => log("notifications-queue", msg);
348
+ var LOCK_RETRY_MAX = 50;
349
+ var LOCK_RETRY_BASE_MS = 5;
350
+ var LOCK_STALE_MS2 = 5e3;
351
+ function queuePath() {
352
+ return join7(homedir6(), ".deeplake", "notifications-queue.json");
353
+ }
354
+ function lockPath() {
355
+ return `${queuePath()}.lock`;
356
+ }
357
+ function readQueue() {
358
+ try {
359
+ const raw = readFileSync5(queuePath(), "utf-8");
360
+ const parsed = JSON.parse(raw);
361
+ if (!parsed || !Array.isArray(parsed.queue)) {
362
+ log2(`queue malformed \u2192 treating as empty`);
363
+ return { queue: [] };
364
+ }
365
+ return { queue: parsed.queue };
366
+ } catch {
367
+ return { queue: [] };
368
+ }
369
+ }
370
+ function _isQueuePathInsideHome(path, home) {
371
+ const r = resolve(path);
372
+ const h = resolve(home);
373
+ return r.startsWith(h + "/") || r === h;
374
+ }
375
+ function writeQueue(q) {
376
+ const path = queuePath();
377
+ const home = resolve(homedir6());
378
+ if (!_isQueuePathInsideHome(path, home)) {
379
+ throw new Error(`notifications-queue write blocked: ${path} is outside ${home}`);
380
+ }
381
+ mkdirSync4(join7(home, ".deeplake"), { recursive: true, mode: 448 });
382
+ const tmp = `${path}.${process.pid}.tmp`;
383
+ writeFileSync3(tmp, JSON.stringify(q, null, 2), { mode: 384 });
384
+ renameSync(tmp, path);
385
+ }
386
+ async function withQueueLock(fn) {
387
+ const path = lockPath();
388
+ mkdirSync4(join7(homedir6(), ".deeplake"), { recursive: true, mode: 448 });
389
+ let fd = null;
390
+ for (let attempt = 0; attempt < LOCK_RETRY_MAX; attempt++) {
391
+ try {
392
+ fd = openSync2(path, "wx", 384);
393
+ break;
394
+ } catch (e) {
395
+ const code = e.code;
396
+ if (code !== "EEXIST")
397
+ throw e;
398
+ try {
399
+ const age = Date.now() - statSync2(path).mtimeMs;
400
+ if (age > LOCK_STALE_MS2) {
401
+ unlinkSync3(path);
402
+ continue;
403
+ }
404
+ } catch {
405
+ }
406
+ const delay = LOCK_RETRY_BASE_MS * (attempt + 1);
407
+ await sleep(delay);
408
+ }
409
+ }
410
+ if (fd === null) {
411
+ log2(`lock acquisition gave up after ${LOCK_RETRY_MAX} attempts \u2014 proceeding unlocked (last-writer-wins)`);
412
+ return fn();
413
+ }
414
+ try {
415
+ return fn();
416
+ } finally {
417
+ try {
418
+ closeSync2(fd);
419
+ } catch {
420
+ }
421
+ try {
422
+ unlinkSync3(path);
423
+ } catch {
424
+ }
425
+ }
426
+ }
427
+ function sameDedupKey(a, b) {
428
+ if (a.id !== b.id)
429
+ return false;
430
+ return JSON.stringify(a.dedupKey) === JSON.stringify(b.dedupKey);
431
+ }
432
+ async function enqueueNotification(n) {
433
+ await withQueueLock(() => {
434
+ const q = readQueue();
435
+ if (q.queue.some((existing) => sameDedupKey(existing, n))) {
436
+ return;
437
+ }
438
+ q.queue.push(n);
439
+ writeQueue(q);
440
+ });
441
+ }
442
+
342
443
  // dist/src/deeplake-api.js
343
444
  var indexMarkerStorePromise = null;
344
445
  function getIndexMarkerStore() {
@@ -346,7 +447,7 @@ function getIndexMarkerStore() {
346
447
  indexMarkerStorePromise = Promise.resolve().then(() => (init_index_marker_store(), index_marker_store_exports));
347
448
  return indexMarkerStorePromise;
348
449
  }
349
- var log2 = (msg) => log("sdk", msg);
450
+ var log3 = (msg) => log("sdk", msg);
350
451
  function summarizeSql(sql, maxLen = 220) {
351
452
  const compact = sql.replace(/\s+/g, " ").trim();
352
453
  return compact.length > maxLen ? `${compact.slice(0, maxLen)}...` : compact;
@@ -358,7 +459,38 @@ function traceSql(msg) {
358
459
  process.stderr.write(`[deeplake-sql] ${msg}
359
460
  `);
360
461
  if (process.env.HIVEMIND_DEBUG === "1")
361
- log2(msg);
462
+ log3(msg);
463
+ }
464
+ var _signalledBalanceExhausted = false;
465
+ function maybeSignalBalanceExhausted(status, bodyText) {
466
+ if (status !== 402)
467
+ return;
468
+ if (!bodyText.includes("balance_cents"))
469
+ return;
470
+ if (_signalledBalanceExhausted)
471
+ return;
472
+ _signalledBalanceExhausted = true;
473
+ log3(`balance exhausted \u2014 enqueuing session-start banner (body=${bodyText.slice(0, 120)})`);
474
+ enqueueNotification({
475
+ id: "balance-exhausted",
476
+ severity: "warn",
477
+ transient: true,
478
+ title: "Hivemind credits exhausted \u2014 top up to keep capturing",
479
+ body: `Sessions are not being saved and memory recall is returning empty. Top up at ${billingUrl()} to restore capture and recall.`,
480
+ dedupKey: { reason: "balance-zero" }
481
+ }).catch((e) => {
482
+ log3(`enqueue balance-exhausted failed: ${e instanceof Error ? e.message : String(e)}`);
483
+ });
484
+ }
485
+ function billingUrl() {
486
+ try {
487
+ const c = loadCredentials();
488
+ if (c?.orgName && c?.workspaceId) {
489
+ return `https://deeplake.ai/${encodeURIComponent(c.orgName)}/workspace/${encodeURIComponent(c.workspaceId)}/billing`;
490
+ }
491
+ } catch {
492
+ }
493
+ return "https://deeplake.ai";
362
494
  }
363
495
  var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
364
496
  var MAX_RETRIES = 3;
@@ -367,8 +499,8 @@ var MAX_CONCURRENCY = 5;
367
499
  function getQueryTimeoutMs() {
368
500
  return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
369
501
  }
370
- function sleep(ms) {
371
- return new Promise((resolve) => setTimeout(resolve, ms));
502
+ function sleep2(ms) {
503
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
372
504
  }
373
505
  function isTimeoutError(error) {
374
506
  const name = error instanceof Error ? error.name.toLowerCase() : "";
@@ -398,7 +530,7 @@ var Semaphore = class {
398
530
  this.active++;
399
531
  return;
400
532
  }
401
- await new Promise((resolve) => this.waiting.push(resolve));
533
+ await new Promise((resolve2) => this.waiting.push(resolve2));
402
534
  }
403
535
  release() {
404
536
  this.active--;
@@ -469,8 +601,8 @@ var DeeplakeApi = class {
469
601
  lastError = e instanceof Error ? e : new Error(String(e));
470
602
  if (attempt < MAX_RETRIES) {
471
603
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
472
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
473
- await sleep(delay);
604
+ log3(`query retry ${attempt + 1}/${MAX_RETRIES} (fetch error: ${lastError.message}) in ${delay.toFixed(0)}ms`);
605
+ await sleep2(delay);
474
606
  continue;
475
607
  }
476
608
  throw lastError;
@@ -486,10 +618,11 @@ var DeeplakeApi = class {
486
618
  const alreadyExists = resp.status === 500 && isDuplicateIndexError(text);
487
619
  if (!alreadyExists && attempt < MAX_RETRIES && (RETRYABLE_CODES.has(resp.status) || retryable403)) {
488
620
  const delay = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200;
489
- log2(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
490
- await sleep(delay);
621
+ log3(`query retry ${attempt + 1}/${MAX_RETRIES} (${resp.status}) in ${delay.toFixed(0)}ms`);
622
+ await sleep2(delay);
491
623
  continue;
492
624
  }
625
+ maybeSignalBalanceExhausted(resp.status, text);
493
626
  throw new Error(`Query failed: ${resp.status}: ${text.slice(0, 200)}`);
494
627
  }
495
628
  throw lastError ?? new Error("Query failed: max retries exceeded");
@@ -510,7 +643,7 @@ var DeeplakeApi = class {
510
643
  const chunk = rows.slice(i, i + CONCURRENCY);
511
644
  await Promise.allSettled(chunk.map((r) => this.upsertRowSql(r)));
512
645
  }
513
- log2(`commit: ${rows.length} rows`);
646
+ log3(`commit: ${rows.length} rows`);
514
647
  }
515
648
  async upsertRowSql(row) {
516
649
  const ts = (/* @__PURE__ */ new Date()).toISOString();
@@ -566,7 +699,7 @@ var DeeplakeApi = class {
566
699
  markers.writeIndexMarker(markerPath);
567
700
  return;
568
701
  }
569
- log2(`index "${indexName}" skipped: ${e.message}`);
702
+ log3(`index "${indexName}" skipped: ${e.message}`);
570
703
  }
571
704
  }
572
705
  /**
@@ -656,13 +789,13 @@ var DeeplakeApi = class {
656
789
  };
657
790
  }
658
791
  if (attempt < MAX_RETRIES && RETRYABLE_CODES.has(resp.status)) {
659
- await sleep(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
792
+ await sleep2(BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 200);
660
793
  continue;
661
794
  }
662
795
  return { tables: [], cacheable: false };
663
796
  } catch {
664
797
  if (attempt < MAX_RETRIES) {
665
- await sleep(BASE_DELAY_MS * Math.pow(2, attempt));
798
+ await sleep2(BASE_DELAY_MS * Math.pow(2, attempt));
666
799
  continue;
667
800
  }
668
801
  return { tables: [], cacheable: false };
@@ -690,9 +823,9 @@ var DeeplakeApi = class {
690
823
  } catch (err) {
691
824
  lastErr = err;
692
825
  const msg = err instanceof Error ? err.message : String(err);
693
- log2(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
826
+ log3(`CREATE TABLE "${label}" attempt ${attempt + 1}/${OUTER_BACKOFFS_MS.length + 1} failed: ${msg}`);
694
827
  if (attempt < OUTER_BACKOFFS_MS.length) {
695
- await sleep(OUTER_BACKOFFS_MS[attempt]);
828
+ await sleep2(OUTER_BACKOFFS_MS[attempt]);
696
829
  }
697
830
  }
698
831
  }
@@ -703,9 +836,9 @@ var DeeplakeApi = class {
703
836
  const tbl = sqlIdent(name ?? this.tableName);
704
837
  const tables = await this.listTables();
705
838
  if (!tables.includes(tbl)) {
706
- log2(`table "${tbl}" not found, creating`);
839
+ log3(`table "${tbl}" not found, creating`);
707
840
  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);
708
- log2(`table "${tbl}" created`);
841
+ log3(`table "${tbl}" created`);
709
842
  if (!tables.includes(tbl))
710
843
  this._tablesCache = [...tables, tbl];
711
844
  }
@@ -718,9 +851,9 @@ var DeeplakeApi = class {
718
851
  const safe = sqlIdent(name);
719
852
  const tables = await this.listTables();
720
853
  if (!tables.includes(safe)) {
721
- log2(`table "${safe}" not found, creating`);
854
+ log3(`table "${safe}" not found, creating`);
722
855
  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);
723
- log2(`table "${safe}" created`);
856
+ log3(`table "${safe}" created`);
724
857
  if (!tables.includes(safe))
725
858
  this._tablesCache = [...tables, safe];
726
859
  }
@@ -743,9 +876,9 @@ var DeeplakeApi = class {
743
876
  const safe = sqlIdent(name);
744
877
  const tables = await this.listTables();
745
878
  if (!tables.includes(safe)) {
746
- log2(`table "${safe}" not found, creating`);
879
+ log3(`table "${safe}" not found, creating`);
747
880
  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);
748
- log2(`table "${safe}" created`);
881
+ log3(`table "${safe}" created`);
749
882
  if (!tables.includes(safe))
750
883
  this._tablesCache = [...tables, safe];
751
884
  }
@@ -754,14 +887,14 @@ var DeeplakeApi = class {
754
887
  };
755
888
 
756
889
  // dist/src/skillify/pull.js
757
- import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, renameSync as renameSync3, lstatSync as lstatSync2, readlinkSync, symlinkSync, unlinkSync as unlinkSync4 } from "node:fs";
890
+ import { existsSync as existsSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, renameSync as renameSync4, lstatSync as lstatSync2, readlinkSync, symlinkSync, unlinkSync as unlinkSync5 } from "node:fs";
758
891
  import { homedir as homedir10 } from "node:os";
759
- import { dirname as dirname5, join as join12 } from "node:path";
892
+ import { dirname as dirname6, join as join14 } from "node:path";
760
893
 
761
894
  // dist/src/skillify/skill-writer.js
762
- import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
763
- import { homedir as homedir6 } from "node:os";
764
- import { join as join8 } from "node:path";
895
+ import { existsSync as existsSync5, mkdirSync as mkdirSync6, readFileSync as readFileSync7, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync5 } from "node:fs";
896
+ import { homedir as homedir7 } from "node:os";
897
+ import { join as join9 } from "node:path";
765
898
  function assertValidSkillName(name) {
766
899
  if (typeof name !== "string" || name.length === 0) {
767
900
  throw new Error(`invalid skill name: empty or non-string`);
@@ -827,34 +960,43 @@ function parseFrontmatter(text) {
827
960
  }
828
961
 
829
962
  // dist/src/skillify/manifest.js
830
- import { existsSync as existsSync7, lstatSync, mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
963
+ import { existsSync as existsSync7, lstatSync, mkdirSync as mkdirSync7, readFileSync as readFileSync8, renameSync as renameSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
964
+ import { dirname as dirname5, join as join12 } from "node:path";
965
+
966
+ // dist/src/skillify/legacy-migration.js
967
+ import { existsSync as existsSync6, renameSync as renameSync2 } from "node:fs";
968
+ import { dirname as dirname4, join as join11 } from "node:path";
969
+
970
+ // dist/src/skillify/state-dir.js
831
971
  import { homedir as homedir8 } from "node:os";
832
- import { dirname as dirname4, join as join10 } from "node:path";
972
+ import { join as join10 } from "node:path";
973
+ function getStateDir() {
974
+ const override = process.env.HIVEMIND_STATE_DIR?.trim();
975
+ return override && override.length > 0 ? override : join10(homedir8(), ".deeplake", "state", "skillify");
976
+ }
833
977
 
834
978
  // dist/src/skillify/legacy-migration.js
835
- import { existsSync as existsSync6, renameSync } from "node:fs";
836
- import { homedir as homedir7 } from "node:os";
837
- import { join as join9 } from "node:path";
838
979
  var dlog = (msg) => log("skillify-migrate", msg);
839
980
  var attempted = false;
840
981
  function migrateLegacyStateDir() {
982
+ if (process.env.HIVEMIND_STATE_DIR?.trim())
983
+ return;
841
984
  if (attempted)
842
985
  return;
843
986
  attempted = true;
844
- const root = join9(homedir7(), ".deeplake", "state");
845
- const legacy = join9(root, "skilify");
846
- const current = join9(root, "skillify");
987
+ const current = getStateDir();
988
+ const legacy = join11(dirname4(current), "skilify");
847
989
  if (!existsSync6(legacy))
848
990
  return;
849
991
  if (existsSync6(current))
850
992
  return;
851
993
  try {
852
- renameSync(legacy, current);
994
+ renameSync2(legacy, current);
853
995
  dlog(`migrated ${legacy} -> ${current}`);
854
996
  } catch (err) {
855
997
  const code = err.code;
856
- if (code === "EXDEV" || code === "EPERM") {
857
- dlog(`migration failed (${code}); leaving legacy dir in place`);
998
+ if (code === "EXDEV" || code === "EPERM" || code === "ENOENT" || code === "EEXIST" || code === "ENOTEMPTY") {
999
+ dlog(`migration skipped (${code}); legacy dir left as-is or another process handled it`);
858
1000
  return;
859
1001
  }
860
1002
  throw err;
@@ -866,7 +1008,7 @@ function emptyManifest() {
866
1008
  return { version: 1, entries: [] };
867
1009
  }
868
1010
  function manifestPath() {
869
- return join10(homedir8(), ".deeplake", "state", "skillify", "pulled.json");
1011
+ return join12(getStateDir(), "pulled.json");
870
1012
  }
871
1013
  function loadManifest(path = manifestPath()) {
872
1014
  migrateLegacyStateDir();
@@ -874,7 +1016,7 @@ function loadManifest(path = manifestPath()) {
874
1016
  return emptyManifest();
875
1017
  let raw;
876
1018
  try {
877
- raw = readFileSync7(path, "utf-8");
1019
+ raw = readFileSync8(path, "utf-8");
878
1020
  } catch {
879
1021
  return emptyManifest();
880
1022
  }
@@ -921,10 +1063,10 @@ function loadManifest(path = manifestPath()) {
921
1063
  }
922
1064
  function saveManifest(m, path = manifestPath()) {
923
1065
  migrateLegacyStateDir();
924
- mkdirSync6(dirname4(path), { recursive: true });
1066
+ mkdirSync7(dirname5(path), { recursive: true });
925
1067
  const tmp = `${path}.tmp`;
926
- writeFileSync5(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
927
- renameSync2(tmp, path);
1068
+ writeFileSync6(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
1069
+ renameSync3(tmp, path);
928
1070
  }
929
1071
  function recordPull(entry, path = manifestPath()) {
930
1072
  const m = loadManifest(path);
@@ -949,7 +1091,7 @@ function unlinkSymlinks(paths) {
949
1091
  if (!st.isSymbolicLink())
950
1092
  continue;
951
1093
  try {
952
- unlinkSync3(path);
1094
+ unlinkSync4(path);
953
1095
  } catch {
954
1096
  }
955
1097
  }
@@ -959,7 +1101,7 @@ function pruneOrphanedEntries(path = manifestPath()) {
959
1101
  const live = [];
960
1102
  let pruned = 0;
961
1103
  for (const e of m.entries) {
962
- if (existsSync7(join10(e.installRoot, e.dirName))) {
1104
+ if (existsSync7(join12(e.installRoot, e.dirName))) {
963
1105
  live.push(e);
964
1106
  continue;
965
1107
  }
@@ -974,20 +1116,20 @@ function pruneOrphanedEntries(path = manifestPath()) {
974
1116
  // dist/src/skillify/agent-roots.js
975
1117
  import { existsSync as existsSync8 } from "node:fs";
976
1118
  import { homedir as homedir9 } from "node:os";
977
- import { join as join11 } from "node:path";
1119
+ import { join as join13 } from "node:path";
978
1120
  function resolveDetected(home) {
979
1121
  const out = [];
980
- const codexInstalled = existsSync8(join11(home, ".codex"));
981
- const piInstalled = existsSync8(join11(home, ".pi", "agent"));
982
- const hermesInstalled = existsSync8(join11(home, ".hermes"));
1122
+ const codexInstalled = existsSync8(join13(home, ".codex"));
1123
+ const piInstalled = existsSync8(join13(home, ".pi", "agent"));
1124
+ const hermesInstalled = existsSync8(join13(home, ".hermes"));
983
1125
  if (codexInstalled || piInstalled) {
984
- out.push(join11(home, ".agents", "skills"));
1126
+ out.push(join13(home, ".agents", "skills"));
985
1127
  }
986
1128
  if (hermesInstalled) {
987
- out.push(join11(home, ".hermes", "skills"));
1129
+ out.push(join13(home, ".hermes", "skills"));
988
1130
  }
989
1131
  if (piInstalled) {
990
- out.push(join11(home, ".pi", "agent", "skills"));
1132
+ out.push(join13(home, ".pi", "agent", "skills"));
991
1133
  }
992
1134
  return out;
993
1135
  }
@@ -1035,15 +1177,15 @@ function isMissingTableError(message) {
1035
1177
  }
1036
1178
  function resolvePullDestination(install, cwd) {
1037
1179
  if (install === "global")
1038
- return join12(homedir10(), ".claude", "skills");
1180
+ return join14(homedir10(), ".claude", "skills");
1039
1181
  if (!cwd)
1040
1182
  throw new Error("install=project requires a cwd");
1041
- return join12(cwd, ".claude", "skills");
1183
+ return join14(cwd, ".claude", "skills");
1042
1184
  }
1043
1185
  function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
1044
1186
  const out = [];
1045
1187
  for (const root of agentRoots) {
1046
- const link = join12(root, dirName);
1188
+ const link = join14(root, dirName);
1047
1189
  let existing;
1048
1190
  try {
1049
1191
  existing = lstatSync2(link);
@@ -1065,13 +1207,13 @@ function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
1065
1207
  continue;
1066
1208
  }
1067
1209
  try {
1068
- unlinkSync4(link);
1210
+ unlinkSync5(link);
1069
1211
  } catch {
1070
1212
  continue;
1071
1213
  }
1072
1214
  }
1073
1215
  try {
1074
- mkdirSync7(dirname5(link), { recursive: true });
1216
+ mkdirSync8(dirname6(link), { recursive: true });
1075
1217
  symlinkSync(canonicalDir, link, "dir");
1076
1218
  out.push(link);
1077
1219
  } catch {
@@ -1086,7 +1228,7 @@ function backfillSymlinks(installRoot) {
1086
1228
  return;
1087
1229
  const detected = detectAgentSkillsRoots(installRoot);
1088
1230
  for (const entry of entries) {
1089
- const canonical = join12(entry.installRoot, entry.dirName);
1231
+ const canonical = join14(entry.installRoot, entry.dirName);
1090
1232
  if (!existsSync9(canonical))
1091
1233
  continue;
1092
1234
  const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
@@ -1200,7 +1342,7 @@ function readLocalVersion(path) {
1200
1342
  if (!existsSync9(path))
1201
1343
  return null;
1202
1344
  try {
1203
- const text = readFileSync8(path, "utf-8");
1345
+ const text = readFileSync9(path, "utf-8");
1204
1346
  const parsed = parseFrontmatter(text);
1205
1347
  if (!parsed)
1206
1348
  return null;
@@ -1295,8 +1437,8 @@ async function runPull(opts) {
1295
1437
  summary.skipped++;
1296
1438
  continue;
1297
1439
  }
1298
- const skillDir = join12(root, dirName);
1299
- const skillFile = join12(skillDir, "SKILL.md");
1440
+ const skillDir = join14(root, dirName);
1441
+ const skillFile = join14(skillDir, "SKILL.md");
1300
1442
  const remoteVersion = Number(row.version ?? 1);
1301
1443
  const localVersion = readLocalVersion(skillFile);
1302
1444
  const action = decideAction({
@@ -1307,14 +1449,14 @@ async function runPull(opts) {
1307
1449
  });
1308
1450
  let manifestError;
1309
1451
  if (action === "wrote") {
1310
- mkdirSync7(skillDir, { recursive: true });
1452
+ mkdirSync8(skillDir, { recursive: true });
1311
1453
  if (existsSync9(skillFile)) {
1312
1454
  try {
1313
- renameSync3(skillFile, `${skillFile}.bak`);
1455
+ renameSync4(skillFile, `${skillFile}.bak`);
1314
1456
  } catch {
1315
1457
  }
1316
1458
  }
1317
- writeFileSync6(skillFile, renderSkillFile(row));
1459
+ writeFileSync7(skillFile, renderSkillFile(row));
1318
1460
  const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir, dirName, detectAgentSkillsRoots(root)) : [];
1319
1461
  try {
1320
1462
  recordPull({
@@ -1356,7 +1498,7 @@ async function runPull(opts) {
1356
1498
  }
1357
1499
 
1358
1500
  // dist/src/skillify/auto-pull.js
1359
- var log3 = (msg) => log("skillify-autopull", msg);
1501
+ var log4 = (msg) => log("skillify-autopull", msg);
1360
1502
  var DEFAULT_TIMEOUT_MS = 5e3;
1361
1503
  function withTimeout(p, ms) {
1362
1504
  let timer = null;
@@ -1372,13 +1514,13 @@ function withTimeout(p, ms) {
1372
1514
  }
1373
1515
  async function autoPullSkills(deps = {}) {
1374
1516
  if (process.env.HIVEMIND_AUTOPULL_DISABLED === "1") {
1375
- log3("disabled via HIVEMIND_AUTOPULL_DISABLED=1");
1517
+ log4("disabled via HIVEMIND_AUTOPULL_DISABLED=1");
1376
1518
  return { pulled: 0, skipped: true, reason: "disabled" };
1377
1519
  }
1378
1520
  const loadFn = deps.loadConfigFn ?? loadConfig;
1379
1521
  const config = loadFn();
1380
1522
  if (!config) {
1381
- log3("skipped: not logged in");
1523
+ log4("skipped: not logged in");
1382
1524
  return { pulled: 0, skipped: true, reason: "not-logged-in" };
1383
1525
  }
1384
1526
  let query;
@@ -1400,31 +1542,31 @@ async function autoPullSkills(deps = {}) {
1400
1542
  dryRun: false,
1401
1543
  force: false
1402
1544
  }), timeoutMs);
1403
- log3(`pulled scanned=${summary.scanned} wrote=${summary.wrote} skipped=${summary.skipped}`);
1545
+ log4(`pulled scanned=${summary.scanned} wrote=${summary.wrote} skipped=${summary.skipped}`);
1404
1546
  return { pulled: summary.wrote, skipped: false };
1405
1547
  } catch (e) {
1406
- log3(`pull failed (swallowed): ${e?.message ?? e}`);
1548
+ log4(`pull failed (swallowed): ${e?.message ?? e}`);
1407
1549
  return { pulled: 0, skipped: true, reason: "error" };
1408
1550
  }
1409
1551
  }
1410
1552
 
1411
1553
  // dist/src/hooks/codex/session-start.js
1412
- var log4 = (msg) => log("codex-session-start", msg);
1413
- var __bundleDir = dirname6(fileURLToPath2(import.meta.url));
1554
+ var log5 = (msg) => log("codex-session-start", msg);
1555
+ var __bundleDir = dirname7(fileURLToPath2(import.meta.url));
1414
1556
  async function main() {
1415
1557
  if (process.env.HIVEMIND_WIKI_WORKER === "1")
1416
1558
  return;
1417
1559
  const input = await readStdin();
1418
1560
  const creds = loadCredentials();
1419
1561
  if (!creds?.token) {
1420
- log4("no credentials found \u2014 run auth login to authenticate");
1562
+ log5("no credentials found \u2014 run auth login to authenticate");
1421
1563
  const auto = maybeAutoMineLocal();
1422
- log4(`auto-mine: ${auto.triggered ? "triggered (background)" : `skipped (${auto.reason})`}`);
1564
+ log5(`auto-mine: ${auto.triggered ? "triggered (background)" : `skipped (${auto.reason})`}`);
1423
1565
  } else {
1424
- log4(`credentials loaded: org=${creds.orgName ?? creds.orgId}`);
1566
+ log5(`credentials loaded: org=${creds.orgName ?? creds.orgId}`);
1425
1567
  }
1426
1568
  if (creds?.token) {
1427
- const setupScript = join13(__bundleDir, "session-start-setup.js");
1569
+ const setupScript = join15(__bundleDir, "session-start-setup.js");
1428
1570
  const child = spawn2("node", [setupScript], {
1429
1571
  detached: true,
1430
1572
  stdio: ["pipe", "ignore", "ignore"],
@@ -1433,10 +1575,10 @@ async function main() {
1433
1575
  child.stdin?.write(JSON.stringify(input));
1434
1576
  child.stdin?.end();
1435
1577
  child.unref();
1436
- log4("spawned async setup process");
1578
+ log5("spawned async setup process");
1437
1579
  }
1438
1580
  const pullResult = await autoPullSkills();
1439
- log4(`autopull: pulled=${pullResult.pulled} skipped=${pullResult.skipped}`);
1581
+ log5(`autopull: pulled=${pullResult.pulled} skipped=${pullResult.skipped}`);
1440
1582
  let versionNotice = "";
1441
1583
  const current = getInstalledVersion(__bundleDir, ".codex-plugin");
1442
1584
  if (current) {
@@ -1458,6 +1600,6 @@ Hivemind v${current}`;
1458
1600
  console.log(JSON.stringify(output));
1459
1601
  }
1460
1602
  main().catch((e) => {
1461
- log4(`fatal: ${e.message}`);
1603
+ log5(`fatal: ${e.message}`);
1462
1604
  process.exit(0);
1463
1605
  });