brainbank 0.1.0-beta.1
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/LICENSE +21 -0
- package/README.md +155 -0
- package/assets/architecture.png +0 -0
- package/bin/brainbank +18 -0
- package/bin/brainbank-mcp +19 -0
- package/dist/chunk-3YBCD6DI.js +117 -0
- package/dist/chunk-3YBCD6DI.js.map +1 -0
- package/dist/chunk-63GBCDS5.js +3249 -0
- package/dist/chunk-63GBCDS5.js.map +1 -0
- package/dist/chunk-DMFMTOHF.js +123 -0
- package/dist/chunk-DMFMTOHF.js.map +1 -0
- package/dist/chunk-FQYKWB2Q.js +136 -0
- package/dist/chunk-FQYKWB2Q.js.map +1 -0
- package/dist/chunk-IMJJ2VEM.js +74 -0
- package/dist/chunk-IMJJ2VEM.js.map +1 -0
- package/dist/chunk-M744PCJQ.js +43 -0
- package/dist/chunk-M744PCJQ.js.map +1 -0
- package/dist/chunk-O3J6ZIXK.js +82 -0
- package/dist/chunk-O3J6ZIXK.js.map +1 -0
- package/dist/chunk-OPH7GZ7U.js +124 -0
- package/dist/chunk-OPH7GZ7U.js.map +1 -0
- package/dist/chunk-PXEWQMN7.js +89 -0
- package/dist/chunk-PXEWQMN7.js.map +1 -0
- package/dist/chunk-RDQYDLYZ.js +69 -0
- package/dist/chunk-RDQYDLYZ.js.map +1 -0
- package/dist/chunk-VIIHPCC4.js +254 -0
- package/dist/chunk-VIIHPCC4.js.map +1 -0
- package/dist/chunk-WCQVDF3K.js +14 -0
- package/dist/chunk-WCQVDF3K.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +3076 -0
- package/dist/cli.js.map +1 -0
- package/dist/haiku-expander-YRSIPGKP.js +8 -0
- package/dist/haiku-expander-YRSIPGKP.js.map +1 -0
- package/dist/haiku-pruner-SHAXUPY6.js +8 -0
- package/dist/haiku-pruner-SHAXUPY6.js.map +1 -0
- package/dist/http-server-QUXHLWUM.js +9 -0
- package/dist/http-server-QUXHLWUM.js.map +1 -0
- package/dist/index.d.ts +2161 -0
- package/dist/index.js +357 -0
- package/dist/index.js.map +1 -0
- package/dist/local-embedding-NZQTILGV.js +8 -0
- package/dist/local-embedding-NZQTILGV.js.map +1 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +334 -0
- package/dist/mcp.js.map +1 -0
- package/dist/openai-embedding-ZP5TSUJG.js +8 -0
- package/dist/openai-embedding-ZP5TSUJG.js.map +1 -0
- package/dist/perplexity-context-embedding-GI5PHE6X.js +9 -0
- package/dist/perplexity-context-embedding-GI5PHE6X.js.map +1 -0
- package/dist/perplexity-embedding-KZRYGJRC.js +10 -0
- package/dist/perplexity-embedding-KZRYGJRC.js.map +1 -0
- package/dist/plugin-IKQ6IRSJ.js +32 -0
- package/dist/plugin-IKQ6IRSJ.js.map +1 -0
- package/dist/resolve-ASGLBNUC.js +10 -0
- package/dist/resolve-ASGLBNUC.js.map +1 -0
- package/dist/stats-tui-ZY2NQSEA.js +1904 -0
- package/dist/stats-tui-ZY2NQSEA.js.map +1 -0
- package/package.json +96 -0
- package/src/brainbank.ts +617 -0
- package/src/cli/commands/collection.ts +77 -0
- package/src/cli/commands/context.ts +179 -0
- package/src/cli/commands/daemon.ts +100 -0
- package/src/cli/commands/docs.ts +71 -0
- package/src/cli/commands/files.ts +69 -0
- package/src/cli/commands/help.ts +77 -0
- package/src/cli/commands/index.ts +482 -0
- package/src/cli/commands/kv.ts +140 -0
- package/src/cli/commands/mcp-export.ts +273 -0
- package/src/cli/commands/mcp.ts +6 -0
- package/src/cli/commands/reembed.ts +30 -0
- package/src/cli/commands/scan.ts +336 -0
- package/src/cli/commands/search.ts +203 -0
- package/src/cli/commands/stats.ts +68 -0
- package/src/cli/commands/status.ts +47 -0
- package/src/cli/commands/watch.ts +47 -0
- package/src/cli/factory/brain-context.ts +43 -0
- package/src/cli/factory/builtin-registration.ts +87 -0
- package/src/cli/factory/config-loader.ts +77 -0
- package/src/cli/factory/index.ts +69 -0
- package/src/cli/factory/plugin-loader.ts +325 -0
- package/src/cli/index.ts +71 -0
- package/src/cli/server-client.ts +178 -0
- package/src/cli/tui/index-tui.tsx +667 -0
- package/src/cli/tui/stats-data.ts +523 -0
- package/src/cli/tui/stats-search.ts +262 -0
- package/src/cli/tui/stats-tui.tsx +1465 -0
- package/src/cli/tui/tree-scanner.ts +650 -0
- package/src/cli/utils.ts +137 -0
- package/src/config.ts +49 -0
- package/src/constants.ts +21 -0
- package/src/db/adapter.ts +112 -0
- package/src/db/metadata.ts +130 -0
- package/src/db/migrations.ts +66 -0
- package/src/db/sqlite-adapter.ts +218 -0
- package/src/db/tracker.ts +91 -0
- package/src/engine/index-api.ts +81 -0
- package/src/engine/reembed.ts +206 -0
- package/src/engine/search-api.ts +218 -0
- package/src/index.ts +154 -0
- package/src/lib/fts.ts +57 -0
- package/src/lib/languages.ts +180 -0
- package/src/lib/logger.ts +126 -0
- package/src/lib/math.ts +87 -0
- package/src/lib/provider-key.ts +20 -0
- package/src/lib/prune.ts +71 -0
- package/src/lib/rrf.ts +133 -0
- package/src/lib/write-lock.ts +108 -0
- package/src/mcp/mcp-server.ts +195 -0
- package/src/mcp/workspace-factory.ts +68 -0
- package/src/mcp/workspace-pool.ts +224 -0
- package/src/plugin.ts +381 -0
- package/src/providers/embeddings/embedding-worker-thread.ts +95 -0
- package/src/providers/embeddings/embedding-worker.ts +141 -0
- package/src/providers/embeddings/local-embedding.ts +115 -0
- package/src/providers/embeddings/openai-embedding.ts +167 -0
- package/src/providers/embeddings/perplexity-context-embedding.ts +195 -0
- package/src/providers/embeddings/perplexity-embedding.ts +165 -0
- package/src/providers/embeddings/resolve.ts +34 -0
- package/src/providers/pruners/haiku-expander.ts +166 -0
- package/src/providers/pruners/haiku-pruner.ts +112 -0
- package/src/providers/vector/hnsw-index.ts +174 -0
- package/src/providers/vector/hnsw-loader.ts +129 -0
- package/src/search/bm25-boost.ts +69 -0
- package/src/search/context-builder.ts +251 -0
- package/src/search/keyword/composite-bm25-search.ts +47 -0
- package/src/search/types.ts +37 -0
- package/src/search/vector/composite-vector-search.ts +61 -0
- package/src/search/vector/mmr.ts +64 -0
- package/src/services/collection.ts +384 -0
- package/src/services/daemon.ts +87 -0
- package/src/services/http-server.ts +336 -0
- package/src/services/kv-service.ts +64 -0
- package/src/services/plugin-registry.ts +77 -0
- package/src/services/watch.ts +340 -0
- package/src/services/webhook-server.ts +100 -0
- package/src/types.ts +493 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BrainBank — Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* All interfaces and types for the semantic knowledge bank.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import type { CollectionItem, CollectionSearchOptions, CollectionAddOptions } from './services/collection.ts';
|
|
9
|
+
|
|
10
|
+
// Re-export collection types so consumers don't need to import from services/
|
|
11
|
+
export type { CollectionItem, CollectionSearchOptions, CollectionAddOptions };
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/** Public contract for a KV collection. Plugins depend on this interface, not the concrete class. */
|
|
15
|
+
export interface ICollection {
|
|
16
|
+
/** Collection name. */
|
|
17
|
+
readonly name: string;
|
|
18
|
+
/** Add an item. Returns its ID. */
|
|
19
|
+
add(content: string, options?: CollectionAddOptions | Record<string, unknown>): Promise<number>;
|
|
20
|
+
/** Update an item's content (re-embeds). Returns the new ID. */
|
|
21
|
+
update(id: number, content: string, options?: CollectionAddOptions): Promise<number>;
|
|
22
|
+
/** Add multiple items. Returns their IDs. */
|
|
23
|
+
addMany(items: { content: string; metadata?: Record<string, unknown>; tags?: string[]; ttl?: string }[]): Promise<number[]>;
|
|
24
|
+
/** Search this collection. */
|
|
25
|
+
search(query: string, options?: CollectionSearchOptions): Promise<CollectionItem[]>;
|
|
26
|
+
/** List items (newest first). */
|
|
27
|
+
list(options?: { limit?: number; offset?: number; tags?: string[] }): CollectionItem[];
|
|
28
|
+
/** Count items in this collection. */
|
|
29
|
+
count(): number;
|
|
30
|
+
/** Keep only the N most recent items. */
|
|
31
|
+
trim(options: { keep: number }): Promise<{ removed: number }>;
|
|
32
|
+
/** Remove items older than a duration string. */
|
|
33
|
+
prune(options: { olderThan: string }): Promise<{ removed: number }>;
|
|
34
|
+
/** Remove a specific item by ID. */
|
|
35
|
+
remove(id: number): void;
|
|
36
|
+
/** Clear all items in this collection. */
|
|
37
|
+
clear(): void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
export interface BrainBankConfig {
|
|
42
|
+
/** Root path of the repository to index. Default: '.' */
|
|
43
|
+
repoPath?: string;
|
|
44
|
+
/** SQLite database path. Default: '.brainbank/data/brainbank.db' */
|
|
45
|
+
dbPath?: string;
|
|
46
|
+
|
|
47
|
+
/** Max git commits to index. Default: 500 */
|
|
48
|
+
gitDepth?: number;
|
|
49
|
+
/** Max file size in bytes to index. Default: 512_000 (500KB) */
|
|
50
|
+
maxFileSize?: number;
|
|
51
|
+
/** Max diff bytes per commit. Default: 8192 */
|
|
52
|
+
maxDiffBytes?: number;
|
|
53
|
+
/** HNSW M parameter (connections per node). Default: 16 */
|
|
54
|
+
hnswM?: number;
|
|
55
|
+
/** HNSW efConstruction (build-time candidates). Default: 200 */
|
|
56
|
+
hnswEfConstruction?: number;
|
|
57
|
+
/** HNSW efSearch (query-time candidates). Default: 50 */
|
|
58
|
+
hnswEfSearch?: number;
|
|
59
|
+
/** Embedding dimensions. Default: 384 */
|
|
60
|
+
embeddingDims?: number;
|
|
61
|
+
/** Max HNSW elements. Default: 2_000_000 */
|
|
62
|
+
maxElements?: number;
|
|
63
|
+
/** Custom embedding provider (default: local WASM model) */
|
|
64
|
+
embeddingProvider?: EmbeddingProvider;
|
|
65
|
+
/** Optional LLM noise filter — drops irrelevant results before formatting */
|
|
66
|
+
pruner?: Pruner;
|
|
67
|
+
/** Optional LLM context expander — discovers additional relevant chunks after pruning */
|
|
68
|
+
expander?: Expander;
|
|
69
|
+
/** Port for optional webhook server (enables push-based watch plugins). */
|
|
70
|
+
webhookPort?: number;
|
|
71
|
+
/** Context field defaults from config.json "context" section. */
|
|
72
|
+
contextFields?: Record<string, unknown>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface ResolvedConfig {
|
|
76
|
+
repoPath: string;
|
|
77
|
+
dbPath: string;
|
|
78
|
+
gitDepth: number;
|
|
79
|
+
maxFileSize: number;
|
|
80
|
+
maxDiffBytes: number;
|
|
81
|
+
hnswM: number;
|
|
82
|
+
hnswEfConstruction: number;
|
|
83
|
+
hnswEfSearch: number;
|
|
84
|
+
embeddingDims: number;
|
|
85
|
+
maxElements: number;
|
|
86
|
+
embeddingProvider?: EmbeddingProvider;
|
|
87
|
+
pruner?: Pruner;
|
|
88
|
+
expander?: Expander;
|
|
89
|
+
webhookPort?: number;
|
|
90
|
+
/** Context field defaults from config.json "context" section. */
|
|
91
|
+
contextFields?: Record<string, unknown>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
export interface EmbeddingProvider {
|
|
96
|
+
/** Vector dimensions produced by this provider. */
|
|
97
|
+
readonly dims: number;
|
|
98
|
+
/** Embed a single text string. */
|
|
99
|
+
embed(text: string): Promise<Float32Array>;
|
|
100
|
+
/** Embed multiple texts (batch). */
|
|
101
|
+
embedBatch(texts: string[]): Promise<Float32Array[]>;
|
|
102
|
+
/** Release resources. */
|
|
103
|
+
close(): Promise<void>;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
/** Item passed to the pruner for noise classification. */
|
|
109
|
+
export interface PrunerItem {
|
|
110
|
+
/** Positional index (used to map back to SearchResult[]) */
|
|
111
|
+
id: number;
|
|
112
|
+
/** File path — primary signal for relevance */
|
|
113
|
+
filePath: string;
|
|
114
|
+
/** Trimmed content preview */
|
|
115
|
+
preview: string;
|
|
116
|
+
/** Chunk metadata (type, name, language, lines, etc.) */
|
|
117
|
+
metadata: Record<string, unknown>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface Pruner {
|
|
121
|
+
/**
|
|
122
|
+
* Filter noise from search results and order by semantic relevance.
|
|
123
|
+
* @param query - The search query
|
|
124
|
+
* @param items - Items to evaluate (filePath + metadata + trimmed preview)
|
|
125
|
+
* @returns Array of item IDs to KEEP, ordered by relevance to the query
|
|
126
|
+
* (most relevant first). Everything else is dropped.
|
|
127
|
+
*/
|
|
128
|
+
prune(query: string, items: PrunerItem[]): Promise<number[]>;
|
|
129
|
+
/** Release resources. */
|
|
130
|
+
close?(): Promise<void>;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Lightweight chunk descriptor for the expander manifest. */
|
|
134
|
+
export interface ExpanderManifestItem {
|
|
135
|
+
/** Chunk ID (code_chunks.id) */
|
|
136
|
+
id: number;
|
|
137
|
+
/** File path */
|
|
138
|
+
filePath: string;
|
|
139
|
+
/** Chunk name (e.g. function/class name) */
|
|
140
|
+
name: string;
|
|
141
|
+
/** Chunk type (function, class, method, etc.) */
|
|
142
|
+
chunkType: string;
|
|
143
|
+
/** Line range (e.g. "L45-L89") */
|
|
144
|
+
lines: string;
|
|
145
|
+
/** True if this chunk is from an import-graph neighbor of the search results. */
|
|
146
|
+
priority?: boolean;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Result from the expander: chunk IDs to add + optional free-text note. */
|
|
150
|
+
export interface ExpanderResult {
|
|
151
|
+
/** Additional chunk IDs to splice into results. */
|
|
152
|
+
ids: number[];
|
|
153
|
+
/** Brief observation for the agent (e.g. "file X not found", "module Y is deprecated"). */
|
|
154
|
+
note?: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface Expander {
|
|
158
|
+
/**
|
|
159
|
+
* Given a task and a manifest of available chunks,
|
|
160
|
+
* return additional chunk IDs + an optional contextual note.
|
|
161
|
+
* Runs after pruning. Fail-open: errors return empty result.
|
|
162
|
+
*
|
|
163
|
+
* @param query - The search query / task description
|
|
164
|
+
* @param currentIds - IDs of chunks already in results (from search + prune)
|
|
165
|
+
* @param manifest - All available chunks (lightweight descriptors)
|
|
166
|
+
* @returns Chunk IDs to add + optional note
|
|
167
|
+
*/
|
|
168
|
+
expand(query: string, currentIds: number[], manifest: ExpanderManifestItem[]): Promise<ExpanderResult>;
|
|
169
|
+
/** Release resources. */
|
|
170
|
+
close?(): Promise<void>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
export interface SearchHit {
|
|
175
|
+
id: number;
|
|
176
|
+
score: number;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface VectorIndex {
|
|
180
|
+
/** Initialize the index. Must be called before add/search. */
|
|
181
|
+
init(): Promise<this>;
|
|
182
|
+
/** Add a vector with an integer ID. Idempotent: duplicate IDs are skipped. */
|
|
183
|
+
add(vector: Float32Array, id: number): void;
|
|
184
|
+
/** Mark a vector as deleted so it no longer appears in searches. */
|
|
185
|
+
remove(id: number): void;
|
|
186
|
+
/** Search for k nearest neighbors. */
|
|
187
|
+
search(query: Float32Array, k: number): SearchHit[];
|
|
188
|
+
/** Clear all vectors and reset to empty state. */
|
|
189
|
+
reinit(): void;
|
|
190
|
+
/** Number of vectors in the index. */
|
|
191
|
+
readonly size: number;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
export interface CodeChunk {
|
|
196
|
+
/** Auto-incremented DB id (set after insert) */
|
|
197
|
+
id?: number;
|
|
198
|
+
/** Relative file path from repo root */
|
|
199
|
+
filePath: string;
|
|
200
|
+
/** Chunk type: 'file' | 'function' | 'class' | 'block' */
|
|
201
|
+
chunkType: string;
|
|
202
|
+
/** Function/class name (if detected) */
|
|
203
|
+
name?: string;
|
|
204
|
+
/** Start line (1-indexed) */
|
|
205
|
+
startLine: number;
|
|
206
|
+
/** End line (1-indexed, inclusive) */
|
|
207
|
+
endLine: number;
|
|
208
|
+
/** Raw content of the chunk */
|
|
209
|
+
content: string;
|
|
210
|
+
/** Language identifier */
|
|
211
|
+
language: string;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
export interface GitCommitRecord {
|
|
216
|
+
id?: number;
|
|
217
|
+
hash: string;
|
|
218
|
+
shortHash: string;
|
|
219
|
+
message: string;
|
|
220
|
+
author: string;
|
|
221
|
+
date: string;
|
|
222
|
+
timestamp: number;
|
|
223
|
+
filesChanged: string[];
|
|
224
|
+
diff?: string;
|
|
225
|
+
additions: number;
|
|
226
|
+
deletions: number;
|
|
227
|
+
isMerge: boolean;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
export type SearchResultType = 'code' | 'commit' | 'document' | 'collection';
|
|
235
|
+
|
|
236
|
+
// Typed metadata per result type
|
|
237
|
+
|
|
238
|
+
export interface CodeResultMetadata {
|
|
239
|
+
/** Database chunk ID (used by call graph annotations). */
|
|
240
|
+
id?: number;
|
|
241
|
+
/** File path (may duplicate CodeResult.filePath for metadata-only access). */
|
|
242
|
+
filePath?: string;
|
|
243
|
+
/** Adjacent chunk IDs from the same file (used by context expansion). */
|
|
244
|
+
chunkIds?: number[];
|
|
245
|
+
chunkType: string;
|
|
246
|
+
name?: string;
|
|
247
|
+
startLine: number;
|
|
248
|
+
endLine: number;
|
|
249
|
+
language: string;
|
|
250
|
+
searchType?: string;
|
|
251
|
+
rrfScore?: number;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export interface CommitResultMetadata {
|
|
255
|
+
hash: string;
|
|
256
|
+
shortHash: string;
|
|
257
|
+
author: string;
|
|
258
|
+
date: string;
|
|
259
|
+
files: string[];
|
|
260
|
+
additions?: number;
|
|
261
|
+
deletions?: number;
|
|
262
|
+
diff?: string;
|
|
263
|
+
searchType?: string;
|
|
264
|
+
rrfScore?: number;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
export interface DocumentResultMetadata {
|
|
270
|
+
collection?: string;
|
|
271
|
+
title?: string;
|
|
272
|
+
seq?: number;
|
|
273
|
+
path?: string;
|
|
274
|
+
searchType?: string;
|
|
275
|
+
/** Internal chunk ID used by hybrid search to map fused results. */
|
|
276
|
+
chunkId?: number;
|
|
277
|
+
rrfScore?: number;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Discriminated union
|
|
281
|
+
|
|
282
|
+
export interface CodeResult {
|
|
283
|
+
type: 'code';
|
|
284
|
+
score: number;
|
|
285
|
+
filePath: string;
|
|
286
|
+
content: string;
|
|
287
|
+
context?: string;
|
|
288
|
+
metadata: CodeResultMetadata;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export interface CommitResult {
|
|
292
|
+
type: 'commit';
|
|
293
|
+
score: number;
|
|
294
|
+
filePath?: string;
|
|
295
|
+
content: string;
|
|
296
|
+
context?: string;
|
|
297
|
+
metadata: CommitResultMetadata;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
export interface DocumentResult {
|
|
303
|
+
type: 'document';
|
|
304
|
+
score: number;
|
|
305
|
+
filePath: string;
|
|
306
|
+
content: string;
|
|
307
|
+
context?: string;
|
|
308
|
+
metadata: DocumentResultMetadata;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export interface CollectionResultMetadata {
|
|
312
|
+
id?: number;
|
|
313
|
+
collection?: string;
|
|
314
|
+
rrfScore?: number;
|
|
315
|
+
[key: string]: unknown;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export interface CollectionResult {
|
|
319
|
+
type: 'collection';
|
|
320
|
+
score: number;
|
|
321
|
+
filePath?: string;
|
|
322
|
+
content: string;
|
|
323
|
+
context?: string;
|
|
324
|
+
metadata: CollectionResultMetadata;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export type SearchResult = CodeResult | CommitResult | DocumentResult | CollectionResult;
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
/** Narrow a SearchResult to CodeResult. */
|
|
331
|
+
export function isCodeResult(r: SearchResult): r is CodeResult {
|
|
332
|
+
return r.type === 'code';
|
|
333
|
+
}
|
|
334
|
+
/** Narrow a SearchResult to CommitResult. */
|
|
335
|
+
export function isCommitResult(r: SearchResult): r is CommitResult {
|
|
336
|
+
return r.type === 'commit';
|
|
337
|
+
}
|
|
338
|
+
/** Narrow a SearchResult to DocumentResult. */
|
|
339
|
+
export function isDocumentResult(r: SearchResult): r is DocumentResult {
|
|
340
|
+
return r.type === 'document';
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/** Narrow a SearchResult to CollectionResult. */
|
|
344
|
+
export function isCollectionResult(r: SearchResult): r is CollectionResult {
|
|
345
|
+
return r.type === 'collection';
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
type MatchHandlers<T> = {
|
|
350
|
+
code?: (r: CodeResult) => T;
|
|
351
|
+
commit?: (r: CommitResult) => T;
|
|
352
|
+
document?: (r: DocumentResult) => T;
|
|
353
|
+
collection?: (r: CollectionResult) => T;
|
|
354
|
+
_?: (r: SearchResult) => T;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Pattern-match on SearchResult type. Calls the matching handler
|
|
359
|
+
* or the `_` fallback. Returns undefined if no handler matches.
|
|
360
|
+
*/
|
|
361
|
+
export function matchResult<T>(
|
|
362
|
+
result: SearchResult,
|
|
363
|
+
handlers: MatchHandlers<T>,
|
|
364
|
+
): T | undefined {
|
|
365
|
+
switch (result.type) {
|
|
366
|
+
case 'code': return (handlers.code ?? handlers._)?.(result);
|
|
367
|
+
case 'commit': return (handlers.commit ?? handlers._)?.(result);
|
|
368
|
+
case 'document': return (handlers.document ?? handlers._)?.(result);
|
|
369
|
+
case 'collection': return (handlers.collection ?? handlers._)?.(result);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
export interface ContextOptions {
|
|
375
|
+
/** Per-source result limits. Built-in: 'code', 'git'. Default: { code: 6, git: 5 } */
|
|
376
|
+
sources?: Record<string, number>;
|
|
377
|
+
/** Files the agent is about to modify (improves co-edit suggestions) */
|
|
378
|
+
affectedFiles?: string[];
|
|
379
|
+
/** Minimum similarity score threshold. Default: 0.25 */
|
|
380
|
+
minScore?: number;
|
|
381
|
+
/** Use MMR for diversity. Default: true */
|
|
382
|
+
useMMR?: boolean;
|
|
383
|
+
/** MMR lambda (0 = diversity, 1 = relevance). Default: 0.7 */
|
|
384
|
+
mmrLambda?: number;
|
|
385
|
+
/** Filter results to files under these path prefixes (e.g. 'src/services/' or ['src/', 'lib/']). */
|
|
386
|
+
pathPrefix?: string | string[];
|
|
387
|
+
/** Exclude results whose filePath starts with any of these prefixes (e.g. ['src/tests/', 'src/mocks/']). */
|
|
388
|
+
ignorePaths?: string[];
|
|
389
|
+
/** File paths to exclude from results (e.g. files already returned in a previous query). */
|
|
390
|
+
excludeFiles?: Set<string>;
|
|
391
|
+
/** Optional per-request pruner override (e.g. HaikuPruner for LLM noise filtering). */
|
|
392
|
+
pruner?: Pruner;
|
|
393
|
+
/** Caller origin for debug logging. */
|
|
394
|
+
source?: 'cli' | 'mcp' | 'daemon' | 'api';
|
|
395
|
+
/**
|
|
396
|
+
* Context field overrides. Merged on top of config.json "context" defaults.
|
|
397
|
+
* Plugin-defined fields like `lines`, `callTree`, `symbols`, `compact`, `imports`.
|
|
398
|
+
* Example: `{ lines: true, callTree: { depth: 3 }, symbols: true }`
|
|
399
|
+
*/
|
|
400
|
+
fields?: Record<string, unknown>;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
export interface DocumentCollection {
|
|
405
|
+
/** Collection name (e.g. 'notes', 'docs') */
|
|
406
|
+
name: string;
|
|
407
|
+
/** Directory path to index */
|
|
408
|
+
path: string;
|
|
409
|
+
/** Glob pattern for files (default: all markdown) */
|
|
410
|
+
pattern?: string;
|
|
411
|
+
/** Glob patterns to ignore */
|
|
412
|
+
ignore?: string[];
|
|
413
|
+
/** Context description for this collection */
|
|
414
|
+
context?: string;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export interface DocChunk {
|
|
418
|
+
id?: number;
|
|
419
|
+
/** Collection name */
|
|
420
|
+
collection: string;
|
|
421
|
+
/** Relative file path within the collection */
|
|
422
|
+
filePath: string;
|
|
423
|
+
/** Document title (first heading or filename) */
|
|
424
|
+
title: string;
|
|
425
|
+
/** Chunk content */
|
|
426
|
+
content: string;
|
|
427
|
+
/** Chunk sequence within the document (0, 1, 2...) */
|
|
428
|
+
seq: number;
|
|
429
|
+
/** Character position in original document */
|
|
430
|
+
pos: number;
|
|
431
|
+
/** Content hash for incremental updates */
|
|
432
|
+
contentHash: string;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
/** Plugin-provided stats. Key is the plugin name. */
|
|
437
|
+
export interface IndexStats {
|
|
438
|
+
[pluginName: string]: Record<string, number | string> | undefined;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
/** File-level progress (used by indexers). */
|
|
443
|
+
export type ProgressCallback = (file: string, current: number, total: number) => void;
|
|
444
|
+
|
|
445
|
+
/** Stage-level progress (used by BrainBank.index() orchestrator). */
|
|
446
|
+
export type StageProgressCallback = (stage: string, message: string) => void;
|
|
447
|
+
|
|
448
|
+
export interface IndexResult {
|
|
449
|
+
indexed: number;
|
|
450
|
+
skipped: number;
|
|
451
|
+
chunks?: number;
|
|
452
|
+
removed?: number;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
export interface CoEditSuggestion {
|
|
457
|
+
file: string;
|
|
458
|
+
count: number;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
/** Generalized watch event — works for files, APIs, webhooks. */
|
|
463
|
+
export interface WatchEvent {
|
|
464
|
+
/** Event type. 'sync' is for batch/poll sources that don't distinguish CRUD. */
|
|
465
|
+
type: 'create' | 'update' | 'delete' | 'sync';
|
|
466
|
+
/** Unique ID of the changed item (file path, PR#123, PROJ-456, etc.). */
|
|
467
|
+
sourceId: string;
|
|
468
|
+
/** Source descriptor (e.g. 'file', 'github:pr', 'jira:card'). */
|
|
469
|
+
sourceName: string;
|
|
470
|
+
/** Optional raw payload to avoid re-fetching. */
|
|
471
|
+
payload?: unknown;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/** Callback that plugins invoke when they detect a change. */
|
|
475
|
+
export type WatchEventHandler = (event: WatchEvent) => void;
|
|
476
|
+
|
|
477
|
+
/** Lifecycle handle returned by WatchablePlugin.watch(). */
|
|
478
|
+
export interface WatchHandle {
|
|
479
|
+
/** Stop watching and release resources. */
|
|
480
|
+
stop(): Promise<void>;
|
|
481
|
+
/** Whether the watcher is still active. */
|
|
482
|
+
readonly active: boolean;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/** Optional hints from plugin to core — debounce, batching, priority. */
|
|
486
|
+
export interface WatchConfig {
|
|
487
|
+
/** Debounce interval in ms. 0 = process immediately. Default: inherited from WatchOptions. */
|
|
488
|
+
debounceMs?: number;
|
|
489
|
+
/** Max events to batch before triggering re-index. Default: unlimited. */
|
|
490
|
+
batchSize?: number;
|
|
491
|
+
/** Processing priority. Default: 'realtime'. */
|
|
492
|
+
priority?: 'realtime' | 'background';
|
|
493
|
+
}
|