@deeplake/hivemind 0.7.75 → 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/session-start.js +49 -0
- 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 +263 -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 +262 -8
- package/hermes/bundle/shell/deeplake-shell.js +725 -20
- package/openclaw/dist/index.js +28 -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
|
@@ -67672,7 +67672,7 @@ var DeeplakeApi = class {
|
|
|
67672
67672
|
};
|
|
67673
67673
|
|
|
67674
67674
|
// dist/src/shell/deeplake-fs.js
|
|
67675
|
-
import { basename as basename5, posix } from "node:path";
|
|
67675
|
+
import { basename as basename5, posix as posix2 } from "node:path";
|
|
67676
67676
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
67677
67677
|
import { fileURLToPath } from "node:url";
|
|
67678
67678
|
import { dirname as dirname9, join as join16 } from "node:path";
|
|
@@ -68822,6 +68822,9 @@ import { dirname as dirname7, join as join14 } from "node:path";
|
|
|
68822
68822
|
import { appendFileSync as appendFileSync2, existsSync as existsSync7, mkdirSync as mkdirSync6, readFileSync as readFileSync8 } from "node:fs";
|
|
68823
68823
|
import { dirname as dirname6, join as join13 } from "node:path";
|
|
68824
68824
|
|
|
68825
|
+
// dist/src/graph/resolve/cross-file.js
|
|
68826
|
+
import { posix } from "node:path";
|
|
68827
|
+
|
|
68825
68828
|
// dist/src/graph/snapshot.js
|
|
68826
68829
|
function graphsRoot() {
|
|
68827
68830
|
return process.env.HIVEMIND_GRAPHS_HOME ?? join14(homedir8(), ".hivemind", "graphs");
|
|
@@ -68877,6 +68880,513 @@ function deriveProjectKey(cwd) {
|
|
|
68877
68880
|
return { key, project };
|
|
68878
68881
|
}
|
|
68879
68882
|
|
|
68883
|
+
// dist/src/graph/render/neighborhood.js
|
|
68884
|
+
var CAP = 25;
|
|
68885
|
+
function renderNeighborhood(snap, file) {
|
|
68886
|
+
const allFiles = [...new Set(snap.nodes.map((n24) => n24.source_file))];
|
|
68887
|
+
let resolved = null;
|
|
68888
|
+
if (allFiles.includes(file)) {
|
|
68889
|
+
resolved = file;
|
|
68890
|
+
} else {
|
|
68891
|
+
const matches = allFiles.filter((f11) => f11.endsWith(file) || f11.includes(file));
|
|
68892
|
+
if (matches.length === 1) {
|
|
68893
|
+
resolved = matches[0];
|
|
68894
|
+
} else if (matches.length > 1) {
|
|
68895
|
+
const lines2 = [];
|
|
68896
|
+
lines2.push(`"${file}" matches multiple files \u2014 which did you mean?`);
|
|
68897
|
+
lines2.push("");
|
|
68898
|
+
for (const m26 of matches.slice(0, 10))
|
|
68899
|
+
lines2.push(` ${m26}`);
|
|
68900
|
+
if (matches.length > 10)
|
|
68901
|
+
lines2.push(` ... and ${matches.length - 10} more`);
|
|
68902
|
+
return lines2.join("\n");
|
|
68903
|
+
}
|
|
68904
|
+
}
|
|
68905
|
+
if (resolved === null) {
|
|
68906
|
+
const lines2 = [];
|
|
68907
|
+
lines2.push(`No nodes for "${file}".`);
|
|
68908
|
+
const parts = file.split("/").filter((p22) => p22.length > 2);
|
|
68909
|
+
const close = allFiles.filter((f11) => parts.some((p22) => f11.includes(p22))).slice(0, 3);
|
|
68910
|
+
if (close.length > 0) {
|
|
68911
|
+
lines2.push("Did you mean:");
|
|
68912
|
+
for (const c15 of close)
|
|
68913
|
+
lines2.push(` ${c15}`);
|
|
68914
|
+
}
|
|
68915
|
+
return lines2.join("\n");
|
|
68916
|
+
}
|
|
68917
|
+
const fileNodes = snap.nodes.filter((n24) => n24.source_file === resolved);
|
|
68918
|
+
const fileNodeIds = new Set(fileNodes.map((n24) => n24.id));
|
|
68919
|
+
const fileOf = /* @__PURE__ */ new Map();
|
|
68920
|
+
for (const n24 of snap.nodes)
|
|
68921
|
+
fileOf.set(n24.id, n24.source_file);
|
|
68922
|
+
const sorted = [...fileNodes].sort((a15, b26) => {
|
|
68923
|
+
const la2 = parseLocation(a15.source_location);
|
|
68924
|
+
const lb = parseLocation(b26.source_location);
|
|
68925
|
+
if (la2 !== lb)
|
|
68926
|
+
return la2 - lb;
|
|
68927
|
+
return a15.label.localeCompare(b26.label);
|
|
68928
|
+
});
|
|
68929
|
+
const lines = [];
|
|
68930
|
+
lines.push(`## Symbols in ${resolved}`);
|
|
68931
|
+
lines.push("");
|
|
68932
|
+
if (sorted.length === 0) {
|
|
68933
|
+
lines.push(" (no symbols)");
|
|
68934
|
+
} else {
|
|
68935
|
+
for (const n24 of sorted) {
|
|
68936
|
+
const exp = n24.exported ? "exported" : "internal";
|
|
68937
|
+
lines.push(` ${n24.label.padEnd(32)} ${n24.kind.padEnd(12)} ${exp.padEnd(10)} ${n24.source_location}`);
|
|
68938
|
+
}
|
|
68939
|
+
}
|
|
68940
|
+
lines.push("");
|
|
68941
|
+
lines.push("## Cross-file neighbors");
|
|
68942
|
+
lines.push("");
|
|
68943
|
+
lines.push("Note: 'calls' edges are intra-file only in the current extractor \u2014 cross-file");
|
|
68944
|
+
lines.push("neighbors here are driven mainly by 'imports' edges.");
|
|
68945
|
+
lines.push("");
|
|
68946
|
+
const outgoing = [];
|
|
68947
|
+
const incoming = [];
|
|
68948
|
+
for (const e6 of snap.links) {
|
|
68949
|
+
const srcIn = fileNodeIds.has(e6.source);
|
|
68950
|
+
const tgtIn = fileNodeIds.has(e6.target);
|
|
68951
|
+
if (srcIn === tgtIn)
|
|
68952
|
+
continue;
|
|
68953
|
+
if (srcIn) {
|
|
68954
|
+
const tgtFile = fileOf.get(e6.target);
|
|
68955
|
+
if (tgtFile !== void 0 && tgtFile !== resolved)
|
|
68956
|
+
outgoing.push(e6);
|
|
68957
|
+
} else {
|
|
68958
|
+
const srcFile = fileOf.get(e6.source);
|
|
68959
|
+
if (srcFile !== void 0 && srcFile !== resolved)
|
|
68960
|
+
incoming.push(e6);
|
|
68961
|
+
}
|
|
68962
|
+
}
|
|
68963
|
+
renderDirectionGroup(lines, outgoing, "Outgoing", "source");
|
|
68964
|
+
renderDirectionGroup(lines, incoming, "Incoming", "target");
|
|
68965
|
+
return lines.join("\n");
|
|
68966
|
+
}
|
|
68967
|
+
function renderDirectionGroup(lines, edges, label, selfField) {
|
|
68968
|
+
const otherField = selfField === "source" ? "target" : "source";
|
|
68969
|
+
const byRelation = /* @__PURE__ */ new Map();
|
|
68970
|
+
for (const e6 of edges) {
|
|
68971
|
+
const otherId = e6[otherField];
|
|
68972
|
+
const rel = e6.relation;
|
|
68973
|
+
let nodeMap = byRelation.get(rel);
|
|
68974
|
+
if (!nodeMap) {
|
|
68975
|
+
nodeMap = /* @__PURE__ */ new Map();
|
|
68976
|
+
byRelation.set(rel, nodeMap);
|
|
68977
|
+
}
|
|
68978
|
+
nodeMap.set(otherId, (nodeMap.get(otherId) ?? 0) + 1);
|
|
68979
|
+
}
|
|
68980
|
+
if (byRelation.size === 0) {
|
|
68981
|
+
lines.push(`${label}: (none)`);
|
|
68982
|
+
lines.push("");
|
|
68983
|
+
return;
|
|
68984
|
+
}
|
|
68985
|
+
lines.push(`${label}:`);
|
|
68986
|
+
let totalShown = 0;
|
|
68987
|
+
const sortedRels = [...byRelation.entries()].sort(([a15], [b26]) => a15.localeCompare(b26));
|
|
68988
|
+
for (const [rel, nodeMap] of sortedRels) {
|
|
68989
|
+
const entries = [...nodeMap.entries()].sort(([a15], [b26]) => a15.localeCompare(b26));
|
|
68990
|
+
lines.push(` ${rel} (${entries.length}):`);
|
|
68991
|
+
let shownInRel = 0;
|
|
68992
|
+
for (const [otherId, cnt] of entries) {
|
|
68993
|
+
if (totalShown >= CAP)
|
|
68994
|
+
break;
|
|
68995
|
+
const suffix = cnt > 1 ? ` \xD7${cnt}` : "";
|
|
68996
|
+
lines.push(` ${otherId}${suffix}`);
|
|
68997
|
+
shownInRel++;
|
|
68998
|
+
totalShown++;
|
|
68999
|
+
}
|
|
69000
|
+
const remaining = entries.length - shownInRel;
|
|
69001
|
+
if (remaining > 0)
|
|
69002
|
+
lines.push(` ... and ${remaining} more`);
|
|
69003
|
+
}
|
|
69004
|
+
if (totalShown >= CAP) {
|
|
69005
|
+
const total = [...byRelation.values()].reduce((s10, m26) => s10 + m26.size, 0);
|
|
69006
|
+
if (total > CAP)
|
|
69007
|
+
lines.push(` ... and ${total - CAP} more`);
|
|
69008
|
+
}
|
|
69009
|
+
lines.push("");
|
|
69010
|
+
}
|
|
69011
|
+
function parseLocation(loc) {
|
|
69012
|
+
const m26 = loc.match(/^L(\d+)/);
|
|
69013
|
+
return m26 ? parseInt(m26[1], 10) : 0;
|
|
69014
|
+
}
|
|
69015
|
+
|
|
69016
|
+
// dist/src/graph/render/layers.js
|
|
69017
|
+
var LAYER_RULES = [
|
|
69018
|
+
{ layer: "Tests", test: (p22) => p22.includes("/tests/") || p22.includes(".test.") || p22.includes("/__tests__/") },
|
|
69019
|
+
{ layer: "Hooks", test: (p22) => p22.includes("/hooks/") },
|
|
69020
|
+
{ layer: "CLI", test: (p22) => p22.includes("/cli/") || p22.includes("/commands/") },
|
|
69021
|
+
{ layer: "Graph", test: (p22) => p22.includes("/graph/") },
|
|
69022
|
+
{ layer: "Shell/VFS", test: (p22) => p22.includes("/shell/") },
|
|
69023
|
+
{ layer: "Embeddings", test: (p22) => p22.includes("/embeddings/") },
|
|
69024
|
+
{ layer: "Skillify", test: (p22) => p22.includes("/skillify/") },
|
|
69025
|
+
{ layer: "Config", test: (p22) => /(?:^|\/)config\.[^/]+$/.test(p22) || /\.config\.[^/]+$/.test(p22) },
|
|
69026
|
+
{ layer: "Utils", test: (p22) => p22.includes("/utils/") }
|
|
69027
|
+
];
|
|
69028
|
+
function layerOf(sourceFile) {
|
|
69029
|
+
const p22 = sourceFile.startsWith("/") ? sourceFile : `/${sourceFile}`;
|
|
69030
|
+
for (const rule of LAYER_RULES) {
|
|
69031
|
+
if (rule.test(p22))
|
|
69032
|
+
return rule.layer;
|
|
69033
|
+
}
|
|
69034
|
+
return "Core";
|
|
69035
|
+
}
|
|
69036
|
+
function renderLayers(snap) {
|
|
69037
|
+
try {
|
|
69038
|
+
const layerNodes = /* @__PURE__ */ new Map();
|
|
69039
|
+
const layerFiles = /* @__PURE__ */ new Map();
|
|
69040
|
+
for (const node of snap.nodes) {
|
|
69041
|
+
const layer = layerOf(node.source_file);
|
|
69042
|
+
layerNodes.set(layer, (layerNodes.get(layer) ?? 0) + 1);
|
|
69043
|
+
let fileMap = layerFiles.get(layer);
|
|
69044
|
+
if (!fileMap) {
|
|
69045
|
+
fileMap = /* @__PURE__ */ new Map();
|
|
69046
|
+
layerFiles.set(layer, fileMap);
|
|
69047
|
+
}
|
|
69048
|
+
fileMap.set(node.source_file, (fileMap.get(node.source_file) ?? 0) + 1);
|
|
69049
|
+
}
|
|
69050
|
+
if (layerNodes.size === 0) {
|
|
69051
|
+
return "No nodes in snapshot \u2014 nothing to layer.";
|
|
69052
|
+
}
|
|
69053
|
+
const sorted = [...layerNodes.entries()].sort(([, a15], [, b26]) => b26 - a15);
|
|
69054
|
+
const lines = [];
|
|
69055
|
+
lines.push("## Architectural Layers");
|
|
69056
|
+
lines.push("");
|
|
69057
|
+
for (const [layer, count] of sorted) {
|
|
69058
|
+
lines.push(`${layer.padEnd(14)} ${String(count).padStart(4)} node${count === 1 ? "" : "s"}`);
|
|
69059
|
+
const fileMap = layerFiles.get(layer);
|
|
69060
|
+
const topFiles = [...fileMap.entries()].sort(([, a15], [, b26]) => b26 - a15).slice(0, 5);
|
|
69061
|
+
for (const [file, n24] of topFiles) {
|
|
69062
|
+
lines.push(` ${String(n24).padStart(3)} ${file}`);
|
|
69063
|
+
}
|
|
69064
|
+
if (fileMap.size > 5) {
|
|
69065
|
+
lines.push(` ... and ${fileMap.size - 5} more file${fileMap.size - 5 === 1 ? "" : "s"}`);
|
|
69066
|
+
}
|
|
69067
|
+
}
|
|
69068
|
+
lines.push("");
|
|
69069
|
+
lines.push(`Total: ${snap.nodes.length} node${snap.nodes.length === 1 ? "" : "s"} across ${sorted.length} layer${sorted.length === 1 ? "" : "s"}`);
|
|
69070
|
+
return lines.join("\n");
|
|
69071
|
+
} catch {
|
|
69072
|
+
return "Failed to render layer view.";
|
|
69073
|
+
}
|
|
69074
|
+
}
|
|
69075
|
+
|
|
69076
|
+
// dist/src/graph/render/tour.js
|
|
69077
|
+
var LINE_CAP = 60;
|
|
69078
|
+
function renderTour(snap) {
|
|
69079
|
+
if (snap.nodes.length === 0) {
|
|
69080
|
+
return "Graph is empty \u2014 no nodes to tour.";
|
|
69081
|
+
}
|
|
69082
|
+
const nodeMap = /* @__PURE__ */ new Map();
|
|
69083
|
+
for (const n24 of snap.nodes)
|
|
69084
|
+
nodeMap.set(n24.id, n24);
|
|
69085
|
+
const inDegOrig = /* @__PURE__ */ new Map();
|
|
69086
|
+
for (const n24 of snap.nodes)
|
|
69087
|
+
inDegOrig.set(n24.id, 0);
|
|
69088
|
+
for (const e6 of snap.links) {
|
|
69089
|
+
if (nodeMap.has(e6.source) && nodeMap.has(e6.target)) {
|
|
69090
|
+
inDegOrig.set(e6.target, (inDegOrig.get(e6.target) ?? 0) + 1);
|
|
69091
|
+
}
|
|
69092
|
+
}
|
|
69093
|
+
const entryPoints = snap.nodes.filter((n24) => n24.exported && inDegOrig.get(n24.id) === 0).sort((a15, b26) => a15.id.localeCompare(b26.id));
|
|
69094
|
+
const entrySet = new Set(entryPoints.map((n24) => n24.id));
|
|
69095
|
+
const revAdj = /* @__PURE__ */ new Map();
|
|
69096
|
+
const inDegRev = /* @__PURE__ */ new Map();
|
|
69097
|
+
for (const n24 of snap.nodes) {
|
|
69098
|
+
revAdj.set(n24.id, []);
|
|
69099
|
+
inDegRev.set(n24.id, 0);
|
|
69100
|
+
}
|
|
69101
|
+
for (const e6 of snap.links) {
|
|
69102
|
+
if (!nodeMap.has(e6.source) || !nodeMap.has(e6.target))
|
|
69103
|
+
continue;
|
|
69104
|
+
revAdj.get(e6.target).push(e6.source);
|
|
69105
|
+
inDegRev.set(e6.source, (inDegRev.get(e6.source) ?? 0) + 1);
|
|
69106
|
+
}
|
|
69107
|
+
const queue = [];
|
|
69108
|
+
for (const n24 of snap.nodes) {
|
|
69109
|
+
if (inDegRev.get(n24.id) === 0)
|
|
69110
|
+
queue.push(n24.id);
|
|
69111
|
+
}
|
|
69112
|
+
queue.sort();
|
|
69113
|
+
const topoOrder = [];
|
|
69114
|
+
while (queue.length > 0) {
|
|
69115
|
+
const id = queue.shift();
|
|
69116
|
+
topoOrder.push(id);
|
|
69117
|
+
const newReady = [];
|
|
69118
|
+
for (const dep of revAdj.get(id) ?? []) {
|
|
69119
|
+
const d15 = (inDegRev.get(dep) ?? 0) - 1;
|
|
69120
|
+
inDegRev.set(dep, d15);
|
|
69121
|
+
if (d15 === 0)
|
|
69122
|
+
newReady.push(dep);
|
|
69123
|
+
}
|
|
69124
|
+
if (newReady.length > 0) {
|
|
69125
|
+
for (const x28 of newReady)
|
|
69126
|
+
queue.push(x28);
|
|
69127
|
+
queue.sort();
|
|
69128
|
+
}
|
|
69129
|
+
}
|
|
69130
|
+
const topoSet = new Set(topoOrder);
|
|
69131
|
+
const cyclic = snap.nodes.filter((n24) => !topoSet.has(n24.id)).sort((a15, b26) => a15.id.localeCompare(b26.id));
|
|
69132
|
+
const walkthrough = topoOrder.filter((id) => !entrySet.has(id));
|
|
69133
|
+
const totalNodes = snap.nodes.length;
|
|
69134
|
+
const lines = [];
|
|
69135
|
+
lines.push(`# Code Graph Tour \u2014 ${totalNodes} node${totalNodes !== 1 ? "s" : ""}`);
|
|
69136
|
+
lines.push("");
|
|
69137
|
+
lines.push(`## Entry points (${entryPoints.length})`);
|
|
69138
|
+
if (entryPoints.length === 0) {
|
|
69139
|
+
lines.push(" (none \u2014 all exported nodes have at least one incoming edge)");
|
|
69140
|
+
} else {
|
|
69141
|
+
lines.push(" Exported symbols with no incoming edges \u2014 likely top-level public API.");
|
|
69142
|
+
lines.push("");
|
|
69143
|
+
for (let i11 = 0; i11 < entryPoints.length; i11++) {
|
|
69144
|
+
if (lines.length >= LINE_CAP) {
|
|
69145
|
+
lines.push(` ... and ${entryPoints.length - i11} more`);
|
|
69146
|
+
break;
|
|
69147
|
+
}
|
|
69148
|
+
lines.push(` ${i11 + 1}. ${entryPoints[i11].id} [${entryPoints[i11].kind}]`);
|
|
69149
|
+
}
|
|
69150
|
+
}
|
|
69151
|
+
lines.push("");
|
|
69152
|
+
lines.push(`## Walkthrough \u2014 dependency order (${walkthrough.length})`);
|
|
69153
|
+
if (walkthrough.length === 0) {
|
|
69154
|
+
lines.push(" (all non-entry nodes are cyclic)");
|
|
69155
|
+
} else {
|
|
69156
|
+
lines.push(" Dependencies before dependents (bottom-up).");
|
|
69157
|
+
lines.push("");
|
|
69158
|
+
for (let i11 = 0; i11 < walkthrough.length; i11++) {
|
|
69159
|
+
if (lines.length >= LINE_CAP) {
|
|
69160
|
+
lines.push(` ... and ${walkthrough.length - i11} more`);
|
|
69161
|
+
break;
|
|
69162
|
+
}
|
|
69163
|
+
const n24 = nodeMap.get(walkthrough[i11]);
|
|
69164
|
+
lines.push(` ${i11 + 1}. ${n24.id} [${n24.kind}]`);
|
|
69165
|
+
}
|
|
69166
|
+
}
|
|
69167
|
+
lines.push("");
|
|
69168
|
+
if (cyclic.length > 0) {
|
|
69169
|
+
lines.push(`## Cyclic / remaining (${cyclic.length})`);
|
|
69170
|
+
lines.push(" These nodes form cycles and were not reached by topological sort.");
|
|
69171
|
+
lines.push("");
|
|
69172
|
+
for (let i11 = 0; i11 < cyclic.length; i11++) {
|
|
69173
|
+
if (lines.length >= LINE_CAP) {
|
|
69174
|
+
lines.push(` ... and ${cyclic.length - i11} more`);
|
|
69175
|
+
break;
|
|
69176
|
+
}
|
|
69177
|
+
lines.push(` ${i11 + 1}. ${cyclic[i11].id} [${cyclic[i11].kind}]`);
|
|
69178
|
+
}
|
|
69179
|
+
lines.push("");
|
|
69180
|
+
}
|
|
69181
|
+
lines.push(`Total: ${entryPoints.length} entry + ${walkthrough.length} walkthrough` + (cyclic.length > 0 ? ` + ${cyclic.length} cyclic` : "") + ` = ${totalNodes} nodes`);
|
|
69182
|
+
return lines.join("\n");
|
|
69183
|
+
}
|
|
69184
|
+
|
|
69185
|
+
// dist/src/graph/render/path.js
|
|
69186
|
+
function resolvePattern(snap, pattern) {
|
|
69187
|
+
const needle = pattern.toLowerCase();
|
|
69188
|
+
return snap.nodes.filter((n24) => n24.id.toLowerCase().includes(needle) || n24.label.toLowerCase().includes(needle)).map((n24) => n24.id).sort();
|
|
69189
|
+
}
|
|
69190
|
+
function buildAdjacency(snap, undirected) {
|
|
69191
|
+
const adj = /* @__PURE__ */ new Map();
|
|
69192
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
69193
|
+
for (const n24 of snap.nodes) {
|
|
69194
|
+
adj.set(n24.id, []);
|
|
69195
|
+
nodeIds.add(n24.id);
|
|
69196
|
+
}
|
|
69197
|
+
for (const edge of snap.links) {
|
|
69198
|
+
if (!nodeIds.has(edge.source) || !nodeIds.has(edge.target))
|
|
69199
|
+
continue;
|
|
69200
|
+
adj.get(edge.source).push({ neighborId: edge.target, edge, reversed: false });
|
|
69201
|
+
if (undirected) {
|
|
69202
|
+
adj.get(edge.target).push({ neighborId: edge.source, edge, reversed: true });
|
|
69203
|
+
}
|
|
69204
|
+
}
|
|
69205
|
+
for (const neighbors of adj.values()) {
|
|
69206
|
+
neighbors.sort((a15, b26) => a15.neighborId.localeCompare(b26.neighborId) || a15.edge.relation.localeCompare(b26.edge.relation) || (a15.reversed === b26.reversed ? 0 : a15.reversed ? 1 : -1));
|
|
69207
|
+
}
|
|
69208
|
+
return adj;
|
|
69209
|
+
}
|
|
69210
|
+
function bfs(adj, fromId, toId) {
|
|
69211
|
+
if (fromId === toId)
|
|
69212
|
+
return [];
|
|
69213
|
+
const parent = /* @__PURE__ */ new Map();
|
|
69214
|
+
const visited = /* @__PURE__ */ new Set([fromId]);
|
|
69215
|
+
const queue = [fromId];
|
|
69216
|
+
while (queue.length > 0) {
|
|
69217
|
+
const current = queue.shift();
|
|
69218
|
+
for (const { neighborId, edge, reversed } of adj.get(current) ?? []) {
|
|
69219
|
+
if (visited.has(neighborId))
|
|
69220
|
+
continue;
|
|
69221
|
+
visited.add(neighborId);
|
|
69222
|
+
parent.set(neighborId, { parentId: current, hop: { edge, reversed } });
|
|
69223
|
+
if (neighborId === toId) {
|
|
69224
|
+
const hops = [];
|
|
69225
|
+
let cur = toId;
|
|
69226
|
+
while (cur !== fromId) {
|
|
69227
|
+
const p22 = parent.get(cur);
|
|
69228
|
+
hops.unshift(p22.hop);
|
|
69229
|
+
cur = p22.parentId;
|
|
69230
|
+
}
|
|
69231
|
+
return hops;
|
|
69232
|
+
}
|
|
69233
|
+
queue.push(neighborId);
|
|
69234
|
+
}
|
|
69235
|
+
}
|
|
69236
|
+
return null;
|
|
69237
|
+
}
|
|
69238
|
+
function renderHops(fromId, hops, undirected) {
|
|
69239
|
+
const lines = [];
|
|
69240
|
+
lines.push(`${undirected ? "Undirected path" : "Directed path"} (${hops.length} hop${hops.length === 1 ? "" : "s"}):`);
|
|
69241
|
+
lines.push("");
|
|
69242
|
+
lines.push(` ${fromId}`);
|
|
69243
|
+
for (const { edge, reversed } of hops) {
|
|
69244
|
+
if (reversed) {
|
|
69245
|
+
lines.push(` <--${edge.relation}-- ${edge.source} [real edge: ${edge.source} \u2192 ${edge.target}]`);
|
|
69246
|
+
} else {
|
|
69247
|
+
lines.push(` --${edge.relation}--> ${edge.target}`);
|
|
69248
|
+
}
|
|
69249
|
+
}
|
|
69250
|
+
if (undirected) {
|
|
69251
|
+
lines.push("");
|
|
69252
|
+
lines.push("Note: no directed path exists. Arrows with <-- are traversed against their declared direction.");
|
|
69253
|
+
}
|
|
69254
|
+
return lines.join("\n");
|
|
69255
|
+
}
|
|
69256
|
+
function candidateList(pattern, ids) {
|
|
69257
|
+
const lines = [`"${pattern}" matches ${ids.length} nodes \u2014 be more specific:`];
|
|
69258
|
+
lines.push("");
|
|
69259
|
+
const shown = ids.slice(0, 20);
|
|
69260
|
+
for (let i11 = 0; i11 < shown.length; i11++)
|
|
69261
|
+
lines.push(` [${i11 + 1}] ${shown[i11]}`);
|
|
69262
|
+
if (ids.length > 20)
|
|
69263
|
+
lines.push(` ... and ${ids.length - 20} more`);
|
|
69264
|
+
return lines.join("\n");
|
|
69265
|
+
}
|
|
69266
|
+
function renderPath(snap, fromPattern, toPattern) {
|
|
69267
|
+
const fromIds = resolvePattern(snap, fromPattern);
|
|
69268
|
+
const toIds = resolvePattern(snap, toPattern);
|
|
69269
|
+
if (fromIds.length === 0) {
|
|
69270
|
+
return `No node matches "${fromPattern}". Try cat memory/graph/find/<pattern> to explore.`;
|
|
69271
|
+
}
|
|
69272
|
+
if (toIds.length === 0) {
|
|
69273
|
+
return `No node matches "${toPattern}". Try cat memory/graph/find/<pattern> to explore.`;
|
|
69274
|
+
}
|
|
69275
|
+
if (fromIds.length > 1)
|
|
69276
|
+
return candidateList(fromPattern, fromIds);
|
|
69277
|
+
if (toIds.length > 1)
|
|
69278
|
+
return candidateList(toPattern, toIds);
|
|
69279
|
+
const fromId = fromIds[0];
|
|
69280
|
+
const toId = toIds[0];
|
|
69281
|
+
if (fromId === toId) {
|
|
69282
|
+
return `"${fromId}" is the same node on both ends \u2014 path length 0.`;
|
|
69283
|
+
}
|
|
69284
|
+
const dirPath = bfs(buildAdjacency(snap, false), fromId, toId);
|
|
69285
|
+
if (dirPath !== null)
|
|
69286
|
+
return renderHops(fromId, dirPath, false);
|
|
69287
|
+
const undirPath = bfs(buildAdjacency(snap, true), fromId, toId);
|
|
69288
|
+
if (undirPath !== null)
|
|
69289
|
+
return renderHops(fromId, undirPath, true);
|
|
69290
|
+
const fromNode = snap.nodes.find((n24) => n24.id === fromId);
|
|
69291
|
+
const toNode = snap.nodes.find((n24) => n24.id === toId);
|
|
69292
|
+
const sameFile = fromNode && toNode && fromNode.source_file === toNode.source_file;
|
|
69293
|
+
const context = sameFile ? `Both are in ${fromNode.source_file} \u2014 same file but no connecting edges.` : `Sources: ${fromNode?.source_file ?? "?"} vs ${toNode?.source_file ?? "?"} \u2014 they appear disconnected.`;
|
|
69294
|
+
return [`No path found between:`, ` from: ${fromId}`, ` to: ${toId}`, ``, context].join("\n");
|
|
69295
|
+
}
|
|
69296
|
+
|
|
69297
|
+
// dist/src/graph/render/impact.js
|
|
69298
|
+
var IMPACT_CAP = 80;
|
|
69299
|
+
var MAX_DEPTH = 25;
|
|
69300
|
+
function renderImpact(snap, pattern) {
|
|
69301
|
+
const needle = pattern.toLowerCase();
|
|
69302
|
+
const matches = snap.nodes.filter((n24) => n24.id.toLowerCase().includes(needle));
|
|
69303
|
+
if (matches.length === 0) {
|
|
69304
|
+
return `No node matches "${pattern}". Try cat memory/graph/find/${pattern} to explore.`;
|
|
69305
|
+
}
|
|
69306
|
+
if (matches.length > 1) {
|
|
69307
|
+
const lines2 = [`"${pattern}" matches ${matches.length} nodes \u2014 be more specific:`, ""];
|
|
69308
|
+
for (const m26 of matches.slice(0, 20))
|
|
69309
|
+
lines2.push(` ${m26.id}`);
|
|
69310
|
+
if (matches.length > 20)
|
|
69311
|
+
lines2.push(` ... and ${matches.length - 20} more`);
|
|
69312
|
+
return lines2.join("\n");
|
|
69313
|
+
}
|
|
69314
|
+
const target = matches[0];
|
|
69315
|
+
const nodeIds = new Set(snap.nodes.map((n24) => n24.id));
|
|
69316
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
69317
|
+
for (const e6 of snap.links) {
|
|
69318
|
+
if (!nodeIds.has(e6.source))
|
|
69319
|
+
continue;
|
|
69320
|
+
const list = incoming.get(e6.target);
|
|
69321
|
+
if (list)
|
|
69322
|
+
list.push(e6);
|
|
69323
|
+
else
|
|
69324
|
+
incoming.set(e6.target, [e6]);
|
|
69325
|
+
}
|
|
69326
|
+
const depthOf = /* @__PURE__ */ new Map();
|
|
69327
|
+
const viaOf = /* @__PURE__ */ new Map();
|
|
69328
|
+
depthOf.set(target.id, 0);
|
|
69329
|
+
let frontier = [target.id];
|
|
69330
|
+
let depth = 0;
|
|
69331
|
+
while (frontier.length > 0 && depth < MAX_DEPTH) {
|
|
69332
|
+
depth++;
|
|
69333
|
+
const next = [];
|
|
69334
|
+
for (const id of frontier) {
|
|
69335
|
+
const edges = (incoming.get(id) ?? []).slice().sort((a15, b26) => a15.source.localeCompare(b26.source) || a15.relation.localeCompare(b26.relation));
|
|
69336
|
+
for (const e6 of edges) {
|
|
69337
|
+
if (depthOf.has(e6.source))
|
|
69338
|
+
continue;
|
|
69339
|
+
depthOf.set(e6.source, depth);
|
|
69340
|
+
viaOf.set(e6.source, { rel: e6.relation, from: id });
|
|
69341
|
+
next.push(e6.source);
|
|
69342
|
+
}
|
|
69343
|
+
}
|
|
69344
|
+
next.sort();
|
|
69345
|
+
frontier = next;
|
|
69346
|
+
}
|
|
69347
|
+
const dependents = [...depthOf.entries()].filter(([id]) => id !== target.id);
|
|
69348
|
+
const total = dependents.length;
|
|
69349
|
+
const lines = [];
|
|
69350
|
+
lines.push(`Impact of ${target.id}`);
|
|
69351
|
+
if (target.signature)
|
|
69352
|
+
lines.push(` ${target.signature}`);
|
|
69353
|
+
lines.push("");
|
|
69354
|
+
if (total === 0) {
|
|
69355
|
+
lines.push("No resolved dependents \u2014 nothing in the graph reaches this symbol.");
|
|
69356
|
+
lines.push("(Cross-file resolution is partial; this is a lower bound, not proof it's unused.)");
|
|
69357
|
+
return lines.join("\n");
|
|
69358
|
+
}
|
|
69359
|
+
lines.push(`${total} dependent${total === 1 ? "" : "s"} (transitive), by depth:`);
|
|
69360
|
+
lines.push("");
|
|
69361
|
+
const byDepth = /* @__PURE__ */ new Map();
|
|
69362
|
+
for (const [id, d15] of dependents) {
|
|
69363
|
+
const list = byDepth.get(d15) ?? [];
|
|
69364
|
+
list.push(id);
|
|
69365
|
+
byDepth.set(d15, list);
|
|
69366
|
+
}
|
|
69367
|
+
let shown = 0;
|
|
69368
|
+
for (const d15 of [...byDepth.keys()].sort((a15, b26) => a15 - b26)) {
|
|
69369
|
+
const ids = byDepth.get(d15).sort();
|
|
69370
|
+
lines.push(` depth ${d15} (${ids.length}):`);
|
|
69371
|
+
for (const id of ids) {
|
|
69372
|
+
if (shown >= IMPACT_CAP)
|
|
69373
|
+
break;
|
|
69374
|
+
const via = viaOf.get(id);
|
|
69375
|
+
const tag = via ? ` [${via.rel} \u2192 ${via.from}]` : "";
|
|
69376
|
+
lines.push(` ${id}${tag}`);
|
|
69377
|
+
shown++;
|
|
69378
|
+
}
|
|
69379
|
+
if (shown >= IMPACT_CAP)
|
|
69380
|
+
break;
|
|
69381
|
+
}
|
|
69382
|
+
if (total > shown)
|
|
69383
|
+
lines.push(` ... and ${total - shown} more`);
|
|
69384
|
+
lines.push("");
|
|
69385
|
+
lines.push("Note: only RESOLVED edges are traversed (cross-file resolution is partial),");
|
|
69386
|
+
lines.push("so this is a lower bound on impact, not a completeness guarantee.");
|
|
69387
|
+
return lines.join("\n");
|
|
69388
|
+
}
|
|
69389
|
+
|
|
68880
69390
|
// dist/src/graph/vfs-handler.js
|
|
68881
69391
|
function workTreeIdFor(cwd) {
|
|
68882
69392
|
return createHash3("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
@@ -68912,10 +69422,50 @@ function handleGraphVfs(subpath, cwd) {
|
|
|
68912
69422
|
body: renderShow(snap, key, baseDir, workTreeIdFor(cwd))
|
|
68913
69423
|
}));
|
|
68914
69424
|
}
|
|
69425
|
+
if (path2.startsWith("query/")) {
|
|
69426
|
+
const pattern = path2.slice("query/".length);
|
|
69427
|
+
if (pattern === "") {
|
|
69428
|
+
return { kind: "not-found", message: "query/ requires a pattern: cat memory/graph/query/<keyword>" };
|
|
69429
|
+
}
|
|
69430
|
+
return loadSnapshotOrError(cwd, (snap, baseDir) => ({
|
|
69431
|
+
kind: "ok",
|
|
69432
|
+
body: renderQuery(snap, pattern, baseDir, workTreeIdFor(cwd))
|
|
69433
|
+
}));
|
|
69434
|
+
}
|
|
69435
|
+
if (path2.startsWith("impact/")) {
|
|
69436
|
+
const pattern = path2.slice("impact/".length);
|
|
69437
|
+
if (pattern === "") {
|
|
69438
|
+
return { kind: "not-found", message: "impact/ requires a pattern: cat memory/graph/impact/<symbol>" };
|
|
69439
|
+
}
|
|
69440
|
+
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderImpact(snap, pattern) }));
|
|
69441
|
+
}
|
|
69442
|
+
if (path2.startsWith("neighborhood/")) {
|
|
69443
|
+
const file = path2.slice("neighborhood/".length);
|
|
69444
|
+
if (file === "") {
|
|
69445
|
+
return { kind: "not-found", message: "neighborhood/ requires a file path: cat memory/graph/neighborhood/<file>" };
|
|
69446
|
+
}
|
|
69447
|
+
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderNeighborhood(snap, file) }));
|
|
69448
|
+
}
|
|
69449
|
+
if (path2 === "layers" || path2 === "layers/" || path2 === "layers/index.md") {
|
|
69450
|
+
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderLayers(snap) }));
|
|
69451
|
+
}
|
|
69452
|
+
if (path2 === "tour" || path2 === "tour/" || path2 === "tour/index.md") {
|
|
69453
|
+
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderTour(snap) }));
|
|
69454
|
+
}
|
|
69455
|
+
if (path2.startsWith("path/")) {
|
|
69456
|
+
const rest = path2.slice("path/".length);
|
|
69457
|
+
const slash = rest.indexOf("/");
|
|
69458
|
+
if (slash <= 0 || slash === rest.length - 1) {
|
|
69459
|
+
return { kind: "not-found", message: "path/ needs two patterns: cat memory/graph/path/<from>/<to> (each a symbol-name substring, no slash)" };
|
|
69460
|
+
}
|
|
69461
|
+
const fromPattern = rest.slice(0, slash);
|
|
69462
|
+
const toPattern = rest.slice(slash + 1);
|
|
69463
|
+
return loadSnapshotOrError(cwd, (snap) => ({ kind: "ok", body: renderPath(snap, fromPattern, toPattern) }));
|
|
69464
|
+
}
|
|
68915
69465
|
return {
|
|
68916
69466
|
kind: "not-found",
|
|
68917
69467
|
message: `Unknown endpoint: graph/${path2}
|
|
68918
|
-
Available: index.md, find/<pattern>, show/<handle-or-pattern>`
|
|
69468
|
+
Available: index.md, find/<pattern>, query/<pattern>, show/<handle-or-pattern>, impact/<pattern>, neighborhood/<file>, layers, tour, path/<from>/<to>`
|
|
68919
69469
|
};
|
|
68920
69470
|
}
|
|
68921
69471
|
function loadSnapshotOrError(cwd, fn4) {
|
|
@@ -68959,7 +69509,13 @@ function dirListing() {
|
|
|
68959
69509
|
return [
|
|
68960
69510
|
"index.md",
|
|
68961
69511
|
"find/",
|
|
68962
|
-
"
|
|
69512
|
+
"query/",
|
|
69513
|
+
"show/",
|
|
69514
|
+
"impact/",
|
|
69515
|
+
"neighborhood/",
|
|
69516
|
+
"layers",
|
|
69517
|
+
"tour",
|
|
69518
|
+
"path/"
|
|
68963
69519
|
].join("\n");
|
|
68964
69520
|
}
|
|
68965
69521
|
function renderIndex(snap, baseDir, cwd) {
|
|
@@ -68987,16 +69543,23 @@ function renderIndex(snap, baseDir, cwd) {
|
|
|
68987
69543
|
lines.push(`Nodes: ${totalNodes} Edges: ${totalEdges}`);
|
|
68988
69544
|
lines.push("");
|
|
68989
69545
|
lines.push("## How to query");
|
|
69546
|
+
lines.push(" cat ~/.deeplake/memory/graph/query/<pattern>");
|
|
69547
|
+
lines.push(" 2-in-1: search + expand the top matches with their 1-hop");
|
|
69548
|
+
lines.push(" neighbors (callers/callees/imports/heritage). Start here.");
|
|
69549
|
+
lines.push(" Multi-token AND: query/<a>+<b> requires both tokens.");
|
|
69550
|
+
lines.push("");
|
|
68990
69551
|
lines.push(" cat ~/.deeplake/memory/graph/find/<pattern>");
|
|
68991
69552
|
lines.push(" Case-insensitive substring match on node id + label.");
|
|
68992
69553
|
lines.push(" Emits numbered handles [1] [2] ... saved for this worktree.");
|
|
68993
69554
|
lines.push("");
|
|
68994
69555
|
lines.push(" cat ~/.deeplake/memory/graph/show/<handle-or-pattern>");
|
|
68995
|
-
lines.push(" <handle>: a digit from a prior `find/` (e.g. 3).");
|
|
69556
|
+
lines.push(" <handle>: a digit from a prior `find/`/`query/` (e.g. 3).");
|
|
68996
69557
|
lines.push(" <pattern>: a substring; resolves to a unique node if possible,");
|
|
68997
69558
|
lines.push(" or shows candidates if ambiguous.");
|
|
68998
69559
|
lines.push(" Output: node detail + 1-hop neighbors grouped by edge kind.");
|
|
68999
69560
|
lines.push("");
|
|
69561
|
+
lines.push(" Also: neighborhood/<file> \xB7 layers \xB7 tour \xB7 path/<from>/<to>");
|
|
69562
|
+
lines.push("");
|
|
69000
69563
|
lines.push("## Node kinds");
|
|
69001
69564
|
for (const [k17, n24] of Object.entries(byKind).sort(([, a15], [, b26]) => b26 - a15)) {
|
|
69002
69565
|
lines.push(` ${k17.padEnd(12)} ${n24}`);
|
|
@@ -69013,31 +69576,92 @@ function renderIndex(snap, baseDir, cwd) {
|
|
|
69013
69576
|
}
|
|
69014
69577
|
lines.push("");
|
|
69015
69578
|
lines.push(`Limitations:`);
|
|
69016
|
-
lines.push(` - TypeScript
|
|
69017
|
-
lines.push(` - 'calls'
|
|
69018
|
-
lines.push(`
|
|
69019
|
-
lines.push(`
|
|
69020
|
-
lines.push(`
|
|
69579
|
+
lines.push(` - TypeScript / JavaScript / Python. AST-based, no semantic similarity edges yet.`);
|
|
69580
|
+
lines.push(` - Cross-file 'calls'/'imports'/'extends' ARE resolved for relative named/namespace`);
|
|
69581
|
+
lines.push(` imports; bare (npm)/aliased/barrel/dynamic imports stay unresolved. So a node`);
|
|
69582
|
+
lines.push(` with "Incoming (0)" is not proof of dead code \u2014 a caller may reach it via an`);
|
|
69583
|
+
lines.push(` unresolved import path. (Python cross-file resolution is a follow-up; Python is`);
|
|
69584
|
+
lines.push(` intra-file + structure only for now.)`);
|
|
69021
69585
|
lines.push(` - Stale after edits \u2014 if a file's mtime is newer than the build, read the live source.`);
|
|
69022
69586
|
void cwd;
|
|
69023
69587
|
return lines.join("\n");
|
|
69024
69588
|
}
|
|
69025
|
-
function
|
|
69026
|
-
const
|
|
69589
|
+
function findMatches(snap, pattern) {
|
|
69590
|
+
const tokens = pattern.toLowerCase().split(/[\s+]+/).filter((t6) => t6.length > 0);
|
|
69591
|
+
if (tokens.length === 0)
|
|
69592
|
+
return [];
|
|
69593
|
+
if (tokens.length === 1) {
|
|
69594
|
+
const needle = tokens[0];
|
|
69595
|
+
const matches2 = [];
|
|
69596
|
+
for (const n24 of snap.nodes) {
|
|
69597
|
+
if (n24.id.toLowerCase().includes(needle) || n24.label.toLowerCase().includes(needle))
|
|
69598
|
+
matches2.push(n24);
|
|
69599
|
+
}
|
|
69600
|
+
matches2.sort((a15, b26) => {
|
|
69601
|
+
const ra2 = rank(a15, needle);
|
|
69602
|
+
const rb = rank(b26, needle);
|
|
69603
|
+
if (ra2 !== rb)
|
|
69604
|
+
return ra2 - rb;
|
|
69605
|
+
return a15.id.localeCompare(b26.id);
|
|
69606
|
+
});
|
|
69607
|
+
if (matches2.length === 0)
|
|
69608
|
+
return fuzzyMatches(snap, needle);
|
|
69609
|
+
return matches2;
|
|
69610
|
+
}
|
|
69027
69611
|
const matches = [];
|
|
69028
69612
|
for (const n24 of snap.nodes) {
|
|
69029
69613
|
const id = n24.id.toLowerCase();
|
|
69030
69614
|
const lbl = n24.label.toLowerCase();
|
|
69031
|
-
if (id.includes(
|
|
69615
|
+
if (tokens.every((t6) => id.includes(t6) || lbl.includes(t6)))
|
|
69032
69616
|
matches.push(n24);
|
|
69033
69617
|
}
|
|
69618
|
+
const score = (n24) => tokens.reduce((s10, t6) => s10 + rank(n24, t6), 0);
|
|
69034
69619
|
matches.sort((a15, b26) => {
|
|
69035
|
-
const
|
|
69036
|
-
const
|
|
69037
|
-
if (
|
|
69038
|
-
return
|
|
69620
|
+
const sa2 = score(a15);
|
|
69621
|
+
const sb = score(b26);
|
|
69622
|
+
if (sa2 !== sb)
|
|
69623
|
+
return sa2 - sb;
|
|
69039
69624
|
return a15.id.localeCompare(b26.id);
|
|
69040
69625
|
});
|
|
69626
|
+
return matches;
|
|
69627
|
+
}
|
|
69628
|
+
function fuzzyMatches(snap, needle) {
|
|
69629
|
+
if (needle.length < 3)
|
|
69630
|
+
return [];
|
|
69631
|
+
const maxDist = Math.max(1, Math.floor(needle.length / 4));
|
|
69632
|
+
const scored = [];
|
|
69633
|
+
for (const n24 of snap.nodes) {
|
|
69634
|
+
const d15 = editDistance(needle, n24.label.toLowerCase(), maxDist);
|
|
69635
|
+
if (d15 <= maxDist)
|
|
69636
|
+
scored.push({ n: n24, d: d15 });
|
|
69637
|
+
}
|
|
69638
|
+
scored.sort((a15, b26) => a15.d !== b26.d ? a15.d - b26.d : a15.n.id.localeCompare(b26.n.id));
|
|
69639
|
+
return scored.slice(0, 25).map((s10) => s10.n);
|
|
69640
|
+
}
|
|
69641
|
+
function editDistance(a15, b26, cap) {
|
|
69642
|
+
if (Math.abs(a15.length - b26.length) > cap)
|
|
69643
|
+
return cap + 1;
|
|
69644
|
+
let prev = new Array(b26.length + 1);
|
|
69645
|
+
let cur = new Array(b26.length + 1);
|
|
69646
|
+
for (let j14 = 0; j14 <= b26.length; j14++)
|
|
69647
|
+
prev[j14] = j14;
|
|
69648
|
+
for (let i11 = 1; i11 <= a15.length; i11++) {
|
|
69649
|
+
cur[0] = i11;
|
|
69650
|
+
let rowMin = cur[0];
|
|
69651
|
+
for (let j14 = 1; j14 <= b26.length; j14++) {
|
|
69652
|
+
const cost = a15[i11 - 1] === b26[j14 - 1] ? 0 : 1;
|
|
69653
|
+
cur[j14] = Math.min(prev[j14] + 1, cur[j14 - 1] + 1, prev[j14 - 1] + cost);
|
|
69654
|
+
if (cur[j14] < rowMin)
|
|
69655
|
+
rowMin = cur[j14];
|
|
69656
|
+
}
|
|
69657
|
+
if (rowMin > cap)
|
|
69658
|
+
return cap + 1;
|
|
69659
|
+
[prev, cur] = [cur, prev];
|
|
69660
|
+
}
|
|
69661
|
+
return prev[b26.length];
|
|
69662
|
+
}
|
|
69663
|
+
function renderFind(snap, pattern, baseDir, worktreeId) {
|
|
69664
|
+
const matches = findMatches(snap, pattern);
|
|
69041
69665
|
const capped = matches.slice(0, 50);
|
|
69042
69666
|
if (capped.length === 0) {
|
|
69043
69667
|
return `No matches for "${pattern}" in ${snap.nodes.length} nodes.
|
|
@@ -69056,6 +69680,76 @@ Try a shorter or different substring.`;
|
|
|
69056
69680
|
lines.push("Use: cat ~/.deeplake/memory/graph/show/<N> to see node + 1-hop neighbors");
|
|
69057
69681
|
return lines.join("\n");
|
|
69058
69682
|
}
|
|
69683
|
+
var QUERY_TOP_N = 5;
|
|
69684
|
+
var QUERY_NEIGHBOR_CAP = 8;
|
|
69685
|
+
function renderQuery(snap, pattern, baseDir, worktreeId) {
|
|
69686
|
+
const matches = findMatches(snap, pattern);
|
|
69687
|
+
if (matches.length === 0) {
|
|
69688
|
+
return `No matches for "${pattern}" in ${snap.nodes.length} nodes.
|
|
69689
|
+
Try a shorter or different substring, or cat memory/graph/find/<pattern>.`;
|
|
69690
|
+
}
|
|
69691
|
+
const top = matches.slice(0, QUERY_TOP_N);
|
|
69692
|
+
saveHandles(baseDir, worktreeId, top.map((n24) => n24.id), pattern);
|
|
69693
|
+
const topIds = new Set(top.map((n24) => n24.id));
|
|
69694
|
+
const outByNode = /* @__PURE__ */ new Map();
|
|
69695
|
+
const inByNode = /* @__PURE__ */ new Map();
|
|
69696
|
+
for (const e6 of snap.links) {
|
|
69697
|
+
if (topIds.has(e6.source))
|
|
69698
|
+
(outByNode.get(e6.source) ?? setGet(outByNode, e6.source)).push(e6);
|
|
69699
|
+
if (topIds.has(e6.target))
|
|
69700
|
+
(inByNode.get(e6.target) ?? setGet(inByNode, e6.target)).push(e6);
|
|
69701
|
+
}
|
|
69702
|
+
const lines = [];
|
|
69703
|
+
lines.push(`Query "${pattern}" \u2014 ${matches.length} match${matches.length === 1 ? "" : "es"}, expanded top ${top.length} (1 hop)`);
|
|
69704
|
+
lines.push("");
|
|
69705
|
+
for (let i11 = 0; i11 < top.length; i11++) {
|
|
69706
|
+
const n24 = top[i11];
|
|
69707
|
+
const tags = [n24.exported ? "exported" : "internal"];
|
|
69708
|
+
if (n24.is_entrypoint)
|
|
69709
|
+
tags.push("entrypoint");
|
|
69710
|
+
if (n24.fan_in !== void 0)
|
|
69711
|
+
tags.push(`fan_in=${n24.fan_in}`);
|
|
69712
|
+
if (n24.fan_out !== void 0)
|
|
69713
|
+
tags.push(`fan_out=${n24.fan_out}`);
|
|
69714
|
+
lines.push(`[${i11 + 1}] ${n24.id} ${n24.kind} (${tags.join(", ")})`);
|
|
69715
|
+
if (n24.signature)
|
|
69716
|
+
lines.push(` ${n24.signature}`);
|
|
69717
|
+
renderHopGroup(lines, outByNode.get(n24.id) ?? [], "OUT", "target");
|
|
69718
|
+
renderHopGroup(lines, inByNode.get(n24.id) ?? [], "IN", "source");
|
|
69719
|
+
lines.push("");
|
|
69720
|
+
}
|
|
69721
|
+
lines.push("Use: cat ~/.deeplake/memory/graph/show/<N> for full detail on a match.");
|
|
69722
|
+
return lines.join("\n");
|
|
69723
|
+
}
|
|
69724
|
+
function setGet(m26, key) {
|
|
69725
|
+
const list = [];
|
|
69726
|
+
m26.set(key, list);
|
|
69727
|
+
return list;
|
|
69728
|
+
}
|
|
69729
|
+
function renderHopGroup(lines, edges, dir, otherField) {
|
|
69730
|
+
if (edges.length === 0)
|
|
69731
|
+
return;
|
|
69732
|
+
const byRel = /* @__PURE__ */ new Map();
|
|
69733
|
+
for (const e6 of edges) {
|
|
69734
|
+
let counts = byRel.get(e6.relation);
|
|
69735
|
+
if (!counts) {
|
|
69736
|
+
counts = /* @__PURE__ */ new Map();
|
|
69737
|
+
byRel.set(e6.relation, counts);
|
|
69738
|
+
}
|
|
69739
|
+
const id = e6[otherField];
|
|
69740
|
+
counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
69741
|
+
}
|
|
69742
|
+
for (const [rel, counts] of [...byRel.entries()].sort(([a15], [b26]) => a15.localeCompare(b26))) {
|
|
69743
|
+
const arrow = dir === "OUT" ? `--${rel}-->` : `<--${rel}--`;
|
|
69744
|
+
const ids = [...counts.keys()].sort();
|
|
69745
|
+
const shown = ids.slice(0, QUERY_NEIGHBOR_CAP).map((id) => {
|
|
69746
|
+
const c15 = counts.get(id);
|
|
69747
|
+
return c15 > 1 ? `${id} \xD7${c15}` : id;
|
|
69748
|
+
});
|
|
69749
|
+
const more = ids.length > shown.length ? ` (+${ids.length - shown.length} more)` : "";
|
|
69750
|
+
lines.push(` ${arrow} ${shown.join(", ")}${more}`);
|
|
69751
|
+
}
|
|
69752
|
+
}
|
|
69059
69753
|
function renderShow(snap, key, baseDir, worktreeId) {
|
|
69060
69754
|
if (/^\d+$/.test(key)) {
|
|
69061
69755
|
const idx = parseInt(key, 10);
|
|
@@ -69117,9 +69811,20 @@ function renderNodeDetail(snap, node) {
|
|
|
69117
69811
|
lines.push(` source: ${node.source_file}:${node.source_location}`);
|
|
69118
69812
|
lines.push(` kind: ${node.kind}`);
|
|
69119
69813
|
lines.push(` label: ${node.label}`);
|
|
69120
|
-
|
|
69814
|
+
if (node.signature)
|
|
69815
|
+
lines.push(` sig: ${node.signature}`);
|
|
69816
|
+
if (node.doc)
|
|
69817
|
+
lines.push(` doc: ${node.doc}`);
|
|
69818
|
+
const tags = [node.exported ? "exported" : "internal"];
|
|
69819
|
+
if (node.is_entrypoint)
|
|
69820
|
+
tags.push("entrypoint");
|
|
69821
|
+
if (node.fan_in !== void 0)
|
|
69822
|
+
tags.push(`fan_in=${node.fan_in}`);
|
|
69823
|
+
if (node.fan_out !== void 0)
|
|
69824
|
+
tags.push(`fan_out=${node.fan_out}`);
|
|
69825
|
+
lines.push(` ${tags.join(" ")}`);
|
|
69121
69826
|
lines.push("");
|
|
69122
|
-
const inHint = incoming.length === 0 ? " \u2014 no
|
|
69827
|
+
const inHint = incoming.length === 0 ? " \u2014 no resolved callers (cross-file resolution is partial; not proof of dead code)" : ":";
|
|
69123
69828
|
lines.push(`Incoming (${incoming.length})${inHint}`);
|
|
69124
69829
|
for (const [rel, es3] of [...inGrp.entries()].sort(([a15], [b26]) => a15.localeCompare(b26))) {
|
|
69125
69830
|
lines.push(` ${rel} (${es3.length}):`);
|
|
@@ -69196,7 +69901,7 @@ var BATCH_SIZE = 10;
|
|
|
69196
69901
|
var PREFETCH_BATCH_SIZE = 50;
|
|
69197
69902
|
var FLUSH_DEBOUNCE_MS = 200;
|
|
69198
69903
|
function normPath(p22) {
|
|
69199
|
-
const r10 =
|
|
69904
|
+
const r10 = posix2.normalize(p22.startsWith("/") ? p22 : "/" + p22);
|
|
69200
69905
|
return r10 === "/" ? r10 : r10.replace(/\/$/, "");
|
|
69201
69906
|
}
|
|
69202
69907
|
function parentOf(p22) {
|
|
@@ -70045,7 +70750,7 @@ var DeeplakeFs = class _DeeplakeFs {
|
|
|
70045
70750
|
resolvePath(base, path2) {
|
|
70046
70751
|
if (path2.startsWith("/"))
|
|
70047
70752
|
return normPath(path2);
|
|
70048
|
-
return normPath(
|
|
70753
|
+
return normPath(posix2.join(base, path2));
|
|
70049
70754
|
}
|
|
70050
70755
|
getAllPaths() {
|
|
70051
70756
|
return [.../* @__PURE__ */ new Set([...this.files.keys(), ...this.dirs.keys()])];
|