@theglitchking/semantic-pages 0.4.8 → 0.4.9

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.
@@ -649,12 +649,9 @@ var NoteCrud = class {
649
649
  throw new Error(`Note already exists: ${relativePath}`);
650
650
  }
651
651
  await mkdir2(dirname2(absPath), { recursive: true });
652
- let fileContent;
653
- if (frontmatter && Object.keys(frontmatter).length > 0) {
654
- fileContent = matter.stringify(content, frontmatter);
655
- } else {
656
- fileContent = content;
657
- }
652
+ const stamps = computeStamps(content);
653
+ const merged = { ...stamps, ...frontmatter ?? {} };
654
+ const fileContent = matter.stringify(content, merged);
658
655
  await writeFile4(absPath, fileContent, "utf-8");
659
656
  return relativePath;
660
657
  }
@@ -691,8 +688,8 @@ var NoteCrud = class {
691
688
  updated = existing + "\n" + content;
692
689
  break;
693
690
  case "prepend": {
694
- const { data, content: body } = matter(existing);
695
- const newBody = content + "\n" + body;
691
+ const { data, content: body2 } = matter(existing);
692
+ const newBody = content + "\n" + body2;
696
693
  updated = Object.keys(data).length > 0 ? matter.stringify(newBody, data) : newBody;
697
694
  break;
698
695
  }
@@ -702,7 +699,10 @@ var NoteCrud = class {
702
699
  break;
703
700
  }
704
701
  }
705
- await writeFile4(absPath, updated, "utf-8");
702
+ const { data: existingFm, content: body } = matter(updated);
703
+ const stamps = computeStamps(body);
704
+ const newFm = { ...existingFm, ...stamps };
705
+ await writeFile4(absPath, matter.stringify(body, newFm), "utf-8");
706
706
  }
707
707
  async delete(relativePath) {
708
708
  const absPath = join4(this.notesPath, relativePath);
@@ -770,6 +770,16 @@ var NoteCrud = class {
770
770
  function escapeRegex(str) {
771
771
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
772
772
  }
773
+ function computeStamps(body) {
774
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
775
+ const wordCount = body.trim() ? body.trim().split(/\s+/).length : 0;
776
+ const minutes = Math.max(1, Math.ceil(wordCount / 200));
777
+ return {
778
+ last_updated: today,
779
+ word_count: wordCount,
780
+ estimated_read_time: `${minutes} min read`
781
+ };
782
+ }
773
783
 
774
784
  // src/core/frontmatter.ts
775
785
  import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
@@ -941,4 +951,4 @@ export {
941
951
  TagManager,
942
952
  Watcher
943
953
  };
944
- //# sourceMappingURL=chunk-55IDPZHC.js.map
954
+ //# sourceMappingURL=chunk-P7BHYKVE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/embedder.ts","../src/core/graph.ts","../src/core/vector.ts","../src/core/search-text.ts","../src/core/crud.ts","../src/core/frontmatter.ts","../src/core/watcher.ts"],"sourcesContent":["import { AutoTokenizer } from \"@huggingface/transformers\";\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { existsSync, createWriteStream } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { Readable } from \"node:stream\";\nimport { pipeline as streamPipeline } from \"node:stream/promises\";\nimport { Worker } from \"node:worker_threads\";\nimport { fileURLToPath } from \"node:url\";\n\n// MiniLM-L6-v2 is the default: ~3 min to index 2,853 chunks on CPU vs ~16 min for nomic.\n// nomic-embed-text-v1.5 gives higher quality embeddings but is much slower on CPU.\nconst DEFAULT_MODEL = \"sentence-transformers/all-MiniLM-L6-v2\";\nconst CACHE_DIR = join(homedir(), \".semantic-pages\", \"models\");\n// Default to 1 worker (serial). Worker threads only help on memory-rich machines\n// (each worker loads its own ONNX session). On typical dev machines\n// with <4 GB free RAM, parallel workers cause swap thrashing and are slower.\n// Enable with --workers N when you have sufficient RAM.\nconst DEFAULT_WORKERS = 1;\n// batch=16 is optimal for MiniLM on CPU (short sequences, low padding waste).\n// For larger models (nomic 768d), batch=1 is faster due to padding overhead.\nconst DEFAULT_BATCH_SIZE = 16;\n// Quantized ONNX: faster on CPU but not all models have a quantized variant.\n// MiniLM fp32 is already fast enough; nomic benefits from quantized.\n// Falls back to fp32 automatically if quantized file is not available.\nconst DEFAULT_QUANTIZED = false;\n\n// Full-precision ONNX model subpaths\nconst ONNX_MODEL_PATHS: Record<string, string> = {\n \"nomic-ai/nomic-embed-text-v1.5\": \"onnx/model.onnx\",\n \"sentence-transformers/all-MiniLM-L6-v2\": \"onnx/model.onnx\",\n};\n\n// Quantized (int8) ONNX model subpaths — faster on CPU, ~same quality\nconst ONNX_QUANTIZED_MODEL_PATHS: Record<string, string> = {\n \"nomic-ai/nomic-embed-text-v1.5\": \"onnx/model_quantized.onnx\",\n \"sentence-transformers/all-MiniLM-L6-v2\": \"onnx/model_quantized.onnx\",\n};\n\ninterface OrtSession {\n run(feeds: Record<string, unknown>): Promise<Record<string, { data: Float32Array; dims: number[] }>>;\n inputNames: string[];\n outputNames: string[];\n}\n\ninterface OrtModule {\n InferenceSession: {\n create(path: string, options?: Record<string, unknown>): Promise<OrtSession>;\n };\n Tensor: new (type: string, data: ArrayLike<number | bigint>, dims: number[]) => unknown;\n}\n\ntype RuntimeLabel = \"native\" | \"wasm\";\n\nasync function resolveOnnxRuntime(): Promise<{ ort: OrtModule; label: RuntimeLabel }> {\n try {\n const ort = await import(\"onnxruntime-node\");\n return { ort: ort as unknown as OrtModule, label: \"native\" };\n } catch {\n const ort = await import(\"onnxruntime-web\");\n return { ort: ort as unknown as OrtModule, label: \"wasm\" };\n }\n}\n\nasync function downloadFile(url: string, destPath: string): Promise<void> {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`Download failed (${response.status}): ${url}`);\n if (!response.body) throw new Error(`No response body: ${url}`);\n const fileStream = createWriteStream(destPath);\n await streamPipeline(Readable.fromWeb(response.body as never), fileStream);\n}\n\nexport class Embedder {\n private model: string;\n private session: OrtSession | null = null;\n private tokenizer: Awaited<ReturnType<typeof AutoTokenizer.from_pretrained>> | null = null;\n private ort: OrtModule | null = null;\n private dimensions = 0;\n private runtimeLabel: RuntimeLabel = \"wasm\";\n private initialized = false;\n private numWorkers: number;\n private batchSize: number;\n private quantized: boolean;\n private modelPath = \"\";\n\n constructor(\n model: string = DEFAULT_MODEL,\n numWorkers: number = DEFAULT_WORKERS,\n batchSize: number = DEFAULT_BATCH_SIZE,\n quantized: boolean = DEFAULT_QUANTIZED\n ) {\n this.model = model;\n this.numWorkers = numWorkers;\n this.batchSize = batchSize;\n this.quantized = quantized;\n }\n\n async init(): Promise<void> {\n if (this.initialized) return;\n\n const modelDir = join(CACHE_DIR, this.model.replace(/\\//g, \"--\"));\n await mkdir(modelDir, { recursive: true });\n\n // Resolve ONNX runtime (native C++ or WASM fallback)\n const { ort, label } = await resolveOnnxRuntime();\n this.ort = ort;\n this.runtimeLabel = label;\n\n // Download ONNX model if not cached. Tries quantized first if requested,\n // falls back to fp32 if the quantized file is not available for this model.\n let useQuantized = this.quantized;\n const modelFileName = useQuantized ? \"model_quantized.onnx\" : \"model.onnx\";\n this.modelPath = join(modelDir, modelFileName);\n const modelPath = this.modelPath;\n if (!existsSync(modelPath)) {\n const pathMap = useQuantized ? ONNX_QUANTIZED_MODEL_PATHS : ONNX_MODEL_PATHS;\n const onnxSubpath = pathMap[this.model] ?? (useQuantized ? \"onnx/model_quantized.onnx\" : \"onnx/model.onnx\");\n const url = `https://huggingface.co/${this.model}/resolve/main/${onnxSubpath}`;\n process.stderr.write(`Downloading ONNX model: ${this.model} (${useQuantized ? \"quantized\" : \"fp32\"})...\\n`);\n try {\n await downloadFile(url, modelPath);\n } catch (err: any) {\n if (useQuantized && err?.message?.includes(\"404\")) {\n // Quantized not available for this model — fall back to fp32\n process.stderr.write(`Quantized model not available, falling back to fp32\\n`);\n useQuantized = false;\n this.modelPath = join(modelDir, \"model.onnx\");\n const fp32Subpath = ONNX_MODEL_PATHS[this.model] ?? \"onnx/model.onnx\";\n const fp32Url = `https://huggingface.co/${this.model}/resolve/main/${fp32Subpath}`;\n process.stderr.write(`Downloading ONNX model: ${this.model} (fp32)...\\n`);\n await downloadFile(fp32Url, this.modelPath);\n } else {\n throw err;\n }\n }\n process.stderr.write(`Model downloaded to ${modelDir}\\n`);\n }\n // Load tokenizer (uses HF transformers tokenizer infrastructure)\n this.tokenizer = await AutoTokenizer.from_pretrained(this.model, {\n cache_dir: CACHE_DIR,\n });\n\n // Create ONNX inference session (use this.modelPath — may have been updated by fallback)\n this.session = await ort.InferenceSession.create(this.modelPath, {\n executionProviders: [label === \"native\" ? \"cpu\" : \"wasm\"],\n });\n\n // Determine dimensions from a test embedding\n const test = await this.embed(\"test\");\n this.dimensions = test.length;\n this.initialized = true;\n\n const modelShort = this.model.split(\"/\").pop() ?? this.model;\n process.stderr.write(`Embedder ready (${modelShort}, ${label}, ${this.dimensions}d, batch=${this.batchSize})\\n`);\n }\n\n async embed(text: string): Promise<Float32Array> {\n if (!this.session || !this.tokenizer || !this.ort)\n throw new Error(\"Embedder not initialized. Call init() first.\");\n\n // Tokenize\n const encoded = await this.tokenizer(text, {\n padding: true,\n truncation: true,\n max_length: 512,\n return_tensor: false,\n });\n\n const inputIdsRaw: number[] = Array.from(encoded.input_ids.data ?? encoded.input_ids);\n const attentionMaskRaw: number[] = Array.from(encoded.attention_mask.data ?? encoded.attention_mask);\n const seqLen = inputIdsRaw.length;\n\n // Build ONNX input tensors (most models expect int64)\n const inputIds = new this.ort.Tensor(\n \"int64\",\n BigInt64Array.from(inputIdsRaw.map(BigInt)),\n [1, seqLen]\n );\n const attentionMask = new this.ort.Tensor(\n \"int64\",\n BigInt64Array.from(attentionMaskRaw.map(BigInt)),\n [1, seqLen]\n );\n\n const feeds: Record<string, unknown> = { input_ids: inputIds, attention_mask: attentionMask };\n\n // Some models need token_type_ids\n if (this.session.inputNames.includes(\"token_type_ids\")) {\n feeds.token_type_ids = new this.ort.Tensor(\n \"int64\",\n new BigInt64Array(seqLen),\n [1, seqLen]\n );\n }\n\n // Run inference\n const output = await this.session.run(feeds);\n const outputTensor = output[this.session.outputNames[0]];\n const hiddenSize = outputTensor.dims[outputTensor.dims.length - 1];\n\n // Mean pooling with attention mask + L2 normalization\n return this.meanPoolAndNormalize(outputTensor.data, attentionMaskRaw, seqLen, hiddenSize);\n }\n\n private meanPoolAndNormalize(\n embeddings: Float32Array,\n attentionMask: number[],\n seqLen: number,\n hiddenSize: number\n ): Float32Array {\n const result = new Float32Array(hiddenSize);\n let maskSum = 0;\n\n for (let t = 0; t < seqLen; t++) {\n const mask = attentionMask[t];\n maskSum += mask;\n const offset = t * hiddenSize;\n for (let d = 0; d < hiddenSize; d++) {\n result[d] += embeddings[offset + d] * mask;\n }\n }\n\n if (maskSum > 0) {\n for (let d = 0; d < hiddenSize; d++) result[d] /= maskSum;\n }\n\n // L2 normalize\n let norm = 0;\n for (let d = 0; d < hiddenSize; d++) norm += result[d] * result[d];\n norm = Math.sqrt(norm);\n if (norm > 0) {\n for (let d = 0; d < hiddenSize; d++) result[d] /= norm;\n }\n\n return result;\n }\n\n // Mean pool + L2 normalize the output of a batched ONNX forward pass.\n // outputData: flat Float32Array of shape [batchSize, seqLen, hiddenSize]\n // maskData: flat number[] of shape [batchSize, seqLen]\n private meanPoolAndNormalizeMany(\n outputData: Float32Array,\n maskData: number[],\n batchSize: number,\n seqLen: number,\n hiddenSize: number\n ): Float32Array[] {\n const results: Float32Array[] = [];\n for (let b = 0; b < batchSize; b++) {\n const result = new Float32Array(hiddenSize);\n let maskSum = 0;\n for (let t = 0; t < seqLen; t++) {\n const mask = maskData[b * seqLen + t];\n maskSum += mask;\n const offset = (b * seqLen + t) * hiddenSize;\n for (let d = 0; d < hiddenSize; d++) {\n result[d] += outputData[offset + d] * mask;\n }\n }\n if (maskSum > 0) {\n for (let d = 0; d < hiddenSize; d++) result[d] /= maskSum;\n }\n // L2 normalize\n let norm = 0;\n for (let d = 0; d < hiddenSize; d++) norm += result[d] * result[d];\n norm = Math.sqrt(norm);\n if (norm > 0) {\n for (let d = 0; d < hiddenSize; d++) result[d] /= norm;\n }\n results.push(result);\n }\n return results;\n }\n\n // Embed a sub-batch of texts (length <= batchSize) in a single ONNX forward pass.\n //\n // Tokenizes each text individually (well-defined output format for all HF versions),\n // then manually pads to the longest sequence in the batch and builds a [n, seqLen]\n // tensor for one ONNX call. The speedup is from batching the ONNX inference —\n // individual tokenization is negligible (<1ms each).\n private async embedSubBatch(texts: string[]): Promise<Float32Array[]> {\n if (!this.session || !this.tokenizer || !this.ort)\n throw new Error(\"Embedder not initialized. Call init() first.\");\n\n const n = texts.length;\n\n // Tokenize each text individually — avoids ambiguous batch tokenizer output format\n const encodings = await Promise.all(\n texts.map((text) =>\n this.tokenizer!(text, {\n padding: false,\n truncation: true,\n max_length: 512,\n return_tensor: false,\n })\n )\n );\n\n // Extract flat token arrays and find max sequence length for this batch\n const tokenized = encodings.map((enc) => ({\n ids: Array.from(enc.input_ids.data ?? enc.input_ids) as number[],\n mask: Array.from(enc.attention_mask.data ?? enc.attention_mask) as number[],\n }));\n const seqLen = Math.max(...tokenized.map((t) => t.ids.length));\n\n // Build flat padded tensors [n * seqLen] — pad with 0 (PAD token, zero attention)\n const flatIds = new BigInt64Array(n * seqLen);\n const flatMask = new BigInt64Array(n * seqLen);\n const flatMaskNums = new Array<number>(n * seqLen).fill(0);\n\n for (let i = 0; i < n; i++) {\n const { ids, mask } = tokenized[i];\n for (let j = 0; j < ids.length; j++) {\n flatIds[i * seqLen + j] = BigInt(ids[j]);\n flatMask[i * seqLen + j] = BigInt(mask[j]);\n flatMaskNums[i * seqLen + j] = mask[j];\n }\n // Positions beyond ids.length remain 0 (padding)\n }\n\n // Build batched ONNX tensors [n, seqLen]\n const inputIds = new this.ort.Tensor(\"int64\", flatIds, [n, seqLen]);\n const attentionMask = new this.ort.Tensor(\"int64\", flatMask, [n, seqLen]);\n\n const feeds: Record<string, unknown> = { input_ids: inputIds, attention_mask: attentionMask };\n\n if (this.session.inputNames.includes(\"token_type_ids\")) {\n feeds.token_type_ids = new this.ort.Tensor(\n \"int64\",\n new BigInt64Array(n * seqLen),\n [n, seqLen]\n );\n }\n\n // Single forward pass → output shape [n, seqLen, hiddenSize]\n const output = await this.session.run(feeds);\n const outputTensor = output[this.session.outputNames[0]];\n const hiddenSize = outputTensor.dims[outputTensor.dims.length - 1];\n\n return this.meanPoolAndNormalizeMany(\n outputTensor.data,\n flatMaskNums,\n n,\n seqLen,\n hiddenSize\n );\n }\n\n async embedBatch(\n texts: string[],\n onProgress?: (embedded: number, total: number, subBatch?: Float32Array[]) => Promise<void> | void\n ): Promise<Float32Array[]> {\n // Workers path (disabled by default; kept for --workers N users)\n if (this.numWorkers > 1 && texts.length >= this.numWorkers * 2) {\n return this.embedBatchParallel(texts, onProgress);\n }\n\n // True batched inference: slice into sub-batches and run one ONNX call each\n const results: Float32Array[] = [];\n for (let i = 0; i < texts.length; i += this.batchSize) {\n const subBatch = texts.slice(i, i + this.batchSize);\n const embeddings = await this.embedSubBatch(subBatch);\n results.push(...embeddings);\n await onProgress?.(Math.min(i + subBatch.length, texts.length), texts.length, embeddings);\n }\n return results;\n }\n\n private async embedBatchParallel(\n texts: string[],\n onProgress?: (embedded: number, total: number, subBatch?: Float32Array[]) => Promise<void> | void\n ): Promise<Float32Array[]> {\n // Resolve worker script path. With tsup splitting, embedder code may land\n // in a top-level chunk (dist/chunk-*.js) rather than dist/core/index.js,\n // so we try two locations: adjacent to this chunk, and dist/core/ relative\n // to the package root (two levels up from a dist/ chunk file).\n const thisDir = dirname(fileURLToPath(import.meta.url));\n let workerPath = join(thisDir, \"embed-worker.js\");\n if (!existsSync(workerPath)) {\n // Chunk file at dist/ level — worker is in dist/core/\n workerPath = join(thisDir, \"core\", \"embed-worker.js\");\n }\n\n if (!existsSync(workerPath)) {\n // Fallback to serial batched if worker script not found\n process.stderr.write(\"Worker script not found, falling back to batched embedding\\n\");\n return this.embedBatch(texts, onProgress);\n }\n\n // Split texts into chunks for each worker\n const chunkSize = Math.ceil(texts.length / this.numWorkers);\n const chunks: { texts: string[]; startIndex: number }[] = [];\n for (let i = 0; i < texts.length; i += chunkSize) {\n chunks.push({ texts: texts.slice(i, i + chunkSize), startIndex: i });\n }\n\n const allResults = new Array<Float32Array>(texts.length);\n let totalDone = 0;\n\n const workerPromises = chunks.map((chunk) => {\n return new Promise<void>((resolve, reject) => {\n const worker = new Worker(workerPath, {\n workerData: {\n modelPath: this.modelPath,\n modelName: this.model,\n cacheDir: CACHE_DIR,\n runtimeLabel: this.runtimeLabel,\n batchSize: this.batchSize,\n },\n });\n\n worker.on(\"message\", (msg: any) => {\n if (msg.type === \"ready\") {\n worker.postMessage({ type: \"embed\", texts: chunk.texts, startIndex: chunk.startIndex });\n } else if (msg.type === \"progress\") {\n totalDone++;\n onProgress?.(totalDone, texts.length);\n } else if (msg.type === \"result\") {\n for (let i = 0; i < msg.embeddings.length; i++) {\n allResults[chunk.startIndex + i] = new Float32Array(msg.embeddings[i]);\n }\n worker.terminate();\n resolve();\n } else if (msg.type === \"error\") {\n worker.terminate();\n reject(new Error(msg.error));\n }\n });\n\n worker.on(\"error\", (err) => {\n worker.terminate();\n reject(err);\n });\n });\n });\n\n await Promise.all(workerPromises);\n return allResults;\n }\n\n getDimensions(): number {\n return this.dimensions;\n }\n\n getModel(): string {\n return this.model;\n }\n\n getRuntime(): RuntimeLabel {\n return this.runtimeLabel;\n }\n\n async saveEmbeddings(\n embeddings: Map<string, Float32Array>,\n indexPath: string\n ): Promise<void> {\n const entries: Array<{ key: string; data: number[] }> = [];\n for (const [key, vec] of embeddings) {\n entries.push({ key, data: Array.from(vec) });\n }\n await writeFile(join(indexPath, \"embeddings.json\"), JSON.stringify(entries));\n }\n\n async loadEmbeddings(\n indexPath: string\n ): Promise<Map<string, Float32Array>> {\n const filePath = join(indexPath, \"embeddings.json\");\n if (!existsSync(filePath)) return new Map();\n\n const raw = await readFile(filePath, \"utf-8\");\n const entries: Array<{ key: string; data: number[] }> = JSON.parse(raw);\n const map = new Map<string, Float32Array>();\n for (const entry of entries) {\n map.set(entry.key, new Float32Array(entry.data));\n }\n return map;\n }\n}\n","import Graph from \"graphology\";\nimport { bfsFromNode } from \"graphology-traversal\";\nimport { bidirectional } from \"graphology-shortest-path\";\nimport type { IndexedDocument, GraphNode, GraphEdge, GraphStats } from \"./types.js\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\n/**\n * Tags shared by more than this many docs are too generic to be meaningful\n * graph edges (e.g. \"api\", \"testing\"). Only specific/rare tags create edges.\n * Docs without frontmatter are unaffected — their inline #tags still participate\n * but only if those tags are specific enough to pass this threshold.\n */\nconst TAG_EDGE_MAX_DOCS = 15;\n\nexport class GraphBuilder {\n private graph: Graph;\n\n constructor() {\n this.graph = new Graph({ type: \"directed\", multi: false });\n }\n\n buildFromDocuments(documents: IndexedDocument[]): void {\n this.graph.clear();\n\n // Add nodes — store optional metadata fields when present\n for (const doc of documents) {\n this.graph.addNode(doc.path, {\n title: doc.title,\n tags: doc.tags,\n ...(doc.status !== undefined && { status: doc.status }),\n ...(doc.loadPriority !== undefined && { loadPriority: doc.loadPriority }),\n });\n }\n\n const pathLookup = new Map<string, string>();\n for (const doc of documents) {\n const nameNoExt = doc.path.replace(/\\.md$/, \"\");\n const basename = nameNoExt.split(\"/\").pop()!;\n pathLookup.set(basename.toLowerCase(), doc.path);\n pathLookup.set(nameNoExt.toLowerCase(), doc.path);\n }\n\n // Add wikilink edges (weight 1.0)\n for (const doc of documents) {\n for (const link of doc.wikilinks) {\n const target = pathLookup.get(link.toLowerCase());\n if (target && target !== doc.path && !this.graph.hasEdge(doc.path, target)) {\n this.graph.addEdge(doc.path, target, { type: \"wikilink\", weight: 1.0 });\n }\n }\n }\n\n // Add related_docs edges (weight 1.0) — only present when frontmatter has related_docs\n // Falls back gracefully: docs without this field are simply skipped\n for (const doc of documents) {\n if (!doc.relatedDocs?.length) continue;\n for (const ref of doc.relatedDocs) {\n // Try full normalized path first, then basename — same strategy as wikilinks\n const normalized = ref.replace(/\\.md$/, \"\").toLowerCase();\n const base = normalized.split(\"/\").pop()!;\n const target = pathLookup.get(normalized) ?? pathLookup.get(base);\n if (target && target !== doc.path && !this.graph.hasEdge(doc.path, target)) {\n this.graph.addEdge(doc.path, target, { type: \"related\", weight: 1.0 });\n }\n }\n }\n\n // Add tag-based edges (weight 0.5) — capped at TAG_EDGE_MAX_DOCS per tag.\n // Generic tags shared by many docs (e.g. \"api\", \"testing\") create noise;\n // only specific tags (e.g. \"qdrant\", \"celery\") create meaningful connections.\n const tagToNotes = new Map<string, string[]>();\n for (const doc of documents) {\n for (const tag of doc.tags) {\n const notes = tagToNotes.get(tag) ?? [];\n notes.push(doc.path);\n tagToNotes.set(tag, notes);\n }\n }\n\n for (const [, notes] of tagToNotes) {\n if (notes.length >= TAG_EDGE_MAX_DOCS) continue; // too generic — skip\n for (let i = 0; i < notes.length; i++) {\n for (let j = i + 1; j < notes.length; j++) {\n if (!this.graph.hasEdge(notes[i], notes[j])) {\n this.graph.addEdge(notes[i], notes[j], { type: \"tag\", weight: 0.5 });\n }\n if (!this.graph.hasEdge(notes[j], notes[i])) {\n this.graph.addEdge(notes[j], notes[i], { type: \"tag\", weight: 0.5 });\n }\n }\n }\n }\n }\n\n backlinks(notePath: string): GraphNode[] {\n if (!this.graph.hasNode(notePath)) return [];\n return this.graph.inNeighbors(notePath).map((n) => this.nodeToGraphNode(n));\n }\n\n forwardlinks(notePath: string): GraphNode[] {\n if (!this.graph.hasNode(notePath)) return [];\n return this.graph.outNeighbors(notePath).map((n) => this.nodeToGraphNode(n));\n }\n\n findPath(from: string, to: string): string[] | null {\n if (!this.graph.hasNode(from) || !this.graph.hasNode(to)) return null;\n const path = bidirectional(this.graph, from, to);\n return path;\n }\n\n searchGraph(concept: string, maxDepth = 2, limit = 20): GraphNode[] {\n const lc = concept.toLowerCase();\n\n const directMatches = new Set<string>(\n this.graph.nodes().filter((n) => {\n const attrs = this.graph.getNodeAttributes(n);\n const title = typeof attrs.title === \"string\" ? attrs.title : String(attrs.title ?? \"\");\n return (\n n.toLowerCase().includes(lc) ||\n title.toLowerCase().includes(lc) ||\n (attrs.tags as string[] | undefined)?.some((t) => t.toLowerCase().includes(lc))\n );\n })\n );\n\n const visited = new Set<string>();\n for (const start of directMatches) {\n bfsFromNode(this.graph, start, (_node, _attr, depth) => {\n if (visited.size >= limit * 3) return true; // gather 3x limit before ranking\n visited.add(_node);\n return depth >= maxDepth;\n });\n }\n\n // Sort: direct matches first, then by loadPriority desc, then by degree desc\n // deprecated/archived nodes sort to the end\n const ranked = [...visited].sort((a, b) => {\n const aAttrs = this.graph.getNodeAttributes(a);\n const bAttrs = this.graph.getNodeAttributes(b);\n const aDeprecated = aAttrs.status === \"deprecated\" || aAttrs.status === \"archived\" ? 1 : 0;\n const bDeprecated = bAttrs.status === \"deprecated\" || bAttrs.status === \"archived\" ? 1 : 0;\n if (aDeprecated !== bDeprecated) return aDeprecated - bDeprecated;\n const aDirect = directMatches.has(a) ? 0 : 1;\n const bDirect = directMatches.has(b) ? 0 : 1;\n if (aDirect !== bDirect) return aDirect - bDirect;\n const aPriority = (aAttrs.loadPriority as number | undefined) ?? 5;\n const bPriority = (bAttrs.loadPriority as number | undefined) ?? 5;\n if (aPriority !== bPriority) return bPriority - aPriority;\n return this.graph.degree(b) - this.graph.degree(a);\n });\n\n return ranked.slice(0, limit).map((n) => this.nodeToGraphNode(n));\n }\n\n statistics(): GraphStats {\n const nodes = this.graph.order;\n const edges = this.graph.size;\n const orphans = this.graph.nodes().filter(\n (n) => this.graph.degree(n) === 0\n );\n\n const connections = this.graph.nodes().map((n) => ({\n path: n,\n connections: this.graph.degree(n),\n }));\n connections.sort((a, b) => b.connections - a.connections);\n\n const maxPossibleEdges = nodes * (nodes - 1);\n const density = maxPossibleEdges > 0 ? edges / maxPossibleEdges : 0;\n\n return {\n totalNodes: nodes,\n totalEdges: edges,\n orphanCount: orphans.length,\n mostConnected: connections.slice(0, 10),\n density,\n };\n }\n\n private nodeToGraphNode(nodePath: string): GraphNode {\n const attrs = this.graph.getNodeAttributes(nodePath);\n return {\n path: nodePath,\n title: typeof attrs.title === \"string\" ? attrs.title : nodePath,\n tags: (attrs.tags as string[]) || [],\n linkCount: this.graph.outDegree(nodePath),\n backlinkCount: this.graph.inDegree(nodePath),\n ...(attrs.loadPriority !== undefined && { loadPriority: attrs.loadPriority as number }),\n ...(attrs.status !== undefined && { status: attrs.status as string }),\n };\n }\n\n async save(indexPath: string): Promise<void> {\n const data = this.graph.export();\n await writeFile(join(indexPath, \"graph.json\"), JSON.stringify(data));\n }\n\n async load(indexPath: string): Promise<boolean> {\n const filePath = join(indexPath, \"graph.json\");\n if (!existsSync(filePath)) return false;\n\n const raw = await readFile(filePath, \"utf-8\");\n const data = JSON.parse(raw);\n this.graph.import(data);\n return true;\n }\n\n getGraph(): Graph {\n return this.graph;\n }\n}\n","import hnswlib from \"hnswlib-node\";\nconst { HierarchicalNSW } = hnswlib;\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport type { SearchResult } from \"./types.js\";\n\ninterface ChunkMeta {\n docPath: string;\n chunkIndex: number;\n text: string;\n}\n\nexport class VectorIndex {\n private index: InstanceType<typeof HierarchicalNSW> | null = null;\n private dimensions: number;\n private chunkMeta: ChunkMeta[] = [];\n\n constructor(dimensions: number) {\n this.dimensions = dimensions;\n }\n\n build(\n embeddings: Float32Array[],\n meta: ChunkMeta[]\n ): void {\n if (embeddings.length === 0) {\n this.index = null;\n this.chunkMeta = [];\n return;\n }\n\n this.index = new HierarchicalNSW(\"cosine\", this.dimensions);\n this.index.initIndex(embeddings.length);\n\n for (let i = 0; i < embeddings.length; i++) {\n this.index.addPoint(Array.from(embeddings[i]), i);\n }\n\n this.chunkMeta = meta;\n }\n\n search(queryEmbedding: Float32Array, k: number = 10): SearchResult[] {\n if (!this.index || this.chunkMeta.length === 0) return [];\n\n const numResults = Math.min(k, this.chunkMeta.length);\n const result = this.index.searchKnn(Array.from(queryEmbedding), numResults);\n\n const seen = new Set<string>();\n const results: SearchResult[] = [];\n\n for (let i = 0; i < result.neighbors.length; i++) {\n const idx = result.neighbors[i];\n const meta = this.chunkMeta[idx];\n if (!meta || seen.has(meta.docPath)) continue;\n seen.add(meta.docPath);\n\n results.push({\n path: meta.docPath,\n title: meta.docPath,\n score: 1 - result.distances[i],\n snippet: meta.text.slice(0, 200),\n matchedChunk: meta.text,\n });\n }\n\n return results;\n }\n\n async save(indexPath: string): Promise<void> {\n if (!this.index) return;\n\n this.index.writeIndexSync(join(indexPath, \"hnsw.bin\"));\n await writeFile(\n join(indexPath, \"hnsw-meta.json\"),\n JSON.stringify(this.chunkMeta)\n );\n }\n\n async load(indexPath: string): Promise<boolean> {\n const hnswPath = join(indexPath, \"hnsw.bin\");\n const metaPath = join(indexPath, \"hnsw-meta.json\");\n\n if (!existsSync(hnswPath) || !existsSync(metaPath)) return false;\n\n const raw = await readFile(metaPath, \"utf-8\");\n this.chunkMeta = JSON.parse(raw);\n\n this.index = new HierarchicalNSW(\"cosine\", this.dimensions);\n this.index.initIndex(this.chunkMeta.length);\n this.index.readIndexSync(hnswPath);\n\n return true;\n }\n\n getChunkMeta(): ChunkMeta[] {\n return this.chunkMeta;\n }\n}\n","import type { IndexedDocument, SearchResult, SearchTextOptions } from \"./types.js\";\nimport { minimatch } from \"minimatch\";\n\nexport class TextSearch {\n private documents: IndexedDocument[] = [];\n\n setDocuments(documents: IndexedDocument[]): void {\n this.documents = documents;\n }\n\n search(options: SearchTextOptions): SearchResult[] {\n const { pattern, regex, caseSensitive, pathGlob, tagFilter, limit = 20 } = options;\n\n let matcher: (text: string) => { matched: boolean; index: number };\n\n if (regex) {\n const flags = caseSensitive ? \"g\" : \"gi\";\n const re = new RegExp(pattern, flags);\n matcher = (text) => {\n re.lastIndex = 0;\n const m = re.exec(text);\n return { matched: !!m, index: m?.index ?? -1 };\n };\n } else {\n const needle = caseSensitive ? pattern : pattern.toLowerCase();\n matcher = (text) => {\n const haystack = caseSensitive ? text : text.toLowerCase();\n const idx = haystack.indexOf(needle);\n return { matched: idx >= 0, index: idx };\n };\n }\n\n const results: SearchResult[] = [];\n\n for (const doc of this.documents) {\n // Path filter\n if (pathGlob && !minimatch(doc.path, pathGlob)) continue;\n\n // Tag filter\n if (tagFilter?.length) {\n const hasTag = tagFilter.some((t) => doc.tags.includes(t));\n if (!hasTag) continue;\n }\n\n const { matched, index } = matcher(doc.content);\n if (!matched) continue;\n\n const snippetStart = Math.max(0, index - 80);\n const snippetEnd = Math.min(doc.content.length, index + 120);\n const snippet = doc.content.slice(snippetStart, snippetEnd).trim();\n\n results.push({\n path: doc.path,\n title: doc.title,\n score: 1.0,\n snippet: (snippetStart > 0 ? \"...\" : \"\") + snippet + (snippetEnd < doc.content.length ? \"...\" : \"\"),\n });\n\n if (results.length >= limit) break;\n }\n\n return results;\n }\n}\n","import { readFile, writeFile, unlink, rename, mkdir } from \"node:fs/promises\";\nimport { dirname, join, relative } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { glob } from \"glob\";\nimport matter from \"gray-matter\";\nimport type { UpdateNoteOptions } from \"./types.js\";\n\nexport class NoteCrud {\n private notesPath: string;\n\n constructor(notesPath: string) {\n this.notesPath = notesPath;\n }\n\n async create(\n relativePath: string,\n content: string,\n frontmatter?: Record<string, unknown>\n ): Promise<string> {\n const absPath = join(this.notesPath, relativePath);\n if (existsSync(absPath)) {\n throw new Error(`Note already exists: ${relativePath}`);\n }\n\n await mkdir(dirname(absPath), { recursive: true });\n\n // Merge auto-stamps with caller-supplied frontmatter (caller wins on conflicts)\n const stamps = computeStamps(content);\n const merged = { ...stamps, ...(frontmatter ?? {}) };\n const fileContent = matter.stringify(content, merged);\n\n await writeFile(absPath, fileContent, \"utf-8\");\n return relativePath;\n }\n\n async read(relativePath: string): Promise<string> {\n const absPath = join(this.notesPath, relativePath);\n return readFile(absPath, \"utf-8\");\n }\n\n async readMultiple(paths: string[]): Promise<Map<string, string>> {\n const results = new Map<string, string>();\n await Promise.all(\n paths.map(async (p) => {\n try {\n const content = await this.read(p);\n results.set(p, content);\n } catch {\n results.set(p, `[Error: could not read ${p}]`);\n }\n })\n );\n return results;\n }\n\n async update(\n relativePath: string,\n content: string,\n options: UpdateNoteOptions\n ): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n if (!existsSync(absPath)) {\n throw new Error(`Note does not exist: ${relativePath}`);\n }\n\n const existing = await readFile(absPath, \"utf-8\");\n\n let updated: string;\n\n switch (options.mode) {\n case \"overwrite\":\n updated = content;\n break;\n\n case \"append\":\n updated = existing + \"\\n\" + content;\n break;\n\n case \"prepend\": {\n const { data, content: body } = matter(existing);\n const newBody = content + \"\\n\" + body;\n updated = Object.keys(data).length > 0 ? matter.stringify(newBody, data) : newBody;\n break;\n }\n\n case \"patch-by-heading\": {\n if (!options.heading) throw new Error(\"patch-by-heading requires a heading\");\n updated = this.patchByHeading(existing, options.heading, content);\n break;\n }\n }\n\n // Re-parse the final content and inject updated stamps\n // (preserves all existing frontmatter, only overwrites the three auto fields)\n const { data: existingFm, content: body } = matter(updated);\n const stamps = computeStamps(body);\n const newFm = { ...existingFm, ...stamps };\n await writeFile(absPath, matter.stringify(body, newFm), \"utf-8\");\n }\n\n async delete(relativePath: string): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n if (!existsSync(absPath)) {\n throw new Error(`Note does not exist: ${relativePath}`);\n }\n await unlink(absPath);\n }\n\n async move(fromPath: string, toPath: string): Promise<void> {\n const absFrom = join(this.notesPath, fromPath);\n const absTo = join(this.notesPath, toPath);\n\n if (!existsSync(absFrom)) {\n throw new Error(`Note does not exist: ${fromPath}`);\n }\n if (existsSync(absTo)) {\n throw new Error(`Destination already exists: ${toPath}`);\n }\n\n await mkdir(dirname(absTo), { recursive: true });\n await rename(absFrom, absTo);\n\n // Update wikilinks in other files that reference the old path\n await this.updateWikilinksAfterMove(fromPath, toPath);\n }\n\n private async updateWikilinksAfterMove(\n oldPath: string,\n newPath: string\n ): Promise<void> {\n const oldName = oldPath.replace(/\\.md$/, \"\").split(\"/\").pop()!;\n const newName = newPath.replace(/\\.md$/, \"\").split(\"/\").pop()!;\n\n if (oldName === newName) return;\n\n const files = await glob(\"**/*.md\", { cwd: this.notesPath });\n\n for (const file of files) {\n const absPath = join(this.notesPath, file);\n const content = await readFile(absPath, \"utf-8\");\n\n const pattern = new RegExp(`\\\\[\\\\[${escapeRegex(oldName)}(\\\\|[^\\\\]]*)?\\\\]\\\\]`, \"g\");\n if (!pattern.test(content)) continue;\n\n const updated = content.replace(pattern, `[[${newName}$1]]`);\n await writeFile(absPath, updated, \"utf-8\");\n }\n }\n\n private patchByHeading(\n content: string,\n heading: string,\n newContent: string\n ): string {\n const lines = content.split(\"\\n\");\n const headingPattern = new RegExp(`^#{1,6}\\\\s+${escapeRegex(heading)}\\\\s*$`, \"i\");\n\n let headingIndex = -1;\n let headingLevel = 0;\n\n for (let i = 0; i < lines.length; i++) {\n if (headingPattern.test(lines[i])) {\n headingIndex = i;\n const match = lines[i].match(/^(#{1,6})\\s+/);\n headingLevel = match ? match[1].length : 1;\n break;\n }\n }\n\n if (headingIndex === -1) {\n throw new Error(`Heading not found: ${heading}`);\n }\n\n // Find the end of this section (next heading of same or higher level)\n let endIndex = lines.length;\n for (let i = headingIndex + 1; i < lines.length; i++) {\n const match = lines[i].match(/^(#{1,6})\\s+/);\n if (match && match[1].length <= headingLevel) {\n endIndex = i;\n break;\n }\n }\n\n const before = lines.slice(0, headingIndex + 1);\n const after = lines.slice(endIndex);\n\n return [...before, \"\", newContent, \"\", ...after].join(\"\\n\");\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Compute the three auto-stamp fields from note body text.\n * These are always factual/computable — no editorial judgment required.\n * - last_updated: today's date (YYYY-MM-DD)\n * - word_count: whitespace-separated token count\n * - estimated_read_time: assumes ~200 wpm average reading speed\n */\nfunction computeStamps(body: string): Record<string, unknown> {\n const today = new Date().toISOString().slice(0, 10); // YYYY-MM-DD\n const wordCount = body.trim() ? body.trim().split(/\\s+/).length : 0;\n const minutes = Math.max(1, Math.ceil(wordCount / 200));\n return {\n last_updated: today,\n word_count: wordCount,\n estimated_read_time: `${minutes} min read`,\n };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { glob } from \"glob\";\nimport matter from \"gray-matter\";\n\nexport class FrontmatterManager {\n private notesPath: string;\n\n constructor(notesPath: string) {\n this.notesPath = notesPath;\n }\n\n async get(relativePath: string): Promise<Record<string, unknown>> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data } = matter(raw);\n return data;\n }\n\n async update(\n relativePath: string,\n fields: Record<string, unknown>\n ): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n\n for (const [key, value] of Object.entries(fields)) {\n if (value === null || value === undefined) {\n delete data[key];\n } else {\n data[key] = value;\n }\n }\n\n const updated = matter.stringify(content, data);\n await writeFile(absPath, updated, \"utf-8\");\n }\n}\n\nexport class TagManager {\n private notesPath: string;\n\n constructor(notesPath: string) {\n this.notesPath = notesPath;\n }\n\n async list(relativePath: string): Promise<string[]> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n\n const fmTags = Array.isArray(data.tags) ? (data.tags as string[]) : [];\n const inlineTags = [...content.matchAll(/(?:^|\\s)#([a-zA-Z][\\w-/]*)/g)].map(\n (m) => m[1]\n );\n\n return [...new Set([...fmTags, ...inlineTags])];\n }\n\n async add(relativePath: string, tags: string[]): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n\n const existing = Array.isArray(data.tags) ? (data.tags as string[]) : [];\n const merged = [...new Set([...existing, ...tags])];\n data.tags = merged;\n\n const updated = matter.stringify(content, data);\n await writeFile(absPath, updated, \"utf-8\");\n }\n\n async remove(relativePath: string, tags: string[]): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n\n // Remove from frontmatter\n if (Array.isArray(data.tags)) {\n data.tags = (data.tags as string[]).filter((t) => !tags.includes(t));\n }\n\n // Remove inline tags\n let updatedContent = content;\n for (const tag of tags) {\n const pattern = new RegExp(`(^|\\\\s)#${escapeRegex(tag)}(?=\\\\s|$)`, \"g\");\n updatedContent = updatedContent.replace(pattern, \"$1\");\n }\n\n const updated = matter.stringify(updatedContent, data);\n await writeFile(absPath, updated, \"utf-8\");\n }\n\n async renameVaultWide(oldTag: string, newTag: string): Promise<number> {\n const files = await glob(\"**/*.md\", { cwd: this.notesPath });\n let count = 0;\n\n for (const file of files) {\n const absPath = join(this.notesPath, file);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n let changed = false;\n\n // Rename in frontmatter\n if (Array.isArray(data.tags)) {\n const idx = (data.tags as string[]).indexOf(oldTag);\n if (idx >= 0) {\n (data.tags as string[])[idx] = newTag;\n changed = true;\n }\n }\n\n // Rename inline tags\n const pattern = new RegExp(`(^|\\\\s)#${escapeRegex(oldTag)}(?=\\\\s|$)`, \"g\");\n const updatedContent = content.replace(pattern, `$1#${newTag}`);\n if (updatedContent !== content) changed = true;\n\n if (changed) {\n const updated = matter.stringify(updatedContent, data);\n await writeFile(absPath, updated, \"utf-8\");\n count++;\n }\n }\n\n return count;\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { watch, type FSWatcher } from \"chokidar\";\nimport { EventEmitter } from \"node:events\";\n\nexport interface WatcherEvents {\n changed: (paths: string[]) => void;\n error: (error: Error) => void;\n}\n\nexport class Watcher extends EventEmitter {\n private notesPath: string;\n private fsWatcher: FSWatcher | null = null;\n private debounceMs: number;\n private pendingChanges = new Set<string>();\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private readyPromise: Promise<void> | null = null;\n private usePolling: boolean;\n\n constructor(notesPath: string, debounceMs: number = 500, usePolling: boolean = false) {\n super();\n this.notesPath = notesPath;\n this.debounceMs = debounceMs;\n this.usePolling = usePolling;\n }\n\n start(): void {\n if (this.fsWatcher) return;\n\n this.fsWatcher = watch(\"**/*.md\", {\n cwd: this.notesPath,\n ignoreInitial: true,\n followSymlinks: true,\n ignored: [\n \"**/node_modules/**\",\n \"**/.semantic-pages-index/**\",\n \"**/.git/**\",\n ],\n ...(this.usePolling ? { usePolling: true, interval: 100 } : {}),\n });\n\n this.readyPromise = new Promise<void>((resolve) => {\n this.fsWatcher!.on(\"ready\", resolve);\n });\n\n this.fsWatcher.on(\"add\", (path) => this.enqueue(path));\n this.fsWatcher.on(\"change\", (path) => this.enqueue(path));\n this.fsWatcher.on(\"unlink\", (path) => this.enqueue(path));\n this.fsWatcher.on(\"error\", (err) => this.emit(\"error\", err));\n }\n\n async ready(): Promise<void> {\n if (this.readyPromise) await this.readyPromise;\n }\n\n stop(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.fsWatcher?.close();\n this.fsWatcher = null;\n this.pendingChanges.clear();\n }\n\n private enqueue(path: string): void {\n this.pendingChanges.add(path);\n\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n const paths = [...this.pendingChanges];\n this.pendingChanges.clear();\n this.emit(\"changed\", paths);\n }, this.debounceMs);\n }\n}\n"],"mappings":"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","names":["readFile","writeFile","join","existsSync","readFile","writeFile","join","existsSync","readFile","writeFile","mkdir","dirname","join","existsSync","body","readFile","writeFile","join","glob","matter","escapeRegex"]}
@@ -7,7 +7,7 @@ import {
7
7
  TextSearch,
8
8
  VectorIndex,
9
9
  Watcher
10
- } from "../chunk-55IDPZHC.js";
10
+ } from "../chunk-P7BHYKVE.js";
11
11
  import {
12
12
  Indexer
13
13
  } from "../chunk-XNEE7Z2S.js";
@@ -7,7 +7,7 @@ import {
7
7
  TextSearch,
8
8
  VectorIndex,
9
9
  Watcher
10
- } from "../chunk-55IDPZHC.js";
10
+ } from "../chunk-P7BHYKVE.js";
11
11
  import {
12
12
  Indexer,
13
13
  __export
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theglitchking/semantic-pages",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "Semantic search + knowledge graph MCP server for any folder of markdown files",
5
5
  "type": "module",
6
6
  "main": "./dist/core/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/embedder.ts","../src/core/graph.ts","../src/core/vector.ts","../src/core/search-text.ts","../src/core/crud.ts","../src/core/frontmatter.ts","../src/core/watcher.ts"],"sourcesContent":["import { AutoTokenizer } from \"@huggingface/transformers\";\nimport { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { existsSync, createWriteStream } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { Readable } from \"node:stream\";\nimport { pipeline as streamPipeline } from \"node:stream/promises\";\nimport { Worker } from \"node:worker_threads\";\nimport { fileURLToPath } from \"node:url\";\n\n// MiniLM-L6-v2 is the default: ~3 min to index 2,853 chunks on CPU vs ~16 min for nomic.\n// nomic-embed-text-v1.5 gives higher quality embeddings but is much slower on CPU.\nconst DEFAULT_MODEL = \"sentence-transformers/all-MiniLM-L6-v2\";\nconst CACHE_DIR = join(homedir(), \".semantic-pages\", \"models\");\n// Default to 1 worker (serial). Worker threads only help on memory-rich machines\n// (each worker loads its own ONNX session). On typical dev machines\n// with <4 GB free RAM, parallel workers cause swap thrashing and are slower.\n// Enable with --workers N when you have sufficient RAM.\nconst DEFAULT_WORKERS = 1;\n// batch=16 is optimal for MiniLM on CPU (short sequences, low padding waste).\n// For larger models (nomic 768d), batch=1 is faster due to padding overhead.\nconst DEFAULT_BATCH_SIZE = 16;\n// Quantized ONNX: faster on CPU but not all models have a quantized variant.\n// MiniLM fp32 is already fast enough; nomic benefits from quantized.\n// Falls back to fp32 automatically if quantized file is not available.\nconst DEFAULT_QUANTIZED = false;\n\n// Full-precision ONNX model subpaths\nconst ONNX_MODEL_PATHS: Record<string, string> = {\n \"nomic-ai/nomic-embed-text-v1.5\": \"onnx/model.onnx\",\n \"sentence-transformers/all-MiniLM-L6-v2\": \"onnx/model.onnx\",\n};\n\n// Quantized (int8) ONNX model subpaths — faster on CPU, ~same quality\nconst ONNX_QUANTIZED_MODEL_PATHS: Record<string, string> = {\n \"nomic-ai/nomic-embed-text-v1.5\": \"onnx/model_quantized.onnx\",\n \"sentence-transformers/all-MiniLM-L6-v2\": \"onnx/model_quantized.onnx\",\n};\n\ninterface OrtSession {\n run(feeds: Record<string, unknown>): Promise<Record<string, { data: Float32Array; dims: number[] }>>;\n inputNames: string[];\n outputNames: string[];\n}\n\ninterface OrtModule {\n InferenceSession: {\n create(path: string, options?: Record<string, unknown>): Promise<OrtSession>;\n };\n Tensor: new (type: string, data: ArrayLike<number | bigint>, dims: number[]) => unknown;\n}\n\ntype RuntimeLabel = \"native\" | \"wasm\";\n\nasync function resolveOnnxRuntime(): Promise<{ ort: OrtModule; label: RuntimeLabel }> {\n try {\n const ort = await import(\"onnxruntime-node\");\n return { ort: ort as unknown as OrtModule, label: \"native\" };\n } catch {\n const ort = await import(\"onnxruntime-web\");\n return { ort: ort as unknown as OrtModule, label: \"wasm\" };\n }\n}\n\nasync function downloadFile(url: string, destPath: string): Promise<void> {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`Download failed (${response.status}): ${url}`);\n if (!response.body) throw new Error(`No response body: ${url}`);\n const fileStream = createWriteStream(destPath);\n await streamPipeline(Readable.fromWeb(response.body as never), fileStream);\n}\n\nexport class Embedder {\n private model: string;\n private session: OrtSession | null = null;\n private tokenizer: Awaited<ReturnType<typeof AutoTokenizer.from_pretrained>> | null = null;\n private ort: OrtModule | null = null;\n private dimensions = 0;\n private runtimeLabel: RuntimeLabel = \"wasm\";\n private initialized = false;\n private numWorkers: number;\n private batchSize: number;\n private quantized: boolean;\n private modelPath = \"\";\n\n constructor(\n model: string = DEFAULT_MODEL,\n numWorkers: number = DEFAULT_WORKERS,\n batchSize: number = DEFAULT_BATCH_SIZE,\n quantized: boolean = DEFAULT_QUANTIZED\n ) {\n this.model = model;\n this.numWorkers = numWorkers;\n this.batchSize = batchSize;\n this.quantized = quantized;\n }\n\n async init(): Promise<void> {\n if (this.initialized) return;\n\n const modelDir = join(CACHE_DIR, this.model.replace(/\\//g, \"--\"));\n await mkdir(modelDir, { recursive: true });\n\n // Resolve ONNX runtime (native C++ or WASM fallback)\n const { ort, label } = await resolveOnnxRuntime();\n this.ort = ort;\n this.runtimeLabel = label;\n\n // Download ONNX model if not cached. Tries quantized first if requested,\n // falls back to fp32 if the quantized file is not available for this model.\n let useQuantized = this.quantized;\n const modelFileName = useQuantized ? \"model_quantized.onnx\" : \"model.onnx\";\n this.modelPath = join(modelDir, modelFileName);\n const modelPath = this.modelPath;\n if (!existsSync(modelPath)) {\n const pathMap = useQuantized ? ONNX_QUANTIZED_MODEL_PATHS : ONNX_MODEL_PATHS;\n const onnxSubpath = pathMap[this.model] ?? (useQuantized ? \"onnx/model_quantized.onnx\" : \"onnx/model.onnx\");\n const url = `https://huggingface.co/${this.model}/resolve/main/${onnxSubpath}`;\n process.stderr.write(`Downloading ONNX model: ${this.model} (${useQuantized ? \"quantized\" : \"fp32\"})...\\n`);\n try {\n await downloadFile(url, modelPath);\n } catch (err: any) {\n if (useQuantized && err?.message?.includes(\"404\")) {\n // Quantized not available for this model — fall back to fp32\n process.stderr.write(`Quantized model not available, falling back to fp32\\n`);\n useQuantized = false;\n this.modelPath = join(modelDir, \"model.onnx\");\n const fp32Subpath = ONNX_MODEL_PATHS[this.model] ?? \"onnx/model.onnx\";\n const fp32Url = `https://huggingface.co/${this.model}/resolve/main/${fp32Subpath}`;\n process.stderr.write(`Downloading ONNX model: ${this.model} (fp32)...\\n`);\n await downloadFile(fp32Url, this.modelPath);\n } else {\n throw err;\n }\n }\n process.stderr.write(`Model downloaded to ${modelDir}\\n`);\n }\n // Load tokenizer (uses HF transformers tokenizer infrastructure)\n this.tokenizer = await AutoTokenizer.from_pretrained(this.model, {\n cache_dir: CACHE_DIR,\n });\n\n // Create ONNX inference session (use this.modelPath — may have been updated by fallback)\n this.session = await ort.InferenceSession.create(this.modelPath, {\n executionProviders: [label === \"native\" ? \"cpu\" : \"wasm\"],\n });\n\n // Determine dimensions from a test embedding\n const test = await this.embed(\"test\");\n this.dimensions = test.length;\n this.initialized = true;\n\n const modelShort = this.model.split(\"/\").pop() ?? this.model;\n process.stderr.write(`Embedder ready (${modelShort}, ${label}, ${this.dimensions}d, batch=${this.batchSize})\\n`);\n }\n\n async embed(text: string): Promise<Float32Array> {\n if (!this.session || !this.tokenizer || !this.ort)\n throw new Error(\"Embedder not initialized. Call init() first.\");\n\n // Tokenize\n const encoded = await this.tokenizer(text, {\n padding: true,\n truncation: true,\n max_length: 512,\n return_tensor: false,\n });\n\n const inputIdsRaw: number[] = Array.from(encoded.input_ids.data ?? encoded.input_ids);\n const attentionMaskRaw: number[] = Array.from(encoded.attention_mask.data ?? encoded.attention_mask);\n const seqLen = inputIdsRaw.length;\n\n // Build ONNX input tensors (most models expect int64)\n const inputIds = new this.ort.Tensor(\n \"int64\",\n BigInt64Array.from(inputIdsRaw.map(BigInt)),\n [1, seqLen]\n );\n const attentionMask = new this.ort.Tensor(\n \"int64\",\n BigInt64Array.from(attentionMaskRaw.map(BigInt)),\n [1, seqLen]\n );\n\n const feeds: Record<string, unknown> = { input_ids: inputIds, attention_mask: attentionMask };\n\n // Some models need token_type_ids\n if (this.session.inputNames.includes(\"token_type_ids\")) {\n feeds.token_type_ids = new this.ort.Tensor(\n \"int64\",\n new BigInt64Array(seqLen),\n [1, seqLen]\n );\n }\n\n // Run inference\n const output = await this.session.run(feeds);\n const outputTensor = output[this.session.outputNames[0]];\n const hiddenSize = outputTensor.dims[outputTensor.dims.length - 1];\n\n // Mean pooling with attention mask + L2 normalization\n return this.meanPoolAndNormalize(outputTensor.data, attentionMaskRaw, seqLen, hiddenSize);\n }\n\n private meanPoolAndNormalize(\n embeddings: Float32Array,\n attentionMask: number[],\n seqLen: number,\n hiddenSize: number\n ): Float32Array {\n const result = new Float32Array(hiddenSize);\n let maskSum = 0;\n\n for (let t = 0; t < seqLen; t++) {\n const mask = attentionMask[t];\n maskSum += mask;\n const offset = t * hiddenSize;\n for (let d = 0; d < hiddenSize; d++) {\n result[d] += embeddings[offset + d] * mask;\n }\n }\n\n if (maskSum > 0) {\n for (let d = 0; d < hiddenSize; d++) result[d] /= maskSum;\n }\n\n // L2 normalize\n let norm = 0;\n for (let d = 0; d < hiddenSize; d++) norm += result[d] * result[d];\n norm = Math.sqrt(norm);\n if (norm > 0) {\n for (let d = 0; d < hiddenSize; d++) result[d] /= norm;\n }\n\n return result;\n }\n\n // Mean pool + L2 normalize the output of a batched ONNX forward pass.\n // outputData: flat Float32Array of shape [batchSize, seqLen, hiddenSize]\n // maskData: flat number[] of shape [batchSize, seqLen]\n private meanPoolAndNormalizeMany(\n outputData: Float32Array,\n maskData: number[],\n batchSize: number,\n seqLen: number,\n hiddenSize: number\n ): Float32Array[] {\n const results: Float32Array[] = [];\n for (let b = 0; b < batchSize; b++) {\n const result = new Float32Array(hiddenSize);\n let maskSum = 0;\n for (let t = 0; t < seqLen; t++) {\n const mask = maskData[b * seqLen + t];\n maskSum += mask;\n const offset = (b * seqLen + t) * hiddenSize;\n for (let d = 0; d < hiddenSize; d++) {\n result[d] += outputData[offset + d] * mask;\n }\n }\n if (maskSum > 0) {\n for (let d = 0; d < hiddenSize; d++) result[d] /= maskSum;\n }\n // L2 normalize\n let norm = 0;\n for (let d = 0; d < hiddenSize; d++) norm += result[d] * result[d];\n norm = Math.sqrt(norm);\n if (norm > 0) {\n for (let d = 0; d < hiddenSize; d++) result[d] /= norm;\n }\n results.push(result);\n }\n return results;\n }\n\n // Embed a sub-batch of texts (length <= batchSize) in a single ONNX forward pass.\n //\n // Tokenizes each text individually (well-defined output format for all HF versions),\n // then manually pads to the longest sequence in the batch and builds a [n, seqLen]\n // tensor for one ONNX call. The speedup is from batching the ONNX inference —\n // individual tokenization is negligible (<1ms each).\n private async embedSubBatch(texts: string[]): Promise<Float32Array[]> {\n if (!this.session || !this.tokenizer || !this.ort)\n throw new Error(\"Embedder not initialized. Call init() first.\");\n\n const n = texts.length;\n\n // Tokenize each text individually — avoids ambiguous batch tokenizer output format\n const encodings = await Promise.all(\n texts.map((text) =>\n this.tokenizer!(text, {\n padding: false,\n truncation: true,\n max_length: 512,\n return_tensor: false,\n })\n )\n );\n\n // Extract flat token arrays and find max sequence length for this batch\n const tokenized = encodings.map((enc) => ({\n ids: Array.from(enc.input_ids.data ?? enc.input_ids) as number[],\n mask: Array.from(enc.attention_mask.data ?? enc.attention_mask) as number[],\n }));\n const seqLen = Math.max(...tokenized.map((t) => t.ids.length));\n\n // Build flat padded tensors [n * seqLen] — pad with 0 (PAD token, zero attention)\n const flatIds = new BigInt64Array(n * seqLen);\n const flatMask = new BigInt64Array(n * seqLen);\n const flatMaskNums = new Array<number>(n * seqLen).fill(0);\n\n for (let i = 0; i < n; i++) {\n const { ids, mask } = tokenized[i];\n for (let j = 0; j < ids.length; j++) {\n flatIds[i * seqLen + j] = BigInt(ids[j]);\n flatMask[i * seqLen + j] = BigInt(mask[j]);\n flatMaskNums[i * seqLen + j] = mask[j];\n }\n // Positions beyond ids.length remain 0 (padding)\n }\n\n // Build batched ONNX tensors [n, seqLen]\n const inputIds = new this.ort.Tensor(\"int64\", flatIds, [n, seqLen]);\n const attentionMask = new this.ort.Tensor(\"int64\", flatMask, [n, seqLen]);\n\n const feeds: Record<string, unknown> = { input_ids: inputIds, attention_mask: attentionMask };\n\n if (this.session.inputNames.includes(\"token_type_ids\")) {\n feeds.token_type_ids = new this.ort.Tensor(\n \"int64\",\n new BigInt64Array(n * seqLen),\n [n, seqLen]\n );\n }\n\n // Single forward pass → output shape [n, seqLen, hiddenSize]\n const output = await this.session.run(feeds);\n const outputTensor = output[this.session.outputNames[0]];\n const hiddenSize = outputTensor.dims[outputTensor.dims.length - 1];\n\n return this.meanPoolAndNormalizeMany(\n outputTensor.data,\n flatMaskNums,\n n,\n seqLen,\n hiddenSize\n );\n }\n\n async embedBatch(\n texts: string[],\n onProgress?: (embedded: number, total: number, subBatch?: Float32Array[]) => Promise<void> | void\n ): Promise<Float32Array[]> {\n // Workers path (disabled by default; kept for --workers N users)\n if (this.numWorkers > 1 && texts.length >= this.numWorkers * 2) {\n return this.embedBatchParallel(texts, onProgress);\n }\n\n // True batched inference: slice into sub-batches and run one ONNX call each\n const results: Float32Array[] = [];\n for (let i = 0; i < texts.length; i += this.batchSize) {\n const subBatch = texts.slice(i, i + this.batchSize);\n const embeddings = await this.embedSubBatch(subBatch);\n results.push(...embeddings);\n await onProgress?.(Math.min(i + subBatch.length, texts.length), texts.length, embeddings);\n }\n return results;\n }\n\n private async embedBatchParallel(\n texts: string[],\n onProgress?: (embedded: number, total: number, subBatch?: Float32Array[]) => Promise<void> | void\n ): Promise<Float32Array[]> {\n // Resolve worker script path. With tsup splitting, embedder code may land\n // in a top-level chunk (dist/chunk-*.js) rather than dist/core/index.js,\n // so we try two locations: adjacent to this chunk, and dist/core/ relative\n // to the package root (two levels up from a dist/ chunk file).\n const thisDir = dirname(fileURLToPath(import.meta.url));\n let workerPath = join(thisDir, \"embed-worker.js\");\n if (!existsSync(workerPath)) {\n // Chunk file at dist/ level — worker is in dist/core/\n workerPath = join(thisDir, \"core\", \"embed-worker.js\");\n }\n\n if (!existsSync(workerPath)) {\n // Fallback to serial batched if worker script not found\n process.stderr.write(\"Worker script not found, falling back to batched embedding\\n\");\n return this.embedBatch(texts, onProgress);\n }\n\n // Split texts into chunks for each worker\n const chunkSize = Math.ceil(texts.length / this.numWorkers);\n const chunks: { texts: string[]; startIndex: number }[] = [];\n for (let i = 0; i < texts.length; i += chunkSize) {\n chunks.push({ texts: texts.slice(i, i + chunkSize), startIndex: i });\n }\n\n const allResults = new Array<Float32Array>(texts.length);\n let totalDone = 0;\n\n const workerPromises = chunks.map((chunk) => {\n return new Promise<void>((resolve, reject) => {\n const worker = new Worker(workerPath, {\n workerData: {\n modelPath: this.modelPath,\n modelName: this.model,\n cacheDir: CACHE_DIR,\n runtimeLabel: this.runtimeLabel,\n batchSize: this.batchSize,\n },\n });\n\n worker.on(\"message\", (msg: any) => {\n if (msg.type === \"ready\") {\n worker.postMessage({ type: \"embed\", texts: chunk.texts, startIndex: chunk.startIndex });\n } else if (msg.type === \"progress\") {\n totalDone++;\n onProgress?.(totalDone, texts.length);\n } else if (msg.type === \"result\") {\n for (let i = 0; i < msg.embeddings.length; i++) {\n allResults[chunk.startIndex + i] = new Float32Array(msg.embeddings[i]);\n }\n worker.terminate();\n resolve();\n } else if (msg.type === \"error\") {\n worker.terminate();\n reject(new Error(msg.error));\n }\n });\n\n worker.on(\"error\", (err) => {\n worker.terminate();\n reject(err);\n });\n });\n });\n\n await Promise.all(workerPromises);\n return allResults;\n }\n\n getDimensions(): number {\n return this.dimensions;\n }\n\n getModel(): string {\n return this.model;\n }\n\n getRuntime(): RuntimeLabel {\n return this.runtimeLabel;\n }\n\n async saveEmbeddings(\n embeddings: Map<string, Float32Array>,\n indexPath: string\n ): Promise<void> {\n const entries: Array<{ key: string; data: number[] }> = [];\n for (const [key, vec] of embeddings) {\n entries.push({ key, data: Array.from(vec) });\n }\n await writeFile(join(indexPath, \"embeddings.json\"), JSON.stringify(entries));\n }\n\n async loadEmbeddings(\n indexPath: string\n ): Promise<Map<string, Float32Array>> {\n const filePath = join(indexPath, \"embeddings.json\");\n if (!existsSync(filePath)) return new Map();\n\n const raw = await readFile(filePath, \"utf-8\");\n const entries: Array<{ key: string; data: number[] }> = JSON.parse(raw);\n const map = new Map<string, Float32Array>();\n for (const entry of entries) {\n map.set(entry.key, new Float32Array(entry.data));\n }\n return map;\n }\n}\n","import Graph from \"graphology\";\nimport { bfsFromNode } from \"graphology-traversal\";\nimport { bidirectional } from \"graphology-shortest-path\";\nimport type { IndexedDocument, GraphNode, GraphEdge, GraphStats } from \"./types.js\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\n/**\n * Tags shared by more than this many docs are too generic to be meaningful\n * graph edges (e.g. \"api\", \"testing\"). Only specific/rare tags create edges.\n * Docs without frontmatter are unaffected — their inline #tags still participate\n * but only if those tags are specific enough to pass this threshold.\n */\nconst TAG_EDGE_MAX_DOCS = 15;\n\nexport class GraphBuilder {\n private graph: Graph;\n\n constructor() {\n this.graph = new Graph({ type: \"directed\", multi: false });\n }\n\n buildFromDocuments(documents: IndexedDocument[]): void {\n this.graph.clear();\n\n // Add nodes — store optional metadata fields when present\n for (const doc of documents) {\n this.graph.addNode(doc.path, {\n title: doc.title,\n tags: doc.tags,\n ...(doc.status !== undefined && { status: doc.status }),\n ...(doc.loadPriority !== undefined && { loadPriority: doc.loadPriority }),\n });\n }\n\n const pathLookup = new Map<string, string>();\n for (const doc of documents) {\n const nameNoExt = doc.path.replace(/\\.md$/, \"\");\n const basename = nameNoExt.split(\"/\").pop()!;\n pathLookup.set(basename.toLowerCase(), doc.path);\n pathLookup.set(nameNoExt.toLowerCase(), doc.path);\n }\n\n // Add wikilink edges (weight 1.0)\n for (const doc of documents) {\n for (const link of doc.wikilinks) {\n const target = pathLookup.get(link.toLowerCase());\n if (target && target !== doc.path && !this.graph.hasEdge(doc.path, target)) {\n this.graph.addEdge(doc.path, target, { type: \"wikilink\", weight: 1.0 });\n }\n }\n }\n\n // Add related_docs edges (weight 1.0) — only present when frontmatter has related_docs\n // Falls back gracefully: docs without this field are simply skipped\n for (const doc of documents) {\n if (!doc.relatedDocs?.length) continue;\n for (const ref of doc.relatedDocs) {\n // Try full normalized path first, then basename — same strategy as wikilinks\n const normalized = ref.replace(/\\.md$/, \"\").toLowerCase();\n const base = normalized.split(\"/\").pop()!;\n const target = pathLookup.get(normalized) ?? pathLookup.get(base);\n if (target && target !== doc.path && !this.graph.hasEdge(doc.path, target)) {\n this.graph.addEdge(doc.path, target, { type: \"related\", weight: 1.0 });\n }\n }\n }\n\n // Add tag-based edges (weight 0.5) — capped at TAG_EDGE_MAX_DOCS per tag.\n // Generic tags shared by many docs (e.g. \"api\", \"testing\") create noise;\n // only specific tags (e.g. \"qdrant\", \"celery\") create meaningful connections.\n const tagToNotes = new Map<string, string[]>();\n for (const doc of documents) {\n for (const tag of doc.tags) {\n const notes = tagToNotes.get(tag) ?? [];\n notes.push(doc.path);\n tagToNotes.set(tag, notes);\n }\n }\n\n for (const [, notes] of tagToNotes) {\n if (notes.length >= TAG_EDGE_MAX_DOCS) continue; // too generic — skip\n for (let i = 0; i < notes.length; i++) {\n for (let j = i + 1; j < notes.length; j++) {\n if (!this.graph.hasEdge(notes[i], notes[j])) {\n this.graph.addEdge(notes[i], notes[j], { type: \"tag\", weight: 0.5 });\n }\n if (!this.graph.hasEdge(notes[j], notes[i])) {\n this.graph.addEdge(notes[j], notes[i], { type: \"tag\", weight: 0.5 });\n }\n }\n }\n }\n }\n\n backlinks(notePath: string): GraphNode[] {\n if (!this.graph.hasNode(notePath)) return [];\n return this.graph.inNeighbors(notePath).map((n) => this.nodeToGraphNode(n));\n }\n\n forwardlinks(notePath: string): GraphNode[] {\n if (!this.graph.hasNode(notePath)) return [];\n return this.graph.outNeighbors(notePath).map((n) => this.nodeToGraphNode(n));\n }\n\n findPath(from: string, to: string): string[] | null {\n if (!this.graph.hasNode(from) || !this.graph.hasNode(to)) return null;\n const path = bidirectional(this.graph, from, to);\n return path;\n }\n\n searchGraph(concept: string, maxDepth = 2, limit = 20): GraphNode[] {\n const lc = concept.toLowerCase();\n\n const directMatches = new Set<string>(\n this.graph.nodes().filter((n) => {\n const attrs = this.graph.getNodeAttributes(n);\n const title = typeof attrs.title === \"string\" ? attrs.title : String(attrs.title ?? \"\");\n return (\n n.toLowerCase().includes(lc) ||\n title.toLowerCase().includes(lc) ||\n (attrs.tags as string[] | undefined)?.some((t) => t.toLowerCase().includes(lc))\n );\n })\n );\n\n const visited = new Set<string>();\n for (const start of directMatches) {\n bfsFromNode(this.graph, start, (_node, _attr, depth) => {\n if (visited.size >= limit * 3) return true; // gather 3x limit before ranking\n visited.add(_node);\n return depth >= maxDepth;\n });\n }\n\n // Sort: direct matches first, then by loadPriority desc, then by degree desc\n // deprecated/archived nodes sort to the end\n const ranked = [...visited].sort((a, b) => {\n const aAttrs = this.graph.getNodeAttributes(a);\n const bAttrs = this.graph.getNodeAttributes(b);\n const aDeprecated = aAttrs.status === \"deprecated\" || aAttrs.status === \"archived\" ? 1 : 0;\n const bDeprecated = bAttrs.status === \"deprecated\" || bAttrs.status === \"archived\" ? 1 : 0;\n if (aDeprecated !== bDeprecated) return aDeprecated - bDeprecated;\n const aDirect = directMatches.has(a) ? 0 : 1;\n const bDirect = directMatches.has(b) ? 0 : 1;\n if (aDirect !== bDirect) return aDirect - bDirect;\n const aPriority = (aAttrs.loadPriority as number | undefined) ?? 5;\n const bPriority = (bAttrs.loadPriority as number | undefined) ?? 5;\n if (aPriority !== bPriority) return bPriority - aPriority;\n return this.graph.degree(b) - this.graph.degree(a);\n });\n\n return ranked.slice(0, limit).map((n) => this.nodeToGraphNode(n));\n }\n\n statistics(): GraphStats {\n const nodes = this.graph.order;\n const edges = this.graph.size;\n const orphans = this.graph.nodes().filter(\n (n) => this.graph.degree(n) === 0\n );\n\n const connections = this.graph.nodes().map((n) => ({\n path: n,\n connections: this.graph.degree(n),\n }));\n connections.sort((a, b) => b.connections - a.connections);\n\n const maxPossibleEdges = nodes * (nodes - 1);\n const density = maxPossibleEdges > 0 ? edges / maxPossibleEdges : 0;\n\n return {\n totalNodes: nodes,\n totalEdges: edges,\n orphanCount: orphans.length,\n mostConnected: connections.slice(0, 10),\n density,\n };\n }\n\n private nodeToGraphNode(nodePath: string): GraphNode {\n const attrs = this.graph.getNodeAttributes(nodePath);\n return {\n path: nodePath,\n title: typeof attrs.title === \"string\" ? attrs.title : nodePath,\n tags: (attrs.tags as string[]) || [],\n linkCount: this.graph.outDegree(nodePath),\n backlinkCount: this.graph.inDegree(nodePath),\n ...(attrs.loadPriority !== undefined && { loadPriority: attrs.loadPriority as number }),\n ...(attrs.status !== undefined && { status: attrs.status as string }),\n };\n }\n\n async save(indexPath: string): Promise<void> {\n const data = this.graph.export();\n await writeFile(join(indexPath, \"graph.json\"), JSON.stringify(data));\n }\n\n async load(indexPath: string): Promise<boolean> {\n const filePath = join(indexPath, \"graph.json\");\n if (!existsSync(filePath)) return false;\n\n const raw = await readFile(filePath, \"utf-8\");\n const data = JSON.parse(raw);\n this.graph.import(data);\n return true;\n }\n\n getGraph(): Graph {\n return this.graph;\n }\n}\n","import hnswlib from \"hnswlib-node\";\nconst { HierarchicalNSW } = hnswlib;\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport type { SearchResult } from \"./types.js\";\n\ninterface ChunkMeta {\n docPath: string;\n chunkIndex: number;\n text: string;\n}\n\nexport class VectorIndex {\n private index: InstanceType<typeof HierarchicalNSW> | null = null;\n private dimensions: number;\n private chunkMeta: ChunkMeta[] = [];\n\n constructor(dimensions: number) {\n this.dimensions = dimensions;\n }\n\n build(\n embeddings: Float32Array[],\n meta: ChunkMeta[]\n ): void {\n if (embeddings.length === 0) {\n this.index = null;\n this.chunkMeta = [];\n return;\n }\n\n this.index = new HierarchicalNSW(\"cosine\", this.dimensions);\n this.index.initIndex(embeddings.length);\n\n for (let i = 0; i < embeddings.length; i++) {\n this.index.addPoint(Array.from(embeddings[i]), i);\n }\n\n this.chunkMeta = meta;\n }\n\n search(queryEmbedding: Float32Array, k: number = 10): SearchResult[] {\n if (!this.index || this.chunkMeta.length === 0) return [];\n\n const numResults = Math.min(k, this.chunkMeta.length);\n const result = this.index.searchKnn(Array.from(queryEmbedding), numResults);\n\n const seen = new Set<string>();\n const results: SearchResult[] = [];\n\n for (let i = 0; i < result.neighbors.length; i++) {\n const idx = result.neighbors[i];\n const meta = this.chunkMeta[idx];\n if (!meta || seen.has(meta.docPath)) continue;\n seen.add(meta.docPath);\n\n results.push({\n path: meta.docPath,\n title: meta.docPath,\n score: 1 - result.distances[i],\n snippet: meta.text.slice(0, 200),\n matchedChunk: meta.text,\n });\n }\n\n return results;\n }\n\n async save(indexPath: string): Promise<void> {\n if (!this.index) return;\n\n this.index.writeIndexSync(join(indexPath, \"hnsw.bin\"));\n await writeFile(\n join(indexPath, \"hnsw-meta.json\"),\n JSON.stringify(this.chunkMeta)\n );\n }\n\n async load(indexPath: string): Promise<boolean> {\n const hnswPath = join(indexPath, \"hnsw.bin\");\n const metaPath = join(indexPath, \"hnsw-meta.json\");\n\n if (!existsSync(hnswPath) || !existsSync(metaPath)) return false;\n\n const raw = await readFile(metaPath, \"utf-8\");\n this.chunkMeta = JSON.parse(raw);\n\n this.index = new HierarchicalNSW(\"cosine\", this.dimensions);\n this.index.initIndex(this.chunkMeta.length);\n this.index.readIndexSync(hnswPath);\n\n return true;\n }\n\n getChunkMeta(): ChunkMeta[] {\n return this.chunkMeta;\n }\n}\n","import type { IndexedDocument, SearchResult, SearchTextOptions } from \"./types.js\";\nimport { minimatch } from \"minimatch\";\n\nexport class TextSearch {\n private documents: IndexedDocument[] = [];\n\n setDocuments(documents: IndexedDocument[]): void {\n this.documents = documents;\n }\n\n search(options: SearchTextOptions): SearchResult[] {\n const { pattern, regex, caseSensitive, pathGlob, tagFilter, limit = 20 } = options;\n\n let matcher: (text: string) => { matched: boolean; index: number };\n\n if (regex) {\n const flags = caseSensitive ? \"g\" : \"gi\";\n const re = new RegExp(pattern, flags);\n matcher = (text) => {\n re.lastIndex = 0;\n const m = re.exec(text);\n return { matched: !!m, index: m?.index ?? -1 };\n };\n } else {\n const needle = caseSensitive ? pattern : pattern.toLowerCase();\n matcher = (text) => {\n const haystack = caseSensitive ? text : text.toLowerCase();\n const idx = haystack.indexOf(needle);\n return { matched: idx >= 0, index: idx };\n };\n }\n\n const results: SearchResult[] = [];\n\n for (const doc of this.documents) {\n // Path filter\n if (pathGlob && !minimatch(doc.path, pathGlob)) continue;\n\n // Tag filter\n if (tagFilter?.length) {\n const hasTag = tagFilter.some((t) => doc.tags.includes(t));\n if (!hasTag) continue;\n }\n\n const { matched, index } = matcher(doc.content);\n if (!matched) continue;\n\n const snippetStart = Math.max(0, index - 80);\n const snippetEnd = Math.min(doc.content.length, index + 120);\n const snippet = doc.content.slice(snippetStart, snippetEnd).trim();\n\n results.push({\n path: doc.path,\n title: doc.title,\n score: 1.0,\n snippet: (snippetStart > 0 ? \"...\" : \"\") + snippet + (snippetEnd < doc.content.length ? \"...\" : \"\"),\n });\n\n if (results.length >= limit) break;\n }\n\n return results;\n }\n}\n","import { readFile, writeFile, unlink, rename, mkdir } from \"node:fs/promises\";\nimport { dirname, join, relative } from \"node:path\";\nimport { existsSync } from \"node:fs\";\nimport { glob } from \"glob\";\nimport matter from \"gray-matter\";\nimport type { UpdateNoteOptions } from \"./types.js\";\n\nexport class NoteCrud {\n private notesPath: string;\n\n constructor(notesPath: string) {\n this.notesPath = notesPath;\n }\n\n async create(\n relativePath: string,\n content: string,\n frontmatter?: Record<string, unknown>\n ): Promise<string> {\n const absPath = join(this.notesPath, relativePath);\n if (existsSync(absPath)) {\n throw new Error(`Note already exists: ${relativePath}`);\n }\n\n await mkdir(dirname(absPath), { recursive: true });\n\n let fileContent: string;\n if (frontmatter && Object.keys(frontmatter).length > 0) {\n fileContent = matter.stringify(content, frontmatter);\n } else {\n fileContent = content;\n }\n\n await writeFile(absPath, fileContent, \"utf-8\");\n return relativePath;\n }\n\n async read(relativePath: string): Promise<string> {\n const absPath = join(this.notesPath, relativePath);\n return readFile(absPath, \"utf-8\");\n }\n\n async readMultiple(paths: string[]): Promise<Map<string, string>> {\n const results = new Map<string, string>();\n await Promise.all(\n paths.map(async (p) => {\n try {\n const content = await this.read(p);\n results.set(p, content);\n } catch {\n results.set(p, `[Error: could not read ${p}]`);\n }\n })\n );\n return results;\n }\n\n async update(\n relativePath: string,\n content: string,\n options: UpdateNoteOptions\n ): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n if (!existsSync(absPath)) {\n throw new Error(`Note does not exist: ${relativePath}`);\n }\n\n const existing = await readFile(absPath, \"utf-8\");\n\n let updated: string;\n\n switch (options.mode) {\n case \"overwrite\":\n updated = content;\n break;\n\n case \"append\":\n updated = existing + \"\\n\" + content;\n break;\n\n case \"prepend\": {\n const { data, content: body } = matter(existing);\n const newBody = content + \"\\n\" + body;\n updated = Object.keys(data).length > 0 ? matter.stringify(newBody, data) : newBody;\n break;\n }\n\n case \"patch-by-heading\": {\n if (!options.heading) throw new Error(\"patch-by-heading requires a heading\");\n updated = this.patchByHeading(existing, options.heading, content);\n break;\n }\n }\n\n await writeFile(absPath, updated, \"utf-8\");\n }\n\n async delete(relativePath: string): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n if (!existsSync(absPath)) {\n throw new Error(`Note does not exist: ${relativePath}`);\n }\n await unlink(absPath);\n }\n\n async move(fromPath: string, toPath: string): Promise<void> {\n const absFrom = join(this.notesPath, fromPath);\n const absTo = join(this.notesPath, toPath);\n\n if (!existsSync(absFrom)) {\n throw new Error(`Note does not exist: ${fromPath}`);\n }\n if (existsSync(absTo)) {\n throw new Error(`Destination already exists: ${toPath}`);\n }\n\n await mkdir(dirname(absTo), { recursive: true });\n await rename(absFrom, absTo);\n\n // Update wikilinks in other files that reference the old path\n await this.updateWikilinksAfterMove(fromPath, toPath);\n }\n\n private async updateWikilinksAfterMove(\n oldPath: string,\n newPath: string\n ): Promise<void> {\n const oldName = oldPath.replace(/\\.md$/, \"\").split(\"/\").pop()!;\n const newName = newPath.replace(/\\.md$/, \"\").split(\"/\").pop()!;\n\n if (oldName === newName) return;\n\n const files = await glob(\"**/*.md\", { cwd: this.notesPath });\n\n for (const file of files) {\n const absPath = join(this.notesPath, file);\n const content = await readFile(absPath, \"utf-8\");\n\n const pattern = new RegExp(`\\\\[\\\\[${escapeRegex(oldName)}(\\\\|[^\\\\]]*)?\\\\]\\\\]`, \"g\");\n if (!pattern.test(content)) continue;\n\n const updated = content.replace(pattern, `[[${newName}$1]]`);\n await writeFile(absPath, updated, \"utf-8\");\n }\n }\n\n private patchByHeading(\n content: string,\n heading: string,\n newContent: string\n ): string {\n const lines = content.split(\"\\n\");\n const headingPattern = new RegExp(`^#{1,6}\\\\s+${escapeRegex(heading)}\\\\s*$`, \"i\");\n\n let headingIndex = -1;\n let headingLevel = 0;\n\n for (let i = 0; i < lines.length; i++) {\n if (headingPattern.test(lines[i])) {\n headingIndex = i;\n const match = lines[i].match(/^(#{1,6})\\s+/);\n headingLevel = match ? match[1].length : 1;\n break;\n }\n }\n\n if (headingIndex === -1) {\n throw new Error(`Heading not found: ${heading}`);\n }\n\n // Find the end of this section (next heading of same or higher level)\n let endIndex = lines.length;\n for (let i = headingIndex + 1; i < lines.length; i++) {\n const match = lines[i].match(/^(#{1,6})\\s+/);\n if (match && match[1].length <= headingLevel) {\n endIndex = i;\n break;\n }\n }\n\n const before = lines.slice(0, headingIndex + 1);\n const after = lines.slice(endIndex);\n\n return [...before, \"\", newContent, \"\", ...after].join(\"\\n\");\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { glob } from \"glob\";\nimport matter from \"gray-matter\";\n\nexport class FrontmatterManager {\n private notesPath: string;\n\n constructor(notesPath: string) {\n this.notesPath = notesPath;\n }\n\n async get(relativePath: string): Promise<Record<string, unknown>> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data } = matter(raw);\n return data;\n }\n\n async update(\n relativePath: string,\n fields: Record<string, unknown>\n ): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n\n for (const [key, value] of Object.entries(fields)) {\n if (value === null || value === undefined) {\n delete data[key];\n } else {\n data[key] = value;\n }\n }\n\n const updated = matter.stringify(content, data);\n await writeFile(absPath, updated, \"utf-8\");\n }\n}\n\nexport class TagManager {\n private notesPath: string;\n\n constructor(notesPath: string) {\n this.notesPath = notesPath;\n }\n\n async list(relativePath: string): Promise<string[]> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n\n const fmTags = Array.isArray(data.tags) ? (data.tags as string[]) : [];\n const inlineTags = [...content.matchAll(/(?:^|\\s)#([a-zA-Z][\\w-/]*)/g)].map(\n (m) => m[1]\n );\n\n return [...new Set([...fmTags, ...inlineTags])];\n }\n\n async add(relativePath: string, tags: string[]): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n\n const existing = Array.isArray(data.tags) ? (data.tags as string[]) : [];\n const merged = [...new Set([...existing, ...tags])];\n data.tags = merged;\n\n const updated = matter.stringify(content, data);\n await writeFile(absPath, updated, \"utf-8\");\n }\n\n async remove(relativePath: string, tags: string[]): Promise<void> {\n const absPath = join(this.notesPath, relativePath);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n\n // Remove from frontmatter\n if (Array.isArray(data.tags)) {\n data.tags = (data.tags as string[]).filter((t) => !tags.includes(t));\n }\n\n // Remove inline tags\n let updatedContent = content;\n for (const tag of tags) {\n const pattern = new RegExp(`(^|\\\\s)#${escapeRegex(tag)}(?=\\\\s|$)`, \"g\");\n updatedContent = updatedContent.replace(pattern, \"$1\");\n }\n\n const updated = matter.stringify(updatedContent, data);\n await writeFile(absPath, updated, \"utf-8\");\n }\n\n async renameVaultWide(oldTag: string, newTag: string): Promise<number> {\n const files = await glob(\"**/*.md\", { cwd: this.notesPath });\n let count = 0;\n\n for (const file of files) {\n const absPath = join(this.notesPath, file);\n const raw = await readFile(absPath, \"utf-8\");\n const { data, content } = matter(raw);\n let changed = false;\n\n // Rename in frontmatter\n if (Array.isArray(data.tags)) {\n const idx = (data.tags as string[]).indexOf(oldTag);\n if (idx >= 0) {\n (data.tags as string[])[idx] = newTag;\n changed = true;\n }\n }\n\n // Rename inline tags\n const pattern = new RegExp(`(^|\\\\s)#${escapeRegex(oldTag)}(?=\\\\s|$)`, \"g\");\n const updatedContent = content.replace(pattern, `$1#${newTag}`);\n if (updatedContent !== content) changed = true;\n\n if (changed) {\n const updated = matter.stringify(updatedContent, data);\n await writeFile(absPath, updated, \"utf-8\");\n count++;\n }\n }\n\n return count;\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { watch, type FSWatcher } from \"chokidar\";\nimport { EventEmitter } from \"node:events\";\n\nexport interface WatcherEvents {\n changed: (paths: string[]) => void;\n error: (error: Error) => void;\n}\n\nexport class Watcher extends EventEmitter {\n private notesPath: string;\n private fsWatcher: FSWatcher | null = null;\n private debounceMs: number;\n private pendingChanges = new Set<string>();\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private readyPromise: Promise<void> | null = null;\n private usePolling: boolean;\n\n constructor(notesPath: string, debounceMs: number = 500, usePolling: boolean = false) {\n super();\n this.notesPath = notesPath;\n this.debounceMs = debounceMs;\n this.usePolling = usePolling;\n }\n\n start(): void {\n if (this.fsWatcher) return;\n\n this.fsWatcher = watch(\"**/*.md\", {\n cwd: this.notesPath,\n ignoreInitial: true,\n followSymlinks: true,\n ignored: [\n \"**/node_modules/**\",\n \"**/.semantic-pages-index/**\",\n \"**/.git/**\",\n ],\n ...(this.usePolling ? { usePolling: true, interval: 100 } : {}),\n });\n\n this.readyPromise = new Promise<void>((resolve) => {\n this.fsWatcher!.on(\"ready\", resolve);\n });\n\n this.fsWatcher.on(\"add\", (path) => this.enqueue(path));\n this.fsWatcher.on(\"change\", (path) => this.enqueue(path));\n this.fsWatcher.on(\"unlink\", (path) => this.enqueue(path));\n this.fsWatcher.on(\"error\", (err) => this.emit(\"error\", err));\n }\n\n async ready(): Promise<void> {\n if (this.readyPromise) await this.readyPromise;\n }\n\n stop(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.fsWatcher?.close();\n this.fsWatcher = null;\n this.pendingChanges.clear();\n }\n\n private enqueue(path: string): void {\n this.pendingChanges.add(path);\n\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n const paths = [...this.pendingChanges];\n this.pendingChanges.clear();\n this.emit(\"changed\", paths);\n }, this.debounceMs);\n }\n}\n"],"mappings":"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","names":["readFile","writeFile","join","existsSync","readFile","writeFile","join","existsSync","readFile","writeFile","mkdir","dirname","join","existsSync","readFile","writeFile","join","glob","matter","escapeRegex"]}