@andespindola/brainlink 0.1.0-beta.7 → 0.1.0-beta.71

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 (63) hide show
  1. package/AGENTS.md +8 -5
  2. package/CHANGELOG.md +58 -2
  3. package/CONTRIBUTING.md +2 -2
  4. package/COPYRIGHT.md +5 -0
  5. package/README.md +266 -20
  6. package/SECURITY.md +1 -1
  7. package/dist/application/add-note.js +62 -13
  8. package/dist/application/analyze-vault.js +95 -8
  9. package/dist/application/build-context.js +56 -1
  10. package/dist/application/dedupe-notes.js +226 -0
  11. package/dist/application/frontend/client-css.js +138 -103
  12. package/dist/application/frontend/client-html.js +47 -41
  13. package/dist/application/frontend/client-js.js +2120 -128
  14. package/dist/application/frontend/client-worker-js.js +66 -0
  15. package/dist/application/get-graph-layout.js +18 -6
  16. package/dist/application/get-graph-node.js +12 -0
  17. package/dist/application/get-graph-summary.js +12 -0
  18. package/dist/application/get-graph.js +3 -3
  19. package/dist/application/import-legacy-sqlite.js +296 -0
  20. package/dist/application/index-vault.js +252 -19
  21. package/dist/application/list-agents.js +3 -3
  22. package/dist/application/list-links.js +5 -5
  23. package/dist/application/migrate-vault.js +91 -0
  24. package/dist/application/offline-pack-backup.js +44 -0
  25. package/dist/application/search-graph-node-ids.js +12 -0
  26. package/dist/application/search-knowledge.js +75 -5
  27. package/dist/application/server/routes.js +102 -1
  28. package/dist/application/start-server.js +75 -4
  29. package/dist/application/watch-vault.js +23 -2
  30. package/dist/benchmarks/large-vault.js +1 -1
  31. package/dist/cli/commands/agent-commands.js +419 -0
  32. package/dist/cli/commands/config-commands.js +167 -0
  33. package/dist/cli/commands/read-commands.js +25 -8
  34. package/dist/cli/commands/write-commands.js +989 -10
  35. package/dist/cli/main.js +4 -0
  36. package/dist/cli/runtime.js +5 -2
  37. package/dist/domain/context.js +53 -11
  38. package/dist/domain/embeddings.js +2 -1
  39. package/dist/domain/graph-layout.js +62 -15
  40. package/dist/domain/markdown.js +36 -4
  41. package/dist/domain/middle-out.js +18 -0
  42. package/dist/infrastructure/config.js +132 -8
  43. package/dist/infrastructure/file-index.js +358 -0
  44. package/dist/infrastructure/file-system-vault.js +30 -0
  45. package/dist/infrastructure/index-state.js +56 -0
  46. package/dist/infrastructure/paths.js +9 -1
  47. package/dist/infrastructure/private-pack-codec.js +134 -0
  48. package/dist/infrastructure/search-packs.js +452 -0
  49. package/dist/infrastructure/session-state.js +172 -0
  50. package/dist/mcp/main.js +11 -3
  51. package/dist/mcp/server.js +27 -2
  52. package/dist/mcp/startup.js +35 -0
  53. package/dist/mcp/tools.js +633 -19
  54. package/docs/AGENT_USAGE.md +178 -16
  55. package/docs/ARCHITECTURE.md +37 -26
  56. package/docs/QUICKSTART.md +111 -0
  57. package/package.json +6 -4
  58. package/dist/infrastructure/sqlite/document-writer.js +0 -51
  59. package/dist/infrastructure/sqlite/graph-reader.js +0 -120
  60. package/dist/infrastructure/sqlite/schema.js +0 -111
  61. package/dist/infrastructure/sqlite/search-reader.js +0 -156
  62. package/dist/infrastructure/sqlite/types.js +0 -1
  63. package/dist/infrastructure/sqlite-index.js +0 -25
@@ -25,6 +25,13 @@ body {
25
25
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
26
26
  }
27
27
 
28
+ body {
29
+ display: flex;
30
+ flex-direction: column;
31
+ min-height: 100vh;
32
+ min-height: 100dvh;
33
+ }
34
+
28
35
  button,
29
36
  input,
30
37
  select {
@@ -32,19 +39,44 @@ select {
32
39
  }
33
40
 
34
41
  .shell {
35
- display: grid;
36
- grid-template-columns: minmax(0, 1fr) 360px;
42
+ flex: 1 1 auto;
37
43
  width: 100%;
38
- height: 100svh;
44
+ min-height: 0;
39
45
  overflow: hidden;
40
46
  }
41
47
 
42
48
  .workspace {
49
+ display: grid;
50
+ grid-template-rows: auto minmax(0, 1fr);
43
51
  position: relative;
52
+ width: 100%;
53
+ height: 100%;
44
54
  min-width: 0;
45
55
  min-height: 0;
46
56
  }
47
57
 
58
+ .graph-header {
59
+ z-index: 5;
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 12px;
63
+ min-height: 72px;
64
+ padding: 10px 16px;
65
+ border-bottom: 1px solid var(--line);
66
+ background: linear-gradient(180deg, rgba(17, 21, 27, 0.96) 0%, rgba(17, 21, 27, 0.86) 100%);
67
+ backdrop-filter: blur(8px);
68
+ }
69
+
70
+ .brand-block {
71
+ display: grid;
72
+ gap: 2px;
73
+ min-width: max-content;
74
+ }
75
+
76
+ .brand-block strong {
77
+ font-size: 18px;
78
+ }
79
+
48
80
  #graph {
49
81
  display: block;
50
82
  width: 100%;
@@ -59,43 +91,25 @@ select {
59
91
  cursor: grabbing;
60
92
  }
61
93
 
62
- .topbar {
63
- position: absolute;
64
- top: 18px;
65
- left: 18px;
66
- right: 18px;
67
- display: flex;
68
- align-items: center;
69
- justify-content: space-between;
70
- gap: 18px;
71
- pointer-events: none;
72
- }
73
-
74
- .topbar > div {
75
- display: flex;
76
- align-items: baseline;
77
- gap: 12px;
78
- }
79
-
80
- .topbar strong {
81
- font-size: 18px;
82
- }
83
-
84
- .topbar span,
85
- .eyebrow,
86
- .inspector small {
94
+ .eyebrow {
87
95
  color: var(--muted);
88
96
  font-size: 12px;
89
97
  }
90
98
 
91
99
  .search {
92
- width: min(420px, 42vw);
93
- pointer-events: auto;
100
+ flex: 1 1 320px;
101
+ min-width: 220px;
94
102
  }
95
103
 
96
104
  .agent-filter {
97
105
  width: min(220px, 28vw);
98
- pointer-events: auto;
106
+ }
107
+
108
+ .header-actions {
109
+ display: flex;
110
+ align-items: center;
111
+ gap: 10px;
112
+ margin-left: auto;
99
113
  }
100
114
 
101
115
  .search input,
@@ -116,9 +130,6 @@ select {
116
130
  }
117
131
 
118
132
  .toolbar {
119
- position: absolute;
120
- left: 18px;
121
- bottom: 18px;
122
133
  display: flex;
123
134
  gap: 8px;
124
135
  }
@@ -138,70 +149,34 @@ select {
138
149
  color: var(--accent);
139
150
  }
140
151
 
141
- .inspector {
142
- display: grid;
143
- grid-template-rows: auto auto auto minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
144
- gap: 22px;
145
- min-width: 0;
146
- height: 100%;
147
- padding: 24px;
148
- border-left: 1px solid var(--line);
149
- background: var(--panel);
150
- overflow: auto;
152
+ .floating-metrics {
153
+ display: flex;
154
+ gap: 10px;
155
+ flex-wrap: wrap;
151
156
  }
152
157
 
153
- .inspector h1,
154
- .inspector h2,
155
- .inspector p {
156
- margin: 0;
158
+ .metric-chip {
159
+ min-width: 94px;
160
+ padding: 10px 12px;
161
+ border: 1px solid var(--line);
162
+ border-radius: 10px;
163
+ background: rgba(21, 25, 31, 0.88);
164
+ display: grid;
165
+ gap: 3px;
157
166
  }
158
167
 
159
- .inspector h1 {
160
- margin-top: 6px;
168
+ .metric-chip strong {
161
169
  font-size: 26px;
162
- line-height: 1.12;
163
- overflow-wrap: anywhere;
170
+ line-height: 1;
164
171
  }
165
172
 
166
- .inspector h2 {
167
- margin-bottom: 10px;
173
+ .metric-chip small {
168
174
  color: var(--muted);
169
- font-size: 12px;
170
- font-weight: 700;
175
+ font-size: 11px;
176
+ letter-spacing: 0.03em;
171
177
  text-transform: uppercase;
172
178
  }
173
179
 
174
- #path {
175
- margin-top: 10px;
176
- color: var(--muted);
177
- line-height: 1.45;
178
- overflow-wrap: anywhere;
179
- }
180
-
181
- .metrics {
182
- display: grid;
183
- grid-template-columns: repeat(3, 1fr);
184
- border: 1px solid var(--line);
185
- border-radius: 8px;
186
- overflow: hidden;
187
- }
188
-
189
- .metrics div {
190
- display: grid;
191
- gap: 4px;
192
- padding: 14px;
193
- background: var(--panel-strong);
194
- }
195
-
196
- .metrics div + div {
197
- border-left: 1px solid var(--line);
198
- }
199
-
200
- .metrics span {
201
- font-size: 22px;
202
- font-weight: 700;
203
- }
204
-
205
180
  .tags {
206
181
  display: flex;
207
182
  flex-wrap: wrap;
@@ -215,6 +190,7 @@ select {
215
190
  background: var(--accent-weak);
216
191
  color: var(--accent);
217
192
  font-size: 12px;
193
+ word-break: break-word;
218
194
  overflow-wrap: anywhere;
219
195
  }
220
196
 
@@ -230,6 +206,7 @@ li {
230
206
  padding: 10px 0;
231
207
  border-bottom: 1px solid var(--line);
232
208
  color: var(--text);
209
+ word-break: break-word;
233
210
  overflow-wrap: anywhere;
234
211
  }
235
212
 
@@ -268,8 +245,8 @@ li small {
268
245
  }
269
246
 
270
247
  .content-dialog {
271
- width: min(920px, calc(100vw - 32px));
272
- max-height: calc(100svh - 32px);
248
+ width: min(1240px, calc(100vw - 24px));
249
+ max-height: calc(100svh - 20px);
273
250
  padding: 0;
274
251
  border: 1px solid var(--line);
275
252
  border-radius: 8px;
@@ -285,8 +262,8 @@ li small {
285
262
 
286
263
  .content-dialog article {
287
264
  display: grid;
288
- grid-template-rows: auto minmax(0, 1fr);
289
- max-height: calc(100svh - 34px);
265
+ grid-template-rows: auto auto minmax(0, 1fr);
266
+ max-height: calc(100svh - 22px);
290
267
  }
291
268
 
292
269
  .content-dialog header {
@@ -333,6 +310,41 @@ li small {
333
310
  color: var(--accent);
334
311
  }
335
312
 
313
+ .content-meta {
314
+ display: grid;
315
+ grid-template-columns: repeat(3, minmax(0, 1fr));
316
+ gap: 10px;
317
+ padding: 14px 22px;
318
+ border-bottom: 1px solid var(--line);
319
+ }
320
+
321
+ .content-meta-section {
322
+ min-height: 0;
323
+ padding: 10px;
324
+ border: 1px solid var(--line);
325
+ border-radius: 8px;
326
+ background: var(--panel-strong);
327
+ display: grid;
328
+ grid-template-rows: auto minmax(0, 1fr);
329
+ gap: 8px;
330
+ }
331
+
332
+ .content-meta-section h3 {
333
+ margin: 0;
334
+ color: var(--muted);
335
+ font-size: 11px;
336
+ font-weight: 700;
337
+ text-transform: uppercase;
338
+ }
339
+
340
+ .content-meta-section ul,
341
+ .content-meta-section .tags {
342
+ max-height: 220px;
343
+ overflow: auto;
344
+ align-content: flex-start;
345
+ padding-right: 4px;
346
+ }
347
+
336
348
  .content-dialog .note-content {
337
349
  max-height: none;
338
350
  min-height: 0;
@@ -341,33 +353,56 @@ li small {
341
353
  padding: 22px;
342
354
  }
343
355
 
344
- @media (max-width: 860px) {
345
- .shell {
346
- grid-template-columns: 1fr;
347
- grid-template-rows: minmax(0, 1fr) 42svh;
348
- }
356
+ .app-footer {
357
+ flex: 0 0 28px;
358
+ height: 28px;
359
+ display: flex;
360
+ align-items: center;
361
+ justify-content: center;
362
+ background: transparent;
363
+ }
349
364
 
350
- .inspector {
351
- border-left: 0;
352
- border-top: 1px solid var(--line);
353
- padding: 18px;
354
- }
365
+ .app-footer small {
366
+ color: var(--muted);
367
+ font-size: 11px;
368
+ letter-spacing: 0.02em;
369
+ }
355
370
 
356
- .topbar {
371
+ @media (max-width: 860px) {
372
+ .graph-header {
357
373
  align-items: stretch;
358
- flex-direction: column;
374
+ flex-wrap: wrap;
375
+ padding: 10px 12px;
376
+ min-height: 0;
359
377
  }
360
378
 
361
379
  .search {
362
380
  width: 100%;
381
+ flex-basis: 100%;
382
+ order: 3;
363
383
  }
364
384
 
365
385
  .agent-filter {
366
386
  width: 100%;
367
387
  }
368
388
 
389
+ .header-actions {
390
+ width: 100%;
391
+ margin-left: 0;
392
+ justify-content: space-between;
393
+ order: 4;
394
+ }
395
+
369
396
  .content-dialog header {
370
397
  align-items: stretch;
371
398
  flex-direction: column;
372
399
  }
400
+
401
+ .metric-chip {
402
+ min-width: 82px;
403
+ }
404
+
405
+ .content-meta {
406
+ grid-template-columns: 1fr;
407
+ }
373
408
  }`;
@@ -9,54 +9,46 @@ export const createClientHtml = () => `<!doctype html>
9
9
  <body>
10
10
  <main class="shell">
11
11
  <section class="workspace" aria-label="Knowledge graph">
12
- <canvas id="graph" aria-label="Brainlink knowledge graph"></canvas>
13
- <div class="topbar">
14
- <div>
12
+ <header class="graph-header" aria-label="Graph actions">
13
+ <div class="brand-block">
15
14
  <strong>Brainlink</strong>
16
- <span id="stats">Loading graph</span>
15
+ <span class="eyebrow">Knowledge Graph</span>
16
+ </div>
17
+ <div class="floating-metrics" aria-label="Graph totals">
18
+ <div class="metric-chip">
19
+ <strong id="nodeCount">0</strong>
20
+ <small>Notes</small>
21
+ </div>
22
+ <div class="metric-chip">
23
+ <strong id="edgeCount">0</strong>
24
+ <small>Links</small>
25
+ </div>
26
+ <div class="metric-chip">
27
+ <strong id="tagCount">0</strong>
28
+ <small>Tags</small>
29
+ </div>
17
30
  </div>
18
31
  <label class="search">
19
32
  <input id="search" type="search" placeholder="Filter notes, tags or paths" autocomplete="off" />
20
33
  </label>
21
- <label class="agent-filter">
22
- <select id="agent"></select>
23
- </label>
24
- </div>
25
- <div class="toolbar" aria-label="Graph controls">
26
- <button id="zoomIn" type="button" title="Zoom in">+</button>
27
- <button id="zoomOut" type="button" title="Zoom out">-</button>
28
- <button id="reset" type="button" title="Reset view">⌂</button>
29
- </div>
34
+ <div class="header-actions">
35
+ <label class="agent-filter">
36
+ <select id="agent"></select>
37
+ </label>
38
+ <div class="toolbar" aria-label="Graph controls">
39
+ <button id="zoomIn" type="button" title="Zoom in">+</button>
40
+ <button id="zoomOut" type="button" title="Zoom out">-</button>
41
+ <button id="fit" type="button" title="Focus central hub">◎</button>
42
+ <button id="reset" type="button" title="Reset view">⌂</button>
43
+ </div>
44
+ </div>
45
+ </header>
46
+ <canvas id="graph" aria-label="Brainlink knowledge graph"></canvas>
30
47
  </section>
31
- <aside class="inspector" aria-label="Selected note">
32
- <div>
33
- <span class="eyebrow">Selected note</span>
34
- <h1 id="title">Graph Overview</h1>
35
- <p id="path">Select a node to inspect links and backlinks.</p>
36
- </div>
37
- <div class="metrics">
38
- <div><span id="nodeCount">0</span><small>Notes</small></div>
39
- <div><span id="edgeCount">0</span><small>Links</small></div>
40
- <div><span id="tagCount">0</span><small>Tags</small></div>
41
- </div>
42
- <section>
43
- <h2>Tags</h2>
44
- <div id="tags" class="tags"></div>
45
- </section>
46
- <section>
47
- <h2>Notes</h2>
48
- <ul id="notes"></ul>
49
- </section>
50
- <section>
51
- <h2>Outgoing</h2>
52
- <ul id="outgoing"></ul>
53
- </section>
54
- <section>
55
- <h2>Backlinks</h2>
56
- <ul id="incoming"></ul>
57
- </section>
58
- </aside>
59
48
  </main>
49
+ <footer class="app-footer" aria-label="Copyright notice">
50
+ <small>Copyright © 2026 Substructa</small>
51
+ </footer>
60
52
  <dialog id="contentDialog" class="content-dialog" aria-labelledby="contentTitle">
61
53
  <article>
62
54
  <header>
@@ -67,6 +59,20 @@ export const createClientHtml = () => `<!doctype html>
67
59
  </div>
68
60
  <button id="contentClose" type="button">Close</button>
69
61
  </header>
62
+ <div class="content-meta">
63
+ <section class="content-meta-section">
64
+ <h3>Tags</h3>
65
+ <div id="contentTags" class="tags"></div>
66
+ </section>
67
+ <section class="content-meta-section">
68
+ <h3>Outgoing</h3>
69
+ <ul id="contentOutgoing"></ul>
70
+ </section>
71
+ <section class="content-meta-section">
72
+ <h3>Backlinks</h3>
73
+ <ul id="contentIncoming"></ul>
74
+ </section>
75
+ </div>
70
76
  <pre id="contentBody" class="note-content"></pre>
71
77
  </article>
72
78
  </dialog>