# Copyright (c) 2025 Patrick Motsch # I/O node executor - delegates to ActionExecutor. import logging from typing import Dict, Any logger = logging.getLogger(__name__) class IOExecutor: """Execute I/O nodes by calling ActionExecutor.executeAction(method, action, params).""" def __init__(self, services: Any): self.services = services async def execute( self, node: Dict[str, Any], context: Dict[str, Any], ) -> Any: from modules.workflows.processing.core.actionExecutor import ActionExecutor nodeType = node.get("type", "") if not nodeType.startswith("io."): return None parts = nodeType.split(".", 2) if len(parts) < 3: return None _, methodName, actionName = parts nodeOutputs = context.get("nodeOutputs", {}) params = dict(node.get("parameters") or {}) from modules.workflows.automation2.graphUtils import resolveParameterReferences resolvedParams = resolveParameterReferences(params, nodeOutputs) nodeId = node.get("id", "") inputSources = context.get("inputSources", {}).get(nodeId, {}) if 0 in inputSources: srcId, _ = inputSources[0] inp = nodeOutputs.get(srcId) if isinstance(inp, dict): resolvedParams.setdefault("documentList", inp.get("documents", inp.get("documentList", []))) elif inp is not None: resolvedParams.setdefault("input", inp) executor = ActionExecutor(self.services) result = await executor.executeAction(methodName, actionName, resolvedParams) return { "success": result.success, "error": result.error, "documents": [d.model_dump() if hasattr(d, "model_dump") else d for d in (result.documents or [])], "data": result.model_dump() if hasattr(result, "model_dump") else {"success": result.success, "error": result.error}, }