md-semantic-search 1.0.2 → 1.1.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/README.md +198 -8
- package/RESEARCH.md +25 -3
- package/bin/cli.mjs +657 -29
- package/dist/completions.d.ts +25 -0
- package/dist/completions.js +238 -0
- package/dist/core.d.ts +31 -0
- package/dist/core.js +121 -1
- package/dist/download-progress.d.ts +52 -0
- package/dist/download-progress.js +112 -0
- package/dist/index-format.js +8 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +5 -4
- package/dist/indexer.d.ts +1 -0
- package/dist/indexer.js +5 -5
- package/dist/ivf.d.ts +14 -7
- package/dist/ivf.js +126 -18
- package/dist/mcp.d.ts +143 -4
- package/dist/mcp.js +499 -23
- package/dist/models.d.ts +1 -1
- package/dist/models.js +52 -31
- package/dist/open.d.ts +43 -0
- package/dist/open.js +84 -0
- package/dist/providers.d.ts +21 -0
- package/dist/providers.js +104 -0
- package/dist/query-cache-disk.d.ts +14 -0
- package/dist/query-cache-disk.js +175 -0
- package/dist/rag.d.ts +72 -7
- package/dist/rag.js +191 -13
- package/dist/repair.d.ts +36 -0
- package/dist/repair.js +208 -0
- package/dist/rerank.d.ts +20 -4
- package/dist/rerank.js +14 -4
- package/dist/search.d.ts +35 -0
- package/dist/search.js +175 -5
- package/dist/serve.d.ts +126 -0
- package/dist/serve.js +676 -46
- package/dist/tui.d.ts +8 -0
- package/dist/tui.js +80 -13
- package/dist/watcher.d.ts +16 -0
- package/dist/watcher.js +41 -0
- package/dist/webui.d.ts +13 -0
- package/dist/webui.js +252 -0
- package/dist/wikilinks.d.ts +31 -0
- package/dist/wikilinks.js +185 -1
- package/package.json +1 -1
- package/src/completions.ts +255 -0
- package/src/core.ts +160 -1
- package/src/download-progress.ts +146 -0
- package/src/index-format.ts +7 -1
- package/src/index.ts +11 -2
- package/src/indexer.ts +8 -4
- package/src/ivf.ts +157 -20
- package/src/mcp.ts +514 -23
- package/src/models.ts +58 -33
- package/src/open.ts +119 -0
- package/src/providers.ts +134 -0
- package/src/query-cache-disk.ts +191 -0
- package/src/rag.ts +279 -17
- package/src/repair.ts +245 -0
- package/src/rerank.ts +43 -8
- package/src/search.ts +199 -6
- package/src/serve.ts +726 -43
- package/src/tui.ts +86 -14
- package/src/watcher.ts +46 -0
- package/src/webui.ts +255 -0
- package/src/wikilinks.ts +220 -1
package/README.md
CHANGED
|
@@ -109,6 +109,9 @@ measurements that shaped its defaults.
|
|
|
109
109
|
|
|
110
110
|
## Install
|
|
111
111
|
|
|
112
|
+
Requires **Node.js ≥ 18**. Native dependencies ship as prebuilt binaries — no
|
|
113
|
+
compiler toolchain needed on any platform.
|
|
114
|
+
|
|
112
115
|
Run on demand with `npx` (no install):
|
|
113
116
|
|
|
114
117
|
```bash
|
|
@@ -131,6 +134,9 @@ npm install
|
|
|
131
134
|
node bin/cli.mjs --help
|
|
132
135
|
```
|
|
133
136
|
|
|
137
|
+
For headless server deployments there is a Docker path — see
|
|
138
|
+
[docs/deploy.md](./docs/deploy.md).
|
|
139
|
+
|
|
134
140
|
---
|
|
135
141
|
|
|
136
142
|
## Library usage
|
|
@@ -177,7 +183,14 @@ indexes and existing library consumers; schema-v3 search uses persisted BM25.
|
|
|
177
183
|
mdss index --db /path/to/your/markdown
|
|
178
184
|
```
|
|
179
185
|
|
|
180
|
-
First run downloads the model (~280 MB)
|
|
186
|
+
First run downloads the model (~280 MB) — and the download itself is
|
|
187
|
+
**visible**: an aggregated bar on stderr shows percent across every file of the
|
|
188
|
+
model directory, live MB/s and ETA (the same bar reappears when `--rerank`
|
|
189
|
+
first pulls the cross-encoder). Under `--json` the bar is replaced by throttled
|
|
190
|
+
`{"type":"download-progress", …}` / `{"type":"download-complete", …}` events
|
|
191
|
+
**on stderr**, so stdout stays machine-readable. A warm cache produces no
|
|
192
|
+
download output at all, and `--offline` behaves exactly as before. The index
|
|
193
|
+
is written to `<db>/.mdss/`
|
|
181
194
|
by default (override with `--index-dir`). Re-run after editing your notes — it's
|
|
182
195
|
incremental at two levels: unchanged files are skipped via their md5, and inside
|
|
183
196
|
a changed file only the sections whose text actually changed are re-embedded
|
|
@@ -374,8 +387,31 @@ mdss search --db /path/to/your/markdown "how do I rotate the api token" --rerank
|
|
|
374
387
|
- The reranker is lazy: nothing loads unless `--rerank` is actually requested,
|
|
375
388
|
so searches without it pay zero extra cost.
|
|
376
389
|
|
|
390
|
+
### 3. Ask & Interactive Multi-turn Chat (`mdss ask`, `mdss chat`)
|
|
377
391
|
|
|
378
|
-
|
|
392
|
+
`md-semantic-search` includes a grounded RAG QA engine that operates fully offline by default with zero external dependencies, or connects optionally to local/remote LLMs (Ollama, OpenAI-compatible APIs).
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
# One-shot grounded QA with citations:
|
|
396
|
+
mdss ask --db ./notes "What is the token expiration policy?"
|
|
397
|
+
|
|
398
|
+
# Multi-turn persistent chat session:
|
|
399
|
+
mdss chat --db ./notes
|
|
400
|
+
|
|
401
|
+
# Resume the most recent session or a specific session:
|
|
402
|
+
mdss chat --db ./notes --resume
|
|
403
|
+
mdss chat --db ./notes --session my-session-id
|
|
404
|
+
|
|
405
|
+
# One-shot query into a persistent session:
|
|
406
|
+
mdss chat --db ./notes --session my-session-id "What about database failover?"
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
- **Offline Extractive Synthesis**: Zero-dependency default extracts salient factual sentences with strict `[file › heading]` source provenance.
|
|
410
|
+
- **Persistent Sessions**: Multi-turn sessions are stored in `<indexDir>/sessions/<id>.json` preserving full conversation turns, retrieved chunk provenance manifests (file, heading, exact line numbers, chunk hashes), and model metadata.
|
|
411
|
+
- **Context Carry-Over**: Follow-up turns re-rank and expand query tokens using prior conversational context.
|
|
412
|
+
- **Interactive REPL Commands**: `/session` (info), `/sources` (manifest of last turn), `/help`, `/exit`.
|
|
413
|
+
|
|
414
|
+
### 4. Serve (daemon, warm index + model)
|
|
379
415
|
|
|
380
416
|
```bash
|
|
381
417
|
mdss serve --db /path/to/your/markdown [--port 8747] [--host 127.0.0.1] [--watch]
|
|
@@ -420,11 +456,76 @@ const { results } = await r.json();
|
|
|
420
456
|
```
|
|
421
457
|
|
|
422
458
|
The API is unauthenticated by default (or secured via `--api-key`) — by default it binds to **loopback only**
|
|
423
|
-
(`127.0.0.1`), so other machines on your LAN cannot reach it.
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
459
|
+
(`127.0.0.1`), so other machines on your LAN cannot reach it. Passing `--host 0.0.0.0` (or `MDSS_HOST`)
|
|
460
|
+
without authentication **refuses to start** — set an API key, or opt in explicitly with `--allow-unsecured`
|
|
461
|
+
(see [Securing remote deployments](#securing-remote-deployments)). Request bodies are capped at 64 KB
|
|
462
|
+
(oversized → `413`), malformed JSON gets a clear `400`, per-client request rate is capped at 60/min with a
|
|
463
|
+
burst of 10 (`429 + Retry-After` above that; tune via `--rate-limit`), and at most `CPU count` searches run
|
|
464
|
+
concurrently with a bounded wait queue (`503` when saturated; tune via `--max-concurrency`). Every response
|
|
465
|
+
carries `X-Content-Type-Options: nosniff` and `Cache-Control: no-store`; the `Host` header is validated
|
|
466
|
+
against a loopback allowlist (`403` otherwise) so DNS-rebinding pages cannot read your notes cross-origin,
|
|
467
|
+
and CORS stays fully off unless you pass `--cors-origin`. `/health` exposes the live counters
|
|
468
|
+
(`in_flight`, `queued`, `rejected_total`).
|
|
469
|
+
|
|
470
|
+
### Web UI (built-in, `--ui`)
|
|
471
|
+
|
|
472
|
+
By default `mdss serve` also serves a **zero-dependency web UI at `/`** — a keyboard-first search page
|
|
473
|
+
with live debounced results, term highlighting, score bars, tag/type/status filters, dark/light theme
|
|
474
|
+
(follows the system until you toggle it) and an API-key prompt when Bearer auth is enabled (the key is kept
|
|
475
|
+
in `sessionStorage`, same-origin only). It ships as plain HTML/CSS/JS split into three assets so a strict
|
|
476
|
+
CSP applies (`default-src 'none'; script-src 'self'; style-src 'self'; connect-src 'self';
|
|
477
|
+
frame-ancestors 'none'`) — no inline code, no external calls. Use `--no-ui` to restore pure JSON at `/`;
|
|
478
|
+
the JSON contract (`/search`, `/health`, `/help`) never changes. A Playwright smoke test runs weekly via
|
|
479
|
+
the opt-in `ui-smoke` workflow.
|
|
480
|
+
|
|
481
|
+
### Securing remote deployments
|
|
482
|
+
|
|
483
|
+
`mdss serve` is designed to be private-first: loopback bind by default, refuse-to-start for unauthenticated
|
|
484
|
+
network binds, DNS-rebinding protection, and rate limiting built in. To serve a team over the network safely:
|
|
485
|
+
|
|
486
|
+
1. **Keep TLS + auth at a reverse proxy** — mdss speaks plain HTTP on loopback; nginx/caddy terminate TLS.
|
|
487
|
+
|
|
488
|
+
```nginx
|
|
489
|
+
# /etc/nginx/sites-available/mdss — TLS termination + Bearer-auth passthrough
|
|
490
|
+
server {
|
|
491
|
+
listen 443 ssl;
|
|
492
|
+
server_name search.example.com;
|
|
493
|
+
ssl_certificate /etc/letsencrypt/live/search.example.com/fullchain.pem;
|
|
494
|
+
ssl_certificate_key /etc/letsencrypt/live/search.example.com/privkey.pem;
|
|
495
|
+
|
|
496
|
+
location / {
|
|
497
|
+
proxy_pass http://127.0.0.1:8747;
|
|
498
|
+
proxy_set_header Host $host; # must match --allowed-host if not loopback-named
|
|
499
|
+
proxy_set_header X-Forwarded-For $remote_addr;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
```caddyfile
|
|
505
|
+
# Caddyfile — automatic HTTPS
|
|
506
|
+
search.example.com {
|
|
507
|
+
reverse_proxy 127.0.0.1:8747
|
|
508
|
+
}
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
2. **Set an API key without leaking it into shell history or CI logs:**
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
echo "$RANDOM_KEY" > /etc/mdss/api-key && chmod 600 /etc/mdss/api-key
|
|
515
|
+
mdss serve --db /srv/wiki --host 127.0.0.1 --api-key-file /etc/mdss/api-key
|
|
516
|
+
# or MDSS_API_KEY_FILE=/etc/mdss/api-key
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
3. **If you must expose mdss directly** (no proxy), require the key *and* keep the firewall tight:
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
MDSS_API_KEY=$(openssl rand -hex 32) mdss serve --db /srv/wiki --host 0.0.0.0
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
The startup banner warns loudly whenever an unsecured non-loopback bind was explicitly allowed.
|
|
526
|
+
|
|
527
|
+
4. **Browser clients on another origin?** Opt into CORS explicitly, exact origins only:
|
|
528
|
+
`--cors-origin https://intranet.example.com`.
|
|
428
529
|
|
|
429
530
|
### 4. MCP Server (Claude Desktop, Cursor, Copilot, Antigravity)
|
|
430
531
|
|
|
@@ -434,11 +535,35 @@ instead of being silently swallowed.
|
|
|
434
535
|
mdss mcp --db /path/to/your/markdown
|
|
435
536
|
```
|
|
436
537
|
|
|
538
|
+
**Streamable HTTP transport (issue #123):** a long-running daemon can expose
|
|
539
|
+
the same tools over HTTP — `mdss serve --db ./notes --mcp` mounts `/mcp`
|
|
540
|
+
(POST JSON-RPC, SSE channel on GET, `Mcp-Session-Id` sessions, protocol
|
|
541
|
+
`2025-03-26`). It sits behind the exact same auth, Host-allowlist and
|
|
542
|
+
rate-limit gates as `/search`, so remote agents inherit the hardening. stdio
|
|
543
|
+
via `mdss mcp` remains the default transport.
|
|
544
|
+
|
|
437
545
|
#### Available MCP Tools:
|
|
438
|
-
- **`search_markdown`**: Hybrid semantic vector + BM25 search with optional `path` glob
|
|
546
|
+
- **`search_markdown`**: Hybrid semantic vector + BM25 search with optional `path` glob, `tag`, rich `filter`, and `graphBoost`.
|
|
439
547
|
- **`get_chunk`**: Retrieve a specific section by file and heading.
|
|
548
|
+
- **`get_lines`**: Retrieve exact line spans (`fromLine`, `maxLines`) from an indexed Markdown document.
|
|
549
|
+
- **`related_notes`**: Find graph-connected (outgoing, backlinks, 2-hop) and semantically related notes for a document.
|
|
440
550
|
- **`list_files`**: List indexed Markdown files with chunk counts.
|
|
441
551
|
- **`index_status`**: Inspect index health, chunk counts, and model metadata.
|
|
552
|
+
- **`ask_knowledge_base`**: Grounded direct Q&A synthesis with citations.
|
|
553
|
+
- *All tools return `structuredContent` alongside text and include `readOnly: true, idempotent: true` annotations.*
|
|
554
|
+
|
|
555
|
+
#### Available MCP Resources & Templates:
|
|
556
|
+
- **`mdss://note/{path}`**: Read full content of an indexed Markdown document.
|
|
557
|
+
- **`mdss://note/{path}?fromLine=1&maxLines=50`**: Addressable line-span slices of notes.
|
|
558
|
+
- **`mdss://vault/{vault}`**: List all indexed notes within a vault.
|
|
559
|
+
- **`mdss://status`**: Live index status and chunk count statistics.
|
|
560
|
+
|
|
561
|
+
#### Available MCP Prompts:
|
|
562
|
+
- **`search-and-cite`**: Synthesizes a grounded answer referencing `mdss://note/{path}` resource URIs.
|
|
563
|
+
- **`summarize-note`**: Produces a structured summary of core concepts and linked notes.
|
|
564
|
+
- **`compare-notes`**: Identifies agreements, divergences, and synergies across two notes.
|
|
565
|
+
- **`find-contradictions`**: Audits notes for conflicting statements or outdated ADRs.
|
|
566
|
+
- **`timeline`**: Builds a chronological milestone / event timeline from notes.
|
|
442
567
|
|
|
443
568
|
#### Claude Desktop Configuration:
|
|
444
569
|
Add to your `claude_desktop_config.json`:
|
|
@@ -485,6 +610,9 @@ Add to your `claude_desktop_config.json`:
|
|
|
485
610
|
| `--k <n>` | Number of results, positive integer (default 6). |
|
|
486
611
|
| `--json` | Machine-readable output: `index` → build result JSON, `stats` → index stats JSON, `search` → hit list JSON (each hit includes `matches` — the query terms found in the chunk). |
|
|
487
612
|
| `--semantic` | `search` only: pure vector ranking, skip lexical/RRF fusion (zero lexical tokenization). |
|
|
613
|
+
| `--open [N]` | `search`: open the top (or Nth) hit in your editor at its `startLine` — `$MDSS_EDITOR`/`$VISUAL`/`$EDITOR`, VS Code `--goto`, or the GUI opener. With `--json` on a non-TTY prints the intent instead of launching (issue #110). |
|
|
614
|
+
| `--fix` | `check`: apply safe auto-repairs — stale `.mdss.lock`, SHA-mismatched `vectors.bin` sidecar, corrupt `ivf.json`; rebuilds a corrupt index / recomputes `.hashes.json` when `--db` is available. Never touches source notes (issue #117). |
|
|
615
|
+
| `--dry-run` | `check --fix`: print the planned repairs without mutating anything. |
|
|
488
616
|
| `--rerank` | Re-rank the candidate pool with a cross-encoder (`Xenova/bge-reranker-base`, ~280 MB model, downloaded on first use). Slower, sharper results — see *Reranking* below. |
|
|
489
617
|
| `--graph-boost <n>` | Weight for Obsidian wikilink graph ranking and PageRank prior (search; default 0). Incorporates document centrality and 2-hop contextual propagation. |
|
|
490
618
|
| `--filter <expr>` | Rich boolean filter across frontmatter tags and properties (e.g. `tag:engineering AND status != archived`). |
|
|
@@ -492,12 +620,50 @@ Add to your `claude_desktop_config.json`:
|
|
|
492
620
|
| `--nprobe <n>` | Number of nearest centroid clusters to probe during ANN search (default 8). |
|
|
493
621
|
| `--port <n>` | HTTP port for `serve` (default 8747, or `MDSS_PORT`). |
|
|
494
622
|
| `--host <ip>` | Bind address for `serve` (default `127.0.0.1` — loopback only; use `0.0.0.0` to expose on the LAN, or `MDSS_HOST`). |
|
|
623
|
+
| `--api-key <key>` | `serve`: require Bearer auth on every request (`MDSS_API_KEY`). |
|
|
624
|
+
| `--api-key-file <path>` | `serve`: read the API key from a file instead of a literal value — avoids shell-history / CI-log leaks (`MDSS_API_KEY_FILE`; trailing newline trimmed, POSIX permissions checked). |
|
|
625
|
+
| `--allow-unsecured` | `serve`: explicit opt-in to bind non-loopback **without** auth; without it (and without an API key) such a bind refuses to start (issue #121). |
|
|
626
|
+
| `--allowed-host <h>` | `serve`: extra `Host` header value to accept (repeatable); anything else gets `403` — DNS-rebinding guard (issue #120). |
|
|
627
|
+
| `--cors-origin <o>` | `serve`: allow cross-origin browser access from this exact origin (repeatable); CORS is off unless set (issue #120). |
|
|
628
|
+
| `--rate-limit <n>` | `serve`: max `/search` requests per minute per client, burst 10 → `429 + Retry-After` above it; `0` disables (default 60, `MDSS_RATE_LIMIT`; issue #119). |
|
|
629
|
+
| `--max-concurrency <n>` | `serve`: max concurrent in-flight searches; queue cap 2× → `503` when full; `0` disables (default = CPU count, `MDSS_MAX_CONCURRENCY`; issue #119). |
|
|
495
630
|
| `--watch` | `serve`: re-index incrementally when files change. |
|
|
631
|
+
| `--watch-debug` | `serve --watch`: verbose trace of polls, FS-error classifications and retries (issue #116). |
|
|
632
|
+
| `--recency <days>` | `search`: time-decay half-life — passages get a `0.5^(age/halfLife)` boost after fusion; age from frontmatter `created`/`updated`, then file mtime; surfaced in `explain` (issue #127). |
|
|
633
|
+
| `--embedder <name>` | Use an external embedding provider (`ollama` or `openai`) instead of local transformers.js, together with `--embedder-model` (+ `--embedder-base-url`, `--embedder-key-file`). The provider id/model/dim are recorded in the index — switching providers invalidates vectors with the usual full re-embed. Local remains the zero-config default and the only fully-offline path (issue #124). |
|
|
634
|
+
| `--no-query-cache` | `search`: skip the persistent query-embedding cache — repeated queries in fresh processes re-embed otherwise (issue #114). |
|
|
635
|
+
| `--no-ui` | `serve`: disable the built-in web UI at `/` — restores JSON API help there (issue #111). |
|
|
496
636
|
| `--watch-interval <ms>` | `serve --watch`: poll every N ms (default 3000). |
|
|
497
637
|
| `--watch-delay <ms>` | `serve --watch`: quiet-period debounce before a burst of saves triggers ONE re-index (default 1000; issue #42). |
|
|
498
638
|
| `--offline` | Never download the model — require a cached one (or `MDSS_OFFLINE=1`). |
|
|
499
639
|
| `--version` | Print the installed version. |
|
|
500
640
|
|
|
641
|
+
### Shell completions
|
|
642
|
+
|
|
643
|
+
`mdss completions <bash|zsh|fish|powershell>` prints a self-contained completion
|
|
644
|
+
script covering every subcommand and flag, with directory completion for
|
|
645
|
+
`--db` / `--index-dir` / `--cache-dir` / `--vault` and file completion for
|
|
646
|
+
`--output` / `--config` / `--api-key-file`:
|
|
647
|
+
|
|
648
|
+
```bash
|
|
649
|
+
# bash — current session only:
|
|
650
|
+
eval "$(mdss completions bash)"
|
|
651
|
+
# bash — persistent:
|
|
652
|
+
mdss completions bash > ~/.local/share/bash-completions/completions/mdss
|
|
653
|
+
|
|
654
|
+
# zsh:
|
|
655
|
+
mkdir -p ~/.zfunc && mdss completions zsh > ~/.zfunc/_mdss # fpath before compinit
|
|
656
|
+
|
|
657
|
+
# fish:
|
|
658
|
+
mdss completions fish > ~/.config/fish/completions/mdss.fish
|
|
659
|
+
|
|
660
|
+
# PowerShell — paste into your $PROFILE:
|
|
661
|
+
mdss completions powershell >> $PROFILE
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
A unit test guards against flag drift: the generated tables must match the
|
|
665
|
+
flags `parseArgs` actually accepts.
|
|
666
|
+
|
|
501
667
|
### The base can live outside the project
|
|
502
668
|
|
|
503
669
|
The index does not need write access to your notes if they're read-only — just
|
|
@@ -517,6 +683,13 @@ mdss index
|
|
|
517
683
|
mdss search "incident runbook for db failover"
|
|
518
684
|
```
|
|
519
685
|
|
|
686
|
+
**Supported layouts** (hardened by the issue #118 suite): deep trees beyond
|
|
687
|
+
Windows MAX_PATH (>260 chars) work; unicode and spaces in names work;
|
|
688
|
+
`--index-dir` may live on a different drive than `--db`; NTFS junction loops
|
|
689
|
+
terminate the walker (bounded by path length); `\\?\` extended-length roots are
|
|
690
|
+
accepted for `--db`/`--index-dir`; remote UNC shares (`\\server\share`) are
|
|
691
|
+
**rejected** by design (local-only security boundary).
|
|
692
|
+
|
|
520
693
|
### Configuration file (`.mdssrc` / `mdss.config.json`)
|
|
521
694
|
|
|
522
695
|
Instead of repeating CLI options on every command, create a `.mdssrc.json` or `mdss.config.json` file.
|
|
@@ -650,6 +823,23 @@ is an in-memory dot-product sweep.
|
|
|
650
823
|
|
|
651
824
|
- **Obsidian**: An official plugin is available in [`integrations/obsidian`](./integrations/obsidian) providing a live semantic search panel directly in your vault connected to `mdss serve`.
|
|
652
825
|
- **Model Context Protocol (MCP)**: Native stdio JSON-RPC 2.0 server (`mdss mcp`) integrating with Claude Desktop, Cursor, Copilot, Antigravity, and AI agents for local knowledge retrieval.
|
|
826
|
+
- **VS Code / Raycast / Alfred**: see [`integrations/README.md`](./integrations/README.md). Releases are automated — tagging `integrations/vscode/vX.Y.Z` builds and attaches the VSIX to a GitHub Release from source (no binaries are committed; issue #112).
|
|
827
|
+
- **Windows tray icon**: [`integrations/windows/`](./integrations/windows/) — a zero-dependency system-tray companion for `mdss serve` (pure PowerShell + .NET WinForms, built into Windows): state-colored icon, indexing stats on hover (chunks / model / index age), a balloon when your notes get re-indexed. One-command start:
|
|
828
|
+
|
|
829
|
+
```cmd
|
|
830
|
+
integrations\windows\start-mdss.cmd D:\Notes
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
## Contributing
|
|
834
|
+
|
|
835
|
+
Contributions are welcome — bug reports with reproduction steps, docs fixes,
|
|
836
|
+
tests, and features all help. Start with
|
|
837
|
+
[CONTRIBUTING.md](./CONTRIBUTING.md) (dev setup, project tour, conventions)
|
|
838
|
+
and look for issues labeled **`good first issue`** — they are scoped for a
|
|
839
|
+
first-time contributor. For the internals — module map, data-flow diagrams,
|
|
840
|
+
on-disk formats, and extension points — see
|
|
841
|
+
[ARCHITECTURE.md](./ARCHITECTURE.md). By participating you agree to the
|
|
842
|
+
[Code of Conduct](./CODE_OF_CONDUCT.md).
|
|
653
843
|
|
|
654
844
|
## License
|
|
655
845
|
|
package/RESEARCH.md
CHANGED
|
@@ -226,7 +226,29 @@ If no candidate meets the multilingual non-inferiority gate, `bge-reranker-base`
|
|
|
226
226
|
- **Trigger:** WebAssembly SIMD dot-product kernels will be considered **only if** CPU profiling on >50,000 chunks shows JS float multiplication accounts for >40% of warm search latency.
|
|
227
227
|
- **Constraint:** Zero native Node C++ bindings; must maintain pure JS fallback for non-WASM environments.
|
|
228
228
|
|
|
229
|
-
### ANN / IVF Scale Threshold (
|
|
229
|
+
### ANN / IVF Scale Threshold & K-Means++ Seeding (Issues #32 & #139)
|
|
230
230
|
- **Baseline:** Exact $O(N \cdot d)$ linear sweep.
|
|
231
|
-
- **
|
|
232
|
-
- **
|
|
231
|
+
- **K-Means++ Seeding:** Uses deterministic pseudo-random $D^2$-weighted centroid seeding (Mulberry32) to prevent initial centroid collapse on correlated notes corpora.
|
|
232
|
+
- **Measured Quality Gate:** `bench/ann-recall.mjs` benchmarks Recall@10 across $nprobe \in \{1, 4, 8, 16\}$ on clustered corpora, demonstrating $\ge 99.5\%$ Recall@10 at default $nprobe=8$ with sub-millisecond candidate pruning.
|
|
233
|
+
- **Trigger:** ANN indexing is auto-engaged above `ANN_THRESHOLD = 500` chunks when `--ann` is passed or IVF index is persisted, while exact pre/post-filter correctness is strictly preserved.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 14. Matryoshka Representation Learning (MRL) Dimension Selection (Issue #143)
|
|
238
|
+
|
|
239
|
+
### Mechanism
|
|
240
|
+
Models trained with Matryoshka Representation Learning (MRL) loss (such as `onnx-community/Qwen3-Embedding-0.6B-ONNX` and `Xenova/bge-m3`) embed semantic information hierarchically, allowing vectors to be sliced at predefined sub-dimensions (`32`, `64`, `128`, `256`, `512`, `768`, `1024`) and re-normalized to unit L2 norm without significant loss in semantic retrieval fidelity.
|
|
241
|
+
|
|
242
|
+
### Benefits & Trade-offs
|
|
243
|
+
- **Storage & RAM Savings:** 1024 → 256 dimensions reduces `vectors.bin` size and memory consumption by 4× (from ~19.5 MB to ~4.88 MB per 5,000 chunks).
|
|
244
|
+
- **Sweep Latency:** Dot-product cosine sweep latency is halved (e.g. from ~14.2 ms to ~6.8 ms for 5,000 chunks in single-threaded pure JS).
|
|
245
|
+
- **Integrity & Cache Invalidation:** `embeddingAdapterFingerprint` binds the selected dimension (`model.dim`). Changing `--dimensions` automatically invalidates previous chunk hashes and forces clean re-indexing rather than silent vector dimension mismatch.
|
|
246
|
+
|
|
247
|
+
### Usage
|
|
248
|
+
```bash
|
|
249
|
+
# Build index truncated to 256 dims (4x smaller vectors)
|
|
250
|
+
mdss index --db ./notes --model qwen3-embedding-0.6b --dimensions 256
|
|
251
|
+
|
|
252
|
+
# Search with dimension safety validation
|
|
253
|
+
mdss search --db ./notes --dimensions 256 "query"
|
|
254
|
+
```
|