@flowdrop/flowdrop 1.4.0 → 1.6.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 (441) hide show
  1. package/README.md +94 -51
  2. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  3. package/dist/adapters/WorkflowAdapter.js +27 -47
  4. package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +2 -2
  5. package/dist/adapters/agentspec/AgentSpecAdapter.js +122 -133
  6. package/dist/adapters/agentspec/agentAdapter.d.ts +2 -2
  7. package/dist/adapters/agentspec/agentAdapter.js +10 -10
  8. package/dist/adapters/agentspec/autoLayout.d.ts +52 -6
  9. package/dist/adapters/agentspec/autoLayout.js +118 -23
  10. package/dist/adapters/agentspec/componentTypeDefaults.d.ts +1 -1
  11. package/dist/adapters/agentspec/componentTypeDefaults.js +120 -120
  12. package/dist/adapters/agentspec/defaultNodeTypes.d.ts +2 -2
  13. package/dist/adapters/agentspec/defaultNodeTypes.js +307 -307
  14. package/dist/adapters/agentspec/index.d.ts +10 -10
  15. package/dist/adapters/agentspec/index.js +6 -6
  16. package/dist/adapters/agentspec/validator.d.ts +2 -2
  17. package/dist/adapters/agentspec/validator.js +20 -22
  18. package/dist/api/enhanced-client.d.ts +3 -3
  19. package/dist/api/enhanced-client.js +72 -73
  20. package/dist/chat/commandClassifier.d.ts +19 -0
  21. package/dist/chat/commandClassifier.js +30 -0
  22. package/dist/chat/index.d.ts +27 -0
  23. package/dist/chat/index.js +32 -0
  24. package/dist/chat/responseParser.d.ts +21 -0
  25. package/dist/chat/responseParser.js +91 -0
  26. package/dist/commands/batch.d.ts +18 -0
  27. package/dist/commands/batch.js +54 -0
  28. package/dist/commands/executor.d.ts +37 -0
  29. package/dist/commands/executor.js +1133 -0
  30. package/dist/commands/index.d.ts +14 -0
  31. package/dist/commands/index.js +17 -0
  32. package/dist/commands/parser.d.ts +16 -0
  33. package/dist/commands/parser.js +295 -0
  34. package/dist/commands/positioner.d.ts +19 -0
  35. package/dist/commands/positioner.js +33 -0
  36. package/dist/commands/storeIntegration.svelte.d.ts +16 -0
  37. package/dist/commands/storeIntegration.svelte.js +67 -0
  38. package/dist/commands/types.d.ts +343 -0
  39. package/dist/commands/types.js +45 -0
  40. package/dist/components/App.svelte +522 -237
  41. package/dist/components/App.svelte.d.ts +11 -8
  42. package/dist/components/CanvasBanner.stories.svelte +10 -16
  43. package/dist/components/CanvasBanner.stories.svelte.d.ts +1 -1
  44. package/dist/components/CanvasBanner.svelte +2 -2
  45. package/dist/components/CanvasBanner.svelte.d.ts +1 -1
  46. package/dist/components/CanvasController.svelte +37 -0
  47. package/dist/components/CanvasController.svelte.d.ts +32 -0
  48. package/dist/components/ConfigForm.svelte +118 -256
  49. package/dist/components/ConfigForm.svelte.d.ts +2 -2
  50. package/dist/components/ConfigMappingRow.svelte +128 -0
  51. package/dist/components/ConfigMappingRow.svelte.d.ts +8 -0
  52. package/dist/components/ConfigModal.svelte +3 -3
  53. package/dist/components/ConfigModal.svelte.d.ts +1 -1
  54. package/dist/components/ConfigPanel.stories.svelte +19 -19
  55. package/dist/components/ConfigPanel.stories.svelte.d.ts +1 -1
  56. package/dist/components/ConfigPanel.svelte +57 -19
  57. package/dist/components/ConfigPanel.svelte.d.ts +3 -1
  58. package/dist/components/ConnectionLine.svelte +4 -4
  59. package/dist/components/EdgeRefresher.svelte +1 -1
  60. package/dist/components/FlowDropEdge.stories.svelte +110 -110
  61. package/dist/components/FlowDropEdge.svelte +11 -19
  62. package/dist/components/FlowDropEdge.svelte.d.ts +1 -1
  63. package/dist/components/FlowDropZone.svelte +6 -9
  64. package/dist/components/FlowDropZone.svelte.d.ts +1 -1
  65. package/dist/components/LoadingSpinner.stories.svelte +13 -13
  66. package/dist/components/LoadingSpinner.stories.svelte.d.ts +1 -1
  67. package/dist/components/LoadingSpinner.svelte +3 -3
  68. package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
  69. package/dist/components/Logo.stories.svelte +4 -4
  70. package/dist/components/Logo.stories.svelte.d.ts +1 -1
  71. package/dist/components/Logo.svelte +3 -9
  72. package/dist/components/LogsSidebar.svelte +46 -53
  73. package/dist/components/LogsSidebar.svelte.d.ts +1 -1
  74. package/dist/components/MarkdownDisplay.stories.svelte +10 -14
  75. package/dist/components/MarkdownDisplay.stories.svelte.d.ts +1 -1
  76. package/dist/components/MarkdownDisplay.svelte +4 -6
  77. package/dist/components/Navbar.stories.svelte +19 -19
  78. package/dist/components/Navbar.stories.svelte.d.ts +1 -1
  79. package/dist/components/Navbar.svelte +28 -49
  80. package/dist/components/Navbar.svelte.d.ts +2 -2
  81. package/dist/components/NodeSidebar.svelte +55 -135
  82. package/dist/components/NodeSidebar.svelte.d.ts +1 -1
  83. package/dist/components/NodeStatusOverlay.stories.svelte +19 -31
  84. package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +1 -1
  85. package/dist/components/NodeStatusOverlay.svelte +40 -55
  86. package/dist/components/NodeStatusOverlay.svelte.d.ts +3 -3
  87. package/dist/components/NodeSwapPicker.svelte +493 -0
  88. package/dist/components/NodeSwapPicker.svelte.d.ts +16 -0
  89. package/dist/components/PipelineStatus.svelte +63 -89
  90. package/dist/components/PipelineStatus.svelte.d.ts +4 -4
  91. package/dist/components/PortCoordinateTracker.svelte +5 -7
  92. package/dist/components/PortCoordinateTracker.svelte.d.ts +1 -1
  93. package/dist/components/PortMappingRow.svelte +205 -0
  94. package/dist/components/PortMappingRow.svelte.d.ts +12 -0
  95. package/dist/components/ReadOnlyDetails.svelte +1 -1
  96. package/dist/components/SchemaForm.stories.svelte +53 -53
  97. package/dist/components/SchemaForm.stories.svelte.d.ts +1 -1
  98. package/dist/components/SchemaForm.svelte +24 -51
  99. package/dist/components/SchemaForm.svelte.d.ts +2 -2
  100. package/dist/components/SettingsModal.svelte +6 -9
  101. package/dist/components/SettingsModal.svelte.d.ts +1 -1
  102. package/dist/components/SettingsPanel.svelte +138 -158
  103. package/dist/components/SettingsPanel.svelte.d.ts +1 -1
  104. package/dist/components/StatusIcon.stories.svelte +16 -29
  105. package/dist/components/StatusIcon.stories.svelte.d.ts +1 -1
  106. package/dist/components/StatusIcon.svelte +19 -19
  107. package/dist/components/StatusIcon.svelte.d.ts +2 -2
  108. package/dist/components/StatusLabel.stories.svelte +8 -8
  109. package/dist/components/StatusLabel.stories.svelte.d.ts +1 -1
  110. package/dist/components/SwapMappingEditor.svelte +529 -0
  111. package/dist/components/SwapMappingEditor.svelte.d.ts +12 -0
  112. package/dist/components/ThemeToggle.stories.svelte +10 -10
  113. package/dist/components/ThemeToggle.stories.svelte.d.ts +1 -1
  114. package/dist/components/ThemeToggle.svelte +22 -33
  115. package/dist/components/ThemeToggle.svelte.d.ts +1 -1
  116. package/dist/components/UniversalNode.svelte +29 -41
  117. package/dist/components/UniversalNode.svelte.d.ts +3 -3
  118. package/dist/components/WorkflowEditor.svelte +210 -170
  119. package/dist/components/WorkflowEditor.svelte.d.ts +12 -4
  120. package/dist/components/chat/AIChatPanel.svelte +797 -0
  121. package/dist/components/chat/AIChatPanel.svelte.d.ts +13 -0
  122. package/dist/components/chat/CommandPreview.svelte +234 -0
  123. package/dist/components/chat/CommandPreview.svelte.d.ts +9 -0
  124. package/dist/components/console/CommandConsole.stories.svelte +111 -0
  125. package/dist/components/console/CommandConsole.stories.svelte.d.ts +27 -0
  126. package/dist/components/console/CommandConsole.svelte +263 -0
  127. package/dist/components/console/CommandConsole.svelte.d.ts +11 -0
  128. package/dist/components/console/ConsoleAutocomplete.svelte +142 -0
  129. package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +21 -0
  130. package/dist/components/console/ConsoleInput.svelte +771 -0
  131. package/dist/components/console/ConsoleInput.svelte.d.ts +16 -0
  132. package/dist/components/console/ConsoleOutput.svelte +116 -0
  133. package/dist/components/console/ConsoleOutput.svelte.d.ts +11 -0
  134. package/dist/components/console/formatters.d.ts +26 -0
  135. package/dist/components/console/formatters.js +116 -0
  136. package/dist/components/form/FormArray.svelte +75 -132
  137. package/dist/components/form/FormArray.svelte.d.ts +1 -1
  138. package/dist/components/form/FormAutocomplete.svelte +65 -108
  139. package/dist/components/form/FormAutocomplete.svelte.d.ts +1 -1
  140. package/dist/components/form/FormCheckboxGroup.stories.svelte +13 -16
  141. package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +1 -1
  142. package/dist/components/form/FormCheckboxGroup.svelte +2 -2
  143. package/dist/components/form/FormCodeEditor.svelte +42 -56
  144. package/dist/components/form/FormField.svelte +79 -90
  145. package/dist/components/form/FormField.svelte.d.ts +2 -2
  146. package/dist/components/form/FormFieldLight.svelte +72 -88
  147. package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
  148. package/dist/components/form/FormFieldWrapper.stories.svelte +14 -14
  149. package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +1 -1
  150. package/dist/components/form/FormFieldWrapper.svelte +2 -9
  151. package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
  152. package/dist/components/form/FormFieldset.svelte +3 -3
  153. package/dist/components/form/FormFieldset.svelte.d.ts +2 -2
  154. package/dist/components/form/FormMarkdownEditor.svelte +123 -156
  155. package/dist/components/form/FormNumberField.stories.svelte +18 -18
  156. package/dist/components/form/FormNumberField.stories.svelte.d.ts +1 -1
  157. package/dist/components/form/FormNumberField.svelte +6 -6
  158. package/dist/components/form/FormRangeField.stories.svelte +13 -13
  159. package/dist/components/form/FormRangeField.stories.svelte.d.ts +1 -1
  160. package/dist/components/form/FormRangeField.svelte +4 -12
  161. package/dist/components/form/FormSelect.stories.svelte +21 -21
  162. package/dist/components/form/FormSelect.stories.svelte.d.ts +1 -1
  163. package/dist/components/form/FormSelect.svelte +5 -5
  164. package/dist/components/form/FormSelect.svelte.d.ts +1 -1
  165. package/dist/components/form/FormTemplateEditor.svelte +126 -175
  166. package/dist/components/form/FormTemplateEditor.svelte.d.ts +1 -1
  167. package/dist/components/form/FormTextField.stories.svelte +17 -23
  168. package/dist/components/form/FormTextField.stories.svelte.d.ts +1 -1
  169. package/dist/components/form/FormTextField.svelte +4 -4
  170. package/dist/components/form/FormTextarea.stories.svelte +18 -21
  171. package/dist/components/form/FormTextarea.stories.svelte.d.ts +1 -1
  172. package/dist/components/form/FormTextarea.svelte +4 -4
  173. package/dist/components/form/FormToggle.stories.svelte +13 -16
  174. package/dist/components/form/FormToggle.stories.svelte.d.ts +1 -1
  175. package/dist/components/form/FormToggle.svelte +3 -3
  176. package/dist/components/form/FormUISchemaRenderer.svelte +12 -19
  177. package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +3 -3
  178. package/dist/components/form/index.d.ts +19 -19
  179. package/dist/components/form/index.js +18 -18
  180. package/dist/components/form/templateAutocomplete.d.ts +2 -2
  181. package/dist/components/form/templateAutocomplete.js +55 -64
  182. package/dist/components/form/types.d.ts +6 -6
  183. package/dist/components/form/types.js +4 -9
  184. package/dist/components/icons/AlertCircleIcon.svelte +1 -6
  185. package/dist/components/icons/CogIcon.svelte +1 -6
  186. package/dist/components/interrupt/ChoicePrompt.stories.svelte +27 -27
  187. package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +1 -1
  188. package/dist/components/interrupt/ChoicePrompt.svelte +17 -41
  189. package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +1 -1
  190. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +17 -17
  191. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +1 -1
  192. package/dist/components/interrupt/ConfirmationPrompt.svelte +10 -16
  193. package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +1 -1
  194. package/dist/components/interrupt/FormPrompt.svelte +10 -15
  195. package/dist/components/interrupt/FormPrompt.svelte.d.ts +1 -1
  196. package/dist/components/interrupt/InterruptBubble.svelte +87 -121
  197. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +2 -2
  198. package/dist/components/interrupt/ReviewPrompt.stories.svelte +37 -37
  199. package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +1 -1
  200. package/dist/components/interrupt/ReviewPrompt.svelte +55 -75
  201. package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +1 -1
  202. package/dist/components/interrupt/TextInputPrompt.stories.svelte +16 -17
  203. package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +1 -1
  204. package/dist/components/interrupt/TextInputPrompt.svelte +13 -18
  205. package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +1 -1
  206. package/dist/components/interrupt/index.d.ts +6 -5
  207. package/dist/components/interrupt/index.js +6 -5
  208. package/dist/components/layouts/MainLayout.svelte +46 -84
  209. package/dist/components/layouts/MainLayout.svelte.d.ts +6 -6
  210. package/dist/components/nodes/GatewayNode.stories.svelte +64 -65
  211. package/dist/components/nodes/GatewayNode.svelte +37 -70
  212. package/dist/components/nodes/GatewayNode.svelte.d.ts +3 -3
  213. package/dist/components/nodes/IdeaNode.stories.svelte +25 -26
  214. package/dist/components/nodes/IdeaNode.svelte +22 -36
  215. package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
  216. package/dist/components/nodes/NotesNode.stories.svelte +37 -38
  217. package/dist/components/nodes/NotesNode.svelte +28 -39
  218. package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
  219. package/dist/components/nodes/SimpleNode.stories.svelte +137 -138
  220. package/dist/components/nodes/SimpleNode.svelte +44 -74
  221. package/dist/components/nodes/SimpleNode.svelte.d.ts +1 -1
  222. package/dist/components/nodes/SquareNode.stories.svelte +75 -75
  223. package/dist/components/nodes/SquareNode.svelte +42 -68
  224. package/dist/components/nodes/SquareNode.svelte.d.ts +1 -1
  225. package/dist/components/nodes/TerminalNode.stories.svelte +10 -10
  226. package/dist/components/nodes/TerminalNode.svelte +74 -112
  227. package/dist/components/nodes/TerminalNode.svelte.d.ts +1 -1
  228. package/dist/components/nodes/ToolNode.stories.svelte +115 -116
  229. package/dist/components/nodes/ToolNode.svelte +31 -64
  230. package/dist/components/nodes/ToolNode.svelte.d.ts +1 -1
  231. package/dist/components/nodes/WorkflowNode.stories.svelte +84 -89
  232. package/dist/components/nodes/WorkflowNode.svelte +50 -103
  233. package/dist/components/nodes/WorkflowNode.svelte.d.ts +3 -3
  234. package/dist/components/playground/ChatPanel.svelte +47 -103
  235. package/dist/components/playground/ExecutionLogs.svelte +45 -68
  236. package/dist/components/playground/InputCollector.svelte +32 -51
  237. package/dist/components/playground/MessageBubble.stories.svelte +25 -25
  238. package/dist/components/playground/MessageBubble.stories.svelte.d.ts +1 -1
  239. package/dist/components/playground/MessageBubble.svelte +54 -70
  240. package/dist/components/playground/MessageBubble.svelte.d.ts +1 -1
  241. package/dist/components/playground/Playground.svelte +60 -91
  242. package/dist/components/playground/Playground.svelte.d.ts +3 -3
  243. package/dist/components/playground/PlaygroundModal.svelte +8 -12
  244. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
  245. package/dist/components/playground/SessionManager.svelte +34 -40
  246. package/dist/components/playground/SessionManager.svelte.d.ts +1 -1
  247. package/dist/config/agentSpecEndpoints.d.ts +1 -1
  248. package/dist/config/agentSpecEndpoints.js +20 -20
  249. package/dist/config/constants.js +2 -2
  250. package/dist/config/defaultCategories.d.ts +1 -1
  251. package/dist/config/defaultCategories.js +86 -86
  252. package/dist/config/defaultPortConfig.d.ts +1 -1
  253. package/dist/config/defaultPortConfig.js +144 -144
  254. package/dist/config/endpoints.d.ts +12 -4
  255. package/dist/config/endpoints.js +70 -65
  256. package/dist/config/runtimeConfig.d.ts +2 -2
  257. package/dist/config/runtimeConfig.js +8 -8
  258. package/dist/core/index.d.ts +68 -63
  259. package/dist/core/index.js +44 -35
  260. package/dist/display/index.d.ts +2 -2
  261. package/dist/display/index.js +2 -2
  262. package/dist/editor/index.d.ts +64 -62
  263. package/dist/editor/index.js +57 -55
  264. package/dist/form/code.d.ts +5 -5
  265. package/dist/form/code.js +14 -14
  266. package/dist/form/fieldRegistry.d.ts +3 -3
  267. package/dist/form/fieldRegistry.js +9 -11
  268. package/dist/form/full.d.ts +8 -8
  269. package/dist/form/full.js +9 -9
  270. package/dist/form/index.d.ts +18 -18
  271. package/dist/form/index.js +16 -16
  272. package/dist/form/markdown.d.ts +4 -4
  273. package/dist/form/markdown.js +8 -8
  274. package/dist/helpers/proximityConnect.d.ts +3 -3
  275. package/dist/helpers/proximityConnect.js +40 -35
  276. package/dist/helpers/workflowEditorHelper.d.ts +8 -58
  277. package/dist/helpers/workflowEditorHelper.js +73 -292
  278. package/dist/index.d.ts +6 -6
  279. package/dist/index.js +6 -6
  280. package/dist/mocks/app-environment.js +2 -2
  281. package/dist/mocks/app-forms.js +1 -1
  282. package/dist/mocks/app-navigation.js +2 -2
  283. package/dist/mocks/app-stores.js +3 -3
  284. package/dist/playground/index.d.ts +19 -19
  285. package/dist/playground/index.js +16 -16
  286. package/dist/playground/mount.d.ts +3 -3
  287. package/dist/playground/mount.js +24 -24
  288. package/dist/registry/builtinFormats.js +13 -13
  289. package/dist/registry/builtinNodes.d.ts +2 -2
  290. package/dist/registry/builtinNodes.js +77 -77
  291. package/dist/registry/index.d.ts +4 -4
  292. package/dist/registry/index.js +4 -4
  293. package/dist/registry/nodeComponentRegistry.d.ts +8 -8
  294. package/dist/registry/nodeComponentRegistry.js +9 -11
  295. package/dist/registry/plugin.d.ts +2 -2
  296. package/dist/registry/plugin.js +11 -11
  297. package/dist/registry/workflowFormatRegistry.d.ts +3 -3
  298. package/dist/registry/workflowFormatRegistry.js +2 -2
  299. package/dist/schema/index.d.ts +1 -1
  300. package/dist/schema/index.js +2 -2
  301. package/dist/schemas/v1/workflow.schema.json +107 -22
  302. package/dist/services/agentSpecExecutionService.d.ts +3 -3
  303. package/dist/services/agentSpecExecutionService.js +55 -56
  304. package/dist/services/api.d.ts +2 -2
  305. package/dist/services/api.js +37 -37
  306. package/dist/services/apiVariableService.d.ts +1 -1
  307. package/dist/services/apiVariableService.js +34 -41
  308. package/dist/services/autoSaveService.js +8 -8
  309. package/dist/services/categoriesApi.d.ts +2 -2
  310. package/dist/services/categoriesApi.js +8 -8
  311. package/dist/services/chatService.d.ts +65 -0
  312. package/dist/services/chatService.js +131 -0
  313. package/dist/services/draftStorage.d.ts +1 -1
  314. package/dist/services/draftStorage.js +11 -11
  315. package/dist/services/dynamicSchemaService.d.ts +1 -1
  316. package/dist/services/dynamicSchemaService.js +39 -41
  317. package/dist/services/globalSave.d.ts +2 -2
  318. package/dist/services/globalSave.js +38 -41
  319. package/dist/services/historyService.d.ts +7 -5
  320. package/dist/services/historyService.js +29 -14
  321. package/dist/services/interruptService.d.ts +1 -1
  322. package/dist/services/interruptService.js +29 -35
  323. package/dist/services/nodeExecutionService.d.ts +1 -1
  324. package/dist/services/nodeExecutionService.js +44 -45
  325. package/dist/services/playgroundService.d.ts +1 -1
  326. package/dist/services/playgroundService.js +29 -29
  327. package/dist/services/portConfigApi.d.ts +2 -2
  328. package/dist/services/portConfigApi.js +8 -8
  329. package/dist/services/settingsService.d.ts +2 -2
  330. package/dist/services/settingsService.js +19 -25
  331. package/dist/services/toastService.d.ts +4 -4
  332. package/dist/services/toastService.js +33 -33
  333. package/dist/services/variableService.d.ts +1 -1
  334. package/dist/services/variableService.js +36 -36
  335. package/dist/services/workflowStorage.d.ts +2 -2
  336. package/dist/services/workflowStorage.js +13 -13
  337. package/dist/settings/index.d.ts +7 -7
  338. package/dist/settings/index.js +6 -6
  339. package/dist/skins/default.d.ts +1 -1
  340. package/dist/skins/default.js +1 -1
  341. package/dist/skins/index.d.ts +3 -3
  342. package/dist/skins/index.js +7 -7
  343. package/dist/skins/slate.d.ts +1 -1
  344. package/dist/skins/slate.js +69 -69
  345. package/dist/stores/categoriesStore.svelte.d.ts +1 -1
  346. package/dist/stores/categoriesStore.svelte.js +5 -5
  347. package/dist/stores/editorStateMachine.svelte.d.ts +2 -2
  348. package/dist/stores/editorStateMachine.svelte.js +34 -34
  349. package/dist/stores/historyStore.svelte.d.ts +4 -4
  350. package/dist/stores/historyStore.svelte.js +4 -4
  351. package/dist/stores/interruptStore.svelte.d.ts +3 -3
  352. package/dist/stores/interruptStore.svelte.js +27 -22
  353. package/dist/stores/playgroundStore.svelte.d.ts +3 -3
  354. package/dist/stores/playgroundStore.svelte.js +29 -23
  355. package/dist/stores/portCoordinateStore.svelte.d.ts +6 -2
  356. package/dist/stores/portCoordinateStore.svelte.js +30 -39
  357. package/dist/stores/settingsStore.svelte.d.ts +2 -2
  358. package/dist/stores/settingsStore.svelte.js +57 -62
  359. package/dist/stores/workflowStore.svelte.d.ts +34 -5
  360. package/dist/stores/workflowStore.svelte.js +127 -108
  361. package/dist/stories/CanvasDecorator.svelte +7 -10
  362. package/dist/stories/CanvasDecorator.svelte.d.ts +2 -2
  363. package/dist/stories/EdgeDecorator.svelte +28 -31
  364. package/dist/stories/EdgeDecorator.svelte.d.ts +1 -1
  365. package/dist/stories/NodeDecorator.svelte +14 -20
  366. package/dist/stories/NodeDecorator.svelte.d.ts +1 -1
  367. package/dist/stories/utils.d.ts +2 -2
  368. package/dist/stories/utils.js +89 -93
  369. package/dist/styles/base.css +16 -50
  370. package/dist/styles/tokens.css +10 -28
  371. package/dist/svelte-app.d.ts +10 -10
  372. package/dist/svelte-app.js +39 -39
  373. package/dist/themes/default.d.ts +1 -1
  374. package/dist/themes/default.js +4 -4
  375. package/dist/themes/index.d.ts +3 -3
  376. package/dist/themes/index.js +11 -11
  377. package/dist/themes/minimal.d.ts +1 -1
  378. package/dist/themes/minimal.js +5 -5
  379. package/dist/types/agentspec.d.ts +18 -18
  380. package/dist/types/agentspec.js +2 -2
  381. package/dist/types/auth.d.ts +1 -1
  382. package/dist/types/auth.js +6 -6
  383. package/dist/types/chat.d.ts +63 -0
  384. package/dist/types/chat.js +9 -0
  385. package/dist/types/config.d.ts +6 -6
  386. package/dist/types/events.d.ts +28 -2
  387. package/dist/types/events.js +2 -1
  388. package/dist/types/index.d.ts +40 -32
  389. package/dist/types/index.js +6 -6
  390. package/dist/types/interrupt.d.ts +6 -6
  391. package/dist/types/interrupt.js +21 -21
  392. package/dist/types/interruptState.d.ts +12 -12
  393. package/dist/types/interruptState.js +66 -66
  394. package/dist/types/playground.d.ts +7 -7
  395. package/dist/types/playground.js +14 -14
  396. package/dist/types/settings.d.ts +12 -4
  397. package/dist/types/settings.js +21 -23
  398. package/dist/types/skin.d.ts +1 -1
  399. package/dist/types/theme.d.ts +2 -2
  400. package/dist/types/uischema.d.ts +4 -4
  401. package/dist/types/uischema.js +3 -3
  402. package/dist/utils/colors.d.ts +1 -1
  403. package/dist/utils/colors.js +95 -97
  404. package/dist/utils/config.d.ts +2 -2
  405. package/dist/utils/config.js +48 -48
  406. package/dist/utils/connections.d.ts +2 -2
  407. package/dist/utils/connections.js +15 -15
  408. package/dist/utils/edgeStyling.d.ts +42 -0
  409. package/dist/utils/edgeStyling.js +173 -0
  410. package/dist/utils/errors.js +3 -3
  411. package/dist/utils/fetchWithAuth.d.ts +1 -1
  412. package/dist/utils/fetchWithAuth.js +2 -2
  413. package/dist/utils/handleIds.d.ts +2 -2
  414. package/dist/utils/handleIds.js +8 -8
  415. package/dist/utils/handlePositioning.d.ts +1 -1
  416. package/dist/utils/handlePositioning.js +2 -2
  417. package/dist/utils/icons.d.ts +1 -1
  418. package/dist/utils/icons.js +74 -74
  419. package/dist/utils/logger.d.ts +1 -1
  420. package/dist/utils/logger.js +7 -7
  421. package/dist/utils/nodeIds.d.ts +31 -0
  422. package/dist/utils/nodeIds.js +42 -0
  423. package/dist/utils/nodeStatus.d.ts +1 -1
  424. package/dist/utils/nodeStatus.js +48 -48
  425. package/dist/utils/nodeSwap.d.ts +221 -0
  426. package/dist/utils/nodeSwap.js +680 -0
  427. package/dist/utils/nodeTypes.d.ts +1 -1
  428. package/dist/utils/nodeTypes.js +20 -21
  429. package/dist/utils/nodeWrapper.d.ts +7 -7
  430. package/dist/utils/nodeWrapper.js +19 -21
  431. package/dist/utils/performanceUtils.d.ts +1 -1
  432. package/dist/utils/performanceUtils.js +1 -2
  433. package/dist/utils/portUtils.d.ts +2 -2
  434. package/dist/utils/portUtils.js +1 -1
  435. package/dist/utils/sanitize.js +1 -1
  436. package/dist/utils/uischema.d.ts +2 -2
  437. package/dist/utils/uischema.js +8 -8
  438. package/dist/utils/validation.js +8 -8
  439. package/package.json +12 -11
  440. package/dist/helpers/nodeLayoutHelper.d.ts +0 -14
  441. package/dist/helpers/nodeLayoutHelper.js +0 -19
@@ -10,9 +10,9 @@
10
10
  *
11
11
  * @module stores/workflowStore
12
12
  */
13
- import type { Workflow, WorkflowNode, WorkflowEdge } from "../types";
14
- import type { WorkflowChangeType } from "../types/events.js";
15
- type WorkflowMetadata = NonNullable<Workflow["metadata"]>;
13
+ import type { Workflow, WorkflowNode, WorkflowEdge } from '../types';
14
+ import type { WorkflowChangeType } from '../types/events.js';
15
+ type WorkflowMetadata = NonNullable<Workflow['metadata']>;
16
16
  /**
17
17
  * Get the current workflow store value reactively
18
18
  *
@@ -22,6 +22,10 @@ export declare function getWorkflowStore(): Workflow | null;
22
22
  /**
23
23
  * Get the current dirty state reactively
24
24
  *
25
+ * Reads both _editVersion and _savedVersion, so Svelte tracks them
26
+ * as reactive dependencies — any component using this will re-render
27
+ * when dirty state changes.
28
+ *
25
29
  * @returns true if there are unsaved changes
26
30
  */
27
31
  export declare function getIsDirty(): boolean;
@@ -121,9 +125,10 @@ export declare function setOnDirtyStateChange(callback: ((isDirty: boolean) => v
121
125
  */
122
126
  export declare function setOnWorkflowChange(callback: ((workflow: Workflow, changeType: WorkflowChangeType) => void) | null): void;
123
127
  /**
124
- * Mark the current workflow state as saved
128
+ * Mark the current workflow state as saved.
125
129
  *
126
- * Clears the dirty state by updating the saved snapshot.
130
+ * Captures the current edit version so isDirty becomes false.
131
+ * Call this after a successful backend save.
127
132
  */
128
133
  export declare function markAsSaved(): void;
129
134
  /**
@@ -132,6 +137,19 @@ export declare function markAsSaved(): void;
132
137
  * @returns true if there are unsaved changes
133
138
  */
134
139
  export declare function isDirty(): boolean;
140
+ /**
141
+ * Get the current edit version.
142
+ *
143
+ * Use this for the save verification protocol:
144
+ * 1. Before save: `const v = getEditVersion()`
145
+ * 2. Include `v` in the save request payload
146
+ * 3. Backend echoes `v` in the response
147
+ * 4. If echoed version matches: `markAsSaved()`
148
+ * 5. If not: the save didn't persist the version you submitted — reset from backend response
149
+ *
150
+ * @returns The current monotonic edit version
151
+ */
152
+ export declare function getEditVersion(): number;
135
153
  /**
136
154
  * Enable or disable history recording
137
155
  *
@@ -246,6 +264,17 @@ export declare const workflowActions: {
246
264
  description?: string;
247
265
  metadata?: Partial<Workflow["metadata"]>;
248
266
  }) => void;
267
+ /**
268
+ * Swap a node — atomically replaces nodes and edges with a descriptive history entry.
269
+ *
270
+ * Unlike batchUpdate, this uses `"node_swap"` as the change type and
271
+ * records a meaningful description for the undo history.
272
+ */
273
+ swapNode: (updates: {
274
+ nodes: WorkflowNode[];
275
+ edges: WorkflowEdge[];
276
+ description?: string;
277
+ }) => void;
249
278
  /**
250
279
  * Push current state to history manually
251
280
  *
@@ -10,14 +10,14 @@
10
10
  *
11
11
  * @module stores/workflowStore
12
12
  */
13
- import { DEFAULT_WORKFLOW_FORMAT } from "../types/index.js";
14
- import { historyService } from "../services/historyService.js";
13
+ import { DEFAULT_WORKFLOW_FORMAT } from '../types/index.js';
14
+ import { historyService } from '../services/historyService.js';
15
15
  /**
16
16
  * Safely build updated workflow metadata, providing defaults for required fields.
17
17
  */
18
18
  function buildMetadata(existing, updates) {
19
19
  return {
20
- version: existing?.version ?? "1.0",
20
+ version: existing?.version ?? '1.0',
21
21
  createdAt: existing?.createdAt ?? new Date().toISOString(),
22
22
  updatedAt: new Date().toISOString(),
23
23
  author: existing?.author,
@@ -25,7 +25,7 @@ function buildMetadata(existing, updates) {
25
25
  versionId: existing?.versionId,
26
26
  updateNumber: existing?.updateNumber,
27
27
  format: existing?.format,
28
- ...updates,
28
+ ...updates
29
29
  };
30
30
  }
31
31
  // =========================================================================
@@ -34,21 +34,23 @@ function buildMetadata(existing, updates) {
34
34
  /** Global workflow state */
35
35
  let workflowState = $state(null);
36
36
  // =========================================================================
37
- // Dirty State Tracking
37
+ // Dirty State Tracking (Version Counter)
38
38
  // =========================================================================
39
39
  /**
40
- * State for tracking if there are unsaved changes
40
+ * Monotonic edit version bumps on every mutation action.
41
41
  *
42
- * This is set to true whenever the workflow changes after initialization.
43
- * It can be reset to false by calling markAsSaved().
42
+ * Used for two purposes:
43
+ * 1. O(1) dirty detection: isDirty = _editVersion !== _savedVersion
44
+ * 2. Save verification protocol: include the version in the save request,
45
+ * backend echoes it back. If the echoed version doesn't match, the save
46
+ * didn't persist the version the client submitted.
44
47
  */
45
- let isDirtyState = $state(false);
48
+ let _editVersion = $state(0);
46
49
  /**
47
- * Snapshot of the workflow when it was last saved
48
- *
49
- * Used to compare current state with saved state.
50
+ * Edit version captured at the last successful save.
51
+ * When _editVersion === _savedVersion, the workflow is clean.
50
52
  */
51
- let savedSnapshot = null;
53
+ let _savedVersion = $state(0);
52
54
  /**
53
55
  * Callback for dirty state changes
54
56
  *
@@ -87,10 +89,14 @@ export function getWorkflowStore() {
87
89
  /**
88
90
  * Get the current dirty state reactively
89
91
  *
92
+ * Reads both _editVersion and _savedVersion, so Svelte tracks them
93
+ * as reactive dependencies — any component using this will re-render
94
+ * when dirty state changes.
95
+ *
90
96
  * @returns true if there are unsaved changes
91
97
  */
92
98
  export function getIsDirty() {
93
- return isDirtyState;
99
+ return _editVersion !== _savedVersion;
94
100
  }
95
101
  /**
96
102
  * Get the workflow ID reactively
@@ -106,7 +112,7 @@ export function getWorkflowId() {
106
112
  * @returns The workflow name or 'Untitled Workflow'
107
113
  */
108
114
  export function getWorkflowName() {
109
- return workflowState?.name ?? "Untitled Workflow";
115
+ return workflowState?.name ?? 'Untitled Workflow';
110
116
  }
111
117
  /**
112
118
  * Get the workflow nodes reactively
@@ -131,11 +137,11 @@ export function getWorkflowEdges() {
131
137
  */
132
138
  export function getWorkflowMetadata() {
133
139
  return (workflowState?.metadata ?? {
134
- version: "1.0.0",
140
+ version: '1.0.0',
135
141
  createdAt: new Date().toISOString(),
136
142
  updatedAt: new Date().toISOString(),
137
143
  versionId: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
138
- updateNumber: 0,
144
+ updateNumber: 0
139
145
  });
140
146
  }
141
147
  /**
@@ -155,7 +161,7 @@ export function getWorkflowChanged() {
155
161
  return {
156
162
  nodes: getWorkflowNodes(),
157
163
  edges: getWorkflowEdges(),
158
- name: getWorkflowName(),
164
+ name: getWorkflowName()
159
165
  };
160
166
  }
161
167
  /**
@@ -171,7 +177,7 @@ export function getWorkflowValidation() {
171
177
  hasEdges: edges.length > 0,
172
178
  nodeCount: nodes.length,
173
179
  edgeCount: edges.length,
174
- isValid: nodes.length > 0 && edges.length >= 0,
180
+ isValid: nodes.length > 0 && edges.length >= 0
175
181
  };
176
182
  }
177
183
  /**
@@ -184,7 +190,7 @@ export function getWorkflowMetadataChanged() {
184
190
  return {
185
191
  createdAt: metadata.createdAt,
186
192
  updatedAt: metadata.updatedAt,
187
- version: metadata.version ?? "1.0.0",
193
+ version: metadata.version ?? '1.0.0'
188
194
  };
189
195
  }
190
196
  /**
@@ -239,53 +245,21 @@ export function setOnWorkflowChange(callback) {
239
245
  // Internal Helpers
240
246
  // =========================================================================
241
247
  /**
242
- * Create a snapshot of the workflow for comparison
243
- *
244
- * @param workflow - The workflow to snapshot
245
- * @returns A JSON string representation for comparison
246
- */
247
- function createSnapshot(workflow) {
248
- if (!workflow)
249
- return null;
250
- // Only include the parts that matter for "dirty" detection
251
- const toSnapshot = {
252
- name: workflow.name,
253
- description: workflow.description,
254
- nodes: workflow.nodes.map((n) => ({
255
- id: n.id,
256
- position: n.position,
257
- data: {
258
- label: n.data.label,
259
- config: n.data.config,
260
- },
261
- })),
262
- edges: workflow.edges.map((e) => ({
263
- id: e.id,
264
- source: e.source,
265
- target: e.target,
266
- sourceHandle: e.sourceHandle,
267
- targetHandle: e.targetHandle,
268
- })),
269
- };
270
- return JSON.stringify(toSnapshot);
271
- }
272
- /**
273
- * Update dirty state based on current workflow
274
- *
275
- * Compares current workflow with saved snapshot.
248
+ * Bump the edit version and notify dirty state change if needed.
249
+ * Called by every mutation action.
276
250
  */
277
- function updateDirtyState() {
278
- const currentSnapshot = createSnapshot(workflowState);
279
- const newIsDirty = currentSnapshot !== savedSnapshot;
280
- if (newIsDirty !== isDirtyState) {
281
- isDirtyState = newIsDirty;
251
+ function bumpVersion() {
252
+ _editVersion++;
253
+ // Dirty state just flipped from clean → dirty
254
+ if (_editVersion - 1 === _savedVersion) {
282
255
  if (onDirtyStateChangeCallback) {
283
- onDirtyStateChangeCallback(newIsDirty);
256
+ onDirtyStateChangeCallback(true);
284
257
  }
285
258
  }
286
259
  }
287
260
  /**
288
- * Mark the workflow change and update dirty state
261
+ * Notify external listeners of a workflow change.
262
+ * Does NOT bump the version — callers that mutate must call bumpVersion() explicitly.
289
263
  *
290
264
  * @param changeType - The type of change that occurred
291
265
  */
@@ -293,17 +267,17 @@ function notifyWorkflowChange(changeType) {
293
267
  if (workflowState && onWorkflowChangeCallback) {
294
268
  onWorkflowChangeCallback(workflowState, changeType);
295
269
  }
296
- updateDirtyState();
297
270
  }
298
271
  /**
299
- * Mark the current workflow state as saved
272
+ * Mark the current workflow state as saved.
300
273
  *
301
- * Clears the dirty state by updating the saved snapshot.
274
+ * Captures the current edit version so isDirty becomes false.
275
+ * Call this after a successful backend save.
302
276
  */
303
277
  export function markAsSaved() {
304
- savedSnapshot = createSnapshot(workflowState);
305
- isDirtyState = false;
306
- if (onDirtyStateChangeCallback) {
278
+ const wasDirty = _editVersion !== _savedVersion;
279
+ _savedVersion = _editVersion;
280
+ if (wasDirty && onDirtyStateChangeCallback) {
307
281
  onDirtyStateChangeCallback(false);
308
282
  }
309
283
  }
@@ -313,7 +287,22 @@ export function markAsSaved() {
313
287
  * @returns true if there are unsaved changes
314
288
  */
315
289
  export function isDirty() {
316
- return isDirtyState;
290
+ return _editVersion !== _savedVersion;
291
+ }
292
+ /**
293
+ * Get the current edit version.
294
+ *
295
+ * Use this for the save verification protocol:
296
+ * 1. Before save: `const v = getEditVersion()`
297
+ * 2. Include `v` in the save request payload
298
+ * 3. Backend echoes `v` in the response
299
+ * 4. If echoed version matches: `markAsSaved()`
300
+ * 5. If not: the save didn't persist the version you submitted — reset from backend response
301
+ *
302
+ * @returns The current monotonic edit version
303
+ */
304
+ export function getEditVersion() {
305
+ return _editVersion;
317
306
  }
318
307
  /**
319
308
  * Enable or disable history recording
@@ -390,7 +379,7 @@ function hasWorkflowDataChanged(currentWorkflow, newNodes, newEdges) {
390
379
  if (currentNode.position.x !== newNode.position.x ||
391
380
  currentNode.position.y !== newNode.position.y)
392
381
  return true;
393
- if (JSON.stringify(currentNode.data) !== JSON.stringify(newNode.data))
382
+ if (currentNode.data !== newNode.data)
394
383
  return true;
395
384
  }
396
385
  // Check if edges have changed
@@ -403,8 +392,7 @@ function hasWorkflowDataChanged(currentWorkflow, newNodes, newEdges) {
403
392
  return true;
404
393
  if (currentEdge.id !== newEdge.id)
405
394
  return true;
406
- if (currentEdge.source !== newEdge.source ||
407
- currentEdge.target !== newEdge.target)
395
+ if (currentEdge.source !== newEdge.source || currentEdge.target !== newEdge.target)
408
396
  return true;
409
397
  }
410
398
  return false;
@@ -426,9 +414,9 @@ export const workflowActions = {
426
414
  */
427
415
  initialize: (workflow) => {
428
416
  workflowState = workflow;
429
- // Set the saved snapshot - workflow is "clean" after initialization
430
- savedSnapshot = createSnapshot(workflow);
431
- isDirtyState = false;
417
+ // Reset version counters workflow is "clean" after initialization
418
+ _editVersion = 0;
419
+ _savedVersion = 0;
432
420
  if (onDirtyStateChangeCallback) {
433
421
  onDirtyStateChangeCallback(false);
434
422
  }
@@ -443,7 +431,8 @@ export const workflowActions = {
443
431
  */
444
432
  updateWorkflow: (workflow) => {
445
433
  workflowState = workflow;
446
- notifyWorkflowChange("metadata");
434
+ bumpVersion();
435
+ notifyWorkflowChange('metadata');
447
436
  },
448
437
  /**
449
438
  * Restore workflow from history (undo/redo)
@@ -453,7 +442,8 @@ export const workflowActions = {
453
442
  restoreFromHistory: (workflow) => {
454
443
  isRestoringFromHistory = true;
455
444
  workflowState = workflow;
456
- notifyWorkflowChange("metadata");
445
+ bumpVersion();
446
+ notifyWorkflowChange('metadata');
457
447
  isRestoringFromHistory = false;
458
448
  },
459
449
  /**
@@ -473,10 +463,11 @@ export const workflowActions = {
473
463
  nodes,
474
464
  metadata: buildMetadata(workflowState.metadata, {
475
465
  versionId,
476
- updateNumber: (workflowState.metadata?.updateNumber ?? 0) + 1,
477
- }),
466
+ updateNumber: (workflowState.metadata?.updateNumber ?? 0) + 1
467
+ })
478
468
  };
479
- notifyWorkflowChange("node_move");
469
+ bumpVersion();
470
+ notifyWorkflowChange('node_move');
480
471
  },
481
472
  /**
482
473
  * Update edges
@@ -495,10 +486,11 @@ export const workflowActions = {
495
486
  edges,
496
487
  metadata: buildMetadata(workflowState.metadata, {
497
488
  versionId,
498
- updateNumber: (workflowState.metadata?.updateNumber ?? 0) + 1,
499
- }),
489
+ updateNumber: (workflowState.metadata?.updateNumber ?? 0) + 1
490
+ })
500
491
  };
501
- notifyWorkflowChange("edge_add");
492
+ bumpVersion();
493
+ notifyWorkflowChange('edge_add');
502
494
  },
503
495
  /**
504
496
  * Update workflow name
@@ -509,23 +501,25 @@ export const workflowActions = {
509
501
  workflowState = {
510
502
  ...workflowState,
511
503
  name,
512
- metadata: buildMetadata(workflowState.metadata),
504
+ metadata: buildMetadata(workflowState.metadata)
513
505
  };
514
- notifyWorkflowChange("name");
506
+ bumpVersion();
507
+ notifyWorkflowChange('name');
515
508
  },
516
509
  /**
517
510
  * Add a node
518
511
  */
519
512
  addNode: (node) => {
520
- pushToHistory("Add node");
513
+ pushToHistory('Add node');
521
514
  if (!workflowState)
522
515
  return;
523
516
  workflowState = {
524
517
  ...workflowState,
525
518
  nodes: [...workflowState.nodes, node],
526
- metadata: buildMetadata(workflowState.metadata),
519
+ metadata: buildMetadata(workflowState.metadata)
527
520
  };
528
- notifyWorkflowChange("node_add");
521
+ bumpVersion();
522
+ notifyWorkflowChange('node_add');
529
523
  },
530
524
  /**
531
525
  * Remove a node
@@ -534,44 +528,47 @@ export const workflowActions = {
534
528
  * A single undo will restore both the node and its edges.
535
529
  */
536
530
  removeNode: (nodeId) => {
537
- pushToHistory("Delete node");
531
+ pushToHistory('Delete node');
538
532
  if (!workflowState)
539
533
  return;
540
534
  workflowState = {
541
535
  ...workflowState,
542
536
  nodes: workflowState.nodes.filter((node) => node.id !== nodeId),
543
537
  edges: workflowState.edges.filter((edge) => edge.source !== nodeId && edge.target !== nodeId),
544
- metadata: buildMetadata(workflowState.metadata),
538
+ metadata: buildMetadata(workflowState.metadata)
545
539
  };
546
- notifyWorkflowChange("node_remove");
540
+ bumpVersion();
541
+ notifyWorkflowChange('node_remove');
547
542
  },
548
543
  /**
549
544
  * Add an edge
550
545
  */
551
546
  addEdge: (edge) => {
552
- pushToHistory("Add connection");
547
+ pushToHistory('Add connection');
553
548
  if (!workflowState)
554
549
  return;
555
550
  workflowState = {
556
551
  ...workflowState,
557
552
  edges: [...workflowState.edges, edge],
558
- metadata: buildMetadata(workflowState.metadata),
553
+ metadata: buildMetadata(workflowState.metadata)
559
554
  };
560
- notifyWorkflowChange("edge_add");
555
+ bumpVersion();
556
+ notifyWorkflowChange('edge_add');
561
557
  },
562
558
  /**
563
559
  * Remove an edge
564
560
  */
565
561
  removeEdge: (edgeId) => {
566
- pushToHistory("Delete connection");
562
+ pushToHistory('Delete connection');
567
563
  if (!workflowState)
568
564
  return;
569
565
  workflowState = {
570
566
  ...workflowState,
571
567
  edges: workflowState.edges.filter((edge) => edge.id !== edgeId),
572
- metadata: buildMetadata(workflowState.metadata),
568
+ metadata: buildMetadata(workflowState.metadata)
573
569
  };
574
- notifyWorkflowChange("edge_remove");
570
+ bumpVersion();
571
+ notifyWorkflowChange('edge_remove');
575
572
  },
576
573
  /**
577
574
  * Update a specific node
@@ -579,15 +576,16 @@ export const workflowActions = {
579
576
  * Used for config changes. Pushes to history for undo support.
580
577
  */
581
578
  updateNode: (nodeId, updates) => {
582
- pushToHistory("Update node config");
579
+ pushToHistory('Update node config');
583
580
  if (!workflowState)
584
581
  return;
585
582
  workflowState = {
586
583
  ...workflowState,
587
584
  nodes: workflowState.nodes.map((node) => node.id === nodeId ? { ...node, ...updates } : node),
588
- metadata: buildMetadata(workflowState.metadata),
585
+ metadata: buildMetadata(workflowState.metadata)
589
586
  };
590
- notifyWorkflowChange("node_config");
587
+ bumpVersion();
588
+ notifyWorkflowChange('node_config');
591
589
  },
592
590
  /**
593
591
  * Clear the workflow
@@ -596,8 +594,8 @@ export const workflowActions = {
596
594
  */
597
595
  clear: () => {
598
596
  workflowState = null;
599
- savedSnapshot = null;
600
- isDirtyState = false;
597
+ _editVersion = 0;
598
+ _savedVersion = 0;
601
599
  historyService.clear();
602
600
  if (onDirtyStateChangeCallback) {
603
601
  onDirtyStateChangeCallback(false);
@@ -611,9 +609,10 @@ export const workflowActions = {
611
609
  return;
612
610
  workflowState = {
613
611
  ...workflowState,
614
- metadata: buildMetadata(workflowState.metadata, metadata),
612
+ metadata: buildMetadata(workflowState.metadata, metadata)
615
613
  };
616
- notifyWorkflowChange("metadata");
614
+ bumpVersion();
615
+ notifyWorkflowChange('metadata');
617
616
  },
618
617
  /**
619
618
  * Batch update nodes and edges
@@ -622,7 +621,7 @@ export const workflowActions = {
622
621
  * Creates a single history entry for the entire batch.
623
622
  */
624
623
  batchUpdate: (updates) => {
625
- pushToHistory("Batch update");
624
+ pushToHistory('Batch update');
626
625
  if (!workflowState)
627
626
  return;
628
627
  workflowState = {
@@ -631,11 +630,31 @@ export const workflowActions = {
631
630
  ...(updates.edges && { edges: updates.edges }),
632
631
  ...(updates.name && { name: updates.name }),
633
632
  ...(updates.description !== undefined && {
634
- description: updates.description,
633
+ description: updates.description
635
634
  }),
636
- metadata: buildMetadata(workflowState.metadata, updates.metadata ?? undefined),
635
+ metadata: buildMetadata(workflowState.metadata, updates.metadata ?? undefined)
636
+ };
637
+ bumpVersion();
638
+ notifyWorkflowChange('metadata');
639
+ },
640
+ /**
641
+ * Swap a node — atomically replaces nodes and edges with a descriptive history entry.
642
+ *
643
+ * Unlike batchUpdate, this uses `"node_swap"` as the change type and
644
+ * records a meaningful description for the undo history.
645
+ */
646
+ swapNode: (updates) => {
647
+ pushToHistory(updates.description ?? 'Swap node');
648
+ if (!workflowState)
649
+ return;
650
+ workflowState = {
651
+ ...workflowState,
652
+ nodes: updates.nodes,
653
+ edges: updates.edges,
654
+ metadata: buildMetadata(workflowState.metadata)
637
655
  };
638
- notifyWorkflowChange("metadata");
656
+ bumpVersion();
657
+ notifyWorkflowChange('node_swap');
639
658
  },
640
659
  /**
641
660
  * Push current state to history manually
@@ -648,5 +667,5 @@ export const workflowActions = {
648
667
  */
649
668
  pushHistory: (description, workflow) => {
650
669
  pushToHistory(description, workflow);
651
- },
670
+ }
652
671
  };
@@ -3,28 +3,25 @@
3
3
  matching how overlay components (e.g. CanvasBanner) appear in the workflow editor.
4
4
  -->
5
5
  <script lang="ts">
6
- import { SvelteFlow, Controls } from "@xyflow/svelte";
7
- import type { ColorMode } from "@xyflow/svelte";
8
- import "@xyflow/svelte/dist/style.css";
9
- import type { Snippet } from "svelte";
6
+ import { SvelteFlow, Controls } from '@xyflow/svelte';
7
+ import type { ColorMode } from '@xyflow/svelte';
8
+ import '@xyflow/svelte/dist/style.css';
9
+ import type { Snippet } from 'svelte';
10
10
 
11
11
  let { children }: { children: Snippet } = $props();
12
12
 
13
13
  // Watch the data-theme attribute set by Storybook's addon-themes
14
14
  let colorMode = $state<ColorMode>(
15
- (document.documentElement.getAttribute("data-theme") as ColorMode) ||
16
- "light",
15
+ (document.documentElement.getAttribute('data-theme') as ColorMode) || 'light'
17
16
  );
18
17
 
19
18
  $effect(() => {
20
19
  const observer = new MutationObserver(() => {
21
- colorMode =
22
- (document.documentElement.getAttribute("data-theme") as ColorMode) ||
23
- "light";
20
+ colorMode = (document.documentElement.getAttribute('data-theme') as ColorMode) || 'light';
24
21
  });
25
22
  observer.observe(document.documentElement, {
26
23
  attributes: true,
27
- attributeFilter: ["data-theme"],
24
+ attributeFilter: ['data-theme']
28
25
  });
29
26
  return () => observer.disconnect();
30
27
  });
@@ -1,5 +1,5 @@
1
- import "@xyflow/svelte/dist/style.css";
2
- import type { Snippet } from "svelte";
1
+ import '@xyflow/svelte/dist/style.css';
2
+ import type { Snippet } from 'svelte';
3
3
  type $$ComponentProps = {
4
4
  children: Snippet;
5
5
  };