stellavault 0.8.5 → 0.8.6
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/README.md +27 -0
- package/dist/graph-ui/assets/{camera_utils-C1y6pgyV.js → camera_utils-DbH6FBwg.js} +1 -1
- package/dist/graph-ui/assets/{hands-BbZLpLop.js → hands-DSGVtDgH.js} +1 -1
- package/dist/graph-ui/assets/{index-KgyFgRwK.js → index-nyIICe1Z.js} +361 -272
- package/dist/graph-ui/index.html +1 -1
- package/dist/stellavault.js +119 -15
- package/package.json +1 -1
package/dist/graph-ui/index.html
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
html, body, #root { width: 100%; height: 100%; overflow: hidden; }
|
|
14
14
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0a0a0f; color: #e0e0e0; }
|
|
15
15
|
</style>
|
|
16
|
-
<script type="module" crossorigin src="/assets/index-
|
|
16
|
+
<script type="module" crossorigin src="/assets/index-nyIICe1Z.js"></script>
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
19
19
|
<div id="root"></div>
|
package/dist/stellavault.js
CHANGED
|
@@ -997,9 +997,13 @@ var init_indexer = __esm({
|
|
|
997
997
|
var graph_data_exports = {};
|
|
998
998
|
__export(graph_data_exports, {
|
|
999
999
|
buildClusteredGraph: () => buildClusteredGraph,
|
|
1000
|
-
buildGraphData: () => buildGraphData
|
|
1000
|
+
buildGraphData: () => buildGraphData,
|
|
1001
|
+
flattenClusterLevel: () => flattenClusterLevel
|
|
1001
1002
|
});
|
|
1002
1003
|
import { createHash as createHash2 } from "node:crypto";
|
|
1004
|
+
function paletteHex(clusterId) {
|
|
1005
|
+
return PALETTE_HEX[(clusterId % PALETTE_HEX.length + PALETTE_HEX.length) % PALETTE_HEX.length];
|
|
1006
|
+
}
|
|
1003
1007
|
async function buildGraphData(store, options = {}) {
|
|
1004
1008
|
const {
|
|
1005
1009
|
// 0.35: 384-dim 임베딩에서 의미있는 코사인 임계. 0.15는 사실상 모든 페어가 통과 →
|
|
@@ -1153,6 +1157,43 @@ async function buildGraphData(store, options = {}) {
|
|
|
1153
1157
|
}
|
|
1154
1158
|
};
|
|
1155
1159
|
}
|
|
1160
|
+
function flattenClusterLevel(level) {
|
|
1161
|
+
const nodes = level.superNodes.map((sn) => ({
|
|
1162
|
+
id: `cluster:${sn.clusterId}`,
|
|
1163
|
+
label: sn.label,
|
|
1164
|
+
filePath: "",
|
|
1165
|
+
tags: [],
|
|
1166
|
+
clusterId: sn.clusterId,
|
|
1167
|
+
position: sn.position,
|
|
1168
|
+
size: sn.size,
|
|
1169
|
+
source: "cluster",
|
|
1170
|
+
type: "cluster",
|
|
1171
|
+
isCluster: true,
|
|
1172
|
+
memberCount: sn.memberCount,
|
|
1173
|
+
representativeId: sn.representativeId
|
|
1174
|
+
}));
|
|
1175
|
+
const edges = level.metaEdges.map((me) => ({
|
|
1176
|
+
source: `cluster:${me.sourceCluster}`,
|
|
1177
|
+
target: `cluster:${me.targetCluster}`,
|
|
1178
|
+
weight: me.weight
|
|
1179
|
+
}));
|
|
1180
|
+
const clusters = level.superNodes.map((sn) => ({
|
|
1181
|
+
id: sn.clusterId,
|
|
1182
|
+
label: sn.label,
|
|
1183
|
+
color: paletteHex(sn.clusterId),
|
|
1184
|
+
nodeCount: sn.memberCount
|
|
1185
|
+
}));
|
|
1186
|
+
return {
|
|
1187
|
+
nodes,
|
|
1188
|
+
edges,
|
|
1189
|
+
clusters,
|
|
1190
|
+
stats: {
|
|
1191
|
+
nodeCount: nodes.length,
|
|
1192
|
+
edgeCount: edges.length,
|
|
1193
|
+
clusterCount: clusters.length
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1156
1197
|
async function buildClusteredGraph(store, options = {}) {
|
|
1157
1198
|
const mode = options.mode ?? "semantic";
|
|
1158
1199
|
const clusterCap = Math.max(200, Math.floor(options.clusterCap ?? (Number(process.env.GRAPH_CLUSTER_CAP) || 3e3)));
|
|
@@ -1456,7 +1497,7 @@ function kMeans(flat, n, dims, k, maxIter = 50) {
|
|
|
1456
1497
|
}
|
|
1457
1498
|
return assignments;
|
|
1458
1499
|
}
|
|
1459
|
-
var CLUSTER_COLORS;
|
|
1500
|
+
var CLUSTER_COLORS, PALETTE_HEX;
|
|
1460
1501
|
var init_graph_data = __esm({
|
|
1461
1502
|
"packages/core/dist/api/graph-data.js"() {
|
|
1462
1503
|
"use strict";
|
|
@@ -1477,6 +1518,23 @@ var init_graph_data = __esm({
|
|
|
1477
1518
|
"#a3e635",
|
|
1478
1519
|
"#fb923c"
|
|
1479
1520
|
];
|
|
1521
|
+
PALETTE_HEX = [
|
|
1522
|
+
"#7c3aed",
|
|
1523
|
+
"#ec4899",
|
|
1524
|
+
"#f59e0b",
|
|
1525
|
+
"#10b981",
|
|
1526
|
+
"#3b82f6",
|
|
1527
|
+
"#ef4444",
|
|
1528
|
+
"#06b6d4",
|
|
1529
|
+
"#84cc16",
|
|
1530
|
+
"#f97316",
|
|
1531
|
+
"#8b5cf6",
|
|
1532
|
+
"#14b8a6",
|
|
1533
|
+
"#e879f9",
|
|
1534
|
+
"#eab308",
|
|
1535
|
+
"#22d3ee",
|
|
1536
|
+
"#fb7185"
|
|
1537
|
+
];
|
|
1480
1538
|
}
|
|
1481
1539
|
});
|
|
1482
1540
|
|
|
@@ -7548,17 +7606,40 @@ function createApiServer(options) {
|
|
|
7548
7606
|
}
|
|
7549
7607
|
const GRAPH_CACHE_TTL = 5 * 60 * 1e3;
|
|
7550
7608
|
const graphCaches = /* @__PURE__ */ new Map();
|
|
7609
|
+
function parseView(q) {
|
|
7610
|
+
return q === "raw" ? "raw" : "cluster";
|
|
7611
|
+
}
|
|
7612
|
+
function parseMode(q) {
|
|
7613
|
+
return q === "folder" ? "folder" : "semantic";
|
|
7614
|
+
}
|
|
7615
|
+
function clampCap(view, raw) {
|
|
7616
|
+
if (!Number.isFinite(raw) || raw <= 0)
|
|
7617
|
+
return void 0;
|
|
7618
|
+
const max = view === "raw" ? 4e3 : 6e3;
|
|
7619
|
+
const rounded = Math.round(raw / 1e3) * 1e3;
|
|
7620
|
+
return Math.max(1e3, Math.min(max, rounded));
|
|
7621
|
+
}
|
|
7622
|
+
async function buildGraphEntry(view, mode, cap) {
|
|
7623
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7624
|
+
if (view === "cluster") {
|
|
7625
|
+
const g = await buildClusteredGraph(store, { mode, clusterCap: cap });
|
|
7626
|
+
return { data: flattenClusterLevel(g.clusterLevel), clustered: g, generatedAt: now, cachedAt: Date.now() };
|
|
7627
|
+
}
|
|
7628
|
+
const data = await buildGraphData(store, { mode, nodeCap: cap });
|
|
7629
|
+
return { data, generatedAt: now, cachedAt: Date.now() };
|
|
7630
|
+
}
|
|
7551
7631
|
app.get("/api/graph", async (req, res) => {
|
|
7552
7632
|
try {
|
|
7553
|
-
const
|
|
7554
|
-
const
|
|
7633
|
+
const view = parseView(req.query.view);
|
|
7634
|
+
const mode = parseMode(req.query.mode);
|
|
7635
|
+
const cap = clampCap(view, Number(req.query.cap));
|
|
7636
|
+
const cacheKey = `${view}:${mode}:${cap ?? ""}`;
|
|
7637
|
+
const cached = graphCaches.get(cacheKey);
|
|
7555
7638
|
if (!cached || Date.now() - cached.cachedAt > GRAPH_CACHE_TTL) {
|
|
7556
|
-
|
|
7557
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7558
|
-
graphCaches.set(mode, { data, generatedAt: now, cachedAt: Date.now() });
|
|
7639
|
+
graphCaches.set(cacheKey, await buildGraphEntry(view, mode, cap));
|
|
7559
7640
|
}
|
|
7560
|
-
const entry = graphCaches.get(
|
|
7561
|
-
res.json({ data: entry.data, generatedAt: entry.generatedAt, mode });
|
|
7641
|
+
const entry = graphCaches.get(cacheKey);
|
|
7642
|
+
res.json({ data: entry.data, generatedAt: entry.generatedAt, mode, view });
|
|
7562
7643
|
} catch (err) {
|
|
7563
7644
|
console.error(err);
|
|
7564
7645
|
res.status(500).json({ error: "Internal server error" });
|
|
@@ -7566,11 +7647,34 @@ function createApiServer(options) {
|
|
|
7566
7647
|
});
|
|
7567
7648
|
app.get("/api/graph/refresh", async (req, res) => {
|
|
7568
7649
|
try {
|
|
7569
|
-
const
|
|
7570
|
-
const
|
|
7571
|
-
const
|
|
7572
|
-
|
|
7573
|
-
|
|
7650
|
+
const view = parseView(req.query.view);
|
|
7651
|
+
const mode = parseMode(req.query.mode);
|
|
7652
|
+
const cap = clampCap(view, Number(req.query.cap));
|
|
7653
|
+
const cacheKey = `${view}:${mode}:${cap ?? ""}`;
|
|
7654
|
+
const entry = await buildGraphEntry(view, mode, cap);
|
|
7655
|
+
graphCaches.set(cacheKey, entry);
|
|
7656
|
+
res.json({ data: entry.data, generatedAt: entry.generatedAt, mode, view });
|
|
7657
|
+
} catch (err) {
|
|
7658
|
+
console.error(err);
|
|
7659
|
+
res.status(500).json({ error: "Internal server error" });
|
|
7660
|
+
}
|
|
7661
|
+
});
|
|
7662
|
+
app.get("/api/graph/cluster/:id", async (req, res) => {
|
|
7663
|
+
try {
|
|
7664
|
+
const mode = parseMode(req.query.mode);
|
|
7665
|
+
const cap = clampCap("cluster", Number(req.query.cap));
|
|
7666
|
+
const cacheKey = `cluster:${mode}:${cap ?? ""}`;
|
|
7667
|
+
let cached = graphCaches.get(cacheKey);
|
|
7668
|
+
if (!cached || !cached.clustered || Date.now() - cached.cachedAt > GRAPH_CACHE_TTL) {
|
|
7669
|
+
cached = await buildGraphEntry("cluster", mode, cap);
|
|
7670
|
+
graphCaches.set(cacheKey, cached);
|
|
7671
|
+
}
|
|
7672
|
+
const members = cached.clustered.members.get(Number(req.params.id));
|
|
7673
|
+
if (!members) {
|
|
7674
|
+
res.status(404).json({ error: "Cluster not found" });
|
|
7675
|
+
return;
|
|
7676
|
+
}
|
|
7677
|
+
res.json({ data: members });
|
|
7574
7678
|
} catch (err) {
|
|
7575
7679
|
console.error(err);
|
|
7576
7680
|
res.status(500).json({ error: "Internal server error" });
|
|
@@ -11550,7 +11654,7 @@ if (nodeVersion < 20) {
|
|
|
11550
11654
|
process.exit(1);
|
|
11551
11655
|
}
|
|
11552
11656
|
var program = new Command();
|
|
11553
|
-
var SV_VERSION = true ? "0.8.
|
|
11657
|
+
var SV_VERSION = true ? "0.8.6" : "0.0.0-dev";
|
|
11554
11658
|
program.name("stellavault").description("Stellavault \u2014 Self-compiling knowledge base for your Obsidian vault").version(SV_VERSION).option("--json", "Output in JSON format (for scripting)").option("--quiet", "Suppress non-essential output");
|
|
11555
11659
|
program.command("init").description("Interactive setup wizard \u2014 get started in 3 minutes").action(initCommand);
|
|
11556
11660
|
program.command("doctor").description("Diagnose setup issues (config, vault, DB, model, Node version)").action(doctorCommand);
|
package/package.json
CHANGED