@bian-womp/spark-graph 0.3.1 → 0.3.2
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 +74 -145
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/index.d.ts +1 -1
- package/lib/cjs/src/index.d.ts.map +1 -1
- package/lib/cjs/src/runtime/GraphRuntime.d.ts +6 -14
- package/lib/cjs/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/lib/cjs/src/runtime/{UnifiedEngine.d.ts → LocalEngine.d.ts} +18 -5
- package/lib/cjs/src/runtime/LocalEngine.d.ts.map +1 -0
- package/lib/cjs/src/runtime/components/ExecutionScheduler.d.ts.map +1 -1
- package/lib/cjs/src/runtime/components/ValuePropagator.d.ts.map +1 -1
- package/lib/esm/index.js +74 -145
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/index.d.ts +1 -1
- package/lib/esm/src/index.d.ts.map +1 -1
- package/lib/esm/src/runtime/GraphRuntime.d.ts +6 -14
- package/lib/esm/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/lib/esm/src/runtime/{UnifiedEngine.d.ts → LocalEngine.d.ts} +18 -5
- package/lib/esm/src/runtime/LocalEngine.d.ts.map +1 -0
- package/lib/esm/src/runtime/components/ExecutionScheduler.d.ts.map +1 -1
- package/lib/esm/src/runtime/components/ValuePropagator.d.ts.map +1 -1
- package/package.json +2 -2
- package/lib/cjs/src/runtime/AbstractEngine.d.ts +0 -28
- package/lib/cjs/src/runtime/AbstractEngine.d.ts.map +0 -1
- package/lib/cjs/src/runtime/UnifiedEngine.d.ts.map +0 -1
- package/lib/esm/src/runtime/AbstractEngine.d.ts +0 -28
- package/lib/esm/src/runtime/AbstractEngine.d.ts.map +0 -1
- package/lib/esm/src/runtime/UnifiedEngine.d.ts.map +0 -1
package/lib/esm/index.js
CHANGED
|
@@ -1068,10 +1068,13 @@ class ValuePropagator {
|
|
|
1068
1068
|
}
|
|
1069
1069
|
}
|
|
1070
1070
|
}
|
|
1071
|
-
// Schedule downstream execution if propagation is enabled
|
|
1072
|
-
|
|
1071
|
+
// Schedule downstream execution if propagation is enabled.
|
|
1072
|
+
// In manual mode we still allow scheduling for run-context-aware runs.
|
|
1073
|
+
const paused = this.runtimeCoordinator.isPaused();
|
|
1074
|
+
const canSchedule = (!paused || isRunContextAware) &&
|
|
1073
1075
|
shouldPropagate &&
|
|
1074
|
-
this.executionScheduler.allInboundHaveValue(e.target.nodeId)
|
|
1076
|
+
this.executionScheduler.allInboundHaveValue(e.target.nodeId);
|
|
1077
|
+
if (canSchedule) {
|
|
1075
1078
|
if (isRunContextAware && effectiveRunContexts) {
|
|
1076
1079
|
this.executionScheduler.scheduleInputsChangedWithRunContexts(e.target.nodeId, effectiveRunContexts);
|
|
1077
1080
|
}
|
|
@@ -1355,7 +1358,8 @@ class ExecutionScheduler {
|
|
|
1355
1358
|
const node = this.graphStructure.getNode(nodeId);
|
|
1356
1359
|
if (!node)
|
|
1357
1360
|
return;
|
|
1358
|
-
|
|
1361
|
+
// Block only auto-mode scheduling while paused; allow run-context runs
|
|
1362
|
+
if (!runContextIds && this.runtimeCoordinator.isPaused())
|
|
1359
1363
|
return;
|
|
1360
1364
|
// If run-context IDs are provided, attach them to the node
|
|
1361
1365
|
if (runContextIds) {
|
|
@@ -1652,6 +1656,8 @@ class GraphRuntime {
|
|
|
1652
1656
|
// State
|
|
1653
1657
|
this.paused = false;
|
|
1654
1658
|
this.environment = {};
|
|
1659
|
+
this.runMode = null;
|
|
1660
|
+
this.pauseRefCount = 0;
|
|
1655
1661
|
// Initialize components
|
|
1656
1662
|
this.graphStructure = new GraphStructure();
|
|
1657
1663
|
this.eventEmitter = new EventEmitter();
|
|
@@ -1798,13 +1804,16 @@ class GraphRuntime {
|
|
|
1798
1804
|
anyChanged = true;
|
|
1799
1805
|
}
|
|
1800
1806
|
}
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1807
|
+
// In auto mode, input updates can trigger execution; in manual mode they never should.
|
|
1808
|
+
const isAutoMode = this.runMode === "auto" || this.runMode === null;
|
|
1809
|
+
const canAutoSchedule = !this.paused && isAutoMode;
|
|
1810
|
+
if (canAutoSchedule) {
|
|
1811
|
+
if (anyChanged && this.executionScheduler.allInboundHaveValue(nodeId)) {
|
|
1804
1812
|
this.executionScheduler.scheduleInputsChangedInternal(nodeId);
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
if (anyChanged) {
|
|
1816
|
+
this.handleResolver.scheduleRecomputeHandles(nodeId);
|
|
1808
1817
|
}
|
|
1809
1818
|
}
|
|
1810
1819
|
getOutput(nodeId, output) {
|
|
@@ -1818,14 +1827,12 @@ class GraphRuntime {
|
|
|
1818
1827
|
return;
|
|
1819
1828
|
const oldResolved = this.graphStructure.getResolvedHandles(nodeId);
|
|
1820
1829
|
this.graphStructure.setResolvedHandles(nodeId, handles);
|
|
1821
|
-
// Clear outputs that are no longer valid handles
|
|
1822
1830
|
const oldOutputs = oldResolved?.outputs ?? {};
|
|
1823
1831
|
const newOutputs = handles.outputs ?? {};
|
|
1824
1832
|
const oldOutputHandles = new Set(Object.keys(oldOutputs));
|
|
1825
1833
|
const newOutputHandles = new Set(Object.keys(newOutputs));
|
|
1826
1834
|
for (const handle of oldOutputHandles) {
|
|
1827
1835
|
if (!newOutputHandles.has(handle)) {
|
|
1828
|
-
// Output handle was removed - clear it and emit undefined to invalidate downstream
|
|
1829
1836
|
delete node.outputs[handle];
|
|
1830
1837
|
this.eventEmitter.emit("value", {
|
|
1831
1838
|
nodeId,
|
|
@@ -1836,19 +1843,17 @@ class GraphRuntime {
|
|
|
1836
1843
|
}
|
|
1837
1844
|
}
|
|
1838
1845
|
const edges = this.graphStructure.getEdges();
|
|
1839
|
-
// Recompute edge converter/type for edges where this node is source or target
|
|
1840
1846
|
for (const e of edges) {
|
|
1841
1847
|
const srcNode = this.graphStructure.getNode(e.source.nodeId);
|
|
1842
1848
|
const dstNode = this.graphStructure.getNode(e.target.nodeId);
|
|
1843
|
-
let srcDeclared = e.effectiveTypeId;
|
|
1849
|
+
let srcDeclared = e.effectiveTypeId;
|
|
1844
1850
|
let dstDeclared = e.dstDeclared;
|
|
1845
|
-
const oldDstDeclared = dstDeclared;
|
|
1851
|
+
const oldDstDeclared = dstDeclared;
|
|
1846
1852
|
if (e.source.nodeId === nodeId) {
|
|
1847
1853
|
const resolved = this.graphStructure.getResolvedHandles(nodeId);
|
|
1848
1854
|
srcDeclared = resolved
|
|
1849
1855
|
? resolved.outputs[e.source.handle]
|
|
1850
1856
|
: srcDeclared;
|
|
1851
|
-
// Update effectiveTypeId if original wasn't explicit
|
|
1852
1857
|
if (!e.typeId) {
|
|
1853
1858
|
e.effectiveTypeId = Array.isArray(srcDeclared)
|
|
1854
1859
|
? srcDeclared?.[0] ?? "untyped"
|
|
@@ -1865,7 +1870,6 @@ class GraphRuntime {
|
|
|
1865
1870
|
const conv = GraphStructure.buildEdgeConverters(srcDeclared, dstDeclared, registry, `updateNodeHandles: ${srcNode?.typeId || ""}.${e.source.nodeId}.${e.source.handle} -> ${dstNode?.typeId || ""}.${e.target.nodeId}.${e.target.handle}`);
|
|
1866
1871
|
e.convert = conv.convert;
|
|
1867
1872
|
e.convertAsync = conv.convertAsync;
|
|
1868
|
-
// If target handle was just resolved (was undefined, now has a type), re-propagate values
|
|
1869
1873
|
if (e.target.nodeId === nodeId &&
|
|
1870
1874
|
oldDstDeclared === undefined &&
|
|
1871
1875
|
dstDeclared !== undefined) {
|
|
@@ -1873,8 +1877,6 @@ class GraphRuntime {
|
|
|
1873
1877
|
if (srcNode) {
|
|
1874
1878
|
const srcValue = srcNode.outputs[e.source.handle];
|
|
1875
1879
|
if (srcValue !== undefined) {
|
|
1876
|
-
// Re-propagate through the now-resolved edge converter
|
|
1877
|
-
// Preserve run-contexts if source node has them
|
|
1878
1880
|
const runContextIds = srcNode.activeRunContexts.size > 0
|
|
1879
1881
|
? new Set(srcNode.activeRunContexts)
|
|
1880
1882
|
: undefined;
|
|
@@ -1883,11 +1885,9 @@ class GraphRuntime {
|
|
|
1883
1885
|
}
|
|
1884
1886
|
}
|
|
1885
1887
|
}
|
|
1886
|
-
// Re-emit only valid outputs (after clearing removed ones)
|
|
1887
1888
|
this.valuePropagator.reemitNodeOutputs(nodeId);
|
|
1888
1889
|
}
|
|
1889
1890
|
launch(invalidate = false) {
|
|
1890
|
-
// call onActivated for nodes that implement it
|
|
1891
1891
|
for (const node of this.graphStructure.getNodes().values()) {
|
|
1892
1892
|
const effectiveInputs = this.executionScheduler.getEffectiveInputs(node.nodeId);
|
|
1893
1893
|
const ctrl = new AbortController();
|
|
@@ -1900,7 +1900,6 @@ class GraphRuntime {
|
|
|
1900
1900
|
node.runtime.onActivated?.();
|
|
1901
1901
|
}
|
|
1902
1902
|
if (invalidate) {
|
|
1903
|
-
// After activation, schedule nodes that have all inbound inputs present
|
|
1904
1903
|
for (const nodeId of this.graphStructure.getNodes().keys()) {
|
|
1905
1904
|
if (this.executionScheduler.allInboundHaveValue(nodeId))
|
|
1906
1905
|
this.executionScheduler.scheduleInputsChangedInternal(nodeId);
|
|
@@ -1911,11 +1910,9 @@ class GraphRuntime {
|
|
|
1911
1910
|
const node = this.graphStructure.getNode(nodeId);
|
|
1912
1911
|
if (!node)
|
|
1913
1912
|
return;
|
|
1914
|
-
// Forward event to node's onExternalEvent handler for custom actions
|
|
1915
1913
|
node.runtime.onExternalEvent?.(event, node.state);
|
|
1916
1914
|
}
|
|
1917
1915
|
dispose() {
|
|
1918
|
-
// Resolve all pending run-context promises before cleanup
|
|
1919
1916
|
this.runContextManager.resolveAll();
|
|
1920
1917
|
for (const node of this.graphStructure.getNodes().values()) {
|
|
1921
1918
|
node.runtime.onDeactivated?.();
|
|
@@ -1930,7 +1927,6 @@ class GraphRuntime {
|
|
|
1930
1927
|
getNodeIds() {
|
|
1931
1928
|
return Array.from(this.graphStructure.getNodes().keys());
|
|
1932
1929
|
}
|
|
1933
|
-
// Unsafe helpers for serializer: read-only accessors and hydration
|
|
1934
1930
|
getNodeData(nodeId) {
|
|
1935
1931
|
const node = this.graphStructure.getNode(nodeId);
|
|
1936
1932
|
if (!node)
|
|
@@ -1950,12 +1946,10 @@ class GraphRuntime {
|
|
|
1950
1946
|
this.environment = { ...env };
|
|
1951
1947
|
this.handleResolver.setEnvironment(this.environment);
|
|
1952
1948
|
this.executionScheduler.setEnvironment(this.environment);
|
|
1953
|
-
// Recompute dynamic handles for all nodes when environment changes
|
|
1954
1949
|
for (const nodeId of this.graphStructure.getNodes().keys()) {
|
|
1955
1950
|
this.handleResolver.scheduleRecomputeHandles(nodeId);
|
|
1956
1951
|
}
|
|
1957
1952
|
}
|
|
1958
|
-
// Export a GraphDefinition reflecting the current runtime view
|
|
1959
1953
|
getGraphDef() {
|
|
1960
1954
|
const nodes = Array.from(this.graphStructure.getNodes().values()).map((n) => {
|
|
1961
1955
|
const resolved = this.graphStructure.getResolvedHandles(n.nodeId);
|
|
@@ -1972,12 +1966,11 @@ class GraphRuntime {
|
|
|
1972
1966
|
id: e.id,
|
|
1973
1967
|
source: { nodeId: e.source.nodeId, handle: e.source.handle },
|
|
1974
1968
|
target: { nodeId: e.target.nodeId, handle: e.target.handle },
|
|
1975
|
-
typeId: e.typeId,
|
|
1969
|
+
typeId: e.typeId,
|
|
1976
1970
|
}));
|
|
1977
1971
|
return { nodes, edges };
|
|
1978
1972
|
}
|
|
1979
1973
|
async whenIdle() {
|
|
1980
|
-
// If we have active run-contexts, wait for all of them to complete
|
|
1981
1974
|
const allRunContexts = this.runContextManager.getAllRunContexts();
|
|
1982
1975
|
if (allRunContexts.size > 0) {
|
|
1983
1976
|
await new Promise((resolve) => {
|
|
@@ -2013,65 +2006,58 @@ class GraphRuntime {
|
|
|
2013
2006
|
setTimeout(check, 10);
|
|
2014
2007
|
});
|
|
2015
2008
|
}
|
|
2016
|
-
/**
|
|
2017
|
-
* Run this node and optionally all dynamically reachable downstream nodes as a run-context.
|
|
2018
|
-
* Includes nodes added later behind the same path (via re-emits).
|
|
2019
|
-
* @param startNodeId - The node to start execution from
|
|
2020
|
-
* @param options - Execution options
|
|
2021
|
-
* @param options.skipPropagateValues - If true, don't set inputs of linked nodes (default: false)
|
|
2022
|
-
* @param options.propagate - If false, don't schedule downstream nodes (default: true)
|
|
2023
|
-
*/
|
|
2024
2009
|
async runFromHereContext(startNodeId, options) {
|
|
2025
2010
|
const node = this.graphStructure.getNode(startNodeId);
|
|
2026
|
-
if (!node)
|
|
2027
|
-
// Node doesn't exist - resolve immediately
|
|
2011
|
+
if (!node)
|
|
2028
2012
|
return;
|
|
2029
|
-
}
|
|
2030
2013
|
const ctx = this.runContextManager.createRunContext(startNodeId, options);
|
|
2031
|
-
// Create promise that resolves when context finishes
|
|
2032
2014
|
const promise = new Promise((resolve) => {
|
|
2033
2015
|
ctx.resolve = resolve;
|
|
2034
2016
|
});
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
this.paused = false;
|
|
2039
|
-
}
|
|
2040
|
-
try {
|
|
2041
|
-
// Seed the start node with this run-context
|
|
2042
|
-
node.activeRunContexts.add(ctx.id);
|
|
2043
|
-
this.scheduleInputsChangedWithRunContexts(startNodeId, new Set([ctx.id]));
|
|
2044
|
-
await promise;
|
|
2045
|
-
}
|
|
2046
|
-
finally {
|
|
2047
|
-
// Restore pause state if it was paused and no other run-contexts are active
|
|
2048
|
-
if (wasPaused && this.runContextManager.getAllRunContexts().size === 0) {
|
|
2049
|
-
this.paused = true;
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2017
|
+
node.activeRunContexts.add(ctx.id);
|
|
2018
|
+
this.scheduleInputsChangedWithRunContexts(startNodeId, new Set([ctx.id]));
|
|
2019
|
+
await promise;
|
|
2052
2020
|
}
|
|
2053
|
-
/**
|
|
2054
|
-
* Schedule a node with run-context IDs attached
|
|
2055
|
-
*/
|
|
2056
2021
|
scheduleInputsChangedWithRunContexts(nodeId, runContextIds) {
|
|
2057
2022
|
const node = this.graphStructure.getNode(nodeId);
|
|
2058
2023
|
if (!node)
|
|
2059
2024
|
return;
|
|
2060
|
-
// Attach run-contexts to the node
|
|
2061
2025
|
for (const id of runContextIds) {
|
|
2062
2026
|
node.activeRunContexts.add(id);
|
|
2063
2027
|
}
|
|
2064
2028
|
this.executionScheduler.scheduleInputsChangedInternal(nodeId, runContextIds);
|
|
2065
2029
|
}
|
|
2066
|
-
|
|
2067
|
-
this.
|
|
2030
|
+
setRunMode(runMode) {
|
|
2031
|
+
this.runMode = runMode;
|
|
2032
|
+
this.updatePausedState();
|
|
2033
|
+
}
|
|
2034
|
+
requestPause() {
|
|
2035
|
+
this.pauseRefCount++;
|
|
2036
|
+
this.updatePausedState();
|
|
2037
|
+
let released = false;
|
|
2038
|
+
return () => {
|
|
2039
|
+
if (released)
|
|
2040
|
+
return;
|
|
2041
|
+
released = true;
|
|
2042
|
+
this.pauseRefCount--;
|
|
2043
|
+
this.updatePausedState();
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
updatePausedState() {
|
|
2047
|
+
if (this.pauseRefCount > 0) {
|
|
2048
|
+
this.paused = true;
|
|
2049
|
+
return;
|
|
2050
|
+
}
|
|
2051
|
+
if (this.runMode === "manual") {
|
|
2052
|
+
this.paused = true;
|
|
2053
|
+
}
|
|
2054
|
+
else if (this.runMode === "auto") {
|
|
2055
|
+
this.paused = false;
|
|
2056
|
+
}
|
|
2068
2057
|
}
|
|
2069
2058
|
isPaused() {
|
|
2070
2059
|
return this.paused;
|
|
2071
2060
|
}
|
|
2072
|
-
resume() {
|
|
2073
|
-
this.paused = false;
|
|
2074
|
-
}
|
|
2075
2061
|
invalidateDownstream(nodeId) {
|
|
2076
2062
|
this.valuePropagator.reemitNodeOutputs(nodeId);
|
|
2077
2063
|
}
|
|
@@ -2082,19 +2068,13 @@ class GraphRuntime {
|
|
|
2082
2068
|
this.executionScheduler.cancelNodeRuns(nodeIds);
|
|
2083
2069
|
}
|
|
2084
2070
|
copyOutputs(fromNodeId, toNodeId, options) {
|
|
2085
|
-
// Get outputs from source node
|
|
2086
2071
|
const fromNode = this.getNodeData(fromNodeId);
|
|
2087
2072
|
if (!fromNode?.outputs)
|
|
2088
2073
|
return;
|
|
2089
|
-
// Copy outputs to target node using hydrate
|
|
2090
|
-
// hydrate already pauses internally, so we don't need to handle dry option here
|
|
2091
|
-
// reemit: !options?.dry means don't propagate downstream if dry mode
|
|
2092
2074
|
this.hydrate({ outputs: { [toNodeId]: { ...fromNode.outputs } } }, { reemit: !options?.dry });
|
|
2093
2075
|
}
|
|
2094
|
-
// Hydrate inputs/outputs without triggering computation; optionally re-emit outputs downstream
|
|
2095
2076
|
hydrate(payload, opts) {
|
|
2096
|
-
const
|
|
2097
|
-
this.paused = true;
|
|
2077
|
+
const releasePause = this.requestPause();
|
|
2098
2078
|
try {
|
|
2099
2079
|
const ins = payload?.inputs || {};
|
|
2100
2080
|
for (const [nodeId, map] of Object.entries(ins)) {
|
|
@@ -2103,7 +2083,6 @@ class GraphRuntime {
|
|
|
2103
2083
|
continue;
|
|
2104
2084
|
for (const [h, v] of Object.entries(map || {})) {
|
|
2105
2085
|
node.inputs[h] = structuredClone(v);
|
|
2106
|
-
// emit input value event
|
|
2107
2086
|
this.eventEmitter.emit("value", {
|
|
2108
2087
|
nodeId,
|
|
2109
2088
|
handle: h,
|
|
@@ -2120,7 +2099,6 @@ class GraphRuntime {
|
|
|
2120
2099
|
continue;
|
|
2121
2100
|
for (const [h, v] of Object.entries(map || {})) {
|
|
2122
2101
|
node.outputs[h] = structuredClone(v);
|
|
2123
|
-
// emit output value event
|
|
2124
2102
|
this.eventEmitter.emit("value", {
|
|
2125
2103
|
nodeId,
|
|
2126
2104
|
handle: h,
|
|
@@ -2137,31 +2115,23 @@ class GraphRuntime {
|
|
|
2137
2115
|
}
|
|
2138
2116
|
}
|
|
2139
2117
|
finally {
|
|
2140
|
-
|
|
2118
|
+
releasePause();
|
|
2141
2119
|
}
|
|
2142
2120
|
}
|
|
2143
|
-
// Incrementally update nodes/edges to match new definition without full rebuild
|
|
2144
2121
|
update(def, registry) {
|
|
2145
|
-
// Handle node additions and removals
|
|
2146
2122
|
const desiredIds = new Set(def.nodes.map((n) => n.nodeId));
|
|
2147
2123
|
const currentIds = new Set(this.graphStructure.getNodes().keys());
|
|
2148
|
-
// Remove nodes not present
|
|
2149
2124
|
for (const nodeId of Array.from(currentIds)) {
|
|
2150
2125
|
if (!desiredIds.has(nodeId)) {
|
|
2151
2126
|
const node = this.graphStructure.getNode(nodeId);
|
|
2152
|
-
// Cancel all active runs and emit cancellation events
|
|
2153
2127
|
this.executionScheduler.cancelNodeActiveRuns(node, "node-deleted");
|
|
2154
|
-
|
|
2155
|
-
this.runContextManager.cancelNodeInRunContexts(nodeId,
|
|
2156
|
-
/* includeDownstream */ true, this.graphStructure.getEdges(), this.graphStructure.getNodes());
|
|
2157
|
-
// Check for run-context completion (they may finish if pending reaches 0)
|
|
2128
|
+
this.runContextManager.cancelNodeInRunContexts(nodeId, true, this.graphStructure.getEdges(), this.graphStructure.getNodes());
|
|
2158
2129
|
const allRunContexts = this.runContextManager.getAllRunContexts();
|
|
2159
2130
|
for (const ctx of Array.from(allRunContexts.values())) {
|
|
2160
2131
|
if (ctx.pending === 0) {
|
|
2161
2132
|
this.runContextManager.finishRunContext(ctx.id, this.graphStructure.getNodes());
|
|
2162
2133
|
}
|
|
2163
2134
|
}
|
|
2164
|
-
// Cleanup node resources
|
|
2165
2135
|
node.runtime.onDeactivated?.();
|
|
2166
2136
|
node.runtime.dispose?.();
|
|
2167
2137
|
node.lifecycle?.dispose?.({
|
|
@@ -2176,7 +2146,6 @@ class GraphRuntime {
|
|
|
2176
2146
|
for (const n of def.nodes) {
|
|
2177
2147
|
const existing = this.graphStructure.getNode(n.nodeId);
|
|
2178
2148
|
if (!existing) {
|
|
2179
|
-
// create new runtime node
|
|
2180
2149
|
const desc = registry.nodes.get(n.typeId);
|
|
2181
2150
|
if (!desc)
|
|
2182
2151
|
throw new Error(`Unknown node type: ${n.typeId}`);
|
|
@@ -2216,7 +2185,6 @@ class GraphRuntime {
|
|
|
2216
2185
|
activeRunContexts: new Set(),
|
|
2217
2186
|
};
|
|
2218
2187
|
this.graphStructure.setNode(n.nodeId, rn);
|
|
2219
|
-
// Activate new node
|
|
2220
2188
|
const effectiveInputs = this.executionScheduler.getEffectiveInputs(rn.nodeId);
|
|
2221
2189
|
const ctrl = new AbortController();
|
|
2222
2190
|
const ctx = this.executionScheduler.createExecutionContext(rn.nodeId, rn, effectiveInputs, `${rn.nodeId}:init`, ctrl.signal);
|
|
@@ -2228,7 +2196,6 @@ class GraphRuntime {
|
|
|
2228
2196
|
rn.runtime.onActivated?.();
|
|
2229
2197
|
}
|
|
2230
2198
|
else {
|
|
2231
|
-
// update params/policy
|
|
2232
2199
|
existing.params = n.params;
|
|
2233
2200
|
if (!existing.stats) {
|
|
2234
2201
|
existing.stats = {
|
|
@@ -2240,7 +2207,6 @@ class GraphRuntime {
|
|
|
2240
2207
|
}
|
|
2241
2208
|
}
|
|
2242
2209
|
}
|
|
2243
|
-
// Capture previous inbound map before rebuilding edges
|
|
2244
2210
|
const edges = this.graphStructure.getEdges();
|
|
2245
2211
|
const prevInbound = new Map();
|
|
2246
2212
|
for (const e of edges) {
|
|
@@ -2248,7 +2214,6 @@ class GraphRuntime {
|
|
|
2248
2214
|
set.add(e.target.handle);
|
|
2249
2215
|
prevInbound.set(e.target.nodeId, set);
|
|
2250
2216
|
}
|
|
2251
|
-
// Capture previous per-handle target sets before rebuilding edges
|
|
2252
2217
|
const prevOutTargets = new Map();
|
|
2253
2218
|
for (const e of edges) {
|
|
2254
2219
|
const tmap = prevOutTargets.get(e.source.nodeId) ?? new Map();
|
|
@@ -2257,9 +2222,7 @@ class GraphRuntime {
|
|
|
2257
2222
|
tmap.set(e.source.handle, tset);
|
|
2258
2223
|
prevOutTargets.set(e.source.nodeId, tmap);
|
|
2259
2224
|
}
|
|
2260
|
-
// Precompute per-node resolved handles for updated graph (include dynamic)
|
|
2261
2225
|
const resolved = GraphStructure.computeResolvedHandleMap(def, registry, this.environment);
|
|
2262
|
-
// Check which handles changed and emit events for those
|
|
2263
2226
|
const changedHandles = {};
|
|
2264
2227
|
for (const [nodeId, newHandles] of resolved.map) {
|
|
2265
2228
|
const oldHandles = this.graphStructure.getResolvedHandles(nodeId);
|
|
@@ -2268,14 +2231,11 @@ class GraphRuntime {
|
|
|
2268
2231
|
changedHandles[nodeId] = newHandles;
|
|
2269
2232
|
}
|
|
2270
2233
|
}
|
|
2271
|
-
// Update resolved handles
|
|
2272
2234
|
for (const [nodeId, handles] of resolved.map) {
|
|
2273
2235
|
this.graphStructure.setResolvedHandles(nodeId, handles);
|
|
2274
2236
|
}
|
|
2275
|
-
// Rebuild edges mapping with coercions
|
|
2276
2237
|
const newEdges = GraphStructure.buildEdges(def, registry, this.graphStructure.getResolvedHandlesMap());
|
|
2277
2238
|
this.graphStructure.setEdges(newEdges);
|
|
2278
|
-
// Build new inbound map
|
|
2279
2239
|
const nextInbound = new Map();
|
|
2280
2240
|
const updatedEdges = this.graphStructure.getEdges();
|
|
2281
2241
|
for (const e of updatedEdges) {
|
|
@@ -2283,7 +2243,6 @@ class GraphRuntime {
|
|
|
2283
2243
|
set.add(e.target.handle);
|
|
2284
2244
|
nextInbound.set(e.target.nodeId, set);
|
|
2285
2245
|
}
|
|
2286
|
-
// For inputs that lost inbound connections, clear and schedule recompute
|
|
2287
2246
|
for (const [nodeId, prevSet] of prevInbound) {
|
|
2288
2247
|
const currSet = nextInbound.get(nodeId) ?? new Set();
|
|
2289
2248
|
const node = this.graphStructure.getNode(nodeId);
|
|
@@ -2299,12 +2258,10 @@ class GraphRuntime {
|
|
|
2299
2258
|
}
|
|
2300
2259
|
}
|
|
2301
2260
|
if (changed) {
|
|
2302
|
-
// Clear buckets for handles that lost inbound (handled by ValuePropagator)
|
|
2303
2261
|
this.valuePropagator.clearArrayBuckets(nodeId);
|
|
2304
2262
|
this.executionScheduler.scheduleInputsChangedInternal(nodeId);
|
|
2305
2263
|
}
|
|
2306
2264
|
}
|
|
2307
|
-
// Re-emit outputs when per-handle target sets change (precise and simple)
|
|
2308
2265
|
const nextOutTargets = new Map();
|
|
2309
2266
|
for (const e of updatedEdges) {
|
|
2310
2267
|
const tmap = nextOutTargets.get(e.source.nodeId) ?? new Map();
|
|
@@ -2313,7 +2270,7 @@ class GraphRuntime {
|
|
|
2313
2270
|
tmap.set(e.source.handle, tset);
|
|
2314
2271
|
nextOutTargets.set(e.source.nodeId, tmap);
|
|
2315
2272
|
}
|
|
2316
|
-
const
|
|
2273
|
+
const setsEqual = (a, b) => {
|
|
2317
2274
|
if (!a && !b)
|
|
2318
2275
|
return true;
|
|
2319
2276
|
if (!a || !b)
|
|
@@ -2339,7 +2296,7 @@ class GraphRuntime {
|
|
|
2339
2296
|
for (const handle of handles) {
|
|
2340
2297
|
const pset = pmap.get(handle) ?? new Set();
|
|
2341
2298
|
const nset = nmap.get(handle) ?? new Set();
|
|
2342
|
-
if (!
|
|
2299
|
+
if (!setsEqual(pset, nset)) {
|
|
2343
2300
|
const val = this.getOutput(nodeId, handle);
|
|
2344
2301
|
if (val !== undefined)
|
|
2345
2302
|
this.valuePropagator.propagate(nodeId, handle, val);
|
|
@@ -2348,11 +2305,6 @@ class GraphRuntime {
|
|
|
2348
2305
|
}
|
|
2349
2306
|
}
|
|
2350
2307
|
}
|
|
2351
|
-
// Prune array bucket contributions for edges that no longer exist
|
|
2352
|
-
// This is handled by ValuePropagator - array buckets are managed there
|
|
2353
|
-
// The buckets will be cleaned up automatically when edges are removed
|
|
2354
|
-
// Schedule async recompute for nodes that indicated Promise-based resolveHandles in this update
|
|
2355
|
-
// Emit event for changed handles (if any)
|
|
2356
2308
|
if (Object.keys(changedHandles).length > 0) {
|
|
2357
2309
|
this.eventEmitter.emit("invalidate", {
|
|
2358
2310
|
reason: "graph-updated",
|
|
@@ -2583,21 +2535,25 @@ class GraphBuilder {
|
|
|
2583
2535
|
}
|
|
2584
2536
|
}
|
|
2585
2537
|
|
|
2586
|
-
|
|
2587
|
-
|
|
2538
|
+
/**
|
|
2539
|
+
* Unified Engine implementation that handles both manual and auto run modes.
|
|
2540
|
+
* - Manual mode: Runtime is paused, nodes execute only when explicitly called via computeNode/runFromHere
|
|
2541
|
+
* - Auto mode: Runtime is resumed, nodes automatically execute when inputs change
|
|
2542
|
+
*/
|
|
2543
|
+
class LocalEngine {
|
|
2544
|
+
constructor(graphRuntime, runMode) {
|
|
2588
2545
|
this.graphRuntime = graphRuntime;
|
|
2546
|
+
this.setRunMode(runMode ?? "manual");
|
|
2589
2547
|
}
|
|
2590
2548
|
setInputs(nodeId, inputs, options) {
|
|
2591
2549
|
if (options?.dry) {
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
this.graphRuntime.pause();
|
|
2550
|
+
// Use requestPause to temporarily pause without affecting base run mode
|
|
2551
|
+
const releasePause = this.graphRuntime.requestPause();
|
|
2595
2552
|
try {
|
|
2596
2553
|
this.graphRuntime.setInputs(nodeId, inputs);
|
|
2597
2554
|
}
|
|
2598
2555
|
finally {
|
|
2599
|
-
|
|
2600
|
-
this.graphRuntime.resume();
|
|
2556
|
+
releasePause();
|
|
2601
2557
|
}
|
|
2602
2558
|
}
|
|
2603
2559
|
else {
|
|
@@ -2606,15 +2562,13 @@ class AbstractEngine {
|
|
|
2606
2562
|
}
|
|
2607
2563
|
triggerExternal(nodeId, event, options) {
|
|
2608
2564
|
if (options?.dry) {
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
this.graphRuntime.pause();
|
|
2565
|
+
// Use requestPause to temporarily pause without affecting base run mode
|
|
2566
|
+
const releasePause = this.graphRuntime.requestPause();
|
|
2612
2567
|
try {
|
|
2613
2568
|
this.graphRuntime.triggerExternal(nodeId, event);
|
|
2614
2569
|
}
|
|
2615
2570
|
finally {
|
|
2616
|
-
|
|
2617
|
-
this.graphRuntime.resume();
|
|
2571
|
+
releasePause();
|
|
2618
2572
|
}
|
|
2619
2573
|
}
|
|
2620
2574
|
else {
|
|
@@ -2639,19 +2593,6 @@ class AbstractEngine {
|
|
|
2639
2593
|
dispose() {
|
|
2640
2594
|
// this.graphRuntime.dispose();
|
|
2641
2595
|
}
|
|
2642
|
-
}
|
|
2643
|
-
|
|
2644
|
-
/**
|
|
2645
|
-
* Unified Engine implementation that handles both manual and auto run modes.
|
|
2646
|
-
* - Manual mode: Runtime is paused, nodes execute only when explicitly called via computeNode/runFromHere
|
|
2647
|
-
* - Auto mode: Runtime is resumed, nodes automatically execute when inputs change
|
|
2648
|
-
*/
|
|
2649
|
-
class UnifiedEngine extends AbstractEngine {
|
|
2650
|
-
constructor(graphRuntime, runMode) {
|
|
2651
|
-
super(graphRuntime);
|
|
2652
|
-
this.runMode = "manual";
|
|
2653
|
-
this.setRunMode(runMode ?? "manual");
|
|
2654
|
-
}
|
|
2655
2596
|
launch(invalidate, runMode) {
|
|
2656
2597
|
if (runMode)
|
|
2657
2598
|
this.setRunMode(runMode);
|
|
@@ -2678,20 +2619,8 @@ class UnifiedEngine extends AbstractEngine {
|
|
|
2678
2619
|
async runFromHere(nodeId) {
|
|
2679
2620
|
await this.graphRuntime.runFromHereContext(nodeId);
|
|
2680
2621
|
}
|
|
2681
|
-
getRunMode() {
|
|
2682
|
-
return this.runMode;
|
|
2683
|
-
}
|
|
2684
2622
|
setRunMode(runMode) {
|
|
2685
|
-
|
|
2686
|
-
return;
|
|
2687
|
-
this.runMode = runMode;
|
|
2688
|
-
// Update runtime pause/resume state based on new mode
|
|
2689
|
-
if (runMode === "manual") {
|
|
2690
|
-
this.graphRuntime.pause();
|
|
2691
|
-
}
|
|
2692
|
-
else {
|
|
2693
|
-
this.graphRuntime.resume();
|
|
2694
|
-
}
|
|
2623
|
+
this.graphRuntime.setRunMode(runMode);
|
|
2695
2624
|
}
|
|
2696
2625
|
}
|
|
2697
2626
|
|
|
@@ -4772,5 +4701,5 @@ function buildValueConverter(config) {
|
|
|
4772
4701
|
};
|
|
4773
4702
|
}
|
|
4774
4703
|
|
|
4775
|
-
export { BaseCompareOperation, BaseLogicOperation, BaseMathOperation, CompositeCategory, ComputeCategory, GraphBuilder, GraphRuntime,
|
|
4704
|
+
export { BaseCompareOperation, BaseLogicOperation, BaseMathOperation, CompositeCategory, ComputeCategory, GraphBuilder, GraphRuntime, LocalEngine, Registry, buildValueConverter, computeGraphCenter, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createSimpleGraphDef, createSimpleGraphRegistry, createValidationGraphDef, createValidationGraphRegistry, findMatchingPaths, generateId, getInputTypeId, getTypedOutputTypeId, getTypedOutputValue, getValueAtPath, installLogging, isInputPrivate, isTypedOutput, mergeGraphDefinitions, mergeInputsOutputs, mergeRuntimeState, mergeSnapshotData, offsetImportedPositions, parseJsonPath, registerDelayNode, registerProgressNodes, setValueAtPath, typed };
|
|
4776
4705
|
//# sourceMappingURL=index.js.map
|