@deeplake/hivemind 0.7.11 → 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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/codex/bundle/session-start-setup.js +63 -106
- package/cursor/bundle/session-start.js +60 -6
- package/hermes/bundle/session-start.js +58 -4
- package/openclaw/dist/index.js +18 -32
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/openclaw/skills/SKILL.md +2 -2
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +32 -0
|
@@ -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.
|
|
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.
|
|
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.
|
|
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 {
|
|
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
|
|
588
|
+
import { join as join5 } from "node:path";
|
|
651
589
|
function makeWikiLogger(hooksDir, filename = "deeplake-wiki.log") {
|
|
652
|
-
const path =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
712
|
+
log4("setup complete");
|
|
722
713
|
}
|
|
723
714
|
} catch (e) {
|
|
724
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
745
|
+
log4("no credentials found");
|
|
693
746
|
} else {
|
|
694
|
-
|
|
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
|
-
|
|
761
|
+
log4("placeholder created");
|
|
708
762
|
}
|
|
709
763
|
} catch (e) {
|
|
710
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
744
|
+
log4("placeholder created");
|
|
691
745
|
}
|
|
692
746
|
} catch (e) {
|
|
693
|
-
|
|
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
|
-
|
|
761
|
+
log4(`fatal: ${e.message}`);
|
|
708
762
|
process.exit(0);
|
|
709
763
|
});
|
package/openclaw/dist/index.js
CHANGED
|
@@ -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://
|
|
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
|
|
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.
|
|
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(
|
|
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
|
-
|
|
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
|
|
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 \`
|
|
1539
|
-
\u2022 Or run in your terminal: \`
|
|
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 (
|
|
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: \`
|
|
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
|
|
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
|
-
|
|
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)}`);
|
package/openclaw/package.json
CHANGED
package/openclaw/skills/SKILL.md
CHANGED
|
@@ -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
|
|
45
|
-
- `/hivemind_update` — shows how to install (ask the agent, or run `
|
|
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
|
@@ -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
|