@bian-womp/spark-workbench 0.1.13 → 0.1.15
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 +86 -65
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts +12 -2
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
- package/lib/cjs/src/runtime/GraphRunner.d.ts +2 -2
- package/lib/cjs/src/runtime/GraphRunner.d.ts.map +1 -1
- package/lib/esm/index.js +87 -66
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/misc/WorkbenchStudio.d.ts +12 -2
- package/lib/esm/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/esm/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
- package/lib/esm/src/runtime/GraphRunner.d.ts +2 -2
- package/lib/esm/src/runtime/GraphRunner.d.ts.map +1 -1
- package/package.json +4 -4
package/lib/cjs/index.cjs
CHANGED
|
@@ -408,6 +408,31 @@ class GraphRunner {
|
|
|
408
408
|
await rc.runner.build(def);
|
|
409
409
|
// Signal UI after remote build as well
|
|
410
410
|
this.emit("invalidate", { reason: "graph-built" });
|
|
411
|
+
// Hydrate current remote inputs/outputs (including defaults) into cache
|
|
412
|
+
try {
|
|
413
|
+
const snap = await rc.runner.snapshot();
|
|
414
|
+
for (const [nodeId, map] of Object.entries(snap.inputs || {})) {
|
|
415
|
+
for (const [handle, value] of Object.entries(map || {})) {
|
|
416
|
+
rc.valueCache.set(`${nodeId}.${handle}`, {
|
|
417
|
+
io: "input",
|
|
418
|
+
value,
|
|
419
|
+
});
|
|
420
|
+
this.emit("value", { nodeId, handle, value, io: "input" });
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
for (const [nodeId, map] of Object.entries(snap.outputs || {})) {
|
|
424
|
+
for (const [handle, value] of Object.entries(map || {})) {
|
|
425
|
+
rc.valueCache.set(`${nodeId}.${handle}`, {
|
|
426
|
+
io: "output",
|
|
427
|
+
value,
|
|
428
|
+
});
|
|
429
|
+
this.emit("value", { nodeId, handle, value, io: "output" });
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
catch {
|
|
434
|
+
console.error("Failed to hydrate remote inputs/outputs");
|
|
435
|
+
}
|
|
411
436
|
const eng = rc.runner.getEngine();
|
|
412
437
|
if (!rc.listenersBound) {
|
|
413
438
|
eng.on("value", (e) => {
|
|
@@ -452,32 +477,13 @@ class GraphRunner {
|
|
|
452
477
|
Object.assign(this.stagedInputs[nodeId], inputs);
|
|
453
478
|
// Local running: pause, set all inputs, resume, schedule a single recompute
|
|
454
479
|
if (this.backend.kind === "local" && this.engine && this.runtime) {
|
|
455
|
-
this.
|
|
456
|
-
try {
|
|
457
|
-
for (const [handle, value] of Object.entries(inputs)) {
|
|
458
|
-
this.engine.setInput(nodeId, handle, value);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
finally {
|
|
462
|
-
this.runtime.resume();
|
|
463
|
-
try {
|
|
464
|
-
this.runtime.__unsafe_scheduleInputsChanged(nodeId);
|
|
465
|
-
}
|
|
466
|
-
catch { }
|
|
467
|
-
}
|
|
480
|
+
this.engine.setInputs(nodeId, inputs);
|
|
468
481
|
}
|
|
469
482
|
// Remote running: forward inputs individually (no batch API available)
|
|
470
|
-
else if (this.engine &&
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}
|
|
475
|
-
else {
|
|
476
|
-
console.warn("Remote engine does not support setInputs");
|
|
477
|
-
for (const [handle, value] of Object.entries(inputs)) {
|
|
478
|
-
this.engine.setInput(nodeId, handle, value);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
483
|
+
else if (this.engine &&
|
|
484
|
+
this.backend.kind !== "local" &&
|
|
485
|
+
this.engine instanceof sparkRemote.RemoteEngine) {
|
|
486
|
+
this.engine.setInputs(nodeId, inputs);
|
|
481
487
|
}
|
|
482
488
|
// Not running: emit value events so UI reflects staged values
|
|
483
489
|
else if (!this.engine) {
|
|
@@ -552,7 +558,7 @@ class GraphRunner {
|
|
|
552
558
|
for (const n of def.nodes) {
|
|
553
559
|
const staged = this.stagedInputs[n.nodeId] ?? {};
|
|
554
560
|
const runtimeInputs = this.runtime
|
|
555
|
-
? this.runtime.
|
|
561
|
+
? this.runtime.getNodeData?.(n.nodeId)?.inputs ?? {}
|
|
556
562
|
: {};
|
|
557
563
|
if (this.isRunning()) {
|
|
558
564
|
out[n.nodeId] = runtimeInputs;
|
|
@@ -877,7 +883,7 @@ function getNodeBorderClassNames(args) {
|
|
|
877
883
|
const status = args.status || {};
|
|
878
884
|
const issues = args.validation?.issues ?? [];
|
|
879
885
|
const hasError = !!status.lastError;
|
|
880
|
-
const hasValidationError = issues.some((i) => i
|
|
886
|
+
const hasValidationError = issues.some((i) => i.level === "error");
|
|
881
887
|
const hasValidationWarning = !hasValidationError && issues.length > 0;
|
|
882
888
|
const isRunning = !!status.activeRuns;
|
|
883
889
|
const isInvalid = !!status.invalidated && !isRunning && !hasError;
|
|
@@ -979,7 +985,8 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, children, }) {
|
|
|
979
985
|
const add = (source, type) => (payload) => setEvents((prev) => {
|
|
980
986
|
if (source === "workbench" &&
|
|
981
987
|
(type === "graphChanged" || type === "graphUiChanged")) {
|
|
982
|
-
const changeType = payload
|
|
988
|
+
const changeType = payload
|
|
989
|
+
.change?.type;
|
|
983
990
|
if (changeType === "moveNode" || changeType === "moveNodes")
|
|
984
991
|
return prev;
|
|
985
992
|
}
|
|
@@ -1736,6 +1743,45 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
1736
1743
|
? registry.nodes.get(selectedNode.typeId)
|
|
1737
1744
|
: undefined;
|
|
1738
1745
|
const [exampleState, setExampleState] = React.useState(example ?? "simple");
|
|
1746
|
+
const defaultExamples = React.useMemo(() => [
|
|
1747
|
+
{
|
|
1748
|
+
id: "simple",
|
|
1749
|
+
label: "Simple",
|
|
1750
|
+
load: async () => ({
|
|
1751
|
+
registry: sparkGraph.createSimpleGraphRegistry(),
|
|
1752
|
+
def: sparkGraph.createSimpleGraphDef(),
|
|
1753
|
+
}),
|
|
1754
|
+
},
|
|
1755
|
+
{
|
|
1756
|
+
id: "async",
|
|
1757
|
+
label: "Async Chain",
|
|
1758
|
+
load: async () => ({
|
|
1759
|
+
registry: sparkGraph.createAsyncGraphRegistry(),
|
|
1760
|
+
def: sparkGraph.createAsyncGraphDef(),
|
|
1761
|
+
}),
|
|
1762
|
+
},
|
|
1763
|
+
{
|
|
1764
|
+
id: "progress",
|
|
1765
|
+
label: "Progress + Errors",
|
|
1766
|
+
load: async () => ({
|
|
1767
|
+
registry: sparkGraph.createProgressGraphRegistry(),
|
|
1768
|
+
def: sparkGraph.createProgressGraphDef(),
|
|
1769
|
+
}),
|
|
1770
|
+
},
|
|
1771
|
+
{
|
|
1772
|
+
id: "validation",
|
|
1773
|
+
label: "Validation",
|
|
1774
|
+
load: async () => ({
|
|
1775
|
+
registry: sparkGraph.createValidationGraphRegistry(),
|
|
1776
|
+
def: sparkGraph.createValidationGraphDef(),
|
|
1777
|
+
}),
|
|
1778
|
+
},
|
|
1779
|
+
], []);
|
|
1780
|
+
const examples = React.useMemo(() => {
|
|
1781
|
+
if (overrides?.getExamples)
|
|
1782
|
+
return overrides.getExamples(defaultExamples);
|
|
1783
|
+
return defaultExamples;
|
|
1784
|
+
}, [overrides, defaultExamples]);
|
|
1739
1785
|
const lastAutoLaunched = React.useRef(undefined);
|
|
1740
1786
|
const autoLayoutRan = React.useRef(false);
|
|
1741
1787
|
const applyExample = React.useCallback(async (key) => {
|
|
@@ -1743,46 +1789,21 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
1743
1789
|
alert(`Stop engine before switching example.`);
|
|
1744
1790
|
return;
|
|
1745
1791
|
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
}
|
|
1754
|
-
case "async": {
|
|
1755
|
-
const r = sparkGraph.createAsyncGraphRegistry();
|
|
1756
|
-
setRegistry(r);
|
|
1757
|
-
wb.setRegistry(r);
|
|
1758
|
-
await wb.load(sparkGraph.createAsyncGraphDef());
|
|
1759
|
-
break;
|
|
1760
|
-
}
|
|
1761
|
-
case "progress": {
|
|
1762
|
-
const r = sparkGraph.createProgressGraphRegistry();
|
|
1763
|
-
setRegistry(r);
|
|
1764
|
-
wb.setRegistry(r);
|
|
1765
|
-
await wb.load(sparkGraph.createProgressGraphDef());
|
|
1766
|
-
break;
|
|
1767
|
-
}
|
|
1768
|
-
case "validation": {
|
|
1769
|
-
const r = sparkGraph.createValidationGraphRegistry();
|
|
1770
|
-
setRegistry(r);
|
|
1771
|
-
wb.setRegistry(r);
|
|
1772
|
-
await wb.load(sparkGraph.createValidationGraphDef());
|
|
1773
|
-
break;
|
|
1774
|
-
}
|
|
1775
|
-
default: {
|
|
1776
|
-
const r = sparkGraph.createSimpleGraphRegistry();
|
|
1777
|
-
setRegistry(r);
|
|
1778
|
-
wb.setRegistry(r);
|
|
1779
|
-
await wb.load(sparkGraph.createSimpleGraphDef());
|
|
1780
|
-
}
|
|
1792
|
+
const ex = examples.find((e) => e.id === key) ?? examples[0];
|
|
1793
|
+
if (!ex)
|
|
1794
|
+
return;
|
|
1795
|
+
const { registry: r, def } = await ex.load();
|
|
1796
|
+
if (r) {
|
|
1797
|
+
setRegistry(r);
|
|
1798
|
+
wb.setRegistry(r);
|
|
1781
1799
|
}
|
|
1800
|
+
await wb.load(def);
|
|
1801
|
+
// Build a local runtime so seeded defaults are visible pre-run
|
|
1802
|
+
runner.build(wb.export());
|
|
1782
1803
|
runAutoLayout();
|
|
1783
1804
|
setExampleState(key);
|
|
1784
1805
|
onExampleChange?.(key);
|
|
1785
|
-
}, [runner, wb, onExampleChange, runAutoLayout]);
|
|
1806
|
+
}, [runner, wb, onExampleChange, runAutoLayout, examples, setRegistry]);
|
|
1786
1807
|
const hydrateFromBackend = React.useCallback(async (kind, base) => {
|
|
1787
1808
|
try {
|
|
1788
1809
|
const transport = kind === "remote-http"
|
|
@@ -2033,9 +2054,9 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
2033
2054
|
return overrides.toElement(baseToElement, { registry });
|
|
2034
2055
|
return baseToElement;
|
|
2035
2056
|
}, [overrides, baseToElement, registry]);
|
|
2036
|
-
return (jsxRuntime.jsxs("div", { className: "w-full h-screen flex flex-col", children: [jsxRuntime.jsxs("div", { className: "p-2 border-b border-gray-300 flex gap-2 items-center", children: [runner.isRunning() ? (jsxRuntime.jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", runner.getRunningEngine()] })) : (jsxRuntime.jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsxRuntime.jsx("label", { className: "ml-2 text-sm", children: "Example:" }), jsxRuntime.
|
|
2057
|
+
return (jsxRuntime.jsxs("div", { className: "w-full h-screen flex flex-col", children: [jsxRuntime.jsxs("div", { className: "p-2 border-b border-gray-300 flex gap-2 items-center", children: [runner.isRunning() ? (jsxRuntime.jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", runner.getRunningEngine()] })) : (jsxRuntime.jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsxRuntime.jsx("label", { className: "ml-2 text-sm", children: "Example:" }), jsxRuntime.jsx("select", { className: "border border-gray-300 rounded px-2 py-1", value: exampleState, onChange: (e) => applyExample(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
|
|
2037
2058
|
? "Stop engine before switching example"
|
|
2038
|
-
: undefined, children:
|
|
2059
|
+
: undefined, children: examples.map((ex) => (jsxRuntime.jsx("option", { value: ex.id, children: ex.label }, ex.id))) }), jsxRuntime.jsx("label", { className: "ml-2 text-sm", children: "Backend:" }), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: backendKind, onChange: (e) => onBackendKindChange(e.target.value), disabled: runner.isRunning(), title: runner.isRunning()
|
|
2039
2060
|
? "Stop engine before switching backend"
|
|
2040
2061
|
: undefined, children: [jsxRuntime.jsx("option", { value: "local", children: "Local" }), jsxRuntime.jsx("option", { value: "remote-http", children: "Remote (HTTP)" }), jsxRuntime.jsx("option", { value: "remote-ws", children: "Remote (WebSocket)" })] }), backendKind === "remote-http" && (jsxRuntime.jsx("input", { className: "ml-2 border border-gray-300 rounded px-2 py-1 w-72", placeholder: "http://127.0.0.1:18080", value: httpBaseUrl, onChange: (e) => onHttpBaseUrlChange(e.target.value) })), backendKind === "remote-ws" && (jsxRuntime.jsx("input", { className: "ml-2 border border-gray-300 rounded px-2 py-1 w-72", placeholder: "ws://127.0.0.1:18081", value: wsUrl, onChange: (e) => onWsUrlChange(e.target.value) })), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: runner.getRunningEngine() ?? engine ?? "", onChange: (e) => {
|
|
2041
2062
|
const kind = e.target.value || undefined;
|