@bian-womp/spark-graph 0.2.34 → 0.2.35

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.
@@ -31,6 +31,7 @@ export declare class GraphRuntime {
31
31
  private static buildEdgeConverters;
32
32
  private scheduleInputsChanged;
33
33
  private allInboundHaveValue;
34
+ private getEffectiveInputs;
34
35
  private invalidateDownstream;
35
36
  private propagate;
36
37
  private static computeResolvedHandleMap;
@@ -1 +1 @@
1
- {"version":3,"file":"GraphRuntime.d.ts","sourceRoot":"","sources":["../../../../src/runtime/GraphRuntime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GraphRuntime.d.ts","sourceRoot":"","sources":["../../../../src/runtime/GraphRuntime.ts"],"names":[],"mappings":"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"}
package/lib/esm/index.js CHANGED
@@ -483,41 +483,12 @@ class GraphRuntime {
483
483
  queued: 0,
484
484
  progress: 0,
485
485
  },
486
+ initialInputs: n.initialInputs ?? {},
486
487
  };
487
488
  gr.nodes.set(n.nodeId, rn);
488
489
  }
489
490
  // Instantiate edges
490
491
  gr.edges = GraphRuntime.buildEdges(def, registry, gr.resolvedByNode);
491
- // After nodes and edges exist, seed registry-, dynamic- and graph-level defaults
492
- for (const n of def.nodes) {
493
- const node = gr.nodes.get(n.nodeId);
494
- const desc = registry.nodes.get(n.typeId);
495
- if (!node || !desc)
496
- continue;
497
- // Resolve registry-level defaults and dynamic (resolved) defaults
498
- const regDefaults = desc.inputDefaults ?? {};
499
- const dynDefaults = gr.resolvedByNode.get(n.nodeId)?.inputDefaults ?? {};
500
- const graphDefaults = n.initialInputs ?? {};
501
- // Apply precedence: graph-level overrides dynamic, which overrides registry-level
502
- const merged = {
503
- ...regDefaults,
504
- ...dynDefaults,
505
- ...graphDefaults,
506
- };
507
- for (const [handle, value] of Object.entries(merged)) {
508
- // Only seed if input has no inbound wiring
509
- const hasInbound = gr.edges.some((e) => e.target.nodeId === n.nodeId && e.target.handle === handle);
510
- if (hasInbound)
511
- continue;
512
- if (value === undefined)
513
- continue;
514
- // Clone to avoid accidental shared references
515
- node.inputs[handle] =
516
- typeof structuredClone === "function"
517
- ? structuredClone(value)
518
- : JSON.parse(JSON.stringify(value));
519
- }
520
- }
521
492
  // Schedule async recompute only for nodes that indicated Promise-based resolveHandles
522
493
  for (const nodeId of initial.pending)
523
494
  gr.scheduleRecomputeHandles(nodeId);
@@ -641,6 +612,8 @@ class GraphRuntime {
641
612
  return;
642
613
  const now = Date.now();
643
614
  const policy = node.policy ?? {};
615
+ // Compute effective inputs (real inputs + defaults) for this execution
616
+ const effectiveInputs = this.getEffectiveInputs(nodeId);
644
617
  if (policy.debounceMs &&
645
618
  node.lastScheduledAt &&
646
619
  now - node.lastScheduledAt < policy.debounceMs) {
@@ -648,7 +621,7 @@ class GraphRuntime {
648
621
  node.queue.splice(0, node.queue.length);
649
622
  node.runSeq += 1;
650
623
  const rid = `${nodeId}:${node.runSeq}:${now}`;
651
- node.queue.push({ runId: rid, inputs: { ...node.inputs } });
624
+ node.queue.push({ runId: rid, inputs: effectiveInputs });
652
625
  return;
653
626
  }
654
627
  node.lastScheduledAt = now;
@@ -754,7 +727,7 @@ class GraphRuntime {
754
727
  return;
755
728
  if (mode === "queue") {
756
729
  const maxQ = policy.maxQueue ?? 8;
757
- node.queue.push({ runId: rid, inputs: { ...node.inputs } });
730
+ node.queue.push({ runId: rid, inputs: effectiveInputs });
758
731
  if (node.queue.length > maxQ)
759
732
  node.queue.shift();
760
733
  const processNext = () => {
@@ -773,7 +746,7 @@ class GraphRuntime {
773
746
  return;
774
747
  }
775
748
  // switch or merge
776
- startRun(rid, { ...node.inputs });
749
+ startRun(rid, effectiveInputs);
777
750
  }
778
751
  // Returns true if all inbound handles for the node currently have a value
779
752
  allInboundHaveValue(nodeId) {
@@ -789,6 +762,62 @@ class GraphRuntime {
789
762
  }
790
763
  return true;
791
764
  }
765
+ // Computes effective inputs for a node by merging real inputs with defaults
766
+ // Defaults are applied only for unbound handles that have no explicit value
767
+ // This method does NOT mutate node.inputs - defaults remain virtual
768
+ // Dynamic handles (from resolveHandles) do NOT get defaults applied - they are metadata-only
769
+ getEffectiveInputs(nodeId) {
770
+ const node = this.nodes.get(nodeId);
771
+ if (!node)
772
+ return {};
773
+ const registry = this.registry;
774
+ if (!registry)
775
+ return {};
776
+ const desc = registry.nodes.get(node.typeId);
777
+ if (!desc)
778
+ return {};
779
+ const resolved = this.resolvedByNode.get(nodeId);
780
+ const regDefaults = desc.inputDefaults ?? {};
781
+ const dynDefaults = resolved?.inputDefaults ?? {};
782
+ const graphDefaults = node.initialInputs ?? {};
783
+ // Identify which handles are dynamically resolved (not in registry statics)
784
+ // Dynamic handles are metadata-only and should not receive defaults in execution
785
+ const staticHandles = new Set(Object.keys(desc.inputs ?? {}));
786
+ const dynamicHandles = new Set(Object.keys(resolved?.inputs ?? {}).filter((h) => !staticHandles.has(h)));
787
+ // Precedence: graph > dynamic > registry
788
+ const mergedDefaults = {
789
+ ...regDefaults,
790
+ ...dynDefaults,
791
+ ...graphDefaults,
792
+ };
793
+ // Start with real inputs only (no defaults)
794
+ const effective = { ...node.inputs };
795
+ // Build set of inbound handles (wired inputs)
796
+ const inbound = new Set(this.edges
797
+ .filter((e) => e.target.nodeId === nodeId)
798
+ .map((e) => e.target.handle));
799
+ // Apply defaults only for:
800
+ // 1. Unbound handles that have no explicit value
801
+ // 2. Static handles (not dynamically resolved)
802
+ // This prevents dynamic handles (like geo:*) from getting defaults in execution
803
+ // Dynamic handles are metadata-only for UI display, not execution values
804
+ for (const [handle, defaultValue] of Object.entries(mergedDefaults)) {
805
+ if (defaultValue === undefined)
806
+ continue;
807
+ if (inbound.has(handle))
808
+ continue; // Don't override wired inputs
809
+ if (effective[handle] !== undefined)
810
+ continue; // Already has value
811
+ if (dynamicHandles.has(handle))
812
+ continue; // Skip defaults for dynamic handles
813
+ // Clone to avoid shared references
814
+ effective[handle] =
815
+ typeof structuredClone === "function"
816
+ ? structuredClone(defaultValue)
817
+ : JSON.parse(JSON.stringify(defaultValue));
818
+ }
819
+ return effective;
820
+ }
792
821
  invalidateDownstream(nodeId) {
793
822
  // Notifies dependents; for now we propagate current outputs
794
823
  for (const e of this.edges.filter((e) => e.source.nodeId === nodeId)) {
@@ -1090,12 +1119,13 @@ class GraphRuntime {
1090
1119
  // call onActivated for nodes that implement it
1091
1120
  for (const node of this.nodes.values()) {
1092
1121
  const ctrl = new AbortController();
1122
+ const effectiveInputs = this.getEffectiveInputs(node.nodeId);
1093
1123
  const ctx = {
1094
1124
  state: node.state,
1095
1125
  setState: (next) => Object.assign(node.state, next),
1096
1126
  emit: (handle, value) => this.propagate(node.nodeId, handle, value),
1097
1127
  invalidateDownstream: () => this.invalidateDownstream(node.nodeId),
1098
- getInput: (handle) => node.inputs[handle],
1128
+ getInput: (handle) => effectiveInputs[handle],
1099
1129
  environment: this.environment,
1100
1130
  runId: `${node.nodeId}:activation`,
1101
1131
  abortSignal: ctrl.signal,
@@ -1123,12 +1153,13 @@ class GraphRuntime {
1123
1153
  if (!node)
1124
1154
  return;
1125
1155
  const ctrl = new AbortController();
1156
+ const effectiveInputs = this.getEffectiveInputs(nodeId);
1126
1157
  const ctx = {
1127
1158
  state: node.state,
1128
1159
  setState: (next) => Object.assign(node.state, next),
1129
1160
  emit: (handle, value) => this.propagate(nodeId, handle, value),
1130
1161
  invalidateDownstream: () => this.invalidateDownstream(nodeId),
1131
- getInput: (handle) => node.inputs[handle],
1162
+ getInput: (handle) => effectiveInputs[handle],
1132
1163
  environment: this.environment,
1133
1164
  runId: `${nodeId}:external`,
1134
1165
  abortSignal: ctrl.signal,
@@ -1385,16 +1416,18 @@ class GraphRuntime {
1385
1416
  queued: 0,
1386
1417
  progress: 0,
1387
1418
  },
1419
+ initialInputs: n.initialInputs ?? {},
1388
1420
  };
1389
1421
  this.nodes.set(n.nodeId, rn);
1390
1422
  // Activate new node
1391
1423
  const ctrl = new AbortController();
1424
+ const effectiveInputs = this.getEffectiveInputs(rn.nodeId);
1392
1425
  const ctx = {
1393
1426
  state: rn.state,
1394
1427
  setState: (next) => Object.assign(rn.state, next),
1395
1428
  emit: (handle, value) => this.propagate(rn.nodeId, handle, value),
1396
1429
  invalidateDownstream: () => this.invalidateDownstream(rn.nodeId),
1397
- getInput: (handle) => rn.inputs[handle],
1430
+ getInput: (handle) => effectiveInputs[handle],
1398
1431
  environment: this.environment,
1399
1432
  runId: `${rn.nodeId}:activation`,
1400
1433
  abortSignal: ctrl.signal,
@@ -1407,8 +1440,9 @@ class GraphRuntime {
1407
1440
  rn.runtime.onActivated?.(ctx);
1408
1441
  }
1409
1442
  else {
1410
- // update params/policy
1443
+ // update params/policy and initialInputs
1411
1444
  existing.params = n.params;
1445
+ existing.initialInputs = n.initialInputs ?? {};
1412
1446
  if (!existing.stats) {
1413
1447
  existing.stats = {
1414
1448
  runs: 0,
@@ -1462,32 +1496,7 @@ class GraphRuntime {
1462
1496
  }
1463
1497
  }
1464
1498
  }
1465
- // If input lost inbound, try to re-seed from defaults
1466
1499
  if (changed) {
1467
- const defNode = def.nodes.find((n) => n.nodeId === nodeId);
1468
- if (defNode) {
1469
- const desc = registry.nodes.get(defNode.typeId);
1470
- if (desc) {
1471
- const regDefaults = desc.inputDefaults ?? {};
1472
- const dynDefaults = this.resolvedByNode.get(defNode.nodeId)?.inputDefaults ?? {};
1473
- const graphDefaults = defNode.initialInputs ?? {};
1474
- const merged = {
1475
- ...regDefaults,
1476
- ...dynDefaults,
1477
- ...graphDefaults,
1478
- };
1479
- for (const h of Array.from(prevSet)) {
1480
- if (!currSet.has(h) && node.inputs[h] === undefined) {
1481
- const v = merged[h];
1482
- if (v !== undefined)
1483
- node.inputs[h] =
1484
- typeof structuredClone === "function"
1485
- ? structuredClone(v)
1486
- : JSON.parse(JSON.stringify(v));
1487
- }
1488
- }
1489
- }
1490
- }
1491
1500
  // Clear buckets for handles that lost inbound
1492
1501
  const bucketsForNode = this.arrayInputBuckets.get(nodeId);
1493
1502
  if (bucketsForNode) {
@@ -1545,34 +1554,6 @@ class GraphRuntime {
1545
1554
  }
1546
1555
  }
1547
1556
  }
1548
- // Seed defaults for nodes (new or existing) where inputs are still undefined and not inbound
1549
- for (const n of def.nodes) {
1550
- const node = this.nodes.get(n.nodeId);
1551
- const desc = registry.nodes.get(n.typeId);
1552
- if (!node || !desc)
1553
- continue;
1554
- const regDefaults = desc.inputDefaults ?? {};
1555
- const dynDefaults = this.resolvedByNode.get(n.nodeId)?.inputDefaults ?? {};
1556
- const graphDefaults = n.initialInputs ?? {};
1557
- const merged = {
1558
- ...regDefaults,
1559
- ...dynDefaults,
1560
- ...graphDefaults,
1561
- };
1562
- const inboundSet = nextInbound.get(n.nodeId) ?? new Set();
1563
- for (const [handle, value] of Object.entries(merged)) {
1564
- if (value === undefined)
1565
- continue;
1566
- if (inboundSet.has(handle))
1567
- continue;
1568
- if (node.inputs[handle] !== undefined)
1569
- continue;
1570
- node.inputs[handle] =
1571
- typeof structuredClone === "function"
1572
- ? structuredClone(value)
1573
- : JSON.parse(JSON.stringify(value));
1574
- }
1575
- }
1576
1557
  // Prune array bucket contributions for edges that no longer exist
1577
1558
  const validPerTarget = new Map();
1578
1559
  for (const ed of this.edges) {
@@ -1651,30 +1632,6 @@ class GraphRuntime {
1651
1632
  return;
1652
1633
  this.resolvedByNode.set(nodeId, next);
1653
1634
  this.updateNodeHandles(nodeId, next, registry);
1654
- // Seed defaults for newly introduced inputs that are not inbound
1655
- const inbound = this.edges
1656
- .filter((e) => e.target.nodeId === nodeId)
1657
- .map((e) => e.target.handle);
1658
- for (const [handle, value] of Object.entries(inputDefaults)) {
1659
- if (value === undefined)
1660
- continue;
1661
- if (inbound.includes(handle))
1662
- continue;
1663
- if (node.inputs[handle] === undefined) {
1664
- node.inputs[handle] =
1665
- typeof structuredClone === "function"
1666
- ? structuredClone(value)
1667
- : JSON.parse(JSON.stringify(value));
1668
- // Emit input value event for seeded defaults
1669
- this.emit("value", {
1670
- nodeId,
1671
- handle,
1672
- value: node.inputs[handle],
1673
- io: "input",
1674
- runtimeTypeId: getTypedOutputTypeId(node.inputs[handle]),
1675
- });
1676
- }
1677
- }
1678
1635
  // Notify graph updated for UI parity
1679
1636
  this.emit("invalidate", { reason: "graph-updated" });
1680
1637
  }