@genfeedai/workflow-ui 0.1.0 → 0.1.1

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.
Files changed (45) hide show
  1. package/dist/canvas.js +12 -13
  2. package/dist/canvas.mjs +6 -7
  3. package/dist/{chunk-FT64PCUP.mjs → chunk-3PMLER6D.mjs} +6 -15
  4. package/dist/{chunk-CSUBLSKZ.mjs → chunk-73V6SUEO.mjs} +27 -36
  5. package/dist/{chunk-HPQT36RR.js → chunk-DICI5FSP.js} +18 -27
  6. package/dist/{chunk-EC2ZIWOK.js → chunk-DUZLPHRC.js} +36 -45
  7. package/dist/{chunk-ADWNF7V3.js → chunk-EMGXUNBL.js} +3 -3
  8. package/dist/{chunk-VOGL2WCE.mjs → chunk-EYL6J4MW.mjs} +9 -18
  9. package/dist/{chunk-H6LZKSLY.js → chunk-H3JOHAS5.js} +113 -148
  10. package/dist/{chunk-E544XUBL.js → chunk-HWY6IBWT.js} +8 -11
  11. package/dist/{chunk-22PDGHNQ.mjs → chunk-I3GNO2SR.mjs} +2 -2
  12. package/dist/{chunk-UQQUWGHW.mjs → chunk-IASLG6IA.mjs} +1 -1
  13. package/dist/chunk-IHF35QZD.js +1095 -0
  14. package/dist/{chunk-SW7QNEZU.js → chunk-OZNYKFMX.js} +30 -30
  15. package/dist/{chunk-XV5Z5XYR.mjs → chunk-PFHFGSM5.mjs} +18 -53
  16. package/dist/{chunk-CETJJ73S.js → chunk-PVWLMJGZ.js} +28 -37
  17. package/dist/chunk-RIGVIEYB.mjs +1093 -0
  18. package/dist/{chunk-LAJ34AH2.mjs → chunk-XOC5ETTX.mjs} +4 -7
  19. package/dist/hooks.js +14 -15
  20. package/dist/hooks.mjs +4 -5
  21. package/dist/index.js +41 -42
  22. package/dist/index.mjs +8 -9
  23. package/dist/lib.js +0 -1
  24. package/dist/lib.mjs +0 -1
  25. package/dist/nodes.js +37 -38
  26. package/dist/nodes.mjs +4 -5
  27. package/dist/panels.js +6 -7
  28. package/dist/panels.mjs +3 -4
  29. package/dist/provider.js +0 -1
  30. package/dist/provider.mjs +0 -1
  31. package/dist/stores.js +7 -8
  32. package/dist/stores.mjs +2 -3
  33. package/dist/toolbar.js +9 -10
  34. package/dist/toolbar.mjs +3 -4
  35. package/dist/ui.js +0 -1
  36. package/dist/ui.mjs +0 -1
  37. package/dist/workflowStore-32ZH5REM.js +11 -0
  38. package/dist/workflowStore-ZCSVIZQF.mjs +2 -0
  39. package/package.json +3 -3
  40. package/dist/chunk-AC6TWLRT.mjs +0 -27
  41. package/dist/chunk-BJ3R5R32.mjs +0 -2163
  42. package/dist/chunk-NSDLGLAQ.js +0 -2166
  43. package/dist/chunk-Z7PWFZG5.js +0 -30
  44. package/dist/workflowStore-4EGKJLYK.mjs +0 -3
  45. package/dist/workflowStore-KM32FDL7.js +0 -12
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkNSDLGLAQ_js = require('./chunk-NSDLGLAQ.js');
4
- var chunkZ7PWFZG5_js = require('./chunk-Z7PWFZG5.js');
3
+ var chunkIHF35QZD_js = require('./chunk-IHF35QZD.js');
5
4
  var zustand = require('zustand');
5
+ var types = require('@genfeedai/types');
6
6
 
7
7
  var notificationId = 0;
8
8
  var useUIStore = zustand.create((set) => ({
@@ -86,9 +86,6 @@ var useUIStore = zustand.create((set) => ({
86
86
  }));
87
87
  }
88
88
  }));
89
-
90
- // src/stores/settingsStore.ts
91
- var import_types = chunkZ7PWFZG5_js.__toESM(chunkNSDLGLAQ_js.require_dist());
92
89
  var STORAGE_KEY = "genfeed-settings";
93
90
  var MAX_RECENT_MODELS = 8;
94
91
  var DEFAULT_SETTINGS = {
@@ -216,7 +213,7 @@ var useSettingsStore = zustand.create((set, get) => {
216
213
  },
217
214
  setEdgeStyle: (style) => {
218
215
  setAndPersist(() => ({ edgeStyle: style }));
219
- import('./workflowStore-KM32FDL7.js').then(({ useWorkflowStore: useWorkflowStore2 }) => {
216
+ import('./workflowStore-32ZH5REM.js').then(({ useWorkflowStore: useWorkflowStore2 }) => {
220
217
  useWorkflowStore2.getState().setEdgeStyle(style);
221
218
  });
222
219
  },
@@ -271,10 +268,10 @@ var useSettingsStore = zustand.create((set, get) => {
271
268
  const key = state.providers[provider].apiKey;
272
269
  if (!key) return {};
273
270
  const headerMap = {
274
- [import_types.ProviderTypeEnum.REPLICATE]: "X-Replicate-Key",
275
- [import_types.ProviderTypeEnum.FAL]: "X-Fal-Key",
276
- [import_types.ProviderTypeEnum.HUGGINGFACE]: "X-HF-Key",
277
- [import_types.ProviderTypeEnum.GENFEED_AI]: "X-Genfeed-Key"
271
+ [types.ProviderTypeEnum.REPLICATE]: "X-Replicate-Key",
272
+ [types.ProviderTypeEnum.FAL]: "X-Fal-Key",
273
+ [types.ProviderTypeEnum.HUGGINGFACE]: "X-HF-Key",
274
+ [types.ProviderTypeEnum.GENFEED_AI]: "X-Genfeed-Key"
278
275
  };
279
276
  return { [headerMap[provider]]: key };
280
277
  },
@@ -287,34 +284,28 @@ var useSettingsStore = zustand.create((set, get) => {
287
284
  };
288
285
  });
289
286
  var PROVIDER_INFO = {
290
- [import_types.ProviderTypeEnum.REPLICATE]: {
287
+ [types.ProviderTypeEnum.REPLICATE]: {
291
288
  name: "Replicate",
292
289
  description: "Access thousands of open-source AI models",
293
290
  docsUrl: "https://replicate.com/docs"
294
291
  },
295
- [import_types.ProviderTypeEnum.FAL]: {
292
+ [types.ProviderTypeEnum.FAL]: {
296
293
  name: "fal.ai",
297
294
  description: "Fast inference for image and video generation",
298
295
  docsUrl: "https://fal.ai/docs"
299
296
  },
300
- [import_types.ProviderTypeEnum.HUGGINGFACE]: {
297
+ [types.ProviderTypeEnum.HUGGINGFACE]: {
301
298
  name: "Hugging Face",
302
299
  description: "The AI community platform with 500k+ models",
303
300
  docsUrl: "https://huggingface.co/docs/api-inference"
304
301
  },
305
- [import_types.ProviderTypeEnum.GENFEED_AI]: {
302
+ [types.ProviderTypeEnum.GENFEED_AI]: {
306
303
  name: "Genfeed AI",
307
304
  description: "Built-in models powered by Genfeed",
308
305
  docsUrl: "https://genfeed.ai/docs"
309
306
  }
310
307
  };
311
308
 
312
- // src/stores/execution/slices/executionSlice.ts
313
- var import_types3 = chunkZ7PWFZG5_js.__toESM(chunkNSDLGLAQ_js.require_dist());
314
-
315
- // src/stores/execution/helpers/sseSubscription.ts
316
- var import_types2 = chunkZ7PWFZG5_js.__toESM(chunkNSDLGLAQ_js.require_dist());
317
-
318
309
  // src/stores/execution/helpers/outputHelpers.ts
319
310
  function extractOutputValue(output) {
320
311
  if (!output) return null;
@@ -396,11 +387,11 @@ function getOutputUpdate(nodeId, output, workflowStore) {
396
387
  // src/stores/execution/helpers/sseSubscription.ts
397
388
  var API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://local.genfeed.ai:3001/api";
398
389
  var statusMap = {
399
- pending: import_types2.NodeStatusEnum.IDLE,
400
- processing: import_types2.NodeStatusEnum.PROCESSING,
401
- complete: import_types2.NodeStatusEnum.COMPLETE,
402
- succeeded: import_types2.NodeStatusEnum.COMPLETE,
403
- error: import_types2.NodeStatusEnum.ERROR
390
+ pending: types.NodeStatusEnum.IDLE,
391
+ processing: types.NodeStatusEnum.PROCESSING,
392
+ complete: types.NodeStatusEnum.COMPLETE,
393
+ succeeded: types.NodeStatusEnum.COMPLETE,
394
+ error: types.NodeStatusEnum.ERROR
404
395
  };
405
396
  function applyJobUpdates(jobs, workflowStore, debugMode, set, filterNodeId) {
406
397
  if (!jobs || jobs.length === 0) return;
@@ -466,9 +457,9 @@ async function reconcileNodeStatuses(executionId) {
466
457
  const response = await fetch(`${API_BASE_URL}/executions/${executionId}`);
467
458
  if (!response.ok) return;
468
459
  const execution = await response.json();
469
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
460
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
470
461
  for (const nodeResult of execution.nodeResults || []) {
471
- const nodeStatus = statusMap[nodeResult.status] ?? import_types2.NodeStatusEnum.IDLE;
462
+ const nodeStatus = statusMap[nodeResult.status] ?? types.NodeStatusEnum.IDLE;
472
463
  const isSuccess = nodeResult.status === "complete" || nodeResult.status === "succeeded";
473
464
  workflowStore.updateNodeData(nodeResult.nodeId, {
474
465
  status: nodeStatus,
@@ -490,10 +481,10 @@ function createExecutionSubscription(executionId, set) {
490
481
  void (async () => {
491
482
  try {
492
483
  const data = JSON.parse(event.data);
493
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
484
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
494
485
  const nodeResults = data.nodeResults || [];
495
486
  for (const nodeResult of nodeResults) {
496
- const nodeStatus = statusMap[nodeResult.status] ?? import_types2.NodeStatusEnum.IDLE;
487
+ const nodeStatus = statusMap[nodeResult.status] ?? types.NodeStatusEnum.IDLE;
497
488
  const isSuccess = nodeResult.status === "complete" || nodeResult.status === "succeeded";
498
489
  workflowStore.updateNodeData(nodeResult.nodeId, {
499
490
  status: nodeStatus,
@@ -541,10 +532,10 @@ function createNodeExecutionSubscription(executionId, nodeId, set, _get) {
541
532
  void (async () => {
542
533
  try {
543
534
  const data = JSON.parse(event.data);
544
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
535
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
545
536
  const nodeResults = data.nodeResults || [];
546
537
  for (const nodeResult of nodeResults) {
547
- const nodeStatus = statusMap[nodeResult.status] ?? import_types2.NodeStatusEnum.IDLE;
538
+ const nodeStatus = statusMap[nodeResult.status] ?? types.NodeStatusEnum.IDLE;
548
539
  const isSuccess = nodeResult.status === "complete" || nodeResult.status === "succeeded";
549
540
  workflowStore.updateNodeData(nodeResult.nodeId, {
550
541
  status: nodeStatus,
@@ -610,7 +601,7 @@ var createExecutionSlice = (set, get) => ({
610
601
  executeWorkflow: async () => {
611
602
  const { isRunning, resetExecution } = get();
612
603
  if (isRunning) return;
613
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
604
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
614
605
  const debugMode = useSettingsStore.getState().debugMode;
615
606
  const validation = workflowStore.validateWorkflow();
616
607
  if (!validation.isValid) {
@@ -650,7 +641,7 @@ var createExecutionSlice = (set, get) => ({
650
641
  set({ isRunning: true });
651
642
  for (const node of workflowStore.nodes) {
652
643
  workflowStore.updateNodeData(node.id, {
653
- status: import_types3.NodeStatusEnum.IDLE,
644
+ status: types.NodeStatusEnum.IDLE,
654
645
  error: void 0,
655
646
  progress: void 0
656
647
  });
@@ -680,14 +671,14 @@ var createExecutionSlice = (set, get) => ({
680
671
  }
681
672
  },
682
673
  executeNode: async (nodeId) => {
683
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
674
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
684
675
  const debugMode = useSettingsStore.getState().debugMode;
685
676
  if (workflowStore.isDirty || !workflowStore.workflowId) {
686
677
  try {
687
678
  await workflowStore.saveWorkflow();
688
679
  } catch {
689
680
  workflowStore.updateNodeData(nodeId, {
690
- status: import_types3.NodeStatusEnum.ERROR,
681
+ status: types.NodeStatusEnum.ERROR,
691
682
  error: "Failed to save workflow"
692
683
  });
693
684
  return;
@@ -696,7 +687,7 @@ var createExecutionSlice = (set, get) => ({
696
687
  const workflowId = workflowStore.workflowId;
697
688
  if (!workflowId) {
698
689
  workflowStore.updateNodeData(nodeId, {
699
- status: import_types3.NodeStatusEnum.ERROR,
690
+ status: types.NodeStatusEnum.ERROR,
700
691
  error: "Workflow must be saved first"
701
692
  });
702
693
  return;
@@ -723,7 +714,7 @@ var createExecutionSlice = (set, get) => ({
723
714
  });
724
715
  } catch (error) {
725
716
  workflowStore.updateNodeData(nodeId, {
726
- status: import_types3.NodeStatusEnum.ERROR,
717
+ status: types.NodeStatusEnum.ERROR,
727
718
  error: error instanceof Error ? error.message : "Node execution failed"
728
719
  });
729
720
  }
@@ -731,7 +722,7 @@ var createExecutionSlice = (set, get) => ({
731
722
  executeSelectedNodes: async () => {
732
723
  const { isRunning, resetExecution } = get();
733
724
  if (isRunning) return;
734
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
725
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
735
726
  const debugMode = useSettingsStore.getState().debugMode;
736
727
  const { selectedNodeIds } = workflowStore;
737
728
  if (selectedNodeIds.length === 0) {
@@ -777,7 +768,7 @@ var createExecutionSlice = (set, get) => ({
777
768
  }
778
769
  for (const nodeId of selectedNodeIds) {
779
770
  workflowStore.updateNodeData(nodeId, {
780
- status: import_types3.NodeStatusEnum.IDLE,
771
+ status: types.NodeStatusEnum.IDLE,
781
772
  error: void 0,
782
773
  progress: void 0
783
774
  });
@@ -810,7 +801,7 @@ var createExecutionSlice = (set, get) => ({
810
801
  resumeFromFailed: async () => {
811
802
  const { isRunning, executionId, lastFailedNodeId } = get();
812
803
  if (isRunning || !executionId || !lastFailedNodeId) return;
813
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
804
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
814
805
  const debugMode = useSettingsStore.getState().debugMode;
815
806
  const workflowId = workflowStore.workflowId;
816
807
  if (!workflowId) {
@@ -828,7 +819,7 @@ var createExecutionSlice = (set, get) => ({
828
819
  useUIStore.getState().setShowDebugPanel(true);
829
820
  }
830
821
  workflowStore.updateNodeData(lastFailedNodeId, {
831
- status: import_types3.NodeStatusEnum.IDLE,
822
+ status: types.NodeStatusEnum.IDLE,
832
823
  error: void 0,
833
824
  progress: void 0
834
825
  });
@@ -884,8 +875,8 @@ var createExecutionSlice = (set, get) => ({
884
875
  return { activeNodeExecutions: newMap };
885
876
  });
886
877
  }
887
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
888
- workflowStore.updateNodeData(nodeId, { status: import_types3.NodeStatusEnum.IDLE, error: void 0 });
878
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
879
+ workflowStore.updateNodeData(nodeId, { status: types.NodeStatusEnum.IDLE, error: void 0 });
889
880
  },
890
881
  isNodeExecuting: (nodeId) => {
891
882
  const { activeNodeExecutions } = get();
@@ -914,10 +905,10 @@ var createExecutionSlice = (set, get) => ({
914
905
  debugPayloads: [],
915
906
  activeNodeExecutions: /* @__PURE__ */ new Map()
916
907
  });
917
- const workflowStore = chunkNSDLGLAQ_js.useWorkflowStore.getState();
908
+ const workflowStore = chunkIHF35QZD_js.useWorkflowStore.getState();
918
909
  for (const node of workflowStore.nodes) {
919
910
  workflowStore.updateNodeData(node.id, {
920
- status: import_types3.NodeStatusEnum.IDLE,
911
+ status: types.NodeStatusEnum.IDLE,
921
912
  error: void 0,
922
913
  progress: void 0
923
914
  });
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkNSDLGLAQ_js = require('./chunk-NSDLGLAQ.js');
3
+ var chunkIHF35QZD_js = require('./chunk-IHF35QZD.js');
4
4
  var react = require('react');
5
5
 
6
6
  function useCanvasKeyboardShortcuts({
@@ -92,11 +92,11 @@ function useCanvasKeyboardShortcuts({
92
92
  }
93
93
  if (e.key === "z" && isMod && !e.shiftKey) {
94
94
  e.preventDefault();
95
- chunkNSDLGLAQ_js.useWorkflowStore.temporal.getState().undo();
95
+ chunkIHF35QZD_js.useWorkflowStore.temporal.getState().undo();
96
96
  }
97
97
  if (e.key === "z" && isMod && e.shiftKey) {
98
98
  e.preventDefault();
99
- chunkNSDLGLAQ_js.useWorkflowStore.temporal.getState().redo();
99
+ chunkIHF35QZD_js.useWorkflowStore.temporal.getState().redo();
100
100
  }
101
101
  };
102
102
  window.addEventListener("keydown", handleKeyDown);
@@ -1,22 +1,19 @@
1
- import { nodeTypes } from './chunk-XV5Z5XYR.mjs';
1
+ import { nodeTypes } from './chunk-PFHFGSM5.mjs';
2
2
  import { getMediaFromNode } from './chunk-E323WAZG.mjs';
3
- import { useCanvasKeyboardShortcuts } from './chunk-UQQUWGHW.mjs';
3
+ import { useCanvasKeyboardShortcuts } from './chunk-IASLG6IA.mjs';
4
4
  import { Button } from './chunk-7SKSRSS7.mjs';
5
5
  import { usePromptEditorStore } from './chunk-CV4M7CNU.mjs';
6
- import { useUIStore, useSettingsStore, useExecutionStore } from './chunk-CSUBLSKZ.mjs';
7
- import { require_dist, useWorkflowStore } from './chunk-BJ3R5R32.mjs';
8
- import { __toESM } from './chunk-AC6TWLRT.mjs';
6
+ import { useUIStore, useSettingsStore, useExecutionStore } from './chunk-73V6SUEO.mjs';
7
+ import { useWorkflowStore } from './chunk-RIGVIEYB.mjs';
9
8
  import { useNodes, ViewportPortal, useViewport, useStore, getBezierPath, BaseEdge, useReactFlow, ReactFlow, SelectionMode, ConnectionMode, Background, BackgroundVariant, Controls, MiniMap } from '@xyflow/react';
10
9
  import { Pause, Palette, Lock, Unlock, Trash2, Search, X, Keyboard, PanelLeft, Download, ChevronLeft, ChevronRight, ZoomOut, ZoomIn } from 'lucide-react';
11
10
  import { memo, useMemo, useState, useCallback, useEffect, useRef } from 'react';
12
11
  import '@xyflow/react/dist/style.css';
12
+ import { NODE_DEFINITIONS } from '@genfeedai/types';
13
13
  import { clsx } from 'clsx';
14
14
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
15
15
  import Image from 'next/image';
16
16
 
17
- // src/canvas/WorkflowCanvas.tsx
18
- var import_types3 = __toESM(require_dist());
19
-
20
17
  // src/types/groups.ts
21
18
  var GROUP_COLORS = {
22
19
  purple: {
@@ -556,9 +553,6 @@ function HelperLinesComponent({ draggingNodeId }) {
556
553
  );
557
554
  }
558
555
  var HelperLines = memo(HelperLinesComponent);
559
-
560
- // src/canvas/NodeSearch.tsx
561
- var import_types = __toESM(require_dist());
562
556
  function NodeSearch() {
563
557
  const { activeModal, closeModal } = useUIStore();
564
558
  const { nodes, setSelectedNodeIds } = useWorkflowStore();
@@ -581,7 +575,7 @@ function NodeSearch() {
581
575
  const label = (node.data.label || "").toLowerCase();
582
576
  const type = (node.type || "").toLowerCase();
583
577
  const comment = (node.data.comment || "").toLowerCase();
584
- const nodeDefLabel = import_types.NODE_DEFINITIONS[node.type]?.label?.toLowerCase() || "";
578
+ const nodeDefLabel = NODE_DEFINITIONS[node.type]?.label?.toLowerCase() || "";
585
579
  return label.includes(query) || type.includes(query) || comment.includes(query) || nodeDefLabel.includes(query);
586
580
  });
587
581
  }, [nodes, search]);
@@ -681,7 +675,7 @@ function NodeSearch() {
681
675
  )
682
676
  ] }),
683
677
  /* @__PURE__ */ jsx("div", { ref: listRef, className: "max-h-[300px] overflow-y-auto space-y-1", children: filteredNodes.length === 0 ? /* @__PURE__ */ jsx("div", { className: "text-center text-muted-foreground py-8", children: search ? `No nodes found for "${search}"` : "No nodes in workflow" }) : filteredNodes.map((node, index) => {
684
- const nodeDef = import_types.NODE_DEFINITIONS[node.type];
678
+ const nodeDef = NODE_DEFINITIONS[node.type];
685
679
  const comment = node.data.comment;
686
680
  return /* @__PURE__ */ jsxs(
687
681
  "button",
@@ -862,9 +856,6 @@ function ShortcutHelpModal() {
862
856
  }
863
857
  );
864
858
  }
865
-
866
- // src/nodes/NodeDetailModal.tsx
867
- var import_types2 = __toESM(require_dist());
868
859
  var PROMPT_NODE_TYPES = ["prompt"];
869
860
  function NodeDetailModal() {
870
861
  const { activeModal, nodeDetailNodeId, nodeDetailStartIndex, closeNodeDetailModal } = useUIStore();
@@ -893,7 +884,7 @@ function NodeDetailModal() {
893
884
  }, [node]);
894
885
  const nodeDef = useMemo(() => {
895
886
  if (!node) return null;
896
- return import_types2.NODE_DEFINITIONS[node.type];
887
+ return NODE_DEFINITIONS[node.type];
897
888
  }, [node]);
898
889
  const imageUrls = mediaInfo.urls ?? [];
899
890
  const hasMultipleImages = imageUrls.length > 1;
@@ -1123,7 +1114,7 @@ function supportsImageInput(schema) {
1123
1114
  function getEdgeDataType(edge, nodeMap) {
1124
1115
  const sourceNode = nodeMap.get(edge.source);
1125
1116
  if (!sourceNode) return null;
1126
- const nodeDef = import_types3.NODE_DEFINITIONS[sourceNode.type];
1117
+ const nodeDef = NODE_DEFINITIONS[sourceNode.type];
1127
1118
  if (!nodeDef) return null;
1128
1119
  const sourceHandle = nodeDef.outputs.find((h) => h.id === edge.sourceHandle);
1129
1120
  return sourceHandle?.type ?? null;