@illuma-ai/agents 1.1.21 → 1.1.22

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.
Files changed (241) hide show
  1. package/dist/cjs/graphs/Graph.cjs +12 -1
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/graphs/MultiAgentGraph.cjs +85 -1
  4. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  5. package/dist/cjs/run.cjs +20 -9
  6. package/dist/cjs/run.cjs.map +1 -1
  7. package/dist/esm/graphs/Graph.mjs +12 -1
  8. package/dist/esm/graphs/Graph.mjs.map +1 -1
  9. package/dist/esm/graphs/MultiAgentGraph.mjs +85 -1
  10. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  11. package/dist/esm/run.mjs +20 -9
  12. package/dist/esm/run.mjs.map +1 -1
  13. package/dist/types/graphs/MultiAgentGraph.d.ts +17 -0
  14. package/package.json +1 -1
  15. package/src/graphs/Graph.ts +12 -1
  16. package/src/graphs/MultiAgentGraph.ts +105 -1
  17. package/src/graphs/__tests__/multi-agent-delegate.test.ts +191 -0
  18. package/src/run.ts +20 -11
  19. package/src/scripts/test-bedrock-handoff-autonomous.ts +231 -0
  20. package/src/agents/AgentContext.js +0 -782
  21. package/src/agents/AgentContext.test.js +0 -421
  22. package/src/agents/__tests__/AgentContext.test.js +0 -678
  23. package/src/agents/__tests__/resolveStructuredOutputMode.test.js +0 -117
  24. package/src/common/enum.js +0 -192
  25. package/src/common/index.js +0 -3
  26. package/src/events.js +0 -166
  27. package/src/graphs/Graph.js +0 -1857
  28. package/src/graphs/MultiAgentGraph.js +0 -1092
  29. package/src/graphs/__tests__/structured-output.integration.test.js +0 -624
  30. package/src/graphs/__tests__/structured-output.test.js +0 -144
  31. package/src/graphs/contextManagement.e2e.test.js +0 -718
  32. package/src/graphs/contextManagement.test.js +0 -485
  33. package/src/graphs/handoffValidation.test.js +0 -276
  34. package/src/graphs/index.js +0 -3
  35. package/src/index.js +0 -28
  36. package/src/instrumentation.js +0 -21
  37. package/src/llm/anthropic/index.js +0 -319
  38. package/src/llm/anthropic/types.js +0 -46
  39. package/src/llm/anthropic/utils/message_inputs.js +0 -627
  40. package/src/llm/anthropic/utils/message_outputs.js +0 -290
  41. package/src/llm/anthropic/utils/output_parsers.js +0 -89
  42. package/src/llm/anthropic/utils/tools.js +0 -25
  43. package/src/llm/bedrock/__tests__/bedrock-caching.test.js +0 -392
  44. package/src/llm/bedrock/index.js +0 -303
  45. package/src/llm/bedrock/types.js +0 -2
  46. package/src/llm/bedrock/utils/index.js +0 -6
  47. package/src/llm/bedrock/utils/message_inputs.js +0 -463
  48. package/src/llm/bedrock/utils/message_outputs.js +0 -269
  49. package/src/llm/fake.js +0 -92
  50. package/src/llm/google/index.js +0 -215
  51. package/src/llm/google/types.js +0 -12
  52. package/src/llm/google/utils/common.js +0 -670
  53. package/src/llm/google/utils/tools.js +0 -111
  54. package/src/llm/google/utils/zod_to_genai_parameters.js +0 -47
  55. package/src/llm/openai/index.js +0 -1033
  56. package/src/llm/openai/types.js +0 -2
  57. package/src/llm/openai/utils/index.js +0 -756
  58. package/src/llm/openai/utils/isReasoningModel.test.js +0 -79
  59. package/src/llm/openrouter/index.js +0 -261
  60. package/src/llm/openrouter/reasoning.test.js +0 -181
  61. package/src/llm/providers.js +0 -36
  62. package/src/llm/text.js +0 -65
  63. package/src/llm/vertexai/index.js +0 -402
  64. package/src/messages/__tests__/tools.test.js +0 -392
  65. package/src/messages/cache.js +0 -404
  66. package/src/messages/cache.test.js +0 -1167
  67. package/src/messages/content.js +0 -48
  68. package/src/messages/content.test.js +0 -314
  69. package/src/messages/core.js +0 -359
  70. package/src/messages/ensureThinkingBlock.test.js +0 -997
  71. package/src/messages/format.js +0 -973
  72. package/src/messages/formatAgentMessages.test.js +0 -2278
  73. package/src/messages/formatAgentMessages.tools.test.js +0 -362
  74. package/src/messages/formatMessage.test.js +0 -608
  75. package/src/messages/ids.js +0 -18
  76. package/src/messages/index.js +0 -9
  77. package/src/messages/labelContentByAgent.test.js +0 -725
  78. package/src/messages/prune.js +0 -438
  79. package/src/messages/reducer.js +0 -60
  80. package/src/messages/shiftIndexTokenCountMap.test.js +0 -63
  81. package/src/messages/summarize.js +0 -146
  82. package/src/messages/summarize.test.js +0 -332
  83. package/src/messages/tools.js +0 -90
  84. package/src/mockStream.js +0 -81
  85. package/src/prompts/collab.js +0 -7
  86. package/src/prompts/index.js +0 -3
  87. package/src/prompts/taskmanager.js +0 -58
  88. package/src/run.js +0 -427
  89. package/src/schemas/index.js +0 -3
  90. package/src/schemas/schema-preparation.test.js +0 -370
  91. package/src/schemas/validate.js +0 -314
  92. package/src/schemas/validate.test.js +0 -264
  93. package/src/scripts/abort.js +0 -127
  94. package/src/scripts/ant_web_search.js +0 -130
  95. package/src/scripts/ant_web_search_edge_case.js +0 -133
  96. package/src/scripts/ant_web_search_error_edge_case.js +0 -119
  97. package/src/scripts/args.js +0 -41
  98. package/src/scripts/bedrock-cache-debug.js +0 -186
  99. package/src/scripts/bedrock-content-aggregation-test.js +0 -195
  100. package/src/scripts/bedrock-merge-test.js +0 -80
  101. package/src/scripts/bedrock-parallel-tools-test.js +0 -150
  102. package/src/scripts/caching.js +0 -106
  103. package/src/scripts/cli.js +0 -152
  104. package/src/scripts/cli2.js +0 -119
  105. package/src/scripts/cli3.js +0 -163
  106. package/src/scripts/cli4.js +0 -165
  107. package/src/scripts/cli5.js +0 -165
  108. package/src/scripts/code_exec.js +0 -171
  109. package/src/scripts/code_exec_files.js +0 -180
  110. package/src/scripts/code_exec_multi_session.js +0 -185
  111. package/src/scripts/code_exec_ptc.js +0 -265
  112. package/src/scripts/code_exec_session.js +0 -217
  113. package/src/scripts/code_exec_simple.js +0 -120
  114. package/src/scripts/content.js +0 -111
  115. package/src/scripts/empty_input.js +0 -125
  116. package/src/scripts/handoff-test.js +0 -96
  117. package/src/scripts/image.js +0 -138
  118. package/src/scripts/memory.js +0 -83
  119. package/src/scripts/multi-agent-chain.js +0 -271
  120. package/src/scripts/multi-agent-conditional.js +0 -185
  121. package/src/scripts/multi-agent-document-review-chain.js +0 -171
  122. package/src/scripts/multi-agent-hybrid-flow.js +0 -264
  123. package/src/scripts/multi-agent-parallel-start.js +0 -214
  124. package/src/scripts/multi-agent-parallel.js +0 -346
  125. package/src/scripts/multi-agent-sequence.js +0 -184
  126. package/src/scripts/multi-agent-supervisor.js +0 -324
  127. package/src/scripts/multi-agent-test.js +0 -147
  128. package/src/scripts/parallel-asymmetric-tools-test.js +0 -202
  129. package/src/scripts/parallel-full-metadata-test.js +0 -176
  130. package/src/scripts/parallel-tools-test.js +0 -256
  131. package/src/scripts/programmatic_exec.js +0 -277
  132. package/src/scripts/programmatic_exec_agent.js +0 -168
  133. package/src/scripts/search.js +0 -118
  134. package/src/scripts/sequential-full-metadata-test.js +0 -143
  135. package/src/scripts/simple.js +0 -174
  136. package/src/scripts/single-agent-metadata-test.js +0 -152
  137. package/src/scripts/stream.js +0 -113
  138. package/src/scripts/test-custom-prompt-key.js +0 -132
  139. package/src/scripts/test-handoff-input.js +0 -143
  140. package/src/scripts/test-handoff-preamble.js +0 -227
  141. package/src/scripts/test-handoff-steering.js +0 -353
  142. package/src/scripts/test-multi-agent-list-handoff.js +0 -318
  143. package/src/scripts/test-parallel-agent-labeling.js +0 -253
  144. package/src/scripts/test-parallel-handoffs.js +0 -229
  145. package/src/scripts/test-thinking-handoff-bedrock.js +0 -132
  146. package/src/scripts/test-thinking-handoff.js +0 -132
  147. package/src/scripts/test-thinking-to-thinking-handoff-bedrock.js +0 -140
  148. package/src/scripts/test-tool-before-handoff-role-order.js +0 -223
  149. package/src/scripts/test-tools-before-handoff.js +0 -187
  150. package/src/scripts/test_code_api.js +0 -263
  151. package/src/scripts/thinking-bedrock.js +0 -128
  152. package/src/scripts/thinking-vertexai.js +0 -130
  153. package/src/scripts/thinking.js +0 -134
  154. package/src/scripts/tool_search.js +0 -114
  155. package/src/scripts/tools.js +0 -125
  156. package/src/specs/agent-handoffs-bedrock.integration.test.js +0 -280
  157. package/src/specs/agent-handoffs.test.js +0 -924
  158. package/src/specs/anthropic.simple.test.js +0 -287
  159. package/src/specs/azure.simple.test.js +0 -381
  160. package/src/specs/cache.simple.test.js +0 -282
  161. package/src/specs/custom-event-await.test.js +0 -148
  162. package/src/specs/deepseek.simple.test.js +0 -189
  163. package/src/specs/emergency-prune.test.js +0 -308
  164. package/src/specs/moonshot.simple.test.js +0 -237
  165. package/src/specs/observability.integration.test.js +0 -1337
  166. package/src/specs/openai.simple.test.js +0 -233
  167. package/src/specs/openrouter.simple.test.js +0 -202
  168. package/src/specs/prune.test.js +0 -733
  169. package/src/specs/reasoning.test.js +0 -144
  170. package/src/specs/spec.utils.js +0 -4
  171. package/src/specs/thinking-handoff.test.js +0 -486
  172. package/src/specs/thinking-prune.test.js +0 -600
  173. package/src/specs/token-distribution-edge-case.test.js +0 -246
  174. package/src/specs/token-memoization.test.js +0 -32
  175. package/src/specs/tokens.test.js +0 -49
  176. package/src/specs/tool-error.test.js +0 -139
  177. package/src/splitStream.js +0 -204
  178. package/src/splitStream.test.js +0 -504
  179. package/src/stream.js +0 -650
  180. package/src/stream.test.js +0 -225
  181. package/src/test/mockTools.js +0 -340
  182. package/src/tools/BrowserTools.js +0 -245
  183. package/src/tools/Calculator.js +0 -38
  184. package/src/tools/Calculator.test.js +0 -225
  185. package/src/tools/CodeExecutor.js +0 -233
  186. package/src/tools/ProgrammaticToolCalling.js +0 -602
  187. package/src/tools/StreamingToolCallBuffer.js +0 -179
  188. package/src/tools/ToolNode.js +0 -930
  189. package/src/tools/ToolSearch.js +0 -904
  190. package/src/tools/__tests__/BrowserTools.test.js +0 -306
  191. package/src/tools/__tests__/ProgrammaticToolCalling.integration.test.js +0 -276
  192. package/src/tools/__tests__/ProgrammaticToolCalling.test.js +0 -807
  193. package/src/tools/__tests__/StreamingToolCallBuffer.test.js +0 -175
  194. package/src/tools/__tests__/ToolApproval.test.js +0 -675
  195. package/src/tools/__tests__/ToolNode.recovery.test.js +0 -200
  196. package/src/tools/__tests__/ToolNode.session.test.js +0 -319
  197. package/src/tools/__tests__/ToolSearch.integration.test.js +0 -125
  198. package/src/tools/__tests__/ToolSearch.test.js +0 -812
  199. package/src/tools/__tests__/handlers.test.js +0 -799
  200. package/src/tools/__tests__/truncation-recovery.integration.test.js +0 -362
  201. package/src/tools/handlers.js +0 -306
  202. package/src/tools/schema.js +0 -25
  203. package/src/tools/search/anthropic.js +0 -34
  204. package/src/tools/search/content.js +0 -116
  205. package/src/tools/search/content.test.js +0 -133
  206. package/src/tools/search/firecrawl.js +0 -173
  207. package/src/tools/search/format.js +0 -198
  208. package/src/tools/search/highlights.js +0 -241
  209. package/src/tools/search/index.js +0 -3
  210. package/src/tools/search/jina-reranker.test.js +0 -106
  211. package/src/tools/search/rerankers.js +0 -165
  212. package/src/tools/search/schema.js +0 -102
  213. package/src/tools/search/search.js +0 -561
  214. package/src/tools/search/serper-scraper.js +0 -126
  215. package/src/tools/search/test.js +0 -129
  216. package/src/tools/search/tool.js +0 -453
  217. package/src/tools/search/types.js +0 -2
  218. package/src/tools/search/utils.js +0 -59
  219. package/src/types/graph.js +0 -24
  220. package/src/types/graph.test.js +0 -192
  221. package/src/types/index.js +0 -7
  222. package/src/types/llm.js +0 -2
  223. package/src/types/messages.js +0 -2
  224. package/src/types/run.js +0 -2
  225. package/src/types/stream.js +0 -2
  226. package/src/types/tools.js +0 -2
  227. package/src/utils/contextAnalytics.js +0 -79
  228. package/src/utils/contextAnalytics.test.js +0 -166
  229. package/src/utils/events.js +0 -26
  230. package/src/utils/graph.js +0 -11
  231. package/src/utils/handlers.js +0 -65
  232. package/src/utils/index.js +0 -10
  233. package/src/utils/llm.js +0 -21
  234. package/src/utils/llmConfig.js +0 -205
  235. package/src/utils/logging.js +0 -37
  236. package/src/utils/misc.js +0 -51
  237. package/src/utils/run.js +0 -69
  238. package/src/utils/schema.js +0 -21
  239. package/src/utils/title.js +0 -119
  240. package/src/utils/tokens.js +0 -92
  241. package/src/utils/toonFormat.js +0 -379
@@ -1,129 +0,0 @@
1
- /* eslint-disable no-console */
2
- // processWikipedia.ts
3
- import * as fs from 'fs';
4
- import * as path from 'path';
5
- import { processContent } from './content';
6
- /**
7
- * Process a Wikipedia article (HTML and Markdown) and create a referenced version
8
- */
9
- async function processWikipediaArticle() {
10
- try {
11
- console.log('Starting Wikipedia article processing...');
12
- // Define file paths - adapt these to your specific file locations
13
- const htmlPath = path.resolve('./test.html');
14
- const markdownPath = path.resolve('./test.md');
15
- const outputPath = path.resolve('./output.md');
16
- // Check if input files exist
17
- if (!fs.existsSync(htmlPath)) {
18
- throw new Error(`Wikipedia HTML file not found at ${htmlPath}`);
19
- }
20
- if (!fs.existsSync(markdownPath)) {
21
- throw new Error(`Wikipedia Markdown file not found at ${markdownPath}`);
22
- }
23
- console.log('Reading Wikipedia article files...');
24
- const html = fs.readFileSync(htmlPath, 'utf-8');
25
- const markdown = fs.readFileSync(markdownPath, 'utf-8');
26
- // Extract article title for logging
27
- const titleMatch = /<h1[^>]*>([^<]+)<\/h1>/i.exec(html);
28
- const articleTitle = titleMatch
29
- ? titleMatch[1].trim()
30
- : 'Wikipedia article';
31
- console.log(`Processing "${articleTitle}"...`);
32
- // Measure processing time
33
- const startTime = process.hrtime();
34
- // Process content
35
- const result = processContent(html, markdown);
36
- // Calculate processing time
37
- const elapsed = process.hrtime(startTime);
38
- const timeInMs = elapsed[0] * 1000 + elapsed[1] / 1000000;
39
- // Generate reference appendix
40
- const appendix = generateReferenceAppendix(result);
41
- // Create complete output with the processed content and appendix
42
- const completeOutput = result.markdown + appendix;
43
- // Write to output file
44
- fs.writeFileSync(outputPath, completeOutput);
45
- // Print processing statistics
46
- console.log('\nWikipedia article processing complete! ✓');
47
- console.log('-'.repeat(60));
48
- console.log(`Article: ${articleTitle}`);
49
- console.log(`Processing time: ${timeInMs.toFixed(2)}ms`);
50
- console.log('Media references replaced:');
51
- console.log(` - Links: ${result.links.length}`);
52
- console.log(` - Images: ${result.images.length}`);
53
- console.log(` - Videos: ${result.videos.length}`);
54
- console.log(` - Total: ${result.links.length + result.images.length + result.videos.length}`);
55
- console.log(`Output saved to: ${outputPath}`);
56
- console.log('-'.repeat(60));
57
- // Print sample of the transformation
58
- const sampleLines = result.markdown.split('\n').slice(0, 10).join('\n');
59
- console.log('\nSample of transformed content:');
60
- console.log('-'.repeat(30));
61
- console.log(sampleLines);
62
- console.log('-'.repeat(30));
63
- console.log('... (continued in output file)');
64
- }
65
- catch (error) {
66
- console.error('Error processing Wikipedia article:', error);
67
- process.exit(1);
68
- }
69
- }
70
- /**
71
- * Generate a comprehensive reference appendix with all media links
72
- */
73
- function generateReferenceAppendix(result) {
74
- let appendix = '\n\n' + '---'.repeat(10) + '\n\n';
75
- appendix += '# References\n\n';
76
- if (result.links.length > 0) {
77
- appendix += '## Links\n\n';
78
- result.links.forEach((link, index) => {
79
- // Clean and format text for display
80
- let displayText = '';
81
- if (link.text != null && link.text.trim()) {
82
- // Limit length for very long link text
83
- let cleanText = link.text.trim();
84
- if (cleanText.length > 50) {
85
- cleanText = cleanText.substring(0, 47) + '...';
86
- }
87
- displayText = ` - "${cleanText}"`;
88
- }
89
- appendix += `**link#${index + 1}**: ${link.originalUrl}${displayText}\n\n`;
90
- });
91
- }
92
- if (result.images.length > 0) {
93
- appendix += '## Images\n\n';
94
- result.images.forEach((image, index) => {
95
- const displayTitle = image.title != null && image.title.trim()
96
- ? ` - ${image.title.trim()}`
97
- : '';
98
- appendix += `**image#${index + 1}**: ${image.originalUrl}${displayTitle}\n\n`;
99
- });
100
- }
101
- if (result.videos.length > 0) {
102
- appendix += '## Videos\n\n';
103
- result.videos.forEach((video, index) => {
104
- const displayTitle = video.title != null && video.title.trim()
105
- ? ` - ${video.title.trim()}`
106
- : '';
107
- appendix += `**video#${index + 1}**: ${video.originalUrl}${displayTitle}\n\n`;
108
- });
109
- }
110
- // Add a category breakdown to show what types of links were found
111
- const totalRefs = result.links.length + result.images.length + result.videos.length;
112
- appendix += '## Summary\n\n';
113
- appendix += `Total references: **${totalRefs}**\n\n`;
114
- appendix += `- Links: ${result.links.length}\n`;
115
- appendix += `- Images: ${result.images.length}\n`;
116
- appendix += `- Videos: ${result.videos.length}\n`;
117
- return appendix;
118
- }
119
- // Using async IIFE to allow for better error handling
120
- (async () => {
121
- try {
122
- await processWikipediaArticle();
123
- }
124
- catch (error) {
125
- console.error('Unhandled error:', error);
126
- process.exit(1);
127
- }
128
- })();
129
- //# sourceMappingURL=test.js.map
@@ -1,453 +0,0 @@
1
- import { tool } from '@langchain/core/tools';
2
- import { countrySchema, imagesSchema, videosSchema, querySchema, dateSchema, newsSchema, } from './schema';
3
- import { createSearchAPI, createSourceProcessor } from './search';
4
- import { createSerperScraper } from './serper-scraper';
5
- import { createFirecrawlScraper } from './firecrawl';
6
- import { expandHighlights } from './highlights';
7
- import { formatResultsForLLM } from './format';
8
- import { createDefaultLogger } from './utils';
9
- import { createReranker } from './rerankers';
10
- import { Constants } from '@/common';
11
- /**
12
- * URL regex pattern to detect direct URLs in query
13
- */
14
- const URL_PATTERN = /https?:\/\/[^\s<>"{}|\\^`[\]]+/gi;
15
- /**
16
- * Extracts URLs from a query string
17
- * @param query - The search query
18
- * @returns Array of URLs found in the query
19
- */
20
- function extractUrlsFromQuery(query) {
21
- const matches = query.match(URL_PATTERN);
22
- return matches ?? [];
23
- }
24
- /**
25
- * Checks if the query is primarily a URL request (contains URL and minimal other text)
26
- * @param query - The search query
27
- * @returns True if the query appears to be a direct URL request
28
- */
29
- function isDirectUrlRequest(query) {
30
- const urls = extractUrlsFromQuery(query);
31
- if (urls.length === 0) {
32
- return false;
33
- }
34
- // Remove URLs from query and check remaining text
35
- let remainingText = query;
36
- for (const url of urls) {
37
- remainingText = remainingText.replace(url, '');
38
- }
39
- // Clean up and check if remaining text is minimal (just filler words or questions about the URL)
40
- remainingText = remainingText.trim().toLowerCase();
41
- // If very little text remains, it's likely a direct URL request
42
- if (remainingText.length < 50) {
43
- return true;
44
- }
45
- return false;
46
- }
47
- /**
48
- * Directly extracts content from URLs using the scraper
49
- * @param urls - URLs to extract content from
50
- * @param scraper - The scraper instance to use
51
- * @param logger - Logger instance
52
- * @returns Search result with extracted content
53
- */
54
- async function extractDirectUrlContent({ urls, scraper, logger, }) {
55
- try {
56
- const results = [];
57
- for (const url of urls) {
58
- try {
59
- logger.debug(`Direct URL extraction: ${url}`);
60
- const [, response] = await scraper.scrapeUrl(url);
61
- if (response.success && response.data) {
62
- const [content, references] = scraper.extractContent(response);
63
- const metadata = scraper.extractMetadata(response);
64
- // Helper to safely extract string from metadata
65
- const getString = (value) => {
66
- return typeof value === 'string' ? value : undefined;
67
- };
68
- results.push({
69
- position: results.length + 1,
70
- title: getString(metadata.title) ?? getString(metadata.ogTitle) ?? url,
71
- link: url,
72
- snippet: getString(metadata.description) ??
73
- getString(metadata.ogDescription) ??
74
- '',
75
- content: content,
76
- references: references,
77
- processed: true,
78
- });
79
- }
80
- else {
81
- logger.warn(`Failed to extract content from ${url}: ${response.error}`);
82
- // Still add the URL as a result, but without content
83
- results.push({
84
- position: results.length + 1,
85
- title: url,
86
- link: url,
87
- snippet: response.error ?? 'Failed to extract content',
88
- processed: false,
89
- });
90
- }
91
- }
92
- catch (error) {
93
- logger.error(`Error extracting URL ${url}:`, error);
94
- results.push({
95
- position: results.length + 1,
96
- title: url,
97
- link: url,
98
- snippet: error instanceof Error ? error.message : String(error),
99
- processed: false,
100
- });
101
- }
102
- }
103
- return {
104
- success: true,
105
- data: {
106
- organic: results,
107
- topStories: [],
108
- images: [],
109
- videos: [],
110
- relatedSearches: [],
111
- },
112
- };
113
- }
114
- catch (error) {
115
- logger.error('Error in direct URL extraction:', error);
116
- return {
117
- success: false,
118
- error: error instanceof Error ? error.message : String(error),
119
- };
120
- }
121
- }
122
- /**
123
- * Executes parallel searches and merges the results
124
- */
125
- async function executeParallelSearches({ searchAPI, query, date, country, safeSearch, images, videos, news, logger, }) {
126
- // Prepare all search tasks to run in parallel
127
- const searchTasks = [
128
- // Main search
129
- searchAPI.getSources({
130
- query,
131
- date,
132
- country,
133
- safeSearch,
134
- }),
135
- ];
136
- if (images) {
137
- searchTasks.push(searchAPI
138
- .getSources({
139
- query,
140
- date,
141
- country,
142
- safeSearch,
143
- type: 'images',
144
- })
145
- .catch((error) => {
146
- logger.error('Error fetching images:', error);
147
- return {
148
- success: false,
149
- error: `Images search failed: ${error instanceof Error ? error.message : String(error)}`,
150
- };
151
- }));
152
- }
153
- if (videos) {
154
- searchTasks.push(searchAPI
155
- .getSources({
156
- query,
157
- date,
158
- country,
159
- safeSearch,
160
- type: 'videos',
161
- })
162
- .catch((error) => {
163
- logger.error('Error fetching videos:', error);
164
- return {
165
- success: false,
166
- error: `Videos search failed: ${error instanceof Error ? error.message : String(error)}`,
167
- };
168
- }));
169
- }
170
- if (news) {
171
- searchTasks.push(searchAPI
172
- .getSources({
173
- query,
174
- date,
175
- country,
176
- safeSearch,
177
- type: 'news',
178
- })
179
- .catch((error) => {
180
- logger.error('Error fetching news:', error);
181
- return {
182
- success: false,
183
- error: `News search failed: ${error instanceof Error ? error.message : String(error)}`,
184
- };
185
- }));
186
- }
187
- // Run all searches in parallel
188
- const results = await Promise.all(searchTasks);
189
- // Get the main search result (first result)
190
- const mainResult = results[0];
191
- if (!mainResult.success) {
192
- throw new Error(mainResult.error ?? 'Search failed');
193
- }
194
- // Merge additional results with the main results
195
- const mergedResults = { ...mainResult.data };
196
- // Convert existing news to topStories if present
197
- if (mergedResults.news !== undefined && mergedResults.news.length > 0) {
198
- const existingNewsAsTopStories = mergedResults.news
199
- .filter((newsItem) => newsItem.link !== undefined && newsItem.link !== '')
200
- .map((newsItem) => ({
201
- title: newsItem.title ?? '',
202
- link: newsItem.link ?? '',
203
- source: newsItem.source ?? '',
204
- date: newsItem.date ?? '',
205
- imageUrl: newsItem.imageUrl ?? '',
206
- processed: false,
207
- }));
208
- mergedResults.topStories = [
209
- ...(mergedResults.topStories ?? []),
210
- ...existingNewsAsTopStories,
211
- ];
212
- delete mergedResults.news;
213
- }
214
- results.slice(1).forEach((result) => {
215
- if (result.success && result.data !== undefined) {
216
- if (result.data.images !== undefined && result.data.images.length > 0) {
217
- mergedResults.images = [
218
- ...(mergedResults.images ?? []),
219
- ...result.data.images,
220
- ];
221
- }
222
- if (result.data.videos !== undefined && result.data.videos.length > 0) {
223
- mergedResults.videos = [
224
- ...(mergedResults.videos ?? []),
225
- ...result.data.videos,
226
- ];
227
- }
228
- if (result.data.news !== undefined && result.data.news.length > 0) {
229
- const newsAsTopStories = result.data.news.map((newsItem) => ({
230
- ...newsItem,
231
- link: newsItem.link ?? '',
232
- }));
233
- mergedResults.topStories = [
234
- ...(mergedResults.topStories ?? []),
235
- ...newsAsTopStories,
236
- ];
237
- }
238
- }
239
- });
240
- return { success: true, data: mergedResults };
241
- }
242
- function createSearchProcessor({ searchAPI, safeSearch, sourceProcessor, scraper, onGetHighlights, logger, }) {
243
- return async function ({ query, date, country, proMode = true, maxSources = 5, onSearchResults, images = false, videos = false, news = false, }) {
244
- try {
245
- // Check if query contains direct URLs for extraction
246
- const urls = extractUrlsFromQuery(query);
247
- const isDirectUrl = isDirectUrlRequest(query);
248
- let searchResult;
249
- if (isDirectUrl && urls.length > 0) {
250
- // Direct URL extraction mode - skip search API and extract directly
251
- logger.debug(`Direct URL extraction mode for: ${urls.join(', ')}`);
252
- searchResult = await extractDirectUrlContent({
253
- urls,
254
- scraper,
255
- logger,
256
- });
257
- }
258
- else {
259
- // Normal search mode - execute parallel searches and merge results
260
- searchResult = await executeParallelSearches({
261
- searchAPI,
262
- query,
263
- date,
264
- country,
265
- safeSearch,
266
- images,
267
- videos,
268
- news,
269
- logger,
270
- });
271
- }
272
- onSearchResults?.(searchResult);
273
- const processedSources = await sourceProcessor.processSources({
274
- query,
275
- news,
276
- result: searchResult,
277
- proMode,
278
- onGetHighlights,
279
- numElements: maxSources,
280
- // Skip additional scraping if we already extracted content directly
281
- skipScraping: isDirectUrl,
282
- });
283
- return expandHighlights(processedSources);
284
- }
285
- catch (error) {
286
- logger.error('Error in search:', error);
287
- return {
288
- organic: [],
289
- topStories: [],
290
- images: [],
291
- videos: [],
292
- news: [],
293
- relatedSearches: [],
294
- error: error instanceof Error ? error.message : String(error),
295
- };
296
- }
297
- };
298
- }
299
- function createOnSearchResults({ runnableConfig, onSearchResults, }) {
300
- return function (results) {
301
- if (!onSearchResults) {
302
- return;
303
- }
304
- onSearchResults(results, runnableConfig);
305
- };
306
- }
307
- function createTool({ schema, search, onSearchResults: _onSearchResults, }) {
308
- return tool(async (rawParams, runnableConfig) => {
309
- const params = rawParams;
310
- const { query, date, country: _c, images, videos, news } = params;
311
- const country = typeof _c === 'string' && _c ? _c : undefined;
312
- // Log the incoming query for debugging URL detection
313
- const toolLogger = createDefaultLogger();
314
- toolLogger.debug(`[web_search] Received query: "${query}"`);
315
- const detectedUrls = extractUrlsFromQuery(query);
316
- if (detectedUrls.length > 0) {
317
- toolLogger.debug(`[web_search] Detected URLs in query: ${detectedUrls.join(', ')}`);
318
- }
319
- const searchResult = await search({
320
- query,
321
- date,
322
- country,
323
- images,
324
- videos,
325
- news,
326
- onSearchResults: createOnSearchResults({
327
- runnableConfig,
328
- onSearchResults: _onSearchResults,
329
- }),
330
- });
331
- const turn = runnableConfig.toolCall?.turn ?? 0;
332
- const { output, references } = formatResultsForLLM(turn, searchResult);
333
- const data = { turn, ...searchResult, references };
334
- return [output, { [Constants.WEB_SEARCH]: data }];
335
- }, {
336
- name: Constants.WEB_SEARCH,
337
- description: `Real-time web search and direct URL content extraction. Results have required citation anchors.
338
-
339
- **CAPABILITIES:**
340
- - Search: Query the web for information on any topic
341
- - Direct URL: Fetch and extract content from a specific URL for summarization or analysis
342
-
343
- **CRITICAL - URL HANDLING:**
344
- When user provides a URL (e.g., "summarize https://example.com/article"), you MUST include the FULL URL in the query parameter.
345
- - CORRECT: query = "https://example.com/article" or "summarize https://example.com/article"
346
- - WRONG: query = "example article summary" (do NOT convert URLs to search terms)
347
-
348
- **USAGE:**
349
- - For search: Use concise search terms as query
350
- - For URL extraction: Pass the complete URL in the query field
351
-
352
- Note: Use ONCE per reply unless instructed otherwise.
353
-
354
- Anchors:
355
- - \\ue202turnXtypeY
356
- - X = turn idx, type = 'search' | 'news' | 'image' | 'ref', Y = item idx
357
-
358
- Special Markers:
359
- - \\ue203...\\ue204 — highlight start/end of cited text (for Standalone or Group citations)
360
- - \\ue200...\\ue201 — group block (e.g. \\ue200\\ue202turn0search1\\ue202turn0news2\\ue201)
361
-
362
- **CITE EVERY NON-OBVIOUS FACT/QUOTE:**
363
- Use anchor marker(s) immediately after the statement:
364
- - Standalone: "Pure functions produce same output. \\ue202turn0search0"
365
- - Standalone (multiple): "Today's News \\ue202turn0search0\\ue202turn0news0"
366
- - Highlight: "\\ue203Highlight text.\\ue204\\ue202turn0news1"
367
- - Group: "Sources. \\ue200\\ue202turn0search0\\ue202turn0news1\\ue201"
368
- - Group Highlight: "\\ue203Highlight for group.\\ue204 \\ue200\\ue202turn0search0\\ue202turn0news1\\ue201"
369
- - Image: "See photo \\ue202turn0image0."
370
-
371
- **NEVER use markdown links, [1], or footnotes. CITE ONLY with anchors provided.**
372
- `.trim(),
373
- schema: schema,
374
- responseFormat: Constants.CONTENT_AND_ARTIFACT,
375
- });
376
- }
377
- export const createSearchTool = (config = {}) => {
378
- const { searchProvider = 'serper', serperApiKey, searxngInstanceUrl, searxngApiKey, rerankerType = 'cohere', topResults = 5, strategies = ['no_extraction'], filterContent = true, safeSearch = 1, scraperProvider = 'firecrawl', firecrawlApiKey, firecrawlApiUrl, firecrawlVersion, firecrawlOptions, serperScraperOptions, scraperTimeout, jinaApiKey, jinaApiUrl, cohereApiKey, onSearchResults: _onSearchResults, onGetHighlights, } = config;
379
- const logger = config.logger || createDefaultLogger();
380
- const schemaProperties = {
381
- query: querySchema,
382
- date: dateSchema,
383
- images: imagesSchema,
384
- videos: videosSchema,
385
- news: newsSchema,
386
- };
387
- if (searchProvider === 'serper') {
388
- schemaProperties.country = countrySchema;
389
- }
390
- const toolSchema = {
391
- type: 'object',
392
- properties: schemaProperties,
393
- required: ['query'],
394
- };
395
- const searchAPI = createSearchAPI({
396
- searchProvider,
397
- serperApiKey,
398
- searxngInstanceUrl,
399
- searxngApiKey,
400
- });
401
- /** Create scraper based on scraperProvider */
402
- let scraperInstance;
403
- if (scraperProvider === 'serper') {
404
- scraperInstance = createSerperScraper({
405
- ...serperScraperOptions,
406
- apiKey: serperApiKey,
407
- timeout: scraperTimeout ?? serperScraperOptions?.timeout,
408
- logger,
409
- });
410
- }
411
- else {
412
- scraperInstance = createFirecrawlScraper({
413
- ...firecrawlOptions,
414
- apiKey: firecrawlApiKey ?? process.env.FIRECRAWL_API_KEY,
415
- apiUrl: firecrawlApiUrl,
416
- version: firecrawlVersion,
417
- timeout: scraperTimeout ?? firecrawlOptions?.timeout,
418
- formats: firecrawlOptions?.formats ?? ['markdown', 'rawHtml'],
419
- logger,
420
- });
421
- }
422
- const selectedReranker = createReranker({
423
- rerankerType,
424
- jinaApiKey,
425
- jinaApiUrl,
426
- cohereApiKey,
427
- logger,
428
- });
429
- if (!selectedReranker) {
430
- logger.warn('No reranker selected. Using default ranking.');
431
- }
432
- const sourceProcessor = createSourceProcessor({
433
- reranker: selectedReranker,
434
- topResults,
435
- strategies,
436
- filterContent,
437
- logger,
438
- }, scraperInstance);
439
- const search = createSearchProcessor({
440
- searchAPI,
441
- safeSearch,
442
- sourceProcessor,
443
- scraper: scraperInstance,
444
- onGetHighlights,
445
- logger,
446
- });
447
- return createTool({
448
- search,
449
- schema: toolSchema,
450
- onSearchResults: _onSearchResults,
451
- });
452
- };
453
- //# sourceMappingURL=tool.js.map
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=types.js.map
@@ -1,59 +0,0 @@
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
- export 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
- export 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
- export const getDomainName = (link, metadata, logger) => {
24
- try {
25
- const url = metadata?.sourceURL ?? metadata?.url ?? (link || '');
26
- const domain = new URL(url).hostname.replace(/^www\./, '');
27
- if (domain) {
28
- return domain;
29
- }
30
- }
31
- catch (e) {
32
- // URL parsing failed
33
- if (logger) {
34
- logger.error('Error parsing URL:', e);
35
- }
36
- else {
37
- console.error('Error parsing URL:', e);
38
- }
39
- }
40
- return;
41
- };
42
- export function getAttribution(link, metadata, logger) {
43
- if (!metadata)
44
- return getDomainName(link, metadata, logger);
45
- const twitterSite = metadata['twitter:site'];
46
- const twitterSiteFormatted = typeof twitterSite === 'string' ? twitterSite.replace(/^@/, '') : undefined;
47
- const possibleAttributions = [
48
- metadata.ogSiteName,
49
- metadata['og:site_name'],
50
- metadata.title?.split('|').pop()?.trim(),
51
- twitterSiteFormatted,
52
- ];
53
- const attribution = possibleAttributions.find((attr) => attr != null && typeof attr === 'string' && attr.trim() !== '');
54
- if (attribution != null) {
55
- return attribution;
56
- }
57
- return getDomainName(link, metadata, logger);
58
- }
59
- //# sourceMappingURL=utils.js.map
@@ -1,24 +0,0 @@
1
- /**
2
- * Error thrown when the model refuses to produce structured output due to safety policies.
3
- */
4
- export class StructuredOutputRefusalError extends Error {
5
- refusalText;
6
- constructor(refusalText) {
7
- super(`Model refused to produce structured output: ${refusalText}`);
8
- this.refusalText = refusalText;
9
- this.name = 'StructuredOutputRefusalError';
10
- }
11
- }
12
- /**
13
- * Error thrown when the structured output response was truncated due to max_tokens.
14
- */
15
- export class StructuredOutputTruncatedError extends Error {
16
- stopReason;
17
- constructor(stopReason) {
18
- super(`Structured output was truncated (stop_reason: ${stopReason}). ` +
19
- 'Increase max_tokens to allow the full JSON response to be generated.');
20
- this.stopReason = stopReason;
21
- this.name = 'StructuredOutputTruncatedError';
22
- }
23
- }
24
- //# sourceMappingURL=graph.js.map