@andespindola/brainlink 0.1.0-beta.152 → 0.1.0-beta.154

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/dist/mcp/tools.js CHANGED
@@ -4,8 +4,10 @@ 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 { canonicalizeContextLinks } from '../application/canonical-context-links.js';
7
8
  import { resolveDuplicateNotes, scanDuplicateNotes } from '../application/dedupe-notes.js';
8
9
  import { getGraph } from '../application/get-graph.js';
10
+ import { getGraphContexts } from '../application/get-graph-contexts.js';
9
11
  import { indexVault } from '../application/index-vault.js';
10
12
  import { searchKnowledge } from '../application/search-knowledge.js';
11
13
  import { resolveAgentRuntimeDefaults, sanitizeSearchMode } from '../infrastructure/config.js';
@@ -237,7 +239,11 @@ export const addNoteInputSchema = {
237
239
  .describe('Durable Markdown memory. Include explicit [[wiki links]] and #tags when the memory should be connected. Put priority markers near important links, for example priority: high, #important or #critical.'),
238
240
  ...agentInput,
239
241
  allowSensitive: z.boolean().optional().default(false).describe('Allow content that looks like a secret.'),
240
- autoIndex: z.boolean().optional().default(true).describe('Reindex vault after writing note.')
242
+ autoIndex: z.boolean().optional().default(true).describe('Reindex vault after writing note.'),
243
+ autoContextLinks: z
244
+ .boolean()
245
+ .optional()
246
+ .describe('Automatically add canonical Context Links to the inferred visual context hub. Defaults to Brainlink config.')
241
247
  };
242
248
  export const volatileAddInputSchema = {
243
249
  ...vaultInput,
@@ -261,6 +267,13 @@ export const addFileInputSchema = {
261
267
  autoIndex: z.boolean().optional().default(true).describe('Reindex vault after ingesting file.'),
262
268
  allowSensitive: z.boolean().optional().default(false).describe('Allow content that looks like a secret.')
263
269
  };
270
+ export const canonicalizeContextLinksInputSchema = {
271
+ ...vaultInput,
272
+ ...agentInput,
273
+ dryRun: z.boolean().optional().default(false).describe('Preview canonical context-link writes without changing Markdown.'),
274
+ createHubs: z.boolean().optional().default(true).describe('Create missing context hub notes when needed.'),
275
+ autoIndex: z.boolean().optional().default(true).describe('Reindex after canonicalization when files changed.')
276
+ };
264
277
  export const indexInputSchema = {
265
278
  ...vaultInput,
266
279
  full: z
@@ -277,6 +290,10 @@ export const graphInputSchema = {
277
290
  ...vaultInput,
278
291
  ...agentInput
279
292
  };
293
+ export const graphContextsInputSchema = {
294
+ ...vaultInput,
295
+ ...agentInput
296
+ };
280
297
  export const brokenLinksInputSchema = {
281
298
  ...vaultInput,
282
299
  ...agentInput
@@ -401,7 +418,8 @@ export const addNoteTool = async (input) => {
401
418
  const context = await resolveExecutionContext(input);
402
419
  const shouldIndex = isTruthy(input.autoIndex);
403
420
  const added = await addNoteWithMetadata(context.vault, input.title, input.content, context.agent, {
404
- allowSensitive: input.allowSensitive
421
+ allowSensitive: input.allowSensitive,
422
+ autoContextLinks: input.autoContextLinks ?? context.config.autoCanonicalContextLinks
405
423
  });
406
424
  const index = shouldIndex ? await indexVault(context.vault) : undefined;
407
425
  const focusPath = added.path.includes('agents/') ? added.path.slice(added.path.indexOf('agents/')).replaceAll('\\', '/') : undefined;
@@ -420,7 +438,9 @@ export const addNoteTool = async (input) => {
420
438
  writeConnectivity: {
421
439
  autoLinked: added.autoLinked,
422
440
  linkTarget: added.linkTarget,
423
- guaranteedEdge: false
441
+ context: added.context,
442
+ hubCreated: added.hubCreated,
443
+ guaranteedEdge: added.autoLinked
424
444
  },
425
445
  possibleDuplicates,
426
446
  ...(index ? { index } : {})
@@ -455,7 +475,8 @@ export const addFileTool = async (input) => {
455
475
  }
456
476
  const shouldIndex = isTruthy(input.autoIndex);
457
477
  const added = await addNoteWithMetadata(context.vault, title, content, context.agent, {
458
- allowSensitive: input.allowSensitive
478
+ allowSensitive: input.allowSensitive,
479
+ autoContextLinks: context.config.autoCanonicalContextLinks
459
480
  });
460
481
  const index = shouldIndex ? await indexVault(context.vault) : undefined;
461
482
  return jsonResult({
@@ -467,11 +488,30 @@ export const addFileTool = async (input) => {
467
488
  writeConnectivity: {
468
489
  autoLinked: added.autoLinked,
469
490
  linkTarget: added.linkTarget,
470
- guaranteedEdge: false
491
+ context: added.context,
492
+ hubCreated: added.hubCreated,
493
+ guaranteedEdge: added.autoLinked
471
494
  },
472
495
  ...(index ? { index } : {})
473
496
  });
474
497
  };
498
+ export const canonicalizeContextLinksTool = async (input) => {
499
+ const context = await resolveExecutionContext(input);
500
+ const result = await canonicalizeContextLinks(context.vault, {
501
+ agentId: context.agent,
502
+ dryRun: input.dryRun === true,
503
+ createMissingHubs: input.createHubs !== false
504
+ });
505
+ const index = input.autoIndex !== false && !result.dryRun && result.changed > 0
506
+ ? await indexVault(context.vault, { full: true })
507
+ : undefined;
508
+ return jsonResult({
509
+ vault: context.vault,
510
+ agent: context.agent,
511
+ ...result,
512
+ ...(index ? { index } : {})
513
+ });
514
+ };
475
515
  export const indexTool = async (input) => {
476
516
  const context = await resolveExecutionContext(input);
477
517
  const result = await indexVault(context.vault, {
@@ -520,6 +560,25 @@ export const graphTool = async (input) => {
520
560
  ...graph
521
561
  });
522
562
  };
563
+ export const graphContextsTool = async (input) => {
564
+ const context = await resolveExecutionContext(input);
565
+ const readiness = await ensureBootstrapReady(context, input, 'brainlink_graph_contexts');
566
+ if (readiness.preflight) {
567
+ return readiness.preflight;
568
+ }
569
+ const contextReadiness = await ensureContextReady(context, input, 'brainlink_graph_contexts');
570
+ if (contextReadiness.preflight) {
571
+ return contextReadiness.preflight;
572
+ }
573
+ const contexts = await getGraphContexts(context.vault, context.agent);
574
+ return jsonResult({
575
+ vault: context.vault,
576
+ agent: context.agent,
577
+ ...(readiness.bootstrap ? { bootstrap: readiness.bootstrap } : {}),
578
+ ...(contextReadiness.context ? { contextReadiness: contextReadiness.context } : {}),
579
+ contexts
580
+ });
581
+ };
523
582
  export const brokenLinksTool = async (input) => {
524
583
  const context = await resolveExecutionContext(input);
525
584
  const readiness = await ensureBootstrapReady(context, input, 'brainlink_broken_links');
@@ -56,6 +56,7 @@ You can tune search-pack compression with `searchPack.rowChunkSize`, `searchPack
56
56
  Guardrails for benchmark acceptance are configured with `searchPack.guardrailMinSavingsPercent` and `searchPack.guardrailMaxLatencyRegressionPercent`.
57
57
 
58
58
  `autoIndexOnWrite` (default: `true`) controls whether `add` and MCP write tools index right after writing.
59
+ `autoCanonicalContextLinks` (default: `true`) controls whether CLI/MCP write tools add canonical `## Context Links` to inferred context hubs.
59
60
 
60
61
  ## Agent Namespaces
61
62
 
@@ -627,12 +628,14 @@ Use `--no-index` when you need to inspect the current index without rebuilding i
627
628
  blink server --vault ./vault --no-index
628
629
  ```
629
630
 
630
- Use `--watch` to keep the graph updated after Markdown edits:
631
+ The server watches Markdown files by default and keeps the graph updated after edits:
631
632
 
632
633
  ```bash
633
- blink server --vault ./vault --watch
634
+ blink server --vault ./vault
634
635
  ```
635
636
 
637
+ Use `--no-watch` when you need to run the graph server without realtime reindexing.
638
+
636
639
  ### Watch A Vault
637
640
 
638
641
  ```bash
@@ -672,6 +675,7 @@ Available MCP tools:
672
675
  - `brainlink_resolve_duplicate`
673
676
  - `brainlink_add_note`
674
677
  - `brainlink_add_file`
678
+ - `brainlink_canonicalize_context_links`
675
679
  - `brainlink_volatile_add`
676
680
  - `brainlink_volatile_clear`
677
681
  - `brainlink_index`
@@ -679,6 +683,7 @@ Available MCP tools:
679
683
  - `brainlink_validate`
680
684
  - `brainlink_sync`
681
685
  - `brainlink_graph`
686
+ - `brainlink_graph_contexts`
682
687
  - `brainlink_broken_links`
683
688
  - `brainlink_orphans`
684
689
 
@@ -154,8 +154,10 @@ server command
154
154
  -> optional index rebuild
155
155
  -> HTTP server
156
156
  -> /api/agents lists indexed namespaces
157
+ -> /api/graph-contexts lists visual graph contexts
157
158
  -> /api/graph reads indexed documents and links
158
159
  -> /api/graph-layout derives a star layout from indexed graph data
160
+ -> optional context query narrows the layout to a segment-scoped star subgraph
159
161
  -> browser renders graph canvas
160
162
  ```
161
163
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.152",
3
+ "version": "0.1.0-beta.154",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",