@invect/ui 0.0.1
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/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/Invect-CWpIwZ5F.js +92738 -0
- package/dist/Invect.d.ts +25 -0
- package/dist/InvectShell.d.ts +14 -0
- package/dist/api/agent-tools.api.d.ts +1 -0
- package/dist/api/client.d.ts +207 -0
- package/dist/api/credentials.api.d.ts +47 -0
- package/dist/api/executions.api.d.ts +43 -0
- package/dist/api/flows.api.d.ts +100 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/node-data.api.d.ts +66 -0
- package/dist/api/query-keys.d.ts +22 -0
- package/dist/api/triggers.api.d.ts +44 -0
- package/dist/api/types.d.ts +147 -0
- package/dist/api/use-flow-run-stream.d.ts +12 -0
- package/dist/assets/invect-branding.d.ts +4 -0
- package/dist/assets/provider-icons/index.d.ts +8 -0
- package/dist/babel-C9OtljFZ.js +9721 -0
- package/dist/components/PageLayout.d.ts +17 -0
- package/dist/components/chat/ChatInput.d.ts +17 -0
- package/dist/components/chat/ChatMessageList.d.ts +14 -0
- package/dist/components/chat/ChatModelSelector.d.ts +11 -0
- package/dist/components/chat/ChatPanel.d.ts +19 -0
- package/dist/components/chat/ChatPromptOverlay.d.ts +13 -0
- package/dist/components/chat/ChatProviderSelector.d.ts +9 -0
- package/dist/components/chat/ChatSettingsPanel.d.ts +11 -0
- package/dist/components/chat/InlineCredentialSetup.d.ts +9 -0
- package/dist/components/chat/MarkdownRenderer.d.ts +7 -0
- package/dist/components/chat/chat-memory.d.ts +21 -0
- package/dist/components/chat/chat.store.d.ts +416 -0
- package/dist/components/chat/index.d.ts +5 -0
- package/dist/components/chat/use-chat.d.ts +28 -0
- package/dist/components/credentials/CreateCredentialModal.d.ts +13 -0
- package/dist/components/credentials/CredentialDetailDialog.d.ts +17 -0
- package/dist/components/credentials/EditCredentialModal.d.ts +11 -0
- package/dist/components/credentials/OAuth2ConnectButton.d.ts +38 -0
- package/dist/components/credentials/OAuth2ProviderSelector.d.ts +15 -0
- package/dist/components/credentials/credential-utils.d.ts +12 -0
- package/dist/components/credentials/index.d.ts +9 -0
- package/dist/components/dashboard/FailedRunsAlert.d.ts +3 -0
- package/dist/components/dashboard/FlowCard.d.ts +7 -0
- package/dist/components/dashboard/RecentActivityTable.d.ts +9 -0
- package/dist/components/dashboard/StatCard.d.ts +10 -0
- package/dist/components/dashboard/index.d.ts +5 -0
- package/dist/components/dashboard/status-helpers.d.ts +5 -0
- package/dist/components/flow-editor/ActionsSidebar.d.ts +2 -0
- package/dist/components/flow-editor/FlowEditor.d.ts +21 -0
- package/dist/components/flow-editor/FlowHeader.d.ts +9 -0
- package/dist/components/flow-editor/FlowLayout.d.ts +24 -0
- package/dist/components/flow-editor/ModeSwitcher.d.ts +7 -0
- package/dist/components/flow-editor/NodeSidebar.d.ts +24 -0
- package/dist/components/flow-editor/RunControls.d.ts +12 -0
- package/dist/components/flow-editor/ToolConfigPanel.d.ts +16 -0
- package/dist/components/flow-editor/ValidationPanel.d.ts +5 -0
- package/dist/components/flow-editor/flow-editor.store.d.ts +1 -0
- package/dist/components/flow-editor/index.d.ts +6 -0
- package/dist/components/flow-editor/inline-edit.d.ts +10 -0
- package/dist/components/flow-editor/node-config-panel/ConfigFieldWithTemplate.d.ts +26 -0
- package/dist/components/flow-editor/node-config-panel/CredentialCombobox.d.ts +21 -0
- package/dist/components/flow-editor/node-config-panel/CredentialsSection.d.ts +19 -0
- package/dist/components/flow-editor/node-config-panel/DroppableInput.d.ts +20 -0
- package/dist/components/flow-editor/node-config-panel/DynamicSelectField.d.ts +22 -0
- package/dist/components/flow-editor/node-config-panel/JsonPreviewPanel.d.ts +25 -0
- package/dist/components/flow-editor/node-config-panel/NodeConfigPanel.d.ts +14 -0
- package/dist/components/flow-editor/node-config-panel/NodeConfigPanelHeader.d.ts +15 -0
- package/dist/components/flow-editor/node-config-panel/ParametersSection.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/SearchableSelectField.d.ts +17 -0
- package/dist/components/flow-editor/node-config-panel/SwitchCasesField.d.ts +18 -0
- package/dist/components/flow-editor/node-config-panel/hooks/index.d.ts +2 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-node-config-panel-state.d.ts +24 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-node-execution.d.ts +46 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-upstream-slots.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/panels/AgentToolsPanel.d.ts +18 -0
- package/dist/components/flow-editor/node-config-panel/panels/ConfigurationPanel.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/panels/DataMapperPane.d.ts +40 -0
- package/dist/components/flow-editor/node-config-panel/panels/InputPanel.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/panels/OutputPanel.d.ts +7 -0
- package/dist/components/flow-editor/node-config-panel/panels/index.d.ts +4 -0
- package/dist/components/flow-editor/node-config-panel/types.d.ts +19 -0
- package/dist/components/flow-editor/node-config-panel/use-node-config-panel-store.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/use-node-config-state.d.ts +26 -0
- package/dist/components/flow-editor/node-config-panel/use-run-node.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/utils.d.ts +9 -0
- package/dist/components/flow-editor/serialize-to-sdk.d.ts +20 -0
- package/dist/components/flow-editor/toolbar-context.d.ts +2 -0
- package/dist/components/flow-editor/use-copy-paste.d.ts +7 -0
- package/dist/components/flow-editor/use-copy-paste.types.d.ts +38 -0
- package/dist/components/flow-editor/use-flow-editor.d.ts +44 -0
- package/dist/components/flow-runs-table/FlowRunsTable.d.ts +6 -0
- package/dist/components/flow-runs-table/index.d.ts +1 -0
- package/dist/components/flow-viewer/FlowRunsView.d.ts +7 -0
- package/dist/components/flow-viewer/FlowStatusView.d.ts +21 -0
- package/dist/components/flow-viewer/RunSelector.d.ts +13 -0
- package/dist/components/flow-viewer/RunsSidebar.d.ts +14 -0
- package/dist/components/flow-viewer/agent-tool-executions-list.d.ts +7 -0
- package/dist/components/flow-viewer/index.d.ts +1 -0
- package/dist/components/flow-viewer/logs-panel.d.ts +18 -0
- package/dist/components/flow-viewer/use-execution-log-data.d.ts +113 -0
- package/dist/components/graph/BatchFlowEdge.d.ts +33 -0
- package/dist/components/graph/LayoutSelector.d.ts +9 -0
- package/dist/components/graph/index.d.ts +47 -0
- package/dist/components/graph/styleUtils.d.ts +124 -0
- package/dist/components/nodes/AgentConfigPanel.d.ts +24 -0
- package/dist/components/nodes/AgentNode.d.ts +8 -0
- package/dist/components/nodes/AgentToolsBox.d.ts +41 -0
- package/dist/components/nodes/NodeAppendix.d.ts +19 -0
- package/dist/components/nodes/NodeStatusIndicator.d.ts +30 -0
- package/dist/components/nodes/NodeViewContext.d.ts +18 -0
- package/dist/components/nodes/ToolParamField.d.ts +28 -0
- package/dist/components/nodes/ToolSelectorModal.d.ts +80 -0
- package/dist/components/nodes/ToolSelectorParts.d.ts +30 -0
- package/dist/components/nodes/UniversalNode.d.ts +2 -0
- package/dist/components/nodes/createContextAwareNodes.d.ts +6 -0
- package/dist/components/nodes/index.d.ts +22 -0
- package/dist/components/nodes/nodeRegistry.d.ts +13 -0
- package/dist/components/nodes/withNodeContext.d.ts +7 -0
- package/dist/components/shared/InvectLoader.d.ts +8 -0
- package/dist/components/shared/InvectLogo.d.ts +9 -0
- package/dist/components/shared/ProviderIcon.d.ts +23 -0
- package/dist/components/side-menu/side-menu.d.ts +4 -0
- package/dist/components/sidebar/BaseSidebar.d.ts +17 -0
- package/dist/components/sidebar/index.d.ts +1 -0
- package/dist/components/triggers/CronPreview.d.ts +12 -0
- package/dist/components/triggers/index.d.ts +1 -0
- package/dist/components/ui/alert-dialog.d.ts +18 -0
- package/dist/components/ui/badge.d.ts +9 -0
- package/dist/components/ui/button.d.ts +13 -0
- package/dist/components/ui/card.d.ts +9 -0
- package/dist/components/ui/codemirror-js-editor.d.ts +25 -0
- package/dist/components/ui/codemirror-json-editor.d.ts +18 -0
- package/dist/components/ui/codemirror-nunjucks-editor.d.ts +13 -0
- package/dist/components/ui/codemirror-vscode-theme.d.ts +24 -0
- package/dist/components/ui/collapsible.d.ts +6 -0
- package/dist/components/ui/command.d.ts +18 -0
- package/dist/components/ui/dialog.d.ts +18 -0
- package/dist/components/ui/dropdown-menu.d.ts +25 -0
- package/dist/components/ui/empty-state.d.ts +21 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/popover.d.ts +10 -0
- package/dist/components/ui/resizable.d.ts +8 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/select.d.ts +18 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/slider.d.ts +4 -0
- package/dist/components/ui/switch.d.ts +3 -0
- package/dist/components/ui/table.d.ts +10 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/tooltip.d.ts +7 -0
- package/dist/components/ui/tree-view.d.ts +107 -0
- package/dist/contexts/AgentToolCallbacksContext.d.ts +23 -0
- package/dist/contexts/ApiContext.d.ts +11 -0
- package/dist/contexts/FlowDataContext.d.ts +9 -0
- package/dist/contexts/NodeRegistryContext.d.ts +14 -0
- package/dist/contexts/PluginRegistryContext.d.ts +39 -0
- package/dist/contexts/ThemeProvider.d.ts +18 -0
- package/dist/contexts/ValidationContext.d.ts +22 -0
- package/dist/demo/DemoInvect.d.ts +11 -0
- package/dist/demo/FlowViewer.d.ts +31 -0
- package/dist/demo/demo-api-client.d.ts +33 -0
- package/dist/demo/index.d.ts +6 -0
- package/dist/demo/sample-data.d.ts +1538 -0
- package/dist/demo.d.ts +2 -0
- package/dist/demo.js +2774 -0
- package/dist/estree-ClbRfS-1.js +7076 -0
- package/dist/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/iosevka-latin-400-normal.woff2 +0 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-document-title.d.ts +1 -0
- package/dist/hooks/use-flow-data.d.ts +22 -0
- package/dist/hooks/use-invect-portal-class.d.ts +21 -0
- package/dist/hooks/useFlowEditorStore.d.ts +1 -0
- package/dist/index.css +3 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +717 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/prettier.d.ts +13 -0
- package/dist/routes/all-flow-runs.d.ts +5 -0
- package/dist/routes/credentials.d.ts +5 -0
- package/dist/routes/flow-route-layout.d.ts +19 -0
- package/dist/routes/flow-runs.d.ts +5 -0
- package/dist/routes/flow.d.ts +5 -0
- package/dist/routes/home.d.ts +5 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/standalone-C3Df7W52.js +3463 -0
- package/dist/stores/executionViewStore.d.ts +64 -0
- package/dist/stores/flow-editor.store.d.ts +137 -0
- package/dist/stores/flowEditorStore.d.ts +1 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/uiStore.d.ts +45 -0
- package/dist/types/agent-tools.types.d.ts +53 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/node-definition.types.d.ts +85 -0
- package/dist/types/plugin.types.d.ts +100 -0
- package/dist/utils/credentialBranding.d.ts +8 -0
- package/dist/utils/credentialFiltering.d.ts +20 -0
- package/dist/utils/flowTransformations.d.ts +16 -0
- package/dist/utils/layoutUtils.d.ts +23 -0
- package/dist/utils/nodeReferenceUtils.d.ts +37 -0
- package/dist/vendor.d.ts +5 -0
- package/package.json +130 -0
- package/src/.DS_Store +0 -0
- package/src/Invect.tsx +229 -0
- package/src/InvectShell.tsx +55 -0
- package/src/api/agent-tools.api.ts +23 -0
- package/src/api/client.ts +899 -0
- package/src/api/credentials.api.ts +197 -0
- package/src/api/executions.api.ts +228 -0
- package/src/api/flows.api.ts +195 -0
- package/src/api/index.ts +17 -0
- package/src/api/node-data.api.ts +167 -0
- package/src/api/query-keys.ts +44 -0
- package/src/api/triggers.api.ts +120 -0
- package/src/api/types.ts +212 -0
- package/src/api/use-flow-run-stream.ts +206 -0
- package/src/app.css +560 -0
- package/src/assets/.DS_Store +0 -0
- package/src/assets/favicon.ico +0 -0
- package/src/assets/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
- package/src/assets/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
- package/src/assets/fonts/geist-latin-wght-normal.woff2 +0 -0
- package/src/assets/fonts/iosevka-latin-400-normal.woff2 +0 -0
- package/src/assets/invect-branding.ts +51 -0
- package/src/assets/provider-icons/anthropic.svg +1 -0
- package/src/assets/provider-icons/anthropic_light.svg +1 -0
- package/src/assets/provider-icons/github.svg +1 -0
- package/src/assets/provider-icons/github_light.svg +1 -0
- package/src/assets/provider-icons/gmail.svg +1 -0
- package/src/assets/provider-icons/google_calendar.svg +1 -0
- package/src/assets/provider-icons/google_docs.svg +1 -0
- package/src/assets/provider-icons/google_drive.svg +1 -0
- package/src/assets/provider-icons/google_sheets.svg +1 -0
- package/src/assets/provider-icons/index.ts +55 -0
- package/src/assets/provider-icons/linear.svg +1 -0
- package/src/assets/provider-icons/openai.svg +1 -0
- package/src/assets/provider-icons/postgres.svg +1 -0
- package/src/assets/provider-icons/slack.svg +1 -0
- package/src/assets/small-loader-dark.svg +22 -0
- package/src/assets/small-loader-light.svg +22 -0
- package/src/assets/small.svg +7 -0
- package/src/components/.DS_Store +0 -0
- package/src/components/PageLayout.tsx +55 -0
- package/src/components/chat/ChatInput.tsx +115 -0
- package/src/components/chat/ChatMessageList.tsx +788 -0
- package/src/components/chat/ChatModelSelector.tsx +208 -0
- package/src/components/chat/ChatPanel.tsx +243 -0
- package/src/components/chat/ChatPromptOverlay.tsx +150 -0
- package/src/components/chat/ChatProviderSelector.tsx +135 -0
- package/src/components/chat/ChatSettingsPanel.tsx +277 -0
- package/src/components/chat/InlineCredentialSetup.tsx +343 -0
- package/src/components/chat/MarkdownRenderer.tsx +140 -0
- package/src/components/chat/chat-memory.ts +88 -0
- package/src/components/chat/chat.store.ts +479 -0
- package/src/components/chat/index.ts +5 -0
- package/src/components/chat/use-chat.ts +473 -0
- package/src/components/credentials/CreateCredentialModal.tsx +609 -0
- package/src/components/credentials/CredentialDetailDialog.tsx +882 -0
- package/src/components/credentials/EditCredentialModal.tsx +399 -0
- package/src/components/credentials/OAuth2ConnectButton.tsx +288 -0
- package/src/components/credentials/OAuth2ProviderSelector.tsx +360 -0
- package/src/components/credentials/credential-utils.ts +99 -0
- package/src/components/credentials/index.ts +10 -0
- package/src/components/dashboard/FailedRunsAlert.tsx +67 -0
- package/src/components/dashboard/FlowCard.tsx +64 -0
- package/src/components/dashboard/RecentActivityTable.tsx +92 -0
- package/src/components/dashboard/StatCard.tsx +32 -0
- package/src/components/dashboard/index.ts +5 -0
- package/src/components/dashboard/status-helpers.tsx +102 -0
- package/src/components/flow-editor/ActionsSidebar.tsx +503 -0
- package/src/components/flow-editor/FlowEditor.tsx +1002 -0
- package/src/components/flow-editor/FlowHeader.tsx +87 -0
- package/src/components/flow-editor/FlowLayout.tsx +117 -0
- package/src/components/flow-editor/ModeSwitcher.tsx +49 -0
- package/src/components/flow-editor/NodeSidebar.tsx +343 -0
- package/src/components/flow-editor/RunControls.tsx +109 -0
- package/src/components/flow-editor/ToolConfigPanel.tsx +434 -0
- package/src/components/flow-editor/ValidationPanel.tsx +167 -0
- package/src/components/flow-editor/flow-editor.store.ts +2 -0
- package/src/components/flow-editor/index.ts +6 -0
- package/src/components/flow-editor/inline-edit.tsx +111 -0
- package/src/components/flow-editor/node-config-panel/ConfigFieldWithTemplate.tsx +334 -0
- package/src/components/flow-editor/node-config-panel/CredentialCombobox.tsx +217 -0
- package/src/components/flow-editor/node-config-panel/CredentialsSection.tsx +154 -0
- package/src/components/flow-editor/node-config-panel/DroppableInput.tsx +45 -0
- package/src/components/flow-editor/node-config-panel/DynamicSelectField.tsx +223 -0
- package/src/components/flow-editor/node-config-panel/JsonPreviewPanel.tsx +134 -0
- package/src/components/flow-editor/node-config-panel/NodeConfigPanel.tsx +650 -0
- package/src/components/flow-editor/node-config-panel/NodeConfigPanelHeader.tsx +91 -0
- package/src/components/flow-editor/node-config-panel/ParametersSection.tsx +144 -0
- package/src/components/flow-editor/node-config-panel/SearchableSelectField.tsx +126 -0
- package/src/components/flow-editor/node-config-panel/SwitchCasesField.tsx +212 -0
- package/src/components/flow-editor/node-config-panel/hooks/index.ts +2 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-node-config-panel-state.ts +284 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-node-execution.ts +287 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-upstream-slots.ts +310 -0
- package/src/components/flow-editor/node-config-panel/panels/AgentToolsPanel.tsx +837 -0
- package/src/components/flow-editor/node-config-panel/panels/ConfigurationPanel.tsx +383 -0
- package/src/components/flow-editor/node-config-panel/panels/DataMapperPane.tsx +456 -0
- package/src/components/flow-editor/node-config-panel/panels/InputPanel.tsx +338 -0
- package/src/components/flow-editor/node-config-panel/panels/OutputPanel.tsx +109 -0
- package/src/components/flow-editor/node-config-panel/panels/index.ts +4 -0
- package/src/components/flow-editor/node-config-panel/types.ts +20 -0
- package/src/components/flow-editor/node-config-panel/use-node-config-panel-store.ts +283 -0
- package/src/components/flow-editor/node-config-panel/use-node-config-state.ts +172 -0
- package/src/components/flow-editor/node-config-panel/use-run-node.ts +147 -0
- package/src/components/flow-editor/node-config-panel/utils.ts +73 -0
- package/src/components/flow-editor/serialize-to-sdk.ts +204 -0
- package/src/components/flow-editor/toolbar-context.ts +9 -0
- package/src/components/flow-editor/use-copy-paste.ts +575 -0
- package/src/components/flow-editor/use-copy-paste.types.ts +35 -0
- package/src/components/flow-editor/use-flow-editor.ts +241 -0
- package/src/components/flow-runs-table/FlowRunsTable.tsx +631 -0
- package/src/components/flow-runs-table/index.ts +1 -0
- package/src/components/flow-viewer/FlowRunsView.tsx +268 -0
- package/src/components/flow-viewer/FlowStatusView.tsx +351 -0
- package/src/components/flow-viewer/RunSelector.tsx +422 -0
- package/src/components/flow-viewer/RunsSidebar.tsx +125 -0
- package/src/components/flow-viewer/agent-tool-executions-list.tsx +298 -0
- package/src/components/flow-viewer/index.ts +1 -0
- package/src/components/flow-viewer/logs-panel.tsx +567 -0
- package/src/components/flow-viewer/use-execution-log-data.ts +374 -0
- package/src/components/graph/BatchFlowEdge.tsx +229 -0
- package/src/components/graph/LayoutSelector.tsx +42 -0
- package/src/components/graph/index.ts +61 -0
- package/src/components/graph/styleUtils.ts +375 -0
- package/src/components/nodes/.DS_Store +0 -0
- package/src/components/nodes/AgentConfigPanel.tsx +1033 -0
- package/src/components/nodes/AgentNode.tsx +298 -0
- package/src/components/nodes/AgentToolsBox.tsx +193 -0
- package/src/components/nodes/NodeAppendix.tsx +98 -0
- package/src/components/nodes/NodeStatusIndicator.tsx +74 -0
- package/src/components/nodes/NodeViewContext.tsx +45 -0
- package/src/components/nodes/ToolParamField.tsx +282 -0
- package/src/components/nodes/ToolSelectorModal.tsx +648 -0
- package/src/components/nodes/ToolSelectorParts.tsx +505 -0
- package/src/components/nodes/UniversalNode.tsx +356 -0
- package/src/components/nodes/createContextAwareNodes.ts +19 -0
- package/src/components/nodes/index.ts +45 -0
- package/src/components/nodes/nodeRegistry.ts +50 -0
- package/src/components/nodes/withNodeContext.tsx +55 -0
- package/src/components/shared/InvectLoader.tsx +59 -0
- package/src/components/shared/InvectLogo.tsx +59 -0
- package/src/components/shared/ProviderIcon.tsx +115 -0
- package/src/components/side-menu/side-menu.tsx +267 -0
- package/src/components/sidebar/BaseSidebar.tsx +148 -0
- package/src/components/sidebar/index.ts +1 -0
- package/src/components/triggers/CronPreview.tsx +243 -0
- package/src/components/triggers/index.ts +1 -0
- package/src/components/ui/alert-dialog.tsx +152 -0
- package/src/components/ui/badge.tsx +39 -0
- package/src/components/ui/button.tsx +58 -0
- package/src/components/ui/card.tsx +75 -0
- package/src/components/ui/codemirror-js-editor.tsx +432 -0
- package/src/components/ui/codemirror-json-editor.tsx +816 -0
- package/src/components/ui/codemirror-nunjucks-editor.tsx +451 -0
- package/src/components/ui/codemirror-vscode-theme.ts +243 -0
- package/src/components/ui/collapsible.tsx +12 -0
- package/src/components/ui/command.tsx +162 -0
- package/src/components/ui/dialog.tsx +140 -0
- package/src/components/ui/dropdown-menu.tsx +232 -0
- package/src/components/ui/empty-state.tsx +93 -0
- package/src/components/ui/input.tsx +26 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/popover.tsx +53 -0
- package/src/components/ui/resizable.tsx +61 -0
- package/src/components/ui/scroll-area.tsx +56 -0
- package/src/components/ui/select.tsx +179 -0
- package/src/components/ui/separator.tsx +26 -0
- package/src/components/ui/slider.tsx +58 -0
- package/src/components/ui/switch.tsx +22 -0
- package/src/components/ui/table.tsx +90 -0
- package/src/components/ui/textarea.tsx +23 -0
- package/src/components/ui/tooltip.tsx +54 -0
- package/src/components/ui/tree-view.tsx +574 -0
- package/src/contexts/AgentToolCallbacksContext.tsx +31 -0
- package/src/contexts/ApiContext.tsx +51 -0
- package/src/contexts/FlowDataContext.tsx +21 -0
- package/src/contexts/NodeRegistryContext.tsx +54 -0
- package/src/contexts/PluginRegistryContext.tsx +182 -0
- package/src/contexts/ThemeProvider.tsx +106 -0
- package/src/contexts/ValidationContext.tsx +122 -0
- package/src/demo/DemoInvect.tsx +42 -0
- package/src/demo/FlowViewer.tsx +294 -0
- package/src/demo/demo-api-client.ts +246 -0
- package/src/demo/index.ts +28 -0
- package/src/demo/sample-data.ts +1980 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-document-title.ts +8 -0
- package/src/hooks/use-flow-data.ts +144 -0
- package/src/hooks/use-invect-portal-class.ts +27 -0
- package/src/hooks/useFlowEditorStore.ts +2 -0
- package/src/index.ts +70 -0
- package/src/lib/utils.ts +6 -0
- package/src/prettier.d.ts +13 -0
- package/src/routes/all-flow-runs.tsx +27 -0
- package/src/routes/credentials.tsx +362 -0
- package/src/routes/flow-route-layout.tsx +113 -0
- package/src/routes/flow-runs.tsx +22 -0
- package/src/routes/flow.tsx +22 -0
- package/src/routes/home.tsx +282 -0
- package/src/services/index.ts +6 -0
- package/src/stores/executionViewStore.ts +211 -0
- package/src/stores/flow-editor.store.ts +738 -0
- package/src/stores/flowEditorStore.ts +2 -0
- package/src/stores/index.ts +10 -0
- package/src/stores/uiStore.ts +189 -0
- package/src/types/agent-tools.types.ts +64 -0
- package/src/types/index.ts +5 -0
- package/src/types/node-definition.types.ts +104 -0
- package/src/types/plugin.types.ts +123 -0
- package/src/utils/credentialBranding.ts +116 -0
- package/src/utils/credentialFiltering.ts +68 -0
- package/src/utils/flowTransformations.ts +137 -0
- package/src/utils/layoutUtils.ts +127 -0
- package/src/utils/nodeReferenceUtils.ts +135 -0
- package/src/vendor.d.ts +7 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
2
|
+
import type { Node, Edge } from '@xyflow/react';
|
|
3
|
+
import { parseJson, stringifyJson } from '../utils';
|
|
4
|
+
import { useFlowEditorStore } from '../../flow-editor.store';
|
|
5
|
+
import type { ReactFlowNodeData } from '@invect/core/types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate a slug from a label string (snake_case, alphanumeric only)
|
|
9
|
+
*/
|
|
10
|
+
function generateSlug(label: string): string {
|
|
11
|
+
return label
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
14
|
+
.replace(/^_+|_+$/g, '')
|
|
15
|
+
.substring(0, 50);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Compute input data for a node based on its incoming edges.
|
|
20
|
+
* Maps output data from source nodes using their reference_id as keys.
|
|
21
|
+
* Structure matches the backend's buildIncomingDataObject format for template resolution.
|
|
22
|
+
*
|
|
23
|
+
* Example output:
|
|
24
|
+
* {
|
|
25
|
+
* "some_node": { output: "value from some_node" },
|
|
26
|
+
* "other_node": { output: "value from other_node" }
|
|
27
|
+
* }
|
|
28
|
+
*/
|
|
29
|
+
// Extended node data type that includes preview-related properties
|
|
30
|
+
// These are runtime properties added during editing, not part of the base ReactFlowNodeData type
|
|
31
|
+
interface ExtendedNodeData {
|
|
32
|
+
id?: string;
|
|
33
|
+
type?: string;
|
|
34
|
+
display_name?: string;
|
|
35
|
+
reference_id?: string;
|
|
36
|
+
status?: string;
|
|
37
|
+
executionStatus?: string;
|
|
38
|
+
executionError?: string;
|
|
39
|
+
executionOutput?: unknown;
|
|
40
|
+
params?: Record<string, unknown>;
|
|
41
|
+
inputs?: unknown;
|
|
42
|
+
outputs?: unknown;
|
|
43
|
+
// Preview/editor-specific properties
|
|
44
|
+
previewInput?: unknown;
|
|
45
|
+
previewOutput?: unknown;
|
|
46
|
+
mockInputData?: unknown;
|
|
47
|
+
mockOutputData?: unknown;
|
|
48
|
+
lastInputs?: unknown;
|
|
49
|
+
exampleInput?: unknown;
|
|
50
|
+
exampleOutput?: unknown;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function computeInputFromEdges(
|
|
54
|
+
targetNodeId: string,
|
|
55
|
+
nodes: Node[],
|
|
56
|
+
edges: Edge[],
|
|
57
|
+
): Record<string, unknown> {
|
|
58
|
+
const incomingEdges = edges.filter((edge) => edge.target === targetNodeId);
|
|
59
|
+
|
|
60
|
+
if (incomingEdges.length === 0) {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const inputData: Record<string, unknown> = {};
|
|
65
|
+
|
|
66
|
+
for (const edge of incomingEdges) {
|
|
67
|
+
const sourceNode = nodes.find((n) => n.id === edge.source);
|
|
68
|
+
if (!sourceNode) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Cast to access ReactFlowNodeData properties at runtime
|
|
73
|
+
const sourceNodeData = sourceNode.data as ExtendedNodeData;
|
|
74
|
+
const displayName = sourceNodeData.display_name || sourceNode.id;
|
|
75
|
+
|
|
76
|
+
// Use reference_id if available, otherwise generate slug from display name
|
|
77
|
+
const slug = sourceNodeData.reference_id || generateSlug(displayName);
|
|
78
|
+
|
|
79
|
+
// Get the output data from the source node
|
|
80
|
+
const sourceOutput =
|
|
81
|
+
sourceNodeData.previewOutput ??
|
|
82
|
+
sourceNodeData.executionOutput ??
|
|
83
|
+
sourceNodeData.mockOutputData ??
|
|
84
|
+
sourceNodeData.exampleOutput;
|
|
85
|
+
|
|
86
|
+
if (sourceOutput !== undefined && sourceOutput !== null) {
|
|
87
|
+
// Map directly: { slug: outputValue }
|
|
88
|
+
// This allows templates to use {{ slug }} directly for the output value
|
|
89
|
+
inputData[slug] = sourceOutput;
|
|
90
|
+
} else {
|
|
91
|
+
// Source node has not been run yet - show placeholder
|
|
92
|
+
inputData[slug] = `[NO DATA]`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return inputData;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface UsePreviewStateOptions {
|
|
100
|
+
nodeId: string | null;
|
|
101
|
+
updateNodeData: (nodeId: string, data: Partial<ReactFlowNodeData>) => void;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function usePreviewState({ nodeId, updateNodeData }: UsePreviewStateOptions) {
|
|
105
|
+
// Use Zustand store as source of truth instead of React Flow's internal store
|
|
106
|
+
const nodes = useFlowEditorStore((s) => s.nodes);
|
|
107
|
+
const edges = useFlowEditorStore((s) => s.edges);
|
|
108
|
+
|
|
109
|
+
// Find the current node from our store
|
|
110
|
+
const node = useMemo(() => {
|
|
111
|
+
if (!nodeId) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return nodes.find((n) => n.id === nodeId) ?? null;
|
|
115
|
+
}, [nodeId, nodes]);
|
|
116
|
+
|
|
117
|
+
const [inputPreview, setInputPreview] = useState('');
|
|
118
|
+
const [outputPreview, setOutputPreview] = useState('');
|
|
119
|
+
const [inputError, setInputError] = useState<string | null>(null);
|
|
120
|
+
const [outputError, setOutputError] = useState<string | null>(null);
|
|
121
|
+
|
|
122
|
+
// Test mode state
|
|
123
|
+
const [isTestMode, setIsTestMode] = useState(false);
|
|
124
|
+
const [originalInputPreview, setOriginalInputPreview] = useState<string | null>(null);
|
|
125
|
+
|
|
126
|
+
const prevNodeIdRef = useRef<string | null>(null);
|
|
127
|
+
|
|
128
|
+
// Initialize previews when node changes
|
|
129
|
+
useEffect(() => {
|
|
130
|
+
const nodeIdChanged = prevNodeIdRef.current !== nodeId;
|
|
131
|
+
prevNodeIdRef.current = nodeId;
|
|
132
|
+
|
|
133
|
+
if (!node || !nodeId) {
|
|
134
|
+
setInputPreview('');
|
|
135
|
+
setOutputPreview('');
|
|
136
|
+
setInputError(null);
|
|
137
|
+
setOutputError(null);
|
|
138
|
+
setIsTestMode(false);
|
|
139
|
+
setOriginalInputPreview(null);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (nodeIdChanged) {
|
|
144
|
+
// Cast to extended type to access preview properties
|
|
145
|
+
const currentNodeData = node.data as ExtendedNodeData;
|
|
146
|
+
const computedInput = computeInputFromEdges(nodeId, nodes, edges);
|
|
147
|
+
const hasComputedInput = Object.keys(computedInput).length > 0;
|
|
148
|
+
|
|
149
|
+
let initialInput: string;
|
|
150
|
+
if (currentNodeData.previewInput) {
|
|
151
|
+
initialInput = stringifyJson(currentNodeData.previewInput);
|
|
152
|
+
} else if (hasComputedInput) {
|
|
153
|
+
initialInput = stringifyJson(computedInput);
|
|
154
|
+
} else {
|
|
155
|
+
initialInput = stringifyJson(
|
|
156
|
+
currentNodeData.mockInputData ??
|
|
157
|
+
currentNodeData.lastInputs ??
|
|
158
|
+
currentNodeData.exampleInput ??
|
|
159
|
+
{},
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
setInputPreview(initialInput);
|
|
164
|
+
setOriginalInputPreview(initialInput);
|
|
165
|
+
setIsTestMode(false);
|
|
166
|
+
|
|
167
|
+
setOutputPreview(
|
|
168
|
+
stringifyJson(
|
|
169
|
+
currentNodeData.previewOutput ??
|
|
170
|
+
currentNodeData.executionOutput ??
|
|
171
|
+
currentNodeData.mockOutputData ??
|
|
172
|
+
currentNodeData.exampleOutput ??
|
|
173
|
+
{},
|
|
174
|
+
),
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
setInputError(null);
|
|
178
|
+
setOutputError(null);
|
|
179
|
+
}
|
|
180
|
+
}, [nodeId, nodes, edges, node]);
|
|
181
|
+
|
|
182
|
+
const handleInputPreviewChange = useCallback(
|
|
183
|
+
(value: string) => {
|
|
184
|
+
setInputPreview(value);
|
|
185
|
+
setInputError(null);
|
|
186
|
+
|
|
187
|
+
if (originalInputPreview !== null && value !== originalInputPreview) {
|
|
188
|
+
setIsTestMode(true);
|
|
189
|
+
} else if (value === originalInputPreview) {
|
|
190
|
+
setIsTestMode(false);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (nodeId) {
|
|
194
|
+
const parsed = parseJson(value, setInputError);
|
|
195
|
+
if (parsed !== null) {
|
|
196
|
+
// Note: previewInput is an extended property, cast is needed
|
|
197
|
+
updateNodeData(nodeId, { previewInput: parsed } as Partial<ReactFlowNodeData>);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
[nodeId, updateNodeData, originalInputPreview],
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const handleOutputPreviewChange = useCallback(
|
|
205
|
+
(value: string) => {
|
|
206
|
+
setOutputPreview(value);
|
|
207
|
+
setOutputError(null);
|
|
208
|
+
|
|
209
|
+
if (nodeId) {
|
|
210
|
+
const parsed = parseJson(value, setOutputError);
|
|
211
|
+
if (parsed !== null) {
|
|
212
|
+
// Note: previewOutput is an extended property, cast is needed
|
|
213
|
+
updateNodeData(nodeId, { previewOutput: parsed } as Partial<ReactFlowNodeData>);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
[nodeId, updateNodeData],
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const handleResetTestMode = useCallback(() => {
|
|
221
|
+
if (originalInputPreview !== null) {
|
|
222
|
+
setInputPreview(originalInputPreview);
|
|
223
|
+
setIsTestMode(false);
|
|
224
|
+
|
|
225
|
+
if (nodeId) {
|
|
226
|
+
const parsed = parseJson(originalInputPreview, setInputError);
|
|
227
|
+
if (parsed !== null) {
|
|
228
|
+
// Note: previewInput is an extended property, cast is needed
|
|
229
|
+
updateNodeData(nodeId, { previewInput: parsed } as Partial<ReactFlowNodeData>);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}, [originalInputPreview, nodeId, updateNodeData]);
|
|
234
|
+
|
|
235
|
+
const updateFromExecution = useCallback((newInput: string, newOutput: string) => {
|
|
236
|
+
setInputPreview(newInput);
|
|
237
|
+
setOriginalInputPreview(newInput);
|
|
238
|
+
setOutputPreview(newOutput);
|
|
239
|
+
setIsTestMode(false);
|
|
240
|
+
}, []);
|
|
241
|
+
|
|
242
|
+
// Refresh input preview from edges (used after running upstream nodes)
|
|
243
|
+
const refreshInputFromEdges = useCallback(() => {
|
|
244
|
+
if (!nodeId) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const computedInput = computeInputFromEdges(nodeId, nodes, edges);
|
|
249
|
+
const newInputStr = stringifyJson(computedInput);
|
|
250
|
+
|
|
251
|
+
setInputPreview(newInputStr);
|
|
252
|
+
setOriginalInputPreview(newInputStr);
|
|
253
|
+
setIsTestMode(false);
|
|
254
|
+
setInputError(null);
|
|
255
|
+
}, [nodeId, nodes, edges]);
|
|
256
|
+
|
|
257
|
+
// Get upstream variable names (reference IDs from connected upstream nodes)
|
|
258
|
+
const upstreamVariables = useMemo(() => {
|
|
259
|
+
if (!nodeId) {
|
|
260
|
+
return [];
|
|
261
|
+
}
|
|
262
|
+
const computedInput = computeInputFromEdges(nodeId, nodes, edges);
|
|
263
|
+
return Object.keys(computedInput);
|
|
264
|
+
}, [nodeId, nodes, edges]);
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
inputPreview,
|
|
268
|
+
outputPreview,
|
|
269
|
+
inputError,
|
|
270
|
+
outputError,
|
|
271
|
+
isTestMode,
|
|
272
|
+
originalInputPreview,
|
|
273
|
+
upstreamVariables,
|
|
274
|
+
setInputPreview,
|
|
275
|
+
setOutputPreview,
|
|
276
|
+
setInputError,
|
|
277
|
+
setOutputError,
|
|
278
|
+
handleInputPreviewChange,
|
|
279
|
+
handleOutputPreviewChange,
|
|
280
|
+
handleResetTestMode,
|
|
281
|
+
updateFromExecution,
|
|
282
|
+
refreshInputFromEdges,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
import { parseJson, stringifyJson } from '../utils';
|
|
3
|
+
import type { UseMutationResult } from '@tanstack/react-query';
|
|
4
|
+
|
|
5
|
+
// Options for save operation
|
|
6
|
+
interface SaveOptions {
|
|
7
|
+
skipSuccessToast?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Flow actions interface
|
|
11
|
+
interface FlowActions {
|
|
12
|
+
onExecute: () => Promise<void>;
|
|
13
|
+
isExecuting: boolean;
|
|
14
|
+
isDirty?: boolean;
|
|
15
|
+
onSave?: (options?: SaveOptions) => Promise<boolean>;
|
|
16
|
+
isSaving?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ExecutionResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
output?: unknown;
|
|
22
|
+
error?: string;
|
|
23
|
+
fieldErrors?: Record<string, string>;
|
|
24
|
+
traces?: Array<{
|
|
25
|
+
nodeId: string;
|
|
26
|
+
inputs: unknown;
|
|
27
|
+
outputs: unknown;
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Type for the executeFlowToNode mutation
|
|
32
|
+
type ExecuteFlowToNodeMutation = UseMutationResult<
|
|
33
|
+
unknown,
|
|
34
|
+
Error,
|
|
35
|
+
{
|
|
36
|
+
flowId: string;
|
|
37
|
+
nodeId: string;
|
|
38
|
+
inputs?: Record<string, unknown>;
|
|
39
|
+
options?: { useBatchProcessing?: boolean };
|
|
40
|
+
}
|
|
41
|
+
>;
|
|
42
|
+
|
|
43
|
+
// Type for the testNode mutation
|
|
44
|
+
type TestNodeMutation = UseMutationResult<
|
|
45
|
+
unknown,
|
|
46
|
+
Error,
|
|
47
|
+
{
|
|
48
|
+
nodeType: string;
|
|
49
|
+
params: Record<string, unknown>;
|
|
50
|
+
inputs: Record<string, unknown>;
|
|
51
|
+
}
|
|
52
|
+
>;
|
|
53
|
+
|
|
54
|
+
interface UseNodeExecutionOptions {
|
|
55
|
+
nodeId: string | null;
|
|
56
|
+
flowId: string;
|
|
57
|
+
nodeType: string;
|
|
58
|
+
nodeParams: Record<string, unknown>;
|
|
59
|
+
executeFlowToNodeMutation: ExecuteFlowToNodeMutation;
|
|
60
|
+
testNodeMutation?: TestNodeMutation;
|
|
61
|
+
flowActions: FlowActions | null;
|
|
62
|
+
updateNodeData: (nodeId: string, data: Record<string, unknown>) => void;
|
|
63
|
+
isTestMode: boolean;
|
|
64
|
+
inputPreview: string;
|
|
65
|
+
onExecutionComplete: (input: string, output: string) => void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Extract output value from the structured node output format
|
|
70
|
+
*/
|
|
71
|
+
function extractOutputValue(nodeOutput: unknown): unknown {
|
|
72
|
+
if (!nodeOutput || typeof nodeOutput !== 'object') {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const typedOutput = nodeOutput as { data?: { variables?: Record<string, { value: unknown }> } };
|
|
77
|
+
|
|
78
|
+
if (typedOutput.data?.variables?.output) {
|
|
79
|
+
const outputVar = typedOutput.data.variables.output;
|
|
80
|
+
return outputVar && typeof outputVar === 'object' && 'value' in outputVar
|
|
81
|
+
? outputVar.value
|
|
82
|
+
: outputVar;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (typedOutput.data?.variables) {
|
|
86
|
+
const firstVar = Object.values(typedOutput.data.variables)[0];
|
|
87
|
+
return firstVar && typeof firstVar === 'object' && 'value' in firstVar
|
|
88
|
+
? firstVar.value
|
|
89
|
+
: firstVar;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Parse Zod prettifyError output to extract per-field error messages.
|
|
97
|
+
* Zod v4 errors look like: "✕ Invalid input: expected string, received undefined\n → at to"
|
|
98
|
+
* Multiple errors are separated by newlines.
|
|
99
|
+
*/
|
|
100
|
+
function parseFieldErrorsFromString(errorStr: string): Record<string, string> | null {
|
|
101
|
+
const fieldErrors: Record<string, string> = {};
|
|
102
|
+
// Split on the arrow marker and extract "message → at fieldName" pairs
|
|
103
|
+
const parts = errorStr.split('→');
|
|
104
|
+
for (let i = 1; i < parts.length; i++) {
|
|
105
|
+
const afterArrow = parts[i].match(/^\s*at\s+(\w+)/);
|
|
106
|
+
if (!afterArrow) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const fieldName = afterArrow[1];
|
|
110
|
+
// Message is everything in the previous part (after any prior field match)
|
|
111
|
+
const rawMessage = (parts[i - 1] ?? '').replace(/\n[ \t]*$/, '');
|
|
112
|
+
// Take the last line as the message (handles multi-error strings)
|
|
113
|
+
const lastLine = rawMessage.split('\n').pop() ?? '';
|
|
114
|
+
const message = lastLine.replace(/^[✕×]\s*/, '').trim();
|
|
115
|
+
if (fieldName && message) {
|
|
116
|
+
fieldErrors[fieldName] = message;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return Object.keys(fieldErrors).length > 0 ? fieldErrors : null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function useNodeExecution({
|
|
123
|
+
nodeId,
|
|
124
|
+
flowId,
|
|
125
|
+
nodeType,
|
|
126
|
+
nodeParams,
|
|
127
|
+
executeFlowToNodeMutation,
|
|
128
|
+
testNodeMutation,
|
|
129
|
+
flowActions,
|
|
130
|
+
updateNodeData,
|
|
131
|
+
isTestMode,
|
|
132
|
+
inputPreview,
|
|
133
|
+
onExecutionComplete,
|
|
134
|
+
}: UseNodeExecutionOptions) {
|
|
135
|
+
const [isRunning, setIsRunning] = useState(false);
|
|
136
|
+
const [runError, setRunError] = useState<string | null>(null);
|
|
137
|
+
const [outputError, setOutputError] = useState<string | null>(null);
|
|
138
|
+
const [fieldErrors, setFieldErrors] = useState<Record<string, string> | null>(null);
|
|
139
|
+
|
|
140
|
+
const runNode = useCallback(async () => {
|
|
141
|
+
if (!nodeId || !flowId) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
setIsRunning(true);
|
|
146
|
+
setRunError(null);
|
|
147
|
+
setOutputError(null);
|
|
148
|
+
setFieldErrors(null);
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
// Auto-save flow before running
|
|
152
|
+
if (flowActions?.onSave) {
|
|
153
|
+
const saveSucceeded = await flowActions.onSave({ skipSuccessToast: true });
|
|
154
|
+
if (!saveSucceeded) {
|
|
155
|
+
setRunError('Failed to save flow. Please fix any validation errors and try again.');
|
|
156
|
+
setOutputError('Save failed - check node configuration');
|
|
157
|
+
setIsRunning(false);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (isTestMode) {
|
|
163
|
+
// Test mode: run single node with custom input
|
|
164
|
+
if (!testNodeMutation) {
|
|
165
|
+
setRunError('Test mode is not available');
|
|
166
|
+
setOutputError('Test mode is not available');
|
|
167
|
+
setIsRunning(false);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const testInput = parseJson(inputPreview, () => ({})) || {};
|
|
172
|
+
const result = (await testNodeMutation.mutateAsync({
|
|
173
|
+
nodeType,
|
|
174
|
+
params: nodeParams,
|
|
175
|
+
inputs: testInput,
|
|
176
|
+
})) as ExecutionResult;
|
|
177
|
+
|
|
178
|
+
if (result.success && result.output) {
|
|
179
|
+
const output = extractOutputValue(result.output) ?? result.output;
|
|
180
|
+
const displayValue = typeof output === 'string' ? output : stringifyJson(output);
|
|
181
|
+
|
|
182
|
+
updateNodeData(nodeId, { previewOutput: output });
|
|
183
|
+
onExecutionComplete(inputPreview, displayValue);
|
|
184
|
+
} else {
|
|
185
|
+
setRunError(result.error || 'Test execution failed');
|
|
186
|
+
setOutputError(result.error || 'Test execution failed');
|
|
187
|
+
if (result.fieldErrors) {
|
|
188
|
+
setFieldErrors(result.fieldErrors);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
// Normal mode: run flow up to this node
|
|
193
|
+
const result = (await executeFlowToNodeMutation.mutateAsync({
|
|
194
|
+
flowId,
|
|
195
|
+
nodeId,
|
|
196
|
+
inputs: {},
|
|
197
|
+
options: { useBatchProcessing: false },
|
|
198
|
+
})) as {
|
|
199
|
+
status: string;
|
|
200
|
+
error?: string;
|
|
201
|
+
nodeErrors?: Record<string, string>;
|
|
202
|
+
traces?: Array<{ nodeId: string; inputs: unknown; outputs: unknown; error?: string }>;
|
|
203
|
+
outputs?: Record<string, unknown>;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
if (result.status === 'SUCCESS') {
|
|
207
|
+
// Update all executed nodes from traces
|
|
208
|
+
if (result.traces && Array.isArray(result.traces)) {
|
|
209
|
+
for (const trace of result.traces) {
|
|
210
|
+
const traceNodeId = trace.nodeId;
|
|
211
|
+
if (!traceNodeId) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const traceOutput = extractOutputValue(trace.outputs);
|
|
216
|
+
updateNodeData(traceNodeId, {
|
|
217
|
+
previewInput: trace.inputs,
|
|
218
|
+
previewOutput: traceOutput,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Get current node's output
|
|
224
|
+
const nodeOutput = result.outputs?.[nodeId];
|
|
225
|
+
const output = extractOutputValue(nodeOutput);
|
|
226
|
+
const displayValue = typeof output === 'string' ? output : stringifyJson(output);
|
|
227
|
+
|
|
228
|
+
// Get current node's input from trace
|
|
229
|
+
const currentTrace = result.traces?.find((t: { nodeId: string }) => t.nodeId === nodeId);
|
|
230
|
+
const newInputPreview = currentTrace?.inputs
|
|
231
|
+
? stringifyJson(currentTrace.inputs)
|
|
232
|
+
: inputPreview;
|
|
233
|
+
|
|
234
|
+
onExecutionComplete(newInputPreview, displayValue);
|
|
235
|
+
} else if (result.status === 'PAUSED_FOR_BATCH') {
|
|
236
|
+
setRunError('Execution paused for batch processing. Check the Runs view for status.');
|
|
237
|
+
setOutputError('Waiting for batch processing...');
|
|
238
|
+
} else {
|
|
239
|
+
// Extract the most specific error available:
|
|
240
|
+
// 1. Error for this specific node from nodeErrors
|
|
241
|
+
// 2. Top-level error from the result
|
|
242
|
+
// 3. Error from the failed trace
|
|
243
|
+
// 4. Generic fallback
|
|
244
|
+
const specificError =
|
|
245
|
+
result.nodeErrors?.[nodeId] ||
|
|
246
|
+
result.error ||
|
|
247
|
+
result.traces?.find((t) => t.error)?.error ||
|
|
248
|
+
'Node execution failed';
|
|
249
|
+
setRunError(specificError);
|
|
250
|
+
setOutputError(specificError);
|
|
251
|
+
// Try to parse field-specific errors from the error string
|
|
252
|
+
const parsed = parseFieldErrorsFromString(specificError);
|
|
253
|
+
if (parsed) {
|
|
254
|
+
setFieldErrors(parsed);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
} catch (error) {
|
|
259
|
+
const errorMessage = error instanceof Error ? error.message : 'An unexpected error occurred';
|
|
260
|
+
setRunError(errorMessage);
|
|
261
|
+
setOutputError(errorMessage);
|
|
262
|
+
} finally {
|
|
263
|
+
setIsRunning(false);
|
|
264
|
+
}
|
|
265
|
+
}, [
|
|
266
|
+
executeFlowToNodeMutation,
|
|
267
|
+
testNodeMutation,
|
|
268
|
+
nodeId,
|
|
269
|
+
flowId,
|
|
270
|
+
flowActions,
|
|
271
|
+
isTestMode,
|
|
272
|
+
inputPreview,
|
|
273
|
+
nodeType,
|
|
274
|
+
nodeParams,
|
|
275
|
+
updateNodeData,
|
|
276
|
+
onExecutionComplete,
|
|
277
|
+
]);
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
isRunning,
|
|
281
|
+
runError,
|
|
282
|
+
outputError,
|
|
283
|
+
fieldErrors,
|
|
284
|
+
runNode,
|
|
285
|
+
setOutputError,
|
|
286
|
+
};
|
|
287
|
+
}
|