@velvetmonkey/flywheel-memory 2.0.77 → 2.0.78
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 +75 -21
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9592,7 +9592,8 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig = () =>
|
|
|
9592
9592
|
import { z as z4 } from "zod";
|
|
9593
9593
|
import {
|
|
9594
9594
|
searchEntities,
|
|
9595
|
-
searchEntitiesPrefix
|
|
9595
|
+
searchEntitiesPrefix,
|
|
9596
|
+
getEntityByName as getEntityByName2
|
|
9596
9597
|
} from "@velvetmonkey/vault-core";
|
|
9597
9598
|
function matchesFrontmatter(note, where) {
|
|
9598
9599
|
for (const [key, value] of Object.entries(where)) {
|
|
@@ -9640,6 +9641,37 @@ function inFolder(note, folder) {
|
|
|
9640
9641
|
const normalizedFolder = folder.endsWith("/") ? folder : folder + "/";
|
|
9641
9642
|
return note.path.startsWith(normalizedFolder) || note.path.split("/")[0] === folder.replace("/", "");
|
|
9642
9643
|
}
|
|
9644
|
+
function enrichResult(result, index, stateDb2) {
|
|
9645
|
+
const note = index.notes.get(result.path);
|
|
9646
|
+
const normalizedPath = result.path.toLowerCase().replace(/\.md$/, "");
|
|
9647
|
+
const backlinks = index.backlinks.get(normalizedPath) || [];
|
|
9648
|
+
const enriched = {
|
|
9649
|
+
path: result.path,
|
|
9650
|
+
title: result.title
|
|
9651
|
+
};
|
|
9652
|
+
if (result.snippet) enriched.snippet = result.snippet;
|
|
9653
|
+
if (note) {
|
|
9654
|
+
enriched.frontmatter = note.frontmatter;
|
|
9655
|
+
enriched.tags = note.tags;
|
|
9656
|
+
enriched.aliases = note.aliases;
|
|
9657
|
+
enriched.backlink_count = backlinks.length;
|
|
9658
|
+
enriched.outlink_count = note.outlinks.length;
|
|
9659
|
+
enriched.modified = note.modified.toISOString();
|
|
9660
|
+
if (note.created) enriched.created = note.created.toISOString();
|
|
9661
|
+
}
|
|
9662
|
+
if (stateDb2) {
|
|
9663
|
+
try {
|
|
9664
|
+
const entity = getEntityByName2(stateDb2, result.title);
|
|
9665
|
+
if (entity) {
|
|
9666
|
+
enriched.category = entity.category;
|
|
9667
|
+
enriched.hub_score = entity.hubScore;
|
|
9668
|
+
if (entity.description) enriched.description = entity.description;
|
|
9669
|
+
}
|
|
9670
|
+
} catch {
|
|
9671
|
+
}
|
|
9672
|
+
}
|
|
9673
|
+
return enriched;
|
|
9674
|
+
}
|
|
9643
9675
|
function sortNotes(notes, sortBy, order) {
|
|
9644
9676
|
const sorted = [...notes];
|
|
9645
9677
|
sorted.sort((a, b) => {
|
|
@@ -9847,22 +9879,20 @@ function registerQueryTools(server2, getIndex, getVaultPath, getStateDb) {
|
|
|
9847
9879
|
const fts5Map = new Map(fts5Results.map((r) => [normalizePath2(r.path), r]));
|
|
9848
9880
|
const semanticMap = new Map(semanticResults.map((r) => [normalizePath2(r.path), r]));
|
|
9849
9881
|
const entityMap = new Map(entityResults.map((r) => [normalizePath2(r.path), r]));
|
|
9850
|
-
const merged = Array.from(allPaths).map((p) =>
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
}));
|
|
9859
|
-
merged.sort((a, b) => b.rrf_score - a.rrf_score);
|
|
9882
|
+
const merged = Array.from(allPaths).map((p) => {
|
|
9883
|
+
const title = fts5Map.get(p)?.title || semanticMap.get(p)?.title || entityMap.get(p)?.name || p.replace(/\.md$/, "").split("/").pop() || p;
|
|
9884
|
+
const snippet = fts5Map.get(p)?.snippet;
|
|
9885
|
+
const rrfScore = rrfScores.get(p) || 0;
|
|
9886
|
+
return { rrfScore, ...enrichResult({ path: p, title, snippet }, index, getStateDb()) };
|
|
9887
|
+
});
|
|
9888
|
+
merged.sort((a, b) => b.rrfScore - a.rrfScore);
|
|
9889
|
+
const results = merged.slice(0, limit).map(({ rrfScore, ...rest }) => rest);
|
|
9860
9890
|
return { content: [{ type: "text", text: JSON.stringify({
|
|
9861
9891
|
scope,
|
|
9862
9892
|
method: "hybrid",
|
|
9863
9893
|
query,
|
|
9864
9894
|
total_results: Math.min(merged.length, limit),
|
|
9865
|
-
results
|
|
9895
|
+
results
|
|
9866
9896
|
}, null, 2) }] };
|
|
9867
9897
|
} catch (err) {
|
|
9868
9898
|
console.error("[Semantic] Hybrid search failed, falling back to FTS5:", err instanceof Error ? err.message : err);
|
|
@@ -9871,11 +9901,10 @@ function registerQueryTools(server2, getIndex, getVaultPath, getStateDb) {
|
|
|
9871
9901
|
if (entityResults.length > 0) {
|
|
9872
9902
|
const normalizePath2 = (p) => p.replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
9873
9903
|
const fts5Map = new Map(fts5Results.map((r) => [normalizePath2(r.path), r]));
|
|
9874
|
-
const entityNormMap = new Map(entityResults.map((r) => [normalizePath2(r.path), r]));
|
|
9875
9904
|
const entityRanked = entityResults.filter((r) => !fts5Map.has(normalizePath2(r.path)));
|
|
9876
9905
|
const merged = [
|
|
9877
|
-
...fts5Results.map((r) => ({ path: r.path, title: r.title, snippet: r.snippet,
|
|
9878
|
-
...entityRanked.map((r) => ({ path: r.path, title: r.name,
|
|
9906
|
+
...fts5Results.map((r) => enrichResult({ path: r.path, title: r.title, snippet: r.snippet }, index, getStateDb())),
|
|
9907
|
+
...entityRanked.map((r) => enrichResult({ path: r.path, title: r.name }, index, getStateDb()))
|
|
9879
9908
|
];
|
|
9880
9909
|
return { content: [{ type: "text", text: JSON.stringify({
|
|
9881
9910
|
scope: "content",
|
|
@@ -9885,12 +9914,13 @@ function registerQueryTools(server2, getIndex, getVaultPath, getStateDb) {
|
|
|
9885
9914
|
results: merged.slice(0, limit)
|
|
9886
9915
|
}, null, 2) }] };
|
|
9887
9916
|
}
|
|
9917
|
+
const enrichedFts5 = fts5Results.map((r) => enrichResult({ path: r.path, title: r.title, snippet: r.snippet }, index, getStateDb()));
|
|
9888
9918
|
return { content: [{ type: "text", text: JSON.stringify({
|
|
9889
9919
|
scope: "content",
|
|
9890
9920
|
method: "fts5",
|
|
9891
9921
|
query,
|
|
9892
|
-
total_results:
|
|
9893
|
-
results:
|
|
9922
|
+
total_results: enrichedFts5.length,
|
|
9923
|
+
results: enrichedFts5
|
|
9894
9924
|
}, null, 2) }] };
|
|
9895
9925
|
}
|
|
9896
9926
|
return { content: [{ type: "text", text: JSON.stringify({ error: "Invalid scope" }, null, 2) }] };
|
|
@@ -10701,7 +10731,8 @@ async function findSections(index, headingPattern, vaultPath2, folder) {
|
|
|
10701
10731
|
}
|
|
10702
10732
|
|
|
10703
10733
|
// src/tools/read/primitives.ts
|
|
10704
|
-
|
|
10734
|
+
import { getEntityByName as getEntityByName3 } from "@velvetmonkey/vault-core";
|
|
10735
|
+
function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig = () => ({}), getStateDb = () => null) {
|
|
10705
10736
|
server2.registerTool(
|
|
10706
10737
|
"get_note_structure",
|
|
10707
10738
|
{
|
|
@@ -10729,8 +10760,31 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig = ()
|
|
|
10729
10760
|
}
|
|
10730
10761
|
}
|
|
10731
10762
|
}
|
|
10763
|
+
const note = index.notes.get(path33);
|
|
10764
|
+
const enriched = { ...result };
|
|
10765
|
+
if (note) {
|
|
10766
|
+
enriched.frontmatter = note.frontmatter;
|
|
10767
|
+
enriched.tags = note.tags;
|
|
10768
|
+
enriched.aliases = note.aliases;
|
|
10769
|
+
const normalizedPath = path33.toLowerCase().replace(/\.md$/, "");
|
|
10770
|
+
const backlinks = index.backlinks.get(normalizedPath) || [];
|
|
10771
|
+
enriched.backlink_count = backlinks.length;
|
|
10772
|
+
enriched.outlink_count = note.outlinks.length;
|
|
10773
|
+
}
|
|
10774
|
+
const stateDb2 = getStateDb();
|
|
10775
|
+
if (stateDb2 && note) {
|
|
10776
|
+
try {
|
|
10777
|
+
const entity = getEntityByName3(stateDb2, note.title);
|
|
10778
|
+
if (entity) {
|
|
10779
|
+
enriched.category = entity.category;
|
|
10780
|
+
enriched.hub_score = entity.hubScore;
|
|
10781
|
+
if (entity.description) enriched.description = entity.description;
|
|
10782
|
+
}
|
|
10783
|
+
} catch {
|
|
10784
|
+
}
|
|
10785
|
+
}
|
|
10732
10786
|
return {
|
|
10733
|
-
content: [{ type: "text", text: JSON.stringify(
|
|
10787
|
+
content: [{ type: "text", text: JSON.stringify(enriched, null, 2) }]
|
|
10734
10788
|
};
|
|
10735
10789
|
}
|
|
10736
10790
|
);
|
|
@@ -19385,7 +19439,7 @@ var ALL_CATEGORIES = [
|
|
|
19385
19439
|
"policy",
|
|
19386
19440
|
"memory"
|
|
19387
19441
|
];
|
|
19388
|
-
var DEFAULT_PRESET = "
|
|
19442
|
+
var DEFAULT_PRESET = "minimal";
|
|
19389
19443
|
function parseEnabledCategories() {
|
|
19390
19444
|
const envValue = (process.env.FLYWHEEL_TOOLS ?? process.env.FLYWHEEL_PRESET)?.trim();
|
|
19391
19445
|
if (!envValue) {
|
|
@@ -19587,7 +19641,7 @@ registerSystemTools(
|
|
|
19587
19641
|
registerGraphTools(server, () => vaultIndex, () => vaultPath, () => stateDb);
|
|
19588
19642
|
registerWikilinkTools(server, () => vaultIndex, () => vaultPath);
|
|
19589
19643
|
registerQueryTools(server, () => vaultIndex, () => vaultPath, () => stateDb);
|
|
19590
|
-
registerPrimitiveTools(server, () => vaultIndex, () => vaultPath, () => flywheelConfig);
|
|
19644
|
+
registerPrimitiveTools(server, () => vaultIndex, () => vaultPath, () => flywheelConfig, () => stateDb);
|
|
19591
19645
|
registerGraphAnalysisTools(server, () => vaultIndex, () => vaultPath, () => stateDb, () => flywheelConfig);
|
|
19592
19646
|
registerVaultSchemaTools(server, () => vaultIndex, () => vaultPath);
|
|
19593
19647
|
registerNoteIntelligenceTools(server, () => vaultIndex, () => vaultPath, () => flywheelConfig);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velvetmonkey/flywheel-memory",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.78",
|
|
4
4
|
"description": "MCP server that gives Claude full read/write access to your Obsidian vault. Select from 51 tools for search, backlinks, graph queries, mutations, agent memory, and hybrid semantic search.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
55
|
-
"@velvetmonkey/vault-core": "^2.0.
|
|
55
|
+
"@velvetmonkey/vault-core": "^2.0.78",
|
|
56
56
|
"better-sqlite3": "^11.0.0",
|
|
57
57
|
"chokidar": "^4.0.0",
|
|
58
58
|
"gray-matter": "^4.0.3",
|