@andespindola/brainlink 0.1.0-beta.99 → 1.0.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/AGENTS.md +6 -6
- package/CHANGELOG.md +14 -0
- package/README.md +186 -38
- package/dist/application/add-note.js +13 -44
- package/dist/application/analyze-vault.js +1 -1
- package/dist/application/auto-migrate-configured-vault.js +37 -0
- package/dist/application/build-context.js +119 -20
- package/dist/application/canonical-context-links.js +209 -0
- package/dist/application/frontend/client-css.js +212 -42
- package/dist/application/frontend/client-html.js +42 -28
- package/dist/application/frontend/client-js.js +1294 -3222
- package/dist/application/frontend/client-render-worker-js.js +676 -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 +3 -33
- package/dist/application/index-vault.js +35 -22
- package/dist/application/migrate-context-links.js +79 -0
- package/dist/application/search-graph-node-ids.js +63 -3
- package/dist/application/server/routes.js +197 -12
- package/dist/cli/commands/read-commands.js +39 -3
- package/dist/cli/commands/vault-commands.js +182 -0
- package/dist/cli/commands/write-commands.js +147 -12
- package/dist/cli/main.js +2 -0
- package/dist/cli/runtime.js +10 -2
- package/dist/domain/context.js +1 -0
- package/dist/domain/graph-contexts.js +180 -0
- package/dist/domain/graph-layout.js +347 -21
- package/dist/domain/markdown.js +53 -9
- package/dist/infrastructure/config.js +105 -6
- package/dist/infrastructure/context-packs.js +122 -0
- package/dist/infrastructure/file-index.js +6 -3
- package/dist/infrastructure/index-state.js +2 -0
- package/dist/infrastructure/vault-migration-state.js +69 -0
- package/dist/infrastructure/volatile-memory.js +100 -0
- package/dist/mcp/http-server.js +97 -0
- package/dist/mcp/runtime.js +20 -0
- package/dist/mcp/server.js +36 -13
- package/dist/mcp/tools.js +203 -14
- package/docs/AGENT_USAGE.md +50 -5
- package/docs/ARCHITECTURE.md +11 -0
- package/docs/QUICKSTART.md +3 -1
- package/docs/RELEASE.md +4 -3
- package/package.json +3 -1
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,10 +78,10 @@ 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
86
|
npm run dev -- bench --vault ./vault
|
|
87
87
|
npm run dev -- bench --vault ./vault --watch
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
- Promoted Brainlink to the first stable functional release.
|
|
6
|
+
- Stabilized the local-first Markdown vault model with rebuildable indexes, graph links, tags, search packs and context packages.
|
|
7
|
+
- Stabilized the CLI memory workflow for init, add, index, search, context, graph inspection, validation, migration and vault management.
|
|
8
|
+
- Stabilized MCP tooling for bootstrap, policy, recommendations, RAG/CAG context, durable writes, volatile memory, graph reads and vault health checks.
|
|
9
|
+
- Added remote MCP server mode for centralized cluster access over Streamable HTTP with health/readiness probes and optional bearer authentication.
|
|
10
|
+
- Added dedicated `vaults` commands to list known vaults, choose the default vault and safely delete local filesystem vaults.
|
|
11
|
+
- Improved graph UI stability, dark theme behavior, large-graph rendering, node interaction and graph node visibility.
|
|
12
|
+
- Kept compatibility with the `0.1.0-beta` vault and index model; derived artifacts remain rebuildable from Markdown source.
|
|
13
|
+
|
|
3
14
|
## 0.1.0-beta.4
|
|
4
15
|
|
|
5
16
|
- Added bootstrap session-state persistence in `$BRAINLINK_HOME/session-state.json` for vault/agent readiness tracking.
|
|
@@ -14,6 +25,9 @@
|
|
|
14
25
|
- Added default MCP startup bootstrap behavior controlled by `brainlink_policy.autoBootstrapOnStartup`.
|
|
15
26
|
- Added CLI MCP policy presets through `blink agent policy --preset fully-auto|strict`.
|
|
16
27
|
- Added write-time non-orphan enforcement by auto-linking notes without wiki edges to agent hub notes.
|
|
28
|
+
- 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.
|
|
29
|
+
- Added `blink index --full` and MCP `brainlink_index` `full=true` for complete source reindexing without clearing the existing index first.
|
|
30
|
+
- Improved index migration so stale graph link model metadata automatically triggers a complete source reindex.
|
|
17
31
|
- Added MCP `brainlink_policy` presets (`fully-auto`, `strict`) for one-call policy switching.
|
|
18
32
|
- Added MCP write connectivity metadata in `brainlink_add_note`/`brainlink_add_file` responses.
|
|
19
33
|
- Added MCP `brainlink_recommendations` tool for plug-and-play workflow guidance.
|
package/README.md
CHANGED
|
@@ -71,6 +71,8 @@ Legacy `.jsonl.gz` packs are upgraded to `.blpk` automatically on first search/c
|
|
|
71
71
|
- Full-text, semantic and hybrid retrieval on a local file index.
|
|
72
72
|
- Middle-out context assembly around the strongest chunk per document.
|
|
73
73
|
- In-process index and context caching with automatic invalidation on index updates.
|
|
74
|
+
- Optional CAG context packs at `.brainlink/context-packs/*.json`, derived from the current index signature and reusable across repeated context calls.
|
|
75
|
+
- HTTP graph server caches generated frontend assets and graph-layout JSON payloads by signature, and skips layout serialization when ETag returns `304`.
|
|
74
76
|
- Compressed-space prefiltering for `.blpk` packs before decryption and scan.
|
|
75
77
|
- Incremental indexing that reprocesses only changed markdown files and reuses existing chunks/embeddings for unchanged notes.
|
|
76
78
|
- Adaptive compressed-pack rebuild policy to keep indexing fast during small edit batches.
|
|
@@ -81,17 +83,17 @@ Legacy `.jsonl.gz` packs are upgraded to `.blpk` automatically on first search/c
|
|
|
81
83
|
- Built-in MCP stdio server for agent tool integration.
|
|
82
84
|
- Local HTTP API.
|
|
83
85
|
- Realtime graph UI with agent selector and colored knowledge groups.
|
|
84
|
-
- Graph renderer
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
86
|
+
- 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.
|
|
87
|
+
- 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.
|
|
88
|
+
- 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.
|
|
89
|
+
- Render pipeline uses WebGL in a dedicated worker through `OffscreenCanvas`, keeping the main thread focused on UI controls and details panels.
|
|
88
90
|
- Large graph layout API automatically uses compact payload encoding with link-coverage-aware edge selection to reduce initial client load without hiding major relationships.
|
|
89
91
|
- 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).
|
|
90
|
-
- Graph coordinates are visually compacted across graph sizes so reset starts from a stable
|
|
91
|
-
- Zoomed-out graph
|
|
92
|
-
- Graph reset
|
|
92
|
+
- Graph coordinates are visually compacted across graph sizes so reset starts from a stable fitted scene and zoom-in progressively reveals local detail.
|
|
93
|
+
- Zoomed-out graph summarizes the scene as segment hub clusters, then progressively reveals individual nodes as the user zooms in.
|
|
94
|
+
- Graph reset fits the full graph scene instead of starting in a separate macro overview mode.
|
|
93
95
|
- Graph filtering runs in a dedicated browser worker to keep the UI thread responsive during heavy datasets.
|
|
94
|
-
-
|
|
96
|
+
- Node titles are shown as the user zooms closer, while labels remain bounded to visible on-screen nodes in very large graphs.
|
|
95
97
|
|
|
96
98
|
## Install
|
|
97
99
|
|
|
@@ -209,19 +211,19 @@ Only store knowledge that is likely to matter later:
|
|
|
209
211
|
```bash
|
|
210
212
|
blink add "Testing Policy" \
|
|
211
213
|
--agent "$BLINK_AGENT" \
|
|
212
|
-
--content
|
|
214
|
+
--content $'Run npm run check before final delivery. #testing #process\n\n## Context Links\n\n- [[Release Checklist]]'
|
|
213
215
|
```
|
|
214
216
|
|
|
215
|
-
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
|
|
217
|
+
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.
|
|
216
218
|
|
|
217
219
|
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`.
|
|
218
220
|
|
|
219
221
|
When adding memory, follow this contract:
|
|
220
222
|
|
|
221
|
-
- Link the new note to
|
|
223
|
+
- Link the new note to existing notes through `## Context Links` when there is a related concept.
|
|
222
224
|
- Use the exact target note title inside `[[...]]`.
|
|
223
225
|
- Add retrieval tags such as `#architecture`, `#decision`, `#runbook` or `#preference`.
|
|
224
|
-
-
|
|
226
|
+
- General wiki-link mentions outside `## Context Links` remain searchable Markdown content, but they do not become graph edges.
|
|
225
227
|
|
|
226
228
|
If you disable auto-index, run `blink index` after batched writes.
|
|
227
229
|
|
|
@@ -264,7 +266,7 @@ blink search "jwt auth" --vault ./vault
|
|
|
264
266
|
|
|
265
267
|
blink context "how does auth work?" --vault ./vault
|
|
266
268
|
|
|
267
|
-
blink server --vault ./vault
|
|
269
|
+
blink server --vault ./vault
|
|
268
270
|
```
|
|
269
271
|
|
|
270
272
|
Open the graph UI:
|
|
@@ -528,18 +530,23 @@ Available tools:
|
|
|
528
530
|
|
|
529
531
|
- `brainlink_bootstrap`: plug-and-play entrypoint that runs index + health checks and can return context in one call.
|
|
530
532
|
- `brainlink_policy`: read or update bootstrap/context-first policy, including presets (`preset: "fully-auto" | "strict"`).
|
|
531
|
-
- `brainlink_recommendations`: return an automatic action plan so agents can run Brainlink in the recommended order.
|
|
532
|
-
- `brainlink_context`: read indexed context for a task or question.
|
|
533
|
+
- `brainlink_recommendations`: return an automatic action plan so agents can run Brainlink in the recommended order, including RAG/CAG context strategy guidance.
|
|
534
|
+
- `brainlink_context`: read indexed context for a task or question; pass `strategy: "rag"` for fresh retrieval assembly, `strategy: "cag"` for persisted context packs or `strategy: "auto"` for CAG hits with RAG fallback.
|
|
535
|
+
- `brainlink_context_packs`: list or clear persisted CAG context packs.
|
|
533
536
|
- `brainlink_search`: search indexed notes.
|
|
534
537
|
- `brainlink_dedupe`: detect duplicate candidates using exact hash + semantic similarity scores.
|
|
535
538
|
- `brainlink_resolve_duplicate`: resolve duplicate pairs (`merge`, `link`, `ignore`) with connectivity-safe fallback edges.
|
|
536
539
|
- `brainlink_add_note`: write durable Markdown memory and reindex.
|
|
537
540
|
- `brainlink_add_file`: ingest a local file as a note and reindex.
|
|
538
|
-
- `
|
|
541
|
+
- `brainlink_canonicalize_context_links`: ensure existing notes link to inferred context hubs.
|
|
542
|
+
- `brainlink_volatile_add`: write temporary agent-decided memory with TTL; volatile sections are included in context and never create durable graph edges.
|
|
543
|
+
- `brainlink_volatile_clear`: clear temporary memory for the current vault/agent namespace.
|
|
544
|
+
- `brainlink_index`: rebuild the vault index. Pass `full=true` for a complete source reindex.
|
|
539
545
|
- `brainlink_stats`: read indexed vault statistics.
|
|
540
546
|
- `brainlink_validate`: validate broken links and orphan notes.
|
|
541
547
|
- `brainlink_sync`: run index, stats, validation, broken-link and orphan checks in one call.
|
|
542
548
|
- `brainlink_graph`: read indexed graph nodes and weighted links.
|
|
549
|
+
- `brainlink_graph_contexts`: list the visual graph contexts used by the local server.
|
|
543
550
|
- `brainlink_broken_links`: list unresolved wiki links.
|
|
544
551
|
- `brainlink_orphans`: list disconnected notes.
|
|
545
552
|
|
|
@@ -550,8 +557,9 @@ By default, Brainlink enforces bootstrap and auto-runs it for read tools when se
|
|
|
550
557
|
If you disable `autoBootstrapOnRead` through `brainlink_policy`, read tools return a preflight instruction with suggested `brainlink_bootstrap` arguments.
|
|
551
558
|
`brainlink_bootstrap`, `brainlink_policy` and preflight responses include structured `nextActions` so MCP clients can continue automatically without custom parsing.
|
|
552
559
|
For one-call planning, use `brainlink_recommendations` to get the recommended tool sequence for the current vault/agent/query.
|
|
560
|
+
The MCP context tools are plug-and-play by default: omit `strategy` to use the configured default (`rag` unless changed), pass `strategy: "cag"` for repeated/stable task context, or pass `strategy: "auto"` so Brainlink chooses CAG on fresh pack hits and RAG otherwise. `brainlink_recommendations`, preflight responses and policy next actions include executable context arguments so clients can continue without custom parsing.
|
|
553
561
|
|
|
554
|
-
The same linking rule applies through MCP: `brainlink_context` is read-only, and real graph links require Markdown notes with explicit `
|
|
562
|
+
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.
|
|
555
563
|
|
|
556
564
|
Agents can raise the importance of a relationship by putting priority markers on the same line as a wiki link:
|
|
557
565
|
|
|
@@ -560,17 +568,25 @@ Agents can raise the importance of a relationship by putting priority markers on
|
|
|
560
568
|
Related: [[Incident Runbook]] #critical
|
|
561
569
|
```
|
|
562
570
|
|
|
563
|
-
Indexed edges expose `weight` and `priority` (`low`, `normal`, `high`, `critical`) through CLI JSON, HTTP graph APIs and `brainlink_graph`.
|
|
571
|
+
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.
|
|
572
|
+
|
|
573
|
+
To migrate older vaults without deleting existing Markdown, generate concise context-link sections from current wiki-link mentions:
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
blink migrate-context-links --vault ./vault --limit 5
|
|
577
|
+
blink index --vault ./vault --full
|
|
578
|
+
```
|
|
564
579
|
|
|
565
580
|
## Graph UI
|
|
566
581
|
|
|
567
582
|
Start the local frontend:
|
|
568
583
|
|
|
569
584
|
```bash
|
|
570
|
-
blink server --host 127.0.0.1 --port 4321
|
|
585
|
+
blink server --host 127.0.0.1 --port 4321
|
|
571
586
|
```
|
|
572
587
|
|
|
573
588
|
By default, the server uses `$HOME/.brainlink/vault`. Pass `--vault ./vault` only when you want to inspect a custom vault.
|
|
589
|
+
By default, the server watches Markdown files in local filesystem vaults and reindexes after note changes. Use `--no-watch` to disable realtime reindexing.
|
|
574
590
|
By default, `blink server` tries to open the graph in a native desktop GUI window:
|
|
575
591
|
- macOS: Swift + WebKit
|
|
576
592
|
- Windows: PowerShell WinForms WebBrowser
|
|
@@ -586,23 +602,27 @@ When native GUI is used, the GUI window automatically closes when the `blink ser
|
|
|
586
602
|
The graph UI shows:
|
|
587
603
|
|
|
588
604
|
- notes as nodes
|
|
589
|
-
- `[[wiki links]]` as weighted edges
|
|
590
|
-
-
|
|
605
|
+
- all non-self `[[wiki links]]` inside `## Context Links` as weighted indexed edges
|
|
606
|
+
- 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
|
|
607
|
+
- details opened in a non-modal side panel (tags, outgoing links, backlinks, full Markdown content), so zoom and pan remain available while inspecting data
|
|
591
608
|
- neutral graph nodes with segment/group metadata
|
|
592
609
|
- agent selector (id-only labels) for isolated views
|
|
610
|
+
- context selector for segment-scoped cauliflower subgraphs derived from the visual graph context
|
|
593
611
|
- graph filter matches title, path, tags and note content
|
|
594
612
|
- graph filter keeps hub context nodes visible (`Memory Hub`/`MOC`/high-degree fallback) to preserve relationship readability
|
|
595
|
-
- realtime refresh while
|
|
613
|
+
- realtime refresh while watch mode is enabled
|
|
596
614
|
- graph controls for zoom in, zoom out, fit visible nodes and reset-to-fit-all
|
|
597
615
|
- wheel zoom (including `cmd+scroll` and `ctrl+scroll`) anchored to cursor position for faster navigation in large graphs
|
|
616
|
+
- wheel/button zoom updates immediately at the cursor anchor without delayed focus-transition interpolation
|
|
617
|
+
- 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
|
|
618
|
+
- zoom-out cluster mode that shows segment hub clusters first, then reveals local nodes as zoom increases
|
|
598
619
|
- keyboard shortcuts: `+` zoom in, `-` zoom out, `0` reset fit
|
|
599
|
-
- double-click on canvas zooms in at cursor position
|
|
620
|
+
- click on a node opens its details panel; double-click on empty canvas zooms in at cursor position
|
|
600
621
|
- floating graph totals (notes, links, tags) below the Brainlink title
|
|
601
|
-
- graph rendering safeguards (batched
|
|
602
|
-
-
|
|
603
|
-
-
|
|
604
|
-
- graph
|
|
605
|
-
- graph LOD progression: graphs up to 1000 notes render directly; larger graphs use one recursive model where each visible level targets up to 999 non-hub nodes, starts from a memory-hub-centered mesh, and each supernode can expand into another same-shape subgraph level (again up to 999 children) with latent fade-in, aggregated real links and local sibling mesh links so org-heavy and stress-50k follow the same structure at different depths; for massive graphs the first expansion starts much deeper in zoom and low-size child levels use slower easing so the view stays as one compact graph longer
|
|
622
|
+
- graph rendering safeguards (batched GPU draw calls, lower redraw rate, zoom-aware interaction)
|
|
623
|
+
- 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
|
|
624
|
+
- worker-first WebGL rendering with Canvas fallback when `OffscreenCanvas` or worker rendering is unavailable
|
|
625
|
+
- 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
|
|
606
626
|
|
|
607
627
|
The server indexes before starting by default. Use `--no-index` to skip that step:
|
|
608
628
|
|
|
@@ -619,8 +639,11 @@ The server always refuses non-loopback hosts. Brainlink HTTP only runs on localh
|
|
|
619
639
|
Routes:
|
|
620
640
|
|
|
621
641
|
- `GET /api/agents`
|
|
642
|
+
- `GET /api/graph-contexts`
|
|
622
643
|
- `GET /api/graph`
|
|
623
644
|
- `GET /api/graph-layout`
|
|
645
|
+
- `GET /api/graph-view?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>`
|
|
646
|
+
- `GET /api/graph-stream?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>&nodeBudget=<n>&edgeBudget=<n>`
|
|
624
647
|
- `GET /api/graph-node?id=<node-id>`
|
|
625
648
|
- `GET /api/search?q=<query>&limit=10&mode=hybrid`
|
|
626
649
|
- `GET /api/context?q=<query>&limit=12&tokens=2000&mode=hybrid`
|
|
@@ -635,6 +658,7 @@ Read routes accept `agent=<agent-id>`:
|
|
|
635
658
|
|
|
636
659
|
```txt
|
|
637
660
|
/api/graph-layout?agent=coding-agent
|
|
661
|
+
/api/graph-layout?agent=coding-agent&context=Architecture
|
|
638
662
|
/api/search?q=typescript&agent=coding-agent&mode=hybrid
|
|
639
663
|
/api/context?q=module-boundaries&agent=coding-agent&mode=semantic
|
|
640
664
|
```
|
|
@@ -689,9 +713,25 @@ blink config set-vault "s3://my-memory-bucket/brainlink" --global
|
|
|
689
713
|
|
|
690
714
|
`config set-vault` writes configuration through CLI (no manual file edits required).
|
|
691
715
|
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.
|
|
716
|
+
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`).
|
|
692
717
|
Use `--global` to write to `$BRAINLINK_HOME/brainlink.config.json`, `--no-migrate` to skip migration, and `--no-index` to skip post-migration indexing.
|
|
693
718
|
`config doctor` is dry-run by default; use `--fix` to apply safe config normalization and allowlist fixes.
|
|
694
719
|
|
|
720
|
+
### `vaults`
|
|
721
|
+
|
|
722
|
+
```bash
|
|
723
|
+
blink vaults list
|
|
724
|
+
blink vaults list --json
|
|
725
|
+
blink vaults use /absolute/path/to/vault
|
|
726
|
+
blink vaults use /absolute/path/to/vault --global
|
|
727
|
+
blink vaults delete /absolute/path/to/vault --yes
|
|
728
|
+
blink vaults delete /absolute/path/to/vault --yes --prune-config
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
Lists known vaults from the configured default, `allowedVaults`, and the built-in default at `$HOME/.brainlink/vault`.
|
|
732
|
+
`vaults use` chooses the default vault without migrating memory; use `migrate-vault` or `config set-vault --migrate-from` when you want to copy Markdown memory between vaults.
|
|
733
|
+
`vaults delete` only deletes local filesystem vaults, requires `--yes`, refuses bucket vaults, and refuses deleting the current default vault. Choose another default first with `vaults use`.
|
|
734
|
+
|
|
695
735
|
### `migrate-vault`
|
|
696
736
|
|
|
697
737
|
```bash
|
|
@@ -768,9 +808,12 @@ When action is not `merge`, Brainlink still creates a low-priority related edge
|
|
|
768
808
|
```bash
|
|
769
809
|
blink index
|
|
770
810
|
blink index --vault ./vault
|
|
811
|
+
blink index --vault ./vault --full
|
|
771
812
|
```
|
|
772
813
|
|
|
773
|
-
Rebuilds the local index from Markdown files.
|
|
814
|
+
Rebuilds the local index from Markdown files. By default, unchanged notes reuse existing indexed chunks for speed.
|
|
815
|
+
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.
|
|
816
|
+
Brainlink also performs this complete source reindex automatically when it detects that the stored graph link model is older than the current model.
|
|
774
817
|
|
|
775
818
|
### `bench`
|
|
776
819
|
|
|
@@ -839,10 +882,15 @@ Context selection uses a middle-out strategy: it starts from the strongest chunk
|
|
|
839
882
|
blink context "question" --vault ./vault --limit 12 --tokens 2000
|
|
840
883
|
blink context "question" --vault ./vault --agent coding-agent --json
|
|
841
884
|
blink context "question" --vault ./vault --agent coding-agent --mode hybrid --json
|
|
885
|
+
blink context "question" --vault ./vault --agent coding-agent --strategy cag --json
|
|
886
|
+
blink context "question" --vault ./vault --agent coding-agent --strategy auto --json
|
|
887
|
+
blink context-packs --vault ./vault --json
|
|
888
|
+
blink context-packs --vault ./vault --stale --clear
|
|
842
889
|
```
|
|
843
890
|
|
|
844
891
|
Builds a compact context package for an agent.
|
|
845
892
|
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.
|
|
893
|
+
The default strategy is configured by `defaultContextStrategy` and starts as `rag`, which retrieves and assembles context from the current index. `--strategy cag` enables cache-augmented context generation by reading or refreshing a persisted context pack under `.brainlink/context-packs`; `--strategy auto` uses CAG when a fresh pack exists and RAG otherwise, refreshing a pack for future calls. Context responses include `cache`, `metrics`, `requestedStrategy` and `recommendedStrategy` metadata. Packs are derived artifacts and become stale when the index or volatile memory signature changes.
|
|
846
894
|
|
|
847
895
|
### `links`
|
|
848
896
|
|
|
@@ -922,15 +970,26 @@ blink watch --vault ./vault
|
|
|
922
970
|
|
|
923
971
|
Watches Markdown files and rebuilds the index when notes change.
|
|
924
972
|
|
|
973
|
+
### `canonicalize-context-links`
|
|
974
|
+
|
|
975
|
+
```bash
|
|
976
|
+
blink canonicalize-context-links --vault ./vault --dry-run
|
|
977
|
+
blink canonicalize-context-links --vault ./vault
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
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.
|
|
981
|
+
|
|
925
982
|
### `server`
|
|
926
983
|
|
|
927
984
|
```bash
|
|
928
|
-
blink server
|
|
929
|
-
blink server --vault ./vault
|
|
930
|
-
blink server --vault ./vault --
|
|
985
|
+
blink server
|
|
986
|
+
blink server --vault ./vault
|
|
987
|
+
blink server --vault ./vault --no-open
|
|
988
|
+
blink server --vault ./vault --no-watch
|
|
931
989
|
```
|
|
932
990
|
|
|
933
991
|
Starts the local read-only graph UI and HTTP API.
|
|
992
|
+
Watch mode is enabled by default for Markdown changes in local filesystem vaults. Use `--no-watch` to run without the watcher.
|
|
934
993
|
By default, it tries to open a native desktop GUI window for the graph URL.
|
|
935
994
|
On Linux, native GUI is disabled by default; enable it with `BRAINLINK_LINUX_NATIVE_GUI=1`.
|
|
936
995
|
If native GUI launch is unavailable, it falls back to dedicated app-window mode and then browser open.
|
|
@@ -971,8 +1030,10 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
|
|
|
971
1030
|
"allowedVaults": [".brainlink-vault"],
|
|
972
1031
|
"defaultAgent": "shared",
|
|
973
1032
|
"autoIndexOnWrite": true,
|
|
1033
|
+
"autoCanonicalContextLinks": true,
|
|
974
1034
|
"defaultSearchLimit": 10,
|
|
975
1035
|
"defaultContextTokens": 2000,
|
|
1036
|
+
"defaultContextStrategy": "rag",
|
|
976
1037
|
"embeddingProvider": "local",
|
|
977
1038
|
"defaultSearchMode": "hybrid",
|
|
978
1039
|
"chunkSize": 1200,
|
|
@@ -987,7 +1048,8 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
|
|
|
987
1048
|
"coding-agent": {
|
|
988
1049
|
"defaultSearchMode": "semantic",
|
|
989
1050
|
"defaultSearchLimit": 8,
|
|
990
|
-
"defaultContextTokens": 2400
|
|
1051
|
+
"defaultContextTokens": 2400,
|
|
1052
|
+
"defaultContextStrategy": "auto"
|
|
991
1053
|
},
|
|
992
1054
|
"*": {
|
|
993
1055
|
"defaultSearchMode": "hybrid"
|
|
@@ -997,9 +1059,93 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
|
|
|
997
1059
|
```
|
|
998
1060
|
|
|
999
1061
|
`defaultAgent` is optional. When set, CLI and MCP calls that omit `--agent`/`agent` use this value automatically. If not set, behavior remains as before.
|
|
1000
|
-
`agentProfiles` is optional. When present, CLI and MCP resolve `mode`, `limit` and `
|
|
1062
|
+
`agentProfiles` is optional. When present, CLI and MCP resolve `mode`, `limit`, `tokens` and context `strategy` per agent automatically, then fallback to global defaults.
|
|
1001
1063
|
|
|
1002
1064
|
`autoIndexOnWrite` is optional and defaults to `true`. Set it to `false` to defer indexing after writes.
|
|
1065
|
+
`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.
|
|
1066
|
+
|
|
1067
|
+
## Remote MCP Server
|
|
1068
|
+
|
|
1069
|
+
Brainlink can run as a centralized MCP service for clustered workloads. This keeps one shared memory service inside the cluster while applications and agents connect to the MCP endpoint over Streamable HTTP.
|
|
1070
|
+
|
|
1071
|
+
```bash
|
|
1072
|
+
BRAINLINK_MCP_TOKEN="change-me" brainlink mcp-server \
|
|
1073
|
+
--vault /data/vault \
|
|
1074
|
+
--host 0.0.0.0 \
|
|
1075
|
+
--port 3333 \
|
|
1076
|
+
--path /mcp
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
The server exposes:
|
|
1080
|
+
|
|
1081
|
+
```txt
|
|
1082
|
+
POST /mcp MCP Streamable HTTP endpoint
|
|
1083
|
+
GET /healthz liveness probe
|
|
1084
|
+
GET /readyz readiness probe
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
When `BRAINLINK_MCP_TOKEN` or `--token` is set, MCP requests must include:
|
|
1088
|
+
|
|
1089
|
+
```txt
|
|
1090
|
+
Authorization: Bearer <token>
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
For Kubernetes, run Brainlink as a central `Deployment` with a `Service` and a mounted vault volume:
|
|
1094
|
+
|
|
1095
|
+
```yaml
|
|
1096
|
+
apiVersion: apps/v1
|
|
1097
|
+
kind: Deployment
|
|
1098
|
+
metadata:
|
|
1099
|
+
name: brainlink-mcp
|
|
1100
|
+
spec:
|
|
1101
|
+
replicas: 1
|
|
1102
|
+
selector:
|
|
1103
|
+
matchLabels:
|
|
1104
|
+
app: brainlink-mcp
|
|
1105
|
+
template:
|
|
1106
|
+
metadata:
|
|
1107
|
+
labels:
|
|
1108
|
+
app: brainlink-mcp
|
|
1109
|
+
spec:
|
|
1110
|
+
containers:
|
|
1111
|
+
- name: brainlink
|
|
1112
|
+
image: brainlink:latest
|
|
1113
|
+
args: ["brainlink", "mcp-server", "--vault", "/data/vault", "--host", "0.0.0.0", "--port", "3333"]
|
|
1114
|
+
env:
|
|
1115
|
+
- name: BRAINLINK_MCP_TOKEN
|
|
1116
|
+
valueFrom:
|
|
1117
|
+
secretKeyRef:
|
|
1118
|
+
name: brainlink-mcp
|
|
1119
|
+
key: token
|
|
1120
|
+
ports:
|
|
1121
|
+
- containerPort: 3333
|
|
1122
|
+
readinessProbe:
|
|
1123
|
+
httpGet:
|
|
1124
|
+
path: /readyz
|
|
1125
|
+
port: 3333
|
|
1126
|
+
livenessProbe:
|
|
1127
|
+
httpGet:
|
|
1128
|
+
path: /healthz
|
|
1129
|
+
port: 3333
|
|
1130
|
+
volumeMounts:
|
|
1131
|
+
- name: vault
|
|
1132
|
+
mountPath: /data/vault
|
|
1133
|
+
volumes:
|
|
1134
|
+
- name: vault
|
|
1135
|
+
persistentVolumeClaim:
|
|
1136
|
+
claimName: brainlink-vault
|
|
1137
|
+
---
|
|
1138
|
+
apiVersion: v1
|
|
1139
|
+
kind: Service
|
|
1140
|
+
metadata:
|
|
1141
|
+
name: brainlink-mcp
|
|
1142
|
+
spec:
|
|
1143
|
+
selector:
|
|
1144
|
+
app: brainlink-mcp
|
|
1145
|
+
ports:
|
|
1146
|
+
- port: 3333
|
|
1147
|
+
targetPort: 3333
|
|
1148
|
+
```
|
|
1003
1149
|
|
|
1004
1150
|
Use `"embeddingProvider": "none"` when you want FTS-only indexing.
|
|
1005
1151
|
|
|
@@ -1078,7 +1224,7 @@ Local CLI:
|
|
|
1078
1224
|
|
|
1079
1225
|
```bash
|
|
1080
1226
|
npm run dev -- --help
|
|
1081
|
-
npm run dev -- server --vault .brainlink-vault
|
|
1227
|
+
npm run dev -- server --vault .brainlink-vault
|
|
1082
1228
|
```
|
|
1083
1229
|
|
|
1084
1230
|
Package smoke test:
|
|
@@ -1111,9 +1257,9 @@ Detailed notes:
|
|
|
1111
1257
|
- HTTP API is local and unauthenticated.
|
|
1112
1258
|
- Watch mode depends on the platform filesystem watcher.
|
|
1113
1259
|
|
|
1114
|
-
##
|
|
1260
|
+
## Stable Scope
|
|
1115
1261
|
|
|
1116
|
-
The `
|
|
1262
|
+
The `1.0.0` line is the first stable functional release of the local-first memory loop:
|
|
1117
1263
|
|
|
1118
1264
|
- Markdown as durable memory.
|
|
1119
1265
|
- Rebuildable file index plus local embeddings and encrypted pack exports.
|
|
@@ -1121,8 +1267,10 @@ The `0.1.0-beta` line is intended to stabilize the local-first memory loop:
|
|
|
1121
1267
|
- HTTP graph API and frontend as inspection tools.
|
|
1122
1268
|
- Agent namespaces to avoid context mixing.
|
|
1123
1269
|
- MCP tools for context retrieval, durable memory writes and graph maintenance.
|
|
1270
|
+
- Remote MCP server mode for centralized cluster access.
|
|
1271
|
+
- Vault management commands for listing, selecting and safely deleting local vaults.
|
|
1124
1272
|
|
|
1125
|
-
The
|
|
1273
|
+
The stable release includes local semantic retrieval, local-first storage, remote MCP transport and operational vault management. Remote embedding providers and deeper graph editing remain future milestones.
|
|
1126
1274
|
|
|
1127
1275
|
## Security
|
|
1128
1276
|
|
|
@@ -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;
|
|
@@ -50,7 +50,7 @@ export const getExtendedStats = async (vaultPath, agentId) => {
|
|
|
50
50
|
await searchKnowledge(absoluteVaultPath, probeQuery, Math.min(defaults.defaultSearchLimit, 8), agentId, 'hybrid');
|
|
51
51
|
const searchLatency = performance.now() - searchStart;
|
|
52
52
|
const contextStart = performance.now();
|
|
53
|
-
await buildContextPackage(absoluteVaultPath, probeQuery, Math.min(defaults.defaultSearchLimit, 8), defaults.defaultContextTokens, agentId, 'hybrid');
|
|
53
|
+
await buildContextPackage(absoluteVaultPath, probeQuery, Math.min(defaults.defaultSearchLimit, 8), defaults.defaultContextTokens, agentId, 'hybrid', undefined, defaults.defaultContextCacheTtlMs);
|
|
54
54
|
const contextLatency = performance.now() - contextStart;
|
|
55
55
|
return {
|
|
56
56
|
stats,
|
|
@@ -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
|
+
};
|