bluera-knowledge 0.31.0 → 0.32.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.
Files changed (67) hide show
  1. package/.claude-plugin/plugin.json +24 -0
  2. package/.mcp.json +13 -0
  3. package/CHANGELOG.md +20 -0
  4. package/NOTICE +47 -0
  5. package/README.md +2 -2
  6. package/bun.lock +1978 -0
  7. package/commands/add-folder.md +48 -0
  8. package/commands/add-repo.md +50 -0
  9. package/commands/cancel.md +63 -0
  10. package/commands/check-status.md +130 -0
  11. package/commands/crawl.md +61 -0
  12. package/commands/doctor.md +27 -0
  13. package/commands/eval.md +222 -0
  14. package/commands/health.md +72 -0
  15. package/commands/index.md +48 -0
  16. package/commands/remove-store.md +52 -0
  17. package/commands/search.md +80 -0
  18. package/commands/search.sh +63 -0
  19. package/commands/skill-activation.md +131 -0
  20. package/commands/stores.md +54 -0
  21. package/commands/suggest.md +118 -0
  22. package/commands/sync.md +96 -0
  23. package/commands/test-plugin.md +547 -0
  24. package/commands/uninstall.md +65 -0
  25. package/dist/{chunk-B335UOU7.js → chunk-3TB7TDVF.js} +24 -3
  26. package/dist/chunk-3TB7TDVF.js.map +1 -0
  27. package/dist/{chunk-KCI4U6FH.js → chunk-KDZDLJUY.js} +2 -2
  28. package/dist/{chunk-AEXFPA57.js → chunk-YDTTD53Y.js} +158 -26
  29. package/dist/chunk-YDTTD53Y.js.map +1 -0
  30. package/dist/index.js +3 -3
  31. package/dist/mcp/bootstrap.js +10 -0
  32. package/dist/mcp/bootstrap.js.map +1 -1
  33. package/dist/mcp/server.d.ts +5 -3
  34. package/dist/mcp/server.js +2 -2
  35. package/dist/workers/background-worker-cli.js +2 -2
  36. package/hooks/check-ready.sh +109 -0
  37. package/hooks/hooks.json +87 -0
  38. package/hooks/job-status-hook.sh +51 -0
  39. package/hooks/posttooluse-bk-reminder.py +126 -0
  40. package/hooks/posttooluse-web-research.py +209 -0
  41. package/hooks/pretooluse-bk-suggest.py +296 -0
  42. package/hooks/skill-activation.py +221 -0
  43. package/hooks/skill-rules.json +131 -0
  44. package/package.json +10 -2
  45. package/scripts/CLAUDE.md +65 -0
  46. package/scripts/auto-setup.sh +65 -0
  47. package/scripts/bench-regression.sh +345 -0
  48. package/scripts/dev.sh +16 -0
  49. package/scripts/doctor.sh +103 -0
  50. package/scripts/download-models.ts +188 -0
  51. package/scripts/export-web-store.ts +142 -0
  52. package/scripts/lib/mock-server.sh +70 -0
  53. package/scripts/mcp-wrapper.sh +91 -0
  54. package/scripts/setup.sh +224 -0
  55. package/scripts/test-mcp-dev.js +260 -0
  56. package/scripts/validate-local.sh +412 -0
  57. package/scripts/validate-npm-release.sh +406 -0
  58. package/skills/advanced-workflows/SKILL.md +273 -0
  59. package/skills/knowledge-search/SKILL.md +110 -0
  60. package/skills/search-optimization/SKILL.md +199 -0
  61. package/skills/search-optimization/references/mistakes.md +21 -0
  62. package/skills/search-optimization/references/strategies.md +80 -0
  63. package/skills/store-lifecycle/SKILL.md +470 -0
  64. package/skills/when-to-query/SKILL.md +160 -0
  65. package/dist/chunk-AEXFPA57.js.map +0 -1
  66. package/dist/chunk-B335UOU7.js.map +0 -1
  67. /package/dist/{chunk-KCI4U6FH.js.map → chunk-KDZDLJUY.js.map} +0 -0
@@ -2,7 +2,7 @@ import {
2
2
  createLogger,
3
3
  summarizePayload,
4
4
  truncateForLog
5
- } from "./chunk-B335UOU7.js";
5
+ } from "./chunk-3TB7TDVF.js";
6
6
 
7
7
  // src/crawl/intelligent-crawler.ts
8
8
  import { EventEmitter } from "events";
@@ -916,4 +916,4 @@ export {
916
916
  getCrawlStrategy,
917
917
  IntelligentCrawler
918
918
  };
919
- //# sourceMappingURL=chunk-KCI4U6FH.js.map
919
+ //# sourceMappingURL=chunk-KDZDLJUY.js.map
@@ -12,7 +12,7 @@ import {
12
12
  isWebStoreDefinition,
13
13
  ok,
14
14
  summarizePayload
15
- } from "./chunk-B335UOU7.js";
15
+ } from "./chunk-3TB7TDVF.js";
16
16
  import {
17
17
  DEFAULT_IGNORE_DIRS,
18
18
  checkStoreModelCompatibility
@@ -656,7 +656,8 @@ var SearchArgsSchema = z.object({
656
656
  "find-implementation",
657
657
  "find-usage",
658
658
  "find-definition",
659
- "find-documentation"
659
+ "find-documentation",
660
+ "find-files"
660
661
  ]).optional(),
661
662
  mode: z.enum(["vector", "fts", "hybrid"]).default("hybrid"),
662
663
  detail: z.enum(["minimal", "contextual", "full"]).default("minimal"),
@@ -666,7 +667,11 @@ var SearchArgsSchema = z.object({
666
667
  minRelevance: z.number().min(0, "minRelevance must be between 0 and 1").max(1, "minRelevance must be between 0 and 1").optional()
667
668
  });
668
669
  var GetFullContextArgsSchema = z.object({
669
- resultId: z.string().min(1, "Result ID must be a non-empty string")
670
+ resultId: z.string().min(1, "Result ID must be a non-empty string").optional(),
671
+ file: z.string().min(1, "File path must be a non-empty string").optional(),
672
+ store: z.string().min(1, "Store name or ID").optional()
673
+ }).refine((data) => data.resultId !== void 0 || data.file !== void 0, {
674
+ message: "Either resultId or file must be provided"
670
675
  });
671
676
  var ListStoresArgsSchema = z.object({
672
677
  type: z.enum(["file", "repo", "web"]).optional()
@@ -2242,7 +2247,14 @@ var LRUCache = class {
2242
2247
  var logger10 = createLogger("mcp-search");
2243
2248
  var resultCache = new LRUCache(1e3);
2244
2249
  var handleSearch = async (args, context) => {
2245
- const validated = SearchArgsSchema.parse(args);
2250
+ let validated = SearchArgsSchema.parse(args);
2251
+ if (validated.intent === "find-files") {
2252
+ validated = {
2253
+ ...validated,
2254
+ detail: "minimal",
2255
+ ...validated.limit === 10 ? { limit: 20 } : {}
2256
+ };
2257
+ }
2246
2258
  logger10.info(
2247
2259
  {
2248
2260
  query: validated.query,
@@ -2310,24 +2322,73 @@ var handleSearch = async (args, context) => {
2310
2322
  for (const result of results.results) {
2311
2323
  resultCache.set(result.id, result);
2312
2324
  }
2313
- const enhancedResults = await Promise.all(
2314
- results.results.map(async (r) => {
2315
- const storeId = r.metadata.storeId;
2316
- const store = await services.store.getByIdOrName(storeId);
2317
- return {
2318
- id: r.id,
2319
- score: r.score,
2320
- summary: {
2321
- ...r.summary,
2322
- storeName: store?.name,
2323
- repoRoot: store?.type === "repo" ? store.path : void 0
2324
- },
2325
- context: r.context,
2326
- full: r.full
2327
- };
2328
- })
2329
- );
2325
+ const storeById = /* @__PURE__ */ new Map();
2326
+ const uniqueStoreIds = new Set(results.results.map((r) => r.metadata.storeId));
2327
+ for (const storeId of uniqueStoreIds) {
2328
+ const store = await services.store.getByIdOrName(storeId);
2329
+ if (store) storeById.set(storeId, store);
2330
+ }
2331
+ const storeMap = {};
2332
+ for (const store of storeById.values()) {
2333
+ storeMap[store.name] = {
2334
+ type: store.type,
2335
+ ..."path" in store ? { path: store.path } : {},
2336
+ ..."url" in store && store.url !== void 0 ? { url: store.url } : {}
2337
+ };
2338
+ }
2339
+ const enhancedResults = results.results.map((r) => {
2340
+ const store = storeById.get(r.metadata.storeId);
2341
+ return {
2342
+ id: r.id,
2343
+ score: r.score,
2344
+ summary: {
2345
+ ...r.summary,
2346
+ storeName: store?.name,
2347
+ repoRoot: store?.type === "repo" ? store.path : void 0
2348
+ },
2349
+ context: r.context,
2350
+ full: r.full
2351
+ };
2352
+ });
2353
+ if (validated.intent === "find-files") {
2354
+ const seen = /* @__PURE__ */ new Set();
2355
+ const files = enhancedResults.filter((r) => {
2356
+ const loc = r.summary.location?.split(":")[0] ?? "";
2357
+ if (seen.has(loc)) return false;
2358
+ seen.add(loc);
2359
+ return true;
2360
+ }).map((r) => ({
2361
+ location: r.summary.location,
2362
+ name: r.summary.name,
2363
+ type: r.summary.type,
2364
+ score: r.score
2365
+ }));
2366
+ const findFilesData = {
2367
+ files,
2368
+ stores: storeMap,
2369
+ totalResults: files.length,
2370
+ timeMs: results.timeMs
2371
+ };
2372
+ const findFilesJson = JSON.stringify(findFilesData, null, 2);
2373
+ const findFilesTokens = estimateTokens(findFilesJson);
2374
+ const findFilesHeader = `Find files: "${validated.query}" | Files: ${String(files.length)} | ${formatTokenCount(findFilesTokens)} tokens | ${String(results.timeMs)}ms
2375
+
2376
+ `;
2377
+ logger10.info(
2378
+ {
2379
+ query: validated.query,
2380
+ totalFiles: files.length,
2381
+ responseTokens: findFilesTokens,
2382
+ timeMs: results.timeMs
2383
+ },
2384
+ "Find-files search complete"
2385
+ );
2386
+ return {
2387
+ content: [{ type: "text", text: findFilesHeader + findFilesJson }]
2388
+ };
2389
+ }
2330
2390
  const responseData = {
2391
+ stores: storeMap,
2331
2392
  results: enhancedResults,
2332
2393
  totalResults: results.totalResults,
2333
2394
  mode: results.mode,
@@ -2370,6 +2431,70 @@ var handleSearch = async (args, context) => {
2370
2431
  };
2371
2432
  var handleGetFullContext = async (args, context) => {
2372
2433
  const validated = GetFullContextArgsSchema.parse(args);
2434
+ const { services } = context;
2435
+ if (validated.file !== void 0) {
2436
+ const filePath = validated.file;
2437
+ logger10.info({ file: filePath, store: validated.store }, "Get full context by file path");
2438
+ let targetStores;
2439
+ if (validated.store !== void 0) {
2440
+ const store2 = await services.store.getByIdOrName(validated.store);
2441
+ if (!store2) throw new Error(`Store not found: ${validated.store}`);
2442
+ targetStores = [store2];
2443
+ } else {
2444
+ targetStores = await services.store.list();
2445
+ }
2446
+ const currentModelId = services.store.getCurrentModelId();
2447
+ const compatible = targetStores.filter(
2448
+ (s) => checkStoreModelCompatibility(s, { currentModelId }).compatible
2449
+ );
2450
+ if (compatible.length === 0) {
2451
+ throw new Error("No compatible stores found");
2452
+ }
2453
+ services.lance.setDimensions(await services.embeddings.ensureDimensions());
2454
+ for (const s of compatible) {
2455
+ await services.lance.initialize(s.id);
2456
+ }
2457
+ const fileResults = await services.search.search({
2458
+ query: filePath,
2459
+ stores: compatible.map((s) => s.id),
2460
+ mode: "fts",
2461
+ limit: 5,
2462
+ detail: "full"
2463
+ });
2464
+ const matching = fileResults.results.filter(
2465
+ (r) => r.metadata.path?.includes(filePath) === true
2466
+ );
2467
+ if (matching.length === 0) {
2468
+ throw new Error(`No indexed content found for file: ${filePath}`);
2469
+ }
2470
+ for (const r of matching) {
2471
+ resultCache.set(r.id, r);
2472
+ }
2473
+ const responseJson2 = JSON.stringify(
2474
+ {
2475
+ results: matching.map((r) => ({
2476
+ id: r.id,
2477
+ score: r.score,
2478
+ summary: r.summary,
2479
+ context: r.context,
2480
+ full: r.full
2481
+ }))
2482
+ },
2483
+ null,
2484
+ 2
2485
+ );
2486
+ logger10.info(
2487
+ {
2488
+ file: filePath,
2489
+ resultCount: matching.length,
2490
+ ...summarizePayload(responseJson2, "mcp-full-context-file", filePath)
2491
+ },
2492
+ "Full context retrieved by file path"
2493
+ );
2494
+ return {
2495
+ content: [{ type: "text", text: responseJson2 }]
2496
+ };
2497
+ }
2373
2498
  logger10.info({ resultId: validated.resultId }, "Get full context requested");
2374
2499
  const resultId = validated.resultId;
2375
2500
  const cachedResult = resultCache.get(resultId);
@@ -2406,7 +2531,6 @@ var handleGetFullContext = async (args, context) => {
2406
2531
  ]
2407
2532
  };
2408
2533
  }
2409
- const { services } = context;
2410
2534
  const store = await services.store.getByIdOrName(cachedResult.metadata.storeId);
2411
2535
  if (!store) {
2412
2536
  throw new Error(`Store not found: ${cachedResult.metadata.storeId}`);
@@ -2529,7 +2653,8 @@ function createMCPServer(options, services) {
2529
2653
  "find-implementation",
2530
2654
  "find-usage",
2531
2655
  "find-definition",
2532
- "find-documentation"
2656
+ "find-documentation",
2657
+ "find-files"
2533
2658
  ],
2534
2659
  description: "Search intent for better ranking"
2535
2660
  },
@@ -2577,9 +2702,16 @@ function createMCPServer(options, services) {
2577
2702
  resultId: {
2578
2703
  type: "string",
2579
2704
  description: "Result ID from previous search"
2705
+ },
2706
+ file: {
2707
+ type: "string",
2708
+ description: "File path to retrieve context for (alternative to resultId)"
2709
+ },
2710
+ store: {
2711
+ type: "string",
2712
+ description: "Store name to scope file lookup (optional, searches all if omitted)"
2580
2713
  }
2581
- },
2582
- required: ["resultId"]
2714
+ }
2583
2715
  }
2584
2716
  },
2585
2717
  // Meta-tool for store and job management (consolidates 8 tools into 1)
@@ -2694,4 +2826,4 @@ export {
2694
2826
  createMCPServer,
2695
2827
  runMCPServer
2696
2828
  };
2697
- //# sourceMappingURL=chunk-AEXFPA57.js.map
2829
+ //# sourceMappingURL=chunk-YDTTD53Y.js.map