brainbank 0.7.0 → 0.8.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 (156) hide show
  1. package/README.md +76 -1398
  2. package/bin/brainbank +5 -1
  3. package/dist/{chunk-N2OJRXSB.js → chunk-3HVCONGF.js} +1 -1
  4. package/dist/{chunk-N2OJRXSB.js.map → chunk-3HVCONGF.js.map} +1 -1
  5. package/dist/{chunk-CCXVL56V.js → chunk-3JZIM5AU.js} +6 -3
  6. package/dist/chunk-3JZIM5AU.js.map +1 -0
  7. package/dist/{chunk-6XOXM7MI.js → chunk-5KU2PP34.js} +2 -2
  8. package/dist/{chunk-6XOXM7MI.js.map → chunk-5KU2PP34.js.map} +1 -1
  9. package/dist/chunk-7JDCHUJV.js +89 -0
  10. package/dist/chunk-7JDCHUJV.js.map +1 -0
  11. package/dist/{chunk-B77KABWH.js → chunk-7T2ZCZQA.js} +17 -15
  12. package/dist/chunk-7T2ZCZQA.js.map +1 -0
  13. package/dist/chunk-E3J37GDA.js +74 -0
  14. package/dist/chunk-E3J37GDA.js.map +1 -0
  15. package/dist/chunk-JEFWMS5Z.js +217 -0
  16. package/dist/chunk-JEFWMS5Z.js.map +1 -0
  17. package/dist/chunk-JRVYSTMP.js +3256 -0
  18. package/dist/chunk-JRVYSTMP.js.map +1 -0
  19. package/dist/chunk-OLDHLOMT.js +69 -0
  20. package/dist/chunk-OLDHLOMT.js.map +1 -0
  21. package/dist/{chunk-424UFCY7.js → chunk-QTZNB6AK.js} +6 -2
  22. package/dist/chunk-QTZNB6AK.js.map +1 -0
  23. package/dist/chunk-RFF7HMP6.js +109 -0
  24. package/dist/chunk-RFF7HMP6.js.map +1 -0
  25. package/dist/{chunk-ZNLN2VWV.js → chunk-TD3TEFI3.js} +1 -1
  26. package/dist/chunk-TD3TEFI3.js.map +1 -0
  27. package/dist/cli.js +1036 -341
  28. package/dist/cli.js.map +1 -1
  29. package/dist/haiku-expander-WOVJIVXD.js +8 -0
  30. package/dist/haiku-pruner-DB77ZQLJ.js +8 -0
  31. package/dist/http-server-GIRELCCL.js +9 -0
  32. package/dist/index.d.ts +1774 -611
  33. package/dist/index.js +282 -70
  34. package/dist/index.js.map +1 -1
  35. package/dist/{local-embedding-ZIMTK6PU.js → local-embedding-2RNCC5EU.js} +2 -2
  36. package/dist/{openai-embedding-VQZCZQYT.js → openai-embedding-Z5I4K4CN.js} +2 -2
  37. package/dist/perplexity-context-embedding-V5YUMXDR.js +9 -0
  38. package/dist/{perplexity-embedding-227WQY4R.js → perplexity-embedding-X2S72OAC.js} +2 -2
  39. package/dist/plugin-FF4Q34TI.js +32 -0
  40. package/dist/{qwen3-reranker-3MHEENT5.js → qwen3-reranker-HVIQOLKS.js} +2 -2
  41. package/dist/{resolve-CUJWY6HP.js → resolve-Q5D6HECY.js} +2 -2
  42. package/package.json +25 -52
  43. package/src/brainbank.ts +620 -0
  44. package/src/cli/commands/collection.ts +77 -0
  45. package/src/cli/commands/context.ts +171 -0
  46. package/src/cli/commands/daemon.ts +100 -0
  47. package/src/cli/commands/docs.ts +71 -0
  48. package/src/cli/commands/files.ts +69 -0
  49. package/src/cli/commands/help.ts +72 -0
  50. package/src/cli/commands/index.ts +282 -0
  51. package/src/cli/commands/kv.ts +140 -0
  52. package/src/cli/commands/mcp.ts +13 -0
  53. package/src/cli/commands/reembed.ts +30 -0
  54. package/src/cli/commands/scan.ts +365 -0
  55. package/src/cli/commands/search.ts +130 -0
  56. package/src/cli/commands/stats.ts +44 -0
  57. package/src/cli/commands/status.ts +47 -0
  58. package/src/cli/commands/watch.ts +43 -0
  59. package/src/cli/factory/brain-context.ts +43 -0
  60. package/src/cli/factory/builtin-registration.ts +123 -0
  61. package/src/cli/factory/config-loader.ts +72 -0
  62. package/src/cli/factory/index.ts +65 -0
  63. package/src/cli/factory/plugin-loader.ts +146 -0
  64. package/src/cli/index.ts +63 -0
  65. package/src/cli/server-client.ts +135 -0
  66. package/src/cli/utils.ts +121 -0
  67. package/src/config.ts +50 -0
  68. package/src/constants.ts +13 -0
  69. package/src/db/adapter.ts +112 -0
  70. package/src/db/metadata.ts +130 -0
  71. package/src/db/migrations.ts +66 -0
  72. package/src/db/sqlite-adapter.ts +208 -0
  73. package/src/db/tracker.ts +91 -0
  74. package/src/engine/index-api.ts +85 -0
  75. package/src/engine/reembed.ts +206 -0
  76. package/src/engine/search-api.ts +222 -0
  77. package/src/index.ts +159 -0
  78. package/src/lib/fts.ts +57 -0
  79. package/src/lib/languages.ts +180 -0
  80. package/src/lib/logger.ts +125 -0
  81. package/src/lib/math.ts +87 -0
  82. package/src/lib/provider-key.ts +20 -0
  83. package/src/lib/prune.ts +71 -0
  84. package/src/lib/rerank.ts +33 -0
  85. package/src/lib/rrf.ts +133 -0
  86. package/src/lib/write-lock.ts +108 -0
  87. package/src/plugin.ts +323 -0
  88. package/src/providers/embeddings/embedding-worker-thread.ts +95 -0
  89. package/src/providers/embeddings/embedding-worker.ts +141 -0
  90. package/src/providers/embeddings/local-embedding.ts +115 -0
  91. package/src/providers/embeddings/openai-embedding.ts +167 -0
  92. package/src/providers/embeddings/perplexity-context-embedding.ts +195 -0
  93. package/src/providers/embeddings/perplexity-embedding.ts +165 -0
  94. package/src/providers/embeddings/resolve.ts +34 -0
  95. package/src/providers/pruners/haiku-expander.ts +152 -0
  96. package/src/providers/pruners/haiku-pruner.ts +112 -0
  97. package/src/providers/rerankers/qwen3-reranker.ts +180 -0
  98. package/src/providers/vector/hnsw-index.ts +174 -0
  99. package/src/providers/vector/hnsw-loader.ts +129 -0
  100. package/src/search/bm25-boost.ts +61 -0
  101. package/src/search/context-builder.ts +298 -0
  102. package/src/search/keyword/composite-bm25-search.ts +62 -0
  103. package/src/search/types.ts +35 -0
  104. package/src/search/vector/composite-vector-search.ts +76 -0
  105. package/src/search/vector/mmr.ts +64 -0
  106. package/src/services/collection.ts +405 -0
  107. package/src/services/daemon.ts +87 -0
  108. package/src/services/http-server.ts +288 -0
  109. package/src/services/kv-service.ts +65 -0
  110. package/src/services/plugin-registry.ts +109 -0
  111. package/src/services/watch.ts +348 -0
  112. package/src/services/webhook-server.ts +100 -0
  113. package/src/types.ts +504 -0
  114. package/dist/base-3SNc_CeY.d.ts +0 -593
  115. package/dist/chunk-424UFCY7.js.map +0 -1
  116. package/dist/chunk-7EZR47JV.js +0 -232
  117. package/dist/chunk-7EZR47JV.js.map +0 -1
  118. package/dist/chunk-B77KABWH.js.map +0 -1
  119. package/dist/chunk-CCXVL56V.js.map +0 -1
  120. package/dist/chunk-DI3H6JVZ.js +0 -2432
  121. package/dist/chunk-DI3H6JVZ.js.map +0 -1
  122. package/dist/chunk-FGL32LUJ.js +0 -754
  123. package/dist/chunk-FGL32LUJ.js.map +0 -1
  124. package/dist/chunk-JRSKWF6K.js +0 -313
  125. package/dist/chunk-JRSKWF6K.js.map +0 -1
  126. package/dist/chunk-U2Q2XGPZ.js +0 -42
  127. package/dist/chunk-U2Q2XGPZ.js.map +0 -1
  128. package/dist/chunk-VQ27YUHH.js +0 -629
  129. package/dist/chunk-VQ27YUHH.js.map +0 -1
  130. package/dist/chunk-VVXYZIIB.js +0 -304
  131. package/dist/chunk-VVXYZIIB.js.map +0 -1
  132. package/dist/chunk-YOLKSYWK.js +0 -79
  133. package/dist/chunk-YOLKSYWK.js.map +0 -1
  134. package/dist/chunk-ZNLN2VWV.js.map +0 -1
  135. package/dist/code.d.ts +0 -33
  136. package/dist/code.js +0 -9
  137. package/dist/docs.d.ts +0 -21
  138. package/dist/docs.js +0 -9
  139. package/dist/git.d.ts +0 -33
  140. package/dist/git.js +0 -9
  141. package/dist/memory.d.ts +0 -17
  142. package/dist/memory.js +0 -9
  143. package/dist/notes.d.ts +0 -17
  144. package/dist/notes.js +0 -10
  145. package/dist/perplexity-context-embedding-KSVSZXMD.js +0 -9
  146. package/dist/resolve-CUJWY6HP.js.map +0 -1
  147. /package/dist/{code.js.map → haiku-expander-WOVJIVXD.js.map} +0 -0
  148. /package/dist/{docs.js.map → haiku-pruner-DB77ZQLJ.js.map} +0 -0
  149. /package/dist/{git.js.map → http-server-GIRELCCL.js.map} +0 -0
  150. /package/dist/{local-embedding-ZIMTK6PU.js.map → local-embedding-2RNCC5EU.js.map} +0 -0
  151. /package/dist/{memory.js.map → openai-embedding-Z5I4K4CN.js.map} +0 -0
  152. /package/dist/{notes.js.map → perplexity-context-embedding-V5YUMXDR.js.map} +0 -0
  153. /package/dist/{openai-embedding-VQZCZQYT.js.map → perplexity-embedding-X2S72OAC.js.map} +0 -0
  154. /package/dist/{perplexity-context-embedding-KSVSZXMD.js.map → plugin-FF4Q34TI.js.map} +0 -0
  155. /package/dist/{perplexity-embedding-227WQY4R.js.map → qwen3-reranker-HVIQOLKS.js.map} +0 -0
  156. /package/dist/{qwen3-reranker-3MHEENT5.js.map → resolve-Q5D6HECY.js.map} +0 -0
@@ -1,593 +0,0 @@
1
- import BetterSqlite3 from 'better-sqlite3';
2
-
3
- /**
4
- * BrainBank — Database
5
- *
6
- * Thin wrapper over better-sqlite3.
7
- * Handles WAL mode, directory creation, schema init, and transactions.
8
- */
9
-
10
- declare class Database {
11
- readonly db: BetterSqlite3.Database;
12
- constructor(dbPath: string);
13
- /**
14
- * Run a function inside a transaction.
15
- * Auto-commits on success, auto-rollbacks on error.
16
- */
17
- transaction<T>(fn: () => T): T;
18
- /**
19
- * Run a prepared statement on multiple rows.
20
- * Wraps in a single transaction for performance.
21
- */
22
- batch<T extends any[]>(sql: string, rows: T[]): void;
23
- /** Prepare a reusable statement. */
24
- prepare(sql: string): BetterSqlite3.Statement;
25
- /** Execute raw SQL (no results). */
26
- exec(sql: string): void;
27
- /** Close the database. */
28
- close(): void;
29
- }
30
-
31
- /**
32
- * BrainBank — Type Definitions
33
- *
34
- * All interfaces and types for the semantic knowledge bank.
35
- */
36
- interface BrainBankConfig {
37
- /** Root path of the repository to index. Default: '.' */
38
- repoPath?: string;
39
- /** SQLite database path. Default: '.brainbank/brainbank.db' */
40
- dbPath?: string;
41
- /** Max git commits to index. Default: 500 */
42
- gitDepth?: number;
43
- /** Max file size in bytes to index. Default: 512_000 (500KB) */
44
- maxFileSize?: number;
45
- /** Max diff bytes per commit. Default: 8192 */
46
- maxDiffBytes?: number;
47
- /** HNSW M parameter (connections per node). Default: 16 */
48
- hnswM?: number;
49
- /** HNSW efConstruction (build-time candidates). Default: 200 */
50
- hnswEfConstruction?: number;
51
- /** HNSW efSearch (query-time candidates). Default: 50 */
52
- hnswEfSearch?: number;
53
- /** Embedding dimensions. Default: 384 */
54
- embeddingDims?: number;
55
- /** Max HNSW elements. Default: 2_000_000 */
56
- maxElements?: number;
57
- /** Custom embedding provider (default: local WASM model) */
58
- embeddingProvider?: EmbeddingProvider;
59
- /** Optional reranker for improved search quality */
60
- reranker?: Reranker;
61
- }
62
- interface ResolvedConfig {
63
- repoPath: string;
64
- dbPath: string;
65
- gitDepth: number;
66
- maxFileSize: number;
67
- maxDiffBytes: number;
68
- hnswM: number;
69
- hnswEfConstruction: number;
70
- hnswEfSearch: number;
71
- embeddingDims: number;
72
- maxElements: number;
73
- embeddingProvider?: EmbeddingProvider;
74
- reranker?: Reranker;
75
- }
76
- interface EmbeddingProvider {
77
- /** Vector dimensions produced by this provider. */
78
- readonly dims: number;
79
- /** Embed a single text string. */
80
- embed(text: string): Promise<Float32Array>;
81
- /** Embed multiple texts (batch). */
82
- embedBatch(texts: string[]): Promise<Float32Array[]>;
83
- /** Release resources. */
84
- close(): Promise<void>;
85
- }
86
- interface Reranker {
87
- /**
88
- * Score each document's relevance to the query.
89
- * @param query - The search query
90
- * @param documents - Document contents to rank
91
- * @returns Relevance scores (0.0 - 1.0) in same order as documents
92
- */
93
- rank(query: string, documents: string[]): Promise<number[]>;
94
- /** Release resources (e.g. unload model). */
95
- close?(): Promise<void>;
96
- }
97
- interface SearchHit {
98
- id: number;
99
- score: number;
100
- }
101
- interface VectorIndex {
102
- /** Initialize the index. Must be called before add/search. */
103
- init(): Promise<this>;
104
- /** Add a vector with an integer ID. Idempotent: duplicate IDs are skipped. */
105
- add(vector: Float32Array, id: number): void;
106
- /** Mark a vector as deleted so it no longer appears in searches. */
107
- remove(id: number): void;
108
- /** Search for k nearest neighbors. */
109
- search(query: Float32Array, k: number): SearchHit[];
110
- /** Clear all vectors and reset to empty state. */
111
- reinit(): void;
112
- /** Number of vectors in the index. */
113
- readonly size: number;
114
- }
115
- interface CodeChunk {
116
- /** Auto-incremented DB id (set after insert) */
117
- id?: number;
118
- /** Relative file path from repo root */
119
- filePath: string;
120
- /** Chunk type: 'file' | 'function' | 'class' | 'block' */
121
- chunkType: string;
122
- /** Function/class name (if detected) */
123
- name?: string;
124
- /** Start line (1-indexed) */
125
- startLine: number;
126
- /** End line (1-indexed, inclusive) */
127
- endLine: number;
128
- /** Raw content of the chunk */
129
- content: string;
130
- /** Language identifier */
131
- language: string;
132
- }
133
- interface GitCommitRecord {
134
- id?: number;
135
- hash: string;
136
- shortHash: string;
137
- message: string;
138
- author: string;
139
- date: string;
140
- timestamp: number;
141
- filesChanged: string[];
142
- diff?: string;
143
- additions: number;
144
- deletions: number;
145
- isMerge: boolean;
146
- }
147
- interface LearningPattern {
148
- id?: number;
149
- /** Category (e.g. 'api', 'refactor', 'debug') */
150
- taskType: string;
151
- /** What was the task */
152
- task: string;
153
- /** How it was approached */
154
- approach: string;
155
- /** What happened */
156
- outcome?: string;
157
- /** 0.0 – 1.0 */
158
- successRate: number;
159
- /** Lessons learned */
160
- critique?: string;
161
- /** Tokens consumed (optional tracking) */
162
- tokensUsed?: number;
163
- /** Latency in ms (optional tracking) */
164
- latencyMs?: number;
165
- }
166
- interface DistilledStrategy {
167
- taskType: string;
168
- strategy: string;
169
- confidence: number;
170
- updatedAt: number;
171
- }
172
- type SearchResultType = 'code' | 'commit' | 'pattern' | 'document' | 'collection';
173
- interface CodeResultMetadata {
174
- chunkType: string;
175
- name?: string;
176
- startLine: number;
177
- endLine: number;
178
- language: string;
179
- searchType?: string;
180
- }
181
- interface CommitResultMetadata {
182
- hash: string;
183
- shortHash: string;
184
- author: string;
185
- date: string;
186
- files: string[];
187
- additions?: number;
188
- deletions?: number;
189
- diff?: string;
190
- searchType?: string;
191
- }
192
- interface PatternResultMetadata {
193
- taskType: string;
194
- task: string;
195
- outcome?: string;
196
- successRate: number;
197
- critique?: string;
198
- searchType?: string;
199
- }
200
- interface DocumentResultMetadata {
201
- collection?: string;
202
- title?: string;
203
- seq?: number;
204
- path?: string;
205
- searchType?: string;
206
- /** Internal chunk ID used by hybrid search to map fused results. */
207
- chunkId?: number;
208
- }
209
- interface CodeResult {
210
- type: 'code';
211
- score: number;
212
- filePath: string;
213
- content: string;
214
- context?: string;
215
- metadata: CodeResultMetadata;
216
- }
217
- interface CommitResult {
218
- type: 'commit';
219
- score: number;
220
- filePath?: string;
221
- content: string;
222
- context?: string;
223
- metadata: CommitResultMetadata;
224
- }
225
- interface PatternResult {
226
- type: 'pattern';
227
- score: number;
228
- filePath?: string;
229
- content: string;
230
- context?: string;
231
- metadata: PatternResultMetadata;
232
- }
233
- interface DocumentResult {
234
- type: 'document';
235
- score: number;
236
- filePath: string;
237
- content: string;
238
- context?: string;
239
- metadata: DocumentResultMetadata;
240
- }
241
- interface CollectionResult {
242
- type: 'collection';
243
- score: number;
244
- filePath?: string;
245
- content: string;
246
- context?: string;
247
- metadata: Record<string, any>;
248
- }
249
- type SearchResult = CodeResult | CommitResult | PatternResult | DocumentResult | CollectionResult;
250
- /** Narrow a SearchResult to CodeResult. */
251
- declare function isCodeResult(r: SearchResult): r is CodeResult;
252
- /** Narrow a SearchResult to CommitResult. */
253
- declare function isCommitResult(r: SearchResult): r is CommitResult;
254
- /** Narrow a SearchResult to DocumentResult. */
255
- declare function isDocumentResult(r: SearchResult): r is DocumentResult;
256
- /** Narrow a SearchResult to PatternResult. */
257
- declare function isPatternResult(r: SearchResult): r is PatternResult;
258
- /** Narrow a SearchResult to CollectionResult. */
259
- declare function isCollectionResult(r: SearchResult): r is CollectionResult;
260
- type MatchHandlers<T> = {
261
- code?: (r: CodeResult) => T;
262
- commit?: (r: CommitResult) => T;
263
- pattern?: (r: PatternResult) => T;
264
- document?: (r: DocumentResult) => T;
265
- collection?: (r: CollectionResult) => T;
266
- _?: (r: SearchResult) => T;
267
- };
268
- /**
269
- * Pattern-match on SearchResult type. Calls the matching handler
270
- * or the `_` fallback. Returns undefined if no handler matches.
271
- */
272
- declare function matchResult<T>(result: SearchResult, handlers: MatchHandlers<T>): T | undefined;
273
- interface ContextOptions {
274
- /** Max code chunks to include. Default: 6 */
275
- codeResults?: number;
276
- /** Max git commits to include. Default: 5 */
277
- gitResults?: number;
278
- /** Max memory patterns to include. Default: 4 */
279
- patternResults?: number;
280
- /** Files the agent is about to modify (improves co-edit suggestions) */
281
- affectedFiles?: string[];
282
- /** Minimum similarity score threshold. Default: 0.25 */
283
- minScore?: number;
284
- /** Use MMR for diversity. Default: true */
285
- useMMR?: boolean;
286
- /** MMR lambda (0 = diversity, 1 = relevance). Default: 0.7 */
287
- mmrLambda?: number;
288
- }
289
- interface DocumentCollection {
290
- /** Collection name (e.g. 'notes', 'docs') */
291
- name: string;
292
- /** Directory path to index */
293
- path: string;
294
- /** Glob pattern for files (default: all markdown) */
295
- pattern?: string;
296
- /** Glob patterns to ignore */
297
- ignore?: string[];
298
- /** Context description for this collection */
299
- context?: string;
300
- }
301
- interface DocChunk {
302
- id?: number;
303
- /** Collection name */
304
- collection: string;
305
- /** Relative file path within the collection */
306
- filePath: string;
307
- /** Document title (first heading or filename) */
308
- title: string;
309
- /** Chunk content */
310
- content: string;
311
- /** Chunk sequence within the document (0, 1, 2...) */
312
- seq: number;
313
- /** Character position in original document */
314
- pos: number;
315
- /** Content hash for incremental updates */
316
- contentHash: string;
317
- }
318
- interface IndexStats {
319
- code?: {
320
- files: number;
321
- chunks: number;
322
- hnswSize: number;
323
- };
324
- git?: {
325
- commits: number;
326
- filesTracked: number;
327
- coEdits: number;
328
- hnswSize: number;
329
- };
330
- memory?: {
331
- patterns: number;
332
- avgSuccess: number;
333
- hnswSize: number;
334
- };
335
- documents?: {
336
- collections: number;
337
- documents: number;
338
- chunks: number;
339
- hnswSize: number;
340
- };
341
- notes?: {
342
- total: number;
343
- short: number;
344
- long: number;
345
- };
346
- }
347
- /** File-level progress (used by indexers). */
348
- type ProgressCallback = (file: string, current: number, total: number) => void;
349
- /** Stage-level progress (used by BrainBank.index() orchestrator). */
350
- type StageProgressCallback = (stage: string, message: string) => void;
351
- interface IndexResult {
352
- indexed: number;
353
- skipped: number;
354
- chunks?: number;
355
- }
356
- interface CoEditSuggestion {
357
- file: string;
358
- count: number;
359
- }
360
-
361
- /**
362
- * BrainBank — HNSW Vector Index
363
- *
364
- * Wraps hnswlib-node for O(log n) approximate nearest neighbor search.
365
- * M=16 connections, ef=200 construction, ef=50 search by default.
366
- * 150x faster than brute force at 1M vectors.
367
- *
368
- * Supports disk persistence: save(path) / tryLoad(path, count)
369
- * to skip costly vector-by-vector rebuild on startup.
370
- */
371
-
372
- declare class HNSWIndex implements VectorIndex {
373
- private _dims;
374
- private _maxElements;
375
- private _M;
376
- private _efConstruction;
377
- private _efSearch;
378
- private _index;
379
- private _lib;
380
- private _ids;
381
- constructor(_dims: number, _maxElements?: number, _M?: number, _efConstruction?: number, _efSearch?: number);
382
- /**
383
- * Initialize the HNSW index.
384
- * Must be called before add/search.
385
- */
386
- init(): Promise<this>;
387
- /**
388
- * Reinitialize the index in-place, clearing all vectors.
389
- * Required after reembed or full re-index to avoid duplicate IDs.
390
- * init() must have been called first.
391
- */
392
- reinit(): void;
393
- private _createIndex;
394
- /** Maximum capacity of this index. */
395
- get maxElements(): number;
396
- /**
397
- * Add a vector with an integer ID.
398
- * The vector should be pre-normalized for cosine distance.
399
- */
400
- add(vector: Float32Array, id: number): void;
401
- /**
402
- * Mark a vector as deleted so it no longer appears in searches.
403
- * Uses hnswlib-node markDelete under the hood.
404
- * Safe to call with an ID that doesn't exist.
405
- */
406
- remove(id: number): void;
407
- /**
408
- * Search for the k nearest neighbors.
409
- * Returns results sorted by score (highest first).
410
- * Score is 1 - cosine_distance (1.0 = identical).
411
- */
412
- search(query: Float32Array, k: number): SearchHit[];
413
- /** Number of vectors in the index. */
414
- get size(): number;
415
- /**
416
- * Save the HNSW graph to disk.
417
- * The file can be loaded later with tryLoad() to skip vector-by-vector insertion.
418
- */
419
- save(path: string): void;
420
- /**
421
- * Try to load a previously saved HNSW index from disk.
422
- * Returns true if loaded successfully, false if stale or missing.
423
- * @param path File path to the saved index
424
- * @param expectedCount Expected number of vectors (from SQLite) — used to detect staleness
425
- */
426
- tryLoad(path: string, expectedCount: number): boolean;
427
- }
428
-
429
- /**
430
- * BrainBank — Collection
431
- *
432
- * Universal key-value store with vector + BM25 hybrid search.
433
- * The foundation primitive — store anything, search semantically.
434
- *
435
- * const errors = brain.collection('debug_errors');
436
- * await errors.add('Fixed null check in api handler', { file: 'api.ts' });
437
- * const hits = await errors.search('null pointer');
438
- */
439
-
440
- interface CollectionItem {
441
- id: number;
442
- collection: string;
443
- content: string;
444
- metadata: Record<string, any>;
445
- tags: string[];
446
- createdAt: number;
447
- expiresAt?: number;
448
- score?: number;
449
- }
450
- interface CollectionSearchOptions {
451
- /** Max results. Default: 5 */
452
- k?: number;
453
- /** Search mode. Default: 'hybrid' */
454
- mode?: 'hybrid' | 'vector' | 'keyword';
455
- /** Minimum score threshold. Default: 0.15 */
456
- minScore?: number;
457
- /** Filter by tags (item must have ALL specified tags). */
458
- tags?: string[];
459
- }
460
- interface CollectionAddOptions {
461
- /** Metadata key-value pairs. */
462
- metadata?: Record<string, any>;
463
- /** Tags for filtering. */
464
- tags?: string[];
465
- /** Time-to-live duration string (e.g. '7d', '24h', '30m'). */
466
- ttl?: string;
467
- }
468
- declare class Collection {
469
- private _name;
470
- private _db;
471
- private _embedding;
472
- private _hnsw;
473
- private _vecs;
474
- private _reranker?;
475
- constructor(_name: string, _db: Database, _embedding: EmbeddingProvider, _hnsw: HNSWIndex, _vecs: Map<number, Float32Array>, _reranker?: Reranker | undefined);
476
- /** Collection name. */
477
- get name(): string;
478
- /** Add an item. Returns its ID. */
479
- add(content: string, options?: CollectionAddOptions | Record<string, any>): Promise<number>;
480
- /** Add multiple items. Returns their IDs. */
481
- addMany(items: {
482
- content: string;
483
- metadata?: Record<string, any>;
484
- tags?: string[];
485
- ttl?: string;
486
- }[]): Promise<number[]>;
487
- /** Search this collection. */
488
- search(query: string, options?: CollectionSearchOptions): Promise<CollectionItem[]>;
489
- /** List items (newest first). */
490
- list(options?: {
491
- limit?: number;
492
- offset?: number;
493
- tags?: string[];
494
- }): CollectionItem[];
495
- /** Count items in this collection. */
496
- count(): number;
497
- /** Keep only the N most recent items, remove the rest. */
498
- trim(options: {
499
- keep: number;
500
- }): Promise<{
501
- removed: number;
502
- }>;
503
- /** Remove items older than a duration string (e.g. '30d', '12h'). */
504
- prune(options: {
505
- olderThan: string;
506
- }): Promise<{
507
- removed: number;
508
- }>;
509
- /** Remove a specific item by ID. */
510
- remove(id: number): void;
511
- /** Clear all items in this collection. */
512
- clear(): void;
513
- private _removeById;
514
- private _searchVector;
515
- private _searchBM25;
516
- private _rowToItem;
517
- /** Filter results by tags (item must have ALL specified tags). */
518
- private _filterByTags;
519
- /** Remove expired items (TTL). Called automatically on search/list. */
520
- private _pruneExpired;
521
- }
522
-
523
- /**
524
- * BrainBank — Plugin System
525
- *
526
- * Plugins are pluggable strategies that scan external data sources
527
- * and push content into BrainBank. Built-in plugins handle code,
528
- * git, and docs. Third-party frameworks (LangChain, etc.)
529
- * can implement custom plugins.
530
- *
531
- * import { BrainBank } from 'brainbank';
532
- * import { code } from 'brainbank/indexers/code';
533
- *
534
- * const brain = new BrainBank()
535
- * .use(code({ repoPath: '.' }));
536
- */
537
-
538
- interface PluginContext {
539
- /** SQLite database (shared across all plugins). */
540
- db: Database;
541
- /** Embedding provider (shared). */
542
- embedding: EmbeddingProvider;
543
- /** Resolved BrainBank config. */
544
- config: ResolvedConfig;
545
- /** Create and initialize an HNSW index. Optionally override dims for per-plugin embeddings. */
546
- createHnsw(maxElements?: number, dims?: number): Promise<HNSWIndex>;
547
- /** Load existing vectors from a SQLite vectors table into an HNSW index + cache. */
548
- loadVectors(table: string, idCol: string, hnsw: HNSWIndex, cache: Map<number, Float32Array>): void;
549
- /** Get or create a shared HNSW index by type (e.g. 'code', 'git'). Optionally override dims for per-plugin embeddings. */
550
- getOrCreateSharedHnsw(type: string, maxElements?: number, dims?: number): Promise<{
551
- hnsw: HNSWIndex;
552
- vecCache: Map<number, Float32Array>;
553
- isNew: boolean;
554
- }>;
555
- /** Get or create a dynamic collection. */
556
- collection(name: string): Collection;
557
- }
558
- interface Plugin {
559
- /** Unique plugin name (e.g. 'code', 'git', 'docs'). */
560
- readonly name: string;
561
- /** Initialize the plugin (create HNSW, load vectors, etc.). */
562
- initialize(ctx: PluginContext): Promise<void>;
563
- /** Return stats for this plugin. */
564
- stats?(): Record<string, any>;
565
- /** Clean up resources. */
566
- close?(): void;
567
- }
568
- /** Plugins that can scan and index content (code, git). */
569
- interface IndexablePlugin extends Plugin {
570
- index(options?: any): Promise<any>;
571
- }
572
- /** Plugins that can search indexed content (docs). */
573
- interface SearchablePlugin extends Plugin {
574
- search(query: string, options?: any): Promise<SearchResult[]>;
575
- }
576
- /** Plugins that support file watch mode. */
577
- interface WatchablePlugin extends Plugin {
578
- onFileChange(filePath: string, event: 'create' | 'update' | 'delete'): Promise<boolean>;
579
- watchPatterns(): string[];
580
- }
581
- /** Plugins that manage document collections. */
582
- interface CollectionPlugin extends Plugin {
583
- addCollection(collection: DocumentCollection): void;
584
- removeCollection(name: string): void;
585
- listCollections(): DocumentCollection[];
586
- indexCollections(options?: any): Promise<any>;
587
- search(query: string, options?: any): Promise<SearchResult[]>;
588
- addContext?(collection: string, path: string, context: string): void;
589
- removeContext?(collection: string, path: string): void;
590
- listContexts?(): any[];
591
- }
592
-
593
- export { type SearchResultType as A, type BrainBankConfig as B, Collection as C, type DocumentCollection as D, type EmbeddingProvider as E, type SearchablePlugin as F, type GitCommitRecord as G, HNSWIndex as H, type IndexResult as I, isCodeResult as J, isCollectionResult as K, type LearningPattern as L, isCommitResult as M, isDocumentResult as N, isPatternResult as O, type Plugin as P, matchResult as Q, type ResolvedConfig as R, type StageProgressCallback as S, type VectorIndex as V, type WatchablePlugin as W, type ProgressCallback as a, type SearchResult as b, type ContextOptions as c, type CoEditSuggestion as d, type IndexStats as e, type Reranker as f, type SearchHit as g, type CodeChunk as h, Database as i, type CodeResult as j, type CodeResultMetadata as k, type CollectionAddOptions as l, type CollectionItem as m, type CollectionPlugin as n, type CollectionResult as o, type CollectionSearchOptions as p, type CommitResult as q, type CommitResultMetadata as r, type DistilledStrategy as s, type DocChunk as t, type DocumentResult as u, type DocumentResultMetadata as v, type IndexablePlugin as w, type PatternResult as x, type PatternResultMetadata as y, type PluginContext as z };
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/providers/embeddings/local-embedding.ts"],"sourcesContent":["/**\n * BrainBank — Local Embedding Provider\n * \n * Uses @xenova/transformers with all-MiniLM-L6-v2 (384 dims, WASM).\n * Downloads ~23MB on first use, cached locally.\n * No external API calls — runs entirely in-process.\n */\n\nimport type { EmbeddingProvider } from '@/types.ts';\n\nexport class LocalEmbedding implements EmbeddingProvider {\n readonly dims: number = 384;\n\n private _pipeline: any = null;\n private _modelName: string;\n private _cacheDir: string;\n\n constructor(options: { model?: string; cacheDir?: string } = {}) {\n this._modelName = options.model ?? 'Xenova/all-MiniLM-L6-v2';\n this._cacheDir = options.cacheDir ?? '.model-cache';\n }\n\n private _pipelinePromise: Promise<any> | null = null;\n\n /**\n * Lazy-load the transformer pipeline.\n * Singleton — created once and reused.\n * Promise-deduped to prevent concurrent downloads.\n */\n private async _getPipeline(): Promise<any> {\n if (this._pipeline) return this._pipeline;\n if (this._pipelinePromise) return this._pipelinePromise;\n\n this._pipelinePromise = (async () => {\n const { pipeline, env } = await import('@xenova/transformers' as any);\n env.cacheDir = this._cacheDir;\n env.allowLocalModels = true;\n\n this._pipeline = await pipeline('feature-extraction', this._modelName, {\n quantized: true,\n });\n\n return this._pipeline;\n })();\n\n try {\n return await this._pipelinePromise;\n } finally {\n this._pipelinePromise = null;\n }\n }\n\n /**\n * Embed a single text string.\n * Returns a normalized Float32Array of length 384.\n */\n async embed(text: string): Promise<Float32Array> {\n const pipe = await this._getPipeline();\n const output = await pipe(text, { pooling: 'mean', normalize: true });\n return output.data as Float32Array;\n }\n\n /**\n * Embed multiple texts using real batch processing.\n * Chunks into groups of BATCH_SIZE to balance throughput vs memory.\n */\n async embedBatch(texts: string[]): Promise<Float32Array[]> {\n if (texts.length === 0) return [];\n\n const BATCH_SIZE = 32;\n const pipe = await this._getPipeline();\n const results: Float32Array[] = [];\n\n for (let i = 0; i < texts.length; i += BATCH_SIZE) {\n const batch = texts.slice(i, i + BATCH_SIZE);\n const output = await pipe(batch, { pooling: 'mean', normalize: true });\n\n // output.data is a flat Float32Array — must copy, not view,\n // because the pipeline may reuse the underlying buffer\n for (let j = 0; j < batch.length; j++) {\n const start = j * this.dims;\n results.push(output.data.slice(start, start + this.dims) as Float32Array);\n }\n }\n\n return results;\n }\n\n async close(): Promise<void> {\n this._pipeline = null;\n }\n}\n"],"mappings":";;;;;AAUO,IAAM,iBAAN,MAAkD;AAAA,EAVzD,OAUyD;AAAA;AAAA;AAAA,EAC5C,OAAe;AAAA,EAEhB,YAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EAER,YAAY,UAAiD,CAAC,GAAG;AAC7D,SAAK,aAAa,QAAQ,SAAS;AACnC,SAAK,YAAY,QAAQ,YAAY;AAAA,EACzC;AAAA,EAEQ,mBAAwC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhD,MAAc,eAA6B;AACvC,QAAI,KAAK,UAAW,QAAO,KAAK;AAChC,QAAI,KAAK,iBAAkB,QAAO,KAAK;AAEvC,SAAK,oBAAoB,YAAY;AACjC,YAAM,EAAE,UAAU,IAAI,IAAI,MAAM,OAAO,sBAA6B;AACpE,UAAI,WAAW,KAAK;AACpB,UAAI,mBAAmB;AAEvB,WAAK,YAAY,MAAM,SAAS,sBAAsB,KAAK,YAAY;AAAA,QACnE,WAAW;AAAA,MACf,CAAC;AAED,aAAO,KAAK;AAAA,IAChB,GAAG;AAEH,QAAI;AACA,aAAO,MAAM,KAAK;AAAA,IACtB,UAAE;AACE,WAAK,mBAAmB;AAAA,IAC5B;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAM,MAAqC;AAC7C,UAAM,OAAO,MAAM,KAAK,aAAa;AACrC,UAAM,SAAS,MAAM,KAAK,MAAM,EAAE,SAAS,QAAQ,WAAW,KAAK,CAAC;AACpE,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW,OAA0C;AACvD,QAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAEhC,UAAM,aAAa;AACnB,UAAM,OAAO,MAAM,KAAK,aAAa;AACrC,UAAM,UAA0B,CAAC;AAEjC,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,YAAY;AAC/C,YAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,UAAU;AAC3C,YAAM,SAAS,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ,WAAW,KAAK,CAAC;AAIrE,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,cAAM,QAAQ,IAAI,KAAK;AACvB,gBAAQ,KAAK,OAAO,KAAK,MAAM,OAAO,QAAQ,KAAK,IAAI,CAAiB;AAAA,MAC5E;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEA,MAAM,QAAuB;AACzB,SAAK,YAAY;AAAA,EACrB;AACJ;","names":[]}