@deeplake/hivemind 0.7.12 → 0.7.13

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.
@@ -6,13 +6,13 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
9
- "version": "0.7.12"
9
+ "version": "0.7.13"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "hivemind",
14
14
  "description": "Persistent shared memory powered by Deeplake — captures all session activity and provides cross-session, cross-agent memory search",
15
- "version": "0.7.12",
15
+ "version": "0.7.13",
16
16
  "source": "./claude-code",
17
17
  "homepage": "https://github.com/activeloopai/hivemind"
18
18
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hivemind",
3
3
  "description": "Cloud-backed persistent memory powered by Deeplake — read, write, and share memory across Claude Code sessions and agents",
4
- "version": "0.7.12",
4
+ "version": "0.7.13",
5
5
  "author": {
6
6
  "name": "Activeloop",
7
7
  "url": "https://deeplake.ai"
@@ -53,9 +53,7 @@ var init_index_marker_store = __esm({
53
53
  });
54
54
 
55
55
  // dist/src/hooks/codex/session-start-setup.js
56
- import { fileURLToPath } from "node:url";
57
- import { dirname as dirname2, join as join7 } from "node:path";
58
- import { execSync as execSync2 } from "node:child_process";
56
+ import { join as join7 } from "node:path";
59
57
  import { homedir as homedir4 } from "node:os";
60
58
 
61
59
  // dist/src/commands/auth.js
@@ -585,71 +583,11 @@ function readStdin() {
585
583
  });
586
584
  }
587
585
 
588
- // dist/src/utils/version-check.js
589
- import { readFileSync as readFileSync4 } from "node:fs";
590
- import { dirname, join as join5 } from "node:path";
591
- var GITHUB_RAW_PKG = "https://raw.githubusercontent.com/activeloopai/hivemind/main/package.json";
592
- function getInstalledVersion(bundleDir, pluginManifestDir) {
593
- try {
594
- const pluginJson = join5(bundleDir, "..", pluginManifestDir, "plugin.json");
595
- const plugin = JSON.parse(readFileSync4(pluginJson, "utf-8"));
596
- if (plugin.version)
597
- return plugin.version;
598
- } catch {
599
- }
600
- try {
601
- const stamp = readFileSync4(join5(bundleDir, "..", ".hivemind_version"), "utf-8").trim();
602
- if (stamp)
603
- return stamp;
604
- } catch {
605
- }
606
- const HIVEMIND_PKG_NAMES = /* @__PURE__ */ new Set([
607
- "hivemind",
608
- "hivemind-codex",
609
- "@deeplake/hivemind",
610
- "@deeplake/hivemind-codex",
611
- "@activeloop/hivemind",
612
- "@activeloop/hivemind-codex"
613
- ]);
614
- let dir = bundleDir;
615
- for (let i = 0; i < 5; i++) {
616
- const candidate = join5(dir, "package.json");
617
- try {
618
- const pkg = JSON.parse(readFileSync4(candidate, "utf-8"));
619
- if (HIVEMIND_PKG_NAMES.has(pkg.name) && pkg.version)
620
- return pkg.version;
621
- } catch {
622
- }
623
- const parent = dirname(dir);
624
- if (parent === dir)
625
- break;
626
- dir = parent;
627
- }
628
- return null;
629
- }
630
- async function getLatestVersion(timeoutMs = 3e3) {
631
- try {
632
- const res = await fetch(GITHUB_RAW_PKG, { signal: AbortSignal.timeout(timeoutMs) });
633
- if (!res.ok)
634
- return null;
635
- const pkg = await res.json();
636
- return pkg.version ?? null;
637
- } catch {
638
- return null;
639
- }
640
- }
641
- function isNewer(latest, current) {
642
- const parse = (v) => v.split(".").map(Number);
643
- const [la, lb, lc] = parse(latest);
644
- const [ca, cb, cc] = parse(current);
645
- return la > ca || la === ca && lb > cb || la === ca && lb === cb && lc > cc;
646
- }
647
-
648
586
  // dist/src/utils/wiki-log.js
649
587
  import { mkdirSync as mkdirSync3, appendFileSync as appendFileSync2 } from "node:fs";
650
- import { join as join6 } from "node:path";
588
+ import { join as join5 } from "node:path";
651
589
  function makeWikiLogger(hooksDir, filename = "deeplake-wiki.log") {
652
- const path = join6(hooksDir, filename);
590
+ const path = join5(hooksDir, filename);
653
591
  return {
654
592
  path,
655
593
  log(msg) {
@@ -663,9 +601,61 @@ function makeWikiLogger(hooksDir, filename = "deeplake-wiki.log") {
663
601
  };
664
602
  }
665
603
 
604
+ // dist/src/hooks/shared/autoupdate.js
605
+ import { spawn } from "node:child_process";
606
+ import { existsSync as existsSync3 } from "node:fs";
607
+ import { join as join6 } from "node:path";
608
+ var log3 = (msg) => log("autoupdate", msg);
609
+ var defaultSpawn = (cmd, args) => {
610
+ const child = spawn(cmd, args, {
611
+ detached: true,
612
+ stdio: "ignore"
613
+ });
614
+ child.unref();
615
+ child.on("error", () => {
616
+ });
617
+ return { pid: child.pid };
618
+ };
619
+ function findHivemindOnPath() {
620
+ const PATH = process.env.PATH ?? "";
621
+ const dirs = PATH.split(":").filter(Boolean);
622
+ for (const dir of dirs) {
623
+ const candidate = join6(dir, "hivemind");
624
+ if (existsSync3(candidate))
625
+ return candidate;
626
+ }
627
+ return null;
628
+ }
629
+ async function autoUpdate(creds, opts) {
630
+ const t0 = Date.now();
631
+ log3(`agent=${opts.agent} entered`);
632
+ if (!creds?.token) {
633
+ log3(`agent=${opts.agent} skip: no creds.token (${Date.now() - t0}ms)`);
634
+ return;
635
+ }
636
+ if (creds.autoupdate === false) {
637
+ log3(`agent=${opts.agent} skip: autoupdate=false (${Date.now() - t0}ms)`);
638
+ return;
639
+ }
640
+ const binaryPath = opts.hivemindBinaryPath !== void 0 ? opts.hivemindBinaryPath : findHivemindOnPath();
641
+ if (!binaryPath) {
642
+ log3(`agent=${opts.agent} skip: hivemind binary not on PATH (${Date.now() - t0}ms)`);
643
+ return;
644
+ }
645
+ log3(`agent=${opts.agent} binary=${binaryPath} \u2192 dispatching detached update`);
646
+ const spawnFn = opts.spawn ?? defaultSpawn;
647
+ let pid;
648
+ try {
649
+ pid = spawnFn(binaryPath, ["update"]).pid;
650
+ } catch (e) {
651
+ log3(`agent=${opts.agent} dispatch threw: ${e?.message ?? e} (${Date.now() - t0}ms)`);
652
+ return;
653
+ }
654
+ log3(`agent=${opts.agent} dispatched (pid=${pid ?? "?"}) (${Date.now() - t0}ms total)`);
655
+ }
656
+
666
657
  // dist/src/hooks/codex/session-start-setup.js
667
- var log3 = (msg) => log("codex-session-setup", msg);
668
- var __bundleDir = dirname2(fileURLToPath(import.meta.url));
658
+ var log4 = (msg) => log("codex-session-setup", msg);
669
659
  var { log: wikiLog } = makeWikiLogger(join7(homedir4(), ".codex", "hooks"));
670
660
  async function createPlaceholder(api, table, sessionId, cwd, userName, orgName, workspaceId) {
671
661
  const summaryPath = `/summaries/${userName}/${sessionId}.md`;
@@ -695,7 +685,7 @@ async function main() {
695
685
  const input = await readStdin();
696
686
  const creds = loadCredentials();
697
687
  if (!creds?.token) {
698
- log3("no credentials");
688
+ log4("no credentials");
699
689
  return;
700
690
  }
701
691
  if (!creds.userName) {
@@ -703,10 +693,11 @@ async function main() {
703
693
  const { userInfo: userInfo2 } = await import("node:os");
704
694
  creds.userName = userInfo2().username ?? "unknown";
705
695
  saveCredentials(creds);
706
- log3(`backfilled userName: ${creds.userName}`);
696
+ log4(`backfilled userName: ${creds.userName}`);
707
697
  } catch {
708
698
  }
709
699
  }
700
+ await autoUpdate(creds, { agent: "codex" });
710
701
  const captureEnabled = process.env.HIVEMIND_CAPTURE !== "false";
711
702
  if (input.session_id) {
712
703
  try {
@@ -718,49 +709,15 @@ async function main() {
718
709
  if (captureEnabled) {
719
710
  await createPlaceholder(api, config.tableName, input.session_id, input.cwd ?? "", config.userName, config.orgName, config.workspaceId);
720
711
  }
721
- log3("setup complete");
712
+ log4("setup complete");
722
713
  }
723
714
  } catch (e) {
724
- log3(`setup failed: ${e.message}`);
715
+ log4(`setup failed: ${e.message}`);
725
716
  wikiLog(`SessionSetup: failed for ${input.session_id}: ${e.message}`);
726
717
  }
727
718
  }
728
- const autoupdate = creds.autoupdate !== false;
729
- try {
730
- const current = getInstalledVersion(__bundleDir, ".codex-plugin");
731
- if (current) {
732
- const latest = await getLatestVersion();
733
- if (latest && isNewer(latest, current)) {
734
- if (autoupdate) {
735
- log3(`autoupdate: updating ${current} \u2192 ${latest}`);
736
- try {
737
- const tag = `v${latest}`;
738
- if (!/^v\d+\.\d+\.\d+$/.test(tag))
739
- throw new Error(`unsafe version tag: ${tag}`);
740
- const findCmd = `INSTALL_DIR=""; CACHE_DIR=$(find ~/.codex/plugins/cache -maxdepth 3 -name "hivemind" -type d 2>/dev/null | head -1); if [ -n "$CACHE_DIR" ]; then INSTALL_DIR=$(ls -1d "$CACHE_DIR"/*/ 2>/dev/null | tail -1); elif [ -d ~/.codex/hivemind ]; then INSTALL_DIR=~/.codex/hivemind; fi; if [ -n "$INSTALL_DIR" ]; then TMPDIR=$(mktemp -d); git clone --depth 1 --branch ${tag} -q https://github.com/activeloopai/hivemind.git "$TMPDIR/hivemind" 2>/dev/null && cp -r "$TMPDIR/hivemind/codex/"* "$INSTALL_DIR/" 2>/dev/null; rm -rf "$TMPDIR"; fi`;
741
- execSync2(findCmd, { stdio: "ignore", timeout: 6e4 });
742
- process.stderr.write(`Hivemind auto-updated: ${current} \u2192 ${latest}. Restart Codex to apply.
743
- `);
744
- log3(`autoupdate succeeded: ${current} \u2192 ${latest} (tag: ${tag})`);
745
- } catch (e) {
746
- process.stderr.write(`Hivemind update available: ${current} \u2192 ${latest}. Auto-update failed.
747
- `);
748
- log3(`autoupdate failed: ${e.message}`);
749
- }
750
- } else {
751
- process.stderr.write(`Hivemind update available: ${current} \u2192 ${latest}.
752
- `);
753
- log3(`update available (autoupdate off): ${current} \u2192 ${latest}`);
754
- }
755
- } else {
756
- log3(`version up to date: ${current}`);
757
- }
758
- }
759
- } catch (e) {
760
- log3(`version check failed: ${e.message}`);
761
- }
762
719
  }
763
720
  main().catch((e) => {
764
- log3(`fatal: ${e.message}`);
721
+ log4(`fatal: ${e.message}`);
765
722
  process.exit(0);
766
723
  });
@@ -618,8 +618,61 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
618
618
  return null;
619
619
  }
620
620
 
621
+ // dist/src/hooks/shared/autoupdate.js
622
+ import { spawn } from "node:child_process";
623
+ import { existsSync as existsSync3 } from "node:fs";
624
+ import { join as join6 } from "node:path";
625
+ var log3 = (msg) => log("autoupdate", msg);
626
+ var defaultSpawn = (cmd, args) => {
627
+ const child = spawn(cmd, args, {
628
+ detached: true,
629
+ stdio: "ignore"
630
+ });
631
+ child.unref();
632
+ child.on("error", () => {
633
+ });
634
+ return { pid: child.pid };
635
+ };
636
+ function findHivemindOnPath() {
637
+ const PATH = process.env.PATH ?? "";
638
+ const dirs = PATH.split(":").filter(Boolean);
639
+ for (const dir of dirs) {
640
+ const candidate = join6(dir, "hivemind");
641
+ if (existsSync3(candidate))
642
+ return candidate;
643
+ }
644
+ return null;
645
+ }
646
+ async function autoUpdate(creds, opts) {
647
+ const t0 = Date.now();
648
+ log3(`agent=${opts.agent} entered`);
649
+ if (!creds?.token) {
650
+ log3(`agent=${opts.agent} skip: no creds.token (${Date.now() - t0}ms)`);
651
+ return;
652
+ }
653
+ if (creds.autoupdate === false) {
654
+ log3(`agent=${opts.agent} skip: autoupdate=false (${Date.now() - t0}ms)`);
655
+ return;
656
+ }
657
+ const binaryPath = opts.hivemindBinaryPath !== void 0 ? opts.hivemindBinaryPath : findHivemindOnPath();
658
+ if (!binaryPath) {
659
+ log3(`agent=${opts.agent} skip: hivemind binary not on PATH (${Date.now() - t0}ms)`);
660
+ return;
661
+ }
662
+ log3(`agent=${opts.agent} binary=${binaryPath} \u2192 dispatching detached update`);
663
+ const spawnFn = opts.spawn ?? defaultSpawn;
664
+ let pid;
665
+ try {
666
+ pid = spawnFn(binaryPath, ["update"]).pid;
667
+ } catch (e) {
668
+ log3(`agent=${opts.agent} dispatch threw: ${e?.message ?? e} (${Date.now() - t0}ms)`);
669
+ return;
670
+ }
671
+ log3(`agent=${opts.agent} dispatched (pid=${pid ?? "?"}) (${Date.now() - t0}ms total)`);
672
+ }
673
+
621
674
  // dist/src/hooks/cursor/session-start.js
622
- var log3 = (msg) => log("cursor-session-start", msg);
675
+ var log4 = (msg) => log("cursor-session-start", msg);
623
676
  var __bundleDir = dirname2(fileURLToPath(import.meta.url));
624
677
  var context = `DEEPLAKE MEMORY: Persistent memory at ~/.deeplake/memory/ shared across sessions, users, and agents.
625
678
 
@@ -689,10 +742,11 @@ async function main() {
689
742
  const cwd = resolveCwd(input);
690
743
  const creds = loadCredentials();
691
744
  if (!creds?.token) {
692
- log3("no credentials found");
745
+ log4("no credentials found");
693
746
  } else {
694
- log3(`credentials loaded: org=${creds.orgName ?? creds.orgId}`);
747
+ log4(`credentials loaded: org=${creds.orgName ?? creds.orgId}`);
695
748
  }
749
+ await autoUpdate(creds, { agent: "cursor" });
696
750
  const captureEnabled = process.env.HIVEMIND_CAPTURE !== "false";
697
751
  if (creds?.token && captureEnabled) {
698
752
  try {
@@ -704,10 +758,10 @@ async function main() {
704
758
  await api.ensureTable();
705
759
  await api.ensureSessionsTable(sessionsTable);
706
760
  await createPlaceholder(api, table, sessionId, cwd, config.userName, config.orgName, config.workspaceId);
707
- log3("placeholder created");
761
+ log4("placeholder created");
708
762
  }
709
763
  } catch (e) {
710
- log3(`placeholder failed: ${e.message}`);
764
+ log4(`placeholder failed: ${e.message}`);
711
765
  }
712
766
  }
713
767
  let versionNotice = "";
@@ -721,6 +775,6 @@ Not logged in to Deeplake. Run: hivemind login${versionNotice}`;
721
775
  console.log(JSON.stringify({ additional_context: additionalContext }));
722
776
  }
723
777
  main().catch((e) => {
724
- log3(`fatal: ${e.message}`);
778
+ log4(`fatal: ${e.message}`);
725
779
  process.exit(0);
726
780
  });
@@ -617,8 +617,61 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
617
617
  return null;
618
618
  }
619
619
 
620
+ // dist/src/hooks/shared/autoupdate.js
621
+ import { spawn } from "node:child_process";
622
+ import { existsSync as existsSync3 } from "node:fs";
623
+ import { join as join6 } from "node:path";
624
+ var log3 = (msg) => log("autoupdate", msg);
625
+ var defaultSpawn = (cmd, args) => {
626
+ const child = spawn(cmd, args, {
627
+ detached: true,
628
+ stdio: "ignore"
629
+ });
630
+ child.unref();
631
+ child.on("error", () => {
632
+ });
633
+ return { pid: child.pid };
634
+ };
635
+ function findHivemindOnPath() {
636
+ const PATH = process.env.PATH ?? "";
637
+ const dirs = PATH.split(":").filter(Boolean);
638
+ for (const dir of dirs) {
639
+ const candidate = join6(dir, "hivemind");
640
+ if (existsSync3(candidate))
641
+ return candidate;
642
+ }
643
+ return null;
644
+ }
645
+ async function autoUpdate(creds, opts) {
646
+ const t0 = Date.now();
647
+ log3(`agent=${opts.agent} entered`);
648
+ if (!creds?.token) {
649
+ log3(`agent=${opts.agent} skip: no creds.token (${Date.now() - t0}ms)`);
650
+ return;
651
+ }
652
+ if (creds.autoupdate === false) {
653
+ log3(`agent=${opts.agent} skip: autoupdate=false (${Date.now() - t0}ms)`);
654
+ return;
655
+ }
656
+ const binaryPath = opts.hivemindBinaryPath !== void 0 ? opts.hivemindBinaryPath : findHivemindOnPath();
657
+ if (!binaryPath) {
658
+ log3(`agent=${opts.agent} skip: hivemind binary not on PATH (${Date.now() - t0}ms)`);
659
+ return;
660
+ }
661
+ log3(`agent=${opts.agent} binary=${binaryPath} \u2192 dispatching detached update`);
662
+ const spawnFn = opts.spawn ?? defaultSpawn;
663
+ let pid;
664
+ try {
665
+ pid = spawnFn(binaryPath, ["update"]).pid;
666
+ } catch (e) {
667
+ log3(`agent=${opts.agent} dispatch threw: ${e?.message ?? e} (${Date.now() - t0}ms)`);
668
+ return;
669
+ }
670
+ log3(`agent=${opts.agent} dispatched (pid=${pid ?? "?"}) (${Date.now() - t0}ms total)`);
671
+ }
672
+
620
673
  // dist/src/hooks/hermes/session-start.js
621
- var log3 = (msg) => log("hermes-session-start", msg);
674
+ var log4 = (msg) => log("hermes-session-start", msg);
622
675
  var __bundleDir = dirname2(fileURLToPath(import.meta.url));
623
676
  var context = `DEEPLAKE MEMORY: Persistent memory at ~/.deeplake/memory/ shared across sessions, users, and agents.
624
677
 
@@ -679,6 +732,7 @@ async function main() {
679
732
  const cwd = input.cwd ?? process.cwd();
680
733
  const creds = loadCredentials();
681
734
  const captureEnabled = process.env.HIVEMIND_CAPTURE !== "false";
735
+ await autoUpdate(creds, { agent: "hermes" });
682
736
  if (creds?.token && captureEnabled) {
683
737
  try {
684
738
  const config = loadConfig();
@@ -687,10 +741,10 @@ async function main() {
687
741
  await api.ensureTable();
688
742
  await api.ensureSessionsTable(config.sessionsTableName);
689
743
  await createPlaceholder(api, config.tableName, sessionId, cwd, config.userName, config.orgName, config.workspaceId);
690
- log3("placeholder created");
744
+ log4("placeholder created");
691
745
  }
692
746
  } catch (e) {
693
- log3(`placeholder failed: ${e.message}`);
747
+ log4(`placeholder failed: ${e.message}`);
694
748
  }
695
749
  }
696
750
  let versionNotice = "";
@@ -704,6 +758,6 @@ Not logged in to Deeplake. Run: hivemind login${versionNotice}`;
704
758
  console.log(JSON.stringify({ context: additional }));
705
759
  }
706
760
  main().catch((e) => {
707
- log3(`fatal: ${e.message}`);
761
+ log4(`fatal: ${e.message}`);
708
762
  process.exit(0);
709
763
  });
@@ -1063,16 +1063,14 @@ async function loadConfig() {
1063
1063
  var requireFromOpenclaw = createRequire(import.meta.url);
1064
1064
  var { spawn: realSpawn, execFileSync: realExecFileSync } = requireFromOpenclaw("node:child_process");
1065
1065
  var DEFAULT_API_URL2 = "https://api.deeplake.ai";
1066
- var VERSION_URL = "https://clawhub.ai/api/v1/packages/hivemind";
1066
+ var VERSION_URL = "https://registry.npmjs.org/@deeplake/hivemind/latest";
1067
1067
  function extractLatestVersion(body) {
1068
1068
  if (typeof body !== "object" || body === null) return null;
1069
- const pkg = body.package;
1070
- if (typeof pkg !== "object" || pkg === null) return null;
1071
- const v = pkg.latestVersion;
1069
+ const v = body.version;
1072
1070
  return typeof v === "string" && v.length > 0 ? v : null;
1073
1071
  }
1074
1072
  function getInstalledVersion() {
1075
- return "0.7.12".length > 0 ? "0.7.12" : null;
1073
+ return "0.7.13".length > 0 ? "0.7.13" : null;
1076
1074
  }
1077
1075
  function isNewer(latest, current) {
1078
1076
  const parse = (v) => v.replace(/-.*$/, "").split(".").map(Number);
@@ -1084,13 +1082,15 @@ async function checkForUpdate(logger) {
1084
1082
  try {
1085
1083
  const current = getInstalledVersion();
1086
1084
  if (!current) return;
1087
- const res = await fetch(VERSION_URL, { signal: AbortSignal.timeout(3e3) });
1085
+ const res = await fetch(VERSION_URL, { signal: AbortSignal.timeout(5e3) });
1088
1086
  if (!res.ok) return;
1089
1087
  const latest = extractLatestVersion(await res.json());
1090
1088
  if (latest && isNewer(latest, current)) {
1091
- logger.info?.(`\u2B06\uFE0F Hivemind update available: ${current} \u2192 ${latest}. Run: openclaw plugins update hivemind`);
1089
+ pendingUpdate = { current, latest };
1090
+ logger.info?.(`\u2B06\uFE0F Hivemind update available: ${current} \u2192 ${latest}. Run: hivemind update`);
1092
1091
  }
1093
- } catch {
1092
+ } catch (err) {
1093
+ logger.error(`Auto-update check failed: ${err instanceof Error ? err.message : String(err)}`);
1094
1094
  }
1095
1095
  }
1096
1096
  var authPending = false;
@@ -1529,14 +1529,14 @@ Run /hivemind_update to install it now.` };
1529
1529
  });
1530
1530
  pluginApi.registerCommand({
1531
1531
  name: "hivemind_update",
1532
- description: "Install the latest Hivemind version from ClawHub",
1532
+ description: "Install the latest Hivemind version from npm",
1533
1533
  handler: async () => {
1534
1534
  const current = getInstalledVersion() ?? "unknown";
1535
1535
  return {
1536
1536
  text: `Hivemind v${current} installed. To install the latest:
1537
1537
 
1538
- \u2022 Ask me in chat: "update hivemind" \u2014 I'll run \`openclaw plugins update hivemind\` via my exec tool.
1539
- \u2022 Or run in your terminal: \`openclaw plugins update hivemind\`
1538
+ \u2022 Ask me in chat: "update hivemind" \u2014 I'll run \`hivemind update\` via my exec tool.
1539
+ \u2022 Or run in your terminal: \`hivemind update\`
1540
1540
 
1541
1541
  The gateway restarts automatically once the install completes.`
1542
1542
  };
@@ -1745,23 +1745,7 @@ ${body.slice(0, 500)}`;
1745
1745
  const hook = (event, handler) => {
1746
1746
  pluginApi.on(event, handler);
1747
1747
  };
1748
- if (config.autoUpdate !== false) {
1749
- (async () => {
1750
- try {
1751
- const current = getInstalledVersion();
1752
- if (!current) return;
1753
- const res = await fetch(VERSION_URL, { signal: AbortSignal.timeout(3e3) });
1754
- if (!res.ok) return;
1755
- const latest = extractLatestVersion(await res.json());
1756
- if (!latest || !isNewer(latest, current)) return;
1757
- pendingUpdate = { current, latest };
1758
- logger.info?.(`Hivemind update available: ${current} \u2192 ${latest}. Agent will be prompted to install when user asks.`);
1759
- } catch (err) {
1760
- logger.error(`Auto-update check failed: ${err instanceof Error ? err.message : String(err)}`);
1761
- }
1762
- })();
1763
- }
1764
- if ('---\nname: hivemind\ndescription: Global team and org memory powered by Activeloop. ALWAYS check BOTH built-in memory AND Hivemind memory when recalling information.\nallowed-tools: hivemind_search, hivemind_read, hivemind_index\n---\n\n# Hivemind Memory\n\nYou have TWO memory sources. ALWAYS check BOTH when the user asks you to recall, remember, or look up ANY information:\n\n1. **Your built-in memory** \u2014 personal per-project notes from the host agent\n2. **Hivemind global memory** \u2014 global memory shared across all sessions, users, and agents in the org, accessed via the tools below\n\n## Memory Structure\n\n```\n/index.md \u2190 START HERE \u2014 table of all sessions\n/summaries/\n <username>/\n <session-id>.md \u2190 AI-generated wiki summary per session\n/sessions/\n <username>/\n <user_org_ws_slug>.jsonl \u2190 raw session data\n```\n\n## How to Search\n\n1. **First**: call `hivemind_index()` \u2014 table of all sessions with dates, projects, descriptions\n2. **If you need details**: call `hivemind_read("/summaries/<username>/<session>.md")`\n3. **If you need raw data**: call `hivemind_read("/sessions/<username>/<file>.jsonl")`\n4. **Keyword search**: call `hivemind_search("keyword")` \u2014 substring search across both summaries and sessions, returns `path:line` hits\n\nDo NOT jump straight to reading raw JSONL files. Always start with `hivemind_index` and summaries.\n\n## Organization Management\n\n- `/hivemind_login` \u2014 sign in via device flow\n- `/hivemind_capture` \u2014 toggle capture on/off (off = no data sent)\n- `/hivemind_whoami` \u2014 show current org and workspace\n- `/hivemind_orgs` \u2014 list organizations\n- `/hivemind_switch_org <name-or-id>` \u2014 switch organization\n- `/hivemind_workspaces` \u2014 list workspaces\n- `/hivemind_switch_workspace <id>` \u2014 switch workspace\n- `/hivemind_version` \u2014 show installed version and check ClawHub for updates\n- `/hivemind_update` \u2014 shows how to install (ask the agent, or run `openclaw plugins update hivemind` in your terminal)\n- `/hivemind_autoupdate [on|off]` \u2014 toggle the agent-facing update nudge (on by default: when a newer version is available, the agent is prompted to install it via `exec` if you ask to update)\n\n## Skill Management (skilify)\n\nHivemind also mines reusable Claude skills from agent sessions and stores them in a per-org Deeplake table. Openclaw itself doesn\'t run sessions to mine, but you can pull skills others have already mined for the user. These run in the user\'s terminal (the openclaw plugin does not register them as `/hivemind_*` commands):\n\n- `hivemind skilify` \u2014 show scope/team/install + per-project state\n- `hivemind skilify pull` \u2014 sync skills for the current project from the org table\n- `hivemind skilify pull --user <email>` \u2014 only that author\'s skills\n- `hivemind skilify pull --users a,b,c` \u2014 multiple authors (CSV)\n- `hivemind skilify pull --all-users` \u2014 explicit "no author filter"\n- `hivemind skilify pull --to project|global` \u2014 install location (`<cwd>/.claude/skills/` vs `~/.claude/skills/`)\n- `hivemind skilify pull --dry-run` \u2014 preview without touching disk\n- `hivemind skilify pull --force` \u2014 overwrite local (creates `.bak`)\n- `hivemind skilify pull <skill-name>` \u2014 pull only that one skill (combines with `--user`)\n- `hivemind skilify scope <me|team|org>` \u2014 set sharing scope for new skills\n- `hivemind skilify install <project|global>` \u2014 default install location\n- `hivemind skilify team add|remove|list <name>` \u2014 manage team list\n\nIf the user asks to "pull skills from X", "share skills with the team", or similar, suggest the matching `hivemind skilify` command. Run `hivemind skilify --help` for the full reference.\n\n## Limits\n\nDo NOT delegate to subagents when reading Hivemind memory. If a tool call returns empty after 2 attempts, skip it and move on. Report what you found rather than exhaustively retrying.\n\n## Getting Started\n\nAfter installing the plugin:\n1. Run `/hivemind_login` to authenticate\n2. Run `/hivemind_setup` to enable the memory tools in your openclaw allowlist (one-time, per install)\n3. Start using memory \u2014 ask questions, the agent automatically captures and searches\n\n## Sharing memory\n\nMultiple agents share memory when users are in the same Activeloop organization.\n'.length > 0) {
1748
+ if ('---\nname: hivemind\ndescription: Global team and org memory powered by Activeloop. ALWAYS check BOTH built-in memory AND Hivemind memory when recalling information.\nallowed-tools: hivemind_search, hivemind_read, hivemind_index\n---\n\n# Hivemind Memory\n\nYou have TWO memory sources. ALWAYS check BOTH when the user asks you to recall, remember, or look up ANY information:\n\n1. **Your built-in memory** \u2014 personal per-project notes from the host agent\n2. **Hivemind global memory** \u2014 global memory shared across all sessions, users, and agents in the org, accessed via the tools below\n\n## Memory Structure\n\n```\n/index.md \u2190 START HERE \u2014 table of all sessions\n/summaries/\n <username>/\n <session-id>.md \u2190 AI-generated wiki summary per session\n/sessions/\n <username>/\n <user_org_ws_slug>.jsonl \u2190 raw session data\n```\n\n## How to Search\n\n1. **First**: call `hivemind_index()` \u2014 table of all sessions with dates, projects, descriptions\n2. **If you need details**: call `hivemind_read("/summaries/<username>/<session>.md")`\n3. **If you need raw data**: call `hivemind_read("/sessions/<username>/<file>.jsonl")`\n4. **Keyword search**: call `hivemind_search("keyword")` \u2014 substring search across both summaries and sessions, returns `path:line` hits\n\nDo NOT jump straight to reading raw JSONL files. Always start with `hivemind_index` and summaries.\n\n## Organization Management\n\n- `/hivemind_login` \u2014 sign in via device flow\n- `/hivemind_capture` \u2014 toggle capture on/off (off = no data sent)\n- `/hivemind_whoami` \u2014 show current org and workspace\n- `/hivemind_orgs` \u2014 list organizations\n- `/hivemind_switch_org <name-or-id>` \u2014 switch organization\n- `/hivemind_workspaces` \u2014 list workspaces\n- `/hivemind_switch_workspace <id>` \u2014 switch workspace\n- `/hivemind_version` \u2014 show installed version and check npm for updates\n- `/hivemind_update` \u2014 shows how to install (ask the agent, or run `hivemind update` in your terminal)\n- `/hivemind_autoupdate [on|off]` \u2014 toggle the agent-facing update nudge (on by default: when a newer version is available, the agent is prompted to install it via `exec` if you ask to update)\n\n## Skill Management (skilify)\n\nHivemind also mines reusable Claude skills from agent sessions and stores them in a per-org Deeplake table. Openclaw itself doesn\'t run sessions to mine, but you can pull skills others have already mined for the user. These run in the user\'s terminal (the openclaw plugin does not register them as `/hivemind_*` commands):\n\n- `hivemind skilify` \u2014 show scope/team/install + per-project state\n- `hivemind skilify pull` \u2014 sync skills for the current project from the org table\n- `hivemind skilify pull --user <email>` \u2014 only that author\'s skills\n- `hivemind skilify pull --users a,b,c` \u2014 multiple authors (CSV)\n- `hivemind skilify pull --all-users` \u2014 explicit "no author filter"\n- `hivemind skilify pull --to project|global` \u2014 install location (`<cwd>/.claude/skills/` vs `~/.claude/skills/`)\n- `hivemind skilify pull --dry-run` \u2014 preview without touching disk\n- `hivemind skilify pull --force` \u2014 overwrite local (creates `.bak`)\n- `hivemind skilify pull <skill-name>` \u2014 pull only that one skill (combines with `--user`)\n- `hivemind skilify scope <me|team|org>` \u2014 set sharing scope for new skills\n- `hivemind skilify install <project|global>` \u2014 default install location\n- `hivemind skilify team add|remove|list <name>` \u2014 manage team list\n\nIf the user asks to "pull skills from X", "share skills with the team", or similar, suggest the matching `hivemind skilify` command. Run `hivemind skilify --help` for the full reference.\n\n## Limits\n\nDo NOT delegate to subagents when reading Hivemind memory. If a tool call returns empty after 2 attempts, skip it and move on. Report what you found rather than exhaustively retrying.\n\n## Getting Started\n\nAfter installing the plugin:\n1. Run `/hivemind_login` to authenticate\n2. Run `/hivemind_setup` to enable the memory tools in your openclaw allowlist (one-time, per install)\n3. Start using memory \u2014 ask questions, the agent automatically captures and searches\n\n## Sharing memory\n\nMultiple agents share memory when users are in the same Activeloop organization.\n'.length > 0) {
1765
1749
  const setupConfigPromise = loadSetupConfig();
1766
1750
  hook("before_prompt_build", async () => {
1767
1751
  const { detectAllowlistMissing } = await setupConfigPromise;
@@ -1769,11 +1753,11 @@ ${body.slice(0, 500)}`;
1769
1753
  const updateNudge = pendingUpdate ? `
1770
1754
 
1771
1755
  <hivemind-update-available>
1772
- A newer Hivemind version is available: ${pendingUpdate.current} \u2192 ${pendingUpdate.latest}. Install command: \`openclaw plugins update hivemind\`. The gateway reloads the plugin after install.
1756
+ A newer Hivemind version is available: ${pendingUpdate.current} \u2192 ${pendingUpdate.latest}. Install command: \`hivemind update\`. The gateway reloads the plugin after install.
1773
1757
  </hivemind-update-available>
1774
1758
  ` : "";
1775
1759
  return {
1776
- prependSystemContext: allowlistNudge + updateNudge + '\n\n<hivemind-skill>\n---\nname: hivemind\ndescription: Global team and org memory powered by Activeloop. ALWAYS check BOTH built-in memory AND Hivemind memory when recalling information.\nallowed-tools: hivemind_search, hivemind_read, hivemind_index\n---\n\n# Hivemind Memory\n\nYou have TWO memory sources. ALWAYS check BOTH when the user asks you to recall, remember, or look up ANY information:\n\n1. **Your built-in memory** \u2014 personal per-project notes from the host agent\n2. **Hivemind global memory** \u2014 global memory shared across all sessions, users, and agents in the org, accessed via the tools below\n\n## Memory Structure\n\n```\n/index.md \u2190 START HERE \u2014 table of all sessions\n/summaries/\n <username>/\n <session-id>.md \u2190 AI-generated wiki summary per session\n/sessions/\n <username>/\n <user_org_ws_slug>.jsonl \u2190 raw session data\n```\n\n## How to Search\n\n1. **First**: call `hivemind_index()` \u2014 table of all sessions with dates, projects, descriptions\n2. **If you need details**: call `hivemind_read("/summaries/<username>/<session>.md")`\n3. **If you need raw data**: call `hivemind_read("/sessions/<username>/<file>.jsonl")`\n4. **Keyword search**: call `hivemind_search("keyword")` \u2014 substring search across both summaries and sessions, returns `path:line` hits\n\nDo NOT jump straight to reading raw JSONL files. Always start with `hivemind_index` and summaries.\n\n## Organization Management\n\n- `/hivemind_login` \u2014 sign in via device flow\n- `/hivemind_capture` \u2014 toggle capture on/off (off = no data sent)\n- `/hivemind_whoami` \u2014 show current org and workspace\n- `/hivemind_orgs` \u2014 list organizations\n- `/hivemind_switch_org <name-or-id>` \u2014 switch organization\n- `/hivemind_workspaces` \u2014 list workspaces\n- `/hivemind_switch_workspace <id>` \u2014 switch workspace\n- `/hivemind_version` \u2014 show installed version and check ClawHub for updates\n- `/hivemind_update` \u2014 shows how to install (ask the agent, or run `openclaw plugins update hivemind` in your terminal)\n- `/hivemind_autoupdate [on|off]` \u2014 toggle the agent-facing update nudge (on by default: when a newer version is available, the agent is prompted to install it via `exec` if you ask to update)\n\n## Skill Management (skilify)\n\nHivemind also mines reusable Claude skills from agent sessions and stores them in a per-org Deeplake table. Openclaw itself doesn\'t run sessions to mine, but you can pull skills others have already mined for the user. These run in the user\'s terminal (the openclaw plugin does not register them as `/hivemind_*` commands):\n\n- `hivemind skilify` \u2014 show scope/team/install + per-project state\n- `hivemind skilify pull` \u2014 sync skills for the current project from the org table\n- `hivemind skilify pull --user <email>` \u2014 only that author\'s skills\n- `hivemind skilify pull --users a,b,c` \u2014 multiple authors (CSV)\n- `hivemind skilify pull --all-users` \u2014 explicit "no author filter"\n- `hivemind skilify pull --to project|global` \u2014 install location (`<cwd>/.claude/skills/` vs `~/.claude/skills/`)\n- `hivemind skilify pull --dry-run` \u2014 preview without touching disk\n- `hivemind skilify pull --force` \u2014 overwrite local (creates `.bak`)\n- `hivemind skilify pull <skill-name>` \u2014 pull only that one skill (combines with `--user`)\n- `hivemind skilify scope <me|team|org>` \u2014 set sharing scope for new skills\n- `hivemind skilify install <project|global>` \u2014 default install location\n- `hivemind skilify team add|remove|list <name>` \u2014 manage team list\n\nIf the user asks to "pull skills from X", "share skills with the team", or similar, suggest the matching `hivemind skilify` command. Run `hivemind skilify --help` for the full reference.\n\n## Limits\n\nDo NOT delegate to subagents when reading Hivemind memory. If a tool call returns empty after 2 attempts, skip it and move on. Report what you found rather than exhaustively retrying.\n\n## Getting Started\n\nAfter installing the plugin:\n1. Run `/hivemind_login` to authenticate\n2. Run `/hivemind_setup` to enable the memory tools in your openclaw allowlist (one-time, per install)\n3. Start using memory \u2014 ask questions, the agent automatically captures and searches\n\n## Sharing memory\n\nMultiple agents share memory when users are in the same Activeloop organization.\n\n</hivemind-skill>\n'
1760
+ prependSystemContext: allowlistNudge + updateNudge + '\n\n<hivemind-skill>\n---\nname: hivemind\ndescription: Global team and org memory powered by Activeloop. ALWAYS check BOTH built-in memory AND Hivemind memory when recalling information.\nallowed-tools: hivemind_search, hivemind_read, hivemind_index\n---\n\n# Hivemind Memory\n\nYou have TWO memory sources. ALWAYS check BOTH when the user asks you to recall, remember, or look up ANY information:\n\n1. **Your built-in memory** \u2014 personal per-project notes from the host agent\n2. **Hivemind global memory** \u2014 global memory shared across all sessions, users, and agents in the org, accessed via the tools below\n\n## Memory Structure\n\n```\n/index.md \u2190 START HERE \u2014 table of all sessions\n/summaries/\n <username>/\n <session-id>.md \u2190 AI-generated wiki summary per session\n/sessions/\n <username>/\n <user_org_ws_slug>.jsonl \u2190 raw session data\n```\n\n## How to Search\n\n1. **First**: call `hivemind_index()` \u2014 table of all sessions with dates, projects, descriptions\n2. **If you need details**: call `hivemind_read("/summaries/<username>/<session>.md")`\n3. **If you need raw data**: call `hivemind_read("/sessions/<username>/<file>.jsonl")`\n4. **Keyword search**: call `hivemind_search("keyword")` \u2014 substring search across both summaries and sessions, returns `path:line` hits\n\nDo NOT jump straight to reading raw JSONL files. Always start with `hivemind_index` and summaries.\n\n## Organization Management\n\n- `/hivemind_login` \u2014 sign in via device flow\n- `/hivemind_capture` \u2014 toggle capture on/off (off = no data sent)\n- `/hivemind_whoami` \u2014 show current org and workspace\n- `/hivemind_orgs` \u2014 list organizations\n- `/hivemind_switch_org <name-or-id>` \u2014 switch organization\n- `/hivemind_workspaces` \u2014 list workspaces\n- `/hivemind_switch_workspace <id>` \u2014 switch workspace\n- `/hivemind_version` \u2014 show installed version and check npm for updates\n- `/hivemind_update` \u2014 shows how to install (ask the agent, or run `hivemind update` in your terminal)\n- `/hivemind_autoupdate [on|off]` \u2014 toggle the agent-facing update nudge (on by default: when a newer version is available, the agent is prompted to install it via `exec` if you ask to update)\n\n## Skill Management (skilify)\n\nHivemind also mines reusable Claude skills from agent sessions and stores them in a per-org Deeplake table. Openclaw itself doesn\'t run sessions to mine, but you can pull skills others have already mined for the user. These run in the user\'s terminal (the openclaw plugin does not register them as `/hivemind_*` commands):\n\n- `hivemind skilify` \u2014 show scope/team/install + per-project state\n- `hivemind skilify pull` \u2014 sync skills for the current project from the org table\n- `hivemind skilify pull --user <email>` \u2014 only that author\'s skills\n- `hivemind skilify pull --users a,b,c` \u2014 multiple authors (CSV)\n- `hivemind skilify pull --all-users` \u2014 explicit "no author filter"\n- `hivemind skilify pull --to project|global` \u2014 install location (`<cwd>/.claude/skills/` vs `~/.claude/skills/`)\n- `hivemind skilify pull --dry-run` \u2014 preview without touching disk\n- `hivemind skilify pull --force` \u2014 overwrite local (creates `.bak`)\n- `hivemind skilify pull <skill-name>` \u2014 pull only that one skill (combines with `--user`)\n- `hivemind skilify scope <me|team|org>` \u2014 set sharing scope for new skills\n- `hivemind skilify install <project|global>` \u2014 default install location\n- `hivemind skilify team add|remove|list <name>` \u2014 manage team list\n\nIf the user asks to "pull skills from X", "share skills with the team", or similar, suggest the matching `hivemind skilify` command. Run `hivemind skilify --help` for the full reference.\n\n## Limits\n\nDo NOT delegate to subagents when reading Hivemind memory. If a tool call returns empty after 2 attempts, skip it and move on. Report what you found rather than exhaustively retrying.\n\n## Getting Started\n\nAfter installing the plugin:\n1. Run `/hivemind_login` to authenticate\n2. Run `/hivemind_setup` to enable the memory tools in your openclaw allowlist (one-time, per install)\n3. Start using memory \u2014 ask questions, the agent automatically captures and searches\n\n## Sharing memory\n\nMultiple agents share memory when users are in the same Activeloop organization.\n\n</hivemind-skill>\n'
1777
1761
  };
1778
1762
  });
1779
1763
  }
@@ -1919,8 +1903,10 @@ One brain for every agent on your team.
1919
1903
  });
1920
1904
  }
1921
1905
  }
1922
- checkForUpdate(logger).catch(() => {
1923
- });
1906
+ if (config.autoUpdate !== false) {
1907
+ checkForUpdate(logger).catch(() => {
1908
+ });
1909
+ }
1924
1910
  logger.info?.("Hivemind plugin registered");
1925
1911
  } catch (err) {
1926
1912
  pluginApi.logger?.error?.(`Hivemind register failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -52,5 +52,5 @@
52
52
  }
53
53
  }
54
54
  },
55
- "version": "0.7.12"
55
+ "version": "0.7.13"
56
56
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hivemind",
3
- "version": "0.7.12",
3
+ "version": "0.7.13",
4
4
  "type": "module",
5
5
  "description": "Hivemind — cloud-backed persistent shared memory for AI agents, powered by DeepLake",
6
6
  "license": "Apache-2.0",
@@ -41,8 +41,8 @@ Do NOT jump straight to reading raw JSONL files. Always start with `hivemind_ind
41
41
  - `/hivemind_switch_org <name-or-id>` — switch organization
42
42
  - `/hivemind_workspaces` — list workspaces
43
43
  - `/hivemind_switch_workspace <id>` — switch workspace
44
- - `/hivemind_version` — show installed version and check ClawHub for updates
45
- - `/hivemind_update` — shows how to install (ask the agent, or run `openclaw plugins update hivemind` in your terminal)
44
+ - `/hivemind_version` — show installed version and check npm for updates
45
+ - `/hivemind_update` — shows how to install (ask the agent, or run `hivemind update` in your terminal)
46
46
  - `/hivemind_autoupdate [on|off]` — toggle the agent-facing update nudge (on by default: when a newer version is available, the agent is prompted to install it via `exec` if you ask to update)
47
47
 
48
48
  ## Skill Management (skilify)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeplake/hivemind",
3
- "version": "0.7.12",
3
+ "version": "0.7.13",
4
4
  "description": "Cloud-backed persistent shared memory for AI agents powered by Deeplake",
5
5
  "type": "module",
6
6
  "repository": {
@@ -63,6 +63,11 @@ interface Creds {
63
63
  orgName?: string;
64
64
  workspaceId: string;
65
65
  userName: string;
66
+ // Mirrors Credentials.autoupdate from src/commands/auth-creds.ts. The
67
+ // inline autoUpdate gate below depends on this — without it the gate
68
+ // sees `undefined !== false` and runs the update even when the user
69
+ // has explicitly run `hivemind autoupdate off`.
70
+ autoupdate?: boolean;
66
71
  }
67
72
 
68
73
  function loadCreds(): Creds | null {
@@ -79,6 +84,7 @@ function loadCreds(): Creds | null {
79
84
  orgName: parsed.orgName,
80
85
  workspaceId: parsed.workspaceId ?? "default",
81
86
  userName: parsed.userName ?? "unknown",
87
+ autoupdate: parsed.autoupdate,
82
88
  };
83
89
  } catch {
84
90
  return null;
@@ -765,6 +771,32 @@ export default function hivemindExtension(pi: ExtensionAPI): void {
765
771
  } else {
766
772
  logHm(`session_start: creds org=${creds.orgName ?? creds.orgId} ws=${creds.workspaceId}`);
767
773
  }
774
+
775
+ // Centralized autoupdate: shells out to `hivemind update` (npm-based,
776
+ // refreshes every detected agent in one shot). Best-effort, fully
777
+ // self-contained because the pi extension ships as raw .ts (no shared-
778
+ // module imports allowed). Mirrors src/hooks/shared/autoupdate.ts —
779
+ // keep in sync.
780
+ if (creds && creds.autoupdate !== false) {
781
+ try {
782
+ const which = execSync("which hivemind 2>/dev/null", { encoding: "utf-8", timeout: 2000 }).trim();
783
+ if (which) {
784
+ await new Promise<void>((resolve) => {
785
+ const child = spawn(which, ["update"], { stdio: ["ignore", "pipe", "pipe"], timeout: 90_000 });
786
+ let out = "";
787
+ child.stdout?.on("data", d => { out += d.toString(); });
788
+ child.stderr?.on("data", d => { out += d.toString(); });
789
+ child.on("close", () => {
790
+ const m = out.match(/Updated to .+\./);
791
+ if (m) process.stderr.write(`✅ Hivemind ${m[0]} Restart pi to apply.\n`);
792
+ resolve();
793
+ });
794
+ child.on("error", () => resolve());
795
+ });
796
+ }
797
+ } catch { /* network down / which missing — silent */ }
798
+ }
799
+
768
800
  if (creds && captureEnabled) {
769
801
  // Other agents' session-start hooks create the memory + sessions tables
770
802
  // via DeeplakeApi.ensureTable / ensureSessionsTable. The pi extension is