@comfanion/usethis_search 3.0.0-dev.14 → 3.0.0-dev.15

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 (2) hide show
  1. package/package.json +1 -1
  2. package/vectorizer/index.ts +39 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/usethis_search",
3
- "version": "3.0.0-dev.14",
3
+ "version": "3.0.0-dev.15",
4
4
  "description": "OpenCode plugin: semantic search with graph-based context (v3: graph relations, 1-hop context, LSP + regex analyzers)",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -28,8 +28,8 @@ if (!DEBUG) {
28
28
  }
29
29
 
30
30
  /**
31
- * Default index presets (can be overridden by config).
32
- */
31
+ * Default index presets (can be overridden by config).
32
+ */
33
33
  const DEFAULT_PRESETS = {
34
34
  code: {
35
35
  pattern: "**/*.{js,ts,jsx,tsx,mjs,cjs,py,go,rs,java,kt,swift,c,cpp,h,hpp,cs,rb,php,scala,clj}",
@@ -44,22 +44,30 @@ const DEFAULT_PRESETS = {
44
44
  "**/__pycache__/**",
45
45
  ],
46
46
  description: "Source code files (excludes docs, vendor, node_modules)",
47
+ hybrid: true,
48
+ bm25_weight: 0.3,
47
49
  },
48
50
  docs: {
49
51
  pattern: "docs/**/*.{md,mdx,txt,rst,adoc}",
50
52
  ignore: [],
51
53
  description: "Documentation in docs/ folder",
54
+ hybrid: false,
55
+ bm25_weight: 0.2,
52
56
  },
53
57
  config: {
54
58
  pattern: "**/*.{yaml,yml,json,toml,ini,env,xml}",
55
59
  ignore: ["**/node_modules/**", "**/.git/**", "**/.opencode/**"],
56
60
  description: "Configuration files",
61
+ hybrid: false,
62
+ bm25_weight: 0.3,
57
63
  },
58
64
  all: {
59
65
  pattern:
60
66
  "**/*.{js,ts,jsx,tsx,mjs,cjs,py,go,rs,java,kt,swift,c,cpp,h,hpp,cs,rb,php,scala,clj,md,mdx,txt,rst,adoc,yaml,yml,json,toml}",
61
67
  ignore: ["**/node_modules/**", "**/.git/**", "**/.opencode/**"],
62
68
  description: "All supported files",
69
+ hybrid: false,
70
+ bm25_weight: 0.3,
63
71
  },
64
72
  };
65
73
 
@@ -124,15 +132,21 @@ function defaultVectorizerYaml() {
124
132
  ` pattern: \"${DEFAULT_PRESETS.code.pattern}\"\n` +
125
133
  ` ignore:\n` +
126
134
  DEFAULT_PRESETS.code.ignore.map((p) => ` - \"${p}\"\n`).join("") +
135
+ ` hybrid: true\n` +
136
+ ` bm25_weight: 0.3\n` +
127
137
  ` docs:\n` +
128
138
  ` enabled: true\n` +
129
139
  ` pattern: \"${DEFAULT_PRESETS.docs.pattern}\"\n` +
130
140
  ` ignore: []\n` +
141
+ ` hybrid: false\n` +
142
+ ` bm25_weight: 0.2\n` +
131
143
  ` config:\n` +
132
144
  ` enabled: false\n` +
133
145
  ` pattern: \"${DEFAULT_PRESETS.config.pattern}\"\n` +
134
146
  ` ignore:\n` +
135
147
  DEFAULT_PRESETS.config.ignore.map((p) => ` - \"${p}\"\n`).join("") +
148
+ ` hybrid: false\n` +
149
+ ` bm25_weight: 0.3\n` +
136
150
  ` exclude:\n` +
137
151
  ` - node_modules\n` +
138
152
  ` - vendor\n` +
@@ -294,15 +308,15 @@ async function loadConfig(projectRoot) {
294
308
  if (!indexMatch) continue;
295
309
 
296
310
  const indexSection = indexMatch[1];
297
-
311
+
298
312
  // Parse enabled
299
313
  const enabledMatch = indexSection.match(/^\s+enabled:\s*(true|false)/m);
300
314
  const enabled = enabledMatch ? enabledMatch[1] === "true" : true;
301
-
315
+
302
316
  // Parse pattern
303
317
  const patternMatch = indexSection.match(/^\s+pattern:\s*["']?([^"'\n]+)["']?/m);
304
318
  const pattern = patternMatch ? patternMatch[1].trim() : DEFAULT_PRESETS[indexName]?.pattern;
305
-
319
+
306
320
  // Parse ignore array
307
321
  const ignoreMatch = indexSection.match(/^\s+ignore:\s*\n((?:\s+-\s+.+\n?)*)/m);
308
322
  let ignore = [];
@@ -312,12 +326,22 @@ async function loadConfig(projectRoot) {
312
326
  .map((line) => line.replace(/^\s*-\s*/, "").replace(/["']/g, "").trim())
313
327
  .filter(Boolean);
314
328
  }
315
-
329
+
330
+ // Parse hybrid (per-index)
331
+ const hybridMatch = indexSection.match(/^\s+hybrid:\s*(true|false)/m);
332
+ const hybrid = hybridMatch ? hybridMatch[1] === "true" : DEFAULT_PRESETS[indexName]?.hybrid;
333
+
334
+ // Parse bm25_weight (per-index)
335
+ const bm25WeightMatch = indexSection.match(/^\s+bm25_weight:\s*([\d.]+)/m);
336
+ const bm25Weight = bm25WeightMatch ? parseFloat(bm25WeightMatch[1]) : DEFAULT_PRESETS[indexName]?.bm25_weight;
337
+
316
338
  if (enabled && pattern) {
317
339
  INDEX_PRESETS[indexName] = {
318
340
  pattern,
319
341
  ignore,
320
342
  description: `${indexName} files from config`,
343
+ hybrid,
344
+ bm25_weight: bm25Weight,
321
345
  };
322
346
  }
323
347
  }
@@ -647,8 +671,11 @@ class CodebaseIndexer {
647
671
  const hasFilters = !includeArchived || options.fileType || options.language ||
648
672
  options.modifiedAfter || options.modifiedBefore ||
649
673
  (options.tags && options.tags.length > 0);
650
- const isHybrid = HYBRID_CONFIG.enabled || options.hybrid;
651
- const fetchLimit = (hasFilters || isHybrid) ? Math.max(limit * 3, 50) : limit;
674
+ const indexConfig = INDEX_PRESETS[this.indexName];
675
+ const indexHybridEnabled = indexConfig?.hybrid ?? false;
676
+ const indexBM25Weight = indexConfig?.bm25_weight ?? HYBRID_CONFIG.bm25_weight;
677
+ const isHybrid = indexHybridEnabled || options.hybrid;
678
+ const fetchLimit = (hasFilters || isHybrid) ? Math.max(limit *3, 50) : limit;
652
679
  let results;
653
680
  try {
654
681
  results = await table.search(queryEmbedding).limit(fetchLimit).execute();
@@ -659,7 +686,7 @@ class CodebaseIndexer {
659
686
  }
660
687
 
661
688
  // ── Hybrid search ───────────────────────────────────────────────────────
662
- if (HYBRID_CONFIG.enabled || options.hybrid) {
689
+ if (isHybrid) {
663
690
  try {
664
691
  const bm25 = await this.ensureBM25();
665
692
  if (bm25 && this._bm25Rows) {
@@ -706,7 +733,7 @@ class CodebaseIndexer {
706
733
  if (v.bm25Score > maxBM25) maxBM25 = v.bm25Score;
707
734
  }
708
735
 
709
- const bw = (options.bm25_weight ?? HYBRID_CONFIG.bm25_weight) || 0.3;
736
+ const bw = (options.bm25_weight ?? indexBM25Weight) || 0.3;
710
737
  const vw = 1 - bw;
711
738
 
712
739
  const merged = [];
@@ -1035,7 +1062,8 @@ class CodebaseIndexer {
1035
1062
  chunkCount,
1036
1063
  features: {
1037
1064
  chunking: CHUNKING_CONFIG.strategy,
1038
- hybrid: HYBRID_CONFIG.enabled,
1065
+ hybrid: preset?.hybrid ?? false,
1066
+ bm25_weight: preset?.bm25_weight ?? HYBRID_CONFIG.bm25_weight,
1039
1067
  metrics: METRICS_ENABLED,
1040
1068
  cache: CACHE_ENABLED,
1041
1069
  },