@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
|
@@ -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,
|
|
129
|
-
const
|
|
237
|
+
const { searchProvider = 'serper', serperApiKey, searxngInstanceUrl, searxngApiKey, rerankerType = 'cohere', topResults = 5, strategies = ['no_extraction'], filterContent = true, safeSearch = 1, firecrawlApiKey, firecrawlApiUrl, firecrawlOptions, scraperTimeout, 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({
|
|
@@ -144,25 +254,32 @@ const createSearchTool = (config = {}) => {
|
|
|
144
254
|
searxngApiKey,
|
|
145
255
|
});
|
|
146
256
|
const firecrawlScraper = createFirecrawlScraper({
|
|
257
|
+
...firecrawlOptions,
|
|
147
258
|
apiKey: firecrawlApiKey ?? process.env.FIRECRAWL_API_KEY,
|
|
148
259
|
apiUrl: firecrawlApiUrl,
|
|
149
|
-
|
|
260
|
+
timeout: scraperTimeout ?? firecrawlOptions?.timeout,
|
|
261
|
+
formats: firecrawlOptions?.formats ?? ['markdown', 'rawHtml'],
|
|
150
262
|
});
|
|
151
263
|
const selectedReranker = createReranker({
|
|
152
264
|
rerankerType,
|
|
153
265
|
jinaApiKey,
|
|
154
266
|
cohereApiKey,
|
|
267
|
+
logger,
|
|
155
268
|
});
|
|
156
269
|
if (!selectedReranker) {
|
|
157
|
-
|
|
270
|
+
logger.warn('No reranker selected. Using default ranking.');
|
|
158
271
|
}
|
|
159
272
|
const sourceProcessor = createSourceProcessor({
|
|
160
273
|
reranker: selectedReranker,
|
|
161
|
-
topResults
|
|
274
|
+
topResults,
|
|
275
|
+
logger,
|
|
276
|
+
}, firecrawlScraper);
|
|
162
277
|
const search = createSearchProcessor({
|
|
163
278
|
searchAPI,
|
|
279
|
+
safeSearch,
|
|
164
280
|
sourceProcessor,
|
|
165
281
|
onGetHighlights,
|
|
282
|
+
logger,
|
|
166
283
|
});
|
|
167
284
|
return createTool({
|
|
168
285
|
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":";;;;;;;;;AAAA;AAYA,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;;;;;CAkBjC,CAAC,IAAI,EAAE;AAER,MAAM,2BAA2B,GAAG,CAAA;;;;;;;CAOnC,CAAC,IAAI,EAAE;AAER,SAAS,qBAAqB,CAAC,EAC7B,SAAS,EACT,eAAe,EACf,eAAe,GAKhB,EAAA;AACC,IAAA,OAAO,gBAAgB,EACrB,KAAK,EACL,OAAO,EACP,OAAO,GAAG,IAAI,EACd,UAAU,GAAG,CAAC,EACd,eAAe,GAOhB,EAAA;AACC,QAAA,IAAI;AACF,YAAA,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC7D,YAAA,eAAe,GAAG,MAAM,CAAC;AAEzB,YAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;gBACnB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,eAAe,CAAC;;AAGlD,YAAA,MAAM,gBAAgB,GAAG,MAAM,eAAe,CAAC,cAAc,CAAC;gBAC5D,KAAK;gBACL,MAAM;gBACN,OAAO;gBACP,eAAe;AACf,gBAAA,WAAW,EAAE,UAAU;AACxB,aAAA,CAAC;AACF,YAAA,OAAO,gBAAgB,CAAC,gBAAgB,CAAC;;QACzC,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC;YACxC,OAAO;AACL,gBAAA,OAAO,EAAE,EAAE;AACX,gBAAA,UAAU,EAAE,EAAE;AACd,gBAAA,MAAM,EAAE,EAAE;AACV,gBAAA,eAAe,EAAE,EAAE;AACnB,gBAAA,KAAK,EAAE,KAAK,YAAY,KAAK,GAAG,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;aAC9D;;AAEL,KAAC;AACH;AAEA,SAAS,qBAAqB,CAAC,EAC7B,cAAc,EACd,eAAe,GAIhB,EAAA;AACC,IAAA,OAAO,UAAU,OAAuB,EAAA;QACtC,IAAI,CAAC,eAAe,EAAE;YACpB;;AAEF,QAAA,eAAe,CAAC,OAAO,EAAE,cAAc,CAAC;AAC1C,KAAC;AACH;AAEA,SAAS,UAAU,CAAC,EAClB,MAAM,EACN,MAAM,EACN,eAAe,EAAE,gBAAgB,GAKlC,EAAA;IACC,OAAO,IAAI,CACT,OAAO,MAAM,EAAE,cAAc,KAAI;QAC/B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM;AACrC,QAAA,MAAM,OAAO,GAAG,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,GAAG,EAAE,GAAG,SAAS;AAC7D,QAAA,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC;YAChC,KAAK;YACL,OAAO;YACP,eAAe,EAAE,qBAAqB,CAAC;gBACrC,cAAc;AACd,gBAAA,eAAe,EAAE,gBAAgB;aAClC,CAAC;AACH,SAAA,CAAC;QACF,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC;AAC/C,QAAA,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,mBAAmB,CAAC,IAAI,EAAE,YAAY,CAAC;QACtE,MAAM,IAAI,GAAuB,EAAE,IAAI,EAAE,GAAG,YAAY,EAAE,UAAU,EAAE;AACtE,QAAA,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,GAAG,IAAI,EAAE,CAAC;AACnD,KAAC,EACD;QACE,IAAI,EAAE,SAAS,CAAC,UAAU;AAC1B,QAAA,WAAW,EAAE,CAAA;;;;;;;;;;;;;;;;;;;;;;AAsBlB,CAAA,CAAC,IAAI,EAAE;AACF,QAAA,MAAM,EAAE,MAAM;QACd,cAAc,EAAE,SAAS,CAAC,oBAAoB;AAC/C,KAAA,CACF;AACH;AAEA;;;;;;AAMG;MACU,gBAAgB,GAAG,CAC9B,MAA6B,GAAA,EAAE,KACa;IAC5C,MAAM,EACJ,cAAc,GAAG,QAAQ,EACzB,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,YAAY,GAAG,QAAQ,EACvB,UAAU,GAAG,CAAC,EACd,UAAU,GAAG,CAAC,eAAe,CAAC,EAC9B,aAAa,GAAG,IAAI,EACpB,eAAe,EACf,eAAe,EACf,gBAAgB,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,EACvC,UAAU,EACV,YAAY,EACZ,eAAe,EAAE,gBAAgB,EACjC,eAAe,GAChB,GAAG,MAAM;IAEV,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;AAClE,IAAA,MAAM,YAAY,GAGd;AACF,QAAA,KAAK,EAAE,WAAW;KACnB;AAED,IAAA,IAAI,cAAc,KAAK,QAAQ,EAAE;QAC/B,YAAY,CAAC,OAAO,GAAG;AACpB,aAAA,MAAM;AACN,aAAA,QAAQ;aACR,QAAQ,CAAC,2BAA2B,CAAC;;IAG1C,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;IAEzC,MAAM,SAAS,GAAG,eAAe,CAAC;QAChC,cAAc;QACd,YAAY;QACZ,kBAAkB;QAClB,aAAa;AACd,KAAA,CAAC;IAEF,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAC9C,QAAA,MAAM,EAAE,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;AACxD,QAAA,MAAM,EAAE,eAAe;AACvB,QAAA,OAAO,EAAE,gBAAgB;AAC1B,KAAA,CAAC;IAEF,MAAM,gBAAgB,GAAG,cAAc,CAAC;QACtC,YAAY;QACZ,UAAU;QACV,YAAY;AACb,KAAA,CAAC;IAEF,IAAI,CAAC,gBAAgB,EAAE;AACrB,QAAA,OAAO,CAAC,IAAI,CAAC,8CAA8C,CAAC;;IAG9D,MAAM,eAAe,GAAG,qBAAqB,CAC3C;AACE,QAAA,QAAQ,EAAE,gBAAgB;QAC1B,WAGD,EACD,gBAAgB,CACjB;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC;QACnC,SAAS;QACT,eAAe;QACf,eAAe;AAChB,KAAA,CAAC;AAEF,IAAA,OAAO,UAAU,CAAC;QAChB,MAAM;AACN,QAAA,MAAM,EAAE,UAAU;AAClB,QAAA,eAAe,EAAE,gBAAgB;AAClC,KAAA,CAAC;AACJ;;;;"}
|
|
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 firecrawlOptions,\n scraperTimeout,\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 ...firecrawlOptions,\n apiKey: firecrawlApiKey ?? process.env.FIRECRAWL_API_KEY,\n apiUrl: firecrawlApiUrl,\n timeout: scraperTimeout ?? firecrawlOptions?.timeout,\n formats: firecrawlOptions?.formats ?? ['markdown', 'rawHtml'],\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;;;;"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { dispatchCustomEvent } from '@langchain/core/callbacks/dispatch';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
// src/utils/events.ts
|
|
5
|
+
/**
|
|
6
|
+
* Safely dispatches a custom event and properly awaits it to avoid
|
|
7
|
+
* race conditions where events are dispatched after run cleanup.
|
|
8
|
+
*/
|
|
9
|
+
async function safeDispatchCustomEvent(event, payload, config) {
|
|
10
|
+
try {
|
|
11
|
+
await dispatchCustomEvent(event, payload, config);
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
// Check if this is the known EventStreamCallbackHandler error
|
|
15
|
+
if (e instanceof Error &&
|
|
16
|
+
e.message.includes('handleCustomEvent: Run ID') &&
|
|
17
|
+
e.message.includes('not found in run map')) {
|
|
18
|
+
// Suppress this specific error - it's expected during parallel execution
|
|
19
|
+
// when EventStreamCallbackHandler loses track of run IDs
|
|
20
|
+
// console.debug('Suppressed error dispatching custom event:', e);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// Log other errors
|
|
24
|
+
console.error('Error dispatching custom event:', e);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { safeDispatchCustomEvent };
|
|
29
|
+
//# sourceMappingURL=events.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.mjs","sources":["../../../src/utils/events.ts"],"sourcesContent":["/* eslint-disable no-console */\n// src/utils/events.ts\nimport { dispatchCustomEvent } from '@langchain/core/callbacks/dispatch';\nimport type { RunnableConfig } from '@langchain/core/runnables';\n\n/**\n * Safely dispatches a custom event and properly awaits it to avoid\n * race conditions where events are dispatched after run cleanup.\n */\nexport async function safeDispatchCustomEvent(\n event: string,\n payload: unknown,\n config?: RunnableConfig\n): Promise<void> {\n try {\n await dispatchCustomEvent(event, payload, config);\n } catch (e) {\n // Check if this is the known EventStreamCallbackHandler error\n if (\n e instanceof Error &&\n e.message.includes('handleCustomEvent: Run ID') &&\n e.message.includes('not found in run map')\n ) {\n // Suppress this specific error - it's expected during parallel execution\n // when EventStreamCallbackHandler loses track of run IDs\n // console.debug('Suppressed error dispatching custom event:', e);\n return;\n }\n // Log other errors\n console.error('Error dispatching custom event:', e);\n }\n}\n"],"names":[],"mappings":";;AAAA;AACA;AAIA;;;AAGG;AACI,eAAe,uBAAuB,CAC3C,KAAa,EACb,OAAgB,EAChB,MAAuB,EAAA;AAEvB,IAAA,IAAI;QACF,MAAM,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;;IACjD,OAAO,CAAC,EAAE;;QAEV,IACE,CAAC,YAAY,KAAK;AAClB,YAAA,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAC;YAC/C,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAC1C;;;;YAIA;;;AAGF,QAAA,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,CAAC,CAAC;;AAEvD;;;;"}
|
package/dist/esm/utils/title.mjs
CHANGED
|
@@ -1,44 +1,79 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
3
2
|
import { RunnableLambda } from '@langchain/core/runnables';
|
|
3
|
+
import { ChatPromptTemplate } from '@langchain/core/prompts';
|
|
4
|
+
import { ContentTypes } from '../common/enum.mjs';
|
|
5
|
+
|
|
6
|
+
const defaultTitlePrompt = `Analyze this conversation and provide:
|
|
7
|
+
1. The detected language of the conversation
|
|
8
|
+
2. A concise title in the detected language (5 words or less, no punctuation or quotation)
|
|
4
9
|
|
|
5
|
-
const defaultTitlePrompt = `Write a concise title for this conversation in the detected language. Title in 5 Words or Less. No Punctuation or Quotation.
|
|
6
10
|
{convo}`;
|
|
7
|
-
const languageInstructions = 'Detect the language used in the following text. Note: words may be misspelled or cut off; use context clues to identify the language:\n{text}';
|
|
8
|
-
const languagePrompt = ChatPromptTemplate.fromTemplate(languageInstructions);
|
|
9
|
-
const languageSchema = z.object({
|
|
10
|
-
language: z.string().describe('The detected language of the conversation')
|
|
11
|
-
});
|
|
12
11
|
const titleSchema = z.object({
|
|
13
|
-
title: z
|
|
12
|
+
title: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe('A concise title for the conversation in 5 words or less, without punctuation or quotation'),
|
|
15
|
+
});
|
|
16
|
+
const combinedSchema = z.object({
|
|
17
|
+
language: z.string().describe('The detected language of the conversation'),
|
|
18
|
+
title: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe('A concise title for the conversation in 5 words or less, without punctuation or quotation'),
|
|
14
21
|
});
|
|
15
22
|
const createTitleRunnable = async (model, _titlePrompt) => {
|
|
16
23
|
// Disabled since this works fine
|
|
17
24
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
18
25
|
/* @ts-ignore */
|
|
19
|
-
const
|
|
26
|
+
const titleLLM = model.withStructuredOutput(titleSchema);
|
|
20
27
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
21
28
|
/* @ts-ignore */
|
|
22
|
-
const
|
|
23
|
-
const languageChain = languagePrompt.pipe(languageLLM);
|
|
29
|
+
const combinedLLM = model.withStructuredOutput(combinedSchema);
|
|
24
30
|
const titlePrompt = ChatPromptTemplate.fromTemplate(_titlePrompt ?? defaultTitlePrompt);
|
|
25
31
|
return new RunnableLambda({
|
|
26
|
-
func: async (input) => {
|
|
32
|
+
func: async (input, config) => {
|
|
27
33
|
if (input.skipLanguage) {
|
|
28
|
-
return await titlePrompt.pipe(titleLLM).invoke({
|
|
29
|
-
convo: input.convo
|
|
30
|
-
});
|
|
34
|
+
return (await titlePrompt.pipe(titleLLM).invoke({
|
|
35
|
+
convo: input.convo,
|
|
36
|
+
}, config));
|
|
31
37
|
}
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
const result = (await titlePrompt.pipe(combinedLLM).invoke({
|
|
39
|
+
convo: input.convo,
|
|
40
|
+
}, config));
|
|
41
|
+
return {
|
|
42
|
+
language: result?.language ?? 'English',
|
|
43
|
+
title: result?.title ?? '',
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
const defaultCompletionPrompt = `Provide a concise, 5-word-or-less title for the conversation, using title case conventions. Only return the title itself.
|
|
49
|
+
|
|
50
|
+
Conversation:
|
|
51
|
+
{convo}`;
|
|
52
|
+
const createCompletionTitleRunnable = async (model, titlePrompt) => {
|
|
53
|
+
const completionPrompt = ChatPromptTemplate.fromTemplate(titlePrompt ?? defaultCompletionPrompt);
|
|
54
|
+
return new RunnableLambda({
|
|
55
|
+
func: async (input, config) => {
|
|
56
|
+
const promptOutput = await completionPrompt.invoke({
|
|
57
|
+
convo: input.convo,
|
|
37
58
|
});
|
|
38
|
-
|
|
59
|
+
const response = await model.invoke(promptOutput, config);
|
|
60
|
+
let content = '';
|
|
61
|
+
if (typeof response.content === 'string') {
|
|
62
|
+
content = response.content;
|
|
63
|
+
}
|
|
64
|
+
else if (Array.isArray(response.content)) {
|
|
65
|
+
content = response.content
|
|
66
|
+
.filter((part) => part.type === ContentTypes.TEXT)
|
|
67
|
+
.map((part) => part.text)
|
|
68
|
+
.join('');
|
|
69
|
+
}
|
|
70
|
+
const title = content.trim();
|
|
71
|
+
return {
|
|
72
|
+
title,
|
|
73
|
+
};
|
|
39
74
|
},
|
|
40
75
|
});
|
|
41
76
|
};
|
|
42
77
|
|
|
43
|
-
export { createTitleRunnable };
|
|
78
|
+
export { createCompletionTitleRunnable, createTitleRunnable };
|
|
44
79
|
//# sourceMappingURL=title.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"title.mjs","sources":["../../../src/utils/title.ts"],"sourcesContent":["import { z } from 'zod';\nimport {
|
|
1
|
+
{"version":3,"file":"title.mjs","sources":["../../../src/utils/title.ts"],"sourcesContent":["import { z } from 'zod';\nimport { RunnableLambda } from '@langchain/core/runnables';\nimport { ChatPromptTemplate } from '@langchain/core/prompts';\nimport type { Runnable, RunnableConfig } from '@langchain/core/runnables';\nimport type * as t from '@/types';\nimport { ContentTypes } from '@/common';\n\nconst defaultTitlePrompt = `Analyze this conversation and provide:\n1. The detected language of the conversation\n2. A concise title in the detected language (5 words or less, no punctuation or quotation)\n\n{convo}`;\n\nconst titleSchema = z.object({\n title: z\n .string()\n .describe(\n 'A concise title for the conversation in 5 words or less, without punctuation or quotation'\n ),\n});\n\nconst combinedSchema = z.object({\n language: z.string().describe('The detected language of the conversation'),\n title: z\n .string()\n .describe(\n 'A concise title for the conversation in 5 words or less, without punctuation or quotation'\n ),\n});\n\nexport const createTitleRunnable = async (\n model: t.ChatModelInstance,\n _titlePrompt?: string\n): Promise<Runnable> => {\n // Disabled since this works fine\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n /* @ts-ignore */\n const titleLLM = model.withStructuredOutput(titleSchema);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n /* @ts-ignore */\n const combinedLLM = model.withStructuredOutput(combinedSchema);\n\n const titlePrompt = ChatPromptTemplate.fromTemplate(\n _titlePrompt ?? defaultTitlePrompt\n );\n\n return new RunnableLambda({\n func: async (\n input: {\n convo: string;\n inputText: string;\n skipLanguage: boolean;\n },\n config?: Partial<RunnableConfig>\n ): Promise<{ language: string; title: string } | { title: string }> => {\n if (input.skipLanguage) {\n return (await titlePrompt.pipe(titleLLM).invoke(\n {\n convo: input.convo,\n },\n config\n )) as { title: string };\n }\n\n const result = (await titlePrompt.pipe(combinedLLM).invoke(\n {\n convo: input.convo,\n },\n config\n )) as { language: string; title: string } | undefined;\n\n return {\n language: result?.language ?? 'English',\n title: result?.title ?? '',\n };\n },\n });\n};\n\nconst defaultCompletionPrompt = `Provide a concise, 5-word-or-less title for the conversation, using title case conventions. Only return the title itself.\n\nConversation:\n{convo}`;\n\nexport const createCompletionTitleRunnable = async (\n model: t.ChatModelInstance,\n titlePrompt?: string\n): Promise<Runnable> => {\n const completionPrompt = ChatPromptTemplate.fromTemplate(\n titlePrompt ?? defaultCompletionPrompt\n );\n\n return new RunnableLambda({\n func: async (\n input: {\n convo: string;\n inputText: string;\n skipLanguage: boolean;\n },\n config?: Partial<RunnableConfig>\n ): Promise<{ title: string }> => {\n const promptOutput = await completionPrompt.invoke({\n convo: input.convo,\n });\n\n const response = await model.invoke(promptOutput, config);\n let content = '';\n if (typeof response.content === 'string') {\n content = response.content;\n } else if (Array.isArray(response.content)) {\n content = response.content\n .filter(\n (part): part is { type: ContentTypes.TEXT; text: string } =>\n part.type === ContentTypes.TEXT\n )\n .map((part) => part.text)\n .join('');\n }\n const title = content.trim();\n return {\n title,\n };\n },\n });\n};\n"],"names":[],"mappings":";;;;;AAOA,MAAM,kBAAkB,GAAG,CAAA;;;;QAInB;AAER,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;AAC3B,IAAA,KAAK,EAAE;AACJ,SAAA,MAAM;SACN,QAAQ,CACP,2FAA2F,CAC5F;AACJ,CAAA,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;AAC1E,IAAA,KAAK,EAAE;AACJ,SAAA,MAAM;SACN,QAAQ,CACP,2FAA2F,CAC5F;AACJ,CAAA,CAAC;AAEW,MAAA,mBAAmB,GAAG,OACjC,KAA0B,EAC1B,YAAqB,KACA;;;;IAIrB,MAAM,QAAQ,GAAG,KAAK,CAAC,oBAAoB,CAAC,WAAW,CAAC;;;IAGxD,MAAM,WAAW,GAAG,KAAK,CAAC,oBAAoB,CAAC,cAAc,CAAC;IAE9D,MAAM,WAAW,GAAG,kBAAkB,CAAC,YAAY,CACjD,YAAY,IAAI,kBAAkB,CACnC;IAED,OAAO,IAAI,cAAc,CAAC;AACxB,QAAA,IAAI,EAAE,OACJ,KAIC,EACD,MAAgC,KACoC;AACpE,YAAA,IAAI,KAAK,CAAC,YAAY,EAAE;gBACtB,QAAQ,MAAM,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAC7C;oBACE,KAAK,EAAE,KAAK,CAAC,KAAK;iBACnB,EACD,MAAM,CACP;;AAGH,YAAA,MAAM,MAAM,IAAI,MAAM,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CACxD;gBACE,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB,EACD,MAAM,CACP,CAAoD;YAErD,OAAO;AACL,gBAAA,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,SAAS;AACvC,gBAAA,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE;aAC3B;SACF;AACF,KAAA,CAAC;AACJ;AAEA,MAAM,uBAAuB,GAAG,CAAA;;;QAGxB;AAEK,MAAA,6BAA6B,GAAG,OAC3C,KAA0B,EAC1B,WAAoB,KACC;IACrB,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,YAAY,CACtD,WAAW,IAAI,uBAAuB,CACvC;IAED,OAAO,IAAI,cAAc,CAAC;AACxB,QAAA,IAAI,EAAE,OACJ,KAIC,EACD,MAAgC,KACF;AAC9B,YAAA,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC;gBACjD,KAAK,EAAE,KAAK,CAAC,KAAK;AACnB,aAAA,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC;YACzD,IAAI,OAAO,GAAG,EAAE;AAChB,YAAA,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,EAAE;AACxC,gBAAA,OAAO,GAAG,QAAQ,CAAC,OAAO;;iBACrB,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;gBAC1C,OAAO,GAAG,QAAQ,CAAC;AAChB,qBAAA,MAAM,CACL,CAAC,IAAI,KACH,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,IAAI;qBAElC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;qBACvB,IAAI,CAAC,EAAE,CAAC;;AAEb,YAAA,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE;YAC5B,OAAO;gBACL,KAAK;aACN;SACF;AACF,KAAA,CAAC;AACJ;;;;"}
|