@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,1033 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { memo, useState, useMemo, useCallback, useEffect } from 'react';
|
|
4
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
5
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog';
|
|
6
|
+
import { Button } from '../ui/button';
|
|
7
|
+
import { Input } from '../ui/input';
|
|
8
|
+
import { Textarea } from '../ui/textarea';
|
|
9
|
+
import { Label } from '../ui/label';
|
|
10
|
+
import { ScrollArea } from '../ui/scroll-area';
|
|
11
|
+
import { Slider } from '../ui/slider';
|
|
12
|
+
import { Switch } from '../ui/switch';
|
|
13
|
+
import { Badge } from '../ui/badge';
|
|
14
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select';
|
|
15
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../ui/collapsible';
|
|
16
|
+
import { Separator } from '../ui/separator';
|
|
17
|
+
import { cn } from '../../lib/utils';
|
|
18
|
+
import {
|
|
19
|
+
Settings,
|
|
20
|
+
Wrench,
|
|
21
|
+
Plus,
|
|
22
|
+
Search,
|
|
23
|
+
ChevronDown,
|
|
24
|
+
ChevronRight,
|
|
25
|
+
X,
|
|
26
|
+
Trash2,
|
|
27
|
+
Bot,
|
|
28
|
+
} from 'lucide-react';
|
|
29
|
+
import { ProviderIcon } from '../shared/ProviderIcon';
|
|
30
|
+
import { ToolParamField, type AddCredentialRequest } from './ToolParamField';
|
|
31
|
+
import { CreateCredentialModal } from '../credentials/CreateCredentialModal';
|
|
32
|
+
import { OAuth2ProviderSelector } from '../credentials/OAuth2ProviderSelector';
|
|
33
|
+
import { useCredentials, useCreateCredential } from '../../api/credentials.api';
|
|
34
|
+
import { useNodeRegistry } from '../../contexts/NodeRegistryContext';
|
|
35
|
+
import type { ToolDefinition, AddedToolInstance } from './ToolSelectorModal';
|
|
36
|
+
import type { NodeParamField } from '../../types/node-definition.types';
|
|
37
|
+
import type { CreateCredentialInput, Credential } from '../../api/types';
|
|
38
|
+
|
|
39
|
+
// ─── Types ─────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
interface AgentSettings {
|
|
42
|
+
credentialId: string;
|
|
43
|
+
model: string;
|
|
44
|
+
taskPrompt: string;
|
|
45
|
+
systemPrompt: string;
|
|
46
|
+
maxIterations: number;
|
|
47
|
+
stopCondition: 'explicit_stop' | 'tool_result' | 'max_iterations';
|
|
48
|
+
temperature: number;
|
|
49
|
+
maxTokens: number | undefined;
|
|
50
|
+
enableParallelTools: boolean;
|
|
51
|
+
toolTimeoutMs: number;
|
|
52
|
+
maxConversationTokens: number;
|
|
53
|
+
useBatchProcessing: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
type SidebarView = 'settings' | 'add-tool' | `tool-${string}`;
|
|
57
|
+
|
|
58
|
+
export interface AgentConfigDialogProps {
|
|
59
|
+
open: boolean;
|
|
60
|
+
onOpenChange: (open: boolean) => void;
|
|
61
|
+
/** Display name of the agent node */
|
|
62
|
+
agentName: string;
|
|
63
|
+
/** Available tools fetched from the API */
|
|
64
|
+
availableTools: ToolDefinition[];
|
|
65
|
+
/** Currently added tool instances on this agent */
|
|
66
|
+
addedTools: AddedToolInstance[];
|
|
67
|
+
/** Current agent node params */
|
|
68
|
+
agentParams: Record<string, unknown>;
|
|
69
|
+
/** Called to add a tool instance, returns the new instanceId */
|
|
70
|
+
onAddTool: (toolId: string) => string;
|
|
71
|
+
/** Called to remove a tool instance */
|
|
72
|
+
onRemoveTool: (instanceId: string) => void;
|
|
73
|
+
/** Called to update a tool instance */
|
|
74
|
+
onUpdateTool: (
|
|
75
|
+
instanceId: string,
|
|
76
|
+
updates: Partial<Omit<AddedToolInstance, 'instanceId' | 'toolId'>>,
|
|
77
|
+
) => void;
|
|
78
|
+
/** Called to update agent-level params */
|
|
79
|
+
onUpdateParams: (params: Record<string, unknown>) => void;
|
|
80
|
+
/** Portal container for sub-modals */
|
|
81
|
+
portalContainer?: HTMLElement | null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ─── Main Dialog ───────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
export const AgentConfigDialog = memo(function AgentConfigDialog({
|
|
87
|
+
open,
|
|
88
|
+
onOpenChange,
|
|
89
|
+
agentName,
|
|
90
|
+
availableTools,
|
|
91
|
+
addedTools,
|
|
92
|
+
agentParams,
|
|
93
|
+
onAddTool,
|
|
94
|
+
onRemoveTool,
|
|
95
|
+
onUpdateTool,
|
|
96
|
+
onUpdateParams,
|
|
97
|
+
portalContainer,
|
|
98
|
+
}: AgentConfigDialogProps) {
|
|
99
|
+
const [activeView, setActiveView] = useState<SidebarView>('settings');
|
|
100
|
+
const [toolsExpanded, setToolsExpanded] = useState(true);
|
|
101
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
102
|
+
const [categoryFilter, setCategoryFilter] = useState<string>('all');
|
|
103
|
+
|
|
104
|
+
// Credential modal state
|
|
105
|
+
const queryClient = useQueryClient();
|
|
106
|
+
const [isCreateCredentialOpen, setIsCreateCredentialOpen] = useState(false);
|
|
107
|
+
const [isOAuth2SelectorOpen, setIsOAuth2SelectorOpen] = useState(false);
|
|
108
|
+
const [activeCredentialField, setActiveCredentialField] = useState<string | null>(null);
|
|
109
|
+
const [activeOAuth2Providers, setActiveOAuth2Providers] = useState<string[] | null>(null);
|
|
110
|
+
const createCredentialMutation = useCreateCredential();
|
|
111
|
+
const { data: credentialsData } = useCredentials();
|
|
112
|
+
const credentials = credentialsData ?? [];
|
|
113
|
+
|
|
114
|
+
// Build settings from agentParams
|
|
115
|
+
const settings: AgentSettings = useMemo(
|
|
116
|
+
() => ({
|
|
117
|
+
credentialId: (agentParams.credentialId as string) ?? '',
|
|
118
|
+
model: (agentParams.model as string) ?? '',
|
|
119
|
+
taskPrompt: (agentParams.taskPrompt as string) ?? '',
|
|
120
|
+
systemPrompt: (agentParams.systemPrompt as string) ?? '',
|
|
121
|
+
maxIterations: (agentParams.maxIterations as number) ?? 10,
|
|
122
|
+
stopCondition:
|
|
123
|
+
(agentParams.stopCondition as AgentSettings['stopCondition']) ?? 'explicit_stop',
|
|
124
|
+
temperature: (agentParams.temperature as number) ?? 0.7,
|
|
125
|
+
maxTokens: agentParams.maxTokens as number | undefined,
|
|
126
|
+
enableParallelTools: (agentParams.enableParallelTools as boolean) ?? true,
|
|
127
|
+
toolTimeoutMs: (agentParams.toolTimeoutMs as number) ?? 30000,
|
|
128
|
+
maxConversationTokens: (agentParams.maxConversationTokens as number) ?? 100000,
|
|
129
|
+
useBatchProcessing: (agentParams.useBatchProcessing as boolean) ?? false,
|
|
130
|
+
}),
|
|
131
|
+
[agentParams],
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const updateSettings = useCallback(
|
|
135
|
+
(partial: Partial<AgentSettings>) => {
|
|
136
|
+
onUpdateParams({ ...agentParams, ...partial });
|
|
137
|
+
},
|
|
138
|
+
[agentParams, onUpdateParams],
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// Filter tools for discovery
|
|
142
|
+
const filteredTools = useMemo(() => {
|
|
143
|
+
return availableTools.filter((tool) => {
|
|
144
|
+
const q = searchQuery.toLowerCase();
|
|
145
|
+
const matchesSearch =
|
|
146
|
+
!q ||
|
|
147
|
+
tool.name.toLowerCase().includes(q) ||
|
|
148
|
+
tool.description.toLowerCase().includes(q) ||
|
|
149
|
+
tool.id.toLowerCase().includes(q) ||
|
|
150
|
+
(tool.provider?.name ?? '').toLowerCase().includes(q);
|
|
151
|
+
const matchesCategory = categoryFilter === 'all' || tool.category === categoryFilter;
|
|
152
|
+
return matchesSearch && matchesCategory;
|
|
153
|
+
});
|
|
154
|
+
}, [availableTools, searchQuery, categoryFilter]);
|
|
155
|
+
|
|
156
|
+
// Group by provider
|
|
157
|
+
const toolsByProvider = useMemo(() => {
|
|
158
|
+
const grouped: Record<string, ToolDefinition[]> = {};
|
|
159
|
+
for (const tool of filteredTools) {
|
|
160
|
+
const providerName = tool.provider?.name ?? 'Other';
|
|
161
|
+
if (!grouped[providerName]) {
|
|
162
|
+
grouped[providerName] = [];
|
|
163
|
+
}
|
|
164
|
+
grouped[providerName].push(tool);
|
|
165
|
+
}
|
|
166
|
+
return grouped;
|
|
167
|
+
}, [filteredTools]);
|
|
168
|
+
|
|
169
|
+
const handleAddTool = useCallback(
|
|
170
|
+
(tool: ToolDefinition) => {
|
|
171
|
+
const instanceId = onAddTool(tool.id);
|
|
172
|
+
if (instanceId) {
|
|
173
|
+
setActiveView(`tool-${instanceId}`);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
[onAddTool],
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const handleRemoveTool = useCallback(
|
|
180
|
+
(instanceId: string) => {
|
|
181
|
+
onRemoveTool(instanceId);
|
|
182
|
+
setActiveView('settings');
|
|
183
|
+
},
|
|
184
|
+
[onRemoveTool],
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const getToolForInstance = useCallback(
|
|
188
|
+
(instance: AddedToolInstance) => {
|
|
189
|
+
return availableTools.find((t) => t.id === instance.toolId);
|
|
190
|
+
},
|
|
191
|
+
[availableTools],
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const selectedInstance = useMemo(() => {
|
|
195
|
+
if (!activeView.startsWith('tool-')) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
const instanceId = activeView.replace('tool-', '');
|
|
199
|
+
return addedTools.find((t) => t.instanceId === instanceId) ?? null;
|
|
200
|
+
}, [activeView, addedTools]);
|
|
201
|
+
|
|
202
|
+
// Reset view if selected instance was removed
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
if (activeView.startsWith('tool-') && !selectedInstance) {
|
|
205
|
+
setActiveView('settings');
|
|
206
|
+
}
|
|
207
|
+
}, [activeView, selectedInstance]);
|
|
208
|
+
|
|
209
|
+
// Credential handlers
|
|
210
|
+
const handleAddCredential = useCallback((request: AddCredentialRequest) => {
|
|
211
|
+
setActiveCredentialField(request.fieldName);
|
|
212
|
+
if (request.oauth2Providers && request.oauth2Providers.length > 0) {
|
|
213
|
+
setActiveOAuth2Providers(request.oauth2Providers);
|
|
214
|
+
setIsOAuth2SelectorOpen(true);
|
|
215
|
+
} else {
|
|
216
|
+
setIsCreateCredentialOpen(true);
|
|
217
|
+
}
|
|
218
|
+
}, []);
|
|
219
|
+
|
|
220
|
+
const handleCredentialCreated = useCallback(
|
|
221
|
+
async (createdCredential: Credential) => {
|
|
222
|
+
await queryClient.refetchQueries({ queryKey: ['credentials'] });
|
|
223
|
+
|
|
224
|
+
// If this credential was created for the agent-level credential field
|
|
225
|
+
if (activeCredentialField === '__agent_credential__') {
|
|
226
|
+
updateSettings({ credentialId: createdCredential.id });
|
|
227
|
+
} else if (activeCredentialField && selectedInstance) {
|
|
228
|
+
// For tool instance credential fields
|
|
229
|
+
onUpdateTool(selectedInstance.instanceId, {
|
|
230
|
+
params: { ...selectedInstance.params, [activeCredentialField]: createdCredential.id },
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
setIsCreateCredentialOpen(false);
|
|
235
|
+
setIsOAuth2SelectorOpen(false);
|
|
236
|
+
setActiveCredentialField(null);
|
|
237
|
+
setActiveOAuth2Providers(null);
|
|
238
|
+
},
|
|
239
|
+
[queryClient, activeCredentialField, selectedInstance, onUpdateTool, updateSettings],
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const handleCreateCredential = useCallback(
|
|
243
|
+
(input: CreateCredentialInput) => {
|
|
244
|
+
createCredentialMutation.mutate(input, {
|
|
245
|
+
onSuccess: (created) => handleCredentialCreated(created),
|
|
246
|
+
});
|
|
247
|
+
},
|
|
248
|
+
[createCredentialMutation, handleCredentialCreated],
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
return (
|
|
252
|
+
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
253
|
+
<DialogContent
|
|
254
|
+
className="w-[90vw] max-w-none sm:max-w-none h-[85vh] p-0 gap-0 overflow-hidden"
|
|
255
|
+
showCloseButton={false}
|
|
256
|
+
aria-describedby={undefined}
|
|
257
|
+
>
|
|
258
|
+
<div className="flex h-full">
|
|
259
|
+
{/* ── Sidebar ─────────────────────────────────────────── */}
|
|
260
|
+
<div className="flex flex-col w-64 border-r border-border bg-muted/30">
|
|
261
|
+
<div className="p-4 border-b border-border">
|
|
262
|
+
<div className="flex items-center gap-2">
|
|
263
|
+
<Bot className="size-5 text-primary" />
|
|
264
|
+
<span className="text-sm font-semibold truncate">{agentName}</span>
|
|
265
|
+
</div>
|
|
266
|
+
</div>
|
|
267
|
+
|
|
268
|
+
<ScrollArea className="flex-1">
|
|
269
|
+
<div className="p-2">
|
|
270
|
+
{/* Agent Settings */}
|
|
271
|
+
<button
|
|
272
|
+
onClick={() => setActiveView('settings')}
|
|
273
|
+
className={cn(
|
|
274
|
+
'w-full flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-colors',
|
|
275
|
+
activeView === 'settings'
|
|
276
|
+
? 'bg-accent text-accent-foreground'
|
|
277
|
+
: 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
|
|
278
|
+
)}
|
|
279
|
+
>
|
|
280
|
+
<Settings className="size-4" />
|
|
281
|
+
Agent Settings
|
|
282
|
+
</button>
|
|
283
|
+
|
|
284
|
+
{/* Tools Section */}
|
|
285
|
+
<Collapsible open={toolsExpanded} onOpenChange={setToolsExpanded} className="mt-2">
|
|
286
|
+
<CollapsibleTrigger className="flex items-center justify-between w-full px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground">
|
|
287
|
+
<div className="flex items-center gap-3">
|
|
288
|
+
<Wrench className="size-4" />
|
|
289
|
+
<span>Tools</span>
|
|
290
|
+
</div>
|
|
291
|
+
<div className="flex items-center gap-2">
|
|
292
|
+
<Badge variant="secondary" className="h-5 px-1.5 text-xs">
|
|
293
|
+
{addedTools.length}
|
|
294
|
+
</Badge>
|
|
295
|
+
{toolsExpanded ? (
|
|
296
|
+
<ChevronDown className="size-4" />
|
|
297
|
+
) : (
|
|
298
|
+
<ChevronRight className="size-4" />
|
|
299
|
+
)}
|
|
300
|
+
</div>
|
|
301
|
+
</CollapsibleTrigger>
|
|
302
|
+
|
|
303
|
+
<CollapsibleContent className="mt-1 space-y-1">
|
|
304
|
+
{/* Add Tool Button */}
|
|
305
|
+
<button
|
|
306
|
+
onClick={() => setActiveView('add-tool')}
|
|
307
|
+
className={cn(
|
|
308
|
+
'w-full flex items-center gap-3 px-3 py-2 rounded-md text-sm transition-colors ml-2',
|
|
309
|
+
activeView === 'add-tool'
|
|
310
|
+
? 'bg-accent text-accent-foreground font-medium'
|
|
311
|
+
: 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
|
|
312
|
+
)}
|
|
313
|
+
>
|
|
314
|
+
<Plus className="size-4" />
|
|
315
|
+
Add Tool
|
|
316
|
+
</button>
|
|
317
|
+
|
|
318
|
+
{/* Tool Instances */}
|
|
319
|
+
{addedTools.map((instance) => {
|
|
320
|
+
const tool = getToolForInstance(instance);
|
|
321
|
+
return (
|
|
322
|
+
<button
|
|
323
|
+
key={instance.instanceId}
|
|
324
|
+
onClick={() => setActiveView(`tool-${instance.instanceId}`)}
|
|
325
|
+
className={cn(
|
|
326
|
+
'w-full flex items-center gap-3 px-3 py-2 rounded-md text-sm transition-colors ml-2 group',
|
|
327
|
+
activeView === `tool-${instance.instanceId}`
|
|
328
|
+
? 'bg-accent text-accent-foreground font-medium'
|
|
329
|
+
: 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
|
|
330
|
+
)}
|
|
331
|
+
>
|
|
332
|
+
<span className="text-muted-foreground shrink-0">
|
|
333
|
+
{tool?.provider?.id ? (
|
|
334
|
+
<ProviderIcon
|
|
335
|
+
providerId={tool.provider.id}
|
|
336
|
+
svgIcon={tool.provider.svgIcon}
|
|
337
|
+
icon={tool.provider.icon}
|
|
338
|
+
className="size-4"
|
|
339
|
+
/>
|
|
340
|
+
) : (
|
|
341
|
+
<Wrench className="size-4" />
|
|
342
|
+
)}
|
|
343
|
+
</span>
|
|
344
|
+
<span className="flex-1 text-left truncate">{instance.name}</span>
|
|
345
|
+
</button>
|
|
346
|
+
);
|
|
347
|
+
})}
|
|
348
|
+
</CollapsibleContent>
|
|
349
|
+
</Collapsible>
|
|
350
|
+
</div>
|
|
351
|
+
</ScrollArea>
|
|
352
|
+
|
|
353
|
+
{/* Footer */}
|
|
354
|
+
<div className="flex gap-2 p-3 border-t border-border">
|
|
355
|
+
<Button
|
|
356
|
+
variant="outline"
|
|
357
|
+
size="sm"
|
|
358
|
+
className="flex-1"
|
|
359
|
+
onClick={() => onOpenChange(false)}
|
|
360
|
+
>
|
|
361
|
+
Close
|
|
362
|
+
</Button>
|
|
363
|
+
</div>
|
|
364
|
+
</div>
|
|
365
|
+
|
|
366
|
+
{/* ── Main Content ────────────────────────────────────── */}
|
|
367
|
+
<div className="flex flex-col flex-1 min-w-0">
|
|
368
|
+
{/* Header */}
|
|
369
|
+
<div className="flex items-center justify-between px-6 py-4 border-b border-border">
|
|
370
|
+
<DialogHeader className="p-0">
|
|
371
|
+
<DialogTitle className="text-base font-semibold">
|
|
372
|
+
{activeView === 'settings' && 'Agent Settings'}
|
|
373
|
+
{activeView === 'add-tool' && 'Add Tool'}
|
|
374
|
+
{selectedInstance && (
|
|
375
|
+
<div className="flex items-center gap-2">
|
|
376
|
+
{(() => {
|
|
377
|
+
const tool = getToolForInstance(selectedInstance);
|
|
378
|
+
return tool?.provider?.id ? (
|
|
379
|
+
<ProviderIcon
|
|
380
|
+
providerId={tool.provider.id}
|
|
381
|
+
svgIcon={tool.provider.svgIcon}
|
|
382
|
+
icon={tool.provider.icon}
|
|
383
|
+
className="size-4 text-muted-foreground"
|
|
384
|
+
/>
|
|
385
|
+
) : (
|
|
386
|
+
<Wrench className="size-4 text-muted-foreground" />
|
|
387
|
+
);
|
|
388
|
+
})()}
|
|
389
|
+
{selectedInstance.name}
|
|
390
|
+
</div>
|
|
391
|
+
)}
|
|
392
|
+
</DialogTitle>
|
|
393
|
+
</DialogHeader>
|
|
394
|
+
<Button
|
|
395
|
+
variant="ghost"
|
|
396
|
+
size="icon"
|
|
397
|
+
className="size-8"
|
|
398
|
+
onClick={() => onOpenChange(false)}
|
|
399
|
+
>
|
|
400
|
+
<X className="size-4" />
|
|
401
|
+
</Button>
|
|
402
|
+
</div>
|
|
403
|
+
|
|
404
|
+
{/* Content */}
|
|
405
|
+
<ScrollArea className="flex-1">
|
|
406
|
+
<div className="p-6">
|
|
407
|
+
{activeView === 'settings' && (
|
|
408
|
+
<AgentSettingsView
|
|
409
|
+
settings={settings}
|
|
410
|
+
credentials={credentials}
|
|
411
|
+
onSettingsChange={updateSettings}
|
|
412
|
+
onAddCredential={() => {
|
|
413
|
+
setActiveCredentialField('__agent_credential__');
|
|
414
|
+
setIsCreateCredentialOpen(true);
|
|
415
|
+
}}
|
|
416
|
+
/>
|
|
417
|
+
)}
|
|
418
|
+
{activeView === 'add-tool' && (
|
|
419
|
+
<ToolDiscoveryView
|
|
420
|
+
searchQuery={searchQuery}
|
|
421
|
+
onSearchChange={setSearchQuery}
|
|
422
|
+
categoryFilter={categoryFilter}
|
|
423
|
+
onCategoryChange={setCategoryFilter}
|
|
424
|
+
toolsByProvider={toolsByProvider}
|
|
425
|
+
addedTools={addedTools}
|
|
426
|
+
onAddTool={handleAddTool}
|
|
427
|
+
/>
|
|
428
|
+
)}
|
|
429
|
+
{selectedInstance && (
|
|
430
|
+
<ToolInstanceView
|
|
431
|
+
instance={selectedInstance}
|
|
432
|
+
tool={getToolForInstance(selectedInstance) ?? null}
|
|
433
|
+
onUpdate={onUpdateTool}
|
|
434
|
+
onRemove={() => handleRemoveTool(selectedInstance.instanceId)}
|
|
435
|
+
onAddCredential={handleAddCredential}
|
|
436
|
+
/>
|
|
437
|
+
)}
|
|
438
|
+
</div>
|
|
439
|
+
</ScrollArea>
|
|
440
|
+
</div>
|
|
441
|
+
</div>
|
|
442
|
+
</DialogContent>
|
|
443
|
+
|
|
444
|
+
{/* Credential modals */}
|
|
445
|
+
<CreateCredentialModal
|
|
446
|
+
open={isCreateCredentialOpen}
|
|
447
|
+
onClose={() => {
|
|
448
|
+
setIsCreateCredentialOpen(false);
|
|
449
|
+
setActiveCredentialField(null);
|
|
450
|
+
}}
|
|
451
|
+
onSubmit={handleCreateCredential}
|
|
452
|
+
isLoading={createCredentialMutation.isPending}
|
|
453
|
+
portalContainer={portalContainer}
|
|
454
|
+
/>
|
|
455
|
+
|
|
456
|
+
<OAuth2ProviderSelector
|
|
457
|
+
open={isOAuth2SelectorOpen}
|
|
458
|
+
onOpenChange={(o) => {
|
|
459
|
+
if (!o) {
|
|
460
|
+
setIsOAuth2SelectorOpen(false);
|
|
461
|
+
setActiveCredentialField(null);
|
|
462
|
+
setActiveOAuth2Providers(null);
|
|
463
|
+
}
|
|
464
|
+
}}
|
|
465
|
+
onCredentialCreated={handleCredentialCreated}
|
|
466
|
+
portalContainer={portalContainer}
|
|
467
|
+
filterProviders={activeOAuth2Providers ?? undefined}
|
|
468
|
+
/>
|
|
469
|
+
</Dialog>
|
|
470
|
+
);
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
AgentConfigDialog.displayName = 'AgentConfigDialog';
|
|
474
|
+
|
|
475
|
+
// ─── Agent Settings View ───────────────────────────────────────────
|
|
476
|
+
|
|
477
|
+
function AgentSettingsView({
|
|
478
|
+
settings,
|
|
479
|
+
credentials,
|
|
480
|
+
onSettingsChange,
|
|
481
|
+
onAddCredential,
|
|
482
|
+
}: {
|
|
483
|
+
settings: AgentSettings;
|
|
484
|
+
credentials: Array<{ id: string; name: string; type?: string }>;
|
|
485
|
+
onSettingsChange: (partial: Partial<AgentSettings>) => void;
|
|
486
|
+
onAddCredential: () => void;
|
|
487
|
+
}) {
|
|
488
|
+
const [advancedOpen, setAdvancedOpen] = useState(false);
|
|
489
|
+
|
|
490
|
+
return (
|
|
491
|
+
<div className="max-w-2xl space-y-6">
|
|
492
|
+
{/* Credentials & Model */}
|
|
493
|
+
<section className="space-y-4">
|
|
494
|
+
<h3 className="text-sm font-semibold text-foreground">Credentials & Model</h3>
|
|
495
|
+
|
|
496
|
+
<div className="grid gap-4">
|
|
497
|
+
<div className="space-y-2">
|
|
498
|
+
<Label htmlFor="credential">Credential</Label>
|
|
499
|
+
<div className="flex gap-2">
|
|
500
|
+
<Select
|
|
501
|
+
value={settings.credentialId}
|
|
502
|
+
onValueChange={(v) => onSettingsChange({ credentialId: v })}
|
|
503
|
+
>
|
|
504
|
+
<SelectTrigger className="flex-1">
|
|
505
|
+
<SelectValue placeholder="Select credential" />
|
|
506
|
+
</SelectTrigger>
|
|
507
|
+
<SelectContent>
|
|
508
|
+
{credentials.map((cred) => (
|
|
509
|
+
<SelectItem key={cred.id} value={cred.id}>
|
|
510
|
+
{cred.name}
|
|
511
|
+
</SelectItem>
|
|
512
|
+
))}
|
|
513
|
+
</SelectContent>
|
|
514
|
+
</Select>
|
|
515
|
+
<Button variant="outline" size="icon" onClick={onAddCredential}>
|
|
516
|
+
<Plus className="size-4" />
|
|
517
|
+
</Button>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
|
|
521
|
+
<div className="space-y-2">
|
|
522
|
+
<Label htmlFor="model">Model</Label>
|
|
523
|
+
<Input
|
|
524
|
+
id="model"
|
|
525
|
+
value={settings.model}
|
|
526
|
+
onChange={(e) => onSettingsChange({ model: e.target.value })}
|
|
527
|
+
placeholder="e.g. gpt-4o, claude-sonnet-4-20250514"
|
|
528
|
+
/>
|
|
529
|
+
<p className="text-xs text-muted-foreground">
|
|
530
|
+
Model identifier matching your credential provider.
|
|
531
|
+
</p>
|
|
532
|
+
</div>
|
|
533
|
+
</div>
|
|
534
|
+
</section>
|
|
535
|
+
|
|
536
|
+
<Separator />
|
|
537
|
+
|
|
538
|
+
{/* Prompts */}
|
|
539
|
+
<section className="space-y-4">
|
|
540
|
+
<h3 className="text-sm font-semibold text-foreground">Prompts</h3>
|
|
541
|
+
|
|
542
|
+
<div className="space-y-4">
|
|
543
|
+
<div className="space-y-2">
|
|
544
|
+
<Label htmlFor="task-prompt">Task Prompt</Label>
|
|
545
|
+
<Textarea
|
|
546
|
+
id="task-prompt"
|
|
547
|
+
placeholder="Enter the main instruction for the agent. Supports {{ upstream_node.field }} template syntax..."
|
|
548
|
+
className="font-mono text-sm min-h-32"
|
|
549
|
+
value={settings.taskPrompt}
|
|
550
|
+
onChange={(e) => onSettingsChange({ taskPrompt: e.target.value })}
|
|
551
|
+
/>
|
|
552
|
+
<p className="text-xs text-muted-foreground">
|
|
553
|
+
The primary instruction telling the agent what to do.
|
|
554
|
+
</p>
|
|
555
|
+
</div>
|
|
556
|
+
|
|
557
|
+
<div className="space-y-2">
|
|
558
|
+
<Label htmlFor="system-prompt">System Prompt (Optional)</Label>
|
|
559
|
+
<Textarea
|
|
560
|
+
id="system-prompt"
|
|
561
|
+
placeholder="Enter system-level instructions..."
|
|
562
|
+
className="font-mono text-sm min-h-24"
|
|
563
|
+
value={settings.systemPrompt}
|
|
564
|
+
onChange={(e) => onSettingsChange({ systemPrompt: e.target.value })}
|
|
565
|
+
/>
|
|
566
|
+
</div>
|
|
567
|
+
</div>
|
|
568
|
+
</section>
|
|
569
|
+
|
|
570
|
+
<Separator />
|
|
571
|
+
|
|
572
|
+
{/* Advanced Settings */}
|
|
573
|
+
<Collapsible open={advancedOpen} onOpenChange={setAdvancedOpen}>
|
|
574
|
+
<CollapsibleTrigger className="flex items-center gap-2 text-sm font-semibold text-foreground hover:text-foreground/80">
|
|
575
|
+
{advancedOpen ? <ChevronDown className="size-4" /> : <ChevronRight className="size-4" />}
|
|
576
|
+
Advanced Settings
|
|
577
|
+
</CollapsibleTrigger>
|
|
578
|
+
|
|
579
|
+
<CollapsibleContent className="pt-4 space-y-4">
|
|
580
|
+
<div className="grid grid-cols-2 gap-4">
|
|
581
|
+
<div className="space-y-2">
|
|
582
|
+
<Label>Max Iterations</Label>
|
|
583
|
+
<div className="flex items-center gap-4">
|
|
584
|
+
<Slider
|
|
585
|
+
value={[settings.maxIterations]}
|
|
586
|
+
onValueChange={([v]) => onSettingsChange({ maxIterations: v })}
|
|
587
|
+
max={50}
|
|
588
|
+
min={1}
|
|
589
|
+
step={1}
|
|
590
|
+
className="flex-1"
|
|
591
|
+
/>
|
|
592
|
+
<span className="w-8 text-sm text-right text-muted-foreground">
|
|
593
|
+
{settings.maxIterations}
|
|
594
|
+
</span>
|
|
595
|
+
</div>
|
|
596
|
+
</div>
|
|
597
|
+
|
|
598
|
+
<div className="space-y-2">
|
|
599
|
+
<Label>Temperature</Label>
|
|
600
|
+
<div className="flex items-center gap-4">
|
|
601
|
+
<Slider
|
|
602
|
+
value={[settings.temperature]}
|
|
603
|
+
onValueChange={([v]) => onSettingsChange({ temperature: v })}
|
|
604
|
+
max={2}
|
|
605
|
+
min={0}
|
|
606
|
+
step={0.1}
|
|
607
|
+
className="flex-1"
|
|
608
|
+
/>
|
|
609
|
+
<span className="w-8 text-sm text-right text-muted-foreground">
|
|
610
|
+
{settings.temperature.toFixed(1)}
|
|
611
|
+
</span>
|
|
612
|
+
</div>
|
|
613
|
+
</div>
|
|
614
|
+
</div>
|
|
615
|
+
|
|
616
|
+
<div className="space-y-2">
|
|
617
|
+
<Label>Stop Condition</Label>
|
|
618
|
+
<Select
|
|
619
|
+
value={settings.stopCondition}
|
|
620
|
+
onValueChange={(v: AgentSettings['stopCondition']) =>
|
|
621
|
+
onSettingsChange({ stopCondition: v })
|
|
622
|
+
}
|
|
623
|
+
>
|
|
624
|
+
<SelectTrigger>
|
|
625
|
+
<SelectValue />
|
|
626
|
+
</SelectTrigger>
|
|
627
|
+
<SelectContent>
|
|
628
|
+
<SelectItem value="explicit_stop">Explicit Stop</SelectItem>
|
|
629
|
+
<SelectItem value="tool_result">First Tool Result</SelectItem>
|
|
630
|
+
<SelectItem value="max_iterations">Max Iterations</SelectItem>
|
|
631
|
+
</SelectContent>
|
|
632
|
+
</Select>
|
|
633
|
+
</div>
|
|
634
|
+
|
|
635
|
+
<div className="grid grid-cols-2 gap-4">
|
|
636
|
+
<div className="space-y-2">
|
|
637
|
+
<Label>Max Tokens</Label>
|
|
638
|
+
<Input
|
|
639
|
+
type="number"
|
|
640
|
+
value={settings.maxTokens ?? ''}
|
|
641
|
+
onChange={(e) =>
|
|
642
|
+
onSettingsChange({
|
|
643
|
+
maxTokens: e.target.value ? parseInt(e.target.value) : undefined,
|
|
644
|
+
})
|
|
645
|
+
}
|
|
646
|
+
placeholder="Default"
|
|
647
|
+
/>
|
|
648
|
+
</div>
|
|
649
|
+
|
|
650
|
+
<div className="space-y-2">
|
|
651
|
+
<Label>Tool Timeout (ms)</Label>
|
|
652
|
+
<Input
|
|
653
|
+
type="number"
|
|
654
|
+
value={settings.toolTimeoutMs}
|
|
655
|
+
onChange={(e) =>
|
|
656
|
+
onSettingsChange({ toolTimeoutMs: parseInt(e.target.value) || 30000 })
|
|
657
|
+
}
|
|
658
|
+
/>
|
|
659
|
+
</div>
|
|
660
|
+
</div>
|
|
661
|
+
|
|
662
|
+
<div className="grid grid-cols-2 gap-4">
|
|
663
|
+
<div className="space-y-2">
|
|
664
|
+
<Label>Max Conversation Tokens</Label>
|
|
665
|
+
<Input
|
|
666
|
+
type="number"
|
|
667
|
+
value={settings.maxConversationTokens}
|
|
668
|
+
onChange={(e) =>
|
|
669
|
+
onSettingsChange({
|
|
670
|
+
maxConversationTokens: parseInt(e.target.value) || 100000,
|
|
671
|
+
})
|
|
672
|
+
}
|
|
673
|
+
/>
|
|
674
|
+
</div>
|
|
675
|
+
</div>
|
|
676
|
+
|
|
677
|
+
<div className="space-y-3">
|
|
678
|
+
<div className="flex items-center justify-between">
|
|
679
|
+
<div>
|
|
680
|
+
<Label>Enable Parallel Tools</Label>
|
|
681
|
+
<p className="text-xs text-muted-foreground">
|
|
682
|
+
Allow multiple tools to run simultaneously
|
|
683
|
+
</p>
|
|
684
|
+
</div>
|
|
685
|
+
<Switch
|
|
686
|
+
checked={settings.enableParallelTools}
|
|
687
|
+
onChange={(e) => onSettingsChange({ enableParallelTools: e.target.checked })}
|
|
688
|
+
/>
|
|
689
|
+
</div>
|
|
690
|
+
|
|
691
|
+
<div className="flex items-center justify-between">
|
|
692
|
+
<div>
|
|
693
|
+
<Label>Use Batch Processing</Label>
|
|
694
|
+
<p className="text-xs text-muted-foreground">
|
|
695
|
+
Process requests in batches for efficiency
|
|
696
|
+
</p>
|
|
697
|
+
</div>
|
|
698
|
+
<Switch
|
|
699
|
+
checked={settings.useBatchProcessing}
|
|
700
|
+
onChange={(e) => onSettingsChange({ useBatchProcessing: e.target.checked })}
|
|
701
|
+
/>
|
|
702
|
+
</div>
|
|
703
|
+
</div>
|
|
704
|
+
</CollapsibleContent>
|
|
705
|
+
</Collapsible>
|
|
706
|
+
</div>
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// ─── Tool Discovery View ───────────────────────────────────────────
|
|
711
|
+
|
|
712
|
+
function ToolDiscoveryView({
|
|
713
|
+
searchQuery,
|
|
714
|
+
onSearchChange,
|
|
715
|
+
categoryFilter,
|
|
716
|
+
onCategoryChange,
|
|
717
|
+
toolsByProvider,
|
|
718
|
+
addedTools,
|
|
719
|
+
onAddTool,
|
|
720
|
+
}: {
|
|
721
|
+
searchQuery: string;
|
|
722
|
+
onSearchChange: (query: string) => void;
|
|
723
|
+
categoryFilter: string;
|
|
724
|
+
onCategoryChange: (category: string) => void;
|
|
725
|
+
toolsByProvider: Record<string, ToolDefinition[]>;
|
|
726
|
+
addedTools: AddedToolInstance[];
|
|
727
|
+
onAddTool: (tool: ToolDefinition) => void;
|
|
728
|
+
}) {
|
|
729
|
+
const categories = [
|
|
730
|
+
{ id: 'all', label: 'All' },
|
|
731
|
+
{ id: 'data', label: 'Data' },
|
|
732
|
+
{ id: 'web', label: 'Web' },
|
|
733
|
+
{ id: 'code', label: 'Code' },
|
|
734
|
+
{ id: 'utility', label: 'Utility' },
|
|
735
|
+
{ id: 'custom', label: 'Custom' },
|
|
736
|
+
];
|
|
737
|
+
|
|
738
|
+
const getInstanceCount = (toolId: string) => {
|
|
739
|
+
return addedTools.filter((t) => t.toolId === toolId).length;
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
return (
|
|
743
|
+
<div className="space-y-4">
|
|
744
|
+
{/* Search */}
|
|
745
|
+
<div className="relative">
|
|
746
|
+
<Search className="absolute -translate-y-1/2 left-3 top-1/2 size-4 text-muted-foreground" />
|
|
747
|
+
<Input
|
|
748
|
+
placeholder="Search tools..."
|
|
749
|
+
value={searchQuery}
|
|
750
|
+
onChange={(e) => onSearchChange(e.target.value)}
|
|
751
|
+
className="pl-10"
|
|
752
|
+
/>
|
|
753
|
+
</div>
|
|
754
|
+
|
|
755
|
+
{/* Categories */}
|
|
756
|
+
<div className="flex flex-wrap gap-2">
|
|
757
|
+
{categories.map((cat) => (
|
|
758
|
+
<Button
|
|
759
|
+
key={cat.id}
|
|
760
|
+
variant={categoryFilter === cat.id ? 'default' : 'outline'}
|
|
761
|
+
size="sm"
|
|
762
|
+
onClick={() => onCategoryChange(cat.id)}
|
|
763
|
+
>
|
|
764
|
+
{cat.label}
|
|
765
|
+
</Button>
|
|
766
|
+
))}
|
|
767
|
+
</div>
|
|
768
|
+
|
|
769
|
+
{/* Tool Grid by Provider */}
|
|
770
|
+
<div className="space-y-6">
|
|
771
|
+
{Object.entries(toolsByProvider).map(([provider, tools]) => (
|
|
772
|
+
<div key={provider}>
|
|
773
|
+
<h4 className="flex items-center gap-2 mb-3 text-sm font-semibold text-muted-foreground">
|
|
774
|
+
{tools[0]?.provider?.id && (
|
|
775
|
+
<ProviderIcon
|
|
776
|
+
providerId={tools[0].provider.id}
|
|
777
|
+
svgIcon={tools[0].provider.svgIcon}
|
|
778
|
+
icon={tools[0].provider.icon}
|
|
779
|
+
className="size-4"
|
|
780
|
+
/>
|
|
781
|
+
)}
|
|
782
|
+
{provider}
|
|
783
|
+
</h4>
|
|
784
|
+
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
|
785
|
+
{tools.map((tool) => {
|
|
786
|
+
const count = getInstanceCount(tool.id);
|
|
787
|
+
return (
|
|
788
|
+
<div
|
|
789
|
+
key={tool.id}
|
|
790
|
+
className="relative p-4 transition-colors border rounded-lg group border-border hover:border-primary/50 hover:bg-accent/50"
|
|
791
|
+
>
|
|
792
|
+
{count > 0 && (
|
|
793
|
+
<Badge
|
|
794
|
+
variant="secondary"
|
|
795
|
+
className="absolute top-2 right-2 h-5 px-1.5 text-xs"
|
|
796
|
+
>
|
|
797
|
+
×{count}
|
|
798
|
+
</Badge>
|
|
799
|
+
)}
|
|
800
|
+
<div className="flex items-start gap-3">
|
|
801
|
+
<span className="text-muted-foreground mt-0.5">
|
|
802
|
+
{tool.provider?.id ? (
|
|
803
|
+
<ProviderIcon
|
|
804
|
+
providerId={tool.provider.id}
|
|
805
|
+
svgIcon={tool.provider.svgIcon}
|
|
806
|
+
icon={tool.provider.icon}
|
|
807
|
+
className="size-4"
|
|
808
|
+
/>
|
|
809
|
+
) : (
|
|
810
|
+
<Wrench className="size-4" />
|
|
811
|
+
)}
|
|
812
|
+
</span>
|
|
813
|
+
<div className="flex-1 min-w-0">
|
|
814
|
+
<h5 className="text-sm font-medium">{tool.name}</h5>
|
|
815
|
+
<p className="mt-1 text-xs text-muted-foreground line-clamp-2">
|
|
816
|
+
{tool.description}
|
|
817
|
+
</p>
|
|
818
|
+
</div>
|
|
819
|
+
</div>
|
|
820
|
+
<Button
|
|
821
|
+
size="sm"
|
|
822
|
+
variant="ghost"
|
|
823
|
+
className="absolute transition-opacity opacity-0 bottom-2 right-2 group-hover:opacity-100"
|
|
824
|
+
onClick={() => onAddTool(tool)}
|
|
825
|
+
>
|
|
826
|
+
<Plus className="mr-1 size-4" />
|
|
827
|
+
Add
|
|
828
|
+
</Button>
|
|
829
|
+
</div>
|
|
830
|
+
);
|
|
831
|
+
})}
|
|
832
|
+
</div>
|
|
833
|
+
</div>
|
|
834
|
+
))}
|
|
835
|
+
|
|
836
|
+
{Object.keys(toolsByProvider).length === 0 && (
|
|
837
|
+
<div className="py-8 text-center text-muted-foreground">
|
|
838
|
+
<p className="text-sm">No tools match your search.</p>
|
|
839
|
+
</div>
|
|
840
|
+
)}
|
|
841
|
+
</div>
|
|
842
|
+
</div>
|
|
843
|
+
);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// ─── Tool Instance View ────────────────────────────────────────────
|
|
847
|
+
|
|
848
|
+
function ToolInstanceView({
|
|
849
|
+
instance,
|
|
850
|
+
tool,
|
|
851
|
+
onUpdate,
|
|
852
|
+
onRemove,
|
|
853
|
+
onAddCredential,
|
|
854
|
+
}: {
|
|
855
|
+
instance: AddedToolInstance;
|
|
856
|
+
tool: ToolDefinition | null;
|
|
857
|
+
onUpdate: (
|
|
858
|
+
instanceId: string,
|
|
859
|
+
updates: Partial<Omit<AddedToolInstance, 'instanceId' | 'toolId'>>,
|
|
860
|
+
) => void;
|
|
861
|
+
onRemove: () => void;
|
|
862
|
+
onAddCredential: (request: AddCredentialRequest) => void;
|
|
863
|
+
}) {
|
|
864
|
+
const [showSchema, setShowSchema] = useState(false);
|
|
865
|
+
const { getNodeDefinition } = useNodeRegistry();
|
|
866
|
+
|
|
867
|
+
// Get param fields from the underlying node definition
|
|
868
|
+
const nodeDefinition = tool?.nodeType ? getNodeDefinition(tool.nodeType) : undefined;
|
|
869
|
+
const paramFields = useMemo(() => {
|
|
870
|
+
const allFields = nodeDefinition?.paramFields ?? [];
|
|
871
|
+
const visibleFields = allFields.filter((field: NodeParamField) => !field.hidden);
|
|
872
|
+
return visibleFields.sort((a: NodeParamField, b: NodeParamField) => {
|
|
873
|
+
if (a.type === 'credential' && b.type !== 'credential') {
|
|
874
|
+
return -1;
|
|
875
|
+
}
|
|
876
|
+
if (a.type !== 'credential' && b.type === 'credential') {
|
|
877
|
+
return 1;
|
|
878
|
+
}
|
|
879
|
+
return 0;
|
|
880
|
+
});
|
|
881
|
+
}, [nodeDefinition]);
|
|
882
|
+
|
|
883
|
+
// Compute effective input schema
|
|
884
|
+
const effectiveInputSchema = useMemo(() => {
|
|
885
|
+
if (!tool?.inputSchema || !instance) {
|
|
886
|
+
return tool?.inputSchema;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
const aiChosenModes = (instance.params._aiChosenModes as Record<string, boolean>) ?? {};
|
|
890
|
+
const schema = tool.inputSchema as {
|
|
891
|
+
properties?: Record<string, unknown>;
|
|
892
|
+
required?: string[];
|
|
893
|
+
};
|
|
894
|
+
if (!schema.properties) {
|
|
895
|
+
return schema;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
const filteredProperties: Record<string, unknown> = {};
|
|
899
|
+
const staticParams: string[] = [];
|
|
900
|
+
|
|
901
|
+
for (const [key, value] of Object.entries(schema.properties)) {
|
|
902
|
+
if (aiChosenModes[key] ?? true) {
|
|
903
|
+
filteredProperties[key] = value;
|
|
904
|
+
} else {
|
|
905
|
+
staticParams.push(key);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
return {
|
|
910
|
+
...schema,
|
|
911
|
+
properties: filteredProperties,
|
|
912
|
+
required: schema.required?.filter((key) => aiChosenModes[key] ?? true),
|
|
913
|
+
_staticParams: staticParams.length > 0 ? staticParams : undefined,
|
|
914
|
+
};
|
|
915
|
+
}, [tool?.inputSchema, instance]);
|
|
916
|
+
|
|
917
|
+
return (
|
|
918
|
+
<div className="max-w-2xl space-y-6">
|
|
919
|
+
{/* Header Info */}
|
|
920
|
+
<div className="flex items-start justify-between">
|
|
921
|
+
<div className="space-y-1">
|
|
922
|
+
<p className="text-xs text-muted-foreground">
|
|
923
|
+
Tool: <code className="bg-muted px-1 py-0.5 rounded">{instance.toolId}</code>
|
|
924
|
+
</p>
|
|
925
|
+
</div>
|
|
926
|
+
<Button
|
|
927
|
+
variant="ghost"
|
|
928
|
+
size="sm"
|
|
929
|
+
className="text-destructive hover:text-destructive hover:bg-destructive/10"
|
|
930
|
+
onClick={onRemove}
|
|
931
|
+
>
|
|
932
|
+
<Trash2 className="mr-2 size-4" />
|
|
933
|
+
Remove Tool
|
|
934
|
+
</Button>
|
|
935
|
+
</div>
|
|
936
|
+
|
|
937
|
+
{/* Instance Identity */}
|
|
938
|
+
<section className="space-y-4">
|
|
939
|
+
<div className="space-y-2">
|
|
940
|
+
<Label htmlFor="instance-name">Instance Name</Label>
|
|
941
|
+
<Input
|
|
942
|
+
id="instance-name"
|
|
943
|
+
value={instance.name}
|
|
944
|
+
onChange={(e) => onUpdate(instance.instanceId, { name: e.target.value })}
|
|
945
|
+
placeholder="Give this tool instance a name..."
|
|
946
|
+
/>
|
|
947
|
+
</div>
|
|
948
|
+
|
|
949
|
+
<div className="space-y-2">
|
|
950
|
+
<Label htmlFor="instance-desc">Instance Description</Label>
|
|
951
|
+
<Textarea
|
|
952
|
+
id="instance-desc"
|
|
953
|
+
value={instance.description}
|
|
954
|
+
onChange={(e) => onUpdate(instance.instanceId, { description: e.target.value })}
|
|
955
|
+
placeholder="Describe when/how this tool should be used..."
|
|
956
|
+
className="min-h-20"
|
|
957
|
+
/>
|
|
958
|
+
</div>
|
|
959
|
+
</section>
|
|
960
|
+
|
|
961
|
+
<Separator />
|
|
962
|
+
|
|
963
|
+
{/* Parameters via real ToolParamField */}
|
|
964
|
+
<section className="space-y-4">
|
|
965
|
+
<h3 className="text-sm font-semibold text-foreground">Parameters</h3>
|
|
966
|
+
|
|
967
|
+
{paramFields.length > 0 ? (
|
|
968
|
+
<div className="space-y-3">
|
|
969
|
+
{paramFields.map((field: NodeParamField) => {
|
|
970
|
+
const aiChosenModes =
|
|
971
|
+
(instance.params._aiChosenModes as Record<string, boolean>) ?? {};
|
|
972
|
+
const isAiChosen = aiChosenModes[field.name] ?? true;
|
|
973
|
+
return (
|
|
974
|
+
<ToolParamField
|
|
975
|
+
key={field.name}
|
|
976
|
+
field={field}
|
|
977
|
+
value={instance.params[field.name]}
|
|
978
|
+
onChange={(value) => {
|
|
979
|
+
onUpdate(instance.instanceId, {
|
|
980
|
+
params: { ...instance.params, [field.name]: value },
|
|
981
|
+
});
|
|
982
|
+
}}
|
|
983
|
+
aiChosen={isAiChosen}
|
|
984
|
+
onAiChosenChange={(enabled) => {
|
|
985
|
+
const updatedModes = { ...aiChosenModes, [field.name]: enabled };
|
|
986
|
+
onUpdate(instance.instanceId, {
|
|
987
|
+
params: { ...instance.params, _aiChosenModes: updatedModes },
|
|
988
|
+
});
|
|
989
|
+
}}
|
|
990
|
+
onAddCredential={onAddCredential}
|
|
991
|
+
/>
|
|
992
|
+
);
|
|
993
|
+
})}
|
|
994
|
+
</div>
|
|
995
|
+
) : (
|
|
996
|
+
<p className="text-sm italic text-muted-foreground">
|
|
997
|
+
This tool has no configurable parameters.
|
|
998
|
+
</p>
|
|
999
|
+
)}
|
|
1000
|
+
</section>
|
|
1001
|
+
|
|
1002
|
+
<Separator />
|
|
1003
|
+
|
|
1004
|
+
{/* Effective Schema */}
|
|
1005
|
+
<Collapsible open={showSchema} onOpenChange={setShowSchema}>
|
|
1006
|
+
<CollapsibleTrigger className="flex items-center gap-2 text-sm font-semibold text-foreground hover:text-foreground/80">
|
|
1007
|
+
{showSchema ? <ChevronDown className="size-4" /> : <ChevronRight className="size-4" />}
|
|
1008
|
+
Effective Schema
|
|
1009
|
+
</CollapsibleTrigger>
|
|
1010
|
+
<CollapsibleContent className="pt-3">
|
|
1011
|
+
<div className="p-4 overflow-auto rounded-lg bg-muted/50">
|
|
1012
|
+
{effectiveInputSchema &&
|
|
1013
|
+
'_staticParams' in effectiveInputSchema &&
|
|
1014
|
+
(effectiveInputSchema as { _staticParams?: string[] })._staticParams && (
|
|
1015
|
+
<div className="pb-2 mb-2 text-[10px] border-b text-muted-foreground">
|
|
1016
|
+
<span className="font-medium">Static params (not sent to AI): </span>
|
|
1017
|
+
{(
|
|
1018
|
+
(effectiveInputSchema as { _staticParams?: string[] })._staticParams ?? []
|
|
1019
|
+
).join(', ')}
|
|
1020
|
+
</div>
|
|
1021
|
+
)}
|
|
1022
|
+
<pre className="text-[10px] whitespace-pre-wrap font-mono text-muted-foreground">
|
|
1023
|
+
{JSON.stringify(effectiveInputSchema, null, 2)}
|
|
1024
|
+
</pre>
|
|
1025
|
+
</div>
|
|
1026
|
+
<p className="mt-2 text-xs text-muted-foreground">
|
|
1027
|
+
This is the schema the agent will see. Parameters with AI-chosen: OFF are hidden.
|
|
1028
|
+
</p>
|
|
1029
|
+
</CollapsibleContent>
|
|
1030
|
+
</Collapsible>
|
|
1031
|
+
</div>
|
|
1032
|
+
);
|
|
1033
|
+
}
|