@andespindola/brainlink 0.1.0-alpha.0
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/AGENTS.md +142 -0
- package/CHANGELOG.md +13 -0
- package/CONTRIBUTING.md +28 -0
- package/LICENSE +23 -0
- package/README.md +715 -0
- package/SECURITY.md +35 -0
- package/dist/application/add-note.js +30 -0
- package/dist/application/analyze-vault.js +28 -0
- package/dist/application/build-context.js +15 -0
- package/dist/application/frontend/client-css.js +294 -0
- package/dist/application/frontend/client-html.js +66 -0
- package/dist/application/frontend/client-js.js +416 -0
- package/dist/application/get-graph-layout.js +3 -0
- package/dist/application/get-graph.js +12 -0
- package/dist/application/index-vault.js +67 -0
- package/dist/application/list-agents.js +12 -0
- package/dist/application/list-links.js +22 -0
- package/dist/application/search-knowledge.js +19 -0
- package/dist/application/server/host-security.js +6 -0
- package/dist/application/server/http.js +13 -0
- package/dist/application/server/routes.js +88 -0
- package/dist/application/server/types.js +1 -0
- package/dist/application/start-server.js +54 -0
- package/dist/application/watch-vault.js +36 -0
- package/dist/benchmarks/large-vault.js +88 -0
- package/dist/cli/commands/read-commands.js +149 -0
- package/dist/cli/commands/write-commands.js +107 -0
- package/dist/cli/main.js +21 -0
- package/dist/cli/runtime.js +18 -0
- package/dist/cli/types.js +1 -0
- package/dist/domain/agents.js +11 -0
- package/dist/domain/context.js +44 -0
- package/dist/domain/embeddings.js +117 -0
- package/dist/domain/graph-analysis.js +48 -0
- package/dist/domain/graph-layout.js +187 -0
- package/dist/domain/ids.js +2 -0
- package/dist/domain/markdown.js +100 -0
- package/dist/domain/note-safety.js +54 -0
- package/dist/domain/tokens.js +1 -0
- package/dist/domain/types.js +1 -0
- package/dist/infrastructure/config.js +60 -0
- package/dist/infrastructure/file-system-vault.js +62 -0
- package/dist/infrastructure/sqlite/document-writer.js +50 -0
- package/dist/infrastructure/sqlite/graph-reader.js +108 -0
- package/dist/infrastructure/sqlite/schema.js +87 -0
- package/dist/infrastructure/sqlite/search-reader.js +156 -0
- package/dist/infrastructure/sqlite/types.js +1 -0
- package/dist/infrastructure/sqlite-index.js +20 -0
- package/docs/AGENT_USAGE.md +477 -0
- package/docs/ARCHITECTURE.md +286 -0
- package/docs/RELEASE.md +67 -0
- package/package.json +67 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Brainlink follows a small clean architecture boundary.
|
|
4
|
+
|
|
5
|
+
```txt
|
|
6
|
+
CLI -> application use cases -> domain functions -> infrastructure adapters
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The core rule is simple:
|
|
10
|
+
|
|
11
|
+
Domain code must not know about the CLI, filesystem, or SQLite.
|
|
12
|
+
|
|
13
|
+
## Modules
|
|
14
|
+
|
|
15
|
+
```txt
|
|
16
|
+
src/
|
|
17
|
+
application/
|
|
18
|
+
frontend/
|
|
19
|
+
client-css.ts
|
|
20
|
+
client-html.ts
|
|
21
|
+
client-js.ts
|
|
22
|
+
server/
|
|
23
|
+
routes.ts
|
|
24
|
+
http.ts
|
|
25
|
+
add-note.ts
|
|
26
|
+
build-context.ts
|
|
27
|
+
get-graph.ts
|
|
28
|
+
index-vault.ts
|
|
29
|
+
list-agents.ts
|
|
30
|
+
list-links.ts
|
|
31
|
+
search-knowledge.ts
|
|
32
|
+
start-server.ts
|
|
33
|
+
watch-vault.ts
|
|
34
|
+
|
|
35
|
+
cli/
|
|
36
|
+
commands/
|
|
37
|
+
read-commands.ts
|
|
38
|
+
write-commands.ts
|
|
39
|
+
main.ts
|
|
40
|
+
runtime.ts
|
|
41
|
+
|
|
42
|
+
domain/
|
|
43
|
+
agents.ts
|
|
44
|
+
context.ts
|
|
45
|
+
graph-analysis.ts
|
|
46
|
+
graph-layout.ts
|
|
47
|
+
embeddings.ts
|
|
48
|
+
ids.ts
|
|
49
|
+
markdown.ts
|
|
50
|
+
tokens.ts
|
|
51
|
+
types.ts
|
|
52
|
+
|
|
53
|
+
infrastructure/
|
|
54
|
+
sqlite/
|
|
55
|
+
document-writer.ts
|
|
56
|
+
graph-reader.ts
|
|
57
|
+
schema.ts
|
|
58
|
+
search-reader.ts
|
|
59
|
+
file-system-vault.ts
|
|
60
|
+
sqlite-index.ts
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Domain
|
|
64
|
+
|
|
65
|
+
The domain layer contains pure knowledge rules:
|
|
66
|
+
|
|
67
|
+
- parse Markdown documents
|
|
68
|
+
- resolve agent namespaces from frontmatter or `agents/<agent-id>/...`
|
|
69
|
+
- extract frontmatter
|
|
70
|
+
- extract note titles
|
|
71
|
+
- extract `[[wiki links]]`
|
|
72
|
+
- extract `#tags`
|
|
73
|
+
- split documents into chunks
|
|
74
|
+
- create deterministic local embeddings
|
|
75
|
+
- create deterministic embedding buckets for semantic candidate retrieval
|
|
76
|
+
- calculate cosine similarity
|
|
77
|
+
- estimate token counts
|
|
78
|
+
- select context sections
|
|
79
|
+
- format context packages
|
|
80
|
+
|
|
81
|
+
Important files:
|
|
82
|
+
|
|
83
|
+
- `src/domain/markdown.ts`
|
|
84
|
+
- `src/domain/context.ts`
|
|
85
|
+
- `src/domain/embeddings.ts`
|
|
86
|
+
- `src/domain/types.ts`
|
|
87
|
+
|
|
88
|
+
## Application
|
|
89
|
+
|
|
90
|
+
The application layer coordinates use cases:
|
|
91
|
+
|
|
92
|
+
- add a note
|
|
93
|
+
- index a vault
|
|
94
|
+
- search knowledge
|
|
95
|
+
- build context
|
|
96
|
+
- list links
|
|
97
|
+
- list backlinks
|
|
98
|
+
- start HTTP graph/API server
|
|
99
|
+
- watch vault changes
|
|
100
|
+
|
|
101
|
+
Application code depends on domain rules and infrastructure interfaces.
|
|
102
|
+
|
|
103
|
+
## Infrastructure
|
|
104
|
+
|
|
105
|
+
The infrastructure layer handles side effects:
|
|
106
|
+
|
|
107
|
+
- reading Markdown files from disk
|
|
108
|
+
- writing Markdown notes
|
|
109
|
+
- creating `.brainlink`
|
|
110
|
+
- writing and querying SQLite
|
|
111
|
+
- running FTS, semantic and hybrid retrieval
|
|
112
|
+
- narrowing semantic candidates through SQLite embedding buckets before cosine scoring
|
|
113
|
+
|
|
114
|
+
SQLite is an index, not the canonical storage model.
|
|
115
|
+
|
|
116
|
+
## Indexing Flow
|
|
117
|
+
|
|
118
|
+
```txt
|
|
119
|
+
read markdown files
|
|
120
|
+
-> parse documents
|
|
121
|
+
-> build agent-scoped title maps
|
|
122
|
+
-> resolve links
|
|
123
|
+
-> split chunks
|
|
124
|
+
-> create chunk embeddings
|
|
125
|
+
-> reset SQLite index
|
|
126
|
+
-> persist documents, chunks and links
|
|
127
|
+
-> populate FTS records
|
|
128
|
+
-> persist embedding vectors
|
|
129
|
+
-> persist embedding buckets
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Retrieval Flow
|
|
133
|
+
|
|
134
|
+
```txt
|
|
135
|
+
question
|
|
136
|
+
-> selected mode: fts | semantic | hybrid
|
|
137
|
+
-> optional query embedding
|
|
138
|
+
-> FTS query and/or embedding bucket candidate lookup
|
|
139
|
+
-> cosine similarity over candidate chunks
|
|
140
|
+
-> ranked chunks with textScore and semanticScore
|
|
141
|
+
-> token-budget selection
|
|
142
|
+
-> Markdown context package
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Graph Server Flow
|
|
146
|
+
|
|
147
|
+
```txt
|
|
148
|
+
server command
|
|
149
|
+
-> optional index rebuild
|
|
150
|
+
-> HTTP server
|
|
151
|
+
-> /api/agents lists indexed namespaces
|
|
152
|
+
-> /api/graph reads indexed documents and links
|
|
153
|
+
-> browser renders graph canvas
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The graph UI is intentionally read-only. Markdown remains the write interface and SQLite remains a derived index.
|
|
157
|
+
|
|
158
|
+
## HTTP API Flow
|
|
159
|
+
|
|
160
|
+
```txt
|
|
161
|
+
HTTP request
|
|
162
|
+
-> route handler
|
|
163
|
+
-> application use case
|
|
164
|
+
-> filesystem and SQLite adapters
|
|
165
|
+
-> JSON response
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The HTTP API is local-first and unauthenticated. It is meant for local agents, browser UI, and development workflows.
|
|
169
|
+
|
|
170
|
+
## External MCP Flow
|
|
171
|
+
|
|
172
|
+
Brainlink does not contain an MCP server. MCP compatibility is achieved by an external MCP server wrapping the CLI.
|
|
173
|
+
|
|
174
|
+
```txt
|
|
175
|
+
MCP client
|
|
176
|
+
-> external MCP server
|
|
177
|
+
-> child_process execFile("blink", ["context", ..., "--json"])
|
|
178
|
+
-> Brainlink CLI
|
|
179
|
+
-> application use case
|
|
180
|
+
-> JSON stdout
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This keeps the package CLI-first and avoids coupling the core project to one MCP SDK.
|
|
184
|
+
|
|
185
|
+
## Link Resolution
|
|
186
|
+
|
|
187
|
+
Links are extracted from Markdown using wiki-link syntax:
|
|
188
|
+
|
|
189
|
+
```md
|
|
190
|
+
[[Architecture]]
|
|
191
|
+
[[Architecture#Runtime]]
|
|
192
|
+
[[Architecture|System design]]
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Resolution is title-based, case-insensitive and scoped by agent namespace.
|
|
196
|
+
|
|
197
|
+
When indexing a document, Brainlink resolves a link in this order:
|
|
198
|
+
|
|
199
|
+
1. matching title inside the same `agentId`
|
|
200
|
+
2. matching title inside `shared`
|
|
201
|
+
3. unresolved link
|
|
202
|
+
|
|
203
|
+
The current title resolution priority is:
|
|
204
|
+
|
|
205
|
+
1. `title` frontmatter
|
|
206
|
+
2. first Markdown `# Heading`
|
|
207
|
+
3. file name without `.md`
|
|
208
|
+
|
|
209
|
+
## Backlinks
|
|
210
|
+
|
|
211
|
+
Backlinks are not stored as separate Markdown files.
|
|
212
|
+
|
|
213
|
+
They are derived from indexed links:
|
|
214
|
+
|
|
215
|
+
```txt
|
|
216
|
+
source note -> target note
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The `backlinks` command queries indexed links pointing to a target title. With `--agent`, it only returns links from that namespace.
|
|
220
|
+
|
|
221
|
+
## Context Building
|
|
222
|
+
|
|
223
|
+
`context` uses search results and selects one chunk per document while staying inside an estimated token budget.
|
|
224
|
+
|
|
225
|
+
The output format is Markdown because it is easy for agents and models to consume:
|
|
226
|
+
|
|
227
|
+
```md
|
|
228
|
+
# Brainlink Context
|
|
229
|
+
Query: question
|
|
230
|
+
|
|
231
|
+
## 1. Note Title
|
|
232
|
+
Source: note.md
|
|
233
|
+
Tags: #tag
|
|
234
|
+
Score: 0.000
|
|
235
|
+
Mode: hybrid
|
|
236
|
+
|
|
237
|
+
Relevant content
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Persistence Model
|
|
241
|
+
|
|
242
|
+
Permanent:
|
|
243
|
+
|
|
244
|
+
- Markdown files
|
|
245
|
+
- optional Git history around the vault
|
|
246
|
+
|
|
247
|
+
Canonical agent memory lives under:
|
|
248
|
+
|
|
249
|
+
```txt
|
|
250
|
+
vault/agents/<agent-id>/**/*.md
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Rebuildable:
|
|
254
|
+
|
|
255
|
+
- `.brainlink/brainlink.db`
|
|
256
|
+
- FTS records
|
|
257
|
+
- local embedding vectors
|
|
258
|
+
- local embedding bucket index
|
|
259
|
+
- chunks
|
|
260
|
+
- resolved links
|
|
261
|
+
|
|
262
|
+
## Design Decisions
|
|
263
|
+
|
|
264
|
+
### Markdown As Source Of Truth
|
|
265
|
+
|
|
266
|
+
Markdown keeps the system portable, inspectable, Git-friendly, and compatible with Obsidian-like workflows.
|
|
267
|
+
|
|
268
|
+
### SQLite As Local Index
|
|
269
|
+
|
|
270
|
+
SQLite gives fast local search, local vector storage and rebuildable retrieval without forcing users to run external infrastructure.
|
|
271
|
+
|
|
272
|
+
### CLI First
|
|
273
|
+
|
|
274
|
+
The CLI is the smallest useful integration surface for agents. HTTP is a local inspection adapter, and MCP can be implemented outside this package by wrapping the CLI.
|
|
275
|
+
|
|
276
|
+
### Functional Core
|
|
277
|
+
|
|
278
|
+
Parsing, transformation, selection, and formatting are implemented as pure functions where practical. Side effects stay at the edges.
|
|
279
|
+
|
|
280
|
+
## Future Architecture
|
|
281
|
+
|
|
282
|
+
Useful next boundaries:
|
|
283
|
+
|
|
284
|
+
- remote embedding providers
|
|
285
|
+
- dedicated vector adapter
|
|
286
|
+
- `graph-exporter`
|
package/docs/RELEASE.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Release
|
|
2
|
+
|
|
3
|
+
Brainlink releases are built from the CLI package. Do not publish until the package name, npm account and version are confirmed.
|
|
4
|
+
|
|
5
|
+
## Alpha Release Checklist
|
|
6
|
+
|
|
7
|
+
1. Confirm `package.json` name, version, repository, license and bin entries.
|
|
8
|
+
2. Run `npm install` from a clean checkout when dependencies changed.
|
|
9
|
+
3. Run `npm run check`.
|
|
10
|
+
4. Run `npm run pack:smoke`.
|
|
11
|
+
5. Run a global install smoke from the generated tarball.
|
|
12
|
+
6. Verify both binaries:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
brainlink --help
|
|
16
|
+
blink --help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
7. Verify core CLI flow:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
blink init ./tmp-vault
|
|
23
|
+
blink add "Release Smoke" --vault ./tmp-vault --content "Release smoke note. #release"
|
|
24
|
+
blink index --vault ./tmp-vault --json
|
|
25
|
+
blink search "release smoke" --vault ./tmp-vault --mode hybrid --json
|
|
26
|
+
blink context "release smoke" --vault ./tmp-vault --mode hybrid --json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
8. Verify HTTP graph server starts:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
blink server --vault ./tmp-vault --host 127.0.0.1 --port 4321
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
9. Verify the server refuses accidental public binds:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
blink server --vault ./tmp-vault --host 0.0.0.0
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
10. Confirm no test/demo vault files are included in the package tarball.
|
|
42
|
+
11. Create the git tag only after the package name is final.
|
|
43
|
+
12. Publish only from a logged-in npm account with permission for the package name.
|
|
44
|
+
|
|
45
|
+
## Publish Commands
|
|
46
|
+
|
|
47
|
+
For scoped public packages:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm publish --access public
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For unscoped packages:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm publish
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Current Package Name Constraint
|
|
60
|
+
|
|
61
|
+
`brainlink` is already present on npm. `@brainlink` alone is not a valid npm package name because scoped packages must use `@scope/name`.
|
|
62
|
+
|
|
63
|
+
Valid alternatives:
|
|
64
|
+
|
|
65
|
+
- `@andespindola/brainlink`
|
|
66
|
+
- `@brainlink/cli`, if the publisher controls the `@brainlink` scope
|
|
67
|
+
- another unscoped name that is available on npm
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@andespindola/brainlink",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Anderson Espindola",
|
|
8
|
+
"homepage": "https://github.com/andersonflima/brainlink#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/andersonflima/brainlink.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/andersonflima/brainlink/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"agents",
|
|
19
|
+
"memory",
|
|
20
|
+
"markdown",
|
|
21
|
+
"obsidian",
|
|
22
|
+
"mcp",
|
|
23
|
+
"knowledge-graph",
|
|
24
|
+
"retrieval"
|
|
25
|
+
],
|
|
26
|
+
"bin": {
|
|
27
|
+
"brainlink": "dist/cli/main.js",
|
|
28
|
+
"blink": "dist/cli/main.js"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"CHANGELOG.md",
|
|
35
|
+
"CONTRIBUTING.md",
|
|
36
|
+
"SECURITY.md",
|
|
37
|
+
"AGENTS.md",
|
|
38
|
+
"docs"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
45
|
+
"build": "npm run clean && tsc -p tsconfig.json",
|
|
46
|
+
"dev": "tsx src/cli/main.ts",
|
|
47
|
+
"test": "vitest run --config vitest.config.ts",
|
|
48
|
+
"check": "npm run build && npm run test",
|
|
49
|
+
"benchmark:large": "tsx src/benchmarks/large-vault.ts",
|
|
50
|
+
"prepack": "npm run build",
|
|
51
|
+
"pack:smoke": "npm pack --dry-run"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"better-sqlite3": "^12.9.0",
|
|
55
|
+
"commander": "^14.0.2"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
59
|
+
"@types/node": "^24.9.2",
|
|
60
|
+
"tsx": "^4.21.0",
|
|
61
|
+
"typescript": "^5.9.3",
|
|
62
|
+
"vitest": "^4.0.6"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=22.5.0"
|
|
66
|
+
}
|
|
67
|
+
}
|