bluera-knowledge 0.33.2 → 0.34.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bluera-knowledge",
3
- "version": "0.33.1",
3
+ "version": "0.34.0",
4
4
  "description": "Clone repos, crawl docs, search locally. Fast, authoritative answers for AI coding agents.",
5
5
  "author": {
6
6
  "name": "Bluera Inc",
@@ -1,6 +1,4 @@
1
1
  {
2
- "skill_activation": false,
3
2
  "websearch_suggestions": false,
4
- "webfetch_suggestions": false,
5
- "bk_read_suggestions": false
3
+ "webfetch_suggestions": false
6
4
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,33 @@
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.34.0](https://github.com/blueraai/bluera-knowledge/compare/v0.28.0...v0.34.0) (2026-03-08)
6
+
7
+
8
+ ### Features
9
+
10
+ * **activation:** rewrite MCP tool descriptions and simplify hooks for proactive BK usage ([0880aa7](https://github.com/blueraai/bluera-knowledge/commit/0880aa78aa8189957555c58d6e67a562cbae13cb))
11
+ * add statusline module with store count display ([4446501](https://github.com/blueraai/bluera-knowledge/commit/44465015a4734cd7c253bda51c98ce149561fda8))
12
+ * **eval:** 3-agent comparison with BK Grep agent and token tracking ([b3045a8](https://github.com/blueraai/bluera-knowledge/commit/b3045a8ae7df7a2e13ecdf992ff4d1055521460b))
13
+ * **eval:** add agent quality eval comparing with-BK vs without-BK answers ([d8c62d8](https://github.com/blueraai/bluera-knowledge/commit/d8c62d804bd10d572049f4f2a01deb30cb00ccf5))
14
+ * **hooks:** add PostToolUse hook for WebSearch BK suggestions ([d0420b4](https://github.com/blueraai/bluera-knowledge/commit/d0420b473c73092b5e6a28be2699f5fc40e090c3))
15
+ * **mcp:** add file count estimation and ETA to store creation responses ([3d71a30](https://github.com/blueraai/bluera-knowledge/commit/3d71a307275fa06b9810ed606583f4ec2acc5841))
16
+ * **mcp:** add stores:pull command for git pull + re-index ([7ca809c](https://github.com/blueraai/bluera-knowledge/commit/7ca809c3675be19d9d0e29e71c5f75d4f40fce35))
17
+ * **mcp:** optimize search-to-read workflow with store paths, relatedFiles, find-files intent, and file-based get_full_context ([4eb9be9](https://github.com/blueraai/bluera-knowledge/commit/4eb9be97598e475576603b2b9a565946197986ac))
18
+ * search infrastructure, benchmark framework, and model registry ([285ff2f](https://github.com/blueraai/bluera-knowledge/commit/285ff2f5574c4d53b61b31e84fdec43553364e98))
19
+ * **search:** add strong-signal FTS bypass, position-aware reranking, and query expansion ([c9b6eac](https://github.com/blueraai/bluera-knowledge/commit/c9b6eac7de9a6f17100b37879304df5a634b5559))
20
+ * training pipeline, evaluation gate, and experiment docs ([d90b395](https://github.com/blueraai/bluera-knowledge/commit/d90b395a330f4ab09ac6d71db77d659c415aa87d))
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * **ci:** remove simple mode from validation and lower coverage threshold ([7aea1ac](https://github.com/blueraai/bluera-knowledge/commit/7aea1ac466de8ee13c6dc85c00932838d41ff829))
26
+ * **config:** wire BK_MODEL env var override in ConfigService.load() ([be56426](https://github.com/blueraai/bluera-knowledge/commit/be564263176410c3eb1441bf85c4fdce48ddc7c4))
27
+ * **crawl:** fix nested session error and remove simple mode ([79447b4](https://github.com/blueraai/bluera-knowledge/commit/79447b4604e54760af433deb21e177f9a71cbe8e))
28
+ * **hooks:** drain stdin in shell hooks, register web-research hook, add settings.json ([1cff9b8](https://github.com/blueraai/bluera-knowledge/commit/1cff9b8ab38e732ffa6d9fb2de8b398fddc98302))
29
+ * **mcp:** add runtime files to package.json files array and improve bootstrap error on corrupt cache ([e195f93](https://github.com/blueraai/bluera-knowledge/commit/e195f93a4600c65bcd0fcbb45380aaa1d32bb356))
30
+ * **mcp:** prevent browser postinstall from crashing bootstrap ([e27fe02](https://github.com/blueraai/bluera-knowledge/commit/e27fe021bdb34c8ca5b8bf93720a176435e7973c))
31
+
5
32
  ## [0.33.1](https://github.com/blueraai/bluera-knowledge/compare/v0.28.0...v0.33.1) (2026-03-03)
6
33
 
7
34
 
@@ -2,7 +2,7 @@ import {
2
2
  createLogger,
3
3
  summarizePayload,
4
4
  truncateForLog
5
- } from "./chunk-SROFPHRA.js";
5
+ } from "./chunk-FYHKBCIH.js";
6
6
 
7
7
  // src/crawl/intelligent-crawler.ts
8
8
  import { EventEmitter } from "events";
@@ -798,4 +798,4 @@ export {
798
798
  getCrawlStrategy,
799
799
  IntelligentCrawler
800
800
  };
801
- //# sourceMappingURL=chunk-OMXQBWCR.js.map
801
+ //# sourceMappingURL=chunk-4S6LWHKI.js.map
@@ -4951,6 +4951,32 @@ function mapSearchIntentToQueryIntent(intent) {
4951
4951
  return "how-to";
4952
4952
  }
4953
4953
  }
4954
+ var INTENT_EXPANSION_TERMS = {
4955
+ "find-implementation": "source code implementation function class",
4956
+ "find-documentation": "documentation guide tutorial example",
4957
+ "find-usage": "usage example how to use",
4958
+ "find-pattern": "pattern matching code structure",
4959
+ "find-definition": "definition type interface declaration",
4960
+ "find-files": "file module path"
4961
+ };
4962
+ function expandQueryWithIntent(query, intent) {
4963
+ if (intent === void 0) return query;
4964
+ const expansion = INTENT_EXPANSION_TERMS[intent];
4965
+ return `${query} ${expansion}`;
4966
+ }
4967
+ function isStrongFtsSignal(query, ftsResults) {
4968
+ if (ftsResults.length < 2) return false;
4969
+ const top = ftsResults[0];
4970
+ const second = ftsResults[1];
4971
+ if (top === void 0 || second === void 0) return false;
4972
+ if (second.score > 0 && top.score / second.score <= 2) return false;
4973
+ const queryLower = query.toLowerCase();
4974
+ const rawFile = top.metadata["file"] ?? top.metadata["path"];
4975
+ const rawName = top.metadata["name"];
4976
+ const filePath = typeof rawFile === "string" ? rawFile : "";
4977
+ const name = typeof rawName === "string" ? rawName : "";
4978
+ return filePath.toLowerCase().includes(queryLower) || name.toLowerCase().includes(queryLower);
4979
+ }
4954
4980
  var RRF_PRESETS = {
4955
4981
  code: { k: 25, vectorWeight: 0.75, ftsWeight: 0.25 },
4956
4982
  web: { k: 30, vectorWeight: 0.7, ftsWeight: 0.3 }
@@ -5039,7 +5065,8 @@ var SearchService = class {
5039
5065
  let rerankTimeMs;
5040
5066
  const fetchLimit = limit * 3;
5041
5067
  if (mode === "vector") {
5042
- const rawResults = await this.vectorSearchRaw(query.query, stores, fetchLimit);
5068
+ const expandedQuery = expandQueryWithIntent(query.query, query.intent);
5069
+ const rawResults = await this.vectorSearchRaw(expandedQuery, stores, fetchLimit);
5043
5070
  maxRawScore = rawResults.length > 0 ? rawResults[0]?.score ?? 0 : 0;
5044
5071
  allResults = this.normalizeAndFilterScores(rawResults, query.threshold).slice(0, fetchLimit);
5045
5072
  } else if (mode === "fts") {
@@ -5049,7 +5076,8 @@ var SearchService = class {
5049
5076
  query.query,
5050
5077
  stores,
5051
5078
  fetchLimit,
5052
- query.threshold
5079
+ query.threshold,
5080
+ query.intent
5053
5081
  );
5054
5082
  allResults = hybridResult.results;
5055
5083
  maxRawScore = hybridResult.maxRawScore;
@@ -5230,18 +5258,37 @@ var SearchService = class {
5230
5258
  /**
5231
5259
  * Internal hybrid search result with additional metadata for confidence calculation.
5232
5260
  */
5233
- async hybridSearchWithMetadata(query, stores, limit, threshold) {
5261
+ async hybridSearchWithMetadata(query, stores, limit, threshold, searchIntent) {
5234
5262
  const intents = classifyQueryIntents(query);
5235
5263
  const envOverrides = parseSearchEnvOverrides(false);
5236
5264
  const candidateMultiplier = envOverrides.candidateMultiplier ?? DEFAULT_CANDIDATE_MULTIPLIER;
5237
- const rawVectorResults = await this.vectorSearchRaw(query, stores, limit * candidateMultiplier);
5265
+ const ftsResults = await this.ftsSearch(query, stores, limit * candidateMultiplier);
5266
+ if (isStrongFtsSignal(query, ftsResults)) {
5267
+ logger4.debug(
5268
+ { query, topScore: ftsResults[0]?.score },
5269
+ "Strong FTS signal \u2014 skipping vector search"
5270
+ );
5271
+ const sorted2 = ftsResults.slice(0, limit).map((r, i) => ({
5272
+ ...r,
5273
+ score: Math.round((1 - i / Math.max(ftsResults.length, 1)) * 1e6) / 1e6
5274
+ }));
5275
+ if (threshold !== void 0) {
5276
+ return { results: sorted2.filter((r) => r.score >= threshold), maxRawScore: 0 };
5277
+ }
5278
+ return { results: sorted2, maxRawScore: 0 };
5279
+ }
5280
+ const expandedQuery = expandQueryWithIntent(query, searchIntent);
5281
+ const rawVectorResults = await this.vectorSearchRaw(
5282
+ expandedQuery,
5283
+ stores,
5284
+ limit * candidateMultiplier
5285
+ );
5238
5286
  const rawVectorScores = /* @__PURE__ */ new Map();
5239
5287
  rawVectorResults.forEach((r) => {
5240
5288
  rawVectorScores.set(r.id, r.score);
5241
5289
  });
5242
5290
  const maxRawScore = rawVectorResults.length > 0 ? rawVectorResults[0]?.score ?? 0 : 0;
5243
5291
  const vectorResults = this.normalizeAndFilterScores(rawVectorResults);
5244
- const ftsResults = await this.ftsSearch(query, stores, limit * candidateMultiplier);
5245
5292
  const vectorRanks = /* @__PURE__ */ new Map();
5246
5293
  const ftsRanks = /* @__PURE__ */ new Map();
5247
5294
  const allDocs = /* @__PURE__ */ new Map();
@@ -5319,10 +5366,20 @@ var SearchService = class {
5319
5366
  reranked.results.forEach((r) => {
5320
5367
  rerankedScores.set(r.id, r.rerankerScore);
5321
5368
  });
5322
- sorted = sortedAll.map((r) => ({
5323
- ...r,
5324
- rerankerScore: rerankedScores.get(r.id)
5325
- })).sort((a, b) => (b.rerankerScore ?? -Infinity) - (a.rerankerScore ?? -Infinity)).slice(0, limit);
5369
+ const maxRrfScore = sortedAll[0]?.score ?? 1;
5370
+ sorted = sortedAll.map((r, rrfRank) => {
5371
+ const rerankerScore = rerankedScores.get(r.id);
5372
+ if (rerankerScore === void 0) {
5373
+ return { ...r, blendedScore: -Infinity };
5374
+ }
5375
+ const normalizedRrf = maxRrfScore > 0 ? r.score / maxRrfScore : 0;
5376
+ const rrfWeight = rrfRank < 3 ? 0.7 : rrfRank < 10 ? 0.5 : 0.3;
5377
+ const rerankerWeight = 1 - rrfWeight;
5378
+ return {
5379
+ ...r,
5380
+ blendedScore: normalizedRrf * rrfWeight + rerankerScore * rerankerWeight
5381
+ };
5382
+ }).sort((a, b) => b.blendedScore - a.blendedScore).slice(0, limit);
5326
5383
  } else {
5327
5384
  sorted = sortedAll.slice(0, limit);
5328
5385
  }
@@ -7575,4 +7632,4 @@ export {
7575
7632
  createServices,
7576
7633
  destroyServices
7577
7634
  };
7578
- //# sourceMappingURL=chunk-SROFPHRA.js.map
7635
+ //# sourceMappingURL=chunk-FYHKBCIH.js.map