@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,356 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { Handle, Position, type NodeProps } from '@xyflow/react';
|
|
5
|
+
import { Card } from '../ui/card';
|
|
6
|
+
import { useNodeRegistry } from '../../contexts/NodeRegistryContext';
|
|
7
|
+
import { GraphNodeType, NodeExecutionStatus } from '@invect/core/types';
|
|
8
|
+
import type { NodeDefinition, NodeHandleDefinition } from '../../types/node-definition.types';
|
|
9
|
+
import { cn } from '../../lib/utils';
|
|
10
|
+
import { Loader2 } from 'lucide-react';
|
|
11
|
+
import { ProviderIcon } from '../shared/ProviderIcon';
|
|
12
|
+
|
|
13
|
+
// Stable style objects for Handles - avoids creating new objects on every render
|
|
14
|
+
const INPUT_HANDLE_STYLE = { top: '50%', transform: 'translate(-54%, -50%)' } as const;
|
|
15
|
+
const OUTPUT_HANDLE_STYLE_SINGLE = { top: '50%', transform: 'translate(54%, -50%)' } as const;
|
|
16
|
+
const OUTPUT_HANDLE_INNER_STYLE = { transform: 'translateX(54%)' } as const;
|
|
17
|
+
|
|
18
|
+
// Invisible handle styles for loading placeholder
|
|
19
|
+
const HIDDEN_HANDLE_STYLE_TRUE = {
|
|
20
|
+
top: '30%',
|
|
21
|
+
transform: 'translate(54%, -50%)',
|
|
22
|
+
opacity: 0,
|
|
23
|
+
width: 1,
|
|
24
|
+
height: 1,
|
|
25
|
+
} as const;
|
|
26
|
+
const HIDDEN_HANDLE_STYLE_FALSE = {
|
|
27
|
+
top: '70%',
|
|
28
|
+
transform: 'translate(54%, -50%)',
|
|
29
|
+
opacity: 0,
|
|
30
|
+
width: 1,
|
|
31
|
+
height: 1,
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
const HANDLE_CLASS =
|
|
35
|
+
'!bg-background !w-4 !h-4 !border-2 !border-muted-foreground !rounded-full !transition-all hover:!w-[18px] hover:!h-[18px] hover:!border-primary !shadow-none !ring-0';
|
|
36
|
+
|
|
37
|
+
// Height calculation for nodes with >2 outputs (e.g. switch with multiple cases)
|
|
38
|
+
const MULTI_OUTPUT_PADDING = 16; // px padding above first handle and below last
|
|
39
|
+
const MULTI_OUTPUT_HANDLE_SPACING = 24; // px between each output handle
|
|
40
|
+
|
|
41
|
+
/** Compute node height based on output count. Must match react-flow-renderer.service.ts */
|
|
42
|
+
function getNodeHeight(outputCount: number): number {
|
|
43
|
+
if (outputCount <= 2) {
|
|
44
|
+
return 60;
|
|
45
|
+
}
|
|
46
|
+
return MULTI_OUTPUT_PADDING * 2 + (outputCount - 1) * MULTI_OUTPUT_HANDLE_SPACING;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const DEFAULT_CATEGORY_COLOR = 'bg-muted text-muted-foreground';
|
|
50
|
+
|
|
51
|
+
function getProviderAccentColor(providerId?: string): string {
|
|
52
|
+
switch (providerId) {
|
|
53
|
+
case 'core':
|
|
54
|
+
return 'border-l-blue-500';
|
|
55
|
+
case 'http':
|
|
56
|
+
return 'border-l-blue-500';
|
|
57
|
+
case 'triggers':
|
|
58
|
+
return 'border-l-emerald-500';
|
|
59
|
+
case 'gmail':
|
|
60
|
+
case 'google-drive':
|
|
61
|
+
case 'google-docs':
|
|
62
|
+
case 'google-sheets':
|
|
63
|
+
case 'google-calendar':
|
|
64
|
+
return 'border-l-amber-500';
|
|
65
|
+
case 'slack':
|
|
66
|
+
return 'border-l-purple-500';
|
|
67
|
+
case 'github':
|
|
68
|
+
return 'border-l-gray-500';
|
|
69
|
+
case 'linear':
|
|
70
|
+
return 'border-l-violet-500';
|
|
71
|
+
case 'microsoft':
|
|
72
|
+
return 'border-l-sky-500';
|
|
73
|
+
case 'postgres':
|
|
74
|
+
return 'border-l-teal-500';
|
|
75
|
+
default:
|
|
76
|
+
return 'border-l-muted-foreground';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
interface UniversalNodeData extends Record<string, unknown> {
|
|
81
|
+
type?: string;
|
|
82
|
+
display_name?: string;
|
|
83
|
+
executionStatus?: NodeExecutionStatus;
|
|
84
|
+
params?: {
|
|
85
|
+
[key: string]: unknown;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolve output handles for a node. For nodes with `dynamicOutputs`, handles
|
|
91
|
+
* are derived from the node's params (e.g. switch cases) instead of the static
|
|
92
|
+
* definition. Falls back to the definition's `outputs` array.
|
|
93
|
+
*/
|
|
94
|
+
function resolveOutputHandles(
|
|
95
|
+
definition: NodeDefinition,
|
|
96
|
+
params: Record<string, unknown> | undefined,
|
|
97
|
+
): NodeHandleDefinition[] {
|
|
98
|
+
if (!definition.dynamicOutputs) {
|
|
99
|
+
return definition.outputs ?? [];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Switch node: derive handles from params.cases + default
|
|
103
|
+
if (definition.type === 'core.switch') {
|
|
104
|
+
const cases = (params?.cases as Array<{ slug: string; label: string }>) ?? [];
|
|
105
|
+
return [
|
|
106
|
+
...cases.map((c) => ({ id: c.slug, label: c.label, type: 'any' })),
|
|
107
|
+
{ id: 'default', label: 'Default', type: 'any' },
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return definition.outputs ?? [];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Loading placeholder shown while node definition is being fetched.
|
|
116
|
+
* Renders a minimal node card with a spinner.
|
|
117
|
+
* IMPORTANT: Must render Handle components to prevent React Flow edge errors.
|
|
118
|
+
* The handles are invisible but allow edges to connect while loading.
|
|
119
|
+
* We render ALL possible handle IDs that any node type might use.
|
|
120
|
+
*/
|
|
121
|
+
const NodeLoadingPlaceholder = memo(
|
|
122
|
+
({ data, selected }: { data: UniversalNodeData; selected: boolean }) => {
|
|
123
|
+
const label = data.display_name || data.type || 'Loading...';
|
|
124
|
+
const nodeType = data.type || 'Loading';
|
|
125
|
+
|
|
126
|
+
// Compute dynamic height for switch nodes
|
|
127
|
+
const switchOutputCount =
|
|
128
|
+
data.type === 'core.switch' && Array.isArray(data.params?.cases)
|
|
129
|
+
? (data.params.cases as unknown[]).length + 1
|
|
130
|
+
: 0;
|
|
131
|
+
const placeholderHeight = switchOutputCount > 2 ? getNodeHeight(switchOutputCount) : 60;
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<Card
|
|
135
|
+
className={`relative w-[240px] flex-row py-0 items-center cursor-move transition-colors bg-card hover:bg-card/80 ${
|
|
136
|
+
selected
|
|
137
|
+
? 'border-blue-500 dark:border-blue-400 shadow-lg shadow-blue-500/25 dark:shadow-blue-400/30'
|
|
138
|
+
: 'border-sidebar-ring hover:border-muted-foreground'
|
|
139
|
+
}`}
|
|
140
|
+
style={{ height: placeholderHeight }}
|
|
141
|
+
>
|
|
142
|
+
{/* Input handle */}
|
|
143
|
+
<Handle
|
|
144
|
+
id="input"
|
|
145
|
+
type="target"
|
|
146
|
+
position={Position.Left}
|
|
147
|
+
style={INPUT_HANDLE_STYLE}
|
|
148
|
+
className={HANDLE_CLASS}
|
|
149
|
+
/>
|
|
150
|
+
|
|
151
|
+
<div className="flex items-center gap-3 px-3 py-0 overflow-hidden">
|
|
152
|
+
<div className="flex items-center justify-center w-10 h-10 shrink-0 rounded-xl bg-muted">
|
|
153
|
+
<Loader2 className="w-5 h-5 animate-spin text-muted-foreground" />
|
|
154
|
+
</div>
|
|
155
|
+
<div className="flex-1 min-w-0">
|
|
156
|
+
<div className="text-xs font-semibold tracking-tight truncate text-card-foreground">
|
|
157
|
+
{label}
|
|
158
|
+
</div>
|
|
159
|
+
<div className="font-mono text-xs tracking-tight truncate text-muted-foreground">
|
|
160
|
+
{nodeType}
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
{/* Standard output handle - visible */}
|
|
166
|
+
<Handle
|
|
167
|
+
id="output"
|
|
168
|
+
type="source"
|
|
169
|
+
position={Position.Right}
|
|
170
|
+
style={OUTPUT_HANDLE_STYLE_SINGLE}
|
|
171
|
+
className={HANDLE_CLASS}
|
|
172
|
+
/>
|
|
173
|
+
|
|
174
|
+
{/* IF_ELSE node handles - hidden but functional */}
|
|
175
|
+
<Handle
|
|
176
|
+
id="true_output"
|
|
177
|
+
type="source"
|
|
178
|
+
position={Position.Right}
|
|
179
|
+
style={HIDDEN_HANDLE_STYLE_TRUE}
|
|
180
|
+
/>
|
|
181
|
+
<Handle
|
|
182
|
+
id="false_output"
|
|
183
|
+
type="source"
|
|
184
|
+
position={Position.Right}
|
|
185
|
+
style={HIDDEN_HANDLE_STYLE_FALSE}
|
|
186
|
+
/>
|
|
187
|
+
|
|
188
|
+
{/* Switch node handles - derived from params.cases */}
|
|
189
|
+
{data.type === 'core.switch' &&
|
|
190
|
+
Array.isArray(data.params?.cases) &&
|
|
191
|
+
(data.params.cases as Array<{ slug: string }>).map((c) => (
|
|
192
|
+
<Handle
|
|
193
|
+
key={c.slug}
|
|
194
|
+
id={c.slug}
|
|
195
|
+
type="source"
|
|
196
|
+
position={Position.Right}
|
|
197
|
+
style={{ ...HIDDEN_HANDLE_STYLE_TRUE, opacity: 0, width: 1, height: 1 }}
|
|
198
|
+
/>
|
|
199
|
+
))}
|
|
200
|
+
{data.type === 'core.switch' && (
|
|
201
|
+
<Handle
|
|
202
|
+
id="default"
|
|
203
|
+
type="source"
|
|
204
|
+
position={Position.Right}
|
|
205
|
+
style={{ ...HIDDEN_HANDLE_STYLE_FALSE, opacity: 0, width: 1, height: 1 }}
|
|
206
|
+
/>
|
|
207
|
+
)}
|
|
208
|
+
</Card>
|
|
209
|
+
);
|
|
210
|
+
},
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
NodeLoadingPlaceholder.displayName = 'NodeLoadingPlaceholder';
|
|
214
|
+
|
|
215
|
+
export const UniversalNode = memo(({ data, selected }: NodeProps) => {
|
|
216
|
+
const typedData = data as UniversalNodeData;
|
|
217
|
+
const nodeType = typedData.type || GraphNodeType.TEMPLATE_STRING;
|
|
218
|
+
|
|
219
|
+
const { getNodeDefinition, isLoading: registryLoading } = useNodeRegistry();
|
|
220
|
+
const definition = getNodeDefinition(nodeType);
|
|
221
|
+
|
|
222
|
+
// Show loading placeholder if registry is still loading or definition not found
|
|
223
|
+
if (registryLoading || !definition) {
|
|
224
|
+
return <NodeLoadingPlaceholder data={typedData} selected={selected ?? false} />;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Get display name from node data or fall back to definition label
|
|
228
|
+
const label = typedData.display_name || definition.label || 'Unknown Node';
|
|
229
|
+
const providerId = definition.provider?.id;
|
|
230
|
+
const iconColorClass =
|
|
231
|
+
providerId === 'core' || providerId === 'triggers'
|
|
232
|
+
? 'bg-accent text-primary'
|
|
233
|
+
: DEFAULT_CATEGORY_COLOR;
|
|
234
|
+
|
|
235
|
+
// Get handle definitions — for dynamicOutputs nodes, derive from params
|
|
236
|
+
const inputHandle = definition.input;
|
|
237
|
+
const outputs = resolveOutputHandles(definition, typedData.params);
|
|
238
|
+
|
|
239
|
+
const hasIncomingHandle = !!inputHandle;
|
|
240
|
+
|
|
241
|
+
// Check execution status for running state
|
|
242
|
+
const isRunning =
|
|
243
|
+
typedData.executionStatus === NodeExecutionStatus.RUNNING ||
|
|
244
|
+
typedData.executionStatus === NodeExecutionStatus.PENDING ||
|
|
245
|
+
typedData.executionStatus === NodeExecutionStatus.BATCH_SUBMITTED;
|
|
246
|
+
const isSuccess = typedData.executionStatus === NodeExecutionStatus.SUCCESS;
|
|
247
|
+
const isError = typedData.executionStatus === NodeExecutionStatus.FAILED;
|
|
248
|
+
const isSkipped = typedData.executionStatus === NodeExecutionStatus.SKIPPED;
|
|
249
|
+
|
|
250
|
+
const outputHandleConfigs = outputs.map((output, index) => {
|
|
251
|
+
if (outputs.length === 1) {
|
|
252
|
+
return { output, topStyle: '50%' };
|
|
253
|
+
}
|
|
254
|
+
// >2 outputs: use pixel positioning (node grows taller to fit)
|
|
255
|
+
if (outputs.length > 2) {
|
|
256
|
+
const topPx = MULTI_OUTPUT_PADDING + index * MULTI_OUTPUT_HANDLE_SPACING;
|
|
257
|
+
return { output, topStyle: `${topPx}px` };
|
|
258
|
+
}
|
|
259
|
+
// 2 outputs (e.g. if_else): percentage positioning within standard 60px height
|
|
260
|
+
const EDGE_OFFSET = 28; // Keep outer handles closer to node edges without clipping
|
|
261
|
+
const availableSpace = 100 - EDGE_OFFSET * 2;
|
|
262
|
+
const topPercent = EDGE_OFFSET + (index / (outputs.length - 1)) * availableSpace;
|
|
263
|
+
return { output, topStyle: `${topPercent}%` };
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const nodeHeight = getNodeHeight(outputs.length);
|
|
267
|
+
|
|
268
|
+
return (
|
|
269
|
+
<Card
|
|
270
|
+
className={cn(
|
|
271
|
+
'relative w-[200px] flex-row py-0 items-center cursor-move transition-colors node-hover-bg bg-card shadow-md border-l-4',
|
|
272
|
+
getProviderAccentColor(definition?.provider?.id),
|
|
273
|
+
// Default border
|
|
274
|
+
!isRunning &&
|
|
275
|
+
!isSuccess &&
|
|
276
|
+
!isError &&
|
|
277
|
+
!isSkipped &&
|
|
278
|
+
'border-sidebar-ring hover:border-primary/80',
|
|
279
|
+
// Running state - animated gradient border
|
|
280
|
+
isRunning &&
|
|
281
|
+
'node-running-border animate-node-border rounded-xl border-y border-r border-transparent',
|
|
282
|
+
// Success state - green border
|
|
283
|
+
isSuccess && 'border-y-2 border-r-2 border-success',
|
|
284
|
+
// Error state - red border
|
|
285
|
+
isError && 'border-y-2 border-r-2 border-destructive',
|
|
286
|
+
// Skipped state - greyed out with dashed border
|
|
287
|
+
isSkipped && 'border-y-2 border-r-2 border-dashed border-muted-foreground/50 opacity-50',
|
|
288
|
+
// Selection state - change existing border color to blue for visibility
|
|
289
|
+
selected && !isRunning && !isSuccess && !isError && !isSkipped && 'node-selected',
|
|
290
|
+
)}
|
|
291
|
+
style={{ height: nodeHeight }}
|
|
292
|
+
>
|
|
293
|
+
{/* Unified Input Handle */}
|
|
294
|
+
{hasIncomingHandle && (
|
|
295
|
+
<Handle
|
|
296
|
+
id={inputHandle?.id || 'input'}
|
|
297
|
+
type="target"
|
|
298
|
+
position={Position.Left}
|
|
299
|
+
style={INPUT_HANDLE_STYLE}
|
|
300
|
+
className={HANDLE_CLASS}
|
|
301
|
+
/>
|
|
302
|
+
)}
|
|
303
|
+
|
|
304
|
+
<div className="flex items-center gap-2 px-3 py-0 overflow-hidden">
|
|
305
|
+
<div
|
|
306
|
+
className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-xl ${iconColorClass}`}
|
|
307
|
+
>
|
|
308
|
+
<ProviderIcon
|
|
309
|
+
providerId={definition.provider?.id}
|
|
310
|
+
svgIcon={definition.provider?.svgIcon}
|
|
311
|
+
icon={definition.icon}
|
|
312
|
+
className="w-6 h-6"
|
|
313
|
+
/>
|
|
314
|
+
</div>
|
|
315
|
+
<div className="flex-1 min-w-0">
|
|
316
|
+
<div className="text-xs font-semibold tracking-tight truncate text-card-foreground">
|
|
317
|
+
{label}
|
|
318
|
+
</div>
|
|
319
|
+
<div className="font-mono text-xs tracking-tight truncate text-muted-foreground">
|
|
320
|
+
{nodeType}
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
|
|
325
|
+
{/* Output Handles */}
|
|
326
|
+
{outputHandleConfigs.map(({ output, topStyle }) => {
|
|
327
|
+
// Show labels when there are multiple outputs (e.g., If/Else True/False)
|
|
328
|
+
const showLabel = outputs.length > 1;
|
|
329
|
+
return (
|
|
330
|
+
<div
|
|
331
|
+
key={output.id}
|
|
332
|
+
className="absolute right-0"
|
|
333
|
+
style={{ top: topStyle, transform: 'translateY(-50%)' }}
|
|
334
|
+
>
|
|
335
|
+
<div className="relative flex items-center">
|
|
336
|
+
<Handle
|
|
337
|
+
id={output.id}
|
|
338
|
+
type="source"
|
|
339
|
+
position={Position.Right}
|
|
340
|
+
style={OUTPUT_HANDLE_INNER_STYLE}
|
|
341
|
+
className="!relative !bg-background !w-4 !h-4 !border-2 !border-muted-foreground !rounded-full !transition-colors hover:!bg-muted hover:!border-foreground !shadow-none !ring-0"
|
|
342
|
+
/>
|
|
343
|
+
{showLabel && (
|
|
344
|
+
<div className="absolute px-1 text-xs border rounded left-8 text-card-foreground whitespace-nowrap bg-card border-sidebar-ring">
|
|
345
|
+
{output.label}
|
|
346
|
+
</div>
|
|
347
|
+
)}
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
);
|
|
351
|
+
})}
|
|
352
|
+
</Card>
|
|
353
|
+
);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
UniversalNode.displayName = 'UniversalNode';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NODE_COMPONENTS } from './nodeRegistry';
|
|
2
|
+
import { withNodeContext } from './withNodeContext';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create context-wrapped node components for all known node types.
|
|
6
|
+
* Returns the base mapping; for dynamic action-based types that aren't
|
|
7
|
+
* in NODE_COMPONENTS, use `getContextAwareComponent()` at lookup time.
|
|
8
|
+
*/
|
|
9
|
+
// eslint-disable-next-line typescript/no-explicit-any -- React node components require generic any props
|
|
10
|
+
export function createContextAwareNodes(): Record<string, React.ComponentType<any>> {
|
|
11
|
+
return Object.entries(NODE_COMPONENTS).reduce(
|
|
12
|
+
(acc, [nodeType, Component]) => {
|
|
13
|
+
acc[nodeType] = withNodeContext(Component);
|
|
14
|
+
return acc;
|
|
15
|
+
},
|
|
16
|
+
// eslint-disable-next-line typescript/no-explicit-any -- React node components require generic any props
|
|
17
|
+
{} as Record<string, React.ComponentType<any>>,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Node, NodeProps } from '@xyflow/react';
|
|
2
|
+
import { NodeExecutionStatus } from '@invect/core/types';
|
|
3
|
+
|
|
4
|
+
// New universal node component
|
|
5
|
+
export { UniversalNode } from './UniversalNode';
|
|
6
|
+
|
|
7
|
+
// Agent node with tools box
|
|
8
|
+
export { AgentNode } from './AgentNode';
|
|
9
|
+
export { NodeAppendix, type AppendixPosition } from './NodeAppendix';
|
|
10
|
+
export { AgentToolsBox, type AgentToolDisplay, type ToolCategory } from './AgentToolsBox';
|
|
11
|
+
export { type ToolDefinition, type AddedToolInstance } from './ToolSelectorModal';
|
|
12
|
+
export { ToolParamField, type AddCredentialRequest } from './ToolParamField';
|
|
13
|
+
|
|
14
|
+
// Node status indicator for showing execution status
|
|
15
|
+
export {
|
|
16
|
+
NodeStatusIndicator,
|
|
17
|
+
type NodeStatusIndicatorStatus,
|
|
18
|
+
type NodeStatusIndicatorLoadingVariant,
|
|
19
|
+
} from './NodeStatusIndicator';
|
|
20
|
+
|
|
21
|
+
// Context-based node utilities
|
|
22
|
+
export {
|
|
23
|
+
NodeViewProvider,
|
|
24
|
+
useNodeViewContext,
|
|
25
|
+
type NodeViewMode,
|
|
26
|
+
type NodeViewProviderProps,
|
|
27
|
+
} from './NodeViewContext';
|
|
28
|
+
export { withNodeContext } from './withNodeContext';
|
|
29
|
+
export { createContextAwareNodes } from './createContextAwareNodes';
|
|
30
|
+
|
|
31
|
+
// Export from node registry
|
|
32
|
+
export { NODE_COMPONENTS, getNodeComponent, type NodeComponentType } from './nodeRegistry';
|
|
33
|
+
|
|
34
|
+
// Common node data interface
|
|
35
|
+
export interface BaseNodeData {
|
|
36
|
+
// display_name?: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
icon?: string;
|
|
39
|
+
status?: string;
|
|
40
|
+
executionStatus?: NodeExecutionStatus;
|
|
41
|
+
executionOutput?: unknown;
|
|
42
|
+
executionError?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type FBNodeProps<T> = NodeProps<Node<T & BaseNodeData & Record<string, unknown>>>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { UniversalNode } from './UniversalNode';
|
|
2
|
+
import { AgentNode } from './AgentNode';
|
|
3
|
+
import { GraphNodeType } from '@invect/core/types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Default component for known AGENT node type.
|
|
7
|
+
* All other nodes (including dynamic action-based nodes) use UniversalNode.
|
|
8
|
+
*/
|
|
9
|
+
const AGENT_TYPE = GraphNodeType.AGENT;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base node component mapping for all known GraphNodeType values.
|
|
13
|
+
* Provider-action nodes (e.g. "gmail.list_messages") are resolved
|
|
14
|
+
* dynamically at runtime — see `getNodeComponent()`.
|
|
15
|
+
*/
|
|
16
|
+
// eslint-disable-next-line typescript/no-explicit-any -- React node components require generic any props
|
|
17
|
+
const BASE_COMPONENTS: Record<string, React.ComponentType<any>> = {
|
|
18
|
+
[GraphNodeType.TEMPLATE_STRING]: UniversalNode,
|
|
19
|
+
[GraphNodeType.MODEL]: UniversalNode,
|
|
20
|
+
[GraphNodeType.SQL_QUERY]: UniversalNode,
|
|
21
|
+
[GraphNodeType.IF_ELSE]: UniversalNode,
|
|
22
|
+
[GraphNodeType.INPUT]: UniversalNode,
|
|
23
|
+
[GraphNodeType.OUTPUT]: UniversalNode,
|
|
24
|
+
[GraphNodeType.JQ]: UniversalNode,
|
|
25
|
+
[GraphNodeType.HTTP_REQUEST]: UniversalNode,
|
|
26
|
+
[GraphNodeType.AGENT]: AgentNode,
|
|
27
|
+
[GraphNodeType.GMAIL]: UniversalNode,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Legacy export — static mapping of known enum node types.
|
|
32
|
+
* For dynamic node type resolution (including action-based types),
|
|
33
|
+
* use `getNodeComponent()` instead.
|
|
34
|
+
*/
|
|
35
|
+
export const NODE_COMPONENTS = BASE_COMPONENTS;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the React component for a given node type string.
|
|
39
|
+
* Returns the custom component for known special types (e.g. AGENT),
|
|
40
|
+
* or UniversalNode as the default for everything else.
|
|
41
|
+
*/
|
|
42
|
+
// eslint-disable-next-line typescript/no-explicit-any -- React node components require generic any props
|
|
43
|
+
export function getNodeComponent(nodeType: string): React.ComponentType<any> {
|
|
44
|
+
if (nodeType === AGENT_TYPE) {
|
|
45
|
+
return AgentNode;
|
|
46
|
+
}
|
|
47
|
+
return BASE_COMPONENTS[nodeType] ?? UniversalNode;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type NodeComponentType = string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { NodeToolbar, Position } from '@xyflow/react';
|
|
3
|
+
import { Pencil } from 'lucide-react';
|
|
4
|
+
import { useNodeViewContext } from './NodeViewContext';
|
|
5
|
+
|
|
6
|
+
export function withNodeContext<
|
|
7
|
+
P extends {
|
|
8
|
+
data?: Record<string, unknown>;
|
|
9
|
+
onEdit?: (...args: unknown[]) => void;
|
|
10
|
+
isStatusView?: boolean;
|
|
11
|
+
id: string;
|
|
12
|
+
},
|
|
13
|
+
>(Component: React.ComponentType<P>) {
|
|
14
|
+
const Wrapped = React.forwardRef<HTMLDivElement, P>((props, _ref) => {
|
|
15
|
+
const { mode, onEdit, onEditNode, stripExecutionData } = useNodeViewContext();
|
|
16
|
+
|
|
17
|
+
// Process data based on context
|
|
18
|
+
let processedData = props.data;
|
|
19
|
+
if (stripExecutionData && props.data) {
|
|
20
|
+
const { executionStatus: _, executionOutput, executionError, ...cleanData } = props.data;
|
|
21
|
+
processedData = cleanData;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Determine props based on context
|
|
25
|
+
const contextProps = {
|
|
26
|
+
...props,
|
|
27
|
+
data: processedData,
|
|
28
|
+
onEdit: mode === 'edit' ? onEdit : undefined,
|
|
29
|
+
isStatusView: mode === 'view' || mode === 'readonly',
|
|
30
|
+
} as P;
|
|
31
|
+
|
|
32
|
+
// In view mode with onEditNode, render a NodeToolbar with an Edit button
|
|
33
|
+
if ((mode === 'view' || mode === 'readonly') && onEditNode) {
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<Component {...contextProps} />
|
|
37
|
+
<NodeToolbar position={Position.Bottom} align="center" offset={8}>
|
|
38
|
+
<button
|
|
39
|
+
onClick={() => onEditNode(props.id)}
|
|
40
|
+
className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md border border-border bg-card text-card-foreground shadow-sm hover:bg-accent hover:text-accent-foreground transition-colors"
|
|
41
|
+
>
|
|
42
|
+
<Pencil className="w-3.5 h-3.5" />
|
|
43
|
+
Edit
|
|
44
|
+
</button>
|
|
45
|
+
</NodeToolbar>
|
|
46
|
+
</>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return <Component {...contextProps} />;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
Wrapped.displayName = `WithNodeContext(${Component.displayName || Component.name || 'Component'})`;
|
|
54
|
+
return Wrapped;
|
|
55
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { cn } from '../../lib/utils';
|
|
5
|
+
import { useOptionalTheme } from '../../contexts/ThemeProvider';
|
|
6
|
+
import { INVECT_LOADER_DARK_SVG, INVECT_LOADER_LIGHT_SVG } from '../../assets/invect-branding';
|
|
7
|
+
|
|
8
|
+
export interface InvectLoaderProps {
|
|
9
|
+
className?: string;
|
|
10
|
+
iconClassName?: string;
|
|
11
|
+
label?: string;
|
|
12
|
+
labelClassName?: string;
|
|
13
|
+
variant?: 'theme' | 'dark' | 'light';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function resolveLoaderMarkup(variant: 'theme' | 'dark' | 'light', resolvedTheme: 'dark' | 'light') {
|
|
17
|
+
if (variant === 'dark') {
|
|
18
|
+
return INVECT_LOADER_DARK_SVG;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (variant === 'light') {
|
|
22
|
+
return INVECT_LOADER_LIGHT_SVG;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return resolvedTheme === 'dark' ? INVECT_LOADER_DARK_SVG : INVECT_LOADER_LIGHT_SVG;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const InvectLoader = memo(function InvectLoader({
|
|
29
|
+
className,
|
|
30
|
+
iconClassName,
|
|
31
|
+
label = 'Loading...',
|
|
32
|
+
labelClassName,
|
|
33
|
+
variant = 'theme',
|
|
34
|
+
}: InvectLoaderProps) {
|
|
35
|
+
const theme = useOptionalTheme();
|
|
36
|
+
const resolvedTheme = theme?.resolvedTheme ?? 'light';
|
|
37
|
+
const svgMarkup = resolveLoaderMarkup(variant, resolvedTheme);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<div className={cn('flex flex-col items-center justify-center gap-3', className)} role="status">
|
|
41
|
+
<span
|
|
42
|
+
aria-hidden="true"
|
|
43
|
+
className={cn(
|
|
44
|
+
'inline-flex shrink-0 items-center justify-center h-12 [&>svg]:h-full [&>svg]:w-full',
|
|
45
|
+
iconClassName,
|
|
46
|
+
)}
|
|
47
|
+
style={{ aspectRatio: '109 / 209' }}
|
|
48
|
+
dangerouslySetInnerHTML={{ __html: svgMarkup }}
|
|
49
|
+
/>
|
|
50
|
+
{label ? (
|
|
51
|
+
<span className={cn('text-sm text-muted-foreground', labelClassName)}>{label}</span>
|
|
52
|
+
) : (
|
|
53
|
+
<span className="sr-only">Loading</span>
|
|
54
|
+
)}
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
InvectLoader.displayName = 'InvectLoader';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { cn } from '../../lib/utils';
|
|
5
|
+
import { useOptionalTheme } from '../../contexts/ThemeProvider';
|
|
6
|
+
import { INVECT_ICON_DARK_SVG, INVECT_ICON_LIGHT_SVG } from '../../assets/invect-branding';
|
|
7
|
+
|
|
8
|
+
export interface InvectLogoProps {
|
|
9
|
+
className?: string;
|
|
10
|
+
iconClassName?: string;
|
|
11
|
+
labelClassName?: string;
|
|
12
|
+
showLabel?: boolean;
|
|
13
|
+
label?: string;
|
|
14
|
+
variant?: 'theme' | 'dark' | 'light';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function resolveLogoMarkup(variant: 'theme' | 'dark' | 'light', resolvedTheme: 'dark' | 'light') {
|
|
18
|
+
if (variant === 'dark') {
|
|
19
|
+
return INVECT_ICON_DARK_SVG;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (variant === 'light') {
|
|
23
|
+
return INVECT_ICON_LIGHT_SVG;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return resolvedTheme === 'dark' ? INVECT_ICON_DARK_SVG : INVECT_ICON_LIGHT_SVG;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const InvectLogo = memo(function InvectLogo({
|
|
30
|
+
className,
|
|
31
|
+
iconClassName,
|
|
32
|
+
labelClassName,
|
|
33
|
+
showLabel = false,
|
|
34
|
+
label = 'Invect',
|
|
35
|
+
variant = 'theme',
|
|
36
|
+
}: InvectLogoProps) {
|
|
37
|
+
const theme = useOptionalTheme();
|
|
38
|
+
const resolvedTheme = theme?.resolvedTheme ?? 'light';
|
|
39
|
+
const svgMarkup = resolveLogoMarkup(variant, resolvedTheme);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div className={cn('flex items-center gap-3', className)}>
|
|
43
|
+
<span
|
|
44
|
+
aria-hidden="true"
|
|
45
|
+
className={cn(
|
|
46
|
+
'flex shrink-0 items-center justify-center h-6 [&>svg]:h-full [&>svg]:w-full',
|
|
47
|
+
iconClassName,
|
|
48
|
+
)}
|
|
49
|
+
style={{ aspectRatio: '109 / 209' }}
|
|
50
|
+
dangerouslySetInnerHTML={{ __html: svgMarkup }}
|
|
51
|
+
/>
|
|
52
|
+
{showLabel ? (
|
|
53
|
+
<span className={cn('text-lg font-semibold tracking-tight', labelClassName)}>{label}</span>
|
|
54
|
+
) : null}
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
InvectLogo.displayName = 'InvectLogo';
|