@andespindola/brainlink 0.1.0-beta.0 → 0.1.0-beta.2
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 +114 -14
- package/dist/cli/commands/write-commands.js +18 -3
- package/dist/infrastructure/config.js +2 -0
- package/dist/mcp/server.js +6 -1
- package/dist/mcp/tools.js +48 -4
- package/docs/AGENT_USAGE.md +11 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -191,7 +191,9 @@ blink add "Testing Policy" \
|
|
|
191
191
|
--content "Run npm run check before final delivery. Related: [[Release Checklist]]. #testing #process"
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
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 in the knowledge graph, the agent must write Markdown that contains an explicit `[[Note Title]]` wiki link
|
|
194
|
+
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 in the knowledge graph, the agent must write Markdown that contains an explicit `[[Note Title]]` wiki link.
|
|
195
|
+
|
|
196
|
+
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`.
|
|
195
197
|
|
|
196
198
|
When adding memory, follow this contract:
|
|
197
199
|
|
|
@@ -200,11 +202,7 @@ When adding memory, follow this contract:
|
|
|
200
202
|
- Add retrieval tags such as `#architecture`, `#decision`, `#runbook` or `#preference`.
|
|
201
203
|
- Do not leave isolated notes unless they are intentionally root concepts.
|
|
202
204
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
```bash
|
|
206
|
-
blink index
|
|
207
|
-
```
|
|
205
|
+
If you disable auto-index, run `blink index` after batched writes.
|
|
208
206
|
|
|
209
207
|
### 6. Validate Memory Health
|
|
210
208
|
|
|
@@ -223,7 +221,7 @@ Use this loop during real work:
|
|
|
223
221
|
3. Use returned sources as project memory.
|
|
224
222
|
4. Perform the task.
|
|
225
223
|
5. Save only durable learnings with `blink add`, including `[[wiki links]]` to related notes.
|
|
226
|
-
6. Run `blink index
|
|
224
|
+
6. Run `blink index` only when auto-index was disabled during a batch.
|
|
227
225
|
7. Validate with `blink validate`, `blink broken-links` and `blink orphans` when graph links matter.
|
|
228
226
|
|
|
229
227
|
Do not store secrets, credentials, private keys, access tokens or transient chat noise.
|
|
@@ -241,8 +239,6 @@ blink add "Auth Decision" \
|
|
|
241
239
|
--vault ./vault \
|
|
242
240
|
--content "We chose JWT for API clients. [[Architecture]] #auth #jwt"
|
|
243
241
|
|
|
244
|
-
blink index --vault ./vault
|
|
245
|
-
|
|
246
242
|
blink search "jwt auth" --vault ./vault
|
|
247
243
|
|
|
248
244
|
blink context "how does auth work?" --vault ./vault
|
|
@@ -384,18 +380,114 @@ Example MCP client configuration:
|
|
|
384
380
|
}
|
|
385
381
|
```
|
|
386
382
|
|
|
383
|
+
For a locked-down setup, allowlist the vaults that MCP clients may access:
|
|
384
|
+
|
|
385
|
+
```json
|
|
386
|
+
{
|
|
387
|
+
"mcpServers": {
|
|
388
|
+
"brainlink": {
|
|
389
|
+
"command": "brainlink-mcp",
|
|
390
|
+
"env": {
|
|
391
|
+
"BRAINLINK_ALLOWED_VAULTS": "/absolute/path/to/project-vault,/absolute/path/to/team-vault"
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Install In MCP Client Stores
|
|
399
|
+
|
|
400
|
+
Brainlink can be exposed to MCP-compatible client stores in two ways:
|
|
401
|
+
|
|
402
|
+
1. Register the stdio server directly when the client accepts `mcpServers` configuration.
|
|
403
|
+
2. Register the local plugin from this repository when the client supports a plugin gallery or local marketplace.
|
|
404
|
+
|
|
405
|
+
Direct MCP server setup:
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
npm install -g @andespindola/brainlink@latest
|
|
409
|
+
command -v brainlink-mcp
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Use this server configuration in any MCP-compatible client that reads a JSON MCP manifest:
|
|
413
|
+
|
|
414
|
+
```json
|
|
415
|
+
{
|
|
416
|
+
"mcpServers": {
|
|
417
|
+
"brainlink": {
|
|
418
|
+
"command": "brainlink-mcp"
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Local plugin gallery setup:
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
npm install -g @andespindola/brainlink@latest
|
|
428
|
+
git clone https://github.com/andersonflima/brainlink.git "$HOME/brainlink"
|
|
429
|
+
mkdir -p "$HOME/plugins"
|
|
430
|
+
ln -s "$HOME/brainlink/plugins/brainlink" "$HOME/plugins/brainlink"
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Then register the plugin in the local marketplace file used by compatible clients:
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
node <<'NODE'
|
|
437
|
+
const fs = require('node:fs')
|
|
438
|
+
const os = require('node:os')
|
|
439
|
+
const path = require('node:path')
|
|
440
|
+
|
|
441
|
+
const marketplacePath = path.join(os.homedir(), '.agents', 'plugins', 'marketplace.json')
|
|
442
|
+
const pluginEntry = {
|
|
443
|
+
name: 'brainlink',
|
|
444
|
+
source: {
|
|
445
|
+
source: 'local',
|
|
446
|
+
path: './plugins/brainlink'
|
|
447
|
+
},
|
|
448
|
+
policy: {
|
|
449
|
+
installation: 'AVAILABLE',
|
|
450
|
+
authentication: 'ON_INSTALL'
|
|
451
|
+
},
|
|
452
|
+
category: 'Productivity'
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
fs.mkdirSync(path.dirname(marketplacePath), { recursive: true })
|
|
456
|
+
|
|
457
|
+
const marketplace = fs.existsSync(marketplacePath)
|
|
458
|
+
? JSON.parse(fs.readFileSync(marketplacePath, 'utf8'))
|
|
459
|
+
: {
|
|
460
|
+
name: 'local',
|
|
461
|
+
interface: {
|
|
462
|
+
displayName: 'Local'
|
|
463
|
+
},
|
|
464
|
+
plugins: []
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const plugins = Array.isArray(marketplace.plugins) ? marketplace.plugins : []
|
|
468
|
+
marketplace.plugins = [...plugins.filter((plugin) => plugin?.name !== 'brainlink'), pluginEntry]
|
|
469
|
+
|
|
470
|
+
fs.writeFileSync(marketplacePath, `${JSON.stringify(marketplace, null, 2)}\n`)
|
|
471
|
+
NODE
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
Restart the client after changing marketplace or MCP configuration so it reloads the Brainlink entry. The plugin starts `brainlink-mcp` and exposes the same tool set listed below.
|
|
475
|
+
|
|
387
476
|
Available tools:
|
|
388
477
|
|
|
389
478
|
- `brainlink_context`: read indexed context for a task or question.
|
|
390
479
|
- `brainlink_search`: search indexed notes.
|
|
391
480
|
- `brainlink_add_note`: write durable Markdown memory and reindex.
|
|
481
|
+
- `brainlink_add_file`: ingest a local file as a note and reindex.
|
|
392
482
|
- `brainlink_index`: rebuild the vault index.
|
|
483
|
+
- `brainlink_stats`: read indexed vault statistics.
|
|
393
484
|
- `brainlink_validate`: validate broken links and orphan notes.
|
|
485
|
+
- `brainlink_sync`: run index, stats, validation, broken-link and orphan checks in one call.
|
|
394
486
|
- `brainlink_graph`: read indexed graph nodes and weighted links.
|
|
395
487
|
- `brainlink_broken_links`: list unresolved wiki links.
|
|
396
488
|
- `brainlink_orphans`: list disconnected notes.
|
|
397
489
|
|
|
398
|
-
The same linking rule applies through MCP: `brainlink_context` is read-only, and real graph links require Markdown notes with explicit `[[wiki links]]`
|
|
490
|
+
The same linking rule applies through MCP: `brainlink_context` is read-only, and real graph links require Markdown notes with explicit `[[wiki links]]`. `brainlink_add_note` and `brainlink_add_file` reindex by default and include the index result when enabled.
|
|
399
491
|
|
|
400
492
|
Agents can raise the importance of a relationship by putting priority markers on the same line as a wiki link:
|
|
401
493
|
|
|
@@ -478,8 +570,12 @@ Initializes vault metadata. Without an argument, Brainlink initializes the defau
|
|
|
478
570
|
```bash
|
|
479
571
|
blink add "Note Title" --agent coding-agent --content "Markdown content"
|
|
480
572
|
blink add "Note Title" --vault ./vault --agent coding-agent --content "Markdown content"
|
|
573
|
+
blink add "Note Title" --vault ./vault --content-file ./notes.md
|
|
574
|
+
blink add "Note Title" --vault ./vault --content-file ./notes.md --no-auto-index
|
|
481
575
|
```
|
|
482
576
|
|
|
577
|
+
`--content` and `--content-file` are mutually exclusive. Add `--no-auto-index` when you want to defer reindexing.
|
|
578
|
+
|
|
483
579
|
Creates a Markdown note under `agents/<agent-id>/`. Common secret patterns are blocked by default; use `--allow-sensitive` only for an intentionally protected vault.
|
|
484
580
|
|
|
485
581
|
### `index`
|
|
@@ -638,15 +734,18 @@ Brainlink reads `brainlink.config.json` or `.brainlink.json` from the current wo
|
|
|
638
734
|
"port": 4321,
|
|
639
735
|
"allowedVaults": [".brainlink-vault"],
|
|
640
736
|
"defaultAgent": "shared",
|
|
737
|
+
"autoIndexOnWrite": true,
|
|
641
738
|
"defaultSearchLimit": 10,
|
|
642
739
|
"defaultContextTokens": 2000,
|
|
643
740
|
"embeddingProvider": "local",
|
|
644
741
|
"defaultSearchMode": "hybrid",
|
|
645
742
|
"chunkSize": 1200
|
|
646
743
|
}
|
|
744
|
+
```
|
|
647
745
|
|
|
648
746
|
`defaultAgent` is optional. When set, CLI and MCP calls that omit `--agent`/`agent` use this value automatically. If not set, behavior remains as before.
|
|
649
|
-
|
|
747
|
+
|
|
748
|
+
`autoIndexOnWrite` is optional and defaults to `true`. Set it to `false` to defer indexing after writes.
|
|
650
749
|
|
|
651
750
|
Use `"embeddingProvider": "none"` when you want FTS-only indexing.
|
|
652
751
|
|
|
@@ -759,17 +858,18 @@ Detailed notes:
|
|
|
759
858
|
- HTTP API is local and unauthenticated.
|
|
760
859
|
- Watch mode depends on the platform filesystem watcher.
|
|
761
860
|
|
|
762
|
-
##
|
|
861
|
+
## Beta Scope
|
|
763
862
|
|
|
764
|
-
`0.1.0-
|
|
863
|
+
`0.1.0-beta.0` is intended to stabilize the local-first memory loop:
|
|
765
864
|
|
|
766
865
|
- Markdown as durable memory.
|
|
767
866
|
- SQLite FTS plus local embeddings and semantic buckets as rebuildable retrieval index.
|
|
768
867
|
- CLI as the primary agent interface.
|
|
769
868
|
- HTTP graph API and frontend as inspection tools.
|
|
770
869
|
- Agent namespaces to avoid context mixing.
|
|
870
|
+
- MCP tools for context retrieval, durable memory writes and graph maintenance.
|
|
771
871
|
|
|
772
|
-
The
|
|
872
|
+
The beta includes local semantic retrieval. Remote embedding providers, remote auth, advanced deduplication and graph editing are future milestones.
|
|
773
873
|
|
|
774
874
|
## Security
|
|
775
875
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
1
2
|
import { addNote } from '../../application/add-note.js';
|
|
2
3
|
import { indexVault } from '../../application/index-vault.js';
|
|
3
4
|
import { startServer } from '../../application/start-server.js';
|
|
@@ -6,6 +7,15 @@ import { doctorVault } from '../../application/analyze-vault.js';
|
|
|
6
7
|
import { loadBrainlinkConfig } from '../../infrastructure/config.js';
|
|
7
8
|
import { assertVaultAllowed, ensureVault } from '../../infrastructure/file-system-vault.js';
|
|
8
9
|
import { parsePositiveInteger, print, resolveOptions } from '../runtime.js';
|
|
10
|
+
const resolveAddContent = (options) => {
|
|
11
|
+
if (options.content != null && options.content.trim().length > 0) {
|
|
12
|
+
return options.content;
|
|
13
|
+
}
|
|
14
|
+
if (options.contentFile == null || options.contentFile.trim().length === 0) {
|
|
15
|
+
throw new Error('Use --content or --content-file to provide note content.');
|
|
16
|
+
}
|
|
17
|
+
return readFileSync(options.contentFile, 'utf8');
|
|
18
|
+
};
|
|
9
19
|
export const registerWriteCommands = (program) => {
|
|
10
20
|
program
|
|
11
21
|
.command('init')
|
|
@@ -20,18 +30,23 @@ export const registerWriteCommands = (program) => {
|
|
|
20
30
|
program
|
|
21
31
|
.command('add')
|
|
22
32
|
.argument('<title>', 'note title')
|
|
23
|
-
.
|
|
33
|
+
.option('-c, --content <content>', 'markdown content')
|
|
34
|
+
.option('-f, --content-file <contentFile>', 'read markdown content from a file')
|
|
24
35
|
.option('-v, --vault <vault>', 'vault directory')
|
|
25
36
|
.option('-a, --agent <agent>', 'agent memory namespace')
|
|
26
37
|
.option('--allow-sensitive', 'allow writing content that looks like a secret')
|
|
38
|
+
.option('--no-auto-index', 'skip reindexing after add')
|
|
27
39
|
.option('--json', 'print machine-readable JSON')
|
|
28
40
|
.description('add a markdown note to the vault')
|
|
29
41
|
.action(async (title, options) => {
|
|
30
42
|
const resolved = await resolveOptions(options);
|
|
31
|
-
const
|
|
43
|
+
const content = resolveAddContent(options);
|
|
44
|
+
const notePath = await addNote(resolved.vault, title, content, resolved.agent, {
|
|
32
45
|
allowSensitive: Boolean(options.allowSensitive)
|
|
33
46
|
});
|
|
34
|
-
|
|
47
|
+
const shouldAutoIndex = options.autoIndex !== false && resolved.config.autoIndexOnWrite;
|
|
48
|
+
const index = shouldAutoIndex ? await indexVault(resolved.vault) : undefined;
|
|
49
|
+
print(options.json, { title, agent: resolved.agent ?? 'shared', path: notePath, ...(index ? { index } : {}) }, () => `Created note at ${notePath}`);
|
|
35
50
|
});
|
|
36
51
|
program
|
|
37
52
|
.command('index')
|
|
@@ -8,6 +8,7 @@ export const defaultBrainlinkConfig = {
|
|
|
8
8
|
port: 4321,
|
|
9
9
|
allowedVaults: [],
|
|
10
10
|
defaultAgent: undefined,
|
|
11
|
+
autoIndexOnWrite: true,
|
|
11
12
|
defaultSearchLimit: 10,
|
|
12
13
|
defaultContextTokens: 2000,
|
|
13
14
|
embeddingProvider: 'local',
|
|
@@ -45,6 +46,7 @@ const sanitizeConfig = (value) => ({
|
|
|
45
46
|
defaultAgent: typeof value.defaultAgent === 'string' && value.defaultAgent.trim().length > 0
|
|
46
47
|
? sanitizeAgentId(value.defaultAgent)
|
|
47
48
|
: defaultBrainlinkConfig.defaultAgent,
|
|
49
|
+
autoIndexOnWrite: typeof value.autoIndexOnWrite === 'boolean' ? value.autoIndexOnWrite : defaultBrainlinkConfig.autoIndexOnWrite,
|
|
48
50
|
defaultSearchLimit: typeof value.defaultSearchLimit === 'number' && value.defaultSearchLimit > 0
|
|
49
51
|
? value.defaultSearchLimit
|
|
50
52
|
: defaultBrainlinkConfig.defaultSearchLimit,
|
package/dist/mcp/server.js
CHANGED
|
@@ -2,7 +2,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { addNoteInputSchema, addNoteTool, brokenLinksInputSchema, brokenLinksTool, contextInputSchema, contextTool, graphInputSchema, graphTool, indexInputSchema, indexTool, orphansInputSchema, orphansTool, searchInputSchema, searchTool, statsInputSchema, statsTool, syncInputSchema, syncTool, validateInputSchema, validateTool } from './tools.js';
|
|
5
|
+
import { addNoteInputSchema, addFileInputSchema, addFileTool, addNoteTool, brokenLinksInputSchema, brokenLinksTool, contextInputSchema, contextTool, graphInputSchema, graphTool, indexInputSchema, indexTool, orphansInputSchema, orphansTool, searchInputSchema, searchTool, statsInputSchema, statsTool, syncInputSchema, syncTool, validateInputSchema, validateTool } from './tools.js';
|
|
6
6
|
const readPackageVersion = () => {
|
|
7
7
|
const packagePath = join(dirname(fileURLToPath(import.meta.url)), '../../package.json');
|
|
8
8
|
const metadata = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
@@ -30,6 +30,11 @@ export const createBrainlinkMcpServer = () => {
|
|
|
30
30
|
description: 'Write durable Markdown memory, then reindex the vault. Include explicit [[wiki links]] for connected graph memory. Add priority markers near links, such as priority: high, #important or #critical, when a relationship should be weighted higher.',
|
|
31
31
|
inputSchema: addNoteInputSchema
|
|
32
32
|
}, addNoteTool);
|
|
33
|
+
server.registerTool('brainlink_add_file', {
|
|
34
|
+
title: 'Ingest Markdown File',
|
|
35
|
+
description: 'Read a local markdown/text file and ingest it as a Brainlink note. Reindex defaults to true.',
|
|
36
|
+
inputSchema: addFileInputSchema
|
|
37
|
+
}, addFileTool);
|
|
33
38
|
server.registerTool('brainlink_index', {
|
|
34
39
|
title: 'Index Brainlink Vault',
|
|
35
40
|
description: 'Rebuild the local Brainlink index from Markdown notes.',
|
package/dist/mcp/tools.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { basename, extname } from 'node:path';
|
|
1
3
|
import { z } from 'zod';
|
|
2
4
|
import { getBrokenLinksReport, getOrphansReport, getStats, validateVault } from '../application/analyze-vault.js';
|
|
3
5
|
import { addNote } from '../application/add-note.js';
|
|
@@ -32,11 +34,21 @@ const resolveExecutionContext = async (input) => {
|
|
|
32
34
|
const vault = await assertVaultAllowed(input.vault ?? config.vault, config.allowedVaults);
|
|
33
35
|
const agent = input.agent ?? config.defaultAgent;
|
|
34
36
|
return {
|
|
35
|
-
vault,
|
|
36
37
|
config,
|
|
38
|
+
vault,
|
|
37
39
|
agent
|
|
38
40
|
};
|
|
39
41
|
};
|
|
42
|
+
const inferTitleFromPath = (filePath) => {
|
|
43
|
+
const extension = extname(filePath);
|
|
44
|
+
const fromFileName = basename(filePath, extension);
|
|
45
|
+
return fromFileName
|
|
46
|
+
.trim()
|
|
47
|
+
.replace(/[-_]+/g, ' ')
|
|
48
|
+
.replace(/\s+/g, ' ')
|
|
49
|
+
.trim();
|
|
50
|
+
};
|
|
51
|
+
const isTruthy = (value) => value !== false;
|
|
40
52
|
const jsonResult = (value) => ({
|
|
41
53
|
content: [
|
|
42
54
|
{
|
|
@@ -68,7 +80,16 @@ export const addNoteInputSchema = {
|
|
|
68
80
|
.string()
|
|
69
81
|
.min(1)
|
|
70
82
|
.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.'),
|
|
71
|
-
|
|
83
|
+
...agentInput,
|
|
84
|
+
allowSensitive: z.boolean().optional().default(false).describe('Allow content that looks like a secret.'),
|
|
85
|
+
autoIndex: z.boolean().optional().default(true).describe('Reindex vault after writing note.')
|
|
86
|
+
};
|
|
87
|
+
export const addFileInputSchema = {
|
|
88
|
+
...vaultInput,
|
|
89
|
+
...agentInput,
|
|
90
|
+
title: z.string().min(1).optional().describe('Optional note title override. If omitted, uses file name.'),
|
|
91
|
+
filePath: z.string().min(1).describe('Filesystem path to markdown or text file to ingest.'),
|
|
92
|
+
autoIndex: z.boolean().optional().default(true).describe('Reindex vault after ingesting file.'),
|
|
72
93
|
allowSensitive: z.boolean().optional().default(false).describe('Allow content that looks like a secret.')
|
|
73
94
|
};
|
|
74
95
|
export const indexInputSchema = {
|
|
@@ -128,16 +149,39 @@ export const searchTool = async (input) => {
|
|
|
128
149
|
};
|
|
129
150
|
export const addNoteTool = async (input) => {
|
|
130
151
|
const context = await resolveExecutionContext(input);
|
|
152
|
+
const shouldIndex = isTruthy(input.autoIndex);
|
|
131
153
|
const path = await addNote(context.vault, input.title, input.content, context.agent, {
|
|
132
154
|
allowSensitive: input.allowSensitive
|
|
133
155
|
});
|
|
134
|
-
const index = await indexVault(context.vault);
|
|
156
|
+
const index = shouldIndex ? await indexVault(context.vault) : undefined;
|
|
135
157
|
return jsonResult({
|
|
136
158
|
vault: context.vault,
|
|
137
159
|
title: input.title,
|
|
138
160
|
agent: context.agent,
|
|
139
161
|
path,
|
|
140
|
-
index
|
|
162
|
+
...(index ? { index } : {})
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
export const addFileTool = async (input) => {
|
|
166
|
+
const context = await resolveExecutionContext(input);
|
|
167
|
+
const content = await readFile(input.filePath, 'utf8');
|
|
168
|
+
const inferredTitle = inferTitleFromPath(input.filePath);
|
|
169
|
+
const title = input.title ?? inferredTitle;
|
|
170
|
+
if (title == null || title.length === 0) {
|
|
171
|
+
throw new Error('Cannot infer note title from file path. Provide a title explicitly.');
|
|
172
|
+
}
|
|
173
|
+
const shouldIndex = isTruthy(input.autoIndex);
|
|
174
|
+
const path = await addNote(context.vault, title, content, context.agent, {
|
|
175
|
+
allowSensitive: input.allowSensitive
|
|
176
|
+
});
|
|
177
|
+
const index = shouldIndex ? await indexVault(context.vault) : undefined;
|
|
178
|
+
return jsonResult({
|
|
179
|
+
vault: context.vault,
|
|
180
|
+
title,
|
|
181
|
+
agent: context.agent,
|
|
182
|
+
filePath: input.filePath,
|
|
183
|
+
path,
|
|
184
|
+
...(index ? { index } : {})
|
|
141
185
|
});
|
|
142
186
|
};
|
|
143
187
|
export const indexTool = async (input) => {
|
package/docs/AGENT_USAGE.md
CHANGED
|
@@ -43,6 +43,8 @@ Use `--vault <path>` for a one-off custom vault, or set `vault` in `brainlink.co
|
|
|
43
43
|
|
|
44
44
|
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.
|
|
45
45
|
|
|
46
|
+
`autoIndexOnWrite` (default: `true`) controls whether `add` and MCP write tools index right after writing.
|
|
47
|
+
|
|
46
48
|
## Agent Namespaces
|
|
47
49
|
|
|
48
50
|
Each agent writes into a dedicated namespace under `agents/<agent-id>/`:
|
|
@@ -162,7 +164,7 @@ Required write behavior:
|
|
|
162
164
|
2. Look for an existing related concept with `search`, `links` or `backlinks`.
|
|
163
165
|
3. Add at least one `[[Existing Note Title]]` link unless the note is intentionally a root concept.
|
|
164
166
|
4. Add useful `#tags` for retrieval.
|
|
165
|
-
5.
|
|
167
|
+
5. `add` writes are indexed by default. Only batch with explicit `--no-auto-index`, then run `index` once.
|
|
166
168
|
6. Run `validate`, `broken-links` or `orphans` when the graph should be connected.
|
|
167
169
|
|
|
168
170
|
Good linked note:
|
|
@@ -171,7 +173,6 @@ Good linked note:
|
|
|
171
173
|
blink add "SQLite Index Rebuild" \
|
|
172
174
|
--agent coding-agent \
|
|
173
175
|
--content "Legacy derived indexes without agent columns are rebuilt because SQLite is disposable. Related: [[Architecture]], [[Agent Namespaces]]. #sqlite #architecture #decision"
|
|
174
|
-
blink index
|
|
175
176
|
blink validate --agent coding-agent
|
|
176
177
|
```
|
|
177
178
|
|
|
@@ -247,7 +248,7 @@ When using MCP, use this compact sequence for the same memory discipline:
|
|
|
247
248
|
1. Bootstrap context:
|
|
248
249
|
- `brainlink_context` with `agent`, `query`, `mode: hybrid`, `limit`.
|
|
249
250
|
2. Capture durable decisions:
|
|
250
|
-
- `brainlink_add_note` with explicit `[[wiki links]]` and `#tags`.
|
|
251
|
+
- `brainlink_add_note` or `brainlink_add_file` with explicit `[[wiki links]]` and `#tags`.
|
|
251
252
|
3. Run maintenance before handoff or before the next step:
|
|
252
253
|
- `brainlink_sync` with `agent`, `contextQuery`, `mode: hybrid`.
|
|
253
254
|
4. Diagnose graph issues only when needed:
|
|
@@ -346,8 +347,12 @@ $HOME/.brainlink/vault/
|
|
|
346
347
|
|
|
347
348
|
```bash
|
|
348
349
|
blink add "Note Title" --vault ./vault --content "Markdown content"
|
|
350
|
+
blink add "Note Title" --vault ./vault --content-file ./notes.md
|
|
351
|
+
blink add "Note Title" --vault ./vault --content-file ./notes.md --no-auto-index
|
|
349
352
|
```
|
|
350
353
|
|
|
354
|
+
`--content` and `--content-file` are mutually exclusive. Use `--no-auto-index` if you want to defer indexing in batch operations.
|
|
355
|
+
|
|
351
356
|
This creates a slugged Markdown file with frontmatter and a heading.
|
|
352
357
|
|
|
353
358
|
The CLI blocks common secret patterns by default. Do not use `--allow-sensitive` unless the vault is intentionally protected.
|
|
@@ -516,8 +521,11 @@ Available MCP tools:
|
|
|
516
521
|
- `brainlink_context`
|
|
517
522
|
- `brainlink_search`
|
|
518
523
|
- `brainlink_add_note`
|
|
524
|
+
- `brainlink_add_file`
|
|
519
525
|
- `brainlink_index`
|
|
526
|
+
- `brainlink_stats`
|
|
520
527
|
- `brainlink_validate`
|
|
528
|
+
- `brainlink_sync`
|
|
521
529
|
- `brainlink_graph`
|
|
522
530
|
- `brainlink_broken_links`
|
|
523
531
|
- `brainlink_orphans`
|
package/package.json
CHANGED