@librechat/agents 3.1.42 → 3.1.43
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.
- package/dist/cjs/agents/AgentContext.cjs +26 -1
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +31 -2
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +80 -10
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +26 -1
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +31 -2
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +81 -11
- package/dist/esm/messages/format.mjs.map +1 -1
- package/package.json +1 -1
- package/src/agents/AgentContext.ts +28 -1
- package/src/messages/cache.test.ts +82 -1
- package/src/messages/cache.ts +42 -3
- package/src/messages/ensureThinkingBlock.test.ts +207 -0
- package/src/messages/format.ts +106 -10
|
@@ -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 */\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, explicitly excluding LangChain\n * serialization metadata to prevent coercion issues.\n */\nfunction cloneMessage<T extends MessageWithContent>(\n message: T,\n content: string | MessageContentComplex[]\n): T {\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\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 content = originalMessage.content;\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n\n if (hasArrayContent) {\n workingContent = deepCloneContent(\n content as MessageContentComplex[]\n ).filter((block) => !isCachePoint(block as MessageContentComplex));\n\n for (let j = 0; j < workingContent.length; j++) {\n const block = workingContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n } else if (typeof content === 'string') {\n workingContent = [\n { type: 'text', text: content },\n ] as MessageContentComplex[];\n } else {\n workingContent = [];\n }\n\n if (userMessagesModified >= 2 || !isUserMessage) {\n updatedMessages[i] = cloneMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\n continue;\n }\n\n for (let j = workingContent.length - 1; j >= 0; j--) {\n const contentPart = workingContent[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 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\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 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 let workingContent: MessageContentComplex[];\n\n if (hasArrayContent) {\n workingContent = deepCloneContent(\n content as MessageContentComplex[]\n ).filter((block) => !isCachePoint(block));\n\n for (let j = 0; j < workingContent.length; j++) {\n const block = workingContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n } else if (typeof content === 'string') {\n workingContent = [{ type: ContentTypes.TEXT, text: content }];\n } else {\n workingContent = [];\n }\n\n if (messagesModified >= 2 || isToolMessage || isEmptyString) {\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n continue;\n }\n\n if (workingContent.length === 0) {\n continue;\n }\n\n let hasCacheableContent = false;\n for (const block of workingContent) {\n if (block.type === ContentTypes.TEXT) {\n if (typeof block.text === 'string' && block.text.trim() !== '') {\n hasCacheableContent = true;\n break;\n }\n }\n }\n\n if (!hasCacheableContent) {\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n continue;\n }\n\n let inserted = false;\n for (let j = workingContent.length - 1; j >= 0; j--) {\n const block = workingContent[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 || text.trim() === '') {\n continue;\n }\n workingContent.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n workingContent.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n messagesModified++;\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 {\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';\n\ntype MessageWithContent = {\n content?: string | MessageContentComplex[];\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,\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\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 content = originalMessage.content;\n const isUserMessage =\n ('getType' in originalMessage && originalMessage.getType() === 'human') ||\n ('role' in originalMessage && originalMessage.role === 'user');\n\n const hasArrayContent = Array.isArray(content);\n const needsStripping =\n hasArrayContent &&\n needsCacheStripping(content as MessageContentComplex[]);\n const needsCacheAdd =\n userMessagesModified < 2 &&\n isUserMessage &&\n (typeof content === 'string' || hasArrayContent);\n\n if (!needsStripping && !needsCacheAdd) {\n continue;\n }\n\n let workingContent: MessageContentComplex[];\n\n if (hasArrayContent) {\n workingContent = deepCloneContent(\n content as MessageContentComplex[]\n ).filter((block) => !isCachePoint(block as MessageContentComplex));\n\n for (let j = 0; j < workingContent.length; j++) {\n const block = workingContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n } else if (typeof content === 'string') {\n workingContent = [\n { type: 'text', text: content },\n ] as MessageContentComplex[];\n } else {\n workingContent = [];\n }\n\n if (userMessagesModified >= 2 || !isUserMessage) {\n updatedMessages[i] = cloneMessage(\n originalMessage as MessageWithContent,\n workingContent\n ) as T;\n continue;\n }\n\n for (let j = workingContent.length - 1; j >= 0; j--) {\n const contentPart = workingContent[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 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\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 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 let workingContent: MessageContentComplex[];\n\n if (hasArrayContent) {\n workingContent = deepCloneContent(\n content as MessageContentComplex[]\n ).filter((block) => !isCachePoint(block));\n\n for (let j = 0; j < workingContent.length; j++) {\n const block = workingContent[j] as Record<string, unknown>;\n if ('cache_control' in block) {\n delete block.cache_control;\n }\n }\n } else if (typeof content === 'string') {\n workingContent = [{ type: ContentTypes.TEXT, text: content }];\n } else {\n workingContent = [];\n }\n\n if (messagesModified >= 2 || isToolMessage || isEmptyString) {\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n continue;\n }\n\n if (workingContent.length === 0) {\n continue;\n }\n\n let hasCacheableContent = false;\n for (const block of workingContent) {\n if (block.type === ContentTypes.TEXT) {\n if (typeof block.text === 'string' && block.text.trim() !== '') {\n hasCacheableContent = true;\n break;\n }\n }\n }\n\n if (!hasCacheableContent) {\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n continue;\n }\n\n let inserted = false;\n for (let j = workingContent.length - 1; j >= 0; j--) {\n const block = workingContent[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 || text.trim() === '') {\n continue;\n }\n workingContent.splice(j + 1, 0, {\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n inserted = true;\n break;\n }\n }\n if (!inserted) {\n workingContent.push({\n cachePoint: { type: 'default' },\n } as MessageContentComplex);\n }\n\n updatedMessages[i] = cloneMessage(originalMessage, workingContent);\n messagesModified++;\n }\n\n return updatedMessages;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HumanMessage, AIMessage, SystemMessage,
|
|
1
|
+
import { HumanMessage, AIMessage, SystemMessage, AIMessageChunk, getBufferString, ToolMessage } from '@langchain/core/messages';
|
|
2
2
|
import { Providers, ContentTypes, Constants } from '../common/enum.mjs';
|
|
3
3
|
|
|
4
4
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
@@ -741,7 +741,11 @@ function ensureThinkingBlockInMessages(messages, _provider) {
|
|
|
741
741
|
let i = 0;
|
|
742
742
|
while (i < messages.length) {
|
|
743
743
|
const msg = messages[i];
|
|
744
|
-
|
|
744
|
+
/** Detect AI messages by instanceof OR by role, in case cache-control cloning
|
|
745
|
+
produced a plain object that lost the LangChain prototype. */
|
|
746
|
+
const isAI = msg instanceof AIMessage ||
|
|
747
|
+
msg instanceof AIMessageChunk ||
|
|
748
|
+
('role' in msg && msg.role === 'assistant');
|
|
745
749
|
if (!isAI) {
|
|
746
750
|
result.push(msg);
|
|
747
751
|
i++;
|
|
@@ -752,25 +756,47 @@ function ensureThinkingBlockInMessages(messages, _provider) {
|
|
|
752
756
|
const contentIsArray = Array.isArray(aiMsg.content);
|
|
753
757
|
// Check if the message has tool calls or tool_use content
|
|
754
758
|
let hasToolUse = hasToolCalls ?? false;
|
|
755
|
-
let
|
|
759
|
+
let hasThinkingBlock = false;
|
|
756
760
|
if (contentIsArray && aiMsg.content.length > 0) {
|
|
757
761
|
const content = aiMsg.content;
|
|
758
|
-
firstContentType = content[0]?.type;
|
|
759
762
|
hasToolUse =
|
|
760
763
|
hasToolUse ||
|
|
761
764
|
content.some((c) => typeof c === 'object' && c.type === 'tool_use');
|
|
765
|
+
// Check ALL content blocks for thinking/reasoning, not just [0].
|
|
766
|
+
// Bedrock may emit a whitespace text chunk before the thinking block,
|
|
767
|
+
// pushing the reasoning_content to index 1+.
|
|
768
|
+
hasThinkingBlock = content.some((c) => typeof c === 'object' &&
|
|
769
|
+
(c.type === ContentTypes.THINKING ||
|
|
770
|
+
c.type === ContentTypes.REASONING_CONTENT ||
|
|
771
|
+
c.type === ContentTypes.REASONING ||
|
|
772
|
+
c.type === 'redacted_thinking'));
|
|
762
773
|
}
|
|
763
|
-
//
|
|
764
|
-
if (
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
774
|
+
// Bedrock also stores reasoning in additional_kwargs (may not be in content array)
|
|
775
|
+
if (!hasThinkingBlock &&
|
|
776
|
+
aiMsg.additional_kwargs.reasoning_content != null) {
|
|
777
|
+
hasThinkingBlock = true;
|
|
778
|
+
}
|
|
779
|
+
// If message has tool use but no thinking block, check whether this is a
|
|
780
|
+
// continuation of a thinking-enabled agent's chain before converting.
|
|
781
|
+
// Bedrock reasoning models can produce multiple AI→Tool rounds after an
|
|
782
|
+
// initial reasoning response: the first AI message has reasoning_content,
|
|
783
|
+
// but follow-ups have content: "" with only tool_calls. These are the
|
|
784
|
+
// same agent's turn and must NOT be converted to HumanMessages.
|
|
785
|
+
if (hasToolUse && !hasThinkingBlock) {
|
|
786
|
+
// Walk backwards — if an earlier AI message in the same chain (before
|
|
787
|
+
// the nearest HumanMessage) has a thinking/reasoning block, this is a
|
|
788
|
+
// continuation of a thinking-enabled turn, not a non-thinking handoff.
|
|
789
|
+
if (chainHasThinkingBlock(messages, i)) {
|
|
790
|
+
result.push(msg);
|
|
791
|
+
i++;
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
769
794
|
// Collect the AI message and any following tool messages
|
|
770
795
|
const toolSequence = [msg];
|
|
771
796
|
let j = i + 1;
|
|
772
797
|
// Look ahead for tool messages that belong to this AI message
|
|
773
|
-
|
|
798
|
+
const isToolMsg = (m) => m instanceof ToolMessage || ('role' in m && m.role === 'tool');
|
|
799
|
+
while (j < messages.length && isToolMsg(messages[j])) {
|
|
774
800
|
toolSequence.push(messages[j]);
|
|
775
801
|
j++;
|
|
776
802
|
}
|
|
@@ -791,6 +817,50 @@ function ensureThinkingBlockInMessages(messages, _provider) {
|
|
|
791
817
|
}
|
|
792
818
|
return result;
|
|
793
819
|
}
|
|
820
|
+
/**
|
|
821
|
+
* Walks backwards from `currentIndex` through the message array to check
|
|
822
|
+
* whether an earlier AI message in the same "chain" (no HumanMessage boundary)
|
|
823
|
+
* contains a thinking/reasoning block.
|
|
824
|
+
*
|
|
825
|
+
* A "chain" is a contiguous sequence of AI + Tool messages with no intervening
|
|
826
|
+
* HumanMessage. Bedrock reasoning models produce reasoning on the first AI
|
|
827
|
+
* response, then issue follow-up tool calls with `content: ""` and no
|
|
828
|
+
* reasoning block. These follow-ups are part of the same thinking-enabled
|
|
829
|
+
* turn and should not be converted.
|
|
830
|
+
*/
|
|
831
|
+
function chainHasThinkingBlock(messages, currentIndex) {
|
|
832
|
+
for (let k = currentIndex - 1; k >= 0; k--) {
|
|
833
|
+
const prev = messages[k];
|
|
834
|
+
// HumanMessage = turn boundary — stop searching
|
|
835
|
+
if (prev instanceof HumanMessage ||
|
|
836
|
+
('role' in prev && prev.role === 'user')) {
|
|
837
|
+
return false;
|
|
838
|
+
}
|
|
839
|
+
// Check AI messages for thinking/reasoning blocks
|
|
840
|
+
const isPrevAI = prev instanceof AIMessage ||
|
|
841
|
+
prev instanceof AIMessageChunk ||
|
|
842
|
+
('role' in prev && prev.role === 'assistant');
|
|
843
|
+
if (isPrevAI) {
|
|
844
|
+
const prevAiMsg = prev;
|
|
845
|
+
if (Array.isArray(prevAiMsg.content) && prevAiMsg.content.length > 0) {
|
|
846
|
+
const content = prevAiMsg.content;
|
|
847
|
+
if (content.some((c) => typeof c === 'object' &&
|
|
848
|
+
(c.type === ContentTypes.THINKING ||
|
|
849
|
+
c.type === ContentTypes.REASONING_CONTENT ||
|
|
850
|
+
c.type === ContentTypes.REASONING ||
|
|
851
|
+
c.type === 'redacted_thinking'))) {
|
|
852
|
+
return true;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
// Bedrock also stores reasoning in additional_kwargs
|
|
856
|
+
if (prevAiMsg.additional_kwargs.reasoning_content != null) {
|
|
857
|
+
return true;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
// ToolMessages are part of the chain — keep walking back
|
|
861
|
+
}
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
794
864
|
|
|
795
865
|
export { ensureThinkingBlockInMessages, formatAgentMessages, formatFromLangChain, formatLangChainMessages, formatMediaMessage, formatMessage, labelContentByAgent, shiftIndexTokenCountMap };
|
|
796
866
|
//# sourceMappingURL=format.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.mjs","sources":["../../../src/messages/format.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n AIMessage,\n AIMessageChunk,\n ToolMessage,\n BaseMessage,\n HumanMessage,\n SystemMessage,\n getBufferString,\n} from '@langchain/core/messages';\nimport type { MessageContentImageUrl } from '@langchain/core/messages';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type {\n ExtendedMessageContent,\n MessageContentComplex,\n ReasoningContentText,\n ToolCallContent,\n ToolCallPart,\n TPayload,\n TMessage,\n} from '@/types';\nimport { Providers, ContentTypes, Constants } from '@/common';\n\ninterface MediaMessageParams {\n message: {\n role: string;\n content: string;\n name?: string;\n [key: string]: any;\n };\n mediaParts: MessageContentComplex[];\n endpoint?: Providers;\n}\n\n/**\n * Formats a message with media content (images, documents, videos, audios) to API payload format.\n *\n * @param params - The parameters for formatting.\n * @returns - The formatted message.\n */\nexport const formatMediaMessage = ({\n message,\n endpoint,\n mediaParts,\n}: MediaMessageParams): {\n role: string;\n content: MessageContentComplex[];\n name?: string;\n [key: string]: any;\n} => {\n // Create a new object to avoid mutating the input\n const result: {\n role: string;\n content: MessageContentComplex[];\n name?: string;\n [key: string]: any;\n } = {\n ...message,\n content: [] as MessageContentComplex[],\n };\n\n if (endpoint === Providers.ANTHROPIC) {\n result.content = [\n ...mediaParts,\n { type: ContentTypes.TEXT, text: message.content },\n ] as MessageContentComplex[];\n return result;\n }\n\n result.content = [\n { type: ContentTypes.TEXT, text: message.content },\n ...mediaParts,\n ] as MessageContentComplex[];\n\n return result;\n};\n\ninterface MessageInput {\n role?: string;\n _name?: string;\n sender?: string;\n text?: string;\n content?: string | MessageContentComplex[];\n image_urls?: MessageContentImageUrl[];\n documents?: MessageContentComplex[];\n videos?: MessageContentComplex[];\n audios?: MessageContentComplex[];\n lc_id?: string[];\n [key: string]: any;\n}\n\ninterface FormatMessageParams {\n message: MessageInput;\n userName?: string;\n assistantName?: string;\n endpoint?: Providers;\n langChain?: boolean;\n}\n\ninterface FormattedMessage {\n role: string;\n content: string | MessageContentComplex[];\n name?: string;\n [key: string]: any;\n}\n\n/**\n * Formats a message to OpenAI payload format based on the provided options.\n *\n * @param params - The parameters for formatting.\n * @returns - The formatted message.\n */\nexport const formatMessage = ({\n message,\n userName,\n endpoint,\n assistantName,\n langChain = false,\n}: FormatMessageParams):\n | FormattedMessage\n | HumanMessage\n | AIMessage\n | SystemMessage => {\n // eslint-disable-next-line prefer-const\n let { role: _role, _name, sender, text, content: _content, lc_id } = message;\n if (lc_id && lc_id[2] && !langChain) {\n const roleMapping: Record<string, string> = {\n SystemMessage: 'system',\n HumanMessage: 'user',\n AIMessage: 'assistant',\n };\n _role = roleMapping[lc_id[2]] || _role;\n }\n const role =\n _role ??\n (sender != null && sender && sender.toLowerCase() === 'user'\n ? 'user'\n : 'assistant');\n const content = _content ?? text ?? '';\n const formattedMessage: FormattedMessage = {\n role,\n content,\n };\n\n // Set name fields first\n if (_name != null && _name) {\n formattedMessage.name = _name;\n }\n\n if (userName != null && userName && formattedMessage.role === 'user') {\n formattedMessage.name = userName;\n }\n\n if (\n assistantName != null &&\n assistantName &&\n formattedMessage.role === 'assistant'\n ) {\n formattedMessage.name = assistantName;\n }\n\n if (formattedMessage.name != null && formattedMessage.name) {\n // Conform to API regex: ^[a-zA-Z0-9_-]{1,64}$\n // https://community.openai.com/t/the-format-of-the-name-field-in-the-documentation-is-incorrect/175684/2\n formattedMessage.name = formattedMessage.name.replace(\n /[^a-zA-Z0-9_-]/g,\n '_'\n );\n\n if (formattedMessage.name.length > 64) {\n formattedMessage.name = formattedMessage.name.substring(0, 64);\n }\n }\n\n const { image_urls, documents, videos, audios } = message;\n const mediaParts: MessageContentComplex[] = [];\n\n if (Array.isArray(documents) && documents.length > 0) {\n mediaParts.push(...documents);\n }\n\n if (Array.isArray(videos) && videos.length > 0) {\n mediaParts.push(...videos);\n }\n\n if (Array.isArray(audios) && audios.length > 0) {\n mediaParts.push(...audios);\n }\n\n if (Array.isArray(image_urls) && image_urls.length > 0) {\n mediaParts.push(...image_urls);\n }\n\n if (mediaParts.length > 0 && role === 'user') {\n const mediaMessage = formatMediaMessage({\n message: {\n ...formattedMessage,\n content:\n typeof formattedMessage.content === 'string'\n ? formattedMessage.content\n : '',\n },\n mediaParts,\n endpoint,\n });\n\n if (!langChain) {\n return mediaMessage;\n }\n\n return new HumanMessage(mediaMessage);\n }\n\n if (!langChain) {\n return formattedMessage;\n }\n\n if (role === 'user') {\n return new HumanMessage(formattedMessage);\n } else if (role === 'assistant') {\n return new AIMessage(formattedMessage);\n } else {\n return new SystemMessage(formattedMessage);\n }\n};\n\n/**\n * Formats an array of messages for LangChain.\n *\n * @param messages - The array of messages to format.\n * @param formatOptions - The options for formatting each message.\n * @returns - The array of formatted LangChain messages.\n */\nexport const formatLangChainMessages = (\n messages: Array<MessageInput>,\n formatOptions: Omit<FormatMessageParams, 'message' | 'langChain'>\n): Array<HumanMessage | AIMessage | SystemMessage> => {\n return messages.map((msg) => {\n const formatted = formatMessage({\n ...formatOptions,\n message: msg,\n langChain: true,\n });\n return formatted as HumanMessage | AIMessage | SystemMessage;\n });\n};\n\ninterface LangChainMessage {\n lc_kwargs?: {\n additional_kwargs?: Record<string, any>;\n [key: string]: any;\n };\n kwargs?: {\n additional_kwargs?: Record<string, any>;\n [key: string]: any;\n };\n [key: string]: any;\n}\n\n/**\n * Formats a LangChain message object by merging properties from `lc_kwargs` or `kwargs` and `additional_kwargs`.\n *\n * @param message - The message object to format.\n * @returns - The formatted LangChain message.\n */\nexport const formatFromLangChain = (\n message: LangChainMessage\n): Record<string, any> => {\n const kwargs = message.lc_kwargs ?? message.kwargs ?? {};\n const { additional_kwargs = {}, ...message_kwargs } = kwargs;\n return {\n ...message_kwargs,\n ...additional_kwargs,\n };\n};\n\n/**\n * Helper function to format an assistant message\n * @param message The message to format\n * @returns Array of formatted messages\n */\nfunction formatAssistantMessage(\n message: Partial<TMessage>\n): Array<AIMessage | ToolMessage> {\n const formattedMessages: Array<AIMessage | ToolMessage> = [];\n let currentContent: MessageContentComplex[] = [];\n let lastAIMessage: AIMessage | null = null;\n let hasReasoning = false;\n\n if (Array.isArray(message.content)) {\n for (const part of message.content as Array<\n MessageContentComplex | undefined | null\n >) {\n if (part == null) {\n continue;\n }\n if (part.type === ContentTypes.TEXT && part.tool_call_ids) {\n /*\n If there's pending content, it needs to be aggregated as a single string to prepare for tool calls.\n For Anthropic models, the \"tool_calls\" field on a message is only respected if content is a string.\n */\n if (currentContent.length > 0) {\n let content = currentContent.reduce((acc, curr) => {\n if (curr.type === ContentTypes.TEXT) {\n return `${acc}${String(curr[ContentTypes.TEXT] ?? '')}\\n`;\n }\n return acc;\n }, '');\n content =\n `${content}\\n${part[ContentTypes.TEXT] ?? part.text ?? ''}`.trim();\n lastAIMessage = new AIMessage({ content });\n formattedMessages.push(lastAIMessage);\n currentContent = [];\n continue;\n }\n // Create a new AIMessage with this text and prepare for tool calls\n lastAIMessage = new AIMessage({\n content: part.text != null ? part.text : '',\n });\n formattedMessages.push(lastAIMessage);\n } else if (part.type === ContentTypes.TOOL_CALL) {\n // Skip malformed tool call entries without tool_call property\n if (part.tool_call == null) {\n continue;\n }\n\n // Note: `tool_calls` list is defined when constructed by `AIMessage` class, and outputs should be excluded from it\n const {\n output,\n args: _args,\n ..._tool_call\n } = part.tool_call as ToolCallPart;\n\n // Skip invalid tool calls that have no name AND no output\n if (\n _tool_call.name == null ||\n (_tool_call.name === '' && (output == null || output === ''))\n ) {\n continue;\n }\n\n if (!lastAIMessage) {\n // \"Heal\" the payload by creating an AIMessage to precede the tool call\n lastAIMessage = new AIMessage({ content: '' });\n formattedMessages.push(lastAIMessage);\n }\n\n const tool_call: ToolCallPart = _tool_call;\n // TODO: investigate; args as dictionary may need to be providers-or-tool-specific\n let args: any = _args;\n try {\n if (typeof _args === 'string') {\n args = JSON.parse(_args);\n }\n } catch {\n if (typeof _args === 'string') {\n args = { input: _args };\n }\n }\n\n tool_call.args = args;\n if (!lastAIMessage.tool_calls) {\n lastAIMessage.tool_calls = [];\n }\n lastAIMessage.tool_calls.push(tool_call as ToolCall);\n\n formattedMessages.push(\n new ToolMessage({\n tool_call_id: tool_call.id ?? '',\n name: tool_call.name,\n content: output != null ? output : '',\n })\n );\n } else if (part.type === ContentTypes.THINK) {\n hasReasoning = true;\n continue;\n } else if (\n part.type === ContentTypes.ERROR ||\n part.type === ContentTypes.AGENT_UPDATE\n ) {\n continue;\n } else {\n currentContent.push(part);\n }\n }\n }\n\n if (hasReasoning && currentContent.length > 0) {\n const content = currentContent\n .reduce((acc, curr) => {\n if (curr.type === ContentTypes.TEXT) {\n return `${acc}${String(curr[ContentTypes.TEXT] ?? '')}\\n`;\n }\n return acc;\n }, '')\n .trim();\n\n if (content) {\n formattedMessages.push(new AIMessage({ content }));\n }\n } else if (currentContent.length > 0) {\n formattedMessages.push(new AIMessage({ content: currentContent }));\n }\n\n return formattedMessages;\n}\n\n/**\n * Labels all agent content for parallel patterns (fan-out/fan-in)\n * Groups consecutive content by agent and wraps with clear labels\n */\nfunction labelAllAgentContent(\n contentParts: MessageContentComplex[],\n agentIdMap: Record<number, string>,\n agentNames?: Record<string, string>\n): MessageContentComplex[] {\n const result: MessageContentComplex[] = [];\n let currentAgentId: string | undefined;\n let agentContentBuffer: MessageContentComplex[] = [];\n\n const flushAgentBuffer = (): void => {\n if (agentContentBuffer.length === 0) {\n return;\n }\n\n if (currentAgentId != null && currentAgentId !== '') {\n const agentName = (agentNames?.[currentAgentId] ?? '') || currentAgentId;\n const formattedParts: string[] = [];\n\n formattedParts.push(`--- ${agentName} ---`);\n\n for (const part of agentContentBuffer) {\n if (part.type === ContentTypes.THINK) {\n const thinkContent = (part as ReasoningContentText).think || '';\n if (thinkContent) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'think',\n think: thinkContent,\n })}`\n );\n }\n } else if (part.type === ContentTypes.TEXT) {\n const textContent: string = part.text ?? '';\n if (textContent) {\n formattedParts.push(`${agentName}: ${textContent}`);\n }\n } else if (part.type === ContentTypes.TOOL_CALL) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'tool_call',\n tool_call: (part as ToolCallContent).tool_call,\n })}`\n );\n }\n }\n\n formattedParts.push(`--- End of ${agentName} ---`);\n\n // Create a single text content part with all agent content\n result.push({\n type: ContentTypes.TEXT,\n text: formattedParts.join('\\n\\n'),\n } as MessageContentComplex);\n } else {\n // No agent ID, pass through as-is\n result.push(...agentContentBuffer);\n }\n\n agentContentBuffer = [];\n };\n\n for (let i = 0; i < contentParts.length; i++) {\n const part = contentParts[i];\n const agentId = agentIdMap[i];\n\n // If agent changed, flush previous buffer\n if (agentId !== currentAgentId && currentAgentId !== undefined) {\n flushAgentBuffer();\n }\n\n currentAgentId = agentId;\n agentContentBuffer.push(part);\n }\n\n // Flush any remaining content\n flushAgentBuffer();\n\n return result;\n}\n\n/**\n * Groups content parts by agent and formats them with agent labels\n * This preprocesses multi-agent content to prevent identity confusion\n *\n * @param contentParts - The content parts from a run\n * @param agentIdMap - Map of content part index to agent ID\n * @param agentNames - Optional map of agent ID to display name\n * @param options - Configuration options\n * @param options.labelNonTransferContent - If true, labels all agent transitions (for parallel patterns)\n * @returns Modified content parts with agent labels where appropriate\n */\nexport const labelContentByAgent = (\n contentParts: MessageContentComplex[],\n agentIdMap?: Record<number, string>,\n agentNames?: Record<string, string>,\n options?: { labelNonTransferContent?: boolean }\n): MessageContentComplex[] => {\n if (!agentIdMap || Object.keys(agentIdMap).length === 0) {\n return contentParts;\n }\n\n // If labelNonTransferContent is true, use a different strategy for parallel patterns\n if (options?.labelNonTransferContent === true) {\n return labelAllAgentContent(contentParts, agentIdMap, agentNames);\n }\n\n const result: MessageContentComplex[] = [];\n let currentAgentId: string | undefined;\n let agentContentBuffer: MessageContentComplex[] = [];\n let transferToolCallIndex: number | undefined;\n let transferToolCallId: string | undefined;\n\n const flushAgentBuffer = (): void => {\n if (agentContentBuffer.length === 0) {\n return;\n }\n\n // If this is content from a transferred agent, format it specially\n if (\n currentAgentId != null &&\n currentAgentId !== '' &&\n transferToolCallIndex !== undefined\n ) {\n const agentName = (agentNames?.[currentAgentId] ?? '') || currentAgentId;\n const formattedParts: string[] = [];\n\n formattedParts.push(`--- Transfer to ${agentName} ---`);\n\n for (const part of agentContentBuffer) {\n if (part.type === ContentTypes.THINK) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'think',\n think: (part as ReasoningContentText).think,\n })}`\n );\n } else if ('text' in part && part.type === ContentTypes.TEXT) {\n const textContent: string = part.text ?? '';\n if (textContent) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'text',\n text: textContent,\n })}`\n );\n }\n } else if (part.type === ContentTypes.TOOL_CALL) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'tool_call',\n tool_call: (part as ToolCallContent).tool_call,\n })}`\n );\n }\n }\n\n formattedParts.push(`--- End of ${agentName} response ---`);\n\n // Find the tool call that triggered this transfer and update its output\n if (transferToolCallIndex < result.length) {\n const transferToolCall = result[transferToolCallIndex];\n if (\n transferToolCall.type === ContentTypes.TOOL_CALL &&\n transferToolCall.tool_call?.id === transferToolCallId\n ) {\n transferToolCall.tool_call.output = formattedParts.join('\\n\\n');\n }\n }\n } else {\n // Not from a transfer, add as-is\n result.push(...agentContentBuffer);\n }\n\n agentContentBuffer = [];\n transferToolCallIndex = undefined;\n transferToolCallId = undefined;\n };\n\n for (let i = 0; i < contentParts.length; i++) {\n const part = contentParts[i];\n const agentId = agentIdMap[i];\n\n // Check if this is a transfer tool call\n const isTransferTool =\n (part.type === ContentTypes.TOOL_CALL &&\n (part as ToolCallContent).tool_call?.name?.startsWith(\n 'lc_transfer_to_'\n )) ??\n false;\n\n // If agent changed, flush previous buffer\n if (agentId !== currentAgentId && currentAgentId !== undefined) {\n flushAgentBuffer();\n }\n\n currentAgentId = agentId;\n\n if (isTransferTool) {\n // Flush any existing buffer first\n flushAgentBuffer();\n // Add the transfer tool call to result\n result.push(part);\n // Mark that the next agent's content should be captured\n transferToolCallIndex = result.length - 1;\n transferToolCallId = (part as ToolCallContent).tool_call?.id;\n currentAgentId = undefined; // Reset to capture the next agent\n } else {\n agentContentBuffer.push(part);\n }\n }\n\n flushAgentBuffer();\n\n return result;\n};\n\n/** Extracts tool names from a tool_search output JSON string. */\nfunction extractToolNamesFromSearchOutput(output: string): string[] {\n try {\n const parsed: unknown = JSON.parse(output);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n Array.isArray((parsed as Record<string, unknown>).tools)\n ) {\n return (\n (parsed as Record<string, unknown>).tools as Array<{ name?: string }>\n )\n .map((t) => t.name)\n .filter((name): name is string => typeof name === 'string');\n }\n } catch {\n /** Output may have warnings prepended, try to find JSON within it */\n const jsonMatch = output.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n try {\n const parsed: unknown = JSON.parse(jsonMatch[0]);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n Array.isArray((parsed as Record<string, unknown>).tools)\n ) {\n return (\n (parsed as Record<string, unknown>).tools as Array<{\n name?: string;\n }>\n )\n .map((t) => t.name)\n .filter((name): name is string => typeof name === 'string');\n }\n } catch {\n /* ignore */\n }\n }\n }\n return [];\n}\n\n/**\n * Formats an array of messages for LangChain, handling tool calls and creating ToolMessage instances.\n *\n * @param payload - The array of messages to format.\n * @param indexTokenCountMap - Optional map of message indices to token counts.\n * @param tools - Optional set of tool names that are allowed in the request.\n * @returns - Object containing formatted messages and updated indexTokenCountMap if provided.\n */\nexport const formatAgentMessages = (\n payload: TPayload,\n indexTokenCountMap?: Record<number, number | undefined>,\n tools?: Set<string>\n): {\n messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;\n indexTokenCountMap?: Record<number, number>;\n} => {\n const messages: Array<\n HumanMessage | AIMessage | SystemMessage | ToolMessage\n > = [];\n // If indexTokenCountMap is provided, create a new map to track the updated indices\n const updatedIndexTokenCountMap: Record<number, number> = {};\n // Keep track of the mapping from original payload indices to result indices\n const indexMapping: Record<number, number[] | undefined> = {};\n\n /**\n * Create a mutable copy of the tools set that can be expanded dynamically.\n * When we encounter tool_search results, we add discovered tools to this set,\n * making their subsequent tool calls valid.\n */\n const discoveredTools = tools ? new Set(tools) : undefined;\n\n // Process messages with tool conversion if tools set is provided\n for (let i = 0; i < payload.length; i++) {\n const message = payload[i];\n // Q: Store the current length of messages to track where this payload message starts in the result?\n // const startIndex = messages.length;\n if (typeof message.content === 'string') {\n message.content = [\n { type: ContentTypes.TEXT, [ContentTypes.TEXT]: message.content },\n ];\n }\n if (message.role !== 'assistant') {\n messages.push(\n formatMessage({\n message: message as MessageInput,\n langChain: true,\n }) as HumanMessage | AIMessage | SystemMessage\n );\n\n // Update the index mapping for this message\n indexMapping[i] = [messages.length - 1];\n continue;\n }\n\n // For assistant messages, track the starting index before processing\n const startMessageIndex = messages.length;\n\n /**\n * If tools set is provided, process tool_calls:\n * - Keep valid tool_calls (tools in the set or dynamically discovered)\n * - Convert invalid tool_calls to string representation for context preservation\n * - Dynamically expand the set when tool_search results are encountered\n */\n let processedMessage = message;\n if (discoveredTools) {\n const content = message.content;\n if (content && Array.isArray(content)) {\n const filteredContent: typeof content = [];\n const invalidToolCallIds = new Set<string>();\n const invalidToolStrings: string[] = [];\n\n for (const part of content) {\n if (part.type !== ContentTypes.TOOL_CALL) {\n filteredContent.push(part);\n continue;\n }\n\n /** Skip malformed tool_call entries */\n if (\n part.tool_call == null ||\n part.tool_call.name == null ||\n part.tool_call.name === ''\n ) {\n if (\n typeof part.tool_call?.id === 'string' &&\n part.tool_call.id !== ''\n ) {\n invalidToolCallIds.add(part.tool_call.id);\n }\n continue;\n }\n\n const toolName = part.tool_call.name;\n\n /**\n * If this is a tool_search result with output, extract discovered tool names\n * and add them to the discoveredTools set for subsequent validation.\n */\n if (\n toolName === Constants.TOOL_SEARCH &&\n typeof part.tool_call.output === 'string' &&\n part.tool_call.output !== ''\n ) {\n const extracted = extractToolNamesFromSearchOutput(\n part.tool_call.output\n );\n for (const name of extracted) {\n discoveredTools.add(name);\n }\n }\n\n if (discoveredTools.has(toolName)) {\n /** Valid tool - keep it */\n filteredContent.push(part);\n } else {\n /** Invalid tool - convert to string for context preservation */\n if (\n typeof part.tool_call.id === 'string' &&\n part.tool_call.id !== ''\n ) {\n invalidToolCallIds.add(part.tool_call.id);\n }\n const output = part.tool_call.output ?? '';\n invalidToolStrings.push(`Tool: ${toolName}, ${output}`);\n }\n }\n\n /** Remove tool_call_ids references to invalid tools from text parts */\n if (invalidToolCallIds.size > 0) {\n for (const part of filteredContent) {\n if (\n part.type === ContentTypes.TEXT &&\n Array.isArray(part.tool_call_ids)\n ) {\n part.tool_call_ids = part.tool_call_ids.filter(\n (id: string) => !invalidToolCallIds.has(id)\n );\n if (part.tool_call_ids.length === 0) {\n delete part.tool_call_ids;\n }\n }\n }\n }\n\n /** Append invalid tool strings to the content for context preservation */\n if (invalidToolStrings.length > 0) {\n /** Find the last text part or create one */\n let lastTextPartIndex = -1;\n for (let j = filteredContent.length - 1; j >= 0; j--) {\n if (filteredContent[j].type === ContentTypes.TEXT) {\n lastTextPartIndex = j;\n break;\n }\n }\n\n const invalidToolText = invalidToolStrings.join('\\n');\n if (lastTextPartIndex >= 0) {\n const lastTextPart = filteredContent[lastTextPartIndex] as {\n type: string;\n [ContentTypes.TEXT]?: string;\n text?: string;\n };\n const existingText =\n lastTextPart[ContentTypes.TEXT] ?? lastTextPart.text ?? '';\n filteredContent[lastTextPartIndex] = {\n ...lastTextPart,\n [ContentTypes.TEXT]: existingText\n ? `${existingText}\\n${invalidToolText}`\n : invalidToolText,\n };\n } else {\n /** No text part exists, create one */\n filteredContent.push({\n type: ContentTypes.TEXT,\n [ContentTypes.TEXT]: invalidToolText,\n });\n }\n }\n\n /** Use filtered content if we made any changes */\n if (\n filteredContent.length !== content.length ||\n invalidToolStrings.length > 0\n ) {\n processedMessage = { ...message, content: filteredContent };\n }\n }\n }\n\n // Process the assistant message using the helper function\n const formattedMessages = formatAssistantMessage(processedMessage);\n messages.push(...formattedMessages);\n\n // Update the index mapping for this assistant message\n // Store all indices that were created from this original message\n const endMessageIndex = messages.length;\n const resultIndices = [];\n for (let j = startMessageIndex; j < endMessageIndex; j++) {\n resultIndices.push(j);\n }\n indexMapping[i] = resultIndices;\n }\n\n if (indexTokenCountMap) {\n for (\n let originalIndex = 0;\n originalIndex < payload.length;\n originalIndex++\n ) {\n const resultIndices = indexMapping[originalIndex] || [];\n const tokenCount = indexTokenCountMap[originalIndex];\n\n if (tokenCount === undefined) {\n continue;\n }\n\n const msgCount = resultIndices.length;\n if (msgCount === 1) {\n updatedIndexTokenCountMap[resultIndices[0]] = tokenCount;\n continue;\n }\n\n if (msgCount < 2) {\n continue;\n }\n\n let totalLength = 0;\n const lastIdx = msgCount - 1;\n const lengths = new Array<number>(msgCount);\n for (let k = 0; k < msgCount; k++) {\n const msg = messages[resultIndices[k]];\n const { content } = msg;\n let len = 0;\n if (typeof content === 'string') {\n len = content.length;\n } else if (Array.isArray(content)) {\n for (const part of content as Array<\n Record<string, unknown> | string | undefined\n >) {\n if (typeof part === 'string') {\n len += part.length;\n } else if (part != null && typeof part === 'object') {\n const val = part.text ?? part.content;\n if (typeof val === 'string') {\n len += val.length;\n }\n }\n }\n }\n const toolCalls = (msg as AIMessage).tool_calls;\n if (Array.isArray(toolCalls)) {\n for (const tc of toolCalls as Array<Record<string, unknown>>) {\n if (typeof tc.name === 'string') {\n len += tc.name.length;\n }\n const { args } = tc;\n if (typeof args === 'string') {\n len += args.length;\n } else if (args != null) {\n len += JSON.stringify(args).length;\n }\n }\n }\n lengths[k] = len;\n totalLength += len;\n }\n\n if (totalLength === 0) {\n const countPerMessage = Math.floor(tokenCount / msgCount);\n for (let k = 0; k < lastIdx; k++) {\n updatedIndexTokenCountMap[resultIndices[k]] = countPerMessage;\n }\n updatedIndexTokenCountMap[resultIndices[lastIdx]] =\n tokenCount - countPerMessage * lastIdx;\n } else {\n let distributed = 0;\n for (let k = 0; k < lastIdx; k++) {\n const share = Math.floor((lengths[k] / totalLength) * tokenCount);\n updatedIndexTokenCountMap[resultIndices[k]] = share;\n distributed += share;\n }\n updatedIndexTokenCountMap[resultIndices[lastIdx]] =\n tokenCount - distributed;\n }\n }\n }\n\n return {\n messages,\n indexTokenCountMap: indexTokenCountMap\n ? updatedIndexTokenCountMap\n : undefined,\n };\n};\n\n/**\n * Adds a value at key 0 for system messages and shifts all key indices by one in an indexTokenCountMap.\n * This is useful when adding a system message at the beginning of a conversation.\n *\n * @param indexTokenCountMap - The original map of message indices to token counts\n * @param instructionsTokenCount - The token count for the system message to add at index 0\n * @returns A new map with the system message at index 0 and all other indices shifted by 1\n */\nexport function shiftIndexTokenCountMap(\n indexTokenCountMap: Record<number, number>,\n instructionsTokenCount: number\n): Record<number, number> {\n // Create a new map to avoid modifying the original\n const shiftedMap: Record<number, number> = {};\n shiftedMap[0] = instructionsTokenCount;\n\n // Shift all existing indices by 1\n for (const [indexStr, tokenCount] of Object.entries(indexTokenCountMap)) {\n const index = Number(indexStr);\n shiftedMap[index + 1] = tokenCount;\n }\n\n return shiftedMap;\n}\n\n/**\n * Ensures compatibility when switching from a non-thinking agent to a thinking-enabled agent.\n * Converts AI messages with tool calls (that lack thinking/reasoning blocks) into buffer strings,\n * avoiding the thinking block signature requirement.\n *\n * Recognizes the following as valid thinking/reasoning blocks:\n * - ContentTypes.THINKING (Anthropic)\n * - ContentTypes.REASONING_CONTENT (Bedrock)\n * - ContentTypes.REASONING (VertexAI / Google)\n * - 'redacted_thinking'\n *\n * @param messages - Array of messages to process\n * @param provider - The provider being used (unused but kept for future compatibility)\n * @returns The messages array with tool sequences converted to buffer strings if necessary\n */\nexport function ensureThinkingBlockInMessages(\n messages: BaseMessage[],\n _provider: Providers\n): BaseMessage[] {\n const result: BaseMessage[] = [];\n let i = 0;\n\n while (i < messages.length) {\n const msg = messages[i];\n const isAI = msg instanceof AIMessage || msg instanceof AIMessageChunk;\n\n if (!isAI) {\n result.push(msg);\n i++;\n continue;\n }\n\n const aiMsg = msg as AIMessage | AIMessageChunk;\n const hasToolCalls = aiMsg.tool_calls && aiMsg.tool_calls.length > 0;\n const contentIsArray = Array.isArray(aiMsg.content);\n\n // Check if the message has tool calls or tool_use content\n let hasToolUse = hasToolCalls ?? false;\n let firstContentType: string | undefined;\n\n if (contentIsArray && aiMsg.content.length > 0) {\n const content = aiMsg.content as ExtendedMessageContent[];\n firstContentType = content[0]?.type;\n hasToolUse =\n hasToolUse ||\n content.some((c) => typeof c === 'object' && c.type === 'tool_use');\n }\n\n // If message has tool use but no thinking block, convert to buffer string\n if (\n hasToolUse &&\n firstContentType !== ContentTypes.THINKING &&\n firstContentType !== ContentTypes.REASONING_CONTENT &&\n firstContentType !== ContentTypes.REASONING &&\n firstContentType !== 'redacted_thinking'\n ) {\n // Collect the AI message and any following tool messages\n const toolSequence: BaseMessage[] = [msg];\n let j = i + 1;\n\n // Look ahead for tool messages that belong to this AI message\n while (j < messages.length && messages[j] instanceof ToolMessage) {\n toolSequence.push(messages[j]);\n j++;\n }\n\n // Convert the sequence to a buffer string and wrap in a HumanMessage\n // This avoids the thinking block requirement which only applies to AI messages\n const bufferString = getBufferString(toolSequence);\n result.push(\n new HumanMessage({\n content: `[Previous agent context]\\n${bufferString}`,\n })\n );\n\n // Skip the messages we've processed\n i = j;\n } else {\n // Keep the message as is\n result.push(msg);\n i++;\n }\n }\n\n return result;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"format.mjs","sources":["../../../src/messages/format.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n AIMessage,\n AIMessageChunk,\n ToolMessage,\n BaseMessage,\n HumanMessage,\n SystemMessage,\n getBufferString,\n} from '@langchain/core/messages';\nimport type { MessageContentImageUrl } from '@langchain/core/messages';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type {\n ExtendedMessageContent,\n MessageContentComplex,\n ReasoningContentText,\n ToolCallContent,\n ToolCallPart,\n TPayload,\n TMessage,\n} from '@/types';\nimport { Providers, ContentTypes, Constants } from '@/common';\n\ninterface MediaMessageParams {\n message: {\n role: string;\n content: string;\n name?: string;\n [key: string]: any;\n };\n mediaParts: MessageContentComplex[];\n endpoint?: Providers;\n}\n\n/**\n * Formats a message with media content (images, documents, videos, audios) to API payload format.\n *\n * @param params - The parameters for formatting.\n * @returns - The formatted message.\n */\nexport const formatMediaMessage = ({\n message,\n endpoint,\n mediaParts,\n}: MediaMessageParams): {\n role: string;\n content: MessageContentComplex[];\n name?: string;\n [key: string]: any;\n} => {\n // Create a new object to avoid mutating the input\n const result: {\n role: string;\n content: MessageContentComplex[];\n name?: string;\n [key: string]: any;\n } = {\n ...message,\n content: [] as MessageContentComplex[],\n };\n\n if (endpoint === Providers.ANTHROPIC) {\n result.content = [\n ...mediaParts,\n { type: ContentTypes.TEXT, text: message.content },\n ] as MessageContentComplex[];\n return result;\n }\n\n result.content = [\n { type: ContentTypes.TEXT, text: message.content },\n ...mediaParts,\n ] as MessageContentComplex[];\n\n return result;\n};\n\ninterface MessageInput {\n role?: string;\n _name?: string;\n sender?: string;\n text?: string;\n content?: string | MessageContentComplex[];\n image_urls?: MessageContentImageUrl[];\n documents?: MessageContentComplex[];\n videos?: MessageContentComplex[];\n audios?: MessageContentComplex[];\n lc_id?: string[];\n [key: string]: any;\n}\n\ninterface FormatMessageParams {\n message: MessageInput;\n userName?: string;\n assistantName?: string;\n endpoint?: Providers;\n langChain?: boolean;\n}\n\ninterface FormattedMessage {\n role: string;\n content: string | MessageContentComplex[];\n name?: string;\n [key: string]: any;\n}\n\n/**\n * Formats a message to OpenAI payload format based on the provided options.\n *\n * @param params - The parameters for formatting.\n * @returns - The formatted message.\n */\nexport const formatMessage = ({\n message,\n userName,\n endpoint,\n assistantName,\n langChain = false,\n}: FormatMessageParams):\n | FormattedMessage\n | HumanMessage\n | AIMessage\n | SystemMessage => {\n // eslint-disable-next-line prefer-const\n let { role: _role, _name, sender, text, content: _content, lc_id } = message;\n if (lc_id && lc_id[2] && !langChain) {\n const roleMapping: Record<string, string> = {\n SystemMessage: 'system',\n HumanMessage: 'user',\n AIMessage: 'assistant',\n };\n _role = roleMapping[lc_id[2]] || _role;\n }\n const role =\n _role ??\n (sender != null && sender && sender.toLowerCase() === 'user'\n ? 'user'\n : 'assistant');\n const content = _content ?? text ?? '';\n const formattedMessage: FormattedMessage = {\n role,\n content,\n };\n\n // Set name fields first\n if (_name != null && _name) {\n formattedMessage.name = _name;\n }\n\n if (userName != null && userName && formattedMessage.role === 'user') {\n formattedMessage.name = userName;\n }\n\n if (\n assistantName != null &&\n assistantName &&\n formattedMessage.role === 'assistant'\n ) {\n formattedMessage.name = assistantName;\n }\n\n if (formattedMessage.name != null && formattedMessage.name) {\n // Conform to API regex: ^[a-zA-Z0-9_-]{1,64}$\n // https://community.openai.com/t/the-format-of-the-name-field-in-the-documentation-is-incorrect/175684/2\n formattedMessage.name = formattedMessage.name.replace(\n /[^a-zA-Z0-9_-]/g,\n '_'\n );\n\n if (formattedMessage.name.length > 64) {\n formattedMessage.name = formattedMessage.name.substring(0, 64);\n }\n }\n\n const { image_urls, documents, videos, audios } = message;\n const mediaParts: MessageContentComplex[] = [];\n\n if (Array.isArray(documents) && documents.length > 0) {\n mediaParts.push(...documents);\n }\n\n if (Array.isArray(videos) && videos.length > 0) {\n mediaParts.push(...videos);\n }\n\n if (Array.isArray(audios) && audios.length > 0) {\n mediaParts.push(...audios);\n }\n\n if (Array.isArray(image_urls) && image_urls.length > 0) {\n mediaParts.push(...image_urls);\n }\n\n if (mediaParts.length > 0 && role === 'user') {\n const mediaMessage = formatMediaMessage({\n message: {\n ...formattedMessage,\n content:\n typeof formattedMessage.content === 'string'\n ? formattedMessage.content\n : '',\n },\n mediaParts,\n endpoint,\n });\n\n if (!langChain) {\n return mediaMessage;\n }\n\n return new HumanMessage(mediaMessage);\n }\n\n if (!langChain) {\n return formattedMessage;\n }\n\n if (role === 'user') {\n return new HumanMessage(formattedMessage);\n } else if (role === 'assistant') {\n return new AIMessage(formattedMessage);\n } else {\n return new SystemMessage(formattedMessage);\n }\n};\n\n/**\n * Formats an array of messages for LangChain.\n *\n * @param messages - The array of messages to format.\n * @param formatOptions - The options for formatting each message.\n * @returns - The array of formatted LangChain messages.\n */\nexport const formatLangChainMessages = (\n messages: Array<MessageInput>,\n formatOptions: Omit<FormatMessageParams, 'message' | 'langChain'>\n): Array<HumanMessage | AIMessage | SystemMessage> => {\n return messages.map((msg) => {\n const formatted = formatMessage({\n ...formatOptions,\n message: msg,\n langChain: true,\n });\n return formatted as HumanMessage | AIMessage | SystemMessage;\n });\n};\n\ninterface LangChainMessage {\n lc_kwargs?: {\n additional_kwargs?: Record<string, any>;\n [key: string]: any;\n };\n kwargs?: {\n additional_kwargs?: Record<string, any>;\n [key: string]: any;\n };\n [key: string]: any;\n}\n\n/**\n * Formats a LangChain message object by merging properties from `lc_kwargs` or `kwargs` and `additional_kwargs`.\n *\n * @param message - The message object to format.\n * @returns - The formatted LangChain message.\n */\nexport const formatFromLangChain = (\n message: LangChainMessage\n): Record<string, any> => {\n const kwargs = message.lc_kwargs ?? message.kwargs ?? {};\n const { additional_kwargs = {}, ...message_kwargs } = kwargs;\n return {\n ...message_kwargs,\n ...additional_kwargs,\n };\n};\n\n/**\n * Helper function to format an assistant message\n * @param message The message to format\n * @returns Array of formatted messages\n */\nfunction formatAssistantMessage(\n message: Partial<TMessage>\n): Array<AIMessage | ToolMessage> {\n const formattedMessages: Array<AIMessage | ToolMessage> = [];\n let currentContent: MessageContentComplex[] = [];\n let lastAIMessage: AIMessage | null = null;\n let hasReasoning = false;\n\n if (Array.isArray(message.content)) {\n for (const part of message.content as Array<\n MessageContentComplex | undefined | null\n >) {\n if (part == null) {\n continue;\n }\n if (part.type === ContentTypes.TEXT && part.tool_call_ids) {\n /*\n If there's pending content, it needs to be aggregated as a single string to prepare for tool calls.\n For Anthropic models, the \"tool_calls\" field on a message is only respected if content is a string.\n */\n if (currentContent.length > 0) {\n let content = currentContent.reduce((acc, curr) => {\n if (curr.type === ContentTypes.TEXT) {\n return `${acc}${String(curr[ContentTypes.TEXT] ?? '')}\\n`;\n }\n return acc;\n }, '');\n content =\n `${content}\\n${part[ContentTypes.TEXT] ?? part.text ?? ''}`.trim();\n lastAIMessage = new AIMessage({ content });\n formattedMessages.push(lastAIMessage);\n currentContent = [];\n continue;\n }\n // Create a new AIMessage with this text and prepare for tool calls\n lastAIMessage = new AIMessage({\n content: part.text != null ? part.text : '',\n });\n formattedMessages.push(lastAIMessage);\n } else if (part.type === ContentTypes.TOOL_CALL) {\n // Skip malformed tool call entries without tool_call property\n if (part.tool_call == null) {\n continue;\n }\n\n // Note: `tool_calls` list is defined when constructed by `AIMessage` class, and outputs should be excluded from it\n const {\n output,\n args: _args,\n ..._tool_call\n } = part.tool_call as ToolCallPart;\n\n // Skip invalid tool calls that have no name AND no output\n if (\n _tool_call.name == null ||\n (_tool_call.name === '' && (output == null || output === ''))\n ) {\n continue;\n }\n\n if (!lastAIMessage) {\n // \"Heal\" the payload by creating an AIMessage to precede the tool call\n lastAIMessage = new AIMessage({ content: '' });\n formattedMessages.push(lastAIMessage);\n }\n\n const tool_call: ToolCallPart = _tool_call;\n // TODO: investigate; args as dictionary may need to be providers-or-tool-specific\n let args: any = _args;\n try {\n if (typeof _args === 'string') {\n args = JSON.parse(_args);\n }\n } catch {\n if (typeof _args === 'string') {\n args = { input: _args };\n }\n }\n\n tool_call.args = args;\n if (!lastAIMessage.tool_calls) {\n lastAIMessage.tool_calls = [];\n }\n lastAIMessage.tool_calls.push(tool_call as ToolCall);\n\n formattedMessages.push(\n new ToolMessage({\n tool_call_id: tool_call.id ?? '',\n name: tool_call.name,\n content: output != null ? output : '',\n })\n );\n } else if (part.type === ContentTypes.THINK) {\n hasReasoning = true;\n continue;\n } else if (\n part.type === ContentTypes.ERROR ||\n part.type === ContentTypes.AGENT_UPDATE\n ) {\n continue;\n } else {\n currentContent.push(part);\n }\n }\n }\n\n if (hasReasoning && currentContent.length > 0) {\n const content = currentContent\n .reduce((acc, curr) => {\n if (curr.type === ContentTypes.TEXT) {\n return `${acc}${String(curr[ContentTypes.TEXT] ?? '')}\\n`;\n }\n return acc;\n }, '')\n .trim();\n\n if (content) {\n formattedMessages.push(new AIMessage({ content }));\n }\n } else if (currentContent.length > 0) {\n formattedMessages.push(new AIMessage({ content: currentContent }));\n }\n\n return formattedMessages;\n}\n\n/**\n * Labels all agent content for parallel patterns (fan-out/fan-in)\n * Groups consecutive content by agent and wraps with clear labels\n */\nfunction labelAllAgentContent(\n contentParts: MessageContentComplex[],\n agentIdMap: Record<number, string>,\n agentNames?: Record<string, string>\n): MessageContentComplex[] {\n const result: MessageContentComplex[] = [];\n let currentAgentId: string | undefined;\n let agentContentBuffer: MessageContentComplex[] = [];\n\n const flushAgentBuffer = (): void => {\n if (agentContentBuffer.length === 0) {\n return;\n }\n\n if (currentAgentId != null && currentAgentId !== '') {\n const agentName = (agentNames?.[currentAgentId] ?? '') || currentAgentId;\n const formattedParts: string[] = [];\n\n formattedParts.push(`--- ${agentName} ---`);\n\n for (const part of agentContentBuffer) {\n if (part.type === ContentTypes.THINK) {\n const thinkContent = (part as ReasoningContentText).think || '';\n if (thinkContent) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'think',\n think: thinkContent,\n })}`\n );\n }\n } else if (part.type === ContentTypes.TEXT) {\n const textContent: string = part.text ?? '';\n if (textContent) {\n formattedParts.push(`${agentName}: ${textContent}`);\n }\n } else if (part.type === ContentTypes.TOOL_CALL) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'tool_call',\n tool_call: (part as ToolCallContent).tool_call,\n })}`\n );\n }\n }\n\n formattedParts.push(`--- End of ${agentName} ---`);\n\n // Create a single text content part with all agent content\n result.push({\n type: ContentTypes.TEXT,\n text: formattedParts.join('\\n\\n'),\n } as MessageContentComplex);\n } else {\n // No agent ID, pass through as-is\n result.push(...agentContentBuffer);\n }\n\n agentContentBuffer = [];\n };\n\n for (let i = 0; i < contentParts.length; i++) {\n const part = contentParts[i];\n const agentId = agentIdMap[i];\n\n // If agent changed, flush previous buffer\n if (agentId !== currentAgentId && currentAgentId !== undefined) {\n flushAgentBuffer();\n }\n\n currentAgentId = agentId;\n agentContentBuffer.push(part);\n }\n\n // Flush any remaining content\n flushAgentBuffer();\n\n return result;\n}\n\n/**\n * Groups content parts by agent and formats them with agent labels\n * This preprocesses multi-agent content to prevent identity confusion\n *\n * @param contentParts - The content parts from a run\n * @param agentIdMap - Map of content part index to agent ID\n * @param agentNames - Optional map of agent ID to display name\n * @param options - Configuration options\n * @param options.labelNonTransferContent - If true, labels all agent transitions (for parallel patterns)\n * @returns Modified content parts with agent labels where appropriate\n */\nexport const labelContentByAgent = (\n contentParts: MessageContentComplex[],\n agentIdMap?: Record<number, string>,\n agentNames?: Record<string, string>,\n options?: { labelNonTransferContent?: boolean }\n): MessageContentComplex[] => {\n if (!agentIdMap || Object.keys(agentIdMap).length === 0) {\n return contentParts;\n }\n\n // If labelNonTransferContent is true, use a different strategy for parallel patterns\n if (options?.labelNonTransferContent === true) {\n return labelAllAgentContent(contentParts, agentIdMap, agentNames);\n }\n\n const result: MessageContentComplex[] = [];\n let currentAgentId: string | undefined;\n let agentContentBuffer: MessageContentComplex[] = [];\n let transferToolCallIndex: number | undefined;\n let transferToolCallId: string | undefined;\n\n const flushAgentBuffer = (): void => {\n if (agentContentBuffer.length === 0) {\n return;\n }\n\n // If this is content from a transferred agent, format it specially\n if (\n currentAgentId != null &&\n currentAgentId !== '' &&\n transferToolCallIndex !== undefined\n ) {\n const agentName = (agentNames?.[currentAgentId] ?? '') || currentAgentId;\n const formattedParts: string[] = [];\n\n formattedParts.push(`--- Transfer to ${agentName} ---`);\n\n for (const part of agentContentBuffer) {\n if (part.type === ContentTypes.THINK) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'think',\n think: (part as ReasoningContentText).think,\n })}`\n );\n } else if ('text' in part && part.type === ContentTypes.TEXT) {\n const textContent: string = part.text ?? '';\n if (textContent) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'text',\n text: textContent,\n })}`\n );\n }\n } else if (part.type === ContentTypes.TOOL_CALL) {\n formattedParts.push(\n `${agentName}: ${JSON.stringify({\n type: 'tool_call',\n tool_call: (part as ToolCallContent).tool_call,\n })}`\n );\n }\n }\n\n formattedParts.push(`--- End of ${agentName} response ---`);\n\n // Find the tool call that triggered this transfer and update its output\n if (transferToolCallIndex < result.length) {\n const transferToolCall = result[transferToolCallIndex];\n if (\n transferToolCall.type === ContentTypes.TOOL_CALL &&\n transferToolCall.tool_call?.id === transferToolCallId\n ) {\n transferToolCall.tool_call.output = formattedParts.join('\\n\\n');\n }\n }\n } else {\n // Not from a transfer, add as-is\n result.push(...agentContentBuffer);\n }\n\n agentContentBuffer = [];\n transferToolCallIndex = undefined;\n transferToolCallId = undefined;\n };\n\n for (let i = 0; i < contentParts.length; i++) {\n const part = contentParts[i];\n const agentId = agentIdMap[i];\n\n // Check if this is a transfer tool call\n const isTransferTool =\n (part.type === ContentTypes.TOOL_CALL &&\n (part as ToolCallContent).tool_call?.name?.startsWith(\n 'lc_transfer_to_'\n )) ??\n false;\n\n // If agent changed, flush previous buffer\n if (agentId !== currentAgentId && currentAgentId !== undefined) {\n flushAgentBuffer();\n }\n\n currentAgentId = agentId;\n\n if (isTransferTool) {\n // Flush any existing buffer first\n flushAgentBuffer();\n // Add the transfer tool call to result\n result.push(part);\n // Mark that the next agent's content should be captured\n transferToolCallIndex = result.length - 1;\n transferToolCallId = (part as ToolCallContent).tool_call?.id;\n currentAgentId = undefined; // Reset to capture the next agent\n } else {\n agentContentBuffer.push(part);\n }\n }\n\n flushAgentBuffer();\n\n return result;\n};\n\n/** Extracts tool names from a tool_search output JSON string. */\nfunction extractToolNamesFromSearchOutput(output: string): string[] {\n try {\n const parsed: unknown = JSON.parse(output);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n Array.isArray((parsed as Record<string, unknown>).tools)\n ) {\n return (\n (parsed as Record<string, unknown>).tools as Array<{ name?: string }>\n )\n .map((t) => t.name)\n .filter((name): name is string => typeof name === 'string');\n }\n } catch {\n /** Output may have warnings prepended, try to find JSON within it */\n const jsonMatch = output.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n try {\n const parsed: unknown = JSON.parse(jsonMatch[0]);\n if (\n typeof parsed === 'object' &&\n parsed !== null &&\n Array.isArray((parsed as Record<string, unknown>).tools)\n ) {\n return (\n (parsed as Record<string, unknown>).tools as Array<{\n name?: string;\n }>\n )\n .map((t) => t.name)\n .filter((name): name is string => typeof name === 'string');\n }\n } catch {\n /* ignore */\n }\n }\n }\n return [];\n}\n\n/**\n * Formats an array of messages for LangChain, handling tool calls and creating ToolMessage instances.\n *\n * @param payload - The array of messages to format.\n * @param indexTokenCountMap - Optional map of message indices to token counts.\n * @param tools - Optional set of tool names that are allowed in the request.\n * @returns - Object containing formatted messages and updated indexTokenCountMap if provided.\n */\nexport const formatAgentMessages = (\n payload: TPayload,\n indexTokenCountMap?: Record<number, number | undefined>,\n tools?: Set<string>\n): {\n messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;\n indexTokenCountMap?: Record<number, number>;\n} => {\n const messages: Array<\n HumanMessage | AIMessage | SystemMessage | ToolMessage\n > = [];\n // If indexTokenCountMap is provided, create a new map to track the updated indices\n const updatedIndexTokenCountMap: Record<number, number> = {};\n // Keep track of the mapping from original payload indices to result indices\n const indexMapping: Record<number, number[] | undefined> = {};\n\n /**\n * Create a mutable copy of the tools set that can be expanded dynamically.\n * When we encounter tool_search results, we add discovered tools to this set,\n * making their subsequent tool calls valid.\n */\n const discoveredTools = tools ? new Set(tools) : undefined;\n\n // Process messages with tool conversion if tools set is provided\n for (let i = 0; i < payload.length; i++) {\n const message = payload[i];\n // Q: Store the current length of messages to track where this payload message starts in the result?\n // const startIndex = messages.length;\n if (typeof message.content === 'string') {\n message.content = [\n { type: ContentTypes.TEXT, [ContentTypes.TEXT]: message.content },\n ];\n }\n if (message.role !== 'assistant') {\n messages.push(\n formatMessage({\n message: message as MessageInput,\n langChain: true,\n }) as HumanMessage | AIMessage | SystemMessage\n );\n\n // Update the index mapping for this message\n indexMapping[i] = [messages.length - 1];\n continue;\n }\n\n // For assistant messages, track the starting index before processing\n const startMessageIndex = messages.length;\n\n /**\n * If tools set is provided, process tool_calls:\n * - Keep valid tool_calls (tools in the set or dynamically discovered)\n * - Convert invalid tool_calls to string representation for context preservation\n * - Dynamically expand the set when tool_search results are encountered\n */\n let processedMessage = message;\n if (discoveredTools) {\n const content = message.content;\n if (content && Array.isArray(content)) {\n const filteredContent: typeof content = [];\n const invalidToolCallIds = new Set<string>();\n const invalidToolStrings: string[] = [];\n\n for (const part of content) {\n if (part.type !== ContentTypes.TOOL_CALL) {\n filteredContent.push(part);\n continue;\n }\n\n /** Skip malformed tool_call entries */\n if (\n part.tool_call == null ||\n part.tool_call.name == null ||\n part.tool_call.name === ''\n ) {\n if (\n typeof part.tool_call?.id === 'string' &&\n part.tool_call.id !== ''\n ) {\n invalidToolCallIds.add(part.tool_call.id);\n }\n continue;\n }\n\n const toolName = part.tool_call.name;\n\n /**\n * If this is a tool_search result with output, extract discovered tool names\n * and add them to the discoveredTools set for subsequent validation.\n */\n if (\n toolName === Constants.TOOL_SEARCH &&\n typeof part.tool_call.output === 'string' &&\n part.tool_call.output !== ''\n ) {\n const extracted = extractToolNamesFromSearchOutput(\n part.tool_call.output\n );\n for (const name of extracted) {\n discoveredTools.add(name);\n }\n }\n\n if (discoveredTools.has(toolName)) {\n /** Valid tool - keep it */\n filteredContent.push(part);\n } else {\n /** Invalid tool - convert to string for context preservation */\n if (\n typeof part.tool_call.id === 'string' &&\n part.tool_call.id !== ''\n ) {\n invalidToolCallIds.add(part.tool_call.id);\n }\n const output = part.tool_call.output ?? '';\n invalidToolStrings.push(`Tool: ${toolName}, ${output}`);\n }\n }\n\n /** Remove tool_call_ids references to invalid tools from text parts */\n if (invalidToolCallIds.size > 0) {\n for (const part of filteredContent) {\n if (\n part.type === ContentTypes.TEXT &&\n Array.isArray(part.tool_call_ids)\n ) {\n part.tool_call_ids = part.tool_call_ids.filter(\n (id: string) => !invalidToolCallIds.has(id)\n );\n if (part.tool_call_ids.length === 0) {\n delete part.tool_call_ids;\n }\n }\n }\n }\n\n /** Append invalid tool strings to the content for context preservation */\n if (invalidToolStrings.length > 0) {\n /** Find the last text part or create one */\n let lastTextPartIndex = -1;\n for (let j = filteredContent.length - 1; j >= 0; j--) {\n if (filteredContent[j].type === ContentTypes.TEXT) {\n lastTextPartIndex = j;\n break;\n }\n }\n\n const invalidToolText = invalidToolStrings.join('\\n');\n if (lastTextPartIndex >= 0) {\n const lastTextPart = filteredContent[lastTextPartIndex] as {\n type: string;\n [ContentTypes.TEXT]?: string;\n text?: string;\n };\n const existingText =\n lastTextPart[ContentTypes.TEXT] ?? lastTextPart.text ?? '';\n filteredContent[lastTextPartIndex] = {\n ...lastTextPart,\n [ContentTypes.TEXT]: existingText\n ? `${existingText}\\n${invalidToolText}`\n : invalidToolText,\n };\n } else {\n /** No text part exists, create one */\n filteredContent.push({\n type: ContentTypes.TEXT,\n [ContentTypes.TEXT]: invalidToolText,\n });\n }\n }\n\n /** Use filtered content if we made any changes */\n if (\n filteredContent.length !== content.length ||\n invalidToolStrings.length > 0\n ) {\n processedMessage = { ...message, content: filteredContent };\n }\n }\n }\n\n // Process the assistant message using the helper function\n const formattedMessages = formatAssistantMessage(processedMessage);\n messages.push(...formattedMessages);\n\n // Update the index mapping for this assistant message\n // Store all indices that were created from this original message\n const endMessageIndex = messages.length;\n const resultIndices = [];\n for (let j = startMessageIndex; j < endMessageIndex; j++) {\n resultIndices.push(j);\n }\n indexMapping[i] = resultIndices;\n }\n\n if (indexTokenCountMap) {\n for (\n let originalIndex = 0;\n originalIndex < payload.length;\n originalIndex++\n ) {\n const resultIndices = indexMapping[originalIndex] || [];\n const tokenCount = indexTokenCountMap[originalIndex];\n\n if (tokenCount === undefined) {\n continue;\n }\n\n const msgCount = resultIndices.length;\n if (msgCount === 1) {\n updatedIndexTokenCountMap[resultIndices[0]] = tokenCount;\n continue;\n }\n\n if (msgCount < 2) {\n continue;\n }\n\n let totalLength = 0;\n const lastIdx = msgCount - 1;\n const lengths = new Array<number>(msgCount);\n for (let k = 0; k < msgCount; k++) {\n const msg = messages[resultIndices[k]];\n const { content } = msg;\n let len = 0;\n if (typeof content === 'string') {\n len = content.length;\n } else if (Array.isArray(content)) {\n for (const part of content as Array<\n Record<string, unknown> | string | undefined\n >) {\n if (typeof part === 'string') {\n len += part.length;\n } else if (part != null && typeof part === 'object') {\n const val = part.text ?? part.content;\n if (typeof val === 'string') {\n len += val.length;\n }\n }\n }\n }\n const toolCalls = (msg as AIMessage).tool_calls;\n if (Array.isArray(toolCalls)) {\n for (const tc of toolCalls as Array<Record<string, unknown>>) {\n if (typeof tc.name === 'string') {\n len += tc.name.length;\n }\n const { args } = tc;\n if (typeof args === 'string') {\n len += args.length;\n } else if (args != null) {\n len += JSON.stringify(args).length;\n }\n }\n }\n lengths[k] = len;\n totalLength += len;\n }\n\n if (totalLength === 0) {\n const countPerMessage = Math.floor(tokenCount / msgCount);\n for (let k = 0; k < lastIdx; k++) {\n updatedIndexTokenCountMap[resultIndices[k]] = countPerMessage;\n }\n updatedIndexTokenCountMap[resultIndices[lastIdx]] =\n tokenCount - countPerMessage * lastIdx;\n } else {\n let distributed = 0;\n for (let k = 0; k < lastIdx; k++) {\n const share = Math.floor((lengths[k] / totalLength) * tokenCount);\n updatedIndexTokenCountMap[resultIndices[k]] = share;\n distributed += share;\n }\n updatedIndexTokenCountMap[resultIndices[lastIdx]] =\n tokenCount - distributed;\n }\n }\n }\n\n return {\n messages,\n indexTokenCountMap: indexTokenCountMap\n ? updatedIndexTokenCountMap\n : undefined,\n };\n};\n\n/**\n * Adds a value at key 0 for system messages and shifts all key indices by one in an indexTokenCountMap.\n * This is useful when adding a system message at the beginning of a conversation.\n *\n * @param indexTokenCountMap - The original map of message indices to token counts\n * @param instructionsTokenCount - The token count for the system message to add at index 0\n * @returns A new map with the system message at index 0 and all other indices shifted by 1\n */\nexport function shiftIndexTokenCountMap(\n indexTokenCountMap: Record<number, number>,\n instructionsTokenCount: number\n): Record<number, number> {\n // Create a new map to avoid modifying the original\n const shiftedMap: Record<number, number> = {};\n shiftedMap[0] = instructionsTokenCount;\n\n // Shift all existing indices by 1\n for (const [indexStr, tokenCount] of Object.entries(indexTokenCountMap)) {\n const index = Number(indexStr);\n shiftedMap[index + 1] = tokenCount;\n }\n\n return shiftedMap;\n}\n\n/**\n * Ensures compatibility when switching from a non-thinking agent to a thinking-enabled agent.\n * Converts AI messages with tool calls (that lack thinking/reasoning blocks) into buffer strings,\n * avoiding the thinking block signature requirement.\n *\n * Recognizes the following as valid thinking/reasoning blocks:\n * - ContentTypes.THINKING (Anthropic)\n * - ContentTypes.REASONING_CONTENT (Bedrock)\n * - ContentTypes.REASONING (VertexAI / Google)\n * - 'redacted_thinking'\n *\n * @param messages - Array of messages to process\n * @param provider - The provider being used (unused but kept for future compatibility)\n * @returns The messages array with tool sequences converted to buffer strings if necessary\n */\nexport function ensureThinkingBlockInMessages(\n messages: BaseMessage[],\n _provider: Providers\n): BaseMessage[] {\n const result: BaseMessage[] = [];\n let i = 0;\n\n while (i < messages.length) {\n const msg = messages[i];\n /** Detect AI messages by instanceof OR by role, in case cache-control cloning\n produced a plain object that lost the LangChain prototype. */\n const isAI =\n msg instanceof AIMessage ||\n msg instanceof AIMessageChunk ||\n ('role' in msg && (msg as any).role === 'assistant');\n\n if (!isAI) {\n result.push(msg);\n i++;\n continue;\n }\n\n const aiMsg = msg as AIMessage | AIMessageChunk;\n const hasToolCalls = aiMsg.tool_calls && aiMsg.tool_calls.length > 0;\n const contentIsArray = Array.isArray(aiMsg.content);\n\n // Check if the message has tool calls or tool_use content\n let hasToolUse = hasToolCalls ?? false;\n let hasThinkingBlock = false;\n\n if (contentIsArray && aiMsg.content.length > 0) {\n const content = aiMsg.content as ExtendedMessageContent[];\n hasToolUse =\n hasToolUse ||\n content.some((c) => typeof c === 'object' && c.type === 'tool_use');\n // Check ALL content blocks for thinking/reasoning, not just [0].\n // Bedrock may emit a whitespace text chunk before the thinking block,\n // pushing the reasoning_content to index 1+.\n hasThinkingBlock = content.some(\n (c) =>\n typeof c === 'object' &&\n (c.type === ContentTypes.THINKING ||\n c.type === ContentTypes.REASONING_CONTENT ||\n c.type === ContentTypes.REASONING ||\n c.type === 'redacted_thinking')\n );\n }\n\n // Bedrock also stores reasoning in additional_kwargs (may not be in content array)\n if (\n !hasThinkingBlock &&\n aiMsg.additional_kwargs.reasoning_content != null\n ) {\n hasThinkingBlock = true;\n }\n\n // If message has tool use but no thinking block, check whether this is a\n // continuation of a thinking-enabled agent's chain before converting.\n // Bedrock reasoning models can produce multiple AI→Tool rounds after an\n // initial reasoning response: the first AI message has reasoning_content,\n // but follow-ups have content: \"\" with only tool_calls. These are the\n // same agent's turn and must NOT be converted to HumanMessages.\n if (hasToolUse && !hasThinkingBlock) {\n // Walk backwards — if an earlier AI message in the same chain (before\n // the nearest HumanMessage) has a thinking/reasoning block, this is a\n // continuation of a thinking-enabled turn, not a non-thinking handoff.\n if (chainHasThinkingBlock(messages, i)) {\n result.push(msg);\n i++;\n continue;\n }\n\n // Collect the AI message and any following tool messages\n const toolSequence: BaseMessage[] = [msg];\n let j = i + 1;\n\n // Look ahead for tool messages that belong to this AI message\n const isToolMsg = (m: BaseMessage): boolean =>\n m instanceof ToolMessage || ('role' in m && (m as any).role === 'tool');\n while (j < messages.length && isToolMsg(messages[j])) {\n toolSequence.push(messages[j]);\n j++;\n }\n\n // Convert the sequence to a buffer string and wrap in a HumanMessage\n // This avoids the thinking block requirement which only applies to AI messages\n const bufferString = getBufferString(toolSequence);\n result.push(\n new HumanMessage({\n content: `[Previous agent context]\\n${bufferString}`,\n })\n );\n\n // Skip the messages we've processed\n i = j;\n } else {\n // Keep the message as is\n result.push(msg);\n i++;\n }\n }\n\n return result;\n}\n\n/**\n * Walks backwards from `currentIndex` through the message array to check\n * whether an earlier AI message in the same \"chain\" (no HumanMessage boundary)\n * contains a thinking/reasoning block.\n *\n * A \"chain\" is a contiguous sequence of AI + Tool messages with no intervening\n * HumanMessage. Bedrock reasoning models produce reasoning on the first AI\n * response, then issue follow-up tool calls with `content: \"\"` and no\n * reasoning block. These follow-ups are part of the same thinking-enabled\n * turn and should not be converted.\n */\nfunction chainHasThinkingBlock(\n messages: BaseMessage[],\n currentIndex: number\n): boolean {\n for (let k = currentIndex - 1; k >= 0; k--) {\n const prev = messages[k];\n\n // HumanMessage = turn boundary — stop searching\n if (\n prev instanceof HumanMessage ||\n ('role' in prev && (prev as any).role === 'user')\n ) {\n return false;\n }\n\n // Check AI messages for thinking/reasoning blocks\n const isPrevAI =\n prev instanceof AIMessage ||\n prev instanceof AIMessageChunk ||\n ('role' in prev && (prev as any).role === 'assistant');\n\n if (isPrevAI) {\n const prevAiMsg = prev as AIMessage | AIMessageChunk;\n\n if (Array.isArray(prevAiMsg.content) && prevAiMsg.content.length > 0) {\n const content = prevAiMsg.content as ExtendedMessageContent[];\n if (\n content.some(\n (c) =>\n typeof c === 'object' &&\n (c.type === ContentTypes.THINKING ||\n c.type === ContentTypes.REASONING_CONTENT ||\n c.type === ContentTypes.REASONING ||\n c.type === 'redacted_thinking')\n )\n ) {\n return true;\n }\n }\n\n // Bedrock also stores reasoning in additional_kwargs\n if (prevAiMsg.additional_kwargs.reasoning_content != null) {\n return true;\n }\n }\n\n // ToolMessages are part of the chain — keep walking back\n }\n\n return false;\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -519,6 +519,12 @@ export class AgentContext {
|
|
|
519
519
|
tokenCounter: t.TokenCounter
|
|
520
520
|
): Promise<void> {
|
|
521
521
|
let toolTokens = 0;
|
|
522
|
+
// Track names to avoid double-counting when a tool appears in both
|
|
523
|
+
// this.tools (bound StructuredTool instances) and this.toolDefinitions
|
|
524
|
+
// (MCP / event-driven schemas).
|
|
525
|
+
const countedToolNames = new Set<string>();
|
|
526
|
+
|
|
527
|
+
// Count tokens for bound tools (StructuredTool instances with .schema)
|
|
522
528
|
if (this.tools && this.tools.length > 0) {
|
|
523
529
|
for (const tool of this.tools) {
|
|
524
530
|
const genericTool = tool as Record<string, unknown>;
|
|
@@ -526,18 +532,39 @@ export class AgentContext {
|
|
|
526
532
|
genericTool.schema != null &&
|
|
527
533
|
typeof genericTool.schema === 'object'
|
|
528
534
|
) {
|
|
535
|
+
const toolName = (genericTool.name as string | undefined) ?? '';
|
|
529
536
|
const jsonSchema = toJsonSchema(
|
|
530
537
|
genericTool.schema,
|
|
531
|
-
|
|
538
|
+
toolName,
|
|
532
539
|
(genericTool.description as string | undefined) ?? ''
|
|
533
540
|
);
|
|
534
541
|
toolTokens += tokenCounter(
|
|
535
542
|
new SystemMessage(JSON.stringify(jsonSchema))
|
|
536
543
|
);
|
|
544
|
+
if (toolName) {
|
|
545
|
+
countedToolNames.add(toolName);
|
|
546
|
+
}
|
|
537
547
|
}
|
|
538
548
|
}
|
|
539
549
|
}
|
|
540
550
|
|
|
551
|
+
// Count tokens for tool definitions (MCP / event-driven tools).
|
|
552
|
+
// These are sent to the provider API as tool schemas alongside bound tools.
|
|
553
|
+
// Both can be populated simultaneously (graph tools + MCP tools).
|
|
554
|
+
if (this.toolDefinitions && this.toolDefinitions.length > 0) {
|
|
555
|
+
for (const def of this.toolDefinitions) {
|
|
556
|
+
if (countedToolNames.has(def.name)) {
|
|
557
|
+
continue; // Already counted via this.tools
|
|
558
|
+
}
|
|
559
|
+
const schema = {
|
|
560
|
+
name: def.name,
|
|
561
|
+
description: def.description ?? '',
|
|
562
|
+
parameters: def.parameters ?? {},
|
|
563
|
+
};
|
|
564
|
+
toolTokens += tokenCounter(new SystemMessage(JSON.stringify(schema)));
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
541
568
|
this.instructionTokens += toolTokens;
|
|
542
569
|
}
|
|
543
570
|
|