@librechat/agents 3.1.97 → 3.1.99

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 (49) hide show
  1. package/dist/cjs/graphs/Graph.cjs +6 -0
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/langfuseToolOutputTracing.cjs +16 -5
  4. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  5. package/dist/cjs/llm/bedrock/index.cjs +10 -0
  6. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  7. package/dist/cjs/llm/bedrock/toolCache.cjs +125 -0
  8. package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -0
  9. package/dist/cjs/messages/cache.cjs +17 -9
  10. package/dist/cjs/messages/cache.cjs.map +1 -1
  11. package/dist/cjs/messages/prune.cjs +45 -8
  12. package/dist/cjs/messages/prune.cjs.map +1 -1
  13. package/dist/cjs/tools/ToolNode.cjs +6 -1
  14. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  15. package/dist/esm/graphs/Graph.mjs +6 -0
  16. package/dist/esm/graphs/Graph.mjs.map +1 -1
  17. package/dist/esm/langfuseToolOutputTracing.mjs +16 -5
  18. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  19. package/dist/esm/llm/bedrock/index.mjs +10 -0
  20. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  21. package/dist/esm/llm/bedrock/toolCache.mjs +122 -0
  22. package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -0
  23. package/dist/esm/messages/cache.mjs +17 -9
  24. package/dist/esm/messages/cache.mjs.map +1 -1
  25. package/dist/esm/messages/prune.mjs +45 -8
  26. package/dist/esm/messages/prune.mjs.map +1 -1
  27. package/dist/esm/tools/ToolNode.mjs +6 -1
  28. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  29. package/dist/types/llm/bedrock/index.d.ts +16 -0
  30. package/dist/types/llm/bedrock/toolCache.d.ts +4 -0
  31. package/dist/types/messages/cache.d.ts +2 -2
  32. package/dist/types/types/llm.d.ts +2 -2
  33. package/package.json +1 -1
  34. package/src/agents/__tests__/AgentContext.anthropic.live.test.ts +332 -0
  35. package/src/agents/__tests__/AgentContext.bedrock.live.test.ts +504 -0
  36. package/src/graphs/Graph.ts +14 -0
  37. package/src/langfuseToolOutputTracing.ts +26 -7
  38. package/src/llm/bedrock/index.ts +32 -1
  39. package/src/llm/bedrock/llm.spec.ts +154 -1
  40. package/src/llm/bedrock/toolCache.test.ts +131 -0
  41. package/src/llm/bedrock/toolCache.ts +191 -0
  42. package/src/messages/cache.test.ts +97 -38
  43. package/src/messages/cache.ts +18 -10
  44. package/src/messages/prune.ts +55 -17
  45. package/src/specs/langfuse-tool-output-tracing.test.ts +28 -0
  46. package/src/specs/prune.test.ts +193 -0
  47. package/src/tools/ToolNode.ts +7 -1
  48. package/src/tools/__tests__/ToolNode.langfuse.test.ts +6 -0
  49. package/src/types/llm.ts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"cache.cjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import {\n AIMessage,\n BaseMessage,\n ToolMessage,\n HumanMessage,\n SystemMessage,\n MessageContentComplex,\n} from '@langchain/core/messages';\nimport type { AnthropicMessage } from '@/types/messages';\nimport type Anthropic from '@anthropic-ai/sdk';\nimport { ContentTypes } from '@/common/enum';\nimport { toLangChainContent } from './langchain';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\n};\n\ntype MessageContentWithCacheControl = MessageContentComplex & {\n cache_control?: unknown;\n};\n\n/**\n * Deep clones a message's content to prevent mutation of the original.\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 new content. For LangChain BaseMessage instances,\n * constructs a proper class instance so that `instanceof` checks are preserved\n * in downstream code (e.g., ensureThinkingBlockInMessages).\n * For plain objects (AnthropicMessage), uses object spread.\n */\nfunction cloneMessage<T extends MessageWithContent>(\n message: T,\n content: string | MessageContentComplex[]\n): T {\n if (message instanceof BaseMessage) {\n const baseParams = {\n content: toLangChainContent(content),\n additional_kwargs: { ...message.additional_kwargs },\n response_metadata: { ...message.response_metadata },\n id: message.id,\n name: message.name,\n };\n\n const msgType = message.getType();\n switch (msgType) {\n case 'ai':\n return new AIMessage({\n ...baseParams,\n tool_calls: (message as unknown as AIMessage).tool_calls,\n }) as unknown as T;\n case 'human':\n return new HumanMessage(baseParams) as unknown as T;\n case 'system':\n return new SystemMessage(baseParams) as unknown as T;\n case 'tool':\n return new ToolMessage({\n ...baseParams,\n tool_call_id: (message as unknown as ToolMessage).tool_call_id,\n }) as unknown as T;\n default:\n break;\n }\n }\n\n const {\n lc_kwargs: _lc_kwargs,\n lc_serializable: _lc_serializable,\n lc_namespace: _lc_namespace,\n ...rest\n } = message as T & {\n lc_kwargs?: unknown;\n lc_serializable?: unknown;\n lc_namespace?: unknown;\n };\n\n const cloned = { ...rest, content } as T;\n\n // LangChain messages don't have a direct 'role' property - derive it from getType()\n if (\n 'getType' in message &&\n typeof message.getType === 'function' &&\n !('role' in cloned)\n ) {\n const msgType = (message as unknown as BaseMessage).getType();\n const roleMap: Record<string, string> = {\n human: 'user',\n ai: 'assistant',\n system: 'system',\n tool: 'tool',\n };\n (cloned as Record<string, unknown>).role = roleMap[msgType] || msgType;\n }\n\n return cloned;\n}\n\nfunction stripAnthropicCacheControlFromBlocks(\n content: MessageContentComplex[]\n): { content: MessageContentComplex[]; modified: boolean } {\n let modified = false;\n const strippedContent = content.map((block) => {\n if (!('cache_control' in block)) {\n return block;\n }\n\n const cloned: MessageContentWithCacheControl = { ...block };\n delete cloned.cache_control;\n modified = true;\n return cloned;\n });\n\n return { content: strippedContent, modified };\n}\n\nfunction sanitizeBedrockSystemMessage<T extends MessageWithContent>(\n message: T\n): T {\n const content = message.content;\n if (!Array.isArray(content)) {\n return message;\n }\n\n const stripped = stripAnthropicCacheControlFromBlocks(content);\n if (!stripped.modified) {\n return message;\n }\n\n return cloneMessage(message, stripped.content);\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 content = originalMessage.content;\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n const hasArrayContent = Array.isArray(content);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof content === 'string' || hasArrayContent);\n\n // Skip messages that don't need any work\n if (!needsCacheAdd && !hasArrayContent) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n let modified = false;\n\n if (hasArrayContent) {\n // Single pass: clone blocks, strip cache markers and cache points,\n // find last text block index for cache insertion — all at once.\n const src = content as MessageContentComplex[];\n workingContent = [];\n let lastTextIndex = -1;\n for (let j = 0; j < src.length; j++) {\n const block = src[j];\n if (isCachePoint(block)) {\n modified = true;\n continue; // skip cache point blocks\n }\n const cloned = { ...block };\n if ('cache_control' in cloned) {\n delete (cloned as Record<string, unknown>).cache_control;\n modified = true;\n }\n if ('type' in cloned && cloned.type === 'text') {\n lastTextIndex = workingContent.length;\n }\n workingContent.push(cloned as MessageContentComplex);\n }\n\n if (!modified && !needsCacheAdd) {\n continue; // nothing to strip and no cache to add\n }\n\n // Add cache control to the last text block for user messages\n if (needsCacheAdd && lastTextIndex >= 0) {\n (\n workingContent[lastTextIndex] as Anthropic.TextBlockParam\n ).cache_control = {\n type: 'ephemeral',\n };\n userMessagesModified++;\n }\n } else if (typeof content === 'string' && needsCacheAdd) {\n workingContent = [\n { type: 'text', text: content, cache_control: { type: 'ephemeral' } },\n ] as unknown as MessageContentComplex[];\n userMessagesModified++;\n } else {\n continue;\n }\n\n updatedMessages[i] = cloneMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\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\nfunction getMessageRole(message: MessageWithContent): string | undefined {\n if (message instanceof BaseMessage) {\n return message.getType();\n }\n if ('role' in message && typeof message.role === 'string') {\n return message.role;\n }\n return undefined;\n}\n\nfunction isCacheableConversationMessage(message: MessageWithContent): boolean {\n const role = getMessageRole(message);\n return (\n role === 'human' || role === 'user' || role === 'ai' || role === 'assistant'\n );\n}\n\nfunction isAssistantConversationMessage(message: MessageWithContent): boolean {\n const role = getMessageRole(message);\n return role === 'ai' || role === 'assistant';\n}\n\nfunction hasCacheMarker(message: MessageWithContent): boolean {\n return (\n Array.isArray(message.content) &&\n message.content.some((block) => 'cache_control' in block)\n );\n}\n\nfunction addCacheControlToRecentMessages<\n T extends AnthropicMessage | BaseMessage,\n>(\n messages: T[],\n maxCachePoints: number,\n canUseMessage: (message: MessageWithContent) => boolean\n): T[] {\n if (\n !Array.isArray(messages) ||\n messages.length === 0 ||\n maxCachePoints <= 0\n ) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let cachePointsAdded = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\n const canAddCache =\n cachePointsAdded < maxCachePoints && canUseMessage(originalMessage);\n\n if (!canAddCache && !hasArrayContent) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n let modified = false;\n\n if (hasArrayContent) {\n const src = content as MessageContentComplex[];\n workingContent = [];\n let lastNonEmptyTextIndex = -1;\n\n for (let j = 0; j < src.length; j++) {\n const block = src[j];\n if (isCachePoint(block)) {\n modified = true;\n continue;\n }\n\n const cloned = { ...block };\n if ('cache_control' in cloned) {\n delete (cloned as Record<string, unknown>).cache_control;\n modified = true;\n }\n\n if ('type' in cloned && cloned.type === 'text') {\n const text = (cloned as { text?: string }).text;\n if (text != null && text.trim() !== '') {\n lastNonEmptyTextIndex = workingContent.length;\n }\n }\n workingContent.push(cloned as MessageContentComplex);\n }\n\n if (canAddCache && lastNonEmptyTextIndex >= 0) {\n (\n workingContent[lastNonEmptyTextIndex] as Anthropic.TextBlockParam\n ).cache_control = {\n type: 'ephemeral',\n };\n cachePointsAdded++;\n modified = true;\n }\n\n if (!modified) {\n continue;\n }\n } else if (\n typeof content === 'string' &&\n content.trim() !== '' &&\n canAddCache\n ) {\n workingContent = [\n { type: 'text', text: content, cache_control: { type: 'ephemeral' } },\n ] as unknown as MessageContentComplex[];\n cachePointsAdded++;\n } else {\n continue;\n }\n\n updatedMessages[i] = cloneMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\n }\n\n return updatedMessages;\n}\n\nexport function addCacheControlToStablePrefixMessages<\n T extends AnthropicMessage | BaseMessage,\n>(messages: T[], maxCachePoints: number): T[] {\n const assistantMarked = addCacheControlToRecentMessages(\n messages,\n maxCachePoints,\n isAssistantConversationMessage\n );\n\n if (assistantMarked.some(hasCacheMarker)) {\n return assistantMarked;\n }\n\n return addCacheControlToRecentMessages(\n messages,\n maxCachePoints,\n isCacheableConversationMessage\n );\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 clonedContent = deepCloneContent(content);\n for (let j = 0; j < clonedContent.length; j++) {\n const block = clonedContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n updatedMessages[i] = cloneMessage(originalMessage, clonedContent);\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 clonedContent = deepCloneContent(content).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n );\n updatedMessages[i] = cloneMessage(originalMessage, clonedContent);\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 MessageWithContent & { getType?: () => string; role?: string },\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 messageType =\n 'getType' in originalMessage &&\n typeof originalMessage.getType === 'function'\n ? originalMessage.getType()\n : undefined;\n const messageRole =\n 'role' in originalMessage && typeof originalMessage.role === 'string'\n ? originalMessage.role\n : undefined;\n\n const isSystemMessage =\n messageType === 'system' || messageRole === 'system';\n if (isSystemMessage) {\n updatedMessages[i] = sanitizeBedrockSystemMessage(originalMessage);\n continue;\n }\n\n const isToolMessage = messageType === 'tool' || messageRole === 'tool';\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\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 (!needsCacheAdd && !hasArrayContent) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n let modified = false;\n\n if (hasArrayContent) {\n // Single pass: clone blocks, strip cache markers, find last\n // non-empty text block for cache point insertion — all at once.\n const src = content as MessageContentComplex[];\n workingContent = [];\n let lastNonEmptyTextIndex = -1;\n for (let j = 0; j < src.length; j++) {\n const block = src[j];\n if (isCachePoint(block)) {\n modified = true;\n continue;\n }\n const cloned = { ...block };\n if ('cache_control' in cloned) {\n delete (cloned as Record<string, unknown>).cache_control;\n modified = true;\n }\n const type = (cloned as { type?: string }).type;\n if (type === ContentTypes.TEXT || type === 'text') {\n const text = (cloned as { text?: string }).text;\n if (text != null && text.trim() !== '') {\n lastNonEmptyTextIndex = workingContent.length;\n }\n }\n workingContent.push(cloned as MessageContentComplex);\n }\n\n if (!modified && !needsCacheAdd) {\n continue;\n }\n\n // Insert cache point after the last non-empty text block.\n // Skip if no cacheable text content exists (whitespace-only messages).\n if (needsCacheAdd && lastNonEmptyTextIndex >= 0) {\n workingContent.splice(lastNonEmptyTextIndex + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n messagesModified++;\n }\n } else if (typeof content === 'string' && needsCacheAdd) {\n workingContent = [\n { type: ContentTypes.TEXT, text: content },\n { cachePoint: { type: 'default' } } as MessageContentComplex,\n ];\n messagesModified++;\n } else {\n continue;\n }\n\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n }\n\n return updatedMessages;\n}\n"],"names":["BaseMessage","toLangChainContent","AIMessage","HumanMessage","SystemMessage","ToolMessage","ContentTypes"],"mappings":"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"}
1
+ {"version":3,"file":"cache.cjs","sources":["../../../src/messages/cache.ts"],"sourcesContent":["import {\n AIMessage,\n BaseMessage,\n ToolMessage,\n HumanMessage,\n SystemMessage,\n MessageContentComplex,\n} from '@langchain/core/messages';\nimport type { AnthropicMessage } from '@/types/messages';\nimport type Anthropic from '@anthropic-ai/sdk';\nimport { ContentTypes } from '@/common/enum';\nimport { toLangChainContent } from './langchain';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\n};\n\ntype MessageContentWithCacheControl = MessageContentComplex & {\n cache_control?: unknown;\n};\n\n/**\n * Deep clones a message's content to prevent mutation of the original.\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 new content. For LangChain BaseMessage instances,\n * constructs a proper class instance so that `instanceof` checks are preserved\n * in downstream code (e.g., ensureThinkingBlockInMessages).\n * For plain objects (AnthropicMessage), uses object spread.\n */\nfunction cloneMessage<T extends MessageWithContent>(\n message: T,\n content: string | MessageContentComplex[]\n): T {\n if (message instanceof BaseMessage) {\n const baseParams = {\n content: toLangChainContent(content),\n additional_kwargs: { ...message.additional_kwargs },\n response_metadata: { ...message.response_metadata },\n id: message.id,\n name: message.name,\n };\n\n const msgType = message.getType();\n switch (msgType) {\n case 'ai':\n return new AIMessage({\n ...baseParams,\n tool_calls: (message as unknown as AIMessage).tool_calls,\n }) as unknown as T;\n case 'human':\n return new HumanMessage(baseParams) as unknown as T;\n case 'system':\n return new SystemMessage(baseParams) as unknown as T;\n case 'tool':\n return new ToolMessage({\n ...baseParams,\n tool_call_id: (message as unknown as ToolMessage).tool_call_id,\n }) as unknown as T;\n default:\n break;\n }\n }\n\n const {\n lc_kwargs: _lc_kwargs,\n lc_serializable: _lc_serializable,\n lc_namespace: _lc_namespace,\n ...rest\n } = message as T & {\n lc_kwargs?: unknown;\n lc_serializable?: unknown;\n lc_namespace?: unknown;\n };\n\n const cloned = { ...rest, content } as T;\n\n // LangChain messages don't have a direct 'role' property - derive it from getType()\n if (\n 'getType' in message &&\n typeof message.getType === 'function' &&\n !('role' in cloned)\n ) {\n const msgType = (message as unknown as BaseMessage).getType();\n const roleMap: Record<string, string> = {\n human: 'user',\n ai: 'assistant',\n system: 'system',\n tool: 'tool',\n };\n (cloned as Record<string, unknown>).role = roleMap[msgType] || msgType;\n }\n\n return cloned;\n}\n\nfunction stripAnthropicCacheControlFromBlocks(\n content: MessageContentComplex[]\n): { content: MessageContentComplex[]; modified: boolean } {\n let modified = false;\n const strippedContent = content.map((block) => {\n if (!('cache_control' in block)) {\n return block;\n }\n\n const cloned: MessageContentWithCacheControl = { ...block };\n delete cloned.cache_control;\n modified = true;\n return cloned;\n });\n\n return { content: strippedContent, modified };\n}\n\nfunction sanitizeBedrockSystemMessage<T extends MessageWithContent>(\n message: T\n): T {\n const content = message.content;\n if (!Array.isArray(content)) {\n return message;\n }\n\n const stripped = stripAnthropicCacheControlFromBlocks(content);\n if (!stripped.modified) {\n return message;\n }\n\n return cloneMessage(message, stripped.content);\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 content = originalMessage.content;\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n const hasArrayContent = Array.isArray(content);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof content === 'string' || hasArrayContent);\n\n // Skip messages that don't need any work\n if (!needsCacheAdd && !hasArrayContent) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n let modified = false;\n\n if (hasArrayContent) {\n // Single pass: clone blocks, strip cache markers and cache points,\n // find last text block index for cache insertion — all at once.\n const src = content as MessageContentComplex[];\n workingContent = [];\n let lastTextIndex = -1;\n for (let j = 0; j < src.length; j++) {\n const block = src[j];\n if (isCachePoint(block)) {\n modified = true;\n continue; // skip cache point blocks\n }\n const cloned = { ...block };\n if ('cache_control' in cloned) {\n delete (cloned as Record<string, unknown>).cache_control;\n modified = true;\n }\n if ('type' in cloned && cloned.type === 'text') {\n lastTextIndex = workingContent.length;\n }\n workingContent.push(cloned as MessageContentComplex);\n }\n\n if (!modified && !needsCacheAdd) {\n continue; // nothing to strip and no cache to add\n }\n\n // Add cache control to the last text block for user messages\n if (needsCacheAdd && lastTextIndex >= 0) {\n (\n workingContent[lastTextIndex] as Anthropic.TextBlockParam\n ).cache_control = {\n type: 'ephemeral',\n };\n userMessagesModified++;\n }\n } else if (typeof content === 'string' && needsCacheAdd) {\n workingContent = [\n { type: 'text', text: content, cache_control: { type: 'ephemeral' } },\n ] as unknown as MessageContentComplex[];\n userMessagesModified++;\n } else {\n continue;\n }\n\n updatedMessages[i] = cloneMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\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\nfunction getMessageRole(message: MessageWithContent): string | undefined {\n if (message instanceof BaseMessage) {\n return message.getType();\n }\n if ('role' in message && typeof message.role === 'string') {\n return message.role;\n }\n return undefined;\n}\n\nfunction isCacheableConversationMessage(message: MessageWithContent): boolean {\n const role = getMessageRole(message);\n return (\n role === 'human' || role === 'user' || role === 'ai' || role === 'assistant'\n );\n}\n\nfunction isAssistantConversationMessage(message: MessageWithContent): boolean {\n const role = getMessageRole(message);\n return role === 'ai' || role === 'assistant';\n}\n\nfunction hasCacheMarker(message: MessageWithContent): boolean {\n return (\n Array.isArray(message.content) &&\n message.content.some((block) => 'cache_control' in block)\n );\n}\n\nfunction addCacheControlToRecentMessages<\n T extends AnthropicMessage | BaseMessage,\n>(\n messages: T[],\n maxCachePoints: number,\n canUseMessage: (message: MessageWithContent) => boolean\n): T[] {\n if (\n !Array.isArray(messages) ||\n messages.length === 0 ||\n maxCachePoints <= 0\n ) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let cachePointsAdded = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const content = originalMessage.content;\n const hasArrayContent = Array.isArray(content);\n const canAddCache =\n cachePointsAdded < maxCachePoints && canUseMessage(originalMessage);\n\n if (!canAddCache && !hasArrayContent) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n let modified = false;\n\n if (hasArrayContent) {\n const src = content as MessageContentComplex[];\n workingContent = [];\n let lastNonEmptyTextIndex = -1;\n\n for (let j = 0; j < src.length; j++) {\n const block = src[j];\n if (isCachePoint(block)) {\n modified = true;\n continue;\n }\n\n const cloned = { ...block };\n if ('cache_control' in cloned) {\n delete (cloned as Record<string, unknown>).cache_control;\n modified = true;\n }\n\n if ('type' in cloned && cloned.type === 'text') {\n const text = (cloned as { text?: string }).text;\n if (text != null && text.trim() !== '') {\n lastNonEmptyTextIndex = workingContent.length;\n }\n }\n workingContent.push(cloned as MessageContentComplex);\n }\n\n if (canAddCache && lastNonEmptyTextIndex >= 0) {\n (\n workingContent[lastNonEmptyTextIndex] as Anthropic.TextBlockParam\n ).cache_control = {\n type: 'ephemeral',\n };\n cachePointsAdded++;\n modified = true;\n }\n\n if (!modified) {\n continue;\n }\n } else if (\n typeof content === 'string' &&\n content.trim() !== '' &&\n canAddCache\n ) {\n workingContent = [\n { type: 'text', text: content, cache_control: { type: 'ephemeral' } },\n ] as unknown as MessageContentComplex[];\n cachePointsAdded++;\n } else {\n continue;\n }\n\n updatedMessages[i] = cloneMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\n }\n\n return updatedMessages;\n}\n\nexport function addCacheControlToStablePrefixMessages<\n T extends AnthropicMessage | BaseMessage,\n>(messages: T[], maxCachePoints: number): T[] {\n const assistantMarked = addCacheControlToRecentMessages(\n messages,\n maxCachePoints,\n isAssistantConversationMessage\n );\n\n if (assistantMarked.some(hasCacheMarker)) {\n return assistantMarked;\n }\n\n return addCacheControlToRecentMessages(\n messages,\n maxCachePoints,\n isCacheableConversationMessage\n );\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 clonedContent = deepCloneContent(content);\n for (let j = 0; j < clonedContent.length; j++) {\n const block = clonedContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n updatedMessages[i] = cloneMessage(originalMessage, clonedContent);\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 clonedContent = deepCloneContent(content).filter(\n (block) => !isCachePoint(block as MessageContentComplex)\n );\n updatedMessages[i] = cloneMessage(originalMessage, clonedContent);\n }\n\n return updatedMessages;\n}\n\n/**\n * Adds Bedrock Converse API cache points to the latest two user 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 latest two non-tool 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 points added.\n */\nexport function addBedrockCacheControl<\n T extends MessageWithContent & { getType?: () => string; role?: string },\n>(messages: T[]): T[] {\n if (!Array.isArray(messages) || messages.length === 0) {\n return messages;\n }\n\n const updatedMessages: T[] = [...messages];\n let cachePointsAdded = 0;\n\n for (let i = updatedMessages.length - 1; i >= 0; i--) {\n const originalMessage = updatedMessages[i];\n const messageType =\n 'getType' in originalMessage &&\n typeof originalMessage.getType === 'function'\n ? originalMessage.getType()\n : undefined;\n const messageRole =\n 'role' in originalMessage && typeof originalMessage.role === 'string'\n ? originalMessage.role\n : undefined;\n\n const isSystemMessage =\n messageType === 'system' || messageRole === 'system';\n if (isSystemMessage) {\n updatedMessages[i] = sanitizeBedrockSystemMessage(originalMessage);\n continue;\n }\n\n const isToolMessage = messageType === 'tool' || messageRole === 'tool';\n const isUserMessage = messageType === 'human' || messageRole === 'user';\n const content = originalMessage.content;\n const hasSerializationProps =\n 'lc_kwargs' in originalMessage ||\n 'lc_serializable' in originalMessage ||\n 'lc_namespace' in originalMessage;\n const hasArrayContent = Array.isArray(content);\n const isEmptyString = typeof content === 'string' && content === '';\n const needsCacheAdd =\n cachePointsAdded < 2 &&\n isUserMessage &&\n !isToolMessage &&\n !isEmptyString &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsCacheAdd && !hasArrayContent && !hasSerializationProps) {\n continue;\n }\n\n let workingContent: string | MessageContentComplex[];\n let modified = hasSerializationProps;\n\n if (hasArrayContent) {\n // Single pass: clone blocks, strip cache markers, find last\n // non-empty text block for cache point insertion — all at once.\n const src = content as MessageContentComplex[];\n workingContent = [];\n let lastNonEmptyTextIndex = -1;\n for (let j = 0; j < src.length; j++) {\n const block = src[j];\n if (isCachePoint(block)) {\n modified = true;\n continue;\n }\n const cloned = { ...block };\n if ('cache_control' in cloned) {\n delete (cloned as Record<string, unknown>).cache_control;\n modified = true;\n }\n const type = (cloned as { type?: string }).type;\n if (type === ContentTypes.TEXT || type === 'text') {\n const text = (cloned as { text?: string }).text;\n if (text != null && text.trim() !== '') {\n lastNonEmptyTextIndex = workingContent.length;\n }\n }\n workingContent.push(cloned as MessageContentComplex);\n }\n\n if (!modified && !needsCacheAdd) {\n continue;\n }\n\n // Insert cache point after the last non-empty text block.\n // Skip if no cacheable text content exists (whitespace-only messages).\n if (needsCacheAdd && lastNonEmptyTextIndex >= 0) {\n workingContent.splice(lastNonEmptyTextIndex + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n cachePointsAdded++;\n }\n } else if (typeof content === 'string' && needsCacheAdd) {\n workingContent = [\n { type: ContentTypes.TEXT, text: content },\n { cachePoint: { type: 'default' } } as MessageContentComplex,\n ];\n cachePointsAdded++;\n } else if (typeof content === 'string' && hasSerializationProps) {\n workingContent = content;\n } else {\n continue;\n }\n\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n }\n\n return updatedMessages;\n}\n"],"names":["BaseMessage","toLangChainContent","AIMessage","HumanMessage","SystemMessage","ToolMessage","ContentTypes"],"mappings":"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"}
@@ -366,7 +366,7 @@ function addThinkingBlock(message, thinkingBlock) {
366
366
  },
367
367
  ];
368
368
  /** Edge case, the message already has the thinking block */
369
- if (content[0].type === thinkingBlock.type) {
369
+ if (content[0]?.type === thinkingBlock.type) {
370
370
  return message;
371
371
  }
372
372
  content.unshift(thinkingBlock);
@@ -399,6 +399,26 @@ function calculateTotalTokens(usage) {
399
399
  total_tokens: totalInputTokens + totalOutputTokens,
400
400
  };
401
401
  }
402
+ /**
403
+ * Locates a reasoning block in assistant content. Reasoning blocks carry
404
+ * provider-specific `type` tags: Anthropic emits `thinking`, while Bedrock and
405
+ * OpenAI-compatible reasoning providers (DeepSeek-R1, DashScope/Qwen-thinking)
406
+ * emit `reasoning_content`. DeepSeek/Qwen route through the `THINKING` default
407
+ * even though their blocks are `reasoning_content` and aren't normalized
408
+ * upstream, so for the `THINKING` case we also accept `reasoning_content` — this
409
+ * is what fixes issue #191.
410
+ *
411
+ * The broadening is intentionally one-directional. A Bedrock run
412
+ * (`REASONING_CONTENT`) must NOT match an Anthropic `thinking` block: the
413
+ * Bedrock input converter rejects `thinking` blocks outright
414
+ * (`src/llm/bedrock/utils/message_inputs.ts`), so reattaching one to a
415
+ * surviving message would make the request fail before it is sent.
416
+ */
417
+ function findReasoningBlock(content, reasoningType) {
418
+ return content.find((part) => part.type === reasoningType ||
419
+ (reasoningType === _enum.ContentTypes.THINKING &&
420
+ part.type === _enum.ContentTypes.REASONING_CONTENT));
421
+ }
402
422
  /**
403
423
  * Processes an array of messages and returns a context of messages that fit within a specified token limit.
404
424
  * It iterates over the messages from newest to oldest, adding them to the context until the token limit is reached.
@@ -431,7 +451,7 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
431
451
  if (_thinkingStartIndex > -1) {
432
452
  const thinkingMessageContent = messages$1[_thinkingStartIndex]?.content;
433
453
  if (Array.isArray(thinkingMessageContent)) {
434
- thinkingBlock = thinkingMessageContent.find((content) => content.type === reasoningType);
454
+ thinkingBlock = findReasoningBlock(thinkingMessageContent, reasoningType);
435
455
  }
436
456
  }
437
457
  if (currentTokenCount < remainingContextTokens) {
@@ -458,7 +478,7 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
458
478
  thinkingStartIndex < 0 &&
459
479
  messageType === 'ai' &&
460
480
  Array.isArray(poppedMessage.content)) {
461
- thinkingBlock = poppedMessage.content.find((content) => content.type === reasoningType);
481
+ thinkingBlock = findReasoningBlock(poppedMessage.content, reasoningType);
462
482
  thinkingStartIndex = thinkingBlock != null ? currentIndex : -1;
463
483
  }
464
484
  /**
@@ -542,11 +562,28 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
542
562
  result.context = context.reverse();
543
563
  return result;
544
564
  }
545
- if (thinkingEndIndex > -1 && thinkingStartIndex < 0) {
546
- throw new Error('The payload is malformed. There is a thinking sequence but no "AI" messages with thinking blocks.');
547
- }
548
- if (!thinkingBlock) {
549
- throw new Error('The payload is malformed. There is a thinking sequence but no thinking block found.');
565
+ /**
566
+ * A trailing reasoning sequence was detected but its block could not be
567
+ * located in the surviving context. Rather than throw — which permanently
568
+ * bricks the conversation, re-firing on every retry of the same thread (see
569
+ * issue #191) return the partially-pruned context and let the provider
570
+ * surface a real, recoverable error if the payload is genuinely malformed.
571
+ * Strict providers (Anthropic) reject it cleanly; lenient ones (DeepSeek,
572
+ * Qwen) proceed. The pruner cannot know which applies, so it must not be the
573
+ * one to make the failure fatal.
574
+ */
575
+ if ((thinkingEndIndex > -1 && thinkingStartIndex < 0) || !thinkingBlock) {
576
+ /**
577
+ * No block was located, so any `thinkingStartIndex` set above came from a
578
+ * stale carried-over index pointing at a block-less message. Drop it:
579
+ * `createPruneMessages` persists the returned index as
580
+ * `runThinkingStartIndex`, and a stale value would suppress the trailing
581
+ * scan (`thinkingStartIndex < 0`) on later turns, causing a real reasoning
582
+ * block to be missed and never reattached.
583
+ */
584
+ delete result.thinkingStartIndex;
585
+ result.context = context.reverse();
586
+ return result;
550
587
  }
551
588
  let assistantIndex = -1;
552
589
  for (let i = 0; i < context.length; i++) {