@deeplake/hivemind 0.7.16 → 0.7.18
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 +294 -105
- package/codex/bundle/session-start.js +1154 -25
- package/codex/bundle/{skilify-worker.js → skillify-worker.js} +65 -30
- package/codex/bundle/stop.js +105 -68
- package/cursor/bundle/capture.js +84 -47
- package/cursor/bundle/session-end.js +82 -45
- package/cursor/bundle/session-start.js +633 -25
- package/cursor/bundle/{skilify-worker.js → skillify-worker.js} +65 -30
- package/hermes/bundle/capture.js +84 -47
- package/hermes/bundle/session-end.js +82 -45
- package/hermes/bundle/session-start.js +631 -23
- package/hermes/bundle/{skilify-worker.js → skillify-worker.js} +65 -30
- package/openclaw/dist/index.js +47 -30
- package/openclaw/dist/{skilify-worker.js → skillify-worker.js} +65 -30
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/openclaw/skills/SKILL.md +19 -19
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +94 -45
package/bundle/cli.js
CHANGED
|
@@ -3352,7 +3352,8 @@ var EXTENSION_PATH = join8(EXTENSIONS_DIR, "hivemind.ts");
|
|
|
3352
3352
|
var VERSION_DIR = join8(PI_AGENT_DIR, ".hivemind");
|
|
3353
3353
|
var WIKI_WORKER_DIR = join8(PI_AGENT_DIR, "hivemind");
|
|
3354
3354
|
var WIKI_WORKER_PATH = join8(WIKI_WORKER_DIR, "wiki-worker.js");
|
|
3355
|
-
var
|
|
3355
|
+
var SKILLIFY_WORKER_PATH = join8(WIKI_WORKER_DIR, "skillify-worker.js");
|
|
3356
|
+
var AUTOPULL_WORKER_PATH = join8(WIKI_WORKER_DIR, "autopull-worker.js");
|
|
3356
3357
|
var HIVEMIND_BLOCK_START = "<!-- BEGIN hivemind-memory -->";
|
|
3357
3358
|
var HIVEMIND_BLOCK_END = "<!-- END hivemind-memory -->";
|
|
3358
3359
|
var HIVEMIND_BLOCK_BODY = `${HIVEMIND_BLOCK_START}
|
|
@@ -3437,10 +3438,15 @@ function installPi() {
|
|
|
3437
3438
|
ensureDir(WIKI_WORKER_DIR);
|
|
3438
3439
|
copyFileSync2(srcWorker, WIKI_WORKER_PATH);
|
|
3439
3440
|
}
|
|
3440
|
-
const
|
|
3441
|
-
if (existsSync7(
|
|
3441
|
+
const srcSkillifyWorker = join8(pkgRoot(), "pi", "bundle", "skillify-worker.js");
|
|
3442
|
+
if (existsSync7(srcSkillifyWorker)) {
|
|
3442
3443
|
ensureDir(WIKI_WORKER_DIR);
|
|
3443
|
-
copyFileSync2(
|
|
3444
|
+
copyFileSync2(srcSkillifyWorker, SKILLIFY_WORKER_PATH);
|
|
3445
|
+
}
|
|
3446
|
+
const srcAutopullWorker = join8(pkgRoot(), "pi", "bundle", "autopull-worker.js");
|
|
3447
|
+
if (existsSync7(srcAutopullWorker)) {
|
|
3448
|
+
ensureDir(WIKI_WORKER_DIR);
|
|
3449
|
+
copyFileSync2(srcAutopullWorker, AUTOPULL_WORKER_PATH);
|
|
3444
3450
|
}
|
|
3445
3451
|
ensureDir(VERSION_DIR);
|
|
3446
3452
|
writeVersionStamp(VERSION_DIR, getVersion());
|
|
@@ -3449,8 +3455,11 @@ function installPi() {
|
|
|
3449
3455
|
if (existsSync7(WIKI_WORKER_PATH)) {
|
|
3450
3456
|
log(` pi wiki-worker installed -> ${WIKI_WORKER_PATH}`);
|
|
3451
3457
|
}
|
|
3452
|
-
if (existsSync7(
|
|
3453
|
-
log(` pi
|
|
3458
|
+
if (existsSync7(SKILLIFY_WORKER_PATH)) {
|
|
3459
|
+
log(` pi skillify-worker installed -> ${SKILLIFY_WORKER_PATH}`);
|
|
3460
|
+
}
|
|
3461
|
+
if (existsSync7(AUTOPULL_WORKER_PATH)) {
|
|
3462
|
+
log(` pi autopull-worker installed -> ${AUTOPULL_WORKER_PATH}`);
|
|
3454
3463
|
}
|
|
3455
3464
|
}
|
|
3456
3465
|
function uninstallPi() {
|
|
@@ -4709,20 +4718,53 @@ if (process.argv[1] && process.argv[1].endsWith("auth-login.js")) {
|
|
|
4709
4718
|
});
|
|
4710
4719
|
}
|
|
4711
4720
|
|
|
4712
|
-
// dist/src/commands/
|
|
4713
|
-
import { readdirSync as readdirSync4, existsSync as
|
|
4714
|
-
import { homedir as
|
|
4715
|
-
import { dirname as
|
|
4721
|
+
// dist/src/commands/skillify.js
|
|
4722
|
+
import { readdirSync as readdirSync4, existsSync as existsSync19, readFileSync as readFileSync13, mkdirSync as mkdirSync8, renameSync as renameSync4 } from "node:fs";
|
|
4723
|
+
import { homedir as homedir12 } from "node:os";
|
|
4724
|
+
import { dirname as dirname4, join as join22 } from "node:path";
|
|
4725
|
+
|
|
4726
|
+
// dist/src/skillify/scope-config.js
|
|
4727
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
4728
|
+
import { homedir as homedir6 } from "node:os";
|
|
4729
|
+
import { join as join16 } from "node:path";
|
|
4716
4730
|
|
|
4717
|
-
// dist/src/
|
|
4718
|
-
import { existsSync as existsSync12,
|
|
4731
|
+
// dist/src/skillify/legacy-migration.js
|
|
4732
|
+
import { existsSync as existsSync12, renameSync } from "node:fs";
|
|
4719
4733
|
import { homedir as homedir5 } from "node:os";
|
|
4720
4734
|
import { join as join15 } from "node:path";
|
|
4721
|
-
var
|
|
4722
|
-
var
|
|
4735
|
+
var dlog = (msg) => log2("skillify-migrate", msg);
|
|
4736
|
+
var attempted = false;
|
|
4737
|
+
function migrateLegacyStateDir() {
|
|
4738
|
+
if (attempted)
|
|
4739
|
+
return;
|
|
4740
|
+
attempted = true;
|
|
4741
|
+
const root = join15(homedir5(), ".deeplake", "state");
|
|
4742
|
+
const legacy = join15(root, "skilify");
|
|
4743
|
+
const current = join15(root, "skillify");
|
|
4744
|
+
if (!existsSync12(legacy))
|
|
4745
|
+
return;
|
|
4746
|
+
if (existsSync12(current))
|
|
4747
|
+
return;
|
|
4748
|
+
try {
|
|
4749
|
+
renameSync(legacy, current);
|
|
4750
|
+
dlog(`migrated ${legacy} -> ${current}`);
|
|
4751
|
+
} catch (err) {
|
|
4752
|
+
const code = err.code;
|
|
4753
|
+
if (code === "EXDEV" || code === "EPERM") {
|
|
4754
|
+
dlog(`migration failed (${code}); leaving legacy dir in place`);
|
|
4755
|
+
return;
|
|
4756
|
+
}
|
|
4757
|
+
throw err;
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
4760
|
+
|
|
4761
|
+
// dist/src/skillify/scope-config.js
|
|
4762
|
+
var STATE_DIR = join16(homedir6(), ".deeplake", "state", "skillify");
|
|
4763
|
+
var CONFIG_PATH2 = join16(STATE_DIR, "config.json");
|
|
4723
4764
|
var DEFAULT = { scope: "me", team: [], install: "project" };
|
|
4724
4765
|
function loadScopeConfig() {
|
|
4725
|
-
|
|
4766
|
+
migrateLegacyStateDir();
|
|
4767
|
+
if (!existsSync13(CONFIG_PATH2))
|
|
4726
4768
|
return DEFAULT;
|
|
4727
4769
|
try {
|
|
4728
4770
|
const raw = JSON.parse(readFileSync9(CONFIG_PATH2, "utf-8"));
|
|
@@ -4735,19 +4777,20 @@ function loadScopeConfig() {
|
|
|
4735
4777
|
}
|
|
4736
4778
|
}
|
|
4737
4779
|
function saveScopeConfig(cfg) {
|
|
4780
|
+
migrateLegacyStateDir();
|
|
4738
4781
|
mkdirSync4(STATE_DIR, { recursive: true });
|
|
4739
4782
|
writeFileSync6(CONFIG_PATH2, JSON.stringify(cfg, null, 2));
|
|
4740
4783
|
}
|
|
4741
4784
|
|
|
4742
|
-
// dist/src/
|
|
4743
|
-
import { existsSync as
|
|
4744
|
-
import { homedir as
|
|
4745
|
-
import { join as
|
|
4785
|
+
// dist/src/skillify/pull.js
|
|
4786
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync7, renameSync as renameSync3, lstatSync as lstatSync4, readlinkSync as readlinkSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync8 } from "node:fs";
|
|
4787
|
+
import { homedir as homedir10 } from "node:os";
|
|
4788
|
+
import { dirname as dirname3, join as join20 } from "node:path";
|
|
4746
4789
|
|
|
4747
|
-
// dist/src/
|
|
4748
|
-
import { existsSync as
|
|
4749
|
-
import { homedir as
|
|
4750
|
-
import { join as
|
|
4790
|
+
// dist/src/skillify/skill-writer.js
|
|
4791
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync10, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
4792
|
+
import { homedir as homedir7 } from "node:os";
|
|
4793
|
+
import { join as join17 } from "node:path";
|
|
4751
4794
|
function assertValidSkillName(name) {
|
|
4752
4795
|
if (typeof name !== "string" || name.length === 0) {
|
|
4753
4796
|
throw new Error(`invalid skill name: empty or non-string`);
|
|
@@ -4805,18 +4848,19 @@ function parseFrontmatter(text) {
|
|
|
4805
4848
|
return { fm, body };
|
|
4806
4849
|
}
|
|
4807
4850
|
|
|
4808
|
-
// dist/src/
|
|
4809
|
-
import { existsSync as
|
|
4810
|
-
import { homedir as
|
|
4811
|
-
import { dirname as dirname2, join as
|
|
4851
|
+
// dist/src/skillify/manifest.js
|
|
4852
|
+
import { existsSync as existsSync15, lstatSync as lstatSync3, mkdirSync as mkdirSync6, readFileSync as readFileSync11, renameSync as renameSync2, unlinkSync as unlinkSync7, writeFileSync as writeFileSync8 } from "node:fs";
|
|
4853
|
+
import { homedir as homedir8 } from "node:os";
|
|
4854
|
+
import { dirname as dirname2, join as join18 } from "node:path";
|
|
4812
4855
|
function emptyManifest() {
|
|
4813
4856
|
return { version: 1, entries: [] };
|
|
4814
4857
|
}
|
|
4815
4858
|
function manifestPath() {
|
|
4816
|
-
return
|
|
4859
|
+
return join18(homedir8(), ".deeplake", "state", "skillify", "pulled.json");
|
|
4817
4860
|
}
|
|
4818
4861
|
function loadManifest(path = manifestPath()) {
|
|
4819
|
-
|
|
4862
|
+
migrateLegacyStateDir();
|
|
4863
|
+
if (!existsSync15(path))
|
|
4820
4864
|
return emptyManifest();
|
|
4821
4865
|
let raw;
|
|
4822
4866
|
try {
|
|
@@ -4846,6 +4890,8 @@ function loadManifest(path = manifestPath()) {
|
|
|
4846
4890
|
continue;
|
|
4847
4891
|
if (e.install !== "global" && e.install !== "project")
|
|
4848
4892
|
continue;
|
|
4893
|
+
const symlinks = Array.isArray(e.symlinks) ? e.symlinks.filter((p) => typeof p === "string" && p.length > 0 && (p.startsWith("/") || /^[A-Za-z]:[\\/]/.test(p)) && // absolute (POSIX or Windows)
|
|
4894
|
+
!p.includes("..")) : [];
|
|
4849
4895
|
entries.push({
|
|
4850
4896
|
dirName: e.dirName,
|
|
4851
4897
|
name: e.name,
|
|
@@ -4854,7 +4900,8 @@ function loadManifest(path = manifestPath()) {
|
|
|
4854
4900
|
remoteVersion: typeof e.remoteVersion === "number" ? e.remoteVersion : 1,
|
|
4855
4901
|
install: e.install,
|
|
4856
4902
|
installRoot: e.installRoot,
|
|
4857
|
-
pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
4903
|
+
pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
4904
|
+
symlinks
|
|
4858
4905
|
});
|
|
4859
4906
|
}
|
|
4860
4907
|
return { version: 1, entries };
|
|
@@ -4863,10 +4910,11 @@ function loadManifest(path = manifestPath()) {
|
|
|
4863
4910
|
}
|
|
4864
4911
|
}
|
|
4865
4912
|
function saveManifest(m, path = manifestPath()) {
|
|
4913
|
+
migrateLegacyStateDir();
|
|
4866
4914
|
mkdirSync6(dirname2(path), { recursive: true });
|
|
4867
4915
|
const tmp = `${path}.tmp`;
|
|
4868
4916
|
writeFileSync8(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
|
|
4869
|
-
|
|
4917
|
+
renameSync2(tmp, path);
|
|
4870
4918
|
}
|
|
4871
4919
|
function recordPull(entry, path = manifestPath()) {
|
|
4872
4920
|
const m = loadManifest(path);
|
|
@@ -4887,8 +4935,64 @@ function removePullEntry(install, installRoot, dirName, path = manifestPath()) {
|
|
|
4887
4935
|
function entriesForRoot(m, install, installRoot) {
|
|
4888
4936
|
return m.entries.filter((e) => e.install === install && e.installRoot === installRoot);
|
|
4889
4937
|
}
|
|
4938
|
+
function unlinkSymlinks(paths) {
|
|
4939
|
+
for (const path of paths) {
|
|
4940
|
+
let st;
|
|
4941
|
+
try {
|
|
4942
|
+
st = lstatSync3(path);
|
|
4943
|
+
} catch {
|
|
4944
|
+
continue;
|
|
4945
|
+
}
|
|
4946
|
+
if (!st.isSymbolicLink())
|
|
4947
|
+
continue;
|
|
4948
|
+
try {
|
|
4949
|
+
unlinkSync7(path);
|
|
4950
|
+
} catch {
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
function pruneOrphanedEntries(path = manifestPath()) {
|
|
4955
|
+
const m = loadManifest(path);
|
|
4956
|
+
const live = [];
|
|
4957
|
+
let pruned = 0;
|
|
4958
|
+
for (const e of m.entries) {
|
|
4959
|
+
if (existsSync15(join18(e.installRoot, e.dirName))) {
|
|
4960
|
+
live.push(e);
|
|
4961
|
+
continue;
|
|
4962
|
+
}
|
|
4963
|
+
unlinkSymlinks(e.symlinks);
|
|
4964
|
+
pruned++;
|
|
4965
|
+
}
|
|
4966
|
+
if (pruned > 0)
|
|
4967
|
+
saveManifest({ version: 1, entries: live }, path);
|
|
4968
|
+
return pruned;
|
|
4969
|
+
}
|
|
4970
|
+
|
|
4971
|
+
// dist/src/skillify/agent-roots.js
|
|
4972
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
4973
|
+
import { homedir as homedir9 } from "node:os";
|
|
4974
|
+
import { join as join19 } from "node:path";
|
|
4975
|
+
function resolveDetected(home) {
|
|
4976
|
+
const out = [];
|
|
4977
|
+
const codexInstalled = existsSync16(join19(home, ".codex"));
|
|
4978
|
+
const piInstalled = existsSync16(join19(home, ".pi", "agent"));
|
|
4979
|
+
const hermesInstalled = existsSync16(join19(home, ".hermes"));
|
|
4980
|
+
if (codexInstalled || piInstalled) {
|
|
4981
|
+
out.push(join19(home, ".agents", "skills"));
|
|
4982
|
+
}
|
|
4983
|
+
if (hermesInstalled) {
|
|
4984
|
+
out.push(join19(home, ".hermes", "skills"));
|
|
4985
|
+
}
|
|
4986
|
+
if (piInstalled) {
|
|
4987
|
+
out.push(join19(home, ".pi", "agent", "skills"));
|
|
4988
|
+
}
|
|
4989
|
+
return out;
|
|
4990
|
+
}
|
|
4991
|
+
function detectAgentSkillsRoots(canonicalRoot, home = homedir9()) {
|
|
4992
|
+
return resolveDetected(home).filter((p) => p !== canonicalRoot);
|
|
4993
|
+
}
|
|
4890
4994
|
|
|
4891
|
-
// dist/src/
|
|
4995
|
+
// dist/src/skillify/pull.js
|
|
4892
4996
|
function assertValidAuthor(author) {
|
|
4893
4997
|
if (!author)
|
|
4894
4998
|
throw new Error("author is empty");
|
|
@@ -4920,10 +5024,78 @@ function isMissingTableError(message) {
|
|
|
4920
5024
|
}
|
|
4921
5025
|
function resolvePullDestination(install, cwd) {
|
|
4922
5026
|
if (install === "global")
|
|
4923
|
-
return
|
|
5027
|
+
return join20(homedir10(), ".claude", "skills");
|
|
4924
5028
|
if (!cwd)
|
|
4925
5029
|
throw new Error("install=project requires a cwd");
|
|
4926
|
-
return
|
|
5030
|
+
return join20(cwd, ".claude", "skills");
|
|
5031
|
+
}
|
|
5032
|
+
function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
5033
|
+
const out = [];
|
|
5034
|
+
for (const root of agentRoots) {
|
|
5035
|
+
const link = join20(root, dirName);
|
|
5036
|
+
let existing;
|
|
5037
|
+
try {
|
|
5038
|
+
existing = lstatSync4(link);
|
|
5039
|
+
} catch {
|
|
5040
|
+
existing = null;
|
|
5041
|
+
}
|
|
5042
|
+
if (existing) {
|
|
5043
|
+
if (!existing.isSymbolicLink()) {
|
|
5044
|
+
continue;
|
|
5045
|
+
}
|
|
5046
|
+
let current;
|
|
5047
|
+
try {
|
|
5048
|
+
current = readlinkSync2(link);
|
|
5049
|
+
} catch {
|
|
5050
|
+
current = null;
|
|
5051
|
+
}
|
|
5052
|
+
if (current === canonicalDir) {
|
|
5053
|
+
out.push(link);
|
|
5054
|
+
continue;
|
|
5055
|
+
}
|
|
5056
|
+
try {
|
|
5057
|
+
unlinkSync8(link);
|
|
5058
|
+
} catch {
|
|
5059
|
+
continue;
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5062
|
+
try {
|
|
5063
|
+
mkdirSync7(dirname3(link), { recursive: true });
|
|
5064
|
+
symlinkSync2(canonicalDir, link, "dir");
|
|
5065
|
+
out.push(link);
|
|
5066
|
+
} catch {
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
return out;
|
|
5070
|
+
}
|
|
5071
|
+
function backfillSymlinks(installRoot) {
|
|
5072
|
+
const manifest = loadManifest();
|
|
5073
|
+
const entries = entriesForRoot(manifest, "global", installRoot);
|
|
5074
|
+
if (entries.length === 0)
|
|
5075
|
+
return;
|
|
5076
|
+
const detected = detectAgentSkillsRoots(installRoot);
|
|
5077
|
+
for (const entry of entries) {
|
|
5078
|
+
const canonical = join20(entry.installRoot, entry.dirName);
|
|
5079
|
+
if (!existsSync17(canonical))
|
|
5080
|
+
continue;
|
|
5081
|
+
const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
|
|
5082
|
+
if (sameSorted(fresh, entry.symlinks))
|
|
5083
|
+
continue;
|
|
5084
|
+
try {
|
|
5085
|
+
recordPull({ ...entry, symlinks: fresh });
|
|
5086
|
+
} catch {
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
}
|
|
5090
|
+
function sameSorted(a, b) {
|
|
5091
|
+
if (a.length !== b.length)
|
|
5092
|
+
return false;
|
|
5093
|
+
const sa = [...a].sort();
|
|
5094
|
+
const sb = [...b].sort();
|
|
5095
|
+
for (let i = 0; i < sa.length; i++)
|
|
5096
|
+
if (sa[i] !== sb[i])
|
|
5097
|
+
return false;
|
|
5098
|
+
return true;
|
|
4927
5099
|
}
|
|
4928
5100
|
function selectLatestPerName(rows) {
|
|
4929
5101
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4989,7 +5161,7 @@ function renderFrontmatter(fm) {
|
|
|
4989
5161
|
return lines.join("\n");
|
|
4990
5162
|
}
|
|
4991
5163
|
function readLocalVersion(path) {
|
|
4992
|
-
if (!
|
|
5164
|
+
if (!existsSync17(path))
|
|
4993
5165
|
return null;
|
|
4994
5166
|
try {
|
|
4995
5167
|
const text = readFileSync12(path, "utf-8");
|
|
@@ -5009,6 +5181,8 @@ function decideAction(args) {
|
|
|
5009
5181
|
return args.dryRun ? "dryrun" : "wrote";
|
|
5010
5182
|
}
|
|
5011
5183
|
async function runPull(opts) {
|
|
5184
|
+
if (!opts.dryRun)
|
|
5185
|
+
pruneOrphanedEntries();
|
|
5012
5186
|
const sql = buildPullSql({
|
|
5013
5187
|
tableName: opts.tableName,
|
|
5014
5188
|
users: opts.users,
|
|
@@ -5076,8 +5250,8 @@ async function runPull(opts) {
|
|
|
5076
5250
|
summary.skipped++;
|
|
5077
5251
|
continue;
|
|
5078
5252
|
}
|
|
5079
|
-
const skillDir =
|
|
5080
|
-
const skillFile =
|
|
5253
|
+
const skillDir = join20(root, dirName);
|
|
5254
|
+
const skillFile = join20(skillDir, "SKILL.md");
|
|
5081
5255
|
const remoteVersion = Number(row.version ?? 1);
|
|
5082
5256
|
const localVersion = readLocalVersion(skillFile);
|
|
5083
5257
|
const action = decideAction({
|
|
@@ -5089,13 +5263,14 @@ async function runPull(opts) {
|
|
|
5089
5263
|
let manifestError;
|
|
5090
5264
|
if (action === "wrote") {
|
|
5091
5265
|
mkdirSync7(skillDir, { recursive: true });
|
|
5092
|
-
if (
|
|
5266
|
+
if (existsSync17(skillFile)) {
|
|
5093
5267
|
try {
|
|
5094
|
-
|
|
5268
|
+
renameSync3(skillFile, `${skillFile}.bak`);
|
|
5095
5269
|
} catch {
|
|
5096
5270
|
}
|
|
5097
5271
|
}
|
|
5098
5272
|
writeFileSync9(skillFile, renderSkillFile(row));
|
|
5273
|
+
const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir, dirName, detectAgentSkillsRoots(root)) : [];
|
|
5099
5274
|
try {
|
|
5100
5275
|
recordPull({
|
|
5101
5276
|
dirName,
|
|
@@ -5105,7 +5280,8 @@ async function runPull(opts) {
|
|
|
5105
5280
|
remoteVersion,
|
|
5106
5281
|
install: opts.install,
|
|
5107
5282
|
installRoot: root,
|
|
5108
|
-
pulledAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5283
|
+
pulledAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5284
|
+
symlinks
|
|
5109
5285
|
});
|
|
5110
5286
|
} catch (e) {
|
|
5111
5287
|
manifestError = e?.message ?? String(e);
|
|
@@ -5128,19 +5304,22 @@ async function runPull(opts) {
|
|
|
5128
5304
|
else
|
|
5129
5305
|
summary.skipped++;
|
|
5130
5306
|
}
|
|
5307
|
+
if (!opts.dryRun && opts.install === "global") {
|
|
5308
|
+
backfillSymlinks(root);
|
|
5309
|
+
}
|
|
5131
5310
|
return summary;
|
|
5132
5311
|
}
|
|
5133
5312
|
|
|
5134
|
-
// dist/src/
|
|
5135
|
-
import { existsSync as
|
|
5136
|
-
import { homedir as
|
|
5137
|
-
import { join as
|
|
5313
|
+
// dist/src/skillify/unpull.js
|
|
5314
|
+
import { existsSync as existsSync18, readdirSync as readdirSync3, rmSync as rmSync5, statSync as statSync3 } from "node:fs";
|
|
5315
|
+
import { homedir as homedir11 } from "node:os";
|
|
5316
|
+
import { join as join21 } from "node:path";
|
|
5138
5317
|
function resolveUnpullRoot(install, cwd) {
|
|
5139
5318
|
if (install === "global")
|
|
5140
|
-
return
|
|
5319
|
+
return join21(homedir11(), ".claude", "skills");
|
|
5141
5320
|
if (!cwd)
|
|
5142
5321
|
throw new Error("cwd required when install === 'project'");
|
|
5143
|
-
return
|
|
5322
|
+
return join21(cwd, ".claude", "skills");
|
|
5144
5323
|
}
|
|
5145
5324
|
function runUnpull(opts) {
|
|
5146
5325
|
const root = resolveUnpullRoot(opts.install, opts.cwd);
|
|
@@ -5163,10 +5342,12 @@ function runUnpull(opts) {
|
|
|
5163
5342
|
const entries = entriesForRoot(manifest, opts.install, root);
|
|
5164
5343
|
for (const entry of entries) {
|
|
5165
5344
|
summary.scanned++;
|
|
5166
|
-
const path =
|
|
5167
|
-
if (!
|
|
5168
|
-
if (!opts.dryRun)
|
|
5345
|
+
const path = join21(root, entry.dirName);
|
|
5346
|
+
if (!existsSync18(path)) {
|
|
5347
|
+
if (!opts.dryRun) {
|
|
5348
|
+
unlinkSymlinks(entry.symlinks);
|
|
5169
5349
|
removePullEntry(opts.install, entry.installRoot, entry.dirName);
|
|
5350
|
+
}
|
|
5170
5351
|
summary.entries.push({
|
|
5171
5352
|
dirName: entry.dirName,
|
|
5172
5353
|
kind: "manifest-orphan",
|
|
@@ -5203,6 +5384,7 @@ function runUnpull(opts) {
|
|
|
5203
5384
|
} else {
|
|
5204
5385
|
try {
|
|
5205
5386
|
rmSync5(path, { recursive: true, force: true });
|
|
5387
|
+
unlinkSymlinks(entry.symlinks);
|
|
5206
5388
|
removePullEntry(opts.install, entry.installRoot, entry.dirName);
|
|
5207
5389
|
result.action = "removed";
|
|
5208
5390
|
summary.removed++;
|
|
@@ -5214,12 +5396,12 @@ function runUnpull(opts) {
|
|
|
5214
5396
|
}
|
|
5215
5397
|
summary.entries.push(result);
|
|
5216
5398
|
}
|
|
5217
|
-
if (
|
|
5399
|
+
if (existsSync18(root) && (opts.all || opts.legacyCleanup)) {
|
|
5218
5400
|
const manifestDirNames = new Set(entries.map((e) => e.dirName));
|
|
5219
5401
|
for (const dirName of readdirSync3(root)) {
|
|
5220
5402
|
if (manifestDirNames.has(dirName))
|
|
5221
5403
|
continue;
|
|
5222
|
-
const path =
|
|
5404
|
+
const path = join21(root, dirName);
|
|
5223
5405
|
let st;
|
|
5224
5406
|
try {
|
|
5225
5407
|
st = statSync3(path);
|
|
@@ -5296,9 +5478,9 @@ function decideTargetForManifestEntry(entry, opts, userFilter, haveUserFilter) {
|
|
|
5296
5478
|
return { shouldRemove: true };
|
|
5297
5479
|
}
|
|
5298
5480
|
|
|
5299
|
-
// dist/src/commands/
|
|
5481
|
+
// dist/src/commands/skillify.js
|
|
5300
5482
|
function stateDir() {
|
|
5301
|
-
return
|
|
5483
|
+
return join22(homedir12(), ".deeplake", "state", "skillify");
|
|
5302
5484
|
}
|
|
5303
5485
|
function showStatus() {
|
|
5304
5486
|
const cfg = loadScopeConfig();
|
|
@@ -5306,11 +5488,11 @@ function showStatus() {
|
|
|
5306
5488
|
console.log(`team: ${cfg.team.length === 0 ? "(empty)" : cfg.team.join(", ")}`);
|
|
5307
5489
|
console.log(`install: ${cfg.install} (${cfg.install === "global" ? "~/.claude/skills/" : "<project>/.claude/skills/"})`);
|
|
5308
5490
|
const dir = stateDir();
|
|
5309
|
-
if (!
|
|
5491
|
+
if (!existsSync19(dir)) {
|
|
5310
5492
|
console.log(`state: (no projects tracked yet)`);
|
|
5311
5493
|
return;
|
|
5312
5494
|
}
|
|
5313
|
-
const files = readdirSync4(dir).filter((f) => f.endsWith(".json") && f !== "config.json" && f !== "pulled.json");
|
|
5495
|
+
const files = readdirSync4(dir).filter((f) => f.endsWith(".json") && f !== "config.json" && f !== "pulled.json" && f !== "autopull-last-run.json");
|
|
5314
5496
|
if (files.length === 0) {
|
|
5315
5497
|
console.log(`state: (no projects tracked yet)`);
|
|
5316
5498
|
return;
|
|
@@ -5318,9 +5500,10 @@ function showStatus() {
|
|
|
5318
5500
|
console.log(`state: ${files.length} project(s) tracked`);
|
|
5319
5501
|
for (const f of files) {
|
|
5320
5502
|
try {
|
|
5321
|
-
const s = JSON.parse(readFileSync13(
|
|
5322
|
-
const
|
|
5323
|
-
|
|
5503
|
+
const s = JSON.parse(readFileSync13(join22(dir, f), "utf-8"));
|
|
5504
|
+
const last = typeof s.updatedAt === "number" ? new Date(s.updatedAt).toISOString() : s.lastDate ?? "never";
|
|
5505
|
+
const skills = Array.isArray(s.skillsGenerated) && s.skillsGenerated.length > 0 ? s.skillsGenerated.join(", ") : "none";
|
|
5506
|
+
console.log(` - ${s.project} (counter=${s.counter}, last=${last}, skills=${skills})`);
|
|
5324
5507
|
} catch {
|
|
5325
5508
|
}
|
|
5326
5509
|
}
|
|
@@ -5334,7 +5517,7 @@ function setScope(scope) {
|
|
|
5334
5517
|
saveScopeConfig({ ...cfg, scope });
|
|
5335
5518
|
console.log(`Scope set to '${scope}'.`);
|
|
5336
5519
|
if (scope === "team" && cfg.team.length === 0) {
|
|
5337
|
-
console.log(`Note: team list is empty. Use 'hivemind
|
|
5520
|
+
console.log(`Note: team list is empty. Use 'hivemind skillify team add <username>' to populate it.`);
|
|
5338
5521
|
}
|
|
5339
5522
|
}
|
|
5340
5523
|
function setInstall(loc) {
|
|
@@ -5344,31 +5527,31 @@ function setInstall(loc) {
|
|
|
5344
5527
|
}
|
|
5345
5528
|
const cfg = loadScopeConfig();
|
|
5346
5529
|
saveScopeConfig({ ...cfg, install: loc });
|
|
5347
|
-
const path = loc === "global" ?
|
|
5530
|
+
const path = loc === "global" ? join22(homedir12(), ".claude", "skills") : "<cwd>/.claude/skills";
|
|
5348
5531
|
console.log(`Install location set to '${loc}'. New skills will be written to ${path}/<name>/SKILL.md.`);
|
|
5349
5532
|
}
|
|
5350
5533
|
function promoteSkill(name, cwd) {
|
|
5351
5534
|
if (!name) {
|
|
5352
|
-
console.error("Usage: hivemind
|
|
5535
|
+
console.error("Usage: hivemind skillify promote <skill-name>");
|
|
5353
5536
|
process.exit(1);
|
|
5354
5537
|
}
|
|
5355
|
-
const projectPath =
|
|
5356
|
-
const globalPath =
|
|
5357
|
-
if (!
|
|
5538
|
+
const projectPath = join22(cwd, ".claude", "skills", name);
|
|
5539
|
+
const globalPath = join22(homedir12(), ".claude", "skills", name);
|
|
5540
|
+
if (!existsSync19(join22(projectPath, "SKILL.md"))) {
|
|
5358
5541
|
console.error(`Skill '${name}' not found at ${projectPath}/SKILL.md`);
|
|
5359
5542
|
process.exit(1);
|
|
5360
5543
|
}
|
|
5361
|
-
if (
|
|
5544
|
+
if (existsSync19(join22(globalPath, "SKILL.md"))) {
|
|
5362
5545
|
console.error(`Skill '${name}' already exists at ${globalPath}/SKILL.md \u2014 refusing to overwrite. Remove it first or rename the project skill.`);
|
|
5363
5546
|
process.exit(1);
|
|
5364
5547
|
}
|
|
5365
|
-
mkdirSync8(
|
|
5366
|
-
|
|
5548
|
+
mkdirSync8(dirname4(globalPath), { recursive: true });
|
|
5549
|
+
renameSync4(projectPath, globalPath);
|
|
5367
5550
|
console.log(`Promoted '${name}' from ${projectPath} \u2192 ${globalPath}.`);
|
|
5368
5551
|
}
|
|
5369
5552
|
function teamAdd(name) {
|
|
5370
5553
|
if (!name) {
|
|
5371
|
-
console.error("Usage: hivemind
|
|
5554
|
+
console.error("Usage: hivemind skillify team add <username>");
|
|
5372
5555
|
process.exit(1);
|
|
5373
5556
|
}
|
|
5374
5557
|
const cfg = loadScopeConfig();
|
|
@@ -5382,7 +5565,7 @@ function teamAdd(name) {
|
|
|
5382
5565
|
}
|
|
5383
5566
|
function teamRemove(name) {
|
|
5384
5567
|
if (!name) {
|
|
5385
|
-
console.error("Usage: hivemind
|
|
5568
|
+
console.error("Usage: hivemind skillify team remove <username>");
|
|
5386
5569
|
process.exit(1);
|
|
5387
5570
|
}
|
|
5388
5571
|
const cfg = loadScopeConfig();
|
|
@@ -5405,14 +5588,14 @@ function teamList() {
|
|
|
5405
5588
|
}
|
|
5406
5589
|
function usage() {
|
|
5407
5590
|
console.log("Usage:");
|
|
5408
|
-
console.log(" hivemind
|
|
5409
|
-
console.log(" hivemind
|
|
5410
|
-
console.log(" hivemind
|
|
5411
|
-
console.log(" hivemind
|
|
5412
|
-
console.log(" hivemind
|
|
5413
|
-
console.log(" hivemind
|
|
5414
|
-
console.log(" hivemind
|
|
5415
|
-
console.log(" hivemind
|
|
5591
|
+
console.log(" hivemind skillify show current scope, team, install, and per-project state");
|
|
5592
|
+
console.log(" hivemind skillify scope <me|team|org> set the mining scope");
|
|
5593
|
+
console.log(" hivemind skillify install <project|global> set where new skills are written");
|
|
5594
|
+
console.log(" hivemind skillify promote <skill-name> move a project skill to the global location");
|
|
5595
|
+
console.log(" hivemind skillify team add <username> add a username to the team list");
|
|
5596
|
+
console.log(" hivemind skillify team remove <username> remove a username from the team list");
|
|
5597
|
+
console.log(" hivemind skillify team list list current team members");
|
|
5598
|
+
console.log(" hivemind skillify pull [skill-name] [opts] fetch skills from Deeplake to local FS");
|
|
5416
5599
|
console.log(" Options for pull:");
|
|
5417
5600
|
console.log(" --to <project|global> destination (default: global)");
|
|
5418
5601
|
console.log(" --user <name> only skills authored by this user");
|
|
@@ -5420,7 +5603,7 @@ function usage() {
|
|
|
5420
5603
|
console.log(" --all-users all authors (default \u2014 equivalent to no filter)");
|
|
5421
5604
|
console.log(" --dry-run show what would be written, don't touch disk");
|
|
5422
5605
|
console.log(" --force overwrite even when local version >= remote");
|
|
5423
|
-
console.log(" hivemind
|
|
5606
|
+
console.log(" hivemind skillify unpull [opts] remove skills previously installed by pull");
|
|
5424
5607
|
console.log(" Options for unpull:");
|
|
5425
5608
|
console.log(" --to <project|global> where to scan (default: global)");
|
|
5426
5609
|
console.log(" --user <name> only entries authored by this user");
|
|
@@ -5429,7 +5612,7 @@ function usage() {
|
|
|
5429
5612
|
console.log(" --dry-run show what would be removed");
|
|
5430
5613
|
console.log(" --all also remove flat-layout (locally-mined) entries");
|
|
5431
5614
|
console.log(" --legacy-cleanup also remove pre-`--author`-layout legacy `<projectKey>/` dirs");
|
|
5432
|
-
console.log(" hivemind
|
|
5615
|
+
console.log(" hivemind skillify status show per-project state");
|
|
5433
5616
|
}
|
|
5434
5617
|
function takeFlagValue(args, flag) {
|
|
5435
5618
|
const idx = args.indexOf(flag);
|
|
@@ -5493,7 +5676,7 @@ async function pullSkills(args) {
|
|
|
5493
5676
|
console.error(`pull failed: ${e?.message ?? e}`);
|
|
5494
5677
|
process.exit(1);
|
|
5495
5678
|
}
|
|
5496
|
-
const dest = toRaw === "global" ?
|
|
5679
|
+
const dest = toRaw === "global" ? join22(homedir12(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
|
|
5497
5680
|
const filterDesc = users.length === 0 ? "all users" : users.join(", ");
|
|
5498
5681
|
console.log(`Destination: ${dest}`);
|
|
5499
5682
|
console.log(`Filter: ${filterDesc}${skillName ? ` \xB7 skill='${skillName}'` : ""}${dryRun ? " \xB7 dry-run" : ""}${force ? " \xB7 force" : ""}`);
|
|
@@ -5543,7 +5726,7 @@ async function unpullSkills(args) {
|
|
|
5543
5726
|
all,
|
|
5544
5727
|
legacyCleanup
|
|
5545
5728
|
});
|
|
5546
|
-
const dest = toRaw === "global" ?
|
|
5729
|
+
const dest = toRaw === "global" ? join22(homedir12(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
|
|
5547
5730
|
const filterParts = [];
|
|
5548
5731
|
if (users.length > 0)
|
|
5549
5732
|
filterParts.push(`users=${users.join(",")}`);
|
|
@@ -5568,7 +5751,7 @@ async function unpullSkills(args) {
|
|
|
5568
5751
|
const prunedNote = summary.manifestPruned > 0 ? `, ${summary.manifestPruned} manifest-pruned` : "";
|
|
5569
5752
|
console.log(`Result: ${summary.removed} removed, ${summary.wouldRemove} dry-run, ${summary.kept} kept${prunedNote}.`);
|
|
5570
5753
|
}
|
|
5571
|
-
function
|
|
5754
|
+
function runSkillifyCommand(args) {
|
|
5572
5755
|
const sub = args[0];
|
|
5573
5756
|
if (!sub || sub === "status") {
|
|
5574
5757
|
showStatus();
|
|
@@ -5615,30 +5798,30 @@ function runSkilifyCommand(args) {
|
|
|
5615
5798
|
teamList();
|
|
5616
5799
|
return;
|
|
5617
5800
|
}
|
|
5618
|
-
console.error("Usage: hivemind
|
|
5801
|
+
console.error("Usage: hivemind skillify team <add|remove|list> [name]");
|
|
5619
5802
|
process.exit(1);
|
|
5620
5803
|
}
|
|
5621
5804
|
if (sub === "--help" || sub === "-h" || sub === "help") {
|
|
5622
5805
|
usage();
|
|
5623
5806
|
return;
|
|
5624
5807
|
}
|
|
5625
|
-
console.error(`Unknown
|
|
5808
|
+
console.error(`Unknown skillify subcommand: ${sub}`);
|
|
5626
5809
|
usage();
|
|
5627
5810
|
process.exit(1);
|
|
5628
5811
|
}
|
|
5629
|
-
if (process.argv[1] && process.argv[1].endsWith("
|
|
5630
|
-
|
|
5812
|
+
if (process.argv[1] && process.argv[1].endsWith("skillify.js")) {
|
|
5813
|
+
runSkillifyCommand(process.argv.slice(2));
|
|
5631
5814
|
}
|
|
5632
5815
|
|
|
5633
5816
|
// dist/src/cli/update.js
|
|
5634
5817
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
5635
|
-
import { existsSync as
|
|
5636
|
-
import { dirname as
|
|
5818
|
+
import { existsSync as existsSync20, readFileSync as readFileSync15, realpathSync } from "node:fs";
|
|
5819
|
+
import { dirname as dirname6, sep } from "node:path";
|
|
5637
5820
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
5638
5821
|
|
|
5639
5822
|
// dist/src/utils/version-check.js
|
|
5640
5823
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
5641
|
-
import { dirname as
|
|
5824
|
+
import { dirname as dirname5, join as join23 } from "node:path";
|
|
5642
5825
|
function isNewer(latest, current) {
|
|
5643
5826
|
const parse = (v) => v.split(".").map(Number);
|
|
5644
5827
|
const [la, lb, lc] = parse(latest);
|
|
@@ -5657,7 +5840,7 @@ function detectInstallKind(argv1) {
|
|
|
5657
5840
|
return argv1 ?? process.argv[1] ?? fileURLToPath2(import.meta.url);
|
|
5658
5841
|
}
|
|
5659
5842
|
})();
|
|
5660
|
-
let dir =
|
|
5843
|
+
let dir = dirname6(realArgv1);
|
|
5661
5844
|
let installDir = null;
|
|
5662
5845
|
for (let i = 0; i < 10; i++) {
|
|
5663
5846
|
const pkgPath = `${dir}${sep}package.json`;
|
|
@@ -5669,12 +5852,12 @@ function detectInstallKind(argv1) {
|
|
|
5669
5852
|
}
|
|
5670
5853
|
} catch {
|
|
5671
5854
|
}
|
|
5672
|
-
const parent =
|
|
5855
|
+
const parent = dirname6(dir);
|
|
5673
5856
|
if (parent === dir)
|
|
5674
5857
|
break;
|
|
5675
5858
|
dir = parent;
|
|
5676
5859
|
}
|
|
5677
|
-
installDir ??=
|
|
5860
|
+
installDir ??= dirname6(realArgv1);
|
|
5678
5861
|
if (realArgv1.includes(`${sep}_npx${sep}`) || realArgv1.includes(`${sep}.npx${sep}`)) {
|
|
5679
5862
|
return { kind: "npx", installDir };
|
|
5680
5863
|
}
|
|
@@ -5683,10 +5866,10 @@ function detectInstallKind(argv1) {
|
|
|
5683
5866
|
}
|
|
5684
5867
|
let gitDir = installDir;
|
|
5685
5868
|
for (let i = 0; i < 6; i++) {
|
|
5686
|
-
if (
|
|
5869
|
+
if (existsSync20(`${gitDir}${sep}.git`)) {
|
|
5687
5870
|
return { kind: "local-dev", installDir };
|
|
5688
5871
|
}
|
|
5689
|
-
const parent =
|
|
5872
|
+
const parent = dirname6(gitDir);
|
|
5690
5873
|
if (parent === gitDir)
|
|
5691
5874
|
break;
|
|
5692
5875
|
gitDir = parent;
|
|
@@ -5840,22 +6023,28 @@ Semantic search (embeddings):
|
|
|
5840
6023
|
to run "embeddings install" automatically after installing the agent(s).
|
|
5841
6024
|
|
|
5842
6025
|
Skill management (mine + share reusable Claude skills across the org):
|
|
5843
|
-
hivemind
|
|
5844
|
-
hivemind
|
|
6026
|
+
hivemind skillify Show scope, team, install, and per-project state.
|
|
6027
|
+
hivemind skillify pull [skill-name] Sync skills from the org table to local FS.
|
|
5845
6028
|
Options: --user <email>, --users a,b,c,
|
|
5846
6029
|
--all-users, --to <project|global>,
|
|
5847
6030
|
--dry-run, --force.
|
|
5848
|
-
|
|
6031
|
+
Note: every agent's SessionStart hook
|
|
6032
|
+
auto-runs 'pull --all-users --to global'
|
|
6033
|
+
on every session. File writes are
|
|
6034
|
+
idempotent (skipped when local is
|
|
6035
|
+
at-or-newer than remote). Disable via
|
|
6036
|
+
HIVEMIND_AUTOPULL_DISABLED=1.
|
|
6037
|
+
hivemind skillify unpull Remove skills previously installed by pull.
|
|
5849
6038
|
Options: --user, --users, --not-mine,
|
|
5850
6039
|
--to <project|global>, --dry-run,
|
|
5851
6040
|
--all (also locally-mined),
|
|
5852
6041
|
--legacy-cleanup (pre-suffix-author dirs).
|
|
5853
|
-
hivemind
|
|
5854
|
-
hivemind
|
|
5855
|
-
hivemind
|
|
5856
|
-
hivemind
|
|
5857
|
-
hivemind
|
|
5858
|
-
hivemind
|
|
6042
|
+
hivemind skillify scope <me|team|org> Set the sharing scope for newly mined skills.
|
|
6043
|
+
hivemind skillify install <project|global> Set where new skills are written.
|
|
6044
|
+
hivemind skillify promote <name> Move a project skill to the global location.
|
|
6045
|
+
hivemind skillify team add <username> Add a username to the team list.
|
|
6046
|
+
hivemind skillify team remove <username> Remove a username from the team list.
|
|
6047
|
+
hivemind skillify team list List current team members.
|
|
5859
6048
|
|
|
5860
6049
|
Account / org / workspace:
|
|
5861
6050
|
hivemind whoami Show current user, org, workspace.
|
|
@@ -6006,8 +6195,8 @@ async function main() {
|
|
|
6006
6195
|
const code = await runUpdate({ dryRun: hasFlag(args.slice(1), "--dry-run") });
|
|
6007
6196
|
process.exit(code);
|
|
6008
6197
|
}
|
|
6009
|
-
if (cmd === "
|
|
6010
|
-
|
|
6198
|
+
if (cmd === "skillify") {
|
|
6199
|
+
runSkillifyCommand(args.slice(1));
|
|
6011
6200
|
return;
|
|
6012
6201
|
}
|
|
6013
6202
|
if (cmd === "embeddings") {
|