@librechat/agents 3.0.0-rc10 → 3.0.0-rc11

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 (121) hide show
  1. package/dist/cjs/graphs/Graph.cjs +7 -1
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/llm/anthropic/index.cjs +21 -2
  4. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  5. package/dist/cjs/llm/google/index.cjs +3 -0
  6. package/dist/cjs/llm/google/index.cjs.map +1 -1
  7. package/dist/cjs/llm/google/utils/common.cjs +13 -0
  8. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  9. package/dist/cjs/llm/ollama/index.cjs +3 -0
  10. package/dist/cjs/llm/ollama/index.cjs.map +1 -1
  11. package/dist/cjs/llm/openai/index.cjs +20 -1
  12. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  13. package/dist/cjs/llm/openai/utils/index.cjs +6 -1
  14. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  15. package/dist/cjs/llm/openrouter/index.cjs +5 -1
  16. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  17. package/dist/cjs/llm/vertexai/index.cjs +1 -1
  18. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  19. package/dist/cjs/main.cjs +3 -1
  20. package/dist/cjs/main.cjs.map +1 -1
  21. package/dist/cjs/messages/core.cjs +5 -1
  22. package/dist/cjs/messages/core.cjs.map +1 -1
  23. package/dist/cjs/messages/format.cjs +52 -34
  24. package/dist/cjs/messages/format.cjs.map +1 -1
  25. package/dist/cjs/messages/prune.cjs +28 -0
  26. package/dist/cjs/messages/prune.cjs.map +1 -1
  27. package/dist/cjs/tools/ToolNode.cjs +2 -0
  28. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  29. package/dist/cjs/tools/search/firecrawl.cjs +3 -1
  30. package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
  31. package/dist/cjs/tools/search/rerankers.cjs +8 -6
  32. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  33. package/dist/cjs/tools/search/search.cjs +5 -5
  34. package/dist/cjs/tools/search/search.cjs.map +1 -1
  35. package/dist/cjs/tools/search/serper-scraper.cjs +132 -0
  36. package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -0
  37. package/dist/cjs/tools/search/tool.cjs +46 -9
  38. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  39. package/dist/cjs/utils/handlers.cjs +70 -0
  40. package/dist/cjs/utils/handlers.cjs.map +1 -0
  41. package/dist/esm/graphs/Graph.mjs +7 -1
  42. package/dist/esm/graphs/Graph.mjs.map +1 -1
  43. package/dist/esm/llm/anthropic/index.mjs +21 -2
  44. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  45. package/dist/esm/llm/google/index.mjs +3 -0
  46. package/dist/esm/llm/google/index.mjs.map +1 -1
  47. package/dist/esm/llm/google/utils/common.mjs +13 -0
  48. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  49. package/dist/esm/llm/ollama/index.mjs +3 -0
  50. package/dist/esm/llm/ollama/index.mjs.map +1 -1
  51. package/dist/esm/llm/openai/index.mjs +20 -1
  52. package/dist/esm/llm/openai/index.mjs.map +1 -1
  53. package/dist/esm/llm/openai/utils/index.mjs +6 -1
  54. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  55. package/dist/esm/llm/openrouter/index.mjs +5 -1
  56. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  57. package/dist/esm/llm/vertexai/index.mjs +1 -1
  58. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  59. package/dist/esm/main.mjs +2 -1
  60. package/dist/esm/main.mjs.map +1 -1
  61. package/dist/esm/messages/core.mjs +5 -1
  62. package/dist/esm/messages/core.mjs.map +1 -1
  63. package/dist/esm/messages/format.mjs +52 -34
  64. package/dist/esm/messages/format.mjs.map +1 -1
  65. package/dist/esm/messages/prune.mjs +28 -0
  66. package/dist/esm/messages/prune.mjs.map +1 -1
  67. package/dist/esm/tools/ToolNode.mjs +2 -0
  68. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  69. package/dist/esm/tools/search/firecrawl.mjs +3 -1
  70. package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
  71. package/dist/esm/tools/search/rerankers.mjs +8 -6
  72. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  73. package/dist/esm/tools/search/search.mjs +5 -5
  74. package/dist/esm/tools/search/search.mjs.map +1 -1
  75. package/dist/esm/tools/search/serper-scraper.mjs +129 -0
  76. package/dist/esm/tools/search/serper-scraper.mjs.map +1 -0
  77. package/dist/esm/tools/search/tool.mjs +46 -9
  78. package/dist/esm/tools/search/tool.mjs.map +1 -1
  79. package/dist/esm/utils/handlers.mjs +68 -0
  80. package/dist/esm/utils/handlers.mjs.map +1 -0
  81. package/dist/types/llm/anthropic/index.d.ts +3 -0
  82. package/dist/types/llm/google/index.d.ts +1 -0
  83. package/dist/types/llm/ollama/index.d.ts +1 -0
  84. package/dist/types/llm/openai/index.d.ts +4 -0
  85. package/dist/types/llm/openrouter/index.d.ts +4 -2
  86. package/dist/types/llm/vertexai/index.d.ts +1 -1
  87. package/dist/types/messages/format.d.ts +23 -20
  88. package/dist/types/tools/search/firecrawl.d.ts +2 -1
  89. package/dist/types/tools/search/rerankers.d.ts +4 -1
  90. package/dist/types/tools/search/search.d.ts +1 -2
  91. package/dist/types/tools/search/serper-scraper.d.ts +59 -0
  92. package/dist/types/tools/search/tool.d.ts +25 -4
  93. package/dist/types/tools/search/types.d.ts +31 -1
  94. package/dist/types/utils/handlers.d.ts +34 -0
  95. package/dist/types/utils/index.d.ts +1 -0
  96. package/package.json +2 -2
  97. package/src/graphs/Graph.ts +8 -1
  98. package/src/llm/anthropic/index.ts +23 -2
  99. package/src/llm/google/index.ts +4 -0
  100. package/src/llm/google/utils/common.ts +14 -0
  101. package/src/llm/ollama/index.ts +3 -0
  102. package/src/llm/openai/index.ts +19 -1
  103. package/src/llm/openai/utils/index.ts +7 -1
  104. package/src/llm/openrouter/index.ts +15 -6
  105. package/src/llm/vertexai/index.ts +2 -2
  106. package/src/messages/core.ts +5 -2
  107. package/src/messages/format.ts +67 -39
  108. package/src/messages/formatMessage.test.ts +418 -2
  109. package/src/messages/prune.ts +51 -0
  110. package/src/scripts/search.ts +5 -1
  111. package/src/scripts/tools.ts +4 -1
  112. package/src/tools/search/firecrawl.ts +5 -2
  113. package/src/tools/search/jina-reranker.test.ts +126 -0
  114. package/src/tools/search/rerankers.ts +11 -5
  115. package/src/tools/search/search.ts +6 -8
  116. package/src/tools/search/serper-scraper.ts +155 -0
  117. package/src/tools/search/tool.ts +49 -8
  118. package/src/tools/search/types.ts +46 -0
  119. package/src/utils/handlers.ts +107 -0
  120. package/src/utils/index.ts +2 -1
  121. package/src/utils/llmConfig.ts +35 -1
@@ -3,5 +3,6 @@ import { ChatOllama as BaseChatOllama } from '@langchain/ollama';
3
3
  import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
4
4
  import type { BaseMessage } from '@langchain/core/messages';
5
5
  export declare class ChatOllama extends BaseChatOllama {
6
+ static lc_name(): 'LibreChatOllama';
6
7
  _streamResponseChunks(messages: BaseMessage[], options: this['ParsedCallOptions'], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
7
8
  }
@@ -45,6 +45,7 @@ export declare class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptio
45
45
  _lc_stream_delay?: number;
46
46
  } & t.OpenAIChatInput['modelKwargs']);
47
47
  get exposedClient(): CustomOpenAIClient;
48
+ static lc_name(): string;
48
49
  protected _getClientOptions(options?: OpenAICoreRequestOptions): OpenAICoreRequestOptions;
49
50
  /**
50
51
  * Returns backwards compatible reasoning parameters from constructor params and call options
@@ -62,6 +63,7 @@ export declare class AzureChatOpenAI extends OriginalAzureChatOpenAI {
62
63
  _lc_stream_delay?: number;
63
64
  });
64
65
  get exposedClient(): CustomOpenAIClient;
66
+ static lc_name(): 'LibreChatAzureOpenAI';
65
67
  /**
66
68
  * Returns backwards compatible reasoning parameters from constructor params and call options
67
69
  * @internal
@@ -73,6 +75,7 @@ export declare class AzureChatOpenAI extends OriginalAzureChatOpenAI {
73
75
  }
74
76
  export declare class ChatDeepSeek extends OriginalChatDeepSeek {
75
77
  get exposedClient(): CustomOpenAIClient;
78
+ static lc_name(): 'LibreChatDeepSeek';
76
79
  protected _getClientOptions(options?: OpenAICoreRequestOptions): OpenAICoreRequestOptions;
77
80
  }
78
81
  /** xAI-specific usage metadata type */
@@ -102,6 +105,7 @@ export declare class ChatXAI extends OriginalChatXAI {
102
105
  };
103
106
  _lc_stream_delay?: number;
104
107
  });
108
+ static lc_name(): 'LibreChatXAI';
105
109
  get exposedClient(): CustomOpenAIClient;
106
110
  protected _getClientOptions(options?: OpenAICoreRequestOptions): OpenAICoreRequestOptions;
107
111
  _streamResponseChunks(messages: BaseMessage[], options: this['ParsedCallOptions'], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
@@ -1,10 +1,12 @@
1
- import type { ChatOpenAICallOptions, OpenAIClient } from '@langchain/openai';
2
- import type { AIMessageChunk, HumanMessageChunk, SystemMessageChunk, FunctionMessageChunk, ToolMessageChunk, ChatMessageChunk } from '@langchain/core/messages';
3
1
  import { ChatOpenAI } from '@/llm/openai';
2
+ import type { FunctionMessageChunk, SystemMessageChunk, HumanMessageChunk, ToolMessageChunk, ChatMessageChunk, AIMessageChunk } from '@langchain/core/messages';
3
+ import type { ChatOpenAICallOptions, OpenAIChatInput, OpenAIClient } from '@langchain/openai';
4
4
  export interface ChatOpenRouterCallOptions extends ChatOpenAICallOptions {
5
5
  include_reasoning?: boolean;
6
+ modelKwargs?: OpenAIChatInput['modelKwargs'];
6
7
  }
7
8
  export declare class ChatOpenRouter extends ChatOpenAI {
8
9
  constructor(_fields: Partial<ChatOpenRouterCallOptions>);
10
+ static lc_name(): 'LibreChatOpenRouter';
9
11
  protected _convertOpenAIDeltaToBaseMessageChunk(delta: Record<string, any>, rawResponse: OpenAIClient.ChatCompletionChunk, defaultRole?: 'function' | 'user' | 'system' | 'developer' | 'assistant' | 'tool'): AIMessageChunk | HumanMessageChunk | SystemMessageChunk | FunctionMessageChunk | ToolMessageChunk | ChatMessageChunk;
10
12
  }
@@ -286,7 +286,7 @@ import type { VertexAIClientOptions } from '@/types';
286
286
  export declare class ChatVertexAI extends ChatGoogle {
287
287
  lc_namespace: string[];
288
288
  dynamicThinkingBudget: boolean;
289
- static lc_name(): 'ChatVertexAI';
289
+ static lc_name(): 'LibreChatVertexAI';
290
290
  constructor(fields?: VertexAIClientOptions);
291
291
  invocationParams(options?: this['ParsedCallOptions'] | undefined): GoogleAIModelRequestParams;
292
292
  buildConnection(fields: VertexAIClientOptions, client: GoogleAbstractedClient): void;
@@ -2,23 +2,23 @@ import { AIMessage, ToolMessage, BaseMessage, HumanMessage, SystemMessage } from
2
2
  import type { MessageContentImageUrl } from '@langchain/core/messages';
3
3
  import type { MessageContentComplex, TPayload } from '@/types';
4
4
  import { Providers } from '@/common';
5
- interface VisionMessageParams {
5
+ interface MediaMessageParams {
6
6
  message: {
7
7
  role: string;
8
8
  content: string;
9
9
  name?: string;
10
10
  [key: string]: any;
11
11
  };
12
- image_urls: MessageContentImageUrl[];
12
+ mediaParts: MessageContentComplex[];
13
13
  endpoint?: Providers;
14
14
  }
15
15
  /**
16
- * Formats a message to OpenAI Vision API payload format.
16
+ * Formats a message with media content (images, documents, videos, audios) to API payload format.
17
17
  *
18
- * @param {VisionMessageParams} params - The parameters for formatting.
19
- * @returns {Object} - The formatted message.
18
+ * @param params - The parameters for formatting.
19
+ * @returns - The formatted message.
20
20
  */
21
- export declare const formatVisionMessage: ({ message, image_urls, endpoint, }: VisionMessageParams) => {
21
+ export declare const formatMediaMessage: ({ message, endpoint, mediaParts, }: MediaMessageParams) => {
22
22
  role: string;
23
23
  content: MessageContentComplex[];
24
24
  name?: string;
@@ -31,6 +31,9 @@ interface MessageInput {
31
31
  text?: string;
32
32
  content?: string | MessageContentComplex[];
33
33
  image_urls?: MessageContentImageUrl[];
34
+ documents?: MessageContentComplex[];
35
+ videos?: MessageContentComplex[];
36
+ audios?: MessageContentComplex[];
34
37
  lc_id?: string[];
35
38
  [key: string]: any;
36
39
  }
@@ -50,16 +53,16 @@ interface FormattedMessage {
50
53
  /**
51
54
  * Formats a message to OpenAI payload format based on the provided options.
52
55
  *
53
- * @param {FormatMessageParams} params - The parameters for formatting.
54
- * @returns {FormattedMessage | HumanMessage | AIMessage | SystemMessage} - The formatted message.
56
+ * @param params - The parameters for formatting.
57
+ * @returns - The formatted message.
55
58
  */
56
- export declare const formatMessage: ({ message, userName, assistantName, endpoint, langChain, }: FormatMessageParams) => FormattedMessage | HumanMessage | AIMessage | SystemMessage;
59
+ export declare const formatMessage: ({ message, userName, endpoint, assistantName, langChain, }: FormatMessageParams) => FormattedMessage | HumanMessage | AIMessage | SystemMessage;
57
60
  /**
58
61
  * Formats an array of messages for LangChain.
59
62
  *
60
- * @param {Array<MessageInput>} messages - The array of messages to format.
61
- * @param {Omit<FormatMessageParams, 'message' | 'langChain'>} formatOptions - The options for formatting each message.
62
- * @returns {Array<HumanMessage | AIMessage | SystemMessage>} - The array of formatted LangChain messages.
63
+ * @param messages - The array of messages to format.
64
+ * @param formatOptions - The options for formatting each message.
65
+ * @returns - The array of formatted LangChain messages.
63
66
  */
64
67
  export declare const formatLangChainMessages: (messages: Array<MessageInput>, formatOptions: Omit<FormatMessageParams, "message" | "langChain">) => Array<HumanMessage | AIMessage | SystemMessage>;
65
68
  interface LangChainMessage {
@@ -76,17 +79,17 @@ interface LangChainMessage {
76
79
  /**
77
80
  * Formats a LangChain message object by merging properties from `lc_kwargs` or `kwargs` and `additional_kwargs`.
78
81
  *
79
- * @param {LangChainMessage} message - The message object to format.
80
- * @returns {Record<string, any>} The formatted LangChain message.
82
+ * @param message - The message object to format.
83
+ * @returns - The formatted LangChain message.
81
84
  */
82
85
  export declare const formatFromLangChain: (message: LangChainMessage) => Record<string, any>;
83
86
  /**
84
87
  * Formats an array of messages for LangChain, handling tool calls and creating ToolMessage instances.
85
88
  *
86
- * @param {TPayload} payload - The array of messages to format.
87
- * @param {Record<number, number>} [indexTokenCountMap] - Optional map of message indices to token counts.
88
- * @param {Set<string>} [tools] - Optional set of tool names that are allowed in the request.
89
- * @returns {Object} - Object containing formatted messages and updated indexTokenCountMap if provided.
89
+ * @param payload - The array of messages to format.
90
+ * @param indexTokenCountMap - Optional map of message indices to token counts.
91
+ * @param tools - Optional set of tool names that are allowed in the request.
92
+ * @returns - Object containing formatted messages and updated indexTokenCountMap if provided.
90
93
  */
91
94
  export declare const formatAgentMessages: (payload: TPayload, indexTokenCountMap?: Record<number, number>, tools?: Set<string>) => {
92
95
  messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
@@ -94,8 +97,8 @@ export declare const formatAgentMessages: (payload: TPayload, indexTokenCountMap
94
97
  };
95
98
  /**
96
99
  * Formats an array of messages for LangChain, making sure all content fields are strings
97
- * @param {Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>} payload - The array of messages to format.
98
- * @returns {Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>} - The array of formatted LangChain messages, including ToolMessages for tool calls.
100
+ * @param payload - The array of messages to format.
101
+ * @returns - The array of formatted LangChain messages, including ToolMessages for tool calls.
99
102
  */
100
103
  export declare const formatContentStrings: (payload: Array<BaseMessage>) => Array<BaseMessage>;
101
104
  /**
@@ -3,9 +3,10 @@ import type * as t from './types';
3
3
  * Firecrawl scraper implementation
4
4
  * Uses the Firecrawl API to scrape web pages
5
5
  */
6
- export declare class FirecrawlScraper {
6
+ export declare class FirecrawlScraper implements t.BaseScraper {
7
7
  private apiKey;
8
8
  private apiUrl;
9
+ private version;
9
10
  private defaultFormats;
10
11
  private timeout;
11
12
  private logger;
@@ -7,8 +7,10 @@ export declare abstract class BaseReranker {
7
7
  protected getDefaultRanking(documents: string[], topK: number): t.Highlight[];
8
8
  }
9
9
  export declare class JinaReranker extends BaseReranker {
10
- constructor({ apiKey, logger, }: {
10
+ private apiUrl;
11
+ constructor({ apiKey, apiUrl, logger, }: {
11
12
  apiKey?: string;
13
+ apiUrl?: string;
12
14
  logger?: t.Logger;
13
15
  });
14
16
  rerank(query: string, documents: string[], topK?: number): Promise<t.Highlight[]>;
@@ -30,6 +32,7 @@ export declare class InfinityReranker extends BaseReranker {
30
32
  export declare const createReranker: (config: {
31
33
  rerankerType: t.RerankerType;
32
34
  jinaApiKey?: string;
35
+ jinaApiUrl?: string;
33
36
  cohereApiKey?: string;
34
37
  logger?: t.Logger;
35
38
  }) => BaseReranker | undefined;
@@ -1,9 +1,8 @@
1
1
  import type * as t from './types';
2
- import { FirecrawlScraper } from './firecrawl';
3
2
  export declare const createSearchAPI: (config: t.SearchConfig) => {
4
3
  getSources: (params: t.GetSourcesParams) => Promise<t.SearchResult>;
5
4
  };
6
- export declare const createSourceProcessor: (config?: t.ProcessSourcesConfig, scraperInstance?: FirecrawlScraper) => {
5
+ export declare const createSourceProcessor: (config?: t.ProcessSourcesConfig, scraperInstance?: t.BaseScraper) => {
7
6
  processSources: (fields: t.ProcessSourcesFields) => Promise<t.SearchResultData>;
8
7
  topResults: number;
9
8
  };
@@ -0,0 +1,59 @@
1
+ import type * as t from './types';
2
+ /**
3
+ * Serper scraper implementation
4
+ * Uses the Serper Scrape API (https://scrape.serper.dev) to scrape web pages
5
+ *
6
+ * Features:
7
+ * - Simple API with single endpoint
8
+ * - Returns both text and markdown content
9
+ * - Includes metadata from scraped pages
10
+ * - Credits-based pricing model
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const scraper = createSerperScraper({
15
+ * apiKey: 'your-serper-api-key',
16
+ * includeMarkdown: true,
17
+ * timeout: 10000
18
+ * });
19
+ *
20
+ * const [url, response] = await scraper.scrapeUrl('https://example.com');
21
+ * if (response.success) {
22
+ * const [content] = scraper.extractContent(response);
23
+ * console.log(content);
24
+ * }
25
+ * ```
26
+ */
27
+ export declare class SerperScraper implements t.BaseScraper {
28
+ private apiKey;
29
+ private apiUrl;
30
+ private timeout;
31
+ private logger;
32
+ private includeMarkdown;
33
+ constructor(config?: t.SerperScraperConfig);
34
+ /**
35
+ * Scrape a single URL
36
+ * @param url URL to scrape
37
+ * @param options Scrape options
38
+ * @returns Scrape response
39
+ */
40
+ scrapeUrl(url: string, options?: t.SerperScrapeOptions): Promise<[string, t.SerperScrapeResponse]>;
41
+ /**
42
+ * Extract content from scrape response
43
+ * @param response Scrape response
44
+ * @returns Extracted content or empty string if not available
45
+ */
46
+ extractContent(response: t.SerperScrapeResponse): [string, undefined | t.References];
47
+ /**
48
+ * Extract metadata from scrape response
49
+ * @param response Scrape response
50
+ * @returns Metadata object
51
+ */
52
+ extractMetadata(response: t.SerperScrapeResponse): Record<string, string | number | boolean | null | undefined>;
53
+ }
54
+ /**
55
+ * Create a Serper scraper instance
56
+ * @param config Scraper configuration
57
+ * @returns Serper scraper instance
58
+ */
59
+ export declare const createSerperScraper: (config?: t.SerperScraperConfig) => SerperScraper;
@@ -6,6 +6,27 @@ import { DATE_RANGE } from './schema';
6
6
  * Creates a search tool with a schema that dynamically includes the country field
7
7
  * only when the searchProvider is 'serper'.
8
8
  *
9
+ * Supports multiple scraper providers:
10
+ * - Firecrawl (default): Full-featured web scraping with multiple formats
11
+ * - Serper: Lightweight scraping using Serper's scrape API
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Using Firecrawl scraper (default)
16
+ * const searchTool = createSearchTool({
17
+ * searchProvider: 'serper',
18
+ * scraperProvider: 'firecrawl',
19
+ * firecrawlApiKey: 'your-firecrawl-key'
20
+ * });
21
+ *
22
+ * // Using Serper scraper
23
+ * const searchTool = createSearchTool({
24
+ * searchProvider: 'serper',
25
+ * scraperProvider: 'serper',
26
+ * serperApiKey: 'your-serper-key'
27
+ * });
28
+ * ```
29
+ *
9
30
  * @param config - The search tool configuration
10
31
  * @returns A DynamicStructuredTool with a schema that depends on the searchProvider
11
32
  */
@@ -18,16 +39,16 @@ export declare const createSearchTool: (config?: t.SearchToolConfig) => DynamicS
18
39
  news: z.ZodOptional<z.ZodBoolean>;
19
40
  }, "strip", z.ZodTypeAny, {
20
41
  query: string;
21
- date?: DATE_RANGE | undefined;
22
- images?: boolean | undefined;
23
42
  videos?: boolean | undefined;
43
+ images?: boolean | undefined;
24
44
  news?: boolean | undefined;
45
+ date?: DATE_RANGE | undefined;
25
46
  country?: unknown;
26
47
  }, {
27
48
  query: string;
28
- date?: DATE_RANGE | undefined;
29
- images?: boolean | undefined;
30
49
  videos?: boolean | undefined;
50
+ images?: boolean | undefined;
31
51
  news?: boolean | undefined;
52
+ date?: DATE_RANGE | undefined;
32
53
  country?: unknown;
33
54
  }>>;
@@ -4,6 +4,7 @@ import type { RunnableConfig } from '@langchain/core/runnables';
4
4
  import type { BaseReranker } from './rerankers';
5
5
  import { DATE_RANGE } from './schema';
6
6
  export type SearchProvider = 'serper' | 'searxng';
7
+ export type ScraperProvider = 'firecrawl' | 'serper';
7
8
  export type RerankerType = 'infinity' | 'jina' | 'cohere' | 'none';
8
9
  export interface Highlight {
9
10
  score: number;
@@ -85,8 +86,16 @@ export interface ProcessSourcesConfig {
85
86
  export interface FirecrawlConfig {
86
87
  firecrawlApiKey?: string;
87
88
  firecrawlApiUrl?: string;
89
+ firecrawlVersion?: string;
88
90
  firecrawlOptions?: FirecrawlScraperConfig;
89
91
  }
92
+ export interface SerperScraperConfig {
93
+ apiKey?: string;
94
+ apiUrl?: string;
95
+ timeout?: number;
96
+ logger?: Logger;
97
+ includeMarkdown?: boolean;
98
+ }
90
99
  export interface ScraperContentResult {
91
100
  content: string;
92
101
  }
@@ -130,9 +139,12 @@ export interface SearchToolConfig extends SearchConfig, ProcessSourcesConfig, Fi
130
139
  logger?: Logger;
131
140
  safeSearch?: SafeSearchLevel;
132
141
  jinaApiKey?: string;
142
+ jinaApiUrl?: string;
133
143
  cohereApiKey?: string;
134
144
  rerankerType?: RerankerType;
145
+ scraperProvider?: ScraperProvider;
135
146
  scraperTimeout?: number;
147
+ serperScraperOptions?: SerperScraperConfig;
136
148
  onSearchResults?: (results: SearchResult, runnableConfig?: RunnableConfig) => void;
137
149
  onGetHighlights?: (link: string) => void;
138
150
  }
@@ -146,8 +158,15 @@ export type UsedReferences = {
146
158
  originalIndex: number;
147
159
  reference: MediaReference;
148
160
  }[];
161
+ /** Base Scraper Interface */
162
+ export interface BaseScraper {
163
+ scrapeUrl(url: string, options?: unknown): Promise<[string, FirecrawlScrapeResponse | SerperScrapeResponse]>;
164
+ extractContent(response: FirecrawlScrapeResponse | SerperScrapeResponse): [string, undefined | References];
165
+ extractMetadata(response: FirecrawlScrapeResponse | SerperScrapeResponse): ScrapeMetadata | Record<string, string | number | boolean | null | undefined>;
166
+ }
149
167
  /** Firecrawl */
150
- export type FirecrawlScrapeOptions = Omit<FirecrawlScraperConfig, 'apiKey' | 'apiUrl' | 'logger'>;
168
+ export type FirecrawlScrapeOptions = Omit<FirecrawlScraperConfig, 'apiKey' | 'apiUrl' | 'version' | 'logger'>;
169
+ export type SerperScrapeOptions = Omit<SerperScraperConfig, 'apiKey' | 'apiUrl' | 'logger'>;
151
170
  export interface ScrapeMetadata {
152
171
  sourceURL?: string;
153
172
  url?: string;
@@ -213,9 +232,20 @@ export interface FirecrawlScrapeResponse {
213
232
  };
214
233
  error?: string;
215
234
  }
235
+ export interface SerperScrapeResponse {
236
+ success: boolean;
237
+ data?: {
238
+ text?: string;
239
+ markdown?: string;
240
+ metadata?: Record<string, string | number | boolean | null | undefined>;
241
+ credits?: number;
242
+ };
243
+ error?: string;
244
+ }
216
245
  export interface FirecrawlScraperConfig {
217
246
  apiKey?: string;
218
247
  apiUrl?: string;
248
+ version?: string;
219
249
  formats?: string[];
220
250
  timeout?: number;
221
251
  logger?: Logger;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Multi-Agent Handler Utilities
3
+ *
4
+ * Provides a simple helper to create handlers with content aggregation for multi-agent scripts.
5
+ *
6
+ * Usage:
7
+ * ```typescript
8
+ * const { contentParts, aggregateContent, handlers } = createHandlers();
9
+ *
10
+ * // With callbacks
11
+ * const { contentParts, aggregateContent, handlers } = createHandlers({
12
+ * onRunStep: (event, data) => console.log('Step:', data),
13
+ * onRunStepCompleted: (event, data) => console.log('Completed:', data)
14
+ * });
15
+ * ```
16
+ */
17
+ import { GraphEvents } from '@/common';
18
+ import { createContentAggregator } from '@/stream';
19
+ import type * as t from '@/types';
20
+ interface HandlerCallbacks {
21
+ onRunStep?: (event: GraphEvents.ON_RUN_STEP, data: t.StreamEventData) => void;
22
+ onRunStepCompleted?: (event: GraphEvents.ON_RUN_STEP_COMPLETED, data: t.StreamEventData) => void;
23
+ onRunStepDelta?: (event: GraphEvents.ON_RUN_STEP_DELTA, data: t.StreamEventData) => void;
24
+ onMessageDelta?: (event: GraphEvents.ON_MESSAGE_DELTA, data: t.StreamEventData) => void;
25
+ }
26
+ /**
27
+ * Creates handlers with content aggregation for multi-agent scripts
28
+ */
29
+ export declare function createHandlers(callbacks?: HandlerCallbacks): {
30
+ contentParts: Array<t.MessageContentComplex | undefined>;
31
+ aggregateContent: ReturnType<typeof createContentAggregator>['aggregateContent'];
32
+ handlers: Record<string, t.EventHandler>;
33
+ };
34
+ export {};
@@ -1,5 +1,6 @@
1
1
  export * from './graph';
2
2
  export * from './llm';
3
3
  export * from './misc';
4
+ export * from './handlers';
4
5
  export * from './run';
5
6
  export * from './tokens';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "3.0.00-rc10",
3
+ "version": "3.0.00-rc11",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -51,7 +51,7 @@
51
51
  "caching": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/caching.ts --name 'Jo' --location 'New York, NY'",
52
52
  "thinking": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/thinking.ts --name 'Jo' --location 'New York, NY'",
53
53
  "memory": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/memory.ts --provider 'openAI' --name 'Jo' --location 'New York, NY'",
54
- "tool-test": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/tools.ts --provider 'bedrock' --name 'Jo' --location 'New York, NY'",
54
+ "tool-test": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/tools.ts --provider 'openrouter' --name 'Jo' --location 'New York, NY'",
55
55
  "search": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/search.ts --provider 'anthropic' --name 'Jo' --location 'New York, NY'",
56
56
  "ant_web_search": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/ant_web_search.ts --name 'Jo' --location 'New York, NY'",
57
57
  "abort": "node -r dotenv/config --loader ./tsconfig-paths-bootstrap.mjs --experimental-specifier-resolution=node ./src/scripts/abort.ts --provider 'openAI' --name 'Jo' --location 'New York, NY'",
@@ -299,6 +299,8 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
299
299
  agentContext.currentTokenType === 'think_and_text'
300
300
  ) {
301
301
  keyList.push('reasoning');
302
+ } else if (agentContext.tokenTypeSwitch === 'content') {
303
+ keyList.push('post-reasoning');
302
304
  }
303
305
 
304
306
  if (this.invokedToolIds != null && this.invokedToolIds.size > 0) {
@@ -580,7 +582,12 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
580
582
  null) ||
581
583
  (agentContext.provider === Providers.BEDROCK &&
582
584
  (agentContext.clientOptions as t.BedrockAnthropicInput)
583
- .additionalModelRequestFields?.['thinking'] != null);
585
+ .additionalModelRequestFields?.['thinking'] != null) ||
586
+ (agentContext.provider === Providers.OPENAI &&
587
+ (
588
+ (agentContext.clientOptions as t.OpenAIClientOptions).modelKwargs
589
+ ?.thinking as t.AnthropicClientOptions['thinking']
590
+ )?.type === 'enabled');
584
591
 
585
592
  agentContext.pruneMessages = createPruneMessages({
586
593
  startIndex: this.startIndex,
@@ -135,12 +135,18 @@ export class CustomAnthropic extends ChatAnthropicMessages {
135
135
  private message_delta: AnthropicMessageDeltaEvent | undefined;
136
136
  private tools_in_params?: boolean;
137
137
  private emitted_usage?: boolean;
138
+ top_k: number | undefined;
138
139
  constructor(fields?: CustomAnthropicInput) {
139
140
  super(fields);
140
141
  this.resetTokenEvents();
142
+ this.setDirectFields(fields);
141
143
  this._lc_stream_delay = fields?._lc_stream_delay ?? 25;
142
144
  }
143
145
 
146
+ static lc_name(): 'LibreChatAnthropic' {
147
+ return 'LibreChatAnthropic';
148
+ }
149
+
144
150
  /**
145
151
  * Get the parameters used to invoke the model
146
152
  */
@@ -158,7 +164,7 @@ export class CustomAnthropic extends ChatAnthropicMessages {
158
164
  | undefined = handleToolChoice(options?.tool_choice);
159
165
 
160
166
  if (this.thinking.type === 'enabled') {
161
- if (this.topK !== -1 && (this.topK as number | undefined) != null) {
167
+ if (this.top_k !== -1 && (this.top_k as number | undefined) != null) {
162
168
  throw new Error('topK is not supported when thinking is enabled');
163
169
  }
164
170
  if (this.topP !== -1 && (this.topP as number | undefined) != null) {
@@ -187,7 +193,7 @@ export class CustomAnthropic extends ChatAnthropicMessages {
187
193
  return {
188
194
  model: this.model,
189
195
  temperature: this.temperature,
190
- top_k: this.topK,
196
+ top_k: this.top_k,
191
197
  top_p: this.topP,
192
198
  stop_sequences: options?.stop ?? this.stopSequences,
193
199
  stream: this.streaming,
@@ -244,6 +250,21 @@ export class CustomAnthropic extends ChatAnthropicMessages {
244
250
  this.tools_in_params = undefined;
245
251
  }
246
252
 
253
+ setDirectFields(fields?: CustomAnthropicInput): void {
254
+ this.temperature = fields?.temperature ?? undefined;
255
+ this.topP = fields?.topP ?? undefined;
256
+ this.top_k = fields?.topK;
257
+ if (this.temperature === -1 || this.temperature === 1) {
258
+ this.temperature = undefined;
259
+ }
260
+ if (this.topP === -1) {
261
+ this.topP = undefined;
262
+ }
263
+ if (this.top_k === -1) {
264
+ this.top_k = undefined;
265
+ }
266
+ }
267
+
247
268
  private createGenerationChunk({
248
269
  token,
249
270
  chunk,
@@ -107,6 +107,10 @@ export class CustomChatGoogleGenerativeAI extends ChatGoogleGenerativeAI {
107
107
  this.streamUsage = fields.streamUsage ?? this.streamUsage;
108
108
  }
109
109
 
110
+ static lc_name(): 'LibreChatGoogleGenerativeAI' {
111
+ return 'LibreChatGoogleGenerativeAI';
112
+ }
113
+
110
114
  invocationParams(
111
115
  options?: this['ParsedCallOptions']
112
116
  ): Omit<GenerateContentRequest, 'contents'> {
@@ -301,6 +301,20 @@ function _convertLangChainContentToPart(
301
301
  mimeType,
302
302
  },
303
303
  };
304
+ } else if (
305
+ content.type === 'document' ||
306
+ content.type === 'audio' ||
307
+ content.type === 'video'
308
+ ) {
309
+ if (!isMultimodalModel) {
310
+ throw new Error(`This model does not support ${content.type}s`);
311
+ }
312
+ return {
313
+ inlineData: {
314
+ data: content.data,
315
+ mimeType: content.mimeType,
316
+ },
317
+ };
304
318
  } else if (content.type === 'media') {
305
319
  return messageContentMedia(content);
306
320
  } else if (content.type === 'tool_use') {
@@ -13,6 +13,9 @@ import {
13
13
  } from './utils';
14
14
 
15
15
  export class ChatOllama extends BaseChatOllama {
16
+ static lc_name(): 'LibreChatOllama' {
17
+ return 'LibreChatOllama';
18
+ }
16
19
  async *_streamResponseChunks(
17
20
  messages: BaseMessage[],
18
21
  options: this['ParsedCallOptions'],
@@ -210,6 +210,9 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
210
210
  public get exposedClient(): CustomOpenAIClient {
211
211
  return this.client;
212
212
  }
213
+ static lc_name(): string {
214
+ return 'LibreChatOpenAI';
215
+ }
213
216
  protected _getClientOptions(
214
217
  options?: OpenAICoreRequestOptions
215
218
  ): OpenAICoreRequestOptions {
@@ -245,7 +248,8 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
245
248
  getReasoningParams(
246
249
  options?: this['ParsedCallOptions']
247
250
  ): OpenAIClient.Reasoning | undefined {
248
- if (!isReasoningModel(this.model)) {
251
+ const lc_name = (this.constructor as typeof ChatOpenAI).lc_name();
252
+ if (lc_name === 'LibreChatOpenAI' && !isReasoningModel(this.model)) {
249
253
  return;
250
254
  }
251
255
 
@@ -360,6 +364,10 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
360
364
  } else if ('reasoning' in delta) {
361
365
  chunk.additional_kwargs.reasoning_content = delta.reasoning;
362
366
  }
367
+ if ('provider_specific_fields' in delta) {
368
+ chunk.additional_kwargs.provider_specific_fields =
369
+ delta.provider_specific_fields;
370
+ }
363
371
  defaultRole = delta.role ?? defaultRole;
364
372
  const newTokenIndices = {
365
373
  prompt: options.promptIndex ?? 0,
@@ -463,6 +471,9 @@ export class AzureChatOpenAI extends OriginalAzureChatOpenAI {
463
471
  public get exposedClient(): CustomOpenAIClient {
464
472
  return this.client;
465
473
  }
474
+ static lc_name(): 'LibreChatAzureOpenAI' {
475
+ return 'LibreChatAzureOpenAI';
476
+ }
466
477
  /**
467
478
  * Returns backwards compatible reasoning parameters from constructor params and call options
468
479
  * @internal
@@ -607,6 +618,9 @@ export class ChatDeepSeek extends OriginalChatDeepSeek {
607
618
  public get exposedClient(): CustomOpenAIClient {
608
619
  return this.client;
609
620
  }
621
+ static lc_name(): 'LibreChatDeepSeek' {
622
+ return 'LibreChatDeepSeek';
623
+ }
610
624
  protected _getClientOptions(
611
625
  options?: OpenAICoreRequestOptions
612
626
  ): OpenAICoreRequestOptions {
@@ -679,6 +693,10 @@ export class ChatXAI extends OriginalChatXAI {
679
693
  }
680
694
  }
681
695
 
696
+ static lc_name(): 'LibreChatXAI' {
697
+ return 'LibreChatXAI';
698
+ }
699
+
682
700
  public get exposedClient(): CustomOpenAIClient {
683
701
  return this.client;
684
702
  }