@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/cjs/index.cjs CHANGED
@@ -135,8 +135,8 @@ class AbstractWorkbench {
135
135
  }
136
136
 
137
137
  class InMemoryWorkbench extends AbstractWorkbench {
138
- constructor() {
139
- super(...arguments);
138
+ constructor(args) {
139
+ super(args);
140
140
  this._def = { nodes: [], edges: [] };
141
141
  this.listeners = new Map();
142
142
  this.positions = {};
@@ -150,12 +150,17 @@ class InMemoryWorkbench extends AbstractWorkbench {
150
150
  this.viewport = null;
151
151
  this.historyState = undefined;
152
152
  this.copiedData = null;
153
+ this._registry = sparkGraph.createSimpleGraphRegistry();
153
154
  }
154
155
  get def() {
155
156
  return this._def;
156
157
  }
158
+ get registry() {
159
+ return this._registry;
160
+ }
157
161
  setRegistry(registry) {
158
- this.registry = registry;
162
+ this._registry = registry;
163
+ this.emit("registryChanged", { registry });
159
164
  }
160
165
  async load(def) {
161
166
  this._def = { nodes: [...def.nodes], edges: [...def.edges] };
@@ -3649,7 +3654,7 @@ function computeInvalidatedFromMetadata(metadata) {
3649
3654
  const maxInputTime = Math.max(...Object.values(lastInputAt));
3650
3655
  return maxInputTime > (lastSuccessAt ?? lastRunAt ?? 0);
3651
3656
  }
3652
- function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVersion, children, }) {
3657
+ function WorkbenchProvider({ wb, runner, overrides, uiVersion, children, }) {
3653
3658
  const [nodeStatus, setNodeStatus] = React.useState({});
3654
3659
  const [edgeStatus, setEdgeStatus] = React.useState({});
3655
3660
  const [events, setEvents] = React.useState([]);
@@ -3724,7 +3729,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3724
3729
  const out = {};
3725
3730
  // Local: runtimeTypeId is not stored; derive from typed wrapper in outputsMap
3726
3731
  for (const n of wb.def.nodes) {
3727
- const effectiveHandles = computeEffectiveHandles(n, registry);
3732
+ const effectiveHandles = computeEffectiveHandles(n, wb.registry);
3728
3733
  const outputsDecl = effectiveHandles.outputs;
3729
3734
  const handles = Object.keys(outputsDecl);
3730
3735
  const cur = {};
@@ -3738,7 +3743,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3738
3743
  out[n.nodeId] = cur;
3739
3744
  }
3740
3745
  return out;
3741
- }, [wb, wb.def, outputsMap, registry]);
3746
+ }, [wb, wb.def, outputsMap, wb.registry, registryVersion]);
3742
3747
  // Initialize nodes and derive invalidated status from persisted metadata
3743
3748
  React.useEffect(() => {
3744
3749
  const workbenchRuntimeState = wb.getRuntimeState() ?? { nodes: {} };
@@ -3816,7 +3821,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3816
3821
  const overrideSize = overrides?.getDefaultNodeSize?.(node.typeId) ?? undefined;
3817
3822
  const size = estimateNodeSize({
3818
3823
  node,
3819
- registry,
3824
+ registry: wb.registry,
3820
3825
  showValues: true,
3821
3826
  overrides: overrideSize,
3822
3827
  });
@@ -3834,7 +3839,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3834
3839
  curX += maxWidth + H_GAP;
3835
3840
  }
3836
3841
  wb.setPositions(pos, { commit: true, reason: "auto-layout" });
3837
- }, [wb, wb.def, registry, overrides?.getDefaultNodeSize]);
3842
+ }, [wb, wb.def, wb.registry, registryVersion, overrides?.getDefaultNodeSize]);
3838
3843
  const updateEdgeType = React.useCallback((edgeId, typeId) => wb.updateEdgeType(edgeId, typeId), [wb]);
3839
3844
  const triggerExternal = React.useCallback((nodeId, event) => runner.triggerExternal(nodeId, event), [runner]);
3840
3845
  const getNodeDisplayName = React.useCallback((nodeId) => {
@@ -3844,9 +3849,9 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
3844
3849
  const node = wb.def.nodes.find((n) => n.nodeId === nodeId);
3845
3850
  if (!node)
3846
3851
  return nodeId;
3847
- const desc = registry.nodes.get(node.typeId);
3852
+ const desc = wb.registry.nodes.get(node.typeId);
3848
3853
  return desc?.displayName || node.typeId;
3849
- }, [wb, registry]);
3854
+ }, [wb, wb.registry, registryVersion]);
3850
3855
  const setNodeName = React.useCallback((nodeId, name) => {
3851
3856
  wb.setNodeName(nodeId, name, { commit: true, reason: "rename-node" });
3852
3857
  }, [wb]);
@@ -4162,6 +4167,9 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4162
4167
  }
4163
4168
  return add("runner", "stats")(s);
4164
4169
  });
4170
+ const offWbRegistryChanged = wb.on("registryChanged", (evt) => {
4171
+ setRegistryVersion((v) => v + 1);
4172
+ });
4165
4173
  const offWbGraphChanged = wb.on("graphChanged", (event) => {
4166
4174
  // Clear validation errors for removed nodes
4167
4175
  if (event.change?.type === "removeNode") {
@@ -4318,10 +4326,8 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4318
4326
  // Registry updates: swap registry and refresh graph validation/UI
4319
4327
  const offRunnerRegistry = runner.on("registry", async (newReg) => {
4320
4328
  try {
4321
- setRegistry(newReg);
4322
4329
  wb.setRegistry(newReg);
4323
4330
  // Increment registry version to trigger UI updates
4324
- setRegistryVersion((v) => v + 1);
4325
4331
  // Trigger a graph update so the UI revalidates with new types/enums/nodes
4326
4332
  try {
4327
4333
  await runner.update(wb.def);
@@ -4392,6 +4398,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4392
4398
  offRunnerError();
4393
4399
  offRunnerInvalidate();
4394
4400
  offRunnerStats();
4401
+ offWbRegistryChanged();
4395
4402
  offWbGraphChanged();
4396
4403
  offWbGraphUiChangedForLog();
4397
4404
  offWbGraphUiChanged();
@@ -4405,7 +4412,7 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4405
4412
  offFlowViewport();
4406
4413
  offWbRuntimeMetadataChanged();
4407
4414
  };
4408
- }, [runner, wb, setRegistry]);
4415
+ }, [runner, wb]);
4409
4416
  const isRunning = React.useCallback(() => runner.isRunning(), [runner]);
4410
4417
  const engineKind = React.useCallback(() => runner.getRunningEngine(), [runner]);
4411
4418
  const start = React.useCallback((engine) => {
@@ -4483,8 +4490,6 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4483
4490
  const value = React.useMemo(() => ({
4484
4491
  wb,
4485
4492
  runner,
4486
- registry,
4487
- setRegistry,
4488
4493
  selectedNodeId,
4489
4494
  selectedEdgeId,
4490
4495
  setSelection,
@@ -4526,8 +4531,6 @@ function WorkbenchProvider({ wb, runner, registry, setRegistry, overrides, uiVer
4526
4531
  }), [
4527
4532
  wb,
4528
4533
  runner,
4529
- registry,
4530
- setRegistry,
4531
4534
  selectedNodeId,
4532
4535
  selectedEdgeId,
4533
4536
  setSelection,
@@ -4589,7 +4592,7 @@ function DefaultNodeHeader({ id, typeId, validation, right, showId, onInvalidate
4589
4592
  const node = ctx.wb.def.nodes.find((n) => n.nodeId === id);
4590
4593
  if (!node)
4591
4594
  return id;
4592
- const desc = ctx.registry.nodes.get(node.typeId);
4595
+ const desc = ctx.wb.registry.nodes.get(node.typeId);
4593
4596
  return desc?.displayName || node.typeId;
4594
4597
  }, [ctx, id, typeId]);
4595
4598
  const handleInvalidate = React.useCallback(() => {
@@ -5048,7 +5051,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5048
5051
  return String(value ?? "");
5049
5052
  }
5050
5053
  };
5051
- 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();
5054
+ 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();
5052
5055
  const nodeValidationIssues = validationByNode.issues;
5053
5056
  const edgeValidationIssues = validationByEdge.issues;
5054
5057
  const nodeValidationHandles = validationByNode;
@@ -5057,7 +5060,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5057
5060
  const selectedEdge = wb.def.edges.find((e) => e.id === selectedEdgeId);
5058
5061
  // Use computeEffectiveHandles to merge registry defaults with dynamically resolved handles
5059
5062
  const effectiveHandles = selectedNode
5060
- ? computeEffectiveHandles(selectedNode, registry)
5063
+ ? computeEffectiveHandles(selectedNode, wb.registry)
5061
5064
  : { inputs: {}, outputs: {}};
5062
5065
  const inputHandles = Object.entries(effectiveHandles.inputs)
5063
5066
  .filter(([k]) => !sparkGraph.isInputPrivate(effectiveHandles.inputs, k))
@@ -5184,7 +5187,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5184
5187
  setDrafts(nextDrafts);
5185
5188
  if (!shallowEqual(originals, nextOriginals))
5186
5189
  setOriginals(nextOriginals);
5187
- }, [selectedNodeId, selectedNode, registry, valuesTick]);
5190
+ }, [selectedNodeId, selectedNode, wb.registry, registryVersion, valuesTick]);
5188
5191
  const widthClass = debug ? "w-[480px]" : "w-[320px]";
5189
5192
  const deleteEdgeById = (edgeId) => {
5190
5193
  if (!edgeId)
@@ -5204,7 +5207,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5204
5207
  const v = e.target.value;
5205
5208
  const next = v === "" ? undefined : v;
5206
5209
  updateEdgeType(selectedEdge.id, next);
5207
- }, children: [jsxRuntime.jsx("option", { value: "", children: "(infer from source)" }), Array.from(registry.types.keys()).map((tid) => (jsxRuntime.jsx("option", { value: tid, children: tid }, tid)))] })] })] }), selectedEdgeValidation.length > 0 && (jsxRuntime.jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsxRuntime.jsx("ul", { className: "list-disc ml-4", children: selectedEdgeValidation.map((m, i) => (jsxRuntime.jsxs("li", { className: "flex items-center gap-1", children: [jsxRuntime.jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsxRuntime.jsx("span", { children: `${m.code}: ${m.message}` }), jsxRuntime.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) => {
5210
+ }, children: [jsxRuntime.jsx("option", { value: "", children: "(infer from source)" }), Array.from(wb.registry.types.keys()).map((tid) => (jsxRuntime.jsx("option", { value: tid, children: tid }, tid)))] })] })] }), selectedEdgeValidation.length > 0 && (jsxRuntime.jsxs("div", { className: "mt-2 text-xs bg-red-50 border border-red-200 rounded px-2 py-1", children: [jsxRuntime.jsx("div", { className: "font-semibold mb-1", children: "Validation" }), jsxRuntime.jsx("ul", { className: "list-disc ml-4", children: selectedEdgeValidation.map((m, i) => (jsxRuntime.jsxs("li", { className: "flex items-center gap-1", children: [jsxRuntime.jsx(IssueBadge, { level: m.level, size: 24, className: "w-6 h-6" }), jsxRuntime.jsx("span", { children: `${m.code}: ${m.message}` }), jsxRuntime.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
5211
  e.stopPropagation();
5209
5212
  deleteEdgeById(selectedEdge.id);
5210
5213
  }, title: "Delete this edge", children: "Delete edge" })] }, i))) })] }))] })) : (jsxRuntime.jsxs("div", { children: [selectedNode && (jsxRuntime.jsxs("div", { className: "mb-2", children: [jsxRuntime.jsxs("div", { children: ["Node: ", selectedNode.nodeId] }), jsxRuntime.jsxs("div", { children: ["Type: ", selectedNode.typeId] }), !!selectedNodeStatus?.activeRuns &&
@@ -5274,7 +5277,7 @@ function Inspector({ debug, autoScroll, hideWorkbench, onAutoScrollChange, onHid
5274
5277
  setOriginals((o) => ({ ...o, [h]: display }));
5275
5278
  }, ...commonProps, children: [jsxRuntime.jsx("option", { value: "", children: placeholder
5276
5279
  ? `Default: ${placeholder}`
5277
- : "(select)" }), registry.enums
5280
+ : "(select)" }), wb.registry.enums
5278
5281
  .get(typeId)
5279
5282
  ?.options.map((opt) => (jsxRuntime.jsx("option", { value: String(opt.value), children: opt.label }, opt.value)))] }), hasValue && !isLinked && (jsxRuntime.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: jsxRuntime.jsx(react$1.XCircleIcon, { size: 16 }) }))] })) : isLinked ? (jsxRuntime.jsx("div", { className: "flex items-center gap-1 flex-1", children: jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: renderLinkedInputDisplay(typeId, current) }) })) : (jsxRuntime.jsxs("div", { className: "flex items-center gap-1 flex-1", children: [jsxRuntime.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
5280
5283
  ? `Default: ${placeholder}`
@@ -5543,7 +5546,7 @@ function useKeyboardShortcutToast() {
5543
5546
  }
5544
5547
 
5545
5548
  const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, getDefaultNodeSize }, ref) => {
5546
- const { wb, registry, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, registryVersion, runner, engineKind, overrides, } = useWorkbenchContext();
5549
+ const { wb, inputsMap, inputDefaultsMap, outputsMap, outputTypesMap, valuesTick, nodeStatus, edgeStatus, validationByNode, validationByEdge, uiVersion, registryVersion, runner, engineKind, overrides, } = useWorkbenchContext();
5547
5550
  const nodeValidation = validationByNode;
5548
5551
  const edgeValidation = validationByEdge.errors;
5549
5552
  const [historyState, setHistoryState] = React.useState(wb.getHistory());
@@ -5621,7 +5624,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5621
5624
  // Build nodeTypes map using UI extension registry
5622
5625
  const custom = new Map(); // Include all types present in registry AND current graph to avoid timing issues
5623
5626
  const ids = new Set([
5624
- ...Array.from(registry.nodes.keys()),
5627
+ ...Array.from(wb.registry.nodes.keys()),
5625
5628
  ...wb.def.nodes.map((n) => n.typeId),
5626
5629
  ]);
5627
5630
  for (const typeId of ids) {
@@ -5640,7 +5643,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5640
5643
  return { nodeTypes: types, resolveNodeType: resolver };
5641
5644
  // Include uiVersion to recompute when custom renderers are registered
5642
5645
  // Include registryVersion to recompute when registry enums/types change
5643
- }, [wb, registry, uiVersion, ui]);
5646
+ }, [wb, wb.registry, registryVersion, uiVersion, ui]);
5644
5647
  const edgeTypes = React.useMemo(() => {
5645
5648
  // Use default edge renderer override if registered, otherwise use DefaultEdge
5646
5649
  const customEdgeRenderer = ui.getEdgeRenderer();
@@ -5666,7 +5669,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5666
5669
  inputsWithDefaults[n.nodeId] = merged;
5667
5670
  }
5668
5671
  }
5669
- const out = toReactFlow(wb.def, wb.getPositions(), wb.getSizes(), registry, {
5672
+ const out = toReactFlow(wb.def, wb.getPositions(), wb.getSizes(), wb.registry, {
5670
5673
  showValues,
5671
5674
  inputs: inputsWithDefaults,
5672
5675
  inputDefaults: inputDefaultsMap,
@@ -5933,7 +5936,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5933
5936
  });
5934
5937
  return () => off();
5935
5938
  }, [wb]);
5936
- const nodeIds = React.useMemo(() => Array.from(registry.nodes.keys()), [registry, registryVersion]);
5939
+ const nodeIds = React.useMemo(() => Array.from(wb.registry.nodes.keys()), [wb.registry, registryVersion]);
5937
5940
  const defaultContextMenuHandlers = React.useMemo(() => {
5938
5941
  // Get storage from override or use workbench's internal storage
5939
5942
  const storage = overrides?.getCopiedDataStorage
@@ -5981,7 +5984,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5981
5984
  get: () => wb.getCopiedData(),
5982
5985
  set: (data) => wb.setCopiedData(data),
5983
5986
  };
5984
- const baseHandlers = createNodeContextMenuHandlers(nodeAtMenu, wb, runner, registry, outputsMap, outputTypesMap, onCloseNodeMenu, overrides?.getDefaultNodeSize, (data) => {
5987
+ const baseHandlers = createNodeContextMenuHandlers(nodeAtMenu, wb, runner, wb.registry, outputsMap, outputTypesMap, onCloseNodeMenu, overrides?.getDefaultNodeSize, (data) => {
5985
5988
  storage.set(data);
5986
5989
  });
5987
5990
  if (overrides?.getNodeContextMenuHandlers) {
@@ -5992,7 +5995,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
5992
5995
  nodeAtMenu,
5993
5996
  wb,
5994
5997
  runner,
5995
- registry,
5998
+ wb.registry,
5999
+ registryVersion,
5996
6000
  outputsMap,
5997
6001
  outputTypesMap,
5998
6002
  onCloseNodeMenu,
@@ -6004,8 +6008,8 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
6004
6008
  const bakeableOutputs = React.useMemo(() => {
6005
6009
  if (!nodeAtMenu)
6006
6010
  return [];
6007
- return getBakeableOutputs(nodeAtMenu, wb, registry, outputTypesMap);
6008
- }, [nodeAtMenu, wb, registry, outputTypesMap]);
6011
+ return getBakeableOutputs(nodeAtMenu, wb, wb.registry, outputTypesMap);
6012
+ }, [nodeAtMenu, wb, wb.registry, registryVersion, outputTypesMap]);
6009
6013
  // Keyboard shortcuts configuration
6010
6014
  const enableKeyboardShortcuts = overrides?.enableKeyboardShortcuts !== false; // Default to true
6011
6015
  const keyboardShortcuts = overrides?.keyboardShortcuts || {
@@ -6201,9 +6205,9 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
6201
6205
  if (savedViewport) {
6202
6206
  inst.setViewport(lod.clone(savedViewport));
6203
6207
  }
6204
- }, 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 ? (jsxRuntime.jsx(BackgroundRenderer, {})) : (jsxRuntime.jsx(react.Background, { id: "workbench-canvas-background", variant: react.BackgroundVariant.Dots, gap: 12, size: 1 })), MinimapRenderer ? jsxRuntime.jsx(MinimapRenderer, {}) : jsxRuntime.jsx(react.MiniMap, {}), ControlsRenderer ? jsxRuntime.jsx(ControlsRenderer, {}) : jsxRuntime.jsx(react.Controls, {}), DefaultContextMenuRenderer ? (jsxRuntime.jsx(DefaultContextMenuRenderer, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: registry, nodeIds: nodeIds, ...(enableKeyboardShortcuts !== false
6208
+ }, 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 ? (jsxRuntime.jsx(BackgroundRenderer, {})) : (jsxRuntime.jsx(react.Background, { id: "workbench-canvas-background", variant: react.BackgroundVariant.Dots, gap: 12, size: 1 })), MinimapRenderer ? jsxRuntime.jsx(MinimapRenderer, {}) : jsxRuntime.jsx(react.MiniMap, {}), ControlsRenderer ? jsxRuntime.jsx(ControlsRenderer, {}) : jsxRuntime.jsx(react.Controls, {}), DefaultContextMenuRenderer ? (jsxRuntime.jsx(DefaultContextMenuRenderer, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, ...(enableKeyboardShortcuts !== false
6205
6209
  ? { enableKeyboardShortcuts, keyboardShortcuts }
6206
- : {}) })) : (jsxRuntime.jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })), !!nodeAtMenu &&
6210
+ : {}) })) : (jsxRuntime.jsx(DefaultContextMenu, { open: menuOpen, clientPos: menuPos, handlers: defaultContextMenuHandlers, registry: wb.registry, nodeIds: nodeIds, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })), !!nodeAtMenu &&
6207
6211
  nodeContextMenuHandlers &&
6208
6212
  (NodeContextMenuRenderer ? (jsxRuntime.jsx(NodeContextMenuRenderer, { open: nodeMenuOpen, clientPos: nodeMenuPos, nodeId: nodeAtMenu, handlers: nodeContextMenuHandlers, canRunPull: canRunPull, bakeableOutputs: bakeableOutputs, ...(enableKeyboardShortcuts !== false
6209
6213
  ? { enableKeyboardShortcuts, keyboardShortcuts }
@@ -6212,14 +6216,14 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
6212
6216
  (SelectionContextMenuRenderer ? (jsxRuntime.jsx(SelectionContextMenuRenderer, { open: selectionMenuOpen, clientPos: selectionMenuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })) : (jsxRuntime.jsx(SelectionContextMenu, { open: selectionMenuOpen, clientPos: selectionMenuPos, handlers: selectionContextMenuHandlers, enableKeyboardShortcuts: enableKeyboardShortcuts, keyboardShortcuts: keyboardShortcuts })))] }) }), toast && (jsxRuntime.jsx(KeyboardShortcutToast, { message: toast.message, onClose: hideToast }, toast.id))] }));
6213
6217
  });
6214
6218
 
6215
- function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
6216
- const { wb, runner, registry, selectedNodeId, runAutoLayout } = useWorkbenchContext();
6219
+ function WorkbenchStudioCanvas({ autoScroll, onAutoScrollChange, example, onExampleChange, engine, onEngineChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, overrides, onInit, onChange, }) {
6220
+ const { wb, runner, selectedNodeId, runAutoLayout } = useWorkbenchContext();
6217
6221
  const [transportStatus, setTransportStatus] = React.useState({
6218
6222
  state: "local",
6219
6223
  });
6220
6224
  const selectedNode = wb.def.nodes.find((n) => n.nodeId === selectedNodeId);
6221
6225
  const effectiveHandles = selectedNode
6222
- ? computeEffectiveHandles(selectedNode, registry)
6226
+ ? computeEffectiveHandles(selectedNode, wb.registry)
6223
6227
  : { inputs: {}, outputs: {}, inputDefaults: {} };
6224
6228
  const [exampleState, setExampleState] = React.useState(example ?? "");
6225
6229
  const isGraphRunning = runner.isRunning();
@@ -6366,7 +6370,6 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6366
6370
  // - For remote backend, registry is automatically managed by RemoteGraphRunner
6367
6371
  if (backendKind === "local") {
6368
6372
  if (r) {
6369
- setRegistry(r);
6370
6373
  wb.setRegistry(r);
6371
6374
  }
6372
6375
  }
@@ -6382,15 +6385,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6382
6385
  runAutoLayout();
6383
6386
  setExampleState(key);
6384
6387
  onExampleChange?.(key);
6385
- }, [
6386
- runner,
6387
- wb,
6388
- onExampleChange,
6389
- runAutoLayout,
6390
- examples,
6391
- setRegistry,
6392
- backendKind,
6393
- ]);
6388
+ }, [runner, wb, onExampleChange, runAutoLayout, examples, backendKind]);
6394
6389
  const download$1 = React.useCallback(async () => {
6395
6390
  try {
6396
6391
  await download(wb, runner);
@@ -6561,11 +6556,11 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6561
6556
  return overrides.setInput(baseSetInput, {
6562
6557
  runner,
6563
6558
  selectedNodeId,
6564
- registry,
6559
+ registry: wb.registry,
6565
6560
  });
6566
6561
  }
6567
6562
  return baseSetInput;
6568
- }, [overrides, baseSetInput, runner, selectedNodeId, registry]);
6563
+ }, [overrides, baseSetInput, runner, selectedNodeId, wb.registry]);
6569
6564
  const baseToString = React.useCallback((typeId, value) => {
6570
6565
  if (value === undefined || value === null)
6571
6566
  return "";
@@ -6573,7 +6568,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6573
6568
  if (sparkGraph.isTypedOutput(value)) {
6574
6569
  return baseToString(sparkGraph.getTypedOutputTypeId(value), sparkGraph.getTypedOutputValue(value));
6575
6570
  }
6576
- const pre = preformatValueForDisplay(typeId, value, registry);
6571
+ const pre = preformatValueForDisplay(typeId, value, wb.registry);
6577
6572
  if (pre !== undefined)
6578
6573
  return pre;
6579
6574
  if (typeof value === "object" &&
@@ -6589,7 +6584,7 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6589
6584
  }
6590
6585
  if (typeId && typeId.startsWith("enum:")) {
6591
6586
  const n = Number(value);
6592
- const label = registry.enums.get(typeId)?.valueToLabel.get(n);
6587
+ const label = wb.registry.enums.get(typeId)?.valueToLabel.get(n);
6593
6588
  return label ?? String(n);
6594
6589
  }
6595
6590
  const round4 = (n) => Math.round(Number(n) * 10000) / 10000;
@@ -6619,22 +6614,22 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
6619
6614
  return String(rounded);
6620
6615
  }
6621
6616
  return String(value);
6622
- }, [registry]);
6617
+ }, [wb.registry]);
6623
6618
  const baseToElement = React.useCallback((typeId, value) => {
6624
6619
  return (jsxRuntime.jsx("span", { className: "ml-1 opacity-60", children: baseToString(typeId, value) }));
6625
6620
  }, [baseToString]);
6626
6621
  const toString = React.useMemo(() => {
6627
6622
  if (overrides?.toString)
6628
- return overrides.toString(baseToString, { registry });
6623
+ return overrides.toString(baseToString, { registry: wb.registry });
6629
6624
  return baseToString;
6630
- }, [overrides, baseToString, registry]);
6625
+ }, [overrides, baseToString, wb.registry]);
6631
6626
  // Optional: toElement (not currently consumed by core UI)
6632
6627
  // Consumers can access it by passing through their own node renderers.
6633
6628
  const toElement = React.useMemo(() => {
6634
6629
  if (overrides?.toElement)
6635
- return overrides.toElement(baseToElement, { registry });
6630
+ return overrides.toElement(baseToElement, { registry: wb.registry });
6636
6631
  return baseToElement;
6637
- }, [overrides, baseToElement, registry]);
6632
+ }, [overrides, baseToElement, wb.registry]);
6638
6633
  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: [isGraphRunning ? (jsxRuntime.jsxs("span", { className: "ml-2 text-sm text-green-700", children: ["Running: ", engineKind] })) : (jsxRuntime.jsx("span", { className: "ml-2 text-sm text-gray-500", children: "Stopped" })), jsxRuntime.jsxs("span", { className: "ml-2 flex items-center gap-1 text-xs", title: transportStatus.kind || undefined, children: [transportStatus.state === "local" && (jsxRuntime.jsx(react$1.PlugsConnectedIcon, { size: 14, className: "text-gray-500" })), transportStatus.state === "connecting" && (jsxRuntime.jsx(react$1.ClockClockwiseIcon, { size: 14, className: "text-amber-600 animate-pulse" })), transportStatus.state === "connected" && (jsxRuntime.jsx(react$1.WifiHighIcon, { size: 14, className: "text-green-600" })), transportStatus.state === "disconnected" && (jsxRuntime.jsx(react$1.WifiSlashIcon, { size: 14, className: "text-red-600" })), transportStatus.state === "retrying" && (jsxRuntime.jsx(react$1.ClockClockwiseIcon, { size: 14, className: "text-amber-700 animate-pulse" }))] }), jsxRuntime.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: [jsxRuntime.jsx("option", { value: "", children: "Select Example\u2026" }), examples.map((ex) => (jsxRuntime.jsx("option", { value: ex.id, children: ex.label }, ex.id)))] }), jsxRuntime.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: [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" && !!onHttpBaseUrlChange && (jsxRuntime.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 && (jsxRuntime.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) })), jsxRuntime.jsxs("select", { className: "border border-gray-300 rounded px-2 py-1", value: engineKind ?? engine ?? "", onChange: async (e) => {
6639
6634
  const kind = e.target.value || undefined;
6640
6635
  const currentEngine = runner.getRunningEngine();
@@ -6736,7 +6731,7 @@ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, bac
6736
6731
  runner.dispose();
6737
6732
  onBackendKindChange(v);
6738
6733
  }, [isGraphRunning]);
6739
- return (jsxRuntime.jsx(WorkbenchProvider, { wb: wb, runner: runner, registry: registry, setRegistry: setRegistry, overrides: overrides, uiVersion: uiVersion, children: jsxRuntime.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 }) }));
6734
+ return (jsxRuntime.jsx(WorkbenchProvider, { wb: wb, runner: runner, overrides: overrides, uiVersion: uiVersion, children: jsxRuntime.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 }) }));
6740
6735
  }
6741
6736
 
6742
6737
  exports.AbstractWorkbench = AbstractWorkbench;