@bian-womp/spark-graph 0.1.13 → 0.1.14
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 +107 -44
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/core/types.d.ts +5 -0
- package/lib/cjs/src/core/types.d.ts.map +1 -1
- package/lib/cjs/src/examples/progress.d.ts.map +1 -1
- package/lib/cjs/src/examples/shared.d.ts.map +1 -1
- package/lib/cjs/src/examples/simple.d.ts.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 +8 -86
- package/lib/cjs/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/lib/esm/index.js +107 -44
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/core/types.d.ts +5 -0
- package/lib/esm/src/core/types.d.ts.map +1 -1
- package/lib/esm/src/examples/progress.d.ts.map +1 -1
- package/lib/esm/src/examples/shared.d.ts.map +1 -1
- package/lib/esm/src/examples/simple.d.ts.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 +8 -86
- package/lib/esm/src/runtime/GraphRuntime.d.ts.map +1 -1
- package/package.json +4 -1
package/lib/cjs/index.cjs
CHANGED
|
@@ -464,6 +464,39 @@ class GraphRuntime {
|
|
|
464
464
|
stats: { runs: 0, inFlight: false, progress: 0 },
|
|
465
465
|
};
|
|
466
466
|
});
|
|
467
|
+
// After nodes and edges exist, seed registry- and graph-level defaults
|
|
468
|
+
for (const n of def.nodes) {
|
|
469
|
+
const node = gr.nodes.get(n.nodeId);
|
|
470
|
+
const desc = registry.nodes.get(n.typeId);
|
|
471
|
+
if (!node || !desc)
|
|
472
|
+
continue;
|
|
473
|
+
// Resolve registry-level defaults (object or function)
|
|
474
|
+
const regDefaults = typeof desc.inputDefaults === "function"
|
|
475
|
+
? desc.inputDefaults({
|
|
476
|
+
params: n.params,
|
|
477
|
+
environment: gr.environment,
|
|
478
|
+
})
|
|
479
|
+
: desc.inputDefaults ?? {};
|
|
480
|
+
const graphDefaults = n.initialInputs ?? {};
|
|
481
|
+
// Apply precedence: graph-level overrides registry-level
|
|
482
|
+
const merged = {
|
|
483
|
+
...regDefaults,
|
|
484
|
+
...graphDefaults,
|
|
485
|
+
};
|
|
486
|
+
for (const [handle, value] of Object.entries(merged)) {
|
|
487
|
+
// Only seed if input has no inbound wiring
|
|
488
|
+
const hasInbound = gr.edges.some((e) => e.target.nodeId === n.nodeId && e.target.handle === handle);
|
|
489
|
+
if (hasInbound)
|
|
490
|
+
continue;
|
|
491
|
+
if (value === undefined)
|
|
492
|
+
continue;
|
|
493
|
+
// Clone to avoid accidental shared references
|
|
494
|
+
node.inputs[handle] =
|
|
495
|
+
typeof structuredClone === "function"
|
|
496
|
+
? structuredClone(value)
|
|
497
|
+
: JSON.parse(JSON.stringify(value));
|
|
498
|
+
}
|
|
499
|
+
}
|
|
467
500
|
return gr;
|
|
468
501
|
}
|
|
469
502
|
on(event, handler) {
|
|
@@ -589,7 +622,7 @@ class GraphRuntime {
|
|
|
589
622
|
await new Promise((r) => setTimeout(r, delay));
|
|
590
623
|
return exec(attempt + 1);
|
|
591
624
|
}
|
|
592
|
-
this.emit("error", { nodeId, runId, err });
|
|
625
|
+
this.emit("error", { kind: "node-run", nodeId, runId, err });
|
|
593
626
|
}
|
|
594
627
|
finally {
|
|
595
628
|
if (timeoutId)
|
|
@@ -749,6 +782,14 @@ class GraphRuntime {
|
|
|
749
782
|
}
|
|
750
783
|
}
|
|
751
784
|
}
|
|
785
|
+
reemitNodeOutputs(nodeId) {
|
|
786
|
+
const node = this.nodes.get(nodeId);
|
|
787
|
+
if (!node)
|
|
788
|
+
return;
|
|
789
|
+
for (const [handle, value] of Object.entries(node.outputs)) {
|
|
790
|
+
this.propagate(nodeId, handle, value);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
752
793
|
launch() {
|
|
753
794
|
// call onActivated for nodes that implement it
|
|
754
795
|
for (const node of this.nodes.values()) {
|
|
@@ -773,6 +814,11 @@ class GraphRuntime {
|
|
|
773
814
|
});
|
|
774
815
|
node.runtime.onActivated?.(ctx);
|
|
775
816
|
}
|
|
817
|
+
// After activation, schedule nodes that have all inbound inputs present
|
|
818
|
+
for (const nodeId of this.nodes.keys()) {
|
|
819
|
+
if (this.allInboundHaveValue(nodeId))
|
|
820
|
+
this.scheduleInputsChanged(nodeId);
|
|
821
|
+
}
|
|
776
822
|
}
|
|
777
823
|
triggerExternal(nodeId, event) {
|
|
778
824
|
const node = this.nodes.get(nodeId);
|
|
@@ -808,8 +854,11 @@ class GraphRuntime {
|
|
|
808
854
|
this.edges = [];
|
|
809
855
|
this.listeners.clear();
|
|
810
856
|
}
|
|
857
|
+
getNodeIds() {
|
|
858
|
+
return Array.from(this.nodes.keys());
|
|
859
|
+
}
|
|
811
860
|
// Unsafe helpers for serializer: read-only accessors and hydration
|
|
812
|
-
|
|
861
|
+
getNodeData(nodeId) {
|
|
813
862
|
const node = this.nodes.get(nodeId);
|
|
814
863
|
if (!node)
|
|
815
864
|
return undefined;
|
|
@@ -821,33 +870,12 @@ class GraphRuntime {
|
|
|
821
870
|
stats: { ...node.stats },
|
|
822
871
|
};
|
|
823
872
|
}
|
|
824
|
-
|
|
873
|
+
getEnvironment() {
|
|
825
874
|
return { ...this.environment };
|
|
826
875
|
}
|
|
827
876
|
setEnvironment(env) {
|
|
828
877
|
this.environment = { ...env };
|
|
829
878
|
}
|
|
830
|
-
__unsafe_setEnvironment(env) {
|
|
831
|
-
this.setEnvironment(env);
|
|
832
|
-
}
|
|
833
|
-
__unsafe_hydrateNode(nodeId, data, opts) {
|
|
834
|
-
const node = this.nodes.get(nodeId);
|
|
835
|
-
if (!node)
|
|
836
|
-
return;
|
|
837
|
-
if (opts?.replace) {
|
|
838
|
-
node.inputs = {};
|
|
839
|
-
node.outputs = {};
|
|
840
|
-
node.state = {};
|
|
841
|
-
}
|
|
842
|
-
if (data.inputs)
|
|
843
|
-
Object.assign(node.inputs, data.inputs);
|
|
844
|
-
if (data.outputs)
|
|
845
|
-
Object.assign(node.outputs, data.outputs);
|
|
846
|
-
if (data.state !== undefined)
|
|
847
|
-
node.state = data.state;
|
|
848
|
-
if (data.params)
|
|
849
|
-
node.params = data.params;
|
|
850
|
-
}
|
|
851
879
|
async whenIdle() {
|
|
852
880
|
const isIdle = () => {
|
|
853
881
|
for (const n of this.nodes.values()) {
|
|
@@ -879,14 +907,6 @@ class GraphRuntime {
|
|
|
879
907
|
__unsafe_invalidateDownstream(nodeId) {
|
|
880
908
|
this.invalidateDownstream(nodeId);
|
|
881
909
|
}
|
|
882
|
-
__unsafe_reemitNodeOutputs(nodeId) {
|
|
883
|
-
const node = this.nodes.get(nodeId);
|
|
884
|
-
if (!node)
|
|
885
|
-
return;
|
|
886
|
-
for (const [handle, value] of Object.entries(node.outputs)) {
|
|
887
|
-
this.propagate(nodeId, handle, value);
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
910
|
__unsafe_scheduleInputsChanged(nodeId) {
|
|
891
911
|
this.scheduleInputsChanged(nodeId);
|
|
892
912
|
}
|
|
@@ -1050,12 +1070,41 @@ class GraphRuntime {
|
|
|
1050
1070
|
}
|
|
1051
1071
|
}
|
|
1052
1072
|
}
|
|
1053
|
-
|
|
1073
|
+
// If input lost inbound, try to re-seed from defaults
|
|
1074
|
+
if (changed) {
|
|
1075
|
+
const defNode = def.nodes.find((n) => n.nodeId === nodeId);
|
|
1076
|
+
if (defNode) {
|
|
1077
|
+
const desc = registry.nodes.get(defNode.typeId);
|
|
1078
|
+
if (desc) {
|
|
1079
|
+
const regDefaults = typeof desc.inputDefaults === "function"
|
|
1080
|
+
? desc.inputDefaults({
|
|
1081
|
+
params: defNode.params,
|
|
1082
|
+
environment: this.environment,
|
|
1083
|
+
})
|
|
1084
|
+
: desc.inputDefaults ?? {};
|
|
1085
|
+
const graphDefaults = defNode.initialInputs ?? {};
|
|
1086
|
+
const merged = {
|
|
1087
|
+
...regDefaults,
|
|
1088
|
+
...graphDefaults,
|
|
1089
|
+
};
|
|
1090
|
+
for (const h of Array.from(prevSet)) {
|
|
1091
|
+
if (!currSet.has(h) && node.inputs[h] === undefined) {
|
|
1092
|
+
const v = merged[h];
|
|
1093
|
+
if (v !== undefined)
|
|
1094
|
+
node.inputs[h] =
|
|
1095
|
+
typeof structuredClone === "function"
|
|
1096
|
+
? structuredClone(v)
|
|
1097
|
+
: JSON.parse(JSON.stringify(v));
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1054
1102
|
this.scheduleInputsChanged(nodeId);
|
|
1103
|
+
}
|
|
1055
1104
|
}
|
|
1056
1105
|
// Re-emit existing outputs to populate new edges
|
|
1057
1106
|
for (const nodeId of this.nodes.keys()) {
|
|
1058
|
-
this.
|
|
1107
|
+
this.reemitNodeOutputs(nodeId);
|
|
1059
1108
|
}
|
|
1060
1109
|
}
|
|
1061
1110
|
}
|
|
@@ -1685,6 +1734,9 @@ function setupBasicGraphRegistry() {
|
|
|
1685
1734
|
Factor: "base.float",
|
|
1686
1735
|
},
|
|
1687
1736
|
outputs: { Value: "base.float[]" },
|
|
1737
|
+
inputDefaults: {
|
|
1738
|
+
Factor: 0.5,
|
|
1739
|
+
},
|
|
1688
1740
|
impl: (ins) => {
|
|
1689
1741
|
const [a, b] = broadcast(ins.ValueA, ins.ValueB);
|
|
1690
1742
|
const t = Number(ins.Factor ?? 0);
|
|
@@ -1736,6 +1788,8 @@ function setupBasicGraphRegistry() {
|
|
|
1736
1788
|
B: "base.float[]",
|
|
1737
1789
|
},
|
|
1738
1790
|
outputs: { Result: "base.float[]" },
|
|
1791
|
+
// Registry-level defaults: Add by default, A=[1], B=[1]
|
|
1792
|
+
inputDefaults: { Operation: 0, A: [1], B: [1] },
|
|
1739
1793
|
impl: (ins) => {
|
|
1740
1794
|
// Gracefully handle missing inputs by treating them as zeros
|
|
1741
1795
|
const a = ins.A === undefined ? [] : asArray(ins.A);
|
|
@@ -1858,6 +1912,8 @@ function setupBasicGraphRegistry() {
|
|
|
1858
1912
|
Seed: "base.float",
|
|
1859
1913
|
},
|
|
1860
1914
|
outputs: { Values: "base.vec3[]" },
|
|
1915
|
+
// Registry-level defaults for convenience
|
|
1916
|
+
inputDefaults: { Domain: 10, Min: [0, 0, 0], Max: [1, 1, 1], Seed: 1 },
|
|
1861
1917
|
impl: (ins) => {
|
|
1862
1918
|
const len = Math.trunc(ins.Domain);
|
|
1863
1919
|
const min = ins.Min ?? [0, 0, 0];
|
|
@@ -1877,12 +1933,14 @@ function registerDelayNode(registry) {
|
|
|
1877
1933
|
registry.registerNode({
|
|
1878
1934
|
id: "async.delay",
|
|
1879
1935
|
categoryId: "compute",
|
|
1880
|
-
inputs: {
|
|
1881
|
-
outputs: {
|
|
1936
|
+
inputs: { Value: "base.float", DelayMs: "base.float" },
|
|
1937
|
+
outputs: { Output: "base.float" },
|
|
1882
1938
|
impl: async (ins, ctx) => {
|
|
1883
|
-
const ms = Number(ins.
|
|
1884
|
-
const
|
|
1885
|
-
if (
|
|
1939
|
+
const ms = Number(ins.DelayMs ?? 200);
|
|
1940
|
+
const valueRaw = ins.Value;
|
|
1941
|
+
if (valueRaw === undefined ||
|
|
1942
|
+
valueRaw === null ||
|
|
1943
|
+
Number.isNaN(Number(valueRaw))) {
|
|
1886
1944
|
return; // wait until x is present to avoid NaN emissions
|
|
1887
1945
|
}
|
|
1888
1946
|
await new Promise((resolve, reject) => {
|
|
@@ -1895,7 +1953,7 @@ function registerDelayNode(registry) {
|
|
|
1895
1953
|
return onAbort();
|
|
1896
1954
|
ctx.abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
1897
1955
|
});
|
|
1898
|
-
return {
|
|
1956
|
+
return { Output: Number(valueRaw) };
|
|
1899
1957
|
},
|
|
1900
1958
|
});
|
|
1901
1959
|
}
|
|
@@ -1950,7 +2008,12 @@ function makeBasicGraphDefinition() {
|
|
|
1950
2008
|
return {
|
|
1951
2009
|
nodes: [
|
|
1952
2010
|
{ nodeId: "n1", typeId: "base.math" },
|
|
1953
|
-
{
|
|
2011
|
+
{
|
|
2012
|
+
nodeId: "n2",
|
|
2013
|
+
typeId: "base.math",
|
|
2014
|
+
// Graph-level defaults override registry if provided
|
|
2015
|
+
initialInputs: { Operation: 2, B: [10] }, // Multiply by 10
|
|
2016
|
+
},
|
|
1954
2017
|
// Transitivity demo nodes
|
|
1955
2018
|
{ nodeId: "n3", typeId: "base.compare" },
|
|
1956
2019
|
{ nodeId: "n4", typeId: "base.randomXYZs" },
|
|
@@ -2009,7 +2072,7 @@ function createAsyncGraphDef() {
|
|
|
2009
2072
|
{
|
|
2010
2073
|
id: "e1",
|
|
2011
2074
|
source: { nodeId: "n1", handle: "Result" },
|
|
2012
|
-
target: { nodeId: "n2", handle: "
|
|
2075
|
+
target: { nodeId: "n2", handle: "Value" },
|
|
2013
2076
|
},
|
|
2014
2077
|
// Demonstrate async edge conversion: vec3[] -> float[] using coercion
|
|
2015
2078
|
{
|
|
@@ -2048,7 +2111,7 @@ function createProgressGraphDef() {
|
|
|
2048
2111
|
const def = {
|
|
2049
2112
|
nodes: [
|
|
2050
2113
|
{ nodeId: "steps", typeId: "base.number" },
|
|
2051
|
-
{ nodeId: "
|
|
2114
|
+
{ nodeId: "delay", typeId: "base.number" },
|
|
2052
2115
|
{ nodeId: "work", typeId: "async.progress" },
|
|
2053
2116
|
],
|
|
2054
2117
|
edges: [
|
|
@@ -2059,7 +2122,7 @@ function createProgressGraphDef() {
|
|
|
2059
2122
|
},
|
|
2060
2123
|
{
|
|
2061
2124
|
id: "e2",
|
|
2062
|
-
source: { nodeId: "
|
|
2125
|
+
source: { nodeId: "delay", handle: "Result" },
|
|
2063
2126
|
target: { nodeId: "work", handle: "DelayMs" },
|
|
2064
2127
|
},
|
|
2065
2128
|
// not wiring ShouldError to show manual input driven error later
|