@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,11 +1,11 @@
1
1
  import { AzureOpenAI } from 'openai';
2
2
  import { ChatXAI as ChatXAI$1 } from '@langchain/xai';
3
3
  import { ChatGenerationChunk } from '@langchain/core/outputs';
4
- import { AIMessage, AIMessageChunk } from '@langchain/core/messages';
4
+ import { isAIMessage, AIMessage, AIMessageChunk } from '@langchain/core/messages';
5
5
  import '@langchain/core/utils/function_calling';
6
6
  import { ChatDeepSeek as ChatDeepSeek$1 } from '@langchain/deepseek';
7
- import { getEndpoint, AzureChatOpenAI as AzureChatOpenAI$1, ChatOpenAI as ChatOpenAI$1, OpenAIClient } from '@langchain/openai';
8
- import { _convertMessagesToOpenAIParams, isReasoningModel, _convertMessagesToOpenAIResponsesParams, _convertOpenAIResponsesDeltaToBaseMessageChunk } from './utils/index.mjs';
7
+ import { getEndpoint, AzureChatOpenAI as AzureChatOpenAI$1, ChatOpenAI as ChatOpenAI$1, OpenAIClient, AzureChatOpenAICompletions, AzureChatOpenAIResponses, ChatOpenAIResponses, ChatOpenAICompletions, getHeadersWithUserAgent } from '@langchain/openai';
8
+ import { isReasoningModel, _convertMessagesToOpenAIParams } from './utils/index.mjs';
9
9
  import '../../common/enum.mjs';
10
10
  import 'nanoid';
11
11
  import '../../messages/core.mjs';
@@ -51,6 +51,153 @@ function normalizeHeaders(headers) {
51
51
  });
52
52
  return Object.fromEntries(output.entries());
53
53
  }
54
+ function getExposedOpenAIClient(completions, responses, preferResponses) {
55
+ const responsesClient = responses.client;
56
+ if (responsesClient?.abortHandler != null) {
57
+ return responsesClient;
58
+ }
59
+ const completionsClient = completions.client;
60
+ if (completionsClient?.abortHandler != null) {
61
+ return completionsClient;
62
+ }
63
+ const delegate = preferResponses ? responses : completions;
64
+ delegate._getClientOptions(undefined);
65
+ return delegate.client;
66
+ }
67
+ function getReasoningParams(baseReasoning, options) {
68
+ let reasoning;
69
+ if (baseReasoning !== undefined) {
70
+ reasoning = {
71
+ ...reasoning,
72
+ ...baseReasoning,
73
+ };
74
+ }
75
+ if (options?.reasoning !== undefined) {
76
+ reasoning = {
77
+ ...reasoning,
78
+ ...options.reasoning,
79
+ };
80
+ }
81
+ if (options?.reasoningEffort !== undefined &&
82
+ reasoning?.effort === undefined) {
83
+ reasoning = {
84
+ ...reasoning,
85
+ effort: options.reasoningEffort,
86
+ };
87
+ }
88
+ return reasoning;
89
+ }
90
+ function getGatedReasoningParams(model, baseReasoning, options) {
91
+ if (!isReasoningModel(model)) {
92
+ return;
93
+ }
94
+ return getReasoningParams(baseReasoning, options);
95
+ }
96
+ function isObject(value) {
97
+ return typeof value === 'object' && value !== null;
98
+ }
99
+ function isOpenAIChatCompletionChunk(value) {
100
+ if (!isObject(value)) {
101
+ return false;
102
+ }
103
+ // Intentionally loose: downstream handlers already tolerate empty choices.
104
+ const { choices } = value;
105
+ return Array.isArray(choices);
106
+ }
107
+ function getOpenAIChatCompletionChunk(value) {
108
+ if (isOpenAIChatCompletionChunk(value)) {
109
+ return value;
110
+ }
111
+ const { data } = value;
112
+ if (isOpenAIChatCompletionChunk(data)) {
113
+ return data;
114
+ }
115
+ return undefined;
116
+ }
117
+ async function* filterOpenAIChatCompletionStream(stream) {
118
+ for await (const item of stream) {
119
+ const chunk = getOpenAIChatCompletionChunk(item);
120
+ if (chunk == null) {
121
+ continue;
122
+ }
123
+ yield chunk;
124
+ }
125
+ }
126
+ async function completionWithFilteredOpenAIStream(request, requestOptions, completionWithRetry) {
127
+ if (request.stream !== true) {
128
+ return (await completionWithRetry(request, requestOptions));
129
+ }
130
+ const stream = await completionWithRetry(request, requestOptions);
131
+ return filterOpenAIChatCompletionStream(stream);
132
+ }
133
+ function attachLibreChatDeltaFields(chunk, delta) {
134
+ if (!AIMessageChunk.isInstance(chunk)) {
135
+ return chunk;
136
+ }
137
+ const libreChatDelta = delta;
138
+ if (libreChatDelta.reasoning != null &&
139
+ chunk.additional_kwargs.reasoning_content == null) {
140
+ chunk.additional_kwargs.reasoning_content = libreChatDelta.reasoning;
141
+ }
142
+ if (libreChatDelta.reasoning_details != null) {
143
+ chunk.additional_kwargs.reasoning_details =
144
+ libreChatDelta.reasoning_details;
145
+ }
146
+ if (libreChatDelta.provider_specific_fields != null) {
147
+ chunk.additional_kwargs.provider_specific_fields =
148
+ libreChatDelta.provider_specific_fields;
149
+ }
150
+ return chunk;
151
+ }
152
+ function attachLibreChatMessageFields(message, rawMessage) {
153
+ if (!isAIMessage(message)) {
154
+ return message;
155
+ }
156
+ if (rawMessage.reasoning != null &&
157
+ message.additional_kwargs.reasoning_content == null) {
158
+ message.additional_kwargs.reasoning_content = rawMessage.reasoning;
159
+ }
160
+ if (rawMessage.reasoning_details != null) {
161
+ message.additional_kwargs.reasoning_details = rawMessage.reasoning_details;
162
+ }
163
+ if (rawMessage.provider_specific_fields != null) {
164
+ message.additional_kwargs.provider_specific_fields =
165
+ rawMessage.provider_specific_fields;
166
+ }
167
+ return message;
168
+ }
169
+ function getCustomOpenAIClientOptions(owner, options) {
170
+ if (!owner.client) {
171
+ const openAIEndpointConfig = {
172
+ baseURL: owner.clientConfig.baseURL,
173
+ };
174
+ const endpoint = getEndpoint(openAIEndpointConfig);
175
+ const params = {
176
+ ...owner.clientConfig,
177
+ baseURL: endpoint,
178
+ timeout: owner.timeout,
179
+ maxRetries: 0,
180
+ };
181
+ if (params.baseURL == null) {
182
+ delete params.baseURL;
183
+ }
184
+ params.defaultHeaders = getHeadersWithUserAgent(params.defaultHeaders);
185
+ owner.client = new CustomOpenAIClient(params);
186
+ }
187
+ const requestOptions = {
188
+ ...owner.clientConfig,
189
+ ...options,
190
+ };
191
+ return requestOptions;
192
+ }
193
+ async function* delayStreamChunks(chunks, delay) {
194
+ for await (const chunk of chunks) {
195
+ yield chunk;
196
+ if (delay != null) {
197
+ await sleep(delay);
198
+ }
199
+ }
200
+ }
54
201
  function createAbortHandler(controller) {
55
202
  return function () {
56
203
  controller.abort();
@@ -110,89 +257,165 @@ class CustomAzureOpenAIClient extends AzureOpenAI {
110
257
  }));
111
258
  }
112
259
  }
113
- /** @ts-expect-error We are intentionally overriding `getReasoningParams` */
114
- class ChatOpenAI extends ChatOpenAI$1 {
115
- _lc_stream_delay;
260
+ class LibreChatOpenAICompletions extends ChatOpenAICompletions {
261
+ includeReasoningContent;
262
+ includeReasoningDetails;
263
+ convertReasoningDetailsToContent;
116
264
  constructor(fields) {
117
265
  super(fields);
118
- this._lc_stream_delay = fields?._lc_stream_delay;
119
- }
120
- get exposedClient() {
121
- return this.client;
266
+ this.includeReasoningContent = fields?.includeReasoningContent;
267
+ this.includeReasoningDetails = fields?.includeReasoningDetails;
268
+ this.convertReasoningDetailsToContent =
269
+ fields?.convertReasoningDetailsToContent;
122
270
  }
123
- static lc_name() {
124
- return 'LibreChatOpenAI';
271
+ _getReasoningParams(options) {
272
+ return getReasoningParams(this.reasoning, options);
125
273
  }
126
274
  _getClientOptions(options) {
127
- if (!this.client) {
128
- const openAIEndpointConfig = {
129
- baseURL: this.clientConfig.baseURL,
275
+ return getCustomOpenAIClientOptions(this, options);
276
+ }
277
+ async completionWithRetry(request, requestOptions) {
278
+ return completionWithFilteredOpenAIStream(request, requestOptions, super.completionWithRetry.bind(this));
279
+ }
280
+ _convertCompletionsDeltaToBaseMessageChunk(delta, rawResponse, defaultRole) {
281
+ return attachLibreChatDeltaFields(super._convertCompletionsDeltaToBaseMessageChunk(delta, rawResponse, defaultRole), delta);
282
+ }
283
+ _convertCompletionsMessageToBaseMessage(message, rawResponse) {
284
+ return attachLibreChatMessageFields(super._convertCompletionsMessageToBaseMessage(message, rawResponse), message);
285
+ }
286
+ async _generate(messages, options, runManager) {
287
+ if (this.includeReasoningContent !== true &&
288
+ this.includeReasoningDetails !== true) {
289
+ return super._generate(messages, options, runManager);
290
+ }
291
+ options.signal?.throwIfAborted();
292
+ const usageMetadata = {};
293
+ const params = this.invocationParams(options);
294
+ const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model, {
295
+ includeReasoningContent: this.includeReasoningContent,
296
+ includeReasoningDetails: this.includeReasoningDetails,
297
+ convertReasoningDetailsToContent: this.convertReasoningDetailsToContent,
298
+ });
299
+ if (params.stream === true) {
300
+ const stream = this._streamResponseChunks(messages, options, runManager);
301
+ const finalChunks = new Map();
302
+ for await (const chunk of stream) {
303
+ chunk.message.response_metadata = {
304
+ ...chunk.generationInfo,
305
+ ...chunk.message.response_metadata,
306
+ };
307
+ const index = typeof chunk.generationInfo?.completion === 'number'
308
+ ? chunk.generationInfo.completion
309
+ : 0;
310
+ const existingChunk = finalChunks.get(index);
311
+ if (existingChunk == null) {
312
+ finalChunks.set(index, chunk);
313
+ }
314
+ else {
315
+ finalChunks.set(index, existingChunk.concat(chunk));
316
+ }
317
+ }
318
+ const generations = Array.from(finalChunks.entries())
319
+ .sort(([aKey], [bKey]) => aKey - bKey)
320
+ .map(([, value]) => value);
321
+ const { functions, function_call } = this.invocationParams(options);
322
+ const promptTokenUsage = await this._getEstimatedTokenCountFromPrompt(messages, functions, function_call);
323
+ const completionTokenUsage = await this._getNumTokensFromGenerations(generations);
324
+ usageMetadata.input_tokens = promptTokenUsage;
325
+ usageMetadata.output_tokens = completionTokenUsage;
326
+ usageMetadata.total_tokens = promptTokenUsage + completionTokenUsage;
327
+ return {
328
+ generations,
329
+ llmOutput: {
330
+ estimatedTokenUsage: {
331
+ promptTokens: usageMetadata.input_tokens,
332
+ completionTokens: usageMetadata.output_tokens,
333
+ totalTokens: usageMetadata.total_tokens,
334
+ },
335
+ },
130
336
  };
131
- const endpoint = getEndpoint(openAIEndpointConfig);
132
- const params = {
133
- ...this.clientConfig,
134
- baseURL: endpoint,
135
- timeout: this.timeout,
136
- maxRetries: 0,
337
+ }
338
+ const data = await this.completionWithRetry({
339
+ ...params,
340
+ stream: false,
341
+ messages: messagesMapped,
342
+ }, {
343
+ signal: options.signal,
344
+ ...options.options,
345
+ });
346
+ const { completion_tokens: completionTokens, prompt_tokens: promptTokens, total_tokens: totalTokens, prompt_tokens_details: promptTokensDetails, completion_tokens_details: completionTokensDetails, } = data.usage ?? {};
347
+ if (completionTokens != null) {
348
+ usageMetadata.output_tokens =
349
+ (usageMetadata.output_tokens ?? 0) + completionTokens;
350
+ }
351
+ if (promptTokens != null) {
352
+ usageMetadata.input_tokens =
353
+ (usageMetadata.input_tokens ?? 0) + promptTokens;
354
+ }
355
+ if (totalTokens != null) {
356
+ usageMetadata.total_tokens =
357
+ (usageMetadata.total_tokens ?? 0) + totalTokens;
358
+ }
359
+ if (promptTokensDetails?.audio_tokens != null ||
360
+ promptTokensDetails?.cached_tokens != null) {
361
+ usageMetadata.input_token_details = {
362
+ ...(promptTokensDetails.audio_tokens != null && {
363
+ audio: promptTokensDetails.audio_tokens,
364
+ }),
365
+ ...(promptTokensDetails.cached_tokens != null && {
366
+ cache_read: promptTokensDetails.cached_tokens,
367
+ }),
137
368
  };
138
- if (params.baseURL == null) {
139
- delete params.baseURL;
140
- }
141
- this.client = new CustomOpenAIClient(params);
142
369
  }
143
- const requestOptions = {
144
- ...this.clientConfig,
145
- ...options,
146
- };
147
- return requestOptions;
148
- }
149
- /**
150
- * Returns backwards compatible reasoning parameters from constructor params and call options
151
- * @internal
152
- */
153
- getReasoningParams(options) {
154
- // apply options in reverse order of importance -- newer options supersede older options
155
- let reasoning;
156
- if (this.reasoning !== undefined) {
157
- reasoning = {
158
- ...reasoning,
159
- ...this.reasoning,
370
+ if (completionTokensDetails?.audio_tokens != null ||
371
+ completionTokensDetails?.reasoning_tokens != null) {
372
+ usageMetadata.output_token_details = {
373
+ ...(completionTokensDetails.audio_tokens != null && {
374
+ audio: completionTokensDetails.audio_tokens,
375
+ }),
376
+ ...(completionTokensDetails.reasoning_tokens != null && {
377
+ reasoning: completionTokensDetails.reasoning_tokens,
378
+ }),
160
379
  };
161
380
  }
162
- if (options?.reasoning !== undefined) {
163
- reasoning = {
164
- ...reasoning,
165
- ...options.reasoning,
381
+ const generations = [];
382
+ for (const part of data.choices) {
383
+ const generation = {
384
+ text: part.message.content ?? '',
385
+ message: this._convertCompletionsMessageToBaseMessage(part.message, data),
386
+ };
387
+ generation.generationInfo = {
388
+ finish_reason: part.finish_reason,
389
+ ...(part.logprobs ? { logprobs: part.logprobs } : {}),
166
390
  };
391
+ if (isAIMessage(generation.message)) {
392
+ generation.message.usage_metadata = usageMetadata;
393
+ }
394
+ generation.message = new AIMessage(Object.fromEntries(Object.entries(generation.message).filter(([key]) => !key.startsWith('lc_'))));
395
+ generations.push(generation);
167
396
  }
168
- return reasoning;
169
- }
170
- _getReasoningParams(options) {
171
- return this.getReasoningParams(options);
397
+ return {
398
+ generations,
399
+ llmOutput: {
400
+ tokenUsage: {
401
+ promptTokens: usageMetadata.input_tokens,
402
+ completionTokens: usageMetadata.output_tokens,
403
+ totalTokens: usageMetadata.total_tokens,
404
+ },
405
+ },
406
+ };
172
407
  }
173
408
  async *_streamResponseChunks(messages, options, runManager) {
174
- if (!this._useResponseApi(options)) {
175
- return yield* this._streamResponseChunks2(messages, options, runManager);
176
- }
177
- const streamIterable = await this.responseApiWithRetry({
178
- ...this.invocationParams(options, { streaming: true }),
179
- input: _convertMessagesToOpenAIResponsesParams(messages, this.model, this.zdrEnabled),
180
- stream: true,
181
- }, options);
182
- for await (const data of streamIterable) {
183
- const chunk = _convertOpenAIResponsesDeltaToBaseMessageChunk(data);
184
- if (chunk == null)
185
- continue;
186
- yield chunk;
187
- if (this._lc_stream_delay != null) {
188
- await sleep(this._lc_stream_delay);
189
- }
190
- await runManager?.handleLLMNewToken(chunk.text || '', undefined, undefined, undefined, undefined, { chunk });
409
+ if (this.includeReasoningContent !== true &&
410
+ this.includeReasoningDetails !== true) {
411
+ yield* super._streamResponseChunks(messages, options, runManager);
412
+ return;
191
413
  }
192
- return;
193
- }
194
- async *_streamResponseChunks2(messages, options, runManager) {
195
- const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model);
414
+ const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model, {
415
+ includeReasoningContent: this.includeReasoningContent,
416
+ includeReasoningDetails: this.includeReasoningDetails,
417
+ convertReasoningDetailsToContent: this.convertReasoningDetailsToContent,
418
+ });
196
419
  const params = {
197
420
  ...this.invocationParams(options, {
198
421
  streaming: true,
@@ -204,49 +427,40 @@ class ChatOpenAI extends ChatOpenAI$1 {
204
427
  const streamIterable = await this.completionWithRetry(params, options);
205
428
  let usage;
206
429
  for await (const data of streamIterable) {
207
- const choice = data.choices[0];
208
- if (data.usage) {
430
+ if (options.signal?.aborted === true) {
431
+ return;
432
+ }
433
+ const choices = data.choices;
434
+ const choice = choices?.[0];
435
+ if (data.usage != null) {
209
436
  usage = data.usage;
210
437
  }
211
- if (!choice) {
438
+ if (choice == null) {
212
439
  continue;
213
440
  }
214
441
  const { delta } = choice;
215
- if (!delta) {
442
+ if (delta == null) {
216
443
  continue;
217
444
  }
218
- const chunk = this._convertOpenAIDeltaToBaseMessageChunk(delta, data, defaultRole);
219
- if ('reasoning_content' in delta) {
220
- chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
221
- }
222
- else if ('reasoning' in delta) {
223
- chunk.additional_kwargs.reasoning_content = delta.reasoning;
224
- }
225
- if ('provider_specific_fields' in delta) {
226
- chunk.additional_kwargs.provider_specific_fields =
227
- delta.provider_specific_fields;
228
- }
445
+ const chunk = this._convertCompletionsDeltaToBaseMessageChunk(delta, data, defaultRole);
229
446
  defaultRole = delta.role ?? defaultRole;
230
447
  const newTokenIndices = {
231
448
  prompt: options.promptIndex ?? 0,
232
- completion: choice.index ?? 0,
449
+ completion: choice.index,
233
450
  };
234
451
  if (typeof chunk.content !== 'string') {
235
452
  // eslint-disable-next-line no-console
236
453
  console.log('[WARNING]: Received non-string content from OpenAI. This is currently not supported.');
237
454
  continue;
238
455
  }
239
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
240
456
  const generationInfo = { ...newTokenIndices };
241
457
  if (choice.finish_reason != null) {
242
458
  generationInfo.finish_reason = choice.finish_reason;
243
- // Only include system fingerprint in the last chunk for now
244
- // to avoid concatenation issues
245
459
  generationInfo.system_fingerprint = data.system_fingerprint;
246
460
  generationInfo.model_name = data.model;
247
461
  generationInfo.service_tier = data.service_tier;
248
462
  }
249
- if (this.logprobs == true) {
463
+ if (this.logprobs === true) {
250
464
  generationInfo.logprobs = choice.logprobs;
251
465
  }
252
466
  const generationChunk = new ChatGenerationChunk({
@@ -255,10 +469,7 @@ class ChatOpenAI extends ChatOpenAI$1 {
255
469
  generationInfo,
256
470
  });
257
471
  yield generationChunk;
258
- if (this._lc_stream_delay != null) {
259
- await sleep(this._lc_stream_delay);
260
- }
261
- await runManager?.handleLLMNewToken(generationChunk.text || '', newTokenIndices, undefined, undefined, undefined, { chunk: generationChunk });
472
+ await runManager?.handleLLMNewToken(generationChunk.text, newTokenIndices, undefined, undefined, undefined, { chunk: generationChunk });
262
473
  }
263
474
  if (usage) {
264
475
  const inputTokenDetails = {
@@ -280,9 +491,7 @@ class ChatOpenAI extends ChatOpenAI$1 {
280
491
  const generationChunk = new ChatGenerationChunk({
281
492
  message: new AIMessageChunk({
282
493
  content: '',
283
- response_metadata: {
284
- usage: { ...usage },
285
- },
494
+ response_metadata: { usage: { ...usage } },
286
495
  usage_metadata: {
287
496
  input_tokens: usage.prompt_tokens,
288
497
  output_tokens: usage.completion_tokens,
@@ -298,54 +507,27 @@ class ChatOpenAI extends ChatOpenAI$1 {
298
507
  text: '',
299
508
  });
300
509
  yield generationChunk;
301
- if (this._lc_stream_delay != null) {
302
- await sleep(this._lc_stream_delay);
303
- }
510
+ await runManager?.handleLLMNewToken(generationChunk.text, {
511
+ prompt: 0,
512
+ completion: 0,
513
+ }, undefined, undefined, undefined, { chunk: generationChunk });
304
514
  }
305
515
  if (options.signal?.aborted === true) {
306
516
  throw new Error('AbortError');
307
517
  }
308
518
  }
309
519
  }
310
- /** @ts-expect-error We are intentionally overriding `getReasoningParams` */
311
- class AzureChatOpenAI extends AzureChatOpenAI$1 {
312
- _lc_stream_delay;
313
- constructor(fields) {
314
- super(fields);
315
- this._lc_stream_delay = fields?._lc_stream_delay;
316
- }
317
- get exposedClient() {
318
- return this.client;
319
- }
320
- static lc_name() {
321
- return 'LibreChatAzureOpenAI';
520
+ class LibreChatOpenAIResponses extends ChatOpenAIResponses {
521
+ _getReasoningParams(options) {
522
+ return getReasoningParams(this.reasoning, options);
322
523
  }
323
- /**
324
- * Returns backwards compatible reasoning parameters from constructor params and call options
325
- * @internal
326
- */
327
- getReasoningParams(options) {
328
- if (!isReasoningModel(this.model)) {
329
- return;
330
- }
331
- // apply options in reverse order of importance -- newer options supersede older options
332
- let reasoning;
333
- if (this.reasoning !== undefined) {
334
- reasoning = {
335
- ...reasoning,
336
- ...this.reasoning,
337
- };
338
- }
339
- if (options?.reasoning !== undefined) {
340
- reasoning = {
341
- ...reasoning,
342
- ...options.reasoning,
343
- };
344
- }
345
- return reasoning;
524
+ _getClientOptions(options) {
525
+ return getCustomOpenAIClientOptions(this, options);
346
526
  }
527
+ }
528
+ class LibreChatAzureOpenAICompletions extends AzureChatOpenAICompletions {
347
529
  _getReasoningParams(options) {
348
- return this.getReasoningParams(options);
530
+ return getGatedReasoningParams(this.model, this.reasoning, options);
349
531
  }
350
532
  _getClientOptions(options) {
351
533
  if (!this.client) {
@@ -399,120 +581,22 @@ class AzureChatOpenAI extends AzureChatOpenAI$1 {
399
581
  }
400
582
  return requestOptions;
401
583
  }
402
- async *_streamResponseChunks(messages, options, runManager) {
403
- if (!this._useResponseApi(options)) {
404
- return yield* super._streamResponseChunks(messages, options, runManager);
405
- }
406
- const streamIterable = await this.responseApiWithRetry({
407
- ...this.invocationParams(options, { streaming: true }),
408
- input: _convertMessagesToOpenAIResponsesParams(messages, this.model, this.zdrEnabled),
409
- stream: true,
410
- }, options);
411
- for await (const data of streamIterable) {
412
- const chunk = _convertOpenAIResponsesDeltaToBaseMessageChunk(data);
413
- if (chunk == null)
414
- continue;
415
- yield chunk;
416
- if (this._lc_stream_delay != null) {
417
- await sleep(this._lc_stream_delay);
418
- }
419
- await runManager?.handleLLMNewToken(chunk.text || '', undefined, undefined, undefined, undefined, { chunk });
420
- }
421
- return;
584
+ async completionWithRetry(request, requestOptions) {
585
+ return completionWithFilteredOpenAIStream(request, requestOptions, super.completionWithRetry.bind(this));
422
586
  }
423
587
  }
424
- class ChatDeepSeek extends ChatDeepSeek$1 {
425
- get exposedClient() {
426
- return this.client;
427
- }
428
- static lc_name() {
429
- return 'LibreChatDeepSeek';
430
- }
431
- _convertMessages(messages) {
432
- return _convertMessagesToOpenAIParams(messages, this.model, {
433
- includeReasoningContent: true,
434
- });
435
- }
436
- async _generate(messages, options, runManager) {
437
- const params = this.invocationParams(options);
438
- if (params.stream === true) {
439
- return super._generate(messages, options ?? {}, runManager);
440
- }
441
- const messagesMapped = this._convertMessages(messages);
442
- const data = await this.completionWithRetry({
443
- ...params,
444
- stream: false,
445
- messages: messagesMapped,
446
- }, {
447
- signal: options?.signal,
448
- ...options?.options,
449
- });
450
- const { completion_tokens, prompt_tokens, total_tokens } = data.usage ?? {};
451
- const generations = [];
452
- for (const part of data.choices ?? []) {
453
- const text = part.message.content ?? '';
454
- const generation = {
455
- text: typeof text === 'string' ? text : '',
456
- message: this._convertResponseToMessage(part, data),
457
- };
458
- generation.generationInfo = {
459
- ...(part.finish_reason != null
460
- ? { finish_reason: part.finish_reason }
461
- : {}),
462
- ...(part.logprobs ? { logprobs: part.logprobs } : {}),
463
- };
464
- generations.push(generation);
465
- }
466
- return {
467
- generations,
468
- llmOutput: {
469
- tokenUsage: {
470
- completionTokens: completion_tokens,
471
- promptTokens: prompt_tokens,
472
- totalTokens: total_tokens,
473
- },
474
- },
475
- };
476
- }
477
- _convertResponseToMessage(choice, data) {
478
- const { message } = choice;
479
- const rawToolCalls = message.tool_calls;
480
- const toolCalls = rawToolCalls?.map((tc) => ({
481
- id: tc.id,
482
- name: tc.function.name,
483
- args: JSON.parse(tc.function.arguments || '{}'),
484
- type: 'tool_call',
485
- }));
486
- const additional_kwargs = {};
487
- if (rawToolCalls) {
488
- additional_kwargs.tool_calls = rawToolCalls;
489
- }
490
- if ('reasoning_content' in message &&
491
- message.reasoning_content != null &&
492
- message.reasoning_content !== '') {
493
- additional_kwargs.reasoning_content = message.reasoning_content;
494
- }
495
- return new AIMessage({
496
- content: message.content ?? '',
497
- tool_calls: toolCalls,
498
- additional_kwargs,
499
- usage_metadata: data.usage
500
- ? {
501
- input_tokens: data.usage.prompt_tokens,
502
- output_tokens: data.usage.completion_tokens,
503
- total_tokens: data.usage.total_tokens,
504
- }
505
- : undefined,
506
- response_metadata: {
507
- model_name: data.model,
508
- system_fingerprint: data.system_fingerprint,
509
- finish_reason: choice.finish_reason,
510
- },
511
- });
588
+ class LibreChatAzureOpenAIResponses extends AzureChatOpenAIResponses {
589
+ _getReasoningParams(options) {
590
+ return getGatedReasoningParams(this.model, this.reasoning, options);
512
591
  }
513
592
  _getClientOptions(options) {
514
593
  if (!this.client) {
515
594
  const openAIEndpointConfig = {
595
+ azureOpenAIApiDeploymentName: this.azureOpenAIApiDeploymentName,
596
+ azureOpenAIApiInstanceName: this.azureOpenAIApiInstanceName,
597
+ azureOpenAIApiKey: this.azureOpenAIApiKey,
598
+ azureOpenAIBasePath: this.azureOpenAIBasePath,
599
+ azureADTokenProvider: this.azureADTokenProvider,
516
600
  baseURL: this.clientConfig.baseURL,
517
601
  };
518
602
  const endpoint = getEndpoint(openAIEndpointConfig);
@@ -522,311 +606,227 @@ class ChatDeepSeek extends ChatDeepSeek$1 {
522
606
  timeout: this.timeout,
523
607
  maxRetries: 0,
524
608
  };
609
+ if (!this.azureADTokenProvider) {
610
+ params.apiKey = openAIEndpointConfig.azureOpenAIApiKey;
611
+ }
525
612
  if (params.baseURL == null) {
526
613
  delete params.baseURL;
527
614
  }
528
- this.client = new CustomOpenAIClient(params);
615
+ const defaultHeaders = normalizeHeaders(params.defaultHeaders);
616
+ params.defaultHeaders = {
617
+ ...params.defaultHeaders,
618
+ 'User-Agent': defaultHeaders['User-Agent'] != null
619
+ ? `${defaultHeaders['User-Agent']}: librechat-azure-openai-v2`
620
+ : 'librechat-azure-openai-v2',
621
+ };
622
+ this.client = new CustomAzureOpenAIClient({
623
+ apiVersion: this.azureOpenAIApiVersion,
624
+ azureADTokenProvider: this.azureADTokenProvider,
625
+ ...params,
626
+ });
529
627
  }
530
628
  const requestOptions = {
531
629
  ...this.clientConfig,
532
630
  ...options,
533
631
  };
632
+ if (this.azureOpenAIApiKey != null) {
633
+ requestOptions.headers = {
634
+ 'api-key': this.azureOpenAIApiKey,
635
+ ...requestOptions.headers,
636
+ };
637
+ requestOptions.query = {
638
+ 'api-version': this.azureOpenAIApiVersion,
639
+ ...requestOptions.query,
640
+ };
641
+ }
534
642
  return requestOptions;
535
643
  }
536
- async *_streamResponseChunks(messages, options, runManager) {
537
- const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model, {
538
- includeReasoningContent: true,
539
- });
540
- const params = {
541
- ...this.invocationParams(options, {
542
- streaming: true,
543
- }),
544
- messages: messagesMapped,
545
- stream: true,
546
- };
547
- let defaultRole;
548
- const streamIterable = await this.completionWithRetry(params, options);
549
- let usage;
550
- for await (const data of streamIterable) {
551
- const choice = data.choices[0];
552
- if (data.usage) {
553
- usage = data.usage;
554
- }
555
- if (!choice) {
556
- continue;
557
- }
558
- const { delta } = choice;
559
- if (!delta) {
560
- continue;
561
- }
562
- const chunk = this._convertOpenAIDeltaToBaseMessageChunk(delta, data, defaultRole);
563
- if ('reasoning_content' in delta) {
564
- chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
565
- }
566
- defaultRole = delta.role ?? defaultRole;
567
- const newTokenIndices = {
568
- prompt: options.promptIndex ?? 0,
569
- completion: choice.index ?? 0,
644
+ }
645
+ function withLibreChatOpenAIFields(fields) {
646
+ const nextFields = fields ?? {};
647
+ return {
648
+ ...nextFields,
649
+ completions: nextFields.completions ?? new LibreChatOpenAICompletions(nextFields),
650
+ responses: nextFields.responses ?? new LibreChatOpenAIResponses(nextFields),
651
+ };
652
+ }
653
+ class ChatOpenAI extends ChatOpenAI$1 {
654
+ _lc_stream_delay;
655
+ constructor(fields) {
656
+ super(withLibreChatOpenAIFields(fields));
657
+ this._lc_stream_delay = fields?._lc_stream_delay;
658
+ }
659
+ get exposedClient() {
660
+ return getExposedOpenAIClient(this.completions, this.responses, this._useResponsesApi(undefined));
661
+ }
662
+ static lc_name() {
663
+ return 'LibreChatOpenAI';
664
+ }
665
+ _getClientOptions(options) {
666
+ if (!this.client) {
667
+ const openAIEndpointConfig = {
668
+ baseURL: this.clientConfig.baseURL,
570
669
  };
571
- if (typeof chunk.content !== 'string') {
572
- // eslint-disable-next-line no-console
573
- console.log('[WARNING]: Received non-string content from OpenAI. This is currently not supported.');
574
- continue;
670
+ const endpoint = getEndpoint(openAIEndpointConfig);
671
+ const params = {
672
+ ...this.clientConfig,
673
+ baseURL: endpoint,
674
+ timeout: this.timeout,
675
+ maxRetries: 0,
676
+ };
677
+ if (params.baseURL == null) {
678
+ delete params.baseURL;
575
679
  }
576
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
577
- const generationInfo = { ...newTokenIndices };
578
- if (choice.finish_reason != null) {
579
- generationInfo.finish_reason = choice.finish_reason;
580
- generationInfo.system_fingerprint = data.system_fingerprint;
581
- generationInfo.model_name = data.model;
582
- generationInfo.service_tier = data.service_tier;
680
+ this.client = new CustomOpenAIClient(params);
681
+ }
682
+ const requestOptions = {
683
+ ...this.clientConfig,
684
+ ...options,
685
+ };
686
+ return requestOptions;
687
+ }
688
+ /**
689
+ * Returns backwards compatible reasoning parameters from constructor params and call options
690
+ * @internal
691
+ */
692
+ getReasoningParams(options) {
693
+ return getReasoningParams(this.reasoning, options);
694
+ }
695
+ _getReasoningParams(options) {
696
+ return this.getReasoningParams(options);
697
+ }
698
+ async *_streamResponseChunks(messages, options, runManager) {
699
+ yield* delayStreamChunks(super._streamResponseChunks(messages, options, runManager), this._lc_stream_delay);
700
+ }
701
+ }
702
+ class AzureChatOpenAI extends AzureChatOpenAI$1 {
703
+ _lc_stream_delay;
704
+ constructor(fields) {
705
+ super(fields);
706
+ this.completions = new LibreChatAzureOpenAICompletions(fields);
707
+ this.responses = new LibreChatAzureOpenAIResponses(fields);
708
+ this._lc_stream_delay = fields?._lc_stream_delay;
709
+ }
710
+ get exposedClient() {
711
+ return getExposedOpenAIClient(this.completions, this.responses, this._useResponsesApi(undefined));
712
+ }
713
+ static lc_name() {
714
+ return 'LibreChatAzureOpenAI';
715
+ }
716
+ /**
717
+ * Returns backwards compatible reasoning parameters from constructor params and call options
718
+ * @internal
719
+ */
720
+ getReasoningParams(options) {
721
+ return getGatedReasoningParams(this.model, this.reasoning, options);
722
+ }
723
+ _getReasoningParams(options) {
724
+ return this.getReasoningParams(options);
725
+ }
726
+ _getClientOptions(options) {
727
+ if (!this.client) {
728
+ const openAIEndpointConfig = {
729
+ azureOpenAIApiDeploymentName: this.azureOpenAIApiDeploymentName,
730
+ azureOpenAIApiInstanceName: this.azureOpenAIApiInstanceName,
731
+ azureOpenAIApiKey: this.azureOpenAIApiKey,
732
+ azureOpenAIBasePath: this.azureOpenAIBasePath,
733
+ azureADTokenProvider: this.azureADTokenProvider,
734
+ baseURL: this.clientConfig.baseURL,
735
+ };
736
+ const endpoint = getEndpoint(openAIEndpointConfig);
737
+ const params = {
738
+ ...this.clientConfig,
739
+ baseURL: endpoint,
740
+ timeout: this.timeout,
741
+ maxRetries: 0,
742
+ };
743
+ if (!this.azureADTokenProvider) {
744
+ params.apiKey = openAIEndpointConfig.azureOpenAIApiKey;
583
745
  }
584
- if (this.logprobs == true) {
585
- generationInfo.logprobs = choice.logprobs;
746
+ if (params.baseURL == null) {
747
+ delete params.baseURL;
586
748
  }
587
- const generationChunk = new ChatGenerationChunk({
588
- message: chunk,
589
- text: chunk.content,
590
- generationInfo,
749
+ const defaultHeaders = normalizeHeaders(params.defaultHeaders);
750
+ params.defaultHeaders = {
751
+ ...params.defaultHeaders,
752
+ 'User-Agent': defaultHeaders['User-Agent'] != null
753
+ ? `${defaultHeaders['User-Agent']}: librechat-azure-openai-v2`
754
+ : 'librechat-azure-openai-v2',
755
+ };
756
+ this.client = new CustomAzureOpenAIClient({
757
+ apiVersion: this.azureOpenAIApiVersion,
758
+ azureADTokenProvider: this.azureADTokenProvider,
759
+ ...params,
591
760
  });
592
- yield generationChunk;
593
- await runManager?.handleLLMNewToken(generationChunk.text || '', newTokenIndices, undefined, undefined, undefined, { chunk: generationChunk });
594
761
  }
595
- if (usage) {
596
- const inputTokenDetails = {
597
- ...(usage.prompt_tokens_details?.audio_tokens != null && {
598
- audio: usage.prompt_tokens_details.audio_tokens,
599
- }),
600
- ...(usage.prompt_tokens_details?.cached_tokens != null && {
601
- cache_read: usage.prompt_tokens_details.cached_tokens,
602
- }),
762
+ const requestOptions = {
763
+ ...this.clientConfig,
764
+ ...options,
765
+ };
766
+ if (this.azureOpenAIApiKey != null) {
767
+ requestOptions.headers = {
768
+ 'api-key': this.azureOpenAIApiKey,
769
+ ...requestOptions.headers,
603
770
  };
604
- const outputTokenDetails = {
605
- ...(usage.completion_tokens_details?.audio_tokens != null && {
606
- audio: usage.completion_tokens_details.audio_tokens,
607
- }),
608
- ...(usage.completion_tokens_details?.reasoning_tokens != null && {
609
- reasoning: usage.completion_tokens_details.reasoning_tokens,
610
- }),
771
+ requestOptions.query = {
772
+ 'api-version': this.azureOpenAIApiVersion,
773
+ ...requestOptions.query,
611
774
  };
612
- const generationChunk = new ChatGenerationChunk({
613
- message: new AIMessageChunk({
614
- content: '',
615
- response_metadata: {
616
- usage: { ...usage },
617
- },
618
- usage_metadata: {
619
- input_tokens: usage.prompt_tokens,
620
- output_tokens: usage.completion_tokens,
621
- total_tokens: usage.total_tokens,
622
- ...(Object.keys(inputTokenDetails).length > 0 && {
623
- input_token_details: inputTokenDetails,
624
- }),
625
- ...(Object.keys(outputTokenDetails).length > 0 && {
626
- output_token_details: outputTokenDetails,
627
- }),
628
- },
629
- }),
630
- text: '',
631
- });
632
- yield generationChunk;
633
- }
634
- if (options.signal?.aborted === true) {
635
- throw new Error('AbortError');
636
775
  }
776
+ return requestOptions;
777
+ }
778
+ async *_streamResponseChunks(messages, options, runManager) {
779
+ yield* delayStreamChunks(super._streamResponseChunks(messages, options, runManager), this._lc_stream_delay);
637
780
  }
638
781
  }
639
- class ChatMoonshot extends ChatOpenAI {
640
- static lc_name() {
641
- return 'LibreChatMoonshot';
782
+ class ChatDeepSeek extends ChatDeepSeek$1 {
783
+ _lc_stream_delay;
784
+ constructor(fields) {
785
+ super(fields);
786
+ this._lc_stream_delay = fields?._lc_stream_delay;
642
787
  }
643
- _convertMessages(messages) {
644
- return _convertMessagesToOpenAIParams(messages, this.model, {
645
- includeReasoningContent: true,
646
- });
788
+ get exposedClient() {
789
+ return this.client;
647
790
  }
648
- async _generate(messages, options, runManager) {
649
- const params = this.invocationParams(options);
650
- if (params.stream === true) {
651
- return super._generate(messages, options, runManager);
652
- }
653
- const messagesMapped = this._convertMessages(messages);
654
- const data = await this.completionWithRetry({
655
- ...params,
656
- stream: false,
657
- messages: messagesMapped,
658
- }, {
659
- signal: options.signal,
660
- ...options.options,
661
- });
662
- const { completion_tokens, prompt_tokens, total_tokens } = data.usage ?? {};
663
- const generations = [];
664
- for (const part of data.choices ?? []) {
665
- const text = part.message.content ?? '';
666
- const generation = {
667
- text: typeof text === 'string' ? text : '',
668
- message: this._convertResponseToMessage(part, data),
791
+ static lc_name() {
792
+ return 'LibreChatDeepSeek';
793
+ }
794
+ _getClientOptions(options) {
795
+ if (!this.client) {
796
+ const openAIEndpointConfig = {
797
+ baseURL: this.clientConfig.baseURL,
669
798
  };
670
- generation.generationInfo = {
671
- ...(part.finish_reason ? { finish_reason: part.finish_reason } : {}),
672
- ...(part.logprobs ? { logprobs: part.logprobs } : {}),
799
+ const endpoint = getEndpoint(openAIEndpointConfig);
800
+ const params = {
801
+ ...this.clientConfig,
802
+ baseURL: endpoint,
803
+ timeout: this.timeout,
804
+ maxRetries: 0,
673
805
  };
674
- generations.push(generation);
806
+ if (params.baseURL == null) {
807
+ delete params.baseURL;
808
+ }
809
+ this.client = new CustomOpenAIClient(params);
675
810
  }
676
- return {
677
- generations,
678
- llmOutput: {
679
- tokenUsage: {
680
- completionTokens: completion_tokens,
681
- promptTokens: prompt_tokens,
682
- totalTokens: total_tokens,
683
- },
684
- },
811
+ const requestOptions = {
812
+ ...this.clientConfig,
813
+ ...options,
685
814
  };
686
- }
687
- _convertResponseToMessage(choice, data) {
688
- const { message } = choice;
689
- const rawToolCalls = message.tool_calls;
690
- const toolCalls = rawToolCalls?.map((tc) => ({
691
- id: tc.id,
692
- name: tc.function.name,
693
- args: JSON.parse(tc.function.arguments || '{}'),
694
- type: 'tool_call',
695
- }));
696
- const additional_kwargs = {};
697
- if (rawToolCalls) {
698
- additional_kwargs.tool_calls = rawToolCalls;
699
- }
700
- if ('reasoning_content' in message &&
701
- message.reasoning_content != null &&
702
- message.reasoning_content !== '') {
703
- additional_kwargs.reasoning_content = message.reasoning_content;
704
- }
705
- return new AIMessage({
706
- content: message.content ?? '',
707
- tool_calls: toolCalls,
708
- additional_kwargs,
709
- usage_metadata: data.usage
710
- ? {
711
- input_tokens: data.usage.prompt_tokens,
712
- output_tokens: data.usage.completion_tokens,
713
- total_tokens: data.usage.total_tokens,
714
- }
715
- : undefined,
716
- response_metadata: {
717
- model_name: data.model,
718
- system_fingerprint: data.system_fingerprint,
719
- finish_reason: choice.finish_reason,
720
- },
721
- });
815
+ return requestOptions;
722
816
  }
723
817
  async *_streamResponseChunks(messages, options, runManager) {
724
- const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model, {
818
+ yield* delayStreamChunks(super._streamResponseChunks(messages, options, runManager), this._lc_stream_delay);
819
+ }
820
+ }
821
+ class ChatMoonshot extends ChatOpenAI {
822
+ constructor(fields) {
823
+ super({
824
+ ...fields,
725
825
  includeReasoningContent: true,
726
826
  });
727
- const params = {
728
- ...this.invocationParams(options, {
729
- streaming: true,
730
- }),
731
- messages: messagesMapped,
732
- stream: true,
733
- };
734
- let defaultRole;
735
- const streamIterable = await this.completionWithRetry(params, options);
736
- let usage;
737
- for await (const data of streamIterable) {
738
- const choice = data.choices[0];
739
- if (data.usage) {
740
- usage = data.usage;
741
- }
742
- if (!choice) {
743
- continue;
744
- }
745
- const { delta } = choice;
746
- if (!delta) {
747
- continue;
748
- }
749
- const chunk = this._convertOpenAIDeltaToBaseMessageChunk(delta, data, defaultRole);
750
- if ('reasoning_content' in delta) {
751
- chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
752
- }
753
- defaultRole = delta.role ?? defaultRole;
754
- const newTokenIndices = {
755
- prompt: options.promptIndex ?? 0,
756
- completion: choice.index ?? 0,
757
- };
758
- if (typeof chunk.content !== 'string') {
759
- // eslint-disable-next-line no-console
760
- console.log('[WARNING]: Received non-string content from OpenAI. This is currently not supported.');
761
- continue;
762
- }
763
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
764
- const generationInfo = { ...newTokenIndices };
765
- if (choice.finish_reason != null) {
766
- generationInfo.finish_reason = choice.finish_reason;
767
- generationInfo.system_fingerprint = data.system_fingerprint;
768
- generationInfo.model_name = data.model;
769
- generationInfo.service_tier = data.service_tier;
770
- }
771
- if (this.logprobs == true) {
772
- generationInfo.logprobs = choice.logprobs;
773
- }
774
- const generationChunk = new ChatGenerationChunk({
775
- message: chunk,
776
- text: chunk.content,
777
- generationInfo,
778
- });
779
- yield generationChunk;
780
- if (this._lc_stream_delay != null) {
781
- await sleep(this._lc_stream_delay);
782
- }
783
- await runManager?.handleLLMNewToken(generationChunk.text || '', newTokenIndices, undefined, undefined, undefined, { chunk: generationChunk });
784
- }
785
- if (usage) {
786
- const inputTokenDetails = {
787
- ...(usage.prompt_tokens_details?.audio_tokens != null && {
788
- audio: usage.prompt_tokens_details.audio_tokens,
789
- }),
790
- ...(usage.prompt_tokens_details?.cached_tokens != null && {
791
- cache_read: usage.prompt_tokens_details.cached_tokens,
792
- }),
793
- };
794
- const outputTokenDetails = {
795
- ...(usage.completion_tokens_details?.audio_tokens != null && {
796
- audio: usage.completion_tokens_details.audio_tokens,
797
- }),
798
- ...(usage.completion_tokens_details?.reasoning_tokens != null && {
799
- reasoning: usage.completion_tokens_details.reasoning_tokens,
800
- }),
801
- };
802
- const generationChunk = new ChatGenerationChunk({
803
- message: new AIMessageChunk({
804
- content: '',
805
- response_metadata: {
806
- usage: { ...usage },
807
- },
808
- usage_metadata: {
809
- input_tokens: usage.prompt_tokens,
810
- output_tokens: usage.completion_tokens,
811
- total_tokens: usage.total_tokens,
812
- ...(Object.keys(inputTokenDetails).length > 0 && {
813
- input_token_details: inputTokenDetails,
814
- }),
815
- ...(Object.keys(outputTokenDetails).length > 0 && {
816
- output_token_details: outputTokenDetails,
817
- }),
818
- },
819
- }),
820
- text: '',
821
- });
822
- yield generationChunk;
823
- if (this._lc_stream_delay != null) {
824
- await sleep(this._lc_stream_delay);
825
- }
826
- }
827
- if (options.signal?.aborted === true) {
828
- throw new Error('AbortError');
829
- }
827
+ }
828
+ static lc_name() {
829
+ return 'LibreChatMoonshot';
830
830
  }
831
831
  }
832
832
  class ChatXAI extends ChatXAI$1 {
@@ -875,143 +875,7 @@ class ChatXAI extends ChatXAI$1 {
875
875
  return requestOptions;
876
876
  }
877
877
  async *_streamResponseChunks(messages, options, runManager) {
878
- const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model);
879
- const params = {
880
- ...this.invocationParams(options, {
881
- streaming: true,
882
- }),
883
- messages: messagesMapped,
884
- stream: true,
885
- };
886
- let defaultRole;
887
- const streamIterable = await this.completionWithRetry(params, options);
888
- let usage;
889
- for await (const data of streamIterable) {
890
- const choice = data.choices[0];
891
- if (data.usage) {
892
- usage = data.usage;
893
- }
894
- if (!choice) {
895
- continue;
896
- }
897
- const { delta } = choice;
898
- if (!delta) {
899
- continue;
900
- }
901
- const chunk = this._convertOpenAIDeltaToBaseMessageChunk(delta, data, defaultRole);
902
- if (chunk.usage_metadata != null) {
903
- chunk.usage_metadata = {
904
- input_tokens: chunk.usage_metadata.input_tokens ?? 0,
905
- output_tokens: chunk.usage_metadata.output_tokens ?? 0,
906
- total_tokens: chunk.usage_metadata.total_tokens ?? 0,
907
- };
908
- }
909
- if ('reasoning_content' in delta) {
910
- chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
911
- }
912
- defaultRole = delta.role ?? defaultRole;
913
- const newTokenIndices = {
914
- prompt: options.promptIndex ?? 0,
915
- completion: choice.index ?? 0,
916
- };
917
- if (typeof chunk.content !== 'string') {
918
- // eslint-disable-next-line no-console
919
- console.log('[WARNING]: Received non-string content from OpenAI. This is currently not supported.');
920
- continue;
921
- }
922
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
923
- const generationInfo = { ...newTokenIndices };
924
- if (choice.finish_reason != null) {
925
- generationInfo.finish_reason = choice.finish_reason;
926
- // Only include system fingerprint in the last chunk for now
927
- // to avoid concatenation issues
928
- generationInfo.system_fingerprint = data.system_fingerprint;
929
- generationInfo.model_name = data.model;
930
- generationInfo.service_tier = data.service_tier;
931
- }
932
- if (this.logprobs == true) {
933
- generationInfo.logprobs = choice.logprobs;
934
- }
935
- const generationChunk = new ChatGenerationChunk({
936
- message: chunk,
937
- text: chunk.content,
938
- generationInfo,
939
- });
940
- yield generationChunk;
941
- if (this._lc_stream_delay != null) {
942
- await sleep(this._lc_stream_delay);
943
- }
944
- await runManager?.handleLLMNewToken(generationChunk.text || '', newTokenIndices, undefined, undefined, undefined, { chunk: generationChunk });
945
- }
946
- if (usage) {
947
- // Type assertion for xAI-specific usage structure
948
- const xaiUsage = usage;
949
- const inputTokenDetails = {
950
- // Standard OpenAI fields
951
- ...(usage.prompt_tokens_details?.audio_tokens != null && {
952
- audio: usage.prompt_tokens_details.audio_tokens,
953
- }),
954
- ...(usage.prompt_tokens_details?.cached_tokens != null && {
955
- cache_read: usage.prompt_tokens_details.cached_tokens,
956
- }),
957
- // Add xAI-specific prompt token details if they exist
958
- ...(xaiUsage.prompt_tokens_details?.text_tokens != null && {
959
- text: xaiUsage.prompt_tokens_details.text_tokens,
960
- }),
961
- ...(xaiUsage.prompt_tokens_details?.image_tokens != null && {
962
- image: xaiUsage.prompt_tokens_details.image_tokens,
963
- }),
964
- };
965
- const outputTokenDetails = {
966
- // Standard OpenAI fields
967
- ...(usage.completion_tokens_details?.audio_tokens != null && {
968
- audio: usage.completion_tokens_details.audio_tokens,
969
- }),
970
- ...(usage.completion_tokens_details?.reasoning_tokens != null && {
971
- reasoning: usage.completion_tokens_details.reasoning_tokens,
972
- }),
973
- // Add xAI-specific completion token details if they exist
974
- ...(xaiUsage.completion_tokens_details?.accepted_prediction_tokens !=
975
- null && {
976
- accepted_prediction: xaiUsage.completion_tokens_details.accepted_prediction_tokens,
977
- }),
978
- ...(xaiUsage.completion_tokens_details?.rejected_prediction_tokens !=
979
- null && {
980
- rejected_prediction: xaiUsage.completion_tokens_details.rejected_prediction_tokens,
981
- }),
982
- };
983
- const generationChunk = new ChatGenerationChunk({
984
- message: new AIMessageChunk({
985
- content: '',
986
- response_metadata: {
987
- usage: { ...usage },
988
- // Include xAI-specific metadata if it exists
989
- ...(xaiUsage.num_sources_used != null && {
990
- num_sources_used: xaiUsage.num_sources_used,
991
- }),
992
- },
993
- usage_metadata: {
994
- input_tokens: usage.prompt_tokens,
995
- output_tokens: usage.completion_tokens,
996
- total_tokens: usage.total_tokens,
997
- ...(Object.keys(inputTokenDetails).length > 0 && {
998
- input_token_details: inputTokenDetails,
999
- }),
1000
- ...(Object.keys(outputTokenDetails).length > 0 && {
1001
- output_token_details: outputTokenDetails,
1002
- }),
1003
- },
1004
- }),
1005
- text: '',
1006
- });
1007
- yield generationChunk;
1008
- if (this._lc_stream_delay != null) {
1009
- await sleep(this._lc_stream_delay);
1010
- }
1011
- }
1012
- if (options.signal?.aborted === true) {
1013
- throw new Error('AbortError');
1014
- }
878
+ yield* delayStreamChunks(super._streamResponseChunks(messages, options, runManager), this._lc_stream_delay);
1015
879
  }
1016
880
  }
1017
881