@bian-womp/spark-graph 0.3.31 → 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 +338 -133
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/builder/GraphBuilder.d.ts +0 -1
- package/lib/cjs/src/builder/GraphBuilder.d.ts.map +1 -1
- package/lib/cjs/src/builder/Registry.d.ts +6 -0
- package/lib/cjs/src/builder/Registry.d.ts.map +1 -1
- package/lib/cjs/src/core/type-utils.d.ts +11 -0
- package/lib/cjs/src/core/type-utils.d.ts.map +1 -1
- package/lib/cjs/src/index.d.ts +4 -1
- package/lib/cjs/src/index.d.ts.map +1 -1
- package/lib/cjs/src/misc/utils/merge.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/Graph.d.ts +1 -2
- package/lib/cjs/src/runtime/components/Graph.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/HandleResolver.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 +15 -4
- 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/cjs/src/runtime/components/types.d.ts +1 -2
- package/lib/cjs/src/runtime/components/types.d.ts.map +1 -1
- package/lib/esm/index.js +336 -134
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/builder/GraphBuilder.d.ts +0 -1
- package/lib/esm/src/builder/GraphBuilder.d.ts.map +1 -1
- package/lib/esm/src/builder/Registry.d.ts +6 -0
- package/lib/esm/src/builder/Registry.d.ts.map +1 -1
- package/lib/esm/src/core/type-utils.d.ts +11 -0
- package/lib/esm/src/core/type-utils.d.ts.map +1 -1
- package/lib/esm/src/index.d.ts +4 -1
- package/lib/esm/src/index.d.ts.map +1 -1
- package/lib/esm/src/misc/utils/merge.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/Graph.d.ts +1 -2
- package/lib/esm/src/runtime/components/Graph.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/HandleResolver.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 +15 -4
- 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/lib/esm/src/runtime/components/types.d.ts +1 -2
- package/lib/esm/src/runtime/components/types.d.ts.map +1 -1
- package/package.json +2 -2
package/lib/esm/index.js
CHANGED
|
@@ -16,19 +16,42 @@ function getTypedOutputValue(v) {
|
|
|
16
16
|
return v.__spark_value;
|
|
17
17
|
return v;
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Get the full declared type(s) for an input handle (supports union types)
|
|
21
|
+
* Returns the typeId as-is: string for single type, string[] for union types
|
|
22
|
+
*/
|
|
23
|
+
function getInputDeclaredTypes(inputs, handle) {
|
|
20
24
|
const v = inputs ? inputs[handle] : undefined;
|
|
21
25
|
if (!v)
|
|
22
26
|
return undefined;
|
|
23
|
-
|
|
27
|
+
if (typeof v === "string")
|
|
28
|
+
return v;
|
|
29
|
+
if (Array.isArray(v))
|
|
30
|
+
return v;
|
|
31
|
+
return v.typeId;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the primary (first) type ID for an input handle.
|
|
35
|
+
* For union types, returns the first type in the array.
|
|
36
|
+
* This maintains backward compatibility for code that expects a single type.
|
|
37
|
+
*/
|
|
38
|
+
function getInputTypeId(inputs, handle) {
|
|
39
|
+
const decl = getInputDeclaredTypes(inputs, handle);
|
|
40
|
+
if (!decl)
|
|
41
|
+
return undefined;
|
|
42
|
+
return Array.isArray(decl) ? decl[0] : decl;
|
|
24
43
|
}
|
|
25
44
|
function isInputPrivate(inputs, handle) {
|
|
26
45
|
const v = inputs ? inputs[handle] : undefined;
|
|
27
|
-
|
|
46
|
+
if (!v || typeof v === "string" || Array.isArray(v))
|
|
47
|
+
return false;
|
|
48
|
+
// At this point, v must be an object with optional private/metadata fields
|
|
49
|
+
return !!(typeof v === "object" && v !== null && "private" in v && v.private);
|
|
28
50
|
}
|
|
29
51
|
/**
|
|
30
52
|
* Merge two InputHandleDescriptor values, with dynamic taking precedence.
|
|
31
53
|
* If both have metadata, merge the metadata objects (dynamic overrides static).
|
|
54
|
+
* Supports union types (arrays) in both static and dynamic descriptors.
|
|
32
55
|
*/
|
|
33
56
|
function mergeInputHandleDescriptors(staticDesc, dynamicDesc) {
|
|
34
57
|
// If only one exists, return it
|
|
@@ -36,12 +59,17 @@ function mergeInputHandleDescriptors(staticDesc, dynamicDesc) {
|
|
|
36
59
|
return dynamicDesc;
|
|
37
60
|
if (!dynamicDesc)
|
|
38
61
|
return staticDesc;
|
|
39
|
-
// If both are
|
|
40
|
-
if (typeof staticDesc === "string"
|
|
62
|
+
// If both are primitive (string or array), dynamic wins
|
|
63
|
+
if ((typeof staticDesc === "string" || Array.isArray(staticDesc)) &&
|
|
64
|
+
(typeof dynamicDesc === "string" || Array.isArray(dynamicDesc))) {
|
|
41
65
|
return dynamicDesc;
|
|
42
66
|
}
|
|
43
|
-
const staticObj = typeof staticDesc === "string"
|
|
44
|
-
|
|
67
|
+
const staticObj = typeof staticDesc === "string" || Array.isArray(staticDesc)
|
|
68
|
+
? { typeId: staticDesc }
|
|
69
|
+
: staticDesc;
|
|
70
|
+
const dynamicObj = typeof dynamicDesc === "string" || Array.isArray(dynamicDesc)
|
|
71
|
+
? { typeId: dynamicDesc }
|
|
72
|
+
: dynamicDesc;
|
|
45
73
|
// Merge: dynamic takes precedence, but merge metadata objects
|
|
46
74
|
const merged = {
|
|
47
75
|
typeId: dynamicObj.typeId ?? staticObj.typeId,
|
|
@@ -62,7 +90,7 @@ function mergeInputHandleDescriptors(staticDesc, dynamicDesc) {
|
|
|
62
90
|
*/
|
|
63
91
|
function getInputHandleMetadata(inputs, handle) {
|
|
64
92
|
const v = inputs ? inputs[handle] : undefined;
|
|
65
|
-
if (!v || typeof v === "string")
|
|
93
|
+
if (!v || typeof v === "string" || Array.isArray(v))
|
|
66
94
|
return undefined;
|
|
67
95
|
return v.metadata;
|
|
68
96
|
}
|
|
@@ -257,7 +285,11 @@ class Registry {
|
|
|
257
285
|
if (cached)
|
|
258
286
|
return cached;
|
|
259
287
|
if (fromTypeId === toTypeId) {
|
|
260
|
-
const res = {
|
|
288
|
+
const res = {
|
|
289
|
+
kind: "sync",
|
|
290
|
+
convert: (v) => v,
|
|
291
|
+
cost: { edges: 0, async: 0 },
|
|
292
|
+
};
|
|
261
293
|
this.resolvedCache.set(cacheKey, res);
|
|
262
294
|
return res;
|
|
263
295
|
}
|
|
@@ -267,6 +299,7 @@ class Registry {
|
|
|
267
299
|
const res = {
|
|
268
300
|
kind: "sync",
|
|
269
301
|
convert: directSync.convert,
|
|
302
|
+
cost: { edges: 1, async: 0 },
|
|
270
303
|
};
|
|
271
304
|
this.resolvedCache.set(cacheKey, res);
|
|
272
305
|
return res;
|
|
@@ -276,6 +309,7 @@ class Registry {
|
|
|
276
309
|
const res = {
|
|
277
310
|
kind: "async",
|
|
278
311
|
convertAsync: directAsync.convertAsync,
|
|
312
|
+
cost: { edges: 1, async: 1 },
|
|
279
313
|
};
|
|
280
314
|
this.resolvedCache.set(cacheKey, res);
|
|
281
315
|
return res;
|
|
@@ -332,6 +366,10 @@ class Registry {
|
|
|
332
366
|
const cur = queue.shift();
|
|
333
367
|
if (cur.node === toTypeId) {
|
|
334
368
|
// Compose
|
|
369
|
+
const cost = {
|
|
370
|
+
edges: cur.cost.edges,
|
|
371
|
+
async: cur.cost.async,
|
|
372
|
+
};
|
|
335
373
|
const hasAsync = cur.path.some((s) => s.kind === "async");
|
|
336
374
|
if (!hasAsync) {
|
|
337
375
|
const convert = (value) => {
|
|
@@ -342,7 +380,11 @@ class Registry {
|
|
|
342
380
|
}
|
|
343
381
|
return acc;
|
|
344
382
|
};
|
|
345
|
-
const res = {
|
|
383
|
+
const res = {
|
|
384
|
+
kind: "sync",
|
|
385
|
+
convert,
|
|
386
|
+
cost,
|
|
387
|
+
};
|
|
346
388
|
this.resolvedCache.set(cacheKey, res);
|
|
347
389
|
return res;
|
|
348
390
|
}
|
|
@@ -359,7 +401,11 @@ class Registry {
|
|
|
359
401
|
}
|
|
360
402
|
return acc;
|
|
361
403
|
};
|
|
362
|
-
const res = {
|
|
404
|
+
const res = {
|
|
405
|
+
kind: "async",
|
|
406
|
+
convertAsync,
|
|
407
|
+
cost,
|
|
408
|
+
};
|
|
363
409
|
this.resolvedCache.set(cacheKey, res);
|
|
364
410
|
return res;
|
|
365
411
|
}
|
|
@@ -816,9 +862,6 @@ class Graph {
|
|
|
816
862
|
const edge = this.edges.find((e) => e.id === edgeId);
|
|
817
863
|
if (!edge)
|
|
818
864
|
return;
|
|
819
|
-
if (updates.effectiveTypeId !== undefined) {
|
|
820
|
-
edge.effectiveTypeId = updates.effectiveTypeId;
|
|
821
|
-
}
|
|
822
865
|
if (updates.dstDeclared !== undefined) {
|
|
823
866
|
edge.dstDeclared = updates.dstDeclared;
|
|
824
867
|
}
|
|
@@ -1412,14 +1455,13 @@ function buildEdges(def, registry, resolvedByNode) {
|
|
|
1412
1455
|
return def.edges.map((e) => {
|
|
1413
1456
|
const srcNode = def.nodes.find((n) => n.nodeId === e.source.nodeId);
|
|
1414
1457
|
const dstNode = def.nodes.find((n) => n.nodeId === e.target.nodeId);
|
|
1415
|
-
const { srcDeclared, dstDeclared
|
|
1458
|
+
const { srcDeclared, dstDeclared } = extractEdgeTypes(e.source.nodeId, e.source.handle, e.target.nodeId, e.target.handle, resolvedByNode);
|
|
1416
1459
|
const { convert, convertAsync } = buildEdgeConverters(srcDeclared, dstDeclared, registry, `buildEdges: ${srcNode?.typeId || ""}.${e.source.nodeId}.${e.source.handle} -> ${dstNode?.typeId || ""}.${e.target.nodeId}.${e.target.handle}`);
|
|
1417
1460
|
return {
|
|
1418
1461
|
id: e.id,
|
|
1419
1462
|
source: { ...e.source },
|
|
1420
1463
|
target: { ...e.target },
|
|
1421
1464
|
typeId: e.typeId, // Preserve original (may be undefined)
|
|
1422
|
-
effectiveTypeId, // Always present
|
|
1423
1465
|
convert,
|
|
1424
1466
|
convertAsync,
|
|
1425
1467
|
srcUnionTypes: Array.isArray(srcDeclared) ? [...srcDeclared] : undefined,
|
|
@@ -1431,37 +1473,79 @@ function buildEdges(def, registry, resolvedByNode) {
|
|
|
1431
1473
|
/**
|
|
1432
1474
|
* Extract edge type information from resolved handles
|
|
1433
1475
|
* Used by both buildEdges and updateNodeHandles to avoid duplication
|
|
1476
|
+
* Now supports union types on both source (output) and destination (input) handles
|
|
1434
1477
|
*/
|
|
1435
|
-
function extractEdgeTypes(sourceNodeId, sourceHandle, targetNodeId, targetHandle, resolvedByNode
|
|
1478
|
+
function extractEdgeTypes(sourceNodeId, sourceHandle, targetNodeId, targetHandle, resolvedByNode) {
|
|
1436
1479
|
const srcResolved = resolvedByNode.get(sourceNodeId);
|
|
1437
1480
|
const dstResolved = resolvedByNode.get(targetNodeId);
|
|
1438
1481
|
const srcDeclared = srcResolved
|
|
1439
1482
|
? srcResolved.outputs[sourceHandle]
|
|
1440
1483
|
: undefined;
|
|
1441
1484
|
const dstDeclared = dstResolved
|
|
1442
|
-
?
|
|
1485
|
+
? getInputDeclaredTypes(dstResolved.inputs, targetHandle)
|
|
1443
1486
|
: undefined;
|
|
1444
|
-
let effectiveTypeId = explicitTypeId;
|
|
1445
|
-
if (!effectiveTypeId) {
|
|
1446
|
-
// Infer if not explicitly set
|
|
1447
|
-
effectiveTypeId = Array.isArray(srcDeclared) ? srcDeclared[0] : srcDeclared;
|
|
1448
|
-
}
|
|
1449
1487
|
return {
|
|
1450
1488
|
srcDeclared,
|
|
1451
1489
|
dstDeclared,
|
|
1452
|
-
effectiveTypeId: effectiveTypeId ?? "untyped",
|
|
1453
1490
|
};
|
|
1454
1491
|
}
|
|
1455
1492
|
// Static helper: build edge converters for type coercion
|
|
1493
|
+
// Now supports union types on both source (output) and destination (input) handles
|
|
1456
1494
|
function buildEdgeConverters(srcDeclared, dstDeclared, registry, edgeLabel) {
|
|
1457
1495
|
if (!dstDeclared || !srcDeclared) {
|
|
1458
1496
|
return {};
|
|
1459
1497
|
}
|
|
1460
|
-
const
|
|
1461
|
-
const srcTypes =
|
|
1462
|
-
|
|
1463
|
-
const
|
|
1464
|
-
|
|
1498
|
+
const isSrcUnion = Array.isArray(srcDeclared);
|
|
1499
|
+
const srcTypes = isSrcUnion ? srcDeclared : [srcDeclared];
|
|
1500
|
+
const isDstUnion = Array.isArray(dstDeclared);
|
|
1501
|
+
const dstTypes = isDstUnion ? dstDeclared : [dstDeclared];
|
|
1502
|
+
// Helper to compare coercion costs (sync preferred, then fewer steps)
|
|
1503
|
+
const compareCost = (a, b) => {
|
|
1504
|
+
// Prefer sync over async
|
|
1505
|
+
if (a.kind === "sync" && b.kind === "async")
|
|
1506
|
+
return -1;
|
|
1507
|
+
if (a.kind === "async" && b.kind === "sync")
|
|
1508
|
+
return 1;
|
|
1509
|
+
// If same kind, prefer fewer edges
|
|
1510
|
+
if (a.cost.edges !== b.cost.edges)
|
|
1511
|
+
return a.cost.edges - b.cost.edges;
|
|
1512
|
+
// If same edges, prefer fewer async steps
|
|
1513
|
+
return a.cost.async - b.cost.async;
|
|
1514
|
+
};
|
|
1515
|
+
// Helper to find the best coercion from a source type to any destination type
|
|
1516
|
+
const getCoercion = (srcTypeId) => {
|
|
1517
|
+
const candidates = [];
|
|
1518
|
+
// Try all destination types and collect valid coercions
|
|
1519
|
+
for (const dstTypeId of dstTypes) {
|
|
1520
|
+
const coercion = registry.resolveCoercion(srcTypeId, dstTypeId);
|
|
1521
|
+
if (coercion) {
|
|
1522
|
+
candidates.push({
|
|
1523
|
+
dstType: dstTypeId,
|
|
1524
|
+
coercion,
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
if (candidates.length === 0)
|
|
1529
|
+
return null;
|
|
1530
|
+
// Select best by cost: sync preferred, then fewer edges, then fewer async steps
|
|
1531
|
+
const best = candidates.reduce((best, cur) => {
|
|
1532
|
+
return compareCost(cur.coercion, best.coercion) < 0 ? cur : best;
|
|
1533
|
+
});
|
|
1534
|
+
if (best.coercion.kind === "sync") {
|
|
1535
|
+
return {
|
|
1536
|
+
kind: "sync",
|
|
1537
|
+
convert: best.coercion.convert,
|
|
1538
|
+
dstType: best.dstType,
|
|
1539
|
+
};
|
|
1540
|
+
}
|
|
1541
|
+
else {
|
|
1542
|
+
return {
|
|
1543
|
+
kind: "async",
|
|
1544
|
+
convert: (v) => v, // placeholder, not used for async
|
|
1545
|
+
convertAsync: best.coercion.convertAsync,
|
|
1546
|
+
dstType: best.dstType,
|
|
1547
|
+
};
|
|
1548
|
+
}
|
|
1465
1549
|
};
|
|
1466
1550
|
// Resolve coercions for all source types
|
|
1467
1551
|
const coercions = srcTypes.map(getCoercion);
|
|
@@ -1470,7 +1554,7 @@ function buildEdgeConverters(srcDeclared, dstDeclared, registry, edgeLabel) {
|
|
|
1470
1554
|
const extractPayload = (v) => {
|
|
1471
1555
|
const typeId = getTypedOutputTypeId(v);
|
|
1472
1556
|
const payload = getTypedOutputValue(v);
|
|
1473
|
-
if (
|
|
1557
|
+
if (isSrcUnion) {
|
|
1474
1558
|
if (!typeId) {
|
|
1475
1559
|
throw new Error(`Typed output required for union source (${edgeLabel}); allowed: ${srcTypes.join("|")}`);
|
|
1476
1560
|
}
|
|
@@ -1484,17 +1568,27 @@ function buildEdgeConverters(srcDeclared, dstDeclared, registry, edgeLabel) {
|
|
|
1484
1568
|
}
|
|
1485
1569
|
return { typeId: typeId || srcTypes[0], payload };
|
|
1486
1570
|
};
|
|
1571
|
+
const wrapIfDstUnion = (dstType, val) => {
|
|
1572
|
+
if (!isDstUnion || !dstType)
|
|
1573
|
+
return val;
|
|
1574
|
+
return typed(dstType, val);
|
|
1575
|
+
};
|
|
1487
1576
|
if (hasAsync) {
|
|
1488
1577
|
return {
|
|
1489
1578
|
convertAsync: async (v, signal) => {
|
|
1490
1579
|
const { typeId, payload } = extractPayload(v);
|
|
1491
1580
|
const res = getCoercion(typeId);
|
|
1492
|
-
if (!res)
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1581
|
+
if (!res) {
|
|
1582
|
+
const fallbackType = isDstUnion && typeId && dstTypes.includes(typeId)
|
|
1583
|
+
? typeId
|
|
1584
|
+
: undefined;
|
|
1585
|
+
return wrapIfDstUnion(fallbackType, payload);
|
|
1496
1586
|
}
|
|
1497
|
-
|
|
1587
|
+
if (res.kind === "async" && res.convertAsync) {
|
|
1588
|
+
const converted = await res.convertAsync(payload, signal);
|
|
1589
|
+
return wrapIfDstUnion(res.dstType, converted);
|
|
1590
|
+
}
|
|
1591
|
+
return wrapIfDstUnion(res.dstType, res.convert(payload));
|
|
1498
1592
|
},
|
|
1499
1593
|
};
|
|
1500
1594
|
}
|
|
@@ -1507,15 +1601,69 @@ function buildEdgeConverters(srcDeclared, dstDeclared, registry, edgeLabel) {
|
|
|
1507
1601
|
convert: (v) => {
|
|
1508
1602
|
const { typeId, payload } = extractPayload(v);
|
|
1509
1603
|
const res = getCoercion(typeId);
|
|
1510
|
-
if (!res)
|
|
1511
|
-
|
|
1604
|
+
if (!res) {
|
|
1605
|
+
const fallbackType = isDstUnion && typeId && dstTypes.includes(typeId)
|
|
1606
|
+
? typeId
|
|
1607
|
+
: undefined;
|
|
1608
|
+
return wrapIfDstUnion(fallbackType, payload);
|
|
1609
|
+
}
|
|
1512
1610
|
if (res.kind === "async") {
|
|
1513
1611
|
throw new Error(`Async coercion required but convert used (${edgeLabel})`);
|
|
1514
1612
|
}
|
|
1515
|
-
|
|
1613
|
+
const converted = res.convert(payload);
|
|
1614
|
+
return wrapIfDstUnion(res.dstType, converted);
|
|
1516
1615
|
},
|
|
1517
1616
|
};
|
|
1518
1617
|
}
|
|
1618
|
+
/**
|
|
1619
|
+
* Compute effective inputs for a node by merging real inputs with defaults.
|
|
1620
|
+
* This is a shared utility used by both NodeExecutor and runtime validators.
|
|
1621
|
+
*
|
|
1622
|
+
* @param nodeId - The node ID to compute effective inputs for
|
|
1623
|
+
* @param graph - Graph component to access node and handle information
|
|
1624
|
+
* @param registry - Registry to access node type descriptors and defaults
|
|
1625
|
+
* @returns Record of effective input values (real inputs merged with defaults)
|
|
1626
|
+
*/
|
|
1627
|
+
function getEffectiveInputs(nodeId, graph, registry) {
|
|
1628
|
+
const node = graph.getNode(nodeId);
|
|
1629
|
+
if (!node)
|
|
1630
|
+
return {};
|
|
1631
|
+
const desc = registry.nodes.get(node.typeId);
|
|
1632
|
+
if (!desc)
|
|
1633
|
+
return {};
|
|
1634
|
+
const resolved = graph.getResolvedHandles(nodeId);
|
|
1635
|
+
const regDefaults = desc.inputDefaults ?? {};
|
|
1636
|
+
const dynDefaults = resolved?.inputDefaults ?? {};
|
|
1637
|
+
// Identify which handles are dynamically resolved (not in registry statics)
|
|
1638
|
+
const staticHandles = new Set(Object.keys(desc.inputs ?? {}));
|
|
1639
|
+
const dynamicHandles = new Set(Object.keys(resolved?.inputs ?? {}).filter((h) => !staticHandles.has(h)));
|
|
1640
|
+
// Precedence: dynamic > registry
|
|
1641
|
+
const mergedDefaults = {
|
|
1642
|
+
...regDefaults,
|
|
1643
|
+
...dynDefaults,
|
|
1644
|
+
};
|
|
1645
|
+
// Start with real inputs only (no defaults)
|
|
1646
|
+
const effective = { ...node.inputs };
|
|
1647
|
+
// Build set of inbound handles (wired inputs)
|
|
1648
|
+
const inboundEdges = graph.getInboundEdges(nodeId);
|
|
1649
|
+
const inbound = new Set(inboundEdges.map((e) => e.target.handle));
|
|
1650
|
+
// Apply defaults only for:
|
|
1651
|
+
// 1. Unbound handles that have no explicit value
|
|
1652
|
+
// 2. Static handles (not dynamically resolved)
|
|
1653
|
+
for (const [handle, defaultValue] of Object.entries(mergedDefaults)) {
|
|
1654
|
+
if (defaultValue === undefined)
|
|
1655
|
+
continue;
|
|
1656
|
+
if (inbound.has(handle))
|
|
1657
|
+
continue; // Don't override wired inputs
|
|
1658
|
+
if (effective[handle] !== undefined)
|
|
1659
|
+
continue; // Already has value
|
|
1660
|
+
if (dynamicHandles.has(handle))
|
|
1661
|
+
continue; // Skip defaults for dynamic handles
|
|
1662
|
+
// Clone to avoid shared references
|
|
1663
|
+
effective[handle] = structuredClone(defaultValue);
|
|
1664
|
+
}
|
|
1665
|
+
return effective;
|
|
1666
|
+
}
|
|
1519
1667
|
|
|
1520
1668
|
/**
|
|
1521
1669
|
* HandleResolver component - manages dynamic handle resolution
|
|
@@ -1615,12 +1763,11 @@ class HandleResolver {
|
|
|
1615
1763
|
const dstNode = this.graph.getNode(e.target.nodeId);
|
|
1616
1764
|
const oldDstDeclared = e.dstDeclared;
|
|
1617
1765
|
// Extract edge types using shared helper (handles both source and target updates)
|
|
1618
|
-
const { srcDeclared, dstDeclared
|
|
1766
|
+
const { srcDeclared, dstDeclared } = extractEdgeTypes(e.source.nodeId, e.source.handle, e.target.nodeId, e.target.handle, resolvedByNode);
|
|
1619
1767
|
// Update converters
|
|
1620
1768
|
const conv = buildEdgeConverters(srcDeclared, dstDeclared, registry, `updateNodeHandles: ${srcNode?.typeId || ""}.${e.source.nodeId}.${e.source.handle} -> ${dstNode?.typeId || ""}.${e.target.nodeId}.${e.target.handle}`);
|
|
1621
1769
|
// Update edge properties via Graph
|
|
1622
1770
|
this.graph.updateEdgeProperties(e.id, {
|
|
1623
|
-
effectiveTypeId: !e.typeId ? effectiveTypeId : undefined,
|
|
1624
1771
|
dstDeclared,
|
|
1625
1772
|
srcUnionTypes: Array.isArray(srcDeclared)
|
|
1626
1773
|
? [...srcDeclared]
|
|
@@ -2153,47 +2300,10 @@ class NodeExecutor {
|
|
|
2153
2300
|
* Compute effective inputs for a node by merging real inputs with defaults
|
|
2154
2301
|
*/
|
|
2155
2302
|
getEffectiveInputs(nodeId) {
|
|
2156
|
-
const node = this.graph.getNode(nodeId);
|
|
2157
|
-
if (!node)
|
|
2158
|
-
return {};
|
|
2159
2303
|
const registry = this.graph.getRegistry();
|
|
2160
2304
|
if (!registry)
|
|
2161
2305
|
return {};
|
|
2162
|
-
|
|
2163
|
-
if (!desc)
|
|
2164
|
-
return {};
|
|
2165
|
-
const resolved = this.graph.getResolvedHandles(nodeId);
|
|
2166
|
-
const regDefaults = desc.inputDefaults ?? {};
|
|
2167
|
-
const dynDefaults = resolved?.inputDefaults ?? {};
|
|
2168
|
-
// Identify which handles are dynamically resolved (not in registry statics)
|
|
2169
|
-
const staticHandles = new Set(Object.keys(desc.inputs ?? {}));
|
|
2170
|
-
const dynamicHandles = new Set(Object.keys(resolved?.inputs ?? {}).filter((h) => !staticHandles.has(h)));
|
|
2171
|
-
// Precedence: dynamic > registry
|
|
2172
|
-
const mergedDefaults = {
|
|
2173
|
-
...regDefaults,
|
|
2174
|
-
...dynDefaults,
|
|
2175
|
-
};
|
|
2176
|
-
// Start with real inputs only (no defaults)
|
|
2177
|
-
const effective = { ...node.inputs };
|
|
2178
|
-
// Build set of inbound handles (wired inputs)
|
|
2179
|
-
const inboundEdges = this.graph.getInboundEdges(nodeId);
|
|
2180
|
-
const inbound = new Set(inboundEdges.map((e) => e.target.handle));
|
|
2181
|
-
// Apply defaults only for:
|
|
2182
|
-
// 1. Unbound handles that have no explicit value
|
|
2183
|
-
// 2. Static handles (not dynamically resolved)
|
|
2184
|
-
for (const [handle, defaultValue] of Object.entries(mergedDefaults)) {
|
|
2185
|
-
if (defaultValue === undefined)
|
|
2186
|
-
continue;
|
|
2187
|
-
if (inbound.has(handle))
|
|
2188
|
-
continue; // Don't override wired inputs
|
|
2189
|
-
if (effective[handle] !== undefined)
|
|
2190
|
-
continue; // Already has value
|
|
2191
|
-
if (dynamicHandles.has(handle))
|
|
2192
|
-
continue; // Skip defaults for dynamic handles
|
|
2193
|
-
// Clone to avoid shared references
|
|
2194
|
-
effective[handle] = structuredClone(defaultValue);
|
|
2195
|
-
}
|
|
2196
|
-
return effective;
|
|
2306
|
+
return getEffectiveInputs(nodeId, this.graph, registry);
|
|
2197
2307
|
}
|
|
2198
2308
|
/**
|
|
2199
2309
|
* Create an execution context for a node
|
|
@@ -2299,6 +2409,20 @@ class NodeExecutor {
|
|
|
2299
2409
|
// Early validation for auto-mode paused state
|
|
2300
2410
|
if (this.runtime.isPaused())
|
|
2301
2411
|
return;
|
|
2412
|
+
// Check runtime validators (check current state, not just graph definition)
|
|
2413
|
+
const runtimeValidationError = this.runtime.hasRuntimeValidationBlock(nodeId);
|
|
2414
|
+
if (runtimeValidationError) {
|
|
2415
|
+
this.eventEmitter.emit("error", {
|
|
2416
|
+
kind: "system",
|
|
2417
|
+
message: runtimeValidationError.message,
|
|
2418
|
+
code: runtimeValidationError.code || "RUNTIME_VALIDATION_BLOCKED",
|
|
2419
|
+
details: {
|
|
2420
|
+
nodeId,
|
|
2421
|
+
...runtimeValidationError.details,
|
|
2422
|
+
},
|
|
2423
|
+
});
|
|
2424
|
+
return;
|
|
2425
|
+
}
|
|
2302
2426
|
// Attach run-context IDs if provided - do this BEFORE checking for pending resolution
|
|
2303
2427
|
// so that handle resolution can track these run contexts
|
|
2304
2428
|
if (runContextIds) {
|
|
@@ -2757,6 +2881,61 @@ class NodeExecutor {
|
|
|
2757
2881
|
}
|
|
2758
2882
|
}
|
|
2759
2883
|
|
|
2884
|
+
/**
|
|
2885
|
+
* RuntimeValidatorManager component - manages runtime validators
|
|
2886
|
+
*/
|
|
2887
|
+
class RuntimeValidatorManager {
|
|
2888
|
+
constructor(graph, registry) {
|
|
2889
|
+
this.graph = graph;
|
|
2890
|
+
this.registry = registry;
|
|
2891
|
+
this.validators = [];
|
|
2892
|
+
}
|
|
2893
|
+
/**
|
|
2894
|
+
* Set the registry (called when registry changes)
|
|
2895
|
+
*/
|
|
2896
|
+
setRegistry(registry) {
|
|
2897
|
+
this.registry = registry;
|
|
2898
|
+
}
|
|
2899
|
+
/**
|
|
2900
|
+
* Register a runtime validator that will be called before node execution.
|
|
2901
|
+
* Validators are called in registration order - if any returns true, execution is blocked.
|
|
2902
|
+
*/
|
|
2903
|
+
registerValidator(validator) {
|
|
2904
|
+
this.validators.push(validator);
|
|
2905
|
+
}
|
|
2906
|
+
/**
|
|
2907
|
+
* Unregister a runtime validator.
|
|
2908
|
+
*/
|
|
2909
|
+
unregisterValidator(validator) {
|
|
2910
|
+
const index = this.validators.indexOf(validator);
|
|
2911
|
+
if (index >= 0) {
|
|
2912
|
+
this.validators.splice(index, 1);
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
/**
|
|
2916
|
+
* Check if any runtime validator blocks execution for this node.
|
|
2917
|
+
* Returns RuntimeValidationError if execution should be blocked, null otherwise.
|
|
2918
|
+
*/
|
|
2919
|
+
hasBlock(nodeId) {
|
|
2920
|
+
if (!this.registry)
|
|
2921
|
+
return null;
|
|
2922
|
+
for (const validator of this.validators) {
|
|
2923
|
+
try {
|
|
2924
|
+
const result = validator(nodeId, this.graph, this.registry);
|
|
2925
|
+
if (result !== false) {
|
|
2926
|
+
// Validator returned an error object
|
|
2927
|
+
return result;
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
catch (err) {
|
|
2931
|
+
// Don't let validator errors break execution - log and continue
|
|
2932
|
+
console.error(`Runtime validator error for node ${nodeId}:`, err);
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
return null;
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2760
2939
|
// Types are now imported from components/types.ts (re-exported above)
|
|
2761
2940
|
class GraphRuntime {
|
|
2762
2941
|
constructor() {
|
|
@@ -2773,6 +2952,8 @@ class GraphRuntime {
|
|
|
2773
2952
|
this.edgePropagator = new EdgePropagator(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this);
|
|
2774
2953
|
// Create NodeExecutor with EdgePropagator and HandleResolver
|
|
2775
2954
|
this.nodeExecutor = new NodeExecutor(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this, this);
|
|
2955
|
+
// Create RuntimeValidatorManager
|
|
2956
|
+
this.runtimeValidatorManager = new RuntimeValidatorManager(this.graph);
|
|
2776
2957
|
}
|
|
2777
2958
|
static create(def, registry, opts) {
|
|
2778
2959
|
const gr = new GraphRuntime();
|
|
@@ -2784,6 +2965,7 @@ class GraphRuntime {
|
|
|
2784
2965
|
gr.handleResolver.setRegistry(registry);
|
|
2785
2966
|
gr.handleResolver.setEnvironment(gr.environment);
|
|
2786
2967
|
gr.nodeExecutor.setEnvironment(gr.environment);
|
|
2968
|
+
gr.runtimeValidatorManager.setRegistry(registry);
|
|
2787
2969
|
// Precompute per-node resolved handles (use def-provided overrides; do not compute dynamically here)
|
|
2788
2970
|
const initial = gr.isPaused()
|
|
2789
2971
|
? {
|
|
@@ -3001,6 +3183,26 @@ class GraphRuntime {
|
|
|
3001
3183
|
this.handleResolver.scheduleRecomputeHandles(nodeId);
|
|
3002
3184
|
}
|
|
3003
3185
|
}
|
|
3186
|
+
/**
|
|
3187
|
+
* Register a runtime validator that will be called before node execution.
|
|
3188
|
+
* Validators are called in registration order - if any returns true, execution is blocked.
|
|
3189
|
+
*/
|
|
3190
|
+
registerRuntimeValidator(validator) {
|
|
3191
|
+
this.runtimeValidatorManager.registerValidator(validator);
|
|
3192
|
+
}
|
|
3193
|
+
/**
|
|
3194
|
+
* Unregister a runtime validator.
|
|
3195
|
+
*/
|
|
3196
|
+
unregisterRuntimeValidator(validator) {
|
|
3197
|
+
this.runtimeValidatorManager.unregisterValidator(validator);
|
|
3198
|
+
}
|
|
3199
|
+
/**
|
|
3200
|
+
* Check if any runtime validator blocks execution for this node.
|
|
3201
|
+
* Returns RuntimeValidationError if execution should be blocked, null otherwise.
|
|
3202
|
+
*/
|
|
3203
|
+
hasRuntimeValidationBlock(nodeId) {
|
|
3204
|
+
return this.runtimeValidatorManager.hasBlock(nodeId);
|
|
3205
|
+
}
|
|
3004
3206
|
getGraphDef() {
|
|
3005
3207
|
const nodes = [];
|
|
3006
3208
|
this.graph.forEachNode((n) => {
|
|
@@ -3466,20 +3668,12 @@ class GraphBuilder {
|
|
|
3466
3668
|
return { inputs, outputs };
|
|
3467
3669
|
};
|
|
3468
3670
|
const normOut = (decl) => Array.isArray(decl) ? decl : decl ? [decl] : [];
|
|
3469
|
-
const inferEdgeType = (srcDeclared, dstDeclared, explicit) => {
|
|
3470
|
-
if (explicit)
|
|
3471
|
-
return explicit;
|
|
3472
|
-
if (Array.isArray(srcDeclared) && dstDeclared)
|
|
3473
|
-
return dstDeclared;
|
|
3474
|
-
if (srcDeclared)
|
|
3475
|
-
return Array.isArray(srcDeclared) ? srcDeclared[0] : srcDeclared;
|
|
3476
|
-
return undefined;
|
|
3477
|
-
};
|
|
3478
3671
|
const canFlow = (from, to) => {
|
|
3479
3672
|
if (!to || !from)
|
|
3480
3673
|
return true;
|
|
3481
|
-
const
|
|
3482
|
-
|
|
3674
|
+
const srcTypes = Array.isArray(from) ? from : [from];
|
|
3675
|
+
const dstTypes = Array.isArray(to) ? to : [to];
|
|
3676
|
+
return srcTypes.some((s) => dstTypes.some((t) => s === t || !!this.registry.canCoerce(s, t)));
|
|
3483
3677
|
};
|
|
3484
3678
|
// Helper to validate enum value
|
|
3485
3679
|
const validateEnumValue = (typeId, value, nodeId, handle) => {
|
|
@@ -3590,37 +3784,29 @@ class GraphBuilder {
|
|
|
3590
3784
|
};
|
|
3591
3785
|
const dstEff = effByNodeId.get(e.target.nodeId) || {
|
|
3592
3786
|
inputs: {}};
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
// Effective edge type
|
|
3600
|
-
const effectiveTypeId = inferEdgeType(_srcDeclared, _dstDeclared, e.typeId);
|
|
3601
|
-
const type = effectiveTypeId
|
|
3602
|
-
? this.registry.types.get(effectiveTypeId)
|
|
3603
|
-
: undefined;
|
|
3604
|
-
if (!type) {
|
|
3605
|
-
pushIssue("error", "TYPE_MISSING", `Edge ${e.id} type missing or unknown`, {
|
|
3606
|
-
edgeId: e.id,
|
|
3607
|
-
});
|
|
3787
|
+
// Validate explicit type if provided
|
|
3788
|
+
if (e.typeId) {
|
|
3789
|
+
const type = this.registry.types.get(e.typeId);
|
|
3790
|
+
if (!type) {
|
|
3791
|
+
pushIssue("error", "TYPE_MISSING", `Edge ${e.id} explicit type ${e.typeId} is missing or unknown`, { edgeId: e.id });
|
|
3792
|
+
}
|
|
3608
3793
|
}
|
|
3609
3794
|
if (srcNode) {
|
|
3610
3795
|
if (!(e.source.handle in srcEff.outputs)) {
|
|
3611
3796
|
pushIssue("error", "OUTPUT_MISSING", `Edge ${e.id} source output ${e.source.handle} missing on ${srcNode.typeId}`, { edgeId: e.id, nodeId: srcNode.nodeId, output: e.source.handle });
|
|
3612
3797
|
}
|
|
3613
3798
|
const declaredArr = normOut(srcEff.outputs[e.source.handle]);
|
|
3614
|
-
if (declaredArr.length > 0
|
|
3615
|
-
|
|
3616
|
-
!canFlow(declaredArr,
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3799
|
+
if (declaredArr.length > 0) {
|
|
3800
|
+
// Check if explicit type matches source output
|
|
3801
|
+
if (e.typeId && !canFlow(declaredArr, e.typeId)) {
|
|
3802
|
+
pushIssue("error", "TYPE_MISMATCH_OUTPUT", `Edge ${e.id} explicit type ${e.typeId} mismatches source output ${srcNode.typeId}.${e.source.handle} (${declaredArr.join("|")}) and no coercion exists`, {
|
|
3803
|
+
edgeId: e.id,
|
|
3804
|
+
nodeId: srcNode.nodeId,
|
|
3805
|
+
output: e.source.handle,
|
|
3806
|
+
declared: declaredArr.join("|"),
|
|
3807
|
+
typeId: e.typeId,
|
|
3808
|
+
});
|
|
3809
|
+
}
|
|
3624
3810
|
}
|
|
3625
3811
|
}
|
|
3626
3812
|
if (dstNode) {
|
|
@@ -3631,30 +3817,30 @@ class GraphBuilder {
|
|
|
3631
3817
|
if (isInputPrivate(dstEff.inputs, e.target.handle)) {
|
|
3632
3818
|
pushIssue("error", "INPUT_PRIVATE", `Edge ${e.id} targets private input ${dstNode.typeId}.${e.target.handle}`, { edgeId: e.id, nodeId: dstNode.nodeId, input: e.target.handle });
|
|
3633
3819
|
}
|
|
3634
|
-
const declaredIn =
|
|
3635
|
-
|
|
3820
|
+
const declaredIn = getInputDeclaredTypes(dstEff.inputs, e.target.handle);
|
|
3821
|
+
const declaredInArr = normOut(declaredIn);
|
|
3822
|
+
if (declaredInArr.length > 0) {
|
|
3636
3823
|
if (srcNode) {
|
|
3637
3824
|
const srcDeclared = srcEff.outputs[e.source.handle];
|
|
3638
|
-
const srcArr = normOut(srcDeclared)
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
if (!canFlow(srcArr, declaredIn)) {
|
|
3642
|
-
pushIssue("error", "TYPE_MISMATCH_INPUT", `Edge ${e.id} output type ${srcArr.join("|")} not convertible to target input ${dstNode.typeId}.${e.target.handle} (${declaredIn})`, {
|
|
3825
|
+
const srcArr = normOut(srcDeclared);
|
|
3826
|
+
if (srcArr.length > 0 && !canFlow(srcArr, declaredInArr)) {
|
|
3827
|
+
pushIssue("error", "TYPE_MISMATCH_INPUT", `Edge ${e.id} output type ${srcArr.join("|")} not convertible to target input ${dstNode.typeId}.${e.target.handle} (${declaredInArr.join("|")})`, {
|
|
3643
3828
|
edgeId: e.id,
|
|
3644
3829
|
nodeId: dstNode.nodeId,
|
|
3645
3830
|
input: e.target.handle,
|
|
3646
|
-
declared:
|
|
3647
|
-
|
|
3831
|
+
declared: declaredInArr.join("|"),
|
|
3832
|
+
typeId: srcArr.join("|"),
|
|
3648
3833
|
});
|
|
3649
3834
|
}
|
|
3650
3835
|
}
|
|
3651
|
-
else if (!canFlow(
|
|
3652
|
-
|
|
3836
|
+
else if (e.typeId && !canFlow([e.typeId], declaredInArr)) {
|
|
3837
|
+
// External source with explicit type
|
|
3838
|
+
pushIssue("error", "TYPE_MISMATCH_INPUT", `Edge ${e.id} explicit type ${e.typeId} mismatches target input ${dstNode.typeId}.${e.target.handle} (${declaredInArr.join("|")}) and no coercion exists`, {
|
|
3653
3839
|
edgeId: e.id,
|
|
3654
3840
|
nodeId: dstNode.nodeId,
|
|
3655
3841
|
input: e.target.handle,
|
|
3656
|
-
declared:
|
|
3657
|
-
|
|
3842
|
+
declared: declaredInArr.join("|"),
|
|
3843
|
+
typeId: e.typeId,
|
|
3658
3844
|
});
|
|
3659
3845
|
}
|
|
3660
3846
|
}
|
|
@@ -5590,9 +5776,17 @@ function buildTypeMaps(def) {
|
|
|
5590
5776
|
const nodeOutputTypes = new Map();
|
|
5591
5777
|
if (node.resolvedHandles?.inputs) {
|
|
5592
5778
|
for (const [handleId, handleDesc] of Object.entries(node.resolvedHandles.inputs)) {
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5779
|
+
let typeId;
|
|
5780
|
+
if (typeof handleDesc === "string") {
|
|
5781
|
+
typeId = handleDesc;
|
|
5782
|
+
}
|
|
5783
|
+
else if (Array.isArray(handleDesc)) {
|
|
5784
|
+
typeId = handleDesc[0]; // Use first type for type map (backward compat)
|
|
5785
|
+
}
|
|
5786
|
+
else {
|
|
5787
|
+
const descTypeId = handleDesc.typeId;
|
|
5788
|
+
typeId = Array.isArray(descTypeId) ? descTypeId[0] : descTypeId;
|
|
5789
|
+
}
|
|
5596
5790
|
if (typeId)
|
|
5597
5791
|
nodeInputTypes.set(handleId, typeId);
|
|
5598
5792
|
}
|
|
@@ -5615,9 +5809,17 @@ function buildTypeMaps(def) {
|
|
|
5615
5809
|
if (!nodeInputTypes.has(handleId) && node.resolvedHandles?.inputs) {
|
|
5616
5810
|
const inputDesc = node.resolvedHandles.inputs[handleId];
|
|
5617
5811
|
if (inputDesc) {
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5812
|
+
let typeId;
|
|
5813
|
+
if (typeof inputDesc === "string") {
|
|
5814
|
+
typeId = inputDesc;
|
|
5815
|
+
}
|
|
5816
|
+
else if (Array.isArray(inputDesc)) {
|
|
5817
|
+
typeId = inputDesc[0]; // Use first type for type map (backward compat)
|
|
5818
|
+
}
|
|
5819
|
+
else {
|
|
5820
|
+
const descTypeId = inputDesc.typeId;
|
|
5821
|
+
typeId = Array.isArray(descTypeId) ? descTypeId[0] : descTypeId;
|
|
5822
|
+
}
|
|
5621
5823
|
if (typeId)
|
|
5622
5824
|
nodeInputTypes.set(handleId, typeId);
|
|
5623
5825
|
}
|
|
@@ -6053,5 +6255,5 @@ function buildValueConverter(config) {
|
|
|
6053
6255
|
};
|
|
6054
6256
|
}
|
|
6055
6257
|
|
|
6056
|
-
export { BaseCompareOperation, BaseLogicOperation, BaseMathOperation, CompositeCategory, ComputeCategory, GraphBuilder, GraphRuntime, LevelLogger, LocalEngine, Registry, buildValueConverter, computeGraphCenter, convertSnapshot, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createSimpleGraphDef, createSimpleGraphRegistry, createValidationGraphDef, createValidationGraphRegistry, findMatchingPaths, generateId, getInputHandleMetadata, getInputTypeId, getTypedOutputTypeId, getTypedOutputValue, getValueAtPath, installLogging, isInputPrivate, isTypedOutput, mergeInputHandleDescriptors, mergeRuntimeState, mergeSnapshots, offsetImportedPositions, parseJsonPath, registerDelayNode, registerProgressNodes, setValueAtPath, setValueAtPathWithCreation, typed };
|
|
6258
|
+
export { BaseCompareOperation, BaseLogicOperation, BaseMathOperation, CompositeCategory, ComputeCategory, Graph, GraphBuilder, GraphRuntime, LevelLogger, LocalEngine, Registry, buildValueConverter, computeGraphCenter, convertSnapshot, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createSimpleGraphDef, createSimpleGraphRegistry, createValidationGraphDef, createValidationGraphRegistry, findMatchingPaths, generateId, getEffectiveInputs, getInputDeclaredTypes, getInputHandleMetadata, getInputTypeId, getTypedOutputTypeId, getTypedOutputValue, getValueAtPath, installLogging, isInputPrivate, isTypedOutput, mergeInputHandleDescriptors, mergeRuntimeState, mergeSnapshots, offsetImportedPositions, parseJsonPath, registerDelayNode, registerProgressNodes, setValueAtPath, setValueAtPathWithCreation, typed };
|
|
6057
6259
|
//# sourceMappingURL=index.js.map
|