recker 1.0.12-alpha.04c18a7 → 1.0.12-alpha.1ab8aa7
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/cache/memory-limits.d.ts +21 -0
- package/dist/cache/memory-limits.d.ts.map +1 -0
- package/dist/cache/memory-limits.js +96 -0
- package/dist/cache/memory-storage.d.ts +125 -2
- package/dist/cache/memory-storage.d.ts.map +1 -1
- package/dist/cache/memory-storage.js +437 -14
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/mcp/search/hybrid-search.d.ts +28 -0
- package/dist/mcp/search/hybrid-search.d.ts.map +1 -0
- package/dist/mcp/search/hybrid-search.js +286 -0
- package/dist/mcp/search/index.d.ts +4 -0
- package/dist/mcp/search/index.d.ts.map +1 -0
- package/dist/mcp/search/index.js +2 -0
- package/dist/mcp/search/math.d.ts +6 -0
- package/dist/mcp/search/math.d.ts.map +1 -0
- package/dist/mcp/search/math.js +59 -0
- package/dist/mcp/search/types.d.ts +45 -0
- package/dist/mcp/search/types.d.ts.map +1 -0
- package/dist/mcp/search/types.js +1 -0
- package/dist/mcp/server.d.ts +27 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +688 -33
- package/package.json +7 -2
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import Fuse from 'fuse.js';
|
|
2
|
+
import { cosineSimilarity, combineScores, levenshtein } from './math.js';
|
|
3
|
+
let cachedEmbeddings = null;
|
|
4
|
+
export class HybridSearch {
|
|
5
|
+
fuse = null;
|
|
6
|
+
docs = [];
|
|
7
|
+
vectors = new Map();
|
|
8
|
+
embeddingsData = null;
|
|
9
|
+
initialized = false;
|
|
10
|
+
config;
|
|
11
|
+
constructor(config = {}) {
|
|
12
|
+
this.config = {
|
|
13
|
+
fuzzyThreshold: config.fuzzyThreshold ?? 0.4,
|
|
14
|
+
fuzzyWeight: config.fuzzyWeight ?? 0.5,
|
|
15
|
+
semanticWeight: config.semanticWeight ?? 0.5,
|
|
16
|
+
debug: config.debug ?? false,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async initialize(docs) {
|
|
20
|
+
this.docs = docs;
|
|
21
|
+
this.fuse = new Fuse(docs, {
|
|
22
|
+
keys: [
|
|
23
|
+
{ name: 'title', weight: 3 },
|
|
24
|
+
{ name: 'keywords', weight: 2 },
|
|
25
|
+
{ name: 'path', weight: 1.5 },
|
|
26
|
+
{ name: 'content', weight: 1 },
|
|
27
|
+
],
|
|
28
|
+
includeScore: true,
|
|
29
|
+
threshold: this.config.fuzzyThreshold,
|
|
30
|
+
ignoreLocation: true,
|
|
31
|
+
useExtendedSearch: true,
|
|
32
|
+
findAllMatches: true,
|
|
33
|
+
});
|
|
34
|
+
await this.loadPrecomputedEmbeddings();
|
|
35
|
+
this.initialized = true;
|
|
36
|
+
this.log(`Initialized with ${docs.length} docs, ${this.vectors.size} embeddings`);
|
|
37
|
+
}
|
|
38
|
+
async loadPrecomputedEmbeddings() {
|
|
39
|
+
try {
|
|
40
|
+
if (cachedEmbeddings) {
|
|
41
|
+
this.embeddingsData = cachedEmbeddings;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const embeddingsPath = new URL('../data/embeddings.json', import.meta.url);
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(embeddingsPath);
|
|
47
|
+
if (response.ok) {
|
|
48
|
+
this.embeddingsData = (await response.json());
|
|
49
|
+
cachedEmbeddings = this.embeddingsData;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
try {
|
|
54
|
+
const fs = await import('fs');
|
|
55
|
+
const path = await import('path');
|
|
56
|
+
const embeddingsFile = path.join(path.dirname(new URL(import.meta.url).pathname), '../data/embeddings.json');
|
|
57
|
+
if (fs.existsSync(embeddingsFile)) {
|
|
58
|
+
const data = fs.readFileSync(embeddingsFile, 'utf-8');
|
|
59
|
+
this.embeddingsData = JSON.parse(data);
|
|
60
|
+
cachedEmbeddings = this.embeddingsData;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (this.embeddingsData) {
|
|
68
|
+
for (const entry of this.embeddingsData.documents) {
|
|
69
|
+
if (entry.vector && entry.vector.length > 0) {
|
|
70
|
+
this.vectors.set(entry.id, entry.vector);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
this.log(`Loaded ${this.vectors.size} pre-computed embeddings (model: ${this.embeddingsData.model})`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.log(`No pre-computed embeddings found: ${error}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async search(query, options = {}) {
|
|
81
|
+
const { limit = 10, category, mode = 'hybrid', minScore = 0 } = options;
|
|
82
|
+
if (!this.initialized) {
|
|
83
|
+
throw new Error('HybridSearch not initialized. Call initialize() first.');
|
|
84
|
+
}
|
|
85
|
+
const results = new Map();
|
|
86
|
+
if (mode === 'hybrid' || mode === 'fuzzy') {
|
|
87
|
+
const fuzzyResults = this.fuzzySearch(query, limit * 2, category);
|
|
88
|
+
for (const result of fuzzyResults) {
|
|
89
|
+
results.set(result.id, result);
|
|
90
|
+
}
|
|
91
|
+
this.log(`Fuzzy search found ${fuzzyResults.length} results`);
|
|
92
|
+
}
|
|
93
|
+
if ((mode === 'hybrid' || mode === 'semantic') && this.vectors.size > 0) {
|
|
94
|
+
const semanticResults = this.semanticSearch(query, limit * 2, category);
|
|
95
|
+
for (const result of semanticResults) {
|
|
96
|
+
const existing = results.get(result.id);
|
|
97
|
+
if (existing) {
|
|
98
|
+
existing.score = combineScores(existing.score, result.score);
|
|
99
|
+
existing.source = 'hybrid';
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
results.set(result.id, result);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
this.log(`Semantic search found ${semanticResults.length} results`);
|
|
106
|
+
}
|
|
107
|
+
return Array.from(results.values())
|
|
108
|
+
.filter((r) => r.score >= minScore)
|
|
109
|
+
.sort((a, b) => b.score - a.score)
|
|
110
|
+
.slice(0, limit);
|
|
111
|
+
}
|
|
112
|
+
fuzzySearch(query, limit, category) {
|
|
113
|
+
if (!this.fuse)
|
|
114
|
+
return [];
|
|
115
|
+
let results = this.fuse.search(query, { limit: limit * 2 });
|
|
116
|
+
if (category) {
|
|
117
|
+
results = results.filter((r) => r.item.category.toLowerCase().includes(category.toLowerCase()));
|
|
118
|
+
}
|
|
119
|
+
return results.slice(0, limit).map((r) => ({
|
|
120
|
+
id: r.item.id,
|
|
121
|
+
path: r.item.path,
|
|
122
|
+
title: r.item.title,
|
|
123
|
+
content: r.item.content,
|
|
124
|
+
snippet: this.extractSnippet(r.item.content, query),
|
|
125
|
+
score: 1 - (r.score || 0),
|
|
126
|
+
source: 'fuzzy',
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
semanticSearch(query, limit, category) {
|
|
130
|
+
if (!this.embeddingsData || this.vectors.size === 0) {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
const queryTerms = this.tokenize(query);
|
|
134
|
+
const scores = [];
|
|
135
|
+
for (const entry of this.embeddingsData.documents) {
|
|
136
|
+
if (category && !entry.category.toLowerCase().includes(category.toLowerCase())) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
let termScore = 0;
|
|
140
|
+
const docText = `${entry.title} ${entry.keywords?.join(' ') || ''}`.toLowerCase();
|
|
141
|
+
const docTerms = this.tokenize(docText);
|
|
142
|
+
for (const queryTerm of queryTerms) {
|
|
143
|
+
if (docTerms.includes(queryTerm)) {
|
|
144
|
+
termScore += 2;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
for (const docTerm of docTerms) {
|
|
148
|
+
const distance = levenshtein(queryTerm, docTerm);
|
|
149
|
+
const maxLen = Math.max(queryTerm.length, docTerm.length);
|
|
150
|
+
if (distance <= Math.min(2, maxLen * 0.3)) {
|
|
151
|
+
termScore += 1 - distance / maxLen;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const normalizedScore = Math.min(1, termScore / (queryTerms.length * 2));
|
|
157
|
+
if (normalizedScore > 0.1) {
|
|
158
|
+
scores.push({ id: entry.id, score: normalizedScore });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const topDocs = scores.sort((a, b) => b.score - a.score).slice(0, 3);
|
|
162
|
+
if (topDocs.length > 0) {
|
|
163
|
+
const topVectors = topDocs
|
|
164
|
+
.map((d) => this.vectors.get(d.id))
|
|
165
|
+
.filter((v) => Array.isArray(v) && v.length > 0);
|
|
166
|
+
if (topVectors.length > 0 && topVectors.every((v) => v.length === topVectors[0].length)) {
|
|
167
|
+
const avgVector = this.averageVectors(topVectors);
|
|
168
|
+
const expectedDimensions = avgVector.length;
|
|
169
|
+
for (const entry of this.embeddingsData.documents) {
|
|
170
|
+
if (scores.some((s) => s.id === entry.id))
|
|
171
|
+
continue;
|
|
172
|
+
if (category && !entry.category.toLowerCase().includes(category.toLowerCase()))
|
|
173
|
+
continue;
|
|
174
|
+
const vector = this.vectors.get(entry.id);
|
|
175
|
+
if (!vector || vector.length === 0 || vector.length !== expectedDimensions)
|
|
176
|
+
continue;
|
|
177
|
+
const similarity = cosineSimilarity(avgVector, vector);
|
|
178
|
+
if (similarity > 0.7) {
|
|
179
|
+
scores.push({ id: entry.id, score: similarity * 0.5 });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const results = [];
|
|
185
|
+
for (const s of scores.sort((a, b) => b.score - a.score).slice(0, limit)) {
|
|
186
|
+
const doc = this.docs.find((d) => d.id === s.id);
|
|
187
|
+
const entry = this.embeddingsData.documents.find((e) => e.id === s.id);
|
|
188
|
+
if (!doc && !entry) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const title = doc?.title || entry?.title || 'Unknown';
|
|
192
|
+
const path = doc?.path || entry?.path || '';
|
|
193
|
+
const content = doc?.content || '';
|
|
194
|
+
results.push({
|
|
195
|
+
id: s.id,
|
|
196
|
+
path,
|
|
197
|
+
title,
|
|
198
|
+
content,
|
|
199
|
+
snippet: this.extractSnippet(content, query),
|
|
200
|
+
score: s.score,
|
|
201
|
+
source: 'semantic',
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return results;
|
|
205
|
+
}
|
|
206
|
+
extractSnippet(content, query) {
|
|
207
|
+
if (!content)
|
|
208
|
+
return '';
|
|
209
|
+
const lowerContent = content.toLowerCase();
|
|
210
|
+
const queryTerms = this.tokenize(query);
|
|
211
|
+
let bestIndex = -1;
|
|
212
|
+
let bestScore = 0;
|
|
213
|
+
for (const term of queryTerms) {
|
|
214
|
+
const idx = lowerContent.indexOf(term);
|
|
215
|
+
if (idx !== -1) {
|
|
216
|
+
bestIndex = idx;
|
|
217
|
+
bestScore = term.length;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (bestIndex === -1) {
|
|
222
|
+
const words = lowerContent.split(/\s+/).slice(0, 500);
|
|
223
|
+
for (let i = 0; i < words.length; i++) {
|
|
224
|
+
for (const term of queryTerms) {
|
|
225
|
+
const dist = levenshtein(words[i].slice(0, 20), term.slice(0, 20));
|
|
226
|
+
if (dist <= 2 && dist < bestScore) {
|
|
227
|
+
bestScore = dist;
|
|
228
|
+
bestIndex = lowerContent.indexOf(words[i]);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (bestIndex === -1) {
|
|
234
|
+
return content.slice(0, 200).trim() + (content.length > 200 ? '...' : '');
|
|
235
|
+
}
|
|
236
|
+
const start = Math.max(0, bestIndex - 50);
|
|
237
|
+
const end = Math.min(content.length, bestIndex + 150);
|
|
238
|
+
let snippet = content.slice(start, end).trim();
|
|
239
|
+
if (start > 0)
|
|
240
|
+
snippet = '...' + snippet;
|
|
241
|
+
if (end < content.length)
|
|
242
|
+
snippet = snippet + '...';
|
|
243
|
+
return snippet.replace(/\n+/g, ' ').replace(/\s+/g, ' ');
|
|
244
|
+
}
|
|
245
|
+
tokenize(text) {
|
|
246
|
+
return text
|
|
247
|
+
.toLowerCase()
|
|
248
|
+
.split(/[\s\-_.,;:!?()[\]{}'"]+/)
|
|
249
|
+
.filter((t) => t.length > 2);
|
|
250
|
+
}
|
|
251
|
+
averageVectors(vectors) {
|
|
252
|
+
if (vectors.length === 0)
|
|
253
|
+
return [];
|
|
254
|
+
if (vectors.length === 1)
|
|
255
|
+
return vectors[0];
|
|
256
|
+
const result = new Array(vectors[0].length).fill(0);
|
|
257
|
+
for (const vec of vectors) {
|
|
258
|
+
for (let i = 0; i < vec.length; i++) {
|
|
259
|
+
result[i] += vec[i];
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
for (let i = 0; i < result.length; i++) {
|
|
263
|
+
result[i] /= vectors.length;
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
hasEmbeddings() {
|
|
268
|
+
return this.vectors.size > 0;
|
|
269
|
+
}
|
|
270
|
+
getStats() {
|
|
271
|
+
return {
|
|
272
|
+
documents: this.docs.length,
|
|
273
|
+
embeddings: this.vectors.size,
|
|
274
|
+
model: this.embeddingsData?.model,
|
|
275
|
+
dimensions: this.embeddingsData?.dimensions,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
log(message) {
|
|
279
|
+
if (this.config.debug) {
|
|
280
|
+
console.log(`[HybridSearch] ${message}`);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
export function createHybridSearch(config) {
|
|
285
|
+
return new HybridSearch(config);
|
|
286
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { HybridSearch, createHybridSearch } from './hybrid-search.js';
|
|
2
|
+
export { cosineSimilarity, levenshtein, stringSimilarity, reciprocalRankFusion, combineScores, } from './math.js';
|
|
3
|
+
export type { IndexedDoc, SearchResult, SearchOptions, HybridSearchConfig, EmbeddingsData, EmbeddingEntry, } from './types.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcp/search/index.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,GACd,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,UAAU,EACV,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
2
|
+
export declare function levenshtein(a: string, b: string): number;
|
|
3
|
+
export declare function stringSimilarity(a: string, b: string): number;
|
|
4
|
+
export declare function reciprocalRankFusion(ranks: number[], k?: number): number;
|
|
5
|
+
export declare function combineScores(score1: number, score2: number, k?: number): number;
|
|
6
|
+
//# sourceMappingURL=math.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../../src/mcp/search/math.ts"],"names":[],"mappings":"AAoBA,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAqBjE;AAgBD,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAyCxD;AAeD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAI7D;AAmBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,SAAK,GAAG,MAAM,CAEpE;AAWD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,SAAK,GAAG,MAAM,CAK5E"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export function cosineSimilarity(a, b) {
|
|
2
|
+
if (a.length !== b.length) {
|
|
3
|
+
throw new Error(`Vector length mismatch: ${a.length} vs ${b.length}`);
|
|
4
|
+
}
|
|
5
|
+
if (a.length === 0) {
|
|
6
|
+
return 0;
|
|
7
|
+
}
|
|
8
|
+
let dot = 0;
|
|
9
|
+
let normA = 0;
|
|
10
|
+
let normB = 0;
|
|
11
|
+
for (let i = 0; i < a.length; i++) {
|
|
12
|
+
dot += a[i] * b[i];
|
|
13
|
+
normA += a[i] * a[i];
|
|
14
|
+
normB += b[i] * b[i];
|
|
15
|
+
}
|
|
16
|
+
const magnitude = Math.sqrt(normA) * Math.sqrt(normB);
|
|
17
|
+
return magnitude === 0 ? 0 : dot / magnitude;
|
|
18
|
+
}
|
|
19
|
+
export function levenshtein(a, b) {
|
|
20
|
+
if (a === b)
|
|
21
|
+
return 0;
|
|
22
|
+
if (a.length === 0)
|
|
23
|
+
return b.length;
|
|
24
|
+
if (b.length === 0)
|
|
25
|
+
return a.length;
|
|
26
|
+
if (a.length > b.length) {
|
|
27
|
+
[a, b] = [b, a];
|
|
28
|
+
}
|
|
29
|
+
const aLen = a.length;
|
|
30
|
+
const bLen = b.length;
|
|
31
|
+
let prevRow = new Array(aLen + 1);
|
|
32
|
+
let currRow = new Array(aLen + 1);
|
|
33
|
+
for (let i = 0; i <= aLen; i++) {
|
|
34
|
+
prevRow[i] = i;
|
|
35
|
+
}
|
|
36
|
+
for (let j = 1; j <= bLen; j++) {
|
|
37
|
+
currRow[0] = j;
|
|
38
|
+
for (let i = 1; i <= aLen; i++) {
|
|
39
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
40
|
+
currRow[i] = Math.min(prevRow[i] + 1, currRow[i - 1] + 1, prevRow[i - 1] + cost);
|
|
41
|
+
}
|
|
42
|
+
[prevRow, currRow] = [currRow, prevRow];
|
|
43
|
+
}
|
|
44
|
+
return prevRow[aLen];
|
|
45
|
+
}
|
|
46
|
+
export function stringSimilarity(a, b) {
|
|
47
|
+
const maxLen = Math.max(a.length, b.length);
|
|
48
|
+
if (maxLen === 0)
|
|
49
|
+
return 1;
|
|
50
|
+
return 1 - levenshtein(a, b) / maxLen;
|
|
51
|
+
}
|
|
52
|
+
export function reciprocalRankFusion(ranks, k = 60) {
|
|
53
|
+
return ranks.reduce((sum, rank) => sum + 1 / (k + rank), 0);
|
|
54
|
+
}
|
|
55
|
+
export function combineScores(score1, score2, k = 60) {
|
|
56
|
+
const rank1 = 1 + (1 - score1) * 100;
|
|
57
|
+
const rank2 = 1 + (1 - score2) * 100;
|
|
58
|
+
return reciprocalRankFusion([rank1, rank2], k);
|
|
59
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface IndexedDoc {
|
|
2
|
+
id: string;
|
|
3
|
+
path: string;
|
|
4
|
+
title: string;
|
|
5
|
+
content: string;
|
|
6
|
+
category: string;
|
|
7
|
+
keywords: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface SearchResult {
|
|
10
|
+
id: string;
|
|
11
|
+
path: string;
|
|
12
|
+
title: string;
|
|
13
|
+
content: string;
|
|
14
|
+
snippet: string;
|
|
15
|
+
score: number;
|
|
16
|
+
source: 'fuzzy' | 'semantic' | 'hybrid';
|
|
17
|
+
}
|
|
18
|
+
export interface EmbeddingsData {
|
|
19
|
+
version: string;
|
|
20
|
+
model: string;
|
|
21
|
+
dimensions: number;
|
|
22
|
+
generatedAt: string;
|
|
23
|
+
documents: EmbeddingEntry[];
|
|
24
|
+
}
|
|
25
|
+
export interface EmbeddingEntry {
|
|
26
|
+
id: string;
|
|
27
|
+
path: string;
|
|
28
|
+
title: string;
|
|
29
|
+
category: string;
|
|
30
|
+
keywords: string[];
|
|
31
|
+
vector: number[];
|
|
32
|
+
}
|
|
33
|
+
export interface SearchOptions {
|
|
34
|
+
limit?: number;
|
|
35
|
+
category?: string;
|
|
36
|
+
mode?: 'hybrid' | 'fuzzy' | 'semantic';
|
|
37
|
+
minScore?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface HybridSearchConfig {
|
|
40
|
+
fuzzyThreshold?: number;
|
|
41
|
+
fuzzyWeight?: number;
|
|
42
|
+
semanticWeight?: number;
|
|
43
|
+
debug?: boolean;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +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;CACpB;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,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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -4,28 +4,53 @@ export interface MCPServerOptions {
|
|
|
4
4
|
name?: string;
|
|
5
5
|
version?: string;
|
|
6
6
|
docsPath?: string;
|
|
7
|
+
examplesPath?: string;
|
|
8
|
+
srcPath?: string;
|
|
7
9
|
port?: number;
|
|
8
10
|
transport?: MCPTransportMode;
|
|
9
11
|
debug?: boolean;
|
|
12
|
+
toolsFilter?: string[];
|
|
10
13
|
}
|
|
11
14
|
export declare class MCPServer {
|
|
12
15
|
private options;
|
|
13
16
|
private server?;
|
|
17
|
+
private hybridSearch;
|
|
14
18
|
private docsIndex;
|
|
19
|
+
private codeExamples;
|
|
20
|
+
private typeDefinitions;
|
|
15
21
|
private sseClients;
|
|
16
22
|
private initialized;
|
|
17
23
|
constructor(options?: MCPServerOptions);
|
|
18
24
|
private log;
|
|
19
25
|
private findDocsPath;
|
|
26
|
+
private findExamplesPath;
|
|
27
|
+
private findSrcPath;
|
|
20
28
|
private buildIndex;
|
|
29
|
+
private indexDocs;
|
|
30
|
+
private indexCodeExamples;
|
|
31
|
+
private parseCodeExample;
|
|
32
|
+
private humanizeFilename;
|
|
33
|
+
private inferFeature;
|
|
34
|
+
private inferComplexity;
|
|
35
|
+
private extractCodeKeywords;
|
|
36
|
+
private indexTypeDefinitions;
|
|
37
|
+
private extractTypeDefinitions;
|
|
38
|
+
private parseInterfaceProperties;
|
|
21
39
|
private walkDir;
|
|
22
40
|
private extractTitle;
|
|
23
41
|
private extractKeywords;
|
|
24
42
|
private getTools;
|
|
43
|
+
private isToolEnabled;
|
|
44
|
+
private matchPattern;
|
|
25
45
|
private handleToolCall;
|
|
26
46
|
private searchDocs;
|
|
27
47
|
private extractSnippet;
|
|
28
48
|
private getDoc;
|
|
49
|
+
private getCodeExamples;
|
|
50
|
+
private getApiSchema;
|
|
51
|
+
private getSuggestions;
|
|
52
|
+
private getFeatureConfig;
|
|
53
|
+
private getCombinedConfig;
|
|
29
54
|
handleRequest(req: JsonRpcRequest): JsonRpcResponse;
|
|
30
55
|
private sendNotification;
|
|
31
56
|
private startStdio;
|
|
@@ -35,6 +60,8 @@ export declare class MCPServer {
|
|
|
35
60
|
stop(): Promise<void>;
|
|
36
61
|
getPort(): number;
|
|
37
62
|
getDocsCount(): number;
|
|
63
|
+
getExamplesCount(): number;
|
|
64
|
+
getTypesCount(): number;
|
|
38
65
|
getTransport(): MCPTransportMode;
|
|
39
66
|
}
|
|
40
67
|
export declare function createMCPServer(options?: MCPServerOptions): MCPServer;
|
package/dist/mcp/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAMhB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AA0CD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,MAAM,CAAC,CAAkC;IACjD,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,gBAAqB;IAiB1C,OAAO,CAAC,GAAG;IAUX,OAAO,CAAC,YAAY;IAyBpB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,WAAW;YAwBL,UAAU;YAoBV,SAAS;IAiCvB,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,gBAAgB;IAqCxB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,oBAAoB;IA8B5B,OAAO,CAAC,sBAAsB;IA0E9B,OAAO,CAAC,wBAAwB;IAoBhC,OAAO,CAAC,OAAO;IAyBf,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,eAAe;IAqBvB,OAAO,CAAC,QAAQ;IAkHhB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,UAAU;IA0ElB,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,MAAM;IAmCd,OAAO,CAAC,eAAe;IAgDvB,OAAO,CAAC,YAAY;IAmEpB,OAAO,CAAC,cAAc;IAmFtB,OAAO,CAAC,gBAAgB;IA+DxB,OAAO,CAAC,iBAAiB;IAuCzB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,eAAe;IA8DnD,OAAO,CAAC,gBAAgB;YAOV,UAAU;YAgCV,SAAS;YA8CT,QAAQ;IAuFhB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAatB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B,OAAO,IAAI,MAAM;IAIjB,YAAY,IAAI,MAAM;IAItB,gBAAgB,IAAI,MAAM;IAI1B,aAAa,IAAI,MAAM;IAIvB,YAAY,IAAI,gBAAgB;CAGjC;AAoBD,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAErE"}
|