bluera-knowledge 0.12.7 → 0.12.9

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bluera-knowledge",
3
- "version": "0.12.7",
3
+ "version": "0.12.9",
4
4
  "description": "Clone repos, crawl docs, search locally. Fast, authoritative answers for AI coding agents.",
5
5
  "mcpServers": {
6
6
  "bluera-knowledge": {
package/CHANGELOG.md CHANGED
@@ -2,6 +2,45 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
4
 
5
+ ## [0.12.9](https://github.com/blueraai/bluera-knowledge/compare/v0.11.21...v0.12.9) (2026-01-15)
6
+
7
+
8
+ ### Features
9
+
10
+ * **hooks:** add PreToolUse hooks for BK suggestions ([23d3fa4](https://github.com/blueraai/bluera-knowledge/commit/23d3fa493dd16427d6bda3ea80064622c6244bba))
11
+ * **hooks:** add skill auto-activation system ([2b4e96b](https://github.com/blueraai/bluera-knowledge/commit/2b4e96bd29f28df63377cdaacab922d4f4321a8f))
12
+ * **hooks:** improve skill activation with forced evaluation pattern ([f044077](https://github.com/blueraai/bluera-knowledge/commit/f044077d260b78b55a00ebf735b68a2d933f34a7)), closes [#15345](https://github.com/blueraai/bluera-knowledge/issues/15345)
13
+ * **test-plugin:** add hook tests to plugin test suite ([475a776](https://github.com/blueraai/bluera-knowledge/commit/475a7766fea47767a2dfb8148f7e74581de2c2ee))
14
+ * **types:** add Zod validation for JSON parsing ([41348eb](https://github.com/blueraai/bluera-knowledge/commit/41348eb337c33d52174c22097e6788948ad605f8))
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **hooks:** use JSON output for PreToolUse hook context injection ([a73977e](https://github.com/blueraai/bluera-knowledge/commit/a73977e0f8f690d43b9d7c987300522dd501fe38))
20
+ * **store:** harden store registry against null entries and invalid types ([c0fedbc](https://github.com/blueraai/bluera-knowledge/commit/c0fedbc5c7f664e46bc8afc7c58bb6d1e1825711))
21
+ * **tests:** stabilize watch service tests in coverage mode ([fdf6c3a](https://github.com/blueraai/bluera-knowledge/commit/fdf6c3a478adff9e4746b54a9519184ca280f344))
22
+ * **workers:** harden dataDir handling with explicit checks and add tests ([691cf50](https://github.com/blueraai/bluera-knowledge/commit/691cf50e0531c4083773eae27e26cb46c3d653b6))
23
+ * **workers:** resolve ONNX runtime mutex crash on macOS ([77b66c6](https://github.com/blueraai/bluera-knowledge/commit/77b66c69c811d72366d49d13f35ec7625450dc98))
24
+
25
+ ## [0.12.8](https://github.com/blueraai/bluera-knowledge/compare/v0.11.21...v0.12.8) (2026-01-15)
26
+
27
+
28
+ ### Features
29
+
30
+ * **hooks:** add PreToolUse hooks for BK suggestions ([23d3fa4](https://github.com/blueraai/bluera-knowledge/commit/23d3fa493dd16427d6bda3ea80064622c6244bba))
31
+ * **hooks:** add skill auto-activation system ([2b4e96b](https://github.com/blueraai/bluera-knowledge/commit/2b4e96bd29f28df63377cdaacab922d4f4321a8f))
32
+ * **hooks:** improve skill activation with forced evaluation pattern ([f044077](https://github.com/blueraai/bluera-knowledge/commit/f044077d260b78b55a00ebf735b68a2d933f34a7)), closes [#15345](https://github.com/blueraai/bluera-knowledge/issues/15345)
33
+ * **test-plugin:** add hook tests to plugin test suite ([475a776](https://github.com/blueraai/bluera-knowledge/commit/475a7766fea47767a2dfb8148f7e74581de2c2ee))
34
+ * **types:** add Zod validation for JSON parsing ([41348eb](https://github.com/blueraai/bluera-knowledge/commit/41348eb337c33d52174c22097e6788948ad605f8))
35
+
36
+
37
+ ### Bug Fixes
38
+
39
+ * **hooks:** use JSON output for PreToolUse hook context injection ([a73977e](https://github.com/blueraai/bluera-knowledge/commit/a73977e0f8f690d43b9d7c987300522dd501fe38))
40
+ * **store:** harden store registry against null entries and invalid types ([c0fedbc](https://github.com/blueraai/bluera-knowledge/commit/c0fedbc5c7f664e46bc8afc7c58bb6d1e1825711))
41
+ * **tests:** stabilize watch service tests in coverage mode ([fdf6c3a](https://github.com/blueraai/bluera-knowledge/commit/fdf6c3a478adff9e4746b54a9519184ca280f344))
42
+ * **workers:** harden dataDir handling with explicit checks and add tests ([691cf50](https://github.com/blueraai/bluera-knowledge/commit/691cf50e0531c4083773eae27e26cb46c3d653b6))
43
+
5
44
  ## [0.12.7](https://github.com/blueraai/bluera-knowledge/compare/v0.11.21...v0.12.7) (2026-01-15)
6
45
 
7
46
 
@@ -7,7 +7,7 @@ import {
7
7
  createStoreId,
8
8
  destroyServices,
9
9
  summarizePayload
10
- } from "./chunk-C4SYGLAI.js";
10
+ } from "./chunk-VTATT3IR.js";
11
11
 
12
12
  // src/mcp/server.ts
13
13
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -2139,4 +2139,4 @@ export {
2139
2139
  createMCPServer,
2140
2140
  runMCPServer
2141
2141
  };
2142
- //# sourceMappingURL=chunk-PFBSZTP3.js.map
2142
+ //# sourceMappingURL=chunk-4ZBK7V54.js.map
@@ -3,7 +3,7 @@ import {
3
3
  createLogger,
4
4
  summarizePayload,
5
5
  truncateForLog
6
- } from "./chunk-C4SYGLAI.js";
6
+ } from "./chunk-VTATT3IR.js";
7
7
 
8
8
  // src/crawl/intelligent-crawler.ts
9
9
  import { EventEmitter } from "events";
@@ -753,4 +753,4 @@ var IntelligentCrawler = class extends EventEmitter {
753
753
  export {
754
754
  IntelligentCrawler
755
755
  };
756
- //# sourceMappingURL=chunk-QCSFBMYW.js.map
756
+ //# sourceMappingURL=chunk-6777ULXC.js.map
@@ -250,6 +250,40 @@ import { randomUUID } from "crypto";
250
250
  import fs from "fs";
251
251
  import path from "path";
252
252
 
253
+ // src/types/job.ts
254
+ import { z } from "zod";
255
+ var JobTypeSchema = z.enum(["clone", "index", "crawl"]);
256
+ var JobStatusSchema = z.enum(["pending", "running", "completed", "failed", "cancelled"]);
257
+ var JobDetailsSchema = z.object({
258
+ storeName: z.string().optional(),
259
+ storeId: z.string().optional(),
260
+ url: z.string().optional(),
261
+ path: z.string().optional(),
262
+ filesProcessed: z.number().optional(),
263
+ totalFiles: z.number().optional(),
264
+ startedAt: z.string().optional(),
265
+ completedAt: z.string().optional(),
266
+ cancelledAt: z.string().optional(),
267
+ error: z.string().optional(),
268
+ // Crawl-specific fields
269
+ crawlInstruction: z.string().optional(),
270
+ extractInstruction: z.string().optional(),
271
+ maxPages: z.number().optional(),
272
+ simple: z.boolean().optional(),
273
+ useHeadless: z.boolean().optional(),
274
+ pagesCrawled: z.number().optional()
275
+ });
276
+ var JobSchema = z.object({
277
+ id: z.string(),
278
+ type: JobTypeSchema,
279
+ status: JobStatusSchema,
280
+ progress: z.number().min(0).max(100),
281
+ message: z.string(),
282
+ details: JobDetailsSchema.default({}),
283
+ createdAt: z.string(),
284
+ updatedAt: z.string()
285
+ });
286
+
253
287
  // src/types/result.ts
254
288
  function ok(data) {
255
289
  return { success: true, data };
@@ -327,7 +361,7 @@ var JobService = class {
327
361
  }
328
362
  try {
329
363
  const content = fs.readFileSync(jobFile, "utf-8");
330
- return JSON.parse(content);
364
+ return JobSchema.parse(JSON.parse(content));
331
365
  } catch (error) {
332
366
  throw new Error(
333
367
  `Failed to read job ${jobId}: ${error instanceof Error ? error.message : String(error)}`
@@ -349,7 +383,7 @@ var JobService = class {
349
383
  }
350
384
  try {
351
385
  const content = fs.readFileSync(path.join(this.jobsDir, file), "utf-8");
352
- const job = JSON.parse(content);
386
+ const job = JobSchema.parse(JSON.parse(content));
353
387
  if (statusFilter !== void 0) {
354
388
  const filters = Array.isArray(statusFilter) ? statusFilter : [statusFilter];
355
389
  if (filters.includes(job.status)) {
@@ -3881,6 +3915,10 @@ var StoreService = class {
3881
3915
  updatedAt: now
3882
3916
  };
3883
3917
  break;
3918
+ default: {
3919
+ const invalidType = input.type;
3920
+ return err(new Error(`Invalid store type: ${String(invalidType)}`));
3921
+ }
3884
3922
  }
3885
3923
  this.registry.stores.push(store);
3886
3924
  await this.saveRegistry();
@@ -3964,7 +4002,7 @@ var StoreService = class {
3964
4002
  try {
3965
4003
  const data = JSON.parse(content);
3966
4004
  this.registry = {
3967
- stores: data.stores.map((s) => ({
4005
+ stores: data.stores.filter((s) => s !== null).map((s) => ({
3968
4006
  ...s,
3969
4007
  id: createStoreId(s.id),
3970
4008
  createdAt: new Date(s.createdAt),
@@ -3990,33 +4028,33 @@ import { createInterface } from "readline";
3990
4028
  import { ZodError } from "zod";
3991
4029
 
3992
4030
  // src/crawl/schemas.ts
3993
- import { z } from "zod";
3994
- var CrawledLinkSchema = z.object({
3995
- href: z.string(),
3996
- text: z.string(),
3997
- title: z.string().optional(),
3998
- base_domain: z.string().optional(),
3999
- head_data: z.unknown().optional(),
4000
- head_extraction_status: z.unknown().optional(),
4001
- head_extraction_error: z.unknown().optional(),
4002
- intrinsic_score: z.number().optional(),
4003
- contextual_score: z.unknown().optional(),
4004
- total_score: z.unknown().optional()
4031
+ import { z as z2 } from "zod";
4032
+ var CrawledLinkSchema = z2.object({
4033
+ href: z2.string(),
4034
+ text: z2.string(),
4035
+ title: z2.string().optional(),
4036
+ base_domain: z2.string().optional(),
4037
+ head_data: z2.unknown().optional(),
4038
+ head_extraction_status: z2.unknown().optional(),
4039
+ head_extraction_error: z2.unknown().optional(),
4040
+ intrinsic_score: z2.number().optional(),
4041
+ contextual_score: z2.unknown().optional(),
4042
+ total_score: z2.unknown().optional()
4005
4043
  });
4006
- var CrawlPageSchema = z.object({
4007
- url: z.string(),
4008
- title: z.string(),
4009
- content: z.string(),
4010
- links: z.array(z.string()),
4011
- crawledAt: z.string()
4044
+ var CrawlPageSchema = z2.object({
4045
+ url: z2.string(),
4046
+ title: z2.string(),
4047
+ content: z2.string(),
4048
+ links: z2.array(z2.string()),
4049
+ crawledAt: z2.string()
4012
4050
  });
4013
- var CrawlResultSchema = z.object({
4014
- pages: z.array(CrawlPageSchema)
4051
+ var CrawlResultSchema = z2.object({
4052
+ pages: z2.array(CrawlPageSchema)
4015
4053
  });
4016
- var HeadlessResultSchema = z.object({
4017
- html: z.string(),
4018
- markdown: z.string(),
4019
- links: z.array(z.union([CrawledLinkSchema, z.string()]))
4054
+ var HeadlessResultSchema = z2.object({
4055
+ html: z2.string(),
4056
+ markdown: z2.string(),
4057
+ links: z2.array(z2.union([CrawledLinkSchema, z2.string()]))
4020
4058
  });
4021
4059
  function validateHeadlessResult(data) {
4022
4060
  return HeadlessResultSchema.parse(data);
@@ -4024,33 +4062,33 @@ function validateHeadlessResult(data) {
4024
4062
  function validateCrawlResult(data) {
4025
4063
  return CrawlResultSchema.parse(data);
4026
4064
  }
4027
- var MethodInfoSchema = z.object({
4028
- name: z.string(),
4029
- async: z.boolean(),
4030
- signature: z.string(),
4031
- startLine: z.number(),
4032
- endLine: z.number(),
4033
- calls: z.array(z.string())
4065
+ var MethodInfoSchema = z2.object({
4066
+ name: z2.string(),
4067
+ async: z2.boolean(),
4068
+ signature: z2.string(),
4069
+ startLine: z2.number(),
4070
+ endLine: z2.number(),
4071
+ calls: z2.array(z2.string())
4034
4072
  });
4035
- var CodeNodeSchema = z.object({
4036
- type: z.enum(["function", "class"]),
4037
- name: z.string(),
4038
- exported: z.boolean(),
4039
- startLine: z.number(),
4040
- endLine: z.number(),
4041
- async: z.boolean().optional(),
4042
- signature: z.string().optional(),
4043
- calls: z.array(z.string()).optional(),
4044
- methods: z.array(MethodInfoSchema).optional()
4073
+ var CodeNodeSchema = z2.object({
4074
+ type: z2.enum(["function", "class"]),
4075
+ name: z2.string(),
4076
+ exported: z2.boolean(),
4077
+ startLine: z2.number(),
4078
+ endLine: z2.number(),
4079
+ async: z2.boolean().optional(),
4080
+ signature: z2.string().optional(),
4081
+ calls: z2.array(z2.string()).optional(),
4082
+ methods: z2.array(MethodInfoSchema).optional()
4045
4083
  });
4046
- var ImportInfoSchema = z.object({
4047
- source: z.string(),
4048
- imported: z.string(),
4049
- alias: z.string().optional().nullable()
4084
+ var ImportInfoSchema = z2.object({
4085
+ source: z2.string(),
4086
+ imported: z2.string(),
4087
+ alias: z2.string().optional().nullable()
4050
4088
  });
4051
- var ParsePythonResultSchema = z.object({
4052
- nodes: z.array(CodeNodeSchema),
4053
- imports: z.array(ImportInfoSchema)
4089
+ var ParsePythonResultSchema = z2.object({
4090
+ nodes: z2.array(CodeNodeSchema),
4091
+ imports: z2.array(ImportInfoSchema)
4054
4092
  });
4055
4093
  function validateParsePythonResult(data) {
4056
4094
  return ParsePythonResultSchema.parse(data);
@@ -4345,10 +4383,36 @@ var EmbeddingEngine = class {
4345
4383
  getDimensions() {
4346
4384
  return this.dimensions;
4347
4385
  }
4386
+ /**
4387
+ * Dispose the embedding pipeline to free resources.
4388
+ * Should be called before process exit to prevent ONNX runtime cleanup issues on macOS.
4389
+ */
4390
+ async dispose() {
4391
+ if (this.extractor !== null) {
4392
+ await this.extractor.dispose();
4393
+ this.extractor = null;
4394
+ }
4395
+ }
4348
4396
  };
4349
4397
 
4350
4398
  // src/db/lance.ts
4351
4399
  import * as lancedb from "@lancedb/lancedb";
4400
+
4401
+ // src/types/document.ts
4402
+ import { z as z3 } from "zod";
4403
+ var DocumentTypeSchema = z3.enum(["file", "chunk", "web"]);
4404
+ var DocumentMetadataSchema = z3.object({
4405
+ path: z3.string().optional(),
4406
+ url: z3.string().optional(),
4407
+ type: DocumentTypeSchema,
4408
+ storeId: z3.string(),
4409
+ indexedAt: z3.union([z3.string(), z3.date()]),
4410
+ fileHash: z3.string().optional(),
4411
+ chunkIndex: z3.number().optional(),
4412
+ totalChunks: z3.number().optional()
4413
+ }).loose();
4414
+
4415
+ // src/db/lance.ts
4352
4416
  var LanceStore = class {
4353
4417
  connection = null;
4354
4418
  tables = /* @__PURE__ */ new Map();
@@ -4395,13 +4459,17 @@ var LanceStore = class {
4395
4459
  const table = await this.getTable(storeId);
4396
4460
  const query = table.vectorSearch(vector).limit(limit).distanceType("cosine");
4397
4461
  const results = await query.toArray();
4398
- return results.map((r) => ({
4399
- id: createDocumentId(r.id),
4400
- content: r.content,
4401
- score: 1 - r._distance,
4402
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
4403
- metadata: JSON.parse(r.metadata)
4404
- }));
4462
+ return results.map((r) => {
4463
+ const metadata = DocumentMetadataSchema.parse(JSON.parse(r.metadata));
4464
+ return {
4465
+ id: createDocumentId(r.id),
4466
+ content: r.content,
4467
+ score: 1 - r._distance,
4468
+ // Schema validates structure, cast to branded type
4469
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
4470
+ metadata
4471
+ };
4472
+ });
4405
4473
  }
4406
4474
  async createFtsIndex(storeId) {
4407
4475
  const table = await this.getTable(storeId);
@@ -4412,13 +4480,17 @@ var LanceStore = class {
4412
4480
  async fullTextSearch(storeId, query, limit) {
4413
4481
  const table = await this.getTable(storeId);
4414
4482
  const results = await table.search(query, "fts").limit(limit).toArray();
4415
- return results.map((r) => ({
4416
- id: createDocumentId(r.id),
4417
- content: r.content,
4418
- score: r._score,
4419
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
4420
- metadata: JSON.parse(r.metadata)
4421
- }));
4483
+ return results.map((r) => {
4484
+ const metadata = DocumentMetadataSchema.parse(JSON.parse(r.metadata));
4485
+ return {
4486
+ id: createDocumentId(r.id),
4487
+ content: r.content,
4488
+ score: r._score,
4489
+ // Schema validates structure, cast to branded type
4490
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
4491
+ metadata
4492
+ };
4493
+ });
4422
4494
  }
4423
4495
  async deleteStore(storeId) {
4424
4496
  const tableName = this.getTableName(storeId);
@@ -4502,6 +4574,13 @@ async function destroyServices(services) {
4502
4574
  logger4.error({ error }, "Error closing LanceStore");
4503
4575
  errors.push(error);
4504
4576
  }
4577
+ try {
4578
+ await services.embeddings.dispose();
4579
+ } catch (e) {
4580
+ const error = e instanceof Error ? e : new Error(String(e));
4581
+ logger4.error({ error }, "Error disposing EmbeddingEngine");
4582
+ errors.push(error);
4583
+ }
4505
4584
  try {
4506
4585
  await services.pythonBridge.stop();
4507
4586
  } catch (e) {
@@ -4538,4 +4617,4 @@ export {
4538
4617
  createServices,
4539
4618
  destroyServices
4540
4619
  };
4541
- //# sourceMappingURL=chunk-C4SYGLAI.js.map
4620
+ //# sourceMappingURL=chunk-VTATT3IR.js.map