@velvetmonkey/flywheel-memory 2.1.1 → 2.1.3

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.
Files changed (3) hide show
  1. package/README.md +4 -4
  2. package/dist/index.js +15 -18
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -26,7 +26,7 @@
26
26
  | "What should I link?" | Not possible | 10-dimension scoring + semantic search |
27
27
  | Hubs, orphans, paths? | Not possible | Pre-indexed graph analysis |
28
28
 
29
- 76 tools across 12 categories. 6-line config. Zero cloud dependencies.
29
+ 75 tools across 12 categories. 6-line config. Zero cloud dependencies.
30
30
 
31
31
  **Try in 60 seconds:**
32
32
 
@@ -273,10 +273,10 @@ Every mutation is:
273
273
  | Schema intelligence | 6 analysis modes | No | No | No |
274
274
  | Entity extraction | Auto (18 categories) | No | No | No |
275
275
  | Learns from usage | Feedback loop + suppression | No | No | No |
276
- | Agent memory | brief + recall + memory | No | No | No |
276
+ | Agent memory | brief + search + memory | No | No | No |
277
277
  | Safe writes | Git + conflict detection | No | N/A | N/A |
278
278
  | Test coverage | 2,456 tests | Unknown | Unknown | Unknown |
279
- | Tool count | 72 | ~10 | 0 (plugin) | ~5 |
279
+ | Tool count | 75 | ~10 | 0 (plugin) | ~5 |
280
280
 
281
281
  ---
282
282
 
@@ -385,7 +385,7 @@ The fewer tools you load, the less context the AI needs to pick the right one. S
385
385
  | Doc | Why read this |
386
386
  |---|---|
387
387
  | [PROVE-IT.md](https://github.com/velvetmonkey/flywheel-memory/blob/main/docs/PROVE-IT.md) | See it working in 5 minutes |
388
- | [TOOLS.md](https://github.com/velvetmonkey/flywheel-memory/blob/main/docs/TOOLS.md) | All 76 tools documented |
388
+ | [TOOLS.md](https://github.com/velvetmonkey/flywheel-memory/blob/main/docs/TOOLS.md) | All 75 tools documented |
389
389
  | [ALGORITHM.md](https://github.com/velvetmonkey/flywheel-memory/blob/main/docs/ALGORITHM.md) | How the scoring works |
390
390
  | [COOKBOOK.md](https://github.com/velvetmonkey/flywheel-memory/blob/main/docs/COOKBOOK.md) | Example prompts by use case |
391
391
  | [SETUP.md](https://github.com/velvetmonkey/flywheel-memory/blob/main/docs/SETUP.md) | Full setup guide for your vault |
package/dist/index.js CHANGED
@@ -10589,7 +10589,6 @@ function parseEnabledCategories(envValue) {
10589
10589
  }
10590
10590
  if (DEPRECATED_ALIASES[lowerValue]) {
10591
10591
  const resolved = DEPRECATED_ALIASES[lowerValue];
10592
- serverLog("server", `Preset "${lowerValue}" is deprecated \u2014 use "${resolved}" instead`, "warn");
10593
10592
  if (PRESETS[resolved]) {
10594
10593
  return new Set(PRESETS[resolved]);
10595
10594
  }
@@ -10599,9 +10598,6 @@ function parseEnabledCategories(envValue) {
10599
10598
  for (const item of raw.split(",")) {
10600
10599
  const rawItem = item.trim().toLowerCase();
10601
10600
  const resolved = DEPRECATED_ALIASES[rawItem] ?? rawItem;
10602
- if (resolved !== rawItem) {
10603
- serverLog("server", `Category "${rawItem}" is deprecated \u2014 use "${resolved}" instead`, "warn");
10604
- }
10605
10601
  if (ALL_CATEGORIES.includes(resolved)) {
10606
10602
  categories.add(resolved);
10607
10603
  } else if (PRESETS[resolved]) {
@@ -14162,7 +14158,7 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig2 = () =>
14162
14158
  const linkDensity = Math.min(1, avgOutlinks / 3);
14163
14159
  let orphanCount = 0;
14164
14160
  for (const note of index.notes.values()) {
14165
- const bl = index.backlinks.get(note.title.toLowerCase());
14161
+ const bl = index.backlinks.get(normalizeTarget(note.path));
14166
14162
  if (!bl || bl.length === 0) orphanCount++;
14167
14163
  }
14168
14164
  const orphanRatio = 1 - orphanCount / noteCount;
@@ -16343,8 +16339,8 @@ function findContradictions2(index, entity) {
16343
16339
  entitiesToCheck.push([name, entityPath]);
16344
16340
  }
16345
16341
  }
16346
- for (const [entityName, _entityPath] of entitiesToCheck) {
16347
- const backlinks = index.backlinks.get(entityName);
16342
+ for (const [entityName, entityPath] of entitiesToCheck) {
16343
+ const backlinks = index.backlinks.get(normalizeTarget(entityPath));
16348
16344
  if (!backlinks || backlinks.length < 2) continue;
16349
16345
  const sourcePaths = [...new Set(backlinks.map((bl) => bl.source))];
16350
16346
  if (sourcePaths.length < 2) continue;
@@ -16579,8 +16575,8 @@ function registerGraphAnalysisTools(server2, getIndex, getVaultPath, getStateDb3
16579
16575
  } else {
16580
16576
  frontmatterScore = 1;
16581
16577
  }
16582
- const normalizedTitle = note.title.toLowerCase();
16583
- const backlinks = index.backlinks.get(normalizedTitle) || [];
16578
+ const normalizedPath = normalizeTarget(note.path);
16579
+ const backlinks = index.backlinks.get(normalizedPath) || [];
16584
16580
  const backlinkCount = backlinks.length;
16585
16581
  const backlinkScore = backlinkCount === 0 ? 0 : backlinkCount <= 2 ? 0.5 : 1;
16586
16582
  const maturity = (wordScore + outlinkScore + frontmatterScore + backlinkScore) / 4;
@@ -17462,7 +17458,7 @@ async function computeFrontmatter(index, notePath, vaultPath2, fields) {
17462
17458
  break;
17463
17459
  }
17464
17460
  case "backlink_count": {
17465
- const backlinks = index.backlinks.get(note?.title.toLowerCase() ?? "");
17461
+ const backlinks = index.backlinks.get(normalizeTarget(note?.path ?? ""));
17466
17462
  value = backlinks?.length ?? 0;
17467
17463
  method = "backlink_index";
17468
17464
  break;
@@ -17604,7 +17600,8 @@ function registerNoteIntelligenceTools(server2, getIndex, getVaultPath, getConfi
17604
17600
  const suggestions = matches.filter((m) => {
17605
17601
  if (m.similarity < 0.3) return false;
17606
17602
  if (excludeTags.size > 0) {
17607
- const entityNote = index.notes.get(m.entityName.toLowerCase() + ".md") ?? [...index.notes.values()].find((n) => n.title.toLowerCase() === m.entityName.toLowerCase());
17603
+ const entityPath = index.entities.get(m.entityName.toLowerCase());
17604
+ const entityNote = entityPath ? index.notes.get(entityPath) : [...index.notes.values()].find((n) => n.title.toLowerCase() === m.entityName.toLowerCase());
17608
17605
  if (entityNote) {
17609
17606
  const noteTags = Object.keys(entityNote.frontmatter).filter((k) => k === "tags").flatMap((k) => {
17610
17607
  const v = entityNote.frontmatter[k];
@@ -22760,9 +22757,9 @@ function registerActivityTools(server2, getStateDb3, getSessionId2) {
22760
22757
  import { z as z31 } from "zod";
22761
22758
 
22762
22759
  // src/core/read/similarity.ts
22763
- init_embeddings();
22764
22760
  import * as fs33 from "fs";
22765
22761
  import * as path36 from "path";
22762
+ init_embeddings();
22766
22763
 
22767
22764
  // src/core/read/mmr.ts
22768
22765
  init_embeddings();
@@ -22862,8 +22859,8 @@ function findSimilarNotes(db4, vaultPath2, index, sourcePath, options = {}) {
22862
22859
  const resolved = index.entities.get(link.target.toLowerCase());
22863
22860
  if (resolved) linkedPaths.add(resolved);
22864
22861
  }
22865
- const normalizedTitle = note.title.toLowerCase();
22866
- const backlinks = index.backlinks.get(normalizedTitle) || [];
22862
+ const normalizedPath = normalizeTarget(note.path);
22863
+ const backlinks = index.backlinks.get(normalizedPath) || [];
22867
22864
  for (const bl of backlinks) {
22868
22865
  linkedPaths.add(bl.source);
22869
22866
  }
@@ -22888,8 +22885,8 @@ function getLinkedPaths(index, sourcePath) {
22888
22885
  const resolved = index.entities.get(link.target.toLowerCase());
22889
22886
  if (resolved) linkedPaths.add(resolved);
22890
22887
  }
22891
- const normalizedTitle = note.title.toLowerCase();
22892
- const backlinks = index.backlinks.get(normalizedTitle) || [];
22888
+ const normalizedPath = normalizeTarget(note.path);
22889
+ const backlinks = index.backlinks.get(normalizedPath) || [];
22893
22890
  for (const bl of backlinks) {
22894
22891
  linkedPaths.add(bl.source);
22895
22892
  }
@@ -24652,8 +24649,8 @@ function registerVaultResources(server2, getIndex) {
24652
24649
  }
24653
24650
  let orphanCount = 0;
24654
24651
  for (const note of index.notes.values()) {
24655
- const normalizedTitle = note.title.toLowerCase();
24656
- const backlinks = index.backlinks.get(normalizedTitle);
24652
+ const normalizedPath = normalizeTarget(note.path);
24653
+ const backlinks = index.backlinks.get(normalizedPath);
24657
24654
  if (!backlinks || backlinks.length === 0) {
24658
24655
  orphanCount++;
24659
24656
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@velvetmonkey/flywheel-memory",
3
- "version": "2.1.1",
4
- "description": "MCP tools that search, write, and auto-link your Obsidian vault and learn from your edits.",
3
+ "version": "2.1.3",
4
+ "description": "MCP tools that search, write, and auto-link your Obsidian vault \u2014 and learn from your edits.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
@@ -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.1.1",
57
+ "@velvetmonkey/vault-core": "^2.1.3",
58
58
  "better-sqlite3": "^12.0.0",
59
59
  "chokidar": "^4.0.0",
60
60
  "gray-matter": "^4.0.3",