@velvetmonkey/flywheel-memory 2.9.1 → 2.11.0
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 +1066 -564
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -273,12 +273,158 @@ var init_vault_scope = __esm({
|
|
|
273
273
|
}
|
|
274
274
|
});
|
|
275
275
|
|
|
276
|
-
// src/core/read/
|
|
277
|
-
import * as crypto from "crypto";
|
|
276
|
+
// src/core/read/embeddingProvider.ts
|
|
278
277
|
import * as fs4 from "fs";
|
|
279
278
|
import * as path3 from "path";
|
|
280
279
|
import { Worker } from "node:worker_threads";
|
|
281
280
|
import { fileURLToPath } from "node:url";
|
|
281
|
+
function resolveWorkerPath() {
|
|
282
|
+
const thisFile = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
|
|
283
|
+
const thisDir = path3.dirname(thisFile);
|
|
284
|
+
const workerPath = path3.join(thisDir, "embedding-worker.js");
|
|
285
|
+
if (fs4.existsSync(workerPath)) return workerPath;
|
|
286
|
+
const devPath = path3.resolve(thisDir, "..", "..", "..", "dist", "embedding-worker.js");
|
|
287
|
+
if (fs4.existsSync(devPath)) return devPath;
|
|
288
|
+
throw new Error(
|
|
289
|
+
`Embedding worker not found at ${workerPath}. Run 'npm run build' to generate it.`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
function getEmbeddingProvider(modelId) {
|
|
293
|
+
if (provider && providerModelId !== modelId) {
|
|
294
|
+
provider.shutdown();
|
|
295
|
+
provider = null;
|
|
296
|
+
providerModelId = null;
|
|
297
|
+
}
|
|
298
|
+
if (!provider) {
|
|
299
|
+
provider = new WorkerEmbeddingProvider(modelId);
|
|
300
|
+
providerModelId = modelId;
|
|
301
|
+
}
|
|
302
|
+
return provider;
|
|
303
|
+
}
|
|
304
|
+
var WorkerEmbeddingProvider, provider, providerModelId;
|
|
305
|
+
var init_embeddingProvider = __esm({
|
|
306
|
+
"src/core/read/embeddingProvider.ts"() {
|
|
307
|
+
"use strict";
|
|
308
|
+
WorkerEmbeddingProvider = class {
|
|
309
|
+
constructor(modelId) {
|
|
310
|
+
this.modelId = modelId;
|
|
311
|
+
}
|
|
312
|
+
initPromise = null;
|
|
313
|
+
dims = 0;
|
|
314
|
+
nextRequestId = 0;
|
|
315
|
+
pending = /* @__PURE__ */ new Map();
|
|
316
|
+
ready = false;
|
|
317
|
+
worker = null;
|
|
318
|
+
async init() {
|
|
319
|
+
if (this.ready && this.worker) {
|
|
320
|
+
return { dims: this.dims };
|
|
321
|
+
}
|
|
322
|
+
if (this.initPromise) {
|
|
323
|
+
return this.initPromise;
|
|
324
|
+
}
|
|
325
|
+
this.initPromise = new Promise((resolve4, reject) => {
|
|
326
|
+
try {
|
|
327
|
+
const workerPath = resolveWorkerPath();
|
|
328
|
+
console.error(`[Semantic] Spawning embedding worker: ${workerPath}`);
|
|
329
|
+
this.worker = new Worker(workerPath);
|
|
330
|
+
this.worker.on("message", (msg) => {
|
|
331
|
+
switch (msg.type) {
|
|
332
|
+
case "ready":
|
|
333
|
+
this.ready = true;
|
|
334
|
+
this.dims = msg.dims;
|
|
335
|
+
console.error(`[Semantic] Worker ready (model: ${this.modelId}, dims: ${msg.dims})`);
|
|
336
|
+
resolve4({ dims: msg.dims });
|
|
337
|
+
break;
|
|
338
|
+
case "result": {
|
|
339
|
+
const pending = this.pending.get(msg.id);
|
|
340
|
+
if (pending) {
|
|
341
|
+
this.pending.delete(msg.id);
|
|
342
|
+
pending.resolve(new Float32Array(msg.embedding));
|
|
343
|
+
}
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
case "error": {
|
|
347
|
+
if (msg.fatal) {
|
|
348
|
+
console.error(`[Semantic] Worker fatal error: ${msg.message}`);
|
|
349
|
+
console.error("[Semantic] Semantic search disabled. Keyword search (BM25) remains available.");
|
|
350
|
+
this.shutdown();
|
|
351
|
+
this.initPromise = null;
|
|
352
|
+
reject(new Error(msg.message));
|
|
353
|
+
} else if (msg.id != null) {
|
|
354
|
+
const pending = this.pending.get(msg.id);
|
|
355
|
+
if (pending) {
|
|
356
|
+
this.pending.delete(msg.id);
|
|
357
|
+
pending.reject(new Error(msg.message));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
this.worker.on("error", (err) => {
|
|
365
|
+
console.error(`[Semantic] Worker error: ${err.message}`);
|
|
366
|
+
this.handleCrash(new Error(`Embedding worker error: ${err.message}`));
|
|
367
|
+
if (!this.ready) {
|
|
368
|
+
this.initPromise = null;
|
|
369
|
+
reject(err);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
this.worker.on("exit", (code) => {
|
|
373
|
+
if (code !== 0 && this.ready) {
|
|
374
|
+
console.error(`[Semantic] Worker exited with code ${code}`);
|
|
375
|
+
this.handleCrash(new Error(`Embedding worker exited with code ${code}`));
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
this.worker.postMessage({ type: "init", modelId: this.modelId });
|
|
379
|
+
} catch (err) {
|
|
380
|
+
this.initPromise = null;
|
|
381
|
+
reject(err);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
return this.initPromise;
|
|
385
|
+
}
|
|
386
|
+
async embed(text) {
|
|
387
|
+
await this.init();
|
|
388
|
+
if (!this.worker) {
|
|
389
|
+
throw new Error("Embedding worker not available");
|
|
390
|
+
}
|
|
391
|
+
const id = ++this.nextRequestId;
|
|
392
|
+
return new Promise((resolve4, reject) => {
|
|
393
|
+
this.pending.set(id, { resolve: resolve4, reject });
|
|
394
|
+
this.worker.postMessage({ type: "embed", id, text });
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
shutdown() {
|
|
398
|
+
if (this.worker) {
|
|
399
|
+
try {
|
|
400
|
+
this.worker.postMessage({ type: "shutdown" });
|
|
401
|
+
} catch {
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
this.worker = null;
|
|
405
|
+
this.ready = false;
|
|
406
|
+
this.initPromise = null;
|
|
407
|
+
this.dims = 0;
|
|
408
|
+
}
|
|
409
|
+
handleCrash(error) {
|
|
410
|
+
for (const [id, pending] of this.pending) {
|
|
411
|
+
pending.reject(error);
|
|
412
|
+
this.pending.delete(id);
|
|
413
|
+
}
|
|
414
|
+
this.worker = null;
|
|
415
|
+
this.ready = false;
|
|
416
|
+
this.initPromise = null;
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
provider = null;
|
|
420
|
+
providerModelId = null;
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// src/core/read/embeddings.ts
|
|
425
|
+
import * as crypto from "crypto";
|
|
426
|
+
import * as fs5 from "fs";
|
|
427
|
+
import * as path4 from "path";
|
|
282
428
|
function getModelConfig() {
|
|
283
429
|
const envModel = process.env.EMBEDDING_MODEL?.trim();
|
|
284
430
|
if (!envModel) return MODEL_REGISTRY[DEFAULT_MODEL];
|
|
@@ -330,115 +476,16 @@ function clearEmbeddingsForRebuild() {
|
|
|
330
476
|
function setEmbeddingsDatabase(database) {
|
|
331
477
|
db = database;
|
|
332
478
|
}
|
|
333
|
-
function resolveWorkerPath() {
|
|
334
|
-
const thisFile = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
|
|
335
|
-
const thisDir = path3.dirname(thisFile);
|
|
336
|
-
const workerPath = path3.join(thisDir, "embedding-worker.js");
|
|
337
|
-
if (fs4.existsSync(workerPath)) return workerPath;
|
|
338
|
-
const devPath = path3.resolve(thisDir, "..", "..", "..", "dist", "embedding-worker.js");
|
|
339
|
-
if (fs4.existsSync(devPath)) return devPath;
|
|
340
|
-
throw new Error(
|
|
341
|
-
`Embedding worker not found at ${workerPath}. Run 'npm run build' to generate it.`
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
479
|
async function initEmbeddings() {
|
|
345
|
-
|
|
346
|
-
if (
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const workerPath = resolveWorkerPath();
|
|
350
|
-
console.error(`[Semantic] Spawning embedding worker: ${workerPath}`);
|
|
351
|
-
worker = new Worker(workerPath);
|
|
352
|
-
worker.on("message", (msg) => {
|
|
353
|
-
switch (msg.type) {
|
|
354
|
-
case "ready":
|
|
355
|
-
workerReady = true;
|
|
356
|
-
workerDims = msg.dims;
|
|
357
|
-
if (activeModelConfig.dims === 0) {
|
|
358
|
-
activeModelConfig.dims = msg.dims;
|
|
359
|
-
console.error(`[Semantic] Probed model ${activeModelConfig.id}: ${msg.dims} dims`);
|
|
360
|
-
}
|
|
361
|
-
console.error(`[Semantic] Worker ready (model: ${activeModelConfig.id}, dims: ${msg.dims})`);
|
|
362
|
-
resolve4();
|
|
363
|
-
break;
|
|
364
|
-
case "result": {
|
|
365
|
-
const pending = pendingEmbeds.get(msg.id);
|
|
366
|
-
if (pending) {
|
|
367
|
-
pendingEmbeds.delete(msg.id);
|
|
368
|
-
pending.resolve(new Float32Array(msg.embedding));
|
|
369
|
-
}
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
case "error": {
|
|
373
|
-
if (msg.fatal) {
|
|
374
|
-
console.error(`[Semantic] Worker fatal error: ${msg.message}`);
|
|
375
|
-
console.error(`[Semantic] Semantic search disabled. Keyword search (BM25) remains available.`);
|
|
376
|
-
terminateWorker();
|
|
377
|
-
workerInitPromise = null;
|
|
378
|
-
reject(new Error(msg.message));
|
|
379
|
-
} else if (msg.id != null) {
|
|
380
|
-
const pending = pendingEmbeds.get(msg.id);
|
|
381
|
-
if (pending) {
|
|
382
|
-
pendingEmbeds.delete(msg.id);
|
|
383
|
-
pending.reject(new Error(msg.message));
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
break;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
worker.on("error", (err) => {
|
|
391
|
-
console.error(`[Semantic] Worker error: ${err.message}`);
|
|
392
|
-
handleWorkerCrash();
|
|
393
|
-
if (!workerReady) {
|
|
394
|
-
workerInitPromise = null;
|
|
395
|
-
reject(err);
|
|
396
|
-
}
|
|
397
|
-
});
|
|
398
|
-
worker.on("exit", (code) => {
|
|
399
|
-
if (code !== 0 && workerReady) {
|
|
400
|
-
console.error(`[Semantic] Worker exited with code ${code}`);
|
|
401
|
-
handleWorkerCrash();
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
worker.postMessage({ type: "init", modelId: activeModelConfig.id });
|
|
405
|
-
} catch (err) {
|
|
406
|
-
workerInitPromise = null;
|
|
407
|
-
reject(err);
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
return workerInitPromise;
|
|
411
|
-
}
|
|
412
|
-
function handleWorkerCrash() {
|
|
413
|
-
for (const [id, pending] of pendingEmbeds) {
|
|
414
|
-
pending.reject(new Error("Embedding worker crashed"));
|
|
415
|
-
pendingEmbeds.delete(id);
|
|
416
|
-
}
|
|
417
|
-
worker = null;
|
|
418
|
-
workerReady = false;
|
|
419
|
-
workerInitPromise = null;
|
|
420
|
-
}
|
|
421
|
-
function terminateWorker() {
|
|
422
|
-
if (worker) {
|
|
423
|
-
try {
|
|
424
|
-
worker.postMessage({ type: "shutdown" });
|
|
425
|
-
} catch {
|
|
426
|
-
}
|
|
427
|
-
worker = null;
|
|
480
|
+
const { dims } = await getEmbeddingProvider(activeModelConfig.id).init();
|
|
481
|
+
if (activeModelConfig.dims === 0) {
|
|
482
|
+
activeModelConfig.dims = dims;
|
|
483
|
+
console.error(`[Semantic] Probed model ${activeModelConfig.id}: ${dims} dims`);
|
|
428
484
|
}
|
|
429
|
-
workerReady = false;
|
|
430
|
-
workerInitPromise = null;
|
|
431
485
|
}
|
|
432
486
|
async function embedText(text) {
|
|
433
487
|
await initEmbeddings();
|
|
434
|
-
|
|
435
|
-
throw new Error("Embedding worker not available");
|
|
436
|
-
}
|
|
437
|
-
const id = ++embedRequestId;
|
|
438
|
-
return new Promise((resolve4, reject) => {
|
|
439
|
-
pendingEmbeds.set(id, { resolve: resolve4, reject });
|
|
440
|
-
worker.postMessage({ type: "embed", id, text });
|
|
441
|
-
});
|
|
488
|
+
return getEmbeddingProvider(activeModelConfig.id).embed(text);
|
|
442
489
|
}
|
|
443
490
|
async function embedTextCached(text) {
|
|
444
491
|
const existing = embeddingCache.get(text);
|
|
@@ -501,12 +548,12 @@ async function buildEmbeddingsIndex(vaultPath2, onProgress) {
|
|
|
501
548
|
for (const file of indexable) {
|
|
502
549
|
progress.current++;
|
|
503
550
|
try {
|
|
504
|
-
const stats =
|
|
551
|
+
const stats = fs5.statSync(file.absolutePath);
|
|
505
552
|
if (stats.size > MAX_FILE_SIZE2) {
|
|
506
553
|
progress.skipped++;
|
|
507
554
|
continue;
|
|
508
555
|
}
|
|
509
|
-
const content =
|
|
556
|
+
const content = fs5.readFileSync(file.absolutePath, "utf-8");
|
|
510
557
|
const hash = contentHash(content);
|
|
511
558
|
if (existingHashes.get(file.path) === hash) {
|
|
512
559
|
progress.skipped++;
|
|
@@ -540,7 +587,7 @@ async function updateEmbedding(notePath, absolutePath) {
|
|
|
540
587
|
const db4 = getDb();
|
|
541
588
|
if (!db4) return;
|
|
542
589
|
try {
|
|
543
|
-
const content =
|
|
590
|
+
const content = fs5.readFileSync(absolutePath, "utf-8");
|
|
544
591
|
const hash = contentHash(content);
|
|
545
592
|
const existing = db4.prepare("SELECT content_hash FROM note_embeddings WHERE path = ?").get(notePath);
|
|
546
593
|
if (existing?.content_hash === hash) return;
|
|
@@ -817,8 +864,8 @@ function buildEntityEmbeddingText(entity, vaultPath2) {
|
|
|
817
864
|
parts.push(entity.category);
|
|
818
865
|
if (entity.path) {
|
|
819
866
|
try {
|
|
820
|
-
const absPath =
|
|
821
|
-
const content =
|
|
867
|
+
const absPath = path4.join(vaultPath2, entity.path);
|
|
868
|
+
const content = fs5.readFileSync(absPath, "utf-8");
|
|
822
869
|
parts.push(content.slice(0, 500));
|
|
823
870
|
} catch {
|
|
824
871
|
}
|
|
@@ -1117,13 +1164,14 @@ function getEntityEmbeddingsCount() {
|
|
|
1117
1164
|
return 0;
|
|
1118
1165
|
}
|
|
1119
1166
|
}
|
|
1120
|
-
var MODEL_REGISTRY, DEFAULT_MODEL, activeModelConfig, MAX_FILE_SIZE2, db, embeddingsBuilding,
|
|
1167
|
+
var MODEL_REGISTRY, DEFAULT_MODEL, activeModelConfig, MAX_FILE_SIZE2, db, embeddingsBuilding, embeddingCache, EMBEDDING_CACHE_MAX, entityEmbeddingsMap, inferredCategoriesMap, EMBEDDING_TEXT_VERSION;
|
|
1121
1168
|
var init_embeddings = __esm({
|
|
1122
1169
|
"src/core/read/embeddings.ts"() {
|
|
1123
1170
|
"use strict";
|
|
1124
1171
|
init_vault_scope();
|
|
1125
1172
|
init_vault();
|
|
1126
1173
|
init_constants();
|
|
1174
|
+
init_embeddingProvider();
|
|
1127
1175
|
MODEL_REGISTRY = {
|
|
1128
1176
|
"Xenova/all-MiniLM-L6-v2": { id: "Xenova/all-MiniLM-L6-v2", dims: 384 },
|
|
1129
1177
|
"Xenova/bge-small-en-v1.5": { id: "Xenova/bge-small-en-v1.5", dims: 384 },
|
|
@@ -1135,12 +1183,6 @@ var init_embeddings = __esm({
|
|
|
1135
1183
|
MAX_FILE_SIZE2 = 5 * 1024 * 1024;
|
|
1136
1184
|
db = null;
|
|
1137
1185
|
embeddingsBuilding = false;
|
|
1138
|
-
worker = null;
|
|
1139
|
-
workerReady = false;
|
|
1140
|
-
workerDims = 0;
|
|
1141
|
-
workerInitPromise = null;
|
|
1142
|
-
embedRequestId = 0;
|
|
1143
|
-
pendingEmbeds = /* @__PURE__ */ new Map();
|
|
1144
1186
|
embeddingCache = /* @__PURE__ */ new Map();
|
|
1145
1187
|
EMBEDDING_CACHE_MAX = 500;
|
|
1146
1188
|
entityEmbeddingsMap = /* @__PURE__ */ new Map();
|
|
@@ -1151,7 +1193,7 @@ var init_embeddings = __esm({
|
|
|
1151
1193
|
|
|
1152
1194
|
// src/core/shared/recency.ts
|
|
1153
1195
|
import { readdir, readFile, stat } from "fs/promises";
|
|
1154
|
-
import
|
|
1196
|
+
import path10 from "path";
|
|
1155
1197
|
import {
|
|
1156
1198
|
getEntityName,
|
|
1157
1199
|
recordEntityMention,
|
|
@@ -1167,9 +1209,9 @@ async function* walkMarkdownFiles(dir, baseDir) {
|
|
|
1167
1209
|
try {
|
|
1168
1210
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
1169
1211
|
for (const entry of entries) {
|
|
1170
|
-
const fullPath =
|
|
1171
|
-
const relativePath =
|
|
1172
|
-
const topFolder = relativePath.split(
|
|
1212
|
+
const fullPath = path10.join(dir, entry.name);
|
|
1213
|
+
const relativePath = path10.relative(baseDir, fullPath);
|
|
1214
|
+
const topFolder = relativePath.split(path10.sep)[0];
|
|
1173
1215
|
if (SYSTEM_EXCLUDED_DIRS.has(topFolder)) {
|
|
1174
1216
|
continue;
|
|
1175
1217
|
}
|
|
@@ -1546,7 +1588,7 @@ var init_stemmer = __esm({
|
|
|
1546
1588
|
|
|
1547
1589
|
// src/core/shared/cooccurrence.ts
|
|
1548
1590
|
import { readdir as readdir2, readFile as readFile2 } from "fs/promises";
|
|
1549
|
-
import
|
|
1591
|
+
import path11 from "path";
|
|
1550
1592
|
function noteContainsEntity(content, entityName, contentTokens) {
|
|
1551
1593
|
const entityTokens = tokenize(entityName);
|
|
1552
1594
|
if (entityTokens.length === 0) return false;
|
|
@@ -1576,9 +1618,9 @@ async function* walkMarkdownFiles2(dir, baseDir) {
|
|
|
1576
1618
|
try {
|
|
1577
1619
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
1578
1620
|
for (const entry of entries) {
|
|
1579
|
-
const fullPath =
|
|
1580
|
-
const relativePath =
|
|
1581
|
-
const topFolder = relativePath.split(
|
|
1621
|
+
const fullPath = path11.join(dir, entry.name);
|
|
1622
|
+
const relativePath = path11.relative(baseDir, fullPath);
|
|
1623
|
+
const topFolder = relativePath.split(path11.sep)[0];
|
|
1582
1624
|
if (SYSTEM_EXCLUDED_DIRS.has(topFolder)) {
|
|
1583
1625
|
continue;
|
|
1584
1626
|
}
|
|
@@ -2019,11 +2061,11 @@ function getAllFeedbackBoosts(stateDb2, folder, now) {
|
|
|
2019
2061
|
if (folder !== void 0) {
|
|
2020
2062
|
folderStatsMap = /* @__PURE__ */ new Map();
|
|
2021
2063
|
for (const gs of globalStats) {
|
|
2022
|
-
const
|
|
2023
|
-
if (
|
|
2064
|
+
const fs35 = getWeightedFolderStats(stateDb2, gs.entity, folder, now);
|
|
2065
|
+
if (fs35.rawTotal >= FEEDBACK_BOOST_MIN_SAMPLES) {
|
|
2024
2066
|
folderStatsMap.set(gs.entity, {
|
|
2025
|
-
weightedAccuracy:
|
|
2026
|
-
rawCount:
|
|
2067
|
+
weightedAccuracy: fs35.weightedAccuracy,
|
|
2068
|
+
rawCount: fs35.rawTotal
|
|
2027
2069
|
});
|
|
2028
2070
|
}
|
|
2029
2071
|
}
|
|
@@ -2033,10 +2075,10 @@ function getAllFeedbackBoosts(stateDb2, folder, now) {
|
|
|
2033
2075
|
if (stat4.rawTotal < FEEDBACK_BOOST_MIN_SAMPLES) continue;
|
|
2034
2076
|
let accuracy;
|
|
2035
2077
|
let sampleCount;
|
|
2036
|
-
const
|
|
2037
|
-
if (
|
|
2038
|
-
accuracy =
|
|
2039
|
-
sampleCount =
|
|
2078
|
+
const fs35 = folderStatsMap?.get(stat4.entity);
|
|
2079
|
+
if (fs35 && fs35.rawCount >= FEEDBACK_BOOST_MIN_SAMPLES) {
|
|
2080
|
+
accuracy = fs35.weightedAccuracy;
|
|
2081
|
+
sampleCount = fs35.rawCount;
|
|
2040
2082
|
} else {
|
|
2041
2083
|
accuracy = stat4.weightedAccuracy;
|
|
2042
2084
|
sampleCount = stat4.rawTotal;
|
|
@@ -2586,8 +2628,8 @@ var init_corrections = __esm({
|
|
|
2586
2628
|
|
|
2587
2629
|
// src/core/write/git.ts
|
|
2588
2630
|
import { simpleGit, CheckRepoActions } from "simple-git";
|
|
2589
|
-
import
|
|
2590
|
-
import
|
|
2631
|
+
import path12 from "path";
|
|
2632
|
+
import fs8 from "fs/promises";
|
|
2591
2633
|
import {
|
|
2592
2634
|
setWriteState,
|
|
2593
2635
|
getWriteState,
|
|
@@ -2638,9 +2680,9 @@ function clearLastMutationCommit() {
|
|
|
2638
2680
|
}
|
|
2639
2681
|
}
|
|
2640
2682
|
async function checkGitLock(vaultPath2) {
|
|
2641
|
-
const lockPath =
|
|
2683
|
+
const lockPath = path12.join(vaultPath2, ".git/index.lock");
|
|
2642
2684
|
try {
|
|
2643
|
-
const stat4 = await
|
|
2685
|
+
const stat4 = await fs8.stat(lockPath);
|
|
2644
2686
|
const ageMs = Date.now() - stat4.mtimeMs;
|
|
2645
2687
|
return {
|
|
2646
2688
|
locked: true,
|
|
@@ -2661,9 +2703,9 @@ async function isGitRepo(vaultPath2) {
|
|
|
2661
2703
|
}
|
|
2662
2704
|
}
|
|
2663
2705
|
async function checkLockFile(vaultPath2) {
|
|
2664
|
-
const lockPath =
|
|
2706
|
+
const lockPath = path12.join(vaultPath2, ".git/index.lock");
|
|
2665
2707
|
try {
|
|
2666
|
-
const stat4 = await
|
|
2708
|
+
const stat4 = await fs8.stat(lockPath);
|
|
2667
2709
|
const ageMs = Date.now() - stat4.mtimeMs;
|
|
2668
2710
|
return { stale: ageMs > STALE_LOCK_THRESHOLD_MS, ageMs };
|
|
2669
2711
|
} catch {
|
|
@@ -2711,7 +2753,7 @@ async function commitChange(vaultPath2, filePath, messagePrefix, retryConfig = D
|
|
|
2711
2753
|
}
|
|
2712
2754
|
}
|
|
2713
2755
|
await git.add(filePath);
|
|
2714
|
-
const fileName =
|
|
2756
|
+
const fileName = path12.basename(filePath);
|
|
2715
2757
|
const commitMessage = `${messagePrefix} Update ${fileName}`;
|
|
2716
2758
|
const result = await git.commit(commitMessage);
|
|
2717
2759
|
if (result.commit) {
|
|
@@ -2739,9 +2781,9 @@ async function commitChange(vaultPath2, filePath, messagePrefix, retryConfig = D
|
|
|
2739
2781
|
lockAgeMs = lockInfo.ageMs;
|
|
2740
2782
|
if (lockInfo.stale) {
|
|
2741
2783
|
staleLockDetected = true;
|
|
2742
|
-
const lockPath =
|
|
2784
|
+
const lockPath = path12.join(vaultPath2, ".git/index.lock");
|
|
2743
2785
|
try {
|
|
2744
|
-
await
|
|
2786
|
+
await fs8.unlink(lockPath);
|
|
2745
2787
|
serverLog("git", `Removed stale git lock (age: ${lockInfo.ageMs}ms)`, "warn");
|
|
2746
2788
|
} catch {
|
|
2747
2789
|
}
|
|
@@ -2881,9 +2923,9 @@ ${files.map((f) => `- ${f}`).join("\n")}`;
|
|
|
2881
2923
|
lockAgeMs = lockInfo.ageMs;
|
|
2882
2924
|
if (lockInfo.stale) {
|
|
2883
2925
|
staleLockDetected = true;
|
|
2884
|
-
const lockPath =
|
|
2926
|
+
const lockPath = path12.join(vaultPath2, ".git/index.lock");
|
|
2885
2927
|
try {
|
|
2886
|
-
await
|
|
2928
|
+
await fs8.unlink(lockPath);
|
|
2887
2929
|
serverLog("git", `Removed stale git lock (age: ${lockInfo.ageMs}ms)`, "warn");
|
|
2888
2930
|
} catch {
|
|
2889
2931
|
}
|
|
@@ -2955,6 +2997,9 @@ function computeProspectDecay(lastSeenAt, now) {
|
|
|
2955
2997
|
function todayISO() {
|
|
2956
2998
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2957
2999
|
}
|
|
3000
|
+
function normalizeProspectKey(term) {
|
|
3001
|
+
return normalizeFuzzyTerm(term).toLowerCase();
|
|
3002
|
+
}
|
|
2958
3003
|
function recordProspectSightings(sightings) {
|
|
2959
3004
|
const stateDb2 = getStateDb3();
|
|
2960
3005
|
if (!stateDb2 || sightings.length === 0) return;
|
|
@@ -3000,6 +3045,88 @@ function recordProspectSightings(sightings) {
|
|
|
3000
3045
|
});
|
|
3001
3046
|
runBatch();
|
|
3002
3047
|
}
|
|
3048
|
+
function recordProspectFeedback(events) {
|
|
3049
|
+
const stateDb2 = getStateDb3();
|
|
3050
|
+
if (!stateDb2 || events.length === 0) return;
|
|
3051
|
+
const insert = stateDb2.db.prepare(`
|
|
3052
|
+
INSERT INTO prospect_feedback (term, action, entity_path, note_path, reason, created_at)
|
|
3053
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
3054
|
+
`);
|
|
3055
|
+
const runBatch = stateDb2.db.transaction(() => {
|
|
3056
|
+
for (const event of events) {
|
|
3057
|
+
insert.run(
|
|
3058
|
+
event.term.toLowerCase(),
|
|
3059
|
+
event.action,
|
|
3060
|
+
event.entityPath ?? null,
|
|
3061
|
+
event.notePath ?? null,
|
|
3062
|
+
event.reason ?? null,
|
|
3063
|
+
event.createdAt ?? Date.now()
|
|
3064
|
+
);
|
|
3065
|
+
}
|
|
3066
|
+
});
|
|
3067
|
+
runBatch();
|
|
3068
|
+
}
|
|
3069
|
+
function getMatchingProspectTerms(candidates) {
|
|
3070
|
+
const stateDb2 = getStateDb3();
|
|
3071
|
+
if (!stateDb2 || candidates.length === 0) return [];
|
|
3072
|
+
const wanted = new Set(
|
|
3073
|
+
candidates.map((value) => value.trim()).filter(Boolean).map((value) => normalizeProspectKey(value))
|
|
3074
|
+
);
|
|
3075
|
+
if (wanted.size === 0) return [];
|
|
3076
|
+
const rows = stateDb2.db.prepare(`
|
|
3077
|
+
SELECT term, display_name
|
|
3078
|
+
FROM prospect_summary
|
|
3079
|
+
WHERE status = 'prospect'
|
|
3080
|
+
`).all();
|
|
3081
|
+
const matched = /* @__PURE__ */ new Set();
|
|
3082
|
+
for (const row of rows) {
|
|
3083
|
+
const rowKey = normalizeProspectKey(row.display_name || row.term);
|
|
3084
|
+
if (wanted.has(rowKey)) matched.add(row.term);
|
|
3085
|
+
}
|
|
3086
|
+
return Array.from(matched);
|
|
3087
|
+
}
|
|
3088
|
+
function resolveProspectsForCreatedEntity(entityPath, title, aliases = []) {
|
|
3089
|
+
const terms = getMatchingProspectTerms([title, ...aliases]);
|
|
3090
|
+
if (terms.length === 0) return [];
|
|
3091
|
+
recordProspectFeedback(
|
|
3092
|
+
terms.map((term) => ({
|
|
3093
|
+
term,
|
|
3094
|
+
action: "create_entity",
|
|
3095
|
+
entityPath,
|
|
3096
|
+
notePath: entityPath
|
|
3097
|
+
}))
|
|
3098
|
+
);
|
|
3099
|
+
refreshProspectSummaries(terms);
|
|
3100
|
+
return terms;
|
|
3101
|
+
}
|
|
3102
|
+
function resolveProspectForAlias(entityPath, alias) {
|
|
3103
|
+
const terms = getMatchingProspectTerms([alias]);
|
|
3104
|
+
if (terms.length === 0) return [];
|
|
3105
|
+
recordProspectFeedback(
|
|
3106
|
+
terms.map((term) => ({
|
|
3107
|
+
term,
|
|
3108
|
+
action: "merge_alias",
|
|
3109
|
+
entityPath,
|
|
3110
|
+
notePath: entityPath
|
|
3111
|
+
}))
|
|
3112
|
+
);
|
|
3113
|
+
refreshProspectSummaries(terms);
|
|
3114
|
+
return terms;
|
|
3115
|
+
}
|
|
3116
|
+
function dismissProspect(term, reason, notePath) {
|
|
3117
|
+
const matched = getMatchingProspectTerms([term]);
|
|
3118
|
+
if (matched.length === 0) return false;
|
|
3119
|
+
recordProspectFeedback(
|
|
3120
|
+
matched.map((matchedTerm) => ({
|
|
3121
|
+
term: matchedTerm,
|
|
3122
|
+
action: "reject",
|
|
3123
|
+
reason,
|
|
3124
|
+
notePath
|
|
3125
|
+
}))
|
|
3126
|
+
);
|
|
3127
|
+
refreshProspectSummaries(matched);
|
|
3128
|
+
return true;
|
|
3129
|
+
}
|
|
3003
3130
|
function refreshProspectSummaries(terms) {
|
|
3004
3131
|
const stateDb2 = getStateDb3();
|
|
3005
3132
|
if (!stateDb2 || terms.length === 0) return;
|
|
@@ -3041,18 +3168,37 @@ function refreshProspectSummaries(terms) {
|
|
|
3041
3168
|
LIMIT 10
|
|
3042
3169
|
`);
|
|
3043
3170
|
const entityExists = stateDb2.db.prepare(`
|
|
3044
|
-
SELECT
|
|
3171
|
+
SELECT path FROM entities
|
|
3045
3172
|
WHERE name_lower = ?
|
|
3046
3173
|
UNION
|
|
3047
|
-
SELECT
|
|
3174
|
+
SELECT path FROM entities
|
|
3048
3175
|
WHERE EXISTS (
|
|
3049
3176
|
SELECT 1 FROM json_each(aliases_json) WHERE LOWER(value) = ?
|
|
3050
3177
|
)
|
|
3051
3178
|
LIMIT 1
|
|
3052
3179
|
`);
|
|
3180
|
+
const latestFeedback = stateDb2.db.prepare(`
|
|
3181
|
+
SELECT action, entity_path, created_at
|
|
3182
|
+
FROM prospect_feedback
|
|
3183
|
+
WHERE term = ?
|
|
3184
|
+
ORDER BY
|
|
3185
|
+
CASE action
|
|
3186
|
+
WHEN 'merge_alias' THEN 3
|
|
3187
|
+
WHEN 'create_entity' THEN 2
|
|
3188
|
+
WHEN 'reject' THEN 1
|
|
3189
|
+
ELSE 0
|
|
3190
|
+
END DESC,
|
|
3191
|
+
created_at DESC
|
|
3192
|
+
LIMIT 1
|
|
3193
|
+
`);
|
|
3194
|
+
const lastFeedbackAt = stateDb2.db.prepare(`
|
|
3195
|
+
SELECT MAX(created_at) AS created_at
|
|
3196
|
+
FROM prospect_feedback
|
|
3197
|
+
WHERE term = ?
|
|
3198
|
+
`);
|
|
3053
3199
|
const upsertSummary = stateDb2.db.prepare(`
|
|
3054
|
-
INSERT INTO prospect_summary (term, display_name, note_count, day_count, total_sightings, backlink_max, cooccurring_entities, best_source, best_confidence, best_score, first_seen_at, last_seen_at, promotion_score, promoted_at, updated_at)
|
|
3055
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3200
|
+
INSERT INTO prospect_summary (term, display_name, note_count, day_count, total_sightings, backlink_max, cooccurring_entities, best_source, best_confidence, best_score, first_seen_at, last_seen_at, promotion_score, promoted_at, status, resolved_entity_path, last_feedback_at, updated_at)
|
|
3201
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3056
3202
|
ON CONFLICT(term) DO UPDATE SET
|
|
3057
3203
|
display_name = excluded.display_name,
|
|
3058
3204
|
note_count = excluded.note_count,
|
|
@@ -3067,6 +3213,9 @@ function refreshProspectSummaries(terms) {
|
|
|
3067
3213
|
last_seen_at = excluded.last_seen_at,
|
|
3068
3214
|
promotion_score = excluded.promotion_score,
|
|
3069
3215
|
promoted_at = excluded.promoted_at,
|
|
3216
|
+
status = excluded.status,
|
|
3217
|
+
resolved_entity_path = excluded.resolved_entity_path,
|
|
3218
|
+
last_feedback_at = excluded.last_feedback_at,
|
|
3070
3219
|
updated_at = excluded.updated_at
|
|
3071
3220
|
`);
|
|
3072
3221
|
const runRefresh = stateDb2.db.transaction(() => {
|
|
@@ -3078,8 +3227,24 @@ function refreshProspectSummaries(terms) {
|
|
|
3078
3227
|
const confRow = bestConfidence.get(term);
|
|
3079
3228
|
const coocRows = cooccurring.all(term, term);
|
|
3080
3229
|
const coocEntities = coocRows.map((r) => r.target);
|
|
3081
|
-
const
|
|
3082
|
-
const
|
|
3230
|
+
const existingEntity = entityExists.get(term, term);
|
|
3231
|
+
const feedback = latestFeedback.get(term);
|
|
3232
|
+
const feedbackTimeRow = lastFeedbackAt.get(term);
|
|
3233
|
+
const promotedAt = existingEntity ? now : null;
|
|
3234
|
+
let status = "prospect";
|
|
3235
|
+
let resolvedEntityPath = null;
|
|
3236
|
+
if (feedback?.action === "merge_alias") {
|
|
3237
|
+
status = "merged";
|
|
3238
|
+
resolvedEntityPath = feedback.entity_path ?? null;
|
|
3239
|
+
} else if (feedback?.action === "create_entity") {
|
|
3240
|
+
status = "entity_created";
|
|
3241
|
+
resolvedEntityPath = feedback.entity_path ?? null;
|
|
3242
|
+
} else if (feedback?.action === "reject") {
|
|
3243
|
+
status = "rejected";
|
|
3244
|
+
} else if (existingEntity?.path) {
|
|
3245
|
+
status = "entity_created";
|
|
3246
|
+
resolvedEntityPath = existingEntity.path;
|
|
3247
|
+
}
|
|
3083
3248
|
const promoScore = computePromotionScore({
|
|
3084
3249
|
noteCount: agg.note_count,
|
|
3085
3250
|
dayCount: agg.day_count,
|
|
@@ -3103,6 +3268,9 @@ function refreshProspectSummaries(terms) {
|
|
|
3103
3268
|
agg.last_seen_at,
|
|
3104
3269
|
promoScore,
|
|
3105
3270
|
promotedAt,
|
|
3271
|
+
status,
|
|
3272
|
+
resolvedEntityPath,
|
|
3273
|
+
feedbackTimeRow?.created_at ?? null,
|
|
3106
3274
|
now
|
|
3107
3275
|
);
|
|
3108
3276
|
}
|
|
@@ -3127,6 +3295,7 @@ function getProspectBoostMap() {
|
|
|
3127
3295
|
SELECT term, promotion_score, last_seen_at
|
|
3128
3296
|
FROM prospect_summary
|
|
3129
3297
|
WHERE promotion_score > 0
|
|
3298
|
+
AND status = 'prospect'
|
|
3130
3299
|
`).all();
|
|
3131
3300
|
const now = Date.now();
|
|
3132
3301
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -3142,7 +3311,7 @@ function getProspectBoostMap() {
|
|
|
3142
3311
|
return /* @__PURE__ */ new Map();
|
|
3143
3312
|
}
|
|
3144
3313
|
}
|
|
3145
|
-
function getPromotionCandidates(limit = 50) {
|
|
3314
|
+
function getPromotionCandidates(limit = 50, statusFilter = "prospect") {
|
|
3146
3315
|
const stateDb2 = getStateDb3();
|
|
3147
3316
|
if (!stateDb2) return [];
|
|
3148
3317
|
try {
|
|
@@ -3150,15 +3319,21 @@ function getPromotionCandidates(limit = 50) {
|
|
|
3150
3319
|
SELECT ps.*
|
|
3151
3320
|
FROM prospect_summary ps
|
|
3152
3321
|
WHERE ps.promotion_score > 0
|
|
3153
|
-
AND
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3322
|
+
AND (? = 'all' OR ps.status = ?)
|
|
3323
|
+
AND (
|
|
3324
|
+
ps.status != 'prospect'
|
|
3325
|
+
OR (
|
|
3326
|
+
NOT EXISTS (
|
|
3327
|
+
SELECT 1 FROM entities WHERE name_lower = ps.term
|
|
3328
|
+
)
|
|
3329
|
+
AND NOT EXISTS (
|
|
3330
|
+
SELECT 1 FROM entities e, json_each(e.aliases_json) j
|
|
3331
|
+
WHERE LOWER(j.value) = ps.term
|
|
3332
|
+
)
|
|
3333
|
+
)
|
|
3159
3334
|
)
|
|
3160
3335
|
ORDER BY ps.promotion_score DESC
|
|
3161
|
-
`).all();
|
|
3336
|
+
`).all(statusFilter, statusFilter);
|
|
3162
3337
|
const now = Date.now();
|
|
3163
3338
|
const candidates = [];
|
|
3164
3339
|
for (const row of rows) {
|
|
@@ -3167,6 +3342,8 @@ function getPromotionCandidates(limit = 50) {
|
|
|
3167
3342
|
candidates.push({
|
|
3168
3343
|
term: row.term,
|
|
3169
3344
|
displayName: row.display_name,
|
|
3345
|
+
status: row.status,
|
|
3346
|
+
resolvedEntityPath: row.resolved_entity_path,
|
|
3170
3347
|
promotionScore: row.promotion_score,
|
|
3171
3348
|
effectiveScore: Math.round(effective * 10) / 10,
|
|
3172
3349
|
promotionReady: effective >= PROMOTION_THRESHOLD,
|
|
@@ -3178,7 +3355,8 @@ function getPromotionCandidates(limit = 50) {
|
|
|
3178
3355
|
bestConfidence: row.best_confidence,
|
|
3179
3356
|
bestScore: row.best_score,
|
|
3180
3357
|
firstSeenAt: row.first_seen_at,
|
|
3181
|
-
lastSeenAt: row.last_seen_at
|
|
3358
|
+
lastSeenAt: row.last_seen_at,
|
|
3359
|
+
lastFeedbackAt: row.last_feedback_at
|
|
3182
3360
|
});
|
|
3183
3361
|
if (candidates.length >= limit) break;
|
|
3184
3362
|
}
|
|
@@ -3227,6 +3405,7 @@ var init_prospects = __esm({
|
|
|
3227
3405
|
"src/core/shared/prospects.ts"() {
|
|
3228
3406
|
"use strict";
|
|
3229
3407
|
init_vault_scope();
|
|
3408
|
+
init_levenshtein();
|
|
3230
3409
|
PROSPECT_DECAY_HALF_LIFE_DAYS = 60;
|
|
3231
3410
|
PROSPECT_DECAY_LAMBDA = Math.LN2 / PROSPECT_DECAY_HALF_LIFE_DAYS;
|
|
3232
3411
|
STALE_AGE_MS = 210 * 24 * 60 * 60 * 1e3;
|
|
@@ -3566,8 +3745,8 @@ import {
|
|
|
3566
3745
|
IMPLICIT_EXCLUDE_WORDS,
|
|
3567
3746
|
COMMON_ENGLISH_WORDS
|
|
3568
3747
|
} from "@velvetmonkey/vault-core";
|
|
3569
|
-
import
|
|
3570
|
-
import * as
|
|
3748
|
+
import path13 from "path";
|
|
3749
|
+
import * as fs9 from "fs/promises";
|
|
3571
3750
|
function setWriteStateDb(stateDb2) {
|
|
3572
3751
|
moduleStateDb5 = stateDb2;
|
|
3573
3752
|
setGitStateDb(stateDb2);
|
|
@@ -4694,9 +4873,9 @@ async function applyProactiveSuggestions(filePath, vaultPath2, suggestions, conf
|
|
|
4694
4873
|
if (candidates.length === 0) {
|
|
4695
4874
|
return { applied: [], skipped: [] };
|
|
4696
4875
|
}
|
|
4697
|
-
const fullPath =
|
|
4876
|
+
const fullPath = path13.join(vaultPath2, filePath);
|
|
4698
4877
|
try {
|
|
4699
|
-
const stat4 = await
|
|
4878
|
+
const stat4 = await fs9.stat(fullPath);
|
|
4700
4879
|
if (Date.now() - stat4.mtimeMs < 3e4) {
|
|
4701
4880
|
return { applied: [], skipped: candidates.map((c) => c.entity) };
|
|
4702
4881
|
}
|
|
@@ -4705,7 +4884,7 @@ async function applyProactiveSuggestions(filePath, vaultPath2, suggestions, conf
|
|
|
4705
4884
|
}
|
|
4706
4885
|
let content;
|
|
4707
4886
|
try {
|
|
4708
|
-
content = await
|
|
4887
|
+
content = await fs9.readFile(fullPath, "utf-8");
|
|
4709
4888
|
} catch {
|
|
4710
4889
|
return { applied: [], skipped: candidates.map((c) => c.entity) };
|
|
4711
4890
|
}
|
|
@@ -4738,7 +4917,7 @@ async function applyProactiveSuggestions(filePath, vaultPath2, suggestions, conf
|
|
|
4738
4917
|
return { applied: [], skipped: candidates.map((c) => c.entity) };
|
|
4739
4918
|
}
|
|
4740
4919
|
try {
|
|
4741
|
-
await
|
|
4920
|
+
await fs9.writeFile(fullPath, result.content, "utf-8");
|
|
4742
4921
|
} catch {
|
|
4743
4922
|
return { applied: [], skipped: candidates.map((c) => c.entity) };
|
|
4744
4923
|
}
|
|
@@ -4972,7 +5151,7 @@ __export(proactiveQueue_exports, {
|
|
|
4972
5151
|
enqueueProactiveSuggestions: () => enqueueProactiveSuggestions,
|
|
4973
5152
|
expireStaleEntries: () => expireStaleEntries
|
|
4974
5153
|
});
|
|
4975
|
-
import * as
|
|
5154
|
+
import * as path14 from "path";
|
|
4976
5155
|
import { statSync as statSync3 } from "fs";
|
|
4977
5156
|
function enqueueProactiveSuggestions(stateDb2, entries) {
|
|
4978
5157
|
if (entries.length === 0) return 0;
|
|
@@ -5044,7 +5223,7 @@ async function drainProactiveQueue(stateDb2, vaultPath2, config2, applyFn) {
|
|
|
5044
5223
|
`SELECT COUNT(*) as cnt FROM wikilink_applications WHERE note_path = ? AND applied_at >= ? AND source = 'proactive'`
|
|
5045
5224
|
);
|
|
5046
5225
|
for (const [filePath, suggestions] of byFile) {
|
|
5047
|
-
const fullPath =
|
|
5226
|
+
const fullPath = path14.join(vaultPath2, filePath);
|
|
5048
5227
|
try {
|
|
5049
5228
|
const mtime = statSync3(fullPath).mtimeMs;
|
|
5050
5229
|
if (Date.now() - mtime < MTIME_GUARD_MS) {
|
|
@@ -5127,16 +5306,16 @@ var init_tool_embeddings_generated = __esm({
|
|
|
5127
5306
|
model: "Xenova/all-MiniLM-L6-v2",
|
|
5128
5307
|
dims: 384,
|
|
5129
5308
|
version: 1,
|
|
5130
|
-
generatedAt: "2026-04-
|
|
5131
|
-
sourceHash: "
|
|
5309
|
+
generatedAt: "2026-04-12T22:35:09.128Z",
|
|
5310
|
+
sourceHash: "4787251246ff6139",
|
|
5132
5311
|
tools: [
|
|
5133
5312
|
{ name: "correct", category: "corrections", tier: 2, descriptionHash: "ab104cbbf9d936e7", embedding: [-0.112137, 0.05077, 0.026377, 0.010174, -0.059357, 0.026808, -0.014668, -0.030909, 0.033262, 0.027611, 0.027976, 0.036543, 227e-6, -0.032873, 0.017395, 0.041123, -219e-5, 0.110179, 0.028379, -0.018504, 6275e-6, 0.070822, 0.0397, 3946e-6, 0.013957, 0.023896, -0.104276, 2763e-6, -0.014054, -0.122577, -0.015989, 0.079155, 0.027459, 0.044122, -0.023387, 0.090762, -0.021924, -0.017856, 0.051318, -0.045432, -9773e-6, -0.022173, -0.053484, -0.041077, 213e-6, -0.03298, -0.059949, -0.032224, -0.090868, 0.061656, 0.015128, -0.063887, -0.043796, 0.059185, -0.016482, 0.094751, 0.033966, 0.075673, -0.02664, -0.036574, 0.108109, -0.040591, -0.060051, -0.043626, -0.030352, 0.026759, 0.053429, -0.068346, 0.052479, -0.034162, 0.052643, -0.011244, 0.011792, -0.015615, -4771e-6, -1779e-6, -0.025966, 0.03719, -0.031432, -0.093345, -0.0162, -0.065183, 0.010272, 0.051686, 0.063362, -0.027996, -0.043456, -0.045347, 0.034818, 0.080175, -0.025879, -0.094627, 0.141497, -5965e-6, -0.065652, 0.031484, -6416e-6, -8356e-6, 0.069022, 0.060329, 0.058135, 0.106371, -0.034696, 0.010363, 0.079416, -0.010569, -9815e-6, 0.013082, -0.04944, -0.053058, -614e-6, 0.025107, 0.045675, -0.026209, 0.028465, -0.037018, -0.016706, 0.011322, -0.053478, 0.049009, 0.072959, -0.018558, -0.017536, 0.015453, -0.056476, -0.025292, -853e-6, 0, 0.109517, 0.051035, -436e-5, -0.02546, 0.053702, 0.012196, -0.092574, -0.067859, -0.082448, -0.030584, 0.04953, 5629e-6, 0.018349, 0.036023, -0.048056, 0.022057, -8418e-6, 0.093832, 0.020071, 0.060862, 0.018577, 0.046417, -0.022997, -0.010351, 0.028345, 0.073876, -445e-6, -0.014539, -0.027922, -0.016345, 0.02612, -0.048091, 0.067337, 0.029427, 0.042862, 0.02865, 0.037074, -0.067455, -0.039382, -0.083748, 0.014111, 0.041082, -0.044054, -0.088079, -0.022421, -0.026242, 1517e-6, 0.029601, 0.083941, -7021e-6, 0.042373, 0.076519, -0.038581, -0.023357, 1342e-6, 4167e-6, 0.014898, 0.026353, 4946e-6, 0.075959, 0.121664, -6181e-6, -0.04119, 188e-6, -0.05305, 0.056259, -0.014163, -0.082006, 0.033895, -3682e-6, -0.067722, 6538e-6, 0.030868, 0.050463, -5444e-6, -0.090016, -0.078164, -0.049525, 0.012905, 182e-5, -0.055408, -0.059239, -0.06449, 0.095689, -0.028328, -0.075978, 8404e-6, -0.073829, -0.039537, 0.014228, 4733e-6, -6572e-6, -0.023809, 0.02693, 0.053276, -0, 0.043507, -0.026395, -0.059847, 0.074179, -0.057412, -0.026139, 0.027878, 0.079916, 0.068508, 5595e-6, 4638e-6, -0.038802, -0.077282, -0.020645, -466e-6, -0.035289, -0.048797, -0.027662, -0.011941, 0.038905, 0.052053, -0.019324, -0.015524, 0.115244, 0.052004, 0.022335, 9845e-6, -0.043505, 0.032588, -0.057991, 0.014567, 4846e-6, -0.054494, -0.026246, 0.05298, -0.087103, 0.053247, -8393e-6, -0.078638, 9214e-6, 0.065006, 0.05517, -0.03903, 0.09994, 0.04905, -0.018042, -0.048194, 0.078942, -3651e-6, -0.035746, 0.03899, -0.058707, -0.019853, -0.017654, 0.048571, 0.028416, 0.026525, -0.093748, -0.026548, 0.03167, -0.052844, 0.060918, -0.052816, 0.029207, 0.042988, -1484e-6, -0.045086, -0.030614, -0.019668, 699e-5, 0.035397, -0.02612, -0.018835, -0.107687, 0.147089, -0.099558, -0.066147, -0.036173, -0.044325, -0.037926, -0.016089, -0.020625, 0.080158, 0.083126, -0.035453, -0.012411, -0.018514, 0.06544, -0.0458, 0.016839, -0.034864, -0.020352, 0.016488, -0.014599, -0.071506, -0, -0.170263, 0.022366, -0.019692, -9536e-6, 0.057014, 6094e-6, -0.027565, 0.095143, -0.029668, -0.056879, -1233e-6, 9667e-6, -0.043449, -0.102301, 0.013517, -0.034099, 0.034423, 0.053725, -0.069814, 0.018209, -0.069986, 0.058077, -0.019755, -0.056135, 673e-5, 4859e-6, 0.013008, 0.092358, 0.022798, -2356e-6, 0.044878, -963e-5, 0.08368, 0.036551, -6654e-6, -0.057746, 0.104987, -0.026351, 0.060275, 0.022709, 0.02862, 0.036379, -0.046548, 0.07899, -0.023751, -0.032051, 0.013826, -0.071854, 0.011729, -0.125561, 0.010702, -61e-6, -0.074215, 0.029655, -0.039268, 0.102985, 0.100883, -0.048536, 0.038982, -0.036561, 0.157337, -0.026732, 0.042879, -0.055083] },
|
|
5134
5313
|
{ name: "discover_tools", category: "search", tier: 1, descriptionHash: "aa8995ef7f47401b", embedding: [-0.075188, -0.021086, -0.070189, 0.027863, -0.011663, -0.111824, -0.030346, -0.055104, -0.028948, -964e-5, 0.048634, -0.057464, 0.033817, 7175e-6, 0.011836, 0.053405, -0.013156, -0.036403, 0.089025, -0.065241, 5382e-6, 0.037918, -5621e-6, -0.040135, 0.019724, -0.022742, -0.055146, -0.04527, 0.02007, -9524e-6, -0.016252, 0.057074, -4075e-6, 505e-6, 0.084357, 0.105241, 0.05814, 0.016512, -0.02048, -0.089392, -0.017279, -0.059956, -0.042557, -0.020422, -0.013626, -0.053287, -0.116333, -0.027996, -0.010748, 3943e-6, -0.046903, -0.094901, -0.06335, 0.072725, 0.058132, 0.109191, 7471e-6, -0.012742, -0.025956, -0.022849, 0.067187, -983e-6, -0.048119, 0.016697, -0.041044, 0.044199, 0.021653, -0.044895, 0.081919, -0.116255, 0.015069, -9135e-6, -0.039679, 0.027543, 0.106306, 0.056589, 0.032697, 0.038454, -0.035896, -0.151718, -0.069043, 0.051894, -0.029377, 0.069531, -0.023954, 0.071038, -0.014322, -0.028599, 0.076246, 0.016156, 0.020133, -0.134726, -0.073939, -0.071862, -0.018366, 0.013815, 7942e-6, -0.03676, 0.034956, -0.010209, -0.077494, -9537e-6, 0.029254, -0.084394, -0.044125, 0.099604, -0.063872, -0.014194, 0.061705, 0.017144, -0.021457, 1541e-6, 0.076249, -0.033957, 0.053548, 0.035583, -0.067036, -0.020214, -0.05177, 0.071649, 0.052922, 0.109373, 0.044848, -0.055537, -0.018694, 0.098885, -0.056785, -0, 0.105679, -0.019862, 2447e-6, 0.062664, -3153e-6, 0.03486, 0.047175, 0.018801, -0.059901, 0.02577, -0.057711, 0.059793, -0.061608, -7361e-6, 0.028895, 0.046272, 0.042275, 0.057409, 0.035205, -0.040239, -5299e-6, -0.014404, -0.029234, 0.043057, 0.101209, 0.053609, -0.0104, -3749e-6, 5548e-6, 0.025031, -0.06258, -0.024213, 0.034139, 0.067818, -0.018895, 0.079705, -0.010918, -0.026168, -0.028529, -0.01576, 0.023614, -0.019583, -0.054301, -0.089354, 0.020601, -0.080503, -0.067058, 0.028848, 0.072858, -0.012721, -0.016256, 7214e-6, 0.073557, 6098e-6, -0.011199, -213e-5, -0.01642, 0.033319, 0.053211, 0.038781, 0.033251, 0.018787, -0.070695, 0.089868, 0.011783, 3361e-6, 0.016143, -0.046838, 8084e-6, 0.089449, -0.043313, 0.061697, -0.040691, 0.012123, 0.024459, -0.148406, -0.037517, -0.057303, 0.024418, -7207e-6, -0.019377, -0.05232, -0.046205, 0.058728, 5983e-6, 0.013952, 0.021432, -0.042616, -0.043659, -0.068847, -0.091945, 9479e-6, -0.061069, 0.032148, 9958e-6, -0, 0.040652, -0.068116, 0.072305, 0.035184, -0.020632, -0.057712, -0.02841, -0.082632, -0.01321, 0.019844, 0.090441, 0.035095, -0.044615, -0.129175, 0.114251, 0.070678, -0.063627, -0.100181, 0.025629, 0.109847, -0.035361, 1383e-6, -0.115486, 0.04072, 0.041929, -0.067248, 8969e-6, -2463e-6, 0.018072, 135e-6, 9092e-6, 0.080653, -0.035027, 495e-5, -0.045352, 0.017452, 0.09904, -0.027698, -527e-6, -0.025174, 3514e-6, 0.049152, -0.099115, 7461e-6, -7823e-6, 0.040005, -0.014621, 0.05924, -0.024107, -0.047808, 0.085614, 0.017335, -0.010463, -0.049807, 2247e-6, 0.064009, 0.042356, 0.018684, -0.040498, -0.020599, 0.036185, -0.010663, -0.043319, 0.083483, -7926e-6, -6604e-6, -0.023185, 0.024318, -0.090426, -0.045626, 0.0199, 0.02269, 0.040662, -0.096964, 0.028033, -0.036186, -0.087325, -0.038926, -0.023116, 0.02771, 0.019014, -1276e-6, 0.118484, 0.010463, -0.033128, 7546e-6, -0.015151, 0.083676, -0.035601, -3541e-6, -0.089467, -0.032535, -0.070525, 0.024172, 0.02375, -0, -0.021465, 0.044607, 0.014306, -0.047116, 0.075083, 0.085343, -0.012816, 0.157587, -0.034197, 1913e-6, -0.029213, -0.019289, -0.014942, 0.041905, 0.029948, -0.013572, 0.025128, 9812e-6, -0.059942, -0.056379, 5458e-6, -252e-5, 0.057553, 3015e-6, 7678e-6, -0.072857, -0.057614, 0.030144, 0.038096, 3422e-6, -992e-5, -0.052856, 0.067301, -7253e-6, 0.093171, 0.057181, 0.024557, 3957e-6, 0.015116, 0.049431, 7994e-6, 0.033472, -5896e-6, -0.035395, -0.084564, -0.018945, 0.027141, 0.028566, 0.020801, -0.028642, -258e-5, -0.023189, -7276e-6, 1472e-6, 377e-6, 0.105597, 0.040329, -0.052133, 0.055025, -0.054046, 0.021824, -0.046932, 0.064667, -2851e-6] },
|
|
5135
5314
|
{ name: "doctor", category: "diagnostics", tier: 1, descriptionHash: "323b22c45b7357a0", embedding: [8136e-6, 0.012652, -0.104053, -0.012698, -0.020335, -0.074709, 0.022254, 0.084598, -0.054423, -0.045362, -3323e-6, 393e-6, 0.011297, 2735e-6, -0.027277, -0.012705, 1631e-6, 0.013887, 0.013833, -0.045375, 0.019835, 0.081895, -0.04618, 0.035734, -0.060544, -0.018431, -0.127578, -0.028479, -0.044941, -0.039594, -384e-6, -2425e-6, 0.036848, 0.076963, 0.022879, 0.048686, 0.088946, 781e-6, -0.054264, -0.044612, 0.015734, -0.079771, -0.043929, 0.013549, 0.030191, -0.045489, -0.119089, -0.053716, -0.04456, 0.067454, -0.057806, -0.057265, 316e-6, 0.121579, 0.011271, 0.05804, 477e-5, -0.031105, -0.097391, -0.061847, -0.036711, 176e-6, -0.032982, 0.057692, 0.034182, 0.053259, 0.032602, -9093e-6, 0.086273, -0.081044, -0.07594, -0.068649, -0.010132, 0.037269, -8189e-6, 0.029522, -0.016749, -0.043189, 1326e-6, -0.110331, -0.052518, 0.051387, -0.015152, 0.061301, -5324e-6, 0.085205, -0.019257, -0.026214, -49e-4, 9382e-6, 0.03915, -0.080184, 0.014607, -0.010532, -348e-6, 0.014564, -0.064922, -0.078807, 0.058181, 0.016433, -0.046079, 5318e-6, 0.076108, 6728e-6, 3499e-6, -0.047199, -0.013175, 0.016525, 0.013801, 5085e-6, 5752e-6, 0.042692, 0.053901, -0.056473, 0.098547, 0.018388, -0.102192, 0.032608, -0.048075, 0.091995, 0.072244, -0.012618, 0.0413, -0.041725, 0.054021, 0.011412, -3073e-6, -0, 0.079493, 0.014237, 0.049427, 0.06834, 0.059033, 0.05144, 0.014408, -0.04276, 0.015375, 0.011979, 0.022073, 0.120143, -0.010709, -0.024758, -0.021697, 0.049621, 4077e-6, 0.105483, -9952e-6, 0.041259, 0.02338, -0.015017, -0.010624, 0.023728, 0.102889, 744e-5, -0.037233, 0.013603, -0.033702, 799e-5, 5733e-6, -0.06343, -9938e-6, -0.071456, 0.048186, 9645e-6, 0.017757, -2797e-6, -0.021119, -0.065155, -0.060029, -0.060184, 0.018777, -0.011857, 0.010794, -0.07595, -0.090741, -2596e-6, 0.01942, 0.016046, 0.019233, -0.019173, 0.032646, -0.031759, 0.046188, -0.032001, 0.029469, -0.024869, -0.031216, 0.074847, 0.064354, -6935e-6, -0.056857, -0.020156, -0.059865, -0.043686, -0.030008, -0.089058, 0.043647, 0.041228, -0.070896, 0.037355, 4331e-6, 0.058013, 0.021254, -0.032409, -0.058646, -0.031653, -0.053518, -0.017684, -0.054452, 2916e-6, -0.050519, 0.150255, 8186e-6, 0.021956, -8975e-6, -0.045364, -0.087999, -0.051391, -0.108334, 0.031466, 7418e-6, 0.019992, -2294e-6, -0, -84e-5, -1124e-6, -0.028518, 0.041323, -0.028531, -0.02041, 7087e-6, -0.022711, 0.031301, 0.019491, 0.058479, 0.04317, -0.084726, -0.036933, 0.016874, 0.039338, -0.09775, -0.128744, 3347e-6, 0.097726, -0.017081, 0.045822, -0.074403, 0.076138, -0.050555, 0.055966, -0.030228, -0.014547, 0.054807, -0.075309, 0.053818, 0.028171, 1849e-6, 0.029274, -0.046137, -0.058202, 0.045929, -0.052037, -0.021068, 8679e-6, 0.114068, 0.031265, -0.035864, -0.036406, -0.059043, 0.029492, 0.036846, 0.012242, 3433e-6, -0.045454, 0.039008, -0.026932, -8463e-6, 0.07396, -0.013812, 0.062471, -0.048673, -0.035366, -0.131441, -0.034066, 0.047647, 0.033703, -0.06332, 0.073051, -0.054582, -0.061743, 0.098632, 0.018907, -0.074109, 664e-5, -0.011785, -0.055462, 0.036835, -0.053971, 0.068999, -0.028482, -0.102404, -0.09826, -0.063134, 0.065532, -0.030944, -0.070604, -0.028021, 0.067256, 0.027959, -0.04778, 0.070257, 1416e-6, 0.024908, -0.014259, -0.043247, -1922e-6, -0.095786, 0.017281, -0.010689, -0, -0.051685, 7184e-6, 0.049666, -0.031695, 0.023869, -0.015568, -0.017808, 0.06918, -7775e-6, 0.048827, 7195e-6, -0.027944, -0.114327, -0.100461, 0.11559, -0.020618, -0.052646, 0.081425, -0.068174, -0.052436, -0.034294, -561e-6, -0.013413, -0.039849, -3429e-6, -882e-6, 0.067595, 0.055667, 0.030007, 0.029895, 0.030387, 0.060059, 0.098835, -0.015598, 7647e-6, 0.065764, 0.063223, 1657e-6, 0.086573, 0.098405, 6676e-6, -2128e-6, 0.041294, 0.054462, -0.045867, -0.032182, -5717e-6, 0.047038, 0.057546, -0.088133, -2008e-6, -9601e-6, 0.045612, 0.083221, -0.036275, 0.087487, 0.086664, -0.049959, 0.046976, 0.034599, 0.095982, -0.021363, 0.069936, -0.01591] },
|
|
5136
5315
|
{ name: "edit_section", category: "write", tier: 1, descriptionHash: "8e0c997860daa732", embedding: [-0.067052, 0.048307, 0.015174, 0.067059, 0.027596, -0.052268, -0.071763, -0.016635, 0.023139, 0.019763, 0.021243, 0.053329, 0.077049, -0.038907, 0.047175, 0.033776, -0.06156, 0.062083, -0.017618, -0.018534, 0.054384, 0.096259, 0.066491, 0.045905, -2441e-6, -0.045738, -0.109804, 0.0359, -0.028463, -0.077512, 0.039082, 7961e-6, 0.051298, 0.024218, 0.053931, 0.08958, -798e-5, -5804e-6, 0.058097, -0.05296, 2235e-6, -0.0817, -0.082882, 0.068258, 4411e-6, -0.028889, -0.037087, -0.080344, -0.028016, 0.089782, -6375e-6, -0.123597, -0.040801, 0.093916, -0.083001, 0.072957, -0.017947, 0.016541, 2439e-6, -0.059709, 0.144232, 0.053963, -4015e-6, -0.045265, -0.010297, 0.023336, 0.061649, 0.050405, 0.011611, -0.0503, 0.061583, -0.02326, 0.026058, 0.017051, 0.026413, -0.02805, -0.071218, -6884e-6, -0.090258, -0.049108, 0.031765, 0.016722, -5343e-6, -0.010928, 0.033908, 0.043257, 2963e-6, -0.096023, 0.017447, 0.034006, 0.036735, -0.143404, 0.103961, -0.089369, -0.029156, 0.020612, -3701e-6, -0.082816, 0.028181, 0.025791, -0.020477, 1954e-6, 0.012171, 0.024567, 0.019771, 4542e-6, -0.011138, 0.073229, -0.056839, -0.029588, 3286e-6, -0.011874, -0.011458, -0.073342, -0.035939, -0.033083, 0.033741, 0.029137, -0.031901, 0.084325, 0.134047, -3984e-6, 4964e-6, 0.058164, -0.109967, -0.080984, -0.055905, 0, 0.092217, 0.063646, -0.100505, 0.06954, 0.019004, -0.021002, -0.018353, -0.034803, -0.062732, -0.046656, 0.042325, -0.063882, 0.013378, -4759e-6, -9881e-6, 0.010279, -0.011301, 0.086284, 0.010003, -3139e-6, -0.035402, 0.071308, -0.049256, -0.102604, 0.043115, 0.043318, -0.036904, -0.027319, -0.02966, -0.013341, 5451e-6, -8296e-6, 0.030978, 0.030911, 1773e-6, -0.019134, 0.023559, -0.046612, -0.043057, -0.03183, 0.033217, 2208e-6, 0.044079, -0.041489, 2237e-6, 0.045476, 0.028155, 0.068179, 0.017865, -0.098845, 0.044667, 0.081164, -0.032552, -0.032692, -0.021051, -0.043075, -1155e-6, -0.045039, 4792e-6, 0.020424, 0.09897, 8135e-6, -0.07348, 0.080432, -0.063947, -0.034491, -0.010039, -0.016932, 0.032387, -0.010912, -0.093681, 6393e-6, -0.042092, 0.058883, -0.04643, -0.113692, -0.104739, -0.021103, -0.033485, -0.011788, -9746e-6, -0.070301, -0.025267, 0.058342, 0.067454, 0.024718, 0.036855, -0.057702, -4955e-6, -0.113337, 0.028752, -0.042897, 0.03358, -0.061752, 0.100702, -0, 0.088136, -0.067319, -0.037074, 0.069494, -0.077527, 0.02395, -0.018071, 0.036678, 2396e-6, 3391e-6, -0.041165, 0.048665, -0.051129, -0.016925, -0.010118, -0.013078, -0.074828, -0.034036, -0.029894, 0.045862, 0.02358, -0.030888, 0.025567, 0.052181, 0.025056, -0.020087, -158e-6, 0.05592, 0.064273, -0.018629, -0.052678, 0.03067, -5597e-6, -0.024412, 0.01147, -641e-5, 0.036802, -0.07137, -0.026161, -1637e-6, 0.142442, -0.034615, 0.023111, 258e-5, -0.024848, 8382e-6, -4387e-6, 0.075396, -0.054066, -0.04846, 0.014834, -0.029765, -0.070955, -0.086352, 0.101422, 0.073069, -0.022721, 0.023387, -801e-6, -0.054793, 0.027974, 0.137145, -0.014716, 0.048945, 0.045883, -0.034078, -0.033381, 0.010678, -0.104538, -0.018514, 0.01488, -0.039602, 0.031921, -0.113138, 0.060907, -0.042833, 0.033138, -0.03025, -2764e-6, -0.027634, -0.03662, -4341e-6, -0.01968, 0.019597, 2712e-6, 0.017167, -0.019994, 0.095157, -0.05552, -0.035796, -0.030043, 263e-6, 0.106622, 0.026061, -0.05899, -0, 0.01673, 0.042963, -0.07519, -0.024475, 0.016026, 929e-6, -1818e-6, 0.061545, 0.023024, 0.013325, 0.022661, 0.027136, -0.052607, -0.077814, -0.079877, 0.028668, -0.028953, 0.063253, -0.049663, -0.028917, -0.046846, 0.096291, -331e-6, -0.072747, 0.028645, 0.03225, 0.020906, 0.06931, 0.081096, -0.024922, 0.044655, -0.056187, -9857e-6, 0.077085, 0.015907, 0.018662, 0.089081, -0.010739, 0.018846, 0.074224, 0.062288, -0.04758, -7368e-6, 0.058292, -0.010243, -0.014694, -1364e-6, -0.02006, 0.047091, -0.043469, 1525e-6, 0.034477, 7767e-6, -0.021154, -0.027786, 0.029545, 0.131995, 7411e-6, 0.014928, -0.018281, 0.086814, -0.022969, 0.087812, 9203e-6] },
|
|
5137
|
-
{ name: "entity", category: "note-ops", tier: 2, descriptionHash: "
|
|
5316
|
+
{ name: "entity", category: "note-ops", tier: 2, descriptionHash: "fc7968d14b8c9cab", embedding: [-0.074349, -0.030711, -4673e-6, 0.014717, 0.016205, -0.039608, 0.021641, 0.023785, 0.014913, -0.011524, 0.060717, -0.039357, 0.013297, -4344e-6, 0.05836, 0.101867, -0.04183, 0.10595, 0.044607, -0.015519, 0.024446, 0.073093, -4335e-6, -0.021167, 8419e-6, -0.099374, -0.081139, 0.015894, -0.066548, -0.096353, 0.055687, 0.134062, -7137e-6, 0.073362, 0.032144, 0.061337, -0.026326, 0.04838, 0.037707, -0.045823, -0.011087, -0.067804, -0.056536, -0.030159, -0.057211, -0.05053, -0.051258, -0.029718, -0.01872, 0.031035, -0.028443, -0.109819, -0.026341, 0.074417, -0.05862, 0.068507, -0.056374, 0.013294, -0.058399, -0.04427, 6184e-6, 0.016332, -0.02226, -0.016271, -0.037241, 0.022785, 0.063241, 0.033494, 0.051421, -0.08406, 0.075491, -0.027314, -0.117858, -2328e-6, 0.010446, -821e-5, -772e-5, 0.024936, -0.042996, -0.075486, -0.081466, 0.034634, -0.015721, -0.057664, -1425e-6, 0.040765, 6163e-6, -0.049531, 0.034535, 0.027097, -0.033255, -0.113266, 0.113385, -3497e-6, 2225e-6, 0.029856, 0.053917, -0.097292, 0.011401, 0.072309, -0.065279, 0.078804, -0.064662, -0.020436, -0.01586, -0.030065, 1e-5, -0.02242, 0.027148, -0.021899, -2489e-6, 0.036677, -0.022297, -0.060509, 0.031537, 0.011305, -0.065819, 0.041585, 0.04277, -0.089205, 0.081537, 0.043829, 8431e-6, -0.038149, -0.084868, 0.019989, -0.077351, 0, 0.072938, 0.07783, -0.016321, 0.013197, 0.014578, 3365e-6, -0.029743, 0.041672, -0.066253, 708e-6, -7259e-6, 0.04384, 0.02702, -0.017667, -0.047038, -0.042624, 0.059663, 0.16348, 0.056527, 0.021449, 9796e-6, 0.132062, -0.016521, 0.018898, 0.046219, 0.026494, -0.037787, -1333e-6, 0.012356, 0.0304, -0.017244, -7358e-6, 0.02361, 0.066725, 0.055691, 0.068757, -0.020913, -0.07959, -0.019111, -0.056279, 441e-6, 0.027094, -0.03443, -0.039197, 0.028451, -0.05634, 0.053026, 3143e-6, 0.097281, 0.049942, -2061e-6, -0.022903, -6358e-6, 0.05247, -0.045488, -0.076316, -0.043571, -0.017934, 2056e-6, -0.013093, 0.017602, -2454e-6, -0.119375, -0.017161, -0.037515, -0.015248, -0.037564, -0.035183, 0.10312, -1734e-6, 0.012156, 0.075233, -0.015103, -0.014867, -7548e-6, -0.106772, -0.010453, 0.020751, 0.065799, 0.017364, 1713e-6, -0.073032, -0.098151, 0.048889, 0.038104, 0.041838, 0.054251, -0.070533, -0.067247, -0.030549, -0.090314, 0.042169, -0.022402, 0.038134, 0.080058, -0, 0.072156, -0.028521, -0.040202, 0.027863, -0.023641, -0.024939, 0.043483, -0.027534, -0.086423, -0.044268, -0.062423, -2552e-6, 0.013815, -0.058316, -6794e-6, -0.058177, -0.034242, -0.020941, -0.039637, 0.087961, -0.015674, -725e-5, 2886e-6, 0.06314, 0.06, 6294e-6, 8963e-6, -0.03842, 8355e-6, -0.073809, 0.071558, -812e-5, -0.069666, -0.075252, 0.015169, -0.061867, 3546e-6, -0.050793, -0.066527, 8e-6, 0.03084, 0.019838, -0.011502, 0.020877, -874e-6, -0.024372, 5663e-6, 0.057321, 0.031993, -0.05237, 0.011831, -0.013311, -0.066601, -0.047359, 0.01335, 0.016531, 0.072481, 0.01181, 0.020594, -0.028156, 0.067552, 0.102041, 0.035974, 0.075115, 0.051617, -0.117679, -0.017597, 0.052714, -0.101744, -0.023201, 0.023351, -7892e-6, 0.03825, -0.099066, 0.048381, -0.118559, -0.018954, -0.109564, 0.015335, -0.014241, -0.016968, -0.0125, 0.026907, -0.015773, -0.011793, -0.042037, 5008e-6, 0.099264, -108e-5, 0.035198, -5905e-6, -0.067192, 0.011385, 0.07176, -0.054807, -0, -0.01612, 0.098306, 2e-5, -0.011442, 0.030306, -0.050975, -0.028135, 0.074353, 0.020353, -0.042162, 0.022544, -0.011764, -0.106717, -0.017467, 0.134766, -0.050684, -3099e-6, 0.053383, -0.06475, 475e-6, -0.07621, 3452e-6, -0.022456, -0.056419, -524e-6, 0.028282, 0.014936, 0.074807, 0.080093, 2737e-6, 0.021908, 0.013577, 0.023381, 0.016646, 0.027662, 0.080965, 0.034267, -6876e-6, 0.035, 0.079081, 0.013812, -0.018612, 878e-5, 0.095351, 0.018059, 2524e-6, 0.016052, -0.061828, 0.030652, -0.043824, -0.032389, -8527e-6, 8395e-6, 0.040602, -0.0146, 0.07797, 0.057081, 618e-6, 0.026012, -0.017675, 0.145267, -0.125366, 7407e-6, 0.069939] },
|
|
5138
5317
|
{ name: "find_notes", category: "read", tier: 2, descriptionHash: "e43ef3fc29d690a1", embedding: [-0.054341, 0.039439, -0.044432, 0.022322, 0.011014, 0.021297, -4058e-6, 0.063912, 6699e-6, -0.020245, 0.036915, 0.014972, 0.02641, -0.0168, 0.054404, 0.068953, 0.044485, 0.014181, 0.064311, -0.026328, 0.077049, 0.078528, 0.043754, 0.011862, 6072e-6, 0.065804, -0.144039, -0.017154, 4967e-6, -1893e-6, 0.018293, 0.105838, 0.074875, 0.064933, 9055e-6, 0.056938, 9252e-6, 0.015548, 8381e-6, -0.039663, -0.056536, 0.035168, -0.03837, -8193e-6, 0.01818, -0.057859, -0.036215, -0.068611, -4045e-6, 0.031883, -0.112803, 4856e-6, -0.098483, 0.039872, 0.061848, 0.074749, -6271e-6, -0.029598, -0.064662, -0.058485, 0.081913, -0.06918, -9205e-6, -0.041496, 0.014628, -0.027251, 0.05546, -0.013967, 0.05891, -0.114635, 0.083853, 0.018713, 0.035283, 0.036248, 0.018283, -1241e-6, 0.011769, -0.046454, -0.080704, -0.105532, -0.096056, 0.035184, 0.033308, 0.028251, 0.015954, -0.050287, 0.023437, -0.061715, 201e-6, 0.044144, 0.088367, -0.102717, -0.022125, -0.028262, -0.012286, 0.033757, 8688e-6, -0.022029, 0.081943, 0.018609, 0.072085, 0.090256, 0.013671, -6267e-6, -0.026406, 0.049545, 934e-5, 0.030417, -0.016597, -0.100792, -0.018438, 0.011967, 0.02029, -0.048835, -647e-5, -0.107246, 0.026166, -0.03588, 0.038517, 0.098497, 0.066761, 8518e-6, -0.013316, -0.011762, -0.072731, 0.028334, -0.091472, 0, 0.048616, 0.012847, 0.027144, 1156e-6, -0.025398, -0.016007, 0.032083, 0.065254, -0.070518, -0.036161, 0.035027, 0.056406, -0.028495, 0.032387, 0.02176, 8554e-6, -0.025108, 0.074236, 0.032739, -0.022668, 0.028385, -0.010285, 0.048268, -0.03827, 0.050248, 0.019086, -0.043955, -0.068474, -0.02828, 0.012578, -0.034184, -0.049215, 0.026051, -0.038005, 0.013429, 0.063066, -0.044237, 0.029965, 996e-6, -0.129581, -0.026558, 6055e-6, 0.01535, -0.066075, -0.042532, -1706e-6, -0.105433, 0.06226, 0.085967, 0.010674, 0.014807, -9169e-6, -0.048066, 0.045601, 0.054746, 0.031343, 0.056235, 0.0533, -0.030893, -1126e-6, 0.022036, 6203e-6, -0.013592, 0.035852, -0.042473, 7124e-6, 2208e-6, -0.033978, 0.075161, 0.054846, -4754e-6, 0.0502, 0.055544, 0.048583, 0.015212, -0.086446, -0.050873, -0.109523, 0.029365, -0.04682, -0.056148, -0.020004, 7237e-6, 0.081601, -0.036359, 0.028221, 0.036311, -0.156106, -0.010089, -0.046791, -0.11062, 0.02759, -0.068914, -0.038736, -0.050262, -0, 0.035006, -0.035668, -0.019049, -0.014392, -5142e-6, 0.017456, -0.037488, -0.012334, 0.037256, 0.072443, 7493e-6, 3859e-6, -0.039783, -0.033929, 0.022894, 0.026035, -0.018817, -0.0455, 0.024698, 0.022968, -0.085025, 0.024032, -0.065655, 0.086953, 0.035452, -0.0146, -0.044447, -0.069359, 0.016187, -0.042209, 8918e-6, -0.056148, -0.039114, -0.029694, -0.086095, -0.016938, 0.015871, -0.079043, -0.082079, 0.114878, 0.016947, 0.103945, 0.026252, -0.047287, -0.035133, -0.034462, -0.040436, 0.082758, -0.016521, -0.032669, 0.126392, -0.055838, -0.033721, -0.017031, -0.021902, 0.05615, -0.013186, 0.012233, -0.096453, -0.038843, -3245e-6, 0.0643, -0.092457, 0.061311, 0.015543, -0.089837, -0.010332, -0.042464, -0.103932, 5331e-6, -0.010902, 6017e-6, 0.053773, -0.02847, 0.063789, 0.058411, -0.049378, -0.036728, -0.034957, -0.04661, -1056e-6, -0.020962, 0.075972, 0.075697, -0.022339, -0.014775, -9826e-6, 0.086344, -0.038529, 1179e-6, -0.017339, -0.090336, 0.035132, 0.036094, 0.031364, -0, -0.123306, -0.056555, -0.064158, -2092e-6, -0.012719, 0.033651, 0.028565, 0.071721, -0.017412, 0.044538, 0.050581, -0.060295, -0.113453, -0.018418, -0.029911, 538e-5, 0.093897, 0.014913, -0.048809, -0.033582, 0.019178, 0.055919, -0.033986, -1684e-6, 0.034307, 0.017134, -0.03497, 0.082927, 0.011102, 0.014656, 0.04996, 0.049819, 0.014126, -7041e-6, 0.067124, 0.042589, 0.053929, -5299e-6, -0.051256, 0.121051, 0.067496, 0.039915, -0.069309, 0.045262, 0.046579, -0.033982, -0.031061, 0.02494, 0.022027, -0.042985, -0.033733, -0.029843, -0.051682, -1858e-6, -0.059954, 0.07073, 0.056452, 0.042733, 0.049113, -0.097473, 0.142043, 0.027087, 0.037172, 0.047505] },
|
|
5139
|
-
{ name: "graph", category: "graph", tier: 2, descriptionHash: "
|
|
5318
|
+
{ name: "graph", category: "graph", tier: 2, descriptionHash: "1b79c0ca03886cbd", embedding: [-0.035909, -8846e-6, -0.041507, -4788e-6, 0.032173, -0.065733, -0.096299, 0.023865, -5473e-6, 0.041158, 0.066489, 0.02576, 0.015557, 0.030437, 0.040624, 0.063476, -0.031096, 0.02673, -4251e-6, -0.072202, 0.028127, -0.013806, 0.016571, -485e-6, 0.048246, -0.043761, -0.067387, -0.016971, 0.035629, -0.069259, -0.033511, 0.033872, -0.013958, 0.055208, 0.013192, 0.134415, 0.031984, -0.014654, 0.024033, -7977e-6, 0.023797, 0.02113, 6925e-6, 0.016055, -2678e-6, 8251e-6, -0.158198, -0.015489, -0.078854, 0.047337, -0.054456, -0.019368, -0.093306, 0.037513, 0.048442, 0.093579, -0.077433, -0.085391, 1507e-6, 0.0361, 0.106361, -0.014488, -0.067992, -518e-5, 0.019918, 0.055019, 0.051241, 0.063897, 0.026877, -0.011902, 0.032036, -0.051093, -0.116894, 0.03736, 0.024688, 0.09436, -0.010614, 0.020526, -0.082658, -0.153377, -0.017834, 0.050199, -0.015689, 0.079668, 2802e-6, 0.017534, -647e-6, -0.024686, -0.017222, 0.047876, -0.03712, 0.011261, 0.049175, -0.015074, -0.025875, 0.049774, 0.050972, -0.040303, -993e-5, 0.024068, 0.017379, 0.029883, 0.07355, -0.043429, -3096e-6, 0.037051, -8769e-6, 0.033582, 0.037079, 0.032086, -0.048391, 0.064836, -0.01385, -0.068058, -0.018794, -0.04012, -0.041947, 1945e-6, 0.034552, 0.052581, 0.056469, 5902e-6, 0.089737, -0.04318, -0.06051, -0.073695, -0.070785, 0, 0.056419, -0.011847, 567e-5, -0.017629, 0.018553, 0.012356, -0.066543, -0.068152, -0.091452, -113e-5, -0.092888, 0.104693, -0.024249, 0.07725, 0.044893, 2658e-6, 0.075136, 0.0447, 0.027947, -0.081548, -155e-6, -3673e-6, 0.012653, 0.040394, 0.10984, 0.01713, -0.022906, -0.046898, -3747e-6, 0.014631, -0.01398, 0.028551, 0.057564, 0.042347, 0.018958, 0.055598, -8864e-6, -0.101964, -0.030339, -0.075357, -0.052891, 662e-5, -0.013085, -0.05675, -9617e-6, -0.020113, -0.024186, -0.045889, -0.015118, 8751e-6, -0.057937, 0.014473, -2387e-6, 0.056074, -0.040174, -0.072804, 0.033112, 5334e-6, 0.026634, 0.096673, 0.029418, 7971e-6, -0.022942, 0.021743, -5642e-6, 0.017654, -0.139056, -0.047749, 0.027206, 0.096436, -0.042175, 0.06749, -0.016763, 0.012173, -0.022599, -0.07406, -0.082232, -0.107685, -0.021949, 0.015389, -0.106065, -0.117851, -0.078646, 557e-5, 355e-6, -0.021651, 0.034759, -0.072601, -0.042125, -0.016595, -0.012008, -0.012026, 0.036182, 1756e-6, 0.017921, -0, -3726e-6, 0.057055, 0.075166, 0.042236, 0.019585, -0.033961, 0.031402, -0.046679, -0.024065, 0.095275, -0.025657, -7449e-6, 0.02645, -0.068149, 0.057246, -0.030347, 0.025119, -0.051593, -0.018231, 0.074431, 0.025042, 0.041597, -0.068957, 0.053691, 0.114658, 0.052031, -0.011683, -0.053284, -0.014647, -348e-6, -0.047916, -0.012494, -0.029503, -0.063356, -934e-5, 0.023811, 0.070161, 9065e-6, -0.013438, -0.08371, 0.03976, 3717e-6, -0.06143, 0.011024, 0.034923, 0.074841, -0.078253, 0.075583, -0.099467, -0.021035, 0.031164, 0.050478, 0.040432, -0.080587, 0.025723, -0.033508, 0.018159, 0.050579, -0.06037, -0.033205, 4755e-6, -0.052926, -0.025845, 0.018374, -4346e-6, -0.03559, 0.011767, -0.011414, -0.125719, 0.038514, 0.051124, 0.069008, -0.015001, -0.061625, 0.062973, -0.067971, -0.071943, -0.020063, 0.018023, -8429e-6, -0.02391, 0.06376, 0.075836, 0.063692, 0.036226, 2423e-6, -0.012509, 0.109564, 0.021036, 0.02948, -0.059277, 0.01145, -0.082244, 0.05629, 0.015731, -0, -0.103531, 1861e-6, 0.01781, -0.036761, 0.044794, 0.054737, 0.082738, 0.130013, 0.013382, 0.088058, 0.083813, 0.055207, -0.116237, -0.011257, 4223e-6, -0.05385, -4549e-6, 0.013901, -0.031821, -0.039662, -0.082183, 0.027529, -0.021048, 0.074416, -0.013113, -0.102264, 8101e-6, 0.071966, 0.011139, -0.058671, 7962e-6, -0.043302, 0.070593, -1162e-6, -0.063857, 0.084633, 0.022543, 0.031713, -0.036442, 0.046021, 3134e-6, 0.034636, -0.030223, 0.036736, 0.012025, 0.012226, -0.022447, 0.018082, -3682e-6, -0.080533, -0.039335, -0.082823, -0.05142, -0.017032, 657e-6, 0.012916, -5871e-6, -0.036762, 0.07996, 0.010178, 0.103885, -0.067465, 9337e-6, -0.03209] },
|
|
5140
5319
|
{ name: "init_semantic", category: "search", tier: 2, descriptionHash: "33cdfeef485b49c6", embedding: [-0.025452, -0.048845, -0.011618, 0.023209, -0.024364, 0.03137, -0.053247, -0.042608, -0.051363, -0.036246, 0.011666, -0.082152, 0.056721, -3851e-6, 0.042404, 0.11714, 0.091872, -2772e-6, 0.010569, -0.027861, 0.058213, 0.036962, 0.042226, -0.037348, -0.043087, -6366e-6, -0.083984, -0.041254, 0.058968, -0.014554, 0.081354, 0.118492, -0.024363, 0.128628, -0.022981, 0.039297, -0.043987, -0.04519, -359e-6, -0.093715, -0.035612, 0.024908, -0.043093, 0.013066, 0.041861, 4982e-6, -0.101195, -0.062399, -0.03433, 0.026001, -0.119525, -2e-5, -0.046593, -6613e-6, 0.058065, 0.051141, -0.044697, 0.044936, -0.01502, -0.096312, 0.01898, -0.077467, 0.033712, -7687e-6, -0.021349, -0.025106, 0.045974, -0.023106, 0.073984, -0.050748, 0.052893, -0.014656, -0.045655, -0.015265, 3907e-6, 0.066162, 5096e-6, 0.011062, -0.029671, -0.135103, -0.064705, -0.03225, 0.04815, 0.03963, 0.057509, -0.052253, 0.039816, -0.093817, -8e-6, 0.031132, 0.084445, -0.099612, -0.02881, 8035e-6, 0.045018, -0.016475, 0.027816, 0.015622, 0.091962, 9961e-6, -0.014911, 0.056744, 0.024435, 0.026216, -0.053843, -0.019819, -0.014845, -0.010925, 0.046932, -0.103588, 33e-6, 0.014263, 0.087409, -0.035952, 1046e-6, -515e-5, 0.025704, -0.072284, 0.118985, 0.060917, 0.031497, 0.072897, -0.043803, -0.042411, -0.109211, 0.03381, -0.042281, 0, 0.080843, -0.013474, 8398e-6, 0.057869, -0.011194, 0.037514, 0.039225, 0.088839, -0.11312, -0.059102, -0.070631, 0.031955, -0.019724, 0.075456, 0.020453, -0.050863, -0.068314, -681e-6, -7973e-6, -7078e-6, 0.050153, 0.029361, -0.046185, -0.036473, 0.015387, 0.028065, 0.056587, -0.094002, -0.010984, 0.019087, -0.069289, -0.027765, -0.059082, 0.025227, 0.011601, -5e-4, -0.029371, 0.048577, -0.090619, -0.123844, -0.027863, 0.028224, 535e-6, -0.129364, -0.057459, 6837e-6, -0.042504, 0.018358, 0.066213, -0.016728, 0.046329, 0.059504, -0.014251, 5446e-6, 0.092261, 0.033873, 0.043768, 0.044972, 0.018907, 0.010377, 1453e-6, -0.012784, 4795e-6, 0.076529, -0.031376, 0.061178, 0.041996, -0.01385, 0.089266, 0.025233, 0.057706, 0.017261, 0.029684, -0.062645, -8791e-6, -0.110273, -0.03159, -0.104761, -0.041266, 0.033456, -0.053093, -0.028247, 5277e-6, -0.010504, 0.01649, -0.016958, 0.021029, -0.144161, 0.042318, -0.017862, 0.014535, -0.064415, -0.031891, 5534e-6, -3548e-6, -0, 0.028299, -0.048146, 0.035547, 0.046838, -0.055222, -0.033674, 0.047132, 0.05698, -6422e-6, 0.070455, 0.040918, -0.017008, 0.031049, -0.010847, -0.041375, 0.059624, -0.037186, -0.015125, 0.03265, 0.11463, -0.020689, 0.058846, -0.086132, 0.109765, 0.038341, 0.074075, 0.031486, -0.030692, -0.020264, -0.093453, 0.030645, -0.08451, -0.111201, -0.031115, -0.076444, 318e-5, 1952e-6, -0.02752, -0.11334, 0.044092, 1005e-6, 0.073434, -0.082935, 0.044757, 0.030054, -0.025717, -0.081733, 0.034689, 0.023261, -0.057735, 0.024434, -8957e-6, 0.040186, -0.026614, -6759e-6, -0.082044, 0.022979, 0.038621, -0.129556, 0.026753, 0.041397, 1654e-6, 0.037205, -0.011891, -1465e-6, -99e-5, -0.026155, 0.039496, -0.046137, -7432e-6, -0.039458, 0.021466, 0.039666, 0.04149, 0.067237, 0.015889, 928e-6, -0.051473, 4571e-6, -0.054656, -0.064496, -0.016879, 0.064129, 0.088521, -0.034872, -0.010411, -6583e-6, 0.064146, -0.029104, 0.015446, 9899e-6, -0.030396, -0.020139, 0.080347, 0.015771, -0, -0.073344, -4747e-6, -0.049687, 0.017255, -3607e-6, -0.029109, 0.037577, 0.063634, -0.052339, 8628e-6, 0.025821, -0.011665, -0.06861, 0.046917, 0.015224, 3369e-6, 0.018254, -4173e-6, -0.026802, -0.04863, -0.010136, 0.065597, 3896e-6, 0.037951, 0.018301, 592e-6, 0.039073, 0.0473, 0.117625, 0.036979, -0.052532, 0.046389, -0.058179, -0.017938, 0.024611, 0.067018, 0.068666, -0.018001, -0.027935, 0.039049, 0.061025, -0.026152, -0.029787, -0.030583, 0.072493, 0.033637, -0.10382, -0.027076, 0.058482, 0.012085, -0.025303, -0.021042, -0.052113, 0.075843, 3589e-6, 0.047474, 5525e-6, 3801e-6, 0.10101, -0.05594, 0.057585, -0.06871, 0.072151, 0.013319] },
|
|
5141
5320
|
{ name: "insights", category: "temporal", tier: 2, descriptionHash: "855ab4926f7a6801", embedding: [-0.063295, -8142e-6, -0.038172, 0.03532, 0.040686, -0.016714, -0.056257, -3287e-6, 0.015134, -0.013824, 3625e-6, 0.044585, -7921e-6, 0.031275, -0.031442, 0.044995, -0.051089, -0.029658, -4379e-6, -0.087946, 5864e-6, 0.029223, 0.050495, -7364e-6, -0.010813, 0.04681, -0.086689, -0.042294, -0.017436, -0.029906, 0.015441, 0.105912, 0.05493, 6903e-6, 0.039625, 0.112582, -0.013149, 0.016343, 0.038377, -0.038804, -0.0403, -0.05024, -0.017444, 0.014813, 0.011559, -0.086677, -0.09845, -0.070249, -0.098581, 0.075896, -0.097783, -0.061588, -0.042206, 0.029136, 8246e-6, 0.081454, -0.020084, 0.040595, -0.056448, -0.059379, 0.112695, -0.025232, -0.014015, -9531e-6, -0.012755, 0.080807, 0.019995, 0.031223, 0.061335, -0.051002, 0.010578, -0.018452, -0.06323, -0.018173, 0.029556, 0.022824, -6672e-6, -0.05807, -1342e-6, -0.169312, -0.022267, -0.035658, -0.022863, 0.026652, 0.041582, -0.056788, 0.015566, -0.053985, 0.010757, 0.019046, 0.051278, -0.058026, 0.074028, -0.017678, 0.04572, 945e-6, -83e-4, -0.04841, 0.024786, 0.069194, -8031e-6, 0.079203, -0.020793, 9091e-6, 0.067237, -3414e-6, 6468e-6, 0.011636, -0.013383, 0.027493, -0.018058, 5521e-6, 0.042896, -0.047974, 0.077419, -0.021558, -0.070058, 0.071013, 0.017298, 0.117801, 0.11145, 7351e-6, -1886e-6, -0.043286, -0.037469, 1474e-6, -0.024378, 0, 0.017595, -0.040932, -0.066118, 0.042636, -0.014735, -0.049733, 4119e-6, -0.031842, -0.068389, -0.018239, 0.017547, 0.071217, -0.052611, 0.029461, 0.019291, -6557e-6, -0.046121, 0.124387, 0.057962, -0.016263, 0.031911, 2563e-6, 0.017743, -0.06372, 0.131525, -0.017698, 0.029113, -6087e-6, -0.081771, -8083e-6, 3806e-6, 5042e-6, 11e-4, 8354e-6, 0.036325, 6888e-6, 0.035691, -0.060973, 0.050427, -0.058276, -0.016176, 0.01707, -0.013841, -0.07685, 0.013712, -134e-6, 0.040153, 7312e-6, 0.038825, 0.014188, -0.033648, 0.034613, -0.021067, -0.041681, -0.040003, -0.026887, 0.021195, -0.016114, -8157e-6, -0.019636, 0.111264, 0.02374, -0.047121, -0.032056, -0.06558, 0.078405, -0.036886, 9887e-6, 0.068641, 0.05437, -786e-5, 0.027193, -732e-5, -9859e-6, -0.017397, -0.086631, -0.01224, -0.015872, 0.016682, -0.031038, -0.033485, -0.075074, -0.075209, 0.040362, -3e-5, 0.015816, 0.048215, -0.056939, -0.033508, -5876e-6, -0.096742, -7803e-6, -124e-5, 5309e-6, 0.014088, -0, 0.019582, -0.037564, -0.060406, 0.081961, 0.054123, 0.024889, -0.090945, 0.035492, 0.015563, 0.062908, -2693e-6, 882e-5, -0.036524, -0.045377, 0.028222, -9982e-6, -7162e-6, -0.095401, -0.018318, 0.108199, 0.046605, -0.031605, -0.120001, 0.049391, 0.051344, 0.052646, 9646e-6, -0.027193, 0.019156, -0.027546, -0.016975, -0.058494, -0.033116, 7577e-6, -0.027853, -0.018491, 0.100959, -0.180773, -0.093329, 0.022668, 0.093884, 0.038685, -0.037316, -2991e-6, -0.031772, 0.05988, -0.0272, 0.086657, -0.087114, -0.092333, 0.105338, 2276e-6, -0.013072, -0.056543, -0.01029, 0.060305, 0.022462, -0.033421, -0.066583, 0.045748, 0.024946, 0.059303, -0.067325, -0.015552, 0.020745, -0.023447, 2772e-6, -351e-6, -0.151103, 0.025064, 0.079183, -484e-5, -0.027406, -0.090547, 0.038329, -0.026243, -0.081134, -0.067797, -0.014319, -0.086898, -0.045973, -2054e-6, 0.049931, 0.059267, 1532e-6, 0.085472, -0.033852, 0.050924, -2367e-6, 0.028192, -0.045562, -0.08446, -0.062257, 0.012305, -0.026982, -0, -0.027423, 0.090977, 2768e-6, 0.011862, 0.075439, -0.037147, -0.01372, 0.094814, 0.054414, 0.019731, 0.09544, -0.043872, -0.073898, -0.035133, 0.031111, -0.023116, -0.019305, 0.033497, -0.040037, -0.016253, 0.051564, 0.077346, 4027e-6, -0.103212, -0.016498, -26e-5, 7975e-6, 0.128707, 0.038103, -6535e-6, 0.019882, 0.031399, 0.058017, -0.075234, 0.03305, 0.033512, 0.06787, -0.037298, -7957e-6, 0.068908, -0.025023, 0.066633, -0.050597, 0.074426, -716e-5, -0.01675, -0.06884, -0.03286, 0.027107, -0.031027, -0.014358, -0.03356, -0.024072, 0.067223, 0.065775, 0.068417, 0.079966, -0.010847, 171e-6, 0.026273, 0.169434, -0.050325, 0.011726, 0.013154] },
|
|
5142
5321
|
{ name: "link", category: "wikilinks", tier: 2, descriptionHash: "f5991633e71ac0e6", embedding: [-0.105211, -0.051175, -0.014955, 0.070203, 0.094131, 0.013247, 2462e-6, 0.061895, 3523e-6, 0.038099, 262e-6, 9244e-6, 0.018201, 0.036586, -0.026886, 0.121965, -0.023067, 0.038931, 0.040324, -0.045367, 0.055688, 0.048809, 0.067382, -0.012725, 0.025349, -0.139325, -0.134768, 0.034046, -0.023531, -0.077858, 0.014222, 0.076492, -0.089917, -0.048617, -0.011276, 0.050469, -0.028663, -0.026588, 0.040878, -0.01898, 0.025442, 5891e-6, -0.039509, 0.035192, -0.039439, 0.049857, -0.018329, -0.065998, -0.113633, 0.117079, -0.137705, -0.029588, 0.032657, -0.011592, 0.027898, 0.018984, -0.129855, -5585e-6, 0.01063, -0.074039, 0.067858, -0.032616, -0.077555, -0.041351, 2928e-6, 0.02392, -0.013358, 0.078737, -0.034541, -0.025256, 7842e-6, -0.054307, -247e-5, 0.017511, 0.030964, -8747e-6, -0.047385, 0.016456, -0.057913, -0.093447, -4794e-6, 0.011713, 0.049448, -1893e-6, 0.055055, 0.060197, 8172e-6, -0.017526, -0.014227, 0.043367, 0.03618, -0.086497, 0.112268, -0.031951, -0.022605, 0.03589, -0.011521, -0.04353, -3027e-6, 0.072896, 0.022479, 0.038038, 0.049187, -0.029073, -0.031375, -0.032972, 0.051462, 0.115384, 7451e-6, 0.021359, -0.059937, -9478e-6, -0.085658, -0.084651, -0.014569, -0.040287, -4465e-6, -1215e-6, 0.089086, -8498e-6, 0.065111, 0.031575, 0.042459, 0.013246, -0.063517, -0.013246, -0.031999, 0, 0.115188, 0.101182, -0.034179, -0.015912, 0.017986, -4269e-6, -0.078143, -0.049314, -0.097431, -0.026028, -0.052334, 0.080905, -0.011248, 0.012377, -0.024596, 0.022708, 3039e-6, 0.083423, -0.046848, -0.062428, 0.011718, 0.084491, -0.01987, 156e-6, 0.0555, 3028e-6, -134e-5, -0.013151, -0.040286, 0.017924, 0.0278, 114e-6, 0.016917, 0.049588, 0.070486, 0.019654, -0.057675, -0.066234, -0.018768, -0.065281, 0.011376, -4547e-6, -0.052151, -0.011786, -0.017052, 0.029821, 0.026028, -0.027522, 0.028279, -0.015119, 7861e-6, 0.014754, 0.020151, 0.012127, 0.019077, -4529e-6, -0.098239, 0.052583, 0.02076, 0.010897, 0.045988, -3608e-6, -0.022366, -0.074248, -0.066018, 0.055597, -0.059601, 0.034221, 0.044492, -0.038879, -719e-5, 0.015953, 0.032836, 0.023192, -0.038382, -0.055607, -0.115347, -0.136553, -0.028439, 9282e-6, -0.080226, -0.169079, -0.055861, 0.036114, 0.067252, -0.023551, 0.035797, -0.058662, -0.024751, -0.024102, 0.010495, 0.020854, -0.019832, 0.056418, -5782e-6, -0, 0.075746, -2897e-6, 0.030092, 0.034463, -9709e-6, 0.025326, 2244e-6, 0.013144, 0.078235, -355e-6, 0.06344, -0.06993, -0.063164, 0.017734, 0.012112, -7685e-6, 2749e-6, -0.044044, 4284e-6, 0.085672, 0.043681, 0.015488, -0.017667, 0.06259, 0.016398, 0.01253, 0.126432, -0.022014, 0.039742, -9333e-6, -0.02521, 0.01218, -0.063496, -0.01253, 0.017962, 0.029351, -0.019498, -4882e-6, -0.02802, -7356e-6, 0.149432, -0.018531, -0.035931, 1085e-6, -0.019631, -924e-5, -0.079662, 0.01923, -0.070051, -0.064508, 0.048826, 0.010655, -0.017871, -0.081734, -0.034362, 0.059971, 0.017234, 0.025876, -0.086982, -101e-5, -6568e-6, 0.044154, -0.058022, 0.061645, 0.070019, -0.094105, -0.021322, 0.011796, -0.040228, -0.015751, 0.025438, -774e-5, 8335e-6, -0.099734, 0.071584, -0.053004, 0.026579, -0.034326, 0.037723, -0.074485, -0.024437, 0.031958, 0.077181, 6378e-6, 0.036474, -1893e-6, -0.037769, 0.083712, -0.023617, -3828e-6, 0.040877, -0.087152, 0.03894, 0.137603, -0.084336, -0, 5716e-6, 0.083963, -698e-5, 0.021144, 0.016048, 0.026998, -3916e-6, 0.050464, -0.034483, 0.031494, 0.030571, 0.021726, -0.12123, -0.045023, 0.085973, -0.071658, -0.031606, 0.061912, -0.02822, -0.031827, -0.047078, -9682e-6, 0.01124, 0.025411, 9235e-6, 4972e-6, -0.035519, 0.042622, 0.015422, -0.026236, -8137e-6, 0.013488, -0.066525, -0.049611, -729e-5, 0.068035, -7959e-6, -0.05708, 476e-5, -0.0244, 0.066389, 0.024302, -0.026597, 0.062248, 0.036823, 0.040825, 0.02206, -0.097542, 0.049637, -0.097868, 0.015866, -0.040273, 0.046721, 0.014174, -0.013605, 0.095691, 0.04449, 0.016153, -0.036602, -0.0348, 0.150135, -0.026655, 5699e-6, 0.041633] },
|
|
@@ -5157,17 +5336,17 @@ var init_tool_embeddings_generated = __esm({
|
|
|
5157
5336
|
});
|
|
5158
5337
|
|
|
5159
5338
|
// src/core/write/path-security.ts
|
|
5160
|
-
import
|
|
5161
|
-
import
|
|
5339
|
+
import fs17 from "fs/promises";
|
|
5340
|
+
import path21 from "path";
|
|
5162
5341
|
function isSensitivePath(filePath) {
|
|
5163
5342
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
5164
5343
|
return SENSITIVE_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath));
|
|
5165
5344
|
}
|
|
5166
5345
|
function isWithinDirectory(child, parent, allowEqual = false) {
|
|
5167
|
-
const rel =
|
|
5346
|
+
const rel = path21.relative(path21.resolve(parent), path21.resolve(child));
|
|
5168
5347
|
if (rel === "") return allowEqual;
|
|
5169
|
-
const firstSeg = rel.split(
|
|
5170
|
-
return firstSeg !== ".." && !
|
|
5348
|
+
const firstSeg = rel.split(path21.sep)[0];
|
|
5349
|
+
return firstSeg !== ".." && !path21.isAbsolute(rel);
|
|
5171
5350
|
}
|
|
5172
5351
|
function validatePath(vaultPath2, notePath) {
|
|
5173
5352
|
if (notePath.startsWith("/")) {
|
|
@@ -5179,11 +5358,11 @@ function validatePath(vaultPath2, notePath) {
|
|
|
5179
5358
|
if (notePath.startsWith("\\")) {
|
|
5180
5359
|
return false;
|
|
5181
5360
|
}
|
|
5182
|
-
return isWithinDirectory(
|
|
5361
|
+
return isWithinDirectory(path21.resolve(vaultPath2, notePath), vaultPath2);
|
|
5183
5362
|
}
|
|
5184
5363
|
function sanitizeNotePath(notePath) {
|
|
5185
|
-
const dir =
|
|
5186
|
-
let filename =
|
|
5364
|
+
const dir = path21.dirname(notePath);
|
|
5365
|
+
let filename = path21.basename(notePath);
|
|
5187
5366
|
const ext = filename.endsWith(".md") ? ".md" : "";
|
|
5188
5367
|
let stem2 = ext ? filename.slice(0, -ext.length) : filename;
|
|
5189
5368
|
stem2 = stem2.replace(/\s+/g, "-");
|
|
@@ -5192,7 +5371,7 @@ function sanitizeNotePath(notePath) {
|
|
|
5192
5371
|
stem2 = stem2.replace(/-{2,}/g, "-");
|
|
5193
5372
|
stem2 = stem2.replace(/^-+|-+$/g, "");
|
|
5194
5373
|
filename = stem2 + (ext || ".md");
|
|
5195
|
-
return dir === "." ? filename :
|
|
5374
|
+
return dir === "." ? filename : path21.join(dir, filename).replace(/\\/g, "/");
|
|
5196
5375
|
}
|
|
5197
5376
|
async function validatePathSecure(vaultPath2, notePath) {
|
|
5198
5377
|
if (notePath.startsWith("/")) {
|
|
@@ -5213,14 +5392,14 @@ async function validatePathSecure(vaultPath2, notePath) {
|
|
|
5213
5392
|
reason: "Absolute paths not allowed"
|
|
5214
5393
|
};
|
|
5215
5394
|
}
|
|
5216
|
-
const firstSeg =
|
|
5395
|
+
const firstSeg = path21.normalize(notePath).split(path21.sep).filter(Boolean)[0];
|
|
5217
5396
|
if (firstSeg === "..") {
|
|
5218
5397
|
return {
|
|
5219
5398
|
valid: false,
|
|
5220
5399
|
reason: "Path traversal not allowed"
|
|
5221
5400
|
};
|
|
5222
5401
|
}
|
|
5223
|
-
if (!isWithinDirectory(
|
|
5402
|
+
if (!isWithinDirectory(path21.resolve(vaultPath2, notePath), vaultPath2)) {
|
|
5224
5403
|
return {
|
|
5225
5404
|
valid: false,
|
|
5226
5405
|
reason: "Path traversal not allowed"
|
|
@@ -5233,18 +5412,18 @@ async function validatePathSecure(vaultPath2, notePath) {
|
|
|
5233
5412
|
};
|
|
5234
5413
|
}
|
|
5235
5414
|
try {
|
|
5236
|
-
const fullPath =
|
|
5415
|
+
const fullPath = path21.join(vaultPath2, notePath);
|
|
5237
5416
|
try {
|
|
5238
|
-
await
|
|
5239
|
-
const realPath = await
|
|
5240
|
-
const realVaultPath = await
|
|
5417
|
+
await fs17.access(fullPath);
|
|
5418
|
+
const realPath = await fs17.realpath(fullPath);
|
|
5419
|
+
const realVaultPath = await fs17.realpath(vaultPath2);
|
|
5241
5420
|
if (!isWithinDirectory(realPath, realVaultPath)) {
|
|
5242
5421
|
return {
|
|
5243
5422
|
valid: false,
|
|
5244
5423
|
reason: "Symlink target is outside vault"
|
|
5245
5424
|
};
|
|
5246
5425
|
}
|
|
5247
|
-
const relativePath =
|
|
5426
|
+
const relativePath = path21.relative(realVaultPath, realPath);
|
|
5248
5427
|
if (isSensitivePath(relativePath)) {
|
|
5249
5428
|
return {
|
|
5250
5429
|
valid: false,
|
|
@@ -5252,11 +5431,11 @@ async function validatePathSecure(vaultPath2, notePath) {
|
|
|
5252
5431
|
};
|
|
5253
5432
|
}
|
|
5254
5433
|
} catch {
|
|
5255
|
-
const parentDir =
|
|
5434
|
+
const parentDir = path21.dirname(fullPath);
|
|
5256
5435
|
try {
|
|
5257
|
-
await
|
|
5258
|
-
const realParentPath = await
|
|
5259
|
-
const realVaultPath = await
|
|
5436
|
+
await fs17.access(parentDir);
|
|
5437
|
+
const realParentPath = await fs17.realpath(parentDir);
|
|
5438
|
+
const realVaultPath = await fs17.realpath(vaultPath2);
|
|
5260
5439
|
if (!isWithinDirectory(realParentPath, realVaultPath, true)) {
|
|
5261
5440
|
return {
|
|
5262
5441
|
valid: false,
|
|
@@ -6053,8 +6232,8 @@ var init_content_mutation = __esm({
|
|
|
6053
6232
|
});
|
|
6054
6233
|
|
|
6055
6234
|
// src/core/write/file-io.ts
|
|
6056
|
-
import
|
|
6057
|
-
import
|
|
6235
|
+
import fs18 from "fs/promises";
|
|
6236
|
+
import path22 from "path";
|
|
6058
6237
|
import matter2 from "gray-matter";
|
|
6059
6238
|
import { createHash as createHash2 } from "node:crypto";
|
|
6060
6239
|
function computeContentHash(rawContent) {
|
|
@@ -6065,10 +6244,10 @@ async function readVaultFile(vaultPath2, notePath) {
|
|
|
6065
6244
|
if (!validation.valid) {
|
|
6066
6245
|
throw new Error(`Invalid path: ${validation.reason}`);
|
|
6067
6246
|
}
|
|
6068
|
-
const fullPath =
|
|
6247
|
+
const fullPath = path22.join(vaultPath2, notePath);
|
|
6069
6248
|
const [rawContent, stat4] = await Promise.all([
|
|
6070
|
-
|
|
6071
|
-
|
|
6249
|
+
fs18.readFile(fullPath, "utf-8"),
|
|
6250
|
+
fs18.stat(fullPath)
|
|
6072
6251
|
]);
|
|
6073
6252
|
const contentHash2 = computeContentHash(rawContent);
|
|
6074
6253
|
const lineEnding = detectLineEnding(rawContent);
|
|
@@ -6120,9 +6299,9 @@ async function writeVaultFile(vaultPath2, notePath, content, frontmatter, lineEn
|
|
|
6120
6299
|
if (!validation.valid) {
|
|
6121
6300
|
throw new Error(`Invalid path: ${validation.reason}`);
|
|
6122
6301
|
}
|
|
6123
|
-
const fullPath =
|
|
6302
|
+
const fullPath = path22.join(vaultPath2, notePath);
|
|
6124
6303
|
if (expectedHash) {
|
|
6125
|
-
const currentRaw = await
|
|
6304
|
+
const currentRaw = await fs18.readFile(fullPath, "utf-8");
|
|
6126
6305
|
const currentHash = computeContentHash(currentRaw);
|
|
6127
6306
|
if (currentHash !== expectedHash) {
|
|
6128
6307
|
throw new WriteConflictError(notePath);
|
|
@@ -6131,7 +6310,7 @@ async function writeVaultFile(vaultPath2, notePath, content, frontmatter, lineEn
|
|
|
6131
6310
|
let output = matter2.stringify(content, frontmatter);
|
|
6132
6311
|
output = normalizeTrailingNewline(output);
|
|
6133
6312
|
output = convertLineEndings(output, lineEnding);
|
|
6134
|
-
await
|
|
6313
|
+
await fs18.writeFile(fullPath, output, "utf-8");
|
|
6135
6314
|
}
|
|
6136
6315
|
var WriteConflictError;
|
|
6137
6316
|
var init_file_io = __esm({
|
|
@@ -6188,8 +6367,8 @@ function createContext(variables = {}) {
|
|
|
6188
6367
|
steps: {}
|
|
6189
6368
|
};
|
|
6190
6369
|
}
|
|
6191
|
-
function resolvePath(obj,
|
|
6192
|
-
const parts =
|
|
6370
|
+
function resolvePath(obj, path40) {
|
|
6371
|
+
const parts = path40.split(".");
|
|
6193
6372
|
let current = obj;
|
|
6194
6373
|
for (const part of parts) {
|
|
6195
6374
|
if (current === void 0 || current === null) {
|
|
@@ -6646,8 +6825,8 @@ __export(conditions_exports, {
|
|
|
6646
6825
|
evaluateCondition: () => evaluateCondition,
|
|
6647
6826
|
shouldStepExecute: () => shouldStepExecute
|
|
6648
6827
|
});
|
|
6649
|
-
import
|
|
6650
|
-
import
|
|
6828
|
+
import fs26 from "fs/promises";
|
|
6829
|
+
import path30 from "path";
|
|
6651
6830
|
async function evaluateCondition(condition, vaultPath2, context) {
|
|
6652
6831
|
const interpolatedPath = condition.path ? interpolate(condition.path, context) : void 0;
|
|
6653
6832
|
const interpolatedSection = condition.section ? interpolate(condition.section, context) : void 0;
|
|
@@ -6700,9 +6879,9 @@ async function evaluateCondition(condition, vaultPath2, context) {
|
|
|
6700
6879
|
}
|
|
6701
6880
|
}
|
|
6702
6881
|
async function evaluateFileExists(vaultPath2, notePath, expectExists) {
|
|
6703
|
-
const fullPath =
|
|
6882
|
+
const fullPath = path30.join(vaultPath2, notePath);
|
|
6704
6883
|
try {
|
|
6705
|
-
await
|
|
6884
|
+
await fs26.access(fullPath);
|
|
6706
6885
|
return {
|
|
6707
6886
|
met: expectExists,
|
|
6708
6887
|
reason: expectExists ? `File exists: ${notePath}` : `File exists (expected not to): ${notePath}`
|
|
@@ -6715,9 +6894,9 @@ async function evaluateFileExists(vaultPath2, notePath, expectExists) {
|
|
|
6715
6894
|
}
|
|
6716
6895
|
}
|
|
6717
6896
|
async function evaluateSectionExists(vaultPath2, notePath, sectionName, expectExists) {
|
|
6718
|
-
const fullPath =
|
|
6897
|
+
const fullPath = path30.join(vaultPath2, notePath);
|
|
6719
6898
|
try {
|
|
6720
|
-
await
|
|
6899
|
+
await fs26.access(fullPath);
|
|
6721
6900
|
} catch {
|
|
6722
6901
|
return {
|
|
6723
6902
|
met: !expectExists,
|
|
@@ -6746,9 +6925,9 @@ async function evaluateSectionExists(vaultPath2, notePath, sectionName, expectEx
|
|
|
6746
6925
|
}
|
|
6747
6926
|
}
|
|
6748
6927
|
async function evaluateFrontmatterExists(vaultPath2, notePath, fieldName, expectExists) {
|
|
6749
|
-
const fullPath =
|
|
6928
|
+
const fullPath = path30.join(vaultPath2, notePath);
|
|
6750
6929
|
try {
|
|
6751
|
-
await
|
|
6930
|
+
await fs26.access(fullPath);
|
|
6752
6931
|
} catch {
|
|
6753
6932
|
return {
|
|
6754
6933
|
met: !expectExists,
|
|
@@ -6777,9 +6956,9 @@ async function evaluateFrontmatterExists(vaultPath2, notePath, fieldName, expect
|
|
|
6777
6956
|
}
|
|
6778
6957
|
}
|
|
6779
6958
|
async function evaluateFrontmatterEquals(vaultPath2, notePath, fieldName, expectedValue) {
|
|
6780
|
-
const fullPath =
|
|
6959
|
+
const fullPath = path30.join(vaultPath2, notePath);
|
|
6781
6960
|
try {
|
|
6782
|
-
await
|
|
6961
|
+
await fs26.access(fullPath);
|
|
6783
6962
|
} catch {
|
|
6784
6963
|
return {
|
|
6785
6964
|
met: false,
|
|
@@ -6921,10 +7100,10 @@ var init_taskHelpers = __esm({
|
|
|
6921
7100
|
});
|
|
6922
7101
|
|
|
6923
7102
|
// src/index.ts
|
|
6924
|
-
import * as
|
|
7103
|
+
import * as path39 from "path";
|
|
6925
7104
|
import { readFileSync as readFileSync6, realpathSync, existsSync as existsSync4 } from "fs";
|
|
6926
7105
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
6927
|
-
import { dirname as dirname8, join as
|
|
7106
|
+
import { dirname as dirname8, join as join20 } from "path";
|
|
6928
7107
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
6929
7108
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6930
7109
|
import { performance } from "node:perf_hooks";
|
|
@@ -7216,8 +7395,8 @@ function updateIndexProgress(parsed, total) {
|
|
|
7216
7395
|
function normalizeTarget(target) {
|
|
7217
7396
|
return target.toLowerCase().replace(/\.md$/, "");
|
|
7218
7397
|
}
|
|
7219
|
-
function normalizeNotePath(
|
|
7220
|
-
return
|
|
7398
|
+
function normalizeNotePath(path40) {
|
|
7399
|
+
return path40.toLowerCase().replace(/\.md$/, "");
|
|
7221
7400
|
}
|
|
7222
7401
|
async function buildVaultIndex(vaultPath2, options = {}) {
|
|
7223
7402
|
const { timeoutMs = DEFAULT_TIMEOUT_MS, onProgress } = options;
|
|
@@ -7375,7 +7554,7 @@ function findSimilarEntity(index, target) {
|
|
|
7375
7554
|
}
|
|
7376
7555
|
const maxDist = normalizedLen <= 10 ? 1 : 2;
|
|
7377
7556
|
let bestMatch;
|
|
7378
|
-
for (const [entity,
|
|
7557
|
+
for (const [entity, path40] of index.entities) {
|
|
7379
7558
|
const lenDiff = Math.abs(entity.length - normalizedLen);
|
|
7380
7559
|
if (lenDiff > maxDist) {
|
|
7381
7560
|
continue;
|
|
@@ -7383,7 +7562,7 @@ function findSimilarEntity(index, target) {
|
|
|
7383
7562
|
const dist = levenshteinDistance(normalized, entity);
|
|
7384
7563
|
if (dist > 0 && dist <= maxDist) {
|
|
7385
7564
|
if (!bestMatch || dist < bestMatch.distance) {
|
|
7386
|
-
bestMatch = { path:
|
|
7565
|
+
bestMatch = { path: path40, entity, distance: dist };
|
|
7387
7566
|
if (dist === 1) {
|
|
7388
7567
|
return bestMatch;
|
|
7389
7568
|
}
|
|
@@ -7498,8 +7677,8 @@ function saveVaultIndexToCache(stateDb2, index) {
|
|
|
7498
7677
|
init_vault();
|
|
7499
7678
|
|
|
7500
7679
|
// src/core/read/config.ts
|
|
7501
|
-
import * as
|
|
7502
|
-
import * as
|
|
7680
|
+
import * as fs6 from "fs";
|
|
7681
|
+
import * as path5 from "path";
|
|
7503
7682
|
import {
|
|
7504
7683
|
loadFlywheelConfigFromDb,
|
|
7505
7684
|
saveFlywheelConfigToDb
|
|
@@ -7569,7 +7748,7 @@ var FOLDER_PATTERNS = {
|
|
|
7569
7748
|
function extractFolders(index) {
|
|
7570
7749
|
const folders = /* @__PURE__ */ new Set();
|
|
7571
7750
|
for (const notePath of index.notes.keys()) {
|
|
7572
|
-
const dir =
|
|
7751
|
+
const dir = path5.dirname(notePath);
|
|
7573
7752
|
if (dir && dir !== ".") {
|
|
7574
7753
|
const parts = dir.split(/[/\\]/);
|
|
7575
7754
|
for (let i = 1; i <= parts.length; i++) {
|
|
@@ -7586,7 +7765,7 @@ function extractFolders(index) {
|
|
|
7586
7765
|
function findMatchingFolder(folders, patterns) {
|
|
7587
7766
|
const lowerPatterns = patterns.map((p) => p.toLowerCase());
|
|
7588
7767
|
for (const folder of folders) {
|
|
7589
|
-
const folderName =
|
|
7768
|
+
const folderName = path5.basename(folder).toLowerCase();
|
|
7590
7769
|
if (lowerPatterns.includes(folderName)) {
|
|
7591
7770
|
return folder;
|
|
7592
7771
|
}
|
|
@@ -7599,7 +7778,7 @@ function inferConfig(index, vaultPath2) {
|
|
|
7599
7778
|
paths: {}
|
|
7600
7779
|
};
|
|
7601
7780
|
if (vaultPath2) {
|
|
7602
|
-
inferred.vault_name =
|
|
7781
|
+
inferred.vault_name = path5.basename(vaultPath2);
|
|
7603
7782
|
}
|
|
7604
7783
|
const folders = extractFolders(index);
|
|
7605
7784
|
const detectedPath = findMatchingFolder(folders, FOLDER_PATTERNS.daily_notes);
|
|
@@ -7637,9 +7816,9 @@ var TEMPLATE_PATTERNS = {
|
|
|
7637
7816
|
};
|
|
7638
7817
|
function scanTemplatesFolder(vaultPath2, templatesFolder) {
|
|
7639
7818
|
const templates = {};
|
|
7640
|
-
const absFolder =
|
|
7819
|
+
const absFolder = path5.join(vaultPath2, templatesFolder);
|
|
7641
7820
|
try {
|
|
7642
|
-
const files =
|
|
7821
|
+
const files = fs6.readdirSync(absFolder);
|
|
7643
7822
|
for (const file of files) {
|
|
7644
7823
|
for (const [type, pattern] of Object.entries(TEMPLATE_PATTERNS)) {
|
|
7645
7824
|
if (pattern.test(file) && !templates[type]) {
|
|
@@ -7677,19 +7856,19 @@ function saveConfig(stateDb2, inferred, existing) {
|
|
|
7677
7856
|
}
|
|
7678
7857
|
|
|
7679
7858
|
// src/core/read/vaultRoot.ts
|
|
7680
|
-
import * as
|
|
7681
|
-
import * as
|
|
7859
|
+
import * as fs7 from "fs";
|
|
7860
|
+
import * as path6 from "path";
|
|
7682
7861
|
var VAULT_MARKERS = [".obsidian", ".flywheel", ".claude"];
|
|
7683
7862
|
function findVaultRoot(startPath) {
|
|
7684
|
-
let current =
|
|
7863
|
+
let current = path6.resolve(startPath || process.cwd());
|
|
7685
7864
|
while (true) {
|
|
7686
7865
|
for (const marker of VAULT_MARKERS) {
|
|
7687
|
-
const markerPath =
|
|
7688
|
-
if (
|
|
7866
|
+
const markerPath = path6.join(current, marker);
|
|
7867
|
+
if (fs7.existsSync(markerPath) && fs7.statSync(markerPath).isDirectory()) {
|
|
7689
7868
|
return current;
|
|
7690
7869
|
}
|
|
7691
7870
|
}
|
|
7692
|
-
const parent =
|
|
7871
|
+
const parent = path6.dirname(current);
|
|
7693
7872
|
if (parent === current) {
|
|
7694
7873
|
return startPath || process.cwd();
|
|
7695
7874
|
}
|
|
@@ -7701,10 +7880,10 @@ function findVaultRoot(startPath) {
|
|
|
7701
7880
|
import chokidar from "chokidar";
|
|
7702
7881
|
|
|
7703
7882
|
// src/core/read/watch/eventQueue.ts
|
|
7704
|
-
import * as
|
|
7883
|
+
import * as path8 from "path";
|
|
7705
7884
|
|
|
7706
7885
|
// src/core/read/watch/pathFilter.ts
|
|
7707
|
-
import
|
|
7886
|
+
import path7 from "path";
|
|
7708
7887
|
var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
7709
7888
|
".git",
|
|
7710
7889
|
".obsidian",
|
|
@@ -7803,7 +7982,7 @@ function isIgnoredDirectory(segment) {
|
|
|
7803
7982
|
return IGNORED_DIRECTORIES.has(segment);
|
|
7804
7983
|
}
|
|
7805
7984
|
function hasIgnoredExtension(filePath) {
|
|
7806
|
-
const ext =
|
|
7985
|
+
const ext = path7.extname(filePath).toLowerCase();
|
|
7807
7986
|
return IGNORED_EXTENSIONS.has(ext);
|
|
7808
7987
|
}
|
|
7809
7988
|
function matchesIgnoredPattern(filename) {
|
|
@@ -7820,7 +7999,7 @@ function normalizePath(filePath, caseInsensitive) {
|
|
|
7820
7999
|
function getRelativePath(vaultPath2, filePath) {
|
|
7821
8000
|
const normalizedVault = normalizePath(vaultPath2);
|
|
7822
8001
|
const normalizedFile = normalizePath(filePath);
|
|
7823
|
-
const relative =
|
|
8002
|
+
const relative = path7.posix.relative(normalizedVault, normalizedFile);
|
|
7824
8003
|
return relative;
|
|
7825
8004
|
}
|
|
7826
8005
|
function shouldWatch(filePath, vaultPath2) {
|
|
@@ -7894,7 +8073,7 @@ function coalesceEvents(events) {
|
|
|
7894
8073
|
var RENAME_PROXIMITY_MS = 5e3;
|
|
7895
8074
|
var COMMON_STEMS = /* @__PURE__ */ new Set(["readme", "index", "todo", "changelog", "license", "notes"]);
|
|
7896
8075
|
function fileStem(p) {
|
|
7897
|
-
return
|
|
8076
|
+
return path8.basename(p).replace(/\.[^.]+$/, "");
|
|
7898
8077
|
}
|
|
7899
8078
|
function detectRenames(events) {
|
|
7900
8079
|
const deletes = events.filter((e) => e.type === "delete");
|
|
@@ -7905,13 +8084,13 @@ function detectRenames(events) {
|
|
|
7905
8084
|
const renames = [];
|
|
7906
8085
|
for (const del of deletes) {
|
|
7907
8086
|
const stem2 = fileStem(del.path);
|
|
7908
|
-
const delDir =
|
|
8087
|
+
const delDir = path8.dirname(del.path);
|
|
7909
8088
|
const delTimestamp = del.originalEvents.length > 0 ? Math.max(...del.originalEvents.map((e) => e.timestamp)) : 0;
|
|
7910
8089
|
const allCandidates = upserts.filter(
|
|
7911
8090
|
(u) => !usedUpserts.has(u.path) && fileStem(u.path) === stem2
|
|
7912
8091
|
);
|
|
7913
8092
|
if (allCandidates.length === 0) continue;
|
|
7914
|
-
const sameDirCandidates = allCandidates.filter((c) =>
|
|
8093
|
+
const sameDirCandidates = allCandidates.filter((c) => path8.dirname(c.path) === delDir);
|
|
7915
8094
|
const candidates = sameDirCandidates.length > 0 ? sameDirCandidates : COMMON_STEMS.has(stem2.toLowerCase()) ? [] : allCandidates;
|
|
7916
8095
|
if (candidates.length === 0) continue;
|
|
7917
8096
|
let bestCandidate = null;
|
|
@@ -7955,30 +8134,30 @@ var EventQueue = class {
|
|
|
7955
8134
|
* Add a new event to the queue
|
|
7956
8135
|
*/
|
|
7957
8136
|
push(type, rawPath) {
|
|
7958
|
-
const
|
|
8137
|
+
const path40 = normalizePath(rawPath);
|
|
7959
8138
|
const now = Date.now();
|
|
7960
8139
|
const event = {
|
|
7961
8140
|
type,
|
|
7962
|
-
path:
|
|
8141
|
+
path: path40,
|
|
7963
8142
|
timestamp: now
|
|
7964
8143
|
};
|
|
7965
|
-
let pending = this.pending.get(
|
|
8144
|
+
let pending = this.pending.get(path40);
|
|
7966
8145
|
if (!pending) {
|
|
7967
8146
|
pending = {
|
|
7968
8147
|
events: [],
|
|
7969
8148
|
timer: null,
|
|
7970
8149
|
lastEvent: now
|
|
7971
8150
|
};
|
|
7972
|
-
this.pending.set(
|
|
8151
|
+
this.pending.set(path40, pending);
|
|
7973
8152
|
}
|
|
7974
8153
|
pending.events.push(event);
|
|
7975
8154
|
pending.lastEvent = now;
|
|
7976
|
-
console.error(`[flywheel] QUEUE: pushed ${type} for ${
|
|
8155
|
+
console.error(`[flywheel] QUEUE: pushed ${type} for ${path40}, pending=${this.pending.size}`);
|
|
7977
8156
|
if (pending.timer) {
|
|
7978
8157
|
clearTimeout(pending.timer);
|
|
7979
8158
|
}
|
|
7980
8159
|
pending.timer = setTimeout(() => {
|
|
7981
|
-
this.flushPath(
|
|
8160
|
+
this.flushPath(path40);
|
|
7982
8161
|
}, this.config.debounceMs);
|
|
7983
8162
|
if (this.pending.size >= this.config.batchSize) {
|
|
7984
8163
|
this.flush();
|
|
@@ -7999,10 +8178,10 @@ var EventQueue = class {
|
|
|
7999
8178
|
/**
|
|
8000
8179
|
* Flush a single path's events
|
|
8001
8180
|
*/
|
|
8002
|
-
flushPath(
|
|
8003
|
-
const pending = this.pending.get(
|
|
8181
|
+
flushPath(path40) {
|
|
8182
|
+
const pending = this.pending.get(path40);
|
|
8004
8183
|
if (!pending || pending.events.length === 0) return;
|
|
8005
|
-
console.error(`[flywheel] QUEUE: flushing ${
|
|
8184
|
+
console.error(`[flywheel] QUEUE: flushing ${path40}, events=${pending.events.length}`);
|
|
8006
8185
|
if (pending.timer) {
|
|
8007
8186
|
clearTimeout(pending.timer);
|
|
8008
8187
|
pending.timer = null;
|
|
@@ -8011,7 +8190,7 @@ var EventQueue = class {
|
|
|
8011
8190
|
if (coalescedType) {
|
|
8012
8191
|
const coalesced = {
|
|
8013
8192
|
type: coalescedType,
|
|
8014
|
-
path:
|
|
8193
|
+
path: path40,
|
|
8015
8194
|
originalEvents: [...pending.events]
|
|
8016
8195
|
};
|
|
8017
8196
|
this.onBatch({
|
|
@@ -8020,7 +8199,7 @@ var EventQueue = class {
|
|
|
8020
8199
|
timestamp: Date.now()
|
|
8021
8200
|
});
|
|
8022
8201
|
}
|
|
8023
|
-
this.pending.delete(
|
|
8202
|
+
this.pending.delete(path40);
|
|
8024
8203
|
}
|
|
8025
8204
|
/**
|
|
8026
8205
|
* Flush all pending events
|
|
@@ -8032,7 +8211,7 @@ var EventQueue = class {
|
|
|
8032
8211
|
}
|
|
8033
8212
|
if (this.pending.size === 0) return;
|
|
8034
8213
|
const events = [];
|
|
8035
|
-
for (const [
|
|
8214
|
+
for (const [path40, pending] of this.pending) {
|
|
8036
8215
|
if (pending.timer) {
|
|
8037
8216
|
clearTimeout(pending.timer);
|
|
8038
8217
|
}
|
|
@@ -8040,7 +8219,7 @@ var EventQueue = class {
|
|
|
8040
8219
|
if (coalescedType) {
|
|
8041
8220
|
events.push({
|
|
8042
8221
|
type: coalescedType,
|
|
8043
|
-
path:
|
|
8222
|
+
path: path40,
|
|
8044
8223
|
originalEvents: [...pending.events]
|
|
8045
8224
|
});
|
|
8046
8225
|
}
|
|
@@ -8118,7 +8297,7 @@ function parseWatcherConfig() {
|
|
|
8118
8297
|
}
|
|
8119
8298
|
|
|
8120
8299
|
// src/core/read/watch/incrementalIndex.ts
|
|
8121
|
-
import
|
|
8300
|
+
import path9 from "path";
|
|
8122
8301
|
function normalizeTarget2(target) {
|
|
8123
8302
|
return target.toLowerCase().replace(/\.md$/, "");
|
|
8124
8303
|
}
|
|
@@ -8255,9 +8434,9 @@ async function upsertNote(index, vaultPath2, notePath) {
|
|
|
8255
8434
|
if (existed) {
|
|
8256
8435
|
releasedKeys = removeNoteFromIndex(index, notePath);
|
|
8257
8436
|
}
|
|
8258
|
-
const fullPath =
|
|
8259
|
-
const
|
|
8260
|
-
const stats = await
|
|
8437
|
+
const fullPath = path9.join(vaultPath2, notePath);
|
|
8438
|
+
const fs35 = await import("fs/promises");
|
|
8439
|
+
const stats = await fs35.stat(fullPath);
|
|
8261
8440
|
const vaultFile = {
|
|
8262
8441
|
path: notePath,
|
|
8263
8442
|
absolutePath: fullPath,
|
|
@@ -8454,31 +8633,31 @@ function createVaultWatcher(options) {
|
|
|
8454
8633
|
usePolling: config2.usePolling,
|
|
8455
8634
|
interval: config2.usePolling ? config2.pollInterval : void 0
|
|
8456
8635
|
});
|
|
8457
|
-
watcher.on("add", (
|
|
8458
|
-
console.error(`[flywheel] RAW EVENT: add ${
|
|
8459
|
-
if (shouldWatch(
|
|
8460
|
-
console.error(`[flywheel] ACCEPTED: add ${
|
|
8461
|
-
eventQueue.push("add",
|
|
8636
|
+
watcher.on("add", (path40) => {
|
|
8637
|
+
console.error(`[flywheel] RAW EVENT: add ${path40}`);
|
|
8638
|
+
if (shouldWatch(path40, vaultPath2)) {
|
|
8639
|
+
console.error(`[flywheel] ACCEPTED: add ${path40}`);
|
|
8640
|
+
eventQueue.push("add", path40);
|
|
8462
8641
|
} else {
|
|
8463
|
-
console.error(`[flywheel] FILTERED: add ${
|
|
8642
|
+
console.error(`[flywheel] FILTERED: add ${path40}`);
|
|
8464
8643
|
}
|
|
8465
8644
|
});
|
|
8466
|
-
watcher.on("change", (
|
|
8467
|
-
console.error(`[flywheel] RAW EVENT: change ${
|
|
8468
|
-
if (shouldWatch(
|
|
8469
|
-
console.error(`[flywheel] ACCEPTED: change ${
|
|
8470
|
-
eventQueue.push("change",
|
|
8645
|
+
watcher.on("change", (path40) => {
|
|
8646
|
+
console.error(`[flywheel] RAW EVENT: change ${path40}`);
|
|
8647
|
+
if (shouldWatch(path40, vaultPath2)) {
|
|
8648
|
+
console.error(`[flywheel] ACCEPTED: change ${path40}`);
|
|
8649
|
+
eventQueue.push("change", path40);
|
|
8471
8650
|
} else {
|
|
8472
|
-
console.error(`[flywheel] FILTERED: change ${
|
|
8651
|
+
console.error(`[flywheel] FILTERED: change ${path40}`);
|
|
8473
8652
|
}
|
|
8474
8653
|
});
|
|
8475
|
-
watcher.on("unlink", (
|
|
8476
|
-
console.error(`[flywheel] RAW EVENT: unlink ${
|
|
8477
|
-
if (shouldWatch(
|
|
8478
|
-
console.error(`[flywheel] ACCEPTED: unlink ${
|
|
8479
|
-
eventQueue.push("unlink",
|
|
8654
|
+
watcher.on("unlink", (path40) => {
|
|
8655
|
+
console.error(`[flywheel] RAW EVENT: unlink ${path40}`);
|
|
8656
|
+
if (shouldWatch(path40, vaultPath2)) {
|
|
8657
|
+
console.error(`[flywheel] ACCEPTED: unlink ${path40}`);
|
|
8658
|
+
eventQueue.push("unlink", path40);
|
|
8480
8659
|
} else {
|
|
8481
|
-
console.error(`[flywheel] FILTERED: unlink ${
|
|
8660
|
+
console.error(`[flywheel] FILTERED: unlink ${path40}`);
|
|
8482
8661
|
}
|
|
8483
8662
|
});
|
|
8484
8663
|
watcher.on("ready", () => {
|
|
@@ -8510,8 +8689,8 @@ function createVaultWatcher(options) {
|
|
|
8510
8689
|
}
|
|
8511
8690
|
|
|
8512
8691
|
// src/core/read/watch/pipeline.ts
|
|
8513
|
-
import * as
|
|
8514
|
-
import * as
|
|
8692
|
+
import * as path17 from "node:path";
|
|
8693
|
+
import * as fs12 from "node:fs/promises";
|
|
8515
8694
|
import {
|
|
8516
8695
|
getAllEntitiesFromDb,
|
|
8517
8696
|
findEntityMatches,
|
|
@@ -8971,7 +9150,7 @@ init_vault();
|
|
|
8971
9150
|
init_serverLog();
|
|
8972
9151
|
init_constants();
|
|
8973
9152
|
init_vault_scope();
|
|
8974
|
-
import * as
|
|
9153
|
+
import * as fs10 from "fs";
|
|
8975
9154
|
var MAX_INDEX_FILE_SIZE = 5 * 1024 * 1024;
|
|
8976
9155
|
var STALE_THRESHOLD_MS = 60 * 60 * 1e3;
|
|
8977
9156
|
function splitFrontmatter(raw) {
|
|
@@ -9030,11 +9209,11 @@ async function buildFTS5Index(vaultPath2) {
|
|
|
9030
9209
|
const rows = [];
|
|
9031
9210
|
for (const file of indexableFiles) {
|
|
9032
9211
|
try {
|
|
9033
|
-
const stats =
|
|
9212
|
+
const stats = fs10.statSync(file.absolutePath);
|
|
9034
9213
|
if (stats.size > MAX_INDEX_FILE_SIZE) {
|
|
9035
9214
|
continue;
|
|
9036
9215
|
}
|
|
9037
|
-
const raw =
|
|
9216
|
+
const raw = fs10.readFileSync(file.absolutePath, "utf-8");
|
|
9038
9217
|
const { frontmatter, body } = splitFrontmatter(raw);
|
|
9039
9218
|
const title = file.path.replace(/\.md$/, "").split("/").pop() || file.path;
|
|
9040
9219
|
rows.push([file.path, title, frontmatter, body]);
|
|
@@ -9114,9 +9293,9 @@ function updateFTS5Incremental(vaultPath2, changed, deleted) {
|
|
|
9114
9293
|
if (!shouldIndexFile2(p)) continue;
|
|
9115
9294
|
const absPath = `${vaultPath2}/${p}`.replace(/\\/g, "/");
|
|
9116
9295
|
try {
|
|
9117
|
-
const stats =
|
|
9296
|
+
const stats = fs10.statSync(absPath);
|
|
9118
9297
|
if (stats.size > MAX_INDEX_FILE_SIZE) continue;
|
|
9119
|
-
const raw =
|
|
9298
|
+
const raw = fs10.readFileSync(absPath, "utf-8");
|
|
9120
9299
|
const { frontmatter, body } = splitFrontmatter(raw);
|
|
9121
9300
|
const title = p.replace(/\.md$/, "").split("/").pop() || p;
|
|
9122
9301
|
del.run(p);
|
|
@@ -9230,11 +9409,11 @@ init_prospects();
|
|
|
9230
9409
|
init_embeddings();
|
|
9231
9410
|
|
|
9232
9411
|
// src/core/read/taskCache.ts
|
|
9233
|
-
import * as
|
|
9412
|
+
import * as path16 from "path";
|
|
9234
9413
|
|
|
9235
9414
|
// src/tools/read/tasks.ts
|
|
9236
|
-
import * as
|
|
9237
|
-
import * as
|
|
9415
|
+
import * as fs11 from "fs";
|
|
9416
|
+
import * as path15 from "path";
|
|
9238
9417
|
var TASK_REGEX = /^(\s*)- \[([ xX\-])\]\s+(.+)$/;
|
|
9239
9418
|
var TAG_REGEX2 = /#([a-zA-Z][a-zA-Z0-9_/-]*)/g;
|
|
9240
9419
|
var DATE_REGEX = /\b(\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}\/\d{2,4})\b/;
|
|
@@ -9260,7 +9439,7 @@ function extractDueDate(text) {
|
|
|
9260
9439
|
async function extractTasksFromNote(notePath, absolutePath) {
|
|
9261
9440
|
let content;
|
|
9262
9441
|
try {
|
|
9263
|
-
content = await
|
|
9442
|
+
content = await fs11.promises.readFile(absolutePath, "utf-8");
|
|
9264
9443
|
} catch {
|
|
9265
9444
|
return [];
|
|
9266
9445
|
}
|
|
@@ -9303,7 +9482,7 @@ async function getAllTasks(index, vaultPath2, options = {}) {
|
|
|
9303
9482
|
const allTasks = [];
|
|
9304
9483
|
for (const note of index.notes.values()) {
|
|
9305
9484
|
if (folder && !note.path.startsWith(folder)) continue;
|
|
9306
|
-
const absolutePath =
|
|
9485
|
+
const absolutePath = path15.join(vaultPath2, note.path);
|
|
9307
9486
|
const tasks = await extractTasksFromNote(note.path, absolutePath);
|
|
9308
9487
|
allTasks.push(...tasks);
|
|
9309
9488
|
}
|
|
@@ -9347,7 +9526,7 @@ async function getAllTasks(index, vaultPath2, options = {}) {
|
|
|
9347
9526
|
async function getTasksFromNote(index, notePath, vaultPath2, excludeTags = []) {
|
|
9348
9527
|
const note = index.notes.get(notePath);
|
|
9349
9528
|
if (!note) return null;
|
|
9350
|
-
const absolutePath =
|
|
9529
|
+
const absolutePath = path15.join(vaultPath2, notePath);
|
|
9351
9530
|
let tasks = await extractTasksFromNote(notePath, absolutePath);
|
|
9352
9531
|
if (excludeTags.length > 0) {
|
|
9353
9532
|
tasks = tasks.filter(
|
|
@@ -9418,7 +9597,7 @@ async function buildTaskCache(vaultPath2, index, excludeTags) {
|
|
|
9418
9597
|
}
|
|
9419
9598
|
const allRows = [];
|
|
9420
9599
|
for (const notePath of notePaths) {
|
|
9421
|
-
const absolutePath =
|
|
9600
|
+
const absolutePath = path16.join(vaultPath2, notePath);
|
|
9422
9601
|
const tasks = await extractTasksFromNote(notePath, absolutePath);
|
|
9423
9602
|
for (const task of tasks) {
|
|
9424
9603
|
if (excludeTags?.length && excludeTags.some((t) => task.tags.includes(t))) {
|
|
@@ -9461,7 +9640,7 @@ async function updateTaskCacheForFile(vaultPath2, relativePath) {
|
|
|
9461
9640
|
const db4 = getDb3();
|
|
9462
9641
|
if (!db4) return;
|
|
9463
9642
|
db4.prepare("DELETE FROM tasks WHERE path = ?").run(relativePath);
|
|
9464
|
-
const absolutePath =
|
|
9643
|
+
const absolutePath = path16.join(vaultPath2, relativePath);
|
|
9465
9644
|
const tasks = await extractTasksFromNote(relativePath, absolutePath);
|
|
9466
9645
|
if (tasks.length > 0) {
|
|
9467
9646
|
const insertStmt = db4.prepare(`
|
|
@@ -10076,7 +10255,7 @@ var PipelineRunner = class {
|
|
|
10076
10255
|
removeEmbedding(event.path);
|
|
10077
10256
|
embRemoved++;
|
|
10078
10257
|
} else if (event.path.endsWith(".md")) {
|
|
10079
|
-
const absPath =
|
|
10258
|
+
const absPath = path17.join(p.vp, event.path);
|
|
10080
10259
|
await updateEmbedding(event.path, absPath);
|
|
10081
10260
|
embUpdated++;
|
|
10082
10261
|
}
|
|
@@ -10322,7 +10501,7 @@ var PipelineRunner = class {
|
|
|
10322
10501
|
for (const event of p.events) {
|
|
10323
10502
|
if (event.type === "delete" || !event.path.endsWith(".md")) continue;
|
|
10324
10503
|
try {
|
|
10325
|
-
const content = await
|
|
10504
|
+
const content = await fs12.readFile(path17.join(p.vp, event.path), "utf-8");
|
|
10326
10505
|
const zones = getProtectedZones(content);
|
|
10327
10506
|
const linked = new Set(
|
|
10328
10507
|
(this.forwardLinkResults.find((r) => r.file === event.path)?.resolved ?? []).map((n) => n.toLowerCase())
|
|
@@ -10367,7 +10546,7 @@ var PipelineRunner = class {
|
|
|
10367
10546
|
for (const event of p.events) {
|
|
10368
10547
|
if (event.type === "delete" || !event.path.endsWith(".md")) continue;
|
|
10369
10548
|
try {
|
|
10370
|
-
const content = await
|
|
10549
|
+
const content = await fs12.readFile(path17.join(p.vp, event.path), "utf-8");
|
|
10371
10550
|
const removed = processImplicitFeedback(p.sd, event.path, content);
|
|
10372
10551
|
for (const entity of removed) feedbackResults.push({ entity, file: event.path });
|
|
10373
10552
|
} catch {
|
|
@@ -10466,7 +10645,7 @@ var PipelineRunner = class {
|
|
|
10466
10645
|
for (const event of p.events) {
|
|
10467
10646
|
if (event.type === "delete" || !event.path.endsWith(".md")) continue;
|
|
10468
10647
|
try {
|
|
10469
|
-
const content = await
|
|
10648
|
+
const content = await fs12.readFile(path17.join(p.vp, event.path), "utf-8");
|
|
10470
10649
|
const zones = getProtectedZones(content);
|
|
10471
10650
|
const linkedSet = new Set(
|
|
10472
10651
|
(this.forwardLinkResults.find((r) => r.file === event.path)?.resolved ?? []).concat(this.forwardLinkResults.find((r) => r.file === event.path)?.dead ?? []).map((n) => n.toLowerCase())
|
|
@@ -10534,7 +10713,7 @@ var PipelineRunner = class {
|
|
|
10534
10713
|
for (const event of p.events) {
|
|
10535
10714
|
if (event.type === "delete" || !event.path.endsWith(".md")) continue;
|
|
10536
10715
|
try {
|
|
10537
|
-
const rawContent = await
|
|
10716
|
+
const rawContent = await fs12.readFile(path17.join(p.vp, event.path), "utf-8");
|
|
10538
10717
|
const content = rawContent.replace(/ → \[\[.*$/gm, "");
|
|
10539
10718
|
const result = await suggestRelatedLinks(content, {
|
|
10540
10719
|
maxSuggestions: 5,
|
|
@@ -10950,7 +11129,7 @@ function getToolEffectivenessScores(stateDb2, minObservations = 15) {
|
|
|
10950
11129
|
}
|
|
10951
11130
|
|
|
10952
11131
|
// src/core/read/integrity.ts
|
|
10953
|
-
import * as
|
|
11132
|
+
import * as path18 from "node:path";
|
|
10954
11133
|
import { existsSync as existsSync3 } from "node:fs";
|
|
10955
11134
|
import { Worker as Worker2 } from "node:worker_threads";
|
|
10956
11135
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -10965,18 +11144,18 @@ var INTEGRITY_METADATA_KEYS = {
|
|
|
10965
11144
|
};
|
|
10966
11145
|
function resolveWorkerSpec() {
|
|
10967
11146
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
10968
|
-
const thisDir =
|
|
10969
|
-
const prodPath =
|
|
11147
|
+
const thisDir = path18.dirname(thisFile);
|
|
11148
|
+
const prodPath = path18.join(thisDir, "integrity-worker.js");
|
|
10970
11149
|
if (existsSync3(prodPath)) return { filename: prodPath };
|
|
10971
|
-
const distPath =
|
|
11150
|
+
const distPath = path18.resolve(thisDir, "..", "..", "..", "dist", "integrity-worker.js");
|
|
10972
11151
|
if (existsSync3(distPath)) return { filename: distPath };
|
|
10973
|
-
const srcPath =
|
|
11152
|
+
const srcPath = path18.join(thisDir, "integrity-worker.ts");
|
|
10974
11153
|
return { filename: srcPath, execArgv: ["--import", "tsx"] };
|
|
10975
11154
|
}
|
|
10976
11155
|
async function runIntegrityWorker(message, timeoutMs = INTEGRITY_CHECK_TIMEOUT_MS) {
|
|
10977
11156
|
const workerSpec = resolveWorkerSpec();
|
|
10978
11157
|
return new Promise((resolve4) => {
|
|
10979
|
-
const
|
|
11158
|
+
const worker = new Worker2(workerSpec.filename, {
|
|
10980
11159
|
execArgv: workerSpec.execArgv
|
|
10981
11160
|
});
|
|
10982
11161
|
let settled = false;
|
|
@@ -10984,7 +11163,7 @@ async function runIntegrityWorker(message, timeoutMs = INTEGRITY_CHECK_TIMEOUT_M
|
|
|
10984
11163
|
if (settled) return;
|
|
10985
11164
|
settled = true;
|
|
10986
11165
|
clearTimeout(timer2);
|
|
10987
|
-
void
|
|
11166
|
+
void worker.terminate().catch(() => {
|
|
10988
11167
|
});
|
|
10989
11168
|
resolve4(result);
|
|
10990
11169
|
};
|
|
@@ -10996,8 +11175,8 @@ async function runIntegrityWorker(message, timeoutMs = INTEGRITY_CHECK_TIMEOUT_M
|
|
|
10996
11175
|
backupCreated: false
|
|
10997
11176
|
});
|
|
10998
11177
|
}, timeoutMs);
|
|
10999
|
-
|
|
11000
|
-
|
|
11178
|
+
worker.once("message", (result) => finish(result));
|
|
11179
|
+
worker.once("error", (err) => {
|
|
11001
11180
|
finish({
|
|
11002
11181
|
status: "error",
|
|
11003
11182
|
detail: err.message,
|
|
@@ -11005,7 +11184,7 @@ async function runIntegrityWorker(message, timeoutMs = INTEGRITY_CHECK_TIMEOUT_M
|
|
|
11005
11184
|
backupCreated: false
|
|
11006
11185
|
});
|
|
11007
11186
|
});
|
|
11008
|
-
|
|
11187
|
+
worker.once("exit", (code) => {
|
|
11009
11188
|
if (settled || code === 0) return;
|
|
11010
11189
|
finish({
|
|
11011
11190
|
status: "error",
|
|
@@ -11014,12 +11193,12 @@ async function runIntegrityWorker(message, timeoutMs = INTEGRITY_CHECK_TIMEOUT_M
|
|
|
11014
11193
|
backupCreated: false
|
|
11015
11194
|
});
|
|
11016
11195
|
});
|
|
11017
|
-
|
|
11196
|
+
worker.postMessage(message);
|
|
11018
11197
|
});
|
|
11019
11198
|
}
|
|
11020
11199
|
|
|
11021
11200
|
// src/index.ts
|
|
11022
|
-
import { openStateDb, scanVaultEntities as scanVaultEntities4, getAllEntitiesFromDb as
|
|
11201
|
+
import { openStateDb, scanVaultEntities as scanVaultEntities4, getAllEntitiesFromDb as getAllEntitiesFromDb7, loadContentHashes, saveContentHashBatch, renameContentHash } from "@velvetmonkey/vault-core";
|
|
11023
11202
|
|
|
11024
11203
|
// src/core/write/memory.ts
|
|
11025
11204
|
init_wikilinkFeedback();
|
|
@@ -12028,7 +12207,7 @@ init_recency();
|
|
|
12028
12207
|
init_prospects();
|
|
12029
12208
|
init_cooccurrence();
|
|
12030
12209
|
init_retrievalCooccurrence();
|
|
12031
|
-
import * as
|
|
12210
|
+
import * as fs34 from "node:fs/promises";
|
|
12032
12211
|
import { createHash as createHash3 } from "node:crypto";
|
|
12033
12212
|
|
|
12034
12213
|
// src/vault-registry.ts
|
|
@@ -12098,7 +12277,6 @@ init_vault_scope();
|
|
|
12098
12277
|
// src/config.ts
|
|
12099
12278
|
init_embeddings();
|
|
12100
12279
|
init_serverLog();
|
|
12101
|
-
var INITIAL_TIER_OVERRIDE = "auto";
|
|
12102
12280
|
var ALL_CATEGORIES = [
|
|
12103
12281
|
"search",
|
|
12104
12282
|
"read",
|
|
@@ -12329,7 +12507,7 @@ var ACTION_PARAM_MAP = {
|
|
|
12329
12507
|
policy: ["list", "validate", "preview", "execute", "author", "revise"],
|
|
12330
12508
|
correct: ["record", "list", "resolve", "undo"],
|
|
12331
12509
|
link: ["suggest", "feedback", "unlinked", "validate", "stubs", "dashboard", "unsuppress", "timeline", "layer_timeseries", "snapshot_diff"],
|
|
12332
|
-
graph: ["analyse", "backlinks", "forward_links", "strong_connections", "path", "neighbors", "strength", "cooccurrence_gaps"],
|
|
12510
|
+
graph: ["analyse", "backlinks", "forward_links", "strong_connections", "path", "neighbors", "strength", "cooccurrence_gaps", "export"],
|
|
12333
12511
|
schema: ["overview", "field_values", "conventions", "folders", "rename_field", "rename_tag", "migrate", "validate"],
|
|
12334
12512
|
insights: ["evolution", "staleness", "context", "note_intelligence", "growth"],
|
|
12335
12513
|
doctor: ["health", "diagnosis", "stats", "pipeline", "config", "log"]
|
|
@@ -12547,8 +12725,8 @@ Temporal tools analyze *patterns and changes* over time \u2014 use them for "wha
|
|
|
12547
12725
|
}
|
|
12548
12726
|
|
|
12549
12727
|
// src/tool-registry.ts
|
|
12550
|
-
import * as
|
|
12551
|
-
import { dirname as dirname6, join as
|
|
12728
|
+
import * as path38 from "path";
|
|
12729
|
+
import { dirname as dirname6, join as join18 } from "path";
|
|
12552
12730
|
import { statSync as statSync5, readFileSync as readFileSync5 } from "fs";
|
|
12553
12731
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
12554
12732
|
import { z as z25 } from "zod";
|
|
@@ -12583,8 +12761,8 @@ import {
|
|
|
12583
12761
|
} from "@velvetmonkey/vault-core";
|
|
12584
12762
|
|
|
12585
12763
|
// src/core/read/similarity.ts
|
|
12586
|
-
import * as
|
|
12587
|
-
import * as
|
|
12764
|
+
import * as fs13 from "fs";
|
|
12765
|
+
import * as path19 from "path";
|
|
12588
12766
|
init_embeddings();
|
|
12589
12767
|
|
|
12590
12768
|
// src/core/read/mmr.ts
|
|
@@ -12654,10 +12832,10 @@ function extractKeyTerms(content, maxTerms = 15) {
|
|
|
12654
12832
|
}
|
|
12655
12833
|
function findSimilarNotes(db4, vaultPath2, index, sourcePath, options = {}) {
|
|
12656
12834
|
const limit = options.limit ?? 10;
|
|
12657
|
-
const absPath =
|
|
12835
|
+
const absPath = path19.join(vaultPath2, sourcePath);
|
|
12658
12836
|
let content;
|
|
12659
12837
|
try {
|
|
12660
|
-
content =
|
|
12838
|
+
content = fs13.readFileSync(absPath, "utf-8");
|
|
12661
12839
|
} catch {
|
|
12662
12840
|
return [];
|
|
12663
12841
|
}
|
|
@@ -13099,13 +13277,13 @@ function multiHopBackfill(primaryResults, index, stateDb2, config2 = {}) {
|
|
|
13099
13277
|
candidates.sort((a, b) => b.score - a.score);
|
|
13100
13278
|
return candidates.slice(0, cfg.maxBackfill).map((c) => c.result);
|
|
13101
13279
|
}
|
|
13102
|
-
function scoreCandidate(
|
|
13103
|
-
const note = index.notes.get(
|
|
13280
|
+
function scoreCandidate(path40, index, stateDb2) {
|
|
13281
|
+
const note = index.notes.get(path40);
|
|
13104
13282
|
const decay = recencyDecay(note?.modified);
|
|
13105
13283
|
let hubScore = 1;
|
|
13106
13284
|
if (stateDb2) {
|
|
13107
13285
|
try {
|
|
13108
|
-
const title = note?.title ??
|
|
13286
|
+
const title = note?.title ?? path40.replace(/\.md$/, "").split("/").pop() ?? "";
|
|
13109
13287
|
const entity = getEntityByName3(stateDb2, title);
|
|
13110
13288
|
if (entity) hubScore = entity.hubScore ?? 1;
|
|
13111
13289
|
} catch {
|
|
@@ -13173,7 +13351,7 @@ init_edgeWeights();
|
|
|
13173
13351
|
// src/core/read/snippets.ts
|
|
13174
13352
|
init_embeddings();
|
|
13175
13353
|
init_stemmer();
|
|
13176
|
-
import * as
|
|
13354
|
+
import * as fs14 from "fs";
|
|
13177
13355
|
function stripFrontmatter(content) {
|
|
13178
13356
|
const match = content.match(/^---[\s\S]*?---\n([\s\S]*)$/);
|
|
13179
13357
|
return match ? match[1] : content;
|
|
@@ -13252,7 +13430,7 @@ async function extractBestSnippets(filePath, queryEmbedding, queryTokens, option
|
|
|
13252
13430
|
const maxChunkChars = options?.maxChunkChars ?? 800;
|
|
13253
13431
|
let content;
|
|
13254
13432
|
try {
|
|
13255
|
-
content =
|
|
13433
|
+
content = fs14.readFileSync(filePath, "utf-8");
|
|
13256
13434
|
} catch {
|
|
13257
13435
|
return [];
|
|
13258
13436
|
}
|
|
@@ -13341,8 +13519,8 @@ function extractDates(text) {
|
|
|
13341
13519
|
init_stemmer();
|
|
13342
13520
|
|
|
13343
13521
|
// src/tools/read/structure.ts
|
|
13344
|
-
import * as
|
|
13345
|
-
import * as
|
|
13522
|
+
import * as fs15 from "fs";
|
|
13523
|
+
import * as path20 from "path";
|
|
13346
13524
|
var HEADING_REGEX2 = /^(#{1,6})\s+(.+)$/;
|
|
13347
13525
|
function extractHeadings2(content) {
|
|
13348
13526
|
const lines = content.replace(/\r\n/g, "\n").split("\n");
|
|
@@ -13396,10 +13574,10 @@ function buildSections(headings, totalLines) {
|
|
|
13396
13574
|
async function getNoteStructure(index, notePath, vaultPath2) {
|
|
13397
13575
|
const note = index.notes.get(notePath);
|
|
13398
13576
|
if (!note) return null;
|
|
13399
|
-
const absolutePath =
|
|
13577
|
+
const absolutePath = path20.join(vaultPath2, notePath);
|
|
13400
13578
|
let content;
|
|
13401
13579
|
try {
|
|
13402
|
-
content = await
|
|
13580
|
+
content = await fs15.promises.readFile(absolutePath, "utf-8");
|
|
13403
13581
|
} catch {
|
|
13404
13582
|
return null;
|
|
13405
13583
|
}
|
|
@@ -13420,10 +13598,10 @@ async function getNoteStructure(index, notePath, vaultPath2) {
|
|
|
13420
13598
|
async function getSectionContent(index, notePath, headingText, vaultPath2, includeSubheadings = true) {
|
|
13421
13599
|
const note = index.notes.get(notePath);
|
|
13422
13600
|
if (!note) return null;
|
|
13423
|
-
const absolutePath =
|
|
13601
|
+
const absolutePath = path20.join(vaultPath2, notePath);
|
|
13424
13602
|
let content;
|
|
13425
13603
|
try {
|
|
13426
|
-
content = await
|
|
13604
|
+
content = await fs15.promises.readFile(absolutePath, "utf-8");
|
|
13427
13605
|
} catch {
|
|
13428
13606
|
return null;
|
|
13429
13607
|
}
|
|
@@ -13463,10 +13641,10 @@ async function findSections(index, headingPattern, vaultPath2, folder) {
|
|
|
13463
13641
|
const results = [];
|
|
13464
13642
|
for (const note of index.notes.values()) {
|
|
13465
13643
|
if (folder && !note.path.startsWith(folder)) continue;
|
|
13466
|
-
const absolutePath =
|
|
13644
|
+
const absolutePath = path20.join(vaultPath2, note.path);
|
|
13467
13645
|
let content;
|
|
13468
13646
|
try {
|
|
13469
|
-
content = await
|
|
13647
|
+
content = await fs15.promises.readFile(absolutePath, "utf-8");
|
|
13470
13648
|
} catch {
|
|
13471
13649
|
continue;
|
|
13472
13650
|
}
|
|
@@ -13635,11 +13813,11 @@ function applyEntityBridging(results, stateDb2, maxBridgesPerResult = 5) {
|
|
|
13635
13813
|
const linkMap = /* @__PURE__ */ new Map();
|
|
13636
13814
|
try {
|
|
13637
13815
|
const paths = results.map((r) => r.path).filter(Boolean);
|
|
13638
|
-
for (const
|
|
13816
|
+
for (const path40 of paths) {
|
|
13639
13817
|
const rows = stateDb2.db.prepare(
|
|
13640
13818
|
"SELECT target FROM note_links WHERE note_path = ?"
|
|
13641
|
-
).all(
|
|
13642
|
-
linkMap.set(
|
|
13819
|
+
).all(path40);
|
|
13820
|
+
linkMap.set(path40, new Set(rows.map((r) => r.target)));
|
|
13643
13821
|
}
|
|
13644
13822
|
} catch {
|
|
13645
13823
|
return;
|
|
@@ -14131,7 +14309,7 @@ function registerQueryTools(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
14131
14309
|
init_vault_scope();
|
|
14132
14310
|
|
|
14133
14311
|
// src/tools/read/health.ts
|
|
14134
|
-
import * as
|
|
14312
|
+
import * as fs16 from "fs";
|
|
14135
14313
|
import { z as z3 } from "zod";
|
|
14136
14314
|
|
|
14137
14315
|
// src/tools/read/periodic.ts
|
|
@@ -14594,7 +14772,7 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig2 = () =>
|
|
|
14594
14772
|
const indexErrorObj = getIndexError();
|
|
14595
14773
|
let vaultAccessible = false;
|
|
14596
14774
|
try {
|
|
14597
|
-
|
|
14775
|
+
fs16.accessSync(vaultPath2, fs16.constants.R_OK);
|
|
14598
14776
|
vaultAccessible = true;
|
|
14599
14777
|
} catch {
|
|
14600
14778
|
vaultAccessible = false;
|
|
@@ -14927,8 +15105,8 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig2 = () =>
|
|
|
14927
15105
|
daily_counts: z3.record(z3.number())
|
|
14928
15106
|
}).describe("Activity summary for the last 7 days")
|
|
14929
15107
|
};
|
|
14930
|
-
function isPeriodicNote2(
|
|
14931
|
-
const filename =
|
|
15108
|
+
function isPeriodicNote2(path40) {
|
|
15109
|
+
const filename = path40.split("/").pop() || "";
|
|
14932
15110
|
const nameWithoutExt = filename.replace(/\.md$/, "");
|
|
14933
15111
|
const patterns = [
|
|
14934
15112
|
/^\d{4}-\d{2}-\d{2}$/,
|
|
@@ -14943,7 +15121,7 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig2 = () =>
|
|
|
14943
15121
|
// YYYY (yearly)
|
|
14944
15122
|
];
|
|
14945
15123
|
const periodicFolders = ["daily", "weekly", "monthly", "quarterly", "yearly", "journal", "journals"];
|
|
14946
|
-
const folder =
|
|
15124
|
+
const folder = path40.split("/")[0]?.toLowerCase() || "";
|
|
14947
15125
|
return patterns.some((p) => p.test(nameWithoutExt)) || periodicFolders.includes(folder);
|
|
14948
15126
|
}
|
|
14949
15127
|
async function runVaultStats() {
|
|
@@ -15068,7 +15246,7 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig2 = () =>
|
|
|
15068
15246
|
const diagWatcherStatus = getWatcherStatus2();
|
|
15069
15247
|
checks.push({ name: "schema_version", status: "ok", detail: `Schema version ${SCHEMA_VERSION}` });
|
|
15070
15248
|
try {
|
|
15071
|
-
|
|
15249
|
+
fs16.accessSync(diagVaultPath, fs16.constants.R_OK | fs16.constants.W_OK);
|
|
15072
15250
|
checks.push({ name: "vault_access", status: "ok", detail: `Vault readable and writable at ${diagVaultPath}` });
|
|
15073
15251
|
} catch {
|
|
15074
15252
|
checks.push({ name: "vault_access", status: "error", detail: `Vault not accessible at ${diagVaultPath}`, fix: "Check PROJECT_PATH environment variable and directory permissions" });
|
|
@@ -15275,6 +15453,17 @@ function registerHealthTools(server2, getIndex, getVaultPath, getConfig2 = () =>
|
|
|
15275
15453
|
saveFlywheelConfigToDb3(stateDb2, updated);
|
|
15276
15454
|
const reloaded = loadConfig(stateDb2);
|
|
15277
15455
|
if (doctorSetConfig) doctorSetConfig(reloaded);
|
|
15456
|
+
if (key === "tool_tier_override") {
|
|
15457
|
+
return {
|
|
15458
|
+
content: [{
|
|
15459
|
+
type: "text",
|
|
15460
|
+
text: JSON.stringify({
|
|
15461
|
+
config: reloaded,
|
|
15462
|
+
warning: "tool_tier_override is deprecated and has no runtime effect. Use agent, power, or full presets instead."
|
|
15463
|
+
}, null, 2)
|
|
15464
|
+
}]
|
|
15465
|
+
};
|
|
15466
|
+
}
|
|
15278
15467
|
return { content: [{ type: "text", text: JSON.stringify(reloaded, null, 2) }] };
|
|
15279
15468
|
}
|
|
15280
15469
|
case "stats": {
|
|
@@ -15942,63 +16131,63 @@ init_constants2();
|
|
|
15942
16131
|
init_writer();
|
|
15943
16132
|
init_wikilinks();
|
|
15944
16133
|
init_wikilinkFeedback();
|
|
15945
|
-
import
|
|
15946
|
-
import
|
|
16134
|
+
import fs20 from "fs/promises";
|
|
16135
|
+
import path24 from "path";
|
|
15947
16136
|
|
|
15948
16137
|
// src/core/write/policy/policyPaths.ts
|
|
15949
|
-
import
|
|
15950
|
-
import
|
|
16138
|
+
import fs19 from "fs/promises";
|
|
16139
|
+
import path23 from "path";
|
|
15951
16140
|
function getPoliciesDir(vaultPath2) {
|
|
15952
|
-
return
|
|
16141
|
+
return path23.join(vaultPath2, ".flywheel", "policies");
|
|
15953
16142
|
}
|
|
15954
16143
|
function getLegacyPoliciesDir(vaultPath2) {
|
|
15955
|
-
return
|
|
16144
|
+
return path23.join(vaultPath2, ".claude", "policies");
|
|
15956
16145
|
}
|
|
15957
16146
|
async function ensurePoliciesDir(vaultPath2) {
|
|
15958
16147
|
const dir = getPoliciesDir(vaultPath2);
|
|
15959
|
-
await
|
|
16148
|
+
await fs19.mkdir(dir, { recursive: true });
|
|
15960
16149
|
}
|
|
15961
16150
|
async function migratePoliciesIfNeeded(vaultPath2) {
|
|
15962
16151
|
const legacyDir = getLegacyPoliciesDir(vaultPath2);
|
|
15963
16152
|
let files;
|
|
15964
16153
|
try {
|
|
15965
|
-
files = await
|
|
16154
|
+
files = await fs19.readdir(legacyDir);
|
|
15966
16155
|
} catch {
|
|
15967
16156
|
return;
|
|
15968
16157
|
}
|
|
15969
16158
|
const yamlFiles = files.filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
|
|
15970
16159
|
if (yamlFiles.length === 0) {
|
|
15971
16160
|
await tryRmdir(legacyDir);
|
|
15972
|
-
await tryRmdir(
|
|
16161
|
+
await tryRmdir(path23.join(vaultPath2, ".claude"));
|
|
15973
16162
|
return;
|
|
15974
16163
|
}
|
|
15975
16164
|
await ensurePoliciesDir(vaultPath2);
|
|
15976
16165
|
const destDir = getPoliciesDir(vaultPath2);
|
|
15977
16166
|
for (const file of yamlFiles) {
|
|
15978
|
-
const src =
|
|
15979
|
-
const dest =
|
|
16167
|
+
const src = path23.join(legacyDir, file);
|
|
16168
|
+
const dest = path23.join(destDir, file);
|
|
15980
16169
|
try {
|
|
15981
|
-
await
|
|
16170
|
+
await fs19.access(dest);
|
|
15982
16171
|
} catch {
|
|
15983
|
-
await
|
|
16172
|
+
await fs19.copyFile(src, dest);
|
|
15984
16173
|
}
|
|
15985
|
-
await
|
|
16174
|
+
await fs19.unlink(src);
|
|
15986
16175
|
}
|
|
15987
16176
|
await tryRmdir(legacyDir);
|
|
15988
|
-
await tryRmdir(
|
|
16177
|
+
await tryRmdir(path23.join(vaultPath2, ".claude"));
|
|
15989
16178
|
}
|
|
15990
16179
|
async function tryRmdir(dir) {
|
|
15991
16180
|
try {
|
|
15992
|
-
const remaining = await
|
|
16181
|
+
const remaining = await fs19.readdir(dir);
|
|
15993
16182
|
if (remaining.length === 0) {
|
|
15994
|
-
await
|
|
16183
|
+
await fs19.rmdir(dir);
|
|
15995
16184
|
}
|
|
15996
16185
|
} catch {
|
|
15997
16186
|
}
|
|
15998
16187
|
}
|
|
15999
16188
|
var migrationCache = /* @__PURE__ */ new Map();
|
|
16000
16189
|
async function ensureMigrated(vaultPath2) {
|
|
16001
|
-
const key =
|
|
16190
|
+
const key = path23.resolve(vaultPath2);
|
|
16002
16191
|
if (!migrationCache.has(key)) {
|
|
16003
16192
|
migrationCache.set(key, migratePoliciesIfNeeded(vaultPath2));
|
|
16004
16193
|
}
|
|
@@ -16054,7 +16243,7 @@ async function handleGitCommit(vaultPath2, notePath, commit, prefix) {
|
|
|
16054
16243
|
async function getPolicyHint(vaultPath2) {
|
|
16055
16244
|
try {
|
|
16056
16245
|
const policiesDir = getPoliciesDir(vaultPath2);
|
|
16057
|
-
const files = await
|
|
16246
|
+
const files = await fs20.readdir(policiesDir);
|
|
16058
16247
|
const yamlFiles = files.filter((f) => f.endsWith(".yaml") || f.endsWith(".yml"));
|
|
16059
16248
|
if (yamlFiles.length > 0) {
|
|
16060
16249
|
const names = yamlFiles.map((f) => f.replace(/\.ya?ml$/, "")).join(", ");
|
|
@@ -16069,9 +16258,9 @@ async function ensureFileExists(vaultPath2, notePath) {
|
|
|
16069
16258
|
if (!validation.valid) {
|
|
16070
16259
|
return errorResult(notePath, `Invalid path: ${validation.reason}`);
|
|
16071
16260
|
}
|
|
16072
|
-
const fullPath =
|
|
16261
|
+
const fullPath = path24.join(vaultPath2, notePath);
|
|
16073
16262
|
try {
|
|
16074
|
-
await
|
|
16263
|
+
await fs20.access(fullPath);
|
|
16075
16264
|
return null;
|
|
16076
16265
|
} catch {
|
|
16077
16266
|
const hint = await getPolicyHint(vaultPath2);
|
|
@@ -16274,17 +16463,17 @@ async function executeCreateNote(options) {
|
|
|
16274
16463
|
if (!pathCheck.valid) {
|
|
16275
16464
|
return { success: false, result: errorResult(notePath, `Path blocked: ${pathCheck.reason}`), filesWritten: [] };
|
|
16276
16465
|
}
|
|
16277
|
-
const fullPath =
|
|
16466
|
+
const fullPath = path24.join(vaultPath2, notePath);
|
|
16278
16467
|
let fileExists = false;
|
|
16279
16468
|
try {
|
|
16280
|
-
await
|
|
16469
|
+
await fs20.access(fullPath);
|
|
16281
16470
|
fileExists = true;
|
|
16282
16471
|
} catch {
|
|
16283
16472
|
}
|
|
16284
16473
|
if (fileExists && !overwrite) {
|
|
16285
16474
|
return { success: false, result: errorResult(notePath, `File already exists: ${notePath}. Use overwrite=true to replace.`), filesWritten: [] };
|
|
16286
16475
|
}
|
|
16287
|
-
await
|
|
16476
|
+
await fs20.mkdir(path24.dirname(fullPath), { recursive: true });
|
|
16288
16477
|
const { maybeApplyWikilinks: maybeApplyWikilinks2 } = await Promise.resolve().then(() => (init_wikilinks(), wikilinks_exports));
|
|
16289
16478
|
const { content: processedContent } = maybeApplyWikilinks2(content, skipWikilinks ?? false, notePath);
|
|
16290
16479
|
let finalFrontmatter = frontmatter;
|
|
@@ -16318,13 +16507,13 @@ async function executeDeleteNote(options) {
|
|
|
16318
16507
|
if (!pathCheck.valid) {
|
|
16319
16508
|
return { success: false, result: errorResult(notePath, `Path blocked: ${pathCheck.reason}`), filesWritten: [] };
|
|
16320
16509
|
}
|
|
16321
|
-
const fullPath =
|
|
16510
|
+
const fullPath = path24.join(vaultPath2, notePath);
|
|
16322
16511
|
try {
|
|
16323
|
-
await
|
|
16512
|
+
await fs20.access(fullPath);
|
|
16324
16513
|
} catch {
|
|
16325
16514
|
return { success: false, result: errorResult(notePath, `File not found: ${notePath}`), filesWritten: [] };
|
|
16326
16515
|
}
|
|
16327
|
-
await
|
|
16516
|
+
await fs20.unlink(fullPath);
|
|
16328
16517
|
const result = successResult(notePath, `Deleted note: ${notePath}`, {});
|
|
16329
16518
|
return { success: true, result, filesWritten: [notePath] };
|
|
16330
16519
|
} catch (error) {
|
|
@@ -16479,19 +16668,19 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16479
16668
|
limit: z7.coerce.number().optional().describe("[sections] Max results (default 50)"),
|
|
16480
16669
|
offset: z7.coerce.number().optional().describe("[sections] Results to skip for pagination (default 0)")
|
|
16481
16670
|
};
|
|
16482
|
-
const noteReadImpl = async ({ action, path:
|
|
16671
|
+
const noteReadImpl = async ({ action, path: path40, include_content, max_content_chars, heading, include_subheadings, max_section_chars, pattern, folder, limit: requestedLimit, offset: requestedOffset }) => {
|
|
16483
16672
|
const index = getIndex();
|
|
16484
16673
|
const vaultPath2 = getVaultPath();
|
|
16485
16674
|
if (action === "structure") {
|
|
16486
|
-
if (!
|
|
16675
|
+
if (!path40) {
|
|
16487
16676
|
return { content: [{ type: "text", text: JSON.stringify({
|
|
16488
16677
|
error: "action=structure requires path.",
|
|
16489
16678
|
example: { action: "structure", path: "projects/alpha.md" }
|
|
16490
16679
|
}, null, 2) }] };
|
|
16491
16680
|
}
|
|
16492
|
-
const result2 = await getNoteStructure(index,
|
|
16681
|
+
const result2 = await getNoteStructure(index, path40, vaultPath2);
|
|
16493
16682
|
if (!result2) {
|
|
16494
|
-
return { content: [{ type: "text", text: JSON.stringify({ error: "Note not found", path:
|
|
16683
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "Note not found", path: path40 }, null, 2) }] };
|
|
16495
16684
|
}
|
|
16496
16685
|
const maxChars = max_content_chars ?? 2e4;
|
|
16497
16686
|
let totalChars = 0;
|
|
@@ -16502,7 +16691,7 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16502
16691
|
truncated = true;
|
|
16503
16692
|
break;
|
|
16504
16693
|
}
|
|
16505
|
-
const sectionResult = await getSectionContent(index,
|
|
16694
|
+
const sectionResult = await getSectionContent(index, path40, section.heading.text, vaultPath2, true);
|
|
16506
16695
|
if (sectionResult) {
|
|
16507
16696
|
let content = sectionResult.content;
|
|
16508
16697
|
const remaining = maxChars - totalChars;
|
|
@@ -16517,13 +16706,13 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16517
16706
|
}
|
|
16518
16707
|
}
|
|
16519
16708
|
}
|
|
16520
|
-
const note = index.notes.get(
|
|
16709
|
+
const note = index.notes.get(path40);
|
|
16521
16710
|
const enriched = { ...result2 };
|
|
16522
16711
|
if (note) {
|
|
16523
16712
|
enriched.frontmatter = note.frontmatter;
|
|
16524
16713
|
enriched.tags = note.tags;
|
|
16525
16714
|
enriched.aliases = note.aliases;
|
|
16526
|
-
const normalizedPath =
|
|
16715
|
+
const normalizedPath = path40.toLowerCase().replace(/\.md$/, "");
|
|
16527
16716
|
const backlinks = index.backlinks.get(normalizedPath) || [];
|
|
16528
16717
|
enriched.backlink_count = backlinks.length;
|
|
16529
16718
|
enriched.outlink_count = note.outlinks.length;
|
|
@@ -16547,7 +16736,7 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16547
16736
|
return { content: [{ type: "text", text: JSON.stringify(enriched, null, 2) }] };
|
|
16548
16737
|
}
|
|
16549
16738
|
if (action === "section") {
|
|
16550
|
-
if (!
|
|
16739
|
+
if (!path40) {
|
|
16551
16740
|
return { content: [{ type: "text", text: JSON.stringify({
|
|
16552
16741
|
error: "action=section requires path.",
|
|
16553
16742
|
example: { action: "section", path: "projects/alpha.md", heading: "Background" }
|
|
@@ -16559,9 +16748,9 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16559
16748
|
example: { action: "section", path: "projects/alpha.md", heading: "Background" }
|
|
16560
16749
|
}, null, 2) }] };
|
|
16561
16750
|
}
|
|
16562
|
-
const result2 = await getSectionContent(index,
|
|
16751
|
+
const result2 = await getSectionContent(index, path40, heading, vaultPath2, include_subheadings ?? true);
|
|
16563
16752
|
if (!result2) {
|
|
16564
|
-
return { content: [{ type: "text", text: JSON.stringify({ error: "Section not found", path:
|
|
16753
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "Section not found", path: path40, heading }, null, 2) }] };
|
|
16565
16754
|
}
|
|
16566
16755
|
const maxChars = max_section_chars ?? 1e4;
|
|
16567
16756
|
let truncated = false;
|
|
@@ -16617,32 +16806,32 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16617
16806
|
session_id: z7.string().optional().describe("[toggle] Session identifier for scoping")
|
|
16618
16807
|
}
|
|
16619
16808
|
},
|
|
16620
|
-
async ({ action = "list", path:
|
|
16809
|
+
async ({ action = "list", path: path40, status, has_due_date, folder, tag, limit: requestedLimit, offset, task, section, commit, dry_run, agent_id, session_id }) => {
|
|
16621
16810
|
if (action === "toggle") {
|
|
16622
|
-
if (!
|
|
16623
|
-
return formatMcpResult(errorResult(
|
|
16811
|
+
if (!path40 || !task) {
|
|
16812
|
+
return formatMcpResult(errorResult(path40 ?? "", "toggle requires path and task"));
|
|
16624
16813
|
}
|
|
16625
16814
|
const vaultPath3 = getVaultPath();
|
|
16626
16815
|
try {
|
|
16627
|
-
const existsError = await ensureFileExists(vaultPath3,
|
|
16816
|
+
const existsError = await ensureFileExists(vaultPath3, path40);
|
|
16628
16817
|
if (existsError) return formatMcpResult(existsError);
|
|
16629
|
-
const { content: fileContent, frontmatter, contentHash: contentHash2 } = await readVaultFile(vaultPath3,
|
|
16818
|
+
const { content: fileContent, frontmatter, contentHash: contentHash2 } = await readVaultFile(vaultPath3, path40);
|
|
16630
16819
|
let sectionBoundary;
|
|
16631
16820
|
if (section) {
|
|
16632
16821
|
const found = findSection(fileContent, section);
|
|
16633
|
-
if (!found) return formatMcpResult(errorResult(
|
|
16822
|
+
if (!found) return formatMcpResult(errorResult(path40, `Section not found: ${section}`));
|
|
16634
16823
|
sectionBoundary = found;
|
|
16635
16824
|
}
|
|
16636
16825
|
const tasks = findTasks(fileContent, sectionBoundary ?? void 0);
|
|
16637
16826
|
const searchLower = task.toLowerCase();
|
|
16638
16827
|
const matchingTask = tasks.find((t) => t.text.toLowerCase().includes(searchLower));
|
|
16639
|
-
if (!matchingTask) return formatMcpResult(errorResult(
|
|
16828
|
+
if (!matchingTask) return formatMcpResult(errorResult(path40, `No task found matching "${task}"`));
|
|
16640
16829
|
const toggleResult = toggleTask(fileContent, matchingTask.line);
|
|
16641
|
-
if (!toggleResult) return formatMcpResult(errorResult(
|
|
16830
|
+
if (!toggleResult) return formatMcpResult(errorResult(path40, "Failed to toggle task"));
|
|
16642
16831
|
const newStatus = toggleResult.newState ? "completed" : "incomplete";
|
|
16643
16832
|
const checkbox = toggleResult.newState ? "[x]" : "[ ]";
|
|
16644
16833
|
if (dry_run) {
|
|
16645
|
-
return formatMcpResult(successResult(
|
|
16834
|
+
return formatMcpResult(successResult(path40, `[dry run] Would toggle task to ${newStatus}`, {}, {
|
|
16646
16835
|
preview: `${checkbox} ${matchingTask.text}`,
|
|
16647
16836
|
dryRun: true
|
|
16648
16837
|
}));
|
|
@@ -16651,11 +16840,11 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16651
16840
|
if (agent_id || session_id) {
|
|
16652
16841
|
finalFrontmatter = injectMutationMetadata(frontmatter, { agent_id, session_id });
|
|
16653
16842
|
}
|
|
16654
|
-
await writeVaultFile(vaultPath3,
|
|
16655
|
-
await updateTaskCacheForFile(vaultPath3,
|
|
16843
|
+
await writeVaultFile(vaultPath3, path40, toggleResult.content, finalFrontmatter, "LF", contentHash2);
|
|
16844
|
+
await updateTaskCacheForFile(vaultPath3, path40).catch(() => {
|
|
16656
16845
|
});
|
|
16657
|
-
const gitInfo = await handleGitCommit(vaultPath3,
|
|
16658
|
-
return formatMcpResult(successResult(
|
|
16846
|
+
const gitInfo = await handleGitCommit(vaultPath3, path40, commit ?? false, "[Flywheel:Task]");
|
|
16847
|
+
return formatMcpResult(successResult(path40, `Toggled task to ${newStatus}`, gitInfo, {
|
|
16659
16848
|
preview: `${checkbox} ${matchingTask.text}`
|
|
16660
16849
|
}));
|
|
16661
16850
|
} catch (error) {
|
|
@@ -16663,18 +16852,18 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16663
16852
|
if (error instanceof WriteConflictError) {
|
|
16664
16853
|
extras.warnings = [{ type: "write_conflict", message: error.message, suggestion: "Re-read and retry." }];
|
|
16665
16854
|
}
|
|
16666
|
-
return formatMcpResult(errorResult(
|
|
16855
|
+
return formatMcpResult(errorResult(path40, `Failed to toggle task: ${error instanceof Error ? error.message : String(error)}`, extras));
|
|
16667
16856
|
}
|
|
16668
16857
|
}
|
|
16669
16858
|
const limit = Math.min(requestedLimit ?? 25, MAX_LIMIT);
|
|
16670
16859
|
const index = getIndex();
|
|
16671
16860
|
const vaultPath2 = getVaultPath();
|
|
16672
16861
|
const config2 = getConfig2();
|
|
16673
|
-
if (
|
|
16674
|
-
const result2 = await getTasksFromNote(index,
|
|
16862
|
+
if (path40) {
|
|
16863
|
+
const result2 = await getTasksFromNote(index, path40, vaultPath2, getExcludeTags(config2));
|
|
16675
16864
|
if (!result2) {
|
|
16676
16865
|
return {
|
|
16677
|
-
content: [{ type: "text", text: JSON.stringify({ error: "Note not found", path:
|
|
16866
|
+
content: [{ type: "text", text: JSON.stringify({ error: "Note not found", path: path40 }, null, 2) }]
|
|
16678
16867
|
};
|
|
16679
16868
|
}
|
|
16680
16869
|
let filtered = result2;
|
|
@@ -16684,7 +16873,7 @@ function registerPrimitiveTools(server2, getIndex, getVaultPath, getConfig2 = ()
|
|
|
16684
16873
|
const paged2 = filtered.slice(offset, offset + limit);
|
|
16685
16874
|
return {
|
|
16686
16875
|
content: [{ type: "text", text: JSON.stringify({
|
|
16687
|
-
path:
|
|
16876
|
+
path: path40,
|
|
16688
16877
|
total_count: filtered.length,
|
|
16689
16878
|
returned_count: paged2.length,
|
|
16690
16879
|
open: result2.filter((t) => t.status === "open").length,
|
|
@@ -17040,8 +17229,8 @@ function inferFolderConventions(index, folder, minConfidence = 0.5) {
|
|
|
17040
17229
|
|
|
17041
17230
|
// src/tools/read/migrations.ts
|
|
17042
17231
|
import { z as z8 } from "zod";
|
|
17043
|
-
import * as
|
|
17044
|
-
import * as
|
|
17232
|
+
import * as fs21 from "fs/promises";
|
|
17233
|
+
import * as path25 from "path";
|
|
17045
17234
|
import matter3 from "gray-matter";
|
|
17046
17235
|
function getNotesInFolder2(index, folder) {
|
|
17047
17236
|
const notes = [];
|
|
@@ -17054,17 +17243,17 @@ function getNotesInFolder2(index, folder) {
|
|
|
17054
17243
|
return notes;
|
|
17055
17244
|
}
|
|
17056
17245
|
async function readFileContent(notePath, vaultPath2) {
|
|
17057
|
-
const fullPath =
|
|
17246
|
+
const fullPath = path25.join(vaultPath2, notePath);
|
|
17058
17247
|
try {
|
|
17059
|
-
return await
|
|
17248
|
+
return await fs21.readFile(fullPath, "utf-8");
|
|
17060
17249
|
} catch {
|
|
17061
17250
|
return null;
|
|
17062
17251
|
}
|
|
17063
17252
|
}
|
|
17064
17253
|
async function writeFileContent(notePath, vaultPath2, content) {
|
|
17065
|
-
const fullPath =
|
|
17254
|
+
const fullPath = path25.join(vaultPath2, notePath);
|
|
17066
17255
|
try {
|
|
17067
|
-
await
|
|
17256
|
+
await fs21.writeFile(fullPath, content, "utf-8");
|
|
17068
17257
|
return true;
|
|
17069
17258
|
} catch {
|
|
17070
17259
|
return false;
|
|
@@ -17182,8 +17371,8 @@ async function migrateFieldValues(index, vaultPath2, field, mapping, options) {
|
|
|
17182
17371
|
}
|
|
17183
17372
|
|
|
17184
17373
|
// src/core/write/tagRename.ts
|
|
17185
|
-
import * as
|
|
17186
|
-
import * as
|
|
17374
|
+
import * as fs22 from "fs/promises";
|
|
17375
|
+
import * as path26 from "path";
|
|
17187
17376
|
import matter4 from "gray-matter";
|
|
17188
17377
|
import { getProtectedZones as getProtectedZones2 } from "@velvetmonkey/vault-core";
|
|
17189
17378
|
function getNotesInFolder3(index, folder) {
|
|
@@ -17289,10 +17478,10 @@ async function renameTag(index, vaultPath2, oldTag, newTag, options) {
|
|
|
17289
17478
|
const previews = [];
|
|
17290
17479
|
let totalChanges = 0;
|
|
17291
17480
|
for (const note of affectedNotes) {
|
|
17292
|
-
const fullPath =
|
|
17481
|
+
const fullPath = path26.join(vaultPath2, note.path);
|
|
17293
17482
|
let fileContent;
|
|
17294
17483
|
try {
|
|
17295
|
-
fileContent = await
|
|
17484
|
+
fileContent = await fs22.readFile(fullPath, "utf-8");
|
|
17296
17485
|
} catch {
|
|
17297
17486
|
continue;
|
|
17298
17487
|
}
|
|
@@ -17365,7 +17554,7 @@ async function renameTag(index, vaultPath2, oldTag, newTag, options) {
|
|
|
17365
17554
|
previews.push(preview);
|
|
17366
17555
|
if (!dryRun) {
|
|
17367
17556
|
const newContent = matter4.stringify(updatedContent, fm);
|
|
17368
|
-
await
|
|
17557
|
+
await fs22.writeFile(fullPath, newContent, "utf-8");
|
|
17369
17558
|
}
|
|
17370
17559
|
}
|
|
17371
17560
|
}
|
|
@@ -17458,8 +17647,8 @@ function registerSchemaTools(server2, getIndex, getVaultPath) {
|
|
|
17458
17647
|
ensureFolder(parentFolder);
|
|
17459
17648
|
folderMap.get(parentFolder).note_count += 1;
|
|
17460
17649
|
}
|
|
17461
|
-
const folders = Array.from(folderMap.entries()).filter(([f]) => f !== "").sort(([a], [b]) => a.localeCompare(b)).map(([
|
|
17462
|
-
path:
|
|
17650
|
+
const folders = Array.from(folderMap.entries()).filter(([f]) => f !== "").sort(([a], [b]) => a.localeCompare(b)).map(([path40, data]) => ({
|
|
17651
|
+
path: path40,
|
|
17463
17652
|
note_count: data.note_count,
|
|
17464
17653
|
subfolder_count: data.subfolders.size
|
|
17465
17654
|
}));
|
|
@@ -17699,12 +17888,246 @@ function getConnectionStrength(index, noteAPath, noteBPath) {
|
|
|
17699
17888
|
|
|
17700
17889
|
// src/tools/read/graphTools.ts
|
|
17701
17890
|
init_wikilinks();
|
|
17891
|
+
|
|
17892
|
+
// src/tools/read/graphExport.ts
|
|
17893
|
+
import { getAllEntitiesFromDb as getAllEntitiesFromDb4 } from "@velvetmonkey/vault-core";
|
|
17894
|
+
init_cooccurrence();
|
|
17895
|
+
function escapeXml(s) {
|
|
17896
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
17897
|
+
}
|
|
17898
|
+
function xmlId(prefix, value) {
|
|
17899
|
+
return `${prefix}:${value}`;
|
|
17900
|
+
}
|
|
17901
|
+
function dataTag(key, value) {
|
|
17902
|
+
if (value === void 0 || value === null) return "";
|
|
17903
|
+
return ` <data key="${key}">${escapeXml(String(value))}</data>
|
|
17904
|
+
`;
|
|
17905
|
+
}
|
|
17906
|
+
function buildGraphData(index, stateDb2, options) {
|
|
17907
|
+
const nodes = [];
|
|
17908
|
+
const edges = [];
|
|
17909
|
+
const noteIds = /* @__PURE__ */ new Set();
|
|
17910
|
+
const entityIds = /* @__PURE__ */ new Set();
|
|
17911
|
+
for (const [notePath, note] of index.notes) {
|
|
17912
|
+
const id = xmlId("note", notePath);
|
|
17913
|
+
noteIds.add(id);
|
|
17914
|
+
nodes.push({
|
|
17915
|
+
id,
|
|
17916
|
+
label: note.title,
|
|
17917
|
+
type: "note",
|
|
17918
|
+
category: typeof note.frontmatter?.type === "string" ? note.frontmatter.type : void 0,
|
|
17919
|
+
modified: note.modified?.toISOString(),
|
|
17920
|
+
tags: note.tags.length > 0 ? note.tags.join(", ") : void 0
|
|
17921
|
+
});
|
|
17922
|
+
}
|
|
17923
|
+
if (stateDb2) {
|
|
17924
|
+
const entities = getAllEntitiesFromDb4(stateDb2);
|
|
17925
|
+
for (const entity of entities) {
|
|
17926
|
+
const id = xmlId("entity", entity.name);
|
|
17927
|
+
if (entityIds.has(id)) continue;
|
|
17928
|
+
entityIds.add(id);
|
|
17929
|
+
nodes.push({
|
|
17930
|
+
id,
|
|
17931
|
+
label: entity.name,
|
|
17932
|
+
type: "entity",
|
|
17933
|
+
category: entity.category,
|
|
17934
|
+
hub_score: entity.hubScore,
|
|
17935
|
+
aliases: entity.aliases.length > 0 ? entity.aliases.join(", ") : void 0
|
|
17936
|
+
});
|
|
17937
|
+
}
|
|
17938
|
+
}
|
|
17939
|
+
const seenWikilinks = /* @__PURE__ */ new Set();
|
|
17940
|
+
for (const [notePath, note] of index.notes) {
|
|
17941
|
+
const sourceId = xmlId("note", notePath);
|
|
17942
|
+
for (const link of note.outlinks) {
|
|
17943
|
+
const resolved = resolveTarget(index, link.target);
|
|
17944
|
+
if (!resolved) continue;
|
|
17945
|
+
const targetId = xmlId("note", resolved);
|
|
17946
|
+
const edgeKey = `${sourceId}\u2192${targetId}`;
|
|
17947
|
+
if (seenWikilinks.has(edgeKey)) continue;
|
|
17948
|
+
seenWikilinks.add(edgeKey);
|
|
17949
|
+
edges.push({
|
|
17950
|
+
source: sourceId,
|
|
17951
|
+
target: targetId,
|
|
17952
|
+
edge_type: "wikilink",
|
|
17953
|
+
weight: 1
|
|
17954
|
+
});
|
|
17955
|
+
}
|
|
17956
|
+
}
|
|
17957
|
+
if (stateDb2) {
|
|
17958
|
+
const rows = stateDb2.db.prepare(
|
|
17959
|
+
"SELECT note_path, target, weight FROM note_links WHERE weight >= ?"
|
|
17960
|
+
).all(options.min_edge_weight);
|
|
17961
|
+
for (const row of rows) {
|
|
17962
|
+
const sourceId = xmlId("note", row.note_path);
|
|
17963
|
+
if (!noteIds.has(sourceId)) continue;
|
|
17964
|
+
const targetLower = row.target.toLowerCase();
|
|
17965
|
+
let targetId;
|
|
17966
|
+
if (entityIds.has(xmlId("entity", row.target))) {
|
|
17967
|
+
targetId = xmlId("entity", row.target);
|
|
17968
|
+
} else {
|
|
17969
|
+
for (const node of nodes) {
|
|
17970
|
+
if (node.type !== "entity") continue;
|
|
17971
|
+
if (node.label.toLowerCase() === targetLower) {
|
|
17972
|
+
targetId = node.id;
|
|
17973
|
+
break;
|
|
17974
|
+
}
|
|
17975
|
+
if (node.aliases) {
|
|
17976
|
+
const aliases = node.aliases.split(", ").map((alias) => alias.toLowerCase());
|
|
17977
|
+
if (aliases.includes(targetLower)) {
|
|
17978
|
+
targetId = node.id;
|
|
17979
|
+
break;
|
|
17980
|
+
}
|
|
17981
|
+
}
|
|
17982
|
+
}
|
|
17983
|
+
}
|
|
17984
|
+
if (!targetId) continue;
|
|
17985
|
+
edges.push({
|
|
17986
|
+
source: sourceId,
|
|
17987
|
+
target: targetId,
|
|
17988
|
+
edge_type: "weighted",
|
|
17989
|
+
weight: row.weight
|
|
17990
|
+
});
|
|
17991
|
+
}
|
|
17992
|
+
}
|
|
17993
|
+
if (options.include_cooccurrence && stateDb2) {
|
|
17994
|
+
const cached = loadCooccurrenceFromStateDb(stateDb2);
|
|
17995
|
+
if (cached) {
|
|
17996
|
+
const seenCooccurrence = /* @__PURE__ */ new Set();
|
|
17997
|
+
for (const [entityName, associations] of Object.entries(cached.index.associations)) {
|
|
17998
|
+
const sourceId = xmlId("entity", entityName);
|
|
17999
|
+
if (!entityIds.has(sourceId)) continue;
|
|
18000
|
+
for (const [relatedName, count] of associations) {
|
|
18001
|
+
const targetId = xmlId("entity", relatedName);
|
|
18002
|
+
if (!entityIds.has(targetId)) continue;
|
|
18003
|
+
const pairKey = [entityName, relatedName].sort().join("\u2194");
|
|
18004
|
+
if (seenCooccurrence.has(pairKey)) continue;
|
|
18005
|
+
seenCooccurrence.add(pairKey);
|
|
18006
|
+
edges.push({
|
|
18007
|
+
source: sourceId,
|
|
18008
|
+
target: targetId,
|
|
18009
|
+
edge_type: "cooccurrence",
|
|
18010
|
+
weight: count
|
|
18011
|
+
});
|
|
18012
|
+
}
|
|
18013
|
+
}
|
|
18014
|
+
}
|
|
18015
|
+
}
|
|
18016
|
+
if (options.center_entity) {
|
|
18017
|
+
const centerLower = options.center_entity.toLowerCase();
|
|
18018
|
+
const maxDepth = options.depth ?? 1;
|
|
18019
|
+
const centerNode = nodes.find((node) => node.label.toLowerCase() === centerLower);
|
|
18020
|
+
if (centerNode) {
|
|
18021
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
18022
|
+
for (const edge of edges) {
|
|
18023
|
+
if (!adjacency.has(edge.source)) adjacency.set(edge.source, /* @__PURE__ */ new Set());
|
|
18024
|
+
if (!adjacency.has(edge.target)) adjacency.set(edge.target, /* @__PURE__ */ new Set());
|
|
18025
|
+
adjacency.get(edge.source).add(edge.target);
|
|
18026
|
+
adjacency.get(edge.target).add(edge.source);
|
|
18027
|
+
}
|
|
18028
|
+
const reachable = /* @__PURE__ */ new Set([centerNode.id]);
|
|
18029
|
+
const queue = [{ id: centerNode.id, depth: 0 }];
|
|
18030
|
+
while (queue.length > 0) {
|
|
18031
|
+
const current = queue.shift();
|
|
18032
|
+
if (current.depth >= maxDepth) continue;
|
|
18033
|
+
for (const neighbor of adjacency.get(current.id) ?? []) {
|
|
18034
|
+
if (reachable.has(neighbor)) continue;
|
|
18035
|
+
reachable.add(neighbor);
|
|
18036
|
+
queue.push({ id: neighbor, depth: current.depth + 1 });
|
|
18037
|
+
}
|
|
18038
|
+
}
|
|
18039
|
+
const filteredNodes = nodes.filter((node) => reachable.has(node.id));
|
|
18040
|
+
const filteredEdges = edges.filter(
|
|
18041
|
+
(edge) => reachable.has(edge.source) && reachable.has(edge.target)
|
|
18042
|
+
);
|
|
18043
|
+
return {
|
|
18044
|
+
nodes: filteredNodes,
|
|
18045
|
+
edges: filteredEdges,
|
|
18046
|
+
metadata: {
|
|
18047
|
+
note_count: filteredNodes.filter((node) => node.type === "note").length,
|
|
18048
|
+
entity_count: filteredNodes.filter((node) => node.type === "entity").length,
|
|
18049
|
+
edge_count: filteredEdges.length,
|
|
18050
|
+
exported_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
18051
|
+
}
|
|
18052
|
+
};
|
|
18053
|
+
}
|
|
18054
|
+
}
|
|
18055
|
+
return {
|
|
18056
|
+
nodes,
|
|
18057
|
+
edges,
|
|
18058
|
+
metadata: {
|
|
18059
|
+
note_count: index.notes.size,
|
|
18060
|
+
entity_count: entityIds.size,
|
|
18061
|
+
edge_count: edges.length,
|
|
18062
|
+
exported_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
18063
|
+
}
|
|
18064
|
+
};
|
|
18065
|
+
}
|
|
18066
|
+
function toGraphML(data) {
|
|
18067
|
+
let xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
18068
|
+
`;
|
|
18069
|
+
xml += `<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
|
|
18070
|
+
`;
|
|
18071
|
+
xml += ` xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
18072
|
+
`;
|
|
18073
|
+
xml += ` xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
|
|
18074
|
+
`;
|
|
18075
|
+
xml += ` <key id="label" for="node" attr.name="label" attr.type="string"/>
|
|
18076
|
+
`;
|
|
18077
|
+
xml += ` <key id="type" for="node" attr.name="type" attr.type="string"/>
|
|
18078
|
+
`;
|
|
18079
|
+
xml += ` <key id="category" for="node" attr.name="category" attr.type="string"/>
|
|
18080
|
+
`;
|
|
18081
|
+
xml += ` <key id="hub_score" for="node" attr.name="hub_score" attr.type="double"/>
|
|
18082
|
+
`;
|
|
18083
|
+
xml += ` <key id="modified" for="node" attr.name="modified" attr.type="string"/>
|
|
18084
|
+
`;
|
|
18085
|
+
xml += ` <key id="tags" for="node" attr.name="tags" attr.type="string"/>
|
|
18086
|
+
`;
|
|
18087
|
+
xml += ` <key id="aliases" for="node" attr.name="aliases" attr.type="string"/>
|
|
18088
|
+
`;
|
|
18089
|
+
xml += ` <key id="edge_type" for="edge" attr.name="edge_type" attr.type="string"/>
|
|
18090
|
+
`;
|
|
18091
|
+
xml += ` <key id="weight" for="edge" attr.name="weight" attr.type="double"/>
|
|
18092
|
+
`;
|
|
18093
|
+
xml += ` <graph id="vault" edgedefault="directed">
|
|
18094
|
+
`;
|
|
18095
|
+
for (const node of data.nodes) {
|
|
18096
|
+
xml += ` <node id="${escapeXml(node.id)}">
|
|
18097
|
+
`;
|
|
18098
|
+
xml += dataTag("label", node.label);
|
|
18099
|
+
xml += dataTag("type", node.type);
|
|
18100
|
+
xml += dataTag("category", node.category);
|
|
18101
|
+
xml += dataTag("hub_score", node.hub_score);
|
|
18102
|
+
xml += dataTag("modified", node.modified);
|
|
18103
|
+
xml += dataTag("tags", node.tags);
|
|
18104
|
+
xml += dataTag("aliases", node.aliases);
|
|
18105
|
+
xml += ` </node>
|
|
18106
|
+
`;
|
|
18107
|
+
}
|
|
18108
|
+
let edgeIndex = 0;
|
|
18109
|
+
for (const edge of data.edges) {
|
|
18110
|
+
xml += ` <edge id="e${edgeIndex++}" source="${escapeXml(edge.source)}" target="${escapeXml(edge.target)}">
|
|
18111
|
+
`;
|
|
18112
|
+
xml += dataTag("edge_type", edge.edge_type);
|
|
18113
|
+
xml += dataTag("weight", edge.weight);
|
|
18114
|
+
xml += ` </edge>
|
|
18115
|
+
`;
|
|
18116
|
+
}
|
|
18117
|
+
xml += ` </graph>
|
|
18118
|
+
`;
|
|
18119
|
+
xml += `</graphml>
|
|
18120
|
+
`;
|
|
18121
|
+
return xml;
|
|
18122
|
+
}
|
|
18123
|
+
|
|
18124
|
+
// src/tools/read/graphTools.ts
|
|
17702
18125
|
function registerGraphTools2(server2, getIndex, getVaultPath, getStateDb4) {
|
|
17703
18126
|
server2.registerTool(
|
|
17704
18127
|
"graph",
|
|
17705
18128
|
{
|
|
17706
18129
|
title: "Graph",
|
|
17707
|
-
description:
|
|
18130
|
+
description: "Vault graph analysis. action: analyse \u2014 hubs/orphans/clusters. action: backlinks/forward_links \u2014 links to/from note. action: strong_connections \u2014 top links. action: path \u2014 shortest chain. action: neighbors \u2014 shared connections. action: strength \u2014 link weight. action: cooccurrence_gaps \u2014 unlinked co-occurring pairs. action: export \u2014 GraphML or JSON export for Gephi, yEd, Cytoscape, or code. Returns metrics, links, paths, gaps, or serialized graph data. Does not modify notes.",
|
|
17708
18131
|
inputSchema: {
|
|
17709
18132
|
action: z10.enum([
|
|
17710
18133
|
"analyse",
|
|
@@ -17714,7 +18137,8 @@ function registerGraphTools2(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
17714
18137
|
"path",
|
|
17715
18138
|
"neighbors",
|
|
17716
18139
|
"strength",
|
|
17717
|
-
"cooccurrence_gaps"
|
|
18140
|
+
"cooccurrence_gaps",
|
|
18141
|
+
"export"
|
|
17718
18142
|
]).describe("Graph operation to perform"),
|
|
17719
18143
|
limit: z10.coerce.number().optional().describe("[analyse|cooccurrence_gaps] Maximum results to return"),
|
|
17720
18144
|
path: z10.string().optional().describe("[backlinks|forward_links|strong_connections] Note path"),
|
|
@@ -17722,7 +18146,13 @@ function registerGraphTools2(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
17722
18146
|
to: z10.string().optional().describe("[path] Target note path"),
|
|
17723
18147
|
path_a: z10.string().optional().describe("[neighbors|strength] First note path"),
|
|
17724
18148
|
path_b: z10.string().optional().describe("[neighbors|strength] Second note path"),
|
|
17725
|
-
entity: z10.string().optional().describe("[cooccurrence_gaps] Entity name to find gaps for")
|
|
18149
|
+
entity: z10.string().optional().describe("[cooccurrence_gaps] Entity name to find gaps for"),
|
|
18150
|
+
format: z10.enum(["graphml", "json"]).optional().describe("[export] Output format: graphml for Gephi/yEd/Cytoscape, json for programmatic use"),
|
|
18151
|
+
include_cooccurrence: z10.boolean().optional().describe("[export] Include co-occurrence edges between entities (default true)"),
|
|
18152
|
+
min_edge_weight: z10.coerce.number().optional().describe("[export] Minimum edge weight threshold for learned weighted edges"),
|
|
18153
|
+
center_entity: z10.string().optional().describe("[export] Center the export on this entity; only include nodes within depth hops"),
|
|
18154
|
+
depth: z10.coerce.number().optional().describe("[export] Hops from center_entity to include (default 1)"),
|
|
18155
|
+
max_nodes: z10.coerce.number().optional().describe("[export] Maximum nodes when center_entity is omitted (default 500)")
|
|
17726
18156
|
}
|
|
17727
18157
|
},
|
|
17728
18158
|
async (params) => {
|
|
@@ -17979,6 +18409,43 @@ function registerGraphTools2(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
17979
18409
|
}, null, 2) }]
|
|
17980
18410
|
};
|
|
17981
18411
|
}
|
|
18412
|
+
// -----------------------------------------------------------------
|
|
18413
|
+
// export — scoped/full graph export as GraphML or JSON
|
|
18414
|
+
// -----------------------------------------------------------------
|
|
18415
|
+
case "export": {
|
|
18416
|
+
const stateDb2 = getStateDb4?.() ?? null;
|
|
18417
|
+
const format = params.format ?? "graphml";
|
|
18418
|
+
const includeCooccurrence = params.include_cooccurrence ?? true;
|
|
18419
|
+
const minEdgeWeight = params.min_edge_weight ?? 0;
|
|
18420
|
+
const depth = params.depth ?? 1;
|
|
18421
|
+
const maxNodes = params.max_nodes ?? 500;
|
|
18422
|
+
const data = buildGraphData(index, stateDb2, {
|
|
18423
|
+
include_cooccurrence: includeCooccurrence,
|
|
18424
|
+
min_edge_weight: minEdgeWeight,
|
|
18425
|
+
center_entity: params.center_entity,
|
|
18426
|
+
depth
|
|
18427
|
+
});
|
|
18428
|
+
if (!params.center_entity && data.nodes.length > maxNodes) {
|
|
18429
|
+
return {
|
|
18430
|
+
content: [{
|
|
18431
|
+
type: "text",
|
|
18432
|
+
text: JSON.stringify({
|
|
18433
|
+
error: `Graph has ${data.nodes.length} nodes and ${data.edges.length} edges, exceeding max_nodes=${maxNodes}. Use center_entity to scope the export or raise max_nodes.`,
|
|
18434
|
+
node_count: data.nodes.length,
|
|
18435
|
+
edge_count: data.edges.length,
|
|
18436
|
+
max_nodes: maxNodes
|
|
18437
|
+
}, null, 2)
|
|
18438
|
+
}],
|
|
18439
|
+
isError: true
|
|
18440
|
+
};
|
|
18441
|
+
}
|
|
18442
|
+
return {
|
|
18443
|
+
content: [{
|
|
18444
|
+
type: "text",
|
|
18445
|
+
text: format === "json" ? JSON.stringify(data, null, 2) : toGraphML(data)
|
|
18446
|
+
}]
|
|
18447
|
+
};
|
|
18448
|
+
}
|
|
17982
18449
|
}
|
|
17983
18450
|
}
|
|
17984
18451
|
);
|
|
@@ -17988,15 +18455,15 @@ function registerGraphTools2(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
17988
18455
|
import { z as z11 } from "zod";
|
|
17989
18456
|
|
|
17990
18457
|
// src/tools/read/bidirectional.ts
|
|
17991
|
-
import * as
|
|
17992
|
-
import * as
|
|
18458
|
+
import * as fs23 from "fs/promises";
|
|
18459
|
+
import * as path27 from "path";
|
|
17993
18460
|
import matter5 from "gray-matter";
|
|
17994
18461
|
var PROSE_PATTERN_REGEX = /^([A-Za-z][A-Za-z0-9 _-]*):\s*(?:\[\[([^\]]+)\]\]|"([^"]+)"|([^\n]+?))\s*$/gm;
|
|
17995
18462
|
var CODE_BLOCK_REGEX2 = /```[\s\S]*?```|`[^`\n]+`/g;
|
|
17996
18463
|
async function readFileContent2(notePath, vaultPath2) {
|
|
17997
|
-
const fullPath =
|
|
18464
|
+
const fullPath = path27.join(vaultPath2, notePath);
|
|
17998
18465
|
try {
|
|
17999
|
-
return await
|
|
18466
|
+
return await fs23.readFile(fullPath, "utf-8");
|
|
18000
18467
|
} catch {
|
|
18001
18468
|
return null;
|
|
18002
18469
|
}
|
|
@@ -18172,21 +18639,21 @@ async function suggestWikilinksInFrontmatter(index, notePath, vaultPath2) {
|
|
|
18172
18639
|
}
|
|
18173
18640
|
|
|
18174
18641
|
// src/tools/read/computed.ts
|
|
18175
|
-
import * as
|
|
18176
|
-
import * as
|
|
18642
|
+
import * as fs24 from "fs/promises";
|
|
18643
|
+
import * as path28 from "path";
|
|
18177
18644
|
import matter6 from "gray-matter";
|
|
18178
18645
|
async function readFileContent3(notePath, vaultPath2) {
|
|
18179
|
-
const fullPath =
|
|
18646
|
+
const fullPath = path28.join(vaultPath2, notePath);
|
|
18180
18647
|
try {
|
|
18181
|
-
return await
|
|
18648
|
+
return await fs24.readFile(fullPath, "utf-8");
|
|
18182
18649
|
} catch {
|
|
18183
18650
|
return null;
|
|
18184
18651
|
}
|
|
18185
18652
|
}
|
|
18186
18653
|
async function getFileStats(notePath, vaultPath2) {
|
|
18187
|
-
const fullPath =
|
|
18654
|
+
const fullPath = path28.join(vaultPath2, notePath);
|
|
18188
18655
|
try {
|
|
18189
|
-
const stats = await
|
|
18656
|
+
const stats = await fs24.stat(fullPath);
|
|
18190
18657
|
return {
|
|
18191
18658
|
modified: stats.mtime,
|
|
18192
18659
|
created: stats.birthtime
|
|
@@ -18773,7 +19240,7 @@ function registerFrontmatterTools(server2, getVaultPath) {
|
|
|
18773
19240
|
}
|
|
18774
19241
|
|
|
18775
19242
|
// src/tools/write/policy.ts
|
|
18776
|
-
import * as
|
|
19243
|
+
import * as path33 from "path";
|
|
18777
19244
|
import { z as z14 } from "zod";
|
|
18778
19245
|
|
|
18779
19246
|
// src/core/write/policy/index.ts
|
|
@@ -18782,8 +19249,8 @@ init_schema();
|
|
|
18782
19249
|
|
|
18783
19250
|
// src/core/write/policy/parser.ts
|
|
18784
19251
|
init_schema();
|
|
18785
|
-
import
|
|
18786
|
-
import
|
|
19252
|
+
import fs25 from "fs/promises";
|
|
19253
|
+
import path29 from "path";
|
|
18787
19254
|
import matter7 from "gray-matter";
|
|
18788
19255
|
function parseYaml(content) {
|
|
18789
19256
|
const parsed = matter7(`---
|
|
@@ -18808,7 +19275,7 @@ function parsePolicyString(yamlContent) {
|
|
|
18808
19275
|
}
|
|
18809
19276
|
async function loadPolicyFile(filePath) {
|
|
18810
19277
|
try {
|
|
18811
|
-
const content = await
|
|
19278
|
+
const content = await fs25.readFile(filePath, "utf-8");
|
|
18812
19279
|
return parsePolicyString(content);
|
|
18813
19280
|
} catch (error) {
|
|
18814
19281
|
if (error.code === "ENOENT") {
|
|
@@ -18834,14 +19301,14 @@ async function loadPolicyFile(filePath) {
|
|
|
18834
19301
|
async function loadPolicy(vaultPath2, policyName) {
|
|
18835
19302
|
await ensureMigrated(vaultPath2);
|
|
18836
19303
|
const policiesDir = getPoliciesDir(vaultPath2);
|
|
18837
|
-
const policyPath =
|
|
19304
|
+
const policyPath = path29.join(policiesDir, `${policyName}.yaml`);
|
|
18838
19305
|
try {
|
|
18839
|
-
await
|
|
19306
|
+
await fs25.access(policyPath);
|
|
18840
19307
|
return loadPolicyFile(policyPath);
|
|
18841
19308
|
} catch {
|
|
18842
|
-
const ymlPath =
|
|
19309
|
+
const ymlPath = path29.join(policiesDir, `${policyName}.yml`);
|
|
18843
19310
|
try {
|
|
18844
|
-
await
|
|
19311
|
+
await fs25.access(ymlPath);
|
|
18845
19312
|
return loadPolicyFile(ymlPath);
|
|
18846
19313
|
} catch {
|
|
18847
19314
|
return {
|
|
@@ -18981,8 +19448,8 @@ init_schema();
|
|
|
18981
19448
|
init_writer();
|
|
18982
19449
|
init_git();
|
|
18983
19450
|
init_wikilinks();
|
|
18984
|
-
import
|
|
18985
|
-
import
|
|
19451
|
+
import fs27 from "fs/promises";
|
|
19452
|
+
import path31 from "path";
|
|
18986
19453
|
init_constants2();
|
|
18987
19454
|
async function executeStep(step, vaultPath2, context, conditionResults, searchFn) {
|
|
18988
19455
|
const { execute, reason } = shouldStepExecute(step.when, conditionResults);
|
|
@@ -19173,12 +19640,12 @@ async function executeCreateNote2(params, vaultPath2, context) {
|
|
|
19173
19640
|
let frontmatter = params.frontmatter || {};
|
|
19174
19641
|
if (params.template) {
|
|
19175
19642
|
try {
|
|
19176
|
-
const templatePath =
|
|
19177
|
-
const raw = await
|
|
19643
|
+
const templatePath = path31.join(vaultPath2, String(params.template));
|
|
19644
|
+
const raw = await fs27.readFile(templatePath, "utf-8");
|
|
19178
19645
|
const matter10 = (await import("gray-matter")).default;
|
|
19179
19646
|
const parsed = matter10(raw);
|
|
19180
19647
|
const dateStr = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
19181
|
-
const title =
|
|
19648
|
+
const title = path31.basename(notePath, ".md");
|
|
19182
19649
|
let templateContent = parsed.content.replace(/\{\{date\}\}/g, dateStr).replace(/\{\{title\}\}/g, title);
|
|
19183
19650
|
if (content) {
|
|
19184
19651
|
templateContent = templateContent.trimEnd() + "\n\n" + content;
|
|
@@ -19211,9 +19678,9 @@ async function executeToggleTask(params, vaultPath2) {
|
|
|
19211
19678
|
const notePath = String(params.path || "");
|
|
19212
19679
|
const task = String(params.task || "");
|
|
19213
19680
|
const section = params.section ? String(params.section) : void 0;
|
|
19214
|
-
const fullPath =
|
|
19681
|
+
const fullPath = path31.join(vaultPath2, notePath);
|
|
19215
19682
|
try {
|
|
19216
|
-
await
|
|
19683
|
+
await fs27.access(fullPath);
|
|
19217
19684
|
} catch {
|
|
19218
19685
|
return { success: false, message: `File not found: ${notePath}`, path: notePath };
|
|
19219
19686
|
}
|
|
@@ -19494,15 +19961,15 @@ async function rollbackChanges(vaultPath2, originalContents, filesModified) {
|
|
|
19494
19961
|
const pathCheck = await validatePathSecure(vaultPath2, filePath);
|
|
19495
19962
|
if (!pathCheck.valid) continue;
|
|
19496
19963
|
const original = originalContents.get(filePath);
|
|
19497
|
-
const fullPath =
|
|
19964
|
+
const fullPath = path31.join(vaultPath2, filePath);
|
|
19498
19965
|
if (original === null) {
|
|
19499
19966
|
try {
|
|
19500
|
-
await
|
|
19967
|
+
await fs27.unlink(fullPath);
|
|
19501
19968
|
} catch {
|
|
19502
19969
|
}
|
|
19503
19970
|
} else if (original !== void 0) {
|
|
19504
19971
|
try {
|
|
19505
|
-
await
|
|
19972
|
+
await fs27.writeFile(fullPath, original);
|
|
19506
19973
|
} catch {
|
|
19507
19974
|
}
|
|
19508
19975
|
}
|
|
@@ -19548,21 +20015,21 @@ async function previewPolicy(policy, vaultPath2, variables) {
|
|
|
19548
20015
|
}
|
|
19549
20016
|
|
|
19550
20017
|
// src/core/write/policy/storage.ts
|
|
19551
|
-
import
|
|
19552
|
-
import
|
|
20018
|
+
import fs28 from "fs/promises";
|
|
20019
|
+
import path32 from "path";
|
|
19553
20020
|
async function listPolicies(vaultPath2) {
|
|
19554
20021
|
await ensureMigrated(vaultPath2);
|
|
19555
20022
|
const dir = getPoliciesDir(vaultPath2);
|
|
19556
20023
|
const policies = [];
|
|
19557
20024
|
try {
|
|
19558
|
-
const files = await
|
|
20025
|
+
const files = await fs28.readdir(dir);
|
|
19559
20026
|
for (const file of files) {
|
|
19560
20027
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) {
|
|
19561
20028
|
continue;
|
|
19562
20029
|
}
|
|
19563
|
-
const filePath =
|
|
19564
|
-
const stat4 = await
|
|
19565
|
-
const content = await
|
|
20030
|
+
const filePath = path32.join(dir, file);
|
|
20031
|
+
const stat4 = await fs28.stat(filePath);
|
|
20032
|
+
const content = await fs28.readFile(filePath, "utf-8");
|
|
19566
20033
|
const metadata = extractPolicyMetadata(content);
|
|
19567
20034
|
policies.push({
|
|
19568
20035
|
name: metadata.name || file.replace(/\.ya?ml$/, ""),
|
|
@@ -19586,10 +20053,10 @@ async function writePolicyRaw(vaultPath2, policyName, content, overwrite = false
|
|
|
19586
20053
|
const dir = getPoliciesDir(vaultPath2);
|
|
19587
20054
|
await ensurePoliciesDir(vaultPath2);
|
|
19588
20055
|
const filename = `${policyName}.yaml`;
|
|
19589
|
-
const filePath =
|
|
20056
|
+
const filePath = path32.join(dir, filename);
|
|
19590
20057
|
if (!overwrite) {
|
|
19591
20058
|
try {
|
|
19592
|
-
await
|
|
20059
|
+
await fs28.access(filePath);
|
|
19593
20060
|
return {
|
|
19594
20061
|
success: false,
|
|
19595
20062
|
path: filename,
|
|
@@ -19606,7 +20073,7 @@ async function writePolicyRaw(vaultPath2, policyName, content, overwrite = false
|
|
|
19606
20073
|
message: `Invalid policy: ${validation.errors.map((e) => e.message).join("; ")}`
|
|
19607
20074
|
};
|
|
19608
20075
|
}
|
|
19609
|
-
await
|
|
20076
|
+
await fs28.writeFile(filePath, content, "utf-8");
|
|
19610
20077
|
return {
|
|
19611
20078
|
success: true,
|
|
19612
20079
|
path: filename,
|
|
@@ -19693,7 +20160,7 @@ function registerPolicyTools(server2, getVaultPath, getSearchFn) {
|
|
|
19693
20160
|
const policies = await listPolicies(vaultPath2);
|
|
19694
20161
|
const response = {
|
|
19695
20162
|
success: true,
|
|
19696
|
-
vault:
|
|
20163
|
+
vault: path33.basename(vaultPath2),
|
|
19697
20164
|
vault_path: vaultPath2,
|
|
19698
20165
|
count: policies.length,
|
|
19699
20166
|
policies: policies.map((p) => ({
|
|
@@ -20138,9 +20605,9 @@ function registerCorrectTool(server2, getStateDb4, getVaultPath) {
|
|
|
20138
20605
|
limit: z15.number().optional().describe("[list] Maximum corrections to return"),
|
|
20139
20606
|
correction_id: z15.string().optional().describe("[resolve] ID of the correction to mark resolved")
|
|
20140
20607
|
},
|
|
20141
|
-
async ({ action, path:
|
|
20608
|
+
async ({ action, path: path40, entity, note, limit, correction_id }) => {
|
|
20142
20609
|
if (action === "record") {
|
|
20143
|
-
if (!
|
|
20610
|
+
if (!path40) {
|
|
20144
20611
|
return {
|
|
20145
20612
|
content: [{ type: "text", text: JSON.stringify({ error: "path is required for action: record" }) }],
|
|
20146
20613
|
isError: true
|
|
@@ -20165,7 +20632,7 @@ function registerCorrectTool(server2, getStateDb4, getVaultPath) {
|
|
|
20165
20632
|
isError: true
|
|
20166
20633
|
};
|
|
20167
20634
|
}
|
|
20168
|
-
const correction = recordCorrection(stateDb2, "general", note, "user", entity,
|
|
20635
|
+
const correction = recordCorrection(stateDb2, "general", note, "user", entity, path40);
|
|
20169
20636
|
return {
|
|
20170
20637
|
content: [{
|
|
20171
20638
|
type: "text",
|
|
@@ -20182,10 +20649,10 @@ function registerCorrectTool(server2, getStateDb4, getVaultPath) {
|
|
|
20182
20649
|
};
|
|
20183
20650
|
}
|
|
20184
20651
|
let corrections;
|
|
20185
|
-
if (
|
|
20652
|
+
if (path40) {
|
|
20186
20653
|
corrections = stateDb2.db.prepare(
|
|
20187
20654
|
`SELECT * FROM corrections WHERE note_path = ? ORDER BY created_at DESC LIMIT ?`
|
|
20188
|
-
).all(
|
|
20655
|
+
).all(path40, limit ?? 50);
|
|
20189
20656
|
} else {
|
|
20190
20657
|
corrections = listCorrections(stateDb2, void 0, void 0, limit ?? 50);
|
|
20191
20658
|
}
|
|
@@ -20299,7 +20766,7 @@ Message: ${undoResult.undoneCommit.message}` : void 0
|
|
|
20299
20766
|
// src/tools/write/entity.ts
|
|
20300
20767
|
init_embeddings();
|
|
20301
20768
|
import { z as z17 } from "zod";
|
|
20302
|
-
import { getEntityIndexFromDb as getEntityIndexFromDb3, getAllEntitiesFromDb as
|
|
20769
|
+
import { getEntityIndexFromDb as getEntityIndexFromDb3, getAllEntitiesFromDb as getAllEntitiesFromDb5, getDismissedMergePairs, recordMergeDismissal } from "@velvetmonkey/vault-core";
|
|
20303
20770
|
|
|
20304
20771
|
// src/core/read/aliasSuggestions.ts
|
|
20305
20772
|
import { STOPWORDS_EN as STOPWORDS_EN4 } from "@velvetmonkey/vault-core";
|
|
@@ -20376,8 +20843,8 @@ init_writer();
|
|
|
20376
20843
|
init_git();
|
|
20377
20844
|
init_wikilinks();
|
|
20378
20845
|
import { z as z16 } from "zod";
|
|
20379
|
-
import
|
|
20380
|
-
import
|
|
20846
|
+
import fs29 from "fs/promises";
|
|
20847
|
+
import path34 from "path";
|
|
20381
20848
|
import matter8 from "gray-matter";
|
|
20382
20849
|
function escapeRegex(str) {
|
|
20383
20850
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -20396,16 +20863,16 @@ function extractWikilinks2(content) {
|
|
|
20396
20863
|
return wikilinks;
|
|
20397
20864
|
}
|
|
20398
20865
|
function getTitleFromPath(filePath) {
|
|
20399
|
-
return
|
|
20866
|
+
return path34.basename(filePath, ".md");
|
|
20400
20867
|
}
|
|
20401
20868
|
async function findBacklinks(vaultPath2, targetTitle, targetAliases) {
|
|
20402
20869
|
const results = [];
|
|
20403
20870
|
const allTargets = [targetTitle, ...targetAliases].map((t) => t.toLowerCase());
|
|
20404
20871
|
async function scanDir(dir) {
|
|
20405
20872
|
const files = [];
|
|
20406
|
-
const entries = await
|
|
20873
|
+
const entries = await fs29.readdir(dir, { withFileTypes: true });
|
|
20407
20874
|
for (const entry of entries) {
|
|
20408
|
-
const fullPath =
|
|
20875
|
+
const fullPath = path34.join(dir, entry.name);
|
|
20409
20876
|
if (entry.isDirectory() && !entry.name.startsWith(".")) {
|
|
20410
20877
|
files.push(...await scanDir(fullPath));
|
|
20411
20878
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -20416,8 +20883,8 @@ async function findBacklinks(vaultPath2, targetTitle, targetAliases) {
|
|
|
20416
20883
|
}
|
|
20417
20884
|
const allFiles = await scanDir(vaultPath2);
|
|
20418
20885
|
for (const filePath of allFiles) {
|
|
20419
|
-
const relativePath =
|
|
20420
|
-
const content = await
|
|
20886
|
+
const relativePath = path34.relative(vaultPath2, filePath);
|
|
20887
|
+
const content = await fs29.readFile(filePath, "utf-8");
|
|
20421
20888
|
const wikilinks = extractWikilinks2(content);
|
|
20422
20889
|
const matchingLinks = [];
|
|
20423
20890
|
for (const link of wikilinks) {
|
|
@@ -20475,13 +20942,14 @@ function extractAliases2(frontmatter) {
|
|
|
20475
20942
|
}
|
|
20476
20943
|
|
|
20477
20944
|
// src/tools/write/entity.ts
|
|
20478
|
-
|
|
20945
|
+
init_prospects();
|
|
20946
|
+
import fs30 from "fs/promises";
|
|
20479
20947
|
function registerEntityTool(server2, getVaultPath, getStateDb4, getIndex) {
|
|
20480
20948
|
server2.tool(
|
|
20481
20949
|
"entity",
|
|
20482
|
-
|
|
20950
|
+
"Manage vault entities and aliases. action: list \u2014 browse by category. alias \u2014 add an alternate name. suggest_aliases \u2014 find missing aliases. merge \u2014 absorb one entity into another and rewire links. suggest_merges \u2014 find duplicates. dismiss_merge \u2014 mark a merge suggestion incorrect. dismiss_prospect \u2014 reject an unresolved prospect term so it stops surfacing as an active stub candidate. Returns lists, results, or candidates. Does not create notes.",
|
|
20483
20951
|
{
|
|
20484
|
-
action: z17.enum(["list", "alias", "suggest_aliases", "merge", "suggest_merges", "dismiss_merge"]).describe("Operation to perform"),
|
|
20952
|
+
action: z17.enum(["list", "alias", "suggest_aliases", "merge", "suggest_merges", "dismiss_merge", "dismiss_prospect"]).describe("Operation to perform"),
|
|
20485
20953
|
query: z17.string().optional().describe("[list] Filter entities by name substring"),
|
|
20486
20954
|
category: z17.string().optional().describe("[list|suggest_aliases] Filter to a specific category"),
|
|
20487
20955
|
limit: z17.number().optional().describe("[list|suggest_aliases|suggest_merges] Maximum results to return"),
|
|
@@ -20493,9 +20961,11 @@ function registerEntityTool(server2, getVaultPath, getStateDb4, getIndex) {
|
|
|
20493
20961
|
target_path: z17.string().optional().describe("[dismiss_merge] Target entity path"),
|
|
20494
20962
|
source_name: z17.string().optional().describe("[dismiss_merge] Source entity name"),
|
|
20495
20963
|
target_name: z17.string().optional().describe("[dismiss_merge] Target entity name"),
|
|
20496
|
-
reason: z17.string().optional().describe("[dismiss_merge] Reason for the original suggestion")
|
|
20964
|
+
reason: z17.string().optional().describe("[dismiss_merge] Reason for the original suggestion"),
|
|
20965
|
+
prospect: z17.string().optional().describe("[dismiss_prospect] Prospect term or display name to reject"),
|
|
20966
|
+
note_path: z17.string().optional().describe("[dismiss_prospect] Optional note path that motivated the dismissal")
|
|
20497
20967
|
},
|
|
20498
|
-
async ({ action, query, category, limit, entity, alias, primary, secondary, source_path, target_path, source_name, target_name, reason }) => {
|
|
20968
|
+
async ({ action, query, category, limit, entity, alias, primary, secondary, source_path, target_path, source_name, target_name, reason, prospect, note_path }) => {
|
|
20499
20969
|
const stateDb2 = getStateDb4();
|
|
20500
20970
|
if (action === "list") {
|
|
20501
20971
|
if (!stateDb2) {
|
|
@@ -20606,6 +21076,7 @@ function registerEntityTool(server2, getVaultPath, getStateDb4, getIndex) {
|
|
|
20606
21076
|
}
|
|
20607
21077
|
fileData.frontmatter.aliases = Array.from(deduped);
|
|
20608
21078
|
await writeVaultFile(vaultPath2, entity, fileData.content, fileData.frontmatter, fileData.lineEnding, fileData.contentHash);
|
|
21079
|
+
const resolvedProspects = resolveProspectForAlias(entity, alias);
|
|
20609
21080
|
return {
|
|
20610
21081
|
content: [{
|
|
20611
21082
|
type: "text",
|
|
@@ -20613,7 +21084,14 @@ function registerEntityTool(server2, getVaultPath, getStateDb4, getIndex) {
|
|
|
20613
21084
|
success: true,
|
|
20614
21085
|
entity,
|
|
20615
21086
|
alias_added: alias,
|
|
20616
|
-
all_aliases: Array.from(deduped)
|
|
21087
|
+
all_aliases: Array.from(deduped),
|
|
21088
|
+
...resolvedProspects.length > 0 ? {
|
|
21089
|
+
prospect_resolution: {
|
|
21090
|
+
resolved_terms: resolvedProspects,
|
|
21091
|
+
status: "merged",
|
|
21092
|
+
resolved_entity_path: entity
|
|
21093
|
+
}
|
|
21094
|
+
} : {}
|
|
20617
21095
|
}, null, 2)
|
|
20618
21096
|
}]
|
|
20619
21097
|
};
|
|
@@ -20698,7 +21176,7 @@ ${trimmedSource}`;
|
|
|
20698
21176
|
}
|
|
20699
21177
|
}
|
|
20700
21178
|
await writeVaultFile(vaultPath2, primary, targetContent, targetFrontmatter, "LF", targetContentHash);
|
|
20701
|
-
await
|
|
21179
|
+
await fs30.unlink(`${vaultPath2}/${secondary}`);
|
|
20702
21180
|
initializeEntityIndex(vaultPath2).catch((err) => {
|
|
20703
21181
|
console.error(`[Flywheel] Entity cache rebuild failed: ${err}`);
|
|
20704
21182
|
});
|
|
@@ -20730,7 +21208,7 @@ ${trimmedSource}`;
|
|
|
20730
21208
|
content: [{ type: "text", text: JSON.stringify({ suggestions: [], error: "StateDb not available" }) }]
|
|
20731
21209
|
};
|
|
20732
21210
|
}
|
|
20733
|
-
const entities =
|
|
21211
|
+
const entities = getAllEntitiesFromDb5(stateDb2);
|
|
20734
21212
|
if (entities.length === 0) {
|
|
20735
21213
|
return { content: [{ type: "text", text: JSON.stringify({ suggestions: [] }) }] };
|
|
20736
21214
|
}
|
|
@@ -20818,6 +21296,28 @@ ${trimmedSource}`;
|
|
|
20818
21296
|
content: [{ type: "text", text: JSON.stringify({ dismissed: true, pair_key: pairKey }) }]
|
|
20819
21297
|
};
|
|
20820
21298
|
}
|
|
21299
|
+
if (action === "dismiss_prospect") {
|
|
21300
|
+
if (!prospect) {
|
|
21301
|
+
return {
|
|
21302
|
+
content: [{ type: "text", text: JSON.stringify({ error: "prospect is required for action: dismiss_prospect" }) }],
|
|
21303
|
+
isError: true
|
|
21304
|
+
};
|
|
21305
|
+
}
|
|
21306
|
+
const dismissed = dismissProspect(prospect, reason ?? null, note_path ?? null);
|
|
21307
|
+
return {
|
|
21308
|
+
content: [{
|
|
21309
|
+
type: "text",
|
|
21310
|
+
text: JSON.stringify({
|
|
21311
|
+
dismissed,
|
|
21312
|
+
prospect,
|
|
21313
|
+
status: dismissed ? "rejected" : "not_found",
|
|
21314
|
+
...reason ? { reason } : {},
|
|
21315
|
+
...note_path ? { note_path } : {}
|
|
21316
|
+
}, null, 2)
|
|
21317
|
+
}],
|
|
21318
|
+
...dismissed ? {} : { isError: true }
|
|
21319
|
+
};
|
|
21320
|
+
}
|
|
20821
21321
|
return {
|
|
20822
21322
|
content: [{ type: "text", text: JSON.stringify({ error: `Unknown action: ${action}` }) }],
|
|
20823
21323
|
isError: true
|
|
@@ -20934,6 +21434,7 @@ function registerLinkTool(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
20934
21434
|
fix: z18.boolean().optional().describe("[validate] Reserved for future auto-fix support"),
|
|
20935
21435
|
limit: z18.number().optional().describe("Maximum items to return"),
|
|
20936
21436
|
min_frequency: z18.coerce.number().optional().describe("[stubs] Minimum reference count to include (default 5)"),
|
|
21437
|
+
status: z18.enum(["prospect", "entity_created", "merged", "rejected", "all"]).optional().describe("[stubs] Prospect lifecycle status filter (default: prospect)"),
|
|
20937
21438
|
days_back: z18.number().optional().describe("[timeline|layer_timeseries] Days to look back (default 30)"),
|
|
20938
21439
|
granularity: z18.enum(["day", "week"]).optional().describe("[layer_timeseries] Time bucket granularity (default: day)"),
|
|
20939
21440
|
timestamp_before: z18.number().optional().describe("[snapshot_diff] Earlier timestamp"),
|
|
@@ -20954,6 +21455,7 @@ function registerLinkTool(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
20954
21455
|
group_by_target,
|
|
20955
21456
|
limit: rawLimit,
|
|
20956
21457
|
min_frequency,
|
|
21458
|
+
status,
|
|
20957
21459
|
days_back,
|
|
20958
21460
|
granularity,
|
|
20959
21461
|
timestamp_before,
|
|
@@ -21043,9 +21545,9 @@ function registerLinkTool(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
21043
21545
|
try {
|
|
21044
21546
|
for (const prospect of prospects) {
|
|
21045
21547
|
const row = stateDb2.db.prepare(
|
|
21046
|
-
"SELECT note_count, day_count, best_source, best_score, promotion_score, last_seen_at FROM prospect_summary WHERE term = ?"
|
|
21548
|
+
"SELECT note_count, day_count, best_source, best_score, promotion_score, last_seen_at, status, resolved_entity_path FROM prospect_summary WHERE term = ?"
|
|
21047
21549
|
).get(prospect.entity.toLowerCase());
|
|
21048
|
-
if (row) {
|
|
21550
|
+
if (row && row.status === "prospect") {
|
|
21049
21551
|
prospect.ledger_source = row.best_source;
|
|
21050
21552
|
prospect.ledger_note_count = row.note_count;
|
|
21051
21553
|
prospect.ledger_day_count = row.day_count;
|
|
@@ -21053,6 +21555,8 @@ function registerLinkTool(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
21053
21555
|
const effective = Math.round(row.promotion_score * decay * 10) / 10;
|
|
21054
21556
|
prospect.effective_score = effective;
|
|
21055
21557
|
prospect.promotion_ready = effective >= PROMOTION_THRESHOLD;
|
|
21558
|
+
prospect.status = row.status;
|
|
21559
|
+
prospect.resolved_entity_path = row.resolved_entity_path;
|
|
21056
21560
|
}
|
|
21057
21561
|
}
|
|
21058
21562
|
} catch {
|
|
@@ -21235,24 +21739,48 @@ function registerLinkTool(server2, getIndex, getVaultPath, getStateDb4) {
|
|
|
21235
21739
|
if (action === "stubs") {
|
|
21236
21740
|
const limit = Math.min(rawLimit ?? 20, 100);
|
|
21237
21741
|
const minFreq = min_frequency ?? 5;
|
|
21742
|
+
const statusFilter = status ?? "prospect";
|
|
21238
21743
|
requireIndex();
|
|
21239
21744
|
const index = getIndex();
|
|
21240
|
-
const
|
|
21745
|
+
const hasLedgerSummaries = !!stateDb2 && (() => {
|
|
21746
|
+
try {
|
|
21747
|
+
const row = stateDb2.db.prepare("SELECT COUNT(*) as cnt FROM prospect_summary").get();
|
|
21748
|
+
return row.cnt > 0;
|
|
21749
|
+
} catch {
|
|
21750
|
+
return false;
|
|
21751
|
+
}
|
|
21752
|
+
})();
|
|
21753
|
+
const prospectCandidates = getPromotionCandidates(limit * 4, statusFilter);
|
|
21241
21754
|
if (prospectCandidates.length > 0) {
|
|
21242
21755
|
const filtered = prospectCandidates.filter((c) => c.backlinkMax >= minFreq).slice(0, limit).map((c) => ({
|
|
21243
21756
|
term: c.displayName,
|
|
21757
|
+
status: c.status,
|
|
21758
|
+
resolved_entity_path: c.resolvedEntityPath,
|
|
21244
21759
|
wikilink_references: c.backlinkMax,
|
|
21245
21760
|
content_mentions: countFTS5Mentions(c.term),
|
|
21246
21761
|
sample_notes: getProspectSampleNotes(c.term, 3),
|
|
21762
|
+
first_seen_at: c.firstSeenAt,
|
|
21763
|
+
last_seen_at: c.lastSeenAt,
|
|
21764
|
+
note_count: c.noteCount,
|
|
21765
|
+
day_count: c.dayCount,
|
|
21247
21766
|
effective_score: c.effectiveScore,
|
|
21248
21767
|
promotion_ready: c.promotionReady
|
|
21249
21768
|
}));
|
|
21250
21769
|
return { content: [{ type: "text", text: JSON.stringify({
|
|
21770
|
+
status: statusFilter,
|
|
21251
21771
|
total_dead_targets: prospectCandidates.length,
|
|
21252
21772
|
candidates_above_threshold: filtered.length,
|
|
21253
21773
|
candidates: filtered
|
|
21254
21774
|
}, null, 2) }] };
|
|
21255
21775
|
}
|
|
21776
|
+
if (hasLedgerSummaries || statusFilter !== "prospect") {
|
|
21777
|
+
return { content: [{ type: "text", text: JSON.stringify({
|
|
21778
|
+
status: statusFilter,
|
|
21779
|
+
total_dead_targets: 0,
|
|
21780
|
+
candidates_above_threshold: 0,
|
|
21781
|
+
candidates: []
|
|
21782
|
+
}, null, 2) }] };
|
|
21783
|
+
}
|
|
21256
21784
|
const targetMap = /* @__PURE__ */ new Map();
|
|
21257
21785
|
for (const note of index.notes.values()) {
|
|
21258
21786
|
for (const link of note.outlinks) {
|
|
@@ -21343,8 +21871,9 @@ init_wikilinks();
|
|
|
21343
21871
|
import { z as z19 } from "zod";
|
|
21344
21872
|
init_git();
|
|
21345
21873
|
init_wikilinks();
|
|
21346
|
-
|
|
21347
|
-
import
|
|
21874
|
+
init_prospects();
|
|
21875
|
+
import fs31 from "fs/promises";
|
|
21876
|
+
import path35 from "path";
|
|
21348
21877
|
import matter9 from "gray-matter";
|
|
21349
21878
|
function registerNoteTool(server2, getVaultPath, getIndex) {
|
|
21350
21879
|
server2.tool(
|
|
@@ -21456,12 +21985,12 @@ async function handleCreate(params, getVaultPath) {
|
|
|
21456
21985
|
if (!validatePath(vaultPath2, notePath)) {
|
|
21457
21986
|
return formatMcpResult(errorResult(notePath, "Invalid path: path traversal not allowed"));
|
|
21458
21987
|
}
|
|
21459
|
-
const fullPath =
|
|
21988
|
+
const fullPath = path35.join(vaultPath2, notePath);
|
|
21460
21989
|
const existsCheck = await ensureFileExists(vaultPath2, notePath);
|
|
21461
21990
|
if (existsCheck === null && !overwrite) {
|
|
21462
21991
|
return formatMcpResult(errorResult(notePath, `File already exists: ${notePath}. Use overwrite:true to replace.`));
|
|
21463
21992
|
}
|
|
21464
|
-
await
|
|
21993
|
+
await fs31.mkdir(path35.dirname(fullPath), { recursive: true });
|
|
21465
21994
|
let effectiveContent = content;
|
|
21466
21995
|
let effectiveFrontmatter = rawFrontmatter;
|
|
21467
21996
|
if (template) {
|
|
@@ -21469,13 +21998,13 @@ async function handleCreate(params, getVaultPath) {
|
|
|
21469
21998
|
if (!templateValidation.valid) {
|
|
21470
21999
|
return formatMcpResult(errorResult(notePath, `Invalid template path: ${templateValidation.reason}`));
|
|
21471
22000
|
}
|
|
21472
|
-
const templatePath =
|
|
22001
|
+
const templatePath = path35.join(vaultPath2, template);
|
|
21473
22002
|
try {
|
|
21474
|
-
const raw = await
|
|
22003
|
+
const raw = await fs31.readFile(templatePath, "utf-8");
|
|
21475
22004
|
const gm = (await import("gray-matter")).default;
|
|
21476
22005
|
const parsed = gm(raw);
|
|
21477
22006
|
const dateStr = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
21478
|
-
const title =
|
|
22007
|
+
const title = path35.basename(notePath, ".md");
|
|
21479
22008
|
let templateContent = parsed.content.replace(/\{\{date\}\}/g, dateStr).replace(/\{\{title\}\}/g, title);
|
|
21480
22009
|
if (content) {
|
|
21481
22010
|
templateContent = templateContent.trimEnd() + "\n\n" + content;
|
|
@@ -21490,7 +22019,7 @@ async function handleCreate(params, getVaultPath) {
|
|
|
21490
22019
|
if (!effectiveFrontmatter.date) effectiveFrontmatter.date = now.toISOString().split("T")[0];
|
|
21491
22020
|
if (!effectiveFrontmatter.created) effectiveFrontmatter.created = now.toISOString();
|
|
21492
22021
|
const warnings = [];
|
|
21493
|
-
const noteName =
|
|
22022
|
+
const noteName = path35.basename(notePath, ".md");
|
|
21494
22023
|
const existingAliases = Array.isArray(effectiveFrontmatter?.aliases) ? effectiveFrontmatter.aliases.filter((a) => typeof a === "string") : [];
|
|
21495
22024
|
const preflight = await checkPreflightSimilarity(noteName);
|
|
21496
22025
|
if (preflight.existingEntity) {
|
|
@@ -21558,11 +22087,21 @@ async function handleCreate(params, getVaultPath) {
|
|
|
21558
22087
|
);
|
|
21559
22088
|
}
|
|
21560
22089
|
await writeVaultFile(vaultPath2, notePath, processedContent, finalFrontmatter);
|
|
22090
|
+
const resolvedProspects = resolveProspectsForCreatedEntity(
|
|
22091
|
+
notePath,
|
|
22092
|
+
noteName,
|
|
22093
|
+
extractAliases2(finalFrontmatter)
|
|
22094
|
+
);
|
|
21561
22095
|
const gitInfo = await handleGitCommit(vaultPath2, notePath, commit, "[Flywheel:Create]");
|
|
21562
22096
|
return formatMcpResult(
|
|
21563
22097
|
successResult(notePath, `Created note: ${notePath}`, gitInfo, {
|
|
21564
22098
|
preview: previewLines.join("\n"),
|
|
21565
|
-
warnings: warnings.length > 0 ? warnings : void 0
|
|
22099
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
22100
|
+
prospect_resolution: resolvedProspects.length > 0 ? {
|
|
22101
|
+
resolved_terms: resolvedProspects,
|
|
22102
|
+
status: "entity_created",
|
|
22103
|
+
resolved_entity_path: notePath
|
|
22104
|
+
} : void 0
|
|
21566
22105
|
})
|
|
21567
22106
|
);
|
|
21568
22107
|
} catch (error) {
|
|
@@ -21589,21 +22128,21 @@ async function handleMove(params, getVaultPath) {
|
|
|
21589
22128
|
const result2 = { success: false, message: "Invalid destination path: path traversal not allowed", path: newPath };
|
|
21590
22129
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
21591
22130
|
}
|
|
21592
|
-
const oldFullPath =
|
|
21593
|
-
const newFullPath =
|
|
22131
|
+
const oldFullPath = path35.join(vaultPath2, oldPath);
|
|
22132
|
+
const newFullPath = path35.join(vaultPath2, newPath);
|
|
21594
22133
|
try {
|
|
21595
|
-
await
|
|
22134
|
+
await fs31.access(oldFullPath);
|
|
21596
22135
|
} catch {
|
|
21597
22136
|
const result2 = { success: false, message: `Source file not found: ${oldPath}`, path: oldPath };
|
|
21598
22137
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
21599
22138
|
}
|
|
21600
22139
|
try {
|
|
21601
|
-
await
|
|
22140
|
+
await fs31.access(newFullPath);
|
|
21602
22141
|
const result2 = { success: false, message: `Destination already exists: ${newPath}`, path: newPath };
|
|
21603
22142
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
21604
22143
|
} catch {
|
|
21605
22144
|
}
|
|
21606
|
-
const sourceContent = await
|
|
22145
|
+
const sourceContent = await fs31.readFile(oldFullPath, "utf-8");
|
|
21607
22146
|
const parsed = matter9(sourceContent);
|
|
21608
22147
|
const aliases = extractAliases2(parsed.data);
|
|
21609
22148
|
const oldTitle = getTitleFromPath(oldPath);
|
|
@@ -21642,8 +22181,8 @@ async function handleMove(params, getVaultPath) {
|
|
|
21642
22181
|
const result2 = { success: true, message: `[dry run] Would move note: ${oldPath} \u2192 ${newPath}`, path: newPath, preview: previewLines.join("\n"), dryRun: true };
|
|
21643
22182
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
21644
22183
|
}
|
|
21645
|
-
await
|
|
21646
|
-
await
|
|
22184
|
+
await fs31.mkdir(path35.dirname(newFullPath), { recursive: true });
|
|
22185
|
+
await fs31.rename(oldFullPath, newFullPath);
|
|
21647
22186
|
let gitCommit;
|
|
21648
22187
|
let undoAvailable;
|
|
21649
22188
|
let staleLockDetected;
|
|
@@ -21687,25 +22226,25 @@ async function handleRename(params, getVaultPath) {
|
|
|
21687
22226
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
21688
22227
|
}
|
|
21689
22228
|
const sanitizedTitle = newTitle.replace(/[<>:"/\\|?*]/g, "");
|
|
21690
|
-
const fullPath =
|
|
21691
|
-
const dir =
|
|
21692
|
-
const newPath = dir === "." ? `${sanitizedTitle}.md` :
|
|
21693
|
-
const newFullPath =
|
|
22229
|
+
const fullPath = path35.join(vaultPath2, notePath);
|
|
22230
|
+
const dir = path35.dirname(notePath);
|
|
22231
|
+
const newPath = dir === "." ? `${sanitizedTitle}.md` : path35.join(dir, `${sanitizedTitle}.md`);
|
|
22232
|
+
const newFullPath = path35.join(vaultPath2, newPath);
|
|
21694
22233
|
try {
|
|
21695
|
-
await
|
|
22234
|
+
await fs31.access(fullPath);
|
|
21696
22235
|
} catch {
|
|
21697
22236
|
const result2 = { success: false, message: `File not found: ${notePath}`, path: notePath };
|
|
21698
22237
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
21699
22238
|
}
|
|
21700
22239
|
if (fullPath !== newFullPath) {
|
|
21701
22240
|
try {
|
|
21702
|
-
await
|
|
22241
|
+
await fs31.access(newFullPath);
|
|
21703
22242
|
const result2 = { success: false, message: `A note with this title already exists: ${newPath}`, path: notePath };
|
|
21704
22243
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
21705
22244
|
} catch {
|
|
21706
22245
|
}
|
|
21707
22246
|
}
|
|
21708
|
-
const sourceContent = await
|
|
22247
|
+
const sourceContent = await fs31.readFile(fullPath, "utf-8");
|
|
21709
22248
|
const parsed = matter9(sourceContent);
|
|
21710
22249
|
const aliases = extractAliases2(parsed.data);
|
|
21711
22250
|
const oldTitle = getTitleFromPath(notePath);
|
|
@@ -21744,7 +22283,7 @@ async function handleRename(params, getVaultPath) {
|
|
|
21744
22283
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
21745
22284
|
}
|
|
21746
22285
|
if (fullPath !== newFullPath) {
|
|
21747
|
-
await
|
|
22286
|
+
await fs31.rename(fullPath, newFullPath);
|
|
21748
22287
|
}
|
|
21749
22288
|
let gitCommit;
|
|
21750
22289
|
let undoAvailable;
|
|
@@ -21814,8 +22353,8 @@ ${sources}`;
|
|
|
21814
22353
|
}
|
|
21815
22354
|
return formatMcpResult(errorResult(notePath, previewLines.join("\n")));
|
|
21816
22355
|
}
|
|
21817
|
-
const fullPath =
|
|
21818
|
-
await
|
|
22356
|
+
const fullPath = path35.join(vaultPath2, notePath);
|
|
22357
|
+
await fs31.unlink(fullPath);
|
|
21819
22358
|
const gitInfo = await handleGitCommit(vaultPath2, notePath, commit, "[Flywheel:Delete]");
|
|
21820
22359
|
const message = backlinkWarning ? `Deleted note: ${notePath}
|
|
21821
22360
|
|
|
@@ -21831,8 +22370,8 @@ Warning: ${backlinkWarning}` : `Deleted note: ${notePath}`;
|
|
|
21831
22370
|
// src/tools/write/editSection.ts
|
|
21832
22371
|
init_writer();
|
|
21833
22372
|
import { z as z21 } from "zod";
|
|
21834
|
-
import
|
|
21835
|
-
import
|
|
22373
|
+
import fs33 from "fs/promises";
|
|
22374
|
+
import path37 from "path";
|
|
21836
22375
|
init_wikilinks();
|
|
21837
22376
|
init_wikilinkFeedback();
|
|
21838
22377
|
init_markdown_structure();
|
|
@@ -21840,8 +22379,8 @@ init_markdown_structure();
|
|
|
21840
22379
|
// src/tools/write/mutations.ts
|
|
21841
22380
|
init_writer();
|
|
21842
22381
|
import { z as z20 } from "zod";
|
|
21843
|
-
import
|
|
21844
|
-
import
|
|
22382
|
+
import fs32 from "fs/promises";
|
|
22383
|
+
import path36 from "path";
|
|
21845
22384
|
init_wikilinks();
|
|
21846
22385
|
init_wikilinkFeedback();
|
|
21847
22386
|
init_markdown_structure();
|
|
@@ -21850,10 +22389,10 @@ async function createNoteFromTemplate(vaultPath2, notePath, config2) {
|
|
|
21850
22389
|
if (!validation.valid) {
|
|
21851
22390
|
throw new Error(`Path blocked: ${validation.reason}`);
|
|
21852
22391
|
}
|
|
21853
|
-
const fullPath =
|
|
21854
|
-
await
|
|
22392
|
+
const fullPath = path36.join(vaultPath2, notePath);
|
|
22393
|
+
await fs32.mkdir(path36.dirname(fullPath), { recursive: true });
|
|
21855
22394
|
const templates = config2.templates || {};
|
|
21856
|
-
const filename =
|
|
22395
|
+
const filename = path36.basename(notePath, ".md").toLowerCase();
|
|
21857
22396
|
let templatePath;
|
|
21858
22397
|
let periodicType;
|
|
21859
22398
|
const dailyPattern = /^\d{4}-\d{2}-\d{2}/;
|
|
@@ -21886,7 +22425,7 @@ async function createNoteFromTemplate(vaultPath2, notePath, config2) {
|
|
|
21886
22425
|
];
|
|
21887
22426
|
for (const candidate of candidates) {
|
|
21888
22427
|
try {
|
|
21889
|
-
await
|
|
22428
|
+
await fs32.access(path36.join(vaultPath2, candidate));
|
|
21890
22429
|
templatePath = candidate;
|
|
21891
22430
|
console.error(`[Flywheel] Template not in config but found at ${candidate} \u2014 using it`);
|
|
21892
22431
|
break;
|
|
@@ -21897,11 +22436,11 @@ async function createNoteFromTemplate(vaultPath2, notePath, config2) {
|
|
|
21897
22436
|
let templateContent;
|
|
21898
22437
|
if (templatePath) {
|
|
21899
22438
|
try {
|
|
21900
|
-
const absTemplatePath =
|
|
21901
|
-
templateContent = await
|
|
22439
|
+
const absTemplatePath = path36.join(vaultPath2, templatePath);
|
|
22440
|
+
templateContent = await fs32.readFile(absTemplatePath, "utf-8");
|
|
21902
22441
|
} catch {
|
|
21903
22442
|
console.error(`[Flywheel] Template at ${templatePath} not readable, using minimal fallback`);
|
|
21904
|
-
const title =
|
|
22443
|
+
const title = path36.basename(notePath, ".md");
|
|
21905
22444
|
templateContent = `---
|
|
21906
22445
|
---
|
|
21907
22446
|
|
|
@@ -21913,7 +22452,7 @@ async function createNoteFromTemplate(vaultPath2, notePath, config2) {
|
|
|
21913
22452
|
if (periodicType) {
|
|
21914
22453
|
console.error(`[Flywheel] No ${periodicType} template found in config or vault \u2014 using minimal fallback`);
|
|
21915
22454
|
}
|
|
21916
|
-
const title =
|
|
22455
|
+
const title = path36.basename(notePath, ".md");
|
|
21917
22456
|
templateContent = `---
|
|
21918
22457
|
---
|
|
21919
22458
|
|
|
@@ -21922,7 +22461,7 @@ async function createNoteFromTemplate(vaultPath2, notePath, config2) {
|
|
|
21922
22461
|
}
|
|
21923
22462
|
const now = /* @__PURE__ */ new Date();
|
|
21924
22463
|
const dateStr = now.toISOString().split("T")[0];
|
|
21925
|
-
templateContent = templateContent.replace(/\{\{date\}\}/g, dateStr).replace(/\{\{title\}\}/g,
|
|
22464
|
+
templateContent = templateContent.replace(/\{\{date\}\}/g, dateStr).replace(/\{\{title\}\}/g, path36.basename(notePath, ".md"));
|
|
21926
22465
|
const matter10 = (await import("gray-matter")).default;
|
|
21927
22466
|
const parsed = matter10(templateContent);
|
|
21928
22467
|
if (!parsed.data.date) {
|
|
@@ -22060,9 +22599,9 @@ async function handleAdd(params, getVaultPath, getConfig2) {
|
|
|
22060
22599
|
let noteCreated = false;
|
|
22061
22600
|
let templateUsed;
|
|
22062
22601
|
if (create_if_missing && !dry_run) {
|
|
22063
|
-
const fullPath =
|
|
22602
|
+
const fullPath = path37.join(vaultPath2, notePath);
|
|
22064
22603
|
try {
|
|
22065
|
-
await
|
|
22604
|
+
await fs33.access(fullPath);
|
|
22066
22605
|
} catch {
|
|
22067
22606
|
const config2 = getConfig2();
|
|
22068
22607
|
const result = await createNoteFromTemplate(vaultPath2, notePath, config2);
|
|
@@ -22071,9 +22610,9 @@ async function handleAdd(params, getVaultPath, getConfig2) {
|
|
|
22071
22610
|
}
|
|
22072
22611
|
}
|
|
22073
22612
|
if (create_if_missing && dry_run) {
|
|
22074
|
-
const fullPath =
|
|
22613
|
+
const fullPath = path37.join(vaultPath2, notePath);
|
|
22075
22614
|
try {
|
|
22076
|
-
await
|
|
22615
|
+
await fs33.access(fullPath);
|
|
22077
22616
|
} catch {
|
|
22078
22617
|
return {
|
|
22079
22618
|
content: [{
|
|
@@ -22791,7 +23330,7 @@ function registerMemoryTools(server2, getStateDb4) {
|
|
|
22791
23330
|
// src/tools/read/semantic.ts
|
|
22792
23331
|
init_embeddings();
|
|
22793
23332
|
import { z as z23 } from "zod";
|
|
22794
|
-
import { getAllEntitiesFromDb as
|
|
23333
|
+
import { getAllEntitiesFromDb as getAllEntitiesFromDb6 } from "@velvetmonkey/vault-core";
|
|
22795
23334
|
function registerSemanticTools(server2, getVaultPath, getStateDb4) {
|
|
22796
23335
|
server2.registerTool(
|
|
22797
23336
|
"init_semantic",
|
|
@@ -22856,7 +23395,7 @@ function registerSemanticTools(server2, getVaultPath, getStateDb4) {
|
|
|
22856
23395
|
const embedded = progress.total - progress.skipped;
|
|
22857
23396
|
let entityEmbedded = 0;
|
|
22858
23397
|
try {
|
|
22859
|
-
const allEntities =
|
|
23398
|
+
const allEntities = getAllEntitiesFromDb6(stateDb2);
|
|
22860
23399
|
const entityMap = /* @__PURE__ */ new Map();
|
|
22861
23400
|
for (const e of allEntities) {
|
|
22862
23401
|
entityMap.set(e.name, {
|
|
@@ -22947,14 +23486,8 @@ function registerDiscoveryTools(server2, controller) {
|
|
|
22947
23486
|
}
|
|
22948
23487
|
}
|
|
22949
23488
|
const matchedCategories = [];
|
|
22950
|
-
const newlyActivatedCategories = [];
|
|
22951
23489
|
for (const { category, tier } of signals) {
|
|
22952
|
-
const wasActive = controller.activeCategories.has(category);
|
|
22953
23490
|
matchedCategories.push(category);
|
|
22954
|
-
controller.activateCategory(category, tier);
|
|
22955
|
-
if (!wasActive && controller.activeCategories.has(category)) {
|
|
22956
|
-
newlyActivatedCategories.push(category);
|
|
22957
|
-
}
|
|
22958
23491
|
}
|
|
22959
23492
|
const tools = [];
|
|
22960
23493
|
for (const [name, handle] of controller.getRegisteredTools()) {
|
|
@@ -22970,10 +23503,9 @@ function registerDiscoveryTools(server2, controller) {
|
|
|
22970
23503
|
}
|
|
22971
23504
|
const result = {
|
|
22972
23505
|
matched_categories: matchedCategories,
|
|
22973
|
-
newly_activated_categories: newlyActivatedCategories,
|
|
22974
23506
|
match_method: matchMethod,
|
|
22975
23507
|
tools,
|
|
22976
|
-
hint: tools.length === 0 ? `No tools matched "${query}". Available categories: ${ALL_CATEGORIES.join(", ")}` : `${tools.length} tools
|
|
23508
|
+
hint: tools.length === 0 ? `No tools matched "${query}". Available categories: ${ALL_CATEGORIES.join(", ")}` : `${tools.length} tools match ${matchedCategories.join(", ")}. These tools are already callable; discover_tools does not change visibility.`
|
|
22977
23509
|
};
|
|
22978
23510
|
return {
|
|
22979
23511
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
@@ -23088,7 +23620,7 @@ function registerVaultResources(server2, getIndex) {
|
|
|
23088
23620
|
// src/tool-registry.ts
|
|
23089
23621
|
var __trFilename = fileURLToPath3(import.meta.url);
|
|
23090
23622
|
var __trDirname = dirname6(__trFilename);
|
|
23091
|
-
var trPkg = JSON.parse(readFileSync5(
|
|
23623
|
+
var trPkg = JSON.parse(readFileSync5(join18(__trDirname, "../package.json"), "utf-8"));
|
|
23092
23624
|
var ACTIVATION_PATTERNS = [
|
|
23093
23625
|
{
|
|
23094
23626
|
category: "memory",
|
|
@@ -23352,7 +23884,7 @@ function applyToolGating(targetServer, categories, getDb4, registry, getVaultPat
|
|
|
23352
23884
|
let totalBytes = 0;
|
|
23353
23885
|
for (const p of notePaths) {
|
|
23354
23886
|
try {
|
|
23355
|
-
totalBytes += statSync5(
|
|
23887
|
+
totalBytes += statSync5(path38.join(vp, p)).size;
|
|
23356
23888
|
} catch {
|
|
23357
23889
|
}
|
|
23358
23890
|
}
|
|
@@ -23702,7 +24234,7 @@ function registerAllTools(targetServer, ctx, controller, options = {}) {
|
|
|
23702
24234
|
// src/index.ts
|
|
23703
24235
|
var __filename2 = fileURLToPath4(import.meta.url);
|
|
23704
24236
|
var __dirname = dirname8(__filename2);
|
|
23705
|
-
var pkg = JSON.parse(readFileSync6(
|
|
24237
|
+
var pkg = JSON.parse(readFileSync6(join20(__dirname, "../package.json"), "utf-8"));
|
|
23706
24238
|
var vaultPath;
|
|
23707
24239
|
var resolvedVaultPath;
|
|
23708
24240
|
var vaultIndex;
|
|
@@ -23734,26 +24266,8 @@ function getWatcherStatus() {
|
|
|
23734
24266
|
var toolConfig = resolveToolConfig();
|
|
23735
24267
|
var enabledCategories = toolConfig.categories;
|
|
23736
24268
|
var toolTierMode = toolConfig.enableProgressiveDisclosure ? "tiered" : "off";
|
|
23737
|
-
var runtimeToolTierOverride = INITIAL_TIER_OVERRIDE;
|
|
23738
|
-
var runtimeActiveCategoryTiers = /* @__PURE__ */ new Map();
|
|
23739
|
-
var primaryToolTierController = null;
|
|
23740
24269
|
function getInstructionActiveCategories() {
|
|
23741
|
-
|
|
23742
|
-
if (runtimeToolTierOverride === "full") {
|
|
23743
|
-
return new Set(enabledCategories);
|
|
23744
|
-
}
|
|
23745
|
-
return new Set(runtimeActiveCategoryTiers.keys());
|
|
23746
|
-
}
|
|
23747
|
-
function syncRuntimeTierState(controller) {
|
|
23748
|
-
runtimeToolTierOverride = controller.getOverride();
|
|
23749
|
-
runtimeActiveCategoryTiers = new Map(controller.getActivatedCategoryTiers());
|
|
23750
|
-
}
|
|
23751
|
-
function handleTierStateChange(controller) {
|
|
23752
|
-
syncRuntimeTierState(controller);
|
|
23753
|
-
invalidateHttpPool();
|
|
23754
|
-
}
|
|
23755
|
-
function getConfigToolTierOverride(config2) {
|
|
23756
|
-
return config2.tool_tier_override ?? "auto";
|
|
24270
|
+
return toolConfig.enableProgressiveDisclosure ? new Set(enabledCategories) : void 0;
|
|
23757
24271
|
}
|
|
23758
24272
|
function buildRegistryContext() {
|
|
23759
24273
|
return {
|
|
@@ -23798,17 +24312,13 @@ function createConfiguredServer() {
|
|
|
23798
24312
|
ctx.getVaultPath,
|
|
23799
24313
|
buildVaultCallbacks(),
|
|
23800
24314
|
toolTierMode,
|
|
23801
|
-
|
|
24315
|
+
void 0,
|
|
23802
24316
|
toolConfig.isFullToolset,
|
|
23803
24317
|
() => {
|
|
23804
24318
|
lastMcpRequestAt = Date.now();
|
|
23805
24319
|
}
|
|
23806
24320
|
);
|
|
23807
24321
|
registerAllTools(s, ctx, toolTierController);
|
|
23808
|
-
toolTierController.setOverride(runtimeToolTierOverride);
|
|
23809
|
-
for (const [category, tier] of runtimeActiveCategoryTiers) {
|
|
23810
|
-
toolTierController.activateCategory(category, tier);
|
|
23811
|
-
}
|
|
23812
24322
|
toolTierController.finalizeRegistration();
|
|
23813
24323
|
return s;
|
|
23814
24324
|
}
|
|
@@ -23855,17 +24365,14 @@ var _gatingResult = applyToolGating(
|
|
|
23855
24365
|
_registryCtx.getVaultPath,
|
|
23856
24366
|
buildVaultCallbacks(),
|
|
23857
24367
|
toolTierMode,
|
|
23858
|
-
|
|
24368
|
+
void 0,
|
|
23859
24369
|
toolConfig.isFullToolset,
|
|
23860
24370
|
() => {
|
|
23861
24371
|
lastMcpRequestAt = Date.now();
|
|
23862
24372
|
}
|
|
23863
24373
|
);
|
|
23864
24374
|
registerAllTools(server, _registryCtx, _gatingResult);
|
|
23865
|
-
_gatingResult.setOverride(runtimeToolTierOverride);
|
|
23866
24375
|
_gatingResult.finalizeRegistration();
|
|
23867
|
-
primaryToolTierController = _gatingResult;
|
|
23868
|
-
syncRuntimeTierState(_gatingResult);
|
|
23869
24376
|
var categoryList = Array.from(enabledCategories).sort().join(", ");
|
|
23870
24377
|
serverLog("server", `Tool categories: ${categoryList}`);
|
|
23871
24378
|
serverLog("server", `Registered ${_gatingResult.registered} tools, skipped ${_gatingResult.skipped}`);
|
|
@@ -24098,11 +24605,6 @@ function updateVaultIndex(index) {
|
|
|
24098
24605
|
function updateFlywheelConfig(config2) {
|
|
24099
24606
|
flywheelConfig = config2;
|
|
24100
24607
|
setWikilinkConfig(config2);
|
|
24101
|
-
if (toolTierMode === "tiered" && primaryToolTierController) {
|
|
24102
|
-
primaryToolTierController.setOverride(getConfigToolTierOverride(config2));
|
|
24103
|
-
syncRuntimeTierState(primaryToolTierController);
|
|
24104
|
-
invalidateHttpPool();
|
|
24105
|
-
}
|
|
24106
24608
|
const ctx = getActiveVaultContext();
|
|
24107
24609
|
if (ctx) {
|
|
24108
24610
|
ctx.flywheelConfig = config2;
|
|
@@ -24549,7 +25051,7 @@ async function runPostIndexWork(ctx) {
|
|
|
24549
25051
|
serverLog("semantic", "Embeddings up-to-date, skipping build");
|
|
24550
25052
|
loadEntityEmbeddingsToMemory();
|
|
24551
25053
|
if (sd) {
|
|
24552
|
-
const entities =
|
|
25054
|
+
const entities = getAllEntitiesFromDb7(sd);
|
|
24553
25055
|
if (entities.length > 0) {
|
|
24554
25056
|
saveInferredCategories(classifyUncategorizedEntities(
|
|
24555
25057
|
entities.map((entity) => ({
|
|
@@ -24586,7 +25088,7 @@ async function runPostIndexWork(ctx) {
|
|
|
24586
25088
|
}
|
|
24587
25089
|
});
|
|
24588
25090
|
if (sd) {
|
|
24589
|
-
const entities =
|
|
25091
|
+
const entities = getAllEntitiesFromDb7(sd);
|
|
24590
25092
|
if (entities.length > 0) {
|
|
24591
25093
|
const entityMap = new Map(entities.map((e) => [e.name, {
|
|
24592
25094
|
name: e.name,
|
|
@@ -24601,7 +25103,7 @@ async function runPostIndexWork(ctx) {
|
|
|
24601
25103
|
activateVault(ctx);
|
|
24602
25104
|
loadEntityEmbeddingsToMemory();
|
|
24603
25105
|
if (sd) {
|
|
24604
|
-
const entities =
|
|
25106
|
+
const entities = getAllEntitiesFromDb7(sd);
|
|
24605
25107
|
if (entities.length > 0) {
|
|
24606
25108
|
saveInferredCategories(classifyUncategorizedEntities(
|
|
24607
25109
|
entities.map((entity) => ({
|
|
@@ -24678,8 +25180,8 @@ async function runPostIndexWork(ctx) {
|
|
|
24678
25180
|
}
|
|
24679
25181
|
} catch {
|
|
24680
25182
|
try {
|
|
24681
|
-
const dir =
|
|
24682
|
-
const base =
|
|
25183
|
+
const dir = path39.dirname(rawPath);
|
|
25184
|
+
const base = path39.basename(rawPath);
|
|
24683
25185
|
const resolvedDir = realpathSync(dir).replace(/\\/g, "/");
|
|
24684
25186
|
for (const prefix of vaultPrefixes) {
|
|
24685
25187
|
if (resolvedDir.startsWith(prefix + "/") || resolvedDir === prefix) {
|
|
@@ -24711,7 +25213,7 @@ async function runPostIndexWork(ctx) {
|
|
|
24711
25213
|
continue;
|
|
24712
25214
|
}
|
|
24713
25215
|
try {
|
|
24714
|
-
const content = await
|
|
25216
|
+
const content = await fs34.readFile(path39.join(vp, event.path), "utf-8");
|
|
24715
25217
|
const hash = createHash3("sha256").update(content).digest("hex").slice(0, 16);
|
|
24716
25218
|
if (lastContentHashes.get(event.path) === hash) {
|
|
24717
25219
|
serverLog("watcher", `Hash unchanged, skipping: ${event.path}`);
|