@swarmvaultai/engine 0.2.1 → 0.2.2
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.d.ts +10 -2
- package/dist/index.js +318 -49
- package/dist/viewer/assets/index-BHjjw4rU.css +1 -0
- package/dist/viewer/assets/{index-Csm8eB3P.js → index-DxKn2KOc.js} +23 -23
- package/dist/viewer/index.html +2 -2
- package/dist/viewer/lib.d.ts +11 -0
- package/package.json +1 -1
- package/dist/viewer/assets/index-DUJ6MWHL.css +0 -1
package/dist/index.js
CHANGED
|
@@ -4481,9 +4481,10 @@ async function analyzeCodeSource(manifest, extractedText, schemaHash) {
|
|
|
4481
4481
|
const language = manifest.language ?? inferCodeLanguage(manifest.originalPath ?? manifest.storedPath, manifest.mimeType) ?? "typescript";
|
|
4482
4482
|
const { code, rationales } = language === "javascript" || language === "jsx" || language === "typescript" || language === "tsx" ? analyzeTypeScriptLikeCode(manifest, extractedText) : await analyzeTreeSitterCode(manifest, extractedText, language);
|
|
4483
4483
|
return {
|
|
4484
|
-
analysisVersion:
|
|
4484
|
+
analysisVersion: 7,
|
|
4485
4485
|
sourceId: manifest.sourceId,
|
|
4486
4486
|
sourceHash: manifest.contentHash,
|
|
4487
|
+
semanticHash: manifest.semanticHash,
|
|
4487
4488
|
extractionHash: manifest.extractionHash,
|
|
4488
4489
|
schemaHash,
|
|
4489
4490
|
title: manifest.title,
|
|
@@ -5208,6 +5209,17 @@ var HARD_REPO_IGNORES = /* @__PURE__ */ new Set([".git", ".venv"]);
|
|
|
5208
5209
|
var PROGRESS_FILE_THRESHOLD = 150;
|
|
5209
5210
|
var PROGRESS_UPDATE_INTERVAL = 100;
|
|
5210
5211
|
var RST_HEADING_MARKERS = /* @__PURE__ */ new Set(["=", "-", "~", "^", '"', "#", "*", "+"]);
|
|
5212
|
+
var MARKDOWN_SEMANTIC_FRONTMATTER_KEYS = [
|
|
5213
|
+
"title",
|
|
5214
|
+
"summary",
|
|
5215
|
+
"description",
|
|
5216
|
+
"aliases",
|
|
5217
|
+
"tags",
|
|
5218
|
+
"authors",
|
|
5219
|
+
"published_at",
|
|
5220
|
+
"canonical_url",
|
|
5221
|
+
"source_type"
|
|
5222
|
+
];
|
|
5211
5223
|
function uniqueStrings(values) {
|
|
5212
5224
|
return [...new Set(values.filter(Boolean))];
|
|
5213
5225
|
}
|
|
@@ -5345,6 +5357,65 @@ function extractedTextForPlainSource(filePath, sourceKind, content) {
|
|
|
5345
5357
|
}
|
|
5346
5358
|
return content;
|
|
5347
5359
|
}
|
|
5360
|
+
function normalizeSemanticMarkdownScalar(value) {
|
|
5361
|
+
if (typeof value !== "string") {
|
|
5362
|
+
return void 0;
|
|
5363
|
+
}
|
|
5364
|
+
const normalized = normalizeWhitespace(value.trim());
|
|
5365
|
+
return normalized || void 0;
|
|
5366
|
+
}
|
|
5367
|
+
function normalizeSemanticMarkdownList(value) {
|
|
5368
|
+
if (!Array.isArray(value)) {
|
|
5369
|
+
return void 0;
|
|
5370
|
+
}
|
|
5371
|
+
const items = uniqueStrings(
|
|
5372
|
+
value.flatMap((item) => typeof item === "string" ? [normalizeWhitespace(item.trim())] : []).filter(Boolean)
|
|
5373
|
+
);
|
|
5374
|
+
return items.length ? items : void 0;
|
|
5375
|
+
}
|
|
5376
|
+
function semanticMarkdownTitle(fallback, content, filePath) {
|
|
5377
|
+
const parsed = matter3(content);
|
|
5378
|
+
const frontmatterTitle = normalizeSemanticMarkdownScalar(parsed.data.title);
|
|
5379
|
+
if (frontmatterTitle) {
|
|
5380
|
+
return frontmatterTitle;
|
|
5381
|
+
}
|
|
5382
|
+
return titleFromText(fallback, parsed.content, filePath);
|
|
5383
|
+
}
|
|
5384
|
+
function semanticMarkdownContent(content) {
|
|
5385
|
+
const parsed = matter3(content);
|
|
5386
|
+
const body = parsed.content.replace(/\r\n?/g, "\n").trim();
|
|
5387
|
+
const semanticFrontmatter = Object.fromEntries(
|
|
5388
|
+
MARKDOWN_SEMANTIC_FRONTMATTER_KEYS.flatMap((key) => {
|
|
5389
|
+
const value = key === "aliases" || key === "tags" || key === "authors" ? normalizeSemanticMarkdownList(parsed.data[key]) : normalizeSemanticMarkdownScalar(parsed.data[key]);
|
|
5390
|
+
return value === void 0 ? [] : [[key, value]];
|
|
5391
|
+
})
|
|
5392
|
+
);
|
|
5393
|
+
const semanticLines = Object.entries(semanticFrontmatter).map(
|
|
5394
|
+
([key, value]) => `${key}: ${Array.isArray(value) ? value.join(", ") : value}`
|
|
5395
|
+
);
|
|
5396
|
+
const extractedText = [...semanticLines, ...semanticLines.length && body ? [""] : [], body].filter(Boolean).join("\n").trim();
|
|
5397
|
+
return {
|
|
5398
|
+
extractedText,
|
|
5399
|
+
semanticHash: sha256(
|
|
5400
|
+
JSON.stringify({
|
|
5401
|
+
body,
|
|
5402
|
+
frontmatter: semanticFrontmatter
|
|
5403
|
+
})
|
|
5404
|
+
)
|
|
5405
|
+
};
|
|
5406
|
+
}
|
|
5407
|
+
function finalizePreparedInput(prepared) {
|
|
5408
|
+
if (prepared.sourceKind !== "markdown") {
|
|
5409
|
+
return prepared;
|
|
5410
|
+
}
|
|
5411
|
+
const semantic = semanticMarkdownContent(prepared.payloadBytes.toString("utf8"));
|
|
5412
|
+
return {
|
|
5413
|
+
...prepared,
|
|
5414
|
+
extractedText: semantic.extractedText,
|
|
5415
|
+
extractionHash: buildExtractionHash(semantic.extractedText, prepared.extractionArtifact),
|
|
5416
|
+
semanticHash: semantic.semanticHash
|
|
5417
|
+
};
|
|
5418
|
+
}
|
|
5348
5419
|
function shouldEmitProgress(totalItems) {
|
|
5349
5420
|
return totalItems >= PROGRESS_FILE_THRESHOLD && Boolean(process.stderr?.isTTY);
|
|
5350
5421
|
}
|
|
@@ -5511,7 +5582,7 @@ function markdownFrontmatter(value) {
|
|
|
5511
5582
|
return matter3.stringify("", normalized).trimEnd().split("\n").concat([""]);
|
|
5512
5583
|
}
|
|
5513
5584
|
function prepareCapturedMarkdownInput(input) {
|
|
5514
|
-
return {
|
|
5585
|
+
return finalizePreparedInput({
|
|
5515
5586
|
title: input.title,
|
|
5516
5587
|
originType: "url",
|
|
5517
5588
|
sourceKind: "markdown",
|
|
@@ -5523,7 +5594,7 @@ function prepareCapturedMarkdownInput(input) {
|
|
|
5523
5594
|
extractedText: input.markdown,
|
|
5524
5595
|
attachments: input.attachments,
|
|
5525
5596
|
logDetails: input.logDetails
|
|
5526
|
-
};
|
|
5597
|
+
});
|
|
5527
5598
|
}
|
|
5528
5599
|
function isPrivateIp(ip) {
|
|
5529
5600
|
if (ip === "::1" || ip.startsWith("fc") || ip.startsWith("fd")) return true;
|
|
@@ -5886,7 +5957,10 @@ async function readManifestByHash(manifestsDir, contentHash) {
|
|
|
5886
5957
|
}
|
|
5887
5958
|
const manifest = await readJsonFile(path12.join(manifestsDir, entry.name));
|
|
5888
5959
|
if (manifest?.contentHash === contentHash) {
|
|
5889
|
-
return
|
|
5960
|
+
return {
|
|
5961
|
+
...manifest,
|
|
5962
|
+
semanticHash: manifest.semanticHash ?? manifest.contentHash
|
|
5963
|
+
};
|
|
5890
5964
|
}
|
|
5891
5965
|
}
|
|
5892
5966
|
return null;
|
|
@@ -5899,7 +5973,10 @@ async function readManifestByOrigin(manifestsDir, prepared) {
|
|
|
5899
5973
|
}
|
|
5900
5974
|
const manifest = await readJsonFile(path12.join(manifestsDir, entry.name));
|
|
5901
5975
|
if (manifest && manifestMatchesOrigin(manifest, prepared)) {
|
|
5902
|
-
return
|
|
5976
|
+
return {
|
|
5977
|
+
...manifest,
|
|
5978
|
+
semanticHash: manifest.semanticHash ?? manifest.contentHash
|
|
5979
|
+
};
|
|
5903
5980
|
}
|
|
5904
5981
|
}
|
|
5905
5982
|
return null;
|
|
@@ -6148,10 +6225,11 @@ async function persistPreparedInput(rootDir, prepared, paths) {
|
|
|
6148
6225
|
await ensureDir(paths.extractsDir);
|
|
6149
6226
|
const attachments = prepared.attachments ?? [];
|
|
6150
6227
|
const contentHash = prepared.contentHash ?? buildCompositeHash(prepared.payloadBytes, attachments);
|
|
6228
|
+
const semanticHash = prepared.semanticHash ?? contentHash;
|
|
6151
6229
|
const extractionHash = prepared.extractionHash ?? buildExtractionHash(prepared.extractedText, prepared.extractionArtifact);
|
|
6152
6230
|
const existingByOrigin = await readManifestByOrigin(paths.manifestsDir, prepared);
|
|
6153
6231
|
const existingByHash = existingByOrigin ? null : await readManifestByHash(paths.manifestsDir, contentHash);
|
|
6154
|
-
if (existingByOrigin && existingByOrigin.contentHash === contentHash && existingByOrigin.extractionHash === extractionHash && existingByOrigin.title === prepared.title && existingByOrigin.sourceKind === prepared.sourceKind && existingByOrigin.sourceType === prepared.sourceType && existingByOrigin.sourceClass === prepared.sourceClass && existingByOrigin.language === prepared.language && existingByOrigin.mimeType === prepared.mimeType && existingByOrigin.repoRelativePath === prepared.repoRelativePath) {
|
|
6232
|
+
if (existingByOrigin && existingByOrigin.contentHash === contentHash && existingByOrigin.semanticHash === semanticHash && existingByOrigin.extractionHash === extractionHash && existingByOrigin.title === prepared.title && existingByOrigin.sourceKind === prepared.sourceKind && existingByOrigin.sourceType === prepared.sourceType && existingByOrigin.sourceClass === prepared.sourceClass && existingByOrigin.language === prepared.language && existingByOrigin.mimeType === prepared.mimeType && existingByOrigin.repoRelativePath === prepared.repoRelativePath) {
|
|
6155
6233
|
return { manifest: existingByOrigin, isNew: false, wasUpdated: false };
|
|
6156
6234
|
}
|
|
6157
6235
|
if (existingByHash) {
|
|
@@ -6209,6 +6287,7 @@ async function persistPreparedInput(rootDir, prepared, paths) {
|
|
|
6209
6287
|
extractionHash,
|
|
6210
6288
|
mimeType: prepared.mimeType,
|
|
6211
6289
|
contentHash,
|
|
6290
|
+
semanticHash,
|
|
6212
6291
|
createdAt: previous?.createdAt ?? now,
|
|
6213
6292
|
updatedAt: now,
|
|
6214
6293
|
attachments: manifestAttachments.length ? manifestAttachments : void 0
|
|
@@ -6523,14 +6602,15 @@ async function prepareFileInput(rootDir, absoluteInput, repoRoot, sourceClass) {
|
|
|
6523
6602
|
let extractedText;
|
|
6524
6603
|
let extractionArtifact;
|
|
6525
6604
|
if (sourceKind === "markdown" || sourceKind === "text" || sourceKind === "code") {
|
|
6526
|
-
|
|
6527
|
-
|
|
6605
|
+
const rawText = payloadBytes.toString("utf8");
|
|
6606
|
+
extractedText = sourceKind === "markdown" ? semanticMarkdownContent(rawText).extractedText : extractedTextForPlainSource(absoluteInput, sourceKind, rawText);
|
|
6607
|
+
title = sourceKind === "markdown" ? semanticMarkdownTitle(path12.basename(absoluteInput, path12.extname(absoluteInput)), rawText, absoluteInput) : titleFromText(path12.basename(absoluteInput, path12.extname(absoluteInput)), extractedText, absoluteInput);
|
|
6528
6608
|
extractionArtifact = createPlainTextExtractionArtifact(sourceKind, mimeType);
|
|
6529
6609
|
} else if (sourceKind === "html") {
|
|
6530
6610
|
const html = payloadBytes.toString("utf8");
|
|
6531
6611
|
const converted = await convertHtmlToMarkdown(html, pathToFileURL(absoluteInput).toString());
|
|
6532
6612
|
title = converted.title;
|
|
6533
|
-
extractedText = converted.markdown;
|
|
6613
|
+
extractedText = semanticMarkdownContent(converted.markdown).extractedText;
|
|
6534
6614
|
extractionArtifact = createHtmlReadabilityExtractionArtifact(sourceKind, mimeType);
|
|
6535
6615
|
} else if (sourceKind === "pdf") {
|
|
6536
6616
|
title = path12.basename(absoluteInput, path12.extname(absoluteInput));
|
|
@@ -6556,7 +6636,7 @@ async function prepareFileInput(rootDir, absoluteInput, repoRoot, sourceClass) {
|
|
|
6556
6636
|
} else {
|
|
6557
6637
|
title = path12.basename(absoluteInput, path12.extname(absoluteInput));
|
|
6558
6638
|
}
|
|
6559
|
-
return {
|
|
6639
|
+
return finalizePreparedInput({
|
|
6560
6640
|
title,
|
|
6561
6641
|
originType: "file",
|
|
6562
6642
|
sourceKind,
|
|
@@ -6570,7 +6650,7 @@ async function prepareFileInput(rootDir, absoluteInput, repoRoot, sourceClass) {
|
|
|
6570
6650
|
extractedText,
|
|
6571
6651
|
extractionArtifact,
|
|
6572
6652
|
extractionHash: buildExtractionHash(extractedText, extractionArtifact)
|
|
6573
|
-
};
|
|
6653
|
+
});
|
|
6574
6654
|
}
|
|
6575
6655
|
async function prepareUrlInput(rootDir, input, options) {
|
|
6576
6656
|
await validateUrlSafety(input);
|
|
@@ -6634,8 +6714,9 @@ async function prepareUrlInput(rootDir, input, options) {
|
|
|
6634
6714
|
const extension = path12.extname(inputUrl.pathname);
|
|
6635
6715
|
storedExtension = extension || `.${mime.extension(mimeType) || "bin"}`;
|
|
6636
6716
|
if (sourceKind === "markdown" || sourceKind === "text" || sourceKind === "code") {
|
|
6637
|
-
|
|
6638
|
-
|
|
6717
|
+
const rawText = payloadBytes.toString("utf8");
|
|
6718
|
+
extractedText = sourceKind === "markdown" ? semanticMarkdownContent(rawText).extractedText : extractedTextForPlainSource(inputUrl.pathname, sourceKind, rawText);
|
|
6719
|
+
title = sourceKind === "markdown" ? semanticMarkdownTitle(title || inputUrl.hostname, rawText, inputUrl.pathname) : titleFromText(title || inputUrl.hostname, extractedText, inputUrl.pathname);
|
|
6639
6720
|
extractionArtifact = createPlainTextExtractionArtifact(sourceKind, mimeType);
|
|
6640
6721
|
if (sourceKind === "markdown" && options.includeAssets) {
|
|
6641
6722
|
const { attachments: remoteAttachments, skippedCount } = await collectRemoteImageAttachments(
|
|
@@ -6677,7 +6758,7 @@ async function prepareUrlInput(rootDir, input, options) {
|
|
|
6677
6758
|
extractionArtifact = extracted.artifact;
|
|
6678
6759
|
}
|
|
6679
6760
|
}
|
|
6680
|
-
return {
|
|
6761
|
+
return finalizePreparedInput({
|
|
6681
6762
|
title,
|
|
6682
6763
|
originType: "url",
|
|
6683
6764
|
sourceKind,
|
|
@@ -6692,7 +6773,7 @@ async function prepareUrlInput(rootDir, input, options) {
|
|
|
6692
6773
|
attachments,
|
|
6693
6774
|
contentHash,
|
|
6694
6775
|
logDetails
|
|
6695
|
-
};
|
|
6776
|
+
});
|
|
6696
6777
|
}
|
|
6697
6778
|
async function collectInboxAttachmentRefs(inputDir, files) {
|
|
6698
6779
|
const refsBySource = /* @__PURE__ */ new Map();
|
|
@@ -6766,7 +6847,7 @@ async function prepareInboxMarkdownInput(absolutePath, attachmentRefs) {
|
|
|
6766
6847
|
);
|
|
6767
6848
|
const rewrittenText = rewriteMarkdownReferences(originalText, replacements);
|
|
6768
6849
|
const extractionArtifact = createPlainTextExtractionArtifact("markdown", "text/markdown");
|
|
6769
|
-
return {
|
|
6850
|
+
return finalizePreparedInput({
|
|
6770
6851
|
title,
|
|
6771
6852
|
originType: "file",
|
|
6772
6853
|
sourceKind: "markdown",
|
|
@@ -6779,7 +6860,7 @@ async function prepareInboxMarkdownInput(absolutePath, attachmentRefs) {
|
|
|
6779
6860
|
extractionHash: buildExtractionHash(rewrittenText, extractionArtifact),
|
|
6780
6861
|
attachments,
|
|
6781
6862
|
contentHash
|
|
6782
|
-
};
|
|
6863
|
+
});
|
|
6783
6864
|
}
|
|
6784
6865
|
async function prepareInboxHtmlInput(absolutePath, attachmentRefs) {
|
|
6785
6866
|
const originalBytes = await fs11.readFile(absolutePath);
|
|
@@ -7021,7 +7102,10 @@ async function listManifests(rootDir) {
|
|
|
7021
7102
|
const manifests = await Promise.all(
|
|
7022
7103
|
entries.filter((entry) => entry.endsWith(".json")).map((entry) => readJsonFile(path12.join(paths.manifestsDir, entry)))
|
|
7023
7104
|
);
|
|
7024
|
-
return manifests.filter((manifest) => Boolean(manifest))
|
|
7105
|
+
return manifests.filter((manifest) => Boolean(manifest)).map((manifest) => ({
|
|
7106
|
+
...manifest,
|
|
7107
|
+
semanticHash: manifest.semanticHash ?? manifest.contentHash
|
|
7108
|
+
}));
|
|
7025
7109
|
}
|
|
7026
7110
|
async function removeManifestBySourceId(rootDir, sourceId) {
|
|
7027
7111
|
const { paths } = await initWorkspace(rootDir);
|
|
@@ -7029,8 +7113,12 @@ async function removeManifestBySourceId(rootDir, sourceId) {
|
|
|
7029
7113
|
if (!manifest) {
|
|
7030
7114
|
return null;
|
|
7031
7115
|
}
|
|
7032
|
-
|
|
7033
|
-
|
|
7116
|
+
const normalizedManifest = {
|
|
7117
|
+
...manifest,
|
|
7118
|
+
semanticHash: manifest.semanticHash ?? manifest.contentHash
|
|
7119
|
+
};
|
|
7120
|
+
await removeManifestArtifacts(rootDir, normalizedManifest, paths);
|
|
7121
|
+
return normalizedManifest;
|
|
7034
7122
|
}
|
|
7035
7123
|
async function readExtractedText(rootDir, manifest) {
|
|
7036
7124
|
if (!manifest.extractedTextPath) {
|
|
@@ -7176,7 +7264,7 @@ import { z as z7 } from "zod";
|
|
|
7176
7264
|
// src/analysis.ts
|
|
7177
7265
|
import path14 from "path";
|
|
7178
7266
|
import { z as z2 } from "zod";
|
|
7179
|
-
var ANALYSIS_FORMAT_VERSION =
|
|
7267
|
+
var ANALYSIS_FORMAT_VERSION = 7;
|
|
7180
7268
|
var sourceAnalysisSchema = z2.object({
|
|
7181
7269
|
title: z2.string().min(1),
|
|
7182
7270
|
summary: z2.string().min(1),
|
|
@@ -7281,6 +7369,7 @@ function heuristicAnalysis(manifest, text, schemaHash) {
|
|
|
7281
7369
|
analysisVersion: ANALYSIS_FORMAT_VERSION,
|
|
7282
7370
|
sourceId: manifest.sourceId,
|
|
7283
7371
|
sourceHash: manifest.contentHash,
|
|
7372
|
+
semanticHash: manifest.semanticHash,
|
|
7284
7373
|
extractionHash: manifest.extractionHash,
|
|
7285
7374
|
schemaHash,
|
|
7286
7375
|
title: deriveTitle(manifest, text),
|
|
@@ -7331,6 +7420,7 @@ ${truncate(text, 18e3)}`
|
|
|
7331
7420
|
analysisVersion: ANALYSIS_FORMAT_VERSION,
|
|
7332
7421
|
sourceId: manifest.sourceId,
|
|
7333
7422
|
sourceHash: manifest.contentHash,
|
|
7423
|
+
semanticHash: manifest.semanticHash,
|
|
7334
7424
|
extractionHash: manifest.extractionHash,
|
|
7335
7425
|
schemaHash: schema.hash,
|
|
7336
7426
|
title: parsed.title,
|
|
@@ -7367,6 +7457,7 @@ function analysisFromVisionExtraction(manifest, extraction, schemaHash) {
|
|
|
7367
7457
|
analysisVersion: ANALYSIS_FORMAT_VERSION,
|
|
7368
7458
|
sourceId: manifest.sourceId,
|
|
7369
7459
|
sourceHash: manifest.contentHash,
|
|
7460
|
+
semanticHash: manifest.semanticHash,
|
|
7370
7461
|
extractionHash: manifest.extractionHash,
|
|
7371
7462
|
schemaHash,
|
|
7372
7463
|
title: extraction.vision.title?.trim() || manifest.title,
|
|
@@ -7405,7 +7496,7 @@ function extractionWarningSummary(manifest, extraction) {
|
|
|
7405
7496
|
async function analyzeSource(manifest, extractedText, provider, paths, schema) {
|
|
7406
7497
|
const cachePath = path14.join(paths.analysesDir, `${manifest.sourceId}.json`);
|
|
7407
7498
|
const cached = await readJsonFile(cachePath);
|
|
7408
|
-
if (cached && cached.analysisVersion === ANALYSIS_FORMAT_VERSION && cached.sourceHash === manifest.
|
|
7499
|
+
if (cached && cached.analysisVersion === ANALYSIS_FORMAT_VERSION && (cached.semanticHash ?? cached.sourceHash) === manifest.semanticHash && cached.extractionHash === manifest.extractionHash && cached.schemaHash === schema.hash) {
|
|
7409
7500
|
return cached;
|
|
7410
7501
|
}
|
|
7411
7502
|
const extraction = await readExtractionArtifact(paths.rootDir, manifest);
|
|
@@ -7422,6 +7513,7 @@ async function analyzeSource(manifest, extractedText, provider, paths, schema) {
|
|
|
7422
7513
|
analysisVersion: ANALYSIS_FORMAT_VERSION,
|
|
7423
7514
|
sourceId: manifest.sourceId,
|
|
7424
7515
|
sourceHash: manifest.contentHash,
|
|
7516
|
+
semanticHash: manifest.semanticHash,
|
|
7425
7517
|
extractionHash: manifest.extractionHash,
|
|
7426
7518
|
schemaHash: schema.hash,
|
|
7427
7519
|
title: manifest.title,
|
|
@@ -7448,6 +7540,7 @@ async function analyzeSource(manifest, extractedText, provider, paths, schema) {
|
|
|
7448
7540
|
analysisVersion: ANALYSIS_FORMAT_VERSION,
|
|
7449
7541
|
sourceId: manifest.sourceId,
|
|
7450
7542
|
sourceHash: manifest.contentHash,
|
|
7543
|
+
semanticHash: manifest.semanticHash,
|
|
7451
7544
|
extractionHash: manifest.extractionHash,
|
|
7452
7545
|
schemaHash: schema.hash,
|
|
7453
7546
|
title: manifest.title,
|
|
@@ -8231,7 +8324,9 @@ async function resolveEmbeddingProvider(rootDir) {
|
|
|
8231
8324
|
}
|
|
8232
8325
|
const provider2 = await createProvider(explicitProviderId, providerConfig, rootDir);
|
|
8233
8326
|
if (!provider2.capabilities.has("embeddings") || typeof provider2.embedTexts !== "function") {
|
|
8234
|
-
throw new Error(
|
|
8327
|
+
throw new Error(
|
|
8328
|
+
`Provider ${provider2.id} does not support required capability "embeddings". Configure tasks.embeddingProvider to use an embedding-capable backend such as ollama or another openai-compatible embedding service.`
|
|
8329
|
+
);
|
|
8235
8330
|
}
|
|
8236
8331
|
return provider2;
|
|
8237
8332
|
}
|
|
@@ -9127,6 +9222,18 @@ function uniqueStrings2(values) {
|
|
|
9127
9222
|
function safeFrontmatter(value) {
|
|
9128
9223
|
return JSON.parse(JSON.stringify(value));
|
|
9129
9224
|
}
|
|
9225
|
+
function sourceHashesForManifest(manifest) {
|
|
9226
|
+
return {
|
|
9227
|
+
sourceHashes: { [manifest.sourceId]: manifest.contentHash },
|
|
9228
|
+
sourceSemanticHashes: { [manifest.sourceId]: manifest.semanticHash }
|
|
9229
|
+
};
|
|
9230
|
+
}
|
|
9231
|
+
function sourceHashFrontmatter(sourceHashes, sourceSemanticHashes) {
|
|
9232
|
+
return {
|
|
9233
|
+
source_hashes: sourceHashes,
|
|
9234
|
+
source_semantic_hashes: sourceSemanticHashes
|
|
9235
|
+
};
|
|
9236
|
+
}
|
|
9130
9237
|
function decoratedTags(baseTags, decorations) {
|
|
9131
9238
|
return uniqueStrings2([
|
|
9132
9239
|
...baseTags,
|
|
@@ -9190,6 +9297,7 @@ function relatedOutputsSection(relatedOutputs) {
|
|
|
9190
9297
|
function buildSourcePage(manifest, analysis, schemaHash, metadata, relatedOutputs = [], modulePage, decorations) {
|
|
9191
9298
|
const relativePath = pagePathFor("source", manifest.sourceId);
|
|
9192
9299
|
const pageId = `source:${manifest.sourceId}`;
|
|
9300
|
+
const { sourceHashes, sourceSemanticHashes } = sourceHashesForManifest(manifest);
|
|
9193
9301
|
const moduleNodeIds = analysis.code ? [analysis.code.moduleId, ...analysis.code.symbols.map((symbol) => symbol.id)] : [];
|
|
9194
9302
|
const nodeIds = [
|
|
9195
9303
|
`source:${manifest.sourceId}`,
|
|
@@ -9222,9 +9330,7 @@ function buildSourcePage(manifest, analysis, schemaHash, metadata, relatedOutput
|
|
|
9222
9330
|
managed_by: metadata.managedBy,
|
|
9223
9331
|
backlinks,
|
|
9224
9332
|
schema_hash: schemaHash,
|
|
9225
|
-
|
|
9226
|
-
[manifest.sourceId]: manifest.contentHash
|
|
9227
|
-
}
|
|
9333
|
+
...sourceHashFrontmatter(sourceHashes, sourceSemanticHashes)
|
|
9228
9334
|
};
|
|
9229
9335
|
const body = [
|
|
9230
9336
|
`# ${analysis.title}`,
|
|
@@ -9287,7 +9393,8 @@ function buildSourcePage(manifest, analysis, schemaHash, metadata, relatedOutput
|
|
|
9287
9393
|
confidence: metadata.confidence,
|
|
9288
9394
|
backlinks,
|
|
9289
9395
|
schemaHash,
|
|
9290
|
-
sourceHashes
|
|
9396
|
+
sourceHashes,
|
|
9397
|
+
sourceSemanticHashes,
|
|
9291
9398
|
relatedPageIds: [...modulePage ? [modulePage.id] : [], ...relatedOutputs.map((page) => page.id)],
|
|
9292
9399
|
relatedNodeIds: moduleNodeIds,
|
|
9293
9400
|
relatedSourceIds: [],
|
|
@@ -9312,6 +9419,7 @@ function buildModulePage(input) {
|
|
|
9312
9419
|
const localModuleBacklinks = input.localModules.map((moduleRef) => moduleRef.page.id);
|
|
9313
9420
|
const relatedOutputs = input.relatedOutputs ?? [];
|
|
9314
9421
|
const backlinks = uniqueStrings2([sourcePage.id, ...localModuleBacklinks, ...relatedOutputs.map((page) => page.id)]);
|
|
9422
|
+
const { sourceHashes, sourceSemanticHashes } = sourceHashesForManifest(manifest);
|
|
9315
9423
|
const importsSection = code.imports.length ? code.imports.map((item) => {
|
|
9316
9424
|
const localModule = item.resolvedSourceId ? input.localModules.find((moduleRef) => moduleRef.sourceId === item.resolvedSourceId && moduleRef.reExport === item.reExport) : void 0;
|
|
9317
9425
|
const importedBits = [
|
|
@@ -9355,9 +9463,7 @@ function buildModulePage(input) {
|
|
|
9355
9463
|
managed_by: metadata.managedBy,
|
|
9356
9464
|
backlinks,
|
|
9357
9465
|
schema_hash: schemaHash,
|
|
9358
|
-
|
|
9359
|
-
[manifest.sourceId]: manifest.contentHash
|
|
9360
|
-
},
|
|
9466
|
+
...sourceHashFrontmatter(sourceHashes, sourceSemanticHashes),
|
|
9361
9467
|
related_page_ids: uniqueStrings2([sourcePage.id, ...localModuleBacklinks, ...relatedOutputs.map((page) => page.id)]),
|
|
9362
9468
|
related_node_ids: [],
|
|
9363
9469
|
related_source_ids: uniqueStrings2([
|
|
@@ -9433,7 +9539,8 @@ function buildModulePage(input) {
|
|
|
9433
9539
|
confidence: metadata.confidence,
|
|
9434
9540
|
backlinks,
|
|
9435
9541
|
schemaHash,
|
|
9436
|
-
sourceHashes
|
|
9542
|
+
sourceHashes,
|
|
9543
|
+
sourceSemanticHashes,
|
|
9437
9544
|
relatedPageIds: uniqueStrings2([sourcePage.id, ...localModuleBacklinks, ...relatedOutputs.map((page) => page.id)]),
|
|
9438
9545
|
relatedNodeIds: [],
|
|
9439
9546
|
relatedSourceIds: uniqueStrings2([
|
|
@@ -9449,7 +9556,7 @@ function buildModulePage(input) {
|
|
|
9449
9556
|
content: matter5.stringify(body, frontmatter)
|
|
9450
9557
|
};
|
|
9451
9558
|
}
|
|
9452
|
-
function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHashes, schemaHash, metadata, relativePath, relatedOutputs = [], decorations) {
|
|
9559
|
+
function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHashes, sourceSemanticHashes, schemaHash, metadata, relativePath, relatedOutputs = [], decorations) {
|
|
9453
9560
|
const slug = slugify(name);
|
|
9454
9561
|
const pageId = `${kind}:${slug}`;
|
|
9455
9562
|
const sourceIds = sourceAnalyses.map((item) => item.sourceId);
|
|
@@ -9473,7 +9580,7 @@ function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHash
|
|
|
9473
9580
|
managed_by: metadata.managedBy,
|
|
9474
9581
|
backlinks: otherPages,
|
|
9475
9582
|
schema_hash: schemaHash,
|
|
9476
|
-
|
|
9583
|
+
...sourceHashFrontmatter(sourceHashes, sourceSemanticHashes)
|
|
9477
9584
|
};
|
|
9478
9585
|
const body = [
|
|
9479
9586
|
`# ${name}`,
|
|
@@ -9511,6 +9618,7 @@ function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHash
|
|
|
9511
9618
|
backlinks: otherPages,
|
|
9512
9619
|
schemaHash,
|
|
9513
9620
|
sourceHashes,
|
|
9621
|
+
sourceSemanticHashes,
|
|
9514
9622
|
relatedPageIds: relatedOutputs.map((page) => page.id),
|
|
9515
9623
|
relatedNodeIds: [],
|
|
9516
9624
|
relatedSourceIds: [],
|
|
@@ -9551,6 +9659,7 @@ function buildIndexPage(pages, schemaHash, metadata, projectPages = []) {
|
|
|
9551
9659
|
"backlinks: []",
|
|
9552
9660
|
`schema_hash: ${schemaHash}`,
|
|
9553
9661
|
"source_hashes: {}",
|
|
9662
|
+
"source_semantic_hashes: {}",
|
|
9554
9663
|
"---",
|
|
9555
9664
|
"",
|
|
9556
9665
|
"# SwarmVault Index",
|
|
@@ -9614,7 +9723,8 @@ function buildSectionIndex(kind, pages, schemaHash, metadata, projectIds = []) {
|
|
|
9614
9723
|
managed_by: metadata.managedBy,
|
|
9615
9724
|
backlinks: [],
|
|
9616
9725
|
schema_hash: schemaHash,
|
|
9617
|
-
source_hashes: {}
|
|
9726
|
+
source_hashes: {},
|
|
9727
|
+
source_semantic_hashes: {}
|
|
9618
9728
|
}
|
|
9619
9729
|
);
|
|
9620
9730
|
}
|
|
@@ -9910,6 +10020,7 @@ function buildGraphReportPage(input) {
|
|
|
9910
10020
|
backlinks: [],
|
|
9911
10021
|
schema_hash: input.schemaHash,
|
|
9912
10022
|
source_hashes: {},
|
|
10023
|
+
source_semantic_hashes: {},
|
|
9913
10024
|
related_page_ids: relatedPageIds,
|
|
9914
10025
|
related_node_ids: relatedNodeIds,
|
|
9915
10026
|
related_source_ids: relatedSourceIds
|
|
@@ -10025,6 +10136,7 @@ function buildGraphReportPage(input) {
|
|
|
10025
10136
|
backlinks: [],
|
|
10026
10137
|
schemaHash: input.schemaHash,
|
|
10027
10138
|
sourceHashes: {},
|
|
10139
|
+
sourceSemanticHashes: {},
|
|
10028
10140
|
relatedPageIds,
|
|
10029
10141
|
relatedNodeIds,
|
|
10030
10142
|
relatedSourceIds,
|
|
@@ -10068,6 +10180,7 @@ function buildCommunitySummaryPage(input) {
|
|
|
10068
10180
|
backlinks: ["graph:report"],
|
|
10069
10181
|
schema_hash: input.schemaHash,
|
|
10070
10182
|
source_hashes: {},
|
|
10183
|
+
source_semantic_hashes: {},
|
|
10071
10184
|
related_page_ids: uniqueStrings2(["graph:report", ...communityPageIds]),
|
|
10072
10185
|
related_node_ids: input.community.nodeIds,
|
|
10073
10186
|
related_source_ids: relatedSourceIds
|
|
@@ -10107,6 +10220,7 @@ function buildCommunitySummaryPage(input) {
|
|
|
10107
10220
|
backlinks: ["graph:report"],
|
|
10108
10221
|
schemaHash: input.schemaHash,
|
|
10109
10222
|
sourceHashes: {},
|
|
10223
|
+
sourceSemanticHashes: {},
|
|
10110
10224
|
relatedPageIds: uniqueStrings2(["graph:report", ...communityPageIds]),
|
|
10111
10225
|
relatedNodeIds: input.community.nodeIds,
|
|
10112
10226
|
relatedSourceIds,
|
|
@@ -10143,7 +10257,8 @@ function buildProjectsIndex(projectPages, schemaHash, metadata) {
|
|
|
10143
10257
|
managed_by: metadata.managedBy,
|
|
10144
10258
|
backlinks: [],
|
|
10145
10259
|
schema_hash: schemaHash,
|
|
10146
|
-
source_hashes: {}
|
|
10260
|
+
source_hashes: {},
|
|
10261
|
+
source_semantic_hashes: {}
|
|
10147
10262
|
}
|
|
10148
10263
|
);
|
|
10149
10264
|
}
|
|
@@ -10195,7 +10310,8 @@ function buildProjectIndex(input) {
|
|
|
10195
10310
|
managed_by: input.metadata.managedBy,
|
|
10196
10311
|
backlinks: [],
|
|
10197
10312
|
schema_hash: input.schemaHash,
|
|
10198
|
-
source_hashes: {}
|
|
10313
|
+
source_hashes: {},
|
|
10314
|
+
source_semantic_hashes: {}
|
|
10199
10315
|
}
|
|
10200
10316
|
);
|
|
10201
10317
|
}
|
|
@@ -10226,6 +10342,7 @@ function buildOutputPage(input) {
|
|
|
10226
10342
|
backlinks,
|
|
10227
10343
|
schema_hash: input.schemaHash,
|
|
10228
10344
|
source_hashes: {},
|
|
10345
|
+
source_semantic_hashes: {},
|
|
10229
10346
|
related_page_ids: relatedPageIds,
|
|
10230
10347
|
related_node_ids: relatedNodeIds,
|
|
10231
10348
|
related_source_ids: relatedSourceIds,
|
|
@@ -10250,6 +10367,7 @@ function buildOutputPage(input) {
|
|
|
10250
10367
|
backlinks,
|
|
10251
10368
|
schemaHash: input.schemaHash,
|
|
10252
10369
|
sourceHashes: {},
|
|
10370
|
+
sourceSemanticHashes: {},
|
|
10253
10371
|
relatedPageIds,
|
|
10254
10372
|
relatedNodeIds,
|
|
10255
10373
|
relatedSourceIds,
|
|
@@ -10352,6 +10470,7 @@ function buildExploreHubPage(input) {
|
|
|
10352
10470
|
backlinks,
|
|
10353
10471
|
schema_hash: input.schemaHash,
|
|
10354
10472
|
source_hashes: {},
|
|
10473
|
+
source_semantic_hashes: {},
|
|
10355
10474
|
related_page_ids: relatedPageIds,
|
|
10356
10475
|
related_node_ids: relatedNodeIds,
|
|
10357
10476
|
related_source_ids: relatedSourceIds,
|
|
@@ -10376,6 +10495,7 @@ function buildExploreHubPage(input) {
|
|
|
10376
10495
|
backlinks,
|
|
10377
10496
|
schemaHash: input.schemaHash,
|
|
10378
10497
|
sourceHashes: {},
|
|
10498
|
+
sourceSemanticHashes: {},
|
|
10379
10499
|
relatedPageIds,
|
|
10380
10500
|
relatedNodeIds,
|
|
10381
10501
|
relatedSourceIds,
|
|
@@ -10674,6 +10794,9 @@ function normalizeSourceHashes(value) {
|
|
|
10674
10794
|
Object.entries(value).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string")
|
|
10675
10795
|
);
|
|
10676
10796
|
}
|
|
10797
|
+
function normalizeSourceSemanticHashes(value) {
|
|
10798
|
+
return normalizeSourceHashes(value);
|
|
10799
|
+
}
|
|
10677
10800
|
function normalizePageStatus(value, fallback = "active") {
|
|
10678
10801
|
return value === "draft" || value === "candidate" || value === "active" || value === "archived" ? value : fallback;
|
|
10679
10802
|
}
|
|
@@ -10802,6 +10925,7 @@ function parseStoredPage(relativePath, content, defaults = {}) {
|
|
|
10802
10925
|
backlinks,
|
|
10803
10926
|
schemaHash: typeof parsed.data.schema_hash === "string" ? parsed.data.schema_hash : "",
|
|
10804
10927
|
sourceHashes: normalizeSourceHashes(parsed.data.source_hashes),
|
|
10928
|
+
sourceSemanticHashes: normalizeSourceSemanticHashes(parsed.data.source_semantic_hashes),
|
|
10805
10929
|
relatedPageIds,
|
|
10806
10930
|
relatedNodeIds,
|
|
10807
10931
|
relatedSourceIds,
|
|
@@ -10855,6 +10979,7 @@ async function loadInsightPages(wikiDir) {
|
|
|
10855
10979
|
backlinks,
|
|
10856
10980
|
schemaHash: typeof parsed.data.schema_hash === "string" ? parsed.data.schema_hash : "",
|
|
10857
10981
|
sourceHashes: normalizeSourceHashes(parsed.data.source_hashes),
|
|
10982
|
+
sourceSemanticHashes: normalizeSourceSemanticHashes(parsed.data.source_semantic_hashes),
|
|
10858
10983
|
relatedPageIds,
|
|
10859
10984
|
relatedNodeIds,
|
|
10860
10985
|
relatedSourceIds,
|
|
@@ -10955,6 +11080,7 @@ async function loadSavedOutputPages(wikiDir) {
|
|
|
10955
11080
|
backlinks,
|
|
10956
11081
|
schemaHash: typeof parsed.data.schema_hash === "string" ? parsed.data.schema_hash : "",
|
|
10957
11082
|
sourceHashes: normalizeSourceHashes(parsed.data.source_hashes),
|
|
11083
|
+
sourceSemanticHashes: normalizeSourceSemanticHashes(parsed.data.source_semantic_hashes),
|
|
10958
11084
|
relatedPageIds,
|
|
10959
11085
|
relatedNodeIds,
|
|
10960
11086
|
relatedSourceIds,
|
|
@@ -12431,11 +12557,13 @@ function aggregateItems(analyses, kind) {
|
|
|
12431
12557
|
name: item.name,
|
|
12432
12558
|
descriptions: [],
|
|
12433
12559
|
sourceAnalyses: [],
|
|
12434
|
-
sourceHashes: {}
|
|
12560
|
+
sourceHashes: {},
|
|
12561
|
+
sourceSemanticHashes: {}
|
|
12435
12562
|
};
|
|
12436
12563
|
existing.descriptions.push(item.description);
|
|
12437
12564
|
existing.sourceAnalyses.push(analysis);
|
|
12438
12565
|
existing.sourceHashes[analysis.sourceId] = analysis.sourceHash;
|
|
12566
|
+
existing.sourceSemanticHashes[analysis.sourceId] = analysis.semanticHash;
|
|
12439
12567
|
grouped.set(key, existing);
|
|
12440
12568
|
}
|
|
12441
12569
|
}
|
|
@@ -12457,6 +12585,7 @@ function emptyGraphPage(input) {
|
|
|
12457
12585
|
backlinks: [],
|
|
12458
12586
|
schemaHash: input.schemaHash,
|
|
12459
12587
|
sourceHashes: input.sourceHashes,
|
|
12588
|
+
sourceSemanticHashes: input.sourceSemanticHashes ?? {},
|
|
12460
12589
|
relatedPageIds: [],
|
|
12461
12590
|
relatedNodeIds: [],
|
|
12462
12591
|
relatedSourceIds: [],
|
|
@@ -12621,6 +12750,7 @@ async function syncVaultArtifacts(rootDir, input) {
|
|
|
12621
12750
|
nodeIds: [analysis.code.moduleId, ...analysis.code.symbols.map((symbol) => symbol.id)],
|
|
12622
12751
|
schemaHash: sourceSchemaHash,
|
|
12623
12752
|
sourceHashes: { [manifest.sourceId]: manifest.contentHash },
|
|
12753
|
+
sourceSemanticHashes: { [manifest.sourceId]: manifest.semanticHash },
|
|
12624
12754
|
confidence: 1
|
|
12625
12755
|
}) : null;
|
|
12626
12756
|
const preview = emptyGraphPage({
|
|
@@ -12639,6 +12769,7 @@ async function syncVaultArtifacts(rootDir, input) {
|
|
|
12639
12769
|
],
|
|
12640
12770
|
schemaHash: sourceSchemaHash,
|
|
12641
12771
|
sourceHashes: { [manifest.sourceId]: manifest.contentHash },
|
|
12772
|
+
sourceSemanticHashes: { [manifest.sourceId]: manifest.semanticHash },
|
|
12642
12773
|
confidence: 1
|
|
12643
12774
|
});
|
|
12644
12775
|
const sourceRecord = await buildManagedGraphPage(
|
|
@@ -12755,6 +12886,7 @@ async function syncVaultArtifacts(rootDir, input) {
|
|
|
12755
12886
|
aggregate.descriptions,
|
|
12756
12887
|
aggregate.sourceAnalyses,
|
|
12757
12888
|
aggregate.sourceHashes,
|
|
12889
|
+
aggregate.sourceSemanticHashes,
|
|
12758
12890
|
schemaHash,
|
|
12759
12891
|
metadata,
|
|
12760
12892
|
relativePath,
|
|
@@ -13002,6 +13134,7 @@ async function syncVaultArtifacts(rootDir, input) {
|
|
|
13002
13134
|
projectConfigHash: projectConfigHash(config),
|
|
13003
13135
|
analyses: Object.fromEntries(input.analyses.map((analysis) => [analysis.sourceId, analysisSignature(analysis)])),
|
|
13004
13136
|
sourceHashes: Object.fromEntries(input.manifests.map((manifest) => [manifest.sourceId, manifest.contentHash])),
|
|
13137
|
+
sourceSemanticHashes: Object.fromEntries(input.manifests.map((manifest) => [manifest.sourceId, manifest.semanticHash])),
|
|
13005
13138
|
sourceProjects: input.sourceProjects,
|
|
13006
13139
|
outputHashes: input.outputHashes,
|
|
13007
13140
|
insightHashes: input.insightHashes,
|
|
@@ -13467,6 +13600,7 @@ function emptyCompileState() {
|
|
|
13467
13600
|
projectConfigHash: "",
|
|
13468
13601
|
analyses: {},
|
|
13469
13602
|
sourceHashes: {},
|
|
13603
|
+
sourceSemanticHashes: {},
|
|
13470
13604
|
sourceProjects: {},
|
|
13471
13605
|
outputHashes: {},
|
|
13472
13606
|
insightHashes: {},
|
|
@@ -13896,7 +14030,8 @@ async function initVault(rootDir, options = {}) {
|
|
|
13896
14030
|
managed_by: "human",
|
|
13897
14031
|
backlinks: [],
|
|
13898
14032
|
schema_hash: "",
|
|
13899
|
-
source_hashes: {}
|
|
14033
|
+
source_hashes: {},
|
|
14034
|
+
source_semantic_hashes: {}
|
|
13900
14035
|
}
|
|
13901
14036
|
)
|
|
13902
14037
|
);
|
|
@@ -13919,7 +14054,8 @@ async function initVault(rootDir, options = {}) {
|
|
|
13919
14054
|
managed_by: "system",
|
|
13920
14055
|
backlinks: [],
|
|
13921
14056
|
schema_hash: "",
|
|
13922
|
-
source_hashes: {}
|
|
14057
|
+
source_hashes: {},
|
|
14058
|
+
source_semantic_hashes: {}
|
|
13923
14059
|
})
|
|
13924
14060
|
);
|
|
13925
14061
|
await writeFileIfChanged(
|
|
@@ -13941,7 +14077,8 @@ async function initVault(rootDir, options = {}) {
|
|
|
13941
14077
|
managed_by: "system",
|
|
13942
14078
|
backlinks: [],
|
|
13943
14079
|
schema_hash: "",
|
|
13944
|
-
source_hashes: {}
|
|
14080
|
+
source_hashes: {},
|
|
14081
|
+
source_semantic_hashes: {}
|
|
13945
14082
|
})
|
|
13946
14083
|
);
|
|
13947
14084
|
if (options.obsidian) {
|
|
@@ -13982,7 +14119,7 @@ async function compileVault(rootDir, options = {}) {
|
|
|
13982
14119
|
);
|
|
13983
14120
|
const nextProjectConfigHash = projectConfigHash(config);
|
|
13984
14121
|
const projectConfigChanged = !previousState || previousState.projectConfigHash !== nextProjectConfigHash;
|
|
13985
|
-
const previousSourceHashes = previousState?.sourceHashes ?? {};
|
|
14122
|
+
const previousSourceHashes = previousState?.sourceSemanticHashes ?? previousState?.sourceHashes ?? {};
|
|
13986
14123
|
const previousAnalyses = previousState?.analyses ?? {};
|
|
13987
14124
|
const previousSourceProjects = previousState?.sourceProjects ?? {};
|
|
13988
14125
|
const previousOutputHashes = previousState?.outputHashes ?? {};
|
|
@@ -13997,7 +14134,7 @@ async function compileVault(rootDir, options = {}) {
|
|
|
13997
14134
|
const dirty = [];
|
|
13998
14135
|
const clean = [];
|
|
13999
14136
|
for (const manifest of manifests) {
|
|
14000
|
-
const hashChanged = previousSourceHashes[manifest.sourceId] !== manifest.
|
|
14137
|
+
const hashChanged = previousSourceHashes[manifest.sourceId] !== manifest.semanticHash;
|
|
14001
14138
|
const noAnalysis = !previousAnalyses[manifest.sourceId];
|
|
14002
14139
|
const projectId = sourceProjects[manifest.sourceId] ?? null;
|
|
14003
14140
|
const projectChanged = (previousSourceProjects[manifest.sourceId] ?? null) !== projectId;
|
|
@@ -14707,9 +14844,11 @@ function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sour
|
|
|
14707
14844
|
relatedPageIds: [page.id]
|
|
14708
14845
|
});
|
|
14709
14846
|
}
|
|
14710
|
-
|
|
14847
|
+
const freshnessHashes = Object.keys(page.sourceSemanticHashes).length ? page.sourceSemanticHashes : page.sourceHashes;
|
|
14848
|
+
for (const [sourceId, knownHash] of Object.entries(freshnessHashes)) {
|
|
14711
14849
|
const manifest = manifestMap.get(sourceId);
|
|
14712
|
-
|
|
14850
|
+
const manifestHash = manifest?.semanticHash ?? manifest?.contentHash;
|
|
14851
|
+
if (manifestHash && manifestHash !== knownHash) {
|
|
14713
14852
|
findings.push({
|
|
14714
14853
|
severity: "warning",
|
|
14715
14854
|
code: "stale_page",
|
|
@@ -14848,7 +14987,7 @@ async function bootstrapDemo(rootDir, input) {
|
|
|
14848
14987
|
}
|
|
14849
14988
|
|
|
14850
14989
|
// src/mcp.ts
|
|
14851
|
-
var SERVER_VERSION = "0.2.
|
|
14990
|
+
var SERVER_VERSION = "0.2.2";
|
|
14852
14991
|
async function createMcpServer(rootDir) {
|
|
14853
14992
|
const server = new McpServer({
|
|
14854
14993
|
name: "swarmvault",
|
|
@@ -16221,6 +16360,124 @@ import { promisify } from "util";
|
|
|
16221
16360
|
import matter10 from "gray-matter";
|
|
16222
16361
|
import mime2 from "mime-types";
|
|
16223
16362
|
|
|
16363
|
+
// src/graph-presentation.ts
|
|
16364
|
+
var OVERVIEW_THRESHOLD = 5e3;
|
|
16365
|
+
var OVERVIEW_NODE_BUDGET = 1500;
|
|
16366
|
+
function nodePriority(node, pinnedNodeIds) {
|
|
16367
|
+
return [pinnedNodeIds.has(node.id) ? 0 : 1, -(node.degree ?? 0), -(node.bridgeScore ?? 0), node.label, node.id];
|
|
16368
|
+
}
|
|
16369
|
+
function compareTuples(left, right) {
|
|
16370
|
+
const length = Math.max(left.length, right.length);
|
|
16371
|
+
for (let index = 0; index < length; index += 1) {
|
|
16372
|
+
const leftValue = left[index];
|
|
16373
|
+
const rightValue = right[index];
|
|
16374
|
+
if (leftValue === rightValue) {
|
|
16375
|
+
continue;
|
|
16376
|
+
}
|
|
16377
|
+
if (typeof leftValue === "number" && typeof rightValue === "number") {
|
|
16378
|
+
return leftValue - rightValue;
|
|
16379
|
+
}
|
|
16380
|
+
return String(leftValue ?? "").localeCompare(String(rightValue ?? ""));
|
|
16381
|
+
}
|
|
16382
|
+
return 0;
|
|
16383
|
+
}
|
|
16384
|
+
function survivingHyperedges(hyperedges, sampledNodeIds) {
|
|
16385
|
+
return hyperedges.filter((hyperedge) => hyperedge.nodeIds.filter((nodeId) => sampledNodeIds.has(nodeId)).length >= 2);
|
|
16386
|
+
}
|
|
16387
|
+
function pinnedNodeIdsForReport(report) {
|
|
16388
|
+
if (!report) {
|
|
16389
|
+
return /* @__PURE__ */ new Set();
|
|
16390
|
+
}
|
|
16391
|
+
return /* @__PURE__ */ new Set([
|
|
16392
|
+
...report.godNodes.map((node) => node.nodeId),
|
|
16393
|
+
...report.bridgeNodes.map((node) => node.nodeId),
|
|
16394
|
+
...report.surprisingConnections.flatMap((connection) => [connection.sourceNodeId, connection.targetNodeId])
|
|
16395
|
+
]);
|
|
16396
|
+
}
|
|
16397
|
+
function sampleGraphNodes(graph, report, nodeBudget = OVERVIEW_NODE_BUDGET) {
|
|
16398
|
+
const pinned = pinnedNodeIdsForReport(report);
|
|
16399
|
+
const nodeById2 = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
16400
|
+
const selected = new Set([...pinned].filter((nodeId) => nodeById2.has(nodeId)));
|
|
16401
|
+
const sortedCommunities2 = [...graph.communities ?? []].sort((left, right) => {
|
|
16402
|
+
const leftNodes = left.nodeIds.map((nodeId) => nodeById2.get(nodeId)).filter((node) => Boolean(node));
|
|
16403
|
+
const rightNodes = right.nodeIds.map((nodeId) => nodeById2.get(nodeId)).filter((node) => Boolean(node));
|
|
16404
|
+
const leftFirstParty = leftNodes.filter((node) => node.sourceClass === "first_party").length;
|
|
16405
|
+
const rightFirstParty = rightNodes.filter((node) => node.sourceClass === "first_party").length;
|
|
16406
|
+
return compareTuples(
|
|
16407
|
+
[-leftFirstParty, -leftNodes.length, left.label, left.id],
|
|
16408
|
+
[-rightFirstParty, -rightNodes.length, right.label, right.id]
|
|
16409
|
+
);
|
|
16410
|
+
});
|
|
16411
|
+
for (const community of sortedCommunities2) {
|
|
16412
|
+
const communityNodes = community.nodeIds.map((nodeId) => nodeById2.get(nodeId)).filter((node) => Boolean(node)).sort((left, right) => compareTuples(nodePriority(left, pinned), nodePriority(right, pinned)));
|
|
16413
|
+
for (const node of communityNodes) {
|
|
16414
|
+
if (selected.size >= nodeBudget && !pinned.has(node.id)) {
|
|
16415
|
+
break;
|
|
16416
|
+
}
|
|
16417
|
+
selected.add(node.id);
|
|
16418
|
+
}
|
|
16419
|
+
if (selected.size >= nodeBudget) {
|
|
16420
|
+
break;
|
|
16421
|
+
}
|
|
16422
|
+
}
|
|
16423
|
+
if (selected.size < nodeBudget) {
|
|
16424
|
+
for (const node of [...graph.nodes].sort((left, right) => compareTuples(nodePriority(left, pinned), nodePriority(right, pinned)))) {
|
|
16425
|
+
if (selected.size >= nodeBudget && !pinned.has(node.id)) {
|
|
16426
|
+
break;
|
|
16427
|
+
}
|
|
16428
|
+
selected.add(node.id);
|
|
16429
|
+
}
|
|
16430
|
+
}
|
|
16431
|
+
return selected;
|
|
16432
|
+
}
|
|
16433
|
+
function buildViewerGraphArtifact(graph, options = {}) {
|
|
16434
|
+
const threshold = options.threshold ?? OVERVIEW_THRESHOLD;
|
|
16435
|
+
const nodeBudget = options.nodeBudget ?? OVERVIEW_NODE_BUDGET;
|
|
16436
|
+
const totalCommunities = graph.communities?.length ?? 0;
|
|
16437
|
+
if (options.full || graph.nodes.length <= threshold) {
|
|
16438
|
+
return {
|
|
16439
|
+
...graph,
|
|
16440
|
+
presentation: {
|
|
16441
|
+
mode: "full",
|
|
16442
|
+
threshold,
|
|
16443
|
+
nodeBudget,
|
|
16444
|
+
totalNodes: graph.nodes.length,
|
|
16445
|
+
displayedNodes: graph.nodes.length,
|
|
16446
|
+
totalEdges: graph.edges.length,
|
|
16447
|
+
displayedEdges: graph.edges.length,
|
|
16448
|
+
totalCommunities,
|
|
16449
|
+
displayedCommunities: totalCommunities
|
|
16450
|
+
}
|
|
16451
|
+
};
|
|
16452
|
+
}
|
|
16453
|
+
const sampledNodeIds = sampleGraphNodes(graph, options.report, nodeBudget);
|
|
16454
|
+
const nodes = graph.nodes.filter((node) => sampledNodeIds.has(node.id));
|
|
16455
|
+
const edges = graph.edges.filter((edge) => sampledNodeIds.has(edge.source) && sampledNodeIds.has(edge.target));
|
|
16456
|
+
const hyperedges = survivingHyperedges(graph.hyperedges ?? [], sampledNodeIds);
|
|
16457
|
+
const communities = (graph.communities ?? []).map((community) => ({
|
|
16458
|
+
...community,
|
|
16459
|
+
nodeIds: community.nodeIds.filter((nodeId) => sampledNodeIds.has(nodeId))
|
|
16460
|
+
})).filter((community) => community.nodeIds.length > 0);
|
|
16461
|
+
return {
|
|
16462
|
+
...graph,
|
|
16463
|
+
nodes,
|
|
16464
|
+
edges,
|
|
16465
|
+
hyperedges,
|
|
16466
|
+
communities,
|
|
16467
|
+
presentation: {
|
|
16468
|
+
mode: "overview",
|
|
16469
|
+
threshold,
|
|
16470
|
+
nodeBudget,
|
|
16471
|
+
totalNodes: graph.nodes.length,
|
|
16472
|
+
displayedNodes: nodes.length,
|
|
16473
|
+
totalEdges: graph.edges.length,
|
|
16474
|
+
displayedEdges: edges.length,
|
|
16475
|
+
totalCommunities,
|
|
16476
|
+
displayedCommunities: communities.length
|
|
16477
|
+
}
|
|
16478
|
+
};
|
|
16479
|
+
}
|
|
16480
|
+
|
|
16224
16481
|
// src/watch.ts
|
|
16225
16482
|
import path26 from "path";
|
|
16226
16483
|
import process3 from "process";
|
|
@@ -16686,7 +16943,7 @@ async function ensureViewerDist(viewerDistDir) {
|
|
|
16686
16943
|
await execFileAsync("pnpm", ["build"], { cwd: viewerProjectDir });
|
|
16687
16944
|
}
|
|
16688
16945
|
}
|
|
16689
|
-
async function startGraphServer(rootDir, port) {
|
|
16946
|
+
async function startGraphServer(rootDir, port, options = {}) {
|
|
16690
16947
|
const { config, paths } = await loadVaultConfig(rootDir);
|
|
16691
16948
|
const effectivePort = port ?? config.viewer.port;
|
|
16692
16949
|
await ensureViewerDist(paths.viewerDistDir);
|
|
@@ -16698,8 +16955,16 @@ async function startGraphServer(rootDir, port) {
|
|
|
16698
16955
|
response.end(JSON.stringify({ error: "Graph artifact not found. Run `swarmvault compile` first." }));
|
|
16699
16956
|
return;
|
|
16700
16957
|
}
|
|
16958
|
+
const graph = await readJsonFile(paths.graphPath);
|
|
16959
|
+
if (!graph) {
|
|
16960
|
+
response.writeHead(404, { "content-type": "application/json" });
|
|
16961
|
+
response.end(JSON.stringify({ error: "Graph artifact not found. Run `swarmvault compile` first." }));
|
|
16962
|
+
return;
|
|
16963
|
+
}
|
|
16964
|
+
const reportPath = path27.join(paths.wikiDir, "graph", "report.json");
|
|
16965
|
+
const report = await readJsonFile(reportPath) ?? null;
|
|
16701
16966
|
response.writeHead(200, { "content-type": "application/json" });
|
|
16702
|
-
response.end(
|
|
16967
|
+
response.end(JSON.stringify(buildViewerGraphArtifact(graph, { report, full: options.full ?? false })));
|
|
16703
16968
|
return;
|
|
16704
16969
|
}
|
|
16705
16970
|
if (url.pathname === "/api/graph/query") {
|
|
@@ -16875,7 +17140,7 @@ async function startGraphServer(rootDir, port) {
|
|
|
16875
17140
|
}
|
|
16876
17141
|
};
|
|
16877
17142
|
}
|
|
16878
|
-
async function exportGraphHtml(rootDir, outputPath) {
|
|
17143
|
+
async function exportGraphHtml(rootDir, outputPath, options = {}) {
|
|
16879
17144
|
const { paths } = await loadVaultConfig(rootDir);
|
|
16880
17145
|
const graph = await readJsonFile(paths.graphPath);
|
|
16881
17146
|
if (!graph) {
|
|
@@ -16919,7 +17184,11 @@ async function exportGraphHtml(rootDir, outputPath) {
|
|
|
16919
17184
|
const script = await fs22.readFile(scriptPath, "utf8");
|
|
16920
17185
|
const style = stylePath && await fileExists(stylePath) ? await fs22.readFile(stylePath, "utf8") : "";
|
|
16921
17186
|
const report = await readJsonFile(path27.join(paths.wikiDir, "graph", "report.json"));
|
|
16922
|
-
const embeddedData = JSON.stringify(
|
|
17187
|
+
const embeddedData = JSON.stringify(
|
|
17188
|
+
{ graph: buildViewerGraphArtifact(graph, { report, full: options.full ?? false }), pages: pages.filter(Boolean), report },
|
|
17189
|
+
null,
|
|
17190
|
+
2
|
|
17191
|
+
).replace(/</g, "\\u003c");
|
|
16923
17192
|
const html = [
|
|
16924
17193
|
"<!doctype html>",
|
|
16925
17194
|
'<html lang="en">',
|