@foresthubai/workflow-builder 0.4.3 → 0.4.5

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 (414) hide show
  1. package/LICENSE +661 -661
  2. package/NOTICE +16 -16
  3. package/README.md +110 -110
  4. package/dist/BuilderLayout.d.ts.map +1 -1
  5. package/dist/BuilderLayout.js +52 -61
  6. package/dist/BuilderLayout.js.map +1 -1
  7. package/dist/Canvas.d.ts.map +1 -1
  8. package/dist/Canvas.js +10 -3
  9. package/dist/Canvas.js.map +1 -1
  10. package/dist/CanvasEditor.d.ts.map +1 -1
  11. package/dist/CanvasEditor.js.map +1 -1
  12. package/dist/CanvasTabsToolbar.d.ts.map +1 -1
  13. package/dist/CanvasTabsToolbar.js +3 -0
  14. package/dist/CanvasTabsToolbar.js.map +1 -1
  15. package/dist/RightConfigPanel.d.ts.map +1 -1
  16. package/dist/RightConfigPanel.js +3 -0
  17. package/dist/RightConfigPanel.js.map +1 -1
  18. package/dist/WorkflowBuilder.d.ts +7 -13
  19. package/dist/WorkflowBuilder.d.ts.map +1 -1
  20. package/dist/WorkflowBuilder.js +25 -13
  21. package/dist/WorkflowBuilder.js.map +1 -1
  22. package/dist/cn.d.ts.map +1 -1
  23. package/dist/cn.js +3 -0
  24. package/dist/cn.js.map +1 -1
  25. package/dist/components/ui/add-button.d.ts.map +1 -1
  26. package/dist/components/ui/add-button.js +3 -0
  27. package/dist/components/ui/add-button.js.map +1 -1
  28. package/dist/components/ui/alert-dialog.d.ts.map +1 -1
  29. package/dist/components/ui/alert-dialog.js +3 -0
  30. package/dist/components/ui/alert-dialog.js.map +1 -1
  31. package/dist/components/ui/alert.d.ts.map +1 -1
  32. package/dist/components/ui/alert.js +3 -0
  33. package/dist/components/ui/alert.js.map +1 -1
  34. package/dist/components/ui/badge.d.ts.map +1 -1
  35. package/dist/components/ui/badge.js.map +1 -1
  36. package/dist/components/ui/button.d.ts.map +1 -1
  37. package/dist/components/ui/button.js +3 -0
  38. package/dist/components/ui/button.js.map +1 -1
  39. package/dist/components/ui/card.d.ts.map +1 -1
  40. package/dist/components/ui/card.js +3 -0
  41. package/dist/components/ui/card.js.map +1 -1
  42. package/dist/components/ui/checkbox.d.ts.map +1 -1
  43. package/dist/components/ui/checkbox.js +3 -0
  44. package/dist/components/ui/checkbox.js.map +1 -1
  45. package/dist/components/ui/collapsible.d.ts.map +1 -1
  46. package/dist/components/ui/collapsible.js +3 -0
  47. package/dist/components/ui/collapsible.js.map +1 -1
  48. package/dist/components/ui/command.d.ts +2 -2
  49. package/dist/components/ui/command.d.ts.map +1 -1
  50. package/dist/components/ui/command.js +3 -0
  51. package/dist/components/ui/command.js.map +1 -1
  52. package/dist/components/ui/delete-button.d.ts.map +1 -1
  53. package/dist/components/ui/delete-button.js +3 -0
  54. package/dist/components/ui/delete-button.js.map +1 -1
  55. package/dist/components/ui/dialog.d.ts.map +1 -1
  56. package/dist/components/ui/dialog.js +3 -0
  57. package/dist/components/ui/dialog.js.map +1 -1
  58. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  59. package/dist/components/ui/dropdown-menu.js +3 -0
  60. package/dist/components/ui/dropdown-menu.js.map +1 -1
  61. package/dist/components/ui/input.d.ts +1 -1
  62. package/dist/components/ui/input.d.ts.map +1 -1
  63. package/dist/components/ui/input.js +3 -0
  64. package/dist/components/ui/input.js.map +1 -1
  65. package/dist/components/ui/label.d.ts.map +1 -1
  66. package/dist/components/ui/label.js +3 -0
  67. package/dist/components/ui/label.js.map +1 -1
  68. package/dist/components/ui/readonly-banner.d.ts.map +1 -1
  69. package/dist/components/ui/readonly-banner.js +3 -0
  70. package/dist/components/ui/readonly-banner.js.map +1 -1
  71. package/dist/components/ui/resizable.d.ts +1 -1
  72. package/dist/components/ui/resizable.d.ts.map +1 -1
  73. package/dist/components/ui/resizable.js +3 -0
  74. package/dist/components/ui/resizable.js.map +1 -1
  75. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  76. package/dist/components/ui/scroll-area.js +3 -0
  77. package/dist/components/ui/scroll-area.js.map +1 -1
  78. package/dist/components/ui/select.d.ts.map +1 -1
  79. package/dist/components/ui/select.js +3 -0
  80. package/dist/components/ui/select.js.map +1 -1
  81. package/dist/components/ui/separator.d.ts.map +1 -1
  82. package/dist/components/ui/separator.js +3 -0
  83. package/dist/components/ui/separator.js.map +1 -1
  84. package/dist/components/ui/switch.d.ts.map +1 -1
  85. package/dist/components/ui/switch.js +3 -0
  86. package/dist/components/ui/switch.js.map +1 -1
  87. package/dist/components/ui/textarea.d.ts +1 -1
  88. package/dist/components/ui/textarea.d.ts.map +1 -1
  89. package/dist/components/ui/textarea.js +3 -0
  90. package/dist/components/ui/textarea.js.map +1 -1
  91. package/dist/components/ui/toast.d.ts.map +1 -1
  92. package/dist/components/ui/toast.js +3 -0
  93. package/dist/components/ui/toast.js.map +1 -1
  94. package/dist/components/ui/toaster.d.ts.map +1 -1
  95. package/dist/components/ui/toaster.js +3 -0
  96. package/dist/components/ui/toaster.js.map +1 -1
  97. package/dist/components/ui/toggle-group.d.ts.map +1 -1
  98. package/dist/components/ui/toggle-group.js +3 -0
  99. package/dist/components/ui/toggle-group.js.map +1 -1
  100. package/dist/components/ui/toggle.d.ts.map +1 -1
  101. package/dist/components/ui/toggle.js +3 -0
  102. package/dist/components/ui/toggle.js.map +1 -1
  103. package/dist/components/ui/tooltip.d.ts.map +1 -1
  104. package/dist/components/ui/tooltip.js +3 -0
  105. package/dist/components/ui/tooltip.js.map +1 -1
  106. package/dist/dialogs/NodePickerDialog.d.ts.map +1 -1
  107. package/dist/dialogs/NodePickerDialog.js +3 -0
  108. package/dist/dialogs/NodePickerDialog.js.map +1 -1
  109. package/dist/dialogs/ValidationDialog.d.ts.map +1 -1
  110. package/dist/dialogs/ValidationDialog.js +3 -0
  111. package/dist/dialogs/ValidationDialog.js.map +1 -1
  112. package/dist/graph/BaseNode.d.ts.map +1 -1
  113. package/dist/graph/BaseNode.js +21 -16
  114. package/dist/graph/BaseNode.js.map +1 -1
  115. package/dist/graph/CustomEdge.d.ts.map +1 -1
  116. package/dist/graph/CustomEdge.js +4 -1
  117. package/dist/graph/CustomEdge.js.map +1 -1
  118. package/dist/graph/CustomNode.d.ts.map +1 -1
  119. package/dist/graph/CustomNode.js +3 -0
  120. package/dist/graph/CustomNode.js.map +1 -1
  121. package/dist/graph/FunctionCallNode.d.ts.map +1 -1
  122. package/dist/graph/FunctionCallNode.js.map +1 -1
  123. package/dist/graph/PortHandle.d.ts.map +1 -1
  124. package/dist/graph/PortHandle.js.map +1 -1
  125. package/dist/graph/reactFlowRegistry.d.ts.map +1 -1
  126. package/dist/graph/reactFlowRegistry.js +3 -0
  127. package/dist/graph/reactFlowRegistry.js.map +1 -1
  128. package/dist/hooks/use-toast.d.ts.map +1 -1
  129. package/dist/hooks/use-toast.js +3 -0
  130. package/dist/hooks/use-toast.js.map +1 -1
  131. package/dist/hooks/useAvailableVariables.d.ts.map +1 -1
  132. package/dist/hooks/useAvailableVariables.js +3 -0
  133. package/dist/hooks/useAvailableVariables.js.map +1 -1
  134. package/dist/hooks/useCanvasHistory.d.ts.map +1 -1
  135. package/dist/hooks/useCanvasHistory.js +3 -0
  136. package/dist/hooks/useCanvasHistory.js.map +1 -1
  137. package/dist/hooks/useCanvasTabs.d.ts.map +1 -1
  138. package/dist/hooks/useCanvasTabs.js +3 -0
  139. package/dist/hooks/useCanvasTabs.js.map +1 -1
  140. package/dist/hooks/useFunctionDiagnosticsSync.d.ts.map +1 -1
  141. package/dist/hooks/useFunctionDiagnosticsSync.js +3 -0
  142. package/dist/hooks/useFunctionDiagnosticsSync.js.map +1 -1
  143. package/dist/hooks/useFunctionRegistry.d.ts.map +1 -1
  144. package/dist/hooks/useFunctionRegistry.js +3 -0
  145. package/dist/hooks/useFunctionRegistry.js.map +1 -1
  146. package/dist/hooks/useFunctions.d.ts.map +1 -1
  147. package/dist/hooks/useFunctions.js +3 -0
  148. package/dist/hooks/useFunctions.js.map +1 -1
  149. package/dist/hooks/useGraph.d.ts.map +1 -1
  150. package/dist/hooks/useGraph.js +3 -0
  151. package/dist/hooks/useGraph.js.map +1 -1
  152. package/dist/hooks/useNodeDefinitions.d.ts.map +1 -1
  153. package/dist/hooks/useNodeDefinitions.js +3 -0
  154. package/dist/hooks/useNodeDefinitions.js.map +1 -1
  155. package/dist/hooks/useParamErrors.d.ts.map +1 -1
  156. package/dist/hooks/useParamErrors.js +3 -0
  157. package/dist/hooks/useParamErrors.js.map +1 -1
  158. package/dist/hooks/useResolvedTheme.d.ts.map +1 -1
  159. package/dist/hooks/useResolvedTheme.js +3 -0
  160. package/dist/hooks/useResolvedTheme.js.map +1 -1
  161. package/dist/hooks/useResourceDiagnosticsSync.d.ts.map +1 -1
  162. package/dist/hooks/useResourceDiagnosticsSync.js +3 -0
  163. package/dist/hooks/useResourceDiagnosticsSync.js.map +1 -1
  164. package/dist/hooks/useSuppressThemeTransition.d.ts.map +1 -1
  165. package/dist/hooks/useSuppressThemeTransition.js +3 -0
  166. package/dist/hooks/useSuppressThemeTransition.js.map +1 -1
  167. package/dist/hooks/useWorkflowSerialization.d.ts.map +1 -1
  168. package/dist/hooks/useWorkflowSerialization.js +3 -0
  169. package/dist/hooks/useWorkflowSerialization.js.map +1 -1
  170. package/dist/i18n/index.d.ts.map +1 -1
  171. package/dist/i18n/index.js +3 -0
  172. package/dist/i18n/index.js.map +1 -1
  173. package/dist/index.d.ts +1 -1
  174. package/dist/index.d.ts.map +1 -1
  175. package/dist/index.js +3 -0
  176. package/dist/index.js.map +1 -1
  177. package/dist/inputs/ExpressionInput.d.ts.map +1 -1
  178. package/dist/inputs/ExpressionInput.js +3 -0
  179. package/dist/inputs/ExpressionInput.js.map +1 -1
  180. package/dist/inputs/ParameterEditor.d.ts.map +1 -1
  181. package/dist/inputs/ParameterEditor.js +3 -0
  182. package/dist/inputs/ParameterEditor.js.map +1 -1
  183. package/dist/inputs/PortSection.d.ts.map +1 -1
  184. package/dist/inputs/PortSection.js.map +1 -1
  185. package/dist/mode.d.ts +11 -0
  186. package/dist/mode.d.ts.map +1 -0
  187. package/dist/mode.js +8 -0
  188. package/dist/mode.js.map +1 -0
  189. package/dist/panels/BuilderSidebar.d.ts.map +1 -1
  190. package/dist/panels/BuilderSidebar.js +3 -0
  191. package/dist/panels/BuilderSidebar.js.map +1 -1
  192. package/dist/panels/ChannelConfigPanel.d.ts.map +1 -1
  193. package/dist/panels/ChannelConfigPanel.js +3 -0
  194. package/dist/panels/ChannelConfigPanel.js.map +1 -1
  195. package/dist/panels/ChannelsPanel.d.ts.map +1 -1
  196. package/dist/panels/ChannelsPanel.js +3 -0
  197. package/dist/panels/ChannelsPanel.js.map +1 -1
  198. package/dist/panels/DebugConsolePanel.d.ts.map +1 -1
  199. package/dist/panels/DebugConsolePanel.js +3 -0
  200. package/dist/panels/DebugConsolePanel.js.map +1 -1
  201. package/dist/panels/DebugContextPanel.d.ts.map +1 -1
  202. package/dist/panels/DebugContextPanel.js +3 -0
  203. package/dist/panels/DebugContextPanel.js.map +1 -1
  204. package/dist/panels/DebugExternalIOPanel.d.ts.map +1 -1
  205. package/dist/panels/DebugExternalIOPanel.js +3 -0
  206. package/dist/panels/DebugExternalIOPanel.js.map +1 -1
  207. package/dist/panels/DiagnosticsPanel.d.ts.map +1 -1
  208. package/dist/panels/DiagnosticsPanel.js +3 -0
  209. package/dist/panels/DiagnosticsPanel.js.map +1 -1
  210. package/dist/panels/EdgeConfigPanel.d.ts.map +1 -1
  211. package/dist/panels/EdgeConfigPanel.js +4 -1
  212. package/dist/panels/EdgeConfigPanel.js.map +1 -1
  213. package/dist/panels/FunctionConfigPanel.d.ts.map +1 -1
  214. package/dist/panels/FunctionConfigPanel.js +4 -1
  215. package/dist/panels/FunctionConfigPanel.js.map +1 -1
  216. package/dist/panels/FunctionListPanel.d.ts.map +1 -1
  217. package/dist/panels/FunctionListPanel.js +3 -0
  218. package/dist/panels/FunctionListPanel.js.map +1 -1
  219. package/dist/panels/MemoryConfigPanel.d.ts.map +1 -1
  220. package/dist/panels/MemoryConfigPanel.js +3 -0
  221. package/dist/panels/MemoryConfigPanel.js.map +1 -1
  222. package/dist/panels/MemoryPanel.d.ts.map +1 -1
  223. package/dist/panels/MemoryPanel.js +3 -0
  224. package/dist/panels/MemoryPanel.js.map +1 -1
  225. package/dist/panels/ModelConfigPanel.d.ts.map +1 -1
  226. package/dist/panels/ModelConfigPanel.js +3 -0
  227. package/dist/panels/ModelConfigPanel.js.map +1 -1
  228. package/dist/panels/ModelsPanel.d.ts.map +1 -1
  229. package/dist/panels/ModelsPanel.js +3 -0
  230. package/dist/panels/ModelsPanel.js.map +1 -1
  231. package/dist/panels/NodeConfigPanel.d.ts.map +1 -1
  232. package/dist/panels/NodeConfigPanel.js +4 -1
  233. package/dist/panels/NodeConfigPanel.js.map +1 -1
  234. package/dist/panels/NodeLibrary.d.ts.map +1 -1
  235. package/dist/panels/NodeLibrary.js +4 -1
  236. package/dist/panels/NodeLibrary.js.map +1 -1
  237. package/dist/panels/ResourceConfigPanel.d.ts.map +1 -1
  238. package/dist/panels/ResourceConfigPanel.js +4 -1
  239. package/dist/panels/ResourceConfigPanel.js.map +1 -1
  240. package/dist/panels/ResourceListPanel.d.ts.map +1 -1
  241. package/dist/panels/ResourceListPanel.js +4 -1
  242. package/dist/panels/ResourceListPanel.js.map +1 -1
  243. package/dist/panels/VariableConfigPanel.d.ts.map +1 -1
  244. package/dist/panels/VariableConfigPanel.js +4 -1
  245. package/dist/panels/VariableConfigPanel.js.map +1 -1
  246. package/dist/panels/VariablesPanel.d.ts.map +1 -1
  247. package/dist/panels/VariablesPanel.js +4 -1
  248. package/dist/panels/VariablesPanel.js.map +1 -1
  249. package/dist/stores/canvasStore.d.ts.map +1 -1
  250. package/dist/stores/canvasStore.js +3 -0
  251. package/dist/stores/canvasStore.js.map +1 -1
  252. package/dist/stores/debugStore.d.ts.map +1 -1
  253. package/dist/stores/debugStore.js +3 -0
  254. package/dist/stores/debugStore.js.map +1 -1
  255. package/dist/stores/diagnosticsStore.d.ts.map +1 -1
  256. package/dist/stores/diagnosticsStore.js +3 -0
  257. package/dist/stores/diagnosticsStore.js.map +1 -1
  258. package/dist/stores/editorStore.d.ts +1 -1
  259. package/dist/stores/editorStore.d.ts.map +1 -1
  260. package/dist/stores/editorStore.js +3 -0
  261. package/dist/stores/editorStore.js.map +1 -1
  262. package/dist/utils/categoryConstants.d.ts.map +1 -1
  263. package/dist/utils/categoryConstants.js +3 -0
  264. package/dist/utils/categoryConstants.js.map +1 -1
  265. package/dist/utils/channelOperations.d.ts.map +1 -1
  266. package/dist/utils/channelOperations.js +3 -0
  267. package/dist/utils/channelOperations.js.map +1 -1
  268. package/dist/utils/connectionRules.d.ts +3 -1
  269. package/dist/utils/connectionRules.d.ts.map +1 -1
  270. package/dist/utils/connectionRules.js +11 -16
  271. package/dist/utils/connectionRules.js.map +1 -1
  272. package/dist/utils/functionOperations.d.ts.map +1 -1
  273. package/dist/utils/functionOperations.js +3 -0
  274. package/dist/utils/functionOperations.js.map +1 -1
  275. package/dist/utils/graphOperations.d.ts.map +1 -1
  276. package/dist/utils/graphOperations.js +3 -0
  277. package/dist/utils/graphOperations.js.map +1 -1
  278. package/dist/utils/history.d.ts.map +1 -1
  279. package/dist/utils/history.js +4 -1
  280. package/dist/utils/history.js.map +1 -1
  281. package/dist/utils/memoryOperations.d.ts.map +1 -1
  282. package/dist/utils/memoryOperations.js +3 -0
  283. package/dist/utils/memoryOperations.js.map +1 -1
  284. package/dist/utils/migrateFunctionNodes.d.ts.map +1 -1
  285. package/dist/utils/migrateFunctionNodes.js +3 -0
  286. package/dist/utils/migrateFunctionNodes.js.map +1 -1
  287. package/dist/utils/modelOperations.d.ts.map +1 -1
  288. package/dist/utils/modelOperations.js +3 -0
  289. package/dist/utils/modelOperations.js.map +1 -1
  290. package/dist/utils/paramDisplay.d.ts.map +1 -1
  291. package/dist/utils/paramDisplay.js +3 -0
  292. package/dist/utils/paramDisplay.js.map +1 -1
  293. package/dist/utils/resourceHelpers.d.ts.map +1 -1
  294. package/dist/utils/resourceHelpers.js +3 -0
  295. package/dist/utils/resourceHelpers.js.map +1 -1
  296. package/dist/utils/translation.d.ts.map +1 -1
  297. package/dist/utils/translation.js +3 -0
  298. package/dist/utils/translation.js.map +1 -1
  299. package/dist/utils/variableOperations.d.ts.map +1 -1
  300. package/dist/utils/variableOperations.js +3 -0
  301. package/dist/utils/variableOperations.js.map +1 -1
  302. package/package.json +2 -2
  303. package/src/BuilderLayout.tsx +338 -345
  304. package/src/Canvas.tsx +270 -261
  305. package/src/CanvasEditor.tsx +146 -142
  306. package/src/CanvasTabsToolbar.tsx +180 -176
  307. package/src/RightConfigPanel.tsx +270 -266
  308. package/src/WorkflowBuilder.tsx +423 -408
  309. package/src/cn.ts +10 -6
  310. package/src/components/ui/add-button.tsx +43 -39
  311. package/src/components/ui/alert-dialog.tsx +145 -141
  312. package/src/components/ui/alert.tsx +63 -59
  313. package/src/components/ui/badge.tsx +40 -36
  314. package/src/components/ui/button.tsx +89 -85
  315. package/src/components/ui/card.tsx +83 -79
  316. package/src/components/ui/checkbox.tsx +32 -28
  317. package/src/components/ui/collapsible.tsx +13 -9
  318. package/src/components/ui/command.tsx +157 -153
  319. package/src/components/ui/delete-button.tsx +27 -23
  320. package/src/components/ui/dialog.tsx +129 -125
  321. package/src/components/ui/dropdown-menu.tsx +202 -198
  322. package/src/components/ui/input.tsx +59 -55
  323. package/src/components/ui/label.tsx +28 -24
  324. package/src/components/ui/readonly-banner.tsx +19 -15
  325. package/src/components/ui/resizable.tsx +47 -43
  326. package/src/components/ui/scroll-area.tsx +106 -102
  327. package/src/components/ui/select.tsx +164 -160
  328. package/src/components/ui/separator.tsx +33 -29
  329. package/src/components/ui/switch.tsx +31 -27
  330. package/src/components/ui/textarea.tsx +55 -51
  331. package/src/components/ui/toast.tsx +131 -127
  332. package/src/components/ui/toaster.tsx +37 -33
  333. package/src/components/ui/toggle-group.tsx +63 -59
  334. package/src/components/ui/toggle.tsx +47 -43
  335. package/src/components/ui/tooltip.tsx +36 -32
  336. package/src/dialogs/NodePickerDialog.tsx +88 -84
  337. package/src/dialogs/ValidationDialog.tsx +188 -184
  338. package/src/graph/BaseNode.tsx +563 -557
  339. package/src/graph/CustomEdge.tsx +189 -185
  340. package/src/graph/CustomNode.tsx +20 -16
  341. package/src/graph/FunctionCallNode.tsx +34 -30
  342. package/src/graph/PortHandle.tsx +193 -189
  343. package/src/graph/reactFlowRegistry.ts +30 -26
  344. package/src/hooks/use-toast.ts +129 -125
  345. package/src/hooks/useAvailableVariables.ts +24 -20
  346. package/src/hooks/useCanvasHistory.ts +26 -22
  347. package/src/hooks/useCanvasTabs.ts +172 -168
  348. package/src/hooks/useFunctionDiagnosticsSync.ts +44 -40
  349. package/src/hooks/useFunctionRegistry.ts +30 -26
  350. package/src/hooks/useFunctions.ts +48 -44
  351. package/src/hooks/useGraph.ts +165 -161
  352. package/src/hooks/useNodeDefinitions.ts +86 -82
  353. package/src/hooks/useParamErrors.ts +30 -26
  354. package/src/hooks/useResolvedTheme.ts +34 -30
  355. package/src/hooks/useResourceDiagnosticsSync.ts +62 -58
  356. package/src/hooks/useSuppressThemeTransition.ts +83 -79
  357. package/src/hooks/useWorkflowSerialization.ts +145 -141
  358. package/src/i18n/index.ts +57 -53
  359. package/src/i18n/locales/de.json +501 -501
  360. package/src/i18n/locales/en.json +557 -557
  361. package/src/index.ts +31 -27
  362. package/src/inputs/ExpressionInput.tsx +301 -297
  363. package/src/inputs/ParameterEditor.tsx +519 -515
  364. package/src/inputs/PortSection.tsx +148 -144
  365. package/src/mode.ts +15 -0
  366. package/src/panels/BuilderSidebar.tsx +305 -301
  367. package/src/panels/ChannelConfigPanel.tsx +53 -49
  368. package/src/panels/ChannelsPanel.tsx +32 -28
  369. package/src/panels/DebugConsolePanel.tsx +77 -73
  370. package/src/panels/DebugContextPanel.tsx +81 -77
  371. package/src/panels/DebugExternalIOPanel.tsx +184 -180
  372. package/src/panels/DiagnosticsPanel.tsx +174 -170
  373. package/src/panels/EdgeConfigPanel.tsx +108 -104
  374. package/src/panels/FunctionConfigPanel.tsx +183 -179
  375. package/src/panels/FunctionListPanel.tsx +49 -45
  376. package/src/panels/MemoryConfigPanel.tsx +59 -55
  377. package/src/panels/MemoryPanel.tsx +44 -40
  378. package/src/panels/ModelConfigPanel.tsx +45 -41
  379. package/src/panels/ModelsPanel.tsx +40 -36
  380. package/src/panels/NodeConfigPanel.tsx +634 -630
  381. package/src/panels/NodeLibrary.tsx +292 -288
  382. package/src/panels/ResourceConfigPanel.tsx +136 -132
  383. package/src/panels/ResourceListPanel.tsx +117 -113
  384. package/src/panels/VariableConfigPanel.tsx +165 -161
  385. package/src/panels/VariablesPanel.tsx +149 -145
  386. package/src/stores/canvasStore.test.ts +48 -44
  387. package/src/stores/canvasStore.ts +249 -245
  388. package/src/stores/debugStore.ts +78 -74
  389. package/src/stores/diagnosticsStore.ts +134 -130
  390. package/src/stores/editorStore.ts +194 -190
  391. package/src/styles/index.css +526 -526
  392. package/src/utils/categoryConstants.ts +30 -26
  393. package/src/utils/channelOperations.ts +90 -86
  394. package/src/utils/connectionRules.ts +140 -137
  395. package/src/utils/functionOperations.ts +183 -179
  396. package/src/utils/graphOperations.ts +554 -550
  397. package/src/utils/history.test.ts +92 -0
  398. package/src/utils/history.ts +211 -207
  399. package/src/utils/memoryOperations.ts +61 -57
  400. package/src/utils/migrateFunctionNodes.ts +111 -107
  401. package/src/utils/modelOperations.ts +59 -55
  402. package/src/utils/paramDisplay.ts +75 -71
  403. package/src/utils/resourceHelpers.ts +36 -32
  404. package/src/utils/translation.ts +32 -28
  405. package/src/utils/variableOperations.ts +79 -75
  406. package/tailwind-preset.ts +170 -166
  407. package/dist/lib/utils.d.ts +0 -3
  408. package/dist/lib/utils.d.ts.map +0 -1
  409. package/dist/lib/utils.js +0 -6
  410. package/dist/lib/utils.js.map +0 -1
  411. package/dist/toolbars/CanvasTabsToolbar.d.ts +0 -11
  412. package/dist/toolbars/CanvasTabsToolbar.d.ts.map +0 -1
  413. package/dist/toolbars/CanvasTabsToolbar.js +0 -101
  414. package/dist/toolbars/CanvasTabsToolbar.js.map +0 -1
@@ -0,0 +1,92 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 ForestHub. All rights reserved.
3
+ // For commercial licensing, contact root@foresthub.ai
4
+
5
+ import { describe, it, expect, beforeEach } from "vitest";
6
+ import { create } from "zustand";
7
+ import { history } from "./history";
8
+
9
+ interface CounterState {
10
+ count: number;
11
+ label: string;
12
+ setCount: (n: number) => void;
13
+ }
14
+
15
+ // A store on DEFAULT config — no custom equality/partialize — so the default
16
+ // equality path is what's under test.
17
+ function makeStore() {
18
+ return create(
19
+ history<CounterState>()((set) => ({
20
+ count: 0,
21
+ label: "a",
22
+ setCount: (n) => set((s) => ({ ...s, count: n })),
23
+ })),
24
+ );
25
+ }
26
+
27
+ describe("history middleware (default config)", () => {
28
+ let store: ReturnType<typeof makeStore>;
29
+ beforeEach(() => {
30
+ store = makeStore();
31
+ });
32
+
33
+ it("withCheckpoint records a checkpoint when the operation changes state", () => {
34
+ store.getState().withCheckpoint(() => store.getState().setCount(1));
35
+ expect(store.getState().count).toBe(1);
36
+ expect(store.getState().canUndo()).toBe(true);
37
+
38
+ store.getState().undo();
39
+ expect(store.getState().count).toBe(0);
40
+ expect(store.getState().canRedo()).toBe(true);
41
+
42
+ store.getState().redo();
43
+ expect(store.getState().count).toBe(1);
44
+ });
45
+
46
+ it("withCheckpoint does NOT record a checkpoint for a no-op", () => {
47
+ store.getState().withCheckpoint(() => {});
48
+ expect(store.getState().canUndo()).toBe(false);
49
+ });
50
+
51
+ it("a no-op withCheckpoint preserves the redo stack", () => {
52
+ store.getState().withCheckpoint(() => store.getState().setCount(1));
53
+ store.getState().undo();
54
+ expect(store.getState().canRedo()).toBe(true);
55
+
56
+ store.getState().withCheckpoint(() => {});
57
+ expect(store.getState().canRedo()).toBe(true);
58
+ });
59
+
60
+ it("a real change clears the redo stack", () => {
61
+ store.getState().withCheckpoint(() => store.getState().setCount(1));
62
+ store.getState().undo();
63
+ store.getState().withCheckpoint(() => store.getState().setCount(7));
64
+ expect(store.getState().canRedo()).toBe(false);
65
+ });
66
+
67
+ it("withCheckpoint returns the operation's result and propagates throws without a checkpoint", () => {
68
+ expect(store.getState().withCheckpoint(() => 42)).toBe(42);
69
+ expect(() =>
70
+ store.getState().withCheckpoint(() => {
71
+ throw new Error("boom");
72
+ }),
73
+ ).toThrow("boom");
74
+ expect(store.getState().canUndo()).toBe(false);
75
+ });
76
+
77
+ it("mutationCount ticks on checkpointed changes only", () => {
78
+ const before = store.getState().mutationCount;
79
+ store.getState().withCheckpoint(() => {});
80
+ expect(store.getState().mutationCount).toBe(before);
81
+ store.getState().withCheckpoint(() => store.getState().setCount(5));
82
+ expect(store.getState().mutationCount).toBe(before + 1);
83
+ });
84
+
85
+ it("takeCheckpoint always records, and clearHistory empties both stacks", () => {
86
+ store.getState().takeCheckpoint();
87
+ expect(store.getState().canUndo()).toBe(true);
88
+ store.getState().clearHistory();
89
+ expect(store.getState().canUndo()).toBe(false);
90
+ expect(store.getState().canRedo()).toBe(false);
91
+ });
92
+ });
@@ -1,207 +1,211 @@
1
- import { StateCreator, StoreMutatorIdentifier } from "zustand";
2
-
3
- // Opaque type for exporting/importing history state
4
- export interface HistoryData {
5
- past: HistoryFrame<unknown>[];
6
- future: HistoryFrame<unknown>[];
7
- }
8
-
9
- // Public interface - only actions
10
- export interface History {
11
- /**
12
- * Manually saves the current state as an undo checkpoint.
13
- * Must be called BEFORE a state change that should be undoable.
14
- */
15
- takeCheckpoint: () => void;
16
-
17
- /**
18
- * Run the given operation and save a checkpoint if the state did change.
19
- * Good to wrap multiple state changes in a single undoable action.
20
- * If the operation throws, no checkpoint is saved and the error is propagated.
21
- * @param operation Function that may perform a state change.
22
- * @returns The result of the operation.
23
- */
24
- withCheckpoint: <R>(operation: () => R) => R;
25
-
26
- /**
27
- * Reverts the state to the previous snapshot in the undo history, if available.
28
- * Moves the current state to the redo history.
29
- */
30
- undo: () => void;
31
-
32
- /**
33
- * Reapplies the most recently undone state from the redo history, if available.
34
- * Moves the current state to the undo history.
35
- */
36
- redo: () => void;
37
-
38
- /**
39
- * Clears both the undo and redo history, but does not affect the current state.
40
- */
41
- clearHistory: () => void;
42
-
43
- /**
44
- * Returns true if there is at least one state in the undo history.
45
- */
46
- canUndo: () => boolean;
47
-
48
- /**
49
- * Returns true if there is at least one state in the redo history.
50
- */
51
- canRedo: () => boolean;
52
-
53
- /**
54
- * Exports the current undo/redo history as an opaque blob.
55
- */
56
- exportHistory: () => HistoryData;
57
-
58
- /**
59
- * Restores a previously exported history blob.
60
- */
61
- importHistory: (data: HistoryData) => void;
62
- }
63
-
64
- // A single frame in history
65
- interface HistoryFrame<T> {
66
- state: T;
67
- timestamp: number;
68
- }
69
-
70
- // Internal state - not exposed publicly
71
- interface HistoryState<T> {
72
- _history_past: HistoryFrame<T>[];
73
- _history_future: HistoryFrame<T>[];
74
- }
75
-
76
- /**
77
- * Public, opaque change signal: a monotonic counter the middleware bumps on every
78
- * history transition (checkpoint, undo, redo, clear, import). Subscribe to it to
79
- * detect domain mutations and undo/redo in O(1). It never ticks on selection or
80
- * drag — those mutate state without a checkpoint. Mirrors editorStore's counter
81
- * of the same name for project-scoped (channel/memory/model) mutations.
82
- */
83
- export interface MutationCount {
84
- readonly mutationCount: number;
85
- }
86
-
87
- // Configuration for history middleware
88
- interface HistoryConfig<T> {
89
- limit?: number;
90
- partialize?: (state: T) => Partial<T>;
91
- equality?: (before: Partial<T>, after: Partial<T>) => boolean;
92
- }
93
-
94
- export const history =
95
- <T>(config: HistoryConfig<T> = {}) =>
96
- <Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = []>(
97
- storeInitializer: StateCreator<T, Mps, Mcs>,
98
- ): StateCreator<T & HistoryState<T> & History & MutationCount, Mps, Mcs> => {
99
- const {
100
- limit = 50,
101
- partialize = (state) => state,
102
- equality = (before, after) => JSON.stringify(before) !== JSON.stringify(after),
103
- } = config;
104
-
105
- return (set, get, store) => {
106
- type FullState = T & HistoryState<T> & History & MutationCount;
107
-
108
- const initialState = storeInitializer(
109
- set as Parameters<StateCreator<T, Mps, Mcs>>[0],
110
- get as Parameters<StateCreator<T, Mps, Mcs>>[1],
111
- store as Parameters<StateCreator<T, Mps, Mcs>>[2],
112
- );
113
-
114
- return {
115
- ...initialState,
116
- _history_past: [],
117
- _history_future: [],
118
- mutationCount: 0,
119
-
120
- takeCheckpoint: () => {
121
- const currentState = partialize(get() as T);
122
- set((state: FullState) => ({
123
- ...state,
124
- _history_past: [...state._history_past, { state: currentState as T, timestamp: Date.now() }].slice(-limit),
125
- _history_future: [],
126
- mutationCount: state.mutationCount + 1,
127
- }));
128
- },
129
-
130
- withCheckpoint: <R>(operation: () => R): R => {
131
- const beforeState = partialize(get() as T);
132
- // Execute operation and capture result to return later to caller
133
- const result = operation();
134
- const afterState = partialize(get() as T);
135
- // Compare using provided equality function
136
- const areEqual = equality(beforeState, afterState);
137
- if (!areEqual) {
138
- set((state: FullState) => ({
139
- ...state,
140
- _history_past: [...state._history_past, { state: beforeState as T, timestamp: Date.now() }].slice(-limit),
141
- _history_future: [],
142
- mutationCount: state.mutationCount + 1,
143
- }));
144
- }
145
- return result;
146
- },
147
-
148
- undo: () => {
149
- const state = get();
150
- if (state._history_past.length === 0) return;
151
- const past = [...state._history_past];
152
- const previousFrame = past.pop()!;
153
- // Save current state to future before restoring
154
- const currentState = partialize(state as T);
155
- set({
156
- ...state,
157
- ...previousFrame.state,
158
- _history_past: past,
159
- _history_future: [...state._history_future, { state: currentState as T, timestamp: Date.now() }],
160
- mutationCount: state.mutationCount + 1,
161
- } as FullState);
162
- },
163
-
164
- redo: () => {
165
- const state = get();
166
- if (state._history_future.length === 0) return;
167
- const future = [...state._history_future];
168
- const nextFrame = future.pop()!;
169
- // Save current state to past before restoring
170
- const currentState = partialize(state as T);
171
- set({
172
- ...state,
173
- ...nextFrame.state,
174
- _history_past: [...state._history_past, { state: currentState as T, timestamp: Date.now() }].slice(-limit),
175
- _history_future: future,
176
- mutationCount: state.mutationCount + 1,
177
- } as FullState);
178
- },
179
-
180
- clearHistory: () => {
181
- set((state: FullState) => ({
182
- ...state,
183
- _history_past: [],
184
- _history_future: [],
185
- mutationCount: state.mutationCount + 1,
186
- }));
187
- },
188
-
189
- canUndo: () => (get() as FullState)._history_past.length > 0,
190
- canRedo: () => (get() as FullState)._history_future.length > 0,
191
-
192
- exportHistory: () => ({
193
- past: [...(get() as FullState)._history_past],
194
- future: [...(get() as FullState)._history_future],
195
- }),
196
-
197
- importHistory: (data: HistoryData) => {
198
- set((state: FullState) => ({
199
- ...state,
200
- _history_past: [...data.past] as HistoryFrame<T>[],
201
- _history_future: [...data.future] as HistoryFrame<T>[],
202
- mutationCount: state.mutationCount + 1,
203
- }));
204
- },
205
- } as FullState;
206
- };
207
- };
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 ForestHub. All rights reserved.
3
+ // For commercial licensing, contact root@foresthub.ai
4
+
5
+ import { StateCreator, StoreMutatorIdentifier } from "zustand";
6
+
7
+ // Opaque type for exporting/importing history state
8
+ export interface HistoryData {
9
+ past: HistoryFrame<unknown>[];
10
+ future: HistoryFrame<unknown>[];
11
+ }
12
+
13
+ // Public interface - only actions
14
+ export interface History {
15
+ /**
16
+ * Manually saves the current state as an undo checkpoint.
17
+ * Must be called BEFORE a state change that should be undoable.
18
+ */
19
+ takeCheckpoint: () => void;
20
+
21
+ /**
22
+ * Run the given operation and save a checkpoint if the state did change.
23
+ * Good to wrap multiple state changes in a single undoable action.
24
+ * If the operation throws, no checkpoint is saved and the error is propagated.
25
+ * @param operation Function that may perform a state change.
26
+ * @returns The result of the operation.
27
+ */
28
+ withCheckpoint: <R>(operation: () => R) => R;
29
+
30
+ /**
31
+ * Reverts the state to the previous snapshot in the undo history, if available.
32
+ * Moves the current state to the redo history.
33
+ */
34
+ undo: () => void;
35
+
36
+ /**
37
+ * Reapplies the most recently undone state from the redo history, if available.
38
+ * Moves the current state to the undo history.
39
+ */
40
+ redo: () => void;
41
+
42
+ /**
43
+ * Clears both the undo and redo history, but does not affect the current state.
44
+ */
45
+ clearHistory: () => void;
46
+
47
+ /**
48
+ * Returns true if there is at least one state in the undo history.
49
+ */
50
+ canUndo: () => boolean;
51
+
52
+ /**
53
+ * Returns true if there is at least one state in the redo history.
54
+ */
55
+ canRedo: () => boolean;
56
+
57
+ /**
58
+ * Exports the current undo/redo history as an opaque blob.
59
+ */
60
+ exportHistory: () => HistoryData;
61
+
62
+ /**
63
+ * Restores a previously exported history blob.
64
+ */
65
+ importHistory: (data: HistoryData) => void;
66
+ }
67
+
68
+ // A single frame in history
69
+ interface HistoryFrame<T> {
70
+ state: T;
71
+ timestamp: number;
72
+ }
73
+
74
+ // Internal state - not exposed publicly
75
+ interface HistoryState<T> {
76
+ _history_past: HistoryFrame<T>[];
77
+ _history_future: HistoryFrame<T>[];
78
+ }
79
+
80
+ /**
81
+ * Public, opaque change signal: a monotonic counter the middleware bumps on every
82
+ * history transition (checkpoint, undo, redo, clear, import). Subscribe to it to
83
+ * detect domain mutations and undo/redo in O(1). It never ticks on selection or
84
+ * drag — those mutate state without a checkpoint. Mirrors editorStore's counter
85
+ * of the same name for project-scoped (channel/memory/model) mutations.
86
+ */
87
+ export interface MutationCount {
88
+ readonly mutationCount: number;
89
+ }
90
+
91
+ // Configuration for history middleware
92
+ interface HistoryConfig<T> {
93
+ limit?: number;
94
+ partialize?: (state: T) => Partial<T>;
95
+ equality?: (before: Partial<T>, after: Partial<T>) => boolean;
96
+ }
97
+
98
+ export const history =
99
+ <T>(config: HistoryConfig<T> = {}) =>
100
+ <Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = []>(
101
+ storeInitializer: StateCreator<T, Mps, Mcs>,
102
+ ): StateCreator<T & HistoryState<T> & History & MutationCount, Mps, Mcs> => {
103
+ const {
104
+ limit = 50,
105
+ partialize = (state) => state,
106
+ equality = (before, after) => JSON.stringify(before) === JSON.stringify(after),
107
+ } = config;
108
+
109
+ return (set, get, store) => {
110
+ type FullState = T & HistoryState<T> & History & MutationCount;
111
+
112
+ const initialState = storeInitializer(
113
+ set as Parameters<StateCreator<T, Mps, Mcs>>[0],
114
+ get as Parameters<StateCreator<T, Mps, Mcs>>[1],
115
+ store as Parameters<StateCreator<T, Mps, Mcs>>[2],
116
+ );
117
+
118
+ return {
119
+ ...initialState,
120
+ _history_past: [],
121
+ _history_future: [],
122
+ mutationCount: 0,
123
+
124
+ takeCheckpoint: () => {
125
+ const currentState = partialize(get() as T);
126
+ set((state: FullState) => ({
127
+ ...state,
128
+ _history_past: [...state._history_past, { state: currentState as T, timestamp: Date.now() }].slice(-limit),
129
+ _history_future: [],
130
+ mutationCount: state.mutationCount + 1,
131
+ }));
132
+ },
133
+
134
+ withCheckpoint: <R>(operation: () => R): R => {
135
+ const beforeState = partialize(get() as T);
136
+ // Execute operation and capture result to return later to caller
137
+ const result = operation();
138
+ const afterState = partialize(get() as T);
139
+ // Compare using provided equality function
140
+ const areEqual = equality(beforeState, afterState);
141
+ if (!areEqual) {
142
+ set((state: FullState) => ({
143
+ ...state,
144
+ _history_past: [...state._history_past, { state: beforeState as T, timestamp: Date.now() }].slice(-limit),
145
+ _history_future: [],
146
+ mutationCount: state.mutationCount + 1,
147
+ }));
148
+ }
149
+ return result;
150
+ },
151
+
152
+ undo: () => {
153
+ const state = get();
154
+ if (state._history_past.length === 0) return;
155
+ const past = [...state._history_past];
156
+ const previousFrame = past.pop()!;
157
+ // Save current state to future before restoring
158
+ const currentState = partialize(state as T);
159
+ set({
160
+ ...state,
161
+ ...previousFrame.state,
162
+ _history_past: past,
163
+ _history_future: [...state._history_future, { state: currentState as T, timestamp: Date.now() }],
164
+ mutationCount: state.mutationCount + 1,
165
+ } as FullState);
166
+ },
167
+
168
+ redo: () => {
169
+ const state = get();
170
+ if (state._history_future.length === 0) return;
171
+ const future = [...state._history_future];
172
+ const nextFrame = future.pop()!;
173
+ // Save current state to past before restoring
174
+ const currentState = partialize(state as T);
175
+ set({
176
+ ...state,
177
+ ...nextFrame.state,
178
+ _history_past: [...state._history_past, { state: currentState as T, timestamp: Date.now() }].slice(-limit),
179
+ _history_future: future,
180
+ mutationCount: state.mutationCount + 1,
181
+ } as FullState);
182
+ },
183
+
184
+ clearHistory: () => {
185
+ set((state: FullState) => ({
186
+ ...state,
187
+ _history_past: [],
188
+ _history_future: [],
189
+ mutationCount: state.mutationCount + 1,
190
+ }));
191
+ },
192
+
193
+ canUndo: () => (get() as FullState)._history_past.length > 0,
194
+ canRedo: () => (get() as FullState)._history_future.length > 0,
195
+
196
+ exportHistory: () => ({
197
+ past: [...(get() as FullState)._history_past],
198
+ future: [...(get() as FullState)._history_future],
199
+ }),
200
+
201
+ importHistory: (data: HistoryData) => {
202
+ set((state: FullState) => ({
203
+ ...state,
204
+ _history_past: [...data.past] as HistoryFrame<T>[],
205
+ _history_future: [...data.future] as HistoryFrame<T>[],
206
+ mutationCount: state.mutationCount + 1,
207
+ }));
208
+ },
209
+ } as FullState;
210
+ };
211
+ };
@@ -1,57 +1,61 @@
1
- import { MemoryRegistry, type MemoryType, type Memory } from "@foresthubai/workflow-core/memory";
2
- import { useEditorStore } from "../stores/editorStore";
3
- import { generateId } from "@foresthubai/workflow-core/id";
4
- import { seedDefaultArguments, uniqueName } from "./resourceHelpers";
5
-
6
- /** Default label prefix per memory type. */
7
- const LABEL_PREFIX: Record<MemoryType, string> = {
8
- MemoryFile: "memory",
9
- VectorDatabase: "vectordb",
10
- };
11
-
12
- /** Create a new memory primitive of the given type in the editor store. Returns the new instance. */
13
- export function addMemory(type: MemoryType): Memory {
14
- const id = generateId();
15
- const existing = Object.values(useEditorStore.getState().memory).map((m) => m.label);
16
- const instance: Memory = {
17
- id,
18
- label: uniqueName(LABEL_PREFIX[type], existing),
19
- type,
20
- arguments: seedDefaultArguments(MemoryRegistry.getByType(type)?.parameters ?? []),
21
- };
22
- useEditorStore.getState().setMemory((mem) => ({ ...mem, [id]: instance }));
23
- return instance;
24
- }
25
-
26
- /**
27
- * Apply a partial patch to a memory primitive. Top-level `label` and the
28
- * `arguments` record are merged separately. The `type` discriminator is fixed
29
- * at creation (the user picks a type when adding), so it is never patched here.
30
- */
31
- export function updateMemory(id: string, patch: { label?: string; arguments?: Record<string, unknown> }): void {
32
- const key = id;
33
- useEditorStore.getState().setMemory((mem) => {
34
- const existing = mem[key];
35
- if (!existing) return mem;
36
- return {
37
- ...mem,
38
- [key]: {
39
- ...existing,
40
- ...(patch.label !== undefined ? { label: patch.label } : {}),
41
- ...(patch.arguments ? { arguments: { ...existing.arguments, ...patch.arguments } } : {}),
42
- },
43
- };
44
- });
45
- }
46
-
47
- export function deleteMemory(id: string): void {
48
- const key = id;
49
- useEditorStore.getState().setMemory((mem) => {
50
- const { [key]: _drop, ...rest } = mem;
51
- return rest;
52
- });
53
- const sel = useEditorStore.getState().selection;
54
- if (sel.kind === "memory" && sel.id === id) {
55
- useEditorStore.getState().clearSelection();
56
- }
57
- }
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (c) 2026 ForestHub. All rights reserved.
3
+ // For commercial licensing, contact root@foresthub.ai
4
+
5
+ import { MemoryRegistry, type MemoryType, type Memory } from "@foresthubai/workflow-core/memory";
6
+ import { useEditorStore } from "../stores/editorStore";
7
+ import { generateId } from "@foresthubai/workflow-core/id";
8
+ import { seedDefaultArguments, uniqueName } from "./resourceHelpers";
9
+
10
+ /** Default label prefix per memory type. */
11
+ const LABEL_PREFIX: Record<MemoryType, string> = {
12
+ MemoryFile: "memory",
13
+ VectorDatabase: "vectordb",
14
+ };
15
+
16
+ /** Create a new memory primitive of the given type in the editor store. Returns the new instance. */
17
+ export function addMemory(type: MemoryType): Memory {
18
+ const id = generateId();
19
+ const existing = Object.values(useEditorStore.getState().memory).map((m) => m.label);
20
+ const instance: Memory = {
21
+ id,
22
+ label: uniqueName(LABEL_PREFIX[type], existing),
23
+ type,
24
+ arguments: seedDefaultArguments(MemoryRegistry.getByType(type)?.parameters ?? []),
25
+ };
26
+ useEditorStore.getState().setMemory((mem) => ({ ...mem, [id]: instance }));
27
+ return instance;
28
+ }
29
+
30
+ /**
31
+ * Apply a partial patch to a memory primitive. Top-level `label` and the
32
+ * `arguments` record are merged separately. The `type` discriminator is fixed
33
+ * at creation (the user picks a type when adding), so it is never patched here.
34
+ */
35
+ export function updateMemory(id: string, patch: { label?: string; arguments?: Record<string, unknown> }): void {
36
+ const key = id;
37
+ useEditorStore.getState().setMemory((mem) => {
38
+ const existing = mem[key];
39
+ if (!existing) return mem;
40
+ return {
41
+ ...mem,
42
+ [key]: {
43
+ ...existing,
44
+ ...(patch.label !== undefined ? { label: patch.label } : {}),
45
+ ...(patch.arguments ? { arguments: { ...existing.arguments, ...patch.arguments } } : {}),
46
+ },
47
+ };
48
+ });
49
+ }
50
+
51
+ export function deleteMemory(id: string): void {
52
+ const key = id;
53
+ useEditorStore.getState().setMemory((mem) => {
54
+ const { [key]: _drop, ...rest } = mem;
55
+ return rest;
56
+ });
57
+ const sel = useEditorStore.getState().selection;
58
+ if (sel.kind === "memory" && sel.id === id) {
59
+ useEditorStore.getState().clearSelection();
60
+ }
61
+ }