illuma-agents 1.0.36 → 1.0.38

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 (128) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +69 -14
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/enum.cjs +3 -1
  4. package/dist/cjs/common/enum.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +50 -8
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/graphs/MultiAgentGraph.cjs +277 -11
  8. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  9. package/dist/cjs/llm/bedrock/index.cjs +128 -61
  10. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  11. package/dist/cjs/main.cjs +16 -7
  12. package/dist/cjs/main.cjs.map +1 -1
  13. package/dist/cjs/messages/cache.cjs +1 -0
  14. package/dist/cjs/messages/cache.cjs.map +1 -1
  15. package/dist/cjs/messages/core.cjs +1 -1
  16. package/dist/cjs/messages/core.cjs.map +1 -1
  17. package/dist/cjs/messages/tools.cjs +2 -2
  18. package/dist/cjs/messages/tools.cjs.map +1 -1
  19. package/dist/cjs/stream.cjs +4 -2
  20. package/dist/cjs/stream.cjs.map +1 -1
  21. package/dist/cjs/tools/BrowserTools.cjs +27 -3
  22. package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
  23. package/dist/cjs/tools/CodeExecutor.cjs +22 -21
  24. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  25. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +14 -11
  26. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  27. package/dist/cjs/tools/ToolNode.cjs +101 -2
  28. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  29. package/dist/cjs/tools/ToolSearch.cjs +862 -0
  30. package/dist/cjs/tools/ToolSearch.cjs.map +1 -0
  31. package/dist/esm/agents/AgentContext.mjs +69 -14
  32. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  33. package/dist/esm/common/enum.mjs +3 -1
  34. package/dist/esm/common/enum.mjs.map +1 -1
  35. package/dist/esm/graphs/Graph.mjs +51 -9
  36. package/dist/esm/graphs/Graph.mjs.map +1 -1
  37. package/dist/esm/graphs/MultiAgentGraph.mjs +278 -12
  38. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  39. package/dist/esm/llm/bedrock/index.mjs +127 -60
  40. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  41. package/dist/esm/main.mjs +1 -1
  42. package/dist/esm/messages/cache.mjs +1 -0
  43. package/dist/esm/messages/cache.mjs.map +1 -1
  44. package/dist/esm/messages/core.mjs +1 -1
  45. package/dist/esm/messages/core.mjs.map +1 -1
  46. package/dist/esm/messages/tools.mjs +2 -2
  47. package/dist/esm/messages/tools.mjs.map +1 -1
  48. package/dist/esm/stream.mjs +4 -2
  49. package/dist/esm/stream.mjs.map +1 -1
  50. package/dist/esm/tools/BrowserTools.mjs +27 -3
  51. package/dist/esm/tools/BrowserTools.mjs.map +1 -1
  52. package/dist/esm/tools/CodeExecutor.mjs +22 -21
  53. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  54. package/dist/esm/tools/ProgrammaticToolCalling.mjs +14 -11
  55. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  56. package/dist/esm/tools/ToolNode.mjs +102 -3
  57. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  58. package/dist/esm/tools/ToolSearch.mjs +827 -0
  59. package/dist/esm/tools/ToolSearch.mjs.map +1 -0
  60. package/dist/types/agents/AgentContext.d.ts +33 -1
  61. package/dist/types/common/enum.d.ts +4 -2
  62. package/dist/types/graphs/Graph.d.ts +6 -0
  63. package/dist/types/graphs/MultiAgentGraph.d.ts +16 -0
  64. package/dist/types/index.d.ts +1 -1
  65. package/dist/types/llm/bedrock/index.d.ts +89 -11
  66. package/dist/types/llm/bedrock/types.d.ts +27 -0
  67. package/dist/types/llm/bedrock/utils/index.d.ts +5 -0
  68. package/dist/types/llm/bedrock/utils/message_inputs.d.ts +31 -0
  69. package/dist/types/llm/bedrock/utils/message_outputs.d.ts +33 -0
  70. package/dist/types/tools/BrowserTools.d.ts +2 -0
  71. package/dist/types/tools/CodeExecutor.d.ts +0 -3
  72. package/dist/types/tools/ProgrammaticToolCalling.d.ts +0 -3
  73. package/dist/types/tools/ToolNode.d.ts +3 -1
  74. package/dist/types/tools/ToolSearch.d.ts +148 -0
  75. package/dist/types/types/graph.d.ts +2 -0
  76. package/dist/types/types/llm.d.ts +3 -1
  77. package/dist/types/types/tools.d.ts +42 -2
  78. package/package.json +12 -5
  79. package/src/agents/AgentContext.ts +88 -16
  80. package/src/common/enum.ts +3 -1
  81. package/src/graphs/Graph.ts +64 -13
  82. package/src/graphs/MultiAgentGraph.ts +350 -13
  83. package/src/index.ts +1 -1
  84. package/src/llm/bedrock/index.ts +221 -99
  85. package/src/llm/bedrock/llm.spec.ts +616 -0
  86. package/src/llm/bedrock/types.ts +51 -0
  87. package/src/llm/bedrock/utils/index.ts +18 -0
  88. package/src/llm/bedrock/utils/message_inputs.ts +563 -0
  89. package/src/llm/bedrock/utils/message_outputs.ts +310 -0
  90. package/src/messages/__tests__/tools.test.ts +21 -21
  91. package/src/messages/cache.test.ts +259 -0
  92. package/src/messages/cache.ts +104 -1
  93. package/src/messages/core.ts +1 -1
  94. package/src/messages/tools.ts +2 -2
  95. package/src/scripts/caching.ts +27 -19
  96. package/src/scripts/code_exec_files.ts +58 -15
  97. package/src/scripts/code_exec_multi_session.ts +241 -0
  98. package/src/scripts/code_exec_session.ts +282 -0
  99. package/src/scripts/multi-agent-conditional.ts +1 -0
  100. package/src/scripts/multi-agent-supervisor.ts +1 -0
  101. package/src/scripts/programmatic_exec_agent.ts +4 -4
  102. package/src/scripts/test-handoff-preamble.ts +277 -0
  103. package/src/scripts/test-parallel-handoffs.ts +291 -0
  104. package/src/scripts/test-tools-before-handoff.ts +8 -4
  105. package/src/scripts/test_code_api.ts +361 -0
  106. package/src/scripts/thinking-bedrock.ts +159 -0
  107. package/src/scripts/thinking.ts +39 -18
  108. package/src/scripts/{tool_search_regex.ts → tool_search.ts} +5 -5
  109. package/src/scripts/tools.ts +7 -3
  110. package/src/stream.ts +4 -2
  111. package/src/tools/BrowserTools.ts +68 -14
  112. package/src/tools/CodeExecutor.ts +26 -23
  113. package/src/tools/ProgrammaticToolCalling.ts +18 -14
  114. package/src/tools/ToolNode.ts +114 -1
  115. package/src/tools/ToolSearch.ts +1041 -0
  116. package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +0 -2
  117. package/src/tools/__tests__/{ToolSearchRegex.integration.test.ts → ToolSearch.integration.test.ts} +6 -6
  118. package/src/tools/__tests__/ToolSearch.test.ts +1003 -0
  119. package/src/types/graph.ts +2 -0
  120. package/src/types/llm.ts +3 -1
  121. package/src/types/tools.ts +51 -2
  122. package/dist/cjs/tools/ToolSearchRegex.cjs +0 -455
  123. package/dist/cjs/tools/ToolSearchRegex.cjs.map +0 -1
  124. package/dist/esm/tools/ToolSearchRegex.mjs +0 -448
  125. package/dist/esm/tools/ToolSearchRegex.mjs.map +0 -1
  126. package/dist/types/tools/ToolSearchRegex.d.ts +0 -80
  127. package/src/tools/ToolSearchRegex.ts +0 -535
  128. package/src/tools/__tests__/ToolSearchRegex.test.ts +0 -232
@@ -1 +1 @@
1
- {"version":3,"file":"tools.mjs","sources":["../../../src/messages/tools.ts"],"sourcesContent":["// src/messages/toolDiscovery.ts\nimport { AIMessageChunk, ToolMessage } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { Constants, MessageTypes } from '@/common';\nimport { findLastIndex } from './core';\n\ntype ToolSearchArtifact = {\n tool_references?: Array<{ tool_name: string }>;\n};\n\n/**\n * Extracts discovered tool names from tool search results in the current turn.\n * Only processes tool search messages after the latest AI message with tool calls.\n *\n * Similar pattern to formatArtifactPayload - finds relevant messages efficiently\n * by identifying the latest AI parent and only processing subsequent tool messages.\n *\n * @param messages - All messages in the conversation\n * @returns Array of discovered tool names (empty if no new discoveries)\n */\nexport function extractToolDiscoveries(messages: BaseMessage[]): string[] {\n const lastMessage = messages[messages.length - 1];\n // Use getType() instead of instanceof to avoid module mismatch issues\n if (lastMessage.getType() !== MessageTypes.TOOL) return [];\n const lastToolMessage = lastMessage as ToolMessage;\n\n // Find the latest AIMessage with tool_calls that this tool message belongs to\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastToolMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return [];\n\n // Collect tool_call_ids from the AI message\n const aiMessage = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);\n\n // Only process tool search results after the AI message that belong to this turn\n const discoveredNames: string[] = [];\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n // Use getType() instead of instanceof to avoid module mismatch issues\n if (msg.getType() !== MessageTypes.TOOL) continue;\n const toolMsg = msg as ToolMessage;\n if (toolMsg.name !== Constants.TOOL_SEARCH_REGEX) continue;\n if (!toolCallIds.has(toolMsg.tool_call_id)) continue;\n\n // This is a tool search result from the current turn\n if (typeof toolMsg.artifact === 'object' && toolMsg.artifact != null) {\n const artifact = toolMsg.artifact as ToolSearchArtifact;\n if (artifact.tool_references && artifact.tool_references.length > 0) {\n for (const ref of artifact.tool_references) {\n discoveredNames.push(ref.tool_name);\n }\n }\n }\n }\n\n return discoveredNames;\n}\n\n/**\n * Checks if the current turn has any tool search results.\n * Quick check to avoid full extraction when not needed.\n */\nexport function hasToolSearchInCurrentTurn(messages: BaseMessage[]): boolean {\n const lastMessage = messages[messages.length - 1];\n // Use getType() instead of instanceof to avoid module mismatch issues\n if (lastMessage.getType() !== MessageTypes.TOOL) return false;\n const lastToolMessage = lastMessage as ToolMessage;\n\n // Find the latest AIMessage with tool_calls\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastToolMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return false;\n\n const aiMessage = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);\n\n // Check if any tool search results exist after the AI message\n // Use getType() instead of instanceof to avoid module mismatch issues\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n if (\n msg.getType() === MessageTypes.TOOL &&\n (msg as ToolMessage).name === Constants.TOOL_SEARCH_REGEX &&\n toolCallIds.has((msg as ToolMessage).tool_call_id)\n ) {\n return true;\n }\n }\n\n return false;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tools.mjs","sources":["../../../src/messages/tools.ts"],"sourcesContent":["// src/messages/toolDiscovery.ts\nimport { AIMessageChunk, ToolMessage } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { Constants, MessageTypes } from '@/common';\nimport { findLastIndex } from './core';\n\ntype ToolSearchArtifact = {\n tool_references?: Array<{ tool_name: string }>;\n};\n\n/**\n * Extracts discovered tool names from tool search results in the current turn.\n * Only processes tool search messages after the latest AI message with tool calls.\n *\n * Similar pattern to formatArtifactPayload - finds relevant messages efficiently\n * by identifying the latest AI parent and only processing subsequent tool messages.\n *\n * @param messages - All messages in the conversation\n * @returns Array of discovered tool names (empty if no new discoveries)\n */\nexport function extractToolDiscoveries(messages: BaseMessage[]): string[] {\n const lastMessage = messages[messages.length - 1];\n // Use getType() instead of instanceof to avoid module mismatch issues\n if (lastMessage.getType() !== MessageTypes.TOOL) return [];\n const lastToolMessage = lastMessage as ToolMessage;\n\n // Find the latest AIMessage with tool_calls that this tool message belongs to\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastToolMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return [];\n\n // Collect tool_call_ids from the AI message\n const aiMessage = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);\n\n // Only process tool search results after the AI message that belong to this turn\n const discoveredNames: string[] = [];\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n // Use getType() instead of instanceof to avoid module mismatch issues\n if (msg.getType() !== MessageTypes.TOOL) continue;\n const toolMsg = msg as ToolMessage;\n if (toolMsg.name !== Constants.TOOL_SEARCH) continue;\n if (!toolCallIds.has(toolMsg.tool_call_id)) continue;\n\n // This is a tool search result from the current turn\n if (typeof toolMsg.artifact === 'object' && toolMsg.artifact != null) {\n const artifact = toolMsg.artifact as ToolSearchArtifact;\n if (artifact.tool_references && artifact.tool_references.length > 0) {\n for (const ref of artifact.tool_references) {\n discoveredNames.push(ref.tool_name);\n }\n }\n }\n }\n\n return discoveredNames;\n}\n\n/**\n * Checks if the current turn has any tool search results.\n * Quick check to avoid full extraction when not needed.\n */\nexport function hasToolSearchInCurrentTurn(messages: BaseMessage[]): boolean {\n const lastMessage = messages[messages.length - 1];\n // Use getType() instead of instanceof to avoid module mismatch issues\n if (lastMessage.getType() !== MessageTypes.TOOL) return false;\n const lastToolMessage = lastMessage as ToolMessage;\n\n // Find the latest AIMessage with tool_calls\n const latestAIParentIndex = findLastIndex(\n messages,\n (msg) =>\n (msg instanceof AIMessageChunk &&\n (msg.tool_calls?.length ?? 0) > 0 &&\n msg.tool_calls?.some((tc) => tc.id === lastToolMessage.tool_call_id)) ??\n false\n );\n\n if (latestAIParentIndex === -1) return false;\n\n const aiMessage = messages[latestAIParentIndex] as AIMessageChunk;\n const toolCallIds = new Set(aiMessage.tool_calls?.map((tc) => tc.id) ?? []);\n\n // Check if any tool search results exist after the AI message\n // Use getType() instead of instanceof to avoid module mismatch issues\n for (let i = latestAIParentIndex + 1; i < messages.length; i++) {\n const msg = messages[i];\n if (\n msg.getType() === MessageTypes.TOOL &&\n (msg as ToolMessage).name === Constants.TOOL_SEARCH &&\n toolCallIds.has((msg as ToolMessage).tool_call_id)\n ) {\n return true;\n }\n }\n\n return false;\n}\n"],"names":[],"mappings":"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"}
@@ -252,7 +252,8 @@ hasToolCallChunks: ${hasToolCallChunks}
252
252
  }
253
253
  else if (content.every((c) => (c.type?.startsWith(ContentTypes.THINKING) ?? false) ||
254
254
  (c.type?.startsWith(ContentTypes.REASONING) ?? false) ||
255
- (c.type?.startsWith(ContentTypes.REASONING_CONTENT) ?? false))) {
255
+ (c.type?.startsWith(ContentTypes.REASONING_CONTENT) ?? false) ||
256
+ c.type === 'redacted_thinking')) {
256
257
  await graph.dispatchReasoningDelta(stepId, {
257
258
  content: content.map((c) => ({
258
259
  type: ContentTypes.THINK,
@@ -269,7 +270,8 @@ hasToolCallChunks: ${hasToolCallChunks}
269
270
  if (Array.isArray(chunk.content) &&
270
271
  (chunk.content[0]?.type === ContentTypes.THINKING ||
271
272
  chunk.content[0]?.type === ContentTypes.REASONING ||
272
- chunk.content[0]?.type === ContentTypes.REASONING_CONTENT)) {
273
+ chunk.content[0]?.type === ContentTypes.REASONING_CONTENT ||
274
+ chunk.content[0]?.type === 'redacted_thinking')) {
273
275
  reasoning_content = 'valid';
274
276
  }
275
277
  else if ((agentContext.provider === Providers.OPENAI ||
@@ -1 +1 @@
1
- {"version":3,"file":"stream.mjs","sources":["../../src/stream.ts"],"sourcesContent":["// src/stream.ts\nimport type { ChatOpenAIReasoningSummary } from '@langchain/openai';\nimport type { AIMessageChunk } from '@langchain/core/messages';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type { AgentContext } from '@/agents/AgentContext';\nimport type { StandardGraph } from '@/graphs';\nimport type * as t from '@/types';\nimport {\n ToolCallTypes,\n ContentTypes,\n GraphEvents,\n StepTypes,\n Providers,\n} from '@/common';\nimport {\n handleServerToolResult,\n handleToolCallChunks,\n handleToolCalls,\n} from '@/tools/handlers';\nimport { getMessageId } from '@/messages';\n\n/**\n * Parses content to extract thinking sections enclosed in <think> tags using string operations\n * @param content The content to parse\n * @returns An object with separated text and thinking content\n */\nfunction parseThinkingContent(content: string): {\n text: string;\n thinking: string;\n} {\n // If no think tags, return the original content as text\n if (!content.includes('<think>')) {\n return { text: content, thinking: '' };\n }\n\n let textResult = '';\n const thinkingResult: string[] = [];\n let position = 0;\n\n while (position < content.length) {\n const thinkStart = content.indexOf('<think>', position);\n\n if (thinkStart === -1) {\n // No more think tags, add the rest and break\n textResult += content.slice(position);\n break;\n }\n\n // Add text before the think tag\n textResult += content.slice(position, thinkStart);\n\n const thinkEnd = content.indexOf('</think>', thinkStart);\n if (thinkEnd === -1) {\n // Malformed input, no closing tag\n textResult += content.slice(thinkStart);\n break;\n }\n\n // Add the thinking content\n const thinkContent = content.slice(thinkStart + 7, thinkEnd);\n thinkingResult.push(thinkContent);\n\n // Move position to after the think tag\n position = thinkEnd + 8; // 8 is the length of '</think>'\n }\n\n return {\n text: textResult.trim(),\n thinking: thinkingResult.join('\\n').trim(),\n };\n}\n\nfunction getNonEmptyValue(possibleValues: string[]): string | undefined {\n for (const value of possibleValues) {\n if (value && value.trim() !== '') {\n return value;\n }\n }\n return undefined;\n}\n\nexport function getChunkContent({\n chunk,\n provider,\n reasoningKey,\n}: {\n chunk?: Partial<AIMessageChunk>;\n provider?: Providers;\n reasoningKey: 'reasoning_content' | 'reasoning';\n}): string | t.MessageContentComplex[] | undefined {\n if (\n (provider === Providers.OPENAI || provider === Providers.AZURE) &&\n (\n chunk?.additional_kwargs?.reasoning as\n | Partial<ChatOpenAIReasoningSummary>\n | undefined\n )?.summary?.[0]?.text != null &&\n ((\n chunk?.additional_kwargs?.reasoning as\n | Partial<ChatOpenAIReasoningSummary>\n | undefined\n )?.summary?.[0]?.text?.length ?? 0) > 0\n ) {\n return (\n chunk?.additional_kwargs?.reasoning as\n | Partial<ChatOpenAIReasoningSummary>\n | undefined\n )?.summary?.[0]?.text;\n }\n /**\n * For OpenRouter, reasoning is stored in additional_kwargs.reasoning (not reasoning_content).\n * NOTE: We intentionally do NOT extract text from reasoning_details here.\n * The reasoning_details array contains the FULL accumulated reasoning text (set only on final chunk),\n * but individual reasoning tokens are already streamed via additional_kwargs.reasoning.\n * Extracting from reasoning_details would cause duplication.\n * The reasoning_details is only used for:\n * 1. Detecting reasoning mode in handleReasoning()\n * 2. Final message storage (for thought signatures)\n */\n if (provider === Providers.OPENROUTER) {\n // Content presence signals end of reasoning phase - prefer content over reasoning\n // This handles transitional chunks that may have both reasoning and content\n if (typeof chunk?.content === 'string' && chunk.content !== '') {\n return chunk.content;\n }\n const reasoning = chunk?.additional_kwargs?.reasoning as string | undefined;\n if (reasoning != null && reasoning !== '') {\n return reasoning;\n }\n return chunk?.content;\n }\n return (\n ((chunk?.additional_kwargs?.[reasoningKey] as string | undefined) ?? '') ||\n chunk?.content\n );\n}\n\nexport class ChatModelStreamHandler implements t.EventHandler {\n async handle(\n event: string,\n data: t.StreamEventData,\n metadata?: Record<string, unknown>,\n graph?: StandardGraph\n ): Promise<void> {\n if (!graph) {\n throw new Error('Graph not found');\n }\n if (!graph.config) {\n throw new Error('Config not found in graph');\n }\n if (!data.chunk) {\n console.warn(`No chunk found in ${event} event`);\n return;\n }\n\n const agentContext = graph.getAgentContext(metadata);\n\n const chunk = data.chunk as Partial<AIMessageChunk>;\n const content = getChunkContent({\n chunk,\n reasoningKey: agentContext.reasoningKey,\n provider: agentContext.provider,\n });\n const skipHandling = await handleServerToolResult({\n graph,\n content,\n metadata,\n agentContext,\n });\n if (skipHandling) {\n return;\n }\n this.handleReasoning(chunk, agentContext);\n let hasToolCalls = false;\n if (\n chunk.tool_calls &&\n chunk.tool_calls.length > 0 &&\n chunk.tool_calls.every(\n (tc) =>\n tc.id != null &&\n tc.id !== '' &&\n (tc as Partial<ToolCall>).name != null &&\n tc.name !== ''\n )\n ) {\n hasToolCalls = true;\n await handleToolCalls(chunk.tool_calls, metadata, graph);\n }\n\n const hasToolCallChunks =\n (chunk.tool_call_chunks && chunk.tool_call_chunks.length > 0) ?? false;\n const isEmptyContent =\n typeof content === 'undefined' ||\n !content.length ||\n (typeof content === 'string' && !content);\n\n /** Set a preliminary message ID if found in empty chunk */\n const isEmptyChunk = isEmptyContent && !hasToolCallChunks;\n if (\n isEmptyChunk &&\n (chunk.id ?? '') !== '' &&\n !graph.prelimMessageIdsByStepKey.has(chunk.id ?? '')\n ) {\n const stepKey = graph.getStepKey(metadata);\n graph.prelimMessageIdsByStepKey.set(stepKey, chunk.id ?? '');\n } else if (isEmptyChunk) {\n return;\n }\n\n const stepKey = graph.getStepKey(metadata);\n\n if (\n hasToolCallChunks &&\n chunk.tool_call_chunks &&\n chunk.tool_call_chunks.length &&\n typeof chunk.tool_call_chunks[0]?.index === 'number'\n ) {\n await handleToolCallChunks({\n graph,\n stepKey,\n toolCallChunks: chunk.tool_call_chunks,\n metadata,\n });\n }\n\n if (isEmptyContent) {\n return;\n }\n\n const message_id = getMessageId(stepKey, graph) ?? '';\n if (message_id) {\n await graph.dispatchRunStep(\n stepKey,\n {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id,\n },\n },\n metadata\n );\n }\n\n const stepId = graph.getStepIdByKey(stepKey);\n const runStep = graph.getRunStep(stepId);\n if (!runStep) {\n console.warn(`\\n\n==============================================================\n\n\nRun step for ${stepId} does not exist, cannot dispatch delta event.\n\nevent: ${event}\nstepId: ${stepId}\nstepKey: ${stepKey}\nmessage_id: ${message_id}\nhasToolCalls: ${hasToolCalls}\nhasToolCallChunks: ${hasToolCallChunks}\n\n==============================================================\n\\n`);\n return;\n }\n\n /* Note: tool call chunks may have non-empty content that matches the current tool chunk generation */\n if (typeof content === 'string' && runStep.type === StepTypes.TOOL_CALLS) {\n return;\n } else if (\n hasToolCallChunks &&\n (chunk.tool_call_chunks?.some((tc) => tc.args === content) ?? false)\n ) {\n return;\n } else if (typeof content === 'string') {\n if (agentContext.currentTokenType === ContentTypes.TEXT) {\n await graph.dispatchMessageDelta(stepId, {\n content: [\n {\n type: ContentTypes.TEXT,\n text: content,\n },\n ],\n });\n } else if (agentContext.currentTokenType === 'think_and_text') {\n const { text, thinking } = parseThinkingContent(content);\n if (thinking) {\n await graph.dispatchReasoningDelta(stepId, {\n content: [\n {\n type: ContentTypes.THINK,\n think: thinking,\n },\n ],\n });\n }\n if (text) {\n agentContext.currentTokenType = ContentTypes.TEXT;\n agentContext.tokenTypeSwitch = 'content';\n const newStepKey = graph.getStepKey(metadata);\n const message_id = getMessageId(newStepKey, graph) ?? '';\n await graph.dispatchRunStep(\n newStepKey,\n {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id,\n },\n },\n metadata\n );\n\n const newStepId = graph.getStepIdByKey(newStepKey);\n await graph.dispatchMessageDelta(newStepId, {\n content: [\n {\n type: ContentTypes.TEXT,\n text: text,\n },\n ],\n });\n }\n } else {\n await graph.dispatchReasoningDelta(stepId, {\n content: [\n {\n type: ContentTypes.THINK,\n think: content,\n },\n ],\n });\n }\n } else if (\n content.every((c) => c.type?.startsWith(ContentTypes.TEXT) ?? false)\n ) {\n await graph.dispatchMessageDelta(stepId, {\n content,\n });\n } else if (\n content.every(\n (c) =>\n (c.type?.startsWith(ContentTypes.THINKING) ?? false) ||\n (c.type?.startsWith(ContentTypes.REASONING) ?? false) ||\n (c.type?.startsWith(ContentTypes.REASONING_CONTENT) ?? false)\n )\n ) {\n await graph.dispatchReasoningDelta(stepId, {\n content: content.map((c) => ({\n type: ContentTypes.THINK,\n think:\n (c as t.ThinkingContentText).thinking ??\n (c as Partial<t.GoogleReasoningContentText>).reasoning ??\n (c as Partial<t.BedrockReasoningContentText>).reasoningText?.text ??\n '',\n })),\n });\n }\n }\n handleReasoning(\n chunk: Partial<AIMessageChunk>,\n agentContext: AgentContext\n ): void {\n let reasoning_content = chunk.additional_kwargs?.[\n agentContext.reasoningKey\n ] as string | Partial<ChatOpenAIReasoningSummary> | undefined;\n if (\n Array.isArray(chunk.content) &&\n (chunk.content[0]?.type === ContentTypes.THINKING ||\n chunk.content[0]?.type === ContentTypes.REASONING ||\n chunk.content[0]?.type === ContentTypes.REASONING_CONTENT)\n ) {\n reasoning_content = 'valid';\n } else if (\n (agentContext.provider === Providers.OPENAI ||\n agentContext.provider === Providers.AZURE) &&\n reasoning_content != null &&\n typeof reasoning_content !== 'string' &&\n reasoning_content.summary?.[0]?.text != null &&\n reasoning_content.summary[0].text\n ) {\n reasoning_content = 'valid';\n } else if (\n agentContext.provider === Providers.OPENROUTER &&\n // Only set reasoning as valid if content is NOT present (content signals end of reasoning)\n (chunk.content == null || chunk.content === '') &&\n // Check for reasoning_details (final chunk) OR reasoning string (intermediate chunks)\n ((chunk.additional_kwargs?.reasoning_details != null &&\n Array.isArray(chunk.additional_kwargs.reasoning_details) &&\n chunk.additional_kwargs.reasoning_details.length > 0) ||\n (typeof chunk.additional_kwargs?.reasoning === 'string' &&\n chunk.additional_kwargs.reasoning !== ''))\n ) {\n reasoning_content = 'valid';\n }\n if (\n reasoning_content != null &&\n reasoning_content !== '' &&\n (chunk.content == null ||\n chunk.content === '' ||\n reasoning_content === 'valid')\n ) {\n agentContext.currentTokenType = ContentTypes.THINK;\n agentContext.tokenTypeSwitch = 'reasoning';\n return;\n } else if (\n agentContext.tokenTypeSwitch === 'reasoning' &&\n agentContext.currentTokenType !== ContentTypes.TEXT &&\n ((chunk.content != null && chunk.content !== '') ||\n (chunk.tool_calls?.length ?? 0) > 0 ||\n (chunk.tool_call_chunks?.length ?? 0) > 0)\n ) {\n agentContext.currentTokenType = ContentTypes.TEXT;\n agentContext.tokenTypeSwitch = 'content';\n } else if (\n chunk.content != null &&\n typeof chunk.content === 'string' &&\n chunk.content.includes('<think>') &&\n chunk.content.includes('</think>')\n ) {\n agentContext.currentTokenType = 'think_and_text';\n agentContext.tokenTypeSwitch = 'content';\n } else if (\n chunk.content != null &&\n typeof chunk.content === 'string' &&\n chunk.content.includes('<think>')\n ) {\n agentContext.currentTokenType = ContentTypes.THINK;\n agentContext.tokenTypeSwitch = 'content';\n } else if (\n agentContext.lastToken != null &&\n agentContext.lastToken.includes('</think>')\n ) {\n agentContext.currentTokenType = ContentTypes.TEXT;\n agentContext.tokenTypeSwitch = 'content';\n }\n if (typeof chunk.content !== 'string') {\n return;\n }\n agentContext.lastToken = chunk.content;\n }\n}\n\nexport function createContentAggregator(): t.ContentAggregatorResult {\n const contentParts: Array<t.MessageContentComplex | undefined> = [];\n const stepMap = new Map<string, t.RunStep>();\n const toolCallIdMap = new Map<string, string>();\n // Track agentId and groupId for each content index (applied to content parts)\n const contentMetaMap = new Map<\n number,\n { agentId?: string; groupId?: number }\n >();\n\n const updateContent = (\n index: number,\n contentPart?: t.MessageContentComplex,\n finalUpdate = false\n ): void => {\n if (!contentPart) {\n console.warn('No content part found in \\'updateContent\\'');\n return;\n }\n const partType = contentPart.type ?? '';\n if (!partType) {\n console.warn('No content type found in content part');\n return;\n }\n\n if (!contentParts[index]) {\n contentParts[index] = { type: partType };\n }\n\n if (!partType.startsWith(contentParts[index]?.type ?? '')) {\n console.warn('Content type mismatch');\n return;\n }\n\n if (\n partType.startsWith(ContentTypes.TEXT) &&\n ContentTypes.TEXT in contentPart &&\n typeof contentPart.text === 'string'\n ) {\n // TODO: update this!!\n const currentContent = contentParts[index] as t.MessageDeltaUpdate;\n const update: t.MessageDeltaUpdate = {\n type: ContentTypes.TEXT,\n text: (currentContent.text || '') + contentPart.text,\n };\n\n if (contentPart.tool_call_ids) {\n update.tool_call_ids = contentPart.tool_call_ids;\n }\n contentParts[index] = update;\n } else if (\n partType.startsWith(ContentTypes.THINK) &&\n ContentTypes.THINK in contentPart &&\n typeof contentPart.think === 'string'\n ) {\n const currentContent = contentParts[index] as t.ReasoningDeltaUpdate;\n const update: t.ReasoningDeltaUpdate = {\n type: ContentTypes.THINK,\n think: (currentContent.think || '') + contentPart.think,\n };\n contentParts[index] = update;\n } else if (\n partType.startsWith(ContentTypes.AGENT_UPDATE) &&\n ContentTypes.AGENT_UPDATE in contentPart &&\n contentPart.agent_update != null\n ) {\n const update: t.AgentUpdate = {\n type: ContentTypes.AGENT_UPDATE,\n agent_update: contentPart.agent_update,\n };\n\n contentParts[index] = update;\n } else if (\n partType === ContentTypes.IMAGE_URL &&\n 'image_url' in contentPart\n ) {\n const currentContent = contentParts[index] as {\n type: 'image_url';\n image_url: string;\n };\n contentParts[index] = {\n ...currentContent,\n };\n } else if (\n partType === ContentTypes.TOOL_CALL &&\n 'tool_call' in contentPart\n ) {\n const incomingName = contentPart.tool_call.name;\n const incomingId = contentPart.tool_call.id;\n const toolCallArgs = (contentPart.tool_call as t.ToolCallPart).args;\n\n // When we receive a tool call with a name, it's the complete tool call\n // Consolidate with any previously accumulated args from chunks\n const hasValidName = incomingName != null && incomingName !== '';\n\n // Only process if incoming has a valid name (complete tool call)\n // or if we're doing a final update with complete data\n if (!hasValidName && !finalUpdate) {\n return;\n }\n\n const existingContent = contentParts[index] as\n | (Omit<t.ToolCallContent, 'tool_call'> & {\n tool_call?: t.ToolCallPart;\n })\n | undefined;\n\n /** When args are a valid object, they are likely already invoked */\n let args =\n finalUpdate ||\n typeof existingContent?.tool_call?.args === 'object' ||\n typeof toolCallArgs === 'object'\n ? contentPart.tool_call.args\n : (existingContent?.tool_call?.args ?? '') + (toolCallArgs ?? '');\n if (\n finalUpdate &&\n args == null &&\n existingContent?.tool_call?.args != null\n ) {\n args = existingContent.tool_call.args;\n }\n\n const id =\n getNonEmptyValue([incomingId, existingContent?.tool_call?.id]) ?? '';\n const name =\n getNonEmptyValue([incomingName, existingContent?.tool_call?.name]) ??\n '';\n\n const newToolCall: ToolCall & t.PartMetadata = {\n id,\n name,\n args,\n type: ToolCallTypes.TOOL_CALL,\n };\n\n if (finalUpdate) {\n newToolCall.progress = 1;\n newToolCall.output = contentPart.tool_call.output;\n }\n\n contentParts[index] = {\n type: ContentTypes.TOOL_CALL,\n tool_call: newToolCall,\n };\n }\n\n // Apply agentId (for MultiAgentGraph) and groupId (for parallel execution) to content parts\n // - agentId present → MultiAgentGraph (show agent labels)\n // - groupId present → parallel execution (render columns)\n const meta = contentMetaMap.get(index);\n if (meta?.agentId != null) {\n (contentParts[index] as t.MessageContentComplex).agentId = meta.agentId;\n }\n if (meta?.groupId != null) {\n (contentParts[index] as t.MessageContentComplex).groupId = meta.groupId;\n }\n };\n\n const aggregateContent = ({\n event,\n data,\n }: {\n event: GraphEvents;\n data:\n | t.RunStep\n | t.AgentUpdate\n | t.MessageDeltaEvent\n | t.RunStepDeltaEvent\n | { result: t.ToolEndEvent };\n }): void => {\n if (event === GraphEvents.ON_RUN_STEP) {\n const runStep = data as t.RunStep;\n stepMap.set(runStep.id, runStep);\n\n // Track agentId (MultiAgentGraph) and groupId (parallel execution) separately\n // - agentId: present for all MultiAgentGraph runs (enables agent labels in UI)\n // - groupId: present only for parallel execution (enables column rendering)\n const hasAgentId = runStep.agentId != null && runStep.agentId !== '';\n const hasGroupId = runStep.groupId != null;\n if (hasAgentId || hasGroupId) {\n const existingMeta = contentMetaMap.get(runStep.index) ?? {};\n if (hasAgentId) {\n existingMeta.agentId = runStep.agentId;\n }\n if (hasGroupId) {\n existingMeta.groupId = runStep.groupId;\n }\n contentMetaMap.set(runStep.index, existingMeta);\n }\n\n // Store tool call IDs if present\n if (\n runStep.stepDetails.type === StepTypes.TOOL_CALLS &&\n runStep.stepDetails.tool_calls\n ) {\n (runStep.stepDetails.tool_calls as ToolCall[]).forEach((toolCall) => {\n const toolCallId = toolCall.id ?? '';\n if ('id' in toolCall && toolCallId) {\n toolCallIdMap.set(runStep.id, toolCallId);\n }\n const contentPart: t.MessageContentComplex = {\n type: ContentTypes.TOOL_CALL,\n tool_call: {\n args: toolCall.args,\n name: toolCall.name,\n id: toolCallId,\n },\n };\n\n updateContent(runStep.index, contentPart);\n });\n }\n } else if (event === GraphEvents.ON_MESSAGE_DELTA) {\n const messageDelta = data as t.MessageDeltaEvent;\n const runStep = stepMap.get(messageDelta.id);\n if (!runStep) {\n console.warn('No run step or runId found for message delta event');\n return;\n }\n\n if (messageDelta.delta.content) {\n const contentPart = Array.isArray(messageDelta.delta.content)\n ? messageDelta.delta.content[0]\n : messageDelta.delta.content;\n\n updateContent(runStep.index, contentPart);\n }\n } else if (\n event === GraphEvents.ON_AGENT_UPDATE &&\n (data as t.AgentUpdate | undefined)?.agent_update\n ) {\n const contentPart = data as t.AgentUpdate | undefined;\n if (!contentPart) {\n return;\n }\n updateContent(contentPart.agent_update.index, contentPart);\n } else if (event === GraphEvents.ON_REASONING_DELTA) {\n const reasoningDelta = data as t.ReasoningDeltaEvent;\n const runStep = stepMap.get(reasoningDelta.id);\n if (!runStep) {\n console.warn('No run step or runId found for reasoning delta event');\n return;\n }\n\n if (reasoningDelta.delta.content) {\n const contentPart = Array.isArray(reasoningDelta.delta.content)\n ? reasoningDelta.delta.content[0]\n : reasoningDelta.delta.content;\n\n updateContent(runStep.index, contentPart);\n }\n } else if (event === GraphEvents.ON_RUN_STEP_DELTA) {\n const runStepDelta = data as t.RunStepDeltaEvent;\n const runStep = stepMap.get(runStepDelta.id);\n if (!runStep) {\n console.warn('No run step or runId found for run step delta event');\n return;\n }\n\n if (\n runStepDelta.delta.type === StepTypes.TOOL_CALLS &&\n runStepDelta.delta.tool_calls\n ) {\n runStepDelta.delta.tool_calls.forEach((toolCallDelta) => {\n const toolCallId = toolCallIdMap.get(runStepDelta.id);\n\n const contentPart: t.MessageContentComplex = {\n type: ContentTypes.TOOL_CALL,\n tool_call: {\n args: toolCallDelta.args ?? '',\n name: toolCallDelta.name,\n id: toolCallId,\n },\n };\n\n updateContent(runStep.index, contentPart);\n });\n }\n } else if (event === GraphEvents.ON_RUN_STEP_COMPLETED) {\n const { result } = data as unknown as { result: t.ToolEndEvent };\n\n const { id: stepId } = result;\n\n const runStep = stepMap.get(stepId);\n if (!runStep) {\n console.warn(\n 'No run step or runId found for completed tool call event'\n );\n return;\n }\n\n const contentPart: t.MessageContentComplex = {\n type: ContentTypes.TOOL_CALL,\n tool_call: result.tool_call,\n };\n\n updateContent(runStep.index, contentPart, true);\n }\n };\n\n return { contentParts, aggregateContent, stepMap };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stream.mjs","sources":["../../src/stream.ts"],"sourcesContent":["// src/stream.ts\nimport type { ChatOpenAIReasoningSummary } from '@langchain/openai';\nimport type { AIMessageChunk } from '@langchain/core/messages';\nimport type { ToolCall } from '@langchain/core/messages/tool';\nimport type { AgentContext } from '@/agents/AgentContext';\nimport type { StandardGraph } from '@/graphs';\nimport type * as t from '@/types';\nimport {\n ToolCallTypes,\n ContentTypes,\n GraphEvents,\n StepTypes,\n Providers,\n} from '@/common';\nimport {\n handleServerToolResult,\n handleToolCallChunks,\n handleToolCalls,\n} from '@/tools/handlers';\nimport { getMessageId } from '@/messages';\n\n/**\n * Parses content to extract thinking sections enclosed in <think> tags using string operations\n * @param content The content to parse\n * @returns An object with separated text and thinking content\n */\nfunction parseThinkingContent(content: string): {\n text: string;\n thinking: string;\n} {\n // If no think tags, return the original content as text\n if (!content.includes('<think>')) {\n return { text: content, thinking: '' };\n }\n\n let textResult = '';\n const thinkingResult: string[] = [];\n let position = 0;\n\n while (position < content.length) {\n const thinkStart = content.indexOf('<think>', position);\n\n if (thinkStart === -1) {\n // No more think tags, add the rest and break\n textResult += content.slice(position);\n break;\n }\n\n // Add text before the think tag\n textResult += content.slice(position, thinkStart);\n\n const thinkEnd = content.indexOf('</think>', thinkStart);\n if (thinkEnd === -1) {\n // Malformed input, no closing tag\n textResult += content.slice(thinkStart);\n break;\n }\n\n // Add the thinking content\n const thinkContent = content.slice(thinkStart + 7, thinkEnd);\n thinkingResult.push(thinkContent);\n\n // Move position to after the think tag\n position = thinkEnd + 8; // 8 is the length of '</think>'\n }\n\n return {\n text: textResult.trim(),\n thinking: thinkingResult.join('\\n').trim(),\n };\n}\n\nfunction getNonEmptyValue(possibleValues: string[]): string | undefined {\n for (const value of possibleValues) {\n if (value && value.trim() !== '') {\n return value;\n }\n }\n return undefined;\n}\n\nexport function getChunkContent({\n chunk,\n provider,\n reasoningKey,\n}: {\n chunk?: Partial<AIMessageChunk>;\n provider?: Providers;\n reasoningKey: 'reasoning_content' | 'reasoning';\n}): string | t.MessageContentComplex[] | undefined {\n if (\n (provider === Providers.OPENAI || provider === Providers.AZURE) &&\n (\n chunk?.additional_kwargs?.reasoning as\n | Partial<ChatOpenAIReasoningSummary>\n | undefined\n )?.summary?.[0]?.text != null &&\n ((\n chunk?.additional_kwargs?.reasoning as\n | Partial<ChatOpenAIReasoningSummary>\n | undefined\n )?.summary?.[0]?.text?.length ?? 0) > 0\n ) {\n return (\n chunk?.additional_kwargs?.reasoning as\n | Partial<ChatOpenAIReasoningSummary>\n | undefined\n )?.summary?.[0]?.text;\n }\n /**\n * For OpenRouter, reasoning is stored in additional_kwargs.reasoning (not reasoning_content).\n * NOTE: We intentionally do NOT extract text from reasoning_details here.\n * The reasoning_details array contains the FULL accumulated reasoning text (set only on final chunk),\n * but individual reasoning tokens are already streamed via additional_kwargs.reasoning.\n * Extracting from reasoning_details would cause duplication.\n * The reasoning_details is only used for:\n * 1. Detecting reasoning mode in handleReasoning()\n * 2. Final message storage (for thought signatures)\n */\n if (provider === Providers.OPENROUTER) {\n // Content presence signals end of reasoning phase - prefer content over reasoning\n // This handles transitional chunks that may have both reasoning and content\n if (typeof chunk?.content === 'string' && chunk.content !== '') {\n return chunk.content;\n }\n const reasoning = chunk?.additional_kwargs?.reasoning as string | undefined;\n if (reasoning != null && reasoning !== '') {\n return reasoning;\n }\n return chunk?.content;\n }\n return (\n ((chunk?.additional_kwargs?.[reasoningKey] as string | undefined) ?? '') ||\n chunk?.content\n );\n}\n\nexport class ChatModelStreamHandler implements t.EventHandler {\n async handle(\n event: string,\n data: t.StreamEventData,\n metadata?: Record<string, unknown>,\n graph?: StandardGraph\n ): Promise<void> {\n if (!graph) {\n throw new Error('Graph not found');\n }\n if (!graph.config) {\n throw new Error('Config not found in graph');\n }\n if (!data.chunk) {\n console.warn(`No chunk found in ${event} event`);\n return;\n }\n\n const agentContext = graph.getAgentContext(metadata);\n\n const chunk = data.chunk as Partial<AIMessageChunk>;\n const content = getChunkContent({\n chunk,\n reasoningKey: agentContext.reasoningKey,\n provider: agentContext.provider,\n });\n const skipHandling = await handleServerToolResult({\n graph,\n content,\n metadata,\n agentContext,\n });\n if (skipHandling) {\n return;\n }\n this.handleReasoning(chunk, agentContext);\n let hasToolCalls = false;\n if (\n chunk.tool_calls &&\n chunk.tool_calls.length > 0 &&\n chunk.tool_calls.every(\n (tc) =>\n tc.id != null &&\n tc.id !== '' &&\n (tc as Partial<ToolCall>).name != null &&\n tc.name !== ''\n )\n ) {\n hasToolCalls = true;\n await handleToolCalls(chunk.tool_calls, metadata, graph);\n }\n\n const hasToolCallChunks =\n (chunk.tool_call_chunks && chunk.tool_call_chunks.length > 0) ?? false;\n const isEmptyContent =\n typeof content === 'undefined' ||\n !content.length ||\n (typeof content === 'string' && !content);\n\n /** Set a preliminary message ID if found in empty chunk */\n const isEmptyChunk = isEmptyContent && !hasToolCallChunks;\n if (\n isEmptyChunk &&\n (chunk.id ?? '') !== '' &&\n !graph.prelimMessageIdsByStepKey.has(chunk.id ?? '')\n ) {\n const stepKey = graph.getStepKey(metadata);\n graph.prelimMessageIdsByStepKey.set(stepKey, chunk.id ?? '');\n } else if (isEmptyChunk) {\n return;\n }\n\n const stepKey = graph.getStepKey(metadata);\n\n if (\n hasToolCallChunks &&\n chunk.tool_call_chunks &&\n chunk.tool_call_chunks.length &&\n typeof chunk.tool_call_chunks[0]?.index === 'number'\n ) {\n await handleToolCallChunks({\n graph,\n stepKey,\n toolCallChunks: chunk.tool_call_chunks,\n metadata,\n });\n }\n\n if (isEmptyContent) {\n return;\n }\n\n const message_id = getMessageId(stepKey, graph) ?? '';\n if (message_id) {\n await graph.dispatchRunStep(\n stepKey,\n {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id,\n },\n },\n metadata\n );\n }\n\n const stepId = graph.getStepIdByKey(stepKey);\n const runStep = graph.getRunStep(stepId);\n if (!runStep) {\n console.warn(`\\n\n==============================================================\n\n\nRun step for ${stepId} does not exist, cannot dispatch delta event.\n\nevent: ${event}\nstepId: ${stepId}\nstepKey: ${stepKey}\nmessage_id: ${message_id}\nhasToolCalls: ${hasToolCalls}\nhasToolCallChunks: ${hasToolCallChunks}\n\n==============================================================\n\\n`);\n return;\n }\n\n /* Note: tool call chunks may have non-empty content that matches the current tool chunk generation */\n if (typeof content === 'string' && runStep.type === StepTypes.TOOL_CALLS) {\n return;\n } else if (\n hasToolCallChunks &&\n (chunk.tool_call_chunks?.some((tc) => tc.args === content) ?? false)\n ) {\n return;\n } else if (typeof content === 'string') {\n if (agentContext.currentTokenType === ContentTypes.TEXT) {\n await graph.dispatchMessageDelta(stepId, {\n content: [\n {\n type: ContentTypes.TEXT,\n text: content,\n },\n ],\n });\n } else if (agentContext.currentTokenType === 'think_and_text') {\n const { text, thinking } = parseThinkingContent(content);\n if (thinking) {\n await graph.dispatchReasoningDelta(stepId, {\n content: [\n {\n type: ContentTypes.THINK,\n think: thinking,\n },\n ],\n });\n }\n if (text) {\n agentContext.currentTokenType = ContentTypes.TEXT;\n agentContext.tokenTypeSwitch = 'content';\n const newStepKey = graph.getStepKey(metadata);\n const message_id = getMessageId(newStepKey, graph) ?? '';\n await graph.dispatchRunStep(\n newStepKey,\n {\n type: StepTypes.MESSAGE_CREATION,\n message_creation: {\n message_id,\n },\n },\n metadata\n );\n\n const newStepId = graph.getStepIdByKey(newStepKey);\n await graph.dispatchMessageDelta(newStepId, {\n content: [\n {\n type: ContentTypes.TEXT,\n text: text,\n },\n ],\n });\n }\n } else {\n await graph.dispatchReasoningDelta(stepId, {\n content: [\n {\n type: ContentTypes.THINK,\n think: content,\n },\n ],\n });\n }\n } else if (\n content.every((c) => c.type?.startsWith(ContentTypes.TEXT) ?? false)\n ) {\n await graph.dispatchMessageDelta(stepId, {\n content,\n });\n } else if (\n content.every(\n (c) =>\n (c.type?.startsWith(ContentTypes.THINKING) ?? false) ||\n (c.type?.startsWith(ContentTypes.REASONING) ?? false) ||\n (c.type?.startsWith(ContentTypes.REASONING_CONTENT) ?? false) ||\n c.type === 'redacted_thinking'\n )\n ) {\n await graph.dispatchReasoningDelta(stepId, {\n content: content.map((c) => ({\n type: ContentTypes.THINK,\n think:\n (c as t.ThinkingContentText).thinking ??\n (c as Partial<t.GoogleReasoningContentText>).reasoning ??\n (c as Partial<t.BedrockReasoningContentText>).reasoningText?.text ??\n '',\n })),\n });\n }\n }\n handleReasoning(\n chunk: Partial<AIMessageChunk>,\n agentContext: AgentContext\n ): void {\n let reasoning_content = chunk.additional_kwargs?.[\n agentContext.reasoningKey\n ] as string | Partial<ChatOpenAIReasoningSummary> | undefined;\n if (\n Array.isArray(chunk.content) &&\n (chunk.content[0]?.type === ContentTypes.THINKING ||\n chunk.content[0]?.type === ContentTypes.REASONING ||\n chunk.content[0]?.type === ContentTypes.REASONING_CONTENT ||\n chunk.content[0]?.type === 'redacted_thinking')\n ) {\n reasoning_content = 'valid';\n } else if (\n (agentContext.provider === Providers.OPENAI ||\n agentContext.provider === Providers.AZURE) &&\n reasoning_content != null &&\n typeof reasoning_content !== 'string' &&\n reasoning_content.summary?.[0]?.text != null &&\n reasoning_content.summary[0].text\n ) {\n reasoning_content = 'valid';\n } else if (\n agentContext.provider === Providers.OPENROUTER &&\n // Only set reasoning as valid if content is NOT present (content signals end of reasoning)\n (chunk.content == null || chunk.content === '') &&\n // Check for reasoning_details (final chunk) OR reasoning string (intermediate chunks)\n ((chunk.additional_kwargs?.reasoning_details != null &&\n Array.isArray(chunk.additional_kwargs.reasoning_details) &&\n chunk.additional_kwargs.reasoning_details.length > 0) ||\n (typeof chunk.additional_kwargs?.reasoning === 'string' &&\n chunk.additional_kwargs.reasoning !== ''))\n ) {\n reasoning_content = 'valid';\n }\n if (\n reasoning_content != null &&\n reasoning_content !== '' &&\n (chunk.content == null ||\n chunk.content === '' ||\n reasoning_content === 'valid')\n ) {\n agentContext.currentTokenType = ContentTypes.THINK;\n agentContext.tokenTypeSwitch = 'reasoning';\n return;\n } else if (\n agentContext.tokenTypeSwitch === 'reasoning' &&\n agentContext.currentTokenType !== ContentTypes.TEXT &&\n ((chunk.content != null && chunk.content !== '') ||\n (chunk.tool_calls?.length ?? 0) > 0 ||\n (chunk.tool_call_chunks?.length ?? 0) > 0)\n ) {\n agentContext.currentTokenType = ContentTypes.TEXT;\n agentContext.tokenTypeSwitch = 'content';\n } else if (\n chunk.content != null &&\n typeof chunk.content === 'string' &&\n chunk.content.includes('<think>') &&\n chunk.content.includes('</think>')\n ) {\n agentContext.currentTokenType = 'think_and_text';\n agentContext.tokenTypeSwitch = 'content';\n } else if (\n chunk.content != null &&\n typeof chunk.content === 'string' &&\n chunk.content.includes('<think>')\n ) {\n agentContext.currentTokenType = ContentTypes.THINK;\n agentContext.tokenTypeSwitch = 'content';\n } else if (\n agentContext.lastToken != null &&\n agentContext.lastToken.includes('</think>')\n ) {\n agentContext.currentTokenType = ContentTypes.TEXT;\n agentContext.tokenTypeSwitch = 'content';\n }\n if (typeof chunk.content !== 'string') {\n return;\n }\n agentContext.lastToken = chunk.content;\n }\n}\n\nexport function createContentAggregator(): t.ContentAggregatorResult {\n const contentParts: Array<t.MessageContentComplex | undefined> = [];\n const stepMap = new Map<string, t.RunStep>();\n const toolCallIdMap = new Map<string, string>();\n // Track agentId and groupId for each content index (applied to content parts)\n const contentMetaMap = new Map<\n number,\n { agentId?: string; groupId?: number }\n >();\n\n const updateContent = (\n index: number,\n contentPart?: t.MessageContentComplex,\n finalUpdate = false\n ): void => {\n if (!contentPart) {\n console.warn('No content part found in \\'updateContent\\'');\n return;\n }\n const partType = contentPart.type ?? '';\n if (!partType) {\n console.warn('No content type found in content part');\n return;\n }\n\n if (!contentParts[index]) {\n contentParts[index] = { type: partType };\n }\n\n if (!partType.startsWith(contentParts[index]?.type ?? '')) {\n console.warn('Content type mismatch');\n return;\n }\n\n if (\n partType.startsWith(ContentTypes.TEXT) &&\n ContentTypes.TEXT in contentPart &&\n typeof contentPart.text === 'string'\n ) {\n // TODO: update this!!\n const currentContent = contentParts[index] as t.MessageDeltaUpdate;\n const update: t.MessageDeltaUpdate = {\n type: ContentTypes.TEXT,\n text: (currentContent.text || '') + contentPart.text,\n };\n\n if (contentPart.tool_call_ids) {\n update.tool_call_ids = contentPart.tool_call_ids;\n }\n contentParts[index] = update;\n } else if (\n partType.startsWith(ContentTypes.THINK) &&\n ContentTypes.THINK in contentPart &&\n typeof contentPart.think === 'string'\n ) {\n const currentContent = contentParts[index] as t.ReasoningDeltaUpdate;\n const update: t.ReasoningDeltaUpdate = {\n type: ContentTypes.THINK,\n think: (currentContent.think || '') + contentPart.think,\n };\n contentParts[index] = update;\n } else if (\n partType.startsWith(ContentTypes.AGENT_UPDATE) &&\n ContentTypes.AGENT_UPDATE in contentPart &&\n contentPart.agent_update != null\n ) {\n const update: t.AgentUpdate = {\n type: ContentTypes.AGENT_UPDATE,\n agent_update: contentPart.agent_update,\n };\n\n contentParts[index] = update;\n } else if (\n partType === ContentTypes.IMAGE_URL &&\n 'image_url' in contentPart\n ) {\n const currentContent = contentParts[index] as {\n type: 'image_url';\n image_url: string;\n };\n contentParts[index] = {\n ...currentContent,\n };\n } else if (\n partType === ContentTypes.TOOL_CALL &&\n 'tool_call' in contentPart\n ) {\n const incomingName = contentPart.tool_call.name;\n const incomingId = contentPart.tool_call.id;\n const toolCallArgs = (contentPart.tool_call as t.ToolCallPart).args;\n\n // When we receive a tool call with a name, it's the complete tool call\n // Consolidate with any previously accumulated args from chunks\n const hasValidName = incomingName != null && incomingName !== '';\n\n // Only process if incoming has a valid name (complete tool call)\n // or if we're doing a final update with complete data\n if (!hasValidName && !finalUpdate) {\n return;\n }\n\n const existingContent = contentParts[index] as\n | (Omit<t.ToolCallContent, 'tool_call'> & {\n tool_call?: t.ToolCallPart;\n })\n | undefined;\n\n /** When args are a valid object, they are likely already invoked */\n let args =\n finalUpdate ||\n typeof existingContent?.tool_call?.args === 'object' ||\n typeof toolCallArgs === 'object'\n ? contentPart.tool_call.args\n : (existingContent?.tool_call?.args ?? '') + (toolCallArgs ?? '');\n if (\n finalUpdate &&\n args == null &&\n existingContent?.tool_call?.args != null\n ) {\n args = existingContent.tool_call.args;\n }\n\n const id =\n getNonEmptyValue([incomingId, existingContent?.tool_call?.id]) ?? '';\n const name =\n getNonEmptyValue([incomingName, existingContent?.tool_call?.name]) ??\n '';\n\n const newToolCall: ToolCall & t.PartMetadata = {\n id,\n name,\n args,\n type: ToolCallTypes.TOOL_CALL,\n };\n\n if (finalUpdate) {\n newToolCall.progress = 1;\n newToolCall.output = contentPart.tool_call.output;\n }\n\n contentParts[index] = {\n type: ContentTypes.TOOL_CALL,\n tool_call: newToolCall,\n };\n }\n\n // Apply agentId (for MultiAgentGraph) and groupId (for parallel execution) to content parts\n // - agentId present → MultiAgentGraph (show agent labels)\n // - groupId present → parallel execution (render columns)\n const meta = contentMetaMap.get(index);\n if (meta?.agentId != null) {\n (contentParts[index] as t.MessageContentComplex).agentId = meta.agentId;\n }\n if (meta?.groupId != null) {\n (contentParts[index] as t.MessageContentComplex).groupId = meta.groupId;\n }\n };\n\n const aggregateContent = ({\n event,\n data,\n }: {\n event: GraphEvents;\n data:\n | t.RunStep\n | t.AgentUpdate\n | t.MessageDeltaEvent\n | t.RunStepDeltaEvent\n | { result: t.ToolEndEvent };\n }): void => {\n if (event === GraphEvents.ON_RUN_STEP) {\n const runStep = data as t.RunStep;\n stepMap.set(runStep.id, runStep);\n\n // Track agentId (MultiAgentGraph) and groupId (parallel execution) separately\n // - agentId: present for all MultiAgentGraph runs (enables agent labels in UI)\n // - groupId: present only for parallel execution (enables column rendering)\n const hasAgentId = runStep.agentId != null && runStep.agentId !== '';\n const hasGroupId = runStep.groupId != null;\n if (hasAgentId || hasGroupId) {\n const existingMeta = contentMetaMap.get(runStep.index) ?? {};\n if (hasAgentId) {\n existingMeta.agentId = runStep.agentId;\n }\n if (hasGroupId) {\n existingMeta.groupId = runStep.groupId;\n }\n contentMetaMap.set(runStep.index, existingMeta);\n }\n\n // Store tool call IDs if present\n if (\n runStep.stepDetails.type === StepTypes.TOOL_CALLS &&\n runStep.stepDetails.tool_calls\n ) {\n (runStep.stepDetails.tool_calls as ToolCall[]).forEach((toolCall) => {\n const toolCallId = toolCall.id ?? '';\n if ('id' in toolCall && toolCallId) {\n toolCallIdMap.set(runStep.id, toolCallId);\n }\n const contentPart: t.MessageContentComplex = {\n type: ContentTypes.TOOL_CALL,\n tool_call: {\n args: toolCall.args,\n name: toolCall.name,\n id: toolCallId,\n },\n };\n\n updateContent(runStep.index, contentPart);\n });\n }\n } else if (event === GraphEvents.ON_MESSAGE_DELTA) {\n const messageDelta = data as t.MessageDeltaEvent;\n const runStep = stepMap.get(messageDelta.id);\n if (!runStep) {\n console.warn('No run step or runId found for message delta event');\n return;\n }\n\n if (messageDelta.delta.content) {\n const contentPart = Array.isArray(messageDelta.delta.content)\n ? messageDelta.delta.content[0]\n : messageDelta.delta.content;\n\n updateContent(runStep.index, contentPart);\n }\n } else if (\n event === GraphEvents.ON_AGENT_UPDATE &&\n (data as t.AgentUpdate | undefined)?.agent_update\n ) {\n const contentPart = data as t.AgentUpdate | undefined;\n if (!contentPart) {\n return;\n }\n updateContent(contentPart.agent_update.index, contentPart);\n } else if (event === GraphEvents.ON_REASONING_DELTA) {\n const reasoningDelta = data as t.ReasoningDeltaEvent;\n const runStep = stepMap.get(reasoningDelta.id);\n if (!runStep) {\n console.warn('No run step or runId found for reasoning delta event');\n return;\n }\n\n if (reasoningDelta.delta.content) {\n const contentPart = Array.isArray(reasoningDelta.delta.content)\n ? reasoningDelta.delta.content[0]\n : reasoningDelta.delta.content;\n\n updateContent(runStep.index, contentPart);\n }\n } else if (event === GraphEvents.ON_RUN_STEP_DELTA) {\n const runStepDelta = data as t.RunStepDeltaEvent;\n const runStep = stepMap.get(runStepDelta.id);\n if (!runStep) {\n console.warn('No run step or runId found for run step delta event');\n return;\n }\n\n if (\n runStepDelta.delta.type === StepTypes.TOOL_CALLS &&\n runStepDelta.delta.tool_calls\n ) {\n runStepDelta.delta.tool_calls.forEach((toolCallDelta) => {\n const toolCallId = toolCallIdMap.get(runStepDelta.id);\n\n const contentPart: t.MessageContentComplex = {\n type: ContentTypes.TOOL_CALL,\n tool_call: {\n args: toolCallDelta.args ?? '',\n name: toolCallDelta.name,\n id: toolCallId,\n },\n };\n\n updateContent(runStep.index, contentPart);\n });\n }\n } else if (event === GraphEvents.ON_RUN_STEP_COMPLETED) {\n const { result } = data as unknown as { result: t.ToolEndEvent };\n\n const { id: stepId } = result;\n\n const runStep = stepMap.get(stepId);\n if (!runStep) {\n console.warn(\n 'No run step or runId found for completed tool call event'\n );\n return;\n }\n\n const contentPart: t.MessageContentComplex = {\n type: ContentTypes.TOOL_CALL,\n tool_call: result.tool_call,\n };\n\n updateContent(runStep.index, contentPart, true);\n }\n };\n\n return { contentParts, aggregateContent, stepMap };\n}\n"],"names":[],"mappings":"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"}
@@ -16,6 +16,8 @@ const EBrowserTools = {
16
16
  BACK: 'browser_back',
17
17
  SCREENSHOT: 'browser_screenshot',
18
18
  GET_PAGE_STATE: 'browser_get_page_state',
19
+ KEYPRESS: 'browser_keypress',
20
+ SWITCH_TAB: 'browser_switch_tab',
19
21
  };
20
22
  /**
21
23
  * Check if browser capability is available based on request headers or context
@@ -35,17 +37,17 @@ function hasBrowserCapability(req) {
35
37
  const BrowserClickSchema = z.object({
36
38
  index: z
37
39
  .number()
38
- .describe('The [index] of the element to click. CRITICAL: Use fieldLabel to identify the correct element. For form fields, always target the actual <input> or <textarea> element (with type=text or role=combobox), NOT the parent <div> container.'),
40
+ .describe('The [index] of the element to click. Use fieldLabel to identify the correct element. For form fields, target <input> or <textarea> elements, NOT parent <div> containers.'),
39
41
  });
40
42
  const BrowserTypeSchema = z.object({
41
43
  index: z
42
44
  .number()
43
- .describe('The [index] of the INPUT element to type into. CRITICAL: Always target <input> or <textarea> elements (look for type=text or role=combobox). Check fieldLabel to identify the correct field (e.g., fieldLabel="To recipients" vs fieldLabel="CC recipients"). Do NOT type into parent container <div> elements.'),
45
+ .describe('The [index] of the INPUT element to type into. Target <input> or <textarea> elements. Check fieldLabel to identify the correct field.'),
44
46
  text: z.string().describe('The text to type into the element'),
45
47
  pressEnter: z
46
48
  .boolean()
47
49
  .optional()
48
- .describe('Whether to press Enter after typing (useful for search forms)'),
50
+ .describe('Whether to press Enter after typing (useful for search forms and submitting)'),
49
51
  });
50
52
  const BrowserNavigateSchema = z.object({
51
53
  url: z
@@ -79,6 +81,16 @@ const BrowserWaitSchema = z.object({
79
81
  const BrowserBackSchema = z.object({});
80
82
  const BrowserScreenshotSchema = z.object({});
81
83
  const BrowserGetPageStateSchema = z.object({});
84
+ const BrowserKeypressSchema = z.object({
85
+ keys: z
86
+ .string()
87
+ .describe('Keyboard keys to press. Use "+" to combine modifiers (e.g., "Control+Enter", "Control+a", "Escape", "Tab", "Enter"). Common shortcuts: Control+Enter (submit forms/send), Escape (close dialogs), Tab (next field).'),
88
+ });
89
+ const BrowserSwitchTabSchema = z.object({
90
+ tabId: z
91
+ .number()
92
+ .describe('The tab ID to switch to. Use the tab IDs shown in the tabs list from page state.'),
93
+ });
82
94
  /**
83
95
  * Format browser action result for LLM consumption
84
96
  */
@@ -213,6 +225,18 @@ function createBrowserTools(options) {
213
225
  description: 'Get page URL, title, and interactive elements with [index] for actions. Start here.',
214
226
  schema: BrowserGetPageStateSchema,
215
227
  }));
228
+ // browser_keypress - for keyboard shortcuts
229
+ tools.push(tool(createToolFunction('keypress'), {
230
+ name: EBrowserTools.KEYPRESS,
231
+ description: 'Send keyboard shortcut or key press. Use for: Control+Enter (send email/submit), Escape (close dialog/cancel), Tab (next field), Enter (confirm). The keys are sent to the currently focused element.',
232
+ schema: BrowserKeypressSchema,
233
+ }));
234
+ // browser_switch_tab - for switching between tabs
235
+ tools.push(tool(createToolFunction('switch_tab'), {
236
+ name: EBrowserTools.SWITCH_TAB,
237
+ description: 'Switch to a different browser tab by its ID. Tab IDs are shown in the page state. Use this to work with existing open tabs (e.g., use existing Gmail tab instead of opening a new one).',
238
+ schema: BrowserSwitchTabSchema,
239
+ }));
216
240
  return tools;
217
241
  }
218
242
 
@@ -1 +1 @@
1
- {"version":3,"file":"BrowserTools.mjs","sources":["../../../src/tools/BrowserTools.ts"],"sourcesContent":["import { z } from 'zod';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport type * as _t from '@/types';\n\n/**\n * Browser tool names - keep in sync with ranger-browser extension\n * These tools execute locally in the browser extension, NOT on the server\n */\nexport const EBrowserTools = {\n CLICK: 'browser_click',\n TYPE: 'browser_type',\n NAVIGATE: 'browser_navigate',\n SCROLL: 'browser_scroll',\n EXTRACT: 'browser_extract',\n HOVER: 'browser_hover',\n WAIT: 'browser_wait',\n BACK: 'browser_back',\n SCREENSHOT: 'browser_screenshot',\n GET_PAGE_STATE: 'browser_get_page_state',\n} as const;\n\nexport type BrowserToolName =\n (typeof EBrowserTools)[keyof typeof EBrowserTools];\n\n/**\n * Callback function type for waiting on browser action results\n * This allows the server (Ranger) to provide a callback that waits for the extension\n * to POST results back to the server before returning to the LLM.\n *\n * @param action - The browser action (click, type, navigate, etc.)\n * @param args - Arguments for the action\n * @param toolCallId - Unique ID for this tool call (from config.toolCall.id)\n * @returns Promise that resolves with the actual browser result (page state, etc.)\n */\nexport type BrowserToolCallback = (\n action: string,\n args: Record<string, unknown>,\n toolCallId: string\n) => Promise<BrowserActionResult>;\n\n/**\n * Result returned from browser action execution\n */\nexport interface BrowserActionResult {\n success: boolean;\n url?: string;\n title?: string;\n elementList?: string; // Text-based element list\n error?: string;\n screenshot?: string; // Base64 screenshot (if requested)\n}\n\n/**\n * Check if browser capability is available based on request headers or context\n * The browser extension sets these headers when connected:\n * - X-Ranger-Browser-Extension: true\n * - X-Ranger-Browser-Capable: true\n */\nexport function hasBrowserCapability(req?: {\n headers?: Record<string, string | string[] | undefined>;\n}): boolean {\n if (!req?.headers) {\n return false;\n }\n\n const browserExtension = req.headers['x-ranger-browser-extension'];\n const browserCapable = req.headers['x-ranger-browser-capable'];\n\n return browserExtension === 'true' || browserCapable === 'true';\n}\n\n// Tool schemas\nconst BrowserClickSchema = z.object({\n index: z\n .number()\n .describe(\n 'The [index] of the element to click. CRITICAL: Use fieldLabel to identify the correct element. For form fields, always target the actual <input> or <textarea> element (with type=text or role=combobox), NOT the parent <div> container.'\n ),\n});\n\nconst BrowserTypeSchema = z.object({\n index: z\n .number()\n .describe('The [index] of the INPUT element to type into. CRITICAL: Always target <input> or <textarea> elements (look for type=text or role=combobox). Check fieldLabel to identify the correct field (e.g., fieldLabel=\"To recipients\" vs fieldLabel=\"CC recipients\"). Do NOT type into parent container <div> elements.'),\n text: z.string().describe('The text to type into the element'),\n pressEnter: z\n .boolean()\n .optional()\n .describe('Whether to press Enter after typing (useful for search forms)'),\n});\n\nconst BrowserNavigateSchema = z.object({\n url: z\n .string()\n .describe('The full URL to navigate to (must include https://)'),\n});\n\nconst BrowserScrollSchema = z.object({\n direction: z\n .enum(['up', 'down', 'left', 'right'])\n .describe('Direction to scroll'),\n amount: z\n .number()\n .optional()\n .describe('Pixels to scroll (default: one viewport height)'),\n});\n\nconst BrowserExtractSchema = z.object({\n query: z\n .string()\n .optional()\n .describe('Optional: specific content to extract from the page'),\n});\n\nconst BrowserHoverSchema = z.object({\n index: z.number().describe('The index number of the element to hover over'),\n});\n\nconst BrowserWaitSchema = z.object({\n duration: z\n .number()\n .optional()\n .describe('Milliseconds to wait (default: 1000)'),\n});\n\nconst BrowserBackSchema = z.object({});\n\nconst BrowserScreenshotSchema = z.object({});\n\nconst BrowserGetPageStateSchema = z.object({});\n\n/**\n * Browser tool response interface\n * This is what the extension returns after executing the action\n */\nexport interface BrowserToolResponse {\n requiresBrowserExecution: true;\n action: string;\n args: Record<string, unknown>;\n toolCallId?: string; // Added to help extension correlate with callback\n}\n\n/**\n * Options for creating browser tools\n */\nexport interface CreateBrowserToolsOptions {\n /**\n * Optional callback that waits for browser action results.\n * When provided, tools will await this callback to get actual results from the extension.\n * When not provided, tools return markers immediately (for non-server contexts).\n */\n waitForResult?: BrowserToolCallback;\n}\n\n/**\n * Format browser action result for LLM consumption\n */\nfunction formatResultForLLM(\n result: BrowserActionResult,\n action: string\n): string {\n if (!result.success && result.error) {\n return `Browser action \"${action}\" failed: ${result.error}`;\n }\n\n const parts: string[] = [];\n\n if (result.url != null && result.url !== '') {\n parts.push(`**Current URL:** ${result.url}`);\n }\n if (result.title != null && result.title !== '') {\n parts.push(`**Page Title:** ${result.title}`);\n }\n if (result.elementList != null && result.elementList !== '') {\n // Add hint about fieldLabel and targeting inputs for form interactions\n parts.push(`\\n**Interactive Elements** (for typing: target <input> elements with fieldLabel, NOT parent <div> containers):\\n${result.elementList}`);\n }\n if (result.screenshot != null && result.screenshot !== '') {\n parts.push('\\n[Screenshot captured and displayed to user]');\n }\n\n if (parts.length === 0) {\n return `Browser action \"${action}\" completed successfully.`;\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Create browser tools with optional callback for waiting on results\n *\n * When waitForResult callback is provided:\n * 1. Tool returns marker that triggers extension\n * 2. Tool then awaits callback to get actual results\n * 3. Returns real page state to LLM\n *\n * When no callback:\n * 1. Tool returns marker only (for non-server contexts)\n *\n * NOTE: These tools use TEXT-BASED element lists, NOT screenshots\n * Screenshots would be 100K+ tokens each - element lists are ~100 tokens\n */\nexport function createBrowserTools(\n options?: CreateBrowserToolsOptions\n): DynamicStructuredTool[] {\n const { waitForResult } = options || {};\n const tools: DynamicStructuredTool[] = [];\n\n /**\n * Helper to create tool function that optionally waits for results\n * The toolCallId is extracted from the RunnableConfig passed by LangChain\n */\n const createToolFunction = (action: string) => {\n return async (\n args: Record<string, unknown>,\n config?: { toolCall?: { id?: string } }\n ): Promise<string> => {\n const toolCallId =\n config?.toolCall?.id ??\n `tool_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n\n // Create marker for extension\n const marker: BrowserToolResponse = {\n requiresBrowserExecution: true,\n action,\n args,\n toolCallId,\n };\n\n // If no callback, return marker immediately (extension handles via SSE interception)\n if (!waitForResult) {\n return JSON.stringify(marker);\n }\n\n // With callback: wait for actual results from extension\n // The marker is still returned initially via SSE, but we wait for the callback\n try {\n const result = await waitForResult(action, args, toolCallId);\n return formatResultForLLM(result, action);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return `Browser action \"${action}\" failed: ${errorMessage}`;\n }\n };\n };\n\n // browser_click\n tools.push(\n tool(createToolFunction('click'), {\n name: EBrowserTools.CLICK,\n description: 'Click element by [index]. Use fieldLabel attribute to identify correct element. For form fields, target <input> elements NOT parent <div> containers.',\n schema: BrowserClickSchema,\n })\n );\n\n // browser_type\n tools.push(\n tool(createToolFunction('type'), {\n name: EBrowserTools.TYPE,\n description: 'Type text into <input> element by [index]. CRITICAL: Always target <input> or <textarea> tags (NOT parent <div> containers). Use fieldLabel to identify correct field (e.g., fieldLabel=\"To recipients\" for To field).',\n schema: BrowserTypeSchema,\n })\n );\n\n // browser_navigate\n tools.push(\n tool(createToolFunction('navigate'), {\n name: EBrowserTools.NAVIGATE,\n description: 'Navigate to URL (include https://). Returns new page element list.',\n schema: BrowserNavigateSchema,\n })\n );\n\n // browser_scroll\n tools.push(\n tool(createToolFunction('scroll'), {\n name: EBrowserTools.SCROLL,\n description: 'Scroll page (up/down/left/right). Returns updated element list.',\n schema: BrowserScrollSchema,\n })\n );\n\n // browser_extract\n tools.push(\n tool(createToolFunction('extract'), {\n name: EBrowserTools.EXTRACT,\n description: 'Extract page content. Returns URL, title, and element list.',\n schema: BrowserExtractSchema,\n })\n );\n\n // browser_hover\n tools.push(\n tool(createToolFunction('hover'), {\n name: EBrowserTools.HOVER,\n description: 'Hover element by [index] to reveal menus/tooltips. Returns updated element list.',\n schema: BrowserHoverSchema,\n })\n );\n\n // browser_wait\n tools.push(\n tool(createToolFunction('wait'), {\n name: EBrowserTools.WAIT,\n description: 'Wait for async content to load. Returns updated element list.',\n schema: BrowserWaitSchema,\n })\n );\n\n // browser_back\n tools.push(\n tool(createToolFunction('back'), {\n name: EBrowserTools.BACK,\n description: 'Go back in browser history. Returns previous page element list.',\n schema: BrowserBackSchema,\n })\n );\n\n // browser_screenshot\n tools.push(\n tool(createToolFunction('screenshot'), {\n name: EBrowserTools.SCREENSHOT,\n description: 'Capture screenshot. Displayed to user. Use get_page_state for automation.',\n schema: BrowserScreenshotSchema,\n })\n );\n\n // browser_get_page_state\n tools.push(\n tool(createToolFunction('get_page_state'), {\n name: EBrowserTools.GET_PAGE_STATE,\n description: 'Get page URL, title, and interactive elements with [index] for actions. Start here.',\n schema: BrowserGetPageStateSchema,\n })\n );\n\n return tools;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BrowserTools.mjs","sources":["../../../src/tools/BrowserTools.ts"],"sourcesContent":["import { z } from 'zod';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport type * as _t from '@/types';\n\n/**\n * Browser tool names - keep in sync with ranger-browser extension\n * These tools execute locally in the browser extension, NOT on the server\n */\nexport const EBrowserTools = {\n CLICK: 'browser_click',\n TYPE: 'browser_type',\n NAVIGATE: 'browser_navigate',\n SCROLL: 'browser_scroll',\n EXTRACT: 'browser_extract',\n HOVER: 'browser_hover',\n WAIT: 'browser_wait',\n BACK: 'browser_back',\n SCREENSHOT: 'browser_screenshot',\n GET_PAGE_STATE: 'browser_get_page_state',\n KEYPRESS: 'browser_keypress',\n SWITCH_TAB: 'browser_switch_tab',\n} as const;\n\nexport type BrowserToolName =\n (typeof EBrowserTools)[keyof typeof EBrowserTools];\n\n/**\n * Callback function type for waiting on browser action results\n * This allows the server (Ranger) to provide a callback that waits for the extension\n * to POST results back to the server before returning to the LLM.\n *\n * @param action - The browser action (click, type, navigate, etc.)\n * @param args - Arguments for the action\n * @param toolCallId - Unique ID for this tool call (from config.toolCall.id)\n * @returns Promise that resolves with the actual browser result (page state, etc.)\n */\nexport type BrowserToolCallback = (\n action: string,\n args: Record<string, unknown>,\n toolCallId: string\n) => Promise<BrowserActionResult>;\n\n/**\n * Result returned from browser action execution\n */\nexport interface BrowserActionResult {\n success: boolean;\n url?: string;\n title?: string;\n elementList?: string; // Text-based element list\n error?: string;\n screenshot?: string; // Base64 screenshot (if requested)\n}\n\n/**\n * Check if browser capability is available based on request headers or context\n * The browser extension sets these headers when connected:\n * - X-Ranger-Browser-Extension: true\n * - X-Ranger-Browser-Capable: true\n */\nexport function hasBrowserCapability(req?: {\n headers?: Record<string, string | string[] | undefined>;\n}): boolean {\n if (!req?.headers) {\n return false;\n }\n\n const browserExtension = req.headers['x-ranger-browser-extension'];\n const browserCapable = req.headers['x-ranger-browser-capable'];\n\n return browserExtension === 'true' || browserCapable === 'true';\n}\n\n// Tool schemas\nconst BrowserClickSchema = z.object({\n index: z\n .number()\n .describe(\n 'The [index] of the element to click. Use fieldLabel to identify the correct element. For form fields, target <input> or <textarea> elements, NOT parent <div> containers.'\n ),\n});\n\nconst BrowserTypeSchema = z.object({\n index: z\n .number()\n .describe(\n 'The [index] of the INPUT element to type into. Target <input> or <textarea> elements. Check fieldLabel to identify the correct field.'\n ),\n text: z.string().describe('The text to type into the element'),\n pressEnter: z\n .boolean()\n .optional()\n .describe(\n 'Whether to press Enter after typing (useful for search forms and submitting)'\n ),\n});\n\nconst BrowserNavigateSchema = z.object({\n url: z\n .string()\n .describe('The full URL to navigate to (must include https://)'),\n});\n\nconst BrowserScrollSchema = z.object({\n direction: z\n .enum(['up', 'down', 'left', 'right'])\n .describe('Direction to scroll'),\n amount: z\n .number()\n .optional()\n .describe('Pixels to scroll (default: one viewport height)'),\n});\n\nconst BrowserExtractSchema = z.object({\n query: z\n .string()\n .optional()\n .describe('Optional: specific content to extract from the page'),\n});\n\nconst BrowserHoverSchema = z.object({\n index: z.number().describe('The index number of the element to hover over'),\n});\n\nconst BrowserWaitSchema = z.object({\n duration: z\n .number()\n .optional()\n .describe('Milliseconds to wait (default: 1000)'),\n});\n\nconst BrowserBackSchema = z.object({});\n\nconst BrowserScreenshotSchema = z.object({});\n\nconst BrowserGetPageStateSchema = z.object({});\n\nconst BrowserKeypressSchema = z.object({\n keys: z\n .string()\n .describe(\n 'Keyboard keys to press. Use \"+\" to combine modifiers (e.g., \"Control+Enter\", \"Control+a\", \"Escape\", \"Tab\", \"Enter\"). Common shortcuts: Control+Enter (submit forms/send), Escape (close dialogs), Tab (next field).'\n ),\n});\n\nconst BrowserSwitchTabSchema = z.object({\n tabId: z\n .number()\n .describe(\n 'The tab ID to switch to. Use the tab IDs shown in the tabs list from page state.'\n ),\n});\n\n/**\n * Browser tool response interface\n * This is what the extension returns after executing the action\n */\nexport interface BrowserToolResponse {\n requiresBrowserExecution: true;\n action: string;\n args: Record<string, unknown>;\n toolCallId?: string; // Added to help extension correlate with callback\n}\n\n/**\n * Options for creating browser tools\n */\nexport interface CreateBrowserToolsOptions {\n /**\n * Optional callback that waits for browser action results.\n * When provided, tools will await this callback to get actual results from the extension.\n * When not provided, tools return markers immediately (for non-server contexts).\n */\n waitForResult?: BrowserToolCallback;\n}\n\n/**\n * Format browser action result for LLM consumption\n */\nfunction formatResultForLLM(\n result: BrowserActionResult,\n action: string\n): string {\n if (!result.success && result.error) {\n return `Browser action \"${action}\" failed: ${result.error}`;\n }\n\n const parts: string[] = [];\n\n if (result.url != null && result.url !== '') {\n parts.push(`**Current URL:** ${result.url}`);\n }\n if (result.title != null && result.title !== '') {\n parts.push(`**Page Title:** ${result.title}`);\n }\n if (result.elementList != null && result.elementList !== '') {\n // Add hint about fieldLabel and targeting inputs for form interactions\n parts.push(\n `\\n**Interactive Elements** (for typing: target <input> elements with fieldLabel, NOT parent <div> containers):\\n${result.elementList}`\n );\n }\n if (result.screenshot != null && result.screenshot !== '') {\n parts.push('\\n[Screenshot captured and displayed to user]');\n }\n\n if (parts.length === 0) {\n return `Browser action \"${action}\" completed successfully.`;\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Create browser tools with optional callback for waiting on results\n *\n * When waitForResult callback is provided:\n * 1. Tool returns marker that triggers extension\n * 2. Tool then awaits callback to get actual results\n * 3. Returns real page state to LLM\n *\n * When no callback:\n * 1. Tool returns marker only (for non-server contexts)\n *\n * NOTE: These tools use TEXT-BASED element lists, NOT screenshots\n * Screenshots would be 100K+ tokens each - element lists are ~100 tokens\n */\nexport function createBrowserTools(\n options?: CreateBrowserToolsOptions\n): DynamicStructuredTool[] {\n const { waitForResult } = options || {};\n const tools: DynamicStructuredTool[] = [];\n\n /**\n * Helper to create tool function that optionally waits for results\n * The toolCallId is extracted from the RunnableConfig passed by LangChain\n */\n const createToolFunction = (action: string) => {\n return async (\n args: Record<string, unknown>,\n config?: { toolCall?: { id?: string } }\n ): Promise<string> => {\n const toolCallId =\n config?.toolCall?.id ??\n `tool_${Date.now()}_${Math.random().toString(36).slice(2)}`;\n\n // Create marker for extension\n const marker: BrowserToolResponse = {\n requiresBrowserExecution: true,\n action,\n args,\n toolCallId,\n };\n\n // If no callback, return marker immediately (extension handles via SSE interception)\n if (!waitForResult) {\n return JSON.stringify(marker);\n }\n\n // With callback: wait for actual results from extension\n // The marker is still returned initially via SSE, but we wait for the callback\n try {\n const result = await waitForResult(action, args, toolCallId);\n return formatResultForLLM(result, action);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return `Browser action \"${action}\" failed: ${errorMessage}`;\n }\n };\n };\n\n // browser_click\n tools.push(\n tool(createToolFunction('click'), {\n name: EBrowserTools.CLICK,\n description:\n 'Click element by [index]. Use fieldLabel attribute to identify correct element. For form fields, target <input> elements NOT parent <div> containers.',\n schema: BrowserClickSchema,\n })\n );\n\n // browser_type\n tools.push(\n tool(createToolFunction('type'), {\n name: EBrowserTools.TYPE,\n description:\n 'Type text into <input> element by [index]. CRITICAL: Always target <input> or <textarea> tags (NOT parent <div> containers). Use fieldLabel to identify correct field (e.g., fieldLabel=\"To recipients\" for To field).',\n schema: BrowserTypeSchema,\n })\n );\n\n // browser_navigate\n tools.push(\n tool(createToolFunction('navigate'), {\n name: EBrowserTools.NAVIGATE,\n description:\n 'Navigate to URL (include https://). Returns new page element list.',\n schema: BrowserNavigateSchema,\n })\n );\n\n // browser_scroll\n tools.push(\n tool(createToolFunction('scroll'), {\n name: EBrowserTools.SCROLL,\n description:\n 'Scroll page (up/down/left/right). Returns updated element list.',\n schema: BrowserScrollSchema,\n })\n );\n\n // browser_extract\n tools.push(\n tool(createToolFunction('extract'), {\n name: EBrowserTools.EXTRACT,\n description:\n 'Extract page content. Returns URL, title, and element list.',\n schema: BrowserExtractSchema,\n })\n );\n\n // browser_hover\n tools.push(\n tool(createToolFunction('hover'), {\n name: EBrowserTools.HOVER,\n description:\n 'Hover element by [index] to reveal menus/tooltips. Returns updated element list.',\n schema: BrowserHoverSchema,\n })\n );\n\n // browser_wait\n tools.push(\n tool(createToolFunction('wait'), {\n name: EBrowserTools.WAIT,\n description:\n 'Wait for async content to load. Returns updated element list.',\n schema: BrowserWaitSchema,\n })\n );\n\n // browser_back\n tools.push(\n tool(createToolFunction('back'), {\n name: EBrowserTools.BACK,\n description:\n 'Go back in browser history. Returns previous page element list.',\n schema: BrowserBackSchema,\n })\n );\n\n // browser_screenshot\n tools.push(\n tool(createToolFunction('screenshot'), {\n name: EBrowserTools.SCREENSHOT,\n description:\n 'Capture screenshot. Displayed to user. Use get_page_state for automation.',\n schema: BrowserScreenshotSchema,\n })\n );\n\n // browser_get_page_state\n tools.push(\n tool(createToolFunction('get_page_state'), {\n name: EBrowserTools.GET_PAGE_STATE,\n description:\n 'Get page URL, title, and interactive elements with [index] for actions. Start here.',\n schema: BrowserGetPageStateSchema,\n })\n );\n\n // browser_keypress - for keyboard shortcuts\n tools.push(\n tool(createToolFunction('keypress'), {\n name: EBrowserTools.KEYPRESS,\n description:\n 'Send keyboard shortcut or key press. Use for: Control+Enter (send email/submit), Escape (close dialog/cancel), Tab (next field), Enter (confirm). The keys are sent to the currently focused element.',\n schema: BrowserKeypressSchema,\n })\n );\n\n // browser_switch_tab - for switching between tabs\n tools.push(\n tool(createToolFunction('switch_tab'), {\n name: EBrowserTools.SWITCH_TAB,\n description:\n 'Switch to a different browser tab by its ID. Tab IDs are shown in the page state. Use this to work with existing open tabs (e.g., use existing Gmail tab instead of opening a new one).',\n schema: BrowserSwitchTabSchema,\n })\n );\n\n return tools;\n}\n"],"names":[],"mappings":"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"}
@@ -12,7 +12,7 @@ const getCodeBaseURL = () => getEnvironmentVariable(EnvVar.CODE_BASEURL) ??
12
12
  Constants.OFFICIAL_CODE_BASEURL;
13
13
  const imageMessage = 'Image is already displayed to the user';
14
14
  const otherMessage = 'File is already downloaded by the user';
15
- const accessMessage = 'Note: Files are READ-ONLY. Save changes to NEW filenames. To access these files in future executions, provide the `session_id` as a parameter (not in your code).';
15
+ const accessMessage = 'Note: Files from previous executions are automatically available and can be modified.';
16
16
  const emptyOutputMessage = 'stdout: Empty. Ensure you\'re writing output explicitly.\n';
17
17
  const CodeExecutionToolSchema = z.object({
18
18
  lang: z
@@ -34,7 +34,8 @@ const CodeExecutionToolSchema = z.object({
34
34
  code: z.string()
35
35
  .describe(`The complete, self-contained code to execute, without any truncation or minimization.
36
36
  - The environment is stateless; variables and imports don't persist between executions.
37
- - When using \`session_id\`: Don't hardcode it in \`code\`, and write file modifications to NEW filenames (files are READ-ONLY).
37
+ - Generated files from previous executions are automatically available in "/mnt/data/".
38
+ - Files from previous executions are automatically available and can be modified in place.
38
39
  - Input code **IS ALREADY** displayed to the user, so **DO NOT** repeat it in your response unless asked.
39
40
  - Output code **IS NOT** displayed to the user, so **DO** write all desired output explicitly.
40
41
  - IMPORTANT: You MUST explicitly print/output ALL results you want the user to see.
@@ -43,15 +44,6 @@ const CodeExecutionToolSchema = z.object({
43
44
  - js: use the \`console\` or \`process\` methods for all outputs.
44
45
  - r: IMPORTANT: No X11 display available. ALL graphics MUST use Cairo library (library(Cairo)).
45
46
  - Other languages: use appropriate output functions.`),
46
- session_id: z
47
- .string()
48
- .optional()
49
- .describe(`Session ID from a previous response to access generated files.
50
- - Files load into the current working directory ("/mnt/data/")
51
- - Use relative paths ONLY
52
- - Files are READ-ONLY and cannot be modified in-place
53
- - To modify: read original file, write to NEW filename
54
- `.trim()),
55
47
  args: z
56
48
  .array(z.string())
57
49
  .optional()
@@ -88,14 +80,29 @@ Rules:
88
80
  - No network access available
89
81
  - Generated files auto-delivered (no download links needed)
90
82
  `.trim();
91
- return tool(async ({ lang, code, session_id, ...rest }) => {
83
+ return tool(async ({ lang, code, ...rest }, config) => {
84
+ /**
85
+ * Extract session context from config.toolCall (injected by ToolNode).
86
+ * - session_id: For API to associate with previous session
87
+ * - _injected_files: File refs to pass directly (avoids /files endpoint race condition)
88
+ */
89
+ const { session_id, _injected_files } = (config.toolCall ?? {});
92
90
  const postData = {
93
91
  lang,
94
92
  code,
95
93
  ...rest,
96
94
  ...params,
97
95
  };
98
- if (session_id != null && session_id.length > 0) {
96
+ /**
97
+ * File injection priority:
98
+ * 1. Use _injected_files from ToolNode (avoids /files endpoint race condition)
99
+ * 2. Fall back to fetching from /files endpoint if session_id provided but no injected files
100
+ */
101
+ if (_injected_files && _injected_files.length > 0) {
102
+ postData.files = _injected_files;
103
+ }
104
+ else if (session_id != null && session_id.length > 0) {
105
+ /** Fallback: fetch from /files endpoint (may have race condition issues) */
99
106
  try {
100
107
  const filesEndpoint = `${baseEndpoint}/files/${session_id}?detail=full`;
101
108
  const fetchOptions = {
@@ -115,7 +122,6 @@ Rules:
115
122
  const files = await response.json();
116
123
  if (Array.isArray(files) && files.length > 0) {
117
124
  const fileReferences = files.map((file) => {
118
- // Extract the ID from the file name (part after session ID prefix and before extension)
119
125
  const nameParts = file.name.split('/');
120
126
  const id = nameParts.length > 1 ? nameParts[1].split('.')[0] : '';
121
127
  return {
@@ -124,12 +130,7 @@ Rules:
124
130
  name: file.metadata['original-filename'],
125
131
  };
126
132
  });
127
- if (!postData.files) {
128
- postData.files = fileReferences;
129
- }
130
- else if (Array.isArray(postData.files)) {
131
- postData.files = [...postData.files, ...fileReferences];
132
- }
133
+ postData.files = fileReferences;
133
134
  }
134
135
  }
135
136
  catch {
@@ -175,7 +176,7 @@ Rules:
175
176
  formattedOutput += fileCount <= 3 ? ', ' : ',\n';
176
177
  }
177
178
  }
178
- formattedOutput += `\nsession_id: ${result.session_id}\n\n${accessMessage}`;
179
+ formattedOutput += `\n\n${accessMessage}`;
179
180
  return [
180
181
  formattedOutput.trim(),
181
182
  {
@@ -1 +1 @@
1
- {"version":3,"file":"CodeExecutor.mjs","sources":["../../../src/tools/CodeExecutor.ts"],"sourcesContent":["import { z } from 'zod';\nimport { config } from 'dotenv';\nimport fetch, { RequestInit } from 'node-fetch';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport { getEnvironmentVariable } from '@langchain/core/utils/env';\nimport type * as t from '@/types';\nimport { EnvVar, Constants } from '@/common';\n\nconfig();\n\nexport const imageExtRegex = /\\.(jpg|jpeg|png|gif|webp)$/i;\nexport const getCodeBaseURL = (): string =>\n getEnvironmentVariable(EnvVar.CODE_BASEURL) ??\n Constants.OFFICIAL_CODE_BASEURL;\n\nconst imageMessage = 'Image is already displayed to the user';\nconst otherMessage = 'File is already downloaded by the user';\nconst accessMessage =\n 'Note: Files are READ-ONLY. Save changes to NEW filenames. To access these files in future executions, provide the `session_id` as a parameter (not in your code).';\nconst emptyOutputMessage =\n 'stdout: Empty. Ensure you\\'re writing output explicitly.\\n';\n\nconst CodeExecutionToolSchema = z.object({\n lang: z\n .enum([\n 'py',\n 'js',\n 'ts',\n 'c',\n 'cpp',\n 'java',\n 'php',\n 'rs',\n 'go',\n 'd',\n 'f90',\n 'r',\n ])\n .describe('The programming language or runtime to execute the code in.'),\n code: z.string()\n .describe(`The complete, self-contained code to execute, without any truncation or minimization.\n- The environment is stateless; variables and imports don't persist between executions.\n- When using \\`session_id\\`: Don't hardcode it in \\`code\\`, and write file modifications to NEW filenames (files are READ-ONLY).\n- Input code **IS ALREADY** displayed to the user, so **DO NOT** repeat it in your response unless asked.\n- Output code **IS NOT** displayed to the user, so **DO** write all desired output explicitly.\n- IMPORTANT: You MUST explicitly print/output ALL results you want the user to see.\n- py: This is not a Jupyter notebook environment. Use \\`print()\\` for all outputs.\n- py: Matplotlib: Use \\`plt.savefig()\\` to save plots as files.\n- js: use the \\`console\\` or \\`process\\` methods for all outputs.\n- r: IMPORTANT: No X11 display available. ALL graphics MUST use Cairo library (library(Cairo)).\n- Other languages: use appropriate output functions.`),\n session_id: z\n .string()\n .optional()\n .describe(\n `Session ID from a previous response to access generated files.\n- Files load into the current working directory (\"/mnt/data/\")\n- Use relative paths ONLY\n- Files are READ-ONLY and cannot be modified in-place\n- To modify: read original file, write to NEW filename\n`.trim()\n ),\n args: z\n .array(z.string())\n .optional()\n .describe(\n 'Additional arguments to execute the code with. This should only be used if the input code requires additional arguments to run.'\n ),\n});\n\nconst baseEndpoint = getCodeBaseURL();\nconst EXEC_ENDPOINT = `${baseEndpoint}/exec`;\n\nfunction createCodeExecutionTool(\n params: t.CodeExecutionToolParams = {}\n): DynamicStructuredTool<typeof CodeExecutionToolSchema> {\n const apiKey =\n params[EnvVar.CODE_API_KEY] ??\n params.apiKey ??\n getEnvironmentVariable(EnvVar.CODE_API_KEY) ??\n '';\n if (!apiKey) {\n throw new Error('No API key provided for code execution tool.');\n }\n\n const description = `\n⛔ STOP! Before using this tool, ask: \"Does user need a DOWNLOADABLE FILE?\"\n- If NO (dashboard, chart, visualization, UI) → DO NOT USE THIS TOOL. Use :::artifact instead.\n- If YES (.pptx, .docx, .pdf, .xlsx) → Use this tool.\n\nRuns code in a stateless execution environment. Each execution is isolated.\n\n🚫 NEVER USE FOR:\n- Dashboards, charts, visualizations → Use :::artifact with React/Chart.js\n- \"Mock data\" or \"sample data\" for display → Hardcode data in artifact\n- UI components, HTML pages, React apps → Use :::artifact\n\n✅ ONLY USE FOR:\n- File generation: PowerPoint (.pptx), Word (.docx), PDF (.pdf), Excel (.xlsx)\n- Processing uploaded files (CSV, Excel analysis)\n- Heavy computation requiring Python\n\nRules:\n- No network access available\n- Generated files auto-delivered (no download links needed)\n`.trim();\n\n return tool<typeof CodeExecutionToolSchema>(\n async ({ lang, code, session_id, ...rest }) => {\n const postData = {\n lang,\n code,\n ...rest,\n ...params,\n };\n\n if (session_id != null && session_id.length > 0) {\n try {\n const filesEndpoint = `${baseEndpoint}/files/${session_id}?detail=full`;\n const fetchOptions: RequestInit = {\n method: 'GET',\n headers: {\n 'User-Agent': 'Illuma/1.0',\n 'X-API-Key': apiKey,\n },\n };\n\n if (process.env.PROXY != null && process.env.PROXY !== '') {\n fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);\n }\n\n const response = await fetch(filesEndpoint, fetchOptions);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch files for session: ${response.status}`\n );\n }\n\n const files = await response.json();\n if (Array.isArray(files) && files.length > 0) {\n const fileReferences: t.CodeEnvFile[] = files.map((file) => {\n // Extract the ID from the file name (part after session ID prefix and before extension)\n const nameParts = file.name.split('/');\n const id = nameParts.length > 1 ? nameParts[1].split('.')[0] : '';\n\n return {\n session_id,\n id,\n name: file.metadata['original-filename'],\n };\n });\n\n if (!postData.files) {\n postData.files = fileReferences;\n } else if (Array.isArray(postData.files)) {\n postData.files = [...postData.files, ...fileReferences];\n }\n }\n } catch {\n // eslint-disable-next-line no-console\n console.warn(`Failed to fetch files for session: ${session_id}`);\n }\n }\n\n try {\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': 'Illuma/1.0',\n 'X-API-Key': apiKey,\n },\n body: JSON.stringify(postData),\n };\n\n if (process.env.PROXY != null && process.env.PROXY !== '') {\n fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);\n }\n const response = await fetch(EXEC_ENDPOINT, fetchOptions);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const result: t.ExecuteResult = await response.json();\n let formattedOutput = '';\n if (result.stdout) {\n formattedOutput += `stdout:\\n${result.stdout}\\n`;\n } else {\n formattedOutput += emptyOutputMessage;\n }\n if (result.stderr) formattedOutput += `stderr:\\n${result.stderr}\\n`;\n if (result.files && result.files.length > 0) {\n formattedOutput += 'Generated files:\\n';\n\n const fileCount = result.files.length;\n for (let i = 0; i < fileCount; i++) {\n const file = result.files[i];\n const isImage = imageExtRegex.test(file.name);\n formattedOutput += `- /mnt/data/${file.name} | ${isImage ? imageMessage : otherMessage}`;\n\n if (i < fileCount - 1) {\n formattedOutput += fileCount <= 3 ? ', ' : ',\\n';\n }\n }\n\n formattedOutput += `\\nsession_id: ${result.session_id}\\n\\n${accessMessage}`;\n return [\n formattedOutput.trim(),\n {\n session_id: result.session_id,\n files: result.files,\n },\n ];\n }\n\n return [formattedOutput.trim(), { session_id: result.session_id }];\n } catch (error) {\n throw new Error(\n `Execution error:\\n\\n${(error as Error | undefined)?.message}`\n );\n }\n },\n {\n name: Constants.EXECUTE_CODE,\n description,\n schema: CodeExecutionToolSchema,\n responseFormat: Constants.CONTENT_AND_ARTIFACT,\n }\n );\n}\n\nexport { createCodeExecutionTool };\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CodeExecutor.mjs","sources":["../../../src/tools/CodeExecutor.ts"],"sourcesContent":["import { z } from 'zod';\nimport { config } from 'dotenv';\nimport fetch, { RequestInit } from 'node-fetch';\nimport { HttpsProxyAgent } from 'https-proxy-agent';\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\nimport { getEnvironmentVariable } from '@langchain/core/utils/env';\nimport type * as t from '@/types';\nimport { EnvVar, Constants } from '@/common';\n\nconfig();\n\nexport const imageExtRegex = /\\.(jpg|jpeg|png|gif|webp)$/i;\nexport const getCodeBaseURL = (): string =>\n getEnvironmentVariable(EnvVar.CODE_BASEURL) ??\n Constants.OFFICIAL_CODE_BASEURL;\n\nconst imageMessage = 'Image is already displayed to the user';\nconst otherMessage = 'File is already downloaded by the user';\nconst accessMessage =\n 'Note: Files from previous executions are automatically available and can be modified.';\nconst emptyOutputMessage =\n 'stdout: Empty. Ensure you\\'re writing output explicitly.\\n';\n\nconst CodeExecutionToolSchema = z.object({\n lang: z\n .enum([\n 'py',\n 'js',\n 'ts',\n 'c',\n 'cpp',\n 'java',\n 'php',\n 'rs',\n 'go',\n 'd',\n 'f90',\n 'r',\n ])\n .describe('The programming language or runtime to execute the code in.'),\n code: z.string()\n .describe(`The complete, self-contained code to execute, without any truncation or minimization.\n- The environment is stateless; variables and imports don't persist between executions.\n- Generated files from previous executions are automatically available in \"/mnt/data/\".\n- Files from previous executions are automatically available and can be modified in place.\n- Input code **IS ALREADY** displayed to the user, so **DO NOT** repeat it in your response unless asked.\n- Output code **IS NOT** displayed to the user, so **DO** write all desired output explicitly.\n- IMPORTANT: You MUST explicitly print/output ALL results you want the user to see.\n- py: This is not a Jupyter notebook environment. Use \\`print()\\` for all outputs.\n- py: Matplotlib: Use \\`plt.savefig()\\` to save plots as files.\n- js: use the \\`console\\` or \\`process\\` methods for all outputs.\n- r: IMPORTANT: No X11 display available. ALL graphics MUST use Cairo library (library(Cairo)).\n- Other languages: use appropriate output functions.`),\n args: z\n .array(z.string())\n .optional()\n .describe(\n 'Additional arguments to execute the code with. This should only be used if the input code requires additional arguments to run.'\n ),\n});\n\nconst baseEndpoint = getCodeBaseURL();\nconst EXEC_ENDPOINT = `${baseEndpoint}/exec`;\n\nfunction createCodeExecutionTool(\n params: t.CodeExecutionToolParams = {}\n): DynamicStructuredTool<typeof CodeExecutionToolSchema> {\n const apiKey =\n params[EnvVar.CODE_API_KEY] ??\n params.apiKey ??\n getEnvironmentVariable(EnvVar.CODE_API_KEY) ??\n '';\n if (!apiKey) {\n throw new Error('No API key provided for code execution tool.');\n }\n\n const description = `\n⛔ STOP! Before using this tool, ask: \"Does user need a DOWNLOADABLE FILE?\"\n- If NO (dashboard, chart, visualization, UI) → DO NOT USE THIS TOOL. Use :::artifact instead.\n- If YES (.pptx, .docx, .pdf, .xlsx) → Use this tool.\n\nRuns code in a stateless execution environment. Each execution is isolated.\n\n🚫 NEVER USE FOR:\n- Dashboards, charts, visualizations → Use :::artifact with React/Chart.js\n- \"Mock data\" or \"sample data\" for display → Hardcode data in artifact\n- UI components, HTML pages, React apps → Use :::artifact\n\n✅ ONLY USE FOR:\n- File generation: PowerPoint (.pptx), Word (.docx), PDF (.pdf), Excel (.xlsx)\n- Processing uploaded files (CSV, Excel analysis)\n- Heavy computation requiring Python\n\nRules:\n- No network access available\n- Generated files auto-delivered (no download links needed)\n`.trim();\n\n return tool<typeof CodeExecutionToolSchema>(\n async ({ lang, code, ...rest }, config) => {\n /**\n * Extract session context from config.toolCall (injected by ToolNode).\n * - session_id: For API to associate with previous session\n * - _injected_files: File refs to pass directly (avoids /files endpoint race condition)\n */\n const { session_id, _injected_files } = (config.toolCall ?? {}) as {\n session_id?: string;\n _injected_files?: t.CodeEnvFile[];\n };\n\n const postData: Record<string, unknown> = {\n lang,\n code,\n ...rest,\n ...params,\n };\n\n /**\n * File injection priority:\n * 1. Use _injected_files from ToolNode (avoids /files endpoint race condition)\n * 2. Fall back to fetching from /files endpoint if session_id provided but no injected files\n */\n if (_injected_files && _injected_files.length > 0) {\n postData.files = _injected_files;\n } else if (session_id != null && session_id.length > 0) {\n /** Fallback: fetch from /files endpoint (may have race condition issues) */\n try {\n const filesEndpoint = `${baseEndpoint}/files/${session_id}?detail=full`;\n const fetchOptions: RequestInit = {\n method: 'GET',\n headers: {\n 'User-Agent': 'Illuma/1.0',\n 'X-API-Key': apiKey,\n },\n };\n\n if (process.env.PROXY != null && process.env.PROXY !== '') {\n fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);\n }\n\n const response = await fetch(filesEndpoint, fetchOptions);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch files for session: ${response.status}`\n );\n }\n\n const files = await response.json();\n if (Array.isArray(files) && files.length > 0) {\n const fileReferences: t.CodeEnvFile[] = files.map((file) => {\n const nameParts = file.name.split('/');\n const id = nameParts.length > 1 ? nameParts[1].split('.')[0] : '';\n\n return {\n session_id,\n id,\n name: file.metadata['original-filename'],\n };\n });\n\n postData.files = fileReferences;\n }\n } catch {\n // eslint-disable-next-line no-console\n console.warn(`Failed to fetch files for session: ${session_id}`);\n }\n }\n\n try {\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': 'Illuma/1.0',\n 'X-API-Key': apiKey,\n },\n body: JSON.stringify(postData),\n };\n\n if (process.env.PROXY != null && process.env.PROXY !== '') {\n fetchOptions.agent = new HttpsProxyAgent(process.env.PROXY);\n }\n const response = await fetch(EXEC_ENDPOINT, fetchOptions);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n const result: t.ExecuteResult = await response.json();\n let formattedOutput = '';\n if (result.stdout) {\n formattedOutput += `stdout:\\n${result.stdout}\\n`;\n } else {\n formattedOutput += emptyOutputMessage;\n }\n if (result.stderr) formattedOutput += `stderr:\\n${result.stderr}\\n`;\n if (result.files && result.files.length > 0) {\n formattedOutput += 'Generated files:\\n';\n\n const fileCount = result.files.length;\n for (let i = 0; i < fileCount; i++) {\n const file = result.files[i];\n const isImage = imageExtRegex.test(file.name);\n formattedOutput += `- /mnt/data/${file.name} | ${isImage ? imageMessage : otherMessage}`;\n\n if (i < fileCount - 1) {\n formattedOutput += fileCount <= 3 ? ', ' : ',\\n';\n }\n }\n\n formattedOutput += `\\n\\n${accessMessage}`;\n return [\n formattedOutput.trim(),\n {\n session_id: result.session_id,\n files: result.files,\n },\n ];\n }\n\n return [formattedOutput.trim(), { session_id: result.session_id }];\n } catch (error) {\n throw new Error(\n `Execution error:\\n\\n${(error as Error | undefined)?.message}`\n );\n }\n },\n {\n name: Constants.EXECUTE_CODE,\n description,\n schema: CodeExecutionToolSchema,\n responseFormat: Constants.CONTENT_AND_ARTIFACT,\n }\n );\n}\n\nexport { createCodeExecutionTool };\n"],"names":[],"mappings":";;;;;;;;AASA,MAAM,EAAE;AAED,MAAM,aAAa,GAAG;AACtB,MAAM,cAAc,GAAG,MAC5B,sBAAsB,CAAC,MAAM,CAAC,YAAY,CAAC;IAC3C,SAAS,CAAC;AAEZ,MAAM,YAAY,GAAG,wCAAwC;AAC7D,MAAM,YAAY,GAAG,wCAAwC;AAC7D,MAAM,aAAa,GACjB,uFAAuF;AACzF,MAAM,kBAAkB,GACtB,4DAA4D;AAE9D,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;AACvC,IAAA,IAAI,EAAE;AACH,SAAA,IAAI,CAAC;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,GAAG;QACH,KAAK;QACL,MAAM;QACN,KAAK;QACL,IAAI;QACJ,IAAI;QACJ,GAAG;QACH,KAAK;QACL,GAAG;KACJ;SACA,QAAQ,CAAC,6DAA6D,CAAC;AAC1E,IAAA,IAAI,EAAE,CAAC,CAAC,MAAM;AACX,SAAA,QAAQ,CAAC,CAAA;;;;;;;;;;;qDAWuC,CAAC;AACpD,IAAA,IAAI,EAAE;AACH,SAAA,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE;AAChB,SAAA,QAAQ;SACR,QAAQ,CACP,iIAAiI,CAClI;AACJ,CAAA,CAAC;AAEF,MAAM,YAAY,GAAG,cAAc,EAAE;AACrC,MAAM,aAAa,GAAG,CAAG,EAAA,YAAY,OAAO;AAE5C,SAAS,uBAAuB,CAC9B,MAAA,GAAoC,EAAE,EAAA;AAEtC,IAAA,MAAM,MAAM,GACV,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;AAC3B,QAAA,MAAM,CAAC,MAAM;AACb,QAAA,sBAAsB,CAAC,MAAM,CAAC,YAAY,CAAC;AAC3C,QAAA,EAAE;IACJ,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC;;AAGjE,IAAA,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;CAoBrB,CAAC,IAAI,EAAE;AAEN,IAAA,OAAO,IAAI,CACT,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,MAAM,KAAI;AACxC;;;;AAIG;AACH,QAAA,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,CAG7D;AAED,QAAA,MAAM,QAAQ,GAA4B;YACxC,IAAI;YACJ,IAAI;AACJ,YAAA,GAAG,IAAI;AACP,YAAA,GAAG,MAAM;SACV;AAED;;;;AAIG;QACH,IAAI,eAAe,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE;AACjD,YAAA,QAAQ,CAAC,KAAK,GAAG,eAAe;;aAC3B,IAAI,UAAU,IAAI,IAAI,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;;AAEtD,YAAA,IAAI;AACF,gBAAA,MAAM,aAAa,GAAG,CAAA,EAAG,YAAY,CAAU,OAAA,EAAA,UAAU,cAAc;AACvE,gBAAA,MAAM,YAAY,GAAgB;AAChC,oBAAA,MAAM,EAAE,KAAK;AACb,oBAAA,OAAO,EAAE;AACP,wBAAA,YAAY,EAAE,YAAY;AAC1B,wBAAA,WAAW,EAAE,MAAM;AACpB,qBAAA;iBACF;AAED,gBAAA,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,EAAE;AACzD,oBAAA,YAAY,CAAC,KAAK,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;;gBAG7D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC;AACzD,gBAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;oBAChB,MAAM,IAAI,KAAK,CACb,CAAA,mCAAA,EAAsC,QAAQ,CAAC,MAAM,CAAE,CAAA,CACxD;;AAGH,gBAAA,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE;AACnC,gBAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;oBAC5C,MAAM,cAAc,GAAoB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;wBACzD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;wBACtC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE;wBAEjE,OAAO;4BACL,UAAU;4BACV,EAAE;AACF,4BAAA,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC;yBACzC;AACH,qBAAC,CAAC;AAEF,oBAAA,QAAQ,CAAC,KAAK,GAAG,cAAc;;;AAEjC,YAAA,MAAM;;AAEN,gBAAA,OAAO,CAAC,IAAI,CAAC,sCAAsC,UAAU,CAAA,CAAE,CAAC;;;AAIpE,QAAA,IAAI;AACF,YAAA,MAAM,YAAY,GAAgB;AAChC,gBAAA,MAAM,EAAE,MAAM;AACd,gBAAA,OAAO,EAAE;AACP,oBAAA,cAAc,EAAE,kBAAkB;AAClC,oBAAA,YAAY,EAAE,YAAY;AAC1B,oBAAA,WAAW,EAAE,MAAM;AACpB,iBAAA;AACD,gBAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;aAC/B;AAED,YAAA,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,EAAE,EAAE;AACzD,gBAAA,YAAY,CAAC,KAAK,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;;YAE7D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC;AACzD,YAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;gBAChB,MAAM,IAAI,KAAK,CAAC,CAAA,oBAAA,EAAuB,QAAQ,CAAC,MAAM,CAAE,CAAA,CAAC;;AAG3D,YAAA,MAAM,MAAM,GAAoB,MAAM,QAAQ,CAAC,IAAI,EAAE;YACrD,IAAI,eAAe,GAAG,EAAE;AACxB,YAAA,IAAI,MAAM,CAAC,MAAM,EAAE;AACjB,gBAAA,eAAe,IAAI,CAAY,SAAA,EAAA,MAAM,CAAC,MAAM,IAAI;;iBAC3C;gBACL,eAAe,IAAI,kBAAkB;;YAEvC,IAAI,MAAM,CAAC,MAAM;AAAE,gBAAA,eAAe,IAAI,CAAY,SAAA,EAAA,MAAM,CAAC,MAAM,IAAI;AACnE,YAAA,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC3C,eAAe,IAAI,oBAAoB;AAEvC,gBAAA,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;AACrC,gBAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE;oBAClC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;oBAC5B,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAC7C,oBAAA,eAAe,IAAI,CAAe,YAAA,EAAA,IAAI,CAAC,IAAI,MAAM,OAAO,GAAG,YAAY,GAAG,YAAY,EAAE;AAExF,oBAAA,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE;AACrB,wBAAA,eAAe,IAAI,SAAS,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK;;;AAIpD,gBAAA,eAAe,IAAI,CAAA,IAAA,EAAO,aAAa,CAAA,CAAE;gBACzC,OAAO;oBACL,eAAe,CAAC,IAAI,EAAE;AACtB,oBAAA;wBACE,UAAU,EAAE,MAAM,CAAC,UAAU;wBAC7B,KAAK,EAAE,MAAM,CAAC,KAAK;AACpB,qBAAA;iBACF;;AAGH,YAAA,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;;QAClE,OAAO,KAAK,EAAE;YACd,MAAM,IAAI,KAAK,CACb,CAAA,oBAAA,EAAwB,KAA2B,EAAE,OAAO,CAAE,CAAA,CAC/D;;AAEL,KAAC,EACD;QACE,IAAI,EAAE,SAAS,CAAC,YAAY;QAC5B,WAAW;AACX,QAAA,MAAM,EAAE,uBAAuB;QAC/B,cAAc,EAAE,SAAS,CAAC,oBAAoB;AAC/C,KAAA,CACF;AACH;;;;"}