{"version":3,"file":"engines/prompt-engineering-tool-call-engine.mjs","sources":["webpack://@multimodal/agent/./src/engines/prompt-engineering-tool-call-engine.ts"],"sourcesContent":["// /multimodal/agent/src/engines/prompt-engineering-tool-call-engine.ts\nimport { EventEmitter } from 'events';\nimport { v4 as uuidv4 } from 'uuid';\nimport type { AgentStreamingEvent, ToolCall } from '../types';\n\ntype ParsingState = 'normal' | 'in_tool_call' | 'collecting_tool_name' | 'collecting_tool_call';\n\ninterface StreamingToolCall {\n  id: string;\n  name: string;\n  arguments: string;\n  argumentsStarted: boolean;\n  nameComplete: boolean;\n}\n\nexport class PromptEngineeringToolCallEngine extends EventEmitter {\n  private state: ParsingState = 'normal';\n  private buffer = '';\n  private currentToolCall: StreamingToolCall | null = null;\n  private streamingToolCallUpdates: Map<string, StreamingToolCall> = new Map();\n  private messageId: string;\n  private toolCallIdCounter = 0;\n\n  constructor(messageId: string) {\n    super();\n    this.messageId = messageId;\n  }\n\n  processChunk(chunk: string): void {\n    this.buffer += chunk;\n\n    while (this.buffer.length > 0) {\n      const processed = this.processBuffer();\n      if (!processed) break;\n    }\n  }\n\n  private processBuffer(): boolean {\n    switch (this.state) {\n      case 'normal':\n        return this.handleNormalState();\n      case 'in_tool_call':\n        return this.handleInToolCallState();\n      case 'collecting_tool_name':\n        return this.handleCollectingToolNameState();\n      case 'collecting_tool_call':\n        return this.handleCollectingToolCallState();\n      default:\n        return false;\n    }\n  }\n\n  private handleNormalState(): boolean {\n    const toolCallStart = this.buffer.indexOf('<tool_call>');\n\n    if (toolCallStart === -1) {\n      // Emit all remaining content as normal content\n      if (this.buffer.length > 0) {\n        this.emitContentChunk(this.buffer);\n        this.buffer = '';\n      }\n      return false;\n    }\n\n    // Emit content before tool_call as normal content\n    if (toolCallStart > 0) {\n      this.emitContentChunk(this.buffer.slice(0, toolCallStart));\n    }\n\n    // Remove processed content and transition to tool_call state\n    this.buffer = this.buffer.slice(toolCallStart + '<tool_call>'.length);\n    this.state = 'in_tool_call';\n    this.initializeNewToolCall();\n\n    return true;\n  }\n\n  private handleInToolCallState(): boolean {\n    // Look for JSON start\n    const jsonStartMatch = this.buffer.match(/^\\s*{/);\n    if (jsonStartMatch) {\n      const matchLength = jsonStartMatch[0].length;\n      this.buffer = this.buffer.slice(matchLength);\n\n      // Start collecting tool call content\n      this.state = 'collecting_tool_call';\n      this.currentToolCall!.argumentsStarted = true;\n\n      // Emit the opening brace as first argument chunk\n      this.emitToolCallChunk('{');\n\n      return true;\n    }\n\n    // If we have more than reasonable whitespace, something is wrong\n    if (this.buffer.length > 10) {\n      this.handleError('Invalid tool call format');\n      return false;\n    }\n\n    return false;\n  }\n\n  private handleCollectingToolNameState(): boolean {\n    // This state is not used in current flow, but kept for completeness\n    return false;\n  }\n\n  private handleCollectingToolCallState(): boolean {\n    const toolCallEnd = this.buffer.indexOf('</tool_call>');\n\n    if (toolCallEnd === -1) {\n      // No end tag found, emit all current buffer content as tool call arguments\n      if (this.buffer.length > 0 && this.currentToolCall?.nameComplete) {\n        this.emitToolCallChunk(this.buffer);\n        this.buffer = '';\n      }\n      return false;\n    }\n\n    // Found end tag, process content before it\n    const toolCallContent = this.buffer.slice(0, toolCallEnd);\n\n    if (toolCallContent.length > 0) {\n      this.parseAndEmitToolCallContent(toolCallContent);\n    }\n\n    // Complete the tool call\n    this.completeCurrentToolCall();\n\n    // Remove processed content and return to normal state\n    this.buffer = this.buffer.slice(toolCallEnd + '</tool_call>'.length);\n    this.state = 'normal';\n\n    return true;\n  }\n\n  private parseAndEmitToolCallContent(content: string): void {\n    if (!this.currentToolCall) return;\n\n    try {\n      // Try to parse the JSON to extract tool name if not already extracted\n      if (!this.currentToolCall.nameComplete) {\n        const nameMatch = content.match(/\"name\"\\s*:\\s*\"([^\"]+)\"/);\n        if (nameMatch) {\n          this.currentToolCall.name = nameMatch[1];\n          this.currentToolCall.nameComplete = true;\n        }\n      }\n\n      // If tool name is complete, emit the content as arguments\n      if (this.currentToolCall.nameComplete) {\n        this.emitToolCallChunk(content);\n      }\n    } catch (error) {\n      // If parsing fails, still emit the content if tool name is known\n      if (this.currentToolCall.nameComplete) {\n        this.emitToolCallChunk(content);\n      }\n    }\n  }\n\n  private initializeNewToolCall(): void {\n    this.toolCallIdCounter++;\n    this.currentToolCall = {\n      id: `call_${Date.now()}_${this.generateRandomId()}`,\n      name: '',\n      arguments: '',\n      argumentsStarted: false,\n      nameComplete: false,\n    };\n  }\n\n  private emitToolCallChunk(argumentChunk: string): void {\n    if (!this.currentToolCall || !this.currentToolCall.nameComplete) return;\n\n    this.currentToolCall.arguments += argumentChunk;\n\n    // Update streaming tool call\n    this.streamingToolCallUpdates.set(this.currentToolCall.id, { ...this.currentToolCall });\n\n    const event: AgentStreamingEvent = {\n      id: uuidv4(),\n      type: 'assistant_streaming_tool_call',\n      timestamp: Date.now(),\n      toolCallId: this.currentToolCall.id,\n      toolName: this.currentToolCall.name,\n      arguments: argumentChunk, // Emit original chunk, not cumulative\n      isComplete: false,\n      messageId: this.messageId,\n    };\n\n    this.emit('streaming_event', event);\n  }\n\n  private emitContentChunk(content: string): void {\n    const event: AgentStreamingEvent = {\n      id: uuidv4(),\n      type: 'assistant_streaming_content',\n      timestamp: Date.now(),\n      content,\n      messageId: this.messageId,\n    };\n\n    this.emit('streaming_event', event);\n  }\n\n  private completeCurrentToolCall(): void {\n    if (!this.currentToolCall || !this.currentToolCall.nameComplete) return;\n\n    // Emit final tool call completion event\n    const event: AgentStreamingEvent = {\n      id: uuidv4(),\n      type: 'assistant_streaming_tool_call',\n      timestamp: Date.now(),\n      toolCallId: this.currentToolCall.id,\n      toolName: this.currentToolCall.name,\n      arguments: '', // Empty for completion event\n      isComplete: true,\n      messageId: this.messageId,\n    };\n\n    this.emit('streaming_event', event);\n    this.currentToolCall = null;\n  }\n\n  private handleError(message: string): void {\n    this.state = 'normal';\n    this.currentToolCall = null;\n    this.buffer = '';\n    console.error(`PromptEngineeringToolCallEngine error: ${message}`);\n  }\n\n  private generateRandomId(): string {\n    return Math.random().toString(36).substring(2, 15);\n  }\n\n  // Get final parsed tool calls\n  getToolCalls(): ToolCall[] {\n    const toolCalls: ToolCall[] = [];\n\n    for (const streamingCall of this.streamingToolCallUpdates.values()) {\n      if (streamingCall.nameComplete && streamingCall.arguments) {\n        try {\n          const parsedArguments = JSON.parse(streamingCall.arguments);\n          toolCalls.push({\n            id: streamingCall.id,\n            name: streamingCall.name,\n            arguments: parsedArguments,\n          });\n        } catch (error) {\n          console.error(`Failed to parse tool call arguments: ${error}`);\n        }\n      }\n    }\n\n    return toolCalls;\n  }\n\n  // Finalize processing\n  finalize(): void {\n    // Process any remaining buffer content\n    if (this.buffer.length > 0) {\n      if (this.state === 'normal') {\n        this.emitContentChunk(this.buffer);\n      } else if (this.state === 'collecting_tool_call' && this.currentToolCall?.nameComplete) {\n        this.parseAndEmitToolCallContent(this.buffer);\n        this.completeCurrentToolCall();\n      }\n    }\n\n    this.buffer = '';\n    this.state = 'normal';\n    this.currentToolCall = null;\n  }\n}\n"],"names":["PromptEngineeringToolCallEngine","EventEmitter","chunk","processed","toolCallStart","jsonStartMatch","matchLength","toolCallEnd","_this_currentToolCall","toolCallContent","content","nameMatch","error","Date","argumentChunk","event","uuidv4","message","console","Math","toolCalls","streamingCall","parsedArguments","JSON","messageId","Map"],"mappings":"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"}