Explorar el Código

docs: Merge selects its arrays by path, so it works after any node

fszontagh hace 1 mes
padre
commit
3c177ea54e
Se han modificado 1 ficheros con 34 adiciones y 13 borrados
  1. 34 13
      docs/superpowers/plans/2026-08-04-tier-1-nodes.md

+ 34 - 13
docs/superpowers/plans/2026-08-04-tier-1-nodes.md

@@ -1648,6 +1648,16 @@ const configSchema = {
             type: 'string',
             title: 'Key Field',
             description: 'Field to match on, for combine-by-key'
+        },
+        path1: {
+            type: 'string',
+            title: 'Path In Input 1',
+            description: 'Dotted path to the array inside input 1. Leave empty to use the input as it arrives'
+        },
+        path2: {
+            type: 'string',
+            title: 'Path In Input 2',
+            description: 'Dotted path to the array inside input 2. Leave empty to use the input as it arrives'
         }
     }
 };
@@ -1673,10 +1683,17 @@ function asArray(value) {
     return Array.isArray(value) ? value : [value];
 }
 
+function selectInput(value, path) {
+    if (!path) {
+        return value;
+    }
+    return smartbotic.utils.getFieldValue(value, path);
+}
+
 async function execute(config, input, context) {
     const mode = config.mode || 'append';
-    const first = input ? input.input1 : undefined;
-    const second = input ? input.input2 : undefined;
+    const first = selectInput(input ? input.input1 : undefined, config.path1);
+    const second = selectInput(input ? input.input2 : undefined, config.path2);
 
     if (mode === 'choose-first') {
         const chosen = first !== undefined && first !== null ? first : second;
@@ -1742,20 +1759,14 @@ Two independent fixture branches landing on the two named inputs, combined on `i
      "config": {"code": "return [{id: 1, name: 'one'}, {id: 2, name: 'two'}];"}},
     {"id": "b", "name": "BranchB", "type": "code", "position": {"x": 100, "y": 100},
      "config": {"code": "return [{id: 2, extra: 'from-b'}, {id: 3, name: 'three'}];"}},
-    {"id": "sa", "name": "ShapeA", "type": "code", "position": {"x": -100, "y": 180},
-     "config": {"code": "return input.data.result;"}},
-    {"id": "sb", "name": "ShapeB", "type": "code", "position": {"x": 100, "y": 180},
-     "config": {"code": "return input.data.result;"}},
-    {"id": "m", "name": "Merge", "type": "merge", "position": {"x": 0, "y": 280},
-     "config": {"mode": "combine-by-key", "key": "id"}}
+    {"id": "m", "name": "Merge", "type": "merge", "position": {"x": 0, "y": 220},
+     "config": {"mode": "combine-by-key", "key": "id", "path1": "result", "path2": "result"}}
   ],
   "connections": [
     {"sourceNodeId": "n1", "sourceOutput": "main", "targetNodeId": "a", "targetInput": "data"},
     {"sourceNodeId": "n1", "sourceOutput": "main", "targetNodeId": "b", "targetInput": "data"},
-    {"sourceNodeId": "a", "sourceOutput": "main", "targetNodeId": "sa", "targetInput": "data"},
-    {"sourceNodeId": "b", "sourceOutput": "main", "targetNodeId": "sb", "targetInput": "data"},
-    {"sourceNodeId": "sa", "sourceOutput": "main", "targetNodeId": "m", "targetInput": "input1"},
-    {"sourceNodeId": "sb", "sourceOutput": "main", "targetNodeId": "m", "targetInput": "input2"}
+    {"sourceNodeId": "a", "sourceOutput": "main", "targetNodeId": "m", "targetInput": "input1"},
+    {"sourceNodeId": "b", "sourceOutput": "main", "targetNodeId": "m", "targetInput": "input2"}
   ],
   "expect": {
     "m": {"status": "completed", "output": {"count": 3}}
@@ -1763,7 +1774,17 @@ Two independent fixture branches landing on the two named inputs, combined on `i
 }
 ```
 
-The `ShapeA`/`ShapeB` nodes exist because the `code` node wraps its return in `{result, executionTime}`; they unwrap it so Merge receives bare arrays.
+No intermediate unwrapping nodes: a connection from a `main` port delivers the
+source node's whole output object (`workflow_engine.cpp:1248`), and the `code`
+node wraps its return as `{result, executionTime}`. So Merge receives those
+wrapper objects and `path1`/`path2` select the arrays inside them. Trying to
+unwrap with an intermediate `code` node does not work - that node re-wraps its
+own return on the way out.
+
+A connection from a *named* port behaves differently: the engine reads
+`output[portName]` directly (`workflow_engine.cpp:1242`), so Filter's `kept`
+port hands Merge a bare array and needs no path at all. Both routes are
+supported, which is why the paths are optional.
 
 - [ ] **Step 3: Run it**