@librechat/agents 2.4.321 → 3.0.0-rc1
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/agents/AgentContext.cjs +218 -0
- package/dist/cjs/agents/AgentContext.cjs.map +1 -0
- package/dist/cjs/common/enum.cjs +14 -5
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/events.cjs +10 -6
- package/dist/cjs/events.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +309 -212
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +322 -0
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/index.cjs +54 -9
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +52 -6
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +22 -2
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/tools.cjs +29 -0
- package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -0
- package/dist/cjs/llm/google/index.cjs +144 -0
- package/dist/cjs/llm/google/index.cjs.map +1 -0
- package/dist/cjs/llm/google/utils/common.cjs +477 -0
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -0
- package/dist/cjs/llm/ollama/index.cjs +67 -0
- package/dist/cjs/llm/ollama/index.cjs.map +1 -0
- package/dist/cjs/llm/ollama/utils.cjs +158 -0
- package/dist/cjs/llm/ollama/utils.cjs.map +1 -0
- package/dist/cjs/llm/openai/index.cjs +389 -3
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +672 -0
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -0
- package/dist/cjs/llm/providers.cjs +15 -15
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs +14 -3
- package/dist/cjs/llm/text.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +330 -0
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -0
- package/dist/cjs/main.cjs +11 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/run.cjs +120 -81
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +85 -51
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +10 -4
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +119 -13
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/search/anthropic.cjs +40 -0
- package/dist/cjs/tools/search/anthropic.cjs.map +1 -0
- package/dist/cjs/tools/search/firecrawl.cjs +61 -13
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs +9 -3
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs +35 -50
- 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 +145 -38
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +165 -48
- 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/cjs/utils/events.cjs +31 -0
- package/dist/cjs/utils/events.cjs.map +1 -0
- package/dist/cjs/utils/title.cjs +57 -21
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +54 -7
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +216 -0
- package/dist/esm/agents/AgentContext.mjs.map +1 -0
- package/dist/esm/common/enum.mjs +15 -6
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/events.mjs +10 -6
- package/dist/esm/events.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +311 -214
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +320 -0
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -0
- package/dist/esm/llm/anthropic/index.mjs +54 -9
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +52 -6
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +22 -2
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/tools.mjs +27 -0
- package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -0
- package/dist/esm/llm/google/index.mjs +142 -0
- package/dist/esm/llm/google/index.mjs.map +1 -0
- package/dist/esm/llm/google/utils/common.mjs +471 -0
- package/dist/esm/llm/google/utils/common.mjs.map +1 -0
- package/dist/esm/llm/ollama/index.mjs +65 -0
- package/dist/esm/llm/ollama/index.mjs.map +1 -0
- package/dist/esm/llm/ollama/utils.mjs +155 -0
- package/dist/esm/llm/ollama/utils.mjs.map +1 -0
- package/dist/esm/llm/openai/index.mjs +388 -4
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +666 -0
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -0
- package/dist/esm/llm/providers.mjs +5 -5
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/text.mjs +14 -3
- package/dist/esm/llm/text.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +328 -0
- package/dist/esm/llm/vertexai/index.mjs.map +1 -0
- package/dist/esm/main.mjs +6 -5
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/run.mjs +121 -83
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +87 -54
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +10 -4
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +119 -15
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/search/anthropic.mjs +37 -0
- package/dist/esm/tools/search/anthropic.mjs.map +1 -0
- package/dist/esm/tools/search/firecrawl.mjs +61 -13
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs +10 -4
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs +35 -50
- 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 +146 -39
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +164 -47
- 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/esm/utils/events.mjs +29 -0
- package/dist/esm/utils/events.mjs.map +1 -0
- package/dist/esm/utils/title.mjs +57 -22
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +54 -8
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/agents/AgentContext.d.ts +91 -0
- package/dist/types/common/enum.d.ts +15 -6
- package/dist/types/events.d.ts +5 -4
- package/dist/types/graphs/Graph.d.ts +64 -67
- package/dist/types/graphs/MultiAgentGraph.d.ts +37 -0
- package/dist/types/graphs/index.d.ts +1 -0
- package/dist/types/llm/anthropic/index.d.ts +11 -0
- package/dist/types/llm/anthropic/types.d.ts +9 -3
- package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -1
- package/dist/types/llm/anthropic/utils/output_parsers.d.ts +4 -4
- package/dist/types/llm/anthropic/utils/tools.d.ts +3 -0
- package/dist/types/llm/google/index.d.ts +13 -0
- package/dist/types/llm/google/types.d.ts +32 -0
- package/dist/types/llm/google/utils/common.d.ts +19 -0
- package/dist/types/llm/google/utils/tools.d.ts +10 -0
- package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +14 -0
- package/dist/types/llm/ollama/index.d.ts +7 -0
- package/dist/types/llm/ollama/utils.d.ts +7 -0
- package/dist/types/llm/openai/index.d.ts +72 -3
- package/dist/types/llm/openai/types.d.ts +10 -0
- package/dist/types/llm/openai/utils/index.d.ts +20 -0
- package/dist/types/llm/text.d.ts +1 -1
- package/dist/types/llm/vertexai/index.d.ts +293 -0
- package/dist/types/messages/reducer.d.ts +9 -0
- package/dist/types/run.d.ts +19 -12
- package/dist/types/scripts/ant_web_search.d.ts +1 -0
- package/dist/types/scripts/args.d.ts +2 -1
- package/dist/types/scripts/handoff-test.d.ts +1 -0
- package/dist/types/scripts/multi-agent-conditional.d.ts +1 -0
- package/dist/types/scripts/multi-agent-parallel.d.ts +1 -0
- package/dist/types/scripts/multi-agent-sequence.d.ts +1 -0
- package/dist/types/scripts/multi-agent-test.d.ts +1 -0
- package/dist/types/stream.d.ts +10 -3
- package/dist/types/tools/CodeExecutor.d.ts +2 -2
- package/dist/types/tools/ToolNode.d.ts +1 -1
- package/dist/types/tools/handlers.d.ts +17 -4
- package/dist/types/tools/search/anthropic.d.ts +16 -0
- package/dist/types/tools/search/firecrawl.d.ts +16 -0
- package/dist/types/tools/search/rerankers.d.ts +8 -5
- 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 +64 -9
- package/dist/types/tools/search/utils.d.ts +9 -2
- package/dist/types/types/graph.d.ts +95 -15
- package/dist/types/types/llm.d.ts +24 -10
- package/dist/types/types/run.d.ts +46 -8
- package/dist/types/types/stream.d.ts +16 -2
- package/dist/types/types/tools.d.ts +1 -1
- package/dist/types/utils/events.d.ts +6 -0
- package/dist/types/utils/title.d.ts +2 -1
- package/dist/types/utils/tokens.d.ts +24 -0
- package/package.json +35 -18
- package/src/agents/AgentContext.ts +315 -0
- package/src/common/enum.ts +14 -5
- package/src/events.ts +24 -13
- package/src/graphs/Graph.ts +495 -312
- package/src/graphs/MultiAgentGraph.ts +381 -0
- package/src/graphs/index.ts +2 -1
- package/src/llm/anthropic/Jacob_Lee_Resume_2023.pdf +0 -0
- package/src/llm/anthropic/index.ts +78 -13
- package/src/llm/anthropic/llm.spec.ts +491 -115
- package/src/llm/anthropic/types.ts +39 -3
- package/src/llm/anthropic/utils/message_inputs.ts +67 -11
- package/src/llm/anthropic/utils/message_outputs.ts +21 -2
- package/src/llm/anthropic/utils/output_parsers.ts +25 -6
- package/src/llm/anthropic/utils/tools.ts +29 -0
- package/src/llm/google/index.ts +218 -0
- package/src/llm/google/types.ts +43 -0
- package/src/llm/google/utils/common.ts +646 -0
- package/src/llm/google/utils/tools.ts +160 -0
- package/src/llm/google/utils/zod_to_genai_parameters.ts +86 -0
- package/src/llm/ollama/index.ts +89 -0
- package/src/llm/ollama/utils.ts +193 -0
- package/src/llm/openai/index.ts +600 -14
- package/src/llm/openai/types.ts +24 -0
- package/src/llm/openai/utils/index.ts +912 -0
- package/src/llm/openai/utils/isReasoningModel.test.ts +90 -0
- package/src/llm/providers.ts +10 -9
- package/src/llm/text.ts +26 -7
- package/src/llm/vertexai/index.ts +360 -0
- package/src/messages/reducer.ts +80 -0
- package/src/run.ts +181 -112
- package/src/scripts/ant_web_search.ts +158 -0
- package/src/scripts/args.ts +12 -8
- package/src/scripts/cli4.ts +29 -21
- package/src/scripts/cli5.ts +29 -21
- package/src/scripts/code_exec.ts +54 -23
- package/src/scripts/code_exec_files.ts +48 -17
- package/src/scripts/code_exec_simple.ts +46 -27
- package/src/scripts/handoff-test.ts +135 -0
- package/src/scripts/image.ts +52 -20
- package/src/scripts/multi-agent-conditional.ts +220 -0
- package/src/scripts/multi-agent-example-output.md +110 -0
- package/src/scripts/multi-agent-parallel.ts +337 -0
- package/src/scripts/multi-agent-sequence.ts +212 -0
- package/src/scripts/multi-agent-test.ts +186 -0
- package/src/scripts/search.ts +4 -12
- package/src/scripts/simple.ts +25 -10
- package/src/scripts/tools.ts +48 -18
- package/src/specs/anthropic.simple.test.ts +150 -34
- package/src/specs/azure.simple.test.ts +325 -0
- package/src/specs/openai.simple.test.ts +140 -33
- package/src/specs/openrouter.simple.test.ts +107 -0
- package/src/specs/prune.test.ts +4 -9
- package/src/specs/reasoning.test.ts +80 -44
- package/src/specs/token-memoization.test.ts +39 -0
- package/src/stream.test.ts +94 -0
- package/src/stream.ts +139 -60
- package/src/tools/ToolNode.ts +21 -7
- package/src/tools/handlers.ts +192 -18
- package/src/tools/search/anthropic.ts +51 -0
- package/src/tools/search/firecrawl.ts +78 -24
- package/src/tools/search/format.ts +10 -5
- package/src/tools/search/rerankers.ts +50 -62
- package/src/tools/search/schema.ts +63 -0
- package/src/tools/search/search.ts +167 -34
- package/src/tools/search/tool.ts +222 -46
- package/src/tools/search/types.ts +65 -10
- package/src/tools/search/utils.ts +37 -5
- package/src/types/graph.ts +272 -103
- package/src/types/llm.ts +25 -12
- package/src/types/run.ts +51 -13
- package/src/types/stream.ts +22 -1
- package/src/types/tools.ts +16 -10
- package/src/utils/events.ts +32 -0
- package/src/utils/llmConfig.ts +20 -8
- package/src/utils/title.ts +104 -30
- package/src/utils/tokens.ts +69 -10
package/src/tools/search/tool.ts
CHANGED
|
@@ -1,88 +1,246 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
1
|
import { z } from 'zod';
|
|
3
2
|
import { tool, DynamicStructuredTool } from '@langchain/core/tools';
|
|
4
3
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
5
4
|
import type * as t from './types';
|
|
5
|
+
import {
|
|
6
|
+
DATE_RANGE,
|
|
7
|
+
querySchema,
|
|
8
|
+
dateSchema,
|
|
9
|
+
countrySchema,
|
|
10
|
+
imagesSchema,
|
|
11
|
+
videosSchema,
|
|
12
|
+
newsSchema,
|
|
13
|
+
} from './schema';
|
|
6
14
|
import { createSearchAPI, createSourceProcessor } from './search';
|
|
7
15
|
import { createFirecrawlScraper } from './firecrawl';
|
|
8
16
|
import { expandHighlights } from './highlights';
|
|
9
17
|
import { formatResultsForLLM } from './format';
|
|
18
|
+
import { createDefaultLogger } from './utils';
|
|
10
19
|
import { createReranker } from './rerankers';
|
|
11
20
|
import { Constants } from '@/common';
|
|
12
21
|
|
|
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
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Executes parallel searches and merges the results
|
|
24
|
+
*/
|
|
25
|
+
async function executeParallelSearches({
|
|
26
|
+
searchAPI,
|
|
27
|
+
query,
|
|
28
|
+
date,
|
|
29
|
+
country,
|
|
30
|
+
safeSearch,
|
|
31
|
+
images,
|
|
32
|
+
videos,
|
|
33
|
+
news,
|
|
34
|
+
logger,
|
|
35
|
+
}: {
|
|
36
|
+
searchAPI: ReturnType<typeof createSearchAPI>;
|
|
37
|
+
query: string;
|
|
38
|
+
date?: DATE_RANGE;
|
|
39
|
+
country?: string;
|
|
40
|
+
safeSearch: t.SearchToolConfig['safeSearch'];
|
|
41
|
+
images: boolean;
|
|
42
|
+
videos: boolean;
|
|
43
|
+
news: boolean;
|
|
44
|
+
logger: t.Logger;
|
|
45
|
+
}): Promise<t.SearchResult> {
|
|
46
|
+
// Prepare all search tasks to run in parallel
|
|
47
|
+
const searchTasks: Promise<t.SearchResult>[] = [
|
|
48
|
+
// Main search
|
|
49
|
+
searchAPI.getSources({
|
|
50
|
+
query,
|
|
51
|
+
date,
|
|
52
|
+
country,
|
|
53
|
+
safeSearch,
|
|
54
|
+
}),
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
if (images) {
|
|
58
|
+
searchTasks.push(
|
|
59
|
+
searchAPI
|
|
60
|
+
.getSources({
|
|
61
|
+
query,
|
|
62
|
+
date,
|
|
63
|
+
country,
|
|
64
|
+
safeSearch,
|
|
65
|
+
type: 'images',
|
|
66
|
+
})
|
|
67
|
+
.catch((error) => {
|
|
68
|
+
logger.error('Error fetching images:', error);
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: `Images search failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
72
|
+
};
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
if (videos) {
|
|
77
|
+
searchTasks.push(
|
|
78
|
+
searchAPI
|
|
79
|
+
.getSources({
|
|
80
|
+
query,
|
|
81
|
+
date,
|
|
82
|
+
country,
|
|
83
|
+
safeSearch,
|
|
84
|
+
type: 'videos',
|
|
85
|
+
})
|
|
86
|
+
.catch((error) => {
|
|
87
|
+
logger.error('Error fetching videos:', error);
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
error: `Videos search failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
91
|
+
};
|
|
92
|
+
})
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
if (news) {
|
|
96
|
+
searchTasks.push(
|
|
97
|
+
searchAPI
|
|
98
|
+
.getSources({
|
|
99
|
+
query,
|
|
100
|
+
date,
|
|
101
|
+
country,
|
|
102
|
+
safeSearch,
|
|
103
|
+
type: 'news',
|
|
104
|
+
})
|
|
105
|
+
.catch((error) => {
|
|
106
|
+
logger.error('Error fetching news:', error);
|
|
107
|
+
return {
|
|
108
|
+
success: false,
|
|
109
|
+
error: `News search failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
110
|
+
};
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Run all searches in parallel
|
|
116
|
+
const results = await Promise.all(searchTasks);
|
|
117
|
+
|
|
118
|
+
// Get the main search result (first result)
|
|
119
|
+
const mainResult = results[0];
|
|
120
|
+
if (!mainResult.success) {
|
|
121
|
+
throw new Error(mainResult.error ?? 'Search failed');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Merge additional results with the main results
|
|
125
|
+
const mergedResults = { ...mainResult.data };
|
|
126
|
+
|
|
127
|
+
// Convert existing news to topStories if present
|
|
128
|
+
if (mergedResults.news !== undefined && mergedResults.news.length > 0) {
|
|
129
|
+
const existingNewsAsTopStories = mergedResults.news
|
|
130
|
+
.filter((newsItem) => newsItem.link !== undefined && newsItem.link !== '')
|
|
131
|
+
.map((newsItem) => ({
|
|
132
|
+
title: newsItem.title ?? '',
|
|
133
|
+
link: newsItem.link ?? '',
|
|
134
|
+
source: newsItem.source ?? '',
|
|
135
|
+
date: newsItem.date ?? '',
|
|
136
|
+
imageUrl: newsItem.imageUrl ?? '',
|
|
137
|
+
processed: false,
|
|
138
|
+
}));
|
|
139
|
+
mergedResults.topStories = [
|
|
140
|
+
...(mergedResults.topStories ?? []),
|
|
141
|
+
...existingNewsAsTopStories,
|
|
142
|
+
];
|
|
143
|
+
delete mergedResults.news;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
results.slice(1).forEach((result) => {
|
|
147
|
+
if (result.success && result.data !== undefined) {
|
|
148
|
+
if (result.data.images !== undefined && result.data.images.length > 0) {
|
|
149
|
+
mergedResults.images = [
|
|
150
|
+
...(mergedResults.images ?? []),
|
|
151
|
+
...result.data.images,
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
if (result.data.videos !== undefined && result.data.videos.length > 0) {
|
|
155
|
+
mergedResults.videos = [
|
|
156
|
+
...(mergedResults.videos ?? []),
|
|
157
|
+
...result.data.videos,
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
if (result.data.news !== undefined && result.data.news.length > 0) {
|
|
161
|
+
const newsAsTopStories = result.data.news.map((newsItem) => ({
|
|
162
|
+
...newsItem,
|
|
163
|
+
link: newsItem.link ?? '',
|
|
164
|
+
}));
|
|
165
|
+
mergedResults.topStories = [
|
|
166
|
+
...(mergedResults.topStories ?? []),
|
|
167
|
+
...newsAsTopStories,
|
|
168
|
+
];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
return { success: true, data: mergedResults };
|
|
174
|
+
}
|
|
41
175
|
|
|
42
176
|
function createSearchProcessor({
|
|
43
177
|
searchAPI,
|
|
178
|
+
safeSearch,
|
|
44
179
|
sourceProcessor,
|
|
45
180
|
onGetHighlights,
|
|
181
|
+
logger,
|
|
46
182
|
}: {
|
|
183
|
+
safeSearch: t.SearchToolConfig['safeSearch'];
|
|
47
184
|
searchAPI: ReturnType<typeof createSearchAPI>;
|
|
48
185
|
sourceProcessor: ReturnType<typeof createSourceProcessor>;
|
|
49
186
|
onGetHighlights: t.SearchToolConfig['onGetHighlights'];
|
|
187
|
+
logger: t.Logger;
|
|
50
188
|
}) {
|
|
51
189
|
return async function ({
|
|
52
190
|
query,
|
|
191
|
+
date,
|
|
53
192
|
country,
|
|
54
193
|
proMode = true,
|
|
55
194
|
maxSources = 5,
|
|
56
195
|
onSearchResults,
|
|
196
|
+
images = false,
|
|
197
|
+
videos = false,
|
|
198
|
+
news = false,
|
|
57
199
|
}: {
|
|
58
200
|
query: string;
|
|
59
201
|
country?: string;
|
|
60
|
-
|
|
202
|
+
date?: DATE_RANGE;
|
|
61
203
|
proMode?: boolean;
|
|
204
|
+
maxSources?: number;
|
|
62
205
|
onSearchResults: t.SearchToolConfig['onSearchResults'];
|
|
206
|
+
images?: boolean;
|
|
207
|
+
videos?: boolean;
|
|
208
|
+
news?: boolean;
|
|
63
209
|
}): Promise<t.SearchResultData> {
|
|
64
210
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
211
|
+
// Execute parallel searches and merge results
|
|
212
|
+
const searchResult = await executeParallelSearches({
|
|
213
|
+
searchAPI,
|
|
214
|
+
query,
|
|
215
|
+
date,
|
|
216
|
+
country,
|
|
217
|
+
safeSearch,
|
|
218
|
+
images,
|
|
219
|
+
videos,
|
|
220
|
+
news,
|
|
221
|
+
logger,
|
|
222
|
+
});
|
|
67
223
|
|
|
68
|
-
|
|
69
|
-
throw new Error(result.error ?? 'Search failed');
|
|
70
|
-
}
|
|
224
|
+
onSearchResults?.(searchResult);
|
|
71
225
|
|
|
72
226
|
const processedSources = await sourceProcessor.processSources({
|
|
73
227
|
query,
|
|
74
|
-
|
|
228
|
+
news,
|
|
229
|
+
result: searchResult,
|
|
75
230
|
proMode,
|
|
76
231
|
onGetHighlights,
|
|
77
232
|
numElements: maxSources,
|
|
78
233
|
});
|
|
234
|
+
|
|
79
235
|
return expandHighlights(processedSources);
|
|
80
236
|
} catch (error) {
|
|
81
|
-
|
|
237
|
+
logger.error('Error in search:', error);
|
|
82
238
|
return {
|
|
83
239
|
organic: [],
|
|
84
240
|
topStories: [],
|
|
85
241
|
images: [],
|
|
242
|
+
videos: [],
|
|
243
|
+
news: [],
|
|
86
244
|
relatedSearches: [],
|
|
87
245
|
error: error instanceof Error ? error.message : String(error),
|
|
88
246
|
};
|
|
@@ -116,11 +274,15 @@ function createTool({
|
|
|
116
274
|
}): DynamicStructuredTool<typeof schema> {
|
|
117
275
|
return tool<typeof schema>(
|
|
118
276
|
async (params, runnableConfig) => {
|
|
119
|
-
const { query, country: _c } = params;
|
|
277
|
+
const { query, date, country: _c, images, videos, news } = params;
|
|
120
278
|
const country = typeof _c === 'string' && _c ? _c : undefined;
|
|
121
279
|
const searchResult = await search({
|
|
122
280
|
query,
|
|
281
|
+
date,
|
|
123
282
|
country,
|
|
283
|
+
images,
|
|
284
|
+
videos,
|
|
285
|
+
news,
|
|
124
286
|
onSearchResults: createOnSearchResults({
|
|
125
287
|
runnableConfig,
|
|
126
288
|
onSearchResults: _onSearchResults,
|
|
@@ -181,28 +343,36 @@ export const createSearchTool = (
|
|
|
181
343
|
topResults = 5,
|
|
182
344
|
strategies = ['no_extraction'],
|
|
183
345
|
filterContent = true,
|
|
346
|
+
safeSearch = 1,
|
|
184
347
|
firecrawlApiKey,
|
|
185
348
|
firecrawlApiUrl,
|
|
186
|
-
|
|
349
|
+
firecrawlOptions,
|
|
350
|
+
scraperTimeout,
|
|
187
351
|
jinaApiKey,
|
|
188
352
|
cohereApiKey,
|
|
189
353
|
onSearchResults: _onSearchResults,
|
|
190
354
|
onGetHighlights,
|
|
191
355
|
} = config;
|
|
192
356
|
|
|
193
|
-
const
|
|
357
|
+
const logger = config.logger || createDefaultLogger();
|
|
358
|
+
|
|
194
359
|
const schemaObject: {
|
|
195
360
|
query: z.ZodString;
|
|
361
|
+
date: z.ZodOptional<z.ZodNativeEnum<typeof DATE_RANGE>>;
|
|
196
362
|
country?: z.ZodOptional<z.ZodString>;
|
|
363
|
+
images: z.ZodOptional<z.ZodBoolean>;
|
|
364
|
+
videos: z.ZodOptional<z.ZodBoolean>;
|
|
365
|
+
news: z.ZodOptional<z.ZodBoolean>;
|
|
197
366
|
} = {
|
|
198
367
|
query: querySchema,
|
|
368
|
+
date: dateSchema,
|
|
369
|
+
images: imagesSchema,
|
|
370
|
+
videos: videosSchema,
|
|
371
|
+
news: newsSchema,
|
|
199
372
|
};
|
|
200
373
|
|
|
201
374
|
if (searchProvider === 'serper') {
|
|
202
|
-
schemaObject.country =
|
|
203
|
-
.string()
|
|
204
|
-
.optional()
|
|
205
|
-
.describe(DEFAULT_COUNTRY_DESCRIPTION);
|
|
375
|
+
schemaObject.country = countrySchema;
|
|
206
376
|
}
|
|
207
377
|
|
|
208
378
|
const toolSchema = z.object(schemaObject);
|
|
@@ -215,19 +385,22 @@ export const createSearchTool = (
|
|
|
215
385
|
});
|
|
216
386
|
|
|
217
387
|
const firecrawlScraper = createFirecrawlScraper({
|
|
388
|
+
...firecrawlOptions,
|
|
218
389
|
apiKey: firecrawlApiKey ?? process.env.FIRECRAWL_API_KEY,
|
|
219
390
|
apiUrl: firecrawlApiUrl,
|
|
220
|
-
|
|
391
|
+
timeout: scraperTimeout ?? firecrawlOptions?.timeout,
|
|
392
|
+
formats: firecrawlOptions?.formats ?? ['markdown', 'rawHtml'],
|
|
221
393
|
});
|
|
222
394
|
|
|
223
395
|
const selectedReranker = createReranker({
|
|
224
396
|
rerankerType,
|
|
225
397
|
jinaApiKey,
|
|
226
398
|
cohereApiKey,
|
|
399
|
+
logger,
|
|
227
400
|
});
|
|
228
401
|
|
|
229
402
|
if (!selectedReranker) {
|
|
230
|
-
|
|
403
|
+
logger.warn('No reranker selected. Using default ranking.');
|
|
231
404
|
}
|
|
232
405
|
|
|
233
406
|
const sourceProcessor = createSourceProcessor(
|
|
@@ -236,14 +409,17 @@ export const createSearchTool = (
|
|
|
236
409
|
topResults,
|
|
237
410
|
strategies,
|
|
238
411
|
filterContent,
|
|
412
|
+
logger,
|
|
239
413
|
},
|
|
240
414
|
firecrawlScraper
|
|
241
415
|
);
|
|
242
416
|
|
|
243
417
|
const search = createSearchProcessor({
|
|
244
418
|
searchAPI,
|
|
419
|
+
safeSearch,
|
|
245
420
|
sourceProcessor,
|
|
246
421
|
onGetHighlights,
|
|
422
|
+
logger,
|
|
247
423
|
});
|
|
248
424
|
|
|
249
425
|
return createTool({
|
|
@@ -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
|
|
|
5
7
|
export type SearchProvider = 'serper' | 'searxng';
|
|
6
8
|
export type RerankerType = 'infinity' | 'jina' | 'cohere' | 'none';
|
|
@@ -86,12 +88,13 @@ export interface ProcessSourcesConfig {
|
|
|
86
88
|
strategies?: string[];
|
|
87
89
|
filterContent?: boolean;
|
|
88
90
|
reranker?: BaseReranker;
|
|
91
|
+
logger?: Logger;
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
export interface FirecrawlConfig {
|
|
92
95
|
firecrawlApiKey?: string;
|
|
93
96
|
firecrawlApiUrl?: string;
|
|
94
|
-
|
|
97
|
+
firecrawlOptions?: FirecrawlScraperConfig;
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
export interface ScraperContentResult {
|
|
@@ -135,13 +138,19 @@ export interface CohereRerankerResponse {
|
|
|
135
138
|
};
|
|
136
139
|
}
|
|
137
140
|
|
|
141
|
+
export type SafeSearchLevel = 0 | 1 | 2;
|
|
142
|
+
|
|
143
|
+
export type Logger = WinstonLogger;
|
|
138
144
|
export interface SearchToolConfig
|
|
139
145
|
extends SearchConfig,
|
|
140
146
|
ProcessSourcesConfig,
|
|
141
147
|
FirecrawlConfig {
|
|
148
|
+
logger?: Logger;
|
|
149
|
+
safeSearch?: SafeSearchLevel;
|
|
142
150
|
jinaApiKey?: string;
|
|
143
151
|
cohereApiKey?: string;
|
|
144
152
|
rerankerType?: RerankerType;
|
|
153
|
+
scraperTimeout?: number;
|
|
145
154
|
onSearchResults?: (
|
|
146
155
|
results: SearchResult,
|
|
147
156
|
runnableConfig?: RunnableConfig
|
|
@@ -161,15 +170,10 @@ export type UsedReferences = {
|
|
|
161
170
|
}[];
|
|
162
171
|
|
|
163
172
|
/** Firecrawl */
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
excludeTags?: string[];
|
|
169
|
-
headers?: Record<string, string>;
|
|
170
|
-
waitFor?: number;
|
|
171
|
-
timeout?: number;
|
|
172
|
-
}
|
|
173
|
+
export type FirecrawlScrapeOptions = Omit<
|
|
174
|
+
FirecrawlScraperConfig,
|
|
175
|
+
'apiKey' | 'apiUrl' | 'logger'
|
|
176
|
+
>;
|
|
173
177
|
|
|
174
178
|
export interface ScrapeMetadata {
|
|
175
179
|
// Core source information
|
|
@@ -251,12 +255,34 @@ export interface FirecrawlScraperConfig {
|
|
|
251
255
|
apiUrl?: string;
|
|
252
256
|
formats?: string[];
|
|
253
257
|
timeout?: number;
|
|
258
|
+
logger?: Logger;
|
|
259
|
+
includeTags?: string[];
|
|
260
|
+
excludeTags?: string[];
|
|
261
|
+
waitFor?: number;
|
|
262
|
+
maxAge?: number;
|
|
263
|
+
mobile?: boolean;
|
|
264
|
+
skipTlsVerification?: boolean;
|
|
265
|
+
blockAds?: boolean;
|
|
266
|
+
removeBase64Images?: boolean;
|
|
267
|
+
parsePDF?: boolean;
|
|
268
|
+
storeInCache?: boolean;
|
|
269
|
+
zeroDataRetention?: boolean;
|
|
270
|
+
headers?: Record<string, string>;
|
|
271
|
+
location?: { country?: string; languages?: string[] };
|
|
272
|
+
onlyMainContent?: boolean;
|
|
273
|
+
changeTrackingOptions?: object;
|
|
254
274
|
}
|
|
255
275
|
|
|
256
276
|
export type GetSourcesParams = {
|
|
257
277
|
query: string;
|
|
278
|
+
date?: DATE_RANGE;
|
|
258
279
|
country?: string;
|
|
259
280
|
numResults?: number;
|
|
281
|
+
safeSearch?: SearchToolConfig['safeSearch'];
|
|
282
|
+
images?: boolean;
|
|
283
|
+
videos?: boolean;
|
|
284
|
+
news?: boolean;
|
|
285
|
+
type?: 'search' | 'images' | 'videos' | 'news';
|
|
260
286
|
};
|
|
261
287
|
|
|
262
288
|
/** Serper API */
|
|
@@ -435,6 +461,13 @@ export interface SerperSearchInput {
|
|
|
435
461
|
*/
|
|
436
462
|
autocorrect?: boolean;
|
|
437
463
|
page?: number;
|
|
464
|
+
/**
|
|
465
|
+
* Date range for search results
|
|
466
|
+
* Options: "h" (past hour), "d" (past 24 hours), "w" (past week),
|
|
467
|
+
* "m" (past month), "y" (past year)
|
|
468
|
+
* `qdr:${DATE_RANGE}`
|
|
469
|
+
*/
|
|
470
|
+
tbs?: string;
|
|
438
471
|
}
|
|
439
472
|
|
|
440
473
|
export type SerperResultData = {
|
|
@@ -558,12 +591,22 @@ export interface SearXNGResult {
|
|
|
558
591
|
content?: string;
|
|
559
592
|
publishedDate?: string;
|
|
560
593
|
img_src?: string;
|
|
594
|
+
score?: number;
|
|
595
|
+
engine?: string;
|
|
596
|
+
category?: string;
|
|
597
|
+
thumbnail?: string;
|
|
598
|
+
priority?: string;
|
|
599
|
+
engines?: string[];
|
|
600
|
+
positions?: number[];
|
|
601
|
+
template?: string;
|
|
602
|
+
parsed_url?: string[];
|
|
561
603
|
}
|
|
562
604
|
|
|
563
605
|
export type ProcessSourcesFields = {
|
|
564
606
|
result: SearchResult;
|
|
565
607
|
numElements: number;
|
|
566
608
|
query: string;
|
|
609
|
+
news: boolean;
|
|
567
610
|
proMode: boolean;
|
|
568
611
|
onGetHighlights: SearchToolConfig['onGetHighlights'];
|
|
569
612
|
};
|
|
@@ -571,16 +614,28 @@ export type ProcessSourcesFields = {
|
|
|
571
614
|
export type SearchToolSchema = z.ZodObject<
|
|
572
615
|
{
|
|
573
616
|
query: z.ZodString;
|
|
617
|
+
date: z.ZodOptional<z.ZodNativeEnum<typeof DATE_RANGE>>;
|
|
574
618
|
country?: z.ZodOptional<z.ZodString>;
|
|
619
|
+
images: z.ZodOptional<z.ZodBoolean>;
|
|
620
|
+
videos: z.ZodOptional<z.ZodBoolean>;
|
|
621
|
+
news: z.ZodOptional<z.ZodBoolean>;
|
|
575
622
|
},
|
|
576
623
|
'strip',
|
|
577
624
|
z.ZodTypeAny,
|
|
578
625
|
{
|
|
579
626
|
query: string;
|
|
627
|
+
date?: DATE_RANGE;
|
|
580
628
|
country?: unknown;
|
|
629
|
+
images?: boolean;
|
|
630
|
+
videos?: boolean;
|
|
631
|
+
news?: boolean;
|
|
581
632
|
},
|
|
582
633
|
{
|
|
583
634
|
query: string;
|
|
635
|
+
date?: DATE_RANGE;
|
|
584
636
|
country?: unknown;
|
|
637
|
+
images?: boolean;
|
|
638
|
+
videos?: boolean;
|
|
639
|
+
news?: boolean;
|
|
585
640
|
}
|
|
586
641
|
>;
|
|
@@ -1,9 +1,36 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
+
|
|
2
3
|
import type * as t from './types';
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Singleton instance of the default logger
|
|
7
|
+
*/
|
|
8
|
+
let defaultLoggerInstance: t.Logger | null = null;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a default logger that maps to console methods
|
|
12
|
+
* Uses a singleton pattern to avoid creating multiple instances
|
|
13
|
+
* @returns A default logger that implements the Logger interface
|
|
14
|
+
*/
|
|
15
|
+
export const createDefaultLogger = (): t.Logger => {
|
|
16
|
+
if (!defaultLoggerInstance) {
|
|
17
|
+
defaultLoggerInstance = {
|
|
18
|
+
error: console.error,
|
|
19
|
+
warn: console.warn,
|
|
20
|
+
info: console.info,
|
|
21
|
+
debug: console.debug,
|
|
22
|
+
} as t.Logger;
|
|
23
|
+
}
|
|
24
|
+
return defaultLoggerInstance;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const fileExtRegex =
|
|
28
|
+
/\.(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;
|
|
29
|
+
|
|
4
30
|
export const getDomainName = (
|
|
5
31
|
link: string,
|
|
6
|
-
metadata?: t.ScrapeMetadata
|
|
32
|
+
metadata?: t.ScrapeMetadata,
|
|
33
|
+
logger?: t.Logger
|
|
7
34
|
): string | undefined => {
|
|
8
35
|
try {
|
|
9
36
|
const url = metadata?.sourceURL ?? metadata?.url ?? (link || '');
|
|
@@ -13,7 +40,11 @@ export const getDomainName = (
|
|
|
13
40
|
}
|
|
14
41
|
} catch (e) {
|
|
15
42
|
// URL parsing failed
|
|
16
|
-
|
|
43
|
+
if (logger) {
|
|
44
|
+
logger.error('Error parsing URL:', e);
|
|
45
|
+
} else {
|
|
46
|
+
console.error('Error parsing URL:', e);
|
|
47
|
+
}
|
|
17
48
|
}
|
|
18
49
|
|
|
19
50
|
return;
|
|
@@ -21,9 +52,10 @@ export const getDomainName = (
|
|
|
21
52
|
|
|
22
53
|
export function getAttribution(
|
|
23
54
|
link: string,
|
|
24
|
-
metadata?: t.ScrapeMetadata
|
|
55
|
+
metadata?: t.ScrapeMetadata,
|
|
56
|
+
logger?: t.Logger
|
|
25
57
|
): string | undefined {
|
|
26
|
-
if (!metadata) return getDomainName(link, metadata);
|
|
58
|
+
if (!metadata) return getDomainName(link, metadata, logger);
|
|
27
59
|
|
|
28
60
|
const twitterSite = metadata['twitter:site'];
|
|
29
61
|
const twitterSiteFormatted =
|
|
@@ -43,5 +75,5 @@ export function getAttribution(
|
|
|
43
75
|
return attribution;
|
|
44
76
|
}
|
|
45
77
|
|
|
46
|
-
return getDomainName(link, metadata);
|
|
78
|
+
return getDomainName(link, metadata, logger);
|
|
47
79
|
}
|