@flowdrop/flowdrop 1.5.0 → 1.7.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/README.md +46 -47
- package/dist/adapters/WorkflowAdapter.d.ts +1 -1
- package/dist/adapters/WorkflowAdapter.js +26 -26
- package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +2 -2
- package/dist/adapters/agentspec/AgentSpecAdapter.js +122 -133
- package/dist/adapters/agentspec/agentAdapter.d.ts +2 -2
- package/dist/adapters/agentspec/agentAdapter.js +10 -10
- package/dist/adapters/agentspec/autoLayout.d.ts +1 -1
- package/dist/adapters/agentspec/autoLayout.js +7 -9
- package/dist/adapters/agentspec/componentTypeDefaults.d.ts +1 -1
- package/dist/adapters/agentspec/componentTypeDefaults.js +120 -120
- package/dist/adapters/agentspec/defaultNodeTypes.d.ts +2 -2
- package/dist/adapters/agentspec/defaultNodeTypes.js +307 -307
- package/dist/adapters/agentspec/index.d.ts +10 -10
- package/dist/adapters/agentspec/index.js +6 -6
- package/dist/adapters/agentspec/validator.d.ts +2 -2
- package/dist/adapters/agentspec/validator.js +20 -22
- package/dist/api/enhanced-client.d.ts +3 -3
- package/dist/api/enhanced-client.js +72 -73
- package/dist/chat/commandClassifier.js +6 -6
- package/dist/chat/index.d.ts +5 -5
- package/dist/chat/index.js +4 -4
- package/dist/chat/responseParser.d.ts +6 -6
- package/dist/chat/responseParser.js +28 -24
- package/dist/commands/batch.d.ts +1 -1
- package/dist/commands/batch.js +5 -7
- package/dist/commands/executor.d.ts +2 -2
- package/dist/commands/executor.js +320 -231
- package/dist/commands/index.d.ts +6 -6
- package/dist/commands/index.js +5 -5
- package/dist/commands/parser.d.ts +1 -1
- package/dist/commands/parser.js +91 -74
- package/dist/commands/positioner.d.ts +2 -2
- package/dist/commands/positioner.js +1 -1
- package/dist/commands/storeIntegration.svelte.d.ts +2 -2
- package/dist/commands/storeIntegration.svelte.js +5 -5
- package/dist/commands/types.d.ts +42 -42
- package/dist/commands/types.js +2 -2
- package/dist/components/App.svelte +280 -303
- package/dist/components/App.svelte.d.ts +11 -9
- package/dist/components/CanvasBanner.stories.svelte +10 -16
- package/dist/components/CanvasBanner.stories.svelte.d.ts +1 -1
- package/dist/components/CanvasBanner.svelte +2 -2
- package/dist/components/CanvasBanner.svelte.d.ts +1 -1
- package/dist/components/CanvasController.svelte +3 -4
- package/dist/components/ConfigForm.svelte +118 -256
- package/dist/components/ConfigForm.svelte.d.ts +2 -2
- package/dist/components/ConfigMappingRow.svelte +7 -9
- package/dist/components/ConfigMappingRow.svelte.d.ts +1 -1
- package/dist/components/ConfigModal.svelte +3 -3
- package/dist/components/ConfigModal.svelte.d.ts +1 -1
- package/dist/components/ConfigPanel.stories.svelte +19 -19
- package/dist/components/ConfigPanel.stories.svelte.d.ts +1 -1
- package/dist/components/ConfigPanel.svelte +9 -20
- package/dist/components/ConfigPanel.svelte.d.ts +1 -1
- package/dist/components/ConnectionLine.svelte +4 -4
- package/dist/components/EdgeRefresher.svelte +1 -1
- package/dist/components/FlowDropEdge.stories.svelte +110 -110
- package/dist/components/FlowDropEdge.svelte +9 -9
- package/dist/components/FlowDropEdge.svelte.d.ts +1 -1
- package/dist/components/FlowDropZone.svelte +6 -9
- package/dist/components/FlowDropZone.svelte.d.ts +1 -1
- package/dist/components/LoadingSpinner.stories.svelte +13 -13
- package/dist/components/LoadingSpinner.stories.svelte.d.ts +1 -1
- package/dist/components/LoadingSpinner.svelte +3 -3
- package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
- package/dist/components/Logo.stories.svelte +4 -4
- package/dist/components/Logo.stories.svelte.d.ts +1 -1
- package/dist/components/Logo.svelte +3 -9
- package/dist/components/LogsSidebar.svelte +41 -48
- package/dist/components/LogsSidebar.svelte.d.ts +1 -1
- package/dist/components/MarkdownDisplay.stories.svelte +10 -14
- package/dist/components/MarkdownDisplay.stories.svelte.d.ts +1 -1
- package/dist/components/MarkdownDisplay.svelte +4 -6
- package/dist/components/Navbar.stories.svelte +19 -19
- package/dist/components/Navbar.stories.svelte.d.ts +1 -1
- package/dist/components/Navbar.svelte +28 -49
- package/dist/components/Navbar.svelte.d.ts +2 -2
- package/dist/components/NodeSidebar.svelte +42 -88
- package/dist/components/NodeSidebar.svelte.d.ts +1 -1
- package/dist/components/NodeStatusOverlay.stories.svelte +19 -31
- package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +1 -1
- package/dist/components/NodeStatusOverlay.svelte +40 -55
- package/dist/components/NodeStatusOverlay.svelte.d.ts +3 -3
- package/dist/components/NodeSwapPicker.svelte +20 -64
- package/dist/components/NodeSwapPicker.svelte.d.ts +1 -1
- package/dist/components/PipelineStatus.svelte +63 -89
- package/dist/components/PipelineStatus.svelte.d.ts +4 -4
- package/dist/components/PortCoordinateTracker.svelte +5 -7
- package/dist/components/PortCoordinateTracker.svelte.d.ts +1 -1
- package/dist/components/PortMappingRow.svelte +20 -24
- package/dist/components/PortMappingRow.svelte.d.ts +2 -2
- package/dist/components/ReadOnlyDetails.svelte +1 -1
- package/dist/components/SchemaForm.stories.svelte +53 -53
- package/dist/components/SchemaForm.stories.svelte.d.ts +1 -1
- package/dist/components/SchemaForm.svelte +24 -51
- package/dist/components/SchemaForm.svelte.d.ts +2 -2
- package/dist/components/SettingsModal.svelte +6 -9
- package/dist/components/SettingsModal.svelte.d.ts +1 -1
- package/dist/components/SettingsPanel.svelte +138 -158
- package/dist/components/SettingsPanel.svelte.d.ts +1 -1
- package/dist/components/StatusIcon.stories.svelte +16 -29
- package/dist/components/StatusIcon.stories.svelte.d.ts +1 -1
- package/dist/components/StatusIcon.svelte +19 -19
- package/dist/components/StatusIcon.svelte.d.ts +2 -2
- package/dist/components/StatusLabel.stories.svelte +8 -8
- package/dist/components/StatusLabel.stories.svelte.d.ts +1 -1
- package/dist/components/SwapMappingEditor.svelte +35 -56
- package/dist/components/SwapMappingEditor.svelte.d.ts +2 -2
- package/dist/components/ThemeToggle.stories.svelte +10 -10
- package/dist/components/ThemeToggle.stories.svelte.d.ts +1 -1
- package/dist/components/ThemeToggle.svelte +22 -33
- package/dist/components/ThemeToggle.svelte.d.ts +1 -1
- package/dist/components/UniversalNode.svelte +29 -41
- package/dist/components/UniversalNode.svelte.d.ts +3 -3
- package/dist/components/WorkflowEditor.svelte +113 -168
- package/dist/components/WorkflowEditor.svelte.d.ts +4 -4
- package/dist/components/chat/AIChatPanel.svelte +272 -133
- package/dist/components/chat/AIChatPanel.svelte.d.ts +3 -3
- package/dist/components/chat/CommandPreview.svelte +74 -24
- package/dist/components/chat/CommandPreview.svelte.d.ts +1 -1
- package/dist/components/console/CommandConsole.stories.svelte +71 -53
- package/dist/components/console/CommandConsole.stories.svelte.d.ts +1 -1
- package/dist/components/console/CommandConsole.svelte +39 -35
- package/dist/components/console/CommandConsole.svelte.d.ts +2 -2
- package/dist/components/console/ConsoleAutocomplete.svelte +6 -3
- package/dist/components/console/ConsoleInput.svelte +148 -89
- package/dist/components/console/ConsoleInput.svelte.d.ts +1 -1
- package/dist/components/console/ConsoleOutput.svelte +5 -10
- package/dist/components/console/ConsoleOutput.svelte.d.ts +1 -1
- package/dist/components/console/formatters.d.ts +1 -1
- package/dist/components/console/formatters.js +27 -29
- package/dist/components/form/FormArray.svelte +75 -132
- package/dist/components/form/FormArray.svelte.d.ts +1 -1
- package/dist/components/form/FormAutocomplete.svelte +65 -108
- package/dist/components/form/FormAutocomplete.svelte.d.ts +1 -1
- package/dist/components/form/FormCheckboxGroup.stories.svelte +13 -16
- package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormCheckboxGroup.svelte +2 -2
- package/dist/components/form/FormCodeEditor.svelte +46 -59
- package/dist/components/form/FormField.svelte +79 -90
- package/dist/components/form/FormField.svelte.d.ts +2 -2
- package/dist/components/form/FormFieldLight.svelte +72 -88
- package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
- package/dist/components/form/FormFieldWrapper.stories.svelte +14 -14
- package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormFieldWrapper.svelte +2 -9
- package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
- package/dist/components/form/FormFieldset.svelte +3 -3
- package/dist/components/form/FormFieldset.svelte.d.ts +2 -2
- package/dist/components/form/FormMarkdownEditor.svelte +123 -156
- package/dist/components/form/FormNumberField.stories.svelte +18 -18
- package/dist/components/form/FormNumberField.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormNumberField.svelte +6 -6
- package/dist/components/form/FormRangeField.stories.svelte +13 -13
- package/dist/components/form/FormRangeField.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormRangeField.svelte +4 -12
- package/dist/components/form/FormSelect.stories.svelte +21 -21
- package/dist/components/form/FormSelect.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormSelect.svelte +5 -5
- package/dist/components/form/FormSelect.svelte.d.ts +1 -1
- package/dist/components/form/FormTemplateEditor.svelte +126 -175
- package/dist/components/form/FormTemplateEditor.svelte.d.ts +1 -1
- package/dist/components/form/FormTextField.stories.svelte +17 -23
- package/dist/components/form/FormTextField.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormTextField.svelte +4 -4
- package/dist/components/form/FormTextarea.stories.svelte +18 -21
- package/dist/components/form/FormTextarea.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormTextarea.svelte +4 -4
- package/dist/components/form/FormToggle.stories.svelte +13 -16
- package/dist/components/form/FormToggle.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormToggle.svelte +3 -3
- package/dist/components/form/FormUISchemaRenderer.svelte +12 -19
- package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +3 -3
- package/dist/components/form/index.d.ts +19 -19
- package/dist/components/form/index.js +18 -18
- package/dist/components/form/templateAutocomplete.d.ts +2 -2
- package/dist/components/form/templateAutocomplete.js +55 -64
- package/dist/components/form/types.d.ts +6 -6
- package/dist/components/form/types.js +4 -9
- package/dist/components/icons/AlertCircleIcon.svelte +1 -6
- package/dist/components/icons/CogIcon.svelte +1 -6
- package/dist/components/interrupt/ChoicePrompt.stories.svelte +27 -27
- package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +1 -1
- package/dist/components/interrupt/ChoicePrompt.svelte +17 -41
- package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +17 -17
- package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +1 -1
- package/dist/components/interrupt/ConfirmationPrompt.svelte +10 -16
- package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/FormPrompt.svelte +10 -15
- package/dist/components/interrupt/FormPrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/InterruptBubble.svelte +87 -121
- package/dist/components/interrupt/InterruptBubble.svelte.d.ts +2 -2
- package/dist/components/interrupt/ReviewPrompt.stories.svelte +37 -37
- package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +1 -1
- package/dist/components/interrupt/ReviewPrompt.svelte +55 -75
- package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/TextInputPrompt.stories.svelte +16 -17
- package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +1 -1
- package/dist/components/interrupt/TextInputPrompt.svelte +13 -18
- package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/index.d.ts +6 -6
- package/dist/components/interrupt/index.js +6 -6
- package/dist/components/layouts/MainLayout.svelte +46 -84
- package/dist/components/layouts/MainLayout.svelte.d.ts +6 -6
- package/dist/components/nodes/GatewayNode.stories.svelte +64 -65
- package/dist/components/nodes/GatewayNode.svelte +37 -70
- package/dist/components/nodes/GatewayNode.svelte.d.ts +3 -3
- package/dist/components/nodes/IdeaNode.stories.svelte +25 -26
- package/dist/components/nodes/IdeaNode.svelte +22 -36
- package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
- package/dist/components/nodes/NotesNode.stories.svelte +37 -38
- package/dist/components/nodes/NotesNode.svelte +28 -39
- package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
- package/dist/components/nodes/SimpleNode.stories.svelte +137 -138
- package/dist/components/nodes/SimpleNode.svelte +51 -81
- package/dist/components/nodes/SimpleNode.svelte.d.ts +1 -1
- package/dist/components/nodes/SquareNode.stories.svelte +75 -75
- package/dist/components/nodes/SquareNode.svelte +42 -68
- package/dist/components/nodes/SquareNode.svelte.d.ts +1 -1
- package/dist/components/nodes/TerminalNode.stories.svelte +10 -10
- package/dist/components/nodes/TerminalNode.svelte +74 -112
- package/dist/components/nodes/TerminalNode.svelte.d.ts +1 -1
- package/dist/components/nodes/ToolNode.stories.svelte +115 -116
- package/dist/components/nodes/ToolNode.svelte +31 -64
- package/dist/components/nodes/ToolNode.svelte.d.ts +1 -1
- package/dist/components/nodes/WorkflowNode.stories.svelte +84 -89
- package/dist/components/nodes/WorkflowNode.svelte +50 -103
- package/dist/components/nodes/WorkflowNode.svelte.d.ts +3 -3
- package/dist/components/playground/ChatPanel.svelte +47 -103
- package/dist/components/playground/ExecutionLogs.svelte +45 -68
- package/dist/components/playground/InputCollector.svelte +32 -51
- package/dist/components/playground/MessageBubble.stories.svelte +25 -25
- package/dist/components/playground/MessageBubble.stories.svelte.d.ts +1 -1
- package/dist/components/playground/MessageBubble.svelte +54 -70
- package/dist/components/playground/MessageBubble.svelte.d.ts +1 -1
- package/dist/components/playground/Playground.svelte +60 -91
- package/dist/components/playground/Playground.svelte.d.ts +3 -3
- package/dist/components/playground/PlaygroundModal.svelte +8 -12
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
- package/dist/components/playground/SessionManager.svelte +34 -40
- package/dist/components/playground/SessionManager.svelte.d.ts +1 -1
- package/dist/config/agentSpecEndpoints.d.ts +1 -1
- package/dist/config/agentSpecEndpoints.js +20 -20
- package/dist/config/constants.js +2 -2
- package/dist/config/defaultCategories.d.ts +1 -1
- package/dist/config/defaultCategories.js +86 -86
- package/dist/config/defaultPortConfig.d.ts +1 -1
- package/dist/config/defaultPortConfig.js +144 -144
- package/dist/config/endpoints.d.ts +4 -4
- package/dist/config/endpoints.js +68 -68
- package/dist/config/runtimeConfig.d.ts +2 -2
- package/dist/config/runtimeConfig.js +8 -8
- package/dist/core/index.d.ts +68 -68
- package/dist/core/index.js +38 -38
- package/dist/display/index.d.ts +2 -2
- package/dist/display/index.js +2 -2
- package/dist/editor/index.d.ts +64 -64
- package/dist/editor/index.js +54 -54
- package/dist/form/code.d.ts +5 -5
- package/dist/form/code.js +14 -14
- package/dist/form/fieldRegistry.d.ts +3 -3
- package/dist/form/fieldRegistry.js +9 -11
- package/dist/form/full.d.ts +8 -8
- package/dist/form/full.js +9 -9
- package/dist/form/index.d.ts +18 -18
- package/dist/form/index.js +16 -16
- package/dist/form/markdown.d.ts +4 -4
- package/dist/form/markdown.js +8 -8
- package/dist/helpers/proximityConnect.d.ts +3 -3
- package/dist/helpers/proximityConnect.js +32 -34
- package/dist/helpers/workflowEditorHelper.d.ts +6 -6
- package/dist/helpers/workflowEditorHelper.js +64 -68
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -6
- package/dist/mocks/app-environment.js +2 -2
- package/dist/mocks/app-forms.js +1 -1
- package/dist/mocks/app-navigation.js +2 -2
- package/dist/mocks/app-stores.js +3 -3
- package/dist/playground/index.d.ts +19 -19
- package/dist/playground/index.js +16 -16
- package/dist/playground/mount.d.ts +3 -3
- package/dist/playground/mount.js +24 -24
- package/dist/registry/builtinFormats.js +13 -13
- package/dist/registry/builtinNodes.d.ts +2 -2
- package/dist/registry/builtinNodes.js +77 -77
- package/dist/registry/index.d.ts +4 -4
- package/dist/registry/index.js +4 -4
- package/dist/registry/nodeComponentRegistry.d.ts +8 -8
- package/dist/registry/nodeComponentRegistry.js +9 -11
- package/dist/registry/plugin.d.ts +2 -2
- package/dist/registry/plugin.js +11 -11
- package/dist/registry/workflowFormatRegistry.d.ts +3 -3
- package/dist/registry/workflowFormatRegistry.js +2 -2
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +2 -2
- package/dist/schemas/v1/workflow.schema.json +5 -0
- package/dist/services/agentSpecExecutionService.d.ts +3 -3
- package/dist/services/agentSpecExecutionService.js +55 -56
- package/dist/services/api.d.ts +2 -2
- package/dist/services/api.js +37 -37
- package/dist/services/apiVariableService.d.ts +1 -1
- package/dist/services/apiVariableService.js +34 -41
- package/dist/services/autoSaveService.js +8 -8
- package/dist/services/categoriesApi.d.ts +2 -2
- package/dist/services/categoriesApi.js +8 -8
- package/dist/services/chatService.d.ts +1 -1
- package/dist/services/chatService.js +18 -18
- package/dist/services/draftStorage.d.ts +1 -1
- package/dist/services/draftStorage.js +11 -11
- package/dist/services/dynamicSchemaService.d.ts +1 -1
- package/dist/services/dynamicSchemaService.js +39 -41
- package/dist/services/globalSave.d.ts +2 -2
- package/dist/services/globalSave.js +38 -41
- package/dist/services/historyService.d.ts +1 -1
- package/dist/services/historyService.js +10 -10
- package/dist/services/interruptService.d.ts +1 -1
- package/dist/services/interruptService.js +29 -35
- package/dist/services/nodeExecutionService.d.ts +1 -1
- package/dist/services/nodeExecutionService.js +44 -45
- package/dist/services/playgroundService.d.ts +1 -1
- package/dist/services/playgroundService.js +29 -29
- package/dist/services/portConfigApi.d.ts +2 -2
- package/dist/services/portConfigApi.js +8 -8
- package/dist/services/settingsService.d.ts +2 -2
- package/dist/services/settingsService.js +19 -25
- package/dist/services/toastService.d.ts +4 -4
- package/dist/services/toastService.js +33 -33
- package/dist/services/variableService.d.ts +1 -1
- package/dist/services/variableService.js +36 -36
- package/dist/services/workflowStorage.d.ts +2 -2
- package/dist/services/workflowStorage.js +13 -13
- package/dist/settings/index.d.ts +7 -7
- package/dist/settings/index.js +6 -6
- package/dist/skins/default.d.ts +1 -1
- package/dist/skins/default.js +1 -1
- package/dist/skins/index.d.ts +3 -3
- package/dist/skins/index.js +7 -7
- package/dist/skins/slate.d.ts +1 -1
- package/dist/skins/slate.js +69 -69
- package/dist/stores/categoriesStore.svelte.d.ts +1 -1
- package/dist/stores/categoriesStore.svelte.js +5 -5
- package/dist/stores/editorStateMachine.svelte.d.ts +2 -2
- package/dist/stores/editorStateMachine.svelte.js +34 -34
- package/dist/stores/historyStore.svelte.d.ts +4 -4
- package/dist/stores/historyStore.svelte.js +4 -4
- package/dist/stores/interruptStore.svelte.d.ts +3 -3
- package/dist/stores/interruptStore.svelte.js +21 -21
- package/dist/stores/playgroundStore.svelte.d.ts +2 -2
- package/dist/stores/playgroundStore.svelte.js +18 -21
- package/dist/stores/portCoordinateStore.svelte.d.ts +2 -2
- package/dist/stores/portCoordinateStore.svelte.js +10 -13
- package/dist/stores/settingsStore.svelte.d.ts +2 -2
- package/dist/stores/settingsStore.svelte.js +57 -62
- package/dist/stores/workflowStore.svelte.d.ts +4 -3
- package/dist/stores/workflowStore.svelte.js +47 -47
- package/dist/stories/CanvasDecorator.svelte +7 -10
- package/dist/stories/CanvasDecorator.svelte.d.ts +2 -2
- package/dist/stories/EdgeDecorator.svelte +28 -31
- package/dist/stories/EdgeDecorator.svelte.d.ts +1 -1
- package/dist/stories/NodeDecorator.svelte +14 -20
- package/dist/stories/NodeDecorator.svelte.d.ts +1 -1
- package/dist/stories/utils.d.ts +2 -2
- package/dist/stories/utils.js +89 -93
- package/dist/styles/base.css +16 -50
- package/dist/styles/tokens.css +10 -28
- package/dist/svelte-app.d.ts +10 -10
- package/dist/svelte-app.js +39 -39
- package/dist/themes/default.d.ts +1 -1
- package/dist/themes/default.js +4 -4
- package/dist/themes/index.d.ts +3 -3
- package/dist/themes/index.js +11 -11
- package/dist/themes/minimal.d.ts +1 -1
- package/dist/themes/minimal.js +5 -5
- package/dist/types/agentspec.d.ts +18 -18
- package/dist/types/agentspec.js +2 -2
- package/dist/types/auth.d.ts +1 -1
- package/dist/types/auth.js +6 -6
- package/dist/types/chat.d.ts +2 -2
- package/dist/types/config.d.ts +6 -6
- package/dist/types/events.d.ts +3 -3
- package/dist/types/events.js +2 -2
- package/dist/types/index.d.ts +34 -32
- package/dist/types/index.js +6 -6
- package/dist/types/interrupt.d.ts +6 -6
- package/dist/types/interrupt.js +21 -21
- package/dist/types/interruptState.d.ts +12 -12
- package/dist/types/interruptState.js +66 -66
- package/dist/types/playground.d.ts +7 -7
- package/dist/types/playground.js +14 -14
- package/dist/types/settings.d.ts +7 -5
- package/dist/types/settings.js +19 -24
- package/dist/types/skin.d.ts +1 -1
- package/dist/types/theme.d.ts +2 -2
- package/dist/types/uischema.d.ts +4 -4
- package/dist/types/uischema.js +3 -3
- package/dist/utils/colors.d.ts +1 -1
- package/dist/utils/colors.js +95 -97
- package/dist/utils/config.d.ts +2 -2
- package/dist/utils/config.js +48 -48
- package/dist/utils/connections.d.ts +6 -2
- package/dist/utils/connections.js +21 -15
- package/dist/utils/edgeStyling.d.ts +2 -2
- package/dist/utils/edgeStyling.js +36 -39
- package/dist/utils/errors.js +3 -3
- package/dist/utils/fetchWithAuth.d.ts +1 -1
- package/dist/utils/fetchWithAuth.js +2 -2
- package/dist/utils/handleIds.d.ts +2 -2
- package/dist/utils/handleIds.js +8 -8
- package/dist/utils/handlePositioning.d.ts +1 -1
- package/dist/utils/handlePositioning.js +2 -2
- package/dist/utils/icons.d.ts +1 -1
- package/dist/utils/icons.js +74 -74
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +7 -7
- package/dist/utils/nodeIds.d.ts +1 -1
- package/dist/utils/nodeIds.js +1 -1
- package/dist/utils/nodeStatus.d.ts +1 -1
- package/dist/utils/nodeStatus.js +48 -48
- package/dist/utils/nodeSwap.d.ts +9 -9
- package/dist/utils/nodeSwap.js +52 -58
- package/dist/utils/nodeTypes.d.ts +1 -1
- package/dist/utils/nodeTypes.js +20 -21
- package/dist/utils/nodeWrapper.d.ts +7 -7
- package/dist/utils/nodeWrapper.js +19 -21
- package/dist/utils/performanceUtils.d.ts +1 -1
- package/dist/utils/performanceUtils.js +1 -2
- package/dist/utils/portUtils.d.ts +2 -2
- package/dist/utils/portUtils.js +1 -1
- package/dist/utils/sanitize.js +1 -1
- package/dist/utils/uischema.d.ts +2 -2
- package/dist/utils/uischema.js +8 -8
- package/dist/utils/validation.js +8 -8
- package/package.json +7 -11
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module commands/executor
|
|
8
8
|
*/
|
|
9
|
-
import { generateNodeId } from
|
|
10
|
-
import { extractConfigDefaults } from
|
|
11
|
-
import { computeAutoPosition } from
|
|
12
|
-
import { buildHandleId, extractPortId } from
|
|
13
|
-
import { applyConnectionStyling } from
|
|
14
|
-
import { computeSwapPreview, executeSwap } from
|
|
15
|
-
import { computeAutoLayout, computeBeautifyLayout } from
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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 !==
|
|
175
|
+
if (raw !== '' && !isNaN(Number(raw))) {
|
|
176
176
|
return Number(raw);
|
|
177
177
|
}
|
|
178
178
|
// Boolean
|
|
179
|
-
if (raw ===
|
|
179
|
+
if (raw === 'true')
|
|
180
180
|
return true;
|
|
181
|
-
if (raw ===
|
|
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:
|
|
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) ?
|
|
207
|
-
const expectedType = 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 ===
|
|
211
|
+
!(expectedType === 'object' && actualType === 'object')) {
|
|
212
212
|
warnings.push({
|
|
213
|
-
type:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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 ===
|
|
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:
|
|
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:
|
|
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:
|
|
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 ===
|
|
386
|
+
if (preferDirection === 'output') {
|
|
387
387
|
if (outputPort)
|
|
388
|
-
return { port: outputPort, direction:
|
|
388
|
+
return { port: outputPort, direction: 'output' };
|
|
389
389
|
if (inputPort)
|
|
390
|
-
return { port: inputPort, direction:
|
|
390
|
+
return { port: inputPort, direction: 'input' };
|
|
391
391
|
}
|
|
392
|
-
else if (preferDirection ===
|
|
392
|
+
else if (preferDirection === 'input') {
|
|
393
393
|
if (inputPort)
|
|
394
|
-
return { port: inputPort, direction:
|
|
394
|
+
return { port: inputPort, direction: 'input' };
|
|
395
395
|
if (outputPort)
|
|
396
|
-
return { port: outputPort, direction:
|
|
396
|
+
return { port: outputPort, direction: 'output' };
|
|
397
397
|
}
|
|
398
398
|
else {
|
|
399
399
|
if (outputPort)
|
|
400
|
-
return { port: outputPort, direction:
|
|
400
|
+
return { port: outputPort, direction: 'output' };
|
|
401
401
|
if (inputPort)
|
|
402
|
-
return { port: inputPort, direction:
|
|
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 ===
|
|
405
|
+
if (metadata.type === 'gateway') {
|
|
406
406
|
const branches = node.data.config?.branches;
|
|
407
407
|
if (branches?.some((b) => b.name === portId)) {
|
|
408
|
-
return {
|
|
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:
|
|
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:
|
|
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:
|
|
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,
|
|
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:
|
|
447
|
+
code: 'PORT_NOT_FOUND'
|
|
445
448
|
};
|
|
446
449
|
}
|
|
447
|
-
const targetPortInfo = findPort(targetNode, command.targetPort,
|
|
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:
|
|
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 !==
|
|
459
|
+
if (sourcePortInfo.direction !== 'output' || targetPortInfo.direction !== 'input') {
|
|
457
460
|
// Check if they're reversed
|
|
458
|
-
if (sourcePortInfo.direction ===
|
|
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:
|
|
465
|
+
code: 'INVALID_CONNECTION'
|
|
463
466
|
};
|
|
464
467
|
}
|
|
465
468
|
// One of them is the wrong direction
|
|
466
|
-
if (sourcePortInfo.direction !==
|
|
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:
|
|
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:
|
|
479
|
+
code: 'INVALID_CONNECTION'
|
|
477
480
|
};
|
|
478
481
|
}
|
|
479
482
|
// Build handle IDs
|
|
480
|
-
const sourceHandle = buildHandleId(sourceNode.id,
|
|
481
|
-
const targetHandle = buildHandleId(targetNode.id,
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
?
|
|
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:
|
|
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
|
-
|
|
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
|
-
{
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
{
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
{
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
{
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
{
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
{
|
|
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:
|
|
684
|
-
code:
|
|
774
|
+
error: 'Nothing to undo',
|
|
775
|
+
code: 'UNDO_UNAVAILABLE'
|
|
685
776
|
};
|
|
686
777
|
}
|
|
687
|
-
return { ok: true, message:
|
|
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:
|
|
695
|
-
code:
|
|
785
|
+
error: 'Nothing to redo',
|
|
786
|
+
code: 'REDO_UNAVAILABLE'
|
|
696
787
|
};
|
|
697
788
|
}
|
|
698
|
-
return { ok: true, message:
|
|
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:
|
|
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:
|
|
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:
|
|
814
|
+
code: 'NODE_NOT_FOUND'
|
|
724
815
|
};
|
|
725
816
|
}
|
|
726
817
|
if (context.dispatch.emitUIAction) {
|
|
727
|
-
context.dispatch.emitUIAction({ type:
|
|
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:
|
|
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:
|
|
840
|
+
code: 'NODE_NOT_FOUND'
|
|
750
841
|
};
|
|
751
842
|
}
|
|
752
843
|
if (context.dispatch.emitUIAction) {
|
|
753
|
-
context.dispatch.emitUIAction({ type:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
935
|
+
return { ok: true, message: 'No nodes to layout' };
|
|
847
936
|
}
|
|
848
|
-
const isVertical = command.direction ===
|
|
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 ??
|
|
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:
|
|
864
|
-
name:
|
|
952
|
+
component_type: 'flow',
|
|
953
|
+
name: 'layout',
|
|
865
954
|
start_node: startNode,
|
|
866
955
|
nodes: workflow.nodes.map((n) => ({
|
|
867
|
-
component_type:
|
|
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 ??
|
|
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:
|
|
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:
|
|
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:
|
|
1043
|
+
return emitCanvasAction(context, { type: 'canvas_fit_view' }, 'Fit view applied');
|
|
955
1044
|
}
|
|
956
1045
|
function executeCanvasZoomIn(context) {
|
|
957
|
-
return emitCanvasAction(context, { type:
|
|
1046
|
+
return emitCanvasAction(context, { type: 'canvas_zoom_in' }, 'Zoomed in');
|
|
958
1047
|
}
|
|
959
1048
|
function executeCanvasZoomOut(context) {
|
|
960
|
-
return emitCanvasAction(context, { type:
|
|
1049
|
+
return emitCanvasAction(context, { type: 'canvas_zoom_out' }, 'Zoomed out');
|
|
961
1050
|
}
|
|
962
1051
|
function executeCanvasZoomTo(command, context) {
|
|
963
|
-
return emitCanvasAction(context, { type:
|
|
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:
|
|
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:
|
|
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
|
|
1068
|
+
case 'add_node':
|
|
980
1069
|
return executeAddNode(command, context);
|
|
981
|
-
case
|
|
1070
|
+
case 'delete_node':
|
|
982
1071
|
return executeDeleteNode(command, context);
|
|
983
|
-
case
|
|
1072
|
+
case 'rename_node':
|
|
984
1073
|
return executeRenameNode(command, context);
|
|
985
|
-
case
|
|
1074
|
+
case 'set_config':
|
|
986
1075
|
return executeSetConfig(command, context);
|
|
987
|
-
case
|
|
1076
|
+
case 'get_config':
|
|
988
1077
|
return executeGetConfig(command, context);
|
|
989
|
-
case
|
|
1078
|
+
case 'info':
|
|
990
1079
|
return executeInfo(command, context);
|
|
991
|
-
case
|
|
1080
|
+
case 'connect':
|
|
992
1081
|
return executeConnect(command, context);
|
|
993
|
-
case
|
|
1082
|
+
case 'disconnect_ports':
|
|
994
1083
|
return executeDisconnectPorts(command, context);
|
|
995
|
-
case
|
|
1084
|
+
case 'disconnect_node':
|
|
996
1085
|
return executeDisconnectNode(command, context);
|
|
997
|
-
case
|
|
1086
|
+
case 'list_nodes':
|
|
998
1087
|
return executeListNodes(context);
|
|
999
|
-
case
|
|
1088
|
+
case 'list_edges':
|
|
1000
1089
|
return executeListEdges(context);
|
|
1001
|
-
case
|
|
1090
|
+
case 'list_types':
|
|
1002
1091
|
return executeListTypes(context);
|
|
1003
|
-
case
|
|
1092
|
+
case 'help':
|
|
1004
1093
|
return executeHelp(command);
|
|
1005
|
-
case
|
|
1094
|
+
case 'undo':
|
|
1006
1095
|
return executeUndo(context);
|
|
1007
|
-
case
|
|
1096
|
+
case 'redo':
|
|
1008
1097
|
return executeRedo(context);
|
|
1009
|
-
case
|
|
1098
|
+
case 'clear':
|
|
1010
1099
|
return executeClear(context);
|
|
1011
|
-
case
|
|
1100
|
+
case 'config_open':
|
|
1012
1101
|
return executeConfigOpen(command, context);
|
|
1013
|
-
case
|
|
1102
|
+
case 'select_node':
|
|
1014
1103
|
return executeSelectNode(command, context);
|
|
1015
|
-
case
|
|
1104
|
+
case 'swap_node':
|
|
1016
1105
|
return executeSwapNode(command, context);
|
|
1017
|
-
case
|
|
1106
|
+
case 'move_node':
|
|
1018
1107
|
return executeMoveNode(command, context);
|
|
1019
|
-
case
|
|
1108
|
+
case 'auto_layout':
|
|
1020
1109
|
return executeAutoLayout(command, context);
|
|
1021
|
-
case
|
|
1110
|
+
case 'beautify_layout':
|
|
1022
1111
|
return executeBeautifyLayout(command, context);
|
|
1023
|
-
case
|
|
1112
|
+
case 'canvas_fit_view':
|
|
1024
1113
|
return executeCanvasFitView(context);
|
|
1025
|
-
case
|
|
1114
|
+
case 'canvas_zoom_in':
|
|
1026
1115
|
return executeCanvasZoomIn(context);
|
|
1027
|
-
case
|
|
1116
|
+
case 'canvas_zoom_out':
|
|
1028
1117
|
return executeCanvasZoomOut(context);
|
|
1029
|
-
case
|
|
1118
|
+
case 'canvas_zoom_to':
|
|
1030
1119
|
return executeCanvasZoomTo(command, context);
|
|
1031
|
-
case
|
|
1120
|
+
case 'canvas_pan_to':
|
|
1032
1121
|
return executeCanvasPanTo(command, context);
|
|
1033
|
-
case
|
|
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:
|
|
1129
|
+
code: 'UNKNOWN_COMMAND'
|
|
1041
1130
|
};
|
|
1042
1131
|
}
|
|
1043
1132
|
}
|