@librechat/agents 3.0.771 → 3.0.773

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.
@@ -16,17 +16,36 @@ function deepCloneContent(content) {
16
16
  return content;
17
17
  }
18
18
  /**
19
- * Creates a shallow clone of a message with deep-cloned content.
20
- * This ensures modifications to content don't affect the original message.
19
+ * Clones a message with deep-cloned content.
20
+ * For LangChain messages, also syncs lc_kwargs.content.
21
21
  */
22
22
  function cloneMessageWithContent(message) {
23
23
  if (message.content === undefined) {
24
24
  return { ...message };
25
25
  }
26
- return {
26
+ const clonedContent = deepCloneContent(message.content);
27
+ const cloned = {
27
28
  ...message,
28
- content: deepCloneContent(message.content),
29
+ content: clonedContent,
29
30
  };
31
+ const lcKwargs = cloned.lc_kwargs;
32
+ if (lcKwargs != null) {
33
+ cloned.lc_kwargs = {
34
+ ...lcKwargs,
35
+ content: clonedContent,
36
+ };
37
+ }
38
+ return cloned;
39
+ }
40
+ /**
41
+ * Syncs lc_kwargs.content with message.content after modifications.
42
+ * Call this after all content modifications are done.
43
+ */
44
+ function syncLcKwargs(message) {
45
+ const lcKwargs = message.lc_kwargs;
46
+ if (lcKwargs != null) {
47
+ lcKwargs.content = message.content;
48
+ }
30
49
  }
31
50
  /**
32
51
  * Checks if a message's content needs cache control stripping.
@@ -82,6 +101,7 @@ function addCacheControl(messages) {
82
101
  }
83
102
  }
84
103
  if (userMessagesModified >= 2 || !isUserMessage) {
104
+ syncLcKwargs(message);
85
105
  continue;
86
106
  }
87
107
  if (typeof message.content === 'string') {
@@ -106,6 +126,7 @@ function addCacheControl(messages) {
106
126
  }
107
127
  }
108
128
  }
129
+ syncLcKwargs(message);
109
130
  }
110
131
  return updatedMessages;
111
132
  }
@@ -230,6 +251,7 @@ function addBedrockCacheControl(messages) {
230
251
  }
231
252
  }
232
253
  if (messagesModified >= 2 || isToolMessage || isEmptyString) {
254
+ syncLcKwargs(message);
233
255
  continue;
234
256
  }
235
257
  if (typeof message.content === 'string') {
@@ -238,6 +260,7 @@ function addBedrockCacheControl(messages) {
238
260
  { cachePoint: { type: 'default' } },
239
261
  ];
240
262
  messagesModified++;
263
+ syncLcKwargs(message);
241
264
  continue;
242
265
  }
243
266
  if (Array.isArray(message.content)) {
@@ -251,6 +274,7 @@ function addBedrockCacheControl(messages) {
251
274
  }
252
275
  }
253
276
  if (!hasCacheableContent) {
277
+ syncLcKwargs(message);
254
278
  continue;
255
279
  }
256
280
  let inserted = false;
@@ -276,6 +300,7 @@ function addBedrockCacheControl(messages) {
276
300
  }
277
301
  messagesModified++;
278
302
  }
303
+ syncLcKwargs(message);
279
304
  }
280
305
  return updatedMessages;
281
306
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cache.cjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import { BaseMessage, MessageContentComplex } from '@langchain/core/messages';\nimport type { AnthropicMessage } from '@/types/messages';\nimport type Anthropic from '@anthropic-ai/sdk';\nimport { ContentTypes } from '@/common/enum';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\n};\n\n/**\n * Deep clones a message's content to prevent mutation of the original.\n * Handles both string and array content types.\n */\nfunction deepCloneContent<T extends string | MessageContentComplex[]>(\n content: T\n): T {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content.map((block) => ({ ...block })) as T;\n }\n return content;\n}\n\n/**\n * Creates a shallow clone of a message with deep-cloned content.\n * This ensures modifications to content don't affect the original message.\n */\nfunction cloneMessageWithContent<T extends MessageWithContent>(message: T): T {\n if (message.content === undefined) {\n return { ...message };\n }\n return {\n ...message,\n content: deepCloneContent(message.content),\n };\n}\n\n/**\n * Checks if a message's content needs cache control stripping.\n * Returns true if content has cachePoint blocks or cache_control fields.\n */\nfunction needsCacheStripping(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n const block = content[i];\n if (isCachePoint(block)) return true;\n if ('cache_control' in block) return true;\n }\n return false;\n}\n\n/**\n * Anthropic API: Adds cache control to the appropriate user messages in the payload.\n * Strips ALL existing cache control (both Anthropic and Bedrock formats) from all messages,\n * then adds fresh cache control to the last 2 user messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new array of message objects with cache control added.\n */\nexport function addCacheControl<T extends AnthropicMessage | BaseMessage>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let userMessagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n\n const hasArrayContent = Array.isArray(originalMessage.content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(originalMessage.content as MessageContentComplex[]);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof originalMessage.content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = cloneMessageWithContent(\n originalMessage as MessageWithContent\n ) as T;\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof message.content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (userMessagesModified >= 2 || !isUserMessage) {\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n {\n type: 'text',\n text: message.content,\n cache_control: { type: 'ephemeral' },\n },\n ];\n userMessagesModified++;\n } else if (Array.isArray(message.content)) {\n for (let j = message.content.length - 1; j >= 0; j--) {\n const contentPart = message.content[j];\n if ('type' in contentPart && contentPart.type === 'text') {\n (contentPart as Anthropic.TextBlockParam).cache_control = {\n type: 'ephemeral',\n };\n userMessagesModified++;\n break;\n }\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a content block is a cache point\n */\nfunction isCachePoint(block: MessageContentComplex): boolean {\n return 'cachePoint' in block && !('type' in block);\n}\n\n/**\n * Checks if a message's content has Anthropic cache_control fields.\n */\nfunction hasAnthropicCacheControl(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if ('cache_control' in content[i]) return true;\n }\n return false;\n}\n\n/**\n * Removes all Anthropic cache_control fields from messages\n * Used when switching from Anthropic to Bedrock provider\n * Returns a new array - only clones messages that require modification.\n */\nexport function stripAnthropicCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a message's content has Bedrock cachePoint blocks.\n */\nfunction hasBedrockCachePoint(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if (isCachePoint(content[i])) return true;\n }\n return false;\n}\n\n/**\n * Removes all Bedrock cachePoint blocks from messages\n * Used when switching from Bedrock to Anthropic provider\n * Returns a new array - only clones messages that require modification.\n */\nexport function stripBedrockCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof content;\n }\n\n return updatedMessages;\n}\n\n/**\n * Adds Bedrock Converse API cache points to the last two messages.\n * Inserts `{ cachePoint: { type: 'default' } }` as a separate content block\n * immediately after the last text block in each targeted message.\n * Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,\n * then adds fresh cache points to the last 2 messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new array of message objects with cache points added.\n */\nexport function addBedrockCacheControl<\n T extends Partial<BaseMessage> & MessageWithContent,\n>(messages: T[]): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let messagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isToolMessage =\n 'getType' in originalMessage &&\n typeof originalMessage.getType === 'function' &&\n originalMessage.getType() === 'tool';\n\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const isEmptyString = typeof content === 'string' && content === '';\n const needsCacheAdd =\n messagesModified < 2 &&\n !isToolMessage &&\n !isEmptyString &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block)\n ) as typeof content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (messagesModified >= 2 || isToolMessage || isEmptyString) {\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n { type: ContentTypes.TEXT, text: message.content },\n { cachePoint: { type: 'default' } },\n ] as MessageContentComplex[];\n messagesModified++;\n continue;\n }\n\n if (Array.isArray(message.content)) {\n let hasCacheableContent = false;\n for (const block of message.content) {\n if (block.type === ContentTypes.TEXT) {\n if (typeof block.text === 'string' && block.text !== '') {\n hasCacheableContent = true;\n break;\n }\n }\n }\n\n if (!hasCacheableContent) {\n continue;\n }\n\n let inserted = false;\n for (let j = message.content.length - 1; j >= 0; j--) {\n const block = message.content[j] as MessageContentComplex;\n const type = (block as { type?: string }).type;\n if (type === ContentTypes.TEXT || type === 'text') {\n const text = (block as { text?: string }).text;\n if (text === '' || text === undefined) {\n continue;\n }\n message.content.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n message.content.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n messagesModified++;\n }\n }\n\n return updatedMessages;\n}\n"],"names":["ContentTypes"],"mappings":"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"}
1
+ {"version":3,"file":"cache.cjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import { BaseMessage, MessageContentComplex } from '@langchain/core/messages';\nimport type { AnthropicMessage } from '@/types/messages';\nimport type Anthropic from '@anthropic-ai/sdk';\nimport { ContentTypes } from '@/common/enum';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\n};\n\n/**\n * Deep clones a message's content to prevent mutation of the original.\n * Handles both string and array content types.\n */\nfunction deepCloneContent<T extends string | MessageContentComplex[]>(\n content: T\n): T {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content.map((block) => ({ ...block })) as T;\n }\n return content;\n}\n\n/**\n * Clones a message with deep-cloned content.\n * For LangChain messages, also syncs lc_kwargs.content.\n */\nfunction cloneMessageWithContent<T extends MessageWithContent>(message: T): T {\n if (message.content === undefined) {\n return { ...message };\n }\n\n const clonedContent = deepCloneContent(message.content);\n const cloned = {\n ...message,\n content: clonedContent,\n } as T;\n\n const lcKwargs = (cloned as Record<string, unknown>).lc_kwargs as\n | Record<string, unknown>\n | undefined;\n if (lcKwargs != null) {\n (cloned as Record<string, unknown>).lc_kwargs = {\n ...lcKwargs,\n content: clonedContent,\n };\n }\n\n return cloned;\n}\n\n/**\n * Syncs lc_kwargs.content with message.content after modifications.\n * Call this after all content modifications are done.\n */\nfunction syncLcKwargs<T extends MessageWithContent>(message: T): void {\n const lcKwargs = (message as Record<string, unknown>).lc_kwargs as\n | Record<string, unknown>\n | undefined;\n if (lcKwargs != null) {\n lcKwargs.content = message.content;\n }\n}\n\n/**\n * Checks if a message's content needs cache control stripping.\n * Returns true if content has cachePoint blocks or cache_control fields.\n */\nfunction needsCacheStripping(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n const block = content[i];\n if (isCachePoint(block)) return true;\n if ('cache_control' in block) return true;\n }\n return false;\n}\n\n/**\n * Anthropic API: Adds cache control to the appropriate user messages in the payload.\n * Strips ALL existing cache control (both Anthropic and Bedrock formats) from all messages,\n * then adds fresh cache control to the last 2 user messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new array of message objects with cache control added.\n */\nexport function addCacheControl<T extends AnthropicMessage | BaseMessage>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let userMessagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n\n const hasArrayContent = Array.isArray(originalMessage.content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(originalMessage.content as MessageContentComplex[]);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof originalMessage.content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = cloneMessageWithContent(\n originalMessage as MessageWithContent\n ) as T;\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof message.content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (userMessagesModified >= 2 || !isUserMessage) {\n syncLcKwargs(message);\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n {\n type: 'text',\n text: message.content,\n cache_control: { type: 'ephemeral' },\n },\n ];\n userMessagesModified++;\n } else if (Array.isArray(message.content)) {\n for (let j = message.content.length - 1; j >= 0; j--) {\n const contentPart = message.content[j];\n if ('type' in contentPart && contentPart.type === 'text') {\n (contentPart as Anthropic.TextBlockParam).cache_control = {\n type: 'ephemeral',\n };\n userMessagesModified++;\n break;\n }\n }\n }\n\n syncLcKwargs(message);\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a content block is a cache point\n */\nfunction isCachePoint(block: MessageContentComplex): boolean {\n return 'cachePoint' in block && !('type' in block);\n}\n\n/**\n * Checks if a message's content has Anthropic cache_control fields.\n */\nfunction hasAnthropicCacheControl(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if ('cache_control' in content[i]) return true;\n }\n return false;\n}\n\n/**\n * Removes all Anthropic cache_control fields from messages\n * Used when switching from Anthropic to Bedrock provider\n * Returns a new array - only clones messages that require modification.\n */\nexport function stripAnthropicCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a message's content has Bedrock cachePoint blocks.\n */\nfunction hasBedrockCachePoint(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if (isCachePoint(content[i])) return true;\n }\n return false;\n}\n\n/**\n * Removes all Bedrock cachePoint blocks from messages\n * Used when switching from Bedrock to Anthropic provider\n * Returns a new array - only clones messages that require modification.\n */\nexport function stripBedrockCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof content;\n }\n\n return updatedMessages;\n}\n\n/**\n * Adds Bedrock Converse API cache points to the last two messages.\n * Inserts `{ cachePoint: { type: 'default' } }` as a separate content block\n * immediately after the last text block in each targeted message.\n * Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,\n * then adds fresh cache points to the last 2 messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new array of message objects with cache points added.\n */\nexport function addBedrockCacheControl<\n T extends Partial<BaseMessage> & MessageWithContent,\n>(messages: T[]): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let messagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isToolMessage =\n 'getType' in originalMessage &&\n typeof originalMessage.getType === 'function' &&\n originalMessage.getType() === 'tool';\n\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const isEmptyString = typeof content === 'string' && content === '';\n const needsCacheAdd =\n messagesModified < 2 &&\n !isToolMessage &&\n !isEmptyString &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block)\n ) as typeof content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (messagesModified >= 2 || isToolMessage || isEmptyString) {\n syncLcKwargs(message);\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n { type: ContentTypes.TEXT, text: message.content },\n { cachePoint: { type: 'default' } },\n ] as MessageContentComplex[];\n messagesModified++;\n syncLcKwargs(message);\n continue;\n }\n\n if (Array.isArray(message.content)) {\n let hasCacheableContent = false;\n for (const block of message.content) {\n if (block.type === ContentTypes.TEXT) {\n if (typeof block.text === 'string' && block.text !== '') {\n hasCacheableContent = true;\n break;\n }\n }\n }\n\n if (!hasCacheableContent) {\n syncLcKwargs(message);\n continue;\n }\n\n let inserted = false;\n for (let j = message.content.length - 1; j >= 0; j--) {\n const block = message.content[j] as MessageContentComplex;\n const type = (block as { type?: string }).type;\n if (type === ContentTypes.TEXT || type === 'text') {\n const text = (block as { text?: string }).text;\n if (text === '' || text === undefined) {\n continue;\n }\n message.content.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n message.content.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n messagesModified++;\n }\n\n syncLcKwargs(message);\n }\n\n return updatedMessages;\n}\n"],"names":["ContentTypes"],"mappings":"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"}
@@ -14,17 +14,36 @@ function deepCloneContent(content) {
14
14
  return content;
15
15
  }
16
16
  /**
17
- * Creates a shallow clone of a message with deep-cloned content.
18
- * This ensures modifications to content don't affect the original message.
17
+ * Clones a message with deep-cloned content.
18
+ * For LangChain messages, also syncs lc_kwargs.content.
19
19
  */
20
20
  function cloneMessageWithContent(message) {
21
21
  if (message.content === undefined) {
22
22
  return { ...message };
23
23
  }
24
- return {
24
+ const clonedContent = deepCloneContent(message.content);
25
+ const cloned = {
25
26
  ...message,
26
- content: deepCloneContent(message.content),
27
+ content: clonedContent,
27
28
  };
29
+ const lcKwargs = cloned.lc_kwargs;
30
+ if (lcKwargs != null) {
31
+ cloned.lc_kwargs = {
32
+ ...lcKwargs,
33
+ content: clonedContent,
34
+ };
35
+ }
36
+ return cloned;
37
+ }
38
+ /**
39
+ * Syncs lc_kwargs.content with message.content after modifications.
40
+ * Call this after all content modifications are done.
41
+ */
42
+ function syncLcKwargs(message) {
43
+ const lcKwargs = message.lc_kwargs;
44
+ if (lcKwargs != null) {
45
+ lcKwargs.content = message.content;
46
+ }
28
47
  }
29
48
  /**
30
49
  * Checks if a message's content needs cache control stripping.
@@ -80,6 +99,7 @@ function addCacheControl(messages) {
80
99
  }
81
100
  }
82
101
  if (userMessagesModified >= 2 || !isUserMessage) {
102
+ syncLcKwargs(message);
83
103
  continue;
84
104
  }
85
105
  if (typeof message.content === 'string') {
@@ -104,6 +124,7 @@ function addCacheControl(messages) {
104
124
  }
105
125
  }
106
126
  }
127
+ syncLcKwargs(message);
107
128
  }
108
129
  return updatedMessages;
109
130
  }
@@ -228,6 +249,7 @@ function addBedrockCacheControl(messages) {
228
249
  }
229
250
  }
230
251
  if (messagesModified >= 2 || isToolMessage || isEmptyString) {
252
+ syncLcKwargs(message);
231
253
  continue;
232
254
  }
233
255
  if (typeof message.content === 'string') {
@@ -236,6 +258,7 @@ function addBedrockCacheControl(messages) {
236
258
  { cachePoint: { type: 'default' } },
237
259
  ];
238
260
  messagesModified++;
261
+ syncLcKwargs(message);
239
262
  continue;
240
263
  }
241
264
  if (Array.isArray(message.content)) {
@@ -249,6 +272,7 @@ function addBedrockCacheControl(messages) {
249
272
  }
250
273
  }
251
274
  if (!hasCacheableContent) {
275
+ syncLcKwargs(message);
252
276
  continue;
253
277
  }
254
278
  let inserted = false;
@@ -274,6 +298,7 @@ function addBedrockCacheControl(messages) {
274
298
  }
275
299
  messagesModified++;
276
300
  }
301
+ syncLcKwargs(message);
277
302
  }
278
303
  return updatedMessages;
279
304
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cache.mjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import { BaseMessage, MessageContentComplex } from '@langchain/core/messages';\nimport type { AnthropicMessage } from '@/types/messages';\nimport type Anthropic from '@anthropic-ai/sdk';\nimport { ContentTypes } from '@/common/enum';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\n};\n\n/**\n * Deep clones a message's content to prevent mutation of the original.\n * Handles both string and array content types.\n */\nfunction deepCloneContent<T extends string | MessageContentComplex[]>(\n content: T\n): T {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content.map((block) => ({ ...block })) as T;\n }\n return content;\n}\n\n/**\n * Creates a shallow clone of a message with deep-cloned content.\n * This ensures modifications to content don't affect the original message.\n */\nfunction cloneMessageWithContent<T extends MessageWithContent>(message: T): T {\n if (message.content === undefined) {\n return { ...message };\n }\n return {\n ...message,\n content: deepCloneContent(message.content),\n };\n}\n\n/**\n * Checks if a message's content needs cache control stripping.\n * Returns true if content has cachePoint blocks or cache_control fields.\n */\nfunction needsCacheStripping(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n const block = content[i];\n if (isCachePoint(block)) return true;\n if ('cache_control' in block) return true;\n }\n return false;\n}\n\n/**\n * Anthropic API: Adds cache control to the appropriate user messages in the payload.\n * Strips ALL existing cache control (both Anthropic and Bedrock formats) from all messages,\n * then adds fresh cache control to the last 2 user messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new array of message objects with cache control added.\n */\nexport function addCacheControl<T extends AnthropicMessage | BaseMessage>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let userMessagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n\n const hasArrayContent = Array.isArray(originalMessage.content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(originalMessage.content as MessageContentComplex[]);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof originalMessage.content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = cloneMessageWithContent(\n originalMessage as MessageWithContent\n ) as T;\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof message.content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (userMessagesModified >= 2 || !isUserMessage) {\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n {\n type: 'text',\n text: message.content,\n cache_control: { type: 'ephemeral' },\n },\n ];\n userMessagesModified++;\n } else if (Array.isArray(message.content)) {\n for (let j = message.content.length - 1; j >= 0; j--) {\n const contentPart = message.content[j];\n if ('type' in contentPart && contentPart.type === 'text') {\n (contentPart as Anthropic.TextBlockParam).cache_control = {\n type: 'ephemeral',\n };\n userMessagesModified++;\n break;\n }\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a content block is a cache point\n */\nfunction isCachePoint(block: MessageContentComplex): boolean {\n return 'cachePoint' in block && !('type' in block);\n}\n\n/**\n * Checks if a message's content has Anthropic cache_control fields.\n */\nfunction hasAnthropicCacheControl(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if ('cache_control' in content[i]) return true;\n }\n return false;\n}\n\n/**\n * Removes all Anthropic cache_control fields from messages\n * Used when switching from Anthropic to Bedrock provider\n * Returns a new array - only clones messages that require modification.\n */\nexport function stripAnthropicCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a message's content has Bedrock cachePoint blocks.\n */\nfunction hasBedrockCachePoint(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if (isCachePoint(content[i])) return true;\n }\n return false;\n}\n\n/**\n * Removes all Bedrock cachePoint blocks from messages\n * Used when switching from Bedrock to Anthropic provider\n * Returns a new array - only clones messages that require modification.\n */\nexport function stripBedrockCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof content;\n }\n\n return updatedMessages;\n}\n\n/**\n * Adds Bedrock Converse API cache points to the last two messages.\n * Inserts `{ cachePoint: { type: 'default' } }` as a separate content block\n * immediately after the last text block in each targeted message.\n * Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,\n * then adds fresh cache points to the last 2 messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new array of message objects with cache points added.\n */\nexport function addBedrockCacheControl<\n T extends Partial<BaseMessage> & MessageWithContent,\n>(messages: T[]): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let messagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isToolMessage =\n 'getType' in originalMessage &&\n typeof originalMessage.getType === 'function' &&\n originalMessage.getType() === 'tool';\n\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const isEmptyString = typeof content === 'string' && content === '';\n const needsCacheAdd =\n messagesModified < 2 &&\n !isToolMessage &&\n !isEmptyString &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block)\n ) as typeof content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (messagesModified >= 2 || isToolMessage || isEmptyString) {\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n { type: ContentTypes.TEXT, text: message.content },\n { cachePoint: { type: 'default' } },\n ] as MessageContentComplex[];\n messagesModified++;\n continue;\n }\n\n if (Array.isArray(message.content)) {\n let hasCacheableContent = false;\n for (const block of message.content) {\n if (block.type === ContentTypes.TEXT) {\n if (typeof block.text === 'string' && block.text !== '') {\n hasCacheableContent = true;\n break;\n }\n }\n }\n\n if (!hasCacheableContent) {\n continue;\n }\n\n let inserted = false;\n for (let j = message.content.length - 1; j >= 0; j--) {\n const block = message.content[j] as MessageContentComplex;\n const type = (block as { type?: string }).type;\n if (type === ContentTypes.TEXT || type === 'text') {\n const text = (block as { text?: string }).text;\n if (text === '' || text === undefined) {\n continue;\n }\n message.content.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n message.content.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n messagesModified++;\n }\n }\n\n return updatedMessages;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.mjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import { BaseMessage, MessageContentComplex } from '@langchain/core/messages';\nimport type { AnthropicMessage } from '@/types/messages';\nimport type Anthropic from '@anthropic-ai/sdk';\nimport { ContentTypes } from '@/common/enum';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\n};\n\n/**\n * Deep clones a message's content to prevent mutation of the original.\n * Handles both string and array content types.\n */\nfunction deepCloneContent<T extends string | MessageContentComplex[]>(\n content: T\n): T {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content.map((block) => ({ ...block })) as T;\n }\n return content;\n}\n\n/**\n * Clones a message with deep-cloned content.\n * For LangChain messages, also syncs lc_kwargs.content.\n */\nfunction cloneMessageWithContent<T extends MessageWithContent>(message: T): T {\n if (message.content === undefined) {\n return { ...message };\n }\n\n const clonedContent = deepCloneContent(message.content);\n const cloned = {\n ...message,\n content: clonedContent,\n } as T;\n\n const lcKwargs = (cloned as Record<string, unknown>).lc_kwargs as\n | Record<string, unknown>\n | undefined;\n if (lcKwargs != null) {\n (cloned as Record<string, unknown>).lc_kwargs = {\n ...lcKwargs,\n content: clonedContent,\n };\n }\n\n return cloned;\n}\n\n/**\n * Syncs lc_kwargs.content with message.content after modifications.\n * Call this after all content modifications are done.\n */\nfunction syncLcKwargs<T extends MessageWithContent>(message: T): void {\n const lcKwargs = (message as Record<string, unknown>).lc_kwargs as\n | Record<string, unknown>\n | undefined;\n if (lcKwargs != null) {\n lcKwargs.content = message.content;\n }\n}\n\n/**\n * Checks if a message's content needs cache control stripping.\n * Returns true if content has cachePoint blocks or cache_control fields.\n */\nfunction needsCacheStripping(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n const block = content[i];\n if (isCachePoint(block)) return true;\n if ('cache_control' in block) return true;\n }\n return false;\n}\n\n/**\n * Anthropic API: Adds cache control to the appropriate user messages in the payload.\n * Strips ALL existing cache control (both Anthropic and Bedrock formats) from all messages,\n * then adds fresh cache control to the last 2 user messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new array of message objects with cache control added.\n */\nexport function addCacheControl<T extends AnthropicMessage | BaseMessage>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let userMessagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n\n const hasArrayContent = Array.isArray(originalMessage.content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(originalMessage.content as MessageContentComplex[]);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof originalMessage.content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = cloneMessageWithContent(\n originalMessage as MessageWithContent\n ) as T;\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof message.content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (userMessagesModified >= 2 || !isUserMessage) {\n syncLcKwargs(message);\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n {\n type: 'text',\n text: message.content,\n cache_control: { type: 'ephemeral' },\n },\n ];\n userMessagesModified++;\n } else if (Array.isArray(message.content)) {\n for (let j = message.content.length - 1; j >= 0; j--) {\n const contentPart = message.content[j];\n if ('type' in contentPart && contentPart.type === 'text') {\n (contentPart as Anthropic.TextBlockParam).cache_control = {\n type: 'ephemeral',\n };\n userMessagesModified++;\n break;\n }\n }\n }\n\n syncLcKwargs(message);\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a content block is a cache point\n */\nfunction isCachePoint(block: MessageContentComplex): boolean {\n return 'cachePoint' in block && !('type' in block);\n}\n\n/**\n * Checks if a message's content has Anthropic cache_control fields.\n */\nfunction hasAnthropicCacheControl(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if ('cache_control' in content[i]) return true;\n }\n return false;\n}\n\n/**\n * Removes all Anthropic cache_control fields from messages\n * Used when switching from Anthropic to Bedrock provider\n * Returns a new array - only clones messages that require modification.\n */\nexport function stripAnthropicCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n return updatedMessages;\n}\n\n/**\n * Checks if a message's content has Bedrock cachePoint blocks.\n */\nfunction hasBedrockCachePoint(content: MessageContentComplex[]): boolean {\n for (let i = 0; i < content.length; i++) {\n if (isCachePoint(content[i])) return true;\n }\n return false;\n}\n\n/**\n * Removes all Bedrock cachePoint blocks from messages\n * Used when switching from Bedrock to Anthropic provider\n * Returns a new array - only clones messages that require modification.\n */\nexport function stripBedrockCacheControl<T extends MessageWithContent>(\n messages: T[]\n): T[] {\n if (!Array.isArray(messages)) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n\n for (let i = 0; i < updatedMessages.length; i++) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n\n if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n ) as typeof content;\n }\n\n return updatedMessages;\n}\n\n/**\n * Adds Bedrock Converse API cache points to the last two messages.\n * Inserts `{ cachePoint: { type: 'default' } }` as a separate content block\n * immediately after the last text block in each targeted message.\n * Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,\n * then adds fresh cache points to the last 2 messages in a single backward pass.\n * This ensures we don't accumulate stale cache points across multiple turns.\n * Returns a new array - only clones messages that require modification.\n * @param messages - The array of message objects.\n * @returns - A new array of message objects with cache points added.\n */\nexport function addBedrockCacheControl<\n T extends Partial<BaseMessage> & MessageWithContent,\n>(messages: T[]): T[] {\n if (!Array.isArray(messages) || messages.length < 2) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let messagesModified = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const isToolMessage =\n 'getType' in originalMessage &&\n typeof originalMessage.getType === 'function' &&\n originalMessage.getType() === 'tool';\n\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const isEmptyString = typeof content === 'string' && content === '';\n const needsCacheAdd =\n messagesModified < 2 &&\n !isToolMessage &&\n !isEmptyString &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n const message = cloneMessageWithContent(originalMessage);\n updatedMessages[i] = message;\n\n if (hasArrayContent) {\n message.content = (message.content as MessageContentComplex[]).filter(\n (block) => !isCachePoint(block)\n ) as typeof content;\n\n for (\n let j = 0;\n j < (message.content as MessageContentComplex[]).length;\n j++\n ) {\n const block = (message.content as MessageContentComplex[])[j] as Record<\n string,\n unknown\n >;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n }\n\n if (messagesModified >= 2 || isToolMessage || isEmptyString) {\n syncLcKwargs(message);\n continue;\n }\n\n if (typeof message.content === 'string') {\n message.content = [\n { type: ContentTypes.TEXT, text: message.content },\n { cachePoint: { type: 'default' } },\n ] as MessageContentComplex[];\n messagesModified++;\n syncLcKwargs(message);\n continue;\n }\n\n if (Array.isArray(message.content)) {\n let hasCacheableContent = false;\n for (const block of message.content) {\n if (block.type === ContentTypes.TEXT) {\n if (typeof block.text === 'string' && block.text !== '') {\n hasCacheableContent = true;\n break;\n }\n }\n }\n\n if (!hasCacheableContent) {\n syncLcKwargs(message);\n continue;\n }\n\n let inserted = false;\n for (let j = message.content.length - 1; j >= 0; j--) {\n const block = message.content[j] as MessageContentComplex;\n const type = (block as { type?: string }).type;\n if (type === ContentTypes.TEXT || type === 'text') {\n const text = (block as { text?: string }).text;\n if (text === '' || text === undefined) {\n continue;\n }\n message.content.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n message.content.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n messagesModified++;\n }\n\n syncLcKwargs(message);\n }\n\n return updatedMessages;\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "3.0.771",
3
+ "version": "3.0.773",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -1048,6 +1048,50 @@ describe('Immutability - addBedrockCacheControl does not mutate original message
1048
1048
  expect(anthropicFirstContent.some((b) => 'cachePoint' in b)).toBe(false);
1049
1049
  expect('cache_control' in anthropicFirstContent[0]).toBe(true);
1050
1050
  });
1051
+
1052
+ it('should keep lc_kwargs.content in sync with content for LangChain messages', () => {
1053
+ type LangChainLikeMsg = TestMsg & {
1054
+ lc_kwargs?: { content?: MessageContentComplex[] };
1055
+ };
1056
+
1057
+ const messagesWithLcKwargs: LangChainLikeMsg[] = [
1058
+ {
1059
+ role: 'user',
1060
+ content: [{ type: ContentTypes.TEXT, text: 'User message' }],
1061
+ lc_kwargs: {
1062
+ content: [{ type: ContentTypes.TEXT, text: 'User message' }],
1063
+ },
1064
+ },
1065
+ {
1066
+ role: 'assistant',
1067
+ content: [{ type: ContentTypes.TEXT, text: 'Assistant response' }],
1068
+ lc_kwargs: {
1069
+ content: [{ type: ContentTypes.TEXT, text: 'Assistant response' }],
1070
+ },
1071
+ },
1072
+ ];
1073
+
1074
+ const bedrockResult = addBedrockCacheControl(messagesWithLcKwargs);
1075
+
1076
+ const resultFirst = bedrockResult[0] as LangChainLikeMsg;
1077
+ const resultSecond = bedrockResult[1] as LangChainLikeMsg;
1078
+
1079
+ expect(resultFirst.content).toEqual(resultFirst.lc_kwargs?.content);
1080
+ expect(resultSecond.content).toEqual(resultSecond.lc_kwargs?.content);
1081
+
1082
+ const firstContent = resultFirst.content as MessageContentComplex[];
1083
+ const firstLcContent = resultFirst.lc_kwargs
1084
+ ?.content as MessageContentComplex[];
1085
+ expect(firstContent.some((b) => 'cachePoint' in b)).toBe(true);
1086
+ expect(firstLcContent.some((b) => 'cachePoint' in b)).toBe(true);
1087
+
1088
+ const originalFirst = messagesWithLcKwargs[0];
1089
+ const originalContent = originalFirst.content as MessageContentComplex[];
1090
+ const originalLcContent = originalFirst.lc_kwargs
1091
+ ?.content as MessageContentComplex[];
1092
+ expect(originalContent.some((b) => 'cachePoint' in b)).toBe(false);
1093
+ expect(originalLcContent.some((b) => 'cachePoint' in b)).toBe(false);
1094
+ });
1051
1095
  });
1052
1096
 
1053
1097
  describe('Multi-turn cache cleanup', () => {
@@ -24,17 +24,44 @@ function deepCloneContent<T extends string | MessageContentComplex[]>(
24
24
  }
25
25
 
26
26
  /**
27
- * Creates a shallow clone of a message with deep-cloned content.
28
- * This ensures modifications to content don't affect the original message.
27
+ * Clones a message with deep-cloned content.
28
+ * For LangChain messages, also syncs lc_kwargs.content.
29
29
  */
30
30
  function cloneMessageWithContent<T extends MessageWithContent>(message: T): T {
31
31
  if (message.content === undefined) {
32
32
  return { ...message };
33
33
  }
34
- return {
34
+
35
+ const clonedContent = deepCloneContent(message.content);
36
+ const cloned = {
35
37
  ...message,
36
- content: deepCloneContent(message.content),
37
- };
38
+ content: clonedContent,
39
+ } as T;
40
+
41
+ const lcKwargs = (cloned as Record<string, unknown>).lc_kwargs as
42
+ | Record<string, unknown>
43
+ | undefined;
44
+ if (lcKwargs != null) {
45
+ (cloned as Record<string, unknown>).lc_kwargs = {
46
+ ...lcKwargs,
47
+ content: clonedContent,
48
+ };
49
+ }
50
+
51
+ return cloned;
52
+ }
53
+
54
+ /**
55
+ * Syncs lc_kwargs.content with message.content after modifications.
56
+ * Call this after all content modifications are done.
57
+ */
58
+ function syncLcKwargs<T extends MessageWithContent>(message: T): void {
59
+ const lcKwargs = (message as Record<string, unknown>).lc_kwargs as
60
+ | Record<string, unknown>
61
+ | undefined;
62
+ if (lcKwargs != null) {
63
+ lcKwargs.content = message.content;
64
+ }
38
65
  }
39
66
 
40
67
  /**
@@ -114,6 +141,7 @@ export function addCacheControl<T extends AnthropicMessage | BaseMessage>(
114
141
  }
115
142
 
116
143
  if (userMessagesModified >= 2 || !isUserMessage) {
144
+ syncLcKwargs(message);
117
145
  continue;
118
146
  }
119
147
 
@@ -138,6 +166,8 @@ export function addCacheControl<T extends AnthropicMessage | BaseMessage>(
138
166
  }
139
167
  }
140
168
  }
169
+
170
+ syncLcKwargs(message);
141
171
  }
142
172
 
143
173
  return updatedMessages;
@@ -314,6 +344,7 @@ export function addBedrockCacheControl<
314
344
  }
315
345
 
316
346
  if (messagesModified >= 2 || isToolMessage || isEmptyString) {
347
+ syncLcKwargs(message);
317
348
  continue;
318
349
  }
319
350
 
@@ -323,6 +354,7 @@ export function addBedrockCacheControl<
323
354
  { cachePoint: { type: 'default' } },
324
355
  ] as MessageContentComplex[];
325
356
  messagesModified++;
357
+ syncLcKwargs(message);
326
358
  continue;
327
359
  }
328
360
 
@@ -338,6 +370,7 @@ export function addBedrockCacheControl<
338
370
  }
339
371
 
340
372
  if (!hasCacheableContent) {
373
+ syncLcKwargs(message);
341
374
  continue;
342
375
  }
343
376
 
@@ -364,6 +397,8 @@ export function addBedrockCacheControl<
364
397
  }
365
398
  messagesModified++;
366
399
  }
400
+
401
+ syncLcKwargs(message);
367
402
  }
368
403
 
369
404
  return updatedMessages;