@deeplake/hivemind 0.7.76 → 0.7.77
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 +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/bundle/cli.js +1077 -230
- package/codex/bundle/graph-on-stop.js +3148 -0
- package/codex/bundle/graph-pull-worker.js +40 -1
- package/codex/bundle/pre-tool-use.js +1237 -21
- package/codex/bundle/shell/deeplake-shell.js +725 -20
- package/codex/skills/hivemind-graph/SKILL.md +94 -0
- package/cursor/bundle/graph-on-stop.js +3148 -0
- package/cursor/bundle/graph-pull-worker.js +40 -1
- package/cursor/bundle/pre-tool-use.js +1232 -8
- package/cursor/bundle/session-start.js +214 -7
- package/cursor/bundle/shell/deeplake-shell.js +725 -20
- package/hermes/bundle/graph-on-stop.js +3148 -0
- package/hermes/bundle/graph-pull-worker.js +40 -1
- package/hermes/bundle/pre-tool-use.js +1225 -8
- package/hermes/bundle/session-start.js +213 -8
- package/hermes/bundle/shell/deeplake-shell.js +725 -20
- package/openclaw/dist/index.js +1 -1
- package/openclaw/openclaw.plugin.json +1 -1
- package/openclaw/package.json +1 -1
- package/package.json +2 -1
- package/scripts/ensure-tree-sitter.mjs +6 -1
package/bundle/cli.js
CHANGED
|
@@ -372,16 +372,29 @@ function buildHooksJson() {
|
|
|
372
372
|
UserPromptSubmit: [hookCmd("capture.js", 10)],
|
|
373
373
|
PreToolUse: [hookCmd("pre-tool-use.js", 10, "Bash")],
|
|
374
374
|
PostToolUse: [hookCmd("capture.js", 15)],
|
|
375
|
-
Stop
|
|
375
|
+
// One Stop matcher-block with TWO commands — stop.js (capture) +
|
|
376
|
+
// graph-on-stop.js (code-graph auto-build, G3). Single block (not two)
|
|
377
|
+
// mirrors the static codex/hooks/hooks.json and keeps one entry per
|
|
378
|
+
// event for the merge/dedupe logic.
|
|
379
|
+
Stop: [stopBlockWithGraph(30)]
|
|
376
380
|
}
|
|
377
381
|
};
|
|
378
382
|
}
|
|
383
|
+
function stopBlockWithGraph(timeout) {
|
|
384
|
+
return {
|
|
385
|
+
hooks: [
|
|
386
|
+
{ type: "command", command: `node "${join4(PLUGIN_DIR, "bundle", "stop.js")}"`, timeout },
|
|
387
|
+
{ type: "command", command: `node "${join4(PLUGIN_DIR, "bundle", "graph-on-stop.js")}"`, timeout }
|
|
388
|
+
]
|
|
389
|
+
};
|
|
390
|
+
}
|
|
379
391
|
var HIVEMIND_BUNDLE_FILES = [
|
|
380
392
|
"session-start.js",
|
|
381
393
|
"session-start-setup.js",
|
|
382
394
|
"capture.js",
|
|
383
395
|
"pre-tool-use.js",
|
|
384
396
|
"stop.js",
|
|
397
|
+
"graph-on-stop.js",
|
|
385
398
|
"wiki-worker.js"
|
|
386
399
|
];
|
|
387
400
|
function isHivemindHookEntry(entry, pluginDir = PLUGIN_DIR) {
|
|
@@ -716,8 +729,12 @@ function buildHookConfig() {
|
|
|
716
729
|
preToolUse: [buildHookCmdShellMatcher("pre-tool-use.js", 30)],
|
|
717
730
|
postToolUse: [buildHookCmd("capture.js", 15)],
|
|
718
731
|
afterAgentResponse: [buildHookCmd("capture.js", 15)],
|
|
719
|
-
stop:
|
|
720
|
-
|
|
732
|
+
// graph-on-stop: auto-build the code graph (A1 Cursor parity). Same hook
|
|
733
|
+
// Claude Code registers under Stop + SessionEnd. It's gated (rate limit +
|
|
734
|
+
// HEAD-changed + source-diff) so the common path is a ~5ms skip, and runs
|
|
735
|
+
// async so it never blocks Cursor.
|
|
736
|
+
stop: [buildHookCmd("capture.js", 15), buildHookCmd("graph-on-stop.js", 30)],
|
|
737
|
+
sessionEnd: [buildHookCmd("session-end.js", 30), buildHookCmd("graph-on-stop.js", 30)]
|
|
721
738
|
};
|
|
722
739
|
}
|
|
723
740
|
function isHivemindEntry(entry) {
|
|
@@ -3479,7 +3496,10 @@ function buildHooksBlock() {
|
|
|
3479
3496
|
pre_llm_call: [buildHookEntry("capture.js", 10)],
|
|
3480
3497
|
post_tool_call: [buildHookEntry("capture.js", 15)],
|
|
3481
3498
|
post_llm_call: [buildHookEntry("capture.js", 15)],
|
|
3482
|
-
|
|
3499
|
+
// graph-on-stop: code-graph auto-build parity (G3), same gated hook as the
|
|
3500
|
+
// other agents. on_session_end is Hermes's session-close event (analogous
|
|
3501
|
+
// to Claude Code's SessionEnd).
|
|
3502
|
+
on_session_end: [buildHookEntry("session-end.js", 30), buildHookEntry("graph-on-stop.js", 30)]
|
|
3483
3503
|
};
|
|
3484
3504
|
}
|
|
3485
3505
|
function mergeHooks3(existing) {
|
|
@@ -5653,8 +5673,8 @@ if (process.argv[1] && process.argv[1].endsWith("auth-login.js")) {
|
|
|
5653
5673
|
|
|
5654
5674
|
// dist/src/commands/graph.js
|
|
5655
5675
|
import { execSync as execSync3 } from "node:child_process";
|
|
5656
|
-
import { readFileSync as
|
|
5657
|
-
import { join as
|
|
5676
|
+
import { readFileSync as readFileSync21, readdirSync as readdirSync2 } from "node:fs";
|
|
5677
|
+
import { join as join28, relative, resolve as resolve4, sep } from "node:path";
|
|
5658
5678
|
import { createHash as createHash6 } from "node:crypto";
|
|
5659
5679
|
|
|
5660
5680
|
// dist/src/graph/cache.js
|
|
@@ -6094,6 +6114,282 @@ import { createHash as createHash4 } from "node:crypto";
|
|
|
6094
6114
|
import { mkdirSync as mkdirSync10, renameSync as renameSync6, writeFileSync as writeFileSync14 } from "node:fs";
|
|
6095
6115
|
import { homedir as homedir10 } from "node:os";
|
|
6096
6116
|
import { dirname as dirname6, join as join23 } from "node:path";
|
|
6117
|
+
|
|
6118
|
+
// dist/src/graph/resolve/cross-file.js
|
|
6119
|
+
import { posix } from "node:path";
|
|
6120
|
+
var EXPORTABLE_KINDS = /* @__PURE__ */ new Set([
|
|
6121
|
+
"function",
|
|
6122
|
+
"class",
|
|
6123
|
+
"const",
|
|
6124
|
+
"interface",
|
|
6125
|
+
"type_alias",
|
|
6126
|
+
"enum"
|
|
6127
|
+
]);
|
|
6128
|
+
var HERITAGE_KINDS = /* @__PURE__ */ new Set([
|
|
6129
|
+
"class",
|
|
6130
|
+
"interface",
|
|
6131
|
+
"type_alias",
|
|
6132
|
+
"enum"
|
|
6133
|
+
]);
|
|
6134
|
+
function buildExportIndex(nodes) {
|
|
6135
|
+
const idx = /* @__PURE__ */ new Map();
|
|
6136
|
+
for (const n of nodes) {
|
|
6137
|
+
if (!n.exported || !EXPORTABLE_KINDS.has(n.kind))
|
|
6138
|
+
continue;
|
|
6139
|
+
let m = idx.get(n.source_file);
|
|
6140
|
+
if (!m) {
|
|
6141
|
+
m = /* @__PURE__ */ new Map();
|
|
6142
|
+
idx.set(n.source_file, m);
|
|
6143
|
+
}
|
|
6144
|
+
if (!m.has(n.label))
|
|
6145
|
+
m.set(n.label, n.id);
|
|
6146
|
+
}
|
|
6147
|
+
return idx;
|
|
6148
|
+
}
|
|
6149
|
+
function resolveCrossFileCalls(extractions, nodes) {
|
|
6150
|
+
const knownFiles = /* @__PURE__ */ new Set();
|
|
6151
|
+
for (const ex of extractions)
|
|
6152
|
+
knownFiles.add(ex.source_file);
|
|
6153
|
+
const exportIndex = buildExportIndex(nodes);
|
|
6154
|
+
const edges = [];
|
|
6155
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6156
|
+
for (const ex of extractions) {
|
|
6157
|
+
const rawCalls = ex.raw_calls ?? [];
|
|
6158
|
+
const bindings = ex.import_bindings ?? [];
|
|
6159
|
+
if (rawCalls.length === 0 || bindings.length === 0)
|
|
6160
|
+
continue;
|
|
6161
|
+
const byLocal = /* @__PURE__ */ new Map();
|
|
6162
|
+
for (const b of bindings) {
|
|
6163
|
+
if (!byLocal.has(b.local_name))
|
|
6164
|
+
byLocal.set(b.local_name, b);
|
|
6165
|
+
}
|
|
6166
|
+
for (const rc of rawCalls) {
|
|
6167
|
+
const target = resolveOne(rc, byLocal, ex.source_file, knownFiles, exportIndex);
|
|
6168
|
+
if (target === null)
|
|
6169
|
+
continue;
|
|
6170
|
+
const key = `${rc.caller_id}\0${target}`;
|
|
6171
|
+
if (seen.has(key))
|
|
6172
|
+
continue;
|
|
6173
|
+
seen.add(key);
|
|
6174
|
+
edges.push({
|
|
6175
|
+
source: rc.caller_id,
|
|
6176
|
+
target,
|
|
6177
|
+
relation: "calls",
|
|
6178
|
+
confidence: "EXTRACTED"
|
|
6179
|
+
});
|
|
6180
|
+
}
|
|
6181
|
+
}
|
|
6182
|
+
return edges;
|
|
6183
|
+
}
|
|
6184
|
+
function resolveOne(rc, byLocal, fromFile, knownFiles, exportIndex) {
|
|
6185
|
+
let binding;
|
|
6186
|
+
let exportName;
|
|
6187
|
+
if (rc.receiver !== void 0) {
|
|
6188
|
+
binding = byLocal.get(rc.receiver);
|
|
6189
|
+
if (binding === void 0 || binding.kind !== "namespace")
|
|
6190
|
+
return null;
|
|
6191
|
+
if (binding.type_only)
|
|
6192
|
+
return null;
|
|
6193
|
+
exportName = rc.callee_name;
|
|
6194
|
+
} else {
|
|
6195
|
+
binding = byLocal.get(rc.callee_name);
|
|
6196
|
+
if (binding === void 0)
|
|
6197
|
+
return null;
|
|
6198
|
+
if (binding.type_only)
|
|
6199
|
+
return null;
|
|
6200
|
+
if (binding.kind !== "named")
|
|
6201
|
+
return null;
|
|
6202
|
+
exportName = binding.imported_name;
|
|
6203
|
+
}
|
|
6204
|
+
const targetFile = resolveModule(fromFile, binding.specifier, knownFiles);
|
|
6205
|
+
if (targetFile === null)
|
|
6206
|
+
return null;
|
|
6207
|
+
return exportIndex.get(targetFile)?.get(exportName) ?? null;
|
|
6208
|
+
}
|
|
6209
|
+
var MODULE_SUFFIX = "::module";
|
|
6210
|
+
var EXTERNAL_PREFIX = "external:";
|
|
6211
|
+
function repointImportEdges(links, knownFiles) {
|
|
6212
|
+
return links.map((e) => {
|
|
6213
|
+
if (e.relation !== "imports" || !e.target.startsWith(EXTERNAL_PREFIX))
|
|
6214
|
+
return e;
|
|
6215
|
+
if (!e.source.endsWith(MODULE_SUFFIX))
|
|
6216
|
+
return e;
|
|
6217
|
+
const fromFile = e.source.slice(0, -MODULE_SUFFIX.length);
|
|
6218
|
+
const specifier = e.target.slice(EXTERNAL_PREFIX.length);
|
|
6219
|
+
const resolved = resolveModule(fromFile, specifier, knownFiles);
|
|
6220
|
+
if (resolved === null)
|
|
6221
|
+
return e;
|
|
6222
|
+
return { ...e, target: `${resolved}${MODULE_SUFFIX}` };
|
|
6223
|
+
});
|
|
6224
|
+
}
|
|
6225
|
+
var UNRESOLVED_PREFIX = "unresolved:";
|
|
6226
|
+
function resolveHeritageEdges(links, extractions, nodes) {
|
|
6227
|
+
const knownFiles = /* @__PURE__ */ new Set();
|
|
6228
|
+
for (const ex of extractions)
|
|
6229
|
+
knownFiles.add(ex.source_file);
|
|
6230
|
+
const exportIndex = buildExportIndex(nodes);
|
|
6231
|
+
const localIndex = /* @__PURE__ */ new Map();
|
|
6232
|
+
for (const n of nodes) {
|
|
6233
|
+
if (!HERITAGE_KINDS.has(n.kind))
|
|
6234
|
+
continue;
|
|
6235
|
+
let m = localIndex.get(n.source_file);
|
|
6236
|
+
if (!m) {
|
|
6237
|
+
m = /* @__PURE__ */ new Map();
|
|
6238
|
+
localIndex.set(n.source_file, m);
|
|
6239
|
+
}
|
|
6240
|
+
if (!m.has(n.label))
|
|
6241
|
+
m.set(n.label, n.id);
|
|
6242
|
+
}
|
|
6243
|
+
const bindingsByFile = /* @__PURE__ */ new Map();
|
|
6244
|
+
for (const ex of extractions) {
|
|
6245
|
+
const m = /* @__PURE__ */ new Map();
|
|
6246
|
+
for (const b of ex.import_bindings ?? [])
|
|
6247
|
+
if (!m.has(b.local_name))
|
|
6248
|
+
m.set(b.local_name, b);
|
|
6249
|
+
bindingsByFile.set(ex.source_file, m);
|
|
6250
|
+
}
|
|
6251
|
+
return links.map((e) => {
|
|
6252
|
+
if (e.relation !== "extends" && e.relation !== "implements")
|
|
6253
|
+
return e;
|
|
6254
|
+
if (!e.target.startsWith(UNRESOLVED_PREFIX))
|
|
6255
|
+
return e;
|
|
6256
|
+
const parsed = parseUnresolved(e.target);
|
|
6257
|
+
if (parsed === null)
|
|
6258
|
+
return e;
|
|
6259
|
+
const { file, name } = parsed;
|
|
6260
|
+
const local = localIndex.get(file)?.get(name);
|
|
6261
|
+
if (local !== void 0)
|
|
6262
|
+
return { ...e, target: local };
|
|
6263
|
+
const binding = bindingsByFile.get(file)?.get(name);
|
|
6264
|
+
if (binding !== void 0 && binding.kind === "named") {
|
|
6265
|
+
const targetFile = resolveModule(file, binding.specifier, knownFiles);
|
|
6266
|
+
if (targetFile !== null) {
|
|
6267
|
+
const id = exportIndex.get(targetFile)?.get(binding.imported_name);
|
|
6268
|
+
if (id !== void 0)
|
|
6269
|
+
return { ...e, target: id };
|
|
6270
|
+
}
|
|
6271
|
+
}
|
|
6272
|
+
return e;
|
|
6273
|
+
});
|
|
6274
|
+
}
|
|
6275
|
+
function parseUnresolved(target) {
|
|
6276
|
+
const body = target.slice(UNRESOLVED_PREFIX.length);
|
|
6277
|
+
const lastColon = body.lastIndexOf(":");
|
|
6278
|
+
if (lastColon <= 0)
|
|
6279
|
+
return null;
|
|
6280
|
+
const rest = body.slice(0, lastColon);
|
|
6281
|
+
const nameColon = rest.lastIndexOf(":");
|
|
6282
|
+
if (nameColon <= 0)
|
|
6283
|
+
return null;
|
|
6284
|
+
const file = rest.slice(0, nameColon);
|
|
6285
|
+
const name = rest.slice(nameColon + 1);
|
|
6286
|
+
if (file.length === 0 || name.length === 0)
|
|
6287
|
+
return null;
|
|
6288
|
+
return { file, name };
|
|
6289
|
+
}
|
|
6290
|
+
function resolveModule(fromFile, specifier, knownFiles) {
|
|
6291
|
+
if (isPythonFile(fromFile))
|
|
6292
|
+
return resolvePythonModule(fromFile, specifier, knownFiles);
|
|
6293
|
+
if (!specifier.startsWith("./") && !specifier.startsWith("../"))
|
|
6294
|
+
return null;
|
|
6295
|
+
const baseDir = posix.dirname(fromFile);
|
|
6296
|
+
const explicit = specifier.match(/\.(tsx?|jsx?|mjs|cjs)$/)?.[0] ?? null;
|
|
6297
|
+
const stem = explicit ? specifier.slice(0, -explicit.length) : specifier;
|
|
6298
|
+
const joined = posix.normalize(posix.join(baseDir, stem));
|
|
6299
|
+
const TS_EXTS = [".ts", ".tsx"];
|
|
6300
|
+
const JS_EXTS = [".js", ".jsx", ".mjs", ".cjs"];
|
|
6301
|
+
const importerIsJs = /\.(jsx?|mjs|cjs)$/.test(fromFile);
|
|
6302
|
+
const primary = importerIsJs ? JS_EXTS : TS_EXTS;
|
|
6303
|
+
const secondary = importerIsJs ? TS_EXTS : JS_EXTS;
|
|
6304
|
+
const exts = [
|
|
6305
|
+
...explicit ? [explicit] : [],
|
|
6306
|
+
...primary,
|
|
6307
|
+
...secondary
|
|
6308
|
+
].filter((e, i, a) => a.indexOf(e) === i);
|
|
6309
|
+
for (const e of exts) {
|
|
6310
|
+
const c = `${joined}${e}`;
|
|
6311
|
+
if (knownFiles.has(c))
|
|
6312
|
+
return c;
|
|
6313
|
+
}
|
|
6314
|
+
for (const e of exts) {
|
|
6315
|
+
const c = `${joined}/index${e}`;
|
|
6316
|
+
if (knownFiles.has(c))
|
|
6317
|
+
return c;
|
|
6318
|
+
}
|
|
6319
|
+
return null;
|
|
6320
|
+
}
|
|
6321
|
+
var PY_EXTS = [".py", ".pyi"];
|
|
6322
|
+
function isPythonFile(p) {
|
|
6323
|
+
return p.endsWith(".py") || p.endsWith(".pyi");
|
|
6324
|
+
}
|
|
6325
|
+
function resolvePythonModule(fromFile, specifier, knownFiles) {
|
|
6326
|
+
let dots = 0;
|
|
6327
|
+
while (dots < specifier.length && specifier[dots] === ".")
|
|
6328
|
+
dots++;
|
|
6329
|
+
const tail = specifier.slice(dots);
|
|
6330
|
+
const segs = tail.length > 0 ? tail.split(".") : [];
|
|
6331
|
+
if (dots === 0) {
|
|
6332
|
+
if (segs.length === 0)
|
|
6333
|
+
return null;
|
|
6334
|
+
return matchPythonSuffix(segs.join("/"), knownFiles);
|
|
6335
|
+
}
|
|
6336
|
+
let dir = posix.dirname(fromFile);
|
|
6337
|
+
let climbed = 1;
|
|
6338
|
+
for (; climbed < dots && dir !== "" && dir !== "."; climbed++)
|
|
6339
|
+
dir = posix.dirname(dir);
|
|
6340
|
+
if (climbed < dots)
|
|
6341
|
+
return null;
|
|
6342
|
+
const base = segs.length > 0 ? posix.normalize(posix.join(dir, ...segs)) : dir;
|
|
6343
|
+
for (const e of PY_EXTS)
|
|
6344
|
+
if (knownFiles.has(`${base}${e}`))
|
|
6345
|
+
return `${base}${e}`;
|
|
6346
|
+
for (const e of PY_EXTS)
|
|
6347
|
+
if (knownFiles.has(`${base}/__init__${e}`))
|
|
6348
|
+
return `${base}/__init__${e}`;
|
|
6349
|
+
return null;
|
|
6350
|
+
}
|
|
6351
|
+
function matchPythonSuffix(suffix, knownFiles) {
|
|
6352
|
+
const targets = [
|
|
6353
|
+
...PY_EXTS.map((e) => `${suffix}${e}`),
|
|
6354
|
+
...PY_EXTS.map((e) => `${suffix}/__init__${e}`)
|
|
6355
|
+
];
|
|
6356
|
+
for (const t of targets) {
|
|
6357
|
+
if (knownFiles.has(t))
|
|
6358
|
+
return t;
|
|
6359
|
+
let hit = null;
|
|
6360
|
+
let count = 0;
|
|
6361
|
+
for (const f of knownFiles) {
|
|
6362
|
+
if (f.endsWith(`/${t}`)) {
|
|
6363
|
+
hit = f;
|
|
6364
|
+
count++;
|
|
6365
|
+
}
|
|
6366
|
+
}
|
|
6367
|
+
if (count === 1)
|
|
6368
|
+
return hit;
|
|
6369
|
+
if (count > 1)
|
|
6370
|
+
return null;
|
|
6371
|
+
}
|
|
6372
|
+
return null;
|
|
6373
|
+
}
|
|
6374
|
+
|
|
6375
|
+
// dist/src/graph/node-metadata.js
|
|
6376
|
+
function annotateNodeDegrees(nodes, links) {
|
|
6377
|
+
const inDeg = /* @__PURE__ */ new Map();
|
|
6378
|
+
const outDeg = /* @__PURE__ */ new Map();
|
|
6379
|
+
for (const e of links) {
|
|
6380
|
+
outDeg.set(e.source, (outDeg.get(e.source) ?? 0) + 1);
|
|
6381
|
+
inDeg.set(e.target, (inDeg.get(e.target) ?? 0) + 1);
|
|
6382
|
+
}
|
|
6383
|
+
for (const n of nodes) {
|
|
6384
|
+
const fi = inDeg.get(n.id) ?? 0;
|
|
6385
|
+
const fo = outDeg.get(n.id) ?? 0;
|
|
6386
|
+
n.fan_in = fi;
|
|
6387
|
+
n.fan_out = fo;
|
|
6388
|
+
n.is_entrypoint = n.exported && fi === 0;
|
|
6389
|
+
}
|
|
6390
|
+
}
|
|
6391
|
+
|
|
6392
|
+
// dist/src/graph/snapshot.js
|
|
6097
6393
|
function graphsRoot() {
|
|
6098
6394
|
return process.env.HIVEMIND_GRAPHS_HOME ?? join23(homedir10(), ".hivemind", "graphs");
|
|
6099
6395
|
}
|
|
@@ -6109,15 +6405,23 @@ function buildSnapshot(extractions, metadata, observation) {
|
|
|
6109
6405
|
for (const e of ex.edges)
|
|
6110
6406
|
links.push(e);
|
|
6111
6407
|
}
|
|
6408
|
+
for (const e of resolveCrossFileCalls(extractions, nodes))
|
|
6409
|
+
links.push(e);
|
|
6410
|
+
const knownFiles = /* @__PURE__ */ new Set();
|
|
6411
|
+
for (const ex of extractions)
|
|
6412
|
+
knownFiles.add(ex.source_file);
|
|
6413
|
+
let resolvedLinks = repointImportEdges(links, knownFiles);
|
|
6414
|
+
resolvedLinks = resolveHeritageEdges(resolvedLinks, extractions, nodes);
|
|
6415
|
+
annotateNodeDegrees(nodes, resolvedLinks);
|
|
6112
6416
|
nodes.sort(compareNodes);
|
|
6113
|
-
|
|
6417
|
+
resolvedLinks.sort(compareEdges);
|
|
6114
6418
|
return {
|
|
6115
6419
|
directed: true,
|
|
6116
6420
|
multigraph: true,
|
|
6117
6421
|
graph: metadata,
|
|
6118
6422
|
observation,
|
|
6119
6423
|
nodes,
|
|
6120
|
-
links
|
|
6424
|
+
links: resolvedLinks
|
|
6121
6425
|
};
|
|
6122
6426
|
}
|
|
6123
6427
|
function compareNodes(a, b) {
|
|
@@ -6235,8 +6539,20 @@ async function pullSnapshot(cwd, deps = {}) {
|
|
|
6235
6539
|
if (cloudPayload === null) {
|
|
6236
6540
|
return errorOutcome2("SELECT cloud row", new Error("invalid snapshot_jsonb payload"));
|
|
6237
6541
|
}
|
|
6542
|
+
let parsedSnapshot;
|
|
6543
|
+
try {
|
|
6544
|
+
parsedSnapshot = JSON.parse(cloudPayload);
|
|
6545
|
+
} catch (err) {
|
|
6546
|
+
return errorOutcome2("parse cloud snapshot", err);
|
|
6547
|
+
}
|
|
6548
|
+
if (parsedSnapshot === null || typeof parsedSnapshot !== "object") {
|
|
6549
|
+
return errorOutcome2("parse cloud snapshot", new Error("snapshot not an object"));
|
|
6550
|
+
}
|
|
6551
|
+
if (!Array.isArray(parsedSnapshot.nodes) || !Array.isArray(parsedSnapshot.links)) {
|
|
6552
|
+
return errorOutcome2("parse cloud snapshot", new Error("snapshot missing nodes/links arrays"));
|
|
6553
|
+
}
|
|
6238
6554
|
if (cloudSha256 !== "") {
|
|
6239
|
-
const computedSha =
|
|
6555
|
+
const computedSha = computeSnapshotSha2562(parsedSnapshot);
|
|
6240
6556
|
if (cloudSha256 !== computedSha) {
|
|
6241
6557
|
return errorOutcome2("SELECT cloud row", new Error(`snapshot_sha256 mismatch (expected ${cloudSha256}, got ${computedSha})`));
|
|
6242
6558
|
}
|
|
@@ -6454,11 +6770,11 @@ function pickParserForPath(relativePath) {
|
|
|
6454
6770
|
}
|
|
6455
6771
|
function extractTypeScript(sourceCode, relativePath) {
|
|
6456
6772
|
const parser = pickParserForPath(relativePath);
|
|
6457
|
-
const
|
|
6773
|
+
const CHUNK_BYTES2 = 16384;
|
|
6458
6774
|
const tree = parser.parse((index) => {
|
|
6459
6775
|
if (index >= sourceCode.length)
|
|
6460
6776
|
return null;
|
|
6461
|
-
return sourceCode.slice(index, index +
|
|
6777
|
+
return sourceCode.slice(index, index + CHUNK_BYTES2);
|
|
6462
6778
|
});
|
|
6463
6779
|
const root = tree.rootNode;
|
|
6464
6780
|
const result = {
|
|
@@ -6466,7 +6782,9 @@ function extractTypeScript(sourceCode, relativePath) {
|
|
|
6466
6782
|
language: "typescript",
|
|
6467
6783
|
nodes: [],
|
|
6468
6784
|
edges: [],
|
|
6469
|
-
parse_errors: []
|
|
6785
|
+
parse_errors: [],
|
|
6786
|
+
raw_calls: [],
|
|
6787
|
+
import_bindings: []
|
|
6470
6788
|
};
|
|
6471
6789
|
collectParseErrors(root, relativePath, result.parse_errors);
|
|
6472
6790
|
const moduleNode = makeModuleNode(relativePath);
|
|
@@ -6475,8 +6793,16 @@ function extractTypeScript(sourceCode, relativePath) {
|
|
|
6475
6793
|
extractDeclarations(root, relativePath, result, declByName, moduleNode);
|
|
6476
6794
|
extractImports(root, relativePath, result, moduleNode);
|
|
6477
6795
|
extractCalls(root, relativePath, result, declByName);
|
|
6796
|
+
if (isJavaScriptPath(relativePath)) {
|
|
6797
|
+
result.language = "javascript";
|
|
6798
|
+
for (const n of result.nodes)
|
|
6799
|
+
n.language = "javascript";
|
|
6800
|
+
}
|
|
6478
6801
|
return result;
|
|
6479
6802
|
}
|
|
6803
|
+
function isJavaScriptPath(relativePath) {
|
|
6804
|
+
return /\.(jsx?|mjs|cjs)$/.test(relativePath);
|
|
6805
|
+
}
|
|
6480
6806
|
function collectParseErrors(node, relativePath, out) {
|
|
6481
6807
|
if (node.isError || node.isMissing) {
|
|
6482
6808
|
out.push({
|
|
@@ -6573,8 +6899,8 @@ function handleDeclaration(node, exported, relativePath, result, declByName, mod
|
|
|
6573
6899
|
continue;
|
|
6574
6900
|
const accessibility = firstNamedChildOfTypes(member, ["accessibility_modifier"]);
|
|
6575
6901
|
const isHardPrivate = firstNamedChildOfTypes(member, ["private_property_identifier"]) !== null;
|
|
6576
|
-
const
|
|
6577
|
-
const methodExported = exported &&
|
|
6902
|
+
const isPublic2 = !isHardPrivate && (accessibility === null || accessibility.text === "public");
|
|
6903
|
+
const methodExported = exported && isPublic2;
|
|
6578
6904
|
const methodKey = `${classNode.label}.${methodName}`;
|
|
6579
6905
|
const methodNode = makeNodeWithExplicitLabel(relativePath, methodKey, methodName, "method", member, methodExported);
|
|
6580
6906
|
pushNode(result, declByName, methodNode, methodKey);
|
|
@@ -6641,6 +6967,7 @@ function extractImports(node, relativePath, result, moduleNode) {
|
|
|
6641
6967
|
relation: "imports",
|
|
6642
6968
|
confidence: "EXTRACTED"
|
|
6643
6969
|
});
|
|
6970
|
+
extractImportBindings(node, specifier, result);
|
|
6644
6971
|
}
|
|
6645
6972
|
}
|
|
6646
6973
|
return;
|
|
@@ -6651,23 +6978,60 @@ function extractImports(node, relativePath, result, moduleNode) {
|
|
|
6651
6978
|
extractImports(child, relativePath, result, moduleNode);
|
|
6652
6979
|
}
|
|
6653
6980
|
}
|
|
6981
|
+
function extractImportBindings(importStmt, specifier, result) {
|
|
6982
|
+
const stmtTypeOnly = /^import\s+type\b/.test(importStmt.text.trimStart());
|
|
6983
|
+
const clause = firstNamedChildOfTypes(importStmt, ["import_clause"]);
|
|
6984
|
+
if (clause === null)
|
|
6985
|
+
return;
|
|
6986
|
+
const push = (b) => {
|
|
6987
|
+
result.import_bindings.push({ ...b, specifier });
|
|
6988
|
+
};
|
|
6989
|
+
for (let i = 0; i < clause.namedChildCount; i++) {
|
|
6990
|
+
const child = clause.namedChild(i);
|
|
6991
|
+
if (child === null)
|
|
6992
|
+
continue;
|
|
6993
|
+
if (child.type === "identifier") {
|
|
6994
|
+
push({ local_name: child.text, imported_name: "default", kind: "default", type_only: stmtTypeOnly });
|
|
6995
|
+
} else if (child.type === "namespace_import") {
|
|
6996
|
+
const id = firstNamedChildOfTypes(child, ["identifier"]);
|
|
6997
|
+
if (id !== null)
|
|
6998
|
+
push({ local_name: id.text, imported_name: "*", kind: "namespace", type_only: stmtTypeOnly });
|
|
6999
|
+
} else if (child.type === "named_imports") {
|
|
7000
|
+
for (let j = 0; j < child.namedChildCount; j++) {
|
|
7001
|
+
const spec = child.namedChild(j);
|
|
7002
|
+
if (spec === null || spec.type !== "import_specifier")
|
|
7003
|
+
continue;
|
|
7004
|
+
const specTypeOnly = stmtTypeOnly || /^type\s+(?!as\b)/.test(spec.text);
|
|
7005
|
+
const nameNode = spec.childForFieldName("name");
|
|
7006
|
+
const aliasNode = spec.childForFieldName("alias");
|
|
7007
|
+
const imported = nameNode !== null ? nameNode.text : null;
|
|
7008
|
+
if (imported === null)
|
|
7009
|
+
continue;
|
|
7010
|
+
const local = aliasNode !== null ? aliasNode.text : imported;
|
|
7011
|
+
push({ local_name: local, imported_name: imported, kind: "named", type_only: specTypeOnly });
|
|
7012
|
+
}
|
|
7013
|
+
}
|
|
7014
|
+
}
|
|
7015
|
+
}
|
|
6654
7016
|
function extractCalls(node, relativePath, result, declByName) {
|
|
6655
7017
|
if (node.type === "call_expression") {
|
|
6656
7018
|
const callee = node.childForFieldName("function");
|
|
6657
7019
|
if (callee !== null) {
|
|
6658
|
-
const
|
|
6659
|
-
if (
|
|
6660
|
-
const
|
|
7020
|
+
const callerNode = findEnclosingDeclaration(node, declByName);
|
|
7021
|
+
if (callerNode !== null) {
|
|
7022
|
+
const calleeKey = resolveCalleeKey(callee, declByName);
|
|
7023
|
+
const targetNode = calleeKey !== null ? declByName.get(calleeKey) : void 0;
|
|
6661
7024
|
if (targetNode !== void 0) {
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
7025
|
+
result.edges.push({
|
|
7026
|
+
source: callerNode.id,
|
|
7027
|
+
target: targetNode.id,
|
|
7028
|
+
relation: "calls",
|
|
7029
|
+
confidence: "EXTRACTED"
|
|
7030
|
+
});
|
|
7031
|
+
} else {
|
|
7032
|
+
const rc = rawCallFromCallee(callee, callerNode.id);
|
|
7033
|
+
if (rc !== null)
|
|
7034
|
+
result.raw_calls.push(rc);
|
|
6671
7035
|
}
|
|
6672
7036
|
}
|
|
6673
7037
|
}
|
|
@@ -6678,6 +7042,19 @@ function extractCalls(node, relativePath, result, declByName) {
|
|
|
6678
7042
|
extractCalls(child, relativePath, result, declByName);
|
|
6679
7043
|
}
|
|
6680
7044
|
}
|
|
7045
|
+
function rawCallFromCallee(callee, callerId) {
|
|
7046
|
+
if (callee.type === "identifier") {
|
|
7047
|
+
return { caller_id: callerId, callee_name: callee.text };
|
|
7048
|
+
}
|
|
7049
|
+
if (callee.type === "member_expression") {
|
|
7050
|
+
const object = callee.childForFieldName("object");
|
|
7051
|
+
const property = callee.childForFieldName("property");
|
|
7052
|
+
if (object !== null && object.type === "identifier" && property !== null && property.type === "property_identifier") {
|
|
7053
|
+
return { caller_id: callerId, callee_name: property.text, receiver: object.text };
|
|
7054
|
+
}
|
|
7055
|
+
}
|
|
7056
|
+
return null;
|
|
7057
|
+
}
|
|
6681
7058
|
function resolveCalleeKey(callee, declByName) {
|
|
6682
7059
|
if (callee.type === "identifier")
|
|
6683
7060
|
return callee.text;
|
|
@@ -6754,9 +7131,31 @@ function makeNode(relativePath, name, kind, node, exported) {
|
|
|
6754
7131
|
source_file: relativePath,
|
|
6755
7132
|
source_location: locationStr(node),
|
|
6756
7133
|
language: "typescript",
|
|
6757
|
-
exported
|
|
7134
|
+
exported,
|
|
7135
|
+
signature: signatureOf(node, kind)
|
|
6758
7136
|
};
|
|
6759
7137
|
}
|
|
7138
|
+
function signatureOf(node, kind) {
|
|
7139
|
+
const text = node.text;
|
|
7140
|
+
let end = text.length;
|
|
7141
|
+
const nl = text.indexOf("\n");
|
|
7142
|
+
if (nl >= 0)
|
|
7143
|
+
end = Math.min(end, nl);
|
|
7144
|
+
const cutsAtBody = kind === "function" || kind === "class" || kind === "method" || kind === "interface" || kind === "enum";
|
|
7145
|
+
if (cutsAtBody) {
|
|
7146
|
+
const body = node.childForFieldName("body");
|
|
7147
|
+
if (body !== null) {
|
|
7148
|
+
end = Math.min(end, body.startIndex - node.startIndex);
|
|
7149
|
+
} else {
|
|
7150
|
+
const brace = text.indexOf("{");
|
|
7151
|
+
if (brace >= 0)
|
|
7152
|
+
end = Math.min(end, brace);
|
|
7153
|
+
}
|
|
7154
|
+
}
|
|
7155
|
+
const sig = text.slice(0, end).replace(/\s+/g, " ").trim();
|
|
7156
|
+
const cps = [...sig];
|
|
7157
|
+
return cps.length > 120 ? `${cps.slice(0, 117).join("")}...` : sig;
|
|
7158
|
+
}
|
|
6760
7159
|
function makeNodeWithExplicitLabel(relativePath, idName, label, kind, node, exported) {
|
|
6761
7160
|
return {
|
|
6762
7161
|
id: nodeId(relativePath, idName, kind),
|
|
@@ -6765,7 +7164,8 @@ function makeNodeWithExplicitLabel(relativePath, idName, label, kind, node, expo
|
|
|
6765
7164
|
source_file: relativePath,
|
|
6766
7165
|
source_location: locationStr(node),
|
|
6767
7166
|
language: "typescript",
|
|
6768
|
-
exported
|
|
7167
|
+
exported,
|
|
7168
|
+
signature: signatureOf(node, kind)
|
|
6769
7169
|
};
|
|
6770
7170
|
}
|
|
6771
7171
|
function pushNode(result, declByName, node, lookupKey) {
|
|
@@ -6805,9 +7205,433 @@ function firstNamedChildOfTypes(node, types) {
|
|
|
6805
7205
|
return null;
|
|
6806
7206
|
}
|
|
6807
7207
|
|
|
7208
|
+
// dist/src/graph/extract/python.js
|
|
7209
|
+
import Parser2 from "tree-sitter";
|
|
7210
|
+
import Python from "tree-sitter-python";
|
|
7211
|
+
var _pythonParser = null;
|
|
7212
|
+
function getPythonParser() {
|
|
7213
|
+
if (_pythonParser === null) {
|
|
7214
|
+
_pythonParser = new Parser2();
|
|
7215
|
+
_pythonParser.setLanguage(Python);
|
|
7216
|
+
}
|
|
7217
|
+
return _pythonParser;
|
|
7218
|
+
}
|
|
7219
|
+
var CHUNK_BYTES = 16384;
|
|
7220
|
+
function extractPython(sourceCode, relativePath) {
|
|
7221
|
+
const parser = getPythonParser();
|
|
7222
|
+
const tree = parser.parse((index) => index >= sourceCode.length ? null : sourceCode.slice(index, index + CHUNK_BYTES));
|
|
7223
|
+
const root = tree.rootNode;
|
|
7224
|
+
const result = {
|
|
7225
|
+
source_file: relativePath,
|
|
7226
|
+
language: "python",
|
|
7227
|
+
nodes: [],
|
|
7228
|
+
edges: [],
|
|
7229
|
+
parse_errors: [],
|
|
7230
|
+
raw_calls: [],
|
|
7231
|
+
import_bindings: []
|
|
7232
|
+
};
|
|
7233
|
+
collectParseErrors2(root, relativePath, result.parse_errors);
|
|
7234
|
+
const moduleNode = makeModuleNode2(relativePath);
|
|
7235
|
+
result.nodes.push(moduleNode);
|
|
7236
|
+
const declByName = /* @__PURE__ */ new Map();
|
|
7237
|
+
extractDeclarations2(
|
|
7238
|
+
root,
|
|
7239
|
+
relativePath,
|
|
7240
|
+
result,
|
|
7241
|
+
declByName,
|
|
7242
|
+
/*topLevel*/
|
|
7243
|
+
true
|
|
7244
|
+
);
|
|
7245
|
+
extractImports2(root, relativePath, result, moduleNode);
|
|
7246
|
+
extractCalls2(root, result, declByName);
|
|
7247
|
+
return result;
|
|
7248
|
+
}
|
|
7249
|
+
function collectParseErrors2(node, relativePath, out) {
|
|
7250
|
+
if (node.isError || node.isMissing) {
|
|
7251
|
+
out.push({ source_file: relativePath, message: node.isMissing ? `missing node: ${node.type}` : `parse error at ${loc(node)}`, location: loc(node) });
|
|
7252
|
+
return;
|
|
7253
|
+
}
|
|
7254
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7255
|
+
const c = node.namedChild(i);
|
|
7256
|
+
if (c !== null)
|
|
7257
|
+
collectParseErrors2(c, relativePath, out);
|
|
7258
|
+
}
|
|
7259
|
+
}
|
|
7260
|
+
function extractDeclarations2(node, relativePath, result, declByName, topLevel) {
|
|
7261
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7262
|
+
const child = node.namedChild(i);
|
|
7263
|
+
if (child === null)
|
|
7264
|
+
continue;
|
|
7265
|
+
if (child.type === "function_definition") {
|
|
7266
|
+
const name = textOfField2(child, "name");
|
|
7267
|
+
if (name !== null)
|
|
7268
|
+
pushNode2(result, declByName, makeNode2(relativePath, name, "function", child, isPublic(name)));
|
|
7269
|
+
} else if (child.type === "class_definition") {
|
|
7270
|
+
handleClass(child, relativePath, result, declByName);
|
|
7271
|
+
} else if (topLevel && child.type === "expression_statement") {
|
|
7272
|
+
const assign = firstOfType(child, "assignment");
|
|
7273
|
+
if (assign !== null) {
|
|
7274
|
+
const lhs = assign.childForFieldName("left");
|
|
7275
|
+
if (lhs !== null && lhs.type === "identifier") {
|
|
7276
|
+
pushNode2(result, declByName, makeNode2(relativePath, lhs.text, "const", assign, isPublic(lhs.text)));
|
|
7277
|
+
}
|
|
7278
|
+
}
|
|
7279
|
+
} else if (child.type === "decorated_definition") {
|
|
7280
|
+
extractDeclarations2(child, relativePath, result, declByName, topLevel);
|
|
7281
|
+
}
|
|
7282
|
+
}
|
|
7283
|
+
}
|
|
7284
|
+
function handleClass(node, relativePath, result, declByName) {
|
|
7285
|
+
const name = textOfField2(node, "name");
|
|
7286
|
+
if (name === null)
|
|
7287
|
+
return;
|
|
7288
|
+
const classNode = makeNode2(relativePath, name, "class", node, isPublic(name));
|
|
7289
|
+
pushNode2(result, declByName, classNode);
|
|
7290
|
+
const supers = node.childForFieldName("superclasses");
|
|
7291
|
+
if (supers !== null) {
|
|
7292
|
+
for (let i = 0; i < supers.namedChildCount; i++) {
|
|
7293
|
+
const base = supers.namedChild(i);
|
|
7294
|
+
if (base === null)
|
|
7295
|
+
continue;
|
|
7296
|
+
let baseName = null;
|
|
7297
|
+
if (base.type === "identifier")
|
|
7298
|
+
baseName = base.text;
|
|
7299
|
+
else if (base.type === "attribute") {
|
|
7300
|
+
const attr = base.childForFieldName("attribute");
|
|
7301
|
+
baseName = attr !== null ? attr.text : null;
|
|
7302
|
+
}
|
|
7303
|
+
if (baseName === null || baseName.length === 0)
|
|
7304
|
+
continue;
|
|
7305
|
+
result.edges.push({
|
|
7306
|
+
source: classNode.id,
|
|
7307
|
+
target: nodeIdUnresolved2(relativePath, baseName, "class"),
|
|
7308
|
+
relation: "extends",
|
|
7309
|
+
confidence: "EXTRACTED"
|
|
7310
|
+
});
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7313
|
+
const body = node.childForFieldName("body");
|
|
7314
|
+
if (body !== null) {
|
|
7315
|
+
for (let i = 0; i < body.namedChildCount; i++) {
|
|
7316
|
+
let member = body.namedChild(i);
|
|
7317
|
+
if (member === null)
|
|
7318
|
+
continue;
|
|
7319
|
+
if (member.type === "decorated_definition")
|
|
7320
|
+
member = firstOfType(member, "function_definition");
|
|
7321
|
+
if (member === null || member.type !== "function_definition")
|
|
7322
|
+
continue;
|
|
7323
|
+
const mName = textOfField2(member, "name");
|
|
7324
|
+
if (mName === null)
|
|
7325
|
+
continue;
|
|
7326
|
+
const methodNode = makeNodeWithExplicitLabel2(relativePath, `${name}.${mName}`, mName, "method", member, isPublic(name) && isPublic(mName));
|
|
7327
|
+
pushNode2(result, declByName, methodNode);
|
|
7328
|
+
result.edges.push({ source: classNode.id, target: methodNode.id, relation: "method_of", confidence: "EXTRACTED" });
|
|
7329
|
+
}
|
|
7330
|
+
}
|
|
7331
|
+
}
|
|
7332
|
+
function extractImports2(node, relativePath, result, moduleNode) {
|
|
7333
|
+
if (node.type === "import_statement") {
|
|
7334
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7335
|
+
const child = node.namedChild(i);
|
|
7336
|
+
if (child === null)
|
|
7337
|
+
continue;
|
|
7338
|
+
let modText = null;
|
|
7339
|
+
let local = null;
|
|
7340
|
+
if (child.type === "dotted_name") {
|
|
7341
|
+
modText = child.text;
|
|
7342
|
+
local = lastDottedSegment(child.text);
|
|
7343
|
+
} else if (child.type === "aliased_import") {
|
|
7344
|
+
const name = child.childForFieldName("name");
|
|
7345
|
+
const alias = child.childForFieldName("alias");
|
|
7346
|
+
if (name !== null) {
|
|
7347
|
+
modText = name.text;
|
|
7348
|
+
local = alias !== null ? alias.text : lastDottedSegment(name.text);
|
|
7349
|
+
}
|
|
7350
|
+
}
|
|
7351
|
+
if (modText !== null) {
|
|
7352
|
+
pushImportEdge(result, moduleNode, modText);
|
|
7353
|
+
if (local !== null)
|
|
7354
|
+
result.import_bindings.push({ local_name: local, imported_name: "*", kind: "namespace", specifier: modText });
|
|
7355
|
+
}
|
|
7356
|
+
}
|
|
7357
|
+
return;
|
|
7358
|
+
}
|
|
7359
|
+
if (node.type === "import_from_statement") {
|
|
7360
|
+
const modNode = node.childForFieldName("module_name");
|
|
7361
|
+
const modText = modNode !== null ? modNode.text : ".";
|
|
7362
|
+
pushImportEdge(result, moduleNode, modText);
|
|
7363
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7364
|
+
const child = node.namedChild(i);
|
|
7365
|
+
if (child === null || child === modNode)
|
|
7366
|
+
continue;
|
|
7367
|
+
if (child.type === "dotted_name" || child.type === "identifier") {
|
|
7368
|
+
const imported = child.text;
|
|
7369
|
+
result.import_bindings.push({ local_name: lastDottedSegment(imported), imported_name: imported, kind: "named", specifier: modText });
|
|
7370
|
+
} else if (child.type === "aliased_import") {
|
|
7371
|
+
const name = child.childForFieldName("name");
|
|
7372
|
+
const alias = child.childForFieldName("alias");
|
|
7373
|
+
if (name !== null)
|
|
7374
|
+
result.import_bindings.push({ local_name: alias !== null ? alias.text : lastDottedSegment(name.text), imported_name: name.text, kind: "named", specifier: modText });
|
|
7375
|
+
}
|
|
7376
|
+
}
|
|
7377
|
+
return;
|
|
7378
|
+
}
|
|
7379
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7380
|
+
const c = node.namedChild(i);
|
|
7381
|
+
if (c !== null)
|
|
7382
|
+
extractImports2(c, relativePath, result, moduleNode);
|
|
7383
|
+
}
|
|
7384
|
+
}
|
|
7385
|
+
function pushImportEdge(result, moduleNode, specifier) {
|
|
7386
|
+
if (specifier.length === 0)
|
|
7387
|
+
return;
|
|
7388
|
+
result.edges.push({ source: moduleNode.id, target: `external:${specifier}`, relation: "imports", confidence: "EXTRACTED" });
|
|
7389
|
+
}
|
|
7390
|
+
function extractCalls2(node, result, declByName) {
|
|
7391
|
+
if (node.type === "call") {
|
|
7392
|
+
const callee = node.childForFieldName("function");
|
|
7393
|
+
if (callee !== null) {
|
|
7394
|
+
const caller = findEnclosingDeclaration2(node, declByName);
|
|
7395
|
+
if (caller !== null) {
|
|
7396
|
+
const key = resolveCalleeKey2(callee);
|
|
7397
|
+
const target = key !== null ? declByName.get(key) : void 0;
|
|
7398
|
+
if (target !== void 0) {
|
|
7399
|
+
result.edges.push({ source: caller.id, target: target.id, relation: "calls", confidence: "EXTRACTED" });
|
|
7400
|
+
} else {
|
|
7401
|
+
const rc = rawCallFromCallee2(callee, caller.id);
|
|
7402
|
+
if (rc !== null)
|
|
7403
|
+
result.raw_calls.push(rc);
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
7406
|
+
}
|
|
7407
|
+
}
|
|
7408
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7409
|
+
const c = node.namedChild(i);
|
|
7410
|
+
if (c !== null)
|
|
7411
|
+
extractCalls2(c, result, declByName);
|
|
7412
|
+
}
|
|
7413
|
+
}
|
|
7414
|
+
function resolveCalleeKey2(callee) {
|
|
7415
|
+
if (callee.type === "identifier")
|
|
7416
|
+
return callee.text;
|
|
7417
|
+
if (callee.type === "attribute") {
|
|
7418
|
+
const obj = callee.childForFieldName("object");
|
|
7419
|
+
const attr = callee.childForFieldName("attribute");
|
|
7420
|
+
if (obj !== null && obj.type === "identifier" && obj.text === "self" && attr !== null) {
|
|
7421
|
+
const cls = findEnclosingClassName2(callee);
|
|
7422
|
+
if (cls !== null)
|
|
7423
|
+
return `${cls}.${attr.text}`;
|
|
7424
|
+
}
|
|
7425
|
+
}
|
|
7426
|
+
return null;
|
|
7427
|
+
}
|
|
7428
|
+
function rawCallFromCallee2(callee, callerId) {
|
|
7429
|
+
if (callee.type === "identifier")
|
|
7430
|
+
return { caller_id: callerId, callee_name: callee.text };
|
|
7431
|
+
if (callee.type === "attribute") {
|
|
7432
|
+
const obj = callee.childForFieldName("object");
|
|
7433
|
+
const attr = callee.childForFieldName("attribute");
|
|
7434
|
+
if (obj !== null && obj.type === "identifier" && obj.text !== "self" && attr !== null) {
|
|
7435
|
+
return { caller_id: callerId, callee_name: attr.text, receiver: obj.text };
|
|
7436
|
+
}
|
|
7437
|
+
}
|
|
7438
|
+
return null;
|
|
7439
|
+
}
|
|
7440
|
+
function findEnclosingDeclaration2(node, declByName) {
|
|
7441
|
+
let cur = node.parent;
|
|
7442
|
+
while (cur !== null) {
|
|
7443
|
+
if (cur.type === "function_definition") {
|
|
7444
|
+
const name = textOfField2(cur, "name");
|
|
7445
|
+
const cls = findEnclosingClassName2(cur);
|
|
7446
|
+
if (name !== null) {
|
|
7447
|
+
const n = cls !== null ? declByName.get(`${cls}.${name}`) : declByName.get(name);
|
|
7448
|
+
if (n !== void 0)
|
|
7449
|
+
return n;
|
|
7450
|
+
}
|
|
7451
|
+
}
|
|
7452
|
+
cur = cur.parent;
|
|
7453
|
+
}
|
|
7454
|
+
return null;
|
|
7455
|
+
}
|
|
7456
|
+
function findEnclosingClassName2(node) {
|
|
7457
|
+
let cur = node.parent;
|
|
7458
|
+
while (cur !== null) {
|
|
7459
|
+
if (cur.type === "class_definition")
|
|
7460
|
+
return textOfField2(cur, "name");
|
|
7461
|
+
cur = cur.parent;
|
|
7462
|
+
}
|
|
7463
|
+
return null;
|
|
7464
|
+
}
|
|
7465
|
+
function makeNode2(relativePath, name, kind, node, exported) {
|
|
7466
|
+
return { id: nodeId2(relativePath, name, kind), label: name, kind, source_file: relativePath, source_location: loc(node), language: "python", exported, signature: signatureOf2(node, kind) };
|
|
7467
|
+
}
|
|
7468
|
+
function makeNodeWithExplicitLabel2(relativePath, idName, label, kind, node, exported) {
|
|
7469
|
+
return { id: nodeId2(relativePath, idName, kind), label, kind, source_file: relativePath, source_location: loc(node), language: "python", exported, signature: signatureOf2(node, kind) };
|
|
7470
|
+
}
|
|
7471
|
+
function makeModuleNode2(relativePath) {
|
|
7472
|
+
return { id: `${relativePath}::module`, label: relativePath, kind: "module", source_file: relativePath, source_location: "L1", language: "python", exported: false };
|
|
7473
|
+
}
|
|
7474
|
+
function pushNode2(result, declByName, node) {
|
|
7475
|
+
result.nodes.push(node);
|
|
7476
|
+
const key = node.kind === "method" ? node.id.split(":")[1] : node.label;
|
|
7477
|
+
if (!declByName.has(key))
|
|
7478
|
+
declByName.set(key, node);
|
|
7479
|
+
}
|
|
7480
|
+
function signatureOf2(node, kind) {
|
|
7481
|
+
const text = node.text;
|
|
7482
|
+
let end = text.length;
|
|
7483
|
+
const nl = text.indexOf("\n");
|
|
7484
|
+
if (nl >= 0)
|
|
7485
|
+
end = Math.min(end, nl);
|
|
7486
|
+
if (kind === "function" || kind === "method" || kind === "class") {
|
|
7487
|
+
const body = node.childForFieldName("body");
|
|
7488
|
+
if (body !== null)
|
|
7489
|
+
end = Math.min(end, body.startIndex - node.startIndex);
|
|
7490
|
+
}
|
|
7491
|
+
const sig = text.slice(0, end).replace(/\s+/g, " ").replace(/:\s*$/, "").trim();
|
|
7492
|
+
const cps = [...sig];
|
|
7493
|
+
return cps.length > 120 ? `${cps.slice(0, 117).join("")}...` : sig;
|
|
7494
|
+
}
|
|
7495
|
+
function nodeId2(relativePath, name, kind) {
|
|
7496
|
+
return `${relativePath}:${name}:${kind}`;
|
|
7497
|
+
}
|
|
7498
|
+
function nodeIdUnresolved2(relativePath, name, kind) {
|
|
7499
|
+
return `unresolved:${relativePath}:${name}:${kind}`;
|
|
7500
|
+
}
|
|
7501
|
+
function loc(node) {
|
|
7502
|
+
const start = node.startPosition.row + 1;
|
|
7503
|
+
const end = node.endPosition.row + 1;
|
|
7504
|
+
return end > start ? `L${start}-${end}` : `L${start}`;
|
|
7505
|
+
}
|
|
7506
|
+
function textOfField2(node, field) {
|
|
7507
|
+
const f = node.childForFieldName(field);
|
|
7508
|
+
return f !== null ? f.text : null;
|
|
7509
|
+
}
|
|
7510
|
+
function firstOfType(node, type2) {
|
|
7511
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
7512
|
+
const c = node.namedChild(i);
|
|
7513
|
+
if (c !== null && c.type === type2)
|
|
7514
|
+
return c;
|
|
7515
|
+
}
|
|
7516
|
+
return null;
|
|
7517
|
+
}
|
|
7518
|
+
function lastDottedSegment(dotted) {
|
|
7519
|
+
const parts = dotted.split(".");
|
|
7520
|
+
return parts[parts.length - 1] ?? dotted;
|
|
7521
|
+
}
|
|
7522
|
+
function isPublic(name) {
|
|
7523
|
+
return !name.startsWith("_");
|
|
7524
|
+
}
|
|
7525
|
+
|
|
7526
|
+
// dist/src/graph/extract/index.js
|
|
7527
|
+
function isPythonPath(relativePath) {
|
|
7528
|
+
return /\.pyi?$/.test(relativePath);
|
|
7529
|
+
}
|
|
7530
|
+
function extractFile(sourceCode, relativePath) {
|
|
7531
|
+
if (isPythonPath(relativePath))
|
|
7532
|
+
return extractPython(sourceCode, relativePath);
|
|
7533
|
+
return extractTypeScript(sourceCode, relativePath);
|
|
7534
|
+
}
|
|
7535
|
+
|
|
7536
|
+
// dist/src/graph/ignore-config.js
|
|
7537
|
+
import { mkdirSync as mkdirSync12, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "node:fs";
|
|
7538
|
+
import { homedir as homedir11 } from "node:os";
|
|
7539
|
+
import { join as join26 } from "node:path";
|
|
7540
|
+
var DEFAULT_IGNORE_DIRS = [
|
|
7541
|
+
// JS / TS toolchains
|
|
7542
|
+
"node_modules",
|
|
7543
|
+
"bower_components",
|
|
7544
|
+
"jspm_packages",
|
|
7545
|
+
".pnpm-store",
|
|
7546
|
+
"dist",
|
|
7547
|
+
"build",
|
|
7548
|
+
"out",
|
|
7549
|
+
"coverage",
|
|
7550
|
+
"bundle",
|
|
7551
|
+
".next",
|
|
7552
|
+
".nuxt",
|
|
7553
|
+
".svelte-kit",
|
|
7554
|
+
".turbo",
|
|
7555
|
+
".parcel-cache",
|
|
7556
|
+
".cache",
|
|
7557
|
+
".vite",
|
|
7558
|
+
".nyc_output",
|
|
7559
|
+
// Python
|
|
7560
|
+
"venv",
|
|
7561
|
+
".venv",
|
|
7562
|
+
"env",
|
|
7563
|
+
".env",
|
|
7564
|
+
"virtualenv",
|
|
7565
|
+
"__pycache__",
|
|
7566
|
+
"site-packages",
|
|
7567
|
+
"__pypackages__",
|
|
7568
|
+
".pytest_cache",
|
|
7569
|
+
".mypy_cache",
|
|
7570
|
+
".ruff_cache",
|
|
7571
|
+
".tox",
|
|
7572
|
+
".eggs",
|
|
7573
|
+
".ipynb_checkpoints",
|
|
7574
|
+
".hypothesis",
|
|
7575
|
+
// Rust / Java / .NET / Go vendoring
|
|
7576
|
+
"target",
|
|
7577
|
+
"obj",
|
|
7578
|
+
"vendor",
|
|
7579
|
+
".gradle",
|
|
7580
|
+
".mvn",
|
|
7581
|
+
// Native / mobile
|
|
7582
|
+
"Pods",
|
|
7583
|
+
"DerivedData",
|
|
7584
|
+
".build",
|
|
7585
|
+
// VCS / IDE
|
|
7586
|
+
".git",
|
|
7587
|
+
".svn",
|
|
7588
|
+
".hg",
|
|
7589
|
+
".idea",
|
|
7590
|
+
".vscode",
|
|
7591
|
+
".vs",
|
|
7592
|
+
// Infra / misc
|
|
7593
|
+
".terraform",
|
|
7594
|
+
"tmp",
|
|
7595
|
+
"temp",
|
|
7596
|
+
"logs",
|
|
7597
|
+
"third_party",
|
|
7598
|
+
"third-party"
|
|
7599
|
+
];
|
|
7600
|
+
var FILE_NAME = "graph-ignore.json";
|
|
7601
|
+
function defaultConfigObject() {
|
|
7602
|
+
return {
|
|
7603
|
+
_comment: "Directory names skipped when building the hivemind code graph. Edit freely. When respectGitignore is true, the repo's .gitignore is also honored (anchoring-correct).",
|
|
7604
|
+
ignoreDirs: [...DEFAULT_IGNORE_DIRS],
|
|
7605
|
+
respectGitignore: true
|
|
7606
|
+
};
|
|
7607
|
+
}
|
|
7608
|
+
function loadGraphIgnore(deeplakeDir = join26(homedir11(), ".deeplake")) {
|
|
7609
|
+
const path = join26(deeplakeDir, FILE_NAME);
|
|
7610
|
+
try {
|
|
7611
|
+
const parsed = JSON.parse(readFileSync19(path, "utf8"));
|
|
7612
|
+
const ignoreDirs = Array.isArray(parsed.ignoreDirs) ? parsed.ignoreDirs.filter((s) => typeof s === "string") : [...DEFAULT_IGNORE_DIRS];
|
|
7613
|
+
const respectGitignore = typeof parsed.respectGitignore === "boolean" ? parsed.respectGitignore : true;
|
|
7614
|
+
return { ignoreDirs, respectGitignore };
|
|
7615
|
+
} catch {
|
|
7616
|
+
}
|
|
7617
|
+
try {
|
|
7618
|
+
mkdirSync12(deeplakeDir, { recursive: true });
|
|
7619
|
+
writeFileSync16(path, JSON.stringify(defaultConfigObject(), null, 2) + "\n", { flag: "wx" });
|
|
7620
|
+
} catch {
|
|
7621
|
+
}
|
|
7622
|
+
return { ignoreDirs: [...DEFAULT_IGNORE_DIRS], respectGitignore: true };
|
|
7623
|
+
}
|
|
7624
|
+
function ignoreDirSet(config) {
|
|
7625
|
+
return new Set(config.ignoreDirs);
|
|
7626
|
+
}
|
|
7627
|
+
function pathHasIgnoredSegment(relPath, ignore) {
|
|
7628
|
+
const segs = relPath.split("/");
|
|
7629
|
+
return segs.some((seg, i) => ignore.has(seg) || i < segs.length - 1 && seg.startsWith("."));
|
|
7630
|
+
}
|
|
7631
|
+
|
|
6808
7632
|
// dist/src/graph/git-hook-install.js
|
|
6809
|
-
import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as
|
|
6810
|
-
import { dirname as dirname8, join as
|
|
7633
|
+
import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync13, readFileSync as readFileSync20, unlinkSync as unlinkSync8, writeFileSync as writeFileSync17 } from "node:fs";
|
|
7634
|
+
import { dirname as dirname8, join as join27, resolve as resolve3 } from "node:path";
|
|
6811
7635
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
6812
7636
|
var HOOK_BEGIN_MARKER = "# HIVEMIND_GRAPH_HOOK_BEGIN \u2014 managed by `hivemind graph init`";
|
|
6813
7637
|
var HOOK_END_MARKER = "# HIVEMIND_GRAPH_HOOK_END";
|
|
@@ -6870,7 +7694,7 @@ function tryGitTopLevel(cwd) {
|
|
|
6870
7694
|
}
|
|
6871
7695
|
function postCommitHookPath(cwd) {
|
|
6872
7696
|
const hooksDir = gitHooksDir(cwd);
|
|
6873
|
-
return hooksDir === null ? null :
|
|
7697
|
+
return hooksDir === null ? null : join27(hooksDir, "post-commit");
|
|
6874
7698
|
}
|
|
6875
7699
|
function installPostCommitHook(cwd, opts = {}) {
|
|
6876
7700
|
const path = postCommitHookPath(cwd);
|
|
@@ -6879,7 +7703,7 @@ function installPostCommitHook(cwd, opts = {}) {
|
|
|
6879
7703
|
}
|
|
6880
7704
|
const existed = existsSync20(path);
|
|
6881
7705
|
if (existed) {
|
|
6882
|
-
const content =
|
|
7706
|
+
const content = readFileSync20(path, "utf8");
|
|
6883
7707
|
if (containsOurMarkers(content)) {
|
|
6884
7708
|
return { kind: "already-ours", path };
|
|
6885
7709
|
}
|
|
@@ -6899,8 +7723,8 @@ function installPostCommitHook(cwd, opts = {}) {
|
|
|
6899
7723
|
hint: "hivemind binary not found on PATH. Install hivemind globally (`npm install -g @deeplake/hivemind`) before running `hivemind graph init`, so the hook can find a stable absolute path to call."
|
|
6900
7724
|
};
|
|
6901
7725
|
}
|
|
6902
|
-
|
|
6903
|
-
|
|
7726
|
+
mkdirSync13(dirname8(path), { recursive: true });
|
|
7727
|
+
writeFileSync17(path, buildHookFile(hivemindPath), { mode: 493 });
|
|
6904
7728
|
try {
|
|
6905
7729
|
chmodSync2(path, 493);
|
|
6906
7730
|
} catch {
|
|
@@ -6927,7 +7751,7 @@ function uninstallPostCommitHook(cwd) {
|
|
|
6927
7751
|
if (!existsSync20(path)) {
|
|
6928
7752
|
return { kind: "no-hook", path };
|
|
6929
7753
|
}
|
|
6930
|
-
const content =
|
|
7754
|
+
const content = readFileSync20(path, "utf8");
|
|
6931
7755
|
if (!containsOurMarkers(content)) {
|
|
6932
7756
|
return {
|
|
6933
7757
|
kind: "not-ours",
|
|
@@ -6941,7 +7765,7 @@ function uninstallPostCommitHook(cwd) {
|
|
|
6941
7765
|
unlinkSync8(path);
|
|
6942
7766
|
return { kind: "removed", path, wholeFileDeleted: true };
|
|
6943
7767
|
}
|
|
6944
|
-
|
|
7768
|
+
writeFileSync17(path, stripped);
|
|
6945
7769
|
return { kind: "removed", path, wholeFileDeleted: false };
|
|
6946
7770
|
}
|
|
6947
7771
|
function containsOurMarkers(content) {
|
|
@@ -6967,11 +7791,11 @@ function buildHookFile(hivemindPath) {
|
|
|
6967
7791
|
}
|
|
6968
7792
|
|
|
6969
7793
|
// dist/src/commands/graph.js
|
|
6970
|
-
var USAGE = `hivemind graph \u2014 codebase-graph commands (
|
|
7794
|
+
var USAGE = `hivemind graph \u2014 codebase-graph commands (TypeScript / JavaScript / Python)
|
|
6971
7795
|
|
|
6972
7796
|
Usage:
|
|
6973
7797
|
hivemind graph build [--cwd <path>]
|
|
6974
|
-
Walk the project for
|
|
7798
|
+
Walk the project for supported source files (TS/JS/Python), extract symbols + edges,
|
|
6975
7799
|
and write a snapshot to ~/.hivemind/graphs/<repo-key>/snapshots/<commit-sha>.json.
|
|
6976
7800
|
Also updates ~/.hivemind/graphs/<repo-key>/latest-commit.txt and the
|
|
6977
7801
|
per-repo .last-build.json (consumed by the SessionEnd auto-build hook).
|
|
@@ -7015,15 +7839,6 @@ Usage:
|
|
|
7015
7839
|
|
|
7016
7840
|
Future subcommands (Phase 1.5+): daemon, search, latest, push, pull, prune.
|
|
7017
7841
|
`;
|
|
7018
|
-
var DEFAULT_IGNORES = /* @__PURE__ */ new Set([
|
|
7019
|
-
"node_modules",
|
|
7020
|
-
".git",
|
|
7021
|
-
"bundle",
|
|
7022
|
-
"dist",
|
|
7023
|
-
"coverage",
|
|
7024
|
-
".cache",
|
|
7025
|
-
".nyc_output"
|
|
7026
|
-
]);
|
|
7027
7842
|
function runGraphCommand(args) {
|
|
7028
7843
|
const sub = args[0];
|
|
7029
7844
|
if (sub === void 0 || sub === "--help" || sub === "-h" || sub === "help") {
|
|
@@ -7299,8 +8114,9 @@ async function runBuildCommand(args) {
|
|
|
7299
8114
|
console.log(` branch: ${branch ?? "(none / detached)"}`);
|
|
7300
8115
|
console.log(` output: ${baseDir}`);
|
|
7301
8116
|
console.log("");
|
|
7302
|
-
const
|
|
7303
|
-
|
|
8117
|
+
const ignoreConfig = loadGraphIgnore();
|
|
8118
|
+
const sourceFiles = discoverSourceFiles(cwd, ignoreConfig);
|
|
8119
|
+
console.log(`Discovered ${sourceFiles.length} source files. Extracting...`);
|
|
7304
8120
|
const extractions = [];
|
|
7305
8121
|
let skipped = 0;
|
|
7306
8122
|
let totalParseErrors = 0;
|
|
@@ -7308,11 +8124,11 @@ async function runBuildCommand(args) {
|
|
|
7308
8124
|
for (const abs of sourceFiles) {
|
|
7309
8125
|
const rel = toForwardSlash(relative(cwd, abs));
|
|
7310
8126
|
try {
|
|
7311
|
-
const content =
|
|
8127
|
+
const content = readFileSync21(abs, "utf8");
|
|
7312
8128
|
const contentSha = fileContentHash(content);
|
|
7313
8129
|
let extraction = readCache(baseDir, contentSha, rel);
|
|
7314
8130
|
if (extraction === null) {
|
|
7315
|
-
extraction =
|
|
8131
|
+
extraction = extractFile(content, rel);
|
|
7316
8132
|
writeCache(baseDir, contentSha, extraction);
|
|
7317
8133
|
} else {
|
|
7318
8134
|
cacheHits += 1;
|
|
@@ -7447,13 +8263,44 @@ async function runPullCommand(args) {
|
|
|
7447
8263
|
function workTreeIdFor2(cwd) {
|
|
7448
8264
|
return createHash6("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
7449
8265
|
}
|
|
7450
|
-
function discoverSourceFiles(rootDir) {
|
|
8266
|
+
function discoverSourceFiles(rootDir, config) {
|
|
8267
|
+
const ignore = ignoreDirSet(config);
|
|
8268
|
+
if (config.respectGitignore) {
|
|
8269
|
+
const fromGit = gitListSourceFiles(rootDir, ignore);
|
|
8270
|
+
if (fromGit !== null)
|
|
8271
|
+
return fromGit;
|
|
8272
|
+
}
|
|
8273
|
+
const out = [];
|
|
8274
|
+
walk(rootDir, out, ignore);
|
|
8275
|
+
out.sort();
|
|
8276
|
+
return out;
|
|
8277
|
+
}
|
|
8278
|
+
function gitListSourceFiles(rootDir, ignore) {
|
|
8279
|
+
let stdout;
|
|
8280
|
+
try {
|
|
8281
|
+
stdout = execSync3("git ls-files --cached --others --exclude-standard -z", {
|
|
8282
|
+
cwd: rootDir,
|
|
8283
|
+
encoding: "utf8",
|
|
8284
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
8285
|
+
maxBuffer: 64 * 1024 * 1024
|
|
8286
|
+
});
|
|
8287
|
+
} catch {
|
|
8288
|
+
return null;
|
|
8289
|
+
}
|
|
7451
8290
|
const out = [];
|
|
7452
|
-
|
|
8291
|
+
for (const rel of stdout.split("\0")) {
|
|
8292
|
+
if (rel.length === 0)
|
|
8293
|
+
continue;
|
|
8294
|
+
if (!isSourceFile(rel))
|
|
8295
|
+
continue;
|
|
8296
|
+
if (pathHasIgnoredSegment(rel, ignore))
|
|
8297
|
+
continue;
|
|
8298
|
+
out.push(join28(rootDir, rel));
|
|
8299
|
+
}
|
|
7453
8300
|
out.sort();
|
|
7454
8301
|
return out;
|
|
7455
8302
|
}
|
|
7456
|
-
function walk(dir, out) {
|
|
8303
|
+
function walk(dir, out, ignore) {
|
|
7457
8304
|
let entries;
|
|
7458
8305
|
try {
|
|
7459
8306
|
entries = readdirSync2(dir, { withFileTypes: true });
|
|
@@ -7461,13 +8308,13 @@ function walk(dir, out) {
|
|
|
7461
8308
|
return;
|
|
7462
8309
|
}
|
|
7463
8310
|
for (const entry of entries) {
|
|
7464
|
-
if (
|
|
8311
|
+
if (ignore.has(entry.name))
|
|
7465
8312
|
continue;
|
|
7466
8313
|
if (entry.name.startsWith("."))
|
|
7467
8314
|
continue;
|
|
7468
|
-
const abs =
|
|
8315
|
+
const abs = join28(dir, entry.name);
|
|
7469
8316
|
if (entry.isDirectory()) {
|
|
7470
|
-
walk(abs, out);
|
|
8317
|
+
walk(abs, out, ignore);
|
|
7471
8318
|
} else if (entry.isFile() && isSourceFile(entry.name)) {
|
|
7472
8319
|
out.push(abs);
|
|
7473
8320
|
}
|
|
@@ -7476,7 +8323,7 @@ function walk(dir, out) {
|
|
|
7476
8323
|
function isSourceFile(name) {
|
|
7477
8324
|
if (name.endsWith(".d.ts"))
|
|
7478
8325
|
return false;
|
|
7479
|
-
return
|
|
8326
|
+
return /\.(tsx?|jsx?|mjs|cjs|pyi?)$/.test(name);
|
|
7480
8327
|
}
|
|
7481
8328
|
function toForwardSlash(p) {
|
|
7482
8329
|
return sep === "\\" ? p.replace(/\\/g, "/") : p;
|
|
@@ -7506,25 +8353,25 @@ function readGitBranch(cwd) {
|
|
|
7506
8353
|
}
|
|
7507
8354
|
|
|
7508
8355
|
// dist/src/commands/dashboard.js
|
|
7509
|
-
import { mkdirSync as
|
|
7510
|
-
import { homedir as
|
|
7511
|
-
import { dirname as dirname12, join as
|
|
8356
|
+
import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync20 } from "node:fs";
|
|
8357
|
+
import { homedir as homedir16 } from "node:os";
|
|
8358
|
+
import { dirname as dirname12, join as join36, resolve as resolve5 } from "node:path";
|
|
7512
8359
|
|
|
7513
8360
|
// dist/src/dashboard/data.js
|
|
7514
|
-
import { existsSync as existsSync25, readFileSync as
|
|
7515
|
-
import { homedir as
|
|
7516
|
-
import { join as
|
|
8361
|
+
import { existsSync as existsSync25, readFileSync as readFileSync25, readdirSync as readdirSync4, statSync as statSync3 } from "node:fs";
|
|
8362
|
+
import { homedir as homedir15 } from "node:os";
|
|
8363
|
+
import { join as join34 } from "node:path";
|
|
7517
8364
|
|
|
7518
8365
|
// dist/src/notifications/sources/org-stats.js
|
|
7519
|
-
import { existsSync as existsSync21, mkdirSync as
|
|
7520
|
-
import { homedir as
|
|
7521
|
-
import { dirname as dirname9, join as
|
|
8366
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync14, readFileSync as readFileSync22, writeFileSync as writeFileSync18 } from "node:fs";
|
|
8367
|
+
import { homedir as homedir12 } from "node:os";
|
|
8368
|
+
import { dirname as dirname9, join as join29 } from "node:path";
|
|
7522
8369
|
var log5 = (msg) => log2("notifications-org-stats", msg);
|
|
7523
8370
|
var FETCH_TIMEOUT_MS = 1500;
|
|
7524
8371
|
var DEFAULT_API_URL3 = "https://api.deeplake.ai";
|
|
7525
8372
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
7526
8373
|
function cacheFilePath() {
|
|
7527
|
-
return
|
|
8374
|
+
return join29(homedir12(), ".deeplake", "hivemind-stats-cache.json");
|
|
7528
8375
|
}
|
|
7529
8376
|
var BALANCE_HEADER = "X-Activeloop-Balance-Cents";
|
|
7530
8377
|
function parseBalanceHeader(resp) {
|
|
@@ -7553,7 +8400,7 @@ function readCache2(scopeKey) {
|
|
|
7553
8400
|
if (!existsSync21(cacheFilePath()))
|
|
7554
8401
|
return {};
|
|
7555
8402
|
try {
|
|
7556
|
-
const parsed = JSON.parse(
|
|
8403
|
+
const parsed = JSON.parse(readFileSync22(cacheFilePath(), "utf-8"));
|
|
7557
8404
|
if (!parsed || typeof parsed !== "object")
|
|
7558
8405
|
return {};
|
|
7559
8406
|
if (parsed.scopeKey !== scopeKey)
|
|
@@ -7574,9 +8421,9 @@ function readCache2(scopeKey) {
|
|
|
7574
8421
|
}
|
|
7575
8422
|
function writeCache2(scopeKey, data) {
|
|
7576
8423
|
try {
|
|
7577
|
-
|
|
8424
|
+
mkdirSync14(dirname9(cacheFilePath()), { recursive: true });
|
|
7578
8425
|
const body = { fetchedAt: Date.now(), scopeKey, data };
|
|
7579
|
-
|
|
8426
|
+
writeFileSync18(cacheFilePath(), JSON.stringify(body), "utf-8");
|
|
7580
8427
|
} catch (e) {
|
|
7581
8428
|
log5(`cache write failed: ${e?.message ?? String(e)}`);
|
|
7582
8429
|
}
|
|
@@ -7628,18 +8475,18 @@ async function fetchOrgStats(creds) {
|
|
|
7628
8475
|
}
|
|
7629
8476
|
|
|
7630
8477
|
// dist/src/notifications/usage-tracker.js
|
|
7631
|
-
import { appendFileSync as appendFileSync3, existsSync as existsSync22, mkdirSync as
|
|
7632
|
-
import { dirname as dirname10, join as
|
|
7633
|
-
import { homedir as
|
|
8478
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync22, mkdirSync as mkdirSync15, readFileSync as readFileSync23, readdirSync as readdirSync3 } from "node:fs";
|
|
8479
|
+
import { dirname as dirname10, join as join30 } from "node:path";
|
|
8480
|
+
import { homedir as homedir13 } from "node:os";
|
|
7634
8481
|
var log6 = (msg) => log2("usage-tracker", msg);
|
|
7635
8482
|
function statsFilePath() {
|
|
7636
|
-
return
|
|
8483
|
+
return join30(homedir13(), ".deeplake", "usage-stats.jsonl");
|
|
7637
8484
|
}
|
|
7638
8485
|
function readUsageRecords() {
|
|
7639
8486
|
try {
|
|
7640
8487
|
if (!existsSync22(statsFilePath()))
|
|
7641
8488
|
return [];
|
|
7642
|
-
const raw =
|
|
8489
|
+
const raw = readFileSync23(statsFilePath(), "utf-8");
|
|
7643
8490
|
const out = [];
|
|
7644
8491
|
for (const line of raw.split("\n")) {
|
|
7645
8492
|
const trimmed = line.trim();
|
|
@@ -7676,7 +8523,7 @@ function sumMetric(records, key) {
|
|
|
7676
8523
|
function countUserGeneratedSkills(userName) {
|
|
7677
8524
|
if (!userName)
|
|
7678
8525
|
return 0;
|
|
7679
|
-
const dir =
|
|
8526
|
+
const dir = join30(homedir13(), ".claude", "skills");
|
|
7680
8527
|
if (!existsSync22(dir))
|
|
7681
8528
|
return 0;
|
|
7682
8529
|
const suffix = `--${userName}`;
|
|
@@ -7695,19 +8542,19 @@ function countUserGeneratedSkills(userName) {
|
|
|
7695
8542
|
}
|
|
7696
8543
|
|
|
7697
8544
|
// dist/src/skillify/state.js
|
|
7698
|
-
import { readFileSync as
|
|
7699
|
-
import { join as
|
|
8545
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync19, writeSync, mkdirSync as mkdirSync16, renameSync as renameSync9, rmdirSync, existsSync as existsSync24, lstatSync as lstatSync3, unlinkSync as unlinkSync9, openSync as openSync2, closeSync as closeSync2 } from "node:fs";
|
|
8546
|
+
import { join as join33 } from "node:path";
|
|
7700
8547
|
|
|
7701
8548
|
// dist/src/skillify/legacy-migration.js
|
|
7702
8549
|
import { existsSync as existsSync23, renameSync as renameSync8 } from "node:fs";
|
|
7703
|
-
import { dirname as dirname11, join as
|
|
8550
|
+
import { dirname as dirname11, join as join32 } from "node:path";
|
|
7704
8551
|
|
|
7705
8552
|
// dist/src/skillify/state-dir.js
|
|
7706
|
-
import { homedir as
|
|
7707
|
-
import { join as
|
|
8553
|
+
import { homedir as homedir14 } from "node:os";
|
|
8554
|
+
import { join as join31 } from "node:path";
|
|
7708
8555
|
function getStateDir() {
|
|
7709
8556
|
const override = process.env.HIVEMIND_STATE_DIR?.trim();
|
|
7710
|
-
return override && override.length > 0 ? override :
|
|
8557
|
+
return override && override.length > 0 ? override : join31(homedir14(), ".deeplake", "state", "skillify");
|
|
7711
8558
|
}
|
|
7712
8559
|
|
|
7713
8560
|
// dist/src/skillify/legacy-migration.js
|
|
@@ -7720,7 +8567,7 @@ function migrateLegacyStateDir() {
|
|
|
7720
8567
|
return;
|
|
7721
8568
|
attempted = true;
|
|
7722
8569
|
const current = getStateDir();
|
|
7723
|
-
const legacy =
|
|
8570
|
+
const legacy = join32(dirname11(current), "skilify");
|
|
7724
8571
|
if (!existsSync23(legacy))
|
|
7725
8572
|
return;
|
|
7726
8573
|
if (existsSync23(current))
|
|
@@ -7750,7 +8597,7 @@ var log7 = (msg) => log2("dashboard-data", msg);
|
|
|
7750
8597
|
var BYTES_PER_TOKEN = 4;
|
|
7751
8598
|
var SAVINGS_MULTIPLIER = 1.7;
|
|
7752
8599
|
function graphsRoot2() {
|
|
7753
|
-
return process.env.HIVEMIND_GRAPHS_HOME ??
|
|
8600
|
+
return process.env.HIVEMIND_GRAPHS_HOME ?? join34(homedir15(), ".hivemind", "graphs");
|
|
7754
8601
|
}
|
|
7755
8602
|
function bytesToSavedTokens(bytes) {
|
|
7756
8603
|
if (!Number.isFinite(bytes) || bytes <= 0)
|
|
@@ -7759,16 +8606,16 @@ function bytesToSavedTokens(bytes) {
|
|
|
7759
8606
|
return (SAVINGS_MULTIPLIER - 1) * delivered;
|
|
7760
8607
|
}
|
|
7761
8608
|
function resolveSnapshot(repoDir2) {
|
|
7762
|
-
const snapshotsDir =
|
|
8609
|
+
const snapshotsDir = join34(repoDir2, "snapshots");
|
|
7763
8610
|
if (!existsSync25(snapshotsDir))
|
|
7764
8611
|
return null;
|
|
7765
8612
|
let snapshotPath = null;
|
|
7766
|
-
const pointer =
|
|
8613
|
+
const pointer = join34(repoDir2, "latest-commit.txt");
|
|
7767
8614
|
if (existsSync25(pointer)) {
|
|
7768
8615
|
try {
|
|
7769
|
-
const sha =
|
|
8616
|
+
const sha = readFileSync25(pointer, "utf-8").trim();
|
|
7770
8617
|
if (sha) {
|
|
7771
|
-
const candidate =
|
|
8618
|
+
const candidate = join34(snapshotsDir, `${sha}.json`);
|
|
7772
8619
|
if (existsSync25(candidate))
|
|
7773
8620
|
snapshotPath = candidate;
|
|
7774
8621
|
else
|
|
@@ -7781,7 +8628,7 @@ function resolveSnapshot(repoDir2) {
|
|
|
7781
8628
|
if (!snapshotPath) {
|
|
7782
8629
|
try {
|
|
7783
8630
|
const candidates = readdirSync4(snapshotsDir).filter((name) => name.endsWith(".json")).map((name) => {
|
|
7784
|
-
const full =
|
|
8631
|
+
const full = join34(snapshotsDir, name);
|
|
7785
8632
|
return { full, mtime: statSync3(full).mtimeMs };
|
|
7786
8633
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
7787
8634
|
if (candidates.length > 0)
|
|
@@ -7794,7 +8641,7 @@ function resolveSnapshot(repoDir2) {
|
|
|
7794
8641
|
return null;
|
|
7795
8642
|
let raw;
|
|
7796
8643
|
try {
|
|
7797
|
-
raw =
|
|
8644
|
+
raw = readFileSync25(snapshotPath, "utf-8");
|
|
7798
8645
|
} catch (e) {
|
|
7799
8646
|
log7(`snapshot read failed: ${e?.message ?? String(e)}`);
|
|
7800
8647
|
return null;
|
|
@@ -7864,7 +8711,7 @@ async function loadKpis(creds) {
|
|
|
7864
8711
|
async function loadDashboardData(opts = {}) {
|
|
7865
8712
|
const cwd = opts.cwd ?? process.cwd();
|
|
7866
8713
|
const { key: repoKey, project: repoProject } = deriveProjectKey(cwd);
|
|
7867
|
-
const repoDir2 =
|
|
8714
|
+
const repoDir2 = join34(opts.graphsHome ?? graphsRoot2(), repoKey);
|
|
7868
8715
|
const graph = resolveSnapshot(repoDir2);
|
|
7869
8716
|
const creds = opts.creds === void 0 ? loadCredentials() : opts.creds;
|
|
7870
8717
|
const kpis = await loadKpis(creds);
|
|
@@ -7881,7 +8728,7 @@ async function loadDashboardData(opts = {}) {
|
|
|
7881
8728
|
import { spawn } from "node:child_process";
|
|
7882
8729
|
import { accessSync, constants as fsConstants, statSync as statSync4 } from "node:fs";
|
|
7883
8730
|
import { platform as nodePlatform } from "node:os";
|
|
7884
|
-
import { delimiter, join as
|
|
8731
|
+
import { delimiter, join as join35 } from "node:path";
|
|
7885
8732
|
function resolveOpenPlatform() {
|
|
7886
8733
|
const p = nodePlatform();
|
|
7887
8734
|
if (p === "linux" || p === "darwin" || p === "win32")
|
|
@@ -7908,7 +8755,7 @@ function findBinaryOnPath(name) {
|
|
|
7908
8755
|
if (!dir)
|
|
7909
8756
|
continue;
|
|
7910
8757
|
for (const ext of exts) {
|
|
7911
|
-
const candidate =
|
|
8758
|
+
const candidate = join35(dir, name + ext);
|
|
7912
8759
|
try {
|
|
7913
8760
|
const st = statSync4(candidate);
|
|
7914
8761
|
if (!st.isFile())
|
|
@@ -8000,8 +8847,8 @@ function transformSnapshotToVis(snapshot) {
|
|
|
8000
8847
|
if (kind)
|
|
8001
8848
|
titleParts.push(kind);
|
|
8002
8849
|
if (sourceFile) {
|
|
8003
|
-
const
|
|
8004
|
-
titleParts.push(
|
|
8850
|
+
const loc2 = sourceLoc ? `${sourceFile}:${sourceLoc}` : sourceFile;
|
|
8851
|
+
titleParts.push(loc2);
|
|
8005
8852
|
}
|
|
8006
8853
|
const color = kind && KIND_COLORS[kind] ? KIND_COLORS[kind] : DEFAULT_NODE_COLOR;
|
|
8007
8854
|
visNodes.push({
|
|
@@ -8418,7 +9265,7 @@ function parseDashboardArgs(args) {
|
|
|
8418
9265
|
};
|
|
8419
9266
|
}
|
|
8420
9267
|
function defaultDashboardOutPath(repoKey) {
|
|
8421
|
-
return
|
|
9268
|
+
return join36(homedir16(), ".hivemind", "dashboards", repoKey, "index.html");
|
|
8422
9269
|
}
|
|
8423
9270
|
async function runDashboardCommand(rawArgs, runOpts = {}) {
|
|
8424
9271
|
const out = runOpts.out ?? ((s) => {
|
|
@@ -8452,8 +9299,8 @@ async function runDashboardCommand(rawArgs, runOpts = {}) {
|
|
|
8452
9299
|
const finalOut = outPath || defaultDashboardOutPath(data.repoKey);
|
|
8453
9300
|
const absOut = resolve5(finalOut);
|
|
8454
9301
|
try {
|
|
8455
|
-
|
|
8456
|
-
|
|
9302
|
+
mkdirSync17(dirname12(absOut), { recursive: true });
|
|
9303
|
+
writeFileSync20(absOut, html, "utf-8");
|
|
8457
9304
|
} catch (e) {
|
|
8458
9305
|
err(`hivemind dashboard: failed to write ${absOut}: ${e?.message ?? String(e)}
|
|
8459
9306
|
`);
|
|
@@ -8532,15 +9379,15 @@ function defaultOnSignal(signal, handler) {
|
|
|
8532
9379
|
}
|
|
8533
9380
|
|
|
8534
9381
|
// dist/src/commands/skillify.js
|
|
8535
|
-
import { readdirSync as readdirSync8, existsSync as existsSync36, readFileSync as
|
|
8536
|
-
import { homedir as
|
|
8537
|
-
import { dirname as dirname17, join as
|
|
9382
|
+
import { readdirSync as readdirSync8, existsSync as existsSync36, readFileSync as readFileSync33, mkdirSync as mkdirSync24, renameSync as renameSync12 } from "node:fs";
|
|
9383
|
+
import { homedir as homedir25 } from "node:os";
|
|
9384
|
+
import { dirname as dirname17, join as join47 } from "node:path";
|
|
8538
9385
|
|
|
8539
9386
|
// dist/src/skillify/scope-config.js
|
|
8540
|
-
import { existsSync as existsSync26, mkdirSync as
|
|
8541
|
-
import { join as
|
|
9387
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync18, readFileSync as readFileSync26, writeFileSync as writeFileSync21 } from "node:fs";
|
|
9388
|
+
import { join as join37 } from "node:path";
|
|
8542
9389
|
function configPath() {
|
|
8543
|
-
return
|
|
9390
|
+
return join37(getStateDir(), "config.json");
|
|
8544
9391
|
}
|
|
8545
9392
|
var DEFAULT = { scope: "me", team: [], install: "project" };
|
|
8546
9393
|
function loadScopeConfig() {
|
|
@@ -8549,7 +9396,7 @@ function loadScopeConfig() {
|
|
|
8549
9396
|
if (!existsSync26(CONFIG_PATH2))
|
|
8550
9397
|
return DEFAULT;
|
|
8551
9398
|
try {
|
|
8552
|
-
const raw = JSON.parse(
|
|
9399
|
+
const raw = JSON.parse(readFileSync26(CONFIG_PATH2, "utf-8"));
|
|
8553
9400
|
const scope = raw.scope === "team" ? "team" : raw.scope === "org" ? "team" : "me";
|
|
8554
9401
|
const team = Array.isArray(raw.team) ? raw.team.filter((s) => typeof s === "string") : [];
|
|
8555
9402
|
const install = raw.install === "global" ? "global" : "project";
|
|
@@ -8560,19 +9407,19 @@ function loadScopeConfig() {
|
|
|
8560
9407
|
}
|
|
8561
9408
|
function saveScopeConfig(cfg) {
|
|
8562
9409
|
migrateLegacyStateDir();
|
|
8563
|
-
|
|
8564
|
-
|
|
9410
|
+
mkdirSync18(getStateDir(), { recursive: true });
|
|
9411
|
+
writeFileSync21(configPath(), JSON.stringify(cfg, null, 2));
|
|
8565
9412
|
}
|
|
8566
9413
|
|
|
8567
9414
|
// dist/src/skillify/pull.js
|
|
8568
|
-
import { existsSync as existsSync30, readFileSync as
|
|
8569
|
-
import { homedir as
|
|
8570
|
-
import { dirname as dirname14, join as
|
|
9415
|
+
import { existsSync as existsSync30, readFileSync as readFileSync29, writeFileSync as writeFileSync24, mkdirSync as mkdirSync21, renameSync as renameSync11, lstatSync as lstatSync5, readlinkSync as readlinkSync2, symlinkSync as symlinkSync2, unlinkSync as unlinkSync11 } from "node:fs";
|
|
9416
|
+
import { homedir as homedir19 } from "node:os";
|
|
9417
|
+
import { dirname as dirname14, join as join41 } from "node:path";
|
|
8571
9418
|
|
|
8572
9419
|
// dist/src/skillify/skill-writer.js
|
|
8573
|
-
import { existsSync as existsSync27, mkdirSync as
|
|
8574
|
-
import { homedir as
|
|
8575
|
-
import { join as
|
|
9420
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync19, readFileSync as readFileSync27, readdirSync as readdirSync5, statSync as statSync5, writeFileSync as writeFileSync22 } from "node:fs";
|
|
9421
|
+
import { homedir as homedir17 } from "node:os";
|
|
9422
|
+
import { join as join38 } from "node:path";
|
|
8576
9423
|
function assertValidSkillName(name) {
|
|
8577
9424
|
if (typeof name !== "string" || name.length === 0) {
|
|
8578
9425
|
throw new Error(`invalid skill name: empty or non-string`);
|
|
@@ -8588,10 +9435,10 @@ function assertValidSkillName(name) {
|
|
|
8588
9435
|
}
|
|
8589
9436
|
}
|
|
8590
9437
|
function skillDir(skillsRoot, name) {
|
|
8591
|
-
return
|
|
9438
|
+
return join38(skillsRoot, name);
|
|
8592
9439
|
}
|
|
8593
9440
|
function skillPath(skillsRoot, name) {
|
|
8594
|
-
return
|
|
9441
|
+
return join38(skillDir(skillsRoot, name), "SKILL.md");
|
|
8595
9442
|
}
|
|
8596
9443
|
function renderFrontmatter(fm) {
|
|
8597
9444
|
const lines = ["---"];
|
|
@@ -8672,7 +9519,7 @@ function writeNewSkill(args) {
|
|
|
8672
9519
|
if (existsSync27(path)) {
|
|
8673
9520
|
throw new Error(`skill already exists at ${path}; use mergeSkill`);
|
|
8674
9521
|
}
|
|
8675
|
-
|
|
9522
|
+
mkdirSync19(dir, { recursive: true });
|
|
8676
9523
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
8677
9524
|
const author = args.author && args.author.length > 0 ? args.author : void 0;
|
|
8678
9525
|
const contributors = author ? [author] : [];
|
|
@@ -8692,7 +9539,7 @@ function writeNewSkill(args) {
|
|
|
8692
9539
|
|
|
8693
9540
|
${args.body.trim()}
|
|
8694
9541
|
`;
|
|
8695
|
-
|
|
9542
|
+
writeFileSync22(path, text);
|
|
8696
9543
|
return {
|
|
8697
9544
|
path,
|
|
8698
9545
|
action: "created",
|
|
@@ -8708,28 +9555,28 @@ function listSkills(skillsRoot) {
|
|
|
8708
9555
|
return [];
|
|
8709
9556
|
const out = [];
|
|
8710
9557
|
for (const name of readdirSync5(skillsRoot)) {
|
|
8711
|
-
const skillFile =
|
|
9558
|
+
const skillFile = join38(skillsRoot, name, "SKILL.md");
|
|
8712
9559
|
if (existsSync27(skillFile) && statSync5(skillFile).isFile()) {
|
|
8713
|
-
out.push({ name, body:
|
|
9560
|
+
out.push({ name, body: readFileSync27(skillFile, "utf-8") });
|
|
8714
9561
|
}
|
|
8715
9562
|
}
|
|
8716
9563
|
return out;
|
|
8717
9564
|
}
|
|
8718
9565
|
function resolveSkillsRoot(install, cwd) {
|
|
8719
9566
|
if (install === "global") {
|
|
8720
|
-
return
|
|
9567
|
+
return join38(homedir17(), ".claude", "skills");
|
|
8721
9568
|
}
|
|
8722
|
-
return
|
|
9569
|
+
return join38(cwd, ".claude", "skills");
|
|
8723
9570
|
}
|
|
8724
9571
|
|
|
8725
9572
|
// dist/src/skillify/manifest.js
|
|
8726
|
-
import { existsSync as existsSync28, lstatSync as lstatSync4, mkdirSync as
|
|
8727
|
-
import { dirname as dirname13, join as
|
|
9573
|
+
import { existsSync as existsSync28, lstatSync as lstatSync4, mkdirSync as mkdirSync20, readFileSync as readFileSync28, renameSync as renameSync10, unlinkSync as unlinkSync10, writeFileSync as writeFileSync23 } from "node:fs";
|
|
9574
|
+
import { dirname as dirname13, join as join39 } from "node:path";
|
|
8728
9575
|
function emptyManifest() {
|
|
8729
9576
|
return { version: 1, entries: [] };
|
|
8730
9577
|
}
|
|
8731
9578
|
function manifestPath() {
|
|
8732
|
-
return
|
|
9579
|
+
return join39(getStateDir(), "pulled.json");
|
|
8733
9580
|
}
|
|
8734
9581
|
function loadManifest(path = manifestPath()) {
|
|
8735
9582
|
migrateLegacyStateDir();
|
|
@@ -8737,7 +9584,7 @@ function loadManifest(path = manifestPath()) {
|
|
|
8737
9584
|
return emptyManifest();
|
|
8738
9585
|
let raw;
|
|
8739
9586
|
try {
|
|
8740
|
-
raw =
|
|
9587
|
+
raw = readFileSync28(path, "utf-8");
|
|
8741
9588
|
} catch {
|
|
8742
9589
|
return emptyManifest();
|
|
8743
9590
|
}
|
|
@@ -8784,9 +9631,9 @@ function loadManifest(path = manifestPath()) {
|
|
|
8784
9631
|
}
|
|
8785
9632
|
function saveManifest(m, path = manifestPath()) {
|
|
8786
9633
|
migrateLegacyStateDir();
|
|
8787
|
-
|
|
9634
|
+
mkdirSync20(dirname13(path), { recursive: true });
|
|
8788
9635
|
const tmp = `${path}.tmp`;
|
|
8789
|
-
|
|
9636
|
+
writeFileSync23(tmp, JSON.stringify(m, null, 2) + "\n", { mode: 384 });
|
|
8790
9637
|
renameSync10(tmp, path);
|
|
8791
9638
|
}
|
|
8792
9639
|
function recordPull(entry, path = manifestPath()) {
|
|
@@ -8829,7 +9676,7 @@ function pruneOrphanedEntries(path = manifestPath()) {
|
|
|
8829
9676
|
const live = [];
|
|
8830
9677
|
let pruned = 0;
|
|
8831
9678
|
for (const e of m.entries) {
|
|
8832
|
-
if (existsSync28(
|
|
9679
|
+
if (existsSync28(join39(e.installRoot, e.dirName))) {
|
|
8833
9680
|
live.push(e);
|
|
8834
9681
|
continue;
|
|
8835
9682
|
}
|
|
@@ -8843,25 +9690,25 @@ function pruneOrphanedEntries(path = manifestPath()) {
|
|
|
8843
9690
|
|
|
8844
9691
|
// dist/src/skillify/agent-roots.js
|
|
8845
9692
|
import { existsSync as existsSync29 } from "node:fs";
|
|
8846
|
-
import { homedir as
|
|
8847
|
-
import { join as
|
|
9693
|
+
import { homedir as homedir18 } from "node:os";
|
|
9694
|
+
import { join as join40 } from "node:path";
|
|
8848
9695
|
function resolveDetected(home) {
|
|
8849
9696
|
const out = [];
|
|
8850
|
-
const codexInstalled = existsSync29(
|
|
8851
|
-
const piInstalled = existsSync29(
|
|
8852
|
-
const hermesInstalled = existsSync29(
|
|
9697
|
+
const codexInstalled = existsSync29(join40(home, ".codex"));
|
|
9698
|
+
const piInstalled = existsSync29(join40(home, ".pi", "agent"));
|
|
9699
|
+
const hermesInstalled = existsSync29(join40(home, ".hermes"));
|
|
8853
9700
|
if (codexInstalled || piInstalled) {
|
|
8854
|
-
out.push(
|
|
9701
|
+
out.push(join40(home, ".agents", "skills"));
|
|
8855
9702
|
}
|
|
8856
9703
|
if (hermesInstalled) {
|
|
8857
|
-
out.push(
|
|
9704
|
+
out.push(join40(home, ".hermes", "skills"));
|
|
8858
9705
|
}
|
|
8859
9706
|
if (piInstalled) {
|
|
8860
|
-
out.push(
|
|
9707
|
+
out.push(join40(home, ".pi", "agent", "skills"));
|
|
8861
9708
|
}
|
|
8862
9709
|
return out;
|
|
8863
9710
|
}
|
|
8864
|
-
function detectAgentSkillsRoots(canonicalRoot, home =
|
|
9711
|
+
function detectAgentSkillsRoots(canonicalRoot, home = homedir18()) {
|
|
8865
9712
|
return resolveDetected(home).filter((p) => p !== canonicalRoot);
|
|
8866
9713
|
}
|
|
8867
9714
|
|
|
@@ -8905,15 +9752,15 @@ function isMissingTableError2(message) {
|
|
|
8905
9752
|
}
|
|
8906
9753
|
function resolvePullDestination(install, cwd) {
|
|
8907
9754
|
if (install === "global")
|
|
8908
|
-
return
|
|
9755
|
+
return join41(homedir19(), ".claude", "skills");
|
|
8909
9756
|
if (!cwd)
|
|
8910
9757
|
throw new Error("install=project requires a cwd");
|
|
8911
|
-
return
|
|
9758
|
+
return join41(cwd, ".claude", "skills");
|
|
8912
9759
|
}
|
|
8913
9760
|
function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
8914
9761
|
const out = [];
|
|
8915
9762
|
for (const root of agentRoots) {
|
|
8916
|
-
const link =
|
|
9763
|
+
const link = join41(root, dirName);
|
|
8917
9764
|
let existing;
|
|
8918
9765
|
try {
|
|
8919
9766
|
existing = lstatSync5(link);
|
|
@@ -8941,7 +9788,7 @@ function fanOutSymlinks(canonicalDir, dirName, agentRoots) {
|
|
|
8941
9788
|
}
|
|
8942
9789
|
}
|
|
8943
9790
|
try {
|
|
8944
|
-
|
|
9791
|
+
mkdirSync21(dirname14(link), { recursive: true });
|
|
8945
9792
|
symlinkSync2(canonicalDir, link, "dir");
|
|
8946
9793
|
out.push(link);
|
|
8947
9794
|
} catch {
|
|
@@ -8956,7 +9803,7 @@ function backfillSymlinks(installRoot) {
|
|
|
8956
9803
|
return;
|
|
8957
9804
|
const detected = detectAgentSkillsRoots(installRoot);
|
|
8958
9805
|
for (const entry of entries) {
|
|
8959
|
-
const canonical =
|
|
9806
|
+
const canonical = join41(entry.installRoot, entry.dirName);
|
|
8960
9807
|
if (!existsSync30(canonical))
|
|
8961
9808
|
continue;
|
|
8962
9809
|
const fresh = fanOutSymlinks(canonical, entry.dirName, detected);
|
|
@@ -9070,7 +9917,7 @@ function readLocalVersion(path) {
|
|
|
9070
9917
|
if (!existsSync30(path))
|
|
9071
9918
|
return null;
|
|
9072
9919
|
try {
|
|
9073
|
-
const text =
|
|
9920
|
+
const text = readFileSync29(path, "utf-8");
|
|
9074
9921
|
const parsed = parseFrontmatter(text);
|
|
9075
9922
|
if (!parsed)
|
|
9076
9923
|
return null;
|
|
@@ -9169,8 +10016,8 @@ async function runPull(opts) {
|
|
|
9169
10016
|
summary.skipped++;
|
|
9170
10017
|
continue;
|
|
9171
10018
|
}
|
|
9172
|
-
const skillDir2 =
|
|
9173
|
-
const skillFile =
|
|
10019
|
+
const skillDir2 = join41(root, dirName);
|
|
10020
|
+
const skillFile = join41(skillDir2, "SKILL.md");
|
|
9174
10021
|
const remoteVersion = Number(row.version ?? 1);
|
|
9175
10022
|
const localVersion = readLocalVersion(skillFile);
|
|
9176
10023
|
const action = decideAction({
|
|
@@ -9181,14 +10028,14 @@ async function runPull(opts) {
|
|
|
9181
10028
|
});
|
|
9182
10029
|
let manifestError;
|
|
9183
10030
|
if (action === "wrote") {
|
|
9184
|
-
|
|
10031
|
+
mkdirSync21(skillDir2, { recursive: true });
|
|
9185
10032
|
if (existsSync30(skillFile)) {
|
|
9186
10033
|
try {
|
|
9187
10034
|
renameSync11(skillFile, `${skillFile}.bak`);
|
|
9188
10035
|
} catch {
|
|
9189
10036
|
}
|
|
9190
10037
|
}
|
|
9191
|
-
|
|
10038
|
+
writeFileSync24(skillFile, renderSkillFile(row));
|
|
9192
10039
|
const symlinks = opts.install === "global" ? fanOutSymlinks(skillDir2, dirName, detectAgentSkillsRoots(root)) : [];
|
|
9193
10040
|
try {
|
|
9194
10041
|
recordPull({
|
|
@@ -9231,14 +10078,14 @@ async function runPull(opts) {
|
|
|
9231
10078
|
|
|
9232
10079
|
// dist/src/skillify/unpull.js
|
|
9233
10080
|
import { existsSync as existsSync31, readdirSync as readdirSync6, rmSync as rmSync5, statSync as statSync6 } from "node:fs";
|
|
9234
|
-
import { homedir as
|
|
9235
|
-
import { join as
|
|
10081
|
+
import { homedir as homedir20 } from "node:os";
|
|
10082
|
+
import { join as join42 } from "node:path";
|
|
9236
10083
|
function resolveUnpullRoot(install, cwd) {
|
|
9237
10084
|
if (install === "global")
|
|
9238
|
-
return
|
|
10085
|
+
return join42(homedir20(), ".claude", "skills");
|
|
9239
10086
|
if (!cwd)
|
|
9240
10087
|
throw new Error("cwd required when install === 'project'");
|
|
9241
|
-
return
|
|
10088
|
+
return join42(cwd, ".claude", "skills");
|
|
9242
10089
|
}
|
|
9243
10090
|
function runUnpull(opts) {
|
|
9244
10091
|
const root = resolveUnpullRoot(opts.install, opts.cwd);
|
|
@@ -9261,7 +10108,7 @@ function runUnpull(opts) {
|
|
|
9261
10108
|
const entries = entriesForRoot(manifest, opts.install, root);
|
|
9262
10109
|
for (const entry of entries) {
|
|
9263
10110
|
summary.scanned++;
|
|
9264
|
-
const path =
|
|
10111
|
+
const path = join42(root, entry.dirName);
|
|
9265
10112
|
if (!existsSync31(path)) {
|
|
9266
10113
|
if (!opts.dryRun) {
|
|
9267
10114
|
unlinkSymlinks(entry.symlinks);
|
|
@@ -9320,7 +10167,7 @@ function runUnpull(opts) {
|
|
|
9320
10167
|
for (const dirName of readdirSync6(root)) {
|
|
9321
10168
|
if (manifestDirNames.has(dirName))
|
|
9322
10169
|
continue;
|
|
9323
|
-
const path =
|
|
10170
|
+
const path = join42(root, dirName);
|
|
9324
10171
|
let st;
|
|
9325
10172
|
try {
|
|
9326
10173
|
st = statSync6(path);
|
|
@@ -9399,21 +10246,21 @@ function decideTargetForManifestEntry(entry, opts, userFilter, haveUserFilter) {
|
|
|
9399
10246
|
|
|
9400
10247
|
// dist/src/commands/mine-local.js
|
|
9401
10248
|
import { spawn as spawn2 } from "node:child_process";
|
|
9402
|
-
import { existsSync as existsSync35, mkdirSync as
|
|
9403
|
-
import { homedir as
|
|
9404
|
-
import { basename as basename2, dirname as dirname16, join as
|
|
10249
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync23, readFileSync as readFileSync32, writeFileSync as writeFileSync26 } from "node:fs";
|
|
10250
|
+
import { homedir as homedir24 } from "node:os";
|
|
10251
|
+
import { basename as basename2, dirname as dirname16, join as join46 } from "node:path";
|
|
9405
10252
|
|
|
9406
10253
|
// dist/src/skillify/local-source.js
|
|
9407
|
-
import { readdirSync as readdirSync7, readFileSync as
|
|
9408
|
-
import { homedir as
|
|
9409
|
-
import { join as
|
|
9410
|
-
var HOME2 =
|
|
10254
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync30, existsSync as existsSync32, statSync as statSync7 } from "node:fs";
|
|
10255
|
+
import { homedir as homedir21 } from "node:os";
|
|
10256
|
+
import { join as join43 } from "node:path";
|
|
10257
|
+
var HOME2 = homedir21();
|
|
9411
10258
|
function encodeCwdClaudeCode(cwd) {
|
|
9412
10259
|
return cwd.replace(/[/_]/g, "-");
|
|
9413
10260
|
}
|
|
9414
10261
|
function detectInstalledAgents() {
|
|
9415
10262
|
const installs = [];
|
|
9416
|
-
const claudeRoot =
|
|
10263
|
+
const claudeRoot = join43(HOME2, ".claude", "projects");
|
|
9417
10264
|
if (existsSync32(claudeRoot)) {
|
|
9418
10265
|
installs.push({
|
|
9419
10266
|
agent: "claude_code",
|
|
@@ -9421,7 +10268,7 @@ function detectInstalledAgents() {
|
|
|
9421
10268
|
encodeCwd: encodeCwdClaudeCode
|
|
9422
10269
|
});
|
|
9423
10270
|
}
|
|
9424
|
-
const codexRoot =
|
|
10271
|
+
const codexRoot = join43(HOME2, ".codex", "sessions");
|
|
9425
10272
|
if (existsSync32(codexRoot)) {
|
|
9426
10273
|
installs.push({
|
|
9427
10274
|
agent: "codex",
|
|
@@ -9449,7 +10296,7 @@ function listLocalSessions(installs, cwd) {
|
|
|
9449
10296
|
continue;
|
|
9450
10297
|
}
|
|
9451
10298
|
for (const sub of subdirs) {
|
|
9452
|
-
const subdirPath =
|
|
10299
|
+
const subdirPath = join43(install.sessionRoot, sub);
|
|
9453
10300
|
try {
|
|
9454
10301
|
if (!statSync7(subdirPath).isDirectory())
|
|
9455
10302
|
continue;
|
|
@@ -9466,7 +10313,7 @@ function listLocalSessions(installs, cwd) {
|
|
|
9466
10313
|
for (const f of files) {
|
|
9467
10314
|
if (!f.endsWith(".jsonl"))
|
|
9468
10315
|
continue;
|
|
9469
|
-
const fullPath =
|
|
10316
|
+
const fullPath = join43(subdirPath, f);
|
|
9470
10317
|
let stats;
|
|
9471
10318
|
try {
|
|
9472
10319
|
stats = statSync7(fullPath);
|
|
@@ -9527,7 +10374,7 @@ function pickSessions(candidates, opts) {
|
|
|
9527
10374
|
function nativeJsonlToRows(filePath, sessionId, agent) {
|
|
9528
10375
|
let raw;
|
|
9529
10376
|
try {
|
|
9530
|
-
raw =
|
|
10377
|
+
raw = readFileSync30(filePath, "utf-8");
|
|
9531
10378
|
} catch {
|
|
9532
10379
|
return [];
|
|
9533
10380
|
}
|
|
@@ -9619,8 +10466,8 @@ function extractPairs(rows) {
|
|
|
9619
10466
|
// dist/src/skillify/gate-runner.js
|
|
9620
10467
|
import { existsSync as existsSync33 } from "node:fs";
|
|
9621
10468
|
import { createRequire } from "node:module";
|
|
9622
|
-
import { homedir as
|
|
9623
|
-
import { join as
|
|
10469
|
+
import { homedir as homedir22 } from "node:os";
|
|
10470
|
+
import { join as join44 } from "node:path";
|
|
9624
10471
|
var requireForCp = createRequire(import.meta.url);
|
|
9625
10472
|
var { execFileSync: runChildProcess } = requireForCp("node:child_process");
|
|
9626
10473
|
var inheritedEnv = process;
|
|
@@ -9632,7 +10479,7 @@ function firstExistingPath(candidates) {
|
|
|
9632
10479
|
return null;
|
|
9633
10480
|
}
|
|
9634
10481
|
function findAgentBin(agent) {
|
|
9635
|
-
const home =
|
|
10482
|
+
const home = homedir22();
|
|
9636
10483
|
switch (agent) {
|
|
9637
10484
|
// /usr/bin/<name> is included in every candidate list — that's the
|
|
9638
10485
|
// common Linux package-manager install path (apt, dnf, pacman). Old
|
|
@@ -9641,45 +10488,45 @@ function findAgentBin(agent) {
|
|
|
9641
10488
|
// #170 caught the gap.
|
|
9642
10489
|
case "claude_code":
|
|
9643
10490
|
return firstExistingPath([
|
|
9644
|
-
|
|
10491
|
+
join44(home, ".claude", "local", "claude"),
|
|
9645
10492
|
"/usr/local/bin/claude",
|
|
9646
10493
|
"/usr/bin/claude",
|
|
9647
|
-
|
|
9648
|
-
|
|
10494
|
+
join44(home, ".npm-global", "bin", "claude"),
|
|
10495
|
+
join44(home, ".local", "bin", "claude"),
|
|
9649
10496
|
"/opt/homebrew/bin/claude"
|
|
9650
|
-
]) ??
|
|
10497
|
+
]) ?? join44(home, ".claude", "local", "claude");
|
|
9651
10498
|
case "codex":
|
|
9652
10499
|
return firstExistingPath([
|
|
9653
10500
|
"/usr/local/bin/codex",
|
|
9654
10501
|
"/usr/bin/codex",
|
|
9655
|
-
|
|
9656
|
-
|
|
10502
|
+
join44(home, ".npm-global", "bin", "codex"),
|
|
10503
|
+
join44(home, ".local", "bin", "codex"),
|
|
9657
10504
|
"/opt/homebrew/bin/codex"
|
|
9658
10505
|
]) ?? "/usr/local/bin/codex";
|
|
9659
10506
|
case "cursor":
|
|
9660
10507
|
return firstExistingPath([
|
|
9661
10508
|
"/usr/local/bin/cursor-agent",
|
|
9662
10509
|
"/usr/bin/cursor-agent",
|
|
9663
|
-
|
|
9664
|
-
|
|
10510
|
+
join44(home, ".npm-global", "bin", "cursor-agent"),
|
|
10511
|
+
join44(home, ".local", "bin", "cursor-agent"),
|
|
9665
10512
|
"/opt/homebrew/bin/cursor-agent"
|
|
9666
10513
|
]) ?? "/usr/local/bin/cursor-agent";
|
|
9667
10514
|
case "hermes":
|
|
9668
10515
|
return firstExistingPath([
|
|
9669
|
-
|
|
10516
|
+
join44(home, ".local", "bin", "hermes"),
|
|
9670
10517
|
"/usr/local/bin/hermes",
|
|
9671
10518
|
"/usr/bin/hermes",
|
|
9672
|
-
|
|
10519
|
+
join44(home, ".npm-global", "bin", "hermes"),
|
|
9673
10520
|
"/opt/homebrew/bin/hermes"
|
|
9674
|
-
]) ??
|
|
10521
|
+
]) ?? join44(home, ".local", "bin", "hermes");
|
|
9675
10522
|
case "pi":
|
|
9676
10523
|
return firstExistingPath([
|
|
9677
|
-
|
|
10524
|
+
join44(home, ".local", "bin", "pi"),
|
|
9678
10525
|
"/usr/local/bin/pi",
|
|
9679
10526
|
"/usr/bin/pi",
|
|
9680
|
-
|
|
10527
|
+
join44(home, ".npm-global", "bin", "pi"),
|
|
9681
10528
|
"/opt/homebrew/bin/pi"
|
|
9682
|
-
]) ??
|
|
10529
|
+
]) ?? join44(home, ".local", "bin", "pi");
|
|
9683
10530
|
}
|
|
9684
10531
|
}
|
|
9685
10532
|
|
|
@@ -9709,23 +10556,23 @@ function extractJsonBlock(s) {
|
|
|
9709
10556
|
}
|
|
9710
10557
|
|
|
9711
10558
|
// dist/src/skillify/local-manifest.js
|
|
9712
|
-
import { existsSync as existsSync34, mkdirSync as
|
|
9713
|
-
import { homedir as
|
|
9714
|
-
import { dirname as dirname15, join as
|
|
9715
|
-
var LOCAL_MANIFEST_PATH =
|
|
9716
|
-
var LOCAL_MINE_LOCK_PATH =
|
|
10559
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync22, readFileSync as readFileSync31, writeFileSync as writeFileSync25 } from "node:fs";
|
|
10560
|
+
import { homedir as homedir23 } from "node:os";
|
|
10561
|
+
import { dirname as dirname15, join as join45 } from "node:path";
|
|
10562
|
+
var LOCAL_MANIFEST_PATH = join45(homedir23(), ".claude", "hivemind", "local-mined.json");
|
|
10563
|
+
var LOCAL_MINE_LOCK_PATH = join45(homedir23(), ".claude", "hivemind", "local-mined.lock");
|
|
9717
10564
|
function readLocalManifest(path = LOCAL_MANIFEST_PATH) {
|
|
9718
10565
|
if (!existsSync34(path))
|
|
9719
10566
|
return null;
|
|
9720
10567
|
try {
|
|
9721
|
-
return JSON.parse(
|
|
10568
|
+
return JSON.parse(readFileSync31(path, "utf-8"));
|
|
9722
10569
|
} catch {
|
|
9723
10570
|
return null;
|
|
9724
10571
|
}
|
|
9725
10572
|
}
|
|
9726
10573
|
function writeLocalManifest(m, path = LOCAL_MANIFEST_PATH) {
|
|
9727
|
-
|
|
9728
|
-
|
|
10574
|
+
mkdirSync22(dirname15(path), { recursive: true });
|
|
10575
|
+
writeFileSync25(path, JSON.stringify(m, null, 2));
|
|
9729
10576
|
}
|
|
9730
10577
|
function countLocalManifestEntries(path = LOCAL_MANIFEST_PATH) {
|
|
9731
10578
|
const m = readLocalManifest(path);
|
|
@@ -10159,8 +11006,8 @@ async function runMineLocalImpl(args) {
|
|
|
10159
11006
|
console.log(`Dry-run: would invoke ${gateAgent} gate on ${picked.length} session(s) in parallel (concurrency=${GATE_CONCURRENCY}).`);
|
|
10160
11007
|
return;
|
|
10161
11008
|
}
|
|
10162
|
-
const tmpDir =
|
|
10163
|
-
|
|
11009
|
+
const tmpDir = join46(homedir24(), ".claude", "hivemind", `mine-local-${Date.now()}`);
|
|
11010
|
+
mkdirSync23(tmpDir, { recursive: true });
|
|
10164
11011
|
console.log(`Running ${picked.length} gate call(s) in parallel (concurrency=${GATE_CONCURRENCY}, timeout=${GATE_TIMEOUT_MS / 1e3}s each)...`);
|
|
10165
11012
|
const results = await parallelMap(picked, GATE_CONCURRENCY, async (s) => {
|
|
10166
11013
|
const shortId = s.sessionId.slice(0, 8);
|
|
@@ -10171,23 +11018,23 @@ async function runMineLocalImpl(args) {
|
|
|
10171
11018
|
return { session: s, skills: [], reason: "no pairs", error: null };
|
|
10172
11019
|
}
|
|
10173
11020
|
const tail = pairs2.slice(-PER_SESSION_PAIR_CAP);
|
|
10174
|
-
const sessionTmp =
|
|
10175
|
-
|
|
10176
|
-
const verdictPath =
|
|
11021
|
+
const sessionTmp = join46(tmpDir, `s-${shortId}`);
|
|
11022
|
+
mkdirSync23(sessionTmp, { recursive: true });
|
|
11023
|
+
const verdictPath = join46(sessionTmp, "verdict.json");
|
|
10177
11024
|
const prompt = buildSessionPrompt(tail, s, verdictPath);
|
|
10178
|
-
|
|
11025
|
+
writeFileSync26(join46(sessionTmp, "prompt.txt"), prompt);
|
|
10179
11026
|
const gate = await runGateViaStdin({ agent: gateAgent, bin: gateBin, prompt, timeoutMs: GATE_TIMEOUT_MS });
|
|
10180
11027
|
try {
|
|
10181
|
-
|
|
11028
|
+
writeFileSync26(join46(sessionTmp, "gate-stdout.txt"), gate.stdout);
|
|
10182
11029
|
if (gate.stderr)
|
|
10183
|
-
|
|
11030
|
+
writeFileSync26(join46(sessionTmp, "gate-stderr.txt"), gate.stderr);
|
|
10184
11031
|
} catch {
|
|
10185
11032
|
}
|
|
10186
11033
|
if (gate.errored) {
|
|
10187
11034
|
console.log(` [${shortId}] gate failed: ${gate.errorMessage}`);
|
|
10188
11035
|
return { session: s, skills: [], reason: null, error: gate.errorMessage ?? "gate failed" };
|
|
10189
11036
|
}
|
|
10190
|
-
const verdictText = existsSync35(verdictPath) ?
|
|
11037
|
+
const verdictText = existsSync35(verdictPath) ? readFileSync32(verdictPath, "utf-8") : gate.stdout;
|
|
10191
11038
|
const mv = parseMultiVerdict(verdictText);
|
|
10192
11039
|
if (!mv) {
|
|
10193
11040
|
console.log(` [${shortId}] unparseable verdict (kept at ${sessionTmp})`);
|
|
@@ -10428,7 +11275,7 @@ function showStatus() {
|
|
|
10428
11275
|
console.log(`state: ${files.length} project(s) tracked`);
|
|
10429
11276
|
for (const f of files) {
|
|
10430
11277
|
try {
|
|
10431
|
-
const s = JSON.parse(
|
|
11278
|
+
const s = JSON.parse(readFileSync33(join47(dir, f), "utf-8"));
|
|
10432
11279
|
const last = typeof s.updatedAt === "number" ? new Date(s.updatedAt).toISOString() : s.lastDate ?? "never";
|
|
10433
11280
|
const skills = Array.isArray(s.skillsGenerated) && s.skillsGenerated.length > 0 ? s.skillsGenerated.join(", ") : "none";
|
|
10434
11281
|
console.log(` - ${s.project} (counter=${s.counter}, last=${last}, skills=${skills})`);
|
|
@@ -10448,32 +11295,32 @@ function setScope(scope) {
|
|
|
10448
11295
|
console.log(`Note: team list is empty. Use 'hivemind skillify team add <username>' to populate it.`);
|
|
10449
11296
|
}
|
|
10450
11297
|
}
|
|
10451
|
-
function setInstall(
|
|
10452
|
-
if (
|
|
10453
|
-
console.error(`Invalid install location '${
|
|
11298
|
+
function setInstall(loc2) {
|
|
11299
|
+
if (loc2 !== "project" && loc2 !== "global") {
|
|
11300
|
+
console.error(`Invalid install location '${loc2}'. Use one of: project, global`);
|
|
10454
11301
|
process.exit(1);
|
|
10455
11302
|
}
|
|
10456
11303
|
const cfg = loadScopeConfig();
|
|
10457
|
-
saveScopeConfig({ ...cfg, install:
|
|
10458
|
-
const path =
|
|
10459
|
-
console.log(`Install location set to '${
|
|
11304
|
+
saveScopeConfig({ ...cfg, install: loc2 });
|
|
11305
|
+
const path = loc2 === "global" ? join47(homedir25(), ".claude", "skills") : "<cwd>/.claude/skills";
|
|
11306
|
+
console.log(`Install location set to '${loc2}'. New skills will be written to ${path}/<name>/SKILL.md.`);
|
|
10460
11307
|
}
|
|
10461
11308
|
function promoteSkill(name, cwd) {
|
|
10462
11309
|
if (!name) {
|
|
10463
11310
|
console.error("Usage: hivemind skillify promote <skill-name>");
|
|
10464
11311
|
process.exit(1);
|
|
10465
11312
|
}
|
|
10466
|
-
const projectPath =
|
|
10467
|
-
const globalPath =
|
|
10468
|
-
if (!existsSync36(
|
|
11313
|
+
const projectPath = join47(cwd, ".claude", "skills", name);
|
|
11314
|
+
const globalPath = join47(homedir25(), ".claude", "skills", name);
|
|
11315
|
+
if (!existsSync36(join47(projectPath, "SKILL.md"))) {
|
|
10469
11316
|
console.error(`Skill '${name}' not found at ${projectPath}/SKILL.md`);
|
|
10470
11317
|
process.exit(1);
|
|
10471
11318
|
}
|
|
10472
|
-
if (existsSync36(
|
|
11319
|
+
if (existsSync36(join47(globalPath, "SKILL.md"))) {
|
|
10473
11320
|
console.error(`Skill '${name}' already exists at ${globalPath}/SKILL.md \u2014 refusing to overwrite. Remove it first or rename the project skill.`);
|
|
10474
11321
|
process.exit(1);
|
|
10475
11322
|
}
|
|
10476
|
-
|
|
11323
|
+
mkdirSync24(dirname17(globalPath), { recursive: true });
|
|
10477
11324
|
renameSync12(projectPath, globalPath);
|
|
10478
11325
|
console.log(`Promoted '${name}' from ${projectPath} \u2192 ${globalPath}.`);
|
|
10479
11326
|
}
|
|
@@ -10580,7 +11427,7 @@ async function pullSkills(args) {
|
|
|
10580
11427
|
console.error(`pull failed: ${e?.message ?? e}`);
|
|
10581
11428
|
process.exit(1);
|
|
10582
11429
|
}
|
|
10583
|
-
const dest = toRaw === "global" ?
|
|
11430
|
+
const dest = toRaw === "global" ? join47(homedir25(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
|
|
10584
11431
|
const filterDesc = users.length === 0 ? "all users" : users.join(", ");
|
|
10585
11432
|
console.log(`Destination: ${dest}`);
|
|
10586
11433
|
console.log(`Filter: ${filterDesc}${skillName ? ` \xB7 skill='${skillName}'` : ""}${dryRun ? " \xB7 dry-run" : ""}${force ? " \xB7 force" : ""}`);
|
|
@@ -10630,7 +11477,7 @@ async function unpullSkills(args) {
|
|
|
10630
11477
|
all,
|
|
10631
11478
|
legacyCleanup
|
|
10632
11479
|
});
|
|
10633
|
-
const dest = toRaw === "global" ?
|
|
11480
|
+
const dest = toRaw === "global" ? join47(homedir25(), ".claude", "skills") : `${process.cwd()}/.claude/skills`;
|
|
10634
11481
|
const filterParts = [];
|
|
10635
11482
|
if (users.length > 0)
|
|
10636
11483
|
filterParts.push(`users=${users.join(",")}`);
|
|
@@ -11498,14 +12345,14 @@ async function runContextCommand(args) {
|
|
|
11498
12345
|
|
|
11499
12346
|
// dist/src/cli/update.js
|
|
11500
12347
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
11501
|
-
import { closeSync as closeSync3, existsSync as existsSync37, mkdirSync as
|
|
11502
|
-
import { homedir as
|
|
11503
|
-
import { dirname as dirname19, join as
|
|
12348
|
+
import { closeSync as closeSync3, existsSync as existsSync37, mkdirSync as mkdirSync25, openSync as openSync3, readFileSync as readFileSync35, realpathSync, unlinkSync as unlinkSync13, writeSync as writeSync2 } from "node:fs";
|
|
12349
|
+
import { homedir as homedir26 } from "node:os";
|
|
12350
|
+
import { dirname as dirname19, join as join49, sep as sep2 } from "node:path";
|
|
11504
12351
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
11505
12352
|
|
|
11506
12353
|
// dist/src/utils/version-check.js
|
|
11507
|
-
import { readFileSync as
|
|
11508
|
-
import { dirname as dirname18, join as
|
|
12354
|
+
import { readFileSync as readFileSync34 } from "node:fs";
|
|
12355
|
+
import { dirname as dirname18, join as join48 } from "node:path";
|
|
11509
12356
|
function isNewer(latest, current) {
|
|
11510
12357
|
const parse = (v) => v.split(".").map(Number);
|
|
11511
12358
|
const [la, lb, lc] = parse(latest);
|
|
@@ -11517,7 +12364,7 @@ function isNewer(latest, current) {
|
|
|
11517
12364
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@deeplake/hivemind/latest";
|
|
11518
12365
|
var PKG_NAME = "@deeplake/hivemind";
|
|
11519
12366
|
function defaultLockPath() {
|
|
11520
|
-
return
|
|
12367
|
+
return join49(homedir26(), ".deeplake", "hivemind-update.lock");
|
|
11521
12368
|
}
|
|
11522
12369
|
function detectInstallKind(argv1) {
|
|
11523
12370
|
const realArgv1 = (() => {
|
|
@@ -11532,7 +12379,7 @@ function detectInstallKind(argv1) {
|
|
|
11532
12379
|
for (let i = 0; i < 10; i++) {
|
|
11533
12380
|
const pkgPath = `${dir}${sep2}package.json`;
|
|
11534
12381
|
try {
|
|
11535
|
-
const pkg = JSON.parse(
|
|
12382
|
+
const pkg = JSON.parse(readFileSync35(pkgPath, "utf-8"));
|
|
11536
12383
|
if (pkg.name === PKG_NAME || pkg.name === "hivemind") {
|
|
11537
12384
|
installDir = dir;
|
|
11538
12385
|
break;
|
|
@@ -11578,7 +12425,7 @@ var defaultSpawn = (cmd, args) => {
|
|
|
11578
12425
|
execFileSync6(cmd, args, { stdio: "inherit" });
|
|
11579
12426
|
};
|
|
11580
12427
|
function tryAcquireLock(path) {
|
|
11581
|
-
|
|
12428
|
+
mkdirSync25(dirname19(path), { recursive: true, mode: 448 });
|
|
11582
12429
|
const claim = () => {
|
|
11583
12430
|
const fd = openSync3(path, "wx", 384);
|
|
11584
12431
|
writeSync2(fd, String(process.pid));
|
|
@@ -11592,7 +12439,7 @@ function tryAcquireLock(path) {
|
|
|
11592
12439
|
}
|
|
11593
12440
|
let holderPid = 0;
|
|
11594
12441
|
try {
|
|
11595
|
-
holderPid = Number(
|
|
12442
|
+
holderPid = Number(readFileSync35(path, "utf-8").trim()) || 0;
|
|
11596
12443
|
} catch {
|
|
11597
12444
|
try {
|
|
11598
12445
|
return claim();
|
|
@@ -11720,9 +12567,9 @@ async function runUpdate(opts = {}) {
|
|
|
11720
12567
|
|
|
11721
12568
|
// dist/src/cli/install-scan.js
|
|
11722
12569
|
import { spawn as spawn4 } from "node:child_process";
|
|
11723
|
-
import { existsSync as existsSync39, readFileSync as
|
|
11724
|
-
import { homedir as
|
|
11725
|
-
import { join as
|
|
12570
|
+
import { existsSync as existsSync39, readFileSync as readFileSync36, readdirSync as readdirSync9, unlinkSync as unlinkSync14 } from "node:fs";
|
|
12571
|
+
import { homedir as homedir27 } from "node:os";
|
|
12572
|
+
import { join as join50 } from "node:path";
|
|
11726
12573
|
|
|
11727
12574
|
// dist/src/skillify/advisor.js
|
|
11728
12575
|
import { spawn as spawn3 } from "node:child_process";
|
|
@@ -11885,10 +12732,10 @@ async function runAdvisor(manifestPath3 = LOCAL_MANIFEST_PATH) {
|
|
|
11885
12732
|
|
|
11886
12733
|
// dist/src/cli/install-scan.js
|
|
11887
12734
|
function claudeProjectsDir() {
|
|
11888
|
-
return
|
|
12735
|
+
return join50(homedir27(), ".claude", "projects");
|
|
11889
12736
|
}
|
|
11890
12737
|
function manifestPath2() {
|
|
11891
|
-
return
|
|
12738
|
+
return join50(homedir27(), ".claude", "hivemind", "local-mined.json");
|
|
11892
12739
|
}
|
|
11893
12740
|
var SCAN_TIMEOUT_MS = 3e5;
|
|
11894
12741
|
var INSTALL_SCAN_SESSION_COUNT = 10;
|
|
@@ -11897,7 +12744,7 @@ function manifestIsTrulyEmpty() {
|
|
|
11897
12744
|
if (!existsSync39(p))
|
|
11898
12745
|
return false;
|
|
11899
12746
|
try {
|
|
11900
|
-
const m = JSON.parse(
|
|
12747
|
+
const m = JSON.parse(readFileSync36(p, "utf-8"));
|
|
11901
12748
|
return Array.isArray(m.entries) && m.entries.length === 0;
|
|
11902
12749
|
} catch {
|
|
11903
12750
|
return false;
|
|
@@ -11916,7 +12763,7 @@ function hasLocalClaudeSessions() {
|
|
|
11916
12763
|
for (const sub of subdirs) {
|
|
11917
12764
|
let files;
|
|
11918
12765
|
try {
|
|
11919
|
-
files = readdirSync9(
|
|
12766
|
+
files = readdirSync9(join50(projectsDir, sub));
|
|
11920
12767
|
} catch {
|
|
11921
12768
|
continue;
|
|
11922
12769
|
}
|