@deeplake/hivemind 0.7.16 → 0.7.17
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 +196 -44
- package/codex/bundle/session-start.js +1103 -8
- package/cursor/bundle/session-start.js +582 -8
- package/hermes/bundle/session-start.js +580 -6
- package/openclaw/dist/index.js +1 -1
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +1 -1
- package/pi/extension-source/hivemind.ts +52 -3
|
@@ -53,7 +53,7 @@ var init_index_marker_store = __esm({
|
|
|
53
53
|
|
|
54
54
|
// dist/src/hooks/hermes/session-start.js
|
|
55
55
|
import { fileURLToPath } from "node:url";
|
|
56
|
-
import { dirname as
|
|
56
|
+
import { dirname as dirname4 } from "node:path";
|
|
57
57
|
|
|
58
58
|
// dist/src/commands/auth.js
|
|
59
59
|
import { execSync } from "node:child_process";
|
|
@@ -670,9 +670,581 @@ async function autoUpdate(creds, opts) {
|
|
|
670
670
|
log3(`agent=${opts.agent} dispatched (pid=${pid ?? "?"}) (${Date.now() - t0}ms total)`);
|
|
671
671
|
}
|
|
672
672
|
|
|
673
|
+
// dist/src/skilify/pull.js
|
|
674
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, renameSync as renameSync2, lstatSync as lstatSync2, readlinkSync, symlinkSync, unlinkSync as unlinkSync3 } from "node:fs";
|
|
675
|
+
import { homedir as homedir7 } from "node:os";
|
|
676
|
+
import { dirname as dirname3, join as join10 } from "node:path";
|
|
677
|
+
|
|
678
|
+
// dist/src/skilify/skill-writer.js
|
|
679
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync5, readdirSync, statSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
680
|
+
import { homedir as homedir4 } from "node:os";
|
|
681
|
+
import { join as join7 } from "node:path";
|
|
682
|
+
function assertValidSkillName(name) {
|
|
683
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
684
|
+
throw new Error(`invalid skill name: empty or non-string`);
|
|
685
|
+
}
|
|
686
|
+
if (name.length > 100) {
|
|
687
|
+
throw new Error(`invalid skill name: too long (${name.length} chars)`);
|
|
688
|
+
}
|
|
689
|
+
if (name.includes("/") || name.includes("\\") || name.includes("..")) {
|
|
690
|
+
throw new Error(`invalid skill name: contains path separator or '..': ${name}`);
|
|
691
|
+
}
|
|
692
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) {
|
|
693
|
+
throw new Error(`invalid skill name: must be kebab-case (lowercase a-z, 0-9, hyphen): ${name}`);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
function parseFrontmatter(text) {
|
|
697
|
+
if (!text.startsWith("---\n") && !text.startsWith("---\r\n"))
|
|
698
|
+
return null;
|
|
699
|
+
const end = text.indexOf("\n---", 4);
|
|
700
|
+
if (end < 0)
|
|
701
|
+
return null;
|
|
702
|
+
const head = text.slice(4, end).trim();
|
|
703
|
+
const body = text.slice(end + 4).replace(/^\r?\n/, "");
|
|
704
|
+
const fm = { source_sessions: [] };
|
|
705
|
+
let mode = "kv";
|
|
706
|
+
for (const raw of head.split(/\r?\n/)) {
|
|
707
|
+
if (mode === "sources") {
|
|
708
|
+
const m2 = raw.match(/^\s+-\s+(.+)$/);
|
|
709
|
+
if (m2) {
|
|
710
|
+
fm.source_sessions.push(m2[1].trim());
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
mode = "kv";
|
|
714
|
+
}
|
|
715
|
+
if (raw.startsWith("source_sessions:")) {
|
|
716
|
+
mode = "sources";
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
const m = raw.match(/^([a-zA-Z_]+):\s*(.*)$/);
|
|
720
|
+
if (!m)
|
|
721
|
+
continue;
|
|
722
|
+
const [, k, v] = m;
|
|
723
|
+
let val = v;
|
|
724
|
+
if (v.startsWith('"') && v.endsWith('"')) {
|
|
725
|
+
try {
|
|
726
|
+
val = JSON.parse(v);
|
|
727
|
+
} catch {
|
|
728
|
+
}
|
|
729
|
+
} else if (k === "version") {
|
|
730
|
+
const n = parseInt(v, 10);
|
|
731
|
+
if (Number.isFinite(n))
|
|
732
|
+
val = n;
|
|
733
|
+
}
|
|
734
|
+
fm[k] = val;
|
|
735
|
+
}
|
|
736
|
+
return { fm, body };
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// dist/src/skilify/manifest.js
|
|
740
|
+
import { existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
741
|
+
import { homedir as homedir5 } from "node:os";
|
|
742
|
+
import { dirname as dirname2, join as join8 } from "node:path";
|
|
743
|
+
function emptyManifest() {
|
|
744
|
+
return { version: 1, entries: [] };
|
|
745
|
+
}
|
|
746
|
+
function manifestPath() {
|
|
747
|
+
return join8(homedir5(), ".deeplake", "state", "skilify", "pulled.json");
|
|
748
|
+
}
|
|
749
|
+
function loadManifest(path = manifestPath()) {
|
|
750
|
+
if (!existsSync5(path))
|
|
751
|
+
return emptyManifest();
|
|
752
|
+
let raw;
|
|
753
|
+
try {
|
|
754
|
+
raw = readFileSync6(path, "utf-8");
|
|
755
|
+
} catch {
|
|
756
|
+
return emptyManifest();
|
|
757
|
+
}
|
|
758
|
+
try {
|
|
759
|
+
const parsed = JSON.parse(raw);
|
|
760
|
+
if (!parsed || typeof parsed !== "object")
|
|
761
|
+
return emptyManifest();
|
|
762
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.entries))
|
|
763
|
+
return emptyManifest();
|
|
764
|
+
const entries = [];
|
|
765
|
+
for (const e of parsed.entries) {
|
|
766
|
+
if (!e || typeof e !== "object")
|
|
767
|
+
continue;
|
|
768
|
+
if (typeof e.dirName !== "string" || !e.dirName)
|
|
769
|
+
continue;
|
|
770
|
+
if (e.dirName.includes("/") || e.dirName.includes("\\") || e.dirName.includes(".."))
|
|
771
|
+
continue;
|
|
772
|
+
if (typeof e.name !== "string" || !e.name)
|
|
773
|
+
continue;
|
|
774
|
+
if (typeof e.author !== "string")
|
|
775
|
+
continue;
|
|
776
|
+
if (typeof e.installRoot !== "string" || !e.installRoot)
|
|
777
|
+
continue;
|
|
778
|
+
if (e.install !== "global" && e.install !== "project")
|
|
779
|
+
continue;
|
|
780
|
+
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)
|
|
781
|
+
!p.includes("..")) : [];
|
|
782
|
+
entries.push({
|
|
783
|
+
dirName: e.dirName,
|
|
784
|
+
name: e.name,
|
|
785
|
+
author: e.author,
|
|
786
|
+
projectKey: typeof e.projectKey === "string" ? e.projectKey : "",
|
|
787
|
+
remoteVersion: typeof e.remoteVersion === "number" ? e.remoteVersion : 1,
|
|
788
|
+
install: e.install,
|
|
789
|
+
installRoot: e.installRoot,
|
|
790
|
+
pulledAt: typeof e.pulledAt === "string" ? e.pulledAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
791
|
+
symlinks
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
return { version: 1, entries };
|
|
795
|
+
} catch {
|
|
796
|
+
return emptyManifest();
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
function saveManifest(m, path = manifestPath()) {
|
|
800
|
+
mkdirSync4(dirname2(path), { recursive: true });
|
|
801
|
+
const tmp = `${path}.tmp`;
|
|
802
|
+
writeFileSync4(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
|
|
803
|
+
renameSync(tmp, path);
|
|
804
|
+
}
|
|
805
|
+
function recordPull(entry, path = manifestPath()) {
|
|
806
|
+
const m = loadManifest(path);
|
|
807
|
+
const idx = m.entries.findIndex((e) => e.install === entry.install && e.installRoot === entry.installRoot && e.dirName === entry.dirName);
|
|
808
|
+
if (idx >= 0)
|
|
809
|
+
m.entries[idx] = entry;
|
|
810
|
+
else
|
|
811
|
+
m.entries.push(entry);
|
|
812
|
+
saveManifest(m, path);
|
|
813
|
+
}
|
|
814
|
+
function entriesForRoot(m, install, installRoot) {
|
|
815
|
+
return m.entries.filter((e) => e.install === install && e.installRoot === installRoot);
|
|
816
|
+
}
|
|
817
|
+
function unlinkSymlinks(paths) {
|
|
818
|
+
for (const path of paths) {
|
|
819
|
+
let st;
|
|
820
|
+
try {
|
|
821
|
+
st = lstatSync(path);
|
|
822
|
+
} catch {
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
if (!st.isSymbolicLink())
|
|
826
|
+
continue;
|
|
827
|
+
try {
|
|
828
|
+
unlinkSync2(path);
|
|
829
|
+
} catch {
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
function pruneOrphanedEntries(path = manifestPath()) {
|
|
834
|
+
const m = loadManifest(path);
|
|
835
|
+
const live = [];
|
|
836
|
+
let pruned = 0;
|
|
837
|
+
for (const e of m.entries) {
|
|
838
|
+
if (existsSync5(join8(e.installRoot, e.dirName))) {
|
|
839
|
+
live.push(e);
|
|
840
|
+
continue;
|
|
841
|
+
}
|
|
842
|
+
unlinkSymlinks(e.symlinks);
|
|
843
|
+
pruned++;
|
|
844
|
+
}
|
|
845
|
+
if (pruned > 0)
|
|
846
|
+
saveManifest({ version: 1, entries: live }, path);
|
|
847
|
+
return pruned;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// dist/src/skilify/agent-roots.js
|
|
851
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
852
|
+
import { homedir as homedir6 } from "node:os";
|
|
853
|
+
import { join as join9 } from "node:path";
|
|
854
|
+
function resolveDetected(home) {
|
|
855
|
+
const out = [];
|
|
856
|
+
const codexInstalled = existsSync6(join9(home, ".codex"));
|
|
857
|
+
const piInstalled = existsSync6(join9(home, ".pi", "agent"));
|
|
858
|
+
const hermesInstalled = existsSync6(join9(home, ".hermes"));
|
|
859
|
+
if (codexInstalled || piInstalled) {
|
|
860
|
+
out.push(join9(home, ".agents", "skills"));
|
|
861
|
+
}
|
|
862
|
+
if (hermesInstalled) {
|
|
863
|
+
out.push(join9(home, ".hermes", "skills"));
|
|
864
|
+
}
|
|
865
|
+
if (piInstalled) {
|
|
866
|
+
out.push(join9(home, ".pi", "agent", "skills"));
|
|
867
|
+
}
|
|
868
|
+
return out;
|
|
869
|
+
}
|
|
870
|
+
function detectAgentSkillsRoots(canonicalRoot, home = homedir6()) {
|
|
871
|
+
return resolveDetected(home).filter((p) => p !== canonicalRoot);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// dist/src/skilify/pull.js
|
|
875
|
+
function assertValidAuthor(author) {
|
|
876
|
+
if (!author)
|
|
877
|
+
throw new Error("author is empty");
|
|
878
|
+
if (author.length > 64)
|
|
879
|
+
throw new Error(`author too long (${author.length}): ${author.slice(0, 32)}\u2026`);
|
|
880
|
+
if (!/^[A-Za-z0-9_.\-@]+$/.test(author)) {
|
|
881
|
+
throw new Error(`author contains invalid characters: ${author}`);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
function esc(s) {
|
|
885
|
+
return s.replace(/\\/g, "\\\\").replace(/'/g, "''").replace(/[\x01-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
886
|
+
}
|
|
887
|
+
function buildPullSql(args) {
|
|
888
|
+
const where = [];
|
|
889
|
+
if (args.users.length > 0) {
|
|
890
|
+
const list = args.users.map((u) => `'${esc(u)}'`).join(", ");
|
|
891
|
+
where.push(`author IN (${list})`);
|
|
892
|
+
}
|
|
893
|
+
if (args.skillName) {
|
|
894
|
+
where.push(`name = '${esc(args.skillName)}'`);
|
|
895
|
+
}
|
|
896
|
+
const whereClause = where.length > 0 ? ` WHERE ${where.join(" AND ")}` : "";
|
|
897
|
+
return `SELECT name, project, project_key, body, version, source_agent, scope, author, description, trigger_text, source_sessions, install, created_at, updated_at FROM "${args.tableName}"${whereClause} ORDER BY project_key ASC, name ASC, version DESC`;
|
|
898
|
+
}
|
|
899
|
+
function isMissingTableError(message) {
|
|
900
|
+
if (!message)
|
|
901
|
+
return false;
|
|
902
|
+
return /Table does not exist|relation .* does not exist|no such table/i.test(message);
|
|
903
|
+
}
|
|
904
|
+
function resolvePullDestination(install, cwd) {
|
|
905
|
+
if (install === "global")
|
|
906
|
+
return join10(homedir7(), ".claude", "skills");
|
|
907
|
+
if (!cwd)
|
|
908
|
+
throw new Error("install=project requires a cwd");
|
|
909
|
+
return join10(cwd, ".claude", "skills");
|
|
910
|
+
}
|
|
911
|
+
function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
912
|
+
const out = [];
|
|
913
|
+
for (const root of agentRoots) {
|
|
914
|
+
const link = join10(root, dirName);
|
|
915
|
+
let existing;
|
|
916
|
+
try {
|
|
917
|
+
existing = lstatSync2(link);
|
|
918
|
+
} catch {
|
|
919
|
+
existing = null;
|
|
920
|
+
}
|
|
921
|
+
if (existing) {
|
|
922
|
+
if (!existing.isSymbolicLink()) {
|
|
923
|
+
continue;
|
|
924
|
+
}
|
|
925
|
+
let current;
|
|
926
|
+
try {
|
|
927
|
+
current = readlinkSync(link);
|
|
928
|
+
} catch {
|
|
929
|
+
current = null;
|
|
930
|
+
}
|
|
931
|
+
if (current === canonicalDir) {
|
|
932
|
+
out.push(link);
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
try {
|
|
936
|
+
unlinkSync3(link);
|
|
937
|
+
} catch {
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
try {
|
|
942
|
+
mkdirSync5(dirname3(link), { recursive: true });
|
|
943
|
+
symlinkSync(canonicalDir, link, "dir");
|
|
944
|
+
out.push(link);
|
|
945
|
+
} catch {
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
return out;
|
|
949
|
+
}
|
|
950
|
+
function backfillSymlinks(installRoot) {
|
|
951
|
+
const manifest = loadManifest();
|
|
952
|
+
const entries = entriesForRoot(manifest, "global", installRoot);
|
|
953
|
+
if (entries.length === 0)
|
|
954
|
+
return;
|
|
955
|
+
const detected = detectAgentSkillsRoots(installRoot);
|
|
956
|
+
for (const entry of entries) {
|
|
957
|
+
const canonical = join10(entry.installRoot, entry.dirName);
|
|
958
|
+
if (!existsSync7(canonical))
|
|
959
|
+
continue;
|
|
960
|
+
const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
|
|
961
|
+
if (sameSorted(fresh, entry.symlinks))
|
|
962
|
+
continue;
|
|
963
|
+
try {
|
|
964
|
+
recordPull({ ...entry, symlinks: fresh });
|
|
965
|
+
} catch {
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
function sameSorted(a, b) {
|
|
970
|
+
if (a.length !== b.length)
|
|
971
|
+
return false;
|
|
972
|
+
const sa = [...a].sort();
|
|
973
|
+
const sb = [...b].sort();
|
|
974
|
+
for (let i = 0; i < sa.length; i++)
|
|
975
|
+
if (sa[i] !== sb[i])
|
|
976
|
+
return false;
|
|
977
|
+
return true;
|
|
978
|
+
}
|
|
979
|
+
function selectLatestPerName(rows) {
|
|
980
|
+
const seen = /* @__PURE__ */ new Set();
|
|
981
|
+
const out = [];
|
|
982
|
+
for (const r of rows) {
|
|
983
|
+
const name = String(r.name ?? "");
|
|
984
|
+
const projectKey = String(r.project_key ?? "");
|
|
985
|
+
if (!name)
|
|
986
|
+
continue;
|
|
987
|
+
const key = `${projectKey}\0${name}`;
|
|
988
|
+
if (seen.has(key))
|
|
989
|
+
continue;
|
|
990
|
+
seen.add(key);
|
|
991
|
+
out.push(r);
|
|
992
|
+
}
|
|
993
|
+
return out;
|
|
994
|
+
}
|
|
995
|
+
function renderSkillFile(row) {
|
|
996
|
+
const sources = parseSourceSessions(row.source_sessions);
|
|
997
|
+
const fm = {
|
|
998
|
+
name: String(row.name ?? ""),
|
|
999
|
+
description: String(row.description ?? ""),
|
|
1000
|
+
trigger: typeof row.trigger_text === "string" && row.trigger_text.length > 0 ? String(row.trigger_text) : void 0,
|
|
1001
|
+
source_sessions: sources,
|
|
1002
|
+
version: Number(row.version ?? 1),
|
|
1003
|
+
created_by_agent: String(row.source_agent ?? "unknown"),
|
|
1004
|
+
created_at: String(row.created_at ?? (/* @__PURE__ */ new Date()).toISOString()),
|
|
1005
|
+
updated_at: String(row.updated_at ?? (/* @__PURE__ */ new Date()).toISOString())
|
|
1006
|
+
};
|
|
1007
|
+
const body = String(row.body ?? "").trim();
|
|
1008
|
+
return `${renderFrontmatter(fm)}
|
|
1009
|
+
|
|
1010
|
+
${body}
|
|
1011
|
+
`;
|
|
1012
|
+
}
|
|
1013
|
+
function parseSourceSessions(v) {
|
|
1014
|
+
if (Array.isArray(v))
|
|
1015
|
+
return v.map(String);
|
|
1016
|
+
if (typeof v === "string") {
|
|
1017
|
+
try {
|
|
1018
|
+
const parsed = JSON.parse(v);
|
|
1019
|
+
if (Array.isArray(parsed))
|
|
1020
|
+
return parsed.map(String);
|
|
1021
|
+
} catch {
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
return [];
|
|
1025
|
+
}
|
|
1026
|
+
function renderFrontmatter(fm) {
|
|
1027
|
+
const lines = ["---"];
|
|
1028
|
+
lines.push(`name: ${fm.name}`);
|
|
1029
|
+
lines.push(`description: ${JSON.stringify(fm.description)}`);
|
|
1030
|
+
if (fm.trigger)
|
|
1031
|
+
lines.push(`trigger: ${JSON.stringify(fm.trigger)}`);
|
|
1032
|
+
lines.push(`source_sessions:`);
|
|
1033
|
+
for (const s of fm.source_sessions)
|
|
1034
|
+
lines.push(` - ${s}`);
|
|
1035
|
+
lines.push(`version: ${fm.version}`);
|
|
1036
|
+
lines.push(`created_by_agent: ${fm.created_by_agent}`);
|
|
1037
|
+
lines.push(`created_at: ${fm.created_at}`);
|
|
1038
|
+
lines.push(`updated_at: ${fm.updated_at}`);
|
|
1039
|
+
lines.push("---");
|
|
1040
|
+
return lines.join("\n");
|
|
1041
|
+
}
|
|
1042
|
+
function readLocalVersion(path) {
|
|
1043
|
+
if (!existsSync7(path))
|
|
1044
|
+
return null;
|
|
1045
|
+
try {
|
|
1046
|
+
const text = readFileSync7(path, "utf-8");
|
|
1047
|
+
const parsed = parseFrontmatter(text);
|
|
1048
|
+
if (!parsed)
|
|
1049
|
+
return null;
|
|
1050
|
+
const v = parsed.fm.version;
|
|
1051
|
+
return typeof v === "number" ? v : null;
|
|
1052
|
+
} catch {
|
|
1053
|
+
return null;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
function decideAction(args) {
|
|
1057
|
+
const shouldWrite = args.localVersion === null || args.remoteVersion > args.localVersion || args.force;
|
|
1058
|
+
if (!shouldWrite)
|
|
1059
|
+
return "skipped";
|
|
1060
|
+
return args.dryRun ? "dryrun" : "wrote";
|
|
1061
|
+
}
|
|
1062
|
+
async function runPull(opts) {
|
|
1063
|
+
if (!opts.dryRun)
|
|
1064
|
+
pruneOrphanedEntries();
|
|
1065
|
+
const sql = buildPullSql({
|
|
1066
|
+
tableName: opts.tableName,
|
|
1067
|
+
users: opts.users,
|
|
1068
|
+
skillName: opts.skillName
|
|
1069
|
+
});
|
|
1070
|
+
let rows = [];
|
|
1071
|
+
try {
|
|
1072
|
+
rows = await opts.query(sql);
|
|
1073
|
+
} catch (e) {
|
|
1074
|
+
if (isMissingTableError(e?.message))
|
|
1075
|
+
rows = [];
|
|
1076
|
+
else
|
|
1077
|
+
throw e;
|
|
1078
|
+
}
|
|
1079
|
+
const latest = selectLatestPerName(rows);
|
|
1080
|
+
const root = resolvePullDestination(opts.install, opts.cwd);
|
|
1081
|
+
const summary = { scanned: latest.length, wrote: 0, skipped: 0, dryrun: 0, entries: [] };
|
|
1082
|
+
for (const row of latest) {
|
|
1083
|
+
const name = String(row.name ?? "");
|
|
1084
|
+
if (!name)
|
|
1085
|
+
continue;
|
|
1086
|
+
try {
|
|
1087
|
+
assertValidSkillName(name);
|
|
1088
|
+
} catch (e) {
|
|
1089
|
+
summary.entries.push({
|
|
1090
|
+
name,
|
|
1091
|
+
remoteVersion: Number(row.version ?? 1),
|
|
1092
|
+
localVersion: null,
|
|
1093
|
+
action: "skipped",
|
|
1094
|
+
destination: "(invalid name \u2014 skipped)",
|
|
1095
|
+
author: String(row.author ?? ""),
|
|
1096
|
+
sourceAgent: String(row.source_agent ?? "")
|
|
1097
|
+
});
|
|
1098
|
+
summary.skipped++;
|
|
1099
|
+
continue;
|
|
1100
|
+
}
|
|
1101
|
+
const author = String(row.author ?? "");
|
|
1102
|
+
if (!author) {
|
|
1103
|
+
summary.entries.push({
|
|
1104
|
+
name,
|
|
1105
|
+
remoteVersion: Number(row.version ?? 1),
|
|
1106
|
+
localVersion: null,
|
|
1107
|
+
action: "skipped",
|
|
1108
|
+
destination: "(empty author \u2014 skipped)",
|
|
1109
|
+
author: "",
|
|
1110
|
+
sourceAgent: String(row.source_agent ?? "")
|
|
1111
|
+
});
|
|
1112
|
+
summary.skipped++;
|
|
1113
|
+
continue;
|
|
1114
|
+
}
|
|
1115
|
+
let dirName;
|
|
1116
|
+
try {
|
|
1117
|
+
assertValidAuthor(author);
|
|
1118
|
+
dirName = `${name}--${author}`;
|
|
1119
|
+
} catch (e) {
|
|
1120
|
+
summary.entries.push({
|
|
1121
|
+
name,
|
|
1122
|
+
remoteVersion: Number(row.version ?? 1),
|
|
1123
|
+
localVersion: null,
|
|
1124
|
+
action: "skipped",
|
|
1125
|
+
destination: `(invalid author '${author}' \u2014 skipped)`,
|
|
1126
|
+
author,
|
|
1127
|
+
sourceAgent: String(row.source_agent ?? "")
|
|
1128
|
+
});
|
|
1129
|
+
summary.skipped++;
|
|
1130
|
+
continue;
|
|
1131
|
+
}
|
|
1132
|
+
const skillDir = join10(root, dirName);
|
|
1133
|
+
const skillFile = join10(skillDir, "SKILL.md");
|
|
1134
|
+
const remoteVersion = Number(row.version ?? 1);
|
|
1135
|
+
const localVersion = readLocalVersion(skillFile);
|
|
1136
|
+
const action = decideAction({
|
|
1137
|
+
remoteVersion,
|
|
1138
|
+
localVersion,
|
|
1139
|
+
force: opts.force ?? false,
|
|
1140
|
+
dryRun: opts.dryRun ?? false
|
|
1141
|
+
});
|
|
1142
|
+
let manifestError;
|
|
1143
|
+
if (action === "wrote") {
|
|
1144
|
+
mkdirSync5(skillDir, { recursive: true });
|
|
1145
|
+
if (existsSync7(skillFile)) {
|
|
1146
|
+
try {
|
|
1147
|
+
renameSync2(skillFile, `${skillFile}.bak`);
|
|
1148
|
+
} catch {
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
writeFileSync5(skillFile, renderSkillFile(row));
|
|
1152
|
+
const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir, dirName, detectAgentSkillsRoots(root)) : [];
|
|
1153
|
+
try {
|
|
1154
|
+
recordPull({
|
|
1155
|
+
dirName,
|
|
1156
|
+
name,
|
|
1157
|
+
author,
|
|
1158
|
+
projectKey: String(row.project_key ?? ""),
|
|
1159
|
+
remoteVersion,
|
|
1160
|
+
install: opts.install,
|
|
1161
|
+
installRoot: root,
|
|
1162
|
+
pulledAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1163
|
+
symlinks
|
|
1164
|
+
});
|
|
1165
|
+
} catch (e) {
|
|
1166
|
+
manifestError = e?.message ?? String(e);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
summary.entries.push({
|
|
1170
|
+
name,
|
|
1171
|
+
remoteVersion,
|
|
1172
|
+
localVersion,
|
|
1173
|
+
action,
|
|
1174
|
+
destination: skillFile,
|
|
1175
|
+
author: String(row.author ?? ""),
|
|
1176
|
+
sourceAgent: String(row.source_agent ?? ""),
|
|
1177
|
+
manifestError
|
|
1178
|
+
});
|
|
1179
|
+
if (action === "wrote")
|
|
1180
|
+
summary.wrote++;
|
|
1181
|
+
else if (action === "dryrun")
|
|
1182
|
+
summary.dryrun++;
|
|
1183
|
+
else
|
|
1184
|
+
summary.skipped++;
|
|
1185
|
+
}
|
|
1186
|
+
if (!opts.dryRun && opts.install === "global") {
|
|
1187
|
+
backfillSymlinks(root);
|
|
1188
|
+
}
|
|
1189
|
+
return summary;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
// dist/src/skilify/auto-pull.js
|
|
1193
|
+
var log4 = (msg) => log("skilify-autopull", msg);
|
|
1194
|
+
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
1195
|
+
function withTimeout(p, ms) {
|
|
1196
|
+
let timer = null;
|
|
1197
|
+
const timeout = new Promise((_, reject) => {
|
|
1198
|
+
timer = setTimeout(() => reject(new Error(`autopull timeout after ${ms}ms`)), ms);
|
|
1199
|
+
if (typeof timer.unref === "function")
|
|
1200
|
+
timer.unref();
|
|
1201
|
+
});
|
|
1202
|
+
return Promise.race([p, timeout]).finally(() => {
|
|
1203
|
+
if (timer)
|
|
1204
|
+
clearTimeout(timer);
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
async function autoPullSkills(deps = {}) {
|
|
1208
|
+
if (process.env.HIVEMIND_AUTOPULL_DISABLED === "1") {
|
|
1209
|
+
log4("disabled via HIVEMIND_AUTOPULL_DISABLED=1");
|
|
1210
|
+
return { pulled: 0, skipped: true, reason: "disabled" };
|
|
1211
|
+
}
|
|
1212
|
+
const loadFn = deps.loadConfigFn ?? loadConfig;
|
|
1213
|
+
const config = loadFn();
|
|
1214
|
+
if (!config) {
|
|
1215
|
+
log4("skipped: not logged in");
|
|
1216
|
+
return { pulled: 0, skipped: true, reason: "not-logged-in" };
|
|
1217
|
+
}
|
|
1218
|
+
let query;
|
|
1219
|
+
if (deps.queryFn) {
|
|
1220
|
+
query = deps.queryFn;
|
|
1221
|
+
} else {
|
|
1222
|
+
const api = new DeeplakeApi(config.token, config.apiUrl, config.orgId, config.workspaceId, config.skillsTableName);
|
|
1223
|
+
query = (sql) => api.query(sql);
|
|
1224
|
+
}
|
|
1225
|
+
const install = deps.install ?? "global";
|
|
1226
|
+
const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
1227
|
+
try {
|
|
1228
|
+
const summary = await withTimeout(runPull({
|
|
1229
|
+
query,
|
|
1230
|
+
tableName: config.skillsTableName,
|
|
1231
|
+
install,
|
|
1232
|
+
cwd: install === "project" ? deps.cwd ?? process.cwd() : void 0,
|
|
1233
|
+
users: [],
|
|
1234
|
+
dryRun: false,
|
|
1235
|
+
force: false
|
|
1236
|
+
}), timeoutMs);
|
|
1237
|
+
log4(`pulled scanned=${summary.scanned} wrote=${summary.wrote} skipped=${summary.skipped}`);
|
|
1238
|
+
return { pulled: summary.wrote, skipped: false };
|
|
1239
|
+
} catch (e) {
|
|
1240
|
+
log4(`pull failed (swallowed): ${e?.message ?? e}`);
|
|
1241
|
+
return { pulled: 0, skipped: true, reason: "error" };
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
|
|
673
1245
|
// dist/src/hooks/hermes/session-start.js
|
|
674
|
-
var
|
|
675
|
-
var __bundleDir =
|
|
1246
|
+
var log5 = (msg) => log("hermes-session-start", msg);
|
|
1247
|
+
var __bundleDir = dirname4(fileURLToPath(import.meta.url));
|
|
676
1248
|
var context = `DEEPLAKE MEMORY: Persistent memory at ~/.deeplake/memory/ shared across sessions, users, and agents.
|
|
677
1249
|
|
|
678
1250
|
Structure: index.md (start here) \u2192 summaries/*.md \u2192 sessions/*.jsonl (last resort). Do NOT jump straight to JSONL.
|
|
@@ -745,12 +1317,14 @@ async function main() {
|
|
|
745
1317
|
await api.ensureTable();
|
|
746
1318
|
await api.ensureSessionsTable(config.sessionsTableName);
|
|
747
1319
|
await createPlaceholder(api, config.tableName, sessionId, cwd, config.userName, config.orgName, config.workspaceId);
|
|
748
|
-
|
|
1320
|
+
log5("placeholder created");
|
|
749
1321
|
}
|
|
750
1322
|
} catch (e) {
|
|
751
|
-
|
|
1323
|
+
log5(`placeholder failed: ${e.message}`);
|
|
752
1324
|
}
|
|
753
1325
|
}
|
|
1326
|
+
const pullResult = await autoPullSkills();
|
|
1327
|
+
log5(`autopull: pulled=${pullResult.pulled} skipped=${pullResult.skipped}`);
|
|
754
1328
|
let versionNotice = "";
|
|
755
1329
|
const current = getInstalledVersion(__bundleDir, ".claude-plugin");
|
|
756
1330
|
if (current)
|
|
@@ -762,6 +1336,6 @@ Not logged in to Deeplake. Run: hivemind login${versionNotice}`;
|
|
|
762
1336
|
console.log(JSON.stringify({ context: additional }));
|
|
763
1337
|
}
|
|
764
1338
|
main().catch((e) => {
|
|
765
|
-
|
|
1339
|
+
log5(`fatal: ${e.message}`);
|
|
766
1340
|
process.exit(0);
|
|
767
1341
|
});
|
package/openclaw/dist/index.js
CHANGED
|
@@ -1070,7 +1070,7 @@ function extractLatestVersion(body) {
|
|
|
1070
1070
|
return typeof v === "string" && v.length > 0 ? v : null;
|
|
1071
1071
|
}
|
|
1072
1072
|
function getInstalledVersion() {
|
|
1073
|
-
return "0.7.
|
|
1073
|
+
return "0.7.17".length > 0 ? "0.7.17" : null;
|
|
1074
1074
|
}
|
|
1075
1075
|
function isNewer(latest, current) {
|
|
1076
1076
|
const parse = (v) => v.replace(/-.*$/, "").split(".").map(Number);
|
package/openclaw/package.json
CHANGED