diff --git a/modules/workflows/automation2/executors/actionNodeExecutor.py b/modules/workflows/automation2/executors/actionNodeExecutor.py index 7c85a757..0d5134f1 100644 --- a/modules/workflows/automation2/executors/actionNodeExecutor.py +++ b/modules/workflows/automation2/executors/actionNodeExecutor.py @@ -158,19 +158,23 @@ def _applyEmailSearchQuery(params: Dict) -> None: def _wireHandover(nodeDef: Dict, inputSources: Dict, nodeOutputs: Dict, params: Dict) -> None: """Apply wire-handover: extract fields from upstream using INPUT_EXTRACTORS.""" if 0 not in inputSources: + logger.debug("_wireHandover: no port 0 in inputSources=%s", inputSources) return srcId, _ = inputSources[0] upstream = nodeOutputs.get(srcId) if not upstream or not isinstance(upstream, dict): + logger.debug("_wireHandover: upstream for %s is missing or not dict: %s", srcId, type(upstream)) return data = _unwrapTransit(upstream) if not isinstance(data, dict): + logger.debug("_wireHandover: unwrapped data is not dict: %s", type(data)) return inputPorts = nodeDef.get("inputPorts", {}) port0 = inputPorts.get(0, {}) accepts = port0.get("accepts", []) + logger.debug("_wireHandover: srcId=%s accepts=%s upstream_keys=%s params_keys_before=%s", srcId, accepts, list(data.keys()), list(params.keys())) for schemaName in accepts: if schemaName == "Transit": @@ -178,9 +182,15 @@ def _wireHandover(nodeDef: Dict, inputSources: Dict, nodeOutputs: Dict, params: extractor = INPUT_EXTRACTORS.get(schemaName) if extractor: extracted = extractor(data) + logger.debug("_wireHandover: extractor %s returned keys=%s", schemaName, list(extracted.keys()) if extracted else None) if extracted: for k, v in extracted.items(): - params.setdefault(k, v) + existing = params.get(k) + if not existing: + params[k] = v + logger.debug("_wireHandover: set %s (was empty/missing) type=%s len=%s", k, type(v).__name__, len(v) if isinstance(v, (list, str, dict)) else "n/a") + else: + logger.debug("_wireHandover: skip %s (already has value, type=%s)", k, type(existing).__name__) return @@ -222,11 +232,14 @@ class ActionNodeExecutor: # 1. Resolve parameters (DataRef, SystemVar, Static) params = dict(node.get("parameters") or {}) + logger.debug("ActionNodeExecutor node %s raw params keys=%s", nodeId, list(params.keys())) resolvedParams = resolveParameterReferences(params, context.get("nodeOutputs", {})) + logger.debug("ActionNodeExecutor node %s resolved params keys=%s documentList_present=%s documentList_type=%s", nodeId, list(resolvedParams.keys()), "documentList" in resolvedParams, type(resolvedParams.get("documentList")).__name__) # 2. Wire-handover via extractors (fills missing params from upstream) inputSources = context.get("inputSources", {}).get(nodeId, {}) _wireHandover(nodeDef, inputSources, context.get("nodeOutputs", {}), resolvedParams) + logger.debug("ActionNodeExecutor node %s after wireHandover: params keys=%s documentList_present=%s documentList_type=%s", nodeId, list(resolvedParams.keys()), "documentList" in resolvedParams, type(resolvedParams.get("documentList")).__name__) # 3. Apply defaults from parameter definitions for pDef in nodeDef.get("parameters", []): diff --git a/modules/workflows/methods/methodTrustee/actions/processDocuments.py b/modules/workflows/methods/methodTrustee/actions/processDocuments.py index c4bf9df1..0d29c9bd 100644 --- a/modules/workflows/methods/methodTrustee/actions/processDocuments.py +++ b/modules/workflows/methods/methodTrustee/actions/processDocuments.py @@ -213,9 +213,11 @@ def _resolveDocumentList(documentListParam, services) -> List[tuple]: if isinstance(documentListParam, list) and documentListParam: first = documentListParam[0] + logger.debug("_resolveDocumentList: %d items, first type=%s, first keys=%s", len(documentListParam), type(first).__name__, list(first.keys()) if isinstance(first, dict) else "n/a") if isinstance(first, dict) and ("documentData" in first or "documentName" in first): for doc in documentListParam: rawData = doc.get("documentData") + logger.debug("_resolveDocumentList: doc keys=%s documentData type=%s documentData truthy=%s", list(doc.keys()), type(rawData).__name__, bool(rawData)) if not rawData: continue try: @@ -228,6 +230,8 @@ def _resolveDocumentList(documentListParam, services) -> List[tuple]: results.append((data, fileId, fileName, mimeType)) if results: return results + else: + logger.debug("_resolveDocumentList: first item has no documentData/documentName key, falling through to chat fallback") chatService = getattr(services, "chat", None) if not chatService: @@ -268,7 +272,9 @@ async def processDocuments(self, parameters: Dict[str, Any]) -> ActionResult: return ActionResult.isFailure(error="featureInstanceId is required") try: + logger.debug("processDocuments: documentListParam type=%s len=%s", type(documentListParam).__name__, len(documentListParam) if isinstance(documentListParam, (list, str)) else "n/a") extractionDocs = _resolveDocumentList(documentListParam, self.services) + logger.debug("processDocuments: extractionDocs count=%d", len(extractionDocs)) if not extractionDocs: return ActionResult.isFailure(error="No documents found for documentList")