@bian-womp/spark-graph 0.3.32 → 0.3.33
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 +144 -38
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/index.d.ts +3 -0
- package/lib/cjs/src/index.d.ts.map +1 -1
- package/lib/cjs/src/runtime/GraphRuntime.d.ts +16 -1
- package/lib/cjs/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/NodeExecutor.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/RuntimeValidatorManager.d.ts +31 -0
- package/lib/cjs/src/runtime/components/RuntimeValidatorManager.d.ts.map +1 -0
- package/lib/cjs/src/runtime/components/graph-utils.d.ts +11 -0
- package/lib/cjs/src/runtime/components/graph-utils.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/interfaces.d.ts +24 -1
- package/lib/cjs/src/runtime/components/interfaces.d.ts.map +1 -1
- package/lib/esm/index.js +143 -39
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/index.d.ts +3 -0
- package/lib/esm/src/index.d.ts.map +1 -1
- package/lib/esm/src/runtime/GraphRuntime.d.ts +16 -1
- package/lib/esm/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/NodeExecutor.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/RuntimeValidatorManager.d.ts +31 -0
- package/lib/esm/src/runtime/components/RuntimeValidatorManager.d.ts.map +1 -0
- package/lib/esm/src/runtime/components/graph-utils.d.ts +11 -0
- package/lib/esm/src/runtime/components/graph-utils.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/interfaces.d.ts +24 -1
- package/lib/esm/src/runtime/components/interfaces.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/cjs/index.cjs
CHANGED
|
@@ -1617,6 +1617,55 @@ function buildEdgeConverters(srcDeclared, dstDeclared, registry, edgeLabel) {
|
|
|
1617
1617
|
},
|
|
1618
1618
|
};
|
|
1619
1619
|
}
|
|
1620
|
+
/**
|
|
1621
|
+
* Compute effective inputs for a node by merging real inputs with defaults.
|
|
1622
|
+
* This is a shared utility used by both NodeExecutor and runtime validators.
|
|
1623
|
+
*
|
|
1624
|
+
* @param nodeId - The node ID to compute effective inputs for
|
|
1625
|
+
* @param graph - Graph component to access node and handle information
|
|
1626
|
+
* @param registry - Registry to access node type descriptors and defaults
|
|
1627
|
+
* @returns Record of effective input values (real inputs merged with defaults)
|
|
1628
|
+
*/
|
|
1629
|
+
function getEffectiveInputs(nodeId, graph, registry) {
|
|
1630
|
+
const node = graph.getNode(nodeId);
|
|
1631
|
+
if (!node)
|
|
1632
|
+
return {};
|
|
1633
|
+
const desc = registry.nodes.get(node.typeId);
|
|
1634
|
+
if (!desc)
|
|
1635
|
+
return {};
|
|
1636
|
+
const resolved = graph.getResolvedHandles(nodeId);
|
|
1637
|
+
const regDefaults = desc.inputDefaults ?? {};
|
|
1638
|
+
const dynDefaults = resolved?.inputDefaults ?? {};
|
|
1639
|
+
// Identify which handles are dynamically resolved (not in registry statics)
|
|
1640
|
+
const staticHandles = new Set(Object.keys(desc.inputs ?? {}));
|
|
1641
|
+
const dynamicHandles = new Set(Object.keys(resolved?.inputs ?? {}).filter((h) => !staticHandles.has(h)));
|
|
1642
|
+
// Precedence: dynamic > registry
|
|
1643
|
+
const mergedDefaults = {
|
|
1644
|
+
...regDefaults,
|
|
1645
|
+
...dynDefaults,
|
|
1646
|
+
};
|
|
1647
|
+
// Start with real inputs only (no defaults)
|
|
1648
|
+
const effective = { ...node.inputs };
|
|
1649
|
+
// Build set of inbound handles (wired inputs)
|
|
1650
|
+
const inboundEdges = graph.getInboundEdges(nodeId);
|
|
1651
|
+
const inbound = new Set(inboundEdges.map((e) => e.target.handle));
|
|
1652
|
+
// Apply defaults only for:
|
|
1653
|
+
// 1. Unbound handles that have no explicit value
|
|
1654
|
+
// 2. Static handles (not dynamically resolved)
|
|
1655
|
+
for (const [handle, defaultValue] of Object.entries(mergedDefaults)) {
|
|
1656
|
+
if (defaultValue === undefined)
|
|
1657
|
+
continue;
|
|
1658
|
+
if (inbound.has(handle))
|
|
1659
|
+
continue; // Don't override wired inputs
|
|
1660
|
+
if (effective[handle] !== undefined)
|
|
1661
|
+
continue; // Already has value
|
|
1662
|
+
if (dynamicHandles.has(handle))
|
|
1663
|
+
continue; // Skip defaults for dynamic handles
|
|
1664
|
+
// Clone to avoid shared references
|
|
1665
|
+
effective[handle] = structuredClone(defaultValue);
|
|
1666
|
+
}
|
|
1667
|
+
return effective;
|
|
1668
|
+
}
|
|
1620
1669
|
|
|
1621
1670
|
/**
|
|
1622
1671
|
* HandleResolver component - manages dynamic handle resolution
|
|
@@ -2253,47 +2302,10 @@ class NodeExecutor {
|
|
|
2253
2302
|
* Compute effective inputs for a node by merging real inputs with defaults
|
|
2254
2303
|
*/
|
|
2255
2304
|
getEffectiveInputs(nodeId) {
|
|
2256
|
-
const node = this.graph.getNode(nodeId);
|
|
2257
|
-
if (!node)
|
|
2258
|
-
return {};
|
|
2259
2305
|
const registry = this.graph.getRegistry();
|
|
2260
2306
|
if (!registry)
|
|
2261
2307
|
return {};
|
|
2262
|
-
|
|
2263
|
-
if (!desc)
|
|
2264
|
-
return {};
|
|
2265
|
-
const resolved = this.graph.getResolvedHandles(nodeId);
|
|
2266
|
-
const regDefaults = desc.inputDefaults ?? {};
|
|
2267
|
-
const dynDefaults = resolved?.inputDefaults ?? {};
|
|
2268
|
-
// Identify which handles are dynamically resolved (not in registry statics)
|
|
2269
|
-
const staticHandles = new Set(Object.keys(desc.inputs ?? {}));
|
|
2270
|
-
const dynamicHandles = new Set(Object.keys(resolved?.inputs ?? {}).filter((h) => !staticHandles.has(h)));
|
|
2271
|
-
// Precedence: dynamic > registry
|
|
2272
|
-
const mergedDefaults = {
|
|
2273
|
-
...regDefaults,
|
|
2274
|
-
...dynDefaults,
|
|
2275
|
-
};
|
|
2276
|
-
// Start with real inputs only (no defaults)
|
|
2277
|
-
const effective = { ...node.inputs };
|
|
2278
|
-
// Build set of inbound handles (wired inputs)
|
|
2279
|
-
const inboundEdges = this.graph.getInboundEdges(nodeId);
|
|
2280
|
-
const inbound = new Set(inboundEdges.map((e) => e.target.handle));
|
|
2281
|
-
// Apply defaults only for:
|
|
2282
|
-
// 1. Unbound handles that have no explicit value
|
|
2283
|
-
// 2. Static handles (not dynamically resolved)
|
|
2284
|
-
for (const [handle, defaultValue] of Object.entries(mergedDefaults)) {
|
|
2285
|
-
if (defaultValue === undefined)
|
|
2286
|
-
continue;
|
|
2287
|
-
if (inbound.has(handle))
|
|
2288
|
-
continue; // Don't override wired inputs
|
|
2289
|
-
if (effective[handle] !== undefined)
|
|
2290
|
-
continue; // Already has value
|
|
2291
|
-
if (dynamicHandles.has(handle))
|
|
2292
|
-
continue; // Skip defaults for dynamic handles
|
|
2293
|
-
// Clone to avoid shared references
|
|
2294
|
-
effective[handle] = structuredClone(defaultValue);
|
|
2295
|
-
}
|
|
2296
|
-
return effective;
|
|
2308
|
+
return getEffectiveInputs(nodeId, this.graph, registry);
|
|
2297
2309
|
}
|
|
2298
2310
|
/**
|
|
2299
2311
|
* Create an execution context for a node
|
|
@@ -2399,6 +2411,20 @@ class NodeExecutor {
|
|
|
2399
2411
|
// Early validation for auto-mode paused state
|
|
2400
2412
|
if (this.runtime.isPaused())
|
|
2401
2413
|
return;
|
|
2414
|
+
// Check runtime validators (check current state, not just graph definition)
|
|
2415
|
+
const runtimeValidationError = this.runtime.hasRuntimeValidationBlock(nodeId);
|
|
2416
|
+
if (runtimeValidationError) {
|
|
2417
|
+
this.eventEmitter.emit("error", {
|
|
2418
|
+
kind: "system",
|
|
2419
|
+
message: runtimeValidationError.message,
|
|
2420
|
+
code: runtimeValidationError.code || "RUNTIME_VALIDATION_BLOCKED",
|
|
2421
|
+
details: {
|
|
2422
|
+
nodeId,
|
|
2423
|
+
...runtimeValidationError.details,
|
|
2424
|
+
},
|
|
2425
|
+
});
|
|
2426
|
+
return;
|
|
2427
|
+
}
|
|
2402
2428
|
// Attach run-context IDs if provided - do this BEFORE checking for pending resolution
|
|
2403
2429
|
// so that handle resolution can track these run contexts
|
|
2404
2430
|
if (runContextIds) {
|
|
@@ -2857,6 +2883,61 @@ class NodeExecutor {
|
|
|
2857
2883
|
}
|
|
2858
2884
|
}
|
|
2859
2885
|
|
|
2886
|
+
/**
|
|
2887
|
+
* RuntimeValidatorManager component - manages runtime validators
|
|
2888
|
+
*/
|
|
2889
|
+
class RuntimeValidatorManager {
|
|
2890
|
+
constructor(graph, registry) {
|
|
2891
|
+
this.graph = graph;
|
|
2892
|
+
this.registry = registry;
|
|
2893
|
+
this.validators = [];
|
|
2894
|
+
}
|
|
2895
|
+
/**
|
|
2896
|
+
* Set the registry (called when registry changes)
|
|
2897
|
+
*/
|
|
2898
|
+
setRegistry(registry) {
|
|
2899
|
+
this.registry = registry;
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* Register a runtime validator that will be called before node execution.
|
|
2903
|
+
* Validators are called in registration order - if any returns true, execution is blocked.
|
|
2904
|
+
*/
|
|
2905
|
+
registerValidator(validator) {
|
|
2906
|
+
this.validators.push(validator);
|
|
2907
|
+
}
|
|
2908
|
+
/**
|
|
2909
|
+
* Unregister a runtime validator.
|
|
2910
|
+
*/
|
|
2911
|
+
unregisterValidator(validator) {
|
|
2912
|
+
const index = this.validators.indexOf(validator);
|
|
2913
|
+
if (index >= 0) {
|
|
2914
|
+
this.validators.splice(index, 1);
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
/**
|
|
2918
|
+
* Check if any runtime validator blocks execution for this node.
|
|
2919
|
+
* Returns RuntimeValidationError if execution should be blocked, null otherwise.
|
|
2920
|
+
*/
|
|
2921
|
+
hasBlock(nodeId) {
|
|
2922
|
+
if (!this.registry)
|
|
2923
|
+
return null;
|
|
2924
|
+
for (const validator of this.validators) {
|
|
2925
|
+
try {
|
|
2926
|
+
const result = validator(nodeId, this.graph, this.registry);
|
|
2927
|
+
if (result !== false) {
|
|
2928
|
+
// Validator returned an error object
|
|
2929
|
+
return result;
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
catch (err) {
|
|
2933
|
+
// Don't let validator errors break execution - log and continue
|
|
2934
|
+
console.error(`Runtime validator error for node ${nodeId}:`, err);
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
return null;
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
|
|
2860
2941
|
// Types are now imported from components/types.ts (re-exported above)
|
|
2861
2942
|
class GraphRuntime {
|
|
2862
2943
|
constructor() {
|
|
@@ -2873,6 +2954,8 @@ class GraphRuntime {
|
|
|
2873
2954
|
this.edgePropagator = new EdgePropagator(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this);
|
|
2874
2955
|
// Create NodeExecutor with EdgePropagator and HandleResolver
|
|
2875
2956
|
this.nodeExecutor = new NodeExecutor(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this, this);
|
|
2957
|
+
// Create RuntimeValidatorManager
|
|
2958
|
+
this.runtimeValidatorManager = new RuntimeValidatorManager(this.graph);
|
|
2876
2959
|
}
|
|
2877
2960
|
static create(def, registry, opts) {
|
|
2878
2961
|
const gr = new GraphRuntime();
|
|
@@ -2884,6 +2967,7 @@ class GraphRuntime {
|
|
|
2884
2967
|
gr.handleResolver.setRegistry(registry);
|
|
2885
2968
|
gr.handleResolver.setEnvironment(gr.environment);
|
|
2886
2969
|
gr.nodeExecutor.setEnvironment(gr.environment);
|
|
2970
|
+
gr.runtimeValidatorManager.setRegistry(registry);
|
|
2887
2971
|
// Precompute per-node resolved handles (use def-provided overrides; do not compute dynamically here)
|
|
2888
2972
|
const initial = gr.isPaused()
|
|
2889
2973
|
? {
|
|
@@ -3101,6 +3185,26 @@ class GraphRuntime {
|
|
|
3101
3185
|
this.handleResolver.scheduleRecomputeHandles(nodeId);
|
|
3102
3186
|
}
|
|
3103
3187
|
}
|
|
3188
|
+
/**
|
|
3189
|
+
* Register a runtime validator that will be called before node execution.
|
|
3190
|
+
* Validators are called in registration order - if any returns true, execution is blocked.
|
|
3191
|
+
*/
|
|
3192
|
+
registerRuntimeValidator(validator) {
|
|
3193
|
+
this.runtimeValidatorManager.registerValidator(validator);
|
|
3194
|
+
}
|
|
3195
|
+
/**
|
|
3196
|
+
* Unregister a runtime validator.
|
|
3197
|
+
*/
|
|
3198
|
+
unregisterRuntimeValidator(validator) {
|
|
3199
|
+
this.runtimeValidatorManager.unregisterValidator(validator);
|
|
3200
|
+
}
|
|
3201
|
+
/**
|
|
3202
|
+
* Check if any runtime validator blocks execution for this node.
|
|
3203
|
+
* Returns RuntimeValidationError if execution should be blocked, null otherwise.
|
|
3204
|
+
*/
|
|
3205
|
+
hasRuntimeValidationBlock(nodeId) {
|
|
3206
|
+
return this.runtimeValidatorManager.hasBlock(nodeId);
|
|
3207
|
+
}
|
|
3104
3208
|
getGraphDef() {
|
|
3105
3209
|
const nodes = [];
|
|
3106
3210
|
this.graph.forEachNode((n) => {
|
|
@@ -6158,6 +6262,7 @@ exports.BaseLogicOperation = BaseLogicOperation;
|
|
|
6158
6262
|
exports.BaseMathOperation = BaseMathOperation;
|
|
6159
6263
|
exports.CompositeCategory = CompositeCategory;
|
|
6160
6264
|
exports.ComputeCategory = ComputeCategory;
|
|
6265
|
+
exports.Graph = Graph;
|
|
6161
6266
|
exports.GraphBuilder = GraphBuilder;
|
|
6162
6267
|
exports.GraphRuntime = GraphRuntime;
|
|
6163
6268
|
exports.LevelLogger = LevelLogger;
|
|
@@ -6176,6 +6281,7 @@ exports.createValidationGraphDef = createValidationGraphDef;
|
|
|
6176
6281
|
exports.createValidationGraphRegistry = createValidationGraphRegistry;
|
|
6177
6282
|
exports.findMatchingPaths = findMatchingPaths;
|
|
6178
6283
|
exports.generateId = generateId;
|
|
6284
|
+
exports.getEffectiveInputs = getEffectiveInputs;
|
|
6179
6285
|
exports.getInputDeclaredTypes = getInputDeclaredTypes;
|
|
6180
6286
|
exports.getInputHandleMetadata = getInputHandleMetadata;
|
|
6181
6287
|
exports.getInputTypeId = getInputTypeId;
|