@swarmvaultai/engine 0.6.6 → 0.6.7
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/dist/index.js +140 -150
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -64,6 +64,13 @@ function buildManagedBlock(target) {
|
|
|
64
64
|
""
|
|
65
65
|
].join("\n");
|
|
66
66
|
}
|
|
67
|
+
function buildCursorRule() {
|
|
68
|
+
const frontmatter = YAML.stringify({
|
|
69
|
+
description: "SwarmVault graph-first repository instructions.",
|
|
70
|
+
alwaysApply: true
|
|
71
|
+
}).trimEnd();
|
|
72
|
+
return ["---", frontmatter, "---", "", buildManagedBlock("cursor").trimEnd(), ""].join("\n");
|
|
73
|
+
}
|
|
67
74
|
function supportsAgentHook(agent) {
|
|
68
75
|
return agent === "claude" || agent === "opencode" || agent === "gemini" || agent === "copilot";
|
|
69
76
|
}
|
|
@@ -690,8 +697,7 @@ async function installAgent(rootDir, agent, options = {}) {
|
|
|
690
697
|
await upsertManagedBlock(target, buildManagedBlock("gemini"));
|
|
691
698
|
break;
|
|
692
699
|
case "cursor":
|
|
693
|
-
await writeOwnedFile(target,
|
|
694
|
-
`);
|
|
700
|
+
await writeOwnedFile(target, buildCursorRule());
|
|
695
701
|
break;
|
|
696
702
|
case "aider":
|
|
697
703
|
await upsertManagedBlock(target, buildManagedBlock("aider"));
|
|
@@ -1343,10 +1349,13 @@ function buildBenchmarkArtifact(input) {
|
|
|
1343
1349
|
const corpusTokens = Math.max(1, Math.round(input.corpusWords * (100 / 75)));
|
|
1344
1350
|
const perQuestion = input.perQuestion.filter((entry) => entry.queryTokens > 0).map((entry) => ({
|
|
1345
1351
|
...entry,
|
|
1346
|
-
reduction:
|
|
1352
|
+
// Honest reduction: negative values mean graph context is larger than the
|
|
1353
|
+
// full corpus, which is the truth on very small vaults. Clamping to zero
|
|
1354
|
+
// hid that signal.
|
|
1355
|
+
reduction: Number((1 - entry.queryTokens / Math.max(1, corpusTokens)).toFixed(3))
|
|
1347
1356
|
}));
|
|
1348
1357
|
const avgQueryTokens = perQuestion.length ? Math.max(1, Math.round(perQuestion.reduce((total, entry) => total + entry.queryTokens, 0) / perQuestion.length)) : 0;
|
|
1349
|
-
const reductionRatio = avgQueryTokens ? Number(
|
|
1358
|
+
const reductionRatio = avgQueryTokens ? Number((1 - avgQueryTokens / Math.max(1, corpusTokens)).toFixed(3)) : 0;
|
|
1350
1359
|
const uniqueVisitedNodes = new Set(perQuestion.flatMap((entry) => entry.visitedNodeIds)).size;
|
|
1351
1360
|
const summary = {
|
|
1352
1361
|
questionCount: input.questions.length,
|
|
@@ -1728,6 +1737,7 @@ import { pathToFileURL } from "url";
|
|
|
1728
1737
|
import { Readability } from "@mozilla/readability";
|
|
1729
1738
|
import matter3 from "gray-matter";
|
|
1730
1739
|
import ignore from "ignore";
|
|
1740
|
+
import { isText } from "istextorbinary";
|
|
1731
1741
|
import { JSDOM as JSDOM2 } from "jsdom";
|
|
1732
1742
|
import mime from "mime-types";
|
|
1733
1743
|
import TurndownService2 from "turndown";
|
|
@@ -2447,14 +2457,18 @@ function rubyStringContent(node) {
|
|
|
2447
2457
|
const contentNode = node.descendantsOfType(["string_content", "simple_symbol", "bare_string"]).find((item) => item !== null) ?? null;
|
|
2448
2458
|
return contentNode?.text.trim() || void 0;
|
|
2449
2459
|
}
|
|
2460
|
+
function normalizePowerShellDotSourceSpecifier(raw) {
|
|
2461
|
+
const unquoted = raw.replace(/^['"]+|['"]+$/g, "").trim();
|
|
2462
|
+
return unquoted.replace(/^\$PSScriptRoot(?:[\\/]+|$)/i, "./");
|
|
2463
|
+
}
|
|
2450
2464
|
function parsePowerShellImport(commandNode) {
|
|
2451
2465
|
const commandName = commandNode.descendantsOfType(["command_name", "command_name_expr"]).find((item) => item !== null)?.text.trim();
|
|
2452
2466
|
const genericTokens = commandNode.descendantsOfType("generic_token").filter((item) => item !== null).map((item) => item.text.trim());
|
|
2453
2467
|
if (commandNode.namedChildren.some((child) => child?.type === "command_invokation_operator")) {
|
|
2454
|
-
const
|
|
2455
|
-
if (
|
|
2468
|
+
const raw = commandName?.trim();
|
|
2469
|
+
if (raw) {
|
|
2456
2470
|
return {
|
|
2457
|
-
specifier,
|
|
2471
|
+
specifier: normalizePowerShellDotSourceSpecifier(raw),
|
|
2458
2472
|
importedSymbols: [],
|
|
2459
2473
|
isExternal: false,
|
|
2460
2474
|
reExport: false
|
|
@@ -2935,6 +2949,21 @@ function rustCodeAnalysis(manifest, rootNode, diagnostics) {
|
|
|
2935
2949
|
imports.push(parseRustUse(child.text));
|
|
2936
2950
|
continue;
|
|
2937
2951
|
}
|
|
2952
|
+
if (child.type === "mod_item") {
|
|
2953
|
+
const hasInlineBody = child.namedChildren.some((item) => item?.type === "declaration_list");
|
|
2954
|
+
if (!hasInlineBody) {
|
|
2955
|
+
const modName = extractIdentifier(child.childForFieldName("name") ?? findNamedChild(child, "identifier"));
|
|
2956
|
+
if (modName) {
|
|
2957
|
+
imports.push({
|
|
2958
|
+
specifier: `self::${modName}`,
|
|
2959
|
+
importedSymbols: [],
|
|
2960
|
+
isExternal: false,
|
|
2961
|
+
reExport: false
|
|
2962
|
+
});
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
continue;
|
|
2966
|
+
}
|
|
2938
2967
|
const name = child.type === "function_item" ? extractIdentifier(child.childForFieldName("name")) : extractIdentifier(child.childForFieldName("name"));
|
|
2939
2968
|
if (child.type === "impl_item") {
|
|
2940
2969
|
const traitName = normalizeSymbolReference(nodeText(child.childForFieldName("trait")));
|
|
@@ -3518,8 +3547,9 @@ function rubyCodeAnalysis(manifest, rootNode, diagnostics) {
|
|
|
3518
3547
|
if (callee === "require" || callee === "require_relative") {
|
|
3519
3548
|
const specifier = rubyStringContent(child.childForFieldName("arguments") ?? child.namedChildren.at(1) ?? null);
|
|
3520
3549
|
if (specifier) {
|
|
3550
|
+
const normalizedSpecifier = callee === "require_relative" && !specifier.startsWith(".") && !specifier.startsWith("/") ? `./${specifier}` : specifier;
|
|
3521
3551
|
imports.push({
|
|
3522
|
-
specifier,
|
|
3552
|
+
specifier: normalizedSpecifier,
|
|
3523
3553
|
importedSymbols: [],
|
|
3524
3554
|
isExternal: callee === "require" && !specifier.startsWith("."),
|
|
3525
3555
|
reExport: false
|
|
@@ -3766,7 +3796,7 @@ async function analyzeTreeSitterCode(manifest, content, language) {
|
|
|
3766
3796
|
};
|
|
3767
3797
|
}
|
|
3768
3798
|
try {
|
|
3769
|
-
const diagnostics = diagnosticsFromTree(tree.rootNode);
|
|
3799
|
+
const diagnostics = language === "lua" ? [] : diagnosticsFromTree(tree.rootNode);
|
|
3770
3800
|
const rationales = extractTreeSitterRationales(manifest, language, tree.rootNode);
|
|
3771
3801
|
switch (language) {
|
|
3772
3802
|
case "bash":
|
|
@@ -4509,7 +4539,13 @@ function modulePageTitle(manifest) {
|
|
|
4509
4539
|
}
|
|
4510
4540
|
function importResolutionCandidates(basePath, specifier, extensions) {
|
|
4511
4541
|
const resolved = path6.posix.normalize(path6.posix.join(path6.posix.dirname(basePath), specifier));
|
|
4512
|
-
|
|
4542
|
+
const resolvedExt = path6.posix.extname(resolved);
|
|
4543
|
+
if (resolvedExt) {
|
|
4544
|
+
if (extensions.includes(resolvedExt)) {
|
|
4545
|
+
const resolvedBase = resolved.slice(0, -resolvedExt.length);
|
|
4546
|
+
const candidates = [resolved, ...extensions.map((extension) => `${resolvedBase}${extension}`)];
|
|
4547
|
+
return uniqueBy(candidates, (candidate) => candidate);
|
|
4548
|
+
}
|
|
4513
4549
|
return [resolved];
|
|
4514
4550
|
}
|
|
4515
4551
|
const direct = extensions.map((extension) => path6.posix.normalize(`${resolved}${extension}`));
|
|
@@ -4604,7 +4640,9 @@ async function readNearestGoModulePath(startPath, cache) {
|
|
|
4604
4640
|
}
|
|
4605
4641
|
function rustModuleAlias(repoRelativePath) {
|
|
4606
4642
|
const withoutExt = stripCodeExtension2(normalizeAlias(repoRelativePath));
|
|
4607
|
-
const
|
|
4643
|
+
const srcIdx = withoutExt.lastIndexOf("/src/");
|
|
4644
|
+
const withinCrate = srcIdx >= 0 ? withoutExt.slice(srcIdx + "/src/".length) : withoutExt.replace(/^src\//, "");
|
|
4645
|
+
const trimmed = withinCrate.replace(/\/mod$/i, "");
|
|
4608
4646
|
if (!trimmed || trimmed === "lib" || trimmed === "main") {
|
|
4609
4647
|
return "crate";
|
|
4610
4648
|
}
|
|
@@ -4819,7 +4857,7 @@ function resolveRustAliases(manifest, specifier) {
|
|
|
4819
4857
|
if (!currentAlias) {
|
|
4820
4858
|
return [];
|
|
4821
4859
|
}
|
|
4822
|
-
const currentParts = currentAlias.replace(/^crate
|
|
4860
|
+
const currentParts = currentAlias.replace(/^crate(?:::)?/, "").split("::").filter(Boolean);
|
|
4823
4861
|
if (specifier.startsWith("self::")) {
|
|
4824
4862
|
return [`crate${currentParts.length ? `::${currentParts.join("::")}` : ""}::${specifier.slice("self::".length)}`];
|
|
4825
4863
|
}
|
|
@@ -6610,7 +6648,7 @@ function inferKind(mimeType, filePath, detectionOptions = {}) {
|
|
|
6610
6648
|
if (mimeType === "text/csv" || mimeType === "text/tab-separated-values" || filePath.toLowerCase().endsWith(".csv") || filePath.toLowerCase().endsWith(".tsv")) {
|
|
6611
6649
|
return "csv";
|
|
6612
6650
|
}
|
|
6613
|
-
if (mimeType.startsWith("text/") || isStructuredTextMime(mimeType)
|
|
6651
|
+
if (mimeType.startsWith("text/") || isStructuredTextMime(mimeType)) {
|
|
6614
6652
|
return "text";
|
|
6615
6653
|
}
|
|
6616
6654
|
if (mimeType === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" || filePath.toLowerCase().endsWith(".xlsx")) {
|
|
@@ -6696,125 +6734,30 @@ function guessMimeType(target) {
|
|
|
6696
6734
|
if (extension === ".ts" || extension === ".tsx" || extension === ".mts" || extension === ".cts") {
|
|
6697
6735
|
return "text/typescript";
|
|
6698
6736
|
}
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
return "text/plain";
|
|
6705
|
-
}
|
|
6706
|
-
return "application/octet-stream";
|
|
6707
|
-
}
|
|
6708
|
-
var KNOWN_TEXT_DOTFILE_NAMES = /* @__PURE__ */ new Set([
|
|
6709
|
-
".gitignore",
|
|
6710
|
-
".gitattributes",
|
|
6711
|
-
".gitkeep",
|
|
6712
|
-
".gitmodules",
|
|
6713
|
-
".editorconfig",
|
|
6714
|
-
".npmrc",
|
|
6715
|
-
".yarnrc",
|
|
6716
|
-
".prettierignore",
|
|
6717
|
-
".prettierrc",
|
|
6718
|
-
".dockerignore",
|
|
6719
|
-
".eslintignore",
|
|
6720
|
-
".eslintrc",
|
|
6721
|
-
".nvmrc",
|
|
6722
|
-
".node-version",
|
|
6723
|
-
".python-version",
|
|
6724
|
-
".ruby-version",
|
|
6725
|
-
".tool-versions"
|
|
6726
|
-
]);
|
|
6727
|
-
var KNOWN_TEXT_BASENAMES = /* @__PURE__ */ new Set([
|
|
6728
|
-
"readme",
|
|
6729
|
-
"license",
|
|
6730
|
-
"licence",
|
|
6731
|
-
"copying",
|
|
6732
|
-
"unlicense",
|
|
6733
|
-
"notice",
|
|
6734
|
-
"authors",
|
|
6735
|
-
"contributors",
|
|
6736
|
-
"patents",
|
|
6737
|
-
"maintainers",
|
|
6738
|
-
"owners",
|
|
6739
|
-
"codeowners",
|
|
6740
|
-
"changelog",
|
|
6741
|
-
"changes",
|
|
6742
|
-
"history",
|
|
6743
|
-
"news",
|
|
6744
|
-
"todo",
|
|
6745
|
-
"install",
|
|
6746
|
-
"dockerfile",
|
|
6747
|
-
"containerfile",
|
|
6748
|
-
"makefile",
|
|
6749
|
-
"gnumakefile",
|
|
6750
|
-
"rakefile",
|
|
6751
|
-
"gemfile",
|
|
6752
|
-
"procfile",
|
|
6753
|
-
"jenkinsfile",
|
|
6754
|
-
"vagrantfile",
|
|
6755
|
-
"brewfile",
|
|
6756
|
-
"go.mod",
|
|
6757
|
-
"go.sum",
|
|
6758
|
-
"go.work",
|
|
6759
|
-
"go.work.sum",
|
|
6760
|
-
"cargo.lock",
|
|
6761
|
-
"pipfile",
|
|
6762
|
-
"pipfile.lock",
|
|
6763
|
-
"poetry.lock",
|
|
6764
|
-
"uv.lock",
|
|
6765
|
-
"py.typed",
|
|
6766
|
-
"package-lock.json",
|
|
6767
|
-
"yarn.lock",
|
|
6768
|
-
"pnpm-lock.yaml",
|
|
6769
|
-
"composer.lock",
|
|
6770
|
-
"requirements.txt"
|
|
6771
|
-
]);
|
|
6772
|
-
var KNOWN_TEXT_BASENAME_PREFIXES = ["license", "licence", "copying", "unlicense", "readme", "changelog", "dockerfile", "containerfile"];
|
|
6773
|
-
var KNOWN_TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
6774
|
-
".toml",
|
|
6775
|
-
".lock",
|
|
6776
|
-
".tmpl",
|
|
6777
|
-
".template",
|
|
6778
|
-
".mustache",
|
|
6779
|
-
".hbs",
|
|
6780
|
-
".handlebars",
|
|
6781
|
-
".ejs",
|
|
6782
|
-
".njk",
|
|
6783
|
-
".liquid",
|
|
6784
|
-
".vim",
|
|
6785
|
-
".typed",
|
|
6786
|
-
".env",
|
|
6787
|
-
".properties",
|
|
6788
|
-
".ini",
|
|
6789
|
-
".cfg",
|
|
6790
|
-
".conf",
|
|
6791
|
-
".config",
|
|
6792
|
-
".bazel",
|
|
6793
|
-
".bzl",
|
|
6794
|
-
".bat",
|
|
6795
|
-
".cmd"
|
|
6796
|
-
]);
|
|
6797
|
-
function isKnownTextPath(target) {
|
|
6798
|
-
const basename = path12.basename(target).toLowerCase();
|
|
6799
|
-
if (KNOWN_TEXT_DOTFILE_NAMES.has(basename)) {
|
|
6800
|
-
return true;
|
|
6801
|
-
}
|
|
6802
|
-
if (basename === ".env" || basename.startsWith(".env.")) {
|
|
6803
|
-
return true;
|
|
6804
|
-
}
|
|
6805
|
-
if (KNOWN_TEXT_BASENAMES.has(basename)) {
|
|
6806
|
-
return true;
|
|
6737
|
+
return mime.lookup(target) || "application/octet-stream";
|
|
6738
|
+
}
|
|
6739
|
+
function refineBinaryKindWithBytes(absolutePath, currentKind, bytes) {
|
|
6740
|
+
if (currentKind !== "binary") {
|
|
6741
|
+
return currentKind;
|
|
6807
6742
|
}
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6743
|
+
const sniffSlice = bytes.length > 4096 ? bytes.subarray(0, 4096) : bytes;
|
|
6744
|
+
return isText(absolutePath, sniffSlice) ? "text" : currentKind;
|
|
6745
|
+
}
|
|
6746
|
+
async function refineBinaryKindWithContentSniff(absolutePath, currentKind) {
|
|
6747
|
+
if (currentKind !== "binary") {
|
|
6748
|
+
return currentKind;
|
|
6812
6749
|
}
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6750
|
+
let handle;
|
|
6751
|
+
try {
|
|
6752
|
+
handle = await fs11.open(absolutePath, "r");
|
|
6753
|
+
const chunk = Buffer.alloc(4096);
|
|
6754
|
+
const { bytesRead } = await handle.read(chunk, 0, chunk.length, 0);
|
|
6755
|
+
return refineBinaryKindWithBytes(absolutePath, currentKind, chunk.subarray(0, bytesRead));
|
|
6756
|
+
} catch {
|
|
6757
|
+
return currentKind;
|
|
6758
|
+
} finally {
|
|
6759
|
+
await handle?.close().catch(() => void 0);
|
|
6816
6760
|
}
|
|
6817
|
-
return false;
|
|
6818
6761
|
}
|
|
6819
6762
|
function sourceGroupIdFor(prepared) {
|
|
6820
6763
|
const originKey = prepared.originType === "url" ? prepared.url ?? prepared.title : prepared.originalPath ?? prepared.title;
|
|
@@ -7666,6 +7609,7 @@ async function collectDirectoryFiles(rootDir, inputDir, repoRoot, options) {
|
|
|
7666
7609
|
sourceKind = "chat_export";
|
|
7667
7610
|
}
|
|
7668
7611
|
}
|
|
7612
|
+
sourceKind = await refineBinaryKindWithContentSniff(absolutePath, sourceKind);
|
|
7669
7613
|
const sourceClass = sourceClassForRelativePath(relativePath, options);
|
|
7670
7614
|
if (!supportedDirectoryKind(sourceKind)) {
|
|
7671
7615
|
skipped.push({ path: toPosix(path12.relative(rootDir, absolutePath)), reason: `unsupported_kind:${sourceKind}` });
|
|
@@ -8287,7 +8231,7 @@ async function prepareFileInputs(rootDir, absoluteInput, repoRoot, sourceClass)
|
|
|
8287
8231
|
}
|
|
8288
8232
|
const mimeType = guessMimeType(absoluteInput);
|
|
8289
8233
|
const detectionOptions = await localCodeDetectionOptions(absoluteInput, payloadBytes);
|
|
8290
|
-
const sourceKind = inferKind(mimeType, absoluteInput, detectionOptions);
|
|
8234
|
+
const sourceKind = refineBinaryKindWithBytes(absoluteInput, inferKind(mimeType, absoluteInput, detectionOptions), payloadBytes);
|
|
8291
8235
|
const language = inferCodeLanguage(absoluteInput, mimeType, detectionOptions);
|
|
8292
8236
|
const storedExtension = path12.extname(absoluteInput) || `.${mime.extension(mimeType) || "bin"}`;
|
|
8293
8237
|
let title;
|
|
@@ -9071,6 +9015,7 @@ async function importInbox(rootDir, inputDir) {
|
|
|
9071
9015
|
sourceKind = "chat_export";
|
|
9072
9016
|
}
|
|
9073
9017
|
}
|
|
9018
|
+
sourceKind = await refineBinaryKindWithContentSniff(absolutePath, sourceKind);
|
|
9074
9019
|
if (!isSupportedInboxKind(sourceKind)) {
|
|
9075
9020
|
skipped.push({ path: toPosix(path12.relative(rootDir, absolutePath)), reason: `unsupported_kind:${sourceKind}` });
|
|
9076
9021
|
continue;
|
|
@@ -9268,6 +9213,7 @@ import { z as z7 } from "zod";
|
|
|
9268
9213
|
|
|
9269
9214
|
// src/analysis.ts
|
|
9270
9215
|
import path14 from "path";
|
|
9216
|
+
import nlp from "compromise";
|
|
9271
9217
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
9272
9218
|
import { z as z2 } from "zod";
|
|
9273
9219
|
var ANALYSIS_FORMAT_VERSION = 7;
|
|
@@ -9345,11 +9291,31 @@ function extractTopTerms(text, count) {
|
|
|
9345
9291
|
return [...frequency.entries()].sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0])).slice(0, count).map(([token]) => token);
|
|
9346
9292
|
}
|
|
9347
9293
|
function extractEntities(text, count) {
|
|
9348
|
-
const
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9294
|
+
const candidates = [];
|
|
9295
|
+
try {
|
|
9296
|
+
const doc = nlp(text);
|
|
9297
|
+
const segments = [
|
|
9298
|
+
doc.match("#ProperNoun+").out("array"),
|
|
9299
|
+
doc.people().out("array"),
|
|
9300
|
+
doc.places().out("array"),
|
|
9301
|
+
doc.organizations().out("array"),
|
|
9302
|
+
doc.topics().out("array")
|
|
9303
|
+
];
|
|
9304
|
+
for (const segment of segments) {
|
|
9305
|
+
for (const term of segment) {
|
|
9306
|
+
const normalized = normalizeWhitespace(term);
|
|
9307
|
+
if (normalized) {
|
|
9308
|
+
candidates.push(normalized);
|
|
9309
|
+
}
|
|
9310
|
+
}
|
|
9311
|
+
}
|
|
9312
|
+
} catch {
|
|
9313
|
+
}
|
|
9314
|
+
if (candidates.length === 0) {
|
|
9315
|
+
const matches = text.match(/\b[A-Z][A-Za-z0-9-]+(?:\s+[A-Z][A-Za-z0-9-]+){0,2}\b/g) ?? [];
|
|
9316
|
+
candidates.push(...matches.map((value) => normalizeWhitespace(value)));
|
|
9317
|
+
}
|
|
9318
|
+
return uniqueBy(candidates, (value) => value.toLowerCase()).slice(0, count);
|
|
9353
9319
|
}
|
|
9354
9320
|
function detectPolarity(text) {
|
|
9355
9321
|
if (/\b(no|not|never|cannot|can't|won't|without)\b/i.test(text)) {
|
|
@@ -11068,15 +11034,37 @@ function graphAdjacency(graph) {
|
|
|
11068
11034
|
}
|
|
11069
11035
|
return adjacency;
|
|
11070
11036
|
}
|
|
11037
|
+
var NODE_TYPE_PRIORITY = {
|
|
11038
|
+
concept: 6,
|
|
11039
|
+
entity: 5,
|
|
11040
|
+
source: 4,
|
|
11041
|
+
module: 3,
|
|
11042
|
+
symbol: 2,
|
|
11043
|
+
rationale: 1
|
|
11044
|
+
};
|
|
11045
|
+
function nodeTypePriority(type) {
|
|
11046
|
+
return NODE_TYPE_PRIORITY[type] ?? 0;
|
|
11047
|
+
}
|
|
11048
|
+
function compareLabelCandidates(left, right) {
|
|
11049
|
+
const priorityDelta = nodeTypePriority(right.type) - nodeTypePriority(left.type);
|
|
11050
|
+
if (priorityDelta !== 0) {
|
|
11051
|
+
return priorityDelta;
|
|
11052
|
+
}
|
|
11053
|
+
const degreeDelta = (right.degree ?? 0) - (left.degree ?? 0);
|
|
11054
|
+
if (degreeDelta !== 0) {
|
|
11055
|
+
return degreeDelta;
|
|
11056
|
+
}
|
|
11057
|
+
return left.id.localeCompare(right.id);
|
|
11058
|
+
}
|
|
11071
11059
|
function resolveNode(graph, target) {
|
|
11072
11060
|
const normalized = normalizeTarget(target);
|
|
11073
11061
|
const byId = nodeById(graph);
|
|
11074
11062
|
if (byId.has(target)) {
|
|
11075
11063
|
return byId.get(target);
|
|
11076
11064
|
}
|
|
11077
|
-
const
|
|
11078
|
-
if (
|
|
11079
|
-
return
|
|
11065
|
+
const labelMatches = graph.nodes.filter((node) => normalizeTarget(node.label) === normalized || normalizeTarget(node.id) === normalized);
|
|
11066
|
+
if (labelMatches.length) {
|
|
11067
|
+
return labelMatches.sort(compareLabelCandidates)[0];
|
|
11080
11068
|
}
|
|
11081
11069
|
const pages = graph.pages.map((page) => ({
|
|
11082
11070
|
page,
|
|
@@ -11085,7 +11073,7 @@ function resolveNode(graph, target) {
|
|
|
11085
11073
|
if (pages[0]) {
|
|
11086
11074
|
return primaryNodeForPage(graph, pages[0].page);
|
|
11087
11075
|
}
|
|
11088
|
-
return graph.nodes.map((node) => ({ node, score: Math.max(scoreMatch(target, node.label), scoreMatch(target, node.id)) })).filter((item) => item.score > 0).sort((left, right) => right.score - left.score || left.node
|
|
11076
|
+
return graph.nodes.map((node) => ({ node, score: Math.max(scoreMatch(target, node.label), scoreMatch(target, node.id)) })).filter((item) => item.score > 0).sort((left, right) => right.score - left.score || compareLabelCandidates(left.node, right.node))[0]?.node;
|
|
11089
11077
|
}
|
|
11090
11078
|
function communityLabel(graph, communityId) {
|
|
11091
11079
|
if (!communityId) {
|
|
@@ -17860,6 +17848,10 @@ function extractClaimSectionLines(content) {
|
|
|
17860
17848
|
}
|
|
17861
17849
|
return found ? claimLines : null;
|
|
17862
17850
|
}
|
|
17851
|
+
function isClaimPlaceholderBullet(line) {
|
|
17852
|
+
const trimmed = line.trim();
|
|
17853
|
+
return /^-\s+No\s+claims\s+extracted\.?$/i.test(trimmed);
|
|
17854
|
+
}
|
|
17863
17855
|
function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sourceProjects) {
|
|
17864
17856
|
const manifestMap = new Map(manifests.map((manifest) => [manifest.sourceId, manifest]));
|
|
17865
17857
|
const pageMap2 = new Map(graph.pages.map((page) => [page.id, page]));
|
|
@@ -17907,7 +17899,9 @@ function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sour
|
|
|
17907
17899
|
const content = await fs19.readFile(absolutePath, "utf8");
|
|
17908
17900
|
const claimLines = extractClaimSectionLines(content);
|
|
17909
17901
|
if (claimLines !== null) {
|
|
17910
|
-
const uncited = claimLines.filter(
|
|
17902
|
+
const uncited = claimLines.filter(
|
|
17903
|
+
(line) => line.startsWith("- ") && !line.includes("[source:") && !isClaimPlaceholderBullet(line)
|
|
17904
|
+
);
|
|
17911
17905
|
if (uncited.length) {
|
|
17912
17906
|
findings.push({
|
|
17913
17907
|
severity: "warning",
|
|
@@ -18022,7 +18016,7 @@ async function bootstrapDemo(rootDir, input) {
|
|
|
18022
18016
|
}
|
|
18023
18017
|
|
|
18024
18018
|
// src/mcp.ts
|
|
18025
|
-
var SERVER_VERSION = "0.6.
|
|
18019
|
+
var SERVER_VERSION = "0.6.7";
|
|
18026
18020
|
async function createMcpServer(rootDir) {
|
|
18027
18021
|
const server = new McpServer({
|
|
18028
18022
|
name: "swarmvault",
|
|
@@ -21115,14 +21109,9 @@ async function startGraphServer(rootDir, port, options = {}) {
|
|
|
21115
21109
|
response.end(JSON.stringify({ error: "Missing explain target." }));
|
|
21116
21110
|
return;
|
|
21117
21111
|
}
|
|
21118
|
-
|
|
21119
|
-
|
|
21120
|
-
|
|
21121
|
-
response.end(JSON.stringify(result));
|
|
21122
|
-
} catch (error) {
|
|
21123
|
-
response.writeHead(404, { "content-type": "application/json" });
|
|
21124
|
-
response.end(JSON.stringify({ error: error instanceof Error ? error.message : `Could not resolve graph target: ${target2}` }));
|
|
21125
|
-
}
|
|
21112
|
+
const result = await explainGraphVault(rootDir, target2);
|
|
21113
|
+
response.writeHead(200, { "content-type": "application/json" });
|
|
21114
|
+
response.end(JSON.stringify(result));
|
|
21126
21115
|
return;
|
|
21127
21116
|
}
|
|
21128
21117
|
if (url.pathname === "/api/search") {
|
|
@@ -21261,7 +21250,8 @@ async function startGraphServer(rootDir, port, options = {}) {
|
|
|
21261
21250
|
const message = error instanceof Error ? error.message : String(error);
|
|
21262
21251
|
console.error(`[viewer] ${request.method ?? "GET"} ${url.pathname} failed: ${message}`);
|
|
21263
21252
|
if (!response.headersSent) {
|
|
21264
|
-
|
|
21253
|
+
const status = /not found|could not resolve|cannot resolve/i.test(message) ? 404 : 500;
|
|
21254
|
+
response.writeHead(status, { "content-type": "application/json" });
|
|
21265
21255
|
response.end(JSON.stringify({ error: message }));
|
|
21266
21256
|
} else {
|
|
21267
21257
|
response.end();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmvaultai/engine",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"description": "Core engine for SwarmVault: ingest, compile, query, lint, and provider abstractions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -44,10 +44,12 @@
|
|
|
44
44
|
"@mozilla/readability": "^0.6.0",
|
|
45
45
|
"@vscode/tree-sitter-wasm": "^0.3.1",
|
|
46
46
|
"chokidar": "^4.0.3",
|
|
47
|
+
"compromise": "^14.14.4",
|
|
47
48
|
"csv-parse": "^6.2.1",
|
|
48
49
|
"fflate": "^0.8.2",
|
|
49
50
|
"gray-matter": "^4.0.3",
|
|
50
51
|
"ignore": "^7.0.5",
|
|
52
|
+
"istextorbinary": "^9.5.0",
|
|
51
53
|
"jsdom": "^27.0.0",
|
|
52
54
|
"mailparser": "^3.9.8",
|
|
53
55
|
"mammoth": "^1.12.0",
|