@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.
Files changed (52) hide show
  1. package/AGENTS.md +142 -0
  2. package/CHANGELOG.md +13 -0
  3. package/CONTRIBUTING.md +28 -0
  4. package/LICENSE +23 -0
  5. package/README.md +715 -0
  6. package/SECURITY.md +35 -0
  7. package/dist/application/add-note.js +30 -0
  8. package/dist/application/analyze-vault.js +28 -0
  9. package/dist/application/build-context.js +15 -0
  10. package/dist/application/frontend/client-css.js +294 -0
  11. package/dist/application/frontend/client-html.js +66 -0
  12. package/dist/application/frontend/client-js.js +416 -0
  13. package/dist/application/get-graph-layout.js +3 -0
  14. package/dist/application/get-graph.js +12 -0
  15. package/dist/application/index-vault.js +67 -0
  16. package/dist/application/list-agents.js +12 -0
  17. package/dist/application/list-links.js +22 -0
  18. package/dist/application/search-knowledge.js +19 -0
  19. package/dist/application/server/host-security.js +6 -0
  20. package/dist/application/server/http.js +13 -0
  21. package/dist/application/server/routes.js +88 -0
  22. package/dist/application/server/types.js +1 -0
  23. package/dist/application/start-server.js +54 -0
  24. package/dist/application/watch-vault.js +36 -0
  25. package/dist/benchmarks/large-vault.js +88 -0
  26. package/dist/cli/commands/read-commands.js +149 -0
  27. package/dist/cli/commands/write-commands.js +107 -0
  28. package/dist/cli/main.js +21 -0
  29. package/dist/cli/runtime.js +18 -0
  30. package/dist/cli/types.js +1 -0
  31. package/dist/domain/agents.js +11 -0
  32. package/dist/domain/context.js +44 -0
  33. package/dist/domain/embeddings.js +117 -0
  34. package/dist/domain/graph-analysis.js +48 -0
  35. package/dist/domain/graph-layout.js +187 -0
  36. package/dist/domain/ids.js +2 -0
  37. package/dist/domain/markdown.js +100 -0
  38. package/dist/domain/note-safety.js +54 -0
  39. package/dist/domain/tokens.js +1 -0
  40. package/dist/domain/types.js +1 -0
  41. package/dist/infrastructure/config.js +60 -0
  42. package/dist/infrastructure/file-system-vault.js +62 -0
  43. package/dist/infrastructure/sqlite/document-writer.js +50 -0
  44. package/dist/infrastructure/sqlite/graph-reader.js +108 -0
  45. package/dist/infrastructure/sqlite/schema.js +87 -0
  46. package/dist/infrastructure/sqlite/search-reader.js +156 -0
  47. package/dist/infrastructure/sqlite/types.js +1 -0
  48. package/dist/infrastructure/sqlite-index.js +20 -0
  49. package/docs/AGENT_USAGE.md +477 -0
  50. package/docs/ARCHITECTURE.md +286 -0
  51. package/docs/RELEASE.md +67 -0
  52. 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`
@@ -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
+ }