@librechat/agents 3.4.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/cjs/graphs/Graph.cjs +111 -27
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/hooks/HookRegistry.cjs +83 -0
  4. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  5. package/dist/cjs/hooks/executeHooks.cjs +60 -14
  6. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  7. package/dist/cjs/hooks/index.cjs.map +1 -1
  8. package/dist/cjs/hooks/types.cjs +2 -0
  9. package/dist/cjs/hooks/types.cjs.map +1 -1
  10. package/dist/cjs/llm/init.cjs +3 -3
  11. package/dist/cjs/llm/invoke.cjs +2 -2
  12. package/dist/cjs/main.cjs +14 -13
  13. package/dist/cjs/messages/format.cjs +40 -23
  14. package/dist/cjs/messages/format.cjs.map +1 -1
  15. package/dist/cjs/run.cjs +82 -15
  16. package/dist/cjs/run.cjs.map +1 -1
  17. package/dist/cjs/session/AgentSession.cjs +37 -2
  18. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  19. package/dist/cjs/stream.cjs +1 -1
  20. package/dist/cjs/summarization/node.cjs +6 -3
  21. package/dist/cjs/summarization/node.cjs.map +1 -1
  22. package/dist/cjs/tools/BashExecutor.cjs +1 -1
  23. package/dist/cjs/tools/CodeExecutor.cjs +1 -1
  24. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +1 -1
  25. package/dist/cjs/tools/ToolNode.cjs +316 -94
  26. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  27. package/dist/cjs/tools/ToolSearch.cjs +1 -1
  28. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +630 -78
  29. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  30. package/dist/cjs/tools/subagent/SubagentReplay.cjs +175 -0
  31. package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -0
  32. package/dist/cjs/tools/toolOutputReferences.cjs +20 -0
  33. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  34. package/dist/cjs/utils/index.cjs +2 -2
  35. package/dist/esm/graphs/Graph.mjs +111 -27
  36. package/dist/esm/graphs/Graph.mjs.map +1 -1
  37. package/dist/esm/hooks/HookRegistry.mjs +83 -0
  38. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  39. package/dist/esm/hooks/executeHooks.mjs +60 -14
  40. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  41. package/dist/esm/hooks/index.mjs.map +1 -1
  42. package/dist/esm/hooks/types.mjs +2 -1
  43. package/dist/esm/hooks/types.mjs.map +1 -1
  44. package/dist/esm/llm/init.mjs +1 -1
  45. package/dist/esm/llm/invoke.mjs +2 -2
  46. package/dist/esm/main.mjs +11 -11
  47. package/dist/esm/messages/format.mjs +40 -23
  48. package/dist/esm/messages/format.mjs.map +1 -1
  49. package/dist/esm/run.mjs +83 -16
  50. package/dist/esm/run.mjs.map +1 -1
  51. package/dist/esm/session/AgentSession.mjs +37 -2
  52. package/dist/esm/session/AgentSession.mjs.map +1 -1
  53. package/dist/esm/stream.mjs +1 -1
  54. package/dist/esm/summarization/node.mjs +6 -3
  55. package/dist/esm/summarization/node.mjs.map +1 -1
  56. package/dist/esm/tools/BashExecutor.mjs +1 -1
  57. package/dist/esm/tools/CodeExecutor.mjs +1 -1
  58. package/dist/esm/tools/ProgrammaticToolCalling.mjs +1 -1
  59. package/dist/esm/tools/ToolNode.mjs +317 -95
  60. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  61. package/dist/esm/tools/ToolSearch.mjs +1 -1
  62. package/dist/esm/tools/subagent/SubagentExecutor.mjs +631 -79
  63. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  64. package/dist/esm/tools/subagent/SubagentReplay.mjs +168 -0
  65. package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -0
  66. package/dist/esm/tools/toolOutputReferences.mjs +20 -0
  67. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  68. package/dist/esm/utils/index.mjs +2 -2
  69. package/dist/types/graphs/Graph.d.ts +16 -1
  70. package/dist/types/hooks/HookRegistry.d.ts +10 -1
  71. package/dist/types/hooks/executeHooks.d.ts +5 -1
  72. package/dist/types/hooks/index.d.ts +2 -2
  73. package/dist/types/hooks/types.d.ts +12 -0
  74. package/dist/types/run.d.ts +4 -1
  75. package/dist/types/session/AgentSession.d.ts +1 -0
  76. package/dist/types/tools/ToolNode.d.ts +23 -15
  77. package/dist/types/tools/subagent/SubagentExecutor.d.ts +46 -7
  78. package/dist/types/tools/subagent/SubagentReplay.d.ts +81 -0
  79. package/dist/types/tools/toolOutputReferences.d.ts +12 -0
  80. package/dist/types/types/graph.d.ts +5 -5
  81. package/dist/types/types/hitl.d.ts +15 -0
  82. package/package.json +6 -2
  83. package/src/graphs/Graph.ts +246 -52
  84. package/src/graphs/__tests__/Graph.breakerLifecycle.test.ts +48 -9
  85. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +1 -1
  86. package/src/graphs/__tests__/Graph.subagentResumeState.test.ts +80 -0
  87. package/src/hooks/HookRegistry.ts +151 -1
  88. package/src/hooks/__tests__/HookRegistry.test.ts +96 -0
  89. package/src/hooks/__tests__/executeHooks.test.ts +160 -0
  90. package/src/hooks/executeHooks.ts +133 -15
  91. package/src/hooks/index.ts +3 -1
  92. package/src/hooks/types.ts +16 -0
  93. package/src/messages/format.ts +54 -26
  94. package/src/messages/formatAgentMessages.reducer.test.ts +162 -0
  95. package/src/messages/formatAgentMessages.steer.test.ts +16 -11
  96. package/src/messages/formatAgentMessages.test.ts +7 -2
  97. package/src/run.ts +164 -18
  98. package/src/session/AgentSession.ts +52 -2
  99. package/src/session/__tests__/JsonlSessionStore.test.ts +53 -0
  100. package/src/summarization/__tests__/node.test.ts +32 -14
  101. package/src/summarization/node.ts +15 -11
  102. package/src/tools/ToolNode.ts +631 -157
  103. package/src/tools/__tests__/SubagentExecutor.test.ts +542 -6
  104. package/src/tools/__tests__/SubagentReplay.test.ts +300 -0
  105. package/src/tools/__tests__/ToolNode.breakerSignal.test.ts +208 -2
  106. package/src/tools/__tests__/directToolHITLResumeScope.test.ts +486 -2
  107. package/src/tools/__tests__/hitl.test.ts +234 -5
  108. package/src/tools/__tests__/subagentHooks.test.ts +1040 -62
  109. package/src/tools/__tests__/toolOutputReferences.test.ts +19 -2
  110. package/src/tools/subagent/SubagentExecutor.ts +1369 -131
  111. package/src/tools/subagent/SubagentReplay.ts +575 -0
  112. package/src/tools/toolOutputReferences.ts +40 -1
  113. package/src/types/graph.ts +5 -5
  114. package/src/types/hitl.ts +16 -0
@@ -1 +1 @@
1
- {"version":3,"file":"format.mjs","names":["isToolMessage"],"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} from '@langchain/core/messages';\nimport type {\n MessageContent,\n MessageContentImageUrl,\n} from '@langchain/core/messages';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type {\n BedrockReasoningContentText,\n ExtendedMessageContent,\n GoogleReasoningContentText,\n MessageContentComplex,\n ReasoningContentText,\n SummaryContentBlock,\n SummaryCoverage,\n ThinkingContentText,\n ToolCallContent,\n ToolResultContent,\n ToolCallPart,\n TPayload,\n TMessage,\n} from '@/types';\nimport {\n compactToolContent,\n getToolContentCharLength,\n isAtomicToolContentBlock,\n serializeStructuredValueBounded,\n} from '@/utils/toolContent';\nimport { normalizeAnthropicToolCallId } from '@/llm/anthropic/utils/message_inputs';\nimport { toLangChainContent, toLangChainMessageFields } from './langchain';\nimport { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';\nimport { Providers, ContentTypes, Constants } from '@/common';\nimport { emitAgentLog } from '@/utils/events';\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\nexport type LangChainMessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\nexport type RoleBearingMessage<T extends BaseMessage = BaseMessage> = T & {\n role: LangChainMessageRole;\n};\n\nexport function withMessageRole<T extends BaseMessage>(\n message: T,\n role: LangChainMessageRole\n): RoleBearingMessage<T> {\n const roleMessage = message as T & { role?: LangChainMessageRole };\n if (roleMessage.role === role) {\n return roleMessage as RoleBearingMessage<T>;\n }\n Object.defineProperty(roleMessage, 'role', {\n value: role,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n return roleMessage as RoleBearingMessage<T>;\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 | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<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 withMessageRole(\n new HumanMessage(toLangChainMessageFields(mediaMessage)),\n 'user'\n );\n }\n\n if (!langChain) {\n return formattedMessage;\n }\n\n if (role === 'user') {\n return withMessageRole(\n new HumanMessage(toLangChainMessageFields(formattedMessage)),\n 'user'\n );\n } else if (role === 'assistant') {\n return withMessageRole(\n new AIMessage(toLangChainMessageFields(formattedMessage)),\n 'assistant'\n );\n } else {\n return withMessageRole(\n new SystemMessage(toLangChainMessageFields(formattedMessage)),\n 'system'\n );\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<\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<SystemMessage>\n> => {\n return messages.map((msg) => {\n const formatted = formatMessage({\n ...formatOptions,\n message: msg,\n langChain: true,\n });\n return formatted as\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<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\ninterface FormatAssistantMessageOptions {\n preserveUnpairedServerToolUses?: boolean;\n preserveReasoningContent?: boolean;\n provider?: Providers;\n}\n\ninterface FormatAgentMessagesOptions {\n provider?: Providers;\n /** Reconstruct hidden `reasoning_content` from `THINK` parts onto prior\n * tool-call messages. Explicit opt-in for OpenAI-compatible endpoints that\n * replay reasoning across turns; defaults to on for DeepSeek thinking-mode. */\n preserveReasoningContent?: boolean;\n /** Skill names already primed fresh this turn (manual/always-apply). Their\n * historical `skill` tool_calls are not reconstructed into a HumanMessage,\n * so the same SKILL.md body is not injected twice in one request. */\n skipSkillBodyNames?: Set<string>;\n}\n\nfunction extractReasoningContent(\n part: MessageContentComplex | undefined | null\n): string {\n if (part == null || typeof part !== 'object') {\n return '';\n }\n if (part.type === ContentTypes.THINK) {\n const think = (part as ReasoningContentText).think;\n return typeof think === 'string' ? think : '';\n }\n if (part.type === ContentTypes.THINKING) {\n const thinking = (part as ThinkingContentText).thinking;\n return typeof thinking === 'string' ? thinking : '';\n }\n if (part.type === ContentTypes.REASONING) {\n const reasoning = (part as GoogleReasoningContentText).reasoning;\n return typeof reasoning === 'string' ? reasoning : '';\n }\n if (part.type === ContentTypes.REASONING_CONTENT) {\n const reasoningText = (part as BedrockReasoningContentText).reasoningText;\n return typeof reasoningText.text === 'string' ? reasoningText.text : '';\n }\n return '';\n}\n\ntype ServerToolInput = Exclude<NonNullable<ToolCallPart['args']>, string>;\n\nfunction parseServerToolInput(args: ToolCallPart['args']): ServerToolInput {\n if (typeof args === 'string') {\n try {\n const parsed = JSON.parse(args) as unknown;\n return parsed != null &&\n typeof parsed === 'object' &&\n !Array.isArray(parsed)\n ? (parsed as ServerToolInput)\n : {};\n } catch {\n return {};\n }\n }\n return args != null && typeof args === 'object' ? args : {};\n}\n\nfunction getTextContent(part: MessageContentComplex): string {\n const { text } = part as { text?: unknown };\n return typeof text === 'string' ? text : '';\n}\n\nfunction hasMeaningfulAssistantContent(part: MessageContentComplex): boolean {\n if (part.type === ContentTypes.TEXT) {\n return getTextContent(part).trim().length > 0;\n }\n if (\n part.type === ContentTypes.TOOL_CALL ||\n part.type === ContentTypes.ERROR ||\n part.type === ContentTypes.AGENT_UPDATE ||\n part.type === ContentTypes.SUMMARY ||\n part.type === ContentTypes.ACTIVITY_LABEL\n ) {\n return false;\n }\n if (\n part.type === ContentTypes.THINK ||\n part.type === ContentTypes.THINKING ||\n part.type === ContentTypes.REASONING ||\n part.type === ContentTypes.REASONING_CONTENT ||\n part.type === 'redacted_thinking'\n ) {\n return extractReasoningContent(part).trim().length > 0;\n }\n return part.type != null && part.type !== '';\n}\n\nfunction getToolUseId(part: MessageContentComplex): string | undefined {\n if (!('tool_use_id' in part) || typeof part.tool_use_id !== 'string') {\n return undefined;\n }\n return part.tool_use_id;\n}\n\nfunction isValidServerToolResult(part: MessageContentComplex): boolean {\n const toolUseId = getToolUseId(part);\n if (\n toolUseId?.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX) !== true ||\n !('content' in part)\n ) {\n return false;\n }\n const { content } = part as { content?: unknown };\n return (\n Array.isArray(content) ||\n (content != null &&\n typeof content === 'object' &&\n 'type' in content &&\n (content as { type?: unknown }).type === 'web_search_tool_result_error')\n );\n}\n\nfunction getToolCallId(part: MessageContentComplex): string | undefined {\n if (part.type !== ContentTypes.TOOL_CALL) {\n return undefined;\n }\n const id = part.tool_call?.id;\n return typeof id === 'string' && id !== '' ? id : undefined;\n}\n\nfunction hasToolCallOutput(part: MessageContentComplex): boolean {\n if (part.type !== ContentTypes.TOOL_CALL) {\n return false;\n }\n const output = part.tool_call?.output;\n return output != null && output !== '';\n}\n\nfunction formatToolCallOutput(\n output: ToolCallPart['output'] | undefined\n): MessageContent {\n if (output == null) {\n return '';\n }\n return compactToolContent(output, HARD_MAX_TOOL_RESULT_CHARS).content;\n}\n\n/**\n * Content for the synthetic assistant turn that separates a trailing steer\n * from the next user turn. Non-empty by necessity — see the push site.\n */\nconst STEER_ANCHOR_PLACEHOLDER = '_';\n\n/**\n * True when an assistant message replayed as a steer and nothing followed it,\n * so the emitted run ends on the steer's `HumanMessage`.\n */\nfunction endsWithSteerMessage(\n formatted: Array<RoleBearingMessage<BaseMessage>>\n): boolean {\n if (formatted.length === 0) {\n return false;\n }\n return formatted[formatted.length - 1].additional_kwargs.source === 'steer';\n}\n\n/**\n * Helper function to format an assistant message\n * @param message The message to format\n * @param options Optional formatting options\n * @returns Array of formatted messages\n */\nfunction formatAssistantMessage(\n message: Partial<TMessage>,\n options?: FormatAssistantMessageOptions\n): Array<\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<ToolMessage>\n | RoleBearingMessage<HumanMessage>\n> {\n const formattedMessages: Array<\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<ToolMessage>\n | RoleBearingMessage<HumanMessage>\n > = [];\n let currentContent: MessageContentComplex[] = [];\n let lastAIMessage: RoleBearingMessage<AIMessage> | null = null;\n let hasReasoning = false;\n let pendingReasoningContent = '';\n const emittedServerToolUseIds = new Set<string>();\n const pendingServerToolUses = new Map<string, MessageContentComplex>();\n const shouldPreserveReasoningContent =\n options?.preserveReasoningContent === true;\n const serverToolResultIds = new Set<string>();\n const preferredToolCallParts = new Map<string, MessageContentComplex>();\n\n const takePendingReasoningContent = (): string | undefined => {\n if (!shouldPreserveReasoningContent || !pendingReasoningContent) {\n return undefined;\n }\n const reasoningContent = pendingReasoningContent;\n pendingReasoningContent = '';\n return reasoningContent;\n };\n\n const createAIMessage = (\n content: MessageContent\n ): RoleBearingMessage<AIMessage> => {\n const reasoningContent = takePendingReasoningContent();\n return withMessageRole(\n new AIMessage({\n content,\n ...(reasoningContent != null && {\n additional_kwargs: { reasoning_content: reasoningContent },\n }),\n }),\n 'assistant'\n );\n };\n\n const attachPendingReasoningContent = (aiMessage: AIMessage): void => {\n const reasoningContent = takePendingReasoningContent();\n if (reasoningContent == null) {\n return;\n }\n aiMessage.additional_kwargs.reasoning_content =\n typeof aiMessage.additional_kwargs.reasoning_content === 'string'\n ? `${aiMessage.additional_kwargs.reasoning_content}${reasoningContent}`\n : reasoningContent;\n };\n\n const flushPendingServerToolUse = (toolUseId: string): void => {\n for (const [id, content] of pendingServerToolUses) {\n pendingServerToolUses.delete(id);\n if (id === toolUseId) {\n currentContent.push(content);\n emittedServerToolUseIds.add(id);\n return;\n }\n }\n };\n\n if (Array.isArray(message.content)) {\n const contentParts = message.content as Array<\n MessageContentComplex | undefined | null\n >;\n\n for (const part of contentParts) {\n if (part == null) {\n continue;\n }\n if (isValidServerToolResult(part)) {\n serverToolResultIds.add(getToolUseId(part) ?? '');\n }\n if (options?.provider === Providers.ANTHROPIC) {\n const toolCallId = getToolCallId(part);\n if (toolCallId == null) {\n continue;\n }\n const preferredPart = preferredToolCallParts.get(toolCallId);\n if (\n preferredPart == null ||\n (!hasToolCallOutput(preferredPart) && hasToolCallOutput(part))\n ) {\n preferredToolCallParts.set(toolCallId, part);\n }\n }\n }\n\n for (const part of contentParts) {\n if (part == null) {\n continue;\n }\n const toolUseId = getToolUseId(part);\n if (toolUseId != null) {\n const isServerToolResult = isValidServerToolResult(part);\n if (\n toolUseId.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX) &&\n !isServerToolResult\n ) {\n continue;\n }\n flushPendingServerToolUse(toolUseId);\n if (isServerToolResult) {\n currentContent.push(part);\n continue;\n }\n } else if (hasMeaningfulAssistantContent(part)) {\n for (const id of pendingServerToolUses.keys()) {\n if (!serverToolResultIds.has(id)) {\n pendingServerToolUses.delete(id);\n }\n }\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 if (\n currentContent.some((content) => content.type !== ContentTypes.TEXT)\n ) {\n currentContent.push(part);\n lastAIMessage = createAIMessage(toLangChainContent(currentContent));\n formattedMessages.push(lastAIMessage);\n currentContent = [];\n continue;\n }\n let content = currentContent.reduce((acc, curr) => {\n if (curr.type === ContentTypes.TEXT) {\n return `${acc}${getTextContent(curr)}\\n`;\n }\n return acc;\n }, '');\n content = `${content}\\n${getTextContent(part)}`.trim();\n lastAIMessage = createAIMessage(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 = createAIMessage(getTextContent(part));\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 const toolCallId = getToolCallId(part);\n if (\n options?.provider === Providers.ANTHROPIC &&\n toolCallId != null &&\n preferredToolCallParts.get(toolCallId) !== part\n ) {\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 (\n options?.provider === Providers.ANTHROPIC &&\n typeof _tool_call.id === 'string' &&\n _tool_call.id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)\n ) {\n if (\n !serverToolResultIds.has(_tool_call.id) &&\n options.preserveUnpairedServerToolUses !== true\n ) {\n continue;\n }\n if (\n emittedServerToolUseIds.has(_tool_call.id) ||\n pendingServerToolUses.has(_tool_call.id)\n ) {\n continue;\n }\n pendingServerToolUses.set(_tool_call.id, {\n type: 'server_tool_use',\n id: _tool_call.id,\n name: _tool_call.name,\n input: parseServerToolInput(_args),\n } as MessageContentComplex);\n continue;\n }\n\n if (!lastAIMessage) {\n // \"Heal\" the payload by creating an AIMessage to precede the tool call\n lastAIMessage = createAIMessage('');\n formattedMessages.push(lastAIMessage);\n } else {\n attachPendingReasoningContent(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 (\n options?.provider === Providers.ANTHROPIC &&\n Array.isArray(lastAIMessage.content)\n ) {\n const content = lastAIMessage.content as MessageContentComplex[];\n content.push({\n type: 'tool_use',\n id: normalizeAnthropicToolCallId(tool_call.id ?? ''),\n name: tool_call.name,\n input: args,\n } as MessageContentComplex);\n lastAIMessage.content = content as MessageContent;\n } else {\n if (!lastAIMessage.tool_calls) {\n lastAIMessage.tool_calls = [];\n }\n lastAIMessage.tool_calls.push(tool_call as ToolCall);\n }\n\n formattedMessages.push(\n withMessageRole(\n new ToolMessage({\n tool_call_id: tool_call.id ?? '',\n name: tool_call.name,\n content: formatToolCallOutput(output),\n }),\n 'tool'\n )\n );\n } else if (\n part.type === ContentTypes.THINK ||\n part.type === ContentTypes.THINKING ||\n part.type === ContentTypes.REASONING ||\n part.type === ContentTypes.REASONING_CONTENT ||\n part.type === 'redacted_thinking'\n ) {\n hasReasoning = true;\n pendingReasoningContent += extractReasoningContent(part);\n continue;\n } else if (part.type === ContentTypes.STEER) {\n /*\n A mid-run steer: user speech persisted inline in the assistant message\n at the tool-batch boundary it was injected. Flush accumulated\n assistant content first so ordering is preserved, then replay the\n steer as a standalone user message — multimodal when the host stamped\n a pre-encoded `media` content array (attachment refs are re-encoded\n per turn host-side, like any other user media). `lastAIMessage` is\n reset AFTER the HumanMessage: a post-steer tool_call must mint a\n FRESH assistant anchor (the heal path) so its AIMessage lands after\n the user turn — attaching it to the pre-steer anchor would emit its\n ToolMessage after the HumanMessage while the call itself sat before\n it, an invalid provider ordering.\n */\n if (currentContent.length > 0) {\n if (\n currentContent.some((content) => content.type !== ContentTypes.TEXT)\n ) {\n lastAIMessage = createAIMessage(toLangChainContent(currentContent));\n formattedMessages.push(lastAIMessage);\n } else {\n const flushed = currentContent\n .reduce((acc, curr) => `${acc}${getTextContent(curr)}\\n`, '')\n .trim();\n if (flushed.length > 0) {\n lastAIMessage = createAIMessage(flushed);\n formattedMessages.push(lastAIMessage);\n }\n }\n currentContent = [];\n } else if (shouldPreserveReasoningContent && pendingReasoningContent) {\n /**\n * Reasoning directly preceding a steer has no `currentContent`\n * flush to consume it and the anchor resets below — emit an anchor\n * AIMessage now (createAIMessage folds the pending reasoning into\n * `additional_kwargs.reasoning_content`) or the persisted\n * assistant reasoning silently vanishes on replay.\n */\n lastAIMessage = createAIMessage('');\n formattedMessages.push(lastAIMessage);\n }\n const steerPart = part as {\n steer?: string;\n media?: MessageContentComplex[];\n };\n const steerContent =\n Array.isArray(steerPart.media) && steerPart.media.length > 0\n ? toLangChainContent(steerPart.media)\n : (steerPart.steer ?? '');\n formattedMessages.push(\n withMessageRole(\n new HumanMessage({\n content: steerContent as MessageContent,\n additional_kwargs: { role: 'user', source: 'steer' },\n }),\n 'user'\n )\n );\n lastAIMessage = null;\n /** The steer splits the assistant message: the post-steer segment\n * starts with fresh reasoning state (pre-steer reasoning was either\n * flushed above or intentionally dropped when not preserving). */\n hasReasoning = false;\n pendingReasoningContent = '';\n } else if (\n part.type === ContentTypes.ERROR ||\n part.type === ContentTypes.AGENT_UPDATE ||\n part.type === ContentTypes.SUMMARY ||\n part.type === ContentTypes.ACTIVITY_LABEL\n ) {\n continue;\n } else {\n if (part.type === ContentTypes.TEXT && !getTextContent(part).trim()) {\n continue;\n }\n currentContent.push(part);\n }\n }\n for (const content of pendingServerToolUses.values()) {\n currentContent.push(content);\n }\n }\n\n if (hasReasoning && currentContent.length > 0) {\n let content = '';\n for (const part of currentContent) {\n if (part.type !== ContentTypes.TEXT) {\n formattedMessages.push(\n createAIMessage(toLangChainContent(currentContent))\n );\n return formattedMessages;\n }\n content += `${getTextContent(part)}\\n`;\n }\n content = content.trim();\n\n if (content) {\n formattedMessages.push(createAIMessage(content));\n }\n } else if (currentContent.length > 0) {\n formattedMessages.push(createAIMessage(toLangChainContent(currentContent)));\n }\n\n return formattedMessages;\n}\n\nfunction getSourceMessageId(message: Partial<TMessage>): string | undefined {\n const candidate =\n (message as { messageId?: string }).messageId ??\n (message as { id?: string }).id;\n if (typeof candidate !== 'string') {\n return undefined;\n }\n const normalized = candidate.trim();\n return normalized.length > 0 ? normalized : undefined;\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 /** UI-only progress headers are not agent content and must not disturb\n * agent state: a label with no `agentIdMap` entry would otherwise read\n * as an agent change and flush the buffer mid-agent, splitting one\n * agent's contiguous content into two labeled blocks. Skipped before\n * any state transition below (mirrors the transfer path). */\n if (part.type === ContentTypes.ACTIVITY_LABEL) {\n continue;\n }\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 if (part.type === ContentTypes.STEER) {\n /** User speech is never agent content — see the transfer path above. */\n flushAgentBuffer();\n result.push(part);\n continue;\n }\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 /** UI-only progress headers are not agent content and must not disturb\n * agent state: a label with no `agentIdMap` entry would otherwise look\n * like an agent change, flushing the buffer and resetting an open\n * transfer capture so the transferred agent's following chunks lose\n * their frame. Skipped before any state transition below. */\n if (part.type === ContentTypes.ACTIVITY_LABEL) {\n continue;\n }\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 if (part.type === ContentTypes.STEER) {\n /**\n * User speech is never agent content: flush the buffer in place and\n * pass the steer through verbatim so `formatAssistantMessage` replays\n * it as a user turn. Folding it into a labeled transfer summary would\n * both drop the user's words and misattribute them to the agent.\n * The steer also CLOSES any open transfer capture — `flushAgentBuffer`\n * no-ops on an empty buffer, and leaving the capture live would fold\n * post-steer agent content into the pre-steer transfer output,\n * replaying it BEFORE the user's redirect.\n */\n flushAgentBuffer();\n transferToolCallIndex = undefined;\n transferToolCallId = undefined;\n currentAgentId = undefined;\n result.push(part);\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 * How far back a persisted summary reaches.\n *\n * `coverage` is authoritative: the block named the first source message that\n * compaction retained, so `messageIndex` is exclusive — everything before it is\n * covered and it survives whole. `positional` is the legacy reading for blocks\n * written before coverage existed (or whose anchor is no longer in the payload)\n * — the block's own location is the boundary, which is why it cannot\n * distinguish a retained tail from covered history.\n */\ntype SummaryBoundary =\n | {\n mode: 'coverage';\n messageIndex: number;\n text: string;\n tokenCount: number;\n }\n | {\n mode: 'positional';\n messageIndex: number;\n contentIndex: number;\n text: string;\n tokenCount: number;\n };\n\ntype SummaryTokenAdjustment = {\n original: number;\n adjusted: number;\n remainingChars: number;\n totalChars: number;\n};\n\ntype SummaryScan = {\n boundary?: SummaryBoundary;\n};\n\nfunction resolveCoverageIndex(\n coverage: SummaryCoverage | undefined,\n indexBySourceId: Map<string, number>,\n summaryMessageIndex: number\n): number | undefined {\n /** Persisted JSON, so the declared string type is not a runtime guarantee. */\n if (typeof coverage?.retainedFromMessageId !== 'string') {\n return undefined;\n }\n const retainedFromMessageId = coverage.retainedFromMessageId.trim();\n if (retainedFromMessageId === '') {\n return undefined;\n }\n const retainedIndex = indexBySourceId.get(retainedFromMessageId);\n return retainedIndex != null && retainedIndex <= summaryMessageIndex\n ? retainedIndex\n : undefined;\n}\n\nfunction scanSummaryBlocks(payload: TPayload): SummaryScan {\n let boundary: SummaryBoundary | undefined;\n /** Filled as the scan advances, so a coverage lookup only ever resolves to a\n * message already passed — no second pass over the payload. */\n const indexBySourceId = new Map<string, number>();\n\n for (let i = 0; i < payload.length; i++) {\n const message = payload[i];\n const sourceMessageId = getSourceMessageId(message);\n if (sourceMessageId != null) {\n indexBySourceId.set(sourceMessageId, i);\n }\n if (!Array.isArray(message.content)) {\n continue;\n }\n\n for (let j = 0; j < message.content.length; j++) {\n const part = message.content[j] as MessageContentComplex | undefined;\n if (part == null || part.type !== ContentTypes.SUMMARY) {\n continue;\n }\n\n const summaryPart = part as Partial<SummaryContentBlock> & {\n text?: string;\n };\n\n // Try content array first (new format), then direct text (legacy format)\n let summaryText = (summaryPart.content ?? [])\n .map((block) =>\n 'text' in block ? (block as { text: string }).text : ''\n )\n .join('')\n .trim();\n\n // Fallback: legacy format where text was a direct field on the block\n if (summaryText.length === 0 && typeof summaryPart.text === 'string') {\n summaryText = summaryPart.text.trim();\n }\n\n if (summaryText.length === 0) {\n continue;\n }\n\n const tokenCount =\n typeof summaryPart.tokenCount === 'number' &&\n Number.isFinite(summaryPart.tokenCount)\n ? summaryPart.tokenCount\n : 0;\n\n const retainedIndex = resolveCoverageIndex(\n summaryPart.coverage,\n indexBySourceId,\n i\n );\n\n boundary =\n retainedIndex != null\n ? {\n mode: 'coverage',\n messageIndex: retainedIndex,\n text: summaryText,\n tokenCount,\n }\n : {\n mode: 'positional',\n messageIndex: i,\n contentIndex: j,\n text: summaryText,\n tokenCount,\n };\n }\n }\n\n return { boundary };\n}\n\nfunction applySummaryBoundary(\n message: Partial<TMessage>,\n messageIndex: number,\n summaryBoundary?: SummaryBoundary\n): Partial<TMessage> | null {\n if (!summaryBoundary) {\n return message;\n }\n\n /** The boundary names the first retained message, so it is exclusive: that\n * message and everything after it — the recency tail included — stays\n * verbatim, and only genuinely covered history is dropped. Summary parts on\n * surviving messages are filtered later by `formatAssistantMessage`. */\n if (summaryBoundary.mode === 'coverage') {\n return messageIndex < summaryBoundary.messageIndex ? null : message;\n }\n\n if (messageIndex < summaryBoundary.messageIndex) {\n return null;\n }\n\n if (\n messageIndex !== summaryBoundary.messageIndex ||\n !Array.isArray(message.content)\n ) {\n return message;\n }\n\n return {\n ...message,\n content: message.content.slice(summaryBoundary.contentIndex + 1),\n };\n}\n\n/**\n * Whether `formatAssistantMessage` filters this part out of the emitted message.\n * Such a part contributes no prompt tokens, so measuring it as zero characters\n * is accurate — it must not be mistaken for content the heuristic cannot see.\n */\nfunction isDroppedByFormatting(\n part: MessageContentComplex | undefined\n): boolean {\n if (part == null) {\n return true;\n }\n if (\n part.type === ContentTypes.SUMMARY ||\n part.type === ContentTypes.ERROR ||\n part.type === ContentTypes.AGENT_UPDATE ||\n part.type === ContentTypes.ACTIVITY_LABEL\n ) {\n return true;\n }\n return part.type === ContentTypes.TEXT && getTextContent(part).trim() === '';\n}\n\nfunction measureValueChars(value: unknown): number {\n if (typeof value === 'string') {\n return value.length;\n }\n if (value == null || typeof value !== 'object') {\n return 0;\n }\n const measured = serializeStructuredValueBounded(value, 0).originalChars;\n return measured === Number.MAX_SAFE_INTEGER\n ? HARD_MAX_TOOL_RESULT_CHARS\n : Math.min(measured, HARD_MAX_TOOL_RESULT_CHARS);\n}\n\n/**\n * Whether a retained part's whole prompt cost is the text the char heuristic\n * reads, making it safe to represent in a character ratio.\n *\n * An allowlist, not a denylist. Media, resources, and tool calls carry cost that\n * is unrelated to their serialized length — a short image URL nested in\n * `tool_call.output` stands in for a fixed four-figure media charge — and\n * rejecting those case by case has repeatedly missed a nesting level. Listing\n * the two shapes whose characters `contentPartCharLength` actually reads makes\n * every other shape, present or future, ineligible by default: the ratio is\n * skipped and the entry keeps its original count, which prunes early rather than\n * exceeding the window.\n */\nfunction isCharRatioEligible(part: MessageContentComplex | undefined): boolean {\n if (part == null) {\n return false;\n }\n return part.type === ContentTypes.TEXT || part.type === ContentTypes.THINKING;\n}\n\nfunction contentPartCharLength(part: MessageContentComplex): number {\n const record = part as Record<string, unknown>;\n let len = 0;\n if (typeof record.text === 'string') {\n len += record.text.length;\n }\n if (typeof record.thinking === 'string') {\n len += record.thinking.length;\n }\n len += measureValueChars(record.input);\n /** Tool calls nest their payload a level down, so measuring only the\n * top-level fields scores an entire tool turn as zero characters. */\n const { tool_call: toolCall } = record;\n if (toolCall != null && typeof toolCall === 'object') {\n const call = toolCall as Record<string, unknown>;\n len += measureValueChars(call.name);\n len += measureValueChars(call.args);\n len += measureValueChars(call.output);\n }\n return len;\n}\n\n/** Extracts the skillName from a skill tool_call's args (string or object). */\nfunction extractSkillName(args: unknown): string | undefined {\n let parsed: Record<string, unknown> | undefined;\n if (typeof args === 'string') {\n try {\n parsed = JSON.parse(args) as Record<string, unknown>;\n } catch {\n /* malformed args — skip */\n }\n } else {\n parsed = args as Record<string, unknown> | undefined;\n }\n const name = parsed?.skillName;\n return typeof name === 'string' && name !== '' ? name : undefined;\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 * @param skills - Optional map of skill name to body for reconstructing skill HumanMessages.\n * @param options - Optional formatting options (provider, skipSkillBodyNames).\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 /** Pre-resolved skill bodies keyed by skill name. When present, HumanMessages\n * are reconstructed after skill ToolMessages to restore skill instructions\n * that were only in LangGraph state during the original run. */\n skills?: Map<string, string>,\n options?: FormatAgentMessagesOptions\n): {\n messages: Array<\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<SystemMessage>\n | RoleBearingMessage<ToolMessage>\n >;\n indexTokenCountMap?: Record<number, number>;\n /** Cross-run summary extracted from the payload. Should be forwarded to the\n * agent run so it can be included in the system message via AgentContext. */\n summary?: { text: string; tokenCount: number };\n /** When a positional summary boundary sliced content from a message, the token\n * count was proportionally reduced. Returned so the caller can log it. */\n boundaryTokenAdjustment?: SummaryTokenAdjustment;\n} => {\n const messages: Array<\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<SystemMessage>\n | RoleBearingMessage<ToolMessage>\n > = [];\n /**\n * A steer ended the previous payload entry, so the next message emitted —\n * whichever entry finally produces one — must be separated from it by an\n * assistant turn. Held rather than emitted so an entry that produces\n * nothing cannot leave the anchor stranded as the final turn.\n */\n let pendingSteerAnchor = false;\n /**\n * Emits the deferred anchor ahead of `next` — the message about to be\n * pushed. When that message is itself an assistant turn, it already IS the\n * separation the anchor exists to synthesize, so the intent is simply\n * discharged: emitting the placeholder anyway would put two assistant turns\n * back to back, which strict-alternation providers can reject and nothing downstream\n * repairs (`coalesceAdjacentUserTurns` merges user turns only).\n */\n const flushSteerAnchor = (next: { role?: LangChainMessageRole }): void => {\n if (!pendingSteerAnchor) {\n return;\n }\n pendingSteerAnchor = false;\n if (next.role === 'assistant') {\n return;\n }\n messages.push(\n withMessageRole(\n new AIMessage({ content: STEER_ANCHOR_PLACEHOLDER }),\n 'assistant'\n )\n );\n };\n // If indexTokenCountMap is provided, create a new map to track the updated indices\n const updatedIndexTokenCountMap: Record<number, number> = {};\n let boundaryTokenAdjustment: SummaryTokenAdjustment | undefined;\n // Keep track of the mapping from original payload indices to result indices\n const indexMapping: Record<number, number[] | undefined> = {};\n const { boundary: summaryBoundary } = scanSummaryBlocks(payload);\n\n // Summary metadata is returned to the caller so it can be forwarded to the\n // agent run and included in the single system message via AgentContext.\n // We intentionally do NOT create a SystemMessage here — that would conflict\n // with the agent's own system message (instructions + summary combined).\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 rawMessage = payload[i];\n const sourceMessageId = getSourceMessageId(rawMessage);\n let message = applySummaryBoundary(rawMessage, i, summaryBoundary);\n if (!message) {\n indexMapping[i] = [];\n continue;\n }\n\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 = {\n ...message,\n content: [\n { type: ContentTypes.TEXT, [ContentTypes.TEXT]: message.content },\n ],\n };\n } else if (Array.isArray(message.content) && message.content.length === 0) {\n indexMapping[i] = [];\n continue;\n }\n\n if (message.role !== 'assistant') {\n const formattedMessage = formatMessage({\n message: message as MessageInput,\n langChain: true,\n }) as\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<SystemMessage>;\n if (sourceMessageId != null && sourceMessageId !== '') {\n formattedMessage.id = sourceMessageId;\n }\n flushSteerAnchor(formattedMessage);\n messages.push(formattedMessage);\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 let pendingSkillNames: Set<string> | undefined;\n if (discoveredTools) {\n const content = message.content;\n if (content != null && 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 filteredContent.push(part);\n if (\n toolName === Constants.SKILL_TOOL &&\n skills?.size != null &&\n skills.size > 0\n ) {\n const skillName = extractSkillName(part.tool_call.args) ?? '';\n if (skillName) {\n (pendingSkillNames ??= new Set()).add(skillName);\n }\n }\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 /** When tools filtering is off, still detect skill tool_calls for body reconstruction */\n if (!discoveredTools && skills?.size != null && skills.size > 0) {\n const content = processedMessage.content;\n if (Array.isArray(content)) {\n for (const part of content) {\n if (\n part.type !== ContentTypes.TOOL_CALL ||\n part.tool_call?.name !== Constants.SKILL_TOOL\n ) {\n continue;\n }\n const skillName = extractSkillName(part.tool_call.args) ?? '';\n if (skillName) {\n (pendingSkillNames ??= new Set()).add(skillName);\n }\n }\n }\n }\n\n const formattedMessages = formatAssistantMessage(processedMessage, {\n preserveUnpairedServerToolUses: i === payload.length - 1,\n preserveReasoningContent:\n options?.preserveReasoningContent ??\n options?.provider === Providers.DEEPSEEK,\n provider: options?.provider,\n });\n if (sourceMessageId != null && sourceMessageId !== '') {\n for (const formattedMessage of formattedMessages) {\n formattedMessage.id = sourceMessageId;\n }\n }\n /**\n * A steer that ends an assistant message leaves the replay on a\n * `HumanMessage`. The next payload message is itself a user turn, so the\n * sequence would reach the provider as two adjacent user turns — rejected\n * by strict-alternation providers. Anchor it with a placeholder assistant\n * turn.\n *\n * The placeholder must be NON-EMPTY. A string-content assistant message\n * with no tool calls passes through `_convertMessagesToAnthropicPayload`\n * verbatim — the empty-text repair there only covers array content and\n * tool-call turns — so an empty anchor would reach Anthropic as\n * `{role: 'assistant', content: ''}` and trade one invalid sequence for\n * another. Same single-underscore convention the Anthropic converter\n * already uses when it has to synthesize a non-empty block.\n *\n * Deferred rather than decided by lookahead. `i < payload.length - 1` only\n * proves a later ENTRY exists, not that it EMITS: entries with empty\n * content, and entries dropped by `applySummaryBoundary`, are skipped\n * silently. A trailing steer followed only by those would get the anchor\n * as the FINAL turn — an assistant prefill with no request after it, which\n * the model may simply never answer. So the intent is recorded and flushed\n * only when a message actually follows.\n *\n * Pushed AFTER the id stamping above, deliberately. `messagesStateReducer`\n * treats a repeated id as replace-in-place, so an anchor carrying the\n * shared `sourceMessageId` would overwrite the steer it exists to protect.\n * Left unstamped, it reaches the reducer with a null id and is assigned a\n * fresh one. `endsWithSteerMessage` reads only `additional_kwargs.source`,\n * so the deferral cannot change which messages get anchored.\n */\n /**\n * Guarded on emission: an assistant entry whose blocks all filtered away\n * emits nothing, and flushing for it would strand the anchor as the final\n * turn — the pending flag stays set for whichever entry emits next.\n */\n if (formattedMessages.length > 0) {\n flushSteerAnchor(formattedMessages[0]);\n }\n messages.push(...formattedMessages);\n if (endsWithSteerMessage(formattedMessages)) {\n pendingSteerAnchor = true;\n }\n\n // Capture index range BEFORE skill body injection so injected\n // HumanMessages are excluded from the assistant's token distribution.\n const endMessageIndex = messages.length;\n\n if (pendingSkillNames?.size != null && pendingSkillNames.size > 0) {\n const skipSkillBodyNames = options?.skipSkillBodyNames;\n for (const skillName of pendingSkillNames) {\n if (skipSkillBodyNames != null && skipSkillBodyNames.has(skillName)) {\n continue;\n }\n const body = skills?.get(skillName) ?? '';\n if (body) {\n messages.push(\n withMessageRole(\n new HumanMessage({\n content: body,\n additional_kwargs: {\n role: 'user',\n isMeta: true,\n source: 'skill',\n skillName,\n },\n }),\n 'user'\n )\n );\n }\n }\n }\n\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 let tokenCount = indexTokenCountMap[originalIndex];\n\n if (tokenCount === undefined) {\n continue;\n }\n\n /**\n * Coverage mode deliberately leaves the count alone, even though the entry\n * holding the block is charged for summary text that `formatAssistantMessage`\n * filters out and `summary.tokenCount` accounts separately.\n *\n * Discounting it needs the summary's cost in the same units as\n * `indexTokenCountMap`, and that figure is not obtainable here: this\n * function receives no tokenizer, and a count recorded at write time is in\n * the writing run's units — `Run.create` derives its counter from the model\n * in play, and a consumer may supply its own — so a conversation continued\n * on a different model would subtract across encodings. Attempts to proxy\n * it (character ratios, provider identity) all under-count some shape,\n * which risks an over-context request; over-counting merely prunes early.\n * Fixing it properly means passing the reader a tokenizer, which is a\n * consumer-facing change and out of scope here.\n */\n if (\n summaryBoundary?.mode === 'positional' &&\n originalIndex === summaryBoundary.messageIndex &&\n Array.isArray(payload[originalIndex].content)\n ) {\n const content = payload[originalIndex]\n .content as MessageContentComplex[];\n const { contentIndex } = summaryBoundary;\n if (contentIndex >= 0 && contentIndex < content.length - 1) {\n let totalCharLen = 0;\n let remainingCharLen = 0;\n /**\n * The ratio applies only when *every* part of the entry is one whose\n * token cost tracks its character length. A single ineligible part\n * cancels the discount, whichever side of the boundary it sits on.\n *\n * Both sides can break it, in opposite directions. A retained image has\n * its fixed cost scaled away, collapsing the entry. A removed base64\n * payload inflates the denominator — serializing to a huge length while\n * the counter charges a fixed estimate — dragging retained text below\n * its real cost. Either way the request can exceed the window.\n *\n * Telling a text-bearing tool payload from a media-bearing one means\n * recursing into arbitrary nested output, which has already missed a\n * level twice here. Cancelling instead keeps the original count: an\n * over-count that prunes early rather than overflowing. Entries of\n * plain text and reasoning — the common shape — still proportion.\n */\n let everyRetainedPartMeasurable = true;\n for (let p = 0; p < content.length; p++) {\n const part = content[p];\n const retained = p > contentIndex;\n\n if (isDroppedByFormatting(part)) {\n /** Removed summary text is real removed content: it is read as\n * plain text and belongs in the denominator. */\n if (!retained && part.type === ContentTypes.SUMMARY) {\n totalCharLen += contentPartCharLength(part);\n }\n continue;\n }\n\n const charLen = contentPartCharLength(part);\n if (!isCharRatioEligible(part) || (retained && charLen === 0)) {\n everyRetainedPartMeasurable = false;\n break;\n }\n totalCharLen += charLen;\n if (retained) {\n remainingCharLen += charLen;\n }\n }\n if (totalCharLen > 0 && everyRetainedPartMeasurable) {\n const original = tokenCount;\n tokenCount = Math.max(\n 1,\n Math.round(tokenCount * (remainingCharLen / totalCharLen))\n );\n boundaryTokenAdjustment = {\n original,\n adjusted: tokenCount,\n remainingChars: remainingCharLen,\n totalChars: totalCharLen,\n };\n }\n }\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 const measured = serializeStructuredValueBounded(\n args,\n 0\n ).originalChars;\n len +=\n measured === Number.MAX_SAFE_INTEGER\n ? HARD_MAX_TOOL_RESULT_CHARS\n : Math.min(measured, HARD_MAX_TOOL_RESULT_CHARS);\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 summary: summaryBoundary\n ? { text: summaryBoundary.text, tokenCount: summaryBoundary.tokenCount }\n : undefined,\n boundaryTokenAdjustment,\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/** Checks whether a BaseMessage is a tool-role message. */\nconst isToolMessage = (m: BaseMessage): boolean =>\n m instanceof ToolMessage || ('role' in m && (m as any).role === 'tool');\n\nconst PORTABLE_FOLDED_MEDIA_TYPES = new Set(['image', 'image_url']);\nconst MAX_FOLDED_BLOCK_CHARS = 8_000;\nconst MAX_FOLDED_CONTEXT_CHARS = HARD_MAX_TOOL_RESULT_CHARS;\nconst MAX_FOLDED_CONTEXT_WORK = 100_000;\nconst FOLDED_CONTEXT_TRUNCATION_NOTICE =\n '… [additional folded context omitted]';\nconst syntheticProviderContextMessages = new WeakSet<BaseMessage>();\n\ntype FoldContextBudget = {\n remainingChars: number;\n remainingWork: number;\n truncated: boolean;\n};\n\nfunction createFoldContextBudget(): FoldContextBudget {\n return {\n remainingChars: MAX_FOLDED_CONTEXT_CHARS,\n remainingWork: MAX_FOLDED_CONTEXT_WORK,\n truncated: false,\n };\n}\n\nfunction readFoldedDataProperty(value: unknown, key: string): unknown {\n if (value == null || typeof value !== 'object') {\n return undefined;\n }\n try {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n return descriptor != null && 'value' in descriptor\n ? descriptor.value\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Adds one logical line without first concatenating caller-controlled strings.\n * The shared budget covers every synthetic message emitted by one transform,\n * so many individually bounded blocks cannot build an unbounded aggregate.\n */\nfunction appendFoldedLine(\n textChunks: string[],\n budget: FoldContextBudget,\n pieces: readonly string[]\n): boolean {\n if (budget.remainingChars <= 0) {\n budget.truncated = true;\n return false;\n }\n\n const separatorChars = textChunks.length > 0 ? 1 : 0;\n const available = budget.remainingChars - separatorChars;\n if (available <= 0) {\n budget.remainingChars = 0;\n budget.truncated = true;\n return false;\n }\n\n let totalChars = 0;\n for (const piece of pieces) {\n totalChars = Math.min(Number.MAX_SAFE_INTEGER, totalChars + piece.length);\n }\n if (totalChars <= available) {\n const line = pieces.join('');\n textChunks.push(line);\n budget.remainingChars -= separatorChars + line.length;\n return true;\n }\n\n const notice = FOLDED_CONTEXT_TRUNCATION_NOTICE.slice(0, available);\n let remainingHeadChars = Math.max(0, available - notice.length);\n const boundedPieces: string[] = [];\n for (const piece of pieces) {\n if (remainingHeadChars <= 0) {\n break;\n }\n const retained = piece.slice(0, remainingHeadChars);\n boundedPieces.push(retained);\n remainingHeadChars -= retained.length;\n }\n boundedPieces.push(notice);\n textChunks.push(boundedPieces.join(''));\n budget.remainingChars = 0;\n budget.truncated = true;\n return false;\n}\n\nfunction consumeFoldedWork(\n textChunks: string[],\n budget: FoldContextBudget\n): boolean {\n if (budget.remainingChars <= 0) {\n return false;\n }\n if (budget.remainingWork-- > 0) {\n return true;\n }\n appendFoldedLine(textChunks, budget, [FOLDED_CONTEXT_TRUNCATION_NOTICE]);\n budget.remainingChars = 0;\n budget.truncated = true;\n return false;\n}\n\nfunction serializeFoldedValue(value: unknown): string {\n const compacted = compactToolContent(value, MAX_FOLDED_BLOCK_CHARS).content;\n return typeof compacted === 'string'\n ? compacted\n : serializeStructuredValueBounded(compacted, MAX_FOLDED_BLOCK_CHARS)\n .content;\n}\n\nfunction markSyntheticProviderContext<T extends BaseMessage>(message: T): T {\n syntheticProviderContextMessages.add(message);\n return message;\n}\n\nfunction appendSyntheticProviderContextMessage(\n result: BaseMessage[],\n parts: MessageContentComplex[]\n): boolean {\n if (parts.length === 0) {\n return false;\n }\n result.push(\n markSyntheticProviderContext(\n withMessageRole(\n new HumanMessage({ content: toLangChainContent(parts) }),\n 'user'\n )\n )\n );\n return true;\n}\n\n/**\n * Identifies provider-context placeholders created by this module without\n * trusting user-controlled content prefixes or leaking marker metadata onto\n * the provider wire.\n */\nexport function isSyntheticProviderContextMessage(\n message: BaseMessage\n): boolean {\n return syntheticProviderContextMessages.has(message);\n}\n\n/** Flushes accumulated text chunks into `parts` as a single text block. */\nfunction flushTextChunks(\n textChunks: string[],\n parts: MessageContentComplex[]\n): void {\n if (textChunks.length === 0) {\n return;\n }\n parts.push({\n type: ContentTypes.TEXT,\n text: textChunks.join('\\n'),\n } as MessageContentComplex);\n textChunks.length = 0;\n}\n\n/**\n * Appends a single message's content to the running `textChunks` / `parts`\n * accumulators. Portable image blocks are shallow-copied into `parts` so\n * binary data never becomes text tokens. Provider-specific media/resource\n * blocks are retained as bounded text so a folded cross-provider history\n * cannot contain an unsupported native block or JSON-expand without limit.\n *\n * When `content` is an array containing tool_use blocks, `tool_calls` is NOT\n * additionally serialized (avoiding double output). `tool_calls` is used as\n * a fallback when `content` is a plain string or an array with no tool_use.\n */\nfunction appendMessageContent(\n msg: BaseMessage,\n role: string,\n textChunks: string[],\n parts: MessageContentComplex[],\n budget: FoldContextBudget\n): void {\n const { content } = msg;\n\n if (typeof content === 'string') {\n if (content && consumeFoldedWork(textChunks, budget)) {\n appendFoldedLine(textChunks, budget, [`${role}: `, content]);\n }\n appendToolCalls(msg, role, textChunks, budget);\n return;\n }\n\n if (!Array.isArray(content)) {\n appendToolCalls(msg, role, textChunks, budget);\n return;\n }\n\n let hasToolUseBlock = false;\n\n for (const block of content as ExtendedMessageContent[]) {\n if (!consumeFoldedWork(textChunks, budget)) {\n hasToolUseBlock = true;\n break;\n }\n const blockTypeValue = readFoldedDataProperty(block, 'type');\n const blockType =\n typeof blockTypeValue === 'string' ? blockTypeValue : undefined;\n\n if (\n blockType !== 'tool_use' &&\n blockType !== 'tool_call' &&\n blockType !== 'tool_result' &&\n isAtomicToolContentBlock(block)\n ) {\n if (PORTABLE_FOLDED_MEDIA_TYPES.has(blockType ?? '')) {\n const blockChars = getToolContentCharLength([block]);\n if (blockChars > budget.remainingChars) {\n appendFoldedLine(textChunks, budget, [\n `${role}: [${blockType ?? 'media'} omitted: folded context limit]`,\n ]);\n continue;\n }\n flushTextChunks(textChunks, parts);\n parts.push({ ...block } as MessageContentComplex);\n budget.remainingChars -= blockChars;\n } else {\n appendFoldedLine(textChunks, budget, [\n `${role}: [${blockType ?? 'media'}] `,\n serializeFoldedValue(block),\n ]);\n }\n continue;\n }\n\n if (blockType === 'tool_use') {\n hasToolUseBlock = true;\n const name = readFoldedDataProperty(block, 'name');\n const input = readFoldedDataProperty(block, 'input');\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_use] ${typeof name === 'string' ? name : ''} `,\n serializeFoldedValue(input ?? {}),\n ]);\n continue;\n }\n\n // A `tool_call` content block appears either as the v1 standard shape\n // (`{ name, args }` at top level, which `@langchain/aws` maps to a Converse\n // toolUse) or this repo's `ToolCallContent` (`{ tool_call: { name, args,\n // output } }`, from `convertMessagesToContent` / persisted history). Handle\n // both, and emit any embedded output, so the name/args/result survive.\n if (blockType === 'tool_call') {\n hasToolUseBlock = true;\n const nested = readFoldedDataProperty(block, 'tool_call');\n const nestedName = readFoldedDataProperty(nested, 'name');\n const topLevelName = readFoldedDataProperty(block, 'name');\n let name = '';\n if (typeof nestedName === 'string') {\n name = nestedName;\n } else if (typeof topLevelName === 'string') {\n name = topLevelName;\n }\n const nestedArgs = readFoldedDataProperty(nested, 'args');\n const topLevelArgs = readFoldedDataProperty(block, 'args');\n const rawArgs = nestedArgs ?? topLevelArgs ?? {};\n const argsText =\n typeof rawArgs === 'string' ? rawArgs : serializeFoldedValue(rawArgs);\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_use] ${name}${argsText ? ' ' : ''}`,\n argsText,\n ]);\n const output = readFoldedDataProperty(nested, 'output');\n if (output != null && output !== '') {\n appendFoldedLine(textChunks, budget, [\n 'Tool: ',\n typeof output === 'string' ? output : serializeFoldedValue(output),\n ]);\n }\n continue;\n }\n\n // A `tool_result` content block (e.g. an AIMessage(tool_call) followed by a\n // user message carrying the result). Preserve nested image blocks as-is\n // instead of JSON-stringifying them through the generic fallback.\n if (blockType === 'tool_result') {\n hasToolUseBlock = true;\n const inner = readFoldedDataProperty(block, 'content') as\n | ToolResultContent['content']\n | undefined;\n if (typeof inner === 'string') {\n if (inner) {\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_result] `,\n inner,\n ]);\n }\n } else if (Array.isArray(inner)) {\n for (const innerBlock of inner as Array<\n string | ExtendedMessageContent\n >) {\n if (!consumeFoldedWork(textChunks, budget)) {\n break;\n }\n if (typeof innerBlock === 'string') {\n if (innerBlock) {\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_result] `,\n innerBlock,\n ]);\n }\n } else {\n const innerTypeValue = readFoldedDataProperty(innerBlock, 'type');\n const innerType =\n typeof innerTypeValue === 'string' ? innerTypeValue : undefined;\n if (\n isAtomicToolContentBlock(innerBlock) &&\n PORTABLE_FOLDED_MEDIA_TYPES.has(innerType ?? '')\n ) {\n const blockChars = getToolContentCharLength([innerBlock]);\n if (blockChars <= budget.remainingChars) {\n flushTextChunks(textChunks, parts);\n parts.push({ ...innerBlock } as MessageContentComplex);\n budget.remainingChars -= blockChars;\n } else {\n appendFoldedLine(textChunks, budget, [\n `${role}: [${innerType ?? 'media'} omitted: folded context limit]`,\n ]);\n }\n } else {\n const textValue = readFoldedDataProperty(innerBlock, 'text');\n const inputValue = readFoldedDataProperty(innerBlock, 'input');\n const innerText = textValue ?? inputValue;\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_result] `,\n typeof innerText === 'string' && innerText\n ? innerText\n : serializeFoldedValue(innerBlock),\n ]);\n }\n }\n }\n } else if (inner != null) {\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_result] `,\n serializeFoldedValue(inner),\n ]);\n }\n continue;\n }\n\n const text =\n readFoldedDataProperty(block, 'text') ??\n readFoldedDataProperty(block, 'input');\n if (typeof text === 'string' && text) {\n appendFoldedLine(textChunks, budget, [`${role}: `, text]);\n continue;\n }\n\n // Fallback: serialize unrecognized block types to preserve context\n if (blockType != null && blockType !== '') {\n appendFoldedLine(textChunks, budget, [\n `${role}: [${blockType}] `,\n serializeFoldedValue(block),\n ]);\n }\n }\n\n // If content array had no tool_use blocks, fall back to tool_calls metadata\n // (handles edge case: empty content array with tool_calls populated)\n if (!hasToolUseBlock) {\n appendToolCalls(msg, role, textChunks, budget);\n }\n}\n\nfunction appendToolCalls(\n msg: BaseMessage,\n role: string,\n textChunks: string[],\n budget: FoldContextBudget\n): void {\n if (role !== 'AI') {\n return;\n }\n const aiMsg = msg as AIMessage;\n if (aiMsg.tool_calls && aiMsg.tool_calls.length > 0) {\n for (const tc of aiMsg.tool_calls) {\n if (!consumeFoldedWork(textChunks, budget)) {\n break;\n }\n const name = readFoldedDataProperty(tc, 'name');\n const args = readFoldedDataProperty(tc, 'args');\n appendFoldedLine(textChunks, budget, [\n `AI: [tool_call] ${typeof name === 'string' ? name : ''}(`,\n serializeFoldedValue(args),\n ')',\n ]);\n }\n return;\n }\n // Fall back to raw provider tool calls kept only in additional_kwargs.\n const rawToolCalls = aiMsg.additional_kwargs.tool_calls;\n if (!Array.isArray(rawToolCalls)) {\n return;\n }\n for (const tc of rawToolCalls) {\n if (!consumeFoldedWork(textChunks, budget)) {\n break;\n }\n const fn = readFoldedDataProperty(tc, 'function');\n if (fn == null) {\n continue;\n }\n const name = readFoldedDataProperty(fn, 'name');\n const args = readFoldedDataProperty(fn, 'arguments');\n appendFoldedLine(textChunks, budget, [\n `AI: [tool_call] ${typeof name === 'string' ? name : ''}(`,\n typeof args === 'string' ? args : '',\n ')',\n ]);\n }\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 * @param config - Optional RunnableConfig for structured agent logging\n * @param runStartIndex - Index in `messages` where the CURRENT run's own\n * appended AI/Tool messages begin (i.e. anything at this index or later\n * was just produced by this run's own iterations, not historical\n * context). When provided, AI messages at or after this index are\n * never converted to `[Previous agent context]` placeholders — Claude\n * can validly skip a thinking block before a tool_use (cf. PR #116),\n * so the agent's own in-run iterations must not be misclassified as\n * foreign history. Without the signal the function falls back to its\n * prior heuristic (`chainHasThinkingBlock`), preserving backward\n * compatibility for callers that don't yet pass the boundary.\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 config?: RunnableConfig,\n runStartIndex?: number\n): BaseMessage[] {\n if (messages.length === 0) {\n return messages;\n }\n\n // Find the last HumanMessage. Only the trailing sequence after it needs\n // validation — earlier messages are history already accepted by the provider.\n let lastHumanIndex = -1;\n for (let k = messages.length - 1; k >= 0; k--) {\n const m = messages[k];\n if (\n m instanceof HumanMessage ||\n ('role' in m && (m as any).role === 'user')\n ) {\n lastHumanIndex = k;\n break;\n }\n }\n\n if (lastHumanIndex === messages.length - 1) {\n return messages;\n }\n\n const result: BaseMessage[] =\n lastHumanIndex >= 0 ? messages.slice(0, lastHumanIndex + 1) : [];\n const foldBudget = createFoldContextBudget();\n let i = lastHumanIndex + 1;\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 for (const c of aiMsg.content as ExtendedMessageContent[]) {\n if (typeof c !== 'object') {\n continue;\n }\n const type = readFoldedDataProperty(c, 'type');\n if (type === 'tool_use') {\n hasToolUse = true;\n } else if (\n type === ContentTypes.THINKING ||\n type === ContentTypes.REASONING_CONTENT ||\n type === ContentTypes.REASONING ||\n type === 'redacted_thinking'\n ) {\n hasThinkingBlock = true;\n }\n if (hasToolUse && hasThinkingBlock) {\n break;\n }\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 // Current-run boundary check: anything at or after `runStartIndex`\n // is the current run's own work — preserve it. Claude is allowed\n // to skip a thinking block before a tool_use (cf. PR #116 in the\n // agents repo), so the agent's own first-iteration AI message can\n // legitimately have tool_calls without reasoning. Converting it to\n // a `[Previous agent context]` placeholder pollutes the next\n // iteration's prompt — the LLM sees the placeholder, treats it as\n // suspicious injected content, ignores its own real prior tool\n // result, and re-runs the tool to verify (which then often fails\n // because subsequent calls land in fresh sandboxes without the\n // file). Skip the conversion when we know this is in-run.\n if (runStartIndex !== undefined && i >= runStartIndex) {\n result.push(msg);\n i++;\n continue;\n }\n\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 // Build structured content in a single pass over the AI + following\n // ToolMessages — preserves image blocks as-is to avoid serializing\n // binary data as text (which caused 174× token amplification).\n const parts: MessageContentComplex[] = [];\n const textChunks: string[] = [];\n appendFoldedLine(textChunks, foldBudget, ['[Previous agent context]']);\n\n appendMessageContent(msg, 'AI', textChunks, parts, foldBudget);\n\n let j = i + 1;\n while (j < messages.length && isToolMessage(messages[j])) {\n appendMessageContent(\n messages[j],\n 'Tool',\n textChunks,\n parts,\n foldBudget\n );\n j++;\n }\n\n flushTextChunks(textChunks, parts);\n if (appendSyntheticProviderContextMessage(result, parts)) {\n emitAgentLog(\n config,\n 'warn',\n 'format',\n 'ensureThinkingBlockInMessages: injecting [Previous agent context] HumanMessage' +\n ` (${parts.length} msgs at index ${i}, no thinking block in chain)`\n );\n }\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/** Whether a message carries tool content a tool-less agent cannot legally\n * send. Covers every representation a provider converter will serialize back\n * into a request: a ToolMessage, parsed `AIMessage.tool_calls`, raw\n * `additional_kwargs.tool_calls` (OpenAI keeps calls here when the parsed\n * array is empty), and `tool_use` / `tool_call` / `tool_result` content\n * blocks (`@langchain/aws` and the Anthropic converter map these to Converse\n * `toolUse` / `toolResult`). Missing the parent AI message is not just a\n * passthrough: folding its ToolMessage alone would leave an orphan\n * `assistant(tool_calls) -> user(...)` sequence. */\nfunction messageHasToolContent(msg: BaseMessage): boolean {\n if (isToolMessage(msg)) {\n return true;\n }\n const aiMsg = msg as AIMessage;\n if (aiMsg.tool_calls != null && aiMsg.tool_calls.length > 0) {\n return true;\n }\n const rawToolCalls = aiMsg.additional_kwargs.tool_calls;\n if (Array.isArray(rawToolCalls) && rawToolCalls.length > 0) {\n return true;\n }\n if (Array.isArray(msg.content)) {\n for (const block of msg.content as ExtendedMessageContent[]) {\n const type = readFoldedDataProperty(block, 'type');\n if (\n typeof block === 'object' &&\n (type === 'tool_use' || type === 'tool_call' || type === 'tool_result')\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/** Whether a message carries a tool RESULT: a ToolMessage, or a message whose\n * content includes a `tool_result` block (the shape when a call/result pair is\n * split as `AIMessage(tool_call)` + `HumanMessage(tool_result)`). Such a result\n * belongs with the preceding tool call, so it is absorbed into the same fold\n * and labelled as tool output. */\nfunction isToolResultMessage(msg: BaseMessage): boolean {\n if (isToolMessage(msg)) {\n return true;\n }\n if (Array.isArray(msg.content)) {\n return (msg.content as ExtendedMessageContent[]).some(\n (block) =>\n typeof block === 'object' &&\n readFoldedDataProperty(block, 'type') === 'tool_result'\n );\n }\n return false;\n}\n\n/**\n * Folds tool_use / tool_result content into plain text for an agent that binds\n * no tools.\n *\n * In a multi-agent graph, a tool-less destination still inherits the prior\n * agent's conversation history, which can contain toolUse/toolResult blocks.\n * Because it binds no tools, the model is invoked with no tool schema — and\n * Bedrock's Converse API rejects any request that carries toolUse/toolResult\n * blocks without a top-level toolConfig (\"The toolConfig field must be defined\n * when using toolUse and toolResult content blocks\"). Adding a dummy toolConfig\n * is not an option: AWS requires at least one tool, and it would expose a\n * capability the destination was intentionally denied.\n *\n * Each tool-call turn plus its trailing tool results (ToolMessages or\n * `tool_result` content blocks) is collapsed into a single `[Previous tool\n * interaction]` HumanMessage that preserves the tool name, arguments and result\n * as text (image blocks are kept as-is). Runs in a single pass: non-tool\n * messages pass through, `result` is allocated lazily on the first fold, and the\n * original array is returned unchanged when it holds no tool content (the common\n * fresh-tool-less-agent case).\n */\nexport function foldToolBlocksForToollessAgent(\n messages: BaseMessage[],\n config?: RunnableConfig\n): BaseMessage[] {\n let result: BaseMessage[] | null = null;\n let foldedCount = 0;\n const foldBudget = createFoldContextBudget();\n let i = 0;\n while (i < messages.length) {\n const msg = messages[i];\n if (!messageHasToolContent(msg)) {\n result?.push(msg);\n i++;\n continue;\n }\n\n /** First fold — copy the untouched prefix once, then append from here. */\n if (result === null) {\n result = messages.slice(0, i);\n }\n\n const parts: MessageContentComplex[] = [];\n const textChunks: string[] = [];\n appendFoldedLine(textChunks, foldBudget, ['[Previous tool interaction]']);\n appendMessageContent(\n msg,\n isToolResultMessage(msg) ? 'Tool' : 'AI',\n textChunks,\n parts,\n foldBudget\n );\n foldedCount++;\n\n let j = i + 1;\n while (j < messages.length && isToolResultMessage(messages[j])) {\n appendMessageContent(messages[j], 'Tool', textChunks, parts, foldBudget);\n foldedCount++;\n j++;\n }\n\n flushTextChunks(textChunks, parts);\n appendSyntheticProviderContextMessage(result, parts);\n i = j;\n }\n\n if (result === null) {\n return messages;\n }\n\n emitAgentLog(\n config,\n 'warn',\n 'format',\n `foldToolBlocksForToollessAgent: folded ${foldedCount} tool message(s) into text for a tool-less agent`\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"],"mappings":"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"}
1
+ {"version":3,"file":"format.mjs","names":["isToolMessage"],"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} from '@langchain/core/messages';\nimport type {\n MessageContent,\n MessageContentImageUrl,\n} from '@langchain/core/messages';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type {\n BedrockReasoningContentText,\n ExtendedMessageContent,\n GoogleReasoningContentText,\n MessageContentComplex,\n ReasoningContentText,\n SummaryContentBlock,\n SummaryCoverage,\n ThinkingContentText,\n ToolCallContent,\n ToolResultContent,\n ToolCallPart,\n TPayload,\n TMessage,\n} from '@/types';\nimport {\n compactToolContent,\n getToolContentCharLength,\n isAtomicToolContentBlock,\n serializeStructuredValueBounded,\n} from '@/utils/toolContent';\nimport { normalizeAnthropicToolCallId } from '@/llm/anthropic/utils/message_inputs';\nimport { toLangChainContent, toLangChainMessageFields } from './langchain';\nimport { HARD_MAX_TOOL_RESULT_CHARS } from '@/utils/truncation';\nimport { Providers, ContentTypes, Constants } from '@/common';\nimport { emitAgentLog } from '@/utils/events';\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\nexport type LangChainMessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\nexport type RoleBearingMessage<T extends BaseMessage = BaseMessage> = T & {\n role: LangChainMessageRole;\n};\n\nexport function withMessageRole<T extends BaseMessage>(\n message: T,\n role: LangChainMessageRole\n): RoleBearingMessage<T> {\n const roleMessage = message as T & { role?: LangChainMessageRole };\n if (roleMessage.role === role) {\n return roleMessage as RoleBearingMessage<T>;\n }\n Object.defineProperty(roleMessage, 'role', {\n value: role,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n return roleMessage as RoleBearingMessage<T>;\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 | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<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 withMessageRole(\n new HumanMessage(toLangChainMessageFields(mediaMessage)),\n 'user'\n );\n }\n\n if (!langChain) {\n return formattedMessage;\n }\n\n if (role === 'user') {\n return withMessageRole(\n new HumanMessage(toLangChainMessageFields(formattedMessage)),\n 'user'\n );\n } else if (role === 'assistant') {\n return withMessageRole(\n new AIMessage(toLangChainMessageFields(formattedMessage)),\n 'assistant'\n );\n } else {\n return withMessageRole(\n new SystemMessage(toLangChainMessageFields(formattedMessage)),\n 'system'\n );\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<\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<SystemMessage>\n> => {\n return messages.map((msg) => {\n const formatted = formatMessage({\n ...formatOptions,\n message: msg,\n langChain: true,\n });\n return formatted as\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<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\ninterface FormatAssistantMessageOptions {\n preserveUnpairedServerToolUses?: boolean;\n preserveReasoningContent?: boolean;\n provider?: Providers;\n sourceMessageId?: string;\n}\n\ninterface FormatAgentMessagesOptions {\n provider?: Providers;\n /** Reconstruct hidden `reasoning_content` from `THINK` parts onto prior\n * tool-call messages. Explicit opt-in for OpenAI-compatible endpoints that\n * replay reasoning across turns; defaults to on for DeepSeek thinking-mode. */\n preserveReasoningContent?: boolean;\n /** Skill names already primed fresh this turn (manual/always-apply). Their\n * historical `skill` tool_calls are not reconstructed into a HumanMessage,\n * so the same SKILL.md body is not injected twice in one request. */\n skipSkillBodyNames?: Set<string>;\n}\n\nfunction extractReasoningContent(\n part: MessageContentComplex | undefined | null\n): string {\n if (part == null || typeof part !== 'object') {\n return '';\n }\n if (part.type === ContentTypes.THINK) {\n const think = (part as ReasoningContentText).think;\n return typeof think === 'string' ? think : '';\n }\n if (part.type === ContentTypes.THINKING) {\n const thinking = (part as ThinkingContentText).thinking;\n return typeof thinking === 'string' ? thinking : '';\n }\n if (part.type === ContentTypes.REASONING) {\n const reasoning = (part as GoogleReasoningContentText).reasoning;\n return typeof reasoning === 'string' ? reasoning : '';\n }\n if (part.type === ContentTypes.REASONING_CONTENT) {\n const reasoningText = (part as BedrockReasoningContentText).reasoningText;\n return typeof reasoningText.text === 'string' ? reasoningText.text : '';\n }\n return '';\n}\n\ntype ServerToolInput = Exclude<NonNullable<ToolCallPart['args']>, string>;\n\nfunction parseServerToolInput(args: ToolCallPart['args']): ServerToolInput {\n if (typeof args === 'string') {\n try {\n const parsed = JSON.parse(args) as unknown;\n return parsed != null &&\n typeof parsed === 'object' &&\n !Array.isArray(parsed)\n ? (parsed as ServerToolInput)\n : {};\n } catch {\n return {};\n }\n }\n return args != null && typeof args === 'object' ? args : {};\n}\n\nfunction getTextContent(part: MessageContentComplex): string {\n const { text } = part as { text?: unknown };\n return typeof text === 'string' ? text : '';\n}\n\nfunction hasMeaningfulAssistantContent(part: MessageContentComplex): boolean {\n if (part.type === ContentTypes.TEXT) {\n return getTextContent(part).trim().length > 0;\n }\n if (\n part.type === ContentTypes.TOOL_CALL ||\n part.type === ContentTypes.ERROR ||\n part.type === ContentTypes.AGENT_UPDATE ||\n part.type === ContentTypes.SUMMARY ||\n part.type === ContentTypes.ACTIVITY_LABEL\n ) {\n return false;\n }\n if (\n part.type === ContentTypes.THINK ||\n part.type === ContentTypes.THINKING ||\n part.type === ContentTypes.REASONING ||\n part.type === ContentTypes.REASONING_CONTENT ||\n part.type === 'redacted_thinking'\n ) {\n return extractReasoningContent(part).trim().length > 0;\n }\n return part.type != null && part.type !== '';\n}\n\nfunction getToolUseId(part: MessageContentComplex): string | undefined {\n if (!('tool_use_id' in part) || typeof part.tool_use_id !== 'string') {\n return undefined;\n }\n return part.tool_use_id;\n}\n\nfunction isValidServerToolResult(part: MessageContentComplex): boolean {\n const toolUseId = getToolUseId(part);\n if (\n toolUseId?.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX) !== true ||\n !('content' in part)\n ) {\n return false;\n }\n const { content } = part as { content?: unknown };\n return (\n Array.isArray(content) ||\n (content != null &&\n typeof content === 'object' &&\n 'type' in content &&\n (content as { type?: unknown }).type === 'web_search_tool_result_error')\n );\n}\n\nfunction getToolCallId(part: MessageContentComplex): string | undefined {\n if (part.type !== ContentTypes.TOOL_CALL) {\n return undefined;\n }\n const id = part.tool_call?.id;\n return typeof id === 'string' && id !== '' ? id : undefined;\n}\n\nfunction hasToolCallOutput(part: MessageContentComplex): boolean {\n if (part.type !== ContentTypes.TOOL_CALL) {\n return false;\n }\n const output = part.tool_call?.output;\n return output != null && output !== '';\n}\n\nfunction formatToolCallOutput(\n output: ToolCallPart['output'] | undefined\n): MessageContent {\n if (output == null) {\n return '';\n }\n return compactToolContent(output, HARD_MAX_TOOL_RESULT_CHARS).content;\n}\n\n/**\n * Content for the synthetic assistant turn that separates a trailing steer\n * from the next user turn. Non-empty by necessity — see the push site.\n */\nconst STEER_ANCHOR_PLACEHOLDER = '_';\n\n/**\n * True when an assistant message replayed as a steer and nothing followed it,\n * so the emitted run ends on the steer's `HumanMessage`.\n */\nfunction endsWithSteerMessage(\n formatted: Array<RoleBearingMessage<BaseMessage>>\n): boolean {\n if (formatted.length === 0) {\n return false;\n }\n return formatted[formatted.length - 1].additional_kwargs.source === 'steer';\n}\n\n/**\n * Helper function to format an assistant message\n * @param message The message to format\n * @param options Optional formatting options\n * @returns Array of formatted messages\n */\nfunction formatAssistantMessage(\n message: Partial<TMessage>,\n options?: FormatAssistantMessageOptions\n): Array<\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<ToolMessage>\n | RoleBearingMessage<HumanMessage>\n> {\n const formattedMessages: Array<\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<ToolMessage>\n | RoleBearingMessage<HumanMessage>\n > = [];\n const appendFormattedMessage = (\n formattedMessage: (typeof formattedMessages)[number]\n ): void => {\n stampSourceMessageIdentity(\n formattedMessage,\n options?.sourceMessageId,\n formattedMessages.length\n );\n formattedMessages.push(formattedMessage);\n };\n let currentContent: MessageContentComplex[] = [];\n let lastAIMessage: RoleBearingMessage<AIMessage> | null = null;\n let hasReasoning = false;\n let pendingReasoningContent = '';\n const emittedServerToolUseIds = new Set<string>();\n const pendingServerToolUses = new Map<string, MessageContentComplex>();\n const shouldPreserveReasoningContent =\n options?.preserveReasoningContent === true;\n const serverToolResultIds = new Set<string>();\n const preferredToolCallParts = new Map<string, MessageContentComplex>();\n\n const takePendingReasoningContent = (): string | undefined => {\n if (!shouldPreserveReasoningContent || !pendingReasoningContent) {\n return undefined;\n }\n const reasoningContent = pendingReasoningContent;\n pendingReasoningContent = '';\n return reasoningContent;\n };\n\n const createAIMessage = (\n content: MessageContent\n ): RoleBearingMessage<AIMessage> => {\n const reasoningContent = takePendingReasoningContent();\n return withMessageRole(\n new AIMessage({\n content,\n ...(reasoningContent != null && {\n additional_kwargs: { reasoning_content: reasoningContent },\n }),\n }),\n 'assistant'\n );\n };\n\n const attachPendingReasoningContent = (aiMessage: AIMessage): void => {\n const reasoningContent = takePendingReasoningContent();\n if (reasoningContent == null) {\n return;\n }\n aiMessage.additional_kwargs.reasoning_content =\n typeof aiMessage.additional_kwargs.reasoning_content === 'string'\n ? `${aiMessage.additional_kwargs.reasoning_content}${reasoningContent}`\n : reasoningContent;\n };\n\n const flushPendingServerToolUse = (toolUseId: string): void => {\n for (const [id, content] of pendingServerToolUses) {\n pendingServerToolUses.delete(id);\n if (id === toolUseId) {\n currentContent.push(content);\n emittedServerToolUseIds.add(id);\n return;\n }\n }\n };\n\n if (Array.isArray(message.content)) {\n const contentParts = message.content as Array<\n MessageContentComplex | undefined | null\n >;\n\n for (const part of contentParts) {\n if (part == null) {\n continue;\n }\n if (isValidServerToolResult(part)) {\n serverToolResultIds.add(getToolUseId(part) ?? '');\n }\n if (options?.provider === Providers.ANTHROPIC) {\n const toolCallId = getToolCallId(part);\n if (toolCallId == null) {\n continue;\n }\n const preferredPart = preferredToolCallParts.get(toolCallId);\n if (\n preferredPart == null ||\n (!hasToolCallOutput(preferredPart) && hasToolCallOutput(part))\n ) {\n preferredToolCallParts.set(toolCallId, part);\n }\n }\n }\n\n for (const part of contentParts) {\n if (part == null) {\n continue;\n }\n const toolUseId = getToolUseId(part);\n if (toolUseId != null) {\n const isServerToolResult = isValidServerToolResult(part);\n if (\n toolUseId.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX) &&\n !isServerToolResult\n ) {\n continue;\n }\n flushPendingServerToolUse(toolUseId);\n if (isServerToolResult) {\n currentContent.push(part);\n continue;\n }\n } else if (hasMeaningfulAssistantContent(part)) {\n for (const id of pendingServerToolUses.keys()) {\n if (!serverToolResultIds.has(id)) {\n pendingServerToolUses.delete(id);\n }\n }\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 if (\n currentContent.some((content) => content.type !== ContentTypes.TEXT)\n ) {\n currentContent.push(part);\n lastAIMessage = createAIMessage(toLangChainContent(currentContent));\n appendFormattedMessage(lastAIMessage);\n currentContent = [];\n continue;\n }\n let content = currentContent.reduce((acc, curr) => {\n if (curr.type === ContentTypes.TEXT) {\n return `${acc}${getTextContent(curr)}\\n`;\n }\n return acc;\n }, '');\n content = `${content}\\n${getTextContent(part)}`.trim();\n lastAIMessage = createAIMessage(content);\n appendFormattedMessage(lastAIMessage);\n currentContent = [];\n continue;\n }\n // Create a new AIMessage with this text and prepare for tool calls\n lastAIMessage = createAIMessage(getTextContent(part));\n appendFormattedMessage(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 const toolCallId = getToolCallId(part);\n if (\n options?.provider === Providers.ANTHROPIC &&\n toolCallId != null &&\n preferredToolCallParts.get(toolCallId) !== part\n ) {\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 (\n options?.provider === Providers.ANTHROPIC &&\n typeof _tool_call.id === 'string' &&\n _tool_call.id.startsWith(Constants.ANTHROPIC_SERVER_TOOL_PREFIX)\n ) {\n if (\n !serverToolResultIds.has(_tool_call.id) &&\n options.preserveUnpairedServerToolUses !== true\n ) {\n continue;\n }\n if (\n emittedServerToolUseIds.has(_tool_call.id) ||\n pendingServerToolUses.has(_tool_call.id)\n ) {\n continue;\n }\n pendingServerToolUses.set(_tool_call.id, {\n type: 'server_tool_use',\n id: _tool_call.id,\n name: _tool_call.name,\n input: parseServerToolInput(_args),\n } as MessageContentComplex);\n continue;\n }\n\n if (!lastAIMessage) {\n // \"Heal\" the payload by creating an AIMessage to precede the tool call\n lastAIMessage = createAIMessage('');\n appendFormattedMessage(lastAIMessage);\n } else {\n attachPendingReasoningContent(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 (\n options?.provider === Providers.ANTHROPIC &&\n Array.isArray(lastAIMessage.content)\n ) {\n const content = lastAIMessage.content as MessageContentComplex[];\n content.push({\n type: 'tool_use',\n id: normalizeAnthropicToolCallId(tool_call.id ?? ''),\n name: tool_call.name,\n input: args,\n } as MessageContentComplex);\n lastAIMessage.content = content as MessageContent;\n } else {\n if (!lastAIMessage.tool_calls) {\n lastAIMessage.tool_calls = [];\n }\n lastAIMessage.tool_calls.push(tool_call as ToolCall);\n }\n\n appendFormattedMessage(\n withMessageRole(\n new ToolMessage({\n tool_call_id: tool_call.id ?? '',\n name: tool_call.name,\n content: formatToolCallOutput(output),\n }),\n 'tool'\n )\n );\n } else if (\n part.type === ContentTypes.THINK ||\n part.type === ContentTypes.THINKING ||\n part.type === ContentTypes.REASONING ||\n part.type === ContentTypes.REASONING_CONTENT ||\n part.type === 'redacted_thinking'\n ) {\n hasReasoning = true;\n pendingReasoningContent += extractReasoningContent(part);\n continue;\n } else if (part.type === ContentTypes.STEER) {\n /*\n A mid-run steer: user speech persisted inline in the assistant message\n at the tool-batch boundary it was injected. Flush accumulated\n assistant content first so ordering is preserved, then replay the\n steer as a standalone user message — multimodal when the host stamped\n a pre-encoded `media` content array (attachment refs are re-encoded\n per turn host-side, like any other user media). `lastAIMessage` is\n reset AFTER the HumanMessage: a post-steer tool_call must mint a\n FRESH assistant anchor (the heal path) so its AIMessage lands after\n the user turn — attaching it to the pre-steer anchor would emit its\n ToolMessage after the HumanMessage while the call itself sat before\n it, an invalid provider ordering.\n */\n if (currentContent.length > 0) {\n if (\n currentContent.some((content) => content.type !== ContentTypes.TEXT)\n ) {\n lastAIMessage = createAIMessage(toLangChainContent(currentContent));\n appendFormattedMessage(lastAIMessage);\n } else {\n const flushed = currentContent\n .reduce((acc, curr) => `${acc}${getTextContent(curr)}\\n`, '')\n .trim();\n if (flushed.length > 0) {\n lastAIMessage = createAIMessage(flushed);\n appendFormattedMessage(lastAIMessage);\n }\n }\n currentContent = [];\n } else if (shouldPreserveReasoningContent && pendingReasoningContent) {\n /**\n * Reasoning directly preceding a steer has no `currentContent`\n * flush to consume it and the anchor resets below — emit an anchor\n * AIMessage now (createAIMessage folds the pending reasoning into\n * `additional_kwargs.reasoning_content`) or the persisted\n * assistant reasoning silently vanishes on replay.\n */\n lastAIMessage = createAIMessage('');\n appendFormattedMessage(lastAIMessage);\n }\n const steerPart = part as {\n steer?: string;\n media?: MessageContentComplex[];\n };\n const steerContent =\n Array.isArray(steerPart.media) && steerPart.media.length > 0\n ? toLangChainContent(steerPart.media)\n : (steerPart.steer ?? '');\n appendFormattedMessage(\n withMessageRole(\n new HumanMessage({\n content: steerContent as MessageContent,\n additional_kwargs: { role: 'user', source: 'steer' },\n }),\n 'user'\n )\n );\n lastAIMessage = null;\n /** The steer splits the assistant message: the post-steer segment\n * starts with fresh reasoning state (pre-steer reasoning was either\n * flushed above or intentionally dropped when not preserving). */\n hasReasoning = false;\n pendingReasoningContent = '';\n } else if (\n part.type === ContentTypes.ERROR ||\n part.type === ContentTypes.AGENT_UPDATE ||\n part.type === ContentTypes.SUMMARY ||\n part.type === ContentTypes.ACTIVITY_LABEL\n ) {\n continue;\n } else {\n if (part.type === ContentTypes.TEXT && !getTextContent(part).trim()) {\n continue;\n }\n currentContent.push(part);\n }\n }\n for (const content of pendingServerToolUses.values()) {\n currentContent.push(content);\n }\n }\n\n if (hasReasoning && currentContent.length > 0) {\n let content = '';\n for (const part of currentContent) {\n if (part.type !== ContentTypes.TEXT) {\n appendFormattedMessage(\n createAIMessage(toLangChainContent(currentContent))\n );\n return formattedMessages;\n }\n content += `${getTextContent(part)}\\n`;\n }\n content = content.trim();\n\n if (content) {\n appendFormattedMessage(createAIMessage(content));\n }\n } else if (currentContent.length > 0) {\n appendFormattedMessage(createAIMessage(toLangChainContent(currentContent)));\n }\n\n return formattedMessages;\n}\n\nfunction getSourceMessageId(message: Partial<TMessage>): string | undefined {\n const candidate =\n (message as { messageId?: string }).messageId ??\n (message as { id?: string }).id;\n if (typeof candidate !== 'string') {\n return undefined;\n }\n const normalized = candidate.trim();\n return normalized.length > 0 ? normalized : undefined;\n}\n\n/**\n * Keeps the first formatted message backward-compatible with its persisted\n * source id and preserves source correlation on every derived message.\n * Derived ids remain unset so the reducer can assign collision-free identities\n * during its existing pass. This also prevents invented provider-shaped ids\n * from leaking into provider request payloads.\n */\nfunction stampSourceMessageIdentity(\n message: RoleBearingMessage<BaseMessage>,\n sourceMessageId: string | undefined,\n derivedIndex = 0\n): void {\n if (sourceMessageId == null) {\n return;\n }\n message.additional_kwargs.sourceMessageId = sourceMessageId;\n if (derivedIndex !== 0) {\n return;\n }\n message.id = sourceMessageId;\n message.lc_kwargs.id = sourceMessageId;\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 /** UI-only progress headers are not agent content and must not disturb\n * agent state: a label with no `agentIdMap` entry would otherwise read\n * as an agent change and flush the buffer mid-agent, splitting one\n * agent's contiguous content into two labeled blocks. Skipped before\n * any state transition below (mirrors the transfer path). */\n if (part.type === ContentTypes.ACTIVITY_LABEL) {\n continue;\n }\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 if (part.type === ContentTypes.STEER) {\n /** User speech is never agent content — see the transfer path above. */\n flushAgentBuffer();\n result.push(part);\n continue;\n }\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 /** UI-only progress headers are not agent content and must not disturb\n * agent state: a label with no `agentIdMap` entry would otherwise look\n * like an agent change, flushing the buffer and resetting an open\n * transfer capture so the transferred agent's following chunks lose\n * their frame. Skipped before any state transition below. */\n if (part.type === ContentTypes.ACTIVITY_LABEL) {\n continue;\n }\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 if (part.type === ContentTypes.STEER) {\n /**\n * User speech is never agent content: flush the buffer in place and\n * pass the steer through verbatim so `formatAssistantMessage` replays\n * it as a user turn. Folding it into a labeled transfer summary would\n * both drop the user's words and misattribute them to the agent.\n * The steer also CLOSES any open transfer capture — `flushAgentBuffer`\n * no-ops on an empty buffer, and leaving the capture live would fold\n * post-steer agent content into the pre-steer transfer output,\n * replaying it BEFORE the user's redirect.\n */\n flushAgentBuffer();\n transferToolCallIndex = undefined;\n transferToolCallId = undefined;\n currentAgentId = undefined;\n result.push(part);\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 * How far back a persisted summary reaches.\n *\n * `coverage` is authoritative: the block named the first source message that\n * compaction retained, so `messageIndex` is exclusive — everything before it is\n * covered and it survives whole. `positional` is the legacy reading for blocks\n * written before coverage existed (or whose anchor is no longer in the payload)\n * — the block's own location is the boundary, which is why it cannot\n * distinguish a retained tail from covered history.\n */\ntype SummaryBoundary =\n | {\n mode: 'coverage';\n messageIndex: number;\n text: string;\n tokenCount: number;\n }\n | {\n mode: 'positional';\n messageIndex: number;\n contentIndex: number;\n text: string;\n tokenCount: number;\n };\n\ntype SummaryTokenAdjustment = {\n original: number;\n adjusted: number;\n remainingChars: number;\n totalChars: number;\n};\n\ntype SummaryScan = {\n boundary?: SummaryBoundary;\n};\n\nfunction resolveCoverageIndex(\n coverage: SummaryCoverage | undefined,\n indexBySourceId: Map<string, number>,\n summaryMessageIndex: number\n): number | undefined {\n /** Persisted JSON, so the declared string type is not a runtime guarantee. */\n if (typeof coverage?.retainedFromMessageId !== 'string') {\n return undefined;\n }\n const retainedFromMessageId = coverage.retainedFromMessageId.trim();\n if (retainedFromMessageId === '') {\n return undefined;\n }\n const retainedIndex = indexBySourceId.get(retainedFromMessageId);\n return retainedIndex != null && retainedIndex <= summaryMessageIndex\n ? retainedIndex\n : undefined;\n}\n\nfunction scanSummaryBlocks(payload: TPayload): SummaryScan {\n let boundary: SummaryBoundary | undefined;\n /** Filled as the scan advances, so a coverage lookup only ever resolves to a\n * message already passed — no second pass over the payload. */\n const indexBySourceId = new Map<string, number>();\n\n for (let i = 0; i < payload.length; i++) {\n const message = payload[i];\n const sourceMessageId = getSourceMessageId(message);\n if (sourceMessageId != null) {\n indexBySourceId.set(sourceMessageId, i);\n }\n if (!Array.isArray(message.content)) {\n continue;\n }\n\n for (let j = 0; j < message.content.length; j++) {\n const part = message.content[j] as MessageContentComplex | undefined;\n if (part == null || part.type !== ContentTypes.SUMMARY) {\n continue;\n }\n\n const summaryPart = part as Partial<SummaryContentBlock> & {\n text?: string;\n };\n\n // Try content array first (new format), then direct text (legacy format)\n let summaryText = (summaryPart.content ?? [])\n .map((block) =>\n 'text' in block ? (block as { text: string }).text : ''\n )\n .join('')\n .trim();\n\n // Fallback: legacy format where text was a direct field on the block\n if (summaryText.length === 0 && typeof summaryPart.text === 'string') {\n summaryText = summaryPart.text.trim();\n }\n\n if (summaryText.length === 0) {\n continue;\n }\n\n const tokenCount =\n typeof summaryPart.tokenCount === 'number' &&\n Number.isFinite(summaryPart.tokenCount)\n ? summaryPart.tokenCount\n : 0;\n\n const retainedIndex = resolveCoverageIndex(\n summaryPart.coverage,\n indexBySourceId,\n i\n );\n\n boundary =\n retainedIndex != null\n ? {\n mode: 'coverage',\n messageIndex: retainedIndex,\n text: summaryText,\n tokenCount,\n }\n : {\n mode: 'positional',\n messageIndex: i,\n contentIndex: j,\n text: summaryText,\n tokenCount,\n };\n }\n }\n\n return { boundary };\n}\n\nfunction applySummaryBoundary(\n message: Partial<TMessage>,\n messageIndex: number,\n summaryBoundary?: SummaryBoundary\n): Partial<TMessage> | null {\n if (!summaryBoundary) {\n return message;\n }\n\n /** The boundary names the first retained message, so it is exclusive: that\n * message and everything after it — the recency tail included — stays\n * verbatim, and only genuinely covered history is dropped. Summary parts on\n * surviving messages are filtered later by `formatAssistantMessage`. */\n if (summaryBoundary.mode === 'coverage') {\n return messageIndex < summaryBoundary.messageIndex ? null : message;\n }\n\n if (messageIndex < summaryBoundary.messageIndex) {\n return null;\n }\n\n if (\n messageIndex !== summaryBoundary.messageIndex ||\n !Array.isArray(message.content)\n ) {\n return message;\n }\n\n return {\n ...message,\n content: message.content.slice(summaryBoundary.contentIndex + 1),\n };\n}\n\n/**\n * Whether `formatAssistantMessage` filters this part out of the emitted message.\n * Such a part contributes no prompt tokens, so measuring it as zero characters\n * is accurate — it must not be mistaken for content the heuristic cannot see.\n */\nfunction isDroppedByFormatting(\n part: MessageContentComplex | undefined\n): boolean {\n if (part == null) {\n return true;\n }\n if (\n part.type === ContentTypes.SUMMARY ||\n part.type === ContentTypes.ERROR ||\n part.type === ContentTypes.AGENT_UPDATE ||\n part.type === ContentTypes.ACTIVITY_LABEL\n ) {\n return true;\n }\n return part.type === ContentTypes.TEXT && getTextContent(part).trim() === '';\n}\n\nfunction measureValueChars(value: unknown): number {\n if (typeof value === 'string') {\n return value.length;\n }\n if (value == null || typeof value !== 'object') {\n return 0;\n }\n const measured = serializeStructuredValueBounded(value, 0).originalChars;\n return measured === Number.MAX_SAFE_INTEGER\n ? HARD_MAX_TOOL_RESULT_CHARS\n : Math.min(measured, HARD_MAX_TOOL_RESULT_CHARS);\n}\n\n/**\n * Whether a retained part's whole prompt cost is the text the char heuristic\n * reads, making it safe to represent in a character ratio.\n *\n * An allowlist, not a denylist. Media, resources, and tool calls carry cost that\n * is unrelated to their serialized length — a short image URL nested in\n * `tool_call.output` stands in for a fixed four-figure media charge — and\n * rejecting those case by case has repeatedly missed a nesting level. Listing\n * the two shapes whose characters `contentPartCharLength` actually reads makes\n * every other shape, present or future, ineligible by default: the ratio is\n * skipped and the entry keeps its original count, which prunes early rather than\n * exceeding the window.\n */\nfunction isCharRatioEligible(part: MessageContentComplex | undefined): boolean {\n if (part == null) {\n return false;\n }\n return part.type === ContentTypes.TEXT || part.type === ContentTypes.THINKING;\n}\n\nfunction contentPartCharLength(part: MessageContentComplex): number {\n const record = part as Record<string, unknown>;\n let len = 0;\n if (typeof record.text === 'string') {\n len += record.text.length;\n }\n if (typeof record.thinking === 'string') {\n len += record.thinking.length;\n }\n len += measureValueChars(record.input);\n /** Tool calls nest their payload a level down, so measuring only the\n * top-level fields scores an entire tool turn as zero characters. */\n const { tool_call: toolCall } = record;\n if (toolCall != null && typeof toolCall === 'object') {\n const call = toolCall as Record<string, unknown>;\n len += measureValueChars(call.name);\n len += measureValueChars(call.args);\n len += measureValueChars(call.output);\n }\n return len;\n}\n\n/** Extracts the skillName from a skill tool_call's args (string or object). */\nfunction extractSkillName(args: unknown): string | undefined {\n let parsed: Record<string, unknown> | undefined;\n if (typeof args === 'string') {\n try {\n parsed = JSON.parse(args) as Record<string, unknown>;\n } catch {\n /* malformed args — skip */\n }\n } else {\n parsed = args as Record<string, unknown> | undefined;\n }\n const name = parsed?.skillName;\n return typeof name === 'string' && name !== '' ? name : undefined;\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 * @param skills - Optional map of skill name to body for reconstructing skill HumanMessages.\n * @param options - Optional formatting options (provider, skipSkillBodyNames).\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 /** Pre-resolved skill bodies keyed by skill name. When present, HumanMessages\n * are reconstructed after skill ToolMessages to restore skill instructions\n * that were only in LangGraph state during the original run. */\n skills?: Map<string, string>,\n options?: FormatAgentMessagesOptions\n): {\n messages: Array<\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<SystemMessage>\n | RoleBearingMessage<ToolMessage>\n >;\n indexTokenCountMap?: Record<number, number>;\n /** Cross-run summary extracted from the payload. Should be forwarded to the\n * agent run so it can be included in the system message via AgentContext. */\n summary?: { text: string; tokenCount: number };\n /** When a positional summary boundary sliced content from a message, the token\n * count was proportionally reduced. Returned so the caller can log it. */\n boundaryTokenAdjustment?: SummaryTokenAdjustment;\n} => {\n const messages: Array<\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<SystemMessage>\n | RoleBearingMessage<ToolMessage>\n > = [];\n /**\n * A steer ended the previous payload entry, so the next message emitted —\n * whichever entry finally produces one — must be separated from it by an\n * assistant turn. Held rather than emitted so an entry that produces\n * nothing cannot leave the anchor stranded as the final turn.\n */\n let pendingSteerAnchor = false;\n /**\n * Emits the deferred anchor ahead of `next` — the message about to be\n * pushed. When that message is itself an assistant turn, it already IS the\n * separation the anchor exists to synthesize, so the intent is simply\n * discharged: emitting the placeholder anyway would put two assistant turns\n * back to back, which strict-alternation providers can reject and nothing downstream\n * repairs (`coalesceAdjacentUserTurns` merges user turns only).\n */\n const flushSteerAnchor = (next: { role?: LangChainMessageRole }): void => {\n if (!pendingSteerAnchor) {\n return;\n }\n pendingSteerAnchor = false;\n if (next.role === 'assistant') {\n return;\n }\n messages.push(\n withMessageRole(\n new AIMessage({ content: STEER_ANCHOR_PLACEHOLDER }),\n 'assistant'\n )\n );\n };\n // If indexTokenCountMap is provided, create a new map to track the updated indices\n const updatedIndexTokenCountMap: Record<number, number> = {};\n let boundaryTokenAdjustment: SummaryTokenAdjustment | undefined;\n // Keep track of the mapping from original payload indices to result indices\n const indexMapping: Record<number, number[] | undefined> = {};\n const { boundary: summaryBoundary } = scanSummaryBlocks(payload);\n\n // Summary metadata is returned to the caller so it can be forwarded to the\n // agent run and included in the single system message via AgentContext.\n // We intentionally do NOT create a SystemMessage here — that would conflict\n // with the agent's own system message (instructions + summary combined).\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 rawMessage = payload[i];\n const sourceMessageId = getSourceMessageId(rawMessage);\n let message = applySummaryBoundary(rawMessage, i, summaryBoundary);\n if (!message) {\n indexMapping[i] = [];\n continue;\n }\n\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 = {\n ...message,\n content: [\n { type: ContentTypes.TEXT, [ContentTypes.TEXT]: message.content },\n ],\n };\n } else if (Array.isArray(message.content) && message.content.length === 0) {\n indexMapping[i] = [];\n continue;\n }\n\n if (message.role !== 'assistant') {\n const formattedMessage = formatMessage({\n message: message as MessageInput,\n langChain: true,\n }) as\n | RoleBearingMessage<HumanMessage>\n | RoleBearingMessage<AIMessage>\n | RoleBearingMessage<SystemMessage>;\n stampSourceMessageIdentity(formattedMessage, sourceMessageId);\n flushSteerAnchor(formattedMessage);\n messages.push(formattedMessage);\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 let pendingSkillNames: Set<string> | undefined;\n if (discoveredTools) {\n const content = message.content;\n if (content != null && 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 filteredContent.push(part);\n if (\n toolName === Constants.SKILL_TOOL &&\n skills?.size != null &&\n skills.size > 0\n ) {\n const skillName = extractSkillName(part.tool_call.args) ?? '';\n if (skillName) {\n (pendingSkillNames ??= new Set()).add(skillName);\n }\n }\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 /** When tools filtering is off, still detect skill tool_calls for body reconstruction */\n if (!discoveredTools && skills?.size != null && skills.size > 0) {\n const content = processedMessage.content;\n if (Array.isArray(content)) {\n for (const part of content) {\n if (\n part.type !== ContentTypes.TOOL_CALL ||\n part.tool_call?.name !== Constants.SKILL_TOOL\n ) {\n continue;\n }\n const skillName = extractSkillName(part.tool_call.args) ?? '';\n if (skillName) {\n (pendingSkillNames ??= new Set()).add(skillName);\n }\n }\n }\n }\n\n const formattedMessages = formatAssistantMessage(processedMessage, {\n preserveUnpairedServerToolUses: i === payload.length - 1,\n preserveReasoningContent:\n options?.preserveReasoningContent ??\n options?.provider === Providers.DEEPSEEK,\n provider: options?.provider,\n sourceMessageId,\n });\n /**\n * A steer that ends an assistant message leaves the replay on a\n * `HumanMessage`. The next payload message is itself a user turn, so the\n * sequence would reach the provider as two adjacent user turns — rejected\n * by strict-alternation providers. Anchor it with a placeholder assistant\n * turn.\n *\n * The placeholder must be NON-EMPTY. A string-content assistant message\n * with no tool calls passes through `_convertMessagesToAnthropicPayload`\n * verbatim — the empty-text repair there only covers array content and\n * tool-call turns — so an empty anchor would reach Anthropic as\n * `{role: 'assistant', content: ''}` and trade one invalid sequence for\n * another. Same single-underscore convention the Anthropic converter\n * already uses when it has to synthesize a non-empty block.\n *\n * Deferred rather than decided by lookahead. `i < payload.length - 1` only\n * proves a later ENTRY exists, not that it EMITS: entries with empty\n * content, and entries dropped by `applySummaryBoundary`, are skipped\n * silently. A trailing steer followed only by those would get the anchor\n * as the FINAL turn — an assistant prefill with no request after it, which\n * the model may simply never answer. So the intent is recorded and flushed\n * only when a message actually follows.\n *\n * Pushed AFTER source identity stamping above, deliberately. The anchor is\n * synthetic rather than derived from the persisted assistant entry, so it\n * must not claim that entry's source metadata. Left unstamped, it reaches\n * the reducer with a null id and is assigned a fresh one.\n * `endsWithSteerMessage` reads only `additional_kwargs.source`, so the\n * deferral cannot change which messages get anchored.\n */\n /**\n * Guarded on emission: an assistant entry whose blocks all filtered away\n * emits nothing, and flushing for it would strand the anchor as the final\n * turn — the pending flag stays set for whichever entry emits next.\n */\n if (formattedMessages.length > 0) {\n flushSteerAnchor(formattedMessages[0]);\n }\n messages.push(...formattedMessages);\n if (endsWithSteerMessage(formattedMessages)) {\n pendingSteerAnchor = true;\n }\n\n // Capture index range BEFORE skill body injection so injected\n // HumanMessages are excluded from the assistant's token distribution.\n const endMessageIndex = messages.length;\n\n if (pendingSkillNames?.size != null && pendingSkillNames.size > 0) {\n const skipSkillBodyNames = options?.skipSkillBodyNames;\n for (const skillName of pendingSkillNames) {\n if (skipSkillBodyNames != null && skipSkillBodyNames.has(skillName)) {\n continue;\n }\n const body = skills?.get(skillName) ?? '';\n if (body) {\n messages.push(\n withMessageRole(\n new HumanMessage({\n content: body,\n additional_kwargs: {\n role: 'user',\n isMeta: true,\n source: 'skill',\n skillName,\n },\n }),\n 'user'\n )\n );\n }\n }\n }\n\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 let tokenCount = indexTokenCountMap[originalIndex];\n\n if (tokenCount === undefined) {\n continue;\n }\n\n /**\n * Coverage mode deliberately leaves the count alone, even though the entry\n * holding the block is charged for summary text that `formatAssistantMessage`\n * filters out and `summary.tokenCount` accounts separately.\n *\n * Discounting it needs the summary's cost in the same units as\n * `indexTokenCountMap`, and that figure is not obtainable here: this\n * function receives no tokenizer, and a count recorded at write time is in\n * the writing run's units — `Run.create` derives its counter from the model\n * in play, and a consumer may supply its own — so a conversation continued\n * on a different model would subtract across encodings. Attempts to proxy\n * it (character ratios, provider identity) all under-count some shape,\n * which risks an over-context request; over-counting merely prunes early.\n * Fixing it properly means passing the reader a tokenizer, which is a\n * consumer-facing change and out of scope here.\n */\n if (\n summaryBoundary?.mode === 'positional' &&\n originalIndex === summaryBoundary.messageIndex &&\n Array.isArray(payload[originalIndex].content)\n ) {\n const content = payload[originalIndex]\n .content as MessageContentComplex[];\n const { contentIndex } = summaryBoundary;\n if (contentIndex >= 0 && contentIndex < content.length - 1) {\n let totalCharLen = 0;\n let remainingCharLen = 0;\n /**\n * The ratio applies only when *every* part of the entry is one whose\n * token cost tracks its character length. A single ineligible part\n * cancels the discount, whichever side of the boundary it sits on.\n *\n * Both sides can break it, in opposite directions. A retained image has\n * its fixed cost scaled away, collapsing the entry. A removed base64\n * payload inflates the denominator — serializing to a huge length while\n * the counter charges a fixed estimate — dragging retained text below\n * its real cost. Either way the request can exceed the window.\n *\n * Telling a text-bearing tool payload from a media-bearing one means\n * recursing into arbitrary nested output, which has already missed a\n * level twice here. Cancelling instead keeps the original count: an\n * over-count that prunes early rather than overflowing. Entries of\n * plain text and reasoning — the common shape — still proportion.\n */\n let everyRetainedPartMeasurable = true;\n for (let p = 0; p < content.length; p++) {\n const part = content[p];\n const retained = p > contentIndex;\n\n if (isDroppedByFormatting(part)) {\n /** Removed summary text is real removed content: it is read as\n * plain text and belongs in the denominator. */\n if (!retained && part.type === ContentTypes.SUMMARY) {\n totalCharLen += contentPartCharLength(part);\n }\n continue;\n }\n\n const charLen = contentPartCharLength(part);\n if (!isCharRatioEligible(part) || (retained && charLen === 0)) {\n everyRetainedPartMeasurable = false;\n break;\n }\n totalCharLen += charLen;\n if (retained) {\n remainingCharLen += charLen;\n }\n }\n if (totalCharLen > 0 && everyRetainedPartMeasurable) {\n const original = tokenCount;\n tokenCount = Math.max(\n 1,\n Math.round(tokenCount * (remainingCharLen / totalCharLen))\n );\n boundaryTokenAdjustment = {\n original,\n adjusted: tokenCount,\n remainingChars: remainingCharLen,\n totalChars: totalCharLen,\n };\n }\n }\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 const measured = serializeStructuredValueBounded(\n args,\n 0\n ).originalChars;\n len +=\n measured === Number.MAX_SAFE_INTEGER\n ? HARD_MAX_TOOL_RESULT_CHARS\n : Math.min(measured, HARD_MAX_TOOL_RESULT_CHARS);\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 summary: summaryBoundary\n ? { text: summaryBoundary.text, tokenCount: summaryBoundary.tokenCount }\n : undefined,\n boundaryTokenAdjustment,\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/** Checks whether a BaseMessage is a tool-role message. */\nconst isToolMessage = (m: BaseMessage): boolean =>\n m instanceof ToolMessage || ('role' in m && (m as any).role === 'tool');\n\nconst PORTABLE_FOLDED_MEDIA_TYPES = new Set(['image', 'image_url']);\nconst MAX_FOLDED_BLOCK_CHARS = 8_000;\nconst MAX_FOLDED_CONTEXT_CHARS = HARD_MAX_TOOL_RESULT_CHARS;\nconst MAX_FOLDED_CONTEXT_WORK = 100_000;\nconst FOLDED_CONTEXT_TRUNCATION_NOTICE =\n '… [additional folded context omitted]';\nconst syntheticProviderContextMessages = new WeakSet<BaseMessage>();\n\ntype FoldContextBudget = {\n remainingChars: number;\n remainingWork: number;\n truncated: boolean;\n};\n\nfunction createFoldContextBudget(): FoldContextBudget {\n return {\n remainingChars: MAX_FOLDED_CONTEXT_CHARS,\n remainingWork: MAX_FOLDED_CONTEXT_WORK,\n truncated: false,\n };\n}\n\nfunction readFoldedDataProperty(value: unknown, key: string): unknown {\n if (value == null || typeof value !== 'object') {\n return undefined;\n }\n try {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n return descriptor != null && 'value' in descriptor\n ? descriptor.value\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Adds one logical line without first concatenating caller-controlled strings.\n * The shared budget covers every synthetic message emitted by one transform,\n * so many individually bounded blocks cannot build an unbounded aggregate.\n */\nfunction appendFoldedLine(\n textChunks: string[],\n budget: FoldContextBudget,\n pieces: readonly string[]\n): boolean {\n if (budget.remainingChars <= 0) {\n budget.truncated = true;\n return false;\n }\n\n const separatorChars = textChunks.length > 0 ? 1 : 0;\n const available = budget.remainingChars - separatorChars;\n if (available <= 0) {\n budget.remainingChars = 0;\n budget.truncated = true;\n return false;\n }\n\n let totalChars = 0;\n for (const piece of pieces) {\n totalChars = Math.min(Number.MAX_SAFE_INTEGER, totalChars + piece.length);\n }\n if (totalChars <= available) {\n const line = pieces.join('');\n textChunks.push(line);\n budget.remainingChars -= separatorChars + line.length;\n return true;\n }\n\n const notice = FOLDED_CONTEXT_TRUNCATION_NOTICE.slice(0, available);\n let remainingHeadChars = Math.max(0, available - notice.length);\n const boundedPieces: string[] = [];\n for (const piece of pieces) {\n if (remainingHeadChars <= 0) {\n break;\n }\n const retained = piece.slice(0, remainingHeadChars);\n boundedPieces.push(retained);\n remainingHeadChars -= retained.length;\n }\n boundedPieces.push(notice);\n textChunks.push(boundedPieces.join(''));\n budget.remainingChars = 0;\n budget.truncated = true;\n return false;\n}\n\nfunction consumeFoldedWork(\n textChunks: string[],\n budget: FoldContextBudget\n): boolean {\n if (budget.remainingChars <= 0) {\n return false;\n }\n if (budget.remainingWork-- > 0) {\n return true;\n }\n appendFoldedLine(textChunks, budget, [FOLDED_CONTEXT_TRUNCATION_NOTICE]);\n budget.remainingChars = 0;\n budget.truncated = true;\n return false;\n}\n\nfunction serializeFoldedValue(value: unknown): string {\n const compacted = compactToolContent(value, MAX_FOLDED_BLOCK_CHARS).content;\n return typeof compacted === 'string'\n ? compacted\n : serializeStructuredValueBounded(compacted, MAX_FOLDED_BLOCK_CHARS)\n .content;\n}\n\nfunction markSyntheticProviderContext<T extends BaseMessage>(message: T): T {\n syntheticProviderContextMessages.add(message);\n return message;\n}\n\nfunction appendSyntheticProviderContextMessage(\n result: BaseMessage[],\n parts: MessageContentComplex[]\n): boolean {\n if (parts.length === 0) {\n return false;\n }\n result.push(\n markSyntheticProviderContext(\n withMessageRole(\n new HumanMessage({ content: toLangChainContent(parts) }),\n 'user'\n )\n )\n );\n return true;\n}\n\n/**\n * Identifies provider-context placeholders created by this module without\n * trusting user-controlled content prefixes or leaking marker metadata onto\n * the provider wire.\n */\nexport function isSyntheticProviderContextMessage(\n message: BaseMessage\n): boolean {\n return syntheticProviderContextMessages.has(message);\n}\n\n/** Flushes accumulated text chunks into `parts` as a single text block. */\nfunction flushTextChunks(\n textChunks: string[],\n parts: MessageContentComplex[]\n): void {\n if (textChunks.length === 0) {\n return;\n }\n parts.push({\n type: ContentTypes.TEXT,\n text: textChunks.join('\\n'),\n } as MessageContentComplex);\n textChunks.length = 0;\n}\n\n/**\n * Appends a single message's content to the running `textChunks` / `parts`\n * accumulators. Portable image blocks are shallow-copied into `parts` so\n * binary data never becomes text tokens. Provider-specific media/resource\n * blocks are retained as bounded text so a folded cross-provider history\n * cannot contain an unsupported native block or JSON-expand without limit.\n *\n * When `content` is an array containing tool_use blocks, `tool_calls` is NOT\n * additionally serialized (avoiding double output). `tool_calls` is used as\n * a fallback when `content` is a plain string or an array with no tool_use.\n */\nfunction appendMessageContent(\n msg: BaseMessage,\n role: string,\n textChunks: string[],\n parts: MessageContentComplex[],\n budget: FoldContextBudget\n): void {\n const { content } = msg;\n\n if (typeof content === 'string') {\n if (content && consumeFoldedWork(textChunks, budget)) {\n appendFoldedLine(textChunks, budget, [`${role}: `, content]);\n }\n appendToolCalls(msg, role, textChunks, budget);\n return;\n }\n\n if (!Array.isArray(content)) {\n appendToolCalls(msg, role, textChunks, budget);\n return;\n }\n\n let hasToolUseBlock = false;\n\n for (const block of content as ExtendedMessageContent[]) {\n if (!consumeFoldedWork(textChunks, budget)) {\n hasToolUseBlock = true;\n break;\n }\n const blockTypeValue = readFoldedDataProperty(block, 'type');\n const blockType =\n typeof blockTypeValue === 'string' ? blockTypeValue : undefined;\n\n if (\n blockType !== 'tool_use' &&\n blockType !== 'tool_call' &&\n blockType !== 'tool_result' &&\n isAtomicToolContentBlock(block)\n ) {\n if (PORTABLE_FOLDED_MEDIA_TYPES.has(blockType ?? '')) {\n const blockChars = getToolContentCharLength([block]);\n if (blockChars > budget.remainingChars) {\n appendFoldedLine(textChunks, budget, [\n `${role}: [${blockType ?? 'media'} omitted: folded context limit]`,\n ]);\n continue;\n }\n flushTextChunks(textChunks, parts);\n parts.push({ ...block } as MessageContentComplex);\n budget.remainingChars -= blockChars;\n } else {\n appendFoldedLine(textChunks, budget, [\n `${role}: [${blockType ?? 'media'}] `,\n serializeFoldedValue(block),\n ]);\n }\n continue;\n }\n\n if (blockType === 'tool_use') {\n hasToolUseBlock = true;\n const name = readFoldedDataProperty(block, 'name');\n const input = readFoldedDataProperty(block, 'input');\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_use] ${typeof name === 'string' ? name : ''} `,\n serializeFoldedValue(input ?? {}),\n ]);\n continue;\n }\n\n // A `tool_call` content block appears either as the v1 standard shape\n // (`{ name, args }` at top level, which `@langchain/aws` maps to a Converse\n // toolUse) or this repo's `ToolCallContent` (`{ tool_call: { name, args,\n // output } }`, from `convertMessagesToContent` / persisted history). Handle\n // both, and emit any embedded output, so the name/args/result survive.\n if (blockType === 'tool_call') {\n hasToolUseBlock = true;\n const nested = readFoldedDataProperty(block, 'tool_call');\n const nestedName = readFoldedDataProperty(nested, 'name');\n const topLevelName = readFoldedDataProperty(block, 'name');\n let name = '';\n if (typeof nestedName === 'string') {\n name = nestedName;\n } else if (typeof topLevelName === 'string') {\n name = topLevelName;\n }\n const nestedArgs = readFoldedDataProperty(nested, 'args');\n const topLevelArgs = readFoldedDataProperty(block, 'args');\n const rawArgs = nestedArgs ?? topLevelArgs ?? {};\n const argsText =\n typeof rawArgs === 'string' ? rawArgs : serializeFoldedValue(rawArgs);\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_use] ${name}${argsText ? ' ' : ''}`,\n argsText,\n ]);\n const output = readFoldedDataProperty(nested, 'output');\n if (output != null && output !== '') {\n appendFoldedLine(textChunks, budget, [\n 'Tool: ',\n typeof output === 'string' ? output : serializeFoldedValue(output),\n ]);\n }\n continue;\n }\n\n // A `tool_result` content block (e.g. an AIMessage(tool_call) followed by a\n // user message carrying the result). Preserve nested image blocks as-is\n // instead of JSON-stringifying them through the generic fallback.\n if (blockType === 'tool_result') {\n hasToolUseBlock = true;\n const inner = readFoldedDataProperty(block, 'content') as\n | ToolResultContent['content']\n | undefined;\n if (typeof inner === 'string') {\n if (inner) {\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_result] `,\n inner,\n ]);\n }\n } else if (Array.isArray(inner)) {\n for (const innerBlock of inner as Array<\n string | ExtendedMessageContent\n >) {\n if (!consumeFoldedWork(textChunks, budget)) {\n break;\n }\n if (typeof innerBlock === 'string') {\n if (innerBlock) {\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_result] `,\n innerBlock,\n ]);\n }\n } else {\n const innerTypeValue = readFoldedDataProperty(innerBlock, 'type');\n const innerType =\n typeof innerTypeValue === 'string' ? innerTypeValue : undefined;\n if (\n isAtomicToolContentBlock(innerBlock) &&\n PORTABLE_FOLDED_MEDIA_TYPES.has(innerType ?? '')\n ) {\n const blockChars = getToolContentCharLength([innerBlock]);\n if (blockChars <= budget.remainingChars) {\n flushTextChunks(textChunks, parts);\n parts.push({ ...innerBlock } as MessageContentComplex);\n budget.remainingChars -= blockChars;\n } else {\n appendFoldedLine(textChunks, budget, [\n `${role}: [${innerType ?? 'media'} omitted: folded context limit]`,\n ]);\n }\n } else {\n const textValue = readFoldedDataProperty(innerBlock, 'text');\n const inputValue = readFoldedDataProperty(innerBlock, 'input');\n const innerText = textValue ?? inputValue;\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_result] `,\n typeof innerText === 'string' && innerText\n ? innerText\n : serializeFoldedValue(innerBlock),\n ]);\n }\n }\n }\n } else if (inner != null) {\n appendFoldedLine(textChunks, budget, [\n `${role}: [tool_result] `,\n serializeFoldedValue(inner),\n ]);\n }\n continue;\n }\n\n const text =\n readFoldedDataProperty(block, 'text') ??\n readFoldedDataProperty(block, 'input');\n if (typeof text === 'string' && text) {\n appendFoldedLine(textChunks, budget, [`${role}: `, text]);\n continue;\n }\n\n // Fallback: serialize unrecognized block types to preserve context\n if (blockType != null && blockType !== '') {\n appendFoldedLine(textChunks, budget, [\n `${role}: [${blockType}] `,\n serializeFoldedValue(block),\n ]);\n }\n }\n\n // If content array had no tool_use blocks, fall back to tool_calls metadata\n // (handles edge case: empty content array with tool_calls populated)\n if (!hasToolUseBlock) {\n appendToolCalls(msg, role, textChunks, budget);\n }\n}\n\nfunction appendToolCalls(\n msg: BaseMessage,\n role: string,\n textChunks: string[],\n budget: FoldContextBudget\n): void {\n if (role !== 'AI') {\n return;\n }\n const aiMsg = msg as AIMessage;\n if (aiMsg.tool_calls && aiMsg.tool_calls.length > 0) {\n for (const tc of aiMsg.tool_calls) {\n if (!consumeFoldedWork(textChunks, budget)) {\n break;\n }\n const name = readFoldedDataProperty(tc, 'name');\n const args = readFoldedDataProperty(tc, 'args');\n appendFoldedLine(textChunks, budget, [\n `AI: [tool_call] ${typeof name === 'string' ? name : ''}(`,\n serializeFoldedValue(args),\n ')',\n ]);\n }\n return;\n }\n // Fall back to raw provider tool calls kept only in additional_kwargs.\n const rawToolCalls = aiMsg.additional_kwargs.tool_calls;\n if (!Array.isArray(rawToolCalls)) {\n return;\n }\n for (const tc of rawToolCalls) {\n if (!consumeFoldedWork(textChunks, budget)) {\n break;\n }\n const fn = readFoldedDataProperty(tc, 'function');\n if (fn == null) {\n continue;\n }\n const name = readFoldedDataProperty(fn, 'name');\n const args = readFoldedDataProperty(fn, 'arguments');\n appendFoldedLine(textChunks, budget, [\n `AI: [tool_call] ${typeof name === 'string' ? name : ''}(`,\n typeof args === 'string' ? args : '',\n ')',\n ]);\n }\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 * @param config - Optional RunnableConfig for structured agent logging\n * @param runStartIndex - Index in `messages` where the CURRENT run's own\n * appended AI/Tool messages begin (i.e. anything at this index or later\n * was just produced by this run's own iterations, not historical\n * context). When provided, AI messages at or after this index are\n * never converted to `[Previous agent context]` placeholders — Claude\n * can validly skip a thinking block before a tool_use (cf. PR #116),\n * so the agent's own in-run iterations must not be misclassified as\n * foreign history. Without the signal the function falls back to its\n * prior heuristic (`chainHasThinkingBlock`), preserving backward\n * compatibility for callers that don't yet pass the boundary.\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 config?: RunnableConfig,\n runStartIndex?: number\n): BaseMessage[] {\n if (messages.length === 0) {\n return messages;\n }\n\n // Find the last HumanMessage. Only the trailing sequence after it needs\n // validation — earlier messages are history already accepted by the provider.\n let lastHumanIndex = -1;\n for (let k = messages.length - 1; k >= 0; k--) {\n const m = messages[k];\n if (\n m instanceof HumanMessage ||\n ('role' in m && (m as any).role === 'user')\n ) {\n lastHumanIndex = k;\n break;\n }\n }\n\n if (lastHumanIndex === messages.length - 1) {\n return messages;\n }\n\n const result: BaseMessage[] =\n lastHumanIndex >= 0 ? messages.slice(0, lastHumanIndex + 1) : [];\n const foldBudget = createFoldContextBudget();\n let i = lastHumanIndex + 1;\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 for (const c of aiMsg.content as ExtendedMessageContent[]) {\n if (typeof c !== 'object') {\n continue;\n }\n const type = readFoldedDataProperty(c, 'type');\n if (type === 'tool_use') {\n hasToolUse = true;\n } else if (\n type === ContentTypes.THINKING ||\n type === ContentTypes.REASONING_CONTENT ||\n type === ContentTypes.REASONING ||\n type === 'redacted_thinking'\n ) {\n hasThinkingBlock = true;\n }\n if (hasToolUse && hasThinkingBlock) {\n break;\n }\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 // Current-run boundary check: anything at or after `runStartIndex`\n // is the current run's own work — preserve it. Claude is allowed\n // to skip a thinking block before a tool_use (cf. PR #116 in the\n // agents repo), so the agent's own first-iteration AI message can\n // legitimately have tool_calls without reasoning. Converting it to\n // a `[Previous agent context]` placeholder pollutes the next\n // iteration's prompt — the LLM sees the placeholder, treats it as\n // suspicious injected content, ignores its own real prior tool\n // result, and re-runs the tool to verify (which then often fails\n // because subsequent calls land in fresh sandboxes without the\n // file). Skip the conversion when we know this is in-run.\n if (runStartIndex !== undefined && i >= runStartIndex) {\n result.push(msg);\n i++;\n continue;\n }\n\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 // Build structured content in a single pass over the AI + following\n // ToolMessages — preserves image blocks as-is to avoid serializing\n // binary data as text (which caused 174× token amplification).\n const parts: MessageContentComplex[] = [];\n const textChunks: string[] = [];\n appendFoldedLine(textChunks, foldBudget, ['[Previous agent context]']);\n\n appendMessageContent(msg, 'AI', textChunks, parts, foldBudget);\n\n let j = i + 1;\n while (j < messages.length && isToolMessage(messages[j])) {\n appendMessageContent(\n messages[j],\n 'Tool',\n textChunks,\n parts,\n foldBudget\n );\n j++;\n }\n\n flushTextChunks(textChunks, parts);\n if (appendSyntheticProviderContextMessage(result, parts)) {\n emitAgentLog(\n config,\n 'warn',\n 'format',\n 'ensureThinkingBlockInMessages: injecting [Previous agent context] HumanMessage' +\n ` (${parts.length} msgs at index ${i}, no thinking block in chain)`\n );\n }\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/** Whether a message carries tool content a tool-less agent cannot legally\n * send. Covers every representation a provider converter will serialize back\n * into a request: a ToolMessage, parsed `AIMessage.tool_calls`, raw\n * `additional_kwargs.tool_calls` (OpenAI keeps calls here when the parsed\n * array is empty), and `tool_use` / `tool_call` / `tool_result` content\n * blocks (`@langchain/aws` and the Anthropic converter map these to Converse\n * `toolUse` / `toolResult`). Missing the parent AI message is not just a\n * passthrough: folding its ToolMessage alone would leave an orphan\n * `assistant(tool_calls) -> user(...)` sequence. */\nfunction messageHasToolContent(msg: BaseMessage): boolean {\n if (isToolMessage(msg)) {\n return true;\n }\n const aiMsg = msg as AIMessage;\n if (aiMsg.tool_calls != null && aiMsg.tool_calls.length > 0) {\n return true;\n }\n const rawToolCalls = aiMsg.additional_kwargs.tool_calls;\n if (Array.isArray(rawToolCalls) && rawToolCalls.length > 0) {\n return true;\n }\n if (Array.isArray(msg.content)) {\n for (const block of msg.content as ExtendedMessageContent[]) {\n const type = readFoldedDataProperty(block, 'type');\n if (\n typeof block === 'object' &&\n (type === 'tool_use' || type === 'tool_call' || type === 'tool_result')\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/** Whether a message carries a tool RESULT: a ToolMessage, or a message whose\n * content includes a `tool_result` block (the shape when a call/result pair is\n * split as `AIMessage(tool_call)` + `HumanMessage(tool_result)`). Such a result\n * belongs with the preceding tool call, so it is absorbed into the same fold\n * and labelled as tool output. */\nfunction isToolResultMessage(msg: BaseMessage): boolean {\n if (isToolMessage(msg)) {\n return true;\n }\n if (Array.isArray(msg.content)) {\n return (msg.content as ExtendedMessageContent[]).some(\n (block) =>\n typeof block === 'object' &&\n readFoldedDataProperty(block, 'type') === 'tool_result'\n );\n }\n return false;\n}\n\n/**\n * Folds tool_use / tool_result content into plain text for an agent that binds\n * no tools.\n *\n * In a multi-agent graph, a tool-less destination still inherits the prior\n * agent's conversation history, which can contain toolUse/toolResult blocks.\n * Because it binds no tools, the model is invoked with no tool schema — and\n * Bedrock's Converse API rejects any request that carries toolUse/toolResult\n * blocks without a top-level toolConfig (\"The toolConfig field must be defined\n * when using toolUse and toolResult content blocks\"). Adding a dummy toolConfig\n * is not an option: AWS requires at least one tool, and it would expose a\n * capability the destination was intentionally denied.\n *\n * Each tool-call turn plus its trailing tool results (ToolMessages or\n * `tool_result` content blocks) is collapsed into a single `[Previous tool\n * interaction]` HumanMessage that preserves the tool name, arguments and result\n * as text (image blocks are kept as-is). Runs in a single pass: non-tool\n * messages pass through, `result` is allocated lazily on the first fold, and the\n * original array is returned unchanged when it holds no tool content (the common\n * fresh-tool-less-agent case).\n */\nexport function foldToolBlocksForToollessAgent(\n messages: BaseMessage[],\n config?: RunnableConfig\n): BaseMessage[] {\n let result: BaseMessage[] | null = null;\n let foldedCount = 0;\n const foldBudget = createFoldContextBudget();\n let i = 0;\n while (i < messages.length) {\n const msg = messages[i];\n if (!messageHasToolContent(msg)) {\n result?.push(msg);\n i++;\n continue;\n }\n\n /** First fold — copy the untouched prefix once, then append from here. */\n if (result === null) {\n result = messages.slice(0, i);\n }\n\n const parts: MessageContentComplex[] = [];\n const textChunks: string[] = [];\n appendFoldedLine(textChunks, foldBudget, ['[Previous tool interaction]']);\n appendMessageContent(\n msg,\n isToolResultMessage(msg) ? 'Tool' : 'AI',\n textChunks,\n parts,\n foldBudget\n );\n foldedCount++;\n\n let j = i + 1;\n while (j < messages.length && isToolResultMessage(messages[j])) {\n appendMessageContent(messages[j], 'Tool', textChunks, parts, foldBudget);\n foldedCount++;\n j++;\n }\n\n flushTextChunks(textChunks, parts);\n appendSyntheticProviderContextMessage(result, parts);\n i = j;\n }\n\n if (result === null) {\n return messages;\n }\n\n emitAgentLog(\n config,\n 'warn',\n 'format',\n `foldToolBlocksForToollessAgent: folded ${foldedCount} tool message(s) into text for a tool-less agent`\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"],"mappings":"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"}