@librechat/agents 3.1.75 → 3.1.77-dev.1

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 (272) hide show
  1. package/dist/cjs/graphs/Graph.cjs +22 -3
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/hitl/askUserQuestion.cjs +67 -0
  4. package/dist/cjs/hitl/askUserQuestion.cjs.map +1 -0
  5. package/dist/cjs/hooks/HookRegistry.cjs +54 -0
  6. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  7. package/dist/cjs/hooks/createToolPolicyHook.cjs +115 -0
  8. package/dist/cjs/hooks/createToolPolicyHook.cjs.map +1 -0
  9. package/dist/cjs/hooks/executeHooks.cjs +40 -1
  10. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  11. package/dist/cjs/hooks/types.cjs +1 -0
  12. package/dist/cjs/hooks/types.cjs.map +1 -1
  13. package/dist/cjs/langchain/google-common.cjs +3 -0
  14. package/dist/cjs/langchain/google-common.cjs.map +1 -0
  15. package/dist/cjs/langchain/index.cjs +86 -0
  16. package/dist/cjs/langchain/index.cjs.map +1 -0
  17. package/dist/cjs/langchain/language_models/chat_models.cjs +3 -0
  18. package/dist/cjs/langchain/language_models/chat_models.cjs.map +1 -0
  19. package/dist/cjs/langchain/messages/tool.cjs +3 -0
  20. package/dist/cjs/langchain/messages/tool.cjs.map +1 -0
  21. package/dist/cjs/langchain/messages.cjs +51 -0
  22. package/dist/cjs/langchain/messages.cjs.map +1 -0
  23. package/dist/cjs/langchain/openai.cjs +3 -0
  24. package/dist/cjs/langchain/openai.cjs.map +1 -0
  25. package/dist/cjs/langchain/prompts.cjs +11 -0
  26. package/dist/cjs/langchain/prompts.cjs.map +1 -0
  27. package/dist/cjs/langchain/runnables.cjs +19 -0
  28. package/dist/cjs/langchain/runnables.cjs.map +1 -0
  29. package/dist/cjs/langchain/tools.cjs +23 -0
  30. package/dist/cjs/langchain/tools.cjs.map +1 -0
  31. package/dist/cjs/langchain/utils/env.cjs +11 -0
  32. package/dist/cjs/langchain/utils/env.cjs.map +1 -0
  33. package/dist/cjs/llm/anthropic/index.cjs +145 -52
  34. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  35. package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
  36. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +21 -14
  37. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  38. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +84 -70
  39. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  40. package/dist/cjs/llm/bedrock/index.cjs +1 -1
  41. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  42. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +213 -3
  43. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  44. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +2 -1
  45. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
  46. package/dist/cjs/llm/google/utils/common.cjs +5 -4
  47. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  48. package/dist/cjs/llm/openai/index.cjs +519 -655
  49. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  50. package/dist/cjs/llm/openai/utils/index.cjs +20 -458
  51. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  52. package/dist/cjs/llm/openrouter/index.cjs +57 -175
  53. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  54. package/dist/cjs/llm/vertexai/index.cjs +5 -3
  55. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  56. package/dist/cjs/main.cjs +112 -3
  57. package/dist/cjs/main.cjs.map +1 -1
  58. package/dist/cjs/messages/cache.cjs +2 -1
  59. package/dist/cjs/messages/cache.cjs.map +1 -1
  60. package/dist/cjs/messages/core.cjs +7 -6
  61. package/dist/cjs/messages/core.cjs.map +1 -1
  62. package/dist/cjs/messages/format.cjs +73 -15
  63. package/dist/cjs/messages/format.cjs.map +1 -1
  64. package/dist/cjs/messages/langchain.cjs +26 -0
  65. package/dist/cjs/messages/langchain.cjs.map +1 -0
  66. package/dist/cjs/messages/prune.cjs +7 -6
  67. package/dist/cjs/messages/prune.cjs.map +1 -1
  68. package/dist/cjs/run.cjs +400 -42
  69. package/dist/cjs/run.cjs.map +1 -1
  70. package/dist/cjs/tools/ToolNode.cjs +556 -56
  71. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  72. package/dist/cjs/tools/search/search.cjs +55 -66
  73. package/dist/cjs/tools/search/search.cjs.map +1 -1
  74. package/dist/cjs/tools/search/tavily-scraper.cjs +189 -0
  75. package/dist/cjs/tools/search/tavily-scraper.cjs.map +1 -0
  76. package/dist/cjs/tools/search/tavily-search.cjs +372 -0
  77. package/dist/cjs/tools/search/tavily-search.cjs.map +1 -0
  78. package/dist/cjs/tools/search/tool.cjs +26 -4
  79. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  80. package/dist/cjs/tools/search/utils.cjs +10 -3
  81. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  82. package/dist/esm/graphs/Graph.mjs +22 -3
  83. package/dist/esm/graphs/Graph.mjs.map +1 -1
  84. package/dist/esm/hitl/askUserQuestion.mjs +65 -0
  85. package/dist/esm/hitl/askUserQuestion.mjs.map +1 -0
  86. package/dist/esm/hooks/HookRegistry.mjs +54 -0
  87. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  88. package/dist/esm/hooks/createToolPolicyHook.mjs +113 -0
  89. package/dist/esm/hooks/createToolPolicyHook.mjs.map +1 -0
  90. package/dist/esm/hooks/executeHooks.mjs +40 -1
  91. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  92. package/dist/esm/hooks/types.mjs +1 -0
  93. package/dist/esm/hooks/types.mjs.map +1 -1
  94. package/dist/esm/langchain/google-common.mjs +2 -0
  95. package/dist/esm/langchain/google-common.mjs.map +1 -0
  96. package/dist/esm/langchain/index.mjs +5 -0
  97. package/dist/esm/langchain/index.mjs.map +1 -0
  98. package/dist/esm/langchain/language_models/chat_models.mjs +2 -0
  99. package/dist/esm/langchain/language_models/chat_models.mjs.map +1 -0
  100. package/dist/esm/langchain/messages/tool.mjs +2 -0
  101. package/dist/esm/langchain/messages/tool.mjs.map +1 -0
  102. package/dist/esm/langchain/messages.mjs +2 -0
  103. package/dist/esm/langchain/messages.mjs.map +1 -0
  104. package/dist/esm/langchain/openai.mjs +2 -0
  105. package/dist/esm/langchain/openai.mjs.map +1 -0
  106. package/dist/esm/langchain/prompts.mjs +2 -0
  107. package/dist/esm/langchain/prompts.mjs.map +1 -0
  108. package/dist/esm/langchain/runnables.mjs +2 -0
  109. package/dist/esm/langchain/runnables.mjs.map +1 -0
  110. package/dist/esm/langchain/tools.mjs +2 -0
  111. package/dist/esm/langchain/tools.mjs.map +1 -0
  112. package/dist/esm/langchain/utils/env.mjs +2 -0
  113. package/dist/esm/langchain/utils/env.mjs.map +1 -0
  114. package/dist/esm/llm/anthropic/index.mjs +146 -54
  115. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  116. package/dist/esm/llm/anthropic/types.mjs.map +1 -1
  117. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +21 -14
  118. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  119. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +84 -71
  120. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  121. package/dist/esm/llm/bedrock/index.mjs +1 -1
  122. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  123. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +214 -4
  124. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  125. package/dist/esm/llm/bedrock/utils/message_outputs.mjs +2 -1
  126. package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
  127. package/dist/esm/llm/google/utils/common.mjs +5 -4
  128. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  129. package/dist/esm/llm/openai/index.mjs +520 -656
  130. package/dist/esm/llm/openai/index.mjs.map +1 -1
  131. package/dist/esm/llm/openai/utils/index.mjs +23 -459
  132. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  133. package/dist/esm/llm/openrouter/index.mjs +57 -175
  134. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  135. package/dist/esm/llm/vertexai/index.mjs +5 -3
  136. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  137. package/dist/esm/main.mjs +7 -0
  138. package/dist/esm/main.mjs.map +1 -1
  139. package/dist/esm/messages/cache.mjs +2 -1
  140. package/dist/esm/messages/cache.mjs.map +1 -1
  141. package/dist/esm/messages/core.mjs +7 -6
  142. package/dist/esm/messages/core.mjs.map +1 -1
  143. package/dist/esm/messages/format.mjs +73 -15
  144. package/dist/esm/messages/format.mjs.map +1 -1
  145. package/dist/esm/messages/langchain.mjs +23 -0
  146. package/dist/esm/messages/langchain.mjs.map +1 -0
  147. package/dist/esm/messages/prune.mjs +7 -6
  148. package/dist/esm/messages/prune.mjs.map +1 -1
  149. package/dist/esm/run.mjs +400 -42
  150. package/dist/esm/run.mjs.map +1 -1
  151. package/dist/esm/tools/ToolNode.mjs +557 -57
  152. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  153. package/dist/esm/tools/search/search.mjs +55 -66
  154. package/dist/esm/tools/search/search.mjs.map +1 -1
  155. package/dist/esm/tools/search/tavily-scraper.mjs +186 -0
  156. package/dist/esm/tools/search/tavily-scraper.mjs.map +1 -0
  157. package/dist/esm/tools/search/tavily-search.mjs +370 -0
  158. package/dist/esm/tools/search/tavily-search.mjs.map +1 -0
  159. package/dist/esm/tools/search/tool.mjs +26 -4
  160. package/dist/esm/tools/search/tool.mjs.map +1 -1
  161. package/dist/esm/tools/search/utils.mjs +10 -3
  162. package/dist/esm/tools/search/utils.mjs.map +1 -1
  163. package/dist/types/graphs/Graph.d.ts +7 -0
  164. package/dist/types/hitl/askUserQuestion.d.ts +55 -0
  165. package/dist/types/hitl/index.d.ts +6 -0
  166. package/dist/types/hooks/HookRegistry.d.ts +58 -0
  167. package/dist/types/hooks/createToolPolicyHook.d.ts +87 -0
  168. package/dist/types/hooks/index.d.ts +4 -1
  169. package/dist/types/hooks/types.d.ts +109 -3
  170. package/dist/types/index.d.ts +10 -0
  171. package/dist/types/langchain/google-common.d.ts +1 -0
  172. package/dist/types/langchain/index.d.ts +8 -0
  173. package/dist/types/langchain/language_models/chat_models.d.ts +1 -0
  174. package/dist/types/langchain/messages/tool.d.ts +1 -0
  175. package/dist/types/langchain/messages.d.ts +2 -0
  176. package/dist/types/langchain/openai.d.ts +1 -0
  177. package/dist/types/langchain/prompts.d.ts +1 -0
  178. package/dist/types/langchain/runnables.d.ts +2 -0
  179. package/dist/types/langchain/tools.d.ts +2 -0
  180. package/dist/types/langchain/utils/env.d.ts +1 -0
  181. package/dist/types/llm/anthropic/index.d.ts +22 -9
  182. package/dist/types/llm/anthropic/types.d.ts +5 -1
  183. package/dist/types/llm/anthropic/utils/message_outputs.d.ts +13 -6
  184. package/dist/types/llm/anthropic/utils/output_parsers.d.ts +1 -1
  185. package/dist/types/llm/openai/index.d.ts +21 -24
  186. package/dist/types/llm/openrouter/index.d.ts +11 -9
  187. package/dist/types/llm/vertexai/index.d.ts +1 -0
  188. package/dist/types/messages/cache.d.ts +4 -1
  189. package/dist/types/messages/format.d.ts +4 -1
  190. package/dist/types/messages/langchain.d.ts +27 -0
  191. package/dist/types/run.d.ts +117 -1
  192. package/dist/types/tools/ToolNode.d.ts +26 -1
  193. package/dist/types/tools/search/tavily-scraper.d.ts +19 -0
  194. package/dist/types/tools/search/tavily-search.d.ts +4 -0
  195. package/dist/types/tools/search/types.d.ts +99 -5
  196. package/dist/types/tools/search/utils.d.ts +2 -2
  197. package/dist/types/types/graph.d.ts +23 -37
  198. package/dist/types/types/hitl.d.ts +272 -0
  199. package/dist/types/types/index.d.ts +1 -0
  200. package/dist/types/types/llm.d.ts +3 -3
  201. package/dist/types/types/run.d.ts +33 -0
  202. package/dist/types/types/stream.d.ts +1 -1
  203. package/dist/types/types/tools.d.ts +19 -0
  204. package/package.json +80 -17
  205. package/src/graphs/Graph.ts +33 -4
  206. package/src/graphs/__tests__/composition.smoke.test.ts +188 -0
  207. package/src/hitl/askUserQuestion.ts +72 -0
  208. package/src/hitl/index.ts +7 -0
  209. package/src/hooks/HookRegistry.ts +71 -0
  210. package/src/hooks/__tests__/createToolPolicyHook.test.ts +259 -0
  211. package/src/hooks/createToolPolicyHook.ts +184 -0
  212. package/src/hooks/executeHooks.ts +50 -1
  213. package/src/hooks/index.ts +6 -0
  214. package/src/hooks/types.ts +112 -0
  215. package/src/index.ts +22 -0
  216. package/src/langchain/google-common.ts +1 -0
  217. package/src/langchain/index.ts +8 -0
  218. package/src/langchain/language_models/chat_models.ts +1 -0
  219. package/src/langchain/messages/tool.ts +5 -0
  220. package/src/langchain/messages.ts +21 -0
  221. package/src/langchain/openai.ts +1 -0
  222. package/src/langchain/prompts.ts +1 -0
  223. package/src/langchain/runnables.ts +7 -0
  224. package/src/langchain/tools.ts +8 -0
  225. package/src/langchain/utils/env.ts +1 -0
  226. package/src/llm/anthropic/index.ts +252 -84
  227. package/src/llm/anthropic/llm.spec.ts +751 -102
  228. package/src/llm/anthropic/types.ts +9 -1
  229. package/src/llm/anthropic/utils/message_inputs.ts +37 -19
  230. package/src/llm/anthropic/utils/message_outputs.ts +119 -101
  231. package/src/llm/bedrock/index.ts +2 -2
  232. package/src/llm/bedrock/llm.spec.ts +341 -0
  233. package/src/llm/bedrock/utils/message_inputs.ts +303 -4
  234. package/src/llm/bedrock/utils/message_outputs.ts +2 -1
  235. package/src/llm/custom-chat-models.smoke.test.ts +836 -0
  236. package/src/llm/google/llm.spec.ts +339 -57
  237. package/src/llm/google/utils/common.ts +53 -48
  238. package/src/llm/openai/contentBlocks.test.ts +346 -0
  239. package/src/llm/openai/index.ts +856 -833
  240. package/src/llm/openai/utils/index.ts +107 -78
  241. package/src/llm/openai/utils/messages.test.ts +159 -0
  242. package/src/llm/openrouter/index.ts +124 -247
  243. package/src/llm/openrouter/reasoning.test.ts +8 -1
  244. package/src/llm/vertexai/index.ts +11 -5
  245. package/src/llm/vertexai/llm.spec.ts +28 -1
  246. package/src/messages/cache.test.ts +4 -3
  247. package/src/messages/cache.ts +3 -2
  248. package/src/messages/core.ts +16 -9
  249. package/src/messages/format.ts +96 -16
  250. package/src/messages/formatAgentMessages.test.ts +166 -1
  251. package/src/messages/langchain.ts +39 -0
  252. package/src/messages/prune.ts +12 -8
  253. package/src/run.ts +456 -47
  254. package/src/scripts/caching.ts +2 -3
  255. package/src/specs/summarization.test.ts +51 -58
  256. package/src/tools/ToolNode.ts +706 -63
  257. package/src/tools/__tests__/hitl.test.ts +3593 -0
  258. package/src/tools/search/search.ts +83 -73
  259. package/src/tools/search/tavily-scraper.ts +235 -0
  260. package/src/tools/search/tavily-search.ts +424 -0
  261. package/src/tools/search/tavily.test.ts +965 -0
  262. package/src/tools/search/tool.ts +36 -26
  263. package/src/tools/search/types.ts +133 -8
  264. package/src/tools/search/utils.ts +13 -5
  265. package/src/types/graph.ts +32 -87
  266. package/src/types/hitl.ts +303 -0
  267. package/src/types/index.ts +1 -0
  268. package/src/types/llm.ts +3 -3
  269. package/src/types/run.ts +33 -0
  270. package/src/types/stream.ts +1 -1
  271. package/src/types/tools.ts +19 -0
  272. package/src/utils/llmConfig.ts +1 -6
@@ -14,6 +14,7 @@ import {
14
14
  } from './schema';
15
15
  import { createSearchAPI, createSourceProcessor } from './search';
16
16
  import { createSerperScraper } from './serper-scraper';
17
+ import { createTavilyScraper } from './tavily-scraper';
17
18
  import { createFirecrawlScraper } from './firecrawl';
18
19
  import { expandHighlights } from './highlights';
19
20
  import { formatResultsForLLM } from './format';
@@ -178,11 +179,13 @@ async function executeParallelSearches({
178
179
  function createSearchProcessor({
179
180
  searchAPI,
180
181
  safeSearch,
182
+ supportsVideos,
181
183
  sourceProcessor,
182
184
  onGetHighlights,
183
185
  logger,
184
186
  }: {
185
187
  safeSearch: t.SearchToolConfig['safeSearch'];
188
+ supportsVideos: boolean;
186
189
  searchAPI: ReturnType<typeof createSearchAPI>;
187
190
  sourceProcessor: ReturnType<typeof createSourceProcessor>;
188
191
  onGetHighlights: t.SearchToolConfig['onGetHighlights'];
@@ -218,7 +221,7 @@ function createSearchProcessor({
218
221
  country,
219
222
  safeSearch,
220
223
  images,
221
- videos,
224
+ videos: supportsVideos && videos,
222
225
  news,
223
226
  logger,
224
227
  });
@@ -306,32 +309,12 @@ function createTool({
306
309
  }
307
310
 
308
311
  /**
309
- * Creates a search tool with a schema that dynamically includes the country field
310
- * only when the searchProvider is 'serper'.
311
- *
312
- * Supports multiple scraper providers:
313
- * - Firecrawl (default): Full-featured web scraping with multiple formats
314
- * - Serper: Lightweight scraping using Serper's scrape API
315
- *
316
- * @example
317
- * ```typescript
318
- * // Using Firecrawl scraper (default)
319
- * const searchTool = createSearchTool({
320
- * searchProvider: 'serper',
321
- * scraperProvider: 'firecrawl',
322
- * firecrawlApiKey: 'your-firecrawl-key'
323
- * });
312
+ * Creates a search tool with configurable search and scraper providers.
324
313
  *
325
- * // Using Serper scraper
326
- * const searchTool = createSearchTool({
327
- * searchProvider: 'serper',
328
- * scraperProvider: 'serper',
329
- * serperApiKey: 'your-serper-key'
330
- * });
331
- * ```
314
+ * Search providers: Serper (Google results), SearXNG (self-hosted meta-search), Tavily (AI-optimized).
315
+ * Scraper providers: Firecrawl (default, full-featured), Serper (lightweight), Tavily (batch extraction).
332
316
  *
333
- * @param config - The search tool configuration
334
- * @returns A DynamicStructuredTool with a schema that depends on the searchProvider
317
+ * The country schema field is exposed to the LLM for providers that support localized results.
335
318
  */
336
319
  /** Input params type for search tool */
337
320
  interface SearchToolParams {
@@ -351,6 +334,10 @@ export const createSearchTool = (
351
334
  serperApiKey,
352
335
  searxngInstanceUrl,
353
336
  searxngApiKey,
337
+ tavilyApiKey,
338
+ tavilySearchUrl,
339
+ tavilyExtractUrl,
340
+ tavilySearchOptions,
354
341
  rerankerType = 'cohere',
355
342
  topResults = 5,
356
343
  strategies = ['no_extraction'],
@@ -362,6 +349,7 @@ export const createSearchTool = (
362
349
  firecrawlVersion,
363
350
  firecrawlOptions,
364
351
  serperScraperOptions,
352
+ tavilyScraperOptions,
365
353
  scraperTimeout,
366
354
  jinaApiKey,
367
355
  jinaApiUrl,
@@ -371,6 +359,13 @@ export const createSearchTool = (
371
359
  } = config;
372
360
 
373
361
  const logger = config.logger || createDefaultLogger();
362
+ const effectiveTavilySearchOptions =
363
+ searchProvider === 'tavily' && config.safeSearch != null
364
+ ? {
365
+ ...tavilySearchOptions,
366
+ safeSearch: config.safeSearch !== 0,
367
+ }
368
+ : tavilySearchOptions;
374
369
 
375
370
  const schemaProperties: Record<string, unknown> = {
376
371
  query: querySchema,
@@ -380,7 +375,7 @@ export const createSearchTool = (
380
375
  news: newsSchema,
381
376
  };
382
377
 
383
- if (searchProvider === 'serper') {
378
+ if (searchProvider === 'serper' || searchProvider === 'tavily') {
384
379
  schemaProperties.country = countrySchema;
385
380
  }
386
381
 
@@ -395,6 +390,9 @@ export const createSearchTool = (
395
390
  serperApiKey,
396
391
  searxngInstanceUrl,
397
392
  searxngApiKey,
393
+ tavilyApiKey,
394
+ tavilySearchUrl,
395
+ tavilySearchOptions: effectiveTavilySearchOptions,
398
396
  });
399
397
 
400
398
  /** Create scraper based on scraperProvider */
@@ -407,6 +405,17 @@ export const createSearchTool = (
407
405
  timeout: scraperTimeout ?? serperScraperOptions?.timeout,
408
406
  logger,
409
407
  });
408
+ } else if (scraperProvider === 'tavily') {
409
+ scraperInstance = createTavilyScraper({
410
+ ...tavilyScraperOptions,
411
+ apiKey:
412
+ tavilyScraperOptions?.apiKey ??
413
+ tavilyApiKey ??
414
+ process.env.TAVILY_API_KEY,
415
+ apiUrl: tavilyScraperOptions?.apiUrl ?? tavilyExtractUrl,
416
+ timeout: scraperTimeout ?? tavilyScraperOptions?.timeout,
417
+ logger,
418
+ });
410
419
  } else {
411
420
  scraperInstance = createFirecrawlScraper({
412
421
  ...firecrawlOptions,
@@ -445,6 +454,7 @@ export const createSearchTool = (
445
454
  const search = createSearchProcessor({
446
455
  searchAPI,
447
456
  safeSearch,
457
+ supportsVideos: searchProvider !== 'tavily',
448
458
  sourceProcessor,
449
459
  onGetHighlights,
450
460
  logger,
@@ -3,8 +3,8 @@ import type { RunnableConfig } from '@langchain/core/runnables';
3
3
  import type { BaseReranker } from './rerankers';
4
4
  import { DATE_RANGE } from './schema';
5
5
 
6
- export type SearchProvider = 'serper' | 'searxng';
7
- export type ScraperProvider = 'firecrawl' | 'serper';
6
+ export type SearchProvider = 'serper' | 'searxng' | 'tavily';
7
+ export type ScraperProvider = 'firecrawl' | 'serper' | 'tavily';
8
8
  export type RerankerType = 'infinity' | 'jina' | 'cohere' | 'none';
9
9
 
10
10
  export interface Highlight {
@@ -62,11 +62,59 @@ export interface Source {
62
62
  date?: string;
63
63
  }
64
64
 
65
+ export type TavilyTimeRange = 'day' | 'week' | 'month' | 'year';
66
+ export type TavilyTimeRangeInput =
67
+ | TavilyTimeRange
68
+ | 'h'
69
+ | 'd'
70
+ | 'w'
71
+ | 'm'
72
+ | 'y';
73
+
74
+ export interface TavilySearchOptions {
75
+ searchDepth?: 'basic' | 'advanced' | 'fast' | 'ultra-fast';
76
+ maxResults?: number;
77
+ includeImages?: boolean;
78
+ includeAnswer?: boolean | 'basic' | 'advanced';
79
+ includeRawContent?: boolean | 'markdown' | 'text';
80
+ includeDomains?: string[];
81
+ excludeDomains?: string[];
82
+ topic?: 'general' | 'news' | 'finance';
83
+ timeRange?: TavilyTimeRangeInput;
84
+ includeImageDescriptions?: boolean;
85
+ includeFavicon?: boolean;
86
+ chunksPerSource?: number;
87
+ safeSearch?: boolean;
88
+ timeout?: number;
89
+ }
90
+
91
+ export interface TavilySearchPayload {
92
+ query: string;
93
+ search_depth: NonNullable<TavilySearchOptions['searchDepth']>;
94
+ topic: NonNullable<TavilySearchOptions['topic']>;
95
+ max_results: number;
96
+ safe_search?: boolean;
97
+ time_range?: TavilyTimeRange;
98
+ country?: string;
99
+ include_images?: boolean;
100
+ include_answer?: NonNullable<TavilySearchOptions['includeAnswer']>;
101
+ include_raw_content?: NonNullable<TavilySearchOptions['includeRawContent']>;
102
+ include_domains?: string[];
103
+ exclude_domains?: string[];
104
+ include_image_descriptions?: boolean;
105
+ include_favicon?: boolean;
106
+ chunks_per_source?: number;
107
+ }
108
+
65
109
  export interface SearchConfig {
66
110
  searchProvider?: SearchProvider;
67
111
  serperApiKey?: string;
68
112
  searxngInstanceUrl?: string;
69
113
  searxngApiKey?: string;
114
+ tavilyApiKey?: string;
115
+ tavilySearchUrl?: string;
116
+ tavilyExtractUrl?: string;
117
+ tavilySearchOptions?: TavilySearchOptions;
70
118
  }
71
119
 
72
120
  export type References = {
@@ -106,6 +154,17 @@ export interface SerperScraperConfig {
106
154
  includeMarkdown?: boolean;
107
155
  }
108
156
 
157
+ export interface TavilyScraperConfig {
158
+ apiKey?: string;
159
+ apiUrl?: string;
160
+ timeout?: number;
161
+ logger?: Logger;
162
+ extractDepth?: 'basic' | 'advanced';
163
+ includeImages?: boolean;
164
+ includeFavicon?: boolean;
165
+ format?: 'markdown' | 'text';
166
+ }
167
+
109
168
  export interface ScraperContentResult {
110
169
  content: string;
111
170
  }
@@ -154,6 +213,7 @@ export interface SearchToolConfig
154
213
  extends SearchConfig,
155
214
  ProcessSourcesConfig,
156
215
  FirecrawlConfig {
216
+ tavilyScraperOptions?: TavilyScraperConfig;
157
217
  logger?: Logger;
158
218
  safeSearch?: SafeSearchLevel;
159
219
  jinaApiKey?: string;
@@ -181,20 +241,27 @@ export type UsedReferences = {
181
241
  reference: MediaReference;
182
242
  }[];
183
243
 
244
+ export type AnyScraperResponse =
245
+ | FirecrawlScrapeResponse
246
+ | SerperScrapeResponse
247
+ | TavilyScrapeResponse;
248
+
184
249
  /** Base Scraper Interface */
185
250
  export interface BaseScraper {
186
251
  scrapeUrl(
187
252
  url: string,
188
253
  options?: unknown
189
- ): Promise<[string, FirecrawlScrapeResponse | SerperScrapeResponse]>;
254
+ ): Promise<[string, AnyScraperResponse]>;
255
+ scrapeUrls?(
256
+ urls: string[],
257
+ options?: unknown
258
+ ): Promise<Array<[string, AnyScraperResponse]>>;
190
259
  extractContent(
191
- response: FirecrawlScrapeResponse | SerperScrapeResponse
260
+ response: AnyScraperResponse
192
261
  ): [string, undefined | References];
193
262
  extractMetadata(
194
- response: FirecrawlScrapeResponse | SerperScrapeResponse
195
- ):
196
- | ScrapeMetadata
197
- | Record<string, string | number | boolean | null | undefined>;
263
+ response: AnyScraperResponse
264
+ ): ScrapeMetadata | GenericScrapeMetadata;
198
265
  }
199
266
 
200
267
  /** Firecrawl */
@@ -208,6 +275,25 @@ export type SerperScrapeOptions = Omit<
208
275
  'apiKey' | 'apiUrl' | 'logger'
209
276
  >;
210
277
 
278
+ export type TavilyScrapeOptions = Omit<
279
+ TavilyScraperConfig,
280
+ 'apiKey' | 'apiUrl' | 'logger'
281
+ >;
282
+
283
+ export interface TavilyExtractPayload {
284
+ urls: string[];
285
+ extract_depth: NonNullable<TavilyScraperConfig['extractDepth']>;
286
+ include_images: boolean;
287
+ include_favicon?: boolean;
288
+ format?: NonNullable<TavilyScraperConfig['format']>;
289
+ timeout?: number;
290
+ }
291
+
292
+ export type GenericScrapeMetadata = Record<
293
+ string,
294
+ string | number | boolean | null | undefined
295
+ >;
296
+
211
297
  export interface ScrapeMetadata {
212
298
  // Core source information
213
299
  sourceURL?: string;
@@ -294,6 +380,45 @@ export interface SerperScrapeResponse {
294
380
  error?: string;
295
381
  }
296
382
 
383
+ export interface TavilyScrapeResponse {
384
+ success: boolean;
385
+ data?: {
386
+ rawContent?: string;
387
+ images?: string[];
388
+ favicon?: string;
389
+ };
390
+ error?: string;
391
+ }
392
+
393
+ export interface TavilySearchResult {
394
+ title?: string;
395
+ url?: string;
396
+ content?: string;
397
+ score?: number;
398
+ published_date?: string;
399
+ }
400
+
401
+ export type TavilyImageResult =
402
+ | string
403
+ | {
404
+ url?: string;
405
+ description?: string;
406
+ };
407
+
408
+ export interface TavilySearchResponse {
409
+ answer?: string;
410
+ images?: TavilyImageResult[];
411
+ results?: TavilySearchResult[];
412
+ }
413
+
414
+ export interface TavilyExtractResult {
415
+ url: string;
416
+ raw_content?: string;
417
+ images?: string[];
418
+ favicon?: string;
419
+ error?: string;
420
+ }
421
+
297
422
  export interface FirecrawlScraperConfig {
298
423
  apiKey?: string;
299
424
  apiUrl?: string;
@@ -29,11 +29,18 @@ export const fileExtRegex =
29
29
 
30
30
  export const getDomainName = (
31
31
  link: string,
32
- metadata?: t.ScrapeMetadata,
32
+ metadata?: t.ScrapeMetadata | t.GenericScrapeMetadata,
33
33
  logger?: t.Logger
34
34
  ): string | undefined => {
35
35
  try {
36
- const url = metadata?.sourceURL ?? metadata?.url ?? (link || '');
36
+ const sourceUrl = metadata?.sourceURL;
37
+ const metadataUrl = metadata?.url;
38
+ const url =
39
+ typeof sourceUrl === 'string'
40
+ ? sourceUrl
41
+ : typeof metadataUrl === 'string'
42
+ ? metadataUrl
43
+ : link || '';
37
44
  const domain = new URL(url).hostname.replace(/^www\./, '');
38
45
  if (domain) {
39
46
  return domain;
@@ -52,7 +59,7 @@ export const getDomainName = (
52
59
 
53
60
  export function getAttribution(
54
61
  link: string,
55
- metadata?: t.ScrapeMetadata,
62
+ metadata?: t.ScrapeMetadata | t.GenericScrapeMetadata,
56
63
  logger?: t.Logger
57
64
  ): string | undefined {
58
65
  if (!metadata) return getDomainName(link, metadata, logger);
@@ -60,16 +67,17 @@ export function getAttribution(
60
67
  const twitterSite = metadata['twitter:site'];
61
68
  const twitterSiteFormatted =
62
69
  typeof twitterSite === 'string' ? twitterSite.replace(/^@/, '') : undefined;
70
+ const title = metadata.title;
63
71
 
64
72
  const possibleAttributions = [
65
73
  metadata.ogSiteName,
66
74
  metadata['og:site_name'],
67
- metadata.title?.split('|').pop()?.trim(),
75
+ typeof title === 'string' ? title.split('|').pop()?.trim() : undefined,
68
76
  twitterSiteFormatted,
69
77
  ];
70
78
 
71
79
  const attribution = possibleAttributions.find(
72
- (attr) => attr != null && typeof attr === 'string' && attr.trim() !== ''
80
+ (attr): attr is string => typeof attr === 'string' && attr.trim() !== ''
73
81
  );
74
82
  if (attribution != null) {
75
83
  return attribution;
@@ -1,14 +1,5 @@
1
1
  // src/types/graph.ts
2
- import type {
3
- START,
4
- StateType,
5
- UpdateType,
6
- StateGraph,
7
- StateGraphArgs,
8
- StateDefinition,
9
- CompiledStateGraph,
10
- BinaryOperatorAggregate,
11
- } from '@langchain/langgraph';
2
+ import type { START, StateGraph, StateGraphArgs } from '@langchain/langgraph';
12
3
  import type { BindToolsInput } from '@langchain/core/language_models/chat_models';
13
4
  import type {
14
5
  BaseMessage,
@@ -129,76 +120,40 @@ export type Workflow<
129
120
  N extends string = string,
130
121
  > = StateGraph<T, U, N>;
131
122
 
132
- export type CompiledWorkflow<
133
- T extends BaseGraphState = BaseGraphState,
134
- U extends Partial<T> = Partial<T>,
135
- N extends string = string,
136
- > = CompiledStateGraph<T, U, N>;
137
-
138
- export type CompiledStateWorkflow = CompiledStateGraph<
139
- StateType<{
140
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
141
- }>,
142
- UpdateType<{
143
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
144
- }>,
145
- string,
146
- {
147
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
148
- },
149
- {
150
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
151
- },
152
- StateDefinition
123
+ type LangChainEventStreamCallbackHandlerInput = NonNullable<
124
+ Parameters<Runnable['streamEvents']>[2]
153
125
  >;
154
126
 
155
- export type CompiledMultiAgentWorkflow = CompiledStateGraph<
156
- StateType<{
157
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
158
- agentMessages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
159
- }>,
160
- UpdateType<{
161
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
162
- agentMessages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
163
- }>,
164
- string,
165
- {
166
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
167
- agentMessages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
168
- },
169
- {
170
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
171
- agentMessages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
172
- },
173
- StateDefinition
174
- >;
127
+ export type EventStreamCallbackHandlerInput =
128
+ LangChainEventStreamCallbackHandlerInput & {
129
+ autoClose?: boolean;
130
+ raiseError?: boolean;
131
+ ignoreCustomEvent?: boolean;
132
+ };
175
133
 
176
- export type CompiledAgentWorfklow = CompiledStateGraph<
134
+ export type WorkflowValuesStreamConfig = RunnableConfig & {
135
+ streamMode: 'values';
136
+ };
137
+
138
+ /**
139
+ * LangGraph stream output is mode-dependent (`values`, `updates`, SSE, etc.).
140
+ * Keep the base Runnable stream output as unknown and narrow at callsites that
141
+ * choose a concrete streamMode.
142
+ */
143
+ export type CompiledWorkflow<
144
+ TInput extends BaseGraphState = BaseGraphState,
145
+ TOutput extends BaseGraphState = TInput,
146
+ > = Omit<Runnable<TInput, unknown>, 'invoke'> & {
147
+ invoke(input: TInput, config?: RunnableConfig): Promise<TOutput>;
148
+ };
149
+
150
+ export type CompiledStateWorkflow = CompiledWorkflow;
151
+
152
+ export type CompiledMultiAgentWorkflow = CompiledWorkflow<MultiAgentGraphState>;
153
+
154
+ export type CompiledAgentWorfklow = CompiledWorkflow<
177
155
  AgentSubgraphState,
178
- Partial<AgentSubgraphState>,
179
- '__start__' | `agent=${string}` | `tools=${string}` | `summarize=${string}`,
180
- {
181
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
182
- summarizationRequest: BinaryOperatorAggregate<
183
- SummarizationNodeInput | undefined,
184
- SummarizationNodeInput | undefined
185
- >;
186
- },
187
- {
188
- messages: BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
189
- summarizationRequest: BinaryOperatorAggregate<
190
- SummarizationNodeInput | undefined,
191
- SummarizationNodeInput | undefined
192
- >;
193
- },
194
- StateDefinition,
195
- {
196
- [x: `agent=${string}`]: Partial<BaseGraphState>;
197
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
198
- [x: `tools=${string}`]: any;
199
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
200
- [x: `summarize=${string}`]: any;
201
- }
156
+ AgentSubgraphState
202
157
  >;
203
158
 
204
159
  export type SystemRunnable =
@@ -214,21 +169,11 @@ export type SystemRunnable =
214
169
  * These are intentionally untyped to avoid coupling to library internals.
215
170
  */
216
171
  export type CompileOptions = {
217
- // A checkpointer instance (e.g., MemorySaver, SQL saver)
218
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
219
- checkpointer?: any;
172
+ checkpointer?: unknown;
220
173
  interruptBefore?: string[];
221
174
  interruptAfter?: string[];
222
175
  };
223
176
 
224
- export type EventStreamCallbackHandlerInput =
225
- Parameters<CompiledWorkflow['streamEvents']>[2] extends Omit<
226
- infer T,
227
- 'autoClose'
228
- >
229
- ? T
230
- : never;
231
-
232
177
  export type StreamChunk =
233
178
  | (ChatGenerationChunk & {
234
179
  message: AIMessageChunk;