bluera-knowledge 0.9.26 → 0.9.30

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 (55) hide show
  1. package/.claude/commands/commit.md +4 -7
  2. package/.claude/hooks/post-edit-check.sh +21 -24
  3. package/.claude/skills/atomic-commits/SKILL.md +6 -0
  4. package/.claude-plugin/plugin.json +1 -1
  5. package/.env.example +4 -0
  6. package/.husky/pre-push +12 -2
  7. package/.versionrc.json +0 -4
  8. package/CHANGELOG.md +69 -0
  9. package/README.md +55 -20
  10. package/bun.lock +35 -1
  11. package/commands/crawl.md +2 -0
  12. package/dist/{chunk-BICFAWMN.js → chunk-DNOIM7BO.js} +73 -8
  13. package/dist/chunk-DNOIM7BO.js.map +1 -0
  14. package/dist/{chunk-5QMHZUC4.js → chunk-NJUMU4X2.js} +462 -105
  15. package/dist/chunk-NJUMU4X2.js.map +1 -0
  16. package/dist/{chunk-J7J6LXOJ.js → chunk-SZNTYLYT.js} +106 -41
  17. package/dist/chunk-SZNTYLYT.js.map +1 -0
  18. package/dist/index.js +65 -25
  19. package/dist/index.js.map +1 -1
  20. package/dist/mcp/server.js +2 -2
  21. package/dist/workers/background-worker-cli.js +2 -2
  22. package/eslint.config.js +1 -1
  23. package/package.json +3 -1
  24. package/src/analysis/ast-parser.test.ts +46 -0
  25. package/src/cli/commands/crawl.test.ts +99 -12
  26. package/src/cli/commands/crawl.ts +76 -24
  27. package/src/crawl/article-converter.ts +36 -1
  28. package/src/crawl/bridge.ts +18 -7
  29. package/src/crawl/intelligent-crawler.ts +45 -4
  30. package/src/db/embeddings.test.ts +16 -0
  31. package/src/logging/index.ts +29 -0
  32. package/src/logging/logger.test.ts +75 -0
  33. package/src/logging/logger.ts +147 -0
  34. package/src/logging/payload.test.ts +152 -0
  35. package/src/logging/payload.ts +121 -0
  36. package/src/mcp/handlers/search.handler.test.ts +28 -9
  37. package/src/mcp/handlers/search.handler.ts +69 -29
  38. package/src/mcp/handlers/store.handler.test.ts +1 -0
  39. package/src/mcp/server.ts +44 -16
  40. package/src/services/chunking.service.ts +23 -0
  41. package/src/services/index.service.test.ts +921 -1
  42. package/src/services/index.service.ts +76 -1
  43. package/src/services/index.ts +10 -1
  44. package/src/services/search.service.test.ts +573 -21
  45. package/src/services/search.service.ts +257 -105
  46. package/src/services/snippet.service.ts +28 -3
  47. package/src/services/token.service.test.ts +45 -0
  48. package/src/services/token.service.ts +33 -0
  49. package/src/types/result.test.ts +10 -0
  50. package/tests/integration/cli-consistency.test.ts +1 -4
  51. package/vitest.config.ts +4 -0
  52. package/dist/chunk-5QMHZUC4.js.map +0 -1
  53. package/dist/chunk-BICFAWMN.js.map +0 -1
  54. package/dist/chunk-J7J6LXOJ.js.map +0 -1
  55. 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: Date.now() - startTime,
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
+ }
@@ -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, undefined, codeGraph);
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,7 @@ 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> {
81
+ logger.info('Shutting down services');
74
82
  await services.pythonBridge.stop();
83
+ await shutdownLogger();
75
84
  }