@velvetmonkey/flywheel-memory 2.0.23 → 2.0.25
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.js +56 -10
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1839,6 +1839,7 @@ var MAX_FILE_SIZE2 = 5 * 1024 * 1024;
|
|
|
1839
1839
|
var db = null;
|
|
1840
1840
|
var pipeline = null;
|
|
1841
1841
|
var initPromise = null;
|
|
1842
|
+
var embeddingsBuilding = false;
|
|
1842
1843
|
var embeddingCache = /* @__PURE__ */ new Map();
|
|
1843
1844
|
var EMBEDDING_CACHE_MAX = 500;
|
|
1844
1845
|
var entityEmbeddingsMap = /* @__PURE__ */ new Map();
|
|
@@ -1894,6 +1895,7 @@ async function buildEmbeddingsIndex(vaultPath2, onProgress) {
|
|
|
1894
1895
|
if (!db) {
|
|
1895
1896
|
throw new Error("Embeddings database not initialized. Call setEmbeddingsDatabase() first.");
|
|
1896
1897
|
}
|
|
1898
|
+
embeddingsBuilding = true;
|
|
1897
1899
|
await initEmbeddings();
|
|
1898
1900
|
const files = await scanVault(vaultPath2);
|
|
1899
1901
|
const indexable = files.filter((f) => shouldIndexFile(f.path));
|
|
@@ -1937,6 +1939,7 @@ async function buildEmbeddingsIndex(vaultPath2, onProgress) {
|
|
|
1937
1939
|
deleteStmt.run(existingPath);
|
|
1938
1940
|
}
|
|
1939
1941
|
}
|
|
1942
|
+
embeddingsBuilding = false;
|
|
1940
1943
|
console.error(`[Semantic] Indexed ${progress.current - progress.skipped} notes, skipped ${progress.skipped}`);
|
|
1941
1944
|
return progress;
|
|
1942
1945
|
}
|
|
@@ -2034,6 +2037,12 @@ function reciprocalRankFusion(...lists) {
|
|
|
2034
2037
|
}
|
|
2035
2038
|
return scores;
|
|
2036
2039
|
}
|
|
2040
|
+
function isEmbeddingsBuilding() {
|
|
2041
|
+
return embeddingsBuilding;
|
|
2042
|
+
}
|
|
2043
|
+
function setEmbeddingsBuilding(value) {
|
|
2044
|
+
embeddingsBuilding = value;
|
|
2045
|
+
}
|
|
2037
2046
|
function hasEmbeddingsIndex() {
|
|
2038
2047
|
if (!db) return false;
|
|
2039
2048
|
try {
|
|
@@ -6934,6 +6943,7 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig = () =>
|
|
|
6934
6943
|
}).optional().describe("Most recent index rebuild event"),
|
|
6935
6944
|
fts5_ready: z3.boolean().describe("Whether the FTS5 keyword search index is ready"),
|
|
6936
6945
|
fts5_building: z3.boolean().describe("Whether the FTS5 keyword search index is currently building"),
|
|
6946
|
+
embeddings_building: z3.boolean().describe("Whether semantic embeddings are currently building"),
|
|
6937
6947
|
embeddings_ready: z3.boolean().describe("Whether semantic embeddings have been built (enables hybrid keyword+semantic search)"),
|
|
6938
6948
|
embeddings_count: z3.coerce.number().describe("Number of notes with semantic embeddings"),
|
|
6939
6949
|
recommendations: z3.array(z3.string()).describe("Suggested actions if any issues detected")
|
|
@@ -7041,6 +7051,7 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig = () =>
|
|
|
7041
7051
|
last_rebuild: lastRebuild,
|
|
7042
7052
|
fts5_ready: ftsState.ready,
|
|
7043
7053
|
fts5_building: ftsState.building,
|
|
7054
|
+
embeddings_building: isEmbeddingsBuilding(),
|
|
7044
7055
|
embeddings_ready: hasEmbeddingsIndex(),
|
|
7045
7056
|
embeddings_count: getEmbeddingsCount(),
|
|
7046
7057
|
recommendations
|
|
@@ -14871,7 +14882,6 @@ async function main() {
|
|
|
14871
14882
|
setEmbeddingsDatabase(stateDb.db);
|
|
14872
14883
|
loadEntityEmbeddingsToMemory();
|
|
14873
14884
|
setWriteStateDb(stateDb);
|
|
14874
|
-
await initializeEntityIndex(vaultPath);
|
|
14875
14885
|
} catch (err) {
|
|
14876
14886
|
const msg = err instanceof Error ? err.message : String(err);
|
|
14877
14887
|
console.error(`[Memory] StateDb initialization failed: ${msg}`);
|
|
@@ -14890,6 +14900,19 @@ async function main() {
|
|
|
14890
14900
|
initializeLogger2(vaultPath).catch((err) => {
|
|
14891
14901
|
console.error(`[Memory] Write logger initialization failed: ${err}`);
|
|
14892
14902
|
});
|
|
14903
|
+
if (process.env.FLYWHEEL_SKIP_FTS5 !== "true") {
|
|
14904
|
+
if (isIndexStale(vaultPath)) {
|
|
14905
|
+
buildFTS5Index(vaultPath).then(() => {
|
|
14906
|
+
console.error("[Memory] FTS5 search index ready");
|
|
14907
|
+
}).catch((err) => {
|
|
14908
|
+
console.error("[Memory] FTS5 build failed:", err);
|
|
14909
|
+
});
|
|
14910
|
+
} else {
|
|
14911
|
+
console.error("[Memory] FTS5 search index already fresh, skipping rebuild");
|
|
14912
|
+
}
|
|
14913
|
+
} else {
|
|
14914
|
+
console.error("[Memory] FTS5 indexing skipped (FLYWHEEL_SKIP_FTS5=true)");
|
|
14915
|
+
}
|
|
14893
14916
|
let cachedIndex = null;
|
|
14894
14917
|
if (stateDb) {
|
|
14895
14918
|
try {
|
|
@@ -14987,6 +15010,7 @@ async function updateEntitiesInStateDb() {
|
|
|
14987
15010
|
}
|
|
14988
15011
|
async function runPostIndexWork(index) {
|
|
14989
15012
|
await updateEntitiesInStateDb();
|
|
15013
|
+
await initializeEntityIndex(vaultPath);
|
|
14990
15014
|
await exportHubScores(index, stateDb);
|
|
14991
15015
|
if (stateDb) {
|
|
14992
15016
|
try {
|
|
@@ -15016,15 +15040,6 @@ async function runPostIndexWork(index) {
|
|
|
15016
15040
|
console.error("[Memory] Failed to update suppression list:", err);
|
|
15017
15041
|
}
|
|
15018
15042
|
}
|
|
15019
|
-
if (isIndexStale(vaultPath)) {
|
|
15020
|
-
buildFTS5Index(vaultPath).then(() => {
|
|
15021
|
-
console.error("[Memory] FTS5 search index ready");
|
|
15022
|
-
}).catch((err) => {
|
|
15023
|
-
console.error("[Memory] FTS5 build failed:", err);
|
|
15024
|
-
});
|
|
15025
|
-
} else {
|
|
15026
|
-
console.error("[Memory] FTS5 search index already fresh, skipping rebuild");
|
|
15027
|
-
}
|
|
15028
15043
|
const existing = loadConfig(stateDb);
|
|
15029
15044
|
const inferred = inferConfig(index, vaultPath);
|
|
15030
15045
|
if (stateDb) {
|
|
@@ -15034,6 +15049,37 @@ async function runPostIndexWork(index) {
|
|
|
15034
15049
|
if (flywheelConfig.vault_name) {
|
|
15035
15050
|
console.error(`[Memory] Vault: ${flywheelConfig.vault_name}`);
|
|
15036
15051
|
}
|
|
15052
|
+
if (process.env.FLYWHEEL_SKIP_EMBEDDINGS !== "true") {
|
|
15053
|
+
if (hasEmbeddingsIndex()) {
|
|
15054
|
+
console.error("[Memory] Embeddings already built, skipping full scan");
|
|
15055
|
+
} else {
|
|
15056
|
+
setEmbeddingsBuilding(true);
|
|
15057
|
+
buildEmbeddingsIndex(vaultPath, (p) => {
|
|
15058
|
+
if (p.current % 100 === 0 || p.current === p.total) {
|
|
15059
|
+
console.error(`[Semantic] ${p.current}/${p.total}`);
|
|
15060
|
+
}
|
|
15061
|
+
}).then(async () => {
|
|
15062
|
+
if (stateDb) {
|
|
15063
|
+
const entities = getAllEntitiesFromDb2(stateDb);
|
|
15064
|
+
if (entities.length > 0) {
|
|
15065
|
+
const entityMap = new Map(entities.map((e) => [e.name, {
|
|
15066
|
+
name: e.name,
|
|
15067
|
+
path: e.path,
|
|
15068
|
+
category: e.category,
|
|
15069
|
+
aliases: e.aliases
|
|
15070
|
+
}]));
|
|
15071
|
+
await buildEntityEmbeddingsIndex(vaultPath, entityMap);
|
|
15072
|
+
}
|
|
15073
|
+
}
|
|
15074
|
+
loadEntityEmbeddingsToMemory();
|
|
15075
|
+
console.error("[Memory] Embeddings refreshed");
|
|
15076
|
+
}).catch((err) => {
|
|
15077
|
+
console.error("[Memory] Embeddings refresh failed:", err);
|
|
15078
|
+
});
|
|
15079
|
+
}
|
|
15080
|
+
} else {
|
|
15081
|
+
console.error("[Memory] Embeddings skipped (FLYWHEEL_SKIP_EMBEDDINGS=true)");
|
|
15082
|
+
}
|
|
15037
15083
|
if (process.env.FLYWHEEL_WATCH !== "false") {
|
|
15038
15084
|
const config = parseWatcherConfig();
|
|
15039
15085
|
console.error(`[Memory] File watcher enabled (debounce: ${config.debounceMs}ms)`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velvetmonkey/flywheel-memory",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.25",
|
|
4
4
|
"description": "MCP server that gives Claude full read/write access to your Obsidian vault. 42 tools for search, backlinks, graph queries, mutations, and hybrid semantic search.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
53
|
-
"@velvetmonkey/vault-core": "^2.0.
|
|
53
|
+
"@velvetmonkey/vault-core": "^2.0.25",
|
|
54
54
|
"better-sqlite3": "^11.0.0",
|
|
55
55
|
"chokidar": "^4.0.0",
|
|
56
56
|
"gray-matter": "^4.0.3",
|