@librechat/agents 3.1.35 → 3.1.37

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ToolNode.mjs","sources":["../../../src/tools/ToolNode.ts"],"sourcesContent":["import { ToolCall } from '@langchain/core/messages/tool';\nimport {\n ToolMessage,\n isAIMessage,\n isBaseMessage,\n} from '@langchain/core/messages';\nimport {\n END,\n Send,\n Command,\n isCommand,\n isGraphInterrupt,\n MessagesAnnotation,\n} from '@langchain/langgraph';\nimport type {\n RunnableConfig,\n RunnableToolLike,\n} from '@langchain/core/runnables';\nimport type { BaseMessage, AIMessage } from '@langchain/core/messages';\nimport type { StructuredToolInterface } from '@langchain/core/tools';\nimport type * as t from '@/types';\nimport { RunnableCallable } from '@/utils';\nimport { safeDispatchCustomEvent } from '@/utils/events';\nimport { Constants, GraphEvents } from '@/common';\n\n/**\n * Helper to check if a value is a Send object\n */\nfunction isSend(value: unknown): value is Send {\n return value instanceof Send;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class ToolNode<T = any> extends RunnableCallable<T, T> {\n private toolMap: Map<string, StructuredToolInterface | RunnableToolLike>;\n private loadRuntimeTools?: t.ToolRefGenerator;\n handleToolErrors = true;\n trace = false;\n toolCallStepIds?: Map<string, string>;\n errorHandler?: t.ToolNodeConstructorParams['errorHandler'];\n private toolUsageCount: Map<string, number>;\n /** Tool registry for filtering (lazy computation of programmatic maps) */\n private toolRegistry?: t.LCToolRegistry;\n /** Cached programmatic tools (computed once on first PTC call) */\n private programmaticCache?: t.ProgrammaticCache;\n /** Reference to Graph's sessions map for automatic session injection */\n private sessions?: t.ToolSessionMap;\n /** When true, dispatches ON_TOOL_EXECUTE events instead of invoking tools directly */\n private eventDrivenMode: boolean = false;\n /** Agent ID for event-driven mode */\n private agentId?: string;\n /** Tool names that bypass event dispatch and execute directly (e.g., graph-managed handoff tools) */\n private directToolNames?: Set<string>;\n\n constructor({\n tools,\n toolMap,\n name,\n tags,\n errorHandler,\n toolCallStepIds,\n handleToolErrors,\n loadRuntimeTools,\n toolRegistry,\n sessions,\n eventDrivenMode,\n agentId,\n directToolNames,\n }: t.ToolNodeConstructorParams) {\n super({ name, tags, func: (input, config) => this.run(input, config) });\n this.toolMap = toolMap ?? new Map(tools.map((tool) => [tool.name, tool]));\n this.toolCallStepIds = toolCallStepIds;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n this.loadRuntimeTools = loadRuntimeTools;\n this.errorHandler = errorHandler;\n this.toolUsageCount = new Map<string, number>();\n this.toolRegistry = toolRegistry;\n this.sessions = sessions;\n this.eventDrivenMode = eventDrivenMode ?? false;\n this.agentId = agentId;\n this.directToolNames = directToolNames;\n }\n\n /**\n * Returns cached programmatic tools, computing once on first access.\n * Single iteration builds both toolMap and toolDefs simultaneously.\n */\n private getProgrammaticTools(): { toolMap: t.ToolMap; toolDefs: t.LCTool[] } {\n if (this.programmaticCache) return this.programmaticCache;\n\n const toolMap: t.ToolMap = new Map();\n const toolDefs: t.LCTool[] = [];\n\n if (this.toolRegistry) {\n for (const [name, toolDef] of this.toolRegistry) {\n if (\n (toolDef.allowed_callers ?? ['direct']).includes('code_execution')\n ) {\n toolDefs.push(toolDef);\n const tool = this.toolMap.get(name);\n if (tool) toolMap.set(name, tool);\n }\n }\n }\n\n this.programmaticCache = { toolMap, toolDefs };\n return this.programmaticCache;\n }\n\n /**\n * Returns a snapshot of the current tool usage counts.\n * @returns A ReadonlyMap where keys are tool names and values are their usage counts.\n */\n public getToolUsageCounts(): ReadonlyMap<string, number> {\n return new Map(this.toolUsageCount); // Return a copy\n }\n\n /**\n * Runs a single tool call with error handling\n */\n protected async runTool(\n call: ToolCall,\n config: RunnableConfig\n ): Promise<BaseMessage | Command> {\n const tool = this.toolMap.get(call.name);\n try {\n if (tool === undefined) {\n throw new Error(`Tool \"${call.name}\" not found.`);\n }\n const turn = this.toolUsageCount.get(call.name) ?? 0;\n this.toolUsageCount.set(call.name, turn + 1);\n const args = call.args;\n const stepId = this.toolCallStepIds?.get(call.id!);\n\n // Build invoke params - LangChain extracts non-schema fields to config.toolCall\n let invokeParams: Record<string, unknown> = {\n ...call,\n args,\n type: 'tool_call',\n stepId,\n turn,\n };\n\n // Inject runtime data for special tools (becomes available at config.toolCall)\n if (call.name === Constants.PROGRAMMATIC_TOOL_CALLING) {\n const { toolMap, toolDefs } = this.getProgrammaticTools();\n invokeParams = {\n ...invokeParams,\n toolMap,\n toolDefs,\n };\n } else if (call.name === Constants.TOOL_SEARCH) {\n invokeParams = {\n ...invokeParams,\n toolRegistry: this.toolRegistry,\n };\n }\n\n /**\n * Inject session context for code execution tools when available.\n * Each file uses its own session_id (supporting multi-session file tracking).\n * Both session_id and _injected_files are injected directly to invokeParams\n * (not inside args) so they bypass Zod schema validation and reach config.toolCall.\n */\n if (\n call.name === Constants.EXECUTE_CODE ||\n call.name === Constants.PROGRAMMATIC_TOOL_CALLING\n ) {\n const codeSession = this.sessions?.get(Constants.EXECUTE_CODE) as\n | t.CodeSessionContext\n | undefined;\n if (codeSession?.files != null && codeSession.files.length > 0) {\n /**\n * Convert tracked files to CodeEnvFile format for the API.\n * Each file uses its own session_id (set when file was created).\n * This supports files from multiple parallel/sequential executions.\n */\n const fileRefs: t.CodeEnvFile[] = codeSession.files.map((file) => ({\n session_id: file.session_id ?? codeSession.session_id,\n id: file.id,\n name: file.name,\n }));\n /** Inject latest session_id and files - bypasses Zod, reaches config.toolCall */\n invokeParams = {\n ...invokeParams,\n session_id: codeSession.session_id,\n _injected_files: fileRefs,\n };\n }\n }\n\n const output = await tool.invoke(invokeParams, config);\n if (\n (isBaseMessage(output) && output._getType() === 'tool') ||\n isCommand(output)\n ) {\n return output;\n } else {\n return new ToolMessage({\n status: 'success',\n name: tool.name,\n content: typeof output === 'string' ? output : JSON.stringify(output),\n tool_call_id: call.id!,\n });\n }\n } catch (_e: unknown) {\n const e = _e as Error;\n if (!this.handleToolErrors) {\n throw e;\n }\n if (isGraphInterrupt(e)) {\n throw e;\n }\n if (this.errorHandler) {\n try {\n await this.errorHandler(\n {\n error: e,\n id: call.id!,\n name: call.name,\n input: call.args,\n },\n config.metadata\n );\n } catch (handlerError) {\n // eslint-disable-next-line no-console\n console.error('Error in errorHandler:', {\n toolName: call.name,\n toolCallId: call.id,\n toolArgs: call.args,\n stepId: this.toolCallStepIds?.get(call.id!),\n turn: this.toolUsageCount.get(call.name),\n originalError: {\n message: e.message,\n stack: e.stack ?? undefined,\n },\n handlerError:\n handlerError instanceof Error\n ? {\n message: handlerError.message,\n stack: handlerError.stack ?? undefined,\n }\n : {\n message: String(handlerError),\n stack: undefined,\n },\n });\n }\n }\n return new ToolMessage({\n status: 'error',\n content: `Error: ${e.message}\\n Please fix your mistakes.`,\n name: call.name,\n tool_call_id: call.id ?? '',\n });\n }\n }\n\n /**\n * Dispatches tool calls to the host via ON_TOOL_EXECUTE event and returns raw ToolMessages.\n * Core logic for event-driven execution, separated from output shaping.\n */\n private async dispatchToolEvents(\n toolCalls: ToolCall[],\n config: RunnableConfig\n ): Promise<ToolMessage[]> {\n const requests: t.ToolCallRequest[] = toolCalls.map((call) => {\n const turn = this.toolUsageCount.get(call.name) ?? 0;\n this.toolUsageCount.set(call.name, turn + 1);\n return {\n id: call.id!,\n name: call.name,\n args: call.args as Record<string, unknown>,\n stepId: this.toolCallStepIds?.get(call.id!),\n turn,\n };\n });\n\n const results = await new Promise<t.ToolExecuteResult[]>(\n (resolve, reject) => {\n const request: t.ToolExecuteBatchRequest = {\n toolCalls: requests,\n userId: config.configurable?.user_id as string | undefined,\n agentId: this.agentId,\n configurable: config.configurable as\n | Record<string, unknown>\n | undefined,\n metadata: config.metadata as Record<string, unknown> | undefined,\n resolve,\n reject,\n };\n\n safeDispatchCustomEvent(GraphEvents.ON_TOOL_EXECUTE, request, config);\n }\n );\n\n return results.map((result) => {\n const request = requests.find((r) => r.id === result.toolCallId);\n const toolName = request?.name ?? 'unknown';\n const stepId = this.toolCallStepIds?.get(result.toolCallId) ?? '';\n\n let toolMessage: ToolMessage;\n let contentString: string;\n\n if (result.status === 'error') {\n contentString = `Error: ${result.errorMessage ?? 'Unknown error'}\\n Please fix your mistakes.`;\n toolMessage = new ToolMessage({\n status: 'error',\n content: contentString,\n name: toolName,\n tool_call_id: result.toolCallId,\n });\n } else {\n contentString =\n typeof result.content === 'string'\n ? result.content\n : JSON.stringify(result.content);\n toolMessage = new ToolMessage({\n status: 'success',\n name: toolName,\n content: contentString,\n artifact: result.artifact,\n tool_call_id: result.toolCallId,\n });\n }\n\n const tool_call: t.ProcessedToolCall = {\n args:\n typeof request?.args === 'string'\n ? request.args\n : JSON.stringify(request?.args ?? {}),\n name: toolName,\n id: result.toolCallId,\n output: contentString,\n progress: 1,\n };\n\n const runStepCompletedData = {\n result: {\n id: stepId,\n index: request?.turn ?? 0,\n type: 'tool_call' as const,\n tool_call,\n },\n };\n\n safeDispatchCustomEvent(\n GraphEvents.ON_RUN_STEP_COMPLETED,\n runStepCompletedData,\n config\n );\n\n return toolMessage;\n });\n }\n\n /**\n * Execute all tool calls via ON_TOOL_EXECUTE event dispatch.\n * Used in event-driven mode where the host handles actual tool execution.\n */\n private async executeViaEvent(\n toolCalls: ToolCall[],\n config: RunnableConfig,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n input: any\n ): Promise<T> {\n const outputs = await this.dispatchToolEvents(toolCalls, config);\n return (Array.isArray(input) ? outputs : { messages: outputs }) as T;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected async run(input: any, config: RunnableConfig): Promise<T> {\n let outputs: (BaseMessage | Command)[];\n\n if (this.isSendInput(input)) {\n const isDirectTool = this.directToolNames?.has(input.lg_tool_call.name);\n if (this.eventDrivenMode && isDirectTool !== true) {\n return this.executeViaEvent([input.lg_tool_call], config, input);\n }\n outputs = [await this.runTool(input.lg_tool_call, config)];\n } else {\n let messages: BaseMessage[];\n if (Array.isArray(input)) {\n messages = input;\n } else if (this.isMessagesState(input)) {\n messages = input.messages;\n } else {\n throw new Error(\n 'ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.'\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg._getType() === 'tool')\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i];\n if (isAIMessage(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (aiMessage == null || !isAIMessage(aiMessage)) {\n throw new Error('ToolNode only accepts AIMessages as input.');\n }\n\n if (this.loadRuntimeTools) {\n const { tools, toolMap } = this.loadRuntimeTools(\n aiMessage.tool_calls ?? []\n );\n this.toolMap =\n toolMap ?? new Map(tools.map((tool) => [tool.name, tool]));\n this.programmaticCache = undefined; // Invalidate cache on toolMap change\n }\n\n const filteredCalls =\n aiMessage.tool_calls?.filter((call) => {\n /**\n * Filter out:\n * 1. Already processed tool calls (present in toolMessageIds)\n * 2. Server tool calls (e.g., web_search with IDs starting with 'srvtoolu_')\n * which are executed by the provider's API and don't require invocation\n */\n return (\n (call.id == null || !toolMessageIds.has(call.id)) &&\n !(call.id?.startsWith('srvtoolu_') ?? false)\n );\n }) ?? [];\n\n if (this.eventDrivenMode && filteredCalls.length > 0) {\n if (!this.directToolNames || this.directToolNames.size === 0) {\n return this.executeViaEvent(filteredCalls, config, input);\n }\n\n const directCalls = filteredCalls.filter((c) =>\n this.directToolNames!.has(c.name)\n );\n const eventCalls = filteredCalls.filter(\n (c) => !this.directToolNames!.has(c.name)\n );\n\n const directOutputs: (BaseMessage | Command)[] =\n directCalls.length > 0\n ? await Promise.all(\n directCalls.map((call) => this.runTool(call, config))\n )\n : [];\n\n const eventOutputs: ToolMessage[] =\n eventCalls.length > 0\n ? await this.dispatchToolEvents(eventCalls, config)\n : [];\n\n outputs = [...directOutputs, ...eventOutputs];\n } else {\n outputs = await Promise.all(\n filteredCalls.map((call) => this.runTool(call, config))\n );\n }\n }\n\n if (!outputs.some(isCommand)) {\n return (Array.isArray(input) ? outputs : { messages: outputs }) as T;\n }\n\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n /**\n * Collect handoff commands (Commands with string goto and Command.PARENT)\n * for potential parallel handoff aggregation\n */\n const handoffCommands: Command[] = [];\n const nonCommandOutputs: BaseMessage[] = [];\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send): send is Send => isSend(send))\n ) {\n /** Aggregate Send-based commands */\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else if (output.graph === Command.PARENT) {\n /**\n * Handoff Command with destination.\n * Handle both string ('agent') and array (['agent']) formats.\n * Collect for potential parallel aggregation.\n */\n const goto = output.goto;\n const isSingleStringDest = typeof goto === 'string';\n const isSingleArrayDest =\n Array.isArray(goto) &&\n goto.length === 1 &&\n typeof goto[0] === 'string';\n\n if (isSingleStringDest || isSingleArrayDest) {\n handoffCommands.push(output);\n } else {\n /** Multi-destination or other command - pass through */\n combinedOutputs.push(output);\n }\n } else {\n /** Other commands - pass through */\n combinedOutputs.push(output);\n }\n } else {\n nonCommandOutputs.push(output);\n combinedOutputs.push(\n Array.isArray(input) ? [output] : { messages: [output] }\n );\n }\n }\n\n /**\n * Handle handoff commands - convert to Send objects for parallel execution\n * when multiple handoffs are requested\n */\n if (handoffCommands.length > 1) {\n /**\n * Multiple parallel handoffs - convert to Send objects.\n * Each Send carries its own state with the appropriate messages.\n * This enables LLM-initiated parallel execution when calling multiple\n * transfer tools simultaneously.\n */\n\n /** Collect all destinations for sibling tracking */\n const allDestinations = handoffCommands.map((cmd) => {\n const goto = cmd.goto;\n return typeof goto === 'string' ? goto : (goto as string[])[0];\n });\n\n const sends = handoffCommands.map((cmd, idx) => {\n const destination = allDestinations[idx];\n /** Get siblings (other destinations, not this one) */\n const siblings = allDestinations.filter((d) => d !== destination);\n\n /** Add siblings to ToolMessage additional_kwargs */\n const update = cmd.update as { messages?: BaseMessage[] } | undefined;\n if (update && update.messages) {\n for (const msg of update.messages) {\n if (msg.getType() === 'tool') {\n (msg as ToolMessage).additional_kwargs.handoff_parallel_siblings =\n siblings;\n }\n }\n }\n\n return new Send(destination, cmd.update);\n });\n\n const parallelCommand = new Command({\n graph: Command.PARENT,\n goto: sends,\n });\n combinedOutputs.push(parallelCommand);\n } else if (handoffCommands.length === 1) {\n /** Single handoff - pass through as-is */\n combinedOutputs.push(handoffCommands[0]);\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as T;\n }\n\n private isSendInput(input: unknown): input is { lg_tool_call: ToolCall } {\n return (\n typeof input === 'object' && input != null && 'lg_tool_call' in input\n );\n }\n\n private isMessagesState(\n input: unknown\n ): input is { messages: BaseMessage[] } {\n return (\n typeof input === 'object' &&\n input != null &&\n 'messages' in input &&\n Array.isArray((input as { messages: unknown }).messages) &&\n (input as { messages: unknown[] }).messages.every(isBaseMessage)\n );\n }\n}\n\nfunction areToolCallsInvoked(\n message: AIMessage,\n invokedToolIds?: Set<string>\n): boolean {\n if (!invokedToolIds || invokedToolIds.size === 0) return false;\n return (\n message.tool_calls?.every(\n (toolCall) => toolCall.id != null && invokedToolIds.has(toolCall.id)\n ) ?? false\n );\n}\n\nexport function toolsCondition<T extends string>(\n state: BaseMessage[] | typeof MessagesAnnotation.State,\n toolNode: T,\n invokedToolIds?: Set<string>\n): T | typeof END {\n const messages = Array.isArray(state) ? state : state.messages;\n const message = messages[messages.length - 1] as AIMessage | undefined;\n\n if (\n message &&\n 'tool_calls' in message &&\n (message.tool_calls?.length ?? 0) > 0 &&\n !areToolCallsInvoked(message, invokedToolIds)\n ) {\n return toolNode;\n }\n return END;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ToolNode.mjs","sources":["../../../src/tools/ToolNode.ts"],"sourcesContent":["import { ToolCall } from '@langchain/core/messages/tool';\nimport {\n ToolMessage,\n isAIMessage,\n isBaseMessage,\n} from '@langchain/core/messages';\nimport {\n END,\n Send,\n Command,\n isCommand,\n isGraphInterrupt,\n MessagesAnnotation,\n} from '@langchain/langgraph';\nimport type {\n RunnableConfig,\n RunnableToolLike,\n} from '@langchain/core/runnables';\nimport type { BaseMessage, AIMessage } from '@langchain/core/messages';\nimport type { StructuredToolInterface } from '@langchain/core/tools';\nimport type * as t from '@/types';\nimport { RunnableCallable } from '@/utils';\nimport { safeDispatchCustomEvent } from '@/utils/events';\nimport { Constants, GraphEvents } from '@/common';\n\n/**\n * Helper to check if a value is a Send object\n */\nfunction isSend(value: unknown): value is Send {\n return value instanceof Send;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class ToolNode<T = any> extends RunnableCallable<T, T> {\n private toolMap: Map<string, StructuredToolInterface | RunnableToolLike>;\n private loadRuntimeTools?: t.ToolRefGenerator;\n handleToolErrors = true;\n trace = false;\n toolCallStepIds?: Map<string, string>;\n errorHandler?: t.ToolNodeConstructorParams['errorHandler'];\n private toolUsageCount: Map<string, number>;\n /** Tool registry for filtering (lazy computation of programmatic maps) */\n private toolRegistry?: t.LCToolRegistry;\n /** Cached programmatic tools (computed once on first PTC call) */\n private programmaticCache?: t.ProgrammaticCache;\n /** Reference to Graph's sessions map for automatic session injection */\n private sessions?: t.ToolSessionMap;\n /** When true, dispatches ON_TOOL_EXECUTE events instead of invoking tools directly */\n private eventDrivenMode: boolean = false;\n /** Agent ID for event-driven mode */\n private agentId?: string;\n /** Tool names that bypass event dispatch and execute directly (e.g., graph-managed handoff tools) */\n private directToolNames?: Set<string>;\n\n constructor({\n tools,\n toolMap,\n name,\n tags,\n errorHandler,\n toolCallStepIds,\n handleToolErrors,\n loadRuntimeTools,\n toolRegistry,\n sessions,\n eventDrivenMode,\n agentId,\n directToolNames,\n }: t.ToolNodeConstructorParams) {\n super({ name, tags, func: (input, config) => this.run(input, config) });\n this.toolMap = toolMap ?? new Map(tools.map((tool) => [tool.name, tool]));\n this.toolCallStepIds = toolCallStepIds;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n this.loadRuntimeTools = loadRuntimeTools;\n this.errorHandler = errorHandler;\n this.toolUsageCount = new Map<string, number>();\n this.toolRegistry = toolRegistry;\n this.sessions = sessions;\n this.eventDrivenMode = eventDrivenMode ?? false;\n this.agentId = agentId;\n this.directToolNames = directToolNames;\n }\n\n /**\n * Returns cached programmatic tools, computing once on first access.\n * Single iteration builds both toolMap and toolDefs simultaneously.\n */\n private getProgrammaticTools(): { toolMap: t.ToolMap; toolDefs: t.LCTool[] } {\n if (this.programmaticCache) return this.programmaticCache;\n\n const toolMap: t.ToolMap = new Map();\n const toolDefs: t.LCTool[] = [];\n\n if (this.toolRegistry) {\n for (const [name, toolDef] of this.toolRegistry) {\n if (\n (toolDef.allowed_callers ?? ['direct']).includes('code_execution')\n ) {\n toolDefs.push(toolDef);\n const tool = this.toolMap.get(name);\n if (tool) toolMap.set(name, tool);\n }\n }\n }\n\n this.programmaticCache = { toolMap, toolDefs };\n return this.programmaticCache;\n }\n\n /**\n * Returns a snapshot of the current tool usage counts.\n * @returns A ReadonlyMap where keys are tool names and values are their usage counts.\n */\n public getToolUsageCounts(): ReadonlyMap<string, number> {\n return new Map(this.toolUsageCount); // Return a copy\n }\n\n /**\n * Runs a single tool call with error handling\n */\n protected async runTool(\n call: ToolCall,\n config: RunnableConfig\n ): Promise<BaseMessage | Command> {\n const tool = this.toolMap.get(call.name);\n try {\n if (tool === undefined) {\n throw new Error(`Tool \"${call.name}\" not found.`);\n }\n const turn = this.toolUsageCount.get(call.name) ?? 0;\n this.toolUsageCount.set(call.name, turn + 1);\n const args = call.args;\n const stepId = this.toolCallStepIds?.get(call.id!);\n\n // Build invoke params - LangChain extracts non-schema fields to config.toolCall\n let invokeParams: Record<string, unknown> = {\n ...call,\n args,\n type: 'tool_call',\n stepId,\n turn,\n };\n\n // Inject runtime data for special tools (becomes available at config.toolCall)\n if (call.name === Constants.PROGRAMMATIC_TOOL_CALLING) {\n const { toolMap, toolDefs } = this.getProgrammaticTools();\n invokeParams = {\n ...invokeParams,\n toolMap,\n toolDefs,\n };\n } else if (call.name === Constants.TOOL_SEARCH) {\n invokeParams = {\n ...invokeParams,\n toolRegistry: this.toolRegistry,\n };\n }\n\n /**\n * Inject session context for code execution tools when available.\n * Each file uses its own session_id (supporting multi-session file tracking).\n * Both session_id and _injected_files are injected directly to invokeParams\n * (not inside args) so they bypass Zod schema validation and reach config.toolCall.\n *\n * session_id is always injected when available (even without tracked files)\n * so the CodeExecutor can fall back to the /files endpoint for session continuity.\n */\n if (\n call.name === Constants.EXECUTE_CODE ||\n call.name === Constants.PROGRAMMATIC_TOOL_CALLING\n ) {\n const codeSession = this.sessions?.get(Constants.EXECUTE_CODE) as\n | t.CodeSessionContext\n | undefined;\n if (codeSession?.session_id != null && codeSession.session_id !== '') {\n invokeParams = {\n ...invokeParams,\n session_id: codeSession.session_id,\n };\n\n if (codeSession.files != null && codeSession.files.length > 0) {\n const fileRefs: t.CodeEnvFile[] = codeSession.files.map((file) => ({\n session_id: file.session_id ?? codeSession.session_id,\n id: file.id,\n name: file.name,\n }));\n invokeParams._injected_files = fileRefs;\n }\n }\n }\n\n const output = await tool.invoke(invokeParams, config);\n if (\n (isBaseMessage(output) && output._getType() === 'tool') ||\n isCommand(output)\n ) {\n return output;\n } else {\n return new ToolMessage({\n status: 'success',\n name: tool.name,\n content: typeof output === 'string' ? output : JSON.stringify(output),\n tool_call_id: call.id!,\n });\n }\n } catch (_e: unknown) {\n const e = _e as Error;\n if (!this.handleToolErrors) {\n throw e;\n }\n if (isGraphInterrupt(e)) {\n throw e;\n }\n if (this.errorHandler) {\n try {\n await this.errorHandler(\n {\n error: e,\n id: call.id!,\n name: call.name,\n input: call.args,\n },\n config.metadata\n );\n } catch (handlerError) {\n // eslint-disable-next-line no-console\n console.error('Error in errorHandler:', {\n toolName: call.name,\n toolCallId: call.id,\n toolArgs: call.args,\n stepId: this.toolCallStepIds?.get(call.id!),\n turn: this.toolUsageCount.get(call.name),\n originalError: {\n message: e.message,\n stack: e.stack ?? undefined,\n },\n handlerError:\n handlerError instanceof Error\n ? {\n message: handlerError.message,\n stack: handlerError.stack ?? undefined,\n }\n : {\n message: String(handlerError),\n stack: undefined,\n },\n });\n }\n }\n return new ToolMessage({\n status: 'error',\n content: `Error: ${e.message}\\n Please fix your mistakes.`,\n name: call.name,\n tool_call_id: call.id ?? '',\n });\n }\n }\n\n /**\n * Builds code session context for injection into event-driven tool calls.\n * Mirrors the session injection logic in runTool() for direct execution.\n */\n private getCodeSessionContext(): t.ToolCallRequest['codeSessionContext'] {\n if (!this.sessions) {\n return undefined;\n }\n\n const codeSession = this.sessions.get(Constants.EXECUTE_CODE) as\n | t.CodeSessionContext\n | undefined;\n if (!codeSession) {\n return undefined;\n }\n\n const context: NonNullable<t.ToolCallRequest['codeSessionContext']> = {\n session_id: codeSession.session_id,\n };\n\n if (codeSession.files && codeSession.files.length > 0) {\n context.files = codeSession.files.map((file) => ({\n session_id: file.session_id ?? codeSession.session_id,\n id: file.id,\n name: file.name,\n }));\n }\n\n return context;\n }\n\n /**\n * Extracts code execution session context from tool results and stores in Graph.sessions.\n * Mirrors the session storage logic in Graph.handleToolCallCompleted() for direct execution.\n */\n private storeCodeSessionFromResults(\n results: t.ToolExecuteResult[],\n requests: t.ToolCallRequest[]\n ): void {\n if (!this.sessions) {\n return;\n }\n\n for (let i = 0; i < results.length; i++) {\n const result = results[i];\n if (result.status !== 'success' || result.artifact == null) {\n continue;\n }\n\n const request = requests.find((r) => r.id === result.toolCallId);\n if (\n request?.name !== Constants.EXECUTE_CODE &&\n request?.name !== Constants.PROGRAMMATIC_TOOL_CALLING\n ) {\n continue;\n }\n\n const artifact = result.artifact as t.CodeExecutionArtifact | undefined;\n if (artifact?.session_id == null || artifact.session_id === '') {\n continue;\n }\n\n const newFiles = artifact.files ?? [];\n const existingSession = this.sessions.get(Constants.EXECUTE_CODE) as\n | t.CodeSessionContext\n | undefined;\n const existingFiles = existingSession?.files ?? [];\n\n if (newFiles.length > 0) {\n const filesWithSession: t.FileRefs = newFiles.map((file) => ({\n ...file,\n session_id: artifact.session_id,\n }));\n\n const newFileNames = new Set(filesWithSession.map((f) => f.name));\n const filteredExisting = existingFiles.filter(\n (f) => !newFileNames.has(f.name)\n );\n\n this.sessions.set(Constants.EXECUTE_CODE, {\n session_id: artifact.session_id,\n files: [...filteredExisting, ...filesWithSession],\n lastUpdated: Date.now(),\n });\n } else {\n this.sessions.set(Constants.EXECUTE_CODE, {\n session_id: artifact.session_id,\n files: existingFiles,\n lastUpdated: Date.now(),\n });\n }\n }\n }\n\n /**\n * Dispatches tool calls to the host via ON_TOOL_EXECUTE event and returns raw ToolMessages.\n * Core logic for event-driven execution, separated from output shaping.\n */\n private async dispatchToolEvents(\n toolCalls: ToolCall[],\n config: RunnableConfig\n ): Promise<ToolMessage[]> {\n const requests: t.ToolCallRequest[] = toolCalls.map((call) => {\n const turn = this.toolUsageCount.get(call.name) ?? 0;\n this.toolUsageCount.set(call.name, turn + 1);\n\n const request: t.ToolCallRequest = {\n id: call.id!,\n name: call.name,\n args: call.args as Record<string, unknown>,\n stepId: this.toolCallStepIds?.get(call.id!),\n turn,\n };\n\n if (\n call.name === Constants.EXECUTE_CODE ||\n call.name === Constants.PROGRAMMATIC_TOOL_CALLING\n ) {\n request.codeSessionContext = this.getCodeSessionContext();\n }\n\n return request;\n });\n\n const results = await new Promise<t.ToolExecuteResult[]>(\n (resolve, reject) => {\n const request: t.ToolExecuteBatchRequest = {\n toolCalls: requests,\n userId: config.configurable?.user_id as string | undefined,\n agentId: this.agentId,\n configurable: config.configurable as\n | Record<string, unknown>\n | undefined,\n metadata: config.metadata as Record<string, unknown> | undefined,\n resolve,\n reject,\n };\n\n safeDispatchCustomEvent(GraphEvents.ON_TOOL_EXECUTE, request, config);\n }\n );\n\n this.storeCodeSessionFromResults(results, requests);\n\n return results.map((result) => {\n const request = requests.find((r) => r.id === result.toolCallId);\n const toolName = request?.name ?? 'unknown';\n const stepId = this.toolCallStepIds?.get(result.toolCallId) ?? '';\n\n let toolMessage: ToolMessage;\n let contentString: string;\n\n if (result.status === 'error') {\n contentString = `Error: ${result.errorMessage ?? 'Unknown error'}\\n Please fix your mistakes.`;\n toolMessage = new ToolMessage({\n status: 'error',\n content: contentString,\n name: toolName,\n tool_call_id: result.toolCallId,\n });\n } else {\n contentString =\n typeof result.content === 'string'\n ? result.content\n : JSON.stringify(result.content);\n toolMessage = new ToolMessage({\n status: 'success',\n name: toolName,\n content: contentString,\n artifact: result.artifact,\n tool_call_id: result.toolCallId,\n });\n }\n\n const tool_call: t.ProcessedToolCall = {\n args:\n typeof request?.args === 'string'\n ? request.args\n : JSON.stringify(request?.args ?? {}),\n name: toolName,\n id: result.toolCallId,\n output: contentString,\n progress: 1,\n };\n\n const runStepCompletedData = {\n result: {\n id: stepId,\n index: request?.turn ?? 0,\n type: 'tool_call' as const,\n tool_call,\n },\n };\n\n safeDispatchCustomEvent(\n GraphEvents.ON_RUN_STEP_COMPLETED,\n runStepCompletedData,\n config\n );\n\n return toolMessage;\n });\n }\n\n /**\n * Execute all tool calls via ON_TOOL_EXECUTE event dispatch.\n * Used in event-driven mode where the host handles actual tool execution.\n */\n private async executeViaEvent(\n toolCalls: ToolCall[],\n config: RunnableConfig,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n input: any\n ): Promise<T> {\n const outputs = await this.dispatchToolEvents(toolCalls, config);\n return (Array.isArray(input) ? outputs : { messages: outputs }) as T;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected async run(input: any, config: RunnableConfig): Promise<T> {\n let outputs: (BaseMessage | Command)[];\n\n if (this.isSendInput(input)) {\n const isDirectTool = this.directToolNames?.has(input.lg_tool_call.name);\n if (this.eventDrivenMode && isDirectTool !== true) {\n return this.executeViaEvent([input.lg_tool_call], config, input);\n }\n outputs = [await this.runTool(input.lg_tool_call, config)];\n } else {\n let messages: BaseMessage[];\n if (Array.isArray(input)) {\n messages = input;\n } else if (this.isMessagesState(input)) {\n messages = input.messages;\n } else {\n throw new Error(\n 'ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.'\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg._getType() === 'tool')\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i];\n if (isAIMessage(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (aiMessage == null || !isAIMessage(aiMessage)) {\n throw new Error('ToolNode only accepts AIMessages as input.');\n }\n\n if (this.loadRuntimeTools) {\n const { tools, toolMap } = this.loadRuntimeTools(\n aiMessage.tool_calls ?? []\n );\n this.toolMap =\n toolMap ?? new Map(tools.map((tool) => [tool.name, tool]));\n this.programmaticCache = undefined; // Invalidate cache on toolMap change\n }\n\n const filteredCalls =\n aiMessage.tool_calls?.filter((call) => {\n /**\n * Filter out:\n * 1. Already processed tool calls (present in toolMessageIds)\n * 2. Server tool calls (e.g., web_search with IDs starting with 'srvtoolu_')\n * which are executed by the provider's API and don't require invocation\n */\n return (\n (call.id == null || !toolMessageIds.has(call.id)) &&\n !(call.id?.startsWith('srvtoolu_') ?? false)\n );\n }) ?? [];\n\n if (this.eventDrivenMode && filteredCalls.length > 0) {\n if (!this.directToolNames || this.directToolNames.size === 0) {\n return this.executeViaEvent(filteredCalls, config, input);\n }\n\n const directCalls = filteredCalls.filter((c) =>\n this.directToolNames!.has(c.name)\n );\n const eventCalls = filteredCalls.filter(\n (c) => !this.directToolNames!.has(c.name)\n );\n\n const directOutputs: (BaseMessage | Command)[] =\n directCalls.length > 0\n ? await Promise.all(\n directCalls.map((call) => this.runTool(call, config))\n )\n : [];\n\n const eventOutputs: ToolMessage[] =\n eventCalls.length > 0\n ? await this.dispatchToolEvents(eventCalls, config)\n : [];\n\n outputs = [...directOutputs, ...eventOutputs];\n } else {\n outputs = await Promise.all(\n filteredCalls.map((call) => this.runTool(call, config))\n );\n }\n }\n\n if (!outputs.some(isCommand)) {\n return (Array.isArray(input) ? outputs : { messages: outputs }) as T;\n }\n\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n /**\n * Collect handoff commands (Commands with string goto and Command.PARENT)\n * for potential parallel handoff aggregation\n */\n const handoffCommands: Command[] = [];\n const nonCommandOutputs: BaseMessage[] = [];\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send): send is Send => isSend(send))\n ) {\n /** Aggregate Send-based commands */\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else if (output.graph === Command.PARENT) {\n /**\n * Handoff Command with destination.\n * Handle both string ('agent') and array (['agent']) formats.\n * Collect for potential parallel aggregation.\n */\n const goto = output.goto;\n const isSingleStringDest = typeof goto === 'string';\n const isSingleArrayDest =\n Array.isArray(goto) &&\n goto.length === 1 &&\n typeof goto[0] === 'string';\n\n if (isSingleStringDest || isSingleArrayDest) {\n handoffCommands.push(output);\n } else {\n /** Multi-destination or other command - pass through */\n combinedOutputs.push(output);\n }\n } else {\n /** Other commands - pass through */\n combinedOutputs.push(output);\n }\n } else {\n nonCommandOutputs.push(output);\n combinedOutputs.push(\n Array.isArray(input) ? [output] : { messages: [output] }\n );\n }\n }\n\n /**\n * Handle handoff commands - convert to Send objects for parallel execution\n * when multiple handoffs are requested\n */\n if (handoffCommands.length > 1) {\n /**\n * Multiple parallel handoffs - convert to Send objects.\n * Each Send carries its own state with the appropriate messages.\n * This enables LLM-initiated parallel execution when calling multiple\n * transfer tools simultaneously.\n */\n\n /** Collect all destinations for sibling tracking */\n const allDestinations = handoffCommands.map((cmd) => {\n const goto = cmd.goto;\n return typeof goto === 'string' ? goto : (goto as string[])[0];\n });\n\n const sends = handoffCommands.map((cmd, idx) => {\n const destination = allDestinations[idx];\n /** Get siblings (other destinations, not this one) */\n const siblings = allDestinations.filter((d) => d !== destination);\n\n /** Add siblings to ToolMessage additional_kwargs */\n const update = cmd.update as { messages?: BaseMessage[] } | undefined;\n if (update && update.messages) {\n for (const msg of update.messages) {\n if (msg.getType() === 'tool') {\n (msg as ToolMessage).additional_kwargs.handoff_parallel_siblings =\n siblings;\n }\n }\n }\n\n return new Send(destination, cmd.update);\n });\n\n const parallelCommand = new Command({\n graph: Command.PARENT,\n goto: sends,\n });\n combinedOutputs.push(parallelCommand);\n } else if (handoffCommands.length === 1) {\n /** Single handoff - pass through as-is */\n combinedOutputs.push(handoffCommands[0]);\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as T;\n }\n\n private isSendInput(input: unknown): input is { lg_tool_call: ToolCall } {\n return (\n typeof input === 'object' && input != null && 'lg_tool_call' in input\n );\n }\n\n private isMessagesState(\n input: unknown\n ): input is { messages: BaseMessage[] } {\n return (\n typeof input === 'object' &&\n input != null &&\n 'messages' in input &&\n Array.isArray((input as { messages: unknown }).messages) &&\n (input as { messages: unknown[] }).messages.every(isBaseMessage)\n );\n }\n}\n\nfunction areToolCallsInvoked(\n message: AIMessage,\n invokedToolIds?: Set<string>\n): boolean {\n if (!invokedToolIds || invokedToolIds.size === 0) return false;\n return (\n message.tool_calls?.every(\n (toolCall) => toolCall.id != null && invokedToolIds.has(toolCall.id)\n ) ?? false\n );\n}\n\nexport function toolsCondition<T extends string>(\n state: BaseMessage[] | typeof MessagesAnnotation.State,\n toolNode: T,\n invokedToolIds?: Set<string>\n): T | typeof END {\n const messages = Array.isArray(state) ? state : state.messages;\n const message = messages[messages.length - 1] as AIMessage | undefined;\n\n if (\n message &&\n 'tool_calls' in message &&\n (message.tool_calls?.length ?? 0) > 0 &&\n !areToolCallsInvoked(message, invokedToolIds)\n ) {\n return toolNode;\n }\n return END;\n}\n"],"names":[],"mappings":"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"}
@@ -39,6 +39,16 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
39
39
  * Runs a single tool call with error handling
40
40
  */
41
41
  protected runTool(call: ToolCall, config: RunnableConfig): Promise<BaseMessage | Command>;
42
+ /**
43
+ * Builds code session context for injection into event-driven tool calls.
44
+ * Mirrors the session injection logic in runTool() for direct execution.
45
+ */
46
+ private getCodeSessionContext;
47
+ /**
48
+ * Extracts code execution session context from tool results and stores in Graph.sessions.
49
+ * Mirrors the session storage logic in Graph.handleToolCallCompleted() for direct execution.
50
+ */
51
+ private storeCodeSessionFromResults;
42
52
  /**
43
53
  * Dispatches tool calls to the host via ON_TOOL_EXECUTE event and returns raw ToolMessages.
44
54
  * Core logic for event-driven execution, separated from output shaping.
@@ -123,6 +123,11 @@ export type ToolCallRequest = {
123
123
  stepId?: string;
124
124
  /** Usage turn count for this tool */
125
125
  turn?: number;
126
+ /** Code execution session context for session continuity in event-driven mode */
127
+ codeSessionContext?: {
128
+ session_id: string;
129
+ files?: CodeEnvFile[];
130
+ };
126
131
  };
127
132
  /** Batch request containing ALL tool calls for a graph step */
128
133
  export type ToolExecuteBatchRequest = {
@@ -278,7 +283,7 @@ export type CodeSessionContext = {
278
283
  /** Session ID from the code execution environment */
279
284
  session_id: string;
280
285
  /** Files generated in this session (for context/tracking) */
281
- files: FileRefs;
286
+ files?: FileRefs;
282
287
  /** Timestamp of last update */
283
288
  lastUpdated: number;
284
289
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "3.1.35",
3
+ "version": "3.1.37",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -1110,46 +1110,51 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1110
1110
  toolName === Constants.PROGRAMMATIC_TOOL_CALLING
1111
1111
  ) {
1112
1112
  const artifact = output.artifact as t.CodeExecutionArtifact | undefined;
1113
- const newFiles = artifact?.files ?? [];
1114
- const hasNewFiles = newFiles.length > 0;
1115
-
1116
- if (
1117
- hasNewFiles &&
1118
- artifact?.session_id != null &&
1119
- artifact.session_id !== ''
1120
- ) {
1121
- /**
1122
- * Stamp each new file with its source session_id.
1123
- * This enables files from different executions (parallel or sequential)
1124
- * to be tracked and passed to subsequent calls.
1125
- */
1126
- const filesWithSession: t.FileRefs = newFiles.map((file) => ({
1127
- ...file,
1128
- session_id: artifact.session_id,
1129
- }));
1130
-
1113
+ if (artifact?.session_id != null && artifact.session_id !== '') {
1114
+ const newFiles = artifact.files ?? [];
1131
1115
  const existingSession = this.sessions.get(Constants.EXECUTE_CODE) as
1132
1116
  | t.CodeSessionContext
1133
1117
  | undefined;
1134
1118
  const existingFiles = existingSession?.files ?? [];
1135
1119
 
1136
- /**
1137
- * Merge files, preferring latest versions by name.
1138
- * If a file with the same name exists, replace it with the new version.
1139
- * This handles cases where files are edited/recreated in subsequent executions.
1140
- */
1141
- const newFileNames = new Set(filesWithSession.map((f) => f.name));
1142
- const filteredExisting = existingFiles.filter(
1143
- (f) => !newFileNames.has(f.name)
1144
- );
1145
-
1146
- this.sessions.set(Constants.EXECUTE_CODE, {
1147
- /** Keep latest session_id for reference/fallback */
1148
- session_id: artifact.session_id,
1149
- /** Accumulated files with latest versions preferred */
1150
- files: [...filteredExisting, ...filesWithSession],
1151
- lastUpdated: Date.now(),
1152
- });
1120
+ if (newFiles.length > 0) {
1121
+ /**
1122
+ * Stamp each new file with its source session_id.
1123
+ * This enables files from different executions (parallel or sequential)
1124
+ * to be tracked and passed to subsequent calls.
1125
+ */
1126
+ const filesWithSession: t.FileRefs = newFiles.map((file) => ({
1127
+ ...file,
1128
+ session_id: artifact.session_id,
1129
+ }));
1130
+
1131
+ /**
1132
+ * Merge files, preferring latest versions by name.
1133
+ * If a file with the same name exists, replace it with the new version.
1134
+ * This handles cases where files are edited/recreated in subsequent executions.
1135
+ */
1136
+ const newFileNames = new Set(filesWithSession.map((f) => f.name));
1137
+ const filteredExisting = existingFiles.filter(
1138
+ (f) => !newFileNames.has(f.name)
1139
+ );
1140
+
1141
+ this.sessions.set(Constants.EXECUTE_CODE, {
1142
+ session_id: artifact.session_id,
1143
+ files: [...filteredExisting, ...filesWithSession],
1144
+ lastUpdated: Date.now(),
1145
+ });
1146
+ } else {
1147
+ /**
1148
+ * Store session_id even without new files for session continuity.
1149
+ * The CodeExecutor can fall back to the /files endpoint to discover
1150
+ * session files not explicitly returned in the exec response.
1151
+ */
1152
+ this.sessions.set(Constants.EXECUTE_CODE, {
1153
+ session_id: artifact.session_id,
1154
+ files: existingFiles,
1155
+ lastUpdated: Date.now(),
1156
+ });
1157
+ }
1153
1158
  }
1154
1159
  }
1155
1160
 
@@ -212,47 +212,6 @@ describe('CustomChatBedrockConverse', () => {
212
212
  return model as any;
213
213
  }
214
214
 
215
- test('should detect contentBlockIndex at top level', () => {
216
- const model = getModelWithCleanMethods();
217
- const objWithIndex = { contentBlockIndex: 0, text: 'hello' };
218
- const objWithoutIndex = { text: 'hello' };
219
-
220
- expect(model.hasContentBlockIndex(objWithIndex)).toBe(true);
221
- expect(model.hasContentBlockIndex(objWithoutIndex)).toBe(false);
222
- });
223
-
224
- test('should detect contentBlockIndex in nested objects', () => {
225
- const model = getModelWithCleanMethods();
226
- const nestedWithIndex = {
227
- outer: {
228
- inner: {
229
- contentBlockIndex: 1,
230
- data: 'test',
231
- },
232
- },
233
- };
234
- const nestedWithoutIndex = {
235
- outer: {
236
- inner: {
237
- data: 'test',
238
- },
239
- },
240
- };
241
-
242
- expect(model.hasContentBlockIndex(nestedWithIndex)).toBe(true);
243
- expect(model.hasContentBlockIndex(nestedWithoutIndex)).toBe(false);
244
- });
245
-
246
- test('should return false for null, undefined, and primitives', () => {
247
- const model = getModelWithCleanMethods();
248
-
249
- expect(model.hasContentBlockIndex(null)).toBe(false);
250
- expect(model.hasContentBlockIndex(undefined)).toBe(false);
251
- expect(model.hasContentBlockIndex('string')).toBe(false);
252
- expect(model.hasContentBlockIndex(123)).toBe(false);
253
- expect(model.hasContentBlockIndex(true)).toBe(false);
254
- });
255
-
256
215
  test('should remove contentBlockIndex from top level', () => {
257
216
  const model = getModelWithCleanMethods();
258
217
  const obj = {
@@ -220,15 +220,12 @@ export function handleConverseStreamContentBlockDelta(
220
220
  bedrockReasoningDeltaToLangchainPartialReasoningBlock(
221
221
  contentBlockDelta.delta.reasoningContent
222
222
  );
223
- // Extract the text for additional_kwargs.reasoning_content (for stream handler compatibility)
224
- const reasoningText =
225
- 'reasoningText' in reasoningBlock
226
- ? (reasoningBlock.reasoningText.text ??
227
- reasoningBlock.reasoningText.signature ??
228
- ('redactedContent' in reasoningBlock
229
- ? reasoningBlock.redactedContent
230
- : ''))
231
- : '';
223
+ let reasoningText = '';
224
+ if ('reasoningText' in reasoningBlock) {
225
+ reasoningText = reasoningBlock.reasoningText.text ?? '';
226
+ } else if ('redactedContent' in reasoningBlock) {
227
+ reasoningText = reasoningBlock.redactedContent;
228
+ }
232
229
  return new ChatGenerationChunk({
233
230
  text: '',
234
231
  message: new AIMessageChunk({
@@ -161,6 +161,9 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
161
161
  * Each file uses its own session_id (supporting multi-session file tracking).
162
162
  * Both session_id and _injected_files are injected directly to invokeParams
163
163
  * (not inside args) so they bypass Zod schema validation and reach config.toolCall.
164
+ *
165
+ * session_id is always injected when available (even without tracked files)
166
+ * so the CodeExecutor can fall back to the /files endpoint for session continuity.
164
167
  */
165
168
  if (
166
169
  call.name === Constants.EXECUTE_CODE ||
@@ -169,23 +172,20 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
169
172
  const codeSession = this.sessions?.get(Constants.EXECUTE_CODE) as
170
173
  | t.CodeSessionContext
171
174
  | undefined;
172
- if (codeSession?.files != null && codeSession.files.length > 0) {
173
- /**
174
- * Convert tracked files to CodeEnvFile format for the API.
175
- * Each file uses its own session_id (set when file was created).
176
- * This supports files from multiple parallel/sequential executions.
177
- */
178
- const fileRefs: t.CodeEnvFile[] = codeSession.files.map((file) => ({
179
- session_id: file.session_id ?? codeSession.session_id,
180
- id: file.id,
181
- name: file.name,
182
- }));
183
- /** Inject latest session_id and files - bypasses Zod, reaches config.toolCall */
175
+ if (codeSession?.session_id != null && codeSession.session_id !== '') {
184
176
  invokeParams = {
185
177
  ...invokeParams,
186
178
  session_id: codeSession.session_id,
187
- _injected_files: fileRefs,
188
179
  };
180
+
181
+ if (codeSession.files != null && codeSession.files.length > 0) {
182
+ const fileRefs: t.CodeEnvFile[] = codeSession.files.map((file) => ({
183
+ session_id: file.session_id ?? codeSession.session_id,
184
+ id: file.id,
185
+ name: file.name,
186
+ }));
187
+ invokeParams._injected_files = fileRefs;
188
+ }
189
189
  }
190
190
  }
191
191
 
@@ -256,6 +256,100 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
256
256
  }
257
257
  }
258
258
 
259
+ /**
260
+ * Builds code session context for injection into event-driven tool calls.
261
+ * Mirrors the session injection logic in runTool() for direct execution.
262
+ */
263
+ private getCodeSessionContext(): t.ToolCallRequest['codeSessionContext'] {
264
+ if (!this.sessions) {
265
+ return undefined;
266
+ }
267
+
268
+ const codeSession = this.sessions.get(Constants.EXECUTE_CODE) as
269
+ | t.CodeSessionContext
270
+ | undefined;
271
+ if (!codeSession) {
272
+ return undefined;
273
+ }
274
+
275
+ const context: NonNullable<t.ToolCallRequest['codeSessionContext']> = {
276
+ session_id: codeSession.session_id,
277
+ };
278
+
279
+ if (codeSession.files && codeSession.files.length > 0) {
280
+ context.files = codeSession.files.map((file) => ({
281
+ session_id: file.session_id ?? codeSession.session_id,
282
+ id: file.id,
283
+ name: file.name,
284
+ }));
285
+ }
286
+
287
+ return context;
288
+ }
289
+
290
+ /**
291
+ * Extracts code execution session context from tool results and stores in Graph.sessions.
292
+ * Mirrors the session storage logic in Graph.handleToolCallCompleted() for direct execution.
293
+ */
294
+ private storeCodeSessionFromResults(
295
+ results: t.ToolExecuteResult[],
296
+ requests: t.ToolCallRequest[]
297
+ ): void {
298
+ if (!this.sessions) {
299
+ return;
300
+ }
301
+
302
+ for (let i = 0; i < results.length; i++) {
303
+ const result = results[i];
304
+ if (result.status !== 'success' || result.artifact == null) {
305
+ continue;
306
+ }
307
+
308
+ const request = requests.find((r) => r.id === result.toolCallId);
309
+ if (
310
+ request?.name !== Constants.EXECUTE_CODE &&
311
+ request?.name !== Constants.PROGRAMMATIC_TOOL_CALLING
312
+ ) {
313
+ continue;
314
+ }
315
+
316
+ const artifact = result.artifact as t.CodeExecutionArtifact | undefined;
317
+ if (artifact?.session_id == null || artifact.session_id === '') {
318
+ continue;
319
+ }
320
+
321
+ const newFiles = artifact.files ?? [];
322
+ const existingSession = this.sessions.get(Constants.EXECUTE_CODE) as
323
+ | t.CodeSessionContext
324
+ | undefined;
325
+ const existingFiles = existingSession?.files ?? [];
326
+
327
+ if (newFiles.length > 0) {
328
+ const filesWithSession: t.FileRefs = newFiles.map((file) => ({
329
+ ...file,
330
+ session_id: artifact.session_id,
331
+ }));
332
+
333
+ const newFileNames = new Set(filesWithSession.map((f) => f.name));
334
+ const filteredExisting = existingFiles.filter(
335
+ (f) => !newFileNames.has(f.name)
336
+ );
337
+
338
+ this.sessions.set(Constants.EXECUTE_CODE, {
339
+ session_id: artifact.session_id,
340
+ files: [...filteredExisting, ...filesWithSession],
341
+ lastUpdated: Date.now(),
342
+ });
343
+ } else {
344
+ this.sessions.set(Constants.EXECUTE_CODE, {
345
+ session_id: artifact.session_id,
346
+ files: existingFiles,
347
+ lastUpdated: Date.now(),
348
+ });
349
+ }
350
+ }
351
+ }
352
+
259
353
  /**
260
354
  * Dispatches tool calls to the host via ON_TOOL_EXECUTE event and returns raw ToolMessages.
261
355
  * Core logic for event-driven execution, separated from output shaping.
@@ -267,13 +361,23 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
267
361
  const requests: t.ToolCallRequest[] = toolCalls.map((call) => {
268
362
  const turn = this.toolUsageCount.get(call.name) ?? 0;
269
363
  this.toolUsageCount.set(call.name, turn + 1);
270
- return {
364
+
365
+ const request: t.ToolCallRequest = {
271
366
  id: call.id!,
272
367
  name: call.name,
273
368
  args: call.args as Record<string, unknown>,
274
369
  stepId: this.toolCallStepIds?.get(call.id!),
275
370
  turn,
276
371
  };
372
+
373
+ if (
374
+ call.name === Constants.EXECUTE_CODE ||
375
+ call.name === Constants.PROGRAMMATIC_TOOL_CALLING
376
+ ) {
377
+ request.codeSessionContext = this.getCodeSessionContext();
378
+ }
379
+
380
+ return request;
277
381
  });
278
382
 
279
383
  const results = await new Promise<t.ToolExecuteResult[]>(
@@ -294,6 +398,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
294
398
  }
295
399
  );
296
400
 
401
+ this.storeCodeSessionFromResults(results, requests);
402
+
297
403
  return results.map((result) => {
298
404
  const request = requests.find((r) => r.id === result.toolCallId);
299
405
  const toolName = request?.name ?? 'unknown';
@@ -153,6 +153,11 @@ export type ToolCallRequest = {
153
153
  stepId?: string;
154
154
  /** Usage turn count for this tool */
155
155
  turn?: number;
156
+ /** Code execution session context for session continuity in event-driven mode */
157
+ codeSessionContext?: {
158
+ session_id: string;
159
+ files?: CodeEnvFile[];
160
+ };
156
161
  };
157
162
 
158
163
  /** Batch request containing ALL tool calls for a graph step */
@@ -335,7 +340,7 @@ export type CodeSessionContext = {
335
340
  /** Session ID from the code execution environment */
336
341
  session_id: string;
337
342
  /** Files generated in this session (for context/tracking) */
338
- files: FileRefs;
343
+ files?: FileRefs;
339
344
  /** Timestamp of last update */
340
345
  lastUpdated: number;
341
346
  };