@velvetmonkey/flywheel-memory 2.0.47 → 2.0.48
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 +216 -33
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3594,6 +3594,19 @@ function updateSuppressionList(stateDb2) {
|
|
|
3594
3594
|
transaction();
|
|
3595
3595
|
return updated;
|
|
3596
3596
|
}
|
|
3597
|
+
function suppressEntity(stateDb2, entity) {
|
|
3598
|
+
stateDb2.db.prepare(`
|
|
3599
|
+
INSERT INTO wikilink_suppressions (entity, false_positive_rate, updated_at)
|
|
3600
|
+
VALUES (?, 1.0, datetime('now'))
|
|
3601
|
+
ON CONFLICT(entity) DO UPDATE SET false_positive_rate = 1.0, updated_at = datetime('now')
|
|
3602
|
+
`).run(entity);
|
|
3603
|
+
}
|
|
3604
|
+
function unsuppressEntity(stateDb2, entity) {
|
|
3605
|
+
const result = stateDb2.db.prepare(
|
|
3606
|
+
"DELETE FROM wikilink_suppressions WHERE entity = ? COLLATE NOCASE"
|
|
3607
|
+
).run(entity);
|
|
3608
|
+
return result.changes > 0;
|
|
3609
|
+
}
|
|
3597
3610
|
function isSuppressed(stateDb2, entity, folder) {
|
|
3598
3611
|
const row = stateDb2.db.prepare(
|
|
3599
3612
|
"SELECT entity FROM wikilink_suppressions WHERE entity = ? COLLATE NOCASE"
|
|
@@ -13062,7 +13075,7 @@ Example: vault_add_to_section({ path: "daily/2026-02-15.md", section: "Log", con
|
|
|
13062
13075
|
throw new Error(validationResult.blockReason || "Output validation failed");
|
|
13063
13076
|
}
|
|
13064
13077
|
let workingReplacement = validationResult.content;
|
|
13065
|
-
let { content: processedReplacement } = maybeApplyWikilinks(workingReplacement, skipWikilinks, notePath);
|
|
13078
|
+
let { content: processedReplacement } = maybeApplyWikilinks(workingReplacement, skipWikilinks, notePath, ctx.content);
|
|
13066
13079
|
if (suggestOutgoingLinks && !skipWikilinks && processedReplacement.length >= 100) {
|
|
13067
13080
|
const result = await suggestRelatedLinks(processedReplacement, { maxSuggestions, notePath });
|
|
13068
13081
|
if (result.suffix) {
|
|
@@ -15857,7 +15870,7 @@ function registerWikilinkFeedbackTools(server2, getStateDb) {
|
|
|
15857
15870
|
title: "Wikilink Feedback",
|
|
15858
15871
|
description: 'Report and query wikilink accuracy feedback. Modes: "report" (record feedback), "list" (view recent feedback), "stats" (entity accuracy statistics), "dashboard" (full feedback loop data), "entity_timeline" (score history for an entity), "layer_timeseries" (per-layer contribution over time), "snapshot_diff" (compare two graph snapshots).',
|
|
15859
15872
|
inputSchema: {
|
|
15860
|
-
mode: z21.enum(["report", "list", "stats", "dashboard", "entity_timeline", "layer_timeseries", "snapshot_diff"]).describe("Operation mode"),
|
|
15873
|
+
mode: z21.enum(["report", "list", "stats", "dashboard", "entity_timeline", "layer_timeseries", "snapshot_diff", "suppress", "unsuppress"]).describe("Operation mode"),
|
|
15861
15874
|
entity: z21.string().optional().describe("Entity name (required for report and entity_timeline modes, optional filter for list/stats)"),
|
|
15862
15875
|
note_path: z21.string().optional().describe("Note path where the wikilink appeared (for report mode)"),
|
|
15863
15876
|
context: z21.string().optional().describe("Surrounding text context (for report mode)"),
|
|
@@ -15904,6 +15917,9 @@ function registerWikilinkFeedbackTools(server2, getStateDb) {
|
|
|
15904
15917
|
).run(entity, note_path);
|
|
15905
15918
|
}
|
|
15906
15919
|
const suppressionUpdated = updateSuppressionList(stateDb2) > 0;
|
|
15920
|
+
if (!correct) {
|
|
15921
|
+
suppressEntity(stateDb2, entity);
|
|
15922
|
+
}
|
|
15907
15923
|
result = {
|
|
15908
15924
|
mode: "report",
|
|
15909
15925
|
reported: {
|
|
@@ -15982,6 +15998,38 @@ function registerWikilinkFeedbackTools(server2, getStateDb) {
|
|
|
15982
15998
|
};
|
|
15983
15999
|
break;
|
|
15984
16000
|
}
|
|
16001
|
+
case "suppress": {
|
|
16002
|
+
if (!entity) {
|
|
16003
|
+
return {
|
|
16004
|
+
content: [{ type: "text", text: JSON.stringify({ error: "entity is required for suppress mode" }) }],
|
|
16005
|
+
isError: true
|
|
16006
|
+
};
|
|
16007
|
+
}
|
|
16008
|
+
suppressEntity(stateDb2, entity);
|
|
16009
|
+
result = {
|
|
16010
|
+
mode: "suppress",
|
|
16011
|
+
entity,
|
|
16012
|
+
suppressed: true,
|
|
16013
|
+
total_suppressed: getSuppressedCount(stateDb2)
|
|
16014
|
+
};
|
|
16015
|
+
break;
|
|
16016
|
+
}
|
|
16017
|
+
case "unsuppress": {
|
|
16018
|
+
if (!entity) {
|
|
16019
|
+
return {
|
|
16020
|
+
content: [{ type: "text", text: JSON.stringify({ error: "entity is required for unsuppress mode" }) }],
|
|
16021
|
+
isError: true
|
|
16022
|
+
};
|
|
16023
|
+
}
|
|
16024
|
+
const wasRemoved = unsuppressEntity(stateDb2, entity);
|
|
16025
|
+
result = {
|
|
16026
|
+
mode: "unsuppress",
|
|
16027
|
+
entity,
|
|
16028
|
+
was_suppressed: wasRemoved,
|
|
16029
|
+
total_suppressed: getSuppressedCount(stateDb2)
|
|
16030
|
+
};
|
|
16031
|
+
break;
|
|
16032
|
+
}
|
|
15985
16033
|
}
|
|
15986
16034
|
return {
|
|
15987
16035
|
content: [
|
|
@@ -15995,8 +16043,142 @@ function registerWikilinkFeedbackTools(server2, getStateDb) {
|
|
|
15995
16043
|
);
|
|
15996
16044
|
}
|
|
15997
16045
|
|
|
15998
|
-
// src/tools/write/
|
|
16046
|
+
// src/tools/write/corrections.ts
|
|
15999
16047
|
import { z as z22 } from "zod";
|
|
16048
|
+
|
|
16049
|
+
// src/core/write/corrections.ts
|
|
16050
|
+
function recordCorrection(stateDb2, type, description, source = "user", entity, notePath) {
|
|
16051
|
+
const result = stateDb2.db.prepare(`
|
|
16052
|
+
INSERT INTO corrections (entity, note_path, correction_type, description, source)
|
|
16053
|
+
VALUES (?, ?, ?, ?, ?)
|
|
16054
|
+
`).run(entity ?? null, notePath ?? null, type, description, source);
|
|
16055
|
+
return stateDb2.db.prepare(
|
|
16056
|
+
"SELECT * FROM corrections WHERE id = ?"
|
|
16057
|
+
).get(result.lastInsertRowid);
|
|
16058
|
+
}
|
|
16059
|
+
function listCorrections(stateDb2, status, entity, limit = 50) {
|
|
16060
|
+
const conditions = [];
|
|
16061
|
+
const params = [];
|
|
16062
|
+
if (status) {
|
|
16063
|
+
conditions.push("status = ?");
|
|
16064
|
+
params.push(status);
|
|
16065
|
+
}
|
|
16066
|
+
if (entity) {
|
|
16067
|
+
conditions.push("entity = ? COLLATE NOCASE");
|
|
16068
|
+
params.push(entity);
|
|
16069
|
+
}
|
|
16070
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
16071
|
+
params.push(limit);
|
|
16072
|
+
return stateDb2.db.prepare(
|
|
16073
|
+
`SELECT * FROM corrections ${where} ORDER BY created_at DESC LIMIT ?`
|
|
16074
|
+
).all(...params);
|
|
16075
|
+
}
|
|
16076
|
+
function resolveCorrection(stateDb2, id, newStatus) {
|
|
16077
|
+
const result = stateDb2.db.prepare(`
|
|
16078
|
+
UPDATE corrections
|
|
16079
|
+
SET status = ?, resolved_at = datetime('now')
|
|
16080
|
+
WHERE id = ?
|
|
16081
|
+
`).run(newStatus, id);
|
|
16082
|
+
return result.changes > 0;
|
|
16083
|
+
}
|
|
16084
|
+
|
|
16085
|
+
// src/tools/write/corrections.ts
|
|
16086
|
+
function registerCorrectionTools(server2, getStateDb) {
|
|
16087
|
+
server2.tool(
|
|
16088
|
+
"vault_record_correction",
|
|
16089
|
+
'Record a persistent correction (e.g., "that link is wrong", "undo that"). Survives across sessions.',
|
|
16090
|
+
{
|
|
16091
|
+
correction_type: z22.enum(["wrong_link", "wrong_entity", "wrong_category", "general"]).describe("Type of correction"),
|
|
16092
|
+
description: z22.string().describe("What went wrong and what should be done"),
|
|
16093
|
+
entity: z22.string().optional().describe("Entity name (if correction is about a specific entity)"),
|
|
16094
|
+
note_path: z22.string().optional().describe("Note path (if correction is about a specific note)")
|
|
16095
|
+
},
|
|
16096
|
+
async ({ correction_type, description, entity, note_path }) => {
|
|
16097
|
+
const stateDb2 = getStateDb();
|
|
16098
|
+
if (!stateDb2) {
|
|
16099
|
+
return {
|
|
16100
|
+
content: [{ type: "text", text: JSON.stringify({ error: "StateDb not available" }) }],
|
|
16101
|
+
isError: true
|
|
16102
|
+
};
|
|
16103
|
+
}
|
|
16104
|
+
const correction = recordCorrection(stateDb2, correction_type, description, "user", entity, note_path);
|
|
16105
|
+
return {
|
|
16106
|
+
content: [{
|
|
16107
|
+
type: "text",
|
|
16108
|
+
text: JSON.stringify({
|
|
16109
|
+
recorded: true,
|
|
16110
|
+
correction
|
|
16111
|
+
}, null, 2)
|
|
16112
|
+
}]
|
|
16113
|
+
};
|
|
16114
|
+
}
|
|
16115
|
+
);
|
|
16116
|
+
server2.tool(
|
|
16117
|
+
"vault_list_corrections",
|
|
16118
|
+
"List recorded corrections, optionally filtered by status or entity.",
|
|
16119
|
+
{
|
|
16120
|
+
status: z22.enum(["pending", "applied", "dismissed"]).optional().describe("Filter by status"),
|
|
16121
|
+
entity: z22.string().optional().describe("Filter by entity name"),
|
|
16122
|
+
limit: z22.number().min(1).max(200).default(50).describe("Max entries to return")
|
|
16123
|
+
},
|
|
16124
|
+
async ({ status, entity, limit }) => {
|
|
16125
|
+
const stateDb2 = getStateDb();
|
|
16126
|
+
if (!stateDb2) {
|
|
16127
|
+
return {
|
|
16128
|
+
content: [{ type: "text", text: JSON.stringify({ error: "StateDb not available" }) }],
|
|
16129
|
+
isError: true
|
|
16130
|
+
};
|
|
16131
|
+
}
|
|
16132
|
+
const corrections = listCorrections(stateDb2, status, entity, limit);
|
|
16133
|
+
return {
|
|
16134
|
+
content: [{
|
|
16135
|
+
type: "text",
|
|
16136
|
+
text: JSON.stringify({
|
|
16137
|
+
corrections,
|
|
16138
|
+
count: corrections.length
|
|
16139
|
+
}, null, 2)
|
|
16140
|
+
}]
|
|
16141
|
+
};
|
|
16142
|
+
}
|
|
16143
|
+
);
|
|
16144
|
+
server2.tool(
|
|
16145
|
+
"vault_resolve_correction",
|
|
16146
|
+
"Resolve a correction by marking it as applied or dismissed.",
|
|
16147
|
+
{
|
|
16148
|
+
correction_id: z22.number().describe("ID of the correction to resolve"),
|
|
16149
|
+
status: z22.enum(["applied", "dismissed"]).describe("New status")
|
|
16150
|
+
},
|
|
16151
|
+
async ({ correction_id, status }) => {
|
|
16152
|
+
const stateDb2 = getStateDb();
|
|
16153
|
+
if (!stateDb2) {
|
|
16154
|
+
return {
|
|
16155
|
+
content: [{ type: "text", text: JSON.stringify({ error: "StateDb not available" }) }],
|
|
16156
|
+
isError: true
|
|
16157
|
+
};
|
|
16158
|
+
}
|
|
16159
|
+
const resolved = resolveCorrection(stateDb2, correction_id, status);
|
|
16160
|
+
if (!resolved) {
|
|
16161
|
+
return {
|
|
16162
|
+
content: [{ type: "text", text: JSON.stringify({ error: `Correction ${correction_id} not found` }) }],
|
|
16163
|
+
isError: true
|
|
16164
|
+
};
|
|
16165
|
+
}
|
|
16166
|
+
return {
|
|
16167
|
+
content: [{
|
|
16168
|
+
type: "text",
|
|
16169
|
+
text: JSON.stringify({
|
|
16170
|
+
resolved: true,
|
|
16171
|
+
correction_id,
|
|
16172
|
+
status
|
|
16173
|
+
}, null, 2)
|
|
16174
|
+
}]
|
|
16175
|
+
};
|
|
16176
|
+
}
|
|
16177
|
+
);
|
|
16178
|
+
}
|
|
16179
|
+
|
|
16180
|
+
// src/tools/write/config.ts
|
|
16181
|
+
import { z as z23 } from "zod";
|
|
16000
16182
|
import { saveFlywheelConfigToDb as saveFlywheelConfigToDb2 } from "@velvetmonkey/vault-core";
|
|
16001
16183
|
function registerConfigTools(server2, getConfig, setConfig, getStateDb) {
|
|
16002
16184
|
server2.registerTool(
|
|
@@ -16005,9 +16187,9 @@ function registerConfigTools(server2, getConfig, setConfig, getStateDb) {
|
|
|
16005
16187
|
title: "Flywheel Config",
|
|
16006
16188
|
description: 'Read or update Flywheel configuration.\n- "get": Returns the current FlywheelConfig\n- "set": Updates a single config key and returns the updated config\n\nExample: flywheel_config({ mode: "get" })\nExample: flywheel_config({ mode: "set", key: "exclude_analysis_tags", value: ["habit", "daily"] })',
|
|
16007
16189
|
inputSchema: {
|
|
16008
|
-
mode:
|
|
16009
|
-
key:
|
|
16010
|
-
value:
|
|
16190
|
+
mode: z23.enum(["get", "set"]).describe("Operation mode"),
|
|
16191
|
+
key: z23.string().optional().describe("Config key to update (required for set mode)"),
|
|
16192
|
+
value: z23.unknown().optional().describe("New value for the key (required for set mode)")
|
|
16011
16193
|
}
|
|
16012
16194
|
},
|
|
16013
16195
|
async ({ mode, key, value }) => {
|
|
@@ -16045,7 +16227,7 @@ function registerConfigTools(server2, getConfig, setConfig, getStateDb) {
|
|
|
16045
16227
|
}
|
|
16046
16228
|
|
|
16047
16229
|
// src/tools/write/enrich.ts
|
|
16048
|
-
import { z as
|
|
16230
|
+
import { z as z24 } from "zod";
|
|
16049
16231
|
import * as fs29 from "fs/promises";
|
|
16050
16232
|
import * as path30 from "path";
|
|
16051
16233
|
function hasSkipWikilinks(content) {
|
|
@@ -16100,9 +16282,9 @@ function registerInitTools(server2, vaultPath2, getStateDb) {
|
|
|
16100
16282
|
"vault_init",
|
|
16101
16283
|
"Initialize vault for Flywheel \u2014 scans legacy notes with zero wikilinks and applies entity links. Safe to re-run (idempotent). Use dry_run (default) to preview.",
|
|
16102
16284
|
{
|
|
16103
|
-
dry_run:
|
|
16104
|
-
batch_size:
|
|
16105
|
-
offset:
|
|
16285
|
+
dry_run: z24.boolean().default(true).describe("If true (default), preview what would be linked without modifying files"),
|
|
16286
|
+
batch_size: z24.number().default(50).describe("Maximum notes to process per invocation (default: 50)"),
|
|
16287
|
+
offset: z24.number().default(0).describe("Skip this many eligible notes (for pagination across invocations)")
|
|
16106
16288
|
},
|
|
16107
16289
|
async ({ dry_run, batch_size, offset }) => {
|
|
16108
16290
|
const startTime = Date.now();
|
|
@@ -16197,7 +16379,7 @@ function registerInitTools(server2, vaultPath2, getStateDb) {
|
|
|
16197
16379
|
}
|
|
16198
16380
|
|
|
16199
16381
|
// src/tools/read/metrics.ts
|
|
16200
|
-
import { z as
|
|
16382
|
+
import { z as z25 } from "zod";
|
|
16201
16383
|
|
|
16202
16384
|
// src/core/shared/metrics.ts
|
|
16203
16385
|
var ALL_METRICS = [
|
|
@@ -16363,10 +16545,10 @@ function registerMetricsTools(server2, getIndex, getStateDb) {
|
|
|
16363
16545
|
title: "Vault Growth",
|
|
16364
16546
|
description: 'Track vault growth over time. Modes: "current" (live snapshot), "history" (time series), "trends" (deltas vs N days ago), "index_activity" (rebuild history). Tracks 11 metrics: note_count, link_count, orphan_count, tag_count, entity_count, avg_links_per_note, link_density, connected_ratio, wikilink_accuracy, wikilink_feedback_volume, wikilink_suppressed_count.',
|
|
16365
16547
|
inputSchema: {
|
|
16366
|
-
mode:
|
|
16367
|
-
metric:
|
|
16368
|
-
days_back:
|
|
16369
|
-
limit:
|
|
16548
|
+
mode: z25.enum(["current", "history", "trends", "index_activity"]).describe("Query mode: current snapshot, historical time series, trend analysis, or index rebuild activity"),
|
|
16549
|
+
metric: z25.string().optional().describe('Filter to specific metric (e.g., "note_count"). Omit for all metrics.'),
|
|
16550
|
+
days_back: z25.number().optional().describe("Number of days to look back for history/trends (default: 30)"),
|
|
16551
|
+
limit: z25.number().optional().describe("Number of recent events to return for index_activity mode (default: 20)")
|
|
16370
16552
|
}
|
|
16371
16553
|
},
|
|
16372
16554
|
async ({ mode, metric, days_back, limit: eventLimit }) => {
|
|
@@ -16439,7 +16621,7 @@ function registerMetricsTools(server2, getIndex, getStateDb) {
|
|
|
16439
16621
|
}
|
|
16440
16622
|
|
|
16441
16623
|
// src/tools/read/activity.ts
|
|
16442
|
-
import { z as
|
|
16624
|
+
import { z as z26 } from "zod";
|
|
16443
16625
|
|
|
16444
16626
|
// src/core/shared/toolTracking.ts
|
|
16445
16627
|
function recordToolInvocation(stateDb2, event) {
|
|
@@ -16599,10 +16781,10 @@ function registerActivityTools(server2, getStateDb, getSessionId2) {
|
|
|
16599
16781
|
title: "Vault Activity",
|
|
16600
16782
|
description: 'Track tool usage patterns and session activity. Modes:\n- "session": Current session summary (tools called, notes accessed)\n- "sessions": List of recent sessions\n- "note_access": Notes ranked by query frequency\n- "tool_usage": Tool usage patterns (most-used tools, avg duration)',
|
|
16601
16783
|
inputSchema: {
|
|
16602
|
-
mode:
|
|
16603
|
-
session_id:
|
|
16604
|
-
days_back:
|
|
16605
|
-
limit:
|
|
16784
|
+
mode: z26.enum(["session", "sessions", "note_access", "tool_usage"]).describe("Activity query mode"),
|
|
16785
|
+
session_id: z26.string().optional().describe("Specific session ID (for session mode, defaults to current)"),
|
|
16786
|
+
days_back: z26.number().optional().describe("Number of days to look back (default: 30)"),
|
|
16787
|
+
limit: z26.number().optional().describe("Maximum results to return (default: 20)")
|
|
16606
16788
|
}
|
|
16607
16789
|
},
|
|
16608
16790
|
async ({ mode, session_id, days_back, limit: resultLimit }) => {
|
|
@@ -16669,7 +16851,7 @@ function registerActivityTools(server2, getStateDb, getSessionId2) {
|
|
|
16669
16851
|
}
|
|
16670
16852
|
|
|
16671
16853
|
// src/tools/read/similarity.ts
|
|
16672
|
-
import { z as
|
|
16854
|
+
import { z as z27 } from "zod";
|
|
16673
16855
|
|
|
16674
16856
|
// src/core/read/similarity.ts
|
|
16675
16857
|
import * as fs30 from "fs";
|
|
@@ -16933,9 +17115,9 @@ function registerSimilarityTools(server2, getIndex, getVaultPath, getStateDb) {
|
|
|
16933
17115
|
title: "Find Similar Notes",
|
|
16934
17116
|
description: "Find notes similar to a given note using FTS5 keyword matching. When embeddings have been built (via init_semantic), automatically uses hybrid ranking (BM25 + embedding similarity via Reciprocal Rank Fusion). Use exclude_linked to filter out notes already connected via wikilinks.",
|
|
16935
17117
|
inputSchema: {
|
|
16936
|
-
path:
|
|
16937
|
-
limit:
|
|
16938
|
-
exclude_linked:
|
|
17118
|
+
path: z27.string().describe('Path to the source note (relative to vault root, e.g. "projects/alpha.md")'),
|
|
17119
|
+
limit: z27.number().optional().describe("Maximum number of similar notes to return (default: 10)"),
|
|
17120
|
+
exclude_linked: z27.boolean().optional().describe("Exclude notes already linked to/from the source note (default: true)")
|
|
16939
17121
|
}
|
|
16940
17122
|
},
|
|
16941
17123
|
async ({ path: path33, limit, exclude_linked }) => {
|
|
@@ -16979,7 +17161,7 @@ function registerSimilarityTools(server2, getIndex, getVaultPath, getStateDb) {
|
|
|
16979
17161
|
}
|
|
16980
17162
|
|
|
16981
17163
|
// src/tools/read/semantic.ts
|
|
16982
|
-
import { z as
|
|
17164
|
+
import { z as z28 } from "zod";
|
|
16983
17165
|
import { getAllEntitiesFromDb } from "@velvetmonkey/vault-core";
|
|
16984
17166
|
function registerSemanticTools(server2, getVaultPath, getStateDb) {
|
|
16985
17167
|
server2.registerTool(
|
|
@@ -16988,7 +17170,7 @@ function registerSemanticTools(server2, getVaultPath, getStateDb) {
|
|
|
16988
17170
|
title: "Initialize Semantic Search",
|
|
16989
17171
|
description: "Download the embedding model and build semantic search index for this vault. After running, search and find_similar automatically use hybrid ranking (BM25 + semantic). Run once per vault \u2014 subsequent calls skip already-embedded notes unless force=true.",
|
|
16990
17172
|
inputSchema: {
|
|
16991
|
-
force:
|
|
17173
|
+
force: z28.boolean().optional().describe(
|
|
16992
17174
|
"Rebuild all embeddings even if they already exist (default: false)"
|
|
16993
17175
|
)
|
|
16994
17176
|
}
|
|
@@ -17068,7 +17250,7 @@ function registerSemanticTools(server2, getVaultPath, getStateDb) {
|
|
|
17068
17250
|
|
|
17069
17251
|
// src/tools/read/merges.ts
|
|
17070
17252
|
init_levenshtein();
|
|
17071
|
-
import { z as
|
|
17253
|
+
import { z as z29 } from "zod";
|
|
17072
17254
|
import { getAllEntitiesFromDb as getAllEntitiesFromDb2, getDismissedMergePairs, recordMergeDismissal } from "@velvetmonkey/vault-core";
|
|
17073
17255
|
function normalizeName(name) {
|
|
17074
17256
|
return name.toLowerCase().replace(/[.\-_]/g, "").replace(/js$/, "").replace(/ts$/, "");
|
|
@@ -17078,7 +17260,7 @@ function registerMergeTools2(server2, getStateDb) {
|
|
|
17078
17260
|
"suggest_entity_merges",
|
|
17079
17261
|
"Find potential duplicate entities that could be merged based on name similarity",
|
|
17080
17262
|
{
|
|
17081
|
-
limit:
|
|
17263
|
+
limit: z29.number().optional().default(50).describe("Maximum number of suggestions to return")
|
|
17082
17264
|
},
|
|
17083
17265
|
async ({ limit }) => {
|
|
17084
17266
|
const stateDb2 = getStateDb();
|
|
@@ -17180,11 +17362,11 @@ function registerMergeTools2(server2, getStateDb) {
|
|
|
17180
17362
|
"dismiss_merge_suggestion",
|
|
17181
17363
|
"Permanently dismiss a merge suggestion so it never reappears",
|
|
17182
17364
|
{
|
|
17183
|
-
source_path:
|
|
17184
|
-
target_path:
|
|
17185
|
-
source_name:
|
|
17186
|
-
target_name:
|
|
17187
|
-
reason:
|
|
17365
|
+
source_path: z29.string().describe("Path of the source entity"),
|
|
17366
|
+
target_path: z29.string().describe("Path of the target entity"),
|
|
17367
|
+
source_name: z29.string().describe("Name of the source entity"),
|
|
17368
|
+
target_name: z29.string().describe("Name of the target entity"),
|
|
17369
|
+
reason: z29.string().describe("Original suggestion reason")
|
|
17188
17370
|
},
|
|
17189
17371
|
async ({ source_path, target_path, source_name, target_name, reason }) => {
|
|
17190
17372
|
const stateDb2 = getStateDb();
|
|
@@ -17583,6 +17765,7 @@ registerSystemTools2(server, vaultPath);
|
|
|
17583
17765
|
registerPolicyTools(server, vaultPath);
|
|
17584
17766
|
registerTagTools(server, () => vaultIndex, () => vaultPath);
|
|
17585
17767
|
registerWikilinkFeedbackTools(server, () => stateDb);
|
|
17768
|
+
registerCorrectionTools(server, () => stateDb);
|
|
17586
17769
|
registerInitTools(server, vaultPath, () => stateDb);
|
|
17587
17770
|
registerConfigTools(
|
|
17588
17771
|
server,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velvetmonkey/flywheel-memory",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.48",
|
|
4
4
|
"description": "MCP server that gives Claude full read/write access to your Obsidian vault. Select from 42 tools for search, backlinks, graph queries, mutations, 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.48",
|
|
56
56
|
"better-sqlite3": "^11.0.0",
|
|
57
57
|
"chokidar": "^4.0.0",
|
|
58
58
|
"gray-matter": "^4.0.3",
|