bluera-knowledge 0.14.8 → 0.15.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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +13 -0
- package/dist/{chunk-SWHYQLSJ.js → chunk-DX5I6U5X.js} +36 -231
- package/dist/chunk-DX5I6U5X.js.map +1 -0
- package/dist/{chunk-TGMFSPTQ.js → chunk-OMC3RAZT.js} +2 -2
- package/dist/{chunk-5VW5DNW4.js → chunk-WYZQUKUD.js} +523 -106
- package/dist/chunk-WYZQUKUD.js.map +1 -0
- package/dist/index.js +7 -7
- package/dist/mcp/server.d.ts +859 -1
- package/dist/mcp/server.js +2 -2
- package/dist/workers/background-worker-cli.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-5VW5DNW4.js.map +0 -1
- package/dist/chunk-SWHYQLSJ.js.map +0 -1
- /package/dist/{chunk-TGMFSPTQ.js.map → chunk-OMC3RAZT.js.map} +0 -0
package/dist/mcp/server.d.ts
CHANGED
|
@@ -1,4 +1,847 @@
|
|
|
1
1
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
interface CodeNode {
|
|
5
|
+
type: 'function' | 'class' | 'interface' | 'type' | 'const';
|
|
6
|
+
name: string;
|
|
7
|
+
exported: boolean;
|
|
8
|
+
async?: boolean;
|
|
9
|
+
startLine: number;
|
|
10
|
+
endLine: number;
|
|
11
|
+
signature?: string;
|
|
12
|
+
methods?: Array<{
|
|
13
|
+
name: string;
|
|
14
|
+
async: boolean;
|
|
15
|
+
signature: string;
|
|
16
|
+
startLine: number;
|
|
17
|
+
endLine: number;
|
|
18
|
+
}>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface GraphNode {
|
|
22
|
+
id: string;
|
|
23
|
+
file: string;
|
|
24
|
+
type: 'function' | 'class' | 'interface' | 'type' | 'const' | 'method';
|
|
25
|
+
name: string;
|
|
26
|
+
exported: boolean;
|
|
27
|
+
startLine: number;
|
|
28
|
+
endLine: number;
|
|
29
|
+
signature?: string;
|
|
30
|
+
}
|
|
31
|
+
interface GraphEdge {
|
|
32
|
+
from: string;
|
|
33
|
+
to: string;
|
|
34
|
+
type: 'calls' | 'imports' | 'extends' | 'implements';
|
|
35
|
+
confidence: number;
|
|
36
|
+
}
|
|
37
|
+
declare class CodeGraph {
|
|
38
|
+
private readonly nodes;
|
|
39
|
+
private readonly edges;
|
|
40
|
+
addNodes(nodes: CodeNode[], file: string): void;
|
|
41
|
+
addImport(fromFile: string, toFile: string, specifiers: string[]): void;
|
|
42
|
+
analyzeCallRelationships(code: string, file: string, functionName: string): void;
|
|
43
|
+
getNode(id: string): GraphNode | undefined;
|
|
44
|
+
getEdges(nodeId: string): GraphEdge[];
|
|
45
|
+
/**
|
|
46
|
+
* Add an edge to the graph (used when restoring from serialized data)
|
|
47
|
+
*/
|
|
48
|
+
addEdge(edge: GraphEdge): void;
|
|
49
|
+
/**
|
|
50
|
+
* Add a graph node directly (used when restoring from serialized data)
|
|
51
|
+
*/
|
|
52
|
+
addGraphNode(node: GraphNode): void;
|
|
53
|
+
/**
|
|
54
|
+
* Get edges where this node is the target (callers of this function)
|
|
55
|
+
*/
|
|
56
|
+
getIncomingEdges(nodeId: string): GraphEdge[];
|
|
57
|
+
/**
|
|
58
|
+
* Count how many nodes call this node
|
|
59
|
+
*/
|
|
60
|
+
getCalledByCount(nodeId: string): number;
|
|
61
|
+
/**
|
|
62
|
+
* Count how many nodes this node calls
|
|
63
|
+
*/
|
|
64
|
+
getCallsCount(nodeId: string): number;
|
|
65
|
+
getAllNodes(): GraphNode[];
|
|
66
|
+
private findNodeByName;
|
|
67
|
+
private resolveImportPath;
|
|
68
|
+
toJSON(): {
|
|
69
|
+
nodes: GraphNode[];
|
|
70
|
+
edges: Array<{
|
|
71
|
+
from: string;
|
|
72
|
+
to: string;
|
|
73
|
+
type: string;
|
|
74
|
+
confidence: number;
|
|
75
|
+
}>;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
declare const CrawlResultSchema: z.ZodObject<{
|
|
80
|
+
pages: z.ZodArray<z.ZodObject<{
|
|
81
|
+
url: z.ZodString;
|
|
82
|
+
title: z.ZodString;
|
|
83
|
+
content: z.ZodString;
|
|
84
|
+
links: z.ZodArray<z.ZodString>;
|
|
85
|
+
crawledAt: z.ZodString;
|
|
86
|
+
}, z.core.$strip>>;
|
|
87
|
+
}, z.core.$strip>;
|
|
88
|
+
declare const HeadlessResultSchema: z.ZodObject<{
|
|
89
|
+
html: z.ZodString;
|
|
90
|
+
markdown: z.ZodString;
|
|
91
|
+
links: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
92
|
+
href: z.ZodString;
|
|
93
|
+
text: z.ZodString;
|
|
94
|
+
title: z.ZodOptional<z.ZodString>;
|
|
95
|
+
base_domain: z.ZodOptional<z.ZodString>;
|
|
96
|
+
head_data: z.ZodOptional<z.ZodUnknown>;
|
|
97
|
+
head_extraction_status: z.ZodOptional<z.ZodUnknown>;
|
|
98
|
+
head_extraction_error: z.ZodOptional<z.ZodUnknown>;
|
|
99
|
+
intrinsic_score: z.ZodOptional<z.ZodNumber>;
|
|
100
|
+
contextual_score: z.ZodOptional<z.ZodUnknown>;
|
|
101
|
+
total_score: z.ZodOptional<z.ZodUnknown>;
|
|
102
|
+
}, z.core.$strip>, z.ZodString]>>;
|
|
103
|
+
}, z.core.$strip>;
|
|
104
|
+
type CrawlResult = z.infer<typeof CrawlResultSchema>;
|
|
105
|
+
type HeadlessResult = z.infer<typeof HeadlessResultSchema>;
|
|
106
|
+
declare const ParsePythonResultSchema: z.ZodObject<{
|
|
107
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
108
|
+
type: z.ZodEnum<{
|
|
109
|
+
function: "function";
|
|
110
|
+
class: "class";
|
|
111
|
+
}>;
|
|
112
|
+
name: z.ZodString;
|
|
113
|
+
exported: z.ZodBoolean;
|
|
114
|
+
startLine: z.ZodNumber;
|
|
115
|
+
endLine: z.ZodNumber;
|
|
116
|
+
async: z.ZodOptional<z.ZodBoolean>;
|
|
117
|
+
signature: z.ZodOptional<z.ZodString>;
|
|
118
|
+
calls: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
119
|
+
methods: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
120
|
+
name: z.ZodString;
|
|
121
|
+
async: z.ZodBoolean;
|
|
122
|
+
signature: z.ZodString;
|
|
123
|
+
startLine: z.ZodNumber;
|
|
124
|
+
endLine: z.ZodNumber;
|
|
125
|
+
calls: z.ZodArray<z.ZodString>;
|
|
126
|
+
}, z.core.$strip>>>;
|
|
127
|
+
}, z.core.$strip>>;
|
|
128
|
+
imports: z.ZodArray<z.ZodObject<{
|
|
129
|
+
source: z.ZodString;
|
|
130
|
+
imported: z.ZodString;
|
|
131
|
+
alias: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
132
|
+
}, z.core.$strip>>;
|
|
133
|
+
}, z.core.$strip>;
|
|
134
|
+
type ParsePythonResult = z.infer<typeof ParsePythonResultSchema>;
|
|
135
|
+
|
|
136
|
+
declare class PythonBridge {
|
|
137
|
+
private process;
|
|
138
|
+
private readonly pending;
|
|
139
|
+
private stoppingIntentionally;
|
|
140
|
+
private stdoutReadline;
|
|
141
|
+
private stderrReadline;
|
|
142
|
+
start(): Promise<void>;
|
|
143
|
+
crawl(url: string, timeoutMs?: number): Promise<CrawlResult>;
|
|
144
|
+
fetchHeadless(url: string, timeoutMs?: number): Promise<HeadlessResult>;
|
|
145
|
+
parsePython(code: string, filePath: string, timeoutMs?: number): Promise<ParsePythonResult>;
|
|
146
|
+
stop(): Promise<void>;
|
|
147
|
+
private rejectAllPending;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
declare const StoreIdBrand: unique symbol;
|
|
151
|
+
declare const DocumentIdBrand: unique symbol;
|
|
152
|
+
type StoreId = string & {
|
|
153
|
+
readonly [StoreIdBrand]: typeof StoreIdBrand;
|
|
154
|
+
};
|
|
155
|
+
type DocumentId = string & {
|
|
156
|
+
readonly [DocumentIdBrand]: typeof DocumentIdBrand;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Service for building, persisting, and querying code graphs.
|
|
161
|
+
* Code graphs track relationships between code elements (functions, classes, etc.)
|
|
162
|
+
* for enhanced search context.
|
|
163
|
+
*/
|
|
164
|
+
declare class CodeGraphService {
|
|
165
|
+
private readonly dataDir;
|
|
166
|
+
private readonly parser;
|
|
167
|
+
private readonly parserFactory;
|
|
168
|
+
private readonly graphCache;
|
|
169
|
+
constructor(dataDir: string, pythonBridge?: PythonBridge);
|
|
170
|
+
/**
|
|
171
|
+
* Build a code graph from source files.
|
|
172
|
+
*/
|
|
173
|
+
buildGraph(files: Array<{
|
|
174
|
+
path: string;
|
|
175
|
+
content: string;
|
|
176
|
+
}>): Promise<CodeGraph>;
|
|
177
|
+
/**
|
|
178
|
+
* Save a code graph for a store.
|
|
179
|
+
*/
|
|
180
|
+
saveGraph(storeId: StoreId, graph: CodeGraph): Promise<void>;
|
|
181
|
+
/**
|
|
182
|
+
* Delete the code graph file for a store.
|
|
183
|
+
* Silently succeeds if the file doesn't exist.
|
|
184
|
+
*/
|
|
185
|
+
deleteGraph(storeId: StoreId): Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* Load a code graph for a store.
|
|
188
|
+
* Returns undefined if no graph exists.
|
|
189
|
+
*/
|
|
190
|
+
loadGraph(storeId: StoreId): Promise<CodeGraph | undefined>;
|
|
191
|
+
/**
|
|
192
|
+
* Get usage stats for a code element.
|
|
193
|
+
*/
|
|
194
|
+
getUsageStats(graph: CodeGraph, filePath: string, symbolName: string): {
|
|
195
|
+
calledBy: number;
|
|
196
|
+
calls: number;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Get related code (callers and callees) for a code element.
|
|
200
|
+
*/
|
|
201
|
+
getRelatedCode(graph: CodeGraph, filePath: string, symbolName: string): Array<{
|
|
202
|
+
id: string;
|
|
203
|
+
relationship: string;
|
|
204
|
+
}>;
|
|
205
|
+
/**
|
|
206
|
+
* Clear cached graphs.
|
|
207
|
+
*/
|
|
208
|
+
clearCache(): void;
|
|
209
|
+
private getGraphPath;
|
|
210
|
+
/**
|
|
211
|
+
* Type guard for SerializedGraph structure.
|
|
212
|
+
*/
|
|
213
|
+
private isSerializedGraph;
|
|
214
|
+
/**
|
|
215
|
+
* Type guard for valid node types.
|
|
216
|
+
*/
|
|
217
|
+
private isValidNodeType;
|
|
218
|
+
/**
|
|
219
|
+
* Validate and return a node type, or undefined if invalid.
|
|
220
|
+
*/
|
|
221
|
+
private validateNodeType;
|
|
222
|
+
/**
|
|
223
|
+
* Type guard for valid edge types.
|
|
224
|
+
*/
|
|
225
|
+
private isValidEdgeType;
|
|
226
|
+
/**
|
|
227
|
+
* Validate and return an edge type, or undefined if invalid.
|
|
228
|
+
*/
|
|
229
|
+
private validateEdgeType;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
interface EmbeddingConfig {
|
|
233
|
+
readonly model: string;
|
|
234
|
+
readonly batchSize: number;
|
|
235
|
+
readonly dimensions: number;
|
|
236
|
+
}
|
|
237
|
+
interface IndexingConfig {
|
|
238
|
+
readonly concurrency: number;
|
|
239
|
+
readonly chunkSize: number;
|
|
240
|
+
readonly chunkOverlap: number;
|
|
241
|
+
readonly ignorePatterns: readonly string[];
|
|
242
|
+
}
|
|
243
|
+
interface SearchConfig {
|
|
244
|
+
readonly defaultMode: 'vector' | 'fts' | 'hybrid';
|
|
245
|
+
readonly defaultLimit: number;
|
|
246
|
+
readonly minScore: number;
|
|
247
|
+
readonly rrf: {
|
|
248
|
+
readonly k: number;
|
|
249
|
+
readonly vectorWeight: number;
|
|
250
|
+
readonly ftsWeight: number;
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
interface CrawlConfig {
|
|
254
|
+
readonly userAgent: string;
|
|
255
|
+
readonly timeout: number;
|
|
256
|
+
readonly maxConcurrency: number;
|
|
257
|
+
}
|
|
258
|
+
interface ServerConfig {
|
|
259
|
+
readonly port: number;
|
|
260
|
+
readonly host: string;
|
|
261
|
+
}
|
|
262
|
+
interface AppConfig {
|
|
263
|
+
readonly version: number;
|
|
264
|
+
readonly dataDir: string;
|
|
265
|
+
readonly embedding: EmbeddingConfig;
|
|
266
|
+
readonly indexing: IndexingConfig;
|
|
267
|
+
readonly search: SearchConfig;
|
|
268
|
+
readonly crawl: CrawlConfig;
|
|
269
|
+
readonly server: ServerConfig;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
declare class ConfigService {
|
|
273
|
+
private readonly configPath;
|
|
274
|
+
private readonly dataDir;
|
|
275
|
+
private config;
|
|
276
|
+
constructor(configPath?: string, dataDir?: string, projectRoot?: string);
|
|
277
|
+
load(): Promise<AppConfig>;
|
|
278
|
+
save(config: AppConfig): Promise<void>;
|
|
279
|
+
resolveDataDir(): string;
|
|
280
|
+
private expandPath;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
declare class EmbeddingEngine {
|
|
284
|
+
private extractor;
|
|
285
|
+
private readonly modelName;
|
|
286
|
+
private readonly dimensions;
|
|
287
|
+
constructor(modelName?: string, dimensions?: number);
|
|
288
|
+
initialize(): Promise<void>;
|
|
289
|
+
embed(text: string): Promise<number[]>;
|
|
290
|
+
embedBatch(texts: string[]): Promise<number[][]>;
|
|
291
|
+
getDimensions(): number;
|
|
292
|
+
/**
|
|
293
|
+
* Dispose the embedding pipeline to free resources.
|
|
294
|
+
* Should be called before process exit to prevent ONNX runtime cleanup issues on macOS.
|
|
295
|
+
*/
|
|
296
|
+
dispose(): Promise<void>;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
declare const DocumentTypeSchema: z.ZodEnum<{
|
|
300
|
+
file: "file";
|
|
301
|
+
web: "web";
|
|
302
|
+
chunk: "chunk";
|
|
303
|
+
}>;
|
|
304
|
+
type DocumentType = z.infer<typeof DocumentTypeSchema>;
|
|
305
|
+
interface DocumentMetadata {
|
|
306
|
+
readonly path?: string | undefined;
|
|
307
|
+
readonly url?: string | undefined;
|
|
308
|
+
readonly type: DocumentType;
|
|
309
|
+
readonly storeId: StoreId;
|
|
310
|
+
readonly indexedAt: Date;
|
|
311
|
+
readonly fileHash?: string | undefined;
|
|
312
|
+
readonly chunkIndex?: number | undefined;
|
|
313
|
+
readonly totalChunks?: number | undefined;
|
|
314
|
+
readonly [key: string]: unknown;
|
|
315
|
+
}
|
|
316
|
+
interface Document {
|
|
317
|
+
readonly id: DocumentId;
|
|
318
|
+
readonly content: string;
|
|
319
|
+
readonly vector: readonly number[];
|
|
320
|
+
readonly metadata: DocumentMetadata;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
declare class LanceStore {
|
|
324
|
+
private connection;
|
|
325
|
+
private readonly tables;
|
|
326
|
+
private readonly dataDir;
|
|
327
|
+
constructor(dataDir: string);
|
|
328
|
+
initialize(storeId: StoreId): Promise<void>;
|
|
329
|
+
addDocuments(storeId: StoreId, documents: Document[]): Promise<void>;
|
|
330
|
+
deleteDocuments(storeId: StoreId, documentIds: DocumentId[]): Promise<void>;
|
|
331
|
+
search(storeId: StoreId, vector: number[], limit: number, _threshold?: number): Promise<Array<{
|
|
332
|
+
id: DocumentId;
|
|
333
|
+
content: string;
|
|
334
|
+
score: number;
|
|
335
|
+
metadata: DocumentMetadata;
|
|
336
|
+
}>>;
|
|
337
|
+
createFtsIndex(storeId: StoreId): Promise<void>;
|
|
338
|
+
fullTextSearch(storeId: StoreId, query: string, limit: number): Promise<Array<{
|
|
339
|
+
id: DocumentId;
|
|
340
|
+
content: string;
|
|
341
|
+
score: number;
|
|
342
|
+
metadata: DocumentMetadata;
|
|
343
|
+
}>>;
|
|
344
|
+
deleteStore(storeId: StoreId): Promise<void>;
|
|
345
|
+
close(): void;
|
|
346
|
+
/**
|
|
347
|
+
* Async close for API consistency. Calls sync close() internally.
|
|
348
|
+
* Do NOT call process.exit() after this - let the event loop drain
|
|
349
|
+
* naturally so native threads can complete cleanup.
|
|
350
|
+
*/
|
|
351
|
+
closeAsync(): Promise<void>;
|
|
352
|
+
private getTableName;
|
|
353
|
+
private getTable;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
interface ProgressEvent {
|
|
357
|
+
type: 'start' | 'progress' | 'complete' | 'error';
|
|
358
|
+
current: number;
|
|
359
|
+
total: number;
|
|
360
|
+
message: string;
|
|
361
|
+
details?: Record<string, unknown>;
|
|
362
|
+
}
|
|
363
|
+
type ProgressCallback = (event: ProgressEvent) => void;
|
|
364
|
+
|
|
365
|
+
type Result<T, E = Error> = {
|
|
366
|
+
readonly success: true;
|
|
367
|
+
readonly data: T;
|
|
368
|
+
} | {
|
|
369
|
+
readonly success: false;
|
|
370
|
+
readonly error: E;
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
type StoreType = 'file' | 'repo' | 'web';
|
|
374
|
+
type StoreStatus = 'ready' | 'indexing' | 'error';
|
|
375
|
+
interface BaseStore {
|
|
376
|
+
readonly id: StoreId;
|
|
377
|
+
readonly name: string;
|
|
378
|
+
readonly description?: string | undefined;
|
|
379
|
+
readonly tags?: readonly string[] | undefined;
|
|
380
|
+
readonly status?: StoreStatus | undefined;
|
|
381
|
+
readonly createdAt: Date;
|
|
382
|
+
readonly updatedAt: Date;
|
|
383
|
+
}
|
|
384
|
+
interface FileStore extends BaseStore {
|
|
385
|
+
readonly type: 'file';
|
|
386
|
+
readonly path: string;
|
|
387
|
+
}
|
|
388
|
+
interface RepoStore extends BaseStore {
|
|
389
|
+
readonly type: 'repo';
|
|
390
|
+
readonly path: string;
|
|
391
|
+
readonly url?: string | undefined;
|
|
392
|
+
readonly branch?: string | undefined;
|
|
393
|
+
}
|
|
394
|
+
interface WebStore extends BaseStore {
|
|
395
|
+
readonly type: 'web';
|
|
396
|
+
readonly url: string;
|
|
397
|
+
readonly depth: number;
|
|
398
|
+
readonly maxPages?: number | undefined;
|
|
399
|
+
}
|
|
400
|
+
type Store = FileStore | RepoStore | WebStore;
|
|
401
|
+
|
|
402
|
+
interface IndexResult {
|
|
403
|
+
documentsIndexed: number;
|
|
404
|
+
chunksCreated: number;
|
|
405
|
+
timeMs: number;
|
|
406
|
+
}
|
|
407
|
+
interface IndexOptions {
|
|
408
|
+
chunkSize?: number;
|
|
409
|
+
chunkOverlap?: number;
|
|
410
|
+
codeGraphService?: CodeGraphService;
|
|
411
|
+
concurrency?: number;
|
|
412
|
+
}
|
|
413
|
+
declare class IndexService {
|
|
414
|
+
private readonly lanceStore;
|
|
415
|
+
private readonly embeddingEngine;
|
|
416
|
+
private readonly chunker;
|
|
417
|
+
private readonly codeGraphService;
|
|
418
|
+
private readonly concurrency;
|
|
419
|
+
constructor(lanceStore: LanceStore, embeddingEngine: EmbeddingEngine, options?: IndexOptions);
|
|
420
|
+
indexStore(store: Store, onProgress?: ProgressCallback): Promise<Result<IndexResult>>;
|
|
421
|
+
private indexFileStore;
|
|
422
|
+
/**
|
|
423
|
+
* Process a single file: read, chunk, embed, and return documents.
|
|
424
|
+
* Extracted for parallel processing.
|
|
425
|
+
*/
|
|
426
|
+
private processFile;
|
|
427
|
+
private scanDirectory;
|
|
428
|
+
/**
|
|
429
|
+
* Classify file type for ranking purposes.
|
|
430
|
+
* Documentation files rank higher than source code for documentation queries.
|
|
431
|
+
* Phase 4: Enhanced to detect internal implementation files.
|
|
432
|
+
*/
|
|
433
|
+
private classifyFileType;
|
|
434
|
+
/**
|
|
435
|
+
* Detect if a source file is internal implementation code.
|
|
436
|
+
* Internal code should rank lower than public-facing APIs and docs.
|
|
437
|
+
*/
|
|
438
|
+
private isInternalImplementation;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
type SearchMode = 'vector' | 'fts' | 'hybrid';
|
|
442
|
+
interface CodeUnit {
|
|
443
|
+
type: 'function' | 'class' | 'interface' | 'type' | 'const' | 'documentation' | 'example';
|
|
444
|
+
name: string;
|
|
445
|
+
signature: string;
|
|
446
|
+
fullContent: string;
|
|
447
|
+
startLine: number;
|
|
448
|
+
endLine: number;
|
|
449
|
+
language: string;
|
|
450
|
+
}
|
|
451
|
+
interface ResultSummary {
|
|
452
|
+
readonly type: 'function' | 'class' | 'interface' | 'pattern' | 'documentation';
|
|
453
|
+
readonly name: string;
|
|
454
|
+
readonly signature: string;
|
|
455
|
+
readonly purpose: string;
|
|
456
|
+
readonly location: string;
|
|
457
|
+
readonly relevanceReason: string;
|
|
458
|
+
}
|
|
459
|
+
interface ResultContext {
|
|
460
|
+
readonly interfaces: readonly string[];
|
|
461
|
+
readonly keyImports: readonly string[];
|
|
462
|
+
readonly relatedConcepts: readonly string[];
|
|
463
|
+
readonly usage: {
|
|
464
|
+
readonly calledBy: number;
|
|
465
|
+
readonly calls: number;
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
interface ResultFull {
|
|
469
|
+
readonly completeCode: string;
|
|
470
|
+
readonly relatedCode: ReadonlyArray<{
|
|
471
|
+
readonly file: string;
|
|
472
|
+
readonly summary: string;
|
|
473
|
+
readonly relationship: string;
|
|
474
|
+
}>;
|
|
475
|
+
readonly documentation: string;
|
|
476
|
+
readonly tests?: string | undefined;
|
|
477
|
+
}
|
|
478
|
+
type DetailLevel = 'minimal' | 'contextual' | 'full';
|
|
479
|
+
interface SearchQuery {
|
|
480
|
+
readonly query: string;
|
|
481
|
+
readonly stores?: readonly StoreId[] | undefined;
|
|
482
|
+
readonly mode?: SearchMode | undefined;
|
|
483
|
+
readonly limit?: number | undefined;
|
|
484
|
+
readonly threshold?: number | undefined;
|
|
485
|
+
readonly minRelevance?: number | undefined;
|
|
486
|
+
readonly filter?: Record<string, unknown> | undefined;
|
|
487
|
+
readonly includeContent?: boolean | undefined;
|
|
488
|
+
readonly contextLines?: number | undefined;
|
|
489
|
+
readonly detail?: DetailLevel | undefined;
|
|
490
|
+
}
|
|
491
|
+
interface SearchResult {
|
|
492
|
+
readonly id: DocumentId;
|
|
493
|
+
score: number;
|
|
494
|
+
readonly content: string;
|
|
495
|
+
readonly highlight?: string | undefined;
|
|
496
|
+
readonly metadata: DocumentMetadata;
|
|
497
|
+
readonly codeUnit?: CodeUnit | undefined;
|
|
498
|
+
readonly summary?: ResultSummary | undefined;
|
|
499
|
+
readonly context?: ResultContext | undefined;
|
|
500
|
+
readonly full?: ResultFull | undefined;
|
|
501
|
+
readonly rankingMetadata?: {
|
|
502
|
+
readonly vectorRank?: number;
|
|
503
|
+
readonly ftsRank?: number;
|
|
504
|
+
readonly vectorRRF: number;
|
|
505
|
+
readonly ftsRRF: number;
|
|
506
|
+
readonly fileTypeBoost: number;
|
|
507
|
+
readonly frameworkBoost: number;
|
|
508
|
+
readonly urlKeywordBoost: number;
|
|
509
|
+
readonly pathKeywordBoost: number;
|
|
510
|
+
readonly rawVectorScore?: number;
|
|
511
|
+
} | undefined;
|
|
512
|
+
}
|
|
513
|
+
type SearchConfidence = 'high' | 'medium' | 'low';
|
|
514
|
+
interface SearchResponse {
|
|
515
|
+
readonly query: string;
|
|
516
|
+
readonly mode: SearchMode;
|
|
517
|
+
readonly stores: readonly StoreId[];
|
|
518
|
+
readonly results: readonly SearchResult[];
|
|
519
|
+
readonly totalResults: number;
|
|
520
|
+
readonly timeMs: number;
|
|
521
|
+
readonly confidence?: SearchConfidence | undefined;
|
|
522
|
+
readonly maxRawScore?: number | undefined;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
declare class SearchService {
|
|
526
|
+
private readonly lanceStore;
|
|
527
|
+
private readonly embeddingEngine;
|
|
528
|
+
private readonly codeUnitService;
|
|
529
|
+
private readonly codeGraphService;
|
|
530
|
+
private readonly graphCache;
|
|
531
|
+
constructor(lanceStore: LanceStore, embeddingEngine: EmbeddingEngine, codeGraphService?: CodeGraphService);
|
|
532
|
+
/**
|
|
533
|
+
* Load code graph for a store, with caching.
|
|
534
|
+
* Returns null if no graph is available.
|
|
535
|
+
*/
|
|
536
|
+
private loadGraphForStore;
|
|
537
|
+
/**
|
|
538
|
+
* Calculate confidence level based on max raw vector similarity score.
|
|
539
|
+
* Configurable via environment variables, with sensible defaults for CLI usage.
|
|
540
|
+
*/
|
|
541
|
+
private calculateConfidence;
|
|
542
|
+
search(query: SearchQuery): Promise<SearchResponse>;
|
|
543
|
+
/**
|
|
544
|
+
* Deduplicate results by source file path.
|
|
545
|
+
* Keeps the best chunk for each unique source, considering both score and query relevance.
|
|
546
|
+
*/
|
|
547
|
+
private deduplicateBySource;
|
|
548
|
+
/**
|
|
549
|
+
* Count how many query terms appear in the content.
|
|
550
|
+
*/
|
|
551
|
+
private countQueryTerms;
|
|
552
|
+
/**
|
|
553
|
+
* Normalize scores to 0-1 range and optionally filter by threshold.
|
|
554
|
+
* This ensures threshold values match displayed scores (UX consistency).
|
|
555
|
+
*
|
|
556
|
+
* Edge case handling:
|
|
557
|
+
* - If there's only 1 result or all results have the same score, normalization
|
|
558
|
+
* would make them all 1.0. In this case, we keep the raw scores to allow
|
|
559
|
+
* threshold filtering to work meaningfully on absolute quality.
|
|
560
|
+
*/
|
|
561
|
+
private normalizeAndFilterScores;
|
|
562
|
+
/**
|
|
563
|
+
* Fetch raw vector search results without normalization.
|
|
564
|
+
* Returns results with raw cosine similarity scores [0-1].
|
|
565
|
+
*/
|
|
566
|
+
private vectorSearchRaw;
|
|
567
|
+
private vectorSearch;
|
|
568
|
+
private ftsSearch;
|
|
569
|
+
/**
|
|
570
|
+
* Internal hybrid search result with additional metadata for confidence calculation.
|
|
571
|
+
*/
|
|
572
|
+
private hybridSearchWithMetadata;
|
|
573
|
+
searchAllStores(query: SearchQuery, storeIds: StoreId[]): Promise<SearchResponse>;
|
|
574
|
+
/**
|
|
575
|
+
* Get a score multiplier based on file type and query intent.
|
|
576
|
+
* Documentation files get a strong boost to surface them higher.
|
|
577
|
+
* Phase 4: Strengthened boosts for better documentation ranking.
|
|
578
|
+
* Phase 1: Intent-based adjustments for context-aware ranking.
|
|
579
|
+
*/
|
|
580
|
+
private getFileTypeBoost;
|
|
581
|
+
/**
|
|
582
|
+
* Get a score multiplier based on URL keyword matching.
|
|
583
|
+
* Boosts results where URL path contains significant query keywords.
|
|
584
|
+
* This helps queries like "troubleshooting" rank /troubleshooting pages first.
|
|
585
|
+
*/
|
|
586
|
+
private getUrlKeywordBoost;
|
|
587
|
+
/**
|
|
588
|
+
* Get a score multiplier based on file path keyword matching.
|
|
589
|
+
* Boosts results where file path contains significant query keywords.
|
|
590
|
+
* This helps queries like "dispatcher" rank async_dispatcher.py higher.
|
|
591
|
+
*/
|
|
592
|
+
private getPathKeywordBoost;
|
|
593
|
+
/**
|
|
594
|
+
* Get a score multiplier based on framework context.
|
|
595
|
+
* If query mentions a framework, boost results from that framework's files.
|
|
596
|
+
*/
|
|
597
|
+
private getFrameworkContextBoost;
|
|
598
|
+
private addProgressiveContext;
|
|
599
|
+
private extractCodeUnitFromResult;
|
|
600
|
+
private extractSymbolName;
|
|
601
|
+
private inferType;
|
|
602
|
+
private generatePurpose;
|
|
603
|
+
private generateRelevanceReason;
|
|
604
|
+
private extractInterfaces;
|
|
605
|
+
private extractImports;
|
|
606
|
+
private extractConcepts;
|
|
607
|
+
private extractDocumentation;
|
|
608
|
+
/**
|
|
609
|
+
* Get usage stats from code graph.
|
|
610
|
+
* Returns default values if no graph is available.
|
|
611
|
+
*/
|
|
612
|
+
private getUsageFromGraph;
|
|
613
|
+
/**
|
|
614
|
+
* Get related code from graph.
|
|
615
|
+
* Returns callers and callees for the symbol.
|
|
616
|
+
*/
|
|
617
|
+
private getRelatedCodeFromGraph;
|
|
618
|
+
/**
|
|
619
|
+
* Parse a node ID into file path and symbol name.
|
|
620
|
+
*/
|
|
621
|
+
private parseNodeId;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Service for managing .gitignore patterns for Bluera Knowledge.
|
|
626
|
+
*
|
|
627
|
+
* When stores are created, this service ensures the project's .gitignore
|
|
628
|
+
* is updated to:
|
|
629
|
+
* - Ignore the .bluera/ data directory (not committed)
|
|
630
|
+
* - Allow committing .bluera/bluera-knowledge/stores.config.json (for team sharing)
|
|
631
|
+
*/
|
|
632
|
+
declare class GitignoreService {
|
|
633
|
+
private readonly gitignorePath;
|
|
634
|
+
constructor(projectRoot: string);
|
|
635
|
+
/**
|
|
636
|
+
* Check if all required patterns are present in .gitignore
|
|
637
|
+
*/
|
|
638
|
+
hasRequiredPatterns(): Promise<boolean>;
|
|
639
|
+
/**
|
|
640
|
+
* Ensure required .gitignore patterns are present.
|
|
641
|
+
*
|
|
642
|
+
* - Creates .gitignore if it doesn't exist
|
|
643
|
+
* - Appends missing patterns if .gitignore exists
|
|
644
|
+
* - Does nothing if all patterns are already present
|
|
645
|
+
*
|
|
646
|
+
* @returns Object with updated flag and descriptive message
|
|
647
|
+
*/
|
|
648
|
+
ensureGitignorePatterns(): Promise<{
|
|
649
|
+
updated: boolean;
|
|
650
|
+
message: string;
|
|
651
|
+
}>;
|
|
652
|
+
/**
|
|
653
|
+
* Get the path to the .gitignore file
|
|
654
|
+
*/
|
|
655
|
+
getGitignorePath(): string;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Discriminated union of all store definition types.
|
|
660
|
+
* Use the `type` field to narrow the type.
|
|
661
|
+
*/
|
|
662
|
+
declare const StoreDefinitionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
663
|
+
name: z.ZodString;
|
|
664
|
+
description: z.ZodOptional<z.ZodString>;
|
|
665
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
666
|
+
type: z.ZodLiteral<"file">;
|
|
667
|
+
path: z.ZodString;
|
|
668
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
669
|
+
name: z.ZodString;
|
|
670
|
+
description: z.ZodOptional<z.ZodString>;
|
|
671
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
672
|
+
type: z.ZodLiteral<"repo">;
|
|
673
|
+
url: z.ZodURL;
|
|
674
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
675
|
+
depth: z.ZodOptional<z.ZodNumber>;
|
|
676
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
677
|
+
name: z.ZodString;
|
|
678
|
+
description: z.ZodOptional<z.ZodString>;
|
|
679
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
680
|
+
type: z.ZodLiteral<"web">;
|
|
681
|
+
url: z.ZodURL;
|
|
682
|
+
depth: z.ZodDefault<z.ZodNumber>;
|
|
683
|
+
maxPages: z.ZodOptional<z.ZodNumber>;
|
|
684
|
+
crawlInstructions: z.ZodOptional<z.ZodString>;
|
|
685
|
+
extractInstructions: z.ZodOptional<z.ZodString>;
|
|
686
|
+
}, z.core.$strip>], "type">;
|
|
687
|
+
type StoreDefinition = z.infer<typeof StoreDefinitionSchema>;
|
|
688
|
+
/**
|
|
689
|
+
* Root configuration schema for store definitions.
|
|
690
|
+
* Version field enables future schema migrations.
|
|
691
|
+
*/
|
|
692
|
+
declare const StoreDefinitionsConfigSchema: z.ZodObject<{
|
|
693
|
+
version: z.ZodLiteral<1>;
|
|
694
|
+
stores: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
695
|
+
name: z.ZodString;
|
|
696
|
+
description: z.ZodOptional<z.ZodString>;
|
|
697
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
698
|
+
type: z.ZodLiteral<"file">;
|
|
699
|
+
path: z.ZodString;
|
|
700
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
701
|
+
name: z.ZodString;
|
|
702
|
+
description: z.ZodOptional<z.ZodString>;
|
|
703
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
704
|
+
type: z.ZodLiteral<"repo">;
|
|
705
|
+
url: z.ZodURL;
|
|
706
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
707
|
+
depth: z.ZodOptional<z.ZodNumber>;
|
|
708
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
709
|
+
name: z.ZodString;
|
|
710
|
+
description: z.ZodOptional<z.ZodString>;
|
|
711
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
712
|
+
type: z.ZodLiteral<"web">;
|
|
713
|
+
url: z.ZodURL;
|
|
714
|
+
depth: z.ZodDefault<z.ZodNumber>;
|
|
715
|
+
maxPages: z.ZodOptional<z.ZodNumber>;
|
|
716
|
+
crawlInstructions: z.ZodOptional<z.ZodString>;
|
|
717
|
+
extractInstructions: z.ZodOptional<z.ZodString>;
|
|
718
|
+
}, z.core.$strip>], "type">>;
|
|
719
|
+
}, z.core.$strip>;
|
|
720
|
+
type StoreDefinitionsConfig = z.infer<typeof StoreDefinitionsConfigSchema>;
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Service for managing git-committable store definitions.
|
|
724
|
+
*
|
|
725
|
+
* Store definitions are saved to `.bluera/bluera-knowledge/stores.config.json`
|
|
726
|
+
* within the project root. This file is designed to be committed to version
|
|
727
|
+
* control, allowing teams to share store configurations.
|
|
728
|
+
*
|
|
729
|
+
* The actual store data (vector embeddings, cloned repos) lives in the data
|
|
730
|
+
* directory and should be gitignored.
|
|
731
|
+
*/
|
|
732
|
+
declare class StoreDefinitionService {
|
|
733
|
+
private readonly configPath;
|
|
734
|
+
private readonly projectRoot;
|
|
735
|
+
private config;
|
|
736
|
+
constructor(projectRoot?: string);
|
|
737
|
+
/**
|
|
738
|
+
* Load store definitions from config file.
|
|
739
|
+
* Returns empty config if file doesn't exist.
|
|
740
|
+
* Throws on parse/validation errors (fail fast per CLAUDE.md).
|
|
741
|
+
*/
|
|
742
|
+
load(): Promise<StoreDefinitionsConfig>;
|
|
743
|
+
/**
|
|
744
|
+
* Save store definitions to config file.
|
|
745
|
+
*/
|
|
746
|
+
save(config: StoreDefinitionsConfig): Promise<void>;
|
|
747
|
+
/**
|
|
748
|
+
* Add a store definition.
|
|
749
|
+
* Throws if a definition with the same name already exists.
|
|
750
|
+
*/
|
|
751
|
+
addDefinition(definition: StoreDefinition): Promise<void>;
|
|
752
|
+
/**
|
|
753
|
+
* Remove a store definition by name.
|
|
754
|
+
* Returns true if removed, false if not found.
|
|
755
|
+
*/
|
|
756
|
+
removeDefinition(name: string): Promise<boolean>;
|
|
757
|
+
/**
|
|
758
|
+
* Update an existing store definition.
|
|
759
|
+
* Only updates the provided fields, preserving others.
|
|
760
|
+
* Throws if definition not found.
|
|
761
|
+
*/
|
|
762
|
+
updateDefinition(name: string, updates: {
|
|
763
|
+
description?: string;
|
|
764
|
+
tags?: string[];
|
|
765
|
+
}): Promise<void>;
|
|
766
|
+
/**
|
|
767
|
+
* Get a store definition by name.
|
|
768
|
+
* Returns undefined if not found.
|
|
769
|
+
*/
|
|
770
|
+
getByName(name: string): Promise<StoreDefinition | undefined>;
|
|
771
|
+
/**
|
|
772
|
+
* Check if any definitions exist.
|
|
773
|
+
*/
|
|
774
|
+
hasDefinitions(): Promise<boolean>;
|
|
775
|
+
/**
|
|
776
|
+
* Resolve a file store path relative to project root.
|
|
777
|
+
*/
|
|
778
|
+
resolvePath(path: string): string;
|
|
779
|
+
/**
|
|
780
|
+
* Get the config file path.
|
|
781
|
+
*/
|
|
782
|
+
getConfigPath(): string;
|
|
783
|
+
/**
|
|
784
|
+
* Get the project root.
|
|
785
|
+
*/
|
|
786
|
+
getProjectRoot(): string;
|
|
787
|
+
/**
|
|
788
|
+
* Clear the cached config (useful for testing).
|
|
789
|
+
*/
|
|
790
|
+
clearCache(): void;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
interface CreateStoreInput {
|
|
794
|
+
name: string;
|
|
795
|
+
type: StoreType;
|
|
796
|
+
path?: string | undefined;
|
|
797
|
+
url?: string | undefined;
|
|
798
|
+
description?: string | undefined;
|
|
799
|
+
tags?: string[] | undefined;
|
|
800
|
+
branch?: string | undefined;
|
|
801
|
+
depth?: number | undefined;
|
|
802
|
+
}
|
|
803
|
+
interface StoreServiceOptions {
|
|
804
|
+
/** Optional definition service for auto-updating git-committable config */
|
|
805
|
+
definitionService?: StoreDefinitionService;
|
|
806
|
+
/** Optional gitignore service for ensuring .gitignore patterns */
|
|
807
|
+
gitignoreService?: GitignoreService;
|
|
808
|
+
}
|
|
809
|
+
interface OperationOptions {
|
|
810
|
+
/** Skip syncing to store definitions (used by stores:sync command) */
|
|
811
|
+
skipDefinitionSync?: boolean;
|
|
812
|
+
}
|
|
813
|
+
declare class StoreService {
|
|
814
|
+
private readonly dataDir;
|
|
815
|
+
private readonly definitionService;
|
|
816
|
+
private readonly gitignoreService;
|
|
817
|
+
private registry;
|
|
818
|
+
constructor(dataDir: string, options?: StoreServiceOptions);
|
|
819
|
+
initialize(): Promise<void>;
|
|
820
|
+
/**
|
|
821
|
+
* Convert a Store and CreateStoreInput to a StoreDefinition for persistence.
|
|
822
|
+
*/
|
|
823
|
+
private createDefinitionFromStore;
|
|
824
|
+
create(input: CreateStoreInput, options?: OperationOptions): Promise<Result<Store>>;
|
|
825
|
+
list(type?: StoreType): Promise<Store[]>;
|
|
826
|
+
get(id: StoreId): Promise<Store | undefined>;
|
|
827
|
+
getByName(name: string): Promise<Store | undefined>;
|
|
828
|
+
getByIdOrName(idOrName: string): Promise<Store | undefined>;
|
|
829
|
+
update(id: StoreId, updates: Partial<Pick<Store, 'name' | 'description' | 'tags'>>, options?: OperationOptions): Promise<Result<Store>>;
|
|
830
|
+
delete(id: StoreId, options?: OperationOptions): Promise<Result<void>>;
|
|
831
|
+
private loadRegistry;
|
|
832
|
+
private saveRegistry;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
interface ServiceContainer {
|
|
836
|
+
config: ConfigService;
|
|
837
|
+
store: StoreService;
|
|
838
|
+
search: SearchService;
|
|
839
|
+
index: IndexService;
|
|
840
|
+
lance: LanceStore;
|
|
841
|
+
embeddings: EmbeddingEngine;
|
|
842
|
+
codeGraph: CodeGraphService;
|
|
843
|
+
pythonBridge: PythonBridge;
|
|
844
|
+
}
|
|
2
845
|
|
|
3
846
|
/**
|
|
4
847
|
* Configuration options for the MCP server
|
|
@@ -9,7 +852,22 @@ interface MCPServerOptions {
|
|
|
9
852
|
projectRoot?: string | undefined;
|
|
10
853
|
}
|
|
11
854
|
|
|
12
|
-
|
|
855
|
+
/**
|
|
856
|
+
* Create MCP server with pre-initialized services.
|
|
857
|
+
*
|
|
858
|
+
* Services are initialized ONCE at server startup and reused for all tool calls.
|
|
859
|
+
* This reduces per-call latency from 1-15s to <500ms.
|
|
860
|
+
*/
|
|
861
|
+
declare function createMCPServer(options: MCPServerOptions, services: ServiceContainer): Server;
|
|
862
|
+
/**
|
|
863
|
+
* Run MCP server with lazy service initialization.
|
|
864
|
+
*
|
|
865
|
+
* Services are initialized ONCE at startup:
|
|
866
|
+
* - Lightweight services (config, store, lance wrapper): immediate
|
|
867
|
+
* - Heavy services (embeddings model): deferred until first use
|
|
868
|
+
*
|
|
869
|
+
* This reduces server startup from ~5s to <500ms.
|
|
870
|
+
*/
|
|
13
871
|
declare function runMCPServer(options: MCPServerOptions): Promise<void>;
|
|
14
872
|
|
|
15
873
|
export { createMCPServer, runMCPServer };
|