@bian-womp/spark-workbench 0.2.92 → 0.2.94
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 +57 -63
- package/lib/cjs/index.cjs.map +1 -1
- package/lib/cjs/src/core/AbstractWorkbench.d.ts +8 -7
- package/lib/cjs/src/core/AbstractWorkbench.d.ts.map +1 -1
- package/lib/cjs/src/core/InMemoryWorkbench.d.ts +4 -2
- package/lib/cjs/src/core/InMemoryWorkbench.d.ts.map +1 -1
- package/lib/cjs/src/core/contracts.d.ts +5 -2
- package/lib/cjs/src/core/contracts.d.ts.map +1 -1
- package/lib/cjs/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/cjs/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/WorkbenchContext.d.ts +1 -2
- package/lib/cjs/src/misc/context/WorkbenchContext.d.ts.map +1 -1
- package/lib/cjs/src/misc/context/WorkbenchContext.provider.d.ts +1 -4
- package/lib/cjs/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
- package/lib/esm/index.js +58 -64
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/src/core/AbstractWorkbench.d.ts +8 -7
- package/lib/esm/src/core/AbstractWorkbench.d.ts.map +1 -1
- package/lib/esm/src/core/InMemoryWorkbench.d.ts +4 -2
- package/lib/esm/src/core/InMemoryWorkbench.d.ts.map +1 -1
- package/lib/esm/src/core/contracts.d.ts +5 -2
- package/lib/esm/src/core/contracts.d.ts.map +1 -1
- package/lib/esm/src/misc/WorkbenchCanvas.d.ts.map +1 -1
- package/lib/esm/src/misc/WorkbenchStudio.d.ts.map +1 -1
- package/lib/esm/src/misc/context/WorkbenchContext.d.ts +1 -2
- package/lib/esm/src/misc/context/WorkbenchContext.d.ts.map +1 -1
- package/lib/esm/src/misc/context/WorkbenchContext.provider.d.ts +1 -4
- package/lib/esm/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
- package/package.json +4 -4
package/lib/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { generateId, GraphBuilder, getTypedOutputValue, isTypedOutput, getInputTypeId, createEngine, StepEngine, PullEngine, BatchedEngine, getTypedOutputTypeId, isInputPrivate, offsetImportedPositions,
|
|
1
|
+
import { generateId, createSimpleGraphRegistry, GraphBuilder, getTypedOutputValue, isTypedOutput, getInputTypeId, createEngine, StepEngine, PullEngine, BatchedEngine, getTypedOutputTypeId, isInputPrivate, offsetImportedPositions, createSimpleGraphDef, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createValidationGraphDef, createValidationGraphRegistry } from '@bian-womp/spark-graph';
|
|
2
2
|
import lod from 'lodash';
|
|
3
3
|
import { RuntimeApiClient } from '@bian-womp/spark-remote';
|
|
4
4
|
import { Position, Handle, NodeResizer, getBezierPath, BaseEdge, useReactFlow, ReactFlowProvider, ReactFlow, Background, BackgroundVariant, MiniMap, Controls } from '@xyflow/react';
|
|
@@ -133,8 +133,8 @@ class AbstractWorkbench {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
class InMemoryWorkbench extends AbstractWorkbench {
|
|
136
|
-
constructor() {
|
|
137
|
-
super(
|
|
136
|
+
constructor(args) {
|
|
137
|
+
super(args);
|
|
138
138
|
this._def = { nodes: [], edges: [] };
|
|
139
139
|
this.listeners = new Map();
|
|
140
140
|
this.positions = {};
|
|
@@ -148,12 +148,17 @@ class InMemoryWorkbench extends AbstractWorkbench {
|
|
|
148
148
|
this.viewport = null;
|
|
149
149
|
this.historyState = undefined;
|
|
150
150
|
this.copiedData = null;
|
|
151
|
+
this._registry = createSimpleGraphRegistry();
|
|
151
152
|
}
|
|
152
153
|
get def() {
|
|
153
154
|
return this._def;
|
|
154
155
|
}
|
|
156
|
+
get registry() {
|
|
157
|
+
return this._registry;
|
|
158
|
+
}
|
|
155
159
|
setRegistry(registry) {
|
|
156
|
-
this.
|
|
160
|
+
this._registry = registry;
|
|
161
|
+
this.emit("registryChanged", { registry });
|
|
157
162
|
}
|
|
158
163
|
async load(def) {
|
|
159
164
|
this._def = { nodes: [...def.nodes], edges: [...def.edges] };
|
|
@@ -3647,7 +3652,7 @@ function computeInvalidatedFromMetadata(metadata) {
|
|
|
3647
3652
|
const maxInputTime = Math.max(...Object.values(lastInputAt));
|
|
3648
3653
|
return maxInputTime > (lastSuccessAt ?? lastRunAt ?? 0);
|
|
3649
3654
|
}
|
|
3650
|
-
function WorkbenchProvider({ wb, runner,
|
|
3655
|
+
function WorkbenchProvider({ wb, runner, overrides, uiVersion, children, }) {
|
|
3651
3656
|
const [nodeStatus, setNodeStatus] = useState({});
|
|
3652
3657
|
const [edgeStatus, setEdgeStatus] = useState({});
|
|
3653
3658
|
const [events, setEvents] = useState([]);
|
|
@@ -3655,6 +3660,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3655
3660
|
const [systemErrors, setSystemErrors] = useState([]);
|
|
3656
3661
|
const [registryErrors, setRegistryErrors] = useState([]);
|
|
3657
3662
|
const [inputValidationErrors, setInputValidationErrors] = useState([]);
|
|
3663
|
+
const [registryVersion, setRegistryVersion] = useState(0);
|
|
3658
3664
|
const clearSystemErrors = useCallback(() => setSystemErrors([]), []);
|
|
3659
3665
|
const clearRegistryErrors = useCallback(() => setRegistryErrors([]), []);
|
|
3660
3666
|
const clearInputValidationErrors = useCallback(() => setInputValidationErrors([]), []);
|
|
@@ -3721,7 +3727,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3721
3727
|
const out = {};
|
|
3722
3728
|
// Local: runtimeTypeId is not stored; derive from typed wrapper in outputsMap
|
|
3723
3729
|
for (const n of wb.def.nodes) {
|
|
3724
|
-
const effectiveHandles = computeEffectiveHandles(n, registry);
|
|
3730
|
+
const effectiveHandles = computeEffectiveHandles(n, wb.registry);
|
|
3725
3731
|
const outputsDecl = effectiveHandles.outputs;
|
|
3726
3732
|
const handles = Object.keys(outputsDecl);
|
|
3727
3733
|
const cur = {};
|
|
@@ -3735,7 +3741,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3735
3741
|
out[n.nodeId] = cur;
|
|
3736
3742
|
}
|
|
3737
3743
|
return out;
|
|
3738
|
-
}, [wb, wb.def, outputsMap, registry]);
|
|
3744
|
+
}, [wb, wb.def, outputsMap, wb.registry, registryVersion]);
|
|
3739
3745
|
// Initialize nodes and derive invalidated status from persisted metadata
|
|
3740
3746
|
useEffect(() => {
|
|
3741
3747
|
const workbenchRuntimeState = wb.getRuntimeState() ?? { nodes: {} };
|
|
@@ -3813,7 +3819,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3813
3819
|
const overrideSize = overrides?.getDefaultNodeSize?.(node.typeId) ?? undefined;
|
|
3814
3820
|
const size = estimateNodeSize({
|
|
3815
3821
|
node,
|
|
3816
|
-
registry,
|
|
3822
|
+
registry: wb.registry,
|
|
3817
3823
|
showValues: true,
|
|
3818
3824
|
overrides: overrideSize,
|
|
3819
3825
|
});
|
|
@@ -3831,7 +3837,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3831
3837
|
curX += maxWidth + H_GAP;
|
|
3832
3838
|
}
|
|
3833
3839
|
wb.setPositions(pos, { commit: true, reason: "auto-layout" });
|
|
3834
|
-
}, [wb, wb.def, registry, overrides?.getDefaultNodeSize]);
|
|
3840
|
+
}, [wb, wb.def, wb.registry, registryVersion, overrides?.getDefaultNodeSize]);
|
|
3835
3841
|
const updateEdgeType = useCallback((edgeId, typeId) => wb.updateEdgeType(edgeId, typeId), [wb]);
|
|
3836
3842
|
const triggerExternal = useCallback((nodeId, event) => runner.triggerExternal(nodeId, event), [runner]);
|
|
3837
3843
|
const getNodeDisplayName = useCallback((nodeId) => {
|
|
@@ -3841,9 +3847,9 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
3841
3847
|
const node = wb.def.nodes.find((n) => n.nodeId === nodeId);
|
|
3842
3848
|
if (!node)
|
|
3843
3849
|
return nodeId;
|
|
3844
|
-
const desc = registry.nodes.get(node.typeId);
|
|
3850
|
+
const desc = wb.registry.nodes.get(node.typeId);
|
|
3845
3851
|
return desc?.displayName || node.typeId;
|
|
3846
|
-
}, [wb, registry]);
|
|
3852
|
+
}, [wb, wb.registry, registryVersion]);
|
|
3847
3853
|
const setNodeName = useCallback((nodeId, name) => {
|
|
3848
3854
|
wb.setNodeName(nodeId, name, { commit: true, reason: "rename-node" });
|
|
3849
3855
|
}, [wb]);
|
|
@@ -4159,6 +4165,9 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
4159
4165
|
}
|
|
4160
4166
|
return add("runner", "stats")(s);
|
|
4161
4167
|
});
|
|
4168
|
+
const offWbRegistryChanged = wb.on("registryChanged", (evt) => {
|
|
4169
|
+
setRegistryVersion((v) => v + 1);
|
|
4170
|
+
});
|
|
4162
4171
|
const offWbGraphChanged = wb.on("graphChanged", (event) => {
|
|
4163
4172
|
// Clear validation errors for removed nodes
|
|
4164
4173
|
if (event.change?.type === "removeNode") {
|
|
@@ -4315,8 +4324,8 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
4315
4324
|
// Registry updates: swap registry and refresh graph validation/UI
|
|
4316
4325
|
const offRunnerRegistry = runner.on("registry", async (newReg) => {
|
|
4317
4326
|
try {
|
|
4318
|
-
setRegistry(newReg);
|
|
4319
4327
|
wb.setRegistry(newReg);
|
|
4328
|
+
// Increment registry version to trigger UI updates
|
|
4320
4329
|
// Trigger a graph update so the UI revalidates with new types/enums/nodes
|
|
4321
4330
|
try {
|
|
4322
4331
|
await runner.update(wb.def);
|
|
@@ -4387,6 +4396,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
4387
4396
|
offRunnerError();
|
|
4388
4397
|
offRunnerInvalidate();
|
|
4389
4398
|
offRunnerStats();
|
|
4399
|
+
offWbRegistryChanged();
|
|
4390
4400
|
offWbGraphChanged();
|
|
4391
4401
|
offWbGraphUiChangedForLog();
|
|
4392
4402
|
offWbGraphUiChanged();
|
|
@@ -4400,7 +4410,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
4400
4410
|
offFlowViewport();
|
|
4401
4411
|
offWbRuntimeMetadataChanged();
|
|
4402
4412
|
};
|
|
4403
|
-
}, [runner, wb
|
|
4413
|
+
}, [runner, wb]);
|
|
4404
4414
|
const isRunning = useCallback(() => runner.isRunning(), [runner]);
|
|
4405
4415
|
const engineKind = useCallback(() => runner.getRunningEngine(), [runner]);
|
|
4406
4416
|
const start = useCallback((engine) => {
|
|
@@ -4478,8 +4488,6 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
4478
4488
|
const value = useMemo(() => ({
|
|
4479
4489
|
wb,
|
|
4480
4490
|
runner,
|
|
4481
|
-
registry,
|
|
4482
|
-
setRegistry,
|
|
4483
4491
|
selectedNodeId,
|
|
4484
4492
|
selectedEdgeId,
|
|
4485
4493
|
setSelection,
|
|
@@ -4514,14 +4522,13 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
4514
4522
|
updateEdgeType,
|
|
4515
4523
|
triggerExternal,
|
|
4516
4524
|
uiVersion,
|
|
4525
|
+
registryVersion,
|
|
4517
4526
|
overrides,
|
|
4518
4527
|
getNodeDisplayName,
|
|
4519
4528
|
setNodeName,
|
|
4520
4529
|
}), [
|
|
4521
4530
|
wb,
|
|
4522
4531
|
runner,
|
|
4523
|
-
registry,
|
|
4524
|
-
setRegistry,
|
|
4525
4532
|
selectedNodeId,
|
|
4526
4533
|
selectedEdgeId,
|
|
4527
4534
|
setSelection,
|
|
@@ -4555,6 +4562,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
|
|
|
4555
4562
|
wb,
|
|
4556
4563
|
runner,
|
|
4557
4564
|
uiVersion,
|
|
4565
|
+
registryVersion,
|
|
4558
4566
|
overrides,
|
|
4559
4567
|
getNodeDisplayName,
|
|
4560
4568
|
setNodeName,
|
|
@@ -4582,7 +4590,7 @@ function DefaultNodeHeader({ id, typeId, validation, right, showId, onInvalidate
|
|
|
4582
4590
|
const node = ctx.wb.def.nodes.find((n) => n.nodeId === id);
|
|
4583
4591
|
if (!node)
|
|
4584
4592
|
return id;
|
|
4585
|
-
const desc = ctx.registry.nodes.get(node.typeId);
|
|
4593
|
+
const desc = ctx.wb.registry.nodes.get(node.typeId);
|
|
4586
4594
|
return desc?.displayName || node.typeId;
|
|
4587
4595
|
}, [ctx, id, typeId]);
|
|
4588
4596
|
const handleInvalidate = React.useCallback(() => {
|
|
@@ -5041,7 +5049,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
5041
5049
|
return String(value ?? "");
|
|
5042
5050
|
}
|
|
5043
5051
|
};
|
|
5044
|
-
const { wb,
|
|
5052
|
+
const { wb, registryVersion, selectedNodeId, selectedEdgeId, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, nodeStatus, edgeStatus, validationByNode, validationByEdge, validationGlobal, valuesTick, updateEdgeType, systemErrors, registryErrors, inputValidationErrors, clearSystemErrors, clearRegistryErrors, clearInputValidationErrors, removeSystemError, removeRegistryError, removeInputValidationError, } = useWorkbenchContext();
|
|
5045
5053
|
const nodeValidationIssues = validationByNode.issues;
|
|
5046
5054
|
const edgeValidationIssues = validationByEdge.issues;
|
|
5047
5055
|
const nodeValidationHandles = validationByNode;
|
|
@@ -5050,7 +5058,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
5050
5058
|
const selectedEdge = wb.def.edges.find((e) => e.id === selectedEdgeId);
|
|
5051
5059
|
// Use computeEffectiveHandles to merge registry defaults with dynamically resolved handles
|
|
5052
5060
|
const effectiveHandles = selectedNode
|
|
5053
|
-
? computeEffectiveHandles(selectedNode, registry)
|
|
5061
|
+
? computeEffectiveHandles(selectedNode, wb.registry)
|
|
5054
5062
|
: { inputs: {}, outputs: {}};
|
|
5055
5063
|
const inputHandles = Object.entries(effectiveHandles.inputs)
|
|
5056
5064
|
.filter(([k]) => !isInputPrivate(effectiveHandles.inputs, k))
|
|
@@ -5177,7 +5185,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
5177
5185
|
setDrafts(nextDrafts);
|
|
5178
5186
|
if (!shallowEqual(originals, nextOriginals))
|
|
5179
5187
|
setOriginals(nextOriginals);
|
|
5180
|
-
}, [selectedNodeId, selectedNode, registry, valuesTick]);
|
|
5188
|
+
}, [selectedNodeId, selectedNode, wb.registry, registryVersion, valuesTick]);
|
|
5181
5189
|
const widthClass = debug ? "w-[480px]" : "w-[320px]";
|
|
5182
5190
|
const deleteEdgeById = (edgeId) => {
|
|
5183
5191
|
if (!edgeId)
|
|
@@ -5197,7 +5205,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
5197
5205
|
const v = e.target.value;
|
|
5198
5206
|
const next = v === "" ? undefined : v;
|
|
5199
5207
|
updateEdgeType(selectedEdge.id, next);
|
|
5200
|
-
}, children: [jsx("option", { value: "", children: "(infer from source)" }), Array.from(registry.types.keys()).map((tid) => (jsx("option", { value: tid, children: tid }, tid)))] })] })] }), selectedEdgeValidation.length > 0 && (jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsx("ul", { className: "list-disc ml-4", children: selectedEdgeValidation.map((m, i) => (jsxs("li", { className: "flex items-center gap-1", children: [jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsx("span", { children: `${m.code}: ${m.message}` }), jsx("button", { className: "ml-2 text-[10px] px-1 py-[2px] border border-red-300 rounded text-red-700 hover:bg-red-50", onClick: (e) => {
|
|
5208
|
+
}, children: [jsx("option", { value: "", children: "(infer from source)" }), Array.from(wb.registry.types.keys()).map((tid) => (jsx("option", { value: tid, children: tid }, tid)))] })] })] }), selectedEdgeValidation.length > 0 && (jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsx("ul", { className: "list-disc ml-4", children: selectedEdgeValidation.map((m, i) => (jsxs("li", { className: "flex items-center gap-1", children: [jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsx("span", { children: `${m.code}: ${m.message}` }), jsx("button", { className: "ml-2 text-[10px] px-1 py-[2px] border border-red-300 rounded text-red-700 hover:bg-red-50", onClick: (e) => {
|
|
5201
5209
|
e.stopPropagation();
|
|
5202
5210
|
deleteEdgeById(selectedEdge.id);
|
|
5203
5211
|
}, title: "Delete this edge", children: "Delete edge" })] }, i))) })] }))] })) : (jsxs("div", { children: [selectedNode && (jsxs("div", { className: "mb-2", children: [jsxs("div", { children: ["Node: ", selectedNode.nodeId] }), jsxs("div", { children: ["Type: ", selectedNode.typeId] }), !!selectedNodeStatus?.activeRuns &&
|
|
@@ -5267,7 +5275,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
|
|
|
5267
5275
|
setOriginals((o) => ({ ...o, [h]: display }));
|
|
5268
5276
|
}, ...commonProps, children: [jsx("option", { value: "", children: placeholder
|
|
5269
5277
|
? `Default: ${placeholder}`
|
|
5270
|
-
: "(select)" }), registry.enums
|
|
5278
|
+
: "(select)" }), wb.registry.enums
|
|
5271
5279
|
.get(typeId)
|
|
5272
5280
|
?.options.map((opt) => (jsx("option", { value: String(opt.value), children: opt.label }, opt.value)))] }), hasValue && !isLinked && (jsx("button", { className: "flex-shrink-0 p-1 hover:bg-gray-100 rounded text-gray-500 hover:text-gray-700", onClick: clearInput, title: "Clear input value", children: jsx(XCircleIcon, { size: 16 }) }))] })) : isLinked ? (jsx("div", { className: "flex items-center gap-1 flex-1", children: jsx("div", { className: "flex-1 min-w-0", children: renderLinkedInputDisplay(typeId, current) }) })) : (jsxs("div", { className: "flex items-center gap-1 flex-1", children: [jsx("input", { className: "border border-gray-300 rounded px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500 flex-1 select-text", placeholder: placeholder
|
|
5273
5281
|
? `Default: ${placeholder}`
|
|
@@ -5536,10 +5544,9 @@ function useKeyboardShortcutToast() {
|
|
|
5536
5544
|
}
|
|
5537
5545
|
|
|
5538
5546
|
const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, getDefaultNodeSize }, ref) => {
|
|
5539
|
-
const { wb,
|
|
5547
|
+
const { wb, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, registryVersion, runner, engineKind, overrides, } = useWorkbenchContext();
|
|
5540
5548
|
const nodeValidation = validationByNode;
|
|
5541
5549
|
const edgeValidation = validationByEdge.errors;
|
|
5542
|
-
const [registryVersion, setRegistryVersion] = useState(0);
|
|
5543
5550
|
const [historyState, setHistoryState] = useState(wb.getHistory());
|
|
5544
5551
|
const prevNodesRef = useRef([]);
|
|
5545
5552
|
const prevEdgesRef = useRef([]);
|
|
@@ -5615,7 +5622,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
5615
5622
|
// Build nodeTypes map using UI extension registry
|
|
5616
5623
|
const custom = new Map(); // Include all types present in registry AND current graph to avoid timing issues
|
|
5617
5624
|
const ids = new Set([
|
|
5618
|
-
...Array.from(registry.nodes.keys()),
|
|
5625
|
+
...Array.from(wb.registry.nodes.keys()),
|
|
5619
5626
|
...wb.def.nodes.map((n) => n.typeId),
|
|
5620
5627
|
]);
|
|
5621
5628
|
for (const typeId of ids) {
|
|
@@ -5633,7 +5640,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
5633
5640
|
const resolver = (nodeTypeId) => custom.has(nodeTypeId) ? `spark-${nodeTypeId}` : "spark-default";
|
|
5634
5641
|
return { nodeTypes: types, resolveNodeType: resolver };
|
|
5635
5642
|
// Include uiVersion to recompute when custom renderers are registered
|
|
5636
|
-
|
|
5643
|
+
// Include registryVersion to recompute when registry enums/types change
|
|
5644
|
+
}, [wb, wb.registry, registryVersion, uiVersion, ui]);
|
|
5637
5645
|
const edgeTypes = useMemo(() => {
|
|
5638
5646
|
// Use default edge renderer override if registered, otherwise use DefaultEdge
|
|
5639
5647
|
const customEdgeRenderer = ui.getEdgeRenderer();
|
|
@@ -5659,7 +5667,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
5659
5667
|
inputsWithDefaults[n.nodeId] = merged;
|
|
5660
5668
|
}
|
|
5661
5669
|
}
|
|
5662
|
-
const out = toReactFlow(wb.def, wb.getPositions(), wb.getSizes(), registry, {
|
|
5670
|
+
const out = toReactFlow(wb.def, wb.getPositions(), wb.getSizes(), wb.registry, {
|
|
5663
5671
|
showValues,
|
|
5664
5672
|
inputs: inputsWithDefaults,
|
|
5665
5673
|
inputDefaults: inputDefaultsMap,
|
|
@@ -5920,19 +5928,13 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
5920
5928
|
const onCloseSelectionMenu = useCallback(() => {
|
|
5921
5929
|
setSelectionMenuOpen(false);
|
|
5922
5930
|
}, []);
|
|
5923
|
-
useEffect(() => {
|
|
5924
|
-
const off = runner.on("registry", () => {
|
|
5925
|
-
setRegistryVersion((v) => v + 1);
|
|
5926
|
-
});
|
|
5927
|
-
return () => off();
|
|
5928
|
-
}, [runner]);
|
|
5929
5931
|
useEffect(() => {
|
|
5930
5932
|
const off = wb.on("historyChanged", (event) => {
|
|
5931
5933
|
setHistoryState(event.history);
|
|
5932
5934
|
});
|
|
5933
5935
|
return () => off();
|
|
5934
5936
|
}, [wb]);
|
|
5935
|
-
const nodeIds = useMemo(() => Array.from(registry.nodes.keys()), [registry, registryVersion]);
|
|
5937
|
+
const nodeIds = useMemo(() => Array.from(wb.registry.nodes.keys()), [wb.registry, registryVersion]);
|
|
5936
5938
|
const defaultContextMenuHandlers = useMemo(() => {
|
|
5937
5939
|
// Get storage from override or use workbench's internal storage
|
|
5938
5940
|
const storage = overrides?.getCopiedDataStorage
|
|
@@ -5980,7 +5982,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
5980
5982
|
get: () => wb.getCopiedData(),
|
|
5981
5983
|
set: (data) => wb.setCopiedData(data),
|
|
5982
5984
|
};
|
|
5983
|
-
const baseHandlers = createNodeContextMenuHandlers(nodeAtMenu, wb, runner, registry, outputsMap, outputTypesMap, onCloseNodeMenu, overrides?.getDefaultNodeSize, (data) => {
|
|
5985
|
+
const baseHandlers = createNodeContextMenuHandlers(nodeAtMenu, wb, runner, wb.registry, outputsMap, outputTypesMap, onCloseNodeMenu, overrides?.getDefaultNodeSize, (data) => {
|
|
5984
5986
|
storage.set(data);
|
|
5985
5987
|
});
|
|
5986
5988
|
if (overrides?.getNodeContextMenuHandlers) {
|
|
@@ -5991,7 +5993,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
5991
5993
|
nodeAtMenu,
|
|
5992
5994
|
wb,
|
|
5993
5995
|
runner,
|
|
5994
|
-
registry,
|
|
5996
|
+
wb.registry,
|
|
5997
|
+
registryVersion,
|
|
5995
5998
|
outputsMap,
|
|
5996
5999
|
outputTypesMap,
|
|
5997
6000
|
onCloseNodeMenu,
|
|
@@ -6003,8 +6006,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
6003
6006
|
const bakeableOutputs = useMemo(() => {
|
|
6004
6007
|
if (!nodeAtMenu)
|
|
6005
6008
|
return [];
|
|
6006
|
-
return getBakeableOutputs(nodeAtMenu, wb, registry, outputTypesMap);
|
|
6007
|
-
}, [nodeAtMenu, wb, registry, outputTypesMap]);
|
|
6009
|
+
return getBakeableOutputs(nodeAtMenu, wb, wb.registry, outputTypesMap);
|
|
6010
|
+
}, [nodeAtMenu, wb, wb.registry, registryVersion, outputTypesMap]);
|
|
6008
6011
|
// Keyboard shortcuts configuration
|
|
6009
6012
|
const enableKeyboardShortcuts = overrides?.enableKeyboardShortcuts !== false; // Default to true
|
|
6010
6013
|
const keyboardShortcuts = overrides?.keyboardShortcuts || {
|
|
@@ -6200,9 +6203,9 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
6200
6203
|
if (savedViewport) {
|
|
6201
6204
|
inst.setViewport(lod.clone(savedViewport));
|
|
6202
6205
|
}
|
|
6203
|
-
}, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, onMoveEnd: onMoveEnd, deleteKeyCode: ["Backspace", "Delete"], proOptions: { hideAttribution: true }, noDragClassName: "wb-nodrag", noWheelClassName: "wb-nowheel", noPanClassName: "wb-nopan", children: [BackgroundRenderer ? (jsx(BackgroundRenderer, {})) : (jsx(Background, { id: "workbench-canvas-background", variant: BackgroundVariant.Dots, gap: 12, size: 1 })), MinimapRenderer ? jsx(MinimapRenderer, {}) : jsx(MiniMap, {}), ControlsRenderer ? jsx(ControlsRenderer, {}) : jsx(Controls, {}), DefaultContextMenuRenderer ? (jsx(DefaultContextMenuRenderer, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: registry, nodeIds: nodeIds, ...(enableKeyboardShortcuts !== false
|
|
6206
|
+
}, onConnect: onConnect, onEdgesChange: onEdgesChange, onEdgesDelete: onEdgesDelete, onNodesDelete: onNodesDelete, onNodesChange: onNodesChange, onMoveEnd: onMoveEnd, deleteKeyCode: ["Backspace", "Delete"], proOptions: { hideAttribution: true }, noDragClassName: "wb-nodrag", noWheelClassName: "wb-nowheel", noPanClassName: "wb-nopan", children: [BackgroundRenderer ? (jsx(BackgroundRenderer, {})) : (jsx(Background, { id: "workbench-canvas-background", variant: BackgroundVariant.Dots, gap: 12, size: 1 })), MinimapRenderer ? jsx(MinimapRenderer, {}) : jsx(MiniMap, {}), ControlsRenderer ? jsx(ControlsRenderer, {}) : jsx(Controls, {}), DefaultContextMenuRenderer ? (jsx(DefaultContextMenuRenderer, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, ...(enableKeyboardShortcuts !== false
|
|
6204
6207
|
? { enableKeyboardShortcuts, keyboardShortcuts }
|
|
6205
|
-
: {}) })) : (jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })), !!nodeAtMenu &&
|
|
6208
|
+
: {}) })) : (jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })), !!nodeAtMenu &&
|
|
6206
6209
|
nodeContextMenuHandlers &&
|
|
6207
6210
|
(NodeContextMenuRenderer ? (jsx(NodeContextMenuRenderer, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers, canRunPull: canRunPull, bakeableOutputs: bakeableOutputs, ...(enableKeyboardShortcuts !== false
|
|
6208
6211
|
? { enableKeyboardShortcuts, keyboardShortcuts }
|
|
@@ -6211,14 +6214,14 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
|
|
|
6211
6214
|
(SelectionContextMenuRenderer ? (jsx(SelectionContextMenuRenderer, { open: selectionMenuOpen, clientPos: selectionMenuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })) : (jsx(SelectionContextMenu, { open: selectionMenuOpen, clientPos: selectionMenuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })))] }) }), toast && (jsx(KeyboardShortcutToast, { message: toast.message, onClose: hideToast }, toast.id))] }));
|
|
6212
6215
|
});
|
|
6213
6216
|
|
|
6214
|
-
function WorkbenchStudioCanvas({
|
|
6215
|
-
const { wb, runner,
|
|
6217
|
+
function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
|
|
6218
|
+
const { wb, runner, selectedNodeId, runAutoLayout } = useWorkbenchContext();
|
|
6216
6219
|
const [transportStatus, setTransportStatus] = useState({
|
|
6217
6220
|
state: "local",
|
|
6218
6221
|
});
|
|
6219
6222
|
const selectedNode = wb.def.nodes.find((n) => n.nodeId === selectedNodeId);
|
|
6220
6223
|
const effectiveHandles = selectedNode
|
|
6221
|
-
? computeEffectiveHandles(selectedNode, registry)
|
|
6224
|
+
? computeEffectiveHandles(selectedNode, wb.registry)
|
|
6222
6225
|
: { inputs: {}, outputs: {}, inputDefaults: {} };
|
|
6223
6226
|
const [exampleState, setExampleState] = useState(example ?? "");
|
|
6224
6227
|
const isGraphRunning = runner.isRunning();
|
|
@@ -6365,7 +6368,6 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
6365
6368
|
// - For remote backend, registry is automatically managed by RemoteGraphRunner
|
|
6366
6369
|
if (backendKind === "local") {
|
|
6367
6370
|
if (r) {
|
|
6368
|
-
setRegistry(r);
|
|
6369
6371
|
wb.setRegistry(r);
|
|
6370
6372
|
}
|
|
6371
6373
|
}
|
|
@@ -6381,15 +6383,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
6381
6383
|
runAutoLayout();
|
|
6382
6384
|
setExampleState(key);
|
|
6383
6385
|
onExampleChange?.(key);
|
|
6384
|
-
}, [
|
|
6385
|
-
runner,
|
|
6386
|
-
wb,
|
|
6387
|
-
onExampleChange,
|
|
6388
|
-
runAutoLayout,
|
|
6389
|
-
examples,
|
|
6390
|
-
setRegistry,
|
|
6391
|
-
backendKind,
|
|
6392
|
-
]);
|
|
6386
|
+
}, [runner, wb, onExampleChange, runAutoLayout, examples, backendKind]);
|
|
6393
6387
|
const download$1 = useCallback(async () => {
|
|
6394
6388
|
try {
|
|
6395
6389
|
await download(wb, runner);
|
|
@@ -6560,11 +6554,11 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
6560
6554
|
return overrides.setInput(baseSetInput, {
|
|
6561
6555
|
runner,
|
|
6562
6556
|
selectedNodeId,
|
|
6563
|
-
registry,
|
|
6557
|
+
registry: wb.registry,
|
|
6564
6558
|
});
|
|
6565
6559
|
}
|
|
6566
6560
|
return baseSetInput;
|
|
6567
|
-
}, [overrides, baseSetInput, runner, selectedNodeId, registry]);
|
|
6561
|
+
}, [overrides, baseSetInput, runner, selectedNodeId, wb.registry]);
|
|
6568
6562
|
const baseToString = useCallback((typeId, value) => {
|
|
6569
6563
|
if (value === undefined || value === null)
|
|
6570
6564
|
return "";
|
|
@@ -6572,7 +6566,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
6572
6566
|
if (isTypedOutput(value)) {
|
|
6573
6567
|
return baseToString(getTypedOutputTypeId(value), getTypedOutputValue(value));
|
|
6574
6568
|
}
|
|
6575
|
-
const pre = preformatValueForDisplay(typeId, value, registry);
|
|
6569
|
+
const pre = preformatValueForDisplay(typeId, value, wb.registry);
|
|
6576
6570
|
if (pre !== undefined)
|
|
6577
6571
|
return pre;
|
|
6578
6572
|
if (typeof value === "object" &&
|
|
@@ -6588,7 +6582,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
6588
6582
|
}
|
|
6589
6583
|
if (typeId && typeId.startsWith("enum:")) {
|
|
6590
6584
|
const n = Number(value);
|
|
6591
|
-
const label = registry.enums.get(typeId)?.valueToLabel.get(n);
|
|
6585
|
+
const label = wb.registry.enums.get(typeId)?.valueToLabel.get(n);
|
|
6592
6586
|
return label ?? String(n);
|
|
6593
6587
|
}
|
|
6594
6588
|
const round4 = (n) => Math.round(Number(n) * 10000) / 10000;
|
|
@@ -6618,22 +6612,22 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
|
|
|
6618
6612
|
return String(rounded);
|
|
6619
6613
|
}
|
|
6620
6614
|
return String(value);
|
|
6621
|
-
}, [registry]);
|
|
6615
|
+
}, [wb.registry]);
|
|
6622
6616
|
const baseToElement = useCallback((typeId, value) => {
|
|
6623
6617
|
return (jsx("span", { className: "ml-1 opacity-60", children: baseToString(typeId, value) }));
|
|
6624
6618
|
}, [baseToString]);
|
|
6625
6619
|
const toString = useMemo(() => {
|
|
6626
6620
|
if (overrides?.toString)
|
|
6627
|
-
return overrides.toString(baseToString, { registry });
|
|
6621
|
+
return overrides.toString(baseToString, { registry: wb.registry });
|
|
6628
6622
|
return baseToString;
|
|
6629
|
-
}, [overrides, baseToString, registry]);
|
|
6623
|
+
}, [overrides, baseToString, wb.registry]);
|
|
6630
6624
|
// Optional: toElement (not currently consumed by core UI)
|
|
6631
6625
|
// Consumers can access it by passing through their own node renderers.
|
|
6632
6626
|
const toElement = useMemo(() => {
|
|
6633
6627
|
if (overrides?.toElement)
|
|
6634
|
-
return overrides.toElement(baseToElement, { registry });
|
|
6628
|
+
return overrides.toElement(baseToElement, { registry: wb.registry });
|
|
6635
6629
|
return baseToElement;
|
|
6636
|
-
}, [overrides, baseToElement, registry]);
|
|
6630
|
+
}, [overrides, baseToElement, wb.registry]);
|
|
6637
6631
|
return (jsxs("div", { className: "w-full h-screen flex flex-col", children: [jsxs("div", { className: "p-2 border-b border-gray-300 flex gap-2 items-center", children: [isGraphRunning ? (jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", engineKind] })) : (jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsxs("span", { className: "ml-2 flex items-center gap-1 text-xs", title: transportStatus.kind || undefined, children: [transportStatus.state === "local" && (jsx(PlugsConnectedIcon, { size: 14, className: "text-gray-500" })), transportStatus.state === "connecting" && (jsx(ClockClockwiseIcon, { size: 14, className: "text-amber-600 animate-pulse" })), transportStatus.state === "connected" && (jsx(WifiHighIcon, { size: 14, className: "text-green-600" })), transportStatus.state === "disconnected" && (jsx(WifiSlashIcon, { size: 14, className: "text-red-600" })), transportStatus.state === "retrying" && (jsx(ClockClockwiseIcon, { size: 14, className: "text-amber-700 animate-pulse" }))] }), jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: exampleState, onChange: (e) => applyExample(e.target.value), disabled: isGraphRunning, title: isGraphRunning ? "Stop engine before switching example" : undefined, children: [jsx("option", { value: "", children: "Select Example\u2026" }), examples.map((ex) => (jsx("option", { value: ex.id, children: ex.label }, ex.id)))] }), jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: backendKind, onChange: (e) => onBackendKindChange(e.target.value), disabled: isGraphRunning, title: isGraphRunning ? "Stop engine before switching backend" : undefined, children: [jsx("option", { value: "local", children: "Local" }), jsx("option", { value: "remote-http", children: "Remote (HTTP)" }), jsx("option", { value: "remote-ws", children: "Remote (WebSocket)" })] }), backendKind === "remote-http" && !!onHttpBaseUrlChange && (jsx("input", { className: "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" && !!onWsUrlChange && (jsx("input", { className: "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) })), jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: engineKind ?? engine ?? "", onChange: async (e) => {
|
|
6638
6632
|
const kind = e.target.value || undefined;
|
|
6639
6633
|
const currentEngine = runner.getRunningEngine();
|
|
@@ -6735,7 +6729,7 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
|
|
|
6735
6729
|
runner.dispose();
|
|
6736
6730
|
onBackendKindChange(v);
|
|
6737
6731
|
}, [isGraphRunning]);
|
|
6738
|
-
return (jsx(WorkbenchProvider, { wb: wb, runner: runner,
|
|
6732
|
+
return (jsx(WorkbenchProvider, { wb: wb, runner: runner, overrides: overrides, uiVersion: uiVersion, children: jsx(WorkbenchStudioCanvas, { setRegistry: setRegistry, autoScroll: autoScroll, onAutoScrollChange: onAutoScrollChange, example: example, onExampleChange: onExampleChange, engine: engine, onEngineChange: onEngineChange, backendKind: backendKind, onBackendKindChange: onBackendKindChangeWithDispose, httpBaseUrl: httpBaseUrl, onHttpBaseUrlChange: onHttpBaseUrlChange, wsUrl: wsUrl, onWsUrlChange: onWsUrlChange, debug: debug, onDebugChange: onDebugChange, showValues: showValues, onShowValuesChange: onShowValuesChange, hideWorkbench: hideWorkbench, onHideWorkbenchChange: onHideWorkbenchChange, overrides: overrides, onInit: onInit, onChange: onChange }) }));
|
|
6739
6733
|
}
|
|
6740
6734
|
|
|
6741
6735
|
export { AbstractWorkbench, CLIWorkbench, DefaultEdge, DefaultNode, DefaultNodeContent, DefaultNodeHeader, DefaultUIExtensionRegistry, InMemoryWorkbench, Inspector, LocalGraphRunner, NodeHandles, RemoteGraphRunner, WorkbenchCanvas, WorkbenchContext, WorkbenchProvider, WorkbenchStudio, captureCanvasThumbnail, computeEffectiveHandles, countVisibleHandles, createCopyHandler, createDefaultContextMenuHandlers, createHandleBounds, createHandleLayout, createNodeContextMenuHandlers, createNodeCopyHandler, createSelectionContextMenuHandlers, download, downloadCanvasThumbnail, estimateNodeSize, excludeViewportFromUIState, formatDataUrlAsLabel, formatDeclaredTypeSignature, getBakeableOutputs, getHandleBoundsX, getHandleBoundsY, getHandleClassName, getHandleLayoutY, getNodeBorderClassNames, isValidViewport, layoutNode, mergeUIState, preformatValueForDisplay, prettyHandle, resolveOutputDisplay, summarizeDeep, toReactFlow, upload, useQueryParamBoolean, useQueryParamString, useThrottledValue, useWorkbenchBridge, useWorkbenchContext, useWorkbenchGraphTick, useWorkbenchGraphUiTick, useWorkbenchVersionTick };
|