{"version":3,"file":"agent/message-history.mjs","sources":["webpack://@multimodal/agent/./src/agent/message-history.ts"],"sourcesContent":["/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n  AgentEventStream,\n  ToolCallEngine,\n  Tool,\n  AgentSingleLoopReponse,\n  ChatCompletionMessageParam,\n  ChatCompletionContentPart,\n} from '@multimodal/agent-interface';\nimport { convertToMultimodalToolCallResult } from '../utils/multimodal';\nimport { getLogger } from '../utils/logger';\nimport { isTest } from '../utils/env';\n\n/**\n * Interface for image information in messages\n */\ninterface ImageReference {\n  eventIndex: number;\n  contentIndex: number;\n  event: AgentEventStream.Event;\n}\n\n/**\n * MessageHistory - Converts event stream to message history\n * This separates the concerns of event storage from message history formatting\n *\n * Features:\n * - Handles multimodal content including text and images\n * - Limits images to prevent context window overflow\n * - Maintains conversation structure for LLM context\n * - Supports environment inputs as part of the conversation\n */\nexport class MessageHistory {\n  private logger = getLogger('MessageHistory');\n\n  /**\n   * Creates a new MessageHistory instance\n   *\n   * @param eventStream - The event stream to convert to message history\n   * @param maxImagesCount - Optional maximum number of images to include in the context.\n   *                         When specified, limits the total number of images in the conversation history\n   *                         to prevent context window overflow. Images beyond this limit will be\n   *                         replaced with text placeholders to preserve context while reducing token usage.\n   */\n  constructor(\n    private eventStream: AgentEventStream.Processor,\n    private maxImagesCount?: number,\n  ) {}\n\n  /**\n   * Convert events to message history format for LLM context\n   * This method uses the provided toolCallEngine to format messages\n   * according to the specific requirements of the underlying LLM\n   *\n   * @param toolCallEngine The tool call engine to use for message formatting\n   * @param systemPrompt The base system prompt to include\n   * @param tools Available tools to enhance the system prompt\n   */\n  toMessageHistory(\n    toolCallEngine: ToolCallEngine,\n    customSystemPrompt: string,\n    tools: Tool[] = [],\n  ): ChatCompletionMessageParam[] {\n    const baseSystemPrompt = this.getSystemPromptWithTime(customSystemPrompt);\n    // Start with the enhanced system message\n    const enhancedSystemPrompt = toolCallEngine.preparePrompt(baseSystemPrompt, tools);\n    const messages: ChatCompletionMessageParam[] = [\n      { role: 'system', content: enhancedSystemPrompt },\n    ];\n\n    this.logger.debug(\n      `Created system message with prompt ${enhancedSystemPrompt.length} chars long`,\n    );\n\n    const events = this.eventStream.getEvents();\n\n    // Create a unified processing path with optional image limiting\n    this.processEvents(events, messages, toolCallEngine);\n\n    return messages;\n  }\n\n  /**\n   * Process all events in a single unified path with optional image limiting\n   */\n  private processEvents(\n    events: AgentEventStream.Event[],\n    messages: ChatCompletionMessageParam[],\n    toolCallEngine: ToolCallEngine,\n  ): void {\n    // If image limiting is enabled, identify which images should be omitted\n    const imagesToOmit =\n      this.maxImagesCount !== undefined ? this.getImagesToOmit(events) : new Set<string>();\n\n    // Process events in order\n    for (let eventIndex = 0; eventIndex < events.length; eventIndex++) {\n      const event = events[eventIndex];\n\n      if (event.type === 'user_message') {\n        this.processUserMessage(event, eventIndex, imagesToOmit, messages);\n      } else if (event.type === 'assistant_message') {\n        this.processAssistantMessage(\n          event as AgentEventStream.AssistantMessageEvent,\n          events,\n          eventIndex,\n          imagesToOmit,\n          messages,\n          toolCallEngine,\n        );\n      } else if (event.type === 'environment_input') {\n        this.processEnvironmentInput(event, eventIndex, imagesToOmit, messages);\n      } else if (event.type === 'plan_update') {\n        this.processPlanUpdate(event, messages);\n      }\n    }\n\n    if (this.maxImagesCount !== undefined) {\n      const totalImages = this.countAllImagesInEvents(events);\n      const omittedImages = imagesToOmit.size;\n\n      this.logger.info(\n        `Message history built with ${totalImages - omittedImages} images ` +\n          `(limit: ${this.maxImagesCount}, ${omittedImages} images replaced with placeholders)`,\n      );\n    }\n  }\n\n  /**\n   * Process plan update event\n   * Adds plan information as a system message to guide the agent\n   */\n  private processPlanUpdate(\n    event: AgentEventStream.PlanUpdateEvent,\n    messages: ChatCompletionMessageParam[],\n  ): void {\n    // Format the plan steps as a readable list\n    const planStepsText = event.steps\n      .map((step, index) => `${index + 1}. [${step.done ? 'DONE' : 'TODO'}] ${step.content}`)\n      .join('\\n');\n\n    // Add as system message to guide the agent's next actions\n    messages.push({\n      role: 'system',\n      content: `Current plan status:\\n${planStepsText}\\n\\nFollow this plan. If a step is done, move to the next step.`,\n    });\n  }\n\n  /**\n   * Process all images in all events\n   */\n  private countAllImagesInEvents(events: AgentEventStream.Event[]): number {\n    return events.reduce((total, event) => {\n      if (\n        (event.type === 'user_message' ||\n          event.type === 'tool_result' ||\n          event.type === 'environment_input') &&\n        Array.isArray(event.content)\n      ) {\n        return total + this.countImagesInContent(event.content);\n      }\n      return total;\n    }, 0);\n  }\n\n  /**\n   * Get a set of image references that should be omitted based on the sliding window\n   */\n  private getImagesToOmit(events: AgentEventStream.Event[]): Set<string> {\n    if (this.maxImagesCount === undefined) {\n      return new Set<string>();\n    }\n\n    // Collect all images from newest to oldest\n    const allImages = this.collectAllImageReferences(events);\n\n    // If we have more images than the limit, mark oldest ones for omission\n    const imagesToOmit = new Set<string>();\n    if (allImages.length > this.maxImagesCount) {\n      // Skip the newest maxImagesCount images, and mark the rest for omission\n      const imagesToBeOmitted = allImages.slice(this.maxImagesCount);\n\n      for (const img of imagesToBeOmitted) {\n        imagesToOmit.add(`${img.eventIndex}:${img.contentIndex}`);\n      }\n\n      this.logger.info(\n        `Image limiting: ${allImages.length} total images, omitting ${imagesToOmit.size} oldest images (limit: ${this.maxImagesCount})`,\n      );\n    }\n\n    return imagesToOmit;\n  }\n\n  /**\n   * Collect all image references from events, ordered from newest to oldest\n   */\n  private collectAllImageReferences(events: AgentEventStream.Event[]): ImageReference[] {\n    const imageReferences: ImageReference[] = [];\n\n    // Scan events in reverse order (newest first)\n    for (let eventIndex = events.length - 1; eventIndex >= 0; eventIndex--) {\n      const event = events[eventIndex];\n\n      if (\n        (event.type === 'user_message' ||\n          event.type === 'tool_result' ||\n          event.type === 'environment_input') &&\n        Array.isArray(event.content)\n      ) {\n        // Find images in this event's content\n        event.content.forEach((part, contentIndex) => {\n          if (typeof part === 'object' && (part.type === 'image_url' || part.type === 'image')) {\n            imageReferences.push({\n              eventIndex,\n              contentIndex,\n              event,\n            });\n          }\n        });\n      }\n    }\n\n    return imageReferences;\n  }\n\n  /**\n   * Process a user message\n   */\n  private processUserMessage(\n    event: AgentEventStream.UserMessageEvent,\n    eventIndex: number,\n    imagesToOmit: Set<string>,\n    messages: ChatCompletionMessageParam[],\n  ): void {\n    const content = event.content;\n\n    if (typeof content === 'string') {\n      messages.push({\n        role: 'user',\n        content: content,\n      });\n      return;\n    }\n\n    // Process the content, potentially omitting images\n    const processedContent = this.processContent(content, eventIndex, imagesToOmit);\n\n    // Add to messages\n    messages.push({\n      role: 'user',\n      content: processedContent,\n    });\n  }\n\n  /**\n   * Process content, replacing omitted images with placeholder text\n   */\n  private processContent(\n    content: string | ChatCompletionContentPart[],\n    eventIndex: number,\n    imagesToOmit: Set<string>,\n  ): ChatCompletionContentPart[] {\n    // If content is a string, convert to content part\n    if (typeof content === 'string') {\n      return [{ type: 'text', text: content }];\n    }\n\n    // If no image omission needed, return as is\n    if (imagesToOmit.size === 0) {\n      return content;\n    }\n\n    // Process each content part, potentially replacing images with placeholders\n    return content.map((part, contentIndex) => {\n      if (\n        typeof part === 'object' &&\n        part.type === 'image_url' &&\n        imagesToOmit.has(`${eventIndex}:${contentIndex}`)\n      ) {\n        return {\n          type: 'text',\n          text: '[Image omitted to conserve context]',\n        };\n      }\n      return part;\n    });\n  }\n\n  /**\n   * Process an assistant message and its tool calls\n   */\n  private processAssistantMessage(\n    assistantEvent: AgentEventStream.AssistantMessageEvent,\n    events: AgentEventStream.Event[],\n    eventIndex: number,\n    imagesToOmit: Set<string>,\n    messages: ChatCompletionMessageParam[],\n    toolCallEngine: ToolCallEngine,\n  ): void {\n    // Format the assistant message\n    const assistantResponse: AgentSingleLoopReponse = {\n      content: assistantEvent.content,\n      toolCalls: assistantEvent.toolCalls,\n    };\n\n    const formattedMessage = toolCallEngine.buildHistoricalAssistantMessage(assistantResponse);\n    messages.push(formattedMessage);\n\n    // Process tool calls if present\n    if (assistantEvent.toolCalls?.length) {\n      this.processToolCalls(assistantEvent, events, imagesToOmit, messages, toolCallEngine);\n    }\n  }\n\n  /**\n   * Process tool calls and their results\n   */\n  private processToolCalls(\n    assistantEvent: AgentEventStream.AssistantMessageEvent,\n    events: AgentEventStream.Event[],\n    imagesToOmit: Set<string>,\n    messages: ChatCompletionMessageParam[],\n    toolCallEngine: ToolCallEngine,\n  ): void {\n    // Find corresponding tool results\n    const toolResults = this.findToolResultsForAssistantMessage(assistantEvent, events);\n\n    // If no results, return early\n    if (toolResults.length === 0) {\n      return;\n    }\n\n    // Convert to multimodal format and process\n    const multimodalResults = toolResults.map((result) => {\n      const convertedResult = convertToMultimodalToolCallResult(result);\n\n      // Apply image omission to tool results if needed\n      if (imagesToOmit.size > 0 && Array.isArray(convertedResult.content)) {\n        // Find the event index for this tool result\n        const toolResultEventIndex = events.findIndex(\n          (e) => e.type === 'tool_result' && e.toolCallId === result.toolCallId,\n        );\n\n        if (toolResultEventIndex !== -1) {\n          convertedResult.content = this.processContent(\n            convertedResult.content,\n            toolResultEventIndex,\n            imagesToOmit,\n          );\n        }\n      }\n\n      return convertedResult;\n    });\n\n    // Format and add the tool results\n    const toolResultMessages =\n      toolCallEngine.buildHistoricalToolCallResultMessages(multimodalResults);\n    messages.push(...toolResultMessages);\n  }\n\n  /**\n   * Helper method to find all tool results associated with an assistant message's tool calls\n   */\n  private findToolResultsForAssistantMessage(\n    assistantEvent: AgentEventStream.AssistantMessageEvent,\n    events: AgentEventStream.Event[],\n  ) {\n    // If no tool calls in the message, return empty array\n    if (!assistantEvent.toolCalls?.length) {\n      return [];\n    }\n\n    // Get all tool call IDs from the assistant message\n    const toolCallIds = assistantEvent.toolCalls.map((tc) => tc.id);\n    const assistantIndex = events.findIndex((e) => e.id === assistantEvent.id);\n    const toolResults: { toolCallId: string; toolName: string; content: any }[] = [];\n\n    // Find tool results after this assistant message until next conversation turn\n    for (let i = assistantIndex + 1; i < events.length; i++) {\n      const event = events[i];\n\n      // Stop at new conversation turn\n      if (\n        event.type === 'user_message' ||\n        (event.type === 'assistant_message' && event !== assistantEvent)\n      ) {\n        break;\n      }\n\n      // Process tool result event\n      if (event.type === 'tool_result') {\n        const toolResult = event;\n        if (toolCallIds.includes(toolResult.toolCallId)) {\n          toolResults.push({\n            toolCallId: toolResult.toolCallId,\n            toolName: toolResult.name,\n            content: toolResult.content,\n          });\n        }\n      }\n    }\n\n    return toolResults;\n  }\n\n  /**\n   * Count the number of images in multimodal content\n   */\n  private countImagesInContent(content: ChatCompletionContentPart[]): number {\n    if (!Array.isArray(content)) {\n      return 0;\n    }\n\n    return content.filter((part) => typeof part === 'object' && part.type === 'image_url').length;\n  }\n\n  /**\n   * Generate the system prompt with current time\n   */\n  getSystemPromptWithTime(instructions: string): string {\n    if (isTest()) {\n      return `${instructions}\n\nCurrent time: 5/20/2025, 10:00:00 AM`;\n    }\n\n    return `${instructions}\n\nCurrent time: ${new Date().toLocaleString()}`;\n  }\n\n  /**\n   * Process environment input event\n   * Adds environment context as a user-like message but with a specific role\n   */\n  private processEnvironmentInput(\n    event: AgentEventStream.EnvironmentInputEvent,\n    eventIndex: number,\n    imagesToOmit: Set<string>,\n    messages: ChatCompletionMessageParam[],\n  ): void {\n    const content = event.content;\n    const description = event.description || 'Environment Input';\n\n    if (typeof content === 'string') {\n      messages.push({\n        role: 'user',\n        content: `[Environment: ${description}] ${content}`,\n      });\n      return;\n    }\n\n    // Process the content, potentially omitting images\n    const processedContent = this.processContent(content, eventIndex, imagesToOmit);\n\n    // For multimodal content, add a text part with the description if not already present\n    const hasTextPart = processedContent.some((part) => part.type === 'text');\n\n    const finalContent = [...processedContent];\n    if (!hasTextPart && event.description) {\n      finalContent.unshift({\n        type: 'text',\n        text: `[Environment: ${description}]`,\n      });\n    } else if (hasTextPart && event.description) {\n      // If there's already text, prefix the first text part\n      const firstTextIndex = finalContent.findIndex((part) => part.type === 'text');\n      if (firstTextIndex >= 0) {\n        const textPart = finalContent[firstTextIndex] as { type: 'text'; text: string };\n        finalContent[firstTextIndex] = {\n          ...textPart,\n          text: `[Environment: ${description}] ${textPart.text}`,\n        };\n      }\n    }\n\n    // Add to messages\n    messages.push({\n      role: 'user',\n      content: finalContent,\n    });\n  }\n}\n"],"names":["MessageHistory","toolCallEngine","customSystemPrompt","tools","baseSystemPrompt","enhancedSystemPrompt","messages","events","imagesToOmit","undefined","Set","eventIndex","event","totalImages","omittedImages","planStepsText","step","index","total","Array","allImages","imagesToBeOmitted","img","imageReferences","part","contentIndex","content","processedContent","assistantEvent","_assistantEvent_toolCalls","assistantResponse","formattedMessage","toolResults","multimodalResults","result","convertedResult","convertToMultimodalToolCallResult","toolResultEventIndex","e","toolResultMessages","toolCallIds","tc","assistantIndex","i","toolResult","instructions","isTest","Date","description","hasTextPart","finalContent","firstTextIndex","textPart","eventStream","maxImagesCount","getLogger"],"mappings":"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"}