@velvetmonkey/flywheel-memory 2.0.72 → 2.0.73

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 (2) hide show
  1. package/dist/index.js +27 -6
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1969,8 +1969,11 @@ async function buildEmbeddingsIndex(vaultPath2, onProgress) {
1969
1969
  const embedding = await embedText(content);
1970
1970
  const buf = Buffer.from(embedding.buffer, embedding.byteOffset, embedding.byteLength);
1971
1971
  upsert.run(file.path, buf, hash, activeModelConfig.id, Date.now());
1972
- } catch {
1972
+ } catch (err) {
1973
1973
  progress.skipped++;
1974
+ if (progress.skipped <= 3) {
1975
+ console.error(`[Semantic] Failed to embed ${file.path}: ${err instanceof Error ? err.message : err}`);
1976
+ }
1974
1977
  }
1975
1978
  if (onProgress) onProgress(progress);
1976
1979
  }
@@ -8292,6 +8295,7 @@ function registerWikilinkTools(server2, getIndex, getVaultPath) {
8292
8295
  },
8293
8296
  async ({ text, limit: requestedLimit, offset, detail }) => {
8294
8297
  const limit = Math.min(requestedLimit ?? 50, MAX_LIMIT);
8298
+ requireIndex();
8295
8299
  const index = getIndex();
8296
8300
  const allMatches = findEntityMatches(text, index.entities);
8297
8301
  const matches = allMatches.slice(offset, offset + limit);
@@ -8389,11 +8393,19 @@ function registerWikilinkTools(server2, getIndex, getVaultPath) {
8389
8393
  });
8390
8394
  const ValidateLinksOutputSchema = {
8391
8395
  scope: z2.string().describe('What was validated (note path or "all")'),
8392
- total_links: z2.coerce.number().describe("Total number of links checked"),
8393
- valid_links: z2.coerce.number().describe("Number of valid links"),
8394
- broken_links: z2.coerce.number().describe("Total number of broken links"),
8396
+ total_links: z2.coerce.number().optional().describe("Total number of links checked"),
8397
+ valid_links: z2.coerce.number().optional().describe("Number of valid links"),
8398
+ broken_links: z2.coerce.number().optional().describe("Total number of broken links"),
8395
8399
  returned_count: z2.coerce.number().describe("Number of broken links returned (may be limited)"),
8396
- broken: z2.array(BrokenLinkSchema).describe("List of broken links")
8400
+ broken: z2.array(BrokenLinkSchema).optional().describe("List of broken links"),
8401
+ total_dead_targets: z2.coerce.number().optional().describe("Number of unique dead link targets (group_by_target mode)"),
8402
+ total_broken_links: z2.coerce.number().optional().describe("Total broken links across all targets (group_by_target mode)"),
8403
+ targets: z2.array(z2.object({
8404
+ target: z2.string(),
8405
+ mention_count: z2.coerce.number(),
8406
+ sources: z2.array(z2.string()),
8407
+ suggestion: z2.string().optional()
8408
+ })).optional().describe("Dead link targets grouped by frequency (group_by_target mode)")
8397
8409
  };
8398
8410
  function findSimilarEntity2(target, entities) {
8399
8411
  const targetLower = target.toLowerCase();
@@ -8425,6 +8437,7 @@ function registerWikilinkTools(server2, getIndex, getVaultPath) {
8425
8437
  },
8426
8438
  async ({ path: notePath, typos_only, group_by_target, limit: requestedLimit, offset }) => {
8427
8439
  const limit = Math.min(requestedLimit ?? 50, MAX_LIMIT);
8440
+ requireIndex();
8428
8441
  const index = getIndex();
8429
8442
  const allBroken = [];
8430
8443
  let totalLinks = 0;
@@ -8530,6 +8543,7 @@ function registerWikilinkTools(server2, getIndex, getVaultPath) {
8530
8543
  }
8531
8544
  },
8532
8545
  async ({ min_frequency, limit: requestedLimit }) => {
8546
+ requireIndex();
8533
8547
  const index = getIndex();
8534
8548
  const limit = Math.min(requestedLimit ?? 20, 100);
8535
8549
  const minFreq = min_frequency ?? 2;
@@ -8578,6 +8592,7 @@ function registerWikilinkTools(server2, getIndex, getVaultPath) {
8578
8592
  }
8579
8593
  },
8580
8594
  async ({ min_cooccurrence, limit: requestedLimit }) => {
8595
+ requireIndex();
8581
8596
  const index = getIndex();
8582
8597
  const coocIndex = getCooccurrenceIndex();
8583
8598
  const limit = Math.min(requestedLimit ?? 20, 100);
@@ -11770,6 +11785,10 @@ function isPeriodicNote(notePath) {
11770
11785
  const folder = notePath.split("/")[0]?.toLowerCase() || "";
11771
11786
  return patterns.some((p) => p.test(nameWithoutExt)) || periodicFolders.includes(folder);
11772
11787
  }
11788
+ function isTemplatePath(notePath) {
11789
+ const folder = notePath.split("/")[0]?.toLowerCase() || "";
11790
+ return folder === "templates" || folder === "template";
11791
+ }
11773
11792
  function getExcludedPaths(index, config) {
11774
11793
  const excluded = /* @__PURE__ */ new Set();
11775
11794
  const excludeTags = new Set((config.exclude_analysis_tags ?? []).map((t) => t.toLowerCase()));
@@ -11893,7 +11912,9 @@ function registerGraphAnalysisTools(server2, getIndex, getVaultPath, getStateDb,
11893
11912
  }, null, 2) }]
11894
11913
  };
11895
11914
  }
11896
- const result = getStaleNotes(index, days, min_backlinks).filter((n) => !excludedPaths.has(n.path)).slice(0, limit);
11915
+ const result = getStaleNotes(index, days, min_backlinks).filter(
11916
+ (n) => !excludedPaths.has(n.path) && !isPeriodicNote(n.path) && !isTemplatePath(n.path)
11917
+ ).slice(0, limit);
11897
11918
  return {
11898
11919
  content: [{ type: "text", text: JSON.stringify({
11899
11920
  analysis: "stale",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velvetmonkey/flywheel-memory",
3
- "version": "2.0.72",
3
+ "version": "2.0.73",
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.72",
55
+ "@velvetmonkey/vault-core": "^2.0.73",
56
56
  "better-sqlite3": "^11.0.0",
57
57
  "chokidar": "^4.0.0",
58
58
  "gray-matter": "^4.0.3",