@bian-womp/spark-graph 0.2.17 → 0.2.18

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.
package/lib/cjs/index.cjs CHANGED
@@ -477,23 +477,20 @@ class GraphRuntime {
477
477
  }
478
478
  // Instantiate edges
479
479
  gr.edges = GraphRuntime.buildEdges(def, registry, gr.resolvedByNode);
480
- // After nodes and edges exist, seed registry- and graph-level defaults
480
+ // After nodes and edges exist, seed registry-, dynamic- and graph-level defaults
481
481
  for (const n of def.nodes) {
482
482
  const node = gr.nodes.get(n.nodeId);
483
483
  const desc = registry.nodes.get(n.typeId);
484
484
  if (!node || !desc)
485
485
  continue;
486
- // Resolve registry-level defaults (object or function)
487
- const regDefaults = typeof desc.inputDefaults === "function"
488
- ? desc.inputDefaults({
489
- params: n.params,
490
- environment: gr.environment,
491
- })
492
- : desc.inputDefaults ?? {};
486
+ // Resolve registry-level defaults and dynamic (resolved) defaults
487
+ const regDefaults = desc.inputDefaults ?? {};
488
+ const dynDefaults = gr.resolvedByNode.get(n.nodeId)?.inputDefaults ?? {};
493
489
  const graphDefaults = n.initialInputs ?? {};
494
- // Apply precedence: graph-level overrides registry-level
490
+ // Apply precedence: graph-level overrides dynamic, which overrides registry-level
495
491
  const merged = {
496
492
  ...regDefaults,
493
+ ...dynDefaults,
497
494
  ...graphDefaults,
498
495
  };
499
496
  for (const [handle, value] of Object.entries(merged)) {
@@ -915,10 +912,12 @@ class GraphRuntime {
915
912
  continue;
916
913
  const overrideInputs = n.resolvedHandles?.inputs;
917
914
  const overrideOutputs = n.resolvedHandles?.outputs;
915
+ const overrideDefaults = n.resolvedHandles?.inputDefaults;
918
916
  // Merge base with overrides (allow partial resolvedHandles)
919
917
  const inputs = { ...desc.inputs, ...overrideInputs };
920
918
  const outputs = { ...desc.outputs, ...overrideOutputs };
921
- out.set(n.nodeId, { inputs, outputs });
919
+ const inputDefaults = { ...desc.inputDefaults, ...overrideDefaults };
920
+ out.set(n.nodeId, { inputs, outputs, inputDefaults });
922
921
  }
923
922
  return out;
924
923
  }
@@ -1326,15 +1325,12 @@ class GraphRuntime {
1326
1325
  if (defNode) {
1327
1326
  const desc = registry.nodes.get(defNode.typeId);
1328
1327
  if (desc) {
1329
- const regDefaults = typeof desc.inputDefaults === "function"
1330
- ? desc.inputDefaults({
1331
- params: defNode.params,
1332
- environment: this.environment,
1333
- })
1334
- : desc.inputDefaults ?? {};
1328
+ const regDefaults = desc.inputDefaults ?? {};
1329
+ const dynDefaults = this.resolvedByNode.get(defNode.nodeId)?.inputDefaults ?? {};
1335
1330
  const graphDefaults = defNode.initialInputs ?? {};
1336
1331
  const merged = {
1337
1332
  ...regDefaults,
1333
+ ...dynDefaults,
1338
1334
  ...graphDefaults,
1339
1335
  };
1340
1336
  for (const h of Array.from(prevSet)) {
@@ -1406,6 +1402,34 @@ class GraphRuntime {
1406
1402
  }
1407
1403
  }
1408
1404
  }
1405
+ // Seed defaults for nodes (new or existing) where inputs are still undefined and not inbound
1406
+ for (const n of def.nodes) {
1407
+ const node = this.nodes.get(n.nodeId);
1408
+ const desc = registry.nodes.get(n.typeId);
1409
+ if (!node || !desc)
1410
+ continue;
1411
+ const regDefaults = desc.inputDefaults ?? {};
1412
+ const dynDefaults = this.resolvedByNode.get(n.nodeId)?.inputDefaults ?? {};
1413
+ const graphDefaults = n.initialInputs ?? {};
1414
+ const merged = {
1415
+ ...regDefaults,
1416
+ ...dynDefaults,
1417
+ ...graphDefaults,
1418
+ };
1419
+ const inboundSet = nextInbound.get(n.nodeId) ?? new Set();
1420
+ for (const [handle, value] of Object.entries(merged)) {
1421
+ if (value === undefined)
1422
+ continue;
1423
+ if (inboundSet.has(handle))
1424
+ continue;
1425
+ if (node.inputs[handle] !== undefined)
1426
+ continue;
1427
+ node.inputs[handle] =
1428
+ typeof structuredClone === "function"
1429
+ ? structuredClone(value)
1430
+ : JSON.parse(JSON.stringify(value));
1431
+ }
1432
+ }
1409
1433
  // Prune array bucket contributions for edges that no longer exist
1410
1434
  const validPerTarget = new Map();
1411
1435
  for (const ed of this.edges) {
@@ -2617,6 +2641,30 @@ function setupBasicGraphRegistry() {
2617
2641
  return { Items: Array.from({ length }, (_, i) => ins[`Item${i}`]) };
2618
2642
  },
2619
2643
  });
2644
+ // Decompose array into dynamic item outputs
2645
+ registry.registerNode({
2646
+ id: "base.array.decompose",
2647
+ categoryId: "compute",
2648
+ inputs: { Items: "base.object" },
2649
+ outputs: {},
2650
+ resolveHandles: ({ inputs }) => {
2651
+ const maxLen = 64;
2652
+ const arr = Array.isArray(inputs?.Items) ? inputs?.Items : [];
2653
+ const n = Math.max(0, Math.min(maxLen, arr.length));
2654
+ const dyn = {};
2655
+ for (let i = 0; i < n; i++)
2656
+ dyn[`Item${i}`] = "base.object";
2657
+ return { outputs: dyn };
2658
+ },
2659
+ impl: (ins) => {
2660
+ const arr = Array.isArray(ins.Items) ? ins.Items : [];
2661
+ const out = {};
2662
+ const n = Math.max(0, Math.min(64, arr.length));
2663
+ for (let i = 0; i < n; i++)
2664
+ out[`Item${i}`] = arr[i];
2665
+ return out;
2666
+ },
2667
+ });
2620
2668
  // Select
2621
2669
  registry.registerNode({
2622
2670
  id: "base.select",