@librechat/agents 2.4.50 → 2.4.52
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/llm/openai/index.cjs +1 -75
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +80 -13
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +3 -76
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +80 -13
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/types/llm/openai/index.d.ts +1 -8
- package/dist/types/tools/search/types.d.ts +9 -0
- package/package.json +3 -3
- package/src/llm/openai/index.ts +2 -80
- package/src/specs/anthropic.simple.test.ts +1 -1
- package/src/tools/search/search.ts +90 -13
- package/src/tools/search/types.ts +9 -0
|
@@ -287,34 +287,111 @@ const createSearXNGAPI = (
|
|
|
287
287
|
|
|
288
288
|
const data = response.data;
|
|
289
289
|
|
|
290
|
+
// Helper function to identify news results since SearXNG doesn't provide that classification by default
|
|
291
|
+
const isNewsResult = (result: t.SearXNGResult): boolean => {
|
|
292
|
+
const url = result.url?.toLowerCase() ?? '';
|
|
293
|
+
const title = result.title?.toLowerCase() ?? '';
|
|
294
|
+
|
|
295
|
+
// News-related keywords in title/content
|
|
296
|
+
const newsKeywords = [
|
|
297
|
+
'breaking news',
|
|
298
|
+
'latest news',
|
|
299
|
+
'top stories',
|
|
300
|
+
'news today',
|
|
301
|
+
'developing story',
|
|
302
|
+
'trending news',
|
|
303
|
+
'news',
|
|
304
|
+
];
|
|
305
|
+
|
|
306
|
+
// Check if title/content contains news keywords
|
|
307
|
+
const hasNewsKeywords = newsKeywords.some(
|
|
308
|
+
(keyword) => title.toLowerCase().includes(keyword) // just title probably fine, content parsing is overkill for what we need: || content.includes(keyword)
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
// Check if URL contains news-related paths
|
|
312
|
+
const hasNewsPath =
|
|
313
|
+
url.includes('/news/') ||
|
|
314
|
+
url.includes('/world/') ||
|
|
315
|
+
url.includes('/politics/') ||
|
|
316
|
+
url.includes('/breaking/');
|
|
317
|
+
|
|
318
|
+
return hasNewsKeywords || hasNewsPath;
|
|
319
|
+
};
|
|
320
|
+
|
|
290
321
|
// Transform SearXNG results to match SerperAPI format
|
|
291
322
|
const organicResults = (data.results ?? [])
|
|
292
323
|
.slice(0, numResults)
|
|
293
|
-
.map((result: t.SearXNGResult) =>
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
324
|
+
.map((result: t.SearXNGResult, index: number) => {
|
|
325
|
+
let attribution = '';
|
|
326
|
+
try {
|
|
327
|
+
attribution = new URL(result.url ?? '').hostname;
|
|
328
|
+
} catch {
|
|
329
|
+
attribution = '';
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
position: index + 1,
|
|
334
|
+
title: result.title ?? '',
|
|
335
|
+
link: result.url ?? '',
|
|
336
|
+
snippet: result.content ?? '',
|
|
337
|
+
date: result.publishedDate ?? '',
|
|
338
|
+
attribution,
|
|
339
|
+
};
|
|
340
|
+
});
|
|
299
341
|
|
|
300
|
-
// Extract image results if available
|
|
301
342
|
const imageResults = (data.results ?? [])
|
|
302
343
|
.filter((result: t.SearXNGResult) => result.img_src)
|
|
303
344
|
.slice(0, 6)
|
|
304
|
-
.map((result: t.SearXNGResult) => ({
|
|
345
|
+
.map((result: t.SearXNGResult, index: number) => ({
|
|
305
346
|
title: result.title ?? '',
|
|
306
347
|
imageUrl: result.img_src ?? '',
|
|
348
|
+
position: index + 1,
|
|
349
|
+
source: new URL(result.url ?? '').hostname,
|
|
350
|
+
domain: new URL(result.url ?? '').hostname,
|
|
351
|
+
link: result.url ?? '',
|
|
307
352
|
}));
|
|
308
353
|
|
|
309
|
-
//
|
|
354
|
+
// Extract news results from organic results
|
|
355
|
+
const newsResults = (data.results ?? [])
|
|
356
|
+
.filter(isNewsResult)
|
|
357
|
+
.map((result: t.SearXNGResult, index: number) => {
|
|
358
|
+
let attribution = '';
|
|
359
|
+
try {
|
|
360
|
+
attribution = new URL(result.url ?? '').hostname;
|
|
361
|
+
} catch {
|
|
362
|
+
attribution = '';
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
title: result.title ?? '',
|
|
367
|
+
link: result.url ?? '',
|
|
368
|
+
snippet: result.content ?? '',
|
|
369
|
+
date: result.publishedDate ?? '',
|
|
370
|
+
source: attribution,
|
|
371
|
+
imageUrl: result.img_src ?? '',
|
|
372
|
+
position: index + 1,
|
|
373
|
+
};
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
const topStories = newsResults.slice(0, 5);
|
|
377
|
+
|
|
378
|
+
const relatedSearches = Array.isArray(data.suggestions)
|
|
379
|
+
? data.suggestions.map((suggestion: string) => ({ query: suggestion }))
|
|
380
|
+
: [];
|
|
381
|
+
|
|
310
382
|
const results: t.SearchResultData = {
|
|
311
383
|
organic: organicResults,
|
|
312
384
|
images: imageResults,
|
|
313
|
-
topStories:
|
|
314
|
-
|
|
315
|
-
relatedSearches: data.suggestions ?? [],
|
|
385
|
+
topStories: topStories, // Use first 5 extracted news as top stories
|
|
386
|
+
relatedSearches,
|
|
316
387
|
videos: [],
|
|
317
|
-
news:
|
|
388
|
+
news: newsResults,
|
|
389
|
+
// Add empty arrays for other Serper fields to maintain parity
|
|
390
|
+
places: [],
|
|
391
|
+
shopping: [],
|
|
392
|
+
peopleAlsoAsk: [],
|
|
393
|
+
knowledgeGraph: undefined,
|
|
394
|
+
answerBox: undefined,
|
|
318
395
|
};
|
|
319
396
|
|
|
320
397
|
return { success: true, data: results };
|
|
@@ -581,6 +581,15 @@ export interface SearXNGResult {
|
|
|
581
581
|
content?: string;
|
|
582
582
|
publishedDate?: string;
|
|
583
583
|
img_src?: string;
|
|
584
|
+
score?: number;
|
|
585
|
+
engine?: string;
|
|
586
|
+
category?: string;
|
|
587
|
+
thumbnail?: string;
|
|
588
|
+
priority?: string;
|
|
589
|
+
engines?: string[];
|
|
590
|
+
positions?: number[];
|
|
591
|
+
template?: string;
|
|
592
|
+
parsed_url?: string[];
|
|
584
593
|
}
|
|
585
594
|
|
|
586
595
|
export type ProcessSourcesFields = {
|