@swarmvaultai/viewer 0.1.27 → 0.1.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.
- package/dist/assets/index-Csm8eB3P.js +331 -0
- package/dist/assets/index-DUJ6MWHL.css +1 -0
- package/dist/index.html +2 -2
- package/dist/lib.js +178 -0
- package/package.json +12 -10
- package/LICENSE +0 -21
- package/dist/assets/index-C7PCTMog.js +0 -330
- package/dist/assets/index-DiMCbjBi.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--c-bg-base: #020617;--c-bg-surface: #0c1222;--c-bg-elevated: rgba(15, 23, 42, .88);--c-bg-inset: rgba(2, 6, 23, .82);--c-bg-input: #070d1a;--c-border: rgba(148, 163, 184, .1);--c-border-subtle: rgba(148, 163, 184, .06);--c-border-focus: rgba(125, 211, 252, .28);--c-border-danger: rgba(248, 113, 113, .24);--c-border-warning: rgba(251, 191, 36, .2);--c-text-primary: #e2e8f0;--c-text-secondary: #94a3b8;--c-text-muted: #64748b;--c-text-accent: #7dd3fc;--c-text-error: #f87171;--c-text-warning: #fbbf24;--c-accent-bg: rgba(14, 165, 233, .08);--c-danger-bg: rgba(127, 29, 29, .18);--font-sans: "Inter", "Avenir Next", "Segoe UI", system-ui, sans-serif;--font-mono: "IBM Plex Mono", "SF Mono", "Fira Code", monospace;--text-2xs: .6875rem;--text-xs: .75rem;--text-sm: .8125rem;--text-base: .9375rem;--text-lg: 1.0625rem;--text-xl: 1.25rem;--sp-1: 4px;--sp-2: 8px;--sp-3: 12px;--sp-4: 16px;--sp-5: 20px;--sp-6: 24px;--radius-sm: 4px;--radius-md: 6px;--radius-lg: 10px;--sidebar-width: 220px;--rail-width: 400px;--bar-height: 42px;color-scheme:dark;font-family:var(--font-sans);background:var(--c-bg-base);color:var(--c-text-primary)}*,*:before,*:after{box-sizing:border-box}body{margin:0;height:100vh;overflow:hidden;font-size:var(--text-sm);line-height:1.5;-webkit-font-smoothing:antialiased}#root{height:100vh;overflow:hidden}.app-shell{display:grid;grid-template-columns:var(--sidebar-width) minmax(0,1fr) var(--rail-width);grid-template-rows:var(--bar-height) minmax(0,1fr);grid-template-areas:"bar bar bar" "sidebar center rail";height:100vh;overflow:hidden}.app-bar{grid-area:bar;display:flex;align-items:center;gap:var(--sp-3);padding:0 var(--sp-5);background:var(--c-bg-surface);border-bottom:1px solid var(--c-border);z-index:10}.app-bar-title{font-size:var(--text-sm);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--c-text-accent)}.app-bar-subtitle{font-size:var(--text-xs);color:var(--c-text-muted);letter-spacing:.04em}.sidebar{grid-area:sidebar;overflow-y:auto;padding:var(--sp-3);background:var(--c-bg-surface);border-right:1px solid var(--c-border);display:flex;flex-direction:column;gap:var(--sp-3);scrollbar-width:thin;scrollbar-color:var(--c-text-muted) transparent}.sidebar-section{display:flex;flex-direction:column;gap:var(--sp-2)}.sidebar-heading{font-size:var(--text-2xs);font-weight:600;text-transform:uppercase;letter-spacing:.1em;color:var(--c-text-muted);padding:var(--sp-1) 0;border-bottom:1px solid var(--c-border-subtle);margin-bottom:var(--sp-1)}.sidebar-section-toggle{all:unset;display:flex;align-items:center;gap:var(--sp-2);width:100%;cursor:pointer;font-size:var(--text-2xs);font-weight:600;text-transform:uppercase;letter-spacing:.1em;color:var(--c-text-muted);padding:var(--sp-1) 0;border-bottom:1px solid var(--c-border-subtle);margin-bottom:var(--sp-1);transition:color .15s}.sidebar-section-toggle:hover{color:var(--c-text-secondary)}.sidebar-section-toggle:before{content:"▸";font-size:.6em;transition:transform .2s ease;display:inline-block}.sidebar-section-toggle.is-expanded:before{transform:rotate(90deg)}.sidebar-section-toggle .filter-badge{margin-left:auto;font-family:var(--font-mono);font-size:var(--text-2xs);color:var(--c-text-accent);font-weight:500}.sidebar-section-body{display:grid;gap:var(--sp-2);max-height:0;overflow:hidden;transition:max-height .25s ease,opacity .2s ease;opacity:0}.sidebar-section-body.is-expanded{max-height:600px;opacity:1}.filter-group{display:flex;flex-direction:column;gap:3px}.filter-label{font-size:var(--text-2xs);text-transform:uppercase;letter-spacing:.06em;color:var(--c-text-muted)}.center-area{grid-area:center;display:grid;grid-template-rows:auto minmax(0,1fr) auto;overflow:hidden}.stats-strip{display:flex;gap:var(--sp-2);padding:var(--sp-2) var(--sp-3);border-bottom:1px solid var(--c-border-subtle);background:var(--c-bg-surface);align-items:center}.stats-group{display:flex;gap:var(--sp-3);align-items:baseline}.stats-divider{width:1px;height:14px;background:var(--c-border);align-self:center;flex-shrink:0}.stat{display:flex;align-items:baseline;gap:var(--sp-1)}.stat-label{font-size:var(--text-2xs);color:var(--c-text-muted);text-transform:uppercase;letter-spacing:.06em}.stat-value{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--c-text-primary);font-weight:500}.canvas{min-height:0;background:radial-gradient(ellipse at 50% 40%,rgba(14,165,233,.025),transparent 65%),radial-gradient(circle at 1px 1px,rgba(148,163,184,.045) 1px,transparent 0),var(--c-bg-base);background-size:100% 100%,28px 28px,100% 100%}.canvas-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-3)}.loading-text{font-size:var(--text-base);color:var(--c-text-muted);letter-spacing:.06em;font-weight:400;animation:pulse-fade 2s ease-in-out infinite}@keyframes pulse-fade{0%,to{opacity:.35}50%{opacity:.85}}.canvas-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--sp-2);color:var(--c-text-muted)}.canvas-empty-icon{font-size:2rem;opacity:.4}.report-tabs{border-top:1px solid var(--c-border);background:var(--c-bg-surface);max-height:360px;overflow:hidden}.report-tabs .tabs{border:none;border-radius:0;background:transparent}.report-tabs .tab-panel{max-height:310px;overflow-y:auto}.report-tabs-empty{padding:var(--sp-3);text-align:center;color:var(--c-text-muted);font-size:var(--text-sm)}.report-stats{display:flex;gap:var(--sp-4);font-size:var(--text-sm);color:var(--c-text-secondary)}.report-stats strong{font-family:var(--font-mono);color:var(--c-text-primary);margin-left:var(--sp-1)}.surprise-row{display:flex;align-items:center;gap:var(--sp-2);flex-wrap:wrap}.detail-rail{grid-area:rail;overflow-y:auto;padding:var(--sp-3);background:var(--c-bg-surface);border-left:1px solid var(--c-border);display:flex;flex-direction:column;gap:var(--sp-3);scrollbar-width:thin;scrollbar-color:var(--c-text-muted) transparent}.tabs{border-radius:var(--radius-lg);border:1px solid var(--c-border);background:var(--c-bg-elevated);overflow:hidden}.tab-bar{display:flex;border-bottom:1px solid var(--c-border);padding:0 var(--sp-1);gap:0}.tab-btn{all:unset;padding:var(--sp-2) var(--sp-3);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:.06em;color:var(--c-text-muted);cursor:pointer;border-bottom:2px solid transparent;transition:color .12s,border-color .12s;white-space:nowrap}.tab-btn.is-active{color:var(--c-text-primary);border-bottom-color:var(--c-text-accent)}.tab-btn:hover:not(.is-active){color:var(--c-text-secondary)}.tab-btn:focus-visible{outline:2px solid var(--c-border-focus);outline-offset:-2px;border-radius:var(--radius-sm)}.tab-count{margin-left:var(--sp-1);font-family:var(--font-mono);font-size:var(--text-2xs);color:var(--c-text-accent)}.tab-panel{padding:var(--sp-3);max-height:320px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--c-text-muted) transparent}.panel{background:var(--c-bg-elevated);border:1px solid var(--c-border);border-radius:var(--radius-lg);padding:var(--sp-3);transition:border-color .15s}.panel-heading{margin:0 0 var(--sp-2);font-size:var(--text-base);font-weight:700;text-transform:none;letter-spacing:.01em;color:var(--c-text-primary)}.page-panel{min-height:120px}.card-list{display:grid;gap:var(--sp-2)}.card{background:var(--c-bg-inset);border:1px solid var(--c-border);border-radius:var(--radius-md);padding:var(--sp-2) var(--sp-3);display:flex;flex-direction:column;gap:4px}.card>.input+.input,.card>.input+.btn,.card>.btn+.input{margin-top:2px}.card-warning{border-color:var(--c-border-warning)}.card-title{font-size:var(--text-sm);font-weight:600;color:var(--c-text-primary);margin:0;line-height:1.3}.result-card{all:unset;display:flex;flex-direction:column;gap:3px;background:var(--c-bg-inset);border:1px solid var(--c-border);border-radius:var(--radius-md);padding:var(--sp-2) var(--sp-3);cursor:pointer;transition:border-color .12s,background .12s}.result-card:hover{border-color:var(--c-border-focus);background:#0ea5e908}.result-card.is-active{border-color:var(--c-border-focus);background:#0ea5e90f}.input{background:var(--c-bg-input);color:var(--c-text-primary);border:1px solid var(--c-border);border-radius:var(--radius-sm);padding:6px var(--sp-2);font-family:var(--font-sans);font-size:var(--text-sm);width:100%;outline:none;transition:border-color .12s}.input:focus{border-color:var(--c-border-focus)}.input::placeholder{color:var(--c-text-muted)}select.input{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%2364748b'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;padding-right:24px;text-overflow:ellipsis}.btn{all:unset;display:inline-flex;align-items:center;gap:var(--sp-1);height:28px;padding:0 var(--sp-3);font-size:var(--text-xs);font-family:var(--font-sans);border-radius:var(--radius-sm);cursor:pointer;border:1px solid var(--c-border);background:transparent;color:var(--c-text-primary);transition:border-color .12s,background .12s;white-space:nowrap}.btn:hover{border-color:var(--c-border-focus);background:var(--c-accent-bg)}.btn:focus-visible{outline:2px solid var(--c-border-focus);outline-offset:1px}.btn:disabled{opacity:.35;cursor:default;pointer-events:none}.btn-primary{border-color:var(--c-border-focus);background:var(--c-accent-bg)}.btn-danger{border-color:var(--c-border-danger);background:var(--c-danger-bg);color:var(--c-text-error)}.btn-ghost{border:none;background:transparent;color:var(--c-text-accent);padding:0 var(--sp-1);height:auto;font-size:var(--text-xs)}.btn-ghost:hover{text-decoration:underline;border:none;background:transparent}.action-row{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-1)}.chip-row{display:flex;flex-wrap:wrap;gap:var(--sp-1);margin-top:var(--sp-1)}.label{font-size:var(--text-2xs);text-transform:uppercase;letter-spacing:.06em;color:var(--c-text-muted);font-weight:500}.meta-grid{display:grid;grid-template-columns:auto 1fr;gap:3px var(--sp-3);font-size:var(--text-xs);align-items:baseline}.meta-label{color:var(--c-text-muted);text-transform:uppercase;letter-spacing:.04em;font-size:var(--text-2xs);white-space:nowrap}.meta-value{color:var(--c-text-primary);overflow-wrap:break-word;word-break:break-word}.meta-value-truncate{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block}.meta-value.mono,.text-mono{font-family:var(--font-mono)}.linked-section{margin-top:var(--sp-2);padding-top:var(--sp-2);border-top:1px solid var(--c-border-subtle)}.asset-preview{display:grid;gap:var(--sp-2);margin-top:var(--sp-2)}.asset-card{margin:0;display:grid;gap:var(--sp-1)}.asset-card img{width:100%;max-height:200px;object-fit:contain;border-radius:var(--radius-md);border:1px solid var(--c-border);background:var(--c-bg-inset)}.asset-card figcaption{color:var(--c-text-muted);font-size:var(--text-2xs)}.content-pre{margin:var(--sp-2) 0 0;white-space:pre-wrap;overflow:auto;max-height:340px;padding:var(--sp-3);border-radius:var(--radius-md);background:var(--c-bg-inset);border:1px solid var(--c-border);font-family:var(--font-mono);font-size:var(--text-xs);color:var(--c-text-secondary);line-height:1.55;scrollbar-width:thin;scrollbar-color:var(--c-text-muted) transparent}.content-truncation-note{margin-top:var(--sp-1);font-size:var(--text-2xs);color:var(--c-text-muted);font-style:italic}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--sp-5) var(--sp-3);color:var(--c-text-muted);text-align:center;min-height:80px;gap:var(--sp-2)}.empty-state-icon{font-size:1.5rem;opacity:.4;line-height:1}mark{background:#7dd3fc26;color:var(--c-text-accent);border-radius:2px;padding:0 2px}.text-sm{font-size:var(--text-sm)}.text-muted{color:var(--c-text-muted)}.text-secondary{color:var(--c-text-secondary)}.text-error{color:var(--c-text-error);font-size:var(--text-xs)}code{font-family:var(--font-mono);font-size:var(--text-xs)}p,h3,h4{margin:0}a{color:var(--c-text-accent);text-decoration:none}a:hover{text-decoration:underline}@media(max-width:900px){.app-shell{grid-template-columns:1fr;grid-template-rows:var(--bar-height) auto minmax(300px,1fr) auto;grid-template-areas:"bar" "sidebar" "center" "rail";height:auto;min-height:100vh;overflow:auto}.sidebar{border-right:none;border-bottom:1px solid var(--c-border);max-height:260px}.center-area{grid-template-rows:auto minmax(50vh,1fr) auto}.detail-rail{border-left:none;border-top:1px solid var(--c-border)}.stats-strip{flex-wrap:wrap;gap:var(--sp-2)}}
|
package/dist/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>SwarmVault Graph</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-Csm8eB3P.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DUJ6MWHL.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
package/dist/lib.js
CHANGED
|
@@ -2,6 +2,176 @@
|
|
|
2
2
|
function embeddedData() {
|
|
3
3
|
return typeof window !== "undefined" ? window.__SWARMVAULT_EMBEDDED_DATA__ : void 0;
|
|
4
4
|
}
|
|
5
|
+
function normalizeGraphTarget(value) {
|
|
6
|
+
return value.trim().toLowerCase();
|
|
7
|
+
}
|
|
8
|
+
function embeddedNodeById(graph) {
|
|
9
|
+
return new Map(graph.nodes.map((node) => [node.id, node]));
|
|
10
|
+
}
|
|
11
|
+
function embeddedPageById(graph) {
|
|
12
|
+
return new Map((graph.pages ?? []).map((page) => [page.id, page]));
|
|
13
|
+
}
|
|
14
|
+
function embeddedResolveNode(graph, target) {
|
|
15
|
+
const normalized = normalizeGraphTarget(target);
|
|
16
|
+
return graph.nodes.find((node) => node.id === target || normalizeGraphTarget(node.label) === normalized || node.pageId === target) ?? null;
|
|
17
|
+
}
|
|
18
|
+
function embeddedGraphAdjacency(graph) {
|
|
19
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
20
|
+
for (const node of graph.nodes) {
|
|
21
|
+
adjacency.set(node.id, []);
|
|
22
|
+
}
|
|
23
|
+
for (const edge of graph.edges) {
|
|
24
|
+
adjacency.get(edge.source)?.push({
|
|
25
|
+
nodeId: edge.target,
|
|
26
|
+
edge,
|
|
27
|
+
direction: "outgoing"
|
|
28
|
+
});
|
|
29
|
+
adjacency.get(edge.target)?.push({
|
|
30
|
+
nodeId: edge.source,
|
|
31
|
+
edge,
|
|
32
|
+
direction: "incoming"
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return adjacency;
|
|
36
|
+
}
|
|
37
|
+
function shortestEmbeddedGraphPath(graph, from, to) {
|
|
38
|
+
const start = embeddedResolveNode(graph, from);
|
|
39
|
+
const end = embeddedResolveNode(graph, to);
|
|
40
|
+
if (!start || !end) {
|
|
41
|
+
return {
|
|
42
|
+
from,
|
|
43
|
+
to,
|
|
44
|
+
resolvedFromNodeId: start?.id,
|
|
45
|
+
resolvedToNodeId: end?.id,
|
|
46
|
+
found: false,
|
|
47
|
+
nodeIds: [],
|
|
48
|
+
edgeIds: [],
|
|
49
|
+
pageIds: [],
|
|
50
|
+
summary: "Could not resolve one or both graph targets."
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const adjacency = embeddedGraphAdjacency(graph);
|
|
54
|
+
const queue = [start.id];
|
|
55
|
+
const visited = /* @__PURE__ */ new Set([start.id]);
|
|
56
|
+
const previous = /* @__PURE__ */ new Map();
|
|
57
|
+
while (queue.length) {
|
|
58
|
+
const current2 = queue.shift();
|
|
59
|
+
if (current2 === end.id) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
for (const neighbor of adjacency.get(current2) ?? []) {
|
|
63
|
+
if (visited.has(neighbor.nodeId)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
visited.add(neighbor.nodeId);
|
|
67
|
+
previous.set(neighbor.nodeId, {
|
|
68
|
+
nodeId: current2,
|
|
69
|
+
edgeId: neighbor.edge.id
|
|
70
|
+
});
|
|
71
|
+
queue.push(neighbor.nodeId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!visited.has(end.id)) {
|
|
75
|
+
return {
|
|
76
|
+
from,
|
|
77
|
+
to,
|
|
78
|
+
resolvedFromNodeId: start.id,
|
|
79
|
+
resolvedToNodeId: end.id,
|
|
80
|
+
found: false,
|
|
81
|
+
nodeIds: [],
|
|
82
|
+
edgeIds: [],
|
|
83
|
+
pageIds: [],
|
|
84
|
+
summary: `No path found between ${start.label} and ${end.label}.`
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const nodeIds = [];
|
|
88
|
+
const edgeIds = [];
|
|
89
|
+
let current = end.id;
|
|
90
|
+
while (current !== start.id) {
|
|
91
|
+
nodeIds.push(current);
|
|
92
|
+
const prev = previous.get(current);
|
|
93
|
+
if (!prev) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
edgeIds.push(prev.edgeId);
|
|
97
|
+
current = prev.nodeId;
|
|
98
|
+
}
|
|
99
|
+
nodeIds.push(start.id);
|
|
100
|
+
nodeIds.reverse();
|
|
101
|
+
edgeIds.reverse();
|
|
102
|
+
const nodes = embeddedNodeById(graph);
|
|
103
|
+
const pageIds = [
|
|
104
|
+
...new Set(
|
|
105
|
+
nodeIds.flatMap((nodeId) => {
|
|
106
|
+
const pageId = nodes.get(nodeId)?.pageId;
|
|
107
|
+
return pageId ? [pageId] : [];
|
|
108
|
+
})
|
|
109
|
+
)
|
|
110
|
+
];
|
|
111
|
+
return {
|
|
112
|
+
from,
|
|
113
|
+
to,
|
|
114
|
+
resolvedFromNodeId: start.id,
|
|
115
|
+
resolvedToNodeId: end.id,
|
|
116
|
+
found: true,
|
|
117
|
+
nodeIds,
|
|
118
|
+
edgeIds,
|
|
119
|
+
pageIds,
|
|
120
|
+
summary: nodeIds.map((nodeId) => nodes.get(nodeId)?.label ?? nodeId).join(" -> ")
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function explainEmbeddedGraphTarget(graph, target) {
|
|
124
|
+
const node = embeddedResolveNode(graph, target);
|
|
125
|
+
if (!node) {
|
|
126
|
+
throw new Error(`Could not resolve graph target: ${target}`);
|
|
127
|
+
}
|
|
128
|
+
const pages = embeddedPageById(graph);
|
|
129
|
+
const page = node.pageId ? pages.get(node.pageId) : void 0;
|
|
130
|
+
const nodes = embeddedNodeById(graph);
|
|
131
|
+
const neighbors = [];
|
|
132
|
+
for (const neighbor of embeddedGraphAdjacency(graph).get(node.id) ?? []) {
|
|
133
|
+
const targetNode = nodes.get(neighbor.nodeId);
|
|
134
|
+
if (!targetNode) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
neighbors.push({
|
|
138
|
+
nodeId: targetNode.id,
|
|
139
|
+
label: targetNode.label,
|
|
140
|
+
type: targetNode.type,
|
|
141
|
+
pageId: targetNode.pageId,
|
|
142
|
+
relation: neighbor.edge.relation,
|
|
143
|
+
direction: neighbor.direction,
|
|
144
|
+
confidence: neighbor.edge.confidence ?? 0,
|
|
145
|
+
evidenceClass: neighbor.edge.evidenceClass ?? "unknown"
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
neighbors.sort((left, right) => right.confidence - left.confidence || left.label.localeCompare(right.label));
|
|
149
|
+
const hyperedges = (graph.hyperedges ?? []).filter((hyperedge) => hyperedge.nodeIds.includes(node.id));
|
|
150
|
+
const community = graph.communities?.find((candidate) => candidate.id === node.communityId);
|
|
151
|
+
return {
|
|
152
|
+
target,
|
|
153
|
+
node,
|
|
154
|
+
page: page ? {
|
|
155
|
+
id: page.id,
|
|
156
|
+
path: page.path,
|
|
157
|
+
title: page.title
|
|
158
|
+
} : void 0,
|
|
159
|
+
community: community ? {
|
|
160
|
+
id: community.id,
|
|
161
|
+
label: community.label
|
|
162
|
+
} : void 0,
|
|
163
|
+
neighbors,
|
|
164
|
+
hyperedges,
|
|
165
|
+
summary: [
|
|
166
|
+
`Node: ${node.label}`,
|
|
167
|
+
`Type: ${node.type}`,
|
|
168
|
+
`Community: ${node.communityId ?? "none"}`,
|
|
169
|
+
`Neighbors: ${neighbors.length}`,
|
|
170
|
+
`Group patterns: ${hyperedges.length}`,
|
|
171
|
+
`Page: ${page?.path ?? "none"}`
|
|
172
|
+
].join("\n")
|
|
173
|
+
};
|
|
174
|
+
}
|
|
5
175
|
function normalizeSnippet(content, query) {
|
|
6
176
|
const normalized = content.replace(/\s+/g, " ").trim();
|
|
7
177
|
if (!query) {
|
|
@@ -129,6 +299,10 @@ async function fetchGraphReport() {
|
|
|
129
299
|
return response.json();
|
|
130
300
|
}
|
|
131
301
|
async function fetchGraphPath(from, to) {
|
|
302
|
+
const embedded = embeddedData();
|
|
303
|
+
if (embedded) {
|
|
304
|
+
return shortestEmbeddedGraphPath(embedded.graph, from, to);
|
|
305
|
+
}
|
|
132
306
|
const params = new URLSearchParams({
|
|
133
307
|
from,
|
|
134
308
|
to
|
|
@@ -140,6 +314,10 @@ async function fetchGraphPath(from, to) {
|
|
|
140
314
|
return response.json();
|
|
141
315
|
}
|
|
142
316
|
async function fetchGraphExplain(target) {
|
|
317
|
+
const embedded = embeddedData();
|
|
318
|
+
if (embedded) {
|
|
319
|
+
return explainEmbeddedGraphTarget(embedded.graph, target);
|
|
320
|
+
}
|
|
143
321
|
const response = await fetch(`/api/graph/explain?target=${encodeURIComponent(target)}`);
|
|
144
322
|
if (!response.ok) {
|
|
145
323
|
throw new Error(`Failed to explain graph target: ${response.status} ${response.statusText}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmvaultai/viewer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"description": "Graph viewer package for SwarmVault graph artifacts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/lib.js",
|
|
@@ -37,6 +37,13 @@
|
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": ">=24.0.0"
|
|
39
39
|
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "pnpm run build:lib && pnpm run build:app",
|
|
42
|
+
"build:lib": "tsup src/lib.ts --format esm --dts --out-dir dist --clean",
|
|
43
|
+
"build:app": "vite build",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"typecheck": "tsc --noEmit"
|
|
46
|
+
},
|
|
40
47
|
"dependencies": {
|
|
41
48
|
"cytoscape": "^3.33.1",
|
|
42
49
|
"react": "^19.1.1",
|
|
@@ -47,15 +54,10 @@
|
|
|
47
54
|
"@types/react": "^19.1.13",
|
|
48
55
|
"@types/react-dom": "^19.1.9",
|
|
49
56
|
"@vitejs/plugin-react": "^5.0.4",
|
|
57
|
+
"jsdom": "^27.0.0",
|
|
50
58
|
"tsup": "^8.5.0",
|
|
51
59
|
"typescript": "^5.9.2",
|
|
52
|
-
"vite": "^7.1.7"
|
|
53
|
-
|
|
54
|
-
"scripts": {
|
|
55
|
-
"build": "pnpm run build:lib && pnpm run build:app",
|
|
56
|
-
"build:lib": "tsup src/lib.ts --format esm --dts --out-dir dist --clean",
|
|
57
|
-
"build:app": "vite build",
|
|
58
|
-
"test": "node -e \"process.exit(0)\"",
|
|
59
|
-
"typecheck": "tsc --noEmit"
|
|
60
|
+
"vite": "^7.1.7",
|
|
61
|
+
"vitest": "^3.2.4"
|
|
60
62
|
}
|
|
61
|
-
}
|
|
63
|
+
}
|
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.
|