@andespindola/brainlink 0.1.0-beta.15 → 0.1.0-beta.151

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.
Files changed (43) hide show
  1. package/AGENTS.md +3 -0
  2. package/CHANGELOG.md +27 -0
  3. package/COPYRIGHT.md +5 -0
  4. package/README.md +140 -9
  5. package/dist/application/auto-migrate-configured-vault.js +37 -0
  6. package/dist/application/build-context.js +64 -3
  7. package/dist/application/dedupe-notes.js +226 -0
  8. package/dist/application/frontend/client-css.js +111 -47
  9. package/dist/application/frontend/client-html.js +42 -26
  10. package/dist/application/frontend/client-js.js +788 -554
  11. package/dist/application/frontend/client-render-worker-js.js +569 -0
  12. package/dist/application/frontend/client-worker-js.js +66 -0
  13. package/dist/application/get-graph-layout.js +38 -5
  14. package/dist/application/get-graph-stream-chunk.js +289 -0
  15. package/dist/application/get-graph-view.js +243 -0
  16. package/dist/application/import-legacy-sqlite.js +296 -0
  17. package/dist/application/index-vault.js +262 -23
  18. package/dist/application/offline-pack-backup.js +44 -0
  19. package/dist/application/server/routes.js +187 -5
  20. package/dist/application/start-server.js +75 -4
  21. package/dist/application/watch-vault.js +23 -2
  22. package/dist/cli/commands/agent-commands.js +7 -0
  23. package/dist/cli/commands/write-commands.js +849 -10
  24. package/dist/cli/runtime.js +10 -2
  25. package/dist/domain/context.js +54 -11
  26. package/dist/domain/graph-layout.js +275 -3
  27. package/dist/domain/markdown.js +22 -9
  28. package/dist/domain/middle-out.js +18 -0
  29. package/dist/infrastructure/config.js +117 -4
  30. package/dist/infrastructure/file-index.js +70 -3
  31. package/dist/infrastructure/file-system-vault.js +15 -0
  32. package/dist/infrastructure/index-state.js +58 -0
  33. package/dist/infrastructure/private-pack-codec.js +71 -10
  34. package/dist/infrastructure/search-packs.js +286 -15
  35. package/dist/infrastructure/vault-migration-state.js +69 -0
  36. package/dist/infrastructure/volatile-memory.js +100 -0
  37. package/dist/mcp/runtime.js +20 -0
  38. package/dist/mcp/server.js +29 -11
  39. package/dist/mcp/tools.js +119 -2
  40. package/docs/AGENT_USAGE.md +89 -3
  41. package/docs/ARCHITECTURE.md +6 -0
  42. package/docs/QUICKSTART.md +7 -0
  43. package/package.json +7 -2
package/dist/mcp/tools.js CHANGED
@@ -4,13 +4,16 @@ import { z } from 'zod';
4
4
  import { getBrokenLinksReport, getOrphansReport, getStats, validateVault } from '../application/analyze-vault.js';
5
5
  import { addNoteWithMetadata } from '../application/add-note.js';
6
6
  import { buildContextPackage } from '../application/build-context.js';
7
+ import { resolveDuplicateNotes, scanDuplicateNotes } from '../application/dedupe-notes.js';
7
8
  import { getGraph } from '../application/get-graph.js';
8
9
  import { indexVault } from '../application/index-vault.js';
9
10
  import { searchKnowledge } from '../application/search-knowledge.js';
10
11
  import { resolveAgentRuntimeDefaults, sanitizeSearchMode } from '../infrastructure/config.js';
11
12
  import { loadBrainlinkConfig } from '../infrastructure/config.js';
12
13
  import { assertVaultAllowed } from '../infrastructure/file-system-vault.js';
14
+ import { addVolatileMemory, clearVolatileMemory } from '../infrastructure/volatile-memory.js';
13
15
  import { getBootstrapPolicy, getBootstrapSessionStatus, getContextSessionStatus, setBootstrapPolicy, touchBootstrapSession, touchContextSession } from '../infrastructure/session-state.js';
16
+ import { getRuntimeMetadata } from './runtime.js';
14
17
  const positiveInteger = (fallback) => z
15
18
  .number()
16
19
  .int()
@@ -236,6 +239,20 @@ export const addNoteInputSchema = {
236
239
  allowSensitive: z.boolean().optional().default(false).describe('Allow content that looks like a secret.'),
237
240
  autoIndex: z.boolean().optional().default(true).describe('Reindex vault after writing note.')
238
241
  };
242
+ export const volatileAddInputSchema = {
243
+ ...vaultInput,
244
+ ...agentInput,
245
+ content: z
246
+ .string()
247
+ .min(1)
248
+ .describe('Temporary agent-decided memory. Use for current task state, hypotheses, transient user preferences and unconfirmed findings.'),
249
+ ttlMinutes: optionalPositiveInteger().describe('Minutes before this volatile memory expires. Defaults to 240.'),
250
+ tags: z.array(z.string()).optional().default([]).describe('Optional tags for volatile retrieval.')
251
+ };
252
+ export const volatileClearInputSchema = {
253
+ ...vaultInput,
254
+ ...agentInput
255
+ };
239
256
  export const addFileInputSchema = {
240
257
  ...vaultInput,
241
258
  ...agentInput,
@@ -245,7 +262,12 @@ export const addFileInputSchema = {
245
262
  allowSensitive: z.boolean().optional().default(false).describe('Allow content that looks like a secret.')
246
263
  };
247
264
  export const indexInputSchema = {
248
- ...vaultInput
265
+ ...vaultInput,
266
+ full: z
267
+ .boolean()
268
+ .optional()
269
+ .default(false)
270
+ .describe('Force a complete reindex from Markdown source without reusing unchanged index entries.')
249
271
  };
250
272
  export const validateInputSchema = {
251
273
  ...vaultInput,
@@ -303,6 +325,10 @@ export const policyInputSchema = {
303
325
  .describe('Run automatic bootstrap during MCP server startup using configured default vault/agent.'),
304
326
  staleAfterMinutes: positiveInteger(120).describe('Bootstrap freshness window in minutes before read tools require a new bootstrap.')
305
327
  };
328
+ export const versionInputSchema = {
329
+ ...vaultInput,
330
+ ...agentInput
331
+ };
306
332
  export const recommendationsInputSchema = {
307
333
  ...vaultInput,
308
334
  ...agentInput,
@@ -311,6 +337,20 @@ export const recommendationsInputSchema = {
311
337
  limit: optionalPositiveInteger().describe('Optional context limit override for generated recommendations.'),
312
338
  tokens: optionalPositiveInteger().describe('Optional context token budget override for generated recommendations.')
313
339
  };
340
+ export const dedupeInputSchema = {
341
+ ...vaultInput,
342
+ ...agentInput,
343
+ limit: optionalPositiveInteger().describe('Maximum duplicate candidate pairs to return.'),
344
+ minScore: z.number().min(0).max(1).optional().describe('Minimum semantic similarity score between 0 and 1.'),
345
+ semantic: z.boolean().optional().default(true).describe('Enable semantic duplicate detection in addition to exact content hash matches.')
346
+ };
347
+ export const dedupeResolveInputSchema = {
348
+ ...vaultInput,
349
+ leftPath: z.string().min(1).describe('Left note path from dedupe results.'),
350
+ rightPath: z.string().min(1).describe('Right note path from dedupe results.'),
351
+ action: z.enum(['merge', 'link', 'ignore']).describe('Resolution action.'),
352
+ autoIndex: z.boolean().optional().default(true).describe('Reindex after duplicate resolution.')
353
+ };
314
354
  export const contextTool = async (input) => {
315
355
  const context = await resolveExecutionContext(input);
316
356
  const readiness = await ensureBootstrapReady(context, input, 'brainlink_context');
@@ -364,6 +404,14 @@ export const addNoteTool = async (input) => {
364
404
  allowSensitive: input.allowSensitive
365
405
  });
366
406
  const index = shouldIndex ? await indexVault(context.vault) : undefined;
407
+ const focusPath = added.path.includes('agents/') ? added.path.slice(added.path.indexOf('agents/')).replaceAll('\\', '/') : undefined;
408
+ const possibleDuplicates = await scanDuplicateNotes(context.vault, {
409
+ agentId: context.agent,
410
+ focusPath,
411
+ limit: 5,
412
+ minSemanticScore: 0.92,
413
+ includeSemantic: true
414
+ });
367
415
  return jsonResult({
368
416
  vault: context.vault,
369
417
  title: input.title,
@@ -374,9 +422,29 @@ export const addNoteTool = async (input) => {
374
422
  linkTarget: added.linkTarget,
375
423
  guaranteedEdge: true
376
424
  },
425
+ possibleDuplicates,
377
426
  ...(index ? { index } : {})
378
427
  });
379
428
  };
429
+ export const volatileAddTool = async (input) => {
430
+ const context = await resolveExecutionContext(input);
431
+ const entry = await addVolatileMemory(context.vault, input.content, context.agent ?? 'shared', input.ttlMinutes ?? 240, input.tags);
432
+ return jsonResult({
433
+ vault: context.vault,
434
+ agent: context.agent,
435
+ volatile: true,
436
+ entry
437
+ });
438
+ };
439
+ export const volatileClearTool = async (input) => {
440
+ const context = await resolveExecutionContext(input);
441
+ const cleared = await clearVolatileMemory(context.vault, context.agent);
442
+ return jsonResult({
443
+ vault: context.vault,
444
+ agent: context.agent,
445
+ cleared
446
+ });
447
+ };
380
448
  export const addFileTool = async (input) => {
381
449
  const context = await resolveExecutionContext(input);
382
450
  const content = await readFile(input.filePath, 'utf8');
@@ -406,7 +474,9 @@ export const addFileTool = async (input) => {
406
474
  };
407
475
  export const indexTool = async (input) => {
408
476
  const context = await resolveExecutionContext(input);
409
- const result = await indexVault(context.vault);
477
+ const result = await indexVault(context.vault, {
478
+ full: input.full === true
479
+ });
410
480
  return jsonResult({
411
481
  vault: context.vault,
412
482
  ...result
@@ -701,12 +771,21 @@ export const policyTool = async (input) => {
701
771
  return jsonResult(withNextActions({
702
772
  vault: context.vault,
703
773
  agent: context.agent,
774
+ runtime: getRuntimeMetadata(),
704
775
  policy,
705
776
  bootstrapStatus,
706
777
  contextStatus,
707
778
  ...(input.preset ? { presetApplied: input.preset } : {})
708
779
  }, withContextAction));
709
780
  };
781
+ export const versionTool = async (input) => {
782
+ const context = await resolveExecutionContext(input);
783
+ return jsonResult({
784
+ vault: context.vault,
785
+ agent: context.agent,
786
+ runtime: getRuntimeMetadata()
787
+ });
788
+ };
710
789
  export const recommendationsTool = async (input) => {
711
790
  const context = await resolveExecutionContext(input);
712
791
  const policy = await getBootstrapPolicy();
@@ -792,6 +871,17 @@ export const recommendationsTool = async (input) => {
792
871
  tokens
793
872
  }
794
873
  },
874
+ {
875
+ tool: 'brainlink_dedupe',
876
+ reason: 'Detect and resolve duplicate durable notes to keep memory quality high.',
877
+ args: {
878
+ vault: context.vault,
879
+ ...(context.agent ? { agent: context.agent } : {}),
880
+ limit: 10,
881
+ minScore: 0.92,
882
+ semantic: true
883
+ }
884
+ },
795
885
  {
796
886
  tool: 'brainlink_add_note',
797
887
  reason: 'Persist durable outcomes after task completion (write responses include connectivity metadata).',
@@ -818,3 +908,30 @@ export const recommendationsTool = async (input) => {
818
908
  recommendations
819
909
  });
820
910
  };
911
+ export const dedupeTool = async (input) => {
912
+ const context = await resolveExecutionContext(input);
913
+ const duplicates = await scanDuplicateNotes(context.vault, {
914
+ agentId: context.agent,
915
+ limit: input.limit ?? 25,
916
+ minSemanticScore: input.minScore ?? 0.92,
917
+ includeSemantic: input.semantic !== false
918
+ });
919
+ return jsonResult({
920
+ vault: context.vault,
921
+ agent: context.agent,
922
+ duplicates
923
+ });
924
+ };
925
+ export const dedupeResolveTool = async (input) => {
926
+ const context = await resolveExecutionContext(input);
927
+ const result = await resolveDuplicateNotes(context.vault, {
928
+ leftPath: input.leftPath,
929
+ rightPath: input.rightPath,
930
+ action: input.action,
931
+ autoIndex: isTruthy(input.autoIndex)
932
+ });
933
+ return jsonResult({
934
+ vault: context.vault,
935
+ ...result
936
+ });
937
+ };
@@ -52,6 +52,8 @@ Use `blink config where` and `blink config doctor` to inspect active paths and e
52
52
 
53
53
  You can also set `defaultAgent` in `brainlink.config.json` / `.brainlink.json` (for example `"defaultAgent": "coding-agent"`). When set, CLI commands and MCP calls reuse it when `--agent`/`agent` is not passed.
54
54
  You can set `agentProfiles` to define per-agent defaults for `defaultSearchMode`, `defaultSearchLimit` and `defaultContextTokens`.
55
+ You can tune search-pack compression with `searchPack.rowChunkSize`, `searchPack.compressionLevel` and `searchPack.useDictionary`.
56
+ Guardrails for benchmark acceptance are configured with `searchPack.guardrailMinSavingsPercent` and `searchPack.guardrailMaxLatencyRegressionPercent`.
55
57
 
56
58
  `autoIndexOnWrite` (default: `true`) controls whether `add` and MCP write tools index right after writing.
57
59
 
@@ -159,7 +161,7 @@ Brainlink only builds graph edges from Markdown `[[wiki links]]`.
159
161
 
160
162
  The `context` command is read-only. It retrieves indexed notes and returns a compact package for the model, but it does not write memory, create backlinks, infer relationships or modify the graph. If an agent reads context and then learns something durable, the agent must write a note with explicit links before that knowledge becomes connected memory.
161
163
 
162
- Graph edges are weighted during indexing. Repeated links increase weight. Links inside headings or task-list lines receive a small boost. Priority markers on the same line as a link raise its priority:
164
+ Graph edges are weighted during indexing. Repeated links increase weight. Links inside headings or task-list lines receive a small boost. Priority markers on the same line as a link raise its priority. The graph relationship model indexes every non-self Markdown `[[wiki link]]` as an edge, including structural hub links such as `Memory Hub`, `Knowledge Root`, `MOC` and map notes. Older indexes without the current graph link model version are automatically rebuilt on the next index run.
163
165
 
164
166
  ```md
165
167
  - [ ] Review [[Architecture]] priority: high
@@ -290,6 +292,8 @@ blink add "Implementation Boundary" \
290
292
  blink index
291
293
  ```
292
294
 
295
+ Use `blink index --full` when you need to rebuild every note from Markdown source. Full reindexing builds the replacement index before persisting it, preserving the previous context until the new index is ready. Brainlink also runs this complete source reindex automatically when it detects an older stored graph link model.
296
+
293
297
  ### Claude Code-Style Agent
294
298
 
295
299
  Use Brainlink as a preflight memory read before editing files:
@@ -377,6 +381,18 @@ blink migrate-vault --from ~/.brainlink/vault --to ./team-vault --report ./migra
377
381
 
378
382
  Use `--dry-run` to preview `copied`, `conflicted`, `unchanged` before writing files.
379
383
 
384
+ ### Import Legacy SQLite DB
385
+
386
+ ```bash
387
+ blink db-import --vault ./team-vault
388
+ blink db-import --vault ./team-vault --db ./legacy/brainlink.db
389
+ blink db-import --vault ./team-vault --db ./legacy/brainlink.db --table legacy_notes --dry-run
390
+ ```
391
+
392
+ `db-import` migrates rows from legacy SQLite memory into Markdown notes in the current vault and indexes the result by default.
393
+ Without `--db`, Brainlink auto-detects common legacy database paths.
394
+ Use `--agent` to force namespace, `--limit` for staged migration, `--dry-run` to preview writes, and `--no-index` to postpone indexing.
395
+
380
396
  ### Install Agent Integration
381
397
 
382
398
  ```bash
@@ -390,6 +406,7 @@ blink agent status
390
406
  ```
391
407
 
392
408
  `agent install` configures Brainlink MCP in `~/.codex/config.toml` so compatible agents can use Brainlink by default.
409
+ `agent install` and `agent upgrade` automatically apply the `fully-auto` MCP bootstrap policy (`enforceBootstrap=true`, `enforceContextFirst=true`, `autoBootstrapOnRead=true`, `autoBootstrapOnStartup=true`) so all plug-and-play Brainlink features start enabled.
393
410
  Use `agent upgrade` on legacy installations to reapply the latest defaults and run self-test diagnostics.
394
411
  Use `agent policy --preset fully-auto` to keep startup/read auto-bootstrap enabled, or `agent policy --preset strict` to force explicit bootstrap calls.
395
412
 
@@ -417,6 +434,25 @@ This creates a slugged Markdown file with frontmatter and a heading.
417
434
 
418
435
  The CLI blocks common secret patterns by default. Do not use `--allow-sensitive` unless the vault is intentionally protected.
419
436
  Brainlink also auto-connects notes that have no `[[wiki links]]` by adding a fallback edge to an agent hub note, so new memory does not stay disconnected.
437
+ `add` also returns `possibleDuplicates` (exact hash + semantic candidates) so agents can decide duplicate resolution immediately.
438
+
439
+ ### Detect Duplicate Notes
440
+
441
+ ```bash
442
+ blink dedupe --vault ./vault --json
443
+ blink dedupe --vault ./vault --agent coding-agent --limit 20 --min-score 0.92 --json
444
+ blink dedupe --vault ./vault --no-semantic --json
445
+ ```
446
+
447
+ ### Resolve Duplicate Notes
448
+
449
+ ```bash
450
+ blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action merge --json
451
+ blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action link --json
452
+ blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action ignore --json
453
+ ```
454
+
455
+ `dedupe-resolve` keeps connectivity: non-merge actions still create a low-priority related edge (`#related-to`).
420
456
 
421
457
  For agent-private memory:
422
458
 
@@ -446,6 +482,37 @@ This scans Markdown files and rebuilds:
446
482
  - links
447
483
  - full-text search records
448
484
 
485
+ ### Benchmark Indexing Realtime
486
+
487
+ ```bash
488
+ blink bench --vault ./vault
489
+ blink bench --vault ./vault --watch
490
+ blink bench --vault ./vault --watch --debounce 500
491
+ blink bench --vault ./vault --json
492
+ ```
493
+
494
+ `bench` runs indexing with realtime phase events and prints a run summary with:
495
+
496
+ - indexed totals (documents, chunks, links)
497
+ - elapsed time and changed document count
498
+ - pack rebuild status and reason
499
+ - pack compression metrics (`inputBytes`, `outputBytes`, ratio/saved percentage)
500
+ - objective guardrails (`guardrailMinSavingsPercent`, `guardrailMaxLatencyRegressionPercent`)
501
+
502
+ Use `--watch` for continuous benchmark runs while editing notes. Watch mode is supported only for local filesystem vaults.
503
+ If pack manifest metadata is missing but encrypted `.blpk` files are present, Brainlink repairs manifest metadata before deciding rebuild policy to avoid unnecessary full repacks on small updates.
504
+
505
+ ### Create Offline Pack Backup
506
+
507
+ ```bash
508
+ blink pack-backup --vault ./vault
509
+ blink pack-backup --vault ./vault --output ./vault/.brainlink/backups/custom.blpkbak.gz
510
+ blink pack-backup --vault ./vault --json
511
+ ```
512
+
513
+ `pack-backup` creates an offline artifact with second-stage compression on top of encrypted `.blpk` packs.
514
+ This is outside the online retrieval path (`index`, `search`, `context`), which keeps a single compression stage.
515
+
449
516
  ### Search Knowledge
450
517
 
451
518
  ```bash
@@ -465,6 +532,7 @@ Search modes:
465
532
  - `semantic`: local deterministic embedding similarity.
466
533
 
467
534
  Hybrid results are cached in-memory for a short TTL and invalidated when `.brainlink/index.json` changes.
535
+ Context assembly uses middle-out ordering inside each note: the highest-scoring chunk is selected first, then nearby chunks are expanded while token budget allows.
468
536
 
469
537
  ### Build Agent Context
470
538
 
@@ -523,15 +591,26 @@ shared: 30 documents
523
591
  ```bash
524
592
  blink server --host 127.0.0.1 --port 4321
525
593
  blink server --vault ./vault --host 127.0.0.1 --port 4321
594
+ blink server --vault ./vault --host 127.0.0.1 --port 4321 --no-open
526
595
  ```
527
596
 
528
597
  This starts a local frontend for inspecting the knowledge graph.
598
+ By default it tries to open the graph in a native desktop GUI window:
599
+ - macOS: Swift + WebKit
600
+ - Windows: PowerShell WinForms WebBrowser
601
+ - Linux: optional Python GTK + WebKit2 (requires `python3` + `gi` + `WebKit2`)
602
+
603
+ On Linux, native GUI is disabled by default for better startup performance. Enable it with `BRAINLINK_LINUX_NATIVE_GUI=1`.
604
+ If native GUI launch is unavailable, it falls back to dedicated app-window mode and then to the default browser.
605
+ Use `--no-open` to keep the server headless.
606
+ When native GUI is active, the GUI window closes automatically when the `blink server` process stops.
529
607
 
530
608
  Without `--vault`, the graph UI serves `$HOME/.brainlink/vault`.
531
609
 
532
- The frontend includes an agent selector. Selecting an agent calls the same read APIs with `agent=<agent-id>` and renders that namespace instead of merging every agent into one graph.
610
+ The frontend includes an agent selector that shows only the agent id. Selecting an agent calls the same read APIs with `agent=<agent-id>` and renders that namespace instead of merging every agent into one graph.
533
611
 
534
- Graph navigation controls include zoom in, zoom out, fit visible nodes and reset-to-fit-all nodes. Mouse wheel zoom is anchored to the cursor. Totals for notes, links and tags stay visible as floating metrics under the Brainlink title, and node details open on click in a modal (tags, outgoing links, backlinks and Markdown content).
612
+ Graph navigation controls include zoom in, zoom out, fit visible nodes and reset-to-fit-all nodes. Mouse wheel zoom (including `cmd+scroll` and `ctrl+scroll`) is anchored to the cursor and applied immediately without delayed focus interpolation. Keyboard shortcuts are `+` (zoom in), `-` (zoom out) and `0` (reset fit). Double-click on empty canvas zooms in at cursor position. Clicking a node opens its details panel. Totals for notes, links and tags stay visible as floating metrics under the Brainlink title, and node details open in a non-modal side panel (tags, outgoing links, backlinks and Markdown content), so zoom and pan remain available during inspection. The visual layout is a star centered on the primary hub, while underlying weighted wiki-link edges are preserved for backlinks, ranking and context traversal. Vaults above 1000 notes keep the same single graph scene and render the full filtered node/edge set during navigation, without viewport-sampled subgraph switching. Node titles appear as zoom approaches readable scale, limited to on-screen nodes in very large graphs.
613
+ During graph filtering, Brainlink keeps hub context nodes visible (`Memory Hub`/`MOC`/high-degree fallback) so filtered views still show relationship anchors.
535
614
 
536
615
  The command reindexes by default, then serves:
537
616
 
@@ -589,8 +668,12 @@ Available MCP tools:
589
668
  - `brainlink_recommendations`
590
669
  - `brainlink_context`
591
670
  - `brainlink_search`
671
+ - `brainlink_dedupe`
672
+ - `brainlink_resolve_duplicate`
592
673
  - `brainlink_add_note`
593
674
  - `brainlink_add_file`
675
+ - `brainlink_volatile_add`
676
+ - `brainlink_volatile_clear`
594
677
  - `brainlink_index`
595
678
  - `brainlink_stats`
596
679
  - `brainlink_validate`
@@ -610,6 +693,7 @@ MCP clients can pass `vault` and `agent` arguments per tool call. Set `BRAINLINK
610
693
 
611
694
  `brainlink_graph` returns weighted edges. Agents should prefer higher `weight` and stronger `priority` when deciding which related notes matter most.
612
695
  `brainlink_add_note` and `brainlink_add_file` return `writeConnectivity` metadata and guarantee at least one edge for new notes.
696
+ Agents should use `brainlink_volatile_add` for temporary task state, hypotheses, local execution details and unconfirmed findings. Volatile memory is included in `brainlink_context` with `Volatile: true`, expires by TTL and does not create durable Markdown notes or graph edges.
613
697
 
614
698
  ```bash
615
699
  export BRAINLINK_ALLOWED_VAULTS="/absolute/path/to/project-vault"
@@ -620,6 +704,7 @@ export BRAINLINK_ALLOWED_VAULTS="/absolute/path/to/project-vault"
620
704
  ```txt
621
705
  GET /api/graph
622
706
  GET /api/graph-layout
707
+ GET /api/graph-view?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>
623
708
  GET /api/graph-node?id=<node-id>
624
709
  GET /api/graph-filter?q=<query>&limit=<n>
625
710
  GET /api/search?q=<query>&limit=10&mode=hybrid
@@ -635,6 +720,7 @@ GET /api/validate
635
720
  The HTTP API is read-only. Use the CLI for writes and indexing.
636
721
 
637
722
  Indexing writes private encrypted search packs at `.brainlink/search-packs/*.blpk` for resilient retrieval and portability.
723
+ Pack search now uses compressed-space prefiltering (token bloom index per pack) before decrypting/reading pack payloads.
638
724
  Pack decryption keys are resolved from `$BRAINLINK_HOME/keys` (or `BRAINLINK_SEARCH_PACK_KEY` when explicitly set).
639
725
 
640
726
  ## Agent Integration Contract
@@ -138,8 +138,10 @@ read markdown files
138
138
  question
139
139
  -> selected mode: fts | semantic | hybrid
140
140
  -> optional query embedding
141
+ -> optional compressed pack prefilter (token bloom)
141
142
  -> lexical scoring and/or semantic cosine scoring
142
143
  -> cosine similarity over candidate chunks
144
+ -> middle-out context expansion around strongest chunk
143
145
  -> ranked chunks with textScore and semanticScore
144
146
  -> token-budget selection
145
147
  -> Markdown context package
@@ -153,10 +155,12 @@ server command
153
155
  -> HTTP server
154
156
  -> /api/agents lists indexed namespaces
155
157
  -> /api/graph reads indexed documents and links
158
+ -> /api/graph-layout derives a star layout from indexed graph data
156
159
  -> browser renders graph canvas
157
160
  ```
158
161
 
159
162
  The graph UI is intentionally read-only. Markdown remains the write interface and index artifacts remain derived data.
163
+ The star layout is visual only: it keeps the indexed weighted wiki-link edges unchanged so backlinks, ranking and context traversal keep their original semantics.
160
164
 
161
165
  ## HTTP API Flow
162
166
 
@@ -169,6 +173,7 @@ HTTP request
169
173
  ```
170
174
 
171
175
  The HTTP API is local-first and unauthenticated. It is meant for local agents, browser UI, and development workflows.
176
+ The route adapter caches generated frontend assets (`/`, `/styles.css`, `/app.js`, `/app-worker.js`) and graph-layout JSON payloads by layout signature to reduce repeated CPU and allocation pressure during navigation.
172
177
 
173
178
  ## MCP Flow
174
179
 
@@ -293,6 +298,7 @@ Markdown keeps the system portable, inspectable, Git-friendly, and compatible wi
293
298
  Brainlink uses a local JSON index plus encrypted pack exports for fast rebuildable retrieval without external infrastructure.
294
299
  Hybrid retrieval also uses a short-lived in-memory cache keyed by vault/query/agent and invalidated by index file mtime to reduce repeated query latency.
295
300
  Indexing exports private encrypted pack files (`.brainlink/search-packs/*.blpk`) from indexed chunks for fast retrieval and recovery continuity.
301
+ Pack manifests include compressed-space token bloom metadata so retrieval can skip unrelated packs before decryption.
296
302
  Pack encryption keys are resolved from `$BRAINLINK_HOME/keys` or from `BRAINLINK_SEARCH_PACK_KEY` when configured.
297
303
  Legacy `.jsonl.gz` search packs are auto-upgraded to `.blpk` on first retrieval flow.
298
304
 
@@ -102,3 +102,10 @@ S3 target:
102
102
  ```bash
103
103
  blink migrate-vault --from ~/.brainlink/vault --to "s3://my-memory-bucket/brainlink" --dry-run
104
104
  ```
105
+
106
+ Legacy SQLite import:
107
+
108
+ ```bash
109
+ blink db-import --vault ./team-vault
110
+ blink db-import --vault ./team-vault --db ./legacy/brainlink.db --dry-run
111
+ ```
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.15",
3
+ "version": "0.1.0-beta.151",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
- "author": "Anderson Espindola",
7
+ "author": "Substructa",
8
8
  "homepage": "https://github.com/andersonflima/brainlink#readme",
9
9
  "repository": {
10
10
  "type": "git",
@@ -32,6 +32,7 @@
32
32
  "dist",
33
33
  "assets",
34
34
  "README.md",
35
+ "COPYRIGHT.md",
35
36
  "LICENSE",
36
37
  "CHANGELOG.md",
37
38
  "CONTRIBUTING.md",
@@ -61,6 +62,10 @@
61
62
  "commander": "^14.0.2",
62
63
  "zod": "^4.3.6"
63
64
  },
65
+ "overrides": {
66
+ "hono": "4.12.21",
67
+ "qs": "6.15.2"
68
+ },
64
69
  "devDependencies": {
65
70
  "@types/node": "^24.9.2",
66
71
  "tsx": "^4.21.0",