@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,168 @@
1
+ import { useState, useCallback, useEffect } from "react";
2
+ import { MAIN_CANVAS_ID } from "../stores/canvasStore";
3
+ import { useEditorStore } from "../stores/editorStore";
4
+
5
+ // Holds info for a canvas tab. id is identical to canvasId.
6
+ export interface CanvasTab {
7
+ id: string;
8
+ label: string;
9
+ }
10
+
11
+ /**
12
+ * Hook for managing canvas tabs UI.
13
+ * Tab switching directly updates the UI store's activeCanvasId.
14
+ */
15
+ export const useCanvasTabs = () => {
16
+ const [tabs, setTabs] = useState<CanvasTab[]>([{ id: MAIN_CANVAS_ID, label: "Main" }]);
17
+
18
+ // Get active canvas ID and setter from editor store
19
+ const activeCanvasId = useEditorStore((state) => state.activeCanvasId);
20
+ const setActiveCanvas = useEditorStore((state) => state.setActiveCanvas);
21
+ const selectFunction = useEditorStore((state) => state.selectFunction);
22
+
23
+ // Tabs are a projection of the function declarations: a deleted function drops its
24
+ // tab (falling back to Main if it was active), a renamed one relabels. Open/close
25
+ // of an existing function's tab is still explicit (openTab/closeTab) — this only
26
+ // reconciles against the source of truth so the strip can't show a stale function.
27
+ const functions = useEditorStore((state) => state.functions);
28
+ useEffect(() => {
29
+ setTabs((prev) => {
30
+ let changed = false;
31
+ const next = prev.flatMap<CanvasTab>((t) => {
32
+ if (t.id === MAIN_CANVAS_ID) return [t];
33
+ const fn = functions[t.id];
34
+ if (!fn) {
35
+ changed = true;
36
+ return [];
37
+ }
38
+ if (fn.name !== t.label) {
39
+ changed = true;
40
+ return [{ ...t, label: fn.name }];
41
+ }
42
+ return [t];
43
+ });
44
+ return changed ? next : prev;
45
+ });
46
+ if (activeCanvasId !== MAIN_CANVAS_ID && !functions[activeCanvasId]) {
47
+ setActiveCanvas(MAIN_CANVAS_ID);
48
+ }
49
+ }, [functions, activeCanvasId, setActiveCanvas]);
50
+
51
+ // Switch to a tab's canvas. A function tab focuses its declaration (selectFunction
52
+ // switches the canvas AND selects the function so its config panel opens) — matching
53
+ // the dropdown/sidebar open path; any other tab just switches the canvas.
54
+ const setActiveTabId = useCallback(
55
+ (tabId: string) => {
56
+ if (tabId !== MAIN_CANVAS_ID && functions[tabId]) {
57
+ selectFunction(tabId);
58
+ } else {
59
+ setActiveCanvas(tabId);
60
+ }
61
+ },
62
+ [functions, selectFunction, setActiveCanvas],
63
+ );
64
+
65
+ // Open a tab for a function (add if not exists, switch to it)
66
+ const openTab = useCallback(
67
+ (id: string, label: string) => {
68
+ setTabs((prev) => {
69
+ const existing = prev.find((t) => t.id === id);
70
+ if (existing) {
71
+ return prev; // Already exists
72
+ }
73
+ return [...prev, { id, label }];
74
+ });
75
+ setActiveCanvas(id);
76
+ return id;
77
+ },
78
+ [setActiveCanvas],
79
+ );
80
+
81
+ // Close a tab (just removes from visible tabs, does NOT delete canvas data)
82
+ const closeTab = useCallback(
83
+ (tabId: string) => {
84
+ // Cannot close main tab
85
+ if (tabId === MAIN_CANVAS_ID) return;
86
+
87
+ setTabs((prev) => {
88
+ const filtered = prev.filter((t) => t.id !== tabId);
89
+ // If closing active tab, switch to main
90
+ if (tabId === activeCanvasId) {
91
+ setActiveCanvas(MAIN_CANVAS_ID);
92
+ }
93
+ return filtered;
94
+ });
95
+ },
96
+ [activeCanvasId, setActiveCanvas],
97
+ );
98
+
99
+ // Remove a tab completely (called when function is deleted)
100
+ const removeTab = useCallback(
101
+ (tabId: string) => {
102
+ if (tabId === MAIN_CANVAS_ID) return;
103
+
104
+ setTabs((prev) => {
105
+ const filtered = prev.filter((t) => t.id !== tabId);
106
+ // Switch to main canvas if removing active tab
107
+ if (tabId === activeCanvasId) {
108
+ setActiveCanvas(MAIN_CANVAS_ID);
109
+ }
110
+ return filtered;
111
+ });
112
+ },
113
+ [activeCanvasId, setActiveCanvas],
114
+ );
115
+
116
+ const renameTab = useCallback((tabId: string, newLabel: string) => {
117
+ setTabs((prev) => prev.map((t) => (t.id === tabId ? { ...t, label: newLabel } : t)));
118
+ }, []);
119
+
120
+ const reorderTabs = useCallback((fromIndex: number, toIndex: number) => {
121
+ if (fromIndex === 0 || toIndex === 0) return;
122
+ setTabs((prev) => {
123
+ const updated = [...prev];
124
+ const [moved] = updated.splice(fromIndex, 1);
125
+ if (!moved) return prev;
126
+ updated.splice(toIndex, 0, moved);
127
+ return updated;
128
+ });
129
+ }, []);
130
+
131
+ // Reset to main canvas only (closes all function tabs)
132
+ const resetToMain = useCallback(() => {
133
+ setTabs([{ id: MAIN_CANVAS_ID, label: "Main" }]);
134
+ setActiveCanvas(MAIN_CANVAS_ID);
135
+ }, [setActiveCanvas]);
136
+
137
+ // Restore a previously saved tab state
138
+ const restoreTabState = useCallback(
139
+ (savedTabs: CanvasTab[], savedActiveId: string) => {
140
+ setTabs(savedTabs);
141
+ setActiveCanvas(savedActiveId);
142
+ },
143
+ [setActiveCanvas],
144
+ );
145
+
146
+ // Get label for a tab
147
+ const getTabLabel = useCallback(
148
+ (tabId: string) => {
149
+ return tabs.find((t) => t.id === tabId)?.label || "Unknown";
150
+ },
151
+ [tabs],
152
+ );
153
+
154
+ return {
155
+ tabs,
156
+ activeTabId: activeCanvasId,
157
+ setActiveTabId,
158
+ openTab,
159
+ closeTab,
160
+ removeTab,
161
+ renameTab,
162
+ reorderTabs,
163
+ resetToMain,
164
+ restoreTabState,
165
+ getTabLabel,
166
+ isMainCanvas: activeCanvasId === MAIN_CANVAS_ID,
167
+ };
168
+ };
@@ -0,0 +1,40 @@
1
+ import { useEffect } from "react";
2
+ import { validateFunction } from "@foresthubai/workflow-core/diagnostics";
3
+ import { computeAvailableVariables } from "@foresthubai/workflow-core/variable";
4
+ import { useEditorStore } from "../stores/editorStore";
5
+ import { useDiagnosticsStore } from "../stores/diagnosticsStore";
6
+ import { getCanvasStore } from "../stores/canvasStore";
7
+
8
+ /**
9
+ * Keeps the `byFunctionId` diagnostics slot in sync with the function declarations —
10
+ * the single source for the sidebar tab badge, the function list ring, AND the config
11
+ * panel's per-output rings (they all read this slot). Mounted once at the
12
+ * workflow-builder root so it survives tab open/close.
13
+ *
14
+ * Scope-aware: each function is validated against its own body canvas's variables, so
15
+ * invalid/typed return expressions surface here too — not just missing ones. (Reacts
16
+ * to declaration/expression edits via `functions`; a body-only edit that changes the
17
+ * available variables without touching a declaration refreshes on the next
18
+ * declaration change or a full `validate`.)
19
+ */
20
+ export function useFunctionDiagnosticsSync(): void {
21
+ const functions = useEditorStore((s) => s.functions);
22
+
23
+ useEffect(() => {
24
+ const ds = useDiagnosticsStore.getState();
25
+
26
+ const seen = new Set<string>();
27
+ for (const [id, def] of Object.entries(functions)) {
28
+ seen.add(id);
29
+ const store = getCanvasStore(id);
30
+ const lookup = store
31
+ ? computeAvailableVariables(store.getState().variables, store.getState().edges).lookup
32
+ : undefined;
33
+ ds.setFunctionDiagnostics(id, validateFunction(def, lookup));
34
+ }
35
+
36
+ for (const id of Object.keys(ds.byFunctionId)) {
37
+ if (!seen.has(id)) ds.clearFunctionDiagnostics(id);
38
+ }
39
+ }, [functions]);
40
+ }
@@ -0,0 +1,26 @@
1
+ import { useCallback, useMemo } from "react";
2
+ import { useEditorStore } from "../stores/editorStore";
3
+ import type { FunctionDeclaration } from "@foresthubai/workflow-core/function";
4
+
5
+ // Functions are a project-scoped resource: the registry IS editorStore.functions —
6
+ // the domain FunctionDeclaration, no conversion. (Crossing to the flat api FunctionInfo
7
+ // is done only when stamping a call-site snapshot; see useNodeDefinitions/migration.)
8
+
9
+ /**
10
+ * Access to all function declarations by id. Reactive over editorStore.functions.
11
+ * - functions: Record of FunctionDeclaration by id
12
+ * - functionsList: array of FunctionDeclaration
13
+ * - getFunction(id): one declaration by id
14
+ */
15
+ export function useFunctionRegistry() {
16
+ const functions = useEditorStore((s) => s.functions);
17
+ const functionsList = useMemo(() => Object.values(functions), [functions]);
18
+ const getFunction = useCallback((id: string): FunctionDeclaration | undefined => functions[id], [functions]);
19
+
20
+ return { functions, functionsList, getFunction };
21
+ }
22
+
23
+ /** All function declarations without React subscription (for non-component code). */
24
+ export function getAllFunctions(): Record<string, FunctionDeclaration> {
25
+ return useEditorStore.getState().functions;
26
+ }
@@ -0,0 +1,44 @@
1
+ import { useCallback } from "react";
2
+ import { useEditorStore } from "../stores/editorStore";
3
+ import { getOrCreateCanvasStore } from "../stores/canvasStore";
4
+ import { useFunctionRegistry } from "./useFunctionRegistry";
5
+ import { addFunction } from "../utils/functionOperations";
6
+
7
+ export interface UseFunctionsOptions {
8
+ /** Open (or focus) a tab for a function canvas. */
9
+ onOpenTab: (id: string, label: string) => void;
10
+ }
11
+
12
+ /**
13
+ * Coordinates the canvas-tab UI with function declarations (editorStore). The
14
+ * declarations themselves are CRUD'd in utils/functionOperations; this hook only
15
+ * handles the open/create flows that must also touch the tab strip and selection.
16
+ */
17
+ export const useFunctions = ({ onOpenTab }: UseFunctionsOptions) => {
18
+ const { functionsList: functions, getFunction } = useFunctionRegistry();
19
+ const selectFunction = useEditorStore((s) => s.selectFunction);
20
+
21
+ // Open an existing function: ensure its body canvas exists, open its tab, and
22
+ // select it so the right panel shows its definition. onOpenTab switches the active
23
+ // canvas first; selectFunction sets the selection last so it isn't cleared.
24
+ const openFunction = useCallback(
25
+ (functionId: string) => {
26
+ const fn = getFunction(functionId);
27
+ if (!fn) return;
28
+ getOrCreateCanvasStore(functionId);
29
+ onOpenTab(functionId, fn.name);
30
+ selectFunction(functionId);
31
+ },
32
+ [getFunction, onOpenTab, selectFunction],
33
+ );
34
+
35
+ // Create a new function and open it (the canvas body is created by addFunction).
36
+ const createFunction = useCallback(() => {
37
+ const fn = addFunction();
38
+ onOpenTab(fn.id, fn.name);
39
+ selectFunction(fn.id);
40
+ return fn.id;
41
+ }, [onOpenTab, selectFunction]);
42
+
43
+ return { functions, openFunction, createFunction };
44
+ };
@@ -0,0 +1,161 @@
1
+ import { NodeDefinition, NodeData } from "@foresthubai/workflow-core/node";
2
+ import { Connection, Edge, Node } from "@xyflow/react";
3
+ import type { EdgeData } from "@foresthubai/workflow-core/edge";
4
+ import { useCallback } from "react";
5
+ import { getOrCreateCanvasStore, MAIN_CANVAS_ID } from "../stores/canvasStore";
6
+ import {
7
+ addNodeToStore,
8
+ type Clipboard,
9
+ connectNodesInStore,
10
+ deleteEdgesFromStore,
11
+ deleteNodeFromStore,
12
+ pasteToStore,
13
+ updateEdgeInStore,
14
+ updateNodeInStore,
15
+ } from "../utils/graphOperations";
16
+ import type { EdgeType } from "@foresthubai/workflow-core/edge";
17
+ import { useNodeDefinitions } from "./useNodeDefinitions";
18
+
19
+ // Shared across all useGraph instances (one per canvas) so copy/paste works
20
+ // across canvas switches within a single builder session.
21
+ const clipboardRef: { current: Clipboard | null } = { current: null };
22
+
23
+ /**
24
+ * Hook that provides graph management actions for a specific canvas.
25
+ *
26
+ * All mutations are:
27
+ * - Gated by readOnly (no-op when true)
28
+ * - Automatically wrapped in a history checkpoint (undo/redo)
29
+ *
30
+ * Callers don't need to worry about either concern.
31
+ */
32
+ export const useGraph = (canvasId: string = MAIN_CANVAS_ID, readOnly: boolean = false) => {
33
+ const canvasStore = getOrCreateCanvasStore(canvasId);
34
+ const nodes = canvasStore((s) => s.nodes);
35
+ const edges = canvasStore((s) => s.edges);
36
+ const { withCheckpoint } = canvasStore;
37
+
38
+ const { getNodeDefinition } = useNodeDefinitions();
39
+
40
+ // Guarded checkpoint: skips when readOnly, otherwise wraps in undo history entry
41
+ const guarded = useCallback(
42
+ <R>(operation: () => R): R | undefined => {
43
+ if (readOnly) return undefined;
44
+ return withCheckpoint(operation);
45
+ },
46
+ [readOnly, withCheckpoint],
47
+ );
48
+
49
+ const addNode = useCallback(
50
+ (nodeDef: NodeDefinition, position?: { x: number; y: number }) => {
51
+ return guarded(() => addNodeToStore(canvasStore, nodeDef, position)) ?? null;
52
+ },
53
+ [canvasStore, guarded],
54
+ );
55
+
56
+ const updateNode = useCallback(
57
+ (nodeId: string, updates: { arguments?: Record<string, unknown>; label?: string }) => {
58
+ guarded(() => updateNodeInStore(canvasStore, nodeId, updates));
59
+ },
60
+ [canvasStore, guarded],
61
+ );
62
+
63
+ const deleteNode = useCallback(
64
+ (nodeId: string) => {
65
+ guarded(() => deleteNodeFromStore(canvasStore, nodeId, getNodeDefinition));
66
+ },
67
+ [canvasStore, getNodeDefinition, guarded],
68
+ );
69
+
70
+ const onConnect = useCallback(
71
+ (connection: Connection): EdgeType | false => {
72
+ return guarded(() => connectNodesInStore(canvasStore, connection)) ?? false;
73
+ },
74
+ [canvasStore, guarded],
75
+ );
76
+
77
+ const updateEdge = useCallback(
78
+ (edgeId: string, updates: Record<string, unknown>) => {
79
+ guarded(() => updateEdgeInStore(canvasStore, edgeId, updates));
80
+ },
81
+ [canvasStore, guarded],
82
+ );
83
+
84
+ const deleteEdges = useCallback(
85
+ (edgeIds: string[]) => {
86
+ guarded(() => deleteEdgesFromStore(canvasStore, edgeIds));
87
+ },
88
+ [canvasStore, guarded],
89
+ );
90
+
91
+ // Batch delete nodes and edges as a single undo entry
92
+ const deleteSelected = useCallback(
93
+ (nodeIds: string[], edgeIds: string[]) => {
94
+ if (nodeIds.length === 0 && edgeIds.length === 0) return;
95
+ guarded(() => {
96
+ for (const nodeId of nodeIds) deleteNodeFromStore(canvasStore, nodeId, getNodeDefinition);
97
+ if (edgeIds.length > 0) deleteEdgesFromStore(canvasStore, edgeIds);
98
+ });
99
+ },
100
+ [canvasStore, getNodeDefinition, guarded],
101
+ );
102
+
103
+ // Copy is read-only — no checkpoint, no readOnly gate
104
+ const copySelection = useCallback(
105
+ (nodeIds: string[]) => {
106
+ if (nodeIds.length === 0) return;
107
+
108
+ const nodeIdSet = new Set(nodeIds);
109
+
110
+ const copiedNodes = nodes
111
+ .filter((node) => nodeIdSet.has(node.id))
112
+ .map((node) => JSON.parse(JSON.stringify(node)) as Node<NodeData>);
113
+
114
+ const copiedEdges = edges
115
+ .filter((edge) => nodeIdSet.has(edge.source) && nodeIdSet.has(edge.target))
116
+ .map((edge) => JSON.parse(JSON.stringify(edge)) as Edge<EdgeData>);
117
+
118
+ clipboardRef.current = { nodes: copiedNodes, edges: copiedEdges };
119
+ },
120
+ [nodes, edges],
121
+ );
122
+
123
+ const pasteSelection = useCallback(
124
+ (offset?: { x: number; y: number }) => {
125
+ const clipboard = clipboardRef.current;
126
+ if (!clipboard) return undefined;
127
+ return guarded(() => pasteToStore(canvasStore, clipboard, offset, getNodeDefinition));
128
+ },
129
+ [canvasStore, getNodeDefinition, guarded],
130
+ );
131
+
132
+ // Batch add node + connect as a single undo entry (used by contextual node picker)
133
+ const addNodeAndConnect = useCallback(
134
+ (nodeDef: NodeDefinition, position: { x: number; y: number }, connection: Connection): string | null => {
135
+ return (
136
+ guarded(() => {
137
+ const nodeId = addNodeToStore(canvasStore, nodeDef, position);
138
+ if (nodeId == null) return null;
139
+ connectNodesInStore(canvasStore, { ...connection, target: nodeId });
140
+ return nodeId;
141
+ }) ?? null
142
+ );
143
+ },
144
+ [canvasStore, guarded],
145
+ );
146
+
147
+ return {
148
+ nodes,
149
+ edges,
150
+ addNode,
151
+ updateNode,
152
+ updateEdge,
153
+ deleteNode,
154
+ deleteEdges,
155
+ deleteSelected,
156
+ onConnect,
157
+ addNodeAndConnect,
158
+ copySelection,
159
+ pasteSelection,
160
+ };
161
+ };
@@ -0,0 +1,82 @@
1
+ import { useMemo, useCallback } from "react";
2
+ import i18n from "../i18n";
3
+ import { NodeCategory, NodeRegistry, NodeDefinition, NodeData } from "@foresthubai/workflow-core/node";
4
+ import { useFunctionRegistry } from "./useFunctionRegistry";
5
+ import { toFunctionInfo, type FunctionInfo } from "@foresthubai/workflow-core/function";
6
+ import { FunctionCallNode, FunctionNodeDefinition, buildFunctionNodeDef as coreBuildFunctionNodeDef } from "@foresthubai/workflow-core/node";
7
+
8
+ /**
9
+ * Workflow-builder binding for {@link coreBuildFunctionNodeDef} — passes
10
+ * `i18n.t` so descriptions are translated. Consumers continue to call
11
+ * `buildFunctionNodeDef(fn)` unchanged; core's signature is the pure
12
+ * `(fn, t?)` form.
13
+ */
14
+ export function buildFunctionNodeDef(fn: FunctionInfo): FunctionNodeDefinition {
15
+ return coreBuildFunctionNodeDef(fn, i18n.t.bind(i18n));
16
+ }
17
+
18
+ // Use function registry to provide dynamic node definitions based on available functions
19
+ export const useNodeDefinitions = () => {
20
+ // Get static node definitions from registry (these never change)
21
+ const staticNodeDefs: NodeDefinition[] = NodeRegistry.getAll();
22
+
23
+ // Subscribe to function registry (derived from all canvas stores)
24
+ const { functions } = useFunctionRegistry();
25
+
26
+ // Dynamically create node definitions for each function. The call-site node def is
27
+ // built from the flat signature snapshot, so project the domain declaration here.
28
+ const functionNodeDefs: FunctionNodeDefinition[] = useMemo(
29
+ () => Object.values(functions).map((fn) => buildFunctionNodeDef(toFunctionInfo(fn))),
30
+ [functions],
31
+ );
32
+
33
+ // Get node definition for a node instance (still depending on all functions)
34
+ const getNodeDefinition = useCallback(
35
+ (node: NodeData): NodeDefinition | undefined => {
36
+ if (node.type === "FunctionCall") {
37
+ const fnNode = node as FunctionCallNode;
38
+ return functionNodeDefs.find((def) => def.type === "FunctionCall" && def.functionInfo.id === fnNode.functionInfo.id);
39
+ }
40
+ return NodeRegistry.getByType(node.type);
41
+ },
42
+ [functionNodeDefs],
43
+ );
44
+
45
+ const getNodeDefinitionsByCategory = useCallback(
46
+ (category: NodeCategory) => {
47
+ const staticNodes = NodeRegistry.getByCategory(category);
48
+ if (category === NodeCategory.Function) {
49
+ return [...staticNodes, ...functionNodeDefs];
50
+ }
51
+ return staticNodes;
52
+ },
53
+ [functionNodeDefs],
54
+ );
55
+
56
+ const getAllCategories = useCallback((): NodeCategory[] => {
57
+ const staticCategories = NodeRegistry.getAllCategories();
58
+ const allCategories = new Set([...staticCategories]);
59
+ if (functionNodeDefs.length > 0) {
60
+ allCategories.add(NodeCategory.Function);
61
+ }
62
+ const categoryOrder = [
63
+ NodeCategory.Trigger,
64
+ NodeCategory.Input,
65
+ NodeCategory.Logic,
66
+ NodeCategory.Data,
67
+ NodeCategory.Function,
68
+ NodeCategory.AI,
69
+ NodeCategory.Tool,
70
+ NodeCategory.Output,
71
+ ];
72
+ return categoryOrder.filter((cat) => allCategories.has(cat));
73
+ }, [functionNodeDefs]);
74
+
75
+ return {
76
+ nodeDefinitions: [...staticNodeDefs, ...functionNodeDefs],
77
+ getAllCategories,
78
+ getNodeDefinition,
79
+ getNodeDefinitionsByCategory,
80
+ };
81
+ };
82
+
@@ -0,0 +1,26 @@
1
+ import { useMemo } from "react";
2
+ import type { Diagnostic } from "@foresthubai/workflow-core/diagnostics";
3
+
4
+ /**
5
+ * Build a per-parameter error map (`paramId → messages`) from a resource's
6
+ * diagnostics, keeping only `error`-severity entries. Shared by every config
7
+ * panel that renders a parameter list (node / edge / channel / memory / model)
8
+ * so the inline Map-building loop lives in exactly one place.
9
+ *
10
+ * Memoized on `diags`, so callers can read it from the diagnostics store with a
11
+ * plain selector and pass the result straight through to `<ParameterEditor>`.
12
+ */
13
+ export function useParamErrors(diags: Diagnostic[] | undefined): Map<string, string[]> {
14
+ return useMemo(() => {
15
+ const map = new Map<string, string[]>();
16
+ if (!diags) return map;
17
+ for (const d of diags) {
18
+ if (d.paramId && d.severity === "error") {
19
+ const arr = map.get(d.paramId);
20
+ if (arr) arr.push(d.message);
21
+ else map.set(d.paramId, [d.message]);
22
+ }
23
+ }
24
+ return map;
25
+ }, [diags]);
26
+ }
@@ -0,0 +1,30 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ /**
4
+ * Returns "light" if `<html>` has the `light` class, else "dark". Subscribes to
5
+ * MutationObserver so toggles by the embedder propagate immediately.
6
+ *
7
+ * Dark is the default — the builder's CSS puts dark tokens on `:root` and
8
+ * overrides them under `.light`. This hook exists so things that need an
9
+ * explicit value — notably ReactFlow's `colorMode` prop — stay in sync.
10
+ */
11
+ export function useResolvedTheme(): "dark" | "light" {
12
+ const [theme, setTheme] = useState<"dark" | "light">(() => detect());
13
+
14
+ useEffect(() => {
15
+ if (typeof document === "undefined") return;
16
+ const root = document.documentElement;
17
+ const observer = new MutationObserver(() => setTheme(detect()));
18
+ observer.observe(root, { attributes: true, attributeFilter: ["class"] });
19
+ // Initial sync in case it changed between mount and effect.
20
+ setTheme(detect());
21
+ return () => observer.disconnect();
22
+ }, []);
23
+
24
+ return theme;
25
+ }
26
+
27
+ function detect(): "dark" | "light" {
28
+ if (typeof document === "undefined") return "dark";
29
+ return document.documentElement.classList.contains("light") ? "light" : "dark";
30
+ }
@@ -0,0 +1,58 @@
1
+ import { useEffect } from "react";
2
+ import { useEditorStore } from "../stores/editorStore";
3
+ import { useDiagnosticsStore } from "../stores/diagnosticsStore";
4
+ import type { Diagnostic } from "@foresthubai/workflow-core/diagnostics";
5
+
6
+ type EditorState = ReturnType<typeof useEditorStore.getState>;
7
+ type DiagnosticsState = ReturnType<typeof useDiagnosticsStore.getState>;
8
+
9
+ interface ResourceDiagnosticsSyncConfig<I extends { id: string }> {
10
+ /** Pick the resource map (e.g. `s.channels`) off the editor store. */
11
+ selectItems: (s: EditorState) => Record<string, I>;
12
+ /** Validate one instance into its diagnostics. */
13
+ validate: (item: I) => Diagnostic[];
14
+ /** Read the matching diagnostics slot (e.g. `d.byChannelId`). */
15
+ getStored: (d: DiagnosticsState) => Record<string, Diagnostic[]>;
16
+ /** Write one instance's diagnostics. */
17
+ set: (d: DiagnosticsState, id: string, diags: Diagnostic[]) => void;
18
+ /** Drop one instance's diagnostics. */
19
+ clear: (d: DiagnosticsState, id: string) => void;
20
+ }
21
+
22
+ /**
23
+ * Keeps a project-scoped diagnostics slot (`byChannelId` / `byMemoryId` /
24
+ * `byModelId`) in sync with the editor's resource map.
25
+ *
26
+ * These resources are project-scoped, not canvas-scoped, and are only rendered
27
+ * visually when their sidebar tab is open. Tying diagnostic writes to card
28
+ * lifecycles would mean errors vanish the moment that tab closes, so this hook
29
+ * is mounted once at the workflow-builder root and reactively rewrites the store
30
+ * whenever the resource map changes.
31
+ *
32
+ * Lifecycle handled implicitly by the effect:
33
+ * - Load → setItems fires → effect re-runs → diagnostics written
34
+ * - Edit → store mutates → effect re-runs → entry replaced
35
+ * - Delete → item leaves → orphan branch → entry cleared
36
+ * - Unmount → store goes down with the app (no cleanup needed)
37
+ */
38
+ export function useResourceDiagnosticsSync<I extends { id: string }>(config: ResourceDiagnosticsSyncConfig<I>): void {
39
+ const items = useEditorStore(config.selectItems);
40
+
41
+ useEffect(() => {
42
+ const ds = useDiagnosticsStore.getState();
43
+
44
+ const seen = new Set<string>();
45
+ for (const item of Object.values(items)) {
46
+ seen.add(item.id);
47
+ config.set(ds, item.id, config.validate(item));
48
+ }
49
+
50
+ // Drop entries for items that have been deleted.
51
+ for (const id of Object.keys(config.getStored(ds))) {
52
+ if (!seen.has(id)) config.clear(ds, id);
53
+ }
54
+ // `config` is recreated each render but only `items` drives a resync; the
55
+ // effect reads the latest closure on every run.
56
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ }, [items]);
58
+ }