@comfanion/usethis_search 3.0.0-dev.22 → 3.0.0-dev.23
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/package.json +1 -1
- package/tools/search.ts +35 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@comfanion/usethis_search",
|
|
3
|
-
"version": "3.0.0-dev.
|
|
3
|
+
"version": "3.0.0-dev.23",
|
|
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",
|
package/tools/search.ts
CHANGED
|
@@ -164,24 +164,34 @@ Examples:
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
// ── Reranking — boost results where query keywords appear in text ──────
|
|
167
|
+
// Also store score components for breakdown display
|
|
167
168
|
const queryKeywords = args.query.toLowerCase().split(/\s+/).filter((w: string) => w.length > 2)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
for (const r of allResults) {
|
|
170
|
+
// Vector score (L2 → similarity)
|
|
171
|
+
const vectorScore = r._distance != null ? Math.max(0, 1 - r._distance / 2) : 0
|
|
172
|
+
r._vectorScore = vectorScore
|
|
173
|
+
|
|
174
|
+
// BM25 component (present only in hybrid mode — embedded in _combinedScore)
|
|
175
|
+
// If _combinedScore exists and differs from vectorScore, the difference is BM25 contribution
|
|
176
|
+
r._bm25Component = r._combinedScore != null ? Math.max(0, r._combinedScore - vectorScore) : 0
|
|
177
|
+
|
|
178
|
+
// Base score before keyword boost
|
|
179
|
+
const baseScore = r._combinedScore ?? vectorScore
|
|
180
|
+
|
|
181
|
+
// Keyword matching
|
|
182
|
+
const text = (r.content || "").toLowerCase()
|
|
183
|
+
const matchedKeywords: string[] = []
|
|
184
|
+
if (queryKeywords.length > 0) {
|
|
172
185
|
for (const kw of queryKeywords) {
|
|
173
|
-
if (text.includes(kw))
|
|
186
|
+
if (text.includes(kw)) matchedKeywords.push(kw)
|
|
174
187
|
}
|
|
175
|
-
const keywordBonus = queryKeywords.length > 0 ? (keywordHits / queryKeywords.length) * 0.15 : 0
|
|
176
|
-
const baseScore = r._combinedScore ?? (r._distance != null ? Math.max(0, 1 - r._distance / 2) : 0)
|
|
177
|
-
r._finalScore = baseScore + keywordBonus
|
|
178
|
-
}
|
|
179
|
-
allResults.sort((a: any, b: any) => (b._finalScore ?? 0) - (a._finalScore ?? 0))
|
|
180
|
-
} else {
|
|
181
|
-
for (const r of allResults) {
|
|
182
|
-
r._finalScore = r._combinedScore ?? (r._distance != null ? Math.max(0, 1 - r._distance / 2) : 0)
|
|
183
188
|
}
|
|
189
|
+
r._matchedKeywords = matchedKeywords
|
|
190
|
+
const keywordBonus = queryKeywords.length > 0 ? (matchedKeywords.length / queryKeywords.length) * 0.15 : 0
|
|
191
|
+
r._keywordBonus = keywordBonus
|
|
192
|
+
r._finalScore = baseScore + keywordBonus
|
|
184
193
|
}
|
|
194
|
+
allResults.sort((a: any, b: any) => (b._finalScore ?? 0) - (a._finalScore ?? 0))
|
|
185
195
|
|
|
186
196
|
// ── Group by file — best chunk per file, with chunk count ─────────────
|
|
187
197
|
const fileGroups = new Map<string, { best: any, chunks: any[] }>()
|
|
@@ -233,8 +243,19 @@ Examples:
|
|
|
233
243
|
if (r.class_name) metaParts.push(`class: ${r.class_name}`)
|
|
234
244
|
const metaLine = metaParts.length > 0 ? ` (${metaParts.join(", ")})` : ""
|
|
235
245
|
|
|
246
|
+
// Score breakdown: vector + bm25 + keywords
|
|
247
|
+
const breakdownParts: string[] = [`vec: ${(r._vectorScore ?? 0).toFixed(2)}`]
|
|
248
|
+
if (r._bm25Component > 0.005) breakdownParts.push(`bm25: +${r._bm25Component.toFixed(2)}`)
|
|
249
|
+
if (r._keywordBonus > 0.005) breakdownParts.push(`kw: +${r._keywordBonus.toFixed(2)}`)
|
|
250
|
+
const breakdown = breakdownParts.join(", ")
|
|
251
|
+
|
|
252
|
+
// Matched keywords
|
|
253
|
+
const kwDisplay = r._matchedKeywords && r._matchedKeywords.length > 0
|
|
254
|
+
? ` | matched: "${r._matchedKeywords.join('", "')}"`
|
|
255
|
+
: ""
|
|
256
|
+
|
|
236
257
|
output += `### ${i + 1}. ${r.file}${indexLabel}${chunkNote}\n`
|
|
237
|
-
output += `**
|
|
258
|
+
output += `**Score:** ${score} (${breakdown}${kwDisplay})${metaLine}\n\n`
|
|
238
259
|
output += "```\n"
|
|
239
260
|
const content = r.content.length > 500 ? r.content.substring(0, 500) + "\n... (truncated)" : r.content
|
|
240
261
|
output += content
|