@librechat/agents 2.3.94 → 2.3.95

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.
@@ -1,8 +1,20 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { ToolMessage, BaseMessage , HumanMessage, AIMessage, SystemMessage, getBufferString } from '@langchain/core/messages';
2
+ import {
3
+ AIMessage,
4
+ ToolMessage,
5
+ BaseMessage,
6
+ HumanMessage,
7
+ SystemMessage,
8
+ getBufferString,
9
+ } from '@langchain/core/messages';
3
10
  import type { MessageContentImageUrl } from '@langchain/core/messages';
4
11
  import type { ToolCall } from '@langchain/core/messages/tool';
5
- import type { MessageContentComplex, ToolCallPart, TPayload, TMessage } from '@/types';
12
+ import type {
13
+ MessageContentComplex,
14
+ ToolCallPart,
15
+ TPayload,
16
+ TMessage,
17
+ } from '@/types';
6
18
  import { Providers, ContentTypes } from '@/common';
7
19
 
8
20
  interface VisionMessageParams {
@@ -22,7 +34,11 @@ interface VisionMessageParams {
22
34
  * @param {VisionMessageParams} params - The parameters for formatting.
23
35
  * @returns {Object} - The formatted message.
24
36
  */
25
- export const formatVisionMessage = ({ message, image_urls, endpoint }: VisionMessageParams): {
37
+ export const formatVisionMessage = ({
38
+ message,
39
+ image_urls,
40
+ endpoint,
41
+ }: VisionMessageParams): {
26
42
  role: string;
27
43
  content: MessageContentComplex[];
28
44
  name?: string;
@@ -36,20 +52,20 @@ export const formatVisionMessage = ({ message, image_urls, endpoint }: VisionMes
36
52
  [key: string]: any;
37
53
  } = {
38
54
  ...message,
39
- content: [] as MessageContentComplex[]
55
+ content: [] as MessageContentComplex[],
40
56
  };
41
57
 
42
58
  if (endpoint === Providers.ANTHROPIC) {
43
59
  result.content = [
44
60
  ...image_urls,
45
- { type: ContentTypes.TEXT, text: message.content }
61
+ { type: ContentTypes.TEXT, text: message.content },
46
62
  ] as MessageContentComplex[];
47
63
  return result;
48
64
  }
49
65
 
50
66
  result.content = [
51
67
  { type: ContentTypes.TEXT, text: message.content },
52
- ...image_urls
68
+ ...image_urls,
53
69
  ] as MessageContentComplex[];
54
70
 
55
71
  return result;
@@ -92,8 +108,12 @@ export const formatMessage = ({
92
108
  userName,
93
109
  assistantName,
94
110
  endpoint,
95
- langChain = false
96
- }: FormatMessageParams): FormattedMessage | HumanMessage | AIMessage | SystemMessage => {
111
+ langChain = false,
112
+ }: FormatMessageParams):
113
+ | FormattedMessage
114
+ | HumanMessage
115
+ | AIMessage
116
+ | SystemMessage => {
97
117
  // eslint-disable-next-line prefer-const
98
118
  let { role: _role, _name, sender, text, content: _content, lc_id } = message;
99
119
  if (lc_id && lc_id[2] && !langChain) {
@@ -104,7 +124,11 @@ export const formatMessage = ({
104
124
  };
105
125
  _role = roleMapping[lc_id[2]] || _role;
106
126
  }
107
- const role = _role ?? (sender != null && sender && sender.toLowerCase() === 'user' ? 'user' : 'assistant');
127
+ const role =
128
+ _role ??
129
+ (sender != null && sender && sender.toLowerCase() === 'user'
130
+ ? 'user'
131
+ : 'assistant');
108
132
  const content = _content ?? text ?? '';
109
133
  const formattedMessage: FormattedMessage = {
110
134
  role,
@@ -116,7 +140,10 @@ export const formatMessage = ({
116
140
  return formatVisionMessage({
117
141
  message: {
118
142
  ...formattedMessage,
119
- content: typeof formattedMessage.content === 'string' ? formattedMessage.content : ''
143
+ content:
144
+ typeof formattedMessage.content === 'string'
145
+ ? formattedMessage.content
146
+ : '',
120
147
  },
121
148
  image_urls,
122
149
  endpoint,
@@ -131,14 +158,21 @@ export const formatMessage = ({
131
158
  formattedMessage.name = userName;
132
159
  }
133
160
 
134
- if (assistantName != null && assistantName && formattedMessage.role === 'assistant') {
161
+ if (
162
+ assistantName != null &&
163
+ assistantName &&
164
+ formattedMessage.role === 'assistant'
165
+ ) {
135
166
  formattedMessage.name = assistantName;
136
167
  }
137
168
 
138
169
  if (formattedMessage.name != null && formattedMessage.name) {
139
170
  // Conform to API regex: ^[a-zA-Z0-9_-]{1,64}$
140
171
  // https://community.openai.com/t/the-format-of-the-name-field-in-the-documentation-is-incorrect/175684/2
141
- formattedMessage.name = formattedMessage.name.replace(/[^a-zA-Z0-9_-]/g, '_');
172
+ formattedMessage.name = formattedMessage.name.replace(
173
+ /[^a-zA-Z0-9_-]/g,
174
+ '_'
175
+ );
142
176
 
143
177
  if (formattedMessage.name.length > 64) {
144
178
  formattedMessage.name = formattedMessage.name.substring(0, 64);
@@ -170,7 +204,11 @@ export const formatLangChainMessages = (
170
204
  formatOptions: Omit<FormatMessageParams, 'message' | 'langChain'>
171
205
  ): Array<HumanMessage | AIMessage | SystemMessage> => {
172
206
  return messages.map((msg) => {
173
- const formatted = formatMessage({ ...formatOptions, message: msg, langChain: true });
207
+ const formatted = formatMessage({
208
+ ...formatOptions,
209
+ message: msg,
210
+ langChain: true,
211
+ });
174
212
  return formatted as HumanMessage | AIMessage | SystemMessage;
175
213
  });
176
214
  };
@@ -193,7 +231,9 @@ interface LangChainMessage {
193
231
  * @param {LangChainMessage} message - The message object to format.
194
232
  * @returns {Record<string, any>} The formatted LangChain message.
195
233
  */
196
- export const formatFromLangChain = (message: LangChainMessage): Record<string, any> => {
234
+ export const formatFromLangChain = (
235
+ message: LangChainMessage
236
+ ): Record<string, any> => {
197
237
  const kwargs = message.lc_kwargs ?? message.kwargs ?? {};
198
238
  const { additional_kwargs = {}, ...message_kwargs } = kwargs;
199
239
  return {
@@ -207,7 +247,9 @@ export const formatFromLangChain = (message: LangChainMessage): Record<string, a
207
247
  * @param message The message to format
208
248
  * @returns Array of formatted messages
209
249
  */
210
- function formatAssistantMessage(message: Partial<TMessage>): Array<AIMessage | ToolMessage> {
250
+ function formatAssistantMessage(
251
+ message: Partial<TMessage>
252
+ ): Array<AIMessage | ToolMessage> {
211
253
  const formattedMessages: Array<AIMessage | ToolMessage> = [];
212
254
  let currentContent: MessageContentComplex[] = [];
213
255
  let lastAIMessage: AIMessage | null = null;
@@ -227,7 +269,8 @@ function formatAssistantMessage(message: Partial<TMessage>): Array<AIMessage | T
227
269
  }
228
270
  return acc;
229
271
  }, '');
230
- content = `${content}\n${part[ContentTypes.TEXT] ?? part.text ?? ''}`.trim();
272
+ content =
273
+ `${content}\n${part[ContentTypes.TEXT] ?? part.text ?? ''}`.trim();
231
274
  lastAIMessage = new AIMessage({ content });
232
275
  formattedMessages.push(lastAIMessage);
233
276
  currentContent = [];
@@ -240,11 +283,17 @@ function formatAssistantMessage(message: Partial<TMessage>): Array<AIMessage | T
240
283
  formattedMessages.push(lastAIMessage);
241
284
  } else if (part.type === ContentTypes.TOOL_CALL) {
242
285
  if (!lastAIMessage) {
243
- throw new Error('Invalid tool call structure: No preceding AIMessage with tool_call_ids');
286
+ // "Heal" the payload by creating an AIMessage to precede the tool call
287
+ lastAIMessage = new AIMessage({ content: '' });
288
+ formattedMessages.push(lastAIMessage);
244
289
  }
245
290
 
246
291
  // Note: `tool_calls` list is defined when constructed by `AIMessage` class, and outputs should be excluded from it
247
- const { output, args: _args, ..._tool_call } = (part.tool_call as ToolCallPart);
292
+ const {
293
+ output,
294
+ args: _args,
295
+ ..._tool_call
296
+ } = part.tool_call as ToolCallPart;
248
297
  const tool_call: ToolCallPart = _tool_call;
249
298
  // TODO: investigate; args as dictionary may need to be providers-or-tool-specific
250
299
  let args: any = _args;
@@ -269,12 +318,15 @@ function formatAssistantMessage(message: Partial<TMessage>): Array<AIMessage | T
269
318
  tool_call_id: tool_call.id ?? '',
270
319
  name: tool_call.name,
271
320
  content: output || '',
272
- }),
321
+ })
273
322
  );
274
323
  } else if (part.type === ContentTypes.THINK) {
275
324
  hasReasoning = true;
276
325
  continue;
277
- } else if (part.type === ContentTypes.ERROR || part.type === ContentTypes.AGENT_UPDATE) {
326
+ } else if (
327
+ part.type === ContentTypes.ERROR ||
328
+ part.type === ContentTypes.AGENT_UPDATE
329
+ ) {
278
330
  continue;
279
331
  } else {
280
332
  currentContent.push(part);
@@ -318,7 +370,9 @@ export const formatAgentMessages = (
318
370
  messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
319
371
  indexTokenCountMap?: Record<number, number>;
320
372
  } => {
321
- const messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage> = [];
373
+ const messages: Array<
374
+ HumanMessage | AIMessage | SystemMessage | ToolMessage
375
+ > = [];
322
376
  // If indexTokenCountMap is provided, create a new map to track the updated indices
323
377
  const updatedIndexTokenCountMap: Record<number, number> = {};
324
378
  // Keep track of the mapping from original payload indices to result indices
@@ -330,13 +384,17 @@ export const formatAgentMessages = (
330
384
  // Q: Store the current length of messages to track where this payload message starts in the result?
331
385
  // const startIndex = messages.length;
332
386
  if (typeof message.content === 'string') {
333
- message.content = [{ type: ContentTypes.TEXT, [ContentTypes.TEXT]: message.content }];
387
+ message.content = [
388
+ { type: ContentTypes.TEXT, [ContentTypes.TEXT]: message.content },
389
+ ];
334
390
  }
335
391
  if (message.role !== 'assistant') {
336
- messages.push(formatMessage({
337
- message: message as MessageInput,
338
- langChain: true
339
- }) as HumanMessage | AIMessage | SystemMessage);
392
+ messages.push(
393
+ formatMessage({
394
+ message: message as MessageInput,
395
+ langChain: true,
396
+ }) as HumanMessage | AIMessage | SystemMessage
397
+ );
340
398
 
341
399
  // Update the index mapping for this message
342
400
  indexMapping[i] = [messages.length - 1];
@@ -441,7 +499,11 @@ export const formatAgentMessages = (
441
499
 
442
500
  // Update the token count map if it was provided
443
501
  if (indexTokenCountMap) {
444
- for (let originalIndex = 0; originalIndex < payload.length; originalIndex++) {
502
+ for (
503
+ let originalIndex = 0;
504
+ originalIndex < payload.length;
505
+ originalIndex++
506
+ ) {
445
507
  const resultIndices = indexMapping[originalIndex] || [];
446
508
  const tokenCount = indexTokenCountMap[originalIndex];
447
509
 
@@ -456,7 +518,8 @@ export const formatAgentMessages = (
456
518
  resultIndices.forEach((resultIndex, idx) => {
457
519
  if (idx === resultIndices.length - 1) {
458
520
  // Give any remainder to the last message
459
- updatedIndexTokenCountMap[resultIndex] = tokenCount - (countPerMessage * (resultIndices.length - 1));
521
+ updatedIndexTokenCountMap[resultIndex] =
522
+ tokenCount - countPerMessage * (resultIndices.length - 1);
460
523
  } else {
461
524
  updatedIndexTokenCountMap[resultIndex] = countPerMessage;
462
525
  }
@@ -468,7 +531,9 @@ export const formatAgentMessages = (
468
531
 
469
532
  return {
470
533
  messages,
471
- indexTokenCountMap: indexTokenCountMap ? updatedIndexTokenCountMap : undefined
534
+ indexTokenCountMap: indexTokenCountMap
535
+ ? updatedIndexTokenCountMap
536
+ : undefined,
472
537
  };
473
538
  };
474
539
 
@@ -477,7 +542,9 @@ export const formatAgentMessages = (
477
542
  * @param {Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>} payload - The array of messages to format.
478
543
  * @returns {Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>} - The array of formatted LangChain messages, including ToolMessages for tool calls.
479
544
  */
480
- export const formatContentStrings = (payload: Array<BaseMessage>): Array<BaseMessage> => {
545
+ export const formatContentStrings = (
546
+ payload: Array<BaseMessage>
547
+ ): Array<BaseMessage> => {
481
548
  // Create a copy of the payload to avoid modifying the original
482
549
  const result = [...payload];
483
550