@foresthubai/workflow-builder 0.3.0

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 (496) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +16 -0
  3. package/README.md +93 -0
  4. package/dist/BuilderLayout.d.ts +34 -0
  5. package/dist/BuilderLayout.d.ts.map +1 -0
  6. package/dist/BuilderLayout.js +172 -0
  7. package/dist/BuilderLayout.js.map +1 -0
  8. package/dist/Canvas.d.ts +23 -0
  9. package/dist/Canvas.d.ts.map +1 -0
  10. package/dist/Canvas.js +141 -0
  11. package/dist/Canvas.js.map +1 -0
  12. package/dist/CanvasEditor.d.ts +46 -0
  13. package/dist/CanvasEditor.d.ts.map +1 -0
  14. package/dist/CanvasEditor.js +57 -0
  15. package/dist/CanvasEditor.js.map +1 -0
  16. package/dist/CanvasTabsToolbar.d.ts +11 -0
  17. package/dist/CanvasTabsToolbar.d.ts.map +1 -0
  18. package/dist/CanvasTabsToolbar.js +101 -0
  19. package/dist/CanvasTabsToolbar.js.map +1 -0
  20. package/dist/RightConfigPanel.d.ts +27 -0
  21. package/dist/RightConfigPanel.d.ts.map +1 -0
  22. package/dist/RightConfigPanel.js +102 -0
  23. package/dist/RightConfigPanel.js.map +1 -0
  24. package/dist/WorkflowBuilder.d.ts +62 -0
  25. package/dist/WorkflowBuilder.d.ts.map +1 -0
  26. package/dist/WorkflowBuilder.js +275 -0
  27. package/dist/WorkflowBuilder.js.map +1 -0
  28. package/dist/cn.d.ts +3 -0
  29. package/dist/cn.d.ts.map +1 -0
  30. package/dist/cn.js +6 -0
  31. package/dist/cn.js.map +1 -0
  32. package/dist/components/ui/add-button.d.ts +16 -0
  33. package/dist/components/ui/add-button.d.ts.map +1 -0
  34. package/dist/components/ui/add-button.js +21 -0
  35. package/dist/components/ui/add-button.js.map +1 -0
  36. package/dist/components/ui/alert-dialog.d.ts +21 -0
  37. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  38. package/dist/components/ui/alert-dialog.js +30 -0
  39. package/dist/components/ui/alert-dialog.js.map +1 -0
  40. package/dist/components/ui/alert.d.ts +9 -0
  41. package/dist/components/ui/alert.d.ts.map +1 -0
  42. package/dist/components/ui/alert.js +23 -0
  43. package/dist/components/ui/alert.js.map +1 -0
  44. package/dist/components/ui/badge.d.ts +10 -0
  45. package/dist/components/ui/badge.d.ts.map +1 -0
  46. package/dist/components/ui/badge.js +21 -0
  47. package/dist/components/ui/badge.js.map +1 -0
  48. package/dist/components/ui/button.d.ts +13 -0
  49. package/dist/components/ui/button.d.ts.map +1 -0
  50. package/dist/components/ui/button.js +40 -0
  51. package/dist/components/ui/button.js.map +1 -0
  52. package/dist/components/ui/card.d.ts +9 -0
  53. package/dist/components/ui/card.d.ts.map +1 -0
  54. package/dist/components/ui/card.js +17 -0
  55. package/dist/components/ui/card.js.map +1 -0
  56. package/dist/components/ui/checkbox.d.ts +5 -0
  57. package/dist/components/ui/checkbox.d.ts.map +1 -0
  58. package/dist/components/ui/checkbox.js +9 -0
  59. package/dist/components/ui/checkbox.js.map +1 -0
  60. package/dist/components/ui/collapsible.d.ts +6 -0
  61. package/dist/components/ui/collapsible.d.ts.map +1 -0
  62. package/dist/components/ui/collapsible.js +6 -0
  63. package/dist/components/ui/collapsible.js.map +1 -0
  64. package/dist/components/ui/command.d.ts +82 -0
  65. package/dist/components/ui/command.d.ts.map +1 -0
  66. package/dist/components/ui/command.js +29 -0
  67. package/dist/components/ui/command.js.map +1 -0
  68. package/dist/components/ui/delete-button.d.ts +11 -0
  69. package/dist/components/ui/delete-button.d.ts.map +1 -0
  70. package/dist/components/ui/delete-button.js +14 -0
  71. package/dist/components/ui/delete-button.js.map +1 -0
  72. package/dist/components/ui/dialog.d.ts +22 -0
  73. package/dist/components/ui/dialog.d.ts.map +1 -0
  74. package/dist/components/ui/dialog.js +27 -0
  75. package/dist/components/ui/dialog.js.map +1 -0
  76. package/dist/components/ui/dropdown-menu.d.ts +28 -0
  77. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  78. package/dist/components/ui/dropdown-menu.js +36 -0
  79. package/dist/components/ui/dropdown-menu.js.map +1 -0
  80. package/dist/components/ui/input.d.ts +13 -0
  81. package/dist/components/ui/input.d.ts.map +1 -0
  82. package/dist/components/ui/input.js +34 -0
  83. package/dist/components/ui/input.js.map +1 -0
  84. package/dist/components/ui/label.d.ts +6 -0
  85. package/dist/components/ui/label.d.ts.map +1 -0
  86. package/dist/components/ui/label.js +10 -0
  87. package/dist/components/ui/label.js.map +1 -0
  88. package/dist/components/ui/readonly-banner.d.ts +7 -0
  89. package/dist/components/ui/readonly-banner.d.ts.map +1 -0
  90. package/dist/components/ui/readonly-banner.js +12 -0
  91. package/dist/components/ui/readonly-banner.js.map +1 -0
  92. package/dist/components/ui/resizable.d.ts +24 -0
  93. package/dist/components/ui/resizable.d.ts.map +1 -0
  94. package/dist/components/ui/resizable.js +9 -0
  95. package/dist/components/ui/resizable.js.map +1 -0
  96. package/dist/components/ui/scroll-area.d.ts +45 -0
  97. package/dist/components/ui/scroll-area.d.ts.map +1 -0
  98. package/dist/components/ui/scroll-area.js +27 -0
  99. package/dist/components/ui/scroll-area.js.map +1 -0
  100. package/dist/components/ui/select.d.ts +14 -0
  101. package/dist/components/ui/select.d.ts.map +1 -0
  102. package/dist/components/ui/select.js +30 -0
  103. package/dist/components/ui/select.js.map +1 -0
  104. package/dist/components/ui/separator.d.ts +5 -0
  105. package/dist/components/ui/separator.d.ts.map +1 -0
  106. package/dist/components/ui/separator.js +8 -0
  107. package/dist/components/ui/separator.js.map +1 -0
  108. package/dist/components/ui/switch.d.ts +5 -0
  109. package/dist/components/ui/switch.d.ts.map +1 -0
  110. package/dist/components/ui/switch.js +8 -0
  111. package/dist/components/ui/switch.js.map +1 -0
  112. package/dist/components/ui/textarea.d.ts +12 -0
  113. package/dist/components/ui/textarea.d.ts.map +1 -0
  114. package/dist/components/ui/textarea.js +34 -0
  115. package/dist/components/ui/textarea.js.map +1 -0
  116. package/dist/components/ui/toast.d.ts +16 -0
  117. package/dist/components/ui/toast.d.ts.map +1 -0
  118. package/dist/components/ui/toast.js +34 -0
  119. package/dist/components/ui/toast.js.map +1 -0
  120. package/dist/components/ui/toaster.d.ts +2 -0
  121. package/dist/components/ui/toaster.d.ts.map +1 -0
  122. package/dist/components/ui/toaster.js +10 -0
  123. package/dist/components/ui/toaster.js.map +1 -0
  124. package/dist/components/ui/toggle-group.d.ts +13 -0
  125. package/dist/components/ui/toggle-group.d.ts.map +1 -0
  126. package/dist/components/ui/toggle-group.js +21 -0
  127. package/dist/components/ui/toggle-group.js.map +1 -0
  128. package/dist/components/ui/toggle.d.ts +13 -0
  129. package/dist/components/ui/toggle.d.ts.map +1 -0
  130. package/dist/components/ui/toggle.js +26 -0
  131. package/dist/components/ui/toggle.js.map +1 -0
  132. package/dist/components/ui/tooltip.d.ts +8 -0
  133. package/dist/components/ui/tooltip.d.ts.map +1 -0
  134. package/dist/components/ui/tooltip.js +14 -0
  135. package/dist/components/ui/tooltip.js.map +1 -0
  136. package/dist/dialogs/NodePickerDialog.d.ts +10 -0
  137. package/dist/dialogs/NodePickerDialog.d.ts.map +1 -0
  138. package/dist/dialogs/NodePickerDialog.js +39 -0
  139. package/dist/dialogs/NodePickerDialog.js.map +1 -0
  140. package/dist/dialogs/ValidationDialog.d.ts +17 -0
  141. package/dist/dialogs/ValidationDialog.d.ts.map +1 -0
  142. package/dist/dialogs/ValidationDialog.js +29 -0
  143. package/dist/dialogs/ValidationDialog.js.map +1 -0
  144. package/dist/graph/BaseNode.d.ts +9 -0
  145. package/dist/graph/BaseNode.d.ts.map +1 -0
  146. package/dist/graph/BaseNode.js +318 -0
  147. package/dist/graph/BaseNode.js.map +1 -0
  148. package/dist/graph/CustomEdge.d.ts +14 -0
  149. package/dist/graph/CustomEdge.d.ts.map +1 -0
  150. package/dist/graph/CustomEdge.js +107 -0
  151. package/dist/graph/CustomEdge.js.map +1 -0
  152. package/dist/graph/CustomNode.d.ts +3 -0
  153. package/dist/graph/CustomNode.d.ts.map +1 -0
  154. package/dist/graph/CustomNode.js +15 -0
  155. package/dist/graph/CustomNode.js.map +1 -0
  156. package/dist/graph/FunctionCallNode.d.ts +3 -0
  157. package/dist/graph/FunctionCallNode.d.ts.map +1 -0
  158. package/dist/graph/FunctionCallNode.js +25 -0
  159. package/dist/graph/FunctionCallNode.js.map +1 -0
  160. package/dist/graph/PortHandle.d.ts +21 -0
  161. package/dist/graph/PortHandle.d.ts.map +1 -0
  162. package/dist/graph/PortHandle.js +113 -0
  163. package/dist/graph/PortHandle.js.map +1 -0
  164. package/dist/graph/reactFlowRegistry.d.ts +65 -0
  165. package/dist/graph/reactFlowRegistry.d.ts.map +1 -0
  166. package/dist/graph/reactFlowRegistry.js +24 -0
  167. package/dist/graph/reactFlowRegistry.js.map +1 -0
  168. package/dist/hooks/use-toast.d.ts +47 -0
  169. package/dist/hooks/use-toast.d.ts.map +1 -0
  170. package/dist/hooks/use-toast.js +95 -0
  171. package/dist/hooks/use-toast.js.map +1 -0
  172. package/dist/hooks/useAvailableVariables.d.ts +12 -0
  173. package/dist/hooks/useAvailableVariables.d.ts.map +1 -0
  174. package/dist/hooks/useAvailableVariables.js +16 -0
  175. package/dist/hooks/useAvailableVariables.js.map +1 -0
  176. package/dist/hooks/useCanvasHistory.d.ts +14 -0
  177. package/dist/hooks/useCanvasHistory.d.ts.map +1 -0
  178. package/dist/hooks/useCanvasHistory.js +20 -0
  179. package/dist/hooks/useCanvasHistory.js.map +1 -0
  180. package/dist/hooks/useCanvasTabs.d.ts +23 -0
  181. package/dist/hooks/useCanvasTabs.d.ts.map +1 -0
  182. package/dist/hooks/useCanvasTabs.js +136 -0
  183. package/dist/hooks/useCanvasTabs.js.map +1 -0
  184. package/dist/hooks/useFunctionDiagnosticsSync.d.ts +14 -0
  185. package/dist/hooks/useFunctionDiagnosticsSync.d.ts.map +1 -0
  186. package/dist/hooks/useFunctionDiagnosticsSync.js +38 -0
  187. package/dist/hooks/useFunctionDiagnosticsSync.js.map +1 -0
  188. package/dist/hooks/useFunctionRegistry.d.ts +15 -0
  189. package/dist/hooks/useFunctionRegistry.d.ts.map +1 -0
  190. package/dist/hooks/useFunctionRegistry.js +22 -0
  191. package/dist/hooks/useFunctionRegistry.js.map +1 -0
  192. package/dist/hooks/useFunctions.d.ts +15 -0
  193. package/dist/hooks/useFunctions.d.ts.map +1 -0
  194. package/dist/hooks/useFunctions.js +34 -0
  195. package/dist/hooks/useFunctions.js.map +1 -0
  196. package/dist/hooks/useGraph.d.ts +40 -0
  197. package/dist/hooks/useGraph.d.ts.map +1 -0
  198. package/dist/hooks/useGraph.js +102 -0
  199. package/dist/hooks/useGraph.js.map +1 -0
  200. package/dist/hooks/useNodeDefinitions.d.ts +17 -0
  201. package/dist/hooks/useNodeDefinitions.d.ts.map +1 -0
  202. package/dist/hooks/useNodeDefinitions.js +65 -0
  203. package/dist/hooks/useNodeDefinitions.js.map +1 -0
  204. package/dist/hooks/useParamErrors.d.ts +12 -0
  205. package/dist/hooks/useParamErrors.d.ts.map +1 -0
  206. package/dist/hooks/useParamErrors.js +28 -0
  207. package/dist/hooks/useParamErrors.js.map +1 -0
  208. package/dist/hooks/useResolvedTheme.d.ts +10 -0
  209. package/dist/hooks/useResolvedTheme.d.ts.map +1 -0
  210. package/dist/hooks/useResolvedTheme.js +29 -0
  211. package/dist/hooks/useResolvedTheme.js.map +1 -0
  212. package/dist/hooks/useResourceDiagnosticsSync.d.ts +40 -0
  213. package/dist/hooks/useResourceDiagnosticsSync.d.ts.map +1 -0
  214. package/dist/hooks/useResourceDiagnosticsSync.js +39 -0
  215. package/dist/hooks/useResourceDiagnosticsSync.js.map +1 -0
  216. package/dist/hooks/useSuppressThemeTransition.d.ts +32 -0
  217. package/dist/hooks/useSuppressThemeTransition.d.ts.map +1 -0
  218. package/dist/hooks/useSuppressThemeTransition.js +75 -0
  219. package/dist/hooks/useSuppressThemeTransition.js.map +1 -0
  220. package/dist/hooks/useWorkflowSerialization.d.ts +24 -0
  221. package/dist/hooks/useWorkflowSerialization.d.ts.map +1 -0
  222. package/dist/hooks/useWorkflowSerialization.js +113 -0
  223. package/dist/hooks/useWorkflowSerialization.js.map +1 -0
  224. package/dist/i18n/index.d.ts +4 -0
  225. package/dist/i18n/index.d.ts.map +1 -0
  226. package/dist/i18n/index.js +46 -0
  227. package/dist/i18n/index.js.map +1 -0
  228. package/dist/i18n/locales/de.json +501 -0
  229. package/dist/i18n/locales/en.json +557 -0
  230. package/dist/index.d.ts +9 -0
  231. package/dist/index.d.ts.map +1 -0
  232. package/dist/index.js +12 -0
  233. package/dist/index.js.map +1 -0
  234. package/dist/inputs/ExpressionInput.d.ts +12 -0
  235. package/dist/inputs/ExpressionInput.d.ts.map +1 -0
  236. package/dist/inputs/ExpressionInput.js +203 -0
  237. package/dist/inputs/ExpressionInput.js.map +1 -0
  238. package/dist/inputs/ParameterEditor.d.ts +13 -0
  239. package/dist/inputs/ParameterEditor.d.ts.map +1 -0
  240. package/dist/inputs/ParameterEditor.js +204 -0
  241. package/dist/inputs/ParameterEditor.js.map +1 -0
  242. package/dist/inputs/PortSection.d.ts +31 -0
  243. package/dist/inputs/PortSection.d.ts.map +1 -0
  244. package/dist/inputs/PortSection.js +26 -0
  245. package/dist/inputs/PortSection.js.map +1 -0
  246. package/dist/panels/BuilderSidebar.d.ts +24 -0
  247. package/dist/panels/BuilderSidebar.d.ts.map +1 -0
  248. package/dist/panels/BuilderSidebar.js +202 -0
  249. package/dist/panels/BuilderSidebar.js.map +1 -0
  250. package/dist/panels/ChannelConfigPanel.d.ts +8 -0
  251. package/dist/panels/ChannelConfigPanel.d.ts.map +1 -0
  252. package/dist/panels/ChannelConfigPanel.js +26 -0
  253. package/dist/panels/ChannelConfigPanel.js.map +1 -0
  254. package/dist/panels/ChannelsPanel.d.ts +2 -0
  255. package/dist/panels/ChannelsPanel.d.ts.map +1 -0
  256. package/dist/panels/ChannelsPanel.js +16 -0
  257. package/dist/panels/ChannelsPanel.js.map +1 -0
  258. package/dist/panels/DebugConsolePanel.d.ts +2 -0
  259. package/dist/panels/DebugConsolePanel.d.ts.map +1 -0
  260. package/dist/panels/DebugConsolePanel.js +32 -0
  261. package/dist/panels/DebugConsolePanel.js.map +1 -0
  262. package/dist/panels/DebugContextPanel.d.ts +2 -0
  263. package/dist/panels/DebugContextPanel.d.ts.map +1 -0
  264. package/dist/panels/DebugContextPanel.js +32 -0
  265. package/dist/panels/DebugContextPanel.js.map +1 -0
  266. package/dist/panels/DebugExternalIOPanel.d.ts +9 -0
  267. package/dist/panels/DebugExternalIOPanel.d.ts.map +1 -0
  268. package/dist/panels/DebugExternalIOPanel.js +66 -0
  269. package/dist/panels/DebugExternalIOPanel.js.map +1 -0
  270. package/dist/panels/DiagnosticsPanel.d.ts +8 -0
  271. package/dist/panels/DiagnosticsPanel.d.ts.map +1 -0
  272. package/dist/panels/DiagnosticsPanel.js +86 -0
  273. package/dist/panels/DiagnosticsPanel.js.map +1 -0
  274. package/dist/panels/EdgeConfigPanel.d.ts +14 -0
  275. package/dist/panels/EdgeConfigPanel.d.ts.map +1 -0
  276. package/dist/panels/EdgeConfigPanel.js +34 -0
  277. package/dist/panels/EdgeConfigPanel.js.map +1 -0
  278. package/dist/panels/FunctionConfigPanel.d.ts +16 -0
  279. package/dist/panels/FunctionConfigPanel.d.ts.map +1 -0
  280. package/dist/panels/FunctionConfigPanel.js +62 -0
  281. package/dist/panels/FunctionConfigPanel.js.map +1 -0
  282. package/dist/panels/FunctionListPanel.d.ts +14 -0
  283. package/dist/panels/FunctionListPanel.d.ts.map +1 -0
  284. package/dist/panels/FunctionListPanel.js +25 -0
  285. package/dist/panels/FunctionListPanel.js.map +1 -0
  286. package/dist/panels/MemoryConfigPanel.d.ts +8 -0
  287. package/dist/panels/MemoryConfigPanel.d.ts.map +1 -0
  288. package/dist/panels/MemoryConfigPanel.js +22 -0
  289. package/dist/panels/MemoryConfigPanel.js.map +1 -0
  290. package/dist/panels/MemoryPanel.d.ts +2 -0
  291. package/dist/panels/MemoryPanel.d.ts.map +1 -0
  292. package/dist/panels/MemoryPanel.js +25 -0
  293. package/dist/panels/MemoryPanel.js.map +1 -0
  294. package/dist/panels/ModelConfigPanel.d.ts +8 -0
  295. package/dist/panels/ModelConfigPanel.d.ts.map +1 -0
  296. package/dist/panels/ModelConfigPanel.js +14 -0
  297. package/dist/panels/ModelConfigPanel.js.map +1 -0
  298. package/dist/panels/ModelsPanel.d.ts +8 -0
  299. package/dist/panels/ModelsPanel.d.ts.map +1 -0
  300. package/dist/panels/ModelsPanel.js +24 -0
  301. package/dist/panels/ModelsPanel.js.map +1 -0
  302. package/dist/panels/NodeConfigPanel.d.ts +16 -0
  303. package/dist/panels/NodeConfigPanel.d.ts.map +1 -0
  304. package/dist/panels/NodeConfigPanel.js +248 -0
  305. package/dist/panels/NodeConfigPanel.js.map +1 -0
  306. package/dist/panels/NodeLibrary.d.ts +16 -0
  307. package/dist/panels/NodeLibrary.d.ts.map +1 -0
  308. package/dist/panels/NodeLibrary.js +125 -0
  309. package/dist/panels/NodeLibrary.js.map +1 -0
  310. package/dist/panels/ResourceConfigPanel.d.ts +37 -0
  311. package/dist/panels/ResourceConfigPanel.d.ts.map +1 -0
  312. package/dist/panels/ResourceConfigPanel.js +35 -0
  313. package/dist/panels/ResourceConfigPanel.js.map +1 -0
  314. package/dist/panels/ResourceListPanel.d.ts +35 -0
  315. package/dist/panels/ResourceListPanel.d.ts.map +1 -0
  316. package/dist/panels/ResourceListPanel.js +35 -0
  317. package/dist/panels/ResourceListPanel.js.map +1 -0
  318. package/dist/panels/VariableConfigPanel.d.ts +9 -0
  319. package/dist/panels/VariableConfigPanel.d.ts.map +1 -0
  320. package/dist/panels/VariableConfigPanel.js +50 -0
  321. package/dist/panels/VariableConfigPanel.js.map +1 -0
  322. package/dist/panels/VariablesPanel.d.ts +7 -0
  323. package/dist/panels/VariablesPanel.d.ts.map +1 -0
  324. package/dist/panels/VariablesPanel.js +56 -0
  325. package/dist/panels/VariablesPanel.js.map +1 -0
  326. package/dist/stores/canvasStore.d.ts +41 -0
  327. package/dist/stores/canvasStore.d.ts.map +1 -0
  328. package/dist/stores/canvasStore.js +187 -0
  329. package/dist/stores/canvasStore.js.map +1 -0
  330. package/dist/stores/debugStore.d.ts +42 -0
  331. package/dist/stores/debugStore.d.ts.map +1 -0
  332. package/dist/stores/debugStore.js +22 -0
  333. package/dist/stores/debugStore.js.map +1 -0
  334. package/dist/stores/diagnosticsStore.d.ts +41 -0
  335. package/dist/stores/diagnosticsStore.d.ts.map +1 -0
  336. package/dist/stores/diagnosticsStore.js +67 -0
  337. package/dist/stores/diagnosticsStore.js.map +1 -0
  338. package/dist/stores/editorStore.d.ts +76 -0
  339. package/dist/stores/editorStore.d.ts.map +1 -0
  340. package/dist/stores/editorStore.js +116 -0
  341. package/dist/stores/editorStore.js.map +1 -0
  342. package/dist/utils/categoryConstants.d.ts +4 -0
  343. package/dist/utils/categoryConstants.d.ts.map +1 -0
  344. package/dist/utils/categoryConstants.js +24 -0
  345. package/dist/utils/categoryConstants.js.map +1 -0
  346. package/dist/utils/channelOperations.d.ts +21 -0
  347. package/dist/utils/channelOperations.d.ts.map +1 -0
  348. package/dist/utils/channelOperations.js +84 -0
  349. package/dist/utils/channelOperations.js.map +1 -0
  350. package/dist/utils/connectionRules.d.ts +15 -0
  351. package/dist/utils/connectionRules.d.ts.map +1 -0
  352. package/dist/utils/connectionRules.js +113 -0
  353. package/dist/utils/connectionRules.js.map +1 -0
  354. package/dist/utils/functionOperations.d.ts +27 -0
  355. package/dist/utils/functionOperations.d.ts.map +1 -0
  356. package/dist/utils/functionOperations.js +140 -0
  357. package/dist/utils/functionOperations.js.map +1 -0
  358. package/dist/utils/graphOperations.d.ts +54 -0
  359. package/dist/utils/graphOperations.d.ts.map +1 -0
  360. package/dist/utils/graphOperations.js +461 -0
  361. package/dist/utils/graphOperations.js.map +1 -0
  362. package/dist/utils/history.d.ts +76 -0
  363. package/dist/utils/history.d.ts.map +1 -0
  364. package/dist/utils/history.js +93 -0
  365. package/dist/utils/history.js.map +1 -0
  366. package/dist/utils/memoryOperations.d.ts +14 -0
  367. package/dist/utils/memoryOperations.d.ts.map +1 -0
  368. package/dist/utils/memoryOperations.js +55 -0
  369. package/dist/utils/memoryOperations.js.map +1 -0
  370. package/dist/utils/migrateFunctionNodes.d.ts +9 -0
  371. package/dist/utils/migrateFunctionNodes.d.ts.map +1 -0
  372. package/dist/utils/migrateFunctionNodes.js +89 -0
  373. package/dist/utils/migrateFunctionNodes.js.map +1 -0
  374. package/dist/utils/modelOperations.d.ts +13 -0
  375. package/dist/utils/modelOperations.d.ts.map +1 -0
  376. package/dist/utils/modelOperations.js +53 -0
  377. package/dist/utils/modelOperations.js.map +1 -0
  378. package/dist/utils/paramDisplay.d.ts +12 -0
  379. package/dist/utils/paramDisplay.d.ts.map +1 -0
  380. package/dist/utils/paramDisplay.js +56 -0
  381. package/dist/utils/paramDisplay.js.map +1 -0
  382. package/dist/utils/resourceHelpers.d.ts +17 -0
  383. package/dist/utils/resourceHelpers.d.ts.map +1 -0
  384. package/dist/utils/resourceHelpers.js +32 -0
  385. package/dist/utils/resourceHelpers.js.map +1 -0
  386. package/dist/utils/translation.d.ts +20 -0
  387. package/dist/utils/translation.d.ts.map +1 -0
  388. package/dist/utils/translation.js +23 -0
  389. package/dist/utils/translation.js.map +1 -0
  390. package/dist/utils/variableOperations.d.ts +15 -0
  391. package/dist/utils/variableOperations.d.ts.map +1 -0
  392. package/dist/utils/variableOperations.js +71 -0
  393. package/dist/utils/variableOperations.js.map +1 -0
  394. package/package.json +79 -0
  395. package/src/BuilderLayout.tsx +345 -0
  396. package/src/Canvas.tsx +261 -0
  397. package/src/CanvasEditor.tsx +142 -0
  398. package/src/CanvasTabsToolbar.tsx +176 -0
  399. package/src/RightConfigPanel.tsx +266 -0
  400. package/src/WorkflowBuilder.tsx +412 -0
  401. package/src/cn.ts +6 -0
  402. package/src/components/ui/add-button.tsx +39 -0
  403. package/src/components/ui/alert-dialog.tsx +141 -0
  404. package/src/components/ui/alert.tsx +59 -0
  405. package/src/components/ui/badge.tsx +36 -0
  406. package/src/components/ui/button.tsx +85 -0
  407. package/src/components/ui/card.tsx +79 -0
  408. package/src/components/ui/checkbox.tsx +28 -0
  409. package/src/components/ui/collapsible.tsx +9 -0
  410. package/src/components/ui/command.tsx +153 -0
  411. package/src/components/ui/delete-button.tsx +23 -0
  412. package/src/components/ui/dialog.tsx +125 -0
  413. package/src/components/ui/dropdown-menu.tsx +198 -0
  414. package/src/components/ui/input.tsx +55 -0
  415. package/src/components/ui/label.tsx +24 -0
  416. package/src/components/ui/readonly-banner.tsx +15 -0
  417. package/src/components/ui/resizable.tsx +43 -0
  418. package/src/components/ui/scroll-area.tsx +102 -0
  419. package/src/components/ui/select.tsx +160 -0
  420. package/src/components/ui/separator.tsx +29 -0
  421. package/src/components/ui/switch.tsx +27 -0
  422. package/src/components/ui/textarea.tsx +51 -0
  423. package/src/components/ui/toast.tsx +127 -0
  424. package/src/components/ui/toaster.tsx +33 -0
  425. package/src/components/ui/toggle-group.tsx +59 -0
  426. package/src/components/ui/toggle.tsx +43 -0
  427. package/src/components/ui/tooltip.tsx +32 -0
  428. package/src/dialogs/NodePickerDialog.tsx +84 -0
  429. package/src/dialogs/ValidationDialog.tsx +184 -0
  430. package/src/graph/BaseNode.tsx +557 -0
  431. package/src/graph/CustomEdge.tsx +185 -0
  432. package/src/graph/CustomNode.tsx +16 -0
  433. package/src/graph/FunctionCallNode.tsx +30 -0
  434. package/src/graph/PortHandle.tsx +189 -0
  435. package/src/graph/reactFlowRegistry.ts +26 -0
  436. package/src/hooks/use-toast.ts +125 -0
  437. package/src/hooks/useAvailableVariables.ts +20 -0
  438. package/src/hooks/useCanvasHistory.ts +22 -0
  439. package/src/hooks/useCanvasTabs.ts +168 -0
  440. package/src/hooks/useFunctionDiagnosticsSync.ts +40 -0
  441. package/src/hooks/useFunctionRegistry.ts +26 -0
  442. package/src/hooks/useFunctions.ts +44 -0
  443. package/src/hooks/useGraph.ts +161 -0
  444. package/src/hooks/useNodeDefinitions.ts +82 -0
  445. package/src/hooks/useParamErrors.ts +26 -0
  446. package/src/hooks/useResolvedTheme.ts +30 -0
  447. package/src/hooks/useResourceDiagnosticsSync.ts +58 -0
  448. package/src/hooks/useSuppressThemeTransition.ts +79 -0
  449. package/src/hooks/useWorkflowSerialization.ts +127 -0
  450. package/src/i18n/index.ts +53 -0
  451. package/src/i18n/locales/de.json +501 -0
  452. package/src/i18n/locales/en.json +557 -0
  453. package/src/index.ts +27 -0
  454. package/src/inputs/ExpressionInput.tsx +297 -0
  455. package/src/inputs/ParameterEditor.tsx +515 -0
  456. package/src/inputs/PortSection.tsx +144 -0
  457. package/src/panels/BuilderSidebar.tsx +301 -0
  458. package/src/panels/ChannelConfigPanel.tsx +49 -0
  459. package/src/panels/ChannelsPanel.tsx +28 -0
  460. package/src/panels/DebugConsolePanel.tsx +73 -0
  461. package/src/panels/DebugContextPanel.tsx +77 -0
  462. package/src/panels/DebugExternalIOPanel.tsx +180 -0
  463. package/src/panels/DiagnosticsPanel.tsx +170 -0
  464. package/src/panels/EdgeConfigPanel.tsx +104 -0
  465. package/src/panels/FunctionConfigPanel.tsx +179 -0
  466. package/src/panels/FunctionListPanel.tsx +45 -0
  467. package/src/panels/MemoryConfigPanel.tsx +55 -0
  468. package/src/panels/MemoryPanel.tsx +40 -0
  469. package/src/panels/ModelConfigPanel.tsx +41 -0
  470. package/src/panels/ModelsPanel.tsx +36 -0
  471. package/src/panels/NodeConfigPanel.tsx +630 -0
  472. package/src/panels/NodeLibrary.tsx +288 -0
  473. package/src/panels/ResourceConfigPanel.tsx +132 -0
  474. package/src/panels/ResourceListPanel.tsx +113 -0
  475. package/src/panels/VariableConfigPanel.tsx +161 -0
  476. package/src/panels/VariablesPanel.tsx +145 -0
  477. package/src/stores/canvasStore.test.ts +44 -0
  478. package/src/stores/canvasStore.ts +245 -0
  479. package/src/stores/debugStore.ts +74 -0
  480. package/src/stores/diagnosticsStore.ts +130 -0
  481. package/src/stores/editorStore.ts +202 -0
  482. package/src/styles/index.css +526 -0
  483. package/src/utils/categoryConstants.ts +26 -0
  484. package/src/utils/channelOperations.ts +86 -0
  485. package/src/utils/connectionRules.ts +137 -0
  486. package/src/utils/functionOperations.ts +179 -0
  487. package/src/utils/graphOperations.ts +550 -0
  488. package/src/utils/history.ts +207 -0
  489. package/src/utils/memoryOperations.ts +57 -0
  490. package/src/utils/migrateFunctionNodes.ts +107 -0
  491. package/src/utils/modelOperations.ts +55 -0
  492. package/src/utils/paramDisplay.ts +71 -0
  493. package/src/utils/resourceHelpers.ts +32 -0
  494. package/src/utils/translation.ts +28 -0
  495. package/src/utils/variableOperations.ts +75 -0
  496. package/tailwind-preset.ts +166 -0
@@ -0,0 +1,550 @@
1
+ import {
2
+ NodeBase,
3
+ NodeCategory,
4
+ NodeDefinition,
5
+ NodeData,
6
+ NodeOutput,
7
+ NodeRegistry,
8
+ NodeType,
9
+ OutputBinding,
10
+ FunctionCallNode,
11
+ FunctionNodeDefinition,
12
+ getArguments,
13
+ getNodeOutput,
14
+ } from "@foresthubai/workflow-core/node";
15
+ import type { Expression } from "@foresthubai/workflow-core";
16
+ import type { FunctionInfo } from "@foresthubai/workflow-core/function";
17
+ import type { OutputDeclaration } from "@foresthubai/workflow-core/parameter";
18
+ import { addEdge, Connection, Edge, Node } from "@xyflow/react";
19
+ import type { EdgeData, EdgeType } from "@foresthubai/workflow-core/edge";
20
+ import { CanvasStore } from "../stores/canvasStore";
21
+ import { computeVariablesFromNodes } from "@foresthubai/workflow-core/workflow";
22
+ import { nodeOutputVarKey, paramKey } from "@foresthubai/workflow-core/variable";
23
+ import { isExpression } from "@foresthubai/workflow-core/expression";
24
+ import { isValidConnection } from "./connectionRules";
25
+ import { generateId } from "@foresthubai/workflow-core/id";
26
+ import { uniqueName } from "./resourceHelpers";
27
+
28
+ // ============================================================================
29
+ // Output Name Deduplication
30
+ // ============================================================================
31
+
32
+ /** Collect all output variable names currently in the store. */
33
+ function collectVariableNames(store: CanvasStore): Set<string> {
34
+ const vars = store.getState().variables;
35
+ return new Set(Object.values(vars).map((v) => v.name));
36
+ }
37
+
38
+ /**
39
+ * Walk a node instance and rename any emit bindings/declarations whose name collides
40
+ * with `existingNames`. Mutates in place. Handles all three locations:
41
+ * - Static outputs, incl. FunctionCall returns (direct field on arguments — OutputBinding)
42
+ * - List output entries (each entry IS an OutputDeclaration — mutate its `name` field directly
43
+ * when mode === "emit". Assign-mode entries have no name to rename, so they're skipped.)
44
+ * `existingNames` is updated with each rename so subsequent calls see the new names.
45
+ */
46
+ function deduplicateEmitNames(node: NodeData, existingNames: Set<string>): void {
47
+ const args = node.arguments as Record<string, unknown>;
48
+
49
+ const renameBindingAt = (key: string): void => {
50
+ const binding = args[key] as OutputBinding | undefined;
51
+ // Only active emit bindings produce a variable that could collide.
52
+ if (!binding || !binding.active || binding.mode !== "emit" || !existingNames.has(binding.name)) return;
53
+ const deduped = uniqueName(binding.name, existingNames);
54
+ existingNames.add(deduped);
55
+ args[key] = { active: true, mode: "emit", name: deduped };
56
+ };
57
+
58
+ if (node.type === "FunctionCall") {
59
+ for (const ret of node.functionInfo.returns) {
60
+ renameBindingAt(paramKey(ret));
61
+ }
62
+ return;
63
+ }
64
+
65
+ const def = NodeRegistry.getByType(node.type);
66
+ if (!def?.outputs) return;
67
+
68
+ for (const out of def.outputs) {
69
+ if (out.type === "static") {
70
+ renameBindingAt(out.id);
71
+ } else {
72
+ const entries = (args[out.id] as OutputDeclaration[] | undefined) ?? [];
73
+ for (const entry of entries) {
74
+ if (entry.mode !== "emit") continue;
75
+ if (!existingNames.has(entry.name)) continue;
76
+ const deduped = uniqueName(entry.name, existingNames);
77
+ existingNames.add(deduped);
78
+ entry.name = deduped;
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ // ============================================================================
85
+ // Pure Store Operations
86
+ // ============================================================================
87
+
88
+ /** Check if a node definition can be added to the store (respects isUnremovable and isSingleton). */
89
+ export function canAddNode(store: CanvasStore, nodeDef: NodeDefinition): boolean {
90
+ if (nodeDef.isUnremovable) return false;
91
+ if (nodeDef.isSingleton) {
92
+ const { nodes } = store.getState();
93
+ if (nodes.some((n) => n.data.type === nodeDef.type)) return false;
94
+ }
95
+ return true;
96
+ }
97
+
98
+ /** Add a node to the store given a node definition and optional position. Returns the new node ID, or null if the node cannot be added. */
99
+ export function addNodeToStore(store: CanvasStore, nodeDef: NodeDefinition, position?: { x: number; y: number }): string | null {
100
+ if (!canAddNode(store, nodeDef)) return null;
101
+
102
+ const nodeId = generateId();
103
+
104
+ // Initialize parameters with default values. Clone so object/array defaults
105
+ // (Expression, weekdays `[]`, memory-refs `[]`) aren't shared by reference
106
+ // across instances or with the definition itself — a shared mutable default
107
+ // would alias on edit.
108
+ const args: Record<string, unknown> = {};
109
+ nodeDef.parameters.forEach((param) => {
110
+ if (param.default !== undefined) {
111
+ args[param.id] = structuredClone(param.default);
112
+ }
113
+ });
114
+
115
+ // Seed outputs directly into args:
116
+ // - Static outputs: `args[out.id] = { active: true, mode: "emit", name: out.id }` (OutputBinding)
117
+ // - List outputs: `args[out.id] = []` (empty OutputDeclaration[] — user adds entries)
118
+ for (const out of nodeDef.outputs ?? []) {
119
+ if (out.type === "static") {
120
+ args[out.id] = { active: true, mode: "emit", name: out.id };
121
+ } else {
122
+ args[out.id] = [];
123
+ }
124
+ }
125
+
126
+ const nodeData: NodeBase = {
127
+ id: nodeId,
128
+ type: nodeDef.type,
129
+ arguments: args,
130
+ };
131
+ if (nodeDef.type === "FunctionCall") {
132
+ const functionDef = nodeDef as FunctionNodeDefinition;
133
+ const functionNode = nodeData as FunctionCallNode;
134
+ functionNode.functionInfo = functionDef.functionInfo;
135
+ // Seed input bindings keyed by arg uid — empty expressions with the declared dataType.
136
+ // Output bindings were already seeded above by the generic outputs[] loop since
137
+ // buildFunctionNodeDef now emits real StaticOutput entries.
138
+ for (const arg of functionDef.functionInfo.arguments) {
139
+ args[paramKey(arg)] = { expression: "", references: [], dataType: arg.dataType };
140
+ }
141
+ // Generic seeding uses the output id as the default emit name, but for function
142
+ // returns we want the return's variable name.
143
+ for (const ret of functionDef.functionInfo.returns) {
144
+ args[paramKey(ret)] = { active: true, mode: "emit" as const, name: ret.name };
145
+ }
146
+ }
147
+
148
+ // Deduplicate emit binding names against existing variables on the canvas
149
+ const existingNames = collectVariableNames(store);
150
+ deduplicateEmitNames(nodeData as NodeData, existingNames);
151
+
152
+ // Nudge position if another node is already nearby (avoids stacking on click-to-add)
153
+ const currentNodes = store.getState().nodes;
154
+ let pos = position || { x: 250, y: 100 };
155
+ const SNAP_DISTANCE = 50;
156
+ while (currentNodes.some((n) => Math.abs(n.position.x - pos.x) < SNAP_DISTANCE && Math.abs(n.position.y - pos.y) < SNAP_DISTANCE)) {
157
+ pos = { x: pos.x + 40, y: pos.y + 40 };
158
+ }
159
+
160
+ const newNode: Node<NodeData> = {
161
+ id: nodeData.id,
162
+ type: getReactFlowType(nodeDef.type),
163
+ position: pos,
164
+ data: nodeData as NodeData,
165
+ };
166
+
167
+ const { setNodes, setVariables } = store.getState();
168
+ setNodes((nds) => [...nds, newNode]);
169
+
170
+ // Add new node's output variables to store (computed via getNodeOutput)
171
+ setVariables((vars) => ({ ...vars, ...computeVariablesFromNodes([newNode.data]) }));
172
+
173
+ return nodeId;
174
+ }
175
+
176
+ /**
177
+ * Update a node's data in the store. Returns true if the node was found and updated.
178
+ *
179
+ * FunctionCallNode is no longer a special case — its arguments are flat, so the same
180
+ * shallow-merge path handles input edits, output binding edits, and migrations uniformly.
181
+ * Migration callers simply pass the full replacement arguments record alongside
182
+ * `functionInfo`; normal edits pass the single changed key.
183
+ */
184
+ export function updateNodeInStore(
185
+ store: CanvasStore,
186
+ nodeId: string,
187
+ updates: {
188
+ arguments?: Record<string, unknown>;
189
+ label?: string;
190
+ functionInfo?: FunctionInfo;
191
+ },
192
+ ): boolean {
193
+ const { setNodes, setVariables } = store.getState();
194
+
195
+ // Track output changes to update variables store
196
+ let oldOutputs: Record<string, NodeOutput> = {};
197
+ let newOutputs: Record<string, NodeOutput> = {};
198
+ let outputsChanged = false;
199
+ let found = false;
200
+
201
+ setNodes((nds) => {
202
+ const targetNodeIndex = nds.findIndex((node) => node.id === nodeId);
203
+ if (targetNodeIndex === -1) return nds;
204
+
205
+ const targetNode = nds[targetNodeIndex];
206
+ if (!targetNode) return nds;
207
+ found = true;
208
+ const currentData = targetNode.data as NodeData;
209
+ oldOutputs = getNodeOutput(currentData);
210
+
211
+ // When functionInfo changes (FunctionCall signature update), arguments are a
212
+ // full replacement so stale keys for removed args/returns get dropped;
213
+ // otherwise shallow-merge.
214
+ let updatedNodeData: NodeData;
215
+
216
+ if (updates.arguments) {
217
+ const mergedArgs = updates.functionInfo
218
+ ? updates.arguments
219
+ : { ...(currentData.arguments as Record<string, unknown>), ...updates.arguments };
220
+ updatedNodeData = {
221
+ ...(currentData as Record<string, unknown>),
222
+ ...updates,
223
+ arguments: mergedArgs,
224
+ } as NodeData;
225
+ } else {
226
+ updatedNodeData = { ...(currentData as Record<string, unknown>), ...updates } as NodeData;
227
+ }
228
+
229
+ newOutputs = getNodeOutput(updatedNodeData);
230
+
231
+ // Build the updated nodes array
232
+ const updatedNodes = nds.map((node, index) => {
233
+ if (index === targetNodeIndex) {
234
+ return { ...node, data: updatedNodeData };
235
+ }
236
+ return node;
237
+ }) as Node<NodeData>[];
238
+
239
+ // Check if any output variable changed (keys added/removed or values changed)
240
+ const oldKeys = Object.keys(oldOutputs);
241
+ const newKeys = Object.keys(newOutputs);
242
+ outputsChanged =
243
+ oldKeys.length !== newKeys.length ||
244
+ newKeys.some((key) => {
245
+ const oldVar = oldOutputs[key];
246
+ const newVar = newOutputs[key];
247
+ return !oldVar || !newVar || oldVar.name !== newVar.name || oldVar.dataType !== newVar.dataType;
248
+ });
249
+
250
+ return updatedNodes;
251
+ });
252
+
253
+ // Update variables store if outputs changed
254
+ if (outputsChanged) {
255
+ setVariables((vars) => {
256
+ const updated = { ...vars };
257
+ // Remove old outputs that no longer exist in new outputs
258
+ for (const outputId of Object.keys(oldOutputs)) {
259
+ if (!(outputId in newOutputs)) {
260
+ delete updated[nodeOutputVarKey(nodeId, outputId)];
261
+ }
262
+ }
263
+ // Add/update new outputs (only if actually changed)
264
+ for (const [outputId, variable] of Object.entries(newOutputs)) {
265
+ const key = nodeOutputVarKey(nodeId, outputId);
266
+ const oldVar = vars[key];
267
+ if (!oldVar || oldVar.name !== variable.name || oldVar.dataType !== variable.dataType) {
268
+ updated[key] = { kind: "node", nodeId, outputId, name: variable.name, dataType: variable.dataType };
269
+ }
270
+ }
271
+ return updated;
272
+ });
273
+ }
274
+
275
+ return found;
276
+ }
277
+
278
+ /**
279
+ * Delete a node from the store, removing connected edges and variables.
280
+ * Takes optional getNodeDefinition callback for isUnremovable check.
281
+ * Returns true if the node was deleted.
282
+ */
283
+ export function deleteNodeFromStore(
284
+ store: CanvasStore,
285
+ nodeId: string,
286
+ getNodeDefinition?: (node: NodeData) => NodeDefinition | undefined,
287
+ ): boolean {
288
+ const { nodes, edges, setNodes, setEdges, setVariables } = store.getState();
289
+
290
+ // Check if node can be deleted
291
+ const nodeToDelete = nodes.find((node) => node.id === nodeId);
292
+ if (!nodeToDelete) return false;
293
+
294
+ if (getNodeDefinition) {
295
+ const nodeDef = getNodeDefinition(nodeToDelete.data);
296
+ if (nodeDef?.isUnremovable ?? false) return false;
297
+ }
298
+
299
+ setNodes((nds) => nds.filter((node) => node.id !== nodeId));
300
+ setEdges((eds) => eds.filter((edge) => edge.source !== nodeId && edge.target !== nodeId));
301
+
302
+ // Remove deleted node's emitted variables from store
303
+ const outputKeys = Object.keys(getNodeOutput(nodeToDelete.data));
304
+ if (outputKeys.length > 0) {
305
+ setVariables((vars) => {
306
+ const updated = { ...vars };
307
+ for (const outputId of outputKeys) {
308
+ delete updated[nodeOutputVarKey(nodeId, outputId)];
309
+ }
310
+ return updated;
311
+ });
312
+ }
313
+
314
+ return true;
315
+ }
316
+
317
+ /**
318
+ * Determine the specific edge type based on base port type and connected nodes.
319
+ * Agent nodes get specialized control-edge types (agentTask, agentChoice, agentDelegate).
320
+ * Tool edges have no agent-specific variant — every tool edge points at an agent.
321
+ */
322
+ function resolveEdgeType(basePortType: EdgeType, sourceNode: Node<NodeData>, targetNode: Node<NodeData>): EdgeType {
323
+ const sourceIsAgent = sourceNode.data.type === "Agent";
324
+ const targetIsAgent = targetNode.data.type === "Agent";
325
+
326
+ if (basePortType === "control") {
327
+ if (sourceIsAgent && targetIsAgent) return "agentDelegate";
328
+ if (targetIsAgent) return "agentTask";
329
+ if (sourceIsAgent) return "agentChoice";
330
+ return "control";
331
+ }
332
+ return basePortType;
333
+ }
334
+
335
+ /** Add an edge if the connection is valid. Returns true if the edge was added. */
336
+ export function connectNodesInStore(store: CanvasStore, connection: Connection): EdgeType | false {
337
+ const { nodes, edges, setEdges } = store.getState();
338
+
339
+ const portType = isValidConnection(connection.source, connection.target, connection.sourceHandle, connection.targetHandle, nodes, edges);
340
+ if (!portType) return false;
341
+
342
+ const sourceNode = nodes.find((n) => n.id === connection.source);
343
+ const targetNode = nodes.find((n) => n.id === connection.target);
344
+ if (!sourceNode || !targetNode) return false;
345
+
346
+ const edgeType = resolveEdgeType(portType, sourceNode, targetNode);
347
+ setEdges((eds) => addEdge({ ...connection, type: edgeType }, eds) as typeof eds);
348
+ return edgeType;
349
+ }
350
+
351
+ /** Update an edge's data in the store. Returns true if the edge was found and updated. */
352
+ export function updateEdgeInStore(store: CanvasStore, edgeId: string, updates: Record<string, unknown>): boolean {
353
+ const { edges, setEdges } = store.getState();
354
+ const edge = edges.find((e) => e.id === edgeId);
355
+ if (!edge) return false;
356
+
357
+ setEdges((eds) => eds.map((e) => (e.id === edgeId ? { ...e, data: { ...e.data, ...updates } as EdgeData } : e)));
358
+ return true;
359
+ }
360
+
361
+ /** Delete edges by ID from the store. */
362
+ export function deleteEdgesFromStore(store: CanvasStore, edgeIds: string[]): void {
363
+ const { setEdges } = store.getState();
364
+ const idSet = new Set(edgeIds);
365
+ setEdges((eds) => eds.filter((e) => !idSet.has(e.id)));
366
+ }
367
+
368
+ // ============================================================================
369
+ // Clipboard
370
+ // ============================================================================
371
+
372
+ export interface Clipboard {
373
+ nodes: Node<NodeData>[];
374
+ edges: Edge<EdgeData>[];
375
+ }
376
+
377
+ export interface PasteResult {
378
+ pasted: boolean;
379
+ /** Labels of nodes that were skipped because they cannot be added (singleton already present or unremovable). */
380
+ skippedLabels: string[];
381
+ }
382
+
383
+ /** Paste clipboard contents into the store with new IDs and optional position offset. */
384
+ export function pasteToStore(
385
+ store: CanvasStore,
386
+ clipboard: Clipboard,
387
+ offset: { x: number; y: number } = { x: 50, y: 50 },
388
+ getNodeDefinition?: (node: NodeData) => NodeDefinition | undefined,
389
+ ): PasteResult {
390
+ const empty: PasteResult = { pasted: false, skippedLabels: [] };
391
+ if (clipboard.nodes.length === 0) return empty;
392
+
393
+ const { setNodes, setEdges, setVariables } = store.getState();
394
+
395
+ // Filter out nodes that cannot be pasted (unremovable or singleton already on canvas)
396
+ const skippedLabels: string[] = [];
397
+ const pastableNodes = clipboard.nodes.filter((node) => {
398
+ if (!getNodeDefinition) return true;
399
+ const def = getNodeDefinition(node.data);
400
+ if (!def) return true;
401
+ if (!canAddNode(store, def)) {
402
+ skippedLabels.push(def.label);
403
+ return false;
404
+ }
405
+ return true;
406
+ });
407
+
408
+ if (pastableNodes.length === 0) return { pasted: false, skippedLabels };
409
+
410
+ // Build old ID -> new ID mapping (only for pastable nodes)
411
+ const idMap = new Map<string, string>();
412
+ pastableNodes.forEach((node) => {
413
+ const newId = generateId();
414
+ idMap.set(node.id, newId);
415
+ });
416
+
417
+ // Create new nodes with updated IDs and positions
418
+ const newNodes: Node<NodeData>[] = pastableNodes.map((node) => {
419
+ const newId = idMap.get(node.id)!;
420
+
421
+ // Deep copy and update node data
422
+ const newData = JSON.parse(JSON.stringify(node.data)) as NodeData;
423
+ newData.id = newId;
424
+
425
+ // Update expression references to point to new node IDs
426
+ newData.arguments = updateExpressionsInArgs(getArguments(newData), idMap) as typeof newData.arguments;
427
+
428
+ return {
429
+ ...node,
430
+ id: newId,
431
+ position: {
432
+ x: node.position.x + offset.x,
433
+ y: node.position.y + offset.y,
434
+ },
435
+ data: newData,
436
+ selected: true,
437
+ };
438
+ });
439
+
440
+ // Dedupe emit binding names on pasted nodes against existing variables.
441
+ // (Pasted nodes come from JSON.parse(JSON.stringify(...)) of live nodes, so
442
+ // their bindings are already present in the correct arguments locations.)
443
+ const existingNames = collectVariableNames(store);
444
+ for (const node of newNodes) {
445
+ deduplicateEmitNames(node.data, existingNames);
446
+ }
447
+
448
+ // Create new edges with updated IDs (only for edges where both nodes are pasted)
449
+ const newEdges: Edge<EdgeData>[] = clipboard.edges
450
+ .filter((edge) => idMap.has(edge.source) && idMap.has(edge.target))
451
+ .map((edge) => {
452
+ const newEdge = {
453
+ ...edge,
454
+ id: generateId(),
455
+ source: idMap.get(edge.source)!,
456
+ target: idMap.get(edge.target)!,
457
+ data: edge.data ? { ...edge.data } : edge.data,
458
+ };
459
+ // Remap prompt references on agentTask edges
460
+ if (newEdge.data?.prompt && isExpression(newEdge.data.prompt)) {
461
+ const prompt = newEdge.data.prompt as Expression;
462
+ newEdge.data = {
463
+ ...newEdge.data,
464
+ prompt: {
465
+ ...prompt,
466
+ references: prompt.references.map((ref) => ({
467
+ srcId: idMap.get(ref.srcId) ?? ref.srcId,
468
+ varId: ref.varId,
469
+ })),
470
+ },
471
+ };
472
+ }
473
+ return newEdge;
474
+ });
475
+
476
+ // Deselect existing nodes before adding new ones
477
+ setNodes((nds) => [...nds.map((n) => ({ ...n, selected: false })), ...newNodes]);
478
+ setEdges((eds) => [...eds, ...newEdges]);
479
+
480
+ // Add pasted nodes' variables to store
481
+ setVariables((vars) => ({ ...vars, ...computeVariablesFromNodes(newNodes.map((n) => n.data)) }));
482
+
483
+ return { pasted: true, skippedLabels };
484
+ }
485
+
486
+ // ============================================================================
487
+ // Expression Reference Updater (for paste)
488
+ // ============================================================================
489
+
490
+ /** Update expression references to point to new node IDs after paste */
491
+ function updateExpressionsInArgs(args: Record<string, unknown>, idMap: Map<string, string>): Record<string, unknown> {
492
+ const updated: Record<string, unknown> = {};
493
+
494
+ for (const [key, value] of Object.entries(args)) {
495
+ if (isExpression(value)) {
496
+ // Update references with new node IDs
497
+ const updatedExpr: Expression = {
498
+ expression: value.expression,
499
+ dataType: value.dataType,
500
+ references: value.references.map((ref) => ({
501
+ srcId: idMap.get(ref.srcId) ?? ref.srcId,
502
+ varId: ref.varId,
503
+ })),
504
+ };
505
+ updated[key] = updatedExpr;
506
+ } else if (Array.isArray(value)) {
507
+ // Handle arrays of expressions
508
+ updated[key] = value.map((item) => {
509
+ if (isExpression(item)) {
510
+ return {
511
+ expression: item.expression,
512
+ dataType: item.dataType,
513
+ references: item.references.map((ref) => ({
514
+ srcId: idMap.get(ref.srcId) ?? ref.srcId,
515
+ varId: ref.varId,
516
+ })),
517
+ };
518
+ }
519
+ return item;
520
+ });
521
+ } else if (value !== null && typeof value === "object") {
522
+ // Handle nested objects
523
+ updated[key] = updateExpressionsInArgs(value as Record<string, unknown>, idMap);
524
+ } else {
525
+ updated[key] = value;
526
+ }
527
+ }
528
+
529
+ return updated;
530
+ }
531
+
532
+ // ============================================================================
533
+ // ReactFlow Type Resolution
534
+ // ============================================================================
535
+
536
+ /** Determine React Flow node type based on NodeCategory */
537
+ export function getReactFlowType(type: NodeType): string {
538
+ if (type === "FunctionCall") {
539
+ return "FunctionCall";
540
+ }
541
+ const category = NodeRegistry.getByType(type)?.category ?? "Uncategorized";
542
+ switch (category) {
543
+ case NodeCategory.Trigger:
544
+ case NodeCategory.Tool:
545
+ case NodeCategory.AI:
546
+ return category;
547
+ default:
548
+ return "Standard";
549
+ }
550
+ }