engramx 0.2.0 → 0.2.1
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.
|
@@ -315,7 +315,13 @@ function truncateGraphemeSafe(s, max) {
|
|
|
315
315
|
|
|
316
316
|
// src/graph/query.ts
|
|
317
317
|
var MISTAKE_SCORE_BOOST = 2.5;
|
|
318
|
+
var KEYWORD_SCORE_DOWNWEIGHT = 0.5;
|
|
318
319
|
var MAX_MISTAKE_LABEL_CHARS = 500;
|
|
320
|
+
function isHiddenKeyword(node) {
|
|
321
|
+
if (node.kind !== "concept") return false;
|
|
322
|
+
const meta = node.metadata;
|
|
323
|
+
return meta?.subkind === "keyword";
|
|
324
|
+
}
|
|
319
325
|
var CHARS_PER_TOKEN = 4;
|
|
320
326
|
function scoreNodes(store, terms) {
|
|
321
327
|
const allNodes = store.getAllNodes();
|
|
@@ -330,6 +336,7 @@ function scoreNodes(store, terms) {
|
|
|
330
336
|
}
|
|
331
337
|
if (score > 0) {
|
|
332
338
|
if (node.kind === "mistake") score *= MISTAKE_SCORE_BOOST;
|
|
339
|
+
if (isHiddenKeyword(node)) score *= KEYWORD_SCORE_DOWNWEIGHT;
|
|
333
340
|
scored.push({ score, node });
|
|
334
341
|
}
|
|
335
342
|
}
|
|
@@ -346,6 +353,12 @@ function queryGraph(store, question, options = {}) {
|
|
|
346
353
|
for (const n of startNodes) store.incrementQueryCount(n.id);
|
|
347
354
|
const visited = new Set(startNodes.map((n) => n.id));
|
|
348
355
|
const collectedEdges = [];
|
|
356
|
+
const shouldSkipEdgeFrom = (currentNodeId, edge) => {
|
|
357
|
+
if (edge.relation !== "triggered_by") return false;
|
|
358
|
+
const currentNode = store.getNode(currentNodeId);
|
|
359
|
+
if (!currentNode) return false;
|
|
360
|
+
return !isHiddenKeyword(currentNode);
|
|
361
|
+
};
|
|
349
362
|
if (mode === "bfs") {
|
|
350
363
|
let frontier = new Set(startNodes.map((n) => n.id));
|
|
351
364
|
for (let d = 0; d < depth; d++) {
|
|
@@ -353,6 +366,7 @@ function queryGraph(store, question, options = {}) {
|
|
|
353
366
|
for (const nid of frontier) {
|
|
354
367
|
const neighbors = store.getNeighbors(nid);
|
|
355
368
|
for (const { node, edge } of neighbors) {
|
|
369
|
+
if (shouldSkipEdgeFrom(nid, edge)) continue;
|
|
356
370
|
if (!visited.has(node.id)) {
|
|
357
371
|
nextFrontier.add(node.id);
|
|
358
372
|
collectedEdges.push(edge);
|
|
@@ -369,6 +383,7 @@ function queryGraph(store, question, options = {}) {
|
|
|
369
383
|
if (d > depth) continue;
|
|
370
384
|
const neighbors = store.getNeighbors(id);
|
|
371
385
|
for (const { node, edge } of neighbors) {
|
|
386
|
+
if (shouldSkipEdgeFrom(id, edge)) continue;
|
|
372
387
|
if (!visited.has(node.id)) {
|
|
373
388
|
visited.add(node.id);
|
|
374
389
|
stack.push({ id: node.id, d: d + 1 });
|
|
@@ -446,7 +461,12 @@ function renderSubgraph(nodes, edges, tokenBudget) {
|
|
|
446
461
|
const charBudget = tokenBudget * CHARS_PER_TOKEN;
|
|
447
462
|
const lines = [];
|
|
448
463
|
const mistakes2 = nodes.filter((n) => n.kind === "mistake");
|
|
449
|
-
const
|
|
464
|
+
const visible = nodes.filter(
|
|
465
|
+
(n) => n.kind !== "mistake" && !isHiddenKeyword(n)
|
|
466
|
+
);
|
|
467
|
+
const hiddenKeywordIds = new Set(
|
|
468
|
+
nodes.filter(isHiddenKeyword).map((n) => n.id)
|
|
469
|
+
);
|
|
450
470
|
if (mistakes2.length > 0) {
|
|
451
471
|
lines.push("\u26A0\uFE0F PAST MISTAKES (relevant to your query):");
|
|
452
472
|
for (const m of mistakes2) {
|
|
@@ -461,7 +481,7 @@ function renderSubgraph(nodes, edges, tokenBudget) {
|
|
|
461
481
|
degreeMap.set(e.source, (degreeMap.get(e.source) ?? 0) + 1);
|
|
462
482
|
degreeMap.set(e.target, (degreeMap.get(e.target) ?? 0) + 1);
|
|
463
483
|
}
|
|
464
|
-
const sorted = [...
|
|
484
|
+
const sorted = [...visible].sort(
|
|
465
485
|
(a, b) => (degreeMap.get(b.id) ?? 0) - (degreeMap.get(a.id) ?? 0)
|
|
466
486
|
);
|
|
467
487
|
for (const n of sorted) {
|
|
@@ -469,7 +489,18 @@ function renderSubgraph(nodes, edges, tokenBudget) {
|
|
|
469
489
|
`NODE ${n.label} [${n.kind}] src=${n.sourceFile} ${n.sourceLocation ?? ""}`
|
|
470
490
|
);
|
|
471
491
|
}
|
|
492
|
+
const skillConceptIds = new Set(
|
|
493
|
+
nodes.filter(
|
|
494
|
+
(n) => n.kind === "concept" && n.metadata?.subkind === "skill"
|
|
495
|
+
).map((n) => n.id)
|
|
496
|
+
);
|
|
472
497
|
for (const e of edges) {
|
|
498
|
+
if (hiddenKeywordIds.has(e.source) || hiddenKeywordIds.has(e.target)) {
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
if (e.relation === "similar_to" && skillConceptIds.has(e.source) && skillConceptIds.has(e.target)) {
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
473
504
|
const srcNode = nodes.find((n) => n.id === e.source);
|
|
474
505
|
const tgtNode = nodes.find((n) => n.id === e.target);
|
|
475
506
|
if (srcNode && tgtNode) {
|
|
@@ -310,7 +310,7 @@ function writeToFile(filePath, summary) {
|
|
|
310
310
|
writeFileSync2(filePath, newContent);
|
|
311
311
|
}
|
|
312
312
|
async function autogen(projectRoot, target, task) {
|
|
313
|
-
const { getStore } = await import("./core-
|
|
313
|
+
const { getStore } = await import("./core-HWOM7GSU.js");
|
|
314
314
|
const store = await getStore(projectRoot);
|
|
315
315
|
try {
|
|
316
316
|
let view = VIEWS.general;
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
install,
|
|
5
5
|
status,
|
|
6
6
|
uninstall
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YQ3FPGPC.js";
|
|
8
8
|
import {
|
|
9
9
|
benchmark,
|
|
10
10
|
godNodes,
|
|
@@ -14,13 +14,13 @@ import {
|
|
|
14
14
|
path,
|
|
15
15
|
query,
|
|
16
16
|
stats
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-22ADJYQ5.js";
|
|
18
18
|
|
|
19
19
|
// src/cli.ts
|
|
20
20
|
import { Command } from "commander";
|
|
21
21
|
import chalk from "chalk";
|
|
22
22
|
var program = new Command();
|
|
23
|
-
program.name("engram").description("AI coding memory that learns from every session").version("0.2.
|
|
23
|
+
program.name("engram").description("AI coding memory that learns from every session").version("0.2.1");
|
|
24
24
|
program.command("init").description("Scan codebase and build knowledge graph (zero LLM cost)").argument("[path]", "Project directory", ".").option(
|
|
25
25
|
"--with-skills [dir]",
|
|
26
26
|
"Also index Claude Code skills from ~/.claude/skills/ or a given path"
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
generateSummary,
|
|
5
5
|
install,
|
|
6
6
|
uninstall
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YQ3FPGPC.js";
|
|
8
8
|
import {
|
|
9
9
|
GraphStore,
|
|
10
10
|
SUPPORTED_EXTENSIONS,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
sliceGraphemeSafe,
|
|
24
24
|
stats,
|
|
25
25
|
truncateGraphemeSafe
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-22ADJYQ5.js";
|
|
27
27
|
export {
|
|
28
28
|
GraphStore,
|
|
29
29
|
SUPPORTED_EXTENSIONS,
|
package/dist/serve.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
query,
|
|
9
9
|
stats,
|
|
10
10
|
truncateGraphemeSafe
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-22ADJYQ5.js";
|
|
12
12
|
|
|
13
13
|
// src/serve.ts
|
|
14
14
|
function clampInt(value, defaultValue, min, max) {
|
|
@@ -174,7 +174,7 @@ async function handleRequest(req) {
|
|
|
174
174
|
result: {
|
|
175
175
|
protocolVersion: "2024-11-05",
|
|
176
176
|
capabilities: { tools: {} },
|
|
177
|
-
serverInfo: { name: "engram", version: "0.2.
|
|
177
|
+
serverInfo: { name: "engram", version: "0.2.1" }
|
|
178
178
|
}
|
|
179
179
|
};
|
|
180
180
|
case "tools/list":
|