@librechat/agents 2.4.317 → 2.4.318
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/cjs/tools/search/content.cjs +140 -0
- package/dist/cjs/tools/search/content.cjs.map +1 -0
- package/dist/cjs/tools/search/firecrawl.cjs +17 -37
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs +79 -29
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/highlights.cjs +64 -13
- package/dist/cjs/tools/search/highlights.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +13 -15
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +44 -12
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +35 -0
- package/dist/cjs/tools/search/utils.cjs.map +1 -0
- package/dist/esm/tools/search/content.mjs +119 -0
- package/dist/esm/tools/search/content.mjs.map +1 -0
- package/dist/esm/tools/search/firecrawl.mjs +18 -37
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs +79 -29
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/highlights.mjs +64 -13
- package/dist/esm/tools/search/highlights.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +12 -14
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +44 -12
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +32 -0
- package/dist/esm/tools/search/utils.mjs.map +1 -0
- package/dist/types/tools/search/content.d.ts +4 -0
- package/dist/types/tools/search/firecrawl.d.ts +6 -86
- package/dist/types/tools/search/format.d.ts +4 -1
- package/dist/types/tools/search/highlights.d.ts +1 -1
- package/dist/types/tools/search/search.d.ts +1 -1
- package/dist/types/tools/search/test.d.ts +1 -0
- package/dist/types/tools/search/tool.d.ts +12 -4
- package/dist/types/tools/search/types.d.ts +380 -46
- package/dist/types/tools/search/utils.d.ts +3 -0
- package/package.json +2 -1
- package/src/scripts/search.ts +5 -3
- package/src/tools/search/content.test.ts +173 -0
- package/src/tools/search/content.ts +147 -0
- package/src/tools/search/firecrawl.ts +27 -144
- package/src/tools/search/format.ts +89 -31
- package/src/tools/search/highlights.ts +99 -17
- package/src/tools/search/output.md +2775 -0
- package/src/tools/search/search.ts +42 -54
- package/src/tools/search/test.html +884 -0
- package/src/tools/search/test.md +643 -0
- package/src/tools/search/test.ts +159 -0
- package/src/tools/search/tool.ts +54 -15
- package/src/tools/search/types.ts +430 -52
- package/src/tools/search/utils.ts +43 -0
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';
|
|
4
4
|
import type * as t from './types';
|
|
5
|
-
import {
|
|
5
|
+
import { FirecrawlScraper } from './firecrawl';
|
|
6
6
|
import { BaseReranker } from './rerankers';
|
|
7
|
+
import { getAttribution } from './utils';
|
|
7
8
|
|
|
8
9
|
const chunker = {
|
|
9
10
|
cleanText: (text: string): string => {
|
|
@@ -116,16 +117,11 @@ const getHighlights = async ({
|
|
|
116
117
|
const createSerperAPI = (
|
|
117
118
|
apiKey?: string
|
|
118
119
|
): {
|
|
119
|
-
getSources: (
|
|
120
|
-
query: string,
|
|
121
|
-
numResults?: number,
|
|
122
|
-
storedLocation?: string
|
|
123
|
-
) => Promise<t.SearchResult>;
|
|
120
|
+
getSources: (params: t.GetSourcesParams) => Promise<t.SearchResult>;
|
|
124
121
|
} => {
|
|
125
122
|
const config = {
|
|
126
123
|
apiKey: apiKey ?? process.env.SERPER_API_KEY,
|
|
127
124
|
apiUrl: 'https://google.serper.dev/search',
|
|
128
|
-
defaultLocation: 'us',
|
|
129
125
|
timeout: 10000,
|
|
130
126
|
};
|
|
131
127
|
|
|
@@ -133,43 +129,46 @@ const createSerperAPI = (
|
|
|
133
129
|
throw new Error('SERPER_API_KEY is required for SerperAPI');
|
|
134
130
|
}
|
|
135
131
|
|
|
136
|
-
const getSources = async (
|
|
137
|
-
query
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
): Promise<t.SearchResult> => {
|
|
132
|
+
const getSources = async ({
|
|
133
|
+
query,
|
|
134
|
+
country,
|
|
135
|
+
numResults = 8,
|
|
136
|
+
}: t.GetSourcesParams): Promise<t.SearchResult> => {
|
|
141
137
|
if (!query.trim()) {
|
|
142
138
|
return { success: false, error: 'Query cannot be empty' };
|
|
143
139
|
}
|
|
144
140
|
|
|
145
141
|
try {
|
|
146
|
-
const
|
|
147
|
-
storedLocation ?? config.defaultLocation
|
|
148
|
-
).toLowerCase();
|
|
149
|
-
|
|
150
|
-
const payload = {
|
|
142
|
+
const payload: t.SerperSearchPayload = {
|
|
151
143
|
q: query,
|
|
152
144
|
num: Math.min(Math.max(1, numResults), 10),
|
|
153
|
-
gl: searchLocation,
|
|
154
145
|
};
|
|
155
146
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
147
|
+
if (country != null && country !== '') {
|
|
148
|
+
payload['gl'] = country.toLowerCase();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const response = await axios.post<t.SerperResultData>(
|
|
152
|
+
config.apiUrl,
|
|
153
|
+
payload,
|
|
154
|
+
{
|
|
155
|
+
headers: {
|
|
156
|
+
'X-API-KEY': config.apiKey,
|
|
157
|
+
'Content-Type': 'application/json',
|
|
158
|
+
},
|
|
159
|
+
timeout: config.timeout,
|
|
160
|
+
}
|
|
161
|
+
);
|
|
163
162
|
|
|
164
163
|
const data = response.data;
|
|
165
164
|
const results: t.SearchResultData = {
|
|
166
165
|
organic: data.organic,
|
|
167
166
|
images: data.images ?? [],
|
|
167
|
+
answerBox: data.answerBox,
|
|
168
168
|
topStories: data.topStories ?? [],
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
relatedSearches: data.relatedSearches as string[],
|
|
169
|
+
peopleAlsoAsk: data.peopleAlsoAsk,
|
|
170
|
+
knowledgeGraph: data.knowledgeGraph,
|
|
171
|
+
relatedSearches: data.relatedSearches,
|
|
173
172
|
};
|
|
174
173
|
|
|
175
174
|
return { success: true, data: results };
|
|
@@ -187,11 +186,7 @@ const createSearXNGAPI = (
|
|
|
187
186
|
instanceUrl?: string,
|
|
188
187
|
apiKey?: string
|
|
189
188
|
): {
|
|
190
|
-
getSources: (
|
|
191
|
-
query: string,
|
|
192
|
-
numResults?: number,
|
|
193
|
-
storedLocation?: string
|
|
194
|
-
) => Promise<t.SearchResult>;
|
|
189
|
+
getSources: (params: t.GetSourcesParams) => Promise<t.SearchResult>;
|
|
195
190
|
} => {
|
|
196
191
|
const config = {
|
|
197
192
|
instanceUrl: instanceUrl ?? process.env.SEARXNG_INSTANCE_URL,
|
|
@@ -204,11 +199,10 @@ const createSearXNGAPI = (
|
|
|
204
199
|
throw new Error('SEARXNG_INSTANCE_URL is required for SearXNG API');
|
|
205
200
|
}
|
|
206
201
|
|
|
207
|
-
const getSources = async (
|
|
208
|
-
query
|
|
209
|
-
numResults
|
|
210
|
-
|
|
211
|
-
): Promise<t.SearchResult> => {
|
|
202
|
+
const getSources = async ({
|
|
203
|
+
query,
|
|
204
|
+
numResults = 8,
|
|
205
|
+
}: t.GetSourcesParams): Promise<t.SearchResult> => {
|
|
212
206
|
if (!query.trim()) {
|
|
213
207
|
return { success: false, error: 'Query cannot be empty' };
|
|
214
208
|
}
|
|
@@ -225,7 +219,7 @@ const createSearXNGAPI = (
|
|
|
225
219
|
}
|
|
226
220
|
|
|
227
221
|
// Prepare parameters for SearXNG
|
|
228
|
-
const params:
|
|
222
|
+
const params: t.SearxNGSearchPayload = {
|
|
229
223
|
q: query,
|
|
230
224
|
format: 'json',
|
|
231
225
|
pageno: 1,
|
|
@@ -233,13 +227,8 @@ const createSearXNGAPI = (
|
|
|
233
227
|
language: 'all',
|
|
234
228
|
safesearch: 0,
|
|
235
229
|
engines: 'google,bing,duckduckgo',
|
|
236
|
-
max_results: Math.min(Math.max(1, numResults), 20),
|
|
237
230
|
};
|
|
238
231
|
|
|
239
|
-
if (storedLocation != null && storedLocation !== 'all') {
|
|
240
|
-
params.language = storedLocation;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
232
|
const headers: Record<string, string> = {
|
|
244
233
|
'Content-Type': 'application/json',
|
|
245
234
|
};
|
|
@@ -301,11 +290,7 @@ const createSearXNGAPI = (
|
|
|
301
290
|
export const createSearchAPI = (
|
|
302
291
|
config: t.SearchConfig
|
|
303
292
|
): {
|
|
304
|
-
getSources: (
|
|
305
|
-
query: string,
|
|
306
|
-
numResults?: number,
|
|
307
|
-
storedLocation?: string
|
|
308
|
-
) => Promise<t.SearchResult>;
|
|
293
|
+
getSources: (params: t.GetSourcesParams) => Promise<t.SearchResult>;
|
|
309
294
|
} => {
|
|
310
295
|
const {
|
|
311
296
|
searchProvider = 'serper',
|
|
@@ -366,12 +351,14 @@ export const createSourceProcessor = (
|
|
|
366
351
|
.then(([url, response]) => {
|
|
367
352
|
const attribution = getAttribution(url, response.data?.metadata);
|
|
368
353
|
if (response.success && response.data) {
|
|
369
|
-
const content =
|
|
354
|
+
const [content, references] =
|
|
355
|
+
firecrawlScraper.extractContent(response);
|
|
370
356
|
return {
|
|
371
357
|
url,
|
|
358
|
+
references,
|
|
372
359
|
attribution,
|
|
373
360
|
content: chunker.cleanText(content),
|
|
374
|
-
};
|
|
361
|
+
} as t.ScrapeResult;
|
|
375
362
|
}
|
|
376
363
|
|
|
377
364
|
return {
|
|
@@ -379,7 +366,7 @@ export const createSourceProcessor = (
|
|
|
379
366
|
attribution,
|
|
380
367
|
error: true,
|
|
381
368
|
content: `Failed to scrape ${url}: ${response.error ?? 'Unknown error'}`,
|
|
382
|
-
};
|
|
369
|
+
} as t.ScrapeResult;
|
|
383
370
|
})
|
|
384
371
|
.then(async (result) => {
|
|
385
372
|
try {
|
|
@@ -443,10 +430,11 @@ export const createSourceProcessor = (
|
|
|
443
430
|
if (result.error === true) {
|
|
444
431
|
continue;
|
|
445
432
|
}
|
|
446
|
-
const { url, content, attribution, highlights } = result;
|
|
433
|
+
const { url, content, attribution, references, highlights } = result;
|
|
447
434
|
onContentScraped?.(url, {
|
|
448
435
|
content,
|
|
449
436
|
attribution,
|
|
437
|
+
references,
|
|
450
438
|
highlights,
|
|
451
439
|
});
|
|
452
440
|
}
|