@andespindola/brainlink 0.1.0-beta.163 → 0.1.0-beta.165
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 +14 -4
- package/dist/application/build-context.js +105 -11
- package/dist/application/frontend/client-css.js +37 -31
- package/dist/application/frontend/client-js.js +103 -37
- package/dist/application/server/routes.js +17 -3
- package/dist/cli/commands/read-commands.js +39 -3
- package/dist/cli/commands/write-commands.js +4 -2
- package/dist/infrastructure/config.js +11 -2
- package/dist/infrastructure/context-packs.js +122 -0
- package/dist/mcp/server.js +8 -3
- package/dist/mcp/tools.js +82 -7
- package/docs/AGENT_USAGE.md +8 -1
- package/docs/ARCHITECTURE.md +6 -0
- package/docs/QUICKSTART.md +2 -1
- package/package.json +1 -1
package/dist/mcp/tools.js
CHANGED
|
@@ -3,14 +3,15 @@ import { basename, extname } from 'node:path';
|
|
|
3
3
|
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
|
-
import { buildContextPackage } from '../application/build-context.js';
|
|
6
|
+
import { buildContextPackage, readContextDataSignature } from '../application/build-context.js';
|
|
7
7
|
import { canonicalizeContextLinks } from '../application/canonical-context-links.js';
|
|
8
8
|
import { resolveDuplicateNotes, scanDuplicateNotes } from '../application/dedupe-notes.js';
|
|
9
9
|
import { getGraph } from '../application/get-graph.js';
|
|
10
10
|
import { getGraphContexts } from '../application/get-graph-contexts.js';
|
|
11
11
|
import { indexVault } from '../application/index-vault.js';
|
|
12
12
|
import { searchKnowledge } from '../application/search-knowledge.js';
|
|
13
|
-
import { resolveAgentRuntimeDefaults, sanitizeSearchMode } from '../infrastructure/config.js';
|
|
13
|
+
import { resolveAgentRuntimeDefaults, sanitizeContextStrategy, sanitizeSearchMode } from '../infrastructure/config.js';
|
|
14
|
+
import { clearContextPacks, listContextPacks } from '../infrastructure/context-packs.js';
|
|
14
15
|
import { loadBrainlinkConfig } from '../infrastructure/config.js';
|
|
15
16
|
import { assertVaultAllowed } from '../infrastructure/file-system-vault.js';
|
|
16
17
|
import { addVolatileMemory, clearVolatileMemory } from '../infrastructure/volatile-memory.js';
|
|
@@ -40,6 +41,12 @@ const agentInput = {
|
|
|
40
41
|
const searchModeInput = {
|
|
41
42
|
mode: z.enum(['fts', 'semantic', 'hybrid']).optional().describe('Search mode. Defaults to the Brainlink config value.')
|
|
42
43
|
};
|
|
44
|
+
const contextStrategyInput = {
|
|
45
|
+
strategy: z
|
|
46
|
+
.enum(['rag', 'cag', 'auto'])
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('Context strategy per call. Use rag for fresh retrieval assembly, cag to reuse persisted context packs when fresh, or auto to choose CAG on fresh pack hits and RAG otherwise. Defaults to the Brainlink config value.')
|
|
49
|
+
};
|
|
43
50
|
const resolveExecutionContext = async (input) => {
|
|
44
51
|
const config = await loadBrainlinkConfig();
|
|
45
52
|
const vault = await assertVaultAllowed(input.vault ?? config.vault, config.allowedVaults);
|
|
@@ -122,12 +129,14 @@ const ensureBootstrapReady = async (context, input, toolName) => {
|
|
|
122
129
|
};
|
|
123
130
|
}
|
|
124
131
|
const mode = typeof input.mode === 'string' && ['fts', 'semantic', 'hybrid'].includes(input.mode) ? input.mode : 'hybrid';
|
|
132
|
+
const strategy = sanitizeContextStrategy(typeof input.strategy === 'string' ? input.strategy : undefined, 'rag');
|
|
125
133
|
const query = typeof input.query === 'string' && input.query.trim().length > 0 ? input.query : undefined;
|
|
126
134
|
const bootstrapArgs = {
|
|
127
135
|
vault: context.vault,
|
|
128
136
|
...(context.agent ? { agent: context.agent } : {}),
|
|
129
137
|
...(query ? { query } : {}),
|
|
130
|
-
mode
|
|
138
|
+
mode,
|
|
139
|
+
strategy
|
|
131
140
|
};
|
|
132
141
|
const nextActions = [
|
|
133
142
|
{
|
|
@@ -178,6 +187,7 @@ const ensureContextReady = async (context, input, toolName) => {
|
|
|
178
187
|
? input.contextQuery
|
|
179
188
|
: '<task>';
|
|
180
189
|
const mode = sanitizeSearchMode(typeof input.mode === 'string' ? input.mode : undefined, context.defaults.defaultSearchMode);
|
|
190
|
+
const strategy = sanitizeContextStrategy(typeof input.strategy === 'string' ? input.strategy : undefined, context.defaults.defaultContextStrategy);
|
|
181
191
|
const limit = typeof input.limit === 'number' && Number.isFinite(input.limit) && input.limit > 0
|
|
182
192
|
? input.limit
|
|
183
193
|
: typeof input.contextLimit === 'number' && Number.isFinite(input.contextLimit) && input.contextLimit > 0
|
|
@@ -193,6 +203,7 @@ const ensureContextReady = async (context, input, toolName) => {
|
|
|
193
203
|
...(context.agent ? { agent: context.agent } : {}),
|
|
194
204
|
query: queryFromInput,
|
|
195
205
|
mode,
|
|
206
|
+
strategy,
|
|
196
207
|
limit,
|
|
197
208
|
tokens
|
|
198
209
|
};
|
|
@@ -219,10 +230,17 @@ export const contextInputSchema = {
|
|
|
219
230
|
...vaultInput,
|
|
220
231
|
...agentInput,
|
|
221
232
|
...searchModeInput,
|
|
233
|
+
...contextStrategyInput,
|
|
222
234
|
query: z.string().min(1).describe('Task or question to retrieve Brainlink context for.'),
|
|
223
235
|
limit: optionalPositiveInteger().describe('Maximum search results before context selection.'),
|
|
224
236
|
tokens: optionalPositiveInteger().describe('Maximum estimated context tokens.')
|
|
225
237
|
};
|
|
238
|
+
export const contextPacksInputSchema = {
|
|
239
|
+
...vaultInput,
|
|
240
|
+
...agentInput,
|
|
241
|
+
action: z.enum(['list', 'clear']).optional().default('list').describe('Action to perform on persisted CAG context packs.'),
|
|
242
|
+
staleOnly: z.boolean().optional().default(false).describe('When clearing, remove only packs stale for the current index and volatile-memory signature.')
|
|
243
|
+
};
|
|
226
244
|
export const searchInputSchema = {
|
|
227
245
|
...vaultInput,
|
|
228
246
|
...agentInput,
|
|
@@ -311,6 +329,7 @@ export const syncInputSchema = {
|
|
|
311
329
|
...agentInput,
|
|
312
330
|
contextQuery: z.string().min(1).optional().describe('Optional context smoke query. Omit to skip context probe.'),
|
|
313
331
|
mode: z.enum(['fts', 'semantic', 'hybrid']).optional().describe('Search mode for the optional context probe. Defaults to config value.'),
|
|
332
|
+
strategy: z.enum(['rag', 'cag', 'auto']).optional().describe('Context strategy for the optional context probe. Defaults to the Brainlink config value.'),
|
|
314
333
|
contextLimit: optionalPositiveInteger().describe('Context smoke result limit when contextQuery is provided.'),
|
|
315
334
|
contextTokens: optionalPositiveInteger().describe('Context smoke token target when contextQuery is provided.')
|
|
316
335
|
};
|
|
@@ -318,6 +337,7 @@ export const bootstrapInputSchema = {
|
|
|
318
337
|
...vaultInput,
|
|
319
338
|
...agentInput,
|
|
320
339
|
...searchModeInput,
|
|
340
|
+
...contextStrategyInput,
|
|
321
341
|
query: z
|
|
322
342
|
.string()
|
|
323
343
|
.min(1)
|
|
@@ -350,6 +370,7 @@ export const recommendationsInputSchema = {
|
|
|
350
370
|
...vaultInput,
|
|
351
371
|
...agentInput,
|
|
352
372
|
...searchModeInput,
|
|
373
|
+
...contextStrategyInput,
|
|
353
374
|
query: z.string().min(1).optional().describe('Optional current task query to generate context-focused recommendations.'),
|
|
354
375
|
limit: optionalPositiveInteger().describe('Optional context limit override for generated recommendations.'),
|
|
355
376
|
tokens: optionalPositiveInteger().describe('Optional context token budget override for generated recommendations.')
|
|
@@ -375,14 +396,16 @@ export const contextTool = async (input) => {
|
|
|
375
396
|
return readiness.preflight;
|
|
376
397
|
}
|
|
377
398
|
const mode = sanitizeSearchMode(input.mode, context.defaults.defaultSearchMode);
|
|
399
|
+
const strategy = sanitizeContextStrategy(input.strategy, context.defaults.defaultContextStrategy);
|
|
378
400
|
const limit = input.limit ?? context.defaults.defaultSearchLimit;
|
|
379
401
|
const tokens = input.tokens ?? context.defaults.defaultContextTokens;
|
|
380
|
-
const contextPackage = await buildContextPackage(context.vault, input.query, limit, tokens, context.agent, mode);
|
|
402
|
+
const contextPackage = await buildContextPackage(context.vault, input.query, limit, tokens, context.agent, mode, strategy);
|
|
381
403
|
const contextSession = await touchContextSession(context.vault, context.agent);
|
|
382
404
|
return jsonResult({
|
|
383
405
|
vault: context.vault,
|
|
384
406
|
agent: context.agent,
|
|
385
407
|
mode,
|
|
408
|
+
strategy,
|
|
386
409
|
limit,
|
|
387
410
|
tokens,
|
|
388
411
|
contextSession,
|
|
@@ -390,6 +413,32 @@ export const contextTool = async (input) => {
|
|
|
390
413
|
...contextPackage
|
|
391
414
|
});
|
|
392
415
|
};
|
|
416
|
+
export const contextPacksTool = async (input) => {
|
|
417
|
+
const context = await resolveExecutionContext(input);
|
|
418
|
+
const dataSignature = await readContextDataSignature(context.vault);
|
|
419
|
+
if (input.action === 'clear') {
|
|
420
|
+
const result = await clearContextPacks(context.vault, {
|
|
421
|
+
staleOnly: input.staleOnly === true,
|
|
422
|
+
dataSignature
|
|
423
|
+
});
|
|
424
|
+
return jsonResult({
|
|
425
|
+
vault: context.vault,
|
|
426
|
+
agent: context.agent,
|
|
427
|
+
dataSignature,
|
|
428
|
+
action: 'clear',
|
|
429
|
+
staleOnly: input.staleOnly === true,
|
|
430
|
+
...result
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
const packs = await listContextPacks(context.vault, dataSignature);
|
|
434
|
+
return jsonResult({
|
|
435
|
+
vault: context.vault,
|
|
436
|
+
agent: context.agent,
|
|
437
|
+
dataSignature,
|
|
438
|
+
action: 'list',
|
|
439
|
+
packs
|
|
440
|
+
});
|
|
441
|
+
};
|
|
393
442
|
export const searchTool = async (input) => {
|
|
394
443
|
const context = await resolveExecutionContext(input);
|
|
395
444
|
const readiness = await ensureBootstrapReady(context, input, 'brainlink_search');
|
|
@@ -666,14 +715,16 @@ export const syncTool = async (input) => {
|
|
|
666
715
|
return jsonResult(response);
|
|
667
716
|
}
|
|
668
717
|
const mode = sanitizeSearchMode(input.mode, context.defaults.defaultSearchMode);
|
|
718
|
+
const strategy = sanitizeContextStrategy(input.strategy, context.defaults.defaultContextStrategy);
|
|
669
719
|
const contextLimit = input.contextLimit ?? context.defaults.defaultSearchLimit;
|
|
670
720
|
const contextTokens = input.contextTokens ?? context.defaults.defaultContextTokens;
|
|
671
|
-
const contextPackage = await buildContextPackage(context.vault, input.contextQuery, contextLimit, contextTokens, context.agent, mode);
|
|
721
|
+
const contextPackage = await buildContextPackage(context.vault, input.contextQuery, contextLimit, contextTokens, context.agent, mode, strategy);
|
|
672
722
|
const contextSession = await touchContextSession(context.vault, context.agent);
|
|
673
723
|
return jsonResult({
|
|
674
724
|
...response,
|
|
675
725
|
context: {
|
|
676
726
|
mode,
|
|
727
|
+
strategy,
|
|
677
728
|
contextSession,
|
|
678
729
|
...contextPackage
|
|
679
730
|
}
|
|
@@ -685,10 +736,11 @@ export const bootstrapTool = async (input) => {
|
|
|
685
736
|
const stats = await getStats(context.vault, context.agent);
|
|
686
737
|
const validation = await validateVault(context.vault, context.agent);
|
|
687
738
|
const mode = sanitizeSearchMode(input.mode, context.defaults.defaultSearchMode);
|
|
739
|
+
const strategy = sanitizeContextStrategy(input.strategy, context.defaults.defaultContextStrategy);
|
|
688
740
|
const limit = input.limit ?? context.defaults.defaultSearchLimit;
|
|
689
741
|
const tokens = input.tokens ?? context.defaults.defaultContextTokens;
|
|
690
742
|
const contextPackage = input.query
|
|
691
|
-
? await buildContextPackage(context.vault, input.query, limit, tokens, context.agent, mode)
|
|
743
|
+
? await buildContextPackage(context.vault, input.query, limit, tokens, context.agent, mode, strategy)
|
|
692
744
|
: undefined;
|
|
693
745
|
const contextSession = input.query ? await touchContextSession(context.vault, context.agent) : undefined;
|
|
694
746
|
const guidance = stats.documentCount === 0
|
|
@@ -742,6 +794,7 @@ export const bootstrapTool = async (input) => {
|
|
|
742
794
|
...(context.agent ? { agent: context.agent } : {}),
|
|
743
795
|
query: '<task>',
|
|
744
796
|
mode,
|
|
797
|
+
strategy,
|
|
745
798
|
limit,
|
|
746
799
|
tokens
|
|
747
800
|
}
|
|
@@ -751,6 +804,7 @@ export const bootstrapTool = async (input) => {
|
|
|
751
804
|
vault: context.vault,
|
|
752
805
|
agent: context.agent,
|
|
753
806
|
mode,
|
|
807
|
+
strategy,
|
|
754
808
|
limit,
|
|
755
809
|
tokens,
|
|
756
810
|
index,
|
|
@@ -806,7 +860,8 @@ export const policyTool = async (input) => {
|
|
|
806
860
|
args: {
|
|
807
861
|
vault: context.vault,
|
|
808
862
|
...(context.agent ? { agent: context.agent } : {}),
|
|
809
|
-
mode: context.defaults.defaultSearchMode
|
|
863
|
+
mode: context.defaults.defaultSearchMode,
|
|
864
|
+
strategy: context.defaults.defaultContextStrategy
|
|
810
865
|
}
|
|
811
866
|
}
|
|
812
867
|
];
|
|
@@ -821,6 +876,7 @@ export const policyTool = async (input) => {
|
|
|
821
876
|
...(context.agent ? { agent: context.agent } : {}),
|
|
822
877
|
query: '<task>',
|
|
823
878
|
mode: context.defaults.defaultSearchMode,
|
|
879
|
+
strategy: context.defaults.defaultContextStrategy,
|
|
824
880
|
limit: context.defaults.defaultSearchLimit,
|
|
825
881
|
tokens: context.defaults.defaultContextTokens
|
|
826
882
|
}
|
|
@@ -852,6 +908,7 @@ export const recommendationsTool = async (input) => {
|
|
|
852
908
|
const contextStatus = await getContextSessionStatus(context.vault, context.agent);
|
|
853
909
|
const stats = await getStats(context.vault, context.agent);
|
|
854
910
|
const mode = sanitizeSearchMode(input.mode, context.defaults.defaultSearchMode);
|
|
911
|
+
const strategy = sanitizeContextStrategy(input.strategy, context.defaults.defaultContextStrategy);
|
|
855
912
|
const limit = input.limit ?? context.defaults.defaultSearchLimit;
|
|
856
913
|
const tokens = input.tokens ?? context.defaults.defaultContextTokens;
|
|
857
914
|
const query = input.query?.trim();
|
|
@@ -876,6 +933,7 @@ export const recommendationsTool = async (input) => {
|
|
|
876
933
|
vault: context.vault,
|
|
877
934
|
...(context.agent ? { agent: context.agent } : {}),
|
|
878
935
|
mode,
|
|
936
|
+
strategy,
|
|
879
937
|
...(query ? { query } : {})
|
|
880
938
|
}
|
|
881
939
|
}
|
|
@@ -891,6 +949,7 @@ export const recommendationsTool = async (input) => {
|
|
|
891
949
|
...(context.agent ? { agent: context.agent } : {}),
|
|
892
950
|
query: query ?? '<task>',
|
|
893
951
|
mode,
|
|
952
|
+
strategy,
|
|
894
953
|
limit,
|
|
895
954
|
tokens
|
|
896
955
|
}
|
|
@@ -926,6 +985,7 @@ export const recommendationsTool = async (input) => {
|
|
|
926
985
|
...(context.agent ? { agent: context.agent } : {}),
|
|
927
986
|
query: query ?? '<task>',
|
|
928
987
|
mode,
|
|
988
|
+
strategy,
|
|
929
989
|
limit,
|
|
930
990
|
tokens
|
|
931
991
|
}
|
|
@@ -957,9 +1017,24 @@ export const recommendationsTool = async (input) => {
|
|
|
957
1017
|
agent: context.agent,
|
|
958
1018
|
defaults: {
|
|
959
1019
|
mode,
|
|
1020
|
+
strategy,
|
|
960
1021
|
limit,
|
|
961
1022
|
tokens
|
|
962
1023
|
},
|
|
1024
|
+
contextStrategies: [
|
|
1025
|
+
{
|
|
1026
|
+
strategy: 'rag',
|
|
1027
|
+
useWhen: 'Use for fresh retrieval and context assembly from the current index.'
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
strategy: 'cag',
|
|
1031
|
+
useWhen: 'Use for repeated or stable task context so Brainlink can reuse a fresh persisted context pack.'
|
|
1032
|
+
},
|
|
1033
|
+
{
|
|
1034
|
+
strategy: 'auto',
|
|
1035
|
+
useWhen: 'Use when the agent wants Brainlink to choose CAG on fresh pack hits and RAG otherwise.'
|
|
1036
|
+
}
|
|
1037
|
+
],
|
|
963
1038
|
policy,
|
|
964
1039
|
bootstrapStatus,
|
|
965
1040
|
contextStatus,
|
package/docs/AGENT_USAGE.md
CHANGED
|
@@ -51,7 +51,7 @@ Set `BRAINLINK_HOME` when the whole Brainlink home directory should live somewhe
|
|
|
51
51
|
Use `blink config where` and `blink config doctor` to inspect active paths and effective source.
|
|
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
|
-
You can set `agentProfiles` to define per-agent defaults for `defaultSearchMode`, `defaultSearchLimit` and `
|
|
54
|
+
You can set `agentProfiles` to define per-agent defaults for `defaultSearchMode`, `defaultSearchLimit`, `defaultContextTokens` and `defaultContextStrategy`.
|
|
55
55
|
You can tune search-pack compression with `searchPack.rowChunkSize`, `searchPack.compressionLevel` and `searchPack.useDictionary`.
|
|
56
56
|
Guardrails for benchmark acceptance are configured with `searchPack.guardrailMinSavingsPercent` and `searchPack.guardrailMaxLatencyRegressionPercent`.
|
|
57
57
|
|
|
@@ -542,9 +542,14 @@ blink context "how does authentication work?" --vault ./vault --limit 12 --token
|
|
|
542
542
|
blink context "how does authentication work?" --vault ./vault --json
|
|
543
543
|
blink context "how does authentication work?" --vault ./vault --agent coding-agent --json
|
|
544
544
|
blink context "how does authentication work?" --vault ./vault --agent coding-agent --mode hybrid --json
|
|
545
|
+
blink context "how does authentication work?" --vault ./vault --agent coding-agent --strategy cag --json
|
|
546
|
+
blink context "how does authentication work?" --vault ./vault --agent coding-agent --strategy auto --json
|
|
547
|
+
blink context-packs --vault ./vault --json
|
|
548
|
+
blink context-packs --vault ./vault --stale --clear
|
|
545
549
|
```
|
|
546
550
|
|
|
547
551
|
This returns a Markdown context package optimized for prompt injection.
|
|
552
|
+
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.
|
|
548
553
|
|
|
549
554
|
### Inspect Links
|
|
550
555
|
|
|
@@ -670,6 +675,7 @@ Available MCP tools:
|
|
|
670
675
|
- `brainlink_policy`
|
|
671
676
|
- `brainlink_recommendations`
|
|
672
677
|
- `brainlink_context`
|
|
678
|
+
- `brainlink_context_packs`
|
|
673
679
|
- `brainlink_search`
|
|
674
680
|
- `brainlink_dedupe`
|
|
675
681
|
- `brainlink_resolve_duplicate`
|
|
@@ -693,6 +699,7 @@ If `autoBootstrapOnRead` or `enforceContextFirst` are disabled through `brainlin
|
|
|
693
699
|
`brainlink_bootstrap`, `brainlink_policy` and preflight responses include structured `nextActions` so clients can continue tool flows automatically.
|
|
694
700
|
`brainlink_policy` also accepts policy presets (`fully-auto`, `strict`) so MCP clients can switch behavior in one call.
|
|
695
701
|
`brainlink_recommendations` returns the suggested execution order so an agent can follow Brainlink best practices automatically.
|
|
702
|
+
MCP context is plug-and-play: agents may omit `strategy` for the configured default, pass `strategy: "rag"` for explicit fresh retrieval assembly, pass `strategy: "cag"` to reuse persisted context packs when the task context is stable or repeated, or pass `strategy: "auto"` to use CAG on fresh pack hits and RAG otherwise. `brainlink_recommendations`, policy next actions and preflight responses return executable context arguments, so clients can continue without custom parsing. `brainlink_context_packs` lists or clears persisted CAG packs.
|
|
696
703
|
|
|
697
704
|
MCP clients can pass `vault` and `agent` arguments per tool call. Set `BRAINLINK_ALLOWED_VAULTS` when exposing Brainlink to an external agent process so a tool cannot pass arbitrary vault paths:
|
|
698
705
|
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -136,6 +136,8 @@ read markdown files
|
|
|
136
136
|
|
|
137
137
|
```txt
|
|
138
138
|
question
|
|
139
|
+
-> selected strategy: rag | cag | auto
|
|
140
|
+
-> if cag/auto and fresh context pack exists, return cached Markdown package
|
|
139
141
|
-> selected mode: fts | semantic | hybrid
|
|
140
142
|
-> optional query embedding
|
|
141
143
|
-> optional compressed pack prefilter (token bloom)
|
|
@@ -145,8 +147,12 @@ question
|
|
|
145
147
|
-> ranked chunks with textScore and semanticScore
|
|
146
148
|
-> token-budget selection
|
|
147
149
|
-> Markdown context package
|
|
150
|
+
-> if cag/auto, persist derived context pack with current data signature
|
|
151
|
+
-> return cache, strategy and timing metrics
|
|
148
152
|
```
|
|
149
153
|
|
|
154
|
+
Context packs are stored under `.brainlink/context-packs/*.json`. They are derived artifacts keyed by query, agent, mode, limit and token budget, and are invalidated by the combined index and volatile-memory signature. Markdown remains the source of truth. The `auto` strategy uses CAG on fresh pack hits and falls back to RAG assembly otherwise, refreshing a pack for later calls.
|
|
155
|
+
|
|
150
156
|
## Graph Server Flow
|
|
151
157
|
|
|
152
158
|
```txt
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -50,7 +50,8 @@ 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": 2400,
|
|
54
|
+
"defaultContextStrategy": "auto"
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
}
|
package/package.json
CHANGED