bluera-knowledge 0.9.26 → 0.9.31
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/commands/commit.md +4 -7
- package/.claude/hooks/post-edit-check.sh +21 -24
- package/.claude/skills/atomic-commits/SKILL.md +6 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.env.example +4 -0
- package/.husky/pre-push +12 -2
- package/.versionrc.json +0 -4
- package/BUGS-FOUND.md +71 -0
- package/CHANGELOG.md +76 -0
- package/README.md +55 -20
- package/bun.lock +35 -1
- package/commands/crawl.md +2 -0
- package/dist/{chunk-BICFAWMN.js → chunk-2SJHNRXD.js} +73 -8
- package/dist/chunk-2SJHNRXD.js.map +1 -0
- package/dist/{chunk-J7J6LXOJ.js → chunk-OGEY66FZ.js} +106 -41
- package/dist/chunk-OGEY66FZ.js.map +1 -0
- package/dist/{chunk-5QMHZUC4.js → chunk-RWSXP3PQ.js} +482 -106
- package/dist/chunk-RWSXP3PQ.js.map +1 -0
- package/dist/index.js +73 -28
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +2 -2
- package/dist/workers/background-worker-cli.js +2 -2
- package/eslint.config.js +1 -1
- package/package.json +3 -1
- package/src/analysis/ast-parser.test.ts +46 -0
- package/src/cli/commands/crawl.test.ts +99 -12
- package/src/cli/commands/crawl.ts +76 -24
- package/src/cli/commands/store.test.ts +68 -1
- package/src/cli/commands/store.ts +9 -3
- package/src/crawl/article-converter.ts +36 -1
- package/src/crawl/bridge.ts +18 -7
- package/src/crawl/intelligent-crawler.ts +45 -4
- package/src/db/embeddings.test.ts +16 -0
- package/src/db/lance.test.ts +31 -0
- package/src/db/lance.ts +8 -0
- package/src/logging/index.ts +29 -0
- package/src/logging/logger.test.ts +75 -0
- package/src/logging/logger.ts +147 -0
- package/src/logging/payload.test.ts +152 -0
- package/src/logging/payload.ts +121 -0
- package/src/mcp/handlers/search.handler.test.ts +28 -9
- package/src/mcp/handlers/search.handler.ts +69 -29
- package/src/mcp/handlers/store.handler.test.ts +1 -0
- package/src/mcp/server.ts +44 -16
- package/src/services/chunking.service.ts +23 -0
- package/src/services/index.service.test.ts +921 -1
- package/src/services/index.service.ts +76 -1
- package/src/services/index.ts +20 -2
- package/src/services/search.service.test.ts +573 -21
- package/src/services/search.service.ts +257 -105
- package/src/services/services.test.ts +2 -2
- package/src/services/snippet.service.ts +28 -3
- package/src/services/store.service.test.ts +28 -0
- package/src/services/store.service.ts +4 -0
- package/src/services/token.service.test.ts +45 -0
- package/src/services/token.service.ts +33 -0
- package/src/types/result.test.ts +10 -0
- package/tests/integration/cli-consistency.test.ts +1 -4
- package/vitest.config.ts +4 -0
- package/dist/chunk-5QMHZUC4.js.map +0 -1
- package/dist/chunk-BICFAWMN.js.map +0 -1
- package/dist/chunk-J7J6LXOJ.js.map +0 -1
- package/scripts/readme-version-updater.cjs +0 -18
|
@@ -11,6 +11,9 @@ import { ok, err } from '../types/result.js';
|
|
|
11
11
|
import { ChunkingService } from './chunking.service.js';
|
|
12
12
|
import type { ProgressCallback } from '../types/progress.js';
|
|
13
13
|
import type { CodeGraphService } from './code-graph.service.js';
|
|
14
|
+
import { createLogger } from '../logging/index.js';
|
|
15
|
+
|
|
16
|
+
const logger = createLogger('index-service');
|
|
14
17
|
|
|
15
18
|
interface IndexResult {
|
|
16
19
|
documentsIndexed: number;
|
|
@@ -51,13 +54,24 @@ export class IndexService {
|
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
async indexStore(store: Store, onProgress?: ProgressCallback): Promise<Result<IndexResult>> {
|
|
57
|
+
logger.info({
|
|
58
|
+
storeId: store.id,
|
|
59
|
+
storeName: store.name,
|
|
60
|
+
storeType: store.type,
|
|
61
|
+
}, 'Starting store indexing');
|
|
62
|
+
|
|
54
63
|
try {
|
|
55
64
|
if (store.type === 'file' || store.type === 'repo') {
|
|
56
65
|
return await this.indexFileStore(store, onProgress);
|
|
57
66
|
}
|
|
58
67
|
|
|
68
|
+
logger.error({ storeId: store.id, storeType: store.type }, 'Unsupported store type for indexing');
|
|
59
69
|
return err(new Error(`Indexing not supported for store type: ${store.type}`));
|
|
60
70
|
} catch (error) {
|
|
71
|
+
logger.error({
|
|
72
|
+
storeId: store.id,
|
|
73
|
+
error: error instanceof Error ? error.message : String(error),
|
|
74
|
+
}, 'Store indexing failed');
|
|
61
75
|
return err(error instanceof Error ? error : new Error(String(error)));
|
|
62
76
|
}
|
|
63
77
|
}
|
|
@@ -68,6 +82,12 @@ export class IndexService {
|
|
|
68
82
|
const documents: Document[] = [];
|
|
69
83
|
let filesProcessed = 0;
|
|
70
84
|
|
|
85
|
+
logger.debug({
|
|
86
|
+
storeId: store.id,
|
|
87
|
+
path: store.path,
|
|
88
|
+
fileCount: files.length,
|
|
89
|
+
}, 'Files scanned for indexing');
|
|
90
|
+
|
|
71
91
|
// Collect source files for code graph building
|
|
72
92
|
const sourceFiles: Array<{ path: string; content: string }> = [];
|
|
73
93
|
|
|
@@ -152,10 +172,21 @@ export class IndexService {
|
|
|
152
172
|
message: 'Indexing complete'
|
|
153
173
|
});
|
|
154
174
|
|
|
175
|
+
const timeMs = Date.now() - startTime;
|
|
176
|
+
|
|
177
|
+
logger.info({
|
|
178
|
+
storeId: store.id,
|
|
179
|
+
storeName: store.name,
|
|
180
|
+
documentsIndexed: filesProcessed,
|
|
181
|
+
chunksCreated: documents.length,
|
|
182
|
+
sourceFilesForGraph: sourceFiles.length,
|
|
183
|
+
timeMs,
|
|
184
|
+
}, 'Store indexing complete');
|
|
185
|
+
|
|
155
186
|
return ok({
|
|
156
187
|
documentsIndexed: filesProcessed,
|
|
157
188
|
chunksCreated: documents.length,
|
|
158
|
-
timeMs
|
|
189
|
+
timeMs,
|
|
159
190
|
});
|
|
160
191
|
}
|
|
161
192
|
|
|
@@ -264,3 +295,47 @@ export class IndexService {
|
|
|
264
295
|
return false;
|
|
265
296
|
}
|
|
266
297
|
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Classify web content type based on URL patterns and page title.
|
|
301
|
+
* Used for ranking boosts similar to local file classification.
|
|
302
|
+
*/
|
|
303
|
+
export function classifyWebContentType(url: string, title?: string): string {
|
|
304
|
+
const urlLower = url.toLowerCase();
|
|
305
|
+
const titleLower = (title ?? '').toLowerCase();
|
|
306
|
+
|
|
307
|
+
// API reference documentation → documentation-primary (1.8x boost)
|
|
308
|
+
if (/\/api[-/]?(ref|reference|docs?)?\//i.test(urlLower) ||
|
|
309
|
+
/api\s*(reference|documentation)/i.test(titleLower)) {
|
|
310
|
+
return 'documentation-primary';
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Getting started / tutorials → documentation-primary (1.8x boost)
|
|
314
|
+
if (/\/(getting[-_]?started|quickstart|tutorial|setup)\b/i.test(urlLower) ||
|
|
315
|
+
/(getting started|quickstart|tutorial)/i.test(titleLower)) {
|
|
316
|
+
return 'documentation-primary';
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// General docs paths → documentation (1.5x boost)
|
|
320
|
+
if (/\/(docs?|documentation|reference|learn|manual|guide)/i.test(urlLower)) {
|
|
321
|
+
return 'documentation';
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Examples and demos → example (1.4x boost)
|
|
325
|
+
if (/\/(examples?|demos?|samples?|cookbook)/i.test(urlLower)) {
|
|
326
|
+
return 'example';
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Changelog → changelog (special handling in intent boosts)
|
|
330
|
+
if (/changelog|release[-_]?notes/i.test(urlLower)) {
|
|
331
|
+
return 'changelog';
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Blog posts → lower priority
|
|
335
|
+
if (/\/blog\//i.test(urlLower)) {
|
|
336
|
+
return 'other';
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Web content without specific path indicators is treated as documentation
|
|
340
|
+
return 'documentation';
|
|
341
|
+
}
|
package/src/services/index.ts
CHANGED
|
@@ -6,6 +6,9 @@ import { CodeGraphService } from './code-graph.service.js';
|
|
|
6
6
|
import { LanceStore } from '../db/lance.js';
|
|
7
7
|
import { EmbeddingEngine } from '../db/embeddings.js';
|
|
8
8
|
import { PythonBridge } from '../crawl/bridge.js';
|
|
9
|
+
import { createLogger, shutdownLogger } from '../logging/index.js';
|
|
10
|
+
|
|
11
|
+
const logger = createLogger('services');
|
|
9
12
|
|
|
10
13
|
export { ConfigService } from './config.service.js';
|
|
11
14
|
export { StoreService } from './store.service.js';
|
|
@@ -32,6 +35,8 @@ export async function createServices(
|
|
|
32
35
|
dataDir?: string,
|
|
33
36
|
projectRoot?: string
|
|
34
37
|
): Promise<ServiceContainer> {
|
|
38
|
+
logger.info({ configPath, dataDir, projectRoot }, 'Initializing services');
|
|
39
|
+
|
|
35
40
|
const config = new ConfigService(configPath, dataDir, projectRoot);
|
|
36
41
|
const appConfig = await config.load();
|
|
37
42
|
const resolvedDataDir = config.resolveDataDir();
|
|
@@ -51,9 +56,11 @@ export async function createServices(
|
|
|
51
56
|
await pythonBridge.start();
|
|
52
57
|
|
|
53
58
|
const codeGraph = new CodeGraphService(resolvedDataDir, pythonBridge);
|
|
54
|
-
const search = new SearchService(lance, embeddings,
|
|
59
|
+
const search = new SearchService(lance, embeddings, codeGraph);
|
|
55
60
|
const index = new IndexService(lance, embeddings, { codeGraphService: codeGraph });
|
|
56
61
|
|
|
62
|
+
logger.info({ dataDir: resolvedDataDir }, 'Services initialized successfully');
|
|
63
|
+
|
|
57
64
|
return {
|
|
58
65
|
config,
|
|
59
66
|
store,
|
|
@@ -71,5 +78,16 @@ export async function createServices(
|
|
|
71
78
|
* Call this after CLI commands complete to allow the process to exit.
|
|
72
79
|
*/
|
|
73
80
|
export async function destroyServices(services: ServiceContainer): Promise<void> {
|
|
74
|
-
|
|
81
|
+
logger.info('Shutting down services');
|
|
82
|
+
try {
|
|
83
|
+
services.lance.close();
|
|
84
|
+
} catch (e) {
|
|
85
|
+
logger.error({ error: e }, 'Error closing LanceStore');
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
await services.pythonBridge.stop();
|
|
89
|
+
} catch (e) {
|
|
90
|
+
logger.error({ error: e }, 'Error stopping Python bridge');
|
|
91
|
+
}
|
|
92
|
+
await shutdownLogger();
|
|
75
93
|
}
|