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