@kiberon-labs/behave-graph-flow 1.0.0 → 3.0.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 (378) hide show
  1. package/.fallowrc.json +16 -0
  2. package/.storybook/main.ts +32 -0
  3. package/.storybook/manager.ts +6 -0
  4. package/.storybook/preview.ts +64 -0
  5. package/.storybook/styles.css +16 -0
  6. package/.turbo/turbo-build.log +7 -0
  7. package/CHANGELOG.md +368 -0
  8. package/LICENSE +6 -0
  9. package/README.md +2 -2
  10. package/data/Polynomial.json +510 -0
  11. package/data/sequence.json +337 -0
  12. package/data/trigger-event.json +241 -0
  13. package/data/variable-change.json +210 -0
  14. package/dist/AnyControlImpl-Ds-CShIB.js +20 -0
  15. package/dist/AnyControlImpl-Ds-CShIB.js.map +1 -0
  16. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js +166 -0
  17. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js.map +1 -0
  18. package/dist/entry.css +4 -0
  19. package/dist/index.css +42 -0
  20. package/dist/index.css.map +1 -0
  21. package/dist/index.d.ts +3597 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +18009 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/noteImpl-KkrrWgJd.js +242 -0
  26. package/dist/noteImpl-KkrrWgJd.js.map +1 -0
  27. package/dist/styles.module-CvmpDkZj.css +3 -0
  28. package/dist/styles.module-CvmpDkZj.css.map +1 -0
  29. package/dist/styles.module-DZxg8aW9.js +271 -0
  30. package/dist/styles.module-DZxg8aW9.js.map +1 -0
  31. package/dist/useChangeNodeData-ChQGK7AI.js +23 -0
  32. package/dist/useChangeNodeData-ChQGK7AI.js.map +1 -0
  33. package/docs/notifications.md +246 -0
  34. package/docs/protocol.md +702 -0
  35. package/docs/specifics.md +191 -0
  36. package/package.json +82 -22
  37. package/postcss.config.ts +3 -4
  38. package/src/annotations/index.ts +32 -0
  39. package/src/components/FloatingToolbar/index.module.css +37 -0
  40. package/src/components/FloatingToolbar/index.tsx +256 -0
  41. package/src/components/Flow.tsx +287 -75
  42. package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
  43. package/src/components/contextMenus/NodePicker.module.css +274 -0
  44. package/src/components/contextMenus/NodePicker.tsx +481 -0
  45. package/src/components/contextMenus/edge.tsx +22 -0
  46. package/src/components/contextMenus/node.tsx +15 -0
  47. package/src/components/contextMenus/selection.tsx +11 -0
  48. package/src/components/controls/any/AnyControlImpl.tsx +14 -0
  49. package/src/components/controls/any/index.tsx +19 -0
  50. package/src/components/controls/boolean/index.tsx +13 -0
  51. package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
  52. package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
  53. package/src/components/controls/colorPicker/index.module.css +18 -0
  54. package/src/components/controls/colorPicker/index.tsx +61 -0
  55. package/src/components/controls/number/index.tsx +35 -0
  56. package/src/components/controls/string/index.tsx +16 -0
  57. package/src/components/edges/index.tsx +475 -0
  58. package/src/components/edges/offsetBezier.ts +134 -0
  59. package/src/components/hotKeys.tsx +20 -0
  60. package/src/components/layoutController/index.module.css +13 -0
  61. package/src/components/layoutController/index.tsx +140 -0
  62. package/src/components/layoutController/utils.ts +248 -0
  63. package/src/components/menubar/defaults.tsx +516 -0
  64. package/src/components/menubar/index.tsx +49 -0
  65. package/src/components/menubar/menuItem.module.css +31 -0
  66. package/src/components/menubar/menuItem.tsx +65 -0
  67. package/src/components/nodes/behave/Node.module.css +23 -0
  68. package/src/components/nodes/behave/Node.tsx +176 -0
  69. package/src/components/nodes/behave/NodeContainer.module.css +88 -0
  70. package/src/components/nodes/behave/NodeContainer.tsx +46 -0
  71. package/src/components/nodes/behave/index.tsx +14 -0
  72. package/src/components/nodes/group/index.tsx +109 -0
  73. package/src/components/nodes/wrapper/index.tsx +73 -0
  74. package/src/components/nodes/wrapper/styles.module.css +87 -0
  75. package/src/components/notifications/NotificationProvider.tsx +81 -0
  76. package/src/components/notifications/index.ts +2 -0
  77. package/src/components/notifications/utils.ts +71 -0
  78. package/src/components/panels/alignment/index.module.css +10 -0
  79. package/src/components/panels/alignment/index.tsx +244 -0
  80. package/src/components/panels/base/index.tsx +5 -0
  81. package/src/components/panels/base/styles.module.css +12 -0
  82. package/src/components/panels/common/PanelHeader.module.css +24 -0
  83. package/src/components/panels/common/PanelHeader.tsx +22 -0
  84. package/src/components/panels/common/SectionTitle.module.css +13 -0
  85. package/src/components/panels/common/SectionTitle.tsx +10 -0
  86. package/src/components/panels/events/EditEventPanel.tsx +324 -0
  87. package/src/components/panels/events/ManageEventsPanel.tsx +101 -0
  88. package/src/components/panels/events/index.tsx +23 -0
  89. package/src/components/panels/events/styles.module.css +178 -0
  90. package/src/components/panels/graphProperties/index.tsx +125 -0
  91. package/src/components/panels/history/index.tsx +92 -0
  92. package/src/components/panels/history/styles.module.css +97 -0
  93. package/src/components/panels/keymaps/index.module.css +68 -0
  94. package/src/components/panels/keymaps/index.tsx +166 -0
  95. package/src/components/panels/layers/index.tsx +245 -0
  96. package/src/components/panels/layers/styles.module.css +107 -0
  97. package/src/components/panels/legend/index.module.css +6 -0
  98. package/src/components/panels/legend/index.tsx +76 -0
  99. package/src/components/panels/logs/index.module.css +218 -0
  100. package/src/components/panels/logs/index.tsx +288 -0
  101. package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
  102. package/src/components/panels/nodeInputs/InputsGroup.tsx +65 -0
  103. package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
  104. package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
  105. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
  106. package/src/components/panels/nodeInputs/OutputsGroup.tsx +55 -0
  107. package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
  108. package/src/components/panels/nodeInputs/index.module.css +308 -0
  109. package/src/components/panels/nodeInputs/index.tsx +349 -0
  110. package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
  111. package/src/components/panels/nodeInputs/useNodeInputsData.ts +153 -0
  112. package/src/components/panels/nodePicker/index.tsx +115 -0
  113. package/src/components/panels/panel/index.module.css +66 -0
  114. package/src/components/panels/panel/index.tsx +88 -0
  115. package/src/components/panels/search/index.module.css +16 -0
  116. package/src/components/panels/search/index.tsx +215 -0
  117. package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
  118. package/src/components/panels/systemSettings/index.tsx +251 -0
  119. package/src/components/panels/systemSettings/styles.module.css +138 -0
  120. package/src/components/panels/traces/GridLines.tsx +38 -0
  121. package/src/components/panels/traces/TimeGrid.tsx +48 -0
  122. package/src/components/panels/traces/TraceLane.tsx +62 -0
  123. package/src/components/panels/traces/TraceTooltip.tsx +22 -0
  124. package/src/components/panels/traces/TracesHeader.tsx +56 -0
  125. package/src/components/panels/traces/index.module.css +159 -0
  126. package/src/components/panels/traces/index.tsx +298 -0
  127. package/src/components/panels/traces/types.ts +48 -0
  128. package/src/components/panels/traces/useDerivedSpans.ts +307 -0
  129. package/src/components/panels/traces/utils.ts +33 -0
  130. package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
  131. package/src/components/panels/variables/ManageVariablesScreen.tsx +147 -0
  132. package/src/components/panels/variables/index.tsx +125 -0
  133. package/src/components/panels/variables/styles.module.css +149 -0
  134. package/src/components/primitives/icon.module.css +45 -0
  135. package/src/components/primitives/icon.tsx +38 -0
  136. package/src/components/sockets/input/index.tsx +83 -0
  137. package/src/components/sockets/input/styles.module.css +26 -0
  138. package/src/components/sockets/output/index.tsx +68 -0
  139. package/src/components/sockets/output/styles.module.css +22 -0
  140. package/src/css/notes.css +135 -0
  141. package/src/css/prosemirror.css +57 -0
  142. package/src/css/rc-dock.css +212 -0
  143. package/src/css/rc-menu.css +101 -0
  144. package/src/css/themes/kiberon.css +127 -0
  145. package/src/css/vars.css +198 -0
  146. package/src/css/vscode-elements.css +124 -0
  147. package/src/entry.css +4 -0
  148. package/src/generators/CallSubgraphGenerator.tsx +136 -0
  149. package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
  150. package/src/generators/GraphBoundaryGenerator.module.css +32 -0
  151. package/src/generators/GraphBoundaryGenerator.tsx +193 -0
  152. package/src/generators/SequenceGenerator.tsx +104 -0
  153. package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
  154. package/src/generators/SwitchOnStringGenerator.tsx +263 -0
  155. package/src/generators/callSubgraphSync.ts +126 -0
  156. package/src/generators/registerDefaultGenerators.ts +55 -0
  157. package/src/generators/registerDefaults.ts +26 -0
  158. package/src/hooks/useBehaveGraphFlow.ts +17 -16
  159. package/src/hooks/useFlowHandlers.ts +154 -30
  160. package/src/hooks/useWasdPan.ts +210 -0
  161. package/src/index.css +134 -0
  162. package/src/index.ts +53 -18
  163. package/src/manifest/contributionRegistry.ts +93 -0
  164. package/src/manifest/index.ts +4 -0
  165. package/src/manifest/loadManifest.ts +82 -0
  166. package/src/manifest/manifestPlugin.ts +29 -0
  167. package/src/manifest/passthroughValueType.ts +40 -0
  168. package/src/plugin/alignment/index.ts +91 -0
  169. package/src/plugin/autosave/controller.ts +366 -0
  170. package/src/plugin/autosave/index.tsx +114 -0
  171. package/src/plugin/autosave/panel/BackupPanel.tsx +141 -0
  172. package/src/plugin/autosave/panel/index.tsx +1 -0
  173. package/src/plugin/autosave/panel/styles.module.css +56 -0
  174. package/src/plugin/autosave/settings.ts +65 -0
  175. package/src/plugin/autosave/storage.ts +147 -0
  176. package/src/plugin/docs/index.tsx +297 -0
  177. package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
  178. package/src/plugin/docs/panel/index.tsx +21 -0
  179. package/src/plugin/docs/panel/styles.module.css +174 -0
  180. package/src/plugin/graphrunner/actions.ts +326 -0
  181. package/src/plugin/graphrunner/buttons.tsx +95 -0
  182. package/src/plugin/graphrunner/client.ts +707 -0
  183. package/src/plugin/graphrunner/index.tsx +184 -0
  184. package/src/plugin/graphrunner/panel.tsx +386 -0
  185. package/src/plugin/graphrunner/runController.ts +283 -0
  186. package/src/plugin/graphrunner/runner.ts +187 -0
  187. package/src/plugin/graphrunner/session.ts +243 -0
  188. package/src/plugin/graphrunner/store.ts +196 -0
  189. package/src/plugin/graphrunner/styles.module.css +171 -0
  190. package/src/plugin/graphrunner/transport.ts +250 -0
  191. package/src/plugin/graphrunner/types.ts +693 -0
  192. package/src/plugin/graphrunner-local/execution-utils.ts +637 -0
  193. package/src/plugin/graphrunner-local/index.tsx +172 -0
  194. package/src/plugin/graphrunner-local/panel.tsx +187 -0
  195. package/src/plugin/graphrunner-local/store.ts +41 -0
  196. package/src/plugin/graphrunner-local/styles.module.css +82 -0
  197. package/src/plugin/graphrunner-local/transport.ts +1339 -0
  198. package/src/plugin/graphrunner-local/types.ts +10 -0
  199. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +635 -0
  200. package/src/plugin/graphrunner-webworker/index.tsx +140 -0
  201. package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
  202. package/src/plugin/graphrunner-webworker/store.ts +98 -0
  203. package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
  204. package/src/plugin/kitchen-sink/index.ts +38 -0
  205. package/src/plugin/layout/dagre.ts +131 -0
  206. package/src/plugin/layout/elk.ts +216 -0
  207. package/src/plugin/layout/index.ts +80 -0
  208. package/src/plugin/notes/FormatToolbar.tsx +200 -0
  209. package/src/plugin/notes/index.tsx +191 -0
  210. package/src/plugin/notes/nodeActions.ts +100 -0
  211. package/src/plugin/notes/note.tsx +20 -0
  212. package/src/plugin/notes/noteImpl.tsx +89 -0
  213. package/src/plugin/realtime/realtimeRunner.ts +624 -0
  214. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
  215. package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
  216. package/src/specifics/VariableGetSpecific.tsx +110 -0
  217. package/src/specifics/VariableSetSpecific.tsx +110 -0
  218. package/src/store/actions.tsx +698 -0
  219. package/src/store/commands.ts +278 -0
  220. package/src/store/contextMenu.ts +192 -0
  221. package/src/store/controls.tsx +62 -0
  222. package/src/store/conversions.ts +47 -0
  223. package/src/store/documentation.tsx +69 -0
  224. package/src/store/events.tsx +116 -0
  225. package/src/store/flow.tsx +230 -0
  226. package/src/store/graphMeta.ts +39 -0
  227. package/src/store/hotKeys.tsx +364 -0
  228. package/src/store/layers.ts +259 -0
  229. package/src/store/legend.tsx +76 -0
  230. package/src/store/logs.ts +28 -0
  231. package/src/store/menubar.ts +41 -0
  232. package/src/store/refs.ts +84 -0
  233. package/src/store/registry.ts +51 -0
  234. package/src/store/selection.ts +22 -0
  235. package/src/store/settings.ts +99 -0
  236. package/src/store/settingsSchema.ts +210 -0
  237. package/src/store/socketGenerator.tsx +54 -0
  238. package/src/store/specific.tsx +75 -0
  239. package/src/store/specs.tsx +35 -0
  240. package/src/store/tabs.ts +282 -0
  241. package/src/store/toolbar.tsx +45 -0
  242. package/src/store/traces.ts +240 -0
  243. package/src/store/variables.ts +37 -0
  244. package/src/system/graph.ts +131 -0
  245. package/src/system/graphSession.ts +172 -0
  246. package/src/system/index.ts +6 -0
  247. package/src/system/notifications.ts +111 -0
  248. package/src/system/persistence.ts +82 -0
  249. package/src/system/plugin.ts +55 -0
  250. package/src/system/provider.tsx +86 -0
  251. package/src/system/pubsub.ts +323 -0
  252. package/src/system/system.ts +653 -0
  253. package/src/system/tabLoader.tsx +303 -0
  254. package/src/system/undoRedo.ts +103 -0
  255. package/src/transformers/Uigraph.ts +61 -0
  256. package/src/transformers/behaveToFlow.ts +16 -4
  257. package/src/transformers/contract.ts +87 -0
  258. package/src/transformers/flowToBehave.ts +40 -12
  259. package/src/types/NodeMetadata.ts +27 -0
  260. package/src/types/graph.ts +49 -0
  261. package/src/types/nodes.ts +50 -0
  262. package/src/types.ts +18 -0
  263. package/src/util/autoConvert.ts +200 -0
  264. package/src/util/colors.ts +1 -29
  265. package/src/util/downloadJson.ts +18 -0
  266. package/src/util/extractNodeMetadata.ts +16 -0
  267. package/src/util/getPickerFilters.ts +1 -1
  268. package/src/util/isBehaveNode.ts +6 -0
  269. package/src/util/isValidConnection.ts +51 -17
  270. package/src/util/mergeSockets.ts +29 -0
  271. package/src/util/serializeVariables.ts +66 -0
  272. package/src/util/sockets.ts +43 -0
  273. package/stories/apex/layoutController/example-graph.worker.ts +39 -0
  274. package/stories/apex/layoutController/index.stories.tsx +48 -0
  275. package/stories/apex/layoutController/webworker.stories.tsx +103 -0
  276. package/stories/apex/menubar/menubar.stories.tsx +19 -0
  277. package/stories/components/colorpicker/index.stories.tsx +20 -0
  278. package/stories/components/contextMenus/edge.stories.tsx +32 -0
  279. package/stories/components/contextMenus/node.stories.tsx +26 -0
  280. package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
  281. package/stories/components/controls/any/index.stories.tsx +19 -0
  282. package/stories/components/controls/boolean/index.stories.tsx +19 -0
  283. package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
  284. package/stories/components/controls/number/index.stories.tsx +19 -0
  285. package/stories/components/controls/string/index.stories.tsx +19 -0
  286. package/stories/components/nodes/behaveNode.stories.tsx +108 -0
  287. package/stories/components/panels/alignment.stories.tsx +24 -0
  288. package/stories/components/panels/events.stories.tsx +38 -0
  289. package/stories/components/panels/graphRunner.stories.tsx +317 -0
  290. package/stories/components/panels/history.stories.tsx +37 -0
  291. package/stories/components/panels/keymaps.stories.tsx +21 -0
  292. package/stories/components/panels/legend.stories.tsx +37 -0
  293. package/stories/components/panels/logs.stories.tsx +24 -0
  294. package/stories/components/panels/nodeInputs.stories.tsx +21 -0
  295. package/stories/components/panels/nodePicker.stories.tsx +37 -0
  296. package/stories/components/panels/panel.stories.tsx +39 -0
  297. package/stories/components/panels/search.stories.tsx +24 -0
  298. package/stories/components/panels/systemSettings.stories.tsx +26 -0
  299. package/stories/components/panels/traces.stories.tsx +225 -0
  300. package/stories/components/panels/variables.stories.tsx +24 -0
  301. package/stories/defaults/defaultStoryProvider.tsx +170 -0
  302. package/stories/defaults/systemGenerator.ts +43 -0
  303. package/stories/plugins/notes.stories.tsx +100 -0
  304. package/tests/autoConvert.test.ts +329 -0
  305. package/tests/autosavePlugin.test.ts +204 -0
  306. package/tests/callSubgraphSync.test.ts +148 -0
  307. package/tests/commandRegistry.test.ts +137 -0
  308. package/tests/components/edges/offsetBezier.test.ts +51 -0
  309. package/tests/components/layoutController/utils.test.ts +68 -0
  310. package/tests/components/panels/traces/utils.test.ts +52 -0
  311. package/tests/contract.test.ts +51 -0
  312. package/tests/contractSerialize.test.ts +62 -0
  313. package/tests/deriveSpans.test.ts +71 -0
  314. package/tests/flowToBehave.test.ts +27 -4
  315. package/tests/hotkeys.test.ts +79 -0
  316. package/tests/keepAliveLifecycle.test.ts +167 -0
  317. package/tests/loadManifest.test.ts +113 -0
  318. package/tests/noteMarkdown.test.ts +65 -0
  319. package/tests/notesPlugin.test.ts +162 -0
  320. package/tests/notifications.test.ts +87 -0
  321. package/tests/persistence.test.ts +51 -0
  322. package/tests/saveLoad.test.ts +373 -0
  323. package/tests/settings.test.ts +178 -0
  324. package/tests/traceStore.test.ts +46 -0
  325. package/tests/util/calculateNewEdge.test.ts +98 -0
  326. package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
  327. package/tests/util/hasPositionMetaData.test.ts +33 -0
  328. package/tests/util/isBehaveNode.test.ts +22 -0
  329. package/tests/util/isHandleConnected.test.ts +37 -0
  330. package/tests/util/mergeSockets.test.ts +43 -0
  331. package/tests/visual/README.md +64 -0
  332. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
  333. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  334. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  335. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  336. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  337. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  338. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  339. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-localGraphRunner-chromium-win32.png +0 -0
  340. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  341. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  342. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  343. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  344. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  345. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  346. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
  347. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  348. package/tests/visual/panels.visual.test.tsx +76 -0
  349. package/tests/wasdPan.test.ts +71 -0
  350. package/tsconfig.base.json +39 -0
  351. package/tsconfig.json +18 -59
  352. package/tsconfig.prod.json +23 -0
  353. package/tsdown.config.ts +15 -3
  354. package/typedoc.json +7 -7
  355. package/vite.config.js +7 -0
  356. package/vitest.config.ts +5 -2
  357. package/vitest.visual.config.ts +55 -0
  358. package/src/components/AutoSizeInput.tsx +0 -65
  359. package/src/components/Controls.tsx +0 -87
  360. package/src/components/InputSocket.tsx +0 -142
  361. package/src/components/Node.tsx +0 -68
  362. package/src/components/NodeContainer.tsx +0 -46
  363. package/src/components/NodePicker.tsx +0 -77
  364. package/src/components/OutputSocket.tsx +0 -58
  365. package/src/components/modals/ClearModal.tsx +0 -40
  366. package/src/components/modals/HelpModal.tsx +0 -36
  367. package/src/components/modals/LoadModal.tsx +0 -96
  368. package/src/components/modals/Modal.tsx +0 -64
  369. package/src/components/modals/SaveModal.tsx +0 -60
  370. package/src/hooks/useCustomNodeTypes.tsx +0 -31
  371. package/src/hooks/useGraphRunner.ts +0 -104
  372. package/src/hooks/useMergeMap.ts +0 -14
  373. package/src/hooks/useNodeSpecJson.ts +0 -20
  374. package/src/hooks/useQueriableDefinitions.ts +0 -22
  375. package/src/styles.css +0 -8
  376. package/tailwind.config.ts +0 -19
  377. package/tests/tsconfig.json +0 -10
  378. /package/src/{types.d.ts → types-declarations.d.ts} +0 -0
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Web Worker graph runner plugin for browser-based graph execution in a worker thread
3
+ * Uses a Web Worker to execute graphs without blocking the UI
4
+ */
5
+
6
+ import type { System } from '../../system/system.js';
7
+ import { plugin } from '../../system/plugin.js';
8
+ import { GraphRunnerClient } from '../graphrunner/client.js';
9
+ import { WorkerTransport } from './worker-transport.js';
10
+ import { graphRunnerClientPlugin } from '../graphrunner/index.js';
11
+ import { webWorkerGraphRunnerStoreFactory } from './store.js';
12
+ import { WebWorkerGraphRunnerPanel } from './panel.js';
13
+ import { MenuItemElement } from '../../components/menubar/menuItem.js';
14
+ import { ErrorBoundary } from 'react-error-boundary';
15
+
16
+ export * from './worker-transport.js';
17
+ export * from './store.js';
18
+ export * from './panel.js';
19
+
20
+ /**
21
+ * Options for the Web Worker graph runner plugin
22
+ */
23
+ export interface WebWorkerGraphRunnerPluginOptions {
24
+ /**
25
+ * Pre-configured Web Worker instance.
26
+ * The worker should be set up with the necessary registry and message handlers.
27
+ * The registry MUST be defined inside the worker file itself.
28
+ *
29
+ * Example:
30
+ * ```ts
31
+ * const worker = new Worker(new URL('./my-graph-worker.ts', import.meta.url), { type: 'module' });
32
+ * ```
33
+ */
34
+ worker: Worker;
35
+
36
+ /**
37
+ * Whether to skip automatic connection.
38
+ * Default: false (will attempt to connect immediately)
39
+ */
40
+ skipAutoConnect?: boolean;
41
+
42
+ /**
43
+ * Whether to add the menu item to the Window menu.
44
+ * Default: true
45
+ */
46
+ addMenuItem?: boolean;
47
+ }
48
+
49
+ /**
50
+ * Plugin initialization function for Web Worker graph execution
51
+ * Registers a GraphRunnerClient with a worker transport that executes graphs in a Web Worker
52
+ */
53
+ export async function webWorkerGraphRunnerPluginLoader(
54
+ system: System,
55
+ options: WebWorkerGraphRunnerPluginOptions
56
+ ): Promise<void> {
57
+ // Create web worker graph runner store
58
+ const webWorkerStore = webWorkerGraphRunnerStoreFactory();
59
+ system.decorate('webWorkerGraphRunnerStore', webWorkerStore);
60
+
61
+ // Create worker transport with the user-provided worker
62
+ const transport = new WorkerTransport(options.worker);
63
+
64
+ // Create client with the worker transport and message activity tracking
65
+ const client = new GraphRunnerClient({
66
+ transport,
67
+ protocolVersion: '1.0.0',
68
+ auth: { type: 'none' },
69
+ onMessageActivity: (direction, message) => {
70
+ // Access the store from the system after it's registered
71
+ const graphRunnerStore = system.runner.store;
72
+ if (graphRunnerStore) {
73
+ graphRunnerStore.getState().addMessageActivity(direction, message);
74
+ }
75
+ }
76
+ });
77
+
78
+ // Register the graph runner client plugin. With skipAutoConnect:false the
79
+ // plugin calls runner.connect(), which wires the persistent client event
80
+ // listeners (trace/logs/lifecycle) on this same client , so we must NOT wire
81
+ // them again here, or every trace span would be recorded twice.
82
+ await system.registerPlugin(graphRunnerClientPlugin, {
83
+ client,
84
+ skipAutoConnect: false
85
+ });
86
+
87
+ // Register the web worker graph runner panel
88
+ system.tabLoader.register('webWorkerGraphRunner', () => {
89
+ return {
90
+ id: 'webWorkerGraphRunner',
91
+ closable: true,
92
+ title: 'Web Worker Graph Runner',
93
+ group: 'default',
94
+ content: () => (
95
+ <ErrorBoundary
96
+ fallback={<div>Error loading Web Worker Graph Runner panel</div>}
97
+ >
98
+ <WebWorkerGraphRunnerPanel />
99
+ </ErrorBoundary>
100
+ )
101
+ };
102
+ });
103
+
104
+ // Add menu item to Window menu (unless disabled)
105
+ if (options.addMenuItem !== false) {
106
+ const menuStore = system.menubarStore;
107
+ const currentItems = menuStore.getState().items;
108
+ const windowMenu = currentItems.find((menu) => menu.name === 'window');
109
+
110
+ if (windowMenu) {
111
+ // Add the Web Worker Graph Runner menu item to the Window menu
112
+ const newMenuItem = {
113
+ name: 'webWorkerGraphRunner',
114
+ render: function WebWorkerGraphRunnerMenuItem() {
115
+ return (
116
+ <MenuItemElement
117
+ onClick={() =>
118
+ system.tabStore.getState().openTab('webWorkerGraphRunner')
119
+ }
120
+ key="webWorkerGraphRunner"
121
+ >
122
+ Web Worker Graph Runner
123
+ </MenuItemElement>
124
+ );
125
+ }
126
+ };
127
+
128
+ menuStore
129
+ .getState()
130
+ .setSubMenuItems('window', [...windowMenu.items, newMenuItem]);
131
+ }
132
+ }
133
+ }
134
+
135
+ export const webWorkerGraphRunnerPlugin = plugin(
136
+ webWorkerGraphRunnerPluginLoader,
137
+ {
138
+ name: 'graphrunner-webworker'
139
+ }
140
+ );
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Panel component for Web Worker Graph Runner
3
+ */
4
+
5
+ import React from 'react';
6
+ import { useSystem } from '@/system/provider';
7
+ import { useStore } from 'zustand';
8
+ import { BasePanel } from '@/components/panels/base';
9
+ import { VscodeButton, VscodeTextfield } from '@vscode-elements/react-elements';
10
+
11
+ import styles from '../graphrunner-local/styles.module.css';
12
+
13
+ export function WebWorkerGraphRunnerPanel() {
14
+ const system = useSystem();
15
+ const store = system.webWorkerGraphRunnerStore;
16
+
17
+ const activeRuns = useStore(store, (s) => s.activeRuns);
18
+ const isExecuting = useStore(store, (s) => s.isExecuting);
19
+ const isPaused = useStore(store, (s) => s.isPaused);
20
+ const tickInterval = useStore(store, (s) => s.tickInterval);
21
+ const stepDelay = useStore(store, (s) => s.stepDelay);
22
+ const executionSpeed = useStore(store, (s) => s.executionSpeed);
23
+
24
+ const [tickInputValue, setTickInputValue] = React.useState(
25
+ String(tickInterval)
26
+ );
27
+ const [stepDelayValue, setStepDelayValue] = React.useState(String(stepDelay));
28
+ const [speedValue, setSpeedValue] = React.useState(String(executionSpeed));
29
+
30
+ const handleApplyTick = () => {
31
+ const value = parseInt(tickInputValue, 10);
32
+ if (!isNaN(value) && value > 0) {
33
+ store.getState().setTickInterval(value);
34
+ }
35
+ };
36
+
37
+ const handleApplyStepDelay = () => {
38
+ const value = parseInt(stepDelayValue, 10);
39
+ if (!isNaN(value) && value >= 0) {
40
+ store.getState().setStepDelay(value);
41
+ }
42
+ };
43
+
44
+ const handleApplySpeed = () => {
45
+ const value = parseFloat(speedValue);
46
+ if (!isNaN(value) && value > 0) {
47
+ store.getState().setExecutionSpeed(value);
48
+ }
49
+ };
50
+
51
+ return (
52
+ <BasePanel>
53
+ <div className={styles.container}>
54
+ <div className={styles.header}>
55
+ <h3>Web Worker Graph Runner</h3>
56
+ <p className={styles.description}>
57
+ Executes graphs in a separate Web Worker thread for non-blocking
58
+ performance
59
+ </p>
60
+ </div>
61
+
62
+ <div className={styles.section}>
63
+ <h4>Status</h4>
64
+ <div className={styles.statusGrid}>
65
+ <div>
66
+ <strong>Active Runs:</strong> {activeRuns}
67
+ </div>
68
+ <div>
69
+ <strong>Executing:</strong> {isExecuting ? 'Yes' : 'No'}
70
+ </div>
71
+ <div>
72
+ <strong>Paused:</strong> {isPaused ? 'Yes' : 'No'}
73
+ </div>
74
+ </div>
75
+ </div>
76
+
77
+ <div className={styles.section}>
78
+ <h4>Execution Settings</h4>
79
+
80
+ <div className={styles.formGroup}>
81
+ <label>Tick Interval (ms)</label>
82
+ <p className={styles.helpText}>
83
+ Time between tick events. Lower = faster ticking.
84
+ </p>
85
+ <div className={styles.inputGroup}>
86
+ <VscodeTextfield
87
+ value={tickInputValue}
88
+ onInput={(e: any) => setTickInputValue(e.target.value)}
89
+ placeholder="50"
90
+ />
91
+ <VscodeButton onClick={handleApplyTick}>Apply</VscodeButton>
92
+ </div>
93
+ <div className={styles.presetButtons}>
94
+ <VscodeButton
95
+ onClick={() => {
96
+ setTickInputValue('1000');
97
+ store.getState().setTickInterval(1000);
98
+ }}
99
+ >
100
+ Very Slow (1000ms)
101
+ </VscodeButton>
102
+ <VscodeButton
103
+ onClick={() => {
104
+ setTickInputValue('200');
105
+ store.getState().setTickInterval(200);
106
+ }}
107
+ >
108
+ Slow (200ms)
109
+ </VscodeButton>
110
+ <VscodeButton
111
+ onClick={() => {
112
+ setTickInputValue('50');
113
+ store.getState().setTickInterval(50);
114
+ }}
115
+ >
116
+ Normal (50ms)
117
+ </VscodeButton>
118
+ <VscodeButton
119
+ onClick={() => {
120
+ setTickInputValue('16');
121
+ store.getState().setTickInterval(16);
122
+ }}
123
+ >
124
+ Fast (16ms)
125
+ </VscodeButton>
126
+ </div>
127
+ </div>
128
+
129
+ <div className={styles.formGroup}>
130
+ <label>Step Delay (ms)</label>
131
+ <p className={styles.helpText}>
132
+ Delay between execution steps. Use for debugging.
133
+ </p>
134
+ <div className={styles.inputGroup}>
135
+ <VscodeTextfield
136
+ value={stepDelayValue}
137
+ onInput={(e: any) => setStepDelayValue(e.target.value)}
138
+ placeholder="0"
139
+ />
140
+ <VscodeButton onClick={handleApplyStepDelay}>Apply</VscodeButton>
141
+ </div>
142
+ </div>
143
+
144
+ <div className={styles.formGroup}>
145
+ <label>Execution Speed</label>
146
+ <p className={styles.helpText}>
147
+ Speed multiplier. 1.0 = normal, 0.5 = half speed, 2.0 = double
148
+ speed.
149
+ </p>
150
+ <div className={styles.inputGroup}>
151
+ <VscodeTextfield
152
+ value={speedValue}
153
+ onInput={(e: any) => setSpeedValue(e.target.value)}
154
+ placeholder="1.0"
155
+ />
156
+ <VscodeButton onClick={handleApplySpeed}>Apply</VscodeButton>
157
+ </div>
158
+ </div>
159
+ </div>
160
+
161
+ <div className={styles.section}>
162
+ <h4>About Web Worker Execution</h4>
163
+ <p className={styles.helpText}>
164
+ Graphs execute in a separate Web Worker thread, keeping the UI
165
+ responsive even during intensive computations. All node execution,
166
+ lifecycle events, and graph state management happens off the main
167
+ thread.
168
+ </p>
169
+ </div>
170
+ </div>
171
+ </BasePanel>
172
+ );
173
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Store for Web Worker Graph Runner state
3
+ */
4
+
5
+ import { create, type StoreApi } from 'zustand';
6
+
7
+ export type WebWorkerGraphRunnerStore = {
8
+ /**
9
+ * Number of active graph runs in the worker
10
+ */
11
+ activeRuns: number;
12
+
13
+ /**
14
+ * Whether a graph is currently executing
15
+ */
16
+ isExecuting: boolean;
17
+
18
+ /**
19
+ * Whether execution is paused
20
+ */
21
+ isPaused: boolean;
22
+
23
+ /**
24
+ * Tick interval in milliseconds (for tick events)
25
+ * Default: 50ms
26
+ */
27
+ tickInterval: number;
28
+
29
+ /**
30
+ * Step delay in milliseconds (between execution steps)
31
+ * Default: 0ms (no delay)
32
+ */
33
+ stepDelay: number;
34
+
35
+ /**
36
+ * Execution speed multiplier
37
+ * 1.0 = normal speed, 0.5 = half speed, 2.0 = double speed
38
+ * Default: 1.0
39
+ */
40
+ executionSpeed: number;
41
+
42
+ /**
43
+ * Set the number of active runs
44
+ */
45
+ setActiveRuns: (count: number) => void;
46
+
47
+ /**
48
+ * Set execution state
49
+ */
50
+ setIsExecuting: (isExecuting: boolean) => void;
51
+
52
+ /**
53
+ * Set pause state
54
+ */
55
+ setIsPaused: (isPaused: boolean) => void;
56
+
57
+ /**
58
+ * Set tick interval
59
+ */
60
+ setTickInterval: (interval: number) => void;
61
+
62
+ /**
63
+ * Set step delay
64
+ */
65
+ setStepDelay: (delay: number) => void;
66
+
67
+ /**
68
+ * Set execution speed
69
+ */
70
+ setExecutionSpeed: (speed: number) => void;
71
+ };
72
+
73
+ export const webWorkerGraphRunnerStoreFactory =
74
+ (): StoreApi<WebWorkerGraphRunnerStore> =>
75
+ create<WebWorkerGraphRunnerStore>((set) => ({
76
+ activeRuns: 0,
77
+ isExecuting: false,
78
+ isPaused: false,
79
+ tickInterval: 50,
80
+ stepDelay: 0,
81
+ executionSpeed: 1.0,
82
+
83
+ setActiveRuns: (count) => set({ activeRuns: count }),
84
+ setIsExecuting: (isExecuting) => set({ isExecuting }),
85
+ setIsPaused: (isPaused) => set({ isPaused }),
86
+ setTickInterval: (interval) => set({ tickInterval: interval }),
87
+ setStepDelay: (delay) => set({ stepDelay: delay }),
88
+ setExecutionSpeed: (speed) => set({ executionSpeed: speed })
89
+ }));
90
+
91
+ declare module '@/system/system' {
92
+ interface System {
93
+ /**
94
+ * Web Worker Graph Runner store
95
+ */
96
+ webWorkerGraphRunnerStore: StoreApi<WebWorkerGraphRunnerStore>;
97
+ }
98
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Web Worker transport implementation for graph execution
3
+ * Communicates with a Web Worker that executes graphs
4
+ */
5
+
6
+ import type { GraphRunnerMessage } from '../graphrunner/types.js';
7
+ import type { ITransport, TransportState } from '../graphrunner/transport.js';
8
+
9
+ /**
10
+ * Messages sent from main thread to worker
11
+ */
12
+ type MainToWorkerMessage = {
13
+ type: 'execute';
14
+ message: GraphRunnerMessage;
15
+ };
16
+
17
+ /**
18
+ * Messages sent from worker to main thread
19
+ */
20
+ type WorkerToMainMessage =
21
+ | {
22
+ type: 'message';
23
+ data: GraphRunnerMessage;
24
+ }
25
+ | {
26
+ type: 'error';
27
+ error: string;
28
+ };
29
+
30
+ /**
31
+ * Web Worker transport that delegates graph execution to a worker thread
32
+ */
33
+ export class WorkerTransport implements ITransport {
34
+ private state: TransportState = 'disconnected';
35
+ private messageHandlers: Array<(message: GraphRunnerMessage) => void> = [];
36
+ private stateChangeHandlers: Array<(state: TransportState) => void> = [];
37
+ private errorHandlers: Array<(error: Error) => void> = [];
38
+ private worker: Worker;
39
+
40
+ constructor(worker: Worker) {
41
+ this.worker = worker;
42
+ }
43
+
44
+ getState(): TransportState {
45
+ console.log('Current transport state:', this.state);
46
+ return this.state;
47
+ }
48
+
49
+ async connect(): Promise<void> {
50
+ this.setState('connecting');
51
+ try {
52
+ // Set up message handler
53
+ this.worker.onmessage = (event: MessageEvent<WorkerToMainMessage>) => {
54
+ this.handleWorkerMessage(event.data);
55
+ };
56
+
57
+ // Set up error handler
58
+ this.worker.onerror = (error) => {
59
+ this.notifyError(new Error(`Worker error: ${error.message}`));
60
+ };
61
+
62
+ this.setState('connected');
63
+ } catch (error) {
64
+ this.setState('error');
65
+ throw error;
66
+ }
67
+ }
68
+
69
+ disconnect(): void {
70
+ this.worker.terminate();
71
+ this.setState('disconnected');
72
+ }
73
+
74
+ send(message: GraphRunnerMessage): void {
75
+ const workerMessage: MainToWorkerMessage = {
76
+ type: 'execute',
77
+ message
78
+ };
79
+ this.worker.postMessage(workerMessage);
80
+ }
81
+
82
+ onMessage(handler: (message: GraphRunnerMessage) => void): void {
83
+ this.messageHandlers.push(handler);
84
+ }
85
+
86
+ onStateChange(handler: (state: TransportState) => void): void {
87
+ this.stateChangeHandlers.push(handler);
88
+ }
89
+
90
+ onError(handler: (error: Error) => void): void {
91
+ this.errorHandlers.push(handler);
92
+ }
93
+
94
+ removeAllHandlers(): void {
95
+ this.messageHandlers = [];
96
+ this.stateChangeHandlers = [];
97
+ this.errorHandlers = [];
98
+ }
99
+
100
+ private setState(newState: TransportState): void {
101
+ this.state = newState;
102
+ this.stateChangeHandlers.forEach((handler) => handler(newState));
103
+ }
104
+
105
+ private notifyError(error: Error): void {
106
+ this.errorHandlers.forEach((handler) => handler(error));
107
+ }
108
+
109
+ private notifyMessage(message: GraphRunnerMessage): void {
110
+ this.messageHandlers.forEach((handler) => handler(message));
111
+ }
112
+
113
+ private handleWorkerMessage(data: WorkerToMainMessage): void {
114
+ switch (data.type) {
115
+ case 'message':
116
+ this.notifyMessage(data.data);
117
+ break;
118
+ case 'error':
119
+ this.notifyError(new Error(data.error));
120
+ break;
121
+ }
122
+ }
123
+ }
@@ -0,0 +1,38 @@
1
+ import { plugin } from '@/system/plugin';
2
+ import type { System } from '@/system/system';
3
+ import { docsPlugin } from '@/plugin/docs';
4
+ import { alignmentPlugin } from '@/plugin/alignment';
5
+ import { layoutPlugin } from '@/plugin/layout';
6
+ import { notesPlugin } from '@/plugin/notes';
7
+ import { autosavePlugin } from '@/plugin/autosave';
8
+
9
+ /**
10
+ * Batteries-included bundle of the standard editor plugins. Register this once
11
+ * instead of wiring each plugin by hand:
12
+ *
13
+ * ```ts
14
+ * const system = new System(registry);
15
+ * system.registerPlugin(kitchenSinkPlugin);
16
+ * ```
17
+ *
18
+ * It currently pulls in:
19
+ * - {@link docsPlugin} — the in-editor node documentation browser;
20
+ * - {@link alignmentPlugin} — node alignment + distribution;
21
+ * - {@link layoutPlugin} — Dagre/ELK auto-layout (heavy deps, opt-in);
22
+ * - {@link notesPlugin} — markdown note nodes (tiptap/prosemirror, opt-in);
23
+ * - {@link autosavePlugin} — client-side local backups of open graphs.
24
+ *
25
+ * It intentionally does **not** register a graph runner: runners
26
+ * ({@link localGraphRunnerPlugin}, the remote client, ...) need host-specific
27
+ * options (a node registry, transport, ...) so hosts wire those themselves.
28
+ */
29
+ export const kitchenSinkPlugin = plugin(
30
+ async (system: System) => {
31
+ await system.registerPlugin(docsPlugin);
32
+ await system.registerPlugin(alignmentPlugin);
33
+ await system.registerPlugin(layoutPlugin);
34
+ await system.registerPlugin(notesPlugin);
35
+ await system.registerPlugin(autosavePlugin);
36
+ },
37
+ { name: 'kitchen-sink' }
38
+ );
@@ -0,0 +1,131 @@
1
+ import { Position } from 'reactflow';
2
+ import type { Edge, Node } from 'reactflow';
3
+ import type dagreNS from 'dagre';
4
+ import type { System } from '@/system';
5
+ import { pinned } from '@/annotations';
6
+
7
+ // the layout direction (T = top, R = right, B = bottom, L = left, TB = top to bottom, ...)
8
+ export type Direction = 'TB' | 'LR' | 'RL' | 'BT';
9
+
10
+ export type Options = {
11
+ direction: Direction;
12
+ };
13
+
14
+ /**
15
+ * dagre is only needed when the user actually runs a Dagre layout, so load it
16
+ * lazily (a dynamic import the bundler code-splits into a separate chunk). This
17
+ * keeps it out of the initial load even for hosts that register the layout
18
+ * plugin. The module is fetched once and reused.
19
+ */
20
+ let dagrePromise: Promise<typeof dagreNS> | undefined;
21
+ const getDagre = () => {
22
+ dagrePromise ??= import('dagre').then((m) => m.default ?? m);
23
+ return dagrePromise;
24
+ };
25
+
26
+ const getDimensions = (node: Node) => {
27
+ return {
28
+ width: node.style?.width ?? node.width ?? 300,
29
+ height: node.style?.height ?? node.height ?? 200
30
+ };
31
+ };
32
+
33
+ const positionMap: Record<string, Position> = {
34
+ T: Position.Top,
35
+ L: Position.Left,
36
+ R: Position.Right,
37
+ B: Position.Bottom
38
+ };
39
+
40
+ export async function applyDagreLayout(
41
+ system: System,
42
+ options: Options | undefined = { direction: 'LR' }
43
+ ) {
44
+ const { direction } = options;
45
+ const { nodes, setNodes } = system.nodeStore.getState();
46
+ const { edges } = system.edgeStore.getState();
47
+
48
+ if (!nodes.length) {
49
+ return;
50
+ }
51
+
52
+ const dagre = await getDagre();
53
+ const dagreGraph = new dagre.graphlib!.Graph();
54
+ dagreGraph.setDefaultEdgeLabel(() => ({}));
55
+ dagreGraph.setGraph({ rankdir: direction });
56
+
57
+ // Add nodes to layout: exclude pinned nodes and child nodes inside groups
58
+ // Include both regular nodes and group nodes
59
+ const layoutNodes = nodes.filter((node) => {
60
+ if ('data' in node) {
61
+ const isPinned = node.data.annotations?.[pinned];
62
+ const isInGroup = !!node.parentId;
63
+ return !isPinned && !isInGroup;
64
+ }
65
+ return false;
66
+ });
67
+
68
+ layoutNodes.forEach((node: Node) => {
69
+ dagreGraph.setNode(node.id, getDimensions(node));
70
+ });
71
+
72
+ // Create a map for quick parent lookup
73
+ const nodeParentMap = new Map<string, string>();
74
+ nodes.forEach((node) => {
75
+ if (node.parentId) {
76
+ nodeParentMap.set(node.id, node.parentId);
77
+ }
78
+ });
79
+
80
+ // Function to get the top-level node or group for layout
81
+ const getLayoutNode = (nodeId: string): string => {
82
+ const parentId = nodeParentMap.get(nodeId);
83
+ return parentId ?? nodeId;
84
+ };
85
+
86
+ // Track unique edges at the layout level to avoid duplicates
87
+ const layoutEdges = new Set<string>();
88
+
89
+ edges.forEach((edge: Edge) => {
90
+ const layoutSource = getLayoutNode(edge.source);
91
+ const layoutTarget = getLayoutNode(edge.target);
92
+
93
+ // Skip self-loops (edges within the same group)
94
+ if (layoutSource === layoutTarget) {
95
+ return;
96
+ }
97
+
98
+ const edgeKey = `${layoutSource}->${layoutTarget}`;
99
+ if (!layoutEdges.has(edgeKey)) {
100
+ layoutEdges.add(edgeKey);
101
+ dagreGraph.setEdge(layoutSource, layoutTarget);
102
+ }
103
+ });
104
+
105
+ dagre.layout(dagreGraph);
106
+
107
+ setNodes((nodes) => {
108
+ const layoutedNodes = nodes.map((node) => {
109
+ // Skip pinned nodes - keep their current position
110
+ const isPinned = 'data' in node && node.data.annotations?.[pinned];
111
+ if (isPinned) {
112
+ return node;
113
+ }
114
+
115
+ // Skip nodes inside groups - they maintain relative positions
116
+ if (node.parentId) {
117
+ return node;
118
+ }
119
+
120
+ const { x, y } = dagreGraph.node(node.id);
121
+
122
+ return {
123
+ ...node,
124
+ sourcePosition: positionMap[direction[1]!],
125
+ targetPosition: positionMap[direction[0]!],
126
+ position: { x, y }
127
+ };
128
+ });
129
+ return layoutedNodes;
130
+ });
131
+ }