@velvetmonkey/flywheel-memory 2.0.152 → 2.0.154
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 +2 -2
- package/dist/index.js +39 -4
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
[](https://www.npmjs.com/package/@velvetmonkey/flywheel-memory)
|
|
14
14
|
[](https://modelcontextprotocol.io/)
|
|
15
15
|
[](https://github.com/velvetmonkey/flywheel-memory/actions/workflows/ci.yml)
|
|
16
|
-
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
17
17
|
[](https://github.com/velvetmonkey/flywheel-memory)
|
|
18
18
|
[](https://github.com/velvetmonkey/flywheel-memory/blob/main/docs/TESTING.md#performance-benchmarks)
|
|
19
19
|
[](https://github.com/velvetmonkey/flywheel-memory/blob/main/docs/TESTING.md)
|
|
@@ -399,4 +399,4 @@ The fewer tools you load, the less context the AI needs to pick the right one. S
|
|
|
399
399
|
|
|
400
400
|
## License
|
|
401
401
|
|
|
402
|
-
|
|
402
|
+
Apache-2.0 — see [LICENSE](https://github.com/velvetmonkey/flywheel-memory/blob/main/LICENSE) for details.
|
package/dist/index.js
CHANGED
|
@@ -8104,7 +8104,7 @@ function computeHubScores(index) {
|
|
|
8104
8104
|
}
|
|
8105
8105
|
}
|
|
8106
8106
|
const N = nodes.length;
|
|
8107
|
-
if (N === 0) return /* @__PURE__ */ new Map();
|
|
8107
|
+
if (N === 0) return { scores: /* @__PURE__ */ new Map(), edgeCount: 0 };
|
|
8108
8108
|
for (const note of index.notes.values()) {
|
|
8109
8109
|
const fromIdx = nodeIdx.get(normalizeTarget(note.path));
|
|
8110
8110
|
if (fromIdx === void 0) continue;
|
|
@@ -8120,6 +8120,11 @@ function computeHubScores(index) {
|
|
|
8120
8120
|
}
|
|
8121
8121
|
}
|
|
8122
8122
|
}
|
|
8123
|
+
const edgeCount = adj.reduce((sum, a) => sum + a.length, 0);
|
|
8124
|
+
if (edgeCount === 0) {
|
|
8125
|
+
console.error(`[Flywheel] Hub scores: 0 edges in graph of ${N} nodes, skipping eigenvector`);
|
|
8126
|
+
return { scores: /* @__PURE__ */ new Map(), edgeCount: 0 };
|
|
8127
|
+
}
|
|
8123
8128
|
let scores = new Float64Array(N).fill(1 / N);
|
|
8124
8129
|
for (let iter = 0; iter < EIGEN_ITERATIONS; iter++) {
|
|
8125
8130
|
const next = new Float64Array(N);
|
|
@@ -8147,7 +8152,21 @@ function computeHubScores(index) {
|
|
|
8147
8152
|
result.set(nodes[i], scaled);
|
|
8148
8153
|
}
|
|
8149
8154
|
}
|
|
8150
|
-
|
|
8155
|
+
if (result.size < N * 0.1 && edgeCount > 0) {
|
|
8156
|
+
console.error(`[Flywheel] Hub scores: eigenvector too sparse (${result.size}/${N}), falling back to degree centrality`);
|
|
8157
|
+
result.clear();
|
|
8158
|
+
let maxDegree = 0;
|
|
8159
|
+
for (let i = 0; i < N; i++) {
|
|
8160
|
+
if (adj[i].length > maxDegree) maxDegree = adj[i].length;
|
|
8161
|
+
}
|
|
8162
|
+
if (maxDegree > 0) {
|
|
8163
|
+
for (let i = 0; i < N; i++) {
|
|
8164
|
+
const scaled = Math.round(adj[i].length / maxDegree * 100);
|
|
8165
|
+
if (scaled > 0) result.set(nodes[i], scaled);
|
|
8166
|
+
}
|
|
8167
|
+
}
|
|
8168
|
+
}
|
|
8169
|
+
return { scores: result, edgeCount };
|
|
8151
8170
|
}
|
|
8152
8171
|
function updateHubScoresInDb(stateDb2, hubScores) {
|
|
8153
8172
|
const updateStmt = stateDb2.db.prepare(`
|
|
@@ -8170,8 +8189,8 @@ async function exportHubScores(vaultIndex2, stateDb2) {
|
|
|
8170
8189
|
console.error("[Flywheel] No StateDb available, skipping hub score export");
|
|
8171
8190
|
return 0;
|
|
8172
8191
|
}
|
|
8173
|
-
const hubScores = computeHubScores(vaultIndex2);
|
|
8174
|
-
console.error(`[Flywheel] Computed hub scores for ${hubScores.size} notes`);
|
|
8192
|
+
const { scores: hubScores, edgeCount } = computeHubScores(vaultIndex2);
|
|
8193
|
+
console.error(`[Flywheel] Computed hub scores for ${hubScores.size} notes (${edgeCount} edges in graph)`);
|
|
8175
8194
|
try {
|
|
8176
8195
|
const updated = updateHubScoresInDb(stateDb2, hubScores);
|
|
8177
8196
|
console.error(`[Flywheel] Updated ${updated} hub scores in StateDb`);
|
|
@@ -8888,6 +8907,7 @@ var PipelineRunner = class {
|
|
|
8888
8907
|
await runStep("tag_scan", tracker, { files: p.events.length }, () => this.tagScan());
|
|
8889
8908
|
await runStep("retrieval_cooccurrence", tracker, {}, () => this.retrievalCooccurrence());
|
|
8890
8909
|
await runStep("integrity_check", tracker, {}, () => this.integrityCheck());
|
|
8910
|
+
await runStep("maintenance", tracker, {}, () => this.maintenance());
|
|
8891
8911
|
const duration = Date.now() - this.batchStart;
|
|
8892
8912
|
if (p.sd) {
|
|
8893
8913
|
recordIndexEvent(p.sd, {
|
|
@@ -9690,6 +9710,21 @@ var PipelineRunner = class {
|
|
|
9690
9710
|
return { integrity: "failed", detail: result.detail };
|
|
9691
9711
|
}
|
|
9692
9712
|
}
|
|
9713
|
+
// ── Maintenance: periodic incremental vacuum ─────────────────────
|
|
9714
|
+
async maintenance() {
|
|
9715
|
+
const { p } = this;
|
|
9716
|
+
if (!p.sd) return { skipped: true, reason: "no statedb" };
|
|
9717
|
+
const VACUUM_INTERVAL_MS = 60 * 60 * 1e3;
|
|
9718
|
+
const lastRow = p.sd.getMetadataValue.get("last_incremental_vacuum");
|
|
9719
|
+
const lastVacuum = lastRow ? parseInt(lastRow.value, 10) : 0;
|
|
9720
|
+
if (Date.now() - lastVacuum < VACUUM_INTERVAL_MS) {
|
|
9721
|
+
return { skipped: true, reason: "vacuumed recently" };
|
|
9722
|
+
}
|
|
9723
|
+
p.sd.db.pragma("incremental_vacuum");
|
|
9724
|
+
p.sd.setMetadataValue.run("last_incremental_vacuum", String(Date.now()));
|
|
9725
|
+
serverLog("watcher", "Incremental vacuum completed");
|
|
9726
|
+
return { vacuumed: true };
|
|
9727
|
+
}
|
|
9693
9728
|
};
|
|
9694
9729
|
|
|
9695
9730
|
// src/core/read/logging.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velvetmonkey/flywheel-memory",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.154",
|
|
4
4
|
"description": "MCP tools that search, write, and auto-link your Obsidian vault — and learn from your edits.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@huggingface/transformers": "^3.8.1",
|
|
56
56
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
57
|
-
"@velvetmonkey/vault-core": "^2.0.
|
|
57
|
+
"@velvetmonkey/vault-core": "^2.0.154",
|
|
58
58
|
"better-sqlite3": "^12.0.0",
|
|
59
59
|
"chokidar": "^4.0.0",
|
|
60
60
|
"gray-matter": "^4.0.3",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"engines": {
|
|
76
76
|
"node": ">=22.0.0"
|
|
77
77
|
},
|
|
78
|
-
"license": "
|
|
78
|
+
"license": "Apache-2.0",
|
|
79
79
|
"files": [
|
|
80
80
|
"bin",
|
|
81
81
|
"dist",
|