recker 1.0.12-alpha.a858d02 → 1.0.12-next.b76976a
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/dist/cli/tui/shell-search.d.ts +2 -1
- package/dist/cli/tui/shell-search.d.ts.map +1 -1
- package/dist/cli/tui/shell-search.js +33 -2
- package/dist/mcp/data/embeddings.json +1 -0
- package/dist/mcp/search/hybrid-search.d.ts +2 -0
- package/dist/mcp/search/hybrid-search.d.ts.map +1 -1
- package/dist/mcp/search/hybrid-search.js +54 -8
- package/dist/mcp/search/types.d.ts +4 -0
- package/dist/mcp/search/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hybrid-search.d.ts","sourceRoot":"","sources":["../../../src/mcp/search/hybrid-search.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AAkBpB,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAA+B;gBAEjC,MAAM,GAAE,kBAAuB;IAYrC,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"hybrid-search.d.ts","sourceRoot":"","sources":["../../../src/mcp/search/hybrid-search.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AAkBpB,qBAAa,YAAY;IACvB,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAA+B;gBAEjC,MAAM,GAAE,kBAAuB;IAYrC,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YA+BrC,yBAAyB;IAuDjC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAmDjF,OAAO,CAAC,WAAW;IAiCnB,OAAO,CAAC,cAAc;IA8GtB,OAAO,CAAC,cAAc;IAoDtB,OAAO,CAAC,MAAM,CAAC,UAAU,CAoCtB;IAKH,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,cAAc;IAmBtB,aAAa,IAAI,OAAO;IAOxB,QAAQ,IAAI;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB;IAYD,OAAO,CAAC,GAAG;CAKZ;AAKD,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,YAAY,CAE5E"}
|
|
@@ -10,7 +10,7 @@ export class HybridSearch {
|
|
|
10
10
|
config;
|
|
11
11
|
constructor(config = {}) {
|
|
12
12
|
this.config = {
|
|
13
|
-
fuzzyThreshold: config.fuzzyThreshold ?? 0.
|
|
13
|
+
fuzzyThreshold: config.fuzzyThreshold ?? 0.6,
|
|
14
14
|
fuzzyWeight: config.fuzzyWeight ?? 0.5,
|
|
15
15
|
semanticWeight: config.semanticWeight ?? 0.5,
|
|
16
16
|
debug: config.debug ?? false,
|
|
@@ -20,16 +20,18 @@ export class HybridSearch {
|
|
|
20
20
|
this.docs = docs;
|
|
21
21
|
this.fuse = new Fuse(docs, {
|
|
22
22
|
keys: [
|
|
23
|
-
{ name: '
|
|
24
|
-
{ name: '
|
|
25
|
-
{ name: '
|
|
26
|
-
{ name: '
|
|
23
|
+
{ name: 'keywords', weight: 6 },
|
|
24
|
+
{ name: 'title', weight: 4 },
|
|
25
|
+
{ name: 'section', weight: 3 },
|
|
26
|
+
{ name: 'path', weight: 1 },
|
|
27
|
+
{ name: 'content', weight: 0.3 },
|
|
27
28
|
],
|
|
28
29
|
includeScore: true,
|
|
29
30
|
threshold: this.config.fuzzyThreshold,
|
|
30
31
|
ignoreLocation: true,
|
|
31
32
|
useExtendedSearch: true,
|
|
32
33
|
findAllMatches: true,
|
|
34
|
+
minMatchCharLength: 2,
|
|
33
35
|
});
|
|
34
36
|
await this.loadPrecomputedEmbeddings();
|
|
35
37
|
this.initialized = true;
|
|
@@ -82,16 +84,19 @@ export class HybridSearch {
|
|
|
82
84
|
if (!this.initialized) {
|
|
83
85
|
throw new Error('HybridSearch not initialized. Call initialize() first.');
|
|
84
86
|
}
|
|
87
|
+
const cleanedQuery = this.cleanQuery(query);
|
|
88
|
+
this.log(`Original query: "${query}" → Cleaned: "${cleanedQuery}"`);
|
|
89
|
+
const searchQuery = cleanedQuery.length > 0 ? cleanedQuery : query;
|
|
85
90
|
const results = new Map();
|
|
86
91
|
if (mode === 'hybrid' || mode === 'fuzzy') {
|
|
87
|
-
const fuzzyResults = this.fuzzySearch(
|
|
92
|
+
const fuzzyResults = this.fuzzySearch(searchQuery, limit * 2, category);
|
|
88
93
|
for (const result of fuzzyResults) {
|
|
89
94
|
results.set(result.id, result);
|
|
90
95
|
}
|
|
91
96
|
this.log(`Fuzzy search found ${fuzzyResults.length} results`);
|
|
92
97
|
}
|
|
93
98
|
if ((mode === 'hybrid' || mode === 'semantic') && this.vectors.size > 0) {
|
|
94
|
-
const semanticResults = this.semanticSearch(
|
|
99
|
+
const semanticResults = this.semanticSearch(searchQuery, limit * 2, category);
|
|
95
100
|
for (const result of semanticResults) {
|
|
96
101
|
const existing = results.get(result.id);
|
|
97
102
|
if (existing) {
|
|
@@ -242,11 +247,52 @@ export class HybridSearch {
|
|
|
242
247
|
snippet = snippet + '...';
|
|
243
248
|
return snippet.replace(/\n+/g, ' ').replace(/\s+/g, ' ');
|
|
244
249
|
}
|
|
250
|
+
static STOP_WORDS = new Set([
|
|
251
|
+
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
|
|
252
|
+
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should',
|
|
253
|
+
'may', 'might', 'must', 'shall', 'can', 'need', 'dare', 'ought', 'used',
|
|
254
|
+
'and', 'but', 'or', 'nor', 'for', 'yet', 'so', 'both', 'either', 'neither',
|
|
255
|
+
'not', 'only', 'own', 'same', 'than', 'too', 'very', 'just', 'also',
|
|
256
|
+
'how', 'what', 'when', 'where', 'who', 'which', 'why', 'whom', 'whose',
|
|
257
|
+
'this', 'that', 'these', 'those', 'here', 'there', 'all', 'each', 'every',
|
|
258
|
+
'any', 'some', 'no', 'none', 'one', 'two', 'other', 'another', 'such',
|
|
259
|
+
'to', 'of', 'in', 'on', 'at', 'by', 'with', 'from', 'as', 'into', 'through',
|
|
260
|
+
'about', 'above', 'below', 'between', 'under', 'over', 'out', 'up', 'down',
|
|
261
|
+
'if', 'then', 'else', 'because', 'while', 'although', 'though', 'unless',
|
|
262
|
+
'my', 'your', 'his', 'her', 'its', 'our', 'their', 'me', 'you', 'him', 'us', 'them',
|
|
263
|
+
'o', 'a', 'os', 'as', 'um', 'uma', 'uns', 'umas', 'de', 'do', 'da', 'dos', 'das',
|
|
264
|
+
'em', 'no', 'na', 'nos', 'nas', 'por', 'para', 'com', 'sem', 'sob', 'sobre',
|
|
265
|
+
'e', 'ou', 'mas', 'porem', 'todavia', 'contudo', 'entretanto',
|
|
266
|
+
'que', 'qual', 'quais', 'quanto', 'quem', 'como', 'onde', 'quando', 'porque',
|
|
267
|
+
'eu', 'tu', 'ele', 'ela', 'nos', 'vos', 'eles', 'elas', 'voce', 'voces',
|
|
268
|
+
'meu', 'minha', 'meus', 'minhas', 'seu', 'sua', 'seus', 'suas',
|
|
269
|
+
'este', 'esta', 'estes', 'estas', 'esse', 'essa', 'esses', 'essas',
|
|
270
|
+
'isso', 'isto', 'aquilo', 'aquele', 'aquela', 'aqueles', 'aquelas',
|
|
271
|
+
'ser', 'estar', 'ter', 'haver', 'fazer', 'ir', 'vir', 'poder', 'dever',
|
|
272
|
+
'sim', 'nao', 'ja', 'ainda', 'sempre', 'nunca', 'tambem', 'so', 'apenas',
|
|
273
|
+
'muito', 'pouco', 'mais', 'menos', 'bem', 'mal', 'assim', 'entao', 'logo',
|
|
274
|
+
'yo', 'hey', 'oi', 'ola', 'bom', 'boa', 'obrigado', 'por favor',
|
|
275
|
+
'configure', 'configuro', 'configurar', 'configurando',
|
|
276
|
+
'use', 'usar', 'using', 'usar',
|
|
277
|
+
'create', 'criar', 'creating', 'criando',
|
|
278
|
+
'setup', 'setar', 'setting', 'setando',
|
|
279
|
+
'add', 'adicionar', 'adding', 'adicionando',
|
|
280
|
+
'get', 'getting', 'pegar', 'pegando',
|
|
281
|
+
'set', 'setting', 'definir', 'definindo',
|
|
282
|
+
'make', 'making', 'fazer', 'fazendo',
|
|
283
|
+
]);
|
|
284
|
+
cleanQuery(query) {
|
|
285
|
+
const words = query
|
|
286
|
+
.toLowerCase()
|
|
287
|
+
.split(/[\s\-_.,;:!?()[\]{}'"]+/)
|
|
288
|
+
.filter((w) => w.length > 1 && !HybridSearch.STOP_WORDS.has(w));
|
|
289
|
+
return words.join(' ');
|
|
290
|
+
}
|
|
245
291
|
tokenize(text) {
|
|
246
292
|
return text
|
|
247
293
|
.toLowerCase()
|
|
248
294
|
.split(/[\s\-_.,;:!?()[\]{}'"]+/)
|
|
249
|
-
.filter((t) => t.length > 2);
|
|
295
|
+
.filter((t) => t.length > 2 && !HybridSearch.STOP_WORDS.has(t));
|
|
250
296
|
}
|
|
251
297
|
averageVectors(vectors) {
|
|
252
298
|
if (vectors.length === 0)
|
|
@@ -5,6 +5,8 @@ export interface IndexedDoc {
|
|
|
5
5
|
content: string;
|
|
6
6
|
category: string;
|
|
7
7
|
keywords: string[];
|
|
8
|
+
section?: string;
|
|
9
|
+
parentPath?: string;
|
|
8
10
|
}
|
|
9
11
|
export interface SearchResult {
|
|
10
12
|
id: string;
|
|
@@ -28,6 +30,8 @@ export interface EmbeddingEntry {
|
|
|
28
30
|
title: string;
|
|
29
31
|
category: string;
|
|
30
32
|
keywords: string[];
|
|
33
|
+
section?: string;
|
|
34
|
+
parentPath?: string;
|
|
31
35
|
vector: number[];
|
|
32
36
|
}
|
|
33
37
|
export interface SearchOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/mcp/search/types.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IAEzB,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,OAAO,EAAE,MAAM,CAAC;IAEhB,QAAQ,EAAE,MAAM,CAAC;IAEjB,QAAQ,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/mcp/search/types.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IAEzB,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,OAAO,EAAE,MAAM,CAAC;IAEhB,QAAQ,EAAE,MAAM,CAAC;IAEjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAKD,MAAM,WAAW,YAAY;IAE3B,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,OAAO,EAAE,MAAM,CAAC;IAEhB,OAAO,EAAE,MAAM,CAAC;IAEhB,KAAK,EAAE,MAAM,CAAC;IAEd,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;CACzC;AAMD,MAAM,WAAW,cAAc;IAE7B,OAAO,EAAE,MAAM,CAAC;IAEhB,KAAK,EAAE,MAAM,CAAC;IAEd,UAAU,EAAE,MAAM,CAAC;IAEnB,WAAW,EAAE,MAAM,CAAC;IAEpB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAKD,MAAM,WAAW,cAAc;IAE7B,EAAE,EAAE,MAAM,CAAC;IAEX,IAAI,EAAE,MAAM,CAAC;IAEb,KAAK,EAAE,MAAM,CAAC;IAEd,QAAQ,EAAE,MAAM,CAAC;IAEjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IAEnB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAKD,MAAM,WAAW,aAAa;IAE5B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;IAEvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD,MAAM,WAAW,kBAAkB;IAEjC,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "recker",
|
|
3
|
-
"version": "1.0.12-
|
|
3
|
+
"version": "1.0.12-next.b76976a",
|
|
4
4
|
"description": "AI & DevX focused HTTP client for Node.js 18+",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
"zod": "^3.24.0"
|
|
167
167
|
},
|
|
168
168
|
"scripts": {
|
|
169
|
-
"build": "tsc",
|
|
169
|
+
"build": "tsc && mkdir -p dist/mcp/data && cp src/mcp/data/embeddings.json dist/mcp/data/",
|
|
170
170
|
"build:embeddings": "tsx scripts/build-embeddings.ts",
|
|
171
171
|
"test": "vitest run",
|
|
172
172
|
"test:coverage": "vitest run --coverage",
|