@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
|
@@ -5,71 +5,66 @@
|
|
|
5
5
|
-->
|
|
6
6
|
|
|
7
7
|
<script lang="ts">
|
|
8
|
-
import { onMount, tick } from
|
|
9
|
-
import MainLayout from
|
|
10
|
-
import WorkflowEditor from
|
|
11
|
-
import NodeSidebar from
|
|
12
|
-
import Icon from
|
|
13
|
-
import ConfigForm from
|
|
14
|
-
import ConfigPanel from
|
|
15
|
-
import CommandConsole from
|
|
16
|
-
import AIChatPanel from
|
|
17
|
-
import type { UIAction } from
|
|
18
|
-
import NodeSwapPicker from
|
|
19
|
-
import SwapMappingEditor from
|
|
20
|
-
import Navbar from
|
|
21
|
-
import { api, setEndpointConfig } from
|
|
22
|
-
import { EnhancedFlowDropApiClient } from
|
|
8
|
+
import { onMount, tick } from 'svelte';
|
|
9
|
+
import MainLayout from './layouts/MainLayout.svelte';
|
|
10
|
+
import WorkflowEditor from './WorkflowEditor.svelte';
|
|
11
|
+
import NodeSidebar from './NodeSidebar.svelte';
|
|
12
|
+
import Icon from '@iconify/svelte';
|
|
13
|
+
import ConfigForm from './ConfigForm.svelte';
|
|
14
|
+
import ConfigPanel from './ConfigPanel.svelte';
|
|
15
|
+
import CommandConsole from './console/CommandConsole.svelte';
|
|
16
|
+
import AIChatPanel from './chat/AIChatPanel.svelte';
|
|
17
|
+
import type { UIAction } from '../commands/index.js';
|
|
18
|
+
import NodeSwapPicker from './NodeSwapPicker.svelte';
|
|
19
|
+
import SwapMappingEditor from './SwapMappingEditor.svelte';
|
|
20
|
+
import Navbar from './Navbar.svelte';
|
|
21
|
+
import { api, setEndpointConfig } from '../services/api.js';
|
|
22
|
+
import { EnhancedFlowDropApiClient } from '../api/enhanced-client.js';
|
|
23
23
|
import type {
|
|
24
24
|
NodeMetadata,
|
|
25
25
|
Workflow,
|
|
26
26
|
WorkflowNode,
|
|
27
27
|
ConfigSchema,
|
|
28
|
-
NodeUIExtensions
|
|
29
|
-
} from
|
|
30
|
-
import type { InteractiveSwapState, SwapEventContext } from
|
|
28
|
+
NodeUIExtensions
|
|
29
|
+
} from '../types/index.js';
|
|
30
|
+
import type { InteractiveSwapState, SwapEventContext } from '../utils/nodeSwap.js';
|
|
31
31
|
import {
|
|
32
32
|
computeInteractiveState,
|
|
33
33
|
buildSwapPreviewFromState,
|
|
34
34
|
executeSwap,
|
|
35
|
-
validateSwapResult
|
|
36
|
-
} from
|
|
37
|
-
import type { SwapStrategy } from
|
|
38
|
-
import { DEFAULT_WORKFLOW_FORMAT } from
|
|
39
|
-
import { createEndpointConfig } from
|
|
40
|
-
import type { EndpointConfig } from
|
|
41
|
-
import type { AuthProvider } from
|
|
42
|
-
import type {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
} from
|
|
46
|
-
import {
|
|
47
|
-
import type { FlowDropTheme, FlowDropThemeName } from "../types/theme.js";
|
|
48
|
-
import type { FlowDropSkinTokens } from "../types/skin.js";
|
|
49
|
-
import { resolveTheme } from "../themes/index.js";
|
|
35
|
+
validateSwapResult
|
|
36
|
+
} from '../utils/nodeSwap.js';
|
|
37
|
+
import type { SwapStrategy } from '../utils/nodeSwap.js';
|
|
38
|
+
import { DEFAULT_WORKFLOW_FORMAT } from '../types/index.js';
|
|
39
|
+
import { createEndpointConfig } from '../config/endpoints.js';
|
|
40
|
+
import type { EndpointConfig } from '../config/endpoints.js';
|
|
41
|
+
import type { AuthProvider } from '../types/auth.js';
|
|
42
|
+
import type { FlowDropEventHandlers, FlowDropFeatures } from '../types/events.js';
|
|
43
|
+
import { mergeFeatures } from '../types/events.js';
|
|
44
|
+
import type { FlowDropTheme, FlowDropThemeName } from '../types/theme.js';
|
|
45
|
+
import type { FlowDropSkinTokens } from '../types/skin.js';
|
|
46
|
+
import { resolveTheme } from '../themes/index.js';
|
|
50
47
|
import {
|
|
51
48
|
getWorkflowStore,
|
|
52
49
|
workflowActions,
|
|
53
50
|
getWorkflowName,
|
|
54
51
|
getWorkflowFormat,
|
|
55
|
-
markAsSaved
|
|
56
|
-
} from
|
|
57
|
-
import {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
} from
|
|
61
|
-
import { apiToasts, dismissToast } from "../services/toastService.js";
|
|
62
|
-
import { initAutoSave } from "../services/autoSaveService.js";
|
|
52
|
+
markAsSaved
|
|
53
|
+
} from '../stores/workflowStore.svelte.js';
|
|
54
|
+
import { globalSaveWorkflow, globalExportWorkflow } from '../services/globalSave.js';
|
|
55
|
+
import { apiToasts, dismissToast } from '../services/toastService.js';
|
|
56
|
+
import { initAutoSave } from '../services/autoSaveService.js';
|
|
57
|
+
import { getUiSettings, updateSettings } from '../stores/settingsStore.svelte.js';
|
|
63
58
|
import {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
import { DEFAULT_PORT_CONFIG } from
|
|
69
|
-
import { workflowFormatRegistry } from
|
|
70
|
-
import { logger } from
|
|
71
|
-
import { validateWorkflowData } from
|
|
72
|
-
import type { SettingsCategory } from
|
|
59
|
+
initializePortCompatibility,
|
|
60
|
+
getPortCompatibilityChecker,
|
|
61
|
+
isPortCompatibilityInitialized
|
|
62
|
+
} from '../utils/connections.js';
|
|
63
|
+
import { DEFAULT_PORT_CONFIG } from '../config/defaultPortConfig.js';
|
|
64
|
+
import { workflowFormatRegistry } from '../registry/workflowFormatRegistry.js';
|
|
65
|
+
import { logger } from '../utils/logger.js';
|
|
66
|
+
import { validateWorkflowData } from '../utils/validation.js';
|
|
67
|
+
import type { SettingsCategory } from '../types/settings.js';
|
|
73
68
|
|
|
74
69
|
/**
|
|
75
70
|
* Configuration props for runtime customization
|
|
@@ -92,10 +87,7 @@
|
|
|
92
87
|
/** Read-only mode */
|
|
93
88
|
readOnly?: boolean;
|
|
94
89
|
/** Node execution statuses */
|
|
95
|
-
nodeStatuses?: Record<
|
|
96
|
-
string,
|
|
97
|
-
"pending" | "running" | "completed" | "error"
|
|
98
|
-
>;
|
|
90
|
+
nodeStatuses?: Record<string, 'pending' | 'running' | 'completed' | 'error'>;
|
|
99
91
|
/** Pipeline ID for fetching node execution info */
|
|
100
92
|
pipelineId?: string;
|
|
101
93
|
/** Custom navbar title */
|
|
@@ -105,7 +97,7 @@
|
|
|
105
97
|
label: string;
|
|
106
98
|
href: string;
|
|
107
99
|
icon?: string;
|
|
108
|
-
variant?:
|
|
100
|
+
variant?: 'primary' | 'secondary' | 'outline';
|
|
109
101
|
onclick?: (event: Event) => void;
|
|
110
102
|
}>;
|
|
111
103
|
/** Show settings gear icon in navbar */
|
|
@@ -130,13 +122,15 @@
|
|
|
130
122
|
showSettingsResetButton?: boolean;
|
|
131
123
|
/** Pluggable swap strategies — instance-scoped, checked in order */
|
|
132
124
|
swapStrategies?: SwapStrategy[];
|
|
125
|
+
/** Additional JSON Schema properties to show in the Workflow Settings panel. Values are persisted in workflow.config. */
|
|
126
|
+
workflowSettingsSchema?: ConfigSchema;
|
|
133
127
|
}
|
|
134
128
|
|
|
135
129
|
let {
|
|
136
130
|
workflow: initialWorkflow,
|
|
137
131
|
nodes: propNodes,
|
|
138
|
-
height =
|
|
139
|
-
width =
|
|
132
|
+
height = '100vh',
|
|
133
|
+
width = '100%',
|
|
140
134
|
showNavbar = false,
|
|
141
135
|
disableSidebar = false,
|
|
142
136
|
lockWorkflow = false,
|
|
@@ -156,6 +150,7 @@
|
|
|
156
150
|
showSettingsSyncButton,
|
|
157
151
|
showSettingsResetButton,
|
|
158
152
|
swapStrategies,
|
|
153
|
+
workflowSettingsSchema
|
|
159
154
|
}: Props = $props();
|
|
160
155
|
|
|
161
156
|
// svelte-ignore state_referenced_locally — feature flags don't change at runtime
|
|
@@ -163,9 +158,7 @@
|
|
|
163
158
|
|
|
164
159
|
// Theme system — resolve named theme or custom object, inject CSS tokens from skin
|
|
165
160
|
// Explicit prop wins; falls back to user's persisted theme preference from settings
|
|
166
|
-
let resolvedTheme = $derived(
|
|
167
|
-
resolveTheme(themeProp ?? getUiSettings().theme),
|
|
168
|
-
);
|
|
161
|
+
let resolvedTheme = $derived(resolveTheme(themeProp ?? getUiSettings().theme));
|
|
169
162
|
let themeConfig = $derived(resolvedTheme.config);
|
|
170
163
|
|
|
171
164
|
// Inject skin tokens as a style tag so light/dark palettes can coexist.
|
|
@@ -176,19 +169,19 @@
|
|
|
176
169
|
const skin = resolvedTheme.skin;
|
|
177
170
|
const tokens = skin?.tokens;
|
|
178
171
|
const darkTokens = skin?.darkTokens;
|
|
179
|
-
if ((!tokens && !darkTokens) || typeof document ===
|
|
172
|
+
if ((!tokens && !darkTokens) || typeof document === 'undefined') return;
|
|
180
173
|
|
|
181
174
|
const toRules = (dict: FlowDropSkinTokens) =>
|
|
182
175
|
Object.entries(dict)
|
|
183
176
|
.map(([k, v]) => ` --fd-${k}: ${v};`)
|
|
184
|
-
.join(
|
|
177
|
+
.join('\n');
|
|
185
178
|
|
|
186
|
-
let css =
|
|
179
|
+
let css = '';
|
|
187
180
|
if (tokens) css += `:root {\n${toRules(tokens)}\n}\n`;
|
|
188
181
|
if (darkTokens) css += `[data-theme='dark'] {\n${toRules(darkTokens)}\n}\n`;
|
|
189
182
|
|
|
190
|
-
const style = document.createElement(
|
|
191
|
-
style.id =
|
|
183
|
+
const style = document.createElement('style');
|
|
184
|
+
style.id = 'fd-skin-tokens';
|
|
192
185
|
document.head.appendChild(style);
|
|
193
186
|
style.textContent = css;
|
|
194
187
|
|
|
@@ -203,8 +196,8 @@
|
|
|
203
196
|
}
|
|
204
197
|
// Default workflow title logic
|
|
205
198
|
const wfName = getWorkflowName();
|
|
206
|
-
if (!wfName || wfName ===
|
|
207
|
-
return
|
|
199
|
+
if (!wfName || wfName === 'Untitled Workflow') {
|
|
200
|
+
return 'Workflow / New Workflow';
|
|
208
201
|
}
|
|
209
202
|
return `Workflow / ${wfName}`;
|
|
210
203
|
});
|
|
@@ -230,43 +223,64 @@
|
|
|
230
223
|
let isWorkflowSettingsOpen = $state(false);
|
|
231
224
|
|
|
232
225
|
// Node swap state
|
|
233
|
-
let swapMode = $state<
|
|
226
|
+
let swapMode = $state<'idle' | 'picking' | 'mapping'>('idle');
|
|
234
227
|
let swapTargetMetadata = $state<NodeMetadata | null>(null);
|
|
235
228
|
let swapInteractiveState = $state<InteractiveSwapState | null>(null);
|
|
236
229
|
|
|
230
|
+
// Built-in workflow settings field names — consumer schemas must not reuse these.
|
|
231
|
+
const WORKFLOW_SETTINGS_RESERVED = new Set(['name', 'description', 'format']);
|
|
232
|
+
|
|
237
233
|
// Workflow configuration schema (derived to pick up dynamic format options)
|
|
238
|
-
let workflowConfigSchema: ConfigSchema = $derived({
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
234
|
+
let workflowConfigSchema: ConfigSchema = $derived.by(() => {
|
|
235
|
+
const extraProps = Object.fromEntries(
|
|
236
|
+
Object.entries(workflowSettingsSchema?.properties ?? {}).filter(([k]) => {
|
|
237
|
+
if (WORKFLOW_SETTINGS_RESERVED.has(k)) {
|
|
238
|
+
logger.warn(
|
|
239
|
+
`workflowSettingsSchema: property "${k}" is reserved and will be ignored. Choose a different key.`
|
|
240
|
+
);
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
return true;
|
|
244
|
+
})
|
|
245
|
+
);
|
|
246
|
+
const extraRequired = (workflowSettingsSchema?.required ?? []).filter(
|
|
247
|
+
(k) => !WORKFLOW_SETTINGS_RESERVED.has(k)
|
|
248
|
+
);
|
|
249
|
+
return {
|
|
250
|
+
type: 'object' as const,
|
|
251
|
+
properties: {
|
|
252
|
+
name: {
|
|
253
|
+
type: 'string',
|
|
254
|
+
title: 'Workflow Name',
|
|
255
|
+
description: 'The name of the workflow',
|
|
256
|
+
default: ''
|
|
257
|
+
},
|
|
258
|
+
description: {
|
|
259
|
+
type: 'string',
|
|
260
|
+
title: 'Description',
|
|
261
|
+
description: 'A description of the workflow',
|
|
262
|
+
format: 'multiline',
|
|
263
|
+
default: ''
|
|
264
|
+
},
|
|
265
|
+
format: {
|
|
266
|
+
type: 'string',
|
|
267
|
+
title: 'Workflow Format',
|
|
268
|
+
description: 'The specification format for this workflow',
|
|
269
|
+
oneOf: workflowFormatRegistry.getOneOfOptions(),
|
|
270
|
+
default: 'flowdrop'
|
|
271
|
+
},
|
|
272
|
+
...extraProps
|
|
260
273
|
},
|
|
261
|
-
|
|
262
|
-
|
|
274
|
+
required: ['name', ...extraRequired]
|
|
275
|
+
};
|
|
263
276
|
});
|
|
264
277
|
|
|
265
278
|
// Workflow configuration values
|
|
266
279
|
let workflowConfigValues = $derived({
|
|
267
|
-
name: getWorkflowName() ||
|
|
268
|
-
description: getWorkflowStore()?.description ||
|
|
269
|
-
format: getWorkflowStore()?.metadata?.format ||
|
|
280
|
+
name: getWorkflowName() || '',
|
|
281
|
+
description: getWorkflowStore()?.description || '',
|
|
282
|
+
format: getWorkflowStore()?.metadata?.format || 'flowdrop',
|
|
283
|
+
...(getWorkflowStore()?.config ?? {})
|
|
270
284
|
});
|
|
271
285
|
|
|
272
286
|
// Get the current node from the workflow store
|
|
@@ -291,18 +305,14 @@
|
|
|
291
305
|
// Merge format-provided nodes with prop nodes (deduplicate by ID, props take priority)
|
|
292
306
|
const formatNodes = workflowFormatRegistry.getAllFormatNodes();
|
|
293
307
|
const existingIds = new Set(propNodes.map((n) => n.id));
|
|
294
|
-
const uniqueFormatNodes = formatNodes.filter(
|
|
295
|
-
(n) => !existingIds.has(n.id),
|
|
296
|
-
);
|
|
308
|
+
const uniqueFormatNodes = formatNodes.filter((n) => !existingIds.has(n.id));
|
|
297
309
|
nodes = [...propNodes, ...uniqueFormatNodes];
|
|
298
310
|
nodeTypesLoading = false;
|
|
299
311
|
return;
|
|
300
312
|
}
|
|
301
313
|
|
|
302
314
|
// Show loading toast (if toasts are enabled)
|
|
303
|
-
const loadingToast = features.showToasts
|
|
304
|
-
? apiToasts.loading("Loading node types")
|
|
305
|
-
: null;
|
|
315
|
+
const loadingToast = features.showToasts ? apiToasts.loading('Loading node types') : null;
|
|
306
316
|
try {
|
|
307
317
|
error = null;
|
|
308
318
|
|
|
@@ -317,9 +327,7 @@
|
|
|
317
327
|
// Merge format-provided nodes with API nodes (deduplicate by ID, API takes priority)
|
|
318
328
|
const formatNodes = workflowFormatRegistry.getAllFormatNodes();
|
|
319
329
|
const existingIds = new Set(fetchedNodes.map((n) => n.id));
|
|
320
|
-
const uniqueFormatNodes = formatNodes.filter(
|
|
321
|
-
(n) => !existingIds.has(n.id),
|
|
322
|
-
);
|
|
330
|
+
const uniqueFormatNodes = formatNodes.filter((n) => !existingIds.has(n.id));
|
|
323
331
|
nodes = [...fetchedNodes, ...uniqueFormatNodes];
|
|
324
332
|
error = null;
|
|
325
333
|
nodeTypesLoading = false;
|
|
@@ -334,13 +342,13 @@
|
|
|
334
342
|
dismissToast(loadingToast);
|
|
335
343
|
}
|
|
336
344
|
|
|
337
|
-
const errorMessage = err instanceof Error ? err.message :
|
|
345
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
338
346
|
|
|
339
347
|
// Notify parent via event handler
|
|
340
348
|
if (eventHandlers?.onApiError) {
|
|
341
349
|
const suppressToast = eventHandlers.onApiError(
|
|
342
350
|
err instanceof Error ? err : new Error(errorMessage),
|
|
343
|
-
|
|
351
|
+
'fetchNodes'
|
|
344
352
|
);
|
|
345
353
|
if (suppressToast) {
|
|
346
354
|
// Parent handled the error, keep nodes empty
|
|
@@ -353,7 +361,7 @@
|
|
|
353
361
|
// Show error and set empty nodes array (no fallback to sample data)
|
|
354
362
|
error = `API Error: ${errorMessage}. No node types available.`;
|
|
355
363
|
if (features.showToasts) {
|
|
356
|
-
apiToasts.error(
|
|
364
|
+
apiToasts.error('Load node types', errorMessage);
|
|
357
365
|
}
|
|
358
366
|
|
|
359
367
|
// Set empty nodes array instead of fallback data
|
|
@@ -374,22 +382,19 @@
|
|
|
374
382
|
*/
|
|
375
383
|
async function testApiConnection(): Promise<void> {
|
|
376
384
|
try {
|
|
377
|
-
const baseUrl = endpointConfig?.baseUrl || apiBaseUrl ||
|
|
385
|
+
const baseUrl = endpointConfig?.baseUrl || apiBaseUrl || '/api/flowdrop';
|
|
378
386
|
const testUrl = `${baseUrl}/nodes`;
|
|
379
387
|
|
|
380
388
|
const response = await fetch(testUrl);
|
|
381
389
|
const data = await response.json();
|
|
382
390
|
|
|
383
391
|
if (response.ok && data.success) {
|
|
384
|
-
apiToasts.success(
|
|
392
|
+
apiToasts.success('API connection test', 'Connection successful');
|
|
385
393
|
} else {
|
|
386
|
-
apiToasts.error(
|
|
394
|
+
apiToasts.error('API connection test', 'Connection failed');
|
|
387
395
|
}
|
|
388
396
|
} catch (err) {
|
|
389
|
-
apiToasts.error(
|
|
390
|
-
"API connection test",
|
|
391
|
-
err instanceof Error ? err.message : "Unknown error",
|
|
392
|
-
);
|
|
397
|
+
apiToasts.error('API connection test', err instanceof Error ? err.message : 'Unknown error');
|
|
393
398
|
}
|
|
394
399
|
}
|
|
395
400
|
|
|
@@ -405,16 +410,13 @@
|
|
|
405
410
|
|
|
406
411
|
// Create enhanced API client with authProvider support if provided
|
|
407
412
|
if (authProvider) {
|
|
408
|
-
apiClient = new EnhancedFlowDropApiClient(
|
|
409
|
-
propEndpointConfig,
|
|
410
|
-
authProvider,
|
|
411
|
-
);
|
|
413
|
+
apiClient = new EnhancedFlowDropApiClient(propEndpointConfig, authProvider);
|
|
412
414
|
}
|
|
413
415
|
return;
|
|
414
416
|
}
|
|
415
417
|
|
|
416
418
|
// Second priority: Check if endpoint config is already set (e.g., by parent layout)
|
|
417
|
-
const { getEndpointConfig } = await import(
|
|
419
|
+
const { getEndpointConfig } = await import('../services/api.js');
|
|
418
420
|
const existingConfig = getEndpointConfig();
|
|
419
421
|
|
|
420
422
|
// If config already exists and no override provided, use existing
|
|
@@ -429,19 +431,19 @@
|
|
|
429
431
|
}
|
|
430
432
|
|
|
431
433
|
// Third priority: Use provided apiBaseUrl or default
|
|
432
|
-
const baseUrl = apiBaseUrl ||
|
|
434
|
+
const baseUrl = apiBaseUrl || '/api/flowdrop';
|
|
433
435
|
|
|
434
436
|
const config = createEndpointConfig(baseUrl, {
|
|
435
437
|
auth: {
|
|
436
|
-
type:
|
|
438
|
+
type: 'none' // No authentication for now
|
|
437
439
|
},
|
|
438
440
|
timeout: 10000, // 10 second timeout
|
|
439
441
|
retry: {
|
|
440
442
|
enabled: true,
|
|
441
443
|
maxAttempts: 2,
|
|
442
444
|
delay: 1000,
|
|
443
|
-
backoff:
|
|
444
|
-
}
|
|
445
|
+
backoff: 'exponential'
|
|
446
|
+
}
|
|
445
447
|
});
|
|
446
448
|
|
|
447
449
|
setEndpointConfig(config);
|
|
@@ -466,7 +468,7 @@
|
|
|
466
468
|
selectedNodeId = node.id;
|
|
467
469
|
isConfigSidebarOpen = true;
|
|
468
470
|
// Reset swap state when switching nodes
|
|
469
|
-
swapMode =
|
|
471
|
+
swapMode = 'idle';
|
|
470
472
|
swapTargetMetadata = null;
|
|
471
473
|
swapInteractiveState = null;
|
|
472
474
|
}
|
|
@@ -475,7 +477,7 @@
|
|
|
475
477
|
isConfigSidebarOpen = false;
|
|
476
478
|
selectedNodeId = null;
|
|
477
479
|
// Reset swap state when closing
|
|
478
|
-
swapMode =
|
|
480
|
+
swapMode = 'idle';
|
|
479
481
|
swapTargetMetadata = null;
|
|
480
482
|
swapInteractiveState = null;
|
|
481
483
|
}
|
|
@@ -495,7 +497,7 @@
|
|
|
495
497
|
* Start swap mode — transitions the right sidebar to the node picker
|
|
496
498
|
*/
|
|
497
499
|
function startSwap(): void {
|
|
498
|
-
swapMode =
|
|
500
|
+
swapMode = 'picking';
|
|
499
501
|
swapTargetMetadata = null;
|
|
500
502
|
swapInteractiveState = null;
|
|
501
503
|
}
|
|
@@ -517,24 +519,21 @@
|
|
|
517
519
|
}
|
|
518
520
|
|
|
519
521
|
// Get port compatibility checker (may be null if not initialized)
|
|
520
|
-
let checker: import(
|
|
522
|
+
let checker: import('../utils/connections.js').PortCompatibilityChecker | null = null;
|
|
521
523
|
try {
|
|
522
524
|
checker = getPortCompatibilityChecker();
|
|
523
525
|
} catch {
|
|
524
526
|
// Checker not initialized — computeSwapPreview will use exact dataType matching
|
|
525
527
|
}
|
|
526
528
|
|
|
527
|
-
const interactive = computeInteractiveState(
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
wf.nodes,
|
|
532
|
-
{ checker, strategies: swapStrategies },
|
|
533
|
-
);
|
|
529
|
+
const interactive = computeInteractiveState(node, metadata, wf.edges, wf.nodes, {
|
|
530
|
+
checker,
|
|
531
|
+
strategies: swapStrategies
|
|
532
|
+
});
|
|
534
533
|
|
|
535
534
|
swapTargetMetadata = metadata;
|
|
536
535
|
swapInteractiveState = interactive;
|
|
537
|
-
swapMode =
|
|
536
|
+
swapMode = 'mapping';
|
|
538
537
|
}
|
|
539
538
|
|
|
540
539
|
/**
|
|
@@ -554,18 +553,12 @@
|
|
|
554
553
|
const preview = buildSwapPreviewFromState(state, wf.edges);
|
|
555
554
|
|
|
556
555
|
// Execute the swap
|
|
557
|
-
const result = executeSwap(
|
|
558
|
-
state.oldNode,
|
|
559
|
-
state.newMetadata,
|
|
560
|
-
preview,
|
|
561
|
-
wf.nodes,
|
|
562
|
-
wf.edges,
|
|
563
|
-
);
|
|
556
|
+
const result = executeSwap(state.oldNode, state.newMetadata, preview, wf.nodes, wf.edges);
|
|
564
557
|
|
|
565
558
|
// Post-swap validation
|
|
566
559
|
const validation = validateSwapResult(result);
|
|
567
560
|
if (!validation.valid) {
|
|
568
|
-
logger.error(
|
|
561
|
+
logger.error('Swap validation failed:', validation.error);
|
|
569
562
|
return;
|
|
570
563
|
}
|
|
571
564
|
|
|
@@ -576,7 +569,7 @@
|
|
|
576
569
|
newMetadata: state.newMetadata,
|
|
577
570
|
preview,
|
|
578
571
|
portOverrides: [],
|
|
579
|
-
configOverrides: []
|
|
572
|
+
configOverrides: []
|
|
580
573
|
};
|
|
581
574
|
const shouldProceed = await eventHandlers.onBeforeSwap(swapEventCtx);
|
|
582
575
|
if (shouldProceed === false) return;
|
|
@@ -586,7 +579,7 @@
|
|
|
586
579
|
workflowActions.swapNode({
|
|
587
580
|
nodes: result.updatedNodes,
|
|
588
581
|
edges: result.updatedEdges,
|
|
589
|
-
description: `Swap node: ${oldLabel} → ${newLabel}
|
|
582
|
+
description: `Swap node: ${oldLabel} → ${newLabel}`
|
|
590
583
|
});
|
|
591
584
|
|
|
592
585
|
// onAfterSwap hook (fire-and-forget — swap is already applied)
|
|
@@ -594,7 +587,7 @@
|
|
|
594
587
|
try {
|
|
595
588
|
eventHandlers.onAfterSwap(result, state.oldNode, state.newNodeId);
|
|
596
589
|
} catch (err) {
|
|
597
|
-
logger.error(
|
|
590
|
+
logger.error('onAfterSwap hook error:', err);
|
|
598
591
|
}
|
|
599
592
|
}
|
|
600
593
|
|
|
@@ -603,7 +596,7 @@
|
|
|
603
596
|
selectedNodeId = newNodeId;
|
|
604
597
|
|
|
605
598
|
// Reset swap state
|
|
606
|
-
swapMode =
|
|
599
|
+
swapMode = 'idle';
|
|
607
600
|
swapTargetMetadata = null;
|
|
608
601
|
swapInteractiveState = null;
|
|
609
602
|
|
|
@@ -624,7 +617,7 @@
|
|
|
624
617
|
* Cancel swap and return to normal config view
|
|
625
618
|
*/
|
|
626
619
|
function cancelSwap(): void {
|
|
627
|
-
swapMode =
|
|
620
|
+
swapMode = 'idle';
|
|
628
621
|
swapTargetMetadata = null;
|
|
629
622
|
swapInteractiveState = null;
|
|
630
623
|
}
|
|
@@ -632,14 +625,12 @@
|
|
|
632
625
|
/**
|
|
633
626
|
* Handle workflow configuration save
|
|
634
627
|
*/
|
|
635
|
-
async function handleWorkflowSave(
|
|
636
|
-
config: Record<string, unknown>,
|
|
637
|
-
): Promise<void> {
|
|
628
|
+
async function handleWorkflowSave(config: Record<string, unknown>): Promise<void> {
|
|
638
629
|
// Update the workflow store
|
|
639
630
|
if (getWorkflowStore()) {
|
|
640
631
|
workflowActions.batchUpdate({
|
|
641
632
|
name: config.name as string | undefined,
|
|
642
|
-
description: config.description as string | undefined
|
|
633
|
+
description: config.description as string | undefined
|
|
643
634
|
});
|
|
644
635
|
}
|
|
645
636
|
|
|
@@ -650,7 +641,7 @@
|
|
|
650
641
|
try {
|
|
651
642
|
await saveWorkflow();
|
|
652
643
|
} catch (error) {
|
|
653
|
-
logger.error(
|
|
644
|
+
logger.error('Failed to save workflow to backend:', error);
|
|
654
645
|
// Note: We don't throw the error here to avoid breaking the UI flow
|
|
655
646
|
// The user can still manually save via the main Save button if needed
|
|
656
647
|
}
|
|
@@ -667,7 +658,7 @@
|
|
|
667
658
|
apiClient: apiClient ?? undefined,
|
|
668
659
|
eventHandlers,
|
|
669
660
|
features,
|
|
670
|
-
onMarkAsSaved: markAsSaved
|
|
661
|
+
onMarkAsSaved: markAsSaved
|
|
671
662
|
});
|
|
672
663
|
}
|
|
673
664
|
|
|
@@ -691,45 +682,38 @@
|
|
|
691
682
|
reader.onload = (event) => {
|
|
692
683
|
try {
|
|
693
684
|
const text = event.target?.result;
|
|
694
|
-
if (typeof text !==
|
|
695
|
-
throw new Error(
|
|
685
|
+
if (typeof text !== 'string') {
|
|
686
|
+
throw new Error('Could not read file contents.');
|
|
696
687
|
}
|
|
697
688
|
const data = JSON.parse(text);
|
|
698
689
|
const validation = validateWorkflowData(data);
|
|
699
690
|
if (!validation.valid) {
|
|
700
691
|
if (features.showToasts) {
|
|
701
|
-
apiToasts.error(
|
|
702
|
-
"Import workflow",
|
|
703
|
-
validation.error ?? "Invalid workflow JSON",
|
|
704
|
-
);
|
|
692
|
+
apiToasts.error('Import workflow', validation.error ?? 'Invalid workflow JSON');
|
|
705
693
|
}
|
|
706
|
-
logger.warn(
|
|
694
|
+
logger.warn('Workflow import validation failed:', validation.error);
|
|
707
695
|
return;
|
|
708
696
|
}
|
|
709
697
|
workflowActions.initialize(data as Workflow);
|
|
710
698
|
if (features.showToasts) {
|
|
711
|
-
apiToasts.success(
|
|
712
|
-
"Import workflow",
|
|
713
|
-
"Workflow imported successfully",
|
|
714
|
-
);
|
|
699
|
+
apiToasts.success('Import workflow', 'Workflow imported successfully');
|
|
715
700
|
}
|
|
716
701
|
if (eventHandlers?.onWorkflowLoad) {
|
|
717
702
|
eventHandlers.onWorkflowLoad(data as Workflow);
|
|
718
703
|
}
|
|
719
704
|
} catch (error) {
|
|
720
|
-
const errorObj =
|
|
721
|
-
|
|
722
|
-
logger.error("Workflow import failed:", errorObj);
|
|
705
|
+
const errorObj = error instanceof Error ? error : new Error('Unknown error occurred');
|
|
706
|
+
logger.error('Workflow import failed:', errorObj);
|
|
723
707
|
if (features.showToasts) {
|
|
724
|
-
apiToasts.error(
|
|
708
|
+
apiToasts.error('Import workflow', errorObj.message);
|
|
725
709
|
}
|
|
726
710
|
}
|
|
727
711
|
};
|
|
728
712
|
reader.onerror = () => {
|
|
729
|
-
const message =
|
|
713
|
+
const message = 'Failed to read the selected file.';
|
|
730
714
|
logger.error(message);
|
|
731
715
|
if (features.showToasts) {
|
|
732
|
-
apiToasts.error(
|
|
716
|
+
apiToasts.error('Import workflow', message);
|
|
733
717
|
}
|
|
734
718
|
};
|
|
735
719
|
reader.readAsText(file);
|
|
@@ -745,15 +729,13 @@
|
|
|
745
729
|
importWorkflow(file);
|
|
746
730
|
}
|
|
747
731
|
// Reset input so same file can be re-imported
|
|
748
|
-
input.value =
|
|
732
|
+
input.value = '';
|
|
749
733
|
}
|
|
750
734
|
|
|
751
735
|
// Function to handle clicks outside the sidebar
|
|
752
736
|
function handleCanvasClick(event: MouseEvent): void {
|
|
753
737
|
// Check if the click is outside the right sidebar
|
|
754
|
-
const rightSidebar = document.querySelector(
|
|
755
|
-
".flowdrop-main-layout__sidebar--right",
|
|
756
|
-
);
|
|
738
|
+
const rightSidebar = document.querySelector('.flowdrop-main-layout__sidebar--right');
|
|
757
739
|
if (rightSidebar && !rightSidebar.contains(event.target as Node)) {
|
|
758
740
|
// Close sidebar when clicking outside of it
|
|
759
741
|
if (isConfigSidebarOpen) {
|
|
@@ -770,7 +752,10 @@
|
|
|
770
752
|
|
|
771
753
|
// Ensure port compatibility checker is initialized (needed for proximity connect, etc.)
|
|
772
754
|
// mountFlowDropApp initializes this before mounting, but SvelteKit routes need it here.
|
|
773
|
-
|
|
755
|
+
// Only initialize with defaults if not already set — preserves custom port configs.
|
|
756
|
+
if (!isPortCompatibilityInitialized()) {
|
|
757
|
+
initializePortCompatibility(DEFAULT_PORT_CONFIG);
|
|
758
|
+
}
|
|
774
759
|
|
|
775
760
|
await fetchNodeTypes();
|
|
776
761
|
|
|
@@ -786,21 +771,21 @@
|
|
|
786
771
|
// Initialize with a default empty workflow so the editor is functional
|
|
787
772
|
// (e.g., drag-and-drop requires a non-null workflow in the store)
|
|
788
773
|
const defaultWorkflow: Workflow = {
|
|
789
|
-
id:
|
|
790
|
-
name:
|
|
774
|
+
id: '',
|
|
775
|
+
name: 'Untitled Workflow',
|
|
791
776
|
nodes: [],
|
|
792
777
|
edges: [],
|
|
793
778
|
metadata: {
|
|
794
|
-
version:
|
|
779
|
+
version: '1.0.0',
|
|
795
780
|
format: DEFAULT_WORKFLOW_FORMAT,
|
|
796
781
|
createdAt: new Date().toISOString(),
|
|
797
|
-
updatedAt: new Date().toISOString()
|
|
798
|
-
}
|
|
782
|
+
updatedAt: new Date().toISOString()
|
|
783
|
+
}
|
|
799
784
|
};
|
|
800
785
|
workflowActions.initialize(defaultWorkflow);
|
|
801
786
|
}
|
|
802
787
|
} catch (error) {
|
|
803
|
-
logger.error(
|
|
788
|
+
logger.error('Failed to initialize editor:', error);
|
|
804
789
|
}
|
|
805
790
|
})();
|
|
806
791
|
|
|
@@ -809,10 +794,7 @@
|
|
|
809
794
|
toggleWorkflowSettings();
|
|
810
795
|
};
|
|
811
796
|
|
|
812
|
-
window.addEventListener(
|
|
813
|
-
"workflow-settings-toggle",
|
|
814
|
-
handleWorkflowSettingsToggle,
|
|
815
|
-
);
|
|
797
|
+
window.addEventListener('workflow-settings-toggle', handleWorkflowSettingsToggle);
|
|
816
798
|
|
|
817
799
|
// Initialize auto-save based on user settings
|
|
818
800
|
const cleanupAutoSave = initAutoSave({
|
|
@@ -821,18 +803,15 @@
|
|
|
821
803
|
},
|
|
822
804
|
onError: (error) => {
|
|
823
805
|
// Don't show toast for auto-save errors to avoid noise
|
|
824
|
-
logger.warn(
|
|
806
|
+
logger.warn('Auto-save failed:', error);
|
|
825
807
|
},
|
|
826
808
|
onSuccess: () => {
|
|
827
|
-
logger.debug(
|
|
828
|
-
}
|
|
809
|
+
logger.debug('Auto-saved workflow');
|
|
810
|
+
}
|
|
829
811
|
});
|
|
830
812
|
|
|
831
813
|
return () => {
|
|
832
|
-
window.removeEventListener(
|
|
833
|
-
"workflow-settings-toggle",
|
|
834
|
-
handleWorkflowSettingsToggle,
|
|
835
|
-
);
|
|
814
|
+
window.removeEventListener('workflow-settings-toggle', handleWorkflowSettingsToggle);
|
|
836
815
|
cleanupAutoSave();
|
|
837
816
|
};
|
|
838
817
|
});
|
|
@@ -842,9 +821,7 @@
|
|
|
842
821
|
* Config panel always appears on the right side
|
|
843
822
|
*/
|
|
844
823
|
const hasConfigPanelOpen = $derived(
|
|
845
|
-
isWorkflowSettingsOpen ||
|
|
846
|
-
!!selectedNodeForConfig ||
|
|
847
|
-
swapMode !== "idle",
|
|
824
|
+
isWorkflowSettingsOpen || !!selectedNodeForConfig || swapMode !== 'idle'
|
|
848
825
|
);
|
|
849
826
|
const showRightPanel = $derived(!disableSidebar && hasConfigPanelOpen);
|
|
850
827
|
|
|
@@ -853,7 +830,7 @@
|
|
|
853
830
|
* When collapsed, use 0; otherwise use user-configured width
|
|
854
831
|
*/
|
|
855
832
|
const leftSidebarWidth = $derived(
|
|
856
|
-
getUiSettings().sidebarCollapsed ? 0 : getUiSettings().sidebarWidth
|
|
833
|
+
getUiSettings().sidebarCollapsed ? 0 : getUiSettings().sidebarWidth
|
|
857
834
|
);
|
|
858
835
|
|
|
859
836
|
/** Whether the sidebar is collapsed */
|
|
@@ -862,7 +839,7 @@
|
|
|
862
839
|
/** Toggle sidebar collapsed state */
|
|
863
840
|
function toggleSidebar(): void {
|
|
864
841
|
updateSettings({
|
|
865
|
-
ui: { sidebarCollapsed: !getUiSettings().sidebarCollapsed }
|
|
842
|
+
ui: { sidebarCollapsed: !getUiSettings().sidebarCollapsed }
|
|
866
843
|
});
|
|
867
844
|
}
|
|
868
845
|
|
|
@@ -875,16 +852,14 @@
|
|
|
875
852
|
*/
|
|
876
853
|
function handleGlobalKeydown(event: KeyboardEvent): void {
|
|
877
854
|
// Dead key on international keyboards — do not intercept
|
|
878
|
-
if (event.key ===
|
|
855
|
+
if (event.key === 'Dead') return;
|
|
879
856
|
|
|
880
|
-
if (event.key !==
|
|
857
|
+
if (event.key !== '`') return;
|
|
881
858
|
|
|
882
859
|
// Don't intercept when user is typing in an input, textarea, or contenteditable
|
|
883
860
|
const target = event.target as HTMLElement;
|
|
884
861
|
const isInputElement =
|
|
885
|
-
target.tagName ===
|
|
886
|
-
target.tagName === "TEXTAREA" ||
|
|
887
|
-
target.isContentEditable;
|
|
862
|
+
target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable;
|
|
888
863
|
|
|
889
864
|
if (isInputElement) return;
|
|
890
865
|
|
|
@@ -893,24 +868,24 @@
|
|
|
893
868
|
}
|
|
894
869
|
|
|
895
870
|
function handleConsoleUIAction(action: UIAction): void {
|
|
896
|
-
if (action.type ===
|
|
871
|
+
if (action.type === 'open_config') {
|
|
897
872
|
const wf = getWorkflowStore();
|
|
898
873
|
if (!wf) return;
|
|
899
874
|
const node = wf.nodes.find((n) => n.id === action.nodeId);
|
|
900
875
|
if (node) openConfigSidebar(node);
|
|
901
|
-
} else if (action.type ===
|
|
876
|
+
} else if (action.type === 'select_node') {
|
|
902
877
|
selectedNodeId = action.nodeId;
|
|
903
|
-
} else if (action.type ===
|
|
878
|
+
} else if (action.type === 'canvas_fit_view') {
|
|
904
879
|
workflowEditorRef?.canvasFitView();
|
|
905
|
-
} else if (action.type ===
|
|
880
|
+
} else if (action.type === 'canvas_zoom_in') {
|
|
906
881
|
workflowEditorRef?.canvasZoomIn();
|
|
907
|
-
} else if (action.type ===
|
|
882
|
+
} else if (action.type === 'canvas_zoom_out') {
|
|
908
883
|
workflowEditorRef?.canvasZoomOut();
|
|
909
|
-
} else if (action.type ===
|
|
884
|
+
} else if (action.type === 'canvas_zoom_to') {
|
|
910
885
|
workflowEditorRef?.canvasZoomTo(action.level);
|
|
911
|
-
} else if (action.type ===
|
|
886
|
+
} else if (action.type === 'canvas_pan_to') {
|
|
912
887
|
workflowEditorRef?.canvasPanTo(action.position.x, action.position.y);
|
|
913
|
-
} else if (action.type ===
|
|
888
|
+
} else if (action.type === 'canvas_reset_view') {
|
|
914
889
|
workflowEditorRef?.canvasResetView();
|
|
915
890
|
}
|
|
916
891
|
}
|
|
@@ -923,13 +898,12 @@
|
|
|
923
898
|
tick().then(() => {
|
|
924
899
|
if (currentOpen) {
|
|
925
900
|
// Console was open, now closing — focus the canvas
|
|
926
|
-
const canvas = document.querySelector<HTMLElement>(
|
|
901
|
+
const canvas = document.querySelector<HTMLElement>('.flowdrop-editor-main');
|
|
927
902
|
canvas?.focus();
|
|
928
903
|
} else {
|
|
929
904
|
// Console was closed, now opening — focus first focusable element inside console
|
|
930
|
-
const consoleEl = document.querySelector<HTMLElement>(
|
|
931
|
-
const focusTarget =
|
|
932
|
-
consoleEl?.querySelector<HTMLElement>("input, button, [tabindex]");
|
|
905
|
+
const consoleEl = document.querySelector<HTMLElement>('.command-console');
|
|
906
|
+
const focusTarget = consoleEl?.querySelector<HTMLElement>('input, button, [tabindex]');
|
|
933
907
|
focusTarget?.focus();
|
|
934
908
|
}
|
|
935
909
|
});
|
|
@@ -940,10 +914,7 @@
|
|
|
940
914
|
|
|
941
915
|
<svelte:head>
|
|
942
916
|
<title>FlowDrop - Visual Workflow Manager</title>
|
|
943
|
-
<meta
|
|
944
|
-
name="description"
|
|
945
|
-
content="A modern drag-and-drop workflow editor for LLM applications"
|
|
946
|
-
/>
|
|
917
|
+
<meta name="description" content="A modern drag-and-drop workflow editor for LLM applications" />
|
|
947
918
|
</svelte:head>
|
|
948
919
|
|
|
949
920
|
<!-- Hidden file input for workflow JSON import -->
|
|
@@ -983,45 +954,45 @@
|
|
|
983
954
|
? navbarActions
|
|
984
955
|
: [
|
|
985
956
|
{
|
|
986
|
-
label:
|
|
987
|
-
href:
|
|
988
|
-
icon:
|
|
989
|
-
variant:
|
|
957
|
+
label: 'Save',
|
|
958
|
+
href: '#save',
|
|
959
|
+
icon: 'heroicons:document-arrow-down',
|
|
960
|
+
variant: 'primary',
|
|
990
961
|
onclick: (e) => {
|
|
991
962
|
e.preventDefault();
|
|
992
963
|
saveWorkflow();
|
|
993
|
-
}
|
|
964
|
+
}
|
|
994
965
|
},
|
|
995
966
|
{
|
|
996
|
-
label:
|
|
997
|
-
href:
|
|
998
|
-
icon:
|
|
999
|
-
variant:
|
|
967
|
+
label: 'Export',
|
|
968
|
+
href: '#export',
|
|
969
|
+
icon: 'heroicons:arrow-down-tray',
|
|
970
|
+
variant: 'outline',
|
|
1000
971
|
onclick: (e) => {
|
|
1001
972
|
e.preventDefault();
|
|
1002
973
|
exportWorkflow();
|
|
1003
|
-
}
|
|
974
|
+
}
|
|
1004
975
|
},
|
|
1005
976
|
{
|
|
1006
|
-
label:
|
|
1007
|
-
href:
|
|
1008
|
-
icon:
|
|
1009
|
-
variant:
|
|
977
|
+
label: 'Import',
|
|
978
|
+
href: '#import',
|
|
979
|
+
icon: 'heroicons:arrow-up-tray',
|
|
980
|
+
variant: 'outline',
|
|
1010
981
|
onclick: (e) => {
|
|
1011
982
|
e.preventDefault();
|
|
1012
983
|
fileInputRef?.click();
|
|
1013
|
-
}
|
|
984
|
+
}
|
|
1014
985
|
},
|
|
1015
986
|
{
|
|
1016
|
-
label:
|
|
1017
|
-
href:
|
|
1018
|
-
icon:
|
|
1019
|
-
variant:
|
|
987
|
+
label: 'Workflow Settings',
|
|
988
|
+
href: '#settings',
|
|
989
|
+
icon: 'heroicons:cog-6-tooth',
|
|
990
|
+
variant: 'outline',
|
|
1020
991
|
onclick: (e) => {
|
|
1021
992
|
e.preventDefault();
|
|
1022
993
|
toggleWorkflowSettings();
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
994
|
+
}
|
|
995
|
+
}
|
|
1025
996
|
]}
|
|
1026
997
|
showStatus={true}
|
|
1027
998
|
{showSettings}
|
|
@@ -1037,23 +1008,31 @@
|
|
|
1037
1008
|
{nodes}
|
|
1038
1009
|
loading={nodeTypesLoading}
|
|
1039
1010
|
activeFormat={getWorkflowFormat()}
|
|
1040
|
-
categoriesDefaultOpen={themeConfig?.sidebar?.categoriesDefaultOpen ??
|
|
1041
|
-
false}
|
|
1011
|
+
categoriesDefaultOpen={themeConfig?.sidebar?.categoriesDefaultOpen ?? false}
|
|
1042
1012
|
/>
|
|
1043
1013
|
{/snippet}
|
|
1044
1014
|
|
|
1045
1015
|
<!-- Right Sidebar: Configuration, Swap, or Workflow Settings -->
|
|
1046
1016
|
{#snippet rightSidebar()}
|
|
1047
|
-
{#if swapMode ===
|
|
1048
|
-
{@const swapChecker = (() => {
|
|
1017
|
+
{#if swapMode === 'mapping' && swapInteractiveState && selectedNodeForConfig}
|
|
1018
|
+
{@const swapChecker = (() => {
|
|
1019
|
+
try {
|
|
1020
|
+
return getPortCompatibilityChecker();
|
|
1021
|
+
} catch {
|
|
1022
|
+
return null;
|
|
1023
|
+
}
|
|
1024
|
+
})()}
|
|
1049
1025
|
<SwapMappingEditor
|
|
1050
1026
|
interactiveState={swapInteractiveState}
|
|
1051
1027
|
checker={swapChecker}
|
|
1052
1028
|
onConfirm={executeNodeSwap}
|
|
1053
1029
|
onCancel={cancelSwap}
|
|
1054
|
-
onBack={() => {
|
|
1030
|
+
onBack={() => {
|
|
1031
|
+
swapMode = 'picking';
|
|
1032
|
+
swapInteractiveState = null;
|
|
1033
|
+
}}
|
|
1055
1034
|
/>
|
|
1056
|
-
{:else if swapMode ===
|
|
1035
|
+
{:else if swapMode === 'picking' && selectedNodeForConfig}
|
|
1057
1036
|
<NodeSwapPicker
|
|
1058
1037
|
currentNode={selectedNodeForConfig}
|
|
1059
1038
|
availableNodes={nodes}
|
|
@@ -1067,13 +1046,13 @@
|
|
|
1067
1046
|
id={getWorkflowStore()?.id}
|
|
1068
1047
|
details={[
|
|
1069
1048
|
{
|
|
1070
|
-
label:
|
|
1071
|
-
value: String(getWorkflowStore()?.nodes?.length ?? 0)
|
|
1049
|
+
label: 'Nodes',
|
|
1050
|
+
value: String(getWorkflowStore()?.nodes?.length ?? 0)
|
|
1072
1051
|
},
|
|
1073
1052
|
{
|
|
1074
|
-
label:
|
|
1075
|
-
value: String(getWorkflowStore()?.edges?.length ?? 0)
|
|
1076
|
-
}
|
|
1053
|
+
label: 'Connections',
|
|
1054
|
+
value: String(getWorkflowStore()?.edges?.length ?? 0)
|
|
1055
|
+
}
|
|
1077
1056
|
]}
|
|
1078
1057
|
configTitle="Settings"
|
|
1079
1058
|
onClose={() => (isWorkflowSettingsOpen = false)}
|
|
@@ -1087,36 +1066,33 @@
|
|
|
1087
1066
|
// Sync workflow settings changes immediately on field blur
|
|
1088
1067
|
const wf = getWorkflowStore();
|
|
1089
1068
|
if (wf) {
|
|
1090
|
-
const newFormat =
|
|
1091
|
-
|
|
1092
|
-
const currentFormat =
|
|
1093
|
-
wf.metadata?.format || DEFAULT_WORKFLOW_FORMAT;
|
|
1069
|
+
const newFormat = (config.format as string) || DEFAULT_WORKFLOW_FORMAT;
|
|
1070
|
+
const currentFormat = wf.metadata?.format || DEFAULT_WORKFLOW_FORMAT;
|
|
1094
1071
|
|
|
1095
1072
|
// Warn about incompatible nodes when format changes
|
|
1096
1073
|
if (newFormat !== currentFormat) {
|
|
1097
1074
|
const incompatibleNodes = wf.nodes?.filter((node) => {
|
|
1098
1075
|
const formats = node.data?.metadata?.formats;
|
|
1099
|
-
return (
|
|
1100
|
-
formats &&
|
|
1101
|
-
formats.length > 0 &&
|
|
1102
|
-
!formats.includes(newFormat)
|
|
1103
|
-
);
|
|
1076
|
+
return formats && formats.length > 0 && !formats.includes(newFormat);
|
|
1104
1077
|
});
|
|
1105
1078
|
if (incompatibleNodes && incompatibleNodes.length > 0) {
|
|
1106
1079
|
logger.warn(
|
|
1107
1080
|
`Format changed to '${newFormat}'. ${incompatibleNodes.length} node(s) are not compatible with this format and may not export correctly:`,
|
|
1108
|
-
incompatibleNodes.map((n) => n.data?.label || n.type)
|
|
1081
|
+
incompatibleNodes.map((n) => n.data?.label || n.type)
|
|
1109
1082
|
);
|
|
1110
1083
|
}
|
|
1111
1084
|
}
|
|
1112
1085
|
|
|
1086
|
+
// Extract built-in fields; everything else belongs in workflow.config
|
|
1087
|
+
const { name, description, format: _format, ...customConfig } = config;
|
|
1113
1088
|
workflowActions.batchUpdate({
|
|
1114
|
-
name:
|
|
1115
|
-
description:
|
|
1089
|
+
name: name as string,
|
|
1090
|
+
description: description as string | undefined,
|
|
1116
1091
|
metadata: {
|
|
1117
1092
|
...wf.metadata,
|
|
1118
|
-
format: newFormat
|
|
1093
|
+
format: newFormat
|
|
1119
1094
|
},
|
|
1095
|
+
...(workflowSettingsSchema && { config: customConfig as Record<string, unknown> })
|
|
1120
1096
|
});
|
|
1121
1097
|
}
|
|
1122
1098
|
}}
|
|
@@ -1127,17 +1103,16 @@
|
|
|
1127
1103
|
<ConfigPanel
|
|
1128
1104
|
title={currentNode.data.label}
|
|
1129
1105
|
id={currentNode.id}
|
|
1130
|
-
description={currentNode.data.metadata?.description ||
|
|
1131
|
-
"Node configuration"}
|
|
1106
|
+
description={currentNode.data.metadata?.description || 'Node configuration'}
|
|
1132
1107
|
details={[
|
|
1133
1108
|
{
|
|
1134
|
-
label:
|
|
1135
|
-
value: currentNode.data.metadata?.type || currentNode.type
|
|
1109
|
+
label: 'Type',
|
|
1110
|
+
value: currentNode.data.metadata?.type || currentNode.type
|
|
1136
1111
|
},
|
|
1137
1112
|
{
|
|
1138
|
-
label:
|
|
1139
|
-
value: currentNode.data.metadata?.category ||
|
|
1140
|
-
}
|
|
1113
|
+
label: 'Category',
|
|
1114
|
+
value: currentNode.data.metadata?.category || 'general'
|
|
1115
|
+
}
|
|
1141
1116
|
]}
|
|
1142
1117
|
onClose={closeConfigSidebar}
|
|
1143
1118
|
onSwap={!readOnly && !lockWorkflow && features.enableNodeSwap ? startSwap : undefined}
|
|
@@ -1154,20 +1129,20 @@
|
|
|
1154
1129
|
// Build the updated node data
|
|
1155
1130
|
const updatedData = {
|
|
1156
1131
|
...currentNode.data,
|
|
1157
|
-
config: updatedConfig
|
|
1132
|
+
config: updatedConfig
|
|
1158
1133
|
};
|
|
1159
1134
|
|
|
1160
1135
|
// Include UI extensions if provided
|
|
1161
1136
|
if (uiExtensions) {
|
|
1162
1137
|
updatedData.extensions = {
|
|
1163
1138
|
...currentNode.data.extensions,
|
|
1164
|
-
ui: uiExtensions
|
|
1139
|
+
ui: uiExtensions
|
|
1165
1140
|
};
|
|
1166
1141
|
}
|
|
1167
1142
|
|
|
1168
1143
|
// Update the node in the workflow store
|
|
1169
1144
|
const nodeUpdates: Record<string, unknown> = {
|
|
1170
|
-
data: updatedData
|
|
1145
|
+
data: updatedData
|
|
1171
1146
|
};
|
|
1172
1147
|
|
|
1173
1148
|
workflowActions.updateNode(selectedNodeId, nodeUpdates);
|
|
@@ -1190,24 +1165,39 @@
|
|
|
1190
1165
|
<div class="bottom-panel-tabs">
|
|
1191
1166
|
<div class="bottom-panel-tabs__bar">
|
|
1192
1167
|
<button
|
|
1193
|
-
class="bottom-panel-tabs__tab {getUiSettings().bottomPanelTab === 'console'
|
|
1168
|
+
class="bottom-panel-tabs__tab {getUiSettings().bottomPanelTab === 'console'
|
|
1169
|
+
? 'bottom-panel-tabs__tab--active'
|
|
1170
|
+
: ''}"
|
|
1194
1171
|
onclick={() => updateSettings({ ui: { bottomPanelTab: 'console' } })}
|
|
1195
1172
|
>
|
|
1196
1173
|
Console
|
|
1197
1174
|
</button>
|
|
1198
1175
|
<button
|
|
1199
|
-
class="bottom-panel-tabs__tab {getUiSettings().bottomPanelTab === 'chat'
|
|
1176
|
+
class="bottom-panel-tabs__tab {getUiSettings().bottomPanelTab === 'chat'
|
|
1177
|
+
? 'bottom-panel-tabs__tab--active'
|
|
1178
|
+
: ''}"
|
|
1200
1179
|
onclick={() => updateSettings({ ui: { bottomPanelTab: 'chat' } })}
|
|
1201
1180
|
>
|
|
1202
1181
|
AI Chat
|
|
1203
1182
|
</button>
|
|
1204
1183
|
</div>
|
|
1205
1184
|
<div class="bottom-panel-tabs__content">
|
|
1206
|
-
<div
|
|
1185
|
+
<div
|
|
1186
|
+
class="bottom-panel-tabs__panel"
|
|
1187
|
+
style:display={getUiSettings().bottomPanelTab === 'console' ? 'contents' : 'none'}
|
|
1188
|
+
>
|
|
1207
1189
|
<CommandConsole nodeTypes={nodes} onUIAction={handleConsoleUIAction} />
|
|
1208
1190
|
</div>
|
|
1209
|
-
<div
|
|
1210
|
-
|
|
1191
|
+
<div
|
|
1192
|
+
class="bottom-panel-tabs__panel"
|
|
1193
|
+
style:display={getUiSettings().bottomPanelTab === 'chat' ? 'flex' : 'none'}
|
|
1194
|
+
>
|
|
1195
|
+
<AIChatPanel
|
|
1196
|
+
nodeTypes={nodes}
|
|
1197
|
+
workflowId={getWorkflowStore()?.id}
|
|
1198
|
+
onUIAction={handleConsoleUIAction}
|
|
1199
|
+
{endpointConfig}
|
|
1200
|
+
/>
|
|
1211
1201
|
</div>
|
|
1212
1202
|
</div>
|
|
1213
1203
|
</div>
|
|
@@ -1216,19 +1206,11 @@
|
|
|
1216
1206
|
<!-- Main Content: Workflow Editor with Error Status -->
|
|
1217
1207
|
<!-- Status Display: aria-live announces API errors dynamically without requiring focus -->
|
|
1218
1208
|
{#if error}
|
|
1219
|
-
<div
|
|
1220
|
-
class="flowdrop-status flowdrop-status--error"
|
|
1221
|
-
aria-live="polite"
|
|
1222
|
-
aria-atomic="true"
|
|
1223
|
-
>
|
|
1209
|
+
<div class="flowdrop-status flowdrop-status--error" aria-live="polite" aria-atomic="true">
|
|
1224
1210
|
<div class="flowdrop-status__content">
|
|
1225
1211
|
<div class="flowdrop-flex flowdrop-gap--3">
|
|
1226
|
-
<div
|
|
1227
|
-
|
|
1228
|
-
></div>
|
|
1229
|
-
<span class="flowdrop-text--sm flowdrop-font--medium"
|
|
1230
|
-
>Error: {error}</span
|
|
1231
|
-
>
|
|
1212
|
+
<div class="flowdrop-status__indicator flowdrop-status__indicator--error"></div>
|
|
1213
|
+
<span class="flowdrop-text--sm flowdrop-font--medium">Error: {error}</span>
|
|
1232
1214
|
</div>
|
|
1233
1215
|
<div class="flowdrop-flex flowdrop-gap--2">
|
|
1234
1216
|
<button
|
|
@@ -1241,8 +1223,8 @@
|
|
|
1241
1223
|
<button
|
|
1242
1224
|
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
1243
1225
|
onclick={() => {
|
|
1244
|
-
const defaultUrl =
|
|
1245
|
-
const newUrl = prompt(
|
|
1226
|
+
const defaultUrl = '/api/flowdrop';
|
|
1227
|
+
const newUrl = prompt('Enter Backend API URL:', defaultUrl);
|
|
1246
1228
|
if (newUrl) {
|
|
1247
1229
|
const endpointConfig = createEndpointConfig(newUrl);
|
|
1248
1230
|
setEndpointConfig(endpointConfig);
|
|
@@ -1277,11 +1259,9 @@
|
|
|
1277
1259
|
<div
|
|
1278
1260
|
class="flowdrop-editor-main"
|
|
1279
1261
|
class:pipeline-view={!!pipelineId}
|
|
1280
|
-
style="--fd-canvas-left-offset: {!disableSidebar
|
|
1281
|
-
? leftSidebarWidth + 'px'
|
|
1282
|
-
: '0px'}"
|
|
1262
|
+
style="--fd-canvas-left-offset: {!disableSidebar ? leftSidebarWidth + 'px' : '0px'}"
|
|
1283
1263
|
onclick={handleCanvasClick}
|
|
1284
|
-
onkeydown={(e) => e.key ===
|
|
1264
|
+
onkeydown={(e) => e.key === 'Escape' && closeConfigSidebar()}
|
|
1285
1265
|
role="region"
|
|
1286
1266
|
aria-label="Workflow canvas"
|
|
1287
1267
|
>
|
|
@@ -1290,12 +1270,10 @@
|
|
|
1290
1270
|
<button
|
|
1291
1271
|
class="flowdrop-sidebar-fab"
|
|
1292
1272
|
onclick={toggleSidebar}
|
|
1293
|
-
aria-label={isSidebarCollapsed
|
|
1294
|
-
|
|
1295
|
-
: "Collapse sidebar"}
|
|
1296
|
-
title={isSidebarCollapsed ? "Expand sidebar" : "Collapse sidebar"}
|
|
1273
|
+
aria-label={isSidebarCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
|
1274
|
+
title={isSidebarCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
|
1297
1275
|
>
|
|
1298
|
-
<Icon icon={isSidebarCollapsed ?
|
|
1276
|
+
<Icon icon={isSidebarCollapsed ? 'mdi:menu' : 'mdi:menu-open'} />
|
|
1299
1277
|
</button>
|
|
1300
1278
|
{/if}
|
|
1301
1279
|
|
|
@@ -1306,7 +1284,7 @@
|
|
|
1306
1284
|
{width}
|
|
1307
1285
|
endpointConfig={endpointConfig ?? undefined}
|
|
1308
1286
|
{isConfigSidebarOpen}
|
|
1309
|
-
|
|
1287
|
+
{selectedNodeForConfig}
|
|
1310
1288
|
{openConfigSidebar}
|
|
1311
1289
|
{closeConfigSidebar}
|
|
1312
1290
|
{lockWorkflow}
|
|
@@ -1520,5 +1498,4 @@
|
|
|
1520
1498
|
overflow: hidden;
|
|
1521
1499
|
flex-direction: column;
|
|
1522
1500
|
}
|
|
1523
|
-
|
|
1524
1501
|
</style>
|