@ignidor/web-search-mcp 1.0.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.
- package/README.md +267 -0
- package/bin/web-search-mcp.js +13 -0
- package/dist/crawl4ai-client.d.ts +238 -0
- package/dist/crawl4ai-client.d.ts.map +1 -0
- package/dist/crawl4ai-client.js +608 -0
- package/dist/crawl4ai-client.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +561 -0
- package/dist/index.js.map +1 -0
- package/dist/playwright-crawler.d.ts +92 -0
- package/dist/playwright-crawler.d.ts.map +1 -0
- package/dist/playwright-crawler.js +454 -0
- package/dist/playwright-crawler.js.map +1 -0
- package/dist/ranking.d.ts +58 -0
- package/dist/ranking.d.ts.map +1 -0
- package/dist/ranking.js +218 -0
- package/dist/ranking.js.map +1 -0
- package/dist/search.d.ts +15 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +187 -0
- package/dist/search.js.map +1 -0
- package/dist/types/index.d.ts +131 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/concurrency.d.ts +24 -0
- package/dist/utils/concurrency.d.ts.map +1 -0
- package/dist/utils/concurrency.js +53 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/validators.d.ts +21 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +75 -0
- package/dist/utils/validators.js.map +1 -0
- package/package.json +77 -0
package/dist/ranking.js
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// BM25 and Hybrid Ranking Engine
|
|
2
|
+
import { BM25 } from 'fast-bm25';
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// BM25 Ranker
|
|
5
|
+
// ============================================================================
|
|
6
|
+
export class BM25Ranker {
|
|
7
|
+
bm25 = null;
|
|
8
|
+
k1 = 1.5; // Term frequency saturation
|
|
9
|
+
b = 0.75; // Length normalization
|
|
10
|
+
constructor(k1, b) {
|
|
11
|
+
if (k1 !== undefined)
|
|
12
|
+
this.k1 = k1;
|
|
13
|
+
if (b !== undefined)
|
|
14
|
+
this.b = b;
|
|
15
|
+
}
|
|
16
|
+
indexDocuments(documents) {
|
|
17
|
+
// fast-bm25 expects array of objects with string fields
|
|
18
|
+
const contents = documents.map(d => ({ content: d.content }));
|
|
19
|
+
this.bm25 = new BM25(contents, { k1: this.k1, b: this.b });
|
|
20
|
+
}
|
|
21
|
+
indexSearchResults(results) {
|
|
22
|
+
const documents = results.map((r, i) => ({
|
|
23
|
+
id: r.url,
|
|
24
|
+
content: `${r.title} ${r.description}`,
|
|
25
|
+
metadata: { ...r, index: i }
|
|
26
|
+
}));
|
|
27
|
+
this.indexDocuments(documents);
|
|
28
|
+
}
|
|
29
|
+
rank(query, documents) {
|
|
30
|
+
if (!this.bm25) {
|
|
31
|
+
this.indexDocuments(documents);
|
|
32
|
+
}
|
|
33
|
+
// fast-bm25 returns array of {index, score} sorted by relevance
|
|
34
|
+
const bm25Results = this.bm25.search(query, documents.length);
|
|
35
|
+
// Map to our RankedDocument format
|
|
36
|
+
return bm25Results.map(({ index, score }) => ({
|
|
37
|
+
doc: documents[index],
|
|
38
|
+
score
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
rankSearchResults(query, results) {
|
|
42
|
+
this.indexSearchResults(results);
|
|
43
|
+
const documents = results.map((r, i) => ({
|
|
44
|
+
id: r.url,
|
|
45
|
+
content: `${r.title} ${r.description}`,
|
|
46
|
+
metadata: { ...r, index: i }
|
|
47
|
+
}));
|
|
48
|
+
const ranked = this.rank(query, documents);
|
|
49
|
+
return ranked.map((r, i) => ({
|
|
50
|
+
position: i + 1,
|
|
51
|
+
score: r.score,
|
|
52
|
+
title: r.doc.metadata.title,
|
|
53
|
+
url: r.doc.id,
|
|
54
|
+
snippet: r.doc.metadata.description,
|
|
55
|
+
provider: r.doc.metadata.provider,
|
|
56
|
+
domain: this.extractDomain(r.doc.id)
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
extractDomain(url) {
|
|
60
|
+
try {
|
|
61
|
+
return new URL(url).hostname;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return 'unknown';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// Hybrid Ranker (BM25 + Freshness + Domain Authority)
|
|
70
|
+
// ============================================================================
|
|
71
|
+
export class HybridRanker {
|
|
72
|
+
bm25Ranker;
|
|
73
|
+
config;
|
|
74
|
+
constructor(config) {
|
|
75
|
+
this.bm25Ranker = new BM25Ranker();
|
|
76
|
+
this.config = {
|
|
77
|
+
alpha: 0.6, // BM25 weight
|
|
78
|
+
beta: 0.2, // Freshness weight
|
|
79
|
+
gamma: 0.2, // Domain authority weight
|
|
80
|
+
...config
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
rank(query, documents) {
|
|
84
|
+
// First get BM25 scores
|
|
85
|
+
this.bm25Ranker.indexDocuments(documents);
|
|
86
|
+
const bm25Ranked = this.bm25Ranker.rank(query, documents);
|
|
87
|
+
// Then add hybrid scoring
|
|
88
|
+
return bm25Ranked.map(({ doc, score: bm25Score }) => {
|
|
89
|
+
const freshnessScore = this.calculateFreshnessScore(doc.metadata?.publishedDate);
|
|
90
|
+
const domainScore = this.calculateDomainScore(doc.id);
|
|
91
|
+
const totalScore = this.config.alpha * bm25Score +
|
|
92
|
+
this.config.beta * freshnessScore +
|
|
93
|
+
this.config.gamma * domainScore;
|
|
94
|
+
return {
|
|
95
|
+
doc,
|
|
96
|
+
score: totalScore,
|
|
97
|
+
breakdown: { bm25: bm25Score, freshness: freshnessScore, domain: domainScore }
|
|
98
|
+
};
|
|
99
|
+
}).sort((a, b) => b.score - a.score);
|
|
100
|
+
}
|
|
101
|
+
rankSearchResults(query, results) {
|
|
102
|
+
const documents = results.map((r, i) => ({
|
|
103
|
+
id: r.url,
|
|
104
|
+
content: `${r.title} ${r.description}`,
|
|
105
|
+
metadata: { ...r, index: i }
|
|
106
|
+
}));
|
|
107
|
+
const ranked = this.rank(query, documents);
|
|
108
|
+
return ranked.map((r, i) => ({
|
|
109
|
+
position: i + 1,
|
|
110
|
+
score: r.score,
|
|
111
|
+
title: r.doc.metadata.title,
|
|
112
|
+
url: r.doc.id,
|
|
113
|
+
snippet: r.doc.metadata.description,
|
|
114
|
+
provider: r.doc.metadata.provider,
|
|
115
|
+
domain: this.extractDomain(r.doc.id),
|
|
116
|
+
publishedDate: r.doc.metadata?.publishedDate
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
calculateFreshnessScore(publishedDate) {
|
|
120
|
+
if (!publishedDate)
|
|
121
|
+
return 0.5; // Neutral for unknown dates
|
|
122
|
+
try {
|
|
123
|
+
const age = Date.now() - new Date(publishedDate).getTime();
|
|
124
|
+
const daysOld = age / (1000 * 60 * 60 * 24);
|
|
125
|
+
// Exponential decay: e^(-lambda * days)
|
|
126
|
+
// Lambda tuned so 7-day-old content has ~0.5 score
|
|
127
|
+
const lambda = 0.1;
|
|
128
|
+
return Math.exp(-lambda * daysOld);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return 0.5;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
calculateDomainScore(url) {
|
|
135
|
+
try {
|
|
136
|
+
const domain = new URL(url).hostname.toLowerCase();
|
|
137
|
+
// High authority domains
|
|
138
|
+
const highAuthorityDomains = [
|
|
139
|
+
'wikipedia.org',
|
|
140
|
+
'github.com',
|
|
141
|
+
'stackoverflow.com',
|
|
142
|
+
'reddit.com',
|
|
143
|
+
'medium.com',
|
|
144
|
+
'nytimes.com',
|
|
145
|
+
'bbc.com',
|
|
146
|
+
'theguardian.com',
|
|
147
|
+
'developer.mozilla.org',
|
|
148
|
+
'docs.rs'
|
|
149
|
+
];
|
|
150
|
+
// Academic/government
|
|
151
|
+
if (domain.endsWith('.edu') || domain.endsWith('.gov')) {
|
|
152
|
+
return 0.9;
|
|
153
|
+
}
|
|
154
|
+
// High authority
|
|
155
|
+
if (highAuthorityDomains.some(d => domain.includes(d))) {
|
|
156
|
+
return 1.0;
|
|
157
|
+
}
|
|
158
|
+
// Common TLDs
|
|
159
|
+
if (domain.endsWith('.com')) {
|
|
160
|
+
return 0.7;
|
|
161
|
+
}
|
|
162
|
+
if (domain.endsWith('.org')) {
|
|
163
|
+
return 0.65;
|
|
164
|
+
}
|
|
165
|
+
if (domain.endsWith('.net')) {
|
|
166
|
+
return 0.6;
|
|
167
|
+
}
|
|
168
|
+
// Country-specific TLDs
|
|
169
|
+
if (domain.endsWith('.io') || domain.endsWith('.dev') || domain.endsWith('.ai')) {
|
|
170
|
+
return 0.55;
|
|
171
|
+
}
|
|
172
|
+
return 0.5; // Default for unknown
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return 0.5;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
extractDomain(url) {
|
|
179
|
+
try {
|
|
180
|
+
return new URL(url).hostname;
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return 'unknown';
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// ============================================================================
|
|
188
|
+
// Re-ranking with Full Content (After Crawl4AI Extraction)
|
|
189
|
+
// ============================================================================
|
|
190
|
+
export function rerankWithFullContent(query, results, extractedContent) {
|
|
191
|
+
const ranker = new BM25Ranker();
|
|
192
|
+
// Index full content instead of just snippets
|
|
193
|
+
const documents = results
|
|
194
|
+
.filter(r => extractedContent.has(r.url))
|
|
195
|
+
.map(r => ({
|
|
196
|
+
id: r.url,
|
|
197
|
+
content: extractedContent.get(r.url),
|
|
198
|
+
metadata: r
|
|
199
|
+
}));
|
|
200
|
+
if (documents.length === 0)
|
|
201
|
+
return results;
|
|
202
|
+
ranker.indexDocuments(documents);
|
|
203
|
+
const ranked = ranker.rank(query, documents);
|
|
204
|
+
// Merge back with non-extracted results (at the end, with lower scores)
|
|
205
|
+
const extractedUrls = new Set(extractedContent.keys());
|
|
206
|
+
const nonExtracted = results
|
|
207
|
+
.filter(r => !extractedUrls.has(r.url))
|
|
208
|
+
.map((r, i) => ({
|
|
209
|
+
doc: { id: r.url, content: `${r.title} ${r.snippet}`, metadata: r },
|
|
210
|
+
score: 0 // Give non-extracted content lowest score
|
|
211
|
+
}));
|
|
212
|
+
const allRanked = [...ranked, ...nonExtracted]
|
|
213
|
+
.sort((a, b) => b.score - a.score)
|
|
214
|
+
.map((r, i) => r.doc.metadata)
|
|
215
|
+
.map((r, i) => ({ ...r, position: i + 1 }));
|
|
216
|
+
return allRanked;
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=ranking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ranking.js","sourceRoot":"","sources":["../src/ranking.ts"],"names":[],"mappings":"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"}
|
package/dist/search.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface RawSearchResult {
|
|
2
|
+
title: string;
|
|
3
|
+
url: string;
|
|
4
|
+
description: string;
|
|
5
|
+
provider: 'google' | 'duckduckgo';
|
|
6
|
+
}
|
|
7
|
+
export interface ProviderResponse {
|
|
8
|
+
results: RawSearchResult[];
|
|
9
|
+
provider: 'google' | 'duckduckgo';
|
|
10
|
+
hasResults: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function performDuckDuckGoSearch(query: string, limit?: number): Promise<ProviderResponse>;
|
|
13
|
+
export declare function performGoogleSearch(query: string, limit?: number): Promise<ProviderResponse>;
|
|
14
|
+
export declare function performSearch(query: string, limit?: number, preferProvider?: 'duckduckgo' | 'google' | 'auto'): Promise<ProviderResponse>;
|
|
15
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AA0CA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;CACrB;AAsCD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,gBAAgB,CAAC,CAqD3B;AAMD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,gBAAgB,CAAC,CA8C3B;AAMD,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,EAClB,cAAc,GAAE,YAAY,GAAG,QAAQ,GAAG,MAAe,GACxD,OAAO,CAAC,gBAAgB,CAAC,CA0B3B"}
|
package/dist/search.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Search Module - DuckDuckGo and Google Discovery
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import * as cheerio from 'cheerio';
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Validators (inlined to avoid module resolution issues)
|
|
6
|
+
// ============================================================================
|
|
7
|
+
function isValidUrl(url) {
|
|
8
|
+
if (!url || typeof url !== 'string')
|
|
9
|
+
return false;
|
|
10
|
+
try {
|
|
11
|
+
const parsed = new URL(url);
|
|
12
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
13
|
+
// Block localhost variants
|
|
14
|
+
if (hostname === 'localhost' ||
|
|
15
|
+
hostname === '127.0.0.1' ||
|
|
16
|
+
hostname === '0.0.0.0' ||
|
|
17
|
+
hostname === '[::1]' ||
|
|
18
|
+
hostname.startsWith('127.')) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
// Block private IP ranges
|
|
22
|
+
if (hostname.startsWith('192.168.') ||
|
|
23
|
+
hostname.startsWith('10.') ||
|
|
24
|
+
hostname.startsWith('172.16.')) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
// Only allow http/https
|
|
28
|
+
return url.startsWith('http://') || url.startsWith('https://');
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// Configuration
|
|
36
|
+
// ============================================================================
|
|
37
|
+
const USER_AGENTS = [
|
|
38
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
|
39
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
|
40
|
+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0',
|
|
41
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1 Safari/605.1.15'
|
|
42
|
+
];
|
|
43
|
+
const SEARCH_TIMEOUT = 10000; // 10 seconds
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Helper Functions
|
|
46
|
+
// ============================================================================
|
|
47
|
+
function getRandomUserAgent() {
|
|
48
|
+
return USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)];
|
|
49
|
+
}
|
|
50
|
+
function getCommonHeaders() {
|
|
51
|
+
return {
|
|
52
|
+
'User-Agent': getRandomUserAgent(),
|
|
53
|
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
54
|
+
'Accept-Language': 'en-US,en;q=0.9',
|
|
55
|
+
'Accept-Encoding': 'gzip, deflate, br',
|
|
56
|
+
'DNT': '1',
|
|
57
|
+
'Connection': 'keep-alive'
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// DuckDuckGo Search
|
|
62
|
+
// ============================================================================
|
|
63
|
+
export async function performDuckDuckGoSearch(query, limit = 10) {
|
|
64
|
+
try {
|
|
65
|
+
const response = await axios.get('https://html.duckduckgo.com/html/', {
|
|
66
|
+
params: { q: query },
|
|
67
|
+
headers: getCommonHeaders(),
|
|
68
|
+
timeout: SEARCH_TIMEOUT
|
|
69
|
+
});
|
|
70
|
+
const $ = cheerio.load(response.data);
|
|
71
|
+
const results = [];
|
|
72
|
+
$('.web-result').each((i, element) => {
|
|
73
|
+
if (i >= limit)
|
|
74
|
+
return false;
|
|
75
|
+
const titleElement = $(element).find('.result__title a.result__a');
|
|
76
|
+
const snippetElement = $(element).find('.result__snippet');
|
|
77
|
+
if (titleElement.length) {
|
|
78
|
+
let url = titleElement.attr('href');
|
|
79
|
+
const title = titleElement.text().trim();
|
|
80
|
+
// DuckDuckGo uses redirect URLs, extract the actual URL
|
|
81
|
+
if (url && url.startsWith('//duckduckgo.com/l/?uddg=')) {
|
|
82
|
+
try {
|
|
83
|
+
const encodedUrl = url.split('uddg=')[1]?.split('&')[0];
|
|
84
|
+
if (encodedUrl) {
|
|
85
|
+
url = decodeURIComponent(encodedUrl);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return; // Skip if decode fails
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (url && isValidUrl(url)) {
|
|
93
|
+
results.push({
|
|
94
|
+
title,
|
|
95
|
+
url,
|
|
96
|
+
description: snippetElement.text().trim() || '',
|
|
97
|
+
provider: 'duckduckgo'
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
results,
|
|
104
|
+
provider: 'duckduckgo',
|
|
105
|
+
hasResults: results.length > 0
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error('[Search] DuckDuckGo failed:', error instanceof Error ? error.message : error);
|
|
110
|
+
return { results: [], provider: 'duckduckgo', hasResults: false };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// ============================================================================
|
|
114
|
+
// Google Search (Fallback)
|
|
115
|
+
// ============================================================================
|
|
116
|
+
export async function performGoogleSearch(query, limit = 10) {
|
|
117
|
+
try {
|
|
118
|
+
const response = await axios.get('https://www.google.com/search', {
|
|
119
|
+
params: {
|
|
120
|
+
q: query,
|
|
121
|
+
num: limit
|
|
122
|
+
},
|
|
123
|
+
headers: {
|
|
124
|
+
...getCommonHeaders(),
|
|
125
|
+
'Upgrade-Insecure-Requests': '1'
|
|
126
|
+
},
|
|
127
|
+
timeout: SEARCH_TIMEOUT
|
|
128
|
+
});
|
|
129
|
+
const $ = cheerio.load(response.data);
|
|
130
|
+
const results = [];
|
|
131
|
+
$('div.g').each((i, element) => {
|
|
132
|
+
if (i >= limit)
|
|
133
|
+
return false;
|
|
134
|
+
const titleElement = $(element).find('h3');
|
|
135
|
+
const linkElement = $(element).find('a');
|
|
136
|
+
const snippetElement = $(element).find('.VwiC3b');
|
|
137
|
+
if (titleElement.length && linkElement.length) {
|
|
138
|
+
const url = linkElement.attr('href');
|
|
139
|
+
if (url && isValidUrl(url)) {
|
|
140
|
+
results.push({
|
|
141
|
+
title: titleElement.text().trim(),
|
|
142
|
+
url,
|
|
143
|
+
description: snippetElement.text().trim() || '',
|
|
144
|
+
provider: 'google'
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
results,
|
|
151
|
+
provider: 'google',
|
|
152
|
+
hasResults: results.length > 0
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
console.error('[Search] Google failed:', error instanceof Error ? error.message : error);
|
|
157
|
+
return { results: [], provider: 'google', hasResults: false };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// ============================================================================
|
|
161
|
+
// Unified Search with Fallback
|
|
162
|
+
// ============================================================================
|
|
163
|
+
export async function performSearch(query, limit = 10, preferProvider = 'auto') {
|
|
164
|
+
// Validate inputs
|
|
165
|
+
if (!query || query.trim().length === 0) {
|
|
166
|
+
return { results: [], provider: 'duckduckgo', hasResults: false };
|
|
167
|
+
}
|
|
168
|
+
const actualLimit = Math.min(Math.max(limit, 1), 50);
|
|
169
|
+
// Try preferred provider first, then fallback
|
|
170
|
+
let response;
|
|
171
|
+
if (preferProvider === 'google') {
|
|
172
|
+
response = await performGoogleSearch(query, actualLimit);
|
|
173
|
+
if (!response.hasResults) {
|
|
174
|
+
console.error('[Search] Google failed, trying DuckDuckGo...');
|
|
175
|
+
response = await performDuckDuckGoSearch(query, actualLimit);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
response = await performDuckDuckGoSearch(query, actualLimit);
|
|
180
|
+
if (!response.hasResults) {
|
|
181
|
+
console.error('[Search] DuckDuckGo failed, trying Google...');
|
|
182
|
+
response = await performGoogleSearch(query, actualLimit);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return response;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
export interface SearchArgs {
|
|
2
|
+
query: string;
|
|
3
|
+
limit?: number;
|
|
4
|
+
rankingMode?: 'bm25' | 'tfidf' | 'hybrid';
|
|
5
|
+
freshness?: 'day' | 'week' | 'month';
|
|
6
|
+
}
|
|
7
|
+
export interface SearchResult {
|
|
8
|
+
position: number;
|
|
9
|
+
score: number;
|
|
10
|
+
title: string;
|
|
11
|
+
url: string;
|
|
12
|
+
snippet: string;
|
|
13
|
+
provider: 'duckduckgo' | 'google';
|
|
14
|
+
domain: string;
|
|
15
|
+
publishedDate?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CrawlArgs {
|
|
18
|
+
urls: string[];
|
|
19
|
+
extractDepth?: 'basic' | 'advanced';
|
|
20
|
+
includeImages?: boolean;
|
|
21
|
+
waitForSelector?: string;
|
|
22
|
+
executeJavascript?: boolean;
|
|
23
|
+
timeout?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface CrawlResult {
|
|
26
|
+
url: string;
|
|
27
|
+
success: boolean;
|
|
28
|
+
markdown?: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
wordCount?: number;
|
|
31
|
+
images?: string[];
|
|
32
|
+
links?: number;
|
|
33
|
+
extractedAt?: string;
|
|
34
|
+
durationMs?: number;
|
|
35
|
+
error?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface SearchAndCrawlArgs extends SearchArgs {
|
|
38
|
+
extractTopN?: number;
|
|
39
|
+
rerankAfterExtract?: boolean;
|
|
40
|
+
extractDepth?: 'basic' | 'advanced';
|
|
41
|
+
includeImages?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface SearchAndCrawlResult {
|
|
44
|
+
searchResults: SearchResult[];
|
|
45
|
+
extractedContent: CrawlResult[];
|
|
46
|
+
summary: {
|
|
47
|
+
totalFetched: number;
|
|
48
|
+
successful: number;
|
|
49
|
+
failed: number;
|
|
50
|
+
totalTimeMs: number;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export interface BulkCrawlArgs {
|
|
54
|
+
urls: string[];
|
|
55
|
+
concurrency?: number;
|
|
56
|
+
extractDepth?: 'basic' | 'advanced';
|
|
57
|
+
includeImages?: boolean;
|
|
58
|
+
timeout?: number;
|
|
59
|
+
continueOnError?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export interface BulkCrawlResult {
|
|
62
|
+
results: CrawlResult[];
|
|
63
|
+
summary: {
|
|
64
|
+
total: number;
|
|
65
|
+
successful: number;
|
|
66
|
+
failed: number;
|
|
67
|
+
totalTimeMs: number;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export interface SearchWithFiltersArgs extends SearchArgs {
|
|
71
|
+
includeDomains?: string[];
|
|
72
|
+
excludeDomains?: string[];
|
|
73
|
+
site?: string;
|
|
74
|
+
fileType?: 'pdf' | 'doc' | 'xls' | 'ppt';
|
|
75
|
+
resultType?: 'web' | 'news' | 'videos' | 'images';
|
|
76
|
+
language?: string;
|
|
77
|
+
region?: string;
|
|
78
|
+
}
|
|
79
|
+
export interface Document {
|
|
80
|
+
id: string;
|
|
81
|
+
content: string;
|
|
82
|
+
metadata?: Record<string, unknown>;
|
|
83
|
+
}
|
|
84
|
+
export interface RankedDocument {
|
|
85
|
+
doc: Document;
|
|
86
|
+
score: number;
|
|
87
|
+
breakdown?: {
|
|
88
|
+
bm25: number;
|
|
89
|
+
freshness: number;
|
|
90
|
+
domain: number;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export interface HybridScoreConfig {
|
|
94
|
+
alpha: number;
|
|
95
|
+
beta: number;
|
|
96
|
+
gamma: number;
|
|
97
|
+
}
|
|
98
|
+
export interface Crawl4AIConfig {
|
|
99
|
+
extractDepth?: 'basic' | 'advanced';
|
|
100
|
+
includeImages?: boolean;
|
|
101
|
+
waitForSelector?: string;
|
|
102
|
+
executeJavascript?: boolean;
|
|
103
|
+
timeout?: number;
|
|
104
|
+
}
|
|
105
|
+
export interface Crawl4AIResponse {
|
|
106
|
+
success: boolean;
|
|
107
|
+
url?: string;
|
|
108
|
+
markdown?: string;
|
|
109
|
+
cleaned_html?: string;
|
|
110
|
+
title?: string;
|
|
111
|
+
links?: {
|
|
112
|
+
internal: number;
|
|
113
|
+
external: number;
|
|
114
|
+
};
|
|
115
|
+
media?: {
|
|
116
|
+
images: string[];
|
|
117
|
+
};
|
|
118
|
+
error?: string;
|
|
119
|
+
}
|
|
120
|
+
export interface RawSearchResult {
|
|
121
|
+
title: string;
|
|
122
|
+
url: string;
|
|
123
|
+
description: string;
|
|
124
|
+
provider: 'google' | 'duckduckgo';
|
|
125
|
+
}
|
|
126
|
+
export interface ProviderResponse {
|
|
127
|
+
results: RawSearchResult[];
|
|
128
|
+
provider: 'google' | 'duckduckgo';
|
|
129
|
+
hasResults: boolean;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,+CAA+C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a concurrency limiter for controlling parallel operations.
|
|
3
|
+
* @param concurrency - Maximum number of concurrent operations (default: 5)
|
|
4
|
+
* @returns A limit function that wraps async operations
|
|
5
|
+
*/
|
|
6
|
+
export declare function createConcurrencyLimiter(concurrency?: number): import("p-limit").LimitFunction;
|
|
7
|
+
/**
|
|
8
|
+
* Processes items in batches with concurrency control.
|
|
9
|
+
* @param items - Array of items to process
|
|
10
|
+
* @param processor - Async function to process each item
|
|
11
|
+
* @param concurrency - Maximum concurrent operations
|
|
12
|
+
* @returns Array of results in the same order as input
|
|
13
|
+
*/
|
|
14
|
+
export declare function processBatch<T, R>(items: T[], processor: (item: T, index: number) => Promise<R>, concurrency?: number): Promise<R[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Processes items with graceful error handling.
|
|
17
|
+
* Failed items return undefined instead of rejecting the entire batch.
|
|
18
|
+
* @param items - Array of items to process
|
|
19
|
+
* @param processor - Async function to process each item
|
|
20
|
+
* @param concurrency - Maximum concurrent operations
|
|
21
|
+
* @returns Array of successful results or undefined for failed items
|
|
22
|
+
*/
|
|
23
|
+
export declare function processBatchWithErrorHandling<T, R>(items: T[], processor: (item: T, index: number) => Promise<R>, concurrency?: number): Promise<Array<R | undefined>>;
|
|
24
|
+
//# sourceMappingURL=concurrency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concurrency.d.ts","sourceRoot":"","sources":["../../src/utils/concurrency.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,GAAE,MAAU,mCAE/D;AAMD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,CAAC,EACrC,KAAK,EAAE,CAAC,EAAE,EACV,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EACjD,WAAW,GAAE,MAAU,GACtB,OAAO,CAAC,CAAC,EAAE,CAAC,CAQd;AAMD;;;;;;;GAOG;AACH,wBAAsB,6BAA6B,CAAC,CAAC,EAAE,CAAC,EACtD,KAAK,EAAE,CAAC,EAAE,EACV,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EACjD,WAAW,GAAE,MAAU,GACtB,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAe/B"}
|