@librechat/agents 2.4.320 → 2.4.322
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/firecrawl.cjs +6 -4
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs +117 -80
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs +43 -36
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/schema.cjs +70 -0
- package/dist/cjs/tools/search/schema.cjs.map +1 -0
- package/dist/cjs/tools/search/search.cjs +125 -52
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +162 -47
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +34 -5
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/esm/tools/search/firecrawl.mjs +6 -4
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs +118 -81
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs +43 -36
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/schema.mjs +61 -0
- package/dist/esm/tools/search/schema.mjs.map +1 -0
- package/dist/esm/tools/search/search.mjs +126 -53
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +161 -46
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +33 -6
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/types/tools/search/firecrawl.d.ts +1 -0
- package/dist/types/tools/search/rerankers.d.ts +8 -4
- package/dist/types/tools/search/schema.d.ts +16 -0
- package/dist/types/tools/search/tool.d.ts +13 -0
- package/dist/types/tools/search/types.d.ts +36 -0
- package/dist/types/tools/search/utils.d.ts +9 -2
- package/package.json +3 -2
- package/src/scripts/search.ts +3 -0
- package/src/tools/search/firecrawl.ts +9 -4
- package/src/tools/search/format.ts +157 -87
- package/src/tools/search/rerankers.ts +57 -36
- package/src/tools/search/schema.ts +63 -0
- package/src/tools/search/search.ts +165 -52
- package/src/tools/search/tool.ts +217 -44
- package/src/tools/search/types.ts +37 -0
- package/src/tools/search/utils.ts +37 -5
- package/src/utils/llmConfig.ts +1 -1
|
@@ -1,51 +1,154 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { tool } from '@langchain/core/tools';
|
|
3
|
+
import { newsSchema, videosSchema, imagesSchema, dateSchema, querySchema, countrySchema } from './schema.mjs';
|
|
3
4
|
import { createSearchAPI, createSourceProcessor } from './search.mjs';
|
|
4
5
|
import { createFirecrawlScraper } from './firecrawl.mjs';
|
|
5
6
|
import { expandHighlights } from './highlights.mjs';
|
|
6
7
|
import { formatResultsForLLM } from './format.mjs';
|
|
8
|
+
import { createDefaultLogger } from './utils.mjs';
|
|
7
9
|
import { createReranker } from './rerankers.mjs';
|
|
8
10
|
import { Constants } from '../../common/enum.mjs';
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Executes parallel searches and merges the results
|
|
14
|
+
*/
|
|
15
|
+
async function executeParallelSearches({ searchAPI, query, date, country, safeSearch, images, videos, news, logger, }) {
|
|
16
|
+
// Prepare all search tasks to run in parallel
|
|
17
|
+
const searchTasks = [
|
|
18
|
+
// Main search
|
|
19
|
+
searchAPI.getSources({
|
|
20
|
+
query,
|
|
21
|
+
date,
|
|
22
|
+
country,
|
|
23
|
+
safeSearch,
|
|
24
|
+
}),
|
|
25
|
+
];
|
|
26
|
+
if (images) {
|
|
27
|
+
searchTasks.push(searchAPI
|
|
28
|
+
.getSources({
|
|
29
|
+
query,
|
|
30
|
+
date,
|
|
31
|
+
country,
|
|
32
|
+
safeSearch,
|
|
33
|
+
type: 'images',
|
|
34
|
+
})
|
|
35
|
+
.catch((error) => {
|
|
36
|
+
logger.error('Error fetching images:', error);
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
error: `Images search failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
40
|
+
};
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
if (videos) {
|
|
44
|
+
searchTasks.push(searchAPI
|
|
45
|
+
.getSources({
|
|
46
|
+
query,
|
|
47
|
+
date,
|
|
48
|
+
country,
|
|
49
|
+
safeSearch,
|
|
50
|
+
type: 'videos',
|
|
51
|
+
})
|
|
52
|
+
.catch((error) => {
|
|
53
|
+
logger.error('Error fetching videos:', error);
|
|
54
|
+
return {
|
|
55
|
+
success: false,
|
|
56
|
+
error: `Videos search failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
57
|
+
};
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
if (news) {
|
|
61
|
+
searchTasks.push(searchAPI
|
|
62
|
+
.getSources({
|
|
63
|
+
query,
|
|
64
|
+
date,
|
|
65
|
+
country,
|
|
66
|
+
safeSearch,
|
|
67
|
+
type: 'news',
|
|
68
|
+
})
|
|
69
|
+
.catch((error) => {
|
|
70
|
+
logger.error('Error fetching news:', error);
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
error: `News search failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
74
|
+
};
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
// Run all searches in parallel
|
|
78
|
+
const results = await Promise.all(searchTasks);
|
|
79
|
+
// Get the main search result (first result)
|
|
80
|
+
const mainResult = results[0];
|
|
81
|
+
if (!mainResult.success) {
|
|
82
|
+
throw new Error(mainResult.error ?? 'Search failed');
|
|
83
|
+
}
|
|
84
|
+
// Merge additional results with the main results
|
|
85
|
+
const mergedResults = { ...mainResult.data };
|
|
86
|
+
// Convert existing news to topStories if present
|
|
87
|
+
if (mergedResults.news !== undefined && mergedResults.news.length > 0) {
|
|
88
|
+
const existingNewsAsTopStories = mergedResults.news
|
|
89
|
+
.filter((newsItem) => newsItem.link !== undefined && newsItem.link !== '')
|
|
90
|
+
.map((newsItem) => ({
|
|
91
|
+
title: newsItem.title ?? '',
|
|
92
|
+
link: newsItem.link ?? '',
|
|
93
|
+
source: newsItem.source ?? '',
|
|
94
|
+
date: newsItem.date ?? '',
|
|
95
|
+
imageUrl: newsItem.imageUrl ?? '',
|
|
96
|
+
processed: false,
|
|
97
|
+
}));
|
|
98
|
+
mergedResults.topStories = [
|
|
99
|
+
...(mergedResults.topStories ?? []),
|
|
100
|
+
...existingNewsAsTopStories,
|
|
101
|
+
];
|
|
102
|
+
delete mergedResults.news;
|
|
103
|
+
}
|
|
104
|
+
results.slice(1).forEach((result) => {
|
|
105
|
+
if (result.success && result.data !== undefined) {
|
|
106
|
+
if (result.data.images !== undefined && result.data.images.length > 0) {
|
|
107
|
+
mergedResults.images = [
|
|
108
|
+
...(mergedResults.images ?? []),
|
|
109
|
+
...result.data.images,
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
if (result.data.videos !== undefined && result.data.videos.length > 0) {
|
|
113
|
+
mergedResults.videos = [
|
|
114
|
+
...(mergedResults.videos ?? []),
|
|
115
|
+
...result.data.videos,
|
|
116
|
+
];
|
|
45
117
|
}
|
|
118
|
+
if (result.data.news !== undefined && result.data.news.length > 0) {
|
|
119
|
+
const newsAsTopStories = result.data.news.map((newsItem) => ({
|
|
120
|
+
...newsItem,
|
|
121
|
+
link: newsItem.link ?? '',
|
|
122
|
+
}));
|
|
123
|
+
mergedResults.topStories = [
|
|
124
|
+
...(mergedResults.topStories ?? []),
|
|
125
|
+
...newsAsTopStories,
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
return { success: true, data: mergedResults };
|
|
131
|
+
}
|
|
132
|
+
function createSearchProcessor({ searchAPI, safeSearch, sourceProcessor, onGetHighlights, logger, }) {
|
|
133
|
+
return async function ({ query, date, country, proMode = true, maxSources = 5, onSearchResults, images = false, videos = false, news = false, }) {
|
|
134
|
+
try {
|
|
135
|
+
// Execute parallel searches and merge results
|
|
136
|
+
const searchResult = await executeParallelSearches({
|
|
137
|
+
searchAPI,
|
|
138
|
+
query,
|
|
139
|
+
date,
|
|
140
|
+
country,
|
|
141
|
+
safeSearch,
|
|
142
|
+
images,
|
|
143
|
+
videos,
|
|
144
|
+
news,
|
|
145
|
+
logger,
|
|
146
|
+
});
|
|
147
|
+
onSearchResults?.(searchResult);
|
|
46
148
|
const processedSources = await sourceProcessor.processSources({
|
|
47
149
|
query,
|
|
48
|
-
|
|
150
|
+
news,
|
|
151
|
+
result: searchResult,
|
|
49
152
|
proMode,
|
|
50
153
|
onGetHighlights,
|
|
51
154
|
numElements: maxSources,
|
|
@@ -53,11 +156,13 @@ function createSearchProcessor({ searchAPI, sourceProcessor, onGetHighlights, })
|
|
|
53
156
|
return expandHighlights(processedSources);
|
|
54
157
|
}
|
|
55
158
|
catch (error) {
|
|
56
|
-
|
|
159
|
+
logger.error('Error in search:', error);
|
|
57
160
|
return {
|
|
58
161
|
organic: [],
|
|
59
162
|
topStories: [],
|
|
60
163
|
images: [],
|
|
164
|
+
videos: [],
|
|
165
|
+
news: [],
|
|
61
166
|
relatedSearches: [],
|
|
62
167
|
error: error instanceof Error ? error.message : String(error),
|
|
63
168
|
};
|
|
@@ -74,11 +179,15 @@ function createOnSearchResults({ runnableConfig, onSearchResults, }) {
|
|
|
74
179
|
}
|
|
75
180
|
function createTool({ schema, search, onSearchResults: _onSearchResults, }) {
|
|
76
181
|
return tool(async (params, runnableConfig) => {
|
|
77
|
-
const { query, country: _c } = params;
|
|
182
|
+
const { query, date, country: _c, images, videos, news } = params;
|
|
78
183
|
const country = typeof _c === 'string' && _c ? _c : undefined;
|
|
79
184
|
const searchResult = await search({
|
|
80
185
|
query,
|
|
186
|
+
date,
|
|
81
187
|
country,
|
|
188
|
+
images,
|
|
189
|
+
videos,
|
|
190
|
+
news,
|
|
82
191
|
onSearchResults: createOnSearchResults({
|
|
83
192
|
runnableConfig,
|
|
84
193
|
onSearchResults: _onSearchResults,
|
|
@@ -125,16 +234,17 @@ Use anchor marker(s) immediately after the statement:
|
|
|
125
234
|
* @returns A DynamicStructuredTool with a schema that depends on the searchProvider
|
|
126
235
|
*/
|
|
127
236
|
const createSearchTool = (config = {}) => {
|
|
128
|
-
const { searchProvider = 'serper', serperApiKey, searxngInstanceUrl, searxngApiKey, rerankerType = 'cohere', topResults = 5, strategies = ['no_extraction'], filterContent = true, firecrawlApiKey, firecrawlApiUrl, firecrawlFormats = ['markdown', 'html'], jinaApiKey, cohereApiKey, onSearchResults: _onSearchResults, onGetHighlights, } = config;
|
|
129
|
-
const
|
|
237
|
+
const { searchProvider = 'serper', serperApiKey, searxngInstanceUrl, searxngApiKey, rerankerType = 'cohere', topResults = 5, strategies = ['no_extraction'], filterContent = true, safeSearch = 1, firecrawlApiKey, firecrawlApiUrl, firecrawlFormats = ['markdown', 'html'], jinaApiKey, cohereApiKey, onSearchResults: _onSearchResults, onGetHighlights, } = config;
|
|
238
|
+
const logger = config.logger || createDefaultLogger();
|
|
130
239
|
const schemaObject = {
|
|
131
240
|
query: querySchema,
|
|
241
|
+
date: dateSchema,
|
|
242
|
+
images: imagesSchema,
|
|
243
|
+
videos: videosSchema,
|
|
244
|
+
news: newsSchema,
|
|
132
245
|
};
|
|
133
246
|
if (searchProvider === 'serper') {
|
|
134
|
-
schemaObject.country =
|
|
135
|
-
.string()
|
|
136
|
-
.optional()
|
|
137
|
-
.describe(DEFAULT_COUNTRY_DESCRIPTION);
|
|
247
|
+
schemaObject.country = countrySchema;
|
|
138
248
|
}
|
|
139
249
|
const toolSchema = z.object(schemaObject);
|
|
140
250
|
const searchAPI = createSearchAPI({
|
|
@@ -152,17 +262,22 @@ const createSearchTool = (config = {}) => {
|
|
|
152
262
|
rerankerType,
|
|
153
263
|
jinaApiKey,
|
|
154
264
|
cohereApiKey,
|
|
265
|
+
logger,
|
|
155
266
|
});
|
|
156
267
|
if (!selectedReranker) {
|
|
157
|
-
|
|
268
|
+
logger.warn('No reranker selected. Using default ranking.');
|
|
158
269
|
}
|
|
159
270
|
const sourceProcessor = createSourceProcessor({
|
|
160
271
|
reranker: selectedReranker,
|
|
161
|
-
topResults
|
|
272
|
+
topResults,
|
|
273
|
+
logger,
|
|
274
|
+
}, firecrawlScraper);
|
|
162
275
|
const search = createSearchProcessor({
|
|
163
276
|
searchAPI,
|
|
277
|
+
safeSearch,
|
|
164
278
|
sourceProcessor,
|
|
165
279
|
onGetHighlights,
|
|
280
|
+
logger,
|
|
166
281
|
});
|
|
167
282
|
return createTool({
|
|
168
283
|
search,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.mjs","sources":["../../../../src/tools/search/tool.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { z } from 'zod';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport type * as t from './types';\nimport { createSearchAPI, createSourceProcessor } from './search';\nimport { createFirecrawlScraper } from './firecrawl';\nimport { expandHighlights } from './highlights';\nimport { formatResultsForLLM } from './format';\nimport { createReranker } from './rerankers';\nimport { Constants } from '@/common';\n\nconst DEFAULT_QUERY_DESCRIPTION = `\nGUIDELINES:\n- Start broad, then narrow: Begin with key concepts, then refine with specifics\n- Think like sources: Use terminology experts would use in the field\n- Consider perspective: Frame queries from different viewpoints for better results\n- Quality over quantity: A precise 3-4 word query often beats lengthy sentences\n\nTECHNIQUES (combine for power searches):\n- EXACT PHRASES: Use quotes (\"climate change report\")\n- EXCLUDE TERMS: Use minus to remove unwanted results (-wikipedia)\n- SITE-SPECIFIC: Restrict to websites (site:edu research)\n- FILETYPE: Find specific documents (filetype:pdf study)\n- OR OPERATOR: Find alternatives (electric OR hybrid cars)\n- DATE RANGE: Recent information (data after:2020)\n- WILDCARDS: Use * for unknown terms (how to * bread)\n- SPECIFIC QUESTIONS: Use who/what/when/where/why/how\n- DOMAIN TERMS: Include technical terminology for specialized topics\n- CONCISE TERMS: Prioritize keywords over sentences\n`.trim();\n\nconst DEFAULT_COUNTRY_DESCRIPTION = `Country code to localize search results.\nUse standard 2-letter country codes: \"us\", \"uk\", \"ca\", \"de\", \"fr\", \"jp\", \"br\", etc.\nProvide this when the search should return results specific to a particular country.\nExamples:\n- \"us\" for United States (default)\n- \"de\" for Germany\n- \"in\" for India\n`.trim();\n\nfunction createSearchProcessor({\n searchAPI,\n sourceProcessor,\n onGetHighlights,\n}: {\n searchAPI: ReturnType<typeof createSearchAPI>;\n sourceProcessor: ReturnType<typeof createSourceProcessor>;\n onGetHighlights: t.SearchToolConfig['onGetHighlights'];\n}) {\n return async function ({\n query,\n country,\n proMode = true,\n maxSources = 5,\n onSearchResults,\n }: {\n query: string;\n country?: string;\n maxSources?: number;\n proMode?: boolean;\n onSearchResults: t.SearchToolConfig['onSearchResults'];\n }): Promise<t.SearchResultData> {\n try {\n const result = await searchAPI.getSources({ query, country });\n onSearchResults?.(result);\n\n if (!result.success) {\n throw new Error(result.error ?? 'Search failed');\n }\n\n const processedSources = await sourceProcessor.processSources({\n query,\n result,\n proMode,\n onGetHighlights,\n numElements: maxSources,\n });\n return expandHighlights(processedSources);\n } catch (error) {\n console.error('Error in search:', error);\n return {\n organic: [],\n topStories: [],\n images: [],\n relatedSearches: [],\n error: error instanceof Error ? error.message : String(error),\n };\n }\n };\n}\n\nfunction createOnSearchResults({\n runnableConfig,\n onSearchResults,\n}: {\n runnableConfig: RunnableConfig;\n onSearchResults: t.SearchToolConfig['onSearchResults'];\n}) {\n return function (results: t.SearchResult): void {\n if (!onSearchResults) {\n return;\n }\n onSearchResults(results, runnableConfig);\n };\n}\n\nfunction createTool({\n schema,\n search,\n onSearchResults: _onSearchResults,\n}: {\n schema: t.SearchToolSchema;\n search: ReturnType<typeof createSearchProcessor>;\n onSearchResults: t.SearchToolConfig['onSearchResults'];\n}): DynamicStructuredTool<typeof schema> {\n return tool<typeof schema>(\n async (params, runnableConfig) => {\n const { query, country: _c } = params;\n const country = typeof _c === 'string' && _c ? _c : undefined;\n const searchResult = await search({\n query,\n country,\n onSearchResults: createOnSearchResults({\n runnableConfig,\n onSearchResults: _onSearchResults,\n }),\n });\n const turn = runnableConfig.toolCall?.turn ?? 0;\n const { output, references } = formatResultsForLLM(turn, searchResult);\n const data: t.SearchResultData = { turn, ...searchResult, references };\n return [output, { [Constants.WEB_SEARCH]: data }];\n },\n {\n name: Constants.WEB_SEARCH,\n description: `Real-time search. Results have required citation anchors.\n\nNote: Use ONCE per reply unless instructed otherwise.\n\nAnchors:\n- \\\\ue202turnXtypeY\n- X = turn idx, type = 'search' | 'news' | 'image' | 'ref', Y = item idx\n\nSpecial Markers:\n- \\\\ue203...\\\\ue204 — highlight start/end of cited text (for Standalone or Group citations)\n- \\\\ue200...\\\\ue201 — group block (e.g. \\\\ue200\\\\ue202turn0search1\\\\ue202turn0news2\\\\ue201)\n\n**CITE EVERY NON-OBVIOUS FACT/QUOTE:**\nUse anchor marker(s) immediately after the statement:\n- Standalone: \"Pure functions produce same output. \\\\ue202turn0search0\"\n- Standalone (multiple): \"Today's News \\\\ue202turn0search0\\\\ue202turn0news0\"\n- Highlight: \"\\\\ue203Highlight text.\\\\ue204\\\\ue202turn0news1\"\n- Group: \"Sources. \\\\ue200\\\\ue202turn0search0\\\\ue202turn0news1\\\\ue201\"\n- Group Highlight: \"\\\\ue203Highlight for group.\\\\ue204 \\\\ue200\\\\ue202turn0search0\\\\ue202turn0news1\\\\ue201\"\n- Image: \"See photo \\\\ue202turn0image0.\"\n\n**NEVER use markdown links, [1], or footnotes. CITE ONLY with anchors provided.**\n`.trim(),\n schema: schema,\n responseFormat: Constants.CONTENT_AND_ARTIFACT,\n }\n );\n}\n\n/**\n * Creates a search tool with a schema that dynamically includes the country field\n * only when the searchProvider is 'serper'.\n *\n * @param config - The search tool configuration\n * @returns A DynamicStructuredTool with a schema that depends on the searchProvider\n */\nexport const createSearchTool = (\n config: t.SearchToolConfig = {}\n): DynamicStructuredTool<typeof toolSchema> => {\n const {\n searchProvider = 'serper',\n serperApiKey,\n searxngInstanceUrl,\n searxngApiKey,\n rerankerType = 'cohere',\n topResults = 5,\n strategies = ['no_extraction'],\n filterContent = true,\n firecrawlApiKey,\n firecrawlApiUrl,\n firecrawlFormats = ['markdown', 'html'],\n jinaApiKey,\n cohereApiKey,\n onSearchResults: _onSearchResults,\n onGetHighlights,\n } = config;\n\n const querySchema = z.string().describe(DEFAULT_QUERY_DESCRIPTION);\n const schemaObject: {\n query: z.ZodString;\n country?: z.ZodOptional<z.ZodString>;\n } = {\n query: querySchema,\n };\n\n if (searchProvider === 'serper') {\n schemaObject.country = z\n .string()\n .optional()\n .describe(DEFAULT_COUNTRY_DESCRIPTION);\n }\n\n const toolSchema = z.object(schemaObject);\n\n const searchAPI = createSearchAPI({\n searchProvider,\n serperApiKey,\n searxngInstanceUrl,\n searxngApiKey,\n });\n\n const firecrawlScraper = createFirecrawlScraper({\n apiKey: firecrawlApiKey ?? process.env.FIRECRAWL_API_KEY,\n apiUrl: firecrawlApiUrl,\n formats: firecrawlFormats,\n });\n\n const selectedReranker = createReranker({\n rerankerType,\n jinaApiKey,\n cohereApiKey,\n });\n\n if (!selectedReranker) {\n console.warn('No reranker selected. Using default ranking.');\n }\n\n const sourceProcessor = createSourceProcessor(\n {\n reranker: selectedReranker,\n topResults,\n strategies,\n filterContent,\n },\n firecrawlScraper\n );\n\n const search = createSearchProcessor({\n searchAPI,\n sourceProcessor,\n onGetHighlights,\n });\n\n return createTool({\n search,\n schema: toolSchema,\n onSearchResults: _onSearchResults,\n });\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tool.mjs","sources":["../../../../src/tools/search/tool.ts"],"sourcesContent":["import { z } from 'zod';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport type * as t from './types';\nimport {\n DATE_RANGE,\n querySchema,\n dateSchema,\n countrySchema,\n imagesSchema,\n videosSchema,\n newsSchema,\n} from './schema';\nimport { createSearchAPI, createSourceProcessor } from './search';\nimport { createFirecrawlScraper } from './firecrawl';\nimport { expandHighlights } from './highlights';\nimport { formatResultsForLLM } from './format';\nimport { createDefaultLogger } from './utils';\nimport { createReranker } from './rerankers';\nimport { Constants } from '@/common';\n\n/**\n * Executes parallel searches and merges the results\n */\nasync function executeParallelSearches({\n searchAPI,\n query,\n date,\n country,\n safeSearch,\n images,\n videos,\n news,\n logger,\n}: {\n searchAPI: ReturnType<typeof createSearchAPI>;\n query: string;\n date?: DATE_RANGE;\n country?: string;\n safeSearch: t.SearchToolConfig['safeSearch'];\n images: boolean;\n videos: boolean;\n news: boolean;\n logger: t.Logger;\n}): Promise<t.SearchResult> {\n // Prepare all search tasks to run in parallel\n const searchTasks: Promise<t.SearchResult>[] = [\n // Main search\n searchAPI.getSources({\n query,\n date,\n country,\n safeSearch,\n }),\n ];\n\n if (images) {\n searchTasks.push(\n searchAPI\n .getSources({\n query,\n date,\n country,\n safeSearch,\n type: 'images',\n })\n .catch((error) => {\n logger.error('Error fetching images:', error);\n return {\n success: false,\n error: `Images search failed: ${error instanceof Error ? error.message : String(error)}`,\n };\n })\n );\n }\n if (videos) {\n searchTasks.push(\n searchAPI\n .getSources({\n query,\n date,\n country,\n safeSearch,\n type: 'videos',\n })\n .catch((error) => {\n logger.error('Error fetching videos:', error);\n return {\n success: false,\n error: `Videos search failed: ${error instanceof Error ? error.message : String(error)}`,\n };\n })\n );\n }\n if (news) {\n searchTasks.push(\n searchAPI\n .getSources({\n query,\n date,\n country,\n safeSearch,\n type: 'news',\n })\n .catch((error) => {\n logger.error('Error fetching news:', error);\n return {\n success: false,\n error: `News search failed: ${error instanceof Error ? error.message : String(error)}`,\n };\n })\n );\n }\n\n // Run all searches in parallel\n const results = await Promise.all(searchTasks);\n\n // Get the main search result (first result)\n const mainResult = results[0];\n if (!mainResult.success) {\n throw new Error(mainResult.error ?? 'Search failed');\n }\n\n // Merge additional results with the main results\n const mergedResults = { ...mainResult.data };\n\n // Convert existing news to topStories if present\n if (mergedResults.news !== undefined && mergedResults.news.length > 0) {\n const existingNewsAsTopStories = mergedResults.news\n .filter((newsItem) => newsItem.link !== undefined && newsItem.link !== '')\n .map((newsItem) => ({\n title: newsItem.title ?? '',\n link: newsItem.link ?? '',\n source: newsItem.source ?? '',\n date: newsItem.date ?? '',\n imageUrl: newsItem.imageUrl ?? '',\n processed: false,\n }));\n mergedResults.topStories = [\n ...(mergedResults.topStories ?? []),\n ...existingNewsAsTopStories,\n ];\n delete mergedResults.news;\n }\n\n results.slice(1).forEach((result) => {\n if (result.success && result.data !== undefined) {\n if (result.data.images !== undefined && result.data.images.length > 0) {\n mergedResults.images = [\n ...(mergedResults.images ?? []),\n ...result.data.images,\n ];\n }\n if (result.data.videos !== undefined && result.data.videos.length > 0) {\n mergedResults.videos = [\n ...(mergedResults.videos ?? []),\n ...result.data.videos,\n ];\n }\n if (result.data.news !== undefined && result.data.news.length > 0) {\n const newsAsTopStories = result.data.news.map((newsItem) => ({\n ...newsItem,\n link: newsItem.link ?? '',\n }));\n mergedResults.topStories = [\n ...(mergedResults.topStories ?? []),\n ...newsAsTopStories,\n ];\n }\n }\n });\n\n return { success: true, data: mergedResults };\n}\n\nfunction createSearchProcessor({\n searchAPI,\n safeSearch,\n sourceProcessor,\n onGetHighlights,\n logger,\n}: {\n safeSearch: t.SearchToolConfig['safeSearch'];\n searchAPI: ReturnType<typeof createSearchAPI>;\n sourceProcessor: ReturnType<typeof createSourceProcessor>;\n onGetHighlights: t.SearchToolConfig['onGetHighlights'];\n logger: t.Logger;\n}) {\n return async function ({\n query,\n date,\n country,\n proMode = true,\n maxSources = 5,\n onSearchResults,\n images = false,\n videos = false,\n news = false,\n }: {\n query: string;\n country?: string;\n date?: DATE_RANGE;\n proMode?: boolean;\n maxSources?: number;\n onSearchResults: t.SearchToolConfig['onSearchResults'];\n images?: boolean;\n videos?: boolean;\n news?: boolean;\n }): Promise<t.SearchResultData> {\n try {\n // Execute parallel searches and merge results\n const searchResult = await executeParallelSearches({\n searchAPI,\n query,\n date,\n country,\n safeSearch,\n images,\n videos,\n news,\n logger,\n });\n\n onSearchResults?.(searchResult);\n\n const processedSources = await sourceProcessor.processSources({\n query,\n news,\n result: searchResult,\n proMode,\n onGetHighlights,\n numElements: maxSources,\n });\n\n return expandHighlights(processedSources);\n } catch (error) {\n logger.error('Error in search:', error);\n return {\n organic: [],\n topStories: [],\n images: [],\n videos: [],\n news: [],\n relatedSearches: [],\n error: error instanceof Error ? error.message : String(error),\n };\n }\n };\n}\n\nfunction createOnSearchResults({\n runnableConfig,\n onSearchResults,\n}: {\n runnableConfig: RunnableConfig;\n onSearchResults: t.SearchToolConfig['onSearchResults'];\n}) {\n return function (results: t.SearchResult): void {\n if (!onSearchResults) {\n return;\n }\n onSearchResults(results, runnableConfig);\n };\n}\n\nfunction createTool({\n schema,\n search,\n onSearchResults: _onSearchResults,\n}: {\n schema: t.SearchToolSchema;\n search: ReturnType<typeof createSearchProcessor>;\n onSearchResults: t.SearchToolConfig['onSearchResults'];\n}): DynamicStructuredTool<typeof schema> {\n return tool<typeof schema>(\n async (params, runnableConfig) => {\n const { query, date, country: _c, images, videos, news } = params;\n const country = typeof _c === 'string' && _c ? _c : undefined;\n const searchResult = await search({\n query,\n date,\n country,\n images,\n videos,\n news,\n onSearchResults: createOnSearchResults({\n runnableConfig,\n onSearchResults: _onSearchResults,\n }),\n });\n const turn = runnableConfig.toolCall?.turn ?? 0;\n const { output, references } = formatResultsForLLM(turn, searchResult);\n const data: t.SearchResultData = { turn, ...searchResult, references };\n return [output, { [Constants.WEB_SEARCH]: data }];\n },\n {\n name: Constants.WEB_SEARCH,\n description: `Real-time search. Results have required citation anchors.\n\nNote: Use ONCE per reply unless instructed otherwise.\n\nAnchors:\n- \\\\ue202turnXtypeY\n- X = turn idx, type = 'search' | 'news' | 'image' | 'ref', Y = item idx\n\nSpecial Markers:\n- \\\\ue203...\\\\ue204 — highlight start/end of cited text (for Standalone or Group citations)\n- \\\\ue200...\\\\ue201 — group block (e.g. \\\\ue200\\\\ue202turn0search1\\\\ue202turn0news2\\\\ue201)\n\n**CITE EVERY NON-OBVIOUS FACT/QUOTE:**\nUse anchor marker(s) immediately after the statement:\n- Standalone: \"Pure functions produce same output. \\\\ue202turn0search0\"\n- Standalone (multiple): \"Today's News \\\\ue202turn0search0\\\\ue202turn0news0\"\n- Highlight: \"\\\\ue203Highlight text.\\\\ue204\\\\ue202turn0news1\"\n- Group: \"Sources. \\\\ue200\\\\ue202turn0search0\\\\ue202turn0news1\\\\ue201\"\n- Group Highlight: \"\\\\ue203Highlight for group.\\\\ue204 \\\\ue200\\\\ue202turn0search0\\\\ue202turn0news1\\\\ue201\"\n- Image: \"See photo \\\\ue202turn0image0.\"\n\n**NEVER use markdown links, [1], or footnotes. CITE ONLY with anchors provided.**\n`.trim(),\n schema: schema,\n responseFormat: Constants.CONTENT_AND_ARTIFACT,\n }\n );\n}\n\n/**\n * Creates a search tool with a schema that dynamically includes the country field\n * only when the searchProvider is 'serper'.\n *\n * @param config - The search tool configuration\n * @returns A DynamicStructuredTool with a schema that depends on the searchProvider\n */\nexport const createSearchTool = (\n config: t.SearchToolConfig = {}\n): DynamicStructuredTool<typeof toolSchema> => {\n const {\n searchProvider = 'serper',\n serperApiKey,\n searxngInstanceUrl,\n searxngApiKey,\n rerankerType = 'cohere',\n topResults = 5,\n strategies = ['no_extraction'],\n filterContent = true,\n safeSearch = 1,\n firecrawlApiKey,\n firecrawlApiUrl,\n firecrawlFormats = ['markdown', 'html'],\n jinaApiKey,\n cohereApiKey,\n onSearchResults: _onSearchResults,\n onGetHighlights,\n } = config;\n\n const logger = config.logger || createDefaultLogger();\n\n const schemaObject: {\n query: z.ZodString;\n date: z.ZodOptional<z.ZodNativeEnum<typeof DATE_RANGE>>;\n country?: z.ZodOptional<z.ZodString>;\n images: z.ZodOptional<z.ZodBoolean>;\n videos: z.ZodOptional<z.ZodBoolean>;\n news: z.ZodOptional<z.ZodBoolean>;\n } = {\n query: querySchema,\n date: dateSchema,\n images: imagesSchema,\n videos: videosSchema,\n news: newsSchema,\n };\n\n if (searchProvider === 'serper') {\n schemaObject.country = countrySchema;\n }\n\n const toolSchema = z.object(schemaObject);\n\n const searchAPI = createSearchAPI({\n searchProvider,\n serperApiKey,\n searxngInstanceUrl,\n searxngApiKey,\n });\n\n const firecrawlScraper = createFirecrawlScraper({\n apiKey: firecrawlApiKey ?? process.env.FIRECRAWL_API_KEY,\n apiUrl: firecrawlApiUrl,\n formats: firecrawlFormats,\n });\n\n const selectedReranker = createReranker({\n rerankerType,\n jinaApiKey,\n cohereApiKey,\n logger,\n });\n\n if (!selectedReranker) {\n logger.warn('No reranker selected. Using default ranking.');\n }\n\n const sourceProcessor = createSourceProcessor(\n {\n reranker: selectedReranker,\n topResults,\n strategies,\n filterContent,\n logger,\n },\n firecrawlScraper\n );\n\n const search = createSearchProcessor({\n searchAPI,\n safeSearch,\n sourceProcessor,\n onGetHighlights,\n logger,\n });\n\n return createTool({\n search,\n schema: toolSchema,\n onSearchResults: _onSearchResults,\n });\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
/**
|
|
3
|
+
* Singleton instance of the default logger
|
|
4
|
+
*/
|
|
5
|
+
let defaultLoggerInstance = null;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a default logger that maps to console methods
|
|
8
|
+
* Uses a singleton pattern to avoid creating multiple instances
|
|
9
|
+
* @returns A default logger that implements the Logger interface
|
|
10
|
+
*/
|
|
11
|
+
const createDefaultLogger = () => {
|
|
12
|
+
if (!defaultLoggerInstance) {
|
|
13
|
+
defaultLoggerInstance = {
|
|
14
|
+
error: console.error,
|
|
15
|
+
warn: console.warn,
|
|
16
|
+
info: console.info,
|
|
17
|
+
debug: console.debug,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return defaultLoggerInstance;
|
|
21
|
+
};
|
|
22
|
+
const fileExtRegex = /\.(pdf|jpe?g|png|gif|svg|webp|bmp|ico|tiff?|avif|heic|doc[xm]?|xls[xm]?|ppt[xm]?|zip|rar|mp[34]|mov|avi|wav)$/i;
|
|
23
|
+
const getDomainName = (link, metadata, logger) => {
|
|
2
24
|
try {
|
|
3
25
|
const url = metadata?.sourceURL ?? metadata?.url ?? (link || '');
|
|
4
26
|
const domain = new URL(url).hostname.replace(/^www\./, '');
|
|
@@ -8,13 +30,18 @@ const getDomainName = (link, metadata) => {
|
|
|
8
30
|
}
|
|
9
31
|
catch (e) {
|
|
10
32
|
// URL parsing failed
|
|
11
|
-
|
|
33
|
+
if (logger) {
|
|
34
|
+
logger.error('Error parsing URL:', e);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
console.error('Error parsing URL:', e);
|
|
38
|
+
}
|
|
12
39
|
}
|
|
13
40
|
return;
|
|
14
41
|
};
|
|
15
|
-
function getAttribution(link, metadata) {
|
|
42
|
+
function getAttribution(link, metadata, logger) {
|
|
16
43
|
if (!metadata)
|
|
17
|
-
return getDomainName(link, metadata);
|
|
44
|
+
return getDomainName(link, metadata, logger);
|
|
18
45
|
const twitterSite = metadata['twitter:site'];
|
|
19
46
|
const twitterSiteFormatted = typeof twitterSite === 'string' ? twitterSite.replace(/^@/, '') : undefined;
|
|
20
47
|
const possibleAttributions = [
|
|
@@ -27,8 +54,8 @@ function getAttribution(link, metadata) {
|
|
|
27
54
|
if (attribution != null) {
|
|
28
55
|
return attribution;
|
|
29
56
|
}
|
|
30
|
-
return getDomainName(link, metadata);
|
|
57
|
+
return getDomainName(link, metadata, logger);
|
|
31
58
|
}
|
|
32
59
|
|
|
33
|
-
export { getAttribution, getDomainName };
|
|
60
|
+
export { createDefaultLogger, fileExtRegex, getAttribution, getDomainName };
|
|
34
61
|
//# sourceMappingURL=utils.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","sources":["../../../../src/tools/search/utils.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport type * as t from './types';\n\nexport const getDomainName = (\n link: string,\n metadata?: t.ScrapeMetadata\n): string | undefined => {\n try {\n const url = metadata?.sourceURL ?? metadata?.url ?? (link || '');\n const domain = new URL(url).hostname.replace(/^www\\./, '');\n if (domain) {\n return domain;\n }\n } catch (e) {\n // URL parsing failed\n console.error('Error parsing URL:', e);\n }\n\n return;\n};\n\nexport function getAttribution(\n link: string,\n metadata?: t.ScrapeMetadata\n): string | undefined {\n if (!metadata) return getDomainName(link, metadata);\n\n const twitterSite = metadata['twitter:site'];\n const twitterSiteFormatted =\n typeof twitterSite === 'string' ? twitterSite.replace(/^@/, '') : undefined;\n\n const possibleAttributions = [\n metadata.ogSiteName,\n metadata['og:site_name'],\n metadata.title?.split('|').pop()?.trim(),\n twitterSiteFormatted,\n ];\n\n const attribution = possibleAttributions.find(\n (attr) => attr != null && typeof attr === 'string' && attr.trim() !== ''\n );\n if (attribution != null) {\n return attribution;\n }\n\n return getDomainName(link, metadata);\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.mjs","sources":["../../../../src/tools/search/utils.ts"],"sourcesContent":["/* eslint-disable no-console */\n\nimport type * as t from './types';\n\n/**\n * Singleton instance of the default logger\n */\nlet defaultLoggerInstance: t.Logger | null = null;\n\n/**\n * Creates a default logger that maps to console methods\n * Uses a singleton pattern to avoid creating multiple instances\n * @returns A default logger that implements the Logger interface\n */\nexport const createDefaultLogger = (): t.Logger => {\n if (!defaultLoggerInstance) {\n defaultLoggerInstance = {\n error: console.error,\n warn: console.warn,\n info: console.info,\n debug: console.debug,\n } as t.Logger;\n }\n return defaultLoggerInstance;\n};\n\nexport const fileExtRegex =\n /\\.(pdf|jpe?g|png|gif|svg|webp|bmp|ico|tiff?|avif|heic|doc[xm]?|xls[xm]?|ppt[xm]?|zip|rar|mp[34]|mov|avi|wav)$/i;\n\nexport const getDomainName = (\n link: string,\n metadata?: t.ScrapeMetadata,\n logger?: t.Logger\n): string | undefined => {\n try {\n const url = metadata?.sourceURL ?? metadata?.url ?? (link || '');\n const domain = new URL(url).hostname.replace(/^www\\./, '');\n if (domain) {\n return domain;\n }\n } catch (e) {\n // URL parsing failed\n if (logger) {\n logger.error('Error parsing URL:', e);\n } else {\n console.error('Error parsing URL:', e);\n }\n }\n\n return;\n};\n\nexport function getAttribution(\n link: string,\n metadata?: t.ScrapeMetadata,\n logger?: t.Logger\n): string | undefined {\n if (!metadata) return getDomainName(link, metadata, logger);\n\n const twitterSite = metadata['twitter:site'];\n const twitterSiteFormatted =\n typeof twitterSite === 'string' ? twitterSite.replace(/^@/, '') : undefined;\n\n const possibleAttributions = [\n metadata.ogSiteName,\n metadata['og:site_name'],\n metadata.title?.split('|').pop()?.trim(),\n twitterSiteFormatted,\n ];\n\n const attribution = possibleAttributions.find(\n (attr) => attr != null && typeof attr === 'string' && attr.trim() !== ''\n );\n if (attribution != null) {\n return attribution;\n }\n\n return getDomainName(link, metadata, logger);\n}\n"],"names":[],"mappings":"AAAA;AAIA;;AAEG;AACH,IAAI,qBAAqB,GAAoB,IAAI;AAEjD;;;;AAIG;AACI,MAAM,mBAAmB,GAAG,MAAe;IAChD,IAAI,CAAC,qBAAqB,EAAE;AAC1B,QAAA,qBAAqB,GAAG;YACtB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK;SACT;;AAEf,IAAA,OAAO,qBAAqB;AAC9B;AAEO,MAAM,YAAY,GACvB;AAEW,MAAA,aAAa,GAAG,CAC3B,IAAY,EACZ,QAA2B,EAC3B,MAAiB,KACK;AACtB,IAAA,IAAI;AACF,QAAA,MAAM,GAAG,GAAG,QAAQ,EAAE,SAAS,IAAI,QAAQ,EAAE,GAAG,KAAK,IAAI,IAAI,EAAE,CAAC;AAChE,QAAA,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC1D,IAAI,MAAM,EAAE;AACV,YAAA,OAAO,MAAM;;;IAEf,OAAO,CAAC,EAAE;;QAEV,IAAI,MAAM,EAAE;AACV,YAAA,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC,CAAC;;aAChC;AACL,YAAA,OAAO,CAAC,KAAK,CAAC,oBAAoB,EAAE,CAAC,CAAC;;;IAI1C;AACF;SAEgB,cAAc,CAC5B,IAAY,EACZ,QAA2B,EAC3B,MAAiB,EAAA;AAEjB,IAAA,IAAI,CAAC,QAAQ;QAAE,OAAO,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC;AAE3D,IAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC;IAC5C,MAAM,oBAAoB,GACxB,OAAO,WAAW,KAAK,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,SAAS;AAE7E,IAAA,MAAM,oBAAoB,GAAG;AAC3B,QAAA,QAAQ,CAAC,UAAU;QACnB,QAAQ,CAAC,cAAc,CAAC;AACxB,QAAA,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE;QACxC,oBAAoB;KACrB;IAED,MAAM,WAAW,GAAG,oBAAoB,CAAC,IAAI,CAC3C,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CACzE;AACD,IAAA,IAAI,WAAW,IAAI,IAAI,EAAE;AACvB,QAAA,OAAO,WAAW;;IAGpB,OAAO,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC;AAC9C;;;;"}
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
import type * as t from './types';
|
|
2
2
|
export declare abstract class BaseReranker {
|
|
3
3
|
protected apiKey: string | undefined;
|
|
4
|
-
|
|
4
|
+
protected logger: t.Logger;
|
|
5
|
+
constructor(logger?: t.Logger);
|
|
5
6
|
abstract rerank(query: string, documents: string[], topK?: number): Promise<t.Highlight[]>;
|
|
6
7
|
protected getDefaultRanking(documents: string[], topK: number): t.Highlight[];
|
|
7
8
|
protected logDocumentSamples(documents: string[]): void;
|
|
8
9
|
}
|
|
9
10
|
export declare class JinaReranker extends BaseReranker {
|
|
10
|
-
constructor({ apiKey }: {
|
|
11
|
+
constructor({ apiKey, logger, }: {
|
|
11
12
|
apiKey?: string;
|
|
13
|
+
logger?: t.Logger;
|
|
12
14
|
});
|
|
13
15
|
rerank(query: string, documents: string[], topK?: number): Promise<t.Highlight[]>;
|
|
14
16
|
}
|
|
15
17
|
export declare class CohereReranker extends BaseReranker {
|
|
16
|
-
constructor({ apiKey }: {
|
|
18
|
+
constructor({ apiKey, logger, }: {
|
|
17
19
|
apiKey?: string;
|
|
20
|
+
logger?: t.Logger;
|
|
18
21
|
});
|
|
19
22
|
rerank(query: string, documents: string[], topK?: number): Promise<t.Highlight[]>;
|
|
20
23
|
}
|
|
21
24
|
export declare class InfinityReranker extends BaseReranker {
|
|
22
|
-
constructor();
|
|
25
|
+
constructor(logger?: t.Logger);
|
|
23
26
|
rerank(query: string, documents: string[], topK?: number): Promise<t.Highlight[]>;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
@@ -29,4 +32,5 @@ export declare const createReranker: (config: {
|
|
|
29
32
|
rerankerType: t.RerankerType;
|
|
30
33
|
jinaApiKey?: string;
|
|
31
34
|
cohereApiKey?: string;
|
|
35
|
+
logger?: t.Logger;
|
|
32
36
|
}) => BaseReranker | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare enum DATE_RANGE {
|
|
3
|
+
PAST_HOUR = "h",
|
|
4
|
+
PAST_24_HOURS = "d",
|
|
5
|
+
PAST_WEEK = "w",
|
|
6
|
+
PAST_MONTH = "m",
|
|
7
|
+
PAST_YEAR = "y"
|
|
8
|
+
}
|
|
9
|
+
export declare const DEFAULT_QUERY_DESCRIPTION: string;
|
|
10
|
+
export declare const DEFAULT_COUNTRY_DESCRIPTION: string;
|
|
11
|
+
export declare const querySchema: z.ZodString;
|
|
12
|
+
export declare const dateSchema: z.ZodOptional<z.ZodNativeEnum<typeof DATE_RANGE>>;
|
|
13
|
+
export declare const countrySchema: z.ZodOptional<z.ZodString>;
|
|
14
|
+
export declare const imagesSchema: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
export declare const videosSchema: z.ZodOptional<z.ZodBoolean>;
|
|
16
|
+
export declare const newsSchema: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
3
3
|
import type * as t from './types';
|
|
4
|
+
import { DATE_RANGE } from './schema';
|
|
4
5
|
/**
|
|
5
6
|
* Creates a search tool with a schema that dynamically includes the country field
|
|
6
7
|
* only when the searchProvider is 'serper'.
|
|
@@ -10,11 +11,23 @@ import type * as t from './types';
|
|
|
10
11
|
*/
|
|
11
12
|
export declare const createSearchTool: (config?: t.SearchToolConfig) => DynamicStructuredTool<z.ZodObject<{
|
|
12
13
|
query: z.ZodString;
|
|
14
|
+
date: z.ZodOptional<z.ZodNativeEnum<typeof DATE_RANGE>>;
|
|
13
15
|
country?: z.ZodOptional<z.ZodString>;
|
|
16
|
+
images: z.ZodOptional<z.ZodBoolean>;
|
|
17
|
+
videos: z.ZodOptional<z.ZodBoolean>;
|
|
18
|
+
news: z.ZodOptional<z.ZodBoolean>;
|
|
14
19
|
}, "strip", z.ZodTypeAny, {
|
|
15
20
|
query: string;
|
|
21
|
+
date?: DATE_RANGE | undefined;
|
|
22
|
+
images?: boolean | undefined;
|
|
23
|
+
videos?: boolean | undefined;
|
|
24
|
+
news?: boolean | undefined;
|
|
16
25
|
country?: unknown;
|
|
17
26
|
}, {
|
|
18
27
|
query: string;
|
|
28
|
+
date?: DATE_RANGE | undefined;
|
|
29
|
+
images?: boolean | undefined;
|
|
30
|
+
videos?: boolean | undefined;
|
|
31
|
+
news?: boolean | undefined;
|
|
19
32
|
country?: unknown;
|
|
20
33
|
}>>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import type { Logger as WinstonLogger } from 'winston';
|
|
2
3
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
3
4
|
import type { BaseReranker } from './rerankers';
|
|
5
|
+
import { DATE_RANGE } from './schema';
|
|
4
6
|
export type SearchProvider = 'serper' | 'searxng';
|
|
5
7
|
export type RerankerType = 'infinity' | 'jina' | 'cohere' | 'none';
|
|
6
8
|
export interface Highlight {
|
|
@@ -13,12 +15,14 @@ export type ProcessedSource = {
|
|
|
13
15
|
attribution?: string;
|
|
14
16
|
references?: References;
|
|
15
17
|
highlights?: Highlight[];
|
|
18
|
+
processed?: boolean;
|
|
16
19
|
};
|
|
17
20
|
export type ProcessedOrganic = OrganicResult & ProcessedSource;
|
|
18
21
|
export type ProcessedTopStory = TopStoryResult & ProcessedSource;
|
|
19
22
|
export type ValidSource = ProcessedOrganic | ProcessedTopStory;
|
|
20
23
|
export type ResultReference = {
|
|
21
24
|
link: string;
|
|
25
|
+
type: 'link' | 'image' | 'video';
|
|
22
26
|
title?: string;
|
|
23
27
|
attribution?: string;
|
|
24
28
|
};
|
|
@@ -76,6 +80,7 @@ export interface ProcessSourcesConfig {
|
|
|
76
80
|
strategies?: string[];
|
|
77
81
|
filterContent?: boolean;
|
|
78
82
|
reranker?: BaseReranker;
|
|
83
|
+
logger?: Logger;
|
|
79
84
|
}
|
|
80
85
|
export interface FirecrawlConfig {
|
|
81
86
|
firecrawlApiKey?: string;
|
|
@@ -119,7 +124,11 @@ export interface CohereRerankerResponse {
|
|
|
119
124
|
};
|
|
120
125
|
};
|
|
121
126
|
}
|
|
127
|
+
export type SafeSearchLevel = 0 | 1 | 2;
|
|
128
|
+
export type Logger = WinstonLogger;
|
|
122
129
|
export interface SearchToolConfig extends SearchConfig, ProcessSourcesConfig, FirecrawlConfig {
|
|
130
|
+
logger?: Logger;
|
|
131
|
+
safeSearch?: SafeSearchLevel;
|
|
123
132
|
jinaApiKey?: string;
|
|
124
133
|
cohereApiKey?: string;
|
|
125
134
|
rerankerType?: RerankerType;
|
|
@@ -215,11 +224,18 @@ export interface FirecrawlScraperConfig {
|
|
|
215
224
|
apiUrl?: string;
|
|
216
225
|
formats?: string[];
|
|
217
226
|
timeout?: number;
|
|
227
|
+
logger?: Logger;
|
|
218
228
|
}
|
|
219
229
|
export type GetSourcesParams = {
|
|
220
230
|
query: string;
|
|
231
|
+
date?: DATE_RANGE;
|
|
221
232
|
country?: string;
|
|
222
233
|
numResults?: number;
|
|
234
|
+
safeSearch?: SearchToolConfig['safeSearch'];
|
|
235
|
+
images?: boolean;
|
|
236
|
+
videos?: boolean;
|
|
237
|
+
news?: boolean;
|
|
238
|
+
type?: 'search' | 'images' | 'videos' | 'news';
|
|
223
239
|
};
|
|
224
240
|
/** Serper API */
|
|
225
241
|
export interface VideoResult {
|
|
@@ -380,6 +396,13 @@ export interface SerperSearchInput {
|
|
|
380
396
|
*/
|
|
381
397
|
autocorrect?: boolean;
|
|
382
398
|
page?: number;
|
|
399
|
+
/**
|
|
400
|
+
* Date range for search results
|
|
401
|
+
* Options: "h" (past hour), "d" (past 24 hours), "w" (past week),
|
|
402
|
+
* "m" (past month), "y" (past year)
|
|
403
|
+
* `qdr:${DATE_RANGE}`
|
|
404
|
+
*/
|
|
405
|
+
tbs?: string;
|
|
383
406
|
}
|
|
384
407
|
export type SerperResultData = {
|
|
385
408
|
searchParameters: SerperSearchPayload;
|
|
@@ -489,16 +512,29 @@ export type ProcessSourcesFields = {
|
|
|
489
512
|
result: SearchResult;
|
|
490
513
|
numElements: number;
|
|
491
514
|
query: string;
|
|
515
|
+
news: boolean;
|
|
492
516
|
proMode: boolean;
|
|
493
517
|
onGetHighlights: SearchToolConfig['onGetHighlights'];
|
|
494
518
|
};
|
|
495
519
|
export type SearchToolSchema = z.ZodObject<{
|
|
496
520
|
query: z.ZodString;
|
|
521
|
+
date: z.ZodOptional<z.ZodNativeEnum<typeof DATE_RANGE>>;
|
|
497
522
|
country?: z.ZodOptional<z.ZodString>;
|
|
523
|
+
images: z.ZodOptional<z.ZodBoolean>;
|
|
524
|
+
videos: z.ZodOptional<z.ZodBoolean>;
|
|
525
|
+
news: z.ZodOptional<z.ZodBoolean>;
|
|
498
526
|
}, 'strip', z.ZodTypeAny, {
|
|
499
527
|
query: string;
|
|
528
|
+
date?: DATE_RANGE;
|
|
500
529
|
country?: unknown;
|
|
530
|
+
images?: boolean;
|
|
531
|
+
videos?: boolean;
|
|
532
|
+
news?: boolean;
|
|
501
533
|
}, {
|
|
502
534
|
query: string;
|
|
535
|
+
date?: DATE_RANGE;
|
|
503
536
|
country?: unknown;
|
|
537
|
+
images?: boolean;
|
|
538
|
+
videos?: boolean;
|
|
539
|
+
news?: boolean;
|
|
504
540
|
}>;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import type * as t from './types';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Creates a default logger that maps to console methods
|
|
4
|
+
* Uses a singleton pattern to avoid creating multiple instances
|
|
5
|
+
* @returns A default logger that implements the Logger interface
|
|
6
|
+
*/
|
|
7
|
+
export declare const createDefaultLogger: () => t.Logger;
|
|
8
|
+
export declare const fileExtRegex: RegExp;
|
|
9
|
+
export declare const getDomainName: (link: string, metadata?: t.ScrapeMetadata, logger?: t.Logger) => string | undefined;
|
|
10
|
+
export declare function getAttribution(link: string, metadata?: t.ScrapeMetadata, logger?: t.Logger): string | undefined;
|