@bian-womp/spark-graph 0.1.28 → 0.1.30

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.
@@ -15,6 +15,7 @@ export declare class GraphRuntime {
15
15
  private listeners;
16
16
  private environment;
17
17
  private paused;
18
+ private valuesEqual;
18
19
  static create(def: GraphDefinition, registry: Registry, opts?: {
19
20
  environment?: Record<string, unknown>;
20
21
  }): GraphRuntime;
@@ -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":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACb,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EACV,eAAe,EAIf,gBAAgB,EAGjB,MAAM,eAAe,CAAC;AAQvB,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,gBAAgB,IAAI,CAC7D,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,KAClB,IAAI,CAAC;AAEV,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,YAAY,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1E,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,YAAY,CAAC;CACrB;AAkCD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAuC;IACpD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,SAAS,CAGb;IACJ,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,MAAM,CAAS;IAGvB,OAAO,CAAC,WAAW;IAanB,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,QAAQ,EAClB,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAC/C,YAAY;IA8Hf,EAAE,CAAC,CAAC,SAAS,gBAAgB,EAC3B,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAC/B,MAAM,IAAI;IAOb,OAAO,CAAC,IAAI;IAQZ,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAI9D,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA0BhE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAKlD,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAqElC,OAAO,CAAC,qBAAqB;IAsJ7B,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,SAAS;IAgHjB,OAAO,CAAC,iBAAiB;IAQzB,MAAM,IAAI,IAAI;IA8Bd,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAqBrD,OAAO,IAAI,IAAI;IAcf,UAAU,IAAI,MAAM,EAAE;IAKtB,WAAW,CAAC,MAAM,EAAE,MAAM,GACtB;QACE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,KAAK,CAAC,EAAE,gBAAgB,CAAC;KAC1B,GACD,SAAS;IAYb,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIzC,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI5C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB/B,KAAK,IAAI,IAAI;IAIb,MAAM,IAAI,IAAI;IAId,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAInD,8BAA8B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKpD,MAAM,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI;CAkOvD"}
package/lib/esm/index.js CHANGED
@@ -407,6 +407,22 @@ class GraphRuntime {
407
407
  this.environment = {};
408
408
  this.paused = false;
409
409
  }
410
+ // Shallow/deep-ish equality to avoid unnecessary runs on identical values
411
+ valuesEqual(a, b) {
412
+ if (a === b)
413
+ return true;
414
+ if (typeof a !== typeof b)
415
+ return false;
416
+ if (a && b && typeof a === "object") {
417
+ try {
418
+ return JSON.stringify(a) === JSON.stringify(b);
419
+ }
420
+ catch {
421
+ return false;
422
+ }
423
+ }
424
+ return false;
425
+ }
410
426
  static create(def, registry, opts) {
411
427
  const gr = new GraphRuntime();
412
428
  gr.environment = opts?.environment ?? {};
@@ -543,17 +559,23 @@ class GraphRuntime {
543
559
  const node = this.nodes.get(nodeId);
544
560
  if (!node)
545
561
  throw new Error(`Node not found: ${nodeId}`);
562
+ let anyChanged = false;
546
563
  for (const [handle, value] of Object.entries(inputs)) {
547
564
  const hasInbound = this.edges.some((e) => e.target.nodeId === nodeId && e.target.handle === handle);
548
565
  if (hasInbound)
549
566
  continue;
550
- node.inputs[handle] = value;
551
- // Emit value event for input updates
552
- this.emit("value", { nodeId, handle, value, io: "input" });
567
+ const prev = node.inputs[handle];
568
+ const same = this.valuesEqual(prev, value);
569
+ if (!same) {
570
+ node.inputs[handle] = value;
571
+ // Emit value event for input updates
572
+ this.emit("value", { nodeId, handle, value, io: "input" });
573
+ anyChanged = true;
574
+ }
553
575
  }
554
576
  if (!this.paused) {
555
577
  // Only schedule if all inbound inputs are present (or there are none)
556
- if (this.allInboundHaveValue(nodeId))
578
+ if (anyChanged && this.allInboundHaveValue(nodeId))
557
579
  this.scheduleInputsChanged(nodeId);
558
580
  }
559
581
  }
@@ -810,17 +832,21 @@ class GraphRuntime {
810
832
  const dstNode = this.nodes.get(e.target.nodeId);
811
833
  if (!dstNode)
812
834
  return;
813
- dstNode.inputs[e.target.handle] = v;
814
- // Emit value event for input updates
815
- this.emit("value", {
816
- nodeId: e.target.nodeId,
817
- handle: e.target.handle,
818
- value: v,
819
- io: "input",
820
- runtimeTypeId: getTypedOutputTypeId(v),
821
- });
822
- if (!this.paused && this.allInboundHaveValue(e.target.nodeId))
823
- this.scheduleInputsChanged(e.target.nodeId);
835
+ const prev = dstNode.inputs[e.target.handle];
836
+ const same = this.valuesEqual(prev, v);
837
+ if (!same) {
838
+ dstNode.inputs[e.target.handle] = v;
839
+ // Emit value event for input updates
840
+ this.emit("value", {
841
+ nodeId: e.target.nodeId,
842
+ handle: e.target.handle,
843
+ value: v,
844
+ io: "input",
845
+ runtimeTypeId: getTypedOutputTypeId(v),
846
+ });
847
+ if (!this.paused && this.allInboundHaveValue(e.target.nodeId))
848
+ this.scheduleInputsChanged(e.target.nodeId);
849
+ }
824
850
  };
825
851
  if (e.convertAsync) {
826
852
  // emit edge-start before launching async conversion
@@ -1100,6 +1126,13 @@ class GraphRuntime {
1100
1126
  set.add(e.target.handle);
1101
1127
  prevInbound.set(e.target.nodeId, set);
1102
1128
  }
1129
+ // Capture previous outgoing map before rebuilding edges
1130
+ const prevOutgoing = new Map();
1131
+ for (const e of this.edges) {
1132
+ const set = prevOutgoing.get(e.source.nodeId) ?? new Set();
1133
+ set.add(e.source.handle);
1134
+ prevOutgoing.set(e.source.nodeId, set);
1135
+ }
1103
1136
  // Rebuild edges mapping with coercions
1104
1137
  this.edges = def.edges.map((e) => {
1105
1138
  const srcNode = def.nodes.find((nn) => nn.nodeId === e.source.nodeId);
@@ -1189,9 +1222,34 @@ class GraphRuntime {
1189
1222
  this.scheduleInputsChanged(nodeId);
1190
1223
  }
1191
1224
  }
1192
- // Re-emit existing outputs to populate new edges
1193
- for (const nodeId of this.nodes.keys()) {
1194
- this.reemitNodeOutputs(nodeId);
1225
+ // Re-emit outputs only for sources whose outgoing edge set changed
1226
+ const nextOutgoing = new Map();
1227
+ for (const e of this.edges) {
1228
+ const set = nextOutgoing.get(e.source.nodeId) ?? new Set();
1229
+ set.add(e.source.handle);
1230
+ nextOutgoing.set(e.source.nodeId, set);
1231
+ }
1232
+ const setsEqual = (a, b) => {
1233
+ if (!a && !b)
1234
+ return true;
1235
+ if (!a || !b)
1236
+ return false;
1237
+ if (a.size !== b.size)
1238
+ return false;
1239
+ for (const v of a)
1240
+ if (!b.has(v))
1241
+ return false;
1242
+ return true;
1243
+ };
1244
+ const reemitCandidates = new Set([
1245
+ ...Array.from(prevOutgoing.keys()),
1246
+ ...Array.from(nextOutgoing.keys()),
1247
+ ]);
1248
+ for (const nodeId of reemitCandidates) {
1249
+ const prev = prevOutgoing.get(nodeId);
1250
+ const next = nextOutgoing.get(nodeId);
1251
+ if (!setsEqual(prev, next))
1252
+ this.reemitNodeOutputs(nodeId);
1195
1253
  }
1196
1254
  }
1197
1255
  }