@swarmvaultai/engine 0.7.27 → 0.7.29

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.
File without changes
File without changes
File without changes
package/dist/index.js CHANGED
@@ -952,6 +952,37 @@ function loadVisNetworkJs() {
952
952
  }
953
953
  return _visNetworkJs;
954
954
  }
955
+ function hexToObsidianColor(hex) {
956
+ return { a: 1, rgb: Number.parseInt(hex.replace("#", ""), 16) };
957
+ }
958
+ var OBSIDIAN_PROPERTY_TYPES = {
959
+ page_id: "text",
960
+ kind: "text",
961
+ title: "text",
962
+ tags: "tags",
963
+ aliases: "aliases",
964
+ source_ids: "multitext",
965
+ project_ids: "multitext",
966
+ node_ids: "multitext",
967
+ freshness: "text",
968
+ status: "text",
969
+ confidence: "number",
970
+ created_at: "datetime",
971
+ updated_at: "datetime",
972
+ compiled_from: "multitext",
973
+ managed_by: "text",
974
+ backlinks: "multitext",
975
+ schema_hash: "text",
976
+ source_class: "text",
977
+ source_type: "text",
978
+ language: "text",
979
+ graph_community: "text",
980
+ degree: "number",
981
+ bridge_score: "number",
982
+ is_god_node: "checkbox",
983
+ community: "text",
984
+ cssclasses: "multitext"
985
+ };
955
986
  var NODE_COLORS = {
956
987
  source: "#f59e0b",
957
988
  module: "#fb7185",
@@ -1680,6 +1711,25 @@ function connectionsSection(nodeIds, adjacency, nodesById, wikilinkTarget) {
1680
1711
  }
1681
1712
  return lines;
1682
1713
  }
1714
+ function typedLinkFrontmatter(nodeIds, adjacency, nodesById, wikilinkTarget) {
1715
+ const byRelation = /* @__PURE__ */ new Map();
1716
+ const seen = /* @__PURE__ */ new Set();
1717
+ for (const nodeId of nodeIds) {
1718
+ for (const entry of adjacency.get(nodeId) ?? []) {
1719
+ const key = `${entry.neighborId}:${entry.relation}`;
1720
+ if (seen.has(key)) continue;
1721
+ seen.add(key);
1722
+ const neighbor = nodesById.get(entry.neighborId);
1723
+ if (!neighbor) continue;
1724
+ const target = wikilinkTarget.get(entry.neighborId);
1725
+ if (!target) continue;
1726
+ const bucket = byRelation.get(entry.relation) ?? [];
1727
+ bucket.push(`[[${target}|${neighbor.label}]]`);
1728
+ byRelation.set(entry.relation, bucket);
1729
+ }
1730
+ }
1731
+ return Object.fromEntries(byRelation);
1732
+ }
1683
1733
  async function exportObsidianVault(rootDir, outputDir) {
1684
1734
  const graph = await loadGraph(rootDir);
1685
1735
  const { paths } = await loadVaultConfig(rootDir);
@@ -1741,6 +1791,9 @@ async function exportObsidianVault(rootDir, outputDir) {
1741
1791
  if (primaryNode.communityId) {
1742
1792
  data.graph_community = primaryNode.communityId;
1743
1793
  }
1794
+ data.degree = primaryNode.degree ?? 0;
1795
+ data.bridge_score = primaryNode.bridgeScore ?? 0;
1796
+ data.is_god_node = primaryNode.isGodNode ?? false;
1744
1797
  const title = data.title ?? "";
1745
1798
  const nodeAliases = pageNodes.map((n) => n.label).filter((label) => label.toLowerCase() !== title.toLowerCase());
1746
1799
  const existingAliases = Array.isArray(data.aliases) ? data.aliases : [];
@@ -1748,6 +1801,15 @@ async function exportObsidianVault(rootDir, outputDir) {
1748
1801
  if (mergedAliases.length > 0) {
1749
1802
  data.aliases = mergedAliases;
1750
1803
  }
1804
+ const typedLinks = typedLinkFrontmatter(
1805
+ pageNodes.map((n) => n.id),
1806
+ adjacency,
1807
+ nodesById,
1808
+ wikilinkTarget
1809
+ );
1810
+ for (const [relation, links] of Object.entries(typedLinks)) {
1811
+ data[relation] = links;
1812
+ }
1751
1813
  }
1752
1814
  let outputContent = matter.stringify(parsed.content, data);
1753
1815
  if (pageNodes.length > 0) {
@@ -1781,11 +1843,19 @@ ${connLines.join("\n")}
1781
1843
  community: node.communityId ?? null,
1782
1844
  confidence: node.confidence ?? null,
1783
1845
  source_class: node.sourceClass ?? null,
1784
- tags: node.tags ?? []
1846
+ degree: node.degree ?? 0,
1847
+ bridge_score: node.bridgeScore ?? 0,
1848
+ is_god_node: node.isGodNode ?? false,
1849
+ tags: node.tags ?? [],
1850
+ cssclasses: ["swarmvault", `sv-${node.type}`]
1785
1851
  };
1786
1852
  if (aliases.length > 0) {
1787
1853
  frontmatter.aliases = aliases;
1788
1854
  }
1855
+ const orphanTypedLinks = typedLinkFrontmatter([node.id], adjacency, nodesById, wikilinkTarget);
1856
+ for (const [relation, links] of Object.entries(orphanTypedLinks)) {
1857
+ frontmatter[relation] = links;
1858
+ }
1789
1859
  const lines = [`# ${node.label}`, ""];
1790
1860
  const connLines = connectionsSection([node.id], adjacency, nodesById, wikilinkTarget);
1791
1861
  if (connLines.length > 0) {
@@ -1887,10 +1957,19 @@ ${connLines.join("\n")}
1887
1957
  {}
1888
1958
  )
1889
1959
  );
1890
- const colorGroups = projectIds.map((pid, index) => ({
1960
+ const nodeTypeGroups = [
1961
+ { query: "tag:#source", color: hexToObsidianColor("#f59e0b") },
1962
+ { query: "tag:#module", color: hexToObsidianColor("#fb7185") },
1963
+ { query: "tag:#concept", color: hexToObsidianColor("#0ea5e9") },
1964
+ { query: "tag:#entity", color: hexToObsidianColor("#22c55e") },
1965
+ { query: "tag:#rationale", color: hexToObsidianColor("#14b8a6") },
1966
+ { query: "tag:#symbol", color: hexToObsidianColor("#8b5cf6") }
1967
+ ];
1968
+ const projectColorGroups = projectIds.map((pid, index) => ({
1891
1969
  query: `tag:#project/${pid}`,
1892
- color: ["#0ea5e9", "#22c55e", "#f59e0b", "#8b5cf6", "#fb7185", "#14b8a6"][index % 6]
1970
+ color: hexToObsidianColor(["#0ea5e9", "#22c55e", "#f59e0b", "#8b5cf6", "#fb7185", "#14b8a6"][index % 6])
1893
1971
  }));
1972
+ const colorGroups = [...nodeTypeGroups, ...projectColorGroups];
1894
1973
  await fs2.writeFile(
1895
1974
  path2.join(obsidianDir, "app.json"),
1896
1975
  JSON.stringify(
@@ -1914,7 +1993,48 @@ ${connLines.join("\n")}
1914
1993
  ),
1915
1994
  "utf8"
1916
1995
  );
1917
- fileCount += 3;
1996
+ await fs2.writeFile(path2.join(obsidianDir, "types.json"), JSON.stringify({ types: OBSIDIAN_PROPERTY_TYPES }, null, 2), "utf8");
1997
+ fileCount += 4;
1998
+ const dashboardDir = path2.join(resolvedOutputDir, "graph", "dashboards");
1999
+ await ensureDir(dashboardDir);
2000
+ const dvPages = [
2001
+ {
2002
+ name: "sources-by-confidence",
2003
+ title: "Sources by Confidence",
2004
+ query: "TABLE confidence, source_class, updated_at FROM #source SORT confidence DESC"
2005
+ },
2006
+ {
2007
+ name: "concepts-index",
2008
+ title: "Concepts Index",
2009
+ query: "TABLE degree, graph_community FROM #concept SORT degree DESC"
2010
+ },
2011
+ {
2012
+ name: "stale-pages",
2013
+ title: "Stale Pages",
2014
+ query: 'TABLE freshness, updated_at FROM "" WHERE freshness = "stale"'
2015
+ },
2016
+ {
2017
+ name: "god-nodes",
2018
+ title: "God Nodes",
2019
+ query: 'TABLE degree, bridge_score FROM "" WHERE is_god_node = true SORT degree DESC'
2020
+ }
2021
+ ];
2022
+ for (const dv of dvPages) {
2023
+ const dvFrontmatter = {
2024
+ title: dv.title,
2025
+ kind: "dashboard",
2026
+ tags: ["dashboard", "dataview"],
2027
+ cssclasses: ["swarmvault", "sv-dashboard"]
2028
+ };
2029
+ const dvBody = `# ${dv.title}
2030
+
2031
+ \`\`\`dataview
2032
+ ${dv.query}
2033
+ \`\`\`
2034
+ `;
2035
+ await fs2.writeFile(path2.join(dashboardDir, `${dv.name}.md`), matter.stringify(dvBody, dvFrontmatter), "utf8");
2036
+ fileCount++;
2037
+ }
1918
2038
  return { format: "obsidian", outputPath: resolvedOutputDir, fileCount };
1919
2039
  }
1920
2040
  async function exportObsidianCanvas(rootDir, outputPath) {
@@ -1929,6 +2049,7 @@ async function exportObsidianCanvas(rootDir, outputPath) {
1929
2049
  const GROUP_PAD = 50;
1930
2050
  const GRID_COLS = 3;
1931
2051
  const GROUP_GAP = 100;
2052
+ const pageById2 = graphPageById(graph);
1932
2053
  const canvasNodes = [];
1933
2054
  const canvasEdges = [];
1934
2055
  const nodeCanvasId = /* @__PURE__ */ new Map();
@@ -1980,19 +2101,33 @@ async function exportObsidianCanvas(rootDir, outputPath) {
1980
2101
  const nodeY = groupY + GROUP_PAD + 30 + innerRow * (NODE_HEIGHT + NODE_PAD_Y);
1981
2102
  const canvasId = `node-${node.id}`;
1982
2103
  nodeCanvasId.set(node.id, canvasId);
1983
- const communityLabel2 = community.id === "community:unassigned" ? "Unassigned" : community.label;
1984
- canvasNodes.push({
1985
- id: canvasId,
1986
- type: "text",
1987
- text: `**${node.label}**
2104
+ const page = node.pageId ? pageById2.get(node.pageId) : void 0;
2105
+ if (page) {
2106
+ canvasNodes.push({
2107
+ id: canvasId,
2108
+ type: "file",
2109
+ file: page.path,
2110
+ x: nodeX,
2111
+ y: nodeY,
2112
+ width: NODE_WIDTH,
2113
+ height: NODE_HEIGHT,
2114
+ color: COLORS[communityIndex % COLORS.length]
2115
+ });
2116
+ } else {
2117
+ const communityLabel2 = community.id === "community:unassigned" ? "Unassigned" : community.label;
2118
+ canvasNodes.push({
2119
+ id: canvasId,
2120
+ type: "text",
2121
+ text: `**${node.label}**
1988
2122
  Type: ${node.type}
1989
2123
  Community: ${communityLabel2}`,
1990
- x: nodeX,
1991
- y: nodeY,
1992
- width: NODE_WIDTH,
1993
- height: NODE_HEIGHT,
1994
- color: COLORS[communityIndex % COLORS.length]
1995
- });
2124
+ x: nodeX,
2125
+ y: nodeY,
2126
+ width: NODE_WIDTH,
2127
+ height: NODE_HEIGHT,
2128
+ color: COLORS[communityIndex % COLORS.length]
2129
+ });
2130
+ }
1996
2131
  });
1997
2132
  });
1998
2133
  for (const edge of graph.edges) {
@@ -2003,6 +2138,10 @@ Community: ${communityLabel2}`,
2003
2138
  id: `edge-${edge.id}`,
2004
2139
  fromNode: fromId,
2005
2140
  toNode: toId,
2141
+ fromSide: "right",
2142
+ toSide: "left",
2143
+ fromEnd: "none",
2144
+ toEnd: "arrow",
2006
2145
  label: edge.relation
2007
2146
  });
2008
2147
  }
@@ -15423,6 +15562,9 @@ function sourceHashFrontmatter(sourceHashes, sourceSemanticHashes) {
15423
15562
  source_semantic_hashes: sourceSemanticHashes
15424
15563
  };
15425
15564
  }
15565
+ function cssclassesFor(kind) {
15566
+ return ["swarmvault", `sv-${kind.replace(/_/g, "-")}`];
15567
+ }
15426
15568
  function decoratedTags(baseTags, decorations) {
15427
15569
  return uniqueStrings2([
15428
15570
  ...baseTags,
@@ -15516,6 +15658,7 @@ function buildSourcePage(manifest, analysis, schemaHash, metadata, relatedOutput
15516
15658
  const frontmatter = {
15517
15659
  page_id: pageId,
15518
15660
  kind: "source",
15661
+ cssclasses: cssclassesFor("source"),
15519
15662
  title: analysis.title,
15520
15663
  ...manifest.sourceType ? { source_type: manifest.sourceType } : {},
15521
15664
  ...manifest.sourceClass ? { source_class: manifest.sourceClass } : {},
@@ -15667,6 +15810,7 @@ function buildModulePage(input) {
15667
15810
  const frontmatter = {
15668
15811
  page_id: pageId,
15669
15812
  kind: "module",
15813
+ cssclasses: cssclassesFor("module"),
15670
15814
  title,
15671
15815
  ...manifest.sourceClass ? { source_class: manifest.sourceClass } : {},
15672
15816
  tags: decoratedTags(["module", "code", code.language], { projectIds: input.projectIds, extraTags: input.extraTags }),
@@ -15784,6 +15928,7 @@ function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHash
15784
15928
  const frontmatter = {
15785
15929
  page_id: pageId,
15786
15930
  kind,
15931
+ cssclasses: cssclassesFor(kind),
15787
15932
  title: name,
15788
15933
  ...decorations?.sourceClass ? { source_class: decorations.sourceClass } : {},
15789
15934
  tags: decoratedTags(metadata.status === "candidate" ? [kind, "candidate"] : [kind], decorations),
@@ -15938,6 +16083,7 @@ function buildSectionIndex(kind, pages, schemaHash, metadata, projectIds = []) {
15938
16083
  {
15939
16084
  page_id: `${kind}:index`,
15940
16085
  kind: "index",
16086
+ cssclasses: cssclassesFor("index"),
15941
16087
  title,
15942
16088
  tags: decoratedTags(["index", kind], { projectIds }),
15943
16089
  source_ids: [],
@@ -16305,6 +16451,7 @@ function buildGraphReportPage(input) {
16305
16451
  const frontmatter = {
16306
16452
  page_id: pageId,
16307
16453
  kind: "graph_report",
16454
+ cssclasses: cssclassesFor("graph_report"),
16308
16455
  title: "Graph Report",
16309
16456
  tags: ["graph", "report"],
16310
16457
  source_ids: relatedSourceIds,
@@ -16465,6 +16612,7 @@ function buildCommunitySummaryPage(input) {
16465
16612
  const frontmatter = {
16466
16613
  page_id: pageId,
16467
16614
  kind: "community_summary",
16615
+ cssclasses: cssclassesFor("community"),
16468
16616
  title: `Community: ${input.community.label}`,
16469
16617
  tags: ["graph", "community"],
16470
16618
  source_ids: relatedSourceIds,
@@ -16543,6 +16691,7 @@ function buildProjectsIndex(projectPages, schemaHash, metadata) {
16543
16691
  {
16544
16692
  page_id: "projects:index",
16545
16693
  kind: "index",
16694
+ cssclasses: cssclassesFor("index"),
16546
16695
  title: "Projects",
16547
16696
  tags: ["index", "projects"],
16548
16697
  source_ids: [],
@@ -16596,6 +16745,7 @@ function buildProjectIndex(input) {
16596
16745
  {
16597
16746
  page_id: `project:${input.projectId}:index`,
16598
16747
  kind: "index",
16748
+ cssclasses: cssclassesFor("index"),
16599
16749
  title,
16600
16750
  tags: decoratedTags(["index", "projects"], { projectIds: [input.projectId] }),
16601
16751
  source_ids: [],
@@ -16627,6 +16777,7 @@ function buildOutputPage(input) {
16627
16777
  const frontmatter = {
16628
16778
  page_id: pageId,
16629
16779
  kind: "output",
16780
+ cssclasses: cssclassesFor("output"),
16630
16781
  title: input.title ?? input.question,
16631
16782
  tags: decoratedTags(["output"], { projectIds: input.projectIds, extraTags: input.extraTags }),
16632
16783
  source_ids: input.citations,
@@ -16756,6 +16907,7 @@ function buildExploreHubPage(input) {
16756
16907
  const frontmatter = {
16757
16908
  page_id: pageId,
16758
16909
  kind: "output",
16910
+ cssclasses: cssclassesFor("output"),
16759
16911
  title,
16760
16912
  tags: decoratedTags(["output", "explore"], { projectIds: input.projectIds, extraTags: input.extraTags }),
16761
16913
  source_ids: relatedSourceIds,
@@ -21086,12 +21238,41 @@ async function ensureObsidianWorkspace(rootDir) {
21086
21238
  showTags: true,
21087
21239
  showAttachments: false,
21088
21240
  hideUnresolved: false,
21089
- colorGroups: projectIds.map((projectId, index) => ({
21090
- query: `tag:#project/${projectId}`,
21091
- color: ["#0ea5e9", "#22c55e", "#f59e0b", "#fb7185", "#8b5cf6", "#14b8a6"][index % 6]
21092
- })),
21241
+ colorGroups: [
21242
+ { query: "tag:#source", color: { a: 1, rgb: 16096779 } },
21243
+ { query: "tag:#module", color: { a: 1, rgb: 16478597 } },
21244
+ { query: "tag:#concept", color: { a: 1, rgb: 959977 } },
21245
+ { query: "tag:#entity", color: { a: 1, rgb: 2278750 } },
21246
+ { query: "tag:#rationale", color: { a: 1, rgb: 1357990 } },
21247
+ { query: "tag:#symbol", color: { a: 1, rgb: 9133302 } },
21248
+ ...projectIds.map((projectId, index) => ({
21249
+ query: `tag:#project/${projectId}`,
21250
+ color: { a: 1, rgb: [959977, 2278750, 16096779, 16478597, 9133302, 1357990][index % 6] }
21251
+ }))
21252
+ ],
21093
21253
  localJumps: false
21094
21254
  }),
21255
+ writeJsonFile(path23.join(obsidianDir, "types.json"), {
21256
+ types: {
21257
+ page_id: "text",
21258
+ kind: "text",
21259
+ title: "text",
21260
+ tags: "tags",
21261
+ aliases: "aliases",
21262
+ source_ids: "multitext",
21263
+ project_ids: "multitext",
21264
+ node_ids: "multitext",
21265
+ freshness: "text",
21266
+ status: "text",
21267
+ confidence: "number",
21268
+ created_at: "datetime",
21269
+ updated_at: "datetime",
21270
+ compiled_from: "multitext",
21271
+ managed_by: "text",
21272
+ backlinks: "multitext",
21273
+ cssclasses: "multitext"
21274
+ }
21275
+ }),
21095
21276
  writeJsonFile(path23.join(obsidianDir, "workspace.json"), {
21096
21277
  active: "root",
21097
21278
  lastOpenFiles: ["wiki/index.md", "wiki/projects/index.md", "wiki/candidates/index.md", "wiki/insights/index.md"],
@@ -22295,7 +22476,7 @@ async function bootstrapDemo(rootDir, input) {
22295
22476
  }
22296
22477
 
22297
22478
  // src/mcp.ts
22298
- var SERVER_VERSION = "0.7.27";
22479
+ var SERVER_VERSION = "0.7.29";
22299
22480
  async function createMcpServer(rootDir) {
22300
22481
  const server = new McpServer({
22301
22482
  name: "swarmvault",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swarmvaultai/engine",
3
- "version": "0.7.27",
3
+ "version": "0.7.29",
4
4
  "description": "Core engine for SwarmVault: ingest, compile, query, lint, and provider abstractions.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -39,6 +39,13 @@
39
39
  "engines": {
40
40
  "node": ">=24.0.0"
41
41
  },
42
+ "scripts": {
43
+ "build": "test -f ../viewer/dist/index.html || pnpm --dir ../viewer build; tsup src/index.ts --format esm --dts && tsup --config tsup.hooks.config.ts && rm -rf dist/viewer && mkdir -p dist/viewer && cp -R ../viewer/dist/. dist/viewer/",
44
+ "pretest": "tsup --config tsup.hooks.config.ts",
45
+ "test": "SWARMVAULT_ALLOW_PRIVATE_URLS=1 vitest run",
46
+ "typecheck": "tsc --noEmit",
47
+ "prepublishOnly": "node ../../scripts/check-release-sync.mjs && node ../../scripts/check-published-manifests.mjs"
48
+ },
42
49
  "dependencies": {
43
50
  "@asciidoctor/core": "^3.0.4",
44
51
  "@modelcontextprotocol/sdk": "^1.29.0",
@@ -88,11 +95,5 @@
88
95
  "graphology-types": "^0.24.8",
89
96
  "tsup": "^8.5.0",
90
97
  "vitest": "^3.2.4"
91
- },
92
- "scripts": {
93
- "build": "test -f ../viewer/dist/index.html || pnpm --dir ../viewer build; tsup src/index.ts --format esm --dts && tsup --config tsup.hooks.config.ts && rm -rf dist/viewer && mkdir -p dist/viewer && cp -R ../viewer/dist/. dist/viewer/",
94
- "pretest": "tsup --config tsup.hooks.config.ts",
95
- "test": "SWARMVAULT_ALLOW_PRIVATE_URLS=1 vitest run",
96
- "typecheck": "tsc --noEmit"
97
98
  }
98
- }
99
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 SwarmVault
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.