@deeplake/hivemind 0.7.26 → 0.7.28
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/bundle/cli.js +1086 -93
- package/codex/bundle/capture.js +10 -5
- package/codex/bundle/commands/auth-login.js +10 -5
- package/codex/bundle/embeddings/embed-daemon.js +4 -2
- package/codex/bundle/pre-tool-use.js +10 -5
- package/codex/bundle/session-start-setup.js +10 -5
- package/codex/bundle/session-start.js +233 -136
- package/codex/bundle/shell/deeplake-shell.js +10 -5
- package/codex/bundle/skillify-worker.js +60 -21
- package/codex/bundle/stop.js +66 -25
- package/codex/bundle/wiki-worker.js +4 -2
- package/codex/skills/deeplake-memory/SKILL.md +33 -0
- package/cursor/bundle/capture.js +63 -22
- package/cursor/bundle/commands/auth-login.js +10 -5
- package/cursor/bundle/embeddings/embed-daemon.js +4 -2
- package/cursor/bundle/pre-tool-use.js +10 -5
- package/cursor/bundle/session-end.js +57 -19
- package/cursor/bundle/session-start.js +238 -87
- package/cursor/bundle/shell/deeplake-shell.js +10 -5
- package/cursor/bundle/skillify-worker.js +60 -21
- package/cursor/bundle/wiki-worker.js +4 -2
- package/hermes/bundle/capture.js +63 -22
- package/hermes/bundle/commands/auth-login.js +10 -5
- package/hermes/bundle/embeddings/embed-daemon.js +4 -2
- package/hermes/bundle/pre-tool-use.js +10 -5
- package/hermes/bundle/session-end.js +57 -19
- package/hermes/bundle/session-start.js +239 -87
- package/hermes/bundle/shell/deeplake-shell.js +10 -5
- package/hermes/bundle/skillify-worker.js +60 -21
- package/hermes/bundle/wiki-worker.js +4 -2
- package/mcp/bundle/server.js +10 -5
- package/openclaw/dist/chunks/{auth-creds-AEKS6D3P.js → auth-creds-KKTYIP27.js} +2 -1
- package/openclaw/dist/chunks/{chunk-SRCBBT4H.js → chunk-OSD5GJJ5.js} +2 -0
- package/openclaw/dist/chunks/{config-ZLH6JFJS.js → config-XEK4MJJS.js} +2 -0
- package/openclaw/dist/chunks/{index-marker-store-PGT5CW6T.js → index-marker-store-CPGF2BI7.js} +4 -2
- package/openclaw/dist/chunks/{setup-config-C35UK4LP.js → setup-config-VI54GEUM.js} +2 -0
- package/openclaw/dist/index.js +68 -19
- package/openclaw/dist/skillify-worker.js +67 -27
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +157 -19
|
@@ -21,13 +21,15 @@ function readStdin() {
|
|
|
21
21
|
import { appendFileSync } from "node:fs";
|
|
22
22
|
import { join } from "node:path";
|
|
23
23
|
import { homedir } from "node:os";
|
|
24
|
-
var DEBUG = process.env.HIVEMIND_DEBUG === "1";
|
|
25
24
|
var LOG = join(homedir(), ".deeplake", "hook-debug.log");
|
|
25
|
+
function isDebug() {
|
|
26
|
+
return process.env.HIVEMIND_DEBUG === "1";
|
|
27
|
+
}
|
|
26
28
|
function utcTimestamp(d = /* @__PURE__ */ new Date()) {
|
|
27
29
|
return d.toISOString().replace("T", " ").slice(0, 19) + " UTC";
|
|
28
30
|
}
|
|
29
31
|
function log(tag, msg) {
|
|
30
|
-
if (!
|
|
32
|
+
if (!isDebug())
|
|
31
33
|
return;
|
|
32
34
|
appendFileSync(LOG, `${(/* @__PURE__ */ new Date()).toISOString()} [${tag}] ${msg}
|
|
33
35
|
`);
|
|
@@ -282,33 +284,69 @@ import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, appendFileSyn
|
|
|
282
284
|
import { homedir as homedir6, tmpdir as tmpdir2 } from "node:os";
|
|
283
285
|
|
|
284
286
|
// dist/src/skillify/gate-runner.js
|
|
285
|
-
import { execFileSync } from "node:child_process";
|
|
286
287
|
import { existsSync as existsSync3 } from "node:fs";
|
|
288
|
+
import { createRequire } from "node:module";
|
|
287
289
|
import { homedir as homedir5 } from "node:os";
|
|
288
290
|
import { join as join7 } from "node:path";
|
|
291
|
+
var requireForCp = createRequire(import.meta.url);
|
|
292
|
+
var { execFileSync: runChildProcess } = requireForCp("node:child_process");
|
|
293
|
+
var inheritedEnv = process;
|
|
294
|
+
function firstExistingPath(candidates) {
|
|
295
|
+
for (const c of candidates) {
|
|
296
|
+
if (existsSync3(c))
|
|
297
|
+
return c;
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
289
301
|
function findAgentBin(agent) {
|
|
290
|
-
const
|
|
291
|
-
try {
|
|
292
|
-
const out = execFileSync("which", [name], {
|
|
293
|
-
encoding: "utf-8",
|
|
294
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
295
|
-
});
|
|
296
|
-
return out.trim() || null;
|
|
297
|
-
} catch {
|
|
298
|
-
return null;
|
|
299
|
-
}
|
|
300
|
-
};
|
|
302
|
+
const home = homedir5();
|
|
301
303
|
switch (agent) {
|
|
304
|
+
// /usr/bin/<name> is included in every candidate list — that's the
|
|
305
|
+
// common Linux package-manager install path (apt, dnf, pacman). Old
|
|
306
|
+
// code used `which` which always checked it; the static-scan fix
|
|
307
|
+
// dropped `which`, so /usr/bin needs to be explicit. CodeRabbit on
|
|
308
|
+
// #170 caught the gap.
|
|
302
309
|
case "claude_code":
|
|
303
|
-
return
|
|
310
|
+
return firstExistingPath([
|
|
311
|
+
join7(home, ".claude", "local", "claude"),
|
|
312
|
+
"/usr/local/bin/claude",
|
|
313
|
+
"/usr/bin/claude",
|
|
314
|
+
join7(home, ".npm-global", "bin", "claude"),
|
|
315
|
+
join7(home, ".local", "bin", "claude"),
|
|
316
|
+
"/opt/homebrew/bin/claude"
|
|
317
|
+
]) ?? join7(home, ".claude", "local", "claude");
|
|
304
318
|
case "codex":
|
|
305
|
-
return
|
|
319
|
+
return firstExistingPath([
|
|
320
|
+
"/usr/local/bin/codex",
|
|
321
|
+
"/usr/bin/codex",
|
|
322
|
+
join7(home, ".npm-global", "bin", "codex"),
|
|
323
|
+
join7(home, ".local", "bin", "codex"),
|
|
324
|
+
"/opt/homebrew/bin/codex"
|
|
325
|
+
]) ?? "/usr/local/bin/codex";
|
|
306
326
|
case "cursor":
|
|
307
|
-
return
|
|
327
|
+
return firstExistingPath([
|
|
328
|
+
"/usr/local/bin/cursor-agent",
|
|
329
|
+
"/usr/bin/cursor-agent",
|
|
330
|
+
join7(home, ".npm-global", "bin", "cursor-agent"),
|
|
331
|
+
join7(home, ".local", "bin", "cursor-agent"),
|
|
332
|
+
"/opt/homebrew/bin/cursor-agent"
|
|
333
|
+
]) ?? "/usr/local/bin/cursor-agent";
|
|
308
334
|
case "hermes":
|
|
309
|
-
return
|
|
335
|
+
return firstExistingPath([
|
|
336
|
+
join7(home, ".local", "bin", "hermes"),
|
|
337
|
+
"/usr/local/bin/hermes",
|
|
338
|
+
"/usr/bin/hermes",
|
|
339
|
+
join7(home, ".npm-global", "bin", "hermes"),
|
|
340
|
+
"/opt/homebrew/bin/hermes"
|
|
341
|
+
]) ?? join7(home, ".local", "bin", "hermes");
|
|
310
342
|
case "pi":
|
|
311
|
-
return
|
|
343
|
+
return firstExistingPath([
|
|
344
|
+
join7(home, ".local", "bin", "pi"),
|
|
345
|
+
"/usr/local/bin/pi",
|
|
346
|
+
"/usr/bin/pi",
|
|
347
|
+
join7(home, ".npm-global", "bin", "pi"),
|
|
348
|
+
"/opt/homebrew/bin/pi"
|
|
349
|
+
]) ?? join7(home, ".local", "bin", "pi");
|
|
312
350
|
}
|
|
313
351
|
}
|
|
314
352
|
|
|
@@ -53,8 +53,8 @@ var init_index_marker_store = __esm({
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
// dist/src/hooks/cursor/session-start.js
|
|
56
|
-
import { fileURLToPath } from "node:url";
|
|
57
|
-
import { dirname as
|
|
56
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
57
|
+
import { dirname as dirname6 } from "node:path";
|
|
58
58
|
|
|
59
59
|
// dist/src/commands/auth.js
|
|
60
60
|
import { execSync } from "node:child_process";
|
|
@@ -126,10 +126,12 @@ import { randomUUID } from "node:crypto";
|
|
|
126
126
|
import { appendFileSync } from "node:fs";
|
|
127
127
|
import { join as join3 } from "node:path";
|
|
128
128
|
import { homedir as homedir3 } from "node:os";
|
|
129
|
-
var DEBUG = process.env.HIVEMIND_DEBUG === "1";
|
|
130
129
|
var LOG = join3(homedir3(), ".deeplake", "hook-debug.log");
|
|
130
|
+
function isDebug() {
|
|
131
|
+
return process.env.HIVEMIND_DEBUG === "1";
|
|
132
|
+
}
|
|
131
133
|
function log(tag, msg) {
|
|
132
|
-
if (!
|
|
134
|
+
if (!isDebug())
|
|
133
135
|
return;
|
|
134
136
|
appendFileSync(LOG, `${(/* @__PURE__ */ new Date()).toISOString()} [${tag}] ${msg}
|
|
135
137
|
`);
|
|
@@ -175,7 +177,9 @@ var RETRYABLE_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
|
175
177
|
var MAX_RETRIES = 3;
|
|
176
178
|
var BASE_DELAY_MS = 500;
|
|
177
179
|
var MAX_CONCURRENCY = 5;
|
|
178
|
-
|
|
180
|
+
function getQueryTimeoutMs() {
|
|
181
|
+
return Number(process.env.HIVEMIND_QUERY_TIMEOUT_MS ?? 1e4);
|
|
182
|
+
}
|
|
179
183
|
function sleep(ms) {
|
|
180
184
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
181
185
|
}
|
|
@@ -256,8 +260,9 @@ var DeeplakeApi = class {
|
|
|
256
260
|
let lastError;
|
|
257
261
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
258
262
|
let resp;
|
|
263
|
+
const timeoutMs = getQueryTimeoutMs();
|
|
259
264
|
try {
|
|
260
|
-
const signal = AbortSignal.timeout(
|
|
265
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
261
266
|
resp = await fetch(`${this.apiUrl}/workspaces/${this.workspaceId}/tables/query`, {
|
|
262
267
|
method: "POST",
|
|
263
268
|
headers: {
|
|
@@ -271,7 +276,7 @@ var DeeplakeApi = class {
|
|
|
271
276
|
});
|
|
272
277
|
} catch (e) {
|
|
273
278
|
if (isTimeoutError(e)) {
|
|
274
|
-
lastError = new Error(`Query timeout after ${
|
|
279
|
+
lastError = new Error(`Query timeout after ${timeoutMs}ms`);
|
|
275
280
|
throw lastError;
|
|
276
281
|
}
|
|
277
282
|
lastError = e instanceof Error ? e : new Error(String(e));
|
|
@@ -561,6 +566,162 @@ var DeeplakeApi = class {
|
|
|
561
566
|
}
|
|
562
567
|
};
|
|
563
568
|
|
|
569
|
+
// dist/src/cli/skillify-spec.js
|
|
570
|
+
var SKILLIFY_COMMANDS = [
|
|
571
|
+
{ cmd: "hivemind skillify", desc: "show scope, team, install, per-project state" },
|
|
572
|
+
{ cmd: "hivemind skillify pull", desc: "sync project skills from the org table to local FS" },
|
|
573
|
+
{ cmd: "hivemind skillify pull --user <email>", desc: "only skills authored by that user" },
|
|
574
|
+
{ cmd: "hivemind skillify pull --users <a,b,c>", desc: "only skills from those authors" },
|
|
575
|
+
{ cmd: "hivemind skillify pull --all-users", desc: 'explicit "no author filter" (default)' },
|
|
576
|
+
{ cmd: "hivemind skillify pull --to <project|global>", desc: "install location (project=cwd/.claude/skills, global=~/.claude/skills)" },
|
|
577
|
+
{ cmd: "hivemind skillify pull --dry-run", desc: "preview without touching disk" },
|
|
578
|
+
{ cmd: "hivemind skillify pull --force", desc: "overwrite local files even if up-to-date (creates .bak)" },
|
|
579
|
+
{ cmd: "hivemind skillify pull <skill-name>", desc: "pull only that one skill (combines with --user)" },
|
|
580
|
+
{ cmd: "hivemind skillify unpull", desc: "remove every skill previously installed by pull" },
|
|
581
|
+
{ cmd: "hivemind skillify unpull --user <email>", desc: "remove only that author's pulls" },
|
|
582
|
+
{ cmd: "hivemind skillify unpull --not-mine", desc: "remove all pulls except your own" },
|
|
583
|
+
{ cmd: "hivemind skillify unpull --dry-run", desc: "preview without touching disk" },
|
|
584
|
+
{ cmd: "hivemind skillify scope <me|team|org>", desc: "sharing scope for newly mined skills" },
|
|
585
|
+
{ cmd: "hivemind skillify install <project|global>", desc: "default install location for new skills" },
|
|
586
|
+
{ cmd: "hivemind skillify promote <skill-name>", desc: "move a project skill to the global location" },
|
|
587
|
+
{ cmd: "hivemind skillify team add|remove|list <name>", desc: "manage team member list" },
|
|
588
|
+
{ cmd: "hivemind skillify mine-local", desc: "one-shot: mine skills from local sessions (no auth needed)" },
|
|
589
|
+
{ cmd: "hivemind skillify mine-local --n <num|all>", desc: "how many sessions to mine (default: 8)" },
|
|
590
|
+
{ cmd: "hivemind skillify mine-local --force", desc: "re-run even if the manifest sentinel exists" },
|
|
591
|
+
{ cmd: "hivemind skillify mine-local --dry-run", desc: "stop before calling the LLM gate" }
|
|
592
|
+
];
|
|
593
|
+
function renderSkillifyCommands() {
|
|
594
|
+
const maxLen = Math.max(...SKILLIFY_COMMANDS.map((c) => c.cmd.length));
|
|
595
|
+
return SKILLIFY_COMMANDS.map((c) => `- ${c.cmd.padEnd(maxLen + 2)} \u2014 ${c.desc}`).join("\n");
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// dist/src/skillify/local-manifest.js
|
|
599
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
600
|
+
import { homedir as homedir4 } from "node:os";
|
|
601
|
+
import { dirname, join as join5 } from "node:path";
|
|
602
|
+
var LOCAL_MANIFEST_PATH = join5(homedir4(), ".claude", "hivemind", "local-mined.json");
|
|
603
|
+
var LOCAL_MINE_LOCK_PATH = join5(homedir4(), ".claude", "hivemind", "local-mined.lock");
|
|
604
|
+
function readLocalManifest(path = LOCAL_MANIFEST_PATH) {
|
|
605
|
+
if (!existsSync3(path))
|
|
606
|
+
return null;
|
|
607
|
+
try {
|
|
608
|
+
return JSON.parse(readFileSync4(path, "utf-8"));
|
|
609
|
+
} catch {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function countLocalManifestEntries(path = LOCAL_MANIFEST_PATH) {
|
|
614
|
+
const m = readLocalManifest(path);
|
|
615
|
+
return Array.isArray(m?.entries) ? m.entries.length : 0;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// dist/src/skillify/spawn-mine-local-worker.js
|
|
619
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
620
|
+
import { closeSync, existsSync as existsSync4, mkdirSync as mkdirSync4, openSync, readdirSync, statSync, unlinkSync as unlinkSync2 } from "node:fs";
|
|
621
|
+
import { homedir as homedir5 } from "node:os";
|
|
622
|
+
import { dirname as dirname2, join as join6 } from "node:path";
|
|
623
|
+
import { fileURLToPath } from "node:url";
|
|
624
|
+
var HOME = homedir5();
|
|
625
|
+
var HIVEMIND_DIR = join6(HOME, ".claude", "hivemind");
|
|
626
|
+
var LOG_PATH = join6(HOME, ".claude", "hooks", "mine-local.log");
|
|
627
|
+
var CLAUDE_PROJECTS_DIR = join6(HOME, ".claude", "projects");
|
|
628
|
+
var LOCK_STALE_MS = 15 * 60 * 1e3;
|
|
629
|
+
function findBundledCliPath() {
|
|
630
|
+
try {
|
|
631
|
+
const thisDir = dirname2(fileURLToPath(import.meta.url));
|
|
632
|
+
const cliPath = join6(thisDir, "..", "..", "bundle", "cli.js");
|
|
633
|
+
return existsSync4(cliPath) ? cliPath : null;
|
|
634
|
+
} catch {
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
function findHivemindLauncher() {
|
|
639
|
+
const bundled = findBundledCliPath();
|
|
640
|
+
if (bundled)
|
|
641
|
+
return { kind: "node-script", path: bundled };
|
|
642
|
+
try {
|
|
643
|
+
const out = execFileSync("which", ["hivemind"], {
|
|
644
|
+
encoding: "utf-8",
|
|
645
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
646
|
+
});
|
|
647
|
+
const bin = out.trim();
|
|
648
|
+
return bin ? { kind: "bin", path: bin } : null;
|
|
649
|
+
} catch {
|
|
650
|
+
return null;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
function hasLocalClaudeSessions() {
|
|
654
|
+
if (!existsSync4(CLAUDE_PROJECTS_DIR))
|
|
655
|
+
return false;
|
|
656
|
+
let subdirs;
|
|
657
|
+
try {
|
|
658
|
+
subdirs = readdirSync(CLAUDE_PROJECTS_DIR);
|
|
659
|
+
} catch {
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
for (const sub of subdirs) {
|
|
663
|
+
let files;
|
|
664
|
+
try {
|
|
665
|
+
files = readdirSync(join6(CLAUDE_PROJECTS_DIR, sub));
|
|
666
|
+
} catch {
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
if (files.some((f) => f.endsWith(".jsonl")))
|
|
670
|
+
return true;
|
|
671
|
+
}
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
function maybeAutoMineLocal() {
|
|
675
|
+
if (existsSync4(LOCAL_MANIFEST_PATH))
|
|
676
|
+
return { triggered: false, reason: "manifest-exists" };
|
|
677
|
+
if (existsSync4(LOCAL_MINE_LOCK_PATH)) {
|
|
678
|
+
let stale = false;
|
|
679
|
+
try {
|
|
680
|
+
const stats = statSync(LOCAL_MINE_LOCK_PATH);
|
|
681
|
+
stale = Date.now() - stats.mtimeMs > LOCK_STALE_MS;
|
|
682
|
+
} catch {
|
|
683
|
+
}
|
|
684
|
+
if (!stale)
|
|
685
|
+
return { triggered: false, reason: "lock-exists" };
|
|
686
|
+
try {
|
|
687
|
+
unlinkSync2(LOCAL_MINE_LOCK_PATH);
|
|
688
|
+
} catch {
|
|
689
|
+
return { triggered: false, reason: "lock-exists" };
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
if (!hasLocalClaudeSessions())
|
|
693
|
+
return { triggered: false, reason: "no-claude-sessions" };
|
|
694
|
+
const launcher = findHivemindLauncher();
|
|
695
|
+
if (!launcher)
|
|
696
|
+
return { triggered: false, reason: "no-hivemind-bin" };
|
|
697
|
+
try {
|
|
698
|
+
mkdirSync4(HIVEMIND_DIR, { recursive: true });
|
|
699
|
+
const fd = openSync(LOCAL_MINE_LOCK_PATH, "wx");
|
|
700
|
+
closeSync(fd);
|
|
701
|
+
} catch {
|
|
702
|
+
return { triggered: false, reason: "lock-acquire-failed" };
|
|
703
|
+
}
|
|
704
|
+
try {
|
|
705
|
+
mkdirSync4(join6(HOME, ".claude", "hooks"), { recursive: true });
|
|
706
|
+
const out = openSync(LOG_PATH, "a");
|
|
707
|
+
const [cmd, args] = launcher.kind === "node-script" ? [process.execPath, [launcher.path, "skillify", "mine-local"]] : [launcher.path, ["skillify", "mine-local"]];
|
|
708
|
+
const child = spawn(cmd, args, {
|
|
709
|
+
detached: true,
|
|
710
|
+
stdio: ["ignore", out, out],
|
|
711
|
+
env: process.env
|
|
712
|
+
});
|
|
713
|
+
closeSync(out);
|
|
714
|
+
child.unref();
|
|
715
|
+
return { triggered: true };
|
|
716
|
+
} catch {
|
|
717
|
+
try {
|
|
718
|
+
unlinkSync2(LOCAL_MINE_LOCK_PATH);
|
|
719
|
+
} catch {
|
|
720
|
+
}
|
|
721
|
+
return { triggered: false, reason: "spawn-failed" };
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
564
725
|
// dist/src/utils/stdin.js
|
|
565
726
|
function readStdin() {
|
|
566
727
|
return new Promise((resolve, reject) => {
|
|
@@ -579,18 +740,18 @@ function readStdin() {
|
|
|
579
740
|
}
|
|
580
741
|
|
|
581
742
|
// dist/src/utils/version-check.js
|
|
582
|
-
import { readFileSync as
|
|
583
|
-
import { dirname, join as
|
|
743
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
744
|
+
import { dirname as dirname3, join as join7 } from "node:path";
|
|
584
745
|
function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
585
746
|
try {
|
|
586
|
-
const pluginJson =
|
|
587
|
-
const plugin = JSON.parse(
|
|
747
|
+
const pluginJson = join7(bundleDir, "..", pluginManifestDir, "plugin.json");
|
|
748
|
+
const plugin = JSON.parse(readFileSync5(pluginJson, "utf-8"));
|
|
588
749
|
if (plugin.version)
|
|
589
750
|
return plugin.version;
|
|
590
751
|
} catch {
|
|
591
752
|
}
|
|
592
753
|
try {
|
|
593
|
-
const stamp =
|
|
754
|
+
const stamp = readFileSync5(join7(bundleDir, "..", ".hivemind_version"), "utf-8").trim();
|
|
594
755
|
if (stamp)
|
|
595
756
|
return stamp;
|
|
596
757
|
} catch {
|
|
@@ -605,14 +766,14 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
|
605
766
|
]);
|
|
606
767
|
let dir = bundleDir;
|
|
607
768
|
for (let i = 0; i < 5; i++) {
|
|
608
|
-
const candidate =
|
|
769
|
+
const candidate = join7(dir, "package.json");
|
|
609
770
|
try {
|
|
610
|
-
const pkg = JSON.parse(
|
|
771
|
+
const pkg = JSON.parse(readFileSync5(candidate, "utf-8"));
|
|
611
772
|
if (HIVEMIND_PKG_NAMES.has(pkg.name) && pkg.version)
|
|
612
773
|
return pkg.version;
|
|
613
774
|
} catch {
|
|
614
775
|
}
|
|
615
|
-
const parent =
|
|
776
|
+
const parent = dirname3(dir);
|
|
616
777
|
if (parent === dir)
|
|
617
778
|
break;
|
|
618
779
|
dir = parent;
|
|
@@ -621,12 +782,12 @@ function getInstalledVersion(bundleDir, pluginManifestDir) {
|
|
|
621
782
|
}
|
|
622
783
|
|
|
623
784
|
// dist/src/hooks/shared/autoupdate.js
|
|
624
|
-
import { spawn } from "node:child_process";
|
|
625
|
-
import { existsSync as
|
|
626
|
-
import { join as
|
|
785
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
786
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
787
|
+
import { join as join8 } from "node:path";
|
|
627
788
|
var log3 = (msg) => log("autoupdate", msg);
|
|
628
789
|
var defaultSpawn = (cmd, args) => {
|
|
629
|
-
const child =
|
|
790
|
+
const child = spawn2(cmd, args, {
|
|
630
791
|
detached: true,
|
|
631
792
|
stdio: "ignore"
|
|
632
793
|
});
|
|
@@ -639,8 +800,8 @@ function findHivemindOnPath() {
|
|
|
639
800
|
const PATH = process.env.PATH ?? "";
|
|
640
801
|
const dirs = PATH.split(":").filter(Boolean);
|
|
641
802
|
for (const dir of dirs) {
|
|
642
|
-
const candidate =
|
|
643
|
-
if (
|
|
803
|
+
const candidate = join8(dir, "hivemind");
|
|
804
|
+
if (existsSync5(candidate))
|
|
644
805
|
return candidate;
|
|
645
806
|
}
|
|
646
807
|
return null;
|
|
@@ -674,14 +835,14 @@ async function autoUpdate(creds, opts) {
|
|
|
674
835
|
}
|
|
675
836
|
|
|
676
837
|
// dist/src/skillify/pull.js
|
|
677
|
-
import { existsSync as
|
|
678
|
-
import { homedir as
|
|
679
|
-
import { dirname as
|
|
838
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, renameSync as renameSync3, lstatSync as lstatSync2, readlinkSync, symlinkSync, unlinkSync as unlinkSync4 } from "node:fs";
|
|
839
|
+
import { homedir as homedir10 } from "node:os";
|
|
840
|
+
import { dirname as dirname5, join as join13 } from "node:path";
|
|
680
841
|
|
|
681
842
|
// dist/src/skillify/skill-writer.js
|
|
682
|
-
import { existsSync as
|
|
683
|
-
import { homedir as
|
|
684
|
-
import { join as
|
|
843
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
844
|
+
import { homedir as homedir6 } from "node:os";
|
|
845
|
+
import { join as join9 } from "node:path";
|
|
685
846
|
function assertValidSkillName(name) {
|
|
686
847
|
if (typeof name !== "string" || name.length === 0) {
|
|
687
848
|
throw new Error(`invalid skill name: empty or non-string`);
|
|
@@ -747,26 +908,26 @@ function parseFrontmatter(text) {
|
|
|
747
908
|
}
|
|
748
909
|
|
|
749
910
|
// dist/src/skillify/manifest.js
|
|
750
|
-
import { existsSync as
|
|
751
|
-
import { homedir as
|
|
752
|
-
import { dirname as
|
|
911
|
+
import { existsSync as existsSync8, lstatSync, mkdirSync as mkdirSync6, readFileSync as readFileSync7, renameSync as renameSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
912
|
+
import { homedir as homedir8 } from "node:os";
|
|
913
|
+
import { dirname as dirname4, join as join11 } from "node:path";
|
|
753
914
|
|
|
754
915
|
// dist/src/skillify/legacy-migration.js
|
|
755
|
-
import { existsSync as
|
|
756
|
-
import { homedir as
|
|
757
|
-
import { join as
|
|
916
|
+
import { existsSync as existsSync7, renameSync } from "node:fs";
|
|
917
|
+
import { homedir as homedir7 } from "node:os";
|
|
918
|
+
import { join as join10 } from "node:path";
|
|
758
919
|
var dlog = (msg) => log("skillify-migrate", msg);
|
|
759
920
|
var attempted = false;
|
|
760
921
|
function migrateLegacyStateDir() {
|
|
761
922
|
if (attempted)
|
|
762
923
|
return;
|
|
763
924
|
attempted = true;
|
|
764
|
-
const root =
|
|
765
|
-
const legacy =
|
|
766
|
-
const current =
|
|
767
|
-
if (!
|
|
925
|
+
const root = join10(homedir7(), ".deeplake", "state");
|
|
926
|
+
const legacy = join10(root, "skilify");
|
|
927
|
+
const current = join10(root, "skillify");
|
|
928
|
+
if (!existsSync7(legacy))
|
|
768
929
|
return;
|
|
769
|
-
if (
|
|
930
|
+
if (existsSync7(current))
|
|
770
931
|
return;
|
|
771
932
|
try {
|
|
772
933
|
renameSync(legacy, current);
|
|
@@ -786,15 +947,15 @@ function emptyManifest() {
|
|
|
786
947
|
return { version: 1, entries: [] };
|
|
787
948
|
}
|
|
788
949
|
function manifestPath() {
|
|
789
|
-
return
|
|
950
|
+
return join11(homedir8(), ".deeplake", "state", "skillify", "pulled.json");
|
|
790
951
|
}
|
|
791
952
|
function loadManifest(path = manifestPath()) {
|
|
792
953
|
migrateLegacyStateDir();
|
|
793
|
-
if (!
|
|
954
|
+
if (!existsSync8(path))
|
|
794
955
|
return emptyManifest();
|
|
795
956
|
let raw;
|
|
796
957
|
try {
|
|
797
|
-
raw =
|
|
958
|
+
raw = readFileSync7(path, "utf-8");
|
|
798
959
|
} catch {
|
|
799
960
|
return emptyManifest();
|
|
800
961
|
}
|
|
@@ -841,9 +1002,9 @@ function loadManifest(path = manifestPath()) {
|
|
|
841
1002
|
}
|
|
842
1003
|
function saveManifest(m, path = manifestPath()) {
|
|
843
1004
|
migrateLegacyStateDir();
|
|
844
|
-
|
|
1005
|
+
mkdirSync6(dirname4(path), { recursive: true });
|
|
845
1006
|
const tmp = `${path}.tmp`;
|
|
846
|
-
|
|
1007
|
+
writeFileSync5(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
|
|
847
1008
|
renameSync2(tmp, path);
|
|
848
1009
|
}
|
|
849
1010
|
function recordPull(entry, path = manifestPath()) {
|
|
@@ -869,7 +1030,7 @@ function unlinkSymlinks(paths) {
|
|
|
869
1030
|
if (!st.isSymbolicLink())
|
|
870
1031
|
continue;
|
|
871
1032
|
try {
|
|
872
|
-
|
|
1033
|
+
unlinkSync3(path);
|
|
873
1034
|
} catch {
|
|
874
1035
|
}
|
|
875
1036
|
}
|
|
@@ -879,7 +1040,7 @@ function pruneOrphanedEntries(path = manifestPath()) {
|
|
|
879
1040
|
const live = [];
|
|
880
1041
|
let pruned = 0;
|
|
881
1042
|
for (const e of m.entries) {
|
|
882
|
-
if (
|
|
1043
|
+
if (existsSync8(join11(e.installRoot, e.dirName))) {
|
|
883
1044
|
live.push(e);
|
|
884
1045
|
continue;
|
|
885
1046
|
}
|
|
@@ -892,26 +1053,26 @@ function pruneOrphanedEntries(path = manifestPath()) {
|
|
|
892
1053
|
}
|
|
893
1054
|
|
|
894
1055
|
// dist/src/skillify/agent-roots.js
|
|
895
|
-
import { existsSync as
|
|
896
|
-
import { homedir as
|
|
897
|
-
import { join as
|
|
1056
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
1057
|
+
import { homedir as homedir9 } from "node:os";
|
|
1058
|
+
import { join as join12 } from "node:path";
|
|
898
1059
|
function resolveDetected(home) {
|
|
899
1060
|
const out = [];
|
|
900
|
-
const codexInstalled =
|
|
901
|
-
const piInstalled =
|
|
902
|
-
const hermesInstalled =
|
|
1061
|
+
const codexInstalled = existsSync9(join12(home, ".codex"));
|
|
1062
|
+
const piInstalled = existsSync9(join12(home, ".pi", "agent"));
|
|
1063
|
+
const hermesInstalled = existsSync9(join12(home, ".hermes"));
|
|
903
1064
|
if (codexInstalled || piInstalled) {
|
|
904
|
-
out.push(
|
|
1065
|
+
out.push(join12(home, ".agents", "skills"));
|
|
905
1066
|
}
|
|
906
1067
|
if (hermesInstalled) {
|
|
907
|
-
out.push(
|
|
1068
|
+
out.push(join12(home, ".hermes", "skills"));
|
|
908
1069
|
}
|
|
909
1070
|
if (piInstalled) {
|
|
910
|
-
out.push(
|
|
1071
|
+
out.push(join12(home, ".pi", "agent", "skills"));
|
|
911
1072
|
}
|
|
912
1073
|
return out;
|
|
913
1074
|
}
|
|
914
|
-
function detectAgentSkillsRoots(canonicalRoot, home =
|
|
1075
|
+
function detectAgentSkillsRoots(canonicalRoot, home = homedir9()) {
|
|
915
1076
|
return resolveDetected(home).filter((p) => p !== canonicalRoot);
|
|
916
1077
|
}
|
|
917
1078
|
|
|
@@ -955,15 +1116,15 @@ function isMissingTableError(message) {
|
|
|
955
1116
|
}
|
|
956
1117
|
function resolvePullDestination(install, cwd) {
|
|
957
1118
|
if (install === "global")
|
|
958
|
-
return
|
|
1119
|
+
return join13(homedir10(), ".claude", "skills");
|
|
959
1120
|
if (!cwd)
|
|
960
1121
|
throw new Error("install=project requires a cwd");
|
|
961
|
-
return
|
|
1122
|
+
return join13(cwd, ".claude", "skills");
|
|
962
1123
|
}
|
|
963
1124
|
function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
964
1125
|
const out = [];
|
|
965
1126
|
for (const root of agentRoots) {
|
|
966
|
-
const link =
|
|
1127
|
+
const link = join13(root, dirName);
|
|
967
1128
|
let existing;
|
|
968
1129
|
try {
|
|
969
1130
|
existing = lstatSync2(link);
|
|
@@ -985,13 +1146,13 @@ function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
|
985
1146
|
continue;
|
|
986
1147
|
}
|
|
987
1148
|
try {
|
|
988
|
-
|
|
1149
|
+
unlinkSync4(link);
|
|
989
1150
|
} catch {
|
|
990
1151
|
continue;
|
|
991
1152
|
}
|
|
992
1153
|
}
|
|
993
1154
|
try {
|
|
994
|
-
|
|
1155
|
+
mkdirSync7(dirname5(link), { recursive: true });
|
|
995
1156
|
symlinkSync(canonicalDir, link, "dir");
|
|
996
1157
|
out.push(link);
|
|
997
1158
|
} catch {
|
|
@@ -1006,8 +1167,8 @@ function backfillSymlinks(installRoot) {
|
|
|
1006
1167
|
return;
|
|
1007
1168
|
const detected = detectAgentSkillsRoots(installRoot);
|
|
1008
1169
|
for (const entry of entries) {
|
|
1009
|
-
const canonical =
|
|
1010
|
-
if (!
|
|
1170
|
+
const canonical = join13(entry.installRoot, entry.dirName);
|
|
1171
|
+
if (!existsSync10(canonical))
|
|
1011
1172
|
continue;
|
|
1012
1173
|
const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
|
|
1013
1174
|
if (sameSorted(fresh, entry.symlinks))
|
|
@@ -1117,10 +1278,10 @@ function renderFrontmatter(fm) {
|
|
|
1117
1278
|
return lines.join("\n");
|
|
1118
1279
|
}
|
|
1119
1280
|
function readLocalVersion(path) {
|
|
1120
|
-
if (!
|
|
1281
|
+
if (!existsSync10(path))
|
|
1121
1282
|
return null;
|
|
1122
1283
|
try {
|
|
1123
|
-
const text =
|
|
1284
|
+
const text = readFileSync8(path, "utf-8");
|
|
1124
1285
|
const parsed = parseFrontmatter(text);
|
|
1125
1286
|
if (!parsed)
|
|
1126
1287
|
return null;
|
|
@@ -1215,8 +1376,8 @@ async function runPull(opts) {
|
|
|
1215
1376
|
summary.skipped++;
|
|
1216
1377
|
continue;
|
|
1217
1378
|
}
|
|
1218
|
-
const skillDir =
|
|
1219
|
-
const skillFile =
|
|
1379
|
+
const skillDir = join13(root, dirName);
|
|
1380
|
+
const skillFile = join13(skillDir, "SKILL.md");
|
|
1220
1381
|
const remoteVersion = Number(row.version ?? 1);
|
|
1221
1382
|
const localVersion = readLocalVersion(skillFile);
|
|
1222
1383
|
const action = decideAction({
|
|
@@ -1227,14 +1388,14 @@ async function runPull(opts) {
|
|
|
1227
1388
|
});
|
|
1228
1389
|
let manifestError;
|
|
1229
1390
|
if (action === "wrote") {
|
|
1230
|
-
|
|
1231
|
-
if (
|
|
1391
|
+
mkdirSync7(skillDir, { recursive: true });
|
|
1392
|
+
if (existsSync10(skillFile)) {
|
|
1232
1393
|
try {
|
|
1233
1394
|
renameSync3(skillFile, `${skillFile}.bak`);
|
|
1234
1395
|
} catch {
|
|
1235
1396
|
}
|
|
1236
1397
|
}
|
|
1237
|
-
|
|
1398
|
+
writeFileSync6(skillFile, renderSkillFile(row));
|
|
1238
1399
|
const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir, dirName, detectAgentSkillsRoots(root)) : [];
|
|
1239
1400
|
try {
|
|
1240
1401
|
recordPull({
|
|
@@ -1330,7 +1491,7 @@ async function autoPullSkills(deps = {}) {
|
|
|
1330
1491
|
|
|
1331
1492
|
// dist/src/hooks/cursor/session-start.js
|
|
1332
1493
|
var log5 = (msg) => log("cursor-session-start", msg);
|
|
1333
|
-
var __bundleDir =
|
|
1494
|
+
var __bundleDir = dirname6(fileURLToPath2(import.meta.url));
|
|
1334
1495
|
var context = `DEEPLAKE MEMORY: Persistent memory at ~/.deeplake/memory/ shared across sessions, users, and agents.
|
|
1335
1496
|
|
|
1336
1497
|
Structure: index.md (start here) \u2192 summaries/*.md \u2192 sessions/*.jsonl (last resort). Do NOT jump straight to JSONL.
|
|
@@ -1350,22 +1511,7 @@ Organization management \u2014 each argument is SEPARATE (do NOT quote subcomman
|
|
|
1350
1511
|
- hivemind remove <user-id> \u2014 remove member
|
|
1351
1512
|
|
|
1352
1513
|
SKILLS (skillify) \u2014 mine + share reusable skills across the org:
|
|
1353
|
-
|
|
1354
|
-
- hivemind skillify pull \u2014 sync project skills from the org table
|
|
1355
|
-
- hivemind skillify pull --user <email> \u2014 only that author's skills
|
|
1356
|
-
- hivemind skillify pull --users a,b,c \u2014 multiple authors (CSV)
|
|
1357
|
-
- hivemind skillify pull --all-users \u2014 explicit "no author filter"
|
|
1358
|
-
- hivemind skillify pull --to project|global \u2014 install location
|
|
1359
|
-
- hivemind skillify pull --dry-run \u2014 preview only
|
|
1360
|
-
- hivemind skillify pull --force \u2014 overwrite local (creates .bak)
|
|
1361
|
-
- hivemind skillify pull <skill-name> \u2014 pull only that skill (combines with --user)
|
|
1362
|
-
- hivemind skillify unpull \u2014 remove every skill previously installed by pull
|
|
1363
|
-
- hivemind skillify unpull --user <email> \u2014 remove only that author's pulls
|
|
1364
|
-
- hivemind skillify unpull --not-mine \u2014 remove all pulls except your own
|
|
1365
|
-
- hivemind skillify unpull --dry-run \u2014 preview without touching disk
|
|
1366
|
-
- hivemind skillify scope <me|team> \u2014 sharing scope for new skills
|
|
1367
|
-
- hivemind skillify install <project|global> \u2014 default install location
|
|
1368
|
-
- hivemind skillify team add|remove|list <name> \u2014 manage team list`;
|
|
1514
|
+
${renderSkillifyCommands()}`;
|
|
1369
1515
|
function resolveSessionId(input) {
|
|
1370
1516
|
return input.session_id ?? input.conversation_id ?? `cursor-${Date.now()}`;
|
|
1371
1517
|
}
|
|
@@ -1404,6 +1550,8 @@ async function main() {
|
|
|
1404
1550
|
const creds = loadCredentials();
|
|
1405
1551
|
if (!creds?.token) {
|
|
1406
1552
|
log5("no credentials found");
|
|
1553
|
+
const auto = maybeAutoMineLocal();
|
|
1554
|
+
log5(`auto-mine: ${auto.triggered ? "triggered (background)" : `skipped (${auto.reason})`}`);
|
|
1407
1555
|
} else {
|
|
1408
1556
|
log5(`credentials loaded: org=${creds.orgName ?? creds.orgId}`);
|
|
1409
1557
|
}
|
|
@@ -1433,9 +1581,12 @@ async function main() {
|
|
|
1433
1581
|
if (current)
|
|
1434
1582
|
versionNotice = `
|
|
1435
1583
|
Hivemind v${current}`;
|
|
1584
|
+
const localMined = countLocalManifestEntries();
|
|
1585
|
+
const localMinedNote = localMined > 0 ? `
|
|
1586
|
+
${localMined} local skill${localMined === 1 ? "" : "s"} from past 'hivemind skillify mine-local' run(s) live in ~/.claude/skills/. Run 'hivemind login' to start sharing new mining results with your team.` : "";
|
|
1436
1587
|
const additionalContext = creds?.token ? `${context}
|
|
1437
1588
|
Logged in to Deeplake as org: ${creds.orgName ?? creds.orgId} (workspace: ${creds.workspaceId ?? "default"})${versionNotice}` : `${context}
|
|
1438
|
-
Not logged in to Deeplake. Run: hivemind login${versionNotice}`;
|
|
1589
|
+
Not logged in to Deeplake. Run: hivemind login${localMinedNote}${versionNotice}`;
|
|
1439
1590
|
console.log(JSON.stringify({ additional_context: additionalContext }));
|
|
1440
1591
|
}
|
|
1441
1592
|
main().catch((e) => {
|