@bian-womp/spark-graph 0.3.86 → 0.3.88

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.
Files changed (31) hide show
  1. package/lib/cjs/index.cjs +55 -75
  2. package/lib/cjs/index.cjs.map +1 -1
  3. package/lib/cjs/src/core/types.d.ts +0 -1
  4. package/lib/cjs/src/core/types.d.ts.map +1 -1
  5. package/lib/cjs/src/runtime/Engine.d.ts +1 -3
  6. package/lib/cjs/src/runtime/Engine.d.ts.map +1 -1
  7. package/lib/cjs/src/runtime/GraphRuntime.d.ts +4 -1
  8. package/lib/cjs/src/runtime/GraphRuntime.d.ts.map +1 -1
  9. package/lib/cjs/src/runtime/LocalEngine.d.ts +1 -5
  10. package/lib/cjs/src/runtime/LocalEngine.d.ts.map +1 -1
  11. package/lib/cjs/src/runtime/components/EdgePropagator.d.ts +0 -4
  12. package/lib/cjs/src/runtime/components/EdgePropagator.d.ts.map +1 -1
  13. package/lib/cjs/src/runtime/components/NodeExecutor.d.ts.map +1 -1
  14. package/lib/cjs/src/runtime/components/RunContextManager.d.ts +0 -2
  15. package/lib/cjs/src/runtime/components/RunContextManager.d.ts.map +1 -1
  16. package/lib/esm/index.js +55 -75
  17. package/lib/esm/index.js.map +1 -1
  18. package/lib/esm/src/core/types.d.ts +0 -1
  19. package/lib/esm/src/core/types.d.ts.map +1 -1
  20. package/lib/esm/src/runtime/Engine.d.ts +1 -3
  21. package/lib/esm/src/runtime/Engine.d.ts.map +1 -1
  22. package/lib/esm/src/runtime/GraphRuntime.d.ts +4 -1
  23. package/lib/esm/src/runtime/GraphRuntime.d.ts.map +1 -1
  24. package/lib/esm/src/runtime/LocalEngine.d.ts +1 -5
  25. package/lib/esm/src/runtime/LocalEngine.d.ts.map +1 -1
  26. package/lib/esm/src/runtime/components/EdgePropagator.d.ts +0 -4
  27. package/lib/esm/src/runtime/components/EdgePropagator.d.ts.map +1 -1
  28. package/lib/esm/src/runtime/components/NodeExecutor.d.ts.map +1 -1
  29. package/lib/esm/src/runtime/components/RunContextManager.d.ts +0 -2
  30. package/lib/esm/src/runtime/components/RunContextManager.d.ts.map +1 -1
  31. package/package.json +2 -2
package/lib/cjs/index.cjs CHANGED
@@ -1884,7 +1884,6 @@ class RunContextManager {
1884
1884
  pendingEdges: 0,
1885
1885
  pendingResolvers: 0,
1886
1886
  pendingQueued: 0,
1887
- skipPropagateValues: options?.skipPropagateValues ?? false,
1888
1887
  propagate: options?.propagate ?? true,
1889
1888
  resolve: options?.resolve,
1890
1889
  };
@@ -1892,7 +1891,6 @@ class RunContextManager {
1892
1891
  this.logger.info("create-run-context", {
1893
1892
  id,
1894
1893
  startNodeId,
1895
- skipPropagateValues: ctx.skipPropagateValues,
1896
1894
  propagate: ctx.propagate,
1897
1895
  });
1898
1896
  return id;
@@ -2943,12 +2941,11 @@ class EdgePropagator {
2943
2941
  if (!shouldExecute) {
2944
2942
  return; // No change and no reason to rerun
2945
2943
  }
2946
- // Set input value (respecting skipPropagateValues)
2947
- const shouldSetValue = this.shouldSetInputValue(effectiveRunContexts);
2948
- if (shouldSetValue && valueChanged) {
2944
+ // Set input value
2945
+ if (valueChanged) {
2949
2946
  this.runtime.setTargetInput(edge, processedValue, "applyToTarget");
2950
2947
  }
2951
- else if (shouldSetValue && !valueChanged) {
2948
+ else {
2952
2949
  // Even if value didn't change, update timestamp if we're forcing execution
2953
2950
  const now = Date.now();
2954
2951
  this.graph.updateNodeLastInputAt(edge.target.nodeId, edge.target.handle, now);
@@ -2986,22 +2983,6 @@ class EdgePropagator {
2986
2983
  }
2987
2984
  return merged;
2988
2985
  }
2989
- /**
2990
- * Check if input value should be set (respecting skipPropagateValues)
2991
- */
2992
- shouldSetInputValue(effectiveRunContexts) {
2993
- if (!effectiveRunContexts) {
2994
- return true; // Auto mode always sets values
2995
- }
2996
- // Check skipPropagateValues (only in run-context mode)
2997
- for (const id of effectiveRunContexts) {
2998
- const ctx = this.runContextManager.getRunContext(id);
2999
- if (ctx && ctx.skipPropagateValues) {
3000
- return false;
3001
- }
3002
- }
3003
- return true;
3004
- }
3005
2986
  /**
3006
2987
  * Execute downstream if conditions are met
3007
2988
  */
@@ -3090,8 +3071,6 @@ class EdgePropagator {
3090
3071
  * If undefined or empty, behaves like auto mode (always propagates values and execution).
3091
3072
  */
3092
3073
  propagate(srcNodeId, srcHandle, value, runContextIds) {
3093
- if (this.runtime.isPaused())
3094
- return;
3095
3074
  // Set source output
3096
3075
  if (!this.setSourceOutput(srcNodeId, srcHandle, value)) {
3097
3076
  return; // Node was removed
@@ -3108,8 +3087,6 @@ class EdgePropagator {
3108
3087
  * Only re-emits outputs that are valid according to resolved handles
3109
3088
  */
3110
3089
  invalidateDownstream(nodeId) {
3111
- if (this.runtime.isPaused())
3112
- return;
3113
3090
  const node = this.graph.getNode(nodeId);
3114
3091
  if (!node)
3115
3092
  return;
@@ -3848,6 +3825,7 @@ class GraphRuntime {
3848
3825
  this.runMode = "manual";
3849
3826
  this.pauseRefCount = 0;
3850
3827
  this.persistentPauseToken = null;
3828
+ this.deferredAutoRunNodeIds = new Set();
3851
3829
  // Initialize components
3852
3830
  this.eventEmitter = new EventEmitter();
3853
3831
  this.graph = new Graph(this.eventEmitter);
@@ -3952,28 +3930,48 @@ class GraphRuntime {
3952
3930
  const e = event;
3953
3931
  return e.action === "invalidate";
3954
3932
  }
3933
+ withRunContext(nodeId, options, run) {
3934
+ const runContextId = this.runContextManager.createRunContext(nodeId, options);
3935
+ try {
3936
+ return run(new Set([runContextId]));
3937
+ }
3938
+ finally {
3939
+ this.runContextManager.releaseScheduling(runContextId);
3940
+ }
3941
+ }
3942
+ withManualNoPropagateContext(nodeId, run) {
3943
+ if (this.runMode !== "manual") {
3944
+ run(undefined);
3945
+ return;
3946
+ }
3947
+ this.withRunContext(nodeId, { propagate: false }, (runContextIds) => {
3948
+ run(runContextIds);
3949
+ });
3950
+ }
3955
3951
  executeNodeAutoRun(nodeId, opts) {
3956
3952
  const node = this.graph.getNode(nodeId);
3957
3953
  const shouldAutoRun = this.runMode === "auto" || node?.policy?.autoRun === true;
3958
3954
  const canExecute = this.graph.allInboundHaveValue(nodeId);
3959
3955
  if (!shouldAutoRun || !canExecute)
3960
3956
  return;
3961
- let runContextIdsToUse = undefined;
3962
- let runContextIdToRelease;
3963
- if (this.runMode === "manual") {
3964
- runContextIdToRelease = this.runContextManager.createRunContext(nodeId, { propagate: false });
3965
- runContextIdsToUse = new Set([runContextIdToRelease]);
3957
+ if (this.isPaused()) {
3958
+ this.deferredAutoRunNodeIds.add(nodeId);
3959
+ return;
3966
3960
  }
3967
- try {
3961
+ this.withManualNoPropagateContext(nodeId, (runContextIds) => {
3968
3962
  this.execute(nodeId, {
3969
- runContextIds: runContextIdsToUse,
3963
+ runContextIds,
3970
3964
  reason: opts?.reason ?? "executeNodeAutoRun",
3971
3965
  });
3972
- }
3973
- finally {
3974
- if (runContextIdToRelease) {
3975
- this.runContextManager.releaseScheduling(runContextIdToRelease);
3976
- }
3966
+ });
3967
+ }
3968
+ flushDeferredAutoRunNodes() {
3969
+ if (this.isPaused() || this.deferredAutoRunNodeIds.size === 0)
3970
+ return;
3971
+ const queuedNodeIds = Array.from(this.deferredAutoRunNodeIds);
3972
+ this.deferredAutoRunNodeIds.clear();
3973
+ for (const nodeId of queuedNodeIds) {
3974
+ this.executeNodeAutoRun(nodeId, { reason: "deferred-auto-run" });
3977
3975
  }
3978
3976
  }
3979
3977
  setInputs(nodeId, inputs) {
@@ -4203,20 +4201,19 @@ class GraphRuntime {
4203
4201
  if (!node)
4204
4202
  return;
4205
4203
  return new Promise((resolve) => {
4206
- const id = this.runContextManager.createRunContext(startNodeId, {
4207
- resolve,
4204
+ this.withRunContext(startNodeId, {
4208
4205
  ...opts,
4209
- });
4210
- this.graph.addNodeRunContextId(startNodeId, id);
4211
- try {
4206
+ resolve,
4207
+ }, (runContextIds) => {
4208
+ const [runContextId] = runContextIds;
4209
+ if (runContextId) {
4210
+ this.graph.addNodeRunContextId(startNodeId, runContextId);
4211
+ }
4212
4212
  this.execute(startNodeId, {
4213
- runContextIds: new Set([id]),
4213
+ runContextIds,
4214
4214
  reason: opts?.reason ?? "runFromHereContext",
4215
4215
  });
4216
- }
4217
- finally {
4218
- this.runContextManager.releaseScheduling(id);
4219
- }
4216
+ });
4220
4217
  });
4221
4218
  }
4222
4219
  setRunMode(runMode) {
@@ -4233,6 +4230,10 @@ class GraphRuntime {
4233
4230
  return;
4234
4231
  released = true;
4235
4232
  this.pauseRefCount--;
4233
+ if (this.pauseRefCount <= 0) {
4234
+ this.pauseRefCount = 0;
4235
+ this.flushDeferredAutoRunNodes();
4236
+ }
4236
4237
  };
4237
4238
  }
4238
4239
  isPaused() {
@@ -4276,18 +4277,13 @@ class GraphRuntime {
4276
4277
  this.handleResolver.scheduleRecomputeHandles(toNodeId);
4277
4278
  if (options?.dry) {
4278
4279
  // Dry copy should propagate values only, never schedule node execution.
4279
- const runContextId = this.runContextManager.createRunContext(toNodeId, { propagate: false });
4280
- const runContextIds = new Set([runContextId]);
4281
- try {
4280
+ this.withRunContext(toNodeId, { propagate: false }, (runContextIds) => {
4282
4281
  for (const [handle, value] of Object.entries(fromNode.outputs || {})) {
4283
4282
  if (value !== undefined) {
4284
4283
  this.propagate(toNodeId, handle, value, runContextIds);
4285
4284
  }
4286
4285
  }
4287
- }
4288
- finally {
4289
- this.runContextManager.releaseScheduling(runContextId);
4290
- }
4286
+ });
4291
4287
  return;
4292
4288
  }
4293
4289
  this.executeNodeAutoRun(toNodeId, { reason: "copyOutputs" });
@@ -4553,22 +4549,9 @@ class GraphRuntime {
4553
4549
  if (!setsEqual(beforeTargetSet, afterTargetSet)) {
4554
4550
  const val = this.getOutput(nodeId, handle);
4555
4551
  if (val !== undefined) {
4556
- let runContextIdsToUse = undefined;
4557
- let runContextIdToRelease;
4558
- if (this.runMode === "manual") {
4559
- runContextIdToRelease = this.runContextManager.createRunContext(nodeId, {
4560
- propagate: false,
4561
- });
4562
- runContextIdsToUse = new Set([runContextIdToRelease]);
4563
- }
4564
- try {
4565
- this.propagate(nodeId, handle, val, runContextIdsToUse);
4566
- }
4567
- finally {
4568
- if (runContextIdToRelease) {
4569
- this.runContextManager.releaseScheduling(runContextIdToRelease);
4570
- }
4571
- }
4552
+ this.withManualNoPropagateContext(nodeId, (runContextIds) => {
4553
+ this.propagate(nodeId, handle, val, runContextIds);
4554
+ });
4572
4555
  }
4573
4556
  }
4574
4557
  }
@@ -4941,12 +4924,9 @@ class LocalEngine {
4941
4924
  * Run only this node, no downstream propagation.
4942
4925
  * Works in both modes, but typically only used in manual mode.
4943
4926
  * @param nodeId - The node to run
4944
- * @param options - Execution options
4945
- * @param options.skipPropagateValues - If true, don't set inputs of linked nodes (default: false)
4946
4927
  */
4947
- async computeNode(nodeId, options) {
4928
+ async computeNode(nodeId) {
4948
4929
  await this.graphRuntime.runFromHereContext(nodeId, {
4949
- skipPropagateValues: options?.skipPropagateValues ?? false,
4950
4930
  propagate: false, // Don't schedule downstream nodes
4951
4931
  reason: "computeNode",
4952
4932
  });