@andespindola/brainlink 0.1.0-beta.16 → 0.1.0-beta.161
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/AGENTS.md +9 -6
- package/CHANGELOG.md +27 -0
- package/COPYRIGHT.md +5 -0
- package/README.md +177 -20
- package/dist/application/add-note.js +13 -44
- package/dist/application/auto-migrate-configured-vault.js +37 -0
- package/dist/application/build-context.js +64 -3
- package/dist/application/canonical-context-links.js +209 -0
- package/dist/application/dedupe-notes.js +226 -0
- package/dist/application/frontend/client-css.js +258 -51
- package/dist/application/frontend/client-html.js +50 -27
- package/dist/application/frontend/client-js.js +1369 -605
- package/dist/application/frontend/client-render-worker-js.js +645 -0
- package/dist/application/frontend/client-worker-js.js +66 -0
- package/dist/application/get-graph-contexts.js +33 -0
- package/dist/application/get-graph-layout.js +62 -8
- package/dist/application/get-graph-stream-chunk.js +326 -0
- package/dist/application/get-graph-view.js +246 -0
- package/dist/application/graph-view-state.js +66 -0
- package/dist/application/import-legacy-sqlite.js +266 -0
- package/dist/application/index-vault.js +262 -23
- package/dist/application/migrate-context-links.js +79 -0
- package/dist/application/offline-pack-backup.js +44 -0
- package/dist/application/search-graph-node-ids.js +63 -3
- package/dist/application/server/routes.js +247 -7
- package/dist/application/start-server.js +75 -4
- package/dist/application/watch-vault.js +23 -2
- package/dist/cli/commands/agent-commands.js +7 -0
- package/dist/cli/commands/write-commands.js +924 -14
- package/dist/cli/runtime.js +10 -2
- package/dist/domain/context.js +54 -11
- package/dist/domain/graph-contexts.js +180 -0
- package/dist/domain/graph-layout.js +389 -18
- package/dist/domain/markdown.js +53 -9
- package/dist/domain/middle-out.js +18 -0
- package/dist/infrastructure/config.js +121 -4
- package/dist/infrastructure/file-index.js +76 -6
- package/dist/infrastructure/file-system-vault.js +15 -0
- package/dist/infrastructure/index-state.js +58 -0
- package/dist/infrastructure/private-pack-codec.js +71 -10
- package/dist/infrastructure/search-packs.js +286 -15
- package/dist/infrastructure/vault-migration-state.js +69 -0
- package/dist/infrastructure/volatile-memory.js +100 -0
- package/dist/mcp/runtime.js +20 -0
- package/dist/mcp/server.js +39 -11
- package/dist/mcp/tools.js +183 -7
- package/docs/AGENT_USAGE.md +96 -5
- package/docs/ARCHITECTURE.md +8 -0
- package/docs/QUICKSTART.md +7 -0
- package/package.json +7 -2
package/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ This file tells coding agents and AI assistants how to use this repository.
|
|
|
6
6
|
|
|
7
7
|
Brainlink is a local-first knowledge memory for agents.
|
|
8
8
|
|
|
9
|
-
It reads a Markdown vault, extracts
|
|
9
|
+
It reads a Markdown vault, extracts concise graph links from `## Context Links`, extracts `#tags`, builds a local file index at `.brainlink/index.json`, and returns compact context packages that agents can inject into prompts.
|
|
10
10
|
|
|
11
11
|
## Source Of Truth
|
|
12
12
|
|
|
@@ -27,15 +27,15 @@ By default, the installed Brainlink CLI uses `$HOME/.brainlink/vault` as its vau
|
|
|
27
27
|
Use this loop when using Brainlink as memory:
|
|
28
28
|
|
|
29
29
|
1. Write durable knowledge into Markdown notes.
|
|
30
|
-
2. Link related notes with explicit `[[Note Title]]` wiki links inside
|
|
30
|
+
2. Link related notes with explicit `[[Note Title]]` wiki links inside a `## Context Links` section.
|
|
31
31
|
3. Add explicit `#tags` for retrieval.
|
|
32
32
|
4. Run `index` after writes.
|
|
33
33
|
5. Run `context "<task or question>"` before answering.
|
|
34
34
|
6. Use the returned sources as grounded context.
|
|
35
35
|
|
|
36
|
-
`context` is read-only. It does not create notes, backlinks, graph edges or durable memory by itself. A relationship exists only when a Markdown note contains a `[[wiki link]]`
|
|
36
|
+
`context` is read-only. It does not create notes, backlinks, graph edges or durable memory by itself. A relationship exists only when a Markdown note contains a `[[wiki link]]` inside `## Context Links` and the vault has been indexed after that write.
|
|
37
37
|
|
|
38
|
-
When an agent adds durable memory, it should
|
|
38
|
+
When an agent adds durable memory, it should add only the canonical relationships to `## Context Links`. Prefer exact note titles in links, for example `[[Architecture]]`, and run `broken-links`, `orphans` or `validate` when graph health matters.
|
|
39
39
|
|
|
40
40
|
Agents can mark important relationships by placing priority hints on the same line as a wiki link, for example `[[Architecture]] priority: high`, `[[Incident Runbook]] #important` or `[[Incident Runbook]] #critical`. Indexed graph edges expose `weight` and `priority` so agents can sort related notes by importance.
|
|
41
41
|
|
|
@@ -78,11 +78,14 @@ http://127.0.0.1:4321/
|
|
|
78
78
|
http://127.0.0.1:4321/api/graph
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
The graph server watches Markdown files by default while editing notes:
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
|
-
npm run dev -- server --vault ./vault
|
|
84
|
+
npm run dev -- server --vault ./vault
|
|
85
85
|
npm run dev -- watch --vault ./vault
|
|
86
|
+
npm run dev -- bench --vault ./vault
|
|
87
|
+
npm run dev -- bench --vault ./vault --watch
|
|
88
|
+
npm run dev -- pack-backup --vault ./vault
|
|
86
89
|
```
|
|
87
90
|
|
|
88
91
|
Start MCP over stdio:
|
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
- Added default MCP startup bootstrap behavior controlled by `brainlink_policy.autoBootstrapOnStartup`.
|
|
15
15
|
- Added CLI MCP policy presets through `blink agent policy --preset fully-auto|strict`.
|
|
16
16
|
- Added write-time non-orphan enforcement by auto-linking notes without wiki edges to agent hub notes.
|
|
17
|
+
- Changed graph indexing to keep every non-self Markdown wiki link as a weighted graph edge so the default star graph represents complete note connectivity.
|
|
18
|
+
- Added `blink index --full` and MCP `brainlink_index` `full=true` for complete source reindexing without clearing the existing index first.
|
|
19
|
+
- Improved index migration so stale graph link model metadata automatically triggers a complete source reindex.
|
|
17
20
|
- Added MCP `brainlink_policy` presets (`fully-auto`, `strict`) for one-call policy switching.
|
|
18
21
|
- Added MCP write connectivity metadata in `brainlink_add_note`/`brainlink_add_file` responses.
|
|
19
22
|
- Added MCP `brainlink_recommendations` tool for plug-and-play workflow guidance.
|
|
@@ -22,6 +25,30 @@
|
|
|
22
25
|
- Added short-lived hybrid search cache with automatic invalidation on index changes.
|
|
23
26
|
- Added `stats --extended` observability output with storage, quality and latency probes.
|
|
24
27
|
- Added `docs/QUICKSTART.md` and aligned README/agent docs with the latest CLI/MCP flows.
|
|
28
|
+
- Added middle-out context assembly so chunk selection expands around the strongest note chunk.
|
|
29
|
+
- Added compressed-space pack prefiltering (token bloom index) before `.blpk` decryption and scan.
|
|
30
|
+
- Improved graph UI auto-fit and viewport recovery so loaded nodes are re-centered when zoom/pan drifts to empty canvas.
|
|
31
|
+
- Added cross-platform native desktop GUI auto-open for `blink server` (macOS Swift/WebKit, Windows PowerShell WinForms, Linux Python GTK/WebKit2), with app-window/browser fallback.
|
|
32
|
+
- Changed Linux default UI launch to app-window/browser for lighter startup; Linux native GUI is now opt-in via `BRAINLINK_LINUX_NATIVE_GUI=1`.
|
|
33
|
+
- Added native GUI parent-process monitoring so GUI windows close automatically when `blink server` stops.
|
|
34
|
+
- Improved non-mac browser detection fallback to try installed Edge/Chrome/Firefox/Chromium candidates before system default open.
|
|
35
|
+
- Improved graph filter rendering to keep hub anchor nodes visible (`Memory Hub`/`MOC`/high-degree fallback) for coherent relationship context.
|
|
36
|
+
- Fixed graph modal content loading by correcting agent query parameter composition for `/api/graph-node` and `/api/graph-filter` requests.
|
|
37
|
+
- Improved 50k+ graph rendering performance with viewport-aware spatial node culling, cached render visibility, and node-adjacent edge selection to avoid full graph scans every frame.
|
|
38
|
+
- Added incremental vault indexing with file snapshots to reuse unchanged documents/chunks/embeddings, plus adaptive search-pack rebuild thresholds to avoid full re-compression on small edits.
|
|
39
|
+
- Reduced large-graph HTTP payload size with compact `/api/graph-layout` encoding for high-node vaults and capped transmitted edges to improve UI load responsiveness.
|
|
40
|
+
- Added aggressive graph LOD clustering when zoomed out, dynamic per-zoom edge render budgets, and a dedicated frontend worker for off-main-thread graph filter matching.
|
|
41
|
+
- Improved Linux browser fallback launch stability by auto-applying Chromium compatibility flags (`--ozone-platform=x11`, `--disable-gpu`, `--disable-features=Vulkan,VaapiVideoDecoder`, `--disable-background-networking`) for app-window/browser modes.
|
|
42
|
+
- Improved massive-graph UI responsiveness with stricter render budgets, adaptive heavy-graph frame throttling, reduced interaction hit-test frequency, and URL-first agent selection on initial graph load.
|
|
43
|
+
- Improved 50k+ graph LOD behavior so zoomed-out views render lightweight cluster overviews and progressively reveal nodes/edges only as zoom increases.
|
|
44
|
+
- Added `blink bench` with realtime index phase telemetry and per-run compressed-pack analysis (input/output bytes, ratio, saved space, rebuild reason and duration), including continuous watch mode.
|
|
45
|
+
- Added tunable single-stage search-pack compression settings (`searchPack.rowChunkSize`, `searchPack.compressionLevel`, `searchPack.useDictionary`).
|
|
46
|
+
- Added benchmark guardrails for compression savings and latency regression (`searchPack.guardrailMinSavingsPercent`, `searchPack.guardrailMaxLatencyRegressionPercent`), reported in `blink bench`.
|
|
47
|
+
- Added `blink pack-backup` for offline second-stage compression backups of encrypted `.blpk` packs, outside the online query path.
|
|
48
|
+
- Hardened Linux browser launch flags for Ubuntu 26 Chromium/Wayland compatibility (`--disable-vulkan`, `--use-gl=swiftshader`, `--ozone-platform-hint=x11`).
|
|
49
|
+
- Improved pack resilience by auto-repairing missing search-pack manifests from existing `.blpk` files, avoiding unnecessary full repacks on small incremental updates.
|
|
50
|
+
- Updated Linux graph auto-open behavior to prioritize the system default browser (`xdg-open`) before explicit browser fallbacks.
|
|
51
|
+
- Removed implicit Chromium dependency in Linux auto-open flow; app-window launch is now opt-in (`BRAINLINK_LINUX_APP_WINDOW=1`).
|
|
25
52
|
|
|
26
53
|
## 0.1.0-beta.3
|
|
27
54
|
|
package/COPYRIGHT.md
ADDED
package/README.md
CHANGED
|
@@ -58,6 +58,7 @@ LLMs do not have infinite context. Brainlink gives agents an external memory lay
|
|
|
58
58
|
|
|
59
59
|
Markdown is the source of truth. `.brainlink/index.json` is a rebuildable index artifact.
|
|
60
60
|
After each index run, Brainlink also writes private encrypted search packs at `.brainlink/search-packs/*.blpk` to preserve fast retrieval and portable recovery.
|
|
61
|
+
Online retrieval always uses a single compression stage per pack; optional second-stage compression is reserved for offline backup artifacts only.
|
|
61
62
|
Pack decryption uses a Brainlink key from `$BRAINLINK_HOME/keys` or from `BRAINLINK_SEARCH_PACK_KEY` when explicitly configured.
|
|
62
63
|
Legacy `.jsonl.gz` packs are upgraded to `.blpk` automatically on first search/context access.
|
|
63
64
|
|
|
@@ -67,8 +68,13 @@ Legacy `.jsonl.gz` packs are upgraded to `.blpk` automatically on first search/c
|
|
|
67
68
|
- Obsidian-compatible `[[wiki links]]` and `#tags`.
|
|
68
69
|
- Weighted graph edges so agents can rank relationship importance and priority.
|
|
69
70
|
- Backlinks, broken-link reports, orphan detection and validation.
|
|
70
|
-
- Full-text, semantic and hybrid retrieval modes.
|
|
71
71
|
- Full-text, semantic and hybrid retrieval on a local file index.
|
|
72
|
+
- Middle-out context assembly around the strongest chunk per document.
|
|
73
|
+
- In-process index and context caching with automatic invalidation on index updates.
|
|
74
|
+
- HTTP graph server caches generated frontend assets and graph-layout JSON payloads by signature, and skips layout serialization when ETag returns `304`.
|
|
75
|
+
- Compressed-space prefiltering for `.blpk` packs before decryption and scan.
|
|
76
|
+
- Incremental indexing that reprocesses only changed markdown files and reuses existing chunks/embeddings for unchanged notes.
|
|
77
|
+
- Adaptive compressed-pack rebuild policy to keep indexing fast during small edit batches.
|
|
72
78
|
- Agent namespaces under `agents/<agent-id>/`.
|
|
73
79
|
- S3-compatible bucket vaults through `s3://bucket/prefix` URIs.
|
|
74
80
|
- CLI with machine-readable `--json` output.
|
|
@@ -76,6 +82,17 @@ Legacy `.jsonl.gz` packs are upgraded to `.blpk` automatically on first search/c
|
|
|
76
82
|
- Built-in MCP stdio server for agent tool integration.
|
|
77
83
|
- Local HTTP API.
|
|
78
84
|
- Realtime graph UI with agent selector and colored knowledge groups.
|
|
85
|
+
- Graph renderer uses a cauliflower-style hub layout: the primary hub stays centered, segment hubs anchor surrounding lobes, and visual edges are simplified to root hub -> segment hubs -> local context nodes.
|
|
86
|
+
- Real weighted `[[wiki link]]` edges stay preserved in the indexed graph APIs for backlinks, ranking and context traversal; the browser layout uses a separate visual edge layer for readability.
|
|
87
|
+
- Graph exploration uses stable chunk streaming (`/api/graph-stream`) with explicit node/edge budgets, returning the full mode-level scene while it fits the budget.
|
|
88
|
+
- Render pipeline uses WebGL in a dedicated worker through `OffscreenCanvas`, keeping the main thread focused on UI controls and details panels.
|
|
89
|
+
- Large graph layout API automatically uses compact payload encoding with link-coverage-aware edge selection to reduce initial client load without hiding major relationships.
|
|
90
|
+
- Large-segment layout spacing now grows logarithmically to keep initial visual density consistent between medium and very large vaults (for example, ~1k vs ~50k notes).
|
|
91
|
+
- Graph coordinates are visually compacted across graph sizes so reset starts from a stable fitted scene and zoom-in progressively reveals local detail.
|
|
92
|
+
- Zoomed-out graph summarizes the scene as segment hub clusters, then progressively reveals individual nodes as the user zooms in.
|
|
93
|
+
- Graph reset fits the full graph scene instead of starting in a separate macro overview mode.
|
|
94
|
+
- Graph filtering runs in a dedicated browser worker to keep the UI thread responsive during heavy datasets.
|
|
95
|
+
- Node titles are shown as the user zooms closer, while labels remain bounded to visible on-screen nodes in very large graphs.
|
|
79
96
|
|
|
80
97
|
## Install
|
|
81
98
|
|
|
@@ -193,19 +210,19 @@ Only store knowledge that is likely to matter later:
|
|
|
193
210
|
```bash
|
|
194
211
|
blink add "Testing Policy" \
|
|
195
212
|
--agent "$BLINK_AGENT" \
|
|
196
|
-
--content
|
|
213
|
+
--content $'Run npm run check before final delivery. #testing #process\n\n## Context Links\n\n- [[Release Checklist]]'
|
|
197
214
|
```
|
|
198
215
|
|
|
199
|
-
Brainlink does not infer durable graph relationships from generated context. A context result is only a read package for the model. To create a real link
|
|
216
|
+
Brainlink does not infer durable graph relationships from generated context. A context result is only a read package for the model. To create a real graph link, write a concise `## Context Links` section and put the canonical `[[Note Title]]` links there.
|
|
200
217
|
|
|
201
218
|
Writes with `blink add` reindex the vault automatically by default. This can be disabled with `--no-auto-index` and controlled globally with `autoIndexOnWrite` in `brainlink.config.json`.
|
|
202
219
|
|
|
203
220
|
When adding memory, follow this contract:
|
|
204
221
|
|
|
205
|
-
- Link the new note to
|
|
222
|
+
- Link the new note to existing notes through `## Context Links` when there is a related concept.
|
|
206
223
|
- Use the exact target note title inside `[[...]]`.
|
|
207
224
|
- Add retrieval tags such as `#architecture`, `#decision`, `#runbook` or `#preference`.
|
|
208
|
-
-
|
|
225
|
+
- General wiki-link mentions outside `## Context Links` remain searchable Markdown content, but they do not become graph edges.
|
|
209
226
|
|
|
210
227
|
If you disable auto-index, run `blink index` after batched writes.
|
|
211
228
|
|
|
@@ -248,7 +265,7 @@ blink search "jwt auth" --vault ./vault
|
|
|
248
265
|
|
|
249
266
|
blink context "how does auth work?" --vault ./vault
|
|
250
267
|
|
|
251
|
-
blink server --vault ./vault
|
|
268
|
+
blink server --vault ./vault
|
|
252
269
|
```
|
|
253
270
|
|
|
254
271
|
Open the graph UI:
|
|
@@ -395,6 +412,7 @@ blink agent upgrade
|
|
|
395
412
|
```
|
|
396
413
|
|
|
397
414
|
This configures `~/.codex/config.toml` with Brainlink MCP (`brainlink-mcp`) so Brainlink is available by default in agent sessions.
|
|
415
|
+
`agent install` and `agent upgrade` also apply the MCP `fully-auto` bootstrap policy by default (`enforceBootstrap`, `enforceContextFirst`, `autoBootstrapOnRead`, `autoBootstrapOnStartup` all enabled).
|
|
398
416
|
|
|
399
417
|
If you are inside this repository and want plugin gallery setup too:
|
|
400
418
|
|
|
@@ -514,13 +532,19 @@ Available tools:
|
|
|
514
532
|
- `brainlink_recommendations`: return an automatic action plan so agents can run Brainlink in the recommended order.
|
|
515
533
|
- `brainlink_context`: read indexed context for a task or question.
|
|
516
534
|
- `brainlink_search`: search indexed notes.
|
|
535
|
+
- `brainlink_dedupe`: detect duplicate candidates using exact hash + semantic similarity scores.
|
|
536
|
+
- `brainlink_resolve_duplicate`: resolve duplicate pairs (`merge`, `link`, `ignore`) with connectivity-safe fallback edges.
|
|
517
537
|
- `brainlink_add_note`: write durable Markdown memory and reindex.
|
|
518
538
|
- `brainlink_add_file`: ingest a local file as a note and reindex.
|
|
519
|
-
- `
|
|
539
|
+
- `brainlink_canonicalize_context_links`: ensure existing notes link to inferred context hubs.
|
|
540
|
+
- `brainlink_volatile_add`: write temporary agent-decided memory with TTL; volatile sections are included in context and never create durable graph edges.
|
|
541
|
+
- `brainlink_volatile_clear`: clear temporary memory for the current vault/agent namespace.
|
|
542
|
+
- `brainlink_index`: rebuild the vault index. Pass `full=true` for a complete source reindex.
|
|
520
543
|
- `brainlink_stats`: read indexed vault statistics.
|
|
521
544
|
- `brainlink_validate`: validate broken links and orphan notes.
|
|
522
545
|
- `brainlink_sync`: run index, stats, validation, broken-link and orphan checks in one call.
|
|
523
546
|
- `brainlink_graph`: read indexed graph nodes and weighted links.
|
|
547
|
+
- `brainlink_graph_contexts`: list the visual graph contexts used by the local server.
|
|
524
548
|
- `brainlink_broken_links`: list unresolved wiki links.
|
|
525
549
|
- `brainlink_orphans`: list disconnected notes.
|
|
526
550
|
|
|
@@ -532,7 +556,7 @@ If you disable `autoBootstrapOnRead` through `brainlink_policy`, read tools retu
|
|
|
532
556
|
`brainlink_bootstrap`, `brainlink_policy` and preflight responses include structured `nextActions` so MCP clients can continue automatically without custom parsing.
|
|
533
557
|
For one-call planning, use `brainlink_recommendations` to get the recommended tool sequence for the current vault/agent/query.
|
|
534
558
|
|
|
535
|
-
The same linking rule applies through MCP: `brainlink_context` is read-only, and real graph links require Markdown notes with explicit `
|
|
559
|
+
The same linking rule applies through MCP: `brainlink_context` is read-only, and real graph links require Markdown notes with explicit `## Context Links` sections. `brainlink_add_note` and `brainlink_add_file` reindex by default and include index + `writeConnectivity` metadata. Brainlink does not auto-link new notes to fallback hubs.
|
|
536
560
|
|
|
537
561
|
Agents can raise the importance of a relationship by putting priority markers on the same line as a wiki link:
|
|
538
562
|
|
|
@@ -541,31 +565,61 @@ Agents can raise the importance of a relationship by putting priority markers on
|
|
|
541
565
|
Related: [[Incident Runbook]] #critical
|
|
542
566
|
```
|
|
543
567
|
|
|
544
|
-
Indexed edges expose `weight` and `priority` (`low`, `normal`, `high`, `critical`) through CLI JSON, HTTP graph APIs and `brainlink_graph`.
|
|
568
|
+
Indexed edges expose `weight` and `priority` (`low`, `normal`, `high`, `critical`) through CLI JSON, HTTP graph APIs and `brainlink_graph`. Brainlink indexes every non-self `[[wiki link]]` inside `## Context Links` as a graph edge. Old indexes are rebuilt automatically when their graph link model version is missing or stale.
|
|
569
|
+
|
|
570
|
+
To migrate older vaults without deleting existing Markdown, generate concise context-link sections from current wiki-link mentions:
|
|
571
|
+
|
|
572
|
+
```bash
|
|
573
|
+
blink migrate-context-links --vault ./vault --limit 5
|
|
574
|
+
blink index --vault ./vault --full
|
|
575
|
+
```
|
|
545
576
|
|
|
546
577
|
## Graph UI
|
|
547
578
|
|
|
548
579
|
Start the local frontend:
|
|
549
580
|
|
|
550
581
|
```bash
|
|
551
|
-
blink server --host 127.0.0.1 --port 4321
|
|
582
|
+
blink server --host 127.0.0.1 --port 4321
|
|
552
583
|
```
|
|
553
584
|
|
|
554
585
|
By default, the server uses `$HOME/.brainlink/vault`. Pass `--vault ./vault` only when you want to inspect a custom vault.
|
|
586
|
+
By default, the server watches Markdown files in local filesystem vaults and reindexes after note changes. Use `--no-watch` to disable realtime reindexing.
|
|
587
|
+
By default, `blink server` tries to open the graph in a native desktop GUI window:
|
|
588
|
+
- macOS: Swift + WebKit
|
|
589
|
+
- Windows: PowerShell WinForms WebBrowser
|
|
590
|
+
- Linux: optional Python GTK + WebKit2 (requires `python3` + `gi` + `WebKit2`)
|
|
591
|
+
|
|
592
|
+
On Linux, native GUI is disabled by default for better startup performance. Enable it with `BRAINLINK_LINUX_NATIVE_GUI=1`.
|
|
593
|
+
If native GUI launch is unavailable on your system, it falls back to dedicated app-window mode and then to the default browser.
|
|
594
|
+
For Chromium-family browsers on Linux (`chromium`, `chromium-browser`, `google-chrome`, `microsoft-edge`, `brave-browser`), Brainlink now auto-applies compatibility flags during launch (`--ozone-platform=x11`, `--ozone-platform-hint=x11`, `--disable-gpu`, `--disable-vulkan`, `--use-gl=swiftshader`, `--disable-features=Vulkan,VaapiVideoDecoder`, `--disable-background-networking`) to avoid common Wayland/Vulkan/VAAPI startup issues.
|
|
595
|
+
On Linux, Brainlink opens the graph through the system default browser first (`xdg-open`), then `$BROWSER`/detected browsers as fallback. Chromium-family app-window mode is optional via `BRAINLINK_LINUX_APP_WINDOW=1`.
|
|
596
|
+
Use `--no-open` to keep it headless.
|
|
597
|
+
When native GUI is used, the GUI window automatically closes when the `blink server` process stops.
|
|
555
598
|
|
|
556
599
|
The graph UI shows:
|
|
557
600
|
|
|
558
601
|
- notes as nodes
|
|
559
|
-
- `[[wiki links]]` as weighted edges
|
|
560
|
-
-
|
|
602
|
+
- all non-self `[[wiki links]]` inside `## Context Links` as weighted indexed edges
|
|
603
|
+
- default cauliflower-style visual layout centered on the primary hub, with segment hubs anchoring surrounding lobes and visual edges simplified to root hub -> segment hubs -> local context nodes
|
|
604
|
+
- details opened in a non-modal side panel (tags, outgoing links, backlinks, full Markdown content), so zoom and pan remain available while inspecting data
|
|
561
605
|
- neutral graph nodes with segment/group metadata
|
|
562
|
-
- agent selector for isolated views
|
|
606
|
+
- agent selector (id-only labels) for isolated views
|
|
607
|
+
- context selector for segment-scoped cauliflower subgraphs derived from the visual graph context
|
|
563
608
|
- graph filter matches title, path, tags and note content
|
|
564
|
-
-
|
|
609
|
+
- graph filter keeps hub context nodes visible (`Memory Hub`/`MOC`/high-degree fallback) to preserve relationship readability
|
|
610
|
+
- realtime refresh while watch mode is enabled
|
|
565
611
|
- graph controls for zoom in, zoom out, fit visible nodes and reset-to-fit-all
|
|
566
|
-
- wheel zoom anchored to cursor position for faster navigation in large graphs
|
|
612
|
+
- wheel zoom (including `cmd+scroll` and `ctrl+scroll`) anchored to cursor position for faster navigation in large graphs
|
|
613
|
+
- wheel/button zoom updates immediately at the cursor anchor without delayed focus-transition interpolation
|
|
614
|
+
- Bloom-like scene navigation: reset fits the current graph scene, wheel zoom stays anchored to the cursor, and worker-driven WebGL rendering keeps pan/zoom interaction responsive
|
|
615
|
+
- zoom-out cluster mode that shows segment hub clusters first, then reveals local nodes as zoom increases
|
|
616
|
+
- keyboard shortcuts: `+` zoom in, `-` zoom out, `0` reset fit
|
|
617
|
+
- click on a node opens its details panel; double-click on empty canvas zooms in at cursor position
|
|
567
618
|
- floating graph totals (notes, links, tags) below the Brainlink title
|
|
568
|
-
-
|
|
619
|
+
- graph rendering safeguards (batched GPU draw calls, lower redraw rate, zoom-aware interaction)
|
|
620
|
+
- adaptive CPU safeguards for large graphs: idle frame pacing, throttled background physics updates and cached viewport dimensions to reduce redraw/layout overhead while preserving interaction responsiveness
|
|
621
|
+
- worker-first WebGL rendering with Canvas fallback when `OffscreenCanvas` or worker rendering is unavailable
|
|
622
|
+
- large graph view keeps one indexed graph model across zoom levels, uses a stable visual hierarchy for rendering, uses segment clusters at high zoom-out, and shows node titles as zoom approaches readable scale
|
|
569
623
|
|
|
570
624
|
The server indexes before starting by default. Use `--no-index` to skip that step:
|
|
571
625
|
|
|
@@ -582,8 +636,11 @@ The server always refuses non-loopback hosts. Brainlink HTTP only runs on localh
|
|
|
582
636
|
Routes:
|
|
583
637
|
|
|
584
638
|
- `GET /api/agents`
|
|
639
|
+
- `GET /api/graph-contexts`
|
|
585
640
|
- `GET /api/graph`
|
|
586
641
|
- `GET /api/graph-layout`
|
|
642
|
+
- `GET /api/graph-view?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>`
|
|
643
|
+
- `GET /api/graph-stream?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>&nodeBudget=<n>&edgeBudget=<n>`
|
|
587
644
|
- `GET /api/graph-node?id=<node-id>`
|
|
588
645
|
- `GET /api/search?q=<query>&limit=10&mode=hybrid`
|
|
589
646
|
- `GET /api/context?q=<query>&limit=12&tokens=2000&mode=hybrid`
|
|
@@ -598,6 +655,7 @@ Read routes accept `agent=<agent-id>`:
|
|
|
598
655
|
|
|
599
656
|
```txt
|
|
600
657
|
/api/graph-layout?agent=coding-agent
|
|
658
|
+
/api/graph-layout?agent=coding-agent&context=Architecture
|
|
601
659
|
/api/search?q=typescript&agent=coding-agent&mode=hybrid
|
|
602
660
|
/api/context?q=module-boundaries&agent=coding-agent&mode=semantic
|
|
603
661
|
```
|
|
@@ -652,6 +710,7 @@ blink config set-vault "s3://my-memory-bucket/brainlink" --global
|
|
|
652
710
|
|
|
653
711
|
`config set-vault` writes configuration through CLI (no manual file edits required).
|
|
654
712
|
By default it writes local config (`./brainlink.config.json`), appends the vault to `allowedVaults`, and migrates Markdown memory from the current configured vault when the target is empty.
|
|
713
|
+
When the configured default vault is changed manually in config files, Brainlink also performs automatic migration on the next command that uses the configured vault (without explicit `--vault`).
|
|
655
714
|
Use `--global` to write to `$BRAINLINK_HOME/brainlink.config.json`, `--no-migrate` to skip migration, and `--no-index` to skip post-migration indexing.
|
|
656
715
|
`config doctor` is dry-run by default; use `--fix` to apply safe config normalization and allowlist fixes.
|
|
657
716
|
|
|
@@ -667,6 +726,18 @@ blink migrate-vault --from ~/.brainlink/vault --to ./team-vault --report ./migra
|
|
|
667
726
|
Runs explicit markdown migration between vaults while preserving conflicts as `.conflict-<timestamp>` files.
|
|
668
727
|
Use `--dry-run` to preview `copied`, `conflicted` and `unchanged` counts before writing.
|
|
669
728
|
|
|
729
|
+
### `db-import`
|
|
730
|
+
|
|
731
|
+
```bash
|
|
732
|
+
blink db-import --vault ./team-vault
|
|
733
|
+
blink db-import --vault ./team-vault --db ./legacy/brainlink.db
|
|
734
|
+
blink db-import --vault ./team-vault --db ./legacy/brainlink.db --table legacy_notes --dry-run
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
Imports durable memory from a legacy SQLite database into Markdown notes (`agents/<agent-id>/*.md`) and reindexes by default.
|
|
738
|
+
When `--db` is omitted, Brainlink auto-detects common legacy paths such as `<vault>/.brainlink/brainlink.db`.
|
|
739
|
+
Use `--agent <id>` to force all imported rows into one namespace, `--limit` for incremental imports, `--dry-run` to preview without writing files, and `--no-index` to defer reindexing.
|
|
740
|
+
|
|
670
741
|
### `init`
|
|
671
742
|
|
|
672
743
|
```bash
|
|
@@ -691,15 +762,72 @@ blink add "Note Title" --vault ./vault --content-file ./notes.md --no-auto-index
|
|
|
691
762
|
|
|
692
763
|
Creates a Markdown note under `agents/<agent-id>/`. Common secret patterns are blocked by default; use `--allow-sensitive` only for an intentionally protected vault.
|
|
693
764
|
To avoid disconnected memory, Brainlink auto-adds a fallback wiki edge when a note is written without links, creating agent hub notes when needed.
|
|
765
|
+
`add` also returns `possibleDuplicates` (exact hash + semantic candidates) so agents can resolve duplicate memory right after writes.
|
|
766
|
+
|
|
767
|
+
### `dedupe`
|
|
768
|
+
|
|
769
|
+
```bash
|
|
770
|
+
blink dedupe --vault ./vault --json
|
|
771
|
+
blink dedupe --vault ./vault --agent coding-agent --limit 20 --min-score 0.92 --json
|
|
772
|
+
blink dedupe --vault ./vault --no-semantic --json
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
Detects `possibleDuplicate` pairs using exact content hashes and optional semantic similarity.
|
|
776
|
+
|
|
777
|
+
### `dedupe-resolve`
|
|
778
|
+
|
|
779
|
+
```bash
|
|
780
|
+
blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action merge --json
|
|
781
|
+
blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action link --json
|
|
782
|
+
blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action ignore --json
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
Resolves a duplicate pair with `merge`, `link` or `ignore`.
|
|
786
|
+
When action is not `merge`, Brainlink still creates a low-priority related edge (`#related-to`) so notes remain connected.
|
|
694
787
|
|
|
695
788
|
### `index`
|
|
696
789
|
|
|
697
790
|
```bash
|
|
698
791
|
blink index
|
|
699
792
|
blink index --vault ./vault
|
|
793
|
+
blink index --vault ./vault --full
|
|
700
794
|
```
|
|
701
795
|
|
|
702
|
-
Rebuilds the local index from Markdown files.
|
|
796
|
+
Rebuilds the local index from Markdown files. By default, unchanged notes reuse existing indexed chunks for speed.
|
|
797
|
+
Use `--full` to force a complete source reindex of every Markdown note. Full reindex builds the replacement index before persisting it, so existing context is not cleared first.
|
|
798
|
+
Brainlink also performs this complete source reindex automatically when it detects that the stored graph link model is older than the current model.
|
|
799
|
+
|
|
800
|
+
### `bench`
|
|
801
|
+
|
|
802
|
+
```bash
|
|
803
|
+
blink bench --vault ./vault
|
|
804
|
+
blink bench --vault ./vault --watch
|
|
805
|
+
blink bench --vault ./vault --watch --debounce 500
|
|
806
|
+
blink bench --vault ./vault --json
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
Runs indexing with realtime phase telemetry (`start`, `scan`, `parse`, `embed`, `persist`, `packs`, `complete`) and prints a benchmark summary at the end of each run.
|
|
810
|
+
|
|
811
|
+
Summary includes compression behavior for `.blpk` packs when rebuild happens:
|
|
812
|
+
- pack rebuild reason
|
|
813
|
+
- pack count and pack build duration
|
|
814
|
+
- uncompressed input bytes vs compressed output bytes
|
|
815
|
+
- saved percentage
|
|
816
|
+
- objective guardrails (minimum savings and maximum latency regression thresholds)
|
|
817
|
+
|
|
818
|
+
Use `--watch` to keep benchmarking incremental reindex runs after Markdown changes (local filesystem vaults only).
|
|
819
|
+
When `.brainlink/search-packs/manifest.json` is missing but `.blpk` files exist, Brainlink repairs the manifest first and avoids unnecessary full pack rebuild on small edits.
|
|
820
|
+
|
|
821
|
+
### `pack-backup`
|
|
822
|
+
|
|
823
|
+
```bash
|
|
824
|
+
blink pack-backup --vault ./vault
|
|
825
|
+
blink pack-backup --vault ./vault --output ./vault/.brainlink/backups/custom.blpkbak.gz
|
|
826
|
+
blink pack-backup --vault ./vault --json
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
Creates an offline backup artifact of encrypted search packs with a second compression pass.
|
|
830
|
+
This is intentionally outside the online retrieval path (`index`, `search`, `context`).
|
|
703
831
|
|
|
704
832
|
### `agents`
|
|
705
833
|
|
|
@@ -728,6 +856,7 @@ Modes:
|
|
|
728
856
|
- `semantic`: local deterministic embedding similarity only.
|
|
729
857
|
|
|
730
858
|
Hybrid results are cached in-memory for a short TTL and invalidated automatically when the local index file changes.
|
|
859
|
+
Context selection uses a middle-out strategy: it starts from the strongest chunk in a note and expands to neighboring chunks while respecting token budget.
|
|
731
860
|
|
|
732
861
|
### `context`
|
|
733
862
|
|
|
@@ -738,6 +867,7 @@ blink context "question" --vault ./vault --agent coding-agent --mode hybrid --js
|
|
|
738
867
|
```
|
|
739
868
|
|
|
740
869
|
Builds a compact context package for an agent.
|
|
870
|
+
Repeated calls with the same vault, agent, query, mode and token/limit settings are served from a short in-memory cache while the index is unchanged.
|
|
741
871
|
|
|
742
872
|
### `links`
|
|
743
873
|
|
|
@@ -817,14 +947,31 @@ blink watch --vault ./vault
|
|
|
817
947
|
|
|
818
948
|
Watches Markdown files and rebuilds the index when notes change.
|
|
819
949
|
|
|
950
|
+
### `canonicalize-context-links`
|
|
951
|
+
|
|
952
|
+
```bash
|
|
953
|
+
blink canonicalize-context-links --vault ./vault --dry-run
|
|
954
|
+
blink canonicalize-context-links --vault ./vault
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
Ensures existing notes have canonical `## Context Links` entries to inferred context hubs such as `User Preferences Hub`, `GitHub Repositories Hub` or `Brainlink Hub`. The command is idempotent, creates missing hub notes by default, and fully reindexes after writes unless `--no-index` is passed.
|
|
958
|
+
|
|
820
959
|
### `server`
|
|
821
960
|
|
|
822
961
|
```bash
|
|
823
|
-
blink server
|
|
824
|
-
blink server --vault ./vault
|
|
962
|
+
blink server
|
|
963
|
+
blink server --vault ./vault
|
|
964
|
+
blink server --vault ./vault --no-open
|
|
965
|
+
blink server --vault ./vault --no-watch
|
|
825
966
|
```
|
|
826
967
|
|
|
827
968
|
Starts the local read-only graph UI and HTTP API.
|
|
969
|
+
Watch mode is enabled by default for Markdown changes in local filesystem vaults. Use `--no-watch` to run without the watcher.
|
|
970
|
+
By default, it tries to open a native desktop GUI window for the graph URL.
|
|
971
|
+
On Linux, native GUI is disabled by default; enable it with `BRAINLINK_LINUX_NATIVE_GUI=1`.
|
|
972
|
+
If native GUI launch is unavailable, it falls back to dedicated app-window mode and then browser open.
|
|
973
|
+
When fallback opens Chromium-family browsers on Linux, Brainlink automatically uses compatibility launch flags for stable rendering on Ubuntu/Wayland setups.
|
|
974
|
+
Use `--no-open` to skip that behavior.
|
|
828
975
|
|
|
829
976
|
The HTTP server only binds to loopback hosts such as `127.0.0.1`, `localhost` or `::1`.
|
|
830
977
|
|
|
@@ -860,11 +1007,19 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
|
|
|
860
1007
|
"allowedVaults": [".brainlink-vault"],
|
|
861
1008
|
"defaultAgent": "shared",
|
|
862
1009
|
"autoIndexOnWrite": true,
|
|
1010
|
+
"autoCanonicalContextLinks": true,
|
|
863
1011
|
"defaultSearchLimit": 10,
|
|
864
1012
|
"defaultContextTokens": 2000,
|
|
865
1013
|
"embeddingProvider": "local",
|
|
866
1014
|
"defaultSearchMode": "hybrid",
|
|
867
1015
|
"chunkSize": 1200,
|
|
1016
|
+
"searchPack": {
|
|
1017
|
+
"rowChunkSize": 5000,
|
|
1018
|
+
"compressionLevel": 5,
|
|
1019
|
+
"useDictionary": true,
|
|
1020
|
+
"guardrailMinSavingsPercent": 8,
|
|
1021
|
+
"guardrailMaxLatencyRegressionPercent": 5
|
|
1022
|
+
},
|
|
868
1023
|
"agentProfiles": {
|
|
869
1024
|
"coding-agent": {
|
|
870
1025
|
"defaultSearchMode": "semantic",
|
|
@@ -882,6 +1037,7 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
|
|
|
882
1037
|
`agentProfiles` is optional. When present, CLI and MCP resolve `mode`, `limit` and `tokens` per agent automatically, then fallback to global defaults.
|
|
883
1038
|
|
|
884
1039
|
`autoIndexOnWrite` is optional and defaults to `true`. Set it to `false` to defer indexing after writes.
|
|
1040
|
+
`autoCanonicalContextLinks` is optional and defaults to `true`. When enabled, `blink add`, `brainlink_add_note` and `brainlink_add_file` add a canonical `## Context Links` entry to the inferred context hub, creating that hub when needed.
|
|
885
1041
|
|
|
886
1042
|
Use `"embeddingProvider": "none"` when you want FTS-only indexing.
|
|
887
1043
|
|
|
@@ -960,7 +1116,7 @@ Local CLI:
|
|
|
960
1116
|
|
|
961
1117
|
```bash
|
|
962
1118
|
npm run dev -- --help
|
|
963
|
-
npm run dev -- server --vault .brainlink-vault
|
|
1119
|
+
npm run dev -- server --vault .brainlink-vault
|
|
964
1120
|
```
|
|
965
1121
|
|
|
966
1122
|
Package smoke test:
|
|
@@ -1025,6 +1181,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
|
1025
1181
|
## License
|
|
1026
1182
|
|
|
1027
1183
|
MIT. See [LICENSE](LICENSE).
|
|
1184
|
+
Copyright (c) 2026 Substructa. See [COPYRIGHT.md](COPYRIGHT.md).
|
|
1028
1185
|
|
|
1029
1186
|
### Memory Optimization Loop (1-7)
|
|
1030
1187
|
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
import { access } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
1
|
import { writeMarkdownFile } from '../infrastructure/file-system-vault.js';
|
|
4
2
|
import { sanitizeAgentId, sharedAgentId } from '../domain/agents.js';
|
|
5
|
-
import { extractWikiLinks } from '../domain/markdown.js';
|
|
6
3
|
import { validateNoteInput } from '../domain/note-safety.js';
|
|
7
4
|
import { ensureVault } from '../infrastructure/file-system-vault.js';
|
|
5
|
+
import { addCanonicalContextLinkToContent, ensureCanonicalContextHub } from './canonical-context-links.js';
|
|
8
6
|
const slugify = (title) => title
|
|
9
7
|
.normalize('NFKD')
|
|
10
8
|
.replace(/[\u0300-\u036f]/g, '')
|
|
11
9
|
.toLowerCase()
|
|
12
10
|
.replace(/[^a-z0-9]+/g, '-')
|
|
13
11
|
.replace(/^-+|-+$/g, '');
|
|
14
|
-
const systemHubTitle = 'Memory Hub';
|
|
15
|
-
const systemRootTitle = 'Knowledge Root';
|
|
16
|
-
const normalizeTitle = (title) => title.trim().replace(/\.md$/i, '').toLowerCase();
|
|
17
|
-
const noteFilename = (agentId, title) => `agents/${agentId}/${slugify(title) || 'untitled'}.md`;
|
|
18
12
|
const buildNote = (title, content, agentId) => [
|
|
19
13
|
`---`,
|
|
20
14
|
`title: "${title.replaceAll('"', '\\"')}"`,
|
|
@@ -26,38 +20,6 @@ const buildNote = (title, content, agentId) => [
|
|
|
26
20
|
content.trim(),
|
|
27
21
|
''
|
|
28
22
|
].join('\n');
|
|
29
|
-
const ensureSystemNote = async (vaultPath, absoluteVaultPath, agentId, title, content) => {
|
|
30
|
-
const filename = noteFilename(agentId, title);
|
|
31
|
-
const absolutePath = join(absoluteVaultPath, filename);
|
|
32
|
-
try {
|
|
33
|
-
await access(absolutePath);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
catch { }
|
|
37
|
-
await writeMarkdownFile(vaultPath, filename, buildNote(title, content, agentId));
|
|
38
|
-
};
|
|
39
|
-
const ensureNonOrphanContent = async (vaultPath, absoluteVaultPath, title, content, agentId) => {
|
|
40
|
-
const links = extractWikiLinks(content).filter((link) => normalizeTitle(link) !== normalizeTitle(title));
|
|
41
|
-
if (links.length > 0) {
|
|
42
|
-
return {
|
|
43
|
-
content: content.trim(),
|
|
44
|
-
autoLinked: false,
|
|
45
|
-
linkTarget: null
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
const fallbackTitle = normalizeTitle(title) === normalizeTitle(systemHubTitle) ? systemRootTitle : systemHubTitle;
|
|
49
|
-
if (fallbackTitle === systemRootTitle) {
|
|
50
|
-
await ensureSystemNote(vaultPath, absoluteVaultPath, agentId, systemRootTitle, `Entry point for agent memory. [[${systemHubTitle}]] #memory #root`);
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
await ensureSystemNote(vaultPath, absoluteVaultPath, agentId, systemHubTitle, 'Central memory index for this agent namespace. #memory #hub');
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
content: `${content.trim()}\n\nRelated: [[${fallbackTitle}]]`,
|
|
57
|
-
autoLinked: true,
|
|
58
|
-
linkTarget: fallbackTitle
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
23
|
export const addNoteWithMetadata = async (vaultPath, title, content, agentId = sharedAgentId, options = {}) => {
|
|
62
24
|
validateNoteInput({
|
|
63
25
|
title,
|
|
@@ -65,15 +27,22 @@ export const addNoteWithMetadata = async (vaultPath, title, content, agentId = s
|
|
|
65
27
|
allowSensitive: options.allowSensitive
|
|
66
28
|
});
|
|
67
29
|
const sanitizedAgentId = sanitizeAgentId(agentId);
|
|
68
|
-
const absoluteVaultPath = await ensureVault(vaultPath);
|
|
69
30
|
const filename = `agents/${sanitizedAgentId}/${slugify(title) || 'untitled'}.md`;
|
|
70
|
-
|
|
71
|
-
const
|
|
31
|
+
await ensureVault(vaultPath);
|
|
32
|
+
const canonical = options.autoContextLinks === false
|
|
33
|
+
? null
|
|
34
|
+
: addCanonicalContextLinkToContent(title, content.trim());
|
|
35
|
+
const hub = canonical?.changed
|
|
36
|
+
? await ensureCanonicalContextHub(vaultPath, canonical.context, sanitizedAgentId)
|
|
37
|
+
: null;
|
|
38
|
+
const note = buildNote(title, canonical?.content ?? content.trim(), sanitizedAgentId);
|
|
72
39
|
const path = await writeMarkdownFile(vaultPath, filename, note);
|
|
73
40
|
return {
|
|
74
41
|
path,
|
|
75
|
-
autoLinked:
|
|
76
|
-
linkTarget:
|
|
42
|
+
autoLinked: canonical?.changed ?? false,
|
|
43
|
+
linkTarget: canonical?.changed ? canonical.hubTitle : null,
|
|
44
|
+
context: canonical?.context ?? null,
|
|
45
|
+
hubCreated: hub?.created ?? false
|
|
77
46
|
};
|
|
78
47
|
};
|
|
79
48
|
export const addNote = async (vaultPath, title, content, agentId = sharedAgentId, options = {}) => (await addNoteWithMetadata(vaultPath, title, content, agentId, options)).path;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { indexVault } from './index-vault.js';
|
|
2
|
+
import { migrateVaultContent } from './migrate-vault.js';
|
|
3
|
+
import { getLastConfiguredVaultForKey, setLastConfiguredVaultForKey } from '../infrastructure/vault-migration-state.js';
|
|
4
|
+
export const autoMigrateConfiguredVaultIfChanged = async (input) => {
|
|
5
|
+
const configKey = input.configKey.trim();
|
|
6
|
+
const configuredVault = input.configuredVault.trim();
|
|
7
|
+
if (configKey.length === 0 || configuredVault.length === 0) {
|
|
8
|
+
return {
|
|
9
|
+
changed: false,
|
|
10
|
+
migrated: false
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const previousVault = await getLastConfiguredVaultForKey(configKey);
|
|
14
|
+
if (!previousVault) {
|
|
15
|
+
await setLastConfiguredVaultForKey(configKey, configuredVault);
|
|
16
|
+
return {
|
|
17
|
+
changed: false,
|
|
18
|
+
migrated: false
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (previousVault === configuredVault) {
|
|
22
|
+
return {
|
|
23
|
+
changed: false,
|
|
24
|
+
migrated: false
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const migration = await migrateVaultContent(previousVault, configuredVault);
|
|
28
|
+
const shouldIndex = migration.copied + migration.conflicted > 0;
|
|
29
|
+
if (shouldIndex) {
|
|
30
|
+
await indexVault(configuredVault);
|
|
31
|
+
}
|
|
32
|
+
await setLastConfiguredVaultForKey(configKey, configuredVault);
|
|
33
|
+
return {
|
|
34
|
+
changed: true,
|
|
35
|
+
migrated: shouldIndex
|
|
36
|
+
};
|
|
37
|
+
};
|