@bian-womp/spark-workbench 0.2.93 → 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/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { generateId, GraphBuilder, getTypedOutputValue, isTypedOutput, getInputTypeId, createEngine, StepEngine, PullEngine, BatchedEngine, getTypedOutputTypeId, isInputPrivate, offsetImportedPositions, createSimpleGraphRegistry, createSimpleGraphDef, createAsyncGraphDef, createAsyncGraphRegistry, createProgressGraphDef, createProgressGraphRegistry, createValidationGraphDef, createValidationGraphRegistry } from '@bian-womp/spark-graph';
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(...arguments);
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.registry = registry;
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, registry, setRegistry, overrides, uiVersion, children, }) {
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([]);
@@ -3722,7 +3727,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3722
3727
  const out = {};
3723
3728
  // Local: runtimeTypeId is not stored; derive from typed wrapper in outputsMap
3724
3729
  for (const n of wb.def.nodes) {
3725
- const effectiveHandles = computeEffectiveHandles(n, registry);
3730
+ const effectiveHandles = computeEffectiveHandles(n, wb.registry);
3726
3731
  const outputsDecl = effectiveHandles.outputs;
3727
3732
  const handles = Object.keys(outputsDecl);
3728
3733
  const cur = {};
@@ -3736,7 +3741,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3736
3741
  out[n.nodeId] = cur;
3737
3742
  }
3738
3743
  return out;
3739
- }, [wb, wb.def, outputsMap, registry]);
3744
+ }, [wb, wb.def, outputsMap, wb.registry, registryVersion]);
3740
3745
  // Initialize nodes and derive invalidated status from persisted metadata
3741
3746
  useEffect(() => {
3742
3747
  const workbenchRuntimeState = wb.getRuntimeState() ?? { nodes: {} };
@@ -3814,7 +3819,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3814
3819
  const overrideSize = overrides?.getDefaultNodeSize?.(node.typeId) ?? undefined;
3815
3820
  const size = estimateNodeSize({
3816
3821
  node,
3817
- registry,
3822
+ registry: wb.registry,
3818
3823
  showValues: true,
3819
3824
  overrides: overrideSize,
3820
3825
  });
@@ -3832,7 +3837,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3832
3837
  curX += maxWidth + H_GAP;
3833
3838
  }
3834
3839
  wb.setPositions(pos, { commit: true, reason: "auto-layout" });
3835
- }, [wb, wb.def, registry, overrides?.getDefaultNodeSize]);
3840
+ }, [wb, wb.def, wb.registry, registryVersion, overrides?.getDefaultNodeSize]);
3836
3841
  const updateEdgeType = useCallback((edgeId, typeId) => wb.updateEdgeType(edgeId, typeId), [wb]);
3837
3842
  const triggerExternal = useCallback((nodeId, event) => runner.triggerExternal(nodeId, event), [runner]);
3838
3843
  const getNodeDisplayName = useCallback((nodeId) => {
@@ -3842,9 +3847,9 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3842
3847
  const node = wb.def.nodes.find((n) => n.nodeId === nodeId);
3843
3848
  if (!node)
3844
3849
  return nodeId;
3845
- const desc = registry.nodes.get(node.typeId);
3850
+ const desc = wb.registry.nodes.get(node.typeId);
3846
3851
  return desc?.displayName || node.typeId;
3847
- }, [wb, registry]);
3852
+ }, [wb, wb.registry, registryVersion]);
3848
3853
  const setNodeName = useCallback((nodeId, name) => {
3849
3854
  wb.setNodeName(nodeId, name, { commit: true, reason: "rename-node" });
3850
3855
  }, [wb]);
@@ -4160,6 +4165,9 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4160
4165
  }
4161
4166
  return add("runner", "stats")(s);
4162
4167
  });
4168
+ const offWbRegistryChanged = wb.on("registryChanged", (evt) => {
4169
+ setRegistryVersion((v) => v + 1);
4170
+ });
4163
4171
  const offWbGraphChanged = wb.on("graphChanged", (event) => {
4164
4172
  // Clear validation errors for removed nodes
4165
4173
  if (event.change?.type === "removeNode") {
@@ -4316,10 +4324,8 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4316
4324
  // Registry updates: swap registry and refresh graph validation/UI
4317
4325
  const offRunnerRegistry = runner.on("registry", async (newReg) => {
4318
4326
  try {
4319
- setRegistry(newReg);
4320
4327
  wb.setRegistry(newReg);
4321
4328
  // Increment registry version to trigger UI updates
4322
- setRegistryVersion((v) => v + 1);
4323
4329
  // Trigger a graph update so the UI revalidates with new types/enums/nodes
4324
4330
  try {
4325
4331
  await runner.update(wb.def);
@@ -4390,6 +4396,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4390
4396
  offRunnerError();
4391
4397
  offRunnerInvalidate();
4392
4398
  offRunnerStats();
4399
+ offWbRegistryChanged();
4393
4400
  offWbGraphChanged();
4394
4401
  offWbGraphUiChangedForLog();
4395
4402
  offWbGraphUiChanged();
@@ -4403,7 +4410,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4403
4410
  offFlowViewport();
4404
4411
  offWbRuntimeMetadataChanged();
4405
4412
  };
4406
- }, [runner, wb, setRegistry]);
4413
+ }, [runner, wb]);
4407
4414
  const isRunning = useCallback(() => runner.isRunning(), [runner]);
4408
4415
  const engineKind = useCallback(() => runner.getRunningEngine(), [runner]);
4409
4416
  const start = useCallback((engine) => {
@@ -4481,8 +4488,6 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4481
4488
  const value = useMemo(() => ({
4482
4489
  wb,
4483
4490
  runner,
4484
- registry,
4485
- setRegistry,
4486
4491
  selectedNodeId,
4487
4492
  selectedEdgeId,
4488
4493
  setSelection,
@@ -4524,8 +4529,6 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4524
4529
  }), [
4525
4530
  wb,
4526
4531
  runner,
4527
- registry,
4528
- setRegistry,
4529
4532
  selectedNodeId,
4530
4533
  selectedEdgeId,
4531
4534
  setSelection,
@@ -4587,7 +4590,7 @@ function DefaultNodeHeader({ id, typeId, validation, right, showId, onInvalidate
4587
4590
  const node = ctx.wb.def.nodes.find((n) => n.nodeId === id);
4588
4591
  if (!node)
4589
4592
  return id;
4590
- const desc = ctx.registry.nodes.get(node.typeId);
4593
+ const desc = ctx.wb.registry.nodes.get(node.typeId);
4591
4594
  return desc?.displayName || node.typeId;
4592
4595
  }, [ctx, id, typeId]);
4593
4596
  const handleInvalidate = React.useCallback(() => {
@@ -5046,7 +5049,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5046
5049
  return String(value ?? "");
5047
5050
  }
5048
5051
  };
5049
- const { wb, registry, selectedNodeId, selectedEdgeId, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, nodeStatus, edgeStatus, validationByNode, validationByEdge, validationGlobal, valuesTick, updateEdgeType, systemErrors, registryErrors, inputValidationErrors, clearSystemErrors, clearRegistryErrors, clearInputValidationErrors, removeSystemError, removeRegistryError, removeInputValidationError, } = useWorkbenchContext();
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();
5050
5053
  const nodeValidationIssues = validationByNode.issues;
5051
5054
  const edgeValidationIssues = validationByEdge.issues;
5052
5055
  const nodeValidationHandles = validationByNode;
@@ -5055,7 +5058,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5055
5058
  const selectedEdge = wb.def.edges.find((e) => e.id === selectedEdgeId);
5056
5059
  // Use computeEffectiveHandles to merge registry defaults with dynamically resolved handles
5057
5060
  const effectiveHandles = selectedNode
5058
- ? computeEffectiveHandles(selectedNode, registry)
5061
+ ? computeEffectiveHandles(selectedNode, wb.registry)
5059
5062
  : { inputs: {}, outputs: {}};
5060
5063
  const inputHandles = Object.entries(effectiveHandles.inputs)
5061
5064
  .filter(([k]) => !isInputPrivate(effectiveHandles.inputs, k))
@@ -5182,7 +5185,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5182
5185
  setDrafts(nextDrafts);
5183
5186
  if (!shallowEqual(originals, nextOriginals))
5184
5187
  setOriginals(nextOriginals);
5185
- }, [selectedNodeId, selectedNode, registry, valuesTick]);
5188
+ }, [selectedNodeId, selectedNode, wb.registry, registryVersion, valuesTick]);
5186
5189
  const widthClass = debug ? "w-[480px]" : "w-[320px]";
5187
5190
  const deleteEdgeById = (edgeId) => {
5188
5191
  if (!edgeId)
@@ -5202,7 +5205,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5202
5205
  const v = e.target.value;
5203
5206
  const next = v === "" ? undefined : v;
5204
5207
  updateEdgeType(selectedEdge.id, next);
5205
- }, 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) => {
5206
5209
  e.stopPropagation();
5207
5210
  deleteEdgeById(selectedEdge.id);
5208
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 &&
@@ -5272,7 +5275,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5272
5275
  setOriginals((o) => ({ ...o, [h]: display }));
5273
5276
  }, ...commonProps, children: [jsx("option", { value: "", children: placeholder
5274
5277
  ? `Default: ${placeholder}`
5275
- : "(select)" }), registry.enums
5278
+ : "(select)" }), wb.registry.enums
5276
5279
  .get(typeId)
5277
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
5278
5281
  ? `Default: ${placeholder}`
@@ -5541,7 +5544,7 @@ function useKeyboardShortcutToast() {
5541
5544
  }
5542
5545
 
5543
5546
  const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, getDefaultNodeSize }, ref) => {
5544
- const { wb, registry, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, registryVersion, runner, engineKind, overrides, } = useWorkbenchContext();
5547
+ const { wb, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, registryVersion, runner, engineKind, overrides, } = useWorkbenchContext();
5545
5548
  const nodeValidation = validationByNode;
5546
5549
  const edgeValidation = validationByEdge.errors;
5547
5550
  const [historyState, setHistoryState] = useState(wb.getHistory());
@@ -5619,7 +5622,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5619
5622
  // Build nodeTypes map using UI extension registry
5620
5623
  const custom = new Map(); // Include all types present in registry AND current graph to avoid timing issues
5621
5624
  const ids = new Set([
5622
- ...Array.from(registry.nodes.keys()),
5625
+ ...Array.from(wb.registry.nodes.keys()),
5623
5626
  ...wb.def.nodes.map((n) => n.typeId),
5624
5627
  ]);
5625
5628
  for (const typeId of ids) {
@@ -5638,7 +5641,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5638
5641
  return { nodeTypes: types, resolveNodeType: resolver };
5639
5642
  // Include uiVersion to recompute when custom renderers are registered
5640
5643
  // Include registryVersion to recompute when registry enums/types change
5641
- }, [wb, registry, uiVersion, ui]);
5644
+ }, [wb, wb.registry, registryVersion, uiVersion, ui]);
5642
5645
  const edgeTypes = useMemo(() => {
5643
5646
  // Use default edge renderer override if registered, otherwise use DefaultEdge
5644
5647
  const customEdgeRenderer = ui.getEdgeRenderer();
@@ -5664,7 +5667,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5664
5667
  inputsWithDefaults[n.nodeId] = merged;
5665
5668
  }
5666
5669
  }
5667
- const out = toReactFlow(wb.def, wb.getPositions(), wb.getSizes(), registry, {
5670
+ const out = toReactFlow(wb.def, wb.getPositions(), wb.getSizes(), wb.registry, {
5668
5671
  showValues,
5669
5672
  inputs: inputsWithDefaults,
5670
5673
  inputDefaults: inputDefaultsMap,
@@ -5931,7 +5934,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5931
5934
  });
5932
5935
  return () => off();
5933
5936
  }, [wb]);
5934
- const nodeIds = useMemo(() => Array.from(registry.nodes.keys()), [registry, registryVersion]);
5937
+ const nodeIds = useMemo(() => Array.from(wb.registry.nodes.keys()), [wb.registry, registryVersion]);
5935
5938
  const defaultContextMenuHandlers = useMemo(() => {
5936
5939
  // Get storage from override or use workbench's internal storage
5937
5940
  const storage = overrides?.getCopiedDataStorage
@@ -5979,7 +5982,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5979
5982
  get: () => wb.getCopiedData(),
5980
5983
  set: (data) => wb.setCopiedData(data),
5981
5984
  };
5982
- 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) => {
5983
5986
  storage.set(data);
5984
5987
  });
5985
5988
  if (overrides?.getNodeContextMenuHandlers) {
@@ -5990,7 +5993,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5990
5993
  nodeAtMenu,
5991
5994
  wb,
5992
5995
  runner,
5993
- registry,
5996
+ wb.registry,
5997
+ registryVersion,
5994
5998
  outputsMap,
5995
5999
  outputTypesMap,
5996
6000
  onCloseNodeMenu,
@@ -6002,8 +6006,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
6002
6006
  const bakeableOutputs = useMemo(() => {
6003
6007
  if (!nodeAtMenu)
6004
6008
  return [];
6005
- return getBakeableOutputs(nodeAtMenu, wb, registry, outputTypesMap);
6006
- }, [nodeAtMenu, wb, registry, outputTypesMap]);
6009
+ return getBakeableOutputs(nodeAtMenu, wb, wb.registry, outputTypesMap);
6010
+ }, [nodeAtMenu, wb, wb.registry, registryVersion, outputTypesMap]);
6007
6011
  // Keyboard shortcuts configuration
6008
6012
  const enableKeyboardShortcuts = overrides?.enableKeyboardShortcuts !== false; // Default to true
6009
6013
  const keyboardShortcuts = overrides?.keyboardShortcuts || {
@@ -6199,9 +6203,9 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
6199
6203
  if (savedViewport) {
6200
6204
  inst.setViewport(lod.clone(savedViewport));
6201
6205
  }
6202
- }, 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
6203
6207
  ? { enableKeyboardShortcuts, keyboardShortcuts }
6204
- : {}) })) : (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 &&
6205
6209
  nodeContextMenuHandlers &&
6206
6210
  (NodeContextMenuRenderer ? (jsx(NodeContextMenuRenderer, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers, canRunPull: canRunPull, bakeableOutputs: bakeableOutputs, ...(enableKeyboardShortcuts !== false
6207
6211
  ? { enableKeyboardShortcuts, keyboardShortcuts }
@@ -6210,14 +6214,14 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
6210
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))] }));
6211
6215
  });
6212
6216
 
6213
- function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
6214
- const { wb, runner, registry, selectedNodeId, runAutoLayout } = useWorkbenchContext();
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();
6215
6219
  const [transportStatus, setTransportStatus] = useState({
6216
6220
  state: "local",
6217
6221
  });
6218
6222
  const selectedNode = wb.def.nodes.find((n) => n.nodeId === selectedNodeId);
6219
6223
  const effectiveHandles = selectedNode
6220
- ? computeEffectiveHandles(selectedNode, registry)
6224
+ ? computeEffectiveHandles(selectedNode, wb.registry)
6221
6225
  : { inputs: {}, outputs: {}, inputDefaults: {} };
6222
6226
  const [exampleState, setExampleState] = useState(example ?? "");
6223
6227
  const isGraphRunning = runner.isRunning();
@@ -6364,7 +6368,6 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6364
6368
  // - For remote backend, registry is automatically managed by RemoteGraphRunner
6365
6369
  if (backendKind === "local") {
6366
6370
  if (r) {
6367
- setRegistry(r);
6368
6371
  wb.setRegistry(r);
6369
6372
  }
6370
6373
  }
@@ -6380,15 +6383,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6380
6383
  runAutoLayout();
6381
6384
  setExampleState(key);
6382
6385
  onExampleChange?.(key);
6383
- }, [
6384
- runner,
6385
- wb,
6386
- onExampleChange,
6387
- runAutoLayout,
6388
- examples,
6389
- setRegistry,
6390
- backendKind,
6391
- ]);
6386
+ }, [runner, wb, onExampleChange, runAutoLayout, examples, backendKind]);
6392
6387
  const download$1 = useCallback(async () => {
6393
6388
  try {
6394
6389
  await download(wb, runner);
@@ -6559,11 +6554,11 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6559
6554
  return overrides.setInput(baseSetInput, {
6560
6555
  runner,
6561
6556
  selectedNodeId,
6562
- registry,
6557
+ registry: wb.registry,
6563
6558
  });
6564
6559
  }
6565
6560
  return baseSetInput;
6566
- }, [overrides, baseSetInput, runner, selectedNodeId, registry]);
6561
+ }, [overrides, baseSetInput, runner, selectedNodeId, wb.registry]);
6567
6562
  const baseToString = useCallback((typeId, value) => {
6568
6563
  if (value === undefined || value === null)
6569
6564
  return "";
@@ -6571,7 +6566,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6571
6566
  if (isTypedOutput(value)) {
6572
6567
  return baseToString(getTypedOutputTypeId(value), getTypedOutputValue(value));
6573
6568
  }
6574
- const pre = preformatValueForDisplay(typeId, value, registry);
6569
+ const pre = preformatValueForDisplay(typeId, value, wb.registry);
6575
6570
  if (pre !== undefined)
6576
6571
  return pre;
6577
6572
  if (typeof value === "object" &&
@@ -6587,7 +6582,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6587
6582
  }
6588
6583
  if (typeId && typeId.startsWith("enum:")) {
6589
6584
  const n = Number(value);
6590
- const label = registry.enums.get(typeId)?.valueToLabel.get(n);
6585
+ const label = wb.registry.enums.get(typeId)?.valueToLabel.get(n);
6591
6586
  return label ?? String(n);
6592
6587
  }
6593
6588
  const round4 = (n) => Math.round(Number(n) * 10000) / 10000;
@@ -6617,22 +6612,22 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6617
6612
  return String(rounded);
6618
6613
  }
6619
6614
  return String(value);
6620
- }, [registry]);
6615
+ }, [wb.registry]);
6621
6616
  const baseToElement = useCallback((typeId, value) => {
6622
6617
  return (jsx("span", { className: "ml-1 opacity-60", children: baseToString(typeId, value) }));
6623
6618
  }, [baseToString]);
6624
6619
  const toString = useMemo(() => {
6625
6620
  if (overrides?.toString)
6626
- return overrides.toString(baseToString, { registry });
6621
+ return overrides.toString(baseToString, { registry: wb.registry });
6627
6622
  return baseToString;
6628
- }, [overrides, baseToString, registry]);
6623
+ }, [overrides, baseToString, wb.registry]);
6629
6624
  // Optional: toElement (not currently consumed by core UI)
6630
6625
  // Consumers can access it by passing through their own node renderers.
6631
6626
  const toElement = useMemo(() => {
6632
6627
  if (overrides?.toElement)
6633
- return overrides.toElement(baseToElement, { registry });
6628
+ return overrides.toElement(baseToElement, { registry: wb.registry });
6634
6629
  return baseToElement;
6635
- }, [overrides, baseToElement, registry]);
6630
+ }, [overrides, baseToElement, wb.registry]);
6636
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) => {
6637
6632
  const kind = e.target.value || undefined;
6638
6633
  const currentEngine = runner.getRunningEngine();
@@ -6734,7 +6729,7 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
6734
6729
  runner.dispose();
6735
6730
  onBackendKindChange(v);
6736
6731
  }, [isGraphRunning]);
6737
- return (jsx(WorkbenchProvider, { wb: wb, runner: runner, registry: registry, setRegistry: setRegistry, 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 }) }));
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 }) }));
6738
6733
  }
6739
6734
 
6740
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 };