@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.
- package/.fallowrc.json +16 -0
- package/.storybook/main.ts +32 -0
- package/.storybook/manager.ts +6 -0
- package/.storybook/preview.ts +64 -0
- package/.storybook/styles.css +16 -0
- package/.turbo/turbo-build.log +7 -0
- package/CHANGELOG.md +368 -0
- package/LICENSE +6 -0
- package/README.md +2 -2
- package/data/Polynomial.json +510 -0
- package/data/sequence.json +337 -0
- package/data/trigger-event.json +241 -0
- package/data/variable-change.json +210 -0
- package/dist/AnyControlImpl-Ds-CShIB.js +20 -0
- package/dist/AnyControlImpl-Ds-CShIB.js.map +1 -0
- package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js +166 -0
- package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js.map +1 -0
- package/dist/entry.css +4 -0
- package/dist/index.css +42 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +3597 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18009 -0
- package/dist/index.js.map +1 -0
- package/dist/noteImpl-KkrrWgJd.js +242 -0
- package/dist/noteImpl-KkrrWgJd.js.map +1 -0
- package/dist/styles.module-CvmpDkZj.css +3 -0
- package/dist/styles.module-CvmpDkZj.css.map +1 -0
- package/dist/styles.module-DZxg8aW9.js +271 -0
- package/dist/styles.module-DZxg8aW9.js.map +1 -0
- package/dist/useChangeNodeData-ChQGK7AI.js +23 -0
- package/dist/useChangeNodeData-ChQGK7AI.js.map +1 -0
- package/docs/notifications.md +246 -0
- package/docs/protocol.md +702 -0
- package/docs/specifics.md +191 -0
- package/package.json +82 -22
- package/postcss.config.ts +3 -4
- package/src/annotations/index.ts +32 -0
- package/src/components/FloatingToolbar/index.module.css +37 -0
- package/src/components/FloatingToolbar/index.tsx +256 -0
- package/src/components/Flow.tsx +287 -75
- package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
- package/src/components/contextMenus/NodePicker.module.css +274 -0
- package/src/components/contextMenus/NodePicker.tsx +481 -0
- package/src/components/contextMenus/edge.tsx +22 -0
- package/src/components/contextMenus/node.tsx +15 -0
- package/src/components/contextMenus/selection.tsx +11 -0
- package/src/components/controls/any/AnyControlImpl.tsx +14 -0
- package/src/components/controls/any/index.tsx +19 -0
- package/src/components/controls/boolean/index.tsx +13 -0
- package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
- package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
- package/src/components/controls/colorPicker/index.module.css +18 -0
- package/src/components/controls/colorPicker/index.tsx +61 -0
- package/src/components/controls/number/index.tsx +35 -0
- package/src/components/controls/string/index.tsx +16 -0
- package/src/components/edges/index.tsx +475 -0
- package/src/components/edges/offsetBezier.ts +134 -0
- package/src/components/hotKeys.tsx +20 -0
- package/src/components/layoutController/index.module.css +13 -0
- package/src/components/layoutController/index.tsx +140 -0
- package/src/components/layoutController/utils.ts +248 -0
- package/src/components/menubar/defaults.tsx +516 -0
- package/src/components/menubar/index.tsx +49 -0
- package/src/components/menubar/menuItem.module.css +31 -0
- package/src/components/menubar/menuItem.tsx +65 -0
- package/src/components/nodes/behave/Node.module.css +23 -0
- package/src/components/nodes/behave/Node.tsx +176 -0
- package/src/components/nodes/behave/NodeContainer.module.css +88 -0
- package/src/components/nodes/behave/NodeContainer.tsx +46 -0
- package/src/components/nodes/behave/index.tsx +14 -0
- package/src/components/nodes/group/index.tsx +109 -0
- package/src/components/nodes/wrapper/index.tsx +73 -0
- package/src/components/nodes/wrapper/styles.module.css +87 -0
- package/src/components/notifications/NotificationProvider.tsx +81 -0
- package/src/components/notifications/index.ts +2 -0
- package/src/components/notifications/utils.ts +71 -0
- package/src/components/panels/alignment/index.module.css +10 -0
- package/src/components/panels/alignment/index.tsx +244 -0
- package/src/components/panels/base/index.tsx +5 -0
- package/src/components/panels/base/styles.module.css +12 -0
- package/src/components/panels/common/PanelHeader.module.css +24 -0
- package/src/components/panels/common/PanelHeader.tsx +22 -0
- package/src/components/panels/common/SectionTitle.module.css +13 -0
- package/src/components/panels/common/SectionTitle.tsx +10 -0
- package/src/components/panels/events/EditEventPanel.tsx +324 -0
- package/src/components/panels/events/ManageEventsPanel.tsx +101 -0
- package/src/components/panels/events/index.tsx +23 -0
- package/src/components/panels/events/styles.module.css +178 -0
- package/src/components/panels/graphProperties/index.tsx +125 -0
- package/src/components/panels/history/index.tsx +92 -0
- package/src/components/panels/history/styles.module.css +97 -0
- package/src/components/panels/keymaps/index.module.css +68 -0
- package/src/components/panels/keymaps/index.tsx +166 -0
- package/src/components/panels/layers/index.tsx +245 -0
- package/src/components/panels/layers/styles.module.css +107 -0
- package/src/components/panels/legend/index.module.css +6 -0
- package/src/components/panels/legend/index.tsx +76 -0
- package/src/components/panels/logs/index.module.css +218 -0
- package/src/components/panels/logs/index.tsx +288 -0
- package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
- package/src/components/panels/nodeInputs/InputsGroup.tsx +65 -0
- package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
- package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
- package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
- package/src/components/panels/nodeInputs/OutputsGroup.tsx +55 -0
- package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
- package/src/components/panels/nodeInputs/index.module.css +308 -0
- package/src/components/panels/nodeInputs/index.tsx +349 -0
- package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
- package/src/components/panels/nodeInputs/useNodeInputsData.ts +153 -0
- package/src/components/panels/nodePicker/index.tsx +115 -0
- package/src/components/panels/panel/index.module.css +66 -0
- package/src/components/panels/panel/index.tsx +88 -0
- package/src/components/panels/search/index.module.css +16 -0
- package/src/components/panels/search/index.tsx +215 -0
- package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
- package/src/components/panels/systemSettings/index.tsx +251 -0
- package/src/components/panels/systemSettings/styles.module.css +138 -0
- package/src/components/panels/traces/GridLines.tsx +38 -0
- package/src/components/panels/traces/TimeGrid.tsx +48 -0
- package/src/components/panels/traces/TraceLane.tsx +62 -0
- package/src/components/panels/traces/TraceTooltip.tsx +22 -0
- package/src/components/panels/traces/TracesHeader.tsx +56 -0
- package/src/components/panels/traces/index.module.css +159 -0
- package/src/components/panels/traces/index.tsx +298 -0
- package/src/components/panels/traces/types.ts +48 -0
- package/src/components/panels/traces/useDerivedSpans.ts +307 -0
- package/src/components/panels/traces/utils.ts +33 -0
- package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
- package/src/components/panels/variables/ManageVariablesScreen.tsx +147 -0
- package/src/components/panels/variables/index.tsx +125 -0
- package/src/components/panels/variables/styles.module.css +149 -0
- package/src/components/primitives/icon.module.css +45 -0
- package/src/components/primitives/icon.tsx +38 -0
- package/src/components/sockets/input/index.tsx +83 -0
- package/src/components/sockets/input/styles.module.css +26 -0
- package/src/components/sockets/output/index.tsx +68 -0
- package/src/components/sockets/output/styles.module.css +22 -0
- package/src/css/notes.css +135 -0
- package/src/css/prosemirror.css +57 -0
- package/src/css/rc-dock.css +212 -0
- package/src/css/rc-menu.css +101 -0
- package/src/css/themes/kiberon.css +127 -0
- package/src/css/vars.css +198 -0
- package/src/css/vscode-elements.css +124 -0
- package/src/entry.css +4 -0
- package/src/generators/CallSubgraphGenerator.tsx +136 -0
- package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
- package/src/generators/GraphBoundaryGenerator.module.css +32 -0
- package/src/generators/GraphBoundaryGenerator.tsx +193 -0
- package/src/generators/SequenceGenerator.tsx +104 -0
- package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
- package/src/generators/SwitchOnStringGenerator.tsx +263 -0
- package/src/generators/callSubgraphSync.ts +126 -0
- package/src/generators/registerDefaultGenerators.ts +55 -0
- package/src/generators/registerDefaults.ts +26 -0
- package/src/hooks/useBehaveGraphFlow.ts +17 -16
- package/src/hooks/useFlowHandlers.ts +154 -30
- package/src/hooks/useWasdPan.ts +210 -0
- package/src/index.css +134 -0
- package/src/index.ts +53 -18
- package/src/manifest/contributionRegistry.ts +93 -0
- package/src/manifest/index.ts +4 -0
- package/src/manifest/loadManifest.ts +82 -0
- package/src/manifest/manifestPlugin.ts +29 -0
- package/src/manifest/passthroughValueType.ts +40 -0
- package/src/plugin/alignment/index.ts +91 -0
- package/src/plugin/autosave/controller.ts +366 -0
- package/src/plugin/autosave/index.tsx +114 -0
- package/src/plugin/autosave/panel/BackupPanel.tsx +141 -0
- package/src/plugin/autosave/panel/index.tsx +1 -0
- package/src/plugin/autosave/panel/styles.module.css +56 -0
- package/src/plugin/autosave/settings.ts +65 -0
- package/src/plugin/autosave/storage.ts +147 -0
- package/src/plugin/docs/index.tsx +297 -0
- package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
- package/src/plugin/docs/panel/index.tsx +21 -0
- package/src/plugin/docs/panel/styles.module.css +174 -0
- package/src/plugin/graphrunner/actions.ts +326 -0
- package/src/plugin/graphrunner/buttons.tsx +95 -0
- package/src/plugin/graphrunner/client.ts +707 -0
- package/src/plugin/graphrunner/index.tsx +184 -0
- package/src/plugin/graphrunner/panel.tsx +386 -0
- package/src/plugin/graphrunner/runController.ts +283 -0
- package/src/plugin/graphrunner/runner.ts +187 -0
- package/src/plugin/graphrunner/session.ts +243 -0
- package/src/plugin/graphrunner/store.ts +196 -0
- package/src/plugin/graphrunner/styles.module.css +171 -0
- package/src/plugin/graphrunner/transport.ts +250 -0
- package/src/plugin/graphrunner/types.ts +693 -0
- package/src/plugin/graphrunner-local/execution-utils.ts +637 -0
- package/src/plugin/graphrunner-local/index.tsx +172 -0
- package/src/plugin/graphrunner-local/panel.tsx +187 -0
- package/src/plugin/graphrunner-local/store.ts +41 -0
- package/src/plugin/graphrunner-local/styles.module.css +82 -0
- package/src/plugin/graphrunner-local/transport.ts +1339 -0
- package/src/plugin/graphrunner-local/types.ts +10 -0
- package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +635 -0
- package/src/plugin/graphrunner-webworker/index.tsx +140 -0
- package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
- package/src/plugin/graphrunner-webworker/store.ts +98 -0
- package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
- package/src/plugin/kitchen-sink/index.ts +38 -0
- package/src/plugin/layout/dagre.ts +131 -0
- package/src/plugin/layout/elk.ts +216 -0
- package/src/plugin/layout/index.ts +80 -0
- package/src/plugin/notes/FormatToolbar.tsx +200 -0
- package/src/plugin/notes/index.tsx +191 -0
- package/src/plugin/notes/nodeActions.ts +100 -0
- package/src/plugin/notes/note.tsx +20 -0
- package/src/plugin/notes/noteImpl.tsx +89 -0
- package/src/plugin/realtime/realtimeRunner.ts +624 -0
- package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
- package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
- package/src/specifics/VariableGetSpecific.tsx +110 -0
- package/src/specifics/VariableSetSpecific.tsx +110 -0
- package/src/store/actions.tsx +698 -0
- package/src/store/commands.ts +278 -0
- package/src/store/contextMenu.ts +192 -0
- package/src/store/controls.tsx +62 -0
- package/src/store/conversions.ts +47 -0
- package/src/store/documentation.tsx +69 -0
- package/src/store/events.tsx +116 -0
- package/src/store/flow.tsx +230 -0
- package/src/store/graphMeta.ts +39 -0
- package/src/store/hotKeys.tsx +364 -0
- package/src/store/layers.ts +259 -0
- package/src/store/legend.tsx +76 -0
- package/src/store/logs.ts +28 -0
- package/src/store/menubar.ts +41 -0
- package/src/store/refs.ts +84 -0
- package/src/store/registry.ts +51 -0
- package/src/store/selection.ts +22 -0
- package/src/store/settings.ts +99 -0
- package/src/store/settingsSchema.ts +210 -0
- package/src/store/socketGenerator.tsx +54 -0
- package/src/store/specific.tsx +75 -0
- package/src/store/specs.tsx +35 -0
- package/src/store/tabs.ts +282 -0
- package/src/store/toolbar.tsx +45 -0
- package/src/store/traces.ts +240 -0
- package/src/store/variables.ts +37 -0
- package/src/system/graph.ts +131 -0
- package/src/system/graphSession.ts +172 -0
- package/src/system/index.ts +6 -0
- package/src/system/notifications.ts +111 -0
- package/src/system/persistence.ts +82 -0
- package/src/system/plugin.ts +55 -0
- package/src/system/provider.tsx +86 -0
- package/src/system/pubsub.ts +323 -0
- package/src/system/system.ts +653 -0
- package/src/system/tabLoader.tsx +303 -0
- package/src/system/undoRedo.ts +103 -0
- package/src/transformers/Uigraph.ts +61 -0
- package/src/transformers/behaveToFlow.ts +16 -4
- package/src/transformers/contract.ts +87 -0
- package/src/transformers/flowToBehave.ts +40 -12
- package/src/types/NodeMetadata.ts +27 -0
- package/src/types/graph.ts +49 -0
- package/src/types/nodes.ts +50 -0
- package/src/types.ts +18 -0
- package/src/util/autoConvert.ts +200 -0
- package/src/util/colors.ts +1 -29
- package/src/util/downloadJson.ts +18 -0
- package/src/util/extractNodeMetadata.ts +16 -0
- package/src/util/getPickerFilters.ts +1 -1
- package/src/util/isBehaveNode.ts +6 -0
- package/src/util/isValidConnection.ts +51 -17
- package/src/util/mergeSockets.ts +29 -0
- package/src/util/serializeVariables.ts +66 -0
- package/src/util/sockets.ts +43 -0
- package/stories/apex/layoutController/example-graph.worker.ts +39 -0
- package/stories/apex/layoutController/index.stories.tsx +48 -0
- package/stories/apex/layoutController/webworker.stories.tsx +103 -0
- package/stories/apex/menubar/menubar.stories.tsx +19 -0
- package/stories/components/colorpicker/index.stories.tsx +20 -0
- package/stories/components/contextMenus/edge.stories.tsx +32 -0
- package/stories/components/contextMenus/node.stories.tsx +26 -0
- package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
- package/stories/components/controls/any/index.stories.tsx +19 -0
- package/stories/components/controls/boolean/index.stories.tsx +19 -0
- package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
- package/stories/components/controls/number/index.stories.tsx +19 -0
- package/stories/components/controls/string/index.stories.tsx +19 -0
- package/stories/components/nodes/behaveNode.stories.tsx +108 -0
- package/stories/components/panels/alignment.stories.tsx +24 -0
- package/stories/components/panels/events.stories.tsx +38 -0
- package/stories/components/panels/graphRunner.stories.tsx +317 -0
- package/stories/components/panels/history.stories.tsx +37 -0
- package/stories/components/panels/keymaps.stories.tsx +21 -0
- package/stories/components/panels/legend.stories.tsx +37 -0
- package/stories/components/panels/logs.stories.tsx +24 -0
- package/stories/components/panels/nodeInputs.stories.tsx +21 -0
- package/stories/components/panels/nodePicker.stories.tsx +37 -0
- package/stories/components/panels/panel.stories.tsx +39 -0
- package/stories/components/panels/search.stories.tsx +24 -0
- package/stories/components/panels/systemSettings.stories.tsx +26 -0
- package/stories/components/panels/traces.stories.tsx +225 -0
- package/stories/components/panels/variables.stories.tsx +24 -0
- package/stories/defaults/defaultStoryProvider.tsx +170 -0
- package/stories/defaults/systemGenerator.ts +43 -0
- package/stories/plugins/notes.stories.tsx +100 -0
- package/tests/autoConvert.test.ts +329 -0
- package/tests/autosavePlugin.test.ts +204 -0
- package/tests/callSubgraphSync.test.ts +148 -0
- package/tests/commandRegistry.test.ts +137 -0
- package/tests/components/edges/offsetBezier.test.ts +51 -0
- package/tests/components/layoutController/utils.test.ts +68 -0
- package/tests/components/panels/traces/utils.test.ts +52 -0
- package/tests/contract.test.ts +51 -0
- package/tests/contractSerialize.test.ts +62 -0
- package/tests/deriveSpans.test.ts +71 -0
- package/tests/flowToBehave.test.ts +27 -4
- package/tests/hotkeys.test.ts +79 -0
- package/tests/keepAliveLifecycle.test.ts +167 -0
- package/tests/loadManifest.test.ts +113 -0
- package/tests/noteMarkdown.test.ts +65 -0
- package/tests/notesPlugin.test.ts +162 -0
- package/tests/notifications.test.ts +87 -0
- package/tests/persistence.test.ts +51 -0
- package/tests/saveLoad.test.ts +373 -0
- package/tests/settings.test.ts +178 -0
- package/tests/traceStore.test.ts +46 -0
- package/tests/util/calculateNewEdge.test.ts +98 -0
- package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
- package/tests/util/hasPositionMetaData.test.ts +33 -0
- package/tests/util/isBehaveNode.test.ts +22 -0
- package/tests/util/isHandleConnected.test.ts +37 -0
- package/tests/util/mergeSockets.test.ts +43 -0
- package/tests/visual/README.md +64 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-localGraphRunner-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
- package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
- package/tests/visual/panels.visual.test.tsx +76 -0
- package/tests/wasdPan.test.ts +71 -0
- package/tsconfig.base.json +39 -0
- package/tsconfig.json +18 -59
- package/tsconfig.prod.json +23 -0
- package/tsdown.config.ts +15 -3
- package/typedoc.json +7 -7
- package/vite.config.js +7 -0
- package/vitest.config.ts +5 -2
- package/vitest.visual.config.ts +55 -0
- package/src/components/AutoSizeInput.tsx +0 -65
- package/src/components/Controls.tsx +0 -87
- package/src/components/InputSocket.tsx +0 -142
- package/src/components/Node.tsx +0 -68
- package/src/components/NodeContainer.tsx +0 -46
- package/src/components/NodePicker.tsx +0 -77
- package/src/components/OutputSocket.tsx +0 -58
- package/src/components/modals/ClearModal.tsx +0 -40
- package/src/components/modals/HelpModal.tsx +0 -36
- package/src/components/modals/LoadModal.tsx +0 -96
- package/src/components/modals/Modal.tsx +0 -64
- package/src/components/modals/SaveModal.tsx +0 -60
- package/src/hooks/useCustomNodeTypes.tsx +0 -31
- package/src/hooks/useGraphRunner.ts +0 -104
- package/src/hooks/useMergeMap.ts +0 -14
- package/src/hooks/useNodeSpecJson.ts +0 -20
- package/src/hooks/useQueriableDefinitions.ts +0 -22
- package/src/styles.css +0 -8
- package/tailwind.config.ts +0 -19
- package/tests/tsconfig.json +0 -10
- /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
|
+
}
|