@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
@@ -1,6 +1,6 @@
1
- import { isDataContentBlock, convertToProviderContentBlock, isAIMessage, AIMessageChunk, ChatMessage, parseBase64DataUrl, parseMimeType, AIMessage } from '@langchain/core/messages';
2
- import { ChatGenerationChunk } from '@langchain/core/outputs';
3
- import { convertLangChainToolCallToOpenAI, parseToolCall, makeInvalidToolCall } from '@langchain/core/output_parsers/openai_tools';
1
+ import { isDataContentBlock, convertToProviderContentBlock, isAIMessage, ChatMessage, parseBase64DataUrl, parseMimeType } from '@langchain/core/messages';
2
+ import '@langchain/core/outputs';
3
+ import { convertLangChainToolCallToOpenAI } from '@langchain/core/output_parsers/openai_tools';
4
4
 
5
5
  function extractGenericMessageCustomRole(message) {
6
6
  if (message.role !== 'system' &&
@@ -163,6 +163,7 @@ const completionsApiContentBlockConverter = {
163
163
  };
164
164
  // Used in LangSmith, export is important here
165
165
  function _convertMessagesToOpenAIParams(messages, model, options) {
166
+ let hasReasoningToolCallContext = false;
166
167
  // TODO: Function messages do not support array content, fix cast
167
168
  return messages.flatMap((message) => {
168
169
  let role = messageToOpenAIRole(message);
@@ -187,6 +188,8 @@ function _convertMessagesToOpenAIParams(messages, model, options) {
187
188
  role,
188
189
  content,
189
190
  };
191
+ let messageHasToolCalls = false;
192
+ let messageIsToolResult = false;
190
193
  if (message.name != null) {
191
194
  completionParam.name = message.name;
192
195
  }
@@ -195,13 +198,9 @@ function _convertMessagesToOpenAIParams(messages, model, options) {
195
198
  completionParam.content = '';
196
199
  }
197
200
  if (isAIMessage(message) && !!message.tool_calls?.length) {
201
+ messageHasToolCalls = true;
198
202
  completionParam.tool_calls = message.tool_calls.map(convertLangChainToolCallToOpenAI);
199
203
  completionParam.content = hasAnthropicThinkingBlock ? content : '';
200
- if (options?.includeReasoningContent === true &&
201
- message.additional_kwargs.reasoning_content != null) {
202
- completionParam.reasoning_content =
203
- message.additional_kwargs.reasoning_content;
204
- }
205
204
  if (options?.includeReasoningDetails === true &&
206
205
  message.additional_kwargs.reasoning_details != null) {
207
206
  // For Claude via OpenRouter, convert reasoning_details to content blocks
@@ -243,12 +242,10 @@ function _convertMessagesToOpenAIParams(messages, model, options) {
243
242
  }
244
243
  else {
245
244
  if (message.additional_kwargs.tool_calls != null) {
245
+ messageHasToolCalls =
246
+ !Array.isArray(message.additional_kwargs.tool_calls) ||
247
+ message.additional_kwargs.tool_calls.length > 0;
246
248
  completionParam.tool_calls = message.additional_kwargs.tool_calls;
247
- if (options?.includeReasoningContent === true &&
248
- message.additional_kwargs.reasoning_content != null) {
249
- completionParam.reasoning_content =
250
- message.additional_kwargs.reasoning_content;
251
- }
252
249
  if (options?.includeReasoningDetails === true &&
253
250
  message.additional_kwargs.reasoning_details != null) {
254
251
  // For Claude via OpenRouter, convert reasoning_details to content blocks
@@ -289,9 +286,21 @@ function _convertMessagesToOpenAIParams(messages, model, options) {
289
286
  }
290
287
  }
291
288
  if (message.tool_call_id != null) {
289
+ messageIsToolResult = true;
292
290
  completionParam.tool_call_id = message.tool_call_id;
293
291
  }
294
292
  }
293
+ if (options?.includeReasoningContent === true &&
294
+ isAIMessage(message) &&
295
+ (hasReasoningToolCallContext || messageHasToolCalls) &&
296
+ typeof message.additional_kwargs.reasoning_content === 'string' &&
297
+ message.additional_kwargs.reasoning_content !== '') {
298
+ completionParam.reasoning_content =
299
+ message.additional_kwargs.reasoning_content;
300
+ }
301
+ if (messageHasToolCalls || messageIsToolResult) {
302
+ hasReasoningToolCallContext = true;
303
+ }
295
304
  if (message.additional_kwargs.audio &&
296
305
  typeof message.additional_kwargs.audio === 'object' &&
297
306
  'id' in message.additional_kwargs.audio) {
@@ -306,454 +315,9 @@ function _convertMessagesToOpenAIParams(messages, model, options) {
306
315
  return completionParam;
307
316
  });
308
317
  }
309
- const _FUNCTION_CALL_IDS_MAP_KEY = '__openai_function_call_ids__';
310
- function _convertReasoningSummaryToOpenAIResponsesParams(reasoning) {
311
- // combine summary parts that have the the same index and then remove the indexes
312
- const summary = (reasoning.summary.length > 1
313
- ? reasoning.summary.reduce((acc, curr) => {
314
- const last = acc.at(-1);
315
- if (last.index === curr.index) {
316
- last.text += curr.text;
317
- }
318
- else {
319
- acc.push(curr);
320
- }
321
- return acc;
322
- }, [{ ...reasoning.summary[0] }])
323
- : reasoning.summary).map((s) => Object.fromEntries(Object.entries(s).filter(([k]) => k !== 'index')));
324
- return {
325
- ...reasoning,
326
- summary,
327
- };
328
- }
329
- function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
330
- return messages.flatMap((lcMsg) => {
331
- const additional_kwargs = lcMsg.additional_kwargs;
332
- let role = messageToOpenAIRole(lcMsg);
333
- if (role === 'system' && isReasoningModel(model))
334
- role = 'developer';
335
- if (role === 'function') {
336
- throw new Error('Function messages are not supported in Responses API');
337
- }
338
- if (role === 'tool') {
339
- const toolMessage = lcMsg;
340
- // Handle computer call output
341
- if (additional_kwargs.type === 'computer_call_output') {
342
- const output = (() => {
343
- if (typeof toolMessage.content === 'string') {
344
- return {
345
- type: 'computer_screenshot',
346
- image_url: toolMessage.content,
347
- };
348
- }
349
- if (Array.isArray(toolMessage.content)) {
350
- const oaiScreenshot = toolMessage.content.find((i) => i.type === 'computer_screenshot');
351
- if (oaiScreenshot)
352
- return oaiScreenshot;
353
- const lcImage = toolMessage.content.find((i) => i.type === 'image_url');
354
- if (lcImage) {
355
- return {
356
- type: 'computer_screenshot',
357
- image_url: typeof lcImage.image_url === 'string'
358
- ? lcImage.image_url
359
- : lcImage.image_url.url,
360
- };
361
- }
362
- }
363
- throw new Error('Invalid computer call output');
364
- })();
365
- return {
366
- type: 'computer_call_output',
367
- output,
368
- call_id: toolMessage.tool_call_id,
369
- };
370
- }
371
- return {
372
- type: 'function_call_output',
373
- call_id: toolMessage.tool_call_id,
374
- id: toolMessage.id?.startsWith('fc_') ? toolMessage.id : undefined,
375
- output: typeof toolMessage.content !== 'string'
376
- ? JSON.stringify(toolMessage.content)
377
- : toolMessage.content,
378
- };
379
- }
380
- if (role === 'assistant') {
381
- // if we have the original response items, just reuse them
382
- if (!zdrEnabled &&
383
- lcMsg.response_metadata.output != null &&
384
- Array.isArray(lcMsg.response_metadata.output) &&
385
- lcMsg.response_metadata.output.length > 0 &&
386
- lcMsg.response_metadata.output.every((item) => 'type' in item)) {
387
- return lcMsg.response_metadata.output;
388
- }
389
- // otherwise, try to reconstruct the response from what we have
390
- const input = [];
391
- // reasoning items
392
- if (additional_kwargs.reasoning && !zdrEnabled) {
393
- const reasoningItem = _convertReasoningSummaryToOpenAIResponsesParams(additional_kwargs.reasoning);
394
- input.push(reasoningItem);
395
- }
396
- // ai content
397
- let { content } = lcMsg;
398
- if (additional_kwargs.refusal) {
399
- if (typeof content === 'string') {
400
- content = [{ type: 'output_text', text: content, annotations: [] }];
401
- }
402
- content = [
403
- ...content,
404
- { type: 'refusal', refusal: additional_kwargs.refusal },
405
- ];
406
- }
407
- input.push({
408
- type: 'message',
409
- role: 'assistant',
410
- ...(lcMsg.id && !zdrEnabled && lcMsg.id.startsWith('msg_')
411
- ? { id: lcMsg.id }
412
- : {}),
413
- content: typeof content === 'string'
414
- ? content
415
- : content.flatMap((item) => {
416
- if (item.type === 'text') {
417
- return {
418
- type: 'output_text',
419
- text: item.text,
420
- // @ts-expect-error TODO: add types for `annotations`
421
- annotations: item.annotations ?? [],
422
- };
423
- }
424
- if (item.type === 'output_text' || item.type === 'refusal') {
425
- return item;
426
- }
427
- return [];
428
- }),
429
- });
430
- const functionCallIds = additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY];
431
- if (isAIMessage(lcMsg) && !!lcMsg.tool_calls?.length) {
432
- input.push(...lcMsg.tool_calls.map((toolCall) => ({
433
- type: 'function_call',
434
- name: toolCall.name,
435
- arguments: JSON.stringify(toolCall.args),
436
- call_id: toolCall.id,
437
- ...(zdrEnabled ? { id: functionCallIds?.[toolCall.id] } : {}),
438
- })));
439
- }
440
- else if (additional_kwargs.tool_calls) {
441
- input.push(...additional_kwargs.tool_calls.map((toolCall) => ({
442
- type: 'function_call',
443
- name: toolCall.function.name,
444
- call_id: toolCall.id,
445
- arguments: toolCall.function.arguments,
446
- ...(zdrEnabled ? { id: functionCallIds?.[toolCall.id] } : {}),
447
- })));
448
- }
449
- const toolOutputs = (lcMsg.response_metadata.output?.length ?? 0) > 0
450
- ? lcMsg.response_metadata.output
451
- : additional_kwargs.tool_outputs;
452
- const fallthroughCallTypes = [
453
- 'computer_call',
454
- /** @ts-ignore */
455
- 'mcp_call',
456
- /** @ts-ignore */
457
- 'code_interpreter_call',
458
- /** @ts-ignore */
459
- 'image_generation_call',
460
- ];
461
- if (toolOutputs != null) {
462
- const castToolOutputs = toolOutputs;
463
- const fallthroughCalls = castToolOutputs.filter((item) => fallthroughCallTypes.includes(item.type));
464
- if (fallthroughCalls.length > 0)
465
- input.push(...fallthroughCalls);
466
- }
467
- return input;
468
- }
469
- if (role === 'user' || role === 'system' || role === 'developer') {
470
- if (typeof lcMsg.content === 'string') {
471
- return { type: 'message', role, content: lcMsg.content };
472
- }
473
- const messages = [];
474
- const content = lcMsg.content.flatMap((item) => {
475
- if (item.type === 'mcp_approval_response') {
476
- messages.push({
477
- // @ts-ignore
478
- type: 'mcp_approval_response',
479
- approval_request_id: item.approval_request_id,
480
- approve: item.approve,
481
- });
482
- }
483
- if (isDataContentBlock(item)) {
484
- return convertToProviderContentBlock(item, completionsApiContentBlockConverter);
485
- }
486
- if (item.type === 'text') {
487
- return {
488
- type: 'input_text',
489
- text: item.text,
490
- };
491
- }
492
- if (item.type === 'image_url') {
493
- return {
494
- type: 'input_image',
495
- image_url: typeof item.image_url === 'string'
496
- ? item.image_url
497
- : item.image_url.url,
498
- detail: typeof item.image_url === 'string'
499
- ? 'auto'
500
- : item.image_url.detail,
501
- };
502
- }
503
- if (item.type === 'input_text' ||
504
- item.type === 'input_image' ||
505
- item.type === 'input_file') {
506
- return item;
507
- }
508
- return [];
509
- });
510
- if (content.length > 0) {
511
- messages.push({ type: 'message', role, content });
512
- }
513
- return messages;
514
- }
515
- console.warn(`Unsupported role found when converting to OpenAI Responses API: ${role}`);
516
- return [];
517
- });
518
- }
519
318
  function isReasoningModel(model) {
520
319
  return model != null && model !== '' && /\b(o\d|gpt-[5-9])\b/i.test(model);
521
320
  }
522
- function _convertOpenAIResponsesMessageToBaseMessage(response) {
523
- if (response.error) {
524
- // TODO: add support for `addLangChainErrorFields`
525
- const error = new Error(response.error.message);
526
- error.name = response.error.code;
527
- throw error;
528
- }
529
- let messageId;
530
- const content = [];
531
- const tool_calls = [];
532
- const invalid_tool_calls = [];
533
- const response_metadata = {
534
- model: response.model,
535
- created_at: response.created_at,
536
- id: response.id,
537
- incomplete_details: response.incomplete_details,
538
- metadata: response.metadata,
539
- object: response.object,
540
- status: response.status,
541
- user: response.user,
542
- service_tier: response.service_tier,
543
- // for compatibility with chat completion calls.
544
- model_name: response.model,
545
- };
546
- const additional_kwargs = {};
547
- for (const item of response.output) {
548
- if (item.type === 'message') {
549
- messageId = item.id;
550
- content.push(...item.content.flatMap((part) => {
551
- if (part.type === 'output_text') {
552
- if ('parsed' in part && part.parsed != null) {
553
- additional_kwargs.parsed = part.parsed;
554
- }
555
- return {
556
- type: 'text',
557
- text: part.text,
558
- annotations: part.annotations,
559
- };
560
- }
561
- if (part.type === 'refusal') {
562
- additional_kwargs.refusal = part.refusal;
563
- return [];
564
- }
565
- return part;
566
- }));
567
- }
568
- else if (item.type === 'function_call') {
569
- const fnAdapter = {
570
- function: { name: item.name, arguments: item.arguments },
571
- id: item.call_id,
572
- };
573
- try {
574
- tool_calls.push(parseToolCall(fnAdapter, { returnId: true }));
575
- }
576
- catch (e) {
577
- let errMessage;
578
- if (typeof e === 'object' &&
579
- e != null &&
580
- 'message' in e &&
581
- typeof e.message === 'string') {
582
- errMessage = e.message;
583
- }
584
- invalid_tool_calls.push(makeInvalidToolCall(fnAdapter, errMessage));
585
- }
586
- additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY] ??= {};
587
- if (item.id) {
588
- additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY][item.call_id] = item.id;
589
- }
590
- }
591
- else if (item.type === 'reasoning') {
592
- additional_kwargs.reasoning = item;
593
- }
594
- else {
595
- additional_kwargs.tool_outputs ??= [];
596
- additional_kwargs.tool_outputs.push(item);
597
- }
598
- }
599
- return new AIMessage({
600
- id: messageId,
601
- content,
602
- tool_calls,
603
- invalid_tool_calls,
604
- usage_metadata: response.usage,
605
- additional_kwargs,
606
- response_metadata,
607
- });
608
- }
609
- function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
610
- const content = [];
611
- let generationInfo = {};
612
- let usage_metadata;
613
- const tool_call_chunks = [];
614
- const response_metadata = {};
615
- const additional_kwargs = {};
616
- let id;
617
- if (chunk.type === 'response.output_text.delta') {
618
- content.push({
619
- type: 'text',
620
- text: chunk.delta,
621
- index: chunk.content_index,
622
- });
623
- /** @ts-ignore */
624
- }
625
- else if (chunk.type === 'response.output_text_annotation.added') {
626
- content.push({
627
- type: 'text',
628
- text: '',
629
- /** @ts-ignore */
630
- annotations: [chunk.annotation],
631
- /** @ts-ignore */
632
- index: chunk.content_index,
633
- });
634
- }
635
- else if (chunk.type === 'response.output_item.added' &&
636
- chunk.item.type === 'message') {
637
- id = chunk.item.id;
638
- }
639
- else if (chunk.type === 'response.output_item.added' &&
640
- chunk.item.type === 'function_call') {
641
- tool_call_chunks.push({
642
- type: 'tool_call_chunk',
643
- name: chunk.item.name,
644
- args: chunk.item.arguments,
645
- id: chunk.item.call_id,
646
- index: chunk.output_index,
647
- });
648
- additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY] = {
649
- [chunk.item.call_id]: chunk.item.id,
650
- };
651
- }
652
- else if (chunk.type === 'response.output_item.done' &&
653
- [
654
- 'web_search_call',
655
- 'file_search_call',
656
- 'computer_call',
657
- 'code_interpreter_call',
658
- 'mcp_call',
659
- 'mcp_list_tools',
660
- 'mcp_approval_request',
661
- 'image_generation_call',
662
- ].includes(chunk.item.type)) {
663
- additional_kwargs.tool_outputs = [chunk.item];
664
- }
665
- else if (chunk.type === 'response.created') {
666
- response_metadata.id = chunk.response.id;
667
- response_metadata.model_name = chunk.response.model;
668
- response_metadata.model = chunk.response.model;
669
- }
670
- else if (chunk.type === 'response.completed') {
671
- const msg = _convertOpenAIResponsesMessageToBaseMessage(chunk.response);
672
- usage_metadata = chunk.response.usage;
673
- if (chunk.response.text?.format?.type === 'json_schema') {
674
- additional_kwargs.parsed ??= JSON.parse(msg.text);
675
- }
676
- for (const [key, value] of Object.entries(chunk.response)) {
677
- if (key !== 'id')
678
- response_metadata[key] = value;
679
- }
680
- }
681
- else if (chunk.type === 'response.function_call_arguments.delta') {
682
- tool_call_chunks.push({
683
- type: 'tool_call_chunk',
684
- args: chunk.delta,
685
- index: chunk.output_index,
686
- });
687
- }
688
- else if (chunk.type === 'response.web_search_call.completed' ||
689
- chunk.type === 'response.file_search_call.completed') {
690
- generationInfo = {
691
- tool_outputs: {
692
- id: chunk.item_id,
693
- type: chunk.type.replace('response.', '').replace('.completed', ''),
694
- status: 'completed',
695
- },
696
- };
697
- }
698
- else if (chunk.type === 'response.refusal.done') {
699
- additional_kwargs.refusal = chunk.refusal;
700
- }
701
- else if (chunk.type === 'response.output_item.added' &&
702
- 'item' in chunk &&
703
- chunk.item.type === 'reasoning') {
704
- const summary = chunk
705
- .item.summary
706
- ? chunk.item.summary.map((s, index) => ({
707
- ...s,
708
- index,
709
- }))
710
- : undefined;
711
- additional_kwargs.reasoning = {
712
- // We only capture ID in the first chunk or else the concatenated result of all chunks will
713
- // have an ID field that is repeated once per chunk. There is special handling for the `type`
714
- // field that prevents this, however.
715
- id: chunk.item.id,
716
- type: chunk.item.type,
717
- ...(summary ? { summary } : {}),
718
- };
719
- }
720
- else if (chunk.type === 'response.reasoning_summary_part.added') {
721
- additional_kwargs.reasoning = {
722
- type: 'reasoning',
723
- summary: [{ ...chunk.part, index: chunk.summary_index }],
724
- };
725
- }
726
- else if (chunk.type === 'response.reasoning_summary_text.delta') {
727
- additional_kwargs.reasoning = {
728
- type: 'reasoning',
729
- summary: [
730
- { text: chunk.delta, type: 'summary_text', index: chunk.summary_index },
731
- ],
732
- };
733
- /** @ts-ignore */
734
- }
735
- else if (chunk.type === 'response.image_generation_call.partial_image') {
736
- // noop/fixme: retaining partial images in a message chunk means that _all_
737
- // partial images get kept in history, so we don't do anything here.
738
- return null;
739
- }
740
- else {
741
- return null;
742
- }
743
- return new ChatGenerationChunk({
744
- // Legacy reasons, `onLLMNewToken` should pulls this out
745
- text: content.map((part) => part.text).join(''),
746
- message: new AIMessageChunk({
747
- id,
748
- content,
749
- tool_call_chunks,
750
- usage_metadata,
751
- additional_kwargs,
752
- response_metadata,
753
- }),
754
- generationInfo,
755
- });
756
- }
757
321
 
758
- export { _convertMessagesToOpenAIParams, _convertMessagesToOpenAIResponsesParams, _convertOpenAIResponsesDeltaToBaseMessageChunk, isReasoningModel, messageToOpenAIRole };
322
+ export { _convertMessagesToOpenAIParams, isReasoningModel, messageToOpenAIRole };
759
323
  //# sourceMappingURL=index.mjs.map