bluera-knowledge 0.9.36 → 0.9.38

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/CHANGELOG.md CHANGED
@@ -2,6 +2,47 @@
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.9.38](https://github.com/blueraai/bluera-knowledge/compare/v0.9.32...v0.9.38) (2026-01-08)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **bridge:** kill Python process before nullifying to prevent zombie ([393dab3](https://github.com/blueraai/bluera-knowledge/commit/393dab3e45c75fd87c9ecfc1ca92e67b14526e79))
11
+ * **bridge:** mock kill() emits exit event & attach rejection handlers before stop ([d73c6ca](https://github.com/blueraai/bluera-knowledge/commit/d73c6ca6d640c3d15bd82756cabcda832f9ae245))
12
+ * **bridge:** stop() now waits for process to actually exit ([a92de41](https://github.com/blueraai/bluera-knowledge/commit/a92de41c89318fc106f996568ed88505352d5159))
13
+ * **cli:** ensure destroyServices runs before process.exit ([22e4267](https://github.com/blueraai/bluera-knowledge/commit/22e4267b7b9f698de3985a89b9c2b10759cfd49c))
14
+ * **code-unit:** brace counting now handles strings and comments ([1e857bb](https://github.com/blueraai/bluera-knowledge/commit/1e857bb297f357b97a6c067950e62495b3c8fc99))
15
+ * **code-unit:** support complex return types in signature extraction ([3bd2467](https://github.com/blueraai/bluera-knowledge/commit/3bd24675a67e73cc74a0c718f4b5a9e86cd826fb))
16
+ * **job:** validate PID before process.kill to prevent process group kill ([67c540f](https://github.com/blueraai/bluera-knowledge/commit/67c540fef6f2c55c5dca2c824104a91fe19aeff1))
17
+ * **search:** apply threshold filtering after score normalization ([1ebc78e](https://github.com/blueraai/bluera-knowledge/commit/1ebc78e0e688ffde0fdbaf049f17a35d129ef055))
18
+ * **search:** enable FTS-only search mode ([4a0f371](https://github.com/blueraai/bluera-knowledge/commit/4a0f371f0c42f80bf87e28ae0e609ac95986964d))
19
+ * **services:** fail fast on corrupted config/registry files ([030f63c](https://github.com/blueraai/bluera-knowledge/commit/030f63c10b0a30bddcd8e9b27b291ab0f53263f1))
20
+ * **tests:** increase timeout for exit code test in CI ([a362dcd](https://github.com/blueraai/bluera-knowledge/commit/a362dcdae32b0c19e757270e5009b0c1c5ead4e4))
21
+ * **tests:** increase timeout for flaky store delete test ([738fb49](https://github.com/blueraai/bluera-knowledge/commit/738fb4975653703d800dee802730dedfdf9e85ba))
22
+ * **watch:** clear pending timeouts on unwatch to prevent timer leak ([4dcafc1](https://github.com/blueraai/bluera-knowledge/commit/4dcafc14417442f6eeed0257cf185e04ae9de12b))
23
+ * **worker:** fail fast on PID file write error ([d92ce42](https://github.com/blueraai/bluera-knowledge/commit/d92ce42eff63cee3c97056ef019f5a52ef699edd))
24
+ * **worker:** prevent division by zero and improve cancellation handling ([b7b40ab](https://github.com/blueraai/bluera-knowledge/commit/b7b40ab950b7ad0fbbe84af243be3138b1072a72))
25
+
26
+ ## [0.9.37](https://github.com/blueraai/bluera-knowledge/compare/v0.9.32...v0.9.37) (2026-01-08)
27
+
28
+
29
+ ### Bug Fixes
30
+
31
+ * **bridge:** kill Python process before nullifying to prevent zombie ([393dab3](https://github.com/blueraai/bluera-knowledge/commit/393dab3e45c75fd87c9ecfc1ca92e67b14526e79))
32
+ * **bridge:** mock kill() emits exit event & attach rejection handlers before stop ([d73c6ca](https://github.com/blueraai/bluera-knowledge/commit/d73c6ca6d640c3d15bd82756cabcda832f9ae245))
33
+ * **bridge:** stop() now waits for process to actually exit ([a92de41](https://github.com/blueraai/bluera-knowledge/commit/a92de41c89318fc106f996568ed88505352d5159))
34
+ * **cli:** ensure destroyServices runs before process.exit ([22e4267](https://github.com/blueraai/bluera-knowledge/commit/22e4267b7b9f698de3985a89b9c2b10759cfd49c))
35
+ * **code-unit:** brace counting now handles strings and comments ([1e857bb](https://github.com/blueraai/bluera-knowledge/commit/1e857bb297f357b97a6c067950e62495b3c8fc99))
36
+ * **code-unit:** support complex return types in signature extraction ([3bd2467](https://github.com/blueraai/bluera-knowledge/commit/3bd24675a67e73cc74a0c718f4b5a9e86cd826fb))
37
+ * **job:** validate PID before process.kill to prevent process group kill ([67c540f](https://github.com/blueraai/bluera-knowledge/commit/67c540fef6f2c55c5dca2c824104a91fe19aeff1))
38
+ * **search:** apply threshold filtering after score normalization ([1ebc78e](https://github.com/blueraai/bluera-knowledge/commit/1ebc78e0e688ffde0fdbaf049f17a35d129ef055))
39
+ * **services:** fail fast on corrupted config/registry files ([030f63c](https://github.com/blueraai/bluera-knowledge/commit/030f63c10b0a30bddcd8e9b27b291ab0f53263f1))
40
+ * **tests:** increase timeout for exit code test in CI ([a362dcd](https://github.com/blueraai/bluera-knowledge/commit/a362dcdae32b0c19e757270e5009b0c1c5ead4e4))
41
+ * **tests:** increase timeout for flaky store delete test ([738fb49](https://github.com/blueraai/bluera-knowledge/commit/738fb4975653703d800dee802730dedfdf9e85ba))
42
+ * **watch:** clear pending timeouts on unwatch to prevent timer leak ([4dcafc1](https://github.com/blueraai/bluera-knowledge/commit/4dcafc14417442f6eeed0257cf185e04ae9de12b))
43
+ * **worker:** fail fast on PID file write error ([d92ce42](https://github.com/blueraai/bluera-knowledge/commit/d92ce42eff63cee3c97056ef019f5a52ef699edd))
44
+ * **worker:** prevent division by zero and improve cancellation handling ([b7b40ab](https://github.com/blueraai/bluera-knowledge/commit/b7b40ab950b7ad0fbbe84af243be3138b1072a72))
45
+
5
46
  ## [0.9.36](https://github.com/blueraai/bluera-knowledge/compare/v0.9.32...v0.9.36) (2026-01-08)
6
47
 
7
48
 
@@ -4,7 +4,7 @@ import {
4
4
  createServices,
5
5
  createStoreId,
6
6
  summarizePayload
7
- } from "./chunk-WFNPNAAP.js";
7
+ } from "./chunk-XJFV7AJW.js";
8
8
 
9
9
  // src/mcp/server.ts
10
10
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -1086,4 +1086,4 @@ export {
1086
1086
  createMCPServer,
1087
1087
  runMCPServer
1088
1088
  };
1089
- //# sourceMappingURL=chunk-Z2KKVH45.js.map
1089
+ //# sourceMappingURL=chunk-36IFANFI.js.map
@@ -2310,6 +2310,7 @@ var IndexService = class {
2310
2310
  }
2311
2311
  if (documents.length > 0) {
2312
2312
  await this.lanceStore.addDocuments(store.id, documents);
2313
+ await this.lanceStore.createFtsIndex(store.id);
2313
2314
  }
2314
2315
  if (this.codeGraphService && sourceFiles.length > 0) {
2315
2316
  const graph = await this.codeGraphService.buildGraph(sourceFiles);
@@ -2839,6 +2840,33 @@ var SearchService = class {
2839
2840
  const lowerContent = content.toLowerCase();
2840
2841
  return queryTerms.filter((term) => lowerContent.includes(term)).length;
2841
2842
  }
2843
+ /**
2844
+ * Normalize scores to 0-1 range and optionally filter by threshold.
2845
+ * This ensures threshold values match displayed scores (UX consistency).
2846
+ *
2847
+ * Edge case handling:
2848
+ * - If there's only 1 result or all results have the same score, normalization
2849
+ * would make them all 1.0. In this case, we keep the raw scores to allow
2850
+ * threshold filtering to work meaningfully on absolute quality.
2851
+ */
2852
+ normalizeAndFilterScores(results, threshold) {
2853
+ if (results.length === 0) return [];
2854
+ const sorted = [...results].sort((a, b) => b.score - a.score);
2855
+ const first = sorted[0];
2856
+ const last = sorted[sorted.length - 1];
2857
+ if (first === void 0 || last === void 0) return [];
2858
+ const maxScore = first.score;
2859
+ const minScore = last.score;
2860
+ const range = maxScore - minScore;
2861
+ const normalized = range > 0 ? sorted.map((r) => ({
2862
+ ...r,
2863
+ score: Math.round((r.score - minScore) / range * 1e6) / 1e6
2864
+ })) : sorted;
2865
+ if (threshold !== void 0) {
2866
+ return normalized.filter((r) => r.score >= threshold);
2867
+ }
2868
+ return normalized;
2869
+ }
2842
2870
  async vectorSearch(query, stores, limit, threshold) {
2843
2871
  const queryVector = await this.embeddingEngine.embed(query);
2844
2872
  const results = [];
@@ -2853,7 +2881,8 @@ var SearchService = class {
2853
2881
  }))
2854
2882
  );
2855
2883
  }
2856
- return results.sort((a, b) => b.score - a.score).slice(0, limit);
2884
+ const normalized = this.normalizeAndFilterScores(results, threshold);
2885
+ return normalized.slice(0, limit);
2857
2886
  }
2858
2887
  async ftsSearch(query, stores, limit) {
2859
2888
  const results = [];
@@ -2873,7 +2902,7 @@ var SearchService = class {
2873
2902
  async hybridSearch(query, stores, limit, threshold) {
2874
2903
  const intents = classifyQueryIntents(query);
2875
2904
  const [vectorResults, ftsResults] = await Promise.all([
2876
- this.vectorSearch(query, stores, limit * 2, threshold),
2905
+ this.vectorSearch(query, stores, limit * 2),
2877
2906
  this.ftsSearch(query, stores, limit * 2)
2878
2907
  ]);
2879
2908
  const vectorRanks = /* @__PURE__ */ new Map();
@@ -2927,32 +2956,41 @@ var SearchService = class {
2927
2956
  });
2928
2957
  }
2929
2958
  const sorted = rrfScores.sort((a, b) => b.score - a.score).slice(0, limit);
2959
+ let normalizedResults;
2930
2960
  if (sorted.length > 0) {
2931
2961
  const first = sorted[0];
2932
2962
  const last = sorted[sorted.length - 1];
2933
2963
  if (first === void 0 || last === void 0) {
2934
- return sorted.map((r) => ({
2964
+ normalizedResults = sorted.map((r) => ({
2935
2965
  ...r.result,
2936
2966
  score: r.score,
2937
2967
  rankingMetadata: r.metadata
2938
2968
  }));
2969
+ } else {
2970
+ const maxScore = first.score;
2971
+ const minScore = last.score;
2972
+ const range = maxScore - minScore;
2973
+ if (range > 0) {
2974
+ normalizedResults = sorted.map((r) => ({
2975
+ ...r.result,
2976
+ score: Math.round((r.score - minScore) / range * 1e6) / 1e6,
2977
+ rankingMetadata: r.metadata
2978
+ }));
2979
+ } else {
2980
+ normalizedResults = sorted.map((r) => ({
2981
+ ...r.result,
2982
+ score: r.score,
2983
+ rankingMetadata: r.metadata
2984
+ }));
2985
+ }
2939
2986
  }
2940
- const maxScore = first.score;
2941
- const minScore = last.score;
2942
- const range = maxScore - minScore;
2943
- if (range > 0) {
2944
- return sorted.map((r) => ({
2945
- ...r.result,
2946
- score: (r.score - minScore) / range,
2947
- rankingMetadata: r.metadata
2948
- }));
2949
- }
2987
+ } else {
2988
+ normalizedResults = [];
2950
2989
  }
2951
- return sorted.map((r) => ({
2952
- ...r.result,
2953
- score: r.score,
2954
- rankingMetadata: r.metadata
2955
- }));
2990
+ if (threshold !== void 0) {
2991
+ return normalizedResults.filter((r) => r.score >= threshold);
2992
+ }
2993
+ return normalizedResults;
2956
2994
  }
2957
2995
  async searchAllStores(query, storeIds) {
2958
2996
  return this.search({
@@ -4016,18 +4054,11 @@ var LanceStore = class {
4016
4054
  const idList = documentIds.map((id) => `"${id}"`).join(", ");
4017
4055
  await table.delete(`id IN (${idList})`);
4018
4056
  }
4019
- async search(storeId, vector, limit, threshold) {
4057
+ async search(storeId, vector, limit, _threshold) {
4020
4058
  const table = await this.getTable(storeId);
4021
- let query = table.vectorSearch(vector).limit(limit);
4022
- if (threshold !== void 0) {
4023
- query = query.distanceType("cosine");
4024
- }
4059
+ const query = table.vectorSearch(vector).limit(limit).distanceType("cosine");
4025
4060
  const results = await query.toArray();
4026
- return results.filter((r) => {
4027
- if (threshold === void 0) return true;
4028
- const score = 1 - r._distance;
4029
- return score >= threshold;
4030
- }).map((r) => ({
4061
+ return results.map((r) => ({
4031
4062
  id: createDocumentId(r.id),
4032
4063
  content: r.content,
4033
4064
  score: 1 - r._distance,
@@ -4048,7 +4079,7 @@ var LanceStore = class {
4048
4079
  return results.map((r) => ({
4049
4080
  id: createDocumentId(r.id),
4050
4081
  content: r.content,
4051
- score: r.score,
4082
+ score: r._score,
4052
4083
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
4053
4084
  metadata: JSON.parse(r.metadata)
4054
4085
  }));
@@ -4160,4 +4191,4 @@ export {
4160
4191
  createServices,
4161
4192
  destroyServices
4162
4193
  };
4163
- //# sourceMappingURL=chunk-WFNPNAAP.js.map
4194
+ //# sourceMappingURL=chunk-XJFV7AJW.js.map