@flowdrop/flowdrop 1.5.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 (434) hide show
  1. package/README.md +46 -47
  2. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  3. package/dist/adapters/WorkflowAdapter.js +26 -26
  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 +1 -1
  9. package/dist/adapters/agentspec/autoLayout.js +7 -9
  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.js +6 -6
  21. package/dist/chat/index.d.ts +5 -5
  22. package/dist/chat/index.js +4 -4
  23. package/dist/chat/responseParser.d.ts +6 -6
  24. package/dist/chat/responseParser.js +28 -24
  25. package/dist/commands/batch.d.ts +1 -1
  26. package/dist/commands/batch.js +5 -7
  27. package/dist/commands/executor.d.ts +2 -2
  28. package/dist/commands/executor.js +320 -231
  29. package/dist/commands/index.d.ts +6 -6
  30. package/dist/commands/index.js +5 -5
  31. package/dist/commands/parser.d.ts +1 -1
  32. package/dist/commands/parser.js +91 -74
  33. package/dist/commands/positioner.d.ts +2 -2
  34. package/dist/commands/positioner.js +1 -1
  35. package/dist/commands/storeIntegration.svelte.d.ts +2 -2
  36. package/dist/commands/storeIntegration.svelte.js +5 -5
  37. package/dist/commands/types.d.ts +42 -42
  38. package/dist/commands/types.js +2 -2
  39. package/dist/components/App.svelte +240 -294
  40. package/dist/components/App.svelte.d.ts +9 -9
  41. package/dist/components/CanvasBanner.stories.svelte +10 -16
  42. package/dist/components/CanvasBanner.stories.svelte.d.ts +1 -1
  43. package/dist/components/CanvasBanner.svelte +2 -2
  44. package/dist/components/CanvasBanner.svelte.d.ts +1 -1
  45. package/dist/components/CanvasController.svelte +3 -4
  46. package/dist/components/ConfigForm.svelte +118 -256
  47. package/dist/components/ConfigForm.svelte.d.ts +2 -2
  48. package/dist/components/ConfigMappingRow.svelte +7 -9
  49. package/dist/components/ConfigMappingRow.svelte.d.ts +1 -1
  50. package/dist/components/ConfigModal.svelte +3 -3
  51. package/dist/components/ConfigModal.svelte.d.ts +1 -1
  52. package/dist/components/ConfigPanel.stories.svelte +19 -19
  53. package/dist/components/ConfigPanel.stories.svelte.d.ts +1 -1
  54. package/dist/components/ConfigPanel.svelte +9 -20
  55. package/dist/components/ConfigPanel.svelte.d.ts +1 -1
  56. package/dist/components/ConnectionLine.svelte +4 -4
  57. package/dist/components/EdgeRefresher.svelte +1 -1
  58. package/dist/components/FlowDropEdge.stories.svelte +110 -110
  59. package/dist/components/FlowDropEdge.svelte +9 -9
  60. package/dist/components/FlowDropEdge.svelte.d.ts +1 -1
  61. package/dist/components/FlowDropZone.svelte +6 -9
  62. package/dist/components/FlowDropZone.svelte.d.ts +1 -1
  63. package/dist/components/LoadingSpinner.stories.svelte +13 -13
  64. package/dist/components/LoadingSpinner.stories.svelte.d.ts +1 -1
  65. package/dist/components/LoadingSpinner.svelte +3 -3
  66. package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
  67. package/dist/components/Logo.stories.svelte +4 -4
  68. package/dist/components/Logo.stories.svelte.d.ts +1 -1
  69. package/dist/components/Logo.svelte +3 -9
  70. package/dist/components/LogsSidebar.svelte +41 -48
  71. package/dist/components/LogsSidebar.svelte.d.ts +1 -1
  72. package/dist/components/MarkdownDisplay.stories.svelte +10 -14
  73. package/dist/components/MarkdownDisplay.stories.svelte.d.ts +1 -1
  74. package/dist/components/MarkdownDisplay.svelte +4 -6
  75. package/dist/components/Navbar.stories.svelte +19 -19
  76. package/dist/components/Navbar.stories.svelte.d.ts +1 -1
  77. package/dist/components/Navbar.svelte +28 -49
  78. package/dist/components/Navbar.svelte.d.ts +2 -2
  79. package/dist/components/NodeSidebar.svelte +42 -88
  80. package/dist/components/NodeSidebar.svelte.d.ts +1 -1
  81. package/dist/components/NodeStatusOverlay.stories.svelte +19 -31
  82. package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +1 -1
  83. package/dist/components/NodeStatusOverlay.svelte +40 -55
  84. package/dist/components/NodeStatusOverlay.svelte.d.ts +3 -3
  85. package/dist/components/NodeSwapPicker.svelte +20 -64
  86. package/dist/components/NodeSwapPicker.svelte.d.ts +1 -1
  87. package/dist/components/PipelineStatus.svelte +63 -89
  88. package/dist/components/PipelineStatus.svelte.d.ts +4 -4
  89. package/dist/components/PortCoordinateTracker.svelte +5 -7
  90. package/dist/components/PortCoordinateTracker.svelte.d.ts +1 -1
  91. package/dist/components/PortMappingRow.svelte +20 -24
  92. package/dist/components/PortMappingRow.svelte.d.ts +2 -2
  93. package/dist/components/ReadOnlyDetails.svelte +1 -1
  94. package/dist/components/SchemaForm.stories.svelte +53 -53
  95. package/dist/components/SchemaForm.stories.svelte.d.ts +1 -1
  96. package/dist/components/SchemaForm.svelte +24 -51
  97. package/dist/components/SchemaForm.svelte.d.ts +2 -2
  98. package/dist/components/SettingsModal.svelte +6 -9
  99. package/dist/components/SettingsModal.svelte.d.ts +1 -1
  100. package/dist/components/SettingsPanel.svelte +138 -158
  101. package/dist/components/SettingsPanel.svelte.d.ts +1 -1
  102. package/dist/components/StatusIcon.stories.svelte +16 -29
  103. package/dist/components/StatusIcon.stories.svelte.d.ts +1 -1
  104. package/dist/components/StatusIcon.svelte +19 -19
  105. package/dist/components/StatusIcon.svelte.d.ts +2 -2
  106. package/dist/components/StatusLabel.stories.svelte +8 -8
  107. package/dist/components/StatusLabel.stories.svelte.d.ts +1 -1
  108. package/dist/components/SwapMappingEditor.svelte +35 -56
  109. package/dist/components/SwapMappingEditor.svelte.d.ts +2 -2
  110. package/dist/components/ThemeToggle.stories.svelte +10 -10
  111. package/dist/components/ThemeToggle.stories.svelte.d.ts +1 -1
  112. package/dist/components/ThemeToggle.svelte +22 -33
  113. package/dist/components/ThemeToggle.svelte.d.ts +1 -1
  114. package/dist/components/UniversalNode.svelte +29 -41
  115. package/dist/components/UniversalNode.svelte.d.ts +3 -3
  116. package/dist/components/WorkflowEditor.svelte +113 -168
  117. package/dist/components/WorkflowEditor.svelte.d.ts +4 -4
  118. package/dist/components/chat/AIChatPanel.svelte +272 -133
  119. package/dist/components/chat/AIChatPanel.svelte.d.ts +3 -3
  120. package/dist/components/chat/CommandPreview.svelte +74 -24
  121. package/dist/components/chat/CommandPreview.svelte.d.ts +1 -1
  122. package/dist/components/console/CommandConsole.stories.svelte +71 -53
  123. package/dist/components/console/CommandConsole.stories.svelte.d.ts +1 -1
  124. package/dist/components/console/CommandConsole.svelte +39 -35
  125. package/dist/components/console/CommandConsole.svelte.d.ts +2 -2
  126. package/dist/components/console/ConsoleAutocomplete.svelte +6 -3
  127. package/dist/components/console/ConsoleInput.svelte +148 -89
  128. package/dist/components/console/ConsoleInput.svelte.d.ts +1 -1
  129. package/dist/components/console/ConsoleOutput.svelte +5 -10
  130. package/dist/components/console/ConsoleOutput.svelte.d.ts +1 -1
  131. package/dist/components/console/formatters.d.ts +1 -1
  132. package/dist/components/console/formatters.js +27 -29
  133. package/dist/components/form/FormArray.svelte +75 -132
  134. package/dist/components/form/FormArray.svelte.d.ts +1 -1
  135. package/dist/components/form/FormAutocomplete.svelte +65 -108
  136. package/dist/components/form/FormAutocomplete.svelte.d.ts +1 -1
  137. package/dist/components/form/FormCheckboxGroup.stories.svelte +13 -16
  138. package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +1 -1
  139. package/dist/components/form/FormCheckboxGroup.svelte +2 -2
  140. package/dist/components/form/FormCodeEditor.svelte +42 -56
  141. package/dist/components/form/FormField.svelte +79 -90
  142. package/dist/components/form/FormField.svelte.d.ts +2 -2
  143. package/dist/components/form/FormFieldLight.svelte +72 -88
  144. package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
  145. package/dist/components/form/FormFieldWrapper.stories.svelte +14 -14
  146. package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +1 -1
  147. package/dist/components/form/FormFieldWrapper.svelte +2 -9
  148. package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
  149. package/dist/components/form/FormFieldset.svelte +3 -3
  150. package/dist/components/form/FormFieldset.svelte.d.ts +2 -2
  151. package/dist/components/form/FormMarkdownEditor.svelte +123 -156
  152. package/dist/components/form/FormNumberField.stories.svelte +18 -18
  153. package/dist/components/form/FormNumberField.stories.svelte.d.ts +1 -1
  154. package/dist/components/form/FormNumberField.svelte +6 -6
  155. package/dist/components/form/FormRangeField.stories.svelte +13 -13
  156. package/dist/components/form/FormRangeField.stories.svelte.d.ts +1 -1
  157. package/dist/components/form/FormRangeField.svelte +4 -12
  158. package/dist/components/form/FormSelect.stories.svelte +21 -21
  159. package/dist/components/form/FormSelect.stories.svelte.d.ts +1 -1
  160. package/dist/components/form/FormSelect.svelte +5 -5
  161. package/dist/components/form/FormSelect.svelte.d.ts +1 -1
  162. package/dist/components/form/FormTemplateEditor.svelte +126 -175
  163. package/dist/components/form/FormTemplateEditor.svelte.d.ts +1 -1
  164. package/dist/components/form/FormTextField.stories.svelte +17 -23
  165. package/dist/components/form/FormTextField.stories.svelte.d.ts +1 -1
  166. package/dist/components/form/FormTextField.svelte +4 -4
  167. package/dist/components/form/FormTextarea.stories.svelte +18 -21
  168. package/dist/components/form/FormTextarea.stories.svelte.d.ts +1 -1
  169. package/dist/components/form/FormTextarea.svelte +4 -4
  170. package/dist/components/form/FormToggle.stories.svelte +13 -16
  171. package/dist/components/form/FormToggle.stories.svelte.d.ts +1 -1
  172. package/dist/components/form/FormToggle.svelte +3 -3
  173. package/dist/components/form/FormUISchemaRenderer.svelte +12 -19
  174. package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +3 -3
  175. package/dist/components/form/index.d.ts +19 -19
  176. package/dist/components/form/index.js +18 -18
  177. package/dist/components/form/templateAutocomplete.d.ts +2 -2
  178. package/dist/components/form/templateAutocomplete.js +55 -64
  179. package/dist/components/form/types.d.ts +6 -6
  180. package/dist/components/form/types.js +4 -9
  181. package/dist/components/icons/AlertCircleIcon.svelte +1 -6
  182. package/dist/components/icons/CogIcon.svelte +1 -6
  183. package/dist/components/interrupt/ChoicePrompt.stories.svelte +27 -27
  184. package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +1 -1
  185. package/dist/components/interrupt/ChoicePrompt.svelte +17 -41
  186. package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +1 -1
  187. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +17 -17
  188. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +1 -1
  189. package/dist/components/interrupt/ConfirmationPrompt.svelte +10 -16
  190. package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +1 -1
  191. package/dist/components/interrupt/FormPrompt.svelte +10 -15
  192. package/dist/components/interrupt/FormPrompt.svelte.d.ts +1 -1
  193. package/dist/components/interrupt/InterruptBubble.svelte +87 -121
  194. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +2 -2
  195. package/dist/components/interrupt/ReviewPrompt.stories.svelte +37 -37
  196. package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +1 -1
  197. package/dist/components/interrupt/ReviewPrompt.svelte +55 -75
  198. package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +1 -1
  199. package/dist/components/interrupt/TextInputPrompt.stories.svelte +16 -17
  200. package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +1 -1
  201. package/dist/components/interrupt/TextInputPrompt.svelte +13 -18
  202. package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +1 -1
  203. package/dist/components/interrupt/index.d.ts +6 -6
  204. package/dist/components/interrupt/index.js +6 -6
  205. package/dist/components/layouts/MainLayout.svelte +46 -84
  206. package/dist/components/layouts/MainLayout.svelte.d.ts +6 -6
  207. package/dist/components/nodes/GatewayNode.stories.svelte +64 -65
  208. package/dist/components/nodes/GatewayNode.svelte +37 -70
  209. package/dist/components/nodes/GatewayNode.svelte.d.ts +3 -3
  210. package/dist/components/nodes/IdeaNode.stories.svelte +25 -26
  211. package/dist/components/nodes/IdeaNode.svelte +22 -36
  212. package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
  213. package/dist/components/nodes/NotesNode.stories.svelte +37 -38
  214. package/dist/components/nodes/NotesNode.svelte +28 -39
  215. package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
  216. package/dist/components/nodes/SimpleNode.stories.svelte +137 -138
  217. package/dist/components/nodes/SimpleNode.svelte +44 -74
  218. package/dist/components/nodes/SimpleNode.svelte.d.ts +1 -1
  219. package/dist/components/nodes/SquareNode.stories.svelte +75 -75
  220. package/dist/components/nodes/SquareNode.svelte +42 -68
  221. package/dist/components/nodes/SquareNode.svelte.d.ts +1 -1
  222. package/dist/components/nodes/TerminalNode.stories.svelte +10 -10
  223. package/dist/components/nodes/TerminalNode.svelte +74 -112
  224. package/dist/components/nodes/TerminalNode.svelte.d.ts +1 -1
  225. package/dist/components/nodes/ToolNode.stories.svelte +115 -116
  226. package/dist/components/nodes/ToolNode.svelte +31 -64
  227. package/dist/components/nodes/ToolNode.svelte.d.ts +1 -1
  228. package/dist/components/nodes/WorkflowNode.stories.svelte +84 -89
  229. package/dist/components/nodes/WorkflowNode.svelte +50 -103
  230. package/dist/components/nodes/WorkflowNode.svelte.d.ts +3 -3
  231. package/dist/components/playground/ChatPanel.svelte +47 -103
  232. package/dist/components/playground/ExecutionLogs.svelte +45 -68
  233. package/dist/components/playground/InputCollector.svelte +32 -51
  234. package/dist/components/playground/MessageBubble.stories.svelte +25 -25
  235. package/dist/components/playground/MessageBubble.stories.svelte.d.ts +1 -1
  236. package/dist/components/playground/MessageBubble.svelte +54 -70
  237. package/dist/components/playground/MessageBubble.svelte.d.ts +1 -1
  238. package/dist/components/playground/Playground.svelte +60 -91
  239. package/dist/components/playground/Playground.svelte.d.ts +3 -3
  240. package/dist/components/playground/PlaygroundModal.svelte +8 -12
  241. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
  242. package/dist/components/playground/SessionManager.svelte +34 -40
  243. package/dist/components/playground/SessionManager.svelte.d.ts +1 -1
  244. package/dist/config/agentSpecEndpoints.d.ts +1 -1
  245. package/dist/config/agentSpecEndpoints.js +20 -20
  246. package/dist/config/constants.js +2 -2
  247. package/dist/config/defaultCategories.d.ts +1 -1
  248. package/dist/config/defaultCategories.js +86 -86
  249. package/dist/config/defaultPortConfig.d.ts +1 -1
  250. package/dist/config/defaultPortConfig.js +144 -144
  251. package/dist/config/endpoints.d.ts +4 -4
  252. package/dist/config/endpoints.js +68 -68
  253. package/dist/config/runtimeConfig.d.ts +2 -2
  254. package/dist/config/runtimeConfig.js +8 -8
  255. package/dist/core/index.d.ts +68 -68
  256. package/dist/core/index.js +38 -38
  257. package/dist/display/index.d.ts +2 -2
  258. package/dist/display/index.js +2 -2
  259. package/dist/editor/index.d.ts +64 -64
  260. package/dist/editor/index.js +54 -54
  261. package/dist/form/code.d.ts +5 -5
  262. package/dist/form/code.js +14 -14
  263. package/dist/form/fieldRegistry.d.ts +3 -3
  264. package/dist/form/fieldRegistry.js +9 -11
  265. package/dist/form/full.d.ts +8 -8
  266. package/dist/form/full.js +9 -9
  267. package/dist/form/index.d.ts +18 -18
  268. package/dist/form/index.js +16 -16
  269. package/dist/form/markdown.d.ts +4 -4
  270. package/dist/form/markdown.js +8 -8
  271. package/dist/helpers/proximityConnect.d.ts +3 -3
  272. package/dist/helpers/proximityConnect.js +32 -34
  273. package/dist/helpers/workflowEditorHelper.d.ts +6 -6
  274. package/dist/helpers/workflowEditorHelper.js +64 -68
  275. package/dist/index.d.ts +6 -6
  276. package/dist/index.js +6 -6
  277. package/dist/mocks/app-environment.js +2 -2
  278. package/dist/mocks/app-forms.js +1 -1
  279. package/dist/mocks/app-navigation.js +2 -2
  280. package/dist/mocks/app-stores.js +3 -3
  281. package/dist/playground/index.d.ts +19 -19
  282. package/dist/playground/index.js +16 -16
  283. package/dist/playground/mount.d.ts +3 -3
  284. package/dist/playground/mount.js +24 -24
  285. package/dist/registry/builtinFormats.js +13 -13
  286. package/dist/registry/builtinNodes.d.ts +2 -2
  287. package/dist/registry/builtinNodes.js +77 -77
  288. package/dist/registry/index.d.ts +4 -4
  289. package/dist/registry/index.js +4 -4
  290. package/dist/registry/nodeComponentRegistry.d.ts +8 -8
  291. package/dist/registry/nodeComponentRegistry.js +9 -11
  292. package/dist/registry/plugin.d.ts +2 -2
  293. package/dist/registry/plugin.js +11 -11
  294. package/dist/registry/workflowFormatRegistry.d.ts +3 -3
  295. package/dist/registry/workflowFormatRegistry.js +2 -2
  296. package/dist/schema/index.d.ts +1 -1
  297. package/dist/schema/index.js +2 -2
  298. package/dist/services/agentSpecExecutionService.d.ts +3 -3
  299. package/dist/services/agentSpecExecutionService.js +55 -56
  300. package/dist/services/api.d.ts +2 -2
  301. package/dist/services/api.js +37 -37
  302. package/dist/services/apiVariableService.d.ts +1 -1
  303. package/dist/services/apiVariableService.js +34 -41
  304. package/dist/services/autoSaveService.js +8 -8
  305. package/dist/services/categoriesApi.d.ts +2 -2
  306. package/dist/services/categoriesApi.js +8 -8
  307. package/dist/services/chatService.d.ts +1 -1
  308. package/dist/services/chatService.js +18 -18
  309. package/dist/services/draftStorage.d.ts +1 -1
  310. package/dist/services/draftStorage.js +11 -11
  311. package/dist/services/dynamicSchemaService.d.ts +1 -1
  312. package/dist/services/dynamicSchemaService.js +39 -41
  313. package/dist/services/globalSave.d.ts +2 -2
  314. package/dist/services/globalSave.js +38 -41
  315. package/dist/services/historyService.d.ts +1 -1
  316. package/dist/services/historyService.js +10 -10
  317. package/dist/services/interruptService.d.ts +1 -1
  318. package/dist/services/interruptService.js +29 -35
  319. package/dist/services/nodeExecutionService.d.ts +1 -1
  320. package/dist/services/nodeExecutionService.js +44 -45
  321. package/dist/services/playgroundService.d.ts +1 -1
  322. package/dist/services/playgroundService.js +29 -29
  323. package/dist/services/portConfigApi.d.ts +2 -2
  324. package/dist/services/portConfigApi.js +8 -8
  325. package/dist/services/settingsService.d.ts +2 -2
  326. package/dist/services/settingsService.js +19 -25
  327. package/dist/services/toastService.d.ts +4 -4
  328. package/dist/services/toastService.js +33 -33
  329. package/dist/services/variableService.d.ts +1 -1
  330. package/dist/services/variableService.js +36 -36
  331. package/dist/services/workflowStorage.d.ts +2 -2
  332. package/dist/services/workflowStorage.js +13 -13
  333. package/dist/settings/index.d.ts +7 -7
  334. package/dist/settings/index.js +6 -6
  335. package/dist/skins/default.d.ts +1 -1
  336. package/dist/skins/default.js +1 -1
  337. package/dist/skins/index.d.ts +3 -3
  338. package/dist/skins/index.js +7 -7
  339. package/dist/skins/slate.d.ts +1 -1
  340. package/dist/skins/slate.js +69 -69
  341. package/dist/stores/categoriesStore.svelte.d.ts +1 -1
  342. package/dist/stores/categoriesStore.svelte.js +5 -5
  343. package/dist/stores/editorStateMachine.svelte.d.ts +2 -2
  344. package/dist/stores/editorStateMachine.svelte.js +34 -34
  345. package/dist/stores/historyStore.svelte.d.ts +4 -4
  346. package/dist/stores/historyStore.svelte.js +4 -4
  347. package/dist/stores/interruptStore.svelte.d.ts +3 -3
  348. package/dist/stores/interruptStore.svelte.js +21 -21
  349. package/dist/stores/playgroundStore.svelte.d.ts +2 -2
  350. package/dist/stores/playgroundStore.svelte.js +18 -21
  351. package/dist/stores/portCoordinateStore.svelte.d.ts +2 -2
  352. package/dist/stores/portCoordinateStore.svelte.js +10 -13
  353. package/dist/stores/settingsStore.svelte.d.ts +2 -2
  354. package/dist/stores/settingsStore.svelte.js +57 -62
  355. package/dist/stores/workflowStore.svelte.d.ts +3 -3
  356. package/dist/stores/workflowStore.svelte.js +46 -47
  357. package/dist/stories/CanvasDecorator.svelte +7 -10
  358. package/dist/stories/CanvasDecorator.svelte.d.ts +2 -2
  359. package/dist/stories/EdgeDecorator.svelte +28 -31
  360. package/dist/stories/EdgeDecorator.svelte.d.ts +1 -1
  361. package/dist/stories/NodeDecorator.svelte +14 -20
  362. package/dist/stories/NodeDecorator.svelte.d.ts +1 -1
  363. package/dist/stories/utils.d.ts +2 -2
  364. package/dist/stories/utils.js +89 -93
  365. package/dist/styles/base.css +16 -50
  366. package/dist/styles/tokens.css +10 -28
  367. package/dist/svelte-app.d.ts +10 -10
  368. package/dist/svelte-app.js +39 -39
  369. package/dist/themes/default.d.ts +1 -1
  370. package/dist/themes/default.js +4 -4
  371. package/dist/themes/index.d.ts +3 -3
  372. package/dist/themes/index.js +11 -11
  373. package/dist/themes/minimal.d.ts +1 -1
  374. package/dist/themes/minimal.js +5 -5
  375. package/dist/types/agentspec.d.ts +18 -18
  376. package/dist/types/agentspec.js +2 -2
  377. package/dist/types/auth.d.ts +1 -1
  378. package/dist/types/auth.js +6 -6
  379. package/dist/types/chat.d.ts +2 -2
  380. package/dist/types/config.d.ts +6 -6
  381. package/dist/types/events.d.ts +3 -3
  382. package/dist/types/events.js +2 -2
  383. package/dist/types/index.d.ts +32 -32
  384. package/dist/types/index.js +6 -6
  385. package/dist/types/interrupt.d.ts +6 -6
  386. package/dist/types/interrupt.js +21 -21
  387. package/dist/types/interruptState.d.ts +12 -12
  388. package/dist/types/interruptState.js +66 -66
  389. package/dist/types/playground.d.ts +7 -7
  390. package/dist/types/playground.js +14 -14
  391. package/dist/types/settings.d.ts +7 -5
  392. package/dist/types/settings.js +19 -24
  393. package/dist/types/skin.d.ts +1 -1
  394. package/dist/types/theme.d.ts +2 -2
  395. package/dist/types/uischema.d.ts +4 -4
  396. package/dist/types/uischema.js +3 -3
  397. package/dist/utils/colors.d.ts +1 -1
  398. package/dist/utils/colors.js +95 -97
  399. package/dist/utils/config.d.ts +2 -2
  400. package/dist/utils/config.js +48 -48
  401. package/dist/utils/connections.d.ts +2 -2
  402. package/dist/utils/connections.js +15 -15
  403. package/dist/utils/edgeStyling.d.ts +2 -2
  404. package/dist/utils/edgeStyling.js +36 -39
  405. package/dist/utils/errors.js +3 -3
  406. package/dist/utils/fetchWithAuth.d.ts +1 -1
  407. package/dist/utils/fetchWithAuth.js +2 -2
  408. package/dist/utils/handleIds.d.ts +2 -2
  409. package/dist/utils/handleIds.js +8 -8
  410. package/dist/utils/handlePositioning.d.ts +1 -1
  411. package/dist/utils/handlePositioning.js +2 -2
  412. package/dist/utils/icons.d.ts +1 -1
  413. package/dist/utils/icons.js +74 -74
  414. package/dist/utils/logger.d.ts +1 -1
  415. package/dist/utils/logger.js +7 -7
  416. package/dist/utils/nodeIds.d.ts +1 -1
  417. package/dist/utils/nodeIds.js +1 -1
  418. package/dist/utils/nodeStatus.d.ts +1 -1
  419. package/dist/utils/nodeStatus.js +48 -48
  420. package/dist/utils/nodeSwap.d.ts +9 -9
  421. package/dist/utils/nodeSwap.js +52 -58
  422. package/dist/utils/nodeTypes.d.ts +1 -1
  423. package/dist/utils/nodeTypes.js +20 -21
  424. package/dist/utils/nodeWrapper.d.ts +7 -7
  425. package/dist/utils/nodeWrapper.js +19 -21
  426. package/dist/utils/performanceUtils.d.ts +1 -1
  427. package/dist/utils/performanceUtils.js +1 -2
  428. package/dist/utils/portUtils.d.ts +2 -2
  429. package/dist/utils/portUtils.js +1 -1
  430. package/dist/utils/sanitize.js +1 -1
  431. package/dist/utils/uischema.d.ts +2 -2
  432. package/dist/utils/uischema.js +8 -8
  433. package/dist/utils/validation.js +8 -8
  434. package/package.json +7 -11
@@ -6,13 +6,13 @@
6
6
  *
7
7
  * @module commands/executor
8
8
  */
9
- import { generateNodeId } from "../utils/nodeIds.js";
10
- import { extractConfigDefaults } from "../utils/nodeIds.js";
11
- import { computeAutoPosition } from "./positioner.js";
12
- import { buildHandleId, extractPortId } from "../utils/handleIds.js";
13
- import { applyConnectionStyling } from "../utils/edgeStyling.js";
14
- import { computeSwapPreview, executeSwap } from "../utils/nodeSwap.js";
15
- import { computeAutoLayout, computeBeautifyLayout } from "../adapters/agentspec/autoLayout.js";
9
+ import { generateNodeId } from '../utils/nodeIds.js';
10
+ import { extractConfigDefaults } from '../utils/nodeIds.js';
11
+ import { computeAutoPosition } from './positioner.js';
12
+ import { buildHandleId, extractPortId } from '../utils/handleIds.js';
13
+ import { applyConnectionStyling } from '../utils/edgeStyling.js';
14
+ import { computeSwapPreview, executeSwap } from '../utils/nodeSwap.js';
15
+ import { computeAutoLayout, computeBeautifyLayout } from '../adapters/agentspec/autoLayout.js';
16
16
  // ============================================================================
17
17
  // Internal Helpers
18
18
  // ============================================================================
@@ -25,12 +25,12 @@ export function toShortId(internalId) {
25
25
  // Node IDs are <namespace>.<typeId>.<number> or <typeId>.<number>
26
26
  // The namespace is the first segment if there are 3+ dot-separated parts
27
27
  // and the last segment is a number
28
- const parts = internalId.split(".");
28
+ const parts = internalId.split('.');
29
29
  if (parts.length >= 3) {
30
30
  const lastPart = parts[parts.length - 1];
31
31
  if (/^\d+$/.test(lastPart)) {
32
32
  // Strip the first segment (namespace)
33
- return parts.slice(1).join(".");
33
+ return parts.slice(1).join('.');
34
34
  }
35
35
  }
36
36
  return internalId;
@@ -41,7 +41,7 @@ export function toShortId(internalId) {
41
41
  * "llm_node" → "llm_node" (no namespace, unchanged)
42
42
  */
43
43
  export function toShortTypeId(typeId) {
44
- const dotIndex = typeId.indexOf(".");
44
+ const dotIndex = typeId.indexOf('.');
45
45
  if (dotIndex !== -1) {
46
46
  return typeId.substring(dotIndex + 1);
47
47
  }
@@ -65,14 +65,14 @@ export function resolveNode(shortId, nodes) {
65
65
  function executeAddNode(command, context) {
66
66
  const workflow = context.getWorkflow();
67
67
  if (!workflow) {
68
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
68
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
69
69
  }
70
70
  const metadata = context.typeMap.get(command.nodeTypeId);
71
71
  if (!metadata) {
72
72
  return {
73
73
  ok: false,
74
74
  error: `Unknown node type: ${command.nodeTypeId}`,
75
- code: "NODE_TYPE_NOT_FOUND",
75
+ code: 'NODE_TYPE_NOT_FOUND'
76
76
  };
77
77
  }
78
78
  const position = command.position ?? computeAutoPosition(workflow.nodes);
@@ -80,15 +80,15 @@ function executeAddNode(command, context) {
80
80
  const config = extractConfigDefaults(metadata.configSchema);
81
81
  const node = {
82
82
  id: nodeId,
83
- type: "universalNode",
83
+ type: 'universalNode',
84
84
  position,
85
85
  deletable: true,
86
86
  data: {
87
87
  label: metadata.name,
88
88
  config,
89
89
  metadata,
90
- nodeId,
91
- },
90
+ nodeId
91
+ }
92
92
  };
93
93
  context.dispatch.addNode(node);
94
94
  const shortId = toShortId(nodeId);
@@ -96,52 +96,52 @@ function executeAddNode(command, context) {
96
96
  nodeId: shortId,
97
97
  type: command.nodeTypeId,
98
98
  label: metadata.name,
99
- position,
99
+ position
100
100
  };
101
101
  return {
102
102
  ok: true,
103
103
  message: `Added ${metadata.name} as ${shortId}`,
104
- data: resultData,
104
+ data: resultData
105
105
  };
106
106
  }
107
107
  function executeDeleteNode(command, context) {
108
108
  const workflow = context.getWorkflow();
109
109
  if (!workflow) {
110
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
110
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
111
111
  }
112
112
  const node = resolveNode(command.nodeId, workflow.nodes);
113
113
  if (!node) {
114
114
  return {
115
115
  ok: false,
116
116
  error: `Node not found: ${command.nodeId}`,
117
- code: "NODE_NOT_FOUND",
117
+ code: 'NODE_NOT_FOUND'
118
118
  };
119
119
  }
120
120
  context.dispatch.removeNode(node.id);
121
121
  return {
122
122
  ok: true,
123
- message: `Deleted node ${toShortId(node.id)}`,
123
+ message: `Deleted node ${toShortId(node.id)}`
124
124
  };
125
125
  }
126
126
  function executeRenameNode(command, context) {
127
127
  const workflow = context.getWorkflow();
128
128
  if (!workflow) {
129
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
129
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
130
130
  }
131
131
  const node = resolveNode(command.nodeId, workflow.nodes);
132
132
  if (!node) {
133
133
  return {
134
134
  ok: false,
135
135
  error: `Node not found: ${command.nodeId}`,
136
- code: "NODE_NOT_FOUND",
136
+ code: 'NODE_NOT_FOUND'
137
137
  };
138
138
  }
139
139
  context.dispatch.updateNode(node.id, {
140
- data: { ...node.data, label: command.label },
140
+ data: { ...node.data, label: command.label }
141
141
  });
142
142
  return {
143
143
  ok: true,
144
- message: `Renamed ${toShortId(node.id)} to "${command.label}"`,
144
+ message: `Renamed ${toShortId(node.id)} to "${command.label}"`
145
145
  };
146
146
  }
147
147
  /**
@@ -163,7 +163,7 @@ function parseConfigValue(raw) {
163
163
  return raw.slice(1, -1);
164
164
  }
165
165
  // Try JSON (arrays, objects, null)
166
- if (raw.startsWith("[") || raw.startsWith("{") || raw === "null") {
166
+ if (raw.startsWith('[') || raw.startsWith('{') || raw === 'null') {
167
167
  try {
168
168
  return JSON.parse(raw);
169
169
  }
@@ -172,13 +172,13 @@ function parseConfigValue(raw) {
172
172
  }
173
173
  }
174
174
  // Number
175
- if (raw !== "" && !isNaN(Number(raw))) {
175
+ if (raw !== '' && !isNaN(Number(raw))) {
176
176
  return Number(raw);
177
177
  }
178
178
  // Boolean
179
- if (raw === "true")
179
+ if (raw === 'true')
180
180
  return true;
181
- if (raw === "false")
181
+ if (raw === 'false')
182
182
  return false;
183
183
  // Raw string
184
184
  return raw;
@@ -195,25 +195,25 @@ function validateConfigValue(key, value, property) {
195
195
  if (property.enum && property.enum.length > 0) {
196
196
  if (!property.enum.includes(value)) {
197
197
  warnings.push({
198
- type: "enum",
199
- message: `Value ${JSON.stringify(value)} is not in allowed values: ${property.enum.map((v) => JSON.stringify(v)).join(", ")}`,
200
- allowedValues: property.enum,
198
+ type: 'enum',
199
+ message: `Value ${JSON.stringify(value)} is not in allowed values: ${property.enum.map((v) => JSON.stringify(v)).join(', ')}`,
200
+ allowedValues: property.enum
201
201
  });
202
202
  }
203
203
  }
204
204
  // Type validation
205
205
  if (property.type) {
206
- const actualType = Array.isArray(value) ? "array" : typeof value;
207
- const expectedType = property.type === "integer" ? "number" : property.type;
206
+ const actualType = Array.isArray(value) ? 'array' : typeof value;
207
+ const expectedType = property.type === 'integer' ? 'number' : property.type;
208
208
  // Only warn if there's a genuine mismatch (null/object handled specially)
209
209
  if (value !== null &&
210
210
  actualType !== expectedType &&
211
- !(expectedType === "object" && actualType === "object")) {
211
+ !(expectedType === 'object' && actualType === 'object')) {
212
212
  warnings.push({
213
- type: "type_mismatch",
213
+ type: 'type_mismatch',
214
214
  message: `Expected type '${property.type}' but got '${actualType}'`,
215
215
  expectedType: property.type,
216
- actualType,
216
+ actualType
217
217
  });
218
218
  }
219
219
  }
@@ -222,14 +222,14 @@ function validateConfigValue(key, value, property) {
222
222
  function executeSetConfig(command, context) {
223
223
  const workflow = context.getWorkflow();
224
224
  if (!workflow) {
225
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
225
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
226
226
  }
227
227
  const node = resolveNode(command.nodeId, workflow.nodes);
228
228
  if (!node) {
229
229
  return {
230
230
  ok: false,
231
231
  error: `Node not found: ${command.nodeId}`,
232
- code: "NODE_NOT_FOUND",
232
+ code: 'NODE_NOT_FOUND'
233
233
  };
234
234
  }
235
235
  const parsedValue = parseConfigValue(command.value);
@@ -240,43 +240,43 @@ function executeSetConfig(command, context) {
240
240
  const warnings = validateConfigValue(command.key, parsedValue, property);
241
241
  // In strict mode, validation warnings become errors
242
242
  if (command.strict && warnings && warnings.length > 0) {
243
- const messages = warnings.map((w) => w.message).join("; ");
243
+ const messages = warnings.map((w) => w.message).join('; ');
244
244
  return {
245
245
  ok: false,
246
246
  error: `Config validation failed for ${toShortId(node.id)}:${command.key}: ${messages}`,
247
- code: "CONFIG_VALIDATION_ERROR",
247
+ code: 'CONFIG_VALIDATION_ERROR'
248
248
  };
249
249
  }
250
250
  const updatedConfig = { ...node.data.config, [command.key]: parsedValue };
251
251
  context.dispatch.updateNode(node.id, {
252
- data: { ...node.data, config: updatedConfig },
252
+ data: { ...node.data, config: updatedConfig }
253
253
  });
254
254
  const resultData = {
255
255
  nodeId: toShortId(node.id),
256
256
  key: command.key,
257
257
  value: parsedValue,
258
- ...(warnings && warnings.length > 0 ? { warnings } : {}),
258
+ ...(warnings && warnings.length > 0 ? { warnings } : {})
259
259
  };
260
260
  const warningMsg = warnings && warnings.length > 0
261
- ? ` (warning: ${warnings.map((w) => w.message).join("; ")})`
262
- : "";
261
+ ? ` (warning: ${warnings.map((w) => w.message).join('; ')})`
262
+ : '';
263
263
  return {
264
264
  ok: true,
265
265
  message: `Set ${toShortId(node.id)}:${command.key} = ${JSON.stringify(parsedValue)}${warningMsg}`,
266
- data: resultData,
266
+ data: resultData
267
267
  };
268
268
  }
269
269
  function executeGetConfig(command, context) {
270
270
  const workflow = context.getWorkflow();
271
271
  if (!workflow) {
272
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
272
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
273
273
  }
274
274
  const node = resolveNode(command.nodeId, workflow.nodes);
275
275
  if (!node) {
276
276
  return {
277
277
  ok: false,
278
278
  error: `Node not found: ${command.nodeId}`,
279
- code: "NODE_NOT_FOUND",
279
+ code: 'NODE_NOT_FOUND'
280
280
  };
281
281
  }
282
282
  const config = node.data.config;
@@ -284,31 +284,31 @@ function executeGetConfig(command, context) {
284
284
  return {
285
285
  ok: false,
286
286
  error: `Config key not found: ${command.key} on ${toShortId(node.id)}`,
287
- code: "CONFIG_KEY_NOT_FOUND",
287
+ code: 'CONFIG_KEY_NOT_FOUND'
288
288
  };
289
289
  }
290
290
  const resultData = {
291
291
  nodeId: toShortId(node.id),
292
292
  key: command.key,
293
- value: config[command.key],
293
+ value: config[command.key]
294
294
  };
295
295
  return {
296
296
  ok: true,
297
297
  message: `${toShortId(node.id)}:${command.key} = ${JSON.stringify(config[command.key])}`,
298
- data: resultData,
298
+ data: resultData
299
299
  };
300
300
  }
301
301
  function executeInfo(command, context) {
302
302
  const workflow = context.getWorkflow();
303
303
  if (!workflow) {
304
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
304
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
305
305
  }
306
306
  const node = resolveNode(command.nodeId, workflow.nodes);
307
307
  if (!node) {
308
308
  return {
309
309
  ok: false,
310
310
  error: `Node not found: ${command.nodeId}`,
311
- code: "NODE_NOT_FOUND",
311
+ code: 'NODE_NOT_FOUND'
312
312
  };
313
313
  }
314
314
  const metadata = node.data.metadata;
@@ -316,19 +316,19 @@ function executeInfo(command, context) {
316
316
  const inputs = (metadata?.inputs ?? []).map((p) => ({
317
317
  portId: p.id,
318
318
  name: p.name,
319
- dataType: p.dataType,
319
+ dataType: p.dataType
320
320
  }));
321
321
  const staticOutputs = (metadata?.outputs ?? []).map((p) => ({
322
322
  portId: p.id,
323
323
  name: p.name,
324
- dataType: p.dataType,
324
+ dataType: p.dataType
325
325
  }));
326
326
  // Gateway nodes expose dynamic branch ports from config.branches
327
- const branchOutputs = metadata?.type === "gateway"
327
+ const branchOutputs = metadata?.type === 'gateway'
328
328
  ? (node.data.config?.branches ?? []).map((b) => ({
329
329
  portId: b.name,
330
330
  name: b.name,
331
- dataType: "trigger",
331
+ dataType: 'trigger'
332
332
  }))
333
333
  : [];
334
334
  const outputs = [...staticOutputs, ...branchOutputs];
@@ -338,36 +338,36 @@ function executeInfo(command, context) {
338
338
  if (edge.source === node.id) {
339
339
  connectedEdges.push({
340
340
  edgeId: edge.id,
341
- direction: "outgoing",
341
+ direction: 'outgoing',
342
342
  remoteNodeId: toShortId(edge.target),
343
- remotePort: extractPortId(edge.targetHandle) ?? "",
344
- localPort: extractPortId(edge.sourceHandle) ?? "",
343
+ remotePort: extractPortId(edge.targetHandle) ?? '',
344
+ localPort: extractPortId(edge.sourceHandle) ?? ''
345
345
  });
346
346
  }
347
347
  else if (edge.target === node.id) {
348
348
  connectedEdges.push({
349
349
  edgeId: edge.id,
350
- direction: "incoming",
350
+ direction: 'incoming',
351
351
  remoteNodeId: toShortId(edge.source),
352
- remotePort: extractPortId(edge.sourceHandle) ?? "",
353
- localPort: extractPortId(edge.targetHandle) ?? "",
352
+ remotePort: extractPortId(edge.sourceHandle) ?? '',
353
+ localPort: extractPortId(edge.targetHandle) ?? ''
354
354
  });
355
355
  }
356
356
  }
357
357
  const resultData = {
358
358
  nodeId: shortId,
359
- label: node.data.label ?? metadata?.name ?? "",
360
- type: metadata?.id ? toShortTypeId(metadata.id) : "",
359
+ label: node.data.label ?? metadata?.name ?? '',
360
+ type: metadata?.id ? toShortTypeId(metadata.id) : '',
361
361
  position: node.position,
362
362
  config: node.data.config ?? {},
363
363
  inputs,
364
364
  outputs,
365
- connectedEdges,
365
+ connectedEdges
366
366
  };
367
367
  return {
368
368
  ok: true,
369
369
  message: `Info for ${shortId}`,
370
- data: resultData,
370
+ data: resultData
371
371
  };
372
372
  }
373
373
  // ============================================================================
@@ -383,29 +383,32 @@ function findPort(node, portId, preferDirection) {
383
383
  return null;
384
384
  const outputPort = metadata.outputs?.find((p) => p.id === portId);
385
385
  const inputPort = metadata.inputs?.find((p) => p.id === portId);
386
- if (preferDirection === "output") {
386
+ if (preferDirection === 'output') {
387
387
  if (outputPort)
388
- return { port: outputPort, direction: "output" };
388
+ return { port: outputPort, direction: 'output' };
389
389
  if (inputPort)
390
- return { port: inputPort, direction: "input" };
390
+ return { port: inputPort, direction: 'input' };
391
391
  }
392
- else if (preferDirection === "input") {
392
+ else if (preferDirection === 'input') {
393
393
  if (inputPort)
394
- return { port: inputPort, direction: "input" };
394
+ return { port: inputPort, direction: 'input' };
395
395
  if (outputPort)
396
- return { port: outputPort, direction: "output" };
396
+ return { port: outputPort, direction: 'output' };
397
397
  }
398
398
  else {
399
399
  if (outputPort)
400
- return { port: outputPort, direction: "output" };
400
+ return { port: outputPort, direction: 'output' };
401
401
  if (inputPort)
402
- return { port: inputPort, direction: "input" };
402
+ return { port: inputPort, direction: 'input' };
403
403
  }
404
404
  // Gateway nodes have dynamic branch ports stored in config.branches, not metadata.outputs
405
- if (metadata.type === "gateway") {
405
+ if (metadata.type === 'gateway') {
406
406
  const branches = node.data.config?.branches;
407
407
  if (branches?.some((b) => b.name === portId)) {
408
- return { port: { id: portId, name: portId, dataType: "trigger" }, direction: "output" };
408
+ return {
409
+ port: { id: portId, name: portId, dataType: 'trigger' },
410
+ direction: 'output'
411
+ };
409
412
  }
410
413
  }
411
414
  return null;
@@ -413,7 +416,7 @@ function findPort(node, portId, preferDirection) {
413
416
  function executeConnect(command, context) {
414
417
  const workflow = context.getWorkflow();
415
418
  if (!workflow) {
416
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
419
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
417
420
  }
418
421
  // Resolve both nodes
419
422
  const sourceNode = resolveNode(command.sourceNodeId, workflow.nodes);
@@ -421,7 +424,7 @@ function executeConnect(command, context) {
421
424
  return {
422
425
  ok: false,
423
426
  error: `Node not found: ${command.sourceNodeId}`,
424
- code: "NODE_NOT_FOUND",
427
+ code: 'NODE_NOT_FOUND'
425
428
  };
426
429
  }
427
430
  const targetNode = resolveNode(command.targetNodeId, workflow.nodes);
@@ -429,56 +432,56 @@ function executeConnect(command, context) {
429
432
  return {
430
433
  ok: false,
431
434
  error: `Node not found: ${command.targetNodeId}`,
432
- code: "NODE_NOT_FOUND",
435
+ code: 'NODE_NOT_FOUND'
433
436
  };
434
437
  }
435
438
  // Look up ports in metadata to determine direction.
436
439
  // Since connections always flow output → input, prefer the output port on the
437
440
  // source node and the input port on the target node when the same port name
438
441
  // exists in both directions on a node.
439
- const sourcePortInfo = findPort(sourceNode, command.sourcePort, "output");
442
+ const sourcePortInfo = findPort(sourceNode, command.sourcePort, 'output');
440
443
  if (!sourcePortInfo) {
441
444
  return {
442
445
  ok: false,
443
446
  error: `Port '${command.sourcePort}' not found on node ${toShortId(sourceNode.id)}`,
444
- code: "PORT_NOT_FOUND",
447
+ code: 'PORT_NOT_FOUND'
445
448
  };
446
449
  }
447
- const targetPortInfo = findPort(targetNode, command.targetPort, "input");
450
+ const targetPortInfo = findPort(targetNode, command.targetPort, 'input');
448
451
  if (!targetPortInfo) {
449
452
  return {
450
453
  ok: false,
451
454
  error: `Port '${command.targetPort}' not found on node ${toShortId(targetNode.id)}`,
452
- code: "PORT_NOT_FOUND",
455
+ code: 'PORT_NOT_FOUND'
453
456
  };
454
457
  }
455
458
  // Validate directions: source port must be output, target port must be input
456
- if (sourcePortInfo.direction !== "output" || targetPortInfo.direction !== "input") {
459
+ if (sourcePortInfo.direction !== 'output' || targetPortInfo.direction !== 'input') {
457
460
  // Check if they're reversed
458
- if (sourcePortInfo.direction === "input" && targetPortInfo.direction === "output") {
461
+ if (sourcePortInfo.direction === 'input' && targetPortInfo.direction === 'output') {
459
462
  return {
460
463
  ok: false,
461
464
  error: `Connection direction reversed: '${command.sourcePort}' is an input on ${toShortId(sourceNode.id)} and '${command.targetPort}' is an output on ${toShortId(targetNode.id)}. Swap source and target.`,
462
- code: "INVALID_CONNECTION",
465
+ code: 'INVALID_CONNECTION'
463
466
  };
464
467
  }
465
468
  // One of them is the wrong direction
466
- if (sourcePortInfo.direction !== "output") {
469
+ if (sourcePortInfo.direction !== 'output') {
467
470
  return {
468
471
  ok: false,
469
472
  error: `Port '${command.sourcePort}' on ${toShortId(sourceNode.id)} is an input, not an output (per node metadata)`,
470
- code: "INVALID_CONNECTION",
473
+ code: 'INVALID_CONNECTION'
471
474
  };
472
475
  }
473
476
  return {
474
477
  ok: false,
475
478
  error: `Port '${command.targetPort}' on ${toShortId(targetNode.id)} is an output, not an input (per node metadata)`,
476
- code: "INVALID_CONNECTION",
479
+ code: 'INVALID_CONNECTION'
477
480
  };
478
481
  }
479
482
  // Build handle IDs
480
- const sourceHandle = buildHandleId(sourceNode.id, "output", command.sourcePort);
481
- const targetHandle = buildHandleId(targetNode.id, "input", command.targetPort);
483
+ const sourceHandle = buildHandleId(sourceNode.id, 'output', command.sourcePort);
484
+ const targetHandle = buildHandleId(targetNode.id, 'input', command.targetPort);
482
485
  // Generate edge ID
483
486
  const edgeId = `${sourceNode.id}-${sourceHandle}-${targetNode.id}-${targetHandle}`;
484
487
  // Build edge
@@ -487,7 +490,7 @@ function executeConnect(command, context) {
487
490
  source: sourceNode.id,
488
491
  target: targetNode.id,
489
492
  sourceHandle,
490
- targetHandle,
493
+ targetHandle
491
494
  };
492
495
  // Apply styling
493
496
  applyConnectionStyling(edge, sourceNode, targetNode);
@@ -495,13 +498,13 @@ function executeConnect(command, context) {
495
498
  context.dispatch.addEdge(edge);
496
499
  return {
497
500
  ok: true,
498
- message: `Connected ${toShortId(sourceNode.id)}:${command.sourcePort} → ${toShortId(targetNode.id)}:${command.targetPort}`,
501
+ message: `Connected ${toShortId(sourceNode.id)}:${command.sourcePort} → ${toShortId(targetNode.id)}:${command.targetPort}`
499
502
  };
500
503
  }
501
504
  function executeDisconnectPorts(command, context) {
502
505
  const workflow = context.getWorkflow();
503
506
  if (!workflow) {
504
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
507
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
505
508
  }
506
509
  // Resolve both nodes
507
510
  const sourceNode = resolveNode(command.sourceNodeId, workflow.nodes);
@@ -509,7 +512,7 @@ function executeDisconnectPorts(command, context) {
509
512
  return {
510
513
  ok: false,
511
514
  error: `Node not found: ${command.sourceNodeId}`,
512
- code: "NODE_NOT_FOUND",
515
+ code: 'NODE_NOT_FOUND'
513
516
  };
514
517
  }
515
518
  const targetNode = resolveNode(command.targetNodeId, workflow.nodes);
@@ -517,7 +520,7 @@ function executeDisconnectPorts(command, context) {
517
520
  return {
518
521
  ok: false,
519
522
  error: `Node not found: ${command.targetNodeId}`,
520
- code: "NODE_NOT_FOUND",
523
+ code: 'NODE_NOT_FOUND'
521
524
  };
522
525
  }
523
526
  // Find the matching edge by checking source/target node IDs and port IDs
@@ -532,26 +535,26 @@ function executeDisconnectPorts(command, context) {
532
535
  return {
533
536
  ok: false,
534
537
  error: `No edge found from ${toShortId(sourceNode.id)}:${command.sourcePort} to ${toShortId(targetNode.id)}:${command.targetPort}`,
535
- code: "EDGE_NOT_FOUND",
538
+ code: 'EDGE_NOT_FOUND'
536
539
  };
537
540
  }
538
541
  context.dispatch.removeEdge(edge.id);
539
542
  return {
540
543
  ok: true,
541
- message: `Disconnected ${toShortId(sourceNode.id)}:${command.sourcePort} from ${toShortId(targetNode.id)}:${command.targetPort}`,
544
+ message: `Disconnected ${toShortId(sourceNode.id)}:${command.sourcePort} from ${toShortId(targetNode.id)}:${command.targetPort}`
542
545
  };
543
546
  }
544
547
  function executeDisconnectNode(command, context) {
545
548
  const workflow = context.getWorkflow();
546
549
  if (!workflow) {
547
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
550
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
548
551
  }
549
552
  const node = resolveNode(command.nodeId, workflow.nodes);
550
553
  if (!node) {
551
554
  return {
552
555
  ok: false,
553
556
  error: `Node not found: ${command.nodeId}`,
554
- code: "NODE_NOT_FOUND",
557
+ code: 'NODE_NOT_FOUND'
555
558
  };
556
559
  }
557
560
  // Find all edges connected to this node
@@ -561,7 +564,7 @@ function executeDisconnectNode(command, context) {
561
564
  }
562
565
  return {
563
566
  ok: true,
564
- message: `Disconnected ${connectedEdges.length} edge(s) from ${toShortId(node.id)}`,
567
+ message: `Disconnected ${connectedEdges.length} edge(s) from ${toShortId(node.id)}`
565
568
  };
566
569
  }
567
570
  // ============================================================================
@@ -570,84 +573,174 @@ function executeDisconnectNode(command, context) {
570
573
  function executeListNodes(context) {
571
574
  const workflow = context.getWorkflow();
572
575
  if (!workflow) {
573
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
576
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
574
577
  }
575
578
  const nodes = workflow.nodes.map((n) => ({
576
579
  nodeId: toShortId(n.id),
577
- label: n.data.label ?? n.data.metadata?.name ?? "",
578
- type: n.data.metadata?.id ? toShortTypeId(n.data.metadata.id) : "",
580
+ label: n.data.label ?? n.data.metadata?.name ?? '',
581
+ type: n.data.metadata?.id ? toShortTypeId(n.data.metadata.id) : ''
579
582
  }));
580
583
  const resultData = { nodes };
581
584
  return {
582
585
  ok: true,
583
586
  message: nodes.length === 0
584
- ? "No nodes in workflow"
585
- : `${nodes.length} node(s): ${nodes.map((n) => n.nodeId).join(", ")}`,
586
- data: resultData,
587
+ ? 'No nodes in workflow'
588
+ : `${nodes.length} node(s): ${nodes.map((n) => n.nodeId).join(', ')}`,
589
+ data: resultData
587
590
  };
588
591
  }
589
592
  function executeListEdges(context) {
590
593
  const workflow = context.getWorkflow();
591
594
  if (!workflow) {
592
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
595
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
593
596
  }
594
597
  const edges = workflow.edges.map((e) => ({
595
598
  edgeId: e.id,
596
599
  sourceNodeId: toShortId(e.source),
597
- sourcePort: extractPortId(e.sourceHandle) ?? "",
600
+ sourcePort: extractPortId(e.sourceHandle) ?? '',
598
601
  targetNodeId: toShortId(e.target),
599
- targetPort: extractPortId(e.targetHandle) ?? "",
602
+ targetPort: extractPortId(e.targetHandle) ?? ''
600
603
  }));
601
604
  const resultData = { edges };
602
605
  return {
603
606
  ok: true,
604
- message: edges.length === 0
605
- ? "No edges in workflow"
606
- : `${edges.length} edge(s)`,
607
- data: resultData,
607
+ message: edges.length === 0 ? 'No edges in workflow' : `${edges.length} edge(s)`,
608
+ data: resultData
608
609
  };
609
610
  }
610
611
  function executeListTypes(context) {
611
612
  const types = context.nodeTypes.map((m) => ({
612
613
  typeId: toShortTypeId(m.id),
613
614
  name: m.name,
614
- category: m.category,
615
+ category: m.category
615
616
  }));
616
617
  const resultData = { types };
617
618
  return {
618
619
  ok: true,
619
620
  message: `${types.length} type(s) available`,
620
- data: resultData,
621
+ data: resultData
621
622
  };
622
623
  }
623
624
  /** All command help entries */
624
625
  export const COMMAND_HELP = [
625
- { name: "add", syntax: "add <type> [at <x>,<y>]", description: "Add a new node of the specified type" },
626
- { name: "delete", syntax: "delete <nodeId>", description: "Delete a node and its connections" },
627
- { name: "rename", syntax: "rename <nodeId> <label>", description: "Rename a node's display label" },
628
- { name: "set", syntax: "set <nodeId>:<key> <value>", description: "Set a config value on a node" },
629
- { name: "get", syntax: "get <nodeId>:<key>", description: "Get a config value from a node" },
630
- { name: "connect", syntax: "connect <nid>:<port> to <nid>:<port>", description: "Connect two node ports" },
631
- { name: "disconnect", syntax: "disconnect <nid>:<port> from <nid>:<port>", description: "Disconnect two node ports" },
632
- { name: "disconnect", syntax: "disconnect <nodeId>", description: "Disconnect all edges from a node" },
633
- { name: "list", syntax: "list nodes|edges|types", description: "List workflow nodes, edges, or available types" },
634
- { name: "info", syntax: "info <nodeId>", description: "Show detailed info about a node" },
635
- { name: "config", syntax: "config <nodeId>", description: "Open the config panel for a node" },
636
- { name: "select", syntax: "select <nodeId>", description: "Select a node on the canvas" },
637
- { name: "swap", syntax: "swap <nodeId> with <type>", description: "Replace a node's type, preserving connections" },
638
- { name: "move", syntax: "move <nodeId> to <x>,<y>", description: "Move a node to a position" },
639
- { name: "layout", syntax: "layout auto [--direction horizontal|vertical]", description: "Auto-arrange all nodes" },
640
- { name: "layout", syntax: "layout beautify", description: "Normalize spacing while preserving node arrangement" },
641
- { name: "undo", syntax: "undo", description: "Undo the last action" },
642
- { name: "redo", syntax: "redo", description: "Redo the last undone action" },
643
- { name: "help", syntax: "help [<command>]", description: "Show help for all or a specific command" },
644
- { name: "clear", syntax: "clear", description: "Remove all nodes and edges" },
645
- { name: "canvas", syntax: "canvas fitview", description: "Fit all nodes into the viewport" },
646
- { name: "canvas", syntax: "canvas zoom in", description: "Zoom in on the canvas" },
647
- { name: "canvas", syntax: "canvas zoom out", description: "Zoom out on the canvas" },
648
- { name: "canvas", syntax: "canvas zoom <level>", description: "Set zoom to a specific level (e.g. 1.5)" },
649
- { name: "canvas", syntax: "canvas pan <x>,<y>", description: "Pan the canvas to center on a position" },
650
- { name: "canvas", syntax: "canvas reset", description: "Reset viewport to default position and zoom" },
626
+ {
627
+ name: 'add',
628
+ syntax: 'add <type> [at <x>,<y>]',
629
+ description: 'Add a new node of the specified type'
630
+ },
631
+ {
632
+ name: 'delete',
633
+ syntax: 'delete <nodeId>',
634
+ description: 'Delete a node and its connections'
635
+ },
636
+ {
637
+ name: 'rename',
638
+ syntax: 'rename <nodeId> <label>',
639
+ description: "Rename a node's display label"
640
+ },
641
+ {
642
+ name: 'set',
643
+ syntax: 'set <nodeId>:<key> <value>',
644
+ description: 'Set a config value on a node'
645
+ },
646
+ {
647
+ name: 'get',
648
+ syntax: 'get <nodeId>:<key>',
649
+ description: 'Get a config value from a node'
650
+ },
651
+ {
652
+ name: 'connect',
653
+ syntax: 'connect <nid>:<port> to <nid>:<port>',
654
+ description: 'Connect two node ports'
655
+ },
656
+ {
657
+ name: 'disconnect',
658
+ syntax: 'disconnect <nid>:<port> from <nid>:<port>',
659
+ description: 'Disconnect two node ports'
660
+ },
661
+ {
662
+ name: 'disconnect',
663
+ syntax: 'disconnect <nodeId>',
664
+ description: 'Disconnect all edges from a node'
665
+ },
666
+ {
667
+ name: 'list',
668
+ syntax: 'list nodes|edges|types',
669
+ description: 'List workflow nodes, edges, or available types'
670
+ },
671
+ {
672
+ name: 'info',
673
+ syntax: 'info <nodeId>',
674
+ description: 'Show detailed info about a node'
675
+ },
676
+ {
677
+ name: 'config',
678
+ syntax: 'config <nodeId>',
679
+ description: 'Open the config panel for a node'
680
+ },
681
+ {
682
+ name: 'select',
683
+ syntax: 'select <nodeId>',
684
+ description: 'Select a node on the canvas'
685
+ },
686
+ {
687
+ name: 'swap',
688
+ syntax: 'swap <nodeId> with <type>',
689
+ description: "Replace a node's type, preserving connections"
690
+ },
691
+ {
692
+ name: 'move',
693
+ syntax: 'move <nodeId> to <x>,<y>',
694
+ description: 'Move a node to a position'
695
+ },
696
+ {
697
+ name: 'layout',
698
+ syntax: 'layout auto [--direction horizontal|vertical]',
699
+ description: 'Auto-arrange all nodes'
700
+ },
701
+ {
702
+ name: 'layout',
703
+ syntax: 'layout beautify',
704
+ description: 'Normalize spacing while preserving node arrangement'
705
+ },
706
+ { name: 'undo', syntax: 'undo', description: 'Undo the last action' },
707
+ { name: 'redo', syntax: 'redo', description: 'Redo the last undone action' },
708
+ {
709
+ name: 'help',
710
+ syntax: 'help [<command>]',
711
+ description: 'Show help for all or a specific command'
712
+ },
713
+ { name: 'clear', syntax: 'clear', description: 'Remove all nodes and edges' },
714
+ {
715
+ name: 'canvas',
716
+ syntax: 'canvas fitview',
717
+ description: 'Fit all nodes into the viewport'
718
+ },
719
+ {
720
+ name: 'canvas',
721
+ syntax: 'canvas zoom in',
722
+ description: 'Zoom in on the canvas'
723
+ },
724
+ {
725
+ name: 'canvas',
726
+ syntax: 'canvas zoom out',
727
+ description: 'Zoom out on the canvas'
728
+ },
729
+ {
730
+ name: 'canvas',
731
+ syntax: 'canvas zoom <level>',
732
+ description: 'Set zoom to a specific level (e.g. 1.5)'
733
+ },
734
+ {
735
+ name: 'canvas',
736
+ syntax: 'canvas pan <x>,<y>',
737
+ description: 'Pan the canvas to center on a position'
738
+ },
739
+ {
740
+ name: 'canvas',
741
+ syntax: 'canvas reset',
742
+ description: 'Reset viewport to default position and zoom'
743
+ }
651
744
  ];
652
745
  function executeHelp(command) {
653
746
  let commands;
@@ -661,15 +754,13 @@ function executeHelp(command) {
661
754
  commands = COMMAND_HELP;
662
755
  }
663
756
  const resultData = { commands };
664
- const message = commands
665
- .map((c) => ` ${c.syntax} — ${c.description}`)
666
- .join("\n");
757
+ const message = commands.map((c) => ` ${c.syntax} — ${c.description}`).join('\n');
667
758
  return {
668
759
  ok: true,
669
760
  message: command.command
670
761
  ? `Help for '${command.command}':\n${message}`
671
762
  : `Available commands:\n${message}`,
672
- data: resultData,
763
+ data: resultData
673
764
  };
674
765
  }
675
766
  // ============================================================================
@@ -680,99 +771,99 @@ function executeUndo(context) {
680
771
  if (!success) {
681
772
  return {
682
773
  ok: false,
683
- error: "Nothing to undo",
684
- code: "UNDO_UNAVAILABLE",
774
+ error: 'Nothing to undo',
775
+ code: 'UNDO_UNAVAILABLE'
685
776
  };
686
777
  }
687
- return { ok: true, message: "Undone" };
778
+ return { ok: true, message: 'Undone' };
688
779
  }
689
780
  function executeRedo(context) {
690
781
  const success = context.dispatch.redo();
691
782
  if (!success) {
692
783
  return {
693
784
  ok: false,
694
- error: "Nothing to redo",
695
- code: "REDO_UNAVAILABLE",
785
+ error: 'Nothing to redo',
786
+ code: 'REDO_UNAVAILABLE'
696
787
  };
697
788
  }
698
- return { ok: true, message: "Redone" };
789
+ return { ok: true, message: 'Redone' };
699
790
  }
700
791
  function executeClear(context) {
701
792
  const workflow = context.getWorkflow();
702
793
  if (!workflow) {
703
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
794
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
704
795
  }
705
796
  const nodeCount = workflow.nodes.length;
706
797
  const edgeCount = workflow.edges.length;
707
798
  context.dispatch.batchUpdate({ nodes: [], edges: [] });
708
799
  return {
709
800
  ok: true,
710
- message: `Cleared ${nodeCount} node(s) and ${edgeCount} edge(s)`,
801
+ message: `Cleared ${nodeCount} node(s) and ${edgeCount} edge(s)`
711
802
  };
712
803
  }
713
804
  function executeConfigOpen(command, context) {
714
805
  const workflow = context.getWorkflow();
715
806
  if (!workflow) {
716
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
807
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
717
808
  }
718
809
  const node = resolveNode(command.nodeId, workflow.nodes);
719
810
  if (!node) {
720
811
  return {
721
812
  ok: false,
722
813
  error: `Node not found: ${command.nodeId}`,
723
- code: "NODE_NOT_FOUND",
814
+ code: 'NODE_NOT_FOUND'
724
815
  };
725
816
  }
726
817
  if (context.dispatch.emitUIAction) {
727
- context.dispatch.emitUIAction({ type: "open_config", nodeId: node.id });
818
+ context.dispatch.emitUIAction({ type: 'open_config', nodeId: node.id });
728
819
  return {
729
820
  ok: true,
730
- message: `Opened config for ${toShortId(node.id)}`,
821
+ message: `Opened config for ${toShortId(node.id)}`
731
822
  };
732
823
  }
733
824
  return {
734
825
  ok: true,
735
826
  message: `Config open requested for ${toShortId(node.id)} (no UI handler)`,
736
- uiActionPending: true,
827
+ uiActionPending: true
737
828
  };
738
829
  }
739
830
  function executeSelectNode(command, context) {
740
831
  const workflow = context.getWorkflow();
741
832
  if (!workflow) {
742
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
833
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
743
834
  }
744
835
  const node = resolveNode(command.nodeId, workflow.nodes);
745
836
  if (!node) {
746
837
  return {
747
838
  ok: false,
748
839
  error: `Node not found: ${command.nodeId}`,
749
- code: "NODE_NOT_FOUND",
840
+ code: 'NODE_NOT_FOUND'
750
841
  };
751
842
  }
752
843
  if (context.dispatch.emitUIAction) {
753
- context.dispatch.emitUIAction({ type: "select_node", nodeId: node.id });
844
+ context.dispatch.emitUIAction({ type: 'select_node', nodeId: node.id });
754
845
  return {
755
846
  ok: true,
756
- message: `Selected ${toShortId(node.id)}`,
847
+ message: `Selected ${toShortId(node.id)}`
757
848
  };
758
849
  }
759
850
  return {
760
851
  ok: true,
761
852
  message: `Select requested for ${toShortId(node.id)} (no UI handler)`,
762
- uiActionPending: true,
853
+ uiActionPending: true
763
854
  };
764
855
  }
765
856
  function executeSwapNode(command, context) {
766
857
  const workflow = context.getWorkflow();
767
858
  if (!workflow) {
768
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
859
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
769
860
  }
770
861
  const node = resolveNode(command.nodeId, workflow.nodes);
771
862
  if (!node) {
772
863
  return {
773
864
  ok: false,
774
865
  error: `Node not found: ${command.nodeId}`,
775
- code: "NODE_NOT_FOUND",
866
+ code: 'NODE_NOT_FOUND'
776
867
  };
777
868
  }
778
869
  const newMetadata = context.typeMap.get(command.newTypeId);
@@ -780,7 +871,7 @@ function executeSwapNode(command, context) {
780
871
  return {
781
872
  ok: false,
782
873
  error: `Unknown node type: ${command.newTypeId}`,
783
- code: "NODE_TYPE_NOT_FOUND",
874
+ code: 'NODE_TYPE_NOT_FOUND'
784
875
  };
785
876
  }
786
877
  const preview = computeSwapPreview(node, newMetadata, workflow.edges, workflow.nodes);
@@ -788,13 +879,13 @@ function executeSwapNode(command, context) {
788
879
  if (context.dispatch.swapNode) {
789
880
  context.dispatch.swapNode({
790
881
  nodes: swapResult.updatedNodes,
791
- edges: swapResult.updatedEdges,
882
+ edges: swapResult.updatedEdges
792
883
  });
793
884
  }
794
885
  else {
795
886
  context.dispatch.batchUpdate({
796
887
  nodes: swapResult.updatedNodes,
797
- edges: swapResult.updatedEdges,
888
+ edges: swapResult.updatedEdges
798
889
  });
799
890
  }
800
891
  const resultData = {
@@ -805,50 +896,48 @@ function executeSwapNode(command, context) {
805
896
  droppedEdges: preview.droppedEdges.length,
806
897
  hasDataLoss: preview.hasDataLoss,
807
898
  configCarriedOver: preview.configCarriedOver,
808
- configReset: preview.configReset,
899
+ configReset: preview.configReset
809
900
  };
810
- const droppedMsg = preview.droppedEdges.length > 0
811
- ? ` (${preview.droppedEdges.length} edge(s) dropped)`
812
- : "";
901
+ const droppedMsg = preview.droppedEdges.length > 0 ? ` (${preview.droppedEdges.length} edge(s) dropped)` : '';
813
902
  return {
814
903
  ok: true,
815
904
  message: `Swapped ${toShortId(node.id)} → ${toShortId(preview.newNodeId)} (${command.newTypeId})${droppedMsg}`,
816
- data: resultData,
905
+ data: resultData
817
906
  };
818
907
  }
819
908
  function executeMoveNode(command, context) {
820
909
  const workflow = context.getWorkflow();
821
910
  if (!workflow) {
822
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
911
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
823
912
  }
824
913
  const node = resolveNode(command.nodeId, workflow.nodes);
825
914
  if (!node) {
826
915
  return {
827
916
  ok: false,
828
917
  error: `Node not found: ${command.nodeId}`,
829
- code: "NODE_NOT_FOUND",
918
+ code: 'NODE_NOT_FOUND'
830
919
  };
831
920
  }
832
921
  context.dispatch.updateNode(node.id, {
833
- position: command.position,
922
+ position: command.position
834
923
  });
835
924
  return {
836
925
  ok: true,
837
- message: `Moved ${toShortId(node.id)} to (${command.position.x}, ${command.position.y})`,
926
+ message: `Moved ${toShortId(node.id)} to (${command.position.x}, ${command.position.y})`
838
927
  };
839
928
  }
840
929
  function executeAutoLayout(command, context) {
841
930
  const workflow = context.getWorkflow();
842
931
  if (!workflow) {
843
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
932
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
844
933
  }
845
934
  if (workflow.nodes.length === 0) {
846
- return { ok: true, message: "No nodes to layout" };
935
+ return { ok: true, message: 'No nodes to layout' };
847
936
  }
848
- const isVertical = command.direction === "vertical";
937
+ const isVertical = command.direction === 'vertical';
849
938
  // Filter out loopback edges (loop_back port) — they go backwards and
850
939
  // would reverse the layout direction if included.
851
- const layoutEdges = workflow.edges.filter((e) => !(e.targetHandle ?? "").includes("-input-loop_back"));
940
+ const layoutEdges = workflow.edges.filter((e) => !(e.targetHandle ?? '').includes('-input-loop_back'));
852
941
  // Determine start node via in-degree: a node with no incoming edges
853
942
  // (from non-loopback edges) is a root. Fall back to leftmost position.
854
943
  const inDegree = new Map();
@@ -858,20 +947,20 @@ function executeAutoLayout(command, context) {
858
947
  inDegree.set(e.target, (inDegree.get(e.target) ?? 0) + 1);
859
948
  }
860
949
  const startNode = workflow.nodes.find((n) => (inDegree.get(n.id) ?? 0) === 0)?.id ??
861
- workflow.nodes.reduce((leftmost, n) => n.position.x < leftmost.position.x ? n : leftmost).id;
950
+ workflow.nodes.reduce((leftmost, n) => (n.position.x < leftmost.position.x ? n : leftmost)).id;
862
951
  const flow = {
863
- component_type: "flow",
864
- name: "layout",
952
+ component_type: 'flow',
953
+ name: 'layout',
865
954
  start_node: startNode,
866
955
  nodes: workflow.nodes.map((n) => ({
867
- component_type: "start_node",
868
- name: n.id,
956
+ component_type: 'start_node',
957
+ name: n.id
869
958
  })),
870
959
  control_flow_connections: layoutEdges.map((e) => ({
871
960
  name: e.id,
872
961
  from_node: e.source,
873
- to_node: e.target,
874
- })),
962
+ to_node: e.target
963
+ }))
875
964
  };
876
965
  // Collect measured node dimensions when available
877
966
  const nodeDimensions = new Map();
@@ -890,23 +979,23 @@ function executeAutoLayout(command, context) {
890
979
  return n;
891
980
  return {
892
981
  ...n,
893
- position: isVertical ? { x: pos.y, y: pos.x } : pos,
982
+ position: isVertical ? { x: pos.y, y: pos.x } : pos
894
983
  };
895
984
  });
896
985
  context.dispatch.batchUpdate({ nodes: updatedNodes });
897
- const direction = command.direction ?? "horizontal";
986
+ const direction = command.direction ?? 'horizontal';
898
987
  return {
899
988
  ok: true,
900
- message: `Auto-layout applied to ${workflow.nodes.length} nodes (${direction})`,
989
+ message: `Auto-layout applied to ${workflow.nodes.length} nodes (${direction})`
901
990
  };
902
991
  }
903
992
  function executeBeautifyLayout(_command, context) {
904
993
  const workflow = context.getWorkflow();
905
994
  if (!workflow) {
906
- return { ok: false, error: "No workflow loaded", code: "NO_WORKFLOW" };
995
+ return { ok: false, error: 'No workflow loaded', code: 'NO_WORKFLOW' };
907
996
  }
908
997
  if (workflow.nodes.length === 0) {
909
- return { ok: true, message: "No nodes to beautify" };
998
+ return { ok: true, message: 'No nodes to beautify' };
910
999
  }
911
1000
  // Collect current positions
912
1001
  const currentPositions = new Map();
@@ -933,7 +1022,7 @@ function executeBeautifyLayout(_command, context) {
933
1022
  context.dispatch.batchUpdate({ nodes: updatedNodes });
934
1023
  return {
935
1024
  ok: true,
936
- message: `Beautified layout for ${workflow.nodes.length} nodes`,
1025
+ message: `Beautified layout for ${workflow.nodes.length} nodes`
937
1026
  };
938
1027
  }
939
1028
  // ============================================================================
@@ -947,26 +1036,26 @@ function emitCanvasAction(context, action, successMessage) {
947
1036
  return {
948
1037
  ok: true,
949
1038
  message: `${successMessage} (no UI handler)`,
950
- uiActionPending: true,
1039
+ uiActionPending: true
951
1040
  };
952
1041
  }
953
1042
  function executeCanvasFitView(context) {
954
- return emitCanvasAction(context, { type: "canvas_fit_view" }, "Fit view applied");
1043
+ return emitCanvasAction(context, { type: 'canvas_fit_view' }, 'Fit view applied');
955
1044
  }
956
1045
  function executeCanvasZoomIn(context) {
957
- return emitCanvasAction(context, { type: "canvas_zoom_in" }, "Zoomed in");
1046
+ return emitCanvasAction(context, { type: 'canvas_zoom_in' }, 'Zoomed in');
958
1047
  }
959
1048
  function executeCanvasZoomOut(context) {
960
- return emitCanvasAction(context, { type: "canvas_zoom_out" }, "Zoomed out");
1049
+ return emitCanvasAction(context, { type: 'canvas_zoom_out' }, 'Zoomed out');
961
1050
  }
962
1051
  function executeCanvasZoomTo(command, context) {
963
- return emitCanvasAction(context, { type: "canvas_zoom_to", level: command.level }, `Zoom set to ${command.level}`);
1052
+ return emitCanvasAction(context, { type: 'canvas_zoom_to', level: command.level }, `Zoom set to ${command.level}`);
964
1053
  }
965
1054
  function executeCanvasPanTo(command, context) {
966
- return emitCanvasAction(context, { type: "canvas_pan_to", position: command.position }, `Panned to (${command.position.x}, ${command.position.y})`);
1055
+ return emitCanvasAction(context, { type: 'canvas_pan_to', position: command.position }, `Panned to (${command.position.x}, ${command.position.y})`);
967
1056
  }
968
1057
  function executeCanvasResetView(context) {
969
- return emitCanvasAction(context, { type: "canvas_reset_view" }, "Viewport reset");
1058
+ return emitCanvasAction(context, { type: 'canvas_reset_view' }, 'Viewport reset');
970
1059
  }
971
1060
  // ============================================================================
972
1061
  // Public API
@@ -976,68 +1065,68 @@ function executeCanvasResetView(context) {
976
1065
  */
977
1066
  export function executeCommand(command, context) {
978
1067
  switch (command.type) {
979
- case "add_node":
1068
+ case 'add_node':
980
1069
  return executeAddNode(command, context);
981
- case "delete_node":
1070
+ case 'delete_node':
982
1071
  return executeDeleteNode(command, context);
983
- case "rename_node":
1072
+ case 'rename_node':
984
1073
  return executeRenameNode(command, context);
985
- case "set_config":
1074
+ case 'set_config':
986
1075
  return executeSetConfig(command, context);
987
- case "get_config":
1076
+ case 'get_config':
988
1077
  return executeGetConfig(command, context);
989
- case "info":
1078
+ case 'info':
990
1079
  return executeInfo(command, context);
991
- case "connect":
1080
+ case 'connect':
992
1081
  return executeConnect(command, context);
993
- case "disconnect_ports":
1082
+ case 'disconnect_ports':
994
1083
  return executeDisconnectPorts(command, context);
995
- case "disconnect_node":
1084
+ case 'disconnect_node':
996
1085
  return executeDisconnectNode(command, context);
997
- case "list_nodes":
1086
+ case 'list_nodes':
998
1087
  return executeListNodes(context);
999
- case "list_edges":
1088
+ case 'list_edges':
1000
1089
  return executeListEdges(context);
1001
- case "list_types":
1090
+ case 'list_types':
1002
1091
  return executeListTypes(context);
1003
- case "help":
1092
+ case 'help':
1004
1093
  return executeHelp(command);
1005
- case "undo":
1094
+ case 'undo':
1006
1095
  return executeUndo(context);
1007
- case "redo":
1096
+ case 'redo':
1008
1097
  return executeRedo(context);
1009
- case "clear":
1098
+ case 'clear':
1010
1099
  return executeClear(context);
1011
- case "config_open":
1100
+ case 'config_open':
1012
1101
  return executeConfigOpen(command, context);
1013
- case "select_node":
1102
+ case 'select_node':
1014
1103
  return executeSelectNode(command, context);
1015
- case "swap_node":
1104
+ case 'swap_node':
1016
1105
  return executeSwapNode(command, context);
1017
- case "move_node":
1106
+ case 'move_node':
1018
1107
  return executeMoveNode(command, context);
1019
- case "auto_layout":
1108
+ case 'auto_layout':
1020
1109
  return executeAutoLayout(command, context);
1021
- case "beautify_layout":
1110
+ case 'beautify_layout':
1022
1111
  return executeBeautifyLayout(command, context);
1023
- case "canvas_fit_view":
1112
+ case 'canvas_fit_view':
1024
1113
  return executeCanvasFitView(context);
1025
- case "canvas_zoom_in":
1114
+ case 'canvas_zoom_in':
1026
1115
  return executeCanvasZoomIn(context);
1027
- case "canvas_zoom_out":
1116
+ case 'canvas_zoom_out':
1028
1117
  return executeCanvasZoomOut(context);
1029
- case "canvas_zoom_to":
1118
+ case 'canvas_zoom_to':
1030
1119
  return executeCanvasZoomTo(command, context);
1031
- case "canvas_pan_to":
1120
+ case 'canvas_pan_to':
1032
1121
  return executeCanvasPanTo(command, context);
1033
- case "canvas_reset_view":
1122
+ case 'canvas_reset_view':
1034
1123
  return executeCanvasResetView(context);
1035
1124
  default: {
1036
1125
  const _exhaustive = command;
1037
1126
  return {
1038
1127
  ok: false,
1039
1128
  error: `Command not yet implemented: ${_exhaustive.type}`,
1040
- code: "UNKNOWN_COMMAND",
1129
+ code: 'UNKNOWN_COMMAND'
1041
1130
  };
1042
1131
  }
1043
1132
  }