@andespindola/brainlink 1.0.4 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -569,7 +569,7 @@ By default, Brainlink enforces bootstrap and auto-runs it for read tools when se
569
569
  If you disable `autoBootstrapOnRead` through `brainlink_policy`, read tools return a preflight instruction with suggested `brainlink_bootstrap` arguments.
570
570
  `brainlink_bootstrap`, `brainlink_policy` and preflight responses include structured `nextActions` so MCP clients can continue automatically without custom parsing.
571
571
  For one-call planning, use `brainlink_recommendations` to get the recommended tool sequence for the current vault/agent/query.
572
- 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.
572
+ The MCP context tools are plug-and-play by default: omit `strategy` to use the configured token-efficient default (`auto` unless changed), pass `strategy: "cag"` for repeated/stable task context, or pass `strategy: "rag"` when fresh retrieval is required. `brainlink_recommendations`, preflight responses and policy next actions include executable context arguments so clients can continue without custom parsing.
573
573
 
574
574
  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.
575
575
 
@@ -657,8 +657,8 @@ Routes:
657
657
  - `GET /api/graph-view?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>`
658
658
  - `GET /api/graph-stream?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>&nodeBudget=<n>&edgeBudget=<n>`
659
659
  - `GET /api/graph-node?id=<node-id>`
660
- - `GET /api/search?q=<query>&limit=10&mode=hybrid`
661
- - `GET /api/context?q=<query>&limit=12&tokens=2000&mode=hybrid`
660
+ - `GET /api/search?q=<query>&limit=8&mode=hybrid`
661
+ - `GET /api/context?q=<query>&limit=8&tokens=1500&mode=hybrid`
662
662
  - `GET /api/links`
663
663
  - `GET /api/backlinks?title=<title>`
664
664
  - `GET /api/stats`
@@ -936,7 +936,7 @@ Context selection uses a middle-out strategy: it starts from the strongest chunk
936
936
  ### `context`
937
937
 
938
938
  ```bash
939
- blink context "question" --vault ./vault --limit 12 --tokens 2000
939
+ blink context "question" --vault ./vault --limit 8 --tokens 1500
940
940
  blink context "question" --vault ./vault --agent coding-agent --json
941
941
  blink context "question" --vault ./vault --agent coding-agent --mode hybrid --json
942
942
  blink context "question" --vault ./vault --agent coding-agent --strategy cag --json
@@ -947,7 +947,7 @@ blink context-packs --vault ./vault --stale --clear
947
947
 
948
948
  Builds a compact context package for an agent.
949
949
  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.
950
- 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.
950
+ The default strategy is configured by `defaultContextStrategy` and starts as `auto`, which uses CAG when a fresh pack exists and RAG otherwise, refreshing a pack for future calls. `--strategy cag` enables cache-augmented context generation by reading or refreshing a persisted context pack under `.brainlink/context-packs`; `--strategy rag` forces fresh retrieval assembly from the current index. Context responses include `cache`, `metrics`, `requestedStrategy` and `recommendedStrategy` metadata. Packs are derived artifacts and become stale when the index or volatile memory signature changes.
951
951
 
952
952
  ### `links`
953
953
 
@@ -1088,9 +1088,9 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
1088
1088
  "defaultAgent": "shared",
1089
1089
  "autoIndexOnWrite": true,
1090
1090
  "autoCanonicalContextLinks": true,
1091
- "defaultSearchLimit": 10,
1092
- "defaultContextTokens": 2000,
1093
- "defaultContextStrategy": "rag",
1091
+ "defaultSearchLimit": 8,
1092
+ "defaultContextTokens": 1500,
1093
+ "defaultContextStrategy": "auto",
1094
1094
  "embeddingProvider": "local",
1095
1095
  "defaultSearchMode": "hybrid",
1096
1096
  "chunkSize": 1200,
@@ -1105,7 +1105,7 @@ If no `vault` is configured and no `--vault` flag is passed, Brainlink uses `$HO
1105
1105
  "coding-agent": {
1106
1106
  "defaultSearchMode": "semantic",
1107
1107
  "defaultSearchLimit": 8,
1108
- "defaultContextTokens": 2400,
1108
+ "defaultContextTokens": 1500,
1109
1109
  "defaultContextStrategy": "auto"
1110
1110
  },
1111
1111
  "*": {
@@ -24,19 +24,20 @@ import { createClientWorkerJs } from '../frontend/client-worker-js.js';
24
24
  import { createClientRenderWorkerJs } from '../frontend/client-render-worker-js.js';
25
25
  import { contentTypes, createJsonResponse, isReadMethod, parsePositiveInteger } from './http.js';
26
26
  import { parseMultipartForm } from './multipart.js';
27
- const readSearchMode = async (url) => {
27
+ const readRuntimeDefaults = async (url) => {
28
28
  const config = await loadBrainlinkConfig();
29
- const defaults = resolveAgentRuntimeDefaults(config, readAgentQuery(url));
29
+ return resolveAgentRuntimeDefaults(config, readAgentQuery(url));
30
+ };
31
+ const readSearchMode = async (url) => {
32
+ const defaults = await readRuntimeDefaults(url);
30
33
  return sanitizeSearchMode(url.searchParams.get('mode'), defaults.defaultSearchMode);
31
34
  };
32
35
  const readContextStrategy = async (url) => {
33
- const config = await loadBrainlinkConfig();
34
- const defaults = resolveAgentRuntimeDefaults(config, readAgentQuery(url));
36
+ const defaults = await readRuntimeDefaults(url);
35
37
  return sanitizeContextStrategy(url.searchParams.get('strategy'), defaults.defaultContextStrategy);
36
38
  };
37
39
  const readContextCacheTtlMs = async (url) => {
38
- const config = await loadBrainlinkConfig();
39
- const defaults = resolveAgentRuntimeDefaults(config, readAgentQuery(url));
40
+ const defaults = await readRuntimeDefaults(url);
40
41
  return defaults.defaultContextCacheTtlMs;
41
42
  };
42
43
  const hasInvalidSearchMode = (url) => {
@@ -428,7 +429,8 @@ export const route = async (request, url, vaultPath) => {
428
429
  }
429
430
  if (isReadMethod(request) && url.pathname === '/api/search') {
430
431
  const query = url.searchParams.get('q') ?? '';
431
- const limit = parsePositiveInteger(url.searchParams.get('limit'), 10);
432
+ const defaults = await readRuntimeDefaults(url);
433
+ const limit = parsePositiveInteger(url.searchParams.get('limit'), defaults.defaultSearchLimit);
432
434
  const mode = await readSearchMode(url);
433
435
  if (hasInvalidSearchMode(url)) {
434
436
  return createResponse(createJsonResponse({ error: 'Invalid mode. Use fts, semantic or hybrid.' }), 400, contentTypes['.json']);
@@ -437,8 +439,9 @@ export const route = async (request, url, vaultPath) => {
437
439
  }
438
440
  if (isReadMethod(request) && url.pathname === '/api/context') {
439
441
  const query = url.searchParams.get('q') ?? '';
440
- const limit = parsePositiveInteger(url.searchParams.get('limit'), 12);
441
- const tokens = parsePositiveInteger(url.searchParams.get('tokens'), 2000);
442
+ const defaults = await readRuntimeDefaults(url);
443
+ const limit = parsePositiveInteger(url.searchParams.get('limit'), defaults.defaultSearchLimit);
444
+ const tokens = parsePositiveInteger(url.searchParams.get('tokens'), defaults.defaultContextTokens);
442
445
  const mode = await readSearchMode(url);
443
446
  const strategy = await readContextStrategy(url);
444
447
  const contextCacheTtlMs = await readContextCacheTtlMs(url);
@@ -11,9 +11,9 @@ export const defaultBrainlinkConfig = {
11
11
  defaultAgent: undefined,
12
12
  autoIndexOnWrite: true,
13
13
  autoCanonicalContextLinks: true,
14
- defaultSearchLimit: 10,
15
- defaultContextTokens: 2000,
16
- defaultContextStrategy: 'rag',
14
+ defaultSearchLimit: 8,
15
+ defaultContextTokens: 1500,
16
+ defaultContextStrategy: 'auto',
17
17
  defaultContextCacheTtlMs: 120_000,
18
18
  embeddingProvider: 'local',
19
19
  defaultSearchMode: 'hybrid',
@@ -46,7 +46,7 @@ const searchModes = new Set(['fts', 'semantic', 'hybrid']);
46
46
  const contextStrategies = new Set(['rag', 'cag', 'auto']);
47
47
  const sanitizeEmbeddingProvider = (value) => typeof value === 'string' && embeddingProviders.has(value) ? value : defaultBrainlinkConfig.embeddingProvider;
48
48
  export const sanitizeSearchMode = (value, fallback = defaultBrainlinkConfig.defaultSearchMode) => typeof value === 'string' && searchModes.has(value) ? value : fallback;
49
- export const sanitizeContextStrategy = (value, fallback = 'rag') => typeof value === 'string' && contextStrategies.has(value) ? value : fallback;
49
+ export const sanitizeContextStrategy = (value, fallback = defaultBrainlinkConfig.defaultContextStrategy) => typeof value === 'string' && contextStrategies.has(value) ? value : fallback;
50
50
  const sanitizeAllowedVaults = (value) => Array.isArray(value) ? value.filter((item) => typeof item === 'string' && item.trim().length > 0) : [];
51
51
  const sanitizePositiveNumber = (value) => typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : undefined;
52
52
  const sanitizeIntegerInRange = (value, fallback, minimum, maximum) => {
@@ -585,7 +585,7 @@ Context assembly uses middle-out ordering inside each note: the highest-scoring
585
585
  ### Build Agent Context
586
586
 
587
587
  ```bash
588
- blink context "how does authentication work?" --vault ./vault --limit 12 --tokens 2000
588
+ blink context "how does authentication work?" --vault ./vault --limit 8 --tokens 1500
589
589
  blink context "how does authentication work?" --vault ./vault --json
590
590
  blink context "how does authentication work?" --vault ./vault --agent coding-agent --json
591
591
  blink context "how does authentication work?" --vault ./vault --agent coding-agent --mode hybrid --json
@@ -596,7 +596,7 @@ blink context-packs --vault ./vault --stale --clear
596
596
  ```
597
597
 
598
598
  This returns a Markdown context package optimized for prompt injection.
599
- The default strategy is configured by `defaultContextStrategy` and starts as `rag`. Use `--strategy cag` when the same agent/task context should be served from a persisted context pack when the index and volatile-memory signatures are unchanged. Use `--strategy auto` when Brainlink should use CAG on fresh pack hits and RAG otherwise. Context responses include `cache`, `metrics`, `requestedStrategy` and `recommendedStrategy` metadata. CAG packs live under `.brainlink/context-packs` and are rebuildable derived artifacts.
599
+ The default strategy is configured by `defaultContextStrategy` and starts as `auto`, so repeated stable context can reuse fresh CAG packs while misses fall back to RAG and refresh a pack for later calls. Use `--strategy cag` when the same agent/task context must be served from a persisted context pack when the index and volatile-memory signatures are unchanged. Use `--strategy rag` when fresh retrieval is required. Context responses include `cache`, `metrics`, `requestedStrategy` and `recommendedStrategy` metadata. CAG packs live under `.brainlink/context-packs` and are rebuildable derived artifacts.
600
600
 
601
601
  ### Inspect Links
602
602
 
@@ -778,8 +778,8 @@ GET /api/graph-layout
778
778
  GET /api/graph-view?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>
779
779
  GET /api/graph-node?id=<node-id>
780
780
  GET /api/graph-filter?q=<query>&limit=<n>
781
- GET /api/search?q=<query>&limit=10&mode=hybrid
782
- GET /api/context?q=<query>&limit=12&tokens=2000&mode=hybrid
781
+ GET /api/search?q=<query>&limit=8&mode=hybrid
782
+ GET /api/context?q=<query>&limit=8&tokens=1500&mode=hybrid
783
783
  GET /api/links
784
784
  GET /api/backlinks?title=<title>
785
785
  GET /api/stats
@@ -50,7 +50,7 @@ Optional per-agent retrieval defaults in `brainlink.config.json`:
50
50
  "coding-agent": {
51
51
  "defaultSearchMode": "semantic",
52
52
  "defaultSearchLimit": 8,
53
- "defaultContextTokens": 2400,
53
+ "defaultContextTokens": 1500,
54
54
  "defaultContextStrategy": "auto",
55
55
  "defaultContextCacheTtlMs": 120000
56
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",